mirror of https://github.com/mosra/magnum.git
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
105 lines
3.7 KiB
105 lines
3.7 KiB
#ifndef Magnum_MeshTools_Subdivide_h |
|
#define Magnum_MeshTools_Subdivide_h |
|
/* |
|
Copyright © 2010, 2011, 2012 Vladimír Vondruš <mosra@centrum.cz> |
|
|
|
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::subdivide() |
|
*/ |
|
|
|
#include <vector> |
|
#include <Utility/Debug.h> |
|
|
|
namespace Magnum { namespace MeshTools { |
|
|
|
#ifndef DOXYGEN_GENERATING_OUTPUT |
|
namespace Implementation { |
|
|
|
template<class Vertex, class Interpolator> class Subdivide { |
|
public: |
|
inline Subdivide(std::vector<std::uint32_t>& indices, std::vector<Vertex>& vertices): indices(indices), vertices(vertices) {} |
|
|
|
void operator()(Interpolator interpolator) { |
|
CORRADE_ASSERT(!(indices.size()%3), "MeshTools::subdivide(): index count is not divisible by 3!", ); |
|
|
|
std::size_t indexCount = indices.size(); |
|
indices.reserve(indices.size()*4); |
|
|
|
/* Subdivide each face to four new */ |
|
for(std::size_t i = 0; i != indexCount; i += 3) { |
|
/* Interpolate each side */ |
|
std::uint32_t newVertices[3]; |
|
for(int j = 0; j != 3; ++j) |
|
newVertices[j] = addVertex(interpolator(vertices[indices[i+j]], vertices[indices[i+(j+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(indices[i], newVertices[0], newVertices[2]); |
|
addFace(newVertices[0], indices[i+1], newVertices[1]); |
|
addFace(newVertices[2], newVertices[1], indices[i+2]); |
|
for(std::size_t j = 0; j != 3; ++j) |
|
indices[i+j] = newVertices[j]; |
|
} |
|
} |
|
|
|
private: |
|
std::vector<std::uint32_t>& indices; |
|
std::vector<Vertex>& vertices; |
|
|
|
std::uint32_t addVertex(const Vertex& v) { |
|
vertices.push_back(v); |
|
return vertices.size()-1; |
|
} |
|
|
|
void addFace(std::uint32_t first, std::uint32_t second, std::uint32_t third) { |
|
indices.push_back(first); |
|
indices.push_back(second); |
|
indices.push_back(third); |
|
} |
|
}; |
|
|
|
} |
|
#endif |
|
|
|
/** |
|
@brief %Subdivide the mesh |
|
@tparam Vertex Vertex data type |
|
@tparam Interpolator See `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)` |
|
|
|
Goes through all triangle faces and subdivides them into four new. Cleaning |
|
duplicate vertices in the mesh is up to user. |
|
*/ |
|
template<class Vertex, class Interpolator> inline void subdivide(std::vector<std::uint32_t>& indices, std::vector<Vertex>& vertices, Interpolator interpolator) { |
|
Implementation::Subdivide<Vertex, Interpolator>(indices, vertices)(interpolator); |
|
} |
|
|
|
}} |
|
|
|
#endif
|
|
|