浏览代码

Removed RTTI from shapes and shape type a member to eventually make it possible to remove vfptr table and blit a shape into memory (#13)

jrouwe 4 年之前
父节点
当前提交
6d5cafd535
共有 41 个文件被更改,包括 575 次插入534 次删除
  1. 1 40
      Jolt/Physics/Body/BodyManager.cpp
  2. 2 133
      Jolt/Physics/Collision/CollisionDispatch.cpp
  3. 29 2
      Jolt/Physics/Collision/CollisionDispatch.h
  4. 8 6
      Jolt/Physics/Collision/Shape/BoxShape.cpp
  5. 5 4
      Jolt/Physics/Collision/Shape/BoxShape.h
  6. 8 6
      Jolt/Physics/Collision/Shape/CapsuleShape.cpp
  7. 5 4
      Jolt/Physics/Collision/Shape/CapsuleShape.h
  8. 8 7
      Jolt/Physics/Collision/Shape/CompoundShape.cpp
  9. 9 15
      Jolt/Physics/Collision/Shape/CompoundShape.h
  10. 8 6
      Jolt/Physics/Collision/Shape/ConvexHullShape.cpp
  11. 4 3
      Jolt/Physics/Collision/Shape/ConvexHullShape.h
  12. 32 14
      Jolt/Physics/Collision/Shape/ConvexShape.cpp
  13. 11 12
      Jolt/Physics/Collision/Shape/ConvexShape.h
  14. 9 7
      Jolt/Physics/Collision/Shape/CylinderShape.cpp
  15. 4 3
      Jolt/Physics/Collision/Shape/CylinderShape.h
  16. 2 7
      Jolt/Physics/Collision/Shape/DecoratedShape.cpp
  17. 5 7
      Jolt/Physics/Collision/Shape/DecoratedShape.h
  18. 22 10
      Jolt/Physics/Collision/Shape/HeightFieldShape.cpp
  19. 7 9
      Jolt/Physics/Collision/Shape/HeightFieldShape.h
  20. 22 10
      Jolt/Physics/Collision/Shape/MeshShape.cpp
  21. 7 9
      Jolt/Physics/Collision/Shape/MeshShape.h
  22. 26 12
      Jolt/Physics/Collision/Shape/MutableCompoundShape.cpp
  23. 10 12
      Jolt/Physics/Collision/Shape/MutableCompoundShape.h
  24. 28 12
      Jolt/Physics/Collision/Shape/OffsetCenterOfMassShape.cpp
  25. 11 24
      Jolt/Physics/Collision/Shape/OffsetCenterOfMassShape.h
  26. 30 14
      Jolt/Physics/Collision/Shape/RotatedTranslatedShape.cpp
  27. 9 22
      Jolt/Physics/Collision/Shape/RotatedTranslatedShape.h
  28. 43 6
      Jolt/Physics/Collision/Shape/ScaledShape.cpp
  29. 13 7
      Jolt/Physics/Collision/Shape/ScaledShape.h
  30. 6 16
      Jolt/Physics/Collision/Shape/Shape.cpp
  31. 80 14
      Jolt/Physics/Collision/Shape/Shape.h
  32. 8 6
      Jolt/Physics/Collision/Shape/SphereShape.cpp
  33. 5 4
      Jolt/Physics/Collision/Shape/SphereShape.h
  34. 26 12
      Jolt/Physics/Collision/Shape/StaticCompoundShape.cpp
  35. 8 10
      Jolt/Physics/Collision/Shape/StaticCompoundShape.h
  36. 8 6
      Jolt/Physics/Collision/Shape/TaperedCapsuleShape.cpp
  37. 4 3
      Jolt/Physics/Collision/Shape/TaperedCapsuleShape.h
  38. 8 6
      Jolt/Physics/Collision/Shape/TriangleShape.cpp
  39. 5 4
      Jolt/Physics/Collision/Shape/TriangleShape.h
  40. 38 30
      Jolt/RegisterTypes.cpp
  41. 1 0
      UnitTests/Physics/ShapeTests.cpp

+ 1 - 40
Jolt/Physics/Body/BodyManager.cpp

@@ -549,46 +549,7 @@ void BodyManager::Draw(const DrawSettings &inDrawSettings, const PhysicsSettings
 					break;
 
 				case EShapeColor::ShapeTypeColor:
-					// Each shape type has own color
-					switch (body->GetShape()->GetType())
-					{
-					case EShapeType::Convex:
-						color = Color::sGreen;
-						break;
-
-					case EShapeType::Scaled:
-						color = Color::sYellow;
-						break;
-
-					case EShapeType::StaticCompound:
-						color = Color::sOrange;
-						break;
-
-					case EShapeType::MutableCompound:
-						color = Color::sDarkOrange;
-						break;
-
-					case EShapeType::Mesh:
-						color = Color::sRed;
-						break;
-
-					case EShapeType::HeightField:
-						color = Color::sPurple;
-						break;
-
-					case EShapeType::RotatedTranslated:
-						color = Color::sBlue;
-						break;
-
-					case EShapeType::OffsetCenterOfMass:
-						color = Color::sCyan;
-						break;
-
-					default:
-						JPH_ASSERT(false);
-						color = Color::sBlack;
-						break;
-					}
+					color = ShapeFunctions::sGet(body->GetShape()->GetSubType()).mColor;
 					break;
 
 				case EShapeColor::MotionTypeColor:

+ 2 - 133
Jolt/Physics/Collision/CollisionDispatch.cpp

@@ -4,141 +4,10 @@
 #include <Jolt.h>
 
 #include <Physics/Collision/CollisionDispatch.h>
-#include <Physics/Collision/Shape/StaticCompoundShape.h>
-#include <Physics/Collision/Shape/MutableCompoundShape.h>
-#include <Physics/Collision/Shape/ConvexShape.h>
-#include <Physics/Collision/Shape/MeshShape.h>
-#include <Physics/Collision/Shape/HeightFieldShape.h>
-#include <Physics/Collision/Shape/ScaledShape.h>
-#include <Physics/Collision/Shape/RotatedTranslatedShape.h>
-#include <Physics/Collision/Shape/OffsetCenterOfMassShape.h>
-#include <Physics/Collision/RayCast.h>
-#include <Physics/Collision/ShapeCast.h>
-#include <Physics/Collision/CastResult.h>
-#include <Physics/Collision/ShapeFilter.h>
 
 namespace JPH {
 
-void CollisionDispatch::sCollideShapeVsShape(const Shape *inShape1, const Shape *inShape2, Vec3Arg inScale1, Vec3Arg inScale2, Mat44Arg inCenterOfMassTransform1, Mat44Arg inCenterOfMassTransform2, const SubShapeIDCreator &inSubShapeIDCreator1, const SubShapeIDCreator &inSubShapeIDCreator2, const CollideShapeSettings &inCollideShapeSettings, CollideShapeCollector &ioCollector)
-{
-	switch (inShape1->GetType())
-	{
-	case EShapeType::Convex:
-		switch (inShape2->GetType())
-		{
-		case EShapeType::Convex:
-			ConvexShape::sCollideConvexVsConvex(static_cast<const ConvexShape *>(inShape1), static_cast<const ConvexShape *>(inShape2), inScale1, inScale2, inCenterOfMassTransform1, inCenterOfMassTransform2, inSubShapeIDCreator1, inSubShapeIDCreator2, inCollideShapeSettings, ioCollector);
-			break;
-
-		case EShapeType::Mesh:
-			MeshShape::sCollideConvexVsMesh(static_cast<const ConvexShape *>(inShape1), static_cast<const MeshShape *>(inShape2), inScale1, inScale2, inCenterOfMassTransform1, inCenterOfMassTransform2, inSubShapeIDCreator1, inSubShapeIDCreator2, inCollideShapeSettings, ioCollector);
-			break;
-
-		case EShapeType::HeightField:
-			HeightFieldShape::sCollideConvexVsHeightField(static_cast<const ConvexShape *>(inShape1), static_cast<const HeightFieldShape *>(inShape2), inScale1, inScale2, inCenterOfMassTransform1, inCenterOfMassTransform2, inSubShapeIDCreator1, inSubShapeIDCreator2, inCollideShapeSettings, ioCollector);
-			break;
-
-		case EShapeType::StaticCompound:
-			StaticCompoundShape::sCollideShapeVsCompound(inShape1, static_cast<const StaticCompoundShape *>(inShape2), inScale1, inScale2, inCenterOfMassTransform1, inCenterOfMassTransform2, inSubShapeIDCreator1, inSubShapeIDCreator2, inCollideShapeSettings, ioCollector);
-			break;
-
-		case EShapeType::MutableCompound:
-			MutableCompoundShape::sCollideShapeVsCompound(inShape1, static_cast<const MutableCompoundShape *>(inShape2), inScale1, inScale2, inCenterOfMassTransform1, inCenterOfMassTransform2, inSubShapeIDCreator1, inSubShapeIDCreator2, inCollideShapeSettings, ioCollector);
-			break;
-
-		case EShapeType::Scaled:
-			{
-				const ScaledShape *scaled_shape2 = static_cast<const ScaledShape *>(inShape2);
-				CollisionDispatch::sCollideShapeVsShape(inShape1, scaled_shape2->GetInnerShape(), inScale1, inScale2 * scaled_shape2->GetScale(), inCenterOfMassTransform1, inCenterOfMassTransform2, inSubShapeIDCreator1, inSubShapeIDCreator2, inCollideShapeSettings, ioCollector);
-			}
-			break;
-
-		case EShapeType::RotatedTranslated:
-			RotatedTranslatedShape::sCollideShapeVsRotatedTranslated(inShape1, static_cast<const RotatedTranslatedShape *>(inShape2), inScale1, inScale2, inCenterOfMassTransform1, inCenterOfMassTransform2, inSubShapeIDCreator1, inSubShapeIDCreator2, inCollideShapeSettings, ioCollector);
-			break;
-
-		case EShapeType::OffsetCenterOfMass:
-			OffsetCenterOfMassShape::sCollideShapeVsOffsetCenterOfMassShape(inShape1, static_cast<const OffsetCenterOfMassShape *>(inShape2), inScale1, inScale2, inCenterOfMassTransform1, inCenterOfMassTransform2, inSubShapeIDCreator1, inSubShapeIDCreator2, inCollideShapeSettings, ioCollector);
-			break;
-		}
-		break;
-
-	case EShapeType::Mesh:
-	case EShapeType::HeightField:
-		JPH_ASSERT(false, "Mesh / height field shapes cannot be dynamic, ignoring!");
-		break;
-
-	case EShapeType::StaticCompound:
-		StaticCompoundShape::sCollideCompoundVsShape(static_cast<const StaticCompoundShape *>(inShape1), inShape2, inScale1, inScale2, inCenterOfMassTransform1, inCenterOfMassTransform2, inSubShapeIDCreator1, inSubShapeIDCreator2, inCollideShapeSettings, ioCollector);
-		break;
-
-	case EShapeType::MutableCompound:
-		MutableCompoundShape::sCollideCompoundVsShape(static_cast<const MutableCompoundShape *>(inShape1), inShape2, inScale1, inScale2, inCenterOfMassTransform1, inCenterOfMassTransform2, inSubShapeIDCreator1, inSubShapeIDCreator2, inCollideShapeSettings, ioCollector);
-		break;
-
-	case EShapeType::Scaled:
-		{
-			const ScaledShape *scaled_shape1 = static_cast<const ScaledShape *>(inShape1);
-			CollisionDispatch::sCollideShapeVsShape(scaled_shape1->GetInnerShape(), inShape2, inScale1 * scaled_shape1->GetScale(), inScale2, inCenterOfMassTransform1, inCenterOfMassTransform2, inSubShapeIDCreator1, inSubShapeIDCreator2, inCollideShapeSettings, ioCollector);
-		}
-		break;
-
-	case EShapeType::RotatedTranslated:
-		RotatedTranslatedShape::sCollideRotatedTranslatedVsShape(static_cast<const RotatedTranslatedShape *>(inShape1), inShape2, inScale1, inScale2, inCenterOfMassTransform1, inCenterOfMassTransform2, inSubShapeIDCreator1, inSubShapeIDCreator2, inCollideShapeSettings, ioCollector);
-		break;
-
-	case EShapeType::OffsetCenterOfMass:
-		OffsetCenterOfMassShape::sCollideOffsetCenterOfMassShapeVsShape(static_cast<const OffsetCenterOfMassShape *>(inShape1), inShape2, inScale1, inScale2, inCenterOfMassTransform1, inCenterOfMassTransform2, inSubShapeIDCreator1, inSubShapeIDCreator2, inCollideShapeSettings, ioCollector);
-		break;
-
-	default:
-		JPH_ASSERT(false);
-		break;
-	}
-}
-
-void CollisionDispatch::sCastShapeVsShape(const ShapeCast &inShapeCast, const ShapeCastSettings &inShapeCastSettings, const Shape *inShape, Vec3Arg inScale, const ShapeFilter &inShapeFilter, Mat44Arg inCenterOfMassTransform2, const SubShapeIDCreator &inSubShapeIDCreator1, const SubShapeIDCreator &inSubShapeIDCreator2, CastShapeCollector &ioCollector)
-{
-	// Only test shape if it passes the shape filter
-	if (!inShapeFilter.ShouldCollide(inSubShapeIDCreator1.GetID(), inSubShapeIDCreator2.GetID()))
-		return;
-
-	switch (inShapeCast.mShape->GetType())
-	{
-	case EShapeType::StaticCompound:
-	case EShapeType::MutableCompound:
-		CompoundShape::sCastCompoundShapeVsShape(inShapeCast, inShapeCastSettings, inShape, inScale, inShapeFilter, inCenterOfMassTransform2, inSubShapeIDCreator1, inSubShapeIDCreator2, ioCollector);
-		break;
-
-	case EShapeType::Convex:
-		inShape->CastShape(inShapeCast, inShapeCastSettings, inScale, inShapeFilter, inCenterOfMassTransform2, inSubShapeIDCreator1, inSubShapeIDCreator2, ioCollector);
-		break;
-
-	case EShapeType::Mesh:
-	case EShapeType::HeightField:
-		JPH_ASSERT(false, "Cannot cast a mesh / height field, ignoring!");
-		break;
-
-	case EShapeType::Scaled:
-		{
-			const ScaledShape *scaled_shape = static_cast<const ScaledShape *>(inShapeCast.mShape.GetPtr());
-			ShapeCast scaled_cast(scaled_shape->GetInnerShape(), inShapeCast.mScale * scaled_shape->GetScale(), inShapeCast.mCenterOfMassStart, inShapeCast.mDirection);
-			CollisionDispatch::sCastShapeVsShape(scaled_cast, inShapeCastSettings, inShape, inScale, inShapeFilter, inCenterOfMassTransform2, inSubShapeIDCreator1, inSubShapeIDCreator2, ioCollector);
-		}
-		break;
-
-	case EShapeType::RotatedTranslated:
-		RotatedTranslatedShape::sCastRotatedTranslatedShapeVsShape(inShapeCast, inShapeCastSettings, inShape, inScale, inShapeFilter, inCenterOfMassTransform2, inSubShapeIDCreator1, inSubShapeIDCreator2, ioCollector);
-		break;
-
-	case EShapeType::OffsetCenterOfMass:
-		OffsetCenterOfMassShape::sCastOffsetCenterOfMassShapeVsShape(inShapeCast, inShapeCastSettings, inShape, inScale, inShapeFilter, inCenterOfMassTransform2, inSubShapeIDCreator1, inSubShapeIDCreator2, ioCollector);
-		break;
-
-	default:
-		JPH_ASSERT(false);
-		break;
-	}
-}
+CollisionDispatch::CollideShape CollisionDispatch::sCollideShape[NumSubShapeTypes][NumSubShapeTypes];
+CollisionDispatch::CastShape CollisionDispatch::sCastShape[NumSubShapeTypes];
 
 } // JPH

+ 29 - 2
Jolt/Physics/Collision/CollisionDispatch.h

@@ -4,6 +4,9 @@
 #pragma once
 
 #include <Physics/Collision/Shape/Shape.h>
+#include <Physics/Collision/Shape/SubShapeID.h>
+#include <Physics/Collision/ShapeCast.h>
+#include <Physics/Collision/ShapeFilter.h>
 
 namespace JPH {
 
@@ -24,7 +27,10 @@ public:
 	/// @param inSubShapeIDCreator2 Class that tracks the current sub shape ID for shape 2
 	/// @param inCollideShapeSettings Options for the CollideShape test
 	/// @param ioCollector The collector that receives the results.
-	static void				sCollideShapeVsShape(const Shape *inShape1, const Shape *inShape2, Vec3Arg inScale1, Vec3Arg inScale2, Mat44Arg inCenterOfMassTransform1, Mat44Arg inCenterOfMassTransform2, const SubShapeIDCreator &inSubShapeIDCreator1, const SubShapeIDCreator &inSubShapeIDCreator2, const CollideShapeSettings &inCollideShapeSettings, CollideShapeCollector &ioCollector);
+	static inline void		sCollideShapeVsShape(const Shape *inShape1, const Shape *inShape2, Vec3Arg inScale1, Vec3Arg inScale2, Mat44Arg inCenterOfMassTransform1, Mat44Arg inCenterOfMassTransform2, const SubShapeIDCreator &inSubShapeIDCreator1, const SubShapeIDCreator &inSubShapeIDCreator2, const CollideShapeSettings &inCollideShapeSettings, CollideShapeCollector &ioCollector)
+	{
+		sCollideShape[(int)inShape1->GetSubType()][(int)inShape2->GetSubType()](inShape1, inShape2, inScale1, inScale2, inCenterOfMassTransform1, inCenterOfMassTransform2, inSubShapeIDCreator1, inSubShapeIDCreator2, inCollideShapeSettings, ioCollector);
+	}
 
 	/// Cast a shape againt this shape, passes any hits found to ioCollector.
 	/// @param inShapeCast The shape to cast against the other shape and its start and direction
@@ -36,7 +42,28 @@ public:
 	/// @param inSubShapeIDCreator1 Class that tracks the current sub shape ID for the casting shape
 	/// @param inSubShapeIDCreator2 Class that tracks the current sub shape ID for the shape we're casting against
 	/// @param ioCollector The collector that receives the results.
-	static void				sCastShapeVsShape(const ShapeCast &inShapeCast, const ShapeCastSettings &inShapeCastSettings, const Shape *inShape, Vec3Arg inScale, const ShapeFilter &inShapeFilter, Mat44Arg inCenterOfMassTransform2, const SubShapeIDCreator &inSubShapeIDCreator1, const SubShapeIDCreator &inSubShapeIDCreator2, CastShapeCollector &ioCollector);
+	static inline void		sCastShapeVsShape(const ShapeCast &inShapeCast, const ShapeCastSettings &inShapeCastSettings, const Shape *inShape, Vec3Arg inScale, const ShapeFilter &inShapeFilter, Mat44Arg inCenterOfMassTransform2, const SubShapeIDCreator &inSubShapeIDCreator1, const SubShapeIDCreator &inSubShapeIDCreator2, CastShapeCollector &ioCollector)
+	{
+		// Only test shape if it passes the shape filter
+		if (inShapeFilter.ShouldCollide(inSubShapeIDCreator1.GetID(), inSubShapeIDCreator2.GetID()))
+			sCastShape[(int)inShapeCast.mShape->GetSubType()](inShapeCast, inShapeCastSettings, inShape, inScale, inShapeFilter, inCenterOfMassTransform2, inSubShapeIDCreator1, inSubShapeIDCreator2, ioCollector);
+	}
+
+	/// Function that collides 2 shapes (see sCollideShapeVsShape) 
+	using CollideShape = void (*)(const Shape *inShape1, const Shape *inShape2, Vec3Arg inScale1, Vec3Arg inScale2, Mat44Arg inCenterOfMassTransform1, Mat44Arg inCenterOfMassTransform2, const SubShapeIDCreator &inSubShapeIDCreator1, const SubShapeIDCreator &inSubShapeIDCreator2, const CollideShapeSettings &inCollideShapeSettings, CollideShapeCollector &ioCollector);
+
+	/// Function that casts a shape vs another shape (see sCastShapeVsShape)
+	using CastShape = void (*)(const ShapeCast &inShapeCast, const ShapeCastSettings &inShapeCastSettings, const Shape *inShape, Vec3Arg inScale, const ShapeFilter &inShapeFilter, Mat44Arg inCenterOfMassTransform2, const SubShapeIDCreator &inSubShapeIDCreator1, const SubShapeIDCreator &inSubShapeIDCreator2, CastShapeCollector &ioCollector);
+
+	/// Register a collide shape function in the collision table
+	static void				sRegisterCollideShape(EShapeSubType inType1, EShapeSubType inType2, CollideShape inFunction)	{ sCollideShape[(int)inType1][(int)inType2] = inFunction; }
+
+	/// Register a cast shape function in the collision table
+	static void				sRegisterCastShape(EShapeSubType inType1, CastShape inFunction)									{ sCastShape[(int)inType1] = inFunction; }
+
+private:
+	static CollideShape		sCollideShape[NumSubShapeTypes][NumSubShapeTypes];
+	static CastShape		sCastShape[NumSubShapeTypes];
 };
 
 } // JPH

+ 8 - 6
Jolt/Physics/Collision/Shape/BoxShape.cpp

@@ -28,11 +28,6 @@ JPH_IMPLEMENT_SERIALIZABLE_VIRTUAL(BoxShapeSettings)
 	JPH_ADD_ATTRIBUTE(BoxShapeSettings, mConvexRadius)
 }
 
