Physics2D: Add DebugDraw method
This commit is contained in:
parent
b14a9f219a
commit
101783126c
|
|
@ -8,6 +8,7 @@
|
|||
#define NAZARA_PHYSWORLD2D_HPP
|
||||
|
||||
#include <Nazara/Prerequesites.hpp>
|
||||
#include <Nazara/Core/Color.hpp>
|
||||
#include <Nazara/Core/Signal.hpp>
|
||||
#include <Nazara/Math/Vector2.hpp>
|
||||
#include <Nazara/Physics2D/Config.hpp>
|
||||
|
|
@ -30,8 +31,16 @@ namespace Nz
|
|||
using ContactPostSolveCallback = std::function<void(PhysWorld2D& world, RigidBody2D& bodyA, RigidBody2D& bodyB, void* userdata)>;
|
||||
using ContactStartCallback = std::function<bool(PhysWorld2D& world, RigidBody2D& bodyA, RigidBody2D& bodyB, void* userdata)>;
|
||||
|
||||
using DebugDrawCircleCallback = std::function<void(const Vector2f& origin, float rotation, float radius, Color outlineColor, Color fillColor, void* userdata)>;
|
||||
using DebugDrawDotCallback = std::function<void(const Vector2f& origin, float radius, Color color, void* userdata)>;
|
||||
using DebugDrawPolygonCallback = std::function<void(const Vector2f* vertices, std::size_t vertexCount, float radius, Color outlineColor, Color fillColor, void* userdata)>;
|
||||
using DebugDrawSegmentCallback = std::function<void(const Vector2f& first, const Vector2f& second, Color color, void* userdata)>;
|
||||
using DebugDrawTickSegmentCallback = std::function<void(const Vector2f& first, const Vector2f& second, float thickness, Color outlineColor, Color fillColor, void* userdata)>;
|
||||
using DebugDrawGetColorCallback = std::function<Color(RigidBody2D& body, std::size_t shapeIndex, void* userdata)>;
|
||||
|
||||
public:
|
||||
struct Callback;
|
||||
struct DebugDrawOptions;
|
||||
struct NearestQueryResult;
|
||||
struct RaycastHit;
|
||||
|
||||
|
|
@ -40,6 +49,8 @@ namespace Nz
|
|||
PhysWorld2D(PhysWorld2D&&) = delete; ///TODO
|
||||
~PhysWorld2D();
|
||||
|
||||
void DebugDraw(const DebugDrawOptions& options, bool drawShapes = true, bool drawConstraints = true, bool drawCollisions = true);
|
||||
|
||||
float GetDamping() const;
|
||||
Vector2f GetGravity() const;
|
||||
cpSpace* GetHandle() const;
|
||||
|
|
@ -74,6 +85,22 @@ namespace Nz
|
|||
void* userdata;
|
||||
};
|
||||
|
||||
struct DebugDrawOptions
|
||||
{
|
||||
Color constraintColor;
|
||||
Color collisionPointColor;
|
||||
Color shapeOutlineColor;
|
||||
|
||||
DebugDrawCircleCallback circleCallback;
|
||||
DebugDrawGetColorCallback colorCallback;
|
||||
DebugDrawDotCallback dotCallback;
|
||||
DebugDrawPolygonCallback polygonCallback;
|
||||
DebugDrawSegmentCallback segmentCallback;
|
||||
DebugDrawTickSegmentCallback thickSegmentCallback;
|
||||
|
||||
void* userdata;
|
||||
};
|
||||
|
||||
struct NearestQueryResult
|
||||
{
|
||||
Nz::RigidBody2D* nearestBody;
|
||||
|
|
|
|||
|
|
@ -13,6 +13,7 @@
|
|||
#include <Nazara/Math/Rect.hpp>
|
||||
#include <Nazara/Physics2D/Config.hpp>
|
||||
#include <Nazara/Physics2D/Collider2D.hpp>
|
||||
#include <limits>
|
||||
|
||||
struct cpBody;
|
||||
|
||||
|
|
@ -44,6 +45,7 @@ namespace Nz
|
|||
float GetMomentOfInertia() const;
|
||||
Vector2f GetPosition() const;
|
||||
float GetRotation() const;
|
||||
std::size_t GetShapeIndex(cpShape* shape) const;
|
||||
void* GetUserdata() const;
|
||||
Vector2f GetVelocity() const;
|
||||
PhysWorld2D* GetWorld() const;
|
||||
|
|
@ -67,6 +69,8 @@ namespace Nz
|
|||
NazaraSignal(OnRigidBody2DMove, RigidBody2D* /*oldPointer*/, RigidBody2D* /*newPointer*/);
|
||||
NazaraSignal(OnRigidBody2DRelease, RigidBody2D* /*rigidBody*/);
|
||||
|
||||
static constexpr std::size_t InvalidShapeIndex = std::numeric_limits<std::size_t>::max();
|
||||
|
||||
private:
|
||||
void CopyBodyData(cpBody* body);
|
||||
cpBody* Create(float mass = 1.f, float moment = 1.f);
|
||||
|
|
|
|||
|
|
@ -3,11 +3,83 @@
|
|||
// For conditions of distribution and use, see copyright notice in Config.hpp
|
||||
|
||||
#include <Nazara/Physics2D/PhysWorld2D.hpp>
|
||||
#include <Nazara/Core/MemoryHelper.hpp>
|
||||
#include <chipmunk/chipmunk.h>
|
||||
#include <Nazara/Physics2D/Debug.hpp>
|
||||
|
||||
namespace Nz
|
||||
{
|
||||
namespace
|
||||
{
|
||||
Color CpDebugColorToColor(cpSpaceDebugColor c)
|
||||
{
|
||||
return Color{ static_cast<Nz::UInt8>(c.r * 255.f), static_cast<Nz::UInt8>(c.g * 255.f), static_cast<Nz::UInt8>(c.b * 255.f), static_cast<Nz::UInt8>(c.a * 255.f) };
|
||||
}
|
||||
|
||||
cpSpaceDebugColor ColorToCpDebugColor(Color c)
|
||||
{
|
||||
return cpSpaceDebugColor{ c.r / 255.f, c.g / 255.f, c.b / 255.f, c.a / 255.f };
|
||||
}
|
||||
|
||||
void DrawCircle(cpVect pos, cpFloat angle, cpFloat radius, cpSpaceDebugColor outlineColor, cpSpaceDebugColor fillColor, cpDataPointer userdata)
|
||||
{
|
||||
auto drawOptions = static_cast<PhysWorld2D::DebugDrawOptions*>(userdata);
|
||||
if (drawOptions->circleCallback)
|
||||
drawOptions->circleCallback(Vector2f(float(pos.x), float(pos.y)), float(angle), float(radius), CpDebugColorToColor(outlineColor), CpDebugColorToColor(fillColor), drawOptions->userdata);
|
||||
};
|
||||
|
||||
void DrawDot(cpFloat size, cpVect pos, cpSpaceDebugColor color, cpDataPointer userdata)
|
||||
{
|
||||
auto drawOptions = static_cast<PhysWorld2D::DebugDrawOptions*>(userdata);
|
||||
if (drawOptions->dotCallback)
|
||||
drawOptions->dotCallback(Vector2f(float(pos.x), float(pos.y)), float(size), CpDebugColorToColor(color), drawOptions->userdata);
|
||||
};
|
||||
|
||||
using DebugDrawPolygonCallback = std::function<void(const Vector2f* vertices, std::size_t vertexCount, float radius, Color outlineColor, Color fillColor, void* userdata)>;
|
||||
|
||||
void DrawPolygon(int vertexCount, const cpVect* vertices, cpFloat radius, cpSpaceDebugColor outlineColor, cpSpaceDebugColor fillColor, cpDataPointer userdata)
|
||||
{
|
||||
auto drawOptions = static_cast<PhysWorld2D::DebugDrawOptions*>(userdata);
|
||||
if (drawOptions->polygonCallback)
|
||||
{
|
||||
//TODO: constexpr if to prevent copy/cast if sizeof(cpVect) == sizeof(Vector2f)
|
||||
|
||||
StackAllocation stackAlloc = NazaraStackAllocation(vertexCount * sizeof(Vector2f));
|
||||
Vector2f* vec = static_cast<Vector2f*>(stackAlloc.GetPtr());
|
||||
for (int i = 0; i < vertexCount; ++i)
|
||||
vec[i].Set(float(vertices[i].x), float(vertices[i].y));
|
||||
|
||||
drawOptions->polygonCallback(vec, vertexCount, float(radius), CpDebugColorToColor(outlineColor), CpDebugColorToColor(fillColor), drawOptions->userdata);
|
||||
}
|
||||
};
|
||||
|
||||
void DrawSegment(cpVect a, cpVect b, cpSpaceDebugColor color, cpDataPointer userdata)
|
||||
{
|
||||
auto drawOptions = static_cast<PhysWorld2D::DebugDrawOptions*>(userdata);
|
||||
if (drawOptions->segmentCallback)
|
||||
drawOptions->segmentCallback(Vector2f(float(a.x), float(a.y)), Vector2f(float(b.x), float(b.y)), CpDebugColorToColor(color), drawOptions->userdata);
|
||||
};
|
||||
|
||||
void DrawThickSegment(cpVect a, cpVect b, cpFloat radius, cpSpaceDebugColor outlineColor, cpSpaceDebugColor fillColor, cpDataPointer userdata)
|
||||
{
|
||||
auto drawOptions = static_cast<PhysWorld2D::DebugDrawOptions*>(userdata);
|
||||
if (drawOptions->thickSegmentCallback)
|
||||
drawOptions->thickSegmentCallback(Vector2f(float(a.x), float(a.y)), Vector2f(float(b.x), float(b.y)), float(radius), CpDebugColorToColor(outlineColor), CpDebugColorToColor(fillColor), drawOptions->userdata);
|
||||
};
|
||||
|
||||
cpSpaceDebugColor GetColorForShape(cpShape* shape, cpDataPointer userdata)
|
||||
{
|
||||
auto drawOptions = static_cast<PhysWorld2D::DebugDrawOptions*>(userdata);
|
||||
if (drawOptions->colorCallback)
|
||||
{
|
||||
RigidBody2D& rigidBody = *static_cast<RigidBody2D*>(cpShapeGetUserData(shape));
|
||||
return ColorToCpDebugColor(drawOptions->colorCallback(rigidBody, rigidBody.GetShapeIndex(shape), drawOptions->userdata));
|
||||
}
|
||||
else
|
||||
return cpSpaceDebugColor{255.f, 0.f, 0.f, 255.f};
|
||||
};
|
||||
}
|
||||
|
||||
PhysWorld2D::PhysWorld2D() :
|
||||
m_stepSize(0.005f),
|
||||
m_timestepAccumulator(0.f)
|
||||
|
|
@ -21,6 +93,42 @@ namespace Nz
|
|||
cpSpaceFree(m_handle);
|
||||
}
|
||||
|
||||
void PhysWorld2D::DebugDraw(const DebugDrawOptions& options, bool drawShapes, bool drawConstraints, bool drawCollisions)
|
||||
{
|
||||
auto ColorToCpDebugColor = [](Color c) -> cpSpaceDebugColor
|
||||
{
|
||||
return cpSpaceDebugColor{ c.r / 255.f, c.g / 255.f, c.b / 255.f, c.a / 255.f };
|
||||
};
|
||||
|
||||
cpSpaceDebugDrawOptions drawOptions;
|
||||
drawOptions.collisionPointColor = ColorToCpDebugColor(options.collisionPointColor);
|
||||
drawOptions.constraintColor = ColorToCpDebugColor(options.constraintColor);
|
||||
drawOptions.shapeOutlineColor = ColorToCpDebugColor(options.shapeOutlineColor);
|
||||
drawOptions.data = const_cast<DebugDrawOptions*>(&options); //< Yeah, I know, shame :bell: but it won't be used for writing anyway
|
||||
|
||||
std::underlying_type_t<cpSpaceDebugDrawFlags> drawFlags = 0;
|
||||
if (drawCollisions)
|
||||
drawFlags |= CP_SPACE_DEBUG_DRAW_COLLISION_POINTS;
|
||||
|
||||
if (drawConstraints)
|
||||
drawFlags |= CP_SPACE_DEBUG_DRAW_CONSTRAINTS;
|
||||
|
||||
if (drawShapes)
|
||||
drawFlags |= CP_SPACE_DEBUG_DRAW_SHAPES;
|
||||
|
||||
drawOptions.flags = static_cast<cpSpaceDebugDrawFlags>(drawFlags);
|
||||
|
||||
// Callback trampoline
|
||||
drawOptions.colorForShape = GetColorForShape;
|
||||
drawOptions.drawCircle = DrawCircle;
|
||||
drawOptions.drawDot = DrawDot;
|
||||
drawOptions.drawFatSegment = DrawThickSegment;
|
||||
drawOptions.drawPolygon = DrawPolygon;
|
||||
drawOptions.drawSegment = DrawSegment;
|
||||
|
||||
cpSpaceDebugDraw(m_handle, &drawOptions);
|
||||
}
|
||||
|
||||
float PhysWorld2D::GetDamping() const
|
||||
{
|
||||
return float(cpSpaceGetDamping(m_handle));
|
||||
|
|
|
|||
|
|
@ -184,6 +184,15 @@ namespace Nz
|
|||
return FromRadians(static_cast<float>(cpBodyGetAngle(m_handle)));
|
||||
}
|
||||
|
||||
std::size_t RigidBody2D::GetShapeIndex(cpShape* shape) const
|
||||
{
|
||||
auto it = std::find(m_shapes.begin(), m_shapes.end(), shape);
|
||||
if (it == m_shapes.end())
|
||||
return InvalidShapeIndex;
|
||||
|
||||
return std::distance(m_shapes.begin(), it);
|
||||
}
|
||||
|
||||
void* RigidBody2D::GetUserdata() const
|
||||
{
|
||||
return m_userData;
|
||||
|
|
|
|||
Loading…
Reference in New Issue