diff --git a/building.txt b/building.txt index 29e6db5..ac668be 100644 --- a/building.txt +++ b/building.txt @@ -5,8 +5,8 @@ Put premake into bounce/. Visual Studio 2017 -Ensure you have installed the Visual Studio 2015 libraries -Say { premake5 vs2017 } on a command line. +Ensure you have installed the Visual Studio 2015 libraries. +Say { premake5 vs2017 } on a command line. Open build/vs2017/bounce.sln. Set testbed as the startup project. In the testbed debugging properties, set the Working Directory to ..\..\examples\testbed. diff --git a/examples/testbed/framework/controller.cpp b/examples/testbed/framework/controller.cpp new file mode 100644 index 0000000..9fee1c2 --- /dev/null +++ b/examples/testbed/framework/controller.cpp @@ -0,0 +1,162 @@ +#include +#include +#include + +// ! +#include + +// ! +static inline b3Vec2 GetCursorPosition() +{ + extern GLFWwindow* g_window; + + double x, y; + glfwGetCursorPos(g_window, &x, &y); + + return b3Vec2(float32(x), float32(y)); +} + +Controller::Controller(Model* model, View* view) +{ + m_model = model; + m_view = view; + + m_leftDown = false; + m_rightDown = false; + m_shiftDown = false; + m_ps0.SetZero(); +} + +Controller::~Controller() +{ + +} + +void Controller::Event_SetWindowSize(u32 w, u32 h) +{ + m_model->Command_ResizeCamera(float32(w), float32(h)); +} + +void Controller::Event_Press_Key(int button) +{ + if (button == GLFW_KEY_LEFT_SHIFT) + { + m_shiftDown = true; + } + + if (m_shiftDown) + { + if (button == GLFW_KEY_DOWN) + { + m_model->Command_ZoomCamera(1.0f); + } + + if (button == GLFW_KEY_UP) + { + m_model->Command_ZoomCamera(-1.0f); + } + } + else + { + m_model->Command_Press_Key(button); + } +} + +void Controller::Event_Release_Key(int button) +{ + if (button == GLFW_KEY_LEFT_SHIFT) + { + m_shiftDown = false; + } + + if (m_shiftDown) + { + + } + else + { + m_model->Command_Release_Key(button); + } +} + +void Controller::Event_Press_Mouse(int button) +{ + if (button == GLFW_MOUSE_BUTTON_LEFT) + { + m_leftDown = true; + + if (!m_shiftDown) + { + m_model->Command_Press_Mouse_Left(GetCursorPosition()); + } + } + + if (button == GLFW_MOUSE_BUTTON_RIGHT) + { + m_rightDown = true; + } +} + +void Controller::Event_Release_Mouse(int button) +{ + if (button == GLFW_MOUSE_BUTTON_LEFT) + { + m_leftDown = false; + + if (!m_shiftDown) + { + m_model->Command_Release_Mouse_Left(GetCursorPosition()); + } + } + + if (button == GLFW_MOUSE_BUTTON_RIGHT) + { + m_rightDown = false; + } +} + +void Controller::Event_Move_Cursor(float32 x, float32 y) +{ + b3Vec2 ps; + ps.Set(float32(x), float32(y)); + + b3Vec2 dp = ps - m_ps0; + m_ps0 = ps; + + float32 ndx = b3Clamp(dp.x, -1.0f, 1.0f); + float32 ndy = b3Clamp(dp.y, -1.0f, 1.0f); + + if (m_shiftDown) + { + if (m_leftDown) + { + float32 ax = -0.005f * B3_PI * ndx; + float32 ay = -0.005f * B3_PI * ndy; + + m_model->Command_RotateCameraY(ax); + m_model->Command_RotateCameraX(ay); + } + + if (m_rightDown) + { + float32 tx = 0.2f * ndx; + float32 ty = -0.2f * ndy; + + m_model->Command_TranslateCameraX(tx); + m_model->Command_TranslateCameraY(ty); + } + } + else + { + m_model->Command_Move_Cursor(GetCursorPosition()); + } +} + +void Controller::Event_Scroll(float32 dx, float32 dy) +{ + if (m_shiftDown) + { + float32 ny = b3Clamp(dy, -1.0f, 1.0f); + m_model->Command_ZoomCamera(1.0f * ny); + } +} \ No newline at end of file diff --git a/examples/testbed/framework/controller.h b/examples/testbed/framework/controller.h new file mode 100644 index 0000000..1f53e4e --- /dev/null +++ b/examples/testbed/framework/controller.h @@ -0,0 +1,59 @@ +/* +* Copyright (c) 2016-2016 Irlan Robson http://www.irlan.net +* +* This software is provided 'as-is', without any express or implied +* warranty. In no event will the authors be held liable for any damages +* arising from the use of this software. +* Permission is granted to anyone to use this software for any purpose, +* including commercial applications, and to alter it and redistribute it +* freely, subject to the following restrictions: +* 1. The origin of this software must not be misrepresented; you must not +* claim that you wrote the original software. If you use this software +* in a product, an acknowledgment in the product documentation would be +* appreciated but is not required. +* 2. Altered source versions must be plainly marked as such, and must not be +* misrepresented as being the original software. +* 3. This notice may not be removed or altered from any source distribution. +*/ + +#ifndef CONTROLLER_H +#define CONTROLLER_H + +#include + +class Model; +class View; + +class Controller +{ +public: + Controller(Model* model, View* view); + + ~Controller(); + + void Event_SetWindowSize(u32 w, u32 h); + + void Event_Press_Key(int button); + void Event_Release_Key(int button); + + void Event_Press_Mouse(int button); + void Event_Release_Mouse(int button); + + void Event_Move_Cursor(float32 x, float32 y); + void Event_Scroll(float32 dx, float32 dy); +private: + friend class Model; + friend class View; + + Model* m_model; + View* m_view; + + bool m_leftDown; + bool m_rightDown; + bool m_shiftDown; + b3Vec2 m_ps0; + + // Ray3 m_ray0; +}; + +#endif \ No newline at end of file diff --git a/examples/testbed/framework/debug_draw.h b/examples/testbed/framework/debug_draw.h index ee560f2..9730b73 100644 --- a/examples/testbed/framework/debug_draw.h +++ b/examples/testbed/framework/debug_draw.h @@ -27,29 +27,34 @@ struct DrawTriangles; struct DrawWire; struct DrawSolid; +// struct Ray3 { - b3Vec3 A() const - { - return origin; - } - - b3Vec3 B() const - { - return origin + fraction * direction; - } + b3Vec3 A() const; + b3Vec3 B() const; b3Vec3 direction; b3Vec3 origin; float32 fraction; }; +inline b3Vec3 Ray3::A() const +{ + return origin; +} + +inline b3Vec3 Ray3::B() const +{ + return origin + fraction * direction; +} + +// class Camera { public: Camera() { - m_center.Set(0.0f, 5.0f, 0.0f); + m_center.SetZero(); m_q.SetIdentity(); m_width = 1024.0f; m_height = 768.0f; @@ -77,6 +82,92 @@ public: float32 m_zFar; }; +inline b3Mat44 MakeMat44(const b3Transform& T) +{ + return b3Mat44( + b3Vec4(T.rotation.x.x, T.rotation.x.y, T.rotation.x.z, 0.0f), + b3Vec4(T.rotation.y.x, T.rotation.y.y, T.rotation.y.z, 0.0f), + b3Vec4(T.rotation.z.x, T.rotation.z.y, T.rotation.z.z, 0.0f), + b3Vec4(T.position.x, T.position.y, T.position.z, 1.0f)); +} + +inline b3Mat44 Camera::BuildProjectionMatrix() const +{ + float32 t = tan(0.5f * m_fovy); + float32 sy = 1.0f / t; + + float32 aspect = m_width / m_height; + float32 sx = 1.0f / (aspect * t); + + float32 invRange = 1.0f / (m_zNear - m_zFar); + float32 sz = invRange * (m_zNear + m_zFar); + float32 tz = invRange * m_zNear * m_zFar; + + b3Mat44 m; + m.x = b3Vec4(sx, 0.0f, 0.0f, 0.0f); + m.y = b3Vec4(0.0f, sy, 0.0f, 0.0f); + m.z = b3Vec4(0.0f, 0.0f, sz, -1.0f); + m.w = b3Vec4(0.0f, 0.0f, tz, 0.0f); + return m; +} + +inline b3Transform Camera::BuildWorldTransform() const +{ + b3Transform xf; + xf.rotation = b3QuatMat33(m_q); + xf.position = (m_zoom * xf.rotation.z) - m_center; + return xf; +} + +inline b3Mat44 Camera::BuildWorldMatrix() const +{ + b3Transform xf = BuildWorldTransform(); + return MakeMat44(xf); +} + +inline b3Transform Camera::BuildViewTransform() const +{ + b3Transform xf; + xf.rotation = b3QuatMat33(m_q); + xf.position = (m_zoom * xf.rotation.z) - m_center; + return b3Inverse(xf); +} + +inline b3Mat44 Camera::BuildViewMatrix() const +{ + b3Transform xf = BuildViewTransform(); + return MakeMat44(xf); +} + +inline b3Vec2 Camera::ConvertWorldToScreen(const b3Vec3& pw) const +{ + b3Vec2 ps; + ps.SetZero(); + return ps; +} + +inline Ray3 Camera::ConvertScreenToWorld(const b3Vec2& ps) const +{ + // Essential Math, page 250. + float32 t = tan(0.5f * m_fovy); + float32 aspect = m_width / m_height; + + b3Vec3 pv; + pv.x = 2.0f * aspect * ps.x / m_width - aspect; + pv.y = -2.0f * ps.y / m_height + 1.0f; + pv.z = -1.0f / t; + + b3Transform xf = BuildWorldTransform(); + b3Vec3 pw = xf * pv; + + Ray3 rw; + rw.direction = b3Normalize(pw - xf.position); + rw.origin = xf.position; + rw.fraction = m_zFar; + return rw; +} + +// class DebugDraw : public b3Draw { public: @@ -114,8 +205,8 @@ public: void DrawTransform(const b3Transform& xf); // - void DrawString(const char* string, const b3Color& color, ...); - + void DrawString(const b3Color& color, const char* string, ...); + void DrawSphere(const b3SphereShape* s, const b3Color& c, const b3Transform& xf); void DrawCapsule(const b3CapsuleShape* s, const b3Color& c, const b3Transform& xf); @@ -139,4 +230,8 @@ private: DrawSolid* m_solid; }; +extern DebugDraw* g_debugDraw; +extern Camera* g_camera; +extern const char* g_overlayName; + #endif \ No newline at end of file diff --git a/examples/testbed/framework/debug_draw_2.cpp b/examples/testbed/framework/debug_draw_2.cpp index 6d090cd..dba41c9 100644 --- a/examples/testbed/framework/debug_draw_2.cpp +++ b/examples/testbed/framework/debug_draw_2.cpp @@ -24,99 +24,10 @@ #include #include -extern Camera g_camera; -extern DebugDraw* g_debugDraw; -extern const char* g_logName; - -static B3_FORCE_INLINE b3Mat34 Convert34(const b3Transform& T) -{ - return b3Mat34(T.rotation.x, T.rotation.y, T.rotation.z, T.position); -} - -static B3_FORCE_INLINE b3Mat44 Convert44(const b3Transform& T) -{ - return b3Mat44( - b3Vec4(T.rotation.x.x, T.rotation.x.y, T.rotation.x.z, 0.0f), - b3Vec4(T.rotation.y.x, T.rotation.y.y, T.rotation.y.z, 0.0f), - b3Vec4(T.rotation.z.x, T.rotation.z.y, T.rotation.z.z, 0.0f), - b3Vec4(T.position.x, T.position.y, T.position.z, 1.0f)); -} - -b3Mat44 Camera::BuildProjectionMatrix() const -{ - float32 t = tan(0.5f * m_fovy); - float32 sy = 1.0f / t; - - float32 aspect = m_width / m_height; - float32 sx = 1.0f / (aspect * t); - - float32 invRange = 1.0f / (m_zNear - m_zFar); - float32 sz = invRange * (m_zNear + m_zFar); - float32 tz = invRange * m_zNear * m_zFar; - - b3Mat44 m; - m.x = b3Vec4(sx, 0.0f, 0.0f, 0.0f); - m.y = b3Vec4(0.0f, sy, 0.0f, 0.0f); - m.z = b3Vec4(0.0f, 0.0f, sz, -1.0f); - m.w = b3Vec4(0.0f, 0.0f, tz, 0.0f); - return m; -} - -b3Transform Camera::BuildWorldTransform() const -{ - b3Transform xf; - xf.rotation = b3QuatMat33(m_q); - xf.position = (m_zoom * xf.rotation.z) - m_center; - return xf; -} - -b3Mat44 Camera::BuildWorldMatrix() const -{ - b3Transform xf = BuildWorldTransform(); - return Convert44(xf); -} - -b3Transform Camera::BuildViewTransform() const -{ - b3Transform xf; - xf.rotation = b3QuatMat33(m_q); - xf.position = (m_zoom * xf.rotation.z) - m_center; - return b3Inverse(xf); -} - -b3Mat44 Camera::BuildViewMatrix() const -{ - b3Transform xf = BuildViewTransform(); - return Convert44(xf); -} - -b3Vec2 Camera::ConvertWorldToScreen(const b3Vec3& pw) const -{ - b3Vec2 ps; - ps.SetZero(); - return ps; -} - -Ray3 Camera::ConvertScreenToWorld(const b3Vec2& ps) const -{ - // Essential Math, page 250. - float32 t = tan(0.5f * m_fovy); - float32 aspect = m_width / m_height; - - b3Vec3 pv; - pv.x = 2.0f * aspect * ps.x / m_width - aspect; - pv.y = -2.0f * ps.y / m_height + 1.0f; - pv.z = -1.0f / t; - - b3Transform xf = BuildWorldTransform(); - b3Vec3 pw = xf * pv; - - Ray3 rw; - rw.direction = b3Normalize(pw - xf.position); - rw.origin = xf.position; - rw.fraction = m_zFar; - return rw; -} +// +DebugDraw* g_debugDraw = nullptr; +Camera* g_camera = nullptr; +const char* g_overlayName = nullptr; #define BUFFER_OFFSET(i) ((char*)NULL + (i)) @@ -283,8 +194,8 @@ struct DrawPoints glUseProgram(m_programId); - b3Mat44 m1 = g_camera.BuildViewMatrix(); - b3Mat44 m2 = g_camera.BuildProjectionMatrix(); + b3Mat44 m1 = g_camera->BuildViewMatrix(); + b3Mat44 m2 = g_camera->BuildProjectionMatrix(); b3Mat44 m = m2 * m1; glUniformMatrix4fv(m_projectionUniform, 1, GL_FALSE, &m.x.x); @@ -412,8 +323,8 @@ struct DrawLines glUseProgram(m_programId); - b3Mat44 m1 = g_camera.BuildViewMatrix(); - b3Mat44 m2 = g_camera.BuildProjectionMatrix(); + b3Mat44 m1 = g_camera->BuildViewMatrix(); + b3Mat44 m2 = g_camera->BuildProjectionMatrix(); b3Mat44 m = m2 * m1; glUniformMatrix4fv(m_projectionUniform, 1, GL_FALSE, &m.x.x); @@ -542,8 +453,8 @@ struct DrawTriangles glUseProgram(m_programId); - b3Mat44 m1 = g_camera.BuildViewMatrix(); - b3Mat44 m2 = g_camera.BuildProjectionMatrix(); + b3Mat44 m1 = g_camera->BuildViewMatrix(); + b3Mat44 m2 = g_camera->BuildProjectionMatrix(); b3Mat44 m = m2 * m1; glUniformMatrix4fv(m_projectionUniform, 1, GL_FALSE, &m.x.x); @@ -722,12 +633,12 @@ struct DrawWire { glUseProgram(m_programId); - b3Mat44 m1 = Convert44(xf); + b3Mat44 m1 = MakeMat44(xf); m1.x = radius * m1.x; m1.y = radius * m1.y; m1.z = radius * m1.z; - b3Mat44 m2 = g_camera.BuildViewMatrix(); - b3Mat44 m3 = g_camera.BuildProjectionMatrix(); + b3Mat44 m2 = g_camera->BuildViewMatrix(); + b3Mat44 m3 = g_camera->BuildProjectionMatrix(); b3Mat44 m = m3 * m2 * m1; glUniformMatrix4fv(m_projectionUniform, 1, GL_FALSE, &m.x.x); @@ -1011,13 +922,13 @@ struct DrawSolid { glUseProgram(m_programId); - b3Mat44 m1 = Convert44(xf); + b3Mat44 m1 = MakeMat44(xf); m1.x = radius * m1.x; m1.y = height * m1.y; m1.z = radius * m1.z; - b3Mat44 m2 = g_camera.BuildViewMatrix(); - b3Mat44 m3 = g_camera.BuildProjectionMatrix(); + b3Mat44 m2 = g_camera->BuildViewMatrix(); + b3Mat44 m3 = g_camera->BuildProjectionMatrix(); b3Mat44 m = m3 * m2 * m1; glUniform4fv(m_colorUniform, 1, &c.r); @@ -1049,13 +960,13 @@ struct DrawSolid { glUseProgram(m_programId); - b3Mat44 m1 = Convert44(xf); + b3Mat44 m1 = MakeMat44(xf); m1.x = radius * m1.x; m1.y = radius * m1.y; m1.z = radius * m1.z; - b3Mat44 m2 = g_camera.BuildViewMatrix(); - b3Mat44 m3 = g_camera.BuildProjectionMatrix(); + b3Mat44 m2 = g_camera->BuildViewMatrix(); + b3Mat44 m3 = g_camera->BuildProjectionMatrix(); b3Mat44 m = m3 * m2 * m1; glUniform4fv(m_colorUniform, 1, &c.r); @@ -1137,7 +1048,7 @@ void DebugDraw::DrawSolidTriangle(const b3Vec3& normal, const b3Vec3& p1, const m_triangles->Vertex(p3, color, normal); b3Color edgeColor(0.0f, 0.0f, 0.0f, 1.0f); - DrawTriangle(p2, p3, p3, edgeColor); + DrawTriangle(p1, p2, p3, edgeColor); } void DebugDraw::DrawSolidTriangle(const b3Vec3& normal, const b3Vec3& p1, const b3Color& color1, const b3Vec3& p2, const b3Color& color2, const b3Vec3& p3, const b3Color& color3) @@ -1147,7 +1058,7 @@ void DebugDraw::DrawSolidTriangle(const b3Vec3& normal, const b3Vec3& p1, const m_triangles->Vertex(p3, color3, normal); b3Color edgeColor(0.0f, 0.0f, 0.0f, 1.0f); - DrawTriangle(p2, p3, p3, edgeColor); + DrawTriangle(p1, p2, p3, edgeColor); } void DebugDraw::DrawPolygon(const b3Vec3* vertices, u32 count, const b3Color& color) @@ -1397,14 +1308,19 @@ void DebugDraw::DrawAABB(const b3AABB3& aabb, const b3Color& color) DrawSegment(vs[1], vs[7], color); } -void DebugDraw::DrawString(const char* text, const b3Color& color, ...) +void DebugDraw::DrawString(const b3Color& color, const char* text, ...) { - va_list arg; - va_start(arg, text); - ImGui::Begin(g_logName, NULL, ImVec2(0, 0), 0.0f, ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoInputs | ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_NoScrollbar); - ImGui::TextColoredV(ImVec4(color.r, color.g, color.b, color.a), text, arg); + va_list args; + va_start(args, text); + + ImGui::SetNextWindowPos(ImVec2(0.0f, 0.0f)); + ImGui::SetNextWindowSize(ImVec2(g_camera->m_width, g_camera->m_height)); + + ImGui::Begin(g_overlayName, NULL, ImVec2(0.0f, 0.0f), 0.0f, ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoInputs | ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_NoScrollbar); + ImGui::TextColoredV(ImVec4(color.r, color.g, color.b, color.a), text, args); ImGui::End(); - va_end(arg); + + va_end(args); } void DebugDraw::DrawSphere(const b3SphereShape* s, const b3Color& c, const b3Transform& xf) diff --git a/examples/testbed/framework/debug_draw_4.cpp b/examples/testbed/framework/debug_draw_4.cpp index 4934b3c..68e7dc1 100644 --- a/examples/testbed/framework/debug_draw_4.cpp +++ b/examples/testbed/framework/debug_draw_4.cpp @@ -24,99 +24,10 @@ #include #include -extern Camera g_camera; -extern DebugDraw* g_debugDraw; -extern const char* g_logName; - -static B3_FORCE_INLINE b3Mat34 Convert34(const b3Transform& T) -{ - return b3Mat34(T.rotation.x, T.rotation.y, T.rotation.z, T.position); -} - -static B3_FORCE_INLINE b3Mat44 Convert44(const b3Transform& T) -{ - return b3Mat44( - b3Vec4(T.rotation.x.x, T.rotation.x.y, T.rotation.x.z, 0.0f), - b3Vec4(T.rotation.y.x, T.rotation.y.y, T.rotation.y.z, 0.0f), - b3Vec4(T.rotation.z.x, T.rotation.z.y, T.rotation.z.z, 0.0f), - b3Vec4(T.position.x, T.position.y, T.position.z, 1.0f)); -} - -b3Mat44 Camera::BuildProjectionMatrix() const -{ - float32 t = tan(0.5f * m_fovy); - float32 sy = 1.0f / t; - - float32 aspect = m_width / m_height; - float32 sx = 1.0f / (aspect * t); - - float32 invRange = 1.0f / (m_zNear - m_zFar); - float32 sz = invRange * (m_zNear + m_zFar); - float32 tz = invRange * m_zNear * m_zFar; - - b3Mat44 m; - m.x = b3Vec4(sx, 0.0f, 0.0f, 0.0f); - m.y = b3Vec4(0.0f, sy, 0.0f, 0.0f); - m.z = b3Vec4(0.0f, 0.0f, sz, -1.0f); - m.w = b3Vec4(0.0f, 0.0f, tz, 0.0f); - return m; -} - -b3Transform Camera::BuildWorldTransform() const -{ - b3Transform xf; - xf.rotation = b3QuatMat33(m_q); - xf.position = (m_zoom * xf.rotation.z) - m_center; - return xf; -} - -b3Mat44 Camera::BuildWorldMatrix() const -{ - b3Transform xf = BuildWorldTransform(); - return Convert44(xf); -} - -b3Transform Camera::BuildViewTransform() const -{ - b3Transform xf; - xf.rotation = b3QuatMat33(m_q); - xf.position = (m_zoom * xf.rotation.z) - m_center; - return b3Inverse(xf); -} - -b3Mat44 Camera::BuildViewMatrix() const -{ - b3Transform xf = BuildViewTransform(); - return Convert44(xf); -} - -b3Vec2 Camera::ConvertWorldToScreen(const b3Vec3& pw) const -{ - b3Vec2 ps; - ps.SetZero(); - return ps; -} - -Ray3 Camera::ConvertScreenToWorld(const b3Vec2& ps) const -{ - // Essential Math, page 250. - float32 t = tan(0.5f * m_fovy); - float32 aspect = m_width / m_height; - - b3Vec3 pv; - pv.x = 2.0f * aspect * ps.x / m_width - aspect; - pv.y = -2.0f * ps.y / m_height + 1.0f; - pv.z = -1.0f / t; - - b3Transform xf = BuildWorldTransform(); - b3Vec3 pw = xf * pv; - - Ray3 rw; - rw.direction = b3Normalize(pw - xf.position); - rw.origin = xf.position; - rw.fraction = m_zFar; - return rw; -} +// +DebugDraw* g_debugDraw = nullptr; +Camera* g_camera = nullptr; +const char* g_overlayName = nullptr; #define BUFFER_OFFSET(i) ((char*)NULL + (i)) @@ -297,8 +208,8 @@ struct DrawPoints glUseProgram(m_programId); - b3Mat44 m1 = g_camera.BuildViewMatrix(); - b3Mat44 m2 = g_camera.BuildProjectionMatrix(); + b3Mat44 m1 = g_camera->BuildViewMatrix(); + b3Mat44 m2 = g_camera->BuildProjectionMatrix(); b3Mat44 m = m2 * m1; glUniformMatrix4fv(m_projectionUniform, 1, GL_FALSE, &m.x.x); @@ -428,8 +339,8 @@ struct DrawLines glUseProgram(m_programId); - b3Mat44 m1 = g_camera.BuildViewMatrix(); - b3Mat44 m2 = g_camera.BuildProjectionMatrix(); + b3Mat44 m1 = g_camera->BuildViewMatrix(); + b3Mat44 m2 = g_camera->BuildProjectionMatrix(); b3Mat44 m = m2 * m1; glUniformMatrix4fv(m_projectionUniform, 1, GL_FALSE, &m.x.x); @@ -566,8 +477,8 @@ struct DrawTriangles glUseProgram(m_programId); - b3Mat44 m1 = g_camera.BuildViewMatrix(); - b3Mat44 m2 = g_camera.BuildProjectionMatrix(); + b3Mat44 m1 = g_camera->BuildViewMatrix(); + b3Mat44 m2 = g_camera->BuildProjectionMatrix(); b3Mat44 m = m2 * m1; glUniformMatrix4fv(m_projectionUniform, 1, GL_FALSE, &m.x.x); @@ -739,12 +650,12 @@ struct DrawWire { glUseProgram(m_programId); - b3Mat44 m1 = Convert44(xf); + b3Mat44 m1 = MakeMat44(xf); m1.x = radius * m1.x; m1.y = radius * m1.y; m1.z = radius * m1.z; - b3Mat44 m2 = g_camera.BuildViewMatrix(); - b3Mat44 m3 = g_camera.BuildProjectionMatrix(); + b3Mat44 m2 = g_camera->BuildViewMatrix(); + b3Mat44 m3 = g_camera->BuildProjectionMatrix(); b3Mat44 m = m3 * m2 * m1; glUniformMatrix4fv(m_projectionUniform, 1, GL_FALSE, &m.x.x); @@ -1027,13 +938,13 @@ struct DrawSolid { glUseProgram(m_programId); - b3Mat44 m1 = Convert44(xf); + b3Mat44 m1 = MakeMat44(xf); m1.x = radius * m1.x; m1.y = height * m1.y; m1.z = radius * m1.z; - b3Mat44 m2 = g_camera.BuildViewMatrix(); - b3Mat44 m3 = g_camera.BuildProjectionMatrix(); + b3Mat44 m2 = g_camera->BuildViewMatrix(); + b3Mat44 m3 = g_camera->BuildProjectionMatrix(); b3Mat44 m = m3 * m2 * m1; glUniform4fv(m_colorUniform, 1, &c.r); @@ -1061,13 +972,13 @@ struct DrawSolid { glUseProgram(m_programId); - b3Mat44 m1 = Convert44(xf); + b3Mat44 m1 = MakeMat44(xf); m1.x = radius * m1.x; m1.y = radius * m1.y; m1.z = radius * m1.z; - b3Mat44 m2 = g_camera.BuildViewMatrix(); - b3Mat44 m3 = g_camera.BuildProjectionMatrix(); + b3Mat44 m2 = g_camera->BuildViewMatrix(); + b3Mat44 m3 = g_camera->BuildProjectionMatrix(); b3Mat44 m = m3 * m2 * m1; glUniform4fv(m_colorUniform, 1, &c.r); @@ -1145,7 +1056,7 @@ void DebugDraw::DrawSolidTriangle(const b3Vec3& normal, const b3Vec3& p1, const m_triangles->Vertex(p3, color, normal); b3Color edgeColor(0.0f, 0.0f, 0.0f, 1.0f); - DrawTriangle(p2, p3, p3, edgeColor); + DrawTriangle(p1, p2, p3, edgeColor); } void DebugDraw::DrawSolidTriangle(const b3Vec3& normal, const b3Vec3& p1, const b3Color& color1, const b3Vec3& p2, const b3Color& color2, const b3Vec3& p3, const b3Color& color3) @@ -1155,7 +1066,7 @@ void DebugDraw::DrawSolidTriangle(const b3Vec3& normal, const b3Vec3& p1, const m_triangles->Vertex(p3, color3, normal); b3Color edgeColor(0.0f, 0.0f, 0.0f, 1.0f); - DrawTriangle(p2, p3, p3, edgeColor); + DrawTriangle(p1, p2, p3, edgeColor); } void DebugDraw::DrawPolygon(const b3Vec3* vertices, u32 count, const b3Color& color) @@ -1405,14 +1316,19 @@ void DebugDraw::DrawAABB(const b3AABB3& aabb, const b3Color& color) DrawSegment(vs[1], vs[7], color); } -void DebugDraw::DrawString(const char* text, const b3Color& color, ...) +void DebugDraw::DrawString(const b3Color& color, const char* text, ...) { - va_list arg; - va_start(arg, text); - ImGui::Begin(g_logName, NULL, ImVec2(0, 0), 0.0f, ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoInputs | ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_NoScrollbar); - ImGui::TextColoredV(ImVec4(color.r, color.g, color.b, color.a), text, arg); + va_list args; + va_start(args, text); + + ImGui::SetNextWindowPos(ImVec2(0.0f, 0.0f)); + ImGui::SetNextWindowSize(ImVec2(g_camera->m_width, g_camera->m_height)); + + ImGui::Begin(g_overlayName, NULL, ImVec2(0.0f, 0.0f), 0.0f, ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoInputs | ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_NoScrollbar); + ImGui::TextColoredV(ImVec4(color.r, color.g, color.b, color.a), text, args); ImGui::End(); - va_end(arg); + + va_end(args); } void DebugDraw::DrawSphere(const b3SphereShape* s, const b3Color& c, const b3Transform& xf) diff --git a/examples/testbed/framework/main.cpp b/examples/testbed/framework/main.cpp index 17224b4..d6a3fe8 100644 --- a/examples/testbed/framework/main.cpp +++ b/examples/testbed/framework/main.cpp @@ -16,166 +16,53 @@ * 3. This notice may not be removed or altered from any source distribution. */ -#if defined(__APPLE_CC__) -#include +#if defined (U_OPENGL_2) + #include +#elif defined (U_OPENGL_4) + #include #else - -#if defined(U_OPENGL_2) -#include -#elif defined(U_OPENGL_4) -#include -#else - + // error #endif -#endif - -#include - -#if defined(U_OPENGL_2) -#include -#elif defined(U_OPENGL_4) -#include -#else -// error -#endif - -#include -#include -#include +#include +#include +#include // GLFWwindow* g_window; -Settings g_settings; -Test* g_test; -u32 g_testCount; -Camera g_camera; -DebugDraw* g_debugDraw; -Profiler* g_profiler; -TestbedListener g_testbedListener; -ProfilerListener* g_profilerListener = &g_testbedListener; -RecorderProfiler g_recorderProfiler; -bool g_leftDown; -bool g_rightDown; -bool g_shiftDown; -b3Vec2 g_ps0; -const char* g_logName = { "log" }; -// These two functions below implement Bounce's profiling interfaces. -// If you're not concerned with profiling then just define two slut functions. -bool b3PushProfileScope(const char* name) +// +Model* g_model; +View* g_view; +Controller* g_controller; + +static void WindowSize(GLFWwindow* ww, int w, int h) { - return g_profiler->PushEvent(name); + g_controller->Event_SetWindowSize(u32(w), u32(h)); } -void b3PopProfileScope() +static void CursorMove(GLFWwindow* w, double x, double y) { - g_profiler->PopEvent(); + g_controller->Event_Move_Cursor(float32(x), float32(y)); } -static void WindowSize(int w, int h) +static void WheelScroll(GLFWwindow* w, double dx, double dy) { - g_camera.m_width = float32(w); - g_camera.m_height = float32(h); -} - -static void MouseMove(GLFWwindow* w, double x, double y) -{ - b3Vec2 ps; - ps.Set(float32(x), float32(y)); - - b3Vec2 dp = ps - g_ps0; - g_ps0 = ps; - - Ray3 pw = g_camera.ConvertScreenToWorld(ps); - - float32 nx = b3Clamp(dp.x, -1.0f, 1.0f); - float32 ny = b3Clamp(dp.y, -1.0f, 1.0f); - - if (g_shiftDown) - { - if (g_leftDown) - { - // Negate angles to do positive rotations (CCW) of the world. - float32 angleY = 0.005f * B3_PI * -ny; - float32 angleX = 0.005f * B3_PI * -nx; - - b3Quat qx = b3QuatRotationX(angleY); - b3Quat qy = b3QuatRotationY(angleX); - - g_camera.m_q = g_camera.m_q * qx; - g_camera.m_q = qy * g_camera.m_q; - g_camera.m_q.Normalize(); - } - - if (g_rightDown) - { - b3Transform xf = g_camera.BuildWorldTransform(); - g_camera.m_center += 0.2f * nx * xf.rotation.x; - g_camera.m_center += 0.2f * -ny * xf.rotation.y; - } - } - else - { - g_test->MouseMove(pw); - } -} - -static void MouseWheel(GLFWwindow* w, double dx, double dy) -{ - float32 n = b3Clamp(float32(dy), -1.0f, 1.0f); - if (g_shiftDown) - { - g_camera.m_zoom += 0.5f * -n; - } + g_controller->Event_Scroll(float32(dx), float32(dy)); } static void MouseButton(GLFWwindow* w, int button, int action, int mods) { - double x, y; - glfwGetCursorPos(w, &x, &y); - b3Vec2 p; - p.Set(float32(x), float32(y)); - - Ray3 pw = g_camera.ConvertScreenToWorld(p); - switch (action) { case GLFW_PRESS: { - if (button == GLFW_MOUSE_BUTTON_LEFT) - { - g_leftDown = true; - - if (g_shiftDown == false) - { - g_test->MouseLeftDown(pw); - } - } - - if (button == GLFW_MOUSE_BUTTON_RIGHT) - { - g_rightDown = true; - } - + g_controller->Event_Press_Mouse(button); break; } case GLFW_RELEASE: { - if (button == GLFW_MOUSE_BUTTON_LEFT) - { - g_leftDown = false; - - if (g_shiftDown == false) - { - g_test->MouseLeftUp(pw); - } - } - - if (button == GLFW_MOUSE_BUTTON_RIGHT) - { - g_rightDown = false; - } + g_controller->Event_Release_Mouse(button); break; } default: @@ -191,43 +78,13 @@ static void KeyButton(GLFWwindow* w, int button, int scancode, int action, int m { case GLFW_PRESS: { - if (button == GLFW_KEY_LEFT_SHIFT) - { - g_shiftDown = true; - g_test->KeyDown(button); - } - - if (g_shiftDown) - { - if (button == GLFW_KEY_DOWN) - { - g_camera.m_zoom += 0.2f; - } - - if (button == GLFW_KEY_UP) - { - g_camera.m_zoom -= 0.2f; - } - } - else - { - g_test->KeyDown(button); - } - + g_controller->Event_Press_Key(button); + break; } case GLFW_RELEASE: { - if (button == GLFW_KEY_LEFT_SHIFT) - { - g_shiftDown = false; - } - - if (g_shiftDown == false) - { - g_test->KeyUp(button); - } - + g_controller->Event_Release_Key(button); break; } default: @@ -237,303 +94,34 @@ static void KeyButton(GLFWwindow* w, int button, int scancode, int action, int m } } -static inline bool ImGui_GLFW_GL_Init(GLFWwindow* w, bool install_callbacks) -{ - -#if defined(U_OPENGL_2) - - return ImGui_ImplGlfwGL2_Init(g_window, false); - -#elif defined(U_OPENGL_4) - - return ImGui_ImplGlfwGL3_Init(g_window, false); - -#else - - // error - -#endif - -} - -static inline void ImGui_GLFW_GL_Shutdown() -{ - -#if defined(U_OPENGL_2) - - ImGui_ImplGlfwGL2_Shutdown(); - -#elif defined(U_OPENGL_4) - - ImGui_ImplGlfwGL3_Shutdown(); - -#else - - // error - -#endif - -} - -static inline void ImGui_GLFW_GL_NewFrame() -{ - -#if defined(U_OPENGL_2) - - ImGui_ImplGlfwGL2_NewFrame(); - -#elif defined(U_OPENGL_4) - - ImGui_ImplGlfwGL3_NewFrame(); - -#else - - // error - -#endif - -} - -static inline void ImGui_GLFW_GL_RenderDrawData(ImDrawData* data) -{ - -#if defined(U_OPENGL_2) - - ImGui_ImplGlfwGL2_RenderDrawData(data); - -#elif defined(U_OPENGL_4) - - ImGui_ImplGlfwGL3_RenderDrawData(data); - -#else - - // error - -#endif - -} - -static void Char(GLFWwindow* w, unsigned int codepoint) -{ - ImGui_ImplGlfw_CharCallback(w, codepoint); -} - -static void CreateInterface() -{ - ImGui::CreateContext(); - - ImGuiIO& io = ImGui::GetIO(); - io.Fonts[0].AddFontDefault(); - - ImGui_GLFW_GL_Init(g_window, false); - - ImGui::StyleColorsDark(); -} - -static void DestroyInterface() -{ - ImGui_GLFW_GL_Shutdown(); - - ImGui::DestroyContext(); -} - -static bool GetTestName(void*, int idx, const char** name) -{ - *name = g_tests[idx].name; - return true; -} - -static void Interface() -{ - ImGui::SetNextWindowPos(ImVec2(g_camera.m_width - 250.0f, 0.0f)); - ImGui::SetNextWindowSize(ImVec2(250.0f, g_camera.m_height)); - ImGui::PushStyleVar(ImGuiStyleVar_WindowRounding, 0.0f); - - ImGui::Begin("Controls", NULL, ImVec2(0.0f, 0.0f), 0.25f, ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoResize); - - ImGui::PushItemWidth(-1.0f); - - ImGui::Text("Test"); - if (ImGui::Combo("##Test", &g_settings.testID, GetTestName, NULL, g_testCount, g_testCount)) - { - g_settings.lastTestID = -1; - } - - ImVec2 buttonSize = ImVec2(-1, 0); - if (ImGui::Button("Restart", buttonSize)) - { - g_settings.lastTestID = -1; - } - if (ImGui::Button("Previous", buttonSize)) - { - g_settings.testID = b3Clamp(g_settings.testID - 1, 0, int(g_testCount) - 1); - g_settings.lastTestID = -1; - } - if (ImGui::Button("Next", buttonSize)) - { - g_settings.testID = b3Clamp(g_settings.testID + 1, 0, int(g_testCount) - 1); - g_settings.lastTestID = -1; - } - if (ImGui::Button("Dump", buttonSize)) - { - if (g_test) - { - g_test->Dump(); - } - } - if (ImGui::Button("Exit", buttonSize)) - { - glfwSetWindowShouldClose(g_window, true); - } - - ImGui::Separator(); - - ImGui::Text("Step"); - - ImGui::Text("Hertz"); - ImGui::SliderFloat("##Hertz", &g_settings.hertz, 0.0f, 240.0f, "%.1f"); - ImGui::Text("Velocity Iterations"); - ImGui::SliderInt("##Velocity Iterations", &g_settings.velocityIterations, 0, 50); - ImGui::Text("Position Iterations"); - ImGui::SliderInt("#Position Iterations", &g_settings.positionIterations, 0, 50); - ImGui::Checkbox("Sleep", &g_settings.sleep); - ImGui::Checkbox("Convex Cache", &g_settings.convexCache); - ImGui::Checkbox("Warm Start", &g_settings.warmStart); - - if (ImGui::Button("Play/Pause", buttonSize)) - { - g_settings.pause = !g_settings.pause; - } - if (ImGui::Button("Single Step", buttonSize)) - { - g_settings.pause = true; - g_settings.singleStep = true; - } - - ImGui::Separator(); - - ImGui::Text("View"); - ImGui::Checkbox("Grid", &g_settings.drawGrid); - ImGui::Checkbox("Vertices and Edges", &g_settings.drawVerticesEdges); - ImGui::Checkbox("Faces", &g_settings.drawFaces); - ImGui::Checkbox("Center of Masses", &g_settings.drawCenterOfMasses); - ImGui::Checkbox("Bounding Boxes", &g_settings.drawBounds); - ImGui::Checkbox("Joints", &g_settings.drawJoints); - ImGui::Checkbox("Contact Points", &g_settings.drawContactPoints); - ImGui::Checkbox("Contact Normals", &g_settings.drawContactNormals); - ImGui::Checkbox("Contact Tangents", &g_settings.drawContactTangents); - ImGui::Checkbox("Contact Polygons", &g_settings.drawContactPolygons); - ImGui::Checkbox("Statistics", &g_settings.drawStats); - ImGui::Checkbox("Profile", &g_settings.drawProfile); - - ImGui::End(); - ImGui::PopStyleVar(); -} - -static void Step() -{ - if (g_settings.pause) - { - g_debugDraw->DrawString("*PAUSED*", b3Color_white); - } - else - { - g_debugDraw->DrawString("*PLAYING*", b3Color_white); - } - - if (g_settings.drawGrid) - { - b3Color color(0.2f, 0.2f, 0.2f, 1.0f); - - b3Vec3 pn(0.0f, 1.0f, 0.0f); - b3Vec3 p(0.0f, 0.0f, 0.0f); - g_debugDraw->DrawCircle(pn, p, 1.0f, color); - - int n = 20; - - b3Vec3 t; - t.x = -0.5f * float32(n); - t.y = 0.0f; - t.z = -0.5f * float32(n); - - for (int i = 0; i < n; i += 1) - { - for (int j = 0; j < n; j += 1) - { - b3Vec3 vs[4]; - vs[0] = b3Vec3((float)i, 0.0f, (float)j); - vs[1] = b3Vec3((float)i, 0.0f, (float)j + 1); - vs[2] = b3Vec3((float)i + 1, 0.0f, (float)j + 1); - vs[3] = b3Vec3((float)i + 1, 0.0f, (float)j); - - for (u32 k = 0; k < 4; ++k) - { - vs[k] += t; - } - - g_debugDraw->DrawPolygon(vs, 4, color); - } - } - } - - if (g_settings.testID != g_settings.lastTestID) - { - delete g_test; - g_settings.lastTestID = g_settings.testID; - g_test = g_tests[g_settings.testID].create(); - g_settings.pause = true; - } - - g_test->Step(); - g_debugDraw->Submit(); -} - static void Run() { - glFrontFace(GL_CCW); - glCullFace(GL_BACK); - glEnable(GL_CULL_FACE); - glEnable(GL_DEPTH_TEST); - glEnable(GL_BLEND); - glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + int w, h; + glfwGetWindowSize(g_window, &w, &h); + g_controller->Event_SetWindowSize(u32(w), u32(h)); - glClearColor(0.3f, 0.3f, 0.3f, 1.0f); - glClearDepth(1.0f); - - double t1 = glfwGetTime(); double frameTime = 0.0; while (glfwWindowShouldClose(g_window) == 0) { - int width, height; - glfwGetWindowSize(g_window, &width, &height); - g_camera.m_width = float32(width); - g_camera.m_height = float32(height); + double time1 = glfwGetTime(); + + g_view->Command_PreDraw(); - glViewport(0, 0, width, height); - glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + g_view->Command_Draw(); - ImGui_GLFW_GL_NewFrame(); + g_debugDraw->DrawString(b3Color_yellow, "%.2f (ms)", 1000.0 * frameTime); - ImGui::SetNextWindowPos(ImVec2(0, 0)); - ImGui::SetNextWindowSize(ImVec2((float)g_camera.m_width, (float)g_camera.m_height)); - ImGui::Begin("Overlay", NULL, ImVec2(0, 0), 0.0f, ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoInputs | ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_NoScrollbar); - ImGui::SetCursorPos(ImVec2(5, (float)g_camera.m_height - 20)); - ImGui::Text("%.1f ms", 1000.0 * frameTime); - ImGui::End(); + g_model->Command_Step(); - Interface(); - Step(); + g_view->Command_PostDraw(); - double t = glfwGetTime(); - frameTime = t - t1; - t1 = t; - - ImGui::Render(); - ImGui_GLFW_GL_RenderDrawData(ImGui::GetDrawData()); + double time2 = glfwGetTime(); + + double fraction = 0.9; + frameTime = fraction * frameTime + (1.0 - fraction) * (time2 - time1); glfwSwapBuffers(g_window); - glfwPollEvents(); } } @@ -542,7 +130,8 @@ int main(int argc, char** args) { #if defined(_WIN32) // Report memory leaks - _CrtSetDbgFlag(_CRTDBG_LEAK_CHECK_DF | _CrtSetDbgFlag(_CRTDBG_REPORT_FLAG)); + _CrtSetDbgFlag(_CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF | _CrtSetDbgFlag(_CRTDBG_REPORT_FLAG)); + //_CrtSetBreakAlloc(x); #endif if (glfwInit() == 0) @@ -556,29 +145,23 @@ int main(int argc, char** args) char title[256]; sprintf(title, "Bounce Testbed Version %d.%d.%d", b3_version.major, b3_version.minor, b3_version.revision); -#if defined(__APPLE__) - glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 4); - glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 0); - glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE); - glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE); -#endif - g_window = glfwCreateWindow(1024, 768, title, NULL, NULL); if (g_window == NULL) { - fprintf(stderr, "Failed to open GLFW window\n"); + fprintf(stderr, "Failed to create GLFW window\n"); glfwTerminate(); return -1; } - - glfwMakeContextCurrent(g_window); - glfwSetCursorPosCallback(g_window, MouseMove); - glfwSetScrollCallback(g_window, MouseWheel); + + glfwSetWindowSizeCallback(g_window, WindowSize); + glfwSetCursorPosCallback(g_window, CursorMove); + glfwSetScrollCallback(g_window, WheelScroll); glfwSetMouseButtonCallback(g_window, MouseButton); glfwSetKeyCallback(g_window, KeyButton); - glfwSetCharCallback(g_window, Char); glfwSwapInterval(1); + glfwMakeContextCurrent(g_window); + if (gladLoadGL() == 0) { fprintf(stderr, "Failed to load OpenGL extensions\n"); @@ -589,48 +172,27 @@ int main(int argc, char** args) printf("OpenGL %s, GLSL %s\n", glGetString(GL_VERSION), glGetString(GL_SHADING_LANGUAGE_VERSION)); - g_leftDown = false; - g_rightDown = false; - g_shiftDown = false; - g_ps0.SetZero(); - - // Create UI - CreateInterface(); - - // Create profiler - g_profiler = new Profiler(); - - // Create renderer - g_debugDraw = new DebugDraw(); - - // Run the testbed - g_testCount = 0; - while (g_tests[g_testCount].create != NULL) - { - ++g_testCount; - } - g_test = NULL; + // + g_model = new Model(); + g_view = new View(g_window, g_model); + g_controller = new Controller(g_model, g_view); + // Run Run(); - // Destroy the last test - if (g_test) - { - delete g_test; - g_test = NULL; - } + // + delete g_controller; + g_controller = nullptr; - // Destroy renderer - delete g_debugDraw; + delete g_view; + g_view = nullptr; - // Destroy profiler - delete g_profiler; + delete g_model; + g_model = nullptr; - // Destroy UI - DestroyInterface(); - - // Destroy g_window + // glfwTerminate(); + g_window = nullptr; return 0; } \ No newline at end of file diff --git a/examples/testbed/framework/model.cpp b/examples/testbed/framework/model.cpp new file mode 100644 index 0000000..afdb52c --- /dev/null +++ b/examples/testbed/framework/model.cpp @@ -0,0 +1,130 @@ +#include + +Model::Model() +{ + g_debugDraw = &m_debugDraw; + g_camera = &m_camera; + g_overlayName = "overlay"; + g_profiler = &m_profiler; + g_profilerListener = &m_profilerListener; + g_settings = &m_settings; + + m_test = nullptr; + + glFrontFace(GL_CCW); + glCullFace(GL_BACK); + glEnable(GL_CULL_FACE); + glEnable(GL_DEPTH_TEST); + glEnable(GL_BLEND); + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + + glClearColor(0.3f, 0.3f, 0.3f, 1.0f); + glClearDepth(1.0f); + + m_camera.m_q = b3QuatRotationX(-0.125f * B3_PI); + m_camera.m_center.SetZero(); + m_camera.m_zoom = 20.0f; +} + +Model::~Model() +{ + g_debugDraw = nullptr; + g_camera = nullptr; + g_overlayName = nullptr; + g_profiler = nullptr; + g_profilerListener = nullptr; + g_settings = nullptr; + + delete m_test; +} + +void Model::Command_Step() +{ + if (m_settings.testID != m_settings.lastTestID) + { + delete m_test; + m_settings.lastTestID = m_settings.testID; + m_test = g_tests[m_settings.testID].create(); + m_settings.pause = true; + } + + glViewport(0, 0, GLsizei(m_camera.m_width), GLsizei(m_camera.m_height)); + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + + if (m_settings.pause) + { + m_debugDraw.DrawString(b3Color_white, "*PAUSED*"); + } + else + { + m_debugDraw.DrawString(b3Color_white, "*PLAYING*"); + } + + if (m_settings.drawGrid) + { + b3Color color(0.2f, 0.2f, 0.2f, 1.0f); + + b3Vec3 pn(0.0f, 1.0f, 0.0f); + b3Vec3 p(0.0f, 0.0f, 0.0f); + m_debugDraw.DrawCircle(pn, p, 1.0f, color); + + int n = 20; + + b3Vec3 t; + t.x = -0.5f * float32(n); + t.y = 0.0f; + t.z = -0.5f * float32(n); + + for (int i = 0; i < n; i += 1) + { + for (int j = 0; j < n; j += 1) + { + b3Vec3 vs[4]; + vs[0] = b3Vec3((float32)i, 0.0f, (float32)j); + vs[1] = b3Vec3((float32)i, 0.0f, (float32)j + 1); + vs[2] = b3Vec3((float32)i + 1, 0.0f, (float32)j + 1); + vs[3] = b3Vec3((float32)i + 1, 0.0f, (float32)j); + + vs[0] += t; + vs[1] += t; + vs[2] += t; + vs[3] += t; + + m_debugDraw.DrawPolygon(vs, 4, color); + } + } + } + + // + m_settings.inv_hertz = m_settings.hertz != 0.0f ? 1.0f / m_settings.hertz : 0.0f; + + if (m_settings.pause) + { + if (m_settings.singleStep) + { + m_settings.singleStep = false; + } + else + { + m_settings.inv_hertz = 0.0f; + } + } + + m_profiler.Begin(); + + m_test->Step(); + + m_profiler.End(g_profilerListener); + + if (m_settings.drawProfile) + { + const b3Array& records = m_profilerListener.m_recorderProfiler.GetRecords(); + for (u32 i = 0; i < records.Count(); ++i) + { + const ProfilerRecord& r = records[i]; + m_debugDraw.DrawString(b3Color_white, "%s %.4f (%.4f) [ms]", r.name, r.elapsed, r.maxElapsed); + } + } + + m_debugDraw.Submit(); +} \ No newline at end of file diff --git a/examples/testbed/framework/model.h b/examples/testbed/framework/model.h new file mode 100644 index 0000000..3a61609 --- /dev/null +++ b/examples/testbed/framework/model.h @@ -0,0 +1,225 @@ +/* +* Copyright (c) 2016-2016 Irlan Robson http://www.irlan.net +* +* This software is provided 'as-is', without any express or implied +* warranty. In no event will the authors be held liable for any damages +* arising from the use of this software. +* Permission is granted to anyone to use this software for any purpose, +* including commercial applications, and to alter it and redistribute it +* freely, subject to the following restrictions: +* 1. The origin of this software must not be misrepresented; you must not +* claim that you wrote the original software. If you use this software +* in a product, an acknowledgment in the product documentation would be +* appreciated but is not required. +* 2. Altered source versions must be plainly marked as such, and must not be +* misrepresented as being the original software. +* 3. This notice may not be removed or altered from any source distribution. +*/ + +#ifndef MODEL_H +#define MODEL_H + +#include +#include +#include + +class Model +{ +public: + Model(); + + ~Model(); + + void Action_SelectTest(int selection); + void Action_RestartTest(); + void Action_PreviousTest(); + void Action_NextTest(); + void Action_DumpTest(); + void Action_PlayPause(); + void Action_SingleStep(); + void Action_LeftCamera(); + void Action_RightCamera(); + void Action_BottomCamera(); + void Action_TopCamera(); + void Action_BackCamera(); + void Action_FrontCamera(); + + void Command_Step(); + void Command_Press_Key(int button); + void Command_Release_Key(int button); + void Command_Press_Mouse_Left(const b3Vec2& ps); + void Command_Release_Mouse_Left(const b3Vec2& ps); + void Command_Move_Cursor(const b3Vec2& ps); + void Command_ResizeCamera(float32 w, float32 h); + void Command_RotateCameraX(float32 angle); + void Command_RotateCameraY(float32 angle); + void Command_TranslateCameraX(float32 d); + void Command_TranslateCameraY(float32 d); + void Command_ZoomCamera(float32 d); +private: + friend class View; + friend class Controller; + + DebugDraw m_debugDraw; + Camera m_camera; + Profiler m_profiler; + TestbedListener m_profilerListener; + + Settings m_settings; + Test* m_test; +}; + +inline void Model::Action_SelectTest(int selection) +{ + m_settings.testID = selection; + m_settings.lastTestID = -1; +} + +inline void Model::Action_RestartTest() +{ + m_settings.lastTestID = -1; +} + +inline void Model::Action_PreviousTest() +{ + m_settings.testID = b3Clamp(m_settings.testID - 1, 0, int(g_testCount) - 1); + m_settings.lastTestID = -1; +} + +inline void Model::Action_NextTest() +{ + m_settings.testID = b3Clamp(m_settings.testID + 1, 0, int(g_testCount) - 1); + m_settings.lastTestID = -1; +} + +inline void Model::Action_DumpTest() +{ + m_test->Dump(); +} + +inline void Model::Action_PlayPause() +{ + m_settings.pause = !m_settings.pause; +} + +inline void Model::Action_SingleStep() +{ + m_settings.pause = true; + m_settings.singleStep = true; +} + +inline void Model::Action_LeftCamera() +{ + m_camera.m_q.Set(b3Vec3(0.0f, 1.0f, 0.0f), 0.5f * B3_PI); + m_camera.m_center.SetZero(); + m_camera.m_zoom = 20.0f; +} + +inline void Model::Action_RightCamera() +{ + m_camera.m_q.Set(b3Vec3(0.0f, 1.0f, 0.0f), -0.5f * B3_PI); + m_camera.m_center.SetZero(); + m_camera.m_zoom = 20.0f; +} + +inline void Model::Action_BottomCamera() +{ + m_camera.m_q.Set(b3Vec3(1.0f, 0.0f, 0.0f), 0.5f * B3_PI); + m_camera.m_center.SetZero(); + m_camera.m_zoom = 20.0f; +} + +inline void Model::Action_TopCamera() +{ + m_camera.m_q.Set(b3Vec3(1.0f, 0.0f, 0.0f), -0.5f * B3_PI); + m_camera.m_center.SetZero(); + m_camera.m_zoom = 20.0f; +} + +inline void Model::Action_BackCamera() +{ + m_camera.m_q.Set(b3Vec3(0.0f, 1.0f, 0.0f), -B3_PI); + m_camera.m_center.SetZero(); + m_camera.m_zoom = 20.0f; +} + +inline void Model::Action_FrontCamera() +{ + m_camera.m_q.SetIdentity(); + m_camera.m_center.SetZero(); + m_camera.m_zoom = 20.0f; +} + +inline void Model::Command_Press_Key(int button) +{ + m_test->KeyDown(button); +} + +inline void Model::Command_Release_Key(int button) +{ + m_test->KeyUp(button); +} + +inline void Model::Command_Press_Mouse_Left(const b3Vec2& ps) +{ + Ray3 pw = m_camera.ConvertScreenToWorld(ps); + + m_test->MouseLeftDown(pw); +} + +inline void Model::Command_Release_Mouse_Left(const b3Vec2& ps) +{ + Ray3 pw = m_camera.ConvertScreenToWorld(ps); + + m_test->MouseLeftUp(pw); +} + +inline void Model::Command_Move_Cursor(const b3Vec2& ps) +{ + Ray3 pw = m_camera.ConvertScreenToWorld(ps); + + m_test->MouseMove(pw); +} + +inline void Model::Command_ResizeCamera(float32 w, float32 h) +{ + m_camera.m_width = w; + m_camera.m_height = h; +} + +inline void Model::Command_RotateCameraX(float32 angle) +{ + b3Quat d = b3QuatRotationX(angle); + + m_camera.m_q = m_camera.m_q * d; + m_camera.m_q.Normalize(); +} + +inline void Model::Command_RotateCameraY(float32 angle) +{ + b3Quat d = b3QuatRotationY(angle); + + m_camera.m_q = d * m_camera.m_q; + m_camera.m_q.Normalize(); +} + +inline void Model::Command_TranslateCameraX(float32 d) +{ + b3Transform transform = m_camera.BuildWorldTransform(); + + m_camera.m_center += d * transform.rotation.x; +} + +inline void Model::Command_TranslateCameraY(float32 d) +{ + b3Transform transform = m_camera.BuildWorldTransform(); + + m_camera.m_center += d * transform.rotation.y; +} + +inline void Model::Command_ZoomCamera(float32 d) +{ + m_camera.m_zoom += d; +} + +#endif \ No newline at end of file diff --git a/examples/testbed/framework/profiler.cpp b/examples/testbed/framework/profiler.cpp index 1c4aec9..bc72572 100644 --- a/examples/testbed/framework/profiler.cpp +++ b/examples/testbed/framework/profiler.cpp @@ -18,6 +18,9 @@ #include +Profiler* g_profiler = nullptr; +ProfilerListener* g_profilerListener = nullptr; + Profiler::Profiler() { m_top = nullptr; diff --git a/examples/testbed/framework/profiler.h b/examples/testbed/framework/profiler.h index 441863c..79dd23a 100644 --- a/examples/testbed/framework/profiler.h +++ b/examples/testbed/framework/profiler.h @@ -71,6 +71,8 @@ private: ProfilerEvent* m_top; }; +extern Profiler* g_profiler; + // Any implementation of this interface passed to Profiler::End will listen to profile events. class ProfilerListener { @@ -110,4 +112,6 @@ public: } }; +extern ProfilerListener* g_profilerListener; + #endif \ No newline at end of file diff --git a/examples/testbed/framework/test.cpp b/examples/testbed/framework/test.cpp index 4bac0c5..75b8353 100644 --- a/examples/testbed/framework/test.cpp +++ b/examples/testbed/framework/test.cpp @@ -22,14 +22,18 @@ extern u32 b3_allocCalls, b3_maxAllocCalls; extern u32 b3_gjkCalls, b3_gjkIters, b3_gjkMaxIters; extern bool b3_convexCache; extern u32 b3_convexCalls, b3_convexCacheHits; -extern b3Draw* b3_debugDraw; -extern Settings g_settings; -extern DebugDraw* g_debugDraw; -extern Camera g_camera; -extern Profiler* g_profiler; -extern ProfilerListener* g_profilerListener; -extern RecorderProfiler g_recorderProfiler; +bool b3PushProfileScope(const char* name) +{ + return g_profiler->PushEvent(name); +} + +void b3PopProfileScope() +{ + g_profiler->PopEvent(); +} + +Settings* g_settings = nullptr; Test::Test() { @@ -37,34 +41,17 @@ Test::Test() b3_gjkCalls = 0; b3_gjkIters = 0; b3_gjkMaxIters = 0; - b3_convexCache = g_settings.convexCache; + b3_convexCache = g_settings->convexCache; b3_convexCalls = 0; b3_convexCacheHits = 0; - b3_debugDraw = g_debugDraw; - - b3Quat q_y = b3QuatRotationY(0.15f * B3_PI); - b3Quat q_x = b3QuatRotationX(-0.15f * B3_PI); - - g_camera.m_q = q_y * q_x; - g_camera.m_zoom = 50.0f; - g_camera.m_center.SetZero(); + b3Draw_draw = g_debugDraw; m_world.SetContactListener(this); m_rayHit.shape = NULL; m_mouseJoint = NULL; - { - b3Transform m; - m.position.SetZero(); - m.rotation = b3Diagonal(50.0f, 1.0f, 50.0f); - m_groundHull.SetTransform(m); - } - - { - m_boxHull.SetIdentity(); - } - + m_groundHull.Set(50.0f, 1.0f, 50.0f); m_groundMesh.BuildTree(); } @@ -77,71 +64,42 @@ Test::~Test() b3_convexCache = false; b3_convexCalls = 0; b3_convexCacheHits = 0; - b3_debugDraw = nullptr; -} - -void Test::BeginContact(b3Contact* contact) -{ -} - -void Test::EndContact(b3Contact* contact) -{ - -} - -void Test::PreSolve(b3Contact* contact) -{ - + b3Draw_draw = nullptr; } void Test::Step() { - float32 dt = g_settings.hertz > 0.0f ? 1.0f / g_settings.hertz : 0.0f; - - if (g_settings.pause) - { - if (g_settings.singleStep) - { - g_settings.singleStep = false; - } - else - { - dt = 0.0f; - } - } - b3_allocCalls = 0; b3_gjkCalls = 0; b3_gjkIters = 0; b3_gjkMaxIters = 0; - b3_convexCache = g_settings.convexCache; + b3_convexCache = g_settings->convexCache; b3_convexCalls = 0; b3_convexCacheHits = 0; + float32 dt = g_settings->inv_hertz; + // Step - g_profiler->Begin(); + m_world.SetSleeping(g_settings->sleep); + m_world.SetWarmStart(g_settings->warmStart); + m_world.Step(dt, g_settings->velocityIterations, g_settings->positionIterations); - m_world.SetSleeping(g_settings.sleep); - m_world.SetWarmStart(g_settings.warmStart); - m_world.Step(dt, g_settings.velocityIterations, g_settings.positionIterations); - - g_profiler->End(g_profilerListener); - g_debugDraw->Submit(); // Draw World u32 drawFlags = 0; - drawFlags += g_settings.drawBounds * b3Draw::e_aabbsFlag; - drawFlags += g_settings.drawVerticesEdges * b3Draw::e_shapesFlag; - drawFlags += g_settings.drawCenterOfMasses * b3Draw::e_centerOfMassesFlag; - drawFlags += g_settings.drawJoints * b3Draw::e_jointsFlag; - drawFlags += g_settings.drawContactPoints * b3Draw::e_contactPointsFlag; - drawFlags += g_settings.drawContactNormals * b3Draw::e_contactNormalsFlag; - drawFlags += g_settings.drawContactTangents * b3Draw::e_contactTangentsFlag; - drawFlags += g_settings.drawContactPolygons * b3Draw::e_contactPolygonsFlag; + drawFlags += g_settings->drawBounds * b3Draw::e_aabbsFlag; + drawFlags += g_settings->drawVerticesEdges * b3Draw::e_shapesFlag; + drawFlags += g_settings->drawCenterOfMasses * b3Draw::e_centerOfMassesFlag; + drawFlags += g_settings->drawJoints * b3Draw::e_jointsFlag; + drawFlags += g_settings->drawContactPoints * b3Draw::e_contactPointsFlag; + drawFlags += g_settings->drawContactNormals * b3Draw::e_contactNormalsFlag; + drawFlags += g_settings->drawContactTangents * b3Draw::e_contactTangentsFlag; + drawFlags += g_settings->drawContactPolygons * b3Draw::e_contactPolygonsFlag; g_debugDraw->SetFlags(drawFlags); - m_world.DebugDraw(); + + m_world.Draw(); if (m_mouseJoint) { @@ -156,20 +114,16 @@ void Test::Step() g_debugDraw->Submit(); - if (g_settings.drawFaces) + if (g_settings->drawFaces) { g_debugDraw->Draw(m_world); } - // Draw Statistics - extern const char* g_logName; - ImGui::Begin(g_logName, NULL, ImVec2(0, 0), 0.0f, ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoInputs | ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_NoScrollbar); - - if (g_settings.drawStats) + if (g_settings->drawStats) { - ImGui::Text("Bodies %d", m_world.GetBodyList().m_count); - ImGui::Text("Joints %d", m_world.GetJointList().m_count); - ImGui::Text("Contacts %d", m_world.GetContactList().m_count); + g_debugDraw->DrawString(b3Color_white, "Bodies %d", m_world.GetBodyList().m_count); + g_debugDraw->DrawString(b3Color_white, "Joints %d", m_world.GetJointList().m_count); + g_debugDraw->DrawString(b3Color_white, "Contacts %d", m_world.GetContactList().m_count); float32 avgGjkIters = 0.0f; if (b3_gjkCalls > 0) @@ -177,8 +131,8 @@ void Test::Step() avgGjkIters = float32(b3_gjkIters) / float32(b3_gjkCalls); } - ImGui::Text("GJK Calls %d", b3_gjkCalls); - ImGui::Text("GJK Iterations %d (%d) (%f)", b3_gjkIters, b3_gjkMaxIters, avgGjkIters); + g_debugDraw->DrawString(b3Color_white, "GJK Calls %d", b3_gjkCalls); + g_debugDraw->DrawString(b3Color_white, "GJK Iterations %d (%d) (%f)", b3_gjkIters, b3_gjkMaxIters, avgGjkIters); float32 convexCacheHitRatio = 0.0f; if (b3_convexCalls > 0) @@ -186,23 +140,10 @@ void Test::Step() convexCacheHitRatio = float32(b3_convexCacheHits) / float32(b3_convexCalls); } - ImGui::Text("Convex Calls %d", b3_convexCalls); - ImGui::Text("Convex Cache Hits %d (%f)", b3_convexCacheHits, convexCacheHitRatio); - ImGui::Text("Frame Allocations %d (%d)", b3_allocCalls, b3_maxAllocCalls); + g_debugDraw->DrawString(b3Color_white, "Convex Calls %d", b3_convexCalls); + g_debugDraw->DrawString(b3Color_white, "Convex Cache Hits %d (%f)", b3_convexCacheHits, convexCacheHitRatio); + g_debugDraw->DrawString(b3Color_white, "Frame Allocations %d (%d)", b3_allocCalls, b3_maxAllocCalls); } - - if (g_settings.drawProfile) - { - const b3Array& records = g_recorderProfiler.GetRecords(); - for (u32 i = 0; i < records.Count(); ++i) - { - const ProfilerRecord& r = records[i]; - - ImGui::Text("%s %.4f (%.4f) [ms]", r.name, r.elapsed, r.maxElapsed); - } - } - - ImGui::End(); } void Test::MouseMove(const Ray3& pw) diff --git a/examples/testbed/framework/test_entries.cpp b/examples/testbed/framework/test_entries.cpp index 47679f1..804d5e5 100644 --- a/examples/testbed/framework/test_entries.cpp +++ b/examples/testbed/framework/test_entries.cpp @@ -117,4 +117,18 @@ TestEntry g_tests[] = { "Mass-Spring System", &MassSpring::Create }, { "Shift Center", &ShiftCenter::Create }, { NULL, NULL } -}; \ No newline at end of file +}; + +// +static u32 TestCount() +{ + u32 count = 0; + while (g_tests[count].create != NULL) + { + ++count; + } + return count; +} + +// Count the tests +u32 g_testCount = TestCount(); \ No newline at end of file diff --git a/examples/testbed/framework/testbed_listener.h b/examples/testbed/framework/testbed_listener.h index dd7f60f..7588f66 100644 --- a/examples/testbed/framework/testbed_listener.h +++ b/examples/testbed/framework/testbed_listener.h @@ -30,14 +30,13 @@ #include #endif -extern RecorderProfiler g_recorderProfiler; class TestbedListener : public ProfilerListener { public: void BeginEvents() override { - g_recorderProfiler.BeginEvents(); + m_recorderProfiler.BeginEvents(); #if (PROFILE_JSON == 1) m_jsonListener.BeginEvents(); @@ -47,7 +46,7 @@ public: void EndEvents() override { - g_recorderProfiler.EndEvents(); + m_recorderProfiler.EndEvents(); #if (PROFILE_JSON == 1) m_jsonListener.EndEvents(); @@ -73,9 +72,11 @@ public: void Duration(const char* name, float64 time) override { - g_recorderProfiler.Add(name, time); + m_recorderProfiler.Add(name, time); } + RecorderProfiler m_recorderProfiler; + #if (PROFILE_JSON == 1) JsonProfiler m_jsonListener; #endif diff --git a/examples/testbed/framework/view.cpp b/examples/testbed/framework/view.cpp new file mode 100644 index 0000000..cf32c5c --- /dev/null +++ b/examples/testbed/framework/view.cpp @@ -0,0 +1,261 @@ +#include +#include + +#if defined (U_OPENGL_2) + #include +#elif defined (U_OPENGL_4) + #include +#else + +#endif + +static bool GetTestName(void* userData, int idx, const char** name) +{ + assert(u32(idx) < g_testCount); + *name = g_tests[idx].name; + return true; +} + +static inline bool ImGui_GLFW_GL_Init(GLFWwindow* w, bool install_callbacks) +{ + +#if defined(U_OPENGL_2) + + return ImGui_ImplGlfwGL2_Init(w, install_callbacks); + +#elif defined(U_OPENGL_4) + + return ImGui_ImplGlfwGL3_Init(w, install_callbacks); + +#else + + // error + +#endif + +} + +static inline void ImGui_GLFW_GL_Shutdown() +{ + +#if defined(U_OPENGL_2) + + ImGui_ImplGlfwGL2_Shutdown(); + +#elif defined(U_OPENGL_4) + + ImGui_ImplGlfwGL3_Shutdown(); + +#else + + // error + +#endif + +} + +static inline void ImGui_GLFW_GL_NewFrame() +{ + +#if defined(U_OPENGL_2) + + ImGui_ImplGlfwGL2_NewFrame(); + +#elif defined(U_OPENGL_4) + + ImGui_ImplGlfwGL3_NewFrame(); + +#else + + // error + +#endif + +} + +static inline void ImGui_GLFW_GL_RenderDrawData(ImDrawData* draw_data) +{ + +#if defined(U_OPENGL_2) + + ImGui_ImplGlfwGL2_RenderDrawData(draw_data); + +#elif defined(U_OPENGL_4) + + ImGui_ImplGlfwGL3_RenderDrawData(draw_data); + +#else + + // error + +#endif + +} + +View::View(GLFWwindow* window, Model* model) +{ + m_window = window; + m_model = model; + + // Create UI + ImGui::CreateContext(); + + ImGuiIO& io = ImGui::GetIO(); + io.Fonts[0].AddFontDefault(); + + ImGui_GLFW_GL_Init(m_window, false); + + ImGui::StyleColorsLight(); +} + +View::~View() +{ + // Destroy UI + ImGui_GLFW_GL_Shutdown(); + + ImGui::DestroyContext(); +} + +void View::Command_PreDraw() +{ + ImGui_GLFW_GL_NewFrame(); +} + +void View::Command_Draw() +{ + Camera& camera = m_model->m_camera; + Settings& settings = m_model->m_settings; + + ImVec2 buttonSize(-1.0f, 0.0f); + + ImGui::SetNextWindowPos(ImVec2(camera.m_width - 250.0f, 0.0f)); + ImGui::SetNextWindowSize(ImVec2(250.0f, camera.m_height)); + ImGui::PushStyleVar(ImGuiStyleVar_WindowRounding, 0.0f); + + ImGui::Begin("Controller", NULL, ImVec2(0.0f, 0.0f), 0.25f, ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoResize); + + ImGui::PushItemWidth(-1.0f); + + ImGui::Separator(); + + ImGui::Text("Test"); + + ImGui::Separator(); + + if (ImGui::Combo("##Test", &settings.testID, GetTestName, NULL, g_testCount, g_testCount)) + { + m_model->Action_SelectTest(settings.testID); + } + + if (ImGui::Button("Restart", buttonSize)) + { + m_model->Action_RestartTest(); + } + + if (ImGui::Button("Previous", buttonSize)) + { + m_model->Action_PreviousTest(); + } + + if (ImGui::Button("Next", buttonSize)) + { + m_model->Action_NextTest(); + } + + if (ImGui::Button("Dump", buttonSize)) + { + m_model->Action_DumpTest(); + } + + if (ImGui::Button("Exit", buttonSize)) + { + glfwSetWindowShouldClose(m_window, true); + } + + ImGui::Separator(); + + ImGui::Text("Step"); + + ImGui::Separator(); + + ImGui::Text("Hertz"); + ImGui::SliderFloat("##Hertz", &settings.hertz, 0.0f, 240.0f, "%.1f"); + ImGui::Text("Velocity Iterations"); + ImGui::SliderInt("##Velocity Iterations", &settings.velocityIterations, 0, 50); + ImGui::Text("Position Iterations"); + ImGui::SliderInt("#Position Iterations", &settings.positionIterations, 0, 50); + ImGui::Checkbox("Sleep", &settings.sleep); + ImGui::Checkbox("Convex Cache", &settings.convexCache); + ImGui::Checkbox("Warm Start", &settings.warmStart); + + if (ImGui::Button("Play/Pause", buttonSize)) + { + m_model->Action_PlayPause(); + } + + if (ImGui::Button("Single Step", buttonSize)) + { + m_model->Action_SingleStep(); + } + + ImGui::Separator(); + + ImGui::Text("View"); + + ImGui::Separator(); + + ImGui::Checkbox("Reference Grid", &settings.drawGrid); + ImGui::Checkbox("Vertices and Edges", &settings.drawVerticesEdges); + ImGui::Checkbox("Faces", &settings.drawFaces); + ImGui::Checkbox("Center of Masses", &settings.drawCenterOfMasses); + ImGui::Checkbox("Bounding Boxes", &settings.drawBounds); + ImGui::Checkbox("Joints", &settings.drawJoints); + ImGui::Checkbox("Contact Points", &settings.drawContactPoints); + ImGui::Checkbox("Contact Normals", &settings.drawContactNormals); + ImGui::Checkbox("Contact Tangents", &settings.drawContactTangents); + ImGui::Checkbox("Contact Polygons", &settings.drawContactPolygons); + ImGui::Checkbox("Statistics", &settings.drawStats); + ImGui::Checkbox("Profile", &settings.drawProfile); + + ImGui::Separator(); + + if (ImGui::Button("Left", buttonSize)) + { + m_model->Action_LeftCamera(); + } + + if (ImGui::Button("Right", buttonSize)) + { + m_model->Action_RightCamera(); + } + + if (ImGui::Button("Bottom", buttonSize)) + { + m_model->Action_BottomCamera(); + } + + if (ImGui::Button("Top", buttonSize)) + { + m_model->Action_TopCamera(); + } + + if (ImGui::Button("Back", buttonSize)) + { + m_model->Action_BackCamera(); + } + + if (ImGui::Button("Front", buttonSize)) + { + m_model->Action_FrontCamera(); + } + + ImGui::End(); + ImGui::PopStyleVar(); +} + +void View::Command_PostDraw() +{ + ImGui::Render(); + + ImGui_GLFW_GL_RenderDrawData(ImGui::GetDrawData()); +} \ No newline at end of file diff --git a/examples/testbed/framework/view.h b/examples/testbed/framework/view.h new file mode 100644 index 0000000..a5042c7 --- /dev/null +++ b/examples/testbed/framework/view.h @@ -0,0 +1,43 @@ +/* +* Copyright (c) 2016-2016 Irlan Robson http://www.irlan.net +* +* This software is provided 'as-is', without any express or implied +* warranty. In no event will the authors be held liable for any damages +* arising from the use of this software. +* Permission is granted to anyone to use this software for any purpose, +* including commercial applications, and to alter it and redistribute it +* freely, subject to the following restrictions: +* 1. The origin of this software must not be misrepresented; you must not +* claim that you wrote the original software. If you use this software +* in a product, an acknowledgment in the product documentation would be +* appreciated but is not required. +* 2. Altered source versions must be plainly marked as such, and must not be +* misrepresented as being the original software. +* 3. This notice may not be removed or altered from any source distribution. +*/ + +#ifndef VIEW_H +#define VIEW_H + +struct GLFWwindow; +class Model; + +class View +{ +public: + View(GLFWwindow* window, Model* model); + + ~View(); + + void Command_PreDraw(); + + void Command_Draw(); + + void Command_PostDraw(); +private: + GLFWwindow * m_window; + + Model* m_model; +}; + +#endif \ No newline at end of file diff --git a/examples/testbed/tests/body_types.h b/examples/testbed/tests/body_types.h index 92458d9..c41efed 100644 --- a/examples/testbed/tests/body_types.h +++ b/examples/testbed/tests/body_types.h @@ -24,8 +24,6 @@ class BodyTypes : public Test public: BodyTypes() { - g_camera.m_zoom = 50.0f; - { b3BodyDef bd; b3Body* ground = m_world.CreateBody(bd); @@ -66,12 +64,11 @@ public: { Test::Step(); - b3Color color(1.0f, 1.0f, 1.0f); - g_debugDraw->DrawString("S - Static", color); - g_debugDraw->DrawString("D - Dynamic", color); - g_debugDraw->DrawString("K - Kinematic", color); - g_debugDraw->DrawString("Space - Throw Bomb", color); - g_debugDraw->DrawString("Arrows - Apply Force/Velocity/Position", color); + g_debugDraw->DrawString(b3Color_white, "S - Static"); + g_debugDraw->DrawString(b3Color_white, "D - Dynamic"); + g_debugDraw->DrawString(b3Color_white, "K - Kinematic"); + g_debugDraw->DrawString(b3Color_white, "Space - Throw Bomb"); + g_debugDraw->DrawString(b3Color_white, "Arrows - Apply Force/Velocity/Position"); } void KeyDown(int button) diff --git a/examples/testbed/tests/box_stack.h b/examples/testbed/tests/box_stack.h index af150b4..6cf636a 100644 --- a/examples/testbed/tests/box_stack.h +++ b/examples/testbed/tests/box_stack.h @@ -31,9 +31,6 @@ public: BoxStack() { - g_camera.m_center.Set(2.5f, -2.0f, 5.5f); - g_camera.m_zoom = 40.0f; - { b3BodyDef bdef; bdef.type = b3BodyType::e_staticBody; @@ -52,14 +49,6 @@ public: b3Vec3 boxScale(1.0f, 1.0f, 1.0f); - static b3BoxHull boxHull; - - b3Transform m; - m.rotation = b3Diagonal(boxScale.x, boxScale.y, boxScale.z); - m.position.SetZero(); - - boxHull.SetTransform(m); - b3Vec3 stackOrigin(0.0f, 4.05f, 0.0f); for (u32 i = 0; i < e_rowCount; ++i) @@ -81,7 +70,7 @@ public: b3Body* body = m_world.CreateBody(bdef); b3HullShape hs; - hs.m_hull = &boxHull; + hs.m_hull = &b3BoxHull_identity; b3ShapeDef sdef; sdef.density = 0.1f; diff --git a/examples/testbed/tests/cloth_test.h b/examples/testbed/tests/cloth_test.h index 9cd3540..32d29a5 100644 --- a/examples/testbed/tests/cloth_test.h +++ b/examples/testbed/tests/cloth_test.h @@ -19,17 +19,11 @@ #ifndef CLOTH_H #define CLOTH_H -extern DebugDraw* g_debugDraw; -extern Camera g_camera; -extern Settings g_settings; - class Cloth : public Test { public: Cloth() { - g_camera.m_zoom = 25.0f; - b3ClothDef def; def.mesh = &m_clothMesh; def.density = 0.2f; @@ -57,22 +51,8 @@ public: void Step() { - float32 dt = g_settings.hertz > 0.0f ? 1.0f / g_settings.hertz : 0.0f; - - if (g_settings.pause) - { - if (g_settings.singleStep) - { - g_settings.singleStep = false; - } - else - { - dt = 0.0f; - } - } - - m_cloth.Step(dt, g_settings.positionIterations); - m_cloth.Draw(g_debugDraw); + m_cloth.Step(g_settings->inv_hertz, g_settings->positionIterations); + m_cloth.Draw(); } static Test* Create() diff --git a/examples/testbed/tests/cluster_test.h b/examples/testbed/tests/cluster_test.h index 3c05c59..2dc305e 100644 --- a/examples/testbed/tests/cluster_test.h +++ b/examples/testbed/tests/cluster_test.h @@ -21,16 +21,11 @@ #include -extern DebugDraw* g_debugDraw; -extern Camera g_camera; - class Cluster : public Test { public: Cluster() { - g_camera.m_zoom = 10.0f; - // Initialize observations for (u32 i = 0; i < 90; ++i) { diff --git a/examples/testbed/tests/collide_test.h b/examples/testbed/tests/collide_test.h index ea025b2..78e5cd8 100644 --- a/examples/testbed/tests/collide_test.h +++ b/examples/testbed/tests/collide_test.h @@ -19,16 +19,12 @@ #ifndef COLLIDE_H #define COLLIDE_H -extern DebugDraw* g_debugDraw; -extern Camera g_camera; -extern Settings g_settings; - class Collide : public Test { public: Collide() { - g_camera.m_zoom = 25.0f; + } void Step() @@ -48,19 +44,19 @@ public: wm.Initialize(&manifold, m_shapeA->m_radius, m_xfA, m_shapeB->m_radius, m_xfB); b3Vec3 pw = wm.points[i].point; - b3Vec2 ps = g_camera.ConvertWorldToScreen(pw); + b3Vec2 ps = g_camera->ConvertWorldToScreen(pw); g_debugDraw->DrawPoint(pw, 4.0f, b3Color(0.0f, 1.0f, 0.0f)); g_debugDraw->DrawSegment(pw, pw + wm.points[i].normal, b3Color(1.0f, 1.0f, 1.0f)); } - if (g_settings.drawFaces) + if (g_settings->drawFaces) { g_debugDraw->DrawShape(m_shapeA, b3Color(1.0f, 1.0f, 1.0f, 0.5f), m_xfA); g_debugDraw->DrawShape(m_shapeB, b3Color(1.0f, 1.0f, 1.0f, 0.5f), m_xfB); } - if (g_settings.drawVerticesEdges) + if (g_settings->drawVerticesEdges) { m_world.DrawShape(m_xfA, m_shapeA); m_world.DrawShape(m_xfB, m_shapeB); diff --git a/examples/testbed/tests/cone_test.h b/examples/testbed/tests/cone_test.h index f262fc2..dfa6691 100644 --- a/examples/testbed/tests/cone_test.h +++ b/examples/testbed/tests/cone_test.h @@ -24,11 +24,6 @@ class ConeTest : public Test public: ConeTest() { - g_camera.m_zoom = 15.0f; - g_camera.m_q = b3Quat(b3Vec3(0.0f, 1.0f, 0.0f), 0.15f * B3_PI); - g_camera.m_q = g_camera.m_q * b3Quat(b3Vec3(1.0f, 0.0f, 0.0f), -0.2f * B3_PI); - g_camera.m_center.Set(0.0f, 0.0f, 0.0f); - b3Body* ref; b3Body* head; diff --git a/examples/testbed/tests/distance_test.h b/examples/testbed/tests/distance_test.h index 9a3a906..d5c4464 100644 --- a/examples/testbed/tests/distance_test.h +++ b/examples/testbed/tests/distance_test.h @@ -19,17 +19,11 @@ #ifndef DISTANCE_H #define DISTANCE_H -extern DebugDraw* g_debugDraw; -extern Camera g_camera; -extern Settings g_settings; - class Distance : public Test { public: Distance() { - g_camera.m_zoom = 25.0f; - m_xfA.SetIdentity(); m_xfA.position.Set(-5.0f, 0.0f, 0.0f); m_xfA.rotation.SetIdentity(); @@ -40,7 +34,7 @@ public: m_xfB.SetIdentity(); m_xfB.position.Set(5.0f, 0.0f, 0.0f); m_xfB.rotation.SetIdentity(); - m_shapeB.m_hull = &m_boxHull; + m_shapeB.m_hull = &b3BoxHull_identity; m_proxyA.Set(&m_shapeA, 0); m_proxyB.Set(&m_shapeB, 0); diff --git a/examples/testbed/tests/gyro_test.h b/examples/testbed/tests/gyro_test.h index 38c7f9c..2dee7a1 100644 --- a/examples/testbed/tests/gyro_test.h +++ b/examples/testbed/tests/gyro_test.h @@ -21,10 +21,6 @@ #include -extern DebugDraw* g_debugDraw; -extern Camera g_camera; -extern Settings g_settings; - class GyroTest : public Test { public: diff --git a/examples/testbed/tests/hinge_chain.h b/examples/testbed/tests/hinge_chain.h index 376b7e3..3cc2e6b 100644 --- a/examples/testbed/tests/hinge_chain.h +++ b/examples/testbed/tests/hinge_chain.h @@ -24,11 +24,6 @@ class HingeChain : public Test public: HingeChain() { - g_camera.m_zoom = 100.0f; - g_camera.m_q = b3Quat(b3Vec3(0.0f, 1.0f, 0.0f), 0.15f * B3_PI); - g_camera.m_q = g_camera.m_q * b3Quat(b3Vec3(1.0f, 0.0f, 0.0f), -0.15f * B3_PI); - g_camera.m_center.SetZero(); - static b3BoxHull doorHull; { b3Transform xf; diff --git a/examples/testbed/tests/initial_overlap.h b/examples/testbed/tests/initial_overlap.h index c54576b..b3e7156 100644 --- a/examples/testbed/tests/initial_overlap.h +++ b/examples/testbed/tests/initial_overlap.h @@ -24,9 +24,6 @@ class InitialOverlap : public Test public: InitialOverlap() { - g_camera.m_center.Set(2.0f, -2.0f, 0.0f); - g_camera.m_zoom = 10.0f; - { b3BodyDef bd; b3Body* body = m_world.CreateBody(bd); diff --git a/examples/testbed/tests/jenga.h b/examples/testbed/tests/jenga.h index 377cad3..8695def 100644 --- a/examples/testbed/tests/jenga.h +++ b/examples/testbed/tests/jenga.h @@ -30,9 +30,6 @@ public: Jenga() { - g_camera.m_center.Set(2.0f, -2.0f, 0.0f); - g_camera.m_zoom = 60.0f; - { b3BodyDef bd; b3Body* body = m_world.CreateBody(bd); diff --git a/examples/testbed/tests/mass_spring.h b/examples/testbed/tests/mass_spring.h index 3d1204e..8c23b92 100644 --- a/examples/testbed/tests/mass_spring.h +++ b/examples/testbed/tests/mass_spring.h @@ -19,17 +19,11 @@ #ifndef MASS_SPRING_H #define MASS_SPRING_H -extern DebugDraw* g_debugDraw; -extern Camera g_camera; -extern Settings g_settings; - class MassSpring : public Test { public: MassSpring() { - g_camera.m_zoom = 20.0f; - m_x.Set(0.0f, 5.0f, 0.0f); m_v.SetZero(); @@ -132,36 +126,18 @@ public: void Step() { - float32 h = g_settings.hertz > 0.0f ? 1.0f / g_settings.hertz : 0.0f; - - if (g_settings.pause) - { - if (g_settings.singleStep) - { - g_settings.singleStep = false; - } - else - { - h = 0.0f; - } - } + float32 h = g_settings->inv_hertz; Solve(h); g_debugDraw->DrawSolidSphere(m_x, 0.25f, b3Color_white); - b3Vec3 b3Vec3_zero; - b3Vec3_zero.SetZero(); g_debugDraw->DrawSegment(b3Vec3_zero, m_x, b3Color_white); - char text1[64]; - sprintf(text1, "Iterations = %u", m_iterations); - g_debugDraw->DrawString(text1, b3Color_white); + g_debugDraw->DrawString(b3Color_white, "Iterations = %u", m_iterations); - char text2[64]; float32 E = 0.5f * b3Dot(m_v, m_v); - sprintf(text2, "E = %f", E); - g_debugDraw->DrawString(text2, b3Color_white); + g_debugDraw->DrawString(b3Color_white, "E = %f", E); } static Test* Create() diff --git a/examples/testbed/tests/mesh_contact_test.h b/examples/testbed/tests/mesh_contact_test.h index f788c6f..173d739 100644 --- a/examples/testbed/tests/mesh_contact_test.h +++ b/examples/testbed/tests/mesh_contact_test.h @@ -114,7 +114,7 @@ public: if (key == GLFW_KEY_H) { b3HullShape hull; - hull.m_hull = &m_boxHull; + hull.m_hull = &b3BoxHull_identity; b3ShapeDef sd; sd.shape = &hull; @@ -163,13 +163,11 @@ public: { Test::Step(); - b3Color color(1.0f, 1.0f, 1.0f); - - g_debugDraw->DrawString("S - Sphere", color); - g_debugDraw->DrawString("C - Capsule", color); - g_debugDraw->DrawString("H - Hull", color); - g_debugDraw->DrawString("G - Grid", color); - g_debugDraw->DrawString("T - Terrain", color); + g_debugDraw->DrawString(b3Color_white, "S - Sphere"); + g_debugDraw->DrawString(b3Color_white, "C - Capsule"); + g_debugDraw->DrawString(b3Color_white, "H - Hull"); + g_debugDraw->DrawString(b3Color_white, "G - Grid"); + g_debugDraw->DrawString(b3Color_white, "T - Terrain"); } static Test* Create() diff --git a/examples/testbed/tests/multiple_pendulum.h b/examples/testbed/tests/multiple_pendulum.h index 4713aea..487b73f 100644 --- a/examples/testbed/tests/multiple_pendulum.h +++ b/examples/testbed/tests/multiple_pendulum.h @@ -24,8 +24,6 @@ class MultiplePendulum : public Test public: MultiplePendulum() { - g_camera.m_zoom = 10.0f; - b3Vec3 axis(0.0f, 0.0f, 1.0f); b3Body* bs[6]; diff --git a/examples/testbed/tests/multiple_shapes.h b/examples/testbed/tests/multiple_shapes.h index 4d4808f..f0fa841 100644 --- a/examples/testbed/tests/multiple_shapes.h +++ b/examples/testbed/tests/multiple_shapes.h @@ -24,8 +24,6 @@ class MultipleShapes : public Test public: MultipleShapes() { - g_settings.drawCenterOfMasses = true; - { b3BodyDef bd; b3Body* body = m_world.CreateBody(bd); diff --git a/examples/testbed/tests/pyramid.h b/examples/testbed/tests/pyramid.h index 06a8336..ecb3235 100644 --- a/examples/testbed/tests/pyramid.h +++ b/examples/testbed/tests/pyramid.h @@ -29,8 +29,6 @@ public: Pyramid() { - g_camera.m_zoom = 100.0f; - { b3BodyDef bd; b3Body* ground = m_world.CreateBody(bd); @@ -71,7 +69,7 @@ public: b3Body* body = m_world.CreateBody(bd); b3HullShape hs; - hs.m_hull = &m_boxHull; + hs.m_hull = &b3BoxHull_identity; b3ShapeDef sd; sd.shape = &hs; diff --git a/examples/testbed/tests/pyramids.h b/examples/testbed/tests/pyramids.h index 9ae0d16..60f4cff 100644 --- a/examples/testbed/tests/pyramids.h +++ b/examples/testbed/tests/pyramids.h @@ -30,8 +30,6 @@ public: Pyramids() { - g_camera.m_zoom = 100.0f; - { b3BodyDef bd; b3Body* ground = m_world.CreateBody(bd); @@ -74,7 +72,7 @@ public: b3Body* body = m_world.CreateBody(bd); b3HullShape hs; - hs.m_hull = &m_boxHull; + hs.m_hull = &b3BoxHull_identity; b3ShapeDef sd; sd.shape = &hs; diff --git a/examples/testbed/tests/quadric_shapes.h b/examples/testbed/tests/quadric_shapes.h index 30cb344..43de380 100644 --- a/examples/testbed/tests/quadric_shapes.h +++ b/examples/testbed/tests/quadric_shapes.h @@ -21,19 +21,11 @@ #include -extern DebugDraw* g_debugDraw; -extern Camera g_camera; -extern Settings g_settings; - class QuadricShapes : public Test { public: QuadricShapes() { - g_camera.m_center.Set(2.0f, -2.0f, 0.0f); - g_camera.m_zoom = 20.0f; - g_settings.drawCenterOfMasses = true; - { b3BodyDef bd; b3Body* ground = m_world.CreateBody(bd); diff --git a/examples/testbed/tests/quickhull_test.h b/examples/testbed/tests/quickhull_test.h index 3b0a3ce..844484f 100644 --- a/examples/testbed/tests/quickhull_test.h +++ b/examples/testbed/tests/quickhull_test.h @@ -21,74 +21,6 @@ #include -extern DebugDraw* g_debugDraw; -extern Camera g_camera; -extern Settings g_settings; - -inline b3Vec3 ComputeCentroid(const b3Hull& h) -{ - b3Vec3 c(0.0f, 0.0f, 0.0f); - float32 volume = 0.0f; - - // Pick reference point not too away from the origin - // to minimize floating point rounding errors. - b3Vec3 p1(0.0f, 0.0f, 0.0f); - // Put it inside the hull. - for (u32 i = 0; i < h.vertexCount; ++i) - { - p1 += h.vertices[i]; - } - p1 *= 1.0f / float32(h.vertexCount); - - const float32 inv4 = 0.25f; - const float32 inv6 = 1.0f / 6.0f; - const float32 inv60 = 1.0f / 60.0f; - const float32 inv120 = 1.0f / 120.0f; - - b3Vec3 diag(0.0f, 0.0f, 0.0f); - b3Vec3 offDiag(0.0f, 0.0f, 0.0f); - - // Triangulate convex polygons - for (u32 i = 0; i < h.faceCount; ++i) - { - const b3Face* face = h.GetFace(i); - const b3HalfEdge* begin = h.GetEdge(face->edge); - - const b3HalfEdge* edge = h.GetEdge(begin->next); - do - { - u32 i1 = begin->origin; - u32 i2 = edge->origin; - const b3HalfEdge* next = h.GetEdge(edge->next); - u32 i3 = next->origin; - - b3Vec3 p2 = h.vertices[i1]; - b3Vec3 p3 = h.vertices[i2]; - b3Vec3 p4 = h.vertices[i3]; - - b3Vec3 e1 = p2 - p1; - b3Vec3 e2 = p3 - p1; - b3Vec3 e3 = p4 - p1; - - float32 D = b3Det(e1, e2, e3); - - float32 tetraVolume = inv6 * D; - volume += tetraVolume; - - // Volume weighted centroid - c += tetraVolume * inv4 * (e1 + e2 + e3); - - edge = next; - } while (h.GetEdge(edge->next) != begin); - } - - // Centroid - B3_ASSERT(volume > B3_EPSILON); - c *= 1.0f / volume; - c += p1; - return c; -} - struct Pair { void* key; @@ -259,7 +191,7 @@ inline b3Hull ConvertHull(const qhHull& hull) out.faceCount = faceCount; out.faces = faces; out.planes = planes; - out.centroid = ComputeCentroid(out); + out.centroid = out.GetCentroid(); out.Validate(); return out; } @@ -347,8 +279,6 @@ class QuickhullTest : public Test public: QuickhullTest() { - g_camera.m_zoom = 15.0f; - b3BoxHull box; box.SetIdentity(); diff --git a/examples/testbed/tests/ray_cast.h b/examples/testbed/tests/ray_cast.h index 524aa96..2255741 100644 --- a/examples/testbed/tests/ray_cast.h +++ b/examples/testbed/tests/ray_cast.h @@ -19,8 +19,6 @@ #ifndef RAY_CAST_H #define RAY_CAST_H -extern Settings g_settings; - class RayCast : public Test { public: @@ -49,7 +47,7 @@ public: b3Body* body = m_world.CreateBody(bdef); b3HullShape hs; - hs.m_hull = &m_boxHull; + hs.m_hull = &b3BoxHull_identity; b3ShapeDef sdef; sdef.shape = &hs; @@ -91,7 +89,7 @@ public: b3Body* body = m_world.CreateBody(bdef); b3HullShape hs; - hs.m_hull = &m_boxHull; + hs.m_hull = &b3BoxHull_identity; b3ShapeDef sdef; sdef.density = 0.0f; @@ -111,7 +109,7 @@ public: b3Body* body = m_world.CreateBody(bdef); b3HullShape hs; - hs.m_hull = &m_boxHull; + hs.m_hull = &b3BoxHull_identity; b3ShapeDef sdef; sdef.density = 0.0f; @@ -131,7 +129,7 @@ public: b3Body* body = m_world.CreateBody(bdef); b3HullShape hs; - hs.m_hull = &m_boxHull; + hs.m_hull = &b3BoxHull_identity; b3ShapeDef sdef; sdef.density = 0.0f; @@ -151,7 +149,7 @@ public: b3Body* body = m_world.CreateBody(bdef); b3HullShape hs; - hs.m_hull = &m_boxHull; + hs.m_hull = &b3BoxHull_identity; b3ShapeDef sdef; sdef.density = 0.0f; @@ -228,7 +226,8 @@ public: void Step() { - float32 dt = g_settings.hertz > 0.0f ? 1.0f / g_settings.hertz : 0.0f; + float32 dt = g_settings->inv_hertz; + b3Quat q(b3Vec3(0.0f, 1.0f, 0.0f), dt * 0.05f * B3_PI); m_p1 = b3Mul(q, m_p1); @@ -252,4 +251,4 @@ public: b3Vec3 m_p12, m_p22; }; -#endif +#endif \ No newline at end of file diff --git a/examples/testbed/tests/rope_test.h b/examples/testbed/tests/rope_test.h index 6699a14..5e41bfe 100644 --- a/examples/testbed/tests/rope_test.h +++ b/examples/testbed/tests/rope_test.h @@ -19,8 +19,6 @@ #ifndef ROPE_TEST_H #define ROPE_TEST_H -extern Settings g_settings; - class Rope : public Test { public: @@ -31,8 +29,6 @@ public: Rope() { - g_camera.m_zoom = 30.0f; - b3Vec3 vs[e_count]; float32 ms[e_count]; @@ -89,22 +85,8 @@ public: void Step() { - float32 dt = g_settings.hertz > 0.0f ? 1.0f / g_settings.hertz : 0.0f; - - if (g_settings.pause) - { - if (g_settings.singleStep) - { - g_settings.singleStep = false; - } - else - { - dt = 0.0f; - } - } - - m_rope.Step(dt); - m_rope.Draw(g_debugDraw); + m_rope.Step(g_settings->inv_hertz); + m_rope.Draw(); } static Test* Create() diff --git a/examples/testbed/tests/shape_stack.h b/examples/testbed/tests/shape_stack.h index f4f1ef1..a22b6ba 100644 --- a/examples/testbed/tests/shape_stack.h +++ b/examples/testbed/tests/shape_stack.h @@ -89,7 +89,7 @@ public: b3Body* body = m_world.CreateBody(bd); b3HullShape hull; - hull.m_hull = &m_boxHull; + hull.m_hull = &b3BoxHull_identity; b3ShapeDef sd; sd.shape = &hull; diff --git a/examples/testbed/tests/shift_center.h b/examples/testbed/tests/shift_center.h index 29e0246..8abb0e3 100644 --- a/examples/testbed/tests/shift_center.h +++ b/examples/testbed/tests/shift_center.h @@ -21,19 +21,11 @@ #include -extern DebugDraw* g_debugDraw; -extern Camera g_camera; -extern Settings g_settings; - class ShiftCenter : public Test { public: ShiftCenter() { - g_camera.m_center.Set(2.0f, -2.0f, 0.0f); - g_camera.m_zoom = 20.0f; - g_settings.drawCenterOfMasses = true; - { b3BodyDef bd; b3Body* ground = m_world.CreateBody(bd); diff --git a/examples/testbed/tests/single_pendulum.h b/examples/testbed/tests/single_pendulum.h index 2432572..f8b3b63 100644 --- a/examples/testbed/tests/single_pendulum.h +++ b/examples/testbed/tests/single_pendulum.h @@ -19,9 +19,6 @@ #ifndef PENDULUM_H #define PENDULUM_H -extern Settings g_settings; -extern DebugDraw* g_debugDraw; - class SinglePendulum : public Test { public: @@ -40,19 +37,7 @@ public: void Step() { - float32 h = g_settings.hertz > 0.0f ? 1.0f / g_settings.hertz : 0.0f; - - if (g_settings.pause) - { - if (g_settings.singleStep) - { - g_settings.singleStep = false; - } - else - { - h = 0.0f; - } - } + float32 h = g_settings->inv_hertz; // Solution (acceleration) float32 omega_dot = -m_g / m_r * sin(m_theta); @@ -83,9 +68,8 @@ public: // Lagrangian float32 L = T - V; - static char s[256]; - sprintf(s, "T = %f \nV = %f \nL = %f", T, V, L); - g_debugDraw->DrawString(s, b3Color_white); + // + g_debugDraw->DrawString(b3Color_white, "T = %f \nV = %f \nL = %f", T, V, L); } static Test* Create() diff --git a/examples/testbed/tests/spring_cloth.h b/examples/testbed/tests/spring_cloth.h index 8444b3c..fc99ed2 100644 --- a/examples/testbed/tests/spring_cloth.h +++ b/examples/testbed/tests/spring_cloth.h @@ -19,10 +19,6 @@ #ifndef SPRING_CLOTH_H #define SPRING_CLOTH_H -extern DebugDraw* g_debugDraw; -extern Camera g_camera; -extern Settings g_settings; - class SpringCloth : public SpringClothTest { public: diff --git a/examples/testbed/tests/spring_cloth_collision_test.h b/examples/testbed/tests/spring_cloth_collision_test.h index 1328694..35c4bbf 100644 --- a/examples/testbed/tests/spring_cloth_collision_test.h +++ b/examples/testbed/tests/spring_cloth_collision_test.h @@ -19,10 +19,6 @@ #ifndef SPRING_CLOTH_COLLISION_H #define SPRING_CLOTH_COLLISION_H -extern DebugDraw* g_debugDraw; -extern Camera g_camera; -extern Settings g_settings; - class SpringClothCollision : public SpringClothTest { public: diff --git a/examples/testbed/tests/spring_cloth_test.h b/examples/testbed/tests/spring_cloth_test.h index 8767dae..e101908 100644 --- a/examples/testbed/tests/spring_cloth_test.h +++ b/examples/testbed/tests/spring_cloth_test.h @@ -19,10 +19,6 @@ #ifndef SPRING_CLOTH_TESH_H #define SPRING_CLOTH_TESH_H -extern DebugDraw* g_debugDraw; -extern Camera g_camera; -extern Settings g_settings; - class ClothDragger { public: @@ -208,28 +204,16 @@ class SpringClothTest : public Test public: SpringClothTest() : m_clothDragger(&m_clothRay, &m_cloth) { - g_camera.m_zoom = 25.0f; + g_camera->m_zoom = 25.0f; m_clothRay.origin.SetZero(); m_clothRay.direction.Set(0.0f, 0.0f, -1.0f); - m_clothRay.fraction = g_camera.m_zFar; + m_clothRay.fraction = g_camera->m_zFar; } void Step() { - float32 dt = g_settings.hertz > 0.0f ? 1.0f / g_settings.hertz : 0.0f; - - if (g_settings.pause) - { - if (g_settings.singleStep) - { - g_settings.singleStep = false; - } - else - { - dt = 0.0f; - } - } + float32 dt = g_settings->inv_hertz; m_cloth.Step(dt); m_cloth.Apply(); @@ -245,13 +229,11 @@ public: g_debugDraw->DrawShape(s, b3Color_white, xf); } - m_cloth.Draw(g_debugDraw); + m_cloth.Draw(); b3SpringClothStep step = m_cloth.GetStep(); - char text[256]; - sprintf(text, "Iterations = %u", step.iterations); - g_debugDraw->DrawString(text, b3Color_white); + g_debugDraw->DrawString(b3Color_white, "Iterations = %u", step.iterations); if (m_clothDragger.IsSelected() == true) { diff --git a/examples/testbed/tests/tension_mapping.h b/examples/testbed/tests/tension_mapping.h index e824a66..19afa90 100644 --- a/examples/testbed/tests/tension_mapping.h +++ b/examples/testbed/tests/tension_mapping.h @@ -19,10 +19,6 @@ #ifndef TENSION_MAPPING_H #define TENSION_MAPPING_H -extern DebugDraw* g_debugDraw; -extern Camera g_camera; -extern Settings g_settings; - // Hot/Cold color map // See http://paulbourke.net/miscellaneous/colourspace/ static inline b3Color Color(float32 x, float32 a, float32 b) @@ -88,19 +84,7 @@ public: void Step() { - float32 dt = g_settings.hertz > 0.0f ? 1.0f / g_settings.hertz : 0.0f; - - if (g_settings.pause) - { - if (g_settings.singleStep) - { - g_settings.singleStep = false; - } - else - { - dt = 0.0f; - } - } + float32 dt = g_settings->inv_hertz; m_cloth.Step(dt); m_cloth.Apply(); @@ -141,9 +125,7 @@ public: b3SpringClothStep step = m_cloth.GetStep(); - char text[256]; - sprintf(text, "Iterations = %u", step.iterations); - g_debugDraw->DrawString(text, b3Color_white); + g_debugDraw->DrawString(b3Color_white, "Iterations = %u", step.iterations); if (m_clothDragger.IsSelected() == true) { diff --git a/examples/testbed/tests/test.h b/examples/testbed/tests/test.h index fcce8af..3b3fed8 100644 --- a/examples/testbed/tests/test.h +++ b/examples/testbed/tests/test.h @@ -36,11 +36,13 @@ inline float32 RandomFloat(float32 a, float32 b) return a + r; } +// Test settings struct Settings { Settings() { hertz = 60.0f; + inv_hertz = 1.0f / hertz; velocityIterations = 8; positionIterations = 2; sleep = false; @@ -69,7 +71,7 @@ struct Settings bool pause; bool singleStep; - float32 hertz; + float32 hertz, inv_hertz; int velocityIterations; int positionIterations; bool sleep; @@ -91,16 +93,7 @@ struct Settings bool drawGrid; }; -class Test; - -struct TestEntry -{ - typedef Test* (*TestCreate)(); - const char* name; - TestCreate create; -}; - -extern TestEntry g_tests[]; +extern Settings* g_settings; class RayCastListener : public b3RayCastListener { @@ -123,11 +116,14 @@ public: Test(); virtual ~Test(); - virtual void BeginContact(b3Contact* contact); - virtual void EndContact(b3Contact* contact); - virtual void PreSolve(b3Contact* contact); + virtual void BeginContact(b3Contact* contact) { } + virtual void EndContact(b3Contact* contact) { } + virtual void PreSolve(b3Contact* contact) { } virtual void Step(); + + virtual void Dump() { } + virtual void RayHit(); virtual void MouseMove(const Ray3& pw); @@ -136,16 +132,22 @@ public: virtual void KeyDown(int button) { } virtual void KeyUp(int button) { } - virtual void Dump() { } - b3World m_world; b3RayCastSingleOutput m_rayHit; b3MouseJoint* m_mouseJoint; - - b3BoxHull m_boxHull; - + b3BoxHull m_groundHull; b3GridMesh<50, 50> m_groundMesh; }; +struct TestEntry +{ + typedef Test* (*TestCreate)(); + const char* name; + TestCreate create; +}; + +extern TestEntry g_tests[]; +extern u32 g_testCount; + #endif \ No newline at end of file diff --git a/examples/testbed/tests/thin.h b/examples/testbed/tests/thin.h index 7073591..88ddf5c 100644 --- a/examples/testbed/tests/thin.h +++ b/examples/testbed/tests/thin.h @@ -31,9 +31,6 @@ public: Thin() { - g_camera.m_center.Set(2.5f, -2.0f, 5.5f); - g_camera.m_zoom = 40.0f; - { b3BodyDef bdef; bdef.type = b3BodyType::e_staticBody; diff --git a/examples/testbed/tests/tumbler.h b/examples/testbed/tests/tumbler.h index c1705d8..d1405a2 100644 --- a/examples/testbed/tests/tumbler.h +++ b/examples/testbed/tests/tumbler.h @@ -21,10 +21,6 @@ #include -extern DebugDraw* g_debugDraw; -extern Camera g_camera; -extern Settings g_settings; - class Tumbler : public Test { public: @@ -35,10 +31,6 @@ public: Tumbler() { - g_camera.m_center.Set(0.0f, 10.0f, 0.0f); - g_camera.m_q.SetIdentity(); - g_camera.m_zoom = 150.0f; - { b3BodyDef bd; b3Body* ground = m_world.CreateBody(bd); diff --git a/examples/testbed/tests/varying_friction.h b/examples/testbed/tests/varying_friction.h index d9951c0..0a1c2ab 100644 --- a/examples/testbed/tests/varying_friction.h +++ b/examples/testbed/tests/varying_friction.h @@ -24,10 +24,6 @@ class VaryingFriction : public Test public: VaryingFriction() { - g_camera.m_zoom = 200.0f; - g_camera.m_q = b3Quat(b3Vec3(1.0f, 0.0f, 0.0f), -0.1f * B3_PI); - g_camera.m_q = b3Quat(b3Vec3(0.0f, 1.0f, 0.0f), -0.1f * B3_PI) * g_camera.m_q; - { b3BodyDef bdef; b3Body* ground = m_world.CreateBody(bdef); @@ -35,9 +31,9 @@ public: b3HullShape hs; hs.m_hull = &m_groundHull; - b3ShapeDef sdef; - sdef.shape = &hs; - ground->CreateShape(sdef); + b3ShapeDef sd; + sd.shape = &hs; + ground->CreateShape(sd); } static b3BoxHull rampHull; @@ -59,10 +55,10 @@ public: b3HullShape hs; hs.m_hull = &rampHull; - b3ShapeDef sdef; - sdef.shape = &hs; - sdef.friction = 0.4f; - ramp->CreateShape(sdef); + b3ShapeDef sd; + sd.shape = &hs; + sd.friction = 0.4f; + ramp->CreateShape(sd); } { @@ -75,10 +71,10 @@ public: b3HullShape hs; hs.m_hull = &rampHull; - b3ShapeDef sdef; - sdef.shape = &hs; - sdef.friction = 0.3f; - ramp->CreateShape(sdef); + b3ShapeDef sd; + sd.shape = &hs; + sd.friction = 0.3f; + ramp->CreateShape(sd); } { @@ -91,10 +87,10 @@ public: b3HullShape hs; hs.m_hull = &rampHull; - b3ShapeDef sdef; - sdef.shape = &hs; - sdef.friction = 0.2f; - ramp->CreateShape(sdef); + b3ShapeDef sd; + sd.shape = &hs; + sd.friction = 0.2f; + ramp->CreateShape(sd); } { @@ -107,10 +103,10 @@ public: b3HullShape hs; hs.m_hull = &rampHull; - b3ShapeDef sdef; - sdef.shape = &hs; - sdef.friction = 0.1f; - ramp->CreateShape(sdef); + b3ShapeDef sd; + sd.shape = &hs; + sd.friction = 0.1f; + ramp->CreateShape(sd); } { @@ -120,14 +116,14 @@ public: b3Body* body = m_world.CreateBody(bd); b3HullShape hs; - hs.m_hull = &m_boxHull; + hs.m_hull = &b3BoxHull_identity; - b3ShapeDef sdef; - sdef.density = 1.0f; - sdef.friction = 0.2f; - sdef.shape = &hs; + b3ShapeDef sd; + sd.density = 1.0f; + sd.friction = 0.2f; + sd.shape = &hs; - body->CreateShape(sdef); + body->CreateShape(sd); } { @@ -137,14 +133,14 @@ public: b3Body* body = m_world.CreateBody(bd); b3HullShape hs; - hs.m_hull = &m_boxHull; + hs.m_hull = &b3BoxHull_identity; - b3ShapeDef sdef; - sdef.density = 1.0f; - sdef.friction = 0.5f; - sdef.shape = &hs; + b3ShapeDef sd; + sd.density = 1.0f; + sd.friction = 0.5f; + sd.shape = &hs; - body->CreateShape(sdef); + body->CreateShape(sd); } { @@ -154,14 +150,14 @@ public: b3Body* body = m_world.CreateBody(bd); b3HullShape hs; - hs.m_hull = &m_boxHull; + hs.m_hull = &b3BoxHull_identity; - b3ShapeDef sdef; - sdef.density = 1.0f; - sdef.friction = 0.8f; - sdef.shape = &hs; + b3ShapeDef sd; + sd.density = 1.0f; + sd.friction = 0.8f; + sd.shape = &hs; - body->CreateShape(sdef); + body->CreateShape(sd); } } @@ -171,4 +167,4 @@ public: } }; -#endif +#endif \ No newline at end of file diff --git a/include/bounce/collision/broad_phase.h b/include/bounce/collision/broad_phase.h index 8ac1efe..1b15376 100644 --- a/include/bounce/collision/broad_phase.h +++ b/include/bounce/collision/broad_phase.h @@ -77,7 +77,7 @@ public: void FindNewPairs(T* callback); // Draw the proxy AABBs. - void Draw(b3Draw* draw) const; + void Draw() const; private : friend class b3DynamicTree; @@ -189,9 +189,9 @@ inline void b3BroadPhase::FindNewPairs(T* callback) } } -inline void b3BroadPhase::Draw(b3Draw* draw) const +inline void b3BroadPhase::Draw() const { - m_tree.Draw(draw); + m_tree.Draw(); } #endif \ No newline at end of file diff --git a/include/bounce/collision/sat/sat_edge_and_hull.h b/include/bounce/collision/sat/sat_edge_and_hull.h index 2eabc74..60ecb2f 100644 --- a/include/bounce/collision/sat/sat_edge_and_hull.h +++ b/include/bounce/collision/sat/sat_edge_and_hull.h @@ -21,20 +21,20 @@ #include -struct b3Segment; +struct b3Capsule; /////////////////////////////////////////////////////////////////////////////////////////////////// -float32 b3ProjectEdge(const b3Segment* hull, const b3Plane& plane); +float32 b3ProjectEdge(const b3Capsule* hull, const b3Plane& plane); -b3FaceQuery b3QueryFaceSeparation(const b3Transform& xf1, const b3Segment* hull1, +b3FaceQuery b3QueryFaceSeparation(const b3Transform& xf1, const b3Capsule* hull1, const b3Transform& xf2, const b3Hull* hull2); /////////////////////////////////////////////////////////////////////////////////////////////////// float32 b3ProjectEdge(const b3Vec3& P1, const b3Vec3& E1, const b3Vec3& P2, const b3Vec3& E2, const b3Vec3& C2); -b3EdgeQuery b3QueryEdgeSeparation(const b3Transform& xf1, const b3Segment* hull1, +b3EdgeQuery b3QueryEdgeSeparation(const b3Transform& xf1, const b3Capsule* hull1, const b3Transform& xf2, const b3Hull* hull2); #endif \ No newline at end of file diff --git a/include/bounce/collision/sat/sat_vertex_and_hull.h b/include/bounce/collision/sat/sat_vertex_and_hull.h index 86ad9d2..52a59d5 100644 --- a/include/bounce/collision/sat/sat_vertex_and_hull.h +++ b/include/bounce/collision/sat/sat_vertex_and_hull.h @@ -21,11 +21,13 @@ #include +struct b3Sphere; + /////////////////////////////////////////////////////////////////////////////////////////////////// -float32 b3ProjectVertex(const b3Vec3& hull, const b3Plane& plane); +float32 b3ProjectVertex(const b3Sphere* hull, const b3Plane& plane); -b3FaceQuery b3QueryFaceSeparation(const b3Transform& xf1, const b3Vec3& hull1, +b3FaceQuery b3QueryFaceSeparation(const b3Transform& xf1, const b3Sphere* hull1, const b3Transform& xf2, const b3Hull* hull2); #endif diff --git a/include/bounce/collision/shapes/box_hull.h b/include/bounce/collision/shapes/box_hull.h index ef20564..5d384fa 100644 --- a/include/bounce/collision/shapes/box_hull.h +++ b/include/bounce/collision/shapes/box_hull.h @@ -31,6 +31,12 @@ struct b3BoxHull : public b3Hull // Does nothing for performance. b3BoxHull() { } + // Construct this box from three extents and centered at the origin. + b3BoxHull(float32 ex, float32 ey, float32 ez) + { + Set(ex, ey, ez); + } + // Set this box to the unit box centered at the origin. void SetIdentity() { @@ -174,4 +180,6 @@ struct b3BoxHull : public b3Hull } }; +extern const b3BoxHull b3BoxHull_identity; + #endif \ No newline at end of file diff --git a/include/bounce/collision/shapes/capsule.h b/include/bounce/collision/shapes/capsule.h index 012fe66..3c5464b 100644 --- a/include/bounce/collision/shapes/capsule.h +++ b/include/bounce/collision/shapes/capsule.h @@ -21,20 +21,38 @@ #include -struct b3Segment +struct b3Capsule { + // + b3Capsule() { } + + // + b3Capsule(const b3Vec3& v1, const b3Vec3& v2, float32 r) + { + vertices[0] = v1; + vertices[1] = v2; + radius = r; + } + + // + ~b3Capsule() { } + b3Vec3 vertices[2]; - + float32 radius; + const b3Vec3& GetVertex(u32 index) const; u32 GetSupportVertex(const b3Vec3& direction) const; }; -inline const b3Vec3& b3Segment::GetVertex(u32 index) const +// Unit capsule centered at the origin +extern const b3Capsule b3Capsule_identity; + +inline const b3Vec3& b3Capsule::GetVertex(u32 index) const { return vertices[index]; } -inline u32 b3Segment::GetSupportVertex(const b3Vec3& d) const +inline u32 b3Capsule::GetSupportVertex(const b3Vec3& d) const { if (b3Dot(d, vertices[0]) > b3Dot(d, vertices[1])) { diff --git a/include/bounce/collision/shapes/hull.h b/include/bounce/collision/shapes/hull.h index cc27c47..afd1285 100644 --- a/include/bounce/collision/shapes/hull.h +++ b/include/bounce/collision/shapes/hull.h @@ -57,6 +57,9 @@ struct b3Hull b3Plane GetEdgeSidePlane(u32 index) const; u32 GetSize() const; + + b3Vec3 GetCentroid() const; + void Validate() const; void Validate(const b3Face* face) const; void Validate(const b3HalfEdge* edge) const; diff --git a/include/bounce/collision/shapes/sphere.h b/include/bounce/collision/shapes/sphere.h index 8d32ff1..7156fb0 100644 --- a/include/bounce/collision/shapes/sphere.h +++ b/include/bounce/collision/shapes/sphere.h @@ -23,6 +23,19 @@ struct b3Sphere { + // + b3Sphere() { } + + // + b3Sphere(const b3Vec3& v, float32 r) + { + vertex = v; + radius = r; + } + + // + ~b3Sphere() { } + b3Vec3 vertex; float32 radius; @@ -30,6 +43,9 @@ struct b3Sphere u32 GetSupportVertex(const b3Vec3& direction) const; }; +// Unit sphere centered at origin +extern const b3Sphere b3Sphere_identity; + inline const b3Vec3& b3Sphere::GetVertex(u32 index) const { B3_NOT_USED(index); diff --git a/include/bounce/collision/trees/dynamic_tree.h b/include/bounce/collision/trees/dynamic_tree.h index c9dd089..29e9bb3 100644 --- a/include/bounce/collision/trees/dynamic_tree.h +++ b/include/bounce/collision/trees/dynamic_tree.h @@ -19,7 +19,6 @@ #ifndef B3_DYNAMIC_TREE_H #define B3_DYNAMIC_TREE_H -#include #include #include #include @@ -67,7 +66,7 @@ public : void Validate(i32 node) const; // Draw this tree. - void Draw(b3Draw* draw) const; + void Draw() const; private : struct b3Node { diff --git a/include/bounce/collision/trees/static_tree.h b/include/bounce/collision/trees/static_tree.h index cac8ba7..2085ca6 100644 --- a/include/bounce/collision/trees/static_tree.h +++ b/include/bounce/collision/trees/static_tree.h @@ -19,7 +19,6 @@ #ifndef B3_STATIC_TREE_H #define B3_STATIC_TREE_H -#include #include #include #include @@ -55,7 +54,7 @@ public: void RayCast(T* callback, const b3RayCastInput& input) const; // Draw this tree. - void Draw(b3Draw* draw) const; + void Draw() const; u32 GetSize() const; private : diff --git a/include/bounce/common/draw.h b/include/bounce/common/draw.h index 98e66bc..cbb2b51 100644 --- a/include/bounce/common/draw.h +++ b/include/bounce/common/draw.h @@ -117,6 +117,11 @@ public : u32 m_flags; }; +// The debug drawer interface used by Bounce. +// You should set this to an implementation +// before calling any function that uses the interface. +extern b3Draw* b3Draw_draw; + inline void b3Draw::SetFlags(u32 flags) { m_flags = flags; diff --git a/include/bounce/common/math/mat22.h b/include/bounce/common/math/mat22.h index cfdda1c..bc66b82 100644 --- a/include/bounce/common/math/mat22.h +++ b/include/bounce/common/math/mat22.h @@ -46,6 +46,12 @@ struct b3Mat22 b3Vec2 x, y; }; +// Zero matrix +extern const b3Mat22 b3Mat22_zero; + +// Identity matrix +extern const b3Mat22 b3Mat22_identity; + // Multiply a matrix times a vector. inline b3Vec2 operator*(const b3Mat22& A, const b3Vec2& v) { diff --git a/include/bounce/common/math/mat33.h b/include/bounce/common/math/mat33.h index 07d3452..3696e22 100644 --- a/include/bounce/common/math/mat33.h +++ b/include/bounce/common/math/mat33.h @@ -90,8 +90,8 @@ struct b3Mat33 }; // Usefull constants. -extern b3Mat33 b3Mat33_zero; -extern b3Mat33 b3Mat33_identity; +extern const b3Mat33 b3Mat33_zero; +extern const b3Mat33 b3Mat33_identity; // Add two matrices. inline b3Mat33 operator+(const b3Mat33& A, const b3Mat33& B) diff --git a/include/bounce/common/math/quat.h b/include/bounce/common/math/quat.h index 4d5ebc1..eb5d8c9 100644 --- a/include/bounce/common/math/quat.h +++ b/include/bounce/common/math/quat.h @@ -141,6 +141,9 @@ struct b3Quat float32 x, y, z, w; }; +// Identity quaternion +extern const b3Quat b3Quat_identity; + // Add two quaternions. inline b3Quat operator+(const b3Quat& a, const b3Quat& b) { diff --git a/include/bounce/common/math/transform.h b/include/bounce/common/math/transform.h index f3a45a8..7169251 100644 --- a/include/bounce/common/math/transform.h +++ b/include/bounce/common/math/transform.h @@ -31,6 +31,13 @@ struct b3Transform // Default ctor does nothing for performance. b3Transform() { } + // Set this transform from a rotation matrix and a translation vector. + b3Transform(const b3Mat33& _rotation, const b3Vec3& _translation) + { + rotation = _rotation; + position = _translation; + } + // Set this transform from a rotation quaternion and a translation vector. b3Transform(const b3Quat& _rotation, const b3Vec3& _translation) { @@ -49,6 +56,9 @@ struct b3Transform b3Vec3 position; // in fact a translation }; +// Identity transformation +extern const b3Transform b3Transform_identity; + // Multiply a transform times a vector. inline b3Vec3 b3Mul(const b3Transform& T, const b3Vec3& v) { diff --git a/include/bounce/common/math/vec2.h b/include/bounce/common/math/vec2.h index 1fe96d3..4fcaac9 100644 --- a/include/bounce/common/math/vec2.h +++ b/include/bounce/common/math/vec2.h @@ -91,6 +91,15 @@ struct b3Vec2 float32 x, y; }; +// Zero vector +extern const b3Vec2 b3Vec2_zero; + +// Left vector +extern const b3Vec2 b3Vec2_x; + +// Right vector +extern const b3Vec2 b3Vec2_y; + // Negate a vector. inline b3Vec2 operator-(const b3Vec2& v) { diff --git a/include/bounce/common/math/vec3.h b/include/bounce/common/math/vec3.h index 66a6cca..0b04bda 100644 --- a/include/bounce/common/math/vec3.h +++ b/include/bounce/common/math/vec3.h @@ -106,6 +106,18 @@ struct b3Vec3 float32 x, y, z; }; +// Zero vector +extern const b3Vec3 b3Vec3_zero; + +// Right vector +extern const b3Vec3 b3Vec3_x; + +// Up vector +extern const b3Vec3 b3Vec3_y; + +// Forward vector +extern const b3Vec3 b3Vec3_z; + // Negate a vector. inline b3Vec3 operator-(const b3Vec3& v) { diff --git a/include/bounce/dynamics/cloth/cloth.h b/include/bounce/dynamics/cloth/cloth.h index 9a27afa..84aca19 100644 --- a/include/bounce/dynamics/cloth/cloth.h +++ b/include/bounce/dynamics/cloth/cloth.h @@ -23,7 +23,6 @@ #include struct b3Mesh; -class b3Draw; struct b3ClothDef { @@ -110,7 +109,7 @@ public: return m_ps; } - void Draw(b3Draw* draw) const; + void Draw() const; private: void SolveC1(); void SolveC2(); diff --git a/include/bounce/dynamics/cloth/spring_cloth.h b/include/bounce/dynamics/cloth/spring_cloth.h index 5e20a08..9d9eb0c 100644 --- a/include/bounce/dynamics/cloth/spring_cloth.h +++ b/include/bounce/dynamics/cloth/spring_cloth.h @@ -25,7 +25,6 @@ #define B3_CLOTH_SHAPE_CAPACITY 32 class b3StackAllocator; -class b3Draw; class b3Shape; @@ -188,7 +187,7 @@ public: void Apply() const; // Debug draw the cloth mesh. - void Draw(b3Draw* draw) const; + void Draw() const; protected: friend class b3SpringSolver; diff --git a/include/bounce/dynamics/contacts/collide/clip.h b/include/bounce/dynamics/contacts/collide/clip.h index 7bae6c5..cb7ff55 100644 --- a/include/bounce/dynamics/contacts/collide/clip.h +++ b/include/bounce/dynamics/contacts/collide/clip.h @@ -75,11 +75,11 @@ struct b3ClipPlane }; struct b3Hull; -struct b3Segment; +struct b3Capsule; // Build a clip edge for an edge. void b3BuildEdge(b3ClipVertex vOut[2], - const b3Segment* hull); + const b3Capsule* hull); // Build a clip polygon given an index to the polygon face. void b3BuildPolygon(b3ClipPolygon& pOut, @@ -99,7 +99,7 @@ void b3ClipPolygonToPlane(b3ClipPolygon& pOut, // Clip a segment by a hull face (side planes). // Return the number of output points. u32 b3ClipEdgeToFace(b3ClipVertex vOut[2], - const b3ClipVertex vIn[2], const b3Segment* hull); + const b3ClipVertex vIn[2], const b3Capsule* hull); // Clip a segment by a hull face (side planes). // Return the number of output points. diff --git a/include/bounce/dynamics/joints/cone_joint.h b/include/bounce/dynamics/joints/cone_joint.h index 1d2b941..7f111cd 100644 --- a/include/bounce/dynamics/joints/cone_joint.h +++ b/include/bounce/dynamics/joints/cone_joint.h @@ -81,7 +81,7 @@ public: void SetConeAngle(float32 angle); // Draw this joint. - void Draw(b3Draw* draw) const; + void Draw() const; private: friend class b3Joint; friend class b3Body; diff --git a/include/bounce/dynamics/joints/joint.h b/include/bounce/dynamics/joints/joint.h index e552ebb..f973d99 100644 --- a/include/bounce/dynamics/joints/joint.h +++ b/include/bounce/dynamics/joints/joint.h @@ -24,7 +24,6 @@ #include #include -class b3Draw; class b3Body; class b3Joint; struct b3SolverData; @@ -116,6 +115,12 @@ public: b3Log("Dump feature not implemented for this joint type.\n"); } + // Draw this joint. + virtual void Draw() const + { + b3Log("Draw feature not implemented for this joint type.\n"); + } + // Get the next joint in the world joint list. const b3Joint* GetNext() const; b3Joint* GetNext(); diff --git a/include/bounce/dynamics/joints/mouse_joint.h b/include/bounce/dynamics/joints/mouse_joint.h index bb9af37..e044495 100644 --- a/include/bounce/dynamics/joints/mouse_joint.h +++ b/include/bounce/dynamics/joints/mouse_joint.h @@ -58,7 +58,7 @@ public: void SetTarget(const b3Vec3& target); // Draw this joint. - void Draw(b3Draw* draw) const; + void Draw() const; private: friend class b3Joint; friend class b3JointManager; diff --git a/include/bounce/dynamics/joints/revolute_joint.h b/include/bounce/dynamics/joints/revolute_joint.h index f17f98d..47214b8 100644 --- a/include/bounce/dynamics/joints/revolute_joint.h +++ b/include/bounce/dynamics/joints/revolute_joint.h @@ -132,7 +132,7 @@ public: void SetMaxMotorTorque(float32 torque); // Draw this joint. - void Draw(b3Draw* draw) const; + void Draw() const; private: friend class b3Joint; friend class b3JointManager; diff --git a/include/bounce/dynamics/joints/sphere_joint.h b/include/bounce/dynamics/joints/sphere_joint.h index aa9fac7..60e1782 100644 --- a/include/bounce/dynamics/joints/sphere_joint.h +++ b/include/bounce/dynamics/joints/sphere_joint.h @@ -52,7 +52,7 @@ public: b3Vec3 GetAnchorB() const; // Draw this joint. - void Draw(b3Draw* draw) const; + void Draw() const; private: friend class b3Joint; friend class b3JointManager; diff --git a/include/bounce/dynamics/joints/spring_joint.h b/include/bounce/dynamics/joints/spring_joint.h index f051610..7af9bcc 100644 --- a/include/bounce/dynamics/joints/spring_joint.h +++ b/include/bounce/dynamics/joints/spring_joint.h @@ -94,7 +94,7 @@ public: void SetDampingRatio(float32 ratio); // Draw this joint. - void Draw(b3Draw* draw) const; + void Draw() const; private: friend class b3Joint; friend class b3JointManager; diff --git a/include/bounce/dynamics/joints/weld_joint.h b/include/bounce/dynamics/joints/weld_joint.h index be60426..e6ced48 100644 --- a/include/bounce/dynamics/joints/weld_joint.h +++ b/include/bounce/dynamics/joints/weld_joint.h @@ -57,7 +57,7 @@ public: b3Vec3 GetAnchorB() const; // Draw this joint. - void Draw(b3Draw* draw) const; + void Draw() const; private: friend class b3Joint; friend class b3JointManager; diff --git a/include/bounce/dynamics/rope/rope.h b/include/bounce/dynamics/rope/rope.h index de3fc7a..4e04763 100644 --- a/include/bounce/dynamics/rope/rope.h +++ b/include/bounce/dynamics/rope/rope.h @@ -21,8 +21,6 @@ #include -class b3Draw; - struct b3RopeBody; // @@ -86,7 +84,7 @@ public: void Step(float32 dt); // - void Draw(b3Draw* draw) const; + void Draw() const; private: // float32 m_kd1, m_kd2; diff --git a/include/bounce/dynamics/world.h b/include/bounce/dynamics/world.h index a74710b..3251875 100644 --- a/include/bounce/dynamics/world.h +++ b/include/bounce/dynamics/world.h @@ -117,13 +117,11 @@ public: const b3List2& GetContactList() const; b3List2& GetContactList(); - // Debug draw the physics entities that belong to this world. - // The user must implement the debug draw interface b3Draw and b3_debugDraw must have been - // set to the user implementation. - void DebugDraw() const; + // Draw the entities in this world. + void Draw() const; + + // Draw a shape. void DrawShape(const b3Transform& xf, const b3Shape* shape) const; - void DrawJoint(const b3Joint* joint) const; - void DrawContact(const b3Contact* contact) const; private : enum b3Flags { @@ -144,7 +142,6 @@ private : bool m_warmStarting; u32 m_flags; b3Vec3 m_gravity; - b3Draw* m_debugDraw; b3StackAllocator m_stackAllocator; b3BlockPool m_bodyBlocks; diff --git a/premake5.lua b/premake5.lua index 38f7fc2..e33ea59 100644 --- a/premake5.lua +++ b/premake5.lua @@ -257,17 +257,33 @@ solution (solution_name) language "C++" location ( solution_dir .. action ) includedirs { external_dir, bounce_inc_dir, examples_inc_dir } - vpaths { ["Headers"] = "**.h", ["Sources"] = "**.cpp" } + vpaths { [""] = "testbed" } files { examples_inc_dir .. "/testbed/framework/debug_draw.h", examples_inc_dir .. "/testbed/framework/profiler.h", + examples_inc_dir .. "/testbed/framework/recorder_profiler.h", + examples_inc_dir .. "/testbed/framework/json_profiler.h", + examples_inc_dir .. "/testbed/framework/testbed_listener.h", + + examples_inc_dir .. "/testbed/framework/model.h", + examples_inc_dir .. "/testbed/framework/view.h", + examples_inc_dir .. "/testbed/framework/controller.h", + examples_inc_dir .. "/testbed/tests/**.h", examples_src_dir .. "/testbed/framework/profiler.cpp", + examples_src_dir .. "/testbed/framework/recorder_profiler.cpp", + examples_src_dir .. "/testbed/framework/json_profiler.cpp", + + examples_inc_dir .. "/testbed/framework/model.cpp", + examples_inc_dir .. "/testbed/framework/view.cpp", + examples_inc_dir .. "/testbed/framework/controller.cpp", + examples_src_dir .. "/testbed/framework/test.cpp", examples_src_dir .. "/testbed/framework/test_entries.cpp", + examples_src_dir .. "/testbed/framework/main.cpp" } diff --git a/src/bounce/collision/collision.cpp b/src/bounce/collision/collision.cpp new file mode 100644 index 0000000..9826e31 --- /dev/null +++ b/src/bounce/collision/collision.cpp @@ -0,0 +1,27 @@ +/* +* Copyright (c) 2016-2016 Irlan Robson http://www.irlan.net +* +* This software is provided 'as-is', without any express or implied +* warranty. In no event will the authors be held liable for any damages +* arising from the use of this software. +* Permission is granted to anyone to use this software for any purpose, +* including commercial applications, and to alter it and redistribute it +* freely, subject to the following restrictions: +* 1. The origin of this software must not be misrepresented; you must not +* claim that you wrote the original software. If you use this software +* in a product, an acknowledgment in the product documentation would be +* appreciated but is not required. +* 2. Altered source versions must be plainly marked as such, and must not be +* misrepresented as being the original software. +* 3. This notice may not be removed or altered from any source distribution. +*/ + +#include +#include +#include + +const b3Sphere b3Sphere_identity(b3Vec3_zero, 1.0f); + +const b3Capsule b3Capsule_identity(b3Vec3(0.0f, -0.5f, 0.0f), b3Vec3(0.0f, 0.5f, 0.0f), 1.0f); + +const b3BoxHull b3BoxHull_identity(1.0f, 1.0f, 1.0f); \ No newline at end of file diff --git a/src/bounce/collision/sat/sat_edge_and_hull.cpp b/src/bounce/collision/sat/sat_edge_and_hull.cpp index ca6ca9a..fe639df 100644 --- a/src/bounce/collision/sat/sat_edge_and_hull.cpp +++ b/src/bounce/collision/sat/sat_edge_and_hull.cpp @@ -20,13 +20,13 @@ #include #include -float32 b3ProjectEdge(const b3Segment* hull, const b3Plane& plane) +float32 b3ProjectEdge(const b3Capsule* hull, const b3Plane& plane) { b3Vec3 support = hull->GetVertex(hull->GetSupportVertex(-plane.normal)); return b3Distance(support, plane); } -b3FaceQuery b3QueryFaceSeparation(const b3Transform& xf1, const b3Segment* hull1, +b3FaceQuery b3QueryFaceSeparation(const b3Transform& xf1, const b3Capsule* hull1, const b3Transform& xf2, const b3Hull* hull2) { // Perform computations in the local space of the first hull. @@ -95,7 +95,7 @@ float32 b3ProjectEdge(const b3Vec3& P1, const b3Vec3& E1, return b3Dot(N, P2 - P1); } -b3EdgeQuery b3QueryEdgeSeparation(const b3Transform& xf1, const b3Segment* hull1, const b3Transform& xf2, const b3Hull* hull2) +b3EdgeQuery b3QueryEdgeSeparation(const b3Transform& xf1, const b3Capsule* hull1, const b3Transform& xf2, const b3Hull* hull2) { // Query minimum edge separation. u32 maxIndex = 0; diff --git a/src/bounce/collision/sat/sat_vertex_and_hull.cpp b/src/bounce/collision/sat/sat_vertex_and_hull.cpp index b3ea83c..96a4b81 100644 --- a/src/bounce/collision/sat/sat_vertex_and_hull.cpp +++ b/src/bounce/collision/sat/sat_vertex_and_hull.cpp @@ -20,17 +20,17 @@ #include #include -float32 b3ProjectVertex(const b3Vec3& hull, const b3Plane& plane) +float32 b3ProjectVertex(const b3Sphere* hull, const b3Plane& plane) { - b3Vec3 support = hull; + b3Vec3 support = hull->GetVertex(hull->GetSupportVertex(-plane.normal)); return b3Distance(support, plane); } -b3FaceQuery b3QueryFaceSeparation(const b3Transform& xf1, const b3Vec3& hull, +b3FaceQuery b3QueryFaceSeparation(const b3Transform& xf1, const b3Sphere* hull, const b3Transform& xf2, const b3Hull* hull2) { // Perform computations in the local space of the second hull. - b3Vec3 support = b3MulT(xf2, b3Mul(xf1, hull)); + b3Vec3 support = b3MulT(xf2, b3Mul(xf1, hull->vertex)); u32 maxIndex = 0; float32 maxSeparation = -B3_MAX_FLOAT; diff --git a/src/bounce/collision/shapes/hull.cpp b/src/bounce/collision/shapes/hull.cpp index 5dbcd19..5347e06 100644 --- a/src/bounce/collision/shapes/hull.cpp +++ b/src/bounce/collision/shapes/hull.cpp @@ -77,4 +77,70 @@ void b3Hull::Validate(const b3HalfEdge* e) const B3_ASSERT(count < edgeCount); ++count; } while (e != begin); +} + +b3Vec3 b3Hull::GetCentroid() const +{ + Validate(); + + b3Vec3 c(0.0f, 0.0f, 0.0f); + float32 volume = 0.0f; + + // Pick reference point not too away from the origin + // to minimize floating point rounding errors. + b3Vec3 p1(0.0f, 0.0f, 0.0f); + // Put it inside the hull. + for (u32 i = 0; i < vertexCount; ++i) + { + p1 += vertices[i]; + } + p1 /= float32(vertexCount); + + const float32 inv4 = 0.25f; + const float32 inv6 = 1.0f / 6.0f; + const float32 inv60 = 1.0f / 60.0f; + const float32 inv120 = 1.0f / 120.0f; + + b3Vec3 diag(0.0f, 0.0f, 0.0f); + b3Vec3 offDiag(0.0f, 0.0f, 0.0f); + + // Triangulate convex polygons + for (u32 i = 0; i < faceCount; ++i) + { + const b3Face* face = GetFace(i); + const b3HalfEdge* begin = GetEdge(face->edge); + + const b3HalfEdge* edge = GetEdge(begin->next); + do + { + u32 i1 = begin->origin; + u32 i2 = edge->origin; + const b3HalfEdge* next = GetEdge(edge->next); + u32 i3 = next->origin; + + b3Vec3 p2 = vertices[i1]; + b3Vec3 p3 = vertices[i2]; + b3Vec3 p4 = vertices[i3]; + + b3Vec3 e1 = p2 - p1; + b3Vec3 e2 = p3 - p1; + b3Vec3 e3 = p4 - p1; + + float32 D = b3Det(e1, e2, e3); + + float32 tetraVolume = inv6 * D; + volume += tetraVolume; + + // Volume weighted centroid + c += tetraVolume * inv4 * (e1 + e2 + e3); + + edge = next; + } while (GetEdge(edge->next) != begin); + } + + // Centroid + B3_ASSERT(volume > B3_EPSILON); + c /= volume; + c += p1; + return c; } \ No newline at end of file diff --git a/src/bounce/collision/trees/dynamic_tree.cpp b/src/bounce/collision/trees/dynamic_tree.cpp index ce54721..9485a71 100644 --- a/src/bounce/collision/trees/dynamic_tree.cpp +++ b/src/bounce/collision/trees/dynamic_tree.cpp @@ -17,6 +17,7 @@ */ #include +#include b3DynamicTree::b3DynamicTree() { @@ -362,7 +363,7 @@ void b3DynamicTree::Validate(i32 nodeID) const } } -void b3DynamicTree::Draw(b3Draw* draw) const +void b3DynamicTree::Draw() const { if (m_nodeCount == 0) { @@ -385,11 +386,11 @@ void b3DynamicTree::Draw(b3Draw* draw) const const b3Node* node = m_nodes + nodeIndex; if (node->IsLeaf()) { - draw->DrawAABB(node->aabb, b3Color_pink); + b3Draw_draw->DrawAABB(node->aabb, b3Color_pink); } else { - draw->DrawAABB(node->aabb, b3Color_red); + b3Draw_draw->DrawAABB(node->aabb, b3Color_red); stack.Push(node->child1); stack.Push(node->child2); diff --git a/src/bounce/collision/trees/static_tree.cpp b/src/bounce/collision/trees/static_tree.cpp index 5f3c104..6535ef1 100644 --- a/src/bounce/collision/trees/static_tree.cpp +++ b/src/bounce/collision/trees/static_tree.cpp @@ -18,6 +18,7 @@ #include #include +#include b3StaticTree::b3StaticTree() { @@ -178,7 +179,7 @@ void b3StaticTree::Build(const b3AABB3* set, u32 count) B3_ASSERT(m_nodeCount == nodeCapacity); } -void b3StaticTree::Draw(b3Draw* draw) const +void b3StaticTree::Draw() const { if (m_nodeCount == 0) { @@ -199,11 +200,11 @@ void b3StaticTree::Draw(b3Draw* draw) const const b3Node* node = m_nodes + nodeIndex; if (node->IsLeaf()) { - draw->DrawAABB(node->aabb, b3Color_pink); + b3Draw_draw->DrawAABB(node->aabb, b3Color_pink); } else { - draw->DrawAABB(node->aabb, b3Color_red); + b3Draw_draw->DrawAABB(node->aabb, b3Color_red); stack.Push(node->child1); stack.Push(node->child2); diff --git a/src/bounce/common/math/mat.cpp b/src/bounce/common/math/math.cpp similarity index 83% rename from src/bounce/common/math/mat.cpp rename to src/bounce/common/math/math.cpp index f1d744c..f50ff18 100644 --- a/src/bounce/common/math/mat.cpp +++ b/src/bounce/common/math/math.cpp @@ -16,28 +16,45 @@ * 3. This notice may not be removed or altered from any source distribution. */ +#include +#include + #include #include #include +#include -b3Mat22 b3Mat22_zero = b3Mat22( +const b3Vec2 b3Vec2_zero(0.0f, 0.0f); +const b3Vec2 b3Vec2_x(1.0f, 0.0f); +const b3Vec2 b3Vec2_y(0.0f, 1.0f); + +const b3Vec3 b3Vec3_zero(0.0f, 0.0f, 0.0f); +const b3Vec3 b3Vec3_x(1.0f, 0.0f, 0.0f); +const b3Vec3 b3Vec3_y(0.0f, 1.0f, 0.0f); +const b3Vec3 b3Vec3_z(0.0f, 0.0f, 1.0f); + +const b3Mat22 b3Mat22_zero( b3Vec2(0.0f, 0.0f), b3Vec2(0.0f, 0.0f)); -b3Mat22 b3Mat22_identity = b3Mat22( +const b3Mat22 b3Mat22_identity( b3Vec2(1.0f, 0.0f), b3Vec2(0.0f, 1.0f)); -b3Mat33 b3Mat33_zero = b3Mat33( +const b3Mat33 b3Mat33_zero( b3Vec3(0.0f, 0.0f, 0.0f), b3Vec3(0.0f, 0.0f, 0.0f), b3Vec3(0.0f, 0.0f, 0.0f)); -b3Mat33 b3Mat33_identity = b3Mat33( +const b3Mat33 b3Mat33_identity( b3Vec3(1.0f, 0.0f, 0.0f), b3Vec3(0.0f, 1.0f, 0.0f), b3Vec3(0.0f, 0.0f, 1.0f)); +const b3Transform b3Transform_identity(b3Mat33_identity, b3Vec3_zero); + +const b3Quat b3Quat_identity(0.0f, 0.0f, 0.0f, 1.0f); + b3Vec2 b3Mat22::Solve(const b3Vec2& b) const { // Cramer's rule diff --git a/src/bounce/dynamics/cloth/cloth.cpp b/src/bounce/dynamics/cloth/cloth.cpp index 830291b..534181c 100644 --- a/src/bounce/dynamics/cloth/cloth.cpp +++ b/src/bounce/dynamics/cloth/cloth.cpp @@ -368,13 +368,13 @@ void b3Cloth::SolveC2() } } -void b3Cloth::Draw(b3Draw* draw) const +void b3Cloth::Draw() const { const b3Mesh* m = m_mesh; for (u32 i = 0; i < m->vertexCount; ++i) { - draw->DrawPoint(m_ps[i].p, 6.0f, b3Color_green); + b3Draw_draw->DrawPoint(m_ps[i].p, 6.0f, b3Color_green); } for (u32 i = 0; i < m->triangleCount; ++i) @@ -394,7 +394,7 @@ void b3Cloth::Draw(b3Draw* draw) const b3Vec3 n2 = -n1; - draw->DrawSolidTriangle(n1, v1, v2, v3, b3Color_blue); - draw->DrawSolidTriangle(n2, v1, v3, v2, b3Color_blue); + b3Draw_draw->DrawSolidTriangle(n1, v1, v2, v3, b3Color_blue); + b3Draw_draw->DrawSolidTriangle(n2, v1, v3, v2, b3Color_blue); } } \ No newline at end of file diff --git a/src/bounce/dynamics/cloth/spring_cloth.cpp b/src/bounce/dynamics/cloth/spring_cloth.cpp index fb2db21..6bf283f 100644 --- a/src/bounce/dynamics/cloth/spring_cloth.cpp +++ b/src/bounce/dynamics/cloth/spring_cloth.cpp @@ -23,6 +23,7 @@ #include #include #include +#include #define B3_FORCE_THRESHOLD (0.1f) @@ -610,7 +611,7 @@ void b3SpringCloth::Apply() const } } -void b3SpringCloth::Draw(b3Draw* draw) const +void b3SpringCloth::Draw() const { const b3Mesh* m = m_mesh; @@ -620,16 +621,16 @@ void b3SpringCloth::Draw(b3Draw* draw) const { if (m_contacts[i].Fn < B3_FORCE_THRESHOLD) { - draw->DrawPoint(m_x[i], 6.0f, b3Color_yellow); + b3Draw_draw->DrawPoint(m_x[i], 6.0f, b3Color_yellow); } else { - draw->DrawPoint(m_x[i], 6.0f, b3Color_red); + b3Draw_draw->DrawPoint(m_x[i], 6.0f, b3Color_red); } } else { - draw->DrawPoint(m_x[i], 6.0f, b3Color_green); + b3Draw_draw->DrawPoint(m_x[i], 6.0f, b3Color_green); } } @@ -646,7 +647,7 @@ void b3SpringCloth::Draw(b3Draw* draw) const b3Vec3 n2 = -n1; - draw->DrawSolidTriangle(n1, v1, v2, v3, b3Color_blue); - draw->DrawSolidTriangle(n2, v1, v3, v2, b3Color_blue); + b3Draw_draw->DrawSolidTriangle(n1, v1, v2, v3, b3Color_blue); + b3Draw_draw->DrawSolidTriangle(n2, v1, v3, v2, b3Color_blue); } } \ No newline at end of file diff --git a/src/bounce/dynamics/contacts/collide/clip.cpp b/src/bounce/dynamics/contacts/collide/clip.cpp index 48e7b38..ded4e26 100644 --- a/src/bounce/dynamics/contacts/collide/clip.cpp +++ b/src/bounce/dynamics/contacts/collide/clip.cpp @@ -21,7 +21,7 @@ #include void b3BuildEdge(b3ClipVertex vOut[2], - const b3Segment* hull) + const b3Capsule* hull) { vOut[0].position = hull->vertices[0]; vOut[0].pair = b3MakePair(0, B3_NULL_EDGE, 0, B3_NULL_EDGE); @@ -150,7 +150,7 @@ void b3ClipPolygonToPlane(b3ClipPolygon& pOut, // Clip a segment to edge side planes. u32 b3ClipEdgeToFace(b3ClipVertex vOut[2], - const b3ClipVertex vIn[2], const b3Segment* hull) + const b3ClipVertex vIn[2], const b3Capsule* hull) { // Start from somewhere. vOut[0] = vIn[0]; @@ -277,4 +277,4 @@ void b3ClipPolygonToFace(b3ClipPolygon& pOut, } while (edge != begin); // Now pOut contains the clipped points. -} +} \ No newline at end of file diff --git a/src/bounce/dynamics/contacts/collide/collide_capsule_hull.cpp b/src/bounce/dynamics/contacts/collide/collide_capsule_hull.cpp index 01d4199..29d3186 100644 --- a/src/bounce/dynamics/contacts/collide/collide_capsule_hull.cpp +++ b/src/bounce/dynamics/contacts/collide/collide_capsule_hull.cpp @@ -94,13 +94,11 @@ static void b3BuildFaceContact(b3Manifold& manifold, const b3Transform& xf2, u32 index2, const b3HullShape* s2) { // Clip edge 1 against the side planes of the face 2. - b3Segment segment1; - segment1.vertices[0] = xf1 * s1->m_centers[0]; - segment1.vertices[1] = xf1 * s1->m_centers[1]; + const b3Capsule hull1(xf1 * s1->m_centers[0], xf1 * s1->m_centers[1], 0.0f); float32 r1 = s1->m_radius; b3ClipVertex edge1[2]; - b3BuildEdge(edge1, &segment1); + b3BuildEdge(edge1, &hull1); const b3Hull* hull2 = s2->m_hull; float32 r2 = s2->m_radius; @@ -162,10 +160,7 @@ void b3CollideCapsuleAndHull(b3Manifold& manifold, return; } - b3Segment hull1; - hull1.vertices[0] = s1->m_centers[0]; - hull1.vertices[1] = s1->m_centers[1]; - + const b3Capsule hull1(s1->m_centers[0], s1->m_centers[1], 0.0f); const b3Hull* hull2 = s2->m_hull; if (gjk.distance > B3_EPSILON) diff --git a/src/bounce/dynamics/contacts/collide/collide_capsules.cpp b/src/bounce/dynamics/contacts/collide/collide_capsules.cpp index 357bd48..7b01ed8 100644 --- a/src/bounce/dynamics/contacts/collide/collide_capsules.cpp +++ b/src/bounce/dynamics/contacts/collide/collide_capsules.cpp @@ -23,7 +23,7 @@ #include // Compute the closest point on a segment to a point. -static b3Vec3 b3ClosestPoint(const b3Vec3& Q, const b3Segment& hull) +static b3Vec3 b3ClosestPoint(const b3Vec3& Q, const b3Capsule& hull) { b3Vec3 A = hull.vertices[0]; b3Vec3 B = hull.vertices[1]; @@ -56,7 +56,7 @@ static b3Vec3 b3ClosestPoint(const b3Vec3& Q, const b3Segment& hull) // Compute the closest points between two line segments. static void b3ClosestPoints(b3Vec3& C1, b3Vec3& C2, - const b3Segment& hull1, const b3Segment& hull2) + const b3Capsule& hull1, const b3Capsule& hull2) { b3Vec3 P1 = hull1.vertices[0]; b3Vec3 Q1 = hull1.vertices[1]; @@ -136,7 +136,7 @@ static void b3ClosestPoints(b3Vec3& C1, b3Vec3& C2, C1 = b3ClosestPoint(C2, hull1); } -static bool b3AreParalell(const b3Segment& hull1, const b3Segment& hull2) +static bool b3AreParalell(const b3Capsule& hull1, const b3Capsule& hull2) { b3Vec3 E1 = hull1.vertices[1] - hull1.vertices[0]; float32 L1 = b3Length(E1); @@ -162,11 +162,11 @@ void b3CollideCapsuleAndCapsule(b3Manifold& manifold, const b3Transform& xf1, const b3CapsuleShape* s1, const b3Transform& xf2, const b3CapsuleShape* s2) { - b3Segment hull1; + b3Capsule hull1; hull1.vertices[0] = xf1 * s1->m_centers[0]; hull1.vertices[1] = xf1 * s1->m_centers[1]; - b3Segment hull2; + b3Capsule hull2; hull2.vertices[0] = xf2 * s2->m_centers[0]; hull2.vertices[1] = xf2 * s2->m_centers[1]; diff --git a/src/bounce/dynamics/contacts/collide/collide_sphere_hull.cpp b/src/bounce/dynamics/contacts/collide/collide_sphere_hull.cpp index 52d225c..1e0e2cc 100644 --- a/src/bounce/dynamics/contacts/collide/collide_sphere_hull.cpp +++ b/src/bounce/dynamics/contacts/collide/collide_sphere_hull.cpp @@ -58,10 +58,10 @@ void b3CollideSphereAndHull(b3Manifold& manifold, return; } - const b3Vec3& hull1 = s1->m_center; + const b3Sphere hull1(s1->m_center, 0.0f); const b3Hull* hull2 = s2->m_hull; - b3FaceQuery faceQuery = b3QueryFaceSeparation(xf1, hull1, xf2, hull2); + b3FaceQuery faceQuery = b3QueryFaceSeparation(xf1, &hull1, xf2, hull2); if (faceQuery.separation > totalRadius) { return; @@ -70,7 +70,7 @@ void b3CollideSphereAndHull(b3Manifold& manifold, b3Plane localPlane2 = hull2->planes[faceQuery.index]; b3Plane plane2 = xf2 * localPlane2; - b3Vec3 c1 = xf1 * hull1; + b3Vec3 c1 = xf1 * hull1.vertex; b3Vec3 c2 = b3ClosestPointOnPlane(c1, plane2); // Ensure normal orientation to shape 2 diff --git a/src/bounce/dynamics/draw_world.cpp b/src/bounce/dynamics/draw_world.cpp index d2d0541..3b674d4 100644 --- a/src/bounce/dynamics/draw_world.cpp +++ b/src/bounce/dynamics/draw_world.cpp @@ -26,13 +26,13 @@ const b3Color b3Color_blue(0.0f, 0.0f, 1.0f); const b3Color b3Color_yellow(1.0f, 1.0f, 0.0f); const b3Color b3Color_pink(1.0f, 0.0f, 1.0f); -b3Draw* b3_debugDraw = NULL; +b3Draw* b3Draw_draw(nullptr); -void b3World::DebugDraw() const +void b3World::Draw() const { - B3_ASSERT(b3_debugDraw); + B3_ASSERT(b3Draw_draw); - u32 flags = b3_debugDraw->m_flags; + u32 flags = b3Draw_draw->m_flags; if (flags & b3Draw::e_centerOfMassesFlag) { @@ -40,7 +40,7 @@ void b3World::DebugDraw() const { b3Transform xf = b->m_xf; xf.position = b->m_sweep.worldCenter; - b3_debugDraw->DrawTransform(xf); + b3Draw_draw->DrawTransform(xf); } } @@ -63,7 +63,7 @@ void b3World::DebugDraw() const for (b3Shape* s = b->m_shapeList.m_head; s; s = s->m_next) { const b3AABB3& aabb = m_contactMan.m_broadPhase.GetAABB(s->m_broadPhaseID); - b3_debugDraw->DrawAABB(aabb, b3Color_pink); + b3Draw_draw->DrawAABB(aabb, b3Color_pink); } } } @@ -72,7 +72,7 @@ void b3World::DebugDraw() const { for (b3Joint* j = m_jointMan.m_jointList.m_head; j; j = j->m_next) { - DrawJoint(j); + j->Draw(); } } @@ -103,12 +103,12 @@ void b3World::DebugDraw() const if (flags & b3Draw::e_contactPointsFlag) { - b3_debugDraw->DrawPoint(p, 4.0f, mp->persisting ? b3Color_green : b3Color_red); + b3Draw_draw->DrawPoint(p, 4.0f, mp->persisting ? b3Color_green : b3Color_red); } if (flags & b3Draw::e_contactNormalsFlag) { - b3_debugDraw->DrawSegment(p, p + n, b3Color_white); + b3Draw_draw->DrawSegment(p, p + n, b3Color_white); } } @@ -121,20 +121,20 @@ void b3World::DebugDraw() const if (flags & b3Draw::e_contactNormalsFlag) { - b3_debugDraw->DrawSegment(p, p + n, b3Color_yellow); + b3Draw_draw->DrawSegment(p, p + n, b3Color_yellow); } if (flags & b3Draw::e_contactTangentsFlag) { - b3_debugDraw->DrawSegment(p, p + t1, b3Color_yellow); - b3_debugDraw->DrawSegment(p, p + t2, b3Color_yellow); + b3Draw_draw->DrawSegment(p, p + t1, b3Color_yellow); + b3Draw_draw->DrawSegment(p, p + t2, b3Color_yellow); } if (m->pointCount > 2) { if (flags & b3Draw::e_contactPolygonsFlag) { - b3_debugDraw->DrawSolidPolygon(wm.normal, points, m->pointCount, b3Color_pink); + b3Draw_draw->DrawSolidPolygon(wm.normal, points, m->pointCount, b3Color_pink); } } } @@ -151,7 +151,7 @@ void b3World::DrawShape(const b3Transform& xf, const b3Shape* shape) const { const b3SphereShape* sphere = (b3SphereShape*)shape; b3Vec3 p = xf * sphere->m_center; - b3_debugDraw->DrawPoint(p, 4.0f, wireColor); + b3Draw_draw->DrawPoint(p, 4.0f, wireColor); break; } case e_capsuleShape: @@ -159,9 +159,9 @@ void b3World::DrawShape(const b3Transform& xf, const b3Shape* shape) const const b3CapsuleShape* capsule = (b3CapsuleShape*)shape; b3Vec3 p1 = xf * capsule->m_centers[0]; b3Vec3 p2 = xf * capsule->m_centers[1]; - b3_debugDraw->DrawPoint(p1, 4.0f, wireColor); - b3_debugDraw->DrawPoint(p2, 4.0f, wireColor); - b3_debugDraw->DrawSegment(p1, p2, wireColor); + b3Draw_draw->DrawPoint(p1, 4.0f, wireColor); + b3Draw_draw->DrawPoint(p2, 4.0f, wireColor); + b3Draw_draw->DrawSegment(p1, p2, wireColor); break; } case e_hullShape: @@ -176,7 +176,7 @@ void b3World::DrawShape(const b3Transform& xf, const b3Shape* shape) const b3Vec3 p1 = xf * hull->vertices[edge->origin]; b3Vec3 p2 = xf * hull->vertices[twin->origin]; - b3_debugDraw->DrawSegment(p1, p2, wireColor); + b3Draw_draw->DrawSegment(p1, p2, wireColor); } break; } @@ -192,7 +192,7 @@ void b3World::DrawShape(const b3Transform& xf, const b3Shape* shape) const b3Vec3 p2 = xf * mesh->vertices[t->v2]; b3Vec3 p3 = xf * mesh->vertices[t->v3]; - b3_debugDraw->DrawTriangle(p1, p2, p3, wireColor); + b3Draw_draw->DrawTriangle(p1, p2, p3, wireColor); } break; } @@ -201,59 +201,4 @@ void b3World::DrawShape(const b3Transform& xf, const b3Shape* shape) const break; } }; -} - -void b3World::DrawJoint(const b3Joint* joint) const -{ - b3JointType type = joint->GetType(); - - switch (type) - { - case e_mouseJoint: - { - b3MouseJoint* o = (b3MouseJoint*)joint; - o->Draw(b3_debugDraw); - break; - } - case e_springJoint: - { - b3SpringJoint* o = (b3SpringJoint*)joint; - o->Draw(b3_debugDraw); - break; - } - case e_weldJoint: - { - b3WeldJoint* o = (b3WeldJoint*)joint; - o->Draw(b3_debugDraw); - break; - } - case e_revoluteJoint: - { - b3RevoluteJoint* o = (b3RevoluteJoint*)joint; - o->Draw(b3_debugDraw); - break; - } - case e_sphereJoint: - { - b3SphereJoint* o = (b3SphereJoint*)joint; - o->Draw(b3_debugDraw); - break; - } - case e_coneJoint: - { - b3ConeJoint* o = (b3ConeJoint*)joint; - o->Draw(b3_debugDraw); - break; - } - default: - { - B3_ASSERT(false); - break; - } - } -} - -void b3World::DrawContact(const b3Contact* c) const -{ - B3_NOT_USED(c); -} +} \ No newline at end of file diff --git a/src/bounce/dynamics/joints/cone_joint.cpp b/src/bounce/dynamics/joints/cone_joint.cpp index a5217a1..94726bd 100644 --- a/src/bounce/dynamics/joints/cone_joint.cpp +++ b/src/bounce/dynamics/joints/cone_joint.cpp @@ -346,10 +346,10 @@ void b3ConeJoint::SetConeAngle(float32 angle) } } -void b3ConeJoint::Draw(b3Draw* draw) const +void b3ConeJoint::Draw() const { b3Transform xfA = GetFrameA(); - draw->DrawTransform(xfA); + b3Draw_draw->DrawTransform(xfA); b3Transform xfB = GetFrameB(); - draw->DrawTransform(xfB); + b3Draw_draw->DrawTransform(xfB); } \ No newline at end of file diff --git a/src/bounce/dynamics/joints/mouse_joint.cpp b/src/bounce/dynamics/joints/mouse_joint.cpp index 1c2d1e6..dc38de1 100644 --- a/src/bounce/dynamics/joints/mouse_joint.cpp +++ b/src/bounce/dynamics/joints/mouse_joint.cpp @@ -109,12 +109,12 @@ void b3MouseJoint::SetTarget(const b3Vec3& target) GetBodyB()->SetAwake(true); } -void b3MouseJoint::Draw(b3Draw* draw) const +void b3MouseJoint::Draw() const { b3Vec3 a = GetAnchorA(); b3Vec3 b = GetAnchorB(); - draw->DrawPoint(a, 4.0f, b3Color_green); - draw->DrawPoint(b, 4.0f, b3Color_red); - draw->DrawSegment(a, b, b3Color_yellow); + b3Draw_draw->DrawPoint(a, 4.0f, b3Color_green); + b3Draw_draw->DrawPoint(b, 4.0f, b3Color_red); + b3Draw_draw->DrawSegment(a, b, b3Color_yellow); } \ No newline at end of file diff --git a/src/bounce/dynamics/joints/revolute_joint.cpp b/src/bounce/dynamics/joints/revolute_joint.cpp index 0bacca8..dc9964b 100644 --- a/src/bounce/dynamics/joints/revolute_joint.cpp +++ b/src/bounce/dynamics/joints/revolute_joint.cpp @@ -749,10 +749,11 @@ void b3RevoluteJoint::SetMaxMotorTorque(float32 torque) m_maxMotorTorque = torque; } -void b3RevoluteJoint::Draw(b3Draw* draw) const +void b3RevoluteJoint::Draw() const { b3Transform xfA = GetFrameA(); + b3Draw_draw->DrawTransform(xfA); + b3Transform xfB = GetFrameB(); - draw->DrawTransform(xfA); - draw->DrawTransform(xfB); + b3Draw_draw->DrawTransform(xfB); } \ No newline at end of file diff --git a/src/bounce/dynamics/joints/sphere_joint.cpp b/src/bounce/dynamics/joints/sphere_joint.cpp index 7bef9aa..f62ef2f 100644 --- a/src/bounce/dynamics/joints/sphere_joint.cpp +++ b/src/bounce/dynamics/joints/sphere_joint.cpp @@ -157,12 +157,13 @@ b3Vec3 b3SphereJoint::GetAnchorB() const return GetBodyB()->GetWorldPoint(m_localAnchorB); } -void b3SphereJoint::Draw(b3Draw* draw) const +void b3SphereJoint::Draw() const { b3Vec3 a = GetAnchorA(); - b3Vec3 b = GetAnchorB(); + b3Draw_draw->DrawPoint(a, 4.0f, b3Color_red); - draw->DrawPoint(a, 4.0f, b3Color_red); - draw->DrawPoint(b, 4.0f, b3Color_green); - draw->DrawSegment(a, b, b3Color_yellow); + b3Vec3 b = GetAnchorB(); + b3Draw_draw->DrawPoint(b, 4.0f, b3Color_green); + + b3Draw_draw->DrawSegment(a, b, b3Color_yellow); } diff --git a/src/bounce/dynamics/joints/spring_joint.cpp b/src/bounce/dynamics/joints/spring_joint.cpp index 1006e49..6aa667e 100644 --- a/src/bounce/dynamics/joints/spring_joint.cpp +++ b/src/bounce/dynamics/joints/spring_joint.cpp @@ -252,12 +252,13 @@ bool b3SpringJoint::SolvePositionConstraints(const b3SolverData* data) return b3Abs(C) < B3_LINEAR_SLOP; } -void b3SpringJoint::Draw(b3Draw* draw) const +void b3SpringJoint::Draw() const { b3Vec3 a = GetBodyA()->GetWorldPoint(m_localAnchorA); - b3Vec3 b = GetBodyB()->GetWorldPoint(m_localAnchorB); + b3Draw_draw->DrawPoint(a, 4.0f, b3Color_red); - draw->DrawPoint(a, 4.0f, b3Color_red); - draw->DrawPoint(b, 4.0f, b3Color_green); - draw->DrawSegment(a, b, b3Color_yellow); -} + b3Vec3 b = GetBodyB()->GetWorldPoint(m_localAnchorB); + b3Draw_draw->DrawPoint(b, 4.0f, b3Color_green); + + b3Draw_draw->DrawSegment(a, b, b3Color_yellow); +} \ No newline at end of file diff --git a/src/bounce/dynamics/joints/weld_joint.cpp b/src/bounce/dynamics/joints/weld_joint.cpp index 13e7d17..22e15b0 100644 --- a/src/bounce/dynamics/joints/weld_joint.cpp +++ b/src/bounce/dynamics/joints/weld_joint.cpp @@ -311,12 +311,13 @@ b3Vec3 b3WeldJoint::GetAnchorB() const return GetBodyB()->GetWorldPoint(m_localAnchorB); } -void b3WeldJoint::Draw(b3Draw* draw) const +void b3WeldJoint::Draw() const { b3Vec3 a = GetAnchorA(); + b3Draw_draw->DrawPoint(a, 4.0f, b3Color_red); + b3Vec3 b = GetAnchorB(); - - draw->DrawPoint(a, 4.0f, b3Color_red); - draw->DrawPoint(b, 4.0f, b3Color_green); - draw->DrawSegment(a, b, b3Color_yellow); -} + b3Draw_draw->DrawPoint(b, 4.0f, b3Color_green); + + b3Draw_draw->DrawSegment(a, b, b3Color_yellow); +} \ No newline at end of file diff --git a/src/bounce/dynamics/rope/rope.cpp b/src/bounce/dynamics/rope/rope.cpp index d03da4a..6ddec52 100644 --- a/src/bounce/dynamics/rope/rope.cpp +++ b/src/bounce/dynamics/rope/rope.cpp @@ -170,12 +170,13 @@ void b3Rope::Initialize(const b3RopeDef& def) b3Vec3 d = -b->m_X_J_j.position; - b3Vec3 w1(1.0f, 0.0f, 0.0f); - b3Vec3 w2(0.0f, 1.0f, 0.0f); - b3Vec3 w3(0.0f, 0.0f, 1.0f); - + b3Vec3 w1(b3Vec3_x); b3Vec3 v1 = b3Cross(w1, d); + + b3Vec3 w2(b3Vec3_y); b3Vec3 v2 = b3Cross(w2, d); + + b3Vec3 w3(b3Vec3_z); b3Vec3 v3 = b3Cross(w3, d); b->m_S[0].w = w1; @@ -468,7 +469,7 @@ void b3Rope::Step(float32 h) } } -void b3Rope::Draw(b3Draw* draw) const +void b3Rope::Draw() const { if (m_count == 0) { @@ -478,8 +479,8 @@ void b3Rope::Draw(b3Draw* draw) const { b3RopeBody* b = m_links; - draw->DrawTransform(b->m_X); - draw->DrawSolidSphere(b->m_X.position, 0.2f, b3Color_green); + b3Draw_draw->DrawTransform(b->m_X); + b3Draw_draw->DrawSolidSphere(b->m_X.position, 0.2f, b3Color_green); } for (u32 i = 1; i < m_count; ++i) @@ -490,13 +491,13 @@ void b3Rope::Draw(b3Draw* draw) const b3Transform X_J = b0->m_X * b3Inverse(b->m_X_i_J); b3Transform X_J0 = b->m_X * b->m_X_J_j; - draw->DrawTransform(X_J); - draw->DrawPoint(X_J.position, 5.0f, b3Color_red); + b3Draw_draw->DrawTransform(X_J); + b3Draw_draw->DrawPoint(X_J.position, 5.0f, b3Color_red); - draw->DrawTransform(X_J0); - draw->DrawPoint(X_J0.position, 5.0f, b3Color_red); + b3Draw_draw->DrawTransform(X_J0); + b3Draw_draw->DrawPoint(X_J0.position, 5.0f, b3Color_red); - draw->DrawTransform(b->m_X); - draw->DrawSolidSphere(b->m_X.position, 0.2f, b3Color_green); + b3Draw_draw->DrawTransform(b->m_X); + b3Draw_draw->DrawSolidSphere(b->m_X.position, 0.2f, b3Color_green); } } \ No newline at end of file diff --git a/src/bounce/dynamics/world.cpp b/src/bounce/dynamics/world.cpp index 50a01f1..27c2972 100644 --- a/src/bounce/dynamics/world.cpp +++ b/src/bounce/dynamics/world.cpp @@ -32,7 +32,6 @@ b3World::b3World() : m_bodyBlocks(sizeof(b3Body)) { b3_allocCalls = 0; b3_maxAllocCalls = 0; - m_debugDraw = NULL; m_flags = e_clearForcesFlag; m_sleeping = false;