Imports various formats using Assimp, in particular:
- Autodesk FBX (
- COLLADA (
- glTF (
- Blender 3D (
- 3ds Max 3DS and ASE (
- 3D Manufacturing Format (
- Wavefront OBJ (
- Industry Foundation Classes (IFC/Step) (
- XGL (
- Stanford PLY (
- AutoCAD DXF (
- LightWave, LightWave Scene (
- Modo (
- Stereolithography (
- DirectX X (
- AC3D (
- Milkshape 3D (
- TrueSpace (
- Biovision BVH (
- CharacterStudio Motion (
- Ogre XML (
- Irrlicht Mesh and Scene (
- Quake I (
- Quake II (
- Quake III Mesh (
- Quake III Map/BSP (
- Return to Castle Wolfenstein (
- Doom 3 (
- Valve Model (
- Open Game Engine Exchange (
- Unreal (
- BlitzBasic 3D (
- Quick3D (
- Neutral File Format (
- Sense8 WorldToolKit (
- Object File Format (
- PovRAY Raw (
- Terragen Terrain (
- 3D GameStudio (3DGS), 3D GameStudio (3DGS) Terrain (
- Izware Nendo (
Supports importing of scene, object, camera, mesh, texture, image, animation and skin data.
This plugin provides
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::
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 set(ASSIMP_BUILD_ASSIMP_TOOLS OFF CACHE BOOL "" FORCE) set(ASSIMP_BUILD_TESTS OFF CACHE BOOL "" FORCE) set(ASSIMP_NO_EXPORT ON CACHE BOOL "" FORCE) # If you won't be accessing Assimp outside of the plugin, build it as static to # have the plugin binary self-contained set(BUILD_SHARED_LIBS OFF CACHE BOOL "" FORCE) # 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. set(INJECT_DEBUG_POSTFIX OFF CACHE BOOL "" FORCE) set(ASSIMP_INJECT_DEBUG_POSTFIX OFF CACHE BOOL "" FORCE) add_subdirectory(assimp EXCLUDE_FROM_ALL) set(MAGNUM_WITH_ANYIMAGEIMPORTER ON CACHE BOOL "" FORCE) add_subdirectory(magnum EXCLUDE_FROM_ALL) set(MAGNUM_WITH_ASSIMPIMPORTER ON CACHE BOOL "" FORCE) 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
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::
The importer recognizes ImporterFlag::
- Assimp supports only a single scene. For some file formats (such as COLLADA) Assimp fails to load the file if it doesn't contain any scene. For some (such as glTF) it will succeed and sceneCount() will return zero.
- Assimp's scene representation is limited to a single root node. To undo undesirable complexity, if the root Assimp node has children, it's ignored and only its children are exposed. On the other hand, for example in presence of postprocessing flags such as
PreTransformVertices, there's sometimes just a single root node. In that case the single node is imported as a single object instead of being ignored.
- Imported scenes always have SceneMappingType::
UnsignedInt, with SceneData:: mappingBound() equal to objectCount(). The scene is always 3D.
- All reported objects have a SceneField::
Parent (of type SceneFieldType:: Int), SceneField:: ImporterState (of type SceneFieldType:: Pointer, see Access to internal importer state below) and SceneField:: Transformation (of type SceneFieldType:: Matrix4x4). These three fields share the same object mapping with SceneFieldFlag:: ImplicitMapping set.
- Assimp doesn't have a builtin way to represent separate TRS components of a transformation, they can only be decomposed from the full matrix post-import. For this reason, only the SceneField::
Transformation is present in the output.
- If the scene references meshes, a SceneField::
Mesh (of type SceneFieldType:: UnsignedInt) and a SceneField:: MeshMaterial (of type SceneFieldType:: Int) is present, both with SceneFieldFlag:: OrderedMapping set. Assimp has no concept of an unassigned material, so the material ID is never
-1. Nodes containing multiple meshes or referencing a multi-primitive mesh have several SceneField::
Mesh (and SceneField:: MeshMaterial) asignments. See Mesh import and Material import for further details.
- If any mesh referenced by a scene is skinned, a SceneField::
Skin (of type SceneFieldType:: UnsignedInt) is present, with SceneFieldFlag:: OrderedMapping set. See Animation and skin import for further details.
- If the scene references cameras, a SceneField::
Camera (of type SceneFieldType:: UnsignedInt) is present, with SceneFieldFlag:: OrderedMapping set. Contrary to Assimp's documentation, for certain formats (such as COLLADA), if one camera is referenced by multiple nodes, it'll get duplicated instead of the nodes sharing the same camera reference. A single node can also only reference one camera at most. See Camera import for further details.
- If the scene references lights, a SceneField::
Light (of type SceneFieldType:: UnsignedInt) is present, with SceneFieldFlag:: OrderedMapping set. Contrary to Assimp's documentation, for certain formats (such as COLLADA), if one light is referenced by multiple nodes, it'll get duplicated instead of the nodes sharing the same light reference. A single node can also only reference one light at most. See Light import for further details.
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
- 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
- If quaternion rotation tracks are not normalized, the importer prints a warning and normalizes them. Can be disabled per-animation with the
- 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_REPEATare currently not implemented and fall back to using Animation::
- It's possible to request all animation clips to be merged into one using the
mergeAnimationClipsoption 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
1and 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
mergeSkinsoption. 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
1and 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.
- 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
- 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
- To load all material attributes with the raw Assimp names and types, enable the
forceRawMaterialDataconfiguration option. You will then get attributes like
$clr.diffuseinstead 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
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
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
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
- 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
- Only point, triangle, and line meshes are loaded (quad and poly meshes are triangularized by Assimp)
- Custom mesh attributes (such as
object_idin 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
maxJointWeightsconfiguration option. For backwards compatibility, unless the
compatibilitySkinningAttributesconfiguration option or MAGNUM_
BUILD_ DEPRECATED is disabled, these are also exposed as custom
"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.
- Textures with mapping mode/wrapping
aiTextureMapMode_Decalare loaded with SamplerWrapping::
- Assimp does not appear to load any filtering information
- Raw embedded image data is not supported
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_
[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.
[configuration] # Controls the workaround for an Assimp 4.1 "white ambient" bug forceWhiteAmbientToBlack=true # Optimize imported linearly-interpolated quaternion animation tracks to # ensure shortest path is always chosen. This can be controlled separately # for each animation import. optimizeQuaternionShortestPath=true # Normalize quaternion animation tracks, if they are not already. # This can be controlled separately for each animation import. normalizeQuaternions=true # 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 # https://blender.stackexchange.com/q/5689 and # https://github.com/KhronosGroup/glTF-Blender-Exporter/pull/166. mergeAnimationClips=false # Remove dummy animation tracks inserted by Assimp that contain only a single # key/value pair with the default node transformation removeDummyAnimationTracks=true # 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. maxJointWeights=0 # 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. compatibilitySkinningAttributes=true # 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. mergeSkins=false # AI_CONFIG_* values, can be changed only before the first file is opened ImportColladaIgnoreUpDirection=false # 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. ignoreUnrecognizedMaterialData=false # 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. forceRawMaterialData=false # aiPostProcessSteps, applied to each opened file [configuration/postprocess] CalcTangentSpace=false JoinIdenticalVertices=true Triangulate=true GenNormals=false GenSmoothNormals=false SplitLargeMeshes=false PreTransformVertices=false # See the maxJointWeights option for LimitBoneWeights instead ValidateDataStructure=false ImproveCacheLocality=false RemoveRedundantMaterials=false FixInfacingNormals=false SortByPType=true FindDegenerates=false FindInvalidData=false GenUVCoords=false TransformUVCoords=false FindInstances=false OptimizeMeshes=false OptimizeGraph=false FlipUVs=false FlipWindingOrder=false SplitByBoneCount=false Debone=false
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:
- Calling importerState() returns a pointer to the imported
- Importer state on data class instances returned from this importer return pointers to matching Assimp structures:
mergeAnimationClipsoption is enabled
importerState() may return
aiTexture, if texture was embedded into the loaded file.
importerState() returns the root
aiNodeand all objects have a SceneField::
ImporterState with their own
mergeSkinsoption is enabled
std::pair<const aiMaterial*, aiTextureType>, in which the first texture of given type in given material is referred to.
- openState() expects a pointer to an Assimp scene (i.e.,
const aiScene*) and optionally a path (in order to be able to load textures, if needed)
- class AbstractImporter
- Base for importer plugins.
Constructors, destructors, conversion operators
- AssimpImporter() explicit
- Default constructor.
Manager<AbstractImporter>& manager) explicit
AbstractManager& manager, const Containers:: StringView& plugin) explicit
- Plugin manager constructor.
Trade:: AssimpImporter:: AssimpImporter() explicit
In case you want to open images, use AssimpImporter(PluginManager::
Trade:: AssimpImporter:: AssimpImporter(PluginManager:: Manager<AbstractImporter>& manager) explicit
The plugin needs access to plugin manager for importing images.