-JPH_IMPLEMENT_RTTI_VIRTUAL(BoxShape)
-{
-	JPH_ADD_BASE_CLASS(BoxShape, ConvexShape)
-}
-
 static const Vec3 sUnitBoxTriangles[] = {
 	Vec3(-1, 1, -1),	Vec3(-1, 1, 1),		Vec3(1, 1, 1),
 	Vec3(-1, 1, -1),	Vec3(1, 1, 1),		Vec3(1, 1, -1),
@@ -56,7 +51,7 @@ ShapeSettings::ShapeResult BoxShapeSettings::Create() const
 }
 
 BoxShape::BoxShape(const BoxShapeSettings &inSettings, ShapeResult &outResult) : 
-	ConvexShape(inSettings, outResult), 
+	ConvexShape(EShapeSubType::Box, inSettings, outResult), 
 	mHalfExtent(inSettings.mHalfExtent), 
 	mConvexRadius(inSettings.mConvexRadius) 
 { 
@@ -239,4 +234,11 @@ void BoxShape::RestoreBinaryState(StreamIn &inStream)
 	inStream.Read(mConvexRadius);
 }
 
+void BoxShape::sRegister()
+{
+	ShapeFunctions &f = ShapeFunctions::sGet(EShapeSubType::Box);
+	f.mConstruct = []() -> Shape * { return new BoxShape; };
+	f.mColor = Color::sGreen;
+}
+
 } // JPH

+ 5 - 4
Jolt/Physics/Collision/Shape/BoxShape.h

@@ -32,15 +32,13 @@ public:
 class BoxShape final : public ConvexShape
 {
 public:
-	JPH_DECLARE_RTTI_VIRTUAL(BoxShape)
-
 	/// Constructor
-							BoxShape() = default;
+							BoxShape() : ConvexShape(EShapeSubType::Box) { }
 							BoxShape(const BoxShapeSettings &inSettings, ShapeResult &outResult);
 
 	/// Create a box with half edge length inHalfExtent and convex radius inConvexRadius.
 	/// (internally the convex radius will be subtracted from the half extent so the total box will not grow with the convex radius).
-							BoxShape(Vec3Arg inHalfExtent, float inConvexRadius = cDefaultConvexRadius, const PhysicsMaterial *inMaterial = nullptr) : ConvexShape(inMaterial), mHalfExtent(inHalfExtent), mConvexRadius(inConvexRadius) { JPH_ASSERT(inConvexRadius >= 0.0f); JPH_ASSERT(inHalfExtent.ReduceMin() >= inConvexRadius); }
+							BoxShape(Vec3Arg inHalfExtent, float inConvexRadius = cDefaultConvexRadius, const PhysicsMaterial *inMaterial = nullptr) : ConvexShape(EShapeSubType::Box, inMaterial), mHalfExtent(inHalfExtent), mConvexRadius(inConvexRadius) { JPH_ASSERT(inConvexRadius >= 0.0f); JPH_ASSERT(inHalfExtent.ReduceMin() >= inConvexRadius); }
 
 	/// Get half extent of box
 	Vec3		 			GetHalfExtent() const										{ return mHalfExtent; }
@@ -90,6 +88,9 @@ public:
 	// See Shape::GetVolume
 	virtual float			GetVolume() const override									{ return GetLocalBounds().GetVolume(); }
 
+	// Register shape functions with the registry
+	static void				sRegister();
+
 protected:
 	// See: Shape::RestoreBinaryState
 	virtual void			RestoreBinaryState(StreamIn &inStream) override;

+ 8 - 6
Jolt/Physics/Collision/Shape/CapsuleShape.cpp

@@ -29,11 +29,6 @@ JPH_IMPLEMENT_SERIALIZABLE_VIRTUAL(CapsuleShapeSettings)
 	JPH_ADD_ATTRIBUTE(CapsuleShapeSettings, mHalfHeightOfCylinder)
 }
 
-JPH_IMPLEMENT_RTTI_VIRTUAL(CapsuleShape)
-{
-	JPH_ADD_BASE_CLASS(CapsuleShape, ConvexShape)
-}
-
 static const int cCapsuleDetailLevel = 2;
 
 static const vector<Vec3> sCapsuleTopTriangles = []() { 
@@ -72,7 +67,7 @@ ShapeSettings::ShapeResult CapsuleShapeSettings::Create() const
 }
 
 CapsuleShape::CapsuleShape(const CapsuleShapeSettings &inSettings, ShapeResult &outResult) : 
-	ConvexShape(inSettings, outResult), 
+	ConvexShape(EShapeSubType::Capsule, inSettings, outResult), 
 	mRadius(inSettings.mRadius), 
 	mHalfHeightOfCylinder(inSettings.mHalfHeightOfCylinder) 
 { 
@@ -376,4 +371,11 @@ bool CapsuleShape::IsValidScale(Vec3Arg inScale) const
 	return ConvexShape::IsValidScale(inScale) && ScaleHelpers::IsUniformScale(inScale.Abs());
 }
 
+void CapsuleShape::sRegister()
+{
+	ShapeFunctions &f = ShapeFunctions::sGet(EShapeSubType::Capsule);
+	f.mConstruct = []() -> Shape * { return new CapsuleShape; };
+	f.mColor = Color::sGreen;
+}
+
 } // JPH

+ 5 - 4
Jolt/Physics/Collision/Shape/CapsuleShape.h

@@ -35,14 +35,12 @@ class CapsuleShapeSettings final : public ConvexShapeSettings
 class CapsuleShape final : public ConvexShape
 {
 public:
-	JPH_DECLARE_RTTI_VIRTUAL(CapsuleShape)
-
 	/// Constructor
-							CapsuleShape() = default;
+							CapsuleShape() : ConvexShape(EShapeSubType::Capsule) { }
 							CapsuleShape(const CapsuleShapeSettings &inSettings, ShapeResult &outResult);
 
 	/// Create a capsule centered around the origin with one sphere cap at (0, -inHalfHeightOfCylinder, 0) and the other at (0, inHalfHeightOfCylinder, 0)
-							CapsuleShape(float inHalfHeightOfCylinder, float inRadius, const PhysicsMaterial *inMaterial = nullptr) : ConvexShape(inMaterial), mRadius(inRadius), mHalfHeightOfCylinder(inHalfHeightOfCylinder) { JPH_ASSERT(inHalfHeightOfCylinder > 0.0f); JPH_ASSERT(inRadius > 0.0f); }
+							CapsuleShape(float inHalfHeightOfCylinder, float inRadius, const PhysicsMaterial *inMaterial = nullptr) : ConvexShape(EShapeSubType::Capsule, inMaterial), mRadius(inRadius), mHalfHeightOfCylinder(inHalfHeightOfCylinder) { JPH_ASSERT(inHalfHeightOfCylinder > 0.0f); JPH_ASSERT(inRadius > 0.0f); }
 
 	/// Radius of the cylinder
 	float					GetRadius() const														{ return mRadius; }
@@ -103,6 +101,9 @@ public:
 	// See Shape::IsValidScale
 	virtual bool			IsValidScale(Vec3Arg inScale) const override;
 
+	// Register shape functions with the registry
+	static void				sRegister();
+
 protected:
 	// See: Shape::RestoreBinaryState
 	virtual void			RestoreBinaryState(StreamIn &inStream) override;

+ 8 - 7
Jolt/Physics/Collision/Shape/CompoundShape.cpp

@@ -33,11 +33,6 @@ JPH_IMPLEMENT_SERIALIZABLE_NON_VIRTUAL(CompoundShapeSettings::SubShapeSettings)
 	JPH_ADD_ATTRIBUTE(CompoundShapeSettings::SubShapeSettings, mUserData)
 }
 
-JPH_IMPLEMENT_RTTI_ABSTRACT(CompoundShape)
-{
-	JPH_ADD_BASE_CLASS(CompoundShape, Shape)
-}
-
 void CompoundShapeSettings::AddShape(Vec3Arg inPosition, QuatArg inRotation, const ShapeSettings *inShape, uint32 inUserData)
 {
 	// Add shape
@@ -242,12 +237,12 @@ void CompoundShape::TransformShape(Mat44Arg inCenterOfMassTransform, Transformed
 		shape.mShape->TransformShape(inCenterOfMassTransform * Mat44::sRotationTranslation(shape.GetRotation(), shape.GetPositionCOM()), ioCollector);
 }
 
-void CompoundShape::sCastCompoundShapeVsShape(const ShapeCast &inShapeCast, const ShapeCastSettings &inShapeCastSettings, const Shape *inShape, Vec3Arg inScale, const ShapeFilter &inShapeFilter, Mat44Arg inCenterOfMassTransform2, const SubShapeIDCreator &inSubShapeIDCreator1, const SubShapeIDCreator &inSubShapeIDCreator2, CastShapeCollector &ioCollector)
+void CompoundShape::sCastCompoundVsShape(const ShapeCast &inShapeCast, const ShapeCastSettings &inShapeCastSettings, const Shape *inShape, Vec3Arg inScale, const ShapeFilter &inShapeFilter, Mat44Arg inCenterOfMassTransform2, const SubShapeIDCreator &inSubShapeIDCreator1, const SubShapeIDCreator &inSubShapeIDCreator2, CastShapeCollector &ioCollector)
 {
 	JPH_PROFILE_FUNCTION();
 
 	// Fetch compound shape from cast shape
-	JPH_ASSERT(inShapeCast.mShape->GetType() == EShapeType::StaticCompound || inShapeCast.mShape->GetType() == EShapeType::MutableCompound);
+	JPH_ASSERT(inShapeCast.mShape->GetType() == EShapeType::Compound);
 	const CompoundShape *compound = static_cast<const CompoundShape *>(inShapeCast.mShape.GetPtr());
 
 	// Number of sub shapes
@@ -380,4 +375,10 @@ bool CompoundShape::IsValidScale(Vec3Arg inScale) const
 	return true;
 }
 
+void CompoundShape::sRegister()
+{
+	for (EShapeSubType s : sCompoundSubShapeTypes)
+		CollisionDispatch::sRegisterCastShape(s, sCastCompoundVsShape);
+}
+
 } // JPH

+ 9 - 15
Jolt/Physics/Collision/Shape/CompoundShape.h

@@ -47,10 +47,9 @@ public:
 class CompoundShape : public Shape
 {
 public:
-	JPH_DECLARE_RTTI_ABSTRACT(CompoundShape)
-
 	/// Constructor
-	using Shape::Shape;
+	explicit						CompoundShape(EShapeSubType inSubType) : Shape(EShapeType::Compound, inSubType) { }
+									CompoundShape(EShapeSubType inSubType, const ShapeSettings &inSettings, ShapeResult &outResult) : Shape(EShapeType::Compound, inSubType, inSettings, outResult) { }
 
 	// See Shape::GetCenterOfMass
 	virtual Vec3					GetCenterOfMass() const override						{ return mCenterOfMass; }
@@ -122,18 +121,6 @@ public:
 	/// @return How many indices were placed in outSubShapeIndices
 	virtual int						GetIntersectingSubShapes(const OrientedBox &inBox, uint *outSubShapeIndices, int inMaxSubShapeIndices) const = 0;
 
-	/// Cast a compound shape againt a shape, reports hits to ioCollector
-	/// @param inShapeCast The shape to cast against the other shape and its start and direction
-	/// @param inShapeCastSettings Settings for performing the cast
-	/// @param inShape The shape to cast against.
-	/// @param inScale Local space scale for the shape to cast against.
-	/// @param inShapeFilter Determines if sub shapes of the shape can collide
-	/// @param inCenterOfMassTransform2 Is the center of mass transform of shape 2 (excluding scale), this is used to provide a transform to the shape cast result so that local quantities can be transformed into world space.
-	/// @param inSubShapeIDCreator1 Class that tracks the current sub shape ID for the casting shape
-	/// @param inSubShapeIDCreator2 Class that tracks the current sub shape ID for the shape we're casting against
-	/// @param ioCollector The collector that receives the results.
-	static void						sCastCompoundShapeVsShape(const ShapeCast &inShapeCast, const ShapeCastSettings &inShapeCastSettings, const Shape *inShape, Vec3Arg inScale, const ShapeFilter &inShapeFilter, Mat44Arg inCenterOfMassTransform2, const SubShapeIDCreator &inSubShapeIDCreator1, const SubShapeIDCreator &inSubShapeIDCreator2, CastShapeCollector &ioCollector);
-
 	struct SubShape
 	{
 		/// Initialize sub shape from sub shape settings
@@ -301,6 +288,9 @@ public:
 	// See Shape::IsValidScale
 	virtual bool					IsValidScale(Vec3Arg inScale) const override;
 
+	// Register shape functions with the registry
+	static void						sRegister();
+
 protected:
 	// See: Shape::RestoreBinaryState
 	virtual void					RestoreBinaryState(StreamIn &inStream) override;
@@ -335,6 +325,10 @@ protected:
 	AABox							mLocalBounds;
 	SubShapes						mSubShapes;
 	float							mInnerRadius = FLT_MAX;									///< Smallest radius of GetInnerRadius() of child shapes
+
+private:
+	// Helper functions called by CollisionDispatch
+	static void						sCastCompoundVsShape(const ShapeCast &inShapeCast, const ShapeCastSettings &inShapeCastSettings, const Shape *inShape, Vec3Arg inScale, const ShapeFilter &inShapeFilter, Mat44Arg inCenterOfMassTransform2, const SubShapeIDCreator &inSubShapeIDCreator1, const SubShapeIDCreator &inSubShapeIDCreator2, CastShapeCollector &ioCollector);
 };
 
 } // JPH

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

@@ -30,11 +30,6 @@ JPH_IMPLEMENT_SERIALIZABLE_VIRTUAL(ConvexHullShapeSettings)
 	JPH_ADD_ATTRIBUTE(ConvexHullShapeSettings, mHullTolerance)
 }
 
-JPH_IMPLEMENT_RTTI_VIRTUAL(ConvexHullShape)
-{
-	JPH_ADD_BASE_CLASS(ConvexHullShape, ConvexShape)
-}
-
 static constexpr int cMaxPointsInHull = 256;
 
 ShapeSettings::ShapeResult ConvexHullShapeSettings::Create() const
@@ -45,7 +40,7 @@ ShapeSettings::ShapeResult ConvexHullShapeSettings::Create() const
 }
 
 ConvexHullShape::ConvexHullShape(const ConvexHullShapeSettings &inSettings, ShapeResult &outResult) :
-	ConvexShape(inSettings, outResult)
+	ConvexShape(EShapeSubType::ConvexHull, inSettings, outResult)
 {
 	using BuilderFace = ConvexHullBuilder::Face;
 	using Edge = ConvexHullBuilder::Edge;
@@ -1175,4 +1170,11 @@ Shape::Stats ConvexHullShape::GetStats() const
 		triangle_count);
 }
 
+void ConvexHullShape::sRegister()
+{
+	ShapeFunctions &f = ShapeFunctions::sGet(EShapeSubType::ConvexHull);
+	f.mConstruct = []() -> Shape * { return new ConvexHullShape; };
+	f.mColor = Color::sGreen;
+}
+
 } // JPH

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

@@ -39,10 +39,8 @@ public:
 class ConvexHullShape final : public ConvexShape
 {
 public:
-	JPH_DECLARE_RTTI_VIRTUAL(ConvexHullShape)
-
 	/// Constructor
-							ConvexHullShape() = default;
+							ConvexHullShape() : ConvexShape(EShapeSubType::ConvexHull) { }
 							ConvexHullShape(const ConvexHullShapeSettings &inSettings, ShapeResult &outResult);
 
 	// See Shape::GetCenterOfMass
@@ -105,6 +103,9 @@ public:
 	/// Get the planes of this convex hull
 	const vector<Plane> &	GetPlanes() const													{ return mPlanes; }
 
+	// Register shape functions with the registry
+	static void				sRegister();
+
 protected:
 	// See: Shape::RestoreBinaryState
 	virtual void			RestoreBinaryState(StreamIn &inStream) override;

+ 32 - 14
Jolt/Physics/Collision/Shape/ConvexShape.cpp

@@ -13,6 +13,7 @@
 #include <Physics/Collision/Shape/GetTrianglesContext.h>
 #include <Physics/Collision/Shape/PolyhedronSubmergedVolumeCalculator.h>
 #include <Physics/Collision/TransformedShape.h>
+#include <Physics/Collision/CollisionDispatch.h>
 #include <Physics/PhysicsSettings.h>
 #include <Core/StatCollector.h>
 #include <Core/StreamIn.h>
@@ -38,11 +39,6 @@ JPH_IMPLEMENT_SERIALIZABLE_ABSTRACT(ConvexShapeSettings)
 	JPH_ADD_ATTRIBUTE(ConvexShapeSettings, mMaterial)
 }
 
