Add triangle mesh split to perf comparison

This commit is contained in:
tamasmeszaros 2021-06-01 17:52:11 +02:00
parent c8be2cdceb
commit b14b000c73
3 changed files with 103 additions and 60 deletions

View File

@ -24,50 +24,71 @@ static MeasureResult measure_index(const indexed_triangle_set &its, IndexCreator
{ {
Benchmark b; Benchmark b;
MeasureResult r;
for (int i = 0; i < 10; ++i) {
b.start(); b.start();
ItsNeighborsWrapper itsn{its, fn(its)}; ItsNeighborsWrapper itsn{its, fn(its)};
b.stop(); b.stop();
MeasureResult r; r.t_index_create += b.getElapsedSec();
r.t_index_create = b.getElapsedSec();
b.start(); b.start();
its_split(itsn); its_split(itsn);
b.stop(); b.stop();
r.t_split = b.getElapsedSec(); r.t_split += b.getElapsedSec();
}
r.t_index_create /= 10;
r.t_split /= 10;
return r; 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); its_transform(sphere1, Transform3f{}.translate(Vec3f{-5.f, 0.f, 0.f}));
sphere2.translate( 5.f, 0.f, 0.f); its_transform(sphere2, Transform3f{}.translate(Vec3f{5.f, 0.f, 0.f}));
sphere1.merge(sphere2); its_merge(sphere1, sphere2);
sphere1.require_shared_vertices();
return sphere1; return sphere1;
} }
static const std::map<std::string, TriangleMesh> ToMeasure = { static const std::map<std::string, indexed_triangle_set> ToMeasure = {
{"simple", make_cube(10., 10., 10.) }, {"simple", its_make_cube(10., 10., 10.) }, // this has 12 faces, 8 vertices
{"two_spheres", two_spheres(200.)}, {"two_spheres_1x", two_spheres(60.)},
{"two_spheres_detail", two_spheres(360.)}, {"two_spheres_2x", two_spheres(120.)},
{"two_spheres_high_detail", two_spheres(3600.)}, {"two_spheres_4x", two_spheres(240.)},
{"two_spheres_8x", two_spheres(480.)},
}; };
static const auto IndexFunctions = std::make_tuple( static const auto IndexFunctions = std::make_tuple(
std::make_pair("tamas's unordered_map based", its_create_neighbors_index_1), 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", its_create_neighbors_index_2), 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", its_create_neighbors_index_3), 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", its_create_neighbors_index_5), 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", its_create_neighbors_index_6), 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", its_create_neighbors_index_7), 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", its_create_neighbors_index_8) 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)>; 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 &name = m.first;
auto &mesh = m.second; auto &mesh = m.second;
libnest2d::opt::metaloop::apply([&mesh, &name, &results, &funcnames](int N, auto &e) { 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; funcnames[N] = e.first;
results[name][N] = r; results[name][N] = r;
}, IndexFunctions); }, IndexFunctions);
} }
std::string outfilename = "out.csv"; std::string outfilename = "out.csv";
std::fstream outfile; std::fstream outfile;
if (argc > 1) { if (argc > 1) {

View File

@ -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. // 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 make_cube(double x, double y, double z)
{ {
TriangleMesh mesh( TriangleMesh mesh(its_make_cube(x, y, z));
{
{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}
});
mesh.repair(); mesh.repair();
return mesh; 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 // Generate the mesh for a cylinder and return it, using
// the generated angle to calculate the top mesh triangles. // the generated angle to calculate the top mesh triangles.
// Default is 360 sides, angle fa is in radians. // 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); size_t n_steps = (size_t)ceil(2. * PI / fa);
double angle_step = 2. * PI / n_steps; double angle_step = 2. * PI / n_steps;
Pointf3s vertices; auto &vertices = mesh.vertices;
std::vector<Vec3i> facets; auto &facets = mesh.indices;
vertices.reserve(2 * n_steps + 2); vertices.reserve(2 * n_steps + 2);
facets.reserve(4 * n_steps); facets.reserve(4 * n_steps);
// 2 special vertices, top and bottom center, rest are relative to this // 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(Vec3f(0.f, 0.f, 0.f));
vertices.emplace_back(Vec3d(0.0, 0.0, h)); vertices.emplace_back(Vec3f(0.f, 0.f, float(h)));
// for each line along the polygon approximating the top/bottom of the // 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 // circle, generate four points and four facets (2 for the wall, 2 for the
// top and bottom. // top and bottom.
// Special case: Last line shares 2 vertices with the first line. // Special case: Last line shares 2 vertices with the first line.
Vec2d p = Eigen::Rotation2Dd(0.) * Eigen::Vector2d(0, r); Vec2f p = Eigen::Rotation2Df(0.f) * Eigen::Vector2f(0, r);
vertices.emplace_back(Vec3d(p(0), p(1), 0.)); vertices.emplace_back(Vec3f(p(0), p(1), 0.f));
vertices.emplace_back(Vec3d(p(0), p(1), h)); vertices.emplace_back(Vec3f(p(0), p(1), float(h)));
for (size_t i = 1; i < n_steps; ++i) { for (size_t i = 1; i < n_steps; ++i) {
p = Eigen::Rotation2Dd(angle_step * i) * Eigen::Vector2d(0, r); p = Eigen::Rotation2Df(angle_step * i) * Eigen::Vector2f(0, float(r));
vertices.emplace_back(Vec3d(p(0), p(1), 0.)); vertices.emplace_back(Vec3f(p(0), p(1), 0.f));
vertices.emplace_back(Vec3d(p(0), p(1), h)); vertices.emplace_back(Vec3f(p(0), p(1), float(h)));
int id = (int)vertices.size() - 1; int id = (int)vertices.size() - 1;
facets.emplace_back( 0, id - 1, id - 3); // top facets.emplace_back( 0, id - 1, id - 3); // top
facets.emplace_back(id, 1, id - 2); // bottom facets.emplace_back(id, 1, id - 2); // bottom
@ -1027,8 +1030,14 @@ TriangleMesh make_cylinder(double r, double h, double fa)
facets.emplace_back(id, 2, 3); facets.emplace_back(id, 2, 3);
facets.emplace_back(id, id - 1, 2); 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(); mesh.repair();
return mesh; return mesh;
} }
@ -1063,14 +1072,15 @@ TriangleMesh make_cone(double r, double h, double fa)
// to determine the granularity. // to determine the granularity.
// Default angle is 1 degree. // Default angle is 1 degree.
//FIXME better to discretize an Icosahedron recursively http://www.songho.ca/opengl/gl_sphere.html //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 sectorCount = int(ceil(2. * M_PI / fa));
int stackCount = int(ceil(M_PI / fa)); int stackCount = int(ceil(M_PI / fa));
float sectorStep = float(2. * M_PI / sectorCount); float sectorStep = float(2. * M_PI / sectorCount);
float stackStep = float(M_PI / stackCount); float stackStep = float(M_PI / stackCount);
Pointf3s vertices; indexed_triangle_set mesh;
auto& vertices = mesh.vertices;
vertices.reserve((stackCount - 1) * sectorCount + 2); vertices.reserve((stackCount - 1) * sectorCount + 2);
for (int i = 0; i <= stackCount; ++ i) { for (int i = 0; i <= stackCount; ++ i) {
// from pi/2 to -pi/2 // from pi/2 to -pi/2
@ -1078,16 +1088,16 @@ TriangleMesh make_sphere(double radius, double fa)
double xy = radius * cos(stackAngle); double xy = radius * cos(stackAngle);
double z = radius * sin(stackAngle); double z = radius * sin(stackAngle);
if (i == 0 || i == stackCount) if (i == 0 || i == stackCount)
vertices.emplace_back(Vec3d(xy, 0., z)); vertices.emplace_back(Vec3f(float(xy), 0.f, float(z)));
else else
for (int j = 0; j < sectorCount; ++ j) { for (int j = 0; j < sectorCount; ++ j) {
// from 0 to 2pi // from 0 to 2pi
double sectorAngle = sectorStep * j; 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); facets.reserve(2 * (stackCount - 1) * sectorCount);
for (int i = 0; i < stackCount; ++ i) { for (int i = 0; i < stackCount; ++ i) {
// Beginning of current stack. // Beginning of current stack.
@ -1112,8 +1122,15 @@ TriangleMesh make_sphere(double radius, double fa)
k2 = k2_next; 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(); mesh.repair();
return mesh; return mesh;
} }

View File

@ -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 std::vector<Vec3f> &triangles);
void its_merge(indexed_triangle_set &A, const Pointf3s &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); 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)); 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_cone(double r, double h, double fa=(2*PI/360));
TriangleMesh make_sphere(double rho, double fa=(2*PI/360)); TriangleMesh make_sphere(double rho, double fa=(2*PI/360));