1 // MIT License
2
3 // Copyright (c) 2019 Erin Catto
4
5 // Permission is hereby granted, free of charge, to any person obtaining a copy
6 // of this software and associated documentation files (the "Software"), to deal
7 // in the Software without restriction, including without limitation the rights
8 // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 // copies of the Software, and to permit persons to whom the Software is
10 // furnished to do so, subject to the following conditions:
11
12 // The above copyright notice and this permission notice shall be included in all
13 // copies or substantial portions of the Software.
14
15 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 // SOFTWARE.
22
23 #include "draw.h"
24 #include <stdio.h>
25 #include <stdarg.h>
26 #include <stdlib.h>
27
28 #include "imgui/imgui.h"
29
30 #define BUFFER_OFFSET(x) ((const void*) (x))
31
32 DebugDraw g_debugDraw;
33 Camera g_camera;
34
35 //
ConvertScreenToWorld(const b2Vec2 & ps)36 b2Vec2 Camera::ConvertScreenToWorld(const b2Vec2& ps)
37 {
38 float w = float(m_width);
39 float h = float(m_height);
40 float u = ps.x / w;
41 float v = (h - ps.y) / h;
42
43 float ratio = w / h;
44 b2Vec2 extents(ratio * 25.0f, 25.0f);
45 extents *= m_zoom;
46
47 b2Vec2 lower = m_center - extents;
48 b2Vec2 upper = m_center + extents;
49
50 b2Vec2 pw;
51 pw.x = (1.0f - u) * lower.x + u * upper.x;
52 pw.y = (1.0f - v) * lower.y + v * upper.y;
53 return pw;
54 }
55
56 //
ConvertWorldToScreen(const b2Vec2 & pw)57 b2Vec2 Camera::ConvertWorldToScreen(const b2Vec2& pw)
58 {
59 float w = float(m_width);
60 float h = float(m_height);
61 float ratio = w / h;
62 b2Vec2 extents(ratio * 25.0f, 25.0f);
63 extents *= m_zoom;
64
65 b2Vec2 lower = m_center - extents;
66 b2Vec2 upper = m_center + extents;
67
68 float u = (pw.x - lower.x) / (upper.x - lower.x);
69 float v = (pw.y - lower.y) / (upper.y - lower.y);
70
71 b2Vec2 ps;
72 ps.x = u * w;
73 ps.y = (1.0f - v) * h;
74 return ps;
75 }
76
77 // Convert from world coordinates to normalized device coordinates.
78 // http://www.songho.ca/opengl/gl_projectionmatrix.html
BuildProjectionMatrix(float * m,float zBias)79 void Camera::BuildProjectionMatrix(float* m, float zBias)
80 {
81 float w = float(m_width);
82 float h = float(m_height);
83 float ratio = w / h;
84 b2Vec2 extents(ratio * 25.0f, 25.0f);
85 extents *= m_zoom;
86
87 b2Vec2 lower = m_center - extents;
88 b2Vec2 upper = m_center + extents;
89
90 m[0] = 2.0f / (upper.x - lower.x);
91 m[1] = 0.0f;
92 m[2] = 0.0f;
93 m[3] = 0.0f;
94
95 m[4] = 0.0f;
96 m[5] = 2.0f / (upper.y - lower.y);
97 m[6] = 0.0f;
98 m[7] = 0.0f;
99
100 m[8] = 0.0f;
101 m[9] = 0.0f;
102 m[10] = 1.0f;
103 m[11] = 0.0f;
104
105 m[12] = -(upper.x + lower.x) / (upper.x - lower.x);
106 m[13] = -(upper.y + lower.y) / (upper.y - lower.y);
107 m[14] = zBias;
108 m[15] = 1.0f;
109 }
110
111 //
sCheckGLError()112 static void sCheckGLError()
113 {
114 GLenum errCode = glGetError();
115 if (errCode != GL_NO_ERROR)
116 {
117 fprintf(stderr, "OpenGL error = %d\n", errCode);
118 assert(false);
119 }
120 }
121
122 // Prints shader compilation errors
sPrintLog(GLuint object)123 static void sPrintLog(GLuint object)
124 {
125 GLint log_length = 0;
126 if (glIsShader(object))
127 glGetShaderiv(object, GL_INFO_LOG_LENGTH, &log_length);
128 else if (glIsProgram(object))
129 glGetProgramiv(object, GL_INFO_LOG_LENGTH, &log_length);
130 else
131 {
132 fprintf(stderr, "printlog: Not a shader or a program\n");
133 return;
134 }
135
136 char* log = (char*)malloc(log_length);
137
138 if (glIsShader(object))
139 glGetShaderInfoLog(object, log_length, NULL, log);
140 else if (glIsProgram(object))
141 glGetProgramInfoLog(object, log_length, NULL, log);
142
143 fprintf(stderr, "%s", log);
144 free(log);
145 }
146
147
148 //
sCreateShaderFromString(const char * source,GLenum type)149 static GLuint sCreateShaderFromString(const char* source, GLenum type)
150 {
151 GLuint res = glCreateShader(type);
152 const char* sources[] = { source };
153 glShaderSource(res, 1, sources, NULL);
154 glCompileShader(res);
155 GLint compile_ok = GL_FALSE;
156 glGetShaderiv(res, GL_COMPILE_STATUS, &compile_ok);
157 if (compile_ok == GL_FALSE)
158 {
159 fprintf(stderr, "Error compiling shader of type %d!\n", type);
160 sPrintLog(res);
161 glDeleteShader(res);
162 return 0;
163 }
164
165 return res;
166 }
167
168 //
sCreateShaderProgram(const char * vs,const char * fs)169 static GLuint sCreateShaderProgram(const char* vs, const char* fs)
170 {
171 GLuint vsId = sCreateShaderFromString(vs, GL_VERTEX_SHADER);
172 GLuint fsId = sCreateShaderFromString(fs, GL_FRAGMENT_SHADER);
173 assert(vsId != 0 && fsId != 0);
174
175 GLuint programId = glCreateProgram();
176 glAttachShader(programId, vsId);
177 glAttachShader(programId, fsId);
178 glBindFragDataLocation(programId, 0, "color");
179 glLinkProgram(programId);
180
181 glDeleteShader(vsId);
182 glDeleteShader(fsId);
183
184 GLint status = GL_FALSE;
185 glGetProgramiv(programId, GL_LINK_STATUS, &status);
186 assert(status != GL_FALSE);
187
188 return programId;
189 }
190
191 //
192 struct GLRenderPoints
193 {
CreateGLRenderPoints194 void Create()
195 {
196 const char* vs = \
197 "#version 330\n"
198 "uniform mat4 projectionMatrix;\n"
199 "layout(location = 0) in vec2 v_position;\n"
200 "layout(location = 1) in vec4 v_color;\n"
201 "layout(location = 2) in float v_size;\n"
202 "out vec4 f_color;\n"
203 "void main(void)\n"
204 "{\n"
205 " f_color = v_color;\n"
206 " gl_Position = projectionMatrix * vec4(v_position, 0.0f, 1.0f);\n"
207 " gl_PointSize = v_size;\n"
208 "}\n";
209
210 const char* fs = \
211 "#version 330\n"
212 "in vec4 f_color;\n"
213 "out vec4 color;\n"
214 "void main(void)\n"
215 "{\n"
216 " color = f_color;\n"
217 "}\n";
218
219 m_programId = sCreateShaderProgram(vs, fs);
220 m_projectionUniform = glGetUniformLocation(m_programId, "projectionMatrix");
221 m_vertexAttribute = 0;
222 m_colorAttribute = 1;
223 m_sizeAttribute = 2;
224
225 // Generate
226 glGenVertexArrays(1, &m_vaoId);
227 glGenBuffers(3, m_vboIds);
228
229 glBindVertexArray(m_vaoId);
230 glEnableVertexAttribArray(m_vertexAttribute);
231 glEnableVertexAttribArray(m_colorAttribute);
232 glEnableVertexAttribArray(m_sizeAttribute);
233
234 // Vertex buffer
235 glBindBuffer(GL_ARRAY_BUFFER, m_vboIds[0]);
236 glVertexAttribPointer(m_vertexAttribute, 2, GL_FLOAT, GL_FALSE, 0, BUFFER_OFFSET(0));
237 glBufferData(GL_ARRAY_BUFFER, sizeof(m_vertices), m_vertices, GL_DYNAMIC_DRAW);
238
239 glBindBuffer(GL_ARRAY_BUFFER, m_vboIds[1]);
240 glVertexAttribPointer(m_colorAttribute, 4, GL_FLOAT, GL_FALSE, 0, BUFFER_OFFSET(0));
241 glBufferData(GL_ARRAY_BUFFER, sizeof(m_colors), m_colors, GL_DYNAMIC_DRAW);
242
243 glBindBuffer(GL_ARRAY_BUFFER, m_vboIds[2]);
244 glVertexAttribPointer(m_sizeAttribute, 1, GL_FLOAT, GL_FALSE, 0, BUFFER_OFFSET(0));
245 glBufferData(GL_ARRAY_BUFFER, sizeof(m_sizes), m_sizes, GL_DYNAMIC_DRAW);
246
247 sCheckGLError();
248
249 // Cleanup
250 glBindBuffer(GL_ARRAY_BUFFER, 0);
251 glBindVertexArray(0);
252
253 m_count = 0;
254 }
255
DestroyGLRenderPoints256 void Destroy()
257 {
258 if (m_vaoId)
259 {
260 glDeleteVertexArrays(1, &m_vaoId);
261 glDeleteBuffers(3, m_vboIds);
262 m_vaoId = 0;
263 }
264
265 if (m_programId)
266 {
267 glDeleteProgram(m_programId);
268 m_programId = 0;
269 }
270 }
271
VertexGLRenderPoints272 void Vertex(const b2Vec2& v, const b2Color& c, float size)
273 {
274 if (m_count == e_maxVertices)
275 Flush();
276
277 m_vertices[m_count] = v;
278 m_colors[m_count] = c;
279 m_sizes[m_count] = size;
280 ++m_count;
281 }
282
FlushGLRenderPoints283 void Flush()
284 {
285 if (m_count == 0)
286 return;
287
288 glUseProgram(m_programId);
289
290 float proj[16] = { 0.0f };
291 g_camera.BuildProjectionMatrix(proj, 0.0f);
292
293 glUniformMatrix4fv(m_projectionUniform, 1, GL_FALSE, proj);
294
295 glBindVertexArray(m_vaoId);
296
297 glBindBuffer(GL_ARRAY_BUFFER, m_vboIds[0]);
298 glBufferSubData(GL_ARRAY_BUFFER, 0, m_count * sizeof(b2Vec2), m_vertices);
299
300 glBindBuffer(GL_ARRAY_BUFFER, m_vboIds[1]);
301 glBufferSubData(GL_ARRAY_BUFFER, 0, m_count * sizeof(b2Color), m_colors);
302
303 glBindBuffer(GL_ARRAY_BUFFER, m_vboIds[2]);
304 glBufferSubData(GL_ARRAY_BUFFER, 0, m_count * sizeof(float), m_sizes);
305
306 glEnable(GL_PROGRAM_POINT_SIZE);
307 glDrawArrays(GL_POINTS, 0, m_count);
308 glDisable(GL_PROGRAM_POINT_SIZE);
309
310 sCheckGLError();
311
312 glBindBuffer(GL_ARRAY_BUFFER, 0);
313 glBindVertexArray(0);
314 glUseProgram(0);
315
316 m_count = 0;
317 }
318
319 enum { e_maxVertices = 512 };
320 b2Vec2 m_vertices[e_maxVertices];
321 b2Color m_colors[e_maxVertices];
322 float m_sizes[e_maxVertices];
323
324 int32 m_count;
325
326 GLuint m_vaoId;
327 GLuint m_vboIds[3];
328 GLuint m_programId;
329 GLint m_projectionUniform;
330 GLint m_vertexAttribute;
331 GLint m_colorAttribute;
332 GLint m_sizeAttribute;
333 };
334
335 //
336 struct GLRenderLines
337 {
CreateGLRenderLines338 void Create()
339 {
340 const char* vs = \
341 "#version 330\n"
342 "uniform mat4 projectionMatrix;\n"
343 "layout(location = 0) in vec2 v_position;\n"
344 "layout(location = 1) in vec4 v_color;\n"
345 "out vec4 f_color;\n"
346 "void main(void)\n"
347 "{\n"
348 " f_color = v_color;\n"
349 " gl_Position = projectionMatrix * vec4(v_position, 0.0f, 1.0f);\n"
350 "}\n";
351
352 const char* fs = \
353 "#version 330\n"
354 "in vec4 f_color;\n"
355 "out vec4 color;\n"
356 "void main(void)\n"
357 "{\n"
358 " color = f_color;\n"
359 "}\n";
360
361 m_programId = sCreateShaderProgram(vs, fs);
362 m_projectionUniform = glGetUniformLocation(m_programId, "projectionMatrix");
363 m_vertexAttribute = 0;
364 m_colorAttribute = 1;
365
366 // Generate
367 glGenVertexArrays(1, &m_vaoId);
368 glGenBuffers(2, m_vboIds);
369
370 glBindVertexArray(m_vaoId);
371 glEnableVertexAttribArray(m_vertexAttribute);
372 glEnableVertexAttribArray(m_colorAttribute);
373
374 // Vertex buffer
375 glBindBuffer(GL_ARRAY_BUFFER, m_vboIds[0]);
376 glVertexAttribPointer(m_vertexAttribute, 2, GL_FLOAT, GL_FALSE, 0, BUFFER_OFFSET(0));
377 glBufferData(GL_ARRAY_BUFFER, sizeof(m_vertices), m_vertices, GL_DYNAMIC_DRAW);
378
379 glBindBuffer(GL_ARRAY_BUFFER, m_vboIds[1]);
380 glVertexAttribPointer(m_colorAttribute, 4, GL_FLOAT, GL_FALSE, 0, BUFFER_OFFSET(0));
381 glBufferData(GL_ARRAY_BUFFER, sizeof(m_colors), m_colors, GL_DYNAMIC_DRAW);
382
383 sCheckGLError();
384
385 // Cleanup
386 glBindBuffer(GL_ARRAY_BUFFER, 0);
387 glBindVertexArray(0);
388
389 m_count = 0;
390 }
391
DestroyGLRenderLines392 void Destroy()
393 {
394 if (m_vaoId)
395 {
396 glDeleteVertexArrays(1, &m_vaoId);
397 glDeleteBuffers(2, m_vboIds);
398 m_vaoId = 0;
399 }
400
401 if (m_programId)
402 {
403 glDeleteProgram(m_programId);
404 m_programId = 0;
405 }
406 }
407
VertexGLRenderLines408 void Vertex(const b2Vec2& v, const b2Color& c)
409 {
410 if (m_count == e_maxVertices)
411 Flush();
412
413 m_vertices[m_count] = v;
414 m_colors[m_count] = c;
415 ++m_count;
416 }
417
FlushGLRenderLines418 void Flush()
419 {
420 if (m_count == 0)
421 return;
422
423 glUseProgram(m_programId);
424
425 float proj[16] = { 0.0f };
426 g_camera.BuildProjectionMatrix(proj, 0.1f);
427
428 glUniformMatrix4fv(m_projectionUniform, 1, GL_FALSE, proj);
429
430 glBindVertexArray(m_vaoId);
431
432 glBindBuffer(GL_ARRAY_BUFFER, m_vboIds[0]);
433 glBufferSubData(GL_ARRAY_BUFFER, 0, m_count * sizeof(b2Vec2), m_vertices);
434
435 glBindBuffer(GL_ARRAY_BUFFER, m_vboIds[1]);
436 glBufferSubData(GL_ARRAY_BUFFER, 0, m_count * sizeof(b2Color), m_colors);
437
438 glDrawArrays(GL_LINES, 0, m_count);
439
440 sCheckGLError();
441
442 glBindBuffer(GL_ARRAY_BUFFER, 0);
443 glBindVertexArray(0);
444 glUseProgram(0);
445
446 m_count = 0;
447 }
448
449 enum { e_maxVertices = 2 * 512 };
450 b2Vec2 m_vertices[e_maxVertices];
451 b2Color m_colors[e_maxVertices];
452
453 int32 m_count;
454
455 GLuint m_vaoId;
456 GLuint m_vboIds[2];
457 GLuint m_programId;
458 GLint m_projectionUniform;
459 GLint m_vertexAttribute;
460 GLint m_colorAttribute;
461 };
462
463 //
464 struct GLRenderTriangles
465 {
CreateGLRenderTriangles466 void Create()
467 {
468 const char* vs = \
469 "#version 330\n"
470 "uniform mat4 projectionMatrix;\n"
471 "layout(location = 0) in vec2 v_position;\n"
472 "layout(location = 1) in vec4 v_color;\n"
473 "out vec4 f_color;\n"
474 "void main(void)\n"
475 "{\n"
476 " f_color = v_color;\n"
477 " gl_Position = projectionMatrix * vec4(v_position, 0.0f, 1.0f);\n"
478 "}\n";
479
480 const char* fs = \
481 "#version 330\n"
482 "in vec4 f_color;\n"
483 "out vec4 color;\n"
484 "void main(void)\n"
485 "{\n"
486 " color = f_color;\n"
487 "}\n";
488
489 m_programId = sCreateShaderProgram(vs, fs);
490 m_projectionUniform = glGetUniformLocation(m_programId, "projectionMatrix");
491 m_vertexAttribute = 0;
492 m_colorAttribute = 1;
493
494 // Generate
495 glGenVertexArrays(1, &m_vaoId);
496 glGenBuffers(2, m_vboIds);
497
498 glBindVertexArray(m_vaoId);
499 glEnableVertexAttribArray(m_vertexAttribute);
500 glEnableVertexAttribArray(m_colorAttribute);
501
502 // Vertex buffer
503 glBindBuffer(GL_ARRAY_BUFFER, m_vboIds[0]);
504 glVertexAttribPointer(m_vertexAttribute, 2, GL_FLOAT, GL_FALSE, 0, BUFFER_OFFSET(0));
505 glBufferData(GL_ARRAY_BUFFER, sizeof(m_vertices), m_vertices, GL_DYNAMIC_DRAW);
506
507 glBindBuffer(GL_ARRAY_BUFFER, m_vboIds[1]);
508 glVertexAttribPointer(m_colorAttribute, 4, GL_FLOAT, GL_FALSE, 0, BUFFER_OFFSET(0));
509 glBufferData(GL_ARRAY_BUFFER, sizeof(m_colors), m_colors, GL_DYNAMIC_DRAW);
510
511 sCheckGLError();
512
513 // Cleanup
514 glBindBuffer(GL_ARRAY_BUFFER, 0);
515 glBindVertexArray(0);
516
517 m_count = 0;
518 }
519
DestroyGLRenderTriangles520 void Destroy()
521 {
522 if (m_vaoId)
523 {
524 glDeleteVertexArrays(1, &m_vaoId);
525 glDeleteBuffers(2, m_vboIds);
526 m_vaoId = 0;
527 }
528
529 if (m_programId)
530 {
531 glDeleteProgram(m_programId);
532 m_programId = 0;
533 }
534 }
535
VertexGLRenderTriangles536 void Vertex(const b2Vec2& v, const b2Color& c)
537 {
538 if (m_count == e_maxVertices)
539 Flush();
540
541 m_vertices[m_count] = v;
542 m_colors[m_count] = c;
543 ++m_count;
544 }
545
FlushGLRenderTriangles546 void Flush()
547 {
548 if (m_count == 0)
549 return;
550
551 glUseProgram(m_programId);
552
553 float proj[16] = { 0.0f };
554 g_camera.BuildProjectionMatrix(proj, 0.2f);
555
556 glUniformMatrix4fv(m_projectionUniform, 1, GL_FALSE, proj);
557
558 glBindVertexArray(m_vaoId);
559
560 glBindBuffer(GL_ARRAY_BUFFER, m_vboIds[0]);
561 glBufferSubData(GL_ARRAY_BUFFER, 0, m_count * sizeof(b2Vec2), m_vertices);
562
563 glBindBuffer(GL_ARRAY_BUFFER, m_vboIds[1]);
564 glBufferSubData(GL_ARRAY_BUFFER, 0, m_count * sizeof(b2Color), m_colors);
565
566 glEnable(GL_BLEND);
567 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
568 glDrawArrays(GL_TRIANGLES, 0, m_count);
569 glDisable(GL_BLEND);
570
571 sCheckGLError();
572
573 glBindBuffer(GL_ARRAY_BUFFER, 0);
574 glBindVertexArray(0);
575 glUseProgram(0);
576
577 m_count = 0;
578 }
579
580 enum { e_maxVertices = 3 * 512 };
581 b2Vec2 m_vertices[e_maxVertices];
582 b2Color m_colors[e_maxVertices];
583
584 int32 m_count;
585
586 GLuint m_vaoId;
587 GLuint m_vboIds[2];
588 GLuint m_programId;
589 GLint m_projectionUniform;
590 GLint m_vertexAttribute;
591 GLint m_colorAttribute;
592 };
593
594 //
DebugDraw()595 DebugDraw::DebugDraw()
596 {
597 m_showUI = true;
598 m_points = NULL;
599 m_lines = NULL;
600 m_triangles = NULL;
601 }
602
603 //
~DebugDraw()604 DebugDraw::~DebugDraw()
605 {
606 b2Assert(m_points == NULL);
607 b2Assert(m_lines == NULL);
608 b2Assert(m_triangles == NULL);
609 }
610
611 //
Create()612 void DebugDraw::Create()
613 {
614 m_points = new GLRenderPoints;
615 m_points->Create();
616 m_lines = new GLRenderLines;
617 m_lines->Create();
618 m_triangles = new GLRenderTriangles;
619 m_triangles->Create();
620 }
621
622 //
Destroy()623 void DebugDraw::Destroy()
624 {
625 m_points->Destroy();
626 delete m_points;
627 m_points = NULL;
628
629 m_lines->Destroy();
630 delete m_lines;
631 m_lines = NULL;
632
633 m_triangles->Destroy();
634 delete m_triangles;
635 m_triangles = NULL;
636 }
637
638 //
DrawPolygon(const b2Vec2 * vertices,int32 vertexCount,const b2Color & color)639 void DebugDraw::DrawPolygon(const b2Vec2* vertices, int32 vertexCount, const b2Color& color)
640 {
641 b2Vec2 p1 = vertices[vertexCount - 1];
642 for (int32 i = 0; i < vertexCount; ++i)
643 {
644 b2Vec2 p2 = vertices[i];
645 m_lines->Vertex(p1, color);
646 m_lines->Vertex(p2, color);
647 p1 = p2;
648 }
649 }
650
651 //
DrawSolidPolygon(const b2Vec2 * vertices,int32 vertexCount,const b2Color & color)652 void DebugDraw::DrawSolidPolygon(const b2Vec2* vertices, int32 vertexCount, const b2Color& color)
653 {
654 b2Color fillColor(0.5f * color.r, 0.5f * color.g, 0.5f * color.b, 0.5f);
655
656 for (int32 i = 1; i < vertexCount - 1; ++i)
657 {
658 m_triangles->Vertex(vertices[0], fillColor);
659 m_triangles->Vertex(vertices[i], fillColor);
660 m_triangles->Vertex(vertices[i + 1], fillColor);
661 }
662
663 b2Vec2 p1 = vertices[vertexCount - 1];
664 for (int32 i = 0; i < vertexCount; ++i)
665 {
666 b2Vec2 p2 = vertices[i];
667 m_lines->Vertex(p1, color);
668 m_lines->Vertex(p2, color);
669 p1 = p2;
670 }
671 }
672
673 //
DrawCircle(const b2Vec2 & center,float radius,const b2Color & color)674 void DebugDraw::DrawCircle(const b2Vec2& center, float radius, const b2Color& color)
675 {
676 const float k_segments = 16.0f;
677 const float k_increment = 2.0f * b2_pi / k_segments;
678 float sinInc = sinf(k_increment);
679 float cosInc = cosf(k_increment);
680 b2Vec2 r1(1.0f, 0.0f);
681 b2Vec2 v1 = center + radius * r1;
682 for (int32 i = 0; i < k_segments; ++i)
683 {
684 // Perform rotation to avoid additional trigonometry.
685 b2Vec2 r2;
686 r2.x = cosInc * r1.x - sinInc * r1.y;
687 r2.y = sinInc * r1.x + cosInc * r1.y;
688 b2Vec2 v2 = center + radius * r2;
689 m_lines->Vertex(v1, color);
690 m_lines->Vertex(v2, color);
691 r1 = r2;
692 v1 = v2;
693 }
694 }
695
696 //
DrawSolidCircle(const b2Vec2 & center,float radius,const b2Vec2 & axis,const b2Color & color)697 void DebugDraw::DrawSolidCircle(const b2Vec2& center, float radius, const b2Vec2& axis, const b2Color& color)
698 {
699 const float k_segments = 16.0f;
700 const float k_increment = 2.0f * b2_pi / k_segments;
701 float sinInc = sinf(k_increment);
702 float cosInc = cosf(k_increment);
703 b2Vec2 v0 = center;
704 b2Vec2 r1(cosInc, sinInc);
705 b2Vec2 v1 = center + radius * r1;
706 b2Color fillColor(0.5f * color.r, 0.5f * color.g, 0.5f * color.b, 0.5f);
707 for (int32 i = 0; i < k_segments; ++i)
708 {
709 // Perform rotation to avoid additional trigonometry.
710 b2Vec2 r2;
711 r2.x = cosInc * r1.x - sinInc * r1.y;
712 r2.y = sinInc * r1.x + cosInc * r1.y;
713 b2Vec2 v2 = center + radius * r2;
714 m_triangles->Vertex(v0, fillColor);
715 m_triangles->Vertex(v1, fillColor);
716 m_triangles->Vertex(v2, fillColor);
717 r1 = r2;
718 v1 = v2;
719 }
720
721 r1.Set(1.0f, 0.0f);
722 v1 = center + radius * r1;
723 for (int32 i = 0; i < k_segments; ++i)
724 {
725 b2Vec2 r2;
726 r2.x = cosInc * r1.x - sinInc * r1.y;
727 r2.y = sinInc * r1.x + cosInc * r1.y;
728 b2Vec2 v2 = center + radius * r2;
729 m_lines->Vertex(v1, color);
730 m_lines->Vertex(v2, color);
731 r1 = r2;
732 v1 = v2;
733 }
734
735 // Draw a line fixed in the circle to animate rotation.
736 b2Vec2 p = center + radius * axis;
737 m_lines->Vertex(center, color);
738 m_lines->Vertex(p, color);
739 }
740
741 //
DrawSegment(const b2Vec2 & p1,const b2Vec2 & p2,const b2Color & color)742 void DebugDraw::DrawSegment(const b2Vec2& p1, const b2Vec2& p2, const b2Color& color)
743 {
744 m_lines->Vertex(p1, color);
745 m_lines->Vertex(p2, color);
746 }
747
748 //
DrawTransform(const b2Transform & xf)749 void DebugDraw::DrawTransform(const b2Transform& xf)
750 {
751 const float k_axisScale = 0.4f;
752 b2Color red(1.0f, 0.0f, 0.0f);
753 b2Color green(0.0f, 1.0f, 0.0f);
754 b2Vec2 p1 = xf.p, p2;
755
756 m_lines->Vertex(p1, red);
757 p2 = p1 + k_axisScale * xf.q.GetXAxis();
758 m_lines->Vertex(p2, red);
759
760 m_lines->Vertex(p1, green);
761 p2 = p1 + k_axisScale * xf.q.GetYAxis();
762 m_lines->Vertex(p2, green);
763 }
764
765 //
DrawPoint(const b2Vec2 & p,float size,const b2Color & color)766 void DebugDraw::DrawPoint(const b2Vec2& p, float size, const b2Color& color)
767 {
768 m_points->Vertex(p, color, size);
769 }
770
771 //
DrawString(int x,int y,const char * string,...)772 void DebugDraw::DrawString(int x, int y, const char* string, ...)
773 {
774 if (m_showUI == false)
775 {
776 return;
777 }
778
779 va_list arg;
780 va_start(arg, string);
781 ImGui::Begin("Overlay", NULL, ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoInputs | ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_NoScrollbar);
782 ImGui::SetCursorPos(ImVec2(float(x), float(y)));
783 ImGui::TextColoredV(ImColor(230, 153, 153, 255), string, arg);
784 ImGui::End();
785 va_end(arg);
786 }
787
788 //
DrawString(const b2Vec2 & pw,const char * string,...)789 void DebugDraw::DrawString(const b2Vec2& pw, const char* string, ...)
790 {
791 b2Vec2 ps = g_camera.ConvertWorldToScreen(pw);
792
793 va_list arg;
794 va_start(arg, string);
795 ImGui::Begin("Overlay", NULL, ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoInputs | ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_NoScrollbar);
796 ImGui::SetCursorPos(ImVec2(ps.x, ps.y));
797 ImGui::TextColoredV(ImColor(230, 153, 153, 255), string, arg);
798 ImGui::End();
799 va_end(arg);
800 }
801
802 //
DrawAABB(b2AABB * aabb,const b2Color & c)803 void DebugDraw::DrawAABB(b2AABB* aabb, const b2Color& c)
804 {
805 b2Vec2 p1 = aabb->lowerBound;
806 b2Vec2 p2 = b2Vec2(aabb->upperBound.x, aabb->lowerBound.y);
807 b2Vec2 p3 = aabb->upperBound;
808 b2Vec2 p4 = b2Vec2(aabb->lowerBound.x, aabb->upperBound.y);
809
810 m_lines->Vertex(p1, c);
811 m_lines->Vertex(p2, c);
812
813 m_lines->Vertex(p2, c);
814 m_lines->Vertex(p3, c);
815
816 m_lines->Vertex(p3, c);
817 m_lines->Vertex(p4, c);
818
819 m_lines->Vertex(p4, c);
820 m_lines->Vertex(p1, c);
821 }
822
823 //
Flush()824 void DebugDraw::Flush()
825 {
826 m_triangles->Flush();
827 m_lines->Flush();
828 m_points->Flush();
829 }
830