Physics2D/RigidBody: Add position offset

This commit is contained in:
Lynix 2019-03-26 18:59:18 +01:00
parent ffc58e9806
commit 3beeeebc1d
6 changed files with 86 additions and 29 deletions

View File

@ -28,10 +28,14 @@ namespace Ndk
CollisionComponent2D(const CollisionComponent2D& collision);
~CollisionComponent2D() = default;
void Align(const Nz::Rectf& aabb);
Nz::Rectf GetAABB() const;
const Nz::Collider2DRef& GetGeom() const;
const Nz::Vector2f& GetGeomOffset() const;
void SetGeom(Nz::Collider2DRef geom);
void SetGeomOffset(const Nz::Vector2f& geomOffset);
CollisionComponent2D& operator=(Nz::Collider2DRef geom);
CollisionComponent2D& operator=(CollisionComponent2D&& collision) = default;
@ -40,6 +44,8 @@ namespace Ndk
private:
void InitializeStaticBody();
Nz::RigidBody2D* GetRigidBody();
const Nz::RigidBody2D* GetRigidBody() const;
Nz::RigidBody2D* GetStaticBody();
void OnAttached() override;

View File

@ -28,16 +28,6 @@ namespace Ndk
{
}
/*!
* \brief Gets the collision box representing the entity
* \return The physics collision box
*/
inline Nz::Rectf CollisionComponent2D::GetAABB() const
{
return m_staticBody->GetAABB();
}
/*!
* \brief Gets the geometry representing the entity
* \return A constant reference to the physics geometry

View File

@ -17,28 +17,41 @@ namespace Ndk
* \brief NDK class that represents a two-dimensional collision geometry
*/
void CollisionComponent2D::Align(const Nz::Rectf& aabb)
{
const Nz::RigidBody2D* rigidBody = GetRigidBody();
SetGeomOffset(aabb.GetCenter() - rigidBody->GetAABB().GetCenter() + rigidBody->GetPositionOffset());
}
/*!
* \brief Gets the collision box representing the entity
* \return The physics collision box
*/
Nz::Rectf CollisionComponent2D::GetAABB() const
{
return GetRigidBody()->GetAABB();
}
const Nz::Vector2f& CollisionComponent2D::GetGeomOffset() const
{
return GetRigidBody()->GetPositionOffset();
}
/*!
* \brief Sets geometry for the entity
*
* \param geom Geometry used for collisions
*
* \remark Produces a NazaraAssert if the entity has no physics component and has no static body
*/
void CollisionComponent2D::SetGeom(Nz::Collider2DRef geom)
{
m_geom = std::move(geom);
if (m_entity->HasComponent<PhysicsComponent2D>())
{
// We update the geometry of the PhysiscsObject linked to the PhysicsComponent2D
PhysicsComponent2D& physComponent = m_entity->GetComponent<PhysicsComponent2D>();
physComponent.GetRigidBody()->SetGeom(m_geom);
}
else
{
NazaraAssert(m_staticBody, "An entity without physics component should have a static body");
m_staticBody->SetGeom(m_geom);
}
GetRigidBody()->SetGeom(m_geom);
}
void CollisionComponent2D::SetGeomOffset(const Nz::Vector2f& geomOffset)
{
GetRigidBody()->SetPositionOffset(geomOffset);
}
/*!
@ -47,7 +60,6 @@ namespace Ndk
* \remark Produces a NazaraAssert if entity is invalid
* \remark Produces a NazaraAssert if entity is not linked to a world, or the world has no physics system
*/
void CollisionComponent2D::InitializeStaticBody()
{
NazaraAssert(m_entity, "Invalid entity");
@ -67,7 +79,34 @@ namespace Ndk
matrix.MakeIdentity();
m_staticBody->SetPosition(Nz::Vector2f(matrix.GetTranslation()));
}
Nz::RigidBody2D* CollisionComponent2D::GetRigidBody()
{
if (m_entity->HasComponent<PhysicsComponent2D>())
{
PhysicsComponent2D& physComponent = m_entity->GetComponent<PhysicsComponent2D>();
return physComponent.GetRigidBody();
}
else
{
NazaraAssert(m_staticBody, "An entity without physics component should have a static body");
return m_staticBody.get();
}
}
const Nz::RigidBody2D* CollisionComponent2D::GetRigidBody() const
{
if (m_entity->HasComponent<PhysicsComponent2D>())
{
PhysicsComponent2D& physComponent = m_entity->GetComponent<PhysicsComponent2D>();
return physComponent.GetRigidBody();
}
else
{
NazaraAssert(m_staticBody, "An entity without physics component should have a static body");
return m_staticBody.get();
}
}
/*!

View File

@ -32,7 +32,7 @@ namespace Nz
RigidBody2D(PhysWorld2D* world, float mass);
RigidBody2D(PhysWorld2D* world, float mass, Collider2DRef geom);
RigidBody2D(const RigidBody2D& object);
RigidBody2D(RigidBody2D&& object);
RigidBody2D(RigidBody2D&& object) noexcept;
~RigidBody2D();
void AddForce(const Vector2f& force, CoordSys coordSys = CoordSys_Global);
@ -60,6 +60,7 @@ namespace Nz
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;
@ -87,6 +88,7 @@ namespace Nz
void SetMassCenter(const Vector2f& center, CoordSys coordSys = CoordSys_Local);
void SetMomentOfInertia(float moment);
void SetPosition(const Vector2f& position);
void SetPositionOffset(const Vector2f& offset);
void SetRotation(const RadianAnglef& rotation);
void SetSurfaceVelocity(const Vector2f& surfaceVelocity);
void SetSurfaceVelocity(std::size_t shapeIndex, const Vector2f& surfaceVelocity);
@ -114,6 +116,7 @@ namespace Nz
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;
Collider2DRef m_geom;

View File

@ -17,6 +17,11 @@ namespace Nz
return GetMassCenter(coordSys);
}
inline const Vector2f& RigidBody2D::GetPositionOffset() const
{
return m_positionOffset;
}
inline std::size_t RigidBody2D::GetShapeCount() const
{
return m_shapes.size();

View File

@ -19,6 +19,7 @@ namespace Nz
}
RigidBody2D::RigidBody2D(PhysWorld2D* world, float mass, Collider2DRef geom) :
m_positionOffset(Vector2f::Zero()),
m_geom(),
m_userData(nullptr),
m_world(world),
@ -35,6 +36,7 @@ namespace Nz
}
RigidBody2D::RigidBody2D(const RigidBody2D& object) :
m_positionOffset(object.m_positionOffset),
m_geom(object.m_geom),
m_userData(object.m_userData),
m_world(object.m_world),
@ -59,9 +61,10 @@ namespace Nz
}
}
RigidBody2D::RigidBody2D(RigidBody2D&& object) :
RigidBody2D::RigidBody2D(RigidBody2D&& object) noexcept :
OnRigidBody2DMove(std::move(object.OnRigidBody2DMove)),
OnRigidBody2DRelease(std::move(object.OnRigidBody2DRelease)),
m_positionOffset(std::move(object.m_positionOffset)),
m_shapes(std::move(object.m_shapes)),
m_geom(std::move(object.m_geom)),
m_handle(object.m_handle),
@ -260,7 +263,7 @@ namespace Nz
Vector2f RigidBody2D::GetPosition() const
{
cpVect pos = cpBodyGetPosition(m_handle);
cpVect pos = cpBodyLocalToWorld(m_handle, cpv(-m_positionOffset.x, -m_positionOffset.y));
return Vector2f(static_cast<float>(pos.x), static_cast<float>(pos.y));
}
@ -467,7 +470,9 @@ namespace Nz
void RigidBody2D::SetPosition(const Vector2f& position)
{
cpBodySetPosition(m_handle, cpv(position.x, position.y));
cpVect oldPosition = cpBodyGetPosition(m_handle);
cpBodySetPosition(m_handle, cpBodyLocalToWorld(m_handle, cpv(position.x - oldPosition.x + m_positionOffset.x, position.y - oldPosition.y + m_positionOffset.y)));
if (m_isStatic)
{
m_world->RegisterPostStep(this, [](Nz::RigidBody2D* body)
@ -477,6 +482,13 @@ namespace Nz
}
}
void RigidBody2D::SetPositionOffset(const Vector2f& offset)
{
Nz::Vector2f position = GetPosition();
m_positionOffset = offset;
SetPosition(position);
}
void RigidBody2D::SetRotation(const RadianAnglef& rotation)
{
cpBodySetAngle(m_handle, rotation.value);
@ -573,6 +585,7 @@ namespace Nz
m_geom = std::move(object.m_geom);
m_gravityFactor = object.m_gravityFactor;
m_mass = object.m_mass;
m_positionOffset = object.m_positionOffset;
m_shapes = std::move(object.m_shapes);
m_userData = object.m_userData;
m_velocityFunc = std::move(object.m_velocityFunc);
@ -653,9 +666,10 @@ namespace Nz
void RigidBody2D::CopyBodyData(cpBody* from, cpBody* to)
{
cpBodySetCenterOfGravity(to, cpBodyGetCenterOfGravity(from));
cpBodySetAngle(to, cpBodyGetAngle(from));
cpBodySetAngularVelocity(to, cpBodyGetAngularVelocity(from));
cpBodySetCenterOfGravity(to, cpBodyGetCenterOfGravity(from));
cpBodySetForce(to, cpBodyGetForce(from));
cpBodySetPosition(to, cpBodyGetPosition(from));
cpBodySetTorque(to, cpBodyGetTorque(from));