diff --git a/ChangeLog.md b/ChangeLog.md index 39ead0d94..6027f226d 100644 --- a/ChangeLog.md +++ b/ChangeLog.md @@ -175,6 +175,7 @@ Nazara Engine: - Fixed ENet UnreliableFragment packets sent as Unreliable (and such being incomplete upon reception) - ENet DisconnectLater now reflects libenet behavior (and is waiting for unreliable commands to be sent before disconnecting for good) - ⚠ Collider3D::ForEachPolygon now takes a void(Vector3f\*, std::size_t) callback (instead of void(float\*, std::size_t)) +- Added Collider2D::ForEachPolygon Nazara Development Kit: - Added ImageWidget (#139) diff --git a/include/Nazara/Physics2D/Collider2D.hpp b/include/Nazara/Physics2D/Collider2D.hpp index cc2f62eac..e817457b8 100644 --- a/include/Nazara/Physics2D/Collider2D.hpp +++ b/include/Nazara/Physics2D/Collider2D.hpp @@ -41,9 +41,11 @@ namespace Nz Collider2D(Collider2D&&) = delete; virtual ~Collider2D(); - virtual Nz::Vector2f ComputeCenterOfMass() const = 0; + virtual Vector2f ComputeCenterOfMass() const = 0; virtual float ComputeMomentOfInertia(float mass) const = 0; + virtual void ForEachPolygon(const std::function& callback) const; + inline UInt32 GetCategoryMask() const; inline UInt32 GetCollisionGroup() const; inline unsigned int GetCollisionId() const; diff --git a/src/Nazara/Physics2D/Collider2D.cpp b/src/Nazara/Physics2D/Collider2D.cpp index 75f5fe332..f997f29f6 100644 --- a/src/Nazara/Physics2D/Collider2D.cpp +++ b/src/Nazara/Physics2D/Collider2D.cpp @@ -3,14 +3,81 @@ // For conditions of distribution and use, see copyright notice in Config.hpp #include +#include #include +#include #include -#include +#include +#include +#include namespace Nz { Collider2D::~Collider2D() = default; + void Collider2D::ForEachPolygon(const std::function& callback) const + { + // Currently, the only way to get only the polygons of a shape is to create a temporary cpSpace containing only this shape + // A better way to do this would be to reimplement this function in every subclass type in the very same way chipmunk does + + PhysWorld2D physWorld; + RigidBody2D rigidBody(&physWorld, 0.f); + + std::vector shapeVector; + rigidBody.SetGeom(const_cast(this), false, false); //< Won't be used for writing, but still ugly + + PhysWorld2D::DebugDrawOptions drawCallbacks; + drawCallbacks.circleCallback = [&](const Vector2f& origin, const RadianAnglef& /*rotation*/, float radius, Nz::Color /*outlineColor*/, Nz::Color /*fillColor*/, void* /*userData*/) + { + constexpr std::size_t circleVerticesCount = 20; + + std::array vertices; + + RadianAnglef angleBetweenVertices = 2.f * float(M_PI) / vertices.size(); + for (std::size_t i = 0; i < vertices.size(); ++i) + { + RadianAnglef angle = float(i) * angleBetweenVertices; + std::pair sincos = angle.GetSinCos(); + + vertices[i] = origin + Vector2f(radius * sincos.first, radius * sincos.second); + } + + callback(vertices.data(), vertices.size()); + }; + + drawCallbacks.polygonCallback = [&](const Vector2f* vertices, std::size_t vertexCount, float radius, Nz::Color /*outlineColor*/, Nz::Color /*fillColor*/, void* /*userData*/) + { + //TODO: Handle radius + callback(vertices, vertexCount); + }; + + drawCallbacks.segmentCallback = [&](const Vector2f& first, const Vector2f& second, Nz::Color /*color*/, void* /*userData*/) + { + std::array vertices = { first, second }; + + callback(vertices.data(), vertices.size()); + }; + + drawCallbacks.thickSegmentCallback = [&](const Vector2f& first, const Vector2f& second, float thickness, Nz::Color /*outlineColor*/, Nz::Color /*fillColor*/, void* /*userData*/) + { + static std::pair sincos = Nz::DegreeAnglef(90.f).GetSinCos(); + + Vector2f normal = Vector2f::Normalize(second - first); + Vector2f thicknessNormal(sincos.second * normal.x - sincos.first * normal.y, + sincos.first * normal.x + sincos.second * normal.y); + + std::array vertices; + vertices[0] = first + thickness * thicknessNormal; + vertices[1] = first - thickness * thicknessNormal; + vertices[2] = second - thickness * thicknessNormal; + vertices[3] = second + thickness * thicknessNormal; + + callback(vertices.data(), vertices.size()); + }; + + physWorld.DebugDraw(drawCallbacks, true, false, false); + } + std::size_t Collider2D::GenerateShapes(RigidBody2D* body, std::vector* shapes) const { std::size_t shapeCount = CreateShapes(body, shapes);