Browse Source

Improved CharacterVirtual interface (#353)

- Made constraints public
- Listener does not need to register operator new as you need to inherit from it
- Added 'shape offset' a local space offset applied to the shape
- Added extra getters/setters
Jorrit Rouwe 2 years ago
parent
commit
d874365e85

+ 11 - 3
Jolt/Physics/Character/CharacterVirtual.cpp

@@ -28,6 +28,7 @@ CharacterVirtual::CharacterVirtual(const CharacterVirtualSettings *inSettings, R
 	mCharacterPadding(inSettings->mCharacterPadding),
 	mCharacterPadding(inSettings->mCharacterPadding),
 	mMaxNumHits(inSettings->mMaxNumHits),
 	mMaxNumHits(inSettings->mMaxNumHits),
 	mPenetrationRecoverySpeed(inSettings->mPenetrationRecoverySpeed),
 	mPenetrationRecoverySpeed(inSettings->mPenetrationRecoverySpeed),
+	mShapeOffset(inSettings->mShapeOffset),
 	mPosition(inPosition),
 	mPosition(inPosition),
 	mRotation(inRotation)
 	mRotation(inRotation)
 {
 {
@@ -623,9 +624,16 @@ void CharacterVirtual::UpdateSupportingContact(bool inSkipContactVelocityCheck,
 	// Flag contacts as having a collision if they're close enough but ignore contacts we're moving away from.
 	// Flag contacts as having a collision if they're close enough but ignore contacts we're moving away from.
 	// Note that if we did MoveShape before we want to preserve any contacts that it marked as colliding
 	// Note that if we did MoveShape before we want to preserve any contacts that it marked as colliding
 	for (Contact &c : mActiveContacts)
 	for (Contact &c : mActiveContacts)
-		if (!c.mWasDiscarded)
-			c.mHadCollision |= c.mDistance < mCollisionTolerance
-								&& (inSkipContactVelocityCheck || c.mSurfaceNormal.Dot(mLinearVelocity - c.mLinearVelocity) <= 0.0f);
+		if (!c.mWasDiscarded
+			&& !c.mHadCollision
+			&& c.mDistance < mCollisionTolerance
+			&& (inSkipContactVelocityCheck || c.mSurfaceNormal.Dot(mLinearVelocity - c.mLinearVelocity) <= 0.0f))
+		{
+			if (ValidateContact(c))
+				c.mHadCollision = true;
+			else
+				c.mWasDiscarded = true;
+		}
 
 
 	// Calculate transform that takes us to character local space
 	// Calculate transform that takes us to character local space
 	RMat44 inv_transform = RMat44::sInverseRotationTranslation(mRotation, mPosition);
 	RMat44 inv_transform = RMat44::sInverseRotationTranslation(mRotation, mPosition);

+ 25 - 4
Jolt/Physics/Character/CharacterVirtual.h

@@ -26,6 +26,9 @@ public:
 	/// Maximum force with which the character can push other bodies (N).
 	/// Maximum force with which the character can push other bodies (N).
 	float								mMaxStrength = 100.0f;
 	float								mMaxStrength = 100.0f;
 
 
+	/// An extra offset applied to the shape in local space. This allows applying an extra offset to the shape in local space.
+	Vec3								mShapeOffset = Vec3::sZero();
+
 	///@name Movement settings
 	///@name Movement settings
 	float								mPredictiveContactDistance = 0.1f;						///< How far to scan outside of the shape for predictive contacts
 	float								mPredictiveContactDistance = 0.1f;						///< How far to scan outside of the shape for predictive contacts
 	uint								mMaxCollisionIterations = 5;							///< Max amount of collision loops
 	uint								mMaxCollisionIterations = 5;							///< Max amount of collision loops
@@ -49,8 +52,6 @@ public:
 class CharacterContactListener
 class CharacterContactListener
 {
 {
 public:
 public:
-	JPH_OVERRIDE_NEW_DELETE
-
 	/// Destructor
 	/// Destructor
 	virtual								~CharacterContactListener() = default;
 	virtual								~CharacterContactListener() = default;
 
 
@@ -121,14 +122,28 @@ public:
 	RMat44								GetCenterOfMassTransform() const						{ return GetCenterOfMassTransform(mPosition, mRotation, mShape); }
 	RMat44								GetCenterOfMassTransform() const						{ return GetCenterOfMassTransform(mPosition, mRotation, mShape); }
 
 
 	/// Character mass (kg)
 	/// Character mass (kg)
+	float								GetMass() const											{ return mMass; }
 	void								SetMass(float inMass)									{ mMass = inMass; }
 	void								SetMass(float inMass)									{ mMass = inMass; }
 
 
 	/// Maximum force with which the character can push other bodies (N)
 	/// Maximum force with which the character can push other bodies (N)
+	float								GetMaxStrength() const									{ return mMaxStrength; }
 	void								SetMaxStrength(float inMaxStrength)						{ mMaxStrength = inMaxStrength; }
 	void								SetMaxStrength(float inMaxStrength)						{ mMaxStrength = inMaxStrength; }
 
 
+	/// This value governs how fast a penetration will be resolved, 0 = nothing is resolved, 1 = everything in one update
+	float								GetPenetrationRecoverySpeed() const						{ return mPenetrationRecoverySpeed; }
+	void								SetPenetrationRecoverySpeed(float inSpeed)				{ mPenetrationRecoverySpeed = inSpeed; }
+
 	/// Character padding
 	/// Character padding
 	float								GetCharacterPadding() const								{ return mCharacterPadding; }
 	float								GetCharacterPadding() const								{ return mCharacterPadding; }
 
 
+	/// Max num hits to collect in order to avoid excess of contact points collection
+	uint								GetMaxNumHits() const									{ return mMaxNumHits; }
+	void								SetMaxNumHits(uint inMaxHits)							{ mMaxNumHits = inMaxHits; }
+
+	/// An extra offset applied to the shape in local space. This allows applying an extra offset to the shape in local space. Note that setting it on the fly can cause the shape to teleport into collision.
+	Vec3								GetShapeOffset() const									{ return mShapeOffset; }
+	void								SetShapeOffset(Vec3Arg inShapeOffset)					{ mShapeOffset = inShapeOffset; }
+
 	/// This function can be called prior to calling Update() to convert a desired velocity into a velocity that won't make the character move further onto steep slopes.
 	/// This function can be called prior to calling Update() to convert a desired velocity into a velocity that won't make the character move further onto steep slopes.
 	/// This velocity can then be set on the character using SetLinearVelocity()
 	/// This velocity can then be set on the character using SetLinearVelocity()
 	/// @param inDesiredVelocity Velocity to clamp against steep walls
 	/// @param inDesiredVelocity Velocity to clamp against steep walls
@@ -235,7 +250,6 @@ public:
 	static inline bool					sDrawStickToFloor = false;								///< Draw the state of the stick to floor algorithm
 	static inline bool					sDrawStickToFloor = false;								///< Draw the state of the stick to floor algorithm
 #endif
 #endif
 
 
-private:
 	// Encapsulates a collision contact
 	// Encapsulates a collision contact
 	struct Contact
 	struct Contact
 	{
 	{
@@ -258,6 +272,10 @@ private:
 	using TempContactList = std::vector<Contact, STLTempAllocator<Contact>>;
 	using TempContactList = std::vector<Contact, STLTempAllocator<Contact>>;
 	using ContactList = Array<Contact>;
 	using ContactList = Array<Contact>;
 
 
+	/// Access to the internal list of contacts that the character has found.
+	const ContactList &					GetActiveContacts() const								{ return mActiveContacts; }
+
+private:
 	// A contact that needs to be ignored
 	// A contact that needs to be ignored
 	struct IgnoredContact
 	struct IgnoredContact
 	{
 	{
@@ -362,7 +380,7 @@ private:
 	// This function returns the actual center of mass of the shape, not corrected for the character padding
 	// This function returns the actual center of mass of the shape, not corrected for the character padding
 	inline RMat44						GetCenterOfMassTransform(RVec3Arg inPosition, QuatArg inRotation, const Shape *inShape) const
 	inline RMat44						GetCenterOfMassTransform(RVec3Arg inPosition, QuatArg inRotation, const Shape *inShape) const
 	{
 	{
-		return RMat44::sRotationTranslation(inRotation, inPosition).PreTranslated(inShape->GetCenterOfMass()).PostTranslated(mCharacterPadding * mUp);
+		return RMat44::sRotationTranslation(inRotation, inPosition).PreTranslated(mShapeOffset + inShape->GetCenterOfMass()).PostTranslated(mCharacterPadding * mUp);
 	}
 	}
 
 
 	// Our main listener for contacts
 	// Our main listener for contacts
@@ -384,6 +402,9 @@ private:
 	// Maximum force with which the character can push other bodies (N)
 	// Maximum force with which the character can push other bodies (N)
 	float								mMaxStrength;
 	float								mMaxStrength;
 
 
+	// An extra offset applied to the shape in local space. This allows applying an extra offset to the shape in local space.
+	Vec3								mShapeOffset = Vec3::sZero();
+
 	// Current position (of the base, not the center of mass)
 	// Current position (of the base, not the center of mass)
 	RVec3								mPosition = RVec3::sZero();
 	RVec3								mPosition = RVec3::sZero();