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
- Added Arbiter2D::GetBodies
- Added RigidBody2D::ForEachArbiter
- Added possibility to change the RigidBody2D velocity function called by the physics engine
Nazara Development Kit:
- Added ImageWidget (#139)

View File

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

View File

@ -338,7 +338,6 @@ namespace Ndk
*
* \remark Produces a NazaraAssert if the physics object is invalid
*/
inline Nz::Vector2f PhysicsComponent2D::GetVelocity() const
{
NazaraAssert(m_object, "Invalid physics object");
@ -346,6 +345,19 @@ namespace Ndk
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
* \return true If synchronization is enabled
@ -370,6 +382,18 @@ namespace Ndk
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
*
@ -580,6 +604,39 @@ namespace Ndk
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
* \return A reference to the physics object

View File

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

View File

@ -296,6 +296,11 @@ namespace Nz
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
{
return m_world;
@ -321,6 +326,11 @@ namespace Nz
return m_isStatic;
}
void RigidBody2D::ResetVelocityFunction()
{
m_handle->velocity_func = cpBodyUpdateVelocity;
}
void RigidBody2D::SetAngularVelocity(const RadianAnglef& angularVelocity)
{
cpBodySetAngularVelocity(m_handle, angularVelocity.value);
@ -516,6 +526,30 @@ namespace Nz
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 physObj(object);
@ -538,6 +572,7 @@ namespace Nz
m_mass = object.m_mass;
m_shapes = std::move(object.m_shapes);
m_userData = object.m_userData;
m_velocityFunc = std::move(object.m_velocityFunc);
m_world = object.m_world;
cpBodySetUserData(m_handle, this);