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

FBX and OBJ importer using ufbx.

Imports FBX files using ufbx, also supports OBJ files despite the name.

This plugin provides FbxImporter and ObjImporter.

Usage

This plugin depends on the Trade and MeshTools libraries and the AnyImageImporter plugin and is built if MAGNUM_WITH_UFBXIMPORTER is enabled when building Magnum Plugins. To use as a dynamic plugin, load "UfbxImporter" 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_UFBXIMPORTER ON CACHE BOOL "" FORCE)
add_subdirectory(magnum-plugins EXCLUDE_FROM_ALL)

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

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

find_package(MagnumPlugins REQUIRED UfbxImporter)

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

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 FileCallback features. Immediate dependencies are loaded during the initial import meaning the callback is called with InputFileCallbackPolicy::LoadTemporary. 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 importer recognizes ImporterFlag::Verbose if built in debug mode (CORRADE_IS_DEBUG_BUILD defined or NDEBUG not defined). The verbose logging prints detailed ufbx-internal callstacks on load failure that can be used for debugging or reporting issues.

Animations and skinning-related data are not imported at the moment.

Scene import

Material import

Light import

Mesh import

  • Vertex creases and any edge or face attributes are not imported
  • The importer follows types used by ufbx truncated to 32-bit, thus indices are always MeshIndexType::UnsignedInt, positions, normals, tangents and bitangents are always imported as VertexFormat::Vector3, texture coordinates as VertexFormat::Vector2 and colors as VertexFormat::Vector4. Most FBX files contain geometry data natively as double-precision floats.
  • If a mesh contains multiple materials it is split into parts and the node contains each part as a separate mesh/material entry.
  • If a mesh contains faces with 1 or 2 vertices (ie. points or lines) they are separated to meshes with the correct primitives (MeshPrimitive::Points and Lines)
  • Faces with more than three vertices are triangulated and represented as MeshPrimitive::Triangles.

The meshes are indexed by default unless generateIndices configuration option is disabled. Vertex position is always defined, normals can be missing unless generateMissingNormals configuration option is set. There are an arbitrary amount of UV/tangent/bitangent/color sets, you can specify a maximum limit using maxUvSets, maxTangentSets and maxColorSets configuration options, note that setting any to zero disables loading any tangents etc.

Texture import

  • Only textures with filenames are retained in the imported scene as textures.
  • Layered textures are converted into material layers.
  • FBX textures have no defined SamplerFilter, so UfbxImporter sets all filters to SamplerFilter::Linear.

Image import

  • Both external and embedded images are supported via the AnyImageImporter plugin.
  • Only 2D images are supported.

Scene processing

Plain FBX files can be tedious to work with as they can contain unusual scene graph features and may be defined in arbitrary coordinate/unit spaces. ufbx can process the scene representation internally to make it easier to interpret, which is exposed as configuration options explained below.

Unit normalization

FBX supports arbitrary coordinate systems and units. The default unit is in centimeters (which can often be seen as exporting a file from Blender with the default settings and ending up with a file where everything is 100x larger), though meters and even inches are reasonably common. The coordinate systems most commonly are right-handed Y-up or Z-up.

Currently the plugin does not support querying the coordinate/unit system of the file so the only way to deal with units is using the normalizeUnits configuration option. This will normalize the file into the glTF system: units are one meter and the coordinates are +X right, +Y up, -Z forward (+Z front in FBX terms). By default the option will adjust the object transforms directly, meaning if you load a file authored in the glTF space it should look like what it did before exporting.

If you want to retain the node transformations written in the FBX file, you can set unitNormalizationHandling=transformRoot in the configuration, this will result in the scene containing an additional root node containing the unit/axis transform as transform/rotation/scaling.

Geometry transforms

FBX nodes can contain somewhat confusingly named "geometric transforms" which are referred to "geometry transforms" here for clarity. These transformations only affect the immediate geometry (or rarely attached light, camera, etc.) of the node, without transforming the child nodes. Most scene graphs don't natively support this, including the standard one in SceneData.

By default UfbxImporter creates "helper nodes" that contain the geometry transforms, so by default they will be transparently supported without any extra implementation effort. SceneData returned by UfbxImporter contains an extra SceneField named "GeometryTransformHelper" mapped implicitly per node containing information whether a node is a helper or a normal one.

You can change how UfbxImporter handles the geometry transforms via the geometryTransformHandling configuration option, the default option being helperNodes.

Using modifyGeometry will attempt to elide the helper nodes by modifying the actual mesh geometry, "baking" the geometry transform into the vertex data. This will fall back into creating helper nodes if necessary, for example for lights/cameras or instanced meshes.

Using preserve will not modify the scene at all and exposes the original geometry transform values via three additional SceneFields per node: "GeometryTranslation" (SceneFieldType::Vector3d), "GeometryRotation" (SceneFieldType::Quaterniond) and "GeometryRotation" (SceneFieldType::Vector3d). These behave in the same way as the standard SceneField::Translation, Rotation and Scaling, but affect only the immediate geometry of the node.

PBR material attributes

ufbx normalizes PBR materials into a superset of all vendor-specific PBR material models that ufbx supports, these attributes are exposed as custom MaterialAttribute names.

Majority of the attributes match Autodesk Standard Surface parameters:

