mirror of https://github.com/mosra/magnum.git
Browse Source
Replaces the STL-heavy combineIndexedArrays(), but in a less extremely horrendous way.pull/371/head
6 changed files with 422 additions and 0 deletions
@ -0,0 +1,143 @@ |
|||||||
|
/*
|
||||||
|
This file is part of Magnum. |
||||||
|
|
||||||
|
Copyright © 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018, 2019 |
||||||
|
Vladimír Vondruš <mosra@centrum.cz> |
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a |
||||||
|
copy of this software and associated documentation files (the "Software"), |
||||||
|
to deal in the Software without restriction, including without limitation |
||||||
|
the rights to use, copy, modify, merge, publish, distribute, sublicense, |
||||||
|
and/or sell copies of the Software, and to permit persons to whom the |
||||||
|
Software is furnished to do so, subject to the following conditions: |
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included |
||||||
|
in all copies or substantial portions of the Software. |
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
||||||
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL |
||||||
|
THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER |
||||||
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING |
||||||
|
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER |
||||||
|
DEALINGS IN THE SOFTWARE. |
||||||
|
*/ |
||||||
|
|
||||||
|
#include "Combine.h" |
||||||
|
|
||||||
|
#include <numeric> |
||||||
|
#include <Corrade/Containers/ArrayView.h> |
||||||
|
#include <Corrade/Containers/Reference.h> |
||||||
|
#include <Corrade/Utility/Algorithms.h> |
||||||
|
|
||||||
|
#include "Magnum/MeshTools/Duplicate.h" |
||||||
|
#include "Magnum/MeshTools/RemoveDuplicates.h" |
||||||
|
#include "Magnum/Trade/MeshData.h" |
||||||
|
|
||||||
|
namespace Magnum { namespace MeshTools { |
||||||
|
|
||||||
|
Trade::MeshData combineIndexedAttributes(const Containers::ArrayView<const Containers::Reference<const Trade::MeshData>> data) { |
||||||
|
CORRADE_ASSERT(!data.empty(), "MeshTools::combineIndexedAttributes(): no meshes passed", (Trade::MeshData{MeshPrimitive{}, 0})); |
||||||
|
|
||||||
|
/* Decide on the output primitive and index count, calculated total
|
||||||
|
combined index type size and also the count and stride of all |
||||||
|
attributes */ |
||||||
|
MeshPrimitive primitive; |
||||||
|
UnsignedInt indexCount; |
||||||
|
std::size_t indexStride = 0; |
||||||
|
std::size_t attributeCount = 0; |
||||||
|
UnsignedInt vertexStride = 0; |
||||||
|
for(std::size_t i = 0; i != data.size(); ++i) { |
||||||
|
CORRADE_ASSERT(data[i]->isIndexed(), |
||||||
|
"MeshTools::combineIndexedAttributes(): data" << i << "is not indexed", |
||||||
|
(Trade::MeshData{MeshPrimitive{}, 0})); |
||||||
|
if(i == 0) { |
||||||
|
primitive = data[i]->primitive(); |
||||||
|
indexCount = data[i]->indexCount(); |
||||||
|
} else { |
||||||
|
CORRADE_ASSERT(data[i]->primitive() == primitive, |
||||||
|
"MeshTools::combineIndexedAttributes(): data" << i << "is" << data[i]->primitive() << "but expected" << primitive, (Trade::MeshData{MeshPrimitive{}, 0})); |
||||||
|
CORRADE_ASSERT(data[i]->indexCount() == indexCount, |
||||||
|
"MeshTools::combineIndexedAttributes(): data" << i << "has" << data[i]->indexCount() << "indices but expected" << indexCount, (Trade::MeshData{MeshPrimitive{}, 0})); |
||||||
|
} |
||||||
|
indexStride += meshIndexTypeSize(data[i]->indexType()); |
||||||
|
attributeCount += data[i]->attributeCount(); |
||||||
|
for(std::size_t j = 0; j != data[i]->attributeCount(); ++j) |
||||||
|
vertexStride += vertexFormatSize(data[i]->attributeFormat(j)); |
||||||
|
} |
||||||
|
|
||||||
|
/* Create a combined index array */ |
||||||
|
Containers::Array<char> combinedIndices{Containers::NoInit, |
||||||
|
indexCount*indexStride}; |
||||||
|
{ |
||||||
|
std::size_t indexOffset = 0; |
||||||
|
for(const Trade::MeshData& mesh: data) { |
||||||
|
const UnsignedInt indexSize = meshIndexTypeSize(mesh.indexType()); |
||||||
|
Containers::StridedArrayView2D<char> dst{combinedIndices, |
||||||
|
combinedIndices.data() + indexOffset, |
||||||
|
{indexCount, indexSize}, |
||||||
|
{std::ptrdiff_t(indexStride), 1}}; |
||||||
|
Utility::copy(mesh.indices(), dst); |
||||||
|
indexOffset += indexSize; |
||||||
|
} |
||||||
|
|
||||||
|
/* Check we pre-calculated correctly */ |
||||||
|
CORRADE_INTERNAL_ASSERT(indexOffset == indexStride); |
||||||
|
} |
||||||
|
|
||||||
|
/** @todo handle alignment in the above somehow (duplicate() will fail when
|
||||||
|
reading 32-bit values from odd addresses on some platforms) */ |
||||||
|
|
||||||
|
/* Make the combined index array unique */ |
||||||
|
Containers::Array<char> indexData{indexCount*sizeof(UnsignedInt)}; |
||||||
|
const auto indexDataI = Containers::arrayCast<UnsignedInt>(indexData); |
||||||
|
const std::size_t vertexCount = removeDuplicatesInPlaceInto( |
||||||
|
Containers::StridedArrayView2D<char>{combinedIndices, {indexCount, indexStride}}, |
||||||
|
indexDataI); |
||||||
|
|
||||||
|
/* Allocate resulting attribute and vertex data and duplicate the
|
||||||
|
attributes there according to the combined index buffer */ |
||||||
|
Containers::Array<char> vertexData{Containers::NoInit, |
||||||
|
vertexStride*vertexCount}; |
||||||
|
Containers::Array<Trade::MeshAttributeData> attributeData{attributeCount}; |
||||||
|
{ |
||||||
|
std::size_t indexOffset = 0; |
||||||
|
std::size_t attributeOffset = 0; |
||||||
|
std::size_t vertexOffset = 0; |
||||||
|
for(const Trade::MeshData& mesh: data) { |
||||||
|
const UnsignedInt indexSize = mesh.isIndexed() ? |
||||||
|
meshIndexTypeSize(mesh.indexType()) : 4; |
||||||
|
Containers::StridedArrayView2D<const char> indices{combinedIndices, |
||||||
|
combinedIndices.data() + indexOffset, |
||||||
|
{vertexCount, indexSize}, |
||||||
|
{std::ptrdiff_t(indexStride), 1}}; |
||||||
|
|
||||||
|
for(UnsignedInt i = 0; i != mesh.attributeCount(); ++i) { |
||||||
|
const UnsignedInt attributeSize = vertexFormatSize(mesh.attributeFormat(i)); |
||||||
|
Containers::StridedArrayView2D<char> dst{vertexData, |
||||||
|
vertexData.data() + vertexOffset, |
||||||
|
{vertexCount, attributeSize}, |
||||||
|
{std::ptrdiff_t(vertexStride), 1}}; |
||||||
|
duplicateInto(indices, mesh.attribute(i), dst); |
||||||
|
vertexOffset += attributeSize; |
||||||
|
attributeData[attributeOffset++] = Trade::MeshAttributeData{ |
||||||
|
mesh.attributeName(i), mesh.attributeFormat(i), dst}; |
||||||
|
} |
||||||
|
|
||||||
|
indexOffset += indexSize; |
||||||
|
} |
||||||
|
|
||||||
|
/* Check we pre-calculated correctly */ |
||||||
|
CORRADE_INTERNAL_ASSERT(attributeOffset == attributeCount && vertexOffset == vertexStride); |
||||||
|
} |
||||||
|
|
||||||
|
return Trade::MeshData{primitive, |
||||||
|
std::move(indexData), Trade::MeshIndexData{indexDataI}, |
||||||
|
std::move(vertexData), std::move(attributeData)}; |
||||||
|
} |
||||||
|
|
||||||
|
Trade::MeshData combineIndexedAttributes(std::initializer_list<Containers::Reference<const Trade::MeshData>> data) { |
||||||
|
return combineIndexedAttributes(Containers::arrayView(data)); |
||||||
|
} |
||||||
|
|
||||||
|
}} |
||||||
@ -0,0 +1,94 @@ |
|||||||
|
#ifndef Magnum_MeshTools_Combine_h |
||||||
|
#define Magnum_MeshTools_Combine_h |
||||||
|
/*
|
||||||
|
This file is part of Magnum. |
||||||
|
|
||||||
|
Copyright © 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018, 2019 |
||||||
|
Vladimír Vondruš <mosra@centrum.cz> |
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a |
||||||
|
copy of this software and associated documentation files (the "Software"), |
||||||
|
to deal in the Software without restriction, including without limitation |
||||||
|
the rights to use, copy, modify, merge, publish, distribute, sublicense, |
||||||
|
and/or sell copies of the Software, and to permit persons to whom the |
||||||
|
Software is furnished to do so, subject to the following conditions: |
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included |
||||||
|
in all copies or substantial portions of the Software. |
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
||||||
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL |
||||||
|
THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER |
||||||
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING |
||||||
|
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER |
||||||
|
DEALINGS IN THE SOFTWARE. |
||||||
|
*/ |
||||||
|
|
||||||
|
/** @file
|
||||||
|
* @brief Function @ref Magnum::MeshTools::combineIndexedAttributes() |
||||||
|
* @m_since_latest |
||||||
|
*/ |
||||||
|
|
||||||
|
#include <initializer_list> |
||||||
|
|
||||||
|
#include "Magnum/MeshTools/visibility.h" |
||||||
|
#include "Magnum/Trade/Trade.h" |
||||||
|
|
||||||
|
namespace Magnum { namespace MeshTools { |
||||||
|
|
||||||
|
/**
|
||||||
|
@brief Combine differently indexed attributes into a single mesh |
||||||
|
@m_since_latest |
||||||
|
|
||||||
|
Assuming each @p data contains only unique vertex data, creates an indexed mesh |
||||||
|
that contains all attributes from @p data combined, with duplicate vertices |
||||||
|
removed. For example, when you have a position and a normal array, each indexed |
||||||
|
with separate indices like this: |
||||||
|
|
||||||
|
@code{.cpp} |
||||||
|
{pA, pB, pC, pD, pE, pF} // positions
|
||||||
|
{nA, nB, nC, nD, nE, nF, nG} // normals
|
||||||
|
|
||||||
|
{0, 2, 5, 0, 0, 1, 3, 2, 2} // position indices
|
||||||
|
{1, 3, 4, 1, 4, 6, 1, 3, 1} // normal indices
|
||||||
|
@endcode |
||||||
|
|
||||||
|
Then the first triangle in the mesh is defined as |
||||||
|
@cb{.cpp} {pA, nB}, {pC, nD}, {pF, nE} @ce. When combined together using this |
||||||
|
function, the resulting mesh stays the same but there's just one index array, |
||||||
|
indexing both positions and normals: |
||||||
|
|
||||||
|
@code{.cpp} |
||||||
|
{{pA, nB}, {pC, nD}, {pF, nE}, {pA, nE}, {pB, nG}, {pD, nB}, {pC, nB}} |
||||||
|
// unique pairs of positions and normals
|
||||||
|
|
||||||
|
{0, 1, 2, 0, 3, 4, 5, 1, 6} // unified indices
|
||||||
|
@endcode |
||||||
|
|
||||||
|
The function preserves all vertex data including repeated or custom attributes. |
||||||
|
The resulting mesh is interleaved, with all attributes packed tightly together. |
||||||
|
If you need to add specific padding for alignment preservation, pass the result |
||||||
|
to @ref interleave() and specify the paddings between attributes manually. |
||||||
|
Similarly, for simplicity the resulting mesh has always |
||||||
|
@ref MeshIndexType::UnsignedInt --- use @ref compressIndices(const Trade::MeshData&, MeshIndexType) |
||||||
|
if you want to have it compressed to a smaller type. |
||||||
|
|
||||||
|
Expects that @p data is non-empty and all data have the same primitive and |
||||||
|
index count. All inputs have to be indexed, although the particular |
||||||
|
@ref MeshIndexType doesn't matter. For non-indexed attributes combining can be |
||||||
|
done much more efficiently using @ref duplicate(const Trade::MeshData&, Containers::ArrayView<const Trade::MeshAttributeData>), |
||||||
|
alternatively you can turn a non-indexed attribute to an indexed one first |
||||||
|
using @ref removeDuplicatesInPlace() and then call this function. |
||||||
|
*/ |
||||||
|
MAGNUM_MESHTOOLS_EXPORT Trade::MeshData combineIndexedAttributes(const Containers::ArrayView<const Containers::Reference<const Trade::MeshData>> data); |
||||||
|
|
||||||
|
/**
|
||||||
|
* @overload |
||||||
|
* @m_since_latest |
||||||
|
*/ |
||||||
|
MAGNUM_MESHTOOLS_EXPORT Trade::MeshData combineIndexedAttributes(std::initializer_list<Containers::Reference<const Trade::MeshData>> data); |
||||||
|
|
||||||
|
}} |
||||||
|
|
||||||
|
#endif |
||||||
@ -0,0 +1,179 @@ |
|||||||
|
/*
|
||||||
|
This file is part of Magnum. |
||||||
|
|
||||||
|
Copyright © 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018, 2019 |
||||||
|
Vladimír Vondruš <mosra@centrum.cz> |
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a |
||||||
|
copy of this software and associated documentation files (the "Software"), |
||||||
|
to deal in the Software without restriction, including without limitation |
||||||
|
the rights to use, copy, modify, merge, publish, distribute, sublicense, |
||||||
|
and/or sell copies of the Software, and to permit persons to whom the |
||||||
|
Software is furnished to do so, subject to the following conditions: |
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included |
||||||
|
in all copies or substantial portions of the Software. |
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
||||||
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL |
||||||
|
THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER |
||||||
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING |
||||||
|
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER |
||||||
|
DEALINGS IN THE SOFTWARE. |
||||||
|
*/ |
||||||
|
|
||||||
|
#include <sstream> |
||||||
|
#include <Corrade/Containers/Reference.h> |
||||||
|
#include <Corrade/TestSuite/Tester.h> |
||||||
|
#include <Corrade/TestSuite/Compare/Container.h> |
||||||
|
#include <Corrade/Utility/DebugStl.h> |
||||||
|
|
||||||
|
#include "Magnum/MeshTools/Combine.h" |
||||||
|
#include "Magnum/Trade/MeshData.h" |
||||||
|
|
||||||
|
namespace Magnum { namespace MeshTools { namespace Test { namespace { |
||||||
|
|
||||||
|
struct CombineTest: TestSuite::Tester { |
||||||
|
explicit CombineTest(); |
||||||
|
|
||||||
|
void combineIndexedAttributes(); |
||||||
|
void combineIndexedAttributesIndicesOnly(); |
||||||
|
|
||||||
|
void combineIndexedAttributesNoMeshes(); |
||||||
|
void combineIndexedAttributesNotIndexed(); |
||||||
|
void combineIndexedAttributesDifferentPrimitive(); |
||||||
|
void combineIndexedAttributesDifferentIndexCount(); |
||||||
|
}; |
||||||
|
|
||||||
|
CombineTest::CombineTest() { |
||||||
|
addTests({&CombineTest::combineIndexedAttributes, |
||||||
|
&CombineTest::combineIndexedAttributesIndicesOnly, |
||||||
|
|
||||||
|
&CombineTest::combineIndexedAttributesNoMeshes, |
||||||
|
&CombineTest::combineIndexedAttributesNotIndexed, |
||||||
|
&CombineTest::combineIndexedAttributesDifferentPrimitive, |
||||||
|
&CombineTest::combineIndexedAttributesDifferentIndexCount}); |
||||||
|
} |
||||||
|
|
||||||
|
void CombineTest::combineIndexedAttributes() { |
||||||
|
const UnsignedInt indicesA[]{2, 1, 2, 0}; |
||||||
|
const Int dataA[]{2, 1, 0}; |
||||||
|
const UnsignedByte indicesB[]{3, 4, 3, 2}; |
||||||
|
const Short dataB[]{4, 3, 2, 1, 0}; |
||||||
|
const UnsignedShort indicesC[]{7, 6, 7, 5}; |
||||||
|
const Float dataC[]{0.0f, 1.0f, 2.0f, 3.0f, 4.0f, 5.0f, 6.0f, 7.0f}; |
||||||
|
Trade::MeshData a{MeshPrimitive::LineLoop, |
||||||
|
{}, indicesA, Trade::MeshIndexData{indicesA}, |
||||||
|
{}, dataA, {Trade::MeshAttributeData{ |
||||||
|
Trade::meshAttributeCustom(2), Containers::arrayView(dataA)}}}; |
||||||
|
Trade::MeshData b{MeshPrimitive::LineLoop, |
||||||
|
{}, indicesB, Trade::MeshIndexData{indicesB}, |
||||||
|
{}, dataB, {Trade::MeshAttributeData{ |
||||||
|
Trade::meshAttributeCustom(17), Containers::arrayView(dataB)}}}; |
||||||
|
Trade::MeshData c{MeshPrimitive::LineLoop, |
||||||
|
{}, indicesC, Trade::MeshIndexData{indicesC}, |
||||||
|
{}, dataC, {Trade::MeshAttributeData{ |
||||||
|
Trade::meshAttributeCustom(22), Containers::arrayView(dataC)}}}; |
||||||
|
|
||||||
|
Trade::MeshData result = MeshTools::combineIndexedAttributes({a, b, c}); |
||||||
|
CORRADE_COMPARE(result.primitive(), MeshPrimitive::LineLoop); |
||||||
|
CORRADE_VERIFY(result.isIndexed()); |
||||||
|
CORRADE_COMPARE(result.indexType(), MeshIndexType::UnsignedInt); |
||||||
|
CORRADE_COMPARE_AS(result.indices<UnsignedInt>(), |
||||||
|
Containers::arrayView<UnsignedInt>({0, 1, 0, 2}), |
||||||
|
TestSuite::Compare::Container); |
||||||
|
|
||||||
|
CORRADE_COMPARE(result.attributeCount(), 3); |
||||||
|
CORRADE_COMPARE(result.attributeName(0), Trade::meshAttributeCustom(2)); |
||||||
|
CORRADE_COMPARE(result.attributeFormat(0), VertexFormat::Int); |
||||||
|
CORRADE_COMPARE_AS(result.attribute<Int>(0), |
||||||
|
Containers::arrayView<Int>({0, 1, 2}), |
||||||
|
TestSuite::Compare::Container); |
||||||
|
CORRADE_COMPARE(result.attributeName(1), Trade::meshAttributeCustom(17)); |
||||||
|
CORRADE_COMPARE(result.attributeFormat(1), VertexFormat::Short); |
||||||
|
CORRADE_COMPARE_AS(result.attribute<Short>(1), |
||||||
|
Containers::arrayView<Short>({1, 0, 2}), |
||||||
|
TestSuite::Compare::Container); |
||||||
|
CORRADE_COMPARE(result.attributeName(2), Trade::meshAttributeCustom(22)); |
||||||
|
CORRADE_COMPARE(result.attributeFormat(2), VertexFormat::Float); |
||||||
|
CORRADE_COMPARE_AS(result.attribute<Float>(2), |
||||||
|
Containers::arrayView<Float>({7.0f, 6.0f, 5.0f}), |
||||||
|
TestSuite::Compare::Container); |
||||||
|
} |
||||||
|
|
||||||
|
void CombineTest::combineIndexedAttributesIndicesOnly() { |
||||||
|
const UnsignedInt indicesA[]{2, 1, 2}; |
||||||
|
const UnsignedShort indicesB[]{3, 4, 3}; |
||||||
|
const UnsignedByte indicesC[]{7, 6, 7}; |
||||||
|
Trade::MeshData a{MeshPrimitive::LineLoop, {}, indicesA, |
||||||
|
Trade::MeshIndexData{indicesA}}; |
||||||
|
Trade::MeshData b{MeshPrimitive::LineLoop, {}, indicesB, |
||||||
|
Trade::MeshIndexData{indicesB}}; |
||||||
|
Trade::MeshData c{MeshPrimitive::LineLoop, {}, indicesC, |
||||||
|
Trade::MeshIndexData{indicesC}}; |
||||||
|
|
||||||
|
Trade::MeshData result = MeshTools::combineIndexedAttributes({a, b, c}); |
||||||
|
CORRADE_COMPARE(result.primitive(), MeshPrimitive::LineLoop); |
||||||
|
CORRADE_VERIFY(result.isIndexed()); |
||||||
|
CORRADE_COMPARE(result.indexType(), MeshIndexType::UnsignedInt); |
||||||
|
CORRADE_COMPARE_AS(result.indices<UnsignedInt>(), |
||||||
|
Containers::arrayView<UnsignedInt>({0, 1, 0}), |
||||||
|
TestSuite::Compare::Container); |
||||||
|
CORRADE_COMPARE(result.attributeCount(), 0); |
||||||
|
CORRADE_COMPARE(result.vertexCount(), 0); |
||||||
|
} |
||||||
|
|
||||||
|
void CombineTest::combineIndexedAttributesNoMeshes() { |
||||||
|
std::ostringstream out; |
||||||
|
Error redirectError{&out}; |
||||||
|
MeshTools::combineIndexedAttributes({}); |
||||||
|
CORRADE_COMPARE(out.str(), "MeshTools::combineIndexedAttributes(): no meshes passed\n"); |
||||||
|
} |
||||||
|
|
||||||
|
void CombineTest::combineIndexedAttributesNotIndexed() { |
||||||
|
const UnsignedShort indices[5]{}; |
||||||
|
Trade::MeshData a{MeshPrimitive::Lines, |
||||||
|
{}, indices, Trade::MeshIndexData{indices}}; |
||||||
|
Trade::MeshData b{MeshPrimitive::Lines, |
||||||
|
{}, indices, Trade::MeshIndexData{indices}}; |
||||||
|
Trade::MeshData c{MeshPrimitive::Lines, 5}; |
||||||
|
|
||||||
|
std::ostringstream out; |
||||||
|
Error redirectError{&out}; |
||||||
|
MeshTools::combineIndexedAttributes({a, b, c}); |
||||||
|
CORRADE_COMPARE(out.str(), "MeshTools::combineIndexedAttributes(): data 2 is not indexed\n"); |
||||||
|
} |
||||||
|
|
||||||
|
void CombineTest::combineIndexedAttributesDifferentPrimitive() { |
||||||
|
const UnsignedShort indices[5]{}; |
||||||
|
Trade::MeshData a{MeshPrimitive::Lines, |
||||||
|
{}, indices, Trade::MeshIndexData{indices}}; |
||||||
|
Trade::MeshData b{MeshPrimitive::Points, |
||||||
|
{}, indices, Trade::MeshIndexData{indices}}; |
||||||
|
|
||||||
|
std::ostringstream out; |
||||||
|
Error redirectError{&out}; |
||||||
|
MeshTools::combineIndexedAttributes({a, b}); |
||||||
|
CORRADE_COMPARE(out.str(), "MeshTools::combineIndexedAttributes(): data 1 is MeshPrimitive::Points but expected MeshPrimitive::Lines\n"); |
||||||
|
} |
||||||
|
|
||||||
|
void CombineTest::combineIndexedAttributesDifferentIndexCount() { |
||||||
|
const UnsignedShort indices[5]{}; |
||||||
|
Trade::MeshData a{MeshPrimitive::Lines, |
||||||
|
{}, indices, Trade::MeshIndexData{indices}}; |
||||||
|
Trade::MeshData b{MeshPrimitive::Lines, |
||||||
|
{}, indices, Trade::MeshIndexData{indices}}; |
||||||
|
Trade::MeshData c{MeshPrimitive::Lines, |
||||||
|
{}, indices, |
||||||
|
Trade::MeshIndexData{Containers::arrayView(indices).prefix(4)}}; |
||||||
|
|
||||||
|
std::ostringstream out; |
||||||
|
Error redirectError{&out}; |
||||||
|
MeshTools::combineIndexedAttributes({a, b, c}); |
||||||
|
CORRADE_COMPARE(out.str(), "MeshTools::combineIndexedAttributes(): data 2 has 4 indices but expected 5\n"); |
||||||
|
} |
||||||
|
|
||||||
|
}}}} |
||||||
|
|
||||||
|
CORRADE_TEST_MAIN(Magnum::MeshTools::Test::CombineTest) |
||||||
Loading…
Reference in new issue