Magnum::Trade::MeshData class new in 2020.06

Mesh data.

Provides access to mesh vertex and index data, together with additional information such as primitive type. Populated instances of this class are returned from AbstractImporter::mesh() and from particular functions in the Primitives library.

Quick usage with MeshTools::compile()

If all you want is to create a GL::Mesh that can be rendered by builtin shaders, a simple yet efficient way is to use MeshTools::compile():

Trade::MeshData data = ;

GL::Mesh mesh = MeshTools::compile(data);

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.

Basic usage

The second simplest usage is accessing attributes through the convenience functions positions2DAsArray(), positions3DAsArray(), tangentsAsArray(), bitangentsAsArray(), normalsAsArray(), tangentsAsArray(), textureCoordinates2DAsArray(), colorsAsArray() and objectIdsAsArray(). You're expected to check for attribute presence first with either hasAttribute() (or attributeCount(MeshAttribute) const, as there can be multiple sets of texture coordinates, for example). If you are creating a GL::Mesh, the usual path forward is then to MeshTools::interleave() attributes of interest, upload them to a GL::Buffer and configure attribute binding for the mesh.

The mesh can be also indexed, in which case the index buffer is exposed through indicesAsArray().

/* Check that we have at least positions and normals */
GL::Mesh mesh{data.primitive()};
if(!data.hasAttribute(Trade::MeshAttribute::Position) ||
   !data.hasAttribute(Trade::MeshAttribute::Normal))
    Fatal{} << "Oh well";

/* Interleave vertex data */
GL::Buffer vertices;
vertices.setData(MeshTools::interleave(data.positions3DAsArray(),
                                       data.normalsAsArray()));
mesh.addVertexBuffer(std::move(vertices), 0,
    Shaders::PhongGL::Position{}, Shaders::PhongGL::Normal{});

/* Set up an index buffer, if the mesh is indexed */
if(data.isIndexed()) {
    GL::Buffer indices;
    indices.setData(data.indicesAsArray());
    mesh.setIndexBuffer(std::move(indices), 0, MeshIndexType::UnsignedInt)
        .setCount(data.indexCount());
} else mesh.setCount(data.vertexCount());

Advanced usage

The positions2DAsArray(), ... functions shown above always return a newly-allocated Containers::Array instance in a well-defined canonical type. While that's convenient and fine at a smaller scale, 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 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 GL::DynamicAttribute accepts also a pair of GL::Attribute defined by the shader and the actual VertexFormat, figuring out the GL-specific properties such as component count or element data type for you:

/* Upload the original packed vertex data */
GL::Buffer vertices;
vertices.setData(data.vertexData());

/* Set up the position and normal attributes */
mesh.addVertexBuffer(vertices,
    data.attributeOffset(Trade::MeshAttribute::Position),
    data.attributeStride(Trade::MeshAttribute::Position),
    GL::DynamicAttribute{Shaders::PhongGL::Position{},
        data.attributeFormat(Trade::MeshAttribute::Position)});
mesh.addVertexBuffer(vertices,
    data.attributeOffset(Trade::MeshAttribute::Normal),
    data.attributeStride(Trade::MeshAttribute::Normal),
    GL::DynamicAttribute{Shaders::PhongGL::Normal{},
        data.attributeFormat(Trade::MeshAttribute::Normal)});

/* Upload the original packed index data */
if(data.isIndexed()) {
    GL::Buffer indices;
    indices.setData(data.indexData());
    mesh.setIndexBuffer(std::move(indices), 0, data.indexType())
        .setCount(data.indexCount());
} else mesh.setCount(data.vertexCount());

This approach is especially useful when dealing with custom attributes. See also 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.

Mutable data access

The interfaces implicitly provide const views on the contained index and vertex data through the indexData(), vertexData(), indices() and attribute() accessors. This is done because in general case the data can also refer to a memory-mapped file or constant memory. In cases when it's desirable to modify the data in-place, there's the mutableIndexData(), mutableVertexData(), mutableIndices() and mutableAttribute() set of functions. To use these, you need to check that the data are mutable using indexDataFlags() or vertexDataFlags() first, and if not then you may want to make a mutable copy first using MeshTools::owned(). The following snippet applies a transformation to the mesh positions:

/* Check prerequisites */
if(!(data.vertexDataFlags() & Trade::DataFlag::Mutable) ||
   !data.hasAttribute(Trade::MeshAttribute::Position) ||
   data.attributeFormat(Trade::MeshAttribute::Position) != VertexFormat::Vector3)
    Fatal{} << "Oh well";

/* Scale the mesh two times */
MeshTools::transformPointsInPlace(Matrix4::scaling(Vector3{2.0f}),
    data.mutableAttribute<Vector3>(Trade::MeshAttribute::Position));

If the transformation includes a rotation or non-uniform scaling, you may want to do a similar operation with normals and tangents as well.

Special data layouts

The class is able to represent data layouts beyond what's supported by common GPU vertex pipelines, in particular:

  • attributes with zero stride (a single value repeated for all vertices),
  • attributes with negative stride (causing the attribute data to be read in reverse order),
  • indices in a non-contiguous array (strided, similar to attributes).

These are allowed in order to support certain special cases where it would otherwise be needed to perform a manual and potentially expensive data repacking operation before putting them in a MeshData. Unless explicitly stated otherwise, all Magnum APIs returning a MeshData (such as the Primitives library or various importer plugins) don't make use of those advanced data layout features; and conversely all Magnum APIs taking a MeshData are aware of such features and can handle them approriately.

When passing mesh data to the GPU, the MeshTools::compile() utility will check and expect that only GPU-compatible layout features are used. However, when configuring meshes directly like shown in the Advanced usage chapter above, you may want to check the constraints explicitly before passing the values over.

if(data.attributeStride(Trade::MeshAttribute::Position) <= 0 ||
   data.attributeStride(Trade::MeshAttribute::Normal) <= 0 ||
   (data.isIndexed() && !data.indices().isContiguous()))
    Fatal{} << "Uh oh";

// Now it's safe to use the Position and Normal attributes and the index buffer
// in a GPU mesh

In order to convert a mesh with a special data layout to something the GPU vertex pipeline is able to consume, MeshTools::interleave() can be used. If you pass neither MeshTools::InterleaveFlag::PreserveInterleavedAttributes nor MeshTools::InterleaveFlag::PreserveStridedIndices, it will interleave all attributes together, regardless of what stride they had originally, and repack the indices into a contiguous buffer as well. Note that, however, it won't be able to work with a custom MeshIndexType or VertexFormat. In that case, it's your responsibility to know what's actually in the mesh data and how to handle it.

Populating an instance

A MeshData instance by default takes over the ownership of an Containers::Array containing the vertex / index data together with a MeshIndexData instance and a list of 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:

struct Vertex {
    Vector3 position;
    Vector4 color;
};

Containers::Array<char> indexData{indexCount*sizeof(UnsignedShort)};
Containers::Array<char> vertexData{vertexCount*sizeof(Vertex)};

auto vertices = Containers::arrayCast<const Vertex>(vertexData);
auto indices = Containers::arrayCast<const UnsignedShort>(indexData);

Trade::MeshData data{MeshPrimitive::Triangles,
    std::move(indexData), Trade::MeshIndexData{indices},
    std::move(vertexData), {
        Trade::MeshAttributeData{Trade::MeshAttribute::Position,
            Containers::StridedArrayView1D<const Vector3>{vertices,
                &vertices[0].position, vertexCount, sizeof(Vertex)}},
        Trade::MeshAttributeData{Trade::MeshAttribute::Color,
            Containers::StridedArrayView1D<const Vector4>{vertices,
                &vertices[0].color, vertexCount, sizeof(Vertex)}}
    }};

In cases where you want the 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 Containers::Array you pass DataFlags describing if the data is mutable or not together with an Containers::ArrayView. A variant of the above where the index data is constant and vertex data mutable, both referenced externally:

