Physics2D: Handle kinematic objects properly

This commit is contained in:
Jérôme Leclercq 2017-09-07 16:16:11 +02:00
parent 305a72a7d2
commit 3153af485c
4 changed files with 46 additions and 39 deletions

View File

@ -44,13 +44,14 @@ namespace Nz
const Collider2DRef& GetGeom() const; const Collider2DRef& GetGeom() const;
cpBody* GetHandle() const; cpBody* GetHandle() const;
float GetMass() const; float GetMass() const;
float GetMomentOfInertia() const;
Vector2f GetPosition() const; Vector2f GetPosition() const;
float GetRotation() const; float GetRotation() const;
void* GetUserdata() const; void* GetUserdata() const;
Vector2f GetVelocity() const; Vector2f GetVelocity() const;
PhysWorld2D* GetWorld() const; PhysWorld2D* GetWorld() const;
bool IsMoveable() const; bool IsKinematic() const;
bool IsSleeping() const; bool IsSleeping() const;
void SetAngularVelocity(float angularVelocity); void SetAngularVelocity(float angularVelocity);
@ -70,7 +71,8 @@ namespace Nz
NazaraSignal(OnRigidBody2DRelease, RigidBody2D* /*rigidBody*/); NazaraSignal(OnRigidBody2DRelease, RigidBody2D* /*rigidBody*/);
private: 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(); void Destroy();
std::vector<cpShape*> m_shapes; std::vector<cpShape*> m_shapes;

View File

@ -143,9 +143,9 @@ namespace Nz
return ColliderType2D_Null; 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<cpShape*>& /*shapes*/) const void NullCollider2D::CreateShapes(RigidBody2D* /*body*/, std::vector<cpShape*>& /*shapes*/) const

View File

@ -27,10 +27,8 @@ namespace Nz
{ {
NazaraAssert(m_world, "Invalid world"); NazaraAssert(m_world, "Invalid world");
Create(); m_handle = Create(mass);
SetGeom(geom); SetGeom(geom);
SetMass(mass);
} }
RigidBody2D::RigidBody2D(const RigidBody2D& object) : RigidBody2D::RigidBody2D(const RigidBody2D& object) :
@ -43,30 +41,13 @@ namespace Nz
NazaraAssert(m_world, "Invalid world"); NazaraAssert(m_world, "Invalid world");
NazaraAssert(m_geom, "Invalid geometry"); NazaraAssert(m_geom, "Invalid geometry");
Create(); m_handle = Create(object.GetMass(), object.GetMomentOfInertia());
SetGeom(object.GetGeom(), false);
cpBodySetMass(m_handle, cpBodyGetMass(object.GetHandle())); CopyBodyData(object.GetHandle());
cpBodySetMoment(m_handle, cpBodyGetMoment(object.GetHandle()));
SetGeom(object.GetGeom()); for (int i = 0; i < m_shapes.size(); ++i)
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)
m_shapes[i]->bb = cpShapeCacheBB(object.m_shapes[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) : RigidBody2D::RigidBody2D(RigidBody2D&& object) :
@ -172,6 +153,11 @@ namespace Nz
return m_mass; return m_mass;
} }
float RigidBody2D::GetMomentOfInertia() const
{
return float(cpBodyGetMoment(m_handle));
}
Vector2f RigidBody2D::GetCenterOfGravity(CoordSys coordSys) const Vector2f RigidBody2D::GetCenterOfGravity(CoordSys coordSys) const
{ {
cpVect cog = cpBodyGetCenterOfGravity(m_handle); cpVect cog = cpBodyGetCenterOfGravity(m_handle);
@ -216,9 +202,9 @@ namespace Nz
return m_world; 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 bool RigidBody2D::IsSleeping() const
@ -240,8 +226,12 @@ namespace Nz
cpFloat mass = cpBodyGetMass(m_handle); cpFloat mass = cpBodyGetMass(m_handle);
cpFloat moment = cpBodyGetMoment(m_handle); cpFloat moment = cpBodyGetMoment(m_handle);
cpBody* newHandle = Create(static_cast<float>(mass), static_cast<float>(moment));
CopyBodyData(m_handle);
Destroy(); Destroy();
Create(static_cast<float>(mass), static_cast<float>(moment));
m_handle = newHandle;
} }
if (geom) if (geom)
@ -299,8 +289,7 @@ namespace Nz
void RigidBody2D::SetMassCenter(const Vector2f& center) 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) void RigidBody2D::SetMomentOfInertia(float moment)
@ -364,12 +353,28 @@ namespace Nz
return *this; return *this;
} }
void RigidBody2D::Create(float mass, float moment) void RigidBody2D::CopyBodyData(cpBody* body)
{ {
m_handle = cpBodyNew(mass, moment); cpBodySetAngle(m_handle, cpBodyGetAngle(body));
cpBodySetUserData(m_handle, this); 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() void RigidBody2D::Destroy()

View File

@ -128,7 +128,7 @@ SCENARIO("RigidBody2D", "[PHYSICS2D][RIGIDBODY2D]")
CHECK(body.GetUserdata() == &userData); CHECK(body.GetUserdata() == &userData);
CHECK(body.GetVelocity() == Nz::Vector2f::Zero()); CHECK(body.GetVelocity() == Nz::Vector2f::Zero());
CHECK(body.IsMoveable() == true); CHECK(body.IsKinematic() == false);
CHECK(body.IsSleeping() == 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.GetRotation() == right.GetRotation());
CHECK(left.GetUserdata() == right.GetUserdata()); CHECK(left.GetUserdata() == right.GetUserdata());
CHECK(left.GetVelocity() == right.GetVelocity()); CHECK(left.GetVelocity() == right.GetVelocity());
} }