Magnum::SceneTools namespace new in Git master

Scene tools.

Scene manipulation and optimization tools.

This library is built if MAGNUM_WITH_SCENETOOLS is enabled when building Magnum. To use this library with CMake, request the SceneTools component of the Magnum package and link to the Magnum::SceneTools target:

find_package(Magnum REQUIRED SceneTools)

# ...
target_link_libraries(your-app PRIVATE Magnum::SceneTools)

Additional utilities are built separately. See the magnum-sceneconverter utility documentation, Downloading and building and Usage with CMake for more information.

Functions

auto flattenMeshHierarchy2D(const Trade::SceneData& scene, const Matrix3& globalTransformation = {}) -> Containers::Array<Containers::Triple<UnsignedInt, Int, Matrix3>> new in Git master
Flatten a 2D mesh hierarchy.
void flattenMeshHierarchy2DInto(const Trade::SceneData& scene, const Containers::StridedArrayView1D<Matrix3>& transformations, const Matrix3& globalTransformation = {}) new in Git master
Flatten a 2D mesh hierarchy into an existing array.
auto flattenMeshHierarchy3D(const Trade::SceneData& scene, const Matrix4& globalTransformation = {}) -> Containers::Array<Containers::Triple<UnsignedInt, Int, Matrix4>> new in Git master
Flatten a 3D mesh hierarchy.
void flattenMeshHierarchy3DInto(const Trade::SceneData& scene, const Containers::StridedArrayView1D<Matrix4>& transformations, const Matrix4& globalTransformation = {}) new in Git master
Flatten a 3D mesh hierarchy into an existing array.
auto orderClusterParents(const Trade::SceneData& scene) -> Containers::Array<Containers::Pair<UnsignedInt, Int>> new in Git master
Calculate ordered and clustered parents.
void orderClusterParentsInto(const Trade::SceneData& scene, const Containers::StridedArrayView1D<UnsignedInt>& mappingDestination, const Containers::StridedArrayView1D<Int>& parentDestination) new in Git master
Calculate ordered and clustered parents into a pre-allocated view.

Function documentation

Containers::Array<Containers::Triple<UnsignedInt, Int, Matrix3>> Magnum::SceneTools::flattenMeshHierarchy2D(const Trade::SceneData& scene, const Matrix3& globalTransformation = {}) new in Git master

Flatten a 2D mesh hierarchy.

For all Trade::SceneField::Mesh entries returns a triple of mesh ID, Trade::SceneField::MeshMaterial and its absolute transformation in the scene with globalTransformation prepended. The Trade::SceneField::Parent field is expected to be contained in the scene, having no cycles or duplicates, and the scene is expected to be 2D. If Trade::SceneField::Mesh is not present or is empty, returns an empty array. You can then use MeshTools::transform2D() to apply the transformations to actual meshes:

Trade::SceneData scene = ;
Containers::Array<Trade::MeshData> meshes = ;

/* Since a mesh can be referenced multiple times, we can't operate in-place */
Containers::Array<Trade::MeshData> flattenedMeshes;
for(const Containers::Triple<UnsignedInt, Int, Matrix3>& meshTransformation:
    SceneTools::flattenMeshHierarchy2D(scene))
{
    arrayAppend(flattenedMeshes, MeshTools::transform2D(
        meshes[meshTransformation.first()], meshTransformation.third()));
}

The operation is done in an $ \mathcal{O}(m + n) $ execution time and memory complexity, with $ m $ being size of the Trade::SceneField::Mesh field and $ n $ being Trade::SceneData::mappingBound(). The function calls orderClusterParents() internally.

The returned data are in the same order as the Trade::SceneField::Mesh attribute. Meshes attached to objects without a Trade::SceneField::Parent or to objects in loose hierarchy subtrees will have their transformation set to an unspecified value.

void Magnum::SceneTools::flattenMeshHierarchy2DInto(const Trade::SceneData& scene, const Containers::StridedArrayView1D<Matrix3>& transformations, const Matrix3& globalTransformation = {}) new in Git master

Flatten a 2D mesh hierarchy into an existing array.

Parameters
scene in Input scene
transformations out Where to put the calculated transformations
globalTransformation in Global transformation to prepend

A variant of flattenMeshHierarchy2D() that fills existing memory instead of allocating a new array. The transformations array is expected to have the same size as the Trade::SceneField::Mesh field. Corresponding mesh and material IDs as well as object ID mapping can be retrieved directly with Trade::SceneData::meshesMaterialsInto(), as the returned transformations are matching their order. The snippet below shows retrieving absolute transformations together with object and mesh IDs, but ignoring materials:

Trade::SceneData scene = ;

struct Data {
    Matrix3 transformation;
    UnsignedInt object;
    UnsignedInt mesh;
};
Containers::Array<Data> data{NoInit, scene.fieldSize(Trade::SceneField::Mesh)};

SceneTools::flattenMeshHierarchy2DInto(scene,
    stridedArrayView(data).slice(&Data::transformation));
scene.meshesMaterialsInto(
    stridedArrayView(data).slice(&Data::object),
    stridedArrayView(data).slice(&Data::mesh),
    nullptr);

Containers::Array<Containers::Triple<UnsignedInt, Int, Matrix4>> Magnum::SceneTools::flattenMeshHierarchy3D(const Trade::SceneData& scene, const Matrix4& globalTransformation = {}) new in Git master

Flatten a 3D mesh hierarchy.

For all Trade::SceneField::Mesh entries returns a triple of mesh ID, Trade::SceneField::MeshMaterial and its absolute transformation in the scene with globalTransformation prepended. The Trade::SceneField::Parent field is expected to be contained in the scene, having no cycles or duplicates, and the scene is expected to be 3D. If Trade::SceneField::Mesh is not present or is empty, returns an empty array. You can then use MeshTools::transform3D() to apply the transformations to actual meshes:

Trade::SceneData scene = ;
Containers::Array<Trade::MeshData> meshes = ;

/* Since a mesh can be referenced multiple times, we can't operate in-place */
Containers::Array<Trade::MeshData> flattenedMeshes;
for(const Containers::Triple<UnsignedInt, Int, Matrix4>& meshTransformation:
    SceneTools::flattenMeshHierarchy3D(scene))
{
    arrayAppend(flattenedMeshes, MeshTools::transform3D(
        meshes[meshTransformation.first()], meshTransformation.third()));
}

The operation is done in an $ \mathcal{O}(m + n) $ execution time and memory complexity, with $ m $ being size of the Trade::SceneField::Mesh field and $ n $ being Trade::SceneData::mappingBound(). The function calls orderClusterParents() internally.

The returned data are in the same order as the Trade::SceneField::Mesh attribute. Meshes attached to objects without a Trade::SceneField::Parent or to objects in loose hierarchy subtrees will have their transformation set to an unspecified value.

void Magnum::SceneTools::flattenMeshHierarchy3DInto(const Trade::SceneData& scene, const Containers::StridedArrayView1D<Matrix4>& transformations, const Matrix4& globalTransformation = {}) new in Git master

Flatten a 3D mesh hierarchy into an existing array.

Parameters
scene in Input scene
transformations out Where to put the calculated transformations
globalTransformation in Global transformation to prepend

A variant of flattenMeshHierarchy3D() that fills existing memory instead of allocating a new array. The transformations array is expected to have the same size as the Trade::SceneField::Mesh field. Corresponding mesh and material IDs as well as object ID mapping can be retrieved directly with Trade::SceneData::meshesMaterialsInto(), as the returned transformations are matching their order. The snippet below shows retrieving absolute transformations together with object and mesh IDs, but ignoring materials:

Trade::SceneData scene = ;

struct Data {
    Matrix4 transformation;
    UnsignedInt object;
    UnsignedInt mesh;
};
Containers::Array<Data> data{NoInit, scene.fieldSize(Trade::SceneField::Mesh)};

SceneTools::flattenMeshHierarchy3DInto(scene,
    stridedArrayView(data).slice(&Data::transformation));
scene.meshesMaterialsInto(
    stridedArrayView(data).slice(&Data::object),
    stridedArrayView(data).slice(&Data::mesh),
    nullptr);

Containers::Array<Containers::Pair<UnsignedInt, Int>> Magnum::SceneTools::orderClusterParents(const Trade::SceneData& scene) new in Git master

Calculate ordered and clustered parents.

Extracts the Trade::SceneField::Parent field from scene and converts it to match the following rules:

  • a parent object reference appears always before any of its children
  • the array is clustered so children sharing the same parent are together

This form is useful primarily for calculating absolute object transformations, for example:

Trade::SceneData scene = ;

/* Put all transformations into an array indexed by object ID. Objects
   implicitly have an identity transformation, first element is reserved for
   the global transformation. */
Containers::Array<Matrix4> transformations{std::size_t(scene.mappingBound() + 1)};
for(const Containers::Pair<UnsignedInt, Matrix4>& transformation:
    scene.transformations3DAsArray())
{
    transformations[transformation.first() + 1] = transformation.second();
}

/* Go through ordered parents and compose absolute transformations for all
   nodes in the hierarchy, objects in the root use transformations[0]. The
   function ensures that the parent transformation is already calculated when
   referenced by child nodes. */
for(const Containers::Pair<UnsignedInt, Int>& parent:
    SceneTools::orderClusterParents(scene))
{
    transformations[parent.first() + 1] =
        transformations[parent.second() + 1]*
        transformations[parent.first() + 1];
}

The operation is done in an $ \mathcal{O}(n) $ execution time and memory complexity, with $ n $ being Trade::SceneData::mappingBound(). The Trade::SceneField::Parent field is expected to be contained in the scene, having no cycles (i.e., every node listed just once) and not being sparse (i.e., every node listed in the field reachable from the root).

void Magnum::SceneTools::orderClusterParentsInto(const Trade::SceneData& scene, const Containers::StridedArrayView1D<UnsignedInt>& mappingDestination, const Containers::StridedArrayView1D<Int>& parentDestination) new in Git master

Calculate ordered and clustered parents into a pre-allocated view.

Like orderClusterParents(), but puts the result into mappingDestination and parentDestination instead of allocating a new array. Expect that both views have a size equal to size of the Trade::SceneField::Parent view in scene.