const UnsignedShort indices[] {
    0, 1, 2,
    2, 1, 3,
    3, 4, 5,
    5, 4, 6
};
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<const Vector3>{
                Containers::arrayView(vertices), &vertices[0].position,
                Containers::arraySize(vertices), sizeof(Vertex)}},
        Trade::MeshAttributeData{Trade::MeshAttribute::Color,
            Containers::StridedArrayView1D<const Vector4>{
                Containers::arrayView(vertices), &vertices[0].color,
                Containers::arraySize(vertices), sizeof(Vertex)}}
    }};

Custom mesh attributes

To allow for greater flexibility, a MeshData instance can describe not just attributes that are predefined in the MeshAttribute enum, but also custom attributes, created with meshAttributeCustom(). For example, the snippet below describes a custom per-face structure that exposes faces as higher-order polygons combining multiple triangles together —in this case, each face has an array of 15 IDs, which is exposed as a 2D array:

/* Each face can consist of 15 triangles at most, triangleCount says how many
   indices in triangleIds are valid */
struct Face {
    UnsignedShort triangleIds[15];
    UnsignedByte triangleCount;
};

constexpr Trade::MeshAttribute TriangleIds = Trade::meshAttributeCustom(0x01);
constexpr Trade::MeshAttribute TriangleCount = Trade::meshAttributeCustom(0x02);

Containers::Array<char> vertexData;
auto faces = Containers::arrayCast<const Face>(vertexData);

Trade::MeshData data{MeshPrimitive::Faces, std::move(vertexData), {
    Trade::MeshAttributeData{TriangleIds,
        Containers::StridedArrayView2D<const UnsignedShort>{faces,
            &faces[0].triangleIds[0],
            {faces.size(), 15},
            {sizeof(Face), sizeof(UnsignedShort)}}},
    Trade::MeshAttributeData{TriangleCount,
        Containers::StridedArrayView1D<const UnsignedByte>{faces,
            &faces[0].triangleCount, faces.size(), sizeof(Face)}}
}};

Later, the (array) attributes can be retrieved back using the same custom identifiers — note the use of [] to get back a 2D array again:

Containers::StridedArrayView2D<const UnsignedShort> triangleIds =
    data.attribute<UnsignedShort[]>(TriangleIds);
Containers::StridedArrayView1D<const UnsignedByte> triangleCounts =
    data.attribute<UnsignedByte>(TriangleCount);

When a custom attribute is exposed through AbstractImporter, it's possible to map custom MeshAttribute values to human-readable string names using AbstractImporter::meshAttributeName() and AbstractImporter::meshAttributeForName(). Using meshPrimitiveWrap() you can also supply implementation-specific values that are not available in the generic MeshPrimitive enum, similarly see also Custom vertex formats for details on implementation-specific VertexFormat values.

Public types

enum (anonymous): UnsignedInt { ImplicitVertexCount = ~UnsignedInt{} }

Constructors, destructors, conversion operators

MeshData(MeshPrimitive primitive, Containers::Array<char>&& indexData, const MeshIndexData& indices, Containers::Array<char>&& vertexData, Containers::Array<MeshAttributeData>&& attributes, UnsignedInt vertexCount = ImplicitVertexCount, const void* importerState = nullptr) explicit noexcept
Construct an indexed mesh data.
MeshData(MeshPrimitive primitive, Containers::Array<char>&& indexData, const MeshIndexData& indices, Containers::Array<char>&& vertexData, std::initializer_list<MeshAttributeData> attributes, UnsignedInt vertexCount = ImplicitVertexCount, const void* importerState = nullptr) explicit
MeshData(MeshPrimitive primitive, DataFlags indexDataFlags, Containers::ArrayView<const void> indexData, const MeshIndexData& indices, DataFlags vertexDataFlags, Containers::ArrayView<const void> vertexData, Containers::Array<MeshAttributeData>&& attributes, UnsignedInt vertexCount = ImplicitVertexCount, const void* importerState = nullptr) explicit noexcept
Construct indexed mesh data with non-owned index and vertex data.
MeshData(MeshPrimitive primitive, DataFlags indexDataFlags, Containers::ArrayView<const void> indexData, const MeshIndexData& indices, DataFlags vertexDataFlags, Containers::ArrayView<const void> vertexData, std::initializer_list<MeshAttributeData> attributes, UnsignedInt vertexCount = ImplicitVertexCount, const void* importerState = nullptr) explicit
MeshData(MeshPrimitive primitive, DataFlags indexDataFlags, Containers::ArrayView<const void> indexData, const MeshIndexData& indices, Containers::Array<char>&& vertexData, Containers::Array<MeshAttributeData>&& attributes, UnsignedInt vertexCount = ImplicitVertexCount, const void* importerState = nullptr) explicit noexcept
Construct indexed mesh data with non-owned index data.
MeshData(MeshPrimitive primitive, DataFlags indexDataFlags, Containers::ArrayView<const void> indexData, const MeshIndexData& indices, Containers::Array<char>&& vertexData, std::initializer_list<MeshAttributeData> attributes, UnsignedInt vertexCount = ImplicitVertexCount, const void* importerState = nullptr) explicit
MeshData(MeshPrimitive primitive, Containers::Array<char>&& indexData, const MeshIndexData& indices, DataFlags vertexDataFlags, Containers::ArrayView<const void> vertexData, Containers::Array<MeshAttributeData>&& attributes, UnsignedInt vertexCount = ImplicitVertexCount, const void* importerState = nullptr) explicit noexcept
Construct indexed mesh data with non-owned vertex data.
MeshData(MeshPrimitive primitive, Containers::Array<char>&& indexData, const MeshIndexData& indices, DataFlags vertexDataFlags, Containers::ArrayView<const void> vertexData, std::initializer_list<MeshAttributeData> attributes, UnsignedInt vertexCount = ImplicitVertexCount, const void* importerState = nullptr) explicit
MeshData(MeshPrimitive primitive, Containers::Array<char>&& vertexData, Containers::Array<MeshAttributeData>&& attributes, UnsignedInt vertexCount = ImplicitVertexCount, const void* importerState = nullptr) explicit noexcept
Construct a non-indexed mesh data.
MeshData(MeshPrimitive primitive, Containers::Array<char>&& vertexData, std::initializer_list<MeshAttributeData> attributes, UnsignedInt vertexCount = ImplicitVertexCount, const void* importerState = nullptr) explicit
MeshData(MeshPrimitive primitive, DataFlags vertexDataFlags, Containers::ArrayView<const void> vertexData, Containers::Array<MeshAttributeData>&& attributes, UnsignedInt vertexCount = ImplicitVertexCount, const void* importerState = nullptr) explicit noexcept
Construct a non-owned non-indexed mesh data.
MeshData(MeshPrimitive primitive, DataFlags vertexDataFlags, Containers::ArrayView<const void> vertexData, std::initializer_list<MeshAttributeData> attributes, UnsignedInt vertexCount = ImplicitVertexCount, const void* importerState = nullptr) explicit
MeshData(MeshPrimitive primitive, Containers::Array<char>&& indexData, const MeshIndexData& indices, UnsignedInt vertexCount, const void* importerState = nullptr) explicit noexcept
Construct an attribute-less indexed mesh data.
MeshData(MeshPrimitive primitive, DataFlags indexDataFlags, Containers::ArrayView<const void> indexData, const MeshIndexData& indices, UnsignedInt vertexCount, const void* importerState = nullptr) explicit noexcept
Construct a non-owned attribute-less indexed mesh data.
MeshData(MeshPrimitive primitive, UnsignedInt vertexCount, const void* importerState = nullptr) explicit noexcept
Construct an index-less attribute-less mesh data.
MeshData(const MeshData&) deleted
Copying is not allowed.
MeshData(MeshData&&) noexcept
Move constructor.

Public functions

