diff --git a/examples/Physics2DDemo/main.cpp b/examples/Physics2DDemo/main.cpp index 031079e18..899baa92f 100644 --- a/examples/Physics2DDemo/main.cpp +++ b/examples/Physics2DDemo/main.cpp @@ -59,20 +59,24 @@ int main(int argc, char* argv[]) std::shared_ptr spriteMaterial = Nz::Graphics::Instance()->GetDefaultMaterials().phongMaterial->Instantiate(); spriteMaterial->SetTextureProperty("BaseColorMap", Nz::Texture::LoadFromFile(resourceDir / "box.png", texParams)); + Nz::ChipmunkRigidBody2DComponent::DynamicSettings boxSettings; + boxSettings.mass = 50.f; + boxSettings.geom = std::make_shared(Nz::Vector2f(32.f, 32.f)); + + std::shared_ptr boxSprite = std::make_shared(spriteMaterial); + boxSprite->SetSize({ 32.f, 32.f }); + boxSprite->SetOrigin({ 0.5f, 0.5f }); + for (std::size_t y = 0; y < 30; ++y) { for (std::size_t x = 0; x < 30; ++x) { entt::handle spriteEntity = world.CreateEntity(); { - std::shared_ptr sprite = std::make_shared(spriteMaterial); - sprite->SetSize({ 32.f, 32.f }); - sprite->SetOrigin({ 0.5f, 0.5f }); + spriteEntity.emplace(Nz::Vector2f(windowSize.x * 0.5f + x * 48.f - 15.f * 48.f, windowSize.y / 2 + y * 48.f)); + spriteEntity.emplace(boxSprite, 1); - spriteEntity.emplace().SetPosition(windowSize.x * 0.5f + x * 48.f - 15.f * 48.f, windowSize.y / 2 + y * 48.f); - - spriteEntity.emplace().AttachRenderable(sprite, 1); - auto& rigidBody = spriteEntity.emplace(physSytem.CreateRigidBody(50.f, std::make_shared(Nz::Vector2f(32.f, 32.f)))); + auto& rigidBody = spriteEntity.emplace(boxSettings); rigidBody.SetFriction(0.9f); //rigidBody.SetElasticity(0.99f); } @@ -99,9 +103,12 @@ int main(int argc, char* argv[]) } } + Nz::ChipmunkRigidBody2DComponent::StaticSettings groundSettings; + groundSettings.geom = std::make_shared(tilemap->GetSize()); + groundEntity.emplace().SetPosition(windowSize.x * 0.5f, -windowSize.y * 0.2f); groundEntity.emplace().AttachRenderable(tilemap, 1); - auto& rigidBody = groundEntity.emplace(physSytem.CreateRigidBody(0.f, std::make_shared(tilemap->GetSize()))); + auto& rigidBody = groundEntity.emplace(groundSettings); rigidBody.SetFriction(0.9f); } diff --git a/include/Nazara/ChipmunkPhysics2D/ChipmunkCollider2D.hpp b/include/Nazara/ChipmunkPhysics2D/ChipmunkCollider2D.hpp index 024eb46ab..2bb495380 100644 --- a/include/Nazara/ChipmunkPhysics2D/ChipmunkCollider2D.hpp +++ b/include/Nazara/ChipmunkPhysics2D/ChipmunkCollider2D.hpp @@ -13,6 +13,7 @@ #include #include #include +#include #include #include #include @@ -38,7 +39,7 @@ namespace Nz virtual Vector2f ComputeCenterOfMass() const = 0; virtual float ComputeMomentOfInertia(float mass) const = 0; - virtual void ForEachPolygon(const std::function& callback) const; + virtual void ForEachPolygon(const FunctionRef& callback) const; inline UInt32 GetCategoryMask() const; inline UInt32 GetCollisionGroup() const; diff --git a/include/Nazara/ChipmunkPhysics2D/ChipmunkRigidBody2D.hpp b/include/Nazara/ChipmunkPhysics2D/ChipmunkRigidBody2D.hpp index b49764775..eda68febf 100644 --- a/include/Nazara/ChipmunkPhysics2D/ChipmunkRigidBody2D.hpp +++ b/include/Nazara/ChipmunkPhysics2D/ChipmunkRigidBody2D.hpp @@ -27,17 +27,20 @@ namespace Nz class NAZARA_CHIPMUNKPHYSICS2D_API ChipmunkRigidBody2D { public: + struct DynamicSettings; + struct StaticSettings; + using VelocityFunc = std::function; - ChipmunkRigidBody2D(ChipmunkPhysWorld2D* world, float mass); - ChipmunkRigidBody2D(ChipmunkPhysWorld2D* world, float mass, std::shared_ptr geom); + inline ChipmunkRigidBody2D(ChipmunkPhysWorld2D& world, const DynamicSettings& settings); + inline ChipmunkRigidBody2D(ChipmunkPhysWorld2D& world, const StaticSettings& settings); ChipmunkRigidBody2D(const ChipmunkRigidBody2D& object); ChipmunkRigidBody2D(ChipmunkRigidBody2D&& object) noexcept; - ~ChipmunkRigidBody2D(); + inline ~ChipmunkRigidBody2D(); - void AddForce(const Vector2f& force, CoordSys coordSys = CoordSys::Global); + inline void AddForce(const Vector2f& force, CoordSys coordSys = CoordSys::Global); void AddForce(const Vector2f& force, const Vector2f& point, CoordSys coordSys = CoordSys::Global); - void AddImpulse(const Vector2f& impulse, CoordSys coordSys = CoordSys::Global); + inline void AddImpulse(const Vector2f& impulse, CoordSys coordSys = CoordSys::Global); void AddImpulse(const Vector2f& impulse, const Vector2f& point, CoordSys coordSys = CoordSys::Global); void AddTorque(const RadianAnglef& torque); @@ -45,40 +48,36 @@ namespace Nz void EnableSimulation(bool simulation); - void ForEachArbiter(std::function callback); + void ForEachArbiter(const FunctionRef& callback); void ForceSleep(); Rectf GetAABB() const; - inline float GetAngularDamping() const; RadianAnglef GetAngularVelocity() const; - NAZARA_DEPRECATED("Name error, please use GetMassCenter") - inline Vector2f GetCenterOfGravity(CoordSys coordSys = CoordSys::Local) const; float GetElasticity(std::size_t shapeIndex = 0) const; float GetFriction(std::size_t shapeIndex = 0) const; - const std::shared_ptr& GetGeom() const; - cpBody* GetHandle() const; - float GetMass() const; + inline const std::shared_ptr& GetGeom() const; + inline cpBody* GetHandle() const; + inline float GetMass() const; Vector2f GetMassCenter(CoordSys coordSys = CoordSys::Local) const; float GetMomentOfInertia() const; Vector2f GetPosition() const; inline const Vector2f& GetPositionOffset() const; RadianAnglef GetRotation() const; inline std::size_t GetShapeCount() const; - std::size_t GetShapeIndex(cpShape* shape) const; + inline std::size_t GetShapeIndex(cpShape* shape) const; Vector2f GetSurfaceVelocity(std::size_t shapeIndex = 0) const; - void* GetUserdata() const; + inline void* GetUserdata() const; Vector2f GetVelocity() const; - const VelocityFunc& GetVelocityFunction() const; - ChipmunkPhysWorld2D* GetWorld() const; + inline const VelocityFunc& GetVelocityFunction() const; + inline ChipmunkPhysWorld2D* GetWorld() const; - bool IsKinematic() const; - bool IsSimulationEnabled() const; + inline bool IsKinematic() const; + inline bool IsSimulationEnabled() const; bool IsSleeping() const; - bool IsStatic() const; + inline bool IsStatic() const; void ResetVelocityFunction(); - inline void SetAngularDamping(float angularDamping); void SetAngularVelocity(const RadianAnglef& angularVelocity); void SetElasticity(float elasticity); void SetElasticity(std::size_t shapeIndex, float elasticity); @@ -94,7 +93,7 @@ namespace Nz void SetSurfaceVelocity(const Vector2f& surfaceVelocity); void SetSurfaceVelocity(std::size_t shapeIndex, const Vector2f& surfaceVelocity); void SetStatic(bool setStaticBody = true); - void SetUserdata(void* ud); + inline void SetUserdata(void* ud); void SetVelocity(const Vector2f& velocity); void SetVelocityFunction(VelocityFunc velocityFunc); @@ -112,24 +111,59 @@ namespace Nz static constexpr std::size_t InvalidShapeIndex = std::numeric_limits::max(); + struct CommonSettings + { + std::shared_ptr geom; + RadianAnglef rotation = RadianAnglef::Zero(); + Vector2f position = Vector2f::Zero(); + bool initiallySleeping = false; + bool isSimulationEnabled = true; + }; + + struct DynamicSettings : CommonSettings + { + DynamicSettings() = default; + DynamicSettings(std::shared_ptr collider, float mass_) : + mass(mass_) + { + geom = std::move(collider); + } + + RadianAnglef angularVelocity = RadianAnglef::Zero(); + Vector2f linearVelocity = Vector2f::Zero(); + float gravityFactor = 1.f; + float mass = 1.f; + }; + + struct StaticSettings : CommonSettings + { + StaticSettings() = default; + StaticSettings(std::shared_ptr collider) + { + geom = std::move(collider); + } + }; + protected: + ChipmunkRigidBody2D() = default; + void Create(ChipmunkPhysWorld2D& world, const DynamicSettings& settings); + void Create(ChipmunkPhysWorld2D& world, const StaticSettings& settings); void Destroy(); private: - cpBody* Create(float mass = 1.f, float moment = 1.f); void RegisterToSpace(); void UnregisterFromSpace(); static void CopyBodyData(cpBody* from, cpBody* to); static void CopyShapeData(cpShape* from, cpShape* to); - Vector2f m_positionOffset; - VelocityFunc m_velocityFunc; std::vector m_shapes; std::shared_ptr m_geom; - cpBody* m_handle; - void* m_userData; - ChipmunkPhysWorld2D* m_world; + MovablePtr m_handle; + MovablePtr m_world; + MovablePtr m_userData; + Vector2f m_positionOffset; + VelocityFunc m_velocityFunc; bool m_isRegistered; bool m_isSimulationEnabled; bool m_isStatic; diff --git a/include/Nazara/ChipmunkPhysics2D/ChipmunkRigidBody2D.inl b/include/Nazara/ChipmunkPhysics2D/ChipmunkRigidBody2D.inl index da94a2ea4..a14d6cc79 100644 --- a/include/Nazara/ChipmunkPhysics2D/ChipmunkRigidBody2D.inl +++ b/include/Nazara/ChipmunkPhysics2D/ChipmunkRigidBody2D.inl @@ -6,14 +6,46 @@ namespace Nz { - inline float ChipmunkRigidBody2D::GetAngularDamping() const + inline ChipmunkRigidBody2D::ChipmunkRigidBody2D(ChipmunkPhysWorld2D& world, const DynamicSettings& settings) { - return GetMomentOfInertia(); + Create(world, settings); } - inline Vector2f ChipmunkRigidBody2D::GetCenterOfGravity(CoordSys coordSys) const + inline ChipmunkRigidBody2D::ChipmunkRigidBody2D(ChipmunkPhysWorld2D& world, const StaticSettings& settings) { - return GetMassCenter(coordSys); + Create(world, settings); + } + + inline ChipmunkRigidBody2D::~ChipmunkRigidBody2D() + { + OnRigidBody2DRelease(this); + + Destroy(); + } + + inline void ChipmunkRigidBody2D::AddForce(const Vector2f& force, CoordSys coordSys) + { + return AddForce(force, GetMassCenter(coordSys), coordSys); + } + + inline void ChipmunkRigidBody2D::AddImpulse(const Vector2f& impulse, CoordSys coordSys) + { + return AddImpulse(impulse, GetMassCenter(coordSys), coordSys); + } + + inline const std::shared_ptr& ChipmunkRigidBody2D::GetGeom() const + { + return m_geom; + } + + inline cpBody* ChipmunkRigidBody2D::GetHandle() const + { + return m_handle; + } + + inline float ChipmunkRigidBody2D::GetMass() const + { + return m_mass; } inline const Vector2f& ChipmunkRigidBody2D::GetPositionOffset() const @@ -21,14 +53,53 @@ namespace Nz return m_positionOffset; } + inline std::size_t ChipmunkRigidBody2D::GetShapeIndex(cpShape* shape) const + { + auto it = std::find(m_shapes.begin(), m_shapes.end(), shape); + if (it == m_shapes.end()) + return InvalidShapeIndex; + + return std::distance(m_shapes.begin(), it); + } + inline std::size_t ChipmunkRigidBody2D::GetShapeCount() const { return m_shapes.size(); } - inline void ChipmunkRigidBody2D::SetAngularDamping(float angularDamping) + inline void* ChipmunkRigidBody2D::GetUserdata() const { - SetMomentOfInertia(angularDamping); + return m_userData; + } + + inline const ChipmunkRigidBody2D::VelocityFunc& ChipmunkRigidBody2D::GetVelocityFunction() const + { + return m_velocityFunc; + } + + inline ChipmunkPhysWorld2D* ChipmunkRigidBody2D::GetWorld() const + { + return m_world; + } + + inline bool ChipmunkRigidBody2D::IsKinematic() const + { + return m_mass <= 0.f; + } + + inline bool ChipmunkRigidBody2D::IsSimulationEnabled() const + { + return m_isSimulationEnabled; + } + + inline bool ChipmunkRigidBody2D::IsStatic() const + { + return m_isStatic; + } + + inline void ChipmunkRigidBody2D::SetUserdata(void* ud) + { + m_userData = ud; } } diff --git a/include/Nazara/ChipmunkPhysics2D/Components/ChipmunkRigidBody2DComponent.hpp b/include/Nazara/ChipmunkPhysics2D/Components/ChipmunkRigidBody2DComponent.hpp index 09e67ab33..0a9620c30 100644 --- a/include/Nazara/ChipmunkPhysics2D/Components/ChipmunkRigidBody2DComponent.hpp +++ b/include/Nazara/ChipmunkPhysics2D/Components/ChipmunkRigidBody2DComponent.hpp @@ -9,6 +9,7 @@ #include #include +#include namespace Nz { @@ -17,13 +18,20 @@ namespace Nz friend class ChipmunkPhysics2DSystem; public: - using ChipmunkRigidBody2D::ChipmunkRigidBody2D; + inline ChipmunkRigidBody2DComponent(const ChipmunkRigidBody2D::DynamicSettings& settings); + inline ChipmunkRigidBody2DComponent(const ChipmunkRigidBody2D::StaticSettings& settings); ChipmunkRigidBody2DComponent(const ChipmunkRigidBody2DComponent&) = default; ChipmunkRigidBody2DComponent(ChipmunkRigidBody2DComponent&&) noexcept = default; ~ChipmunkRigidBody2DComponent() = default; ChipmunkRigidBody2DComponent& operator=(const ChipmunkRigidBody2DComponent&) = default; ChipmunkRigidBody2DComponent& operator=(ChipmunkRigidBody2DComponent&&) noexcept = default; + + private: + inline void Construct(ChipmunkPhysWorld2D& world); + + using Setting = std::variant; + std::unique_ptr m_settings; }; } diff --git a/include/Nazara/ChipmunkPhysics2D/Components/ChipmunkRigidBody2DComponent.inl b/include/Nazara/ChipmunkPhysics2D/Components/ChipmunkRigidBody2DComponent.inl index 32eb90091..3a57558aa 100644 --- a/include/Nazara/ChipmunkPhysics2D/Components/ChipmunkRigidBody2DComponent.inl +++ b/include/Nazara/ChipmunkPhysics2D/Components/ChipmunkRigidBody2DComponent.inl @@ -6,6 +6,25 @@ namespace Nz { + inline ChipmunkRigidBody2DComponent::ChipmunkRigidBody2DComponent(const ChipmunkRigidBody2D::DynamicSettings& settings) + { + m_settings = std::make_unique(settings); + } + + inline ChipmunkRigidBody2DComponent::ChipmunkRigidBody2DComponent(const ChipmunkRigidBody2D::StaticSettings& settings) + { + m_settings = std::make_unique(settings); + } + + inline void ChipmunkRigidBody2DComponent::Construct(ChipmunkPhysWorld2D& world) + { + assert(m_settings); + std::visit([&](auto&& arg) + { + Create(world, arg); + }, *m_settings); + m_settings.reset(); + } } #include diff --git a/include/Nazara/ChipmunkPhysics2D/Systems/ChipmunkPhysics2DSystem.hpp b/include/Nazara/ChipmunkPhysics2D/Systems/ChipmunkPhysics2DSystem.hpp index 18643c8fd..c9f5256e7 100644 --- a/include/Nazara/ChipmunkPhysics2D/Systems/ChipmunkPhysics2DSystem.hpp +++ b/include/Nazara/ChipmunkPhysics2D/Systems/ChipmunkPhysics2DSystem.hpp @@ -27,8 +27,6 @@ namespace Nz ChipmunkPhysics2DSystem(ChipmunkPhysics2DSystem&&) = delete; ~ChipmunkPhysics2DSystem(); - template ChipmunkRigidBody2DComponent CreateRigidBody(Args&&... args); - inline ChipmunkPhysWorld2D& GetPhysWorld(); inline const ChipmunkPhysWorld2D& GetPhysWorld() const; @@ -38,9 +36,11 @@ namespace Nz ChipmunkPhysics2DSystem& operator=(ChipmunkPhysics2DSystem&&) = delete; private: + void OnBodyConstruct(entt::registry& registry, entt::entity entity); + entt::registry& m_registry; entt::observer m_physicsConstructObserver; - entt::scoped_connection m_constructConnection; + entt::scoped_connection m_bodyConstructConnection; ChipmunkPhysWorld2D m_physWorld; }; } diff --git a/include/Nazara/ChipmunkPhysics2D/Systems/ChipmunkPhysics2DSystem.inl b/include/Nazara/ChipmunkPhysics2D/Systems/ChipmunkPhysics2DSystem.inl index 6f34f7413..0cad5bd27 100644 --- a/include/Nazara/ChipmunkPhysics2D/Systems/ChipmunkPhysics2DSystem.inl +++ b/include/Nazara/ChipmunkPhysics2D/Systems/ChipmunkPhysics2DSystem.inl @@ -6,12 +6,6 @@ namespace Nz { - template - ChipmunkRigidBody2DComponent ChipmunkPhysics2DSystem::CreateRigidBody(Args&&... args) - { - return ChipmunkRigidBody2DComponent(&m_physWorld, std::forward(args)...); - } - inline ChipmunkPhysWorld2D& ChipmunkPhysics2DSystem::GetPhysWorld() { return m_physWorld; diff --git a/src/Nazara/ChipmunkPhysics2D/ChipmunkCollider2D.cpp b/src/Nazara/ChipmunkPhysics2D/ChipmunkCollider2D.cpp index a994f77fe..b447f827a 100644 --- a/src/Nazara/ChipmunkPhysics2D/ChipmunkCollider2D.cpp +++ b/src/Nazara/ChipmunkPhysics2D/ChipmunkCollider2D.cpp @@ -27,7 +27,7 @@ namespace Nz ChipmunkCollider2D::~ChipmunkCollider2D() = default; - void ChipmunkCollider2D::ForEachPolygon(const std::function& callback) const + void ChipmunkCollider2D::ForEachPolygon(const FunctionRef& callback) const { // Currently, the only way to get only the polygons of a shape is to create a temporary cpSpace containing only this shape // A better way to do this would be to reimplement this function in every subclass type in the very same way chipmunk does diff --git a/src/Nazara/ChipmunkPhysics2D/ChipmunkRigidBody2D.cpp b/src/Nazara/ChipmunkPhysics2D/ChipmunkRigidBody2D.cpp index 112c65b6e..f0eec661b 100644 --- a/src/Nazara/ChipmunkPhysics2D/ChipmunkRigidBody2D.cpp +++ b/src/Nazara/ChipmunkPhysics2D/ChipmunkRigidBody2D.cpp @@ -13,33 +13,11 @@ namespace Nz { - ChipmunkRigidBody2D::ChipmunkRigidBody2D(ChipmunkPhysWorld2D* world, float mass) : - ChipmunkRigidBody2D(world, mass, nullptr) - { - } - - ChipmunkRigidBody2D::ChipmunkRigidBody2D(ChipmunkPhysWorld2D* world, float mass, std::shared_ptr geom) : - m_positionOffset(Vector2f::Zero()), - m_geom(), - m_userData(nullptr), - m_world(world), - m_isRegistered(false), - m_isSimulationEnabled(true), - m_isStatic(false), - m_gravityFactor(1.f), - m_mass(mass) - { - NazaraAssert(m_world, "Invalid world"); - - m_handle = Create(mass); - SetGeom(std::move(geom)); - } - ChipmunkRigidBody2D::ChipmunkRigidBody2D(const ChipmunkRigidBody2D& object) : - m_positionOffset(object.m_positionOffset), m_geom(object.m_geom), - m_userData(object.m_userData), m_world(object.m_world), + m_userData(object.m_userData), + m_positionOffset(object.m_positionOffset), m_isRegistered(false), m_isSimulationEnabled(true), m_isStatic(object.m_isStatic), @@ -49,8 +27,11 @@ namespace Nz NazaraAssert(m_world, "Invalid world"); NazaraAssert(m_geom, "Invalid geometry"); - m_handle = Create(m_mass, object.GetMomentOfInertia()); + m_handle = cpBodyNew(m_mass, object.GetMomentOfInertia()); + cpBodySetUserData(m_handle, this); + SetGeom(object.GetGeom(), false, false); + SetVelocityFunction(object.m_velocityFunc); CopyBodyData(object.GetHandle(), m_handle); @@ -64,12 +45,12 @@ namespace Nz ChipmunkRigidBody2D::ChipmunkRigidBody2D(ChipmunkRigidBody2D&& object) noexcept : OnRigidBody2DMove(std::move(object.OnRigidBody2DMove)), OnRigidBody2DRelease(std::move(object.OnRigidBody2DRelease)), - m_positionOffset(std::move(object.m_positionOffset)), m_shapes(std::move(object.m_shapes)), m_geom(std::move(object.m_geom)), m_handle(object.m_handle), - m_userData(object.m_userData), m_world(object.m_world), + m_userData(object.m_userData), + m_positionOffset(std::move(object.m_positionOffset)), m_isRegistered(object.m_isRegistered), m_isSimulationEnabled(object.m_isSimulationEnabled), m_isStatic(object.m_isStatic), @@ -85,18 +66,6 @@ namespace Nz OnRigidBody2DMove(&object, this); } - ChipmunkRigidBody2D::~ChipmunkRigidBody2D() - { - OnRigidBody2DRelease(this); - - Destroy(); - } - - void ChipmunkRigidBody2D::AddForce(const Vector2f& force, CoordSys coordSys) - { - return AddForce(force, GetMassCenter(coordSys), coordSys); - } - void ChipmunkRigidBody2D::AddForce(const Vector2f& force, const Vector2f& point, CoordSys coordSys) { switch (coordSys) @@ -111,11 +80,6 @@ namespace Nz } } - void ChipmunkRigidBody2D::AddImpulse(const Vector2f& impulse, CoordSys coordSys) - { - return AddImpulse(impulse, GetMassCenter(coordSys), coordSys); - } - void ChipmunkRigidBody2D::AddImpulse(const Vector2f& impulse, const Vector2f& point, CoordSys coordSys) { switch (coordSys) @@ -179,19 +143,19 @@ namespace Nz } } - void ChipmunkRigidBody2D::ForEachArbiter(std::function callback) + void ChipmunkRigidBody2D::ForEachArbiter(const FunctionRef& callback) { - using CallbackType = decltype(callback); + using CallbackType = std::remove_reference_t; - auto RealCallback = [](cpBody* /*body*/, cpArbiter* arbiter, void* data) + auto Trampoline = [](cpBody* /*body*/, cpArbiter* arbiter, void* data) { CallbackType& cb = *static_cast(data); - ChipmunkArbiter2D nzArbiter(arbiter); - cb(nzArbiter); + ChipmunkArbiter2D wrappedArbiter(arbiter); + cb(wrappedArbiter); }; - cpBodyEachArbiter(m_handle, RealCallback, &callback); + cpBodyEachArbiter(m_handle, Trampoline, const_cast(static_cast(&callback))); } void ChipmunkRigidBody2D::ForceSleep() @@ -233,21 +197,6 @@ namespace Nz return float(cpShapeGetFriction(m_shapes[shapeIndex])); } - const std::shared_ptr& ChipmunkRigidBody2D::GetGeom() const - { - return m_geom; - } - - cpBody* ChipmunkRigidBody2D::GetHandle() const - { - return m_handle; - } - - float ChipmunkRigidBody2D::GetMass() const - { - return m_mass; - } - Vector2f ChipmunkRigidBody2D::GetMassCenter(CoordSys coordSys) const { cpVect massCenter = cpBodyGetCenterOfGravity(m_handle); @@ -281,15 +230,6 @@ namespace Nz return float(cpBodyGetAngle(m_handle)); } - std::size_t ChipmunkRigidBody2D::GetShapeIndex(cpShape* shape) const - { - auto it = std::find(m_shapes.begin(), m_shapes.end(), shape); - if (it == m_shapes.end()) - return InvalidShapeIndex; - - return std::distance(m_shapes.begin(), it); - } - Vector2f ChipmunkRigidBody2D::GetSurfaceVelocity(std::size_t shapeIndex) const { assert(shapeIndex < m_shapes.size()); @@ -297,47 +237,17 @@ namespace Nz return Vector2f(static_cast(vel.x), static_cast(vel.y)); } - void* ChipmunkRigidBody2D::GetUserdata() const - { - return m_userData; - } - Vector2f ChipmunkRigidBody2D::GetVelocity() const { cpVect vel = cpBodyGetVelocity(m_handle); return Vector2f(static_cast(vel.x), static_cast(vel.y)); } - const ChipmunkRigidBody2D::VelocityFunc& ChipmunkRigidBody2D::GetVelocityFunction() const - { - return m_velocityFunc; - } - - ChipmunkPhysWorld2D* ChipmunkRigidBody2D::GetWorld() const - { - return m_world; - } - - bool ChipmunkRigidBody2D::IsKinematic() const - { - return m_mass <= 0.f; - } - - bool ChipmunkRigidBody2D::IsSimulationEnabled() const - { - return m_isSimulationEnabled; - } - bool ChipmunkRigidBody2D::IsSleeping() const { return cpBodyIsSleeping(m_handle) != 0; } - bool ChipmunkRigidBody2D::IsStatic() const - { - return m_isStatic; - } - void ChipmunkRigidBody2D::ResetVelocityFunction() { m_handle->velocity_func = cpBodyUpdateVelocity; @@ -383,7 +293,8 @@ namespace Nz cpFloat mass = cpBodyGetMass(m_handle); cpFloat moment = cpBodyGetMoment(m_handle); - cpBody* newHandle = Create(static_cast(mass), static_cast(moment)); + cpBody* newHandle = cpBodyNew(static_cast(mass), static_cast(moment)); + cpBodySetUserData(newHandle, this); CopyBodyData(m_handle, newHandle); @@ -538,11 +449,6 @@ namespace Nz }); } - void ChipmunkRigidBody2D::SetUserdata(void* ud) - { - m_userData = ud; - } - void ChipmunkRigidBody2D::SetVelocity(const Vector2f& velocity) { cpBodySetVelocity(m_handle, cpv(velocity.x, velocity.y)); @@ -637,6 +543,48 @@ namespace Nz return *this; } + void ChipmunkRigidBody2D::Create(ChipmunkPhysWorld2D& world, const DynamicSettings& settings) + { + m_isRegistered = false; + m_isSimulationEnabled = settings.isSimulationEnabled; + m_isStatic = false; + m_gravityFactor = settings.gravityFactor; + m_mass = settings.mass; + m_positionOffset = Vector2f::Zero(); + m_userData = nullptr; + m_world = &world; + + m_handle = cpBodyNew(m_mass, 0.f); // moment will be recomputed by SetGeom + cpBodySetUserData(m_handle, this); + if (m_mass <= 0.f) + cpBodySetType(m_handle, CP_BODY_TYPE_KINEMATIC); + + SetGeom(settings.geom); + SetAngularVelocity(settings.angularVelocity); + SetPosition(settings.position); + SetRotation(settings.rotation); + SetVelocity(settings.linearVelocity); + } + + void ChipmunkRigidBody2D::Create(ChipmunkPhysWorld2D& world, const StaticSettings& settings) + { + m_gravityFactor = 1.f; + m_isRegistered = false; + m_isSimulationEnabled = settings.isSimulationEnabled; + m_isStatic = true; + m_mass = 0.f; + m_positionOffset = Vector2f::Zero(); + m_userData = nullptr; + m_world = &world; + + m_handle = cpBodyNewStatic(); + cpBodySetUserData(m_handle, this); + + SetGeom(settings.geom); + SetPosition(settings.position); + SetRotation(settings.rotation); + } + void ChipmunkRigidBody2D::Destroy() { UnregisterFromSpace(); @@ -653,24 +601,6 @@ namespace Nz m_shapes.clear(); } - cpBody* ChipmunkRigidBody2D::Create(float mass, float moment) - { - cpBody* handle; - if (IsKinematic()) - { - if (IsStatic()) - handle = cpBodyNewStatic(); - else - handle = cpBodyNewKinematic(); - } - else - handle = cpBodyNew(mass, moment); - - cpBodySetUserData(handle, this); - - return handle; - } - void ChipmunkRigidBody2D::RegisterToSpace() { if (!m_isRegistered) diff --git a/src/Nazara/ChipmunkPhysics2D/Systems/ChipmunkPhysics2DSystem.cpp b/src/Nazara/ChipmunkPhysics2D/Systems/ChipmunkPhysics2DSystem.cpp index faa7d89ca..1bad2ebd3 100644 --- a/src/Nazara/ChipmunkPhysics2D/Systems/ChipmunkPhysics2DSystem.cpp +++ b/src/Nazara/ChipmunkPhysics2D/Systems/ChipmunkPhysics2DSystem.cpp @@ -24,6 +24,7 @@ namespace Nz m_registry(registry), m_physicsConstructObserver(m_registry, entt::collector.group()) { + m_bodyConstructConnection = registry.on_construct().connect<&ChipmunkPhysics2DSystem::OnBodyConstruct>(this); } ChipmunkPhysics2DSystem::~ChipmunkPhysics2DSystem() @@ -59,4 +60,10 @@ namespace Nz nodeComponent.SetTransform(rigidBodyComponent.GetPosition(), rigidBodyComponent.GetRotation()); } } + + void ChipmunkPhysics2DSystem::OnBodyConstruct(entt::registry& registry, entt::entity entity) + { + ChipmunkRigidBody2DComponent& rigidBody = registry.get(entity); + rigidBody.Construct(m_physWorld); + } } diff --git a/tests/UnitTests/Engine/Physics2D/PhysWorld2DTest.cpp b/tests/UnitTests/Engine/Physics2D/PhysWorld2DTest.cpp index 45c404501..7abc043df 100644 --- a/tests/UnitTests/Engine/Physics2D/PhysWorld2DTest.cpp +++ b/tests/UnitTests/Engine/Physics2D/PhysWorld2DTest.cpp @@ -114,20 +114,20 @@ SCENARIO("PhysWorld2D", "[PHYSICS2D][PHYSWORLD2D]") Nz::Rectf characterAABB(0.f, 0.f, 1.f, 1.f); std::shared_ptr characterBox = std::make_shared(characterAABB); characterBox->SetCollisionId(CHARACTER_COLLISION_ID); - Nz::ChipmunkRigidBody2D character(&world, 1.f, characterBox); + Nz::ChipmunkRigidBody2D character(world, Nz::ChipmunkRigidBody2D::DynamicSettings(characterBox, 1.f)); character.SetPosition(Nz::Vector2f::Zero()); Nz::Rectf wallAABB(0.f, 0.f, 1.f, 2.f); std::shared_ptr wallBox = std::make_shared(wallAABB); wallBox->SetCollisionId(WALL_COLLISION_ID); - Nz::ChipmunkRigidBody2D wall(&world, 0.f, wallBox); + Nz::ChipmunkRigidBody2D wall(world, Nz::ChipmunkRigidBody2D::StaticSettings(wallBox)); wall.SetPosition(Nz::Vector2f(5.f, 0.f)); Nz::Rectf triggerAABB(0.f, 0.f, 1.f, 1.f); std::shared_ptr triggerBox = std::make_shared(triggerAABB); triggerBox->SetTrigger(true); triggerBox->SetCollisionId(TRIGGER_COLLISION_ID); - Nz::ChipmunkRigidBody2D trigger(&world, 0.f, triggerBox); + Nz::ChipmunkRigidBody2D trigger(world, Nz::ChipmunkRigidBody2D::StaticSettings(triggerBox)); trigger.SetPosition(Nz::Vector2f(2.f, 0.f)); world.Step(Nz::Time::Zero()); @@ -199,8 +199,11 @@ Nz::ChipmunkRigidBody2D CreateBody(Nz::ChipmunkPhysWorld2D& world, const Nz::Vec std::shared_ptr box = std::make_shared(aabb); box->SetCategoryMask(categoryMask); box->SetCollisionMask(collisionMask); - float mass = isMoving ? 1.f : 0.f; - Nz::ChipmunkRigidBody2D rigidBody(&world, mass, box); - rigidBody.SetPosition(position); - return rigidBody; + + Nz::ChipmunkRigidBody2D::DynamicSettings settings; + settings.geom = std::move(box); + settings.mass = isMoving ? 1.f : 0.f; + settings.position = position; + + return Nz::ChipmunkRigidBody2D(world, settings); } diff --git a/tests/UnitTests/Engine/Physics2D/RigidBody2DTest.cpp b/tests/UnitTests/Engine/Physics2D/RigidBody2DTest.cpp index 2c4a6f7cf..36715a3ed 100644 --- a/tests/UnitTests/Engine/Physics2D/RigidBody2DTest.cpp +++ b/tests/UnitTests/Engine/Physics2D/RigidBody2DTest.cpp @@ -18,9 +18,12 @@ SCENARIO("RigidBody2D", "[PHYSICS2D][RIGIDBODY2D]") Nz::Vector2f positionAABB(3.f, 4.f); Nz::Rectf aabb(positionAABB.x, positionAABB.y, 1.f, 2.f); - std::shared_ptr box = std::make_shared(aabb); - float mass = 1.f; - Nz::ChipmunkRigidBody2D body(&world, mass, box); + + Nz::ChipmunkRigidBody2D::DynamicSettings dynamicSettings; + dynamicSettings.geom = std::make_shared(aabb); + dynamicSettings.mass = 1.f; + + Nz::ChipmunkRigidBody2D body(world, dynamicSettings); float angularVelocity = 0.2f; body.SetAngularVelocity(angularVelocity); Nz::Vector2f massCenter(5.f, 7.f); @@ -36,6 +39,8 @@ SCENARIO("RigidBody2D", "[PHYSICS2D][RIGIDBODY2D]") world.Step(Nz::Time::Second()); + Nz::ChipmunkRigidBody2D::StaticSettings staticSettings; + WHEN("We copy construct the body") { body.AddForce(Nz::Vector2f(3.f, 5.f)); @@ -54,7 +59,7 @@ SCENARIO("RigidBody2D", "[PHYSICS2D][RIGIDBODY2D]") WHEN("We copy assign the body") { - Nz::ChipmunkRigidBody2D copiedBody(&world, 0.f); + Nz::ChipmunkRigidBody2D copiedBody(world, staticSettings); copiedBody = body; EQUALITY(copiedBody, body); } @@ -62,7 +67,7 @@ SCENARIO("RigidBody2D", "[PHYSICS2D][RIGIDBODY2D]") WHEN("We move assign the body") { Nz::ChipmunkRigidBody2D copiedBody(body); - Nz::ChipmunkRigidBody2D movedBody(&world, 0.f); + Nz::ChipmunkRigidBody2D movedBody(world, staticSettings); movedBody = std::move(body); EQUALITY(movedBody, copiedBody); } @@ -113,9 +118,13 @@ SCENARIO("RigidBody2D", "[PHYSICS2D][RIGIDBODY2D]") Nz::Vector2f positionAABB(3.f, 4.f); Nz::Rectf aabb(positionAABB.x, positionAABB.y, 1.f, 2.f); - std::shared_ptr box = std::make_shared(aabb); - float mass = 1.f; - Nz::ChipmunkRigidBody2D body(&world, mass); + + Nz::ChipmunkRigidBody2D::DynamicSettings dynamicSettings; + dynamicSettings.mass = 1.f; + + auto box = std::make_shared(aabb); + + Nz::ChipmunkRigidBody2D body(world, dynamicSettings); body.SetGeom(box, true, false); bool userData = false; @@ -134,7 +143,7 @@ SCENARIO("RigidBody2D", "[PHYSICS2D][RIGIDBODY2D]") CHECK(body.GetAngularVelocity() == 0.f); CHECK(body.GetMassCenter(Nz::CoordSys::Global) == position); CHECK(body.GetGeom() == box); - CHECK(body.GetMass() == Catch::Approx(mass)); + CHECK(body.GetMass() == Catch::Approx(dynamicSettings.mass)); CHECK(body.GetPosition() == position); CHECK(body.GetRotation().value == Catch::Approx(0.f)); CHECK(body.GetUserdata() == &userData); @@ -216,9 +225,10 @@ SCENARIO("RigidBody2D", "[PHYSICS2D][RIGIDBODY2D]") Nz::Vector2f position(3.f, 4.f); float radius = 5.f; + std::shared_ptr circle = std::make_shared(radius, position); - float mass = 1.f; - Nz::ChipmunkRigidBody2D body(&world, mass); + + Nz::ChipmunkRigidBody2D body(world, Nz::ChipmunkRigidBody2D::DynamicSettings({}, 1.f)); body.SetGeom(circle, true, false); world.Step(Nz::Time::Second()); @@ -249,7 +259,7 @@ SCENARIO("RigidBody2D", "[PHYSICS2D][RIGIDBODY2D]") std::shared_ptr compound = std::make_shared(colliders); float mass = 1.f; - Nz::ChipmunkRigidBody2D body(&world, mass); + Nz::ChipmunkRigidBody2D body(world, Nz::ChipmunkRigidBody2D::DynamicSettings({}, mass)); body.SetGeom(compound, true, false); world.Step(Nz::Time::Second()); @@ -278,7 +288,7 @@ SCENARIO("RigidBody2D", "[PHYSICS2D][RIGIDBODY2D]") Nz::SparsePtr sparsePtr(vertices.data()); std::shared_ptr convex = std::make_shared(sparsePtr, vertices.size()); float mass = 1.f; - Nz::ChipmunkRigidBody2D body(&world, mass); + Nz::ChipmunkRigidBody2D body(world, Nz::ChipmunkRigidBody2D::DynamicSettings({}, mass)); body.SetGeom(convex, true, false); world.Step(Nz::Time::Second()); @@ -302,7 +312,7 @@ SCENARIO("RigidBody2D", "[PHYSICS2D][RIGIDBODY2D]") Nz::Vector2f positionB(1.f, -4.f); std::shared_ptr segment = std::make_shared(positionA, positionB, 0.f); float mass = 1.f; - Nz::ChipmunkRigidBody2D body(&world, mass); + Nz::ChipmunkRigidBody2D body(world, Nz::ChipmunkRigidBody2D::DynamicSettings({}, mass)); body.SetGeom(segment, true, false); world.Step(Nz::Time::Second()); @@ -325,7 +335,7 @@ Nz::ChipmunkRigidBody2D CreateBody(Nz::ChipmunkPhysWorld2D& world) std::shared_ptr box = std::make_shared(aabb); float mass = 1.f; - Nz::ChipmunkRigidBody2D body(&world, mass, box); + Nz::ChipmunkRigidBody2D body(world, Nz::ChipmunkRigidBody2D::DynamicSettings(box, mass)); body.SetPosition(Nz::Vector2f::Zero()); return body;