瀏覽代碼

Added SoftBodyCreationSettings::mFacesDoubleSided (#1657)

This treats the faces of the soft body as double sided. This can be used to make e.g. flags double sided.

See #1656
Jorrit Rouwe 1 月之前
父節點
當前提交
3ad037b926

+ 1 - 0
Docs/ReleaseNotes.md

@@ -9,6 +9,7 @@ For breaking API changes see [this document](https://github.com/jrouwe/JoltPhysi
 * Added Cosserat rods to soft bodies. This is a stick constraint with an orientation that can be used to attach geometry. Can be used e.g. to simulate vegetation in a cheap way. See the new `SoftBodyCosseratRodConstraintTest` demo.
 * Added Cosserat rods to soft bodies. This is a stick constraint with an orientation that can be used to attach geometry. Can be used e.g. to simulate vegetation in a cheap way. See the new `SoftBodyCosseratRodConstraintTest` demo.
 * Added ability to drive hinge constraints with `Ragdoll::DriveToPoseUsingMotors`. This also adds `HingeConstraint::SetTargetOrientationBS` which sets the target angle in body space.
 * Added ability to drive hinge constraints with `Ragdoll::DriveToPoseUsingMotors`. This also adds `HingeConstraint::SetTargetOrientationBS` which sets the target angle in body space.
 * Added `JPH_USE_EXTERNAL_PROFILE` cmake option that allows overriding the behavior of the profile macros.
 * Added `JPH_USE_EXTERNAL_PROFILE` cmake option that allows overriding the behavior of the profile macros.
+* Added `SoftBodyCreationSettings::mFacesDoubleSided` which treats the faces of the soft body as double sided. This can be used to make e.g. flags double sided.
 
 
 ### Bug Fixes
 ### Bug Fixes
 
 

+ 2 - 0
Jolt/Physics/Body/Body.cpp

@@ -416,6 +416,8 @@ SoftBodyCreationSettings Body::GetSoftBodyCreationSettings() const
 	result.mPressure = mp->GetPressure();
 	result.mPressure = mp->GetPressure();
 	result.mUpdatePosition = mp->GetUpdatePosition();
 	result.mUpdatePosition = mp->GetUpdatePosition();
 	result.mVertexRadius = mp->GetVertexRadius();
 	result.mVertexRadius = mp->GetVertexRadius();
+	result.mAllowSleeping = mp->GetAllowSleeping();
+	result.mFacesDoubleSided = mp->GetFacesDoubleSided();
 	result.mSettings = mp->GetSettings();
 	result.mSettings = mp->GetSettings();
 
 
 	return result;
 	return result;

+ 3 - 0
Jolt/Physics/SoftBody/SoftBodyCreationSettings.cpp

@@ -30,6 +30,7 @@ JPH_IMPLEMENT_SERIALIZABLE_NON_VIRTUAL(SoftBodyCreationSettings)
 	JPH_ADD_ATTRIBUTE(SoftBodyCreationSettings, mUpdatePosition)
 	JPH_ADD_ATTRIBUTE(SoftBodyCreationSettings, mUpdatePosition)
 	JPH_ADD_ATTRIBUTE(SoftBodyCreationSettings, mMakeRotationIdentity)
 	JPH_ADD_ATTRIBUTE(SoftBodyCreationSettings, mMakeRotationIdentity)
 	JPH_ADD_ATTRIBUTE(SoftBodyCreationSettings, mAllowSleeping)
 	JPH_ADD_ATTRIBUTE(SoftBodyCreationSettings, mAllowSleeping)
+	JPH_ADD_ATTRIBUTE(SoftBodyCreationSettings, mFacesDoubleSided)
 }
 }
 
 
 void SoftBodyCreationSettings::SaveBinaryState(StreamOut &inStream) const
 void SoftBodyCreationSettings::SaveBinaryState(StreamOut &inStream) const
@@ -50,6 +51,7 @@ void SoftBodyCreationSettings::SaveBinaryState(StreamOut &inStream) const
 	inStream.Write(mUpdatePosition);
 	inStream.Write(mUpdatePosition);
 	inStream.Write(mMakeRotationIdentity);
 	inStream.Write(mMakeRotationIdentity);
 	inStream.Write(mAllowSleeping);
 	inStream.Write(mAllowSleeping);
+	inStream.Write(mFacesDoubleSided);
 }
 }
 
 
 void SoftBodyCreationSettings::RestoreBinaryState(StreamIn &inStream)
 void SoftBodyCreationSettings::RestoreBinaryState(StreamIn &inStream)
