Browse Source

Make PhysicsWorld a singleton

Panagiotis Christopoulos Charitos 2 years ago
parent
commit
8ebf2ea4b1

+ 4 - 7
AnKi/Core/App.cpp

@@ -130,8 +130,7 @@ void App::cleanup()
 	m_resources = nullptr;
 	deleteInstance(m_mainPool, m_resourceFs);
 	m_resourceFs = nullptr;
-	deleteInstance(m_mainPool, m_physics);
-	m_physics = nullptr;
+	PhysicsWorld::freeSingleton();
 	deleteInstance(m_mainPool, m_rebarPool);
 	m_rebarPool = nullptr;
 	deleteInstance(m_mainPool, m_unifiedGometryMemPool);
@@ -301,8 +300,9 @@ Error App::initInternal(AllocAlignedCallback allocCb, void* allocCbUserData)
 	//
 	// Physics
 	//
-	m_physics = newInstance<PhysicsWorld>(m_mainPool);
-	ANKI_CHECK(m_physics->init(m_mainPool.getAllocationCallback(), m_mainPool.getAllocationCallbackUserData()));
+	PhysicsWorld::allocateSingleton();
+	ANKI_CHECK(PhysicsWorld::getSingleton().init(m_mainPool.getAllocationCallback(),
+												 m_mainPool.getAllocationCallbackUserData()));
 
 	//
 	// Resource FS
@@ -328,7 +328,6 @@ Error App::initInternal(AllocAlignedCallback allocCb, void* allocCbUserData)
 	//
 	ResourceManagerInitInfo rinit;
 	rinit.m_grManager = m_gr;
-	rinit.m_physicsWorld = m_physics;
 	rinit.m_resourceFilesystem = m_resourceFs;
 	rinit.m_unifiedGometryMemoryPool = m_unifiedGometryMemPool;
 	rinit.m_config = m_config;
@@ -375,7 +374,6 @@ Error App::initInternal(AllocAlignedCallback allocCb, void* allocCbUserData)
 	renderInit.m_gpuScenePool = m_gpuSceneMemPool;
 	renderInit.m_gpuSceneMicroPatcher = m_gpuSceneMicroPatcher;
 	renderInit.m_unifiedGometryMemoryPool = m_unifiedGometryMemPool;
-	renderInit.m_physicsWorld = m_physics;
 	m_renderer = newInstance<MainRenderer>(m_mainPool);
 	ANKI_CHECK(m_renderer->init(renderInit));
 
@@ -404,7 +402,6 @@ Error App::initInternal(AllocAlignedCallback allocCb, void* allocCbUserData)
 	sceneInit.m_uiManager = m_ui;
 	sceneInit.m_unifiedGeometryMemPool = m_unifiedGometryMemPool;
 	sceneInit.m_grManager = m_gr;
-	sceneInit.m_physicsWorld = m_physics;
 	ANKI_CHECK(m_scene->init(sceneInit));
 
 	// Inform the script engine about some subsystems

+ 0 - 7
AnKi/Core/App.h

@@ -20,7 +20,6 @@ class NativeWindow;
 class Input;
 class GrManager;
 class MainRenderer;
-class PhysicsWorld;
 class SceneGraph;
 class ScriptManager;
 class ResourceManager;
@@ -115,11 +114,6 @@ public:
 		return *m_script;
 	}
 
-	PhysicsWorld& getPhysicsWorld()
-	{
-		return *m_physics;
-	}
-
 	NativeWindow& getWindow()
 	{
 		return *m_window;
@@ -152,7 +146,6 @@ private:
 	GpuSceneMemoryPool* m_gpuSceneMemPool = nullptr;
 	GpuSceneMicroPatcher* m_gpuSceneMicroPatcher = nullptr;
 	RebarStagingGpuMemoryPool* m_rebarPool = nullptr;
-	PhysicsWorld* m_physics = nullptr;
 	ResourceFilesystem* m_resourceFs = nullptr;
 	ResourceManager* m_resources = nullptr;
 	UiManager* m_ui = nullptr;

+ 1 - 2
AnKi/Physics/Common.cpp

@@ -16,8 +16,7 @@ void PhysicsPtrDeleter::operator()(PhysicsObject* ptr)
 		return;
 	}
 
-	PhysicsWorld& world = ptr->getWorld();
-	world.destroyObject(ptr);
+	PhysicsWorld::getSingleton().destroyObject(ptr);
 }
 
 } // end namespace anki

+ 15 - 0
AnKi/Physics/Common.h

@@ -8,6 +8,7 @@
 #include <AnKi/Util/StdTypes.h>
 #include <AnKi/Util/Enum.h>
 #include <AnKi/Util/Ptr.h>
+#include <AnKi/Util/MemoryPool.h>
 #include <AnKi/Math.h>
 
 #if ANKI_COMPILER_GCC_COMPATIBLE
@@ -44,6 +45,20 @@ namespace anki {
 #define ANKI_PHYS_LOGW(...) ANKI_LOG("PHYS", kWarning, __VA_ARGS__)
 #define ANKI_PHYS_LOGF(...) ANKI_LOG("PHYS", kFatal, __VA_ARGS__)
 
+class PhysicsMemoryPool : public HeapMemoryPool, public MakeSingleton<PhysicsMemoryPool>
+{
+	template<typename>
+	friend class MakeSingleton;
+
+private:
+	PhysicsMemoryPool(AllocAlignedCallback allocCb, void* allocCbUserData)
+		: HeapMemoryPool(allocCb, allocCbUserData, "PhysicsMemPool")
+	{
+	}
+
+	~PhysicsMemoryPool() = default;
+};
+
 // Forward
 class PhysicsObject;
 class PhysicsFilteredObject;

+ 4 - 4
AnKi/Physics/PhysicsBody.cpp

@@ -9,8 +9,8 @@
 
 namespace anki {
 
-PhysicsBody::PhysicsBody(PhysicsWorld* world, const PhysicsBodyInitInfo& init)
-	: PhysicsFilteredObject(kClassType, world)
+PhysicsBody::PhysicsBody(const PhysicsBodyInitInfo& init)
+	: PhysicsFilteredObject(kClassType)
 {
 	ANKI_ASSERT(init.m_mass >= 0.0f);
 
@@ -66,12 +66,12 @@ void PhysicsBody::setMass(F32 mass)
 
 void PhysicsBody::registerToWorld()
 {
-	getWorld().getBtWorld().addRigidBody(m_body.get());
+	PhysicsWorld::getSingleton().getBtWorld().addRigidBody(m_body.get());
 }
 
 void PhysicsBody::unregisterFromWorld()
 {
-	getWorld().getBtWorld().removeRigidBody(m_body.get());
+	PhysicsWorld::getSingleton().getBtWorld().removeRigidBody(m_body.get());
 }
 
 } // end namespace anki

+ 1 - 1
AnKi/Physics/PhysicsBody.h

@@ -123,7 +123,7 @@ private:
 
 	F32 m_mass = 1.0f;
 
-	PhysicsBody(PhysicsWorld* world, const PhysicsBodyInitInfo& init);
+	PhysicsBody(const PhysicsBodyInitInfo& init);
 
 	~PhysicsBody();
 

+ 11 - 12
AnKi/Physics/PhysicsCollisionShape.cpp

@@ -8,11 +8,11 @@
 
 namespace anki {
 
-PhysicsSphere::PhysicsSphere(PhysicsWorld* world, F32 radius)
-	: PhysicsCollisionShape(world, ShapeType::kSphere)
+PhysicsSphere::PhysicsSphere(F32 radius)
+	: PhysicsCollisionShape(ShapeType::kSphere)
 {
 	m_sphere.init(radius);
-	m_sphere->setMargin(getWorld().getCollisionMargin());
+	m_sphere->setMargin(PhysicsWorld::getSingleton().getCollisionMargin());
 	m_sphere->setUserPointer(static_cast<PhysicsObject*>(this));
 }
 
@@ -21,11 +21,11 @@ PhysicsSphere::~PhysicsSphere()
 	m_sphere.destroy();
 }
 
-PhysicsBox::PhysicsBox(PhysicsWorld* world, const Vec3& extend)
-	: PhysicsCollisionShape(world, ShapeType::kBox)
+PhysicsBox::PhysicsBox(const Vec3& extend)
+	: PhysicsCollisionShape(ShapeType::kBox)
 {
 	m_box.init(toBt(extend));
-	m_box->setMargin(getWorld().getCollisionMargin());
+	m_box->setMargin(PhysicsWorld::getSingleton().getCollisionMargin());
 	m_box->setUserPointer(static_cast<PhysicsObject*>(this));
 }
 
@@ -34,9 +34,8 @@ PhysicsBox::~PhysicsBox()
 	m_box.destroy();
 }
 
-PhysicsTriangleSoup::PhysicsTriangleSoup(PhysicsWorld* world, ConstWeakArray<Vec3> positions,
-										 ConstWeakArray<U32> indices, Bool convex)
-	: PhysicsCollisionShape(world, ShapeType::kTrimesh)
+PhysicsTriangleSoup::PhysicsTriangleSoup(ConstWeakArray<Vec3> positions, ConstWeakArray<U32> indices, Bool convex)
+	: PhysicsCollisionShape(ShapeType::kTrimesh)
 {
 	if(!convex)
 	{
@@ -52,13 +51,13 @@ PhysicsTriangleSoup::PhysicsTriangleSoup(PhysicsWorld* world, ConstWeakArray<Vec
 
 		// Create the dynamic shape
 		m_triMesh.m_dynamic.init(m_mesh.get());
-		m_triMesh.m_dynamic->setMargin(getWorld().getCollisionMargin());
+		m_triMesh.m_dynamic->setMargin(PhysicsWorld::getSingleton().getCollisionMargin());
 		m_triMesh.m_dynamic->updateBound();
 		m_triMesh.m_dynamic->setUserPointer(static_cast<PhysicsObject*>(this));
 
 		// And the static one
 		m_triMesh.m_static.init(m_mesh.get(), true);
-		m_triMesh.m_static->setMargin(getWorld().getCollisionMargin());
+		m_triMesh.m_static->setMargin(PhysicsWorld::getSingleton().getCollisionMargin());
 		m_triMesh.m_static->setUserPointer(static_cast<PhysicsObject*>(this));
 	}
 	else
@@ -66,7 +65,7 @@ PhysicsTriangleSoup::PhysicsTriangleSoup(PhysicsWorld* world, ConstWeakArray<Vec
 		m_type = ShapeType::kConvex; // Fake the type
 
 		m_convex.init(&positions[0][0], I32(positions.getSize()), U32(sizeof(Vec3)));
-		m_convex->setMargin(getWorld().getCollisionMargin());
+		m_convex->setMargin(PhysicsWorld::getSingleton().getCollisionMargin());
 		m_convex->setUserPointer(static_cast<PhysicsObject*>(this));
 	}
 }

+ 6 - 7
AnKi/Physics/PhysicsCollisionShape.h

@@ -57,8 +57,8 @@ protected:
 
 	ShapeType m_type;
 
-	PhysicsCollisionShape(PhysicsWorld* world, ShapeType type)
-		: PhysicsObject(kClassType, world)
+	PhysicsCollisionShape(ShapeType type)
+		: PhysicsObject(kClassType)
 		, m_type(type)
 	{
 	}
@@ -103,7 +103,7 @@ class PhysicsSphere final : public PhysicsCollisionShape
 	ANKI_PHYSICS_OBJECT(PhysicsObjectType::kCollisionShape)
 
 private:
-	PhysicsSphere(PhysicsWorld* world, F32 radius);
+	PhysicsSphere(F32 radius);
 
 	~PhysicsSphere();
 };
@@ -114,7 +114,7 @@ class PhysicsBox final : public PhysicsCollisionShape
 	ANKI_PHYSICS_OBJECT(PhysicsObjectType::kCollisionShape)
 
 private:
-	PhysicsBox(PhysicsWorld* world, const Vec3& extend);
+	PhysicsBox(const Vec3& extend);
 
 	~PhysicsBox();
 };
