Browse Source

MeshTools: deprecate ID-based filter*Attributes() in favor a new API.

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
Vladimír Vondruš 3 years ago
parent
commit
8eff8f2879
  1. 3
      doc/changelog.dox
  2. 5
      src/Magnum/MeshTools/CMakeLists.txt
  3. 148
      src/Magnum/MeshTools/Filter.cpp
  4. 110
      src/Magnum/MeshTools/Filter.h
  5. 216
      src/Magnum/MeshTools/FilterAttributes.cpp
  6. 93
      src/Magnum/MeshTools/FilterAttributes.h
  7. 2
      src/Magnum/MeshTools/Test/CMakeLists.txt
  8. 244
      src/Magnum/MeshTools/Test/FilterTest.cpp

3
doc/changelog.dox

@ -227,7 +227,8 @@ See also:
@ref MeshTools::boundingRange() for AABBs (see [mosra/magnum#557](https://github.com/mosra/magnum/pull/557)) @ref MeshTools::boundingRange() for AABBs (see [mosra/magnum#557](https://github.com/mosra/magnum/pull/557))
- Added @ref MeshTools::generateQuadIndices() for quad triangulation - Added @ref MeshTools::generateQuadIndices() for quad triangulation
including non-convex and non-planar quads including non-convex and non-planar quads
- New @ref MeshTools::filterOnlyAttributes() and - New @ref MeshTools::filterAttributes(),
@ref MeshTools::filterOnlyAttributes() and
@ref MeshTools::filterExceptAttributes() utilities for filtering mesh data @ref MeshTools::filterExceptAttributes() utilities for filtering mesh data
attribute lists attribute lists
- New family of @ref MeshTools::transform2D(), @ref MeshTools::transform3D() - New family of @ref MeshTools::transform2D(), @ref MeshTools::transform3D()

5
src/Magnum/MeshTools/CMakeLists.txt

@ -38,7 +38,7 @@ set(MagnumMeshTools_GracefulAssert_SRCS
CompressIndices.cpp CompressIndices.cpp
Concatenate.cpp Concatenate.cpp
Duplicate.cpp Duplicate.cpp
FilterAttributes.cpp Filter.cpp
FlipNormals.cpp FlipNormals.cpp
GenerateIndices.cpp GenerateIndices.cpp
GenerateLines.cpp GenerateLines.cpp
@ -54,7 +54,7 @@ set(MagnumMeshTools_HEADERS
CompressIndices.h CompressIndices.h
Concatenate.h Concatenate.h
Duplicate.h Duplicate.h
FilterAttributes.h Filter.h
FlipNormals.h FlipNormals.h
GenerateIndices.h GenerateIndices.h
GenerateLines.h GenerateLines.h
@ -77,6 +77,7 @@ if(MAGNUM_BUILD_DEPRECATED)
CombineIndexedArrays.cpp) CombineIndexedArrays.cpp)
list(APPEND MagnumMeshTools_HEADERS list(APPEND MagnumMeshTools_HEADERS
CombineIndexedArrays.h CombineIndexedArrays.h
FilterAttributes.h
GenerateFlatNormals.h) GenerateFlatNormals.h)
endif() endif()

148
src/Magnum/MeshTools/Filter.cpp

@ -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
}}

110
src/Magnum/MeshTools/Filter.h

@ -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

216
src/Magnum/MeshTools/FilterAttributes.cpp

@ -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));
}
}}

93
src/Magnum/MeshTools/FilterAttributes.h