@@ -70,6 +72,7 @@ void SoftBodyCreationSettings::RestoreBinaryState(StreamIn &inStream)
 	inStream.Read(mUpdatePosition);
 	inStream.Read(mUpdatePosition);
 	inStream.Read(mMakeRotationIdentity);
 	inStream.Read(mMakeRotationIdentity);
 	inStream.Read(mAllowSleeping);
 	inStream.Read(mAllowSleeping);
+	inStream.Read(mFacesDoubleSided);
 }
 }
 
 
 void SoftBodyCreationSettings::SaveWithChildren(StreamOut &inStream, SharedSettingsToIDMap *ioSharedSettingsMap, MaterialToIDMap *ioMaterialMap, GroupFilterToIDMap *ioGroupFilterMap) const
 void SoftBodyCreationSettings::SaveWithChildren(StreamOut &inStream, SharedSettingsToIDMap *ioSharedSettingsMap, MaterialToIDMap *ioMaterialMap, GroupFilterToIDMap *ioGroupFilterMap) const

+ 1 - 0
Jolt/Physics/SoftBody/SoftBodyCreationSettings.h

@@ -69,6 +69,7 @@ public:
 	bool				mUpdatePosition = true;				///< Update the position of the body while simulating (set to false for something that is attached to the static world)
 	bool				mUpdatePosition = true;				///< Update the position of the body while simulating (set to false for something that is attached to the static world)
 	bool				mMakeRotationIdentity = true;		///< Bake specified mRotation in the vertices and set the body rotation to identity (simulation is slightly more accurate if the rotation of a soft body is kept to identity)
 	bool				mMakeRotationIdentity = true;		///< Bake specified mRotation in the vertices and set the body rotation to identity (simulation is slightly more accurate if the rotation of a soft body is kept to identity)
 	bool				mAllowSleeping = true;				///< If this body can go to sleep or not
 	bool				mAllowSleeping = true;				///< If this body can go to sleep or not
+	bool				mFacesDoubleSided = false;			///< If the faces in this soft body should be treated as double sided for the purpose of collision detection (ray cast / collide shape / cast shape)
 };
 };
 
 
 JPH_NAMESPACE_END
 JPH_NAMESPACE_END

+ 1 - 0
Jolt/Physics/SoftBody/SoftBodyMotionProperties.cpp

