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. ImporterFlag::Quiet is recognized as well and causes all import warnings to be suppressed. All ImporterFlags are also propagated to image importer plugins the importer delegates to.

Scene import

Material import

  • Supports both legacy FBX Phong material model and more modern PBR materials, in some cases both are defined as PBR materials may have a legacy Phong material filled as a fallback.
  • PBR material properties in OBJ files are supported as well.
  • The legacy FBX material model and most PBR material models have factors for various attributes, by default these are premultiplied into the value but you can retain them using the preserveMaterialFactors configuration option
  • ufbx tries to normalize the various vendor-specific PBR material modes into a single set of attributes that are imported, see PBR material attributes for an exhaustive listing.
  • MaterialAttribute::DiffuseTextureMatrix and similar matrix attributes for other textures are imported.
  • MaterialAttribute::DiffuseTextureCoordinates and similar UV layer attributes are not supported, as FBX stores them as UV set names instead of layer indices, and the conversion would be fragile.
  • FBX materials have no equivalent for the MaterialAttribute::DoubleSided, MaterialAttribute::AlphaMask and MaterialAttribute::AlphaBlend properties, and thus they are undefined for materials.
  • In addition to opening OBJ files, ufbx allows directly opening a .mtl file, which will result in just the material data being parsed, without any meshes or a scene present.

Light import

  • LightType::Directional and LightType::Ambient expect the attenuation to be constant, but FBX is not required to follow that. In that case the attenuation value from the file is ignored.
  • Area and volume lights are not supported

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.

Animation and skin import

  • FBX represents rotations using Euler angles, which are converted to quaternions on import.
  • Cubic FBX animation curves are resampled to linear interpolation as time tangents prevent representing them via cubic Hermite splines. The resampling rate can be configured via the resampleRate configuration option.
  • As FBX represents rotations using Euler angles, even linear rotations are resampled by default to preserve the original motion. This can be disabled via the resampleRotation configuration option.
  • FBX supports animating object visibility as well, which are imported with a custom animation track target named "visibility"
  • Morph targets are not supported
  • Animation tracks are always imported with Animation::Extrapolation::Constant because FBX does not contain any extrapolation information.
  • UfbxImporter imports FBX animation stacks as individual animations by default. You can specify the animationLayers configuration option to import each animation layer as an individual animation. Currently this loses information about what layers animation stacks contain.
  • As many FBX exporters resample animations already, to avoid double resampling UfbxImporter will avoid resampling closely spaced keyframes. This interval can be adjusted via the minimumSampleRate configuration option.
  • Constant keyframes are represented as nearly-equal time keyframes. The constant interpolation interval can be adjusted via the constantInterpolationDuration configuration option.
  • Skin deformers are supported but only the first skin deformer for a mesh is imported at the moment.

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

# Maximum number of joint weights per vertex, use negative for unbounded.
maxJointWeights=-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

# Import individual animation layers instead of animation stacks.
animationLayers=false

# Sampling rate in Hz (frames per second) for non-linear animation curves.
resampleRate=30

# Resample rotation to preserve Euler interpolation in the file.
resampleRotation=true

# Minimum sampling rate for animation that will not be resampled.
minimumSampleRate=20

# Time interval in seconds for non-continuous steps in the animation.
constantInterpolationDuration=0.001

# Include all TRS components always if even one is defined
animateFullTransform=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.