Browse Source

Primitives: use compile-time attribute definitions where possible.

Now possible in all cases, except for grid, where the combination count
is too large to be practical, even more so with the introduction of
tangents in the future.
pull/371/head
Vladimír Vondruš 6 years ago
parent
commit
06b82755ad
  1. 87
      src/Magnum/Primitives/Circle.cpp
  2. 15
      src/Magnum/Primitives/Grid.cpp
  3. 50
      src/Magnum/Primitives/Implementation/Spheroid.cpp
  4. 13
      src/Magnum/Primitives/Implementation/WireframeSpheroid.cpp

87
src/Magnum/Primitives/Circle.cpp

@ -32,26 +32,39 @@
namespace Magnum { namespace Primitives { 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) { Trade::MeshData circle2DSolid(const UnsignedInt segments, const CircleTextureCoords textureCoords) {
CORRADE_ASSERT(segments >= 3, "Primitives::circle2DSolid(): segments must be >= 3", CORRADE_ASSERT(segments >= 3, "Primitives::circle2DSolid(): segments must be >= 3",
(Trade::MeshData{MeshPrimitive::TriangleFan, 0})); (Trade::MeshData{MeshPrimitive::TriangleFan, 0}));
/* Allocate interleaved array for all vertex data */ /* Allocate interleaved array for all vertex data */
std::size_t stride = sizeof(Vector2); Containers::Array<Trade::MeshAttributeData> attributes;
std::size_t attributeCount = 1; if(textureCoords == CircleTextureCoords::Generate)
if(textureCoords == CircleTextureCoords::Generate) { attributes = Trade::meshAttributeDataNonOwningArray(AttributeData2DTextureCoords);
++attributeCount; else
stride += sizeof(Vector2); attributes = Trade::meshAttributeDataNonOwningArray(AttributeData2D);
} const std::size_t stride = attributes[0].stride();
Containers::Array<char> vertexData{stride*(segments + 2)}; Containers::Array<char> vertexData{stride*(segments + 2)};
Containers::Array<Trade::MeshAttributeData> attributes{attributeCount};
/* Fill positions */ /* Fill positions */
Containers::StridedArrayView1D<Vector2> positions{vertexData, Containers::StridedArrayView1D<Vector2> positions{vertexData,
reinterpret_cast<Vector2*>(vertexData.begin()), reinterpret_cast<Vector2*>(vertexData.begin()),
segments + 2, std::ptrdiff_t(stride)}; segments + 2, std::ptrdiff_t(stride)};
attributes[0] =
Trade::MeshAttributeData{Trade::MeshAttribute::Position, positions};
positions[0] = {}; positions[0] = {};
/* Points on the circle. The first/last point is here twice to close the /* Points on the circle. The first/last point is here twice to close the
circle properly. */ circle properly. */
@ -67,13 +80,11 @@ Trade::MeshData circle2DSolid(const UnsignedInt segments, const CircleTextureCoo
Containers::StridedArrayView1D<Vector2> textureCoords{vertexData, Containers::StridedArrayView1D<Vector2> textureCoords{vertexData,
reinterpret_cast<Vector2*>(vertexData.begin() + sizeof(Vector2)), reinterpret_cast<Vector2*>(vertexData.begin() + sizeof(Vector2)),
positions.size(), std::ptrdiff_t(stride)}; positions.size(), std::ptrdiff_t(stride)};
attributes[1] =
Trade::MeshAttributeData{Trade::MeshAttribute::TextureCoordinates, textureCoords};
for(std::size_t i = 0; i != positions.size(); ++i) for(std::size_t i = 0; i != positions.size(); ++i)
textureCoords[i] = positions[i]*0.5f + Vector2{0.5f}; 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) { Trade::MeshData circle2DWireframe(const UnsignedInt segments) {
@ -91,7 +102,33 @@ Trade::MeshData circle2DWireframe(const UnsignedInt segments) {
positions[i] = {sincos.second, sincos.first}; 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) { 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})); (Trade::MeshData{MeshPrimitive::TriangleFan, 0}));
/* Allocate interleaved array for all vertex data */ /* Allocate interleaved array for all vertex data */
std::size_t stride = 2*sizeof(Vector3); Containers::Array<Trade::MeshAttributeData> attributes;
std::size_t attributeCount = 2; if(textureCoords == CircleTextureCoords::Generate)
if(textureCoords == CircleTextureCoords::Generate) { attributes = Trade::meshAttributeDataNonOwningArray(AttributeData3DTextureCoords);
++attributeCount; else
stride += sizeof(Vector2); attributes = Trade::meshAttributeDataNonOwningArray(AttributeData3D);
} const std::size_t stride = attributes[0].stride();
Containers::Array<char> vertexData{stride*(segments + 2)}; Containers::Array<char> vertexData{stride*(segments + 2)};
Containers::Array<Trade::MeshAttributeData> attributes{attributeCount};
/* Fill positions */ /* Fill positions */
Containers::StridedArrayView1D<Vector3> positions{vertexData, Containers::StridedArrayView1D<Vector3> positions{vertexData,
reinterpret_cast<Vector3*>(vertexData.begin()), reinterpret_cast<Vector3*>(vertexData.begin()),
segments + 2, std::ptrdiff_t(stride)}; segments + 2, std::ptrdiff_t(stride)};
attributes[0] =
Trade::MeshAttributeData{Trade::MeshAttribute::Position, positions};
positions[0] = {}; positions[0] = {};
/* Points on the circle. The first/last point is here twice to close the /* Points on the circle. The first/last point is here twice to close the
circle properly. */ circle properly. */
@ -128,8 +162,6 @@ Trade::MeshData circle3DSolid(const UnsignedInt segments, CircleTextureCoords te
Containers::StridedArrayView1D<Vector3> normals{vertexData, Containers::StridedArrayView1D<Vector3> normals{vertexData,
reinterpret_cast<Vector3*>(vertexData.begin() + sizeof(Vector3)), reinterpret_cast<Vector3*>(vertexData.begin() + sizeof(Vector3)),
segments + 2, std::ptrdiff_t(stride)}; segments + 2, std::ptrdiff_t(stride)};
attributes[1] =
Trade::MeshAttributeData{Trade::MeshAttribute::Normal, normals};
for(Vector3& normal: normals) normal = Vector3::zAxis(1.0f); for(Vector3& normal: normals) normal = Vector3::zAxis(1.0f);
/* Fill texture coords, if any */ /* Fill texture coords, if any */
@ -137,13 +169,11 @@ Trade::MeshData circle3DSolid(const UnsignedInt segments, CircleTextureCoords te
Containers::StridedArrayView1D<Vector2> textureCoords{vertexData, Containers::StridedArrayView1D<Vector2> textureCoords{vertexData,
reinterpret_cast<Vector2*>(vertexData.begin() + 2*sizeof(Vector3)), reinterpret_cast<Vector2*>(vertexData.begin() + 2*sizeof(Vector3)),
positions.size(), std::ptrdiff_t(stride)}; positions.size(), std::ptrdiff_t(stride)};
attributes[2] =
Trade::MeshAttributeData{Trade::MeshAttribute::TextureCoordinates, textureCoords};
for(std::size_t i = 0; i != positions.size(); ++i) for(std::size_t i = 0; i != positions.size(); ++i)
textureCoords[i] = positions[i].xy()*0.5f + Vector2{0.5f}; 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) { Trade::MeshData circle3DWireframe(const UnsignedInt segments) {
@ -161,7 +191,8 @@ Trade::MeshData circle3DWireframe(const UnsignedInt segments) {
positions[i] = {sincos.second, sincos.first, 0.0f}; 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())};
} }
}} }}