@@ -63,6 +63,7 @@ void SoftBodyMotionProperties::Initialize(const SoftBodyCreationSettings &inSett
 	mNumIterations = inSettings.mNumIterations;
 	mNumIterations = inSettings.mNumIterations;
 	mPressure = inSettings.mPressure;
 	mPressure = inSettings.mPressure;
 	mUpdatePosition = inSettings.mUpdatePosition;
 	mUpdatePosition = inSettings.mUpdatePosition;
+	mFacesDoubleSided = inSettings.mFacesDoubleSided;
 	SetVertexRadius(inSettings.mVertexRadius);
 	SetVertexRadius(inSettings.mVertexRadius);
 
 
 	// Initialize vertices
 	// Initialize vertices

+ 5 - 0
Jolt/Physics/SoftBody/SoftBodyMotionProperties.h

@@ -85,6 +85,10 @@ public:
 	bool								GetUpdatePosition() const					{ return mUpdatePosition; }
 	bool								GetUpdatePosition() const					{ return mUpdatePosition; }
 	void								SetUpdatePosition(bool inUpdatePosition)	{ mUpdatePosition = inUpdatePosition; }
 	void								SetUpdatePosition(bool inUpdatePosition)	{ mUpdatePosition = inUpdatePosition; }
 
 
+	/// If the faces in this soft body should be treated as double sided for the purpose of collision detection (ray cast / collide shape / cast shape)
+	bool								GetFacesDoubleSided() const					{ return mFacesDoubleSided; }
+	void								SetFacesDoubleSided(bool inDoubleSided)		{ mFacesDoubleSided = inDoubleSided; }
+
 	/// Global setting to turn on/off skin constraints
 	/// Global setting to turn on/off skin constraints
 	bool								GetEnableSkinConstraints() const			{ return mEnableSkinConstraints; }
 	bool								GetEnableSkinConstraints() const			{ return mEnableSkinConstraints; }
 	void								SetEnableSkinConstraints(bool inEnableSkinConstraints) { mEnableSkinConstraints = inEnableSkinConstraints; }
 	void								SetEnableSkinConstraints(bool inEnableSkinConstraints) { mEnableSkinConstraints = inEnableSkinConstraints; }
@@ -320,6 +324,7 @@ private:
 	float								mSkinnedMaxDistanceMultiplier = 1.0f;		///< Multiplier applied to Skinned::mMaxDistance to allow tightening or loosening of the skin constraints
 	float								mSkinnedMaxDistanceMultiplier = 1.0f;		///< Multiplier applied to Skinned::mMaxDistance to allow tightening or loosening of the skin constraints
 	float								mVertexRadius = 0.0f;						///< How big the particles are, can be used to push the vertices a little bit away from the surface of other bodies to prevent z-fighting
 	float								mVertexRadius = 0.0f;						///< How big the particles are, can be used to push the vertices a little bit away from the surface of other bodies to prevent z-fighting
 	bool								mUpdatePosition;							///< Update the position of the body while simulating (set to false for something that is attached to the static world)
 	bool								mUpdatePosition;							///< Update the position of the body while simulating (set to false for something that is attached to the static world)
+	bool								mFacesDoubleSided;							///< If the faces in this soft body should be treated as double sided for the purpose of collision detection (ray cast / collide shape / cast shape)
 	atomic<bool>						mNeedContactCallback = false;				///< True if the soft body has collided with anything in the last update
 	atomic<bool>						mNeedContactCallback = false;				///< True if the soft body has collided with anything in the last update
 	bool								mEnableSkinConstraints = true;				///< If skin constraints are enabled
 	bool								mEnableSkinConstraints = true;				///< If skin constraints are enabled
 	bool								mSkinStatePreviousPositionValid = false;	///< True if the skinning was updated in the last update so that the previous position of the skin state is valid
 	bool								mSkinStatePreviousPositionValid = false;	///< True if the skinning was updated in the last update so that the previous position of the skin state is valid

+ 18 - 5
Jolt/Physics/SoftBody/SoftBodyShape.cpp

@@ -83,6 +83,7 @@ void SoftBodyShape::CastRay(const RayCast &inRay, const RayCastSettings &inRayCa
 		return;
 		return;
 
 
 	uint num_triangle_bits = GetSubShapeIDBits();
 	uint num_triangle_bits = GetSubShapeIDBits();
+	bool check_backfaces = inRayCastSettings.mBackFaceModeTriangles == EBackFaceMode::IgnoreBackFaces && !mSoftBodyMotionProperties->GetFacesDoubleSided();
 
 
 	const Array<SoftBodyVertex> &vertices = mSoftBodyMotionProperties->GetVertices();
 	const Array<SoftBodyVertex> &vertices = mSoftBodyMotionProperties->GetVertices();
 	for (const SoftBodyMotionProperties::Face &f : mSoftBodyMotionProperties->GetFaces())
 	for (const SoftBodyMotionProperties::Face &f : mSoftBodyMotionProperties->GetFaces())
@@ -92,7 +93,7 @@ void SoftBodyShape::CastRay(const RayCast &inRay, const RayCastSettings &inRayCa
 		Vec3 x3 = vertices[f.mVertex[2]].mPosition;
 		Vec3 x3 = vertices[f.mVertex[2]].mPosition;
 
 
 		// Back facing check
 		// Back facing check
-		if (inRayCastSettings.mBackFaceModeTriangles == EBackFaceMode::IgnoreBackFaces && (x2 - x1).Cross(x3 - x1).Dot(inRay.mDirection) > 0.0f)
+		if (check_backfaces && (x2 - x1).Cross(x3 - x1).Dot(inRay.mDirection) > 0.0f)
 			continue;
 			continue;
 
 
 		// Test ray against triangle
 		// Test ray against triangle
@@ -245,7 +246,10 @@ void SoftBodyShape::sCollideConvexVsSoftBody(const Shape *inShape1, const Shape
 	const Array<SoftBodyMotionProperties::Face> &faces = shape2->mSoftBodyMotionProperties->GetFaces();
 	const Array<SoftBodyMotionProperties::Face> &faces = shape2->mSoftBodyMotionProperties->GetFaces();
 	uint num_triangle_bits = shape2->GetSubShapeIDBits();
 	uint num_triangle_bits = shape2->GetSubShapeIDBits();
 
 
-	CollideConvexVsTriangles collider(shape1, inScale1, inScale2, inCenterOfMassTransform1, inCenterOfMassTransform2, inSubShapeIDCreator1.GetID(), inCollideShapeSettings, ioCollector);
+	CollideShapeSettings settings(inCollideShapeSettings);
+	if (shape2->mSoftBodyMotionProperties->GetFacesDoubleSided())
+		settings.mBackFaceMode = EBackFaceMode::CollideWithBackFaces;
+	CollideConvexVsTriangles collider(shape1, inScale1, inScale2, inCenterOfMassTransform1, inCenterOfMassTransform2, inSubShapeIDCreator1.GetID(), settings, ioCollector);
 	for (const SoftBodyMotionProperties::Face &f : faces)
 	for (const SoftBodyMotionProperties::Face &f : faces)
 	{
 	{
 		Vec3 x1 = vertices[f.mVertex[0]].mPosition;
 		Vec3 x1 = vertices[f.mVertex[0]].mPosition;
@@ -267,7 +271,10 @@ void SoftBodyShape::sCollideSphereVsSoftBody(const Shape *inShape1, const Shape
 	const Array<SoftBodyMotionProperties::Face> &faces = shape2->mSoftBodyMotionProperties->GetFaces();
 	const Array<SoftBodyMotionProperties::Face> &faces = shape2->mSoftBodyMotionProperties->GetFaces();
 	uint num_triangle_bits = shape2->GetSubShapeIDBits();
 	uint num_triangle_bits = shape2->GetSubShapeIDBits();
 
 
-	CollideSphereVsTriangles collider(shape1, inScale1, inScale2, inCenterOfMassTransform1, inCenterOfMassTransform2, inSubShapeIDCreator1.GetID(), inCollideShapeSettings, ioCollector);
+	CollideShapeSettings settings(inCollideShapeSettings);
+	if (shape2->mSoftBodyMotionProperties->GetFacesDoubleSided())
+		settings.mBackFaceMode = EBackFaceMode::CollideWithBackFaces;
+	CollideSphereVsTriangles collider(shape1, inScale1, inScale2, inCenterOfMassTransform1, inCenterOfMassTransform2, inSubShapeIDCreator1.GetID(), settings, ioCollector);
 	for (const SoftBodyMotionProperties::Face &f : faces)
 	for (const SoftBodyMotionProperties::Face &f : faces)
 	{
 	{
 		Vec3 x1 = vertices[f.mVertex[0]].mPosition;
 		Vec3 x1 = vertices[f.mVertex[0]].mPosition;
@@ -287,7 +294,10 @@ void SoftBodyShape::sCastConvexVsSoftBody(const ShapeCast &inShapeCast, const Sh
 	const Array<SoftBodyMotionProperties::Face> &faces = shape->mSoftBodyMotionProperties->GetFaces();
 	const Array<SoftBodyMotionProperties::Face> &faces = shape->mSoftBodyMotionProperties->GetFaces();
 	uint num_triangle_bits = shape->GetSubShapeIDBits();
 	uint num_triangle_bits = shape->GetSubShapeIDBits();
 
 
-	CastConvexVsTriangles caster(inShapeCast, inShapeCastSettings, inScale, inCenterOfMassTransform2, inSubShapeIDCreator1, ioCollector);
+	ShapeCastSettings settings(inShapeCastSettings);
+	if (shape->mSoftBodyMotionProperties->GetFacesDoubleSided())
+		settings.mBackFaceModeTriangles = EBackFaceMode::CollideWithBackFaces;
+	CastConvexVsTriangles caster(inShapeCast, settings, inScale, inCenterOfMassTransform2, inSubShapeIDCreator1, ioCollector);
 	for (const SoftBodyMotionProperties::Face &f : faces)
 	for (const SoftBodyMotionProperties::Face &f : faces)
 	{
 	{
 		Vec3 x1 = vertices[f.mVertex[0]].mPosition;
 		Vec3 x1 = vertices[f.mVertex[0]].mPosition;
@@ -307,7 +317,10 @@ void SoftBodyShape::sCastSphereVsSoftBody(const ShapeCast &inShapeCast, const Sh
 	const Array<SoftBodyMotionProperties::Face> &faces = shape->mSoftBodyMotionProperties->GetFaces();
 	const Array<SoftBodyMotionProperties::Face> &faces = shape->mSoftBodyMotionProperties->GetFaces();
 	uint num_triangle_bits = shape->GetSubShapeIDBits();
 	uint num_triangle_bits = shape->GetSubShapeIDBits();
 
 
-	CastSphereVsTriangles caster(inShapeCast, inShapeCastSettings, inScale, inCenterOfMassTransform2, inSubShapeIDCreator1, ioCollector);
+	ShapeCastSettings settings(inShapeCastSettings);
+	if (shape->mSoftBodyMotionProperties->GetFacesDoubleSided())
+		settings.mBackFaceModeTriangles = EBackFaceMode::CollideWithBackFaces;
+	CastSphereVsTriangles caster(inShapeCast, settings, inScale, inCenterOfMassTransform2, inSubShapeIDCreator1, ioCollector);
 	for (const SoftBodyMotionProperties::Face &f : faces)
 	for (const SoftBodyMotionProperties::Face &f : faces)
 	{
 	{
 		Vec3 x1 = vertices[f.mVertex[0]].mPosition;
 		Vec3 x1 = vertices[f.mVertex[0]].mPosition;