diff --git a/src/Magnum/Primitives/Gradient.cpp b/src/Magnum/Primitives/Gradient.cpp index a4931453b..4e2c961d9 100644 --- a/src/Magnum/Primitives/Gradient.cpp +++ b/src/Magnum/Primitives/Gradient.cpp @@ -32,14 +32,27 @@ namespace Magnum { namespace Primitives { -Trade::MeshData gradient2D(const Vector2& a, const Color4& colorA, const Vector2& b, const Color4& colorB) { - struct Vertex { - Vector2 position; - Color4 color; - }; +namespace { + +struct Vertex2D { + Vector2 position; + Color4 color; +}; + +constexpr Trade::MeshAttributeData Attributes2D[]{ + Trade::MeshAttributeData{Trade::MeshAttribute::Position, + VertexFormat::Vector2, offsetof(Vertex2D, position), + 4, sizeof(Vertex2D)}, + Trade::MeshAttributeData{Trade::MeshAttribute::Color, + VertexFormat::Vector4, offsetof(Vertex2D, color), + 4, sizeof(Vertex2D)}, +}; + +} - Containers::Array vertexData{sizeof(Vertex)*4}; - auto vertices = Containers::arrayCast(vertexData); +Trade::MeshData gradient2D(const Vector2& a, const Color4& colorA, const Vector2& b, const Color4& colorB) { + Containers::Array vertexData{sizeof(Vertex2D)*4}; + auto vertices = Containers::arrayCast(vertexData); vertices[0].position = { 1.0f, -1.0f}; vertices[1].position = { 1.0f, 1.0f}; vertices[2].position = {-1.0f, -1.0f}; @@ -56,14 +69,8 @@ Trade::MeshData gradient2D(const Vector2& a, const Color4& colorA, const Vector2 vertices[i].color = Math::lerp(colorA, colorB, t); } - Trade::MeshAttributeData positions{Trade::MeshAttribute::Position, - Containers::stridedArrayView(vertices, &vertices[0].position, - vertices.size(), sizeof(Vertex))}; - Trade::MeshAttributeData colors{Trade::MeshAttribute::Color, - Containers::stridedArrayView(vertices, &vertices[0].color, - vertices.size(), sizeof(Vertex))}; - return Trade::MeshData{MeshPrimitive::TriangleStrip, - std::move(vertexData), {positions, colors}}; + return Trade::MeshData{MeshPrimitive::TriangleStrip, std::move(vertexData), + Trade::meshAttributeDataNonOwningArray(Attributes2D)}; } Trade::MeshData gradient2DHorizontal(const Color4& colorLeft, const Color4& colorRight) { @@ -74,15 +81,31 @@ Trade::MeshData gradient2DVertical(const Color4& colorBottom, const Color4& colo return Primitives::gradient2D({0.0f, -1.0f}, colorBottom, {0.0f, 1.0f}, colorTop); } +namespace { + +struct Vertex3D { + Vector3 position; + Vector3 normal; + Color4 color; +}; + +constexpr Trade::MeshAttributeData Attributes3D[]{ + Trade::MeshAttributeData{Trade::MeshAttribute::Position, + VertexFormat::Vector3, offsetof(Vertex3D, position), + 4, sizeof(Vertex3D)}, + Trade::MeshAttributeData{Trade::MeshAttribute::Normal, + VertexFormat::Vector3, offsetof(Vertex3D, normal), + 4, sizeof(Vertex3D)}, + Trade::MeshAttributeData{Trade::MeshAttribute::Color, + VertexFormat::Vector4, offsetof(Vertex3D, color), + 4, sizeof(Vertex3D)}, +}; + +} + Trade::MeshData gradient3D(const Vector3& a, const Color4& colorA, const Vector3& b, const Color4& colorB) { - struct Vertex { - Vector3 position; - Vector3 normal; - Color4 color; - }; - - Containers::Array vertexData{sizeof(Vertex)*4}; - auto vertices = Containers::arrayCast(vertexData); + Containers::Array vertexData{sizeof(Vertex3D)*4}; + auto vertices = Containers::arrayCast(vertexData); vertices[0].position = { 1.0f, -1.0f, 0}; vertices[1].position = { 1.0f, 1.0f, 0}; vertices[2].position = {-1.0f, -1.0f, 0}; @@ -103,17 +126,8 @@ Trade::MeshData gradient3D(const Vector3& a, const Color4& colorA, const Vector3 vertices[i].color = Math::lerp(colorA, colorB, t); } - Trade::MeshAttributeData positions{Trade::MeshAttribute::Position, - Containers::stridedArrayView(vertices, &vertices[0].position, - vertices.size(), sizeof(Vertex))}; - Trade::MeshAttributeData normals{Trade::MeshAttribute::Normal, - Containers::stridedArrayView(vertices, &vertices[0].normal, - vertices.size(), sizeof(Vertex))}; - Trade::MeshAttributeData colors{Trade::MeshAttribute::Color, - Containers::stridedArrayView(vertices, &vertices[0].color, - vertices.size(), sizeof(Vertex))}; - return Trade::MeshData{MeshPrimitive::TriangleStrip, - std::move(vertexData), {positions, normals, colors}}; + return Trade::MeshData{MeshPrimitive::TriangleStrip, std::move(vertexData), + Trade::meshAttributeDataNonOwningArray(Attributes3D)}; } Trade::MeshData gradient3DHorizontal(const Color4& colorLeft, const Color4& colorRight) { diff --git a/src/Magnum/Primitives/Line.cpp b/src/Magnum/Primitives/Line.cpp index 37a05460a..c688a9a84 100644 --- a/src/Magnum/Primitives/Line.cpp +++ b/src/Magnum/Primitives/Line.cpp @@ -31,6 +31,15 @@ namespace Magnum { namespace Primitives { +namespace { + +constexpr Trade::MeshAttributeData Attributes2D[]{ + Trade::MeshAttributeData{Trade::MeshAttribute::Position, + VertexFormat::Vector2, 0, 2, sizeof(Vector2)}, +}; + +} + Trade::MeshData line2D(const Vector2& a, const Vector2& b) { Containers::Array vertexData{sizeof(Vector2)*2}; auto positions = Containers::arrayCast(vertexData); @@ -38,7 +47,16 @@ Trade::MeshData line2D(const Vector2& a, const Vector2& b) { positions[1] = b; return Trade::MeshData{MeshPrimitive::Lines, std::move(vertexData), - {Trade::MeshAttributeData{Trade::MeshAttribute::Position, positions}}}; + Trade::meshAttributeDataNonOwningArray(Attributes2D)}; +} + +namespace { + +constexpr Trade::MeshAttributeData Attributes3D[]{ + Trade::MeshAttributeData{Trade::MeshAttribute::Position, + VertexFormat::Vector3, 0, 2, sizeof(Vector3)}, +}; + } Trade::MeshData line3D(const Vector3& a, const Vector3& b) { @@ -48,7 +66,7 @@ Trade::MeshData line3D(const Vector3& a, const Vector3& b) { positions[1] = b; return Trade::MeshData{MeshPrimitive::Lines, std::move(vertexData), - {Trade::MeshAttributeData{Trade::MeshAttribute::Position, positions}}}; + Trade::meshAttributeDataNonOwningArray(Attributes3D)}; } Trade::MeshData line2D() { diff --git a/src/Magnum/Trade/MeshData.cpp b/src/Magnum/Trade/MeshData.cpp index a28ff3a86..e8982ee70 100644 --- a/src/Magnum/Trade/MeshData.cpp +++ b/src/Magnum/Trade/MeshData.cpp @@ -302,12 +302,22 @@ UnsignedInt MeshData::attributeStride(MeshAttribute name, UnsignedInt id) const return attributeStride(attributeId); } +Containers::StridedArrayView1D MeshData::attributeDataViewInternal(const MeshAttributeData& attribute) const { + return Containers::StridedArrayView1D{ + /* We're *sure* the view is correct, so faking the view size */ + /** @todo better ideas for the StridedArrayView API? */ + {attribute._isOffsetOnly ? _vertexData.data() + attribute._data.offset : + attribute._data.pointer, ~std::size_t{}}, + /* Not using attribute._vertexCount because that gets stale after + releaseVertexData() gets called, and then we would need to slice the + result inside attribute() and elsewhere anyway */ + _vertexCount, attribute._stride}; +} + Containers::StridedArrayView2D MeshData::attribute(UnsignedInt id) const { CORRADE_ASSERT(id < _attributes.size(), "Trade::MeshData::attribute(): index" << id << "out of range for" << _attributes.size() << "attributes", nullptr); - /* Build a 2D view using information about attribute type size, return only - a prefix of the actual vertex count (which is zero in case vertex data - is released) */ + /* Build a 2D view using information about attribute type size */ return Containers::arrayCast<2, const char>( attributeDataViewInternal(_attributes[id]), vertexFormatSize(_attributes[id]._format)); @@ -318,9 +328,7 @@ Containers::StridedArrayView2D MeshData::mutableAttribute(UnsignedInt id) "Trade::MeshData::mutableAttribute(): vertex data not mutable", {}); CORRADE_ASSERT(id < _attributes.size(), "Trade::MeshData::mutableAttribute(): index" << id << "out of range for" << _attributes.size() << "attributes", nullptr); - /* Build a 2D view using information about attribute type size, return only - a prefix of the actual vertex count (which is zero in case vertex data - is released) */ + /* Build a 2D view using information about attribute type size */ auto out = Containers::arrayCast<2, const char>( attributeDataViewInternal(_attributes[id]), vertexFormatSize(_attributes[id]._format)); @@ -378,18 +386,6 @@ Containers::Array MeshData::indicesAsArray() const { return output; } -Containers::StridedArrayView1D MeshData::attributeDataViewInternal(const MeshAttributeData& attribute) const { - return Containers::StridedArrayView1D{ - /* We're *sure* the view is correct, so faking the view size */ - /** @todo better ideas for the StridedArrayView API? */ - {attribute._isOffsetOnly ? _vertexData.data() + attribute._data.offset : - attribute._data.pointer, ~std::size_t{}}, - /* Not using attribute._vertexCount because that gets stale after - releaseVertexData() gets called, and then we would need to slice the - result inside attribute() and elsewhere */ - _vertexCount, attribute._stride}; -} - void MeshData::positions2DInto(const Containers::StridedArrayView1D destination, const UnsignedInt id) const { const UnsignedInt attributeId = attributeFor(MeshAttribute::Position, id); CORRADE_ASSERT(attributeId != ~UnsignedInt{}, "Trade::MeshData::positions2DInto(): index" << id << "out of range for" << attributeCount(MeshAttribute::Position) << "position attributes", ); diff --git a/src/Magnum/Trade/Test/MeshDataTest.cpp b/src/Magnum/Trade/Test/MeshDataTest.cpp index 7da715e43..972f2d254 100644 --- a/src/Magnum/Trade/Test/MeshDataTest.cpp +++ b/src/Magnum/Trade/Test/MeshDataTest.cpp @@ -486,6 +486,7 @@ void MeshDataTest::constructAttribute2D() { {4, sizeof(Vector2)}}.every(2); MeshAttributeData positions{MeshAttribute::Position, VertexFormat::Vector2, positionView}; + CORRADE_VERIFY(!positions.isOffsetOnly()); CORRADE_COMPARE(positions.name(), MeshAttribute::Position); CORRADE_COMPARE(positions.format(), VertexFormat::Vector2); CORRADE_COMPARE(positions.data().data(), positionView.data()); @@ -516,6 +517,7 @@ void MeshDataTest::constructAttribute2DNonContiguous() { void MeshDataTest::constructAttributeTypeErased() { const Vector3 positionData[3]{}; MeshAttributeData positions{MeshAttribute::Position, VertexFormat::Vector3, Containers::arrayCast(Containers::stridedArrayView(positionData))}; + CORRADE_VERIFY(!positions.isOffsetOnly()); CORRADE_COMPARE(positions.name(), MeshAttribute::Position); CORRADE_COMPARE(positions.format(), VertexFormat::Vector3); CORRADE_VERIFY(positions.data().data() == positionData); @@ -523,6 +525,7 @@ void MeshDataTest::constructAttributeTypeErased() { void MeshDataTest::constructAttributeNullptr() { MeshAttributeData positions{MeshAttribute::Position, VertexFormat::Vector2, nullptr}; + CORRADE_VERIFY(!positions.isOffsetOnly()); CORRADE_COMPARE(positions.name(), MeshAttribute::Position); CORRADE_COMPARE(positions.format(), VertexFormat::Vector2); CORRADE_VERIFY(!positions.data().data()); @@ -530,6 +533,7 @@ void MeshDataTest::constructAttributeNullptr() { void MeshDataTest::constructAttributePadding() { MeshAttributeData padding{-35}; + CORRADE_VERIFY(!padding.isOffsetOnly()); CORRADE_COMPARE(padding.name(), MeshAttribute{}); CORRADE_COMPARE(padding.format(), VertexFormat{}); CORRADE_COMPARE(padding.data().size(), 0);