auto operator=(const MeshData&) -> MeshData& deleted
Copying is not allowed.
auto operator=(MeshData&&) -> MeshData& noexcept
Move assignment.
auto indexDataFlags() const -> DataFlags
Index data flags.
auto vertexDataFlags() const -> DataFlags
Vertex data flags.
auto primitive() const -> MeshPrimitive
Primitive.
auto indexData() const & -> Containers::ArrayView<const char>
Raw index data.
auto indexData() const && -> Containers::ArrayView<const char> deleted
Taking a view to a r-value instance is not allowed.
auto mutableIndexData() & -> Containers::ArrayView<char>
Mutable raw index data.
auto mutableIndexData() && -> Containers::ArrayView<char> deleted
Taking a view to a r-value instance is not allowed.
auto attributeData() const & -> Containers::ArrayView<const MeshAttributeData>
Raw attribute metadata.
auto attributeData() && -> Containers::ArrayView<const MeshAttributeData> deleted
Taking a view to a r-value instance is not allowed.
auto vertexData() const & -> Containers::ArrayView<const char>
Raw vertex data.
auto vertexData() const && -> Containers::ArrayView<const char> deleted
Taking a view to a r-value instance is not allowed.
auto mutableVertexData() & -> Containers::ArrayView<char>
Mutable raw vertex data.
auto mutableVertexData() && -> Containers::ArrayView<char> deleted
Taking a view to a r-value instance is not allowed.
auto isIndexed() const -> bool
Whether the mesh is indexed.
auto indexCount() const -> UnsignedInt
Index count.
auto indexType() const -> MeshIndexType
Index type.
auto indexOffset() const -> std::size_t
Index offset.
auto indexStride() const -> Short new in Git master
Index stride.
auto indices() const -> Containers::StridedArrayView2D<const char>
Mesh indices.
auto mutableIndices() -> Containers::StridedArrayView2D<char>
Mutable mesh indices.
template<class T>
auto indices() const -> Containers::StridedArrayView1D<const T>
Mesh indices in a concrete type.
template<class T>
auto mutableIndices() -> Containers::StridedArrayView1D<T>
Mutable mesh indices in a concrete type.
auto vertexCount() const -> UnsignedInt
Mesh vertex count.
auto attributeCount() const -> UnsignedInt
Attribute array count.
auto attributeData(UnsignedInt id) const -> MeshAttributeData
Raw attribute data.
auto attributeName(UnsignedInt id) const -> MeshAttribute
Attribute name.
auto attributeId(UnsignedInt id) const -> UnsignedInt new in Git master
Attribute ID in a set of attributes of the same name.
auto attributeFormat(UnsignedInt id) const -> VertexFormat
Attribute format.
auto attributeOffset(UnsignedInt id) const -> std::size_t
Attribute offset.
auto attributeStride(UnsignedInt id) const -> Short
Attribute stride.
auto attributeArraySize(UnsignedInt id) const -> UnsignedShort
Attribute array size.
auto hasAttribute(MeshAttribute name) const -> bool
Whether the mesh has given attribute.
auto attributeCount(MeshAttribute name) const -> UnsignedInt
Count of given named attribute.
auto findAttributeId(MeshAttribute name, UnsignedInt id = 0) const -> Containers::Optional<UnsignedInt> new in Git master
Find an absolute ID of a named attribute.
auto attributeId(MeshAttribute name, UnsignedInt id = 0) const -> UnsignedInt
Absolute ID of a named attribute.
auto attributeFormat(MeshAttribute name, UnsignedInt id = 0) const -> VertexFormat
Format of a named attribute.
auto attributeOffset(MeshAttribute name, UnsignedInt id = 0) const -> std::size_t
Offset of a named attribute.
auto attributeStride(MeshAttribute name, UnsignedInt id = 0) const -> Short
Stride of a named attribute.
auto attributeArraySize(MeshAttribute name, UnsignedInt id = 0) const -> UnsignedShort
Array size of a named attribute.
auto attribute(UnsignedInt id) const -> Containers::StridedArrayView2D<const char>
Data for given attribute.
auto mutableAttribute(UnsignedInt id) -> Containers::StridedArrayView2D<char>
Mutable data for given attribute.
template<class T, class = typename std::enable_if<!std::is_array<T>::value>::type>
auto attribute(UnsignedInt id) const -> Containers::StridedArrayView1D<const T>
Data for given attribute in a concrete type.
template<class T, class = typename std::enable_if<std::is_array<T>::value>::type>
auto attribute(UnsignedInt id) const -> Containers::StridedArrayView2D<const typename std::remove_extent<T>::type>
Data for given array attribute in a concrete type.
template<class T, class = typename std::enable_if<!std::is_array<T>::value>::type>
auto mutableAttribute(UnsignedInt id) -> Containers::StridedArrayView1D<T>
Mutable data for given attribute in a concrete type.
template<class T, class = typename std::enable_if<std::is_array<T>::value>::type>
auto mutableAttribute(UnsignedInt id) -> Containers::StridedArrayView2D<typename std::remove_extent<T>::type>
Mutable data for given array attribute in a concrete type.
auto attribute(MeshAttribute name, UnsignedInt id = 0) const -> Containers::StridedArrayView2D<const char>
Data for given named attribute.
auto mutableAttribute(MeshAttribute name, UnsignedInt id = 0) -> Containers::StridedArrayView2D<char>
Mutable data for given named attribute.
template<class T, class = typename std::enable_if<!std::is_array<T>::value>::type>
auto attribute(MeshAttribute name, UnsignedInt id = 0) const -> Containers::StridedArrayView1D<const T>
Data for given named attribute in a concrete type.
template<class T, class = typename std::enable_if<std::is_array<T>::value>::type>
auto attribute(MeshAttribute name, UnsignedInt id = 0) const -> Containers::StridedArrayView2D<const typename std::remove_extent<T>::type>
Data for given named array attribute in a concrete type.
template<class T, class = typename std::enable_if<!std::is_array<T>::value>::type>
auto mutableAttribute(MeshAttribute name, UnsignedInt id = 0) -> Containers::StridedArrayView1D<T>
Mutable data for given named attribute in a concrete type.
template<class T, class = typename std::enable_if<std::is_array<T>::value>::type>
auto mutableAttribute(MeshAttribute name, UnsignedInt id = 0) -> Containers::StridedArrayView2D<typename std::remove_extent<T>::type>
Mutable data for given named array attribute in a concrete type.
auto indicesAsArray() const -> Containers::Array<UnsignedInt>
Indices as 32-bit integers.
void indicesInto(const Containers::StridedArrayView1D<UnsignedInt>& destination) const
Positions as 32-bit integers into a pre-allocated view.
auto positions2DAsArray(UnsignedInt id = 0) const -> Containers::Array<Vector2>
Positions as 2D float vectors.
void positions2DInto(const Containers::StridedArrayView1D<Vector2>& destination, UnsignedInt id = 0) const
Positions as 2D float vectors into a pre-allocated view.
auto positions3DAsArray(UnsignedInt id = 0) const -> Containers::Array<Vector3>
Positions as 3D float vectors.
void positions3DInto(const Containers::StridedArrayView1D<Vector3>& destination, UnsignedInt id = 0) const
Positions as 3D float vectors into a pre-allocated view.
auto tangentsAsArray(UnsignedInt id = 0) const -> Containers::Array<Vector3>
Tangents as 3D float vectors.
void tangentsInto(const Containers::StridedArrayView1D<Vector3>& destination, UnsignedInt id = 0) const
Tangents as 3D float vectors into a pre-allocated view.
auto bitangentSignsAsArray(UnsignedInt id = 0) const -> Containers::Array<Float>
Bitangent signs as floats.
void bitangentSignsInto(const Containers::StridedArrayView1D<Float>& destination, UnsignedInt id = 0) const
Bitangent signs as floats into a pre-allocated view.
auto bitangentsAsArray(UnsignedInt id = 0) const -> Containers::Array<Vector3>
Bitangents as 3D float vectors.
void bitangentsInto(const Containers::StridedArrayView1D<Vector3>& destination, UnsignedInt id = 0) const
Bitangents as 3D float vectors into a pre-allocated view.
auto normalsAsArray(UnsignedInt id = 0) const -> Containers::Array<Vector3>
Normals as 3D float vectors.
void normalsInto(const Containers::StridedArrayView1D<Vector3>& destination, UnsignedInt id = 0) const
Normals as 3D float vectors into a pre-allocated view.
auto textureCoordinates2DAsArray(UnsignedInt id = 0) const -> Containers::Array<Vector2>
Texture coordinates as 2D float vectors.
void textureCoordinates2DInto(const Containers::StridedArrayView1D<Vector2>& destination, UnsignedInt id = 0) const
Texture coordinates as 2D float vectors into a pre-allocated view.
auto colorsAsArray(UnsignedInt id = 0) const -> Containers::Array<Color4>
Colors as RGBA floats.
void colorsInto(const Containers::StridedArrayView1D<Color4>& destination, UnsignedInt id = 0) const
Colors as RGBA floats into a pre-allocated view.
auto objectIdsAsArray(UnsignedInt id = 0) const -> Containers::Array<UnsignedInt>
Object IDs as 32-bit integers.
void objectIdsInto(const Containers::StridedArrayView1D<UnsignedInt>& destination, UnsignedInt id = 0) const
Object IDs as 32-bit integers into a pre-allocated view.
auto releaseIndexData() -> Containers::Array<char>
Release index data storage.
auto releaseAttributeData() -> Containers::Array<MeshAttributeData>
Release attribute data storage.
auto releaseVertexData() -> Containers::Array<char>
Release vertex data storage.
auto importerState() const -> const void*
Importer-specific state.

