From fdb754bc27bb68ade5a4ba2b38f37319956fadc5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Wed, 17 Jun 2020 19:30:30 +0200 Subject: [PATCH] MeshTools: add owned() and reference() utils. Finally. --- src/Magnum/MeshTools/CMakeLists.txt | 2 + src/Magnum/MeshTools/Reference.cpp | 124 ++++++++++ src/Magnum/MeshTools/Reference.h | 93 ++++++++ src/Magnum/MeshTools/Test/CMakeLists.txt | 1 + src/Magnum/MeshTools/Test/ReferenceTest.cpp | 252 ++++++++++++++++++++ 5 files changed, 472 insertions(+) create mode 100644 src/Magnum/MeshTools/Reference.cpp create mode 100644 src/Magnum/MeshTools/Reference.h create mode 100644 src/Magnum/MeshTools/Test/ReferenceTest.cpp diff --git a/src/Magnum/MeshTools/CMakeLists.txt b/src/Magnum/MeshTools/CMakeLists.txt index 3870d3aa8..c0433f84e 100644 --- a/src/Magnum/MeshTools/CMakeLists.txt +++ b/src/Magnum/MeshTools/CMakeLists.txt @@ -37,6 +37,7 @@ set(MagnumMeshTools_GracefulAssert_SRCS GenerateIndices.cpp GenerateNormals.cpp Interleave.cpp + Reference.cpp RemoveDuplicates.cpp) set(MagnumMeshTools_HEADERS @@ -48,6 +49,7 @@ set(MagnumMeshTools_HEADERS GenerateIndices.h GenerateNormals.h Interleave.h + Reference.h RemoveDuplicates.h Subdivide.h Tipsify.h diff --git a/src/Magnum/MeshTools/Reference.cpp b/src/Magnum/MeshTools/Reference.cpp new file mode 100644 index 000000000..2a0d451e0 --- /dev/null +++ b/src/Magnum/MeshTools/Reference.cpp @@ -0,0 +1,124 @@ +/* + This file is part of Magnum. + + Copyright © 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018, 2019, + 2020 Vladimír Vondruš + + 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 "Reference.h" + +#include + +#include "Magnum/Trade/MeshData.h" + +namespace Magnum { namespace MeshTools { + +Trade::MeshData reference(const Trade::MeshData& data) { + return Trade::MeshData{data.primitive(), + {}, data.indexData(), Trade::MeshIndexData{data.indices()}, + {}, data.vertexData(), Trade::meshAttributeDataNonOwningArray(data.attributeData()), + data.vertexCount()}; +} + +Trade::MeshData mutableReference(Trade::MeshData& data) { + CORRADE_ASSERT((data.indexDataFlags() & Trade::DataFlag::Mutable) && (data.vertexDataFlags() & Trade::DataFlag::Mutable), + "MeshTools::mutableReference(): data not mutable", + (Trade::MeshData{MeshPrimitive::Points, 0})); + + return Trade::MeshData{data.primitive(), + Trade::DataFlag::Mutable, data.mutableIndexData(), Trade::MeshIndexData{data.indices()}, + Trade::DataFlag::Mutable, data.mutableVertexData(), Trade::meshAttributeDataNonOwningArray(data.attributeData()), + data.vertexCount()}; +} + +Trade::MeshData owned(const Trade::MeshData& data) { + return owned(reference(data)); +} + +Trade::MeshData owned(Trade::MeshData&& data) { + /** @todo copy only the actually used range instead of the whole thing? */ + + /* If index data are already owned, move them to the output. This works + without any extra effort also for non-indexed meshes. */ + Containers::Array indexData; + Trade::MeshIndexData indices; + if(data.indexDataFlags() & Trade::DataFlag::Owned) { + indices = Trade::MeshIndexData{data.indices()}; + indexData = data.releaseIndexData(); + + /* Otherwise copy them, if the mesh is indexed. If not, the + default-constructed instances are fine. */ + } else if(data.isIndexed()) { + indexData = Containers::Array{Containers::NoInit, data.indexData().size()}; + indices = Trade::MeshIndexData{data.indexType(), indexData.slice(data.indexOffset(), data.indexOffset() + data.indexCount()*meshIndexTypeSize(data.indexType()))}; + Utility::copy(data.indexData(), indexData); + } + + /* If vertex data are already owned, move them to the output. Because + releasing them will clear vertex count, save that in advance, save also + original vertex data view for attribute offset calculation */ + const UnsignedInt vertexCount = data.vertexCount(); + const Containers::ArrayView originalVertexData = data.vertexData(); + Containers::Array vertexData; + if(data.vertexDataFlags() & Trade::DataFlag::Owned) { + vertexData = data.releaseVertexData(); + + /* Otherwise copy them */ + } else { + vertexData = Containers::Array{Containers::NoInit, originalVertexData.size()}; + Utility::copy(originalVertexData, vertexData); + } + + /* There's no way to know if attribute data are owned until we release + them and check the deleter, but releasing them makes it impossible to + use the convenience MeshData APIs, so we have to do the hard way. */ + Containers::Array originalAttributeData = data.releaseAttributeData(); + + /* If the attribute data are owned *and* the vertex data weren't copied, + we can reuse the original array in its entirety */ + Containers::Array attributeData; + if(!originalAttributeData.deleter() && (data.vertexDataFlags() & Trade::DataFlag::Owned)) { + attributeData = std::move(originalAttributeData); + + /* Otherwise we have to allocate a new one and re-route the attributes to + a potentially different vertex array */ + } else { + attributeData = Containers::Array{originalAttributeData.size()}; + for(std::size_t i = 0; i != originalAttributeData.size(); ++i) { + attributeData[i] = Trade::MeshAttributeData{ + originalAttributeData[i].name(), + originalAttributeData[i].format(), + Containers::StridedArrayView1D{ + vertexData, + vertexData.data() + originalAttributeData[i].offset(originalVertexData), + vertexCount, + originalAttributeData[i].stride()}, + originalAttributeData[i].arraySize()}; + } + } + + return Trade::MeshData{data.primitive(), + std::move(indexData), indices, + std::move(vertexData), std::move(attributeData), + vertexCount}; +} + +}} diff --git a/src/Magnum/MeshTools/Reference.h b/src/Magnum/MeshTools/Reference.h new file mode 100644 index 000000000..f8e4dfa99 --- /dev/null +++ b/src/Magnum/MeshTools/Reference.h @@ -0,0 +1,93 @@ +#ifndef Magnum_MeshTools_Reference_h +#define Magnum_MeshTools_Reference_h +/* + This file is part of Magnum. + + Copyright © 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018, 2019, + 2020 Vladimír Vondruš + + 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::reference(), @ref Magnum::MeshTools::owned() + * @m_since_latest + */ + +#include "Magnum/MeshTools/visibility.h" +#include "Magnum/Trade/Trade.h" + +namespace Magnum { namespace MeshTools { + +/** +@brief Create an immutable reference on a @ref Trade::MeshData +@m_since_latest + +The returned instance has empty @ref Trade::MeshData::indexDataFlags() and +@ref Trade::MeshData::vertexDataFlags() and references attribute data from the +@p data as well. The function performs no allocation or data copy. Use +@ref owned() for an inverse operation. +@see @ref mutableReference() +*/ +MAGNUM_MESHTOOLS_EXPORT Trade::MeshData reference(const Trade::MeshData& data); + +/** +@brief Create a mutable reference on a @ref Trade::MeshData +@m_since_latest + +The returned instance has @ref Trade::MeshData::indexDataFlags() and +@ref Trade::MeshData::vertexDataFlags() set to @ref Trade::DataFlag::Mutable. +The function performs no allocation or data copy. Use @ref owned() for an +inverse operation. Expects that @p data is mutable. +@see @ref reference() +*/ +MAGNUM_MESHTOOLS_EXPORT Trade::MeshData mutableReference(Trade::MeshData& data); + +/** +@brief Create an owned @ref Trade::MeshData +@m_since_latest + +The returned instance owns its index, vertex and attribute data --- both +@ref Trade::MeshData::indexDataFlags() and +@ref Trade::MeshData::vertexDataFlags() have @ref Trade::DataFlag::Mutable and +@ref Trade::DataFlag::Owned set. This function unconditionally does an +allocation and a copy even if the @p data is already owned, use +@ref owned(Trade::MeshData&&) to make an owned copy only if the instance isn't +already owned. +@see @ref reference(), @ref mutableReference() +*/ +MAGNUM_MESHTOOLS_EXPORT Trade::MeshData owned(const Trade::MeshData& data); + +/** +@brief Create an owned @ref Trade::MeshData, if not already +@m_since_latest + +The returned instance owns its index, vertex and attribute data --- both +@ref Trade::MeshData::indexDataFlags() and +@ref Trade::MeshData::vertexDataFlags() have @ref Trade::DataFlag::Mutable and +@ref Trade::DataFlag::Owned set. Index, vertex and attribute data that are +already owned are simply moved to the output, otherwise the data get copied +into newly allocated arrays. +@see @ref reference(), @ref mutableReference() +*/ +MAGNUM_MESHTOOLS_EXPORT Trade::MeshData owned(Trade::MeshData&& data); + +}} + +#endif diff --git a/src/Magnum/MeshTools/Test/CMakeLists.txt b/src/Magnum/MeshTools/Test/CMakeLists.txt index 593556537..f2b34829d 100644 --- a/src/Magnum/MeshTools/Test/CMakeLists.txt +++ b/src/Magnum/MeshTools/Test/CMakeLists.txt @@ -31,6 +31,7 @@ corrade_add_test(MeshToolsFlipNormalsTest FlipNormalsTest.cpp LIBRARIES MagnumMe corrade_add_test(MeshToolsGenerateIndicesTest GenerateIndicesTest.cpp LIBRARIES MagnumMeshToolsTestLib) corrade_add_test(MeshToolsGenerateNormalsTest GenerateNormalsTest.cpp LIBRARIES MagnumMeshToolsTestLib MagnumPrimitives) corrade_add_test(MeshToolsInterleaveTest InterleaveTest.cpp LIBRARIES MagnumMeshToolsTestLib) +corrade_add_test(MeshToolsReferenceTest ReferenceTest.cpp LIBRARIES MagnumMeshToolsTestLib MagnumPrimitives) corrade_add_test(MeshToolsRemoveDuplicatesTest RemoveDuplicatesTest.cpp LIBRARIES MagnumMeshToolsTestLib) corrade_add_test(MeshToolsSubdivideTest SubdivideTest.cpp LIBRARIES Magnum MagnumPrimitives) corrade_add_test(MeshToolsTipsifyTest TipsifyTest.cpp LIBRARIES MagnumMeshTools) diff --git a/src/Magnum/MeshTools/Test/ReferenceTest.cpp b/src/Magnum/MeshTools/Test/ReferenceTest.cpp new file mode 100644 index 000000000..d39bbdab7 --- /dev/null +++ b/src/Magnum/MeshTools/Test/ReferenceTest.cpp @@ -0,0 +1,252 @@ +/* + This file is part of Magnum. + + Copyright © 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018, 2019, + 2020 Vladimír Vondruš + + 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 +#include +#include +#include + +#include "Magnum/Math/Color.h" +#include "Magnum/MeshTools/Reference.h" +#include "Magnum/Primitives/Cube.h" +#include "Magnum/Primitives/Gradient.h" +#include "Magnum/Primitives/Grid.h" +#include "Magnum/Trade/MeshData.h" + +namespace Magnum { namespace MeshTools { namespace Test { namespace { + +struct ReferenceTest: TestSuite::Tester { + explicit ReferenceTest(); + + void reference(); + void referenceNoIndexVertexAttributeData(); + + void mutableReference(); + void mutableReferenceNoIndexVertexAttributeData(); + void mutableReferenceNotMutable(); + + void owned(); + void ownedNoIndexData(); + void ownedNoAttributeVertexData(); + void ownedArrayAttribute(); + void ownedRvaluePassthrough(); + void ownedRvaluePartialPassthrough(); +}; + +ReferenceTest::ReferenceTest() { + addTests({&ReferenceTest::reference, + &ReferenceTest::referenceNoIndexVertexAttributeData, + + &ReferenceTest::mutableReference, + &ReferenceTest::mutableReferenceNoIndexVertexAttributeData, + &ReferenceTest::mutableReferenceNotMutable, + + &ReferenceTest::owned, + &ReferenceTest::ownedNoIndexData, + &ReferenceTest::ownedNoAttributeVertexData, + &ReferenceTest::ownedArrayAttribute, + &ReferenceTest::ownedRvaluePassthrough, + &ReferenceTest::ownedRvaluePartialPassthrough}); +} + +void ReferenceTest::reference() { + const Trade::MeshData circle = Primitives::grid3DSolid({15, 3}, Primitives::GridFlag::Tangents); + + Trade::MeshData reference = MeshTools::reference(circle); + CORRADE_COMPARE(reference.primitive(), circle.primitive()); + CORRADE_COMPARE(reference.indexDataFlags(), Trade::DataFlags{}); + CORRADE_COMPARE(reference.vertexDataFlags(), Trade::DataFlags{}); + CORRADE_COMPARE(reference.vertexCount(), circle.vertexCount()); + CORRADE_COMPARE(static_cast(reference.indexData().data()), circle.indexData().data()); + CORRADE_COMPARE(static_cast(reference.vertexData().data()), circle.vertexData().data()); + CORRADE_COMPARE(static_cast(reference.attributeData().data()), circle.attributeData().data()); +} + +void ReferenceTest::referenceNoIndexVertexAttributeData() { + Trade::MeshData fourtytwo{MeshPrimitive::Edges, 42}; + + Trade::MeshData reference = MeshTools::reference(fourtytwo); + CORRADE_COMPARE(reference.primitive(), fourtytwo.primitive()); + CORRADE_COMPARE(reference.indexDataFlags(), Trade::DataFlags{}); + CORRADE_COMPARE(reference.vertexDataFlags(), Trade::DataFlags{}); + CORRADE_COMPARE(reference.vertexCount(), 42); + CORRADE_VERIFY(!static_cast(reference.indexData().data())); + CORRADE_VERIFY(!static_cast(reference.vertexData().data())); + CORRADE_VERIFY(!static_cast(reference.attributeData().data())); +} + +void ReferenceTest::mutableReference() { + Trade::MeshData circle = Primitives::grid3DSolid({15, 3}, Primitives::GridFlag::Tangents); + CORRADE_VERIFY(circle.isIndexed()); + + Trade::MeshData reference = MeshTools::mutableReference(circle); + CORRADE_COMPARE(reference.primitive(), circle.primitive()); + CORRADE_COMPARE(reference.indexDataFlags(), Trade::DataFlag::Mutable); + CORRADE_COMPARE(reference.vertexDataFlags(), Trade::DataFlag::Mutable); + CORRADE_COMPARE(reference.vertexCount(), circle.vertexCount()); + CORRADE_COMPARE(static_cast(reference.indexData().data()), circle.indexData().data()); + CORRADE_COMPARE(static_cast(reference.vertexData().data()), circle.vertexData().data()); + CORRADE_COMPARE(static_cast(reference.attributeData().data()), circle.attributeData().data()); +} + +void ReferenceTest::mutableReferenceNoIndexVertexAttributeData() { + Trade::MeshData fourtytwo{MeshPrimitive::Edges, 42}; + + Trade::MeshData reference = MeshTools::mutableReference(fourtytwo); + CORRADE_COMPARE(reference.primitive(), fourtytwo.primitive()); + CORRADE_COMPARE(reference.indexDataFlags(), Trade::DataFlag::Mutable); + CORRADE_COMPARE(reference.vertexDataFlags(), Trade::DataFlag::Mutable); + CORRADE_COMPARE(reference.vertexCount(), 42); + CORRADE_VERIFY(!static_cast(reference.indexData().data())); + CORRADE_VERIFY(!static_cast(reference.vertexData().data())); + CORRADE_VERIFY(!static_cast(reference.attributeData().data())); +} + +void ReferenceTest::mutableReferenceNotMutable() { + #ifdef CORRADE_NO_ASSERT + CORRADE_SKIP("CORRADE_NO_ASSERT defined, can't test assertions"); + #endif + + Trade::MeshData cube = Primitives::cubeSolid(); + CORRADE_COMPARE(cube.indexDataFlags(), Trade::DataFlags{}); + CORRADE_COMPARE(cube.vertexDataFlags(), Trade::DataFlags{}); + + std::ostringstream out; + Error redirectError{&out}; + MeshTools::mutableReference(cube); + CORRADE_COMPARE(out.str(), "MeshTools::mutableReference(): data not mutable\n"); +} + +void ReferenceTest::owned() { + Trade::MeshData cube = Primitives::cubeSolid(); + CORRADE_COMPARE(cube.indexDataFlags(), Trade::DataFlags{}); + CORRADE_COMPARE(cube.vertexDataFlags(), Trade::DataFlags{}); + + Trade::MeshData owned = MeshTools::owned(cube); + CORRADE_COMPARE(owned.primitive(), cube.primitive()); + CORRADE_COMPARE(owned.indexDataFlags(), Trade::DataFlag::Mutable|Trade::DataFlag::Owned); + CORRADE_COMPARE(owned.vertexDataFlags(), Trade::DataFlag::Mutable|Trade::DataFlag::Owned); + CORRADE_VERIFY(owned.isIndexed()); + CORRADE_COMPARE(owned.indexCount(), cube.indexCount()); + CORRADE_COMPARE(owned.indexType(), cube.indexType()); + CORRADE_COMPARE(owned.vertexCount(), cube.vertexCount()); + CORRADE_COMPARE(owned.attributeCount(), cube.attributeCount()); + + for(std::size_t i = 0; i != cube.attributeCount(); ++i) { + CORRADE_ITERATION(i); + + CORRADE_COMPARE(owned.attributeName(i), cube.attributeName(i)); + CORRADE_COMPARE(owned.attributeFormat(i), cube.attributeFormat(i)); + CORRADE_COMPARE(owned.attributeOffset(i), cube.attributeOffset(i)); + CORRADE_COMPARE(owned.attributeStride(i), cube.attributeStride(i)); + CORRADE_COMPARE(owned.attributeArraySize(i), cube.attributeArraySize(i)); + } + + CORRADE_COMPARE_AS(owned.indexData(), cube.indexData(), TestSuite::Compare::Container); + CORRADE_COMPARE_AS(owned.vertexData(), cube.vertexData(), TestSuite::Compare::Container); +} + +void ReferenceTest::ownedNoIndexData() { + Trade::MeshData cube = Primitives::cubeSolidStrip(); + CORRADE_VERIFY(!cube.isIndexed()); + CORRADE_COMPARE(cube.vertexDataFlags(), Trade::DataFlags{}); + + Trade::MeshData owned = MeshTools::owned(cube); + CORRADE_COMPARE(owned.primitive(), cube.primitive()); + CORRADE_COMPARE(owned.indexDataFlags(), Trade::DataFlag::Mutable|Trade::DataFlag::Owned); + CORRADE_COMPARE(owned.vertexDataFlags(), Trade::DataFlag::Mutable|Trade::DataFlag::Owned); + CORRADE_VERIFY(!owned.isIndexed()); + CORRADE_COMPARE(owned.vertexCount(), cube.vertexCount()); + CORRADE_COMPARE(owned.attributeCount(), cube.attributeCount()); +} + +void ReferenceTest::ownedNoAttributeVertexData() { + UnsignedShort indexData[]{0, 41, 2}; + Trade::MeshData indexedFourtytwo{MeshPrimitive::Edges, + {}, indexData, Trade::MeshIndexData{indexData}, + 42}; + + Trade::MeshData owned = MeshTools::owned(indexedFourtytwo); + CORRADE_COMPARE(owned.primitive(), MeshPrimitive::Edges); + CORRADE_COMPARE(owned.indexDataFlags(), Trade::DataFlag::Mutable|Trade::DataFlag::Owned); + CORRADE_COMPARE(owned.vertexDataFlags(), Trade::DataFlag::Mutable|Trade::DataFlag::Owned); + CORRADE_VERIFY(owned.isIndexed()); + CORRADE_COMPARE(owned.indexCount(), 3); + CORRADE_COMPARE(owned.indexType(), MeshIndexType::UnsignedShort); + CORRADE_COMPARE(owned.vertexCount(), 42); + CORRADE_COMPARE(owned.attributeCount(), 0); + + CORRADE_COMPARE_AS(owned.indexData(), indexedFourtytwo.indexData(), TestSuite::Compare::Container); + CORRADE_VERIFY(!static_cast(owned.vertexData().data())); + CORRADE_VERIFY(!static_cast(owned.attributeData().data())); +} + +void ReferenceTest::ownedArrayAttribute() { + const Vector3us vertexData[13]{}; + /* Verify that array attributes are propagated correctly */ + Trade::MeshData weirdThing{MeshPrimitive::Faces, + {}, vertexData, + {Trade::MeshAttributeData{Trade::meshAttributeCustom(42), VertexFormat::Half, Containers::arrayView(vertexData), 3}}}; + + Trade::MeshData owned = MeshTools::owned(weirdThing); + CORRADE_COMPARE(owned.vertexCount(), 13); + CORRADE_COMPARE(owned.attributeCount(), 1); + CORRADE_COMPARE(owned.attributeArraySize(0), 3); +} + +void ReferenceTest::ownedRvaluePassthrough() { + Trade::MeshData circle = Primitives::grid3DSolid({15, 3}, Primitives::GridFlag::Tangents); + CORRADE_COMPARE(circle.indexDataFlags(), Trade::DataFlag::Mutable|Trade::DataFlag::Owned); + CORRADE_COMPARE(circle.vertexDataFlags(), Trade::DataFlag::Mutable|Trade::DataFlag::Owned); + const void* indexData = circle.indexData(); + const void* vertexData = circle.vertexData(); + const void* attributeData = circle.attributeData(); + + Trade::MeshData owned = MeshTools::owned(std::move(circle)); + CORRADE_COMPARE(owned.indexDataFlags(), Trade::DataFlag::Mutable|Trade::DataFlag::Owned); + CORRADE_COMPARE(owned.vertexDataFlags(), Trade::DataFlag::Mutable|Trade::DataFlag::Owned); + CORRADE_COMPARE(owned.indexData(), indexData); + CORRADE_COMPARE(owned.vertexData(), vertexData); + CORRADE_COMPARE(owned.attributeData(), attributeData); +} + +void ReferenceTest::ownedRvaluePartialPassthrough() { + Trade::MeshData gradient = Primitives::gradient3DHorizontal({}, {}); + CORRADE_COMPARE(gradient.vertexDataFlags(), Trade::DataFlag::Mutable|Trade::DataFlag::Owned); + const void* vertexData = gradient.vertexData(); + const void* attributeData = gradient.attributeData(); + + Trade::MeshData owned = MeshTools::owned(std::move(gradient)); + CORRADE_COMPARE(owned.indexDataFlags(), Trade::DataFlag::Mutable|Trade::DataFlag::Owned); + CORRADE_COMPARE(owned.vertexDataFlags(), Trade::DataFlag::Mutable|Trade::DataFlag::Owned); + CORRADE_VERIFY(!owned.isIndexed()); + CORRADE_COMPARE(owned.vertexData(), vertexData); + /* Attribute data is constant in the original, so this gets copied */ + CORRADE_VERIFY(owned.attributeData() != attributeData); +} + +}}}} + +CORRADE_TEST_MAIN(Magnum::MeshTools::Test::ReferenceTest)