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