Пример #1
0
void CPhysxSkeleton::Update()
{
    if (IsRagdollActive())
    {
        UpdateCal3dFromPhysx();
    }
    else
    {
        UpdatePhysxFromCal3d();
    }

}
Пример #2
0
void CCharEntity::DeactivateRagdoll()
{
	n_assert(IsRagdollActive());

	Flags.Clear(RAGDOLL_ACTIVE);

	if (RagdollComposite.isvalid())
	{
		DisableCollision();
		SetComposite(DefaultComposite);
		EnableCollision();
	}
}
Пример #3
0
void CCharEntity::ActivateRagdoll()
{
	n_assert(pNCharacter);
	n_assert(!IsRagdollActive());

	//!!!many unnecessary matrix copyings!
	if (RagdollComposite.isvalid())
	{
		// Get transform before detaching current composite
		matrix44 CurrTfm = GetTransform();

		// Switch current composite, this will reset the
		// composite's transform to the entity's initial transform
		DisableCollision();
		SetComposite(RagdollComposite);
		EnableCollision();

		// Fix transform (all the 180 voodoo is necessary because Nebula2's
		// characters are rotated by 180 degree around the Y axis
		matrix44 R180 = Rotate180;
		R180.mult_simple(CurrTfm);
		RagdollComposite->SetTransform(R180);

		// Sync physics joint angles with bind pose model
		RagdollComposite->ReadJoints();

		// Apply a the stored impulse to the ragdoll
		if (pRagdollImpulse.isvalid())
		{
			pRagdollImpulse->Apply();
			pRagdollImpulse = NULL;
		}

		Flags.Set(RAGDOLL_ACTIVE);
	}
}
Пример #4
0
void CCharEntity::OnStepBefore()
{
	if (IsCollisionEnabled() && !IsRagdollActive())
	{
		CEnvInfo EnvInfo;
		vector3 Pos = GetTransform().pos_component();
		Pos.y += Height;

		float DistanceToGround;
		if (EnvQueryMgr->GetEnvInfoAt(Pos, EnvInfo, Height + 0.1f, GetUniqueID()))
		{
			DistanceToGround = Pos.y - Height - EnvInfo.WorldHeight;
			GroundMtl = EnvInfo.Material;
		}
		else
		{
			DistanceToGround = FLT_MAX;
			GroundMtl = InvalidMaterial;
		}

		CRigidBody* pMasterBody = Composite->GetMasterBody();
		bool BodyIsEnabled = IsEnabled();
		vector3 AngularVel = pMasterBody->GetAngularVelocity();
		vector3 LinearVel = pMasterBody->GetLinearVelocity();
		vector3 DesiredLVelChange = DesiredLinearVel - LinearVel;

 		if (DistanceToGround <= 0.f)
		{
			// No torques now, angular velocity changes by impulse immediately to desired value
			bool Actuated = DesiredAngularVel != AngularVel.y;
			if (Actuated)
			{
				if (!BodyIsEnabled) SetEnabled(true);
				pMasterBody->SetAngularVelocity(vector3(0.f, DesiredAngularVel, 0.f));
			}

			if (!DesiredLVelChange.isequal(vector3::Zero, 0.0001f))
			{
				if (!Actuated)
				{
					Actuated = true;
					SetEnabled(true);
				}

				// Vertical movement for non-flying actors is impulse (jump).
				// Since speed if already clamped to actor caps, we save vertical desired velocity as is.
				// Spring force pushes us from below the ground.
				
				//!!!!!!!!!!!!!!!
				//!!!calc correct impulse for the spring!
				//!!!!!!!!!!!!!!!
				
				float VerticalDesVelChange = DesiredLVelChange.y - (50.0f * DistanceToGround);

				float Mass = pMasterBody->GetMass();

				//!!!remove calcs for Y, it is zero (optimization)!
				dVector3 ODEForce;
				dWorldImpulseToForce(Level->GetODEWorldID(), dReal(Level->GetStepSize()),
					DesiredLVelChange.x * Mass, 0.f, DesiredLVelChange.z * Mass, ODEForce);
				float SqForceMagnitude = (float)dCalcVectorLengthSquare3(ODEForce);
				if (SqForceMagnitude > 0.f)
				{
					float MaxForceMagnitude = Mass * MaxHorizAccel;
					float SqMaxForceMagnitude = MaxForceMagnitude * MaxForceMagnitude;
					if (SqForceMagnitude > SqMaxForceMagnitude)
						dScaleVector3(ODEForce, MaxForceMagnitude / n_sqrt(SqForceMagnitude));
					dBodyAddForce(pMasterBody->GetODEBodyID(), ODEForce[0], ODEForce[1], ODEForce[2]);
				}
				
				if (VerticalDesVelChange != 0.f)
				{
					dWorldImpulseToForce(Level->GetODEWorldID(), dReal(Level->GetStepSize()),
						0.f, VerticalDesVelChange * Mass, 0.f, ODEForce);
					dBodyAddForce(pMasterBody->GetODEBodyID(), ODEForce[0], ODEForce[1], ODEForce[2]);
				}
			}

			if (BodyIsEnabled && !Actuated && DistanceToGround > -0.002f)
			{
				const float FreezeThreshold = 0.00001f; //???use TINY?

				bool AVelIsAlmostZero = n_fabs(AngularVel.y) < FreezeThreshold;
				bool LVelIsAlmostZero = n_fabs(LinearVel.x) * (float)Level->GetStepSize() < FreezeThreshold &&
										n_fabs(LinearVel.z) * (float)Level->GetStepSize() < FreezeThreshold;

				if (AVelIsAlmostZero)
					pMasterBody->SetAngularVelocity(vector3::Zero);

				if (LVelIsAlmostZero)
					pMasterBody->SetLinearVelocity(vector3::Zero);

				if (AVelIsAlmostZero && LVelIsAlmostZero) SetEnabled(false);
			}
		}
		//???!!!else (when falling) apply damping?!
	}
	// NOTE: do NOT call the parent class, we don't need any damping
}