generate convex hull/cluster using 'G' while the tests are running

This commit is contained in:
Irlan 2018-04-20 03:13:16 -03:00
parent c413f4d8aa
commit 43f59409de
3 changed files with 125 additions and 59 deletions

View File

@ -17,8 +17,8 @@
*/
#include <testbed/framework/test.h>
#include <testbed/tests/quickhull_test.h>
#include <testbed/tests/cluster_test.h>
#include <testbed/tests/convex_hull.h>
#include <testbed/tests/cluster.h>
#include <testbed/tests/distance_test.h>
#include <testbed/tests/collide_test.h>
#include <testbed/tests/capsule_collision.h>
@ -69,9 +69,9 @@
TestEntry g_tests[] =
{
{ "Quickhull Test", &QuickhullTest::Create },
{ "Cluster Test", &Cluster::Create },
{ "Distance Test", &Distance::Create },
{ "Convex Hull", &ConvexHull::Create },
{ "Cluster", &Cluster::Create },
{ "Distance", &Distance::Create },
{ "Capsule Collision", &CapsuleCollision::Create },
{ "Deep Capsule", &DeepCapsule::Create },
{ "Degenerate Capsule", &DegenerateCapsule::Create },

View File

@ -24,45 +24,77 @@
class Cluster : public Test
{
public:
enum
{
e_count = 64
};
Cluster()
{
// Initialize observations
for (u32 i = 0; i < 90; ++i)
{
float32 x = RandomFloat(-1.0f, 1.0f);
float32 y = RandomFloat(-1.0f, 1.0f);
float32 z = RandomFloat(-1.0f, 1.0f);
b3Observation obs;
obs.point.Set(x, y, z);
obs.point = b3Normalize(obs.point);
obs.cluster = B3_NULL_CLUSTER;
Generate();
}
m_solver.AddObservation(obs);
void Generate()
{
for (u32 i = 0; i < e_count; ++i)
{
float32 x = 3.0f * RandomFloat(-1.0f, 1.0f);
float32 y = 3.0f * RandomFloat(-1.0f, 1.0f);
float32 z = 3.0f * RandomFloat(-1.0f, 1.0f);
b3Vec3 p(x, y, z);
m_points[i] = p;
}
// Initialize clusters
m_solver.Solve();
const b3Array<b3Cluster>& clusters = m_solver.GetClusters();
m_colors.Resize(clusters.Count());
for (u32 i = 0; i < clusters.Count(); ++i)
for (u32 i = 0; i < B3_MAX_MANIFOLDS; ++i)
{
m_colors[i] = b3Color(RandomFloat(0.0f, 1.0f), RandomFloat(0.0f, 1.0f), RandomFloat(0.0f, 1.0f));
float32 r = RandomFloat(0.0f, 1.0f);
float32 g = RandomFloat(0.0f, 1.0f);
float32 b = RandomFloat(0.0f, 1.0f);
b3Color c(r, g, b);
m_colors[i] = c;
}
}
void KeyDown(int button)
{
if (button == GLFW_KEY_G)
{
Generate();
}
}
void Step()
{
const b3Array<b3Observation>& observations = m_solver.GetObservations();
const b3Array<b3Cluster>& clusters = m_solver.GetClusters();
b3ClusterSolver cluster;
// Initialize observations
for (u32 i = 0; i < e_count; ++i)
{
b3Observation obs;
obs.point = m_points[i];
obs.point = b3Normalize(obs.point);
obs.cluster = B3_NULL_CLUSTER;
cluster.AddObservation(obs);
}
// Run cluster
cluster.Solve();
// Draw
const b3Array<b3Observation>& observations = cluster.GetObservations();
const b3Array<b3Cluster>& clusters = cluster.GetClusters();
B3_ASSERT(clusters.Count() <= B3_MAX_MANIFOLDS);
for (u32 i = 0; i < clusters.Count(); ++i)
{
g_draw->DrawSegment(b3Vec3(0, 0, 0), clusters[i].centroid, b3Color(1, 1, 1));
g_draw->DrawPoint(clusters[i].centroid, 4.0f, m_colors[i]);
b3Vec3 centroid = clusters[i].centroid;
g_draw->DrawSegment(b3Vec3_zero, centroid, b3Color_white);
g_draw->DrawPoint(centroid, 4.0f, m_colors[i]);
for (u32 j = 0; j < observations.Count(); ++j)
{
@ -73,6 +105,9 @@ public:
}
}
}
g_draw->DrawString(b3Color_white, "G - Generate a random cluster");
g_draw->DrawString(b3Color_white, "Iterations = %d", cluster.GetIterations());
}
static Test* Create()
@ -80,9 +115,8 @@ public:
return new Cluster();
}
b3ClusterSolver m_solver;
b3StackArray<b3Color, 32> m_colors;
b3Vec3 m_points[e_count];
b3Color m_colors[B3_MAX_MANIFOLDS];
};
#endif
#endif

