Jelajahi Sumber

Created ESupportMode::Default (#944)

This mode will switch between IncludeConvexRadius/ExcludeConvexRadius depending on which representation is the most efficient/accurate for a particular shape and is used by CastShape to get better performance and a better quality normal.

Fixes #935
Jorrit Rouwe 1 tahun lalu
induk
melakukan
0f67cc2915

+ 1 - 1
Jolt/Physics/Collision/CastConvexVsTriangles.cpp

@@ -51,7 +51,7 @@ void CastConvexVsTriangles::Cast(Vec3Arg inV0, Vec3Arg inV1, Vec3Arg inV2, uint8
 	if (mSupport == nullptr)
 	{
 		// Determine if we want to use the actual shape or a shrunken shape with convex radius
-		ConvexShape::ESupportMode support_mode = mShapeCastSettings.mUseShrunkenShapeAndConvexRadius? ConvexShape::ESupportMode::ExcludeConvexRadius : ConvexShape::ESupportMode::IncludeConvexRadius;
+		ConvexShape::ESupportMode support_mode = mShapeCastSettings.mUseShrunkenShapeAndConvexRadius? ConvexShape::ESupportMode::ExcludeConvexRadius : ConvexShape::ESupportMode::Default;
 
 		// Create support function
 		mSupport = static_cast<const ConvexShape *>(mShapeCast.mShape)->GetSupportFunction(support_mode, mSupportBuffer, mShapeCast.mScale);

+ 1 - 0
Jolt/Physics/Collision/Shape/BoxShape.cpp

@@ -103,6 +103,7 @@ const ConvexShape::Support *BoxShape::GetSupportFunction(ESupportMode inMode, Su
 	switch (inMode)
 	{
 	case ESupportMode::IncludeConvexRadius:
+	case ESupportMode::Default:
 		{
 			// Make box out of our half extents
 			AABox box = AABox(-scaled_half_extent, scaled_half_extent);

+ 1 - 0
Jolt/Physics/Collision/Shape/CapsuleShape.cpp

@@ -165,6 +165,7 @@ const ConvexShape::Support *CapsuleShape::GetSupportFunction(ESupportMode inMode
 		return new (&inBuffer) CapsuleWithConvex(scaled_half_height_of_cylinder, scaled_radius);
 
 	case ESupportMode::ExcludeConvexRadius:
+	case ESupportMode::Default:
 		return new (&inBuffer) CapsuleNoConvex(scaled_half_height_of_cylinder, scaled_radius);
 	}
 

+ 1 - 0
Jolt/Physics/Collision/Shape/ConvexHullShape.cpp

@@ -542,6 +542,7 @@ const ConvexShape::Support *ConvexHullShape::GetSupportFunction(ESupportMode inM
 	switch (inMode)
 	{
 	case ESupportMode::IncludeConvexRadius:
+	case ESupportMode::Default:
 		if (ScaleHelpers::IsNotScaled(inScale))
 			return new (&inBuffer) HullWithConvex(this);
 		else

+ 1 - 1
Jolt/Physics/Collision/Shape/ConvexShape.cpp

@@ -259,7 +259,7 @@ void ConvexShape::sCastConvexVsConvex(const ShapeCast &inShapeCast, const ShapeC
 	const ConvexShape *shape = static_cast<const ConvexShape *>(inShape);
 
 	// Determine if we want to use the actual shape or a shrunken shape with convex radius
-	ConvexShape::ESupportMode support_mode = inShapeCastSettings.mUseShrunkenShapeAndConvexRadius? ConvexShape::ESupportMode::ExcludeConvexRadius : ConvexShape::ESupportMode::IncludeConvexRadius;
+	ConvexShape::ESupportMode support_mode = inShapeCastSettings.mUseShrunkenShapeAndConvexRadius? ConvexShape::ESupportMode::ExcludeConvexRadius : ConvexShape::ESupportMode::Default;
 
 	// Create support function for shape to cast
 	SupportBuffer cast_buffer;

+ 3 - 2
Jolt/Physics/Collision/Shape/ConvexShape.h

@@ -90,8 +90,9 @@ public:
 	/// How the GetSupport function should behave
 	enum class ESupportMode
 	{
-		ExcludeConvexRadius,		///< Return the shape excluding the convex radius
-		IncludeConvexRadius,		///< Return the shape including the convex radius
+		ExcludeConvexRadius,		///< Return the shape excluding the convex radius, Support::GetConvexRadius will return the convex radius if there is one, but adding this radius may not result in the most accurate/efficient representation of shapes with sharp edges
+		IncludeConvexRadius,		///< Return the shape including the convex radius, Support::GetSupport includes the convex radius if there is one, Support::GetConvexRadius will return 0
+		Default,					///< Use both Support::GetSupport add Support::GetConvexRadius to get a support point that matches the original shape as accurately/efficiently as possible
 	};
 
 	/// Returns an object that provides the GetSupport function for this shape.

+ 1 - 0
Jolt/Physics/Collision/Shape/CylinderShape.cpp

@@ -177,6 +177,7 @@ const ConvexShape::Support *CylinderShape::GetSupportFunction(ESupportMode inMod
 	switch (inMode)
 	{
 	case ESupportMode::IncludeConvexRadius:
+	case ESupportMode::Default:
 		return new (&inBuffer) Cylinder(scaled_half_height, scaled_radius, 0.0f);
 
 	case ESupportMode::ExcludeConvexRadius:

+ 1 - 0
Jolt/Physics/Collision/Shape/SphereShape.cpp

@@ -132,6 +132,7 @@ const ConvexShape::Support *SphereShape::GetSupportFunction(ESupportMode inMode,
 		return new (&inBuffer) SphereWithConvex(scaled_radius);
 
 	case ESupportMode::ExcludeConvexRadius:
+	case ESupportMode::Default:
 		return new (&inBuffer) SphereNoConvex(scaled_radius);
 	}
 

+ 1 - 0
Jolt/Physics/Collision/Shape/TaperedCapsuleShape.cpp

@@ -196,6 +196,7 @@ const ConvexShape::Support *TaperedCapsuleShape::GetSupportFunction(ESupportMode
 		return new (&inBuffer) TaperedCapsule(scaled_top_center, scaled_bottom_center, scaled_top_radius, scaled_bottom_radius, 0.0f);
 
 	case ESupportMode::ExcludeConvexRadius:
+	case ESupportMode::Default:
 		{
 			// Get radii reduced by convex radius
 			float tr = scaled_top_radius - scaled_convex_radius;

+ 1 - 0
Jolt/Physics/Collision/Shape/TriangleShape.cpp

@@ -146,6 +146,7 @@ const ConvexShape::Support *TriangleShape::GetSupportFunction(ESupportMode inMod
 	switch (inMode)
 	{
 	case ESupportMode::IncludeConvexRadius:
+	case ESupportMode::Default:
 		if (mConvexRadius > 0.0f)
 			return new (&inBuffer) TriangleWithConvex(inScale * mV1, inScale * mV2, inScale * mV3, mConvexRadius);
 		[[fallthrough]];

+ 2 - 2
UnitTests/Physics/CastShapeTests.cpp

@@ -267,8 +267,8 @@ TEST_SUITE("CastShapeTests")
 			CHECK_APPROX_EQUAL(result.mFraction, 0.0f);
 			CHECK(result.mPenetrationAxis.Normalized().Dot(Vec3(1, 0, 0)) > Cos(DegreesToRadians(1.0f)));
 			CHECK_APPROX_EQUAL(result.mPenetrationDepth, 1.05f);
-			CHECK_APPROX_EQUAL(result.mContactPointOn1, Vec3(2.05f, 0, 0), 1.0e-5f); // Box starts at 1.0, center of sphere adds 0.05, radius of sphere is 1
-			CHECK_APPROX_EQUAL(result.mContactPointOn2, Vec3(1.0f, 0, 0), 1.0e-5f); // Box starts at 1.0
+			CHECK_APPROX_EQUAL(result.mContactPointOn1, Vec3(2.05f, 0, 0), 2.0e-5f); // Box starts at 1.0, center of sphere adds 0.05, radius of sphere is 1
+			CHECK_APPROX_EQUAL(result.mContactPointOn2, Vec3(1.0f, 0, 0), 2.0e-5f); // Box starts at 1.0
 			CHECK(!result.mIsBackFaceHit);
 		}
 	}