//------------------------------------------------------------------------ bool CVehicleSeatActionRotateTurret::GetRemainingAnglesToAimGoalInDegrees(float &pitch, float &yaw) { // no aim goal set (or it got cleared)? if (m_aimGoal.IsZero()) { return false; // have no aim goal } IVehiclePart* pPitchPart = m_rotations[eVTRT_Pitch].m_pPart; IVehiclePart* pYawPart = m_rotations[eVTRT_Yaw].m_pPart; if (!pYawPart) { pitch = yaw = 0.0f; return true; // have an aim goal } // aim goal is a world pos. Convert it to vehicle space: Vec3 aimGoalLocal = m_pVehicle->GetEntity()->GetWorldTM().GetInverted() * m_aimGoal; // direction from yaw part pivot to aim goal Vec3 yawPartToAimGoal = aimGoalLocal - pYawPart->GetLocalTM(false).GetTranslation(); // angles from yaw part to aim goal Quat aimDir = Quat::CreateRotationVDir(yawPartToAimGoal.GetNormalizedSafe()); Ang3 desiredAngles(aimDir); if (pPitchPart) { Ang3 pitchAngles(pPitchPart->GetLocalTM(false)); pitch = RAD2DEG(desiredAngles.x - pitchAngles.x); pitch = fmod(pitch, 360.0f); } else { pitch = 0.0f; } Ang3 yawAngles(pYawPart->GetLocalTM(false)); yaw = RAD2DEG(desiredAngles.z - yawAngles.z); yaw = fmod(yaw, 360.0f); return true; // have an aim goal }
/* ============ hhPhysics_StaticWeapon::Evaluate ============ */ bool hhPhysics_StaticWeapon::Evaluate( int timeStepMSec, int endTimeMSec ) { if( !selfOwner ) { return false; } idMat3 localAxis; idVec3 localOrigin( 0.0f, 0.0f, selfOwner->EyeHeight() ); idAngles pitchAngles( selfOwner->GetUntransformedViewAngles().pitch, 0.0f, 0.0f ); if( selfOwner->InVehicle() ) { localAxis = pitchAngles.ToMat3(); } else { localAxis = ( pitchAngles + selfOwner->GunTurningOffset() ).ToMat3(); localOrigin += selfOwner->GunAcceleratingOffset(); if ( castSelf ) { castSelf->MuzzleRise( localOrigin, localAxis ); } } SetLocalAxis( localAxis ); SetLocalOrigin( localOrigin ); return idPhysics_Static::Evaluate( timeStepMSec, endTimeMSec ); }
/* ================ sdVehicleIKArms::Update ================ */ void sdVehicleIKArms::Update( void ) { idEntity* vehicleEnt = vehicle; if ( !vehicleEnt ) { return; } idVec3 shoulderPos; idMat3 temp; idAnimator* animator = vehicleEnt->GetAnimator(); animator->GetJointTransform( ikJoints[ ARM_JOINT_INDEX_SHOULDER ], gameLocal.time, shoulderPos, temp ); idVec3 shoulderToElbow = baseJointPositions[ ARM_JOINT_INDEX_ELBOW ] - baseJointPositions[ ARM_JOINT_INDEX_SHOULDER ]; idVec3 elbowToWrist = baseJointPositions[ ARM_JOINT_INDEX_WRIST ] - baseJointPositions[ ARM_JOINT_INDEX_ELBOW ]; idVec3 wristToMuzzle = baseJointPositions[ ARM_JOINT_INDEX_MUZZLE ] - baseJointPositions[ ARM_JOINT_INDEX_WRIST ]; idVec3 elbowToMuzzle = baseJointPositions[ ARM_JOINT_INDEX_MUZZLE ] - baseJointPositions[ ARM_JOINT_INDEX_ELBOW ]; idMat3 shoulderAxis; TransposeMultiply( baseJointAxes[ ARM_JOINT_INDEX_SHOULDER ], temp, shoulderAxis ); idMat3 transposedShoulderAxis = shoulderAxis.Transpose(); idPlayer* player = GetPlayer(); if ( player && requireTophat ) { if ( !gameLocal.usercmds[ player->entityNumber ].buttons.btn.tophat ) { player = NULL; } } bool changed = false; changed |= !oldParentAxis.Compare( temp, 0.005f ); idAngles newAngles; renderView_t* view = player ? player->GetRenderView() : NULL; renderEntity_t* renderEnt = vehicleEnt->GetRenderEntity(); trace_t trace; idVec3 modelTarget; if( view ) { idVec3 end = view->vieworg + ( 8192 * view->viewaxis[ 0 ] ); gameLocal.clip.TracePoint( CLIP_DEBUG_PARMS trace, view->vieworg, end, CONTENTS_SOLID | CONTENTS_OPAQUE, player ); modelTarget = trace.endpos; modelTarget -= renderEnt->origin; modelTarget *= renderEnt->axis.Transpose(); modelTarget -= shoulderPos; modelTarget *= transposedShoulderAxis; modelTarget -= shoulderToElbow; } if ( view ) { idVec3 target = modelTarget; const idVec3& dir = baseJointAxes[ ARM_JOINT_INDEX_MUZZLE ][ 0 ]; target -= elbowToMuzzle - ( ( dir * elbowToMuzzle ) * dir ); target *= baseJointAxes[ ARM_JOINT_INDEX_MUZZLE ].Transpose(); newAngles.yaw = RAD2DEG( atan2( target[ 1 ], target[ 0 ] ) ); } else { newAngles.yaw = 0; } bool yawChanged = !sdVehiclePosition::ClampAngle( newAngles, jointAngles, clampYaw, 1, 0.1f ); if ( yawSound != NULL ) { yawSound->Update( yawChanged ); } changed |= yawChanged; idMat3 yawMat; idAngles::YawToMat3( newAngles.yaw, yawMat ); if ( view ) { idVec3 target = modelTarget; idVec3 newElbowToWrist = elbowToWrist * yawMat; idVec3 newWristToMuzzle = wristToMuzzle * yawMat; idMat3 muzzleAxis = baseJointAxes[ ARM_JOINT_INDEX_MUZZLE ] * yawMat; target -= newElbowToWrist; target -= newWristToMuzzle - ( ( muzzleAxis[ 0 ] * newWristToMuzzle ) * muzzleAxis[ 0 ] ); target *= muzzleAxis.Transpose(); newAngles.pitch = -RAD2DEG( atan2( target[ 2 ], target[ 0 ] ) ); } else { newAngles.pitch = 0; } bool pitchChanged = !sdVehiclePosition::ClampAngle( newAngles, jointAngles, clampPitch, 0, 0.1f ); if ( pitchSound != NULL ) { pitchSound->Update( pitchChanged ); } changed |= pitchChanged; // configurable pitching axis - to support vertically oriented arms (eg badger, bumblebee) // as well as horizontally oriented arms (eg goliath) int truePitchAxis = pitchAxis; if ( truePitchAxis < 0 ) { newAngles.pitch = -newAngles.pitch; truePitchAxis = -truePitchAxis; } idAngles pitchAngles( 0.0f, 0.0f, 0.0f ); if ( truePitchAxis == 1 ) { // x-axis pitchAngles.roll = newAngles.pitch; } else if ( truePitchAxis == 3 ) { // z-axis pitchAngles.yaw = newAngles.pitch; } else { // y-axis pitchAngles.pitch = newAngles.pitch; } idMat3 pitchMat = pitchAngles.ToMat3(); if( changed ) { oldParentAxis = temp; jointAngles = newAngles; animator->SetJointAxis( ikJoints[ ARM_JOINT_INDEX_ELBOW ], JOINTMOD_WORLD_OVERRIDE, baseJointAxes[ ARM_JOINT_INDEX_ELBOW ] * yawMat * shoulderAxis ); animator->SetJointAxis( ikJoints[ ARM_JOINT_INDEX_WRIST ], JOINTMOD_WORLD_OVERRIDE, pitchMat * baseJointAxes[ ARM_JOINT_INDEX_WRIST ] * yawMat * shoulderAxis ); } }