From 3153af485c933c0a515934bbb900570482a66540 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Leclercq?= Date: Thu, 7 Sep 2017 16:16:11 +0200 Subject: [PATCH] Physics2D: Handle kinematic objects properly --- include/Nazara/Physics2D/RigidBody2D.hpp | 6 +- src/Nazara/Physics2D/Collider2D.cpp | 4 +- src/Nazara/Physics2D/RigidBody2D.cpp | 71 +++++++++++++----------- tests/Engine/Physics2D/RigidBody2D.cpp | 4 +- 4 files changed, 46 insertions(+), 39 deletions(-) diff --git a/include/Nazara/Physics2D/RigidBody2D.hpp b/include/Nazara/Physics2D/RigidBody2D.hpp index d2a4ba29d..aec505e15 100644 --- a/include/Nazara/Physics2D/RigidBody2D.hpp +++ b/include/Nazara/Physics2D/RigidBody2D.hpp @@ -44,13 +44,14 @@ namespace Nz const Collider2DRef& GetGeom() const; cpBody* GetHandle() const; float GetMass() const; + float GetMomentOfInertia() const; Vector2f GetPosition() const; float GetRotation() const; void* GetUserdata() const; Vector2f GetVelocity() const; PhysWorld2D* GetWorld() const; - bool IsMoveable() const; + bool IsKinematic() const; bool IsSleeping() const; void SetAngularVelocity(float angularVelocity); @@ -70,7 +71,8 @@ namespace Nz NazaraSignal(OnRigidBody2DRelease, RigidBody2D* /*rigidBody*/); private: - void Create(float mass = 1.f, float moment = 1.f); + void CopyBodyData(cpBody* body); + cpBody* Create(float mass = 1.f, float moment = 1.f); void Destroy(); std::vector m_shapes; diff --git a/src/Nazara/Physics2D/Collider2D.cpp b/src/Nazara/Physics2D/Collider2D.cpp index f92c405db..95cd633af 100644 --- a/src/Nazara/Physics2D/Collider2D.cpp +++ b/src/Nazara/Physics2D/Collider2D.cpp @@ -143,9 +143,9 @@ namespace Nz return ColliderType2D_Null; } - float NullCollider2D::ComputeMomentOfInertia(float /*mass*/) const + float NullCollider2D::ComputeMomentOfInertia(float mass) const { - return 0.f; + return (mass > 0.f) ? 1.f : 0.f; //< Null inertia is only possible for static/kinematic objects } void NullCollider2D::CreateShapes(RigidBody2D* /*body*/, std::vector& /*shapes*/) const diff --git a/src/Nazara/Physics2D/RigidBody2D.cpp b/src/Nazara/Physics2D/RigidBody2D.cpp index 8829df66d..6e6191c41 100644 --- a/src/Nazara/Physics2D/RigidBody2D.cpp +++ b/src/Nazara/Physics2D/RigidBody2D.cpp @@ -27,10 +27,8 @@ namespace Nz { NazaraAssert(m_world, "Invalid world"); - Create(); - + m_handle = Create(mass); SetGeom(geom); - SetMass(mass); } RigidBody2D::RigidBody2D(const RigidBody2D& object) : @@ -43,30 +41,13 @@ namespace Nz NazaraAssert(m_world, "Invalid world"); NazaraAssert(m_geom, "Invalid geometry"); - Create(); + m_handle = Create(object.GetMass(), object.GetMomentOfInertia()); + SetGeom(object.GetGeom(), false); - cpBodySetMass(m_handle, cpBodyGetMass(object.GetHandle())); - cpBodySetMoment(m_handle, cpBodyGetMoment(object.GetHandle())); + CopyBodyData(object.GetHandle()); - SetGeom(object.GetGeom()); - SetMass(object.GetMass()); - - cpBodySetForce(m_handle, cpBodyGetForce(object.GetHandle())); - cpBodySetTorque(m_handle, cpBodyGetTorque(object.GetHandle())); - - cpBodySetAngle(m_handle, cpBodyGetAngle(object.GetHandle())); - cpBodySetAngularVelocity(m_handle, cpBodyGetAngularVelocity(object.GetHandle())); - cpBodySetCenterOfGravity(m_handle, cpBodyGetCenterOfGravity(object.GetHandle())); - cpBodySetPosition(m_handle, cpBodyGetPosition(object.GetHandle())); - cpBodySetVelocity(m_handle, cpBodyGetVelocity(object.GetHandle())); - - for (int i = 0; i != m_shapes.size(); ++i) + for (int i = 0; i < m_shapes.size(); ++i) m_shapes[i]->bb = cpShapeCacheBB(object.m_shapes[i]); - - cpBodySetMass(m_handle, cpBodyGetMass(object.GetHandle())); - cpBodySetMoment(m_handle, cpBodyGetMoment(object.GetHandle())); - - m_handle->m = object.GetHandle()->m; } RigidBody2D::RigidBody2D(RigidBody2D&& object) : @@ -172,6 +153,11 @@ namespace Nz return m_mass; } + float RigidBody2D::GetMomentOfInertia() const + { + return float(cpBodyGetMoment(m_handle)); + } + Vector2f RigidBody2D::GetCenterOfGravity(CoordSys coordSys) const { cpVect cog = cpBodyGetCenterOfGravity(m_handle); @@ -216,9 +202,9 @@ namespace Nz return m_world; } - bool RigidBody2D::IsMoveable() const + bool RigidBody2D::IsKinematic() const { - return m_mass > 0.f; + return m_mass <= 0.f; } bool RigidBody2D::IsSleeping() const @@ -240,8 +226,12 @@ namespace Nz cpFloat mass = cpBodyGetMass(m_handle); cpFloat moment = cpBodyGetMoment(m_handle); + cpBody* newHandle = Create(static_cast(mass), static_cast(moment)); + + CopyBodyData(m_handle); Destroy(); - Create(static_cast(mass), static_cast(moment)); + + m_handle = newHandle; } if (geom) @@ -299,8 +289,7 @@ namespace Nz void RigidBody2D::SetMassCenter(const Vector2f& center) { - if (m_mass > 0.f) - cpBodySetCenterOfGravity(m_handle, cpv(center.x, center.y)); + cpBodySetCenterOfGravity(m_handle, cpv(center.x, center.y)); } void RigidBody2D::SetMomentOfInertia(float moment) @@ -364,12 +353,28 @@ namespace Nz return *this; } - void RigidBody2D::Create(float mass, float moment) + void RigidBody2D::CopyBodyData(cpBody* body) { - m_handle = cpBodyNew(mass, moment); - cpBodySetUserData(m_handle, this); + cpBodySetAngle(m_handle, cpBodyGetAngle(body)); + cpBodySetAngularVelocity(m_handle, cpBodyGetAngularVelocity(body)); + cpBodySetCenterOfGravity(m_handle, cpBodyGetCenterOfGravity(body)); + cpBodySetForce(m_handle, cpBodyGetForce(body)); + cpBodySetPosition(m_handle, cpBodyGetPosition(body)); + cpBodySetTorque(m_handle, cpBodyGetTorque(body)); + cpBodySetVelocity(m_handle, cpBodyGetVelocity(body)); + } - cpSpaceAddBody(m_world->GetHandle(), m_handle); + cpBody* RigidBody2D::Create(float mass, float moment) + { + cpBody* handle = cpBodyNew(mass, moment); + cpBodySetUserData(handle, this); + + if (mass <= 0.f) + cpBodySetType(handle, CP_BODY_TYPE_KINEMATIC); + + cpSpaceAddBody(m_world->GetHandle(), handle); + + return handle; } void RigidBody2D::Destroy() diff --git a/tests/Engine/Physics2D/RigidBody2D.cpp b/tests/Engine/Physics2D/RigidBody2D.cpp index f45e727b1..98a7fc35a 100644 --- a/tests/Engine/Physics2D/RigidBody2D.cpp +++ b/tests/Engine/Physics2D/RigidBody2D.cpp @@ -128,7 +128,7 @@ SCENARIO("RigidBody2D", "[PHYSICS2D][RIGIDBODY2D]") CHECK(body.GetUserdata() == &userData); CHECK(body.GetVelocity() == Nz::Vector2f::Zero()); - CHECK(body.IsMoveable() == true); + CHECK(body.IsKinematic() == false); CHECK(body.IsSleeping() == false); } } @@ -315,4 +315,4 @@ void EQUALITY(const Nz::RigidBody2D& left, const Nz::RigidBody2D& right) CHECK(left.GetRotation() == right.GetRotation()); CHECK(left.GetUserdata() == right.GetUserdata()); CHECK(left.GetVelocity() == right.GetVelocity()); -} \ No newline at end of file +}