Enum documentation

enum Magnum::Trade::MeshData::(anonymous): UnsignedInt

Enumerators
ImplicitVertexCount

Implicit vertex count. When passed to a constructor, indicates that vertex count should be taken from attribute data views.

Function documentation

Magnum::Trade::MeshData::MeshData(MeshPrimitive primitive, Containers::Array<char>&& indexData, const MeshIndexData& indices, Containers::Array<char>&& vertexData, Containers::Array<MeshAttributeData>&& attributes, UnsignedInt vertexCount = ImplicitVertexCount, const void* importerState = nullptr) explicit noexcept

Construct an indexed mesh data.

Parameters
primitive Primitive
indexData Index data
indices Index data description
vertexData Vertex data
attributes Description of all vertex attribute data
vertexCount Vertex count. If set to ImplicitVertexCount, vertex count is taken from data views passed to attributes (in which case there has to be at least one).
importerState Importer-specific state

The indices are expected to point to a sub-range of indexData. The attributes are expected to reference (sparse) sub-ranges of vertexData. If the mesh has no attributes, the indices are expected to be valid (but can be empty). If you want to create an attribute-less non-indexed mesh, use MeshData(MeshPrimitive, UnsignedInt, const void*) to specify desired vertex count.

The indexDataFlags() / vertexDataFlags() are implicitly set to a combination of DataFlag::Owned and DataFlag::Mutable. For non-owned data use the MeshData(MeshPrimitive, DataFlags, Containers::ArrayView<const void>, const MeshIndexData&, DataFlags, Containers::ArrayView<const void>, Containers::Array<MeshAttributeData>&&, UnsignedInt, const void*) constructor or its variants instead.

Magnum::Trade::MeshData::MeshData(MeshPrimitive primitive, Containers::Array<char>&& indexData, const MeshIndexData& indices, Containers::Array<char>&& vertexData, std::initializer_list<MeshAttributeData> attributes, UnsignedInt vertexCount = ImplicitVertexCount, const void* importerState = nullptr) explicit

This is an overloaded member function, provided for convenience. It differs from the above function only in what argument(s) it accepts.

Magnum::Trade::MeshData::MeshData(MeshPrimitive primitive, DataFlags indexDataFlags, Containers::ArrayView<const void> indexData, const MeshIndexData& indices, DataFlags vertexDataFlags, Containers::ArrayView<const void> vertexData, Containers::Array<MeshAttributeData>&& attributes, UnsignedInt vertexCount = ImplicitVertexCount, const void* importerState = nullptr) explicit noexcept

Construct indexed mesh data with non-owned index and vertex data.

Parameters
primitive Primitive
indexDataFlags Index data flags
indexData View on index data
indices Index data description
vertexDataFlags Vertex data flags
vertexData View on vertex data
attributes Description of all vertex attribute data
vertexCount Vertex count. If set to ImplicitVertexCount, vertex count is taken from data views passed to attributes (in which case there has to be at least one).
importerState Importer-specific state

Compared to MeshData(MeshPrimitive, Containers::Array<char>&&, const MeshIndexData&, Containers::Array<char>&&, Containers::Array<MeshAttributeData>&&, UnsignedInt, const void*) creates an instance that doesn't own the passed vertex and index data. The indexDataFlags / vertexDataFlags parameters can contain DataFlag::Mutable to indicate the external data can be modified, and are expected to not have DataFlag::Owned set.

Magnum::Trade::MeshData::MeshData(MeshPrimitive primitive, DataFlags indexDataFlags, Containers::ArrayView<const void> indexData, const MeshIndexData& indices, DataFlags vertexDataFlags, Containers::ArrayView<const void> vertexData, std::initializer_list<MeshAttributeData> attributes, UnsignedInt vertexCount = ImplicitVertexCount, const void* importerState = nullptr) explicit

This is an overloaded member function, provided for convenience. It differs from the above function only in what argument(s) it accepts.

Magnum::Trade::MeshData::MeshData(MeshPrimitive primitive, DataFlags indexDataFlags, Containers::ArrayView<const void> indexData, const MeshIndexData& indices, Containers::Array<char>&& vertexData, Containers::Array<MeshAttributeData>&& attributes, UnsignedInt vertexCount = ImplicitVertexCount, const void* importerState = nullptr) explicit noexcept

Construct indexed mesh data with non-owned index data.

Parameters
primitive Primitive
indexDataFlags Index data flags
indexData View on index data
indices Index data description
vertexData Vertex data
attributes Description of all vertex attribute data
vertexCount Vertex count. If set to ImplicitVertexCount, vertex count is taken from data views passed to attributes (in which case there has to be at least one).
importerState Importer-specific state

Compared to MeshData(MeshPrimitive, Containers::Array<char>&&, const MeshIndexData&, Containers::Array<char>&&, Containers::Array<MeshAttributeData>&&, UnsignedInt, const void*) creates an instance that doesn't own the passed index data. The indexDataFlags parameter can contain DataFlag::Mutable to indicate the external data can be modified, and is expected to not have DataFlag::Owned set. The vertexDataFlags() are implicitly set to a combination of DataFlag::Owned and DataFlag::Mutable.

Magnum::Trade::MeshData::MeshData(MeshPrimitive primitive, DataFlags indexDataFlags, Containers::ArrayView<const void> indexData, const MeshIndexData& indices, Containers::Array<char>&& vertexData, std::initializer_list<MeshAttributeData> attributes, UnsignedInt vertexCount = ImplicitVertexCount, const void* importerState = nullptr) explicit

This is an overloaded member function, provided for convenience. It differs from the above function only in what argument(s) it accepts.

Magnum::Trade::MeshData::MeshData(MeshPrimitive primitive, Containers::Array<char>&& indexData, const MeshIndexData& indices, DataFlags vertexDataFlags, Containers::ArrayView<const void> vertexData, Containers::Array<MeshAttributeData>&& attributes, UnsignedInt vertexCount = ImplicitVertexCount, const void* importerState = nullptr) explicit noexcept

Construct indexed mesh data with non-owned vertex data.

Parameters
primitive Primitive
indexData Index data
indices Index data description
vertexDataFlags Vertex data flags
vertexData View on vertex data
attributes Description of all vertex attribute data
vertexCount Vertex count. If set to ImplicitVertexCount, vertex count is taken from data views passed to attributes (in which case there has to be at least one).
importerState Importer-specific state

Compared to MeshData(MeshPrimitive, Containers::Array<char>&&, const MeshIndexData&, Containers::Array<char>&&, Containers::Array<MeshAttributeData>&&, UnsignedInt, const void*) creates an instance that doesn't own the passed vertex data. The vertexDataFlags parameter can contain DataFlag::Mutable to indicate the external data can be modified, and is expected to not have DataFlag::Owned set. The indexDataFlags() are implicitly set to a combination of DataFlag::Owned and DataFlag::Mutable.

Magnum::Trade::MeshData::MeshData(MeshPrimitive primitive, Containers::Array<char>&& indexData, const MeshIndexData& indices, DataFlags vertexDataFlags, Containers::ArrayView<const void> vertexData, std::initializer_list<MeshAttributeData> attributes, UnsignedInt vertexCount = ImplicitVertexCount, const void* importerState = nullptr) explicit

This is an overloaded member function, provided for convenience. It differs from the above function only in what argument(s) it accepts.

Magnum::Trade::MeshData::MeshData(MeshPrimitive primitive, Containers::Array<char>&& vertexData, Containers::Array<MeshAttributeData>&& attributes, UnsignedInt vertexCount = ImplicitVertexCount, const void* importerState = nullptr) explicit noexcept

Construct a non-indexed mesh data.

Parameters
primitive Primitive
vertexData Vertex data
attributes Description of all vertex attribute data
vertexCount Vertex count. If set to ImplicitVertexCount, vertex count is taken from data views passed to attributes (in which case there has to be at least one).
importerState Importer-specific state

Same as calling MeshData(MeshPrimitive, Containers::Array<char>&&, const MeshIndexData&, Containers::Array<char>&&, Containers::Array<MeshAttributeData>&&, UnsignedInt, const void*) with default-constructed indexData and indices arguments.

The vertexDataFlags() are implicitly set to a combination of DataFlag::Owned and DataFlag::Mutable. For consistency, the indexDataFlags() are implicitly set to a combination of DataFlag::Owned and DataFlag::Mutable, even though there isn't any data to own or to mutate. For non-owned data use the MeshData(MeshPrimitive, DataFlags, Containers::ArrayView<const void>, Containers::Array<MeshAttributeData>&&, UnsignedInt, const void*) constructor instead.

Magnum::Trade::MeshData::MeshData(MeshPrimitive primitive, Containers::Array<char>&& vertexData, std::initializer_list<MeshAttributeData> attributes, UnsignedInt vertexCount = ImplicitVertexCount, const void* importerState = nullptr) explicit

This is an overloaded member function, provided for convenience. It differs from the above function only in what argument(s) it accepts.

Magnum::Trade::MeshData::MeshData(MeshPrimitive primitive, DataFlags vertexDataFlags, Containers::ArrayView<const void> vertexData, Containers::Array<MeshAttributeData>&& attributes, UnsignedInt vertexCount = ImplicitVertexCount, const void* importerState = nullptr) explicit noexcept

Construct a non-owned non-indexed mesh data.

Parameters
primitive Primitive
vertexDataFlags Vertex data flags
vertexData View on vertex data
attributes Description of all vertex attribute data
vertexCount Vertex count. If set to ImplicitVertexCount, vertex count is taken from data views passed to attributes (in which case there has to be at least one).
importerState Importer-specific state

Compared to MeshData(MeshPrimitive, Containers::Array<char>&&, Containers::Array<MeshAttributeData>&&, UnsignedInt, const void*) creates an instance that doesn't own the passed data. The vertexDataFlags parameter can contain DataFlag::Mutable to indicate the external data can be modified, and is expected to not have DataFlag::Owned set. For consistency, the indexDataFlags() are implicitly set to a combination of DataFlag::Owned and DataFlag::Mutable, even though there isn't any data to own or to mutate.

Magnum::Trade::MeshData::MeshData(MeshPrimitive primitive, DataFlags vertexDataFlags, Containers::ArrayView<const void> vertexData, std::initializer_list<MeshAttributeData> attributes, UnsignedInt vertexCount = ImplicitVertexCount, const void* importerState = nullptr) explicit

This is an overloaded member function, provided for convenience. It differs from the above function only in what argument(s) it accepts.

Magnum::Trade::MeshData::MeshData(MeshPrimitive primitive, Containers::Array<char>&& indexData, const MeshIndexData& indices, UnsignedInt vertexCount, const void* importerState = nullptr) explicit noexcept

Construct an attribute-less indexed mesh data.

Parameters
primitive Primitive
indexData Index data
indices Index data description
vertexCount Vertex count. Passing ImplicitVertexCount is not allowed in this overload.
importerState Importer-specific state

Same as calling MeshData(MeshPrimitive, Containers::Array<char>&&, const MeshIndexData&, Containers::Array<char>&&, Containers::Array<MeshAttributeData>&&, UnsignedInt, const void*) with default-constructed vertexData and attributes arguments. The indices are expected to be valid (but can be empty). If you want to create an attribute-less non-indexed mesh, use MeshData(MeshPrimitive, UnsignedInt, const void*) to specify desired vertex count.

The indexDataFlags() are implicitly set to a combination of DataFlag::Owned and DataFlag::Mutable. For consistency, the vertexDataFlags() are implicitly set to a combination of DataFlag::Owned and DataFlag::Mutable, even though there isn't any data to own or to mutate. For non-owned data use the MeshData(MeshPrimitive, DataFlags, Containers::ArrayView<const void>, const MeshIndexData&, UnsignedInt, const void*) constructor instead.

Magnum::Trade::MeshData::MeshData(MeshPrimitive primitive, DataFlags indexDataFlags, Containers::ArrayView<const void> indexData, const MeshIndexData& indices, UnsignedInt vertexCount, const void* importerState = nullptr) explicit noexcept

Construct a non-owned attribute-less indexed mesh data.

Parameters
primitive Primitive
indexDataFlags Index data flags
indexData View on index data
indices Index data description
vertexCount Vertex count. Passing ImplicitVertexCount is not allowed in this overload.
importerState Importer-specific state

Compared to MeshData(MeshPrimitive, Containers::Array<char>&&, const MeshIndexData&, UnsignedInt, const void*) creates an instance that doesn't own the passed data. The indexDataFlags parameter can contain DataFlag::Mutable to indicate the external data can be modified, and is expected to not have DataFlag::Owned set. For consistency, the vertexDataFlags() are implicitly set to a combination of DataFlag::Owned and DataFlag::Mutable, even though there isn't any data to own or to mutate.

Magnum::Trade::MeshData::MeshData(MeshPrimitive primitive, UnsignedInt vertexCount, const void* importerState = nullptr) explicit noexcept

Construct an index-less attribute-less mesh data.

Parameters
primitive Primitive
vertexCount Vertex count. Passing ImplicitVertexCount is not allowed in this overload.
importerState Importer-specific state

Useful in case the drawing is fully driven by a shader. For consistency, the indexDataFlags() / vertexDataFlags() are implicitly set to a combination of DataFlag::Owned and DataFlag::Mutable, even though there isn't any data to own or to mutate.

DataFlags Magnum::Trade::MeshData::indexDataFlags() const

Index data flags.

DataFlags Magnum::Trade::MeshData::vertexDataFlags() const

Vertex data flags.

Containers::ArrayView<const char> Magnum::Trade::MeshData::indexData() const &

Raw index data.

Returns nullptr if the mesh is not indexed.

Containers::ArrayView<char> Magnum::Trade::MeshData::mutableIndexData() &

Mutable raw index data.

Like indexData(), but returns a non-const view. Expects that the mesh is mutable.

Containers::ArrayView<const MeshAttributeData> Magnum::Trade::MeshData::attributeData() const &

Raw attribute metadata.

Returns the raw data that are used as a base for all attribute*() accessors, or nullptr if the mesh has no attributes. In most cases you don't want to access those directly, but rather use the attribute(), attributeName(), attributeFormat(), attributeOffset(), attributeStride() etc. accessors. Compared to those and to attributeData(UnsignedInt) const, the MeshAttributeData instances returned by this function may have different data pointers, and some of them might be offset-only — use this function only if you really know what are you doing.

Containers::ArrayView<const char> Magnum::Trade::MeshData::vertexData() const &

Raw vertex data.

Contains data for all vertex attributes. Returns nullptr if the mesh has no attributes.

Containers::ArrayView<char> Magnum::Trade::MeshData::mutableVertexData() &

Mutable raw vertex data.

Like vertexData(), but returns a non-const view. Expects that the mesh is mutable.

UnsignedInt Magnum::Trade::MeshData::indexCount() const

Index count.

Count of elements in the indices() array. Expects that the mesh is indexed; returned value is always non-zero. See also vertexCount() which returns count of elements in every attribute() array, and attributeCount() which returns count of different per-vertex attribute arrays.