-JPH_IMPLEMENT_RTTI_ABSTRACT(ConvexShape)
-{
-	JPH_ADD_BASE_CLASS(ConvexShape, Shape)
-}
-
 const vector<Vec3> ConvexShape::sUnitSphereTriangles = []() { 
 	const int level = 2;
 
@@ -52,20 +48,26 @@ const vector<Vec3> ConvexShape::sUnitSphereTriangles = []() {
 	return verts;
 }();
 
-void ConvexShape::sCollideConvexVsConvex(const ConvexShape *inShape1, const ConvexShape *inShape2, Vec3Arg inScale1, Vec3Arg inScale2, Mat44Arg inCenterOfMassTransform1, Mat44Arg inCenterOfMassTransform2, const SubShapeIDCreator &inSubShapeIDCreator1, const SubShapeIDCreator &inSubShapeIDCreator2, const CollideShapeSettings &inCollideShapeSettings, CollideShapeCollector &ioCollector)
+void ConvexShape::sCollideConvexVsConvex(const Shape *inShape1, const Shape *inShape2, Vec3Arg inScale1, Vec3Arg inScale2, Mat44Arg inCenterOfMassTransform1, Mat44Arg inCenterOfMassTransform2, const SubShapeIDCreator &inSubShapeIDCreator1, const SubShapeIDCreator &inSubShapeIDCreator2, const CollideShapeSettings &inCollideShapeSettings, CollideShapeCollector &ioCollector)
 {
 	JPH_PROFILE_FUNCTION();
 
 	JPH_IF_STAT_COLLECTOR(sNumCollideChecks++;)
 
+	// Get the shapes
+	JPH_ASSERT(inShape1->GetType() == EShapeType::Convex);
+	JPH_ASSERT(inShape2->GetType() == EShapeType::Convex);
+	const ConvexShape *shape1 = static_cast<const ConvexShape *>(inShape1);
+	const ConvexShape *shape2 = static_cast<const ConvexShape *>(inShape2);
+
 	// Get transforms
 	Mat44 inverse_transform1 = inCenterOfMassTransform1.InversedRotationTranslation();
 	Mat44 transform_2_to_1 = inverse_transform1 * inCenterOfMassTransform2;
 
 	// Get bounding boxes
-	AABox shape1_bbox = inShape1->GetLocalBounds().Scaled(inScale1);
+	AABox shape1_bbox = shape1->GetLocalBounds().Scaled(inScale1);
 	shape1_bbox.ExpandBy(Vec3::sReplicate(inCollideShapeSettings.mMaxSeparationDistance));
-	AABox shape2_bbox = inShape2->GetLocalBounds().Scaled(inScale2);
+	AABox shape2_bbox = shape2->GetLocalBounds().Scaled(inScale2);
 
 	// Check if they overlap
 	if (!OrientedBox(transform_2_to_1, shape2_bbox).Overlaps(shape1_bbox))
@@ -81,8 +83,8 @@ void ConvexShape::sCollideConvexVsConvex(const ConvexShape *inShape1, const Conv
 
 		// Create support function
 		SupportBuffer buffer1_excl_cvx_radius, buffer2_excl_cvx_radius;
-		const Support *shape1_excl_cvx_radius = inShape1->GetSupportFunction(ConvexShape::ESupportMode::ExcludeConvexRadius, buffer1_excl_cvx_radius, inScale1);
-		const Support *shape2_excl_cvx_radius = inShape2->GetSupportFunction(ConvexShape::ESupportMode::ExcludeConvexRadius, buffer2_excl_cvx_radius, inScale2);
+		const Support *shape1_excl_cvx_radius = shape1->GetSupportFunction(ConvexShape::ESupportMode::ExcludeConvexRadius, buffer1_excl_cvx_radius, inScale1);
+		const Support *shape2_excl_cvx_radius = shape2->GetSupportFunction(ConvexShape::ESupportMode::ExcludeConvexRadius, buffer2_excl_cvx_radius, inScale2);
 
 		// Transform shape 2 in the space of shape 1
 		TransformedConvexObject<Support> transformed2_excl_cvx_radius(transform_2_to_1, *shape2_excl_cvx_radius);
@@ -107,8 +109,8 @@ void ConvexShape::sCollideConvexVsConvex(const ConvexShape *inShape1, const Conv
 
 			// Create support function
 			SupportBuffer buffer1_incl_cvx_radius, buffer2_incl_cvx_radius;
-			const Support *shape1_incl_cvx_radius = inShape1->GetSupportFunction(ConvexShape::ESupportMode::IncludeConvexRadius, buffer1_incl_cvx_radius, inScale1);
-			const Support *shape2_incl_cvx_radius = inShape2->GetSupportFunction(ConvexShape::ESupportMode::IncludeConvexRadius, buffer2_incl_cvx_radius, inScale2);
+			const Support *shape1_incl_cvx_radius = shape1->GetSupportFunction(ConvexShape::ESupportMode::IncludeConvexRadius, buffer1_incl_cvx_radius, inScale1);
+			const Support *shape2_incl_cvx_radius = shape2->GetSupportFunction(ConvexShape::ESupportMode::IncludeConvexRadius, buffer2_incl_cvx_radius, inScale2);
 
 			// Add separation distance
 			AddConvexRadius<Support> shape1_add_max_separation_distance(*shape1_incl_cvx_radius, inCollideShapeSettings.mMaxSeparationDistance);
@@ -145,14 +147,14 @@ void ConvexShape::sCollideConvexVsConvex(const ConvexShape *inShape1, const Conv
 	if (inCollideShapeSettings.mCollectFacesMode == ECollectFacesMode::CollectFaces)
 	{
 		// Get supporting face of shape 1
-		inShape1->GetSupportingFace(-penetration_axis, inScale1, result.mShape1Face);
+		shape1->GetSupportingFace(-penetration_axis, inScale1, result.mShape1Face);
 
 		// Convert to world space
 		for (Vec3 &p : result.mShape1Face)
 			p = inCenterOfMassTransform1 * p;
 
 		// Get supporting face of shape 2 
-		inShape2->GetSupportingFace(transform_2_to_1.Multiply3x3Transposed(penetration_axis), inScale2, result.mShape2Face);
+		shape2->GetSupportingFace(transform_2_to_1.Multiply3x3Transposed(penetration_axis), inScale2, result.mShape2Face);
 
 		// Convert to world space
 		for (Vec3 &p : result.mShape2Face)
@@ -165,6 +167,11 @@ void ConvexShape::sCollideConvexVsConvex(const ConvexShape *inShape1, const Conv
 	ioCollector.AddHit(result);
 }
 
+void ConvexShape::sCastConvexVsShape(const ShapeCast &inShapeCast, const ShapeCastSettings &inShapeCastSettings, const Shape *inShape, Vec3Arg inScale, const ShapeFilter &inShapeFilter, Mat44Arg inCenterOfMassTransform2, const SubShapeIDCreator &inSubShapeIDCreator1, const SubShapeIDCreator &inSubShapeIDCreator2, CastShapeCollector &ioCollector)
+{
+	inShape->CastShape(inShapeCast, inShapeCastSettings, inScale, inShapeFilter, inCenterOfMassTransform2, inSubShapeIDCreator1, inSubShapeIDCreator2, ioCollector);
+}
+
 bool ConvexShape::CastRay(const RayCast &inRay, const SubShapeIDCreator &inSubShapeIDCreator, RayCastResult &ioHit) const
 {
 	// Note: This is a fallback routine, most convex shapes should implement a more performant version!
@@ -583,4 +590,15 @@ void ConvexShape::RestoreMaterialState(const PhysicsMaterialRefC *inMaterials, u
 	mMaterial = inMaterials[0]; 
 }
 
+void ConvexShape::sRegister()
+{
+	for (EShapeSubType s1 : sConvexSubShapeTypes)
+	{
+		for (EShapeSubType s2 : sConvexSubShapeTypes)
+			CollisionDispatch::sRegisterCollideShape(s1, s2, sCollideConvexVsConvex);
+
+		CollisionDispatch::sRegisterCastShape(s1, sCastConvexVsShape);
+	}
+}
+
 } // JPH

+ 11 - 12
Jolt/Physics/Collision/Shape/ConvexShape.h

@@ -24,7 +24,7 @@ public:
 
 	/// Constructor
 									ConvexShapeSettings() = default;
-									ConvexShapeSettings(const PhysicsMaterial *inMaterial)		: mMaterial(inMaterial) { }
+	explicit						ConvexShapeSettings(const PhysicsMaterial *inMaterial)		: mMaterial(inMaterial) { }
 
 	/// Set the density of the object in kg / m^3
 	void							SetDensity(float inDensity)									{ mDensity = inDensity; }
@@ -38,15 +38,10 @@ public:
 class ConvexShape : public Shape
 {
 public:
-	JPH_DECLARE_RTTI_ABSTRACT(ConvexShape)
-
 	/// Constructor
-									ConvexShape() = default;
-									ConvexShape(const ConvexShapeSettings &inSettings, ShapeResult &outResult) : Shape(inSettings, outResult), mMaterial(inSettings.mMaterial), mDensity(inSettings.mDensity) { }
-									ConvexShape(const PhysicsMaterial *inMaterial) : mMaterial(inMaterial) { }
-
-	// Get type
-	virtual EShapeType				GetType() const override									{ return EShapeType::Convex; }
+	explicit						ConvexShape(EShapeSubType inSubType) : Shape(EShapeType::Convex, inSubType) { }
+									ConvexShape(EShapeSubType inSubType, const ConvexShapeSettings &inSettings, ShapeResult &outResult) : Shape(EShapeType::Convex, inSubType, inSettings, outResult), mMaterial(inSettings.mMaterial), mDensity(inSettings.mDensity) { }
+									ConvexShape(EShapeSubType inSubType, const PhysicsMaterial *inMaterial) : Shape(EShapeType::Convex, inSubType), mMaterial(inMaterial) { }
 
 	// See Shape::GetSubShapeIDBitsRecursive
 	virtual uint					GetSubShapeIDBitsRecursive() const override					{ return 0; } // Convex shapes don't have sub shapes
@@ -126,9 +121,6 @@ public:
 	/// Get density of the shape (kg / m^3)
 	float							GetDensity() const											{ return mDensity; }
 
-	/// Collide 2 shapes and report any hits to ioCollector.
-	static void						sCollideConvexVsConvex(const ConvexShape *inShape1, const ConvexShape *inShape2, Vec3Arg inScale1, Vec3Arg inScale2, Mat44Arg inCenterOfMassTransform1, Mat44Arg inCenterOfMassTransform2, const SubShapeIDCreator &inSubShapeIDCreator1, const SubShapeIDCreator &inSubShapeIDCreator2, const CollideShapeSettings &inCollideShapeSettings, CollideShapeCollector &ioCollector);
-
 #ifdef JPH_DEBUG_RENDERER
 	// See Shape::DrawGetSupportFunction
 	virtual void					DrawGetSupportFunction(DebugRenderer *inRenderer, Mat44Arg inCenterOfMassTransform, Vec3Arg inScale, ColorArg inColor, bool inDrawSupportDirection) const override;
@@ -150,6 +142,9 @@ public:
 	virtual void					SaveMaterialState(PhysicsMaterialList &outMaterials) const override;
 	virtual void					RestoreMaterialState(const PhysicsMaterialRefC *inMaterials, uint inNumMaterials) override;
 
+	// Register shape functions with the registry
+	static void						sRegister();
+
 protected:
 	// See: Shape::RestoreBinaryState
 	virtual void					RestoreBinaryState(StreamIn &inStream) override;
@@ -161,6 +156,10 @@ private:
 	// Class for GetTrianglesStart/Next
 	class							CSGetTrianglesContext;
 
+	// Helper functions called by CollisionDispatch
+	static void						sCollideConvexVsConvex(const Shape *inShape1, const Shape *inShape2, Vec3Arg inScale1, Vec3Arg inScale2, Mat44Arg inCenterOfMassTransform1, Mat44Arg inCenterOfMassTransform2, const SubShapeIDCreator &inSubShapeIDCreator1, const SubShapeIDCreator &inSubShapeIDCreator2, const CollideShapeSettings &inCollideShapeSettings, CollideShapeCollector &ioCollector);
+	static void						sCastConvexVsShape(const ShapeCast &inShapeCast, const ShapeCastSettings &inShapeCastSettings, const Shape *inShape, Vec3Arg inScale, const ShapeFilter &inShapeFilter, Mat44Arg inCenterOfMassTransform2, const SubShapeIDCreator &inSubShapeIDCreator1, const SubShapeIDCreator &inSubShapeIDCreator2, CastShapeCollector &ioCollector);
+
 #ifdef JPH_STAT_COLLECTOR
 	// Statistics
 	alignas(JPH_CACHE_LINE_SIZE) static atomic<int>	sNumCollideChecks;

+ 9 - 7
Jolt/Physics/Collision/Shape/CylinderShape.cpp

@@ -29,11 +29,6 @@ JPH_IMPLEMENT_SERIALIZABLE_VIRTUAL(CylinderShapeSettings)
 	JPH_ADD_ATTRIBUTE(CylinderShapeSettings, mConvexRadius)
 }
 
-JPH_IMPLEMENT_RTTI_VIRTUAL(CylinderShape)
-{
-	JPH_ADD_BASE_CLASS(CylinderShape, ConvexShape)
-}
-
 // Approximation of top face with 8 vertices
 static const float cSin45 = 0.70710678118654752440084436210485f;
 static const Vec3 cTopFace[] =
@@ -92,7 +87,7 @@ ShapeSettings::ShapeResult CylinderShapeSettings::Create() const
 }
 
 CylinderShape::CylinderShape(const CylinderShapeSettings &inSettings, ShapeResult &outResult) : 
-	ConvexShape(inSettings, outResult),
+	ConvexShape(EShapeSubType::Cylinder, inSettings, outResult),
 	mHalfHeight(inSettings.mHalfHeight), 
 	mRadius(inSettings.mRadius),
 	mConvexRadius(inSettings.mConvexRadius)
@@ -119,7 +114,7 @@ CylinderShape::CylinderShape(const CylinderShapeSettings &inSettings, ShapeResul
 }
 
 CylinderShape::CylinderShape(float inHalfHeight, float inRadius, float inConvexRadius, const PhysicsMaterial *inMaterial) : 
-	ConvexShape(inMaterial),
+	ConvexShape(EShapeSubType::Cylinder, inMaterial),
 	mHalfHeight(inHalfHeight), 
 	mRadius(inRadius),
 	mConvexRadius(inConvexRadius)
@@ -344,4 +339,11 @@ bool CylinderShape::IsValidScale(Vec3Arg inScale) const
 	return ConvexShape::IsValidScale(inScale) && abs_scale.Swizzle<SWIZZLE_Z, SWIZZLE_Y, SWIZZLE_X>().IsClose(abs_scale, ScaleHelpers::cScaleToleranceSq);
 }
 
+void CylinderShape::sRegister()
+{
+	ShapeFunctions &f = ShapeFunctions::sGet(EShapeSubType::Cylinder);
+	f.mConstruct = []() -> Shape * { return new CylinderShape; };
+	f.mColor = Color::sGreen;
+}
+
 } // JPH

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

@@ -33,10 +33,8 @@ public:
 class CylinderShape final : public ConvexShape
 {
 public:
-	JPH_DECLARE_RTTI_VIRTUAL(CylinderShape)
-
 	/// Constructor
-							CylinderShape() = default;
+							CylinderShape() : ConvexShape(EShapeSubType::Cylinder) { }
 							CylinderShape(const CylinderShapeSettings &inSettings, ShapeResult &outResult);
 
 	/// Create a shape centered around the origin with one top at (0, -inHalfHeight, 0) and the other at (0, inHalfHeight, 0) and radius inRadius.
@@ -99,6 +97,9 @@ public:
 	// See Shape::IsValidScale
 	virtual bool			IsValidScale(Vec3Arg inScale) const override;
 
+	// Register shape functions with the registry
+	static void				sRegister();
+
 protected:
 	// See: Shape::RestoreBinaryState
 	virtual void			RestoreBinaryState(StreamIn &inStream) override;

+ 2 - 7
Jolt/Physics/Collision/Shape/DecoratedShape.cpp

@@ -15,13 +15,8 @@ JPH_IMPLEMENT_SERIALIZABLE_ABSTRACT(DecoratedShapeSettings)
 	JPH_ADD_ATTRIBUTE(DecoratedShapeSettings, mInnerShape)
 }
 
-JPH_IMPLEMENT_RTTI_ABSTRACT(DecoratedShape)
-{
-	JPH_ADD_BASE_CLASS(DecoratedShape, Shape)
-}
-
-DecoratedShape::DecoratedShape(const DecoratedShapeSettings &inSettings, ShapeResult &outResult) :
-	Shape(inSettings, outResult)
+DecoratedShape::DecoratedShape(EShapeSubType inSubType, const DecoratedShapeSettings &inSettings, ShapeResult &outResult) :
+	Shape(EShapeType::Decorated, inSubType, inSettings, outResult)
 {
 	// Check that there's a shape
 	if (inSettings.mInnerShape == nullptr && inSettings.mInnerShapePtr == nullptr)

+ 5 - 7
Jolt/Physics/Collision/Shape/DecoratedShape.h

@@ -16,8 +16,8 @@ class DecoratedShapeSettings : public ShapeSettings
 									DecoratedShapeSettings() = default;
 
 	/// Constructor that decorates another shape
-									DecoratedShapeSettings(const ShapeSettings *inShape)	: mInnerShape(inShape) { }
-									DecoratedShapeSettings(const Shape *inShape)			: mInnerShapePtr(inShape) { }
+	explicit						DecoratedShapeSettings(const ShapeSettings *inShape)	: mInnerShape(inShape) { }
+	explicit						DecoratedShapeSettings(const Shape *inShape)			: mInnerShapePtr(inShape) { }
 
 	RefConst<ShapeSettings>			mInnerShape;											///< Sub shape (either this or mShapePtr needs to be filled up)
 	RefConst<Shape>					mInnerShapePtr;											///< Sub shape (either this or mShape needs to be filled up)
@@ -27,12 +27,10 @@ class DecoratedShapeSettings : public ShapeSettings
 class DecoratedShape : public Shape
 {
 public:
-	JPH_DECLARE_RTTI_VIRTUAL(DecoratedShape)
-
 	/// Constructor
-									DecoratedShape() = default;
-									DecoratedShape(const Shape *inInnerShape) : mInnerShape(inInnerShape) { }
-									DecoratedShape(const DecoratedShapeSettings &inSettings, ShapeResult &outResult);
+	explicit						DecoratedShape(EShapeSubType inSubType) : Shape(EShapeType::Decorated, inSubType) { }
+									DecoratedShape(EShapeSubType inSubType, const Shape *inInnerShape) : Shape(EShapeType::Decorated, inSubType), mInnerShape(inInnerShape) { }
+									DecoratedShape(EShapeSubType inSubType, const DecoratedShapeSettings &inSettings, ShapeResult &outResult);
 
 	/// Access to the decorated inner shape
 	const Shape *					GetInnerShape() const									{ return mInnerShape; }

+ 22 - 10
Jolt/Physics/Collision/Shape/HeightFieldShape.cpp

@@ -15,6 +15,7 @@
 #include <Physics/Collision/CollideConvexVsTriangles.h>
 #include <Physics/Collision/TransformedShape.h>
 #include <Physics/Collision/ActiveEdges.h>
+#include <Physics/Collision/CollisionDispatch.h>
 #include <Core/Profiler.h>
 #include <Core/StringTools.h>
 #include <Core/StreamIn.h>
@@ -49,11 +50,6 @@ JPH_IMPLEMENT_SERIALIZABLE_VIRTUAL(HeightFieldShapeSettings)
 	JPH_ADD_ATTRIBUTE(HeightFieldShapeSettings, mMaterials)
 }
 
-JPH_IMPLEMENT_RTTI_VIRTUAL(HeightFieldShape)
-{
-	JPH_ADD_BASE_CLASS(HeightFieldShape, Shape)
-}
-
 const uint HeightFieldShape::sGridOffsets[] = 
 {
 	0,			// level:  0, max x/y:     0, offset: 0
@@ -302,7 +298,7 @@ void HeightFieldShape::CacheValues()
 }
 
 HeightFieldShape::HeightFieldShape(const HeightFieldShapeSettings &inSettings, ShapeResult &outResult) :
-	Shape(inSettings, outResult),
+	Shape(EShapeType::HeightField, EShapeSubType::HeightField, inSettings, outResult),
 	mOffset(inSettings.mOffset),
 	mScale(inSettings.mScale),
 	mSampleCount(inSettings.mSampleCount),
@@ -1633,10 +1629,16 @@ int HeightFieldShape::GetTrianglesNext(GetTrianglesContext &ioContext, int inMax
 	return context.mNumTrianglesFound;
 }
 
-void HeightFieldShape::sCollideConvexVsHeightField(const ConvexShape *inShape1, const HeightFieldShape *inShape2, Vec3Arg inScale1, Vec3Arg inScale2, Mat44Arg inCenterOfMassTransform1, Mat44Arg inCenterOfMassTransform2, const SubShapeIDCreator &inSubShapeIDCreator1, const SubShapeIDCreator &inSubShapeIDCreator2, const CollideShapeSettings &inCollideShapeSettings, CollideShapeCollector &ioCollector)
+void HeightFieldShape::sCollideConvexVsHeightField(const Shape *inShape1, const Shape *inShape2, Vec3Arg inScale1, Vec3Arg inScale2, Mat44Arg inCenterOfMassTransform1, Mat44Arg inCenterOfMassTransform2, const SubShapeIDCreator &inSubShapeIDCreator1, const SubShapeIDCreator &inSubShapeIDCreator2, const CollideShapeSettings &inCollideShapeSettings, CollideShapeCollector &ioCollector)
 {
 	JPH_PROFILE_FUNCTION();
 
+	// Get the shapes
+	JPH_ASSERT(inShape1->GetType() == EShapeType::Convex);
+	JPH_ASSERT(inShape2->GetType() == EShapeType::HeightField);
+	const ConvexShape *shape1 = static_cast<const ConvexShape *>(inShape1);
+	const HeightFieldShape *shape2 = static_cast<const HeightFieldShape *>(inShape2);
+
 	struct Visitor : public CollideConvexVsTriangles
 	{
 		using CollideConvexVsTriangles::CollideConvexVsTriangles;
@@ -1682,10 +1684,10 @@ void HeightFieldShape::sCollideConvexVsHeightField(const ConvexShape *inShape1,
 		SubShapeIDCreator			mSubShapeIDCreator2;
 	};
 
-	Visitor visitor(inShape1, inScale1, inScale2, inCenterOfMassTransform1, inCenterOfMassTransform2, inSubShapeIDCreator1.GetID(), inCollideShapeSettings, ioCollector);
-	visitor.mShape2 = inShape2;
+	Visitor visitor(shape1, inScale1, inScale2, inCenterOfMassTransform1, inCenterOfMassTransform2, inSubShapeIDCreator1.GetID(), inCollideShapeSettings, ioCollector);
+	visitor.mShape2 = shape2;
 	visitor.mSubShapeIDCreator2 = inSubShapeIDCreator2;
-	inShape2->WalkHeightField(visitor);
+	shape2->WalkHeightField(visitor);
 }
 
 void HeightFieldShape::SaveBinaryState(StreamOut &inStream) const
@@ -1748,4 +1750,14 @@ Shape::Stats HeightFieldShape::GetStats() const
 		mHeightSamples.empty()? 0 : Square(mSampleCount - 1) * 2);
 }
 
+void HeightFieldShape::sRegister()
+{
+	ShapeFunctions &f = ShapeFunctions::sGet(EShapeSubType::HeightField);
+	f.mConstruct = []() -> Shape * { return new HeightFieldShape; };
+	f.mColor = Color::sPurple;
+
+	for (EShapeSubType s : sConvexSubShapeTypes)
+		CollisionDispatch::sRegisterCollideShape(s, EShapeSubType::HeightField, sCollideConvexVsHeightField);
+}
+
 } // JPH

+ 7 - 9
Jolt/Physics/Collision/Shape/HeightFieldShape.h

@@ -91,15 +91,10 @@ public:
 class HeightFieldShape final : public Shape
 {
 public:
-	JPH_DECLARE_RTTI_VIRTUAL(HeightFieldShape)
-
 	/// Constructor
-									HeightFieldShape() = default;
+									HeightFieldShape() : Shape(EShapeType::HeightField, EShapeSubType::HeightField) { }
 									HeightFieldShape(const HeightFieldShapeSettings &inSettings, ShapeResult &outResult);
 
-	/// Get type
-	virtual EShapeType				GetType() const override											{ return EShapeType::HeightField; }
-
 	// See Shape::MustBeStatic
 	virtual bool					MustBeStatic() const override										{ return true; }
 
@@ -148,9 +143,6 @@ public:
 	// See Shape::GetTrianglesNext
 	virtual int						GetTrianglesNext(GetTrianglesContext &ioContext, int inMaxTrianglesRequested, Float3 *outTriangleVertices, const PhysicsMaterial **outMaterials = nullptr) const override;
 
-	/// Collide 2 shapes and pass any collisions on to ioCollector
-	static void						sCollideConvexVsHeightField(const ConvexShape *inShape1, const HeightFieldShape *inShape2, Vec3Arg inScale1, Vec3Arg inScale2, Mat44Arg inCenterOfMassTransform1, Mat44Arg inCenterOfMassTransform2, const SubShapeIDCreator &inSubShapeIDCreator1, const SubShapeIDCreator &inSubShapeIDCreator2, const CollideShapeSettings &inCollideShapeSettings, CollideShapeCollector &ioCollector);
-
 	/// Get height field position at sampled location (inX, inY).
 	/// where inX and inY are integers in the range inX e [0, mSampleCount - 1] and inY e [0, mSampleCount - 1].
 	Vec3							GetPosition(uint inX, uint inY) const;
@@ -178,6 +170,9 @@ public:
 	static bool						sDrawTriangleOutlines;
 #endif // JPH_DEBUG_RENDERER
 
+	// Register shape functions with the registry
+	static void						sRegister();
+
 protected:
 	// See: Shape::RestoreBinaryState
 	virtual void					RestoreBinaryState(StreamIn &inStream) override;
@@ -223,6 +218,9 @@ private:
 	/// Get the edge flags for a triangle
 	inline uint8					GetEdgeFlags(uint inX, uint inY, uint inTriangle) const;
 
+	// Helper functions called by CollisionDispatch
+	static void						sCollideConvexVsHeightField(const Shape *inShape1, const Shape *inShape2, Vec3Arg inScale1, Vec3Arg inScale2, Mat44Arg inCenterOfMassTransform1, Mat44Arg inCenterOfMassTransform2, const SubShapeIDCreator &inSubShapeIDCreator1, const SubShapeIDCreator &inSubShapeIDCreator2, const CollideShapeSettings &inCollideShapeSettings, CollideShapeCollector &ioCollector);
+
 	/// Visit the entire height field using a visitor pattern
 	template <class Visitor>
 	JPH_INLINE void					WalkHeightField(Visitor &ioVisitor) const;

+ 22 - 10
Jolt/Physics/Collision/Shape/MeshShape.cpp

@@ -16,6 +16,7 @@
 #include <Physics/Collision/CastConvexVsTriangles.h>
 #include <Physics/Collision/TransformedShape.h>
 #include <Physics/Collision/ActiveEdges.h>
+#include <Physics/Collision/CollisionDispatch.h>
 #include <Core/StringTools.h>
 #include <Core/StreamIn.h>
 #include <Core/StreamOut.h>
@@ -48,11 +49,6 @@ JPH_IMPLEMENT_SERIALIZABLE_VIRTUAL(MeshShapeSettings)
 	JPH_ADD_ATTRIBUTE(MeshShapeSettings, mMaterials)
 }
 
-JPH_IMPLEMENT_RTTI_VIRTUAL(MeshShape)
-{
-	JPH_ADD_BASE_CLASS(MeshShape, Shape)
-}
-
 // Codecs this mesh shape is using
 using TriangleCodec = TriangleCodecIndexed8BitPackSOA4Flags;
 using NodeCodec = NodeCodecQuadTreeHalfFloat<1>;
@@ -107,7 +103,7 @@ ShapeSettings::ShapeResult MeshShapeSettings::Create() const
 }
 
 MeshShape::MeshShape(const MeshShapeSettings &inSettings, ShapeResult &outResult) : 
-	Shape(inSettings, outResult)
+	Shape(EShapeType::Mesh, EShapeSubType::Mesh, inSettings, outResult)
 {
 	// Check if there are any triangles
 	if (inSettings.mIndexedTriangles.empty())
@@ -969,10 +965,16 @@ int MeshShape::GetTrianglesNext(GetTrianglesContext &ioContext, int inMaxTriangl
 	return context.mNumTrianglesFound;
 }
 
-void MeshShape::sCollideConvexVsMesh(const ConvexShape *inShape1, const MeshShape *inShape2, Vec3Arg inScale1, Vec3Arg inScale2, Mat44Arg inCenterOfMassTransform1, Mat44Arg inCenterOfMassTransform2, const SubShapeIDCreator &inSubShapeIDCreator1, const SubShapeIDCreator &inSubShapeIDCreator2, const CollideShapeSettings &inCollideShapeSettings, CollideShapeCollector &ioCollector)
+void MeshShape::sCollideConvexVsMesh(const Shape *inShape1, const Shape *inShape2, Vec3Arg inScale1, Vec3Arg inScale2, Mat44Arg inCenterOfMassTransform1, Mat44Arg inCenterOfMassTransform2, const SubShapeIDCreator &inSubShapeIDCreator1, const SubShapeIDCreator &inSubShapeIDCreator2, const CollideShapeSettings &inCollideShapeSettings, CollideShapeCollector &ioCollector)
 {
 	JPH_PROFILE_FUNCTION();
 
+	// Get the shapes
+	JPH_ASSERT(inShape1->GetType() == EShapeType::Convex);
+	JPH_ASSERT(inShape2->GetType() == EShapeType::Mesh);
+	const ConvexShape *shape1 = static_cast<const ConvexShape *>(inShape1);
+	const MeshShape *shape2 = static_cast<const MeshShape *>(inShape2);
+
 	struct Visitor : public CollideConvexVsTriangles
 	{
 		using CollideConvexVsTriangles::CollideConvexVsTriangles;
@@ -1041,11 +1043,11 @@ void MeshShape::sCollideConvexVsMesh(const ConvexShape *inShape1, const MeshShap
 		SubShapeIDCreator				mSubShapeIDCreator2;
 	};
 
-	Visitor visitor(inShape1, inScale1, inScale2, inCenterOfMassTransform1, inCenterOfMassTransform2, inSubShapeIDCreator1.GetID(), inCollideShapeSettings, ioCollector);
-	visitor.mTriangleBlockIDBits = NodeCodec::DecodingContext::sTriangleBlockIDBits(inShape2->mTree);
+	Visitor visitor(shape1, inScale1, inScale2, inCenterOfMassTransform1, inCenterOfMassTransform2, inSubShapeIDCreator1.GetID(), inCollideShapeSettings, ioCollector);
+	visitor.mTriangleBlockIDBits = NodeCodec::DecodingContext::sTriangleBlockIDBits(shape2->mTree);
 	visitor.mSubShapeIDCreator2 = inSubShapeIDCreator2;
 
-	inShape2->WalkTree(visitor);
+	shape2->WalkTree(visitor);
 }
 
 void MeshShape::SaveBinaryState(StreamOut &inStream) const
@@ -1108,4 +1110,14 @@ Shape::Stats MeshShape::GetStats() const
 	return Stats(sizeof(*this) + mMaterials.size() * sizeof(Ref<PhysicsMaterial>) + mTree.size() * sizeof(uint8), visitor.mNumTriangles);
 }
 
+void MeshShape::sRegister()
+{
+	ShapeFunctions &f = ShapeFunctions::sGet(EShapeSubType::Mesh);
+	f.mConstruct = []() -> Shape * { return new MeshShape; };
+	f.mColor = Color::sRed;
+
+	for (EShapeSubType s : sConvexSubShapeTypes)
+		CollisionDispatch::sRegisterCollideShape(s, EShapeSubType::Mesh, sCollideConvexVsMesh);
+}
+
 } // JPH

+ 7 - 9
Jolt/Physics/Collision/Shape/MeshShape.h

@@ -48,15 +48,10 @@ public:
 class MeshShape final : public Shape
 {
 public:
-	JPH_DECLARE_RTTI_VIRTUAL(MeshShape)
-
 	/// Constructor
-									MeshShape() = default;
+									MeshShape() : Shape(EShapeType::Mesh, EShapeSubType::Mesh) { }
 									MeshShape(const MeshShapeSettings &inSettings, ShapeResult &outResult);
 
-	/// Get type
-	virtual EShapeType				GetType() const override									{ return EShapeType::Mesh; }
-
 	// See Shape::MustBeStatic
 	virtual bool					MustBeStatic() const override								{ return true; }
 
@@ -102,9 +97,6 @@ public:
 	// 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"); }
 
-	/// Collide 2 shapes and pass any collisions on to ioCollector
-	static void						sCollideConvexVsMesh(const ConvexShape *inShape1, const MeshShape *inShape2, Vec3Arg inScale1, Vec3Arg inScale2, Mat44Arg inCenterOfMassTransform1, Mat44Arg inCenterOfMassTransform2, const SubShapeIDCreator &inSubShapeIDCreator1, const SubShapeIDCreator &inSubShapeIDCreator2, const CollideShapeSettings &inCollideShapeSettings, CollideShapeCollector &ioCollector);
-
 	// See Shape
 	virtual void					SaveBinaryState(StreamOut &inStream) const override;
 	virtual void					SaveMaterialState(PhysicsMaterialList &outMaterials) const override;
@@ -122,6 +114,9 @@ public:
 	static bool						sDrawTriangleOutlines;
 #endif // JPH_DEBUG_RENDERER
 
+	// Register shape functions with the registry
+	static void						sRegister();
+
 protected:
 	// See: Shape::RestoreBinaryState
 	virtual void					RestoreBinaryState(StreamIn &inStream) override;
@@ -142,6 +137,9 @@ private:
 	/// Decode a sub shape ID
 	inline void						DecodeSubShapeID(const SubShapeID &inSubShapeID, const void *&outTriangleBlock, uint32 &outTriangleIndex) const;
 
+	// Helper functions called by CollisionDispatch
+	static void						sCollideConvexVsMesh(const Shape *inShape1, const Shape *inShape2, Vec3Arg inScale1, Vec3Arg inScale2, Mat44Arg inCenterOfMassTransform1, Mat44Arg inCenterOfMassTransform2, const SubShapeIDCreator &inSubShapeIDCreator1, const SubShapeIDCreator &inSubShapeIDCreator2, const CollideShapeSettings &inCollideShapeSettings, CollideShapeCollector &ioCollector);
+
 	/// Materials assigned to the triangles. Each triangle specifies which material it uses through its mMaterialIndex
 	PhysicsMaterialList				mMaterials;
 

+ 26 - 12
Jolt/Physics/Collision/Shape/MutableCompoundShape.cpp

@@ -17,11 +17,6 @@ JPH_IMPLEMENT_SERIALIZABLE_VIRTUAL(MutableCompoundShapeSettings)
 	JPH_ADD_BASE_CLASS(MutableCompoundShapeSettings, CompoundShapeSettings)
 }
 
-JPH_IMPLEMENT_RTTI_VIRTUAL(MutableCompoundShape)
-{
-	JPH_ADD_BASE_CLASS(MutableCompoundShape, CompoundShape)
-}
-
 ShapeSettings::ShapeResult MutableCompoundShapeSettings::Create() const
 { 
 	// Build a mutable compound shape
@@ -32,7 +27,7 @@ ShapeSettings::ShapeResult MutableCompoundShapeSettings::Create() const
 }
 
 MutableCompoundShape::MutableCompoundShape(const MutableCompoundShapeSettings &inSettings, ShapeResult &outResult) :
-	CompoundShape(inSettings, outResult)
+	CompoundShape(EShapeSubType::MutableCompound, inSettings, outResult)
 {
 	mSubShapes.reserve(inSettings.mSubShapes.size());
 	for (const CompoundShapeSettings::SubShapeSettings &shape : inSettings.mSubShapes)
@@ -465,10 +460,13 @@ int MutableCompoundShape::GetIntersectingSubShapes(const OrientedBox &inBox, uin
 	return visitor.GetNumResults();
 }
 
-void MutableCompoundShape::sCollideCompoundVsShape(const MutableCompoundShape *inShape1, const Shape *inShape2, Vec3Arg inScale1, Vec3Arg inScale2, Mat44Arg inCenterOfMassTransform1, Mat44Arg inCenterOfMassTransform2, const SubShapeIDCreator &inSubShapeIDCreator1, const SubShapeIDCreator &inSubShapeIDCreator2, const CollideShapeSettings &inCollideShapeSettings, CollideShapeCollector &ioCollector)
+void MutableCompoundShape::sCollideCompoundVsShape(const Shape *inShape1, const Shape *inShape2, Vec3Arg inScale1, Vec3Arg inScale2, Mat44Arg inCenterOfMassTransform1, Mat44Arg inCenterOfMassTransform2, const SubShapeIDCreator &inSubShapeIDCreator1, const SubShapeIDCreator &inSubShapeIDCreator2, const CollideShapeSettings &inCollideShapeSettings, CollideShapeCollector &ioCollector)
 {	
 	JPH_PROFILE_FUNCTION();
 
+	JPH_ASSERT(inShape1->GetSubType() == EShapeSubType::MutableCompound);
+	const MutableCompoundShape *shape1 = static_cast<const MutableCompoundShape *>(inShape1);
+
 	struct Visitor : public CollideCompoundVsShapeVisitor
 	{
 		using CollideCompoundVsShapeVisitor::CollideCompoundVsShapeVisitor;
@@ -491,14 +489,17 @@ void MutableCompoundShape::sCollideCompoundVsShape(const MutableCompoundShape *i
 		}
 	};
 
-	Visitor visitor(inShape1, inShape2, inScale1, inScale2, inCenterOfMassTransform1, inCenterOfMassTransform2, inSubShapeIDCreator1, inSubShapeIDCreator2, inCollideShapeSettings, ioCollector);
-	inShape1->WalkSubShapes(visitor);
+	Visitor visitor(shape1, inShape2, inScale1, inScale2, inCenterOfMassTransform1, inCenterOfMassTransform2, inSubShapeIDCreator1, inSubShapeIDCreator2, inCollideShapeSettings, ioCollector);
+	shape1->WalkSubShapes(visitor);
 }
 
-void MutableCompoundShape::sCollideShapeVsCompound(const Shape *inShape1, const MutableCompoundShape *inShape2, Vec3Arg inScale1, Vec3Arg inScale2, Mat44Arg inCenterOfMassTransform1, Mat44Arg inCenterOfMassTransform2, const SubShapeIDCreator &inSubShapeIDCreator1, const SubShapeIDCreator &inSubShapeIDCreator2, const CollideShapeSettings &inCollideShapeSettings, CollideShapeCollector &ioCollector)
+void MutableCompoundShape::sCollideShapeVsCompound(const Shape *inShape1, const Shape *inShape2, Vec3Arg inScale1, Vec3Arg inScale2, Mat44Arg inCenterOfMassTransform1, Mat44Arg inCenterOfMassTransform2, const SubShapeIDCreator &inSubShapeIDCreator1, const SubShapeIDCreator &inSubShapeIDCreator2, const CollideShapeSettings &inCollideShapeSettings, CollideShapeCollector &ioCollector)
 {
 	JPH_PROFILE_FUNCTION();
 
+	JPH_ASSERT(inShape2->GetSubType() == EShapeSubType::MutableCompound);
+	const MutableCompoundShape *shape2 = static_cast<const MutableCompoundShape *>(inShape2);
+
 	struct Visitor : public CollideShapeVsCompoundVisitor
 	{
 		using CollideShapeVsCompoundVisitor::CollideShapeVsCompoundVisitor;
@@ -521,8 +522,8 @@ void MutableCompoundShape::sCollideShapeVsCompound(const Shape *inShape1, const
 		}
 	};
 
-	Visitor visitor(inShape1, inShape2, inScale1, inScale2, inCenterOfMassTransform1, inCenterOfMassTransform2, inSubShapeIDCreator1, inSubShapeIDCreator2, inCollideShapeSettings, ioCollector);
-	inShape2->WalkSubShapes(visitor);
+	Visitor visitor(inShape1, shape2, inScale1, inScale2, inCenterOfMassTransform1, inCenterOfMassTransform2, inSubShapeIDCreator1, inSubShapeIDCreator2, inCollideShapeSettings, ioCollector);
+	shape2->WalkSubShapes(visitor);
 }
 
 void MutableCompoundShape::SaveBinaryState(StreamOut &inStream) const
@@ -548,4 +549,17 @@ void MutableCompoundShape::RestoreBinaryState(StreamIn &inStream)
 		inStream.ReadBytes(mSubShapeBounds[i], bounds_size);
 }
 
+void MutableCompoundShape::sRegister()
+{
+	ShapeFunctions &f = ShapeFunctions::sGet(EShapeSubType::MutableCompound);
+	f.mConstruct = []() -> Shape * { return new MutableCompoundShape; };
+	f.mColor = Color::sDarkOrange;
+
+	for (EShapeSubType s : sAllSubShapeTypes)
+	{
+		CollisionDispatch::sRegisterCollideShape(EShapeSubType::MutableCompound, s, sCollideCompoundVsShape);
+		CollisionDispatch::sRegisterCollideShape(s, EShapeSubType::MutableCompound, sCollideShapeVsCompound);
+	}
+}
+
 } // JPH

