Browse Source

Trade: typeless access to MeshData indices.

Like with attributes, it returns a 2D strided view with the second
dimension having the same size as the index type.
pull/371/head
Vladimír Vondruš 6 years ago
parent
commit
506740f9c8
  1. 34
      src/Magnum/Trade/MeshData.cpp
  2. 51
      src/Magnum/Trade/MeshData.h
  3. 62
      src/Magnum/Trade/Test/MeshDataTest.cpp

34
src/Magnum/Trade/MeshData.cpp

@ -40,6 +40,16 @@ MeshIndexData::MeshIndexData(const MeshIndexType type, const Containers::ArrayVi
"Trade::MeshIndexData: view size" << data.size() << "does not correspond to" << type, ); "Trade::MeshIndexData: view size" << data.size() << "does not correspond to" << type, );
} }
MeshIndexData::MeshIndexData(const Containers::StridedArrayView2D<const char>& data) noexcept {
if(data.size()[1] == 4) _type = MeshIndexType::UnsignedInt;
else if(data.size()[1] == 2) _type = MeshIndexType::UnsignedShort;
else if(data.size()[1] == 1) _type = MeshIndexType::UnsignedByte;
else CORRADE_ASSERT(false, "Trade::MeshIndexData: expected index type size 1, 2 or 4 but got" << data.size()[1], );
CORRADE_ASSERT(data.isContiguous(), "Trade::MeshIndexData: view is not contiguous", );
_data = data.asContiguous();
}
MeshAttributeData::MeshAttributeData(const MeshAttribute name, const VertexFormat format, const Containers::StridedArrayView1D<const void>& data) noexcept: MeshAttributeData{name, format, data, nullptr} { MeshAttributeData::MeshAttributeData(const MeshAttribute name, const VertexFormat format, const Containers::StridedArrayView1D<const void>& data) noexcept: MeshAttributeData{name, format, data, nullptr} {
/* Yes, this calls into a constexpr function defined in the header -- /* Yes, this calls into a constexpr function defined in the header --
because I feel that makes more sense than duplicating the full assert because I feel that makes more sense than duplicating the full assert
@ -181,6 +191,30 @@ MeshIndexType MeshData::indexType() const {
return _indexType; return _indexType;
} }
Containers::StridedArrayView2D<const char> MeshData::indices() const {
CORRADE_ASSERT(isIndexed(),
"Trade::MeshData::indices(): the mesh is not indexed", {});
const std::size_t indexTypeSize = meshIndexTypeSize(_indexType);
/* Build a 2D view using information about attribute type size */
return {_indices, {_indices.size()/indexTypeSize, indexTypeSize}};
}
Containers::StridedArrayView2D<char> MeshData::mutableIndices() {
CORRADE_ASSERT(_indexDataFlags & DataFlag::Mutable,
"Trade::MeshData::mutableIndices(): index data not mutable", {});
CORRADE_ASSERT(isIndexed(),
"Trade::MeshData::mutableIndices(): the mesh is not indexed", {});
const std::size_t indexTypeSize = meshIndexTypeSize(_indexType);
/* Build a 2D view using information about attribute type size */
Containers::StridedArrayView2D<const char> out{_indices, {_indices.size()/indexTypeSize, indexTypeSize}};
/** @todo some arrayConstCast? UGH */
return Containers::StridedArrayView2D<char>{
/* The view size is there only for a size assert, we're pretty sure the
view is valid */
{static_cast<char*>(const_cast<void*>(out.data())), ~std::size_t{}},
out.size(), out.stride()};
}
MeshAttribute MeshData::attributeName(UnsignedInt id) const { MeshAttribute MeshData::attributeName(UnsignedInt id) const {
CORRADE_ASSERT(id < _attributes.size(), CORRADE_ASSERT(id < _attributes.size(),
"Trade::MeshData::attributeName(): index" << id << "out of range for" << _attributes.size() << "attributes", {}); "Trade::MeshData::attributeName(): index" << id << "out of range for" << _attributes.size() << "attributes", {});

51
src/Magnum/Trade/MeshData.h

@ -159,7 +159,7 @@ introduction.
class MAGNUM_TRADE_EXPORT MeshIndexData { class MAGNUM_TRADE_EXPORT MeshIndexData {
public: public:
/** @brief Construct for a non-indexed mesh */ /** @brief Construct for a non-indexed mesh */
explicit MeshIndexData() noexcept: _type{} {} explicit MeshIndexData(std::nullptr_t = nullptr) noexcept: _type{} {}
/** /**
* @brief Construct with a runtime-specified index type * @brief Construct with a runtime-specified index type
@ -185,6 +185,15 @@ class MAGNUM_TRADE_EXPORT MeshIndexData {
/** @brief Construct with unsigned int indices */ /** @brief Construct with unsigned int indices */
constexpr explicit MeshIndexData(Containers::ArrayView<const UnsignedInt> data) noexcept: MeshIndexData{MeshIndexType::UnsignedInt, data, nullptr} {} constexpr explicit MeshIndexData(Containers::ArrayView<const UnsignedInt> data) noexcept: MeshIndexData{MeshIndexType::UnsignedInt, data, nullptr} {}
/**
* @brief Constructor
*
* Expects that @p data is contiguous and size of the second dimension
* is either 1, 2 or 4, corresponding to one of the @ref MeshIndexType
* values.
*/
explicit MeshIndexData(const Containers::StridedArrayView2D<const char>& data) noexcept;
/** @brief Index type */ /** @brief Index type */
constexpr MeshIndexType type() const { return _type; } constexpr MeshIndexType type() const { return _type; }
@ -675,6 +684,26 @@ class MAGNUM_TRADE_EXPORT MeshData {
/** /**
* @brief Mesh indices * @brief Mesh indices
* *
* The view is guaranteed to be contiguous and its second dimension
* represents the actual data type (its size is equal to type size).
* Use the templated overload below to get the indices in a concrete
* type.
* @see @ref Corrade::Containers::StridedArrayView::isContiguous()
*/
Containers::StridedArrayView2D<const char> indices() const;
/**
* @brief Mutable mesh indices
*
* Like @ref indices() const, but returns a mutable view. Expects that
* the mesh is mutable.
* @see @ref indexDataFlags()
*/
Containers::StridedArrayView2D<char> mutableIndices();
/**
* @brief Mesh indices in a concrete type
*
* Expects that the mesh is indexed and that @p T corresponds to * Expects that the mesh is indexed and that @p T corresponds to
* @ref indexType(). You can also use the non-templated * @ref indexType(). You can also use the non-templated
* @ref indicesAsArray() accessor to get indices converted to 32-bit, * @ref indicesAsArray() accessor to get indices converted to 32-bit,
@ -685,7 +714,7 @@ class MAGNUM_TRADE_EXPORT MeshData {
template<class T> Containers::ArrayView<const T> indices() const; template<class T> Containers::ArrayView<const T> indices() const;
/** /**
* @brief Mutable mesh indices * @brief Mutable mesh indices in a concrete type
* *
* Like @ref indices() const, but returns a mutable view. Expects that * Like @ref indices() const, but returns a mutable view. Expects that
* the mesh is mutable. * the mesh is mutable.
@ -1140,21 +1169,23 @@ constexpr MeshAttributeData::MeshAttributeData(const MeshAttribute name, const V
template<class T> constexpr MeshAttributeData::MeshAttributeData(MeshAttribute name, const Containers::StridedArrayView1D<T>& data) noexcept: MeshAttributeData{name, Implementation::vertexFormatFor<typename std::remove_const<T>::type>(), data, nullptr} {} template<class T> constexpr MeshAttributeData::MeshAttributeData(MeshAttribute name, const Containers::StridedArrayView1D<T>& data) noexcept: MeshAttributeData{name, Implementation::vertexFormatFor<typename std::remove_const<T>::type>(), data, nullptr} {}
template<class T> Containers::ArrayView<const T> MeshData::indices() const { template<class T> Containers::ArrayView<const T> MeshData::indices() const {
CORRADE_ASSERT(isIndexed(), Containers::StridedArrayView2D<const char> data = indices();
"Trade::MeshData::indices(): the mesh is not indexed", {}); #ifdef CORRADE_GRACEFUL_ASSERT /* Sigh. Brittle. Better idea? */
if(!data.stride()[1]) return {};
#endif
CORRADE_ASSERT(Implementation::meshIndexTypeFor<T>() == _indexType, CORRADE_ASSERT(Implementation::meshIndexTypeFor<T>() == _indexType,
"Trade::MeshData::indices(): improper type requested for" << _indexType, nullptr); "Trade::MeshData::indices(): improper type requested for" << _indexType, nullptr);
return Containers::arrayCast<const T>(_indices); return Containers::arrayCast<1, const T>(data).asContiguous();
} }
template<class T> Containers::ArrayView<T> MeshData::mutableIndices() { template<class T> Containers::ArrayView<T> MeshData::mutableIndices() {
CORRADE_ASSERT(_indexDataFlags & DataFlag::Mutable, Containers::StridedArrayView2D<char> data = mutableIndices();
"Trade::MeshData::mutableIndices(): index data not mutable", {}); #ifdef CORRADE_GRACEFUL_ASSERT /* Sigh. Brittle. Better idea? */
CORRADE_ASSERT(isIndexed(), if(!data.stride()[1]) return {};
"Trade::MeshData::mutableIndices(): the mesh is not indexed", {}); #endif
CORRADE_ASSERT(Implementation::meshIndexTypeFor<T>() == _indexType, CORRADE_ASSERT(Implementation::meshIndexTypeFor<T>() == _indexType,
"Trade::MeshData::mutableIndices(): improper type requested for" << _indexType, nullptr); "Trade::MeshData::mutableIndices(): improper type requested for" << _indexType, nullptr);
return Containers::arrayCast<T>(reinterpret_cast<Containers::ArrayView<char>&>(_indices)); return Containers::arrayCast<1, T>(data).asContiguous();
} }
template<class T> Containers::StridedArrayView1D<const T> MeshData::attribute(UnsignedInt id) const { template<class T> Containers::StridedArrayView1D<const T> MeshData::attribute(UnsignedInt id) const {

62
src/Magnum/Trade/Test/MeshDataTest.cpp

@ -45,6 +45,10 @@ struct MeshDataTest: TestSuite::Tester {
void constructIndexZeroCount(); void constructIndexZeroCount();
void constructIndexTypeErased(); void constructIndexTypeErased();
void constructIndexTypeErasedWrongSize(); void constructIndexTypeErasedWrongSize();
void constructIndex2D();
void constructIndex2DWrongSize();
void constructIndex2DNonContiguous();
void constructIndexNullptr();
void constructAttribute(); void constructAttribute();
void constructAttributeCustom(); void constructAttributeCustom();
@ -142,6 +146,10 @@ MeshDataTest::MeshDataTest() {
&MeshDataTest::constructIndexZeroCount, &MeshDataTest::constructIndexZeroCount,
&MeshDataTest::constructIndexTypeErased, &MeshDataTest::constructIndexTypeErased,
&MeshDataTest::constructIndexTypeErasedWrongSize, &MeshDataTest::constructIndexTypeErasedWrongSize,
&MeshDataTest::constructIndex2D,
&MeshDataTest::constructIndex2DWrongSize,
&MeshDataTest::constructIndex2DNonContiguous,
&MeshDataTest::constructIndexNullptr,
&MeshDataTest::constructAttribute, &MeshDataTest::constructAttribute,
&MeshDataTest::constructAttributeCustom, &MeshDataTest::constructAttributeCustom,
@ -326,6 +334,49 @@ void MeshDataTest::constructIndexTypeErasedWrongSize() {
CORRADE_COMPARE(out.str(), "Trade::MeshIndexData: view size 6 does not correspond to MeshIndexType::UnsignedInt\n"); CORRADE_COMPARE(out.str(), "Trade::MeshIndexData: view size 6 does not correspond to MeshIndexType::UnsignedInt\n");
} }
void MeshDataTest::constructIndex2D() {
{
const UnsignedByte indexData[]{25, 132, 3};
MeshIndexData indices{Containers::arrayCast<2, const char>(Containers::stridedArrayView(indexData))};
CORRADE_COMPARE(indices.type(), MeshIndexType::UnsignedByte);
CORRADE_COMPARE(indices.data().data(), indexData);
} {
const UnsignedShort indexData[]{2575, 13224, 3};
MeshIndexData indices{Containers::arrayCast<2, const char>(Containers::stridedArrayView(indexData))};
CORRADE_COMPARE(indices.type(), MeshIndexType::UnsignedShort);
CORRADE_COMPARE(indices.data().data(), indexData);
} {
const UnsignedInt indexData[]{2110122, 132257, 3};
MeshIndexData indices{Containers::arrayCast<2, const char>(Containers::stridedArrayView(indexData))};
CORRADE_COMPARE(indices.type(), MeshIndexType::UnsignedInt);
CORRADE_COMPARE(indices.data().data(), indexData);
}
}
void MeshDataTest::constructIndex2DWrongSize() {
const char data[3*3]{};
std::ostringstream out;
Error redirectError{&out};
MeshIndexData{Containers::StridedArrayView2D<const char>{data, {3, 3}}};
CORRADE_COMPARE(out.str(), "Trade::MeshIndexData: expected index type size 1, 2 or 4 but got 3\n");
}
void MeshDataTest::constructIndex2DNonContiguous() {
const char data[3*4]{};
std::ostringstream out;
Error redirectError{&out};
MeshIndexData{Containers::StridedArrayView2D<const char>{data, {3, 2}, {4, 2}}};
CORRADE_COMPARE(out.str(), "Trade::MeshIndexData: view is not contiguous\n");
}
void MeshDataTest::constructIndexNullptr() {
/* Just verify it's not ambiguous */
MeshIndexData data{nullptr};
CORRADE_VERIFY(!data.data());
}
constexpr Vector2 Positions[] { constexpr Vector2 Positions[] {
{1.2f, 0.2f}, {1.2f, 0.2f},
{2.2f, 1.1f}, {2.2f, 1.1f},
@ -500,6 +551,13 @@ void MeshDataTest::construct() {
CORRADE_VERIFY(data.isIndexed()); CORRADE_VERIFY(data.isIndexed());
CORRADE_COMPARE(data.indexCount(), 6); CORRADE_COMPARE(data.indexCount(), 6);
CORRADE_COMPARE(data.indexType(), MeshIndexType::UnsignedShort); CORRADE_COMPARE(data.indexType(), MeshIndexType::UnsignedShort);
/* Typeless index access with a cast later */
CORRADE_COMPARE((Containers::arrayCast<1, const UnsignedShort>(data.indices())[1]), 1);
CORRADE_COMPARE((Containers::arrayCast<1, const UnsignedShort>(data.indices())[3]), 0);
CORRADE_COMPARE((Containers::arrayCast<1, const UnsignedShort>(data.indices())[4]), 2);
/* Typed index access */
CORRADE_COMPARE(data.indices<UnsignedShort>()[0], 0); CORRADE_COMPARE(data.indices<UnsignedShort>()[0], 0);
CORRADE_COMPARE(data.indices<UnsignedShort>()[2], 2); CORRADE_COMPARE(data.indices<UnsignedShort>()[2], 2);
CORRADE_COMPARE(data.indices<UnsignedShort>()[5], 1); CORRADE_COMPARE(data.indices<UnsignedShort>()[5], 1);
@ -1374,6 +1432,7 @@ void MeshDataTest::mutableAccessNotAllowed() {
Error redirectError{&out}; Error redirectError{&out};
data.mutableIndexData(); data.mutableIndexData();
data.mutableVertexData(); data.mutableVertexData();
data.mutableIndices();
data.mutableIndices<UnsignedShort>(); data.mutableIndices<UnsignedShort>();
data.mutableAttribute(0); data.mutableAttribute(0);
data.mutableAttribute<Vector2>(0); data.mutableAttribute<Vector2>(0);
@ -1383,6 +1442,7 @@ void MeshDataTest::mutableAccessNotAllowed() {
"Trade::MeshData::mutableIndexData(): index data not mutable\n" "Trade::MeshData::mutableIndexData(): index data not mutable\n"
"Trade::MeshData::mutableVertexData(): vertex data not mutable\n" "Trade::MeshData::mutableVertexData(): vertex data not mutable\n"
"Trade::MeshData::mutableIndices(): index data not mutable\n" "Trade::MeshData::mutableIndices(): index data not mutable\n"
"Trade::MeshData::mutableIndices(): index data not mutable\n"
"Trade::MeshData::mutableAttribute(): vertex data not mutable\n" "Trade::MeshData::mutableAttribute(): vertex data not mutable\n"
"Trade::MeshData::mutableAttribute(): vertex data not mutable\n" "Trade::MeshData::mutableAttribute(): vertex data not mutable\n"
"Trade::MeshData::mutableAttribute(): vertex data not mutable\n" "Trade::MeshData::mutableAttribute(): vertex data not mutable\n"
@ -1396,6 +1456,7 @@ void MeshDataTest::indicesNotIndexed() {
Error redirectError{&out}; Error redirectError{&out};
data.indexCount(); data.indexCount();
data.indexType(); data.indexType();
data.indices();
data.indices<UnsignedInt>(); data.indices<UnsignedInt>();
data.indicesAsArray(); data.indicesAsArray();
UnsignedInt a[1]; UnsignedInt a[1];
@ -1404,6 +1465,7 @@ void MeshDataTest::indicesNotIndexed() {
"Trade::MeshData::indexCount(): the mesh is not indexed\n" "Trade::MeshData::indexCount(): the mesh is not indexed\n"
"Trade::MeshData::indexType(): the mesh is not indexed\n" "Trade::MeshData::indexType(): the mesh is not indexed\n"
"Trade::MeshData::indices(): the mesh is not indexed\n" "Trade::MeshData::indices(): the mesh is not indexed\n"
"Trade::MeshData::indices(): the mesh is not indexed\n"
"Trade::MeshData::indicesAsArray(): the mesh is not indexed\n" "Trade::MeshData::indicesAsArray(): the mesh is not indexed\n"
"Trade::MeshData::indicesInto(): the mesh is not indexed\n"); "Trade::MeshData::indicesInto(): the mesh is not indexed\n");
} }

Loading…
Cancel
Save