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 {
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<Trade::MeshAttributeData> attributes;
if(textureCoords == CircleTextureCoords::Generate)
attributes = Trade::meshAttributeDataNonOwningArray(AttributeData2DTextureCoords);
else
attributes = Trade::meshAttributeDataNonOwningArray(AttributeData2D);
const std::size_t stride = attributes[0].stride();
Containers::Array<char> vertexData{stride*(segments + 2)};
Containers::Array<Trade::MeshAttributeData> attributes{attributeCount};
/* Fill positions */
Containers::StridedArrayView1D<Vector2> positions{vertexData,
reinterpret_cast<Vector2*>(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<Vector2> textureCoords{vertexData,
reinterpret_cast<Vector2*>(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<Trade::MeshAttributeData> attributes;
if(textureCoords == CircleTextureCoords::Generate)
attributes = Trade::meshAttributeDataNonOwningArray(AttributeData3DTextureCoords);
else
attributes = Trade::meshAttributeDataNonOwningArray(AttributeData3D);
const std::size_t stride = attributes[0].stride();
Containers::Array<char> vertexData{stride*(segments + 2)};
Containers::Array<Trade::MeshAttributeData> attributes{attributeCount};
/* Fill positions */
Containers::StridedArrayView1D<Vector3> positions{vertexData,
reinterpret_cast<Vector3*>(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<Vector3> normals{vertexData,
reinterpret_cast<Vector3*>(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<Vector2> textureCoords{vertexData,
reinterpret_cast<Vector2*>(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())};
}
}}

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};
}
/* 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())};
}
}}

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() {
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<VertexTextureCoords*>(_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<Trade::MeshAttributeData> 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<Trade::MeshAttributeData>{Containers::InPlaceInit, {positions, normals, textureCoords}};
} else {
attributes = Containers::Array<Trade::MeshAttributeData>{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<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});
}
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<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