Physics2D/RigidBody2D: Add possibility to setup a custom velocity function

This commit is contained in:
Lynix 2019-01-19 02:31:29 +01:00
parent 40cd8a7987
commit 662ccbd5d0
5 changed files with 113 additions and 1 deletions

View File

@ -159,6 +159,7 @@ Nazara Engine:
- Fixed LuaCoroutine movement assignation operator - Fixed LuaCoroutine movement assignation operator
- Added Arbiter2D::GetBodies - Added Arbiter2D::GetBodies
- Added RigidBody2D::ForEachArbiter - Added RigidBody2D::ForEachArbiter
- Added possibility to change the RigidBody2D velocity function called by the physics engine
Nazara Development Kit: Nazara Development Kit:
- Added ImageWidget (#139) - Added ImageWidget (#139)

View File

@ -24,6 +24,8 @@ namespace Ndk
friend class ConstraintComponent2D; friend class ConstraintComponent2D;
public: public:
using VelocityFunc = Nz::RigidBody2D::VelocityFunc;
PhysicsComponent2D(); PhysicsComponent2D();
PhysicsComponent2D(const PhysicsComponent2D& physics); PhysicsComponent2D(const PhysicsComponent2D& physics);
~PhysicsComponent2D() = default; ~PhysicsComponent2D() = default;
@ -55,10 +57,13 @@ namespace Ndk
inline Nz::Vector2f GetSurfaceVelocity(std::size_t shapeIndex = 0) const; inline Nz::Vector2f GetSurfaceVelocity(std::size_t shapeIndex = 0) const;
inline std::size_t GetShapeCount() const; inline std::size_t GetShapeCount() const;
inline Nz::Vector2f GetVelocity() const; inline Nz::Vector2f GetVelocity() const;
const VelocityFunc& GetVelocityFunction() const;
inline bool IsNodeSynchronizationEnabled() const; inline bool IsNodeSynchronizationEnabled() const;
inline bool IsSleeping() const; inline bool IsSleeping() const;
inline void ResetVelocityFunction();
inline void SetAngularDamping(float angularDamping); inline void SetAngularDamping(float angularDamping);
inline void SetAngularVelocity(const Nz::RadianAnglef& angularVelocity); inline void SetAngularVelocity(const Nz::RadianAnglef& angularVelocity);
inline void SetElasticity(float elasticity); inline void SetElasticity(float elasticity);
@ -73,6 +78,9 @@ namespace Ndk
inline void SetSurfaceVelocity(const Nz::Vector2f& velocity); inline void SetSurfaceVelocity(const Nz::Vector2f& velocity);
inline void SetSurfaceVelocity(std::size_t shapeIndex, const Nz::Vector2f& velocity); inline void SetSurfaceVelocity(std::size_t shapeIndex, const Nz::Vector2f& velocity);
inline void SetVelocity(const Nz::Vector2f& velocity); inline void SetVelocity(const Nz::Vector2f& velocity);
inline void SetVelocityFunction(VelocityFunc velocityFunc);
inline void UpdateVelocity(const Nz::Vector2f& gravity, float damping, float deltaTime);
static ComponentIndex componentIndex; static ComponentIndex componentIndex;

View File

@ -338,7 +338,6 @@ namespace Ndk
* *
* \remark Produces a NazaraAssert if the physics object is invalid * \remark Produces a NazaraAssert if the physics object is invalid
*/ */
inline Nz::Vector2f PhysicsComponent2D::GetVelocity() const inline Nz::Vector2f PhysicsComponent2D::GetVelocity() const
{ {
NazaraAssert(m_object, "Invalid physics object"); NazaraAssert(m_object, "Invalid physics object");
@ -346,6 +345,19 @@ namespace Ndk
return m_object->GetVelocity(); return m_object->GetVelocity();
} }
/*!
* \brief Gets the custom velocity function of the physics object
* \return Velocity function of the object (may be empty if default function is used)
*
* \remark Produces a NazaraAssert if the physics object is invalid
*/
inline auto PhysicsComponent2D::GetVelocityFunction() const -> const VelocityFunc&
{
NazaraAssert(m_object, "Invalid physics object");
return m_object->GetVelocityFunction();
}
/*! /*!
* \brief Checks if position & rotation are synchronized with NodeComponent * \brief Checks if position & rotation are synchronized with NodeComponent
* \return true If synchronization is enabled * \return true If synchronization is enabled
@ -370,6 +382,18 @@ namespace Ndk
return m_object->IsSleeping(); return m_object->IsSleeping();
} }
/*!
* \brief Reset velocity function to default one
*
* \remark Produces a NazaraAssert if the physics object is invalid
*/
inline void PhysicsComponent2D::ResetVelocityFunction()
{
NazaraAssert(m_object, "Invalid physics object");
return m_object->ResetVelocityFunction();
}
/*! /*!
* \brief Sets the angular damping or moment of inertia of the physics object * \brief Sets the angular damping or moment of inertia of the physics object
* *
@ -580,6 +604,39 @@ namespace Ndk
m_object->SetVelocity(velocity); m_object->SetVelocity(velocity);
} }
/*!
* \brief Sets a custom velocity function for the physics object
*
* A velocity function is called (for non-kinematic and non-static objects) at every physics update to compute the new velocity of the object.
* You may call UpdateVelocity (the default velocity function) to let the physics engine compute that itself and then adjust it using GetVelocity/SetVelocity as you need.
*
* \param velocityFunc New custom velocity function
*
* \remark Passing an empty VelocityFunc has the same effect as calling ResetVelocityFunction
* \see ResetVelocityFunction
* \see UpdateVelocity
*/
inline void PhysicsComponent2D::SetVelocityFunction(VelocityFunc velocityFunc)
{
NazaraAssert(m_object, "Invalid physics object");
m_object->SetVelocityFunction(std::move(velocityFunc));
}
/*!
* \brief Calls the physics engine default velocity function
*
* \param gravity Physics system gravity
* \param damping Physics system damping (adjusted to deltaTime)
* \param deltaTime Elapsed time since last physics update
*/
inline void PhysicsComponent2D::UpdateVelocity(const Nz::Vector2f& gravity, float damping, float deltaTime)
{
NazaraAssert(m_object, "Invalid physics object");
m_object->UpdateVelocity(gravity, damping, deltaTime);
}
/*! /*!
* \brief Gets the underlying physics object * \brief Gets the underlying physics object
* \return A reference to the physics object * \return A reference to the physics object

View File

@ -14,17 +14,21 @@
#include <Nazara/Math/Rect.hpp> #include <Nazara/Math/Rect.hpp>
#include <Nazara/Physics2D/Config.hpp> #include <Nazara/Physics2D/Config.hpp>
#include <Nazara/Physics2D/Collider2D.hpp> #include <Nazara/Physics2D/Collider2D.hpp>
#include <functional>
#include <limits> #include <limits>
struct cpBody; struct cpBody;
namespace Nz namespace Nz
{ {
class Arbiter2D;
class PhysWorld2D; class PhysWorld2D;
class NAZARA_PHYSICS2D_API RigidBody2D class NAZARA_PHYSICS2D_API RigidBody2D
{ {
public: public:
using VelocityFunc = std::function<void(RigidBody2D& body2D, const Nz::Vector2f& gravity, float damping, float deltaTime)>;
RigidBody2D(PhysWorld2D* world, float mass); RigidBody2D(PhysWorld2D* world, float mass);
RigidBody2D(PhysWorld2D* world, float mass, Collider2DRef geom); RigidBody2D(PhysWorld2D* world, float mass, Collider2DRef geom);
RigidBody2D(const RigidBody2D& object); RigidBody2D(const RigidBody2D& object);
@ -62,6 +66,7 @@ namespace Nz
Vector2f GetSurfaceVelocity(std::size_t shapeIndex = 0) const; Vector2f GetSurfaceVelocity(std::size_t shapeIndex = 0) const;
void* GetUserdata() const; void* GetUserdata() const;
Vector2f GetVelocity() const; Vector2f GetVelocity() const;
const VelocityFunc& GetVelocityFunction() const;
PhysWorld2D* GetWorld() const; PhysWorld2D* GetWorld() const;
bool IsKinematic() const; bool IsKinematic() const;
@ -69,6 +74,8 @@ namespace Nz
bool IsSleeping() const; bool IsSleeping() const;
bool IsStatic() const; bool IsStatic() const;
void ResetVelocityFunction();
inline void SetAngularDamping(float angularDamping); inline void SetAngularDamping(float angularDamping);
void SetAngularVelocity(const RadianAnglef& angularVelocity); void SetAngularVelocity(const RadianAnglef& angularVelocity);
void SetElasticity(float elasticity); void SetElasticity(float elasticity);
@ -86,6 +93,9 @@ namespace Nz
void SetStatic(bool setStaticBody = true); void SetStatic(bool setStaticBody = true);
void SetUserdata(void* ud); void SetUserdata(void* ud);
void SetVelocity(const Vector2f& velocity); void SetVelocity(const Vector2f& velocity);
void SetVelocityFunction(VelocityFunc velocityFunc);
void UpdateVelocity(const Nz::Vector2f& gravity, float damping, float deltaTime);
RigidBody2D& operator=(const RigidBody2D& object); RigidBody2D& operator=(const RigidBody2D& object);
RigidBody2D& operator=(RigidBody2D&& object); RigidBody2D& operator=(RigidBody2D&& object);
@ -104,6 +114,7 @@ namespace Nz
static void CopyBodyData(cpBody* from, cpBody* to); static void CopyBodyData(cpBody* from, cpBody* to);
static void CopyShapeData(cpShape* from, cpShape* to); static void CopyShapeData(cpShape* from, cpShape* to);
VelocityFunc m_velocityFunc;
std::vector<cpShape*> m_shapes; std::vector<cpShape*> m_shapes;
Collider2DRef m_geom; Collider2DRef m_geom;
cpBody* m_handle; cpBody* m_handle;

View File

@ -296,6 +296,11 @@ namespace Nz
return Vector2f(static_cast<float>(vel.x), static_cast<float>(vel.y)); return Vector2f(static_cast<float>(vel.x), static_cast<float>(vel.y));
} }
const RigidBody2D::VelocityFunc& RigidBody2D::GetVelocityFunction() const
{
return m_velocityFunc;
}
PhysWorld2D* RigidBody2D::GetWorld() const PhysWorld2D* RigidBody2D::GetWorld() const
{ {
return m_world; return m_world;
@ -321,6 +326,11 @@ namespace Nz
return m_isStatic; return m_isStatic;
} }
void RigidBody2D::ResetVelocityFunction()
{
m_handle->velocity_func = cpBodyUpdateVelocity;
}
void RigidBody2D::SetAngularVelocity(const RadianAnglef& angularVelocity) void RigidBody2D::SetAngularVelocity(const RadianAnglef& angularVelocity)
{ {
cpBodySetAngularVelocity(m_handle, angularVelocity.value); cpBodySetAngularVelocity(m_handle, angularVelocity.value);
@ -516,6 +526,30 @@ namespace Nz
cpBodySetVelocity(m_handle, cpv(velocity.x, velocity.y)); cpBodySetVelocity(m_handle, cpv(velocity.x, velocity.y));
} }
void RigidBody2D::SetVelocityFunction(VelocityFunc velocityFunc)
{
m_velocityFunc = std::move(velocityFunc);
if (m_velocityFunc)
{
m_handle->velocity_func = [](cpBody* body, cpVect gravity, cpFloat damping, cpFloat dt)
{
RigidBody2D* rigidBody = static_cast<RigidBody2D*>(cpBodyGetUserData(body));
const auto& callback = rigidBody->GetVelocityFunction();
assert(callback);
callback(*rigidBody, Nz::Vector2f(float(gravity.x), float(gravity.y)), float(damping), float(dt));
};
}
else
m_handle->velocity_func = cpBodyUpdateVelocity;
}
void RigidBody2D::UpdateVelocity(const Nz::Vector2f & gravity, float damping, float deltaTime)
{
cpBodyUpdateVelocity(m_handle, cpv(gravity.x, gravity.y), damping, deltaTime);
}
RigidBody2D& RigidBody2D::operator=(const RigidBody2D& object) RigidBody2D& RigidBody2D::operator=(const RigidBody2D& object)
{ {
RigidBody2D physObj(object); RigidBody2D physObj(object);
@ -538,6 +572,7 @@ namespace Nz
m_mass = object.m_mass; m_mass = object.m_mass;
m_shapes = std::move(object.m_shapes); m_shapes = std::move(object.m_shapes);
m_userData = object.m_userData; m_userData = object.m_userData;
m_velocityFunc = std::move(object.m_velocityFunc);
m_world = object.m_world; m_world = object.m_world;
cpBodySetUserData(m_handle, this); cpBodySetUserData(m_handle, this);