+ 10 - 12
Jolt/Physics/Collision/Shape/MutableCompoundShape.h

@@ -29,16 +29,11 @@ public:
 class MutableCompoundShape final : public CompoundShape
 {
 public:
-	JPH_DECLARE_RTTI_VIRTUAL(MutableCompoundShape)
-
 	/// Constructor
-									MutableCompoundShape() = default;
+									MutableCompoundShape() : CompoundShape(EShapeSubType::MutableCompound) { }
 									MutableCompoundShape(const MutableCompoundShapeSettings &inSettings, ShapeResult &outResult);
-	virtual							~MutableCompoundShape() override;
-
-	/// Get type
-	virtual EShapeType				GetType() const override								{ return EShapeType::MutableCompound; }
-
+	virtual							~MutableCompoundShape();
+		
 	// See Shape::CastRay
 	virtual bool					CastRay(const RayCast &inRay, const SubShapeIDCreator &inSubShapeIDCreator, RayCastResult &ioHit) const override;
 	virtual void					CastRay(const RayCast &inRay, const RayCastSettings &inRayCastSettings, const SubShapeIDCreator &inSubShapeIDCreator, CastRayCollector &ioCollector) const override;
@@ -58,10 +53,6 @@ public:
 	// See: CompoundShape::GetIntersectingSubShapes
 	virtual int						GetIntersectingSubShapes(const OrientedBox &inBox, uint *outSubShapeIndices, int inMaxSubShapeIndices) const override;
 
-	/// Collide 2 shapes and pass any hits on to ioCollector
-	static void						sCollideCompoundVsShape(const MutableCompoundShape *inShape1, const Shape *inShape2, Vec3Arg inScale1, Vec3Arg inScale2, Mat44Arg inCenterOfMassTransform1, Mat44Arg inCenterOfMassTransform2, const SubShapeIDCreator &inSubShapeIDCreator1, const SubShapeIDCreator &inSubShapeIDCreator2, const CollideShapeSettings &inCollideShapeSettings, CollideShapeCollector &ioCollector);
-	static void						sCollideShapeVsCompound(const Shape *inShape1, const MutableCompoundShape *inShape2, Vec3Arg inScale1, Vec3Arg inScale2, Mat44Arg inCenterOfMassTransform1, Mat44Arg inCenterOfMassTransform2, const SubShapeIDCreator &inSubShapeIDCreator1, const SubShapeIDCreator &inSubShapeIDCreator2, const CollideShapeSettings &inCollideShapeSettings, CollideShapeCollector &ioCollector);
-
 	// See Shape
 	virtual void					SaveBinaryState(StreamOut &inStream) const override;
 
@@ -99,6 +90,9 @@ public:
 
 	///@}
 
+	// Register shape functions with the registry
+	static void						sRegister();
+
 protected:
 	// See: Shape::RestoreBinaryState
 	virtual void					RestoreBinaryState(StreamIn &inStream) override;
@@ -145,6 +139,10 @@ private:
 	template <class Visitor>
 	JPH_INLINE void					WalkSubShapes(Visitor &ioVisitor) const;					///< Walk the sub shapes and call Visitor::VisitShape for each sub shape encountered
 
+	// Helper functions called by CollisionDispatch
+	static void						sCollideCompoundVsShape(const Shape *inShape1, const Shape *inShape2, Vec3Arg inScale1, Vec3Arg inScale2, Mat44Arg inCenterOfMassTransform1, Mat44Arg inCenterOfMassTransform2, const SubShapeIDCreator &inSubShapeIDCreator1, const SubShapeIDCreator &inSubShapeIDCreator2, const CollideShapeSettings &inCollideShapeSettings, CollideShapeCollector &ioCollector);
+	static void						sCollideShapeVsCompound(const Shape *inShape1, const Shape *inShape2, Vec3Arg inScale1, Vec3Arg inScale2, Mat44Arg inCenterOfMassTransform1, Mat44Arg inCenterOfMassTransform2, const SubShapeIDCreator &inSubShapeIDCreator1, const SubShapeIDCreator &inSubShapeIDCreator2, const CollideShapeSettings &inCollideShapeSettings, CollideShapeCollector &ioCollector);
+
 	Vec4 *							mSubShapeBounds[6];											///< Bounding boxes of all sub shapes in SOA format, 0 = MinX, 1 = MinY, 2 = MinZ, 3 = MaxX, 4 = MaxY, 5 = MaxZ
 	uint							mSubShapeBoundsCapacity = 0;								///< Number of bounding boxes that can be stored in the mSubShapeBounds array (will be multiple of 4)
 };

+ 28 - 12
Jolt/Physics/Collision/Shape/OffsetCenterOfMassShape.cpp

@@ -21,11 +21,6 @@ JPH_IMPLEMENT_SERIALIZABLE_VIRTUAL(OffsetCenterOfMassShapeSettings)
 	JPH_ADD_ATTRIBUTE(OffsetCenterOfMassShapeSettings, mOffset)
 }
 
-JPH_IMPLEMENT_RTTI_VIRTUAL(OffsetCenterOfMassShape)
-{
-	JPH_ADD_BASE_CLASS(OffsetCenterOfMassShape, DecoratedShape)
-}
-
 ShapeSettings::ShapeResult OffsetCenterOfMassShapeSettings::Create() const
 { 
 	if (mCachedResult.IsEmpty())
@@ -34,7 +29,7 @@ ShapeSettings::ShapeResult OffsetCenterOfMassShapeSettings::Create() const
 }
 
 OffsetCenterOfMassShape::OffsetCenterOfMassShape(const OffsetCenterOfMassShapeSettings &inSettings, ShapeResult &outResult) :
-	DecoratedShape(inSettings, outResult),
+	DecoratedShape(EShapeSubType::OffsetCenterOfMass, inSettings, outResult),
 	mOffset(inSettings.mOffset)
 {
 	if (outResult.HasError())
@@ -136,20 +131,26 @@ void OffsetCenterOfMassShape::TransformShape(Mat44Arg inCenterOfMassTransform, T
 	mInnerShape->TransformShape(inCenterOfMassTransform * Mat44::sTranslation(-mOffset), ioCollector);
 }
 
-void OffsetCenterOfMassShape::sCollideOffsetCenterOfMassShapeVsShape(const OffsetCenterOfMassShape *inShape1, const Shape *inShape2, Vec3Arg inScale1, Vec3Arg inScale2, Mat44Arg inCenterOfMassTransform1, Mat44Arg inCenterOfMassTransform2, const SubShapeIDCreator &inSubShapeIDCreator1, const SubShapeIDCreator &inSubShapeIDCreator2, const CollideShapeSettings &inCollideShapeSettings, CollideShapeCollector &ioCollector)
+void OffsetCenterOfMassShape::sCollideOffsetCenterOfMassVsShape(const Shape *inShape1, const Shape *inShape2, Vec3Arg inScale1, Vec3Arg inScale2, Mat44Arg inCenterOfMassTransform1, Mat44Arg inCenterOfMassTransform2, const SubShapeIDCreator &inSubShapeIDCreator1, const SubShapeIDCreator &inSubShapeIDCreator2, const CollideShapeSettings &inCollideShapeSettings, CollideShapeCollector &ioCollector)
 {	
-	CollisionDispatch::sCollideShapeVsShape(inShape1->mInnerShape, inShape2, inScale1, inScale2, inCenterOfMassTransform1 * Mat44::sTranslation(-inShape1->mOffset), inCenterOfMassTransform2, inSubShapeIDCreator1, inSubShapeIDCreator2, inCollideShapeSettings, ioCollector);
+	JPH_ASSERT(inShape1->GetSubType() == EShapeSubType::OffsetCenterOfMass);
+	const OffsetCenterOfMassShape *shape1 = static_cast<const OffsetCenterOfMassShape *>(inShape1);
+
+	CollisionDispatch::sCollideShapeVsShape(shape1->mInnerShape, inShape2, inScale1, inScale2, inCenterOfMassTransform1 * Mat44::sTranslation(-shape1->mOffset), inCenterOfMassTransform2, inSubShapeIDCreator1, inSubShapeIDCreator2, inCollideShapeSettings, ioCollector);
 }
 
-void OffsetCenterOfMassShape::sCollideShapeVsOffsetCenterOfMassShape(const Shape *inShape1, const OffsetCenterOfMassShape *inShape2, Vec3Arg inScale1, Vec3Arg inScale2, Mat44Arg inCenterOfMassTransform1, Mat44Arg inCenterOfMassTransform2, const SubShapeIDCreator &inSubShapeIDCreator1, const SubShapeIDCreator &inSubShapeIDCreator2, const CollideShapeSettings &inCollideShapeSettings, CollideShapeCollector &ioCollector)
+void OffsetCenterOfMassShape::sCollideShapeVsOffsetCenterOfMass(const Shape *inShape1, const Shape *inShape2, Vec3Arg inScale1, Vec3Arg inScale2, Mat44Arg inCenterOfMassTransform1, Mat44Arg inCenterOfMassTransform2, const SubShapeIDCreator &inSubShapeIDCreator1, const SubShapeIDCreator &inSubShapeIDCreator2, const CollideShapeSettings &inCollideShapeSettings, CollideShapeCollector &ioCollector)
 {
-	CollisionDispatch::sCollideShapeVsShape(inShape1, inShape2->mInnerShape, inScale1, inScale2, inCenterOfMassTransform1, inCenterOfMassTransform2 * Mat44::sTranslation(-inShape2->mOffset), inSubShapeIDCreator1, inSubShapeIDCreator2, inCollideShapeSettings, ioCollector);
+	JPH_ASSERT(inShape2->GetSubType() == EShapeSubType::OffsetCenterOfMass);
+	const OffsetCenterOfMassShape *shape2 = static_cast<const OffsetCenterOfMassShape *>(inShape2);
+
+	CollisionDispatch::sCollideShapeVsShape(inShape1, shape2->mInnerShape, inScale1, inScale2, inCenterOfMassTransform1, inCenterOfMassTransform2 * Mat44::sTranslation(-shape2->mOffset), inSubShapeIDCreator1, inSubShapeIDCreator2, inCollideShapeSettings, ioCollector);
 }
 
-void OffsetCenterOfMassShape::sCastOffsetCenterOfMassShapeVsShape(const ShapeCast &inShapeCast, const ShapeCastSettings &inShapeCastSettings, const Shape *inShape, Vec3Arg inScale, const ShapeFilter &inShapeFilter, Mat44Arg inCenterOfMassTransform2, const SubShapeIDCreator &inSubShapeIDCreator1, const SubShapeIDCreator &inSubShapeIDCreator2, CastShapeCollector &ioCollector)
+void OffsetCenterOfMassShape::sCastOffsetCenterOfMassVsShape(const ShapeCast &inShapeCast, const ShapeCastSettings &inShapeCastSettings, const Shape *inShape, Vec3Arg inScale, const ShapeFilter &inShapeFilter, Mat44Arg inCenterOfMassTransform2, const SubShapeIDCreator &inSubShapeIDCreator1, const SubShapeIDCreator &inSubShapeIDCreator2, CastShapeCollector &ioCollector)
 {
 	// Fetch offset center of mass shape from cast shape
-	JPH_ASSERT(inShapeCast.mShape->GetType() == EShapeType::OffsetCenterOfMass);
+	JPH_ASSERT(inShapeCast.mShape->GetSubType() == EShapeSubType::OffsetCenterOfMass);
 	const OffsetCenterOfMassShape *shape1 = static_cast<const OffsetCenterOfMassShape *>(inShapeCast.mShape.GetPtr());
 
 	// Transform the shape cast and update the shape
@@ -172,4 +173,19 @@ void OffsetCenterOfMassShape::RestoreBinaryState(StreamIn &inStream)
 	inStream.Read(mOffset);
 }
 
+void OffsetCenterOfMassShape::sRegister()
+{
+	ShapeFunctions &f = ShapeFunctions::sGet(EShapeSubType::OffsetCenterOfMass);
+	f.mConstruct = []() -> Shape * { return new OffsetCenterOfMassShape; };
+	f.mColor = Color::sCyan;
+
+	for (EShapeSubType s : sAllSubShapeTypes)
+	{
+		CollisionDispatch::sRegisterCollideShape(EShapeSubType::OffsetCenterOfMass, s, sCollideOffsetCenterOfMassVsShape);
+		CollisionDispatch::sRegisterCollideShape(s, EShapeSubType::OffsetCenterOfMass, sCollideShapeVsOffsetCenterOfMass);
+	}
+
+	CollisionDispatch::sRegisterCastShape(EShapeSubType::OffsetCenterOfMass, sCastOffsetCenterOfMassVsShape);
+}
+
 } // JPH

+ 11 - 24
Jolt/Physics/Collision/Shape/OffsetCenterOfMassShape.h

@@ -34,15 +34,10 @@ public:
 class OffsetCenterOfMassShape final : public DecoratedShape
 {
 public:
-	JPH_DECLARE_RTTI_VIRTUAL(OffsetCenterOfMassShape)
-
 	/// Constructor
-									OffsetCenterOfMassShape() = default;
+									OffsetCenterOfMassShape() : DecoratedShape(EShapeSubType::OffsetCenterOfMass) { }
 									OffsetCenterOfMassShape(const OffsetCenterOfMassShapeSettings &inSettings, ShapeResult &outResult);
 
-	/// Get type
-	virtual EShapeType				GetType() const override								{ return EShapeType::OffsetCenterOfMass; }
-
 	/// Access the offset that is applied to the center of mass
 	const Vec3						GetOffset() const										{ return mOffset; }
 
@@ -103,22 +98,6 @@ public:
 	// See Shape::GetTrianglesNext
 	virtual int						GetTrianglesNext(GetTrianglesContext &ioContext, int inMaxTrianglesRequested, Float3 *outTriangleVertices, const PhysicsMaterial **outMaterials = nullptr) const override { JPH_ASSERT(false, "Cannot call on non-leaf shapes, use CollectTransformedShapes to collect the leaves first!"); return 0; }
 
-	/// Collide 2 shapes and pass any hits on to ioCollector
-	static void						sCollideOffsetCenterOfMassShapeVsShape(const OffsetCenterOfMassShape *inShape1, const Shape *inShape2, Vec3Arg inScale1, Vec3Arg inScale2, Mat44Arg inCenterOfMassTransform1, Mat44Arg inCenterOfMassTransform2, const SubShapeIDCreator &inSubShapeIDCreator1, const SubShapeIDCreator &inSubShapeIDCreator2, const CollideShapeSettings &inCollideShapeSettings, CollideShapeCollector &ioCollector);
-	static void						sCollideShapeVsOffsetCenterOfMassShape(const Shape *inShape1, const OffsetCenterOfMassShape *inShape2, Vec3Arg inScale1, Vec3Arg inScale2, Mat44Arg inCenterOfMassTransform1, Mat44Arg inCenterOfMassTransform2, const SubShapeIDCreator &inSubShapeIDCreator1, const SubShapeIDCreator &inSubShapeIDCreator2, const CollideShapeSettings &inCollideShapeSettings, CollideShapeCollector &ioCollector);
-
-	/// Cast an offset center of mass shape againt a shape, reports hits to ioCollector
-	/// @param inShapeCast The shape to cast against the other shape and its start and direction
-	/// @param inShapeCastSettings Settings for performing the cast
-	/// @param inShape The shape to cast against.
-	/// @param inScale Local space scale for the shape to cast against.
-	/// @param inShapeFilter Determines if sub shapes of the shape can collide
-	/// @param inCenterOfMassTransform2 Is the center of mass transform of shape 2 (excluding scale), this is used to provide a transform to the shape cast result so that local quantities can be transformed into world space.
-	/// @param inSubShapeIDCreator1 Class that tracks the current sub shape ID for the casting shape
-	/// @param inSubShapeIDCreator2 Class that tracks the current sub shape ID for the shape we're casting against
-	/// @param ioCollector The collector that receives the results.
-	static void						sCastOffsetCenterOfMassShapeVsShape(const ShapeCast &inShapeCast, const ShapeCastSettings &inShapeCastSettings, const Shape *inShape, Vec3Arg inScale, const ShapeFilter &inShapeFilter, Mat44Arg inCenterOfMassTransform2, const SubShapeIDCreator &inSubShapeIDCreator1, const SubShapeIDCreator &inSubShapeIDCreator2, CastShapeCollector &ioCollector);
-
 	// See Shape
 	virtual void					SaveBinaryState(StreamOut &inStream) const override;
 
@@ -131,11 +110,19 @@ public:
 	// See Shape::IsValidScale
 	virtual bool					IsValidScale(Vec3Arg inScale) const override			{ return mInnerShape->IsValidScale(inScale); }
 
+	// Register shape functions with the registry
+	static void						sRegister();
+
 protected:
 	// See: Shape::RestoreBinaryState
 	virtual void					RestoreBinaryState(StreamIn &inStream) override;
-		
-	Vec3							mCenterOfMass;											///< Position of the center of mass
+
+private:
+	// Helper functions called by CollisionDispatch
+	static void						sCollideOffsetCenterOfMassVsShape(const Shape *inShape1, const Shape *inShape2, Vec3Arg inScale1, Vec3Arg inScale2, Mat44Arg inCenterOfMassTransform1, Mat44Arg inCenterOfMassTransform2, const SubShapeIDCreator &inSubShapeIDCreator1, const SubShapeIDCreator &inSubShapeIDCreator2, const CollideShapeSettings &inCollideShapeSettings, CollideShapeCollector &ioCollector);
+	static void						sCollideShapeVsOffsetCenterOfMass(const Shape *inShape1, const Shape *inShape2, Vec3Arg inScale1, Vec3Arg inScale2, Mat44Arg inCenterOfMassTransform1, Mat44Arg inCenterOfMassTransform2, const SubShapeIDCreator &inSubShapeIDCreator1, const SubShapeIDCreator &inSubShapeIDCreator2, const CollideShapeSettings &inCollideShapeSettings, CollideShapeCollector &ioCollector);
+	static void						sCastOffsetCenterOfMassVsShape(const ShapeCast &inShapeCast, const ShapeCastSettings &inShapeCastSettings, const Shape *inShape, Vec3Arg inScale, const ShapeFilter &inShapeFilter, Mat44Arg inCenterOfMassTransform2, const SubShapeIDCreator &inSubShapeIDCreator1, const SubShapeIDCreator &inSubShapeIDCreator2, CastShapeCollector &ioCollector);
+
 	Vec3							mOffset;												///< Offset of the center of mass
 };
 

+ 30 - 14
Jolt/Physics/Collision/Shape/RotatedTranslatedShape.cpp

@@ -22,11 +22,6 @@ JPH_IMPLEMENT_SERIALIZABLE_VIRTUAL(RotatedTranslatedShapeSettings)
 	JPH_ADD_ATTRIBUTE(RotatedTranslatedShapeSettings, mRotation)
 }
 
-JPH_IMPLEMENT_RTTI_VIRTUAL(RotatedTranslatedShape)
-{
-	JPH_ADD_BASE_CLASS(RotatedTranslatedShape, DecoratedShape)
-}
-
 ShapeSettings::ShapeResult RotatedTranslatedShapeSettings::Create() const
 { 
 	if (mCachedResult.IsEmpty())
@@ -35,7 +30,7 @@ ShapeSettings::ShapeResult RotatedTranslatedShapeSettings::Create() const
 }
 
 RotatedTranslatedShape::RotatedTranslatedShape(const RotatedTranslatedShapeSettings &inSettings, ShapeResult &outResult) :
