From ec3241f4257cbefb60fec1e1fcb8970027bea05d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Mon, 19 Jun 2023 00:04:48 +0200 Subject: [PATCH] MeshTools: common helper for remapping MeshAttributeData to new arrays. So all the locations don't need to be explicitly tested when anything happens with this -- already way too complex -- MeshAttributeData constructor. --- src/Magnum/MeshTools/CMakeLists.txt | 1 + src/Magnum/MeshTools/CompressIndices.cpp | 11 ++-- src/Magnum/MeshTools/Concatenate.cpp | 12 ++--- src/Magnum/MeshTools/Copy.cpp | 13 ++--- src/Magnum/MeshTools/GenerateIndices.cpp | 10 ++-- .../Implementation/remapAttributeData.h | 53 +++++++++++++++++++ src/Magnum/MeshTools/Interleave.cpp | 13 ++--- src/Magnum/MeshTools/RemoveDuplicates.cpp | 9 +--- 8 files changed, 77 insertions(+), 45 deletions(-) create mode 100644 src/Magnum/MeshTools/Implementation/remapAttributeData.h diff --git a/src/Magnum/MeshTools/CMakeLists.txt b/src/Magnum/MeshTools/CMakeLists.txt index 6ec6aeb09..1c1dc106f 100644 --- a/src/Magnum/MeshTools/CMakeLists.txt +++ b/src/Magnum/MeshTools/CMakeLists.txt @@ -70,6 +70,7 @@ set(MagnumMeshTools_HEADERS visibility.h) set(MagnumMeshTools_INTERNAL_HEADERS + Implementation/remapAttributeData.h Implementation/Tipsify.h) if(MAGNUM_BUILD_DEPRECATED) diff --git a/src/Magnum/MeshTools/CompressIndices.cpp b/src/Magnum/MeshTools/CompressIndices.cpp index de9303f77..408593b1e 100644 --- a/src/Magnum/MeshTools/CompressIndices.cpp +++ b/src/Magnum/MeshTools/CompressIndices.cpp @@ -31,6 +31,7 @@ #include "Magnum/Math/FunctionsBatch.h" #include "Magnum/MeshTools/Copy.h" +#include "Magnum/MeshTools/Implementation/remapAttributeData.h" #include "Magnum/Trade/MeshData.h" #ifdef MAGNUM_BUILD_DEPRECATED @@ -130,6 +131,7 @@ Trade::MeshData compressIndices(Trade::MeshData&& mesh, MeshIndexType atLeast) { /* Transfer vertex data as-is, as those don't need any changes. Release if possible. */ + const Containers::ArrayView originalVertexData = mesh.vertexData(); Containers::Array vertexData; const UnsignedInt vertexCount = mesh.vertexCount(); if(mesh.vertexDataFlags() & Trade::DataFlag::Owned) @@ -160,15 +162,12 @@ Trade::MeshData compressIndices(Trade::MeshData&& mesh, MeshIndexType atLeast) { result = compressIndicesImplementation(indices, atLeast, offset); } - /* Recreate the attribute array */ + /* Recreate the attribute array with each attribute being shifted by the + offset calculated above */ const UnsignedInt newVertexCount = vertexCount - offset; Containers::Array attributeData{mesh.attributeCount()}; for(UnsignedInt i = 0, max = attributeData.size(); i != max; ++i) { - const UnsignedInt stride = mesh.attributeStride(i); - attributeData[i] = Trade::MeshAttributeData{mesh.attributeName(i), - mesh.attributeFormat(i), - Containers::StridedArrayView1D{vertexData, vertexData.data() + mesh.attributeOffset(i) + offset*stride, newVertexCount, stride}, - mesh.attributeArraySize(i)}; + attributeData[i] = Implementation::remapAttributeData(mesh.attributeData(i), newVertexCount, originalVertexData, vertexData.exceptPrefix(offset*mesh.attributeStride(i))); } Trade::MeshIndexData indices{result.second(), result.first()}; diff --git a/src/Magnum/MeshTools/Concatenate.cpp b/src/Magnum/MeshTools/Concatenate.cpp index c024f0921..476fe313a 100644 --- a/src/Magnum/MeshTools/Concatenate.cpp +++ b/src/Magnum/MeshTools/Concatenate.cpp @@ -29,6 +29,8 @@ #include #include +#include "Magnum/MeshTools/Implementation/remapAttributeData.h" + namespace Magnum { namespace MeshTools { namespace Implementation { @@ -69,14 +71,8 @@ Trade::MeshData concatenate(Containers::Array&& indexData, const UnsignedI /* Convert the attributes from offset-only and zero vertex count to absolute, referencing the vertex data array */ - for(Trade::MeshAttributeData& attribute: attributeData) { - attribute = Trade::MeshAttributeData{ - attribute.name(), attribute.format(), - Containers::StridedArrayView1D{vertexData, - vertexData + attribute.offset(vertexData), - vertexCount, attribute.stride()}, - attribute.arraySize()}; - } + for(Trade::MeshAttributeData& attribute: attributeData) + attribute = Implementation::remapAttributeData(attribute, vertexCount, vertexData, vertexData); /* Only list primitives are supported currently */ /** @todo delegate to `indexTriangleStrip()` (`duplicate*()`?) etc when diff --git a/src/Magnum/MeshTools/Copy.cpp b/src/Magnum/MeshTools/Copy.cpp index d93615b2b..291872ddf 100644 --- a/src/Magnum/MeshTools/Copy.cpp +++ b/src/Magnum/MeshTools/Copy.cpp @@ -28,6 +28,7 @@ #include #include "Magnum/Trade/MeshData.h" +#include "Magnum/MeshTools/Implementation/remapAttributeData.h" #ifdef MAGNUM_BUILD_DEPRECATED #define _MAGNUM_NO_DEPRECATED_MESHTOOLS_REFERENCE @@ -149,16 +150,8 @@ Trade::MeshData copy(Trade::MeshData&& mesh) { if(originalAttribute.isOffsetOnly()) attributeData[i] = originalAttribute; - /* Otherwise it's kinda verbose */ - else attributeData[i] = Trade::MeshAttributeData{ - originalAttribute.name(), - originalAttribute.format(), - Containers::StridedArrayView1D{ - vertexData, - vertexData.data() + originalAttribute.offset(originalVertexData), - vertexCount, - originalAttribute.stride()}, - originalAttribute.arraySize()}; + /* Otherwise remap it to the new vertex data */ + else attributeData[i] = Implementation::remapAttributeData(originalAttribute, vertexCount, originalVertexData, vertexData); } } diff --git a/src/Magnum/MeshTools/GenerateIndices.cpp b/src/Magnum/MeshTools/GenerateIndices.cpp index 44ac85c89..6701da151 100644 --- a/src/Magnum/MeshTools/GenerateIndices.cpp +++ b/src/Magnum/MeshTools/GenerateIndices.cpp @@ -31,6 +31,7 @@ #include "Magnum/Math/Vector3.h" #include "Magnum/MeshTools/Copy.h" +#include "Magnum/MeshTools/Implementation/remapAttributeData.h" #include "Magnum/Trade/MeshData.h" namespace Magnum { namespace MeshTools { @@ -599,6 +600,7 @@ Trade::MeshData generateIndices(Trade::MeshData&& mesh) { /* Transfer vertex / attribute data as-is, as those don't need any changes. Release if possible. */ + const Containers::ArrayView originalVertexData = mesh.vertexData(); Containers::Array vertexData; if(mesh.vertexDataFlags() & Trade::DataFlag::Owned) vertexData = mesh.releaseVertexData(); @@ -611,12 +613,8 @@ Trade::MeshData generateIndices(Trade::MeshData&& mesh) { /** @todo if the vertex data were moved and this array is owned, it wouldn't need to be recreated, but the logic is a bit complex */ Containers::Array attributeData{mesh.attributeCount()}; - for(UnsignedInt i = 0, max = attributeData.size(); i != max; ++i) { - attributeData[i] = Trade::MeshAttributeData{mesh.attributeName(i), - mesh.attributeFormat(i), - Containers::StridedArrayView1D{vertexData, vertexData.data() + mesh.attributeOffset(i), vertexCount, mesh.attributeStride(i)}, - mesh.attributeArraySize(i)}; - } + for(UnsignedInt i = 0, max = attributeData.size(); i != max; ++i) + attributeData[i] = Implementation::remapAttributeData(mesh.attributeData(i), vertexCount, originalVertexData, vertexData); /* Generate the index array */ MeshPrimitive primitive; diff --git a/src/Magnum/MeshTools/Implementation/remapAttributeData.h b/src/Magnum/MeshTools/Implementation/remapAttributeData.h new file mode 100644 index 000000000..127c011fe --- /dev/null +++ b/src/Magnum/MeshTools/Implementation/remapAttributeData.h @@ -0,0 +1,53 @@ +#ifndef Magnum_MeshTools_Implementation_remapAttributeData_h +#define Magnum_MeshTools_Implementation_remapAttributeData_h +/* + This file is part of Magnum. + + Copyright © 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018, 2019, + 2020, 2021, 2022, 2023 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 "Magnum/Trade/MeshData.h" + +namespace Magnum { namespace MeshTools { namespace Implementation { + +/* Common helper used by various MeshTools algorithms. + + Remaps MeshAttributeData to be relative to the passed vertexData array, + which is assumed to be exactly the same as the original except in different + memory location. All properties including array size are kept but + offset-only attributes are changed to absolute and attributes with + (placeholder) zero vertex count are changed to actual vertex count. */ +inline Trade::MeshAttributeData remapAttributeData(const Trade::MeshAttributeData& attribute, const UnsignedInt vertexCount, const Containers::ArrayView originalVertexData, Containers::ArrayView vertexData) { + return Trade::MeshAttributeData{ + attribute.name(), + attribute.format(), + Containers::StridedArrayView1D{ + vertexData, + vertexData.data() + attribute.offset(originalVertexData), + vertexCount, + attribute.stride()}, + attribute.arraySize()}; +} + +}}} + +#endif diff --git a/src/Magnum/MeshTools/Interleave.cpp b/src/Magnum/MeshTools/Interleave.cpp index f6f14350c..52daf9197 100644 --- a/src/Magnum/MeshTools/Interleave.cpp +++ b/src/Magnum/MeshTools/Interleave.cpp @@ -30,6 +30,7 @@ #include "Magnum/Math/Functions.h" #include "Magnum/MeshTools/Copy.h" +#include "Magnum/MeshTools/Implementation/remapAttributeData.h" #include "Magnum/Trade/MeshData.h" namespace Magnum { namespace MeshTools { @@ -230,15 +231,11 @@ Trade::MeshData interleavedLayout(Trade::MeshData&& mesh, const UnsignedInt vert /* Allocate new data array */ Containers::Array vertexData{NoInit, attributeData[0].stride()*vertexCount}; - /* Convert the attributes from offset-only and zero vertex count to - absolute, referencing the above-allocated data array */ + /* Convert the attributes from all being offset-only and zero vertex count + to absolute, referencing the above-allocated data array */ for(Trade::MeshAttributeData& attribute: attributeData) { - attribute = Trade::MeshAttributeData{ - attribute.name(), attribute.format(), - Containers::StridedArrayView1D{vertexData, - vertexData + attribute.offset(vertexData), - vertexCount, attribute.stride()}, - attribute.arraySize()}; + CORRADE_INTERNAL_ASSERT(attribute.isOffsetOnly()); + attribute = Implementation::remapAttributeData(attribute, vertexCount, vertexData, vertexData); } return Trade::MeshData{mesh.primitive(), std::move(vertexData), std::move(attributeData)}; diff --git a/src/Magnum/MeshTools/RemoveDuplicates.cpp b/src/Magnum/MeshTools/RemoveDuplicates.cpp index 56612bf27..aa6b7c608 100644 --- a/src/Magnum/MeshTools/RemoveDuplicates.cpp +++ b/src/Magnum/MeshTools/RemoveDuplicates.cpp @@ -40,6 +40,7 @@ #include "Magnum/MeshTools/Copy.h" #include "Magnum/MeshTools/Duplicate.h" #include "Magnum/MeshTools/Interleave.h" +#include "Magnum/MeshTools/Implementation/remapAttributeData.h" #include "Magnum/Trade/MeshData.h" namespace Magnum { namespace MeshTools { @@ -456,13 +457,7 @@ Trade::MeshData removeDuplicates(const Trade::MeshData& mesh) { /* Route all attributes to the new vertex data */ Containers::Array attributeData{ownedInterleaved.attributeCount()}; for(UnsignedInt i = 0; i != ownedInterleaved.attributeCount(); ++i) - attributeData[i] = Trade::MeshAttributeData{ownedInterleaved.attributeName(i), - ownedInterleaved.attributeFormat(i), - Containers::StridedArrayView1D{uniqueVertexData, - uniqueVertexData.data() + ownedInterleaved.attributeOffset(i), - uniqueVertexCount, - ownedInterleaved.attributeStride(i)}, - ownedInterleaved.attributeArraySize(i)}; + attributeData[i] = Implementation::remapAttributeData(ownedInterleaved.attributeData(i), uniqueVertexCount, ownedInterleaved.vertexData(), uniqueVertexData); Trade::MeshIndexData indices{indexType, indexData}; return Trade::MeshData{ownedInterleaved.primitive(),