Physics2D: Automatically compute center of mass
This commit is contained in:
parent
b6c1bfb5d0
commit
439a62a7f8
|
|
@ -169,6 +169,8 @@ Nazara Engine:
|
||||||
- Fixed TileMap not rendering the right materials if it had no tile using some materials in-between
|
- Fixed TileMap not rendering the right materials if it had no tile using some materials in-between
|
||||||
- Added Vector[2|3|4](u)i64 typedefs
|
- Added Vector[2|3|4](u)i64 typedefs
|
||||||
- Fixed missing static Vector4::DotProduct implementation
|
- Fixed missing static Vector4::DotProduct implementation
|
||||||
|
- ⚠ **By default, Nazara computes the mass center of all 2D physics object when calling SetGeom**
|
||||||
|
- ⚠ Added Collider2D::ComputeCenterOfMass
|
||||||
|
|
||||||
Nazara Development Kit:
|
Nazara Development Kit:
|
||||||
- Added ImageWidget (#139)
|
- Added ImageWidget (#139)
|
||||||
|
|
|
||||||
|
|
@ -41,6 +41,7 @@ namespace Nz
|
||||||
Collider2D(Collider2D&&) = delete;
|
Collider2D(Collider2D&&) = delete;
|
||||||
virtual ~Collider2D();
|
virtual ~Collider2D();
|
||||||
|
|
||||||
|
virtual Nz::Vector2f ComputeCenterOfMass() const = 0;
|
||||||
virtual float ComputeMomentOfInertia(float mass) const = 0;
|
virtual float ComputeMomentOfInertia(float mass) const = 0;
|
||||||
|
|
||||||
inline UInt32 GetCategoryMask() const;
|
inline UInt32 GetCategoryMask() const;
|
||||||
|
|
@ -99,6 +100,7 @@ namespace Nz
|
||||||
BoxCollider2D(const Vector2f& size, float radius = 0.f);
|
BoxCollider2D(const Vector2f& size, float radius = 0.f);
|
||||||
BoxCollider2D(const Rectf& rect, float radius = 0.f);
|
BoxCollider2D(const Rectf& rect, float radius = 0.f);
|
||||||
|
|
||||||
|
Nz::Vector2f ComputeCenterOfMass() const override;
|
||||||
float ComputeMomentOfInertia(float mass) const override;
|
float ComputeMomentOfInertia(float mass) const override;
|
||||||
|
|
||||||
inline float GetRadius() const;
|
inline float GetRadius() const;
|
||||||
|
|
@ -125,6 +127,7 @@ namespace Nz
|
||||||
public:
|
public:
|
||||||
CircleCollider2D(float radius, const Vector2f& offset = Vector2f::Zero());
|
CircleCollider2D(float radius, const Vector2f& offset = Vector2f::Zero());
|
||||||
|
|
||||||
|
Nz::Vector2f ComputeCenterOfMass() const override;
|
||||||
float ComputeMomentOfInertia(float mass) const override;
|
float ComputeMomentOfInertia(float mass) const override;
|
||||||
|
|
||||||
inline const Vector2f& GetOffset() const;
|
inline const Vector2f& GetOffset() const;
|
||||||
|
|
@ -150,6 +153,7 @@ namespace Nz
|
||||||
public:
|
public:
|
||||||
CompoundCollider2D(std::vector<Collider2DRef> geoms);
|
CompoundCollider2D(std::vector<Collider2DRef> geoms);
|
||||||
|
|
||||||
|
Nz::Vector2f ComputeCenterOfMass() const override;
|
||||||
float ComputeMomentOfInertia(float mass) const override;
|
float ComputeMomentOfInertia(float mass) const override;
|
||||||
|
|
||||||
inline bool DoesOverrideCollisionProperties() const;
|
inline bool DoesOverrideCollisionProperties() const;
|
||||||
|
|
@ -179,6 +183,7 @@ namespace Nz
|
||||||
public:
|
public:
|
||||||
ConvexCollider2D(SparsePtr<const Vector2f> vertices, std::size_t vertexCount, float radius = 0.f);
|
ConvexCollider2D(SparsePtr<const Vector2f> vertices, std::size_t vertexCount, float radius = 0.f);
|
||||||
|
|
||||||
|
Nz::Vector2f ComputeCenterOfMass() const override;
|
||||||
float ComputeMomentOfInertia(float mass) const override;
|
float ComputeMomentOfInertia(float mass) const override;
|
||||||
|
|
||||||
ColliderType2D GetType() const override;
|
ColliderType2D GetType() const override;
|
||||||
|
|
@ -203,6 +208,7 @@ namespace Nz
|
||||||
public:
|
public:
|
||||||
NullCollider2D() = default;
|
NullCollider2D() = default;
|
||||||
|
|
||||||
|
Nz::Vector2f ComputeCenterOfMass() const override;
|
||||||
float ComputeMomentOfInertia(float mass) const override;
|
float ComputeMomentOfInertia(float mass) const override;
|
||||||
|
|
||||||
ColliderType2D GetType() const override;
|
ColliderType2D GetType() const override;
|
||||||
|
|
@ -223,6 +229,7 @@ namespace Nz
|
||||||
public:
|
public:
|
||||||
inline SegmentCollider2D(const Vector2f& first, const Vector2f& second, float thickness = 1.f);
|
inline SegmentCollider2D(const Vector2f& first, const Vector2f& second, float thickness = 1.f);
|
||||||
|
|
||||||
|
Nz::Vector2f ComputeCenterOfMass() const override;
|
||||||
float ComputeMomentOfInertia(float mass) const override;
|
float ComputeMomentOfInertia(float mass) const override;
|
||||||
|
|
||||||
inline const Vector2f& GetFirstPoint() const;
|
inline const Vector2f& GetFirstPoint() const;
|
||||||
|
|
|
||||||
|
|
@ -82,7 +82,7 @@ namespace Nz
|
||||||
void SetElasticity(std::size_t shapeIndex, float elasticity);
|
void SetElasticity(std::size_t shapeIndex, float elasticity);
|
||||||
void SetFriction(float friction);
|
void SetFriction(float friction);
|
||||||
void SetFriction(std::size_t shapeIndex, float friction);
|
void SetFriction(std::size_t shapeIndex, float friction);
|
||||||
void SetGeom(Collider2DRef geom, bool recomputeMoment = true);
|
void SetGeom(Collider2DRef geom, bool recomputeMoment = true, bool recomputeMassCenter = true);
|
||||||
void SetMass(float mass, bool recomputeMoment = true);
|
void SetMass(float mass, bool recomputeMoment = true);
|
||||||
void SetMassCenter(const Vector2f& center, CoordSys coordSys = CoordSys_Local);
|
void SetMassCenter(const Vector2f& center, CoordSys coordSys = CoordSys_Local);
|
||||||
void SetMomentOfInertia(float moment);
|
void SetMomentOfInertia(float moment);
|
||||||
|
|
|
||||||
|
|
@ -20,7 +20,7 @@ namespace Nz
|
||||||
{
|
{
|
||||||
cpShape* shape = (*shapes)[i];
|
cpShape* shape = (*shapes)[i];
|
||||||
|
|
||||||
cpShapeSetCollisionType(shape, cpFloat(m_collisionId));
|
cpShapeSetCollisionType(shape, m_collisionId);
|
||||||
cpShapeSetElasticity(shape, cpFloat(m_elasticity));
|
cpShapeSetElasticity(shape, cpFloat(m_elasticity));
|
||||||
cpShapeSetFilter(shape, filter);
|
cpShapeSetFilter(shape, filter);
|
||||||
cpShapeSetFriction(shape, cpFloat(m_friction));
|
cpShapeSetFriction(shape, cpFloat(m_friction));
|
||||||
|
|
@ -44,6 +44,11 @@ namespace Nz
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Nz::Vector2f BoxCollider2D::ComputeCenterOfMass() const
|
||||||
|
{
|
||||||
|
return m_rect.GetCenter();
|
||||||
|
}
|
||||||
|
|
||||||
float BoxCollider2D::ComputeMomentOfInertia(float mass) const
|
float BoxCollider2D::ComputeMomentOfInertia(float mass) const
|
||||||
{
|
{
|
||||||
return static_cast<float>(cpMomentForBox2(mass, cpBBNew(m_rect.x, m_rect.y, m_rect.x + m_rect.width, m_rect.y + m_rect.height)));
|
return static_cast<float>(cpMomentForBox2(mass, cpBBNew(m_rect.x, m_rect.y, m_rect.x + m_rect.width, m_rect.y + m_rect.height)));
|
||||||
|
|
@ -68,6 +73,11 @@ namespace Nz
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Nz::Vector2f CircleCollider2D::ComputeCenterOfMass() const
|
||||||
|
{
|
||||||
|
return m_offset + Nz::Vector2f(m_radius, m_radius);
|
||||||
|
}
|
||||||
|
|
||||||
float CircleCollider2D::ComputeMomentOfInertia(float mass) const
|
float CircleCollider2D::ComputeMomentOfInertia(float mass) const
|
||||||
{
|
{
|
||||||
return static_cast<float>(cpMomentForCircle(mass, 0.f, m_radius, cpv(m_offset.x, m_offset.y)));
|
return static_cast<float>(cpMomentForCircle(mass, 0.f, m_radius, cpv(m_offset.x, m_offset.y)));
|
||||||
|
|
@ -92,6 +102,15 @@ namespace Nz
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Nz::Vector2f CompoundCollider2D::ComputeCenterOfMass() const
|
||||||
|
{
|
||||||
|
Nz::Vector2f centerOfMass = Nz::Vector2f::Zero();
|
||||||
|
for (const auto& geom : m_geoms)
|
||||||
|
centerOfMass += geom->ComputeCenterOfMass();
|
||||||
|
|
||||||
|
return centerOfMass / float(m_geoms.size());
|
||||||
|
}
|
||||||
|
|
||||||
float CompoundCollider2D::ComputeMomentOfInertia(float mass) const
|
float CompoundCollider2D::ComputeMomentOfInertia(float mass) const
|
||||||
{
|
{
|
||||||
///TODO: Correctly compute moment using parallel axis theorem:
|
///TODO: Correctly compute moment using parallel axis theorem:
|
||||||
|
|
@ -144,6 +163,15 @@ namespace Nz
|
||||||
m_vertices[i].Set(*vertices++);
|
m_vertices[i].Set(*vertices++);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Nz::Vector2f ConvexCollider2D::ComputeCenterOfMass() const
|
||||||
|
{
|
||||||
|
static_assert(sizeof(cpVect) == sizeof(Vector2d), "Chipmunk vector is not equivalent to Vector2d");
|
||||||
|
|
||||||
|
cpVect center = cpCentroidForPoly(int(m_vertices.size()), reinterpret_cast<const cpVect*>(m_vertices.data()));
|
||||||
|
|
||||||
|
return Nz::Vector2f(float(center.x), float(center.y));
|
||||||
|
}
|
||||||
|
|
||||||
float ConvexCollider2D::ComputeMomentOfInertia(float mass) const
|
float ConvexCollider2D::ComputeMomentOfInertia(float mass) const
|
||||||
{
|
{
|
||||||
static_assert(sizeof(cpVect) == sizeof(Vector2d), "Chipmunk vector is not equivalent to Vector2d");
|
static_assert(sizeof(cpVect) == sizeof(Vector2d), "Chipmunk vector is not equivalent to Vector2d");
|
||||||
|
|
@ -169,6 +197,11 @@ namespace Nz
|
||||||
return ColliderType2D_Null;
|
return ColliderType2D_Null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Nz::Vector2f NullCollider2D::ComputeCenterOfMass() const
|
||||||
|
{
|
||||||
|
return Nz::Vector2f::Zero();
|
||||||
|
}
|
||||||
|
|
||||||
float NullCollider2D::ComputeMomentOfInertia(float mass) const
|
float NullCollider2D::ComputeMomentOfInertia(float mass) const
|
||||||
{
|
{
|
||||||
return (mass > 0.f) ? 1.f : 0.f; //< Null inertia is only possible for static/kinematic objects
|
return (mass > 0.f) ? 1.f : 0.f; //< Null inertia is only possible for static/kinematic objects
|
||||||
|
|
@ -181,6 +214,11 @@ namespace Nz
|
||||||
|
|
||||||
/******************************** SegmentCollider2D *********************************/
|
/******************************** SegmentCollider2D *********************************/
|
||||||
|
|
||||||
|
Nz::Vector2f SegmentCollider2D::ComputeCenterOfMass() const
|
||||||
|
{
|
||||||
|
return (m_first + m_second) / 2.f;
|
||||||
|
}
|
||||||
|
|
||||||
float SegmentCollider2D::ComputeMomentOfInertia(float mass) const
|
float SegmentCollider2D::ComputeMomentOfInertia(float mass) const
|
||||||
{
|
{
|
||||||
return static_cast<float>(cpMomentForSegment(mass, cpv(m_first.x, m_first.y), cpv(m_second.x, m_second.y), m_thickness));
|
return static_cast<float>(cpMomentForSegment(mass, cpv(m_first.x, m_first.y), cpv(m_second.x, m_second.y), m_thickness));
|
||||||
|
|
|
||||||
|
|
@ -48,7 +48,7 @@ namespace Nz
|
||||||
NazaraAssert(m_geom, "Invalid geometry");
|
NazaraAssert(m_geom, "Invalid geometry");
|
||||||
|
|
||||||
m_handle = Create(m_mass, object.GetMomentOfInertia());
|
m_handle = Create(m_mass, object.GetMomentOfInertia());
|
||||||
SetGeom(object.GetGeom(), false);
|
SetGeom(object.GetGeom(), false, false);
|
||||||
|
|
||||||
CopyBodyData(object.GetHandle(), m_handle);
|
CopyBodyData(object.GetHandle(), m_handle);
|
||||||
|
|
||||||
|
|
@ -362,7 +362,7 @@ namespace Nz
|
||||||
cpShapeSetFriction(m_shapes[shapeIndex], cpFloat(friction));
|
cpShapeSetFriction(m_shapes[shapeIndex], cpFloat(friction));
|
||||||
}
|
}
|
||||||
|
|
||||||
void RigidBody2D::SetGeom(Collider2DRef geom, bool recomputeMoment)
|
void RigidBody2D::SetGeom(Collider2DRef geom, bool recomputeMoment, bool recomputeMassCenter)
|
||||||
{
|
{
|
||||||
// We have no public way of getting rid of an existing geom without removing the whole body
|
// We have no public way of getting rid of an existing geom without removing the whole body
|
||||||
// So let's save some attributes of the body, destroy it and rebuild it
|
// So let's save some attributes of the body, destroy it and rebuild it
|
||||||
|
|
@ -399,6 +399,9 @@ namespace Nz
|
||||||
if (!IsStatic() && !IsKinematic())
|
if (!IsStatic() && !IsKinematic())
|
||||||
cpBodySetMoment(m_handle, m_geom->ComputeMomentOfInertia(m_mass));
|
cpBodySetMoment(m_handle, m_geom->ComputeMomentOfInertia(m_mass));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (recomputeMassCenter)
|
||||||
|
SetMassCenter(m_geom->ComputeCenterOfMass());
|
||||||
}
|
}
|
||||||
|
|
||||||
void RigidBody2D::SetMass(float mass, bool recomputeMoment)
|
void RigidBody2D::SetMass(float mass, bool recomputeMoment)
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue