From cfd01c74202dd22c9abb179365e9ef431d49da9f Mon Sep 17 00:00:00 2001
From: Joseph Walton-Rivers <joseph@walton-rivers.uk>
Date: Thu, 4 Aug 2022 12:05:59 +0100
Subject: [PATCH] standardise debug draw call

---
 include/fggl/phys/types.hpp                   |  3 +
 .../bullet/include/fggl/phys/bullet/types.hpp | 32 +++++--
 integrations/bullet/src/service.cpp           |  1 -
 integrations/bullet/src/simulation.cpp        | 92 ++++---------------
 4 files changed, 43 insertions(+), 85 deletions(-)

diff --git a/include/fggl/phys/types.hpp b/include/fggl/phys/types.hpp
index e69c45a..9d8c558 100644
--- a/include/fggl/phys/types.hpp
+++ b/include/fggl/phys/types.hpp
@@ -116,6 +116,9 @@ namespace fggl::phys {
 
 			// update
 			virtual void step() = 0;
+
+			// debug
+			virtual void setDebugDraw(bool enable) = 0;
 	};
 
 } // namespace fggl::phys
diff --git a/integrations/bullet/include/fggl/phys/bullet/types.hpp b/integrations/bullet/include/fggl/phys/bullet/types.hpp
index b692413..abed2a1 100644
--- a/integrations/bullet/include/fggl/phys/bullet/types.hpp
+++ b/integrations/bullet/include/fggl/phys/bullet/types.hpp
@@ -75,6 +75,14 @@ namespace fggl::phys::bullet {
 			explicit BulletPhysicsEngine(entity::EntityManager* world);
 			~BulletPhysicsEngine() override;
 
+			// copy is not allowed
+			BulletPhysicsEngine(const BulletPhysicsEngine&) = delete;
+			BulletPhysicsEngine& operator=(const BulletPhysicsEngine&) = delete;
+
+			// move is not allowed
+			BulletPhysicsEngine(BulletPhysicsEngine&&) = delete;
+			BulletPhysicsEngine& operator=(BulletPhysicsEngine&&) = delete;
+
 			void step() override;
 			void onEntityDeath(entity::EntityID entity);
 
@@ -83,9 +91,19 @@ namespace fggl::phys::bullet {
 			std::vector<entity::EntityID> raycastAll(math::vec3 from, math::vec3 to) override;
 			std::vector<entity::EntityID> sweep(PhyShape& shape, math::Transform& from, math::Transform& to) override;
 
+			/**
+			 * Add a rigid body to the physics world.
+			 *
+			 * The body should not currently be in the simulation. Physics position will be synced with the motion
+			 * state prior to it being added to the simulation. This method should not need to be called manually, it
+			 * is called when the entity is decoded.
+			 *
+			 * @param entity the entity the BulletBody is attached to.
+			 * @param body the pre-configured bullet body.
+			 */
 			void addBody(entity::EntityID entity, BulletBody& body);
 
-			bool debugDraw = false;
+			void setDebugDraw(bool enabled) override;
 		private:
 			entity::EntityManager* m_ecs;
 			BulletConfiguration m_config;
@@ -94,14 +112,12 @@ namespace fggl::phys::bullet {
 			ContactCache m_contactCache;
 
 			/**
-			 * Check for ECS components which aren't in the physics world and add them.
-			 */
-			void checkForPhys();
-
-			/**
-			 * Sync the bullet world state back to the ECS.
+			 * Force position and rotation in the ECS to match those from the physics world.
+			 *
+			 * As FGGL uses motion states, this should not be required. As it iterates all entities in a scene this is
+			 * also a very expensive operation.
 			 */
-			void forceSyncToECS();
+			void syncTransformToECS();
 
 			/**
 			 * Deal with physics collisions
diff --git a/integrations/bullet/src/service.cpp b/integrations/bullet/src/service.cpp
index c50d791..82e2351 100644
--- a/integrations/bullet/src/service.cpp
+++ b/integrations/bullet/src/service.cpp
@@ -97,7 +97,6 @@ namespace fggl::phys::bullet {
 			auto& physComp = manager.template get<BulletBody>(entity);
 			engine->addBody(entity, physComp);
 		});
-		engine->debugDraw = true;
 
 		return engine;
 	}
diff --git a/integrations/bullet/src/simulation.cpp b/integrations/bullet/src/simulation.cpp
index 85a3803..8ae499d 100644
--- a/integrations/bullet/src/simulation.cpp
+++ b/integrations/bullet/src/simulation.cpp
@@ -35,7 +35,7 @@ namespace fggl::phys::bullet {
 		return {fgglVec.x, fgglVec.y, fgglVec.z};
 	}
 
-	BulletPhysicsEngine::BulletPhysicsEngine(entity::EntityManager* world) : m_ecs(world), m_config(), m_world(nullptr) {
+	BulletPhysicsEngine::BulletPhysicsEngine(entity::EntityManager* world) : m_ecs(world), m_config(), m_world(nullptr), m_debug(nullptr) {
 		m_config.broadphase = new btDbvtBroadphase();
 		m_config.collisionConfiguration = new btDefaultCollisionConfiguration();
 		m_config.dispatcher = new btCollisionDispatcher(m_config.collisionConfiguration);
@@ -47,9 +47,6 @@ namespace fggl::phys::bullet {
 			m_config.solver,
 			m_config.collisionConfiguration);
 
-		m_debug = std::make_unique<debug::BulletDebugDrawList>();
-		m_world->setDebugDrawer( m_debug.get() );
-		m_debug->setDebugMode(btIDebugDraw::DBG_DrawWireframe);
 
 		// callbacks (for handling bullet -> ecs)
 
@@ -78,7 +75,8 @@ namespace fggl::phys::bullet {
 		//syncToECS();
 		pollCollisions();
 
-		if ( debugDraw ) {
+		// if debug draw is enabled, trigger a draw call
+		if ( m_debug != nullptr ) {
 			m_world->debugDrawWorld();
 		}
 	}
@@ -92,83 +90,26 @@ namespace fggl::phys::bullet {
 		m_world->addRigidBody(body.body);
 	}
 
-	inline btCollisionShape* shape_to_bullet(const phys::RigidBody& fgglBody) {
-		if ( fgglBody.shape == nullptr ) {
-			// they forgot to put a shape, we'll assume a unit sphere to avoid crashes...
-			return new btSphereShape(0.5F);
-		}
-
-		switch (fgglBody.shape->type) {
-			case phys::ShapeType::BOX: {
-				auto extents = ((phys::Box*)fgglBody.shape)->extents;
-				return new btBoxShape({extents.x, extents.y, extents.z});
-			}
-			case phys::ShapeType::SPHERE: {
-				float radius = ((phys::Sphere*)fgglBody.shape)->radius;
-				return new btSphereShape(radius);
-			}
-			default:
-				return new btSphereShape(0.5f);
-		}
-	}
-
-	void BulletPhysicsEngine::checkForPhys() {
-		// FIXME without reactive-based approaches this is very slow
-		auto entsWantPhys = m_ecs->find<phys::RigidBody>();
-		for (auto ent : entsWantPhys) {
-			auto* btComp = m_ecs->tryGet<BulletBody>(ent);
-			if ( btComp != nullptr ) {
-				// they are already in the simulation
-				continue;
-			}
-
-			// set up the bullet proxy for our object
-			btComp = &m_ecs->add<BulletBody>(ent);
-			const auto& fgBody = m_ecs->get<phys::RigidBody>(ent);
-			btComp->motion = new FgglMotionState(m_ecs, ent);
-
-			// collisions
-			btCollisionShape* colShape = shape_to_bullet(fgBody);
-			btVector3 localInt(0, 0, 0);
-			if ( !fgBody.isStatic() ) {
-				colShape->calculateLocalInertia(fgBody.mass, localInt);
-			}
-
-			// setup the construction information
-			btRigidBody::btRigidBodyConstructionInfo bodyCI(
-				fgBody.mass,
-				btComp->motion,
-				colShape,
-				localInt
-			);
-			btComp->body = new btRigidBody(bodyCI);
-			btComp->body->setUserIndex( static_cast<int>(ent) );
-
-
-			if (!fgBody.isStatic()) {
-				btComp->body->setRestitution(0.5f);
-				btComp->body->setRollingFriction(0.0f);
-			}
-
-			if ( fgBody.type == BodyType::KINEMATIC ) {
-				auto flags = btComp->body->getCollisionFlags() | btCollisionObject::CF_KINEMATIC_OBJECT;
-				btComp->body->setCollisionFlags( flags );
-
-				// we don't have a clean way of saying a kinematic object moved, so just prevent sleeping.
-				// if this turns out to be an issue, we'll need to revisit this.
-				btComp->body->setActivationState( DISABLE_DEACTIVATION );
-			}
-
-			m_world->addRigidBody( btComp->body );
+	void BulletPhysicsEngine::setDebugDraw(bool active)  {
+		if ( active ) {
+			m_debug = std::make_unique<debug::BulletDebugDrawList>();
+			m_world->setDebugDrawer(m_debug.get());
+			m_debug->setDebugMode(btIDebugDraw::DBG_DrawWireframe);
+		} else {
+			m_debug = nullptr;
 		}
 	}
 
-	void BulletPhysicsEngine::forceSyncToECS() {
+	void BulletPhysicsEngine::syncTransformToECS() {
 		const auto physEnts = m_ecs->find<math::Transform, BulletBody>();
 		for (const auto& ent : physEnts) {
-			auto& transform = m_ecs->get<math::Transform>(ent);
 			auto& physBody = m_ecs->get<BulletBody>(ent);
+			// don't bother syncing things with motion states, it's not necessary
+			if ( physBody.motion != nullptr ) {
+				continue;
+			}
 
+			auto& transform = m_ecs->get<math::Transform>(ent);
 			if ( physBody.body->isKinematicObject() ) {
 				continue;
 			}
@@ -201,7 +142,6 @@ namespace fggl::phys::bullet {
 
 			// release resources and delete
 			bulletBody.release();
-			//m_ecs->remove<BulletBody>(ent);
 		}
 
 		// delete the world
-- 
GitLab