@ -25,46 +25,30 @@
DEALINGS IN THE SOFTWARE. DEALINGS IN THE SOFTWARE.
*/ */
#ifdef MAGNUM_BUILD_DEPRECATED
/** @file /** @file
* @brief Function @ref Magnum::MeshTools::filterOnlyAttributes(), @ref Magnum::MeshTools::filterExceptAttributes() * @brief Function @ref Magnum::MeshTools::filterOnlyAttributes(), @ref Magnum::MeshTools::filterExceptAttributes()
* @m_since_latest * @m_deprecated_since_latest Use @ref Magnum/MeshTools/Filter.h instead.
*/ */
#endif
#include <initializer_list> #include "Magnum/configure.h"
#include "Magnum/MeshTools/visibility.h" #ifdef MAGNUM_BUILD_DEPRECATED
#include "Magnum/Trade/Trade.h" #include <Corrade/Utility/Macros.h>
namespace Magnum { namespace MeshTools { #include "Magnum/MeshTools/Filter.h"
/** #ifndef _MAGNUM_NO_DEPRECATED_MESHTOOLS_FILTERATTRIBUTES
@brief Filter a mesh to contain only the selected subset of named attributes CORRADE_DEPRECATED_FILE("use Magnum/MeshTools/Filter.h instead")
@m_since_latest #endif
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);
/** namespace Magnum { namespace MeshTools {
* @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 only the selected subset of attributes @brief Filter a mesh to contain only the selected subset of attributes
@m_since_latest @m_deprecated_since_latest Use @ref filterAttributes(const Trade::MeshData&, Containers::BitArrayView)
instead.
Returns a non-owning reference to the vertex and index buffer from @p mesh with Returns a non-owning reference to the vertex and index buffer from @p mesh with
only the attribute IDs listed in @p attributes. IDs specified more than once only the attribute IDs listed in @p attributes. IDs specified more than once
@ -78,42 +62,19 @@ the output to @ref interleave(const Trade::MeshData&, Containers::ArrayView<cons
without @ref InterleaveFlag::PreserveInterleavedAttributes set. without @ref InterleaveFlag::PreserveInterleavedAttributes set.
@see @ref reference() @see @ref reference()
*/ */
MAGNUM_MESHTOOLS_EXPORT Trade::MeshData filterOnlyAttributes(const Trade::MeshData& mesh, Containers::ArrayView<const UnsignedInt> attributes); CORRADE_DEPRECATED("use filterAttributes() instead") MAGNUM_MESHTOOLS_EXPORT Trade::MeshData filterOnlyAttributes(const Trade::MeshData& mesh, Containers::ArrayView<const UnsignedInt> attributes);
/** /**
* @overload @brief Filter a mesh to contain only the selected subset of attributes
* @m_since_latest @m_deprecated_since_latest Use @ref filterAttributes(const Trade::MeshData&, Containers::BitArrayView)
*/ instead.
MAGNUM_MESHTOOLS_EXPORT Trade::MeshData filterOnlyAttributes(const Trade::MeshData& mesh, std::initializer_list<UnsignedInt> 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); CORRADE_DEPRECATED("use filterAttributes() instead") MAGNUM_MESHTOOLS_EXPORT Trade::MeshData filterOnlyAttributes(const Trade::MeshData& mesh, std::initializer_list<UnsignedInt> attributes);
/**
* @overload
* @m_since_latest
*/
MAGNUM_MESHTOOLS_EXPORT Trade::MeshData filterExceptAttributes(const Trade::MeshData& mesh, std::initializer_list<Trade::MeshAttribute> attributes);
/** /**
@brief Filter a mesh to contain everything except the selected subset of attributes @brief Filter a mesh to contain everything except the selected subset of attributes
@m_since_latest @m_deprecated_since_latest Use @ref filterAttributes(const Trade::MeshData&, Containers::BitArrayView)
instead.
Returns a non-owning reference to the vertex and index buffer from @p mesh with Returns a non-owning reference to the vertex and index buffer from @p mesh with
only the attribute IDs that are not listed in @p attributes. IDs specified only the attribute IDs that are not listed in @p attributes. IDs specified
@ -127,14 +88,18 @@ 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()" the output to @ref interleave(const Trade::MeshData&, Containers::ArrayView<const Trade::MeshAttributeData>, InterleaveFlags) "interleave()"
without @ref InterleaveFlag::PreserveInterleavedAttributes set. without @ref InterleaveFlag::PreserveInterleavedAttributes set.
*/ */
MAGNUM_MESHTOOLS_EXPORT Trade::MeshData filterExceptAttributes(const Trade::MeshData& mesh, Containers::ArrayView<const UnsignedInt> attributes); CORRADE_DEPRECATED("use filterAttributes() instead") MAGNUM_MESHTOOLS_EXPORT Trade::MeshData filterExceptAttributes(const Trade::MeshData& mesh, Containers::ArrayView<const UnsignedInt> attributes);
/** /**
* @overload @brief Filter a mesh to contain everything except the selected subset of attributes
* @m_since_latest @m_deprecated_since_latest Use @ref filterAttributes(const Trade::MeshData&, Containers::BitArrayView)
*/ instead.
MAGNUM_MESHTOOLS_EXPORT Trade::MeshData filterExceptAttributes(const Trade::MeshData& mesh, std::initializer_list<UnsignedInt> attributes); */
CORRADE_DEPRECATED("use filterAttributes() instead") MAGNUM_MESHTOOLS_EXPORT Trade::MeshData filterExceptAttributes(const Trade::MeshData& mesh, std::initializer_list<UnsignedInt> attributes);
}} }}
#else
#error use Magnum/MeshTools/Filter.h instead
#endif
#endif #endif

2
src/Magnum/MeshTools/Test/CMakeLists.txt

@ -32,7 +32,7 @@ corrade_add_test(MeshToolsCombineTest CombineTest.cpp LIBRARIES MagnumMeshToolsT
corrade_add_test(MeshToolsCompressIndicesTest CompressIndicesTest.cpp LIBRARIES MagnumMeshToolsTestLib) corrade_add_test(MeshToolsCompressIndicesTest CompressIndicesTest.cpp LIBRARIES MagnumMeshToolsTestLib)
corrade_add_test(MeshToolsConcatenateTest ConcatenateTest.cpp LIBRARIES MagnumMeshToolsTestLib) corrade_add_test(MeshToolsConcatenateTest ConcatenateTest.cpp LIBRARIES MagnumMeshToolsTestLib)
corrade_add_test(MeshToolsDuplicateTest DuplicateTest.cpp LIBRARIES MagnumMeshToolsTestLib) corrade_add_test(MeshToolsDuplicateTest DuplicateTest.cpp LIBRARIES MagnumMeshToolsTestLib)
corrade_add_test(MeshToolsFilterAttributesTest FilterAttributesTest.cpp LIBRARIES MagnumMeshToolsTestLib) corrade_add_test(MeshToolsFilterTest FilterTest.cpp LIBRARIES MagnumMeshToolsTestLib)
corrade_add_test(MeshToolsFlipNormalsTest FlipNormalsTest.cpp LIBRARIES MagnumMeshToolsTestLib) corrade_add_test(MeshToolsFlipNormalsTest FlipNormalsTest.cpp LIBRARIES MagnumMeshToolsTestLib)
corrade_add_test(MeshToolsGenerateIndicesTest GenerateIndicesTest.cpp LIBRARIES MagnumMeshToolsTestLib) corrade_add_test(MeshToolsGenerateIndicesTest GenerateIndicesTest.cpp LIBRARIES MagnumMeshToolsTestLib)
corrade_add_test(MeshToolsGenerateLinesTest GenerateLinesTest.cpp corrade_add_test(MeshToolsGenerateLinesTest GenerateLinesTest.cpp

244
src/Magnum/MeshTools/Test/FilterAttributesTest.cpp → src/Magnum/MeshTools/Test/FilterTest.cpp

@ -24,35 +24,50 @@
*/ */
#include <sstream> #include <sstream>
#include <Corrade/Containers/BitArray.h>
#include <Corrade/Containers/BitArrayView.h>
#include <Corrade/TestSuite/Tester.h> #include <Corrade/TestSuite/Tester.h>
#include <Corrade/Utility/DebugStl.h> #include <Corrade/Utility/DebugStl.h>
#include "Magnum/Math/Vector4.h" #include "Magnum/Math/Vector4.h"
#include "Magnum/MeshTools/FilterAttributes.h" #include "Magnum/MeshTools/Filter.h"
#include "Magnum/Trade/MeshData.h" #include "Magnum/Trade/MeshData.h"
namespace Magnum { namespace MeshTools { namespace Test { namespace { #ifdef MAGNUM_BUILD_DEPRECATED
#define _MAGNUM_NO_DEPRECATED_MESHTOOLS_FILTERATTRIBUTES /* so it doesn't warn */
struct FilterAttributesTest: TestSuite::Tester { #include "Magnum/MeshTools/FilterAttributes.h"
explicit FilterAttributesTest(); #endif
void filterOnlyAttributeNames();
void filterOnlyAttributeNamesNoIndexData();
void filterOnlyAttributeNamesNoAttributeData();
void filterOnlyAttributeIds();
void filterOnlyAttributeIdsOutOfBounds();
void filterOnlyAttributeIdsNoIndexData();
void filterOnlyAttributeIdsNoAttributeData();
void filterExceptAttributeNames(); namespace Magnum { namespace MeshTools { namespace Test { namespace {
void filterExceptAttributeNamesNoIndexData();
void filterExceptAttributeNamesNoAttributeData();
void filterExceptAttributeIds(); struct FilterTest: TestSuite::Tester {
void filterExceptAttributeIdsOutOfBounds(); explicit FilterTest();
void filterExceptAttributeIdsNoIndexData();
void filterExceptAttributeIdsNoAttributeData(); void attributes();
void attributesNoIndexData();
void attributesWrongBitCount();
void onlyAttributes();
void onlyAttributesNoIndexData();
void onlyAttributesNoAttributeData();
#ifdef MAGNUM_BUILD_DEPRECATED
void onlyAttributeIds();
void onlyAttributeIdsOutOfBounds();
void onlyAttributeIdsNoIndexData();
void onlyAttributeIdsNoAttributeData();
#endif
void exceptAttributes();
void exceptAttributesNoIndexData();
void exceptAttributesNoAttributeData();
#ifdef MAGNUM_BUILD_DEPRECATED
void exceptAttributeIds();
void exceptAttributeIdsOutOfBounds();
void exceptAttributeIdsNoIndexData();
void exceptAttributeIdsNoAttributeData();
#endif
}; };
const struct { const struct {
@ -63,32 +78,42 @@ const struct {
{"implementation-specific index type", meshIndexTypeWrap(0xcaca)} {"implementation-specific index type", meshIndexTypeWrap(0xcaca)}
}; };
FilterAttributesTest::FilterAttributesTest() { FilterTest::FilterTest() {
addInstancedTests({&FilterAttributesTest::filterOnlyAttributeNames}, addInstancedTests({&FilterTest::attributes},
Containers::arraySize(ImplementationSpecificIndexTypeData));
addTests({&FilterTest::attributesNoIndexData,
&FilterTest::attributesWrongBitCount});
addInstancedTests({&FilterTest::onlyAttributes},
Containers::arraySize(ImplementationSpecificIndexTypeData)); Containers::arraySize(ImplementationSpecificIndexTypeData));
addTests({&FilterAttributesTest::filterOnlyAttributeNamesNoIndexData, addTests({&FilterTest::onlyAttributesNoIndexData,
&FilterAttributesTest::filterOnlyAttributeNamesNoAttributeData}); &FilterTest::onlyAttributesNoAttributeData});
addInstancedTests({&FilterAttributesTest::filterOnlyAttributeIds}, #ifdef MAGNUM_BUILD_DEPRECATED
addInstancedTests({&FilterTest::onlyAttributeIds},
Containers::arraySize(ImplementationSpecificIndexTypeData)); Containers::arraySize(ImplementationSpecificIndexTypeData));
addTests({&FilterAttributesTest::filterOnlyAttributeIdsOutOfBounds, addTests({&FilterTest::onlyAttributeIdsOutOfBounds,
&FilterAttributesTest::filterOnlyAttributeIdsNoIndexData, &FilterTest::onlyAttributeIdsNoIndexData,
&FilterAttributesTest::filterOnlyAttributeIdsNoAttributeData}); &FilterTest::onlyAttributeIdsNoAttributeData});
#endif
addInstancedTests({&FilterAttributesTest::filterExceptAttributeNames}, addInstancedTests({&FilterTest::exceptAttributes},
Containers::arraySize(ImplementationSpecificIndexTypeData)); Containers::arraySize(ImplementationSpecificIndexTypeData));
addTests({&FilterAttributesTest::filterExceptAttributeNamesNoIndexData, addTests({&FilterTest::exceptAttributesNoIndexData,
&FilterAttributesTest::filterExceptAttributeNamesNoAttributeData}); &FilterTest::exceptAttributesNoAttributeData});
addInstancedTests({&FilterAttributesTest::filterExceptAttributeIds}, #ifdef MAGNUM_BUILD_DEPRECATED
addInstancedTests({&FilterTest::exceptAttributeIds},
Containers::arraySize(ImplementationSpecificIndexTypeData)); Containers::arraySize(ImplementationSpecificIndexTypeData));
addTests({&FilterAttributesTest::filterExceptAttributeIdsOutOfBounds, addTests({&FilterTest::exceptAttributeIdsOutOfBounds,
&FilterAttributesTest::filterExceptAttributeIdsNoIndexData, &FilterTest::exceptAttributeIdsNoIndexData,
&FilterAttributesTest::filterExceptAttributeIdsNoAttributeData}); &FilterTest::exceptAttributeIdsNoAttributeData});
#endif
} }
struct Vertex { struct Vertex {
@ -97,7 +122,104 @@ struct Vertex {
Vector2 textureCoordinates1, textureCoordinates2; Vector2 textureCoordinates1, textureCoordinates2;
}; };
void FilterAttributesTest::filterOnlyAttributeNames() { void FilterTest::attributes() {
auto&& data = ImplementationSpecificIndexTypeData[testCaseInstanceId()];
setTestCaseDescription(data.name);
Containers::Array<char> indexData{5*sizeof(UnsignedShort)};
Containers::StridedArrayView1D<UnsignedShort> indices = Containers::arrayCast<UnsignedShort>(indexData);
Containers::Array<char> vertexData{3*sizeof(Vertex)};
Containers::StridedArrayView1D<Vertex> vertices = Containers::arrayCast<Vertex>(vertexData);
Trade::MeshData mesh{MeshPrimitive::TriangleStrip,
std::move(indexData), Trade::MeshIndexData{data.indexType, indices},
std::move(vertexData), {
Trade::MeshAttributeData{Trade::MeshAttribute::Position, vertices.slice(&Vertex::position)},
Trade::MeshAttributeData{Trade::MeshAttribute::Tangent, vertices.slice(&Vertex::tangent)},
Trade::MeshAttributeData{Trade::MeshAttribute::TextureCoordinates, vertices.slice(&Vertex::textureCoordinates1)},
Trade::MeshAttributeData{Trade::MeshAttribute::TextureCoordinates, vertices.slice(&Vertex::textureCoordinates2)},
}};
Containers::BitArray attributesToKeep{ValueInit, mesh.attributeCount()};
attributesToKeep.set(1);
attributesToKeep.set(3);
Trade::MeshData filtered = filterAttributes(mesh, attributesToKeep);
CORRADE_COMPARE(filtered.primitive(), MeshPrimitive::TriangleStrip);
CORRADE_VERIFY(filtered.isIndexed());
CORRADE_COMPARE(filtered.indexCount(), 5);
CORRADE_COMPARE(filtered.indexType(), data.indexType);
CORRADE_COMPARE(filtered.indexData().data(), indices.data());
CORRADE_COMPARE(filtered.indexDataFlags(), Trade::DataFlags{});
CORRADE_COMPARE(filtered.vertexCount(), 3);
CORRADE_COMPARE(filtered.vertexData().data(), vertices.data());
CORRADE_COMPARE(filtered.vertexDataFlags(), Trade::DataFlags{});
/* Testing just the offset if it matches expectations, the
MeshAttributeData is copied directly so no metadata should get lost */
CORRADE_COMPARE(filtered.attributeCount(), 2);
CORRADE_COMPARE(filtered.attributeName(0), Trade::MeshAttribute::Tangent);
CORRADE_COMPARE(filtered.attributeOffset(0), offsetof(Vertex, tangent));
CORRADE_COMPARE(filtered.attributeName(1), Trade::MeshAttribute::TextureCoordinates);
CORRADE_COMPARE(filtered.attributeOffset(1), offsetof(Vertex, textureCoordinates2));
/* The attribute data should not be a growable array to make this usable in
plugins */
Containers::Array<Trade::MeshAttributeData> attributeData = filtered.releaseAttributeData();
CORRADE_VERIFY(!attributeData.deleter());
}
void FilterTest::attributesNoIndexData() {
/* A trivial subset of filterAttributes() testing it doesn't blow up if the
mesh is not indexed */
Containers::Array<char> vertexData{3*sizeof(Vertex)};
Containers::StridedArrayView1D<Vertex> vertices = Containers::arrayCast<Vertex>(vertexData);
Trade::MeshData mesh{MeshPrimitive::TriangleFan,
std::move(vertexData), {
Trade::MeshAttributeData{Trade::MeshAttribute::TextureCoordinates, vertices.slice(&Vertex::textureCoordinates1)}
}};
Trade::MeshData filtered = filterAttributes(mesh, Containers::BitArray{DirectInit, 1, true});
CORRADE_COMPARE(filtered.primitive(), MeshPrimitive::TriangleFan);
CORRADE_VERIFY(!filtered.isIndexed());
/* Consistent with behavior in reference() for index-less meshes */
CORRADE_COMPARE(filtered.indexDataFlags(), Trade::DataFlags{});
CORRADE_COMPARE(filtered.vertexCount(), 3);
CORRADE_COMPARE(filtered.vertexData().data(), vertices.data());
CORRADE_COMPARE(filtered.vertexDataFlags(), Trade::DataFlags{});
/* Testing just the offset if it matches expectations, the
MeshAttributeData is copied directly so no metadata should get lost */
CORRADE_COMPARE(filtered.attributeCount(), 1);
CORRADE_COMPARE(filtered.attributeName(0), Trade::MeshAttribute::TextureCoordinates);
CORRADE_COMPARE(filtered.attributeOffset(0), offsetof(Vertex, textureCoordinates1));
}
void FilterTest::attributesWrongBitCount() {
CORRADE_SKIP_IF_NO_ASSERT();
/* GCC 4.8 dies if I try to initialize this with a {}. I won't, then. */
Vertex vertices[3];
Trade::MeshData mesh{MeshPrimitive::TriangleFan,
{}, vertices, {
Trade::MeshAttributeData{Trade::MeshAttribute::Position, Containers::stridedArrayView(vertices).slice(&Vertex::position)},
Trade::MeshAttributeData{Trade::MeshAttribute::TextureCoordinates, Containers::stridedArrayView(vertices).slice(&Vertex::textureCoordinates1)}
}};
std::ostringstream out;
Error redirectError{&out};
filterAttributes(mesh, Containers::BitArray{ValueInit, 3});
CORRADE_COMPARE(out.str(), "MeshTools::filterAttributes(): expected 2 bits but got 3\n");
}
void FilterTest::onlyAttributes() {
auto&& data = ImplementationSpecificIndexTypeData[testCaseInstanceId()]; auto&& data = ImplementationSpecificIndexTypeData[testCaseInstanceId()];
setTestCaseDescription(data.name); setTestCaseDescription(data.name);
@ -148,7 +270,7 @@ void FilterAttributesTest::filterOnlyAttributeNames() {
CORRADE_VERIFY(!attributeData.deleter()); CORRADE_VERIFY(!attributeData.deleter());
} }
void FilterAttributesTest::filterOnlyAttributeNamesNoIndexData() { void FilterTest::onlyAttributesNoIndexData() {
/* A trivial subset of filterOnlyAttributeNames() testing it doesn't blow /* A trivial subset of filterOnlyAttributeNames() testing it doesn't blow
up if the mesh is not indexed */ up if the mesh is not indexed */
@ -180,7 +302,7 @@ void FilterAttributesTest::filterOnlyAttributeNamesNoIndexData() {
CORRADE_COMPARE(filtered.attributeOffset(0), offsetof(Vertex, textureCoordinates1)); CORRADE_COMPARE(filtered.attributeOffset(0), offsetof(Vertex, textureCoordinates1));
} }
void FilterAttributesTest::filterOnlyAttributeNamesNoAttributeData() { void FilterTest::onlyAttributesNoAttributeData() {
Containers::Array<char> indexData{5*sizeof(UnsignedShort)}; Containers::Array<char> indexData{5*sizeof(UnsignedShort)};
Containers::StridedArrayView1D<UnsignedShort> indices = Containers::arrayCast<UnsignedShort>(indexData); Containers::StridedArrayView1D<UnsignedShort> indices = Containers::arrayCast<UnsignedShort>(indexData);
@ -206,7 +328,8 @@ void FilterAttributesTest::filterOnlyAttributeNamesNoAttributeData() {
CORRADE_COMPARE(filtered.attributeCount(), 0); CORRADE_COMPARE(filtered.attributeCount(), 0);
} }
void FilterAttributesTest::filterOnlyAttributeIds() { #ifdef MAGNUM_BUILD_DEPRECATED
void FilterTest::onlyAttributeIds() {
auto&& data = ImplementationSpecificIndexTypeData[testCaseInstanceId()]; auto&& data = ImplementationSpecificIndexTypeData[testCaseInstanceId()];
setTestCaseDescription(data.name); setTestCaseDescription(data.name);
@ -224,11 +347,13 @@ void FilterAttributesTest::filterOnlyAttributeIds() {
Trade::MeshAttributeData{Trade::MeshAttribute::TextureCoordinates, vertices.slice(&Vertex::textureCoordinates2)}, Trade::MeshAttributeData{Trade::MeshAttribute::TextureCoordinates, vertices.slice(&Vertex::textureCoordinates2)},
}}; }};
CORRADE_IGNORE_DEPRECATED_PUSH
Trade::MeshData filtered = filterOnlyAttributes(mesh, { Trade::MeshData filtered = filterOnlyAttributes(mesh, {
/* The attribute 1 is specified twice, but that won't result in the /* The attribute 1 is specified twice, but that won't result in the
same attribute being added twice */ same attribute being added twice */
1, 1, 3 1, 1, 3
}); });
CORRADE_IGNORE_DEPRECATED_POP
CORRADE_COMPARE(filtered.primitive(), MeshPrimitive::TriangleStrip); CORRADE_COMPARE(filtered.primitive(), MeshPrimitive::TriangleStrip);
CORRADE_VERIFY(filtered.isIndexed()); CORRADE_VERIFY(filtered.isIndexed());
@ -255,7 +380,7 @@ void FilterAttributesTest::filterOnlyAttributeIds() {
CORRADE_VERIFY(!attributeData.deleter()); CORRADE_VERIFY(!attributeData.deleter());
} }
void FilterAttributesTest::filterOnlyAttributeIdsOutOfBounds() { void FilterTest::onlyAttributeIdsOutOfBounds() {
CORRADE_SKIP_IF_NO_ASSERT(); CORRADE_SKIP_IF_NO_ASSERT();
/* GCC 4.8 dies if I try to initialize this with a {}. I won't, then. */ /* GCC 4.8 dies if I try to initialize this with a {}. I won't, then. */
@ -269,11 +394,13 @@ void FilterAttributesTest::filterOnlyAttributeIdsOutOfBounds() {
std::ostringstream out; std::ostringstream out;
Error redirectError{&out}; Error redirectError{&out};
CORRADE_IGNORE_DEPRECATED_PUSH
filterOnlyAttributes(mesh, {0, 0, 2}); filterOnlyAttributes(mesh, {0, 0, 2});
CORRADE_IGNORE_DEPRECATED_POP
CORRADE_COMPARE(out.str(), "MeshTools::filterOnlyAttributes(): index 2 out of range for 2 attributes\n"); CORRADE_COMPARE(out.str(), "MeshTools::filterOnlyAttributes(): index 2 out of range for 2 attributes\n");
} }
void FilterAttributesTest::filterOnlyAttributeIdsNoIndexData() { void FilterTest::onlyAttributeIdsNoIndexData() {
/* A trivial subset of filterOnlyAttributeIds() testing it doesn't blow up /* A trivial subset of filterOnlyAttributeIds() testing it doesn't blow up
if the mesh is not indexed */ if the mesh is not indexed */
@ -285,9 +412,11 @@ void FilterAttributesTest::filterOnlyAttributeIdsNoIndexData() {
Trade::MeshAttributeData{Trade::MeshAttribute::TextureCoordinates, vertices.slice(&Vertex::textureCoordinates1)} Trade::MeshAttributeData{Trade::MeshAttribute::TextureCoordinates, vertices.slice(&Vertex::textureCoordinates1)}
}}; }};
CORRADE_IGNORE_DEPRECATED_PUSH
Trade::MeshData filtered = filterOnlyAttributes(mesh, { Trade::MeshData filtered = filterOnlyAttributes(mesh, {
0 0
}); });
CORRADE_IGNORE_DEPRECATED_POP
CORRADE_COMPARE(filtered.primitive(), MeshPrimitive::TriangleFan); CORRADE_COMPARE(filtered.primitive(), MeshPrimitive::TriangleFan);
CORRADE_VERIFY(!filtered.isIndexed()); CORRADE_VERIFY(!filtered.isIndexed());
@ -305,14 +434,16 @@ void FilterAttributesTest::filterOnlyAttributeIdsNoIndexData() {
CORRADE_COMPARE(filtered.attributeOffset(0), offsetof(Vertex, textureCoordinates1)); CORRADE_COMPARE(filtered.attributeOffset(0), offsetof(Vertex, textureCoordinates1));
} }
void FilterAttributesTest::filterOnlyAttributeIdsNoAttributeData() { void FilterTest::onlyAttributeIdsNoAttributeData() {
Containers::Array<char> indexData{5*sizeof(UnsignedShort)}; Containers::Array<char> indexData{5*sizeof(UnsignedShort)};
Containers::StridedArrayView1D<UnsignedShort> indices = Containers::arrayCast<UnsignedShort>(indexData); Containers::StridedArrayView1D<UnsignedShort> indices = Containers::arrayCast<UnsignedShort>(indexData);
Trade::MeshData mesh{MeshPrimitive::Points, Trade::MeshData mesh{MeshPrimitive::Points,
std::move(indexData), Trade::MeshIndexData{indices}, 15}; std::move(indexData), Trade::MeshIndexData{indices}, 15};
CORRADE_IGNORE_DEPRECATED_PUSH
Trade::MeshData filtered = filterOnlyAttributes(mesh, std::initializer_list<UnsignedInt>{}); Trade::MeshData filtered = filterOnlyAttributes(mesh, std::initializer_list<UnsignedInt>{});
CORRADE_IGNORE_DEPRECATED_POP
CORRADE_COMPARE(filtered.primitive(), MeshPrimitive::Points); CORRADE_COMPARE(filtered.primitive(), MeshPrimitive::Points);
CORRADE_VERIFY(filtered.isIndexed()); CORRADE_VERIFY(filtered.isIndexed());
@ -328,8 +459,9 @@ void FilterAttributesTest::filterOnlyAttributeIdsNoAttributeData() {
CORRADE_COMPARE(filtered.attributeCount(), 0); CORRADE_COMPARE(filtered.attributeCount(), 0);
} }
#endif
void FilterAttributesTest::filterExceptAttributeNames() { void FilterTest::exceptAttributes() {
auto&& data = ImplementationSpecificIndexTypeData[testCaseInstanceId()]; auto&& data = ImplementationSpecificIndexTypeData[testCaseInstanceId()];
setTestCaseDescription(data.name); setTestCaseDescription(data.name);
@ -380,7 +512,7 @@ void FilterAttributesTest::filterExceptAttributeNames() {
CORRADE_VERIFY(!attributeData.deleter()); CORRADE_VERIFY(!attributeData.deleter());
} }
void FilterAttributesTest::filterExceptAttributeNamesNoIndexData() { void FilterTest::exceptAttributesNoIndexData() {
/* A trivial subset of filterExceptAttributeNames() testing it doesn't blow /* A trivial subset of filterExceptAttributeNames() testing it doesn't blow
up if the mesh is not indexed */ up if the mesh is not indexed */
@ -413,7 +545,7 @@ void FilterAttributesTest::filterExceptAttributeNamesNoIndexData() {
CORRADE_COMPARE(filtered.attributeOffset(0), offsetof(Vertex, textureCoordinates1)); CORRADE_COMPARE(filtered.attributeOffset(0), offsetof(Vertex, textureCoordinates1));
} }
void FilterAttributesTest::filterExceptAttributeNamesNoAttributeData() { void FilterTest::exceptAttributesNoAttributeData() {
Containers::Array<char> indexData{5*sizeof(UnsignedShort)}; Containers::Array<char> indexData{5*sizeof(UnsignedShort)};
Containers::StridedArrayView1D<UnsignedShort> indices = Containers::arrayCast<UnsignedShort>(indexData); Containers::StridedArrayView1D<UnsignedShort> indices = Containers::arrayCast<UnsignedShort>(indexData);
@ -439,7 +571,8 @@ void FilterAttributesTest::filterExceptAttributeNamesNoAttributeData() {
CORRADE_COMPARE(filtered.attributeCount(), 0); CORRADE_COMPARE(filtered.attributeCount(), 0);
} }
void FilterAttributesTest::filterExceptAttributeIds() { #ifdef MAGNUM_BUILD_DEPRECATED
void FilterTest::exceptAttributeIds() {
auto&& data = ImplementationSpecificIndexTypeData[testCaseInstanceId()]; auto&& data = ImplementationSpecificIndexTypeData[testCaseInstanceId()];
setTestCaseDescription(data.name); setTestCaseDescription(data.name);
@ -457,11 +590,13 @@ void FilterAttributesTest::filterExceptAttributeIds() {
Trade::MeshAttributeData{Trade::MeshAttribute::TextureCoordinates, vertices.slice(&Vertex::textureCoordinates2)}, Trade::MeshAttributeData{Trade::MeshAttribute::TextureCoordinates, vertices.slice(&Vertex::textureCoordinates2)},
}}; }};
CORRADE_IGNORE_DEPRECATED_PUSH
Trade::MeshData filtered = filterExceptAttributes(mesh, { Trade::MeshData filtered = filterExceptAttributes(mesh, {
/* The attribute 1 is specified twice, but that won't result in /* The attribute 1 is specified twice, but that won't result in
attribute 1 being removed and then again */ attribute 1 being removed and then again */
1, 1, 3 1, 1, 3
}); });
CORRADE_IGNORE_DEPRECATED_POP
CORRADE_COMPARE(filtered.primitive(), MeshPrimitive::TriangleStrip); CORRADE_COMPARE(filtered.primitive(), MeshPrimitive::TriangleStrip);
CORRADE_VERIFY(filtered.isIndexed()); CORRADE_VERIFY(filtered.isIndexed());
@ -488,7 +623,7 @@ void FilterAttributesTest::filterExceptAttributeIds() {
CORRADE_VERIFY(!attributeData.deleter()); CORRADE_VERIFY(!attributeData.deleter());
} }
void FilterAttributesTest::filterExceptAttributeIdsOutOfBounds() { void FilterTest::exceptAttributeIdsOutOfBounds() {
CORRADE_SKIP_IF_NO_ASSERT(); CORRADE_SKIP_IF_NO_ASSERT();
/* GCC 4.8 dies if I try to initialize this with a {}. I won't, then. */ /* GCC 4.8 dies if I try to initialize this with a {}. I won't, then. */
@ -502,11 +637,13 @@ void FilterAttributesTest::filterExceptAttributeIdsOutOfBounds() {
std::ostringstream out; std::ostringstream out;
Error redirectError{&out}; Error redirectError{&out};
CORRADE_IGNORE_DEPRECATED_PUSH
filterExceptAttributes(mesh, {0, 0, 2}); filterExceptAttributes(mesh, {0, 0, 2});
CORRADE_IGNORE_DEPRECATED_POP
CORRADE_COMPARE(out.str(), "MeshTools::filterExceptAttributes(): index 2 out of range for 2 attributes\n"); CORRADE_COMPARE(out.str(), "MeshTools::filterExceptAttributes(): index 2 out of range for 2 attributes\n");
} }
void FilterAttributesTest::filterExceptAttributeIdsNoIndexData() { void FilterTest::exceptAttributeIdsNoIndexData() {
/* A trivial subset of filterExceptAttributeIds() testing it doesn't blow up /* A trivial subset of filterExceptAttributeIds() testing it doesn't blow up
if the mesh is not indexed */ if the mesh is not indexed */
@ -519,9 +656,11 @@ void FilterAttributesTest::filterExceptAttributeIdsNoIndexData() {
Trade::MeshAttributeData{Trade::MeshAttribute::TextureCoordinates, vertices.slice(&Vertex::textureCoordinates1)} Trade::MeshAttributeData{Trade::MeshAttribute::TextureCoordinates, vertices.slice(&Vertex::textureCoordinates1)}
}}; }};
CORRADE_IGNORE_DEPRECATED_PUSH
Trade::MeshData filtered = filterExceptAttributes(mesh, { Trade::MeshData filtered = filterExceptAttributes(mesh, {
0 0
}); });
CORRADE_IGNORE_DEPRECATED_POP
CORRADE_COMPARE(filtered.primitive(), MeshPrimitive::TriangleFan); CORRADE_COMPARE(filtered.primitive(), MeshPrimitive::TriangleFan);
CORRADE_VERIFY(!filtered.isIndexed()); CORRADE_VERIFY(!filtered.isIndexed());
@ -539,14 +678,16 @@ void FilterAttributesTest::filterExceptAttributeIdsNoIndexData() {
CORRADE_COMPARE(filtered.attributeOffset(0), offsetof(Vertex, textureCoordinates1)); CORRADE_COMPARE(filtered.attributeOffset(0), offsetof(Vertex, textureCoordinates1));
} }
void FilterAttributesTest::filterExceptAttributeIdsNoAttributeData() { void FilterTest::exceptAttributeIdsNoAttributeData() {
Containers::Array<char> indexData{5*sizeof(UnsignedShort)}; Containers::Array<char> indexData{5*sizeof(UnsignedShort)};
Containers::StridedArrayView1D<UnsignedShort> indices = Containers::arrayCast<UnsignedShort>(indexData); Containers::StridedArrayView1D<UnsignedShort> indices = Containers::arrayCast<UnsignedShort>(indexData);
Trade::MeshData mesh{MeshPrimitive::Points, Trade::MeshData mesh{MeshPrimitive::Points,
std::move(indexData), Trade::MeshIndexData{indices}, 15}; std::move(indexData), Trade::MeshIndexData{indices}, 15};
CORRADE_IGNORE_DEPRECATED_PUSH
Trade::MeshData filtered = filterExceptAttributes(mesh, std::initializer_list<UnsignedInt>{}); Trade::MeshData filtered = filterExceptAttributes(mesh, std::initializer_list<UnsignedInt>{});
CORRADE_IGNORE_DEPRECATED_POP
CORRADE_COMPARE(filtered.primitive(), MeshPrimitive::Points); CORRADE_COMPARE(filtered.primitive(), MeshPrimitive::Points);
CORRADE_VERIFY(filtered.isIndexed()); CORRADE_VERIFY(filtered.isIndexed());
@ -562,7 +703,8 @@ void FilterAttributesTest::filterExceptAttributeIdsNoAttributeData() {
CORRADE_COMPARE(filtered.attributeCount(), 0); CORRADE_COMPARE(filtered.attributeCount(), 0);
} }
#endif
}}}} }}}}
CORRADE_TEST_MAIN(Magnum::MeshTools::Test::FilterAttributesTest) CORRADE_TEST_MAIN(Magnum::MeshTools::Test::FilterTest)
Loading…
Cancel
Save