From 30348525d7b2fe0ae43a68f6f358d47c18a8b69c Mon Sep 17 00:00:00 2001 From: Lynix Date: Tue, 9 Oct 2018 23:22:28 +0200 Subject: [PATCH] Physics2D: Expose elasticity/friction/surface velocity --- .../NDK/Components/PhysicsComponent2D.hpp | 10 ++ .../NDK/Components/PhysicsComponent2D.inl | 150 +++++++++++++++++- include/Nazara/Physics2D/Collider2D.hpp | 13 +- include/Nazara/Physics2D/Collider2D.inl | 39 ++++- include/Nazara/Physics2D/RigidBody2D.hpp | 19 ++- include/Nazara/Physics2D/RigidBody2D.inl | 5 + src/Nazara/Physics2D/Collider2D.cpp | 5 +- src/Nazara/Physics2D/RigidBody2D.cpp | 67 +++++++- 8 files changed, 294 insertions(+), 14 deletions(-) diff --git a/SDK/include/NDK/Components/PhysicsComponent2D.hpp b/SDK/include/NDK/Components/PhysicsComponent2D.hpp index 79204fbdd..a652ceec6 100644 --- a/SDK/include/NDK/Components/PhysicsComponent2D.hpp +++ b/SDK/include/NDK/Components/PhysicsComponent2D.hpp @@ -41,22 +41,32 @@ namespace Ndk inline Nz::RadianAnglef GetAngularVelocity() const; NAZARA_DEPRECATED("Name error, please use GetMassCenter") inline Nz::Vector2f GetCenterOfGravity(Nz::CoordSys coordSys = Nz::CoordSys_Local) const; + inline float GetElasticity(std::size_t shapeIndex = 0) const; + inline float GetFriction(std::size_t shapeIndex = 0) const; inline float GetMass() const; inline Nz::Vector2f GetMassCenter(Nz::CoordSys coordSys = Nz::CoordSys_Local) const; inline float GetMomentOfInertia() const; inline Nz::Vector2f GetPosition() const; inline Nz::RadianAnglef GetRotation() const; + inline Nz::Vector2f GetSurfaceVelocity(std::size_t shapeIndex = 0) const; + inline std::size_t GetShapeCount() const; inline Nz::Vector2f GetVelocity() const; inline bool IsSleeping() const; inline void SetAngularDamping(float angularDamping); inline void SetAngularVelocity(const Nz::RadianAnglef& angularVelocity); + inline void SetElasticity(float elasticity); + inline void SetElasticity(std::size_t shapeIndex, float friction); + inline void SetFriction(float friction); + inline void SetFriction(std::size_t shapeIndex, float friction); inline void SetMass(float mass); inline void SetMassCenter(const Nz::Vector2f& center, Nz::CoordSys coordSys = Nz::CoordSys_Local); inline void SetMomentOfInertia(float moment); inline void SetPosition(const Nz::Vector2f& position); inline void SetRotation(const Nz::RadianAnglef& rotation); + inline void SetSurfaceVelocity(const Nz::Vector2f& velocity); + inline void SetSurfaceVelocity(std::size_t shapeIndex, const Nz::Vector2f& velocity); inline void SetVelocity(const Nz::Vector2f& velocity); static ComponentIndex componentIndex; diff --git a/SDK/include/NDK/Components/PhysicsComponent2D.inl b/SDK/include/NDK/Components/PhysicsComponent2D.inl index 075bd0ff3..8af4356f4 100644 --- a/SDK/include/NDK/Components/PhysicsComponent2D.inl +++ b/SDK/include/NDK/Components/PhysicsComponent2D.inl @@ -174,6 +174,36 @@ namespace Ndk return m_object->GetMassCenter(coordSys); } + /*! + * \brief Gets the elasticity of a shape belonging to this physics object + * \return Elasticity of the shape + * + * \param shapeIndex Shape index of the collider we're interested + * + * \remark Produces a NazaraAssert if the physics object is invalid + */ + inline float PhysicsComponent2D::GetElasticity(std::size_t shapeIndex) const + { + NazaraAssert(m_object, "Invalid physics object"); + + return m_object->GetElasticity(shapeIndex); + } + + /*! + * \brief Gets the friction of a shape belonging to this physics object + * \return Friction of the shape + * + * \param shapeIndex Shape index of the collider we're interested + * + * \remark Produces a NazaraAssert if the physics object is invalid + */ + inline float PhysicsComponent2D::GetFriction(std::size_t shapeIndex) const + { + NazaraAssert(m_object, "Invalid physics object"); + + return m_object->GetFriction(shapeIndex); + } + /*! * \brief Gets the mass of the physics object * \return Mass of the object @@ -246,6 +276,30 @@ namespace Ndk return m_object->GetRotation(); } + /*! + * \brief Gets the surface velocity of a shape belonging to this physics object + * \return Surface velocity of the shape + * + * \param shapeIndex Shape index of the collider we're interested + * + * \remark Produces a NazaraAssert if the physics object is invalid + */ + inline Nz::Vector2f PhysicsComponent2D::GetSurfaceVelocity(std::size_t shapeIndex) const +{ + return m_object->GetSurfaceVelocity(shapeIndex); + } + + /*! + * \brief Gets the rotation of the physics object + * \return Shape count of the object + * + * \remark Produces a NazaraAssert if the physics object is invalid + */ + inline std::size_t PhysicsComponent2D::GetShapeCount() const + { + return m_object->GetShapeCount(); + } + /*! * \brief Gets the velocity of the physics object * \return Velocity of the object @@ -305,6 +359,72 @@ namespace Ndk m_object->SetAngularVelocity(angularVelocity); } + /*! + * \brief Sets the elasticity of the whole physics object + * + * Overrides all shapes elasticity with a single value + * + * \param elasticity Elasticity to be applied + * + * \remark Elasticity must be positive or zero + */ + inline void PhysicsComponent2D::SetElasticity(float elasticity) + { + NazaraAssert(m_object, "Invalid physics object"); + NazaraAssert(elasticity >= 0.f, "Friction must be positive"); + + m_object->SetElasticity(elasticity); + } + + /*! + * \brief Sets the elasticity of a single shape of the physics object + * + * \param shapeIndex Target shape index + * \param elasticity Elasticity to be applied + * + * \remark Elasticity must be positive or zero + */ + inline void PhysicsComponent2D::SetElasticity(std::size_t shapeIndex, float elasticity) + { + NazaraAssert(m_object, "Invalid physics object"); + NazaraAssert(elasticity >= 0.f, "Friction must be positive"); + + m_object->SetElasticity(shapeIndex, elasticity); + } + + /*! + * \brief Sets the friction of the whole physics object + * + * Overrides all shapes friction with a single value + * + * \param friction Friction to be applied + * + * \remark Friction must be positive or zero + */ + inline void PhysicsComponent2D::SetFriction(float friction) + { + NazaraAssert(m_object, "Invalid physics object"); + NazaraAssert(friction >= 0.f, "Friction must be positive"); + + m_object->SetFriction(friction); + } + + /*! + * \brief Sets the friction of a single shape of the physics object + * + * \param shapeIndex Target shape index + * \param friction Friction to be applied + * + * \remark Friction must be positive or zero + */ + inline void PhysicsComponent2D::SetFriction(std::size_t shapeIndex, float friction) + { + NazaraAssert(m_object, "Invalid physics object"); + NazaraAssert(friction >= 0.f, "Friction must be positive"); + + m_object->SetFriction(shapeIndex, friction); + } + /*! * \brief Sets the mass of the physics object * @@ -378,14 +498,38 @@ namespace Ndk m_object->SetRotation(rotation); } + /*! + * \brief Sets the surface velocity of the whole physics object + * + * Overrides all shapes surface velocity with a single value + * + * \param velocity Surface velocity to be applied + */ + inline void PhysicsComponent2D::SetSurfaceVelocity(const Nz::Vector2f& velocity) + { + NazaraAssert(m_object, "Invalid physics object"); + + m_object->SetSurfaceVelocity(velocity); + } + + /*! + * \brief Sets the surface velocity of a single shape of the physics object + * + * \param shapeIndex Target shape index + * \param velocity Surface velocity to be applied + */ + inline void PhysicsComponent2D::SetSurfaceVelocity(std::size_t shapeIndex, const Nz::Vector2f& velocity) + { + NazaraAssert(m_object, "Invalid physics object"); + + m_object->SetSurfaceVelocity(shapeIndex, velocity); + } + /*! * \brief Sets the velocity of the physics object * * \param velocity Velocity of the object - * - * \remark Produces a NazaraAssert if the physics object is invalid */ - inline void PhysicsComponent2D::SetVelocity(const Nz::Vector2f& velocity) { NazaraAssert(m_object, "Invalid physics object"); diff --git a/include/Nazara/Physics2D/Collider2D.hpp b/include/Nazara/Physics2D/Collider2D.hpp index 36443e66a..8b69bd780 100644 --- a/include/Nazara/Physics2D/Collider2D.hpp +++ b/include/Nazara/Physics2D/Collider2D.hpp @@ -47,6 +47,9 @@ namespace Nz inline UInt32 GetCollisionGroup() const; inline unsigned int GetCollisionId() const; inline UInt32 GetCollisionMask() const; + inline float GetElasticity() const; + inline float GetFriction() const; + inline Vector2f GetSurfaceVelocity() const; virtual ColliderType2D GetType() const = 0; @@ -56,6 +59,9 @@ namespace Nz inline void SetCollisionGroup(UInt32 groupId); inline void SetCollisionId(unsigned int typeId); inline void SetCollisionMask(UInt32 mask); + inline void SetElasticity(float elasticity); + inline void SetFriction(float friction); + inline void SetSurfaceVelocity(const Vector2f& surfaceVelocity); inline void SetTrigger(bool trigger); Collider2D& operator=(const Collider2D&) = delete; @@ -67,11 +73,14 @@ namespace Nz protected: virtual std::size_t CreateShapes(RigidBody2D* body, std::vector* shapes) const = 0; - bool m_trigger; UInt32 m_categoryMask; UInt32 m_collisionGroup; - unsigned int m_collisionId; UInt32 m_collisionMask; + Vector2f m_surfaceVelocity; + bool m_trigger; + float m_elasticity; + float m_friction; + unsigned int m_collisionId; private: virtual std::size_t GenerateShapes(RigidBody2D* body, std::vector* shapes) const; diff --git a/include/Nazara/Physics2D/Collider2D.inl b/include/Nazara/Physics2D/Collider2D.inl index 71ae0603c..2142ba47e 100644 --- a/include/Nazara/Physics2D/Collider2D.inl +++ b/include/Nazara/Physics2D/Collider2D.inl @@ -9,11 +9,14 @@ namespace Nz { inline Collider2D::Collider2D() : - m_trigger(false), m_categoryMask(0xFFFFFFFF), m_collisionGroup(0), - m_collisionId(0), - m_collisionMask(0xFFFFFFFF) + m_collisionMask(0xFFFFFFFF), + m_trigger(false), + m_elasticity(0.f), + m_friction(0.f), + m_surfaceVelocity(Vector2f::Zero()), + m_collisionId(0) { } @@ -37,6 +40,21 @@ namespace Nz return m_collisionMask; } + inline float Collider2D::GetElasticity() const + { + return m_elasticity; + } + + inline float Collider2D::GetFriction() const + { + return m_friction; + } + + inline Vector2f Collider2D::GetSurfaceVelocity() const + { + return m_surfaceVelocity; + } + inline bool Collider2D::IsTrigger() const { return m_trigger; @@ -62,6 +80,21 @@ namespace Nz m_collisionMask = mask; } + inline void Collider2D::SetElasticity(float elasticity) + { + m_elasticity = elasticity; + } + + inline void Collider2D::SetFriction(float friction) + { + m_friction = friction; + } + + inline void Collider2D::SetSurfaceVelocity(const Vector2f& surfaceVelocity) + { + m_surfaceVelocity = surfaceVelocity; + } + inline void Collider2D::SetTrigger(bool trigger) { m_trigger = trigger; diff --git a/include/Nazara/Physics2D/RigidBody2D.hpp b/include/Nazara/Physics2D/RigidBody2D.hpp index ee5ff3cf0..b23b97187 100644 --- a/include/Nazara/Physics2D/RigidBody2D.hpp +++ b/include/Nazara/Physics2D/RigidBody2D.hpp @@ -10,6 +10,7 @@ #include #include #include +#include #include #include #include @@ -42,17 +43,21 @@ namespace Nz Rectf GetAABB() const; inline float GetAngularDamping() const; - float GetAngularVelocity() const; + RadianAnglef GetAngularVelocity() const; NAZARA_DEPRECATED("Name error, please use GetMassCenter") inline Vector2f GetCenterOfGravity(CoordSys coordSys = CoordSys_Local) const; + float GetElasticity(std::size_t shapeIndex = 0) const; + float GetFriction(std::size_t shapeIndex = 0) const; const Collider2DRef& GetGeom() const; cpBody* GetHandle() const; float GetMass() const; Vector2f GetMassCenter(CoordSys coordSys = CoordSys_Local) const; float GetMomentOfInertia() const; Vector2f GetPosition() const; - float GetRotation() const; + RadianAnglef GetRotation() const; + inline std::size_t GetShapeCount() const; std::size_t GetShapeIndex(cpShape* shape) const; + Vector2f GetSurfaceVelocity(std::size_t shapeIndex = 0) const; void* GetUserdata() const; Vector2f GetVelocity() const; PhysWorld2D* GetWorld() const; @@ -63,14 +68,19 @@ namespace Nz bool IsStatic() const; inline void SetAngularDamping(float angularDamping); - void SetAngularVelocity(float angularVelocity); + void SetAngularVelocity(const RadianAnglef& angularVelocity); + void SetElasticity(float elasticity); + void SetElasticity(std::size_t shapeIndex, float elasticity); + void SetFriction(float friction); void SetFriction(std::size_t shapeIndex, float friction); void SetGeom(Collider2DRef geom, bool recomputeMoment = true); void SetMass(float mass, bool recomputeMoment = true); void SetMassCenter(const Vector2f& center, CoordSys coordSys = CoordSys_Local); void SetMomentOfInertia(float moment); void SetPosition(const Vector2f& position); - void SetRotation(float rotation); + void SetRotation(const RadianAnglef& rotation); + void SetSurfaceVelocity(const Vector2f& surfaceVelocity); + void SetSurfaceVelocity(std::size_t shapeIndex, const Vector2f& surfaceVelocity); void SetStatic(bool setStaticBody = true); void SetUserdata(void* ud); void SetVelocity(const Vector2f& velocity); @@ -90,6 +100,7 @@ namespace Nz void UnregisterFromSpace(); static void CopyBodyData(cpBody* from, cpBody* to); + static void CopyShapeData(cpShape* from, cpShape* to); std::vector m_shapes; Collider2DRef m_geom; diff --git a/include/Nazara/Physics2D/RigidBody2D.inl b/include/Nazara/Physics2D/RigidBody2D.inl index faebd017d..a654c03e7 100644 --- a/include/Nazara/Physics2D/RigidBody2D.inl +++ b/include/Nazara/Physics2D/RigidBody2D.inl @@ -17,6 +17,11 @@ namespace Nz return GetMassCenter(coordSys); } + inline std::size_t RigidBody2D::GetShapeCount() const + { + return m_shapes.size(); + } + inline void RigidBody2D::SetAngularDamping(float angularDamping) { SetMomentOfInertia(angularDamping); diff --git a/src/Nazara/Physics2D/Collider2D.cpp b/src/Nazara/Physics2D/Collider2D.cpp index 5f0e9bcfe..0be746838 100644 --- a/src/Nazara/Physics2D/Collider2D.cpp +++ b/src/Nazara/Physics2D/Collider2D.cpp @@ -20,9 +20,12 @@ namespace Nz { cpShape* shape = (*shapes)[i]; + cpShapeSetCollisionType(shape, cpFloat(m_collisionId)); + cpShapeSetElasticity(shape, cpFloat(m_elasticity)); cpShapeSetFilter(shape, filter); - cpShapeSetCollisionType(shape, m_collisionId); + cpShapeSetFriction(shape, cpFloat(m_friction)); cpShapeSetSensor(shape, (m_trigger) ? cpTrue : cpFalse); + cpShapeSetSurfaceVelocity(shape, cpv(cpFloat(m_surfaceVelocity.x), cpFloat(m_surfaceVelocity.y))); } return shapeCount; diff --git a/src/Nazara/Physics2D/RigidBody2D.cpp b/src/Nazara/Physics2D/RigidBody2D.cpp index 16e737e30..99013467e 100644 --- a/src/Nazara/Physics2D/RigidBody2D.cpp +++ b/src/Nazara/Physics2D/RigidBody2D.cpp @@ -52,7 +52,10 @@ namespace Nz CopyBodyData(object.GetHandle(), m_handle); for (std::size_t i = 0; i < m_shapes.size(); ++i) + { + CopyShapeData(object.m_shapes[i], m_shapes[i]); m_shapes[i]->bb = cpShapeCacheBB(object.m_shapes[i]); + } } RigidBody2D::RigidBody2D(RigidBody2D&& object) : @@ -186,8 +189,20 @@ namespace Nz } RadianAnglef RigidBody2D::GetAngularVelocity() const - return float(cpBodyGetAngularVelocity(m_handle)); { + return float(cpBodyGetAngularVelocity(m_handle)); + } + + float Nz::RigidBody2D::GetElasticity(std::size_t shapeIndex) const + { + assert(shapeIndex < m_shapes.size()); + return float(cpShapeGetElasticity(m_shapes[shapeIndex])); + } + + float Nz::RigidBody2D::GetFriction(std::size_t shapeIndex) const + { + assert(shapeIndex < m_shapes.size()); + return float(cpShapeGetFriction(m_shapes[shapeIndex])); } const Collider2DRef& RigidBody2D::GetGeom() const @@ -247,6 +262,13 @@ namespace Nz return std::distance(m_shapes.begin(), it); } + Vector2f Nz::RigidBody2D::GetSurfaceVelocity(std::size_t shapeIndex) const + { + assert(shapeIndex < m_shapes.size()); + cpVect vel = cpShapeGetSurfaceVelocity(m_shapes[shapeIndex]); + return Vector2f(static_cast(vel.x), static_cast(vel.y)); + } + void* RigidBody2D::GetUserdata() const { return m_userData; @@ -286,8 +308,32 @@ namespace Nz void RigidBody2D::SetAngularVelocity(const RadianAnglef& angularVelocity) { cpBodySetAngularVelocity(m_handle, angularVelocity.angle); + } + + void RigidBody2D::SetElasticity(float friction) + { + cpFloat frict(friction); + for (cpShape* shape : m_shapes) + cpShapeSetElasticity(shape, frict); + } + + void RigidBody2D::SetElasticity(std::size_t shapeIndex, float friction) { assert(shapeIndex < m_shapes.size()); + cpShapeSetElasticity(m_shapes[shapeIndex], cpFloat(friction)); + } + + void RigidBody2D::SetFriction(float friction) + { + cpFloat frict(friction); + for (cpShape* shape : m_shapes) + cpShapeSetFriction(shape, frict); + } + + void RigidBody2D::SetFriction(std::size_t shapeIndex, float friction) + { + assert(shapeIndex < m_shapes.size()); + cpShapeSetFriction(m_shapes[shapeIndex], cpFloat(friction)); } void RigidBody2D::SetGeom(Collider2DRef geom, bool recomputeMoment) @@ -414,6 +460,19 @@ namespace Nz } } + void RigidBody2D::SetSurfaceVelocity(const Vector2f& surfaceVelocity) + { + Vector2 velocity(surfaceVelocity.x, surfaceVelocity.y); + for (cpShape* shape : m_shapes) + cpShapeSetSurfaceVelocity(shape, cpv(velocity.x, velocity.y)); + } + + void RigidBody2D::SetSurfaceVelocity(std::size_t shapeIndex, const Vector2f& surfaceVelocity) + { + assert(shapeIndex < m_shapes.size()); + cpShapeSetSurfaceVelocity(m_shapes[shapeIndex], cpv(cpFloat(surfaceVelocity.x), cpFloat(surfaceVelocity.y))); + } + void RigidBody2D::SetStatic(bool setStaticBody) { m_isStatic = setStaticBody; @@ -549,4 +608,10 @@ namespace Nz cpBodySetVelocity(to, cpBodyGetVelocity(from)); } + void RigidBody2D::CopyShapeData(cpShape* from, cpShape* to) + { + cpShapeSetElasticity(to, cpShapeGetElasticity(from)); + cpShapeSetFriction(to, cpShapeGetFriction(from)); + cpShapeSetSurfaceVelocity(to, cpShapeGetSurfaceVelocity(from)); + } }