diff --git a/src/MeshBuilder.h b/src/MeshBuilder.h index 6bcbd59ba..6a04b65ac 100644 --- a/src/MeshBuilder.h +++ b/src/MeshBuilder.h @@ -169,6 +169,47 @@ template class MeshBuilder { _faces.insert(face); } + /** + * @brief Subdivide mesh + * @param interpolator Functor or function pointer which interpolates + * two adjacent vertices: Vertex interpolator(Vertex a, Vertex + * b) + * + * Goes through all triangle faces and subdivides them in four new. + * Cleaning the mesh is up to user. + */ + template void subdivide(Interpolator interpolator) { + /* Copy of current faces */ + std::set f = faces(); + + /* Subdivide each face to four new */ + for(typename std::set::const_iterator face = f.begin(); face != f.end(); ++face) { + /* Interpolate each side */ + Vertex* newVertices[3]; + for(int i = 0; i != 3; ++i) + newVertices[i] = new Vertex(interpolator(*(*face)->vertices[i], *(*face)->vertices[(i+1)%3])); + + /* + * Add three new faces (0, 1, 3) and update original (2) + * + * orig 0 + * / \ + * / 0 \ + * / \ + * new 0 ----- new 2 + * / \ / \ + * / 1 \ 2 / 3 \ + * / \ / \ + * orig 1 ----- new 1 ---- orig 2 + */ + addFace(new Face((*face)->vertices[0], newVertices[0], newVertices[2])); + addFace(new Face(newVertices[0], (*face)->vertices[1], newVertices[1])); + addFace(new Face(newVertices[2], newVertices[1], (*face)->vertices[2])); + for(int i = 0; i != 3; ++i) + (*face)->vertices[i] = newVertices[i]; + } + } + /** * @brief Clean the mesh * diff --git a/src/Test/MeshBuilderTest.cpp b/src/Test/MeshBuilderTest.cpp index 9c7010fa4..732a674ed 100644 --- a/src/Test/MeshBuilderTest.cpp +++ b/src/Test/MeshBuilderTest.cpp @@ -150,4 +150,29 @@ void MeshBuilderTest::cleanMesh() { QVERIFY(builder.faces() == faces); } +void MeshBuilderTest::subdivide() { + MeshBuilder builder; + + int* v1 = new int(0); + int* v2 = new int(2); + int* v3 = new int(6); + int* v4 = new int(8); + + MeshBuilder::Face* f1 = new MeshBuilder::Face(v1, v2, v3); + builder.addFace(f1); + MeshBuilder::Face* f2 = new MeshBuilder::Face(v2, v3, v4); + builder.addFace(f2); + + builder.subdivide(interpolator); + + QVERIFY(builder.vertices().size() == 10); + QVERIFY(builder.faces().size() == 8); + + /* This also effectively checks the data, as the vertices should be exactly + 0, 1, 2, .. 8 */ + builder.cleanMesh(); + QVERIFY(builder.vertices().size() == 9); + QVERIFY(builder.faces().size() == 8); +} + }} diff --git a/src/Test/MeshBuilderTest.h b/src/Test/MeshBuilderTest.h index 85635c499..e446502a5 100644 --- a/src/Test/MeshBuilderTest.h +++ b/src/Test/MeshBuilderTest.h @@ -27,6 +27,10 @@ class MeshBuilderTest: public QObject { void addFace(); void removeFace(); void cleanMesh(); + void subdivide(); + + private: + inline static int interpolator(int a, int b) { return (a+b)/2; } }; }}