namespace
MeshToolsMesh tools.
Contents
- Reference
Tools for generating, optimizing and cleaning meshes.
This library is built if WITH_MESHTOOLS
is enabled when building Magnum. To use this library with CMake, you need to request the MeshTools
component of the Magnum
package and link to the Magnum::MeshTools
target:
find_package(Magnum REQUIRED MeshTools) # ... target_link_libraries(your-app Magnum::MeshTools)
Note that functionality depending on GL APIs is available only if Magnum is built with both WITH_GL
and TARGET_GL
enabled (which is done by default).
See Downloading and building and Usage with CMake for more information.
Functions
-
auto combineIndexArrays(const std::
vector<UnsignedInt>& interleavedArrays, UnsignedInt stride) -> std:: pair<std:: vector<UnsignedInt>, std:: vector<UnsignedInt>> - Combine interleaved index arrays.
-
auto combineIndexArrays(const std::
vector<std:: reference_wrapper<std:: vector<UnsignedInt>>>& arrays) -> std:: vector<UnsignedInt> - Combine index arrays.
-
auto combineIndexArrays(std::
initializer_list<std:: reference_wrapper<std:: vector<UnsignedInt>>> arrays) -> std:: vector<UnsignedInt> -
template<class ... T>auto combineIndexedArrays(const std::
pair<const std:: vector<UnsignedInt>&, std:: vector<T>&>&... indexedArrays) -> std:: vector<UnsignedInt> - Combine indexed arrays.
-
auto compile(const Trade::
MeshData2D& meshData, GL:: BufferUsage usage) -> std:: tuple<GL::Mesh, std:: unique_ptr<GL::Buffer>, std:: unique_ptr<GL::Buffer>> - Compile 2D mesh data.
-
auto compile(const Trade::
MeshData3D& meshData, GL:: BufferUsage usage) -> std:: tuple<GL::Mesh, std:: unique_ptr<GL::Buffer>, std:: unique_ptr<GL::Buffer>> - Compile 3D mesh data.
-
auto compressIndices(const std::
vector<UnsignedInt>& indices) -> std:: tuple<Containers:: Array<char>, MeshIndexType, UnsignedInt, UnsignedInt> - Compress vertex indices.
-
template<class T>auto compressIndicesAs(const std::
vector<UnsignedInt>& indices) -> Containers:: Array<T> - Compress vertex indices as given type.
-
template<class T>auto duplicate(const std::
vector<UnsignedInt>& indices, const std:: vector<T>& data) -> std:: vector<T> - Duplicate data using index array.
-
void flipFaceWinding(std::
vector<UnsignedInt>& indices) - Flip face winding.
-
void flipNormals(std::
vector<Vector3>& normals) - Flip mesh normals.
-
void flipNormals(std::
vector<UnsignedInt>& indices, std:: vector<Vector3>& normals) - Flip mesh normals and face winding.
-
auto fullScreenTriangle(GL::
Version version) -> std:: pair<std:: unique_ptr<GL::Buffer>, GL::Mesh> - Create full screen triangle mesh.
-
auto fullScreenTriangle() -> std::
pair<std:: unique_ptr<GL::Buffer>, GL::Mesh> -
auto generateFlatNormals(const std::
vector<UnsignedInt>& indices, const std:: vector<Vector3>& positions) -> std:: tuple<std:: vector<UnsignedInt>, std:: vector<Vector3>> - Generate flat normals.
-
template<class T, class ... U>auto interleave(const T& first, const U&... next) -> Containers::
Array<char> - Interleave vertex attributes.
-
template<class T, class ... U>void interleaveInto(Containers::
ArrayView<char> buffer, const T& first, const U&... next) - Interleave vertex attributes into existing buffer.
-
template<class Vector>auto removeDuplicates(std::
vector<Vector>& data, typename Vector::Type epsilon = Math:: TypeTraits<typename Vector::Type>::epsilon()) -> std:: vector<UnsignedInt> - Remove duplicate floating-point vector data from given array.
-
template<class Vertex, class Interpolator>void subdivide(std::
vector<UnsignedInt>& indices, std:: vector<Vertex>& vertices, Interpolator interpolator) - Subdivide the mesh.
-
void tipsify(std::
vector<UnsignedInt>& indices, UnsignedInt vertexCount, std:: size_t cacheSize) - Tipsify the mesh.
-
template<class T, class U>void transformVectorsInPlace(const Math::
Quaternion<T>& normalizedQuaternion, U& vectors) - Transform vectors in-place using given transformation.
-
template<class T, class U>void transformVectorsInPlace(const Math::
Complex<T>& complex, U& vectors) -
template<class T, class U>void transformVectorsInPlace(const Math::
Matrix3<T>& matrix, U& vectors) -
template<class T, class U>void transformVectorsInPlace(const Math::
Matrix4<T>& matrix, U& vectors) -
template<class T, class U>auto transformVectors(const T& transformation, U vectors) -> U
- Transform vectors using given transformation.
-
template<class T, class U>void transformPointsInPlace(const Math::
DualQuaternion<T>& normalizedDualQuaternion, U& points) - Transform points in-place using given transformation.
-
template<class T, class U>void transformPointsInPlace(const Math::
DualComplex<T>& dualComplex, U& points) -
template<class T, class U>void transformPointsInPlace(const Math::
Matrix3<T>& matrix, U& points) -
template<class T, class U>void transformPointsInPlace(const Math::
Matrix4<T>& matrix, U& points) -
template<class T, class U>auto transformPoints(const T& transformation, U vectors) -> U
- Transform points using given transformation.
Function documentation
std:: pair<std:: vector<UnsignedInt>, std:: vector<UnsignedInt>> Magnum:: MeshTools:: combineIndexArrays(const std:: vector<UnsignedInt>& interleavedArrays,
UnsignedInt stride)
Combine interleaved index arrays.
Unlike above, this function takes one interleaved array instead of separate index arrays. Continuing with the above example, you would call this function with the following array (odd value is vertex index, even is normal index, stride
is thus 2):
0 1 2 3 5 4 0 1 0 4 1 6 3 1 2 3 2 1
Similarly to above this function will return the following combined index array as first pair value:
0 1 2 0 3 4 5 1 6
And second pair value is the cleaned up interleaved array:
0 1 2 3 5 4 0 4 1 6 3 1 2 1
std:: vector<UnsignedInt> Magnum:: MeshTools:: combineIndexArrays(const std:: vector<std:: reference_wrapper<std:: vector<UnsignedInt>>>& arrays)
Combine index arrays.
Parameters | |
---|---|
arrays in/out | Index arrays to combine. These arrays are updated in-place to contain unique combinations of the original indices. |
Returns | Resulting combined index array |
Creates new combined index array and updates the original ones with translation to new ones. For example, when you have position and normal array, each indexed with separate indices and you want to index both of them with single index array:
a b c d e f // positions A B C D E F G // normals 0 2 5 0 0 1 3 2 2 // position indices 1 3 4 1 4 6 1 3 1 // normal indices
In particular, first triangle in the mesh will have positions a c f
and normals B D E
. You can see that not all combinations are unique and also that there are some vertices unused. When you pass the two index arrays above to this function, the following combined index array is returned:
0 1 2 0 3 4 5 1 6
And the original arrays are cleaned up to have only unique combinations:
0 2 5 0 1 3 2 1 3 4 4 6 1 1
You can use these as translation table to create new vertex and normal arrays which can be then indexed with the combined index array:
a c f a b d c B D E E G B B
Again, first triangle in the mesh will have positions a c f
and normals B D E
.
This function calls combineIndexArrays(const std::
std:: vector<UnsignedInt> Magnum:: MeshTools:: combineIndexArrays(std:: initializer_list<std:: reference_wrapper<std:: vector<UnsignedInt>>> arrays)
This is an overloaded member function, provided for convenience. It differs from the above function only in what argument(s) it accepts.
template<class ... T>
std:: vector<UnsignedInt> Magnum:: MeshTools:: combineIndexedArrays(const std:: pair<const std:: vector<UnsignedInt>&, std:: vector<T>&>&... indexedArrays)
Combine indexed arrays.
Parameters | |
---|---|
indexedArrays in/out | Index and attribute arrays |
Returns | Array with resulting indices |
Creates new combined index array and reorders original attribute arrays so they can be indexed with the new single index array.
The index array must be passed as const reference (to avoid copying) and attribute array as reference, so it can be replaced with combined data. To avoid explicit verbose specification of tuple type, you can write it with help of some STL functions like shown below. Also if one index array is shared by more than one attribute array, just pass the index array more times. Example:
std::vector<UnsignedInt> vertexIndices; std::vector<Vector3> positions; std::vector<UnsignedInt> normalTextureIndices; std::vector<Vector3> normals; std::vector<Vector2> textureCoordinates; std::vector<UnsignedInt> indices = MeshTools::combineIndexedArrays( std::make_pair(std::cref(vertexIndices), std::ref(positions)), std::make_pair(std::cref(normalTextureIndices), std::ref(normals)), std::make_pair(std::cref(normalTextureIndices), std::ref(textureCoordinates)) );
See combineIndexArrays() documentation for more information about the procedure.
std:: tuple<GL::Mesh, std:: unique_ptr<GL::Buffer>, std:: unique_ptr<GL::Buffer>> Magnum:: MeshTools:: compile(const Trade:: MeshData2D& meshData,
GL:: BufferUsage usage)
Compile 2D mesh data.
Configures mesh for Shaders::usage
parameter is used for both vertex and index buffer.
The second returned buffer may be nullptr
if the mesh is not indexed.
This is just a convenience function for creating generic meshes, you might want to use interleave() and compressIndices() functions instead for greater flexibility.
std:: tuple<GL::Mesh, std:: unique_ptr<GL::Buffer>, std:: unique_ptr<GL::Buffer>> Magnum:: MeshTools:: compile(const Trade:: MeshData3D& meshData,
GL:: BufferUsage usage)
Compile 3D mesh data.
Configures mesh for Shaders::usage
parameter is used for both vertex and index buffer.
The second returned buffer may be nullptr
if the mesh is not indexed.
This is just a convenience function for creating generic meshes, you might want to use interleave() and compressIndices() functions instead for greater flexibility.
std:: tuple<Containers:: Array<char>, MeshIndexType, UnsignedInt, UnsignedInt> Magnum:: MeshTools:: compressIndices(const std:: vector<UnsignedInt>& indices)
Compress vertex indices.
Parameters | |
---|---|
indices | Index array |
Returns | Index range, type and compressed index array |
This function takes index array and outputs them compressed to smallest possible size. For example when your indices have maximum number 463, it's wasteful to store them in array of 32bit integers, array of 16bit integers is sufficient.
Example usage:
std::vector<UnsignedInt> indices; Containers::Array<char> indexData; MeshIndexType indexType; UnsignedInt indexStart, indexEnd; std::tie(indexData, indexType, indexStart, indexEnd) = MeshTools::compressIndices(indices); GL::Buffer indexBuffer; indexBuffer.setData(indexData, GL::BufferUsage::StaticDraw); GL::Mesh mesh; mesh.setCount(indices.size()) .setIndexBuffer(indexBuffer, 0, indexType, indexStart, indexEnd);
template<class T>
Containers:: Array<T> Magnum:: MeshTools:: compressIndicesAs(const std:: vector<UnsignedInt>& indices)
Compress vertex indices as given type.
The type can be either UnsignedByte, UnsignedShort or UnsignedInt. Values in the index array are expected to be representable with given type.
Example usage:
std::vector<UnsignedInt> indices; Containers::Array<UnsignedShort> indexData = MeshTools::compressIndicesAs<UnsignedShort>(indices);
template<class T>
std:: vector<T> Magnum:: MeshTools:: duplicate(const std:: vector<UnsignedInt>& indices,
const std:: vector<T>& data)
Duplicate data using index array.
Converts indexed array to non-indexed, for example data {a, b, c, d}
with index array {1, 1, 0, 3, 2, 2}
will be converted to {b, b, a, d, c, c}
.
void Magnum:: MeshTools:: flipFaceWinding(std:: vector<UnsignedInt>& indices)
Flip face winding.
Parameters | |
---|---|
indices in/out | Index array to operate on |
The same as flipNormals(std::
void Magnum:: MeshTools:: flipNormals(std:: vector<Vector3>& normals)
Flip mesh normals.
Parameters | |
---|---|
normals in/out | Normal array to operate on |
The same as flipNormals(std::
void Magnum:: MeshTools:: flipNormals(std:: vector<UnsignedInt>& indices,
std:: vector<Vector3>& normals)
Flip mesh normals and face winding.
Parameters | |
---|---|
indices in/out | Index array to operate on |
normals in/out | Normal array to operate on |
Flips normal vectors and face winding in index array for face culling to work properly too. See also flipNormals(std::
std:: pair<std:: unique_ptr<GL::Buffer>, GL::Mesh> Magnum:: MeshTools:: fullScreenTriangle(GL:: Version version)
Create full screen triangle mesh.
Returns pre-configured mesh along with vertex buffer which can be used for full-screen post-processing effects. The mesh is single triangle covering whole screen area ( on both dimensions) and provides only vertex positions, as other attributes (such as texture coordinates) can be computed from them. The vertex positions are, in order:
Based on version
parameter, on OpenGL 2.1 and OpenGL ES 2.0 the vertex positions are passed explicitly as attribute 0
, contained in the buffer. On OpenGL 3.0+ and OpenGL ES 3.0+ the mesh is attribute-less and the vertex positions can be computed using gl_VertexID
builtin shader variable, thus nullptr
is returned instead of vertex buffer.
Computing positions in vertex shader in a portable way might be done like this. For OpenGL 2.1 and OpenGL ES 2.0 you then need to bind the location of position
attribute to 0
.
#if (!defined(GL_ES) && __VERSION__ >= 130) || (defined(GL_ES) && __VERSION__ >= 300) #define NEW_GLSL #endif #ifndef NEW_GLSL attribute lowp vec4 position; #endif void main() { #ifdef NEW_GLSL gl_Position = vec4((gl_VertexID == 2) ? 3.0 : -1.0, (gl_VertexID == 1) ? -3.0 : 1.0, 0.0, 1.0); #else gl_Position = position; #endif }
std:: pair<std:: unique_ptr<GL::Buffer>, GL::Mesh> Magnum:: MeshTools:: fullScreenTriangle()
This is an overloaded member function, provided for convenience. It differs from the above function only in what argument(s) it accepts.
This function implicitly uses current context version.
std:: tuple<std:: vector<UnsignedInt>, std:: vector<Vector3>> Magnum:: MeshTools:: generateFlatNormals(const std:: vector<UnsignedInt>& indices,
const std:: vector<Vector3>& positions)
Generate flat normals.
Parameters | |
---|---|
indices | Array of triangle face indices |
positions | Array of vertex positions |
Returns | Normal indices and vectors |
For each face generates one normal vector, removes duplicates before returning. Example usage:
std::vector<UnsignedInt> vertexIndices; std::vector<Vector3> positions; std::vector<UnsignedInt> normalIndices; std::vector<Vector3> normals; std::tie(normalIndices, normals) = MeshTools::generateFlatNormals(vertexIndices, positions);
You can then use combineIndexedArrays() to combine normal and vertex array to use the same indices.
template<class T, class ... U>
Containers:: Array<char> Magnum:: MeshTools:: interleave(const T& first,
const U&... next)
Interleave vertex attributes.
This function takes list of attribute arrays and returns them interleaved, so data for each attribute are in continuous place in memory.
Example usage:
std::vector<Vector3> positions; std::vector<Vector2> textureCoordinates; GL::Buffer vertexBuffer; vertexBuffer.setData(MeshTools::interleave(positions, textureCoordinates), GL::BufferUsage::StaticDraw); GL::Mesh mesh; mesh.setCount(positions.size()) .addVertexBuffer(vertexBuffer, 0, MyShader::Position{}, MyShader::TextureCoordinates{});
It's often desirable to align data for one vertex on 32bit boundaries. To achieve that, you can specify gaps between the attributes:
std::vector<Vector4> positions; std::vector<UnsignedShort> weights; std::vector<Color3ub> vertexColors; auto data = MeshTools::interleave(positions, weights, 2, vertexColors, 1);
All gap bytes are set zero. This way vertex stride is 24 bytes, without gaps it would be 21 bytes, causing possible performance loss.
template<class T, class ... U>
void Magnum:: MeshTools:: interleaveInto(Containers:: ArrayView<char> buffer,
const T& first,
const U&... next)
Interleave vertex attributes into existing buffer.
Unlike interleave() this function interleaves the data into existing buffer and leaves gaps untouched instead of zero-initializing them. This function can thus be used for interleaving data depending on runtime parameters.
template<class Vector>
std:: vector<UnsignedInt> Magnum:: MeshTools:: removeDuplicates(std:: vector<Vector>& data,
typename Vector::Type epsilon = Math:: TypeTraits<typename Vector::Type>::epsilon())
Remove duplicate floating-point vector data from given array.
Parameters | |
---|---|
data in/out | Input data array |
epsilon in | Epsilon value, vertices nearer than this distance will be melt together |
Returns | Index array and unique data |
Removes duplicate data from the array by collapsing them into buckets of size epsilon
. First vector in given bucket is used, other ones are thrown away, no interpolation is done. Note that this function is meant to be used for floating-point data (or generally with non-zero epsilon
), for discrete data the usual sorting method is much more efficient.
If you want to remove duplicate data from already indexed array, first remove duplicates as if the array wasn't indexed at all and then use duplicate() to combine the two index arrays:
std::vector<UnsignedInt> indices; std::vector<Vector3> positions; indices = MeshTools::duplicate(indices, MeshTools::removeDuplicates(positions));
Removing duplicates in multiple indcidental arrays is also possible — first remove duplicates in each array separately and then use combineIndexedArrays() to combine the resulting index arrays to single index array and reorder the data accordingly:
std::vector<Vector3> positions; std::vector<Vector2> texCoords; std::vector<UnsignedInt> positionIndices = MeshTools::removeDuplicates(positions); std::vector<UnsignedInt> texCoordIndices = MeshTools::removeDuplicates(texCoords); std::vector<UnsignedInt> indices = MeshTools::combineIndexedArrays( std::make_pair(std::cref(positionIndices), std::ref(positions)), std::make_pair(std::cref(texCoordIndices), std::ref(texCoords)) );
template<class Vertex, class Interpolator>
void Magnum:: MeshTools:: subdivide(std:: vector<UnsignedInt>& indices,
std:: vector<Vertex>& vertices,
Interpolator interpolator)
Subdivide the mesh.
Template parameters | |
---|---|
Vertex | Vertex data type |
Interpolator | See interpolator function parameter |
Parameters | |
indices in/out | Index array to operate on |
vertices in/out | Vertex array to operate on |
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. Removing duplicate vertices in the mesh is up to user.
void Magnum:: MeshTools:: tipsify(std:: vector<UnsignedInt>& indices,
UnsignedInt vertexCount,
std:: size_t cacheSize)
Tipsify the mesh.
Parameters | |
---|---|
indices in/out | Indices array to operate on |
vertexCount in | Vertex count |
cacheSize in | Post-transform vertex cache size |
Optimizes the mesh for vertex-bound applications by rearranging its index array for beter usage of post-transform vertex cache. Algorithm used: Pedro V. Sander, Diego Nehab, and Joshua Barczak — Fast Triangle Reordering for Vertex Locality and Reduced Overdraw, SIGGRAPH 2007, http://gfx.cs.princeton.edu/pubs/Sander_
template<class T, class U>
void Magnum:: MeshTools:: transformVectorsInPlace(const Math:: Quaternion<T>& normalizedQuaternion,
U& vectors)
Transform vectors in-place using given transformation.
Usable for one-time mesh transformations that would otherwise negatively affect dependent objects, such as (uneven) scaling. Accepts any forward-iterable type with compatible vector type as vectors
. Expects that Quaternion is normalized, no further requirements are for other transformation representations.
Unlike in transformPointsInPlace(), the transformation does not involve translation.
Example usage:
std::vector<Vector3> vectors; auto transformation = Quaternion::rotation(35.0_degf, Vector3::yAxis()); MeshTools::transformVectorsInPlace(transformation, vectors);
template<class T, class U>
void Magnum:: MeshTools:: transformVectorsInPlace(const Math:: Complex<T>& complex,
U& vectors)
This is an overloaded member function, provided for convenience. It differs from the above function only in what argument(s) it accepts.
template<class T, class U>
void Magnum:: MeshTools:: transformVectorsInPlace(const Math:: Matrix3<T>& matrix,
U& vectors)
This is an overloaded member function, provided for convenience. It differs from the above function only in what argument(s) it accepts.
template<class T, class U>
void Magnum:: MeshTools:: transformVectorsInPlace(const Math:: Matrix4<T>& matrix,
U& vectors)
This is an overloaded member function, provided for convenience. It differs from the above function only in what argument(s) it accepts.
template<class T, class U>
U Magnum:: MeshTools:: transformVectors(const T& transformation,
U vectors)
Transform vectors using given transformation.
Returns transformed vectors instead of modifying them in-place. See transformVectorsInPlace() for more information.
template<class T, class U>
void Magnum:: MeshTools:: transformPointsInPlace(const Math:: DualQuaternion<T>& normalizedDualQuaternion,
U& points)
Transform points in-place using given transformation.
Usable for one-time mesh transformations that would otherwise negatively affect dependent objects, such as (uneven) scaling. Accepts any forward-iterable type with compatible vector type as vectors
. Expects that DualQuaternion is normalized, no further requirements are for other transformation representations.
Unlike in transformVectorsInPlace(), the transformation also involves translation.
Example usage:
std::vector<Vector3> points; auto transformation = DualQuaternion::rotation(35.0_degf, Vector3::yAxis())* DualQuaternion::translation({0.5f, -1.0f, 3.0f}); MeshTools::transformPointsInPlace(transformation, points);
template<class T, class U>
void Magnum:: MeshTools:: transformPointsInPlace(const Math:: DualComplex<T>& dualComplex,
U& points)
This is an overloaded member function, provided for convenience. It differs from the above function only in what argument(s) it accepts.
template<class T, class U>
void Magnum:: MeshTools:: transformPointsInPlace(const Math:: Matrix3<T>& matrix,
U& points)
This is an overloaded member function, provided for convenience. It differs from the above function only in what argument(s) it accepts.
template<class T, class U>
void Magnum:: MeshTools:: transformPointsInPlace(const Math:: Matrix4<T>& matrix,
U& points)
This is an overloaded member function, provided for convenience. It differs from the above function only in what argument(s) it accepts.
template<class T, class U>
U Magnum:: MeshTools:: transformPoints(const T& transformation,
U vectors)
Transform points using given transformation.
Returns transformed points instead of modifying them in-place. See transformPointsInPlace() for more information.