void CSDKPlayerAnimState::ComputePoseParam_MoveYaw( CStudioHdr *pStudioHdr ) { // Get the estimated movement yaw. EstimateYaw(); // Get the view yaw. float flAngle = AngleNormalize( m_flEyeYaw ); // Calc side to side turning - the view vs. movement yaw. float flYaw = flAngle - m_PoseParameterData.m_flEstimateYaw; flYaw = AngleNormalize( -flYaw ); // Get the current speed the character is running. bool bIsMoving; float flPlaybackRate = CalcMovementPlaybackRate( &bIsMoving ); // Setup the 9-way blend parameters based on our speed and direction. Vector2D vecCurrentMoveYaw( 0.0f, 0.0f ); if ( bIsMoving ) { if ( mp_slammoveyaw.GetBool() ) { flYaw = SnapYawTo( flYaw ); } vecCurrentMoveYaw.x = cos( DEG2RAD( flYaw ) ) * flPlaybackRate; vecCurrentMoveYaw.y = -sin( DEG2RAD( flYaw ) ) * flPlaybackRate; } // Set the 9-way blend movement pose parameters. GetBasePlayer()->SetPoseParameter( pStudioHdr, m_PoseParameterData.m_iMoveX, vecCurrentMoveYaw.x ); GetBasePlayer()->SetPoseParameter( pStudioHdr, m_PoseParameterData.m_iMoveY, -vecCurrentMoveYaw.y ); //Tony; flip it m_DebugAnimData.m_vecMoveYaw = vecCurrentMoveYaw; }
int AngleIntervalSubtract(const AngleInterval& a,const AngleInterval& b,AngleInterval& p,AngleInterval& q) { if(a.intersects(b)) { if(a.contains(b)) { p.setRange(a.c,b.c); q.setRange(AngleNormalize(b.c+b.d),AngleNormalize(a.c+a.d)); return 2; } else if(a.contains(b.c)) { p.setRange(a.c,b.c); return 1; } else if(a.contains(AngleNormalize(b.c+b.d))) { p.setRange(AngleNormalize(b.c+b.d),AngleNormalize(a.c+a.d)); return 1; } else { Assert(b.contains(a)); return 0; } } else { p=a; return 1; } }
//----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- void CObjectBaseMannedGun::ProcessMovement( CBasePlayer *pPlayer, CMoveData *pMove ) { m_Movement.ProcessMovement( pPlayer, pMove ); m_flGunPitch = AngleNormalize( m_flGunPitch ); m_flBarrelPitch = AngleNormalize( m_flBarrelPitch ); }
//----------------------------------------------------------------------------- // Purpose: // Input : flGoalYaw - // flYawRate - // flDeltaTime - // &flCurrentYaw - //----------------------------------------------------------------------------- void CSDKPlayerAnimState::ConvergeYawAngles( float flGoalYaw, float flYawRate, float flDeltaTime, float &flCurrentYaw ) { #define FADE_TURN_DEGREES 60.0f // Find the yaw delta. float flDeltaYaw = flGoalYaw - flCurrentYaw; float flDeltaYawAbs = fabs( flDeltaYaw ); flDeltaYaw = AngleNormalize( flDeltaYaw ); // Always do at least a bit of the turn (1%). float flScale = 1.0f; flScale = flDeltaYawAbs / FADE_TURN_DEGREES; flScale = clamp( flScale, 0.01f, 1.0f ); float flYaw = flYawRate * flDeltaTime * flScale; if ( flDeltaYawAbs < flYaw ) { flCurrentYaw = flGoalYaw; } else { float flSide = ( flDeltaYaw < 0.0f ) ? -1.0f : 1.0f; flCurrentYaw += ( flYaw * flSide ); } flCurrentYaw = AngleNormalize( flCurrentYaw ); #undef FADE_TURN_DEGREES }
//----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- void CSDKPlayerAnimState::Update( float eyeYaw, float eyePitch ) { // Profile the animation update. VPROF( "CMultiPlayerAnimState::Update" ); // Clear animation overlays because we're about to completely reconstruct them. ClearAnimationLayers(); // Some mods don't want to update the player's animation state if they're dead and ragdolled. if ( !ShouldUpdateAnimState() ) { ClearAnimationState(); return; } // Get the SDK player. CSDKPlayer *pSDKPlayer = GetSDKPlayer(); if ( !pSDKPlayer ) return; // Get the studio header for the player. CStudioHdr *pStudioHdr = pSDKPlayer->GetModelPtr(); if ( !pStudioHdr ) return; // Check to see if we should be updating the animation state - dead, ragdolled? if ( !ShouldUpdateAnimState() ) { ClearAnimationState(); return; } // Store the eye angles. m_flEyeYaw = AngleNormalize( eyeYaw ); m_flEyePitch = AngleNormalize( eyePitch ); // Compute the player sequences. ComputeSequences( pStudioHdr ); if ( SetupPoseParameters( pStudioHdr ) ) { // Pose parameter - what direction are the player's legs running in. ComputePoseParam_MoveYaw( pStudioHdr ); // Pose parameter - Torso aiming (up/down). ComputePoseParam_AimPitch( pStudioHdr ); // Pose parameter - Torso aiming (rotation). ComputePoseParam_AimYaw( pStudioHdr ); } #ifdef CLIENT_DLL if ( C_BasePlayer::ShouldDrawLocalPlayer() ) { m_pSDKPlayer->SetPlaybackRate( 1.0f ); } #endif }
Real AngleInterval::clamp(Real x) const { Real dc=AngleCCWDiff(x,c); if(dc <= d) return x; Real da=AngleCCWDiff(c,x); Real db=AngleCCWDiff(x,AngleNormalize(c+d)); if(da < db) return c; else return AngleNormalize(c+d); }
void AngleInterval::normalize() { if (d<0) { c=AngleNormalize(c+d); d=-d; } else c=AngleNormalize(c); }
void CSDKPlayerAnimState::EstimateYaw( void ) { // Get the frame time. float flDeltaTime = gpGlobals->frametime * m_pSDKPlayer->GetSlowMoMultiplier(); if ( flDeltaTime == 0.0f ) return; // Get the player's velocity and angles. Vector vecEstVelocity; GetOuterAbsVelocity( vecEstVelocity ); QAngle angles = GetBasePlayer()->GetLocalAngles(); // If we are not moving, sync up the feet and eyes slowly. if (m_pSDKPlayer->m_Shared.IsProne()) { // Don't touch it } else if ( vecEstVelocity.x == 0.0f && vecEstVelocity.y == 0.0f ) { float flYawDelta = angles[YAW] - m_PoseParameterData.m_flEstimateYaw; flYawDelta = AngleNormalize( flYawDelta ); if ( flDeltaTime < 0.25f ) { flYawDelta *= ( flDeltaTime * 4.0f ); } else { flYawDelta *= flDeltaTime; } m_PoseParameterData.m_flEstimateYaw += flYawDelta; m_PoseParameterData.m_flEstimateYaw = AngleNormalize( m_PoseParameterData.m_flEstimateYaw ); } else if (m_pSDKPlayer->m_Shared.IsAimedIn() || m_pSDKPlayer->m_Shared.IsDiving() || m_pSDKPlayer->m_Shared.IsRolling() || m_pSDKPlayer->m_Shared.IsSliding()) { m_PoseParameterData.m_flEstimateYaw = ( atan2( vecEstVelocity.y, vecEstVelocity.x ) * 180.0f / M_PI ); m_PoseParameterData.m_flEstimateYaw = clamp( m_PoseParameterData.m_flEstimateYaw, -180.0f, 180.0f ); } else { QAngle angDir; VectorAngles(vecEstVelocity, angDir); if (fabs(AngleNormalize(angDir[YAW] - m_flEyeYaw)) <= 90) m_bFacingForward = true; else if (fabs(AngleNormalize(angDir[YAW] - m_flEyeYaw)) >= 91) m_bFacingForward = false; float flYawDelta = AngleNormalize(m_flGoalFeetYaw - m_flCurrentFeetYaw); if (m_bFacingForward) m_PoseParameterData.m_flEstimateYaw = flYawDelta; else m_PoseParameterData.m_flEstimateYaw = 180-flYawDelta; } }
//----------------------------------------------------------------------------- // Purpose: Causes the turret to face its desired angles //----------------------------------------------------------------------------- bool CNPC_CeilingTurret::UpdateFacing( void ) { bool bMoved = false; matrix3x4_t localToWorld; GetAttachment( LookupAttachment( "eyes" ), localToWorld ); Vector vecGoalDir; AngleVectors( m_vecGoalAngles, &vecGoalDir ); Vector vecGoalLocalDir; VectorIRotate( vecGoalDir, localToWorld, vecGoalLocalDir ); if ( g_debug_turret_ceiling.GetBool() ) { Vector vecMuzzle, vecMuzzleDir; QAngle vecMuzzleAng; GetAttachment( "eyes", vecMuzzle, vecMuzzleAng ); AngleVectors( vecMuzzleAng, &vecMuzzleDir ); NDebugOverlay::Cross3D( vecMuzzle, -Vector(2,2,2), Vector(2,2,2), 255, 255, 0, false, 0.05 ); NDebugOverlay::Cross3D( vecMuzzle+(vecMuzzleDir*256), -Vector(2,2,2), Vector(2,2,2), 255, 255, 0, false, 0.05 ); NDebugOverlay::Line( vecMuzzle, vecMuzzle+(vecMuzzleDir*256), 255, 255, 0, false, 0.05 ); NDebugOverlay::Cross3D( vecMuzzle, -Vector(2,2,2), Vector(2,2,2), 255, 0, 0, false, 0.05 ); NDebugOverlay::Cross3D( vecMuzzle+(vecGoalDir*256), -Vector(2,2,2), Vector(2,2,2), 255, 0, 0, false, 0.05 ); NDebugOverlay::Line( vecMuzzle, vecMuzzle+(vecGoalDir*256), 255, 0, 0, false, 0.05 ); } QAngle vecGoalLocalAngles; VectorAngles( vecGoalLocalDir, vecGoalLocalAngles ); // Update pitch float flDiff = AngleNormalize( UTIL_ApproachAngle( vecGoalLocalAngles.x, 0.0, 0.1f * MaxYawSpeed() ) ); SetPoseParameter( m_poseAim_Pitch, GetPoseParameter( m_poseAim_Pitch ) + ( flDiff / 1.5f ) ); if ( fabs( flDiff ) > 0.1f ) { bMoved = true; } // Update yaw flDiff = AngleNormalize( UTIL_ApproachAngle( vecGoalLocalAngles.y, 0.0, 0.1f * MaxYawSpeed() ) ); SetPoseParameter( m_poseAim_Yaw, GetPoseParameter( m_poseAim_Yaw ) + ( flDiff / 1.5f ) ); if ( fabs( flDiff ) > 0.1f ) { bMoved = true; } InvalidateBoneCache(); return bMoved; }
int CBaseTurret::MoveTurret(void) { bool bDidMove = false; int iPose; matrix3x4_t localToWorld; GetAttachment( LookupAttachment( "eyes" ), localToWorld ); Vector vecGoalDir; AngleVectors( m_vecGoalAngles, &vecGoalDir ); Vector vecGoalLocalDir; VectorIRotate( vecGoalDir, localToWorld, vecGoalLocalDir ); QAngle vecGoalLocalAngles; VectorAngles( vecGoalLocalDir, vecGoalLocalAngles ); float flDiff; QAngle vecNewAngles; // update pitch flDiff = AngleNormalize( UTIL_ApproachAngle( vecGoalLocalAngles.x, 0.0, 0.1 * m_iBaseTurnRate ) ); iPose = LookupPoseParameter( TURRET_BC_PITCH ); SetPoseParameter( iPose, GetPoseParameter( iPose ) + flDiff / 1.5 ); if (fabs(flDiff) > 0.1) { bDidMove = true; } // update yaw, with acceleration #if 0 float flDist = AngleNormalize( vecGoalLocalAngles.y ); float flNewDist; float flNewTurnRate; ChangeDistance( 0.1, flDist, 0.0, m_fTurnRate, m_iBaseTurnRate, m_iBaseTurnRate * 4, flNewDist, flNewTurnRate ); m_fTurnRate = flNewTurnRate; flDiff = flDist - flNewDist; #else flDiff = AngleNormalize( UTIL_ApproachAngle( vecGoalLocalAngles.y, 0.0, 0.1 * m_iBaseTurnRate ) ); #endif iPose = LookupPoseParameter( TURRET_BC_YAW ); SetPoseParameter( iPose, GetPoseParameter( iPose ) + flDiff / 1.5 ); if (fabs(flDiff) > 0.1) { bDidMove = true; } if (bDidMove) { // DevMsg( "(%.2f, %.2f)\n", AngleNormalize( vecGoalLocalAngles.x ), AngleNormalize( vecGoalLocalAngles.y ) ); } return bDidMove; }
void CAI_Spotlight::UpdateSpotlightDirection( void ) { if ( !m_hSpotlight ) { CreateSpotlightEntities(); } // Compute the current beam direction Vector vTargetDir; VectorSubtract( m_vSpotlightTargetPos, m_hSpotlight->GetAbsStartPos(), vTargetDir ); VectorNormalize(vTargetDir); ConstrainToCone( &vTargetDir ); // Compute the amount to rotate float flDot = DotProduct( vTargetDir, m_vSpotlightDir ); flDot = clamp( flDot, -1.0f, 1.0f ); float flAngle = AngleNormalize( RAD2DEG( acos( flDot ) ) ); float flClampedAngle = clamp( flAngle, 0.0f, 45.0f ); float flBeamTurnRate = SimpleSplineRemapVal( flClampedAngle, 0.0f, 45.0f, 10.0f, 45.0f ); if ( fabs(flAngle) > flBeamTurnRate * gpGlobals->frametime ) { flAngle = flBeamTurnRate * gpGlobals->frametime; } // Compute the rotation axis Vector vecRotationAxis; CrossProduct( m_vSpotlightDir, vTargetDir, vecRotationAxis ); if ( VectorNormalize( vecRotationAxis ) < 1e-3 ) { vecRotationAxis.Init( 0, 0, 1 ); } // Compute the actual rotation amount, using quat slerp blending Quaternion desiredQuat, resultQuat; AxisAngleQuaternion( vecRotationAxis, flAngle, desiredQuat ); QuaternionSlerp( m_vAngularVelocity, desiredQuat, QUAT_BLEND_FACTOR, resultQuat ); m_vAngularVelocity = resultQuat; // If we're really close, and we're not moving very quickly, slam. float flActualRotation = AngleNormalize( RAD2DEG(2 * acos(m_vAngularVelocity.w)) ); if (( flActualRotation < 1e-3 ) && (flAngle < 1e-3 )) { m_vSpotlightDir = vTargetDir; m_vAngularVelocity.Init( 0, 0, 0, 1 ); return; } // Update the desired direction matrix3x4_t rot; Vector vecNewDir; QuaternionMatrix( m_vAngularVelocity, rot ); VectorRotate( m_vSpotlightDir, rot, vecNewDir ); m_vSpotlightDir = vecNewDir; VectorNormalize(m_vSpotlightDir); }
void CSDKPlayerAnimState::ComputePoseParam_StuntYaw( CStudioHdr *pStudioHdr ) { // Get the view yaw. float flAngle = AngleNormalize( m_flEyeYaw ); // Calc side to side turning - the view vs. movement yaw. float flYaw = flAngle - m_PoseParameterData.m_flEstimateYaw; flYaw = AngleNormalize( flYaw ); GetBasePlayer()->SetPoseParameter( pStudioHdr, m_iStuntYawPose, flYaw ); }
/** * Orient head and eyes towards m_lookAt. */ void C_HL2MP_Player::UpdateLookAt( void ) { // head yaw if (m_headYawPoseParam < 0 || m_headPitchPoseParam < 0) return; // orient eyes m_viewtarget = m_vLookAtTarget; // blinking if (m_blinkTimer.IsElapsed()) { m_blinktoggle = !m_blinktoggle; m_blinkTimer.Start( RandomFloat( 1.5f, 4.0f ) ); } // Figure out where we want to look in world space. QAngle desiredAngles; Vector to = m_vLookAtTarget - EyePosition(); VectorAngles( to, desiredAngles ); // Figure out where our body is facing in world space. QAngle bodyAngles( 0, 0, 0 ); bodyAngles[YAW] = GetLocalAngles()[YAW]; float flBodyYawDiff = bodyAngles[YAW] - m_flLastBodyYaw; m_flLastBodyYaw = bodyAngles[YAW]; // Set the head's yaw. float desired = AngleNormalize( desiredAngles[YAW] - bodyAngles[YAW] ); desired = clamp( desired, m_headYawMin, m_headYawMax ); m_flCurrentHeadYaw = ApproachAngle( desired, m_flCurrentHeadYaw, 130 * gpGlobals->frametime ); // Counterrotate the head from the body rotation so it doesn't rotate past its target. m_flCurrentHeadYaw = AngleNormalize( m_flCurrentHeadYaw - flBodyYawDiff ); desired = clamp( desired, m_headYawMin, m_headYawMax ); SetPoseParameter( m_headYawPoseParam, m_flCurrentHeadYaw ); // Set the head's yaw. desired = AngleNormalize( desiredAngles[PITCH] ); desired = clamp( desired, m_headPitchMin, m_headPitchMax ); m_flCurrentHeadPitch = ApproachAngle( desired, m_flCurrentHeadPitch, 130 * gpGlobals->frametime ); m_flCurrentHeadPitch = AngleNormalize( m_flCurrentHeadPitch ); SetPoseParameter( m_headPitchPoseParam, m_flCurrentHeadPitch ); }
//----------------------------------------------------------------------------- // Purpose: Causes the camera to face its desired angles //----------------------------------------------------------------------------- bool CNPC_CombineCamera::UpdateFacing() { bool bMoved = false; matrix3x4_t localToWorld; GetAttachment(LookupAttachment("eyes"), localToWorld); Vector vecGoalDir; AngleVectors(m_vecGoalAngles, &vecGoalDir ); Vector vecGoalLocalDir; VectorIRotate(vecGoalDir, localToWorld, vecGoalLocalDir); QAngle vecGoalLocalAngles; VectorAngles(vecGoalLocalDir, vecGoalLocalAngles); // Update pitch float flDiff = AngleNormalize(UTIL_ApproachAngle( vecGoalLocalAngles.x, 0.0, 0.1f * MaxYawSpeed())); int iPose = LookupPoseParameter(COMBINE_CAMERA_BC_PITCH); SetPoseParameter(iPose, GetPoseParameter(iPose) + (flDiff / 1.5f)); if (fabs(flDiff) > 0.1f) { bMoved = true; } // Update yaw flDiff = AngleNormalize(UTIL_ApproachAngle( vecGoalLocalAngles.y, 0.0, 0.1f * MaxYawSpeed())); iPose = LookupPoseParameter(COMBINE_CAMERA_BC_YAW); SetPoseParameter(iPose, GetPoseParameter(iPose) + (flDiff / 1.5f)); if (fabs(flDiff) > 0.1f) { bMoved = true; } if (bMoved && (m_flMoveSoundTime < gpGlobals->curtime)) { EmitSound("NPC_CombineCamera.Move"); m_flMoveSoundTime = gpGlobals->curtime + CAMERA_MOVE_INTERVAL; } // You're going to make decisions based on this info. So bump the bone cache after you calculate everything InvalidateBoneCache(); return bMoved; }
//----------------------------------------------------------------------------- // Purpose: // Input : goal - // maxrate - // dt - // current - // Output : int //----------------------------------------------------------------------------- int CBasePlayerAnimState::ConvergeAngles( float goal,float maxrate, float maxgap, float dt, float& current ) { int direction = TURN_NONE; float anglediff = goal - current; anglediff = AngleNormalize( anglediff ); float anglediffabs = fabs( anglediff ); float scale = 1.0f; if ( anglediffabs <= FADE_TURN_DEGREES ) { scale = anglediffabs / FADE_TURN_DEGREES; // Always do at least a bit of the turn ( 1% ) scale = clamp( scale, 0.01f, 1.0f ); } float maxmove = maxrate * dt * scale; if ( anglediffabs > maxgap ) { // gap is too big, jump maxmove = (anglediffabs - maxgap); } if ( anglediffabs < maxmove ) { // we are close enought, just set the final value current = goal; } else { // adjust value up or down if ( anglediff > 0 ) { current += maxmove; direction = TURN_LEFT; } else { current -= maxmove; direction = TURN_RIGHT; } } current = AngleNormalize( current ); return direction; }
//----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- void CHL2MPPlayerAnimState::Update( float eyeYaw, float eyePitch ) { // Profile the animation update. VPROF( "CHL2MPPlayerAnimState::Update" ); // Get the HL2MP player. CHL2MP_Player *pHL2MPPlayer = GetHL2MPPlayer(); if ( !pHL2MPPlayer ) return; // Get the studio header for the player. CStudioHdr *pStudioHdr = pHL2MPPlayer->GetModelPtr(); if ( !pStudioHdr ) return; // Check to see if we should be updating the animation state - dead, ragdolled? if ( !ShouldUpdateAnimState() ) { ClearAnimationState(); return; } // Store the eye angles. m_flEyeYaw = AngleNormalize( eyeYaw ); m_flEyePitch = AngleNormalize( eyePitch ); // Compute the player sequences. ComputeSequences( pStudioHdr ); if ( SetupPoseParameters( pStudioHdr ) ) { // Pose parameter - what direction are the player's legs running in. ComputePoseParam_MoveYaw( pStudioHdr ); // Pose parameter - Torso aiming (up/down). ComputePoseParam_AimPitch( pStudioHdr ); // Pose parameter - Torso aiming (rotation). ComputePoseParam_AimYaw( pStudioHdr ); } #ifdef CLIENT_DLL if ( C_BasePlayer::ShouldDrawLocalPlayer() ) { m_pHL2MPPlayer->SetPlaybackRate( 1.0f ); } #endif }
// remaps an angular variable to a 3 band function: // 0 <= t < start : f(t) = 0 // start <= t <= end : f(t) = end * spline(( t-start) / (end-start) ) // s curve between clamped and linear // end < t : f(t) = t float RemapAngleRange( float startInterval, float endInterval, float value ) { // Fixup the roll value = AngleNormalize( value ); float absAngle = fabs(value); // beneath cutoff? if ( absAngle < startInterval ) { value = 0; } // in spline range? else if ( absAngle <= endInterval ) { float newAngle = SimpleSpline( (absAngle - startInterval) / (endInterval-startInterval) ) * endInterval; // grab the sign from the initial value if ( value < 0 ) { newAngle *= -1; } value = newAngle; } // else leave it alone, in linear range return value; }
//----------------------------------------------------------------------------- // Purpose: // Input : pData - // vehicleEyeAngles - //----------------------------------------------------------------------------- void RemapViewAngles( ViewSmoothingData_t *pData, QAngle &vehicleEyeAngles ) { QAngle vecEyeAnglesRemapped; // Clamp pitch. RemapAngleRange_CurvePart_t ePitchCurvePart; vecEyeAnglesRemapped.x = RemapAngleRange( pData->flPitchCurveZero, pData->flPitchCurveLinear, vehicleEyeAngles.x, &ePitchCurvePart ); vehicleEyeAngles.z = vecEyeAnglesRemapped.z = AngleNormalize( vehicleEyeAngles.z ); // Blend out the roll dampening as our pitch approaches 90 degrees, to avoid gimbal lock problems. float flBlendRoll = 1.0; if ( fabs( vehicleEyeAngles.x ) > 60 ) { flBlendRoll = RemapValClamped( fabs( vecEyeAnglesRemapped.x ), 60, 80, 1, 0); } RemapAngleRange_CurvePart_t eRollCurvePart; float flRollDamped = RemapAngleRange( pData->flRollCurveZero, pData->flRollCurveLinear, vecEyeAnglesRemapped.z, &eRollCurvePart ); vecEyeAnglesRemapped.z = Lerp( flBlendRoll, vecEyeAnglesRemapped.z, flRollDamped ); //Msg("PITCH "); vehicleEyeAngles.x = ApplyViewLocking( vehicleEyeAngles.x, vecEyeAnglesRemapped.x, pData->pitchLockData, ePitchCurvePart ); //Msg("ROLL "); vehicleEyeAngles.z = ApplyViewLocking( vehicleEyeAngles.z, vecEyeAnglesRemapped.z, pData->rollLockData, eRollCurvePart ); }
void CSDKPlayerAnimState::ConvergeYawAnglesThroughZero( float flGoalYaw, float flYawRate, float flDeltaTime, float &flCurrentYaw ) { float flFadeTurnDegrees = 60; float flEyeGoalYaw = AngleDiff(flGoalYaw, m_flEyeYaw); float flEyeCurrentYaw = AngleDiff(flCurrentYaw, m_flEyeYaw); // Find the yaw delta. float flDeltaYaw = flEyeGoalYaw - flEyeCurrentYaw; float flDeltaYawAbs = fabs( flDeltaYaw ); // Always do at least a bit of the turn (1%). float flScale = 1.0f; flScale = flDeltaYawAbs / flFadeTurnDegrees; flScale = clamp( flScale, 0.01f, 1.0f ); float flYaw = flYawRate * flDeltaTime * flScale; if ( flDeltaYawAbs < flYaw ) { flCurrentYaw = flGoalYaw; } else { float flSide = ( flDeltaYaw < 0.0f ) ? -1.0f : 1.0f; flCurrentYaw += ( flYaw * flSide ); } flCurrentYaw = AngleNormalize( flCurrentYaw ); }
void CDODPlayerShared::ClampDeployedAngles( QAngle *vecTestAngles ) { Assert( vecTestAngles ); // Clamp Pitch vecTestAngles->x = clamp( vecTestAngles->x, MAX_DEPLOY_PITCH, MIN_DEPLOY_PITCH ); // Clamp Yaw - do a bit more work as yaw will wrap around and cause problems float flDeployedYawCenter = GetDeployedAngles().y; float flDelta = AngleNormalize( vecTestAngles->y - flDeployedYawCenter ); if( flDelta < m_flDeployedYawLimitRight ) { vecTestAngles->y = flDeployedYawCenter + m_flDeployedYawLimitRight; } else if( flDelta > m_flDeployedYawLimitLeft ) { vecTestAngles->y = flDeployedYawCenter + m_flDeployedYawLimitLeft; } /* Msg( "delta %.1f ( left %.1f, right %.1f ) ( %.1f -> %.1f )\n", flDelta, flDeployedYawCenter + m_flDeployedYawLimitLeft, flDeployedYawCenter + m_flDeployedYawLimitRight, before, vecTestAngles->y ); */ }
void CObjectTeleporter::ShowDirectionArrow( bool bShow ) { if ( bShow != m_bShowDirectionArrow ) { if ( m_iDirectionBodygroup >= 0 ) { SetBodygroup( m_iDirectionBodygroup, bShow ? 1 : 0 ); } m_bShowDirectionArrow = bShow; if ( bShow ) { CObjectTeleporter *pMatch = GetMatchingTeleporter(); Assert( pMatch ); Vector vecToOwner = pMatch->GetAbsOrigin() - GetAbsOrigin(); QAngle angleToExit; VectorAngles( vecToOwner, Vector(0,0,1), angleToExit ); angleToExit -= GetAbsAngles(); // pose param is flipped and backwards, adjust. //m_flYawToExit = anglemod( -angleToExit.y + 180.0 ); m_flYawToExit = AngleNormalize( -angleToExit.y + 180.0 ); // For whatever reason the original code normalizes angle 0 to 360 while pose param // takes angle from -180 to 180. I have no idea how did this work properly // in official TF2 all this time. (Nicknine) } } }
void AngleInterval::setCosGreater(Real y) { if(y >= One) setEmpty(); else if(y <= -One) setCircle(); else { c=Acos(y); d=c+c; c=AngleNormalize(-c); } }
void AngleInterval::setSinGreater(Real y) { if(y > One) setEmpty(); else if(y <= -One) setCircle(); else { c=Asin(y); d=Pi-c; c=AngleNormalize(c); } }
//----------------------------------------------------------------------------- // Purpose: // Input : goal - // maxrate - // dt - // current - // Output : int //----------------------------------------------------------------------------- int CPlayerAnimState::ConvergeAngles( float goal,float maxrate, float dt, float& current ) { int direction = TURN_NONE; float anglediff = goal - current; float anglediffabs = fabs( anglediff ); anglediff = AngleNormalize( anglediff ); float scale = 1.0f; if ( anglediffabs <= FADE_TURN_DEGREES ) { scale = anglediffabs / FADE_TURN_DEGREES; // Always do at least a bit of the turn ( 1% ) scale = clamp( scale, 0.01f, 1.0f ); } float maxmove = maxrate * dt * scale; if ( fabs( anglediff ) < maxmove ) { current = goal; } else { if ( anglediff > 0 ) { current += maxmove; direction = TURN_LEFT; } else { current -= maxmove; direction = TURN_RIGHT; } } current = AngleNormalize( current ); return direction; }
bool AngleInterval::contains(const AngleInterval& i) const { if(i.isEmpty()) return true; if(isFull()) return true; if(isEmpty()) return false; if(i.d > d) return false; //tricky at pi if(i.d == Pi && d == Pi) return c==i.c; Real delta1 = AngleCCWDiff(i.c,c); Real delta2 = AngleCCWDiff(AngleNormalize(i.c+i.d),c); return delta1 <= d+Epsilon && delta2 <=d+Epsilon; }
//----------------------------------------------------------------------------- // Purpose: // Input : dt - //----------------------------------------------------------------------------- void CBasePlayerAnimState::EstimateYaw() { Vector est_velocity; GetOuterAbsVelocity( est_velocity ); float flLength = est_velocity.Length2D(); if ( flLength > MOVING_MINIMUM_SPEED ) { m_flGaitYaw = atan2( est_velocity[1], est_velocity[0] ); m_flGaitYaw = RAD2DEG( m_flGaitYaw ); m_flGaitYaw = AngleNormalize( m_flGaitYaw ); } }
//----------------------------------------------------------------------------- // Purpose: // Output : void SyncPoseToAimAngles //----------------------------------------------------------------------------- void CNPC_RocketTurret::SyncPoseToAimAngles ( void ) { QAngle localAngles = TransformAnglesToLocalSpace( m_vecCurrentAngles.Get(), EntityToWorldTransform() ); // Update pitch SetPoseParameter( m_iPosePitch, localAngles.x ); // Update yaw -- NOTE: This yaw movement is screwy for this model, we must invert the yaw delta and also skew an extra 90 deg to // get the 'forward face' of the turret to match up with the look direction. If the model and it's pose parameters change, this will be wrong. SetPoseParameter( m_iPoseYaw, AngleNormalize( -localAngles.y - 90 ) ); InvalidateBoneCache(); }
//----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- void CSDKPlayerAnimState::EstimateYaw( void ) { // Get the frame time. float flDeltaTime = gpGlobals->frametime; if ( flDeltaTime == 0.0f ) return; // Get the player's velocity and angles. Vector vecEstVelocity; GetOuterAbsVelocity( vecEstVelocity ); QAngle angles = GetBasePlayer()->GetLocalAngles(); // If we are not moving, sync up the feet and eyes slowly. if ( vecEstVelocity.x == 0.0f && vecEstVelocity.y == 0.0f ) { float flYawDelta = angles[YAW] - m_PoseParameterData.m_flEstimateYaw; flYawDelta = AngleNormalize( flYawDelta ); if ( flDeltaTime < 0.25f ) { flYawDelta *= ( flDeltaTime * 4.0f ); } else { flYawDelta *= flDeltaTime; } m_PoseParameterData.m_flEstimateYaw += flYawDelta; AngleNormalize( m_PoseParameterData.m_flEstimateYaw ); } else { m_PoseParameterData.m_flEstimateYaw = ( atan2( vecEstVelocity.y, vecEstVelocity.x ) * 180.0f / M_PI ); m_PoseParameterData.m_flEstimateYaw = clamp( m_PoseParameterData.m_flEstimateYaw, -180.0f, 180.0f ); } }
//----------------------------------------------------------------------------- // Purpose: Alien Swarm camera yaw. //----------------------------------------------------------------------------- float CASWInput::ASW_GetCameraYaw( const float *pfDeathCamInterp /*= NULL*/ ) { float fDeathCamInterp; if ( pfDeathCamInterp ) { fDeathCamInterp = *pfDeathCamInterp; } else { fDeathCamInterp = ( ASWGameRules() ? ASWGameRules()->GetMarineDeathCamInterp() : 0.0f ); } if ( fDeathCamInterp > 0.0f ) { float fRotate = gpGlobals->curtime * asw_cam_marine_yaw_death_rate.GetFloat() + ASWGameRules()->m_fDeathCamYawAngleOffset; float fFullRotations = static_cast< int >( fRotate / 360.0f ); fRotate -= fFullRotations * 360.0f; fRotate = AngleNormalize( fRotate ); return ( 1.0f - fDeathCamInterp ) * asw_cam_marine_yaw.GetFloat() + fDeathCamInterp * ( asw_cam_marine_yaw.GetFloat() + fRotate ); } // Check to see if we are in a camera volume. C_ASW_Player *pPlayer = C_ASW_Player::GetLocalASWPlayer(); if (pPlayer && pPlayer->GetMarine()) { C_ASW_Camera_Volume *pCameraVolume = C_ASW_Camera_Volume::IsPointInCameraVolume( pPlayer->GetMarine()->GetAbsOrigin() ); if ( pCameraVolume ) { m_fCurrentBlendCamYaw = ASW_ClampYaw( asw_cam_marine_yaw_rate.GetFloat(), m_fCurrentBlendCamYaw, pCameraVolume->m_fCameraYaw, MIN( 0.2f, gpGlobals->frametime ) ); } else { m_fCurrentBlendCamYaw = ASW_ClampYaw( asw_cam_marine_yaw_rate.GetFloat(), m_fCurrentBlendCamYaw, asw_cam_marine_yaw.GetFloat(), MIN( 0.2f, gpGlobals->frametime ) ); } if ( m_flLastYawSend + 0.2f < gpGlobals->curtime || m_flLastYawSend > gpGlobals->curtime ) { m_flLastYawSend = gpGlobals->curtime; char buf[32]; Q_snprintf( buf, sizeof( buf ), "cl_aswcamerayaw %f\n", m_fCurrentBlendCamYaw ); engine->ServerCmd( buf, false ); } } return m_fCurrentBlendCamYaw; }
void MultiRobot2DCSpace::SampleNeighborhood(const Config& c,Real r,Config& x) { int stride = (allowRotation ? 3 : 2); Assert(c.n==stride*(int)robots.size()); x = c; int k=0; for(size_t i=0;i<robots.size();i++,k+=stride) { Real dx,dy; SampleDisk(r,dx,dy); x(k) += dx; x(k+1) += dy; if(allowRotation) { x(k+2) += Rand(-r,r)/angleDistanceWeight; x(k+2)=AngleNormalize(x(k+2)); } } }