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