Magnum::Trade::AssimpImporter class

Assimp importer.

Imports various formats using Assimp, in particular:

  • Autodesk FBX (*.fbx)
  • COLLADA (*.dae)
  • glTF (*.gltf, *.glb)
  • Blender 3D (*.blend)
  • 3ds Max 3DS and ASE (*.3ds, *.ase)
  • 3D Manufacturing Format (*.3mf)
  • Wavefront OBJ (*.obj)
  • Industry Foundation Classes (IFC/Step) (*.ifc)
  • XGL (*.xgl, *.zgl)
  • Stanford PLY (*.ply)
  • AutoCAD DXF (*.dxf)
  • LightWave, LightWave Scene (*.lwo, *.lws)
  • Modo (*.lxo)
  • Stereolithography (*.stl)
  • DirectX X (*.x)
  • AC3D (*.ac)
  • Milkshape 3D (*.ms3d)
  • TrueSpace (*.cob, *.scn)
  • Biovision BVH (*.bvh)
  • CharacterStudio Motion (*.csm)
  • Ogre XML (*.xml)
  • Irrlicht Mesh and Scene (*.irrmesh, *.irr)
  • Quake I (*.mdl)
  • Quake II (*.md2)
  • Quake III Mesh (*.md3)
  • Quake III Map/BSP (*.pk3)
  • Return to Castle Wolfenstein (*.mdc)
  • Doom 3 (*.md5*)
  • Valve Model (*.smd, *.vta)
  • Open Game Engine Exchange (*.ogex)
  • Unreal (*.3d)
  • BlitzBasic 3D (*.b3d)
  • Quick3D (*.q3d, *.q3s)
  • Neutral File Format (*.nff)
  • Sense8 WorldToolKit (*.nff)
  • Object File Format (*.off)
  • PovRAY Raw (*.raw)
  • Terragen Terrain (*.ter)
  • 3D GameStudio (3DGS), 3D GameStudio (3DGS) Terrain (*.mdl, *.hmp)
  • Izware Nendo (*.ndo)

Supports importing of scene, object, camera, mesh, texture, image, animation and skin data.

This plugin provides 3dsImporter, 3mfImporter, Ac3dImporter, BlenderImporter, BvhImporter, CsmImporter, ColladaImporter, DirectXImporter, DxfImporter, FbxImporter, GltfImporter, IfcImporter, IrrlichtImporter, LightWaveImporter, ModoImporter, MilkshapeImporter, ObjImporter, OgreImporter, OpenGexImporter, StanfordImporter, StlImporter, TrueSpaceImporter, UnrealImporter, ValveImporter and XglImporter plugins.


This plugin depends on the Trade and Assimp libraries and the AnyImageImporter plugin and is built if MAGNUM_WITH_ASSIMPIMPORTER is enabled when building Magnum Plugins. To use as a dynamic plugin, load "AssimpImporter" via Corrade::PluginManager::Manager.

Additionally, if you're using Magnum as a CMake subproject, bundle the magnum-plugins and assimp repositories and do the following. If you want to use system-installed Assimp, omit the first part and point CMAKE_PREFIX_PATH to its installation dir if necessary.

# Disable Assimp tests, tools and exporter functionality
# If you won't be accessing Assimp outside of the plugin, build it as static to
# have the plugin binary self-contained
# The following is important to avoid Assimp appending `d` to all your
# binaries. You need Assimp >= 5.0.0 for this to work, also note that after
# 5.0.1 this option is prefixed with ASSIMP_, so better set both variants.
add_subdirectory(assimp EXCLUDE_FROM_ALL)

add_subdirectory(magnum EXCLUDE_FROM_ALL)

add_subdirectory(magnum-plugins EXCLUDE_FROM_ALL)

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

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

find_package(MagnumPlugins REQUIRED AssimpImporter)

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

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, OpenState and FileCallback features. The Assimp library loads everything during initial import, meaning all external file loading callbacks are called with InputFileCallbackPolicy::LoadTemporary and the resources can be safely freed right after the openData() / openFile() function exits. In some cases, Assimp will explicitly call InputFileCallbackPolicy::Close on the opened file and then open it again. 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, enabling verbose logging in Assimp when the flag is enabled. However please note that since Assimp handles logging through a global singleton, it's not possible to have different verbosity levels in each instance.

Scene import