MeshIndexType Magnum::Trade::MeshData::indexType() const

Index type.

Expects that the mesh is indexed.

std::size_t Magnum::Trade::MeshData::indexOffset() const

Index offset.

Byte offset of the first index from the beginning of the indexData(), or a byte difference between pointers returned from indexData() and indices(). Expects that the mesh is indexed.

Short Magnum::Trade::MeshData::indexStride() const new in Git master

Index stride.

Stride between consecutive elements in the indexData() array. In rare cases the stride may be different from the index type size and even be zero or negative, such data layouts are however not commonly supported by GPU APIs.

Containers::StridedArrayView2D<const char> Magnum::Trade::MeshData::indices() const

Mesh indices.

For an indexed mesh, the second dimension represent the actual data type (its size is equal to type size for known MeshIndexType values, and to absolute indexStride() for implementation-specific values), even in case there's zero indices, and is guaranteed to be contiguous. For a non-indexed mesh, the returned view has a zero size in both dimensions. In rare cases the first dimension stride may be different from the index type size and even be zero or negative, such data layouts are however not commonly supported by GPU APIs.

Use the templated overload below to get the indices in a concrete type.

Containers::StridedArrayView2D<char> Magnum::Trade::MeshData::mutableIndices()

Mutable mesh indices.

Like indices() const, but returns a mutable view. Expects that the mesh is mutable.

template<class T>
Containers::StridedArrayView1D<const T> Magnum::Trade::MeshData::indices() const

Mesh indices in a concrete type.

Expects that the mesh is indexed and that T corresponds to indexType(). In rare cases the first dimension stride may be different from the index type size and even be zero or negative, such data layouts are however not commonly supported by GPU APIs. You can also use the non-templated indicesAsArray() accessor to get indices converted to a contiguous 32-bit array, but note that such operation involves extra allocation and data conversion.

template<class T>
Containers::StridedArrayView1D<T> Magnum::Trade::MeshData::mutableIndices()

Mutable mesh indices in a concrete type.

Like indices() const, but returns a mutable view. Expects that the mesh is mutable.

UnsignedInt Magnum::Trade::MeshData::vertexCount() const

Mesh vertex count.

Count of elements in every attribute array returned by attribute() (or, in case of an attribute-less mesh, the desired vertex count). See also indexCount() which returns count of elements in the indices() array, and attributeCount() which returns count of different per-vertex attribute arrays.

UnsignedInt Magnum::Trade::MeshData::attributeCount() const

Attribute array count.

Count of different per-vertex attribute arrays, or 0 for an attribute-less mesh. See also indexCount() which returns count of elements in the indices() array and vertexCount() which returns count of elements in every attribute() array.

MeshAttributeData Magnum::Trade::MeshData::attributeData(UnsignedInt id) const

Raw attribute data.

Returns the raw data that are used as a base for all attribute*() accessors. In most cases you don't want to access those directly, but rather use the attribute(), attributeName(), attributeFormat(), attributeOffset(), attributeStride() etc. accessors. This is also the reason why there's no overload taking a MeshAttribute, unlike the other accessors.

Useful mainly for passing particular attributes unchanged directly to MeshTools algorithms — unlike with attributeData() and releaseAttributeData(), returned instances are guaranteed to always have an absolute data pointer (i.e., MeshAttributeData::isOffsetOnly() always returning false). The id is expected to be smaller than attributeCount() const.

UnsignedInt Magnum::Trade::MeshData::attributeId(UnsignedInt id) const new in Git master

Attribute ID in a set of attributes of the same name.

The id is expected to be smaller than attributeCount() const. Returns the number of attributes of the same attributeName() preceeding id, or 0 if it's the first attribute of given name.

VertexFormat Magnum::Trade::MeshData::attributeFormat(UnsignedInt id) const

Attribute format.

The id is expected to be smaller than attributeCount() const. You can also use attributeFormat(MeshAttribute, UnsignedInt) const to directly get a type of given named attribute.

std::size_t Magnum::Trade::MeshData::attributeOffset(UnsignedInt id) const

Attribute offset.

Byte offset of the first element of given attribute from the beginning of the vertexData() array, or a byte difference between pointers returned from vertexData() and a particular attribute(). The id is expected to be smaller than attributeCount() const. You can also use attributeOffset(MeshAttribute, UnsignedInt) const to directly get an offset of given named attribute.

Short Magnum::Trade::MeshData::attributeStride(UnsignedInt id) const

Attribute stride.

Stride between consecutive elements of given attribute in the vertexData() array. In rare cases the stride may be zero or negative, such data layouts are however not commonly supported by GPU APIs. The id is expected to be smaller than attributeCount() const. You can also use attributeStride(MeshAttribute, UnsignedInt) const to directly get a stride of given named attribute.

UnsignedShort Magnum::Trade::MeshData::attributeArraySize(UnsignedInt id) const

Attribute array size.

In case given attribute is an array (the equivalent of e.g. int[30]), returns array size, otherwise returns 0. At the moment only custom attributes can be arrays, no builtin MeshAttribute is an array attribute. You can also use attributeArraySize(MeshAttribute, UnsignedInt) const to directly get array size of given named attribute.

Note that this is different from vertex count, which is exposed through vertexCount(), and is an orthogonal concept to having multiple attributes of the same name (for example two sets of texture coordinates), which is exposed through attributeCount(MeshAttribute) const. See Custom mesh attributes for an example.

bool Magnum::Trade::MeshData::hasAttribute(MeshAttribute name) const

Whether the mesh has given attribute.

UnsignedInt Magnum::Trade::MeshData::attributeCount(MeshAttribute name) const

Count of given named attribute.

Unlike attributeCount() const this returns count for given attribute name — for example a mesh can have more than one set of texture coordinates.

Containers::Optional<UnsignedInt> Magnum::Trade::MeshData::findAttributeId(MeshAttribute name, UnsignedInt id = 0) const new in Git master

Find an absolute ID of a named attribute.

If name isn't present or id is not smaller than attributeCount(MeshAttribute) const, returns Containers::NullOpt. The lookup is done in an $ \mathcal{O}(n) $ complexity with $ n $ being the attribute count.

UnsignedInt Magnum::Trade::MeshData::attributeId(MeshAttribute name, UnsignedInt id = 0) const

Absolute ID of a named attribute.

Like findAttributeId(), but the id is expected to be smaller than attributeCount(MeshAttribute) const.

VertexFormat Magnum::Trade::MeshData::attributeFormat(MeshAttribute name, UnsignedInt id = 0) const

Format of a named attribute.

The id is expected to be smaller than attributeCount(MeshAttribute) const.

std::size_t Magnum::Trade::MeshData::attributeOffset(MeshAttribute name, UnsignedInt id = 0) const

Offset of a named attribute.

Byte offset of the first element of given named attribute from the beginning of the vertexData() array. The id is expected to be smaller than attributeCount(MeshAttribute) const.

Short Magnum::Trade::MeshData::attributeStride(MeshAttribute name, UnsignedInt id = 0) const

Stride of a named attribute.

Stride between consecutive elements of given named attribute in the vertexData() array. In rare cases the stride may be zero or negative, such data layouts are however not commonly supported by GPU APIs. The id is expected to be smaller than attributeCount(MeshAttribute) const.

UnsignedShort Magnum::Trade::MeshData::attributeArraySize(MeshAttribute name, UnsignedInt id = 0) const

Array size of a named attribute.

The id is expected to be smaller than attributeCount(MeshAttribute) const. Note that this is different from vertex count, and is an orthogonal concept to having multiple attributes of the same name — see attributeArraySize(UnsignedInt) const for more information.

Containers::StridedArrayView2D<const char> Magnum::Trade::MeshData::attribute(UnsignedInt id) const

Data for given attribute.

The id is expected to be smaller than attributeCount() const. The second dimension represents the actual data type (its size is equal to format size for known VertexFormat values, possibly multiplied by array size, and to absolute attribute stride for implementation-specific values) and is guaranteed to be contiguous. In rare cases the first dimension stride may be zero or negative, such data layouts are however not commonly supported by GPU APIs.

