diff --git a/src/graphics/engine/engine.cpp b/src/graphics/engine/engine.cpp index 23ed2108..8722f1af 100644 --- a/src/graphics/engine/engine.cpp +++ b/src/graphics/engine/engine.cpp @@ -3147,24 +3147,6 @@ void CEngine::ApplyChange() } } -void CEngine::ClearDisplayCrashSpheres() -{ - m_displayCrashSpheres.clear(); - - m_debugCrashSpheres = false; -} - -void CEngine::AddDisplayCrashSpheres(const std::vector& crashSpheres) -{ - for (const auto& crashSphere : crashSpheres) - { - m_displayCrashSpheres.push_back(crashSphere); - } - - m_debugCrashSpheres = true; -} - - /******************************************************* Rendering *******************************************************/ @@ -3483,8 +3465,7 @@ void CEngine::Draw3DScene() m_device->SetRenderState(RENDER_STATE_LIGHTING, false); - if (m_debugCrashSpheres) - DrawCrashSpheres(); + RenderPendingDebugDraws(); if (m_debugGoto) { @@ -3651,74 +3632,136 @@ void CEngine::DrawCaptured3DScene() m_device->DrawPrimitive(PRIMITIVE_TRIANGLE_STRIP, vertices, 4); } -void CEngine::DrawCrashSpheres() +void CEngine::RenderDebugSphere(const Math::Sphere& sphere, const Math::Matrix& transform, const Gfx::Color& color) { - Math::Matrix worldMatrix; - worldMatrix.LoadIdentity(); - m_device->SetTransform(TRANSFORM_WORLD, worldMatrix); + static constexpr int LONGITUDE_DIVISIONS = 16; + static constexpr int LATITUDE_DIVISIONS = 8; + static constexpr int NUM_LINE_STRIPS = 2 + LONGITUDE_DIVISIONS + LATITUDE_DIVISIONS; + static constexpr int VERTS_IN_LINE_STRIP = 32; - SetState(ENG_RSTATE_OPAQUE_COLOR); + static std::array verticesTemplate = []{ + std::array vertices; - static const int LINE_SEGMENTS = 32; - static const int LONGITUDE_DIVISIONS = 16; - static const int LATITUDE_DIVISIONS = 8; + auto SpherePoint = [&](float latitude, float longitude) + { + float latitudeAngle = (latitude - 0.5f) * 2.0f * Math::PI; + float longitudeAngle = longitude * 2.0f * Math::PI; + return Math::Vector(sinf(latitudeAngle) * cosf(longitudeAngle), + cosf(latitudeAngle), + sinf(latitudeAngle) * sinf(longitudeAngle)); + }; - std::vector lines((2 + LONGITUDE_DIVISIONS + LATITUDE_DIVISIONS) * LINE_SEGMENTS); - std::vector firsts(2 + LONGITUDE_DIVISIONS + LATITUDE_DIVISIONS); - std::vector counts(2 + LONGITUDE_DIVISIONS + LATITUDE_DIVISIONS); - - Color color(0.0f, 0.0f, 1.0f); - - auto SpherePoint = [&](float sphereRadius, float latitude, float longitude) - { - float latitudeAngle = (latitude - 0.5f) * 2.0f * Math::PI; - float longitudeAngle = longitude * 2.0f * Math::PI; - return Math::Vector(sphereRadius * sinf(latitudeAngle) * cosf(longitudeAngle), - sphereRadius * cosf(latitudeAngle), - sphereRadius * sinf(latitudeAngle) * sinf(longitudeAngle)); - }; - - for (const auto& crashSphere : m_displayCrashSpheres) - { - int i = 0; - int primitive = 0; + auto vert = vertices.begin(); for (int longitudeDivision = 0; longitudeDivision <= LONGITUDE_DIVISIONS; ++longitudeDivision) { - firsts[primitive] = i; - counts[primitive] = LINE_SEGMENTS; - - for (int segment = 0; segment < LINE_SEGMENTS; ++segment) + for (int segment = 0; segment < VERTS_IN_LINE_STRIP; ++segment) { - Math::Vector pos = crashSphere.pos; - float latitude = static_cast(segment) / LINE_SEGMENTS; + float latitude = static_cast(segment) / VERTS_IN_LINE_STRIP; float longitude = static_cast(longitudeDivision) / (LONGITUDE_DIVISIONS); - pos += SpherePoint(crashSphere.radius, latitude, longitude); - lines[i++] = VertexCol(pos, color); + *vert++ = SpherePoint(latitude, longitude); } - - primitive++; } for (int latitudeDivision = 0; latitudeDivision <= LATITUDE_DIVISIONS; ++latitudeDivision) { - firsts[primitive] = i; - counts[primitive] = LINE_SEGMENTS; - - for (int segment = 0; segment < LINE_SEGMENTS; ++segment) + for (int segment = 0; segment < VERTS_IN_LINE_STRIP; ++segment) { - Math::Vector pos = crashSphere.pos; float latitude = static_cast(latitudeDivision + 1) / (LATITUDE_DIVISIONS + 2); - float longitude = static_cast(segment) / LINE_SEGMENTS; - pos += SpherePoint(crashSphere.radius, latitude, longitude); - lines[i++] = VertexCol(pos, color); + float longitude = static_cast(segment) / VERTS_IN_LINE_STRIP; + *vert++ = SpherePoint(latitude, longitude); } - - primitive++; } + return vertices; + }(); - m_device->DrawPrimitives(PRIMITIVE_LINE_STRIP, lines.data(), firsts.data(), counts.data(), primitive); + + const int firstDraw = m_pendingDebugDraws.firsts.size(); + const int firstVert = m_pendingDebugDraws.vertices.size(); + + m_pendingDebugDraws.firsts.resize(m_pendingDebugDraws.firsts.size() + NUM_LINE_STRIPS); + m_pendingDebugDraws.counts.resize(m_pendingDebugDraws.counts.size() + NUM_LINE_STRIPS); + m_pendingDebugDraws.vertices.resize(m_pendingDebugDraws.vertices.size() + verticesTemplate.size()); + + for (int i = 0; i < NUM_LINE_STRIPS; ++i) + { + m_pendingDebugDraws.firsts[i + firstDraw] = firstVert + i * VERTS_IN_LINE_STRIP; } + + for (int i = 0; i < NUM_LINE_STRIPS; ++i) + { + m_pendingDebugDraws.counts[i + firstDraw] = VERTS_IN_LINE_STRIP; + } + + for (std::size_t i = 0; i < verticesTemplate.size(); ++i) + { + auto pos = Math::MatrixVectorMultiply(transform, sphere.pos + verticesTemplate[i] * sphere.radius); + m_pendingDebugDraws.vertices[i + firstVert] = VertexCol{pos, color}; + } +} + +void CEngine::RenderDebugBox(const Math::Vector& mins, const Math::Vector& maxs, const Math::Matrix& transform, const Gfx::Color& color) +{ + static constexpr int NUM_LINE_STRIPS = 4; + static constexpr int VERTS_IN_LINE_STRIP = 4; + + const int firstDraw = m_pendingDebugDraws.firsts.size(); + const int firstVert = m_pendingDebugDraws.vertices.size(); + + m_pendingDebugDraws.firsts.resize(m_pendingDebugDraws.firsts.size() + NUM_LINE_STRIPS); + m_pendingDebugDraws.counts.resize(m_pendingDebugDraws.counts.size() + NUM_LINE_STRIPS); + m_pendingDebugDraws.vertices.resize(m_pendingDebugDraws.vertices.size() + NUM_LINE_STRIPS * VERTS_IN_LINE_STRIP); + + for (int i = 0; i < NUM_LINE_STRIPS; ++i) + { + m_pendingDebugDraws.firsts[i + firstDraw] = firstVert + (i * VERTS_IN_LINE_STRIP); + } + + for (int i = 0; i < NUM_LINE_STRIPS; ++i) + { + m_pendingDebugDraws.counts[i + firstDraw] = NUM_LINE_STRIPS; + } + + auto vert = m_pendingDebugDraws.vertices.begin() + firstVert; + + *vert++ = VertexCol{Math::MatrixVectorMultiply(transform, Math::Vector{mins.x, mins.y, mins.z}), color}; + *vert++ = VertexCol{Math::MatrixVectorMultiply(transform, Math::Vector{maxs.x, mins.y, mins.z}), color}; + *vert++ = VertexCol{Math::MatrixVectorMultiply(transform, Math::Vector{maxs.x, maxs.y, mins.z}), color}; + *vert++ = VertexCol{Math::MatrixVectorMultiply(transform, Math::Vector{maxs.x, maxs.y, maxs.z}), color}; + + *vert++ = VertexCol{Math::MatrixVectorMultiply(transform, Math::Vector{mins.x, mins.y, maxs.z}), color}; + *vert++ = VertexCol{Math::MatrixVectorMultiply(transform, Math::Vector{mins.x, mins.y, mins.z}), color}; + *vert++ = VertexCol{Math::MatrixVectorMultiply(transform, Math::Vector{mins.x, maxs.y, mins.z}), color}; + *vert++ = VertexCol{Math::MatrixVectorMultiply(transform, Math::Vector{maxs.x, maxs.y, mins.z}), color}; + + *vert++ = VertexCol{Math::MatrixVectorMultiply(transform, Math::Vector{maxs.x, mins.y, maxs.z}), color}; + *vert++ = VertexCol{Math::MatrixVectorMultiply(transform, Math::Vector{mins.x, mins.y, maxs.z}), color}; + *vert++ = VertexCol{Math::MatrixVectorMultiply(transform, Math::Vector{mins.x, maxs.y, maxs.z}), color}; + *vert++ = VertexCol{Math::MatrixVectorMultiply(transform, Math::Vector{mins.x, maxs.y, mins.z}), color}; + + *vert++ = VertexCol{Math::MatrixVectorMultiply(transform, Math::Vector{maxs.x, mins.y, mins.z}), color}; + *vert++ = VertexCol{Math::MatrixVectorMultiply(transform, Math::Vector{maxs.x, mins.y, maxs.z}), color}; + *vert++ = VertexCol{Math::MatrixVectorMultiply(transform, Math::Vector{maxs.x, maxs.y, maxs.z}), color}; + *vert++ = VertexCol{Math::MatrixVectorMultiply(transform, Math::Vector{mins.x, maxs.y, maxs.z}), color}; +} + +void CEngine::RenderPendingDebugDraws() +{ + if (m_pendingDebugDraws.firsts.empty()) return; + + m_device->SetTransform(TRANSFORM_WORLD, Math::Matrix{}); + + SetState(ENG_RSTATE_OPAQUE_COLOR); + + m_device->DrawPrimitives(PRIMITIVE_LINE_STRIP, + m_pendingDebugDraws.vertices.data(), + m_pendingDebugDraws.firsts.data(), + m_pendingDebugDraws.counts.data(), + m_pendingDebugDraws.firsts.size()); + + m_pendingDebugDraws.firsts.clear(); + m_pendingDebugDraws.counts.clear(); + m_pendingDebugDraws.vertices.clear(); } void CEngine::RenderShadowMap() diff --git a/src/graphics/engine/engine.h b/src/graphics/engine/engine.h index 27f01585..f7f4db49 100644 --- a/src/graphics/engine/engine.h +++ b/src/graphics/engine/engine.h @@ -1161,8 +1161,8 @@ public: //! Updates the scene after a change of parameters void ApplyChange(); - void ClearDisplayCrashSpheres(); - void AddDisplayCrashSpheres(const std::vector& crashSpheres); + void RenderDebugSphere(const Math::Sphere&, const Math::Matrix& transform = Math::Matrix{}, const Color& = Color{0.0f, 0.0f, 1.0f, 1.0f}); + void RenderDebugBox(const Math::Vector& mins, const Math::Vector& maxs, const Math::Matrix& transform = Math::Matrix{}, const Color& = Color{0.0f, 0.0f, 1.0f, 1.0f}); void SetDebugLights(bool debugLights); bool GetDebugLights(); @@ -1228,7 +1228,7 @@ protected: void DrawStats(); //! Draw mission timer void DrawTimer(); - void DrawCrashSpheres(); + void RenderPendingDebugDraws(); //! Creates a new tier 2 object (texture) EngineBaseObjTexTier& AddLevel2(EngineBaseObject& p1, const std::string& tex1Name, const std::string& tex2Name); @@ -1406,6 +1406,13 @@ protected: Texture m_shadowMap; + struct + { + std::vector vertices; + std::vector firsts; + std::vector counts; + } m_pendingDebugDraws; + //! Ranks of highlighted objects int m_highlightRank[100]; //! Highlight visible? @@ -1479,7 +1486,6 @@ protected: std::unordered_map m_staticMeshBaseObjects; - std::vector m_displayCrashSpheres; std::vector> m_displayGoto; std::unique_ptr m_displayGotoImage; diff --git a/src/level/robotmain.cpp b/src/level/robotmain.cpp index 5e49cc68..24e944c7 100644 --- a/src/level/robotmain.cpp +++ b/src/level/robotmain.cpp @@ -5949,18 +5949,14 @@ void CRobotMain::SetCodeBattleSpectatorMode(bool mode) void CRobotMain::UpdateDebugCrashSpheres() { - m_engine->ClearDisplayCrashSpheres(); if (m_debugCrashSpheres) { for (CObject* obj : m_objMan->GetAllObjects()) { - auto crashSpheres = obj->GetAllCrashSpheres(); - std::vector displaySpheres; - for (const auto& crashSphere : crashSpheres) + for (const auto& crashSphere : obj->GetAllCrashSpheres()) { - displaySpheres.push_back(crashSphere.sphere); + m_engine->RenderDebugSphere(crashSphere.sphere, Math::Matrix{}, Gfx::Color{0.0f, 0.0f, 1.0f, 1.0f}); } - m_engine->AddDisplayCrashSpheres(displaySpheres); } } }