diff --git a/src/Magnum/Trade/MeshData.cpp b/src/Magnum/Trade/MeshData.cpp index ed68f5443..3841e56a6 100644 --- a/src/Magnum/Trade/MeshData.cpp +++ b/src/Magnum/Trade/MeshData.cpp @@ -40,23 +40,13 @@ MeshIndexData::MeshIndexData(const MeshIndexType type, const Containers::ArrayVi "Trade::MeshIndexData: view size" << data.size() << "does not correspond to" << type, ); } -MeshAttributeData::MeshAttributeData(const MeshAttribute name, const VertexFormat format, const Containers::StridedArrayView1D& data) noexcept: name{name}, format{format}, data{data} { +MeshAttributeData::MeshAttributeData(const MeshAttribute name, const VertexFormat format, const Containers::StridedArrayView1D& data) noexcept: MeshAttributeData{name, format, data, nullptr} { + /* Yes, this calls into a constexpr function defined in the header -- + because I feel that makes more sense than duplicating the full assert + logic */ /** @todo support zero / negative stride? would be hard to transfer to GL */ CORRADE_ASSERT(data.empty() || std::ptrdiff_t(vertexFormatSize(format)) <= data.stride(), "Trade::MeshAttributeData: view stride" << data.stride() << "is not large enough to contain" << format, ); - CORRADE_ASSERT( - (name == MeshAttribute::Position && - (format == VertexFormat::Vector2 || - format == VertexFormat::Vector3)) || - (name == MeshAttribute::Normal && - (format == VertexFormat::Vector3)) || - (name == MeshAttribute::Color && - (format == VertexFormat::Vector3 || - format == VertexFormat::Vector4)) || - (name == MeshAttribute::TextureCoordinates && - (format == VertexFormat::Vector2)) || - isMeshAttributeCustom(name) /* can be any format */, - "Trade::MeshAttributeData:" << format << "is not a valid format for" << name, ); } Containers::Array meshAttributeDataNonOwningArray(const Containers::ArrayView view) { @@ -88,10 +78,11 @@ MeshData::MeshData(const MeshPrimitive primitive, Containers::Array&& inde constructors */ for(std::size_t i = 0; i != _attributes.size(); ++i) { const MeshAttributeData& attribute = _attributes[i]; - CORRADE_ASSERT(attribute.data.size() == _vertexCount, - "Trade::MeshData: attribute" << i << "has" << attribute.data.size() << "vertices but" << _vertexCount << "expected", ); - CORRADE_ASSERT(attribute.data.empty() || (&attribute.data.front() >= _vertexData.begin() && &attribute.data.back() + vertexFormatSize(attribute.format) <= _vertexData.end()), - "Trade::MeshData: attribute" << i << "[" << Debug::nospace << static_cast(&attribute.data.front()) << Debug::nospace << ":" << Debug::nospace << static_cast(&attribute.data.back() + vertexFormatSize(attribute.format)) << Debug::nospace << "] is not contained in passed vertexData array [" << Debug::nospace << static_cast(_vertexData.begin()) << Debug::nospace << ":" << Debug::nospace << static_cast(_vertexData.end()) << Debug::nospace << "]", ); + const Containers::StridedArrayView1D data = Containers::arrayCast(attribute.data); + CORRADE_ASSERT(data.size() == _vertexCount, + "Trade::MeshData: attribute" << i << "has" << data.size() << "vertices but" << _vertexCount << "expected", ); + CORRADE_ASSERT(data.empty() || (&data.front() >= _vertexData.begin() && &data.back() + vertexFormatSize(attribute.format) <= _vertexData.end()), + "Trade::MeshData: attribute" << i << "[" << Debug::nospace << static_cast(&data.front()) << Debug::nospace << ":" << Debug::nospace << static_cast(&data.back() + vertexFormatSize(attribute.format)) << Debug::nospace << "] is not contained in passed vertexData array [" << Debug::nospace << static_cast(_vertexData.begin()) << Debug::nospace << ":" << Debug::nospace << static_cast(_vertexData.end()) << Debug::nospace << "]", ); } #endif } diff --git a/src/Magnum/Trade/MeshData.h b/src/Magnum/Trade/MeshData.h index 1df7d111c..b69ca987e 100644 --- a/src/Magnum/Trade/MeshData.h +++ b/src/Magnum/Trade/MeshData.h @@ -216,7 +216,7 @@ class MAGNUM_TRADE_EXPORT MeshAttributeData { * initialization of the attribute array for @ref MeshData, expected to * be replaced with concrete values later. */ - explicit MeshAttributeData() noexcept: name{}, format{}, data{} {} + constexpr explicit MeshAttributeData() noexcept: name{}, format{}, data{} {} /** * @brief Type-erased constructor @@ -227,7 +227,7 @@ class MAGNUM_TRADE_EXPORT MeshAttributeData { * Expects that @p data stride is large enough to fit @p type and that * @p type corresponds to @p name. */ - explicit MeshAttributeData(MeshAttribute name, VertexFormat format, const Containers::StridedArrayView1D& data) noexcept; + explicit MeshAttributeData(MeshAttribute name, VertexFormat format, const Containers::StridedArrayView1D& data) noexcept; /** * @brief Constructor @@ -237,18 +237,20 @@ class MAGNUM_TRADE_EXPORT MeshAttributeData { * Detects @ref VertexFormat based on @p T and calls * @ref MeshAttributeData(MeshAttribute, VertexFormat, const Containers::StridedArrayView1D&). */ - template explicit MeshAttributeData(MeshAttribute name, const Containers::StridedArrayView1D& data) noexcept; + template constexpr explicit MeshAttributeData(MeshAttribute name, const Containers::StridedArrayView1D& data) noexcept; /** @overload */ - template explicit MeshAttributeData(MeshAttribute name, const Containers::ArrayView& data) noexcept: MeshAttributeData{name, Containers::stridedArrayView(data)} {} + template constexpr explicit MeshAttributeData(MeshAttribute name, const Containers::ArrayView& data) noexcept: MeshAttributeData{name, Containers::stridedArrayView(data)} {} private: + constexpr explicit MeshAttributeData(MeshAttribute name, VertexFormat format, const Containers::StridedArrayView1D& data, std::nullptr_t) noexcept; + /* Not prefixed with _ because we use them like public in MeshData */ friend MeshData; MeshAttribute name; /* Here's some room for flags */ VertexFormat format; - Containers::StridedArrayView1D data; + Containers::StridedArrayView1D data; }; /** @relatesalso MeshAttributeData @@ -1027,7 +1029,23 @@ namespace Implementation { constexpr MeshIndexData::MeshIndexData(MeshIndexType type, Containers::ArrayView data, std::nullptr_t): type{type}, data{(CORRADE_CONSTEXPR_ASSERT(!data.empty(), "Trade::MeshIndexData: index array can't be empty, create a non-indexed mesh instead"), data)} {} -template MeshAttributeData::MeshAttributeData(MeshAttribute name, const Containers::StridedArrayView1D& data) noexcept: MeshAttributeData{name, Implementation::vertexFormatFor::type>(), Containers::arrayCast(data)} {} +constexpr MeshAttributeData::MeshAttributeData(const MeshAttribute name, const VertexFormat format, const Containers::StridedArrayView1D& data, std::nullptr_t) noexcept: + name{name}, format{format}, data{(CORRADE_CONSTEXPR_ASSERT( + (name == MeshAttribute::Position && + (format == VertexFormat::Vector2 || + format == VertexFormat::Vector3)) || + (name == MeshAttribute::Normal && + (format == VertexFormat::Vector3)) || + (name == MeshAttribute::Color && + (format == VertexFormat::Vector3 || + format == VertexFormat::Vector4)) || + (name == MeshAttribute::TextureCoordinates && + (format == VertexFormat::Vector2)) || + isMeshAttributeCustom(name) /* can be any format */, + "Trade::MeshAttributeData:" << format << "is not a valid format for" << name), data)} + {} + +template constexpr MeshAttributeData::MeshAttributeData(MeshAttribute name, const Containers::StridedArrayView1D& data) noexcept: MeshAttributeData{name, Implementation::vertexFormatFor::type>(), data, nullptr} {} template Containers::ArrayView MeshData::indices() const { CORRADE_ASSERT(isIndexed(), diff --git a/src/Magnum/Trade/Test/MeshDataTest.cpp b/src/Magnum/Trade/Test/MeshDataTest.cpp index bce1be59b..3741e020b 100644 --- a/src/Magnum/Trade/Test/MeshDataTest.cpp +++ b/src/Magnum/Trade/Test/MeshDataTest.cpp @@ -330,6 +330,12 @@ void MeshDataTest::constructIndexTypeErasedWrongSize() { CORRADE_COMPARE(out.str(), "Trade::MeshIndexData: view size 6 does not correspond to MeshIndexType::UnsignedInt\n"); } +constexpr Vector2 Positions[] { + {1.2f, 0.2f}, + {2.2f, 1.1f}, + {-0.2f, 7.2f} +}; + void MeshDataTest::constructAttribute() { Containers::Array positionData{3*sizeof(Vector2)}; auto positionView = Containers::arrayCast(positionData); @@ -340,6 +346,13 @@ void MeshDataTest::constructAttribute() { CORRADE_COMPARE(data.attributeFormat(0), VertexFormat::Vector2); CORRADE_COMPARE(static_cast(data.attribute(0).data()), positionView.data()); + + constexpr MeshAttributeData cpositions{MeshAttribute::Position, Containers::arrayView(Positions)}; + MeshData cdata{MeshPrimitive::Points, {}, Positions, {cpositions}}; + CORRADE_COMPARE(cdata.attributeName(0), MeshAttribute::Position); + CORRADE_COMPARE(cdata.attributeFormat(0), VertexFormat::Vector2); + CORRADE_COMPARE(static_cast(cdata.attribute(0).data()), + Positions); } void MeshDataTest::constructAttributeCustom() {