Magnum::Trade::GltfImporter class new in Git master

glTF importer plugin

Imports glTF (*.gltf) and binary glTF (*.glb) files. You can use GltfSceneConverter to encode scenes into this format.

Usage

This plugin depends on the Trade library and the AnyImageImporter plugin and is built if MAGNUM_WITH_GLTFIMPORTER is enabled when building Magnum Plugins. To use as a dynamic plugin, load "GltfImporter" via Corrade::PluginManager::Manager.

Additionally, if you're using Magnum as a CMake subproject, bundle the magnum-plugins repository and do the following:

set(MAGNUM_WITH_ANYIMAGEIMPORTER ON CACHE BOOL "" FORCE)
add_subdirectory(magnum EXCLUDE_FROM_ALL)

set(MAGNUM_WITH_GLTFIMPORTER ON CACHE BOOL "" FORCE)
add_subdirectory(magnum-plugins EXCLUDE_FROM_ALL)

# So the dynamically loaded plugin gets built implicitly
add_dependencies(your-app MagnumPlugins::GltfImporter)

To use as a static plugin or as a dependency of another plugin with CMake, put FindMagnumPlugins.cmake into your modules/ directory, request the GltfImporter component of the MagnumPlugins package and link to the MagnumPlugins::GltfImporter target:

find_package(MagnumPlugins REQUIRED GltfImporter)

# ...
target_link_libraries(your-app PRIVATE MagnumPlugins::GltfImporter)

See Downloading and building plugins, Plugin usage with CMake, Loading and using plugins and File format support for more information.

Behavior and limitations

The plugin supports ImporterFeature::OpenData and ImporterFeature::FileCallback features. All buffers are loaded on-demand and kept in memory for any later access. As a result, external file loading callbacks are called with InputFileCallbackPolicy::LoadPermanent. Resources returned from file callbacks can only be safely freed after closing the importer instance. In case of images, the files are loaded on-demand inside image2D() calls with InputFileCallbackPolicy::LoadTemporary and InputFileCallbackPolicy::Close is emitted right after the file is fully read.

The content of the global extensionsRequired array is checked against all extensions supported by the plugin. If a glTF file requires an unknown extension, the import will fail. This behaviour can be disabled with the ignoreRequiredExtensions configuration option.

Import of morph data is not supported at the moment.

The plugin recognizes ImporterFlag::Quiet, which will cause all import warnings to be suppressed. All ImporterFlags are also propagated to image importer plugins the importer delegates to.

Scene import

Animation and skin import

  • Linear quaternion rotation tracks are postprocessed in order to make it possible to use the faster Math::lerp() / Math::slerp() functions instead of Math::lerpShortestPath() / Math::slerpShortestPath(). Can be disabled per-animation with the optimizeQuaternionShortestPath configuration option. This doesn't affect spline-interpolated rotation tracks.
  • If linear quaternion rotation tracks are not normalized, the importer prints a warning and normalizes them. Can be disabled per-animation with the normalizeQuaternions configuration option. This doesn't affect spline-interpolated rotation tracks.
  • Skin skeleton property is not imported
  • Morph target animations are not supported
  • Animation tracks are always imported with Animation::Extrapolation::Constant, because glTF doesn't support anything else
  • It's possible to request all animation clips to be merged into one using the mergeAnimationClips option in order to for example preserve cinematic animations when using the Blender glTF exporter (as it otherwise outputs a separate clip for each object). When this option is enabled, animationCount() always report either 0 or 1 and the merged animation has no name. With this option enabled, however, it can happen that multiple conflicting tracks affecting the same node are merged in the same clip, causing the animation to misbehave.

Camera import

  • Cameras in glTF are specified with vertical FoV and vertical:horizontal aspect ratio, these values are recalculated for horizontal FoV and horizontal:vertical aspect ratio as is common in Magnum

Light import

Mesh import

