class
TinyGltfImporterTinyGltf importer plugin.
Contents
Imports glTF and binary glTF using the TinyGLTF library.
This plugin provides the GltfImporter
plugin.
Usage
This plugin depends on the Trade library and the AnyImageImporter plugin and is built if WITH_TINYGLTFIMPORTER
is enabled when building Magnum Plugins. To use as a dynamic plugin, load "TinyGltfImporter"
via Corrade::
Additionally, if you're using Magnum as a CMake subproject, bundle the magnum-plugins repository and do the following:
set(WITH_ANYIMAGEIMPORTER ON CACHE BOOL "" FORCE) add_subdirectory(magnum EXCLUDE_FROM_ALL) set(WITH_TINYGLTFIMPORTER ON CACHE BOOL "" FORCE) add_subdirectory(magnum-plugins EXCLUDE_FROM_ALL) # So the dynamically loaded plugin gets built implicitly add_dependencies(your-app MagnumPlugins::TinyGltfImporter)
To use as a static plugin or as a dependency of another plugin with CMake, put FindMagnumPlugins.cmake into your modules/
directory, request the TinyGltfImporter
component of the MagnumPlugins
package and link to the MagnumPlugins::TinyGltfImporter
target:
find_package(MagnumPlugins REQUIRED TinyGltfImporter) # ... target_link_libraries(your-app PRIVATE MagnumPlugins::TinyGltfImporter)
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::tiny_gltf
library loads everything during initial import, meaning all external file loading callbacks are called with InputFileCallbackPolicy::
Import of skeleton, skin and morph data is not supported at the moment.
Animation 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
option, see below. 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
option, see below. This doesn't affect spline-interpolated rotation tracks. - Skin
skeleton
property is not imported, but you can retrieve it via SkinData::importerState() — see Access to internal importer state for more information - Morph targets 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 either0
or1
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.
Scene and object import
- If no
"scene"
property is present and the file contains at least one scene, defaultScene() returns0
instead of-1
. According to the glTF 2.0 specification the importer is free to not render anything, but the suggested behavior would break even some official sample models. - In case object transformation is set via separate translation/rotation/scaling properties in the source file, ObjectData3D is created with ObjectFlag3D::
HasTranslationRotationScaling and these separate properties accessible - If object rotation quaternion is not normalized, the importer prints a warning and normalizes it. Can be disabled per-object with the
normalizeQuaternions
option, see below.
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
- The importer supports the KHR_
lights_ punctual extension
Mesh import
- Indices are imported as either MeshIndexType::
UnsignedByte, MeshIndexType:: UnsignedShort or MeshIndexType:: UnsignedInt - Positions are imported as VertexFormat::
Vector3, VertexFormat:: Vector3ub, VertexFormat:: Vector3b, VertexFormat:: Vector3us, VertexFormat:: Vector3s, VertexFormat:: Vector3ubNormalized, VertexFormat:: Vector3bNormalized, VertexFormat:: Vector3usNormalized or VertexFormat:: Vector3sNormalized (which includes the additional types specified by KHR_ mesh_ quantization) - Normals, if any, are imported as VertexFormat::
Vector3, VertexFormat:: Vector3bNormalized or VertexFormat:: Vector3sNormalized - Texture coordinates are imported as VertexFormat::
Vector3, VertexFormat:: Vector3ub, VertexFormat:: Vector3b, VertexFormat:: Vector3us, VertexFormat:: Vector3s, VertexFormat:: Vector3ubNormalized, VertexFormat:: Vector3bNormalized, VertexFormat:: Vector3usNormalized or VertexFormat:: Vector3sNormalized (which includes the additional types specified by KHR_ mesh_ quantization). The data are by default Y-flipped on import unless textureCoordinateYFlipInMaterial
is either explicitly enabled, or if the file contains non-normalized integer or normalized signed integer texture coordinates (which can't easily be flipped). In that case texture coordinate data are kept as-is and materials provide a texture transformation that does the Y-flip instead. - Colors are imported as VertexFormat::
Vector3, VertexFormat:: Vector4, VertexFormat:: Vector3ubNormalized, VertexFormat:: Vector4ubNormalized, VertexFormat:: Vector3usNormalized or VertexFormat:: Vector4usNormalized - Per-vertex object ID attribute is imported as either VertexFormat::
UnsignedInt, VertexFormat:: UnsignedShort or VertexFormat:: UnsignedByte. By default _OBJECT_ID
is the recognized name, use theobjectIdAttribute
configuration option to change the identifier that's being looked for. - Multi-primitive meshes are loaded as follows, consistently with the behavior of AssimpImporter:
- The meshCount() query returns a number of all primitives, not meshes
- Each multi-primitive mesh is split into a sequence of MeshData instances following each other
- meshForName() points to the first mesh in given sequence and meshName() returns the same name for all meshes in given sequence
- The object3DCount() query returns a number of all nodes extended with number of extra nodes for each additional mesh primitive
- Each node referencing a multi-primitive mesh is split into a sequence of MeshObjectData3D instances following each other; the extra nodes being a direct and immediate children of the first one with an identity transformation
- object3DForName() points to the first object containing the first primitive, object3DName() returns the same name for all objects in given sequence
- AnimationData instances returned by animation() have their AnimationData::
trackTarget() values patched to account for the extra nodes, always pointing to the first object in the sequence and thus indirectly affecting transformations of the extra nodes represented as its children
- Attribute-less meshes either with or without an index buffer are supported, however since glTF has no way of specifying vertex count for those, returned Trade::
MeshData:: vertexCount() is set to 0
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
- Builtin metallic/
roughness material is imported always, setting MaterialType:: PbrMetallicRoughness on the MaterialData. Unfortunately TinyGLTF doesn't provide a way to detect if metallic/roughness properties are actually present, so this type is set always. - If the KHR_
materials_ pbrSpecularGlossiness extension is present, its properties are imported with MaterialType:: PbrSpecularGlossiness present in material types. - Additional normal, occlusion and emissive maps are imported, together with related properties
- If the KHR_
materials_ unlit extension is present, MaterialType:: Flat is set in material types, replacing MaterialType:: PbrMetallicRoughness or MaterialType:: PbrSpecularGlossiness. - If the KHR_
materials_ clearcoat extension is present, MaterialType:: PbrClearCoat is set in material types, and a new layer with clearcoat properties is added - Custom texture coordinate sets as well as KHR_
texture_ transform properties are imported on all textures. - If the on-by-default
phongMaterialFallback
configuration option is enabled, the importer provides a Phong fallback for backwards compatibility:- MaterialType::
Phong is added to material types - Base color and base color texture along with custom texture coordinate set and transformation, if present, is exposed as a diffuse color and texture, unless already present together with specular color / texture from the specular/glossiness material
- All other PhongMaterialData values are is kept at their defaults
- MaterialType::
Texture and image import
- Texture type is always Trade::
TextureData:: Type:: Texture2D, as glTF doesn't support anything else - Z coordinate of Trade::
TextureData:: wrapping() is always SamplerWrapping:: Repeat, as glTF doesn't support 3D textures glTF leaves the defaults of sampler properties to the application, the following defaults have been chosen for this importer:
- Minification/magnification/mipmap filter: SamplerFilter::
Linear, SamplerMipmap:: Linear - Wrapping (all axes): SamplerWrapping::
Repeat
- Minification/magnification/mipmap filter: SamplerFilter::
The importer supports the non-standard
GOOGLE_texture_basis
extension for referencing Basis Universal files, which then get loaded using BasisImporter (or an equivalent alias). The use is like this, equivalently to Basis own glTF example:{ ... "textures": [ { "extensions": { "GOOGLE_texture_basis": { "source": 0 } } } ], "images": [ { "mimeType": "image/x-basis", "uri": "texture.basis" } ], "extensionsUsed": [ "GOOGLE_texture_basis" ], "extensionsRequired": [ "GOOGLE_texture_basis" ] }
The MIME type is not standard either and the importer doesn't check its value. However, in case of embedded data URIs, the prefix has to be set to
data:application/octet-stream
as TinyGLTF has a whitelist for data URI detection and would treat the URI as a filename otherwise:{ ... "images": [ { "mimeType": "image/x-basis", "uri": "data:application/octet-stream;base64,..." } ] }
Plugin-specific config
It's possible to tune various output options through configuration(). See below for all options and their default values.
[configuration] # 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. See https://blender.stackexchange.com/q/5689 # and https://github.com/KhronosGroup/glTF-Blender-Exporter/pull/166 for more # information. 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 # 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
Access to internal importer state
Access to the underlying TinyGLTF structures it is provided through importer-specific data accessors:
- importerState() returns pointer to the
tinygltf::Model
structure. If you use this class statically, you get the concrete type instead of aconst void*
pointer as returned by AbstractImporter::importerState(). - AbstractMaterialData::
importerState() returns pointer to the tinygltf::Material
structure - CameraData::
importerState() returns pointer to the tinygltf::Camera
structure - ImageData::
importerState() returns pointer to the tinygltf::Image
structure - MeshData::
importerState() returns pointer to the tinygltf::Mesh
structure - ObjectData3D::
importerState() returns pointer to the tinygltf::Node
structure - SceneData::
importerState() returns pointer to the tinygltf::Scene
structure - SkinData::
importerState() returns pointer to the tinygltf::Skin
structure - TextureData::
importerState() returns pointer to the tinygltf::Texture
structure
The TinyGLTF header is installed alsongside the plugin and accessible like this:
#include <MagnumExternal/TinyGLTF/tiny_gltf.h>
Base classes
- class AbstractImporter
- Base for importer plugins.
Constructors, destructors, conversion operators
- TinyGltfImporter() explicit
- Default constructor.
-
TinyGltfImporter(PluginManager::
Manager<AbstractImporter>& manager) explicit - Constructor.
-
TinyGltfImporter(PluginManager::
AbstractManager& manager, const std:: string& plugin) explicit - Plugin manager constructor.
Public functions
- auto importerState() const -> const tinygltf::Model*
- Importer state.
Function documentation
Magnum:: Trade:: TinyGltfImporter:: TinyGltfImporter() explicit
Default constructor.
In case you want to open images, use TinyGltfImporter(PluginManager::
Magnum:: Trade:: TinyGltfImporter:: TinyGltfImporter(PluginManager:: Manager<AbstractImporter>& manager) explicit
Constructor.
The plugin needs access to plugin manager for importing images.
const tinygltf::Model* Magnum:: Trade:: TinyGltfImporter:: importerState() const
Importer state.
See class documentation for more information.