Use the templated overload below to get the attribute in a concrete type.

Containers::StridedArrayView2D<char> Magnum::Trade::MeshData::mutableAttribute(UnsignedInt id)

Mutable data for given attribute.

Like attribute(UnsignedInt) const, but returns a mutable view. Expects that the mesh is mutable.

template<class T, class = typename std::enable_if<!std::is_array<T>::value>::type>
Containers::StridedArrayView1D<const T> Magnum::Trade::MeshData::attribute(UnsignedInt id) const

Data for given attribute in a concrete type.

The id is expected to be smaller than attributeCount() const and T is expected to correspond to attributeFormat(UnsignedInt) const. Expects that the vertex format is not implementation-specific, in that case you can only access the attribute via the typeless attribute(UnsignedInt) const above. The attribute is also expected to not be an array, in that case you need to use the overload below by using T[] instead of T. In rare cases the stride of the returned view may be zero or negative, such data layouts are however not commonly supported by GPU APIs. You can also use the non-templated positions2DAsArray(), positions3DAsArray(), tangentsAsArray(), bitangentSignsAsArray(), bitangentsAsArray(), normalsAsArray(), textureCoordinates2DAsArray(), colorsAsArray() and objectIdsAsArray() accessors to get common attributes converted to usual types in contiguous arrays, but note that these operations involve extra allocation and data conversion.

template<class T, class = typename std::enable_if<std::is_array<T>::value>::type>
Containers::StridedArrayView2D<const typename std::remove_extent<T>::type> Magnum::Trade::MeshData::attribute(UnsignedInt id) const

Data for given array attribute in a concrete type.

Same as above, except that it works with array attributes instead — you're expected to select this overload by passing T[] instead of T. The second dimension is guaranteed to be contiguous and have the same size as reported by attributeArraySize() for given attribute.

template<class T, class = typename std::enable_if<!std::is_array<T>::value>::type>
Containers::StridedArrayView1D<T> Magnum::Trade::MeshData::mutableAttribute(UnsignedInt id)

Mutable data for given attribute in a concrete type.

Like attribute(UnsignedInt) const, but returns a mutable view. Expects that the mesh is mutable.

template<class T, class = typename std::enable_if<std::is_array<T>::value>::type>
Containers::StridedArrayView2D<typename std::remove_extent<T>::type> Magnum::Trade::MeshData::mutableAttribute(UnsignedInt id)

Mutable data for given array attribute in a concrete type.

Same as above, except that it works with array attributes instead — you're expected to select this overload by passing T[] instead of T. The second dimension is guaranteed to be contiguous and have the same size as reported by attributeArraySize() for given attribute.

Containers::StridedArrayView2D<const char> Magnum::Trade::MeshData::attribute(MeshAttribute name, UnsignedInt id = 0) const

Data for given named attribute.

The id is expected to be smaller than attributeCount(MeshAttribute) const. The second dimension represents the actual data type (its size is equal to format size for known VertexFormat values and to attribute stride for implementation-specific values) and is guaranteed to be contiguous. In rare cases the first dimension stride may be zero or negative, such data layouts are however not commonly supported by GPU APIs.

Use the templated overload below to get the attribute in a concrete type.

Containers::StridedArrayView2D<char> Magnum::Trade::MeshData::mutableAttribute(MeshAttribute name, UnsignedInt id = 0)

Mutable data for given named attribute.

Like attribute(MeshAttribute, UnsignedInt) const, but returns a mutable view. Expects that the mesh is mutable.

template<class T, class = typename std::enable_if<!std::is_array<T>::value>::type>
Containers::StridedArrayView1D<const T> Magnum::Trade::MeshData::attribute(MeshAttribute name, UnsignedInt id = 0) const

Data for given named attribute in a concrete type.

The id is expected to be smaller than attributeCount(MeshAttribute) const and T is expected to correspond to attributeFormat(MeshAttribute, UnsignedInt) const. Expects that the vertex format is not implementation-specific, in that case you can only access the attribute via the typeless attribute(MeshAttribute, UnsignedInt) const above. The attribute is also expected to not be an array, in that case you need to use the overload below by using T[] instead of T. In rare cases the stride of the returned view may be zero or negative, such data layouts are however not commonly supported by GPU APIs. You can also use the non-templated positions2DAsArray(), positions3DAsArray(), tangentsAsArray(), bitangentSignsAsArray(), bitangentsAsArray(), normalsAsArray(), textureCoordinates2DAsArray(), colorsAsArray() and objectIdsAsArray() accessors to get common attributes converted to usual types in contiguous arrays, but note that these operations involve extra data conversion and an allocation.

template<class T, class = typename std::enable_if<std::is_array<T>::value>::type>
Containers::StridedArrayView2D<const typename std::remove_extent<T>::type> Magnum::Trade::MeshData::attribute(MeshAttribute name, UnsignedInt id = 0) const

Data for given named array attribute in a concrete type.

Same as above, except that it works with array attributes instead — you're expected to select this overload by passing T[] instead of T. The second dimension is guaranteed to be contiguous and have the same size as reported by attributeArraySize() for given attribute.

template<class T, class = typename std::enable_if<!std::is_array<T>::value>::type>
Containers::StridedArrayView1D<T> Magnum::Trade::MeshData::mutableAttribute(MeshAttribute name, UnsignedInt id = 0)

Mutable data for given named attribute in a concrete type.

Like attribute(MeshAttribute, UnsignedInt) const, but returns a mutable view. Expects that the mesh is mutable.

template<class T, class = typename std::enable_if<std::is_array<T>::value>::type>
Containers::StridedArrayView2D<typename std::remove_extent<T>::type> Magnum::Trade::MeshData::mutableAttribute(MeshAttribute name, UnsignedInt id = 0)

Mutable data for given named array attribute in a concrete type.

Same as above, except that it works with array attributes instead — you're expected to select this overload by passing T[] instead of T. The second dimension is guaranteed to be contiguous and have the same size as reported by attributeArraySize() for given attribute.

Containers::Array<UnsignedInt> Magnum::Trade::MeshData::indicesAsArray() const

Indices as 32-bit integers.

Convenience alternative to the templated indices(). Converts the index array from an arbitrary underlying type and returns it in a newly-allocated array.

void Magnum::Trade::MeshData::indicesInto(const Containers::StridedArrayView1D<UnsignedInt>& destination) const

Positions as 32-bit integers into a pre-allocated view.

Like indicesAsArray(), but puts the result into destination instead of allocating a new array. Expects that destination is sized to contain exactly all data.

Containers::Array<Vector2> Magnum::Trade::MeshData::positions2DAsArray(UnsignedInt id = 0) const

Positions as 2D float vectors.

Convenience alternative to attribute(MeshAttribute, UnsignedInt) const with MeshAttribute::Position as the first argument. Converts the position array from an arbitrary underlying type and returns it in a newly-allocated array. If the underlying type is three-component, the last component is dropped. Expects that the vertex format is not implementation-specific, in that case you can only access the attribute via the typeless attribute(MeshAttribute, UnsignedInt) const.

void Magnum::Trade::MeshData::positions2DInto(const Containers::StridedArrayView1D<Vector2>& destination, UnsignedInt id = 0) const

Positions as 2D float vectors into a pre-allocated view.

Like positions2DAsArray(), but puts the result into destination instead of allocating a new array. Expects that destination is sized to contain exactly all data.

Containers::Array<Vector3> Magnum::Trade::MeshData::positions3DAsArray(UnsignedInt id = 0) const

Positions as 3D float vectors.

Convenience alternative to attribute(MeshAttribute, UnsignedInt) const with MeshAttribute::Position as the first argument. Converts the position array from an arbitrary underlying type and returns it in a newly-allocated array. If the underlying type is two-component, the Z component is set to 0.0f. Expects that the vertex format is not implementation-specific, in that case you can only access the attribute via the typeless attribute(MeshAttribute, UnsignedInt) const.

void Magnum::Trade::MeshData::positions3DInto(const Containers::StridedArrayView1D<Vector3>& destination, UnsignedInt id = 0) const

