Improved performance regression: create indexed polygon before tessellating, don't tessellate triangles

master
Marius Kintel 2015-03-08 19:35:20 -04:00
parent 30f5343834
commit 28b347065d
1 changed files with 43 additions and 14 deletions

View File

@ -3,6 +3,8 @@
#include "Polygon2d.h"
#include "printutils.h"
#include "GeometryUtils.h"
#include "Reindexer.h"
#include "grid.h"
#ifdef ENABLE_CGAL
#include "cgalutils.h"
#endif
@ -47,26 +49,53 @@ namespace PolysetUtils {
polyset has simple polygon faces with no holes.
The tessellation will be robust wrt. degenerate and self-intersecting
*/
void tessellate_faces(const PolySet &inps, PolySet &outps) {
void tessellate_faces(const PolySet &inps, PolySet &outps)
{
int degeneratePolygons = 0;
for (size_t i = 0; i < inps.polygons.size(); i++) {
const Polygon &pgon = inps.polygons[i];
// Build Indexed PolyMesh
Reindexer<Vector3f> allVertices;
std::vector<std::vector<IndexedFace> > polygons;
BOOST_FOREACH(const Polygon &pgon, inps.polygons) {
if (pgon.size() < 3) {
degeneratePolygons++;
continue;
}
if (pgon.size() == 3) { // Short-circuit
outps.append_poly(pgon);
continue;
}
polygons.push_back(std::vector<IndexedFace>());
std::vector<IndexedFace> &faces = polygons.back();
faces.push_back(IndexedFace());
IndexedFace &currface = faces.back();
BOOST_FOREACH (const Vector3d &v, pgon) {
// Create vertex indices and remove consecutive duplicate vertices
int idx = allVertices.lookup(v.cast<float>());
if (currface.empty() || idx != currface.back()) currface.push_back(idx);
}
if (currface.front() == currface.back()) currface.pop_back();
if (currface.size() < 3) faces.pop_back(); // Cull empty triangles
}
// Tessellate indexed mesh
const Vector3f *verts = allVertices.getArray();
std::vector<IndexedTriangle> allTriangles;
BOOST_FOREACH(const std::vector<IndexedFace> &faces, polygons) {
std::vector<IndexedTriangle> triangles;
if (faces[0].size() == 3) {
triangles.push_back(IndexedTriangle(faces[0][0], faces[0][1], faces[0][2]));
}
else {
Polygons triangles;
bool err = GeometryUtils::tessellatePolygon(pgon, triangles);
// Empty triangles tend to happen quite often,
// probably due to previous floating point conversion, so
// we don't issue any warnings.
if (!triangles.empty()) {
// ..and pass to the output polyhedron
BOOST_FOREACH(const Polygon &t, triangles) {
bool err = GeometryUtils::tessellatePolygonWithHoles(verts, faces, triangles, NULL);
if (!err) {
BOOST_FOREACH(const IndexedTriangle &t, triangles) {
outps.append_poly();
outps.append_vertex(t[0]);
outps.append_vertex(t[1]);
outps.append_vertex(t[2]);
outps.append_vertex(verts[t[0]]);
outps.append_vertex(verts[t[1]]);
outps.append_vertex(verts[t[2]]);
}
}
}