//------------------------------------------------------------------------ float CVehicleMovementWarrior::RotatePart(IVehiclePart *pPart, float angleGoal, int axis, float speed, float deltaTime, float maxDelta) { assert(axis >= AXIS_X && axis <= AXIS_Z); if(!pPart) return 0.f; const Matrix34 &tm = pPart->GetLocalBaseTM(); Matrix33 tm33(tm); float ang = Ang3::GetAnglesXYZ(tm33)[axis]; float absDelta = abs(angleGoal - ang); if(absDelta > 0.01f) { float angleDelta = min(absDelta, speed*deltaTime); if(maxDelta > 0.f) angleDelta = min(angleDelta, maxDelta); angleDelta *= sgn(angleGoal-ang); Matrix34 newTM(tm33 * CreateRotation<Matrix33>(axis, angleDelta), tm.GetTranslation()); pPart->SetLocalBaseTM(newTM); return angleDelta; } return 0.f; }
//------------------------------------------------------------------------ void CVehicleSeatActionRotateTurret::Serialize(TSerialize ser, EEntityAspects aspects) { // MR: for network, only turret parts are serialized // for savegame, all parts are serialized (by CVehicle) if (ser.GetSerializationTarget() == eST_Network) { for (int i = 0; i < eVTRT_NumRotationTypes; ++i) { if (m_rotations[i].m_pPart) { m_rotations[i].m_pPart->Serialize(ser, aspects); } } } else { // save rotation details CryFixedStringT<16> tag; for (int i = 0; i < eVTRT_NumRotationTypes; ++i) { if (m_rotations[i].m_pPart) { Quat q; Matrix34 currentTM = m_rotations[i].m_pPart->GetLocalBaseTM(); if (ser.IsWriting()) q = Quat(currentTM); tag = (i == eVTRT_Pitch) ? "rotation_pitch" : "rotation_yaw"; ser.Value(tag.c_str(), q, 'ori1'); if (ser.IsReading()) { Matrix34 newTM(q); newTM.SetTranslation(currentTM.GetTranslation()); m_rotations[i].m_pPart->SetLocalBaseTM(newTM); m_rotations[i].m_orientation.Set(q); } } } } }
//------------------------------------------------------------------------ void CVehicleSeatActionRotateTurret::UpdatePartRotation(EVehicleTurretRotationType eType, float frameTime) { CRY_ASSERT( eType < eVTRT_NumRotationTypes ); const float threshold = 0.01f; if (frameTime > 0.08f) frameTime = 0.08f; CVehiclePartBase* pPart = m_rotations[eType].m_pPart; IVehiclePart* pParent = pPart->GetParent(); IActor* pActor = m_pSeat->GetPassengerActor(); float rot_dir = fsgnf(m_rotations[eType].m_action); float max_rotation = fabsf(m_rotations[eType].m_action); float rot_speed = DEG2RAD(fabsf(m_rotations[eType].m_speed)) * GetDamageSpeedMul(pPart); float delta = rot_dir * rot_speed * frameTime; delta += m_rotations[eType].m_aimAssist; delta = fmod(delta, gf_PI2); if (delta > gf_PI) delta -= gf_PI2; if (delta < -gf_PI) delta += gf_PI2; Limit( delta, -max_rotation, max_rotation); Ang3 deltaAngles(ZERO); if (eType == eVTRT_Pitch) deltaAngles.x = delta; else if (eType == eVTRT_Yaw) deltaAngles.z = delta; else CRY_ASSERT(false && "Unknown turret rotation"); Matrix34 tm = pPart->GetLocalBaseTM(); Ang3 angles = Ang3::GetAnglesXYZ(tm) + deltaAngles; float lerp = 0.f; if (eType == eVTRT_Pitch) { Vec3 yAxis = m_rotations[eVTRT_Yaw].m_pPart->GetLocalBaseTM().GetColumn1(); yAxis.z = 0.f; yAxis.normalize(); lerp = 0.5f - 0.5f * yAxis.y; Limit(lerp, 0.0f, 1.0f); } // clamp to limits if (m_rotations[eType].m_minLimitF != 0.0f || m_rotations[eType].m_maxLimit != 0.0f) { // Different clamp angles facing forwards/backwards float minLimit = m_rotations[eType].m_minLimitF + (m_rotations[eType].m_minLimitB - m_rotations[eType].m_minLimitF) * lerp; float angle = (eType == eVTRT_Pitch) ? angles.x : angles.z; if (angle > m_rotations[eType].m_maxLimit || angle < minLimit) { angle = clamp_tpl(angle, minLimit, m_rotations[eType].m_maxLimit); m_rotations[eType].m_currentValue = 0.f; if (eType == eVTRT_Pitch) angles.x = angle; else angles.z = angle; } } m_rotations[eType].m_orientation.Set(Quat::CreateRotationXYZ(angles)); m_rotations[eType].m_orientation.Update(frameTime); m_rotations[eType].m_action = 0.0f; m_rotations[eType].m_aimAssist = 0.0f; Matrix34 newTM(m_rotations[eType].m_orientation.Get().GetNormalized()); newTM.SetTranslation(tm.GetTranslation()); pPart->SetLocalBaseTM(newTM); // store world-space rotation const Matrix34 &worldTM = pPart->GetWorldTM(); m_rotations[eType].m_prevWorldQuat = Quat(worldTM); CRY_ASSERT(m_rotations[eType].m_prevWorldQuat.IsValid()); // now update the turret sound based on the calculated rotation speed UpdateRotationSound(eType, delta, frameTime); }