Add triangle mesh split to perf comparison
This commit is contained in:
parent
c8be2cdceb
commit
b14b000c73
@ -24,50 +24,71 @@ static MeasureResult measure_index(const indexed_triangle_set &its, IndexCreator
|
||||
{
|
||||
Benchmark b;
|
||||
|
||||
b.start();
|
||||
ItsNeighborsWrapper itsn{its, fn(its)};
|
||||
b.stop();
|
||||
|
||||
MeasureResult r;
|
||||
r.t_index_create = b.getElapsedSec();
|
||||
for (int i = 0; i < 10; ++i) {
|
||||
b.start();
|
||||
ItsNeighborsWrapper itsn{its, fn(its)};
|
||||
b.stop();
|
||||
|
||||
b.start();
|
||||
its_split(itsn);
|
||||
b.stop();
|
||||
r.t_index_create += b.getElapsedSec();
|
||||
|
||||
r.t_split = b.getElapsedSec();
|
||||
b.start();
|
||||
its_split(itsn);
|
||||
b.stop();
|
||||
|
||||
r.t_split += b.getElapsedSec();
|
||||
}
|
||||
|
||||
r.t_index_create /= 10;
|
||||
r.t_split /= 10;
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
static TriangleMesh two_spheres(double detail)
|
||||
static indexed_triangle_set two_spheres(double detail)
|
||||
{
|
||||
TriangleMesh sphere1 = make_sphere(10., 2 * PI / detail), sphere2 = sphere1;
|
||||
auto sphere1 = its_make_sphere(10., 2 * PI / detail), sphere2 = sphere1;
|
||||
|
||||
sphere1.translate(-5.f, 0.f, 0.f);
|
||||
sphere2.translate( 5.f, 0.f, 0.f);
|
||||
its_transform(sphere1, Transform3f{}.translate(Vec3f{-5.f, 0.f, 0.f}));
|
||||
its_transform(sphere2, Transform3f{}.translate(Vec3f{5.f, 0.f, 0.f}));
|
||||
|
||||
sphere1.merge(sphere2);
|
||||
sphere1.require_shared_vertices();
|
||||
its_merge(sphere1, sphere2);
|
||||
|
||||
return sphere1;
|
||||
}
|
||||
|
||||
static const std::map<std::string, TriangleMesh> ToMeasure = {
|
||||
{"simple", make_cube(10., 10., 10.) },
|
||||
{"two_spheres", two_spheres(200.)},
|
||||
{"two_spheres_detail", two_spheres(360.)},
|
||||
{"two_spheres_high_detail", two_spheres(3600.)},
|
||||
static const std::map<std::string, indexed_triangle_set> ToMeasure = {
|
||||
{"simple", its_make_cube(10., 10., 10.) }, // this has 12 faces, 8 vertices
|
||||
{"two_spheres_1x", two_spheres(60.)},
|
||||
{"two_spheres_2x", two_spheres(120.)},
|
||||
{"two_spheres_4x", two_spheres(240.)},
|
||||
{"two_spheres_8x", two_spheres(480.)},
|
||||
};
|
||||
|
||||
static const auto IndexFunctions = std::make_tuple(
|
||||
std::make_pair("tamas's unordered_map based", its_create_neighbors_index_1),
|
||||
std::make_pair("vojta std::sort based", its_create_neighbors_index_2),
|
||||
std::make_pair("vojta tbb::parallel_sort based", its_create_neighbors_index_3),
|
||||
std::make_pair("filip's vertex->face based", its_create_neighbors_index_5),
|
||||
std::make_pair("tamas's std::sort based", its_create_neighbors_index_6),
|
||||
std::make_pair("tamas's tbb::parallel_sort based", its_create_neighbors_index_7),
|
||||
std::make_pair("tamas's map based", its_create_neighbors_index_8)
|
||||
std::make_pair("tamas's unordered_map based", [](const auto &its) { return measure_index(its, its_create_neighbors_index_1); }),
|
||||
std::make_pair("vojta std::sort based", [](const auto &its) { return measure_index(its, its_create_neighbors_index_2); }),
|
||||
std::make_pair("vojta tbb::parallel_sort based", [](const auto &its) { return measure_index(its, its_create_neighbors_index_3); }),
|
||||
std::make_pair("filip's vertex->face based", [](const auto &its) { return measure_index(its, its_create_neighbors_index_5); }),
|
||||
std::make_pair("tamas's std::sort based", [](const auto &its) { return measure_index(its, its_create_neighbors_index_6); }),
|
||||
std::make_pair("tamas's tbb::parallel_sort based", [](const auto &its) { return measure_index(its, its_create_neighbors_index_7); }),
|
||||
std::make_pair("tamas's map based", [](const auto &its) { return measure_index(its, its_create_neighbors_index_8); }),
|
||||
std::make_pair("TriangleMesh split", [](const auto &its) {
|
||||
TriangleMesh m{its};
|
||||
|
||||
MeasureResult ret;
|
||||
for (int i = 0; i < 10; ++i) {
|
||||
Benchmark b;
|
||||
b.start();
|
||||
m.repair();
|
||||
m.split();
|
||||
b.stop();
|
||||
ret.t_split += b.getElapsedSec();
|
||||
}
|
||||
ret.t_split /= 10;
|
||||
|
||||
return ret;
|
||||
})
|
||||
);
|
||||
|
||||
static constexpr size_t IndexFuncNum = std::tuple_size_v<decltype (IndexFunctions)>;
|
||||
@ -85,13 +106,12 @@ int main(const int argc, const char * argv[])
|
||||
auto &name = m.first;
|
||||
auto &mesh = m.second;
|
||||
libnest2d::opt::metaloop::apply([&mesh, &name, &results, &funcnames](int N, auto &e) {
|
||||
MeasureResult r = measure_index(mesh.its, e.second);
|
||||
MeasureResult r = e.second(mesh);
|
||||
funcnames[N] = e.first;
|
||||
results[name][N] = r;
|
||||
}, IndexFunctions);
|
||||
}
|
||||
|
||||
|
||||
std::string outfilename = "out.csv";
|
||||
std::fstream outfile;
|
||||
if (argc > 1) {
|
||||
|
@ -968,20 +968,22 @@ Polygon its_convex_hull_2d_above(const indexed_triangle_set &its, const Transfor
|
||||
}
|
||||
|
||||
// Generate the vertex list for a cube solid of arbitrary size in X/Y/Z.
|
||||
indexed_triangle_set its_make_cube(double xd, double yd, double zd)
|
||||
{
|
||||
auto x = float(xd), y = float(yd), z = float(zd);
|
||||
indexed_triangle_set mesh;
|
||||
mesh.vertices = {{x, y, 0}, {x, 0, 0}, {0, 0, 0}, {0, y, 0},
|
||||
{x, y, z}, {0, y, z}, {0, 0, z}, {x, 0, z}};
|
||||
mesh.indices = {{0, 1, 2}, {0, 2, 3}, {4, 5, 6}, {4, 6, 7},
|
||||
{0, 4, 7}, {0, 7, 1}, {1, 7, 6}, {1, 6, 2},
|
||||
{2, 6, 5}, {2, 5, 3}, {4, 0, 3}, {4, 3, 5}};
|
||||
|
||||
return mesh;
|
||||
}
|
||||
|
||||
TriangleMesh make_cube(double x, double y, double z)
|
||||
{
|
||||
TriangleMesh mesh(
|
||||
{
|
||||
{x, y, 0}, {x, 0, 0}, {0, 0, 0},
|
||||
{0, y, 0}, {x, y, z}, {0, y, z},
|
||||
{0, 0, z}, {x, 0, z}
|
||||
},
|
||||
{
|
||||
{0, 1, 2}, {0, 2, 3}, {4, 5, 6},
|
||||
{4, 6, 7}, {0, 4, 7}, {0, 7, 1},
|
||||
{1, 7, 6}, {1, 6, 2}, {2, 6, 5},
|
||||
{2, 5, 3}, {4, 0, 3}, {4, 3, 5}
|
||||
});
|
||||
TriangleMesh mesh(its_make_cube(x, y, z));
|
||||
mesh.repair();
|
||||
return mesh;
|
||||
}
|
||||
@ -989,31 +991,32 @@ TriangleMesh make_cube(double x, double y, double z)
|
||||
// Generate the mesh for a cylinder and return it, using
|
||||
// the generated angle to calculate the top mesh triangles.
|
||||
// Default is 360 sides, angle fa is in radians.
|
||||
TriangleMesh make_cylinder(double r, double h, double fa)
|
||||
indexed_triangle_set its_make_cylinder(double r, double h, double fa)
|
||||
{
|
||||
indexed_triangle_set mesh;
|
||||
size_t n_steps = (size_t)ceil(2. * PI / fa);
|
||||
double angle_step = 2. * PI / n_steps;
|
||||
|
||||
Pointf3s vertices;
|
||||
std::vector<Vec3i> facets;
|
||||
auto &vertices = mesh.vertices;
|
||||
auto &facets = mesh.indices;
|
||||
vertices.reserve(2 * n_steps + 2);
|
||||
facets.reserve(4 * n_steps);
|
||||
|
||||
// 2 special vertices, top and bottom center, rest are relative to this
|
||||
vertices.emplace_back(Vec3d(0.0, 0.0, 0.0));
|
||||
vertices.emplace_back(Vec3d(0.0, 0.0, h));
|
||||
vertices.emplace_back(Vec3f(0.f, 0.f, 0.f));
|
||||
vertices.emplace_back(Vec3f(0.f, 0.f, float(h)));
|
||||
|
||||
// for each line along the polygon approximating the top/bottom of the
|
||||
// circle, generate four points and four facets (2 for the wall, 2 for the
|
||||
// top and bottom.
|
||||
// Special case: Last line shares 2 vertices with the first line.
|
||||
Vec2d p = Eigen::Rotation2Dd(0.) * Eigen::Vector2d(0, r);
|
||||
vertices.emplace_back(Vec3d(p(0), p(1), 0.));
|
||||
vertices.emplace_back(Vec3d(p(0), p(1), h));
|
||||
Vec2f p = Eigen::Rotation2Df(0.f) * Eigen::Vector2f(0, r);
|
||||
vertices.emplace_back(Vec3f(p(0), p(1), 0.f));
|
||||
vertices.emplace_back(Vec3f(p(0), p(1), float(h)));
|
||||
for (size_t i = 1; i < n_steps; ++i) {
|
||||
p = Eigen::Rotation2Dd(angle_step * i) * Eigen::Vector2d(0, r);
|
||||
vertices.emplace_back(Vec3d(p(0), p(1), 0.));
|
||||
vertices.emplace_back(Vec3d(p(0), p(1), h));
|
||||
p = Eigen::Rotation2Df(angle_step * i) * Eigen::Vector2f(0, float(r));
|
||||
vertices.emplace_back(Vec3f(p(0), p(1), 0.f));
|
||||
vertices.emplace_back(Vec3f(p(0), p(1), float(h)));
|
||||
int id = (int)vertices.size() - 1;
|
||||
facets.emplace_back( 0, id - 1, id - 3); // top
|
||||
facets.emplace_back(id, 1, id - 2); // bottom
|
||||
@ -1026,9 +1029,15 @@ TriangleMesh make_cylinder(double r, double h, double fa)
|
||||
facets.emplace_back( 3, 1, id);
|
||||
facets.emplace_back(id, 2, 3);
|
||||
facets.emplace_back(id, id - 1, 2);
|
||||
|
||||
TriangleMesh mesh(std::move(vertices), std::move(facets));
|
||||
|
||||
return mesh;
|
||||
}
|
||||
|
||||
TriangleMesh make_cylinder(double r, double h, double fa)
|
||||
{
|
||||
TriangleMesh mesh{its_make_cylinder(r, h, fa)};
|
||||
mesh.repair();
|
||||
|
||||
return mesh;
|
||||
}
|
||||
|
||||
@ -1063,14 +1072,15 @@ TriangleMesh make_cone(double r, double h, double fa)
|
||||
// to determine the granularity.
|
||||
// Default angle is 1 degree.
|
||||
//FIXME better to discretize an Icosahedron recursively http://www.songho.ca/opengl/gl_sphere.html
|
||||
TriangleMesh make_sphere(double radius, double fa)
|
||||
indexed_triangle_set its_make_sphere(double radius, double fa)
|
||||
{
|
||||
int sectorCount = int(ceil(2. * M_PI / fa));
|
||||
int stackCount = int(ceil(M_PI / fa));
|
||||
float sectorStep = float(2. * M_PI / sectorCount);
|
||||
float stackStep = float(M_PI / stackCount);
|
||||
|
||||
Pointf3s vertices;
|
||||
indexed_triangle_set mesh;
|
||||
auto& vertices = mesh.vertices;
|
||||
vertices.reserve((stackCount - 1) * sectorCount + 2);
|
||||
for (int i = 0; i <= stackCount; ++ i) {
|
||||
// from pi/2 to -pi/2
|
||||
@ -1078,16 +1088,16 @@ TriangleMesh make_sphere(double radius, double fa)
|
||||
double xy = radius * cos(stackAngle);
|
||||
double z = radius * sin(stackAngle);
|
||||
if (i == 0 || i == stackCount)
|
||||
vertices.emplace_back(Vec3d(xy, 0., z));
|
||||
vertices.emplace_back(Vec3f(float(xy), 0.f, float(z)));
|
||||
else
|
||||
for (int j = 0; j < sectorCount; ++ j) {
|
||||
// from 0 to 2pi
|
||||
double sectorAngle = sectorStep * j;
|
||||
vertices.emplace_back(Vec3d(xy * cos(sectorAngle), xy * sin(sectorAngle), z));
|
||||
vertices.emplace_back(Vec3d(xy * std::cos(sectorAngle), xy * std::sin(sectorAngle), z).cast<float>());
|
||||
}
|
||||
}
|
||||
|
||||
std::vector<Vec3i> facets;
|
||||
auto& facets = mesh.indices;
|
||||
facets.reserve(2 * (stackCount - 1) * sectorCount);
|
||||
for (int i = 0; i < stackCount; ++ i) {
|
||||
// Beginning of current stack.
|
||||
@ -1112,8 +1122,15 @@ TriangleMesh make_sphere(double radius, double fa)
|
||||
k2 = k2_next;
|
||||
}
|
||||
}
|
||||
TriangleMesh mesh(std::move(vertices), std::move(facets));
|
||||
|
||||
return mesh;
|
||||
}
|
||||
|
||||
TriangleMesh make_sphere(double radius, double fa)
|
||||
{
|
||||
TriangleMesh mesh(its_make_sphere(radius, fa));
|
||||
mesh.repair();
|
||||
|
||||
return mesh;
|
||||
}
|
||||
|
||||
|
@ -179,8 +179,14 @@ void its_merge(indexed_triangle_set &A, const indexed_triangle_set &B);
|
||||
void its_merge(indexed_triangle_set &A, const std::vector<Vec3f> &triangles);
|
||||
void its_merge(indexed_triangle_set &A, const Pointf3s &triangles);
|
||||
|
||||
indexed_triangle_set its_make_cube(double x, double y, double z);
|
||||
TriangleMesh make_cube(double x, double y, double z);
|
||||
|
||||
// Generate a TriangleMesh of a cylinder
|
||||
indexed_triangle_set its_make_cylinder(double r, double h, double fa=(2*PI/360));
|
||||
TriangleMesh make_cylinder(double r, double h, double fa=(2*PI/360));
|
||||
|
||||
indexed_triangle_set its_make_sphere(double rho, double fa=(2*PI/360));
|
||||
TriangleMesh make_cone(double r, double h, double fa=(2*PI/360));
|
||||
TriangleMesh make_sphere(double rho, double fa=(2*PI/360));
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user