ChipmunkPhysics2D: Rework RigidBody2D

This commit is contained in:
SirLynix
2023-08-07 18:17:00 +02:00
parent 8eef44ff76
commit 32f8141bd8
13 changed files with 287 additions and 203 deletions

View File

@@ -13,6 +13,7 @@
#include <Nazara/Core/ObjectLibrary.hpp>
#include <Nazara/Math/Rect.hpp>
#include <Nazara/Math/Vector2.hpp>
#include <NazaraUtils/FunctionRef.hpp>
#include <NazaraUtils/Signal.hpp>
#include <NazaraUtils/SparsePtr.hpp>
#include <vector>
@@ -38,7 +39,7 @@ namespace Nz
virtual Vector2f ComputeCenterOfMass() const = 0;
virtual float ComputeMomentOfInertia(float mass) const = 0;
virtual void ForEachPolygon(const std::function<void(const Vector2f* vertices, std::size_t vertexCount)>& callback) const;
virtual void ForEachPolygon(const FunctionRef<void(const Vector2f* vertices, std::size_t vertexCount)>& callback) const;
inline UInt32 GetCategoryMask() const;
inline UInt32 GetCollisionGroup() const;

View File

@@ -27,17 +27,20 @@ namespace Nz
class NAZARA_CHIPMUNKPHYSICS2D_API ChipmunkRigidBody2D
{
public:
struct DynamicSettings;
struct StaticSettings;
using VelocityFunc = std::function<void(ChipmunkRigidBody2D& body2D, const Vector2f& gravity, float damping, float deltaTime)>;
ChipmunkRigidBody2D(ChipmunkPhysWorld2D* world, float mass);
ChipmunkRigidBody2D(ChipmunkPhysWorld2D* world, float mass, std::shared_ptr<ChipmunkCollider2D> 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<void(ChipmunkArbiter2D& /*arbiter*/)> callback);
void ForEachArbiter(const FunctionRef<void(ChipmunkArbiter2D& /*arbiter*/)>& 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<ChipmunkCollider2D>& GetGeom() const;
cpBody* GetHandle() const;
float GetMass() const;
inline const std::shared_ptr<ChipmunkCollider2D>& 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<std::size_t>::max();
struct CommonSettings
{
std::shared_ptr<ChipmunkCollider2D> geom;
RadianAnglef rotation = RadianAnglef::Zero();
Vector2f position = Vector2f::Zero();
bool initiallySleeping = false;
bool isSimulationEnabled = true;
};
struct DynamicSettings : CommonSettings
{
DynamicSettings() = default;
DynamicSettings(std::shared_ptr<ChipmunkCollider2D> 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<ChipmunkCollider2D> 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<cpShape*> m_shapes;
std::shared_ptr<ChipmunkCollider2D> m_geom;
cpBody* m_handle;
void* m_userData;
ChipmunkPhysWorld2D* m_world;
MovablePtr<cpBody> m_handle;
MovablePtr<ChipmunkPhysWorld2D> m_world;
MovablePtr<void> m_userData;
Vector2f m_positionOffset;
VelocityFunc m_velocityFunc;
bool m_isRegistered;
bool m_isSimulationEnabled;
bool m_isStatic;

View File

@@ -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<ChipmunkCollider2D>& 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;
}
}

View File

@@ -9,6 +9,7 @@
#include <NazaraUtils/Prerequisites.hpp>
#include <Nazara/ChipmunkPhysics2D/ChipmunkRigidBody2D.hpp>
#include <variant>
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<ChipmunkRigidBody2D::DynamicSettings, ChipmunkRigidBody2D::StaticSettings>;
std::unique_ptr<Setting> m_settings;
};
}

View File

@@ -6,6 +6,25 @@
namespace Nz
{
inline ChipmunkRigidBody2DComponent::ChipmunkRigidBody2DComponent(const ChipmunkRigidBody2D::DynamicSettings& settings)
{
m_settings = std::make_unique<Setting>(settings);
}
inline ChipmunkRigidBody2DComponent::ChipmunkRigidBody2DComponent(const ChipmunkRigidBody2D::StaticSettings& settings)
{
m_settings = std::make_unique<Setting>(settings);
}
inline void ChipmunkRigidBody2DComponent::Construct(ChipmunkPhysWorld2D& world)
{
assert(m_settings);
std::visit([&](auto&& arg)
{
Create(world, arg);
}, *m_settings);
m_settings.reset();
}
}
#include <Nazara/ChipmunkPhysics2D/DebugOff.hpp>

View File

@@ -27,8 +27,6 @@ namespace Nz
ChipmunkPhysics2DSystem(ChipmunkPhysics2DSystem&&) = delete;
~ChipmunkPhysics2DSystem();
template<typename... Args> 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;
};
}

View File

@@ -6,12 +6,6 @@
namespace Nz
{
template<typename... Args>
ChipmunkRigidBody2DComponent ChipmunkPhysics2DSystem::CreateRigidBody(Args&&... args)
{
return ChipmunkRigidBody2DComponent(&m_physWorld, std::forward<Args>(args)...);
}
inline ChipmunkPhysWorld2D& ChipmunkPhysics2DSystem::GetPhysWorld()
{
return m_physWorld;