@@ -125,7 +125,7 @@ class PhysicsConvexHull final : public PhysicsCollisionShape
 	ANKI_PHYSICS_OBJECT(PhysicsObjectType::kCollisionShape)
 
 private:
-	PhysicsConvexHull(PhysicsWorld* world, const Vec3* positions, U32 positionsCount, U32 positionsStride);
+	PhysicsConvexHull(const Vec3* positions, U32 positionsCount, U32 positionsStride);
 
 	~PhysicsConvexHull();
 };
@@ -138,8 +138,7 @@ class PhysicsTriangleSoup final : public PhysicsCollisionShape
 private:
 	ClassWrapper<btTriangleMesh> m_mesh;
 
-	PhysicsTriangleSoup(PhysicsWorld* world, ConstWeakArray<Vec3> positions, ConstWeakArray<U32> indices,
-						Bool convex = false);
+	PhysicsTriangleSoup(ConstWeakArray<Vec3> positions, ConstWeakArray<U32> indices, Bool convex = false);
 
 	~PhysicsTriangleSoup();
 };

+ 11 - 11
AnKi/Physics/PhysicsJoint.cpp

@@ -9,33 +9,33 @@
 
 namespace anki {
 
-PhysicsJoint::PhysicsJoint(PhysicsWorld* world, JointType type)
-	: PhysicsObject(kClassType, world)
+PhysicsJoint::PhysicsJoint(JointType type)
+	: PhysicsObject(kClassType)
 	, m_type(type)
 {
 }
 
 void PhysicsJoint::registerToWorld()
 {
-	getWorld().getBtWorld().addConstraint(getJoint());
+	PhysicsWorld::getSingleton().getBtWorld().addConstraint(getJoint());
 }
 
 void PhysicsJoint::unregisterFromWorld()
 {
-	getWorld().getBtWorld().removeConstraint(getJoint());
+	PhysicsWorld::getSingleton().getBtWorld().removeConstraint(getJoint());
 }
 
-PhysicsPoint2PointJoint::PhysicsPoint2PointJoint(PhysicsWorld* world, PhysicsBodyPtr bodyA, const Vec3& relPos)
-	: PhysicsJoint(world, JointType::kP2P)
+PhysicsPoint2PointJoint::PhysicsPoint2PointJoint(PhysicsBodyPtr bodyA, const Vec3& relPos)
+	: PhysicsJoint(JointType::kP2P)
 {
 	m_bodyA = std::move(bodyA);
 	m_p2p.init(*m_bodyA->getBtBody(), toBt(relPos));
 	getJoint()->setUserConstraintPtr(static_cast<PhysicsObject*>(this));
 }
 
-PhysicsPoint2PointJoint::PhysicsPoint2PointJoint(PhysicsWorld* world, PhysicsBodyPtr bodyA, const Vec3& relPosA,
-												 PhysicsBodyPtr bodyB, const Vec3& relPosB)
-	: PhysicsJoint(world, JointType::kP2P)
+PhysicsPoint2PointJoint::PhysicsPoint2PointJoint(PhysicsBodyPtr bodyA, const Vec3& relPosA, PhysicsBodyPtr bodyB,
+												 const Vec3& relPosB)
+	: PhysicsJoint(JointType::kP2P)
 {
 	ANKI_ASSERT(bodyA != bodyB);
 	m_bodyA = std::move(bodyA);
@@ -50,8 +50,8 @@ PhysicsPoint2PointJoint::~PhysicsPoint2PointJoint()
 	m_p2p.destroy();
 }
 
-PhysicsHingeJoint::PhysicsHingeJoint(PhysicsWorld* world, PhysicsBodyPtr bodyA, const Vec3& relPos, const Vec3& axis)
-	: PhysicsJoint(world, JointType::kHinge)
+PhysicsHingeJoint::PhysicsHingeJoint(PhysicsBodyPtr bodyA, const Vec3& relPos, const Vec3& axis)
+	: PhysicsJoint(JointType::kHinge)
 {
 	m_bodyA = std::move(bodyA);
 	m_hinge.init(*m_bodyA->getBtBody(), toBt(relPos), toBt(axis));

+ 6 - 7
AnKi/Physics/PhysicsJoint.h

@@ -55,7 +55,7 @@ protected:
 
 	JointType m_type;
 
-	PhysicsJoint(PhysicsWorld* world, JointType type);
+	PhysicsJoint(JointType type);
 
 	void registerToWorld() override;
 	void unregisterFromWorld() override;
@@ -91,10 +91,9 @@ class PhysicsPoint2PointJoint : public PhysicsJoint
 	ANKI_PHYSICS_OBJECT(PhysicsObjectType::kJoint)
 
 private:
-	PhysicsPoint2PointJoint(PhysicsWorld* world, PhysicsBodyPtr bodyA, const Vec3& relPos);
+	PhysicsPoint2PointJoint(PhysicsBodyPtr bodyA, const Vec3& relPos);
 
-	PhysicsPoint2PointJoint(PhysicsWorld* world, PhysicsBodyPtr bodyA, const Vec3& relPosA, PhysicsBodyPtr bodyB,
-							const Vec3& relPosB);
+	PhysicsPoint2PointJoint(PhysicsBodyPtr bodyA, const Vec3& relPosA, PhysicsBodyPtr bodyB, const Vec3& relPosB);
 
 	~PhysicsPoint2PointJoint();
 };
@@ -105,10 +104,10 @@ class PhysicsHingeJoint : public PhysicsJoint
 	ANKI_PHYSICS_OBJECT(PhysicsObjectType::kJoint)
 
 private:
-	PhysicsHingeJoint(PhysicsWorld* world, PhysicsBodyPtr bodyA, const Vec3& relPos, const Vec3& axis);
+	PhysicsHingeJoint(PhysicsBodyPtr bodyA, const Vec3& relPos, const Vec3& axis);
 
-	PhysicsHingeJoint(PhysicsWorld* world, PhysicsBodyPtr bodyA, const Vec3& relPosA, const Vec3& axisA,
-					  PhysicsBodyPtr bodyB, const Vec3& relPosB, const Vec3& axisB);
+	PhysicsHingeJoint(PhysicsBodyPtr bodyA, const Vec3& relPosA, const Vec3& axisA, PhysicsBodyPtr bodyB,
+					  const Vec3& relPosB, const Vec3& axisB);
 
 	~PhysicsHingeJoint();
 };