-	DecoratedShape(inSettings, outResult)
+	DecoratedShape(EShapeSubType::RotatedTranslated, inSettings, outResult)
 {
 	if (outResult.HasError())
 		return;
@@ -161,26 +156,32 @@ void RotatedTranslatedShape::TransformShape(Mat44Arg inCenterOfMassTransform, Tr
 	mInnerShape->TransformShape(inCenterOfMassTransform * Mat44::sRotation(mRotation), ioCollector);
 }
 
-void RotatedTranslatedShape::sCollideRotatedTranslatedVsShape(const RotatedTranslatedShape *inShape1, const Shape *inShape2, Vec3Arg inScale1, Vec3Arg inScale2, Mat44Arg inCenterOfMassTransform1, Mat44Arg inCenterOfMassTransform2, const SubShapeIDCreator &inSubShapeIDCreator1, const SubShapeIDCreator &inSubShapeIDCreator2, const CollideShapeSettings &inCollideShapeSettings, CollideShapeCollector &ioCollector)
+void RotatedTranslatedShape::sCollideRotatedTranslatedVsShape(const Shape *inShape1, const Shape *inShape2, Vec3Arg inScale1, Vec3Arg inScale2, Mat44Arg inCenterOfMassTransform1, Mat44Arg inCenterOfMassTransform2, const SubShapeIDCreator &inSubShapeIDCreator1, const SubShapeIDCreator &inSubShapeIDCreator2, const CollideShapeSettings &inCollideShapeSettings, CollideShapeCollector &ioCollector)
 {	
+	JPH_ASSERT(inShape1->GetSubType() == EShapeSubType::RotatedTranslated);
+	const RotatedTranslatedShape *shape1 = static_cast<const RotatedTranslatedShape *>(inShape1);
+
 	// Get world transform of 1
-	Mat44 transform1 = inCenterOfMassTransform1 * Mat44::sRotation(inShape1->mRotation);
+	Mat44 transform1 = inCenterOfMassTransform1 * Mat44::sRotation(shape1->mRotation);
 
-	CollisionDispatch::sCollideShapeVsShape(inShape1->mInnerShape, inShape2, inShape1->TransformScale(inScale1), inScale2, transform1, inCenterOfMassTransform2, inSubShapeIDCreator1, inSubShapeIDCreator2, inCollideShapeSettings, ioCollector);
+	CollisionDispatch::sCollideShapeVsShape(shape1->mInnerShape, inShape2, shape1->TransformScale(inScale1), inScale2, transform1, inCenterOfMassTransform2, inSubShapeIDCreator1, inSubShapeIDCreator2, inCollideShapeSettings, ioCollector);
 }
 
-void RotatedTranslatedShape::sCollideShapeVsRotatedTranslated(const Shape *inShape1, const RotatedTranslatedShape *inShape2, Vec3Arg inScale1, Vec3Arg inScale2, Mat44Arg inCenterOfMassTransform1, Mat44Arg inCenterOfMassTransform2, const SubShapeIDCreator &inSubShapeIDCreator1, const SubShapeIDCreator &inSubShapeIDCreator2, const CollideShapeSettings &inCollideShapeSettings, CollideShapeCollector &ioCollector)
+void RotatedTranslatedShape::sCollideShapeVsRotatedTranslated(const Shape *inShape1, const Shape *inShape2, Vec3Arg inScale1, Vec3Arg inScale2, Mat44Arg inCenterOfMassTransform1, Mat44Arg inCenterOfMassTransform2, const SubShapeIDCreator &inSubShapeIDCreator1, const SubShapeIDCreator &inSubShapeIDCreator2, const CollideShapeSettings &inCollideShapeSettings, CollideShapeCollector &ioCollector)
 {
+	JPH_ASSERT(inShape2->GetSubType() == EShapeSubType::RotatedTranslated);
+	const RotatedTranslatedShape *shape2 = static_cast<const RotatedTranslatedShape *>(inShape2);
+
 	// Get world transform of 2
-	Mat44 transform2 = inCenterOfMassTransform2 * Mat44::sRotation(inShape2->mRotation);
+	Mat44 transform2 = inCenterOfMassTransform2 * Mat44::sRotation(shape2->mRotation);
 
-	CollisionDispatch::sCollideShapeVsShape(inShape1, inShape2->mInnerShape, inScale1, inShape2->TransformScale(inScale2), inCenterOfMassTransform1, transform2, inSubShapeIDCreator1, inSubShapeIDCreator2, inCollideShapeSettings, ioCollector);
+	CollisionDispatch::sCollideShapeVsShape(inShape1, shape2->mInnerShape, inScale1, shape2->TransformScale(inScale2), inCenterOfMassTransform1, transform2, inSubShapeIDCreator1, inSubShapeIDCreator2, inCollideShapeSettings, ioCollector);
 }
 
-void RotatedTranslatedShape::sCastRotatedTranslatedShapeVsShape(const ShapeCast &inShapeCast, const ShapeCastSettings &inShapeCastSettings, const Shape *inShape, Vec3Arg inScale, const ShapeFilter &inShapeFilter, Mat44Arg inCenterOfMassTransform2, const SubShapeIDCreator &inSubShapeIDCreator1, const SubShapeIDCreator &inSubShapeIDCreator2, CastShapeCollector &ioCollector)
+void RotatedTranslatedShape::sCastRotatedTranslatedVsShape(const ShapeCast &inShapeCast, const ShapeCastSettings &inShapeCastSettings, const Shape *inShape, Vec3Arg inScale, const ShapeFilter &inShapeFilter, Mat44Arg inCenterOfMassTransform2, const SubShapeIDCreator &inSubShapeIDCreator1, const SubShapeIDCreator &inSubShapeIDCreator2, CastShapeCollector &ioCollector)
 {
 	// Fetch rotated translated shape from cast shape
-	JPH_ASSERT(inShapeCast.mShape->GetType() == EShapeType::RotatedTranslated);
+	JPH_ASSERT(inShapeCast.mShape->GetSubType() == EShapeSubType::RotatedTranslated);
 	const RotatedTranslatedShape *shape1 = static_cast<const RotatedTranslatedShape *>(inShapeCast.mShape.GetPtr());
 
 	// Transform the shape cast and update the shape
@@ -222,4 +223,19 @@ bool RotatedTranslatedShape::IsValidScale(Vec3Arg inScale) const
 	return mInnerShape->IsValidScale(ScaleHelpers::RotateScale(mRotation, inScale));
 }
 
+void RotatedTranslatedShape::sRegister()
+{
+	ShapeFunctions &f = ShapeFunctions::sGet(EShapeSubType::RotatedTranslated);
+	f.mConstruct = []() -> Shape * { return new RotatedTranslatedShape; };
+	f.mColor = Color::sBlue;
+
+	for (EShapeSubType s : sAllSubShapeTypes)
+	{
+		CollisionDispatch::sRegisterCollideShape(EShapeSubType::RotatedTranslated, s, sCollideRotatedTranslatedVsShape);
+		CollisionDispatch::sRegisterCollideShape(s, EShapeSubType::RotatedTranslated, sCollideShapeVsRotatedTranslated);
+	}
+
+	CollisionDispatch::sRegisterCastShape(EShapeSubType::RotatedTranslated, sCastRotatedTranslatedVsShape);
+}
+
 } // JPH

+ 9 - 22
Jolt/Physics/Collision/Shape/RotatedTranslatedShape.h

@@ -37,15 +37,10 @@ public:
 class RotatedTranslatedShape final : public DecoratedShape
 {
 public:
-	JPH_DECLARE_RTTI_VIRTUAL(RotatedTranslatedShape)
-
 	/// Constructor
-									RotatedTranslatedShape() = default;
+									RotatedTranslatedShape() : DecoratedShape(EShapeSubType::RotatedTranslated) { }
 									RotatedTranslatedShape(const RotatedTranslatedShapeSettings &inSettings, ShapeResult &outResult);
 
-	/// Get type
-	virtual EShapeType				GetType() const override								{ return EShapeType::RotatedTranslated; }
-
 	/// Access the rotation that is applied to the inner shape
 	const Quat						GetRotation() const										{ return mRotation; }
 
@@ -109,22 +104,6 @@ public:
 	// See Shape::GetTrianglesNext
 	virtual int						GetTrianglesNext(GetTrianglesContext &ioContext, int inMaxTrianglesRequested, Float3 *outTriangleVertices, const PhysicsMaterial **outMaterials = nullptr) const override { JPH_ASSERT(false, "Cannot call on non-leaf shapes, use CollectTransformedShapes to collect the leaves first!"); return 0; }
 
-	/// Collide 2 shapes and pass any hits on to ioCollector
-	static void						sCollideRotatedTranslatedVsShape(const RotatedTranslatedShape *inShape1, const Shape *inShape2, Vec3Arg inScale1, Vec3Arg inScale2, Mat44Arg inCenterOfMassTransform1, Mat44Arg inCenterOfMassTransform2, const SubShapeIDCreator &inSubShapeIDCreator1, const SubShapeIDCreator &inSubShapeIDCreator2, const CollideShapeSettings &inCollideShapeSettings, CollideShapeCollector &ioCollector);
-	static void						sCollideShapeVsRotatedTranslated(const Shape *inShape1, const RotatedTranslatedShape *inShape2, Vec3Arg inScale1, Vec3Arg inScale2, Mat44Arg inCenterOfMassTransform1, Mat44Arg inCenterOfMassTransform2, const SubShapeIDCreator &inSubShapeIDCreator1, const SubShapeIDCreator &inSubShapeIDCreator2, const CollideShapeSettings &inCollideShapeSettings, CollideShapeCollector &ioCollector);
-
-	/// Cast a rotated translated shape againt a shape, reports hits to ioCollector
-	/// @param inShapeCast The shape to cast against the other shape and its start and direction
-	/// @param inShapeCastSettings Settings for performing the cast
-	/// @param inShape The shape to cast against.
-	/// @param inScale Local space scale for the shape to cast against.
-	/// @param inShapeFilter Determines if sub shapes of the shape can collide
-	/// @param inCenterOfMassTransform2 Is the center of mass transform of shape 2 (excluding scale), this is used to provide a transform to the shape cast result so that local quantities can be transformed into world space.
-	/// @param inSubShapeIDCreator1 Class that tracks the current sub shape ID for the casting shape
-	/// @param inSubShapeIDCreator2 Class that tracks the current sub shape ID for the shape we're casting against
-	/// @param ioCollector The collector that receives the results.
-	static void						sCastRotatedTranslatedShapeVsShape(const ShapeCast &inShapeCast, const ShapeCastSettings &inShapeCastSettings, const Shape *inShape, Vec3Arg inScale, const ShapeFilter &inShapeFilter, Mat44Arg inCenterOfMassTransform2, const SubShapeIDCreator &inSubShapeIDCreator1, const SubShapeIDCreator &inSubShapeIDCreator2, CastShapeCollector &ioCollector);
-
 	// See Shape
 	virtual void					SaveBinaryState(StreamOut &inStream) const override;
 
@@ -137,11 +116,19 @@ public:
 	// See Shape::IsValidScale
 	virtual bool					IsValidScale(Vec3Arg inScale) const override;
 
+	// Register shape functions with the registry
+	static void						sRegister();
+
 protected:
 	// See: Shape::RestoreBinaryState
 	virtual void					RestoreBinaryState(StreamIn &inStream) override;
 
 private:
+	// Helper functions called by CollisionDispatch
+	static void						sCollideRotatedTranslatedVsShape(const Shape *inShape1, const Shape *inShape2, Vec3Arg inScale1, Vec3Arg inScale2, Mat44Arg inCenterOfMassTransform1, Mat44Arg inCenterOfMassTransform2, const SubShapeIDCreator &inSubShapeIDCreator1, const SubShapeIDCreator &inSubShapeIDCreator2, const CollideShapeSettings &inCollideShapeSettings, CollideShapeCollector &ioCollector);
+	static void						sCollideShapeVsRotatedTranslated(const Shape *inShape1, const Shape *inShape2, Vec3Arg inScale1, Vec3Arg inScale2, Mat44Arg inCenterOfMassTransform1, Mat44Arg inCenterOfMassTransform2, const SubShapeIDCreator &inSubShapeIDCreator1, const SubShapeIDCreator &inSubShapeIDCreator2, const CollideShapeSettings &inCollideShapeSettings, CollideShapeCollector &ioCollector);
+	static void						sCastRotatedTranslatedVsShape(const ShapeCast &inShapeCast, const ShapeCastSettings &inShapeCastSettings, const Shape *inShape, Vec3Arg inScale, const ShapeFilter &inShapeFilter, Mat44Arg inCenterOfMassTransform2, const SubShapeIDCreator &inSubShapeIDCreator1, const SubShapeIDCreator &inSubShapeIDCreator2, CastShapeCollector &ioCollector);
+
 	/// Transform the scale to the local space of the child shape
 	inline Vec3						TransformScale(Vec3Arg inScale) const
 	{

+ 43 - 6
Jolt/Physics/Collision/Shape/ScaledShape.cpp

@@ -5,7 +5,9 @@
 
 #include <Physics/Collision/Shape/ScaledShape.h>
 #include <Physics/Collision/RayCast.h>
+#include <Physics/Collision/ShapeCast.h>
 #include <Physics/Collision/TransformedShape.h>
+#include <Physics/Collision/CollisionDispatch.h>
 #include <ObjectStream/TypeDeclarations.h>
 #include <Core/StreamIn.h>
 #include <Core/StreamOut.h>
@@ -19,11 +21,6 @@ JPH_IMPLEMENT_SERIALIZABLE_VIRTUAL(ScaledShapeSettings)
 	JPH_ADD_ATTRIBUTE(ScaledShapeSettings, mScale)
 }
 
-JPH_IMPLEMENT_RTTI_VIRTUAL(ScaledShape)
-{
-	JPH_ADD_BASE_CLASS(ScaledShape, DecoratedShape)
-}
-
 ShapeSettings::ShapeResult ScaledShapeSettings::Create() const
 { 
 	if (mCachedResult.IsEmpty())
@@ -32,7 +29,7 @@ ShapeSettings::ShapeResult ScaledShapeSettings::Create() const
 }
 
 ScaledShape::ScaledShape(const ScaledShapeSettings &inSettings, ShapeResult &outResult) :
-	DecoratedShape(inSettings, outResult),
+	DecoratedShape(EShapeSubType::Scaled, inSettings, outResult),
 	mScale(inSettings.mScale)
 {
 	if (outResult.HasError())
@@ -160,4 +157,44 @@ bool ScaledShape::IsValidScale(Vec3Arg inScale) const
 	return mInnerShape->IsValidScale(inScale * mScale);
 }
 
+void ScaledShape::sCollideScaledVsShape(const Shape *inShape1, const Shape *inShape2, Vec3Arg inScale1, Vec3Arg inScale2, Mat44Arg inCenterOfMassTransform1, Mat44Arg inCenterOfMassTransform2, const SubShapeIDCreator &inSubShapeIDCreator1, const SubShapeIDCreator &inSubShapeIDCreator2, const CollideShapeSettings &inCollideShapeSettings, CollideShapeCollector &ioCollector)
+{	
+	JPH_ASSERT(inShape1->GetSubType() == EShapeSubType::Scaled);
+	const ScaledShape *shape1 = static_cast<const ScaledShape *>(inShape1);
+
+	CollisionDispatch::sCollideShapeVsShape(shape1->GetInnerShape(), inShape2, inScale1 * shape1->GetScale(), inScale2, inCenterOfMassTransform1, inCenterOfMassTransform2, inSubShapeIDCreator1, inSubShapeIDCreator2, inCollideShapeSettings, ioCollector);
+}
+
+void ScaledShape::sCollideShapeVsScaled(const Shape *inShape1, const Shape *inShape2, Vec3Arg inScale1, Vec3Arg inScale2, Mat44Arg inCenterOfMassTransform1, Mat44Arg inCenterOfMassTransform2, const SubShapeIDCreator &inSubShapeIDCreator1, const SubShapeIDCreator &inSubShapeIDCreator2, const CollideShapeSettings &inCollideShapeSettings, CollideShapeCollector &ioCollector)
+{
+	JPH_ASSERT(inShape2->GetSubType() == EShapeSubType::Scaled);
+	const ScaledShape *shape2 = static_cast<const ScaledShape *>(inShape2);
+
+	CollisionDispatch::sCollideShapeVsShape(inShape1, shape2->GetInnerShape(), inScale1, inScale2 * shape2->GetScale(), inCenterOfMassTransform1, inCenterOfMassTransform2, inSubShapeIDCreator1, inSubShapeIDCreator2, inCollideShapeSettings, ioCollector);
+}
+
+void ScaledShape::sCastScaledVsShape(const ShapeCast &inShapeCast, const ShapeCastSettings &inShapeCastSettings, const Shape *inShape, Vec3Arg inScale, const ShapeFilter &inShapeFilter, Mat44Arg inCenterOfMassTransform2, const SubShapeIDCreator &inSubShapeIDCreator1, const SubShapeIDCreator &inSubShapeIDCreator2, CastShapeCollector &ioCollector)
+{
+	JPH_ASSERT(inShapeCast.mShape->GetSubType() == EShapeSubType::Scaled);
+	const ScaledShape *shape = static_cast<const ScaledShape *>(inShapeCast.mShape.GetPtr());
+
+	ShapeCast scaled_cast(shape->GetInnerShape(), inShapeCast.mScale * shape->GetScale(), inShapeCast.mCenterOfMassStart, inShapeCast.mDirection);
+	CollisionDispatch::sCastShapeVsShape(scaled_cast, inShapeCastSettings, inShape, inScale, inShapeFilter, inCenterOfMassTransform2, inSubShapeIDCreator1, inSubShapeIDCreator2, ioCollector);
+}
+
+void ScaledShape::sRegister()
+{
+	ShapeFunctions &f = ShapeFunctions::sGet(EShapeSubType::Scaled);
+	f.mConstruct = []() -> Shape * { return new ScaledShape; };
+	f.mColor = Color::sYellow;
+
+	for (EShapeSubType s : sAllSubShapeTypes)
+	{
+		CollisionDispatch::sRegisterCollideShape(EShapeSubType::Scaled, s, sCollideScaledVsShape);
+		CollisionDispatch::sRegisterCollideShape(s, EShapeSubType::Scaled, sCollideShapeVsScaled);
+	}
+
+	CollisionDispatch::sRegisterCastShape(EShapeSubType::Scaled, sCastScaledVsShape);
+}
+
 } // JPH

+ 13 - 7
Jolt/Physics/Collision/Shape/ScaledShape.h

