use mvc for the testbed, update almost all tests, bugfixes, improvements, cleanup
Since I started altering the testbed for better maintainability, I prefered to drop this (tested) large change with a single commit. Some changes below: Put some globals in their correct place, Now Testbed uses the MVC pattern (Model-View Controller). This way it becomes better to maintain than using no pattern in my opinion. Fixed some bugs in the debug draw interface. Of course, updated almost all tests because of the differences. Update script.
This commit is contained in:
162
examples/testbed/framework/controller.cpp
Normal file
162
examples/testbed/framework/controller.cpp
Normal file
@ -0,0 +1,162 @@
|
||||
#include <testbed/framework/controller.h>
|
||||
#include <testbed/framework/model.h>
|
||||
#include <testbed/framework/view.h>
|
||||
|
||||
// !
|
||||
#include <glfw/glfw3.h>
|
||||
|
||||
// !
|
||||
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);
|
||||
}
|
||||
}
|
59
examples/testbed/framework/controller.h
Normal file
59
examples/testbed/framework/controller.h
Normal file
@ -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 <bounce/common/math/vec2.h>
|
||||
|
||||
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
|
@ -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
|
@ -24,99 +24,10 @@
|
||||
#include <stdio.h>
|
||||
#include <stdarg.h>
|
||||
|
||||
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)
|
||||
|
@ -24,99 +24,10 @@
|
||||
#include <stdio.h>
|
||||
#include <stdarg.h>
|
||||
|
||||
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)
|
||||
|
@ -16,166 +16,53 @@
|
||||
* 3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
|
||||
#if defined(__APPLE_CC__)
|
||||
#include <OpenGL/gl3.h>
|
||||
#if defined (U_OPENGL_2)
|
||||
#include <glad_2/glad.h>
|
||||
#elif defined (U_OPENGL_4)
|
||||
#include <glad_4/glad.h>
|
||||
#else
|
||||
|
||||
#if defined(U_OPENGL_2)
|
||||
#include <glad_2/glad.h>
|
||||
#elif defined(U_OPENGL_4)
|
||||
#include <glad_4/glad.h>
|
||||
#else
|
||||
|
||||
// error
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
#include <imgui/imgui.h>
|
||||
|
||||
#if defined(U_OPENGL_2)
|
||||
#include <imgui/imgui_impl_glfw_gl2.h>
|
||||
#elif defined(U_OPENGL_4)
|
||||
#include <imgui/imgui_impl_glfw_gl3.h>
|
||||
#else
|
||||
// error
|
||||
#endif
|
||||
|
||||
#include <testbed/framework/testbed_listener.h>
|
||||
#include <testbed/tests/test.h>
|
||||
#include <glfw/glfw3.h>
|
||||
#include <testbed/framework/model.h>
|
||||
#include <testbed/framework/view.h>
|
||||
#include <testbed/framework/controller.h>
|
||||
|
||||
//
|
||||
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;
|
||||
}
|
130
examples/testbed/framework/model.cpp
Normal file
130
examples/testbed/framework/model.cpp
Normal file
@ -0,0 +1,130 @@
|
||||
#include <testbed/framework/model.h>
|
||||
|
||||
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<ProfilerRecord>& 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();
|
||||
}
|
225
examples/testbed/framework/model.h
Normal file
225
examples/testbed/framework/model.h
Normal file
@ -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 <testbed/framework/debug_draw.h>
|
||||
#include <testbed/framework/testbed_listener.h>
|
||||
#include <testbed/tests/test.h>
|
||||
|
||||
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
|
@ -18,6 +18,9 @@
|
||||
|
||||
#include <testbed/framework/profiler.h>
|
||||
|
||||
Profiler* g_profiler = nullptr;
|
||||
ProfilerListener* g_profilerListener = nullptr;
|
||||
|
||||
Profiler::Profiler()
|
||||
{
|
||||
m_top = nullptr;
|
||||
|
@ -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
|
@ -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<ProfilerRecord>& 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)
|
||||
|
@ -117,4 +117,18 @@ TestEntry g_tests[] =
|
||||
{ "Mass-Spring System", &MassSpring::Create },
|
||||
{ "Shift Center", &ShiftCenter::Create },
|
||||
{ NULL, NULL }
|
||||
};
|
||||
};
|
||||
|
||||
//
|
||||
static u32 TestCount()
|
||||
{
|
||||
u32 count = 0;
|
||||
while (g_tests[count].create != NULL)
|
||||
{
|
||||
++count;
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
// Count the tests
|
||||
u32 g_testCount = TestCount();
|
@ -30,14 +30,13 @@
|
||||
#include <testbed\framework\json_profiler.h>
|
||||
#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
|
||||
|
261
examples/testbed/framework/view.cpp
Normal file
261
examples/testbed/framework/view.cpp
Normal file
@ -0,0 +1,261 @@
|
||||
#include <testbed/framework/view.h>
|
||||
#include <testbed/framework/model.h>
|
||||
|
||||
#if defined (U_OPENGL_2)
|
||||
#include <imgui/imgui_impl_glfw_gl2.h>
|
||||
#elif defined (U_OPENGL_4)
|
||||
#include <imgui/imgui_impl_glfw_gl3.h>
|
||||
#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());
|
||||
}
|
43
examples/testbed/framework/view.h
Normal file
43
examples/testbed/framework/view.h
Normal file
@ -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
|
Reference in New Issue
Block a user