View File

@ -16,65 +16,97 @@
* 3. This notice may not be removed or altered from any source distribution.
*/
#ifndef QHULL_H
#define QHULL_H
#ifndef CONVEX_HULL_H
#define CONVEX_HULL_H
#include <bounce/quickhull/qh_hull.h>
class QuickhullTest : public Test
class ConvexHull : public Test
{
public:
QuickhullTest()
enum
{
// Half to avoid generation failure due to many vertices
e_count = B3_MAX_HULL_VERTICES / 2
};
ConvexHull()
{
b3BoxHull box;
box.SetIdentity();
b3StackArray<b3Vec3, 256> tetra;
b3Vec3 tetra[4];
b3Vec3 v1(-1.0f, 0.0f, 0.0f);
b3Vec3 v2(1.0f, 0.0f, 0.0f);
b3Vec3 v3(0.0f, 0.0f, -1.0f);
b3Vec3 v4 = 0.5f * (v1 + v2 + v3);
v4.y += 2.0f;
tetra.PushBack(v1);
tetra.PushBack(v2);
tetra.PushBack(v3);
tetra.PushBack(v4);
tetra[0] = v1;
tetra[1] = v2;
tetra[2] = v3;
tetra[3] = v4;
// Minkowski sum of box and tetrahedron
b3StackArray<b3Vec3, 256> points;
m_count = 0;
for (u32 i = 0; i < box.vertexCount; ++i)
{
for (u32 j = 0; j < tetra.Count(); ++j)
for (u32 j = 0; j < 4; ++j)
{
b3Vec3 p = box.vertices[i] - tetra[j];
points.PushBack(p);
m_points[m_count++] = p;
}
}
u32 size = qhGetMemorySize(points.Count());
m_memory = b3Alloc(size);
m_qhull.Construct(m_memory, points);
}
~QuickhullTest()
~ConvexHull()
{
b3Free(m_memory);
}
void KeyDown(int button)
{
if (button == GLFW_KEY_G)
{
Generate();
}
}
void Generate()
{
m_count = 0;
for (u32 i = 0; i < e_count; ++i)
{
// Clamp to force coplanarities.
// This will stress the generation code.
float32 x = 3.0f * RandomFloat(-1.0f, 1.0f);
float32 y = 3.0f * RandomFloat(-1.0f, 1.0f);
float32 z = 3.0f * RandomFloat(-1.0f, 1.0f);
b3Vec3 p(x, y, z);
m_points[m_count++] = p;
}
}
void Step()
{
g_draw->DrawString(b3Color_white, "Iterations = %d", m_qhull.GetIterations());
m_qhull.Draw();
b3QHull hull;
hull.Set(m_points, m_count);
b3HullShape shape;
shape.m_hull = &hull;
g_draw->DrawSolidShape(&shape, b3Color_white, b3Transform_identity);
g_draw->DrawString(b3Color_white, "G - Generate a random convex hull");
}
static Test* Create()
{
return new QuickhullTest();
return new ConvexHull();
}
void* m_memory;
qhHull m_qhull;
u32 m_count;
b3Vec3 m_points[e_count];
};
#endif