Browse Source

Trade: refresh MeshData docs slightly.

It was rather discouraging to start "Basic usage" with a boring-ass long
snippet. On the other hand showing just compile() first would lead
people to think it's all some opaque magic, so trying to balance that a
bit.

Also why the hell was the compile() snippet showing the horrendous GL
way of specifying attribute formats? This is not great either but at
least not redundant.
pull/525/head
Vladimír Vondruš 5 years ago
parent
commit
efa02d46df
  1. 11
      doc/snippets/MagnumMeshTools-gl.cpp
  2. 23
      doc/snippets/MagnumTrade.cpp
  3. 101
      src/Magnum/Trade/MeshData.h

11
doc/snippets/MagnumMeshTools-gl.cpp

@ -38,6 +38,8 @@
#include <vector> #include <vector>
#endif #endif
#define DOXYGEN_IGNORE(...) __VA_ARGS__
using namespace Magnum; using namespace Magnum;
int main() { int main() {
@ -55,8 +57,9 @@ GL::Mesh mesh = MeshTools::compile(meshData, indices, vertices);
{ {
Trade::MeshData meshData{MeshPrimitive::Lines, 5}; Trade::MeshData meshData{MeshPrimitive::Lines, 5};
Trade::MeshAttribute myCustomAttribute{};
/* [compile-external-attributes] */ /* [compile-external-attributes] */
Trade::MeshAttribute myCustomAttribute = DOXYGEN_IGNORE({});
GL::Buffer indices, vertices; GL::Buffer indices, vertices;
indices.setData(meshData.indexData()); indices.setData(meshData.indexData());
vertices.setData(meshData.vertexData()); vertices.setData(meshData.vertexData());
@ -66,10 +69,8 @@ GL::Mesh mesh = MeshTools::compile(meshData, std::move(indices), vertices);
mesh.addVertexBuffer(std::move(vertices), mesh.addVertexBuffer(std::move(vertices),
meshData.attributeOffset(myCustomAttribute), meshData.attributeOffset(myCustomAttribute),
meshData.attributeStride(myCustomAttribute), meshData.attributeStride(myCustomAttribute),
GL::DynamicAttribute{ GL::DynamicAttribute{GL::DynamicAttribute::Kind::Generic, 7,
GL::DynamicAttribute::Kind::Generic, 7, meshData.attributeFormat(myCustomAttribute)});
GL::DynamicAttribute::Components::One,
GL::DynamicAttribute::DataType::Float});
/* [compile-external-attributes] */ /* [compile-external-attributes] */
} }

23
doc/snippets/MagnumTrade.cpp

@ -638,7 +638,7 @@ constexpr Trade::MeshAttributeData colors{Trade::MeshAttribute::Color,
/* Actual data populated later */ /* Actual data populated later */
Containers::Array<char> vertexData{15*sizeof(Vertex)}; Containers::Array<char> vertexData{15*sizeof(Vertex)};
// ... DOXYGEN_IGNORE()
Trade::MeshData{MeshPrimitive::Triangles, std::move(vertexData), Trade::MeshData{MeshPrimitive::Triangles, std::move(vertexData),
{positions, colors}}; {positions, colors}};
/* [MeshAttributeData-usage-offset-only] */ /* [MeshAttributeData-usage-offset-only] */
@ -656,6 +656,14 @@ Trade::MeshAttributeData normals{Trade::MeshAttribute::Normal,
#endif #endif
#ifdef MAGNUM_TARGET_GL #ifdef MAGNUM_TARGET_GL
{
/* [MeshData-usage-compile] */
Trade::MeshData data = DOXYGEN_IGNORE(Trade::MeshData{MeshPrimitive::Points, 0});
GL::Mesh mesh = MeshTools::compile(data);
/* [MeshData-usage-compile] */
}
{ {
Trade::MeshData data{MeshPrimitive::Points, 0}; Trade::MeshData data{MeshPrimitive::Points, 0};
/* [MeshData-usage] */ /* [MeshData-usage] */
@ -672,7 +680,7 @@ vertices.setData(MeshTools::interleave(data.positions3DAsArray(),
mesh.addVertexBuffer(std::move(vertices), 0, mesh.addVertexBuffer(std::move(vertices), 0,
Shaders::PhongGL::Position{}, Shaders::PhongGL::Normal{}); Shaders::PhongGL::Position{}, Shaders::PhongGL::Normal{});
/* Set up an index buffer, if the mesh is indexed*/ /* Set up an index buffer, if the mesh is indexed */
if(data.isIndexed()) { if(data.isIndexed()) {
GL::Buffer indices; GL::Buffer indices;
indices.setData(data.indicesAsArray()); indices.setData(data.indicesAsArray());
@ -702,8 +710,6 @@ mesh.addVertexBuffer(vertices,
GL::DynamicAttribute{Shaders::PhongGL::Normal{}, GL::DynamicAttribute{Shaders::PhongGL::Normal{},
data.attributeFormat(Trade::MeshAttribute::Normal)}); data.attributeFormat(Trade::MeshAttribute::Normal)});
// Set up other attributes ...
/* Upload the original packed index data */ /* Upload the original packed index data */
if(data.isIndexed()) { if(data.isIndexed()) {
GL::Buffer indices; GL::Buffer indices;
@ -713,13 +719,6 @@ if(data.isIndexed()) {
} else mesh.setCount(data.vertexCount()); } else mesh.setCount(data.vertexCount());
/* [MeshData-usage-advanced] */ /* [MeshData-usage-advanced] */
} }
{
Trade::MeshData data{MeshPrimitive::Points, 0};
/* [MeshData-usage-compile] */
GL::Mesh mesh = MeshTools::compile(data);
/* [MeshData-usage-compile] */
}
#endif #endif
{ {
@ -747,7 +746,7 @@ struct Vertex {
Containers::Array<char> indexData{indexCount*sizeof(UnsignedShort)}; Containers::Array<char> indexData{indexCount*sizeof(UnsignedShort)};
Containers::Array<char> vertexData{vertexCount*sizeof(Vertex)}; Containers::Array<char> vertexData{vertexCount*sizeof(Vertex)};
// … DOXYGEN_IGNORE()
auto vertices = Containers::arrayCast<const Vertex>(vertexData); auto vertices = Containers::arrayCast<const Vertex>(vertexData);
auto indices = Containers::arrayCast<const UnsignedShort>(indexData); auto indices = Containers::arrayCast<const UnsignedShort>(indexData);

101
src/Magnum/Trade/MeshData.h

@ -223,7 +223,7 @@ index array. The @ref MeshIndexType gets inferred from the view type:
Alternatively, you can pass a typeless @cpp const void @ce view and supply Alternatively, you can pass a typeless @cpp const void @ce view and supply
@ref MeshIndexType explicitly, or a contiguous 2D view and let the class detect @ref MeshIndexType explicitly, or a contiguous 2D view and let the class detect
the actual index type from second dimension size. Note that the class accepts the actual index type from second dimension size. Note that the class accepts
only contiguous views and not @ref Corrade::Containers::StridedArrayView, only contiguous views and not @relativeref{Corrade,Containers::StridedArrayView},
following limitations of GPU index buffers that also have to be contiguous. following limitations of GPU index buffers that also have to be contiguous.
@see @ref MeshAttributeData @see @ref MeshAttributeData
*/ */
@ -594,47 +594,60 @@ information such as primitive type. Populated instances of this class are
returned from @ref AbstractImporter::mesh() and from particular functions in returned from @ref AbstractImporter::mesh() and from particular functions in
the @ref Primitives library. the @ref Primitives library.
@section Trade-MeshData-usage-compile Quick usage with MeshTools::compile()
If all you want is to create a @ref GL::Mesh that can be rendered by builtin
shaders, a simple yet efficient way is to use @ref MeshTools::compile():
@snippet MagnumTrade.cpp MeshData-usage-compile
This one-liner uploads the data and configures the mesh for all attributes
known by Magnum that are present in it. It's however rather opaque and doesn't
give you any opportunity to do anything with the mesh data before they get sent
to the GPU. It also won't be able to deal with any custom attributes that the
mesh contains. Continue below to see how to achieve a similar effect with
lower-level APIs.
@section Trade-MeshData-usage Basic usage @section Trade-MeshData-usage Basic usage
The simplest usage is through the convenience functions @ref positions2DAsArray(), The second simplest usage is accessing attributes through the convenience
@ref positions3DAsArray(), @ref tangentsAsArray(), @ref bitangentsAsArray(), functions @ref positions2DAsArray(), @ref positions3DAsArray(),
@ref normalsAsArray(), @ref tangentsAsArray(), @ref textureCoordinates2DAsArray(), @ref tangentsAsArray(), @ref bitangentsAsArray(), @ref normalsAsArray(),
@ref colorsAsArray() and @ref objectIdsAsArray(). Each of these takes an index @ref tangentsAsArray(), @ref textureCoordinates2DAsArray(),
(as there can be multiple sets of texture coordinates, for example) and you're @ref colorsAsArray() and @ref objectIdsAsArray(). You're expected to check for
expected to check for attribute presence first with either @ref hasAttribute() attribute presence first with either @ref hasAttribute() (or
or @ref attributeCount(MeshAttribute) const: @ref attributeCount(MeshAttribute) const, as there can be multiple sets of
texture coordinates, for example). If you are creating a @ref GL::Mesh, the
usual path forward is then to @ref MeshTools::interleave() attributes of
interest, upload them to a @ref GL::Buffer and configure attribute binding for
the mesh.
The mesh can be also indexed, in which case the index buffer is exposed through
@ref indicesAsArray().
@snippet MagnumTrade.cpp MeshData-usage @snippet MagnumTrade.cpp MeshData-usage
@section Trade-MeshData-usage-advanced Advanced usage @section Trade-MeshData-usage-advanced Advanced usage
The @ref positions2DAsArray(), ... functions shown above always return a The @ref positions2DAsArray(), ... functions shown above always return a
newly-allocated @ref Corrade::Containers::Array instance with a clearly defined newly-allocated @relativeref{Corrade,Containers::Array} instance of a type
type that's large enough to represent most data. While that's fine for many use that's large enough to represent most data. While that's fine for many use
cases, sometimes you may want to minimize the import time of a large model or cases, it can take significant amount of time for large models or maybe the
the imported data may be already in a well-optimized layout and format that you imported data is already in a well-optimized layout and format that you want to
want to preserve. The @ref MeshData class internally stores a contiguous blob preserve. The @ref MeshData class internally stores a contiguous blob of data,
of data, which you can directly upload, and then use provided metadata to let which you can directly upload, and then use provided metadata to let the GPU
the GPU know of the format and layout. Because there's a lot of possible types know of the format and layout. There's a lot of possible types of each
of each attribute (floats, packed integers, ...), the @ref GL::DynamicAttribute attribute (floats, packed integers, ...), so @ref GL::DynamicAttribute accepts
can accept a pair of @ref GL::Attribute defined by the shader and the actual also a pair of @ref GL::Attribute defined by the shader and the actual
@ref VertexFormat, figuring out all properties such as component count and @ref VertexFormat, figuring out gthe GL-specific properties such as component
element data type without having to explicitly handle all relevant types: count or element data type for you:
@snippet MagnumTrade.cpp MeshData-usage-advanced @snippet MagnumTrade.cpp MeshData-usage-advanced
@section Trade-MeshData-usage-compile Using MeshTools::compile() This approach is especially useful when dealing with custom attributes. See
also @ref MeshTools::compile(const Trade::MeshData&, GL::Buffer&, GL::Buffer&)
For a quick yet efficient way to upload all data and configure a mesh for all for a combined way that gives you both the flexibility needed for custom
known attributes that are present, @ref MeshTools::compile() can be used. attributes as well as the convenience for builtin attributes.
Compared to the above, it's just an oneliner:
@snippet MagnumTrade.cpp MeshData-usage-compile
Compared to configuring the mesh manually you may lose a bit of flexibility,
especially when you need to set up custom attributes or modify the data after.
See @ref MeshTools::compile(const Trade::MeshData&, GL::Buffer&, GL::Buffer&)
for a possible solution.
@section Trade-MeshData-usage-mutable Mutable data access @section Trade-MeshData-usage-mutable Mutable data access
@ -658,21 +671,21 @@ to do a similar operation with normals and tangents as well.
@section Trade-MeshData-populating Populating an instance @section Trade-MeshData-populating Populating an instance
A @ref MeshData instance by default takes over the ownership of an A @ref MeshData instance by default takes over the ownership of an
@ref Corrade::Containers::Array containing the vertex / index data together @relativeref{Corrade,Containers::Array} containing the vertex / index data
with a @ref MeshIndexData instance and a list of @ref MeshAttributeData together with a @ref MeshIndexData instance and a list of
describing various index and vertex properties. For example, an interleaved @ref MeshAttributeData describing various index and vertex properties. For
indexed mesh with 3D positions and RGBA colors would look like this --- example, an interleaved indexed mesh with 3D positions and RGBA colors would
and variants with just vertex data or just index data or neither are possible look like this --- and variants with just vertex data or just index data or
too: neither are possible too:
@snippet MagnumTrade.cpp MeshData-populating @snippet MagnumTrade.cpp MeshData-populating
In cases where you want the @ref MeshData instance to only refer to external In cases where you want the @ref MeshData instance to only refer to external
data without taking ownership (for example in a memory-mapped file, constant data without taking ownership (for example in a memory-mapped file, constant
memory etc.). Instead of moving in an @ref Corrade::Containers::Array you pass memory etc.). Instead of moving in an @relativeref{Corrade,Containers::Array}
@ref DataFlags describing if the data is mutable or not together with an you pass @ref DataFlags describing if the data is mutable or not together with
@ref Corrade::Containers::ArrayView. A variant of the above where the index an @relativeref{Corrade,Containers::ArrayView}. A variant of the above where
data is constant and vertex data mutable, both referenced externally: the index data is constant and vertex data mutable, both referenced externally:
@snippet MagnumTrade.cpp MeshData-populating-non-owned @snippet MagnumTrade.cpp MeshData-populating-non-owned
@ -1092,7 +1105,7 @@ class MAGNUM_TRADE_EXPORT MeshData {
* *
* Use the templated overload below to get the indices in a concrete * Use the templated overload below to get the indices in a concrete
* type. * type.
* @see @ref Corrade::Containers::StridedArrayView::isContiguous() * @see @relativeref{Corrade,Containers::StridedArrayView::isContiguous()}
*/ */
Containers::StridedArrayView2D<const char> indices() const; Containers::StridedArrayView2D<const char> indices() const;
@ -1315,7 +1328,7 @@ class MAGNUM_TRADE_EXPORT MeshData {
* implementation-specific values) and is guaranteed to be contiguous. * implementation-specific values) and is guaranteed to be contiguous.
* Use the templated overload below to get the attribute in a concrete * Use the templated overload below to get the attribute in a concrete
* type. * type.
* @see @ref Corrade::Containers::StridedArrayView::isContiguous(), * @see @relativeref{Corrade,Containers::StridedArrayView::isContiguous()},
* @ref vertexFormatSize(), * @ref vertexFormatSize(),
* @ref isVertexFormatImplementationSpecific() * @ref isVertexFormatImplementationSpecific()
*/ */
@ -1398,7 +1411,7 @@ class MAGNUM_TRADE_EXPORT MeshData {
* type. * type.
* @see @ref attribute(UnsignedInt) const, * @see @ref attribute(UnsignedInt) const,
* @ref mutableAttribute(MeshAttribute, UnsignedInt), * @ref mutableAttribute(MeshAttribute, UnsignedInt),
* @ref Corrade::Containers::StridedArrayView::isContiguous(), * @relativeref{Corrade,Containers::StridedArrayView::isContiguous()},
* @ref isVertexFormatImplementationSpecific() * @ref isVertexFormatImplementationSpecific()
*/ */
Containers::StridedArrayView2D<const char> attribute(MeshAttribute name, UnsignedInt id = 0) const; Containers::StridedArrayView2D<const char> attribute(MeshAttribute name, UnsignedInt id = 0) const;

Loading…
Cancel
Save