refactor: Replace PhysicsBridge with PhysicsBridgeService and update related implementations

This commit is contained in:
2026-01-05 00:04:03 +00:00
parent bb497aaae2
commit dd8a9cf4e7
8 changed files with 122 additions and 198 deletions

View File

@@ -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

View File

@@ -21,7 +21,7 @@ void BulletPhysicsService::Initialize(const btVector3& gravity) {
return;
}
physicsBridge_ = std::make_unique<PhysicsBridge>(logger_);
physicsBridge_ = std::make_unique<PhysicsBridgeService>(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<PhysicsBridge>(logger_);
physicsBridge_ = std::make_unique<PhysicsBridgeService>(logger_);
}
} // namespace sdl3cpp::services::impl

View File

@@ -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 <memory>
@@ -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<ILogger> logger_;
std::unique_ptr<PhysicsBridge> physicsBridge_;
std::unique_ptr<PhysicsBridgeService> physicsBridge_;
bool initialized_ = false;
};

View File

@@ -1,105 +0,0 @@
#include "physics_bridge.hpp"
#include "../interfaces/i_logger.hpp"
#include <btBulletDynamicsCommon.h>
namespace sdl3cpp::services::impl {
PhysicsBridge::PhysicsBridge(std::shared_ptr<services::ILogger> logger)
: collisionConfig_(std::make_unique<btDefaultCollisionConfiguration>()),
dispatcher_(std::make_unique<btCollisionDispatcher>(collisionConfig_.get())),
broadphase_(std::make_unique<btDbvtBroadphase>()),
solver_(std::make_unique<btSequentialImpulseConstraintSolver>()),
world_(std::make_unique<btDiscreteDynamicsWorld>(
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<btBoxShape>(halfExtents);
btVector3 inertia(0.0f, 0.0f, 0.0f);
if (mass > 0.0f) {
shape->calculateLocalInertia(mass, inertia);
}
auto motionState = std::make_unique<btDefaultMotionState>(transform);
btRigidBody::btRigidBodyConstructionInfo constructionInfo(
mass,
motionState.get(),
shape.get(),
inertia);
auto body = std::make_unique<btRigidBody>(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<int>(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

View File

@@ -1,58 +0,0 @@
#pragma once
#include <memory>
#include <string>
#include <unordered_map>
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<services::ILogger> 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<btCollisionShape> shape;
std::unique_ptr<btMotionState> motionState;
std::unique_ptr<btRigidBody> body;
};
std::unique_ptr<btDefaultCollisionConfiguration> collisionConfig_;
std::unique_ptr<btCollisionDispatcher> dispatcher_;
std::unique_ptr<btBroadphaseInterface> broadphase_;
std::unique_ptr<btSequentialImpulseConstraintSolver> solver_;
std::unique_ptr<btDiscreteDynamicsWorld> world_;
std::unordered_map<std::string, BodyRecord> bodies_;
std::shared_ptr<services::ILogger> logger_;
};
} // namespace sdl3cpp::services::impl

View File

@@ -1,14 +1,36 @@
#include "physics_bridge_service.hpp"
#include <btBulletDynamicsCommon.h>
#include <utility>
namespace sdl3cpp::services::impl {
PhysicsBridgeService::PhysicsBridgeService(std::shared_ptr<ILogger> logger)
: bridge_(std::make_unique<PhysicsBridge>(logger)),
: collisionConfig_(std::make_unique<btDefaultCollisionConfiguration>()),
dispatcher_(std::make_unique<btCollisionDispatcher>(collisionConfig_.get())),
broadphase_(std::make_unique<btDbvtBroadphase>()),
solver_(std::make_unique<btSequentialImpulseConstraintSolver>()),
world_(std::make_unique<btDiscreteDynamicsWorld>(
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<btBoxShape>(halfExtents);
btVector3 inertia(0.0f, 0.0f, 0.0f);
if (mass > 0.0f) {
shape->calculateLocalInertia(mass, inertia);
}
auto motionState = std::make_unique<btDefaultMotionState>(transform);
btRigidBody::btRigidBodyConstructionInfo constructionInfo(
mass,
motionState.get(),
shape.get(),
inertia);
auto body = std::make_unique<btRigidBody>(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<int>(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

View File

@@ -2,8 +2,20 @@
#include "../interfaces/i_physics_bridge_service.hpp"
#include "../interfaces/i_logger.hpp"
#include "physics_bridge.hpp"
#include <memory>
#include <string>
#include <unordered_map>
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<ILogger> 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<PhysicsBridge> bridge_;
struct BodyRecord {
std::unique_ptr<btCollisionShape> shape;
std::unique_ptr<btMotionState> motionState;
std::unique_ptr<btRigidBody> body;
};
std::unique_ptr<btDefaultCollisionConfiguration> collisionConfig_;
std::unique_ptr<btCollisionDispatcher> dispatcher_;
std::unique_ptr<btBroadphaseInterface> broadphase_;
std::unique_ptr<btSequentialImpulseConstraintSolver> solver_;
std::unique_ptr<btDiscreteDynamicsWorld> world_;
std::unordered_map<std::string, BodyRecord> bodies_;
std::shared_ptr<ILogger> logger_;
};

View File

@@ -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: