Browse Source

MeshTools: generate*Indices() overloads taking an existing index buffer.

To perform conversion of an already-indexed TriangleStrip to Triangles,
for example, without having to perform an expensive deindexing using
duplicate() first.
pull/601/head
Vladimír Vondruš 3 years ago
parent
commit
4a83ea67ef
  1. 6
      doc/changelog.dox
  2. 204
      src/Magnum/MeshTools/GenerateIndices.cpp
  3. 200
      src/Magnum/MeshTools/GenerateIndices.h
  4. 227
      src/Magnum/MeshTools/Test/GenerateIndicesTest.cpp

6
doc/changelog.dox

@ -551,6 +551,12 @@ See also:
@relativeref{MeshTools,generateIndices()} now allow empty input, producing
an empty index buffer as a result. Disallowing empty input was an
unnecessary restriction that was inconsistent with other APIs.
- Added overloads to @ref MeshTools::generateLineStripIndices(),
@relativeref{MeshTools,generateLineLoopIndices()},
@relativeref{MeshTools,generateTriangleStripIndices()} and
@relativeref{MeshTools,generateTriangleFanIndices()} that take an existing
index buffer instead of vertex count as an input to generate an index
buffer for a mesh that's already indexed.
@subsubsection changelog-latest-changes-platform Platform libraries

204
src/Magnum/MeshTools/GenerateIndices.cpp

