diff --git a/src/Magnum/Primitives/Circle.cpp b/src/Magnum/Primitives/Circle.cpp index 61ddb4665..9086eea9b 100644 --- a/src/Magnum/Primitives/Circle.cpp +++ b/src/Magnum/Primitives/Circle.cpp @@ -32,26 +32,39 @@ namespace Magnum { namespace Primitives { +namespace { + +constexpr Trade::MeshAttributeData AttributeData2D[]{ + Trade::MeshAttributeData{Trade::MeshAttribute::Position, VertexFormat::Vector2, + 0, 0, sizeof(Vector2)} +}; + +constexpr Trade::MeshAttributeData AttributeData2DTextureCoords[]{ + Trade::MeshAttributeData{Trade::MeshAttribute::Position, VertexFormat::Vector2, + 0, 0, 2*sizeof(Vector2)}, + Trade::MeshAttributeData{Trade::MeshAttribute::TextureCoordinates, VertexFormat::Vector2, + sizeof(Vector2), 0, 2*sizeof(Vector2)} +}; + +} + Trade::MeshData circle2DSolid(const UnsignedInt segments, const CircleTextureCoords textureCoords) { CORRADE_ASSERT(segments >= 3, "Primitives::circle2DSolid(): segments must be >= 3", (Trade::MeshData{MeshPrimitive::TriangleFan, 0})); /* Allocate interleaved array for all vertex data */ - std::size_t stride = sizeof(Vector2); - std::size_t attributeCount = 1; - if(textureCoords == CircleTextureCoords::Generate) { - ++attributeCount; - stride += sizeof(Vector2); - } + Containers::Array attributes; + if(textureCoords == CircleTextureCoords::Generate) + attributes = Trade::meshAttributeDataNonOwningArray(AttributeData2DTextureCoords); + else + attributes = Trade::meshAttributeDataNonOwningArray(AttributeData2D); + const std::size_t stride = attributes[0].stride(); Containers::Array vertexData{stride*(segments + 2)}; - Containers::Array attributes{attributeCount}; /* Fill positions */ Containers::StridedArrayView1D positions{vertexData, reinterpret_cast(vertexData.begin()), segments + 2, std::ptrdiff_t(stride)}; - attributes[0] = - Trade::MeshAttributeData{Trade::MeshAttribute::Position, positions}; positions[0] = {}; /* Points on the circle. The first/last point is here twice to close the circle properly. */ @@ -67,13 +80,11 @@ Trade::MeshData circle2DSolid(const UnsignedInt segments, const CircleTextureCoo Containers::StridedArrayView1D textureCoords{vertexData, reinterpret_cast(vertexData.begin() + sizeof(Vector2)), positions.size(), std::ptrdiff_t(stride)}; - attributes[1] = - Trade::MeshAttributeData{Trade::MeshAttribute::TextureCoordinates, textureCoords}; for(std::size_t i = 0; i != positions.size(); ++i) textureCoords[i] = positions[i]*0.5f + Vector2{0.5f}; } - return Trade::MeshData{MeshPrimitive::TriangleFan, std::move(vertexData), std::move(attributes)}; + return Trade::MeshData{MeshPrimitive::TriangleFan, std::move(vertexData), std::move(attributes), UnsignedInt(positions.size())}; } Trade::MeshData circle2DWireframe(const UnsignedInt segments) { @@ -91,7 +102,33 @@ Trade::MeshData circle2DWireframe(const UnsignedInt segments) { positions[i] = {sincos.second, sincos.first}; } - return Trade::MeshData{MeshPrimitive::LineLoop, std::move(vertexData), {Trade::MeshAttributeData{Trade::MeshAttribute::Position, positions}}}; + return Trade::MeshData{MeshPrimitive::LineLoop, std::move(vertexData), + Trade::meshAttributeDataNonOwningArray(AttributeData2D), UnsignedInt(positions.size())}; +} + +namespace { + +constexpr Trade::MeshAttributeData AttributeData3D[]{ + Trade::MeshAttributeData{Trade::MeshAttribute::Position, VertexFormat::Vector3, + 0, 0, 2*sizeof(Vector3)}, + Trade::MeshAttributeData{Trade::MeshAttribute::Normal, VertexFormat::Vector3, + sizeof(Vector3), 0, 2*sizeof(Vector3)} +}; + +constexpr Trade::MeshAttributeData AttributeData3DTextureCoords[]{ + Trade::MeshAttributeData{Trade::MeshAttribute::Position, VertexFormat::Vector3, + 0, 0, 2*sizeof(Vector3) + sizeof(Vector2)}, + Trade::MeshAttributeData{Trade::MeshAttribute::Normal, VertexFormat::Vector3, + sizeof(Vector3), 0, 2*sizeof(Vector3) + sizeof(Vector2)}, + Trade::MeshAttributeData{Trade::MeshAttribute::TextureCoordinates, VertexFormat::Vector2, + 2*sizeof(Vector3), 0, 2*sizeof(Vector3) + sizeof(Vector2)} +}; + +constexpr Trade::MeshAttributeData AttributeData3DWireframe[]{ + Trade::MeshAttributeData{Trade::MeshAttribute::Position, VertexFormat::Vector3, + 0, 0, sizeof(Vector3)} +}; + } Trade::MeshData circle3DSolid(const UnsignedInt segments, CircleTextureCoords textureCoords) { @@ -99,21 +136,18 @@ Trade::MeshData circle3DSolid(const UnsignedInt segments, CircleTextureCoords te (Trade::MeshData{MeshPrimitive::TriangleFan, 0})); /* Allocate interleaved array for all vertex data */ - std::size_t stride = 2*sizeof(Vector3); - std::size_t attributeCount = 2; - if(textureCoords == CircleTextureCoords::Generate) { - ++attributeCount; - stride += sizeof(Vector2); - } + Containers::Array attributes; + if(textureCoords == CircleTextureCoords::Generate) + attributes = Trade::meshAttributeDataNonOwningArray(AttributeData3DTextureCoords); + else + attributes = Trade::meshAttributeDataNonOwningArray(AttributeData3D); + const std::size_t stride = attributes[0].stride(); Containers::Array vertexData{stride*(segments + 2)}; - Containers::Array attributes{attributeCount}; /* Fill positions */ Containers::StridedArrayView1D positions{vertexData, reinterpret_cast(vertexData.begin()), segments + 2, std::ptrdiff_t(stride)}; - attributes[0] = - Trade::MeshAttributeData{Trade::MeshAttribute::Position, positions}; positions[0] = {}; /* Points on the circle. The first/last point is here twice to close the circle properly. */ @@ -128,8 +162,6 @@ Trade::MeshData circle3DSolid(const UnsignedInt segments, CircleTextureCoords te Containers::StridedArrayView1D normals{vertexData, reinterpret_cast(vertexData.begin() + sizeof(Vector3)), segments + 2, std::ptrdiff_t(stride)}; - attributes[1] = - Trade::MeshAttributeData{Trade::MeshAttribute::Normal, normals}; for(Vector3& normal: normals) normal = Vector3::zAxis(1.0f); /* Fill texture coords, if any */ @@ -137,13 +169,11 @@ Trade::MeshData circle3DSolid(const UnsignedInt segments, CircleTextureCoords te Containers::StridedArrayView1D textureCoords{vertexData, reinterpret_cast(vertexData.begin() + 2*sizeof(Vector3)), positions.size(), std::ptrdiff_t(stride)}; - attributes[2] = - Trade::MeshAttributeData{Trade::MeshAttribute::TextureCoordinates, textureCoords}; for(std::size_t i = 0; i != positions.size(); ++i) textureCoords[i] = positions[i].xy()*0.5f + Vector2{0.5f}; } - return Trade::MeshData{MeshPrimitive::TriangleFan, std::move(vertexData), std::move(attributes)}; + return Trade::MeshData{MeshPrimitive::TriangleFan, std::move(vertexData), std::move(attributes), UnsignedInt(positions.size())}; } Trade::MeshData circle3DWireframe(const UnsignedInt segments) { @@ -161,7 +191,8 @@ Trade::MeshData circle3DWireframe(const UnsignedInt segments) { positions[i] = {sincos.second, sincos.first, 0.0f}; } - return Trade::MeshData{MeshPrimitive::LineLoop, std::move(vertexData), {Trade::MeshAttributeData{Trade::MeshAttribute::Position, positions}}}; + return Trade::MeshData{MeshPrimitive::LineLoop, std::move(vertexData), + Trade::meshAttributeDataNonOwningArray(AttributeData3DWireframe), UnsignedInt(positions.size())}; } }} diff --git a/src/Magnum/Primitives/Grid.cpp b/src/Magnum/Primitives/Grid.cpp index d85262df8..68f434710 100644 --- a/src/Magnum/Primitives/Grid.cpp +++ b/src/Magnum/Primitives/Grid.cpp @@ -109,11 +109,22 @@ Trade::MeshData grid3DSolid(const Vector2i& subdivisions, const GridFlags flags) textureCoords[i] = positions[i].xy()*0.5f + Vector2{0.5f}; } + /* Not using a compile-time attribute array because there's way too many + combinations */ return Trade::MeshData{MeshPrimitive::Triangles, std::move(indexData), Trade::MeshIndexData{indices}, std::move(vertexData), std::move(attributes)}; } +namespace { + +constexpr Trade::MeshAttributeData AttributeData3DWireframe[]{ + Trade::MeshAttributeData{Trade::MeshAttribute::Position, VertexFormat::Vector3, + 0, 0, sizeof(Vector3)} +}; + +} + Trade::MeshData grid3DWireframe(const Vector2i& subdivisions) { const Vector2i vertexCount = subdivisions + Vector2i{2}; const Vector2i faceCount = subdivisions + Vector2i{1}; @@ -153,7 +164,9 @@ Trade::MeshData grid3DWireframe(const Vector2i& subdivisions) { return Trade::MeshData{MeshPrimitive::Lines, std::move(indexData), Trade::MeshIndexData{indices}, - std::move(vertexData), {Trade::MeshAttributeData{Trade::MeshAttribute::Position, positions}}}; + std::move(vertexData), + Trade::meshAttributeDataNonOwningArray(AttributeData3DWireframe), + UnsignedInt(vertexCount.product())}; } }} diff --git a/src/Magnum/Primitives/Implementation/Spheroid.cpp b/src/Magnum/Primitives/Implementation/Spheroid.cpp index 8c8d31e39..377ce59ca 100644 --- a/src/Magnum/Primitives/Implementation/Spheroid.cpp +++ b/src/Magnum/Primitives/Implementation/Spheroid.cpp @@ -220,37 +220,39 @@ void Spheroid::capVertexRing(Float y, Float textureCoordsV, const Vector3& norma } } -Trade::MeshData Spheroid::finalize() { - Trade::MeshIndexData indices{_indexData}; +namespace { + +constexpr Trade::MeshAttributeData AttributeData[]{ + Trade::MeshAttributeData{Trade::MeshAttribute::Position, VertexFormat::Vector3, + offsetof(Vertex, position), 0, sizeof(Vertex)}, + Trade::MeshAttributeData{Trade::MeshAttribute::Normal, VertexFormat::Vector3, + offsetof(Vertex, normal), 0, sizeof(Vertex)} +}; - const std::size_t stride = _textureCoords == TextureCoords::Generate ? - sizeof(VertexTextureCoords) : sizeof(Vertex); - const std::size_t size = _vertexData.size()/stride; +constexpr Trade::MeshAttributeData AttributeDataTextureCoords[]{ + Trade::MeshAttributeData{Trade::MeshAttribute::Position, VertexFormat::Vector3, + offsetof(VertexTextureCoords, position), 0, sizeof(VertexTextureCoords)}, + Trade::MeshAttributeData{Trade::MeshAttribute::Normal, VertexFormat::Vector3, + offsetof(VertexTextureCoords, normal), 0, sizeof(VertexTextureCoords)}, + Trade::MeshAttributeData{Trade::MeshAttribute::TextureCoordinates, VertexFormat::Vector2, + offsetof(VertexTextureCoords, textureCoords), 0, sizeof(VertexTextureCoords)} +}; - auto typedVertices = reinterpret_cast(_vertexData.data()); - Trade::MeshAttributeData positions{Trade::MeshAttribute::Position, - /* GCC 4.8 needs the arrayView() */ - Containers::stridedArrayView(Containers::arrayView(_vertexData), - &typedVertices[0].position, size, stride)}; - Trade::MeshAttributeData normals{Trade::MeshAttribute::Normal, - /* GCC 4.8 needs the arrayView() */ - Containers::stridedArrayView(Containers::arrayView(_vertexData), - &typedVertices[0].normal, size, stride)}; +} + +Trade::MeshData Spheroid::finalize() { + Trade::MeshIndexData indices{_indexData}; Containers::Array attributes; - if(_textureCoords == TextureCoords::Generate) { - Trade::MeshAttributeData textureCoords{Trade::MeshAttribute::TextureCoordinates, - /* GCC 4.8 needs the arrayView() */ - Containers::stridedArrayView(Containers::arrayView(_vertexData), - &typedVertices[0].textureCoords, size, stride)}; - attributes = Containers::Array{Containers::InPlaceInit, {positions, normals, textureCoords}}; - } else { - attributes = Containers::Array{Containers::InPlaceInit, {positions, normals}}; - } + if(_textureCoords == TextureCoords::Generate) + attributes = Trade::meshAttributeDataNonOwningArray(AttributeDataTextureCoords); + else + attributes = Trade::meshAttributeDataNonOwningArray(AttributeData); + const UnsignedInt vertexCount = _vertexData.size()/attributes[0].stride(); return Trade::MeshData{MeshPrimitive::Triangles, Containers::arrayAllocatorCast(std::move(_indexData)), indices, - std::move(_vertexData), std::move(attributes)}; + std::move(_vertexData), std::move(attributes), vertexCount}; } }}} diff --git a/src/Magnum/Primitives/Implementation/WireframeSpheroid.cpp b/src/Magnum/Primitives/Implementation/WireframeSpheroid.cpp index 6b40ca3aa..29212b416 100644 --- a/src/Magnum/Primitives/Implementation/WireframeSpheroid.cpp +++ b/src/Magnum/Primitives/Implementation/WireframeSpheroid.cpp @@ -124,12 +124,23 @@ void WireframeSpheroid::cylinder() { arrayAppend(_indexData, {UnsignedInt(_vertexData.size()) - 4*_segments + i, UnsignedInt(_vertexData.size()) + i}); } +namespace { + +constexpr Trade::MeshAttributeData AttributeData[]{ + Trade::MeshAttributeData{Trade::MeshAttribute::Position, VertexFormat::Vector3, + 0, 0, sizeof(Vector3)} +}; + +} + Trade::MeshData WireframeSpheroid::finalize() { Trade::MeshIndexData indices{_indexData}; Trade::MeshAttributeData positions{Trade::MeshAttribute::Position, Containers::arrayView(_vertexData)}; + const UnsignedInt vertexCount = _vertexData.size(); return Trade::MeshData{MeshPrimitive::Lines, Containers::arrayAllocatorCast(std::move(_indexData)), indices, - Containers::arrayAllocatorCast(std::move(_vertexData)), {positions}}; + Containers::arrayAllocatorCast(std::move(_vertexData)), + Trade::meshAttributeDataNonOwningArray(AttributeData), vertexCount}; } }}}