testbed, tests, ui
This commit is contained in:
parent
3c8af0060a
commit
eb698f146a
522
examples/testbed/framework/draw.cpp
Normal file
522
examples/testbed/framework/draw.cpp
Normal 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();
|
||||
}
|
@ -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
|
@ -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
|
@ -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();
|
||||
}
|
||||
};
|
@ -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();
|
||||
|
@ -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();
|
||||
}
|
@ -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;
|
||||
};
|
||||
|
||||
|
@ -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)
|
||||
|
@ -47,4 +47,6 @@ private:
|
||||
b3StackArray<ProfilerRecord, 256> m_records;
|
||||
};
|
||||
|
||||
extern RecorderProfiler* g_profilerRecorder;
|
||||
|
||||
#endif
|
@ -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);
|
||||
}
|
||||
}
|
@ -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;
|
||||
|
@ -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 },
|
||||
|
@ -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();
|
||||
|
||||
|
@ -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)
|
||||
|
@ -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();
|
||||
}
|
||||
|
||||
|
@ -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]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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)
|
||||
|
@ -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;
|
@ -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);
|
||||
|
@ -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;
|
@ -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()
|
||||
|
@ -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()
|
||||
|
@ -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
|
@ -317,7 +317,7 @@ public:
|
||||
|
||||
void Step()
|
||||
{
|
||||
m_qhull.Draw(g_debugDraw);
|
||||
m_qhull.Draw(g_draw);
|
||||
}
|
||||
|
||||
static Test* Create()
|
||||
|
@ -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);
|
||||
|
@ -85,7 +85,7 @@ public:
|
||||
|
||||
void Step()
|
||||
{
|
||||
m_rope.Step(g_settings->inv_hertz);
|
||||
m_rope.Step(g_testSettings->inv_hertz);
|
||||
m_rope.Draw();
|
||||
}
|
||||
|
||||
|
@ -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
|
@ -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()
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user