Browse Source

Made GetSupportingFace available for all shape types (#286)

Jorrit Rouwe 2 years ago
parent
commit
5ad6a803bf
35 changed files with 226 additions and 79 deletions
  1. 1 6
      Jolt/Physics/Collision/CastConvexVsTriangles.cpp
  2. 1 5
      Jolt/Physics/Collision/CollideConvexVsTriangles.cpp
  3. 7 1
      Jolt/Physics/Collision/Shape/BoxShape.cpp
  4. 3 3
      Jolt/Physics/Collision/Shape/BoxShape.h
  5. 4 3
      Jolt/Physics/Collision/Shape/CapsuleShape.cpp
  6. 3 3
      Jolt/Physics/Collision/Shape/CapsuleShape.h
  7. 12 0
      Jolt/Physics/Collision/Shape/CompoundShape.cpp
  8. 3 0
      Jolt/Physics/Collision/Shape/CompoundShape.h
  9. 8 3
      Jolt/Physics/Collision/Shape/ConvexHullShape.cpp
  10. 3 3
      Jolt/Physics/Collision/Shape/ConvexHullShape.h
  11. 5 22
      Jolt/Physics/Collision/Shape/ConvexShape.cpp
  12. 0 7
      Jolt/Physics/Collision/Shape/ConvexShape.h
  13. 6 4
      Jolt/Physics/Collision/Shape/CylinderShape.cpp
  14. 3 3
      Jolt/Physics/Collision/Shape/CylinderShape.h
  15. 5 0
      Jolt/Physics/Collision/Shape/DecoratedShape.cpp
  16. 3 0
      Jolt/Physics/Collision/Shape/DecoratedShape.h
  17. 31 0
      Jolt/Physics/Collision/Shape/HeightFieldShape.cpp
  18. 3 0
      Jolt/Physics/Collision/Shape/HeightFieldShape.h
  19. 24 0
      Jolt/Physics/Collision/Shape/MeshShape.cpp
  20. 3 0
      Jolt/Physics/Collision/Shape/MeshShape.h
  21. 5 0
      Jolt/Physics/Collision/Shape/OffsetCenterOfMassShape.cpp
  22. 3 0
      Jolt/Physics/Collision/Shape/OffsetCenterOfMassShape.h
  23. 6 0
      Jolt/Physics/Collision/Shape/RotatedTranslatedShape.cpp
  24. 3 0
      Jolt/Physics/Collision/Shape/RotatedTranslatedShape.h
  25. 5 0
      Jolt/Physics/Collision/Shape/ScaledShape.cpp
  26. 3 0
      Jolt/Physics/Collision/Shape/ScaledShape.h
  27. 12 0
      Jolt/Physics/Collision/Shape/Shape.h
  28. 3 3
      Jolt/Physics/Collision/Shape/SphereShape.h
  29. 4 3
      Jolt/Physics/Collision/Shape/TaperedCapsuleShape.cpp
  30. 3 3
      Jolt/Physics/Collision/Shape/TaperedCapsuleShape.h
  31. 19 4
      Jolt/Physics/Collision/Shape/TriangleShape.cpp
  32. 3 3
      Jolt/Physics/Collision/Shape/TriangleShape.h
  33. 11 0
      Jolt/Physics/Collision/TransformedShape.h
  34. 17 0
      Samples/SamplesApp.cpp
  35. 1 0
      Samples/SamplesApp.h

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

@@ -91,12 +91,7 @@ void CastConvexVsTriangles::Cast(Vec3Arg inV0, Vec3Arg inV1, Vec3Arg inV2, uint8
 			// Get supporting face of shape 1
 			// Get supporting face of shape 1
 			Mat44 transform_1_to_2 = mShapeCast.mCenterOfMassStart;
 			Mat44 transform_1_to_2 = mShapeCast.mCenterOfMassStart;
 			transform_1_to_2.SetTranslation(transform_1_to_2.GetTranslation() + fraction * mShapeCast.mDirection);
 			transform_1_to_2.SetTranslation(transform_1_to_2.GetTranslation() + fraction * mShapeCast.mDirection);
-			static_cast<const ConvexShape *>(mShapeCast.mShape)->GetSupportingFace(transform_1_to_2.Multiply3x3Transposed(-contact_normal), mShapeCast.mScale, result.mShape1Face);
-
-			// Convert to world space
-			Mat44 transform_1_to_world = mCenterOfMassTransform2 * transform_1_to_2;
-			for (Vec3 &p : result.mShape1Face)
-				p = transform_1_to_world * p;
+			static_cast<const ConvexShape *>(mShapeCast.mShape)->GetSupportingFace(SubShapeID(), transform_1_to_2.Multiply3x3Transposed(-contact_normal), mShapeCast.mScale, mCenterOfMassTransform2 * transform_1_to_2, result.mShape1Face);
 
 
 			// Get face of the triangle
 			// Get face of the triangle
 			triangle.GetSupportingFace(contact_normal, result.mShape2Face);
 			triangle.GetSupportingFace(contact_normal, result.mShape2Face);

+ 1 - 5
Jolt/Physics/Collision/CollideConvexVsTriangles.cpp

@@ -132,11 +132,7 @@ void CollideConvexVsTriangles::Collide(Vec3Arg inV0, Vec3Arg inV1, Vec3Arg inV2,
 	if (mCollideShapeSettings.mCollectFacesMode == ECollectFacesMode::CollectFaces)
 	if (mCollideShapeSettings.mCollectFacesMode == ECollectFacesMode::CollectFaces)
 	{
 	{
 		// Get supporting face of shape 1
 		// Get supporting face of shape 1
-		mShape1->GetSupportingFace(-penetration_axis, mScale1, result.mShape1Face);
-
-		// Convert to world space
-		for (Vec3 &p : result.mShape1Face)
-			p = mTransform1 * p;
+		mShape1->GetSupportingFace(SubShapeID(), -penetration_axis, mScale1, mTransform1, result.mShape1Face);
 
 
 		// Get face of the triangle
 		// Get face of the triangle
 		triangle.GetSupportingFace(penetration_axis, result.mShape2Face);
 		triangle.GetSupportingFace(penetration_axis, result.mShape2Face);

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

@@ -124,11 +124,17 @@ const ConvexShape::Support *BoxShape::GetSupportFunction(ESupportMode inMode, Su
 	return nullptr;
 	return nullptr;
 }
 }
 
 
-void BoxShape::GetSupportingFace(Vec3Arg inDirection, Vec3Arg inScale, SupportingFace &outVertices) const 
+void BoxShape::GetSupportingFace(const SubShapeID &inSubShapeID, Vec3Arg inDirection, Vec3Arg inScale, Mat44Arg inCenterOfMassTransform, SupportingFace &outVertices) const 
 { 
 { 
+	JPH_ASSERT(inSubShapeID.IsEmpty(), "Invalid subshape ID");
+
 	Vec3 scaled_half_extent = inScale.Abs() * mHalfExtent;
 	Vec3 scaled_half_extent = inScale.Abs() * mHalfExtent;
 	AABox box(-scaled_half_extent, scaled_half_extent);
 	AABox box(-scaled_half_extent, scaled_half_extent);
 	box.GetSupportingFace(inDirection, outVertices); 
 	box.GetSupportingFace(inDirection, outVertices); 
+
+	// Transform to world space
+	for (Vec3 &v : outVertices)
+		v = inCenterOfMassTransform * v;
 }
 }
 
 
 MassProperties BoxShape::GetMassProperties() const
 MassProperties BoxShape::GetMassProperties() const

+ 3 - 3
Jolt/Physics/Collision/Shape/BoxShape.h

@@ -57,12 +57,12 @@ public:
 	// See Shape::GetSurfaceNormal
 	// See Shape::GetSurfaceNormal
 	virtual Vec3			GetSurfaceNormal(const SubShapeID &inSubShapeID, Vec3Arg inLocalSurfacePosition) const override;
 	virtual Vec3			GetSurfaceNormal(const SubShapeID &inSubShapeID, Vec3Arg inLocalSurfacePosition) const override;
 
 
+	// See Shape::GetSupportingFace
+	virtual void			GetSupportingFace(const SubShapeID &inSubShapeID, Vec3Arg inDirection, Vec3Arg inScale, Mat44Arg inCenterOfMassTransform, SupportingFace &outVertices) const override;
+
 	// See ConvexShape::GetSupportFunction
 	// See ConvexShape::GetSupportFunction
 	virtual const Support *	GetSupportFunction(ESupportMode inMode, SupportBuffer &inBuffer, Vec3Arg inScale) const override;
 	virtual const Support *	GetSupportFunction(ESupportMode inMode, SupportBuffer &inBuffer, Vec3Arg inScale) const override;
 
 
-	// See ConvexShape::GetSupportingFace
-	virtual void			GetSupportingFace(Vec3Arg inDirection, Vec3Arg inScale, SupportingFace &outVertices) const override;
-
 #ifdef JPH_DEBUG_RENDERER
 #ifdef JPH_DEBUG_RENDERER
 	// See Shape::Draw
 	// See Shape::Draw
 	virtual void			Draw(DebugRenderer *inRenderer, Mat44Arg inCenterOfMassTransform, Vec3Arg inScale, ColorArg inColor, bool inUseMaterialColors, bool inDrawWireframe) const override;
 	virtual void			Draw(DebugRenderer *inRenderer, Mat44Arg inCenterOfMassTransform, Vec3Arg inScale, ColorArg inColor, bool inUseMaterialColors, bool inDrawWireframe) const override;

+ 4 - 3
Jolt/Physics/Collision/Shape/CapsuleShape.cpp

@@ -170,8 +170,9 @@ const ConvexShape::Support *CapsuleShape::GetSupportFunction(ESupportMode inMode
 	return nullptr;
 	return nullptr;
 }
 }
 
 
-void CapsuleShape::GetSupportingFace(Vec3Arg inDirection, Vec3Arg inScale, SupportingFace &outVertices) const
+void CapsuleShape::GetSupportingFace(const SubShapeID &inSubShapeID, Vec3Arg inDirection, Vec3Arg inScale, Mat44Arg inCenterOfMassTransform, SupportingFace &outVertices) const
 {	
 {	
+	JPH_ASSERT(inSubShapeID.IsEmpty(), "Invalid subshape ID");
 	JPH_ASSERT(IsValidScale(inScale));
 	JPH_ASSERT(IsValidScale(inScale));
 
 
 	// Get direction in horizontal plane
 	// Get direction in horizontal plane
@@ -203,8 +204,8 @@ void CapsuleShape::GetSupportingFace(Vec3Arg inDirection, Vec3Arg inScale, Suppo
 	// If projection is roughly equal then return line, otherwise we return nothing as there's only 1 point
 	// If projection is roughly equal then return line, otherwise we return nothing as there's only 1 point
 	if (abs(proj_top - proj_bottom) < cCapsuleProjectionSlop * inDirection.Length())
 	if (abs(proj_top - proj_bottom) < cCapsuleProjectionSlop * inDirection.Length())
 	{
 	{
-		outVertices.push_back(support_top);
-		outVertices.push_back(support_bottom);
+		outVertices.push_back(inCenterOfMassTransform * support_top);
+		outVertices.push_back(inCenterOfMassTransform * support_bottom);
 	}
 	}
 }
 }
 
 

+ 3 - 3
Jolt/Physics/Collision/Shape/CapsuleShape.h

@@ -65,12 +65,12 @@ public:
 	// See Shape::GetSurfaceNormal
 	// See Shape::GetSurfaceNormal
 	virtual Vec3			GetSurfaceNormal(const SubShapeID &inSubShapeID, Vec3Arg inLocalSurfacePosition) const override;
 	virtual Vec3			GetSurfaceNormal(const SubShapeID &inSubShapeID, Vec3Arg inLocalSurfacePosition) const override;
 
 
+	// See Shape::GetSupportingFace
+	virtual void			GetSupportingFace(const SubShapeID &inSubShapeID, Vec3Arg inDirection, Vec3Arg inScale, Mat44Arg inCenterOfMassTransform, SupportingFace &outVertices) const override;
+
 	// See ConvexShape::GetSupportFunction
 	// See ConvexShape::GetSupportFunction
 	virtual const Support *	GetSupportFunction(ESupportMode inMode, SupportBuffer &inBuffer, Vec3Arg inScale) const override;
 	virtual const Support *	GetSupportFunction(ESupportMode inMode, SupportBuffer &inBuffer, Vec3Arg inScale) const override;
 
 
-	// See ConvexShape::GetSupportingFace
-	virtual void			GetSupportingFace(Vec3Arg inDirection, Vec3Arg inScale, SupportingFace &outVertices) const override;
-
 #ifdef JPH_DEBUG_RENDERER
 #ifdef JPH_DEBUG_RENDERER
 	// See Shape::Draw
 	// See Shape::Draw
 	virtual void			Draw(DebugRenderer *inRenderer, Mat44Arg inCenterOfMassTransform, Vec3Arg inScale, ColorArg inColor, bool inUseMaterialColors, bool inDrawWireframe) const override;
 	virtual void			Draw(DebugRenderer *inRenderer, Mat44Arg inCenterOfMassTransform, Vec3Arg inScale, ColorArg inColor, bool inUseMaterialColors, bool inDrawWireframe) const override;

+ 12 - 0
Jolt/Physics/Collision/Shape/CompoundShape.cpp

@@ -170,6 +170,18 @@ Vec3 CompoundShape::GetSurfaceNormal(const SubShapeID &inSubShapeID, Vec3Arg inL
 	return transform.Multiply3x3Transposed(normal);
 	return transform.Multiply3x3Transposed(normal);
 }
 }
 
 
+void CompoundShape::GetSupportingFace(const SubShapeID &inSubShapeID, Vec3Arg inDirection, Vec3Arg inScale, Mat44Arg inCenterOfMassTransform, SupportingFace &outVertices) const
+{
+	// Decode sub shape index
+	SubShapeID remainder;
+	uint32 index = GetSubShapeIndexFromID(inSubShapeID, remainder);
+
+	// Apply transform and pass on to sub shape
+	const SubShape &shape = mSubShapes[index];
+	Mat44 transform = shape.GetLocalTransformNoScale(inScale);
+	shape.mShape->GetSupportingFace(remainder, transform.Multiply3x3Transposed(inDirection), shape.TransformScale(inScale), inCenterOfMassTransform * transform, outVertices);
+}
+
 void CompoundShape::GetSubmergedVolume(Mat44Arg inCenterOfMassTransform, Vec3Arg inScale, const Plane &inSurface, float &outTotalVolume, float &outSubmergedVolume, Vec3 &outCenterOfBuoyancy) const
 void CompoundShape::GetSubmergedVolume(Mat44Arg inCenterOfMassTransform, Vec3Arg inScale, const Plane &inSurface, float &outTotalVolume, float &outSubmergedVolume, Vec3 &outCenterOfBuoyancy) const
 {
 {
 	outTotalVolume = 0.0f;
 	outTotalVolume = 0.0f;

+ 3 - 0
Jolt/Physics/Collision/Shape/CompoundShape.h

@@ -86,6 +86,9 @@ public:
 	// See Shape::GetSurfaceNormal
 	// See Shape::GetSurfaceNormal
 	virtual Vec3					GetSurfaceNormal(const SubShapeID &inSubShapeID, Vec3Arg inLocalSurfacePosition) const override;
 	virtual Vec3					GetSurfaceNormal(const SubShapeID &inSubShapeID, Vec3Arg inLocalSurfacePosition) const override;
 
 
+	// See Shape::GetSupportingFace
+	virtual void					GetSupportingFace(const SubShapeID &inSubShapeID, Vec3Arg inDirection, Vec3Arg inScale, Mat44Arg inCenterOfMassTransform, SupportingFace &outVertices) const override;
+
 	// See Shape::GetSubmergedVolume
 	// See Shape::GetSubmergedVolume
 	virtual void					GetSubmergedVolume(Mat44Arg inCenterOfMassTransform, Vec3Arg inScale, const Plane &inSurface, float &outTotalVolume, float &outSubmergedVolume, Vec3 &outCenterOfBuoyancy) const override;
 	virtual void					GetSubmergedVolume(Mat44Arg inCenterOfMassTransform, Vec3Arg inScale, const Plane &inSurface, float &outTotalVolume, float &outSubmergedVolume, Vec3 &outCenterOfBuoyancy) const override;
 
 

+ 8 - 3
Jolt/Physics/Collision/Shape/ConvexHullShape.cpp

@@ -669,8 +669,10 @@ const ConvexShape::Support *ConvexHullShape::GetSupportFunction(ESupportMode inM
 	return nullptr;
 	return nullptr;
 }
 }
 
 
-void ConvexHullShape::GetSupportingFace(Vec3Arg inDirection, Vec3Arg inScale, SupportingFace &outVertices) const 
+void ConvexHullShape::GetSupportingFace(const SubShapeID &inSubShapeID, Vec3Arg inDirection, Vec3Arg inScale, Mat44Arg inCenterOfMassTransform, SupportingFace &outVertices) const 
 {
 {
+	JPH_ASSERT(inSubShapeID.IsEmpty(), "Invalid subshape ID");
+
 	Vec3 inv_scale = inScale.Reciprocal();
 	Vec3 inv_scale = inScale.Reciprocal();
 	
 	
 	// Need to transform the plane normals using inScale
 	// Need to transform the plane normals using inScale
@@ -701,17 +703,20 @@ void ConvexHullShape::GetSupportingFace(Vec3Arg inDirection, Vec3Arg inScale, Su
 	int max_vertices_to_return = outVertices.capacity() / 2;
 	int max_vertices_to_return = outVertices.capacity() / 2;
 	int delta_vtx = (int(best_face.mNumVertices) + max_vertices_to_return) / max_vertices_to_return;
 	int delta_vtx = (int(best_face.mNumVertices) + max_vertices_to_return) / max_vertices_to_return;
 
 
+	// Calculate transform with scale
+	Mat44 transform = inCenterOfMassTransform.PreScaled(inScale);
+
 	if (ScaleHelpers::IsInsideOut(inScale))
 	if (ScaleHelpers::IsInsideOut(inScale))
 	{
 	{
 		// Flip winding of supporting face
 		// Flip winding of supporting face
 		for (const uint8 *v = end_vtx - 1; v >= first_vtx; v -= delta_vtx)
 		for (const uint8 *v = end_vtx - 1; v >= first_vtx; v -= delta_vtx)
-			outVertices.push_back(inScale * mPoints[*v].mPosition);
+			outVertices.push_back(transform * mPoints[*v].mPosition);
 	}
 	}
 	else
 	else
 	{
 	{
 		// Normal winding of supporting face
 		// Normal winding of supporting face
 		for (const uint8 *v = first_vtx; v < end_vtx; v += delta_vtx)
 		for (const uint8 *v = first_vtx; v < end_vtx; v += delta_vtx)
-			outVertices.push_back(inScale * mPoints[*v].mPosition);
+			outVertices.push_back(transform * mPoints[*v].mPosition);
 	}
 	}
 }
 }
 
 

+ 3 - 3
Jolt/Physics/Collision/Shape/ConvexHullShape.h

@@ -64,12 +64,12 @@ public:
 	// See Shape::GetSurfaceNormal
 	// See Shape::GetSurfaceNormal
 	virtual Vec3			GetSurfaceNormal(const SubShapeID &inSubShapeID, Vec3Arg inLocalSurfacePosition) const override;
 	virtual Vec3			GetSurfaceNormal(const SubShapeID &inSubShapeID, Vec3Arg inLocalSurfacePosition) const override;
 
 
+	// See Shape::GetSupportingFace
+	virtual void			GetSupportingFace(const SubShapeID &inSubShapeID, Vec3Arg inDirection, Vec3Arg inScale, Mat44Arg inCenterOfMassTransform, SupportingFace &outVertices) const override;
+
 	// See ConvexShape::GetSupportFunction
 	// See ConvexShape::GetSupportFunction
 	virtual const Support *	GetSupportFunction(ESupportMode inMode, SupportBuffer &inBuffer, Vec3Arg inScale) const override;
 	virtual const Support *	GetSupportFunction(ESupportMode inMode, SupportBuffer &inBuffer, Vec3Arg inScale) const override;
 
 
-	// See ConvexShape::GetSupportingFace
-	virtual void			GetSupportingFace(Vec3Arg inDirection, Vec3Arg inScale, SupportingFace &outVertices) const override;
-
 	// See Shape::GetSubmergedVolume
 	// See Shape::GetSubmergedVolume
 	virtual void			GetSubmergedVolume(Mat44Arg inCenterOfMassTransform, Vec3Arg inScale, const Plane &inSurface, float &outTotalVolume, float &outSubmergedVolume, Vec3 &outCenterOfBuoyancy) const override;
 	virtual void			GetSubmergedVolume(Mat44Arg inCenterOfMassTransform, Vec3Arg inScale, const Plane &inSurface, float &outTotalVolume, float &outSubmergedVolume, Vec3 &outCenterOfBuoyancy) const override;
 
 

+ 5 - 22
Jolt/Physics/Collision/Shape/ConvexShape.cpp

@@ -144,18 +144,10 @@ void ConvexShape::sCollideConvexVsConvex(const Shape *inShape1, const Shape *inS
 	if (inCollideShapeSettings.mCollectFacesMode == ECollectFacesMode::CollectFaces)
 	if (inCollideShapeSettings.mCollectFacesMode == ECollectFacesMode::CollectFaces)
 	{
 	{
 		// Get supporting face of shape 1
 		// Get supporting face of shape 1
-		shape1->GetSupportingFace(-penetration_axis, inScale1, result.mShape1Face);
-
-		// Convert to world space
-		for (Vec3 &p : result.mShape1Face)
-			p = inCenterOfMassTransform1 * p;
+		shape1->GetSupportingFace(SubShapeID(), -penetration_axis, inScale1, inCenterOfMassTransform1, result.mShape1Face);
 
 
 		// Get supporting face of shape 2 
 		// Get supporting face of shape 2 
-		shape2->GetSupportingFace(transform_2_to_1.Multiply3x3Transposed(penetration_axis), inScale2, result.mShape2Face);
-
-		// Convert to world space
-		for (Vec3 &p : result.mShape2Face)
-			p = inCenterOfMassTransform2 * p;
+		shape2->GetSupportingFace(SubShapeID(), transform_2_to_1.Multiply3x3Transposed(penetration_axis), inScale2, inCenterOfMassTransform2, result.mShape2Face);
 	}
 	}
 
 
 	// Notify the collector
 	// Notify the collector
@@ -297,19 +289,10 @@ void ConvexShape::sCastConvexVsConvex(const ShapeCast &inShapeCast, const ShapeC
 			// Get supporting face of shape 1
 			// Get supporting face of shape 1
 			Mat44 transform_1_to_2 = inShapeCast.mCenterOfMassStart;
 			Mat44 transform_1_to_2 = inShapeCast.mCenterOfMassStart;
 			transform_1_to_2.SetTranslation(transform_1_to_2.GetTranslation() + fraction * inShapeCast.mDirection);
 			transform_1_to_2.SetTranslation(transform_1_to_2.GetTranslation() + fraction * inShapeCast.mDirection);
-			cast_shape->GetSupportingFace(transform_1_to_2.Multiply3x3Transposed(-contact_normal), inShapeCast.mScale, result.mShape1Face);
-
-			// Convert to world space
-			Mat44 transform_1_to_world = inCenterOfMassTransform2 * transform_1_to_2;
-			for (Vec3 &p : result.mShape1Face)
-				p = transform_1_to_world * p;
+			cast_shape->GetSupportingFace(SubShapeID(), transform_1_to_2.Multiply3x3Transposed(-contact_normal), inShapeCast.mScale, inCenterOfMassTransform2 * transform_1_to_2, result.mShape1Face);
 
 
 			// Get supporting face of shape 2
 			// Get supporting face of shape 2
-			shape->GetSupportingFace(contact_normal, inScale, result.mShape2Face);
-
-			// Convert to world space
-			for (Vec3 &p : result.mShape2Face)
-				p = inCenterOfMassTransform2 * p;
+			shape->GetSupportingFace(SubShapeID(), contact_normal, inScale, inCenterOfMassTransform2, result.mShape2Face);
 		}
 		}
 
 
 		JPH_IF_TRACK_NARROWPHASE_STATS(TrackNarrowPhaseCollector track;)
 		JPH_IF_TRACK_NARROWPHASE_STATS(TrackNarrowPhaseCollector track;)
@@ -491,7 +474,7 @@ void ConvexShape::DrawGetSupportingFace(DebugRenderer *inRenderer, Mat44Arg inCe
 		Vec3 direction = 0.05f * v;
 		Vec3 direction = 0.05f * v;
 			
 			
 		SupportingFace face;
 		SupportingFace face;
-		GetSupportingFace(direction, inScale, face);
+		GetSupportingFace(SubShapeID(), direction, inScale, Mat44::sIdentity(), face);
 			
 			
 		if (!face.empty())
 		if (!face.empty())
 		{
 		{

+ 0 - 7
Jolt/Physics/Collision/Shape/ConvexShape.h

@@ -99,13 +99,6 @@ public:
 	/// inScale scales this shape in local space.
 	/// inScale scales this shape in local space.
 	virtual const Support *			GetSupportFunction(ESupportMode inMode, SupportBuffer &inBuffer, Vec3Arg inScale) const = 0;
 	virtual const Support *			GetSupportFunction(ESupportMode inMode, SupportBuffer &inBuffer, Vec3Arg inScale) const = 0;
 
 
-	/// Type definition for a supporting face
-	using SupportingFace = StaticArray<Vec3, 32>;
-
-	/// Get the vertices of the face that faces inDirection the most (includes convex radius).
-	/// Face is relative to the center of mass of the shape.
-	virtual void					GetSupportingFace(Vec3Arg inDirection, Vec3Arg inScale, SupportingFace &outVertices) const = 0;
-
 	/// Material of the shape
 	/// Material of the shape
 	void							SetMaterial(const PhysicsMaterial *inMaterial)				{ mMaterial = inMaterial; }
 	void							SetMaterial(const PhysicsMaterial *inMaterial)				{ mMaterial = inMaterial; }
 	const PhysicsMaterial *			GetMaterial() const											{ return mMaterial != nullptr? mMaterial : PhysicsMaterial::sDefault; }
 	const PhysicsMaterial *			GetMaterial() const											{ return mMaterial != nullptr? mMaterial : PhysicsMaterial::sDefault; }

+ 6 - 4
Jolt/Physics/Collision/Shape/CylinderShape.cpp

@@ -185,8 +185,9 @@ const ConvexShape::Support *CylinderShape::GetSupportFunction(ESupportMode inMod
 	return nullptr;
 	return nullptr;
 }
 }
 
 
-void CylinderShape::GetSupportingFace(Vec3Arg inDirection, Vec3Arg inScale, SupportingFace &outVertices) const
+void CylinderShape::GetSupportingFace(const SubShapeID &inSubShapeID, Vec3Arg inDirection, Vec3Arg inScale, Mat44Arg inCenterOfMassTransform, SupportingFace &outVertices) const
 {	
 {	
+	JPH_ASSERT(inSubShapeID.IsEmpty(), "Invalid subshape ID");
 	JPH_ASSERT(IsValidScale(inScale));
 	JPH_ASSERT(IsValidScale(inScale));
 
 
 	// Get scaled cylinder
 	// Get scaled cylinder
@@ -206,15 +207,16 @@ void CylinderShape::GetSupportingFace(Vec3Arg inDirection, Vec3Arg inScale, Supp
 		float f = -scaled_radius / o;
 		float f = -scaled_radius / o;
 		float vx = x * f;
 		float vx = x * f;
 		float vz = z * f;
 		float vz = z * f;
-		outVertices.push_back(Vec3(vx, scaled_half_height, vz));
-		outVertices.push_back(Vec3(vx, -scaled_half_height, vz));
+		outVertices.push_back(inCenterOfMassTransform * Vec3(vx, scaled_half_height, vz));
+		outVertices.push_back(inCenterOfMassTransform * Vec3(vx, -scaled_half_height, vz));
 	}
 	}
 	else
 	else
 	{
 	{
 		// Hitting top or bottom
 		// Hitting top or bottom
 		Vec3 multiplier = y < 0.0f? Vec3(scaled_radius, scaled_half_height, scaled_radius) : Vec3(-scaled_radius, -scaled_half_height, scaled_radius);
 		Vec3 multiplier = y < 0.0f? Vec3(scaled_radius, scaled_half_height, scaled_radius) : Vec3(-scaled_radius, -scaled_half_height, scaled_radius);
+		Mat44 transform = inCenterOfMassTransform.PreScaled(multiplier);
 		for (const Vec3 &v : cTopFace)
 		for (const Vec3 &v : cTopFace)
-			outVertices.push_back(multiplier * v);
+			outVertices.push_back(transform * v);
 	}
 	}
 }
 }
 
 

+ 3 - 3
Jolt/Physics/Collision/Shape/CylinderShape.h

@@ -61,12 +61,12 @@ public:
 	// See Shape::GetSurfaceNormal
 	// See Shape::GetSurfaceNormal
 	virtual Vec3			GetSurfaceNormal(const SubShapeID &inSubShapeID, Vec3Arg inLocalSurfacePosition) const override;
 	virtual Vec3			GetSurfaceNormal(const SubShapeID &inSubShapeID, Vec3Arg inLocalSurfacePosition) const override;
 
 
+	// See Shape::GetSupportingFace
+	virtual void			GetSupportingFace(const SubShapeID &inSubShapeID, Vec3Arg inDirection, Vec3Arg inScale, Mat44Arg inCenterOfMassTransform, SupportingFace &outVertices) const override;
+
 	// See ConvexShape::GetSupportFunction
 	// See ConvexShape::GetSupportFunction
 	virtual const Support *	GetSupportFunction(ESupportMode inMode, SupportBuffer &inBuffer, Vec3Arg inScale) const override;
 	virtual const Support *	GetSupportFunction(ESupportMode inMode, SupportBuffer &inBuffer, Vec3Arg inScale) const override;
 
 
-	// See ConvexShape::GetSupportingFace
-	virtual void			GetSupportingFace(Vec3Arg inDirection, Vec3Arg inScale, SupportingFace &outVertices) const override;
-
 #ifdef JPH_DEBUG_RENDERER
 #ifdef JPH_DEBUG_RENDERER
 	// See Shape::Draw
 	// See Shape::Draw
 	virtual void			Draw(DebugRenderer *inRenderer, Mat44Arg inCenterOfMassTransform, Vec3Arg inScale, ColorArg inColor, bool inUseMaterialColors, bool inDrawWireframe) const override;
 	virtual void			Draw(DebugRenderer *inRenderer, Mat44Arg inCenterOfMassTransform, Vec3Arg inScale, ColorArg inColor, bool inUseMaterialColors, bool inDrawWireframe) const override;

+ 5 - 0
Jolt/Physics/Collision/Shape/DecoratedShape.cpp

@@ -48,6 +48,11 @@ const PhysicsMaterial *DecoratedShape::GetMaterial(const SubShapeID &inSubShapeI
 	return mInnerShape->GetMaterial(inSubShapeID);
 	return mInnerShape->GetMaterial(inSubShapeID);
 }
 }
 
 
+void DecoratedShape::GetSupportingFace(const SubShapeID &inSubShapeID, Vec3Arg inDirection, Vec3Arg inScale, Mat44Arg inCenterOfMassTransform, SupportingFace &outVertices) const
+{
+	mInnerShape->GetSupportingFace(inSubShapeID, inDirection, inScale, inCenterOfMassTransform, outVertices);
+}
+
 uint64 DecoratedShape::GetSubShapeUserData(const SubShapeID &inSubShapeID) const
 uint64 DecoratedShape::GetSubShapeUserData(const SubShapeID &inSubShapeID) const
 {
 {
 	return mInnerShape->GetSubShapeUserData(inSubShapeID);
 	return mInnerShape->GetSubShapeUserData(inSubShapeID);

+ 3 - 0
Jolt/Physics/Collision/Shape/DecoratedShape.h

@@ -49,6 +49,9 @@ public:
 	// See Shape::GetMaterial
 	// See Shape::GetMaterial
 	virtual const PhysicsMaterial *	GetMaterial(const SubShapeID &inSubShapeID) const override;
 	virtual const PhysicsMaterial *	GetMaterial(const SubShapeID &inSubShapeID) const override;
 
 
+	// See Shape::GetSupportingFace
+	virtual void					GetSupportingFace(const SubShapeID &inSubShapeID, Vec3Arg inDirection, Vec3Arg inScale, Mat44Arg inCenterOfMassTransform, SupportingFace &outVertices) const override;
+
 	// See Shape::GetSubShapeUserData
 	// See Shape::GetSubShapeUserData
 	virtual uint64					GetSubShapeUserData(const SubShapeID &inSubShapeID) const override;
 	virtual uint64					GetSubShapeUserData(const SubShapeID &inSubShapeID) const override;
 
 

+ 31 - 0
Jolt/Physics/Collision/Shape/HeightFieldShape.cpp

@@ -829,6 +829,37 @@ Vec3 HeightFieldShape::GetSurfaceNormal(const SubShapeID &inSubShapeID, Vec3Arg
 	return normal.Normalized();
 	return normal.Normalized();
 }
 }
 
 
+void HeightFieldShape::GetSupportingFace(const SubShapeID &inSubShapeID, Vec3Arg inDirection, Vec3Arg inScale, Mat44Arg inCenterOfMassTransform, SupportingFace &outVertices) const
+{
+	// Decode ID
+	uint x, y, triangle;
+	DecodeSubShapeID(inSubShapeID, x, y, triangle);
+
+	// Fetch the triangle
+	outVertices.resize(3);
+	outVertices[0] = GetPosition(x, y);
+	Vec3 v2 = GetPosition(x + 1, y + 1);
+	if (triangle == 0)
+	{
+		outVertices[1] = GetPosition(x, y + 1);
+		outVertices[2] = v2;
+	}
+	else
+	{
+		outVertices[1] = v2;
+		outVertices[2] = GetPosition(x + 1, y);
+	}
+
+	// Flip triangle if scaled inside out
+	if (ScaleHelpers::IsInsideOut(inScale))
+		swap(outVertices[1], outVertices[2]);
+
+	// Transform to world space
+	Mat44 transform = inCenterOfMassTransform.PreScaled(inScale);
+	for (Vec3 &v : outVertices)
+		v = transform * v;
+}
+
 inline uint8 HeightFieldShape::GetEdgeFlags(uint inX, uint inY, uint inTriangle) const
 inline uint8 HeightFieldShape::GetEdgeFlags(uint inX, uint inY, uint inTriangle) const
 {
 {
 	if (inTriangle == 0)
 	if (inTriangle == 0)

+ 3 - 0
Jolt/Physics/Collision/Shape/HeightFieldShape.h

@@ -121,6 +121,9 @@ public:
 	// See Shape::GetSurfaceNormal
 	// See Shape::GetSurfaceNormal
 	virtual Vec3					GetSurfaceNormal(const SubShapeID &inSubShapeID, Vec3Arg inLocalSurfacePosition) const override;
 	virtual Vec3					GetSurfaceNormal(const SubShapeID &inSubShapeID, Vec3Arg inLocalSurfacePosition) const override;
 
 
+	// See Shape::GetSupportingFace
+	virtual void					GetSupportingFace(const SubShapeID &inSubShapeID, Vec3Arg inDirection, Vec3Arg inScale, Mat44Arg inCenterOfMassTransform, SupportingFace &outVertices) const override;
+
 	// See Shape::GetSubmergedVolume
 	// See Shape::GetSubmergedVolume
 	virtual void					GetSubmergedVolume(Mat44Arg inCenterOfMassTransform, Vec3Arg inScale, const Plane &inSurface, float &outTotalVolume, float &outSubmergedVolume, Vec3 &outCenterOfBuoyancy) const override { JPH_ASSERT(false, "Not supported"); }
 	virtual void					GetSubmergedVolume(Mat44Arg inCenterOfMassTransform, Vec3Arg inScale, const Plane &inSurface, float &outTotalVolume, float &outSubmergedVolume, Vec3 &outCenterOfBuoyancy) const override { JPH_ASSERT(false, "Not supported"); }
 
 

+ 24 - 0
Jolt/Physics/Collision/Shape/MeshShape.cpp

@@ -385,6 +385,30 @@ Vec3 MeshShape::GetSurfaceNormal(const SubShapeID &inSubShapeID, Vec3Arg inLocal
 	return (v3 - v2).Cross(v1 - v2).Normalized();
 	return (v3 - v2).Cross(v1 - v2).Normalized();
 }
 }
 
 
+void MeshShape::GetSupportingFace(const SubShapeID &inSubShapeID, Vec3Arg inDirection, Vec3Arg inScale, Mat44Arg inCenterOfMassTransform, SupportingFace &outVertices) const
+{
+	// Decode ID
+	const void *block_start;
+	uint32 triangle_idx;
+	DecodeSubShapeID(inSubShapeID, block_start, triangle_idx);
+
+	// Decode triangle	
+	const TriangleCodec::DecodingContext triangle_ctx(sGetTriangleHeader(mTree));
+	outVertices.resize(3);
+	triangle_ctx.GetTriangle(block_start, triangle_idx, outVertices[0], outVertices[1], outVertices[2]);
+
+	// Flip triangle if scaled inside out
+	if (ScaleHelpers::IsInsideOut(inScale))
+		swap(outVertices[1], outVertices[2]);
+
+	// Calculate transform with scale
+	Mat44 transform = inCenterOfMassTransform.PreScaled(inScale);
+
+	// Transform to world space
+	for (Vec3 &v : outVertices)
+		v = transform * v;
+}
+
 AABox MeshShape::GetLocalBounds() const
 AABox MeshShape::GetLocalBounds() const
 {
 {
 	const NodeCodec::Header *header = sGetNodeHeader(mTree);
 	const NodeCodec::Header *header = sGetNodeHeader(mTree);

+ 3 - 0
Jolt/Physics/Collision/Shape/MeshShape.h

@@ -86,6 +86,9 @@ public:
 	// See Shape::GetSurfaceNormal
 	// See Shape::GetSurfaceNormal
 	virtual Vec3					GetSurfaceNormal(const SubShapeID &inSubShapeID, Vec3Arg inLocalSurfacePosition) const override;
 	virtual Vec3					GetSurfaceNormal(const SubShapeID &inSubShapeID, Vec3Arg inLocalSurfacePosition) const override;
 
 
+	// See Shape::GetSupportingFace
+	virtual void					GetSupportingFace(const SubShapeID &inSubShapeID, Vec3Arg inDirection, Vec3Arg inScale, Mat44Arg inCenterOfMassTransform, SupportingFace &outVertices) const override;
+
 #ifdef JPH_DEBUG_RENDERER
 #ifdef JPH_DEBUG_RENDERER
 	// See Shape::Draw
 	// See Shape::Draw
 	virtual void					Draw(DebugRenderer *inRenderer, Mat44Arg inCenterOfMassTransform, Vec3Arg inScale, ColorArg inColor, bool inUseMaterialColors, bool inDrawWireframe) const override;
 	virtual void					Draw(DebugRenderer *inRenderer, Mat44Arg inCenterOfMassTransform, Vec3Arg inScale, ColorArg inColor, bool inUseMaterialColors, bool inDrawWireframe) const override;

+ 5 - 0
Jolt/Physics/Collision/Shape/OffsetCenterOfMassShape.cpp

@@ -67,6 +67,11 @@ Vec3 OffsetCenterOfMassShape::GetSurfaceNormal(const SubShapeID &inSubShapeID, V
 	return mInnerShape->GetSurfaceNormal(inSubShapeID, inLocalSurfacePosition + mOffset);
 	return mInnerShape->GetSurfaceNormal(inSubShapeID, inLocalSurfacePosition + mOffset);
 }
 }
 
 
+void OffsetCenterOfMassShape::GetSupportingFace(const SubShapeID &inSubShapeID, Vec3Arg inDirection, Vec3Arg inScale, Mat44Arg inCenterOfMassTransform, SupportingFace &outVertices) const
+{
+	mInnerShape->GetSupportingFace(inSubShapeID, inDirection, inScale, inCenterOfMassTransform.PreTranslated(-mOffset), outVertices);
+}
+
 void OffsetCenterOfMassShape::GetSubmergedVolume(Mat44Arg inCenterOfMassTransform, Vec3Arg inScale, const Plane &inSurface, float &outTotalVolume, float &outSubmergedVolume, Vec3 &outCenterOfBuoyancy) const
 void OffsetCenterOfMassShape::GetSubmergedVolume(Mat44Arg inCenterOfMassTransform, Vec3Arg inScale, const Plane &inSurface, float &outTotalVolume, float &outSubmergedVolume, Vec3 &outCenterOfBuoyancy) const
 {
 {
 	mInnerShape->GetSubmergedVolume(inCenterOfMassTransform.PreTranslated(-mOffset), inScale, inSurface, outTotalVolume, outSubmergedVolume, outCenterOfBuoyancy);
 	mInnerShape->GetSubmergedVolume(inCenterOfMassTransform.PreTranslated(-mOffset), inScale, inSurface, outTotalVolume, outSubmergedVolume, outCenterOfBuoyancy);

+ 3 - 0
Jolt/Physics/Collision/Shape/OffsetCenterOfMassShape.h

@@ -64,6 +64,9 @@ public:
 	// See Shape::GetSurfaceNormal
 	// See Shape::GetSurfaceNormal
 	virtual Vec3					GetSurfaceNormal(const SubShapeID &inSubShapeID, Vec3Arg inLocalSurfacePosition) const override;
 	virtual Vec3					GetSurfaceNormal(const SubShapeID &inSubShapeID, Vec3Arg inLocalSurfacePosition) const override;
 
 
+	// See Shape::GetSupportingFace
+	virtual void					GetSupportingFace(const SubShapeID &inSubShapeID, Vec3Arg inDirection, Vec3Arg inScale, Mat44Arg inCenterOfMassTransform, SupportingFace &outVertices) const override;
+
 	// See Shape::GetSubmergedVolume
 	// See Shape::GetSubmergedVolume
 	virtual void					GetSubmergedVolume(Mat44Arg inCenterOfMassTransform, Vec3Arg inScale, const Plane &inSurface, float &outTotalVolume, float &outSubmergedVolume, Vec3 &outCenterOfBuoyancy) const override;
 	virtual void					GetSubmergedVolume(Mat44Arg inCenterOfMassTransform, Vec3Arg inScale, const Plane &inSurface, float &outTotalVolume, float &outSubmergedVolume, Vec3 &outCenterOfBuoyancy) const override;
 
 

+ 6 - 0
Jolt/Physics/Collision/Shape/RotatedTranslatedShape.cpp

@@ -95,6 +95,12 @@ Vec3 RotatedTranslatedShape::GetSurfaceNormal(const SubShapeID &inSubShapeID, Ve
 	return transform.Multiply3x3Transposed(normal);
 	return transform.Multiply3x3Transposed(normal);
 }
 }
 
 
+void RotatedTranslatedShape::GetSupportingFace(const SubShapeID &inSubShapeID, Vec3Arg inDirection, Vec3Arg inScale, Mat44Arg inCenterOfMassTransform, SupportingFace &outVertices) const
+{
+	Mat44 transform = Mat44::sRotation(mRotation);
+	mInnerShape->GetSupportingFace(inSubShapeID, transform.Multiply3x3Transposed(inDirection), TransformScale(inScale), inCenterOfMassTransform * transform, outVertices);
+}
+
 void RotatedTranslatedShape::GetSubmergedVolume(Mat44Arg inCenterOfMassTransform, Vec3Arg inScale, const Plane &inSurface, float &outTotalVolume, float &outSubmergedVolume, Vec3 &outCenterOfBuoyancy) const
 void RotatedTranslatedShape::GetSubmergedVolume(Mat44Arg inCenterOfMassTransform, Vec3Arg inScale, const Plane &inSurface, float &outTotalVolume, float &outSubmergedVolume, Vec3 &outCenterOfBuoyancy) const
 {
 {
 	// Get center of mass transform of child
 	// Get center of mass transform of child

+ 3 - 0
Jolt/Physics/Collision/Shape/RotatedTranslatedShape.h

@@ -71,6 +71,9 @@ public:
 	// See Shape::GetSurfaceNormal
 	// See Shape::GetSurfaceNormal
 	virtual Vec3					GetSurfaceNormal(const SubShapeID &inSubShapeID, Vec3Arg inLocalSurfacePosition) const override;
 	virtual Vec3					GetSurfaceNormal(const SubShapeID &inSubShapeID, Vec3Arg inLocalSurfacePosition) const override;
 
 
+	// See Shape::GetSupportingFace
+	virtual void					GetSupportingFace(const SubShapeID &inSubShapeID, Vec3Arg inDirection, Vec3Arg inScale, Mat44Arg inCenterOfMassTransform, SupportingFace &outVertices) const override;
+
 	// See Shape::GetSubmergedVolume
 	// See Shape::GetSubmergedVolume
 	virtual void					GetSubmergedVolume(Mat44Arg inCenterOfMassTransform, Vec3Arg inScale, const Plane &inSurface, float &outTotalVolume, float &outSubmergedVolume, Vec3 &outCenterOfBuoyancy) const override;
 	virtual void					GetSubmergedVolume(Mat44Arg inCenterOfMassTransform, Vec3Arg inScale, const Plane &inSurface, float &outTotalVolume, float &outSubmergedVolume, Vec3 &outCenterOfBuoyancy) const override;
 
 

+ 5 - 0
Jolt/Physics/Collision/Shape/ScaledShape.cpp

@@ -76,6 +76,11 @@ Vec3 ScaledShape::GetSurfaceNormal(const SubShapeID &inSubShapeID, Vec3Arg inLoc
 	return (normal / mScale).Normalized();
 	return (normal / mScale).Normalized();
 }
 }
 
 
+void ScaledShape::GetSupportingFace(const SubShapeID &inSubShapeID, Vec3Arg inDirection, Vec3Arg inScale, Mat44Arg inCenterOfMassTransform, SupportingFace &outVertices) const
+{
+	mInnerShape->GetSupportingFace(inSubShapeID, inDirection, inScale * mScale, inCenterOfMassTransform, outVertices);
+}
+
 void ScaledShape::GetSubmergedVolume(Mat44Arg inCenterOfMassTransform, Vec3Arg inScale, const Plane &inSurface, float &outTotalVolume, float &outSubmergedVolume, Vec3 &outCenterOfBuoyancy) const
 void ScaledShape::GetSubmergedVolume(Mat44Arg inCenterOfMassTransform, Vec3Arg inScale, const Plane &inSurface, float &outTotalVolume, float &outSubmergedVolume, Vec3 &outCenterOfBuoyancy) const
 {
 {
 	mInnerShape->GetSubmergedVolume(inCenterOfMassTransform, inScale * mScale, inSurface, outTotalVolume, outSubmergedVolume, outCenterOfBuoyancy);
 	mInnerShape->GetSubmergedVolume(inCenterOfMassTransform, inScale * mScale, inSurface, outTotalVolume, outSubmergedVolume, outCenterOfBuoyancy);

+ 3 - 0
Jolt/Physics/Collision/Shape/ScaledShape.h

@@ -64,6 +64,9 @@ public:
 	// See Shape::GetSurfaceNormal
 	// See Shape::GetSurfaceNormal
 	virtual Vec3					GetSurfaceNormal(const SubShapeID &inSubShapeID, Vec3Arg inLocalSurfacePosition) const override;
 	virtual Vec3					GetSurfaceNormal(const SubShapeID &inSubShapeID, Vec3Arg inLocalSurfacePosition) const override;
 
 
+	// See Shape::GetSupportingFace
+	virtual void					GetSupportingFace(const SubShapeID &inSubShapeID, Vec3Arg inDirection, Vec3Arg inScale, Mat44Arg inCenterOfMassTransform, SupportingFace &outVertices) const override;
+
 	// See Shape::GetSubmergedVolume
 	// See Shape::GetSubmergedVolume
 	virtual void					GetSubmergedVolume(Mat44Arg inCenterOfMassTransform, Vec3Arg inScale, const Plane &inSurface, float &outTotalVolume, float &outSubmergedVolume, Vec3 &outCenterOfBuoyancy) const override;
 	virtual void					GetSubmergedVolume(Mat44Arg inCenterOfMassTransform, Vec3Arg inScale, const Plane &inSurface, float &outTotalVolume, float &outSubmergedVolume, Vec3 &outCenterOfBuoyancy) const override;
 
 

+ 12 - 0
Jolt/Physics/Collision/Shape/Shape.h

@@ -208,6 +208,18 @@ public:
 	/// Note: When you have a CollideShapeResult or ShapeCastResult you should use -mPenetrationAxis.Normalized() as contact normal as GetSurfaceNormal will only return face normals (and not vertex or edge normals).
 	/// Note: When you have a CollideShapeResult or ShapeCastResult you should use -mPenetrationAxis.Normalized() as contact normal as GetSurfaceNormal will only return face normals (and not vertex or edge normals).
 	virtual Vec3					GetSurfaceNormal(const SubShapeID &inSubShapeID, Vec3Arg inLocalSurfacePosition) const = 0;
 	virtual Vec3					GetSurfaceNormal(const SubShapeID &inSubShapeID, Vec3Arg inLocalSurfacePosition) const = 0;
 
 
+	/// Type definition for a supporting face
+	using SupportingFace = StaticArray<Vec3, 32>;
+
+	/// Get the vertices of the face that faces inDirection the most (includes any convex radius). Note that this function can only return faces of
+	/// convex shapes or triangles, which is why a sub shape ID to get to that leaf must be provided. 
+	/// @param inSubShapeID Sub shape ID of target shape
+	/// @param inDirection Direction that the face should be facing (in local space to this shape)
+	/// @param inCenterOfMassTransform Transform to transform outVertices with
+	/// @param inScale Scale of this shape
+	/// @param outVertices Resulting face. The returned face can be empty if the shape doesn't have polygons to return (e.g. because it's a sphere). The face will be returned in world space.
+	virtual void					GetSupportingFace(const SubShapeID &inSubShapeID, Vec3Arg inDirection, Vec3Arg inScale, Mat44Arg inCenterOfMassTransform, SupportingFace &outVertices) const { /* Nothing */ }
+
 	/// Get the user data of a particular sub shape ID
 	/// Get the user data of a particular sub shape ID
 	virtual uint64					GetSubShapeUserData(const SubShapeID &inSubShapeID) const			{ return mUserData; }
 	virtual uint64					GetSubShapeUserData(const SubShapeID &inSubShapeID) const			{ return mUserData; }
 
 

+ 3 - 3
Jolt/Physics/Collision/Shape/SphereShape.h

@@ -57,12 +57,12 @@ public:
 	// See Shape::GetSurfaceNormal
 	// See Shape::GetSurfaceNormal
 	virtual Vec3			GetSurfaceNormal(const SubShapeID &inSubShapeID, Vec3Arg inLocalSurfacePosition) const override;
 	virtual Vec3			GetSurfaceNormal(const SubShapeID &inSubShapeID, Vec3Arg inLocalSurfacePosition) const override;
 
 
+	// See Shape::GetSupportingFace
+	virtual void			GetSupportingFace(const SubShapeID &inSubShapeID, Vec3Arg inDirection, Vec3Arg inScale, Mat44Arg inCenterOfMassTransform, SupportingFace &outVertices) const override { /* Hit is always a single point, no point in returning anything */ }
+
 	// See ConvexShape::GetSupportFunction
 	// See ConvexShape::GetSupportFunction
 	virtual const Support *	GetSupportFunction(ESupportMode inMode, SupportBuffer &inBuffer, Vec3Arg inScale) const override;
 	virtual const Support *	GetSupportFunction(ESupportMode inMode, SupportBuffer &inBuffer, Vec3Arg inScale) const override;
 
 
-	// See ConvexShape::GetSupportingFace
-	virtual void			GetSupportingFace(Vec3Arg inDirection, Vec3Arg inScale, SupportingFace &outVertices) const override	{ /* Hit is always a single point, no point in returning anything */ }
-
 	// See Shape::GetSubmergedVolume
 	// See Shape::GetSubmergedVolume
 	virtual void			GetSubmergedVolume(Mat44Arg inCenterOfMassTransform, Vec3Arg inScale, const Plane &inSurface, float &outTotalVolume, float &outSubmergedVolume, Vec3 &outCenterOfBuoyancy) const override;
 	virtual void			GetSubmergedVolume(Mat44Arg inCenterOfMassTransform, Vec3Arg inScale, const Plane &inSurface, float &outTotalVolume, float &outSubmergedVolume, Vec3 &outCenterOfBuoyancy) const override;
 
 

+ 4 - 3
Jolt/Physics/Collision/Shape/TaperedCapsuleShape.cpp

@@ -208,8 +208,9 @@ const ConvexShape::Support *TaperedCapsuleShape::GetSupportFunction(ESupportMode
 	return nullptr;
 	return nullptr;
 }
 }
 
 
-void TaperedCapsuleShape::GetSupportingFace(Vec3Arg inDirection, Vec3Arg inScale, SupportingFace &outVertices) const
+void TaperedCapsuleShape::GetSupportingFace(const SubShapeID &inSubShapeID, Vec3Arg inDirection, Vec3Arg inScale, Mat44Arg inCenterOfMassTransform, SupportingFace &outVertices) const
 {	
 {	
+	JPH_ASSERT(inSubShapeID.IsEmpty(), "Invalid subshape ID");
 	JPH_ASSERT(IsValidScale(inScale));
 	JPH_ASSERT(IsValidScale(inScale));
 
 
 	// Check zero vector
 	// Check zero vector
@@ -237,8 +238,8 @@ void TaperedCapsuleShape::GetSupportingFace(Vec3Arg inDirection, Vec3Arg inScale
 	// If projection is roughly equal then return line, otherwise we return nothing as there's only 1 point
 	// If projection is roughly equal then return line, otherwise we return nothing as there's only 1 point
 	if (abs(proj_top - proj_bottom) < cCapsuleProjectionSlop * len)
 	if (abs(proj_top - proj_bottom) < cCapsuleProjectionSlop * len)
 	{
 	{
-		outVertices.push_back(support_top);
-		outVertices.push_back(support_bottom);
+		outVertices.push_back(inCenterOfMassTransform * support_top);
+		outVertices.push_back(inCenterOfMassTransform * support_bottom);
 	}
 	}
 }
 }
 
 

+ 3 - 3
Jolt/Physics/Collision/Shape/TaperedCapsuleShape.h

@@ -63,12 +63,12 @@ public:
 	// See Shape::GetSurfaceNormal
 	// See Shape::GetSurfaceNormal
 	virtual Vec3			GetSurfaceNormal(const SubShapeID &inSubShapeID, Vec3Arg inLocalSurfacePosition) const override;
 	virtual Vec3			GetSurfaceNormal(const SubShapeID &inSubShapeID, Vec3Arg inLocalSurfacePosition) const override;
 
 
+	// See Shape::GetSupportingFace
+	virtual void			GetSupportingFace(const SubShapeID &inSubShapeID, Vec3Arg inDirection, Vec3Arg inScale, Mat44Arg inCenterOfMassTransform, SupportingFace &outVertices) const override;
+
 	// See ConvexShape::GetSupportFunction
 	// See ConvexShape::GetSupportFunction
 	virtual const Support *	GetSupportFunction(ESupportMode inMode, SupportBuffer &inBuffer, Vec3Arg inScale) const override;
 	virtual const Support *	GetSupportFunction(ESupportMode inMode, SupportBuffer &inBuffer, Vec3Arg inScale) const override;
 
 
-	// See ConvexShape::GetSupportingFace
-	virtual void			GetSupportingFace(Vec3Arg inDirection, Vec3Arg inScale, SupportingFace &outVertices) const override;
-
 #ifdef JPH_DEBUG_RENDERER
 #ifdef JPH_DEBUG_RENDERER
 	// See Shape::Draw
 	// See Shape::Draw
 	virtual void			Draw(DebugRenderer *inRenderer, Mat44Arg inCenterOfMassTransform, Vec3Arg inScale, ColorArg inColor, bool inUseMaterialColors, bool inDrawWireframe) const override;
 	virtual void			Draw(DebugRenderer *inRenderer, Mat44Arg inCenterOfMassTransform, Vec3Arg inScale, ColorArg inColor, bool inUseMaterialColors, bool inDrawWireframe) const override;

+ 19 - 4
Jolt/Physics/Collision/Shape/TriangleShape.cpp

@@ -155,11 +155,26 @@ const ConvexShape::Support *TriangleShape::GetSupportFunction(ESupportMode inMod
 	return nullptr;
 	return nullptr;
 }
 }
 
 
-void TriangleShape::GetSupportingFace(Vec3Arg inDirection, Vec3Arg inScale, SupportingFace &outVertices) const
+void TriangleShape::GetSupportingFace(const SubShapeID &inSubShapeID, Vec3Arg inDirection, Vec3Arg inScale, Mat44Arg inCenterOfMassTransform, SupportingFace &outVertices) const
 {
 {
-	outVertices.push_back(inScale * mV1);
-	outVertices.push_back(inScale * mV2);
-	outVertices.push_back(inScale * mV3);
+	JPH_ASSERT(inSubShapeID.IsEmpty(), "Invalid subshape ID");
+
+	// Calculate transform with scale
+	Mat44 transform = inCenterOfMassTransform.PreScaled(inScale);
+
+	// Flip triangle if scaled inside out
+	if (ScaleHelpers::IsInsideOut(inScale))
+	{
+		outVertices.push_back(transform * mV1);
+		outVertices.push_back(transform * mV3);
+		outVertices.push_back(transform * mV2);
+	}
+	else
+	{
+		outVertices.push_back(transform * mV1);
+		outVertices.push_back(transform * mV2);
+		outVertices.push_back(transform * mV3);
+	}
 }
 }
 
 
 MassProperties TriangleShape::GetMassProperties() const
 MassProperties TriangleShape::GetMassProperties() const

+ 3 - 3
Jolt/Physics/Collision/Shape/TriangleShape.h

@@ -61,12 +61,12 @@ public:
 	// See Shape::GetSurfaceNormal
 	// See Shape::GetSurfaceNormal
 	virtual Vec3			GetSurfaceNormal(const SubShapeID &inSubShapeID, Vec3Arg inLocalSurfacePosition) const override;
 	virtual Vec3			GetSurfaceNormal(const SubShapeID &inSubShapeID, Vec3Arg inLocalSurfacePosition) const override;
 
 
+	// See Shape::GetSupportingFace
+	virtual void			GetSupportingFace(const SubShapeID &inSubShapeID, Vec3Arg inDirection, Vec3Arg inScale, Mat44Arg inCenterOfMassTransform, SupportingFace &outVertices) const override;
+
 	// See ConvexShape::GetSupportFunction
 	// See ConvexShape::GetSupportFunction
 	virtual const Support *	GetSupportFunction(ESupportMode inMode, SupportBuffer &inBuffer, Vec3Arg inScale) const override;
 	virtual const Support *	GetSupportFunction(ESupportMode inMode, SupportBuffer &inBuffer, Vec3Arg inScale) const override;
 
 
-	// See ConvexShape::GetSupportingFace
-	virtual void			GetSupportingFace(Vec3Arg inDirection, Vec3Arg inScale, SupportingFace &outVertices) const override;
-
 	// See Shape::GetSubmergedVolume
 	// See Shape::GetSubmergedVolume
 	virtual void			GetSubmergedVolume(Mat44Arg inCenterOfMassTransform, Vec3Arg inScale, const Plane &inSurface, float &outTotalVolume, float &outSubmergedVolume, Vec3 &outCenterOfBuoyancy) const override;
 	virtual void			GetSubmergedVolume(Mat44Arg inCenterOfMassTransform, Vec3Arg inScale, const Plane &inSurface, float &outTotalVolume, float &outSubmergedVolume, Vec3 &outCenterOfBuoyancy) const override;
 
 

+ 11 - 0
Jolt/Physics/Collision/TransformedShape.h

@@ -127,6 +127,17 @@ public:
 		return inv_com.Multiply3x3Transposed(mShape->GetSurfaceNormal(MakeSubShapeIDRelativeToShape(inSubShapeID), (inv_com * inPosition) / scale) / scale).Normalized();
 		return inv_com.Multiply3x3Transposed(mShape->GetSurfaceNormal(MakeSubShapeIDRelativeToShape(inSubShapeID), (inv_com * inPosition) / scale) / scale).Normalized();
 	}
 	}
 
 
+	/// Get the vertices of the face that faces inDirection the most (includes any convex radius). Note that this function can only return faces of
+	/// convex shapes or triangles, which is why a sub shape ID to get to that leaf must be provided. 
+	/// @param inSubShapeID Sub shape ID of target shape
+	/// @param inDirection Direction that the face should be facing (in world space)
+	/// @param outVertices Resulting face. Note the returned face can have a single point if the shape doesn't have polygons to return (e.g. because it's a sphere). The face will be returned in world space.
+	void						GetSupportingFace(const SubShapeID &inSubShapeID, Vec3Arg inDirection, Shape::SupportingFace &outVertices) const
+	{
+		Mat44 com = GetCenterOfMassTransform();
+		mShape->GetSupportingFace(MakeSubShapeIDRelativeToShape(inSubShapeID), com.Multiply3x3Transposed(inDirection), GetShapeScale(), com, outVertices);
+	}
+
 	/// Get material of a particular sub shape
 	/// Get material of a particular sub shape
 	inline const PhysicsMaterial *GetMaterial(const SubShapeID &inSubShapeID) const
 	inline const PhysicsMaterial *GetMaterial(const SubShapeID &inSubShapeID) const
 	{
 	{

+ 17 - 0
Samples/SamplesApp.cpp

@@ -450,6 +450,7 @@ SamplesApp::SamplesApp()
 			mDebugUI->CreateCheckBox(probe_options, "Treat Convex As Solid", mTreatConvexAsSolid, [this](UICheckBox::EState inState) { mTreatConvexAsSolid = inState == UICheckBox::STATE_CHECKED; });
 			mDebugUI->CreateCheckBox(probe_options, "Treat Convex As Solid", mTreatConvexAsSolid, [this](UICheckBox::EState inState) { mTreatConvexAsSolid = inState == UICheckBox::STATE_CHECKED; });
 			mDebugUI->CreateCheckBox(probe_options, "Return Deepest Point", mReturnDeepestPoint, [this](UICheckBox::EState inState) { mReturnDeepestPoint = inState == UICheckBox::STATE_CHECKED; });
 			mDebugUI->CreateCheckBox(probe_options, "Return Deepest Point", mReturnDeepestPoint, [this](UICheckBox::EState inState) { mReturnDeepestPoint = inState == UICheckBox::STATE_CHECKED; });
 			mDebugUI->CreateCheckBox(probe_options, "Shrunken Shape + Convex Radius", mUseShrunkenShapeAndConvexRadius, [this](UICheckBox::EState inState) { mUseShrunkenShapeAndConvexRadius = inState == UICheckBox::STATE_CHECKED; });
 			mDebugUI->CreateCheckBox(probe_options, "Shrunken Shape + Convex Radius", mUseShrunkenShapeAndConvexRadius, [this](UICheckBox::EState inState) { mUseShrunkenShapeAndConvexRadius = inState == UICheckBox::STATE_CHECKED; });
+			mDebugUI->CreateCheckBox(probe_options, "Draw Supporting Face", mDrawSupportingFace, [this](UICheckBox::EState inState) { mDrawSupportingFace = inState == UICheckBox::STATE_CHECKED; });
 			mDebugUI->CreateSlider(probe_options, "Max Hits", float(mMaxHits), 0, 10, 1, [this](float inValue) { mMaxHits = (int)inValue; });
 			mDebugUI->CreateSlider(probe_options, "Max Hits", float(mMaxHits), 0, 10, 1, [this](float inValue) { mMaxHits = (int)inValue; });
 			mDebugUI->ShowMenu(probe_options);
 			mDebugUI->ShowMenu(probe_options);
 		});
 		});
@@ -953,6 +954,14 @@ bool SamplesApp::CastProbe(float inProbeLength, float &outFraction, Vec3 &outPos
 					Vec3 perp2 = normal.Cross(perp1);
 					Vec3 perp2 = normal.Cross(perp1);
 					mDebugRenderer->DrawLine(outPosition - 0.1f * perp1, outPosition + 0.1f * perp1, color);
 					mDebugRenderer->DrawLine(outPosition - 0.1f * perp1, outPosition + 0.1f * perp1, color);
 					mDebugRenderer->DrawLine(outPosition - 0.1f * perp2, outPosition + 0.1f * perp2, color);
 					mDebugRenderer->DrawLine(outPosition - 0.1f * perp2, outPosition + 0.1f * perp2, color);
+
+					// Get and draw the result of GetSupportingFace
+					if (mDrawSupportingFace)
+					{
+						Shape::SupportingFace face;
+						hit_body.GetTransformedShape().GetSupportingFace(hit.mSubShapeID2, -normal, face);
+						mDebugRenderer->DrawWirePolygon(face, Color::sWhite, 0.01f);
+					}
 				}
 				}
 			}
 			}
 			else
 			else
@@ -1037,6 +1046,14 @@ bool SamplesApp::CastProbe(float inProbeLength, float &outFraction, Vec3 &outPos
 						Vec3 perp2 = normal.Cross(perp1);
 						Vec3 perp2 = normal.Cross(perp1);
 						mDebugRenderer->DrawLine(position - 0.1f * perp1, position + 0.1f * perp1, color);
 						mDebugRenderer->DrawLine(position - 0.1f * perp1, position + 0.1f * perp1, color);
 						mDebugRenderer->DrawLine(position - 0.1f * perp2, position + 0.1f * perp2, color);
 						mDebugRenderer->DrawLine(position - 0.1f * perp2, position + 0.1f * perp2, color);
+
+						// Get and draw the result of GetSupportingFace
+						if (mDrawSupportingFace)
+						{
+							Shape::SupportingFace face;
+							hit_body.GetTransformedShape().GetSupportingFace(hit.mSubShapeID2, -normal, face);
+							mDebugRenderer->DrawWirePolygon(face, Color::sWhite, 0.01f);
+						}
 					}
 					}
 				}
 				}
 
 

+ 1 - 0
Samples/SamplesApp.h

@@ -188,6 +188,7 @@ private:
 	bool					mTreatConvexAsSolid = true;									// For ray casts if the shape should be treated as solid or if the ray should only collide with the surface
 	bool					mTreatConvexAsSolid = true;									// For ray casts if the shape should be treated as solid or if the ray should only collide with the surface
 	bool					mReturnDeepestPoint = true;									// For shape casts, when true this will return the deepest point
 	bool					mReturnDeepestPoint = true;									// For shape casts, when true this will return the deepest point
 	bool					mUseShrunkenShapeAndConvexRadius = false;					// Shrink then expand the shape by the convex radius
 	bool					mUseShrunkenShapeAndConvexRadius = false;					// Shrink then expand the shape by the convex radius
+	bool					mDrawSupportingFace = false;								// Draw the result of GetSupportingFace
 	int						mMaxHits = 10;												// The maximum number of hits to request for a collision probe.
 	int						mMaxHits = 10;												// The maximum number of hits to request for a collision probe.
 
 
 	// Which object to shoot
 	// Which object to shoot