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