mirror of https://github.com/mosra/magnum.git
Browse Source
The new filterAttributes() API takes a BitArray, which makes the internals a lot simpler -- no O(n^2) lookup, no growable arrays, and no need to duplicate the same code in the ID- and name-based variants. For consistency with MaterialTools and soon MeshTools, the APIs are moved to a new Filter.h header, with the deprecated variants kept only in the original FilterAttributes.h.pull/620/head
8 changed files with 486 additions and 335 deletions
@ -0,0 +1,148 @@
|
||||
/*
|
||||
This file is part of Magnum. |
||||
|
||||
Copyright © 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018, 2019, |
||||
2020, 2021, 2022 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 "Filter.h" |
||||
|
||||
#include <Corrade/Containers/BitArray.h> |
||||
#include <Corrade/Containers/BitArrayView.h> |
||||
|
||||
#include "Magnum/Trade/MeshData.h" |
||||
|
||||
#ifdef MAGNUM_BUILD_DEPRECATED |
||||
#define _MAGNUM_NO_DEPRECATED_MESHTOOLS_FILTERATTRIBUTES /* so it doesn't warn */ |
||||
#include "Magnum/MeshTools/FilterAttributes.h" |
||||
#endif |
||||
|
||||
namespace Magnum { namespace MeshTools { |
||||
|
||||
Trade::MeshData filterAttributes(const Trade::MeshData& mesh, const Containers::BitArrayView attributesToKeep) { |
||||
CORRADE_ASSERT(attributesToKeep.size() == mesh.attributeCount(), |
||||
"MeshTools::filterAttributes(): expected" << mesh.attributeCount() << "bits but got" << attributesToKeep.size(), (Trade::MeshData{MeshPrimitive::Triangles, 0})); |
||||
|
||||
/* Copy attributes that aren't filtered away. Not using NoInit in order to
|
||||
use the default deleter and have this usable from plugins. */ |
||||
Containers::Array<Trade::MeshAttributeData> filtered{attributesToKeep.count()}; |
||||
/** @todo some copyMasked() utility */ |
||||
UnsignedInt attributeOffset = 0; |
||||
for(UnsignedInt i = 0; i != attributesToKeep.size(); ++i) { |
||||
if(!attributesToKeep[i]) continue; |
||||
filtered[attributeOffset++] = mesh.attributeData()[i]; |
||||
} |
||||
CORRADE_INTERNAL_ASSERT(attributeOffset == filtered.size()); |
||||
|
||||
/* Can't do just Trade::MeshIndexData{data.indices()} as that would discard
|
||||
implementation-specific types. And can't do |
||||
Trade::meshIndexData{data.indexType(), view} |
||||
because asking for index type would assert on non-indexed meshes. */ |
||||
Trade::MeshIndexData indices; |
||||
if(mesh.isIndexed()) indices = Trade::MeshIndexData{ |
||||
mesh.indexType(), |
||||
Containers::StridedArrayView1D<const void>{ |
||||
mesh.indexData(), |
||||
mesh.indexData().data() + mesh.indexOffset(), |
||||
mesh.indexCount(), |
||||
mesh.indexStride()}}; |
||||
|
||||
return Trade::MeshData{mesh.primitive(), |
||||
{}, mesh.indexData(), indices, |
||||
{}, mesh.vertexData(), std::move(filtered), |
||||
mesh.vertexCount()}; |
||||
} |
||||
|
||||
Trade::MeshData filterOnlyAttributes(const Trade::MeshData& mesh, const Containers::ArrayView<const Trade::MeshAttribute> attributes) { |
||||
Containers::BitArray attributesToKeep{DirectInit, mesh.attributeCount(), false}; |
||||
for(const Trade::MeshAttribute attribute: attributes) { |
||||
/* Can't use findAttributeId() because all instances of the attribute
|
||||
should be kept, not just the first one */ |
||||
for(UnsignedInt i = 0; i != attributesToKeep.size(); ++i) { |
||||
if(mesh.attributeName(i) == attribute) |
||||
attributesToKeep.set(i); |
||||
} |
||||
} |
||||
return filterAttributes(mesh, attributesToKeep); |
||||
} |
||||
|
||||
Trade::MeshData filterOnlyAttributes(const Trade::MeshData& mesh, std::initializer_list<Trade::MeshAttribute> attributes) { |
||||
return filterOnlyAttributes(mesh, Containers::arrayView(attributes)); |
||||
} |
||||
|
||||
#ifdef MAGNUM_BUILD_DEPRECATED |
||||
Trade::MeshData filterOnlyAttributes(const Trade::MeshData& mesh, const Containers::ArrayView<const UnsignedInt> attributes) { |
||||
Containers::BitArray attributesToKeep{DirectInit, mesh.attributeCount(), false}; |
||||
for(const UnsignedInt i: attributes) { |
||||
CORRADE_ASSERT(i < mesh.attributeCount(), |
||||
"MeshTools::filterOnlyAttributes(): index" << i << "out of range for" << mesh.attributeCount() << "attributes", |
||||
(Trade::MeshData{MeshPrimitive{}, 0})); |
||||
attributesToKeep.set(i); |
||||
} |
||||
|
||||
return filterAttributes(mesh, attributesToKeep); |
||||
} |
||||
|
||||
Trade::MeshData filterOnlyAttributes(const Trade::MeshData& mesh, std::initializer_list<UnsignedInt> attributes) { |
||||
CORRADE_IGNORE_DEPRECATED_PUSH |
||||
return filterOnlyAttributes(mesh, Containers::arrayView(attributes)); |
||||
CORRADE_IGNORE_DEPRECATED_POP |
||||
} |
||||
#endif |
||||
|
||||
Trade::MeshData filterExceptAttributes(const Trade::MeshData& mesh, const Containers::ArrayView<const Trade::MeshAttribute> attributes) { |
||||
Containers::BitArray attributesToKeep{DirectInit, mesh.attributeCount(), true}; |
||||
for(const Trade::MeshAttribute attribute: attributes) { |
||||
/* Can't use findAttributeId() because all instances of the attribute
|
||||
should be removed, not just the first one */ |
||||
for(UnsignedInt i = 0; i != attributesToKeep.size(); ++i) { |
||||
if(mesh.attributeName(i) == attribute) |
||||
attributesToKeep.reset(i); |
||||
} |
||||
} |
||||
return filterAttributes(mesh, attributesToKeep); |
||||
} |
||||
|
||||
Trade::MeshData filterExceptAttributes(const Trade::MeshData& mesh, std::initializer_list<Trade::MeshAttribute> attributes) { |
||||
return filterExceptAttributes(mesh, Containers::arrayView(attributes)); |
||||
} |
||||
|
||||
#ifdef MAGNUM_BUILD_DEPRECATED |
||||
Trade::MeshData filterExceptAttributes(const Trade::MeshData& mesh, const Containers::ArrayView<const UnsignedInt> attributes) { |
||||
Containers::BitArray attributesToKeep{DirectInit, mesh.attributeCount(), true}; |
||||
for(const UnsignedInt i: attributes) { |
||||
CORRADE_ASSERT(i < mesh.attributeCount(), |
||||
"MeshTools::filterExceptAttributes(): index" << i << "out of range for" << mesh.attributeCount() << "attributes", |
||||
(Trade::MeshData{MeshPrimitive{}, 0})); |
||||
attributesToKeep.reset(i); |
||||
} |
||||
|
||||
return filterAttributes(mesh, attributesToKeep); |
||||
} |
||||
|
||||
Trade::MeshData filterExceptAttributes(const Trade::MeshData& mesh, std::initializer_list<UnsignedInt> attributes) { |
||||
CORRADE_IGNORE_DEPRECATED_PUSH |
||||
return filterExceptAttributes(mesh, Containers::arrayView(attributes)); |
||||
CORRADE_IGNORE_DEPRECATED_POP |
||||
} |
||||
#endif |
||||
|
||||
}} |
||||
@ -0,0 +1,110 @@
|
||||
#ifndef Magnum_MeshTools_Filter_h |
||||
#define Magnum_MeshTools_Filter_h |
||||
/*
|
||||
This file is part of Magnum. |
||||
|
||||
Copyright © 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018, 2019, |
||||
2020, 2021, 2022 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::filterAttributes(), @ref Magnum::MeshTools::filterOnlyAttributes(), @ref Magnum::MeshTools::filterExceptAttributes() |
||||
* @m_since_latest |
||||
*/ |
||||
|
||||
#include <initializer_list> |
||||
|
||||
#include "Magnum/MeshTools/visibility.h" |
||||
#include "Magnum/Trade/Trade.h" |
||||
|
||||
namespace Magnum { namespace MeshTools { |
||||
|
||||
/**
|
||||
@brief Filter a mesh to contain only the selected subset of attributes |
||||
@m_since_latest |
||||
|
||||
Returns a non-owning reference to the vertex and index buffer from @p mesh with |
||||
only the attributes for which the corresponding bit in @p attributesToKeep was |
||||
set. The index buffer, if present, is left untouched. The size of |
||||
@p attributesToKeep is expected to be equal to |
||||
@ref Trade::MeshData::attributeCount(). |
||||
|
||||
This function only operates on the attribute metadata --- if you'd like to have |
||||
the vertex data repacked to contain just the remaining attributes as well, pass |
||||
the output to @ref interleave(const Trade::MeshData&, Containers::ArrayView<const Trade::MeshAttributeData>, InterleaveFlags) "interleave()" |
||||
without @ref InterleaveFlag::PreserveInterleavedAttributes set. |
||||
@see @ref reference() |
||||
*/ |
||||
MAGNUM_MESHTOOLS_EXPORT Trade::MeshData filterAttributes(const Trade::MeshData& mesh, Containers::BitArrayView attributesToKeep); |
||||
|
||||
/**
|
||||
@brief Filter a mesh to contain only the selected subset of named attributes |
||||
@m_since_latest |
||||
|
||||
Returns a non-owning reference to the vertex and index buffer from @p mesh with |
||||
only the attributes that are listed in @p attributes. The index buffer, if |
||||
present, is left untouched. Attributes from the list that are not present in |
||||
@p mesh are skipped. All duplicates of a listed attribute are kept --- if you |
||||
want a different behavior, use the @ref filterOnlyAttributes(const Trade::MeshData&, Containers::ArrayView<const UnsignedInt>) |
||||
overload and pick attributes by their IDs instead. |
||||
|
||||
This function only operates on the attribute metadata --- if you'd like to have |
||||
the vertex data repacked to contain just the remaining attributes as well, pass |
||||
the output to @ref interleave(const Trade::MeshData&, Containers::ArrayView<const Trade::MeshAttributeData>, InterleaveFlags) "interleave()" |
||||
without @ref InterleaveFlag::PreserveInterleavedAttributes set. |
||||
@see @ref reference() |
||||
*/ |
||||
MAGNUM_MESHTOOLS_EXPORT Trade::MeshData filterOnlyAttributes(const Trade::MeshData& mesh, Containers::ArrayView<const Trade::MeshAttribute> attributes); |
||||
|
||||
/**
|
||||
* @overload |
||||
* @m_since_latest |
||||
*/ |
||||
MAGNUM_MESHTOOLS_EXPORT Trade::MeshData filterOnlyAttributes(const Trade::MeshData& mesh, std::initializer_list<Trade::MeshAttribute> attributes); |
||||
|
||||
/**
|
||||
@brief Filter a mesh to contain everything except the selected subset of named attributes |
||||
@m_since_latest |
||||
|
||||
Returns a non-owning reference to the vertex and index buffer from @p mesh with |
||||
only the attributes that are not listed in @p attributes. The index buffer, if |
||||
present, is left untouched. Attributes from the list that are not present in |
||||
@p mesh are skipped. All duplicates of a listed attribute are removed --- if |
||||
you want a different behavior, use the @ref filterExceptAttributes(const Trade::MeshData&, Containers::ArrayView<const UnsignedInt>) |
||||
overload and pick attributes by their IDs instead. If @p attributes is empty, |
||||
the behavior is equivalent to @ref reference(). |
||||
|
||||
This function only operates on the attribute metadata --- if you'd like to have |
||||
the vertex mesh repacked to contain just the remaining attributes as well, pass |
||||
the output to @ref interleave(const Trade::MeshData&, Containers::ArrayView<const Trade::MeshAttributeData>, InterleaveFlags) "interleave()" |
||||
without @ref InterleaveFlag::PreserveInterleavedAttributes set. |
||||
*/ |
||||
MAGNUM_MESHTOOLS_EXPORT Trade::MeshData filterExceptAttributes(const Trade::MeshData& mesh, Containers::ArrayView<const Trade::MeshAttribute> attributes); |
||||
|
||||
/**
|
||||
* @overload |
||||
* @m_since_latest |
||||
*/ |
||||
MAGNUM_MESHTOOLS_EXPORT Trade::MeshData filterExceptAttributes(const Trade::MeshData& mesh, std::initializer_list<Trade::MeshAttribute> attributes); |
||||
|
||||
}} |
||||
|
||||
#endif |
||||
@ -1,216 +0,0 @@
|
||||
/*
|
||||
This file is part of Magnum. |
||||
|
||||
Copyright © 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018, 2019, |
||||
2020, 2021, 2022 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 "FilterAttributes.h" |
||||
|
||||
#include <Corrade/Containers/ArrayView.h> |
||||
#include <Corrade/Containers/GrowableArray.h> |
||||
|
||||
#include "Magnum/Trade/MeshData.h" |
||||
|
||||
namespace Magnum { namespace MeshTools { |
||||
|
||||
namespace { |
||||
|
||||
bool hasAttribute(const Containers::ArrayView<const Trade::MeshAttribute> attributes, const Trade::MeshAttribute attribute) { |
||||
for(const Trade::MeshAttribute i: attributes) |
||||
if(i == attribute) return true; |
||||
return false; |
||||
} |
||||
|
||||
/** @todo drop this insanity in favor of a BitArray */ |
||||
bool hasAttribute(const Containers::ArrayView<const UnsignedInt> attributes, const UnsignedInt attribute) { |
||||
for(const UnsignedInt i: attributes) |
||||
if(i == attribute) return true; |
||||
return false; |
||||
} |
||||
|
||||
} |
||||
|
||||
Trade::MeshData filterOnlyAttributes(const Trade::MeshData& mesh, const Containers::ArrayView<const Trade::MeshAttribute> attributes) { |
||||
/* Not asserting here for existence of attributes since that'd be another
|
||||
O(n^2) operation */ |
||||
/** @todo but that's not consistent with the ID-based variant, or maybe do
|
||||
this via a BitArray in the second loop and check that all attributes |
||||
got referenced afterwards? */ |
||||
|
||||
/* Pick just attributes from the list */ |
||||
Containers::Array<Trade::MeshAttributeData> filtered; |
||||
arrayReserve(filtered, mesh.attributeCount()); |
||||
for(UnsignedInt i = 0; i != mesh.attributeCount(); ++i) { |
||||
if(hasAttribute(attributes, mesh.attributeName(i))) |
||||
arrayAppend(filtered, mesh.attributeData(i)); |
||||
} |
||||
|
||||
/* Convert back to a default deleter to make this usable in plugins */ |
||||
arrayShrink(filtered, DefaultInit); |
||||
|
||||
/* Can't do just Trade::MeshIndexData{data.indices()} as that would discard
|
||||
implementation-specific types. And can't do |
||||
Trade::meshIndexData{data.indexType(), view} |
||||
because asking for index type would assert on non-indexed meshes. */ |
||||
Trade::MeshIndexData indices; |
||||
if(mesh.isIndexed()) indices = Trade::MeshIndexData{ |
||||
mesh.indexType(), |
||||
Containers::StridedArrayView1D<const void>{ |
||||
mesh.indexData(), |
||||
mesh.indexData().data() + mesh.indexOffset(), |
||||
mesh.indexCount(), |
||||
mesh.indexStride()}}; |
||||
|
||||
return Trade::MeshData{mesh.primitive(), |
||||
{}, mesh.indexData(), indices, |
||||
{}, mesh.vertexData(), std::move(filtered), |
||||
mesh.vertexCount()}; |
||||
} |
||||
|
||||
Trade::MeshData filterOnlyAttributes(const Trade::MeshData& mesh, std::initializer_list<Trade::MeshAttribute> attributes) { |
||||
return filterOnlyAttributes(mesh, Containers::arrayView(attributes)); |
||||
} |
||||
|
||||
Trade::MeshData filterOnlyAttributes(const Trade::MeshData& mesh, const Containers::ArrayView<const UnsignedInt> attributes) { |
||||
#ifndef CORRADE_NO_ASSERT |
||||
for(const UnsignedInt i: attributes) CORRADE_ASSERT(i < mesh.attributeCount(), |
||||
"MeshTools::filterOnlyAttributes(): index" << i << "out of range for" << mesh.attributeCount() << "attributes", |
||||
(Trade::MeshData{MeshPrimitive{}, 0})); |
||||
#endif |
||||
|
||||
/* Pick just attributes from the list */ |
||||
Containers::Array<Trade::MeshAttributeData> filtered; |
||||
arrayReserve(filtered, mesh.attributeCount()); |
||||
for(UnsignedInt i = 0; i != mesh.attributeCount(); ++i) { |
||||
if(hasAttribute(attributes, i)) |
||||
arrayAppend(filtered, mesh.attributeData(i)); |
||||
} |
||||
|
||||
/* Convert back to a default deleter to make this usable in plugins */ |
||||
arrayShrink(filtered, DefaultInit); |
||||
|
||||
/* Can't do just Trade::MeshIndexData{data.indices()} as that would discard
|
||||
implementation-specific types. And can't do |
||||
Trade::meshIndexData{data.indexType(), view} |
||||
because asking for index type would assert on non-indexed meshes. */ |
||||
Trade::MeshIndexData indices; |
||||
if(mesh.isIndexed()) indices = Trade::MeshIndexData{ |
||||
mesh.indexType(), |
||||
Containers::StridedArrayView1D<const void>{ |
||||
mesh.indexData(), |
||||
mesh.indexData().data() + mesh.indexOffset(), |
||||
mesh.indexCount(), |
||||
mesh.indexStride()}}; |
||||
|
||||
return Trade::MeshData{mesh.primitive(), |
||||
{}, mesh.indexData(), indices, |
||||
{}, mesh.vertexData(), std::move(filtered), |
||||
mesh.vertexCount()}; |
||||
} |
||||
|
||||
Trade::MeshData filterOnlyAttributes(const Trade::MeshData& mesh, std::initializer_list<UnsignedInt> attributes) { |
||||
return filterOnlyAttributes(mesh, Containers::arrayView(attributes)); |
||||
} |
||||
|
||||
Trade::MeshData filterExceptAttributes(const Trade::MeshData& mesh, const Containers::ArrayView<const Trade::MeshAttribute> attributes) { |
||||
/* Not asserting here for existence of attributes since that'd be another
|
||||
O(n^2) operation */ |
||||
/** @todo but that's not consistent with the ID-based variant, or maybe do
|
||||
this via a BitArray in the second loop and check that all attributes |
||||
got referenced afterwards? */ |
||||
|
||||
/* Pick just attributes from the list */ |
||||
Containers::Array<Trade::MeshAttributeData> filtered; |
||||
arrayReserve(filtered, mesh.attributeCount()); |
||||
for(UnsignedInt i = 0; i != mesh.attributeCount(); ++i) { |
||||
if(!hasAttribute(attributes, mesh.attributeName(i))) |
||||
arrayAppend(filtered, mesh.attributeData(i)); |
||||
} |
||||
|
||||
/* Convert back to a default deleter to make this usable in plugins */ |
||||
arrayShrink(filtered, DefaultInit); |
||||
|
||||
/* Can't do just Trade::MeshIndexData{data.indices()} as that would discard
|
||||
implementation-specific types. And can't do |
||||
Trade::meshIndexData{data.indexType(), view} |
||||
because asking for index type would assert on non-indexed meshes. */ |
||||
Trade::MeshIndexData indices; |
||||
if(mesh.isIndexed()) indices = Trade::MeshIndexData{ |
||||
mesh.indexType(), |
||||
Containers::StridedArrayView1D<const void>{ |
||||
mesh.indexData(), |
||||
mesh.indexData().data() + mesh.indexOffset(), |
||||
mesh.indexCount(), |
||||
mesh.indexStride()}}; |
||||
|
||||
return Trade::MeshData{mesh.primitive(), |
||||
{}, mesh.indexData(), indices, |
||||
{}, mesh.vertexData(), std::move(filtered), |
||||
mesh.vertexCount()}; |
||||
} |
||||
|
||||
Trade::MeshData filterExceptAttributes(const Trade::MeshData& mesh, std::initializer_list<Trade::MeshAttribute> attributes) { |
||||
return filterExceptAttributes(mesh, Containers::arrayView(attributes)); |
||||
} |
||||
|
||||
Trade::MeshData filterExceptAttributes(const Trade::MeshData& mesh, const Containers::ArrayView<const UnsignedInt> attributes) { |
||||
#ifndef CORRADE_NO_ASSERT |
||||
for(const UnsignedInt i: attributes) CORRADE_ASSERT(i < mesh.attributeCount(), |
||||
"MeshTools::filterExceptAttributes(): index" << i << "out of range for" << mesh.attributeCount() << "attributes", |
||||
(Trade::MeshData{MeshPrimitive{}, 0})); |
||||
#endif |
||||
|
||||
/* Pick just attributes from the list */ |
||||
Containers::Array<Trade::MeshAttributeData> filtered; |
||||
arrayReserve(filtered, mesh.attributeCount()); |
||||
for(UnsignedInt i = 0; i != mesh.attributeCount(); ++i) { |
||||
if(!hasAttribute(attributes, i)) |
||||
arrayAppend(filtered, mesh.attributeData(i)); |
||||
} |
||||
|
||||
/* Convert back to a default deleter to make this usable in plugins */ |
||||
arrayShrink(filtered, DefaultInit); |
||||
|
||||
/* Can't do just Trade::MeshIndexData{data.indices()} as that would discard
|
||||
implementation-specific types. And can't do |
||||
Trade::meshIndexData{data.indexType(), view} |
||||
because asking for index type would assert on non-indexed meshes. */ |
||||
Trade::MeshIndexData indices; |
||||
if(mesh.isIndexed()) indices = Trade::MeshIndexData{ |
||||
mesh.indexType(), |
||||
Containers::StridedArrayView1D<const void>{ |
||||
mesh.indexData(), |
||||
mesh.indexData().data() + mesh.indexOffset(), |
||||
mesh.indexCount(), |
||||
mesh.indexStride()}}; |
||||
|
||||
return Trade::MeshData{mesh.primitive(), |
||||
{}, mesh.indexData(), indices, |
||||
{}, mesh.vertexData(), std::move(filtered), |
||||
mesh.vertexCount()}; |
||||
} |
||||
|
||||
Trade::MeshData filterExceptAttributes(const Trade::MeshData& mesh, std::initializer_list<UnsignedInt> attributes) { |
||||
return filterExceptAttributes(mesh, Containers::arrayView(attributes)); |
||||
} |
||||
|
||||
}} |
||||
Loading…
Reference in new issue