diff --git a/doc/snippets/MagnumTrade.cpp b/doc/snippets/MagnumTrade.cpp index 78feb6856..b39fafa89 100644 --- a/doc/snippets/MagnumTrade.cpp +++ b/doc/snippets/MagnumTrade.cpp @@ -758,24 +758,20 @@ Trade::MeshAttributeData data{Trade::MeshAttribute::Position, positions}; } { +UnsignedInt vertexCount{}; /* [MeshAttributeData-usage-offset-only] */ struct Vertex { Vector3 position; Vector4 color; }; -/* Layout defined statically, 15 vertices in total */ -constexpr Trade::MeshAttributeData positions{Trade::MeshAttribute::Position, - VertexFormat::Vector3, offsetof(Vertex, position), 15, sizeof(Vertex)}; -constexpr Trade::MeshAttributeData colors{Trade::MeshAttribute::Color, - VertexFormat::Vector4, offsetof(Vertex, color), 15, sizeof(Vertex)}; - -/* Actual data populated later */ -Containers::Array vertexData{15*sizeof(Vertex)}; -DOXYGEN_ELLIPSIS() -Trade::MeshData{MeshPrimitive::Triangles, std::move(vertexData), - {positions, colors}}; +Trade::MeshAttributeData positions{Trade::MeshAttribute::Position, + VertexFormat::Vector3, offsetof(Vertex, position), vertexCount, sizeof(Vertex)}; +Trade::MeshAttributeData colors{Trade::MeshAttribute::Color, + VertexFormat::Vector4, offsetof(Vertex, color), vertexCount, sizeof(Vertex)}; /* [MeshAttributeData-usage-offset-only] */ +static_cast(positions); +static_cast(colors); } #ifdef MAGNUM_TARGET_VK @@ -895,18 +891,18 @@ struct Vertex { Containers::Array indexData{indexCount*sizeof(UnsignedShort)}; Containers::Array vertexData{vertexCount*sizeof(Vertex)}; DOXYGEN_ELLIPSIS() -auto vertices = Containers::arrayCast(vertexData); -auto indices = Containers::arrayCast(indexData); +Containers::StridedArrayView1D vertices = + Containers::arrayCast(vertexData); +Containers::ArrayView indices = + Containers::arrayCast(indexData); Trade::MeshData data{MeshPrimitive::Triangles, std::move(indexData), Trade::MeshIndexData{indices}, std::move(vertexData), { Trade::MeshAttributeData{Trade::MeshAttribute::Position, - Containers::StridedArrayView1D{vertices, - &vertices[0].position, vertexCount, sizeof(Vertex)}}, + vertices.slice(&Vertex::position)}, Trade::MeshAttributeData{Trade::MeshAttribute::Color, - Containers::StridedArrayView1D{vertices, - &vertices[0].color, vertexCount, sizeof(Vertex)}} + vertices.slice(&Vertex::color)} }}; /* [MeshData-populating] */ } @@ -917,29 +913,51 @@ struct Vertex { Vector4 color; }; /* [MeshData-populating-non-owned] */ -const UnsignedShort indices[] { - 0, 1, 2, - 2, 1, 3, - 3, 4, 5, - 5, 4, 6 +const UnsignedShort indices[]{ + DOXYGEN_ELLIPSIS(0) +}; +Vertex vertices[]{ + DOXYGEN_ELLIPSIS({}) }; -Vertex vertices[7]; Trade::MeshData data{MeshPrimitive::Triangles, Trade::DataFlags{}, indices, Trade::MeshIndexData{indices}, Trade::DataFlag::Mutable, vertices, { Trade::MeshAttributeData{Trade::MeshAttribute::Position, - Containers::StridedArrayView1D{ - Containers::arrayView(vertices), &vertices[0].position, - Containers::arraySize(vertices), sizeof(Vertex)}}, + Containers::stridedArrayView(vertices).slice(&Vertex::position)}, Trade::MeshAttributeData{Trade::MeshAttribute::Color, - Containers::StridedArrayView1D{ - Containers::arrayView(vertices), &vertices[0].color, - Containers::arraySize(vertices), sizeof(Vertex)}} + Containers::stridedArrayView(vertices).slice(&Vertex::color)} }}; /* [MeshData-populating-non-owned] */ } +{ +UnsignedInt vertexCount{}; +/* [MeshData-populating-offset-only] */ +struct Vertex { + Vector3 position; + Vector4 color; +}; + +/* Layout known in advance, except for vertex count */ +constexpr Trade::MeshAttributeData attributes[]{ + Trade::MeshAttributeData{Trade::MeshAttribute::Position, + VertexFormat::Vector3, offsetof(Vertex, position), 0, sizeof(Vertex)}, + Trade::MeshAttributeData{Trade::MeshAttribute::Color, + VertexFormat::Vector4, offsetof(Vertex, color), 15, sizeof(Vertex)} +}; + +/* Actual data populated later */ +Containers::Array vertexData{vertexCount*sizeof(Vertex)}; +DOXYGEN_ELLIPSIS() + +/* Using the statically defined attribute layout together with explicitly + passed vertex count */ +Trade::MeshData mesh{MeshPrimitive::Triangles, std::move(vertexData), + Trade::meshAttributeDataNonOwningArray(attributes), vertexCount}; +/* [MeshData-populating-offset-only] */ +} + { /* [MeshData-populating-custom] */ /* Each face can consist of 15 triangles at most, triangleCount says how many @@ -1060,27 +1078,23 @@ Trade::SceneFieldData field{Trade::SceneField::Transformation, } { +std::size_t objectCount = 120; /* [SceneFieldData-usage-offset-only] */ struct Node { - UnsignedInt object; + UnsignedInt mapping; Int parent; - Matrix4 transform; + Matrix4 transformation; }; -/* Layout defined statically, 120 objects in total */ -constexpr Trade::SceneFieldData parents{Trade::SceneField::Parent, 120, - Trade::SceneMappingType::UnsignedInt, offsetof(Node, object), sizeof(Node), +Trade::SceneFieldData parents{Trade::SceneField::Parent, objectCount, + Trade::SceneMappingType::UnsignedInt, offsetof(Node, mapping), sizeof(Node), Trade::SceneFieldType::Int, offsetof(Node, parent), sizeof(Node)}; -constexpr Trade::SceneFieldData transforms{Trade::SceneField::Transformation, 120, - Trade::SceneMappingType::UnsignedInt, offsetof(Node, object), sizeof(Node), - Trade::SceneFieldType::Matrix4x4, offsetof(Node, transform), sizeof(Node)}; - -/* Actual data populated later */ -Containers::Array data{120*sizeof(Node)}; -DOXYGEN_ELLIPSIS() -Trade::SceneData{Trade::SceneMappingType::UnsignedInt, 120, std::move(data), - {parents, transforms}}; +Trade::SceneFieldData transformations{Trade::SceneField::Transformation, objectCount, + Trade::SceneMappingType::UnsignedInt, offsetof(Node, mapping), sizeof(Node), + Trade::SceneFieldType::Matrix4x4, offsetof(Node, transformation), sizeof(Node)}; /* [SceneFieldData-usage-offset-only] */ +static_cast(parents); +static_cast(transformations); } { @@ -1197,7 +1211,7 @@ for(std::size_t i = 0; i != transformationMapping.size(); ++i) { const std::size_t nodeCount{}, meshAssignmentCount{}; /* [SceneData-populating] */ struct Common { - UnsignedShort object; + UnsignedShort mapping; Short parent; Matrix4 transformation; }; @@ -1219,17 +1233,71 @@ Trade::SceneData scene{ Trade::SceneMappingType::UnsignedShort, nodeCount, std::move(data), { Trade::SceneFieldData{Trade::SceneField::Parent, - common.slice(&Common::object), common.slice(&Common::parent)}, + common.slice(&Common::mapping), + common.slice(&Common::parent)}, Trade::SceneFieldData{Trade::SceneField::Transformation, - common.slice(&Common::object), common.slice(&Common::transformation)}, + common.slice(&Common::mapping), common.slice(&Common::transformation)}, Trade::SceneFieldData{Trade::SceneField::Mesh, - meshMaterialMapping, meshes}, + meshMaterialMapping, + meshes}, Trade::SceneFieldData{Trade::SceneField::MeshMaterial, - meshMaterialMapping, meshMaterials} + meshMaterialMapping, + meshMaterials} }}; /* [SceneData-populating] */ } +{ +constexpr std::size_t objectCount = 1; +/* [SceneData-populating-non-owned] */ +constexpr struct Data { + UnsignedShort mapping; + Short parent; + Matrix4 transformation; +} data[objectCount]{ + DOXYGEN_ELLIPSIS({}) +}; + +Trade::SceneData scene{ + Trade::SceneMappingType::UnsignedShort, objectCount, + Trade::DataFlag::Global, data, { + Trade::SceneFieldData{Trade::SceneField::Parent, + Containers::stridedArrayView(data).slice(&Data::mapping), + Containers::stridedArrayView(data).slice(&Data::parent)}, + DOXYGEN_ELLIPSIS() + }}; +/* [SceneData-populating-non-owned] */ +} + +{ +constexpr std::size_t objectCount = 1; +/* [SceneData-populating-offset-only] */ +struct Data { + UnsignedInt mapping; + Int parent; + Matrix4 transformation; +}; + +/* Layout defined statically */ +constexpr Trade::SceneFieldData fields[]{ + Trade::SceneFieldData{Trade::SceneField::Parent, objectCount, + Trade::SceneMappingType::UnsignedInt, offsetof(Data, mapping), sizeof(Data), + Trade::SceneFieldType::Int, offsetof(Data, parent), sizeof(Data)}, + Trade::SceneFieldData{Trade::SceneField::Transformation, objectCount, + Trade::SceneMappingType::UnsignedInt, offsetof(Data, mapping), sizeof(Data), + Trade::SceneFieldType::Matrix4x4, offsetof(Data, transformation), sizeof(Data)} +}; + +/* Actual data populated later */ +Containers::Array data{objectCount*sizeof(Data)}; +DOXYGEN_ELLIPSIS() + +/* Using the statically defined field layout */ +Trade::SceneData scene{Trade::SceneMappingType::UnsignedInt, objectCount, + std::move(data), Trade::sceneFieldDataNonOwningArray(fields)}; +/* [SceneData-populating-offset-only] */ +} + { std::size_t nodeCount{}; /* [SceneData-populating-custom1] */ diff --git a/src/Magnum/Trade/MaterialData.h b/src/Magnum/Trade/MaterialData.h index f2b61c362..d71cf82b5 100644 --- a/src/Magnum/Trade/MaterialData.h +++ b/src/Magnum/Trade/MaterialData.h @@ -1919,11 +1919,14 @@ internally sorted by name to allow a @f$ \mathcal{O}(\log n) @f$ lookup. @snippet MagnumTrade.cpp MaterialData-populating -In addition to passing ownership of an array it's also possible to have the -@ref MaterialData instance refer to external data (for example in a -memory-mapped file, constant 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 +@subsection Trade-MaterialData-populating-non-owned Non-owned instances + +In some cases you may want the @ref MaterialData instance to only refer to +external data without taking ownership, for example with a memory-mapped file, +global data etc. For that, instead of moving in an +@relativeref{Corrade,Containers::Array} of @ref MaterialAttributeData or +allocating it implicitly from an initializer list in the constructor, pass +@ref DataFlags describing data mutability and ownership together with an @relativeref{Corrade,Containers::ArrayView}. Note that in this case, since the attribute data is treated as immutable, you *have to* ensure the list is already sorted by name. diff --git a/src/Magnum/Trade/MeshData.h b/src/Magnum/Trade/MeshData.h index 6d035f2b4..d769d85f6 100644 --- a/src/Magnum/Trade/MeshData.h +++ b/src/Magnum/Trade/MeshData.h @@ -387,8 +387,9 @@ class MAGNUM_TRADE_EXPORT MeshIndexData { @brief Mesh attribute data @m_since{2020,06} -Convenience type for populating @ref MeshData, see its documentation for an -introduction. Additionally usable in various @ref MeshTools algorithms such as +Convenience type for populating @ref MeshData, see +@ref Trade-MeshData-populating "its documentation" for an introduction. +Additionally usable in various @ref MeshTools algorithms such as @ref MeshTools::duplicate(const Trade::MeshData& data, Containers::ArrayView) or @ref MeshTools::interleave(const Trade::MeshData& data, Containers::ArrayView, InterleaveFlags). @@ -406,19 +407,21 @@ supply @ref VertexFormat explicitly. @subsection Trade-MeshAttributeData-usage-offset-only Offset-only attribute data If the actual attribute data location is not known yet, the instance can be -created as "offset-only", meaning the actual view gets created only later when -passed to a @ref MeshData instance with a concrete vertex data array. This is -useful mainly to avoid pointer patching during data serialization, but also for -example when vertex layout is static (and thus can be defined at compile time), -but the actual data is allocated / populated at runtime: +created as "offset-only" using @ref MeshAttributeData(MeshAttribute, VertexFormat, std::size_t, UnsignedInt, std::ptrdiff_t, UnsignedShort), +meaning the actual view gets created only later when passed to a @ref MeshData +instance with a concrete vertex data array. This is useful mainly to avoid +pointer patching during data serialization, but also for example when vertex +layout is static (and thus can be defined at compile time), but the actual data +is allocated / populated at runtime. @snippet MagnumTrade.cpp MeshAttributeData-usage-offset-only -Offset-only attributes return @cpp true @ce for @ref isOffsetOnly(). Note that -@ref MeshTools algorithms generally don't accept offset-only -@ref MeshAttributeData instances except when passed through a @ref MeshData, as -for a standalone offset-only @ref MeshAttributeData it's impossible to know -what data it points to. +See @ref Trade-MeshData-populating-non-owned "the corresponding MeshData documentation" +for a complete usage example. Offset-only attributes return @cpp true @ce for +@ref isOffsetOnly(). Note that @ref MeshTools algorithms generally don't accept +offset-only @ref MeshAttributeData instances except when passed through a +@ref MeshData, as for a standalone offset-only @ref MeshAttributeData it's +impossible to know what data it points to. @section Trade-MeshAttributeData-custom-vertex-format Custom vertex formats @@ -696,7 +699,9 @@ class MAGNUM_TRADE_EXPORT MeshAttributeData { Useful when you have the attribute definitions statically defined (for example when the vertex data themselves are already defined at compile time) and don't -want to allocate just to pass those to @ref MeshData. +want to allocate just to pass those to @ref MeshData. See documentation about +@ref Trade-MeshData-populating "populating a MeshData instance" for more +information. */ Containers::Array MAGNUM_TRADE_EXPORT meshAttributeDataNonOwningArray(Containers::ArrayView view); @@ -706,8 +711,8 @@ Containers::Array MAGNUM_TRADE_EXPORT meshAttributeDataNonOwn Provides access to mesh vertex and index data, together with additional 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. +returned from @ref AbstractImporter::mesh(), from particular functions in +the @ref Primitives library as well as from various @ref MeshTools algorithms. @section Trade-MeshData-usage-compile Quick usage with MeshTools::compile() @@ -837,15 +842,32 @@ 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 @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: +@subsection Trade-MeshData-populating-non-owned Non-owned instances and static vertex layouts + +In some cases you may want the @ref MeshData instance to only refer to external +data without taking ownership, for example with a memory-mapped file, global +data etc. For that, instead of moving in +@relativeref{Corrade,Containers::Array} instances, pass @ref DataFlags +describing data mutability and ownership together with +@relativeref{Corrade,Containers::ArrayView} instances to the +@ref MeshData(MeshPrimitive, DataFlags, Containers::ArrayView, const MeshIndexData&, DataFlags, Containers::ArrayView, Containers::Array&&, UnsignedInt, const void*) +constructor. The following snippet is 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 +There are also other constructor overloads allowing you to mix and match owned +vertex data with non-owned index data and vice versa. The @ref MeshAttributeData +list is still implicitly allocated in the above case, but it can also be +defined externally and referenced via @ref meshAttributeDataNonOwningArray() +instead if desired. Finally, if the vertex layout is constant but the actual +data is allocated / populated at runtime, the @ref MeshAttributeData instances +can be defined in a global array as offset-only: + +@snippet MagnumTrade.cpp MeshData-populating-offset-only + +See also the @ref Trade-MeshAttributeData-usage-offset-only "corresponding MeshAttributeData documentation for offset-only fields". + @subsection Trade-MeshData-populating-custom Custom mesh attributes To allow for greater flexibility, a @ref MeshData instance can describe not @@ -870,7 +892,6 @@ you can also supply implementation-specific values that are not available in the generic @relativeref{Magnum,MeshPrimitive} enum, similarly see also @ref Trade-MeshAttributeData-custom-vertex-format for details on implementation-specific @ref VertexFormat values. -@see @ref AbstractImporter::mesh() */ class MAGNUM_TRADE_EXPORT MeshData { public: @@ -896,14 +917,20 @@ class MAGNUM_TRADE_EXPORT MeshData { * @param importerState Importer-specific state * * The @p indices are expected to point to a sub-range of @p indexData. + * For a non-indexed mesh either pass default-constructed + * @ref indexData and @p indices arguments, or use the + * @ref MeshData(MeshPrimitive, Containers::Array&&, Containers::Array&&, UnsignedInt, const void*) + * constructor. + * * The @p attributes are expected to reference (sparse) sub-ranges of * @p vertexData. Particular attributes can have additional * restrictions, see documentation of @ref MeshAttribute values for * more information. If the mesh has no attributes, the @p indices are - * expected to be valid (but can be empty). If you want to create an - * attribute-less non-indexed mesh, use - * @ref MeshData(MeshPrimitive, UnsignedInt, const void*) to specify - * desired vertex count. + * expected to be valid (but can be empty), you can also use the + * @ref MeshData(MeshPrimitive, Containers::Array&&, const MeshIndexData&, UnsignedInt, const void*) + * constructor in that case. If you want to create an attribute-less + * non-indexed mesh, use @ref MeshData(MeshPrimitive, UnsignedInt, const void*) + * instead. * * The @ref indexDataFlags() / @ref vertexDataFlags() are implicitly * set to a combination of @ref DataFlag::Owned and @@ -937,6 +964,15 @@ class MAGNUM_TRADE_EXPORT MeshData { * data. The @p indexDataFlags / @p vertexDataFlags parameters can * contain @ref DataFlag::Mutable to indicate the external data can be * modified, and are expected to *not* have @ref DataFlag::Owned set. + * + * Use @ref MeshData(MeshPrimitive, DataFlags, Containers::ArrayView, const MeshIndexData&, Containers::Array&&, Containers::Array&&, UnsignedInt, const void*) + * to create a mesh with only index data non-owned and + * @ref MeshData(MeshPrimitive, Containers::Array&&, const MeshIndexData&, DataFlags, Containers::ArrayView, Containers::Array&&, UnsignedInt, const void*) + * to create a mesh with only vertex data non-owned. There's also a + * @ref MeshData(MeshPrimitive, DataFlags, Containers::ArrayView, Containers::Array&&, UnsignedInt, const void*) + * convenience overload for non-indexed meshes with non-owned vertex + * data and @ref MeshData(MeshPrimitive, DataFlags, Containers::ArrayView, const MeshIndexData&, UnsignedInt, const void*) + * for attribute-less meshes with non-owned index data. */ explicit MeshData(MeshPrimitive primitive, DataFlags indexDataFlags, Containers::ArrayView indexData, const MeshIndexData& indices, DataFlags vertexDataFlags, Containers::ArrayView vertexData, Containers::Array&& attributes, UnsignedInt vertexCount = ImplicitVertexCount, const void* importerState = nullptr) noexcept; @@ -965,6 +1001,7 @@ class MAGNUM_TRADE_EXPORT MeshData { * have @ref DataFlag::Owned set. The @ref vertexDataFlags() are * implicitly set to a combination of @ref DataFlag::Owned and * @ref DataFlag::Mutable. + * @see @ref MeshData(MeshPrimitive, DataFlags, Containers::ArrayView, const MeshIndexData&, DataFlags, Containers::ArrayView, Containers::Array&&, UnsignedInt, const void*) */ explicit MeshData(MeshPrimitive primitive, DataFlags indexDataFlags, Containers::ArrayView indexData, const MeshIndexData& indices, Containers::Array&& vertexData, Containers::Array&& attributes, UnsignedInt vertexCount = ImplicitVertexCount, const void* importerState = nullptr) noexcept; @@ -993,6 +1030,7 @@ class MAGNUM_TRADE_EXPORT MeshData { * have @ref DataFlag::Owned set. The @ref indexDataFlags() are * implicitly set to a combination of @ref DataFlag::Owned and * @ref DataFlag::Mutable. + * @see @ref MeshData(MeshPrimitive, DataFlags, Containers::ArrayView, const MeshIndexData&, DataFlags, Containers::ArrayView, Containers::Array&&, UnsignedInt, const void*) */ explicit MeshData(MeshPrimitive primitive, Containers::Array&& indexData, const MeshIndexData& indices, DataFlags vertexDataFlags, Containers::ArrayView vertexData, Containers::Array&& attributes, UnsignedInt vertexCount = ImplicitVertexCount, const void* importerState = nullptr) noexcept; @@ -1068,8 +1106,7 @@ class MAGNUM_TRADE_EXPORT MeshData { * with default-constructed @p vertexData and @p attributes arguments. * The @p indices are expected to be valid (but can be empty). If you * want to create an attribute-less non-indexed mesh, use - * @ref MeshData(MeshPrimitive, UnsignedInt, const void*) to specify - * desired vertex count. + * @ref MeshData(MeshPrimitive, UnsignedInt, const void*) instead. * * The @ref indexDataFlags() are implicitly set to a combination of * @ref DataFlag::Owned and @ref DataFlag::Mutable. For consistency, diff --git a/src/Magnum/Trade/SceneData.h b/src/Magnum/Trade/SceneData.h index 7dc81316d..ca2d2adef 100644 --- a/src/Magnum/Trade/SceneData.h +++ b/src/Magnum/Trade/SceneData.h @@ -817,20 +817,22 @@ Alternatively, you can pass typeless @cpp const void @ce or 2D views and supply @subsection Trade-SceneFieldData-usage-offset-only Offset-only field data -If the actual field / object data location is not known yet, the instance can -be created as "offset-only", meaning the actual view gets created only later -when passed to a @ref SceneData instance with a concrete data array. This is -useful mainly to avoid pointer patching during data serialization, less so when -the data layout is static (and thus can be defined at compile time), but the -actual data is allocated / populated at runtime: +If the actual field / mapping data location is not known yet, the instance can +be created as "offset-only" using @ref SceneFieldData(SceneField, std::size_t, SceneMappingType, std::size_t, std::ptrdiff_t, SceneFieldType, std::size_t, std::ptrdiff_t, UnsignedShort, SceneFieldFlags) +and related constructor overloads, meaning the actual views get created only +later when passed to a @ref SceneData instance with a concrete data array. This +is useful mainly to avoid pointer patching during data serialization, but also +for example when the data layout is static (and thus can be defined at compile +time), but the actual data is allocated / populated at runtime. @snippet MagnumTrade.cpp SceneFieldData-usage-offset-only -Offset-only fields are marked with @ref SceneFieldFlag::OffsetOnly in -@ref flags(). Note that @ref SceneTools algorithms generally don't accept -offset-only @ref SceneFieldData instances except when passed through a -@ref SceneData, as for a standalone offset-only @ref SceneFieldData it's -impossible to know what data it points to. +See @ref Trade-SceneData-populating-non-owned "the corresponding SceneData documentation" +for a complete usage example. Offset-only fields are marked with +@ref SceneFieldFlag::OffsetOnly in @ref flags(). Note that @ref SceneTools +algorithms generally don't accept offset-only @ref SceneFieldData instances +except when passed through a @ref SceneData, as for a standalone offset-only +@ref SceneFieldData it's impossible to know what data it points to. @subsection Trade-SceneFieldData-usage-object-mapping Ordered and implicit object mapping @@ -1196,8 +1198,7 @@ class MAGNUM_TRADE_EXPORT SceneFieldData { * @param mappingType Object mapping type * @param mappingOffset Object mapping data offset * @param mappingStride Object mapping data stride - * @param fieldType Field type. @ref SceneFieldType::Bit and - * `SceneFieldType::String*` values are not allowed here. + * @param fieldType Field type * @param fieldOffset Field data offset * @param fieldStride Field data stride * @param fieldArraySize Field array size. Use @cpp 0 @ce for @@ -1217,6 +1218,13 @@ class MAGNUM_TRADE_EXPORT SceneFieldData { * @p fieldType / @p fieldArraySize checks against @p fieldStride can * be done. You're encouraged to use the @ref SceneFieldData(SceneField, SceneMappingType, const Containers::StridedArrayView1D&, SceneFieldType, const Containers::StridedArrayView1D&, UnsignedShort, SceneFieldFlags) * constructor if you want additional safeguards. + * + * @ref SceneFieldType::Bit and `SceneFieldType::String*` values are + * not allowed in @p fieldType. For offset-only bit fields use the + * @ref SceneFieldData(SceneField, std::size_t, SceneMappingType, std::size_t, std::ptrdiff_t, std::size_t, std::size_t, std::ptrdiff_t, UnsignedShort, SceneFieldFlags) + * constructor instead, for offset-only string fields use + * @ref SceneFieldData(SceneField, std::size_t, SceneMappingType, std::size_t, std::ptrdiff_t, std::size_t, SceneFieldType, std::size_t, std::ptrdiff_t, SceneFieldFlags) + * instead. * @see @ref flags(), @ref fieldArraySize() const, * @ref mappingData(Containers::ArrayView) const, * @ref fieldData(Containers::ArrayView) const @@ -1257,7 +1265,8 @@ class MAGNUM_TRADE_EXPORT SceneFieldData { * You're encouraged to use the @ref SceneFieldData(SceneField, SceneMappingType, const Containers::StridedArrayView1D&, const Containers::StridedBitArrayView1D&, SceneFieldFlags) * or @ref SceneFieldData(SceneField, SceneMappingType, const Containers::StridedArrayView1D&, const Containers::StridedBitArrayView2D&, SceneFieldFlags) * constructors if you want additional safeguards. - * @see @ref flags(), + * @see @ref SceneFieldData(SceneField, std::size_t, SceneMappingType, std::size_t, std::ptrdiff_t, SceneFieldType, std::size_t, std::ptrdiff_t, UnsignedShort, SceneFieldFlags), + * @ref flags(), * @ref mappingData(Containers::ArrayView) const, * @ref fieldData(Containers::ArrayView) const */ @@ -1299,7 +1308,8 @@ class MAGNUM_TRADE_EXPORT SceneFieldData { * @p fieldType checks against @p fieldStride can be done. You're * encouraged to use the @ref SceneFieldData(SceneField, SceneMappingType, const Containers::StridedArrayView1D&, SceneFieldType, const Containers::StridedArrayView1D&, UnsignedShort, SceneFieldFlags) * constructor if you want additional safeguards. - * @see @ref flags(), + * @see @ref SceneFieldData(SceneField, std::size_t, SceneMappingType, std::size_t, std::ptrdiff_t, SceneFieldType, std::size_t, std::ptrdiff_t, UnsignedShort, SceneFieldFlags), + * @ref flags(), * @ref mappingData(Containers::ArrayView) const, * @ref fieldData(Containers::ArrayView) const */ @@ -1523,7 +1533,8 @@ Containers::Array MAGNUM_TRADE_EXPORT sceneFieldDataNonOwningArr Contains scene node hierarchy, transformations, resource assignment as well as any other data associated with the scene. Populated instances of this class are -returned from @ref AbstractImporter::scene(). +returned from @ref AbstractImporter::scene() as well as from various +@ref SceneTools algorithms. @section Trade-SceneData-representation Data representation and terminology @@ -1745,6 +1756,31 @@ representation that matches your use case best, with fields interleaved together or not. See also the @ref SceneFieldData class documentation for additional ways how to specify and annotate the data. +@subsection Trade-SceneData-populating-non-owned Non-owned instances and static data layouts + +In some cases you may want the @ref SceneData instance to only refer to +external data without taking ownership, for example with a memory-mapped file, +global data etc. For that, instead of moving in an +@relativeref{Corrade,Containers::Array}, pass @ref DataFlags describing data +mutability and ownership together with an +@relativeref{Corrade,Containers::ArrayView} to the +@ref SceneData(SceneMappingType, UnsignedLong, DataFlags, Containers::ArrayView, Containers::Array&&, const void*) +constructor: + +@snippet MagnumTrade.cpp SceneData-populating-non-owned + +The @ref SceneFieldData list is still implicitly allocated in the above case, +but it can also be defined externally and referenced via +@ref sceneFieldDataNonOwningArray() instead if desired. Finally, if the data +layout is constant but the actual data is allocated / populated at runtime, the +@ref SceneFieldData instances can be defined in a global array as offset-only +and then subsequently referenced from a @ref SceneData with a concrete data +array: + +@snippet MagnumTrade.cpp SceneData-populating-offset-only + +See also the @ref Trade-SceneFieldData-usage-offset-only "corresponding SceneFieldData documentation for offset-only fields". + @subsection Trade-SceneData-populating-custom Custom scene fields and non-node objects Let's say that, in addition to the node hierarchy from above, our scene @@ -1825,8 +1861,6 @@ While there's many options how to store the string, retrieving of any string @ref SceneFieldType can be conveniently done using @ref fieldStrings(): @snippet MagnumTrade.cpp SceneData-populating-strings-retrieve - -@see @ref AbstractImporter::scene() */ class MAGNUM_TRADE_EXPORT SceneData { public: