diff --git a/CMakeLists.txt b/CMakeLists.txt index 0097c1c..9868fd7 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -148,7 +148,6 @@ if(BUILD_SDL3_APP) src/services/impl/gui_renderer_service.cpp src/services/impl/vulkan_gui_service.cpp src/services/impl/bullet_physics_service.cpp - src/services/impl/physics_bridge.cpp src/services/impl/scene_service.cpp src/services/impl/graphics_service.cpp src/app/service_based_app.cpp diff --git a/src/services/impl/bullet_physics_service.cpp b/src/services/impl/bullet_physics_service.cpp index 5fc771c..e5e237a 100644 --- a/src/services/impl/bullet_physics_service.cpp +++ b/src/services/impl/bullet_physics_service.cpp @@ -21,7 +21,7 @@ void BulletPhysicsService::Initialize(const btVector3& gravity) { return; } - physicsBridge_ = std::make_unique(logger_); + physicsBridge_ = std::make_unique(logger_); initialized_ = true; logger_->Info("Physics service initialized"); @@ -51,7 +51,11 @@ bool BulletPhysicsService::AddBoxRigidBody(const std::string& name, } std::string error; - return physicsBridge_->addBoxRigidBody(name, halfExtents, mass, transform, error); + if (!physicsBridge_->AddBoxRigidBody(name, halfExtents, mass, transform, error)) { + logger_->Error("AddBoxRigidBody failed: " + error); + return false; + } + return true; } bool BulletPhysicsService::AddSphereRigidBody(const std::string& name, @@ -60,16 +64,16 @@ bool BulletPhysicsService::AddSphereRigidBody(const std::string& name, const btTransform& transform) { logger_->TraceFunction(__func__); - // PhysicsBridge doesn't support sphere rigid bodies in current implementation - logger_->Warn("AddSphereRigidBody not supported by PhysicsBridge"); + // PhysicsBridgeService doesn't support sphere rigid bodies in current implementation + logger_->Warn("AddSphereRigidBody not supported by PhysicsBridgeService"); return false; } bool BulletPhysicsService::RemoveRigidBody(const std::string& name) { logger_->TraceFunction(__func__); - // PhysicsBridge doesn't support removing bodies in current implementation - logger_->Warn("RemoveRigidBody not supported by PhysicsBridge"); + // PhysicsBridgeService doesn't support removing bodies in current implementation + logger_->Warn("RemoveRigidBody not supported by PhysicsBridgeService"); return false; } @@ -80,7 +84,7 @@ void BulletPhysicsService::StepSimulation(float deltaTime, int maxSubSteps) { throw std::runtime_error("Physics service not initialized"); } - physicsBridge_->stepSimulation(deltaTime); + physicsBridge_->StepSimulation(deltaTime); } bool BulletPhysicsService::GetTransform(const std::string& name, btTransform& outTransform) const { @@ -89,43 +93,49 @@ bool BulletPhysicsService::GetTransform(const std::string& name, btTransform& ou } std::string error; - return physicsBridge_->getRigidBodyTransform(name, outTransform, error); + if (!physicsBridge_->GetRigidBodyTransform(name, outTransform, error)) { + if (logger_) { + logger_->Warn("GetTransform failed: " + error); + } + return false; + } + return true; } bool BulletPhysicsService::SetTransform(const std::string& name, const btTransform& transform) { logger_->TraceFunction(__func__); - // PhysicsBridge doesn't support setting transforms in current implementation - logger_->Warn("SetTransform not supported by PhysicsBridge"); + // PhysicsBridgeService doesn't support setting transforms in current implementation + logger_->Warn("SetTransform not supported by PhysicsBridgeService"); return false; } bool BulletPhysicsService::ApplyForce(const std::string& name, const btVector3& force) { logger_->TraceFunction(__func__); - // PhysicsBridge doesn't support applying forces in current implementation - logger_->Warn("ApplyForce not supported by PhysicsBridge"); + // PhysicsBridgeService doesn't support applying forces in current implementation + logger_->Warn("ApplyForce not supported by PhysicsBridgeService"); return false; } bool BulletPhysicsService::ApplyImpulse(const std::string& name, const btVector3& impulse) { logger_->TraceFunction(__func__); - // PhysicsBridge doesn't support applying impulses in current implementation - logger_->Warn("ApplyImpulse not supported by PhysicsBridge"); + // PhysicsBridgeService doesn't support applying impulses in current implementation + logger_->Warn("ApplyImpulse not supported by PhysicsBridgeService"); return false; } bool BulletPhysicsService::SetLinearVelocity(const std::string& name, const btVector3& velocity) { logger_->TraceFunction(__func__); - // PhysicsBridge doesn't support setting velocity in current implementation - logger_->Warn("SetLinearVelocity not supported by PhysicsBridge"); + // PhysicsBridgeService doesn't support setting velocity in current implementation + logger_->Warn("SetLinearVelocity not supported by PhysicsBridgeService"); return false; } size_t BulletPhysicsService::GetBodyCount() const { - // PhysicsBridge doesn't expose GetBodyCount in current implementation + // PhysicsBridgeService doesn't expose GetBodyCount in current implementation // Returning 0 as stub - could track bodies in wrapper if needed return 0; } @@ -137,10 +147,10 @@ void BulletPhysicsService::Clear() { return; } - // PhysicsBridge doesn't expose Clear in current implementation + // PhysicsBridgeService doesn't expose Clear in current implementation // Shutdown and reinitialize to clear all bodies physicsBridge_.reset(); - physicsBridge_ = std::make_unique(logger_); + physicsBridge_ = std::make_unique(logger_); } } // namespace sdl3cpp::services::impl diff --git a/src/services/impl/bullet_physics_service.hpp b/src/services/impl/bullet_physics_service.hpp index 37c45b9..a7e8b35 100644 --- a/src/services/impl/bullet_physics_service.hpp +++ b/src/services/impl/bullet_physics_service.hpp @@ -2,7 +2,7 @@ #include "../interfaces/i_physics_service.hpp" #include "../interfaces/i_logger.hpp" -#include "physics_bridge.hpp" +#include "physics_bridge_service.hpp" #include "../../di/lifecycle.hpp" #include @@ -11,7 +11,7 @@ namespace sdl3cpp::services::impl { /** * @brief Bullet physics service implementation. * - * Small wrapper service (~120 lines) around PhysicsBridge. + * Small wrapper service (~120 lines) around PhysicsBridgeService. * Provides rigid body physics simulation using Bullet Physics. */ class BulletPhysicsService : public IPhysicsService, @@ -54,7 +54,7 @@ public: private: std::shared_ptr logger_; - std::unique_ptr physicsBridge_; + std::unique_ptr physicsBridge_; bool initialized_ = false; }; diff --git a/src/services/impl/physics_bridge.cpp b/src/services/impl/physics_bridge.cpp deleted file mode 100644 index c6ed1f7..0000000 --- a/src/services/impl/physics_bridge.cpp +++ /dev/null @@ -1,105 +0,0 @@ -#include "physics_bridge.hpp" -#include "../interfaces/i_logger.hpp" - -#include - -namespace sdl3cpp::services::impl { - -PhysicsBridge::PhysicsBridge(std::shared_ptr logger) - : collisionConfig_(std::make_unique()), - dispatcher_(std::make_unique(collisionConfig_.get())), - broadphase_(std::make_unique()), - solver_(std::make_unique()), - world_(std::make_unique( - dispatcher_.get(), - broadphase_.get(), - solver_.get(), - collisionConfig_.get())), - logger_(std::move(logger)) { - if (logger_) { - logger_->Trace("PhysicsBridge", "PhysicsBridge"); - } - world_->setGravity(btVector3(0.0f, -9.81f, 0.0f)); -} - -PhysicsBridge::~PhysicsBridge() { - if (world_) { - for (auto& [name, entry] : bodies_) { - if (entry.body) { - world_->removeRigidBody(entry.body.get()); - } - } - } -} - -bool PhysicsBridge::addBoxRigidBody(const std::string& name, - const btVector3& halfExtents, - float mass, - const btTransform& transform, - std::string& error) { - if (logger_) { - logger_->Trace("PhysicsBridge", "addBoxRigidBody", "name=" + name); - } - if (name.empty()) { - error = "Rigid body name must not be empty"; - return false; - } - if (!world_) { - error = "Physics world is not initialized"; - return false; - } - if (bodies_.count(name)) { - error = "Rigid body already exists: " + name; - return false; - } - auto shape = std::make_unique(halfExtents); - btVector3 inertia(0.0f, 0.0f, 0.0f); - if (mass > 0.0f) { - shape->calculateLocalInertia(mass, inertia); - } - auto motionState = std::make_unique(transform); - btRigidBody::btRigidBodyConstructionInfo constructionInfo( - mass, - motionState.get(), - shape.get(), - inertia); - auto body = std::make_unique(constructionInfo); - world_->addRigidBody(body.get()); - bodies_.emplace(name, BodyRecord{ - std::move(shape), - std::move(motionState), - std::move(body), - }); - return true; -} - -int PhysicsBridge::stepSimulation(float deltaTime) { - if (logger_) { - logger_->Trace("PhysicsBridge", "stepSimulation", "deltaTime=" + std::to_string(deltaTime)); - } - if (!world_) { - return 0; - } - return static_cast(world_->stepSimulation(deltaTime, 10, 1.0f / 60.0f)); -} - -bool PhysicsBridge::getRigidBodyTransform(const std::string& name, - btTransform& outTransform, - std::string& error) const { - if (logger_) { - logger_->Trace("PhysicsBridge", "getRigidBodyTransform", "name=" + name); - } - auto it = bodies_.find(name); - if (it == bodies_.end()) { - error = "Rigid body not found: " + name; - return false; - } - if (!it->second.motionState) { - error = "Rigid body motion state is missing"; - return false; - } - it->second.motionState->getWorldTransform(outTransform); - return true; -} - -} // namespace sdl3cpp::services::impl diff --git a/src/services/impl/physics_bridge.hpp b/src/services/impl/physics_bridge.hpp deleted file mode 100644 index 80a2256..0000000 --- a/src/services/impl/physics_bridge.hpp +++ /dev/null @@ -1,58 +0,0 @@ -#pragma once - -#include -#include -#include - -namespace sdl3cpp::services { -class ILogger; -} - -class btVector3; -class btTransform; -class btCollisionShape; -class btMotionState; -class btRigidBody; -class btDefaultCollisionConfiguration; -class btCollisionDispatcher; -class btBroadphaseInterface; -class btSequentialImpulseConstraintSolver; -class btDiscreteDynamicsWorld; - -namespace sdl3cpp::services::impl { - -class PhysicsBridge { -public: - explicit PhysicsBridge(std::shared_ptr logger); - ~PhysicsBridge(); - - PhysicsBridge(const PhysicsBridge&) = delete; - PhysicsBridge& operator=(const PhysicsBridge&) = delete; - - bool addBoxRigidBody(const std::string& name, - const btVector3& halfExtents, - float mass, - const btTransform& transform, - std::string& error); - int stepSimulation(float deltaTime); - bool getRigidBodyTransform(const std::string& name, - btTransform& outTransform, - std::string& error) const; - -private: - struct BodyRecord { - std::unique_ptr shape; - std::unique_ptr motionState; - std::unique_ptr body; - }; - - std::unique_ptr collisionConfig_; - std::unique_ptr dispatcher_; - std::unique_ptr broadphase_; - std::unique_ptr solver_; - std::unique_ptr world_; - std::unordered_map bodies_; - std::shared_ptr logger_; -}; - -} // namespace sdl3cpp::services::impl diff --git a/src/services/impl/physics_bridge_service.cpp b/src/services/impl/physics_bridge_service.cpp index 9d1dba5..fe83a6d 100644 --- a/src/services/impl/physics_bridge_service.cpp +++ b/src/services/impl/physics_bridge_service.cpp @@ -1,14 +1,36 @@ #include "physics_bridge_service.hpp" + +#include + #include namespace sdl3cpp::services::impl { PhysicsBridgeService::PhysicsBridgeService(std::shared_ptr logger) - : bridge_(std::make_unique(logger)), + : collisionConfig_(std::make_unique()), + dispatcher_(std::make_unique(collisionConfig_.get())), + broadphase_(std::make_unique()), + solver_(std::make_unique()), + world_(std::make_unique( + dispatcher_.get(), + broadphase_.get(), + solver_.get(), + collisionConfig_.get())), logger_(std::move(logger)) { if (logger_) { logger_->Trace("PhysicsBridgeService", "PhysicsBridgeService"); } + world_->setGravity(btVector3(0.0f, -9.81f, 0.0f)); +} + +PhysicsBridgeService::~PhysicsBridgeService() { + if (world_) { + for (auto& [name, entry] : bodies_) { + if (entry.body) { + world_->removeRigidBody(entry.body.get()); + } + } + } } bool PhysicsBridgeService::AddBoxRigidBody(const std::string& name, @@ -19,21 +41,47 @@ bool PhysicsBridgeService::AddBoxRigidBody(const std::string& name, if (logger_) { logger_->Trace("PhysicsBridgeService", "AddBoxRigidBody", "name=" + name); } - if (!bridge_) { - error = "Physics bridge not initialized"; + if (name.empty()) { + error = "Rigid body name must not be empty"; return false; } - return bridge_->addBoxRigidBody(name, halfExtents, mass, transform, error); + if (!world_) { + error = "Physics world is not initialized"; + return false; + } + if (bodies_.count(name)) { + error = "Rigid body already exists: " + name; + return false; + } + auto shape = std::make_unique(halfExtents); + btVector3 inertia(0.0f, 0.0f, 0.0f); + if (mass > 0.0f) { + shape->calculateLocalInertia(mass, inertia); + } + auto motionState = std::make_unique(transform); + btRigidBody::btRigidBodyConstructionInfo constructionInfo( + mass, + motionState.get(), + shape.get(), + inertia); + auto body = std::make_unique(constructionInfo); + world_->addRigidBody(body.get()); + bodies_.emplace(name, BodyRecord{ + std::move(shape), + std::move(motionState), + std::move(body), + }); + return true; } int PhysicsBridgeService::StepSimulation(float deltaTime) { if (logger_) { logger_->Trace("PhysicsBridgeService", "StepSimulation", "deltaTime=" + std::to_string(deltaTime)); } - if (!bridge_) { + if (!world_) { return 0; } - return bridge_->stepSimulation(deltaTime); + return static_cast(world_->stepSimulation(deltaTime, 10, 1.0f / 60.0f)); } bool PhysicsBridgeService::GetRigidBodyTransform(const std::string& name, @@ -42,11 +90,17 @@ bool PhysicsBridgeService::GetRigidBodyTransform(const std::string& name, if (logger_) { logger_->Trace("PhysicsBridgeService", "GetRigidBodyTransform", "name=" + name); } - if (!bridge_) { - error = "Physics bridge not initialized"; + auto it = bodies_.find(name); + if (it == bodies_.end()) { + error = "Rigid body not found: " + name; return false; } - return bridge_->getRigidBodyTransform(name, outTransform, error); + if (!it->second.motionState) { + error = "Rigid body motion state is missing"; + return false; + } + it->second.motionState->getWorldTransform(outTransform); + return true; } } // namespace sdl3cpp::services::impl diff --git a/src/services/impl/physics_bridge_service.hpp b/src/services/impl/physics_bridge_service.hpp index 51a680f..bb751da 100644 --- a/src/services/impl/physics_bridge_service.hpp +++ b/src/services/impl/physics_bridge_service.hpp @@ -2,8 +2,20 @@ #include "../interfaces/i_physics_bridge_service.hpp" #include "../interfaces/i_logger.hpp" -#include "physics_bridge.hpp" #include +#include +#include + +class btVector3; +class btTransform; +class btCollisionShape; +class btMotionState; +class btRigidBody; +class btDefaultCollisionConfiguration; +class btCollisionDispatcher; +class btBroadphaseInterface; +class btSequentialImpulseConstraintSolver; +class btDiscreteDynamicsWorld; namespace sdl3cpp::services::impl { @@ -13,6 +25,7 @@ namespace sdl3cpp::services::impl { class PhysicsBridgeService : public IPhysicsBridgeService { public: explicit PhysicsBridgeService(std::shared_ptr logger); + ~PhysicsBridgeService() override; bool AddBoxRigidBody(const std::string& name, const btVector3& halfExtents, @@ -25,7 +38,18 @@ public: std::string& error) const override; private: - std::unique_ptr bridge_; + struct BodyRecord { + std::unique_ptr shape; + std::unique_ptr motionState; + std::unique_ptr body; + }; + + std::unique_ptr collisionConfig_; + std::unique_ptr dispatcher_; + std::unique_ptr broadphase_; + std::unique_ptr solver_; + std::unique_ptr world_; + std::unordered_map bodies_; std::shared_ptr logger_; }; diff --git a/src/services/interfaces/i_physics_service.hpp b/src/services/interfaces/i_physics_service.hpp index 7aeb793..c80a655 100644 --- a/src/services/interfaces/i_physics_service.hpp +++ b/src/services/interfaces/i_physics_service.hpp @@ -10,7 +10,7 @@ namespace sdl3cpp::services { * @brief Physics simulation service interface. * * Provides rigid body physics simulation using Bullet Physics. - * Wraps the PhysicsBridge class with a clean service interface. + * Wraps the physics bridge service with a clean simulation interface. */ class IPhysicsService { public: