Browse Source

MeshTools: added a STL-less subdivideInPlace() variant.

What's extremely funny is that this made the benchmark *twice as fast*
in Debug.
pull/405/head
Vladimír Vondruš 6 years ago
parent
commit
2e52cc0f3c
  1. 5
      doc/changelog.dox
  2. 64
      src/Magnum/MeshTools/Subdivide.h

5
doc/changelog.dox

@ -113,6 +113,11 @@ See also:
in order to allow passing runtime-sized lists (see
[mosra/magnum#403](https://github.com/mosra/magnum/pull/403))
@subsubsection changelog-latest-changes-meshtools MeshTools library
- Added @ref MeshTools::subdivideInPlace() that operates on a partially
filled array view instead of a @ref std::vector
@subsubsection changelog-latest-changes-platform Platform libraries
- Worked around @ref Platform::GlfwApplication crash while creating GL

64
src/Magnum/MeshTools/Subdivide.h

@ -26,41 +26,69 @@
*/
/** @file
* @brief Function @ref Magnum::MeshTools::subdivide()
* @brief Function @ref Magnum::MeshTools::subdivide(), @ref Magnum::MeshTools::subdivideInPlace()
*/
#include <vector>
#include <Corrade/Containers/ArrayViewStl.h>
#include <Corrade/Utility/Assert.h>
namespace Magnum { namespace MeshTools {
#ifndef DOXYGEN_GENERATING_OUTPUT
template<class Vertex, class Interpolator> void subdivideInPlace(Containers::ArrayView<UnsignedInt> indices, Containers::ArrayView<Vertex> vertices, Interpolator interpolator);
#endif
/**
@brief Subdivide the mesh
@tparam Vertex Vertex data type
@tparam Interpolator See `interpolator` function parameter
@tparam Interpolator See the @p interpolator function parameter
@param[in,out] indices Index array to operate on
@param[in,out] vertices Vertex array to operate on
@param interpolator Functor or function pointer which interpolates
two adjacent vertices: `Vertex interpolator(Vertex a, Vertex b)`
two adjacent vertices: @cpp Vertex interpolator(Vertex a, Vertex b) @ce
Goes through all triangle faces and subdivides them into four new. Removing
duplicate vertices in the mesh is up to user.
duplicate vertices in the mesh is up to the user.
@see @ref subdivideInPlace()
*/
template<class Vertex, class Interpolator> void subdivide(std::vector<UnsignedInt>& indices, std::vector<Vertex>& vertices, Interpolator interpolator) {
CORRADE_ASSERT(!(indices.size()%3), "MeshTools::subdivide(): index count is not divisible by 3!", );
/* For each triangle it'll generate three new vertices and three more
triangles */
indices.reserve(indices.size()*4);
vertices.reserve(vertices.size() + indices.size());
vertices.resize(vertices.size() + indices.size());
indices.resize(indices.size()*4);
subdivideInPlace(Containers::arrayView(indices), Containers::arrayView(vertices), interpolator);
}
/**
@brief Subdivide the mesh in-place
@tparam Vertex Vertex data type
@tparam Interpolator See the @p interpolator function parameter
@param[in,out] indices Index array to operate on
@param[in,out] vertices Vertex array to operate on
@param interpolator Functor or function pointer which interpolates
two adjacent vertices: @cpp Vertex interpolator(Vertex a, Vertex b) @ce
Assumes the original triangle mesh indices are in the first quarter of the
@p indices array and original vertices in a prefix of the @p vertices array,
with @cpp indices.size() @ce left at the end of it for newly added vertices.
Then goes through all those triangle faces and subdivides them into four new,
filling up the remaining space in both. Removing duplicate vertices in the mesh
is up to the user.
*/
template<class Vertex, class Interpolator> void subdivideInPlace(Containers::ArrayView<UnsignedInt> indices, Containers::ArrayView<Vertex> vertices, Interpolator interpolator) {
CORRADE_ASSERT(!(indices.size()%12), "MeshTools::subdivideInto(): can't divide" << indices.size() << "indices to four parts with each having triangle faces", );
/* Subdivide each face to four new */
std::size_t indexCount = indices.size();
const std::size_t indexCount = indices.size()/4;
std::size_t indexOffset = indexCount;
std::size_t vertexOffset = vertices.size() - indexCount;
for(std::size_t i = 0; i != indexCount; i += 3) {
/* Interpolate each side */
UnsignedInt newVertices[3];
for(int j = 0; j != 3; ++j) {
newVertices[j] = vertices.size(); vertices.push_back(interpolator(vertices[indices[i+j]], vertices[indices[i+(j+1)%3]]));
newVertices[j] = vertexOffset;
vertices[vertexOffset++] = interpolator(vertices[indices[i+j]], vertices[indices[i+(j+1)%3]]);
}
/*
@ -76,11 +104,17 @@ template<class Vertex, class Interpolator> void subdivide(std::vector<UnsignedIn
/ \ / \
orig 1 ----- new 1 ---- orig 2
*/
indices.insert(indices.end(), {
indices[i], newVertices[0], newVertices[2],
newVertices[0], indices[i+1], newVertices[1],
newVertices[2], newVertices[1], indices[i+2]
});
indices[indexOffset++] = indices[i];
indices[indexOffset++] = newVertices[0];
indices[indexOffset++] = newVertices[2];
indices[indexOffset++] = newVertices[0];
indices[indexOffset++] = indices[i+1];
indices[indexOffset++] = newVertices[1];
indices[indexOffset++] = newVertices[2];
indices[indexOffset++] = newVertices[1];
indices[indexOffset++] = indices[i+2];
for(std::size_t j = 0; j != 3; ++j)
indices[i+j] = newVertices[j];
}

Loading…
Cancel
Save