예제 #1
0
파일: Space.cpp 프로젝트: adammead/pioneer
static Frame *MakeFrameFor(SystemBody *sbody, Body *b, Frame *f)
{
    if (!sbody->parent) {
        if (b) b->SetFrame(f);
        f->SetBodies(sbody, b);
        return f;
    }

    if (sbody->type == SystemBody::TYPE_GRAVPOINT) {
        Frame *orbFrame = new Frame(f, sbody->name.c_str());
        orbFrame->SetBodies(sbody, b);
        orbFrame->SetRadius(sbody->GetMaxChildOrbitalDistance()*1.1);
        return orbFrame;
    }

    SystemBody::BodySuperType supertype = sbody->GetSuperType();

    if ((supertype == SystemBody::SUPERTYPE_GAS_GIANT) ||
            (supertype == SystemBody::SUPERTYPE_ROCKY_PLANET)) {
        // for planets we want an non-rotating frame for a few radii
        // and a rotating frame with no radius to contain attached objects
        double frameRadius = std::max(4.0*sbody->GetRadius(), sbody->GetMaxChildOrbitalDistance()*1.05);
        Frame *orbFrame = new Frame(f, sbody->name.c_str(), Frame::FLAG_HAS_ROT);
        orbFrame->SetBodies(sbody, b);
        orbFrame->SetRadius(frameRadius);
        //printf("\t\t\t%s has frame size %.0fkm, body radius %.0fkm\n", sbody->name.c_str(),
        //	(frameRadius ? frameRadius : 10*sbody->GetRadius())*0.001f,
        //	sbody->GetRadius()*0.001f);

        assert(sbody->rotationPeriod != 0);
        Frame *rotFrame = new Frame(orbFrame, sbody->name.c_str(), Frame::FLAG_ROTATING);
        rotFrame->SetBodies(sbody, b);

        // rotating frame has atmosphere radius or feature height, whichever is larger
        rotFrame->SetRadius(b->GetPhysRadius());

        matrix3x3d rotMatrix = matrix3x3d::RotateX(sbody->axialTilt.ToDouble());
        double angSpeed = 2.0*M_PI/sbody->GetRotationPeriod();
        rotFrame->SetAngSpeed(angSpeed);

        if (sbody->rotationalPhaseAtStart != fixed(0))
            rotMatrix = rotMatrix * matrix3x3d::RotateY(sbody->rotationalPhaseAtStart.ToDouble());
        rotFrame->SetOrient(rotMatrix);

        b->SetFrame(rotFrame);
        return orbFrame;
    }
    else if (supertype == SystemBody::SUPERTYPE_STAR) {
        // stars want a single small non-rotating frame
        // bigger than it's furtherest orbiting body.
        // if there are no orbiting bodies use a frame of several radii.
        Frame *orbFrame = new Frame(f, sbody->name.c_str());
        orbFrame->SetBodies(sbody, b);
        orbFrame->SetRadius(std::max(10.0*sbody->GetRadius(), sbody->GetMaxChildOrbitalDistance()*1.1));
        b->SetFrame(orbFrame);
        return orbFrame;
    }
    else if (sbody->type == SystemBody::TYPE_STARPORT_ORBITAL) {
        // space stations want non-rotating frame to some distance
        // and a zero-size rotating frame
        Frame *orbFrame = new Frame(f, sbody->name.c_str(), Frame::FLAG_HAS_ROT);
        orbFrame->SetBodies(sbody, b);
//		orbFrame->SetRadius(10*sbody->GetRadius());
        orbFrame->SetRadius(20000.0);				// 4x standard parking radius
        b->SetFrame(orbFrame);
        return orbFrame;

//		assert(sbody->rotationPeriod != 0);
//		rotFrame = new Frame(orbFrame, sbody->name.c_str(), Frame::FLAG_ROTATING);
//		rotFrame->SetBodies(sbody, b);
//		rotFrame->SetRadius(0.0);
//		rotFrame->SetAngVelocity(vector3d(0.0,double(static_cast<SpaceStation*>(b)->GetDesiredAngVel()),0.0));
//		b->SetFrame(rotFrame);

    } else if (sbody->type == SystemBody::TYPE_STARPORT_SURFACE) {
        // just put body into rotating frame of planet, not in its own frame
        // (because collisions only happen between objects in same frame,
        // and we want collisions on starport and on planet itself)
        Frame *rotFrame = f->GetRotFrame();
        b->SetFrame(rotFrame);
        assert(rotFrame->IsRotFrame());
        assert(rotFrame->GetBody()->IsType(Object::PLANET));
        matrix3x3d rot;
        vector3d pos;
        Planet *planet = static_cast<Planet*>(rotFrame->GetBody());
        RelocateStarportIfUnderwaterOrBuried(sbody, rotFrame, planet, pos, rot);
        sbody->orbit.rotMatrix = rot;
        b->SetPosition(pos * planet->GetTerrainHeight(pos));
        b->SetOrient(rot);
        return rotFrame;
    } else {
        assert(0);
    }
    return NULL;
}
예제 #2
0
static Frame *MakeFrameFor(double at_time, SystemBody *sbody, Body *b, Frame *f)
{
	if (!sbody->GetParent()) {
		if (b) b->SetFrame(f);
		f->SetBodies(sbody, b);
		return f;
	}

	if (sbody->GetType() == SystemBody::TYPE_GRAVPOINT) {
		Frame *orbFrame = new Frame(f, sbody->GetName().c_str());
		orbFrame->SetBodies(sbody, b);
		orbFrame->SetRadius(sbody->GetMaxChildOrbitalDistance()*1.1);
		return orbFrame;
	}

	SystemBody::BodySuperType supertype = sbody->GetSuperType();

	if ((supertype == SystemBody::SUPERTYPE_GAS_GIANT) ||
	    (supertype == SystemBody::SUPERTYPE_ROCKY_PLANET)) {
		// for planets we want an non-rotating frame for a few radii
		// and a rotating frame with no radius to contain attached objects
		double frameRadius = std::max(4.0*sbody->GetRadius(), sbody->GetMaxChildOrbitalDistance()*1.05);
		Frame *orbFrame = new Frame(f, sbody->GetName().c_str(), Frame::FLAG_HAS_ROT);
		orbFrame->SetBodies(sbody, b);
		orbFrame->SetRadius(frameRadius);
		//Output("\t\t\t%s has frame size %.0fkm, body radius %.0fkm\n", sbody->name.c_str(),
		//	(frameRadius ? frameRadius : 10*sbody->GetRadius())*0.001f,
		//	sbody->GetRadius()*0.001f);

		assert(sbody->IsRotating() != 0);
		Frame *rotFrame = new Frame(orbFrame, sbody->GetName().c_str(), Frame::FLAG_ROTATING);
		rotFrame->SetBodies(sbody, b);

		// rotating frame has atmosphere radius or feature height, whichever is larger
		rotFrame->SetRadius(b->GetPhysRadius());

		matrix3x3d rotMatrix = matrix3x3d::RotateX(sbody->GetAxialTilt());
		double angSpeed = 2.0*M_PI/sbody->GetRotationPeriod();
		rotFrame->SetAngSpeed(angSpeed);

		if (sbody->HasRotationPhase())
			rotMatrix = rotMatrix * matrix3x3d::RotateY(sbody->GetRotationPhaseAtStart());
		rotFrame->SetInitialOrient(rotMatrix, at_time);

		b->SetFrame(rotFrame);
		return orbFrame;
	}
	else if (supertype == SystemBody::SUPERTYPE_STAR) {
		// stars want a single small non-rotating frame
		// bigger than it's furtherest orbiting body.
		// if there are no orbiting bodies use a frame of several radii.
		Frame *orbFrame = new Frame(f, sbody->GetName().c_str());
		orbFrame->SetBodies(sbody, b);
		double frameRadius = std::max(10.0*sbody->GetRadius(), sbody->GetMaxChildOrbitalDistance()*1.1);
		// Respect the frame of other stars in the multi-star system. We still make sure that the frame ends outside
		// the body. For a minimum separation of 1.236 radii, nothing will overlap (see StarSystem::StarSystem()).
		if (sbody->GetParent() && frameRadius > AU * 0.11 * sbody->GetOrbMin())
			frameRadius = std::max(1.1*sbody->GetRadius(), AU * 0.11 * sbody->GetOrbMin());
		orbFrame->SetRadius(frameRadius);
		b->SetFrame(orbFrame);
		return orbFrame;
	}
	else if (sbody->GetType() == SystemBody::TYPE_STARPORT_ORBITAL) {
		// space stations want non-rotating frame to some distance
		Frame *orbFrame = new Frame(f, sbody->GetName().c_str());
		orbFrame->SetBodies(sbody, b);
//		orbFrame->SetRadius(10*sbody->GetRadius());
		orbFrame->SetRadius(20000.0);				// 4x standard parking radius
		b->SetFrame(orbFrame);
		return orbFrame;

	} else if (sbody->GetType() == SystemBody::TYPE_STARPORT_SURFACE) {
		// just put body into rotating frame of planet, not in its own frame
		// (because collisions only happen between objects in same frame,
		// and we want collisions on starport and on planet itself)
		Frame *rotFrame = f->GetRotFrame();
		b->SetFrame(rotFrame);
		assert(rotFrame->IsRotFrame());
		assert(rotFrame->GetBody()->IsType(Object::PLANET));
		matrix3x3d rot;
		vector3d pos;
		Planet *planet = static_cast<Planet*>(rotFrame->GetBody());
		RelocateStarportIfUnderwaterOrBuried(sbody, rotFrame, planet, pos, rot);
		sbody->SetOrbitPlane(rot);
		b->SetPosition(pos * planet->GetTerrainHeight(pos));
		b->SetOrient(rot);
		return rotFrame;
	} else {
		assert(0);
	}
	return 0;
}
예제 #3
0
static Frame *MakeFrameFor(SystemBody *sbody, Body *b, Frame *f)
{
	Frame *orbFrame, *rotFrame;
	double frameRadius;

	if (!sbody->parent) {
		if (b) b->SetFrame(f);
		f->m_sbody = sbody;
		f->m_astroBody = b;
		return f;
	}

	if (sbody->type == SystemBody::TYPE_GRAVPOINT) {
		orbFrame = new Frame(f, sbody->name.c_str());
		orbFrame->m_sbody = sbody;
		orbFrame->m_astroBody = b;
		orbFrame->SetRadius(sbody->GetMaxChildOrbitalDistance()*1.1);
		return orbFrame;
	}

	SystemBody::BodySuperType supertype = sbody->GetSuperType();

	if ((supertype == SystemBody::SUPERTYPE_GAS_GIANT) ||
	    (supertype == SystemBody::SUPERTYPE_ROCKY_PLANET)) {
		// for planets we want an non-rotating frame for a few radii
		// and a rotating frame in the same position but with maybe 1.05*radius,
		// which actually contains the object.
		frameRadius = std::max(4.0*sbody->GetRadius(), sbody->GetMaxChildOrbitalDistance()*1.05);
		orbFrame = new Frame(f, sbody->name.c_str());
		orbFrame->m_sbody = sbody;
		orbFrame->SetRadius(frameRadius);
		//printf("\t\t\t%s has frame size %.0fkm, body radius %.0fkm\n", sbody->name.c_str(),
		//	(frameRadius ? frameRadius : 10*sbody->GetRadius())*0.001f,
		//	sbody->GetRadius()*0.001f);

		assert(sbody->rotationPeriod != 0);
		rotFrame = new Frame(orbFrame, sbody->name.c_str());
		// rotating frame has size of GeoSphere terrain bounding sphere
		rotFrame->SetRadius(b->GetBoundingRadius());
		matrix4x4d rotMatrix = matrix4x4d::RotateXMatrix(sbody->axialTilt.ToDouble());
		vector3d angVel = vector3d(0.0, 2.0*M_PI/sbody->GetRotationPeriod(), 0.0);
		rotFrame->SetAngVelocity(angVel);

		if (sbody->rotationalPhaseAtStart != fixed(0))
			rotMatrix = rotMatrix * matrix4x4d::RotateYMatrix(sbody->rotationalPhaseAtStart.ToDouble());
		rotFrame->SetRotationOnly(rotMatrix);

		rotFrame->m_astroBody = b;
		b->SetFrame(rotFrame);
		return orbFrame;
	}
	else if (supertype == SystemBody::SUPERTYPE_STAR) {
		// stars want a single small non-rotating frame
		orbFrame = new Frame(f, sbody->name.c_str());
		orbFrame->m_sbody = sbody;
		orbFrame->m_astroBody = b;
		orbFrame->SetRadius(sbody->GetMaxChildOrbitalDistance()*1.1);
		b->SetFrame(orbFrame);
		return orbFrame;
	}
	else if (sbody->type == SystemBody::TYPE_STARPORT_ORBITAL) {
		// space stations want non-rotating frame to some distance
		// and a much closer rotating frame
		frameRadius = 1000000.0; // XXX NFI!
		orbFrame = new Frame(f, sbody->name.c_str());
		orbFrame->m_sbody = sbody;
//		orbFrame->SetRadius(10*sbody->GetRadius());
		orbFrame->SetRadius(frameRadius);

		assert(sbody->rotationPeriod != 0);
		rotFrame = new Frame(orbFrame, sbody->name.c_str());
		rotFrame->SetRadius(1000.0);
//		rotFrame->SetRadius(1.1*sbody->GetRadius());		// enough for collisions?
		rotFrame->SetAngVelocity(vector3d(0.0,double(static_cast<SpaceStation*>(b)->GetDesiredAngVel()),0.0));
		rotFrame->m_astroBody = b;		// hope this doesn't break anything
		b->SetFrame(rotFrame);
		return orbFrame;
	} else if (sbody->type == SystemBody::TYPE_STARPORT_SURFACE) {
		// just put body into rotating frame of planet, not in its own frame
		// (because collisions only happen between objects in same frame,
		// and we want collisions on starport and on planet itself)
		Frame *frame = *f->m_children.begin();
		b->SetFrame(frame);
		assert(frame->m_astroBody->IsType(Object::PLANET));
		matrix4x4d rot;
		vector3d pos;
		Planet *planet = static_cast<Planet*>(frame->m_astroBody);
		RelocateStarportIfUnderwaterOrBuried(sbody, frame, planet, pos, rot);
		sbody->orbit.rotMatrix = rot;
		b->SetPosition(pos * planet->GetTerrainHeight(pos));
		b->SetRotMatrix(rot);
		return frame;
	} else {
		assert(0);
	}
	return NULL;
}
예제 #4
0
파일: Space.cpp 프로젝트: cj31387/pioneer
static Frame *MakeFrameFor(SBody *sbody, Body *b, Frame *f)
{
    Frame *orbFrame, *rotFrame;
    double frameRadius;

    if (!sbody->parent) {
        if (b) b->SetFrame(f);
        f->m_sbody = sbody;
        f->m_astroBody = b;
        return f;
    }

    if (sbody->type == SBody::TYPE_GRAVPOINT) {
        orbFrame = new Frame(f, sbody->name.c_str());
        orbFrame->m_sbody = sbody;
        orbFrame->m_astroBody = b;
        orbFrame->SetRadius(sbody->GetMaxChildOrbitalDistance()*1.1);
        return orbFrame;
    }

    SBody::BodySuperType supertype = sbody->GetSuperType();

    if ((supertype == SBody::SUPERTYPE_GAS_GIANT) ||
            (supertype == SBody::SUPERTYPE_ROCKY_PLANET)) {
        // for planets we want an non-rotating frame for a few radii
        // and a rotating frame in the same position but with maybe 1.05*radius,
        // which actually contains the object.
        frameRadius = std::max(4.0*sbody->GetRadius(), sbody->GetMaxChildOrbitalDistance()*1.05);
        orbFrame = new Frame(f, sbody->name.c_str());
        orbFrame->m_sbody = sbody;
        orbFrame->SetRadius(frameRadius);
        //printf("\t\t\t%s has frame size %.0fkm, body radius %.0fkm\n", sbody->name.c_str(),
        //	(frameRadius ? frameRadius : 10*sbody->GetRadius())*0.001f,
        //	sbody->GetRadius()*0.001f);

        assert(sbody->rotationPeriod != 0);
        rotFrame = new Frame(orbFrame, sbody->name.c_str());
        // rotating frame has size of GeoSphere terrain bounding sphere
        rotFrame->SetRadius(b->GetBoundingRadius());
        rotFrame->SetAngVelocity(vector3d(0,2*M_PI/sbody->GetRotationPeriod(),0));
        rotFrame->m_astroBody = b;
        SetFrameOrientationFromSBodyAxialTilt(rotFrame, sbody);
        b->SetFrame(rotFrame);
        return orbFrame;
    }
    else if (supertype == SBody::SUPERTYPE_STAR) {
        // stars want a single small non-rotating frame
        orbFrame = new Frame(f, sbody->name.c_str());
        orbFrame->m_sbody = sbody;
        orbFrame->m_astroBody = b;
        orbFrame->SetRadius(sbody->GetMaxChildOrbitalDistance()*1.1);
        b->SetFrame(orbFrame);
        return orbFrame;
    }
    else if (sbody->type == SBody::TYPE_STARPORT_ORBITAL) {
        // space stations want non-rotating frame to some distance
        // and a much closer rotating frame
        frameRadius = 1000000.0; // XXX NFI!
        orbFrame = new Frame(f, sbody->name.c_str());
        orbFrame->m_sbody = sbody;
//		orbFrame->SetRadius(10*sbody->GetRadius());
        orbFrame->SetRadius(frameRadius);

        assert(sbody->rotationPeriod != 0);
        rotFrame = new Frame(orbFrame, sbody->name.c_str());
        rotFrame->SetRadius(1000.0);
//		rotFrame->SetRadius(1.1*sbody->GetRadius());		// enough for collisions?
        rotFrame->SetAngVelocity(vector3d(0.0,double(static_cast<SpaceStation*>(b)->GetDesiredAngVel()),0.0));
        rotFrame->m_astroBody = b;		// hope this doesn't break anything
        b->SetFrame(rotFrame);
        return orbFrame;
    } else if (sbody->type == SBody::TYPE_STARPORT_SURFACE) {
        // just put body into rotating frame of planet, not in its own frame
        // (because collisions only happen between objects in same frame,
        // and we want collisions on starport and on planet itself)
        Frame *frame = *f->m_children.begin();
        b->SetFrame(frame);
        assert(frame->m_astroBody->IsType(Object::PLANET));
        Planet *planet = static_cast<Planet*>(frame->m_astroBody);

        /* position on planet surface */
        double height;
        int tries;
        matrix4x4d rot;
        vector3d pos;
        // first try suggested position
        rot = sbody->orbit.rotMatrix;
        pos = rot * vector3d(0,1,0);
        if (planet->GetTerrainHeight(pos) - planet->GetSBody()->GetRadius() <= 0.0) {
            MTRand r(sbody->seed);
            // position is under water. try some random ones
            for (tries=0; tries<100; tries++) {
                // used for orientation on planet surface
                double r2 = r.Double(); 	// function parameter evaluation order is implementation-dependent
                double r1 = r.Double();		// can't put two rands in the same expression
                rot = matrix4x4d::RotateZMatrix(2*M_PI*r1)
                      * matrix4x4d::RotateYMatrix(2*M_PI*r2);
                pos = rot * vector3d(0,1,0);
                height = planet->GetTerrainHeight(pos) - planet->GetSBody()->GetRadius();
                // don't want to be under water
                if (height > 0.0) break;
            }
        }
        b->SetPosition(pos * planet->GetTerrainHeight(pos));
        b->SetRotMatrix(rot);
        return frame;
    } else {
        assert(0);
    }
    return NULL;
}