By default, the mesh import silently allows certain features that aren't strictly valid according to the glTF specification, such as 32-bit integer VertexFormat, because they're useful in general. Enable the strict configuration option to fail the import in such cases instead.

Custom and unrecognized vertex attributes of allowed types are present in the imported meshes as well. Their mapping to/from a string can be queried using meshAttributeName() and meshAttributeForName(). Attributes with unsupported types (such as non-normalized integer matrices) cause the import to fail.

Material import

Texture and image import

2D array texture support

If the experimentalKhrTextureKtx configuration option is enabled, textures can contain also the proposed KHR_texture_ktx extension. Besides having an ability to use 2D *.ktx2 files the same way as other texture extensions listed above, it can also reference 2D array textures. The importer behavior is as follows and may get adapted to eventual changes in the extension proposal:

  • If a texture object contains the KHR_texture_ktx extension with a layer property, the image it references is assumed to be a 2D array. Otherwise, it's assumed to be 2D. The *.ktx2 file itself is not checked upfront as that goes against the goal of accessing the data only once actually needed.
  • If the same image is referenced as both 2D and 2D array, it's an import error. In other words, a texture referencing a 2D array image has to have the layer property even if it would be zero.
  • Images that are assumed to be 2D arrays are available through image3D() and related APIs, other images through image2D(). The sum of image2DCount() and image3DCount() is the count of glTF image objects in the file.
  • Textures referencing the same 2D array image are collapsed together and are exposed as a TextureData with TextureType::Texture2DArray, with TextureData::image() giving an index of a 3D image instead of a 2D one. Differing samplers are not taken into account, the resulting TextureData will always use the sampler properties referenced from the first texture. This means that, in this case, textureCount() may be less the actual count of glTF texture objects in the file.
  • Materials referencing KHR_texture_ktx textures with the layer property then get a *TextureLayer attribute. I.e., if MaterialAttribute::BaseColorTexture is a 2D array texture, the material will get a MaterialAttribute::BaseColorTextureLayer as well, containing the value of the layer property.

Plugin-specific configuration

It's possible to tune various output options through configuration(). See below for all options and their default values.

[configuration]
# Don't fail the import and only print a warning if an unknown or unsupported
# extension is listed in extensionsRequired. Some things might be missing or
# not get imported correctly if this is enabled.
ignoreRequiredExtensions=false

# Allow only strictly valid glTF files. If enabled, the following cause a
# particular data import to fail:
# - Meshes with zero vertices, zero indices or zero attributes
# - Meshes with 32-bit integer attributes
# - Builtin mesh attributes with invalid types (such as unnormalized colors).
#   By default, those produce a warning and are imported as custom attributes
#   in order to make it possible to fix them post-import.
# This can be controlled separately for each data import.
strict=false

# Optimize imported linearly-interpolated quaternion animation tracks to
# ensure shortest path is always chosen. This can be controlled separately
# for each animation import.
optimizeQuaternionShortestPath=true

# Normalize transformation quaternions and linearly-interpolated quaternion
# animation tracks, if they are not already. Note that spline-interpolated
# quaternion animation tracks are not patched. This can be controlled
# separately for each object/animation import.
normalizeQuaternions=true

# Merge all animations into a single clip. Useful for preserving cinematic
# animations when using the Blender glTF exporter, as it exports animation of
# every object as a separate clip. For more information see
# https://blender.stackexchange.com/q/5689 and
# https://github.com/KhronosGroup/glTF-Blender-Exporter/pull/166.
mergeAnimationClips=false

# Perform Y-flip for texture coordinates in a material texture transform. By
# default texture coordinates are Y-flipped directly in the mesh data to
# avoid the need to supply texture transformation matrix to a shader,
# enabling this will cause all texture coordinate data to be unchanged and
# instead all materials will have a Y-flipping texture transformation
# present. Note that this flag has to be enabled before opening a file,
# changing it during import will have undefined behavior.
textureCoordinateYFlipInMaterial=false

