Add generic debug rendering functions
Currently the engine can draw debug spheres to show crash sphere positions. This extends this to draw arbitrary spheres and cuboids, transformed arbitrarily. With these in place it's now very quick and easy to create a debug visualisation - for example, it's a one-line code change to render the bounding box or sphere of every EngineObject.1008-fix
parent
fdf67b8217
commit
c445d7d9a9
|
@ -3147,24 +3147,6 @@ void CEngine::ApplyChange()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void CEngine::ClearDisplayCrashSpheres()
|
|
||||||
{
|
|
||||||
m_displayCrashSpheres.clear();
|
|
||||||
|
|
||||||
m_debugCrashSpheres = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
void CEngine::AddDisplayCrashSpheres(const std::vector<Math::Sphere>& crashSpheres)
|
|
||||||
{
|
|
||||||
for (const auto& crashSphere : crashSpheres)
|
|
||||||
{
|
|
||||||
m_displayCrashSpheres.push_back(crashSphere);
|
|
||||||
}
|
|
||||||
|
|
||||||
m_debugCrashSpheres = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*******************************************************
|
/*******************************************************
|
||||||
Rendering
|
Rendering
|
||||||
*******************************************************/
|
*******************************************************/
|
||||||
|
@ -3483,8 +3465,7 @@ void CEngine::Draw3DScene()
|
||||||
|
|
||||||
m_device->SetRenderState(RENDER_STATE_LIGHTING, false);
|
m_device->SetRenderState(RENDER_STATE_LIGHTING, false);
|
||||||
|
|
||||||
if (m_debugCrashSpheres)
|
RenderPendingDebugDraws();
|
||||||
DrawCrashSpheres();
|
|
||||||
|
|
||||||
if (m_debugGoto)
|
if (m_debugGoto)
|
||||||
{
|
{
|
||||||
|
@ -3651,74 +3632,136 @@ void CEngine::DrawCaptured3DScene()
|
||||||
m_device->DrawPrimitive(PRIMITIVE_TRIANGLE_STRIP, vertices, 4);
|
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;
|
static constexpr int LONGITUDE_DIVISIONS = 16;
|
||||||
worldMatrix.LoadIdentity();
|
static constexpr int LATITUDE_DIVISIONS = 8;
|
||||||
m_device->SetTransform(TRANSFORM_WORLD, worldMatrix);
|
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<Math::Vector, NUM_LINE_STRIPS * VERTS_IN_LINE_STRIP> verticesTemplate = []{
|
||||||
|
std::array<Math::Vector, NUM_LINE_STRIPS * VERTS_IN_LINE_STRIP> vertices;
|
||||||
|
|
||||||
static const int LINE_SEGMENTS = 32;
|
auto SpherePoint = [&](float latitude, float longitude)
|
||||||
static const int LONGITUDE_DIVISIONS = 16;
|
{
|
||||||
static const int LATITUDE_DIVISIONS = 8;
|
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<VertexCol> lines((2 + LONGITUDE_DIVISIONS + LATITUDE_DIVISIONS) * LINE_SEGMENTS);
|
auto vert = vertices.begin();
|
||||||
std::vector<int> firsts(2 + LONGITUDE_DIVISIONS + LATITUDE_DIVISIONS);
|
|
||||||
std::vector<int> 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;
|
|
||||||
|
|
||||||
for (int longitudeDivision = 0; longitudeDivision <= LONGITUDE_DIVISIONS; ++longitudeDivision)
|
for (int longitudeDivision = 0; longitudeDivision <= LONGITUDE_DIVISIONS; ++longitudeDivision)
|
||||||
{
|
{
|
||||||
firsts[primitive] = i;
|
for (int segment = 0; segment < VERTS_IN_LINE_STRIP; ++segment)
|
||||||
counts[primitive] = LINE_SEGMENTS;
|
|
||||||
|
|
||||||
for (int segment = 0; segment < LINE_SEGMENTS; ++segment)
|
|
||||||
{
|
{
|
||||||
Math::Vector pos = crashSphere.pos;
|
float latitude = static_cast<float>(segment) / VERTS_IN_LINE_STRIP;
|
||||||
float latitude = static_cast<float>(segment) / LINE_SEGMENTS;
|
|
||||||
float longitude = static_cast<float>(longitudeDivision) / (LONGITUDE_DIVISIONS);
|
float longitude = static_cast<float>(longitudeDivision) / (LONGITUDE_DIVISIONS);
|
||||||
pos += SpherePoint(crashSphere.radius, latitude, longitude);
|
*vert++ = SpherePoint(latitude, longitude);
|
||||||
lines[i++] = VertexCol(pos, color);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
primitive++;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
for (int latitudeDivision = 0; latitudeDivision <= LATITUDE_DIVISIONS; ++latitudeDivision)
|
for (int latitudeDivision = 0; latitudeDivision <= LATITUDE_DIVISIONS; ++latitudeDivision)
|
||||||
{
|
{
|
||||||
firsts[primitive] = i;
|
for (int segment = 0; segment < VERTS_IN_LINE_STRIP; ++segment)
|
||||||
counts[primitive] = LINE_SEGMENTS;
|
|
||||||
|
|
||||||
for (int segment = 0; segment < LINE_SEGMENTS; ++segment)
|
|
||||||
{
|
{
|
||||||
Math::Vector pos = crashSphere.pos;
|
|
||||||
float latitude = static_cast<float>(latitudeDivision + 1) / (LATITUDE_DIVISIONS + 2);
|
float latitude = static_cast<float>(latitudeDivision + 1) / (LATITUDE_DIVISIONS + 2);
|
||||||
float longitude = static_cast<float>(segment) / LINE_SEGMENTS;
|
float longitude = static_cast<float>(segment) / VERTS_IN_LINE_STRIP;
|
||||||
pos += SpherePoint(crashSphere.radius, latitude, longitude);
|
*vert++ = SpherePoint(latitude, longitude);
|
||||||
lines[i++] = VertexCol(pos, color);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
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()
|
void CEngine::RenderShadowMap()
|
||||||
|
|
|
@ -1161,8 +1161,8 @@ public:
|
||||||
//! Updates the scene after a change of parameters
|
//! Updates the scene after a change of parameters
|
||||||
void ApplyChange();
|
void ApplyChange();
|
||||||
|
|
||||||
void ClearDisplayCrashSpheres();
|
void RenderDebugSphere(const Math::Sphere&, const Math::Matrix& transform = Math::Matrix{}, const Color& = Color{0.0f, 0.0f, 1.0f, 1.0f});
|
||||||
void AddDisplayCrashSpheres(const std::vector<Math::Sphere>& crashSpheres);
|
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);
|
void SetDebugLights(bool debugLights);
|
||||||
bool GetDebugLights();
|
bool GetDebugLights();
|
||||||
|
@ -1228,7 +1228,7 @@ protected:
|
||||||
void DrawStats();
|
void DrawStats();
|
||||||
//! Draw mission timer
|
//! Draw mission timer
|
||||||
void DrawTimer();
|
void DrawTimer();
|
||||||
void DrawCrashSpheres();
|
void RenderPendingDebugDraws();
|
||||||
|
|
||||||
//! Creates a new tier 2 object (texture)
|
//! Creates a new tier 2 object (texture)
|
||||||
EngineBaseObjTexTier& AddLevel2(EngineBaseObject& p1, const std::string& tex1Name, const std::string& tex2Name);
|
EngineBaseObjTexTier& AddLevel2(EngineBaseObject& p1, const std::string& tex1Name, const std::string& tex2Name);
|
||||||
|
@ -1406,6 +1406,13 @@ protected:
|
||||||
|
|
||||||
Texture m_shadowMap;
|
Texture m_shadowMap;
|
||||||
|
|
||||||
|
struct
|
||||||
|
{
|
||||||
|
std::vector<VertexCol> vertices;
|
||||||
|
std::vector<int> firsts;
|
||||||
|
std::vector<int> counts;
|
||||||
|
} m_pendingDebugDraws;
|
||||||
|
|
||||||
//! Ranks of highlighted objects
|
//! Ranks of highlighted objects
|
||||||
int m_highlightRank[100];
|
int m_highlightRank[100];
|
||||||
//! Highlight visible?
|
//! Highlight visible?
|
||||||
|
@ -1479,7 +1486,6 @@ protected:
|
||||||
|
|
||||||
std::unordered_map<std::string, int> m_staticMeshBaseObjects;
|
std::unordered_map<std::string, int> m_staticMeshBaseObjects;
|
||||||
|
|
||||||
std::vector<Math::Sphere> m_displayCrashSpheres;
|
|
||||||
std::vector<std::vector<VertexCol>> m_displayGoto;
|
std::vector<std::vector<VertexCol>> m_displayGoto;
|
||||||
std::unique_ptr<CImage> m_displayGotoImage;
|
std::unique_ptr<CImage> m_displayGotoImage;
|
||||||
|
|
||||||
|
|
|
@ -5949,18 +5949,14 @@ void CRobotMain::SetCodeBattleSpectatorMode(bool mode)
|
||||||
|
|
||||||
void CRobotMain::UpdateDebugCrashSpheres()
|
void CRobotMain::UpdateDebugCrashSpheres()
|
||||||
{
|
{
|
||||||
m_engine->ClearDisplayCrashSpheres();
|
|
||||||
if (m_debugCrashSpheres)
|
if (m_debugCrashSpheres)
|
||||||
{
|
{
|
||||||
for (CObject* obj : m_objMan->GetAllObjects())
|
for (CObject* obj : m_objMan->GetAllObjects())
|
||||||
{
|
{
|
||||||
auto crashSpheres = obj->GetAllCrashSpheres();
|
for (const auto& crashSphere : obj->GetAllCrashSpheres())
|
||||||
std::vector<Math::Sphere> displaySpheres;
|
|
||||||
for (const auto& crashSphere : crashSpheres)
|
|
||||||
{
|
{
|
||||||
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);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue