diff --git a/ChangeLog.md b/ChangeLog.md index 6027f226d..44ab35911 100644 --- a/ChangeLog.md +++ b/ChangeLog.md @@ -175,7 +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 +- Added Collider2D::ForEachPolygon method Nazara Development Kit: - Added ImageWidget (#139) @@ -219,7 +219,7 @@ Nazara Development Kit: - Fix GraphicsComponent bounding volume not taking local matrix in account - ⚠️ Rewrote all render queue system, which should be more efficient, take scissor box into account - ⚠️ All widgets are now bound to a scissor box when rendering -- Add DebugComponent (a component able to show aabb/obb/collision mesh) +- Add DebugComponent (a component able to show aabb/obb/collision mesh 2D and 3D) - ⚠️ TextAreaWidget now support text selection (WIP) - ⚠️ TextAreaWidget::GetHoveredGlyph now returns a two-dimensional position instead of a single glyph position - Fixed Entity::OnEntityDestruction signal not being properly moved and thus not being called. diff --git a/SDK/include/NDK/Components/DebugComponent.hpp b/SDK/include/NDK/Components/DebugComponent.hpp index 206f85724..0777a9812 100644 --- a/SDK/include/NDK/Components/DebugComponent.hpp +++ b/SDK/include/NDK/Components/DebugComponent.hpp @@ -16,7 +16,7 @@ namespace Ndk { enum class DebugDraw { - //TODO: Collider2D + Collider2D, Collider3D, GraphicsAABB, GraphicsOBB, diff --git a/SDK/include/NDK/Systems/DebugSystem.hpp b/SDK/include/NDK/Systems/DebugSystem.hpp index 3dd186f36..0cb4839b7 100644 --- a/SDK/include/NDK/Systems/DebugSystem.hpp +++ b/SDK/include/NDK/Systems/DebugSystem.hpp @@ -26,6 +26,7 @@ namespace Ndk private: Nz::InstancedRenderableRef GenerateBox(Nz::Boxf box); + Nz::InstancedRenderableRef GenerateCollision2DMesh(Entity* entity, Nz::Vector3f* origin); Nz::InstancedRenderableRef GenerateCollision3DMesh(Entity* entity); Nz::MaterialRef GetCollisionMaterial(); diff --git a/SDK/src/NDK/Systems/DebugSystem.cpp b/SDK/src/NDK/Systems/DebugSystem.cpp index 063a25d77..21a184981 100644 --- a/SDK/src/NDK/Systems/DebugSystem.cpp +++ b/SDK/src/NDK/Systems/DebugSystem.cpp @@ -8,10 +8,12 @@ #include #include #include +#include #include #include #include #include +#include namespace Ndk { @@ -227,17 +229,26 @@ namespace Ndk { switch (option) { + case DebugDraw::Collider2D: + { + const Nz::Boxf& obb = entityGfx.GetAABB(); + + Nz::Vector3f origin; + Nz::InstancedRenderableRef renderable = GenerateCollision2DMesh(entity, &origin); + if (renderable) + entityGfx.Attach(renderable, Nz::Matrix4f::Translate(origin - entityNode.GetPosition()), DebugDrawOrder); + + entityDebug.UpdateDebugRenderable(option, std::move(renderable)); + break; + } + case DebugDraw::Collider3D: { const Nz::Boxf& obb = entityGfx.GetAABB(); Nz::InstancedRenderableRef renderable = GenerateCollision3DMesh(entity); if (renderable) - { - renderable->SetPersistent(false); - entityGfx.Attach(renderable, Nz::Matrix4f::Translate(obb.GetCenter() - entityNode.GetPosition()), DebugDrawOrder); - } entityDebug.UpdateDebugRenderable(option, std::move(renderable)); break; @@ -305,6 +316,73 @@ namespace Ndk return model; } + + Nz::InstancedRenderableRef DebugSystem::GenerateCollision2DMesh(Entity* entity, Nz::Vector3f* origin) + { + if (entity->HasComponent()) + { + CollisionComponent2D& entityCollision = entity->GetComponent(); + const Nz::Collider2DRef& geom = entityCollision.GetGeom(); + + std::vector vertices; + std::vector indices; + + geom->ForEachPolygon([&](const Nz::Vector2f* polygonVertices, std::size_t vertexCount) + { + std::size_t firstIndex = vertices.size(); + + // Don't reserve and let the vector handle its own capacity + for (std::size_t i = 0; i < vertexCount; ++i) + vertices.emplace_back(*polygonVertices++); + + for (std::size_t i = 0; i < vertexCount - 1; ++i) + { + indices.push_back(firstIndex + i); + indices.push_back(firstIndex + i + 1); + } + + indices.push_back(firstIndex + vertexCount - 1); + indices.push_back(firstIndex); + }); + + Nz::IndexBufferRef indexBuffer = Nz::IndexBuffer::New(vertices.size() > 0xFFFF, Nz::UInt32(indices.size()), Nz::DataStorage_Hardware, 0); + Nz::IndexMapper indexMapper(indexBuffer, Nz::BufferAccess_WriteOnly); + + Nz::IndexIterator indexPtr = indexMapper.begin(); + for (std::size_t index : indices) + *indexPtr++ = static_cast(index); + + indexMapper.Unmap(); + + Nz::VertexBufferRef vertexBuffer = Nz::VertexBuffer::New(Nz::VertexDeclaration::Get(Nz::VertexLayout_XYZ), Nz::UInt32(vertices.size()), Nz::DataStorage_Hardware, 0); + vertexBuffer->Fill(vertices.data(), 0, Nz::UInt32(vertices.size())); + + Nz::MeshRef mesh = Nz::Mesh::New(); + mesh->CreateStatic(); + + Nz::StaticMeshRef subMesh = Nz::StaticMesh::New(vertexBuffer, indexBuffer); + subMesh->SetPrimitiveMode(Nz::PrimitiveMode_LineList); + subMesh->SetMaterialIndex(0); + subMesh->GenerateAABB(); + + mesh->SetMaterialCount(1); + mesh->AddSubMesh(subMesh); + + Nz::ModelRef model = Nz::Model::New(); + model->SetMesh(mesh); + model->SetMaterial(0, GetCollisionMaterial()); + + // Find center of mass + if (entity->HasComponent()) + *origin = entity->GetComponent().GetMassCenter(Nz::CoordSys_Global); + else + *origin = entity->GetComponent().GetPosition(Nz::CoordSys_Global); + + return model; + } + else + return nullptr; + } Nz::InstancedRenderableRef DebugSystem::GenerateCollision3DMesh(Entity* entity) { @@ -315,16 +393,12 @@ namespace Ndk std::vector vertices; std::vector indices; - - geom->ForEachPolygon([&](const float* polygonVertices, std::size_t vertexCount) + + geom->ForEachPolygon([&](const Nz::Vector3f* polygonVertices, std::size_t vertexCount) { std::size_t firstIndex = vertices.size(); - - for (std::size_t i = 0; i < vertexCount; ++i) - { - const float* vertexData = &polygonVertices[i * 3]; - vertices.emplace_back(vertexData[0], vertexData[1], vertexData[2]); - } + vertices.resize(firstIndex + vertexCount); + std::copy(polygonVertices, polygonVertices + vertexCount, &vertices[firstIndex]); for (std::size_t i = 0; i < vertexCount - 1; ++i) { @@ -378,7 +452,7 @@ namespace Ndk m_globalAabbMaterial->EnableDepthBuffer(true); m_globalAabbMaterial->SetDiffuseColor(Nz::Color::Orange); m_globalAabbMaterial->SetFaceFilling(Nz::FaceFilling_Line); - m_globalAabbMaterial->SetLineWidth(2.f); + //m_globalAabbMaterial->SetLineWidth(2.f); } return m_globalAabbMaterial; @@ -393,7 +467,7 @@ namespace Ndk m_localAabbMaterial->EnableDepthBuffer(true); m_localAabbMaterial->SetDiffuseColor(Nz::Color::Red); m_localAabbMaterial->SetFaceFilling(Nz::FaceFilling_Line); - m_localAabbMaterial->SetLineWidth(2.f); + //m_localAabbMaterial->SetLineWidth(2.f); } return m_localAabbMaterial; @@ -408,7 +482,7 @@ namespace Ndk m_collisionMaterial->EnableDepthBuffer(true); m_collisionMaterial->SetDiffuseColor(Nz::Color::Blue); m_collisionMaterial->SetFaceFilling(Nz::FaceFilling_Line); - m_collisionMaterial->SetLineWidth(2.f); + //m_collisionMaterial->SetLineWidth(2.f); } return m_collisionMaterial; @@ -423,7 +497,7 @@ namespace Ndk m_obbMaterial->EnableDepthBuffer(true); m_obbMaterial->SetDiffuseColor(Nz::Color::Green); m_obbMaterial->SetFaceFilling(Nz::FaceFilling_Line); - m_obbMaterial->SetLineWidth(2.f); + //m_obbMaterial->SetLineWidth(2.f); } return m_obbMaterial;