From 7a451994ea693f85077519da335d6775f8a5d315 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Sat, 21 Apr 2012 02:54:44 +0200 Subject: [PATCH] MeshTools: function for generating flat normals. --- src/MeshTools/CMakeLists.txt | 1 + src/MeshTools/GenerateFlatNormals.cpp | 52 ++++++++++++++ src/MeshTools/GenerateFlatNormals.h | 54 +++++++++++++++ src/MeshTools/Test/CMakeLists.txt | 1 + .../Test/GenerateFlatNormalsTest.cpp | 68 +++++++++++++++++++ src/MeshTools/Test/GenerateFlatNormalsTest.h | 32 +++++++++ 6 files changed, 208 insertions(+) create mode 100644 src/MeshTools/GenerateFlatNormals.cpp create mode 100644 src/MeshTools/GenerateFlatNormals.h create mode 100644 src/MeshTools/Test/GenerateFlatNormalsTest.cpp create mode 100644 src/MeshTools/Test/GenerateFlatNormalsTest.h diff --git a/src/MeshTools/CMakeLists.txt b/src/MeshTools/CMakeLists.txt index f59b8ee59..785cd9253 100644 --- a/src/MeshTools/CMakeLists.txt +++ b/src/MeshTools/CMakeLists.txt @@ -1,4 +1,5 @@ set(MagnumMeshTools_SRCS + GenerateFlatNormals.cpp Tipsify.cpp ) diff --git a/src/MeshTools/GenerateFlatNormals.cpp b/src/MeshTools/GenerateFlatNormals.cpp new file mode 100644 index 000000000..ad667dc3a --- /dev/null +++ b/src/MeshTools/GenerateFlatNormals.cpp @@ -0,0 +1,52 @@ +/* + Copyright © 2010, 2011, 2012 Vladimír Vondruš + + This file is part of Magnum. + + Magnum is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License version 3 + only, as published by the Free Software Foundation. + + Magnum is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Lesser General Public License version 3 for more details. +*/ + +#include "GenerateFlatNormals.h" + +#include "MeshTools/Clean.h" + +using namespace std; +using namespace Corrade::Utility; + +namespace Magnum { namespace MeshTools { + +tuple, vector> generateFlatNormals(const std::vector< unsigned int >& indices, const vector< Vector4 >& vertices) { + if(indices.size()%3 != 0) { + Error() << "MeshTools::generateFlatNormals(): index count is not divisible by 3!"; + return tuple, vector>(); + } + + /* Create normal for every triangle (assuming counterclockwise winding) */ + vector normalIndices; + normalIndices.reserve(indices.size()); + vector normals; + normals.reserve(indices.size()/3); + for(size_t i = 0; i != indices.size(); i += 3) { + Vector3 normal = Vector3::cross(vertices[indices[i+2]].xyz()-vertices[indices[i+1]].xyz(), + vertices[indices[i]].xyz()-vertices[indices[i+1]].xyz()).normalized(); + + /* Use the same normal for all three vertices of the face */ + normalIndices.push_back(normals.size()); + normalIndices.push_back(normals.size()); + normalIndices.push_back(normals.size()); + normals.push_back(normal); + } + + /* Clean duplicate normals and return */ + clean(normalIndices, normals); + return make_tuple(normalIndices, normals); +} + +}} diff --git a/src/MeshTools/GenerateFlatNormals.h b/src/MeshTools/GenerateFlatNormals.h new file mode 100644 index 000000000..2e113c640 --- /dev/null +++ b/src/MeshTools/GenerateFlatNormals.h @@ -0,0 +1,54 @@ +#ifndef Magnum_MeshTools_GenerateFlatNormals_h +#define Magnum_MeshTools_GenerateFlatNormals_h +/* + Copyright © 2010, 2011, 2012 Vladimír Vondruš + + This file is part of Magnum. + + Magnum is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License version 3 + only, as published by the Free Software Foundation. + + Magnum is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Lesser General Public License version 3 for more details. +*/ + +/** @file + * @brief Function Magnum::MeshTools::generateFlatNormals() + */ + +#include + +#include "Magnum.h" + +namespace Magnum { namespace MeshTools { + +/** +@brief Generate flat normals +@param indices Array of triangle face indexes +@param vertices Vertex array +@return Normal indices and vectors + +For each face generates one normal vector, removes duplicates before +returning. Example usage: +@code +std::vector vertexIndices; +std::vector vertices; + +std::vector normalIndices; +std::vector normals; +std::tie(normalIndices, normals) = MeshTools::generateFlatNormals(vertexIndices, vertices); +@endcode +You can then use combineIndexedArrays() to combine normal and vertex array to +use the same indices. + +@attention Index count must be divisible by 3, otherwise zero length result + is generated. +*/ +std::tuple, std::vector> generateFlatNormals(const std::vector& indices, const std::vector& vertices); + +}} + +#endif diff --git a/src/MeshTools/Test/CMakeLists.txt b/src/MeshTools/Test/CMakeLists.txt index 9dd4c453d..e01d10259 100644 --- a/src/MeshTools/Test/CMakeLists.txt +++ b/src/MeshTools/Test/CMakeLists.txt @@ -1,6 +1,7 @@ corrade_add_test(CleanTest CleanTest.h CleanTest.cpp ${CORRADE_UTILITY_LIBRARY}) corrade_add_test(CombineIndexedArraysTest CombineIndexedArraysTest.h CombineIndexedArraysTest.cpp ${CORRADE_UTILITY_LIBRARY}) corrade_add_test(CompressIndicesTest CompressIndicesTest.h CompressIndicesTest.cpp ${CORRADE_UTILITY_LIBRARY} ${MAGNUM_LIBRARY}) +corrade_add_test(GenerateFlatNormalsTest GenerateFlatNormalsTest.h GenerateFlatNormalsTest.cpp ${MAGNUM_MESHTOOLS_LIBRARY}) corrade_add_test(InterleaveTest InterleaveTest.h InterleaveTest.cpp ${CORRADE_UTILITY_LIBRARY}) corrade_add_test(SubdivideTest SubdivideTest.h SubdivideTest.cpp ${CORRADE_UTILITY_LIBRARY}) corrade_add_test(SubdivideCleanBenchmark SubdivideCleanBenchmark.h SubdivideCleanBenchmark.cpp ${CORRADE_UTILITY_LIBRARY} ${MAGNUM_PRIMITIVES_LIBRARY}) diff --git a/src/MeshTools/Test/GenerateFlatNormalsTest.cpp b/src/MeshTools/Test/GenerateFlatNormalsTest.cpp new file mode 100644 index 000000000..4ff813db1 --- /dev/null +++ b/src/MeshTools/Test/GenerateFlatNormalsTest.cpp @@ -0,0 +1,68 @@ +/* + Copyright © 2010, 2011, 2012 Vladimír Vondruš + + This file is part of Magnum. + + Magnum is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License version 3 + only, as published by the Free Software Foundation. + + Magnum is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Lesser General Public License version 3 for more details. +*/ + +#include "GenerateFlatNormalsTest.h" + +#include +#include +#include "MeshTools/GenerateFlatNormals.h" + +QTEST_APPLESS_MAIN(Magnum::MeshTools::Test::GenerateFlatNormalsTest) + +using namespace std; +using namespace Corrade::Utility; + +namespace Magnum { namespace MeshTools { namespace Test { + +void GenerateFlatNormalsTest::wrongIndexCount() { + stringstream ss; + Error::setOutput(&ss); + vector indices; + vector normals; + tie(indices, normals) = MeshTools::generateFlatNormals({ + 0, 1 + }, {}); + + QVERIFY(indices.size() == 0); + QVERIFY(normals.size() == 0); + QVERIFY(ss.str() == "MeshTools::generateFlatNormals(): index count is not divisible by 3!\n"); +} + +void GenerateFlatNormalsTest::generate() { + /* Two vertices connected by one edge, each winded in another direction */ + vector indices; + vector normals; + tie(indices, normals) = MeshTools::generateFlatNormals({ + 0, 1, 2, + 1, 2, 3 + }, { + {-1.0f, 0.0f, 0.0f}, + {0.0f, -1.0f, 0.0f}, + {0.0f, 1.0f, 0.0f}, + {1.0f, 0.0f, 0.0f} + }); + + + QVERIFY((indices == vector{ + 0, 0, 0, + 1, 1, 1 + })); + QVERIFY((normals == vector{ + Vector3::zAxis(), + -Vector3::zAxis() + })); +} + +}}} diff --git a/src/MeshTools/Test/GenerateFlatNormalsTest.h b/src/MeshTools/Test/GenerateFlatNormalsTest.h new file mode 100644 index 000000000..32d798d16 --- /dev/null +++ b/src/MeshTools/Test/GenerateFlatNormalsTest.h @@ -0,0 +1,32 @@ +#ifndef Magnum_MeshTools_Test_GenerateFlatNormalsTest_h +#define Magnum_MeshTools_Test_GenerateFlatNormalsTest_h +/* + Copyright © 2010, 2011, 2012 Vladimír Vondruš + + This file is part of Magnum. + + Magnum is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License version 3 + only, as published by the Free Software Foundation. + + Magnum is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Lesser General Public License version 3 for more details. +*/ + +#include + +namespace Magnum { namespace MeshTools { namespace Test { + +class GenerateFlatNormalsTest: public QObject { + Q_OBJECT + + private slots: + void wrongIndexCount(); + void generate(); +}; + +}}} + +#endif