ChipmunkPhysics2D/RigidBody2D: Add unique body index and remove userdata
This commit is contained in:
parent
09f282f2fe
commit
5484967498
|
|
@ -14,11 +14,13 @@
|
||||||
#include <Nazara/Core/Time.hpp>
|
#include <Nazara/Core/Time.hpp>
|
||||||
#include <Nazara/Math/Angle.hpp>
|
#include <Nazara/Math/Angle.hpp>
|
||||||
#include <Nazara/Math/Vector2.hpp>
|
#include <Nazara/Math/Vector2.hpp>
|
||||||
|
#include <NazaraUtils/Bitset.hpp>
|
||||||
#include <NazaraUtils/FunctionRef.hpp>
|
#include <NazaraUtils/FunctionRef.hpp>
|
||||||
#include <NazaraUtils/Signal.hpp>
|
#include <NazaraUtils/Signal.hpp>
|
||||||
#include <functional>
|
#include <functional>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <unordered_map>
|
#include <unordered_map>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
struct cpCollisionHandler;
|
struct cpCollisionHandler;
|
||||||
struct cpSpace;
|
struct cpSpace;
|
||||||
|
|
@ -51,10 +53,10 @@ namespace Nz
|
||||||
|
|
||||||
ChipmunkPhysWorld2D();
|
ChipmunkPhysWorld2D();
|
||||||
ChipmunkPhysWorld2D(const ChipmunkPhysWorld2D&) = delete;
|
ChipmunkPhysWorld2D(const ChipmunkPhysWorld2D&) = delete;
|
||||||
ChipmunkPhysWorld2D(ChipmunkPhysWorld2D&&) = delete; ///TODO
|
ChipmunkPhysWorld2D(ChipmunkPhysWorld2D&&) = delete;
|
||||||
~ChipmunkPhysWorld2D();
|
~ChipmunkPhysWorld2D();
|
||||||
|
|
||||||
void DebugDraw(const DebugDrawOptions& options, bool drawShapes = true, bool drawConstraints = true, bool drawCollisions = true);
|
void DebugDraw(const DebugDrawOptions& options, bool drawShapes = true, bool drawConstraints = true, bool drawCollisions = true) const;
|
||||||
|
|
||||||
float GetDamping() const;
|
float GetDamping() const;
|
||||||
Vector2f GetGravity() const;
|
Vector2f GetGravity() const;
|
||||||
|
|
@ -135,32 +137,27 @@ namespace Nz
|
||||||
NazaraSignal(OnPhysWorld2DPostStep, const ChipmunkPhysWorld2D* /*physWorld*/, float /*invStepCount*/);
|
NazaraSignal(OnPhysWorld2DPostStep, const ChipmunkPhysWorld2D* /*physWorld*/, float /*invStepCount*/);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void InitCallbacks(cpCollisionHandler* handler, Callback callbacks);
|
|
||||||
|
|
||||||
using PostStep = std::function<void(ChipmunkRigidBody2D* body)>;
|
using PostStep = std::function<void(ChipmunkRigidBody2D* body)>;
|
||||||
|
|
||||||
void OnRigidBodyMoved(ChipmunkRigidBody2D* oldPointer, ChipmunkRigidBody2D* newPointer);
|
static constexpr std::size_t FreeBodyIdGrowRate = 256;
|
||||||
void OnRigidBodyRelease(ChipmunkRigidBody2D* rigidBody);
|
|
||||||
|
|
||||||
void RegisterPostStep(ChipmunkRigidBody2D* rigidBody, PostStep&& func);
|
void DeferBodyAction(ChipmunkRigidBody2D& rigidBody, PostStep&& func);
|
||||||
|
void InitCallbacks(cpCollisionHandler* handler, Callback callbacks);
|
||||||
struct PostStepContainer
|
inline UInt32 RegisterBody(ChipmunkRigidBody2D& rigidBody);
|
||||||
{
|
inline void UnregisterBody(UInt32 bodyIndex);
|
||||||
NazaraSlot(ChipmunkRigidBody2D, OnRigidBody2DMove, onMovedSlot);
|
inline void UpdateBodyPointer(ChipmunkRigidBody2D& rigidBody);
|
||||||
NazaraSlot(ChipmunkRigidBody2D, OnRigidBody2DRelease, onReleaseSlot);
|
|
||||||
|
|
||||||
std::vector<PostStep> funcs;
|
|
||||||
};
|
|
||||||
|
|
||||||
static_assert(std::is_nothrow_move_constructible<PostStepContainer>::value, "PostStepContainer should be noexcept MoveConstructible");
|
|
||||||
|
|
||||||
std::size_t m_maxStepCount;
|
std::size_t m_maxStepCount;
|
||||||
std::unordered_map<cpCollisionHandler*, std::unique_ptr<Callback>> m_callbacks;
|
std::unordered_map<cpCollisionHandler*, std::unique_ptr<Callback>> m_callbacks;
|
||||||
std::unordered_map<ChipmunkRigidBody2D*, PostStepContainer> m_rigidPostSteps;
|
std::unordered_map<UInt32, std::vector<PostStep>> m_rigidBodyPostSteps;
|
||||||
|
std::vector<ChipmunkRigidBody2D*> m_bodies;
|
||||||
cpSpace* m_handle;
|
cpSpace* m_handle;
|
||||||
|
Bitset<UInt64> m_freeBodyIndices;
|
||||||
Time m_stepSize;
|
Time m_stepSize;
|
||||||
Time m_timestepAccumulator;
|
Time m_timestepAccumulator;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#include <Nazara/ChipmunkPhysics2D/ChipmunkPhysWorld2D.inl>
|
||||||
|
|
||||||
#endif // NAZARA_CHIPMUNKPHYSICS2D_CHIPMUNKPHYSWORLD2D_HPP
|
#endif // NAZARA_CHIPMUNKPHYSICS2D_CHIPMUNKPHYSWORLD2D_HPP
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,47 @@
|
||||||
|
// Copyright (C) 2023 Jérôme "Lynix" Leclercq (lynix680@gmail.com)
|
||||||
|
// This file is part of the "Nazara Engine - ChipmunkPhysics2D module"
|
||||||
|
// For conditions of distribution and use, see copyright notice in Config.hpp
|
||||||
|
|
||||||
|
#include <cassert>
|
||||||
|
#include <Nazara/ChipmunkPhysics2D/Debug.hpp>
|
||||||
|
|
||||||
|
namespace Nz
|
||||||
|
{
|
||||||
|
inline UInt32 ChipmunkPhysWorld2D::RegisterBody(ChipmunkRigidBody2D& rigidBody)
|
||||||
|
{
|
||||||
|
std::size_t bodyIndex = m_freeBodyIndices.FindFirst();
|
||||||
|
if (bodyIndex == m_freeBodyIndices.npos)
|
||||||
|
{
|
||||||
|
bodyIndex = m_freeBodyIndices.GetSize();
|
||||||
|
m_freeBodyIndices.Resize(bodyIndex + FreeBodyIdGrowRate, true);
|
||||||
|
m_bodies.resize(m_freeBodyIndices.GetSize());
|
||||||
|
}
|
||||||
|
|
||||||
|
assert(m_freeBodyIndices.Test(bodyIndex));
|
||||||
|
m_freeBodyIndices.Set(bodyIndex, false);
|
||||||
|
|
||||||
|
assert(!m_bodies[bodyIndex]);
|
||||||
|
m_bodies[bodyIndex] = &rigidBody;
|
||||||
|
|
||||||
|
return SafeCast<UInt32>(bodyIndex);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void ChipmunkPhysWorld2D::UnregisterBody(UInt32 bodyIndex)
|
||||||
|
{
|
||||||
|
assert(!m_freeBodyIndices.Test(bodyIndex));
|
||||||
|
m_freeBodyIndices.Set(bodyIndex, true);
|
||||||
|
assert(m_bodies[bodyIndex]);
|
||||||
|
m_bodies[bodyIndex] = nullptr;
|
||||||
|
|
||||||
|
m_rigidBodyPostSteps.erase(bodyIndex);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void ChipmunkPhysWorld2D::UpdateBodyPointer(ChipmunkRigidBody2D& rigidBody)
|
||||||
|
{
|
||||||
|
UInt32 bodyIndex = rigidBody.GetBodyIndex();
|
||||||
|
assert(m_bodies[bodyIndex]);
|
||||||
|
m_bodies[bodyIndex] = &rigidBody;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#include <Nazara/ChipmunkPhysics2D/DebugOff.hpp>
|
||||||
|
|
@ -53,6 +53,7 @@ namespace Nz
|
||||||
|
|
||||||
Rectf GetAABB() const;
|
Rectf GetAABB() const;
|
||||||
RadianAnglef GetAngularVelocity() const;
|
RadianAnglef GetAngularVelocity() const;
|
||||||
|
inline UInt32 GetBodyIndex() const;
|
||||||
float GetElasticity(std::size_t shapeIndex = 0) const;
|
float GetElasticity(std::size_t shapeIndex = 0) const;
|
||||||
float GetFriction(std::size_t shapeIndex = 0) const;
|
float GetFriction(std::size_t shapeIndex = 0) const;
|
||||||
inline const std::shared_ptr<ChipmunkCollider2D>& GetGeom() const;
|
inline const std::shared_ptr<ChipmunkCollider2D>& GetGeom() const;
|
||||||
|
|
@ -66,7 +67,6 @@ namespace Nz
|
||||||
inline std::size_t GetShapeCount() const;
|
inline std::size_t GetShapeCount() const;
|
||||||
inline std::size_t GetShapeIndex(cpShape* shape) const;
|
inline std::size_t GetShapeIndex(cpShape* shape) const;
|
||||||
Vector2f GetSurfaceVelocity(std::size_t shapeIndex = 0) const;
|
Vector2f GetSurfaceVelocity(std::size_t shapeIndex = 0) const;
|
||||||
inline void* GetUserdata() const;
|
|
||||||
Vector2f GetVelocity() const;
|
Vector2f GetVelocity() const;
|
||||||
inline const VelocityFunc& GetVelocityFunction() const;
|
inline const VelocityFunc& GetVelocityFunction() const;
|
||||||
inline ChipmunkPhysWorld2D* GetWorld() const;
|
inline ChipmunkPhysWorld2D* GetWorld() const;
|
||||||
|
|
@ -93,7 +93,6 @@ namespace Nz
|
||||||
void SetSurfaceVelocity(const Vector2f& surfaceVelocity);
|
void SetSurfaceVelocity(const Vector2f& surfaceVelocity);
|
||||||
void SetSurfaceVelocity(std::size_t shapeIndex, const Vector2f& surfaceVelocity);
|
void SetSurfaceVelocity(std::size_t shapeIndex, const Vector2f& surfaceVelocity);
|
||||||
void SetStatic(bool setStaticBody = true);
|
void SetStatic(bool setStaticBody = true);
|
||||||
inline void SetUserdata(void* ud);
|
|
||||||
void SetVelocity(const Vector2f& velocity);
|
void SetVelocity(const Vector2f& velocity);
|
||||||
void SetVelocityFunction(VelocityFunc velocityFunc);
|
void SetVelocityFunction(VelocityFunc velocityFunc);
|
||||||
|
|
||||||
|
|
@ -104,11 +103,9 @@ namespace Nz
|
||||||
void Wakeup();
|
void Wakeup();
|
||||||
|
|
||||||
ChipmunkRigidBody2D& operator=(const ChipmunkRigidBody2D& object);
|
ChipmunkRigidBody2D& operator=(const ChipmunkRigidBody2D& object);
|
||||||
ChipmunkRigidBody2D& operator=(ChipmunkRigidBody2D&& object);
|
ChipmunkRigidBody2D& operator=(ChipmunkRigidBody2D&& object) noexcept;
|
||||||
|
|
||||||
NazaraSignal(OnRigidBody2DMove, ChipmunkRigidBody2D* /*oldPointer*/, ChipmunkRigidBody2D* /*newPointer*/);
|
|
||||||
NazaraSignal(OnRigidBody2DRelease, ChipmunkRigidBody2D* /*rigidBody*/);
|
|
||||||
|
|
||||||
|
static constexpr UInt32 InvalidBodyIndex = std::numeric_limits<UInt32>::max();
|
||||||
static constexpr std::size_t InvalidShapeIndex = std::numeric_limits<std::size_t>::max();
|
static constexpr std::size_t InvalidShapeIndex = std::numeric_limits<std::size_t>::max();
|
||||||
|
|
||||||
struct CommonSettings
|
struct CommonSettings
|
||||||
|
|
@ -151,6 +148,7 @@ namespace Nz
|
||||||
void Destroy();
|
void Destroy();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
void DestroyBody();
|
||||||
void RegisterToSpace();
|
void RegisterToSpace();
|
||||||
void UnregisterFromSpace();
|
void UnregisterFromSpace();
|
||||||
|
|
||||||
|
|
@ -161,7 +159,7 @@ namespace Nz
|
||||||
std::shared_ptr<ChipmunkCollider2D> m_geom;
|
std::shared_ptr<ChipmunkCollider2D> m_geom;
|
||||||
MovablePtr<cpBody> m_handle;
|
MovablePtr<cpBody> m_handle;
|
||||||
MovablePtr<ChipmunkPhysWorld2D> m_world;
|
MovablePtr<ChipmunkPhysWorld2D> m_world;
|
||||||
MovablePtr<void> m_userData;
|
UInt32 m_bodyIndex;
|
||||||
Vector2f m_positionOffset;
|
Vector2f m_positionOffset;
|
||||||
VelocityFunc m_velocityFunc;
|
VelocityFunc m_velocityFunc;
|
||||||
bool m_isRegistered;
|
bool m_isRegistered;
|
||||||
|
|
|
||||||
|
|
@ -18,8 +18,6 @@ namespace Nz
|
||||||
|
|
||||||
inline ChipmunkRigidBody2D::~ChipmunkRigidBody2D()
|
inline ChipmunkRigidBody2D::~ChipmunkRigidBody2D()
|
||||||
{
|
{
|
||||||
OnRigidBody2DRelease(this);
|
|
||||||
|
|
||||||
Destroy();
|
Destroy();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -33,6 +31,11 @@ namespace Nz
|
||||||
return AddImpulse(impulse, GetMassCenter(coordSys), coordSys);
|
return AddImpulse(impulse, GetMassCenter(coordSys), coordSys);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inline UInt32 ChipmunkRigidBody2D::GetBodyIndex() const
|
||||||
|
{
|
||||||
|
return m_bodyIndex;
|
||||||
|
}
|
||||||
|
|
||||||
inline const std::shared_ptr<ChipmunkCollider2D>& ChipmunkRigidBody2D::GetGeom() const
|
inline const std::shared_ptr<ChipmunkCollider2D>& ChipmunkRigidBody2D::GetGeom() const
|
||||||
{
|
{
|
||||||
return m_geom;
|
return m_geom;
|
||||||
|
|
@ -67,11 +70,6 @@ namespace Nz
|
||||||
return m_shapes.size();
|
return m_shapes.size();
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void* ChipmunkRigidBody2D::GetUserdata() const
|
|
||||||
{
|
|
||||||
return m_userData;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline const ChipmunkRigidBody2D::VelocityFunc& ChipmunkRigidBody2D::GetVelocityFunction() const
|
inline const ChipmunkRigidBody2D::VelocityFunc& ChipmunkRigidBody2D::GetVelocityFunction() const
|
||||||
{
|
{
|
||||||
return m_velocityFunc;
|
return m_velocityFunc;
|
||||||
|
|
@ -96,11 +94,6 @@ namespace Nz
|
||||||
{
|
{
|
||||||
return m_isStatic;
|
return m_isStatic;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void ChipmunkRigidBody2D::SetUserdata(void* ud)
|
|
||||||
{
|
|
||||||
m_userData = ud;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#include <Nazara/ChipmunkPhysics2D/DebugOff.hpp>
|
#include <Nazara/ChipmunkPhysics2D/DebugOff.hpp>
|
||||||
|
|
|
||||||
|
|
@ -41,13 +41,16 @@ namespace Nz
|
||||||
auto drawOptions = static_cast<ChipmunkPhysWorld2D::DebugDrawOptions*>(userdata);
|
auto drawOptions = static_cast<ChipmunkPhysWorld2D::DebugDrawOptions*>(userdata);
|
||||||
if (drawOptions->polygonCallback)
|
if (drawOptions->polygonCallback)
|
||||||
{
|
{
|
||||||
//TODO: constexpr if to prevent copy/cast if sizeof(cpVect) == sizeof(Vector2f)
|
if constexpr (sizeof(cpVect) == sizeof(Vector2f))
|
||||||
|
drawOptions->polygonCallback(reinterpret_cast<const Vector2f*>(vertices), vertexCount, float(radius), CpDebugColorToColor(outlineColor), CpDebugColorToColor(fillColor), drawOptions->userdata);
|
||||||
|
else
|
||||||
|
{
|
||||||
|
StackArray<Vector2f> nVertices = NazaraStackArray(Vector2f, vertexCount);
|
||||||
|
for (int i = 0; i < vertexCount; ++i)
|
||||||
|
nVertices[i] = Vector2f(float(vertices[i].x), float(vertices[i].y));
|
||||||
|
|
||||||
StackArray<Vector2f> nVertices = NazaraStackArray(Vector2f, vertexCount);
|
drawOptions->polygonCallback(nVertices.data(), vertexCount, float(radius), CpDebugColorToColor(outlineColor), CpDebugColorToColor(fillColor), drawOptions->userdata);
|
||||||
for (int i = 0; i < vertexCount; ++i)
|
}
|
||||||
nVertices[i] = Vector2f(float(vertices[i].x), float(vertices[i].y));
|
|
||||||
|
|
||||||
drawOptions->polygonCallback(nVertices.data(), vertexCount, float(radius), CpDebugColorToColor(outlineColor), CpDebugColorToColor(fillColor), drawOptions->userdata);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -92,7 +95,7 @@ namespace Nz
|
||||||
cpSpaceFree(m_handle);
|
cpSpaceFree(m_handle);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ChipmunkPhysWorld2D::DebugDraw(const DebugDrawOptions& options, bool drawShapes, bool drawConstraints, bool drawCollisions)
|
void ChipmunkPhysWorld2D::DebugDraw(const DebugDrawOptions& options, bool drawShapes, bool drawConstraints, bool drawCollisions) const
|
||||||
{
|
{
|
||||||
auto ColorToCpDebugColor = [](Color c) -> cpSpaceDebugColor
|
auto ColorToCpDebugColor = [](Color c) -> cpSpaceDebugColor
|
||||||
{
|
{
|
||||||
|
|
@ -103,7 +106,7 @@ namespace Nz
|
||||||
drawOptions.collisionPointColor = ColorToCpDebugColor(options.collisionPointColor);
|
drawOptions.collisionPointColor = ColorToCpDebugColor(options.collisionPointColor);
|
||||||
drawOptions.constraintColor = ColorToCpDebugColor(options.constraintColor);
|
drawOptions.constraintColor = ColorToCpDebugColor(options.constraintColor);
|
||||||
drawOptions.shapeOutlineColor = ColorToCpDebugColor(options.shapeOutlineColor);
|
drawOptions.shapeOutlineColor = ColorToCpDebugColor(options.shapeOutlineColor);
|
||||||
drawOptions.data = const_cast<DebugDrawOptions*>(&options); //< Yeah, I know, shame :bell: but it won't be used for writing anyway
|
drawOptions.data = const_cast<DebugDrawOptions*>(&options); //< won't be used to write
|
||||||
|
|
||||||
std::underlying_type_t<cpSpaceDebugDrawFlags> drawFlags = 0;
|
std::underlying_type_t<cpSpaceDebugDrawFlags> drawFlags = 0;
|
||||||
if (drawCollisions)
|
if (drawCollisions)
|
||||||
|
|
@ -364,15 +367,18 @@ namespace Nz
|
||||||
cpSpaceStep(m_handle, dt);
|
cpSpaceStep(m_handle, dt);
|
||||||
|
|
||||||
OnPhysWorld2DPostStep(this, invStepCount);
|
OnPhysWorld2DPostStep(this, invStepCount);
|
||||||
if (!m_rigidPostSteps.empty())
|
if (!m_rigidBodyPostSteps.empty())
|
||||||
{
|
{
|
||||||
for (const auto& pair : m_rigidPostSteps)
|
for (auto&& [bodyIndex, callbackVec] : m_rigidBodyPostSteps)
|
||||||
{
|
{
|
||||||
for (const auto& step : pair.second.funcs)
|
ChipmunkRigidBody2D* rigidBody = m_bodies[bodyIndex];
|
||||||
step(pair.first);
|
assert(rigidBody);
|
||||||
|
|
||||||
|
for (const auto& step : callbackVec)
|
||||||
|
step(rigidBody);
|
||||||
}
|
}
|
||||||
|
|
||||||
m_rigidPostSteps.clear();
|
m_rigidBodyPostSteps.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
m_timestepAccumulator -= m_stepSize;
|
m_timestepAccumulator -= m_stepSize;
|
||||||
|
|
@ -504,40 +510,16 @@ namespace Nz
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void ChipmunkPhysWorld2D::OnRigidBodyMoved(ChipmunkRigidBody2D* oldPointer, ChipmunkRigidBody2D* newPointer)
|
void ChipmunkPhysWorld2D::DeferBodyAction(ChipmunkRigidBody2D& rigidBody, PostStep&& func)
|
||||||
{
|
|
||||||
auto it = m_rigidPostSteps.find(oldPointer);
|
|
||||||
if (it == m_rigidPostSteps.end())
|
|
||||||
return; //< Shouldn't happen
|
|
||||||
|
|
||||||
m_rigidPostSteps.emplace(std::make_pair(newPointer, std::move(it->second)));
|
|
||||||
m_rigidPostSteps.erase(oldPointer);
|
|
||||||
}
|
|
||||||
|
|
||||||
void ChipmunkPhysWorld2D::OnRigidBodyRelease(ChipmunkRigidBody2D* rigidBody)
|
|
||||||
{
|
|
||||||
m_rigidPostSteps.erase(rigidBody);
|
|
||||||
}
|
|
||||||
|
|
||||||
void ChipmunkPhysWorld2D::RegisterPostStep(ChipmunkRigidBody2D* rigidBody, PostStep&& func)
|
|
||||||
{
|
{
|
||||||
// If space isn't locked, no need to wait
|
// If space isn't locked, no need to wait
|
||||||
if (!cpSpaceIsLocked(m_handle))
|
if (!cpSpaceIsLocked(m_handle))
|
||||||
{
|
{
|
||||||
func(rigidBody);
|
func(&rigidBody);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto it = m_rigidPostSteps.find(rigidBody);
|
UInt32 bodyIndex = rigidBody.GetBodyIndex();
|
||||||
if (it == m_rigidPostSteps.end())
|
m_rigidBodyPostSteps[bodyIndex].emplace_back(std::move(func));
|
||||||
{
|
|
||||||
PostStepContainer postStep;
|
|
||||||
postStep.onMovedSlot.Connect(rigidBody->OnRigidBody2DMove, this, &ChipmunkPhysWorld2D::OnRigidBodyMoved);
|
|
||||||
postStep.onReleaseSlot.Connect(rigidBody->OnRigidBody2DRelease, this, &ChipmunkPhysWorld2D::OnRigidBodyRelease);
|
|
||||||
|
|
||||||
it = m_rigidPostSteps.insert(std::make_pair(rigidBody, std::move(postStep))).first;
|
|
||||||
}
|
|
||||||
|
|
||||||
it->second.funcs.emplace_back(std::move(func));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -16,7 +16,6 @@ namespace Nz
|
||||||
ChipmunkRigidBody2D::ChipmunkRigidBody2D(const ChipmunkRigidBody2D& object) :
|
ChipmunkRigidBody2D::ChipmunkRigidBody2D(const ChipmunkRigidBody2D& object) :
|
||||||
m_geom(object.m_geom),
|
m_geom(object.m_geom),
|
||||||
m_world(object.m_world),
|
m_world(object.m_world),
|
||||||
m_userData(object.m_userData),
|
|
||||||
m_positionOffset(object.m_positionOffset),
|
m_positionOffset(object.m_positionOffset),
|
||||||
m_isRegistered(false),
|
m_isRegistered(false),
|
||||||
m_isSimulationEnabled(true),
|
m_isSimulationEnabled(true),
|
||||||
|
|
@ -27,6 +26,7 @@ namespace Nz
|
||||||
NazaraAssert(m_world, "Invalid world");
|
NazaraAssert(m_world, "Invalid world");
|
||||||
NazaraAssert(m_geom, "Invalid geometry");
|
NazaraAssert(m_geom, "Invalid geometry");
|
||||||
|
|
||||||
|
m_bodyIndex = m_world->RegisterBody(*this);
|
||||||
m_handle = cpBodyNew(m_mass, object.GetMomentOfInertia());
|
m_handle = cpBodyNew(m_mass, object.GetMomentOfInertia());
|
||||||
cpBodySetUserData(m_handle, this);
|
cpBodySetUserData(m_handle, this);
|
||||||
|
|
||||||
|
|
@ -43,13 +43,11 @@ namespace Nz
|
||||||
}
|
}
|
||||||
|
|
||||||
ChipmunkRigidBody2D::ChipmunkRigidBody2D(ChipmunkRigidBody2D&& object) noexcept :
|
ChipmunkRigidBody2D::ChipmunkRigidBody2D(ChipmunkRigidBody2D&& object) noexcept :
|
||||||
OnRigidBody2DMove(std::move(object.OnRigidBody2DMove)),
|
|
||||||
OnRigidBody2DRelease(std::move(object.OnRigidBody2DRelease)),
|
|
||||||
m_shapes(std::move(object.m_shapes)),
|
m_shapes(std::move(object.m_shapes)),
|
||||||
m_geom(std::move(object.m_geom)),
|
m_geom(std::move(object.m_geom)),
|
||||||
m_handle(object.m_handle),
|
m_handle(object.m_handle),
|
||||||
m_world(object.m_world),
|
m_world(object.m_world),
|
||||||
m_userData(object.m_userData),
|
m_bodyIndex(object.m_bodyIndex),
|
||||||
m_positionOffset(std::move(object.m_positionOffset)),
|
m_positionOffset(std::move(object.m_positionOffset)),
|
||||||
m_isRegistered(object.m_isRegistered),
|
m_isRegistered(object.m_isRegistered),
|
||||||
m_isSimulationEnabled(object.m_isSimulationEnabled),
|
m_isSimulationEnabled(object.m_isSimulationEnabled),
|
||||||
|
|
@ -57,13 +55,17 @@ namespace Nz
|
||||||
m_gravityFactor(object.m_gravityFactor),
|
m_gravityFactor(object.m_gravityFactor),
|
||||||
m_mass(object.m_mass)
|
m_mass(object.m_mass)
|
||||||
{
|
{
|
||||||
cpBodySetUserData(m_handle, this);
|
if (m_handle)
|
||||||
for (cpShape* shape : m_shapes)
|
{
|
||||||
cpShapeSetUserData(shape, this);
|
cpBodySetUserData(m_handle, this);
|
||||||
|
for (cpShape* shape : m_shapes)
|
||||||
|
cpShapeSetUserData(shape, this);
|
||||||
|
|
||||||
|
m_world->UpdateBodyPointer(*this);
|
||||||
|
}
|
||||||
|
|
||||||
|
object.m_bodyIndex = InvalidBodyIndex;
|
||||||
object.m_handle = nullptr;
|
object.m_handle = nullptr;
|
||||||
|
|
||||||
OnRigidBody2DMove(&object, this);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void ChipmunkRigidBody2D::AddForce(const Vector2f& force, const Vector2f& point, CoordSys coordSys)
|
void ChipmunkRigidBody2D::AddForce(const Vector2f& force, const Vector2f& point, CoordSys coordSys)
|
||||||
|
|
@ -160,7 +162,7 @@ namespace Nz
|
||||||
|
|
||||||
void ChipmunkRigidBody2D::ForceSleep()
|
void ChipmunkRigidBody2D::ForceSleep()
|
||||||
{
|
{
|
||||||
m_world->RegisterPostStep(this, [](ChipmunkRigidBody2D* body)
|
m_world->DeferBodyAction(*this, [](ChipmunkRigidBody2D* body)
|
||||||
{
|
{
|
||||||
if (cpBodyGetType(body->GetHandle()) == CP_BODY_TYPE_DYNAMIC)
|
if (cpBodyGetType(body->GetHandle()) == CP_BODY_TYPE_DYNAMIC)
|
||||||
cpBodySleep(body->GetHandle());
|
cpBodySleep(body->GetHandle());
|
||||||
|
|
@ -298,7 +300,7 @@ namespace Nz
|
||||||
|
|
||||||
CopyBodyData(m_handle, newHandle);
|
CopyBodyData(m_handle, newHandle);
|
||||||
|
|
||||||
Destroy();
|
DestroyBody();
|
||||||
|
|
||||||
m_handle = newHandle;
|
m_handle = newHandle;
|
||||||
}
|
}
|
||||||
|
|
@ -332,7 +334,7 @@ namespace Nz
|
||||||
{
|
{
|
||||||
if (mass > 0.f)
|
if (mass > 0.f)
|
||||||
{
|
{
|
||||||
m_world->RegisterPostStep(this, [mass, recomputeMoment](ChipmunkRigidBody2D* body)
|
m_world->DeferBodyAction(*this, [mass, recomputeMoment](ChipmunkRigidBody2D* body)
|
||||||
{
|
{
|
||||||
cpBodySetMass(body->GetHandle(), mass);
|
cpBodySetMass(body->GetHandle(), mass);
|
||||||
|
|
||||||
|
|
@ -341,11 +343,11 @@ namespace Nz
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
m_world->RegisterPostStep(this, [](ChipmunkRigidBody2D* body) { cpBodySetType(body->GetHandle(), (body->IsStatic()) ? CP_BODY_TYPE_STATIC : CP_BODY_TYPE_KINEMATIC); } );
|
m_world->DeferBodyAction(*this, [](ChipmunkRigidBody2D* body) { cpBodySetType(body->GetHandle(), (body->IsStatic()) ? CP_BODY_TYPE_STATIC : CP_BODY_TYPE_KINEMATIC); } );
|
||||||
}
|
}
|
||||||
else if (mass > 0.f)
|
else if (mass > 0.f)
|
||||||
{
|
{
|
||||||
m_world->RegisterPostStep(this, [mass, recomputeMoment](ChipmunkRigidBody2D* body)
|
m_world->DeferBodyAction(*this, [mass, recomputeMoment](ChipmunkRigidBody2D* body)
|
||||||
{
|
{
|
||||||
if (cpBodyGetType(body->GetHandle()) != CP_BODY_TYPE_DYNAMIC)
|
if (cpBodyGetType(body->GetHandle()) != CP_BODY_TYPE_DYNAMIC)
|
||||||
{
|
{
|
||||||
|
|
@ -381,7 +383,7 @@ namespace Nz
|
||||||
void ChipmunkRigidBody2D::SetMomentOfInertia(float moment)
|
void ChipmunkRigidBody2D::SetMomentOfInertia(float moment)
|
||||||
{
|
{
|
||||||
// Even though Chipmunk allows us to change this anytime, we need to do it in a post-step to prevent other post-steps to override this
|
// Even though Chipmunk allows us to change this anytime, we need to do it in a post-step to prevent other post-steps to override this
|
||||||
m_world->RegisterPostStep(this, [moment] (ChipmunkRigidBody2D* body)
|
m_world->DeferBodyAction(*this, [moment] (ChipmunkRigidBody2D* body)
|
||||||
{
|
{
|
||||||
cpBodySetMoment(body->GetHandle(), moment);
|
cpBodySetMoment(body->GetHandle(), moment);
|
||||||
});
|
});
|
||||||
|
|
@ -393,7 +395,7 @@ namespace Nz
|
||||||
cpBodySetPosition(m_handle, cpvadd(cpv(position.x, position.y), cpTransformVect(m_handle->transform, cpv(m_positionOffset.x, m_positionOffset.y))));
|
cpBodySetPosition(m_handle, cpvadd(cpv(position.x, position.y), cpTransformVect(m_handle->transform, cpv(m_positionOffset.x, m_positionOffset.y))));
|
||||||
if (m_isStatic)
|
if (m_isStatic)
|
||||||
{
|
{
|
||||||
m_world->RegisterPostStep(this, [](ChipmunkRigidBody2D* body)
|
m_world->DeferBodyAction(*this, [](ChipmunkRigidBody2D* body)
|
||||||
{
|
{
|
||||||
cpSpaceReindexShapesForBody(body->GetWorld()->GetHandle(), body->GetHandle());
|
cpSpaceReindexShapesForBody(body->GetWorld()->GetHandle(), body->GetHandle());
|
||||||
});
|
});
|
||||||
|
|
@ -412,7 +414,7 @@ namespace Nz
|
||||||
cpBodySetAngle(m_handle, rotation.value);
|
cpBodySetAngle(m_handle, rotation.value);
|
||||||
if (m_isStatic)
|
if (m_isStatic)
|
||||||
{
|
{
|
||||||
m_world->RegisterPostStep(this, [](ChipmunkRigidBody2D* body)
|
m_world->DeferBodyAction(*this, [](ChipmunkRigidBody2D* body)
|
||||||
{
|
{
|
||||||
cpSpaceReindexShapesForBody(body->GetWorld()->GetHandle(), body->GetHandle());
|
cpSpaceReindexShapesForBody(body->GetWorld()->GetHandle(), body->GetHandle());
|
||||||
});
|
});
|
||||||
|
|
@ -435,7 +437,7 @@ namespace Nz
|
||||||
void ChipmunkRigidBody2D::SetStatic(bool setStaticBody)
|
void ChipmunkRigidBody2D::SetStatic(bool setStaticBody)
|
||||||
{
|
{
|
||||||
m_isStatic = setStaticBody;
|
m_isStatic = setStaticBody;
|
||||||
m_world->RegisterPostStep(this, [](ChipmunkRigidBody2D* body)
|
m_world->DeferBodyAction(*this, [](ChipmunkRigidBody2D* body)
|
||||||
{
|
{
|
||||||
if (body->IsStatic())
|
if (body->IsStatic())
|
||||||
{
|
{
|
||||||
|
|
@ -480,7 +482,7 @@ namespace Nz
|
||||||
cpBodySetAngle(m_handle, rotation.value);
|
cpBodySetAngle(m_handle, rotation.value);
|
||||||
if (m_isStatic)
|
if (m_isStatic)
|
||||||
{
|
{
|
||||||
m_world->RegisterPostStep(this, [](ChipmunkRigidBody2D* body)
|
m_world->DeferBodyAction(*this, [](ChipmunkRigidBody2D* body)
|
||||||
{
|
{
|
||||||
cpSpaceReindexShapesForBody(body->GetWorld()->GetHandle(), body->GetHandle());
|
cpSpaceReindexShapesForBody(body->GetWorld()->GetHandle(), body->GetHandle());
|
||||||
});
|
});
|
||||||
|
|
@ -494,7 +496,7 @@ namespace Nz
|
||||||
|
|
||||||
void ChipmunkRigidBody2D::Wakeup()
|
void ChipmunkRigidBody2D::Wakeup()
|
||||||
{
|
{
|
||||||
m_world->RegisterPostStep(this, [](ChipmunkRigidBody2D* body)
|
m_world->DeferBodyAction(*this, [](ChipmunkRigidBody2D* body)
|
||||||
{
|
{
|
||||||
if (cpBodyGetType(body->GetHandle()) != CP_BODY_TYPE_STATIC)
|
if (cpBodyGetType(body->GetHandle()) != CP_BODY_TYPE_STATIC)
|
||||||
cpBodyActivate(body->GetHandle());
|
cpBodyActivate(body->GetHandle());
|
||||||
|
|
@ -505,17 +507,14 @@ namespace Nz
|
||||||
|
|
||||||
ChipmunkRigidBody2D& ChipmunkRigidBody2D::operator=(const ChipmunkRigidBody2D& object)
|
ChipmunkRigidBody2D& ChipmunkRigidBody2D::operator=(const ChipmunkRigidBody2D& object)
|
||||||
{
|
{
|
||||||
ChipmunkRigidBody2D physObj(object);
|
return operator=(ChipmunkRigidBody2D(object));
|
||||||
return operator=(std::move(physObj));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ChipmunkRigidBody2D& ChipmunkRigidBody2D::operator=(ChipmunkRigidBody2D&& object)
|
ChipmunkRigidBody2D& ChipmunkRigidBody2D::operator=(ChipmunkRigidBody2D&& object) noexcept
|
||||||
{
|
{
|
||||||
Destroy();
|
Destroy();
|
||||||
|
|
||||||
OnRigidBody2DMove = std::move(object.OnRigidBody2DMove);
|
m_bodyIndex = object.m_bodyIndex;
|
||||||
OnRigidBody2DRelease = std::move(object.OnRigidBody2DRelease);
|
|
||||||
|
|
||||||
m_handle = object.m_handle;
|
m_handle = object.m_handle;
|
||||||
m_isRegistered = object.m_isRegistered;
|
m_isRegistered = object.m_isRegistered;
|
||||||
m_isSimulationEnabled = object.m_isSimulationEnabled;
|
m_isSimulationEnabled = object.m_isSimulationEnabled;
|
||||||
|
|
@ -525,7 +524,6 @@ namespace Nz
|
||||||
m_mass = object.m_mass;
|
m_mass = object.m_mass;
|
||||||
m_positionOffset = object.m_positionOffset;
|
m_positionOffset = object.m_positionOffset;
|
||||||
m_shapes = std::move(object.m_shapes);
|
m_shapes = std::move(object.m_shapes);
|
||||||
m_userData = object.m_userData;
|
|
||||||
m_velocityFunc = std::move(object.m_velocityFunc);
|
m_velocityFunc = std::move(object.m_velocityFunc);
|
||||||
m_world = object.m_world;
|
m_world = object.m_world;
|
||||||
|
|
||||||
|
|
@ -534,12 +532,13 @@ namespace Nz
|
||||||
cpBodySetUserData(m_handle, this);
|
cpBodySetUserData(m_handle, this);
|
||||||
for (cpShape* shape : m_shapes)
|
for (cpShape* shape : m_shapes)
|
||||||
cpShapeSetUserData(shape, this);
|
cpShapeSetUserData(shape, this);
|
||||||
|
|
||||||
|
m_world->UpdateBodyPointer(*this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
object.m_bodyIndex = InvalidBodyIndex;
|
||||||
object.m_handle = nullptr;
|
object.m_handle = nullptr;
|
||||||
|
|
||||||
OnRigidBody2DMove(&object, this);
|
|
||||||
|
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -551,9 +550,10 @@ namespace Nz
|
||||||
m_gravityFactor = settings.gravityFactor;
|
m_gravityFactor = settings.gravityFactor;
|
||||||
m_mass = settings.mass;
|
m_mass = settings.mass;
|
||||||
m_positionOffset = Vector2f::Zero();
|
m_positionOffset = Vector2f::Zero();
|
||||||
m_userData = nullptr;
|
|
||||||
m_world = &world;
|
m_world = &world;
|
||||||
|
|
||||||
|
m_bodyIndex = m_world->RegisterBody(*this);
|
||||||
|
|
||||||
m_handle = cpBodyNew(m_mass, 0.f); // moment will be recomputed by SetGeom
|
m_handle = cpBodyNew(m_mass, 0.f); // moment will be recomputed by SetGeom
|
||||||
cpBodySetUserData(m_handle, this);
|
cpBodySetUserData(m_handle, this);
|
||||||
if (m_mass <= 0.f)
|
if (m_mass <= 0.f)
|
||||||
|
|
@ -574,9 +574,10 @@ namespace Nz
|
||||||
m_isStatic = true;
|
m_isStatic = true;
|
||||||
m_mass = 0.f;
|
m_mass = 0.f;
|
||||||
m_positionOffset = Vector2f::Zero();
|
m_positionOffset = Vector2f::Zero();
|
||||||
m_userData = nullptr;
|
|
||||||
m_world = &world;
|
m_world = &world;
|
||||||
|
|
||||||
|
m_bodyIndex = m_world->RegisterBody(*this);
|
||||||
|
|
||||||
m_handle = cpBodyNewStatic();
|
m_handle = cpBodyNewStatic();
|
||||||
cpBodySetUserData(m_handle, this);
|
cpBodySetUserData(m_handle, this);
|
||||||
|
|
||||||
|
|
@ -586,6 +587,17 @@ namespace Nz
|
||||||
}
|
}
|
||||||
|
|
||||||
void ChipmunkRigidBody2D::Destroy()
|
void ChipmunkRigidBody2D::Destroy()
|
||||||
|
{
|
||||||
|
if (m_bodyIndex != InvalidBodyIndex)
|
||||||
|
{
|
||||||
|
m_world->UnregisterBody(m_bodyIndex);
|
||||||
|
m_bodyIndex = InvalidBodyIndex;
|
||||||
|
}
|
||||||
|
|
||||||
|
DestroyBody();
|
||||||
|
}
|
||||||
|
|
||||||
|
void ChipmunkRigidBody2D::DestroyBody()
|
||||||
{
|
{
|
||||||
UnregisterFromSpace();
|
UnregisterFromSpace();
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -34,8 +34,6 @@ SCENARIO("RigidBody2D", "[PHYSICS2D][RIGIDBODY2D]")
|
||||||
body.SetRotation(rotation);
|
body.SetRotation(rotation);
|
||||||
Nz::Vector2f velocity(-4.f, -2.f);
|
Nz::Vector2f velocity(-4.f, -2.f);
|
||||||
body.SetVelocity(velocity);
|
body.SetVelocity(velocity);
|
||||||
bool userdata = false;
|
|
||||||
body.SetUserdata(&userdata);
|
|
||||||
|
|
||||||
world.Step(Nz::Time::Second());
|
world.Step(Nz::Time::Second());
|
||||||
|
|
||||||
|
|
@ -127,9 +125,6 @@ SCENARIO("RigidBody2D", "[PHYSICS2D][RIGIDBODY2D]")
|
||||||
Nz::ChipmunkRigidBody2D body(world, dynamicSettings);
|
Nz::ChipmunkRigidBody2D body(world, dynamicSettings);
|
||||||
body.SetGeom(box, true, false);
|
body.SetGeom(box, true, false);
|
||||||
|
|
||||||
bool userData = false;
|
|
||||||
body.SetUserdata(&userData);
|
|
||||||
|
|
||||||
Nz::Vector2f position = Nz::Vector2f::Zero();
|
Nz::Vector2f position = Nz::Vector2f::Zero();
|
||||||
body.SetPosition(position);
|
body.SetPosition(position);
|
||||||
|
|
||||||
|
|
@ -146,7 +141,6 @@ SCENARIO("RigidBody2D", "[PHYSICS2D][RIGIDBODY2D]")
|
||||||
CHECK(body.GetMass() == Catch::Approx(dynamicSettings.mass));
|
CHECK(body.GetMass() == Catch::Approx(dynamicSettings.mass));
|
||||||
CHECK(body.GetPosition() == position);
|
CHECK(body.GetPosition() == position);
|
||||||
CHECK(body.GetRotation().value == Catch::Approx(0.f));
|
CHECK(body.GetRotation().value == Catch::Approx(0.f));
|
||||||
CHECK(body.GetUserdata() == &userData);
|
|
||||||
CHECK(body.GetVelocity() == Nz::Vector2f::Zero());
|
CHECK(body.GetVelocity() == Nz::Vector2f::Zero());
|
||||||
|
|
||||||
CHECK(body.IsKinematic() == false);
|
CHECK(body.IsKinematic() == false);
|
||||||
|
|
@ -351,7 +345,6 @@ void EQUALITY(const Nz::ChipmunkRigidBody2D& left, const Nz::ChipmunkRigidBody2D
|
||||||
CHECK(left.GetMass() == Catch::Approx(right.GetMass()));
|
CHECK(left.GetMass() == Catch::Approx(right.GetMass()));
|
||||||
CHECK(left.GetPosition() == right.GetPosition());
|
CHECK(left.GetPosition() == right.GetPosition());
|
||||||
CHECK(left.GetRotation().value == Catch::Approx(right.GetRotation().value));
|
CHECK(left.GetRotation().value == Catch::Approx(right.GetRotation().value));
|
||||||
CHECK(left.GetUserdata() == right.GetUserdata());
|
|
||||||
CHECK(left.GetVelocity() == right.GetVelocity());
|
CHECK(left.GetVelocity() == right.GetVelocity());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue