testbed, tests, ui

This commit is contained in:
Irlan 2018-04-12 01:50:22 -03:00
parent 3c8af0060a
commit eb698f146a
31 changed files with 1031 additions and 1370 deletions

View File

@ -0,0 +1,522 @@
/*
* 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 <testbed/framework/draw.h>
#if defined (U_OPENGL_2)
#include <testbed/framework/draw_gl2.h>
#elif defined (U_OPENGL_4)
#include <testbed/framework/draw_gl4.h>
#else
#endif
#include <imgui/imgui.h>
Camera* g_camera = nullptr;
Draw* g_draw = nullptr;
u32 g_drawFlags = 0;
Draw::Draw()
{
m_points = new DrawPoints();
m_lines = new DrawLines();
m_triangles = new DrawTriangles();
m_wire = new DrawWire();
m_solid = new DrawSolid();
}
Draw::~Draw()
{
delete m_points;
delete m_lines;
delete m_triangles;
delete m_wire;
delete m_solid;
}
void Draw::DrawPoint(const b3Vec3& p, float32 size, const b3Color& color)
{
m_points->Vertex(p, size, color);
}
void Draw::DrawSegment(const b3Vec3& p1, const b3Vec3& p2, const b3Color& color)
{
m_lines->Vertex(p1, color);
m_lines->Vertex(p2, color);
}
void Draw::DrawTriangle(const b3Vec3& p1, const b3Vec3& p2, const b3Vec3& p3, const b3Color& color)
{
DrawSegment(p1, p2, color);
DrawSegment(p2, p3, color);
DrawSegment(p3, p1, color);
}
void Draw::DrawSolidTriangle(const b3Vec3& normal, const b3Vec3& p1, const b3Vec3& p2, const b3Vec3& p3, const b3Color& color)
{
m_triangles->Vertex(p1, color, normal);
m_triangles->Vertex(p2, color, normal);
m_triangles->Vertex(p3, color, normal);
b3Color edgeColor(0.0f, 0.0f, 0.0f, 1.0f);
DrawTriangle(p1, p2, p3, edgeColor);
}
void Draw::DrawSolidTriangle(const b3Vec3& normal, const b3Vec3& p1, const b3Color& color1, const b3Vec3& p2, const b3Color& color2, const b3Vec3& p3, const b3Color& color3)
{
m_triangles->Vertex(p1, color1, normal);
m_triangles->Vertex(p2, color2, normal);
m_triangles->Vertex(p3, color3, normal);
b3Color edgeColor(0.0f, 0.0f, 0.0f, 1.0f);
DrawTriangle(p1, p2, p3, edgeColor);
}
void Draw::DrawPolygon(const b3Vec3* vertices, u32 count, const b3Color& color)
{
b3Vec3 p1 = vertices[count - 1];
for (u32 i = 0; i < count; ++i)
{
b3Vec3 p2 = vertices[i];
m_lines->Vertex(p1, color);
m_lines->Vertex(p2, color);
p1 = p2;
}
}
void Draw::DrawSolidPolygon(const b3Vec3& normal, const b3Vec3* vertices, u32 count, const b3Color& color)
{
b3Color fillColor(color.r, color.g, color.b, color.a);
b3Vec3 p1 = vertices[0];
for (u32 i = 1; i < count - 1; ++i)
{
b3Vec3 p2 = vertices[i];
b3Vec3 p3 = vertices[i + 1];
m_triangles->Vertex(p1, fillColor, normal);
m_triangles->Vertex(p2, fillColor, normal);
m_triangles->Vertex(p3, fillColor, normal);
}
b3Color frameColor(0.5f * color.r, 0.5f * color.g, 0.5f * color.b, 1.0f);
DrawPolygon(vertices, count, frameColor);
}
void Draw::DrawCircle(const b3Vec3& normal, const b3Vec3& center, float32 radius, const b3Color& color)
{
// Build a tangent vector to normal.
b3Vec3 u = b3Cross(normal, b3Vec3(1.0f, 0.0f, 0.0f));
b3Vec3 v = b3Cross(normal, b3Vec3(0.0f, 1.0f, 0.0f));
// Handle edge cases (zero cross product).
b3Vec3 n1;
if (b3LengthSquared(u) > b3LengthSquared(v))
{
n1 = u;
}
else
{
n1 = v;
}
n1.Normalize();
// Build a quaternion to rotate the tangent about the normal.
u32 kEdgeCount = 20;
float32 kAngleInc = 2.0f * B3_PI / float32(kEdgeCount);
b3Quat q(normal, kAngleInc);
b3Vec3 p1 = center + radius * n1;
for (u32 i = 0; i < kEdgeCount; ++i)
{
b3Vec3 n2 = b3Mul(q, n1);
b3Vec3 p2 = center + radius * n2;
m_lines->Vertex(p1, color);
m_lines->Vertex(p2, color);
n1 = n2;
p1 = p2;
}
}
void Draw::DrawSolidCircle(const b3Vec3& normal, const b3Vec3& center, float32 radius, const b3Color& color)
{
b3Color fillColor(color.r, color.g, color.b, color.a);
b3Color frameColor(0.5f * color.r, 0.5f * color.g, 0.5f * color.b, 1.0f);
// Build a tangent vector to normal.
b3Vec3 u = b3Cross(normal, b3Vec3(1.0f, 0.0f, 0.0f));
b3Vec3 v = b3Cross(normal, b3Vec3(0.0f, 1.0f, 0.0f));
// Handle edge cases (zero cross product).
b3Vec3 n1;
if (b3LengthSquared(u) > b3LengthSquared(v))
{
n1 = u;
}
else
{
n1 = v;
}
n1.Normalize();
// Build a quaternion to rotate the tangent about the normal.
const u32 kEdgeCount = 20;
const float32 kAngleInc = 2.0f * B3_PI / float32(kEdgeCount);
b3Quat q(normal, kAngleInc);
b3Vec3 p1 = center + radius * n1;
for (u32 i = 0; i < kEdgeCount; ++i)
{
b3Vec3 n2 = b3Mul(q, n1);
b3Vec3 p2 = center + radius * n2;
m_triangles->Vertex(center, fillColor, normal);
m_triangles->Vertex(p1, fillColor, normal);
m_triangles->Vertex(p2, fillColor, normal);
m_lines->Vertex(p1, frameColor);
m_lines->Vertex(p2, frameColor);
n1 = n2;
p1 = p2;
}
}
void Draw::DrawSphere(const b3Vec3& center, float32 radius, const b3Color& color)
{
b3Transform xf;
xf.SetIdentity();
xf.position = center;
m_wire->DrawSphere(radius, color, xf);
}
void Draw::DrawSolidSphere(const b3Vec3& center, float32 radius, const b3Color& color)
{
b3Transform xf;
xf.SetIdentity();
xf.position = center;
m_solid->DrawSphere(radius, color, xf);
}
void Draw::DrawCapsule(const b3Vec3& c1, const b3Vec3& c2, float32 radius, const b3Color& color)
{
float32 height = b3Length(c1 - c2);
{
b3Transform xfc;
xfc.rotation.SetIdentity();
xfc.position = c1;
m_wire->DrawSphere(radius, color, xfc);
}
if (height > 0.0f)
{
DrawSegment(c1, c2, color);
{
b3Transform xfc;
xfc.rotation.SetIdentity();
xfc.position = c2;
m_wire->DrawSphere(radius, color, xfc);
}
}
}
void Draw::DrawSolidCapsule(const b3Vec3& c1, const b3Vec3& c2, float32 radius, const b3Color& c)
{
float32 height = b3Length(c1 - c2);
{
b3Transform xfc;
xfc.rotation.SetIdentity();
xfc.position = c1;
m_solid->DrawSphere(radius, c, xfc);
}
if (height > 0.0f)
{
{
b3Mat33 R;
R.y = (1.0f / height) * (c1 - c2);
R.z = b3Perp(R.y);
R.x = b3Cross(R.y, R.z);
b3Transform xfc;
xfc.position = 0.5f * (c1 + c2);
xfc.rotation = R;
m_solid->DrawCylinder(radius, height, c, xfc);
}
{
b3Transform xfc;
xfc.rotation.SetIdentity();
xfc.position = c2;
m_solid->DrawSphere(radius, c, xfc);
}
}
}
void Draw::DrawTransform(const b3Transform& xf)
{
float32 lenght = 1.0f;
b3Color red(1.0f, 0.0f, 0.0f, 1.0f);
b3Color green(0.0f, 1.0f, 0.0f, 1.0f);
b3Color blue(0.0f, 0.0f, 1.0f, 1.0f);
b3Vec3 position = xf.position;
b3Mat33 rotation = xf.rotation;
b3Vec3 A = position + lenght * rotation.x;
b3Vec3 B = position + lenght * rotation.y;
b3Vec3 C = position + lenght * rotation.z;
DrawSegment(position, A, red);
DrawSegment(position, B, green);
DrawSegment(position, C, blue);
}
void Draw::DrawAABB(const b3AABB3& aabb, const b3Color& color)
{
b3Vec3 lower = aabb.m_lower;
b3Vec3 upper = aabb.m_upper;
b3Vec3 vs[8];
vs[0] = lower;
vs[1] = b3Vec3(lower.x, upper.y, lower.z);
vs[2] = b3Vec3(upper.x, upper.y, lower.z);
vs[3] = b3Vec3(upper.x, lower.y, lower.z);
vs[4] = upper;
vs[5] = b3Vec3(upper.x, lower.y, upper.z);
vs[6] = b3Vec3(lower.x, lower.y, upper.z);
vs[7] = b3Vec3(lower.x, upper.y, upper.z);
DrawSegment(vs[0], vs[1], color);
DrawSegment(vs[1], vs[2], color);
DrawSegment(vs[2], vs[3], color);
DrawSegment(vs[3], vs[0], color);
DrawSegment(vs[4], vs[5], color);
DrawSegment(vs[5], vs[6], color);
DrawSegment(vs[6], vs[7], color);
DrawSegment(vs[7], vs[4], color);
DrawSegment(vs[2], vs[4], color);
DrawSegment(vs[5], vs[3], color);
DrawSegment(vs[6], vs[0], color);
DrawSegment(vs[1], vs[7], color);
}
void Draw::DrawString(const b3Color& color, const char* text, ...)
{
va_list args;
va_start(args, text);
ImGui::SetNextWindowPos(ImVec2(0.0f, 40.0f));
ImGui::SetNextWindowSize(ImVec2(g_camera->m_width, g_camera->m_height));
ImGui::Begin("Overlay", 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(args);
}
void Draw::DrawSolidSphere(const b3SphereShape* s, const b3Color& c, const b3Transform& xf)
{
b3Transform xfc;
xfc.rotation = xf.rotation;
xfc.position = xf * s->m_center;
m_solid->DrawSphere(s->m_radius, c, xfc);
}
void Draw::DrawSolidCapsule(const b3CapsuleShape* s, const b3Color& c, const b3Transform& xf)
{
b3Vec3 c1 = s->m_centers[0];
b3Vec3 c2 = s->m_centers[1];
float32 height = b3Length(c1 - c2);
float32 radius = s->m_radius;
{
b3Transform xfc;
xfc.rotation = xf.rotation;
xfc.position = xf * c1;
m_solid->DrawSphere(radius, c, xfc);
}
if (height > 0.0f)
{
{
b3Mat33 R;
R.y = (1.0f / height) * (c1 - c2);
R.z = b3Perp(R.y);
R.x = b3Cross(R.y, R.z);
b3Transform xfc;
xfc.position = xf * (0.5f * (c1 + c2));
xfc.rotation = xf.rotation * R;
m_solid->DrawCylinder(radius, height, c, xfc);
}
{
b3Transform xfc;
xfc.rotation = xf.rotation;
xfc.position = xf * c2;
m_solid->DrawSphere(radius, c, xfc);
}
}
}
void Draw::DrawSolidHull(const b3HullShape* s, const b3Color& c, const b3Transform& xf)
{
const b3Hull* hull = s->m_hull;
for (u32 i = 0; i < hull->faceCount; ++i)
{
const b3Face* face = hull->GetFace(i);
const b3HalfEdge* begin = hull->GetEdge(face->edge);
b3Vec3 n = xf.rotation * hull->planes[i].normal;
const b3HalfEdge* edge = hull->GetEdge(begin->next);
do
{
u32 i1 = begin->origin;
u32 i2 = edge->origin;
const b3HalfEdge* next = hull->GetEdge(edge->next);
u32 i3 = next->origin;
b3Vec3 p1 = xf * hull->vertices[i1];
b3Vec3 p2 = xf * hull->vertices[i2];
b3Vec3 p3 = xf * hull->vertices[i3];
m_triangles->Vertex(p1, c, n);
m_triangles->Vertex(p2, c, n);
m_triangles->Vertex(p3, c, n);
edge = next;
} while (hull->GetEdge(edge->next) != begin);
}
}
void Draw::DrawSolidMesh(const b3MeshShape* s, const b3Color& c, const b3Transform& xf)
{
const b3Mesh* mesh = s->m_mesh;
for (u32 i = 0; i < mesh->triangleCount; ++i)
{
const b3Triangle* t = mesh->triangles + i;
b3Vec3 p1 = xf * mesh->vertices[t->v1];
b3Vec3 p2 = xf * mesh->vertices[t->v2];
b3Vec3 p3 = xf * mesh->vertices[t->v3];
b3Vec3 n1 = b3Cross(p2 - p1, p3 - p1);
n1.Normalize();
m_triangles->Vertex(p1, c, n1);
m_triangles->Vertex(p2, c, n1);
m_triangles->Vertex(p3, c, n1);
b3Vec3 n2 = -n1;
m_triangles->Vertex(p1, c, n2);
m_triangles->Vertex(p3, c, n2);
m_triangles->Vertex(p2, c, n2);
}
}
void Draw::DrawSolidShape(const b3Shape* s, const b3Color& c, const b3Transform& xf)
{
switch (s->GetType())
{
case e_sphereShape:
{
DrawSolidSphere((b3SphereShape*)s, c, xf);
break;
}
case e_capsuleShape:
{
DrawSolidCapsule((b3CapsuleShape*)s, c, xf);
break;
}
case e_hullShape:
{
DrawSolidHull((b3HullShape*)s, c, xf);
break;
}
case e_meshShape:
{
DrawSolidMesh((b3MeshShape*)s, c, xf);
break;
}
default:
{
break;
}
}
}
void Draw::DrawSolidShapes(const b3World& world)
{
for (b3Body* b = world.GetBodyList().m_head; b; b = b->GetNext())
{
b3Color c;
if (b->IsAwake() == false)
{
c = b3Color(0.5f, 0.25f, 0.25f, 1.0f);
}
else if (b->GetType() == e_staticBody)
{
c = b3Color(0.5f, 0.5f, 0.5f, 1.0f);
}
else if (b->GetType() == e_dynamicBody)
{
c = b3Color(1.0f, 0.5f, 0.5f, 1.0f);
}
else
{
c = b3Color(0.5f, 0.5f, 1.0f, 1.0f);
}
b3Transform xf = b->GetTransform();
for (b3Shape* s = b->GetShapeList().m_head; s; s = s->GetNext())
{
DrawSolidShape(s, c, xf);
}
}
}
void Draw::Flush()
{
m_triangles->Flush();
m_lines->Flush();
m_points->Flush();
}

View File

@ -16,8 +16,8 @@
* 3. This notice may not be removed or altered from any source distribution.
*/
#ifndef DEBUG_DRAW_H
#define DEBUG_DRAW_H
#ifndef DRAW_H
#define DRAW_H
#include <bounce/bounce.h>
@ -168,12 +168,19 @@ inline Ray3 Camera::ConvertScreenToWorld(const b3Vec2& ps) const
}
//
class DebugDraw : public b3Draw
enum DrawFlags
{
e_pointsFlag = 0x0001,
e_linesFlag = 0x0002,
e_trianglesFlag = 0x0004
};
class Draw : public b3Draw
{
public:
DebugDraw();
~DebugDraw();
Draw();
~Draw();
void DrawPoint(const b3Vec3& p, float32 size, const b3Color& color);
void DrawSegment(const b3Vec3& p1, const b3Vec3& p2, const b3Color& color);
@ -203,35 +210,40 @@ public:
void DrawAABB(const b3AABB3& aabb, const b3Color& color);
void DrawTransform(const b3Transform& xf);
//
void DrawString(const b3Color& color, const char* string, ...);
void DrawSphere(const b3SphereShape* s, const b3Color& c, const b3Transform& xf);
void DrawSolidSphere(const b3SphereShape* s, const b3Color& c, const b3Transform& xf);
void DrawCapsule(const b3CapsuleShape* s, const b3Color& c, const b3Transform& xf);
void DrawSolidCapsule(const b3CapsuleShape* s, const b3Color& c, const b3Transform& xf);
void DrawHull(const b3HullShape* s, const b3Color& c, const b3Transform& xf);
void DrawSolidHull(const b3HullShape* s, const b3Color& c, const b3Transform& xf);
void DrawMesh(const b3MeshShape* s, const b3Color& c, const b3Transform& xf);
void DrawSolidMesh(const b3MeshShape* s, const b3Color& c, const b3Transform& xf);
void DrawShape(const b3Shape* s, const b3Color& c, const b3Transform& xf);
void DrawSolidShape(const b3Shape* s, const b3Color& c, const b3Transform& xf);
void Draw(const b3World& world);
void DrawSolidShapes(const b3World& world);
void Submit();
void Flush();
private:
friend struct DrawShapes;
friend struct DrawPoints;
friend struct DrawLines;
friend struct DrawTriangles;
DrawPoints* m_points;
DrawLines* m_lines;
DrawTriangles* m_triangles;
friend struct DrawWire;
friend struct DrawSolid;
DrawWire* m_wire;
DrawSolid* m_solid;
};
extern DebugDraw* g_debugDraw;
extern Camera* g_camera;
extern const char* g_overlayName;
extern Draw* g_draw;
extern u32 g_drawFlags;
#endif

View File

@ -16,19 +16,16 @@
* 3. This notice may not be removed or altered from any source distribution.
*/
#include <testbed/framework/debug_draw.h>
#ifndef DRAW_GL2_H
#define DRAW_GL2_H
#include <testbed/framework/draw.h>
#include <glad_2/glad.h>
#include <imgui/imgui.h>
#include <stdio.h>
#include <stdarg.h>
//
DebugDraw* g_debugDraw = nullptr;
Camera* g_camera = nullptr;
const char* g_overlayName = nullptr;
#define BUFFER_OFFSET(i) ((char*)NULL + (i))
static void AssertGL()
@ -176,7 +173,7 @@ struct DrawPoints
{
if (m_count == e_vertexCapacity)
{
Submit();
Flush();
}
m_vertices[m_count] = v;
@ -185,13 +182,19 @@ struct DrawPoints
++m_count;
}
void Submit()
void Flush()
{
if (m_count == 0)
{
return;
}
if ((g_drawFlags & DrawFlags::e_pointsFlag) == 0)
{
m_count = 0;
return;
}
glUseProgram(m_programId);
b3Mat44 m1 = g_camera->BuildViewMatrix();
@ -306,7 +309,7 @@ struct DrawLines
{
if (m_count == e_vertexCapacity)
{
Submit();
Flush();
}
m_vertices[m_count] = v;
@ -314,13 +317,19 @@ struct DrawLines
++m_count;
}
void Submit()
void Flush()
{
if (m_count == 0)
{
return;
}
if ((g_drawFlags & DrawFlags::e_linesFlag) == 0)
{
m_count = 0;
return;
}
glUseProgram(m_programId);
b3Mat44 m1 = g_camera->BuildViewMatrix();
@ -435,7 +444,7 @@ struct DrawTriangles
{
if (m_count == e_vertexCapacity)
{
Submit();
Flush();
}
m_vertices[m_count] = v;
@ -444,12 +453,18 @@ struct DrawTriangles
++m_count;
}
void Submit()
void Flush()
{
if (m_count == 0)
{
return;
}
if ((g_drawFlags & DrawFlags::e_trianglesFlag) == 0)
{
m_count = 0;
return;
}
glUseProgram(m_programId);
@ -631,6 +646,11 @@ struct DrawWire
void DrawSphere(float32 radius, const b3Color& c, const b3Transform& xf)
{
if ((g_drawFlags & DrawFlags::e_linesFlag) == 0)
{
return;
}
glUseProgram(m_programId);
b3Mat44 m1 = MakeMat44(xf);
@ -920,6 +940,11 @@ struct DrawSolid
void DrawCylinder(float32 radius, float32 height, const b3Color& c, const b3Transform& xf)
{
if ((g_drawFlags & DrawFlags::e_trianglesFlag) == 0)
{
return;
}
glUseProgram(m_programId);
b3Mat44 m1 = MakeMat44(xf);
@ -958,6 +983,11 @@ struct DrawSolid
void DrawSphere(float32 radius, const b3Color& c, const b3Transform& xf)
{
if ((g_drawFlags & DrawFlags::e_trianglesFlag) == 0)
{
return;
}
glUseProgram(m_programId);
b3Mat44 m1 = MakeMat44(xf);
@ -1005,494 +1035,4 @@ struct DrawSolid
DrawSolidCylinder m_cylinder;
};
DebugDraw::DebugDraw()
{
m_points = new DrawPoints();
m_lines = new DrawLines();
m_triangles = new DrawTriangles();
m_wire = new DrawWire();
m_solid = new DrawSolid();
}
DebugDraw::~DebugDraw()
{
delete m_points;
delete m_lines;
delete m_triangles;
delete m_wire;
delete m_solid;
}
void DebugDraw::DrawPoint(const b3Vec3& p, float32 size, const b3Color& color)
{
m_points->Vertex(p, size, color);
}
void DebugDraw::DrawSegment(const b3Vec3& p1, const b3Vec3& p2, const b3Color& color)
{
m_lines->Vertex(p1, color);
m_lines->Vertex(p2, color);
}
void DebugDraw::DrawTriangle(const b3Vec3& p1, const b3Vec3& p2, const b3Vec3& p3, const b3Color& color)
{
DrawSegment(p1, p2, color);
DrawSegment(p2, p3, color);
DrawSegment(p3, p1, color);
}
void DebugDraw::DrawSolidTriangle(const b3Vec3& normal, const b3Vec3& p1, const b3Vec3& p2, const b3Vec3& p3, const b3Color& color)
{
m_triangles->Vertex(p1, color, normal);
m_triangles->Vertex(p2, color, normal);
m_triangles->Vertex(p3, color, normal);
b3Color edgeColor(0.0f, 0.0f, 0.0f, 1.0f);
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)
{
m_triangles->Vertex(p1, color1, normal);
m_triangles->Vertex(p2, color2, normal);
m_triangles->Vertex(p3, color3, normal);
b3Color edgeColor(0.0f, 0.0f, 0.0f, 1.0f);
DrawTriangle(p1, p2, p3, edgeColor);
}
void DebugDraw::DrawPolygon(const b3Vec3* vertices, u32 count, const b3Color& color)
{
b3Vec3 p1 = vertices[count - 1];
for (u32 i = 0; i < count; ++i)
{
b3Vec3 p2 = vertices[i];
m_lines->Vertex(p1, color);
m_lines->Vertex(p2, color);
p1 = p2;
}
}
void DebugDraw::DrawSolidPolygon(const b3Vec3& normal, const b3Vec3* vertices, u32 count, const b3Color& color)
{
b3Color fillColor(color.r, color.g, color.b, color.a);
b3Vec3 p1 = vertices[0];
for (u32 i = 1; i < count - 1; ++i)
{
b3Vec3 p2 = vertices[i];
b3Vec3 p3 = vertices[i + 1];
m_triangles->Vertex(p1, fillColor, normal);
m_triangles->Vertex(p2, fillColor, normal);
m_triangles->Vertex(p3, fillColor, normal);
}
b3Color frameColor(0.5f * color.r, 0.5f * color.g, 0.5f * color.b, 1.0f);
DrawPolygon(vertices, count, frameColor);
}
void DebugDraw::DrawCircle(const b3Vec3& normal, const b3Vec3& center, float32 radius, const b3Color& color)
{
// Build a tangent vector to normal.
b3Vec3 u = b3Cross(normal, b3Vec3(1.0f, 0.0f, 0.0f));
b3Vec3 v = b3Cross(normal, b3Vec3(0.0f, 1.0f, 0.0f));
// Handle edge cases (zero cross product).
b3Vec3 n1;
if (b3LengthSquared(u) > b3LengthSquared(v))
{
n1 = u;
}
else
{
n1 = v;
}
n1.Normalize();
// Build a quaternion to rotate the tangent about the normal.
u32 kEdgeCount = 20;
float32 kAngleInc = 2.0f * B3_PI / float32(kEdgeCount);
b3Quat q(normal, kAngleInc);
b3Vec3 p1 = center + radius * n1;
for (u32 i = 0; i < kEdgeCount; ++i)
{
b3Vec3 n2 = b3Mul(q, n1);
b3Vec3 p2 = center + radius * n2;
m_lines->Vertex(p1, color);
m_lines->Vertex(p2, color);
n1 = n2;
p1 = p2;
}
}
void DebugDraw::DrawSolidCircle(const b3Vec3& normal, const b3Vec3& center, float32 radius, const b3Color& color)
{
b3Color fillColor(color.r, color.g, color.b, color.a);
b3Color frameColor(0.5f * color.r, 0.5f * color.g, 0.5f * color.b, 1.0f);
// Build a tangent vector to normal.
b3Vec3 u = b3Cross(normal, b3Vec3(1.0f, 0.0f, 0.0f));
b3Vec3 v = b3Cross(normal, b3Vec3(0.0f, 1.0f, 0.0f));
// Handle edge cases (zero cross product).
b3Vec3 n1;
if (b3LengthSquared(u) > b3LengthSquared(v))
{
n1 = u;
}
else
{
n1 = v;
}
n1.Normalize();
// Build a quaternion to rotate the tangent about the normal.
const u32 kEdgeCount = 20;
const float32 kAngleInc = 2.0f * B3_PI / float32(kEdgeCount);
b3Quat q(normal, kAngleInc);
b3Vec3 p1 = center + radius * n1;
for (u32 i = 0; i < kEdgeCount; ++i)
{
b3Vec3 n2 = b3Mul(q, n1);
b3Vec3 p2 = center + radius * n2;
m_triangles->Vertex(center, fillColor, normal);
m_triangles->Vertex(p1, fillColor, normal);
m_triangles->Vertex(p2, fillColor, normal);
m_lines->Vertex(p1, frameColor);
m_lines->Vertex(p2, frameColor);
n1 = n2;
p1 = p2;
}
}
void DebugDraw::DrawSphere(const b3Vec3& center, float32 radius, const b3Color& color)
{
b3Transform xf;
xf.SetIdentity();
xf.position = center;
m_wire->DrawSphere(radius, color, xf);
}
void DebugDraw::DrawSolidSphere(const b3Vec3& center, float32 radius, const b3Color& color)
{
b3Transform xf;
xf.SetIdentity();
xf.position = center;
m_solid->DrawSphere(radius, color, xf);
}
void DebugDraw::DrawCapsule(const b3Vec3& c1, const b3Vec3& c2, float32 radius, const b3Color& color)
{
float32 height = b3Length(c1 - c2);
{
b3Transform xfc;
xfc.rotation.SetIdentity();
xfc.position = c1;
m_wire->DrawSphere(radius, color, xfc);
}
if (height > 0.0f)
{
DrawSegment(c1, c2, color);
{
b3Transform xfc;
xfc.rotation.SetIdentity();
xfc.position = c2;
m_wire->DrawSphere(radius, color, xfc);
}
}
}
void DebugDraw::DrawSolidCapsule(const b3Vec3& c1, const b3Vec3& c2, float32 radius, const b3Color& c)
{
float32 height = b3Length(c1 - c2);
{
b3Transform xfc;
xfc.rotation.SetIdentity();
xfc.position = c1;
m_solid->DrawSphere(radius, c, xfc);
}
if (height > 0.0f)
{
{
b3Mat33 R;
R.y = (1.0f / height) * (c1 - c2);
R.z = b3Perp(R.y);
R.x = b3Cross(R.y, R.z);
b3Transform xfc;
xfc.position = 0.5f * (c1 + c2);
xfc.rotation = R;
m_solid->DrawCylinder(radius, height, c, xfc);
}
{
b3Transform xfc;
xfc.rotation.SetIdentity();
xfc.position = c2;
m_solid->DrawSphere(radius, c, xfc);
}
}
}
void DebugDraw::DrawTransform(const b3Transform& xf)
{
float32 lenght = 1.0f;
b3Color red(1.0f, 0.0f, 0.0f, 1.0f);
b3Color green(0.0f, 1.0f, 0.0f, 1.0f);
b3Color blue(0.0f, 0.0f, 1.0f, 1.0f);
b3Vec3 position = xf.position;
b3Mat33 rotation = xf.rotation;
b3Vec3 A = position + lenght * rotation.x;
b3Vec3 B = position + lenght * rotation.y;
b3Vec3 C = position + lenght * rotation.z;
DrawSegment(position, A, red);
DrawSegment(position, B, green);
DrawSegment(position, C, blue);
}
void DebugDraw::DrawAABB(const b3AABB3& aabb, const b3Color& color)
{
b3Vec3 lower = aabb.m_lower;
b3Vec3 upper = aabb.m_upper;
b3Vec3 vs[8];
vs[0] = lower;
vs[1] = b3Vec3(lower.x, upper.y, lower.z);
vs[2] = b3Vec3(upper.x, upper.y, lower.z);
vs[3] = b3Vec3(upper.x, lower.y, lower.z);
vs[4] = upper;
vs[5] = b3Vec3(upper.x, lower.y, upper.z);
vs[6] = b3Vec3(lower.x, lower.y, upper.z);
vs[7] = b3Vec3(lower.x, upper.y, upper.z);
DrawSegment(vs[0], vs[1], color);
DrawSegment(vs[1], vs[2], color);
DrawSegment(vs[2], vs[3], color);
DrawSegment(vs[3], vs[0], color);
DrawSegment(vs[4], vs[5], color);
DrawSegment(vs[5], vs[6], color);
DrawSegment(vs[6], vs[7], color);
DrawSegment(vs[7], vs[4], color);
DrawSegment(vs[2], vs[4], color);
DrawSegment(vs[5], vs[3], color);
DrawSegment(vs[6], vs[0], color);
DrawSegment(vs[1], vs[7], color);
}
void DebugDraw::DrawString(const b3Color& color, const char* text, ...)
{
va_list args;
va_start(args, text);
ImGui::SetNextWindowPos(ImVec2(0.0f, 40.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(args);
}
void DebugDraw::DrawSphere(const b3SphereShape* s, const b3Color& c, const b3Transform& xf)
{
b3Transform xfc;
xfc.rotation = xf.rotation;
xfc.position = xf * s->m_center;
m_solid->DrawSphere(s->m_radius, c, xfc);
}
void DebugDraw::DrawCapsule(const b3CapsuleShape* s, const b3Color& c, const b3Transform& xf)
{
b3Vec3 c1 = s->m_centers[0];
b3Vec3 c2 = s->m_centers[1];
float32 height = b3Length(c1 - c2);
float32 radius = s->m_radius;
{
b3Transform xfc;
xfc.rotation = xf.rotation;
xfc.position = xf * c1;
m_solid->DrawSphere(radius, c, xfc);
}
if (height > 0.0f)
{
{
b3Mat33 R;
R.y = (1.0f / height) * (c1 - c2);
R.z = b3Perp(R.y);
R.x = b3Cross(R.y, R.z);
b3Transform xfc;
xfc.position = xf * (0.5f * (c1 + c2));
xfc.rotation = xf.rotation * R;
m_solid->DrawCylinder(radius, height, c, xfc);
}
{
b3Transform xfc;
xfc.rotation = xf.rotation;
xfc.position = xf * c2;
m_solid->DrawSphere(radius, c, xfc);
}
}
}
void DebugDraw::DrawHull(const b3HullShape* s, const b3Color& c, const b3Transform& xf)
{
const b3Hull* hull = s->m_hull;
for (u32 i = 0; i < hull->faceCount; ++i)
{
const b3Face* face = hull->GetFace(i);
const b3HalfEdge* begin = hull->GetEdge(face->edge);
b3Vec3 n = xf.rotation * hull->planes[i].normal;
const b3HalfEdge* edge = hull->GetEdge(begin->next);
do
{
u32 i1 = begin->origin;
u32 i2 = edge->origin;
const b3HalfEdge* next = hull->GetEdge(edge->next);
u32 i3 = next->origin;
b3Vec3 p1 = xf * hull->vertices[i1];
b3Vec3 p2 = xf * hull->vertices[i2];
b3Vec3 p3 = xf * hull->vertices[i3];
m_triangles->Vertex(p1, c, n);
m_triangles->Vertex(p2, c, n);
m_triangles->Vertex(p3, c, n);
edge = next;
} while (hull->GetEdge(edge->next) != begin);
}
}
void DebugDraw::DrawMesh(const b3MeshShape* s, const b3Color& c, const b3Transform& xf)
{
const b3Mesh* mesh = s->m_mesh;
for (u32 i = 0; i < mesh->triangleCount; ++i)
{
const b3Triangle* t = mesh->triangles + i;
b3Vec3 p1 = xf * mesh->vertices[t->v1];
b3Vec3 p2 = xf * mesh->vertices[t->v2];
b3Vec3 p3 = xf * mesh->vertices[t->v3];
b3Vec3 n1 = b3Cross(p2 - p1, p3 - p1);
n1.Normalize();
m_triangles->Vertex(p1, c, n1);
m_triangles->Vertex(p2, c, n1);
m_triangles->Vertex(p3, c, n1);
b3Vec3 n2 = -n1;
m_triangles->Vertex(p1, c, n2);
m_triangles->Vertex(p3, c, n2);
m_triangles->Vertex(p2, c, n2);
}
}
void DebugDraw::DrawShape(const b3Shape* s, const b3Color& c, const b3Transform& xf)
{
switch (s->GetType())
{
case e_sphereShape:
{
DrawSphere((b3SphereShape*)s, c, xf);
break;
}
case e_capsuleShape:
{
DrawCapsule((b3CapsuleShape*)s, c, xf);
break;
}
case e_hullShape:
{
DrawHull((b3HullShape*)s, c, xf);
break;
}
case e_meshShape:
{
DrawMesh((b3MeshShape*)s, c, xf);
break;
}
default:
{
break;
}
}
}
void DebugDraw::Draw(const b3World& world)
{
for (b3Body* b = world.GetBodyList().m_head; b; b = b->GetNext())
{
b3Color c;
if (b->IsAwake() == false)
{
c = b3Color(0.5f, 0.25f, 0.25f, 1.0f);
}
else if (b->GetType() == e_staticBody)
{
c = b3Color(0.5f, 0.5f, 0.5f, 1.0f);
}
else if (b->GetType() == e_dynamicBody)
{
c = b3Color(1.0f, 0.5f, 0.5f, 1.0f);
}
else
{
c = b3Color(0.5f, 0.5f, 1.0f, 1.0f);
}
b3Transform xf = b->GetTransform();
for (b3Shape* s = b->GetShapeList().m_head; s; s = s->GetNext())
{
DrawShape(s, c, xf);
}
}
g_debugDraw->Submit();
}
void DebugDraw::Submit()
{
m_triangles->Submit();
m_lines->Submit();
m_points->Submit();
}
#endif

View File

@ -16,19 +16,13 @@
* 3. This notice may not be removed or altered from any source distribution.
*/
#include <testbed/framework/debug_draw.h>
#include <testbed/framework/draw.h>
#include <glad_4/glad.h>
#include <imgui/imgui.h>
#include <stdio.h>
#include <stdarg.h>
//
DebugDraw* g_debugDraw = nullptr;
Camera* g_camera = nullptr;
const char* g_overlayName = nullptr;
#define BUFFER_OFFSET(i) ((char*)NULL + (i))
static void AssertGL()
@ -190,7 +184,7 @@ struct DrawPoints
{
if (m_count == e_vertexCapacity)
{
Submit();
Flush();
}
m_vertices[m_count] = v;
@ -199,12 +193,18 @@ struct DrawPoints
++m_count;
}
void Submit()
void Flush()
{
if (m_count == 0)
{
return;
}
if ((g_drawFlags & DrawFlags::e_pointsFlag) == 0)
{
m_count = 0;
return;
}
glUseProgram(m_programId);
@ -322,7 +322,7 @@ struct DrawLines
{
if (m_count == e_vertexCapacity)
{
Submit();
Flush();
}
m_vertices[m_count] = v;
@ -330,12 +330,18 @@ struct DrawLines
++m_count;
}
void Submit()
void Flush()
{
if (m_count == 0)
{
return;
}
if ((g_drawFlags & DrawFlags::e_linesFlag) == 0)
{
m_count = 0;
return;
}
glUseProgram(m_programId);
@ -459,7 +465,7 @@ struct DrawTriangles
{
if (m_count == e_vertexCapacity)
{
Submit();
Flush();
}
m_vertices[m_count] = v;
@ -468,13 +474,19 @@ struct DrawTriangles
++m_count;
}
void Submit()
void Flush()
{
if (m_count == 0)
{
return;
}
if ((g_drawFlags & DrawFlags::e_trianglesFlag) == 0)
{
m_count = 0;
return;
}
glUseProgram(m_programId);
b3Mat44 m1 = g_camera->BuildViewMatrix();
@ -648,6 +660,11 @@ struct DrawWire
void DrawSphere(float32 radius, const b3Color& c, const b3Transform& xf)
{
if ((g_drawFlags & DrawFlags::e_linesFlag) == 0)
{
return;
}
glUseProgram(m_programId);
b3Mat44 m1 = MakeMat44(xf);
@ -936,6 +953,11 @@ struct DrawSolid
void DrawCylinder(float32 radius, float32 height, const b3Color& c, const b3Transform& xf)
{
if ((g_drawFlags & DrawFlags::e_trianglesFlag) == 0)
{
return;
}
glUseProgram(m_programId);
b3Mat44 m1 = MakeMat44(xf);
@ -970,6 +992,11 @@ struct DrawSolid
void DrawSphere(float32 radius, const b3Color& c, const b3Transform& xf)
{
if ((g_drawFlags & DrawFlags::e_trianglesFlag) == 0)
{
return;
}
glUseProgram(m_programId);
b3Mat44 m1 = MakeMat44(xf);
@ -1011,496 +1038,4 @@ struct DrawSolid
DrawSolidSphere m_sphere;
DrawSolidCylinder m_cylinder;
};
DebugDraw::DebugDraw()
{
m_points = new DrawPoints();
m_lines = new DrawLines();
m_triangles = new DrawTriangles();
m_wire = new DrawWire();
m_solid = new DrawSolid();
}
DebugDraw::~DebugDraw()
{
delete m_points;
delete m_lines;
delete m_triangles;
delete m_wire;
delete m_solid;
}
void DebugDraw::DrawPoint(const b3Vec3& p, float32 size, const b3Color& color)
{
m_points->Vertex(p, size, color);
}
void DebugDraw::DrawSegment(const b3Vec3& p1, const b3Vec3& p2, const b3Color& color)
{
m_lines->Vertex(p1, color);
m_lines->Vertex(p2, color);
}
void DebugDraw::DrawTriangle(const b3Vec3& p1, const b3Vec3& p2, const b3Vec3& p3, const b3Color& color)
{
DrawSegment(p1, p2, color);
DrawSegment(p2, p3, color);
DrawSegment(p3, p1, color);
}
void DebugDraw::DrawSolidTriangle(const b3Vec3& normal, const b3Vec3& p1, const b3Vec3& p2, const b3Vec3& p3, const b3Color& color)
{
m_triangles->Vertex(p1, color, normal);
m_triangles->Vertex(p2, color, normal);
m_triangles->Vertex(p3, color, normal);
b3Color edgeColor(0.0f, 0.0f, 0.0f, 1.0f);
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)
{
m_triangles->Vertex(p1, color1, normal);
m_triangles->Vertex(p2, color2, normal);
m_triangles->Vertex(p3, color3, normal);
b3Color edgeColor(0.0f, 0.0f, 0.0f, 1.0f);
DrawTriangle(p1, p2, p3, edgeColor);
}
void DebugDraw::DrawPolygon(const b3Vec3* vertices, u32 count, const b3Color& color)
{
b3Vec3 p1 = vertices[count - 1];
for (u32 i = 0; i < count; ++i)
{
b3Vec3 p2 = vertices[i];
m_lines->Vertex(p1, color);
m_lines->Vertex(p2, color);
p1 = p2;
}
}
void DebugDraw::DrawSolidPolygon(const b3Vec3& normal, const b3Vec3* vertices, u32 count, const b3Color& color)
{
b3Color fillColor(color.r, color.g, color.b, color.a);
b3Vec3 p1 = vertices[0];
for (u32 i = 1; i < count - 1; ++i)
{
b3Vec3 p2 = vertices[i];
b3Vec3 p3 = vertices[i + 1];
m_triangles->Vertex(p1, fillColor, normal);
m_triangles->Vertex(p2, fillColor, normal);
m_triangles->Vertex(p3, fillColor, normal);
}
b3Color frameColor(0.5f * color.r, 0.5f * color.g, 0.5f * color.b, 1.0f);
DrawPolygon(vertices, count, frameColor);
}
void DebugDraw::DrawCircle(const b3Vec3& normal, const b3Vec3& center, float32 radius, const b3Color& color)
{
// Build a tangent vector to normal.
b3Vec3 u = b3Cross(normal, b3Vec3(1.0f, 0.0f, 0.0f));
b3Vec3 v = b3Cross(normal, b3Vec3(0.0f, 1.0f, 0.0f));
// Handle edge cases (zero cross product).
b3Vec3 n1;
if (b3LengthSquared(u) > b3LengthSquared(v))
{
n1 = u;
}
else
{
n1 = v;
}
n1.Normalize();
// Build a quaternion to rotate the tangent about the normal.
u32 kEdgeCount = 20;
float32 kAngleInc = 2.0f * B3_PI / float32(kEdgeCount);
b3Quat q(normal, kAngleInc);
b3Vec3 p1 = center + radius * n1;
for (u32 i = 0; i < kEdgeCount; ++i)
{
b3Vec3 n2 = b3Mul(q, n1);
b3Vec3 p2 = center + radius * n2;
m_lines->Vertex(p1, color);
m_lines->Vertex(p2, color);
n1 = n2;
p1 = p2;
}
}
void DebugDraw::DrawSolidCircle(const b3Vec3& normal, const b3Vec3& center, float32 radius, const b3Color& color)
{
b3Color fillColor(color.r, color.g, color.b, color.a);
b3Color frameColor(0.5f * color.r, 0.5f * color.g, 0.5f * color.b, 1.0f);
// Build a tangent vector to normal.
b3Vec3 u = b3Cross(normal, b3Vec3(1.0f, 0.0f, 0.0f));
b3Vec3 v = b3Cross(normal, b3Vec3(0.0f, 1.0f, 0.0f));
// Handle edge cases (zero cross product).
b3Vec3 n1;
if (b3LengthSquared(u) > b3LengthSquared(v))
{
n1 = u;
}
else
{
n1 = v;
}
n1.Normalize();
// Build a quaternion to rotate the tangent about the normal.
const u32 kEdgeCount = 20;
const float32 kAngleInc = 2.0f * B3_PI / float32(kEdgeCount);
b3Quat q(normal, kAngleInc);
b3Vec3 p1 = center + radius * n1;
for (u32 i = 0; i < kEdgeCount; ++i)
{
b3Vec3 n2 = b3Mul(q, n1);
b3Vec3 p2 = center + radius * n2;
m_triangles->Vertex(center, fillColor, normal);
m_triangles->Vertex(p1, fillColor, normal);
m_triangles->Vertex(p2, fillColor, normal);
m_lines->Vertex(p1, frameColor);
m_lines->Vertex(p2, frameColor);
n1 = n2;
p1 = p2;
}
}
void DebugDraw::DrawSphere(const b3Vec3& center, float32 radius, const b3Color& color)
{
b3Transform xf;
xf.SetIdentity();
xf.position = center;
m_wire->DrawSphere(radius, color, xf);
}
void DebugDraw::DrawSolidSphere(const b3Vec3& center, float32 radius, const b3Color& color)
{
b3Transform xf;
xf.SetIdentity();
xf.position = center;
m_solid->DrawSphere(radius, color, xf);
}
void DebugDraw::DrawCapsule(const b3Vec3& c1, const b3Vec3& c2, float32 radius, const b3Color& color)
{
float32 height = b3Length(c1 - c2);
{
b3Transform xfc;
xfc.rotation.SetIdentity();
xfc.position = c1;
m_wire->DrawSphere(radius, color, xfc);
}
if (height > 0.0f)
{
DrawSegment(c1, c2, color);
{
b3Transform xfc;
xfc.rotation.SetIdentity();
xfc.position = c2;
m_wire->DrawSphere(radius, color, xfc);
}
}
}
void DebugDraw::DrawSolidCapsule(const b3Vec3& c1, const b3Vec3& c2, float32 radius, const b3Color& c)
{
float32 height = b3Length(c1 - c2);
{
b3Transform xfc;
xfc.rotation.SetIdentity();
xfc.position = c1;
m_solid->DrawSphere(radius, c, xfc);
}
if (height > 0.0f)
{
{
b3Mat33 R;
R.y = (1.0f / height) * (c1 - c2);
R.z = b3Perp(R.y);
R.x = b3Cross(R.y, R.z);
b3Transform xfc;
xfc.position = 0.5f * (c1 + c2);
xfc.rotation = R;
m_solid->DrawCylinder(radius, height, c, xfc);
}
{
b3Transform xfc;
xfc.rotation.SetIdentity();
xfc.position = c2;
m_solid->DrawSphere(radius, c, xfc);
}
}
}
void DebugDraw::DrawTransform(const b3Transform& xf)
{
float32 lenght = 1.0f;
b3Color red(1.0f, 0.0f, 0.0f, 1.0f);
b3Color green(0.0f, 1.0f, 0.0f, 1.0f);
b3Color blue(0.0f, 0.0f, 1.0f, 1.0f);
b3Vec3 position = xf.position;
b3Mat33 rotation = xf.rotation;
b3Vec3 A = position + lenght * rotation.x;
b3Vec3 B = position + lenght * rotation.y;
b3Vec3 C = position + lenght * rotation.z;
DrawSegment(position, A, red);
DrawSegment(position, B, green);
DrawSegment(position, C, blue);
}
void DebugDraw::DrawAABB(const b3AABB3& aabb, const b3Color& color)
{
b3Vec3 lower = aabb.m_lower;
b3Vec3 upper = aabb.m_upper;
b3Vec3 vs[8];
vs[0] = lower;
vs[1] = b3Vec3(lower.x, upper.y, lower.z);
vs[2] = b3Vec3(upper.x, upper.y, lower.z);
vs[3] = b3Vec3(upper.x, lower.y, lower.z);
vs[4] = upper;
vs[5] = b3Vec3(upper.x, lower.y, upper.z);
vs[6] = b3Vec3(lower.x, lower.y, upper.z);
vs[7] = b3Vec3(lower.x, upper.y, upper.z);
DrawSegment(vs[0], vs[1], color);
DrawSegment(vs[1], vs[2], color);
DrawSegment(vs[2], vs[3], color);
DrawSegment(vs[3], vs[0], color);
DrawSegment(vs[4], vs[5], color);
DrawSegment(vs[5], vs[6], color);
DrawSegment(vs[6], vs[7], color);
DrawSegment(vs[7], vs[4], color);
DrawSegment(vs[2], vs[4], color);
DrawSegment(vs[5], vs[3], color);
DrawSegment(vs[6], vs[0], color);
DrawSegment(vs[1], vs[7], color);
}
void DebugDraw::DrawString(const b3Color& color, const char* text, ...)
{
va_list args;
va_start(args, text);
ImGui::SetNextWindowPos(ImVec2(0.0f, 40.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(args);
}
void DebugDraw::DrawSphere(const b3SphereShape* s, const b3Color& c, const b3Transform& xf)
{
b3Transform xfc;
xfc.rotation = xf.rotation;
xfc.position = xf * s->m_center;
m_solid->DrawSphere(s->m_radius, c, xfc);
}
void DebugDraw::DrawCapsule(const b3CapsuleShape* s, const b3Color& c, const b3Transform& xf)
{
b3Vec3 c1 = s->m_centers[0];
b3Vec3 c2 = s->m_centers[1];
float32 height = b3Length(c1 - c2);
float32 radius = s->m_radius;
{
b3Transform xfc;
xfc.rotation = xf.rotation;
xfc.position = xf * c1;
m_solid->DrawSphere(radius, c, xfc);
}
if (height > 0.0f)
{
{
b3Mat33 R;
R.y = (1.0f / height) * (c1 - c2);
R.z = b3Perp(R.y);
R.x = b3Cross(R.y, R.z);
b3Transform xfc;
xfc.position = xf * (0.5f * (c1 + c2));
xfc.rotation = xf.rotation * R;
m_solid->DrawCylinder(radius, height, c, xfc);
}
{
b3Transform xfc;
xfc.rotation = xf.rotation;
xfc.position = xf * c2;
m_solid->DrawSphere(radius, c, xfc);
}
}
}
void DebugDraw::DrawHull(const b3HullShape* s, const b3Color& c, const b3Transform& xf)
{
const b3Hull* hull = s->m_hull;
for (u32 i = 0; i < hull->faceCount; ++i)
{
const b3Face* face = hull->GetFace(i);
const b3HalfEdge* begin = hull->GetEdge(face->edge);
b3Vec3 n = xf.rotation * hull->planes[i].normal;
const b3HalfEdge* edge = hull->GetEdge(begin->next);
do
{
u32 i1 = begin->origin;
u32 i2 = edge->origin;
const b3HalfEdge* next = hull->GetEdge(edge->next);
u32 i3 = next->origin;
b3Vec3 p1 = xf * hull->vertices[i1];
b3Vec3 p2 = xf * hull->vertices[i2];
b3Vec3 p3 = xf * hull->vertices[i3];
m_triangles->Vertex(p1, c, n);
m_triangles->Vertex(p2, c, n);
m_triangles->Vertex(p3, c, n);
edge = next;
} while (hull->GetEdge(edge->next) != begin);
}
}
void DebugDraw::DrawMesh(const b3MeshShape* s, const b3Color& c, const b3Transform& xf)
{
const b3Mesh* mesh = s->m_mesh;
for (u32 i = 0; i < mesh->triangleCount; ++i)
{
const b3Triangle* t = mesh->triangles + i;
b3Vec3 p1 = xf * mesh->vertices[t->v1];
b3Vec3 p2 = xf * mesh->vertices[t->v2];
b3Vec3 p3 = xf * mesh->vertices[t->v3];
b3Vec3 n1 = b3Cross(p2 - p1, p3 - p1);
n1.Normalize();
m_triangles->Vertex(p1, c, n1);
m_triangles->Vertex(p2, c, n1);
m_triangles->Vertex(p3, c, n1);
b3Vec3 n2 = -n1;
m_triangles->Vertex(p1, c, n2);
m_triangles->Vertex(p3, c, n2);
m_triangles->Vertex(p2, c, n2);
}
}
void DebugDraw::DrawShape(const b3Shape* s, const b3Color& c, const b3Transform& xf)
{
switch (s->GetType())
{
case e_sphereShape:
{
DrawSphere((b3SphereShape*)s, c, xf);
break;
}
case e_capsuleShape:
{
DrawCapsule((b3CapsuleShape*)s, c, xf);
break;
}
case e_hullShape:
{
DrawHull((b3HullShape*)s, c, xf);
break;
}
case e_meshShape:
{
DrawMesh((b3MeshShape*)s, c, xf);
break;
}
default:
{
break;
}
}
}
void DebugDraw::Draw(const b3World& world)
{
for (b3Body* b = world.GetBodyList().m_head; b; b = b->GetNext())
{
b3Color c;
if (b->IsAwake() == false)
{
c = b3Color(0.5f, 0.25f, 0.25f, 1.0f);
}
else if (b->GetType() == e_staticBody)
{
c = b3Color(0.5f, 0.5f, 0.5f, 1.0f);
}
else if (b->GetType() == e_dynamicBody)
{
c = b3Color(1.0f, 0.5f, 0.5f, 1.0f);
}
else
{
c = b3Color(0.5f, 0.5f, 1.0f, 1.0f);
}
b3Transform xf = b->GetTransform();
for (b3Shape* s = b->GetShapeList().m_head; s; s = s->GetNext())
{
DrawShape(s, c, xf);
}
}
g_debugDraw->Submit();
}
void DebugDraw::Submit()
{
m_triangles->Submit();
m_lines->Submit();
m_points->Submit();
}
};

View File

@ -99,27 +99,34 @@ static void Run()
int w, h;
glfwGetWindowSize(g_window, &w, &h);
g_controller->Event_SetWindowSize(u32(w), u32(h));
double frameTime = 0.0;
while (glfwWindowShouldClose(g_window) == 0)
{
double time1 = glfwGetTime();
g_profiler->Begin();
g_profiler->PushEvent("Frame");
g_view->Command_PreDraw();
g_view->Command_Draw();
if (g_settings->drawProfile)
{
const b3Array<ProfilerRecord>& records = g_profilerRecorder->GetRecords();
for (u32 i = 0; i < records.Count(); ++i)
{
const ProfilerRecord& r = records[i];
g_draw->DrawString(b3Color_white, "%s %.4f (%.4f) [ms]", r.name, r.elapsed, r.maxElapsed);
}
}
g_debugDraw->DrawString(b3Color_yellow, "%.2f [ms]", 1000.0 * frameTime);
g_view->Command_Draw();
g_model->Command_Step();
g_view->Command_PostDraw();
double time2 = glfwGetTime();
g_profiler->PopEvent();
double fraction = 0.9;
frameTime = fraction * frameTime + (1.0 - fraction) * (time2 - time1);
g_profiler->End(g_profilerListener);
glfwSwapBuffers(g_window);
glfwPollEvents();

View File

@ -20,12 +20,13 @@
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;
g_testSettings = &m_testSettings;
g_draw = &m_draw;
g_camera = &m_camera;
g_profiler = &m_profiler;
g_profilerRecorder = &m_profilerListener.m_recorderProfiler;
g_profilerListener = &m_profilerListener;
m_test = nullptr;
@ -44,38 +45,44 @@ Model::Model()
Model::~Model()
{
g_debugDraw = nullptr;
g_testSettings = nullptr;
g_draw = nullptr;
g_camera = nullptr;
g_overlayName = nullptr;
g_profiler = nullptr;
g_profilerRecorder = nullptr;
g_profilerListener = nullptr;
g_settings = nullptr;
g_testSettings = nullptr;
delete m_test;
}
void Model::Command_Step()
{
g_drawFlags = 0;
g_drawFlags += m_settings.drawPoints * DrawFlags::e_pointsFlag;
g_drawFlags += m_settings.drawLines * DrawFlags::e_linesFlag;
g_drawFlags += m_settings.drawTriangles * DrawFlags::e_trianglesFlag;
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.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;
Action_DefaultCamera();
}
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*");
m_draw.DrawString(b3Color_white, "*PAUSED*");
}
else
{
m_debugDraw.DrawString(b3Color_white, "*PLAYING*");
m_draw.DrawString(b3Color_white, "*PLAYING*");
}
if (m_settings.drawGrid)
@ -84,7 +91,7 @@ void Model::Command_Step()
b3Vec3 pn(0.0f, 1.0f, 0.0f);
b3Vec3 p(0.0f, 0.0f, 0.0f);
m_debugDraw.DrawCircle(pn, p, 1.0f, color);
m_draw.DrawCircle(pn, p, 1.0f, color);
int n = 20;
@ -108,13 +115,13 @@ void Model::Command_Step()
vs[2] += t;
vs[3] += t;
m_debugDraw.DrawPolygon(vs, 4, color);
m_draw.DrawPolygon(vs, 4, color);
}
}
}
//
m_settings.inv_hertz = m_settings.hertz != 0.0f ? 1.0f / m_settings.hertz : 0.0f;
m_testSettings.inv_hertz = m_testSettings.hertz != 0.0f ? 1.0f / m_testSettings.hertz : 0.0f;
if (m_settings.pause)
{
@ -124,25 +131,11 @@ void Model::Command_Step()
}
else
{
m_settings.inv_hertz = 0.0f;
m_testSettings.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();
m_draw.Flush();
}

View File

@ -19,10 +19,43 @@
#ifndef MODEL_H
#define MODEL_H
#include <testbed/framework/debug_draw.h>
#include <testbed/framework/draw.h>
#include <testbed/framework/testbed_listener.h>
#include <testbed/framework/test.h>
struct Settings
{
Settings()
{
lastTestID = -1;
testID = 0;
pause = false;
singleStep = false;
drawPoints = true;
drawLines = true;
drawTriangles = true;
drawGrid = true;
drawProfile = false;
drawStats = false;
}
int lastTestID;
int testID;
bool pause;
bool singleStep;
bool drawPoints;
bool drawLines;
bool drawTriangles;
bool drawGrid;
bool drawProfile;
bool drawStats;
};
//
extern Settings* g_settings;
class Model
{
public:
@ -62,12 +95,15 @@ private:
friend class View;
friend class Controller;
DebugDraw m_debugDraw;
// UI State
Settings m_settings;
TestSettings m_testSettings;
// App State
Draw m_draw;
Camera m_camera;
Profiler m_profiler;
TestbedListener m_profilerListener;
Settings m_settings;
Test* m_test;
};

View File

@ -18,6 +18,8 @@
#include <testbed/framework/recorder_profiler.h>
RecorderProfiler* g_profilerRecorder = nullptr;
void RecorderProfiler::BeginEvents()
{
for (u32 i = 0; i < m_records.Count(); ++i)

View File

@ -47,4 +47,6 @@ private:
b3StackArray<ProfilerRecord, 256> m_records;
};
extern RecorderProfiler* g_profilerRecorder;
#endif

View File

@ -17,6 +17,7 @@
*/
#include <testbed/framework/test.h>
#include <testbed/framework/model.h>
extern u32 b3_allocCalls, b3_maxAllocCalls;
extern u32 b3_gjkCalls, b3_gjkIters, b3_gjkMaxIters;
@ -34,22 +35,24 @@ void b3PopProfileScope()
}
Settings* g_settings = nullptr;
TestSettings* g_testSettings = nullptr;
Test::Test()
Test::Test() : m_bodyDragger(&m_bodyRay, &m_world)
{
b3_allocCalls = 0;
b3_gjkCalls = 0;
b3_gjkIters = 0;
b3_gjkMaxIters = 0;
b3_convexCache = g_settings->convexCache;
b3_convexCache = g_testSettings->convexCache;
b3_convexCalls = 0;
b3_convexCacheHits = 0;
b3Draw_draw = g_debugDraw;
b3Draw_draw = g_draw;
m_world.SetContactListener(this);
m_rayHit.shape = NULL;
m_mouseJoint = NULL;
m_bodyRay.origin.SetZero();
m_bodyRay.direction.Set(0.0f, 0.0f, -1.0f);
m_bodyRay.fraction = g_camera->m_zFar;
m_groundHull.Set(50.0f, 1.0f, 50.0f);
m_groundMesh.BuildTree();
@ -73,57 +76,44 @@ void Test::Step()
b3_gjkCalls = 0;
b3_gjkIters = 0;
b3_gjkMaxIters = 0;
b3_convexCache = g_settings->convexCache;
b3_convexCache = g_testSettings->convexCache;
b3_convexCalls = 0;
b3_convexCacheHits = 0;
float32 dt = g_settings->inv_hertz;
// Step
m_world.SetSleeping(g_settings->sleep);
m_world.SetWarmStart(g_settings->warmStart);
m_world.Step(dt, g_settings->velocityIterations, g_settings->positionIterations);
float32 dt = g_testSettings->inv_hertz;
g_debugDraw->Submit();
m_world.SetSleeping(g_testSettings->sleep);
m_world.SetWarmStart(g_testSettings->warmStart);
m_world.Step(dt, g_testSettings->velocityIterations, g_testSettings->positionIterations);
// Draw World
// Draw
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_testSettings->drawBounds * b3Draw::e_aabbsFlag;
drawFlags += g_testSettings->drawShapes * b3Draw::e_shapesFlag;
drawFlags += g_testSettings->drawCenterOfMasses * b3Draw::e_centerOfMassesFlag;
drawFlags += g_testSettings->drawJoints * b3Draw::e_jointsFlag;
drawFlags += g_testSettings->drawContactPoints * b3Draw::e_contactPointsFlag;
drawFlags += g_testSettings->drawContactNormals * b3Draw::e_contactNormalsFlag;
drawFlags += g_testSettings->drawContactTangents * b3Draw::e_contactTangentsFlag;
drawFlags += g_testSettings->drawContactPolygons * b3Draw::e_contactPolygonsFlag;
g_debugDraw->SetFlags(drawFlags);
g_draw->SetFlags(drawFlags);
m_world.Draw();
if (m_mouseJoint)
{
b3Shape* shape = m_rayHit.shape;
b3Body* body = shape->GetBody();
b3Vec3 n = body->GetWorldVector(m_rayHit.normal);
b3Vec3 p = body->GetWorldPoint(m_rayHit.point);
g_debugDraw->DrawSolidCircle(n, p + 0.05f * n, 1.0f, b3Color_white);
}
g_draw->Flush();
g_debugDraw->Submit();
if (g_settings->drawFaces)
if (g_settings->drawTriangles)
{
g_debugDraw->Draw(m_world);
g_draw->DrawSolidShapes(m_world);
}
if (g_settings->drawStats)
{
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);
g_draw->DrawString(b3Color_white, "Bodies %d", m_world.GetBodyList().m_count);
g_draw->DrawString(b3Color_white, "Joints %d", m_world.GetJointList().m_count);
g_draw->DrawString(b3Color_white, "Contacts %d", m_world.GetContactList().m_count);
float32 avgGjkIters = 0.0f;
if (b3_gjkCalls > 0)
@ -131,8 +121,8 @@ void Test::Step()
avgGjkIters = float32(b3_gjkIters) / float32(b3_gjkCalls);
}
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);
g_draw->DrawString(b3Color_white, "GJK Calls %d", b3_gjkCalls);
g_draw->DrawString(b3Color_white, "GJK Iterations %d (%d) (%f)", b3_gjkIters, b3_gjkMaxIters, avgGjkIters);
float32 convexCacheHitRatio = 0.0f;
if (b3_convexCalls > 0)
@ -140,84 +130,39 @@ void Test::Step()
convexCacheHitRatio = float32(b3_convexCacheHits) / float32(b3_convexCalls);
}
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);
g_draw->DrawString(b3Color_white, "Convex Calls %d", b3_convexCalls);
g_draw->DrawString(b3Color_white, "Convex Cache Hits %d (%f)", b3_convexCacheHits, convexCacheHitRatio);
g_draw->DrawString(b3Color_white, "Frame Allocations %d (%d)", b3_allocCalls, b3_maxAllocCalls);
}
}
void Test::MouseMove(const Ray3& pw)
{
if (m_mouseJoint)
{
float32 t = m_rayHit.fraction;
float32 w1 = 1.0f - t;
float32 w2 = t;
m_bodyRay = pw;
b3Vec3 target = w1 * pw.A() + w2 * pw.B();
m_mouseJoint->SetTarget(target);
if (m_bodyDragger.IsSelected() == true)
{
m_bodyDragger.Drag();
}
}
void Test::MouseLeftDown(const Ray3& pw)
{
// Clear the current hit
m_rayHit.shape = NULL;
if (m_mouseJoint)
if (m_bodyDragger.IsSelected() == false)
{
b3Body* groundBody = m_mouseJoint->GetBodyA();
m_world.DestroyJoint(m_mouseJoint);
m_mouseJoint = NULL;
m_world.DestroyBody(groundBody);
}
// Perform the ray cast
b3Vec3 p1 = pw.A();
b3Vec3 p2 = pw.B();
b3RayCastSingleOutput out;
if (m_world.RayCastSingle(&out, p1, p2))
{
b3Shape* shape = out.shape;
b3Body* body = shape->GetBody();
m_rayHit.shape = out.shape;
m_rayHit.point = body->GetLocalPoint(out.point);
m_rayHit.normal = body->GetLocalVector(out.normal);
m_rayHit.fraction = out.fraction;
RayHit();
if (m_bodyDragger.StartDragging() == true)
{
BeginDragging();
}
}
}
void Test::MouseLeftUp(const Ray3& pw)
{
m_rayHit.shape = NULL;
if (m_mouseJoint)
if (m_bodyDragger.IsSelected() == true)
{
b3Body* groundBody = m_mouseJoint->GetBodyA();
m_world.DestroyJoint(m_mouseJoint);
m_mouseJoint = NULL;
m_world.DestroyBody(groundBody);
m_bodyDragger.StopDragging();
EndDragging();
}
}
void Test::RayHit()
{
b3BodyDef bdef;
b3Body* bodyA = m_world.CreateBody(bdef);
b3Body* bodyB = m_rayHit.shape->GetBody();
b3MouseJointDef def;
def.bodyA = bodyA;
def.bodyB = bodyB;
def.target = bodyB->GetWorldPoint(m_rayHit.point);
def.maxForce = 2000.0f * bodyB->GetMass();
m_mouseJoint = (b3MouseJoint*)m_world.CreateJoint(def);
bodyB->SetAwake(true);
}
}

View File

@ -24,7 +24,7 @@
#include <bounce/bounce.h>
#include <testbed/framework/debug_draw.h>
#include <testbed/framework/draw.h>
#include <testbed/framework/profiler.h>
#include <testbed/framework/recorder_profiler.h>
@ -36,10 +36,9 @@ inline float32 RandomFloat(float32 a, float32 b)
return a + r;
}
// Test settings
struct Settings
struct TestSettings
{
Settings()
TestSettings()
{
hertz = 60.0f;
inv_hertz = 1.0f / hertz;
@ -48,52 +47,34 @@ struct Settings
sleep = false;
warmStart = true;
convexCache = true;
drawCenterOfMasses = false;
drawVerticesEdges = true;
drawFaces = true;
drawCenterOfMasses = true;
drawShapes = true;
drawBounds = false;
drawJoints = true;
drawContactPoints = true;
drawContactNormals = false;
drawContactTangents = false;
drawContactPolygons = false;
drawStats = false;
drawProfile = false;
drawGrid = true;
pause = false;
singleStep = false;
lastTestID = -1;
testID = 0;
}
int lastTestID;
int testID;
bool pause;
bool singleStep;
float32 hertz, inv_hertz;
float hertz, inv_hertz;
int velocityIterations;
int positionIterations;
bool sleep;
bool warmStart;
bool convexCache;
bool drawCenterOfMasses;
bool drawBounds;
bool drawVerticesEdges;
bool drawFaces;
bool drawSolidShapes;
bool drawShapes;
bool drawJoints;
bool drawContactPoints;
bool drawContactNormals;
bool drawContactTangents;
bool drawContactPolygons;
bool drawStats;
bool drawProfile;
bool drawGrid;
};
extern Settings* g_settings;
extern TestSettings* g_testSettings;
class RayCastListener : public b3RayCastListener
{
@ -110,6 +91,110 @@ public:
b3RayCastSingleOutput hit;
};
class BodyDragger
{
public:
BodyDragger(Ray3* ray, b3World* world)
{
m_ray = ray;
m_world = world;
m_shape = nullptr;
m_mouseJoint = nullptr;
}
~BodyDragger()
{
}
bool StartDragging()
{
B3_ASSERT(m_mouseJoint == nullptr);
b3RayCastSingleOutput out;
if (m_world->RayCastSingle(&out, m_ray->A(), m_ray->B()) == false)
{
return false;
}
m_x = out.fraction;
m_shape = out.shape;
b3BodyDef bd;
b3Body* groundBody = m_world->CreateBody(bd);
b3Body* body = m_shape->GetBody();
body->SetAwake(true);
b3MouseJointDef jd;
jd.bodyA = groundBody;
jd.bodyB = body;
jd.target = out.point;
jd.maxForce = 2000.0f * body->GetMass();
m_mouseJoint = (b3MouseJoint*)m_world->CreateJoint(jd);
m_p = body->GetLocalPoint(out.point);
return true;
}
void Drag()
{
B3_ASSERT(m_mouseJoint);
m_mouseJoint->SetTarget(GetPointB());
}
void StopDragging()
{
B3_ASSERT(m_mouseJoint);
b3Body* groundBody = m_mouseJoint->GetBodyA();
m_world->DestroyJoint(m_mouseJoint);
m_mouseJoint = nullptr;
m_world->DestroyBody(groundBody);
m_shape = nullptr;
}
bool IsSelected() const
{
return m_mouseJoint != nullptr;
}
Ray3* GetRay() const
{
return m_ray;
}
b3Body* GetBody() const
{
B3_ASSERT(m_shape);
return m_shape->GetBody();
}
b3Vec3 GetPointA() const
{
B3_ASSERT(m_shape);
return m_shape->GetBody()->GetWorldPoint(m_p);
}
b3Vec3 GetPointB() const
{
B3_ASSERT(m_mouseJoint);
return (1.0f - m_x) * m_ray->A() + m_x * m_ray->B();
}
private:
Ray3* m_ray;
float32 m_x;
b3World* m_world;
b3Shape* m_shape;
b3Vec3 m_p;
b3MouseJoint* m_mouseJoint;
};
class Test : public b3ContactListener
{
public:
@ -120,21 +205,23 @@ public:
virtual void Step();
virtual void RayHit();
virtual void MouseMove(const Ray3& pw);
virtual void MouseLeftDown(const Ray3& pw);
virtual void MouseLeftUp(const Ray3& pw);
virtual void KeyDown(int button) { }
virtual void KeyUp(int button) { }
virtual void BeginContact(b3Contact* contact) { }
virtual void EndContact(b3Contact* contact) { }
virtual void PreSolve(b3Contact* contact) { }
virtual void BeginDragging() { }
virtual void EndDragging() { }
void BeginContact(b3Contact* c) override { }
void EndContact(b3Contact* c) override { }
void PreSolve(b3Contact* c) override { }
b3World m_world;
b3RayCastSingleOutput m_rayHit;
b3MouseJoint* m_mouseJoint;
Ray3 m_bodyRay;
BodyDragger m_bodyDragger;
b3BoxHull m_groundHull;
b3GridMesh<50, 50> m_groundMesh;

View File

@ -28,11 +28,11 @@
#include <testbed/tests/hull_collision_2.h>
#include <testbed/tests/linear_motion.h>
#include <testbed/tests/angular_motion.h>
#include <testbed/tests/gyro_motion.h>
#include <testbed/tests/initial_overlap.h>
#include <testbed/tests/capsule_and_hull_contact_1.h>
#include <testbed/tests/quadric_shapes.h>
#include <testbed/tests/multiple_shapes.h>
#include <testbed/tests/gyro_test.h>
#include <testbed/tests/compound_body.h>
#include <testbed/tests/spring.h>
#include <testbed/tests/weld_test.h>
#include <testbed/tests/cone_test.h>
@ -44,14 +44,14 @@
#include <testbed/tests/sphere_stack.h>
#include <testbed/tests/capsule_stack.h>
#include <testbed/tests/box_stack.h>
#include <testbed/tests/sheet_stack.h>
#include <testbed/tests/shape_stack.h>
#include <testbed/tests/jenga.h>
#include <testbed/tests/thin.h>
#include <testbed/tests/pyramid.h>
#include <testbed/tests/pyramids.h>
#include <testbed/tests/ray_cast.h>
#include <testbed/tests/sensor_test.h>
#include <testbed/tests/character_test.h>
#include <testbed/tests/point_click.h>
#include <testbed/tests/body_types.h>
#include <testbed/tests/varying_friction.h>
#include <testbed/tests/varying_restitution.h>
@ -78,12 +78,12 @@ TestEntry g_tests[] =
{ "Hull Collision (1)", &HullAndHull::Create },
{ "Hull Collision (2)", &HullAndHull2::Create },
{ "Capsule and Hull Contact (1)", &CapsuleAndHullContact1::Create },
{ "Mesh Contact Test", &MeshContactTest::Create },
{ "Linear Motion", &LinearMotion::Create },
{ "Angular Motion", &AngularMotion::Create },
{ "Multiple Shapes", &MultipleShapes::Create },
{ "Gyroscopic Motion", &GyroMotion::Create },
{ "Compound Body", &CompoundBody::Create },
{ "Quadric Shapes", &QuadricShapes::Create },
{ "Thin Boxes", &Thin::Create },
{ "Gyroscopic Test", &GyroTest::Create },
{ "Springs", &Spring::Create },
{ "Weld Test", &WeldTest::Create },
{ "Cone Test", &ConeTest::Create },
@ -91,17 +91,17 @@ TestEntry g_tests[] =
{ "Hinge Chain", &HingeChain::Create },
{ "Ragdoll", &Ragdoll::Create },
{ "Newton's Cradle", &NewtonCradle::Create },
{ "Mesh Contact Test", &MeshContactTest::Create },
{ "Sphere Stack", &SphereStack::Create },
{ "Capsule Stack", &CapsuleStack::Create },
{ "Box Stack", &BoxStack::Create },
{ "Sheet Stack", &SheetStack::Create },
{ "Shape Stack", &ShapeStack::Create },
{ "Jenga", &Jenga::Create },
{ "Box Pyramid", &Pyramid::Create },
{ "Box Pyramid Rows", &Pyramids::Create },
{ "Ray Cast", &RayCast::Create },
{ "Sensor Test", &SensorTest::Create },
{ "Character Test", &Character::Create },
{ "Point & Click", &PointClick::Create },
{ "Body Types", &BodyTypes::Create },
{ "Varying Friction", &VaryingFriction::Create },
{ "Varying Restitution", &VaryingRestitution::Create },

View File

@ -24,7 +24,6 @@
#elif defined (U_OPENGL_4)
#include <imgui/imgui_impl_glfw_gl3.h>
#else
#endif
static bool GetTestName(void* userData, int idx, const char** name)
@ -147,6 +146,7 @@ void View::Command_Draw()
{
Camera& camera = m_model->m_camera;
Settings& settings = m_model->m_settings;
TestSettings& testSettings = m_model->m_testSettings;
bool openAbout = false;
if (ImGui::BeginMainMenuBar())
@ -170,24 +170,29 @@ void View::Command_Draw()
if (ImGui::BeginMenu("View"))
{
ImGui::MenuItem("Reference Grid", "", &settings.drawGrid);
ImGui::MenuItem("Vertices and Edges", "", &settings.drawVerticesEdges);
ImGui::MenuItem("Faces", "", &settings.drawFaces);
ImGui::Separator();
ImGui::MenuItem("Center of Masses", "", &settings.drawCenterOfMasses);
ImGui::MenuItem("Bounding Boxes", "", &settings.drawBounds);
ImGui::MenuItem("Joints", "", &settings.drawJoints);
ImGui::MenuItem("Contact Points", "", &settings.drawContactPoints);
ImGui::MenuItem("Contact Normals", "", &settings.drawContactNormals);
ImGui::MenuItem("Contact Tangents", "", &settings.drawContactTangents);
ImGui::MenuItem("Contact Polygons", "", &settings.drawContactPolygons);
ImGui::Separator();
ImGui::MenuItem("Statistics", "", &settings.drawStats);
ImGui::MenuItem("Profile", "", &settings.drawProfile);
ImGui::MenuItem("Statistics", "", &settings.drawStats);
ImGui::Separator();
ImGui::MenuItem("Points", "", &settings.drawPoints);
ImGui::MenuItem("Lines", "", &settings.drawLines);
ImGui::MenuItem("Triangles", "", &settings.drawTriangles);
ImGui::Separator();
ImGui::MenuItem("Reference Grid", "", &settings.drawGrid);
ImGui::Separator();
ImGui::MenuItem("Center of Masses", "", &testSettings.drawCenterOfMasses);
ImGui::MenuItem("Bounding Boxes", "", &testSettings.drawBounds);
ImGui::MenuItem("Shapes", "", &testSettings.drawShapes);
ImGui::MenuItem("Joints", "", &testSettings.drawJoints);
ImGui::MenuItem("Contact Points", "", &testSettings.drawContactPoints);
ImGui::MenuItem("Contact Normals", "", &testSettings.drawContactNormals);
ImGui::MenuItem("Contact Tangents", "", &testSettings.drawContactTangents);
ImGui::MenuItem("Contact Polygons", "", &testSettings.drawContactPolygons);
ImGui::EndMenu();
}
@ -307,17 +312,17 @@ void View::Command_Draw()
ImGui::PushItemWidth(-1.0f);
ImGui::Text("Hertz");
ImGui::SliderFloat("##Hertz", &settings.hertz, 0.0f, 240.0f, "%.1f");
ImGui::SliderFloat("##Hertz", &testSettings.hertz, 0.0f, 240.0f, "%.1f");
ImGui::Text("Velocity Iterations");
ImGui::SliderInt("##Velocity Iterations", &settings.velocityIterations, 0, 50);
ImGui::SliderInt("##Velocity Iterations", &testSettings.velocityIterations, 0, 50);
ImGui::Text("Position Iterations");
ImGui::SliderInt("##Position Iterations", &settings.positionIterations, 0, 50);
ImGui::SliderInt("##Position Iterations", &testSettings.positionIterations, 0, 50);
ImGui::Checkbox("Sleep", &settings.sleep);
ImGui::Checkbox("Convex Cache", &settings.convexCache);
ImGui::Checkbox("Warm Start", &settings.warmStart);
ImGui::Checkbox("Sleep", &testSettings.sleep);
ImGui::Checkbox("Convex Cache", &testSettings.convexCache);
ImGui::Checkbox("Warm Start", &testSettings.warmStart);
ImGui::PopItemWidth();

View File

@ -64,11 +64,11 @@ public:
{
Test::Step();
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");
g_draw->DrawString(b3Color_white, "S - Static");
g_draw->DrawString(b3Color_white, "D - Dynamic");
g_draw->DrawString(b3Color_white, "K - Kinematic");
g_draw->DrawString(b3Color_white, "Space - Throw Bomb");
g_draw->DrawString(b3Color_white, "Arrows - Apply Force/Velocity/Position");
}
void KeyDown(int button)

View File

@ -51,7 +51,7 @@ public:
void Step()
{
m_cloth.Step(g_settings->inv_hertz, g_settings->positionIterations);
m_cloth.Step(g_testSettings->inv_hertz, g_testSettings->positionIterations);
m_cloth.Draw();
}

View File

@ -61,15 +61,15 @@ public:
for (u32 i = 0; i < clusters.Count(); ++i)
{
g_debugDraw->DrawSegment(b3Vec3(0, 0, 0), clusters[i].centroid, b3Color(1, 1, 1));
g_debugDraw->DrawPoint(clusters[i].centroid, 4.0f, m_colors[i]);
g_draw->DrawSegment(b3Vec3(0, 0, 0), clusters[i].centroid, b3Color(1, 1, 1));
g_draw->DrawPoint(clusters[i].centroid, 4.0f, m_colors[i]);
for (u32 j = 0; j < observations.Count(); ++j)
{
b3Observation obs = observations[j];
if (obs.cluster == i)
{
g_debugDraw->DrawPoint(obs.point, 4.0f, m_colors[i]);
g_draw->DrawPoint(obs.point, 4.0f, m_colors[i]);
}
}
}

View File

@ -46,21 +46,15 @@ public:
b3Vec3 pw = wm.points[i].point;
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));
g_draw->DrawPoint(pw, 4.0f, b3Color(0.0f, 1.0f, 0.0f));
g_draw->DrawSegment(pw, pw + wm.points[i].normal, b3Color(1.0f, 1.0f, 1.0f));
}
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)
{
m_world.DrawShape(m_xfA, m_shapeA);
m_world.DrawShape(m_xfB, m_shapeB);
}
g_draw->DrawSolidShape(m_shapeA, b3Color(1.0f, 1.0f, 1.0f, 0.5f), m_xfA);
g_draw->DrawSolidShape(m_shapeB, b3Color(1.0f, 1.0f, 1.0f, 0.5f), m_xfB);
m_world.DrawShape(m_xfA, m_shapeA);
m_world.DrawShape(m_xfB, m_shapeB);
}
virtual void KeyDown(int key)

