diff --git a/doc/changelog.dox b/doc/changelog.dox index 7a5b9be6f..a2ce112da 100644 --- a/doc/changelog.dox +++ b/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 diff --git a/src/Magnum/MeshTools/Subdivide.h b/src/Magnum/MeshTools/Subdivide.h index ce09d1b98..41b7e42d8 100644 --- a/src/Magnum/MeshTools/Subdivide.h +++ b/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 +#include #include namespace Magnum { namespace MeshTools { +#ifndef DOXYGEN_GENERATING_OUTPUT +template void subdivideInPlace(Containers::ArrayView indices, Containers::ArrayView 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 void subdivide(std::vector& indices, std::vector& 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 void subdivideInPlace(Containers::ArrayView indices, Containers::ArrayView 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 void subdivide(std::vector