@@ -7,6 +7,9 @@
 
 namespace JPH {
 
+class SubShapeIDCreator;
+class CollideShapeSettings;
+
 /// Class that constructs a ScaledShape
 class ScaledShapeSettings final : public DecoratedShapeSettings
 {
@@ -28,17 +31,12 @@ class ScaledShapeSettings final : public DecoratedShapeSettings
 class ScaledShape final : public DecoratedShape
 {
 public:
-	JPH_DECLARE_RTTI_VIRTUAL(ScaledShape)
-
 	/// Constructor
-									ScaledShape() = default;
+									ScaledShape() : DecoratedShape(EShapeSubType::Scaled) { }
 									ScaledShape(const ScaledShapeSettings &inSettings, ShapeResult &outResult);
 
 	/// Constructor that decorates another shape with a scale
-									ScaledShape(const Shape *inShape, Vec3Arg inScale)		: DecoratedShape(inShape), mScale(inScale) { }
-
-	/// Get type
-	virtual EShapeType				GetType() const override								{ return EShapeType::Scaled; }
+									ScaledShape(const Shape *inShape, Vec3Arg inScale)		: DecoratedShape(EShapeSubType::Scaled, inShape), mScale(inScale) { }
 
 	/// Get the scale
 	Vec3		 					GetScale() const										{ return mScale; }
@@ -112,11 +110,19 @@ public:
 	// See Shape::IsValidScale
 	virtual bool					IsValidScale(Vec3Arg inScale) const override;
 
+	// Register shape functions with the registry
+	static void						sRegister();
+
 protected:
 	// See: Shape::RestoreBinaryState
 	virtual void					RestoreBinaryState(StreamIn &inStream) override;
 
 private:
+	// Helper functions called by CollisionDispatch
+	static void						sCollideScaledVsShape(const Shape *inShape1, const Shape *inShape2, Vec3Arg inScale1, Vec3Arg inScale2, Mat44Arg inCenterOfMassTransform1, Mat44Arg inCenterOfMassTransform2, const SubShapeIDCreator &inSubShapeIDCreator1, const SubShapeIDCreator &inSubShapeIDCreator2, const CollideShapeSettings &inCollideShapeSettings, CollideShapeCollector &ioCollector);
+	static void						sCollideShapeVsScaled(const Shape *inShape1, const Shape *inShape2, Vec3Arg inScale1, Vec3Arg inScale2, Mat44Arg inCenterOfMassTransform1, Mat44Arg inCenterOfMassTransform2, const SubShapeIDCreator &inSubShapeIDCreator1, const SubShapeIDCreator &inSubShapeIDCreator2, const CollideShapeSettings &inCollideShapeSettings, CollideShapeCollector &ioCollector);
+	static void						sCastScaledVsShape(const ShapeCast &inShapeCast, const ShapeCastSettings &inShapeCastSettings, const Shape *inShape, Vec3Arg inScale, const ShapeFilter &inShapeFilter, Mat44Arg inCenterOfMassTransform2, const SubShapeIDCreator &inSubShapeIDCreator1, const SubShapeIDCreator &inSubShapeIDCreator2, CastShapeCollector &ioCollector);
+
 	Vec3							mScale = Vec3(1, 1, 1);
 };
 

+ 6 - 16
Jolt/Physics/Collision/Shape/Shape.cpp

@@ -22,14 +22,12 @@ JPH_IMPLEMENT_SERIALIZABLE_ABSTRACT_BASE(ShapeSettings)
 	JPH_ADD_ATTRIBUTE(ShapeSettings, mUserData)
 }
 
-JPH_IMPLEMENT_RTTI_ABSTRACT_BASE(Shape)
-{
-}
-
 #ifdef JPH_DEBUG_RENDERER
 bool Shape::sDrawSubmergedVolumes = false;
 #endif // JPH_DEBUG_RENDERER
 
+ShapeFunctions ShapeFunctions::sRegistry[NumSubShapeTypes];
+
 TransformedShape Shape::GetSubShapeTransformedShape(const SubShapeID &inSubShapeID, Vec3Arg inPositionCOM, QuatArg inRotation, Vec3Arg inScale, SubShapeID &outRemainder) const
 {
 	// We have reached the leaf shape so there is no remainder
@@ -59,7 +57,7 @@ void Shape::TransformShape(Mat44Arg inCenterOfMassTransform, TransformedShapeCol
 
 void Shape::SaveBinaryState(StreamOut &inStream) const
 { 
-	inStream.Write(GetRTTI()->GetHash());
+	inStream.Write(mShapeSubType);
 	inStream.Write(mUserData);
 }
 
@@ -74,24 +72,16 @@ Shape::ShapeResult Shape::sRestoreFromBinaryState(StreamIn &inStream)
 	ShapeResult result;
 
 	// Read the type of the shape
-	uint32 hash;
-	inStream.Read(hash);
+	EShapeSubType shape_sub_type;
+	inStream.Read(shape_sub_type);
 	if (inStream.IsEOF() || inStream.IsFailed())
 	{
 		result.SetError("Failed to read type id");
 		return result;
 	}
 
-	// Get the RTTI for the shape
-	const RTTI *rtti = Factory::sInstance.Find(hash);
-	if (rtti == nullptr)
-	{
-		result.SetError("Failed to resolve type. Type not registered in factory?");
-		return result;
-	}
-
 	// Construct and read the data of the shape
-	Ref<Shape> shape = reinterpret_cast<Shape *>(rtti->CreateObject());
+	Ref<Shape> shape = ShapeFunctions::sGet(shape_sub_type).mConstruct();
 	shape->RestoreBinaryState(inStream);
 	if (inStream.IsEOF() || inStream.IsFailed())
 	{

+ 80 - 14
Jolt/Physics/Collision/Shape/Shape.h

@@ -47,18 +47,66 @@ using PhysicsMaterialRefC = RefConst<PhysicsMaterial>;
 using PhysicsMaterialList = vector<PhysicsMaterialRefC>;
 
 /// Shapes are categorized in groups, each shape can return which group it belongs to through its Shape::GetType function.
-enum class EShapeType
+enum class EShapeType : uint8
 {
-	Convex,							///< All shapes that use the generic convex vs convex collision detection system (box, sphere, capsule, tapered capsule, cylinder, triangle)
-	Mesh,							///< Used only by MeshShape
-	HeightField,					///< Used only by HeightFieldShape
-	StaticCompound,					///< Used only by StaticCompoundShape
-	MutableCompound,				///< Used only by MutableCompoundShape
-	RotatedTranslated,				///< Used only by RotatedTranslatedShape
-	Scaled,							///< Used only by ScaledShape
-	OffsetCenterOfMass,				///< Used only by OffsetCenterOfMassShape
+	Convex,							///< Used by ConvexShape, all shapes that use the generic convex vs convex collision detection system (box, sphere, capsule, tapered capsule, cylinder, triangle)
+	Compound,						///< Used by CompoundShape
+	Decorated,						///< Used by DecoratedShape
+	Mesh,							///< Used by MeshShape
+	HeightField,					///< Used by HeightFieldShape
+	
+	// User defined shapes
+	User1,
+	User2,
+	User3,
+	User4,
 };
 
+/// This enumerates all shape types, each shape can return its type through Shape::GetSubType
+enum class EShapeSubType : uint8
+{
+	// Convex shapes
+	Sphere,
+	Box,
+	Triangle,
+	Capsule,
+	TaperedCapsule,
+	Cylinder,
+	ConvexHull,
+	
+	// Compound shapes
+	StaticCompound,
+	MutableCompound,
+	
+	// Decorated shapes
+	RotatedTranslated,
+	Scaled,
+	OffsetCenterOfMass,
+
+	// Other shapes
+	Mesh,
+	HeightField,
+	
+	// User defined shapes
+	User1,
+	User2,
+	User3,
+	User4,
+	User5,
+	User6,
+	User7,
+	User8,
+};
+
+// Sets of shape sub types
+static constexpr EShapeSubType sAllSubShapeTypes[] = { EShapeSubType::Sphere, EShapeSubType::Box, EShapeSubType::Triangle, EShapeSubType::Capsule, EShapeSubType::TaperedCapsule, EShapeSubType::Cylinder, EShapeSubType::ConvexHull, EShapeSubType::StaticCompound, EShapeSubType::MutableCompound, EShapeSubType::RotatedTranslated, EShapeSubType::Scaled, EShapeSubType::OffsetCenterOfMass, EShapeSubType::Mesh, EShapeSubType::HeightField, EShapeSubType::User1, EShapeSubType::User2, EShapeSubType::User3, EShapeSubType::User4, EShapeSubType::User5, EShapeSubType::User6, EShapeSubType::User7, EShapeSubType::User8 };
+static constexpr EShapeSubType sConvexSubShapeTypes[] = { EShapeSubType::Sphere, EShapeSubType::Box, EShapeSubType::Triangle, EShapeSubType::Capsule, EShapeSubType::TaperedCapsule, EShapeSubType::Cylinder, EShapeSubType::ConvexHull };
+static constexpr EShapeSubType sCompoundSubShapeTypes[] = { EShapeSubType::StaticCompound, EShapeSubType::MutableCompound };
+static constexpr EShapeSubType sDecoratorSubShapeTypes[] = { EShapeSubType::RotatedTranslated, EShapeSubType::Scaled, EShapeSubType::OffsetCenterOfMass };
+
+/// How many shape types we support
+static constexpr uint NumSubShapeTypes = (uint)size(sAllSubShapeTypes);
+
 /// Class that can construct shapes and that is serializable using the ObjectStream system.
 /// Can be used to store shape data in 'uncooked' form (i.e. in a form that is still human readable and authorable).
 /// Once the shape has been created using the Create() function, the data will be moved into the Shape class
@@ -82,23 +130,39 @@ protected:
 	mutable ShapeResult				mCachedResult;
 };
 
+/// Function table for functions on shapes
+class ShapeFunctions
+{
+public:
+	/// Construct a shape
+	Shape *							(*mConstruct)() = nullptr;
+
+	/// Color of the shape when drawing
+	Color							mColor = Color::sBlack;
+
+	/// Get an entry in the registry for a particular sub type
+	static inline ShapeFunctions &	sGet(EShapeSubType inSubType)										{ return sRegistry[(int)inSubType]; }
+
+private:
+	static ShapeFunctions 			sRegistry[NumSubShapeTypes];
+};
+
 /// Base class for all shapes (collision volume of a body). Defines a virtual interface for collision detection.
 class Shape : public RefTarget<Shape>
 {
 public:
-	JPH_DECLARE_RTTI_ABSTRACT_BASE(Shape)
-
 	using ShapeResult = ShapeSettings::ShapeResult;
 
 	/// Constructor
-									Shape() = default;
-									Shape(const ShapeSettings &inSettings, ShapeResult &outResult)		: mUserData(inSettings.mUserData) { }
+									Shape(EShapeType inType, EShapeSubType inSubType) : mShapeType(inType), mShapeSubType(inSubType) { }
+									Shape(EShapeType inType, EShapeSubType inSubType, const ShapeSettings &inSettings, [[maybe_unused]] ShapeResult &outResult) : mUserData(inSettings.mUserData), mShapeType(inType), mShapeSubType(inSubType) { }
 
 	/// Destructor
 	virtual							~Shape() = default;
 
 	/// Get type
-	virtual EShapeType				GetType() const = 0;
+	inline EShapeType				GetType() const														{ return mShapeType; }
+	inline EShapeSubType			GetSubType() const													{ return mShapeSubType; }
 
 	/// User data (to be used freely by the application)
 	uint32							GetUserData() const													{ return mUserData; }
@@ -299,6 +363,8 @@ protected:
 
 private:
 	uint32							mUserData = 0;
+	EShapeType						mShapeType;
+	EShapeSubType					mShapeSubType;
 };
 
 } // JPH

+ 8 - 6
Jolt/Physics/Collision/Shape/SphereShape.cpp

@@ -28,11 +28,6 @@ JPH_IMPLEMENT_SERIALIZABLE_VIRTUAL(SphereShapeSettings)
 	JPH_ADD_ATTRIBUTE(SphereShapeSettings, mRadius)
 }
 
-JPH_IMPLEMENT_RTTI_VIRTUAL(SphereShape)
-{
-	JPH_ADD_BASE_CLASS(SphereShape, ConvexShape)
-}
-
 ShapeSettings::ShapeResult SphereShapeSettings::Create() const
 { 
 	if (mCachedResult.IsEmpty())
@@ -41,7 +36,7 @@ ShapeSettings::ShapeResult SphereShapeSettings::Create() const
 }
 
 SphereShape::SphereShape(const SphereShapeSettings &inSettings, ShapeResult &outResult) : 
-	ConvexShape(inSettings, outResult), 
+	ConvexShape(EShapeSubType::Sphere, inSettings, outResult), 
 	mRadius(inSettings.mRadius) 
 { 
 	if (inSettings.mRadius <= 0.0f)
@@ -309,4 +304,11 @@ bool SphereShape::IsValidScale(Vec3Arg inScale) const
 	return ConvexShape::IsValidScale(inScale) && ScaleHelpers::IsUniformScale(inScale.Abs());
 }
 
+void SphereShape::sRegister()
+{
+	ShapeFunctions &f = ShapeFunctions::sGet(EShapeSubType::Sphere);
+	f.mConstruct = []() -> Shape * { return new SphereShape; };
+	f.mColor = Color::sGreen;
+}
+
 } // JPH

+ 5 - 4
Jolt/Physics/Collision/Shape/SphereShape.h

@@ -30,14 +30,12 @@ public:
 class SphereShape final : public ConvexShape
 {
 public:
-	JPH_DECLARE_RTTI_VIRTUAL(SphereShape)
-
 	/// Constructor
-							SphereShape() = default;
+							SphereShape() : ConvexShape(EShapeSubType::Sphere) { }
 							SphereShape(const SphereShapeSettings &inSettings, ShapeResult &outResult);
 
 	/// Create a sphere with radius inRadius
-							SphereShape(float inRadius, const PhysicsMaterial *inMaterial = nullptr)			: ConvexShape(inMaterial), mRadius(inRadius) { JPH_ASSERT(inRadius > 0.0f); }
+							SphereShape(float inRadius, const PhysicsMaterial *inMaterial = nullptr)			: ConvexShape(EShapeSubType::Sphere, inMaterial), mRadius(inRadius) { JPH_ASSERT(inRadius > 0.0f); }
 
 	/// Radius of the sphere
 	float					GetRadius() const																	{ return mRadius; }
@@ -99,6 +97,9 @@ public:
 	// See Shape::IsValidScale
 	virtual bool			IsValidScale(Vec3Arg inScale) const override;
 
+	// Register shape functions with the registry
+	static void				sRegister();
+
 protected:
 	// See: Shape::RestoreBinaryState
 	virtual void			RestoreBinaryState(StreamIn &inStream) override;

+ 26 - 12
Jolt/Physics/Collision/Shape/StaticCompoundShape.cpp

@@ -19,11 +19,6 @@ JPH_IMPLEMENT_SERIALIZABLE_VIRTUAL(StaticCompoundShapeSettings)
 	JPH_ADD_BASE_CLASS(StaticCompoundShapeSettings, CompoundShapeSettings)
 }
 
-JPH_IMPLEMENT_RTTI_VIRTUAL(StaticCompoundShape)
-{
-	JPH_ADD_BASE_CLASS(StaticCompoundShape, CompoundShape)
-}
-
 ShapeSettings::ShapeResult StaticCompoundShapeSettings::Create(TempAllocator &inTempAllocator) const
 { 
 	if (mCachedResult.IsEmpty())
@@ -165,7 +160,7 @@ void StaticCompoundShape::sPartition4(uint *ioBodyIdx, AABox *ioBounds, int inBe
 }
 
 StaticCompoundShape::StaticCompoundShape(const StaticCompoundShapeSettings &inSettings, TempAllocator &inTempAllocator, ShapeResult &outResult) :
-	CompoundShape(inSettings, outResult)
+	CompoundShape(EShapeSubType::StaticCompound, inSettings, outResult)
 {
 	// Check that there's at least 1 shape
 	uint num_subshapes = (uint)inSettings.mSubShapes.size();
@@ -608,10 +603,13 @@ int StaticCompoundShape::GetIntersectingSubShapes(const OrientedBox &inBox, uint
 	return visitor.GetNumResults();
 }
 
-void StaticCompoundShape::sCollideCompoundVsShape(const StaticCompoundShape *inShape1, const Shape *inShape2, Vec3Arg inScale1, Vec3Arg inScale2, Mat44Arg inCenterOfMassTransform1, Mat44Arg inCenterOfMassTransform2, const SubShapeIDCreator &inSubShapeIDCreator1, const SubShapeIDCreator &inSubShapeIDCreator2, const CollideShapeSettings &inCollideShapeSettings, CollideShapeCollector &ioCollector)
+void StaticCompoundShape::sCollideCompoundVsShape(const Shape *inShape1, const Shape *inShape2, Vec3Arg inScale1, Vec3Arg inScale2, Mat44Arg inCenterOfMassTransform1, Mat44Arg inCenterOfMassTransform2, const SubShapeIDCreator &inSubShapeIDCreator1, const SubShapeIDCreator &inSubShapeIDCreator2, const CollideShapeSettings &inCollideShapeSettings, CollideShapeCollector &ioCollector)
 {	
 	JPH_PROFILE_FUNCTION();
 
+	JPH_ASSERT(inShape1->GetSubType() == EShapeSubType::StaticCompound);
+	const StaticCompoundShape *shape1 = static_cast<const StaticCompoundShape *>(inShape1);
+
 	struct Visitor : public CollideCompoundVsShapeVisitor
 	{
 		using CollideCompoundVsShapeVisitor::CollideCompoundVsShapeVisitor;
@@ -634,11 +632,11 @@ void StaticCompoundShape::sCollideCompoundVsShape(const StaticCompoundShape *inS
 		}
 	};
 
-	Visitor visitor(inShape1, inShape2, inScale1, inScale2, inCenterOfMassTransform1, inCenterOfMassTransform2, inSubShapeIDCreator1, inSubShapeIDCreator2, inCollideShapeSettings, ioCollector);
-	inShape1->WalkTree(visitor);
+	Visitor visitor(shape1, inShape2, inScale1, inScale2, inCenterOfMassTransform1, inCenterOfMassTransform2, inSubShapeIDCreator1, inSubShapeIDCreator2, inCollideShapeSettings, ioCollector);
+	shape1->WalkTree(visitor);
 }
 
-void StaticCompoundShape::sCollideShapeVsCompound(const Shape *inShape1, const StaticCompoundShape *inShape2, Vec3Arg inScale1, Vec3Arg inScale2, Mat44Arg inCenterOfMassTransform1, Mat44Arg inCenterOfMassTransform2, const SubShapeIDCreator &inSubShapeIDCreator1, const SubShapeIDCreator &inSubShapeIDCreator2, const CollideShapeSettings &inCollideShapeSettings, CollideShapeCollector &ioCollector)
+void StaticCompoundShape::sCollideShapeVsCompound(const Shape *inShape1, const Shape *inShape2, Vec3Arg inScale1, Vec3Arg inScale2, Mat44Arg inCenterOfMassTransform1, Mat44Arg inCenterOfMassTransform2, const SubShapeIDCreator &inSubShapeIDCreator1, const SubShapeIDCreator &inSubShapeIDCreator2, const CollideShapeSettings &inCollideShapeSettings, CollideShapeCollector &ioCollector)
 {
 	JPH_PROFILE_FUNCTION();
 
@@ -664,8 +662,11 @@ void StaticCompoundShape::sCollideShapeVsCompound(const Shape *inShape1, const S
 		}
 	};
 
-	Visitor visitor(inShape1, inShape2, inScale1, inScale2, inCenterOfMassTransform1, inCenterOfMassTransform2, inSubShapeIDCreator1, inSubShapeIDCreator2, inCollideShapeSettings, ioCollector);
-	inShape2->WalkTree(visitor);
+	JPH_ASSERT(inShape2->GetSubType() == EShapeSubType::StaticCompound);
+	const StaticCompoundShape *shape2 = static_cast<const StaticCompoundShape *>(inShape2);
+
+	Visitor visitor(inShape1, shape2, inScale1, inScale2, inCenterOfMassTransform1, inCenterOfMassTransform2, inSubShapeIDCreator1, inSubShapeIDCreator2, inCollideShapeSettings, ioCollector);
+	shape2->WalkTree(visitor);
 }
 
 void StaticCompoundShape::SaveBinaryState(StreamOut &inStream) const
@@ -682,4 +683,17 @@ void StaticCompoundShape::RestoreBinaryState(StreamIn &inStream)
 	inStream.Read(mNodes);
 }
 
+void StaticCompoundShape::sRegister()
+{
+	ShapeFunctions &f = ShapeFunctions::sGet(EShapeSubType::StaticCompound);
+	f.mConstruct = []() -> Shape * { return new StaticCompoundShape; };
+	f.mColor = Color::sOrange;
+
+	for (EShapeSubType s : sAllSubShapeTypes)
+	{
+		CollisionDispatch::sRegisterCollideShape(EShapeSubType::StaticCompound, s, sCollideCompoundVsShape);
+		CollisionDispatch::sRegisterCollideShape(s, EShapeSubType::StaticCompound, sCollideShapeVsCompound);
+	}
+}
+
 } // JPH

+ 8 - 10
Jolt/Physics/Collision/Shape/StaticCompoundShape.h

