Exemple #1
0
void cCar::Drive ( void )
{
	// default implementation of driving a car using w, s, a and d keys

	if ( m_bControlSteering ) ControlSteering ( );
	if ( m_bApplyTorque     ) ApplyTorque     ( );

	//ApplyAcceleration ( );
	//return;

	// check to accelerate, slow down, apply handbrake or no input
	if ( dbKeyState ( 17 ) )
	{
		// state of acceleration
		if ( m_bApplyAcceleration )
			ApplyAcceleration ( );
	}
	else if ( dbKeyState ( 31 ) )
	{
		// state of braking
		if ( m_bApplyBrakes )
			ApplyBrakes ( );
	}
	else if ( dbKeyState ( 57 ) )
	{
		// state of handbrake when space key is pressed
		if ( m_bApplyHandBrake )
			ApplyHandBrake ( );
	}
	else
	{
		// state of no input

		// set clutch, motor input and gear to 0
		//dbMeqCarSetClutch	  ( m_iID, 0 );
		dbMeqCarSetMotorInput ( m_iID, 0 );
		//dbMeqCarSetGear		  ( m_iID, 0 );
	}
}
void SkeletizedObj :: Update(float T_time)
{
    Profile("Update skeletized object");

    //RigidObj::Update(T_time);

    //////////////////////////////////////////////////////// Update Verlets

    for (int bi = 0; bi < I_bones; ++bi)
        if (!FL_stationary)
        {
            xFLOAT I_count = 0;

            if (Collisions.size())
            {
                xVector3 NW_dump; NW_dump.zero();

                std::vector<Physics::Colliders::CollisionPoint>::iterator
                            iter_cur, iter_end = Collisions.end();

                for (iter_cur = Collisions.begin(); iter_cur != iter_end; ++iter_cur)
                    ApplyAcceleration(iter_cur->V_reaction, 1.f, *iter_cur);
                for (iter_cur = Collisions.begin(); iter_cur != iter_end; ++iter_cur)
                {
                    bool supports = false;
                    for (int ci = 0; ci < iter_cur->I_Bones && !supports; ++ci)
                        supports = (iter_cur->W_Bones[ci].I_bone == bi);

                    if (supports)
                    {
                        xVector3 N_fix = xVector3::Normalize(iter_cur->NW_fix);
                        xFLOAT W_cos = xVector3::DotProduct(N_fix, NW_VerletVelocity_new[bi]);
                        if (W_cos < 0.f)
                        {
                            NW_dump -= N_fix * W_cos;
                            ++I_count;
                        }
                    }
                }

                if (I_count)
                {
                    NW_VerletVelocity_new[bi] += NW_dump / I_count;
                    verletSystem.FL_attached[bi] = true;
                }
            }
            if (!I_count)
            {
                //if (T_time != 0)
                //{
                //    //drag
                //    xFLOAT V_vel = NW_VerletVelocity[i].length();
                //    xFLOAT W_air_drag = air_drag(S_radius, V_vel*V_vel) * T_time / M_mass;
                //    if (V_vel > W_air_drag)
                //        NW_VerletVelocity_new[i] += NW_VerletVelocity[i] * (1.f - W_air_drag / V_vel);
                //}
                //else
                    NW_VerletVelocity_new[bi] += NW_VerletVelocity[bi];
            }
            NW_VerletVelocity[bi] = NW_VerletVelocity_new[bi];

            if (!NW_VerletVelocity[bi].isZero())
            {
                if (T_time != 0)
                {
                    verletSystem.P_previous[bi] = verletSystem.P_current[bi] + NW_VerletVelocity[bi] * T_time;
                    Modify();
                }
                else
                    verletSystem.P_previous[bi] = verletSystem.P_current[bi];
                NW_VerletVelocity_new[bi].zero();
            }
            else
                verletSystem.P_previous[bi] = verletSystem.P_current[bi];
        }
    verletSystem.SwapPositions();

    xVector3 NW_translation;
    if (Collisions.size())
    {
        NW_translation = MergeCollisions() * 0.9f;
        if (NW_translation.lengthSqr() < 0.0001f)
            NW_translation.zero();
    }
    else
        NW_translation = verletSystem.P_current[0]-verletSystem.P_previous[0];

    // Update Matrices
    MX_LocalToWorld_Set().postTranslateT(NW_translation);
    UpdateMatrices();

    xSkeleton &spine = ModelGr->xModelP->Spine;
    verletSystem.C_constraints = spine.C_constraints;
    verletSystem.I_constraints = spine.I_constraints;
    verletSystem.C_lengthConst = spine.C_boneLength;
    verletSystem.Spine = &spine;
    verletSystem.MX_ModelToWorld   = MX_LocalToWorld_Get();
    verletSystem.MX_WorldToModel_T = MX_WorldToLocal;
    verletSystem.MX_WorldToModel_T.transpose();
    verletSystem.T_step = T_time;

    VerletSolver engine;
    engine.Init(verletSystem);
    engine.I_passes = 5;
    //engine.Verlet();
    engine.SatisfyConstraints();

    if (T_time > EPSILON)
    {
        xFLOAT T_time_Inv = 1.f / T_time;
        for (int i = 0; i < I_bones; ++i)
        {
            xVector3 V_speed = (verletSystem.P_current[i] - verletSystem.P_previous[i]) * T_time_Inv;
            if (V_speed.x > 0.f && NW_VerletVelocity[i].x > 0.f)
                V_speed.x = min (V_speed.x, NW_VerletVelocity[i].x);
            else
            if (V_speed.x < 0.f && NW_VerletVelocity[i].x < 0.f)
                V_speed.x = max (V_speed.x, NW_VerletVelocity[i].x);
            else
                V_speed.x = 0.f;

            if (V_speed.y > 0.f && NW_VerletVelocity[i].y > 0.f)
                V_speed.y = min (V_speed.y, NW_VerletVelocity[i].y);
            else
            if (V_speed.y < 0.f && NW_VerletVelocity[i].y < 0.f)
                V_speed.y = max (V_speed.y, NW_VerletVelocity[i].y);
            else
                V_speed.y = 0.f;

            if (V_speed.z > 0.f && NW_VerletVelocity[i].z > 0.f)
                V_speed.z = min (V_speed.z, NW_VerletVelocity[i].z);
            else
            if (V_speed.z < 0.f && NW_VerletVelocity[i].z < 0.f)
                V_speed.z = max (V_speed.z, NW_VerletVelocity[i].z);
            else
                V_speed.z = 0.f;
            NW_VerletVelocity[i] = V_speed;
        }
    }
    else
        for (int i = 0; i < I_bones; ++i)
            NW_VerletVelocity[i].zero();

    spine.CalcQuats(verletSystem.P_current, verletSystem.QT_boneSkew,
        0, verletSystem.MX_WorldToModel_T);
    spine.QuatsToArray(QT_verlet);

    FL_verlet = false;
    bool FL_locked = false;
    for (int i = 0; i < I_bones; ++i)
        if (verletSystem.FL_attached[i])
        {
            FL_locked = true;
            break;
        }

    xFLOAT T_mod = T_time;
    for (int i = 0; i < I_bones; ++i)
        if (T_Verlet[i] > T_time)
        {
            if (FL_locked) T_Verlet[i] -= T_time;
            verletSystem.W_boneMix[i] = 1.f;
            FL_verlet = true;
        }
        else
        if (T_Verlet[i] > 0.f)
        {
            T_Verlet[i] = 0.f;
            verletSystem.W_boneMix[i] = 1.f;
            FL_verlet = true;
        }
        else
        if (verletSystem.W_boneMix[i] > T_mod)
        {
            if (FL_locked) verletSystem.W_boneMix[i] -= T_mod;
            FL_verlet = true;
        }
        else
            verletSystem.W_boneMix[i] = 0.f;

    if (FL_verlet)
        comBoard.ID_action_cur = comBoard.StopAction.ID_action;


    spine.L_bones->QT_rotation.zeroQ();
    QT_verlet[0].zeroQ();

    //////////////////////////////////////////////////////// Track enemy movement

    if (FL_auto_movement && Tracker.Mode != Math::Tracking::ObjectTracker::TRACK_NOTHING &&
        !FL_verlet && LifeEnergy > 0.f && T_time > 0.f)
    {
        xVector3 NW_aim = MX_LocalToWorld_Get().preTransformV(
                              comBoard.GetActionRotation().preTransformV(
                                  xVector3::Create(0.f, -1.1f, 0.f)));
        NW_aim.z = 0.f;
        Tracker.P_destination = P_center_Trfm + NW_aim;
        Tracker.UpdateDestination();
        xVector3 NW_dst = Tracker.P_destination - P_center_Trfm; NW_dst.z = 0.f;

        comBoard.AutoMovement(NW_aim, NW_dst, T_time);
        MX_LocalToWorld_Set().preMultiply(comBoard.MX_shift);
    }
    bool FL_auto_movement_needed = comBoard.AutoAction != ComBoard::AutoHint::HINT_NONE;

    //////////////////////////////////////////////////////// Update Animation

	xQuaternion *bones = NULL, *bones2 = NULL;

    if (LifeEnergy > 0.f)
    {
        if (actions.L_actions.size())
        {
            xDWORD delta = (xDWORD)(T_time*1000);

            actions.Update(delta);
		    bones = actions.GetTransformations();

            if (actions.T_progress > 10000) actions.T_progress = 0;
        }
        
        if ((ControlType == Control_ComBoardInput || FL_auto_movement_needed) && comBoard.L_actions.size())
        {
            if (!FL_verlet)
            {
                comBoard.Update(T_time * 1000, ControlType == Control_ComBoardInput);
                MX_LocalToWorld_Set().preMultiply(comBoard.MX_shift);
            }
            bones2 = comBoard.GetTransformations();
        }
        else
        if (ControlType == Control_CaptureInput)
            bones2 = g_CaptureInput.GetTransformations();
        else
        if (ControlType == Control_NetworkInput)
            bones2 = g_NetworkInput.GetTransformations();
        else
        {
            //bones2 = new xQuaternion[ModelGr->instance.I_bones];
            //for (int i = 0; i < ModelGr->instance.I_bones; ++i)
            //    bones2[i].zeroQ();
        }
    }

    if (!bones && bones2) bones = bones2;
    else
    if (bones2)
    {
        xAnimation::Average(bones2, bones, ModelGr->instance.I_bones, 0.5f, bones);
        delete[] bones2;
    }

    if (bones)
        if (FL_verlet)
            xAnimation::Average(bones, QT_verlet, ModelGr->instance.I_bones, verletSystem.W_boneMix, bones);
        else
            UpdateSkews(bones);

    if (bones)
    {
        ModelGr->xModelP->Spine.QuatsFromArray(bones);
        delete[] bones;
        CalculateSkeleton();
    }
    else
    {
        ModelGr->xModelP->Spine.QuatsFromArray(QT_verlet);
        CalculateSkeleton();
    }

    //////////////////////////////////////////////////////// Update Physical Representation

	UpdateMatrices();
    UpdateVerletSystem();

    P_center_Trfm = MX_LocalToWorld_Get().preTransformP(P_center);

    if (T_time > EPSILON)
    {
        xFLOAT T_time_Inv = 1.f / T_time;
        for (int i = 0; i < I_bones; ++i)
            NW_VerletVelocity_total[i] = (verletSystem.P_current[i] - verletSystem.P_previous[i]) * T_time_Inv;
    }
    else
        for (int i = 0; i < I_bones; ++i)
            NW_VerletVelocity_total[i].zero();

    for (int i = 0; i < I_bones; ++i)
        if (NW_VerletVelocity_total[i].isZero())
            F_VerletPower[i].zero();
        else
        {
            xVector3 N_speed = xVector3::Normalize(NW_VerletVelocity_total[i]);
            xFLOAT   W_power = xVector3::DotProduct(F_VerletPower[i], N_speed);
            F_VerletPower[i] = NW_VerletVelocity_total[i];
            if (W_power > 0.f) F_VerletPower[i] += N_speed*W_power;

        }
}