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;
}
Example #5
0
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;
}
Example #8
0
//------------------------------------------------------------------------------
// 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( &currentPos, &currentAng );

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