示例#1
0
void DynamicBody::CalcExternalForce()
{
	// gravity
	if (!GetFrame()) return;			// no external force if not in a frame
	Body *body = GetFrame()->GetBody();
	if (body && !body->IsType(Object::SPACESTATION)) {	// they ought to have mass though...
		vector3d b1b2 = GetPosition();
		double m1m2 = GetMass() * body->GetMass();
		double invrsqr = 1.0 / b1b2.LengthSqr();
		double force = G*m1m2 * invrsqr;
		m_externalForce = -b1b2 * sqrt(invrsqr) * force;
	}
	else m_externalForce = vector3d(0.0);
	m_gravityForce = m_externalForce;

	// atmospheric drag
	if (body && GetFrame()->IsRotFrame() && body->IsType(Object::PLANET))
	{
		Planet *planet = static_cast<Planet*>(body);
		double dist = GetPosition().Length();
		double speed = m_vel.Length();
		double pressure, density;
		planet->GetAtmosphericState(dist, &pressure, &density);
		const double radius = GetClipRadius();		// bogus, preserving behaviour
		const double AREA = radius;
		// ^^^ yes that is as stupid as it looks
		const double DRAG_COEFF = 0.1; // 'smooth sphere'
		vector3d dragDir = -m_vel.NormalizedSafe();
		vector3d fDrag = 0.5*density*speed*speed*AREA*DRAG_COEFF*dragDir;

		// make this a bit less daft at high time accel
		// only allow atmosForce to increase by .1g per frame
		vector3d f1g = m_atmosForce + dragDir * GetMass();
		if (fDrag.LengthSqr() > f1g.LengthSqr()) m_atmosForce = f1g;
		else m_atmosForce = fDrag;

		m_externalForce += m_atmosForce;
	}
	else m_atmosForce = vector3d(0.0);

	// centrifugal and coriolis forces for rotating frames
	if (GetFrame()->IsRotFrame()) {
		vector3d angRot(0, GetFrame()->GetAngSpeed(), 0);
		m_externalForce -= m_mass * angRot.Cross(angRot.Cross(GetPosition()));	// centrifugal
		m_externalForce -= 2 * m_mass * angRot.Cross(GetVelocity());			// coriolis
	}
}
示例#2
0
void DynamicsSystem::update(ent_ptr<EntityManager> em, ent_ptr<EventManager> events, double dt)
{
	for (auto entity : em->entities_with_components<DynamicsComponent>()) {
        ent_ptr<DynamicsComponent> dc = entity.component<DynamicsComponent>();
        ent_ptr<PosOrientComponent> poc = entity.component<PosOrientComponent>();
        ent_ptr<MassComponent> mc = entity.component<MassComponent>();
        SDL_assert(poc);
        SDL_assert(mc);

        //save previous
        //poc->oldPos = poc->pos;
        //poc->oldAngDisplacement = dc->angVel * dt;

        dc->force += dc->externalForce;

		dc->vel += dt * dc->force * (1.0 / mc->mass);
		dc->angVel += dt * dc->torque * (1.0 / dc->angInertia);

		//update pos
		poc->pos += dc->vel * dt;
		//update orient
		double len = dc->angVel.Length();
		if (len > 1e-16) {
			vector3d axis = dc->angVel * (1.0 / len);
			matrix3x3d r = matrix3x3d::Rotate(len * dt, axis);
			poc->orient = r * poc->orient;
		}

		dc->force = vector3d(0.0);
		dc->torque = vector3d(0.0);

		//calculate external forces
		//- gravity
		//- atmospheric drag
		//- centrifugal/coriolis force
        auto fc = entity.component<FrameComponent>();
        if (fc) {
			if (fc->frame->IsRotFrame()) {
				vector3d angRot(0, fc->frame->GetAngSpeed(), 0);
				dc->externalForce -= mc->mass * angRot.Cross(angRot.Cross(poc->pos));	// centrifugal
				dc->externalForce -= 2 * mc->mass * angRot.Cross(dc->vel);			// coriolis
			}
        }
	}
}
示例#3
0
void DynamicBody::CalcExternalForce()
{
    // gravity
    if (!GetFrame()) return;			// no external force if not in a frame
    Body *body = GetFrame()->GetBody();
    if (body && !body->IsType(Object::SPACESTATION)) {	// they ought to have mass though...
        vector3d b1b2 = GetPosition();
        double m1m2 = GetMass() * body->GetMass();
        double invrsqr = 1.0 / b1b2.LengthSqr();
        double force = G*m1m2 * invrsqr;
        m_externalForce = -b1b2 * sqrt(invrsqr) * force;
    }
    else m_externalForce = vector3d(0.0);
    m_gravityForce = m_externalForce;

    // atmospheric drag
    if (body && GetFrame()->IsRotFrame() && body->IsType(Object::PLANET))
    {
        vector3d dragDir = -m_vel.NormalizedSafe();
        vector3d fDrag = CalcAtmosphericForce(m_dragCoeff)*dragDir;

        // make this a bit less daft at high time accel
        // only allow atmosForce to increase by .1g per frame
        vector3d f1g = m_atmosForce + dragDir * GetMass();
        if (fDrag.LengthSqr() > f1g.LengthSqr()) m_atmosForce = f1g;
        else m_atmosForce = fDrag;

        m_externalForce += m_atmosForce;
    }
    else m_atmosForce = vector3d(0.0);

    // centrifugal and coriolis forces for rotating frames
    if (GetFrame()->IsRotFrame()) {
        vector3d angRot(0, GetFrame()->GetAngSpeed(), 0);
        m_externalForce -= m_mass * angRot.Cross(angRot.Cross(GetPosition()));	// centrifugal
        m_externalForce -= 2 * m_mass * angRot.Cross(GetVelocity());			// coriolis
    }
}