class new in Git master
GltfSceneConverterglTF converter plugin
Exports full scenes to either *.gltf
files with an external *.bin
buffer or to a self-contained *.glb
. You can use GltfImporter to import scenes in this format.
Usage
This plugin depends on the Trade library and is built if WITH_GLTFSCENECONVERTER
is enabled when building Magnum Plugins. To use as a dynamic plugin, load "GltfSceneConverter"
via Corrade::
Additionally, if you're using Magnum as a CMake subproject, bundle the magnum-plugins repository and do the following:
set(WITH_GLTFSCENECONVERTER ON CACHE BOOL "" FORCE) add_subdirectory(magnum-plugins EXCLUDE_FROM_ALL) # So the dynamically loaded plugin gets built implicitly add_dependencies(your-app MagnumPlugins::GltfSceneConverter)
To use as a static plugin or as a dependency of another plugin with CMake, put FindMagnumPlugins.cmake into your modules/
directory, request the GltfSceneConverter
component of the MagnumPlugins
package and link to the MagnumPlugins::GltfSceneConverter
target:
find_package(MagnumPlugins REQUIRED GltfSceneConverter) # ... target_link_libraries(your-app PRIVATE MagnumPlugins::GltfSceneConverter)
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 recognizes SceneConverterFlag::
Mesh export
- The MeshData is exported with its exact binary layout. Only padding before and after an index view is omitted, the vertex buffer is saved verbatim into the glTF buffer. The vertex buffer may get padded with zeros at the end to satisfy glTF buffer bounds requirements.
- MeshPrimitive::
Points, Lines, LineLoop, LineStrip, Triangles, TriangleStrip and TriangleFan is supported by core glTF. Implementation-specific primitive types can't be exported. - Both non-indexed and indexed meshes with MeshIndexType::
UnsignedShort or MeshIndexType:: UnsignedInt are supported by core glTF, MeshIndexType:: UnsignedByte is supported but discouraged. Implementation-specific index types and non-contiguous index arrays can't be exported. - While glTF has a requirement that vertex / index count corresponds to the actual primitive type, the exporter doesn't check that at the moment. Attribute-less meshes and meshes with zero vertices are not allowed by the spec but GltfImporter supports them and they can be exported with a warning if you disable the
strict
configuration option. Attribute-less meshes with a non-zero vertex count are unrepresentable in glTF and thus can't be exported. - MeshAttribute::
Position in VertexFormat:: Vector3 is supported by core glTF; Vector3b, Vector3bNormalized, Vector3ub, Vector3ubNormalized, Vector3s, Vector3sNormalized, Vector3us or Vector3usNormalized will be exported with KHR_ mesh_ quantization being added to required extensions. Other formats or 2D positions are not supported. - MeshAttribute::
Normal in VertexFormat:: Vector3 is supported by core glTF; Vector3bNormalized and Vector3sNormalized will be exported with KHR_ mesh_ quantization being added to required extensions. No other formats are supported. - MeshAttribute::
Tangent in VertexFormat:: Vector4 is supported by core glTF; Vector4bNormalized and Vector4sNormalized will be exported with KHR_ mesh_ quantization being added to required extensions. No other formats are supported. Three-component tangents and separate bitangents will be exported as a custom _TANGENT3
/_BITANGENT
attributes under rules that apply to custom attributes as described below. - MeshAttribute::
TextureCoordinates in VertexFormat:: Vector2, Vector2ubNormalized and Vector2usNormalized are supported by core glTF. The data are by default Y-flipped unless the textureCoordinateYFlipInMaterial
configuration option is enabled. Vector2b, Vector2bNormalized, Vector2ub, Vector2s, Vector2sNormalized or Vector2us will be exported with KHR_mesh_ quantization being added to required extensions. Those can't be Y-flipped and thus require the textureCoordinateYFlipInMaterial
option to be explicitly enabled. Other formats are not supported. - MeshAttribute::
Color in VertexFormat:: Vector3 / Vector4, Vector3ubNormalized / Vector4ubNormalized and Vector3usNormalized / Vector4usNormalized are supported by core glTF. No other formats are supported. - MeshAttribute::
JointIds in VertexFormat:: UnsignedByteNormalized and VertexFormat:: UnsignedShortNormalized are supported by core glTF. glTF allows 32-bit integers only for index types, exporting VertexFormat:: UnsignedInt is possible with a warning if you disable the strict
configuration option. The attribute is required to have the array size divisible by four, each group of four elements is then exported as one attribute. - MeshAttribute::
Weights in VertexFormat:: Float, VertexFormat:: UnsignedByte and VertexFormat:: UnsignedShort are supported by core glTF. No other formats are supported. The attribute is required to have the array size divisible by four, each group of four elements is then exported as one attribute. - MeshAttribute::
ObjectId in VertexFormat:: UnsignedByte and VertexFormat:: UnsignedShort is exported as _OBJECT_ID
by default, use theobjectIdAttribute
configuration option to change the identifier name. glTF allows 32-bit integers only for index types, exporting VertexFormat::UnsignedInt is possible with a warning if you disable the strict
configuration option. - Custom attributes are exported with identifiers set via setMeshAttributeName(), and unless the custom attribute corresponds to a builtin glTF attribute, the name should be prefixed with a
_
to adhere to the spec. If no name was set for an attribute, it's exported with an underscore followed by its numeric value extracted using meshAttributeCustom(MeshAttribute). Allowed formats are VertexFormat::Float, Byte, ByteNormalized, UnsignedByte, UnsignedByteNormalized, Short, ShortNormalized, UnsignedShort, UnsignedShortNormalized, its 2-, 3- and 4-component vector counterparts, Matrix2x2, Matrix2x2bNormalizedAligned, Matrix2x2sNormalized, Matrix3x3, Matrix3x3bNormalizedAligned, Matrix3x3sNormalizedAligned, Matrix4x4, Matrix4x4bNormalized and Matrix4x4sNormalized. Exporting VertexFormat,UnsignedInt, Vector2ui, Vector3ui and Vector4ui is possible with a warning if you disable the strict
configuration option. Signed 32-bit integers, half-floats, doubles or packed types are not representable in glTF, implementation-specific vertex formats can't be exported. - MeshAttribute::
TextureCoordinates, MeshAttribute:: Color, (custom) JOINTS
andWEIGHTS
attributes are suffixed with_0
,_1
, ... for each occurence. Second and following occurences of other attributes are prefixed with an underscore if not already and suffixed with_1
,_2
, ..., so e.g. a second position attribute becomes_POSITION_1
. - Mesh name, if passed, is saved into the file. Additionally the buffer views and accessors referenced by it will be annotated with mesh ID and name if the
accessorNames
configuration option is enabled. - Due to a material and a mesh being tied together in a glTF file, meshes that are referenced by a scene are written in the order they are referenced from SceneData. They and get duplicated (including the name) if the same mesh gets used with different materials, but their vertex and index data stay shared. If multiple meshes are assigned to a single object, a glTF multi-primitive mesh is formed of them. In that case the name is preserved only if all meshes referenced by the object have the same. Meshes that were not referenced by any scene are written at the end, without any material assignment.
- At the moment, alignment rules for vertex stride are not respected.
- In some cases it might happen that the official Khronos glTF validator will warn about
min
/max
accessor bounds very slightly differing from the calculated values. This is a known issue due to the validator floating-point comparison being overly strict.
Image and texture export
- Images are converted using a converter specified in the
imageConverter
configuration option, propagating flags set via setFlags(). An AbstractImageConverter plugin manager has to be registered using PluginManager::Manager:: registerExternalManager() for image conversion to work. Options for a particular converter are meant to be set globally via PluginManager:: Manager:: metadata() through the image converter manager. - By default, images are saved as external files for a
*.gltf
output and embedded into the buffer for a*.glb
output. This behavior can be overriden using thebundleImages
configuration option on a per-image basis. - Core glTF supports only JPEG and PNG file formats, other formats are available via extensions:
- WebP can be saved with the EXT_
texture_ webp extension - Basis-encoded KTX2 files can be saved with the KHR_
texture_ basisu extension by setting imageConverter=BasisKtxImageConverter
The MSFT_texture_ dds extension is not exported because there's currently no image converter capable of saving DDS files. Other formats (such as TGA, OpenEXR...) are not supported by the spec but GltfImporter supports them and they can be exported if the strict
configuration option is disabled. Such images are then referenced directly without any extension.
- WebP can be saved with the EXT_
- If the
experimentalKhrTextureKtx
configuration option is enabled, generic KTX2 images can be saved with the proposed KHR_texture_ ktx extension. - Image and texture names, if passed, are saved into the file. Additionally the buffer views referenced by embedded images will be annotated with image ID and name if the
accessorNames
configuration option is enabled. - The texture is required to only be added after all images it references
- At the moment, there's no support for exporting multi-level images even though the KTX2 container is capable of storing these.
2D array texture export
If the experimentalKhrTextureKtx
configuration option is enabled, the plugin supports also 3D images and 2D array textures using a proposed KHR_
- Only KTX2 images are supported for 3D, i.e. with either
imageConverter=KtxImageConverter
orimageConverter=BasisKtxImageConverter
. They need to have ImageFlag3D::Array set. - Use a TextureType::
Texture2DArray texture to reference the 3D images. Due to how the extension is designed, the resulting glTF then has the texture duplicated for each layer of the image; GltfImporter then undoes the duplication again on import. - Due to how the extension is designed, the presence of the texture referencing the 3D image is essential for properly recognizing the image as 3D on import. Without it, the image gets recognized as 2D and the import will subsequently fail due to the image file not actually being 2D.
- A material referencing a 2D array texture implicitly uses the first (
0
) layer. Use the*TextureLayer
attributes (such as MaterialAttribute::BaseColorTextureLayer for a MaterialAttribute:: BaseColorTexture) to specify a layer. The layer index has to be smaller than the Z dimension of the image.
Material export
- Implicitly, only attributes that are different from glTF material defaults are written to save file on size. Enable the
keepMaterialDefaults
configuration option to write them as well. - Both a separate MaterialAttribute::
MetalnessTexture and MaterialAttribute:: RoughnessTexture as well as a combined MaterialAttribute:: NoneRoughnessMetallicTexture is supported, but either both or neither textures have to be present and have to satisfy glTF packing rules as described in PbrMetallicRoughnessMaterialData:: hasNoneRoughnessMetallicTexture(). - MaterialAttribute::
NormalTextureSwizzle has to be MaterialTextureSwizzle:: RGB, if present; MaterialAttribute:: OcclusionTextureSwizzle has to be MaterialTextureSwizzle:: R, if present. - If MaterialType::
Flat is present, the KHR_ materials_ unlit extension is included in the output. If MaterialType:: PbrMetallicRoughness is present, the output material has the pbrMetallicRoughness
material property object written even if it would be empty in order to make GltfImporter import the material with MaterialType::PbrMetallicRoughness set again. Without the type present, the pbrMetallicRoughness
object is written only if non-empty. Other MaterialTypes are ignored, the material is only filled based on the attributes present. - If MaterialLayer::
ClearCoat is present, the KHR_ materials_ clearcoat extension is included in the output. - If any MaterialAttribute::
*TextureMatrix attributes are present, the KHR_ texture_ transform extension is included in the output. At the moment, only offset and scaling is written, rotation is ignored with a warning. If the textureCoordinateYFlipInMaterial
configuration option is enabled, all material textures will contain an Y-flip transformation in addition to any existing transformation. - Material names, if passed, are saved into the file
- The material is required to only be added after all textures it references, in case of 2D array textures it's also required to reference only existing layers
- An informational warning is printed for all attributes that were unused due to not having a glTF equivalent, due to referring to a texture but the texture attribute isn't present or due to the support not being implemented yet. The only exception is Phong MaterialAttribute::
DiffuseColor and DiffuseTexture attributes if they match the corresponding MaterialAttribute:: BaseColor / BaseColorTexture attributes. Such attributes are produced by GltfImporter for compatibility purposes when the phongMaterialFallback
configuration option is enabled and are redundant. - Custom material attributes and layers are exported in a way inverse to what GltfImporter does, with the intent to fully preserve yet-unrecognized extensions and material extras if an imported glTF file is exported back:
- Custom attributes (i.e., ones not starting with an uppercase letter) in the base layers are written to glTF
extras
object in the material - Custom layers with a name that start with a
#
are assumed to be glTF extensions and are written to glTFextensions
object in the material, with the layer name (except the#
) used as extension name. Other custom layers and unnamed layers are ignored with a warning. - MaterialAttributeType::
String, Bool and Float are exported as-is, UnsignedInt, Int, UnsignedLong and Long are converted to a JSON double-precision number. Deg and Rad are exported as a plain number, losing their original unit - MaterialAttributeType::
Vector2, Vector3 and Vector4 are exported as numeric arrays, Vector2ui, Vector2i, Vector3ui, Vector3i, Vector4ui and Vector4i are converted to arrays of JSON double-precision numbers. - Custom attributes inside extension layers that end with
*Texture
and are MaterialAttributeType::UnsignedInt are recognized as texture references and written as a glTF textureInfo objects, with corresponding *TextureLayer
attributes (if they are MaterialAttributeType::UnsignedInt) then recognized as 2D array texture layers, *TextureCoordinates
(if MaterialAttributeType::UnsignedInt) as coordinate index and *TextureMatrix
(if MaterialAttributeType::Matrix3x3) as a texture matrix. Layer-local and global fallback to MaterialAttribute:: TextureLayer, TextureCoordinates and TextureMatrix applies to the custom attributes as well. The texture ID and layer attributes are bounds-checked against existing textures and layer count of existing textures and the whole texture is ignored with a warning if either of the two is outside of the bounds. If any of these has an unexpected type, it's ignored with a warning. *Texture
and related attributes inside the base layer (as opposed to custom layers) have no special handling, so they'll be exported as numbers.*Texture
-related attributes inside extension layers that have no base*Texture
attribute are ignored with a warning.- MaterialAttributeType::
Pointer, MutablePointer and Buffer attributes are ignored with a warning. - Custom MaterialAttributeType::
TextureSwizzle attributes are always ignored with a warning, as glTF doesn't have a builtin way to describe a texture swizzle. (In contrast, builtin MaterialAttributeType:: TextureSwizzle attributes are used to check if given texture is compatible with the layout glTF expects or potentially used to pick a glTF extension that enables support for given swizzle.) - MaterialAttributeType::
Matrix2x2 and other matrix attributes, except for MaterialAttribute:: TextureMatrix as described above, are ignored with a warning. While they could be flattened to JSON arrays as well, it's impossible to know whether they're a vector or a matrix on import and so they're not exported at the moment because GltfImporter wouldn't be able to import them anyway. - Attributes in extension layers starting with an uppercase letter, except for MaterialAttribute::
TextureLayer, TextureCoordinates and TextureMatrix, are ignored with a warning.
- Custom attributes (i.e., ones not starting with an uppercase letter) in the base layers are written to glTF
Scene export
- Only 3D scenes are supported
- Only objects with a SceneField::
Parent entry are exported, all other objects are ignored with a warning. This also implies that object IDs are not preserved, as otherwise the glTF would contain a lot of empty unreferenced node objects. - The SceneField::
Parent hierarchy is required to be acyclical - To satisfy glTF requirements, if both SceneField::
Transformation and at least one of Translation, Rotation and Scaling is present, only the TRS component(s) are saved into the file and not the matrix, assuming the transformation matrix is equivalent to them - Object and scene names, if passed, are saved into the file
- The scene is required to only be added after all meshes and materials it references
- Multiple SceneField::
Mesh and SceneField:: MeshMaterial entries per object are turned into multi-mesh primitives. Other duplicate builtin fields are ignored with a warning. - Custom SceneFieldType::
Float, UnsignedInt, Int, Bit and string fields are exported if a name is set for them via setSceneFieldName(). Custom fields of other types and without a name assigned are ignored with a warning. Fields that have SceneFieldFlag:: MultiEntry set are exported as arrays, otherwise duplicate entries for the same object are ignored with a warning. - At the moment, only SceneField::
Parent, Transformation, Translation, Rotation, Scaling, Mesh and MeshMaterial is exported, other builtin fields are ignored with a warning - At the moment, only a single scene can be exported. Default scene index is however only written if setDefaultScene() is called.
Plugin-specific config
It's possible to tune various output options through configuration(). See below for all options and their default values:
[configuration] # Copyright and generator name, written into the asset object. If empty, no # value is written. The {0} placeholder, if present, will be replaced with # Corrade, Magnum and Magnum Plugins version info including Git commit hashes # if the plugin is built in Release from a non-sparse Git clone. copyright= generator=Magnum GltfSceneConverter {0} # Add one or more extensionUsed and/or extensionRequired values to populate # the extension usage and requirement arrays. # Whether to write a *.gltf or a *.glb file. If empty, detected automatically # based on filename extension, conversion to data defaults to a binary file. # If a text file is selected for conversion to data, converting anything that # involves binary buffers will currently fail. binary= # Name all buffer views and accessors to see what they belong to. Useful for # debugging purposes. The option can be also enabled just for a particular # add() operation and then disabled again to reduce the impact on file sizes. accessorNames=false # Allow only strictly valid glTF files. Disallows: # - Meshes with zero vertices, zero indices or zero attributes # - Meshes with 32-bit integer attributes # - Image formats that don't have a corresponding glTF extension # Magnum's GltfImporter will be able to open files with this option unset # (unless it's own strict option is enabled), but other libraries may fail. # The option can be also disabled just for a particular add() operation and # then enabled again to not loosen up validation for everything at once. strict=true # 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 beginning a file, # changing it during conversion will have undefined behavior. textureCoordinateYFlipInMaterial=false # The non-standard MeshAttribute::ObjectId is by default recognized under # this name. Change if you want to export it under a different identifier. objectIdAttribute=_OBJECT_ID # Implicitly, only material attributes that differ from glTF material # defaults are written. Enable to unconditionally save all attributes present # in given MaterialData. Attributes that are not present in given # MaterialData are saved only if the Magnum default differs from the glTF # default and this option doesn't affect them. keepMaterialDefaults=false # Whether to bundle images in buffers. If empty, images are bundled for *.glb # files and saved externally for *.gltf files. Can be set differently for # each add() operation. bundleImages= # Experimental KHR_texture_ktx support. The extension is not stabilized yet, # thus the implementation may not reflect latest changes to the proposal. experimentalKhrTextureKtx=false # Image converter to use. Can be set differently for each add() operation in # order to export different images in different formats. Formats that don't # have any corresponding glTF image extension are allowed only with the # strict option unset. imageConverter=PngImageConverter # Configuration options to propagate to the image converter. Obsolete, prefer # to set the converter options directly through the plugin manager. [configuration/imageConverter]
See Editing plugin-specific configuration for more information and an example showing how to edit the configuration values.
Base classes
- class AbstractSceneConverter new in 2020.06
- Base for scene converter plugins.
Constructors, destructors, conversion operators
-
GltfSceneConverter(PluginManager::
AbstractManager& manager, const Containers:: StringView& plugin) explicit - Plugin manager constructor.