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.
|
* 3. This notice may not be removed or altered from any source distribution.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef DEBUG_DRAW_H
|
#ifndef DRAW_H
|
||||||
#define DEBUG_DRAW_H
|
#define DRAW_H
|
||||||
|
|
||||||
#include <bounce/bounce.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:
|
public:
|
||||||
DebugDraw();
|
Draw();
|
||||||
~DebugDraw();
|
~Draw();
|
||||||
|
|
||||||
void DrawPoint(const b3Vec3& p, float32 size, const b3Color& color);
|
void DrawPoint(const b3Vec3& p, float32 size, const b3Color& color);
|
||||||
|
|
||||||
void DrawSegment(const b3Vec3& p1, const b3Vec3& p2, 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 DrawAABB(const b3AABB3& aabb, const b3Color& color);
|
||||||
|
|
||||||
void DrawTransform(const b3Transform& xf);
|
void DrawTransform(const b3Transform& xf);
|
||||||
|
|
||||||
//
|
|
||||||
void DrawString(const b3Color& color, const char* string, ...);
|
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:
|
private:
|
||||||
friend struct DrawShapes;
|
friend struct DrawPoints;
|
||||||
|
friend struct DrawLines;
|
||||||
|
friend struct DrawTriangles;
|
||||||
|
|
||||||
DrawPoints* m_points;
|
DrawPoints* m_points;
|
||||||
DrawLines* m_lines;
|
DrawLines* m_lines;
|
||||||
DrawTriangles* m_triangles;
|
DrawTriangles* m_triangles;
|
||||||
|
|
||||||
|
friend struct DrawWire;
|
||||||
|
friend struct DrawSolid;
|
||||||
|
|
||||||
DrawWire* m_wire;
|
DrawWire* m_wire;
|
||||||
DrawSolid* m_solid;
|
DrawSolid* m_solid;
|
||||||
};
|
};
|
||||||
|
|
||||||
extern DebugDraw* g_debugDraw;
|
|
||||||
extern Camera* g_camera;
|
extern Camera* g_camera;
|
||||||
extern const char* g_overlayName;
|
extern Draw* g_draw;
|
||||||
|
extern u32 g_drawFlags;
|
||||||
|
|
||||||
#endif
|
#endif
|
@ -16,19 +16,16 @@
|
|||||||
* 3. This notice may not be removed or altered from any source distribution.
|
* 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 <glad_2/glad.h>
|
||||||
#include <imgui/imgui.h>
|
|
||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdarg.h>
|
#include <stdarg.h>
|
||||||
|
|
||||||
//
|
|
||||||
DebugDraw* g_debugDraw = nullptr;
|
|
||||||
Camera* g_camera = nullptr;
|
|
||||||
const char* g_overlayName = nullptr;
|
|
||||||
|
|
||||||
#define BUFFER_OFFSET(i) ((char*)NULL + (i))
|
#define BUFFER_OFFSET(i) ((char*)NULL + (i))
|
||||||
|
|
||||||
static void AssertGL()
|
static void AssertGL()
|
||||||
@ -176,7 +173,7 @@ struct DrawPoints
|
|||||||
{
|
{
|
||||||
if (m_count == e_vertexCapacity)
|
if (m_count == e_vertexCapacity)
|
||||||
{
|
{
|
||||||
Submit();
|
Flush();
|
||||||
}
|
}
|
||||||
|
|
||||||
m_vertices[m_count] = v;
|
m_vertices[m_count] = v;
|
||||||
@ -185,13 +182,19 @@ struct DrawPoints
|
|||||||
++m_count;
|
++m_count;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Submit()
|
void Flush()
|
||||||
{
|
{
|
||||||
if (m_count == 0)
|
if (m_count == 0)
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ((g_drawFlags & DrawFlags::e_pointsFlag) == 0)
|
||||||
|
{
|
||||||
|
m_count = 0;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
glUseProgram(m_programId);
|
glUseProgram(m_programId);
|
||||||
|
|
||||||
b3Mat44 m1 = g_camera->BuildViewMatrix();
|
b3Mat44 m1 = g_camera->BuildViewMatrix();
|
||||||
@ -306,7 +309,7 @@ struct DrawLines
|
|||||||
{
|
{
|
||||||
if (m_count == e_vertexCapacity)
|
if (m_count == e_vertexCapacity)
|
||||||
{
|
{
|
||||||
Submit();
|
Flush();
|
||||||
}
|
}
|
||||||
|
|
||||||
m_vertices[m_count] = v;
|
m_vertices[m_count] = v;
|
||||||
@ -314,13 +317,19 @@ struct DrawLines
|
|||||||
++m_count;
|
++m_count;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Submit()
|
void Flush()
|
||||||
{
|
{
|
||||||
if (m_count == 0)
|
if (m_count == 0)
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ((g_drawFlags & DrawFlags::e_linesFlag) == 0)
|
||||||
|
{
|
||||||
|
m_count = 0;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
glUseProgram(m_programId);
|
glUseProgram(m_programId);
|
||||||
|
|
||||||
b3Mat44 m1 = g_camera->BuildViewMatrix();
|
b3Mat44 m1 = g_camera->BuildViewMatrix();
|
||||||
@ -435,7 +444,7 @@ struct DrawTriangles
|
|||||||
{
|
{
|
||||||
if (m_count == e_vertexCapacity)
|
if (m_count == e_vertexCapacity)
|
||||||
{
|
{
|
||||||
Submit();
|
Flush();
|
||||||
}
|
}
|
||||||
|
|
||||||
m_vertices[m_count] = v;
|
m_vertices[m_count] = v;
|
||||||
@ -444,12 +453,18 @@ struct DrawTriangles
|
|||||||
++m_count;
|
++m_count;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Submit()
|
void Flush()
|
||||||
{
|
{
|
||||||
if (m_count == 0)
|
if (m_count == 0)
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ((g_drawFlags & DrawFlags::e_trianglesFlag) == 0)
|
||||||
|
{
|
||||||
|
m_count = 0;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
glUseProgram(m_programId);
|
glUseProgram(m_programId);
|
||||||
|
|
||||||
@ -631,6 +646,11 @@ struct DrawWire
|
|||||||
|
|
||||||
void DrawSphere(float32 radius, const b3Color& c, const b3Transform& xf)
|
void DrawSphere(float32 radius, const b3Color& c, const b3Transform& xf)
|
||||||
{
|
{
|
||||||
|
if ((g_drawFlags & DrawFlags::e_linesFlag) == 0)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
glUseProgram(m_programId);
|
glUseProgram(m_programId);
|
||||||
|
|
||||||
b3Mat44 m1 = MakeMat44(xf);
|
b3Mat44 m1 = MakeMat44(xf);
|
||||||
@ -920,6 +940,11 @@ struct DrawSolid
|
|||||||
|
|
||||||
void DrawCylinder(float32 radius, float32 height, const b3Color& c, const b3Transform& xf)
|
void DrawCylinder(float32 radius, float32 height, const b3Color& c, const b3Transform& xf)
|
||||||
{
|
{
|
||||||
|
if ((g_drawFlags & DrawFlags::e_trianglesFlag) == 0)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
glUseProgram(m_programId);
|
glUseProgram(m_programId);
|
||||||
|
|
||||||
b3Mat44 m1 = MakeMat44(xf);
|
b3Mat44 m1 = MakeMat44(xf);
|
||||||
@ -958,6 +983,11 @@ struct DrawSolid
|
|||||||
|
|
||||||
void DrawSphere(float32 radius, const b3Color& c, const b3Transform& xf)
|
void DrawSphere(float32 radius, const b3Color& c, const b3Transform& xf)
|
||||||
{
|
{
|
||||||
|
if ((g_drawFlags & DrawFlags::e_trianglesFlag) == 0)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
glUseProgram(m_programId);
|
glUseProgram(m_programId);
|
||||||
|
|
||||||
b3Mat44 m1 = MakeMat44(xf);
|
b3Mat44 m1 = MakeMat44(xf);
|
||||||
@ -1005,494 +1035,4 @@ struct DrawSolid
|
|||||||
DrawSolidCylinder m_cylinder;
|
DrawSolidCylinder m_cylinder;
|
||||||
};
|
};
|
||||||
|
|
||||||
DebugDraw::DebugDraw()
|
#endif
|
||||||
{
|
|
||||||
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();
|
|
||||||
}
|
|
@ -16,19 +16,13 @@
|
|||||||
* 3. This notice may not be removed or altered from any source distribution.
|
* 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 <glad_4/glad.h>
|
||||||
#include <imgui/imgui.h>
|
|
||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdarg.h>
|
#include <stdarg.h>
|
||||||
|
|
||||||
//
|
|
||||||
DebugDraw* g_debugDraw = nullptr;
|
|
||||||
Camera* g_camera = nullptr;
|
|
||||||
const char* g_overlayName = nullptr;
|
|
||||||
|
|
||||||
#define BUFFER_OFFSET(i) ((char*)NULL + (i))
|
#define BUFFER_OFFSET(i) ((char*)NULL + (i))
|
||||||
|
|
||||||
static void AssertGL()
|
static void AssertGL()
|
||||||
@ -190,7 +184,7 @@ struct DrawPoints
|
|||||||
{
|
{
|
||||||
if (m_count == e_vertexCapacity)
|
if (m_count == e_vertexCapacity)
|
||||||
{
|
{
|
||||||
Submit();
|
Flush();
|
||||||
}
|
}
|
||||||
|
|
||||||
m_vertices[m_count] = v;
|
m_vertices[m_count] = v;
|
||||||
@ -199,12 +193,18 @@ struct DrawPoints
|
|||||||
++m_count;
|
++m_count;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Submit()
|
void Flush()
|
||||||
{
|
{
|
||||||
if (m_count == 0)
|
if (m_count == 0)
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ((g_drawFlags & DrawFlags::e_pointsFlag) == 0)
|
||||||
|
{
|
||||||
|
m_count = 0;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
glUseProgram(m_programId);
|
glUseProgram(m_programId);
|
||||||
|
|
||||||
@ -322,7 +322,7 @@ struct DrawLines
|
|||||||
{
|
{
|
||||||
if (m_count == e_vertexCapacity)
|
if (m_count == e_vertexCapacity)
|
||||||
{
|
{
|
||||||
Submit();
|
Flush();
|
||||||
}
|
}
|
||||||
|
|
||||||
m_vertices[m_count] = v;
|
m_vertices[m_count] = v;
|
||||||
@ -330,12 +330,18 @@ struct DrawLines
|
|||||||
++m_count;
|
++m_count;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Submit()
|
void Flush()
|
||||||
{
|
{
|
||||||
if (m_count == 0)
|
if (m_count == 0)
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ((g_drawFlags & DrawFlags::e_linesFlag) == 0)
|
||||||
|
{
|
||||||
|
m_count = 0;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
glUseProgram(m_programId);
|
glUseProgram(m_programId);
|
||||||
|
|
||||||
@ -459,7 +465,7 @@ struct DrawTriangles
|
|||||||
{
|
{
|
||||||
if (m_count == e_vertexCapacity)
|
if (m_count == e_vertexCapacity)
|
||||||
{
|
{
|
||||||
Submit();
|
Flush();
|
||||||
}
|
}
|
||||||
|
|
||||||
m_vertices[m_count] = v;
|
m_vertices[m_count] = v;
|
||||||
@ -468,13 +474,19 @@ struct DrawTriangles
|
|||||||
++m_count;
|
++m_count;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Submit()
|
void Flush()
|
||||||
{
|
{
|
||||||
if (m_count == 0)
|
if (m_count == 0)
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ((g_drawFlags & DrawFlags::e_trianglesFlag) == 0)
|
||||||
|
{
|
||||||
|
m_count = 0;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
glUseProgram(m_programId);
|
glUseProgram(m_programId);
|
||||||
|
|
||||||
b3Mat44 m1 = g_camera->BuildViewMatrix();
|
b3Mat44 m1 = g_camera->BuildViewMatrix();
|
||||||
@ -648,6 +660,11 @@ struct DrawWire
|
|||||||
|
|
||||||
void DrawSphere(float32 radius, const b3Color& c, const b3Transform& xf)
|
void DrawSphere(float32 radius, const b3Color& c, const b3Transform& xf)
|
||||||
{
|
{
|
||||||
|
if ((g_drawFlags & DrawFlags::e_linesFlag) == 0)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
glUseProgram(m_programId);
|
glUseProgram(m_programId);
|
||||||
|
|
||||||
b3Mat44 m1 = MakeMat44(xf);
|
b3Mat44 m1 = MakeMat44(xf);
|
||||||
@ -936,6 +953,11 @@ struct DrawSolid
|
|||||||
|
|
||||||
void DrawCylinder(float32 radius, float32 height, const b3Color& c, const b3Transform& xf)
|
void DrawCylinder(float32 radius, float32 height, const b3Color& c, const b3Transform& xf)
|
||||||
{
|
{
|
||||||
|
if ((g_drawFlags & DrawFlags::e_trianglesFlag) == 0)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
glUseProgram(m_programId);
|
glUseProgram(m_programId);
|
||||||
|
|
||||||
b3Mat44 m1 = MakeMat44(xf);
|
b3Mat44 m1 = MakeMat44(xf);
|
||||||
@ -970,6 +992,11 @@ struct DrawSolid
|
|||||||
|
|
||||||
void DrawSphere(float32 radius, const b3Color& c, const b3Transform& xf)
|
void DrawSphere(float32 radius, const b3Color& c, const b3Transform& xf)
|
||||||
{
|
{
|
||||||
|
if ((g_drawFlags & DrawFlags::e_trianglesFlag) == 0)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
glUseProgram(m_programId);
|
glUseProgram(m_programId);
|
||||||
|
|
||||||
b3Mat44 m1 = MakeMat44(xf);
|
b3Mat44 m1 = MakeMat44(xf);
|
||||||
@ -1011,496 +1038,4 @@ struct DrawSolid
|
|||||||
|
|
||||||
DrawSolidSphere m_sphere;
|
DrawSolidSphere m_sphere;
|
||||||
DrawSolidCylinder m_cylinder;
|
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;
|
int w, h;
|
||||||
glfwGetWindowSize(g_window, &w, &h);
|
glfwGetWindowSize(g_window, &w, &h);
|
||||||
g_controller->Event_SetWindowSize(u32(w), u32(h));
|
g_controller->Event_SetWindowSize(u32(w), u32(h));
|
||||||
|
|
||||||
double frameTime = 0.0;
|
|
||||||
|
|
||||||
while (glfwWindowShouldClose(g_window) == 0)
|
while (glfwWindowShouldClose(g_window) == 0)
|
||||||
{
|
{
|
||||||
double time1 = glfwGetTime();
|
g_profiler->Begin();
|
||||||
|
|
||||||
|
g_profiler->PushEvent("Frame");
|
||||||
|
|
||||||
g_view->Command_PreDraw();
|
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_model->Command_Step();
|
||||||
|
|
||||||
g_view->Command_PostDraw();
|
g_view->Command_PostDraw();
|
||||||
|
|
||||||
double time2 = glfwGetTime();
|
g_profiler->PopEvent();
|
||||||
|
|
||||||
double fraction = 0.9;
|
g_profiler->End(g_profilerListener);
|
||||||
frameTime = fraction * frameTime + (1.0 - fraction) * (time2 - time1);
|
|
||||||
|
|
||||||
glfwSwapBuffers(g_window);
|
glfwSwapBuffers(g_window);
|
||||||
glfwPollEvents();
|
glfwPollEvents();
|
||||||
|
@ -20,12 +20,13 @@
|
|||||||
|
|
||||||
Model::Model()
|
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_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;
|
m_test = nullptr;
|
||||||
|
|
||||||
@ -44,38 +45,44 @@ Model::Model()
|
|||||||
|
|
||||||
Model::~Model()
|
Model::~Model()
|
||||||
{
|
{
|
||||||
g_debugDraw = nullptr;
|
g_testSettings = nullptr;
|
||||||
|
g_draw = nullptr;
|
||||||
g_camera = nullptr;
|
g_camera = nullptr;
|
||||||
g_overlayName = nullptr;
|
|
||||||
g_profiler = nullptr;
|
g_profiler = nullptr;
|
||||||
|
g_profilerRecorder = nullptr;
|
||||||
g_profilerListener = nullptr;
|
g_profilerListener = nullptr;
|
||||||
g_settings = nullptr;
|
g_testSettings = nullptr;
|
||||||
|
|
||||||
delete m_test;
|
delete m_test;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Model::Command_Step()
|
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)
|
if (m_settings.testID != m_settings.lastTestID)
|
||||||
{
|
{
|
||||||
delete m_test;
|
delete m_test;
|
||||||
m_settings.lastTestID = m_settings.testID;
|
m_settings.lastTestID = m_settings.testID;
|
||||||
m_test = g_tests[m_settings.testID].create();
|
m_test = g_tests[m_settings.testID].create();
|
||||||
|
|
||||||
m_settings.pause = true;
|
m_settings.pause = true;
|
||||||
|
|
||||||
Action_DefaultCamera();
|
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)
|
if (m_settings.pause)
|
||||||
{
|
{
|
||||||
m_debugDraw.DrawString(b3Color_white, "*PAUSED*");
|
m_draw.DrawString(b3Color_white, "*PAUSED*");
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
m_debugDraw.DrawString(b3Color_white, "*PLAYING*");
|
m_draw.DrawString(b3Color_white, "*PLAYING*");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (m_settings.drawGrid)
|
if (m_settings.drawGrid)
|
||||||
@ -84,7 +91,7 @@ void Model::Command_Step()
|
|||||||
|
|
||||||
b3Vec3 pn(0.0f, 1.0f, 0.0f);
|
b3Vec3 pn(0.0f, 1.0f, 0.0f);
|
||||||
b3Vec3 p(0.0f, 0.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;
|
int n = 20;
|
||||||
|
|
||||||
@ -108,13 +115,13 @@ void Model::Command_Step()
|
|||||||
vs[2] += t;
|
vs[2] += t;
|
||||||
vs[3] += 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)
|
if (m_settings.pause)
|
||||||
{
|
{
|
||||||
@ -124,25 +131,11 @@ void Model::Command_Step()
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
m_settings.inv_hertz = 0.0f;
|
m_testSettings.inv_hertz = 0.0f;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
m_profiler.Begin();
|
|
||||||
|
|
||||||
m_test->Step();
|
m_test->Step();
|
||||||
|
|
||||||
m_profiler.End(g_profilerListener);
|
m_draw.Flush();
|
||||||
|
|
||||||
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();
|
|
||||||
}
|
}
|
@ -19,10 +19,43 @@
|
|||||||
#ifndef MODEL_H
|
#ifndef MODEL_H
|
||||||
#define 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/testbed_listener.h>
|
||||||
#include <testbed/framework/test.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
|
class Model
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
@ -62,12 +95,15 @@ private:
|
|||||||
friend class View;
|
friend class View;
|
||||||
friend class Controller;
|
friend class Controller;
|
||||||
|
|
||||||
DebugDraw m_debugDraw;
|
// UI State
|
||||||
|
Settings m_settings;
|
||||||
|
TestSettings m_testSettings;
|
||||||
|
|
||||||
|
// App State
|
||||||
|
Draw m_draw;
|
||||||
Camera m_camera;
|
Camera m_camera;
|
||||||
Profiler m_profiler;
|
Profiler m_profiler;
|
||||||
TestbedListener m_profilerListener;
|
TestbedListener m_profilerListener;
|
||||||
|
|
||||||
Settings m_settings;
|
|
||||||
Test* m_test;
|
Test* m_test;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -18,6 +18,8 @@
|
|||||||
|
|
||||||
#include <testbed/framework/recorder_profiler.h>
|
#include <testbed/framework/recorder_profiler.h>
|
||||||
|
|
||||||
|
RecorderProfiler* g_profilerRecorder = nullptr;
|
||||||
|
|
||||||
void RecorderProfiler::BeginEvents()
|
void RecorderProfiler::BeginEvents()
|
||||||
{
|
{
|
||||||
for (u32 i = 0; i < m_records.Count(); ++i)
|
for (u32 i = 0; i < m_records.Count(); ++i)
|
||||||
|
@ -47,4 +47,6 @@ private:
|
|||||||
b3StackArray<ProfilerRecord, 256> m_records;
|
b3StackArray<ProfilerRecord, 256> m_records;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
extern RecorderProfiler* g_profilerRecorder;
|
||||||
|
|
||||||
#endif
|
#endif
|
@ -17,6 +17,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include <testbed/framework/test.h>
|
#include <testbed/framework/test.h>
|
||||||
|
#include <testbed/framework/model.h>
|
||||||
|
|
||||||
extern u32 b3_allocCalls, b3_maxAllocCalls;
|
extern u32 b3_allocCalls, b3_maxAllocCalls;
|
||||||
extern u32 b3_gjkCalls, b3_gjkIters, b3_gjkMaxIters;
|
extern u32 b3_gjkCalls, b3_gjkIters, b3_gjkMaxIters;
|
||||||
@ -34,22 +35,24 @@ void b3PopProfileScope()
|
|||||||
}
|
}
|
||||||
|
|
||||||
Settings* g_settings = nullptr;
|
Settings* g_settings = nullptr;
|
||||||
|
TestSettings* g_testSettings = nullptr;
|
||||||
|
|
||||||
Test::Test()
|
Test::Test() : m_bodyDragger(&m_bodyRay, &m_world)
|
||||||
{
|
{
|
||||||
b3_allocCalls = 0;
|
b3_allocCalls = 0;
|
||||||
b3_gjkCalls = 0;
|
b3_gjkCalls = 0;
|
||||||
b3_gjkIters = 0;
|
b3_gjkIters = 0;
|
||||||
b3_gjkMaxIters = 0;
|
b3_gjkMaxIters = 0;
|
||||||
b3_convexCache = g_settings->convexCache;
|
b3_convexCache = g_testSettings->convexCache;
|
||||||
b3_convexCalls = 0;
|
b3_convexCalls = 0;
|
||||||
b3_convexCacheHits = 0;
|
b3_convexCacheHits = 0;
|
||||||
b3Draw_draw = g_debugDraw;
|
b3Draw_draw = g_draw;
|
||||||
|
|
||||||
m_world.SetContactListener(this);
|
m_world.SetContactListener(this);
|
||||||
|
|
||||||
m_rayHit.shape = NULL;
|
m_bodyRay.origin.SetZero();
|
||||||
m_mouseJoint = NULL;
|
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_groundHull.Set(50.0f, 1.0f, 50.0f);
|
||||||
m_groundMesh.BuildTree();
|
m_groundMesh.BuildTree();
|
||||||
@ -73,57 +76,44 @@ void Test::Step()
|
|||||||
b3_gjkCalls = 0;
|
b3_gjkCalls = 0;
|
||||||
b3_gjkIters = 0;
|
b3_gjkIters = 0;
|
||||||
b3_gjkMaxIters = 0;
|
b3_gjkMaxIters = 0;
|
||||||
b3_convexCache = g_settings->convexCache;
|
b3_convexCache = g_testSettings->convexCache;
|
||||||
b3_convexCalls = 0;
|
b3_convexCalls = 0;
|
||||||
b3_convexCacheHits = 0;
|
b3_convexCacheHits = 0;
|
||||||
|
|
||||||
float32 dt = g_settings->inv_hertz;
|
|
||||||
|
|
||||||
// Step
|
// Step
|
||||||
m_world.SetSleeping(g_settings->sleep);
|
float32 dt = g_testSettings->inv_hertz;
|
||||||
m_world.SetWarmStart(g_settings->warmStart);
|
|
||||||
m_world.Step(dt, g_settings->velocityIterations, g_settings->positionIterations);
|
|
||||||
|
|
||||||
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;
|
u32 drawFlags = 0;
|
||||||
drawFlags += g_settings->drawBounds * b3Draw::e_aabbsFlag;
|
drawFlags += g_testSettings->drawBounds * b3Draw::e_aabbsFlag;
|
||||||
drawFlags += g_settings->drawVerticesEdges * b3Draw::e_shapesFlag;
|
drawFlags += g_testSettings->drawShapes * b3Draw::e_shapesFlag;
|
||||||
drawFlags += g_settings->drawCenterOfMasses * b3Draw::e_centerOfMassesFlag;
|
drawFlags += g_testSettings->drawCenterOfMasses * b3Draw::e_centerOfMassesFlag;
|
||||||
drawFlags += g_settings->drawJoints * b3Draw::e_jointsFlag;
|
drawFlags += g_testSettings->drawJoints * b3Draw::e_jointsFlag;
|
||||||
drawFlags += g_settings->drawContactPoints * b3Draw::e_contactPointsFlag;
|
drawFlags += g_testSettings->drawContactPoints * b3Draw::e_contactPointsFlag;
|
||||||
drawFlags += g_settings->drawContactNormals * b3Draw::e_contactNormalsFlag;
|
drawFlags += g_testSettings->drawContactNormals * b3Draw::e_contactNormalsFlag;
|
||||||
drawFlags += g_settings->drawContactTangents * b3Draw::e_contactTangentsFlag;
|
drawFlags += g_testSettings->drawContactTangents * b3Draw::e_contactTangentsFlag;
|
||||||
drawFlags += g_settings->drawContactPolygons * b3Draw::e_contactPolygonsFlag;
|
drawFlags += g_testSettings->drawContactPolygons * b3Draw::e_contactPolygonsFlag;
|
||||||
|
|
||||||
g_debugDraw->SetFlags(drawFlags);
|
g_draw->SetFlags(drawFlags);
|
||||||
|
|
||||||
m_world.Draw();
|
m_world.Draw();
|
||||||
|
|
||||||
if (m_mouseJoint)
|
|
||||||
{
|
|
||||||
b3Shape* shape = m_rayHit.shape;
|
|
||||||
b3Body* body = shape->GetBody();
|
|
||||||
|
|
||||||
b3Vec3 n = body->GetWorldVector(m_rayHit.normal);
|
g_draw->Flush();
|
||||||
b3Vec3 p = body->GetWorldPoint(m_rayHit.point);
|
|
||||||
|
|
||||||
g_debugDraw->DrawSolidCircle(n, p + 0.05f * n, 1.0f, b3Color_white);
|
|
||||||
}
|
|
||||||
|
|
||||||
g_debugDraw->Submit();
|
if (g_settings->drawTriangles)
|
||||||
|
|
||||||
if (g_settings->drawFaces)
|
|
||||||
{
|
{
|
||||||
g_debugDraw->Draw(m_world);
|
g_draw->DrawSolidShapes(m_world);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (g_settings->drawStats)
|
if (g_settings->drawStats)
|
||||||
{
|
{
|
||||||
g_debugDraw->DrawString(b3Color_white, "Bodies %d", m_world.GetBodyList().m_count);
|
g_draw->DrawString(b3Color_white, "Bodies %d", m_world.GetBodyList().m_count);
|
||||||
g_debugDraw->DrawString(b3Color_white, "Joints %d", m_world.GetJointList().m_count);
|
g_draw->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, "Contacts %d", m_world.GetContactList().m_count);
|
||||||
|
|
||||||
float32 avgGjkIters = 0.0f;
|
float32 avgGjkIters = 0.0f;
|
||||||
if (b3_gjkCalls > 0)
|
if (b3_gjkCalls > 0)
|
||||||
@ -131,8 +121,8 @@ void Test::Step()
|
|||||||
avgGjkIters = float32(b3_gjkIters) / float32(b3_gjkCalls);
|
avgGjkIters = float32(b3_gjkIters) / float32(b3_gjkCalls);
|
||||||
}
|
}
|
||||||
|
|
||||||
g_debugDraw->DrawString(b3Color_white, "GJK Calls %d", b3_gjkCalls);
|
g_draw->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 Iterations %d (%d) (%f)", b3_gjkIters, b3_gjkMaxIters, avgGjkIters);
|
||||||
|
|
||||||
float32 convexCacheHitRatio = 0.0f;
|
float32 convexCacheHitRatio = 0.0f;
|
||||||
if (b3_convexCalls > 0)
|
if (b3_convexCalls > 0)
|
||||||
@ -140,84 +130,39 @@ void Test::Step()
|
|||||||
convexCacheHitRatio = float32(b3_convexCacheHits) / float32(b3_convexCalls);
|
convexCacheHitRatio = float32(b3_convexCacheHits) / float32(b3_convexCalls);
|
||||||
}
|
}
|
||||||
|
|
||||||
g_debugDraw->DrawString(b3Color_white, "Convex Calls %d", b3_convexCalls);
|
g_draw->DrawString(b3Color_white, "Convex Calls %d", b3_convexCalls);
|
||||||
g_debugDraw->DrawString(b3Color_white, "Convex Cache Hits %d (%f)", b3_convexCacheHits, convexCacheHitRatio);
|
g_draw->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, "Frame Allocations %d (%d)", b3_allocCalls, b3_maxAllocCalls);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Test::MouseMove(const Ray3& pw)
|
void Test::MouseMove(const Ray3& pw)
|
||||||
{
|
{
|
||||||
if (m_mouseJoint)
|
m_bodyRay = pw;
|
||||||
{
|
|
||||||
float32 t = m_rayHit.fraction;
|
|
||||||
float32 w1 = 1.0f - t;
|
|
||||||
float32 w2 = t;
|
|
||||||
|
|
||||||
b3Vec3 target = w1 * pw.A() + w2 * pw.B();
|
if (m_bodyDragger.IsSelected() == true)
|
||||||
m_mouseJoint->SetTarget(target);
|
{
|
||||||
|
m_bodyDragger.Drag();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Test::MouseLeftDown(const Ray3& pw)
|
void Test::MouseLeftDown(const Ray3& pw)
|
||||||
{
|
{
|
||||||
// Clear the current hit
|
if (m_bodyDragger.IsSelected() == false)
|
||||||
m_rayHit.shape = NULL;
|
|
||||||
if (m_mouseJoint)
|
|
||||||
{
|
{
|
||||||
b3Body* groundBody = m_mouseJoint->GetBodyA();
|
if (m_bodyDragger.StartDragging() == true)
|
||||||
|
{
|
||||||
m_world.DestroyJoint(m_mouseJoint);
|
BeginDragging();
|
||||||
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();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Test::MouseLeftUp(const Ray3& pw)
|
void Test::MouseLeftUp(const Ray3& pw)
|
||||||
{
|
{
|
||||||
m_rayHit.shape = NULL;
|
if (m_bodyDragger.IsSelected() == true)
|
||||||
if (m_mouseJoint)
|
|
||||||
{
|
{
|
||||||
b3Body* groundBody = m_mouseJoint->GetBodyA();
|
m_bodyDragger.StopDragging();
|
||||||
|
|
||||||
m_world.DestroyJoint(m_mouseJoint);
|
EndDragging();
|
||||||
m_mouseJoint = NULL;
|
|
||||||
|
|
||||||
m_world.DestroyBody(groundBody);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
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 <bounce/bounce.h>
|
||||||
|
|
||||||
#include <testbed/framework/debug_draw.h>
|
#include <testbed/framework/draw.h>
|
||||||
#include <testbed/framework/profiler.h>
|
#include <testbed/framework/profiler.h>
|
||||||
#include <testbed/framework/recorder_profiler.h>
|
#include <testbed/framework/recorder_profiler.h>
|
||||||
|
|
||||||
@ -36,10 +36,9 @@ inline float32 RandomFloat(float32 a, float32 b)
|
|||||||
return a + r;
|
return a + r;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Test settings
|
struct TestSettings
|
||||||
struct Settings
|
|
||||||
{
|
{
|
||||||
Settings()
|
TestSettings()
|
||||||
{
|
{
|
||||||
hertz = 60.0f;
|
hertz = 60.0f;
|
||||||
inv_hertz = 1.0f / hertz;
|
inv_hertz = 1.0f / hertz;
|
||||||
@ -48,52 +47,34 @@ struct Settings
|
|||||||
sleep = false;
|
sleep = false;
|
||||||
warmStart = true;
|
warmStart = true;
|
||||||
convexCache = true;
|
convexCache = true;
|
||||||
drawCenterOfMasses = false;
|
drawCenterOfMasses = true;
|
||||||
drawVerticesEdges = true;
|
drawShapes = true;
|
||||||
drawFaces = true;
|
|
||||||
drawBounds = false;
|
drawBounds = false;
|
||||||
drawJoints = true;
|
drawJoints = true;
|
||||||
drawContactPoints = true;
|
drawContactPoints = true;
|
||||||
drawContactNormals = false;
|
drawContactNormals = false;
|
||||||
drawContactTangents = false;
|
drawContactTangents = false;
|
||||||
drawContactPolygons = false;
|
drawContactPolygons = false;
|
||||||
drawStats = false;
|
|
||||||
drawProfile = false;
|
|
||||||
drawGrid = true;
|
|
||||||
pause = false;
|
|
||||||
singleStep = false;
|
|
||||||
lastTestID = -1;
|
|
||||||
testID = 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int lastTestID;
|
float hertz, inv_hertz;
|
||||||
int testID;
|
|
||||||
bool pause;
|
|
||||||
bool singleStep;
|
|
||||||
|
|
||||||
float32 hertz, inv_hertz;
|
|
||||||
int velocityIterations;
|
int velocityIterations;
|
||||||
int positionIterations;
|
int positionIterations;
|
||||||
bool sleep;
|
bool sleep;
|
||||||
bool warmStart;
|
bool warmStart;
|
||||||
bool convexCache;
|
bool convexCache;
|
||||||
|
|
||||||
bool drawCenterOfMasses;
|
bool drawCenterOfMasses;
|
||||||
bool drawBounds;
|
bool drawBounds;
|
||||||
bool drawVerticesEdges;
|
bool drawShapes;
|
||||||
bool drawFaces;
|
|
||||||
bool drawSolidShapes;
|
|
||||||
bool drawJoints;
|
bool drawJoints;
|
||||||
bool drawContactPoints;
|
bool drawContactPoints;
|
||||||
bool drawContactNormals;
|
bool drawContactNormals;
|
||||||
bool drawContactTangents;
|
bool drawContactTangents;
|
||||||
bool drawContactPolygons;
|
bool drawContactPolygons;
|
||||||
bool drawStats;
|
|
||||||
bool drawProfile;
|
|
||||||
bool drawGrid;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
extern Settings* g_settings;
|
extern TestSettings* g_testSettings;
|
||||||
|
|
||||||
class RayCastListener : public b3RayCastListener
|
class RayCastListener : public b3RayCastListener
|
||||||
{
|
{
|
||||||
@ -110,6 +91,110 @@ public:
|
|||||||
b3RayCastSingleOutput hit;
|
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
|
class Test : public b3ContactListener
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
@ -120,21 +205,23 @@ public:
|
|||||||
|
|
||||||
virtual void Step();
|
virtual void Step();
|
||||||
|
|
||||||
virtual void RayHit();
|
|
||||||
|
|
||||||
virtual void MouseMove(const Ray3& pw);
|
virtual void MouseMove(const Ray3& pw);
|
||||||
virtual void MouseLeftDown(const Ray3& pw);
|
virtual void MouseLeftDown(const Ray3& pw);
|
||||||
virtual void MouseLeftUp(const Ray3& pw);
|
virtual void MouseLeftUp(const Ray3& pw);
|
||||||
virtual void KeyDown(int button) { }
|
virtual void KeyDown(int button) { }
|
||||||
virtual void KeyUp(int button) { }
|
virtual void KeyUp(int button) { }
|
||||||
|
|
||||||
virtual void BeginContact(b3Contact* contact) { }
|
virtual void BeginDragging() { }
|
||||||
virtual void EndContact(b3Contact* contact) { }
|
virtual void EndDragging() { }
|
||||||
virtual void PreSolve(b3Contact* contact) { }
|
|
||||||
|
void BeginContact(b3Contact* c) override { }
|
||||||
|
void EndContact(b3Contact* c) override { }
|
||||||
|
void PreSolve(b3Contact* c) override { }
|
||||||
|
|
||||||
b3World m_world;
|
b3World m_world;
|
||||||
b3RayCastSingleOutput m_rayHit;
|
|
||||||
b3MouseJoint* m_mouseJoint;
|
Ray3 m_bodyRay;
|
||||||
|
BodyDragger m_bodyDragger;
|
||||||
|
|
||||||
b3BoxHull m_groundHull;
|
b3BoxHull m_groundHull;
|
||||||
b3GridMesh<50, 50> m_groundMesh;
|
b3GridMesh<50, 50> m_groundMesh;
|
||||||
|
@ -28,11 +28,11 @@
|
|||||||
#include <testbed/tests/hull_collision_2.h>
|
#include <testbed/tests/hull_collision_2.h>
|
||||||
#include <testbed/tests/linear_motion.h>
|
#include <testbed/tests/linear_motion.h>
|
||||||
#include <testbed/tests/angular_motion.h>
|
#include <testbed/tests/angular_motion.h>
|
||||||
|
#include <testbed/tests/gyro_motion.h>
|
||||||
#include <testbed/tests/initial_overlap.h>
|
#include <testbed/tests/initial_overlap.h>
|
||||||
#include <testbed/tests/capsule_and_hull_contact_1.h>
|
#include <testbed/tests/capsule_and_hull_contact_1.h>
|
||||||
#include <testbed/tests/quadric_shapes.h>
|
#include <testbed/tests/quadric_shapes.h>
|
||||||
#include <testbed/tests/multiple_shapes.h>
|
#include <testbed/tests/compound_body.h>
|
||||||
#include <testbed/tests/gyro_test.h>
|
|
||||||
#include <testbed/tests/spring.h>
|
#include <testbed/tests/spring.h>
|
||||||
#include <testbed/tests/weld_test.h>
|
#include <testbed/tests/weld_test.h>
|
||||||
#include <testbed/tests/cone_test.h>
|
#include <testbed/tests/cone_test.h>
|
||||||
@ -44,14 +44,14 @@
|
|||||||
#include <testbed/tests/sphere_stack.h>
|
#include <testbed/tests/sphere_stack.h>
|
||||||
#include <testbed/tests/capsule_stack.h>
|
#include <testbed/tests/capsule_stack.h>
|
||||||
#include <testbed/tests/box_stack.h>
|
#include <testbed/tests/box_stack.h>
|
||||||
|
#include <testbed/tests/sheet_stack.h>
|
||||||
#include <testbed/tests/shape_stack.h>
|
#include <testbed/tests/shape_stack.h>
|
||||||
#include <testbed/tests/jenga.h>
|
#include <testbed/tests/jenga.h>
|
||||||
#include <testbed/tests/thin.h>
|
|
||||||
#include <testbed/tests/pyramid.h>
|
#include <testbed/tests/pyramid.h>
|
||||||
#include <testbed/tests/pyramids.h>
|
#include <testbed/tests/pyramids.h>
|
||||||
#include <testbed/tests/ray_cast.h>
|
#include <testbed/tests/ray_cast.h>
|
||||||
#include <testbed/tests/sensor_test.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/body_types.h>
|
||||||
#include <testbed/tests/varying_friction.h>
|
#include <testbed/tests/varying_friction.h>
|
||||||
#include <testbed/tests/varying_restitution.h>
|
#include <testbed/tests/varying_restitution.h>
|
||||||
@ -78,12 +78,12 @@ TestEntry g_tests[] =
|
|||||||
{ "Hull Collision (1)", &HullAndHull::Create },
|
{ "Hull Collision (1)", &HullAndHull::Create },
|
||||||
{ "Hull Collision (2)", &HullAndHull2::Create },
|
{ "Hull Collision (2)", &HullAndHull2::Create },
|
||||||
{ "Capsule and Hull Contact (1)", &CapsuleAndHullContact1::Create },
|
{ "Capsule and Hull Contact (1)", &CapsuleAndHullContact1::Create },
|
||||||
|
{ "Mesh Contact Test", &MeshContactTest::Create },
|
||||||
{ "Linear Motion", &LinearMotion::Create },
|
{ "Linear Motion", &LinearMotion::Create },
|
||||||
{ "Angular Motion", &AngularMotion::Create },
|
{ "Angular Motion", &AngularMotion::Create },
|
||||||
{ "Multiple Shapes", &MultipleShapes::Create },
|
{ "Gyroscopic Motion", &GyroMotion::Create },
|
||||||
|
{ "Compound Body", &CompoundBody::Create },
|
||||||
{ "Quadric Shapes", &QuadricShapes::Create },
|
{ "Quadric Shapes", &QuadricShapes::Create },
|
||||||
{ "Thin Boxes", &Thin::Create },
|
|
||||||
{ "Gyroscopic Test", &GyroTest::Create },
|
|
||||||
{ "Springs", &Spring::Create },
|
{ "Springs", &Spring::Create },
|
||||||
{ "Weld Test", &WeldTest::Create },
|
{ "Weld Test", &WeldTest::Create },
|
||||||
{ "Cone Test", &ConeTest::Create },
|
{ "Cone Test", &ConeTest::Create },
|
||||||
@ -91,17 +91,17 @@ TestEntry g_tests[] =
|
|||||||
{ "Hinge Chain", &HingeChain::Create },
|
{ "Hinge Chain", &HingeChain::Create },
|
||||||
{ "Ragdoll", &Ragdoll::Create },
|
{ "Ragdoll", &Ragdoll::Create },
|
||||||
{ "Newton's Cradle", &NewtonCradle::Create },
|
{ "Newton's Cradle", &NewtonCradle::Create },
|
||||||
{ "Mesh Contact Test", &MeshContactTest::Create },
|
|
||||||
{ "Sphere Stack", &SphereStack::Create },
|
{ "Sphere Stack", &SphereStack::Create },
|
||||||
{ "Capsule Stack", &CapsuleStack::Create },
|
{ "Capsule Stack", &CapsuleStack::Create },
|
||||||
{ "Box Stack", &BoxStack::Create },
|
{ "Box Stack", &BoxStack::Create },
|
||||||
|
{ "Sheet Stack", &SheetStack::Create },
|
||||||
{ "Shape Stack", &ShapeStack::Create },
|
{ "Shape Stack", &ShapeStack::Create },
|
||||||
{ "Jenga", &Jenga::Create },
|
{ "Jenga", &Jenga::Create },
|
||||||
{ "Box Pyramid", &Pyramid::Create },
|
{ "Box Pyramid", &Pyramid::Create },
|
||||||
{ "Box Pyramid Rows", &Pyramids::Create },
|
{ "Box Pyramid Rows", &Pyramids::Create },
|
||||||
{ "Ray Cast", &RayCast::Create },
|
{ "Ray Cast", &RayCast::Create },
|
||||||
{ "Sensor Test", &SensorTest::Create },
|
{ "Sensor Test", &SensorTest::Create },
|
||||||
{ "Character Test", &Character::Create },
|
{ "Point & Click", &PointClick::Create },
|
||||||
{ "Body Types", &BodyTypes::Create },
|
{ "Body Types", &BodyTypes::Create },
|
||||||
{ "Varying Friction", &VaryingFriction::Create },
|
{ "Varying Friction", &VaryingFriction::Create },
|
||||||
{ "Varying Restitution", &VaryingRestitution::Create },
|
{ "Varying Restitution", &VaryingRestitution::Create },
|
||||||
|
@ -24,7 +24,6 @@
|
|||||||
#elif defined (U_OPENGL_4)
|
#elif defined (U_OPENGL_4)
|
||||||
#include <imgui/imgui_impl_glfw_gl3.h>
|
#include <imgui/imgui_impl_glfw_gl3.h>
|
||||||
#else
|
#else
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
static bool GetTestName(void* userData, int idx, const char** name)
|
static bool GetTestName(void* userData, int idx, const char** name)
|
||||||
@ -147,6 +146,7 @@ void View::Command_Draw()
|
|||||||
{
|
{
|
||||||
Camera& camera = m_model->m_camera;
|
Camera& camera = m_model->m_camera;
|
||||||
Settings& settings = m_model->m_settings;
|
Settings& settings = m_model->m_settings;
|
||||||
|
TestSettings& testSettings = m_model->m_testSettings;
|
||||||
|
|
||||||
bool openAbout = false;
|
bool openAbout = false;
|
||||||
if (ImGui::BeginMainMenuBar())
|
if (ImGui::BeginMainMenuBar())
|
||||||
@ -170,24 +170,29 @@ void View::Command_Draw()
|
|||||||
|
|
||||||
if (ImGui::BeginMenu("View"))
|
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("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();
|
ImGui::EndMenu();
|
||||||
}
|
}
|
||||||
@ -307,17 +312,17 @@ void View::Command_Draw()
|
|||||||
ImGui::PushItemWidth(-1.0f);
|
ImGui::PushItemWidth(-1.0f);
|
||||||
|
|
||||||
ImGui::Text("Hertz");
|
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::Text("Velocity Iterations");
|
||||||
ImGui::SliderInt("##Velocity Iterations", &settings.velocityIterations, 0, 50);
|
ImGui::SliderInt("##Velocity Iterations", &testSettings.velocityIterations, 0, 50);
|
||||||
|
|
||||||
ImGui::Text("Position Iterations");
|
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("Sleep", &testSettings.sleep);
|
||||||
ImGui::Checkbox("Convex Cache", &settings.convexCache);
|
ImGui::Checkbox("Convex Cache", &testSettings.convexCache);
|
||||||
ImGui::Checkbox("Warm Start", &settings.warmStart);
|
ImGui::Checkbox("Warm Start", &testSettings.warmStart);
|
||||||
|
|
||||||
ImGui::PopItemWidth();
|
ImGui::PopItemWidth();
|
||||||
|
|
||||||
|
@ -64,11 +64,11 @@ public:
|
|||||||
{
|
{
|
||||||
Test::Step();
|
Test::Step();
|
||||||
|
|
||||||
g_debugDraw->DrawString(b3Color_white, "S - Static");
|
g_draw->DrawString(b3Color_white, "S - Static");
|
||||||
g_debugDraw->DrawString(b3Color_white, "D - Dynamic");
|
g_draw->DrawString(b3Color_white, "D - Dynamic");
|
||||||
g_debugDraw->DrawString(b3Color_white, "K - Kinematic");
|
g_draw->DrawString(b3Color_white, "K - Kinematic");
|
||||||
g_debugDraw->DrawString(b3Color_white, "Space - Throw Bomb");
|
g_draw->DrawString(b3Color_white, "Space - Throw Bomb");
|
||||||
g_debugDraw->DrawString(b3Color_white, "Arrows - Apply Force/Velocity/Position");
|
g_draw->DrawString(b3Color_white, "Arrows - Apply Force/Velocity/Position");
|
||||||
}
|
}
|
||||||
|
|
||||||
void KeyDown(int button)
|
void KeyDown(int button)
|
||||||
|
@ -51,7 +51,7 @@ public:
|
|||||||
|
|
||||||
void Step()
|
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();
|
m_cloth.Draw();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -61,15 +61,15 @@ public:
|
|||||||
|
|
||||||
for (u32 i = 0; i < clusters.Count(); ++i)
|
for (u32 i = 0; i < clusters.Count(); ++i)
|
||||||
{
|
{
|
||||||
g_debugDraw->DrawSegment(b3Vec3(0, 0, 0), clusters[i].centroid, b3Color(1, 1, 1));
|
g_draw->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->DrawPoint(clusters[i].centroid, 4.0f, m_colors[i]);
|
||||||
|
|
||||||
for (u32 j = 0; j < observations.Count(); ++j)
|
for (u32 j = 0; j < observations.Count(); ++j)
|
||||||
{
|
{
|
||||||
b3Observation obs = observations[j];
|
b3Observation obs = observations[j];
|
||||||
if (obs.cluster == i)
|
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;
|
b3Vec3 pw = wm.points[i].point;
|
||||||
b3Vec2 ps = g_camera->ConvertWorldToScreen(pw);
|
b3Vec2 ps = g_camera->ConvertWorldToScreen(pw);
|
||||||
|
|
||||||
g_debugDraw->DrawPoint(pw, 4.0f, b3Color(0.0f, 1.0f, 0.0f));
|
g_draw->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->DrawSegment(pw, pw + wm.points[i].normal, b3Color(1.0f, 1.0f, 1.0f));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (g_settings->drawFaces)
|
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);
|
||||||
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);
|
m_world.DrawShape(m_xfA, m_shapeA);
|
||||||
}
|
m_world.DrawShape(m_xfB, m_shapeB);
|
||||||
|
|
||||||
if (g_settings->drawVerticesEdges)
|
|
||||||
{
|
|
||||||
m_world.DrawShape(m_xfA, m_shapeA);
|
|
||||||
m_world.DrawShape(m_xfB, m_shapeB);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void KeyDown(int key)
|
virtual void KeyDown(int key)
|
||||||
|
@ -16,13 +16,13 @@
|
|||||||
* 3. This notice may not be removed or altered from any source distribution.
|
* 3. This notice may not be removed or altered from any source distribution.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef MULTIPLE_SHAPES_H
|
#ifndef COMPOUND_BODY_H
|
||||||
#define MULTIPLE_SHAPES_H
|
#define COMPOUND_BODY_H
|
||||||
|
|
||||||
class MultipleShapes : public Test
|
class CompoundBody : public Test
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
MultipleShapes()
|
CompoundBody()
|
||||||
{
|
{
|
||||||
{
|
{
|
||||||
b3BodyDef bd;
|
b3BodyDef bd;
|
||||||
@ -76,7 +76,7 @@ public:
|
|||||||
b3BodyDef bd;
|
b3BodyDef bd;
|
||||||
bd.type = e_dynamicBody;
|
bd.type = e_dynamicBody;
|
||||||
bd.position.Set(0.0f, 0.0f, 0.0f);
|
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);
|
b3Body* body = m_world.CreateBody(bd);
|
||||||
|
|
||||||
@ -105,7 +105,7 @@ public:
|
|||||||
|
|
||||||
static Test* Create()
|
static Test* Create()
|
||||||
{
|
{
|
||||||
return new MultipleShapes();
|
return new CompoundBody();
|
||||||
}
|
}
|
||||||
|
|
||||||
b3BoxHull m_box1;
|
b3BoxHull m_box1;
|
@ -51,22 +51,22 @@ public:
|
|||||||
for (u32 i = 0; i < featurePair.count1; ++i)
|
for (u32 i = 0; i < featurePair.count1; ++i)
|
||||||
{
|
{
|
||||||
u32 index = featurePair.index1[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)
|
for (u32 i = 0; i < featurePair.count2; ++i)
|
||||||
{
|
{
|
||||||
u32 index = featurePair.index2[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_draw->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_draw->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->DrawSegment(out.point1, out.point2, b3Color(1.0f, 1.0f, 1.0f));
|
||||||
|
|
||||||
g_debugDraw->DrawTransform(m_xfA);
|
g_draw->DrawTransform(m_xfA);
|
||||||
g_debugDraw->DrawTransform(m_xfB);
|
g_draw->DrawTransform(m_xfB);
|
||||||
|
|
||||||
m_world.DrawShape(m_xfA, &m_shapeA);
|
m_world.DrawShape(m_xfA, &m_shapeA);
|
||||||
m_world.DrawShape(m_xfB, &m_shapeB);
|
m_world.DrawShape(m_xfB, &m_shapeB);
|
||||||
|
@ -16,15 +16,15 @@
|
|||||||
* 3. This notice may not be removed or altered from any source distribution.
|
* 3. This notice may not be removed or altered from any source distribution.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef GYRO_TEST_H
|
#ifndef GYRO_MOTION_H
|
||||||
#define GYRO_TEST_H
|
#define GYRO_MOTION_H
|
||||||
|
|
||||||
#include <testbed/tests/quickhull_test.h>
|
#include <testbed/tests/quickhull_test.h>
|
||||||
|
|
||||||
class GyroTest : public Test
|
class GyroMotion : public Test
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
GyroTest()
|
GyroMotion()
|
||||||
{
|
{
|
||||||
{
|
{
|
||||||
b3StackArray<b3Vec3, 32> points;
|
b3StackArray<b3Vec3, 32> points;
|
||||||
@ -63,10 +63,7 @@ public:
|
|||||||
b3Body* body = m_world.CreateBody(bdef);
|
b3Body* body = m_world.CreateBody(bdef);
|
||||||
|
|
||||||
{
|
{
|
||||||
b3Transform xf;
|
m_rotorBox.Set(1.0f, 0.5f, 7.0f);
|
||||||
xf.position.SetZero();
|
|
||||||
xf.rotation = b3Diagonal(1.0f, 0.5f, 7.0f);
|
|
||||||
m_rotorBox.SetTransform(xf);
|
|
||||||
|
|
||||||
b3HullShape hull;
|
b3HullShape hull;
|
||||||
hull.m_hull = &m_rotorBox;
|
hull.m_hull = &m_rotorBox;
|
||||||
@ -93,7 +90,7 @@ public:
|
|||||||
m_world.SetGravity(b3Vec3(0.0f, 0.0f, 0.0f));
|
m_world.SetGravity(b3Vec3(0.0f, 0.0f, 0.0f));
|
||||||
}
|
}
|
||||||
|
|
||||||
~GyroTest()
|
~GyroMotion()
|
||||||
{
|
{
|
||||||
{
|
{
|
||||||
b3Free(m_cylinderHull.vertices);
|
b3Free(m_cylinderHull.vertices);
|
||||||
@ -105,7 +102,7 @@ public:
|
|||||||
|
|
||||||
static Test* Create()
|
static Test* Create()
|
||||||
{
|
{
|
||||||
return new GyroTest();
|
return new GyroMotion();
|
||||||
}
|
}
|
||||||
|
|
||||||
b3BoxHull m_rotorBox;
|
b3BoxHull m_rotorBox;
|
@ -126,18 +126,18 @@ public:
|
|||||||
|
|
||||||
void Step()
|
void Step()
|
||||||
{
|
{
|
||||||
float32 h = g_settings->inv_hertz;
|
float32 h = g_testSettings->inv_hertz;
|
||||||
|
|
||||||
Solve(h);
|
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);
|
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()
|
static Test* Create()
|
||||||
|
@ -163,11 +163,11 @@ public:
|
|||||||
{
|
{
|
||||||
Test::Step();
|
Test::Step();
|
||||||
|
|
||||||
g_debugDraw->DrawString(b3Color_white, "S - Sphere");
|
g_draw->DrawString(b3Color_white, "S - Sphere");
|
||||||
g_debugDraw->DrawString(b3Color_white, "C - Capsule");
|
g_draw->DrawString(b3Color_white, "C - Capsule");
|
||||||
g_debugDraw->DrawString(b3Color_white, "H - Hull");
|
g_draw->DrawString(b3Color_white, "H - Hull");
|
||||||
g_debugDraw->DrawString(b3Color_white, "G - Grid");
|
g_draw->DrawString(b3Color_white, "G - Grid");
|
||||||
g_debugDraw->DrawString(b3Color_white, "T - Terrain");
|
g_draw->DrawString(b3Color_white, "T - Terrain");
|
||||||
}
|
}
|
||||||
|
|
||||||
static Test* Create()
|
static Test* Create()
|
||||||
|
@ -16,13 +16,13 @@
|
|||||||
* 3. This notice may not be removed or altered from any source distribution.
|
* 3. This notice may not be removed or altered from any source distribution.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef CHARACTER_H
|
#ifndef POINT_CLICK_H
|
||||||
#define CHARACTER_H
|
#define POINT_CLICK_H
|
||||||
|
|
||||||
class Character : public Test
|
class PointClick : public Test
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
Character()
|
PointClick()
|
||||||
{
|
{
|
||||||
{
|
{
|
||||||
b3BodyDef bdef;
|
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)
|
m_bodyDragger.StopDragging();
|
||||||
{
|
|
||||||
Test::RayHit();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Step()
|
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 p1 = m_character->GetPosition();
|
||||||
b3Vec3 normal = m_rayHit.normal;
|
b3Vec3 p2 = m_bodyDragger.GetPointA();
|
||||||
|
|
||||||
const b3Transform& xf = m_character->GetTransform();
|
|
||||||
b3Vec3 n = point - xf.position;
|
|
||||||
n.Normalize();
|
|
||||||
|
|
||||||
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()
|
static Test* Create()
|
||||||
{
|
{
|
||||||
return new Character();
|
return new PointClick();
|
||||||
}
|
}
|
||||||
|
|
||||||
b3Body* m_character;
|
b3Body* m_character;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
@ -317,7 +317,7 @@ public:
|
|||||||
|
|
||||||
void Step()
|
void Step()
|
||||||
{
|
{
|
||||||
m_qhull.Draw(g_debugDraw);
|
m_qhull.Draw(g_draw);
|
||||||
}
|
}
|
||||||
|
|
||||||
static Test* Create()
|
static Test* Create()
|
||||||
|
@ -181,22 +181,20 @@ public:
|
|||||||
b3RayCastSingleOutput out;
|
b3RayCastSingleOutput out;
|
||||||
if (m_world.RayCastSingle(&out, p1, p2))
|
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_draw->DrawPoint(out.point, 4.0f, b3Color_red);
|
||||||
g_debugDraw->DrawSegment(out.point, out.point + out.normal, b3Color_white);
|
g_draw->DrawSegment(out.point, out.point + out.normal, b3Color_white);
|
||||||
|
|
||||||
g_debugDraw->DrawSolidCircle(out.normal, out.point + 0.025f * out.normal, 1.0f, b3Color_white);
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
g_debugDraw->DrawSegment(p1, p2, b3Color_green);
|
g_draw->DrawSegment(p1, p2, b3Color_green);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Step()
|
void Step()
|
||||||
{
|
{
|
||||||
float32 dt = g_settings->inv_hertz;
|
float32 dt = g_testSettings->inv_hertz;
|
||||||
b3Quat dq = b3QuatRotationY(0.05f * B3_PI * dt);
|
b3Quat dq = b3QuatRotationY(0.05f * B3_PI * dt);
|
||||||
|
|
||||||
m_p1 = b3Mul(dq, m_p1);
|
m_p1 = b3Mul(dq, m_p1);
|
||||||
|
@ -85,7 +85,7 @@ public:
|
|||||||
|
|
||||||
void Step()
|
void Step()
|
||||||
{
|
{
|
||||||
m_rope.Step(g_settings->inv_hertz);
|
m_rope.Step(g_testSettings->inv_hertz);
|
||||||
m_rope.Draw();
|
m_rope.Draw();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -16,10 +16,10 @@
|
|||||||
* 3. This notice may not be removed or altered from any source distribution.
|
* 3. This notice may not be removed or altered from any source distribution.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef THIN_H
|
#ifndef SHEET_STACK_H
|
||||||
#define THIN_H
|
#define SHEET_STACK_H
|
||||||
|
|
||||||
class Thin : public Test
|
class SheetStack : public Test
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
enum
|
enum
|
||||||
@ -29,7 +29,7 @@ public:
|
|||||||
e_depthCount = 1
|
e_depthCount = 1
|
||||||
};
|
};
|
||||||
|
|
||||||
Thin()
|
SheetStack()
|
||||||
{
|
{
|
||||||
{
|
{
|
||||||
b3BodyDef bdef;
|
b3BodyDef bdef;
|
||||||
@ -47,22 +47,12 @@ public:
|
|||||||
b3Shape* shape = body->CreateShape(sdef);
|
b3Shape* shape = body->CreateShape(sdef);
|
||||||
}
|
}
|
||||||
|
|
||||||
static b3BoxHull thinHull;
|
static b3Vec3 sheetExtents(4.05f, 2.0f * B3_LINEAR_SLOP, 4.05f);
|
||||||
|
static b3BoxHull sheetHull(sheetExtents.x, sheetExtents.y, sheetExtents.z);
|
||||||
{
|
|
||||||
b3Transform xf;
|
|
||||||
xf.position.SetZero();
|
|
||||||
xf.rotation = b3Diagonal(4.05f, 2.0f * B3_LINEAR_SLOP, 4.05f);
|
|
||||||
|
|
||||||
thinHull.SetTransform(xf);
|
|
||||||
}
|
|
||||||
|
|
||||||
b3Vec3 stackOrigin;
|
b3Vec3 stackOrigin;
|
||||||
stackOrigin.Set(0.0f, 4.05f, 0.0f);
|
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 i = 0; i < e_rowCount; ++i)
|
||||||
{
|
{
|
||||||
for (u32 j = 0; j < e_columnCount; ++j)
|
for (u32 j = 0; j < e_columnCount; ++j)
|
||||||
@ -72,15 +62,15 @@ public:
|
|||||||
b3BodyDef bdef;
|
b3BodyDef bdef;
|
||||||
bdef.type = b3BodyType::e_dynamicBody;
|
bdef.type = b3BodyType::e_dynamicBody;
|
||||||
|
|
||||||
bdef.position.x = float32(i) * boxScale.x;
|
bdef.position.x = float32(i) * sheetExtents.x;
|
||||||
bdef.position.y = 1.5f * float32(j) * boxScale.y;
|
bdef.position.y = float32(j) * 50.0f * sheetExtents.y;
|
||||||
bdef.position.z = float32(k) * boxScale.z;
|
bdef.position.z = float32(k) * sheetExtents.z;
|
||||||
bdef.position += stackOrigin;
|
bdef.position += stackOrigin;
|
||||||
|
|
||||||
b3Body* body = m_world.CreateBody(bdef);
|
b3Body* body = m_world.CreateBody(bdef);
|
||||||
|
|
||||||
b3HullShape hs;
|
b3HullShape hs;
|
||||||
hs.m_hull = &thinHull;
|
hs.m_hull = &sheetHull;
|
||||||
|
|
||||||
b3ShapeDef sdef;
|
b3ShapeDef sdef;
|
||||||
sdef.shape = &hs;
|
sdef.shape = &hs;
|
||||||
@ -95,8 +85,8 @@ public:
|
|||||||
|
|
||||||
static Test* Create()
|
static Test* Create()
|
||||||
{
|
{
|
||||||
return new Thin();
|
return new SheetStack();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
@ -37,7 +37,7 @@ public:
|
|||||||
|
|
||||||
void Step()
|
void Step()
|
||||||
{
|
{
|
||||||
float32 h = g_settings->inv_hertz;
|
float32 h = g_testSettings->inv_hertz;
|
||||||
|
|
||||||
// Solution (acceleration)
|
// Solution (acceleration)
|
||||||
float32 omega_dot = -m_g / m_r * sin(m_theta);
|
float32 omega_dot = -m_g / m_r * sin(m_theta);
|
||||||
@ -53,11 +53,11 @@ public:
|
|||||||
c.x = m_r * sin(m_theta);
|
c.x = m_r * sin(m_theta);
|
||||||
c.y = m_r * cos(m_theta);
|
c.y = m_r * cos(m_theta);
|
||||||
c.z = 0.0f;
|
c.z = 0.0f;
|
||||||
g_debugDraw->DrawSolidSphere(c, 1.0f, b3Color_white);
|
g_draw->DrawSolidSphere(c, 1.0f, b3Color_white);
|
||||||
|
|
||||||
b3Vec3 pole;
|
b3Vec3 pole;
|
||||||
pole.SetZero();
|
pole.SetZero();
|
||||||
g_debugDraw->DrawSegment(pole, c, b3Color_white);
|
g_draw->DrawSegment(pole, c, b3Color_white);
|
||||||
|
|
||||||
// Kinetic energy
|
// Kinetic energy
|
||||||
float32 T = 0.5f * m_I * m_omega * m_omega;
|
float32 T = 0.5f * m_I * m_omega * m_omega;
|
||||||
@ -69,7 +69,7 @@ public:
|
|||||||
float32 L = T - V;
|
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()
|
static Test* Create()
|
||||||
|
@ -204,8 +204,6 @@ class SpringClothTest : public Test
|
|||||||
public:
|
public:
|
||||||
SpringClothTest() : m_clothDragger(&m_clothRay, &m_cloth)
|
SpringClothTest() : m_clothDragger(&m_clothRay, &m_cloth)
|
||||||
{
|
{
|
||||||
g_camera->m_zoom = 25.0f;
|
|
||||||
|
|
||||||
m_clothRay.origin.SetZero();
|
m_clothRay.origin.SetZero();
|
||||||
m_clothRay.direction.Set(0.0f, 0.0f, -1.0f);
|
m_clothRay.direction.Set(0.0f, 0.0f, -1.0f);
|
||||||
m_clothRay.fraction = g_camera->m_zFar;
|
m_clothRay.fraction = g_camera->m_zFar;
|
||||||
@ -213,7 +211,7 @@ public:
|
|||||||
|
|
||||||
void Step()
|
void Step()
|
||||||
{
|
{
|
||||||
float32 dt = g_settings->inv_hertz;
|
float32 dt = g_testSettings->inv_hertz;
|
||||||
|
|
||||||
m_cloth.Step(dt);
|
m_cloth.Step(dt);
|
||||||
m_cloth.Apply();
|
m_cloth.Apply();
|
||||||
@ -226,18 +224,18 @@ public:
|
|||||||
b3Transform xf;
|
b3Transform xf;
|
||||||
xf.SetIdentity();
|
xf.SetIdentity();
|
||||||
|
|
||||||
g_debugDraw->DrawShape(s, b3Color_white, xf);
|
g_draw->DrawSolidShape(s, b3Color_white, xf);
|
||||||
}
|
}
|
||||||
|
|
||||||
m_cloth.Draw();
|
m_cloth.Draw();
|
||||||
|
|
||||||
b3SpringClothStep step = m_cloth.GetStep();
|
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)
|
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()
|
void Step()
|
||||||
{
|
{
|
||||||
float32 dt = g_settings->inv_hertz;
|
float32 dt = g_testSettings->inv_hertz;
|
||||||
|
|
||||||
m_cloth.Step(dt);
|
m_cloth.Step(dt);
|
||||||
m_cloth.Apply();
|
m_cloth.Apply();
|
||||||
@ -119,17 +119,17 @@ public:
|
|||||||
|
|
||||||
b3Vec3 n2 = -n1;
|
b3Vec3 n2 = -n1;
|
||||||
|
|
||||||
g_debugDraw->DrawSolidTriangle(n1, v1, c1, v2, c2, v3, c3);
|
g_draw->DrawSolidTriangle(n1, v1, c1, v2, c2, v3, c3);
|
||||||
g_debugDraw->DrawSolidTriangle(n2, v1, c1, v3, c3, v2, c2);
|
g_draw->DrawSolidTriangle(n2, v1, c1, v3, c3, v2, c2);
|
||||||
}
|
}
|
||||||
|
|
||||||
b3SpringClothStep step = m_cloth.GetStep();
|
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)
|
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
|
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/profiler.h",
|
||||||
examples_inc_dir .. "/testbed/framework/recorder_profiler.h",
|
examples_inc_dir .. "/testbed/framework/recorder_profiler.h",
|
||||||
examples_inc_dir .. "/testbed/framework/json_profiler.h",
|
examples_inc_dir .. "/testbed/framework/json_profiler.h",
|
||||||
@ -275,6 +275,7 @@ solution (solution_name)
|
|||||||
|
|
||||||
examples_inc_dir .. "/testbed/tests/**.h",
|
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/profiler.cpp",
|
||||||
examples_src_dir .. "/testbed/framework/recorder_profiler.cpp",
|
examples_src_dir .. "/testbed/framework/recorder_profiler.cpp",
|
||||||
examples_src_dir .. "/testbed/framework/json_profiler.cpp",
|
examples_src_dir .. "/testbed/framework/json_profiler.cpp",
|
||||||
@ -292,14 +293,14 @@ solution (solution_name)
|
|||||||
if is_gfxapi("opengl_2") then
|
if is_gfxapi("opengl_2") then
|
||||||
files
|
files
|
||||||
{
|
{
|
||||||
examples_src_dir .. "/testbed/framework/debug_draw_2.cpp"
|
examples_src_dir .. "/testbed/framework/draw_gl2.h"
|
||||||
}
|
}
|
||||||
end
|
end
|
||||||
|
|
||||||
if is_gfxapi("opengl_4") then
|
if is_gfxapi("opengl_4") then
|
||||||
files
|
files
|
||||||
{
|
{
|
||||||
examples_src_dir .. "/testbed/framework/debug_draw_4.cpp"
|
examples_src_dir .. "/testbed/framework/draw_gl4.h"
|
||||||
}
|
}
|
||||||
end
|
end
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user