@@ -30,15 +30,10 @@ public:
 class StaticCompoundShape final : public CompoundShape
 {
 public:
-	JPH_DECLARE_RTTI_VIRTUAL(StaticCompoundShape)
-
 	/// Constructor
-									StaticCompoundShape() = default;
+									StaticCompoundShape() : CompoundShape(EShapeSubType::StaticCompound) { }
 									StaticCompoundShape(const StaticCompoundShapeSettings &inSettings, TempAllocator &inTempAllocator, ShapeResult &outResult);
 
-	/// Get type
-	virtual EShapeType				GetType() const override								{ return EShapeType::StaticCompound; }
-
 	// See Shape::CastRay
 	virtual bool					CastRay(const RayCast &inRay, const SubShapeIDCreator &inSubShapeIDCreator, RayCastResult &ioHit) const override;
 	virtual void					CastRay(const RayCast &inRay, const RayCastSettings &inRayCastSettings, const SubShapeIDCreator &inSubShapeIDCreator, CastRayCollector &ioCollector) const override;
@@ -58,16 +53,15 @@ public:
 	// See: CompoundShape::GetIntersectingSubShapes
 	virtual int						GetIntersectingSubShapes(const OrientedBox &inBox, uint *outSubShapeIndices, int inMaxSubShapeIndices) const override;
 
-	/// Collide 2 shapes and pass any hits on to ioCollector
-	static void						sCollideCompoundVsShape(const StaticCompoundShape *inShape1, const Shape *inShape2, Vec3Arg inScale1, Vec3Arg inScale2, Mat44Arg inCenterOfMassTransform1, Mat44Arg inCenterOfMassTransform2, const SubShapeIDCreator &inSubShapeIDCreator1, const SubShapeIDCreator &inSubShapeIDCreator2, const CollideShapeSettings &inCollideShapeSettings, CollideShapeCollector &ioCollector);
-	static void						sCollideShapeVsCompound(const Shape *inShape1, const StaticCompoundShape *inShape2, Vec3Arg inScale1, Vec3Arg inScale2, Mat44Arg inCenterOfMassTransform1, Mat44Arg inCenterOfMassTransform2, const SubShapeIDCreator &inSubShapeIDCreator1, const SubShapeIDCreator &inSubShapeIDCreator2, const CollideShapeSettings &inCollideShapeSettings, CollideShapeCollector &ioCollector);
-
 	// See Shape
 	virtual void					SaveBinaryState(StreamOut &inStream) const override;
 
 	// See Shape::GetStats
 	virtual Stats					GetStats() const override								{ return Stats(sizeof(*this) + mSubShapes.size() * sizeof(SubShape) + mNodes.size() * sizeof(Node), 0); }
 
+	// Register shape functions with the registry
+	static void						sRegister();
+
 protected:
 	// See: Shape::RestoreBinaryState
 	virtual void					RestoreBinaryState(StreamIn &inStream) override;
@@ -105,6 +99,10 @@ private:
 	/// After the function returns ioBodyIdx and ioBounds will be shuffled
 	static void						sPartition4(uint *ioBodyIdx, AABox *ioBounds, int inBegin, int inEnd, int *outSplit);
 
+	// Helper functions called by CollisionDispatch
+	static void						sCollideCompoundVsShape(const Shape *inShape1, const Shape *inShape2, Vec3Arg inScale1, Vec3Arg inScale2, Mat44Arg inCenterOfMassTransform1, Mat44Arg inCenterOfMassTransform2, const SubShapeIDCreator &inSubShapeIDCreator1, const SubShapeIDCreator &inSubShapeIDCreator2, const CollideShapeSettings &inCollideShapeSettings, CollideShapeCollector &ioCollector);
+	static void						sCollideShapeVsCompound(const Shape *inShape1, const Shape *inShape2, Vec3Arg inScale1, Vec3Arg inScale2, Mat44Arg inCenterOfMassTransform1, Mat44Arg inCenterOfMassTransform2, const SubShapeIDCreator &inSubShapeIDCreator1, const SubShapeIDCreator &inSubShapeIDCreator2, const CollideShapeSettings &inCollideShapeSettings, CollideShapeCollector &ioCollector);
+
 	// Maximum size of the stack during tree walk
 	static constexpr int			cStackSize = 128;
 

+ 8 - 6
Jolt/Physics/Collision/Shape/TaperedCapsuleShape.cpp

@@ -27,11 +27,6 @@ JPH_IMPLEMENT_SERIALIZABLE_VIRTUAL(TaperedCapsuleShapeSettings)
 	JPH_ADD_ATTRIBUTE(TaperedCapsuleShapeSettings, mBottomRadius)
 }
 
-JPH_IMPLEMENT_RTTI_VIRTUAL(TaperedCapsuleShape)
-{
-	JPH_ADD_BASE_CLASS(TaperedCapsuleShape, ConvexShape)
-}
-
 bool TaperedCapsuleShapeSettings::IsSphere() const
 {
 	return max(mTopRadius, mBottomRadius) >= 2.0f * mHalfHeightOfTaperedCylinder + min(mTopRadius, mBottomRadius);
@@ -87,7 +82,7 @@ TaperedCapsuleShapeSettings::TaperedCapsuleShapeSettings(float inHalfHeightOfTap
 }
 
 TaperedCapsuleShape::TaperedCapsuleShape(const TaperedCapsuleShapeSettings &inSettings, ShapeResult &outResult) :
-	ConvexShape(inSettings, outResult),
+	ConvexShape(EShapeSubType::TaperedCapsule, inSettings, outResult),
 	mTopRadius(inSettings.mTopRadius), 
 	mBottomRadius(inSettings.mBottomRadius)
 { 
@@ -377,4 +372,11 @@ bool TaperedCapsuleShape::IsValidScale(Vec3Arg inScale) const
 	return ConvexShape::IsValidScale(inScale) && ScaleHelpers::IsUniformScale(inScale.Abs());
 }
 
+void TaperedCapsuleShape::sRegister()
+{
+	ShapeFunctions &f = ShapeFunctions::sGet(EShapeSubType::TaperedCapsule);
+	f.mConstruct = []() -> Shape * { return new TaperedCapsuleShape; };
+	f.mColor = Color::sGreen;
+}
+
 } // JPH

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

@@ -36,10 +36,8 @@ class TaperedCapsuleShapeSettings final : public ConvexShapeSettings
 class TaperedCapsuleShape final : public ConvexShape
 {
 public:
-	JPH_DECLARE_RTTI_VIRTUAL(TaperedCapsuleShape)
-
 	/// Constructor
-							TaperedCapsuleShape() = default;
+							TaperedCapsuleShape() : ConvexShape(EShapeSubType::TaperedCapsule) { }
 							TaperedCapsuleShape(const TaperedCapsuleShapeSettings &inSettings, ShapeResult &outResult);
 
 	// See Shape::GetCenterOfMass
@@ -86,6 +84,9 @@ public:
 	// See Shape::IsValidScale
 	virtual bool			IsValidScale(Vec3Arg inScale) const override;
 
+	// Register shape functions with the registry
+	static void				sRegister();
+
 protected:
 	// See: Shape::RestoreBinaryState
 	virtual void			RestoreBinaryState(StreamIn &inStream) override;

+ 8 - 6
Jolt/Physics/Collision/Shape/TriangleShape.cpp

@@ -33,11 +33,6 @@ JPH_IMPLEMENT_SERIALIZABLE_VIRTUAL(TriangleShapeSettings)
 	JPH_ADD_ATTRIBUTE(TriangleShapeSettings, mConvexRadius)
 }
 
-JPH_IMPLEMENT_RTTI_VIRTUAL(TriangleShape)
-{
-	JPH_ADD_BASE_CLASS(TriangleShape, ConvexShape)
-}
-
 ShapeSettings::ShapeResult TriangleShapeSettings::Create() const
 { 
 	if (mCachedResult.IsEmpty())
@@ -46,7 +41,7 @@ ShapeSettings::ShapeResult TriangleShapeSettings::Create() const
 }
 
 TriangleShape::TriangleShape(const TriangleShapeSettings &inSettings, ShapeResult &outResult) :
-	ConvexShape(inSettings, outResult), 
+	ConvexShape(EShapeSubType::Triangle, inSettings, outResult), 
 	mV1(inSettings.mV1), 
 	mV2(inSettings.mV2), 
 	mV3(inSettings.mV3), 
@@ -324,4 +319,11 @@ bool TriangleShape::IsValidScale(Vec3Arg inScale) const
 	return ConvexShape::IsValidScale(inScale) && (mConvexRadius == 0.0f || ScaleHelpers::IsUniformScale(inScale.Abs()));
 }
 
+void TriangleShape::sRegister()
+{
+	ShapeFunctions &f = ShapeFunctions::sGet(EShapeSubType::Triangle);
+	f.mConstruct = []() -> Shape * { return new TriangleShape; };
+	f.mColor = Color::sGreen;
+}
+
 } // JPH

+ 5 - 4
Jolt/Physics/Collision/Shape/TriangleShape.h

@@ -33,15 +33,13 @@ public:
 class TriangleShape final : public ConvexShape
 {
 public:
-	JPH_DECLARE_RTTI_VIRTUAL(TriangleShape)
-
 	/// Constructor
-							TriangleShape() = default;
+							TriangleShape() : ConvexShape(EShapeSubType::Triangle) { }
 							TriangleShape(const TriangleShapeSettings &inSettings, ShapeResult &outResult);
 
 	/// Create a triangle with points (inV1, inV2, inV3) (counter clockwise) and convex radius inConvexRadius.
 	/// Note that the convex radius is currently only used for shape vs shape collision, for all other purposes the triangle is infinitely thin.
-							TriangleShape(Vec3Arg inV1, Vec3Arg inV2, Vec3Arg inV3, float inConvexRadius = 0.0f, const PhysicsMaterial *inMaterial = nullptr) : ConvexShape(inMaterial), mV1(inV1), mV2(inV2), mV3(inV3), mConvexRadius(inConvexRadius) { JPH_ASSERT(inConvexRadius >= 0.0f); }
+							TriangleShape(Vec3Arg inV1, Vec3Arg inV2, Vec3Arg inV3, float inConvexRadius = 0.0f, const PhysicsMaterial *inMaterial = nullptr) : ConvexShape(EShapeSubType::Triangle, inMaterial), mV1(inV1), mV2(inV2), mV3(inV3), mConvexRadius(inConvexRadius) { JPH_ASSERT(inConvexRadius >= 0.0f); }
 
 	/// Convex radius
 	float					GetConvexRadius() const																{ return mConvexRadius; }
@@ -106,6 +104,9 @@ public:
 	// See Shape::IsValidScale
 	virtual bool			IsValidScale(Vec3Arg inScale) const override;
 
+	// Register shape functions with the registry
+	static void				sRegister();
+
 protected:
 	// See: Shape::RestoreBinaryState
 	virtual void			RestoreBinaryState(StreamIn &inStream) override;

+ 38 - 30
Jolt/RegisterTypes.cpp

@@ -6,39 +6,38 @@
 #include <RegisterTypes.h>
 #include <Core/Factory.h>
 #include <Core/RTTI.h>
+#include <Physics/Collision/Shape/TriangleShape.h>
+#include <Physics/Collision/Shape/SphereShape.h>
+#include <Physics/Collision/Shape/BoxShape.h>
+#include <Physics/Collision/Shape/CapsuleShape.h>
+#include <Physics/Collision/Shape/TaperedCapsuleShape.h>
+#include <Physics/Collision/Shape/CylinderShape.h>
+#include <Physics/Collision/Shape/ScaledShape.h>
+#include <Physics/Collision/Shape/MeshShape.h>
+#include <Physics/Collision/Shape/ConvexHullShape.h>
+#include <Physics/Collision/Shape/HeightFieldShape.h>
+#include <Physics/Collision/Shape/RotatedTranslatedShape.h>
+#include <Physics/Collision/Shape/OffsetCenterOfMassShape.h>
+#include <Physics/Collision/Shape/MutableCompoundShape.h>
+#include <Physics/Collision/Shape/StaticCompoundShape.h>
 
 JPH_DECLARE_RTTI_WITH_NAMESPACE_FOR_FACTORY(JPH, Skeleton);
 JPH_DECLARE_RTTI_WITH_NAMESPACE_FOR_FACTORY(JPH, SkeletalAnimation);
 JPH_DECLARE_RTTI_WITH_NAMESPACE_FOR_FACTORY(JPH, CompoundShapeSettings);
-JPH_DECLARE_RTTI_WITH_NAMESPACE_FOR_FACTORY(JPH, CompoundShape);
 JPH_DECLARE_RTTI_WITH_NAMESPACE_FOR_FACTORY(JPH, StaticCompoundShapeSettings);
-JPH_DECLARE_RTTI_WITH_NAMESPACE_FOR_FACTORY(JPH, StaticCompoundShape);
 JPH_DECLARE_RTTI_WITH_NAMESPACE_FOR_FACTORY(JPH, MutableCompoundShapeSettings);
-JPH_DECLARE_RTTI_WITH_NAMESPACE_FOR_FACTORY(JPH, MutableCompoundShape);
 JPH_DECLARE_RTTI_WITH_NAMESPACE_FOR_FACTORY(JPH, TriangleShapeSettings);
-JPH_DECLARE_RTTI_WITH_NAMESPACE_FOR_FACTORY(JPH, TriangleShape);
 JPH_DECLARE_RTTI_WITH_NAMESPACE_FOR_FACTORY(JPH, SphereShapeSettings);
-JPH_DECLARE_RTTI_WITH_NAMESPACE_FOR_FACTORY(JPH, SphereShape);
 JPH_DECLARE_RTTI_WITH_NAMESPACE_FOR_FACTORY(JPH, BoxShapeSettings);
-JPH_DECLARE_RTTI_WITH_NAMESPACE_FOR_FACTORY(JPH, BoxShape);
 JPH_DECLARE_RTTI_WITH_NAMESPACE_FOR_FACTORY(JPH, CapsuleShapeSettings);
-JPH_DECLARE_RTTI_WITH_NAMESPACE_FOR_FACTORY(JPH, CapsuleShape);
 JPH_DECLARE_RTTI_WITH_NAMESPACE_FOR_FACTORY(JPH, TaperedCapsuleShapeSettings);
-JPH_DECLARE_RTTI_WITH_NAMESPACE_FOR_FACTORY(JPH, TaperedCapsuleShape);
 JPH_DECLARE_RTTI_WITH_NAMESPACE_FOR_FACTORY(JPH, CylinderShapeSettings);
-JPH_DECLARE_RTTI_WITH_NAMESPACE_FOR_FACTORY(JPH, CylinderShape);
 JPH_DECLARE_RTTI_WITH_NAMESPACE_FOR_FACTORY(JPH, ScaledShapeSettings);
-JPH_DECLARE_RTTI_WITH_NAMESPACE_FOR_FACTORY(JPH, ScaledShape);
 JPH_DECLARE_RTTI_WITH_NAMESPACE_FOR_FACTORY(JPH, MeshShapeSettings);
-JPH_DECLARE_RTTI_WITH_NAMESPACE_FOR_FACTORY(JPH, MeshShape);
 JPH_DECLARE_RTTI_WITH_NAMESPACE_FOR_FACTORY(JPH, ConvexHullShapeSettings);
-JPH_DECLARE_RTTI_WITH_NAMESPACE_FOR_FACTORY(JPH, ConvexHullShape);
 JPH_DECLARE_RTTI_WITH_NAMESPACE_FOR_FACTORY(JPH, HeightFieldShapeSettings);
-JPH_DECLARE_RTTI_WITH_NAMESPACE_FOR_FACTORY(JPH, HeightFieldShape);
 JPH_DECLARE_RTTI_WITH_NAMESPACE_FOR_FACTORY(JPH, RotatedTranslatedShapeSettings);
-JPH_DECLARE_RTTI_WITH_NAMESPACE_FOR_FACTORY(JPH, RotatedTranslatedShape);
 JPH_DECLARE_RTTI_WITH_NAMESPACE_FOR_FACTORY(JPH, OffsetCenterOfMassShapeSettings);
-JPH_DECLARE_RTTI_WITH_NAMESPACE_FOR_FACTORY(JPH, OffsetCenterOfMassShape);
 JPH_DECLARE_RTTI_WITH_NAMESPACE_FOR_FACTORY(JPH, RagdollSettings);
 JPH_DECLARE_RTTI_WITH_NAMESPACE_FOR_FACTORY(JPH, PointConstraintSettings);
 JPH_DECLARE_RTTI_WITH_NAMESPACE_FOR_FACTORY(JPH, SixDOFConstraintSettings);
@@ -64,38 +63,47 @@ namespace JPH {
 
 void RegisterTypes()
 {
+	// Register base classes first so that we can specialize them later
+	CompoundShape::sRegister();
+	ConvexShape::sRegister();
+
+	// Register compounds before others so that we can specialize them later (register them in reverse order of collision complexity)
+	MutableCompoundShape::sRegister();
+	StaticCompoundShape::sRegister();
+
+	// Leaf classes
+	TriangleShape::sRegister();
+	SphereShape::sRegister();
+	BoxShape::sRegister();
+	CapsuleShape::sRegister();
+	TaperedCapsuleShape::sRegister();
+	CylinderShape::sRegister();
+	MeshShape::sRegister();
+	ConvexHullShape::sRegister();
+	HeightFieldShape::sRegister();
+
+	// Register these last because their collision functions are simple so we want to execute them first (register them in reverse order of collision complexity)
+	RotatedTranslatedShape::sRegister();
+	OffsetCenterOfMassShape::sRegister();
+	ScaledShape::sRegister();
+
 	Factory::sInstance.Register(JPH_RTTI(SkeletalAnimation));
 	Factory::sInstance.Register(JPH_RTTI(Skeleton));
 	Factory::sInstance.Register(JPH_RTTI(CompoundShapeSettings));
-	Factory::sInstance.Register(JPH_RTTI(CompoundShape));
 	Factory::sInstance.Register(JPH_RTTI(StaticCompoundShapeSettings));
-	Factory::sInstance.Register(JPH_RTTI(StaticCompoundShape));
 	Factory::sInstance.Register(JPH_RTTI(MutableCompoundShapeSettings));
-	Factory::sInstance.Register(JPH_RTTI(MutableCompoundShape));
 	Factory::sInstance.Register(JPH_RTTI(TriangleShapeSettings));
-	Factory::sInstance.Register(JPH_RTTI(TriangleShape));
 	Factory::sInstance.Register(JPH_RTTI(SphereShapeSettings));
-	Factory::sInstance.Register(JPH_RTTI(SphereShape));
 	Factory::sInstance.Register(JPH_RTTI(BoxShapeSettings));
-	Factory::sInstance.Register(JPH_RTTI(BoxShape));
 	Factory::sInstance.Register(JPH_RTTI(CapsuleShapeSettings));
-	Factory::sInstance.Register(JPH_RTTI(CapsuleShape));
 	Factory::sInstance.Register(JPH_RTTI(TaperedCapsuleShapeSettings));
-	Factory::sInstance.Register(JPH_RTTI(TaperedCapsuleShape));
 	Factory::sInstance.Register(JPH_RTTI(CylinderShapeSettings));
-	Factory::sInstance.Register(JPH_RTTI(CylinderShape));
 	Factory::sInstance.Register(JPH_RTTI(ScaledShapeSettings));
-	Factory::sInstance.Register(JPH_RTTI(ScaledShape));
 	Factory::sInstance.Register(JPH_RTTI(MeshShapeSettings));
-	Factory::sInstance.Register(JPH_RTTI(MeshShape));
 	Factory::sInstance.Register(JPH_RTTI(ConvexHullShapeSettings));
-	Factory::sInstance.Register(JPH_RTTI(ConvexHullShape));
 	Factory::sInstance.Register(JPH_RTTI(HeightFieldShapeSettings));
-	Factory::sInstance.Register(JPH_RTTI(HeightFieldShape));
 	Factory::sInstance.Register(JPH_RTTI(RotatedTranslatedShapeSettings));
-	Factory::sInstance.Register(JPH_RTTI(RotatedTranslatedShape));
 	Factory::sInstance.Register(JPH_RTTI(OffsetCenterOfMassShapeSettings));
-	Factory::sInstance.Register(JPH_RTTI(OffsetCenterOfMassShape));
 	Factory::sInstance.Register(JPH_RTTI(RagdollSettings));
 	Factory::sInstance.Register(JPH_RTTI(PointConstraintSettings));
 	Factory::sInstance.Register(JPH_RTTI(SixDOFConstraintSettings));

+ 1 - 0
UnitTests/Physics/ShapeTests.cpp

@@ -522,6 +522,7 @@ TEST_SUITE("ShapeTests")
 
 		// Check that the sphere and its user data was preserved
 		CHECK(sphere->GetType() == EShapeType::Convex);
+		CHECK(sphere->GetSubType() == EShapeSubType::Sphere);
 		CHECK(sphere->GetUserData() == 5678);
 		CHECK(static_cast<SphereShape *>(sphere.GetPtr())->GetRadius() == cRadius);
 	}