SleakEngine 1.0.0
C++23 multi-backend game engine
Loading...
Searching...
No Matches
DebugLineRenderer.cpp
Go to the documentation of this file.
6#include <Camera/Camera.hpp>
7#include <Core/Logger.hpp>
8#include <cmath>
9
10namespace Sleak {
11
15
16// Static member definitions
17std::vector<Vertex>* DebugLineRenderer::s_vertices = nullptr;
18RefPtr<RenderEngine::BufferBase> DebugLineRenderer::s_vertexBuffer;
19RefPtr<RenderEngine::Shader> DebugLineRenderer::s_shader;
20RefPtr<RenderEngine::BufferBase> DebugLineRenderer::s_constantBuffer;
21bool DebugLineRenderer::s_enabled = false;
22bool DebugLineRenderer::s_initialized = false;
23
25 if (s_initialized) return;
26
28 "assets/shaders/debug_line.hlsl"));
29 if (!s_shader.IsValid()) {
30 SLEAK_ERROR("DebugLineRenderer: Failed to create debug line shader");
31 return;
32 }
33
34 // Create dynamic vertex buffer (pre-allocate for MAX_VERTICES)
35 std::vector<Vertex> emptyVerts(MAX_VERTICES);
38 MAX_VERTICES * sizeof(Vertex),
39 emptyVerts.data()));
40
41 // Create constant buffer for ViewProjection matrix
42 DebugLineCBData cbData;
46 sizeof(DebugLineCBData),
47 &cbData));
48 s_constantBuffer->SetSlot(0);
49
50 s_vertices = new std::vector<Vertex>();
51 s_vertices->reserve(MAX_VERTICES);
52 s_initialized = true;
53 SLEAK_INFO("DebugLineRenderer initialized");
54}
55
57 delete s_vertices;
58 s_vertices = nullptr;
59 s_vertexBuffer.reset();
60 s_shader.reset();
61 s_constantBuffer.reset();
62 s_initialized = false;
63}
64
66 float r, float g, float b, float a) {
67 if (s_vertices->size() + 2 > MAX_VERTICES) return;
68
69 Vertex v1{};
70 v1.px = start.GetX(); v1.py = start.GetY(); v1.pz = start.GetZ();
71 v1.r = r; v1.g = g; v1.b = b; v1.a = a;
72
73 Vertex v2{};
74 v2.px = end.GetX(); v2.py = end.GetY(); v2.pz = end.GetZ();
75 v2.r = r; v2.g = g; v2.b = b; v2.a = a;
76
77 s_vertices->push_back(v1);
78 s_vertices->push_back(v2);
79}
80
82 float r, float g, float b, float a) {
83 Math::Vector3D mn = aabb.min;
84 Math::Vector3D mx = aabb.max;
85
86 // 8 corners
87 Math::Vector3D c000(mn.GetX(), mn.GetY(), mn.GetZ());
88 Math::Vector3D c001(mn.GetX(), mn.GetY(), mx.GetZ());
89 Math::Vector3D c010(mn.GetX(), mx.GetY(), mn.GetZ());
90 Math::Vector3D c011(mn.GetX(), mx.GetY(), mx.GetZ());
91 Math::Vector3D c100(mx.GetX(), mn.GetY(), mn.GetZ());
92 Math::Vector3D c101(mx.GetX(), mn.GetY(), mx.GetZ());
93 Math::Vector3D c110(mx.GetX(), mx.GetY(), mn.GetZ());
94 Math::Vector3D c111(mx.GetX(), mx.GetY(), mx.GetZ());
95
96 // Bottom face
97 DrawLine(c000, c100, r, g, b, a);
98 DrawLine(c100, c101, r, g, b, a);
99 DrawLine(c101, c001, r, g, b, a);
100 DrawLine(c001, c000, r, g, b, a);
101
102 // Top face
103 DrawLine(c010, c110, r, g, b, a);
104 DrawLine(c110, c111, r, g, b, a);
105 DrawLine(c111, c011, r, g, b, a);
106 DrawLine(c011, c010, r, g, b, a);
107
108 // Vertical edges
109 DrawLine(c000, c010, r, g, b, a);
110 DrawLine(c100, c110, r, g, b, a);
111 DrawLine(c101, c111, r, g, b, a);
112 DrawLine(c001, c011, r, g, b, a);
113}
114
115void DebugLineRenderer::DrawSphere(const Math::Vector3D& center, float radius,
116 float r, float g, float b, float a,
117 int segments) {
118 float step = 2.0f * 3.14159265f / static_cast<float>(segments);
119
120 // XY plane circle
121 for (int i = 0; i < segments; ++i) {
122 float angle0 = step * i;
123 float angle1 = step * (i + 1);
124 Math::Vector3D p0(center.GetX() + radius * std::cos(angle0),
125 center.GetY() + radius * std::sin(angle0),
126 center.GetZ());
127 Math::Vector3D p1(center.GetX() + radius * std::cos(angle1),
128 center.GetY() + radius * std::sin(angle1),
129 center.GetZ());
130 DrawLine(p0, p1, r, g, b, a);
131 }
132
133 // XZ plane circle
134 for (int i = 0; i < segments; ++i) {
135 float angle0 = step * i;
136 float angle1 = step * (i + 1);
137 Math::Vector3D p0(center.GetX() + radius * std::cos(angle0),
138 center.GetY(),
139 center.GetZ() + radius * std::sin(angle0));
140 Math::Vector3D p1(center.GetX() + radius * std::cos(angle1),
141 center.GetY(),
142 center.GetZ() + radius * std::sin(angle1));
143 DrawLine(p0, p1, r, g, b, a);
144 }
145
146 // YZ plane circle
147 for (int i = 0; i < segments; ++i) {
148 float angle0 = step * i;
149 float angle1 = step * (i + 1);
150 Math::Vector3D p0(center.GetX(),
151 center.GetY() + radius * std::cos(angle0),
152 center.GetZ() + radius * std::sin(angle0));
153 Math::Vector3D p1(center.GetX(),
154 center.GetY() + radius * std::cos(angle1),
155 center.GetZ() + radius * std::sin(angle1));
156 DrawLine(p0, p1, r, g, b, a);
157 }
158}
159
161 float r, float g, float b, float a,
162 int segments) {
163 Math::Vector3D pointA = capsule.GetPointA();
164 Math::Vector3D pointB = capsule.GetPointB();
165 float radius = capsule.radius;
166
167 // Draw connecting lines between the two hemispheres
168 float step = 2.0f * 3.14159265f / static_cast<float>(segments);
169
170 // Determine the perpendicular axes based on capsule axis
171 int ax = capsule.axis;
172 int ax1 = (ax + 1) % 3;
173 int ax2 = (ax + 2) % 3;
174
175 for (int i = 0; i < segments; ++i) {
176 float angle = step * i;
177 float c1 = radius * std::cos(angle);
178 float c2 = radius * std::sin(angle);
179
180 Math::Vector3D offset(0, 0, 0);
181 if (ax1 == 0) offset.SetX(c1); else if (ax1 == 1) offset.SetY(c1); else offset.SetZ(c1);
182 if (ax2 == 0) offset.SetX(c2); else if (ax2 == 1) offset.SetY(c2); else offset.SetZ(c2);
183
184 DrawLine(pointA + offset, pointB + offset, r, g, b, a);
185 }
186
187 // Draw circles at both ends
188 DrawSphere(pointA, radius, r, g, b, a, segments);
189 DrawSphere(pointB, radius, r, g, b, a, segments);
190}
191
193 if (!s_initialized || !s_vertices || s_vertices->empty()) {
194 if (s_vertices) s_vertices->clear();
195 return;
196 }
197
198 if (!camera) {
199 s_vertices->clear();
200 return;
201 }
202
203 uint32_t vertexCount = static_cast<uint32_t>(s_vertices->size());
204 if (vertexCount > MAX_VERTICES) vertexCount = MAX_VERTICES;
205
206 // Update constant buffer with ViewProjection
207 DebugLineCBData cbData;
209 s_constantBuffer->Update(&cbData, sizeof(DebugLineCBData));
210
211 // Update vertex buffer
212 s_vertexBuffer->Update(s_vertices->data(), vertexCount * sizeof(Vertex));
213
214 // Capture for lambda
215 auto shader = s_shader;
216 auto vb = s_vertexBuffer;
217 auto cb = s_constantBuffer;
218 uint32_t count = vertexCount;
219
221 [shader, vb, cb, count](RenderEngine::RenderContext* ctx) {
222 ctx->BeginDebugLinePass();
223
224 shader->bind();
225
226 ctx->BindConstantBuffer(cb, 0);
227 ctx->BindVertexBuffer(vb, 0);
228 ctx->Draw(count);
229
230 ctx->EndDebugLinePass();
231 });
232
233 s_vertices->clear();
234}
235
236} // namespace Sleak
#define SLEAK_ERROR(...)
Definition Logger.hpp:22
#define SLEAK_INFO(...)
Definition Logger.hpp:20
static const Math::Matrix4 & GetMainProjectionMatrix()
Definition Camera.hpp:107
static const Math::Matrix4 & GetMainViewMatrix()
Definition Camera.hpp:103
static void DrawLine(const Math::Vector3D &start, const Math::Vector3D &end, float r, float g, float b, float a=1.0f)
Queues a single line segment for the next Flush.
static void Flush(Camera *camera)
Uploads all queued lines and draws them in one pass, then clears the queue.
static void DrawSphere(const Math::Vector3D &center, float radius, float r, float g, float b, float a=1.0f, int segments=16)
Queues a wireframe sphere approximated with segments latitude/longitude rings.
static void DrawAABB(const Physics::AABB &aabb, float r, float g, float b, float a=1.0f)
Queues a wireframe box outline.
static void DrawCapsule(const Physics::BoundingCapsule &capsule, float r, float g, float b, float a=1.0f, int segments=16)
Queues a wireframe capsule outline.
static void Initialize()
Allocates the shared vertex buffer, shader, and constant buffer.
static Matrix< float, Rows, Rows > Identity()
Definition Matrix.hpp:203
float GetY() const
Definition Vector.hpp:361
void SetY(float val)
Definition Vector.hpp:366
float GetX() const
Definition Vector.hpp:360
float GetZ() const
Definition Vector.hpp:362
void SetX(float val)
Definition Vector.hpp:365
void SetZ(float val)
Definition Vector.hpp:367
void SubmitCustomCommand(CustomCommand::ExecuteFunction function)
Queues an arbitrary callback to run inline with other render commands.
static RenderCommandQueue * GetInstance()
Lazily creates and returns the process-wide singleton instance.
Abstract interface for high-level graphics command execution and resource management.
virtual void Draw(uint32_t vertexCount)=0
Non-indexed draw from the currently bound vertex buffer.
virtual void BindVertexBuffer(RefPtr< BufferBase > buffer, uint32_t slot=0)=0
virtual void BindConstantBuffer(RefPtr< BufferBase > buffer, uint32_t slot=0)=0
static Shader * CreateShader(const std::string &ShaderPath)
Compiles a shader via the currently registered backend factory.
static BufferBase * CreateBuffer(BufferType Type, uint32_t Size, void *Data)
Creates a buffer via the currently registered backend factory.
Matrix< float, 4, 4 > Matrix4
Definition Matrix.hpp:413
Root namespace for everything the engine exposes.
Definition Camera.hpp:10
Vector3D GetPointA() const
World position of the capsule's positive-axis cap center.
Vector3D GetPointB() const
World position of the capsule's negative-axis cap center.