View File

@ -16,13 +16,13 @@
* 3. This notice may not be removed or altered from any source distribution.
*/
#ifndef MULTIPLE_SHAPES_H
#define MULTIPLE_SHAPES_H
#ifndef COMPOUND_BODY_H
#define COMPOUND_BODY_H
class MultipleShapes : public Test
class CompoundBody : public Test
{
public:
MultipleShapes()
CompoundBody()
{
{
b3BodyDef bd;
@ -76,7 +76,7 @@ public:
b3BodyDef bd;
bd.type = e_dynamicBody;
bd.position.Set(0.0f, 0.0f, 0.0f);
bd.angularVelocity.Set(0.0f, 200.0f * B3_PI, 0.0f);
bd.angularVelocity.Set(0.0f, 2.0f * B3_PI, 0.0f);
b3Body* body = m_world.CreateBody(bd);
@ -105,7 +105,7 @@ public:
static Test* Create()
{
return new MultipleShapes();
return new CompoundBody();
}
b3BoxHull m_box1;

View File

@ -51,22 +51,22 @@ public:
for (u32 i = 0; i < featurePair.count1; ++i)
{
u32 index = featurePair.index1[i];
g_debugDraw->DrawPoint(m_xfA * m_proxyA.GetVertex(index), 4.0f, b3Color(1.0f, 1.0f, 0.0f));
g_draw->DrawPoint(m_xfA * m_proxyA.GetVertex(index), 4.0f, b3Color(1.0f, 1.0f, 0.0f));
}
for (u32 i = 0; i < featurePair.count2; ++i)
{
u32 index = featurePair.index2[i];
g_debugDraw->DrawPoint(m_xfB * m_proxyB.GetVertex(index), 4.0f, b3Color(1.0f, 1.0f, 0.0f));
g_draw->DrawPoint(m_xfB * m_proxyB.GetVertex(index), 4.0f, b3Color(1.0f, 1.0f, 0.0f));
}
}
g_debugDraw->DrawPoint(out.point1, 4.0f, b3Color(0.0f, 1.0f, 0.0f));
g_debugDraw->DrawPoint(out.point2, 4.0f, b3Color(0.0f, 1.0f, 0.0f));
g_debugDraw->DrawSegment(out.point1, out.point2, b3Color(1.0f, 1.0f, 1.0f));
g_draw->DrawPoint(out.point1, 4.0f, b3Color(0.0f, 1.0f, 0.0f));
g_draw->DrawPoint(out.point2, 4.0f, b3Color(0.0f, 1.0f, 0.0f));
g_draw->DrawSegment(out.point1, out.point2, b3Color(1.0f, 1.0f, 1.0f));
g_debugDraw->DrawTransform(m_xfA);
g_debugDraw->DrawTransform(m_xfB);
g_draw->DrawTransform(m_xfA);
g_draw->DrawTransform(m_xfB);
m_world.DrawShape(m_xfA, &m_shapeA);
m_world.DrawShape(m_xfB, &m_shapeB);

View File

@ -16,15 +16,15 @@
* 3. This notice may not be removed or altered from any source distribution.
*/
#ifndef GYRO_TEST_H
#define GYRO_TEST_H
#ifndef GYRO_MOTION_H
#define GYRO_MOTION_H
#include <testbed/tests/quickhull_test.h>
class GyroTest : public Test
class GyroMotion : public Test
{
public:
GyroTest()
GyroMotion()
{
{
b3StackArray<b3Vec3, 32> points;
@ -63,10 +63,7 @@ public:
b3Body* body = m_world.CreateBody(bdef);
{
b3Transform xf;
xf.position.SetZero();
xf.rotation = b3Diagonal(1.0f, 0.5f, 7.0f);
m_rotorBox.SetTransform(xf);
m_rotorBox.Set(1.0f, 0.5f, 7.0f);
b3HullShape hull;
hull.m_hull = &m_rotorBox;
@ -93,7 +90,7 @@ public:
m_world.SetGravity(b3Vec3(0.0f, 0.0f, 0.0f));
}
~GyroTest()
~GyroMotion()
{
{
b3Free(m_cylinderHull.vertices);
@ -105,7 +102,7 @@ public:
static Test* Create()
{
return new GyroTest();
return new GyroMotion();
}
b3BoxHull m_rotorBox;

View File

@ -126,18 +126,18 @@ public:
void Step()
{
float32 h = g_settings->inv_hertz;
float32 h = g_testSettings->inv_hertz;
Solve(h);
g_debugDraw->DrawSolidSphere(m_x, 0.25f, b3Color_white);
g_draw->DrawSolidSphere(m_x, 0.25f, b3Color_white);
g_debugDraw->DrawSegment(b3Vec3_zero, m_x, b3Color_white);
g_draw->DrawSegment(b3Vec3_zero, m_x, b3Color_white);
g_debugDraw->DrawString(b3Color_white, "Iterations = %u", m_iterations);
g_draw->DrawString(b3Color_white, "Iterations = %u", m_iterations);
float32 E = 0.5f * b3Dot(m_v, m_v);
g_debugDraw->DrawString(b3Color_white, "E = %f", E);
g_draw->DrawString(b3Color_white, "E = %f", E);
}
static Test* Create()

View File

@ -163,11 +163,11 @@ public:
{
Test::Step();
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");
g_draw->DrawString(b3Color_white, "S - Sphere");
g_draw->DrawString(b3Color_white, "C - Capsule");
g_draw->DrawString(b3Color_white, "H - Hull");
g_draw->DrawString(b3Color_white, "G - Grid");
g_draw->DrawString(b3Color_white, "T - Terrain");
}
static Test* Create()

View File

@ -16,13 +16,13 @@
* 3. This notice may not be removed or altered from any source distribution.
*/
#ifndef CHARACTER_H
#define CHARACTER_H
#ifndef POINT_CLICK_H
#define POINT_CLICK_H
class Character : public Test
class PointClick : public Test
{
public:
Character()
PointClick()
{
{
b3BodyDef bdef;
@ -59,31 +59,28 @@ public:
}
}
void RayHit()
void BeginDragging()
{
if (m_rayHit.shape)
if (m_bodyDragger.GetBody() == m_character)
{
if (m_rayHit.shape->GetBody() != m_character)
{
Test::RayHit();
}
m_bodyDragger.StopDragging();
}
}
void Step()
{
if (m_rayHit.shape)
if (m_bodyDragger.IsSelected())
{
if (m_rayHit.shape->GetBody() != m_character)
if (m_bodyDragger.GetBody() != m_character)
{
b3Vec3 point = m_rayHit.point;
b3Vec3 normal = m_rayHit.normal;
const b3Transform& xf = m_character->GetTransform();
b3Vec3 n = point - xf.position;
n.Normalize();
b3Vec3 p1 = m_character->GetPosition();
b3Vec3 p2 = m_bodyDragger.GetPointA();
m_character->ApplyForceToCenter(1000.0f * n, true);
b3Vec3 n = b3Normalize(p2 - p1);
const float32 k = 1000.0f;
b3Vec3 f = k * n;
m_character->ApplyForceToCenter(f, true);
}
}
@ -92,10 +89,10 @@ public:
static Test* Create()
{
return new Character();
return new PointClick();
}
b3Body* m_character;
};
#endif
#endif

View File

@ -317,7 +317,7 @@ public:
void Step()
{
m_qhull.Draw(g_debugDraw);
m_qhull.Draw(g_draw);
}
static Test* Create()

View File

@ -181,22 +181,20 @@ public:
b3RayCastSingleOutput out;
if (m_world.RayCastSingle(&out, p1, p2))
{
g_debugDraw->DrawSegment(p1, out.point, b3Color_green);
g_draw->DrawSegment(p1, out.point, b3Color_green);
g_debugDraw->DrawPoint(out.point, 4.0f, b3Color_red);
g_debugDraw->DrawSegment(out.point, out.point + out.normal, b3Color_white);
g_debugDraw->DrawSolidCircle(out.normal, out.point + 0.025f * out.normal, 1.0f, b3Color_white);
g_draw->DrawPoint(out.point, 4.0f, b3Color_red);
g_draw->DrawSegment(out.point, out.point + out.normal, b3Color_white);
}
else
{
g_debugDraw->DrawSegment(p1, p2, b3Color_green);
g_draw->DrawSegment(p1, p2, b3Color_green);
}
}
void Step()
{
float32 dt = g_settings->inv_hertz;
float32 dt = g_testSettings->inv_hertz;
b3Quat dq = b3QuatRotationY(0.05f * B3_PI * dt);
m_p1 = b3Mul(dq, m_p1);

View File

@ -85,7 +85,7 @@ public:
void Step()
{
m_rope.Step(g_settings->inv_hertz);
m_rope.Step(g_testSettings->inv_hertz);
m_rope.Draw();
}

View File

@ -16,10 +16,10 @@
* 3. This notice may not be removed or altered from any source distribution.
*/
#ifndef THIN_H
#define THIN_H
#ifndef SHEET_STACK_H
#define SHEET_STACK_H
class Thin : public Test
class SheetStack : public Test
{
public:
enum
@ -29,7 +29,7 @@ public:
e_depthCount = 1
};
Thin()
SheetStack()
{
{
b3BodyDef bdef;
@ -47,22 +47,12 @@ public:
b3Shape* shape = body->CreateShape(sdef);
}
static b3BoxHull thinHull;
{
b3Transform xf;
xf.position.SetZero();
xf.rotation = b3Diagonal(4.05f, 2.0f * B3_LINEAR_SLOP, 4.05f);
thinHull.SetTransform(xf);
}
static b3Vec3 sheetExtents(4.05f, 2.0f * B3_LINEAR_SLOP, 4.05f);
static b3BoxHull sheetHull(sheetExtents.x, sheetExtents.y, sheetExtents.z);
b3Vec3 stackOrigin;
stackOrigin.Set(0.0f, 4.05f, 0.0f);
b3Vec3 boxScale;
boxScale.Set(4.05f, 2.05f, 4.05f);
for (u32 i = 0; i < e_rowCount; ++i)
{
for (u32 j = 0; j < e_columnCount; ++j)
@ -72,15 +62,15 @@ public:
b3BodyDef bdef;
bdef.type = b3BodyType::e_dynamicBody;
bdef.position.x = float32(i) * boxScale.x;
bdef.position.y = 1.5f * float32(j) * boxScale.y;
bdef.position.z = float32(k) * boxScale.z;
bdef.position.x = float32(i) * sheetExtents.x;
bdef.position.y = float32(j) * 50.0f * sheetExtents.y;
bdef.position.z = float32(k) * sheetExtents.z;
bdef.position += stackOrigin;
b3Body* body = m_world.CreateBody(bdef);
b3HullShape hs;
hs.m_hull = &thinHull;
hs.m_hull = &sheetHull;
b3ShapeDef sdef;
sdef.shape = &hs;
@ -95,8 +85,8 @@ public:
static Test* Create()
{
return new Thin();
return new SheetStack();
}
};
#endif
#endif

View File

@ -37,7 +37,7 @@ public:
void Step()
{
float32 h = g_settings->inv_hertz;
float32 h = g_testSettings->inv_hertz;
// Solution (acceleration)
float32 omega_dot = -m_g / m_r * sin(m_theta);
@ -53,11 +53,11 @@ public:
c.x = m_r * sin(m_theta);
c.y = m_r * cos(m_theta);
c.z = 0.0f;
g_debugDraw->DrawSolidSphere(c, 1.0f, b3Color_white);
g_draw->DrawSolidSphere(c, 1.0f, b3Color_white);
b3Vec3 pole;
pole.SetZero();
g_debugDraw->DrawSegment(pole, c, b3Color_white);
g_draw->DrawSegment(pole, c, b3Color_white);
// Kinetic energy
float32 T = 0.5f * m_I * m_omega * m_omega;
@ -69,7 +69,7 @@ public:
float32 L = T - V;
//
g_debugDraw->DrawString(b3Color_white, "T = %f \nV = %f \nL = %f", T, V, L);
g_draw->DrawString(b3Color_white, "T = %f \nV = %f \nL = %f", T, V, L);
}
static Test* Create()

View File

@ -204,8 +204,6 @@ class SpringClothTest : public Test
public:
SpringClothTest() : m_clothDragger(&m_clothRay, &m_cloth)
{
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;
@ -213,7 +211,7 @@ public:
void Step()
{
float32 dt = g_settings->inv_hertz;
float32 dt = g_testSettings->inv_hertz;
m_cloth.Step(dt);
m_cloth.Apply();
@ -226,18 +224,18 @@ public:
b3Transform xf;
xf.SetIdentity();
g_debugDraw->DrawShape(s, b3Color_white, xf);
g_draw->DrawSolidShape(s, b3Color_white, xf);
}
m_cloth.Draw();
b3SpringClothStep step = m_cloth.GetStep();
g_debugDraw->DrawString(b3Color_white, "Iterations = %u", step.iterations);
g_draw->DrawString(b3Color_white, "Iterations = %u", step.iterations);
if (m_clothDragger.IsSelected() == true)
{
g_debugDraw->DrawSegment(m_clothDragger.GetPointA(), m_clothDragger.GetPointB(), b3Color_white);
g_draw->DrawSegment(m_clothDragger.GetPointA(), m_clothDragger.GetPointB(), b3Color_white);
}
}

View File

@ -84,7 +84,7 @@ public:
void Step()
{
float32 dt = g_settings->inv_hertz;
float32 dt = g_testSettings->inv_hertz;
m_cloth.Step(dt);
m_cloth.Apply();
@ -119,17 +119,17 @@ public:
b3Vec3 n2 = -n1;
g_debugDraw->DrawSolidTriangle(n1, v1, c1, v2, c2, v3, c3);
g_debugDraw->DrawSolidTriangle(n2, v1, c1, v3, c3, v2, c2);
g_draw->DrawSolidTriangle(n1, v1, c1, v2, c2, v3, c3);
g_draw->DrawSolidTriangle(n2, v1, c1, v3, c3, v2, c2);
}
b3SpringClothStep step = m_cloth.GetStep();
g_debugDraw->DrawString(b3Color_white, "Iterations = %u", step.iterations);
g_draw->DrawString(b3Color_white, "Iterations = %u", step.iterations);
if (m_clothDragger.IsSelected() == true)
{
g_debugDraw->DrawSegment(m_clothDragger.GetPointA(), m_clothDragger.GetPointB(), b3Color_white);
g_draw->DrawSegment(m_clothDragger.GetPointA(), m_clothDragger.GetPointB(), b3Color_white);
}
}

View File

@ -261,7 +261,7 @@ solution (solution_name)
files
{
examples_inc_dir .. "/testbed/framework/debug_draw.h",
examples_inc_dir .. "/testbed/framework/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",
@ -275,6 +275,7 @@ solution (solution_name)
examples_inc_dir .. "/testbed/tests/**.h",
examples_src_dir .. "/testbed/framework/draw.cpp",
examples_src_dir .. "/testbed/framework/profiler.cpp",
examples_src_dir .. "/testbed/framework/recorder_profiler.cpp",
examples_src_dir .. "/testbed/framework/json_profiler.cpp",
@ -292,14 +293,14 @@ solution (solution_name)
if is_gfxapi("opengl_2") then
files
{
examples_src_dir .. "/testbed/framework/debug_draw_2.cpp"
examples_src_dir .. "/testbed/framework/draw_gl2.h"
}
end
if is_gfxapi("opengl_4") then
files
{
examples_src_dir .. "/testbed/framework/debug_draw_4.cpp"
examples_src_dir .. "/testbed/framework/draw_gl4.h"
}
end