Animation and skin import

  • Assimp sometimes adds dummy animation tracks with a single key-value pair and the default node transformation. If found, the importer removes these dummy tracks and prints a message if verbose logging is enabled. Can be disabled per-animation with the removeDummyAnimationTracks configuration option.
  • Channel order within animations is not always preserved by Assimp, depending on file type and compiler. You may have to manually order tracks by type and target after importing.
  • 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 configuration option.
  • If quaternion rotation tracks are not normalized, the importer prints a warning and normalizes them. Can be disabled per-animation with the normalizeQuaternions configuration option.
  • Morph targets are not supported
  • Animation tracks are always imported with Animation::Interpolation::Linear, because Assimp doesn't expose any interpolation modes
  • Animation tracks using aiAnimBehaviour_DEFAULT or aiAnimBehaviour_REPEAT are currently not implemented and fall back to using Animation::Extrapolation::Constant
  • 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 either 0 or 1 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.
  • Assimp versions before commit e3083c21f0a7beae6c37a2265b7919a02cbf83c4 read spline-interpolated glTF animation tracks incorrectly and produce broken animations. A warning is printed when importing glTF animations on these versions. Because it's impossible to detect the actual brokenness, the warning is printed even if the imported data may be correct.
  • Original skins are not exposed by Assimp, instead each mesh with joint weights produces its own skin. Skin names will be equal to their corresponding mesh names. A consequence of this is that Assimp only imports joint weight attributes for one skin and ignores all other skins targetting the same mesh.
  • You can request to merge all mesh skins into one using the mergeSkins option. Duplicate joints (same object index and inverse bind matrix) will be merged and joint ids in vertex attributes adjusted accordingly. When this option is enabled, skin3DCount() always report either 0 or 1 and the merged skin has no name. This option needs to be set before opening a file because it affects skin as well as mesh loading.

Material import

  • Assimp has no concept of an unassigned material and thus it may create dummy materials and assign them to meshes that have no material specified
  • Only materials with shading mode aiShadingMode_Phong are supported
  • Two-sided property and alpha mode is not imported
  • Unrecognized Assimp material attributes are imported with their raw names and types. You can find the attribute names in assimp/material.h. Unknown or raw buffer types are imported as MaterialAttributeType::String. To ignore all unrecognized Assimp materials instead, enable the ignoreUnrecognizedMaterialData configuration option.
  • To load all material attributes with the raw Assimp names and types, enable the forceRawMaterialData configuration option. You will then get attributes like $clr.diffuse instead of MaterialAttribute::DiffuseColor. MaterialData::types() will always be empty with this option enabled.
  • Assimp seems to ignore ambient textures in COLLADA files
  • For some reason, Assimp 4.1 imports STL models with ambient set to 0xffffff_srgbf, which causes all other color information to be discarded. If such a case is detected and there's no ambient texture present, the ambient is forced back to 0x000000_srgbf. See also assimp/assimp#2059. This workaround can be disabled using the forceWhiteAmbientToBlack configuration option.
  • MaterialAttribute::DiffuseTextureMatrix and similar matrix attributes for other textures are imported, although it's currently unclear whether the transformation is correct when texture rotations are involved

Light import

  • LightData::intensity() is always 1.0f, instead Assimp premultiplies LightData::color() with the intensity
  • The following properties are ignored:
    • Specular color
    • Custom light orientation vectors — the orientation is always only inherited from the node containing the light
  • LightData::Type::Directional and LightData::Type::Ambient expect the attenuation to be constant, but Assimp doesn't follow that for certain file formats (such as Blender). In that case the attenuation value from Assimp is ignored.
  • Area lights are not supported
  • For certain file formats (such as COLLADA), if a light isn't referenced by any node, it gets ignored during import

Camera import

  • Up vector property is not imported
  • Orthographic camera support requires Assimp 5.1.0. Earlier versions import them as perspective cameras with arbitrary field of view and aspect ratio.
  • For certain file formats (such as COLLADA), if a camera isn't referenced by any node, it gets ignored during import

