summaryrefslogtreecommitdiff
path: root/Client/ThirdParty/Box2D/testbed/draw.cpp
diff options
context:
space:
mode:
authorchai <chaifix@163.com>2021-12-13 00:07:19 +0800
committerchai <chaifix@163.com>2021-12-13 00:07:19 +0800
commit60cbbdec07ab7a5636eac5b3c024ae44e937f4d4 (patch)
treeb2c7b0a868f18159dbc43d8954e1bd7668549a88 /Client/ThirdParty/Box2D/testbed/draw.cpp
+init
Diffstat (limited to 'Client/ThirdParty/Box2D/testbed/draw.cpp')
-rw-r--r--Client/ThirdParty/Box2D/testbed/draw.cpp829
1 files changed, 829 insertions, 0 deletions
diff --git a/Client/ThirdParty/Box2D/testbed/draw.cpp b/Client/ThirdParty/Box2D/testbed/draw.cpp
new file mode 100644
index 0000000..03ab6af
--- /dev/null
+++ b/Client/ThirdParty/Box2D/testbed/draw.cpp
@@ -0,0 +1,829 @@
+// MIT License
+
+// Copyright (c) 2019 Erin Catto
+
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+
+// The above copyright notice and this permission notice shall be included in all
+// copies or substantial portions of the Software.
+
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+// SOFTWARE.
+
+#include "draw.h"
+#include <stdio.h>
+#include <stdarg.h>
+#include <stdlib.h>
+
+#include "imgui/imgui.h"
+
+#define BUFFER_OFFSET(x) ((const void*) (x))
+
+DebugDraw g_debugDraw;
+Camera g_camera;
+
+//
+b2Vec2 Camera::ConvertScreenToWorld(const b2Vec2& ps)
+{
+ float w = float(m_width);
+ float h = float(m_height);
+ float u = ps.x / w;
+ float v = (h - ps.y) / h;
+
+ float ratio = w / h;
+ b2Vec2 extents(ratio * 25.0f, 25.0f);
+ extents *= m_zoom;
+
+ b2Vec2 lower = m_center - extents;
+ b2Vec2 upper = m_center + extents;
+
+ b2Vec2 pw;
+ pw.x = (1.0f - u) * lower.x + u * upper.x;
+ pw.y = (1.0f - v) * lower.y + v * upper.y;
+ return pw;
+}
+
+//
+b2Vec2 Camera::ConvertWorldToScreen(const b2Vec2& pw)
+{
+ float w = float(m_width);
+ float h = float(m_height);
+ float ratio = w / h;
+ b2Vec2 extents(ratio * 25.0f, 25.0f);
+ extents *= m_zoom;
+
+ b2Vec2 lower = m_center - extents;
+ b2Vec2 upper = m_center + extents;
+
+ float u = (pw.x - lower.x) / (upper.x - lower.x);
+ float v = (pw.y - lower.y) / (upper.y - lower.y);
+
+ b2Vec2 ps;
+ ps.x = u * w;
+ ps.y = (1.0f - v) * h;
+ return ps;
+}
+
+// Convert from world coordinates to normalized device coordinates.
+// http://www.songho.ca/opengl/gl_projectionmatrix.html
+void Camera::BuildProjectionMatrix(float* m, float zBias)
+{
+ float w = float(m_width);
+ float h = float(m_height);
+ float ratio = w / h;
+ b2Vec2 extents(ratio * 25.0f, 25.0f);
+ extents *= m_zoom;
+
+ b2Vec2 lower = m_center - extents;
+ b2Vec2 upper = m_center + extents;
+
+ m[0] = 2.0f / (upper.x - lower.x);
+ m[1] = 0.0f;
+ m[2] = 0.0f;
+ m[3] = 0.0f;
+
+ m[4] = 0.0f;
+ m[5] = 2.0f / (upper.y - lower.y);
+ m[6] = 0.0f;
+ m[7] = 0.0f;
+
+ m[8] = 0.0f;
+ m[9] = 0.0f;
+ m[10] = 1.0f;
+ m[11] = 0.0f;
+
+ m[12] = -(upper.x + lower.x) / (upper.x - lower.x);
+ m[13] = -(upper.y + lower.y) / (upper.y - lower.y);
+ m[14] = zBias;
+ m[15] = 1.0f;
+}
+
+//
+static void sCheckGLError()
+{
+ GLenum errCode = glGetError();
+ if (errCode != GL_NO_ERROR)
+ {
+ fprintf(stderr, "OpenGL error = %d\n", errCode);
+ assert(false);
+ }
+}
+
+// Prints shader compilation errors
+static void sPrintLog(GLuint object)
+{
+ GLint log_length = 0;
+ if (glIsShader(object))
+ glGetShaderiv(object, GL_INFO_LOG_LENGTH, &log_length);
+ else if (glIsProgram(object))
+ glGetProgramiv(object, GL_INFO_LOG_LENGTH, &log_length);
+ else
+ {
+ fprintf(stderr, "printlog: Not a shader or a program\n");
+ return;
+ }
+
+ char* log = (char*)malloc(log_length);
+
+ if (glIsShader(object))
+ glGetShaderInfoLog(object, log_length, NULL, log);
+ else if (glIsProgram(object))
+ glGetProgramInfoLog(object, log_length, NULL, log);
+
+ fprintf(stderr, "%s", log);
+ free(log);
+}
+
+
+//
+static GLuint sCreateShaderFromString(const char* source, GLenum type)
+{
+ GLuint res = glCreateShader(type);
+ const char* sources[] = { source };
+ glShaderSource(res, 1, sources, NULL);
+ glCompileShader(res);
+ GLint compile_ok = GL_FALSE;
+ glGetShaderiv(res, GL_COMPILE_STATUS, &compile_ok);
+ if (compile_ok == GL_FALSE)
+ {
+ fprintf(stderr, "Error compiling shader of type %d!\n", type);
+ sPrintLog(res);
+ glDeleteShader(res);
+ return 0;
+ }
+
+ return res;
+}
+
+//
+static GLuint sCreateShaderProgram(const char* vs, const char* fs)
+{
+ GLuint vsId = sCreateShaderFromString(vs, GL_VERTEX_SHADER);
+ GLuint fsId = sCreateShaderFromString(fs, GL_FRAGMENT_SHADER);
+ assert(vsId != 0 && fsId != 0);
+
+ GLuint programId = glCreateProgram();
+ glAttachShader(programId, vsId);
+ glAttachShader(programId, fsId);
+ glBindFragDataLocation(programId, 0, "color");
+ glLinkProgram(programId);
+
+ glDeleteShader(vsId);
+ glDeleteShader(fsId);
+
+ GLint status = GL_FALSE;
+ glGetProgramiv(programId, GL_LINK_STATUS, &status);
+ assert(status != GL_FALSE);
+
+ return programId;
+}
+
+//
+struct GLRenderPoints
+{
+ void Create()
+ {
+ const char* vs = \
+ "#version 330\n"
+ "uniform mat4 projectionMatrix;\n"
+ "layout(location = 0) in vec2 v_position;\n"
+ "layout(location = 1) in vec4 v_color;\n"
+ "layout(location = 2) in float v_size;\n"
+ "out vec4 f_color;\n"
+ "void main(void)\n"
+ "{\n"
+ " f_color = v_color;\n"
+ " gl_Position = projectionMatrix * vec4(v_position, 0.0f, 1.0f);\n"
+ " gl_PointSize = v_size;\n"
+ "}\n";
+
+ const char* fs = \
+ "#version 330\n"
+ "in vec4 f_color;\n"
+ "out vec4 color;\n"
+ "void main(void)\n"
+ "{\n"
+ " color = f_color;\n"
+ "}\n";
+
+ m_programId = sCreateShaderProgram(vs, fs);
+ m_projectionUniform = glGetUniformLocation(m_programId, "projectionMatrix");
+ m_vertexAttribute = 0;
+ m_colorAttribute = 1;
+ m_sizeAttribute = 2;
+
+ // Generate
+ glGenVertexArrays(1, &m_vaoId);
+ glGenBuffers(3, m_vboIds);
+
+ glBindVertexArray(m_vaoId);
+ glEnableVertexAttribArray(m_vertexAttribute);
+ glEnableVertexAttribArray(m_colorAttribute);
+ glEnableVertexAttribArray(m_sizeAttribute);
+
+ // Vertex buffer
+ glBindBuffer(GL_ARRAY_BUFFER, m_vboIds[0]);
+ glVertexAttribPointer(m_vertexAttribute, 2, GL_FLOAT, GL_FALSE, 0, BUFFER_OFFSET(0));
+ glBufferData(GL_ARRAY_BUFFER, sizeof(m_vertices), m_vertices, GL_DYNAMIC_DRAW);
+
+ glBindBuffer(GL_ARRAY_BUFFER, m_vboIds[1]);
+ glVertexAttribPointer(m_colorAttribute, 4, GL_FLOAT, GL_FALSE, 0, BUFFER_OFFSET(0));
+ glBufferData(GL_ARRAY_BUFFER, sizeof(m_colors), m_colors, GL_DYNAMIC_DRAW);
+
+ glBindBuffer(GL_ARRAY_BUFFER, m_vboIds[2]);
+ glVertexAttribPointer(m_sizeAttribute, 1, GL_FLOAT, GL_FALSE, 0, BUFFER_OFFSET(0));
+ glBufferData(GL_ARRAY_BUFFER, sizeof(m_sizes), m_sizes, GL_DYNAMIC_DRAW);
+
+ sCheckGLError();
+
+ // Cleanup
+ glBindBuffer(GL_ARRAY_BUFFER, 0);
+ glBindVertexArray(0);
+
+ m_count = 0;
+ }
+
+ void Destroy()
+ {
+ if (m_vaoId)
+ {
+ glDeleteVertexArrays(1, &m_vaoId);
+ glDeleteBuffers(3, m_vboIds);
+ m_vaoId = 0;
+ }
+
+ if (m_programId)
+ {
+ glDeleteProgram(m_programId);
+ m_programId = 0;
+ }
+ }
+
+ void Vertex(const b2Vec2& v, const b2Color& c, float size)
+ {
+ if (m_count == e_maxVertices)
+ Flush();
+
+ m_vertices[m_count] = v;
+ m_colors[m_count] = c;
+ m_sizes[m_count] = size;
+ ++m_count;
+ }
+
+ void Flush()
+ {
+ if (m_count == 0)
+ return;
+
+ glUseProgram(m_programId);
+
+ float proj[16] = { 0.0f };
+ g_camera.BuildProjectionMatrix(proj, 0.0f);
+
+ glUniformMatrix4fv(m_projectionUniform, 1, GL_FALSE, proj);
+
+ glBindVertexArray(m_vaoId);
+
+ glBindBuffer(GL_ARRAY_BUFFER, m_vboIds[0]);
+ glBufferSubData(GL_ARRAY_BUFFER, 0, m_count * sizeof(b2Vec2), m_vertices);
+
+ glBindBuffer(GL_ARRAY_BUFFER, m_vboIds[1]);
+ glBufferSubData(GL_ARRAY_BUFFER, 0, m_count * sizeof(b2Color), m_colors);
+
+ glBindBuffer(GL_ARRAY_BUFFER, m_vboIds[2]);
+ glBufferSubData(GL_ARRAY_BUFFER, 0, m_count * sizeof(float), m_sizes);
+
+ glEnable(GL_PROGRAM_POINT_SIZE);
+ glDrawArrays(GL_POINTS, 0, m_count);
+ glDisable(GL_PROGRAM_POINT_SIZE);
+
+ sCheckGLError();
+
+ glBindBuffer(GL_ARRAY_BUFFER, 0);
+ glBindVertexArray(0);
+ glUseProgram(0);
+
+ m_count = 0;
+ }
+
+ enum { e_maxVertices = 512 };
+ b2Vec2 m_vertices[e_maxVertices];
+ b2Color m_colors[e_maxVertices];
+ float m_sizes[e_maxVertices];
+
+ int32 m_count;
+
+ GLuint m_vaoId;
+ GLuint m_vboIds[3];
+ GLuint m_programId;
+ GLint m_projectionUniform;
+ GLint m_vertexAttribute;
+ GLint m_colorAttribute;
+ GLint m_sizeAttribute;
+};
+
+//
+struct GLRenderLines
+{
+ void Create()
+ {
+ const char* vs = \
+ "#version 330\n"
+ "uniform mat4 projectionMatrix;\n"
+ "layout(location = 0) in vec2 v_position;\n"
+ "layout(location = 1) in vec4 v_color;\n"
+ "out vec4 f_color;\n"
+ "void main(void)\n"
+ "{\n"
+ " f_color = v_color;\n"
+ " gl_Position = projectionMatrix * vec4(v_position, 0.0f, 1.0f);\n"
+ "}\n";
+
+ const char* fs = \
+ "#version 330\n"
+ "in vec4 f_color;\n"
+ "out vec4 color;\n"
+ "void main(void)\n"
+ "{\n"
+ " color = f_color;\n"
+ "}\n";
+
+ m_programId = sCreateShaderProgram(vs, fs);
+ m_projectionUniform = glGetUniformLocation(m_programId, "projectionMatrix");
+ m_vertexAttribute = 0;
+ m_colorAttribute = 1;
+
+ // Generate
+ glGenVertexArrays(1, &m_vaoId);
+ glGenBuffers(2, m_vboIds);
+
+ glBindVertexArray(m_vaoId);
+ glEnableVertexAttribArray(m_vertexAttribute);
+ glEnableVertexAttribArray(m_colorAttribute);
+
+ // Vertex buffer
+ glBindBuffer(GL_ARRAY_BUFFER, m_vboIds[0]);
+ glVertexAttribPointer(m_vertexAttribute, 2, GL_FLOAT, GL_FALSE, 0, BUFFER_OFFSET(0));
+ glBufferData(GL_ARRAY_BUFFER, sizeof(m_vertices), m_vertices, GL_DYNAMIC_DRAW);
+
+ glBindBuffer(GL_ARRAY_BUFFER, m_vboIds[1]);
+ glVertexAttribPointer(m_colorAttribute, 4, GL_FLOAT, GL_FALSE, 0, BUFFER_OFFSET(0));
+ glBufferData(GL_ARRAY_BUFFER, sizeof(m_colors), m_colors, GL_DYNAMIC_DRAW);
+
+ sCheckGLError();
+
+ // Cleanup
+ glBindBuffer(GL_ARRAY_BUFFER, 0);
+ glBindVertexArray(0);
+
+ m_count = 0;
+ }
+
+ void Destroy()
+ {
+ if (m_vaoId)
+ {
+ glDeleteVertexArrays(1, &m_vaoId);
+ glDeleteBuffers(2, m_vboIds);
+ m_vaoId = 0;
+ }
+
+ if (m_programId)
+ {
+ glDeleteProgram(m_programId);
+ m_programId = 0;
+ }
+ }
+
+ void Vertex(const b2Vec2& v, const b2Color& c)
+ {
+ if (m_count == e_maxVertices)
+ Flush();
+
+ m_vertices[m_count] = v;
+ m_colors[m_count] = c;
+ ++m_count;
+ }
+
+ void Flush()
+ {
+ if (m_count == 0)
+ return;
+
+ glUseProgram(m_programId);
+
+ float proj[16] = { 0.0f };
+ g_camera.BuildProjectionMatrix(proj, 0.1f);
+
+ glUniformMatrix4fv(m_projectionUniform, 1, GL_FALSE, proj);
+
+ glBindVertexArray(m_vaoId);
+
+ glBindBuffer(GL_ARRAY_BUFFER, m_vboIds[0]);
+ glBufferSubData(GL_ARRAY_BUFFER, 0, m_count * sizeof(b2Vec2), m_vertices);
+
+ glBindBuffer(GL_ARRAY_BUFFER, m_vboIds[1]);
+ glBufferSubData(GL_ARRAY_BUFFER, 0, m_count * sizeof(b2Color), m_colors);
+
+ glDrawArrays(GL_LINES, 0, m_count);
+
+ sCheckGLError();
+
+ glBindBuffer(GL_ARRAY_BUFFER, 0);
+ glBindVertexArray(0);
+ glUseProgram(0);
+
+ m_count = 0;
+ }
+
+ enum { e_maxVertices = 2 * 512 };
+ b2Vec2 m_vertices[e_maxVertices];
+ b2Color m_colors[e_maxVertices];
+
+ int32 m_count;
+
+ GLuint m_vaoId;
+ GLuint m_vboIds[2];
+ GLuint m_programId;
+ GLint m_projectionUniform;
+ GLint m_vertexAttribute;
+ GLint m_colorAttribute;
+};
+
+//
+struct GLRenderTriangles
+{
+ void Create()
+ {
+ const char* vs = \
+ "#version 330\n"
+ "uniform mat4 projectionMatrix;\n"
+ "layout(location = 0) in vec2 v_position;\n"
+ "layout(location = 1) in vec4 v_color;\n"
+ "out vec4 f_color;\n"
+ "void main(void)\n"
+ "{\n"
+ " f_color = v_color;\n"
+ " gl_Position = projectionMatrix * vec4(v_position, 0.0f, 1.0f);\n"
+ "}\n";
+
+ const char* fs = \
+ "#version 330\n"
+ "in vec4 f_color;\n"
+ "out vec4 color;\n"
+ "void main(void)\n"
+ "{\n"
+ " color = f_color;\n"
+ "}\n";
+
+ m_programId = sCreateShaderProgram(vs, fs);
+ m_projectionUniform = glGetUniformLocation(m_programId, "projectionMatrix");
+ m_vertexAttribute = 0;
+ m_colorAttribute = 1;
+
+ // Generate
+ glGenVertexArrays(1, &m_vaoId);
+ glGenBuffers(2, m_vboIds);
+
+ glBindVertexArray(m_vaoId);
+ glEnableVertexAttribArray(m_vertexAttribute);
+ glEnableVertexAttribArray(m_colorAttribute);
+
+ // Vertex buffer
+ glBindBuffer(GL_ARRAY_BUFFER, m_vboIds[0]);
+ glVertexAttribPointer(m_vertexAttribute, 2, GL_FLOAT, GL_FALSE, 0, BUFFER_OFFSET(0));
+ glBufferData(GL_ARRAY_BUFFER, sizeof(m_vertices), m_vertices, GL_DYNAMIC_DRAW);
+
+ glBindBuffer(GL_ARRAY_BUFFER, m_vboIds[1]);
+ glVertexAttribPointer(m_colorAttribute, 4, GL_FLOAT, GL_FALSE, 0, BUFFER_OFFSET(0));
+ glBufferData(GL_ARRAY_BUFFER, sizeof(m_colors), m_colors, GL_DYNAMIC_DRAW);
+
+ sCheckGLError();
+
+ // Cleanup
+ glBindBuffer(GL_ARRAY_BUFFER, 0);
+ glBindVertexArray(0);
+
+ m_count = 0;
+ }
+
+ void Destroy()
+ {
+ if (m_vaoId)
+ {
+ glDeleteVertexArrays(1, &m_vaoId);
+ glDeleteBuffers(2, m_vboIds);
+ m_vaoId = 0;
+ }
+
+ if (m_programId)
+ {
+ glDeleteProgram(m_programId);
+ m_programId = 0;
+ }
+ }
+
+ void Vertex(const b2Vec2& v, const b2Color& c)
+ {
+ if (m_count == e_maxVertices)
+ Flush();
+
+ m_vertices[m_count] = v;
+ m_colors[m_count] = c;
+ ++m_count;
+ }
+
+ void Flush()
+ {
+ if (m_count == 0)
+ return;
+
+ glUseProgram(m_programId);
+
+ float proj[16] = { 0.0f };
+ g_camera.BuildProjectionMatrix(proj, 0.2f);
+
+ glUniformMatrix4fv(m_projectionUniform, 1, GL_FALSE, proj);
+
+ glBindVertexArray(m_vaoId);
+
+ glBindBuffer(GL_ARRAY_BUFFER, m_vboIds[0]);
+ glBufferSubData(GL_ARRAY_BUFFER, 0, m_count * sizeof(b2Vec2), m_vertices);
+
+ glBindBuffer(GL_ARRAY_BUFFER, m_vboIds[1]);
+ glBufferSubData(GL_ARRAY_BUFFER, 0, m_count * sizeof(b2Color), m_colors);
+
+ glEnable(GL_BLEND);
+ glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+ glDrawArrays(GL_TRIANGLES, 0, m_count);
+ glDisable(GL_BLEND);
+
+ sCheckGLError();
+
+ glBindBuffer(GL_ARRAY_BUFFER, 0);
+ glBindVertexArray(0);
+ glUseProgram(0);
+
+ m_count = 0;
+ }
+
+ enum { e_maxVertices = 3 * 512 };
+ b2Vec2 m_vertices[e_maxVertices];
+ b2Color m_colors[e_maxVertices];
+
+ int32 m_count;
+
+ GLuint m_vaoId;
+ GLuint m_vboIds[2];
+ GLuint m_programId;
+ GLint m_projectionUniform;
+ GLint m_vertexAttribute;
+ GLint m_colorAttribute;
+};
+
+//
+DebugDraw::DebugDraw()
+{
+ m_showUI = true;
+ m_points = NULL;
+ m_lines = NULL;
+ m_triangles = NULL;
+}
+
+//
+DebugDraw::~DebugDraw()
+{
+ b2Assert(m_points == NULL);
+ b2Assert(m_lines == NULL);
+ b2Assert(m_triangles == NULL);
+}
+
+//
+void DebugDraw::Create()
+{
+ m_points = new GLRenderPoints;
+ m_points->Create();
+ m_lines = new GLRenderLines;
+ m_lines->Create();
+ m_triangles = new GLRenderTriangles;
+ m_triangles->Create();
+}
+
+//
+void DebugDraw::Destroy()
+{
+ m_points->Destroy();
+ delete m_points;
+ m_points = NULL;
+
+ m_lines->Destroy();
+ delete m_lines;
+ m_lines = NULL;
+
+ m_triangles->Destroy();
+ delete m_triangles;
+ m_triangles = NULL;
+}
+
+//
+void DebugDraw::DrawPolygon(const b2Vec2* vertices, int32 vertexCount, const b2Color& color)
+{
+ b2Vec2 p1 = vertices[vertexCount - 1];
+ for (int32 i = 0; i < vertexCount; ++i)
+ {
+ b2Vec2 p2 = vertices[i];
+ m_lines->Vertex(p1, color);
+ m_lines->Vertex(p2, color);
+ p1 = p2;
+ }
+}
+
+//
+void DebugDraw::DrawSolidPolygon(const b2Vec2* vertices, int32 vertexCount, const b2Color& color)
+{
+ b2Color fillColor(0.5f * color.r, 0.5f * color.g, 0.5f * color.b, 0.5f);
+
+ for (int32 i = 1; i < vertexCount - 1; ++i)
+ {
+ m_triangles->Vertex(vertices[0], fillColor);
+ m_triangles->Vertex(vertices[i], fillColor);
+ m_triangles->Vertex(vertices[i + 1], fillColor);
+ }
+
+ b2Vec2 p1 = vertices[vertexCount - 1];
+ for (int32 i = 0; i < vertexCount; ++i)
+ {
+ b2Vec2 p2 = vertices[i];
+ m_lines->Vertex(p1, color);
+ m_lines->Vertex(p2, color);
+ p1 = p2;
+ }
+}
+
+//
+void DebugDraw::DrawCircle(const b2Vec2& center, float radius, const b2Color& color)
+{
+ const float k_segments = 16.0f;
+ const float k_increment = 2.0f * b2_pi / k_segments;
+ float sinInc = sinf(k_increment);
+ float cosInc = cosf(k_increment);
+ b2Vec2 r1(1.0f, 0.0f);
+ b2Vec2 v1 = center + radius * r1;
+ for (int32 i = 0; i < k_segments; ++i)
+ {
+ // Perform rotation to avoid additional trigonometry.
+ b2Vec2 r2;
+ r2.x = cosInc * r1.x - sinInc * r1.y;
+ r2.y = sinInc * r1.x + cosInc * r1.y;
+ b2Vec2 v2 = center + radius * r2;
+ m_lines->Vertex(v1, color);
+ m_lines->Vertex(v2, color);
+ r1 = r2;
+ v1 = v2;
+ }
+}
+
+//
+void DebugDraw::DrawSolidCircle(const b2Vec2& center, float radius, const b2Vec2& axis, const b2Color& color)
+{
+ const float k_segments = 16.0f;
+ const float k_increment = 2.0f * b2_pi / k_segments;
+ float sinInc = sinf(k_increment);
+ float cosInc = cosf(k_increment);
+ b2Vec2 v0 = center;
+ b2Vec2 r1(cosInc, sinInc);
+ b2Vec2 v1 = center + radius * r1;
+ b2Color fillColor(0.5f * color.r, 0.5f * color.g, 0.5f * color.b, 0.5f);
+ for (int32 i = 0; i < k_segments; ++i)
+ {
+ // Perform rotation to avoid additional trigonometry.
+ b2Vec2 r2;
+ r2.x = cosInc * r1.x - sinInc * r1.y;
+ r2.y = sinInc * r1.x + cosInc * r1.y;
+ b2Vec2 v2 = center + radius * r2;
+ m_triangles->Vertex(v0, fillColor);
+ m_triangles->Vertex(v1, fillColor);
+ m_triangles->Vertex(v2, fillColor);
+ r1 = r2;
+ v1 = v2;
+ }
+
+ r1.Set(1.0f, 0.0f);
+ v1 = center + radius * r1;
+ for (int32 i = 0; i < k_segments; ++i)
+ {
+ b2Vec2 r2;
+ r2.x = cosInc * r1.x - sinInc * r1.y;
+ r2.y = sinInc * r1.x + cosInc * r1.y;
+ b2Vec2 v2 = center + radius * r2;
+ m_lines->Vertex(v1, color);
+ m_lines->Vertex(v2, color);
+ r1 = r2;
+ v1 = v2;
+ }
+
+ // Draw a line fixed in the circle to animate rotation.
+ b2Vec2 p = center + radius * axis;
+ m_lines->Vertex(center, color);
+ m_lines->Vertex(p, color);
+}
+
+//
+void DebugDraw::DrawSegment(const b2Vec2& p1, const b2Vec2& p2, const b2Color& color)
+{
+ m_lines->Vertex(p1, color);
+ m_lines->Vertex(p2, color);
+}
+
+//
+void DebugDraw::DrawTransform(const b2Transform& xf)
+{
+ const float k_axisScale = 0.4f;
+ b2Color red(1.0f, 0.0f, 0.0f);
+ b2Color green(0.0f, 1.0f, 0.0f);
+ b2Vec2 p1 = xf.p, p2;
+
+ m_lines->Vertex(p1, red);
+ p2 = p1 + k_axisScale * xf.q.GetXAxis();
+ m_lines->Vertex(p2, red);
+
+ m_lines->Vertex(p1, green);
+ p2 = p1 + k_axisScale * xf.q.GetYAxis();
+ m_lines->Vertex(p2, green);
+}
+
+//
+void DebugDraw::DrawPoint(const b2Vec2& p, float size, const b2Color& color)
+{
+ m_points->Vertex(p, color, size);
+}
+
+//
+void DebugDraw::DrawString(int x, int y, const char* string, ...)
+{
+ if (m_showUI == false)
+ {
+ return;
+ }
+
+ va_list arg;
+ va_start(arg, string);
+ ImGui::Begin("Overlay", NULL, ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoInputs | ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_NoScrollbar);
+ ImGui::SetCursorPos(ImVec2(float(x), float(y)));
+ ImGui::TextColoredV(ImColor(230, 153, 153, 255), string, arg);
+ ImGui::End();
+ va_end(arg);
+}
+
+//
+void DebugDraw::DrawString(const b2Vec2& pw, const char* string, ...)
+{
+ b2Vec2 ps = g_camera.ConvertWorldToScreen(pw);
+
+ va_list arg;
+ va_start(arg, string);
+ ImGui::Begin("Overlay", NULL, ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoInputs | ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_NoScrollbar);
+ ImGui::SetCursorPos(ImVec2(ps.x, ps.y));
+ ImGui::TextColoredV(ImColor(230, 153, 153, 255), string, arg);
+ ImGui::End();
+ va_end(arg);
+}
+
+//
+void DebugDraw::DrawAABB(b2AABB* aabb, const b2Color& c)
+{
+ b2Vec2 p1 = aabb->lowerBound;
+ b2Vec2 p2 = b2Vec2(aabb->upperBound.x, aabb->lowerBound.y);
+ b2Vec2 p3 = aabb->upperBound;
+ b2Vec2 p4 = b2Vec2(aabb->lowerBound.x, aabb->upperBound.y);
+
+ m_lines->Vertex(p1, c);
+ m_lines->Vertex(p2, c);
+
+ m_lines->Vertex(p2, c);
+ m_lines->Vertex(p3, c);
+
+ m_lines->Vertex(p3, c);
+ m_lines->Vertex(p4, c);
+
+ m_lines->Vertex(p4, c);
+ m_lines->Vertex(p1, c);
+}
+
+//
+void DebugDraw::Flush()
+{
+ m_triangles->Flush();
+ m_lines->Flush();
+ m_points->Flush();
+}