Positions as 3D float vectors into a pre-allocated view.

Like positions3DAsArray(), but puts the result into destination instead of allocating a new array. Expects that destination is sized to contain exactly all data.

Containers::Array<Vector3> Magnum::Trade::MeshData::tangentsAsArray(UnsignedInt id = 0) const

Tangents as 3D float vectors.

Convenience alternative to attribute(MeshAttribute, UnsignedInt) const with MeshAttribute::Tangent as the first argument. Converts the tangent array from an arbitrary underlying type and returns it in a newly-allocated array. Expects that the vertex format is not implementation-specific, in that case you can only access the attribute via the typeless attribute(MeshAttribute, UnsignedInt) const.

If the tangents contain a fourth component with bitangent direction, it's ignored here — use bitangentSignsAsArray() to get those instead. You can also use tangentsInto() together with bitangentSignsInto() to put them both in a single array.

void Magnum::Trade::MeshData::tangentsInto(const Containers::StridedArrayView1D<Vector3>& destination, UnsignedInt id = 0) const

Tangents as 3D float vectors into a pre-allocated view.

Like tangentsAsArray(), but puts the result into destination instead of allocating a new array. Expects that destination is sized to contain exactly all data. Use bitangentSignsInto() to extract the fourth component wit bitangent direction, if present.

Containers::Array<Float> Magnum::Trade::MeshData::bitangentSignsAsArray(UnsignedInt id = 0) const

Bitangent signs as floats.

Counterpart to tangentsAsArray() returning value of the fourth component. Expects that the type of MeshAttribute::Tangent is four-component. You can also use tangentsInto() together with bitangentSignsInto() to put them both in a single array.

void Magnum::Trade::MeshData::bitangentSignsInto(const Containers::StridedArrayView1D<Float>& destination, UnsignedInt id = 0) const

Bitangent signs as floats into a pre-allocated view.

Like bitangentsAsArray(), but puts the result into destination instead of allocating a new array. Expects that destination is sized to contain exactly all data.

Containers::Array<Vector3> Magnum::Trade::MeshData::bitangentsAsArray(UnsignedInt id = 0) const

Bitangents as 3D float vectors.

Convenience alternative to attribute(MeshAttribute, UnsignedInt) const with MeshAttribute::Bitangent as the first argument. Converts the bitangent array from an arbitrary underlying type and returns it in a newly-allocated array. Expects that the vertex format is not implementation-specific, in that case you can only access the attribute via the typeless attribute(MeshAttribute, UnsignedInt) const.

Note that in some cases the bitangents aren't provided directly but calculated from normals and four-component tangents. In that case you'll need to get bitangent signs via bitangentSignsAsArray() and calculate the bitangents as shown in the documentation of MeshAttribute::Tangent.

void Magnum::Trade::MeshData::bitangentsInto(const Containers::StridedArrayView1D<Vector3>& destination, UnsignedInt id = 0) const

Bitangents as 3D float vectors into a pre-allocated view.

Like bitangentsAsArray(), but puts the result into destination instead of allocating a new array. Expects that destination is sized to contain exactly all data.

Containers::Array<Vector3> Magnum::Trade::MeshData::normalsAsArray(UnsignedInt id = 0) const

Normals as 3D float vectors.

Convenience alternative to attribute(MeshAttribute, UnsignedInt) const with MeshAttribute::Normal as the first argument. Converts the normal array from an arbitrary underlying type and returns it in a newly-allocated array. Expects that the vertex format is not implementation-specific, in that case you can only access the attribute via the typeless attribute(MeshAttribute, UnsignedInt) const.

void Magnum::Trade::MeshData::normalsInto(const Containers::StridedArrayView1D<Vector3>& destination, UnsignedInt id = 0) const

Normals as 3D float vectors into a pre-allocated view.

Like normalsAsArray(), but puts the result into destination instead of allocating a new array. Expects that destination is sized to contain exactly all data.

Containers::Array<Vector2> Magnum::Trade::MeshData::textureCoordinates2DAsArray(UnsignedInt id = 0) const

Texture coordinates as 2D float vectors.

Convenience alternative to attribute(MeshAttribute, UnsignedInt) const with MeshAttribute::TextureCoordinates as the first argument. Converts the texture coordinate array from an arbitrary underlying type and returns it in a newly-allocated array. Expects that the vertex format is not implementation-specific, in that case you can only access the attribute via the typeless attribute(MeshAttribute, UnsignedInt) const.

void Magnum::Trade::MeshData::textureCoordinates2DInto(const Containers::StridedArrayView1D<Vector2>& destination, UnsignedInt id = 0) const

Texture coordinates as 2D float vectors into a pre-allocated view.

Like textureCoordinates2DAsArray(), but puts the result into destination instead of allocating a new array. Expects that destination is sized to contain exactly all data.

Containers::Array<Color4> Magnum::Trade::MeshData::colorsAsArray(UnsignedInt id = 0) const

Colors as RGBA floats.

Convenience alternative to attribute(MeshAttribute, UnsignedInt) const with MeshAttribute::Color as the first argument. Converts the color array from an arbitrary underlying type and returns it in a newly-allocated array. If the underlying type is three-component, the alpha component is set to 1.0f. Expects that the vertex format is not implementation-specific, in that case you can only access the attribute via the typeless attribute(MeshAttribute, UnsignedInt) const.

void Magnum::Trade::MeshData::colorsInto(const Containers::StridedArrayView1D<Color4>& destination, UnsignedInt id = 0) const

Colors as RGBA floats into a pre-allocated view.

Like colorsAsArray(), but puts the result into destination instead of allocating a new array. Expects that destination is sized to contain exactly all data.

Containers::Array<UnsignedInt> Magnum::Trade::MeshData::objectIdsAsArray(UnsignedInt id = 0) const

Object IDs as 32-bit integers.

Convenience alternative to attribute(MeshAttribute, UnsignedInt) const with MeshAttribute::ObjectId as the first argument. Converts the object ID array from an arbitrary underlying type and returns it in a newly-allocated array. Expects that the vertex format is not implementation-specific, in that case you can only access the attribute via the typeless attribute(MeshAttribute, UnsignedInt) const.

void Magnum::Trade::MeshData::objectIdsInto(const Containers::StridedArrayView1D<UnsignedInt>& destination, UnsignedInt id = 0) const

Object IDs as 32-bit integers into a pre-allocated view.

Like objectIdsAsArray(), but puts the result into destination instead of allocating a new array. Expects that destination is sized to contain exactly all data.

Containers::Array<char> Magnum::Trade::MeshData::releaseIndexData()

Release index data storage.

Releases the ownership of the index data array and resets internal index-related state to default. The mesh then behaves like it has zero indices (but it can still have a non-zero vertex count), however indexData() still return a zero-sized non-null array so index offset calculation continues to work as expected.

Note that the returned array has a custom no-op deleter when the data are not owned by the mesh, and while the returned array type is mutable, the actual memory might be not.

Containers::Array<MeshAttributeData> Magnum::Trade::MeshData::releaseAttributeData()

Release attribute data storage.

Releases the ownership of the attribute data array and resets internal attribute-related state to default. The mesh then behaves like if it has no attributes (but it can still have a non-zero vertex count). Note that the returned array has a custom no-op deleter when the data are not owned by the mesh, and while the returned array type is mutable, the actual memory might be not. Additionally, the returned MeshAttributeData instances may have different data pointers and sizes than what's returned by the attribute() and attributeData(UnsignedInt) const accessors as some of them might be offset-only — use this function only if you really know what are you doing.

Containers::Array<char> Magnum::Trade::MeshData::releaseVertexData()

Release vertex data storage.

Releases the ownership of the vertex data array and resets internal attribute-related state to default. The mesh then behaves like it has zero vertices (but it can still have a non-zero amount of attributes), however vertexData() will still return a zero- sized non-null array so attribute offset calculation continues to work as expected.

Note that the returned array has a custom no-op deleter when the data are not owned by the mesh, and while the returned array type is mutable, the actual memory might be not.

const void* Magnum::Trade::MeshData::importerState() const

Importer-specific state.

See AbstractImporter::importerState() for more information.