LayerAttributeTypeOSL parameter
(base)baseColorFactor 1Floatbase
(base)BaseColorVector4base_color
(base)RoughnessFloatspecular_roughness
(base)MetalnessFloatmetalness
(base)diffuseRoughnessFloatdiffuse_roughness
(base)specularColorFactor 1Floatspecular
(base)SpecularColorVector4specular_color
(base)specularIorFloatspecular_IOR
(base)specularAnisotropyFloatspecular_anisotropy
(base)specularRotationFloatspecular_rotation
(base)thinFilmThicknessFloatthin_film_thickness
(base)thinFilmIorFloatthin_film_IOR
(base)emissiveColorFactor 1Floatemission
(base)EmissiveColorVector3emission_color
(base)opacityVector3opacity
ClearCoatLayerFactorFloatcoat
ClearCoatcolorVector4coat_color
ClearCoatRoughnessFloatcoat_roughness
ClearCoatiorFloatcoat_IOR
ClearCoatanisotropyFloatcoat_anisotropy
ClearCoatrotationFloatcoat_rotation
ClearCoatNormalTextureUnsignedIntcoat_normal
transmissionLayerFactorFloattransmission
transmissioncolorVector4transmission_color
transmissiondepthFloattransmission_depth
transmissionscatterVector3transmission_scatter
transmissionscatterAnisotropyFloattransmission_scatter_anisotropy
transmissiondispersionFloattransmission_dispersion
transmissionextraRoughnessFloattransmission_extra_roughness
subsurfaceLayerFactorFloatsubsurface
subsurfacecolorVector4subsurface_color
subsurfaceradiusVector3subsurface_radius
subsurfacescaleFloatsubsurface_scale
subsurfaceanisotropyFloatsubsurface_anisotropy
sheenLayerFactorFloatsheen
sheencolorVector3sheen_color
sheenRoughnessFloatsheen_roughness
1.
Requires preserveMaterialFactors configuration option to be enabled.

Other attributes not defined by the OSL Standard Surface:

LayerAttributeTypeDescription
(base)GlossinessFloatInverse of roughness used by some material models
(base)NormalTextureUnsignedIntTangent-space normal map texture
(base)OcclusionTextureUnsignedIntAmbient occlusion texture
(base)tangentTextureUnsignedIntTangent re-orientation texture
(base)displacementTextureUnsignedIntDisplacement texture
(base)displacementFactorFloatDisplacement texture weight
(base)indirectDiffuseFloatFactor for indirect diffuse lighting
(base)indirectSpecularFloatFactor for indirect specular lighting
ClearCoatGlossinessFloatInverse of roughness used by some material models
ClearCoataffectBaseColorFloatModify the base color based on the coat color
ClearCoataffectBaseRoughnessFloatModify the base roughness based on the coat roughness
transmissionRoughnessFloatTransmission roughness (base Roughness not added)
transmissionGlossinessFloatInverse of roughness used by some material models
transmissionpriorityLongIOR transmission priority
transmissionenableInAovBoolRender transmission into AOVs (Arbitrary Output Variable)
subsurfacetintColorVector4Extra tint color that is multiplied after SSS calculation
subsurfacetypeLongShader-specific subsurface random walk type
matteLayerFactorFloatMatte surface weight
mattecolorVector3Matte surface color

Plugin-specific configuration

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

[configuration]
# Generate normals if missing.
generateMissingNormals=false

# Fail if the file is slightly malformed.
strict=false

# Disable any exporter-specific quirks in the importer.
disableQuirks=false

# Attempt to load further files referenced by this file.
# On .obj files this would include .mtl files.
loadExternalFiles=true

# Ignore all geometry (vertices, indices) during loading.
ignoreGeometry=false

# Ignore all animation data (curves) during loading.
ignoreAnimation=false

# Ignore embedded data (such as images) during loading.
ignoreEmbedded=false

# Ignore all the actual content in the file, only loading the scene
# information such as object relationships and names.
ignoreAllContent=false

# Maximum amount of temporary memory in bytes to use, negative for unlimited.
# Loading is aborted if memory usage exceeds this limit.
maxTemporaryMemory=-1

# Maximum amount of result memory in bytes to use, negative for unlimited.
# Loading is aborted if memory usage exceeds this limit.
maxResultMemory=-1

# Normalize units to meters with right-handed Y up coordinates.
# This coordinate/unit system matches the glTF specification.
normalizeUnits=false

# Method of handling FBX "geometric transforms" that offset geometry from
# nodes without affecting children in the hierarchy. Possible values:
#  - helperNodes -- add dummy nodes between nodes and meshes where needed
#  - modifyGeometry -- modify the geometry data if possible, fall back to
#    helperNodes in some edge cases.
#  - preserve -- retain the geometry transforms as additional custom
#    SceneFields -- GeometryTranslation as Vector3d, GeometryRotation as
#    Quaterniond and GeometryScaling as Vector3d
geometryTransformHandling=helperNodes

# Method of handling normalizeUnits. Note that if set to transformRoot the
# root node is retained even if normalizeUnits=false. Possible values:
#  - adjustTransforms -- modify the top-level node transforms
#  - transformRoot -- retain an additional root node where the
#    coordinate/unit transform is stored as a normal TRS tuple
unitNormalizationHandling=adjustTransforms

# Deduplicate raw vertex data to an indexed mesh.
generateIndices=true

# Maximum number of UV sets per vertex, use negative for unbounded.
maxUvSets=-1

# Maximum number of tangent/bitangent sets per vertex, use negative for
# unbounded.
maxTangentSets=-1

# Maximum number of vertex color sets per vertex, use negative for unbounded.
maxColorSets=-1

# Preserve factor attributes for materials instead of premultiplying them.
# For example instead of a single BaseColor the importer would return both
# BaseColor and baseColorFactor.
preserveMaterialFactors=false

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

Base classes

class AbstractImporter
Base for importer plugins.

Constructors, destructors, conversion operators

UfbxImporter(PluginManager::AbstractManager& manager, const Containers::StringView& plugin) explicit
Plugin manager constructor.