Browse Source

MeshTools: deSTLify flipNormals(), flipFaceWinding() and tipsify().

And rename them to *InPlace(), since that's what they do. The original
STL variants are now deprecated wrappers over the new names. Not
adapting the test yet in order to test everything is alright.
pull/371/head
Vladimír Vondruš 6 years ago
parent
commit
b589f15640
  1. 17
      doc/changelog.dox
  2. 37
      src/Magnum/MeshTools/FlipNormals.cpp
  3. 113
      src/Magnum/MeshTools/FlipNormals.h
  4. 18
      src/Magnum/MeshTools/Implementation/Tipsify.h
  5. 23
      src/Magnum/MeshTools/Test/TipsifyTest.cpp
  6. 58
      src/Magnum/MeshTools/Tipsify.cpp
  7. 41
      src/Magnum/MeshTools/Tipsify.h

17
doc/changelog.dox

@ -219,6 +219,13 @@ See also:
@ref MeshTools::removeDuplicatesInPlace() variant @ref MeshTools::removeDuplicatesInPlace() variant
- Added @ref MeshTools::duplicateInto() variants that take type-erased - Added @ref MeshTools::duplicateInto() variants that take type-erased
2D strided array views 2D strided array views
- @ref MeshTools::flipNormalsInPlace() and @ref MeshTools::flipFaceWindingInPlace()
were renamed for clarity and now accept a
@ref Corrade::Containers::StridedArrayView instead of a @ref std::vector,
additionally working on 8- and 16-byte index types as well
- @ref MeshTools::tipsifyInPlace() was renamed for clarity and now accepts a
@ref Corrade::Containers::StridedArrayView instead of a @ref std::vector,
additionally working on 8- and 16-byte index types as well
- Added @ref MeshTools::generateSmoothNormals() and - Added @ref MeshTools::generateSmoothNormals() and
@ref MeshTools::generateSmoothNormalsInto() variants taking type-erased @ref MeshTools::generateSmoothNormalsInto() variants taking type-erased
index arrays index arrays
@ -313,8 +320,8 @@ See also:
- It was not possible to override DPI scaling using - It was not possible to override DPI scaling using
@ref Platform::Sdl2Application::Configuration as command-line arguments @ref Platform::Sdl2Application::Configuration as command-line arguments
always got a priority (see [mosra/magnum#416](https://github.com/mosra/magnum/issues/416)) always got a priority (see [mosra/magnum#416](https://github.com/mosra/magnum/issues/416))
- Fixed an otherwise harmless OOB access in @ref MeshTools::tipsify() that - Fixed an otherwise harmless OOB access in @ref MeshTools::tipsifyInPlace()
could trigger ASan or debug iterator errors that could trigger ASan or debug iterator errors
- With @ref Corrade/Utility/DebugStl.h not being included, @ref std::string - With @ref Corrade/Utility/DebugStl.h not being included, @ref std::string
instances could get accidentally printed as @ref ResourceKey instances. instances could get accidentally printed as @ref ResourceKey instances.
Added and explicit header dependency to avoid such cases. Added and explicit header dependency to avoid such cases.
@ -356,6 +363,12 @@ See also:
@ref Text::FontConverterFeatures, @ref Trade::ImporterFeatures, @ref Text::FontConverterFeatures, @ref Trade::ImporterFeatures,
@ref Trade::ImageConverterFeatures enum sets and their corresponding enums @ref Trade::ImageConverterFeatures enum sets and their corresponding enums
placed directly in the namespace to have them shorter and unambiguous placed directly in the namespace to have them shorter and unambiguous
- @cpp MeshTools::flipNormals() @ce and @cpp MeshTools::flipFaceWinding() @ce
and @cpp MeshTools::tipsify() @ce are deprecated in favor of
@ref MeshTools::flipNormalsInPlace(),
@ref MeshTools::flipFaceWindingInPlace() and @ref MeshTools::tipsifyInPlace()
that accept a @ref Corrade::Containers::StridedArrayView instead of a
@ref std::vector and work with 8- and 16-byte index types as well.
@subsection changelog-latest-compatibility Potential compatibility breakages, removed APIs @subsection changelog-latest-compatibility Potential compatibility breakages, removed APIs

37
src/Magnum/MeshTools/FlipNormals.cpp

@ -25,11 +25,16 @@
#include "FlipNormals.h" #include "FlipNormals.h"
#include <vector>
#include <Corrade/Containers/StridedArrayView.h>
#include "Magnum/Math/Vector3.h" #include "Magnum/Math/Vector3.h"
namespace Magnum { namespace MeshTools { namespace Magnum { namespace MeshTools {
void flipFaceWinding(std::vector<UnsignedInt>& indices) { namespace {
template<class T> inline void flipFaceWindingInPlaceImplementation(const Containers::StridedArrayView1D<T>& indices) {
CORRADE_ASSERT(!(indices.size()%3), "MeshTools::flipNormals(): index count is not divisible by 3!", ); CORRADE_ASSERT(!(indices.size()%3), "MeshTools::flipNormals(): index count is not divisible by 3!", );
using std::swap; using std::swap;
@ -37,9 +42,37 @@ void flipFaceWinding(std::vector<UnsignedInt>& indices) {
swap(indices[i+1], indices[i+2]); swap(indices[i+1], indices[i+2]);
} }
void flipNormals(std::vector<Vector3>& normals) { }
void flipFaceWindingInPlace(const Containers::StridedArrayView1D<UnsignedInt>& indices) {
flipFaceWindingInPlaceImplementation(indices);
}
void flipFaceWindingInPlace(const Containers::StridedArrayView1D<UnsignedShort>& indices) {
flipFaceWindingInPlaceImplementation(indices);
}
void flipFaceWindingInPlace(const Containers::StridedArrayView1D<UnsignedByte>& indices) {
flipFaceWindingInPlaceImplementation(indices);
}
void flipNormalsInPlace(const Containers::StridedArrayView1D<Vector3>& normals) {
for(Vector3& normal: normals) for(Vector3& normal: normals)
normal = -normal; normal = -normal;
} }
#ifdef MAGNUM_BUILD_DEPRECATED
void flipNormals(std::vector<UnsignedInt>& indices, std::vector<Vector3>& normals) {
flipNormalsInPlace(indices, normals);
}
void flipFaceWinding(std::vector<UnsignedInt>& indices) {
flipFaceWindingInPlace(indices);
}
void flipNormals(std::vector<Vector3>& normals) {
flipNormalsInPlace(normals);
}
#endif
}} }}

113
src/Magnum/MeshTools/FlipNormals.h

@ -26,52 +26,119 @@
*/ */
/** @file /** @file
* @brief Function @ref Magnum::MeshTools::flipFaceWinding(), @ref Magnum::MeshTools::flipNormals() * @brief Function @ref Magnum::MeshTools::flipFaceWindingInPlace(), @ref Magnum::MeshTools::flipNormalsInPlace()
*/ */
#include <vector> #include <Corrade/Containers/Containers.h>
#include "Magnum/Magnum.h" #include "Magnum/Magnum.h"
#include "Magnum/MeshTools/visibility.h" #include "Magnum/MeshTools/visibility.h"
#ifdef MAGNUM_BUILD_DEPRECATED
#include <Corrade/Utility/StlForwardVector.h>
#include <Corrade/Containers/ArrayViewStl.h>
#include <Corrade/Containers/StridedArrayView.h>
#include <Corrade/Utility/Macros.h>
#endif
namespace Magnum { namespace MeshTools { namespace Magnum { namespace MeshTools {
/** /**
@brief Flip face winding @brief Flip mesh normals and face winding in-place
@param[in,out] indices Index array to operate on @param[in,out] indices Index array to operate on
@param[in,out] normals Normal array to operate on
The same as @ref flipNormals(std::vector<UnsignedInt>&, std::vector<Vector3>&), Flips normal vectors and face winding in index array for face culling to work
but flips only face winding. properly too. See also @ref flipNormalsInPlace(const Containers::StridedArrayView1D<Vector3>&)
and @ref flipFaceWindingInPlace(), which flip normals or face winding only.
@attention The function requires the mesh to have triangle faces, thus index Expects a triangle mesh, thus the index count has to be divisible by 3.
count must be divisible by 3.
*/ */
void MAGNUM_MESHTOOLS_EXPORT flipFaceWinding(std::vector<UnsignedInt>& indices); void flipNormalsInPlace(const Containers::StridedArrayView1D<UnsignedInt>& indices, const Containers::StridedArrayView1D<Vector3>& normals);
/** /**
@brief Flip mesh normals * @overload
@param[in,out] normals Normal array to operate on * @m_since_latest
*/
void flipNormalsInPlace(const Containers::StridedArrayView1D<UnsignedShort>& indices, const Containers::StridedArrayView1D<Vector3>& normals);
The same as @ref flipNormals(std::vector<UnsignedInt>&, std::vector<Vector3>&), /**
but flips only normals, not face winding. * @overload
* @m_since_latest
*/
void flipNormalsInPlace(const Containers::StridedArrayView1D<UnsignedByte>& indices, const Containers::StridedArrayView1D<Vector3>& normals);
#ifdef MAGNUM_BUILD_DEPRECATED
/**
@brief @copybrief flipNormalsInPlace(const Containers::StridedArrayView1D<UnsignedInt>&, const Containers::StridedArrayView1D<Vector3>&)
@m_deprecated_since_latest Use @ref flipNormalsInPlace(const Containers::StridedArrayView1D<UnsignedInt>&, const Containers::StridedArrayView1D<Vector3>&)
instead.
*/ */
void MAGNUM_MESHTOOLS_EXPORT flipNormals(std::vector<Vector3>& normals); CORRADE_DEPRECATED("use flipNormalsInPlace() instead") MAGNUM_MESHTOOLS_EXPORT void flipNormals(std::vector<UnsignedInt>& indices, std::vector<Vector3>& normals);
#endif
/** /**
@brief Flip mesh normals and face winding @brief Flip face winding in-place
@param[in,out] indices Index array to operate on @param[in,out] indices Index array to operate on
@m_since_latest
Same as @ref flipNormalsInPlace(const Containers::StridedArrayView1D<UnsignedInt>&, const Containers::StridedArrayView1D<Vector3>&),
but flips only face winding. Expects a triangle mesh, thus the index count has
to be divisible by 3.
*/
void MAGNUM_MESHTOOLS_EXPORT flipFaceWindingInPlace(const Containers::StridedArrayView1D<UnsignedInt>& indices);
/**
* @overload
* @m_since_latest
*/
void MAGNUM_MESHTOOLS_EXPORT flipFaceWindingInPlace(const Containers::StridedArrayView1D<UnsignedShort>& indices);
/**
* @overload
* @m_since_latest
*/
void MAGNUM_MESHTOOLS_EXPORT flipFaceWindingInPlace(const Containers::StridedArrayView1D<UnsignedByte>& indices);
#ifdef MAGNUM_BUILD_DEPRECATED
/**
@brief @copybrief flipFaceWindingInPlace(const Containers::StridedArrayView1D<UnsignedInt>&)
@m_deprecated_since_latest Use @ref flipFaceWindingInPlace(const Containers::StridedArrayView1D<UnsignedInt>&)
instead.
*/
CORRADE_DEPRECATED("use flipFaceWindingInPlace() instead") MAGNUM_MESHTOOLS_EXPORT void flipFaceWinding(std::vector<UnsignedInt>& indices);
#endif
/**
@brief Flip mesh normals in-place
@param[in,out] normals Normal array to operate on @param[in,out] normals Normal array to operate on
Flips normal vectors and face winding in index array for face culling to work Same as @ref flipNormalsInPlace(const Containers::StridedArrayView1D<UnsignedInt>&, const Containers::StridedArrayView1D<Vector3>&),
properly too. See also @ref flipNormals(std::vector<Vector3>&) and but flips only normals, not face winding.
@ref flipFaceWinding(), which flip normals or face winding only. */
void MAGNUM_MESHTOOLS_EXPORT flipNormalsInPlace(const Containers::StridedArrayView1D<Vector3>& normals);
@attention The function requires the mesh to have triangle faces, thus index #ifdef MAGNUM_BUILD_DEPRECATED
count must be divisible by 3. /**
@copybrief flipNormalsInPlace(const Containers::StridedArrayView1D<Vector3>&)
@m_deprecated_since_latest Use @ref flipNormalsInPlace(const Containers::StridedArrayView1D<Vector3>&)
instead.
*/ */
inline void flipNormals(std::vector<UnsignedInt>& indices, std::vector<Vector3>& normals) { CORRADE_DEPRECATED("use flipNormalsInPlace() instead") MAGNUM_MESHTOOLS_EXPORT void flipNormals(std::vector<Vector3>& normals);
flipFaceWinding(indices); #endif
flipNormals(normals);
inline void flipNormalsInPlace(const Containers::StridedArrayView1D<UnsignedInt>& indices, const Containers::StridedArrayView1D<Vector3>& normals) {
flipFaceWindingInPlace(indices);
flipNormalsInPlace(normals);
}
inline void flipNormalsInPlace(const Containers::StridedArrayView1D<UnsignedShort>& indices, const Containers::StridedArrayView1D<Vector3>& normals) {
flipFaceWindingInPlace(indices);
flipNormalsInPlace(normals);
}
inline void flipNormalsInPlace(const Containers::StridedArrayView1D<UnsignedByte>& indices, const Containers::StridedArrayView1D<Vector3>& normals) {
flipFaceWindingInPlace(indices);
flipNormalsInPlace(normals);
} }
}} }}

18
src/Magnum/MeshTools/Implementation/Tipsify.h

@ -25,7 +25,8 @@
DEALINGS IN THE SOFTWARE. DEALINGS IN THE SOFTWARE.
*/ */
#include <vector> #include <Corrade/Containers/Array.h>
#include <Corrade/Containers/StridedArrayView.h>
#include "Magnum/Magnum.h" #include "Magnum/Magnum.h"
@ -33,11 +34,10 @@ namespace Magnum { namespace MeshTools { namespace Implementation { namespace {
/* Vertex-triangle adjacency. Computes count and indices of adjacent triangles /* Vertex-triangle adjacency. Computes count and indices of adjacent triangles
for each vertex (used internally by tipsify()) */ for each vertex (used internally by tipsify()) */
void buildAdjacency(const std::vector<UnsignedInt>& indices, const UnsignedInt vertexCount, std::vector<UnsignedInt>& liveTriangleCount, std::vector<UnsignedInt>& neighborOffset, std::vector<UnsignedInt>& neighbors) { template<class T> void buildAdjacency(const Containers::StridedArrayView1D<const T>& indices, const UnsignedInt vertexCount, Containers::Array<UnsignedInt>& liveTriangleCount, Containers::Array<UnsignedInt>& neighborOffset, Containers::Array<UnsignedInt>& neighbors) {
/* How many times is each vertex referenced == count of neighboring /* How many times is each vertex referenced == count of neighboring
triangles for each vertex */ triangles for each vertex */
liveTriangleCount.clear(); liveTriangleCount = Containers::Array<UnsignedInt>{vertexCount};
liveTriangleCount.resize(vertexCount);
for(std::size_t i = 0; i != indices.size(); ++i) for(std::size_t i = 0; i != indices.size(); ++i)
++liveTriangleCount[indices[i]]; ++liveTriangleCount[indices[i]];
@ -45,19 +45,17 @@ void buildAdjacency(const std::vector<UnsignedInt>& indices, const UnsignedInt v
the end be in interval neighbors[neighborOffset[i]] ; the end be in interval neighbors[neighborOffset[i]] ;
neighbors[neighborOffset[i+1]]. Currently the values are shifted to neighbors[neighborOffset[i+1]]. Currently the values are shifted to
right, because the next loop will shift them back left. */ right, because the next loop will shift them back left. */
neighborOffset.clear(); neighborOffset = Containers::Array<UnsignedInt>{Containers::NoInit, vertexCount + 1};
neighborOffset.reserve(vertexCount+1); neighborOffset[0] = 0;
neighborOffset.push_back(0);
UnsignedInt sum = 0; UnsignedInt sum = 0;
for(std::size_t i = 0; i != vertexCount; ++i) { for(std::size_t i = 0; i != vertexCount; ++i) {
neighborOffset.push_back(sum); neighborOffset[i + 1] = sum;
sum += liveTriangleCount[i]; sum += liveTriangleCount[i];
} }
/* Array of neighbors, using (and changing) neighborOffset array for /* Array of neighbors, using (and changing) neighborOffset array for
positioning */ positioning */
neighbors.clear(); neighbors = Containers::Array<UnsignedInt>{Containers::NoInit, sum};
neighbors.resize(sum);
for(std::size_t i = 0; i != indices.size(); ++i) for(std::size_t i = 0; i != indices.size(); ++i)
neighbors[neighborOffset[indices[i]+1]++] = i/3; neighbors[neighborOffset[indices[i]+1]++] = i/3;
} }

23
src/Magnum/MeshTools/Test/TipsifyTest.cpp

@ -23,7 +23,9 @@
DEALINGS IN THE SOFTWARE. DEALINGS IN THE SOFTWARE.
*/ */
#include <Corrade/Containers/Array.h>
#include <Corrade/TestSuite/Tester.h> #include <Corrade/TestSuite/Tester.h>
#include <Corrade/TestSuite/Compare/Container.h>
#include "Magnum/Magnum.h" #include "Magnum/Magnum.h"
#include "Magnum/MeshTools/Tipsify.h" #include "Magnum/MeshTools/Tipsify.h"
@ -54,7 +56,7 @@ struct TipsifyTest: TestSuite::Tester {
*/ */
const std::vector<UnsignedInt> Indices{ constexpr UnsignedInt Indices[]{
4, 1, 0, 4, 1, 0,
10, 9, 13, 10, 9, 13,
6, 3, 2, 6, 3, 2,
@ -88,27 +90,26 @@ TipsifyTest::TipsifyTest() {
} }
void TipsifyTest::buildAdjacency() { void TipsifyTest::buildAdjacency() {
std::vector<UnsignedInt> indices = Indices; Containers::Array<UnsignedInt> liveTriangleCount, neighborOffset, neighbors;
std::vector<UnsignedInt> liveTriangleCount, neighborOffset, neighbors; Implementation::buildAdjacency(Containers::stridedArrayView(Indices), VertexCount, liveTriangleCount, neighborOffset, neighbors);
Implementation::buildAdjacency(indices, VertexCount, liveTriangleCount, neighborOffset, neighbors);
CORRADE_COMPARE(liveTriangleCount, (std::vector<UnsignedInt>{ CORRADE_COMPARE_AS(liveTriangleCount, Containers::arrayView<UnsignedInt>({
1, 3, 3, 2, 1, 3, 3, 2,
4, 6, 6, 2, 4, 6, 6, 2,
2, 6, 6, 4, 2, 6, 6, 4,
2, 3, 3, 1, 2, 3, 3, 1,
1, 1, 1 1, 1, 1
})); }), TestSuite::Compare::Container);
CORRADE_COMPARE(neighborOffset, (std::vector<UnsignedInt>{ CORRADE_COMPARE_AS(neighborOffset, Containers::arrayView<UnsignedInt>({
0, 1, 4, 7, 0, 1, 4, 7,
9, 13, 19, 25, 9, 13, 19, 25,
27, 29, 35, 41, 27, 29, 35, 41,
45, 47, 50, 53, 45, 47, 50, 53,
54, 55, 56, 57 54, 55, 56, 57
})); }), TestSuite::Compare::Container);
CORRADE_COMPARE(neighbors, (std::vector<UnsignedInt>{ CORRADE_COMPARE_AS(neighbors, Containers::arrayView<UnsignedInt>({
0, 0,
0, 7, 11, 0, 7, 11,
2, 7, 13, 2, 7, 13,
@ -130,11 +131,11 @@ void TipsifyTest::buildAdjacency() {
6, 6,
18, 18, 18 18, 18, 18
})); }), TestSuite::Compare::Container);
} }
void TipsifyTest::tipsify() { void TipsifyTest::tipsify() {
std::vector<UnsignedInt> indices = Indices; std::vector<UnsignedInt> indices{std::begin(Indices), std::end(Indices)};
MeshTools::tipsify(indices, VertexCount, 3); MeshTools::tipsify(indices, VertexCount, 3);
CORRADE_COMPARE(indices, (std::vector<UnsignedInt>{ CORRADE_COMPARE(indices, (std::vector<UnsignedInt>{

58
src/Magnum/MeshTools/Tipsify.cpp

@ -25,36 +25,43 @@
#include "Tipsify.h" #include "Tipsify.h"
#include <stack> #include <Corrade/Containers/GrowableArray.h>
#include <Corrade/Utility/Algorithms.h>
#include "Magnum/MeshTools/Implementation/Tipsify.h" #include "Magnum/MeshTools/Implementation/Tipsify.h"
namespace Magnum { namespace MeshTools { namespace Magnum { namespace MeshTools {
void tipsify(std::vector<UnsignedInt>& indices, const UnsignedInt vertexCount, const std::size_t cacheSize) { namespace {
template<class T> void tipsifyInPlaceImplementation(const Containers::StridedArrayView1D<T>& indices, const UnsignedInt vertexCount, const std::size_t cacheSize) {
/* Neighboring triangles for each vertex, per-vertex live triangle count */ /* Neighboring triangles for each vertex, per-vertex live triangle count */
std::vector<UnsignedInt> liveTriangleCount, neighborOffset, neighbors; Containers::Array<UnsignedInt> liveTriangleCount, neighborOffset, neighbors;
Implementation::buildAdjacency(indices, vertexCount, liveTriangleCount, neighborOffset, neighbors); Implementation::buildAdjacency<T>(indices, vertexCount, liveTriangleCount, neighborOffset, neighbors);
/* Global time, per-vertex caching timestamps, per-triangle emmited flag */ /* Global time, per-vertex caching timestamps, per-triangle emmited flag */
UnsignedInt time = cacheSize+1; UnsignedInt time = cacheSize+1;
std::vector<UnsignedInt> timestamp(vertexCount); Containers::Array<UnsignedInt> timestamp{vertexCount};
std::vector<bool> emitted(indices.size()/3); /** @todo Have some bitset/staticbitset class for this */
Containers::Array<bool> emitted{indices.size()/3};
/* Dead-end vertex stack */ /* Dead-end vertex stack */
std::stack<UnsignedInt> deadEndStack; Containers::Array<UnsignedInt> deadEndStack;
/* Output index buffer */ /* Output index buffer */
std::vector<UnsignedInt> outputIndices; Containers::Array<T> outputIndices{Containers::NoInit, indices.size()};
outputIndices.reserve(indices.size()); std::size_t outputIndex = 0;
/* Array with candidates for next fanning vertex (in 1-ring around
fanning vertex) */
Containers::Array<UnsignedInt> candidates;
/* Starting vertex for fanning, cursor */ /* Starting vertex for fanning, cursor */
UnsignedInt fanningVertex = 0; UnsignedInt fanningVertex = 0;
UnsignedInt i = 0; UnsignedInt i = 0;
while(fanningVertex != 0xFFFFFFFFu) { while(fanningVertex != 0xFFFFFFFFu) {
/* Array with candidates for next fanning vertex (in 1-ring around /* Reset the candidates for this vertex */
fanning vertex) */ arrayResize(candidates, 0);
std::vector<UnsignedInt> candidates;
/* For all neighbors of fanning vertex */ /* For all neighbors of fanning vertex */
for(UnsignedInt ti = neighborOffset[fanningVertex]; ti != neighborOffset[fanningVertex+1]; ++ti) { for(UnsignedInt ti = neighborOffset[fanningVertex]; ti != neighborOffset[fanningVertex+1]; ++ti) {
@ -68,12 +75,12 @@ void tipsify(std::vector<UnsignedInt>& indices, const UnsignedInt vertexCount, c
for(UnsignedInt vi = 0; vi != 3; ++vi) { for(UnsignedInt vi = 0; vi != 3; ++vi) {
const UnsignedInt v = indices[vi + t*3]; const UnsignedInt v = indices[vi + t*3];
outputIndices.push_back(v); outputIndices[outputIndex++] = v;
/* Add to dead end stack and candidates array */ /* Add to dead end stack and candidates array */
/** @todo Limit size of dead end stack to cache size */ /** @todo Limit size of dead end stack to cache size */
deadEndStack.push(v); arrayAppend(deadEndStack, v);
candidates.push_back(v); arrayAppend(candidates, v);
/* Decrease live triangle count */ /* Decrease live triangle count */
--liveTriangleCount[v]; --liveTriangleCount[v];
@ -109,8 +116,8 @@ void tipsify(std::vector<UnsignedInt>& indices, const UnsignedInt vertexCount, c
if(fanningVertex == 0xFFFFFFFFu) { if(fanningVertex == 0xFFFFFFFFu) {
/* Find vertex with live triangles in dead-end stack */ /* Find vertex with live triangles in dead-end stack */
while(!deadEndStack.empty()) { while(!deadEndStack.empty()) {
unsigned int d = deadEndStack.top(); UnsignedInt d = deadEndStack.back();
deadEndStack.pop(); arrayRemoveSuffix(deadEndStack);
if(!liveTriangleCount[d]) continue; if(!liveTriangleCount[d]) continue;
fanningVertex = d; fanningVertex = d;
@ -129,8 +136,21 @@ void tipsify(std::vector<UnsignedInt>& indices, const UnsignedInt vertexCount, c
} }
/* Swap original index buffer with optimized */ /* Swap original index buffer with optimized */
using std::swap; Utility::copy(outputIndices, indices);
swap(indices, outputIndices); }
}
void tipsifyInPlace(const Containers::StridedArrayView1D<UnsignedInt>& indices, const UnsignedInt vertexCount, const std::size_t cacheSize) {
tipsifyInPlaceImplementation(indices, vertexCount, cacheSize);
}
void tipsifyInPlace(const Containers::StridedArrayView1D<UnsignedShort>& indices, const UnsignedInt vertexCount, const std::size_t cacheSize) {
tipsifyInPlaceImplementation(indices, vertexCount, cacheSize);
}
void tipsifyInPlace(const Containers::StridedArrayView1D<UnsignedByte>& indices, const UnsignedInt vertexCount, const std::size_t cacheSize) {
tipsifyInPlaceImplementation(indices, vertexCount, cacheSize);
} }
}} }}

41
src/Magnum/MeshTools/Tipsify.h

@ -26,30 +26,59 @@
*/ */
/** @file /** @file
* @brief Function @ref Magnum::MeshTools::tipsify() * @brief Function @ref Magnum::MeshTools::tipsifyInPlace()
*/ */
#include <vector> #include <Corrade/Containers/Containers.h>
#include "Magnum/Types.h" #include "Magnum/Magnum.h"
#include "Magnum/MeshTools/visibility.h" #include "Magnum/MeshTools/visibility.h"
#ifdef MAGNUM_BUILD_DEPRECATED
#include <vector>
#include <Corrade/Containers/ArrayViewStl.h>
#include <Corrade/Containers/StridedArrayView.h>
#include <Corrade/Utility/Macros.h>
#endif
namespace Magnum { namespace MeshTools { namespace Magnum { namespace MeshTools {
/** /**
@brief Tipsify the mesh @brief Tipsify the mesh in-place
@param[in,out] indices Indices array to operate on @param[in,out] indices Indices array to operate on
@param[in] vertexCount Vertex count @param[in] vertexCount Vertex count
@param[in] cacheSize Post-transform vertex cache size @param[in] cacheSize Post-transform vertex cache size
Optimizes the mesh for vertex-bound applications by rearranging its index Optimizes the mesh for vertex-bound applications by rearranging its index
array for beter usage of post-transform vertex cache. Algorithm used: array for beter usage of post-transform vertex cache. Algorithm used:
*Pedro V. Sander, Diego Nehab, and Joshua Barczak --- Fast Triangle Reordering * *Pedro V. Sander, Diego Nehab, and Joshua Barczak --- Fast Triangle Reordering
for Vertex Locality and Reduced Overdraw, SIGGRAPH 2007, for Vertex Locality and Reduced Overdraw, SIGGRAPH 2007,
http://gfx.cs.princeton.edu/pubs/Sander_2007_%3ETR/index.php*. http://gfx.cs.princeton.edu/pubs/Sander_2007_%3ETR/index.php*.
@todo Ability to compute vertex count automatically @todo Ability to compute vertex count automatically
*/ */
MAGNUM_MESHTOOLS_EXPORT void tipsify(std::vector<UnsignedInt>& indices, UnsignedInt vertexCount, std::size_t cacheSize); MAGNUM_MESHTOOLS_EXPORT void tipsifyInPlace(const Containers::StridedArrayView1D<UnsignedInt>& indices, UnsignedInt vertexCount, std::size_t cacheSize);
/**
* @overload
* @m_since_latest
*/
MAGNUM_MESHTOOLS_EXPORT void tipsifyInPlace(const Containers::StridedArrayView1D<UnsignedShort>& indices, UnsignedInt vertexCount, std::size_t cacheSize);
/**
* @overload
* @m_since_latest
*/
MAGNUM_MESHTOOLS_EXPORT void tipsifyInPlace(const Containers::StridedArrayView1D<UnsignedByte>& indices, UnsignedInt vertexCount, std::size_t cacheSize);
#ifdef MAGNUM_BUILD_DEPRECATED
/**
* @brief @copybrief tipsifyInPlace()
* @m_deprecated_since_latest Use @ref tipsifyInPlace() instead.
*/
inline CORRADE_DEPRECATED("use tipsifyInPlace() instead") void tipsify(std::vector<UnsignedInt>& indices, UnsignedInt vertexCount, std::size_t cacheSize) {
tipsifyInPlace(indices, vertexCount, cacheSize);
}
#endif
}} }}

Loading…
Cancel
Save