Browse Source

MeshTools: assert on impl-specific vert format in concatenate*().

pull/549/head
Vladimír Vondruš 4 years ago
parent
commit
40acab4e37
  1. 8
      src/Magnum/MeshTools/Concatenate.cpp
  2. 28
      src/Magnum/MeshTools/Concatenate.h
  3. 32
      src/Magnum/MeshTools/Test/ConcatenateTest.cpp

8
src/Magnum/MeshTools/Concatenate.cpp

@ -189,6 +189,14 @@ Trade::MeshData concatenate(const Containers::ArrayView<const Containers::Refere
CORRADE_ASSERT(!meshes.empty(), CORRADE_ASSERT(!meshes.empty(),
"MeshTools::concatenate(): expected at least one mesh", "MeshTools::concatenate(): expected at least one mesh",
(Trade::MeshData{MeshPrimitive::Points, 0})); (Trade::MeshData{MeshPrimitive::Points, 0}));
#ifndef CORRADE_NO_ASSERT
for(std::size_t i = 0; i != meshes.front()->attributeCount(); ++i) {
const VertexFormat format = meshes.front()->attributeFormat(i);
CORRADE_ASSERT(!isVertexFormatImplementationSpecific(format),
"MeshTools::concatenate(): attribute" << i << "of the first mesh has an implementation-specific format" << reinterpret_cast<void*>(vertexFormatUnwrap(format)),
(Trade::MeshData{MeshPrimitive::Points, 0}));
}
#endif
/* Calculate final attribute stride and offsets. Make a non-owning copy of /* Calculate final attribute stride and offsets. Make a non-owning copy of
the attribute data to avoid interleavedLayout() stealing the original the attribute data to avoid interleavedLayout() stealing the original

28
src/Magnum/MeshTools/Concatenate.h

@ -57,20 +57,21 @@ concatenated --- use @ref generateIndices() to turn them into
@ref MeshPrimitive::Lines or @ref MeshPrimitive::Triangles first. The @p meshes @ref MeshPrimitive::Lines or @ref MeshPrimitive::Triangles first. The @p meshes
array is expected to have at least one item. array is expected to have at least one item.
All attributes from the first mesh are taken; for each following mesh All attributes from the first mesh are taken, expected to not have an
attributes present in the first are copied, superfluous attributes ignored and implementation-specific format. For each following mesh attributes present in
missing attributes zeroed out. Matching attributes are expected to have the the first are copied, superfluous attributes ignored and missing attributes
same type, all meshes are expected to have the same primitive. The vertex data zeroed out. Matching attributes are expected to have the same type, all meshes
are concatenated in the same order as passed, with no duplicate removal. are expected to have the same primitive. The vertex data are concatenated in
Returned instance vertex and index data flags always have both the same order as passed, with no duplicate removal. Returned instance vertex
@ref Trade::DataFlag::Owned and @ref Trade::DataFlag::Mutable to guarante and index data flags always have both @ref Trade::DataFlag::Owned and
mutable access to particular parts of the concatenated mesh --- for example for @ref Trade::DataFlag::Mutable to guarante mutable access to particular parts of
applying transformations. the concatenated mesh --- for example for applying transformations.
If an index buffer is needed, @ref MeshIndexType::UnsignedInt is always used. If an index buffer is needed, @ref MeshIndexType::UnsignedInt is always used.
Call @ref compressIndices(const Trade::MeshData&, MeshIndexType) on the result Call @ref compressIndices(const Trade::MeshData&, MeshIndexType) on the result
to compress it to a smaller type, if desired. to compress it to a smaller type, if desired.
@see @ref concatenateInto(), @ref SceneTools::flattenMeshHierarchy2D(), @see @ref concatenateInto(), @ref isVertexFormatImplementationSpecific(),
@ref SceneTools::flattenMeshHierarchy2D(),
@ref SceneTools::flattenMeshHierarchy3D() @ref SceneTools::flattenMeshHierarchy3D()
*/ */
MAGNUM_MESHTOOLS_EXPORT Trade::MeshData concatenate(Containers::ArrayView<const Containers::Reference<const Trade::MeshData>> meshes); MAGNUM_MESHTOOLS_EXPORT Trade::MeshData concatenate(Containers::ArrayView<const Containers::Reference<const Trade::MeshData>> meshes);
@ -99,6 +100,13 @@ layout from @p destination is used, all vertex/index data are taken from
template<template<class> class Allocator = Containers::ArrayAllocator> void concatenateInto(Trade::MeshData& destination, const Containers::ArrayView<const Containers::Reference<const Trade::MeshData>> meshes) { template<template<class> class Allocator = Containers::ArrayAllocator> void concatenateInto(Trade::MeshData& destination, const Containers::ArrayView<const Containers::Reference<const Trade::MeshData>> meshes) {
CORRADE_ASSERT(!meshes.empty(), CORRADE_ASSERT(!meshes.empty(),
"MeshTools::concatenateInto(): no meshes passed", ); "MeshTools::concatenateInto(): no meshes passed", );
#ifndef CORRADE_NO_ASSERT
for(std::size_t i = 0; i != destination.attributeCount(); ++i) {
const VertexFormat format = destination.attributeFormat(i);
CORRADE_ASSERT(!isVertexFormatImplementationSpecific(format),
"MeshTools::concatenateInto(): attribute" << i << "of the destination mesh has an implementation-specific format" << reinterpret_cast<void*>(vertexFormatUnwrap(format)), );
}
#endif
std::pair<UnsignedInt, UnsignedInt> indexVertexCount = Implementation::concatenateIndexVertexCount(meshes); std::pair<UnsignedInt, UnsignedInt> indexVertexCount = Implementation::concatenateIndexVertexCount(meshes);

32
src/Magnum/MeshTools/Test/ConcatenateTest.cpp

@ -50,6 +50,7 @@ struct ConcatenateTest: TestSuite::Tester {
void concatenateInconsistentPrimitive(); void concatenateInconsistentPrimitive();
void concatenateInconsistentAttributeFormat(); void concatenateInconsistentAttributeFormat();
void concatenateInconsistentAttributeArraySize(); void concatenateInconsistentAttributeArraySize();
void concatenateImplementationSpecificVertexFormat();
void concatenateIntoNoMeshes(); void concatenateIntoNoMeshes();
}; };
@ -68,6 +69,7 @@ ConcatenateTest::ConcatenateTest() {
&ConcatenateTest::concatenateInconsistentPrimitive, &ConcatenateTest::concatenateInconsistentPrimitive,
&ConcatenateTest::concatenateInconsistentAttributeFormat, &ConcatenateTest::concatenateInconsistentAttributeFormat,
&ConcatenateTest::concatenateInconsistentAttributeArraySize, &ConcatenateTest::concatenateInconsistentAttributeArraySize,
&ConcatenateTest::concatenateImplementationSpecificVertexFormat,
&ConcatenateTest::concatenateIntoNoMeshes}); &ConcatenateTest::concatenateIntoNoMeshes});
} }
@ -637,6 +639,36 @@ void ConcatenateTest::concatenateInconsistentAttributeArraySize() {
"MeshTools::concatenateInto(): expected array size 5 for attribute 2 (Trade::MeshAttribute::Custom(42)) but got 4 in mesh 3 attribute 1\n"); "MeshTools::concatenateInto(): expected array size 5 for attribute 2 (Trade::MeshAttribute::Custom(42)) but got 4 in mesh 3 attribute 1\n");
} }
void ConcatenateTest::concatenateImplementationSpecificVertexFormat() {
#ifdef CORRADE_NO_ASSERT
CORRADE_SKIP("CORRADE_NO_ASSERT defined, can't test assertions");
#endif
/* Things are a bit duplicated to test correct numbering */
Trade::MeshData a{MeshPrimitive::Lines, nullptr, {
Trade::MeshAttributeData{Trade::MeshAttribute::Position,
VertexFormat::Vector3, nullptr},
Trade::MeshAttributeData{Trade::MeshAttribute::Normal,
VertexFormat::Vector3, nullptr},
Trade::MeshAttributeData{Trade::MeshAttribute::Color,
vertexFormatWrap(0xcaca), nullptr}
}};
Trade::MeshData b{MeshPrimitive::Lines, nullptr, {
Trade::MeshAttributeData{Trade::MeshAttribute::Position,
VertexFormat::Vector3, nullptr},
Trade::MeshAttributeData{Trade::MeshAttribute::Normal,
VertexFormat::Vector3, nullptr}
}};
std::ostringstream out;
Error redirectError{&out};
MeshTools::concatenate({a, b});
MeshTools::concatenateInto(a, {b});
CORRADE_COMPARE(out.str(),
"MeshTools::concatenate(): attribute 2 of the first mesh has an implementation-specific format 0xcaca\n"
"MeshTools::concatenateInto(): attribute 2 of the destination mesh has an implementation-specific format 0xcaca\n");
}
void ConcatenateTest::concatenateIntoNoMeshes() { void ConcatenateTest::concatenateIntoNoMeshes() {
#ifdef CORRADE_NO_ASSERT #ifdef CORRADE_NO_ASSERT
CORRADE_SKIP("CORRADE_NO_ASSERT defined, can't test assertions"); CORRADE_SKIP("CORRADE_NO_ASSERT defined, can't test assertions");

Loading…
Cancel
Save