diff --git a/doc/snippets/MagnumMeshTools-gl.cpp b/doc/snippets/MagnumMeshTools-gl.cpp index fc027b7d5..e8fe5adbe 100644 --- a/doc/snippets/MagnumMeshTools-gl.cpp +++ b/doc/snippets/MagnumMeshTools-gl.cpp @@ -38,6 +38,8 @@ #include #endif +#define DOXYGEN_IGNORE(...) __VA_ARGS__ + using namespace Magnum; int main() { @@ -55,8 +57,9 @@ GL::Mesh mesh = MeshTools::compile(meshData, indices, vertices); { Trade::MeshData meshData{MeshPrimitive::Lines, 5}; -Trade::MeshAttribute myCustomAttribute{}; /* [compile-external-attributes] */ +Trade::MeshAttribute myCustomAttribute = DOXYGEN_IGNORE({}); + GL::Buffer indices, vertices; indices.setData(meshData.indexData()); vertices.setData(meshData.vertexData()); @@ -66,10 +69,8 @@ GL::Mesh mesh = MeshTools::compile(meshData, std::move(indices), vertices); mesh.addVertexBuffer(std::move(vertices), meshData.attributeOffset(myCustomAttribute), meshData.attributeStride(myCustomAttribute), - GL::DynamicAttribute{ - GL::DynamicAttribute::Kind::Generic, 7, - GL::DynamicAttribute::Components::One, - GL::DynamicAttribute::DataType::Float}); + GL::DynamicAttribute{GL::DynamicAttribute::Kind::Generic, 7, + meshData.attributeFormat(myCustomAttribute)}); /* [compile-external-attributes] */ } diff --git a/doc/snippets/MagnumTrade.cpp b/doc/snippets/MagnumTrade.cpp index 5627ebc29..fa9c5aad0 100644 --- a/doc/snippets/MagnumTrade.cpp +++ b/doc/snippets/MagnumTrade.cpp @@ -638,7 +638,7 @@ constexpr Trade::MeshAttributeData colors{Trade::MeshAttribute::Color, /* Actual data populated later */ Containers::Array vertexData{15*sizeof(Vertex)}; -// ... +DOXYGEN_IGNORE() Trade::MeshData{MeshPrimitive::Triangles, std::move(vertexData), {positions, colors}}; /* [MeshAttributeData-usage-offset-only] */ @@ -656,6 +656,14 @@ Trade::MeshAttributeData normals{Trade::MeshAttribute::Normal, #endif #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}; /* [MeshData-usage] */ @@ -672,7 +680,7 @@ vertices.setData(MeshTools::interleave(data.positions3DAsArray(), mesh.addVertexBuffer(std::move(vertices), 0, 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()) { GL::Buffer indices; indices.setData(data.indicesAsArray()); @@ -702,8 +710,6 @@ mesh.addVertexBuffer(vertices, GL::DynamicAttribute{Shaders::PhongGL::Normal{}, data.attributeFormat(Trade::MeshAttribute::Normal)}); -// Set up other attributes ... - /* Upload the original packed index data */ if(data.isIndexed()) { GL::Buffer indices; @@ -713,13 +719,6 @@ if(data.isIndexed()) { } else mesh.setCount(data.vertexCount()); /* [MeshData-usage-advanced] */ } - -{ -Trade::MeshData data{MeshPrimitive::Points, 0}; -/* [MeshData-usage-compile] */ -GL::Mesh mesh = MeshTools::compile(data); -/* [MeshData-usage-compile] */ -} #endif { @@ -747,7 +746,7 @@ struct Vertex { Containers::Array indexData{indexCount*sizeof(UnsignedShort)}; Containers::Array vertexData{vertexCount*sizeof(Vertex)}; -// … +DOXYGEN_IGNORE() auto vertices = Containers::arrayCast(vertexData); auto indices = Containers::arrayCast(indexData); diff --git a/src/Magnum/Trade/MeshData.h b/src/Magnum/Trade/MeshData.h index 707b81a78..438236bcd 100644 --- a/src/Magnum/Trade/MeshData.h +++ b/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 @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 -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. @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 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 -The simplest usage is through the convenience functions @ref positions2DAsArray(), -@ref positions3DAsArray(), @ref tangentsAsArray(), @ref bitangentsAsArray(), -@ref normalsAsArray(), @ref tangentsAsArray(), @ref textureCoordinates2DAsArray(), -@ref colorsAsArray() and @ref objectIdsAsArray(). Each of these takes an index -(as there can be multiple sets of texture coordinates, for example) and you're -expected to check for attribute presence first with either @ref hasAttribute() -or @ref attributeCount(MeshAttribute) const: +The second simplest usage is accessing attributes through the convenience +functions @ref positions2DAsArray(), @ref positions3DAsArray(), +@ref tangentsAsArray(), @ref bitangentsAsArray(), @ref normalsAsArray(), +@ref tangentsAsArray(), @ref textureCoordinates2DAsArray(), +@ref colorsAsArray() and @ref objectIdsAsArray(). You're expected to check for +attribute presence first with either @ref hasAttribute() (or +@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 @section Trade-MeshData-usage-advanced Advanced usage The @ref positions2DAsArray(), ... functions shown above always return a -newly-allocated @ref Corrade::Containers::Array instance with a clearly defined -type 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 -the imported data may be already in a well-optimized layout and format that you -want to preserve. The @ref MeshData class internally stores a contiguous blob -of data, which you can directly upload, and then use provided metadata to let -the GPU know of the format and layout. Because there's a lot of possible types -of each attribute (floats, packed integers, ...), the @ref GL::DynamicAttribute -can accept a pair of @ref GL::Attribute defined by the shader and the actual -@ref VertexFormat, figuring out all properties such as component count and -element data type without having to explicitly handle all relevant types: +newly-allocated @relativeref{Corrade,Containers::Array} instance of a type +that's large enough to represent most data. While that's fine for many use +cases, it can take significant amount of time for large models or maybe the +imported data is already in a well-optimized layout and format that you want to +preserve. The @ref MeshData class internally stores a contiguous blob of data, +which you can directly upload, and then use provided metadata to let the GPU +know of the format and layout. There's a lot of possible types of each +attribute (floats, packed integers, ...), so @ref GL::DynamicAttribute accepts +also a pair of @ref GL::Attribute defined by the shader and the actual +@ref VertexFormat, figuring out gthe GL-specific properties such as component +count or element data type for you: @snippet MagnumTrade.cpp MeshData-usage-advanced -@section Trade-MeshData-usage-compile Using MeshTools::compile() - -For a quick yet efficient way to upload all data and configure a mesh for all -known attributes that are present, @ref MeshTools::compile() can be used. -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. +This approach is especially useful when dealing with custom attributes. See +also @ref MeshTools::compile(const Trade::MeshData&, GL::Buffer&, GL::Buffer&) +for a combined way that gives you both the flexibility needed for custom +attributes as well as the convenience for builtin attributes. @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 A @ref MeshData instance by default takes over the ownership of an -@ref Corrade::Containers::Array containing the vertex / index data together -with a @ref MeshIndexData instance and a list of @ref MeshAttributeData -describing various index and vertex properties. For example, an interleaved -indexed mesh with 3D positions and RGBA colors would look like this --- -and variants with just vertex data or just index data or neither are possible -too: +@relativeref{Corrade,Containers::Array} containing the vertex / index data +together with a @ref MeshIndexData instance and a list of +@ref MeshAttributeData describing various index and vertex properties. For +example, an interleaved indexed mesh with 3D positions and RGBA colors would +look like this --- and variants with just vertex data or just index data or +neither are possible too: @snippet MagnumTrade.cpp MeshData-populating 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 -memory etc.). Instead of moving in an @ref Corrade::Containers::Array you pass -@ref DataFlags describing if the data is mutable or not together with an -@ref Corrade::Containers::ArrayView. A variant of the above where the index -data is constant and vertex data mutable, both referenced externally: +memory etc.). Instead of moving in an @relativeref{Corrade,Containers::Array} +you pass @ref DataFlags describing if the data is mutable or not together with +an @relativeref{Corrade,Containers::ArrayView}. A variant of the above where +the index data is constant and vertex data mutable, both referenced externally: @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 * type. - * @see @ref Corrade::Containers::StridedArrayView::isContiguous() + * @see @relativeref{Corrade,Containers::StridedArrayView::isContiguous()} */ Containers::StridedArrayView2D indices() const; @@ -1315,7 +1328,7 @@ class MAGNUM_TRADE_EXPORT MeshData { * implementation-specific values) and is guaranteed to be contiguous. * Use the templated overload below to get the attribute in a concrete * type. - * @see @ref Corrade::Containers::StridedArrayView::isContiguous(), + * @see @relativeref{Corrade,Containers::StridedArrayView::isContiguous()}, * @ref vertexFormatSize(), * @ref isVertexFormatImplementationSpecific() */ @@ -1398,7 +1411,7 @@ class MAGNUM_TRADE_EXPORT MeshData { * type. * @see @ref attribute(UnsignedInt) const, * @ref mutableAttribute(MeshAttribute, UnsignedInt), - * @ref Corrade::Containers::StridedArrayView::isContiguous(), + * @relativeref{Corrade,Containers::StridedArrayView::isContiguous()}, * @ref isVertexFormatImplementationSpecific() */ Containers::StridedArrayView2D attribute(MeshAttribute name, UnsignedInt id = 0) const;