Browse Source

Ability to configure back face culling behavior (#425)

Should help to resolve #363
Jorrit Rouwe 2 years ago
parent
commit
2a989c4d81

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

@@ -20,6 +20,7 @@ JPH_NAMESPACE_BEGIN
 
 
 CharacterVirtual::CharacterVirtual(const CharacterVirtualSettings *inSettings, RVec3Arg inPosition, QuatArg inRotation, PhysicsSystem *inSystem) :
 CharacterVirtual::CharacterVirtual(const CharacterVirtualSettings *inSettings, RVec3Arg inPosition, QuatArg inRotation, PhysicsSystem *inSystem) :
 	CharacterBase(inSettings, inSystem),
 	CharacterBase(inSettings, inSystem),
+	mBackFaceMode(inSettings->mBackFaceMode),
 	mPredictiveContactDistance(inSettings->mPredictiveContactDistance),
 	mPredictiveContactDistance(inSettings->mPredictiveContactDistance),
 	mMaxCollisionIterations(inSettings->mMaxCollisionIterations),
 	mMaxCollisionIterations(inSettings->mMaxCollisionIterations),
 	mMaxConstraintIterations(inSettings->mMaxConstraintIterations),
 	mMaxConstraintIterations(inSettings->mMaxConstraintIterations),
@@ -193,7 +194,7 @@ void CharacterVirtual::CheckCollision(RVec3Arg inPosition, QuatArg inRotation, V
 	// Settings for collide shape
 	// Settings for collide shape
 	CollideShapeSettings settings;
 	CollideShapeSettings settings;
 	settings.mActiveEdgeMode = EActiveEdgeMode::CollideOnlyWithActive;
 	settings.mActiveEdgeMode = EActiveEdgeMode::CollideOnlyWithActive;
-	settings.mBackFaceMode = EBackFaceMode::CollideWithBackFaces;
+	settings.mBackFaceMode = mBackFaceMode;
 	settings.mActiveEdgeMovementDirection = inMovementDirection;
 	settings.mActiveEdgeMovementDirection = inMovementDirection;
 	settings.mMaxSeparationDistance = mCharacterPadding + inMaxSeparationDistance;
 	settings.mMaxSeparationDistance = mCharacterPadding + inMaxSeparationDistance;
 
 
@@ -304,7 +305,7 @@ bool CharacterVirtual::GetFirstContactForSweep(RVec3Arg inPosition, Vec3Arg inDi
 
 
 	// Settings for the cast
 	// Settings for the cast
 	ShapeCastSettings settings;
 	ShapeCastSettings settings;
-	settings.mBackFaceModeTriangles = EBackFaceMode::CollideWithBackFaces;
+	settings.mBackFaceModeTriangles = mBackFaceMode;
 	settings.mBackFaceModeConvex = EBackFaceMode::IgnoreBackFaces;
 	settings.mBackFaceModeConvex = EBackFaceMode::IgnoreBackFaces;
 	settings.mActiveEdgeMode = EActiveEdgeMode::CollideOnlyWithActive;
 	settings.mActiveEdgeMode = EActiveEdgeMode::CollideOnlyWithActive;
 	settings.mUseShrunkenShapeAndConvexRadius = true;
 	settings.mUseShrunkenShapeAndConvexRadius = true;

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

@@ -30,7 +30,8 @@ public:
 	Vec3								mShapeOffset = Vec3::sZero();
 	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
+	EBackFaceMode						mBackFaceMode = EBackFaceMode::CollideWithBackFaces;	///< When colliding with back faces, the character will not be able to move through back facing triangles. Use this if you have triangles that need to collide on both sides.
+	float								mPredictiveContactDistance = 0.1f;						///< How far to scan outside of the shape for predictive contacts. A value of 0 will most likely cause the character to get stuck as it properly calculate a sliding direction anymore. A value that's too high will cause ghost collisions.
 	uint								mMaxCollisionIterations = 5;							///< Max amount of collision loops
 	uint								mMaxCollisionIterations = 5;							///< Max amount of collision loops
 	uint								mMaxConstraintIterations = 15;							///< How often to try stepping in the constraint solving
 	uint								mMaxConstraintIterations = 15;							///< How often to try stepping in the constraint solving
 	float								mMinTimeRemaining = 1.0e-4f;							///< Early out condition: If this much time is left to simulate we are done
 	float								mMinTimeRemaining = 1.0e-4f;							///< Early out condition: If this much time is left to simulate we are done
@@ -424,7 +425,8 @@ private:
 	CharacterContactListener *			mListener = nullptr;
 	CharacterContactListener *			mListener = nullptr;
 
 
 	// Movement settings
 	// Movement settings
-	float								mPredictiveContactDistance;								// How far to scan outside of the shape for predictive contacts
+	EBackFaceMode						mBackFaceMode;											// When colliding with back faces, the character will not be able to move through back facing triangles. Use this if you have triangles that need to collide on both sides.
+	float								mPredictiveContactDistance;								// How far to scan outside of the shape for predictive contacts. A value of 0 will most likely cause the character to get stuck as it properly calculate a sliding direction anymore. A value that's too high will cause ghost collisions.
 	uint								mMaxCollisionIterations;								// Max amount of collision loops
 	uint								mMaxCollisionIterations;								// Max amount of collision loops
 	uint								mMaxConstraintIterations;								// How often to try stepping in the constraint solving
 	uint								mMaxConstraintIterations;								// How often to try stepping in the constraint solving
 	float								mMinTimeRemaining;										// Early out condition: If this much time is left to simulate we are done
 	float								mMinTimeRemaining;										// Early out condition: If this much time is left to simulate we are done

+ 2 - 0
Samples/Tests/Character/CharacterVirtualTest.cpp

@@ -24,6 +24,7 @@ void CharacterVirtualTest::Initialize()
 	settings->mMaxSlopeAngle = sMaxSlopeAngle;
 	settings->mMaxSlopeAngle = sMaxSlopeAngle;
 	settings->mMaxStrength = sMaxStrength;
 	settings->mMaxStrength = sMaxStrength;
 	settings->mShape = mStandingShape;
 	settings->mShape = mStandingShape;
+	settings->mBackFaceMode = sBackFaceMode;
 	settings->mCharacterPadding = sCharacterPadding;
 	settings->mCharacterPadding = sCharacterPadding;
 	settings->mPenetrationRecoverySpeed = sPenetrationRecoverySpeed;
 	settings->mPenetrationRecoverySpeed = sPenetrationRecoverySpeed;
 	settings->mPredictiveContactDistance = sPredictiveContactDistance;
 	settings->mPredictiveContactDistance = sPredictiveContactDistance;
@@ -151,6 +152,7 @@ void CharacterVirtualTest::HandleInput(Vec3Arg inMovementDirection, bool inJump,
 
 
 void CharacterVirtualTest::AddConfigurationSettings(DebugUI *inUI, UIElement *inSubMenu)
 void CharacterVirtualTest::AddConfigurationSettings(DebugUI *inUI, UIElement *inSubMenu)
 {
 {
+	inUI->CreateComboBox(inSubMenu, "Back Face Mode", { "Ignore", "Collide" }, (int)sBackFaceMode, [=](int inItem) { sBackFaceMode = (EBackFaceMode)inItem; });
 	inUI->CreateSlider(inSubMenu, "Up Rotation X (degrees)", RadiansToDegrees(sUpRotationX), -90.0f, 90.0f, 1.0f, [](float inValue) { sUpRotationX = DegreesToRadians(inValue); });
 	inUI->CreateSlider(inSubMenu, "Up Rotation X (degrees)", RadiansToDegrees(sUpRotationX), -90.0f, 90.0f, 1.0f, [](float inValue) { sUpRotationX = DegreesToRadians(inValue); });
 	inUI->CreateSlider(inSubMenu, "Up Rotation Z (degrees)", RadiansToDegrees(sUpRotationZ), -90.0f, 90.0f, 1.0f, [](float inValue) { sUpRotationZ = DegreesToRadians(inValue); });
 	inUI->CreateSlider(inSubMenu, "Up Rotation Z (degrees)", RadiansToDegrees(sUpRotationZ), -90.0f, 90.0f, 1.0f, [](float inValue) { sUpRotationZ = DegreesToRadians(inValue); });
 	inUI->CreateSlider(inSubMenu, "Max Slope Angle (degrees)", RadiansToDegrees(sMaxSlopeAngle), 0.0f, 90.0f, 1.0f, [](float inValue) { sMaxSlopeAngle = DegreesToRadians(inValue); });
 	inUI->CreateSlider(inSubMenu, "Max Slope Angle (degrees)", RadiansToDegrees(sMaxSlopeAngle), 0.0f, 90.0f, 1.0f, [](float inValue) { sMaxSlopeAngle = DegreesToRadians(inValue); });

+ 1 - 0
Samples/Tests/Character/CharacterVirtualTest.h

@@ -43,6 +43,7 @@ protected:
 
 
 private:
 private:
 	// Test settings
 	// Test settings
+	static inline EBackFaceMode sBackFaceMode = EBackFaceMode::CollideWithBackFaces;
 	static inline float		sUpRotationX = 0;
 	static inline float		sUpRotationX = 0;
 	static inline float		sUpRotationZ = 0;	
 	static inline float		sUpRotationZ = 0;	
 	static inline float		sMaxSlopeAngle = DegreesToRadians(45.0f);
 	static inline float		sMaxSlopeAngle = DegreesToRadians(45.0f);