@ -104,12 +104,62 @@ void generateLineStripIndicesInto(const UnsignedInt vertexCount, const Container
}
}
namespace {
template<class T> void generateLineStripIndicesIntoImplementation(const Containers::StridedArrayView1D<const T>& indices, const Containers::StridedArrayView1D<UnsignedInt>& output) {
CORRADE_ASSERT(indices.size() == 0 || indices.size() >= 2,
"MeshTools::generateLineStripIndicesInto(): expected either zero or at least two indices, got" << indices.size(), );
const UnsignedInt iMax = Math::max(indices.size(), std::size_t{1}) - 1;
CORRADE_ASSERT(output.size() == 2*iMax,
"MeshTools::generateLineStripIndicesInto(): bad output size, expected" << 2*iMax << "but got" << output.size(), );
/* Same as generateLineStripIndicesInto() above, just with the index array
indirection on top */
for(std::size_t i = 0; i != iMax; ++i) {
output[i*2 + 0] = indices[i];
output[i*2 + 1] = indices[i + 1];
}
}
}
void generateLineStripIndicesInto(const Containers::StridedArrayView1D<const UnsignedInt>& indices, const Containers::StridedArrayView1D<UnsignedInt>& output) {
generateLineStripIndicesIntoImplementation(indices, output);
}
void generateLineStripIndicesInto(const Containers::StridedArrayView1D<const UnsignedShort>& indices, const Containers::StridedArrayView1D<UnsignedInt>& output) {
generateLineStripIndicesIntoImplementation(indices, output);
}
void generateLineStripIndicesInto(const Containers::StridedArrayView1D<const UnsignedByte>& indices, const Containers::StridedArrayView1D<UnsignedInt>& output) {
generateLineStripIndicesIntoImplementation(indices, output);
}
Containers::Array<UnsignedInt> generateLineStripIndices(const UnsignedInt vertexCount) {
Containers::Array<UnsignedInt> output{NoInit, 2*(Math::max(vertexCount, 1u) - 1)};
generateLineStripIndicesInto(vertexCount, output);
return output;
}
Containers::Array<UnsignedInt> generateLineStripIndices(const Containers::StridedArrayView1D<const UnsignedInt>& indices) {
Containers::Array<UnsignedInt> output{NoInit, 2*(Math::max(indices.size(), std::size_t{1}) - 1)};
generateLineStripIndicesInto(indices, output);
return output;
}
Containers::Array<UnsignedInt> generateLineStripIndices(const Containers::StridedArrayView1D<const UnsignedShort>& indices) {
Containers::Array<UnsignedInt> output{NoInit, 2*(Math::max(indices.size(), std::size_t{1}) - 1)};
generateLineStripIndicesInto(indices, output);
return output;
}
Containers::Array<UnsignedInt> generateLineStripIndices(const Containers::StridedArrayView1D<const UnsignedByte>& indices) {
Containers::Array<UnsignedInt> output{NoInit, 2*(Math::max(indices.size(), std::size_t{1}) - 1)};
generateLineStripIndicesInto(indices, output);
return output;
}
void generateLineLoopIndicesInto(const UnsignedInt vertexCount, const Containers::StridedArrayView1D<UnsignedInt>& output) {
CORRADE_ASSERT(vertexCount == 0 || vertexCount >= 2,
"MeshTools::generateLineLoopIndicesInto(): expected either zero or at least two vertices, got" << vertexCount, );
@ -135,12 +185,64 @@ void generateLineLoopIndicesInto(const UnsignedInt vertexCount, const Containers
}
}
namespace {
template<class T> void generateLineLoopIndicesIntoImplementation(const Containers::StridedArrayView1D<const T>& indices, const Containers::StridedArrayView1D<UnsignedInt>& output) {
CORRADE_ASSERT(indices.size() == 0 || indices.size() >= 2,
"MeshTools::generateLineLoopIndicesInto(): expected either zero or at least two indices, got" << indices.size(), );
CORRADE_ASSERT(output.size() == 2*indices.size(),
"MeshTools::generateLineLoopIndicesInto(): bad output size, expected" << 2*indices.size() << "but got" << output.size(), );
/* Same as generateLineLoopIndicesInto() above, just with the index array
indirection on top */
for(std::size_t i = 0, iMax = Math::max(indices.size(), std::size_t{1}) - 1; i != iMax; ++i) {
output[i*2 + 0] = indices[i];
output[i*2 + 1] = indices[i + 1];
}
if(indices.size() >= 2) {
output[2*indices.size() - 2] = indices[indices.size() - 1];
output[2*indices.size() - 1] = indices[0];
}
}
}
void generateLineLoopIndicesInto(const Containers::StridedArrayView1D<const UnsignedInt>& indices, const Containers::StridedArrayView1D<UnsignedInt>& output) {
generateLineLoopIndicesIntoImplementation(indices, output);
}
void generateLineLoopIndicesInto(const Containers::StridedArrayView1D<const UnsignedShort>& indices, const Containers::StridedArrayView1D<UnsignedInt>& output) {
generateLineLoopIndicesIntoImplementation(indices, output);
}
void generateLineLoopIndicesInto(const Containers::StridedArrayView1D<const UnsignedByte>& indices, const Containers::StridedArrayView1D<UnsignedInt>& output) {
generateLineLoopIndicesIntoImplementation(indices, output);
}
Containers::Array<UnsignedInt> generateLineLoopIndices(const UnsignedInt vertexCount) {
Containers::Array<UnsignedInt> output{NoInit, 2*vertexCount};
generateLineLoopIndicesInto(vertexCount, output);
return output;
}
Containers::Array<UnsignedInt> generateLineLoopIndices(const Containers::StridedArrayView1D<const UnsignedInt>& indices) {
Containers::Array<UnsignedInt> output{NoInit, 2*indices.size()};
generateLineLoopIndicesInto(indices, output);
return output;
}
Containers::Array<UnsignedInt> generateLineLoopIndices(const Containers::StridedArrayView1D<const UnsignedShort>& indices) {
Containers::Array<UnsignedInt> output{NoInit, 2*indices.size()};
generateLineLoopIndicesInto(indices, output);
return output;
}
Containers::Array<UnsignedInt> generateLineLoopIndices(const Containers::StridedArrayView1D<const UnsignedByte>& indices) {
Containers::Array<UnsignedInt> output{NoInit, 2*indices.size()};
generateLineLoopIndicesInto(indices, output);
return output;
}
void generateTriangleStripIndicesInto(const UnsignedInt vertexCount, const Containers::StridedArrayView1D<UnsignedInt>& output) {
CORRADE_ASSERT(vertexCount == 0 || vertexCount >= 3,
"MeshTools::generateTriangleStripIndicesInto(): expected either zero or at least three vertices, got" << vertexCount, );
@ -166,12 +268,63 @@ void generateTriangleStripIndicesInto(const UnsignedInt vertexCount, const Conta
}
}
namespace {
template<class T> void generateTriangleStripIndicesIntoImplementation(const Containers::StridedArrayView1D<const T>& indices, const Containers::StridedArrayView1D<UnsignedInt>& output) {
CORRADE_ASSERT(indices.size() == 0 || indices.size() >= 3,
"MeshTools::generateTriangleStripIndicesInto(): expected either zero or at least three indices, got" << indices.size(), );
const UnsignedInt iMax = Math::max(indices.size(), std::size_t{2}) - 2;
CORRADE_ASSERT(output.size() == 3*iMax,
"MeshTools::generateTriangleStripIndicesInto(): bad output size, expected" << 3*iMax << "but got" << output.size(), );
/* Same as generateTriangleStripIndicesInto() above, just with the index
array indirection on top */
for(std::size_t i = 0; i != iMax; ++i) {
output[i*3 + 0] = indices[i % 2 ? i + 1 : i];
output[i*3 + 1] = indices[i % 2 ? i : i + 1];
output[i*3 + 2] = indices[i + 2];
}
}
}
void generateTriangleStripIndicesInto(const Containers::StridedArrayView1D<const UnsignedInt>& indices, const Containers::StridedArrayView1D<UnsignedInt>& output) {
generateTriangleStripIndicesIntoImplementation(indices, output);
}
void generateTriangleStripIndicesInto(const Containers::StridedArrayView1D<const UnsignedShort>& indices, const Containers::StridedArrayView1D<UnsignedInt>& output) {
generateTriangleStripIndicesIntoImplementation(indices, output);
}
void generateTriangleStripIndicesInto(const Containers::StridedArrayView1D<const UnsignedByte>& indices, const Containers::StridedArrayView1D<UnsignedInt>& output) {
generateTriangleStripIndicesIntoImplementation(indices, output);
}
Containers::Array<UnsignedInt> generateTriangleStripIndices(const UnsignedInt vertexCount) {
Containers::Array<UnsignedInt> output{NoInit, 3*(Math::max(vertexCount, 2u) - 2u)};
generateTriangleStripIndicesInto(vertexCount, output);
return output;
}
Containers::Array<UnsignedInt> generateTriangleStripIndices(const Containers::StridedArrayView1D<const UnsignedInt>& indices) {
Containers::Array<UnsignedInt> output{NoInit, 3*(Math::max(indices.size(), std::size_t{2}) - 2)};
generateTriangleStripIndicesInto(indices, output);
return output;
}
Containers::Array<UnsignedInt> generateTriangleStripIndices(const Containers::StridedArrayView1D<const UnsignedShort>& indices) {
Containers::Array<UnsignedInt> output{NoInit, 3*(Math::max(indices.size(), std::size_t{2}) - 2)};
generateTriangleStripIndicesInto(indices, output);
return output;
}
Containers::Array<UnsignedInt> generateTriangleStripIndices(const Containers::StridedArrayView1D<const UnsignedByte>& indices) {
Containers::Array<UnsignedInt> output{NoInit, 3*(Math::max(indices.size(), std::size_t{2}) - 2)};
generateTriangleStripIndicesInto(indices, output);
return output;
}
void generateTriangleFanIndicesInto(const UnsignedInt vertexCount, const Containers::StridedArrayView1D<UnsignedInt>& output) {
CORRADE_ASSERT(vertexCount == 0 || vertexCount >= 3,
"MeshTools::generateTriangleFanIndicesInto(): expected either zero or at least three vertices, got" << vertexCount, );
@ -198,12 +351,63 @@ void generateTriangleFanIndicesInto(const UnsignedInt vertexCount, const Contain
}
}
namespace {
template<class T> void generateTriangleFanIndicesIntoImplementation(const Containers::StridedArrayView1D<const T>& indices, const Containers::StridedArrayView1D<UnsignedInt>& output) {
CORRADE_ASSERT(indices.size() == 0 || indices.size() >= 3,
"MeshTools::generateTriangleFanIndicesInto(): expected either zero or at least three indices, got" << indices.size(), );
const UnsignedInt iMax = Math::max(indices.size(), std::size_t{2}) - 2;
CORRADE_ASSERT(output.size() == 3*iMax,
"MeshTools::generateTriangleFanIndicesInto(): bad output size, expected" << 3*iMax << "but got" << output.size(), );
/* Same as generateTriangleStripIndicesInto() above, just with the index
array indirection on top */
for(std::size_t i = 0; i != iMax; ++i) {
output[i*3 + 0] = indices[0];
output[i*3 + 1] = indices[i + 1];
output[i*3 + 2] = indices[i + 2];
}
}
}
void generateTriangleFanIndicesInto(const Containers::StridedArrayView1D<const UnsignedInt>& indices, const Containers::StridedArrayView1D<UnsignedInt>& output) {
generateTriangleFanIndicesIntoImplementation(indices, output);
}
void generateTriangleFanIndicesInto(const Containers::StridedArrayView1D<const UnsignedShort>& indices, const Containers::StridedArrayView1D<UnsignedInt>& output) {
generateTriangleFanIndicesIntoImplementation(indices, output);
}
void generateTriangleFanIndicesInto(const Containers::StridedArrayView1D<const UnsignedByte>& indices, const Containers::StridedArrayView1D<UnsignedInt>& output) {
generateTriangleFanIndicesIntoImplementation(indices, output);
}
Containers::Array<UnsignedInt> generateTriangleFanIndices(const UnsignedInt vertexCount) {
Containers::Array<UnsignedInt> output{NoInit, 3*(Math::max(vertexCount, 2u) - 2)};
generateTriangleFanIndicesInto(vertexCount, output);
return output;
}
Containers::Array<UnsignedInt> generateTriangleFanIndices(const Containers::StridedArrayView1D<const UnsignedInt>& indices) {
Containers::Array<UnsignedInt> output{NoInit, 3*(Math::max(indices.size(), std::size_t{2}) - 2)};
generateTriangleFanIndicesInto(indices, output);
return output;
}
Containers::Array<UnsignedInt> generateTriangleFanIndices(const Containers::StridedArrayView1D<const UnsignedShort>& indices) {
Containers::Array<UnsignedInt> output{NoInit, 3*(Math::max(indices.size(), std::size_t{2}) - 2)};
generateTriangleFanIndicesInto(indices, output);
return output;
}
Containers::Array<UnsignedInt> generateTriangleFanIndices(const Containers::StridedArrayView1D<const UnsignedByte>& indices) {
Containers::Array<UnsignedInt> output{NoInit, 3*(Math::max(indices.size(), std::size_t{2}) - 2)};
generateTriangleFanIndicesInto(indices, output);
return output;
}
namespace {
template<class T> inline void generateQuadIndicesIntoImplementation(const Containers::StridedArrayView1D<const Vector3>& positions, const Containers::StridedArrayView1D<const T>& quads, const Containers::StridedArrayView1D<T>& output) {

200
src/Magnum/MeshTools/GenerateIndices.h

@ -55,13 +55,36 @@ MAGNUM_MESHTOOLS_EXPORT UnsignedInt primitiveCount(MeshPrimitive primitive, Unsi
Can be used to convert a @ref MeshPrimitive::LineStrip mesh to
@ref MeshPrimitive::Lines. The @p vertexCount is expected to be either
@cpp 0 @ce or at least @cpp 2 @ce. Primitive restart is not supported.
@cpp 0 @ce or at least @cpp 2 @ce. Primitive restart is not supported. If the
mesh is already indexed, use @ref generateLineStripIndices(const Containers::StridedArrayView1D<const UnsignedInt>&)
and overloads instead.
@see @ref generateLineStripIndicesInto(), @ref generateLineLoopIndices(),
@ref generateTriangleStripIndices(), @ref generateTriangleFanIndices(),
@ref generateIndices()
*/
MAGNUM_MESHTOOLS_EXPORT Containers::Array<UnsignedInt> generateLineStripIndices(UnsignedInt vertexCount);
/**
@brief Create index buffer for an indexed line strip primitive
@m_since_latest
Like @ref generateLineStripIndices(UnsignedInt), but merges @p indices into the
generated line strip index buffer.
*/
MAGNUM_MESHTOOLS_EXPORT Containers::Array<UnsignedInt> generateLineStripIndices(const Containers::StridedArrayView1D<const UnsignedInt>& indices);
/**
* @overload
* @m_since_latest
*/
MAGNUM_MESHTOOLS_EXPORT Containers::Array<UnsignedInt> generateLineStripIndices(const Containers::StridedArrayView1D<const UnsignedShort>& indices);
/**
* @overload
* @m_since_latest
*/
MAGNUM_MESHTOOLS_EXPORT Containers::Array<UnsignedInt> generateLineStripIndices(const Containers::StridedArrayView1D<const UnsignedByte>& indices);
/**
@brief Create index buffer for a line strip primitive into an existing array
@m_since{2020,06}
@ -69,23 +92,69 @@ MAGNUM_MESHTOOLS_EXPORT Containers::Array<UnsignedInt> generateLineStripIndices(
A variant of @ref generateLineStripIndicesInto() that fills existing memory
instead of allocating a new array. The @p vertexCount is expected to be either
@cpp 0 @ce or at least @cpp 2 @ce, the @p output array is expected to have a
size of @cpp 2*(vertexCount - 1) @ce. Primitive restart is not supported.
size of @cpp 2*(vertexCount - 1) @ce. Primitive restart is not supported. If
the mesh is already indexed, use @ref generateLineStripIndicesInto(const Containers::StridedArrayView1D<const UnsignedInt>&, const Containers::StridedArrayView1D<UnsignedInt>&)
and overloads instead.
*/
MAGNUM_MESHTOOLS_EXPORT void generateLineStripIndicesInto(UnsignedInt vertexCount, const Containers::StridedArrayView1D<UnsignedInt>& output);
/**
@brief Create index buffer for an indexed line strip primitive into an existing array
@m_since_latest
Like @ref generateLineStripIndicesInto(UnsignedInt, const Containers::StridedArrayView1D<UnsignedInt>&),
but merges @p indices into the generated line strip index buffer.
*/
MAGNUM_MESHTOOLS_EXPORT void generateLineStripIndicesInto(const Containers::StridedArrayView1D<const UnsignedInt>& indices, const Containers::StridedArrayView1D<UnsignedInt>& output);
/**
* @overload
* @m_since_latest
*/
MAGNUM_MESHTOOLS_EXPORT void generateLineStripIndicesInto(const Containers::StridedArrayView1D<const UnsignedShort>& indices, const Containers::StridedArrayView1D<UnsignedInt>& output);
/**
* @overload
* @m_since_latest
*/
MAGNUM_MESHTOOLS_EXPORT void generateLineStripIndicesInto(const Containers::StridedArrayView1D<const UnsignedByte>& indices, const Containers::StridedArrayView1D<UnsignedInt>& output);
/**
@brief Create index buffer for a line loop primitive
@m_since{2020,06}
Can be used to convert a @ref MeshPrimitive::LineLoop mesh to
@ref MeshPrimitive::Lines. The @p vertexCount is expected to be either
@cpp 0 @ce or at least @cpp 2 @ce. Primitive restart is not supported.
@cpp 0 @ce or at least @cpp 2 @ce. Primitive restart is not supported. If the
mesh is already indexed, use @ref generateLineLoopIndices(const Containers::StridedArrayView1D<const UnsignedInt>&)
and overloads instead.
@see @ref generateLineLoopIndicesInto(), @ref generateLineStripIndices(),
@ref generateTriangleStripIndices(), @ref generateTriangleFanIndices(),
@ref generateIndices()
*/
MAGNUM_MESHTOOLS_EXPORT Containers::Array<UnsignedInt> generateLineLoopIndices(UnsignedInt vertexCount);
/**
@brief Create index buffer for an indexed line loop primitive
@m_since_latest
Like @ref generateLineLoopIndices(UnsignedInt), but merges @p indices into the
generated line loop index buffer.
*/
MAGNUM_MESHTOOLS_EXPORT Containers::Array<UnsignedInt> generateLineLoopIndices(const Containers::StridedArrayView1D<const UnsignedInt>& indices);
/**
* @overload
* @m_since_latest
*/
MAGNUM_MESHTOOLS_EXPORT Containers::Array<UnsignedInt> generateLineLoopIndices(const Containers::StridedArrayView1D<const UnsignedShort>& indices);
/**
* @overload
* @m_since_latest
*/
MAGNUM_MESHTOOLS_EXPORT Containers::Array<UnsignedInt> generateLineLoopIndices(const Containers::StridedArrayView1D<const UnsignedByte>& indices);
/**
@brief Create index buffer for a line loop primitive into an existing array
@m_since{2020,06}
@ -93,23 +162,69 @@ MAGNUM_MESHTOOLS_EXPORT Containers::Array<UnsignedInt> generateLineLoopIndices(U
A variant of @ref generateLineLoopIndicesInto() that fills existing memory
instead of allocating a new array. The @p vertexCount is expected to be either
@cpp 0 @ce or at least @cpp 2 @ce, the @p output array is expected to have a
size of @cpp 2*vertexCount @ce. Primitive restart is not supported.
size of @cpp 2*vertexCount @ce. Primitive restart is not supported.If
the mesh is already indexed, use @ref generateLineLoopIndicesInto(const Containers::StridedArrayView1D<const UnsignedInt>&, const Containers::StridedArrayView1D<UnsignedInt>&)
and overloads instead.
*/
MAGNUM_MESHTOOLS_EXPORT void generateLineLoopIndicesInto(UnsignedInt vertexCount, const Containers::StridedArrayView1D<UnsignedInt>& output);
/**
@brief Create index buffer for an indexed line loop primitive into an existing array
@m_since_latest
Like @ref generateLineLoopIndicesInto(UnsignedInt, const Containers::StridedArrayView1D<UnsignedInt>&),
but merges @p indices into the generated line loop index buffer.
*/
MAGNUM_MESHTOOLS_EXPORT void generateLineLoopIndicesInto(const Containers::StridedArrayView1D<const UnsignedInt>& indices, const Containers::StridedArrayView1D<UnsignedInt>& output);
/**
* @overload
* @m_since_latest
*/
MAGNUM_MESHTOOLS_EXPORT void generateLineLoopIndicesInto(const Containers::StridedArrayView1D<const UnsignedShort>& indices, const Containers::StridedArrayView1D<UnsignedInt>& output);
/**
* @overload
* @m_since_latest
*/
MAGNUM_MESHTOOLS_EXPORT void generateLineLoopIndicesInto(const Containers::StridedArrayView1D<const UnsignedByte>& indices, const Containers::StridedArrayView1D<UnsignedInt>& output);
/**
@brief Create index buffer for a triangle strip primitive
@m_since{2020,06}
Can be used to convert a @ref MeshPrimitive::TriangleStrip mesh to
@ref MeshPrimitive::Triangles. The @p vertexCount is expected to be either
@cpp 0 @ce or at least @cpp 3 @ce. Primitive restart is not supported.
@cpp 0 @ce or at least @cpp 3 @ce. Primitive restart is not supported. If the
mesh is already indexed, use @ref generateTriangleStripIndices(const Containers::StridedArrayView1D<const UnsignedInt>&)
and overloads instead.
@see @ref generateTriangleStripIndicesInto(), @ref generateLineStripIndices(),
@ref generateLineLoopIndices(), @ref generateTriangleFanIndices(),
@ref generateIndices()
*/
MAGNUM_MESHTOOLS_EXPORT Containers::Array<UnsignedInt> generateTriangleStripIndices(UnsignedInt vertexCount);
/**
@brief Create index buffer for an indexed triangle strip primitive
@m_since_latest
Like @ref generateTriangleStripIndices(UnsignedInt), but merges @p indices into
the generated triangle strip index buffer.
*/
MAGNUM_MESHTOOLS_EXPORT Containers::Array<UnsignedInt> generateTriangleStripIndices(const Containers::StridedArrayView1D<const UnsignedInt>& indices);
/**
* @overload
* @m_since_latest
*/
MAGNUM_MESHTOOLS_EXPORT Containers::Array<UnsignedInt> generateTriangleStripIndices(const Containers::StridedArrayView1D<const UnsignedShort>& indices);
/**
* @overload
* @m_since_latest
*/
MAGNUM_MESHTOOLS_EXPORT Containers::Array<UnsignedInt> generateTriangleStripIndices(const Containers::StridedArrayView1D<const UnsignedByte>& indices);
/**
@brief Create index buffer for a triangle strip primitive into an existing array
@m_since{2020,06}
@ -117,23 +232,69 @@ MAGNUM_MESHTOOLS_EXPORT Containers::Array<UnsignedInt> generateTriangleStripIndi
A variant of @ref generateTriangleStripIndicesInto() that fills existing memory
instead of allocating a new array. The @p vertexCount is expected to be either
@cpp 0 @ce or at least @cpp 3 @ce, the @p output array is expected to have a
size of @cpp 3*(vertexCount - 2) @ce. Primitive restart is not supported.
size of @cpp 3*(vertexCount - 2) @ce. Primitive restart is not supported. If
the mesh is already indexed, use @ref generateTriangleStripIndicesInto(const Containers::StridedArrayView1D<const UnsignedInt>&, const Containers::StridedArrayView1D<UnsignedInt>&)
and overloads instead.
*/
MAGNUM_MESHTOOLS_EXPORT void generateTriangleStripIndicesInto(UnsignedInt vertexCount, const Containers::StridedArrayView1D<UnsignedInt>& output);
/**
@brief Create index buffer for an indexed triangle strip primitive into an existing array
@m_since_latest
Like @ref generateTriangleStripIndicesInto(UnsignedInt, const Containers::StridedArrayView1D<UnsignedInt>&),
but merges @p indices into the generated triangle strip index buffer.
*/
MAGNUM_MESHTOOLS_EXPORT void generateTriangleStripIndicesInto(const Containers::StridedArrayView1D<const UnsignedInt>& indices, const Containers::StridedArrayView1D<UnsignedInt>& output);
/**
* @overload
* @m_since_latest
*/
MAGNUM_MESHTOOLS_EXPORT void generateTriangleStripIndicesInto(const Containers::StridedArrayView1D<const UnsignedShort>& indices, const Containers::StridedArrayView1D<UnsignedInt>& output);
/**
* @overload
* @m_since_latest
*/
MAGNUM_MESHTOOLS_EXPORT void generateTriangleStripIndicesInto(const Containers::StridedArrayView1D<const UnsignedByte>& indices, const Containers::StridedArrayView1D<UnsignedInt>& output);
/**
@brief Create index buffer for a triangle fan primitive
@m_since{2020,06}
Can be used to convert a @ref MeshPrimitive::TriangleFan mesh to
@ref MeshPrimitive::Triangles. The @p vertexCount is expected to be either
@cpp 0 @ce or at least @cpp 3 @ce. Primitive restart is not supported.
@cpp 0 @ce or at least @cpp 3 @ce. Primitive restart is not supported. If the
mesh is already indexed, use @ref generateTriangleFanIndices(const Containers::StridedArrayView1D<const UnsignedInt>&)
and overloads instead.
@see @ref generateTriangleFanIndicesInto(), @ref generateLineStripIndices(),
@ref generateLineLoopIndices(), @ref generateTriangleStripIndices(),
@ref generateIndices()
*/
MAGNUM_MESHTOOLS_EXPORT Containers::Array<UnsignedInt> generateTriangleFanIndices(UnsignedInt vertexCount);
/**
@brief Create index buffer for an indexed triangle fan primitive
@m_since_latest
Like @ref generateTriangleFanIndices(UnsignedInt), but merges @p indices into
the generated triangle fan index buffer.
*/
MAGNUM_MESHTOOLS_EXPORT Containers::Array<UnsignedInt> generateTriangleFanIndices(const Containers::StridedArrayView1D<const UnsignedInt>& indices);
/**
* @overload
* @m_since_latest
*/
MAGNUM_MESHTOOLS_EXPORT Containers::Array<UnsignedInt> generateTriangleFanIndices(const Containers::StridedArrayView1D<const UnsignedShort>& indices);
/**
* @overload
* @m_since_latest
*/
MAGNUM_MESHTOOLS_EXPORT Containers::Array<UnsignedInt> generateTriangleFanIndices(const Containers::StridedArrayView1D<const UnsignedByte>& indices);
/**
@brief Create index buffer for a triangle fan primitive into an existing array
@m_since{2020,06}
@ -141,10 +302,33 @@ MAGNUM_MESHTOOLS_EXPORT Containers::Array<UnsignedInt> generateTriangleFanIndice
A variant of @ref generateTriangleFanIndicesInto() that fills existing memory
instead of allocating a new array. The @p vertexCount is expected to be either
@cpp 0 @ce or at least @cpp 3 @ce, the @p output array is expected to have a
size of @cpp 3*(vertexCount - 2) @ce. Primitive restart is not supported.
size of @cpp 3*(vertexCount - 2) @ce. Primitive restart is not supported. If
the mesh is already indexed, use @ref generateTriangleFanIndicesInto(const Containers::StridedArrayView1D<const UnsignedInt>&, const Containers::StridedArrayView1D<UnsignedInt>&)
and overloads instead.
*/
MAGNUM_MESHTOOLS_EXPORT void generateTriangleFanIndicesInto(UnsignedInt vertexCount, const Containers::StridedArrayView1D<UnsignedInt>& output);
/**
@brief Create index buffer for an indexed triangle fan primitive into an existing array
@m_since_latest
Like @ref generateTriangleFanIndicesInto(UnsignedInt, const Containers::StridedArrayView1D<UnsignedInt>&),
but merges @p indices into the generated triangle fan index buffer.
*/
MAGNUM_MESHTOOLS_EXPORT void generateTriangleFanIndicesInto(const Containers::StridedArrayView1D<const UnsignedInt>& indices, const Containers::StridedArrayView1D<UnsignedInt>& output);
/**
* @overload
* @m_since_latest
*/
MAGNUM_MESHTOOLS_EXPORT void generateTriangleFanIndicesInto(const Containers::StridedArrayView1D<const UnsignedShort>& indices, const Containers::StridedArrayView1D<UnsignedInt>& output);
/**
* @overload
* @m_since_latest
*/
MAGNUM_MESHTOOLS_EXPORT void generateTriangleFanIndicesInto(const Containers::StridedArrayView1D<const UnsignedByte>& indices, const Containers::StridedArrayView1D<UnsignedInt>& output);
/**
@brief Create a triangle index buffer for quad primitives
@m_since_latest

227
src/Magnum/MeshTools/Test/GenerateIndicesTest.cpp

@ -46,18 +46,22 @@ struct GenerateIndicesTest: TestSuite::Tester {
void primitiveCountInvalidPrimitive();
void generateLineStripIndices();
template<class T> void generateLineStripIndicesIndexed();
void generateLineStripIndicesWrongVertexCount();
void generateLineStripIndicesIntoWrongSize();
void generateLineLoopIndices();
template<class T> void generateLineLoopIndicesIndexed();
void generateLineLoopIndicesWrongVertexCount();
void generateLineLoopIndicesIntoWrongSize();
void generateTriangleStripIndices();
template<class T> void generateTriangleStripIndicesIndexed();
void generateTriangleStripIndicesWrongVertexCount();
void generateTriangleStripIndicesIntoWrongSize();
void generateTriangleFanIndices();
template<class T> void generateTriangleFanIndicesIndexed();
void generateTriangleFanIndicesWrongVertexCount();
void generateTriangleFanIndicesIntoWrongSize();
@ -180,18 +184,30 @@ GenerateIndicesTest::GenerateIndicesTest() {
&GenerateIndicesTest::primitiveCountInvalidPrimitive,
&GenerateIndicesTest::generateLineStripIndices,
&GenerateIndicesTest::generateLineStripIndicesIndexed<UnsignedInt>,
&GenerateIndicesTest::generateLineStripIndicesIndexed<UnsignedShort>,
&GenerateIndicesTest::generateLineStripIndicesIndexed<UnsignedByte>,
&GenerateIndicesTest::generateLineStripIndicesWrongVertexCount,
&GenerateIndicesTest::generateLineStripIndicesIntoWrongSize,
&GenerateIndicesTest::generateLineLoopIndices,
&GenerateIndicesTest::generateLineLoopIndicesIndexed<UnsignedInt>,
&GenerateIndicesTest::generateLineLoopIndicesIndexed<UnsignedShort>,
&GenerateIndicesTest::generateLineLoopIndicesIndexed<UnsignedByte>,
&GenerateIndicesTest::generateLineLoopIndicesWrongVertexCount,
&GenerateIndicesTest::generateLineLoopIndicesIntoWrongSize,
&GenerateIndicesTest::generateTriangleStripIndices,
&GenerateIndicesTest::generateTriangleStripIndicesIndexed<UnsignedInt>,
&GenerateIndicesTest::generateTriangleStripIndicesIndexed<UnsignedShort>,
&GenerateIndicesTest::generateTriangleStripIndicesIndexed<UnsignedByte>,
&GenerateIndicesTest::generateTriangleStripIndicesWrongVertexCount,
&GenerateIndicesTest::generateTriangleStripIndicesIntoWrongSize,
&GenerateIndicesTest::generateTriangleFanIndices,
&GenerateIndicesTest::generateTriangleFanIndicesIndexed<UnsignedInt>,
&GenerateIndicesTest::generateTriangleFanIndicesIndexed<UnsignedShort>,
&GenerateIndicesTest::generateTriangleFanIndicesIndexed<UnsignedByte>,
&GenerateIndicesTest::generateTriangleFanIndicesWrongVertexCount,
&GenerateIndicesTest::generateTriangleFanIndicesIntoWrongSize});
@ -307,27 +323,76 @@ void GenerateIndicesTest::generateLineStripIndices() {
}), TestSuite::Compare::Container);
}
template<class T> void GenerateIndicesTest::generateLineStripIndicesIndexed() {
setTestCaseTemplateName(Math::TypeTraits<T>::name());
/* The second digit is 0, 1, 2, 3, 4, 5 for easier ordering. The output in
the second digit should then be the same as in
generateLineStripIndices() above. */
T indexData[]{60, 21, 72, 93, 44, 85};
auto indices = Containers::arrayView(indexData);
/* Empty input */
CORRADE_COMPARE_AS(MeshTools::generateLineStripIndices(indices.prefix(std::size_t{})),
Containers::ArrayView<const UnsignedInt>{},
TestSuite::Compare::Container);
/* Minimal non-empty input */
CORRADE_COMPARE_AS(MeshTools::generateLineStripIndices(indices.prefix(2)),
Containers::arrayView<UnsignedInt>({
60, 21
}), TestSuite::Compare::Container);
/* Odd */
CORRADE_COMPARE_AS(MeshTools::generateLineStripIndices(indices.prefix(5)),
Containers::arrayView<UnsignedInt>({
60, 21,
21, 72,
72, 93,
93, 44
}), TestSuite::Compare::Container);
/* Even */
CORRADE_COMPARE_AS(MeshTools::generateLineStripIndices(indices),
Containers::arrayView<UnsignedInt>({
60, 21,
21, 72,
72, 93,
93, 44,
44, 85
}), TestSuite::Compare::Container);
}
void GenerateIndicesTest::generateLineStripIndicesWrongVertexCount() {
CORRADE_SKIP_IF_NO_ASSERT();
UnsignedShort indices[1];
std::ostringstream out;
Error redirectError{&out};
MeshTools::generateLineStripIndicesInto(1, nullptr);
MeshTools::generateLineStripIndicesInto(indices, nullptr);
CORRADE_COMPARE(out.str(),
"MeshTools::generateLineStripIndicesInto(): expected either zero or at least two vertices, got 1\n");
"MeshTools::generateLineStripIndicesInto(): expected either zero or at least two vertices, got 1\n"
"MeshTools::generateLineStripIndicesInto(): expected either zero or at least two indices, got 1\n");
}
void GenerateIndicesTest::generateLineStripIndicesIntoWrongSize() {
CORRADE_SKIP_IF_NO_ASSERT();
UnsignedByte indices[5];
UnsignedInt output[7];
std::ostringstream out;
Error redirectError{&out};
MeshTools::generateLineStripIndicesInto(0, output);
MeshTools::generateLineStripIndicesInto(Containers::arrayView(indices).prefix(std::size_t{}), output);
MeshTools::generateLineStripIndicesInto(5, output);
MeshTools::generateLineStripIndicesInto(indices, output);
CORRADE_COMPARE(out.str(),
"MeshTools::generateLineStripIndicesInto(): bad output size, expected 0 but got 7\n"
"MeshTools::generateLineStripIndicesInto(): bad output size, expected 0 but got 7\n"
"MeshTools::generateLineStripIndicesInto(): bad output size, expected 8 but got 7\n"
"MeshTools::generateLineStripIndicesInto(): bad output size, expected 8 but got 7\n");
}
@ -366,27 +431,79 @@ void GenerateIndicesTest::generateLineLoopIndices() {
}), TestSuite::Compare::Container);
}
template<class T> void GenerateIndicesTest::generateLineLoopIndicesIndexed() {
setTestCaseTemplateName(Math::TypeTraits<T>::name());
/* The second digit is 0, 1, 2, 3, 4, 5 for easier ordering. The output in
the second digit should then be the same as in generateLineLoopIndices()
above. */
T indexData[]{60, 21, 72, 93, 44, 85};
auto indices = Containers::arrayView(indexData);
/* Empty input */
CORRADE_COMPARE_AS(MeshTools::generateLineLoopIndices(indices.prefix(std::size_t{})),
Containers::ArrayView<const UnsignedInt>{},
TestSuite::Compare::Container);
/* Minimal non-empty input */
CORRADE_COMPARE_AS(MeshTools::generateLineLoopIndices(indices.prefix(2)),
Containers::arrayView<UnsignedInt>({
60, 21,
21, 60
}), TestSuite::Compare::Container);
/* Odd */
CORRADE_COMPARE_AS(MeshTools::generateLineLoopIndices(indices.prefix(5)),
Containers::arrayView<UnsignedInt>({
60, 21,
21, 72,
72, 93,
93, 44,
44, 60
}), TestSuite::Compare::Container);
/* Even */
CORRADE_COMPARE_AS(MeshTools::generateLineLoopIndices(indices),
Containers::arrayView<UnsignedInt>({
60, 21,
21, 72,
72, 93,
93, 44,
44, 85,
85, 60
}), TestSuite::Compare::Container);
}
void GenerateIndicesTest::generateLineLoopIndicesWrongVertexCount() {
CORRADE_SKIP_IF_NO_ASSERT();
UnsignedInt indices[1];
std::ostringstream out;
Error redirectError{&out};
MeshTools::generateLineLoopIndicesInto(1, nullptr);
MeshTools::generateLineLoopIndicesInto(indices, nullptr);
CORRADE_COMPARE(out.str(),
"MeshTools::generateLineLoopIndicesInto(): expected either zero or at least two vertices, got 1\n");
"MeshTools::generateLineLoopIndicesInto(): expected either zero or at least two vertices, got 1\n"
"MeshTools::generateLineLoopIndicesInto(): expected either zero or at least two indices, got 1\n");
}
void GenerateIndicesTest::generateLineLoopIndicesIntoWrongSize() {
CORRADE_SKIP_IF_NO_ASSERT();
UnsignedShort indices[5];
UnsignedInt output[9];
std::ostringstream out;
Error redirectError{&out};
MeshTools::generateLineLoopIndicesInto(0, output);
MeshTools::generateLineLoopIndicesInto(Containers::arrayView(indices).prefix(std::size_t{}), output);
MeshTools::generateLineLoopIndicesInto(5, output);
MeshTools::generateLineLoopIndicesInto(indices, output);
CORRADE_COMPARE(out.str(),
"MeshTools::generateLineLoopIndicesInto(): bad output size, expected 0 but got 9\n"
"MeshTools::generateLineLoopIndicesInto(): bad output size, expected 0 but got 9\n"
"MeshTools::generateLineLoopIndicesInto(): bad output size, expected 10 but got 9\n"
"MeshTools::generateLineLoopIndicesInto(): bad output size, expected 10 but got 9\n");
}
@ -424,27 +541,78 @@ void GenerateIndicesTest::generateTriangleStripIndices() {
}), TestSuite::Compare::Container);
}
template<class T> void GenerateIndicesTest::generateTriangleStripIndicesIndexed() {
setTestCaseTemplateName(Math::TypeTraits<T>::name());
/* The second digit is 0, 1, 2, 3, 4, 5, 6, 7 for easier ordering. The
output in the second digit should then be the same as in
generateTriangleStripIndices() above. */
T indexData[]{60, 21, 72, 93, 44, 85, 36, 17};
auto indices = Containers::arrayView(indexData);
/* Empty input */
CORRADE_COMPARE_AS(MeshTools::generateTriangleStripIndices(indices.prefix(std::size_t{})),
Containers::ArrayView<const UnsignedInt>{},
TestSuite::Compare::Container);
/* Minimal non-empty input */
CORRADE_COMPARE_AS(MeshTools::generateTriangleStripIndices(indices.prefix(3)),
Containers::arrayView<UnsignedInt>({
60, 21, 72
}), TestSuite::Compare::Container);
/* Odd */
CORRADE_COMPARE_AS(MeshTools::generateTriangleStripIndices(indices.prefix(7)),
Containers::arrayView<UnsignedInt>({
60, 21, 72,
72, 21, 93, /* Reversed */
72, 93, 44,
44, 93, 85, /* Reversed */
44, 85, 36
}), TestSuite::Compare::Container);
/* Even */
CORRADE_COMPARE_AS(MeshTools::generateTriangleStripIndices(indices),
Containers::arrayView<UnsignedInt>({
60, 21, 72,
72, 21, 93, /* Reversed */
72, 93, 44,
44, 93, 85, /* Reversed */
44, 85, 36,
36, 85, 17 /* Reversed */
}), TestSuite::Compare::Container);
}
void GenerateIndicesTest::generateTriangleStripIndicesWrongVertexCount() {
CORRADE_SKIP_IF_NO_ASSERT();
UnsignedByte indices[2];
std::ostringstream out;
Error redirectError{&out};
MeshTools::generateTriangleStripIndicesInto(2, nullptr);
MeshTools::generateTriangleStripIndicesInto(indices, nullptr);
CORRADE_COMPARE(out.str(),
"MeshTools::generateTriangleStripIndicesInto(): expected either zero or at least three vertices, got 2\n");
"MeshTools::generateTriangleStripIndicesInto(): expected either zero or at least three vertices, got 2\n"
"MeshTools::generateTriangleStripIndicesInto(): expected either zero or at least three indices, got 2\n");
}
void GenerateIndicesTest::generateTriangleStripIndicesIntoWrongSize() {
CORRADE_SKIP_IF_NO_ASSERT();
UnsignedInt indices[5];
UnsignedInt output[8];
std::ostringstream out;
Error redirectError{&out};
MeshTools::generateTriangleStripIndicesInto(0, output);
MeshTools::generateTriangleStripIndicesInto(Containers::arrayView(indices).prefix(std::size_t{}), output);
MeshTools::generateTriangleStripIndicesInto(5, output);
MeshTools::generateTriangleStripIndicesInto(indices, output);
CORRADE_COMPARE(out.str(),
"MeshTools::generateTriangleStripIndicesInto(): bad output size, expected 0 but got 8\n"
"MeshTools::generateTriangleStripIndicesInto(): bad output size, expected 0 but got 8\n"
"MeshTools::generateTriangleStripIndicesInto(): bad output size, expected 9 but got 8\n"
"MeshTools::generateTriangleStripIndicesInto(): bad output size, expected 9 but got 8\n");
}
@ -482,27 +650,78 @@ void GenerateIndicesTest::generateTriangleFanIndices() {
}), TestSuite::Compare::Container);
}
template<class T> void GenerateIndicesTest::generateTriangleFanIndicesIndexed() {
setTestCaseTemplateName(Math::TypeTraits<T>::name());
/* The second digit is 0, 1, 2, 3, 4, 5, 6, 7 for easier ordering. The
output in the second digit should then be the same as in
generateTriangleFanIndices() above. */
T indexData[]{60, 21, 72, 93, 44, 85, 36, 17};
auto indices = Containers::arrayView(indexData);
/* Empty input */
CORRADE_COMPARE_AS(MeshTools::generateTriangleFanIndices(indices.prefix(std::size_t{})),
Containers::ArrayView<const UnsignedInt>{},
TestSuite::Compare::Container);
/* Minimal non-empty input */
CORRADE_COMPARE_AS(MeshTools::generateTriangleFanIndices(indices.prefix(3)),
Containers::arrayView<UnsignedInt>({
60, 21, 72
}), TestSuite::Compare::Container);
/* Odd */
CORRADE_COMPARE_AS(MeshTools::generateTriangleFanIndices(indices.prefix(7)),
Containers::arrayView<UnsignedInt>({
60, 21, 72,
60, 72, 93,
60, 93, 44,
60, 44, 85,
60, 85, 36
}), TestSuite::Compare::Container);
/* Even */
CORRADE_COMPARE_AS(MeshTools::generateTriangleFanIndices(indices),
Containers::arrayView<UnsignedInt>({
60, 21, 72,
60, 72, 93,
60, 93, 44,
60, 44, 85,
60, 85, 36,
60, 36, 17
}), TestSuite::Compare::Container);
}
void GenerateIndicesTest::generateTriangleFanIndicesWrongVertexCount() {
CORRADE_SKIP_IF_NO_ASSERT();
UnsignedInt indices[2];
std::ostringstream out;
Error redirectError{&out};
MeshTools::generateTriangleFanIndicesInto(2, nullptr);
MeshTools::generateTriangleFanIndicesInto(indices, nullptr);
CORRADE_COMPARE(out.str(),
"MeshTools::generateTriangleFanIndicesInto(): expected either zero or at least three vertices, got 2\n");
"MeshTools::generateTriangleFanIndicesInto(): expected either zero or at least three vertices, got 2\n"
"MeshTools::generateTriangleFanIndicesInto(): expected either zero or at least three indices, got 2\n");
}
void GenerateIndicesTest::generateTriangleFanIndicesIntoWrongSize() {
CORRADE_SKIP_IF_NO_ASSERT();
UnsignedInt indices[5];
UnsignedInt output[8];
std::ostringstream out;
Error redirectError{&out};
MeshTools::generateTriangleFanIndicesInto(0, output);
MeshTools::generateTriangleFanIndicesInto(Containers::arrayView(indices).prefix(std::size_t{}), output);
MeshTools::generateTriangleFanIndicesInto(5, output);
MeshTools::generateTriangleFanIndicesInto(indices, output);
CORRADE_COMPARE(out.str(),
"MeshTools::generateTriangleFanIndicesInto(): bad output size, expected 0 but got 8\n"
"MeshTools::generateTriangleFanIndicesInto(): bad output size, expected 0 but got 8\n"
"MeshTools::generateTriangleFanIndicesInto(): bad output size, expected 9 but got 8\n"
"MeshTools::generateTriangleFanIndicesInto(): bad output size, expected 9 but got 8\n");
}

Loading…
Cancel
Save