15
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}; 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, return Trade::MeshData{MeshPrimitive::Triangles,
std::move(indexData), Trade::MeshIndexData{indices}, std::move(indexData), Trade::MeshIndexData{indices},
std::move(vertexData), std::move(attributes)}; 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) { Trade::MeshData grid3DWireframe(const Vector2i& subdivisions) {
const Vector2i vertexCount = subdivisions + Vector2i{2}; const Vector2i vertexCount = subdivisions + Vector2i{2};
const Vector2i faceCount = subdivisions + Vector2i{1}; const Vector2i faceCount = subdivisions + Vector2i{1};
@ -153,7 +164,9 @@ Trade::MeshData grid3DWireframe(const Vector2i& subdivisions) {
return Trade::MeshData{MeshPrimitive::Lines, return Trade::MeshData{MeshPrimitive::Lines,
std::move(indexData), Trade::MeshIndexData{indices}, std::move(indexData), Trade::MeshIndexData{indices},
std::move(vertexData), {Trade::MeshAttributeData{Trade::MeshAttribute::Position, positions}}}; std::move(vertexData),
Trade::meshAttributeDataNonOwningArray(AttributeData3DWireframe),
UnsignedInt(vertexCount.product())};
} }
}} }}

50
src/Magnum/Primitives/Implementation/Spheroid.cpp

@ -220,37 +220,39 @@ void Spheroid::capVertexRing(Float y, Float textureCoordsV, const Vector3& norma
} }
} }
Trade::MeshData Spheroid::finalize() { namespace {
Trade::MeshIndexData indices{_indexData};
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 ? constexpr Trade::MeshAttributeData AttributeDataTextureCoords[]{
sizeof(VertexTextureCoords) : sizeof(Vertex); Trade::MeshAttributeData{Trade::MeshAttribute::Position, VertexFormat::Vector3,
const std::size_t size = _vertexData.size()/stride; 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<VertexTextureCoords*>(_vertexData.data()); }
Trade::MeshAttributeData positions{Trade::MeshAttribute::Position,
/* GCC 4.8 needs the arrayView() */ Trade::MeshData Spheroid::finalize() {
Containers::stridedArrayView(Containers::arrayView(_vertexData), Trade::MeshIndexData indices{_indexData};
&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)};
Containers::Array<Trade::MeshAttributeData> attributes; Containers::Array<Trade::MeshAttributeData> attributes;
if(_textureCoords == TextureCoords::Generate) { if(_textureCoords == TextureCoords::Generate)
Trade::MeshAttributeData textureCoords{Trade::MeshAttribute::TextureCoordinates, attributes = Trade::meshAttributeDataNonOwningArray(AttributeDataTextureCoords);
/* GCC 4.8 needs the arrayView() */ else
Containers::stridedArrayView(Containers::arrayView(_vertexData), attributes = Trade::meshAttributeDataNonOwningArray(AttributeData);
&typedVertices[0].textureCoords, size, stride)}; const UnsignedInt vertexCount = _vertexData.size()/attributes[0].stride();
attributes = Containers::Array<Trade::MeshAttributeData>{Containers::InPlaceInit, {positions, normals, textureCoords}};
} else {
attributes = Containers::Array<Trade::MeshAttributeData>{Containers::InPlaceInit, {positions, normals}};
}
return Trade::MeshData{MeshPrimitive::Triangles, return Trade::MeshData{MeshPrimitive::Triangles,
Containers::arrayAllocatorCast<char>(std::move(_indexData)), indices, Containers::arrayAllocatorCast<char>(std::move(_indexData)), indices,
std::move(_vertexData), std::move(attributes)}; std::move(_vertexData), std::move(attributes), vertexCount};
} }
}}} }}}

13
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}); 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::MeshData WireframeSpheroid::finalize() {
Trade::MeshIndexData indices{_indexData}; Trade::MeshIndexData indices{_indexData};
Trade::MeshAttributeData positions{Trade::MeshAttribute::Position, Containers::arrayView(_vertexData)}; Trade::MeshAttributeData positions{Trade::MeshAttribute::Position, Containers::arrayView(_vertexData)};
const UnsignedInt vertexCount = _vertexData.size();
return Trade::MeshData{MeshPrimitive::Lines, return Trade::MeshData{MeshPrimitive::Lines,
Containers::arrayAllocatorCast<char>(std::move(_indexData)), indices, Containers::arrayAllocatorCast<char>(std::move(_indexData)), indices,
Containers::arrayAllocatorCast<char>(std::move(_vertexData)), {positions}}; Containers::arrayAllocatorCast<char>(std::move(_vertexData)),
Trade::meshAttributeDataNonOwningArray(AttributeData), vertexCount};
} }
}}} }}}

Loading…
Cancel
Save