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
- At the moment, alignment rules for the
*.glb
layout are not respected.
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.
- 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. At the moment, the position attribute doesn't have the min
andmax
properties calculated even though required by the spec. - 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:: 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, and attribute index 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, and get duplicated (including the name) if the same mesh gets used with different materials.
- At the moment, alignment rules for vertex stride are not respected.
- At the moment, each attribute has its own dedicated buffer view instead of a single view being shared by multiple interleaved attributes. This also implies that for single-vertex meshes the buffer view size might sometimes be larger than stride, which is not allowed by the spec.
Image and texture export
- Images are converted using a converter specified in the
imageConverter
configuration option, propagating flags set via setFlags() and all configuration options from the[imageConverter]
group to it. An AbstractImageConverter plugin manager has to be registered using PluginManager::Manager:: registerExternalManager() for image conversion to work. - 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. Basis-encoded KTX2 files can be saved with the KHR_
texture_ basisu extension by setting imageConverter=BasisKtxImageConverter
. The MSFT_texture_ dds and EXT_ texture_ webp extensions are not exported because there's currently no image converter capable of saving DDS and WebP 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. - 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. 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
- Custom SceneFieldType::
Float, SceneFieldType:: UnsignedInt and SceneFieldType:: Int 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. - 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, duplicate fields including multiple mesh assignments are ignored with a warning
- At the moment, only a single scene can be exported. As a consequence, information about the default scene is redundant and thus not written.
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. copyright= generator=Magnum GltfSceneConverter # 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 [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.