# The non-standard MeshAttribute::ObjectId is by default recognized under
# this name. Change if your file uses a different identifier.
objectIdAttribute=_OBJECT_ID

# Expose MeshAttribute::JointIds and Weights under custom "JOINTS" and
# "WEIGHTS" aliases for backwards compatibility with code that relies on
# those being present. If Magnum is built with MAGNUM_BUILD_DEPRECATED
# disabled, no aliases are provided and this option is ignored.
compatibilitySkinningAttributes=true

# Provide basic Phong material attributes even for PBR materials in order to
# be compatible with PhongMaterialData workflows from version 2020.06 and
# before. This option will eventually become disabled by default.
phongMaterialFallback=true

# Experimental KHR_texture_ktx support, which enables use of 2D array
# textures. The extension is not stabilized yet, thus the implementation may
# not reflect latest changes to the proposal.
experimentalKhrTextureKtx=false

# By default, numeric extra properties of scene nodes are imported as custom
# SceneFieldType::Float fields. To override this for fields of particular
# names, add <name>=<type> entries to this group, where <type> is Float,
# UnsignedInt or Int. Properties that don't fit into given type will be
# ignored. The overrides only have an effect if set before a file is opened.
[configuration/customSceneFieldTypes]

See Editing plugin-specific configuration for more information and an example showing how to edit the configuration values.

Access to internal importer state

The glTF JSON is internally parsed using Utility::Json and you can access the parsed content through importer-specific data accessors.

Be aware that not all of the JSON may be parsed when accessed — where possible, the importerimplementation defers parsing only to when a particular data is accessed, and tokens unrecognized by the importers may be left unparsed. In order to parse what you need, do it through the Utility::Json instance that gets made mutable first. For example, in order to access the contents of the CESIUM_primitive_outline extension on a glTF mesh primitive object:

Containers::Pointer<Trade::AbstractImporter> importer = ;
Containers::Optional<Trade::MeshData> mesh = importer->mesh();

/* Get a mutable reference to the Json instance so we can parse using it */
Utility::Json& gltf = *static_cast<Utility::Json*>(
    const_cast<void*>(importer->importerState())
);

/* Get the outline indices accessor, if present. Can't assume anything is
   parsed, so call parseObject() and parseUnsignedInt() before accessing every
   value. */
Containers::Optional<UnsignedInt> indices;
if(const Utility::JsonToken* gltfExtensions = gltf.parseObject(
    *static_cast<const Utility::JsonToken*>(mesh->importerState()))->find("extensions"))
{
    if(const Utility::JsonToken* gltfCesiumPrimitiveOutline =
        gltf.parseObject(*gltfExtensions)->find("CESIUM_primitive_outline"))
    {
        indices = gltf.parseUnsignedInt((
            *gltf.parseObject(*gltfCesiumPrimitiveOutline))["indices"]);
    }
}

Base classes

class AbstractImporter
Base for importer plugins.

Derived classes

class CgltfImporter deprecated in Git master
glTF importer plugin

Constructors, destructors, conversion operators

GltfImporter() explicit
Default constructor.
GltfImporter(PluginManager::Manager<AbstractImporter>& manager) explicit
Constructor.
GltfImporter(PluginManager::AbstractManager& manager, const Containers::StringView& plugin) explicit
Plugin manager constructor.

Public functions

auto importerState() -> Utility::Json*
Importer state.
auto importerState() const -> const Utility::Json*

Function documentation

Magnum::Trade::GltfImporter::GltfImporter() explicit

Default constructor.

In case you want to open images, use GltfImporter(PluginManager::Manager<AbstractImporter>&) instead.

Magnum::Trade::GltfImporter::GltfImporter(PluginManager::Manager<AbstractImporter>& manager) explicit

Constructor.

The plugin needs access to plugin manager for importing images.

Utility::Json* Magnum::Trade::GltfImporter::importerState()

Importer state.

See class documentation for more information.

const Utility::Json* Magnum::Trade::GltfImporter::importerState() const

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