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; } }