IMotionEvent::simresult_e CPhysicsNPCSolver::Simulate( IPhysicsMotionController *pController, IPhysicsObject *pObject, float deltaTime, Vector &linear, AngularImpulse &angular ) { if ( IsIntersecting() ) { const float PUSH_SPEED = 150.0f; if ( pObject->GetGameFlags() & FVPHYSICS_PLAYER_HELD ) { CBasePlayer *pPlayer = UTIL_GetLocalPlayer(); if ( pPlayer ) { pPlayer->ForceDropOfCarriedPhysObjects( m_hEntity ); } } ResetCancelTime(); angular.Init(); linear.Init(); // Don't push on vehicles because they won't move if ( pObject->GetGameFlags() & FVPHYSICS_MULTIOBJECT_ENTITY ) { if ( m_hEntity->GetServerVehicle() ) return SIM_NOTHING; } Vector origin, vel; pObject->GetPosition( &origin, NULL ); pObject->GetVelocity( &vel, NULL ); Vector dir = origin - m_hNPC->GetAbsOrigin(); dir.z = dir.z > 0 ? 0.1f : -0.1f; VectorNormalize(dir); AngularImpulse angVel; angVel.Init(); // NOTE: Iterate this object's contact points // if it can't move in this direction, try sliding along the plane/crease Vector pushImpulse; PhysComputeSlideDirection( pObject, dir * PUSH_SPEED, angVel, &pushImpulse, NULL, 0 ); dir = pushImpulse; VectorNormalize(dir); if ( DotProduct( vel, dir ) < PUSH_SPEED * 0.5f ) { linear = pushImpulse; if ( pObject->GetContactPoint(NULL,NULL) ) { linear.z += GetCurrentGravity(); } } return SIM_GLOBAL_ACCELERATION; } return SIM_NOTHING; }
//----------------------------------------------------------------------------- // Purpose: Returns the magnitude of the entity's angular velocity. //----------------------------------------------------------------------------- float CPointAngularVelocitySensor::SampleAngularVelocity(CBaseEntity *pEntity) { if (pEntity->GetMoveType() == MOVETYPE_VPHYSICS) { IPhysicsObject *pPhys = pEntity->VPhysicsGetObject(); if (pPhys != NULL) { Vector vecVelocity; AngularImpulse vecAngVelocity; pPhys->GetVelocity(&vecVelocity, &vecAngVelocity); QAngle angles; pPhys->GetPosition( NULL, &angles ); float dt = gpGlobals->curtime - GetLastThink(); if ( dt == 0 ) dt = 0.1; // HACKHACK: We don't expect a real 'delta' orientation here, just enough of an error estimate to tell if this thing // is trying to move, but failing. QAngle delta = angles - m_lastOrientation; if ( ( delta.Length() / dt ) < ( vecAngVelocity.Length() * 0.01 ) ) { return 0.0f; } m_lastOrientation = angles; if ( m_bUseHelper == false ) { return vecAngVelocity.Length(); } else { Vector vLine = m_vecAxis - GetAbsOrigin(); VectorNormalize( vLine ); Vector vecWorldAngVelocity; pPhys->LocalToWorldVector( &vecWorldAngVelocity, vecAngVelocity ); float flDot = DotProduct( vecWorldAngVelocity, vLine ); return flDot; } } } else { QAngle vecAngVel = pEntity->GetLocalAngularVelocity(); float flMax = MAX(fabs(vecAngVel[PITCH]), fabs(vecAngVel[YAW])); return MAX(flMax, fabs(vecAngVel[ROLL])); } return 0; }
IMotionEvent::simresult_e CGrabController::Simulate( IPhysicsMotionController *pController, IPhysicsObject *pObject, float deltaTime, Vector &linear, AngularImpulse &angular ) { game_shadowcontrol_params_t shadowParams = m_shadow; if ( InContactWithHeavyObject( pObject, GetLoadWeight() ) ) { m_contactAmount = Approach( 0.1f, m_contactAmount, deltaTime*2.0f ); } else { m_contactAmount = Approach( 1.0f, m_contactAmount, deltaTime*2.0f ); } shadowParams.maxAngular = m_shadow.maxAngular * m_contactAmount * m_contactAmount * m_contactAmount; m_timeToArrive = pObject->ComputeShadowControl( shadowParams, m_timeToArrive, deltaTime ); // Slide along the current contact points to fix bouncing problems Vector velocity; AngularImpulse angVel; pObject->GetVelocity( &velocity, &angVel ); PhysComputeSlideDirection( pObject, velocity, angVel, &velocity, &angVel, GetLoadWeight() ); pObject->SetVelocityInstantaneous( &velocity, NULL ); linear.Init(); angular.Init(); m_errorTime += deltaTime; return SIM_LOCAL_ACCELERATION; }
IMotionEvent::simresult_e CGrabController::Simulate( IPhysicsMotionController *pController, IPhysicsObject *pObject, float deltaTime, Vector &linear, AngularImpulse &angular ) { m_timeToArrive = pObject->ComputeShadowControl( m_shadow, m_timeToArrive, deltaTime ); linear.Init(); angular.Init(); m_errorTime += deltaTime; return SIM_LOCAL_ACCELERATION; }
void PhysForceClearVelocity( IPhysicsObject *pPhys ) { IPhysicsFrictionSnapshot *pSnapshot = pPhys->CreateFrictionSnapshot(); // clear the velocity of the rigid body Vector vel; AngularImpulse angVel; vel.Init(); angVel.Init(); pPhys->SetVelocity( &vel, &angVel ); // now clear the "strain" stored in the contact points while ( pSnapshot->IsValid() ) { pSnapshot->ClearFrictionForce(); pSnapshot->RecomputeFriction(); pSnapshot->NextFrictionData(); } pPhys->DestroyFrictionSnapshot( pSnapshot ); }
void CWeaponBaseRifleGrenade::ShootGrenade( void ) { CDODPlayer *pPlayer = ToDODPlayer( GetOwner() ); if ( !pPlayer ) { Assert( false ); return; } QAngle angThrow = pPlayer->LocalEyeAngles(); Vector vForward, vRight, vUp; AngleVectors( angThrow, &vForward, &vRight, &vUp ); Vector eyes = pPlayer->GetAbsOrigin() + pPlayer->GetViewOffset(); Vector vecSrc = eyes; Vector vecThrow = vForward * DOD_RIFLEGRENADE_SPEED; // raise origin enough so that you can't shoot it straight down through the world if ( pPlayer->m_Shared.IsProne() ) { vecSrc.z += 16; } SetCollisionGroup( COLLISION_GROUP_WEAPON ); QAngle angles; VectorAngles( -vecThrow, angles ); // estimate angular velocity based on initial conditions // uses a constant ang velocity instead of the derivative of the flight path, oh well. AngularImpulse angImpulse; angImpulse.Init(); if ( vecThrow.z > 0 ) angImpulse.y = -angles.x / ( sqrt( (-2 * vecThrow.z) / dod_grenadegravity.GetFloat() )); else angImpulse.y = -10; EmitGrenade( vecSrc, angles, vecThrow, angImpulse, pPlayer, RIFLEGRENADE_FUSE_LENGTH ); }
IMotionEvent::simresult_e CGravControllerPoint::Simulate( IPhysicsMotionController *pController, IPhysicsObject *pObject, float deltaTime, Vector &linear, AngularImpulse &angular ) { hlshadowcontrol_params_t shadowParams = m_shadow; #ifndef CLIENT_DLL m_timeToArrive = pObject->ComputeShadowControl( shadowParams, m_timeToArrive, deltaTime ); #else m_timeToArrive = pObject->ComputeShadowControl( shadowParams, (TICK_INTERVAL*2), deltaTime ); #endif linear.Init(); angular.Init(); return SIM_LOCAL_ACCELERATION; }
//------------------------------------------------------------------------------ // Apply the forces to the entity //------------------------------------------------------------------------------ IMotionEvent::simresult_e C_EntityDissolve::Simulate( IPhysicsMotionController *pController, IPhysicsObject *pObject, float deltaTime, Vector &linear, AngularImpulse &angular ) { linear.Init(); angular.Init(); // Make it zero g linear.z -= -1.02 * GetCurrentGravity(); Vector vel; AngularImpulse angVel; pObject->GetVelocity( &vel, &angVel ); vel += linear * deltaTime; // account for gravity scale Vector unitVel = vel; Vector unitAngVel = angVel; float speed = VectorNormalize( unitVel ); // float angSpeed = VectorNormalize( unitAngVel ); // float speedScale = 0.0; // float angSpeedScale = 0.0; float flLinearLimit = 50; float flLinearLimitDelta = 40; if ( speed > flLinearLimit ) { float flDeltaVel = (flLinearLimit - speed) / deltaTime; if ( flLinearLimitDelta != 0.0f ) { float flMaxDeltaVel = -flLinearLimitDelta / deltaTime; if ( flDeltaVel < flMaxDeltaVel ) { flDeltaVel = flMaxDeltaVel; } } VectorMA( linear, flDeltaVel, unitVel, linear ); } return SIM_GLOBAL_ACCELERATION; }
void CPhysThruster::SetupForces( IPhysicsObject *pPhys, Vector &linear, AngularImpulse &angular ) { Vector forward; AngleVectors( GetLocalAngles(), &forward ); forward = forward * m_force; // multiply the force by mass (it's actually just an acceleration) if ( m_spawnflags & SF_THRUST_MASS_INDEPENDENT ) { forward = forward * pPhys->GetMass(); } EntityMatrix xform; xform.InitFromEntity( m_attachedObject ); Vector origin = xform.LocalToWorld( m_localOrigin ); forward = xform.LocalToWorldRotation( forward ); // Adjust for the position of the thruster -- apply proper torque) pPhys->CalculateVelocityOffset( forward, origin, linear, angular ); // Stay in local space always if this flag is set if ( m_spawnflags & SF_THRUST_LOCAL_ORIENTATION ) { linear = xform.WorldToLocalRotation( linear ); } if ( !(m_spawnflags & SF_THRUST_FORCE) ) { // clear out force linear.Init(); } if ( !(m_spawnflags & SF_THRUST_TORQUE) ) { // clear out torque angular.Init(); } }
IMotionEvent::simresult_e CNailGrenadeController::Simulate( IPhysicsMotionController *pController, IPhysicsObject *pObject, float deltaTime, Vector &linear, AngularImpulse &angular ) { // Try to get to m_vecDesiredPosition // Try to orient ourselves to m_angDesiredOrientation Vector currentPos; QAngle currentAng; pObject->GetPosition( ¤tPos, ¤tAng ); Vector vecVel; AngularImpulse angVel; pObject->GetVelocity( &vecVel, &angVel ); linear.Init(); angular.Init(); if ( m_bReachedPos ) { // Lock at this height if ( vecVel.Length() > 1.0 ) { AngularImpulse nil( 0,0,0 ); pObject->SetVelocityInstantaneous( &vec3_origin, &nil ); // For now teleport to the proper orientation currentAng.x = 0; currentAng.y = 0; currentAng.z = 0; pObject->SetPosition( currentPos, currentAng, true ); } } else { // not at the right height yet, keep moving up linear.z = 50 * ( m_vecDesiredPosition.z - currentPos.z ); if ( currentPos.z > m_vecDesiredPosition.z ) { // lock into position m_bReachedPos = true; } // Start rotating in the right direction // we'll lock angles once we reach proper height to stop the oscillating matrix3x4_t matrix; // get the object's local to world transform pObject->GetPositionMatrix( &matrix ); Vector m_worldGoalAxis(0,0,1); // Get the alignment axis in object space Vector currentLocalTargetAxis; VectorIRotate( m_worldGoalAxis, matrix, currentLocalTargetAxis ); float invDeltaTime = (1/deltaTime); float m_angularLimit = 10; angular = ComputeRotSpeedToAlignAxes( m_worldGoalAxis, currentLocalTargetAxis, angVel, 1.0, invDeltaTime * invDeltaTime, m_angularLimit * invDeltaTime ); } return SIM_GLOBAL_ACCELERATION; }