Mesh import

  • Only point, triangle, and line meshes are loaded (quad and poly meshes are triangularized by Assimp)
  • Custom mesh attributes (such as object_id in Stanford PLY files) are not imported.
  • Texture coordinate layers with other than two components are skipped
  • Per-face attributes in Stanford PLY files are not imported.
  • Stanford PLY files that contain a comment before the format line fail to import.
  • The importer follows types used by Assimp, 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. In other words, everything gets expanded by Assimp to floats, even if the original file might be using different types.
  • The imported model always has either both MeshAttribute::Tangent MeshAttribute::Bitangent or neither of them, tangents are always three-component with binormals separate.
  • Skin joint IDs are imported as arrays of VertexFormat::UnsignedInt, skin weights then as arrays of VertexFormat::Float, with MeshData::attributeArraySize() varying based on how many per-vertex weights there's at most in given mesh. You can limit this with the maxJointWeights configuration option. For backwards compatibility, unless the compatibilitySkinningAttributes configuration option or MAGNUM_BUILD_DEPRECATED is disabled, these are also exposed as custom "JOINTS" and "WEIGHTS" attributes with VertexFormat::Vector4ui and VertexFormat::Vector4 (non-array) formats, respectively, with as many instances of these as needed to cover all array items. The compatibility attributes alias the builtin ones, i.e. point to the same memory, so their presence causes no extra overhead.
  • Assimp doesn't correctly import glTF meshes with multiple sets of joint weights prior to version 5.2.5. Depending on the version it either fails to import the file at all or imports either the first or the last set of joint weights. A warning is printed when this is detected, but it may misfire for other meshes with non-normalized weights.
  • Multi-primitive meshes are split by Assimp into individual meshes, nodes that reference a multi-primitive mesh have multiple SceneField::Mesh (and SceneField::MeshMaterial) entries in the imported SceneData.
  • For certain file formats (such as COLLADA), if a mesh isn't referenced by any node, it gets ignored during import

The mesh is always indexed; positions are always present, normals, colors and texture coordinates are optional.

Texture import

  • Textures with mapping mode/wrapping aiTextureMapMode_Decal are loaded with SamplerWrapping::ClampToEdge
  • Assimp does not appear to load any filtering information
  • Raw embedded image data is not supported

Plugin-specific configuration

Assimp has a versatile set of configuration options and processing operations applied on imported scenes. A subset of these is exposed via configuration(), the full form shown below. The first group of options matches the AI_CONFIG_* macros and has to be applied before opening first file with given plugin instance; to change them again you need to create a new importer instance.

The [postprocess] subgroup contains boolean toggles that correspond to the aiPostProcessSteps enum. Some of them are enabled by default, some not; options for not yet supported features are omitted. These are passed to Assimp when opening a file, meaning a change in these will be always applied to the next opened file.

# Controls the workaround for an Assimp 4.1 "white ambient" bug

# Optimize imported linearly-interpolated quaternion animation tracks to
# ensure shortest path is always chosen. This can be controlled separately
# for each animation import.

# Normalize quaternion animation tracks, if they are not already.
# This can be controlled separately for each animation import.

# 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. For more information see
# and

# Remove dummy animation tracks inserted by Assimp that contain only a single
# key/value pair with the default node transformation

# Maximum amount of joint weights per vertex to import as vertex attributes.
# A value of 0 disables any limit, any other value implicitly enables
# aiProcess_LimitBoneWeights. This can be changed only before the first file
# is opened.

# Expose MeshAttribute::JointIds and Weights under custom "JOINTS" and
# "WEIGHTS" aliases for backwards compatibility with code that relies on
# those being present. If Magnum is built with MAGNUM_BUILD_DEPRECATED
# disabled, no aliases are provided and this option is ignored.

# Merge all skins into a single skin. Since Assimp exposes one skin for each
# mesh with joint weights, this is useful for getting a single skin covering
# all meshes in the file. This can only be controlled on a per-file basis.

# AI_CONFIG_* values, can be changed only before the first file is opened

# By default material attributes that aren't recognized as builtin attributes
# are imported with raw Assimp names and types. Enabling this option
# completely ignores unrecognized attributes instead.

# Don't attempt to recognize builtin material attributes and always import
# them as raw material data (so e.g. instead of DiffuseColor you'll get
# $clr.diffuse). Implicitly disables ignoreUnrecognizedMaterialData. Mainly
# for testing purposes.

# aiPostProcessSteps, applied to each opened file
# See the maxJointWeights option for LimitBoneWeights instead

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

Access to internal importer state

The Assimp structures used to import data from a file can be accessed through importer state methods:

Base classes

class AbstractImporter
Base for importer plugins.

Constructors, destructors, conversion operators

AssimpImporter() explicit
Default constructor.
AssimpImporter(PluginManager::Manager<AbstractImporter>& manager) explicit
AssimpImporter(PluginManager::AbstractManager& manager, const Containers::StringView& plugin) explicit
Plugin manager constructor.

Function documentation

Magnum::Trade::AssimpImporter::AssimpImporter() explicit

Default constructor.

In case you want to open images, use AssimpImporter(PluginManager::Manager<AbstractImporter>&) instead.

Magnum::Trade::AssimpImporter::AssimpImporter(PluginManager::Manager<AbstractImporter>& manager) explicit


The plugin needs access to plugin manager for importing images.