+ 1 - 6
AnKi/Physics/PhysicsObject.cpp

@@ -21,14 +21,9 @@ PhysicsFilteredObject::~PhysicsFilteredObject()
 
 		if(pair->shouldDelete())
 		{
-			deleteInstance(getMemoryPool(), pair);
+			deleteInstance(PhysicsMemoryPool::getSingleton(), pair);
 		}
 	}
 }
 
-HeapMemoryPool& PhysicsObject::getMemoryPool()
-{
-	return m_world->getMemoryPool();
-}
-
 } // end namespace anki

+ 8 - 25
AnKi/Physics/PhysicsObject.h

@@ -50,11 +50,9 @@ class PhysicsObject : public IntrusiveListEnabled<PhysicsObject>
 	ANKI_PHYSICS_OBJECT_FRIENDS
 
 public:
-	PhysicsObject(PhysicsObjectType type, PhysicsWorld* world)
-		: m_world(world)
-		, m_type(type)
+	PhysicsObject(PhysicsObjectType type)
+		: m_type(type)
 	{
-		ANKI_ASSERT(m_world);
 	}
 
 	virtual ~PhysicsObject()
@@ -77,19 +75,7 @@ public:
 		return m_userData;
 	}
 
-	PhysicsWorld& getWorld()
-	{
-		return *m_world;
-	}
-
-	const PhysicsWorld& getWorld() const
-	{
-		return *m_world;
-	}
-
 protected:
-	PhysicsWorld* m_world = nullptr;
-
 	void retain() const
 	{
 		m_refcount.fetchAdd(1);
@@ -100,19 +86,16 @@ protected:
 		return m_refcount.fetchSub(1);
 	}
 
-	HeapMemoryPool& getMemoryPool();
-
 private:
+	mutable Atomic<I32> m_refcount = {0};
+	void* m_userData = nullptr;
+
+	PhysicsObjectType m_type;
 	Bool m_registered = false;
 
 	virtual void registerToWorld() = 0;
 
 	virtual void unregisterFromWorld() = 0;
-
-private:
-	mutable Atomic<I32> m_refcount = {0};
-	PhysicsObjectType m_type;
-	void* m_userData = nullptr;
 };
 
 /// This is a factor that will decide if two filtered objects will be checked for collision.
@@ -148,8 +131,8 @@ class PhysicsFilteredObject : public PhysicsObject
 public:
 	ANKI_PHYSICS_OBJECT_FRIENDS
 
-	PhysicsFilteredObject(PhysicsObjectType type, PhysicsWorld* world)
-		: PhysicsObject(type, world)
+	PhysicsFilteredObject(PhysicsObjectType type)
+		: PhysicsObject(type)
 	{
 	}
 

+ 10 - 8
AnKi/Physics/PhysicsPlayerController.cpp

@@ -8,8 +8,8 @@
 
 namespace anki {
 
-PhysicsPlayerController::PhysicsPlayerController(PhysicsWorld* world, const PhysicsPlayerControllerInitInfo& init)
-	: PhysicsFilteredObject(kClassType, world)
+PhysicsPlayerController::PhysicsPlayerController(const PhysicsPlayerControllerInitInfo& init)
+	: PhysicsFilteredObject(kClassType)
 {
 	const btTransform trf = toBt(Transform(init.m_position.xyz0(), Mat3x4::getIdentity(), 1.0f));
 
@@ -37,7 +37,7 @@ PhysicsPlayerController::~PhysicsPlayerController()
 
 void PhysicsPlayerController::registerToWorld()
 {
-	btDynamicsWorld& btworld = getWorld().getBtWorld();
+	btDynamicsWorld& btworld = PhysicsWorld::getSingleton().getBtWorld();
 	btworld.addCollisionObject(m_ghostObject.get(), btBroadphaseProxy::CharacterFilter,
 							   btBroadphaseProxy::StaticFilter | btBroadphaseProxy::DefaultFilter);
 	btworld.addAction(m_controller.get());
@@ -45,8 +45,8 @@ void PhysicsPlayerController::registerToWorld()
 
 void PhysicsPlayerController::unregisterFromWorld()
 {
-	getWorld().getBtWorld().removeAction(m_controller.get());
-	getWorld().getBtWorld().removeCollisionObject(m_ghostObject.get());
+	PhysicsWorld::getSingleton().getBtWorld().removeAction(m_controller.get());
+	PhysicsWorld::getSingleton().getBtWorld().removeCollisionObject(m_ghostObject.get());
 }
 
 void PhysicsPlayerController::moveToPositionForReal()
@@ -56,10 +56,12 @@ void PhysicsPlayerController::moveToPositionForReal()
 		return;
 	}
 
-	getWorld().getBtWorld().getBroadphase()->getOverlappingPairCache()->cleanProxyFromPairs(
-		m_ghostObject->getBroadphaseHandle(), getWorld().getBtWorld().getDispatcher());
+	btDynamicsWorld& btworld = PhysicsWorld::getSingleton().getBtWorld();
 
-	m_controller->reset(&getWorld().getBtWorld());
+	btworld.getBroadphase()->getOverlappingPairCache()->cleanProxyFromPairs(m_ghostObject->getBroadphaseHandle(),
+																			btworld.getDispatcher());
+
+	m_controller->reset(&btworld);
 	m_controller->warp(toBt(m_moveToPosition));
 
 	m_moveToPosition.x() = kMaxF32;

+ 1 - 1
AnKi/Physics/PhysicsPlayerController.h

@@ -55,7 +55,7 @@ private:
 	ClassWrapper<btKinematicCharacterController> m_controller;
 	Vec3 m_moveToPosition = Vec3(kMaxF32);
 
-	PhysicsPlayerController(PhysicsWorld* world, const PhysicsPlayerControllerInitInfo& init);
+	PhysicsPlayerController(const PhysicsPlayerControllerInitInfo& init);
 
 	~PhysicsPlayerController();
 

+ 12 - 11
AnKi/Physics/PhysicsTrigger.cpp

@@ -10,8 +10,8 @@
 
 namespace anki {
 
-PhysicsTrigger::PhysicsTrigger(PhysicsWorld* world, PhysicsCollisionShapePtr shape)
-	: PhysicsFilteredObject(kClassType, world)
+PhysicsTrigger::PhysicsTrigger(PhysicsCollisionShapePtr shape)
+	: PhysicsFilteredObject(kClassType)
 {
 	m_shape = shape;
 
@@ -38,23 +38,23 @@ PhysicsTrigger::~PhysicsTrigger()
 
 		if(pair->shouldDelete())
 		{
-			deleteInstance(getMemoryPool(), pair);
+			deleteInstance(PhysicsMemoryPool::getSingleton(), pair);
 		}
 	}
 
-	m_pairs.destroy(getMemoryPool());
+	m_pairs.destroy(PhysicsMemoryPool::getSingleton());
 
 	m_ghostShape.destroy();
 }
 
 void PhysicsTrigger::registerToWorld()
 {
-	getWorld().getBtWorld().addCollisionObject(m_ghostShape.get());
+	PhysicsWorld::getSingleton().getBtWorld().addCollisionObject(m_ghostShape.get());
 }
 
 void PhysicsTrigger::unregisterFromWorld()
 {
-	getWorld().getBtWorld().removeCollisionObject(m_ghostShape.get());
+	PhysicsWorld::getSingleton().getBtWorld().removeCollisionObject(m_ghostShape.get());
 }
 
 void PhysicsTrigger::processContacts()
@@ -63,12 +63,12 @@ void PhysicsTrigger::processContacts()
 
 	if(m_contactCallback == nullptr)
 	{
-		m_pairs.destroy(getMemoryPool());
+		m_pairs.destroy(PhysicsMemoryPool::getSingleton());
 		return;
 	}
 
 	// Gather the new pairs
-	DynamicArrayRaii<PhysicsTriggerFilteredPair*> newPairs(&getWorld().getTempMemoryPool());
+	DynamicArrayRaii<PhysicsTriggerFilteredPair*> newPairs(&PhysicsWorld::getSingleton().getTempMemoryPool());
 	newPairs.resizeStorage(m_ghostShape->getOverlappingPairs().size());
 	for(U32 i = 0; i < U32(m_ghostShape->getOverlappingPairs().size()); ++i)
 	{
@@ -79,7 +79,8 @@ void PhysicsTrigger::processContacts()
 		PhysicsFilteredObject* obj = dcast<PhysicsFilteredObject*>(aobj);
 
 		Bool isNew;
-		PhysicsTriggerFilteredPair* pair = getWorld().getOrCreatePhysicsTriggerFilteredPair(this, obj, isNew);
+		PhysicsTriggerFilteredPair* pair =
+			PhysicsWorld::getSingleton().getOrCreatePhysicsTriggerFilteredPair(this, obj, isNew);
 		if(pair)
 		{
 			ANKI_ASSERT(pair->isAlive());
@@ -107,7 +108,7 @@ void PhysicsTrigger::processContacts()
 		if(pair->m_filteredObject == nullptr)
 		{
 			// Filtered object died while inside the tigger, destroy the pair
-			deleteInstance(getMemoryPool(), pair);
+			deleteInstance(PhysicsMemoryPool::getSingleton(), pair);
 		}
 		else if(pair->m_frame == m_processContactsFrame)
 		{
@@ -124,7 +125,7 @@ void PhysicsTrigger::processContacts()
 	}
 
 	// Store the new contacts
-	m_pairs.resize(getMemoryPool(), newPairs.getSize());
+	m_pairs.resize(PhysicsMemoryPool::getSingleton(), newPairs.getSize());
 	if(m_pairs.getSize())
 	{
 		memcpy(&m_pairs[0], &newPairs[0], m_pairs.getSizeInBytes());

+ 1 - 1
AnKi/Physics/PhysicsTrigger.h

@@ -67,7 +67,7 @@ private:
 
 	U64 m_processContactsFrame = 0;
 
-	PhysicsTrigger(PhysicsWorld* world, PhysicsCollisionShapePtr shape);
+	PhysicsTrigger(PhysicsCollisionShapePtr shape);
 
 	~PhysicsTrigger();
 

+ 10 - 14
AnKi/Physics/PhysicsWorld.cpp

@@ -13,19 +13,14 @@
 
 namespace anki {
 
-// Ugly but there is no other way
-static HeapMemoryPool* g_pool = nullptr;
-
 static void* btAlloc(size_t size)
 {
-	ANKI_ASSERT(g_pool);
-	return g_pool->allocate(size, 16);
+	return PhysicsMemoryPool::getSingleton().allocate(size, 16);
 }
 
 static void btFree(void* ptr)
 {
-	ANKI_ASSERT(g_pool);
-	g_pool->free(ptr);
+	PhysicsMemoryPool::getSingleton().free(ptr);
 }
 
 /// Broad phase collision callback.
@@ -155,25 +150,25 @@ PhysicsWorld::~PhysicsWorld()
 	m_collisionConfig.destroy();
 	m_broadphase.destroy();
 	m_gpc.destroy();
-	deleteInstance(m_pool, m_filterCallback);
+	deleteInstance(PhysicsMemoryPool::getSingleton(), m_filterCallback);
 
-	g_pool = nullptr;
+	PhysicsMemoryPool::freeSingleton();
 }
 
 Error PhysicsWorld::init(AllocAlignedCallback allocCb, void* allocCbData)
 {
-	m_pool.init(allocCb, allocCbData);
+	PhysicsMemoryPool::allocateSingleton(allocCb, allocCbData);
+
 	m_tmpPool.init(allocCb, allocCbData, 1_KB, 2.0f);
 
 	// Set allocators
-	g_pool = &m_pool;
 	btAlignedAllocSetCustom(btAlloc, btFree);
 
 	// Create objects
 	m_broadphase.init();
 	m_gpc.init();
 	m_broadphase->getOverlappingPairCache()->setInternalGhostPairCallback(m_gpc.get());
-	m_filterCallback = anki::newInstance<MyOverlapFilterCallback>(m_pool);
+	m_filterCallback = anki::newInstance<MyOverlapFilterCallback>(PhysicsMemoryPool::getSingleton());
 	m_broadphase->getOverlappingPairCache()->setOverlapFilterCallback(m_filterCallback);
 
 	m_collisionConfig.init();
@@ -214,7 +209,7 @@ void PhysicsWorld::destroyMarkedForDeletion()
 			break;
 		}
 
-		deleteInstance(m_pool, obj);
+		deleteInstance(PhysicsMemoryPool::getSingleton(), obj);
 #if ANKI_ENABLE_ASSERTIONS
 		const I32 count = m_objectsCreatedCount.fetchSub(1) - 1;
 		ANKI_ASSERT(count >= 0);
@@ -330,7 +325,8 @@ PhysicsTriggerFilteredPair* PhysicsWorld::getOrCreatePhysicsTriggerFilteredPair(
 	PhysicsTriggerFilteredPair* newPair;
 	if(filtered->m_triggerFilteredPairs[emptySlot] == nullptr)
 	{
-		filtered->m_triggerFilteredPairs[emptySlot] = anki::newInstance<PhysicsTriggerFilteredPair>(m_pool);
+		filtered->m_triggerFilteredPairs[emptySlot] =
+			anki::newInstance<PhysicsTriggerFilteredPair>(PhysicsMemoryPool::getSingleton());
 	}
 	newPair = filtered->m_triggerFilteredPairs[emptySlot];
 

+ 10 - 12
AnKi/Physics/PhysicsWorld.h

@@ -37,19 +37,19 @@ public:
 };
 
 /// The master container for all physics related stuff.
-class PhysicsWorld
+class PhysicsWorld : public MakeSingleton<PhysicsWorld>
 {
-public:
-	PhysicsWorld();
-	~PhysicsWorld();
+	template<typename>
+	friend class MakeSingleton;
 
+public:
 	Error init(AllocAlignedCallback allocCb, void* allocCbData);
 
 	template<typename T, typename... TArgs>
 	PhysicsPtr<T> newInstance(TArgs&&... args)
 	{
-		T* obj = static_cast<T*>(m_pool.allocate(sizeof(T), alignof(T)));
-		callConstructor(*obj, this, std::forward<TArgs>(args)...);
+		T* obj = static_cast<T*>(PhysicsMemoryPool::getSingleton().allocate(sizeof(T), alignof(T)));
+		callConstructor(*obj, std::forward<TArgs>(args)...);
 		{
 			LockGuard<Mutex> lock(m_markedMtx);
 			m_markedForCreation.pushBack(obj);
@@ -64,11 +64,6 @@ public:
 	/// Do the update.
 	void update(Second dt);
 
-	HeapMemoryPool& getMemoryPool()
-	{
-		return m_pool;
-	}
-
 	StackMemoryPool& getTempMemoryPool()
 	{
 		return m_tmpPool;
@@ -107,7 +102,6 @@ private:
 	class MyOverlapFilterCallback;
 	class MyRaycastCallback;
 
-	HeapMemoryPool m_pool;
 	StackMemoryPool m_tmpPool;
 
 	ClassWrapper<btDbvtBroadphase> m_broadphase;
@@ -128,6 +122,10 @@ private:
 	Atomic<I32> m_objectsCreatedCount = {0};
 #endif
 
+	PhysicsWorld();
+
+	~PhysicsWorld();
+
 	void destroyMarkedForDeletion();
 };
 /// @}

+ 0 - 1
AnKi/Renderer/Common.h

@@ -85,7 +85,6 @@ public:
 	GpuSceneMemoryPool* m_gpuScenePool = nullptr;
 	GpuSceneMicroPatcher* m_gpuSceneMicroPatcher = nullptr;
 	UnifiedGeometryMemoryPool* m_unifiedGometryMemoryPool = nullptr;
-	PhysicsWorld* m_physicsWorld = nullptr; ///< For debug drawing.
 };
 
 /// Rendering context.

+ 1 - 1
AnKi/Renderer/Dbg.cpp

@@ -232,7 +232,7 @@ void Dbg::run(RenderPassWorkContext& rgraphCtx, const RenderingContext& ctx)
 	if(threadId == (threadCount - 1) && getExternalSubsystems().m_config->getRDbgPhysics())
 	{
 		m_physicsDrawer.start(ctx.m_matrices.m_viewProjection, cmdb, &rebar);
-		m_physicsDrawer.drawWorld(*getExternalSubsystems().m_physicsWorld);
+		m_physicsDrawer.drawWorld(PhysicsWorld::getSingleton());
 		m_physicsDrawer.end();
 	}
 

+ 0 - 1
AnKi/Resource/Common.h

@@ -63,7 +63,6 @@ class ResourceManagerExternalSubsystems
 {
 public:
 	GrManager* m_grManager = nullptr;
-	PhysicsWorld* m_physicsWorld = nullptr;
 	ResourceFilesystem* m_resourceFilesystem = nullptr;
 	ConfigSet* m_config = nullptr;
 	UnifiedGeometryMemoryPool* m_unifiedGometryMemoryPool = nullptr;

+ 1 - 2
AnKi/Resource/CpuMeshResource.cpp

@@ -37,8 +37,7 @@ Error CpuMeshResource::load(const ResourceFilename& filename, [[maybe_unused]] B
 
 	// Create the collision shape
 	const Bool convex = !!(loader.getHeader().m_flags & MeshBinaryFlag::kConvex);
-	m_physicsShape =
-		getExternalSubsystems().m_physicsWorld->newInstance<PhysicsTriangleSoup>(m_positions, m_indices, convex);
+	m_physicsShape = PhysicsWorld::getSingleton().newInstance<PhysicsTriangleSoup>(m_positions, m_indices, convex);
 
 	return Error::kNone;
 }

+ 0 - 1
AnKi/Scene/Common.h

@@ -54,7 +54,6 @@ public:
 	UiManager* m_uiManager = nullptr;
 	GrManager* m_grManager = nullptr;
 	const Timestamp* m_globalTimestamp = nullptr;
-	PhysicsWorld* m_physicsWorld = nullptr;
 	UnifiedGeometryMemoryPool* m_unifiedGeometryMemPool = nullptr;
 	GpuSceneMemoryPool* m_gpuSceneMemoryPool = nullptr;
 	GpuSceneMicroPatcher* m_gpuSceneMicroPatcher = nullptr;

+ 2 - 2
AnKi/Scene/Components/BodyComponent.cpp

@@ -44,7 +44,7 @@ void BodyComponent::loadMeshResource(CString meshFilename)
 	init.m_mass = prevMass;
 	init.m_transform = prevTransform;
 	init.m_shape = m_mesh->getCollisionShape();
-	m_body = getExternalSubsystems(*m_node).m_physicsWorld->newInstance<PhysicsBody>(init);
+	m_body = PhysicsWorld::getSingleton().newInstance<PhysicsBody>(init);
 	m_body->setUserData(this);
 	m_body->setTransform(m_node->getWorldTransform());
 
@@ -87,7 +87,7 @@ void BodyComponent::setMass(F32 mass)
 		init.m_transform = prevTransform;
 		init.m_mass = mass;
 		init.m_shape = m_mesh->getCollisionShape();
-		m_body = getExternalSubsystems(*m_node).m_physicsWorld->newInstance<PhysicsBody>(init);
+		m_body = PhysicsWorld::getSingleton().newInstance<PhysicsBody>(init);
 		m_body->setUserData(this);
 
 		m_dirty = true;

+ 3 - 3
AnKi/Scene/Components/JointComponent.cpp

@@ -62,8 +62,8 @@ void JointComponent::newJoint(const Vec3& relPosFactor, F32 breakingImpulse, TAr
 	{
 		Vec3 relPos = computeLocalPivotFromFactors(bodyc->getPhysicsBody(), relPosFactor);
 
-		PhysicsJointPtr joint = getExternalSubsystems(*m_node).m_physicsWorld->newInstance<TJoint>(
-			bodyc->getPhysicsBody(), relPos, std::forward<TArgs>(args)...);
+		PhysicsJointPtr joint = PhysicsWorld::getSingleton().newInstance<TJoint>(bodyc->getPhysicsBody(), relPos,
+																				 std::forward<TArgs>(args)...);
 		joint->setBreakingImpulseThreshold(breakingImpulse);
 
 		JointNode* newNode = newInstance<JointNode>(m_node->getMemoryPool());
@@ -95,7 +95,7 @@ void JointComponent::newPoint2PointJoint2(const Vec3& relPosFactorA, const Vec3&
 		Vec3 relPosA = computeLocalPivotFromFactors(bodycA->getPhysicsBody(), relPosFactorA);
 		Vec3 relPosB = computeLocalPivotFromFactors(bodycB->getPhysicsBody(), relPosFactorB);
 
-		PhysicsJointPtr joint = getExternalSubsystems(*m_node).m_physicsWorld->newInstance<PhysicsPoint2PointJoint>(
+		PhysicsJointPtr joint = PhysicsWorld::getSingleton().newInstance<PhysicsPoint2PointJoint>(
 			bodycA->getPhysicsBody(), relPosA, bodycB->getPhysicsBody(), relPosB);
 		joint->setBreakingImpulseThreshold(breakingImpulse);
 

+ 2 - 3
AnKi/Scene/Components/ParticleEmitterComponent.cpp

@@ -130,7 +130,7 @@ public:
 
 	PhysicsParticle(const PhysicsBodyInitInfo& init, SceneNode* node, ParticleEmitterComponent* component)
 	{
-		m_body = getExternalSubsystems(*node).m_physicsWorld->newInstance<PhysicsBody>(init);
+		m_body = PhysicsWorld::getSingleton().newInstance<PhysicsBody>(init);
 		m_body->setUserData(component);
 		m_body->activate(false);
 		m_body->setMaterialGroup(PhysicsMaterialBit::kParticle);
@@ -256,8 +256,7 @@ void ParticleEmitterComponent::loadParticleEmitterResource(CString filename)
 	if(m_simulationType == SimulationType::kPhysicsEngine)
 	{
 		PhysicsCollisionShapePtr collisionShape =
-			getExternalSubsystems(*m_node).m_physicsWorld->newInstance<PhysicsSphere>(
-				m_props.m_particle.m_minInitialSize / 2.0f);
+			PhysicsWorld::getSingleton().newInstance<PhysicsSphere>(m_props.m_particle.m_minInitialSize / 2.0f);
 
 		PhysicsBodyInitInfo binit;
 		binit.m_shape = std::move(collisionShape);

+ 1 - 1
AnKi/Scene/Components/PlayerControllerComponent.cpp

@@ -15,7 +15,7 @@ PlayerControllerComponent::PlayerControllerComponent(SceneNode* node)
 {
 	PhysicsPlayerControllerInitInfo init;
 	init.m_position = node->getWorldTransform().getOrigin().xyz();
-	m_player = getExternalSubsystems(*node).m_physicsWorld->newInstance<PhysicsPlayerController>(init);
+	m_player = PhysicsWorld::getSingleton().newInstance<PhysicsPlayerController>(init);
 	m_player->setUserData(this);
 
 	node->setIgnoreParentTransform(true);

+ 2 - 2
AnKi/Scene/Components/TriggerComponent.cpp

@@ -87,8 +87,8 @@ TriggerComponent::~TriggerComponent()
 void TriggerComponent::setSphereVolumeRadius(F32 radius)
 {
 	// Need to re-create it
-	m_shape = getExternalSubsystems(*m_node).m_physicsWorld->newInstance<PhysicsSphere>(radius);
-	m_trigger = getExternalSubsystems(*m_node).m_physicsWorld->newInstance<PhysicsTrigger>(m_shape);
+	m_shape = PhysicsWorld::getSingleton().newInstance<PhysicsSphere>(radius);
+	m_trigger = PhysicsWorld::getSingleton().newInstance<PhysicsTrigger>(m_shape);
 	m_trigger->setUserData(this);
 	m_trigger->setContactProcessCallback(m_callbacks);
 	m_trigger->setTransform(m_node->getWorldTransform());

+ 1 - 1
AnKi/Scene/SceneGraph.cpp

@@ -185,7 +185,7 @@ Error SceneGraph::update(Second prevUpdateTime, Second crntTime)
 	{
 		ANKI_TRACE_SCOPED_EVENT(ScenePhysics);
 		m_stats.m_physicsUpdate = HighRezTimer::getCurrentTime();
-		m_subsystems.m_physicsWorld->update(crntTime - prevUpdateTime);
+		PhysicsWorld::getSingleton().update(crntTime - prevUpdateTime);
 		m_stats.m_physicsUpdate = HighRezTimer::getCurrentTime() - m_stats.m_physicsUpdate;
 	}
 

+ 40 - 0
AnKi/Util/MemoryPool.h

@@ -170,6 +170,21 @@ private:
 #endif
 };
 
+/// The default global memory pool.
+class DefaultHeapMemoryPool : public HeapMemoryPool, public MakeSingleton<DefaultHeapMemoryPool>
+{
+	template<typename>
+	friend class MakeSingleton;
+
+private:
+	DefaultHeapMemoryPool(AllocAlignedCallback allocCb, void* allocCbUserData)
+		: HeapMemoryPool(allocCb, allocCbUserData, "DefaultMemPool")
+	{
+	}
+
+	~DefaultHeapMemoryPool() = default;
+};
+
 /// Thread safe memory pool. It's a preallocated memory pool that is used for memory allocations on top of that
 /// preallocated memory. It is mainly used by fast stack allocators
 class StackMemoryPool : public BaseMemoryPool
@@ -378,6 +393,31 @@ private:
 	mutable Atomic<I32> m_refcount = {0};
 };
 
+template<typename TMemoryPool>
+class SingletonMemoryPoolWrapper
+{
+public:
+	TMemoryPool* operator&()
+	{
+		return &TMemoryPool::getSingleton();
+	}
+
+	operator TMemoryPool&()
+	{
+		return TMemoryPool::getSingleton();
+	}
+
+	void* allocate(PtrSize size, PtrSize alignmentBytes)
+	{
+		return TMemoryPool::getSingleton().allocate(size, alignmentBytes);
+	}
+
+	void free(void* ptr)
+	{
+		TMemoryPool::getSingleton().free(ptr);
+	}
+};
+
 inline void* BaseMemoryPool::allocate(PtrSize size, PtrSize alignmentBytes)
 {
 	void* out = nullptr;

+ 1 - 1
Samples/PhysicsPlayground/Main.cpp

@@ -370,7 +370,7 @@ Error MyApp::userMainLoop(Bool& quit, [[maybe_unused]] Second elapsedTime)
 		RayCast ray(from, to, PhysicsMaterialBit::kAll & (~PhysicsMaterialBit::kParticle));
 		ray.m_firstHit = true;
 
-		getPhysicsWorld().rayCast(ray);
+		PhysicsWorld::getSingleton().rayCast(ray);
 
 		if(ray.m_hit)
 		{

+ 1 - 7
Tests/Framework/Framework.cpp

@@ -279,19 +279,13 @@ GrManager* createGrManager(ConfigSet* cfg, NativeWindow* win)
 	return gr;
 }
 
-ResourceManager* createResourceManager(ConfigSet* cfg, GrManager* gr, PhysicsWorld*& physics,
-									   ResourceFilesystem*& resourceFs)
+ResourceManager* createResourceManager(ConfigSet* cfg, GrManager* gr, ResourceFilesystem*& resourceFs)
 {
-	physics = new PhysicsWorld();
-
-	ANKI_TEST_EXPECT_NO_ERR(physics->init(allocAligned, nullptr));
-
 	resourceFs = new ResourceFilesystem();
 	ANKI_TEST_EXPECT_NO_ERR(resourceFs->init(*cfg, allocAligned, nullptr));
 
 	ResourceManagerInitInfo rinit;
 	rinit.m_grManager = gr;
-	rinit.m_physicsWorld = physics;
 	rinit.m_resourceFilesystem = resourceFs;
 	rinit.m_config = cfg;
 	rinit.m_allocCallback = allocAligned;

+ 1 - 2
Tests/Framework/Framework.h

@@ -226,8 +226,7 @@ NativeWindow* createWindow(ConfigSet& cfg);
 
 GrManager* createGrManager(ConfigSet* cfg, NativeWindow* win);
 
-ResourceManager* createResourceManager(ConfigSet* cfg, GrManager* gr, PhysicsWorld*& physics,
-									   ResourceFilesystem*& resourceFs);
+ResourceManager* createResourceManager(ConfigSet* cfg, GrManager* gr, ResourceFilesystem*& resourceFs);
 
 /// Stolen from https://en.cppreference.com/w/cpp/algorithm/random_shuffle because std::random_suffle got deprecated
 template<class TRandomIt>

+ 1 - 3
Tests/Ui/Ui.cpp

@@ -69,9 +69,8 @@ ANKI_TEST(Ui, Ui)
 	Input* in;
 	ANKI_TEST_EXPECT_NO_ERR(Input::newInstance(allocAligned, nullptr, win, in));
 	GrManager* gr = createGrManager(&cfg, win);
-	PhysicsWorld* physics;
 	ResourceFilesystem* fs;
-	ResourceManager* resource = createResourceManager(&cfg, gr, physics, fs);
+	ResourceManager* resource = createResourceManager(&cfg, gr, fs);
 	UiManager* ui = new UiManager();
 
 	RebarStagingGpuMemoryPool* stagingMem = new RebarStagingGpuMemoryPool();
@@ -164,7 +163,6 @@ ANKI_TEST(Ui, Ui)
 	delete ui;
 	delete stagingMem;
 	delete resource;
-	delete physics;
 	delete fs;
 	GrManager::deleteInstance(gr);
 	Input::deleteInstance(in);