2009-01-15 17:15:05 +00:00
/** @file dox.h
* @ brief General documentation built from a doxygen comment
*/
2008-05-20 16:02:29 +00:00
2009-01-13 20:19:40 +00:00
/**
2012-02-03 17:26:06 +00:00
@ mainpage assimp - Open Asset Import Library
2009-01-23 20:19:59 +00:00
< img src = " dragonsplash.png " > < / img >
2008-05-20 16:02:29 +00:00
@ section intro Introduction
2015-04-20 22:36:47 +00:00
assimp is a library to load and process geometric scenes from various data formats . It is tailored at typical game
2008-05-20 16:02:29 +00:00
scenarios by supporting a node hierarchy , static or skinned meshes , materials , bone animations and potential texture data .
2015-04-20 22:36:47 +00:00
The library is * not * designed for speed , it is primarily useful for importing assets from various sources once and
2012-02-03 17:26:06 +00:00
storing it in a engine - specific format for easy and fast every - day - loading . assimp is also able to apply various post
2008-05-20 16:02:29 +00:00
processing steps to the imported data such as conversion to indexed meshes , calculation of normals or tangents / bitangents
or conversion from right - handed to left - handed coordinate systems .
2015-04-20 22:36:47 +00:00
assimp currently supports the following file formats ( note that some loaders lack some features of their formats because
2012-02-03 17:26:06 +00:00
some file formats contain data not supported by assimp , some stuff would require so much conversion work
2010-04-14 21:13:58 +00:00
that it has not been implemented yet and some ( most . . . ) formats lack proper specifications ) :
2008-09-13 18:58:56 +00:00
< hr >
2009-01-13 20:19:40 +00:00
< br > < tt >
2010-03-06 10:31:37 +00:00
< b > Collada < / b > ( < i > * . dae ; * . xml < / i > ) < br >
2010-11-21 16:11:32 +00:00
< b > Blender < / b > ( < i > * . blend < / i > ) < sup > 3 < / sup > < br >
2009-01-13 20:19:40 +00:00
< b > Biovision BVH < / b > ( < i > * . bvh < / i > ) < br >
2008-09-13 18:58:56 +00:00
< b > 3 D Studio Max 3 DS < / b > ( < i > * .3 ds < / i > ) < br >
< b > 3 D Studio Max ASE < / b > ( < i > * . ase < / i > ) < br >
< b > Wavefront Object < / b > ( < i > * . obj < / i > ) < br >
< b > Stanford Polygon Library < / b > ( < i > * . ply < / i > ) < br >
2011-05-07 13:41:35 +00:00
< b > AutoCAD DXF < / b > ( < i > * . dxf < / i > ) < br >
< b > IFC - STEP < / b > ( < i > * . ifc < / i > ) < br >
2008-09-13 18:58:56 +00:00
< b > Neutral File Format < / b > ( < i > * . nff < / i > ) < br >
2009-01-13 20:19:40 +00:00
< b > Sense8 WorldToolkit < / b > ( < i > * . nff < / i > ) < br >
2008-09-13 18:58:56 +00:00
< b > Valve Model < / b > ( < i > * . smd , * . vta < / i > ) < sup > 3 < / sup > < br >
< b > Quake I < / b > ( < i > * . mdl < / i > ) < br >
< b > Quake II < / b > ( < i > * . md2 < / i > ) < br >
< b > Quake III < / b > ( < i > * . md3 < / i > ) < br >
2010-11-21 16:11:32 +00:00
< b > Quake 3 BSP < / b > ( < i > * . pk3 < / i > ) < sup > 1 < / sup > < br >
2009-01-13 20:19:40 +00:00
< b > RtCW < / b > ( < i > * . mdc < / i > ) < br >
2009-03-15 00:40:30 +00:00
< b > Doom 3 < / b > ( < i > * . md5mesh ; * . md5anim ; * . md5camera < / i > ) < br >
2015-04-20 22:36:47 +00:00
< b > DirectX X < / b > ( < i > * . x < / i > ) . < br >
< b > Quick3D < / b > ( < i > * . q3o ; * q3s < / i > ) . < br >
< b > Raw Triangles < / b > ( < i > * . raw < / i > ) . < br >
2009-01-13 20:19:40 +00:00
< b > AC3D < / b > ( < i > * . ac < / i > ) . < br >
< b > Stereolithography < / b > ( < i > * . stl < / i > ) . < br >
< b > Autodesk DXF < / b > ( < i > * . dxf < / i > ) . < br >
< b > Irrlicht Mesh < / b > ( < i > * . irrmesh ; * . xml < / i > ) . < br >
< b > Irrlicht Scene < / b > ( < i > * . irr ; * . xml < / i > ) . < br >
2015-04-20 22:36:47 +00:00
< b > Object File Format < / b > ( < i > * . off < / i > ) . < br >
2009-01-13 20:19:40 +00:00
< b > Terragen Terrain < / b > ( < i > * . ter < / i > ) < br >
< b > 3 D GameStudio Model < / b > ( < i > * . mdl < / i > ) < br >
2009-09-05 12:04:32 +00:00
< b > 3 D GameStudio Terrain < / b > ( < i > * . hmp < / i > ) < br >
2010-04-14 21:13:58 +00:00
< b > Ogre < / b > ( < i > * . mesh . xml , * . skeleton . xml , * . material < / i > ) < sup > 3 < / sup > < br >
< b > Milkshape 3 D < / b > ( < i > * . ms3d < / i > ) < br >
< b > LightWave Model < / b > ( < i > * . lwo < / i > ) < br >
< b > LightWave Scene < / b > ( < i > * . lws < / i > ) < br >
< b > Modo Model < / b > ( < i > * . lxo < / i > ) < br >
< b > CharacterStudio Motion < / b > ( < i > * . csm < / i > ) < br >
< b > Stanford Ply < / b > ( < i > * . ply < / i > ) < br >
2010-11-21 16:11:32 +00:00
< b > TrueSpace < / b > ( < i > * . cob , * . scn < / i > ) < sup > 2 < / sup > < br > < br >
2009-01-13 20:19:40 +00:00
< / tt >
2015-04-20 22:36:47 +00:00
See the @ link importer_notes Importer Notes Page @ endlink for informations , what a specific importer can do and what not .
Note that although this paper claims to be the official documentation ,
http : //assimp.sourceforge.net/main_features_formats.html
2010-04-14 21:13:58 +00:00
< br > is usually the most up - to - date list of file formats supported by the library . < br >
2009-09-05 12:04:32 +00:00
2010-11-21 16:11:32 +00:00
< sup > 1 < / sup > : Experimental loaders < br >
< sup > 2 < / sup > : Indicates very limited support - many of the format ' s features don ' t map to Assimp ' s data structures . < br >
2012-02-03 17:26:06 +00:00
< sup > 3 < / sup > : These formats support animations , but assimp doesn ' t yet support them ( or they ' re buggy ) < br >
2009-01-13 20:19:40 +00:00
< br >
2008-09-13 18:58:56 +00:00
< hr >
2008-05-23 22:38:35 +00:00
2015-04-20 22:36:47 +00:00
assimp is independent of the Operating System by nature , providing a C + + interface for easy integration
with game engines and a C interface to allow bindings to other programming languages . At the moment the library runs
on any little - endian platform including X86 / Windows / Linux / Mac and X64 / Windows / Linux / Mac . Special attention
was paid to keep the library as free as possible from dependencies .
2008-05-20 16:02:29 +00:00
2015-04-20 22:36:47 +00:00
Big endian systems such as PPC - Macs or PPC - Linux systems are not officially supported at the moment . However , most
2009-01-15 17:15:05 +00:00
formats handle the required endian conversion correctly , so large parts of the library should work .
2009-01-13 20:19:40 +00:00
2012-02-03 17:26:06 +00:00
The assimp linker library and viewer application are provided under the BSD 3 - clause license . This basically means
2008-05-20 16:02:29 +00:00
that you are free to use it in open - or closed - source projects , for commercial or non - commercial purposes as you like
as long as you retain the license informations and take own responsibility for what you do with it . For details see
2009-01-13 20:19:40 +00:00
the LICENSE file .
2008-05-20 16:02:29 +00:00
2009-01-23 20:19:59 +00:00
You can find test models for almost all formats in the < assimp_root > / test / models directory . Beware , they ' re * free * ,
but not all of them are * open - source * . If there ' s an accompagning ' < file > \ source . txt ' file don ' t forget to read it .
2008-05-20 16:02:29 +00:00
@ section main_install Installation
2015-04-20 22:36:47 +00:00
assimp can be used in two ways : linking against the pre - built libraries or building the library on your own . The former
2012-02-03 17:26:06 +00:00
option is the easiest , but the assimp distribution contains pre - built libraries only for Visual C + + 2005 and 2008. For other
2015-04-20 22:36:47 +00:00
compilers you ' ll have to build assimp for yourself . Which is hopefully as hassle - free as the other way , but needs a bit
2008-05-20 16:02:29 +00:00
more work . Both ways are described at the @ link install Installation page . @ endlink
@ section main_usage Usage
2015-04-20 22:36:47 +00:00
When you ' re done integrating the library into your IDE / project , you can now start using it . There are two separate
2008-05-20 16:02:29 +00:00
interfaces by which you can access the library : a C + + interface and a C interface using flat functions . While the former
is easier to handle , the latter also forms a point where other programming languages can connect to . Upto the moment , though ,
there are no bindings for any other language provided . Have a look at the @ link usage Usage page @ endlink for a detailed explanation and code examples .
@ section main_data Data Structures
When the importer successfully completed its job , the imported data is returned in an aiScene structure . This is the root
2015-04-20 22:36:47 +00:00
point from where you can access all the various data types that a scene / model file can possibly contain . The
2008-05-20 16:02:29 +00:00
@ link data Data Structures page @ endlink describes how to interpret this data .
2009-08-31 15:51:54 +00:00
@ section ext Extending the library
There are many 3 d file formats in the world , and we ' re happy to support as many as possible . If you need support for
a particular file format , why not implement it yourself and add it to the library ? Writing importer plugins for
2012-02-03 17:26:06 +00:00
assimp is considerably easy , as the whole postprocessing infrastructure is available and does much of the work for you .
2009-08-31 15:51:54 +00:00
See the @ link extend Extending the library @ endlink page for more information .
2009-01-23 20:19:59 +00:00
@ section main_support Support & Feedback
2015-04-20 22:36:47 +00:00
If you have any questions / comments / suggestions / bug reports you ' re welcome to post them in our
2009-01-23 20:19:59 +00:00
< a href = " https://sourceforge.net/forum/forum.php?forum_id=817653 " > forums < / a > . Alternatively there ' s
a mailing list , < a href = " https://sourceforge.net/mailarchive/forum.php?forum_name=assimp-discussions " >
assimp - discussions < / a > .
2008-05-20 16:02:29 +00:00
*/
2011-07-14 17:46:05 +00:00
2008-05-20 16:02:29 +00:00
/**
@ page install Installation
2011-07-17 21:25:23 +00:00
2009-01-23 20:19:59 +00:00
@ section install_prebuilt Using the pre - built libraries with Visual C + + 8 / 9
2008-05-20 16:02:29 +00:00
2009-01-15 17:15:05 +00:00
If you develop at Visual Studio 2005 or 2008 , you can simply use the pre - built linker libraries provided in the distribution .
2012-02-03 17:26:06 +00:00
Extract all files to a place of your choice . A directory called " assimp " will be created there . Add the assimp / include path
2009-01-15 17:15:05 +00:00
to your include paths ( Menu - & gt ; Extras - & gt ; Options - & gt ; Projects and Solutions - & gt ; VC + + Directories - & gt ; Include files )
2012-02-03 17:26:06 +00:00
and the assimp / lib / & lt ; Compiler & gt ; path to your linker paths ( Menu - & gt ; Extras - & gt ; Options - & gt ; Projects and Solutions - & gt ; VC + + Directories - & gt ; Library files ) .
2008-05-20 16:02:29 +00:00
This is neccessary only once to setup all paths inside you IDE .
2012-02-03 17:26:06 +00:00
To use the library in your C + + project you have to include either & lt ; assimp / Importer . hpp & gt ; or & lt ; assimp / cimport . h & gt ; plus some others starting with & lt ; types . h & gt ; .
2008-05-20 16:02:29 +00:00
If you set up your IDE correctly the compiler should be able to find the files . Then you have to add the linker library to your
2009-01-23 20:19:59 +00:00
project dependencies . Link to < assimp_root > / lib / < config - name > / assimp . lib . config - name is one of the predefined
project configs . For static linking , use release / debug . See the sections below on this page for more information on the
other build configs .
If done correctly you should now be able to compile , link ,
2008-05-20 16:02:29 +00:00
run and use the application . If the linker complains about some integral functions being defined twice you propably have
2015-04-20 22:36:47 +00:00
mixed the runtimes . Recheck the project configuration ( project properties - & gt ; C + + - & gt ; Code generation - & gt ; Runtime ) if you use
2009-01-23 20:19:59 +00:00
static runtimes ( Multithreaded / Multithreaded Debug ) or dynamic runtimes ( Multithreaded DLL / Multithreaded Debug DLL ) .
2015-04-20 22:36:47 +00:00
Choose the assimp linker lib accordingly .
2011-07-17 21:25:23 +00:00
< br > < br >
2010-04-10 20:03:26 +00:00
Please don ' t forget to also read the @ ref assimp_stl section on MSVC and the STL .
2009-01-23 20:19:59 +00:00
2015-04-20 22:36:47 +00:00
@ section assimp_stl Microsoft Compilers and the C + + Standard Library
2009-01-23 20:19:59 +00:00
2011-07-17 21:25:23 +00:00
In VC8 and VC9 Microsoft introduced some Standard Library debugging features . A good example are improved iterator checks and
various useful debug checks . The problem is the performance penalty that incurs with those extra checks .
2009-01-23 20:19:59 +00:00
2015-04-20 22:36:47 +00:00
Most of these security enhancements are active in release builds by default , rendering assimp several times
2011-07-17 21:25:23 +00:00
slower . However , it is possible to disable them by setting
2009-01-23 20:19:59 +00:00
@ code
_HAS_ITERATOR_DEBUGGING = 0
_SECURE_SCL = 0
@ endcode
in the preprocessor options ( or alternatively in the source code , just before the STL is included for the first time ) .
2012-02-03 17:26:06 +00:00
< b > assimp ' s vc8 and vc9 configs enable these flags by default < / b > .
2009-01-23 20:19:59 +00:00
2015-04-20 22:36:47 +00:00
< i > If you ' re linking statically against assimp : < / i > Make sure your applications uses the same STl settings !
If you do not , there are two binary incompatible STL versions mangled together and you ' ll crash .
2012-02-03 17:26:06 +00:00
Alternatively you can disable the fast STL settings for assimp by removing the ' FastSTL ' property sheet from
2009-01-23 20:19:59 +00:00
the vc project file .
2012-02-03 17:26:06 +00:00
< i > If you ' re using assimp in a DLL / SO : < / i > It ' s ok . There ' s no STL used in the binary DLL / SO interface , so it doesn ' t care whether
2009-01-23 20:19:59 +00:00
your application uses the same STL settings or not .
< br > < br >
2015-04-20 22:36:47 +00:00
Another option is to build against a different STL implementation , for example STlport . There ' s a special
2011-07-17 21:25:23 +00:00
@ ref assimp_stlport section that has a description how to achieve this .
2009-01-23 20:19:59 +00:00
2008-05-20 16:02:29 +00:00
@ section install_own Building the library from scratch
2015-04-20 22:36:47 +00:00
To build the library on your own you first have to get hold of the dependencies . Fortunately , special attention was paid to
keep the list of dependencies short . Unfortunately , the only dependency is < a href = " http://www.boost.org " > boost < / a > which
can be a bit painful to set up for certain development environments . Boost is a widely used collection of classes and
functions for various purposes . Chances are that it was already installed along with your compiler . If not , you have to install
it for yourself . Read the " Getting Started " section of the Boost documentation for how to setup boost . VisualStudio users
2008-05-21 15:35:28 +00:00
can use a comfortable installer from < a href = " http://www.boost-consulting.com/products/free " >
http : //www.boost-consulting.com/products/free</a>. Choose the appropriate version of boost for your runtime of choice.
2015-04-20 22:36:47 +00:00
< b > If you don ' t want to use boost < / b > , you can build against our < i > " Boost-Workaround " < / i > . It consists of very small
implementations of the various boost utility classes used . However , you ' ll lose functionality ( e . g . threading ) by doing this .
So , if you can use boost , you should use boost . Otherwise , See the @ link use_noboost NoBoost - Section @ endlink
2011-07-17 21:25:23 +00:00
later on this page for the details of the workaround .
2009-01-13 20:19:40 +00:00
2012-02-03 17:26:06 +00:00
Once boost is working , you have to set up a project for the assimp library in your favorite IDE . If you use VC2005 or
2015-04-20 22:36:47 +00:00
VC2008 , you can simply load the solution or project files in the workspaces / folder , otherwise you have to create a new
2008-05-21 15:35:28 +00:00
package and add all the headers and source files from the include / and code / directories . Set the temporary output folder
2008-05-22 13:55:13 +00:00
to obj / , for example , and redirect the output folder to bin / . Then build the library - it should compile and link fine .
2008-05-21 15:35:28 +00:00
2015-04-20 22:36:47 +00:00
The last step is to integrate the library into your project . This is basically the same task as described in the
2009-01-15 17:15:05 +00:00
" Using the pre-built libraries " section above : add the include / and bin / directories to your IDE ' s paths so that the compiler can find
2012-02-03 17:26:06 +00:00
the library files . Alternatively you can simply add the assimp project to your project ' s overall solution and build it inside
2008-05-21 15:35:28 +00:00
your solution .
2009-01-13 20:19:40 +00:00
@ section use_noboost Building without boost .
The Boost - Workaround consists of dummy replacements for some boost utility templates . Currently there are replacements for
2011-07-17 21:25:23 +00:00
- boost . scoped_ptr
- boost . scoped_array
- boost . format
- boost . random
- boost . common_factor
- boost . foreach
- boost . tuple
- boost . make_shared
2012-02-03 17:26:06 +00:00
These implementations are very limited and are not intended for use outside assimp . A compiler
2009-01-13 20:19:40 +00:00
with full support for partial template specializations is required . To enable the workaround , put the following in
2015-04-20 22:36:47 +00:00
your compiler ' s list of predefined macros :
2009-01-13 20:19:40 +00:00
@ code
# define ASSIMP_BUILD_BOOST_WORKAROUND
@ endcode
< br >
If you ' re working with the provided solutions for Visual Studio use the < i > - noboost < / i > build configs . < br >
2012-02-03 17:26:06 +00:00
< b > assimp_BUILD_BOOST_WORKAROUND < / b > implies < b > assimp_BUILD_SINGLETHREADED < / b > . < br >
2010-04-10 20:03:26 +00:00
See the @ ref assimp_st section
2009-01-13 20:19:40 +00:00
for more details .
2009-09-26 22:04:27 +00:00
2009-01-13 20:19:40 +00:00
2011-07-17 21:25:23 +00:00
@ section assimp_dll Windows DLL Build
2009-01-13 20:19:40 +00:00
2012-02-03 17:26:06 +00:00
assimp can be built as DLL . You just need to select a - dll config from the list of project
2011-07-17 21:25:23 +00:00
configs and you ' re fine .
2009-01-13 20:19:40 +00:00
2015-04-20 22:36:47 +00:00
< b > NOTE : < / b > Theoretically , assimp - dll can be used with multithreaded ( non - dll ) runtime libraries ,
2011-07-17 21:25:23 +00:00
as long as you don ' t utilize any non - public stuff from the code folder . However , if you happen
to encounter * very * strange problems , try changing the runtime to < i > Multithreaded ( Debug ) DLL < / i > .
2009-01-20 22:01:31 +00:00
@ section assimp_stlport Building against STLport
2011-07-17 21:25:23 +00:00
STLport is a free , fast and secure STL replacement that works with
all major compilers and platforms . To get it , download the latest release from
< a href = " http://www.stlport.org " / > < stlport . org > < / a > .
Usually you ' ll just need to run ' configure ' + a makefile ( see their README for more details ) .
2009-01-23 19:21:04 +00:00
Don ' t miss to add < stlport_root > / stlport to your compiler ' s default include paths - < b > prior < / b >
2011-07-17 21:25:23 +00:00
to the directory where your compiler vendor ' s headers lie . Do the same for < stlport_root > / lib and
2012-02-03 17:26:06 +00:00
recompile assimp . To ensure you ' re really building against STLport see aiGetCompileFlags ( ) .
2009-01-23 19:21:04 +00:00
< br >
2011-07-17 21:25:23 +00:00
In our testing , STLport builds tend to be a bit faster than builds against Microsoft ' s
C + + Standard Library .
2009-01-20 22:01:31 +00:00
2008-05-20 16:02:29 +00:00
*/
2009-01-23 20:19:59 +00:00
2015-04-20 22:36:47 +00:00
/**
2008-05-20 16:02:29 +00:00
@ page usage Usage
2009-01-13 20:19:40 +00:00
@ section access_cpp Access by C + + class interface
2008-05-22 13:55:13 +00:00
2012-02-03 17:26:06 +00:00
The assimp library can be accessed by both a class or flat function interface . The C + + class
2015-04-20 22:36:47 +00:00
interface is the preferred way of interaction : you create an instance of class Assimp : : Importer ,
2009-07-20 18:50:51 +00:00
maybe adjust some settings of it and then call Assimp : : Importer : : ReadFile ( ) . The class will
2015-04-20 22:36:47 +00:00
read the files and process its data , handing back the imported data as a pointer to an aiScene
2008-05-22 13:55:13 +00:00
to you . You can now extract the data you need from the file . The importer manages all the resources
2015-04-20 22:36:47 +00:00
for itsself . If the importer is destroyed , all the data that was created / read by it will be
2008-05-22 13:55:13 +00:00
destroyed , too . So the easiest way to use the Importer is to create an instance locally , use its
2015-04-20 22:36:47 +00:00
results and then simply let it go out of scope .
2008-05-22 13:55:13 +00:00
C + + example :
@ code
2012-02-03 17:26:06 +00:00
# include <assimp/Importer.hpp> // C++ importer interface
# include <assimp/scene.h> // Output data structure
# include <assimp/postprocess.h> // Post processing flags
2009-01-13 20:19:40 +00:00
2008-05-22 13:55:13 +00:00
bool DoTheImportThing ( const std : : string & pFile )
{
2009-01-13 20:19:40 +00:00
// Create an instance of the Importer class
2009-07-20 18:50:51 +00:00
Assimp : : Importer importer ;
2008-05-22 13:55:13 +00:00
2009-01-13 20:19:40 +00:00
// And have it read the given file with some example postprocessing
2015-04-20 22:36:47 +00:00
// Usually - if speed is not the most important aspect for you - you'll
2009-01-13 20:19:40 +00:00
// propably to request more postprocessing than we do in this example.
2015-04-20 22:36:47 +00:00
const aiScene * scene = importer . ReadFile ( pFile ,
aiProcess_CalcTangentSpace |
2009-01-13 20:19:40 +00:00
aiProcess_Triangulate |
aiProcess_JoinIdenticalVertices |
aiProcess_SortByPType ) ;
2015-04-20 22:36:47 +00:00
2009-01-13 20:19:40 +00:00
// If the import failed, report it
2008-05-22 13:55:13 +00:00
if ( ! scene )
{
2008-11-27 15:54:35 +00:00
DoTheErrorLogging ( importer . GetErrorString ( ) ) ;
2008-05-22 13:55:13 +00:00
return false ;
}
2015-04-20 22:36:47 +00:00
// Now we can access the file's contents.
2008-05-22 13:55:13 +00:00
DoTheSceneProcessing ( scene ) ;
2009-01-13 20:19:40 +00:00
// We're done. Everything will be cleaned up by the importer destructor
2008-05-22 13:55:13 +00:00
return true ;
}
@ endcode
2012-02-03 17:26:06 +00:00
What exactly is read from the files and how you interpret it is described at the @ ref data page . @ endlink The post processing steps that the assimp library can apply to the
2010-04-10 20:03:26 +00:00
imported data are listed at # aiPostProcessSteps . See the @ ref pp Post proccessing page for more details .
2009-01-13 20:19:40 +00:00
2015-04-20 22:36:47 +00:00
Note that the aiScene data structure returned is declared ' const ' . Yes , you can get rid of
these 5 letters with a simple cast . Yes , you may do that . No , it ' s not recommended ( and it ' s
suicide in DLL builds if you try to use new or delete on any of the arrays in the scene ) .
2008-05-22 13:55:13 +00:00
2009-01-13 20:19:40 +00:00
@ section access_c Access by plain - c function interface
2008-05-22 13:55:13 +00:00
The plain function interface is just as simple , but requires you to manually call the clean - up
after you ' re done with the imported data . To start the import process , call aiImportFile ( )
with the filename in question and the desired postprocessing flags like above . If the call
is successful , an aiScene pointer with the imported data is handed back to you . When you ' re
done with the extraction of the data you ' re interested in , call aiReleaseImport ( ) on the
imported scene to clean up all resources associated with the import .
C example :
@ code
2012-02-03 17:26:06 +00:00
# include <assimp/cimport.h> // Plain-C interface
# include <assimp/scene.h> // Output data structure
# include <assimp/postprocess.h> // Post processing flags
2008-05-22 13:55:13 +00:00
bool DoTheImportThing ( const char * pFile )
{
2008-05-28 20:45:56 +00:00
// Start the import on the given file with some example postprocessing
2009-01-13 20:19:40 +00:00
// Usually - if speed is not the most important aspect for you - you'll t
2009-01-15 17:15:05 +00:00
// probably to request more postprocessing than we do in this example.
2015-04-20 22:36:47 +00:00
const aiScene * scene = aiImportFile ( pFile ,
aiProcess_CalcTangentSpace |
2009-01-13 20:19:40 +00:00
aiProcess_Triangulate |
aiProcess_JoinIdenticalVertices |
aiProcess_SortByPType ) ;
2008-05-22 13:55:13 +00:00
2008-05-28 20:45:56 +00:00
// If the import failed, report it
2008-05-22 13:55:13 +00:00
if ( ! scene )
{
DoTheErrorLogging ( aiGetErrorString ( ) ) ;
return false ;
}
2008-05-28 20:45:56 +00:00
// Now we can access the file's contents
2008-05-22 13:55:13 +00:00
DoTheSceneProcessing ( scene ) ;
2008-05-28 20:45:56 +00:00
// We're done. Release all resources associated with this import
2008-05-22 13:55:13 +00:00
aiReleaseImport ( scene ) ;
return true ;
}
@ endcode
2009-07-20 18:50:51 +00:00
@ section custom_io Using custom IO logic with the C + + class interface
2008-05-22 13:55:13 +00:00
2012-02-03 17:26:06 +00:00
The assimp library needs to access files internally . This of course applies to the file you want
2008-05-22 13:55:13 +00:00
to read , but also to additional files in the same folder for certain file formats . By default ,
standard C / C + + IO logic is used to access these files . If your application works in a special
2015-04-20 22:36:47 +00:00
environment where custom logic is needed to access the specified files , you have to supply
2008-05-22 13:55:13 +00:00
custom implementations of IOStream and IOSystem . A shortened example might look like this :
@ code
2012-02-03 17:26:06 +00:00
# include <assimp/IOStream.hpp>
# include <assimp/IOSystem.hpp>
2008-05-22 13:55:13 +00:00
// My own implementation of IOStream
2012-02-03 17:26:06 +00:00
class MyIOStream : public Assimp : : IOStream
2008-05-22 13:55:13 +00:00
{
friend class MyIOSystem ;
protected :
// Constructor protected for private usage by MyIOSystem
MyIOStream ( void ) ;
public :
~ MyIOStream ( void ) ;
size_t Read ( void * pvBuffer , size_t pSize , size_t pCount ) { . . . }
size_t Write ( const void * pvBuffer , size_t pSize , size_t pCount ) { . . . }
aiReturn Seek ( size_t pOffset , aiOrigin pOrigin ) { . . . }
size_t Tell ( ) const { . . . }
size_t FileSize ( ) const { . . . }
2009-01-13 20:19:40 +00:00
void Flush ( ) { . . . }
2008-05-22 13:55:13 +00:00
} ;
// Fisher Price - My First Filesystem
2012-02-03 17:26:06 +00:00
class MyIOSystem : public Assimp : : IOSystem
2008-05-22 13:55:13 +00:00
{
MyIOSystem ( ) { . . . }
~ MyIOSystem ( ) { . . . }
2009-01-13 20:19:40 +00:00
// Check whether a specific file exists
bool Exists ( const std : : string & pFile ) const {
2015-04-20 22:36:47 +00:00
. .
2009-01-13 20:19:40 +00:00
}
2009-07-20 18:50:51 +00:00
// Get the path delimiter character we'd like to see
2015-04-20 22:36:47 +00:00
char GetOsSeparator ( ) const {
return ' / ' ;
2009-01-13 20:19:40 +00:00
}
// ... and finally a method to open a custom stream
IOStream * Open ( const std : : string & pFile , const std : : string & pMode ) {
2015-04-20 22:36:47 +00:00
return new MyIOStream ( . . . ) ;
2009-01-13 20:19:40 +00:00
}
2008-05-22 13:55:13 +00:00
void Close ( IOStream * pFile ) { delete pFile ; }
} ;
@ endcode
2015-04-20 22:36:47 +00:00
Now that your IO system is implemented , supply an instance of it to the Importer object by calling
Assimp : : Importer : : SetIOHandler ( ) .
2008-05-22 13:55:13 +00:00
@ code
void DoTheImportThing ( const std : : string & pFile )
{
2009-07-20 18:50:51 +00:00
Assimp : : Importer importer ;
2008-05-22 13:55:13 +00:00
// put my custom IO handling in place
importer . SetIOHandler ( new MyIOSystem ( ) ) ;
// the import process will now use this implementation to access any file
importer . ReadFile ( pFile , SomeFlag | SomeOtherFlag ) ;
}
@ endcode
2009-01-13 20:19:40 +00:00
@ section custom_io_c Using custom IO logic with the plain - c function interface
2009-07-20 18:50:51 +00:00
The C interface also provides a way to override the file system . Control is not as fine - grained as for C + + although
surely enough for almost any purpose . The process is simple :
< ul >
2012-02-03 17:26:06 +00:00
< li > Include cfileio . h
2009-07-20 18:50:51 +00:00
< li > Fill an aiFileIO structure with custom file system callbacks ( they ' re self - explanatory as they work similar to the CRT ' s fXXX functions )
2012-02-03 17:26:06 +00:00
< li > . . and pass it as parameter to # aiImportFileEx
2009-07-20 18:50:51 +00:00
< / ul >
2009-01-13 20:19:40 +00:00
2015-04-20 22:36:47 +00:00
@ section logging Logging
2008-05-23 16:58:13 +00:00
2015-04-20 22:36:47 +00:00
The assimp library provides an easy mechanism to log messages . For instance if you want to check the state of your
import and you just want to see , after which preprocessing step the import - process was aborted you can take a look
into the log .
2012-02-03 17:26:06 +00:00
Per default the assimp - library provides a default log implementation , where you can log your user specific message
2008-05-28 20:45:56 +00:00
by calling it as a singleton with the requested logging - type . To see how this works take a look to this :
2008-05-23 16:58:13 +00:00
@ code
2009-07-20 18:50:51 +00:00
using namespace Assimp ;
2008-05-23 16:58:13 +00:00
2015-04-20 22:36:47 +00:00
// Create a logger instance
2009-07-20 18:50:51 +00:00
DefaultLogger : : create ( " " , Logger : : VERBOSE ) ;
2008-05-23 16:58:13 +00:00
// Now I am ready for logging my stuff
2009-07-20 18:50:51 +00:00
DefaultLogger : : get ( ) - > info ( " this is my info-call " ) ;
2008-05-23 16:58:13 +00:00
// Kill it after the work is done
2009-07-20 18:50:51 +00:00
DefaultLogger : : kill ( ) ;
2008-05-23 16:58:13 +00:00
@ endcode
2015-04-20 22:36:47 +00:00
At first you have to create the default - logger - instance ( create ) . Now you are ready to rock and can log a
2008-05-28 20:45:56 +00:00
little bit around . After that you should kill it to release the singleton instance .
2008-05-23 16:58:13 +00:00
2012-02-03 17:26:06 +00:00
If you want to integrate the assimp - log into your own GUI it my be helpful to have a mechanism writing
2008-05-28 20:45:56 +00:00
the logs into your own log windows . The logger interface provides this by implementing an interface called LogStream .
2015-04-20 22:36:47 +00:00
You can attach and detach this log stream to the default - logger instance or any implementation derived from Logger .
2009-01-15 17:15:05 +00:00
Just derivate your own logger from the abstract base class LogStream and overwrite the write - method :
2008-05-23 16:58:13 +00:00
@ code
2008-05-28 20:45:56 +00:00
// Example stream
2008-05-23 16:58:13 +00:00
class myStream :
public LogStream
{
public :
2008-05-28 20:45:56 +00:00
// Constructor
2008-05-23 16:58:13 +00:00
myStream ( )
{
// empty
}
2015-04-20 22:36:47 +00:00
2008-05-28 20:45:56 +00:00
// Destructor
2008-05-23 16:58:13 +00:00
~ myStream ( )
{
// empty
}
2008-05-28 20:45:56 +00:00
// Write womethink using your own functionality
2009-01-23 20:19:59 +00:00
void write ( const char * message )
2008-05-23 16:58:13 +00:00
{
2009-01-23 20:19:59 +00:00
: : printf ( " %s \n " , message ) ;
2008-05-23 16:58:13 +00:00
}
} ;
2009-07-20 18:50:51 +00:00
// Select the kinds of messages you want to receive on this log stream
const unsigned int severity = Logger : : DEBUGGING | Logger : : INFO | Logger : : ERR | Logger : : WARN ;
2008-05-23 16:58:13 +00:00
// Attaching it to the default logger
2009-07-20 18:50:51 +00:00
Assimp : : DefaultLogger : : get ( ) - > attachStream ( new myStream ( ) , severity ) ;
2008-05-23 16:58:13 +00:00
@ endcode
The severity level controls the kind of message which will be written into
2015-04-20 22:36:47 +00:00
the attached stream . If you just want to log errors and warnings set the warn
and error severity flag for those severities . It is also possible to remove
a self defined logstream from an error severity by detaching it with the severity
2008-05-28 20:45:56 +00:00
flag set :
2008-05-23 16:58:13 +00:00
@ code
unsigned int severity = 0 ;
severity | = Logger : : DEBUGGING ;
// Detach debug messages from you self defined stream
2009-07-20 18:50:51 +00:00
Assimp : : DefaultLogger : : get ( ) - > attachStream ( new myStream ( ) , severity ) ;
2008-05-23 16:58:13 +00:00
@ endcode
2015-04-20 22:36:47 +00:00
If you want to implement your own logger just derive from the abstract base class
# Logger and overwrite the methods debug, info, warn and error.
2008-05-23 16:58:13 +00:00
2015-04-20 22:36:47 +00:00
If you want to see the debug - messages in a debug - configured build , the Logger - interface
2008-05-28 20:45:56 +00:00
provides a logging - severity . You can set it calling the following method :
2008-05-23 16:58:13 +00:00
@ code
2009-07-20 18:50:51 +00:00
Assimp : : DefaultLogger : : get ( ) - > setLogSeverity ( LogSeverity log_severity ) ;
2008-05-23 16:58:13 +00:00
@ endcode
2015-04-20 22:36:47 +00:00
The normal logging severity supports just the basic stuff like , info , warnings and errors .
2009-07-20 18:50:51 +00:00
In the verbose level very fine - grained debug messages will be logged , too . Note that this
kind kind of logging might decrease import performance .
2008-05-20 16:02:29 +00:00
*/
2015-04-20 22:36:47 +00:00
/**
2008-05-20 16:02:29 +00:00
@ page data Data Structures
2012-02-03 17:26:06 +00:00
The assimp library returns the imported data in a collection of structures . aiScene forms the root
2008-05-22 23:33:51 +00:00
of the data , from here you gain access to all the nodes , meshes , materials , animations or textures
2015-04-20 22:36:47 +00:00
that were read from the imported file . The aiScene is returned from a successful call to
2012-02-03 17:26:06 +00:00
assimp : : Importer : : ReadFile ( ) , aiImportFile ( ) or aiImportFileEx ( ) - see the @ link usage Usage page @ endlink
2008-05-22 23:33:51 +00:00
for further information on how to use the library .
By default , all 3 D data is provided in a right - handed coordinate system such as OpenGL uses . In
2009-09-26 22:04:27 +00:00
this coordinate system , + X points to the right , - Z points away from the viewer into the screen and
+ Y points upwards . Several modeling packages such as 3 D Studio Max use this coordinate system as well ( or a rotated variant of it ) .
2008-05-22 23:33:51 +00:00
By contrast , some other environments use left - handed coordinate systems , a prominent example being
DirectX . If you need the imported data to be in a left - handed coordinate system , supply the
2009-03-15 00:40:30 +00:00
# aiProcess_MakeLeftHanded flag to the ReadFile() function call.
2009-04-02 15:16:01 +00:00
The output face winding is counter clockwise . Use # aiProcess_FlipWindingOrder to get CW data .
2009-03-15 00:40:30 +00:00
@ code
2009-04-02 15:16:01 +00:00
x2
2015-04-20 22:36:47 +00:00
2009-03-18 22:01:11 +00:00
x1
2009-04-02 15:16:01 +00:00
x0
2009-03-15 00:40:30 +00:00
@ endcode
2009-04-02 15:16:01 +00:00
Outputted polygons can be literally everything : they ' re probably concave , self - intersecting or non - planar ,
2015-04-20 22:36:47 +00:00
although our built - in triangulation ( # aiProcess_Triangulate postprocessing step ) doesn ' t handle the two latter .
2009-04-02 15:16:01 +00:00
2009-03-15 00:40:30 +00:00
The output UV coordinate system has its origin in the lower - left corner :
@ code
2015-04-20 22:36:47 +00:00
0 y | 1 y - - - - - - - - - - 1 x | 1 y
2009-03-15 00:40:30 +00:00
| |
| |
| |
0 x | 0 y - - - - - - - - - - 1 x | 0 y
@ endcode
Use the # aiProcess_FlipUVs flag to get UV coordinates with the upper - left corner als origin .
2008-05-22 23:33:51 +00:00
All matrices in the library are row - major . That means that the matrices are stored row by row in memory ,
which is similar to the OpenGL matrix layout . A typical 4 x4 matrix including a translational part looks like this :
@ code
X1 Y1 Z1 T1
X2 Y2 Z2 T2
X3 Y3 Z3 T3
0 0 0 1
@ endcode
2015-04-20 22:36:47 +00:00
. . . with ( X1 , X2 , X3 ) being the X base vector , ( Y1 , Y2 , Y3 ) being the Y base vector , ( Z1 , Z2 , Z3 )
2009-01-15 17:15:05 +00:00
being the Z base vector and ( T1 , T2 , T3 ) being the translation part . If you want to use these matrices
2008-05-22 23:33:51 +00:00
in DirectX functions , you have to transpose them .
2010-01-13 16:37:57 +00:00
< hr >
2015-04-20 22:36:47 +00:00
< b > 11.24 .09 : < / b > We changed the orientation of our quaternions to the most common convention to avoid confusion .
However , if you ' re a previous user of Assimp and you update the library to revisions beyond SVNREV 502 ,
you have to adapt your animation loading code to match the new quaternion orientation .
2010-01-13 16:37:57 +00:00
< hr >
2008-05-22 23:33:51 +00:00
@ section hierarchy The Node Hierarchy
Nodes are little named entities in the scene that have a place and orientation relative to their parents .
2015-04-20 22:36:47 +00:00
Starting from the scene ' s root node all nodes can have 0 to x child nodes , thus forming a hierarchy .
2008-05-22 23:33:51 +00:00
They form the base on which the scene is built on : a node can refer to 0. . x meshes , can be referred to
by a bone of a mesh or can be animated by a key sequence of an animation . DirectX calls them " frames " ,
2015-04-20 22:36:47 +00:00
others call them " objects " , we call them aiNode .
2008-05-22 23:33:51 +00:00
A node can potentially refer to single or multiple meshes . The meshes are not stored inside the node , but
instead in an array of aiMesh inside the aiScene . A node only refers to them by their array index . This also means
that multiple nodes can refer to the same mesh , which provides a simple form of instancing . A mesh referred to
by this way lives in the node ' s local coordinate system . If you want the mesh ' s orientation in global
2015-04-20 22:36:47 +00:00
space , you ' d have to concatenate the transformations from the referring node and all of its parents .
2008-05-22 23:33:51 +00:00
Most of the file formats don ' t really support complex scenes , though , but a single model only . But there are
more complex formats such as .3 ds , . x or . collada scenes which may contain an arbitrary complex
hierarchy of nodes and meshes . I for myself would suggest a recursive filter function such as the
following pseudocode :
@ code
void CopyNodesWithMeshes ( aiNode node , SceneObject targetParent , Matrix4x4 accTransform )
{
SceneObject parent ;
Matrix4x4 transform ;
// if node has meshes, create a new scene object for it
if ( node . mNumMeshes > 0 )
{
SceneObjekt newObject = new SceneObject ;
targetParent . addChild ( newObject ) ;
// copy the meshes
CopyMeshes ( node , newObject ) ;
// the new object is the parent for all child nodes
parent = newObject ;
transform . SetUnity ( ) ;
} else
{
// if no meshes, skip the node, but keep its transformation
parent = targetParent ;
transform = node . mTransformation * accTransform ;
}
// continue for all child nodes
for ( all node . mChildren )
CopyNodesWithMeshes ( node . mChildren [ a ] , parent , transform ) ;
}
@ endcode
This function copies a node into the scene graph if it has children . If yes , a new scene object
is created for the import node and the node ' s meshes are copied over . If not , no object is created .
Potential child objects will be added to the old targetParent , but there transformation will be correct
2015-04-20 22:36:47 +00:00
in respect to the global space . This function also works great in filtering the bone nodes - nodes
2009-01-15 17:15:05 +00:00
that form the bone hierarchy for another mesh / node , but don ' t have any mesh themselves .
2008-05-22 23:33:51 +00:00
@ section meshes Meshes
All meshes of an imported scene are stored in an array of aiMesh * inside the aiScene . Nodes refer
2008-05-28 20:45:56 +00:00
to them by their index in the array and providing the coordinate system for them , too . One mesh uses
2008-05-22 23:33:51 +00:00
only a single material everywhere - if parts of the model use a different material , this part is
moved to a separate mesh at the same node . The mesh refers to its material in the same way as the
node refers to its meshes : materials are stored in an array inside aiScene , the mesh stores only
an index into this array .
An aiMesh is defined by a series of data channels . The presence of these data channels is defined
by the contents of the imported file : by default there are only those data channels present in the mesh
that were also found in the file . The only channels guarenteed to be always present are aiMesh : : mVertices
and aiMesh : : mFaces . You can test for the presence of other data by testing the pointers against NULL
2015-04-20 22:36:47 +00:00
or use the helper functions provided by aiMesh . You may also specify several post processing flags
2012-02-03 17:26:06 +00:00
at Importer : : ReadFile ( ) to let assimp calculate or recalculate additional data channels for you .
2008-05-22 23:33:51 +00:00
At the moment , a single aiMesh may contain a set of triangles and polygons . A single vertex does always
have a position . In addition it may have one normal , one tangent and bitangent , zero to AI_MAX_NUMBER_OF_TEXTURECOORDS
( 4 at the moment ) texture coords and zero to AI_MAX_NUMBER_OF_COLOR_SETS ( 4 ) vertex colors . In addition
a mesh may or may not have a set of bones described by an array of aiBone structures . How to interpret
the bone information is described later on .
@ section material Materials
2009-05-03 21:49:34 +00:00
See the @ link materials Material System Page . @ endlink
2008-06-22 10:09:26 +00:00
2008-05-22 23:33:51 +00:00
@ section bones Bones
2015-04-20 22:36:47 +00:00
A mesh may have a set of bones in the form of aiBone structures . . Bones are a means to deform a mesh
according to the movement of a skeleton . Each bone has a name and a set of vertices on which it has influence .
Its offset matrix declares the transformation needed to transform from mesh space to the local space of this bone .
2008-05-22 23:33:51 +00:00
Using the bones name you can find the corresponding node in the node hierarchy . This node in relation
to the other bones ' nodes defines the skeleton of the mesh . Unfortunately there might also be
nodes which are not used by a bone in the mesh , but still affect the pose of the skeleton because
they have child nodes which are bones . So when creating the skeleton hierarchy for a mesh I
suggest the following method :
2015-04-20 22:36:47 +00:00
a ) Create a map or a similar container to store which nodes are necessary for the skeleton .
2009-01-15 17:15:05 +00:00
Pre - initialise it for all nodes with a " no " . < br >
2008-05-22 23:33:51 +00:00
b ) For each bone in the mesh : < br >
2008-05-28 20:45:56 +00:00
b1 ) Find the corresponding node in the scene ' s hierarchy by comparing their names . < br >
2008-05-22 23:33:51 +00:00
b2 ) Mark this node as " yes " in the necessityMap . < br >
b3 ) Mark all of its parents the same way until you 1 ) find the mesh ' s node or 2 ) the parent of the mesh ' s node . < br >
c ) Recursively iterate over the node hierarchy < br >
c1 ) If the node is marked as necessary , copy it into the skeleton and check its children < br >
2008-05-23 14:15:51 +00:00
c2 ) If the node is marked as not necessary , skip it and do not iterate over its children . < br >
2008-05-22 23:33:51 +00:00
2015-04-20 22:36:47 +00:00
Reasons : you need all the parent nodes to keep the transformation chain intact . For most
2011-12-18 20:54:50 +00:00
file formats and modelling packages the node hierarchy of the skeleton is either a child
2015-04-20 22:36:47 +00:00
of the mesh node or a sibling of the mesh node but this is by no means a requirement so you shouldn ' t rely on it .
2011-12-18 20:54:50 +00:00
The node closest to the root node is your skeleton root , from there you
2015-04-20 22:36:47 +00:00
start copying the hierarchy . You can skip every branch without a node being a bone in the mesh -
2008-05-22 23:33:51 +00:00
that ' s why the algorithm skips the whole branch if the node is marked as " not necessary " .
You should now have a mesh in your engine with a skeleton that is a subset of the imported hierarchy .
@ section anims Animations
2008-05-23 14:15:51 +00:00
An imported scene may contain zero to x aiAnimation entries . An animation in this context is a set
of keyframe sequences where each sequence describes the orientation of a single node in the hierarchy
over a limited time span . Animations of this kind are usually used to animate the skeleton of
a skinned mesh , but there are other uses as well .
An aiAnimation has a duration . The duration as well as all time stamps are given in ticks . To get
the correct timing , all time stamp thus have to be divided by aiAnimation : : mTicksPerSecond . Beware ,
though , that certain combinations of file format and exporter don ' t always store this information
in the exported file . In this case , mTicksPerSecond is set to 0 to indicate the lack of knowledge .
2009-01-20 20:26:35 +00:00
The aiAnimation consists of a series of aiNodeAnim ' s . Each bone animation affects a single node in
2015-04-20 22:36:47 +00:00
the node hierarchy only , the name specifying which node is affected . For this node the structure
2008-05-23 14:15:51 +00:00
stores three separate key sequences : a vector key sequence for the position , a quaternion key sequence
for the rotation and another vector key sequence for the scaling . All 3 d data is local to the
coordinate space of the node ' s parent , that means in the same space as the node ' s transformation matrix .
There might be cases where animation tracks refer to a non - existent node by their name , but this
2015-04-20 22:36:47 +00:00
should not be the case in your every - day data .
2008-05-23 14:15:51 +00:00
To apply such an animation you need to identify the animation tracks that refer to actual bones
in your mesh . Then for every track : < br >
a ) Find the keys that lay right before the current anim time . < br >
b ) Optional : interpolate between these and the following keys . < br >
c ) Combine the calculated position , rotation and scaling to a tranformation matrix < br >
d ) Set the affected node ' s transformation to the calculated matrix . < br >
2015-04-20 22:36:47 +00:00
If you need hints on how to convert to or from quaternions , have a look at the
2008-05-23 14:15:51 +00:00
< a href = " http://www.j3d.org/matrix_faq/matrfaq_latest.html " > Matrix & Quaternion FAQ < / a > . I suggest
using logarithmic interpolation for the scaling keys if you happen to need them - usually you don ' t
need them at all .
2008-05-22 23:33:51 +00:00
@ section textures Textures
2008-05-30 23:01:25 +00:00
Normally textures used by assets are stored in separate files , however ,
there are file formats embedding their textures directly into the model file .
2015-04-20 22:36:47 +00:00
Such textures are loaded into an aiTexture structure .
2008-05-30 23:01:25 +00:00
< br >
There are two cases :
< br >
< b > 1 ) < / b > The texture is NOT compressed . Its color data is directly stored
in the aiTexture structure as an array of aiTexture : : mWidth * aiTexture : : mHeight aiTexel structures . Each aiTexel represents a pixel ( or " texel " ) of the texture
image . The color data is stored in an unsigned RGBA8888 format , which can be easily used for
both Direct3D and OpenGL ( swizzling the order of the color components might be necessary ) .
RGBA8888 has been chosen because it is well - known , easy to use and natively
supported by nearly all graphics APIs .
< br >
2009-07-20 18:50:51 +00:00
< b > 2 ) < / b > This applies if aiTexture : : mHeight = = 0 is fullfilled . Then , texture is stored in a
2008-05-30 23:01:25 +00:00
" compressed " format such as DDS or PNG . The term " compressed " does not mean that the
2009-07-20 18:50:51 +00:00
texture data must actually be compressed , however the texture was found in the
2008-05-30 23:01:25 +00:00
model file as if it was stored in a separate file on the harddisk . Appropriate
decoders ( such as libjpeg , libpng , D3DX , DevIL ) are required to load theses textures .
aiTexture : : mWidth specifies the size of the texture data in bytes , aiTexture : : pcData is
a pointer to the raw image data and aiTexture : : achFormatHint is either zeroed or
2009-07-20 18:50:51 +00:00
contains the most common file extension of the embedded texture ' s format . This value is only
2012-02-03 17:26:06 +00:00
set if assimp is able to determine the file format .
2008-05-20 16:02:29 +00:00
*/
2009-08-31 15:51:54 +00:00
2009-05-03 21:49:34 +00:00
/**
@ page materials Material System
@ section General Overview
2015-04-20 22:36:47 +00:00
All materials are stored in an array of aiMaterial inside the aiScene .
2009-05-03 21:49:34 +00:00
2015-04-20 22:36:47 +00:00
Each aiMesh refers to one
2009-05-03 21:49:34 +00:00
material by its index in the array . Due to the vastly diverging definitions and usages of material
parameters there is no hard definition of a material structure . Instead a material is defined by
2015-04-20 22:36:47 +00:00
a set of properties accessible by their names . Have a look at assimp / material . h to see what types of
2009-05-03 21:49:34 +00:00
properties are defined . In this file there are also various functions defined to test for the
presence of certain properties in a material and retrieve their values .
2009-05-04 19:41:38 +00:00
@ section mat_tex Textures
Textures are organized in stacks , each stack being evaluated independently . The final color value from a particular texture stack is used in the shading equation . For example , the computed color value of the diffuse texture stack ( aiTextureType_DIFFUSE ) is multipled with the amount of incoming diffuse light to obtain the final diffuse color of a pixel .
@ code
Stack Resulting equation
- - - - - - - - - - - - - - - - - - - - - - - -
| Constant base color | color
2015-04-20 22:36:47 +00:00
- - - - - - - - - - - - - - - - - - - - - - - -
2009-05-04 19:41:38 +00:00
| Blend operation 0 | +
- - - - - - - - - - - - - - - - - - - - - - - -
| Strength factor 0 | 0.25 *
- - - - - - - - - - - - - - - - - - - - - - - -
| Texture 0 | texture_0
2015-04-20 22:36:47 +00:00
- - - - - - - - - - - - - - - - - - - - - - - -
2009-05-04 19:41:38 +00:00
| Blend operation 1 | *
- - - - - - - - - - - - - - - - - - - - - - - -
| Strength factor 1 | 1.0 *
- - - - - - - - - - - - - - - - - - - - - - - -
| Texture 1 | texture_1
- - - - - - - - - - - - - - - - - - - - - - - -
. . . . . .
@ endcode
2009-05-03 21:49:34 +00:00
@ section keys Constants
2015-04-20 22:36:47 +00:00
All material key constants start with ' AI_MATKEY ' ( it ' s an ugly macro for historical reasons , don ' t ask ) .
2009-05-03 21:49:34 +00:00
< table border = " 1 " >
< tr >
< th > Name < / th >
< th > Data Type < / th >
< th > Default Value < / th >
< th > Meaning < / th >
< th > Notes < / th >
< / tr >
< tr >
< td > < tt > NAME < / tt > < / td >
< td > aiString < / td >
< td > n / a < / td >
< td > The name of the material , if available . < / td >
< td > Ignored by < tt > aiProcess_RemoveRedundantMaterials < / tt > . Materials are considered equal even if their names are different . < / td >
< / tr >
< tr >
< td > < tt > COLOR_DIFFUSE < / tt > < / td >
< td > aiColor3D < / td >
< td > black ( 0 , 0 , 0 ) < / td >
< td > Diffuse color of the material . This is typically scaled by the amount of incoming diffuse light ( e . g . using gouraud shading ) < / td >
< td > - - - < / td >
< / tr >
< tr >
< td > < tt > COLOR_SPECULAR < / tt > < / td >
< td > aiColor3D < / td >
< td > black ( 0 , 0 , 0 ) < / td >
< td > Specular color of the material . This is typically scaled by the amount of incoming specular light ( e . g . using phong shading ) < / td >
< td > - - - < / td >
< / tr >
< tr >
< td > < tt > COLOR_AMBIENT < / tt > < / td >
< td > aiColor3D < / td >
< td > black ( 0 , 0 , 0 ) < / td >
< td > Ambient color of the material . This is typically scaled by the amount of ambient light < / td >
< td > - - - < / td >
< / tr >
< tr >
< td > < tt > COLOR_EMISSIVE < / tt > < / td >
< td > aiColor3D < / td >
< td > black ( 0 , 0 , 0 ) < / td >
< td > Emissive color of the material . This is the amount of light emitted by the object . In real time applications it will usually not affect surrounding objects , but raytracing applications may wish to treat emissive objects as light sources . < / td >
< td > - - - < / tt > < / td >
< / tr >
< tr >
< td > < tt > COLOR_TRANSPARENT < / tt > < / td >
< td > aiColor3D < / td >
< td > black ( 0 , 0 , 0 ) < / td >
2015-04-20 22:36:47 +00:00
< td > Defines the transparent color of the material , this is the color to be multiplied with the color of
2009-05-03 21:49:34 +00:00
translucent light to construct the final ' destination color ' for a particular position in the screen buffer . T < / td >
< td > - - - < / tt > < / td >
< / tr >
< tr >
< td > < tt > WIREFRAME < / tt > < / td >
< td > int < / td >
< td > false < / td >
< td > Specifies whether wireframe rendering must be turned on for the material . 0 for false , ! 0 for true . < / td >
< td > - - - < / tt > < / td >
< / tr >
< tr >
< td > < tt > TWOSIDED < / tt > < / td >
< td > int < / td >
< td > false < / td >
< td > Specifies whether meshes using this material must be rendered without backface culling . 0 for false , ! 0 for true . < / td >
< td > Some importers set this property if they don ' t know whether the output face oder is right . As long as it is not set , you may safely enable backface culling . < / tt > < / td >
< / tr >
< tr >
< td > < tt > SHADING_MODEL < / tt > < / td >
< td > int < / td >
< td > gouraud < / td >
< td > One of the # aiShadingMode enumerated values . Defines the library shading model to use for ( real time ) rendering to approximate the original look of the material as closely as possible . < / td >
< td > The presence of this key might indicate a more complex material . If absent , assume phong shading only if a specular exponent is given . < / tt > < / td >
< / tr >
< tr >
< td > < tt > BLEND_FUNC < / tt > < / td >
< td > int < / td >
< td > false < / td >
< td > One of the # aiBlendMode enumerated values . Defines how the final color value in the screen buffer is computed from the given color at that position and the newly computed color from the material . Simply said , alpha blending settings . < / td >
< td > - < / td >
< / tr >
< tr >
< td > < tt > OPACITY < / tt > < / td >
< td > float < / td >
< td > 1.0 < / td >
< td > Defines the opacity of the material in a range between 0. .1 . < / td >
< td > Use this value to decide whether you have to activate alpha blending for rendering . < tt > OPACITY < / tt > ! = 1 usually also implies TWOSIDED = 1 to avoid cull artifacts . < / td >
< / tr >
< tr >
< td > < tt > SHININESS < / tt > < / td >
< td > float < / td >
< td > 0.f < / td >
< td > Defines the shininess of a phong - shaded material . This is actually the exponent of the phong specular equation < / td >
< td > < tt > SHININESS < / tt > = 0 is equivalent to < tt > SHADING_MODEL < / tt > = < tt > aiShadingMode_Gouraud < / tt > . < / td >
< / tr >
< tr >
< td > < tt > SHININESS_STRENGTH < / tt > < / td >
< td > float < / td >
< td > 1.0 < / td >
< td > Scales the specular color of the material . < / td >
< td > This value is kept separate from the specular color by most modelers , and so do we . < / td >
< / tr >
< tr >
< td > < tt > REFRACTI < / tt > < / td >
< td > float < / td >
< td > 1.0 < / td >
< td > Defines the Index Of Refraction for the material . That ' s not supported by most file formats . < / td >
< td > Might be of interest for raytracing . < / td >
< / tr >
< tr >
< td > < tt > TEXTURE ( t , n ) < / tt > < / td >
< td > aiString < / td >
< td > n / a < / td >
< td > Defines the path to the n ' th texture on the stack ' t ' , where ' n ' is any value > = 0 and ' t ' is one of the # aiTextureType enumerated values . < / td >
2009-05-04 19:41:38 +00:00
< td > See the ' Textures ' section above . < / td >
< / tr >
< tr >
< td > < tt > TEXBLEND ( t , n ) < / tt > < / td >
< td > float < / td >
< td > n / a < / td >
< td > Defines the strength the n ' th texture on the stack ' t ' . All color components ( rgb ) are multipled with this factor * before * any further processing is done . < / td >
< td > - < / td >
< / tr >
< tr >
< td > < tt > TEXOP ( t , n ) < / tt > < / td >
< td > int < / td >
< td > n / a < / td >
< td > One of the # aiTextureOp enumerated values . Defines the arithmetic operation to be used to combine the n ' th texture on the stack ' t ' with the n - 1 ' th . < tt > TEXOP ( t , 0 ) < / tt > refers to the blend operation between the base color for this stack ( e . g . < tt > COLOR_DIFFUSE < / tt > for the diffuse stack ) and the first texture . < / td >
< td > - < / td >
< / tr >
< tr >
< td > < tt > MAPPING ( t , n ) < / tt > < / td >
< td > int < / td >
< td > n / a < / td >
< td > Defines how the input mapping coordinates for sampling the n ' th texture on the stack ' t ' are computed . Usually explicit UV coordinates are provided , but some model file formats might also be using basic shapes , such as spheres or cylinders , to project textures onto meshes . < / td >
< td > See the ' Textures ' section below . # aiProcess_GenUVCoords can be used to let Assimp compute proper UV coordinates from projective mappings . < / td >
< / tr >
< tr >
< td > < tt > UVWSRC ( t , n ) < / tt > < / td >
< td > int < / td >
< td > n / a < / td >
< td > Defines the UV channel to be used as input mapping coordinates for sampling the n ' th texture on the stack ' t ' . All meshes assigned to this material share the same UV channel setup < / td >
2010-04-10 20:03:26 +00:00
< td > Presence of this key implies < tt > MAPPING ( t , n ) < / tt > to be # aiTextureMapping_UV . See @ ref uvwsrc for more details . < / td >
2009-05-04 19:41:38 +00:00
< / tr >
< tr >
< td > < tt > MAPPINGMODE_U ( t , n ) < / tt > < / td >
< td > int < / td >
< td > n / a < / td >
< td > Any of the # aiTextureMapMode enumerated values . Defines the texture wrapping mode on the x axis for sampling the n ' th texture on the stack ' t ' . ' Wrapping ' occurs whenever UVs lie outside the 0. .1 range . < / td >
< td > - < / td >
< / tr >
< tr >
< td > < tt > MAPPINGMODE_V ( t , n ) < / tt > < / td >
< td > int < / td >
< td > n / a < / td >
< td > Wrap mode on the v axis . See < tt > MAPPINGMODE_U < / tt > . < / td >
< td > - < / td >
< / tr >
< tr >
< td > < tt > TEXMAP_AXIS ( t , n ) < / tt > < / td >
< td > aiVector3D < / td >
< td > n / a < / td >
< td > < / tt > Defines the base axis to to compute the mapping coordinates for the n ' th texture on the stack ' t ' from . This is not required for UV - mapped textures . For instance , if < tt > MAPPING ( t , n ) < / tt > is # aiTextureMapping_SPHERE , U and V would map to longitude and latitude of a sphere around the given axis . The axis is given in local mesh space . < / td >
< td > - < / td >
< / tr >
< tr >
< td > < tt > TEXFLAGS ( t , n ) < / tt > < / td >
< td > int < / td >
< td > n / a < / td >
< td > < / tt > Defines miscellaneous flag for the n ' th texture on the stack ' t ' . This is a bitwise combination of the # aiTextureFlags enumerated values . < / td >
< td > - < / td >
2009-05-03 21:49:34 +00:00
< / tr >
< / table >
@ section cpp C + + - API
Retrieving a property from a material is done using various utility functions . For C + + it ' s simply calling aiMaterial : : Get ( )
@ code
aiMaterial * mat = . . . . .
// The generic way
if ( AI_SUCCESS ! = mat - > Get ( < material - key > , < where - to - store > ) ) {
// handle epic failure here
}
@ endcode
Simple , isn ' t it ? To get the name of a material you would use
@ code
aiString name ;
mat - > Get ( AI_MATKEY_NAME , name ) ;
@ endcode
Or for the diffuse color ( ' color ' won ' t be modified if the property is not set )
@ code
aiColor3D color ( 0.f , 0.f , 0.f ) ;
mat - > Get ( AI_MATKEY_COLOR_DIFFUSE , color ) ;
@ endcode
< b > Note : < / b > Get ( ) is actually a template with explicit specializations for aiColor3D , aiColor4D , aiString , float , int and some others .
2015-04-20 22:36:47 +00:00
Make sure that the type of the second parameter matches the expected data type of the material property ( no compile - time check yet ! ) .
2009-05-03 21:49:34 +00:00
Don ' t follow this advice if you wish to encounter very strange results .
@ section C C - API
For good old C it ' s slightly different . Take a look at the aiGetMaterialGet < data - type > functions .
@ code
aiMaterial * mat = . . . . .
if ( AI_SUCCESS ! = aiGetMaterialFloat ( mat , < material - key > , < where - to - store > ) ) {
// handle epic failure here
}
@ endcode
To get the name of a material you would use
@ code
aiString name ;
aiGetMaterialString ( mat , AI_MATKEY_NAME , & name ) ;
@ endcode
Or for the diffuse color ( ' color ' won ' t be modified if the property is not set )
@ code
aiColor3D color ( 0.f , 0.f , 0.f ) ;
aiGetMaterialColor ( mat , AI_MATKEY_COLOR_DIFFUSE , & color ) ;
@ endcode
2010-04-10 20:03:26 +00:00
@ section uvwsrc How to map UV channels to textures ( MATKEY_UVWSRC )
The MATKEY_UVWSRC property is only present if the source format doesn ' t specify an explicit mapping from
2012-02-03 17:26:06 +00:00
textures to UV channels . Many formats don ' t do this and assimp is not aware of a perfect rule either .
2010-04-10 20:03:26 +00:00
Your handling of UV channels needs to be flexible therefore . Our recommendation is to use logic like this
to handle most cases properly :
@ verbatim
have only one uv channel ?
assign channel 0 to all textures and break
for all textures
have uvwsrc for this texture ?
assign channel specified in uvwsrc
else
2015-04-20 22:36:47 +00:00
assign channels in ascending order for all texture stacks ,
2010-04-10 20:03:26 +00:00
i . e . diffuse1 gets channel 1 , opacity0 gets channel 0.
@ endverbatim
2009-05-03 21:49:34 +00:00
@ section pseudo Pseudo Code Listing
2015-04-20 22:36:47 +00:00
For completeness , the following is a very rough pseudo - code sample showing how to evaluate Assimp materials in your
shading pipeline . You ' ll probably want to limit your handling of all those material keys to a reasonable subset suitable for your purposes
2009-05-03 21:49:34 +00:00
( for example most 3 d engines won ' t support highly complex multi - layer materials , but many 3 d modellers do ) .
Also note that this sample is targeted at a ( shader - based ) rendering pipeline for real time graphics .
@ code
// ---------------------------------------------------------------------------------------
// Evaluate multiple textures stacked on top of each other
float3 EvaluateStack ( stack )
{
// For the 'diffuse' stack stack.base_color would be COLOR_DIFFUSE
// and TEXTURE(aiTextureType_DIFFUSE,n) the n'th texture.
float3 base = stack . base_color ;
for ( every texture in stack )
{
// assuming we have explicit & pretransformed UVs for this texture
2015-04-20 22:36:47 +00:00
float3 color = SampleTexture ( texture , uv ) ;
2009-05-03 21:49:34 +00:00
// scale by texture blend factor
color * = texture . blend ;
if ( texture . op = = add )
base + = color ;
else if ( texture . op = = multiply )
base * = color ;
else // other blend ops go here
}
return base ;
}
// ---------------------------------------------------------------------------------------
// Compute the diffuse contribution for a pixel
float3 ComputeDiffuseContribution ( )
{
if ( shading = = none )
return float3 ( 1 , 1 , 1 ) ;
float3 intensity ( 0 , 0 , 0 ) ;
for ( all lights in range )
{
float fac = 1.f ;
if ( shading = = gouraud )
fac = lambert - term . .
else // other shading modes go here
// handling of different types of lights, such as point or spot lights
// ...
// and finally sum the contribution of this single light ...
intensity + = light . diffuse_color * fac ;
}
// ... and combine the final incoming light with the diffuse color
return EvaluateStack ( diffuse ) * intensity ;
}
// ---------------------------------------------------------------------------------------
// Compute the specular contribution for a pixel
float3 ComputeSpecularContribution ( )
{
if ( shading = = gouraud | | specular_strength = = 0 | | specular_exponent = = 0 )
return float3 ( 0 , 0 , 0 ) ;
float3 intensity ( 0 , 0 , 0 ) ;
for ( all lights in range )
{
float fac = 1.f ;
if ( shading = = phong )
fac = phong - term . .
else // other specular shading modes go here
// handling of different types of lights, such as point or spot lights
// ...
// and finally sum the specular contribution of this single light ...
intensity + = light . specular_color * fac ;
}
// ... and combine the final specular light with the specular color
return EvaluateStack ( specular ) * intensity * specular_strength ;
}
// ---------------------------------------------------------------------------------------
// Compute the ambient contribution for a pixel
float3 ComputeAmbientContribution ( )
{
if ( shading = = none )
return float3 ( 0 , 0 , 0 ) ;
float3 intensity ( 0 , 0 , 0 ) ;
for ( all lights in range )
{
float fac = 1.f ;
// handling of different types of lights, such as point or spot lights
// ...
// and finally sum the ambient contribution of this single light ...
intensity + = light . ambient_color * fac ;
}
// ... and combine the final ambient light with the ambient color
return EvaluateStack ( ambient ) * intensity ;
}
// ---------------------------------------------------------------------------------------
// Compute the final color value for a pixel
// @param prev Previous color at that position in the framebuffer
float4 PimpMyPixel ( float4 prev )
{
// .. handle displacement mapping per vertex
// .. handle bump/normal mapping
// Get all single light contribution terms
float3 diff = ComputeDiffuseContribution ( ) ;
2015-04-20 22:36:47 +00:00
float3 spec = ComputeSpecularContribution ( ) ;
2009-05-03 21:49:34 +00:00
float3 ambi = ComputeAmbientContribution ( ) ;
// .. and compute the final color value for this pixel
float3 color = diff + spec + ambi ;
float3 opac = EvaluateStack ( opacity ) ;
2010-01-13 16:37:57 +00:00
// note the *slightly* strange meaning of additive and multiplicative blending here ...
// those names will most likely be changed in future versions
if ( blend_func = = add )
return prev + color * opac ;
else if ( blend_func = = multiply )
return prev * ( 1.0 - opac ) + prev * opac ;
return color ;
2009-05-03 21:49:34 +00:00
}
@ endcode
*/
2011-07-14 17:46:05 +00:00
2009-01-13 20:19:40 +00:00
2015-04-20 22:36:47 +00:00
/**
2010-07-08 22:44:44 +00:00
@ page perf Performance
@ section perf_overview Overview
2012-02-03 17:26:06 +00:00
This page discusses general performance issues related to assimp .
2010-07-08 22:44:44 +00:00
@ section perf_profile Profiling
2012-02-03 17:26:06 +00:00
assimp has built - in support for < i > very < / i > basic profiling and time measurement . To turn it on , set the < tt > GLOB_MEASURE_TIME < / tt >
2011-07-14 17:46:05 +00:00
configuration switch to < tt > true < / tt > ( nonzero ) . Results are dumped to the log file , so you need to setup
an appropriate logger implementation with at least one output stream first ( see the @ link logging Logging Page @ endlink
2015-04-20 22:36:47 +00:00
for the details . ) .
2011-07-14 17:46:05 +00:00
2015-04-20 22:36:47 +00:00
Note that these measurements are based on a single run of the importer and each of the post processing steps , so
2011-07-14 17:46:05 +00:00
a single result set is far away from being significant in a statistic sense . While precision can be improved
by running the test multiple times , the low accuracy of the timings may render the results useless
for smaller files .
2010-07-08 22:44:44 +00:00
2011-07-14 17:46:05 +00:00
A sample report looks like this ( some unrelated log messages omitted , entries grouped for clarity ) :
2010-07-08 22:44:44 +00:00
@ verbatim
Debug , T5488 : START ` total `
Info , T5488 : Found a matching importer for this file format
2010-07-09 16:44:13 +00:00
2010-07-08 22:44:44 +00:00
Debug , T5488 : START ` import `
Info , T5488 : BlendModifier : Applied the ` Subdivision ` modifier to ` OBMonkey `
Debug , T5488 : END ` import ` , dt = 3.516 s
Debug , T5488 : START ` preprocess `
Debug , T5488 : END ` preprocess ` , dt = 0.001 s
Info , T5488 : Entering post processing pipeline
2010-07-09 16:44:13 +00:00
2010-07-08 22:44:44 +00:00
Debug , T5488 : START ` postprocess `
Debug , T5488 : RemoveRedundantMatsProcess begin
2015-04-20 22:36:47 +00:00
Debug , T5488 : RemoveRedundantMatsProcess finished
2010-07-08 22:44:44 +00:00
Debug , T5488 : END ` postprocess ` , dt = 0.001 s
2010-07-09 16:44:13 +00:00
2010-07-08 22:44:44 +00:00
Debug , T5488 : START ` postprocess `
Debug , T5488 : TriangulateProcess begin
Info , T5488 : TriangulateProcess finished . All polygons have been triangulated .
Debug , T5488 : END ` postprocess ` , dt = 3.415 s
2010-07-09 16:44:13 +00:00
2010-07-08 22:44:44 +00:00
Debug , T5488 : START ` postprocess `
Debug , T5488 : SortByPTypeProcess begin
Info , T5488 : Points : 0 , Lines : 0 , Triangles : 1 , Polygons : 0 ( Meshes , X = removed )
2010-07-09 16:44:13 +00:00
Debug , T5488 : SortByPTypeProcess finished
2010-07-08 22:44:44 +00:00
Debug , T5488 : START ` postprocess `
Debug , T5488 : JoinVerticesProcess begin
Debug , T5488 : Mesh 0 ( unnamed ) | Verts in : 503808 out : 126345 | ~ 74.922
Info , T5488 : JoinVerticesProcess finished | Verts in : 503808 out : 126345 | ~ 74.9
2010-07-09 16:44:13 +00:00
Debug , T5488 : END ` postprocess ` , dt = 2.052 s
2010-07-08 22:44:44 +00:00
Debug , T5488 : START ` postprocess `
Debug , T5488 : FlipWindingOrderProcess begin
Debug , T5488 : FlipWindingOrderProcess finished
Debug , T5488 : END ` postprocess ` , dt = 0.006 s
2010-07-09 16:44:13 +00:00
2010-07-08 22:44:44 +00:00
Debug , T5488 : START ` postprocess `
Debug , T5488 : LimitBoneWeightsProcess begin
Debug , T5488 : LimitBoneWeightsProcess end
Debug , T5488 : END ` postprocess ` , dt = 0.001 s
2010-07-09 16:44:13 +00:00
2010-07-08 22:44:44 +00:00
Debug , T5488 : START ` postprocess `
Debug , T5488 : ImproveCacheLocalityProcess begin
Debug , T5488 : Mesh 0 | ACMR in : 0.851622 out : 0.718139 | ~ 15.7
Info , T5488 : Cache relevant are 1 meshes ( 251904 faces ) . Average output ACMR is 0.718139
2015-04-20 22:36:47 +00:00
Debug , T5488 : ImproveCacheLocalityProcess finished .
2010-07-08 22:44:44 +00:00
Debug , T5488 : END ` postprocess ` , dt = 1.903 s
2010-07-09 16:44:13 +00:00
2010-07-08 22:44:44 +00:00
Info , T5488 : Leaving post processing pipeline
Debug , T5488 : END ` total ` , dt = 11.269 s
@ endverbatim
2011-07-14 17:46:05 +00:00
In this particular example only one fourth of the total import time was spent on the actual importing , while the rest of the
2015-04-20 22:36:47 +00:00
time got consumed by the # aiProcess_Triangulate , # aiProcess_JoinIdenticalVertices and # aiProcess_ImproveCacheLocality
postprocessing steps . A wise selection of postprocessing steps is therefore essential to getting good performance .
Of course this depends on the individual requirements of your application , in many of the typical use cases of assimp performance won ' t
2011-07-14 17:46:05 +00:00
matter ( i . e . in an offline content pipeline ) .
2010-07-08 22:44:44 +00:00
*/
2015-04-20 22:36:47 +00:00
/**
2010-07-08 22:44:44 +00:00
@ page threading Threading
@ section overview Overview
2012-02-03 17:26:06 +00:00
This page discusses both assimps scalability in threaded environments and the precautions to be taken in order to
2011-07-14 17:46:05 +00:00
use it from multiple threads concurrently .
2010-07-08 22:44:44 +00:00
2011-07-14 17:46:05 +00:00
@ section threadsafety Thread - safety / using Assimp concurrently from several threads
2010-07-08 22:44:44 +00:00
The library can be accessed by multiple threads simultaneously , as long as the
2015-04-20 22:36:47 +00:00
following prerequisites are fulfilled :
2011-07-14 17:46:05 +00:00
- Users of the C + + - API should ensure that they use a dedicated # Assimp : : Importer instance for each thread . Constructing instances of # Assimp : : Importer is expensive , so it might be a good idea to
let every thread maintain its own thread - local instance ( which can be used to
load as many files as necessary ) .
2012-02-03 17:26:06 +00:00
- The C - API is thread safe .
2011-07-14 17:46:05 +00:00
- When supplying custom IO logic , one must make sure the underlying implementation is thread - safe .
- Custom log streams or logger replacements have to be thread - safe , too .
2010-07-08 22:44:44 +00:00
2015-04-20 22:36:47 +00:00
Multiple concurrent imports may or may not be beneficial , however . For certain file formats in conjunction with
little or no post processing IO times tend to be the performance bottleneck . Intense post processing together
with ' slow ' file formats like X or Collada might scale well with multiple concurrent imports .
2010-07-08 22:44:44 +00:00
@ section automt Internal threading
2011-07-14 17:46:05 +00:00
Internal multi - threading is not currently implemented .
2010-07-08 22:44:44 +00:00
*/
2009-01-13 20:19:40 +00:00
2009-09-05 12:04:32 +00:00
/**
2011-07-14 17:46:05 +00:00
@ page res Resources
2015-04-20 22:36:47 +00:00
This page lists some useful resources for assimp . Note that , even though the core team has an eye on them ,
we cannot guarantee the accuracy of third - party information . If in doubt , it ' s best to ask either on the
2011-07-14 17:46:05 +00:00
mailing list or on our forums on SF . net .
2012-02-03 17:26:06 +00:00
- assimp comes with some sample applications , these can be found in the < i > . / samples < / i > folder . Don ' t forget to read the < i > README < / i > file .
2011-07-14 17:46:05 +00:00
- http : //www.drivenbynostalgia.com/files/AssimpOpenGLDemo.rar - OpenGl animation sample using the library's animation import facilities.
- http : //nolimitsdesigns.com/game-design/open-asset-import-library-animation-loader/ is another utility to
simplify animation playback .
- http : //ogldev.atspace.co.uk/www/tutorial22/tutorial22.html - Tutorial "Loading models using the Open Asset Import Library", out of a series of OpenGl tutorials.
*/
/**
2012-02-03 17:26:06 +00:00
@ page importer_notes Importer Notes
2009-09-05 12:04:32 +00:00
2011-05-07 13:41:35 +00:00
< hr >
2010-07-08 22:44:44 +00:00
@ section blender Blender
2011-05-07 13:41:35 +00:00
2015-04-20 22:36:47 +00:00
This section contains implementation notes for the Blender3D importer .
2010-07-08 22:44:44 +00:00
@ subsection bl_overview Overview
2009-09-05 12:04:32 +00:00
2015-04-20 22:36:47 +00:00
assimp provides a self - contained reimplementation of Blender ' s so called SDNA system ( http : //www.blender.org/development/architecture/notes-on-sdna/).
2011-07-14 17:46:05 +00:00
SDNA allows Blender to be fully backward and forward compatible and to exchange
2015-04-20 22:36:47 +00:00
files across all platforms . The BLEND format is thus a non - trivial binary monster and the loader tries to read the most of it ,
2011-07-14 17:46:05 +00:00
naturally limited by the scope of the # aiScene output data structure .
2015-04-20 22:36:47 +00:00
Consequently , if Blender is the only modeling tool in your asset work flow , consider writing a
2012-02-03 17:26:06 +00:00
custom exporter from Blender if assimps format coverage does not meet the requirements .
2010-03-03 16:08:27 +00:00
2010-07-08 22:44:44 +00:00
@ subsection bl_status Current status
2011-07-14 17:46:05 +00:00
The Blender loader does not support animations yet , but is apart from that considered relatively stable .
2011-05-07 13:41:35 +00:00
2010-07-08 22:44:44 +00:00
@ subsection bl_notes Notes
2011-07-14 17:46:05 +00:00
When filing bugs on the Blender loader , always give the Blender version ( or , even better , post the file caused the error ) .
2011-05-07 13:41:35 +00:00
< hr >
@ section ifc IFC
2015-04-20 22:36:47 +00:00
This section contains implementation notes on the IFC - STEP importer .
2011-05-07 13:41:35 +00:00
@ subsection ifc_overview Overview
2010-07-08 22:44:44 +00:00
2015-04-20 22:36:47 +00:00
The library provides a partial implementation of the IFC2x3 industry standard for automatized exchange of CAE / architectural
data sets . See http : //en.wikipedia.org/wiki/Industry_Foundation_Classes for more information on the format. We aim
at getting as much 3 D data out of the files as possible .
2010-07-08 22:44:44 +00:00
2011-05-07 13:41:35 +00:00
@ subsection ifc_status Current status
IFC support is new and considered experimental . Please report any bugs you may encounter .
@ subsection ifc_notes Notes
2011-07-14 17:46:05 +00:00
- Only the STEP - based encoding is supported . IFCZIP and IFCXML are not ( but IFCZIP can simply be unzipped to get a STEP file ) .
2011-05-07 13:41:35 +00:00
- The importer leaves vertex coordinates untouched , but applies a global scaling to the root transform to
convert from whichever unit the IFC file uses to < i > metres < / i > .
2015-04-20 22:36:47 +00:00
- If multiple geometric representations are provided , the choice which one to load is based on how expensive a representation seems
2011-07-14 17:46:05 +00:00
to be in terms of import time . The loader also avoids representation types for which it has known deficits .
2015-04-20 22:36:47 +00:00
- Not supported are arbitrary binary operations ( binary clipping is implemented , though ) .
2011-07-14 17:46:05 +00:00
- Of the various relationship types that IFC knows , only aggregation , containment and material assignment are resolved and mapped to
the output graph .
2015-04-20 22:36:47 +00:00
- The implementation knows only about IFC2X3 and applies this rule set to all models it encounters ,
2011-07-14 17:46:05 +00:00
regardless of their actual version . Loading of older or newer files may fail with parsing errors .
2011-05-07 13:41:35 +00:00
2013-03-29 12:42:38 +00:00
@ subsection ifc_metadata Metadata
2015-04-20 22:36:47 +00:00
IFC file properties ( IfcPropertySet ) are kept as per - node metadata , see aiNode : : mMetaData .
2013-03-29 12:42:38 +00:00
2011-05-07 13:41:35 +00:00
< hr >
2010-07-08 22:44:44 +00:00
@ section ogre Ogre
2012-03-12 13:59:51 +00:00
* ATTENTION * : The Ogre - Loader is currently under development , many things have changed after this documentation was written , but they are not final enough to rewrite the documentation . So things may have changed by now !
2015-04-20 22:36:47 +00:00
This section contains implementations notes for the OgreXML importer .
2010-07-08 22:44:44 +00:00
@ subsection overview Overview
2012-06-03 11:06:47 +00:00
Ogre importer is currently optimized for the Blender Ogre exporter , because thats the only one that I use . You can find the Blender Ogre exporter at : http : //www.ogre3d.org/forums/viewtopic.php?f=8&t=45922
2010-03-03 16:08:27 +00:00
@ subsection what What will be loaded ?
2012-06-03 11:06:47 +00:00
Mesh : Faces , Positions , Normals and all TexCoords . The Materialname will be used to load the material .
2010-03-03 16:08:27 +00:00
Material : The right material in the file will be searched , the importer should work with materials who
2010-11-09 18:13:08 +00:00
have 1 technique and 1 pass in this technique . From there , the texturename ( for 1 color - and 1 normalmap ) and the
materialcolors ( but not in custom materials ) will be loaded . Also , the materialname will be set .
2010-03-03 16:08:27 +00:00
Skeleton : Skeleton with Bone hierarchy ( Position and Rotation , but no Scaling in the skeleton is supported ) , names and transformations ,
animations with rotation , translation and scaling keys .
@ subsection export_Blender How to export Files from Blender
You can find informations about how to use the Ogreexporter by your own , so here are just some options that you need , so the assimp
importer will load everything correctly :
- Use either " Rendering Material " or " Custom Material " see @ ref material
- do not use " Flip Up Axies to Y "
- use " Skeleton name follow mesh "
@ subsection xml XML Format
There is a binary and a XML mesh Format from Ogre . This loader can only
2009-09-05 12:04:32 +00:00
Handle xml files , but don ' t panic , there is a command line converter , which you can use
to create XML files from Binary Files . Just look on the Ogre page for it .
Currently you can only load meshes . So you will need to import the * . mesh . xml file , the loader will
try to find the appendant material and skeleton file .
The skeleton file must have the same name as the mesh file , e . g . fish . mesh . xml and fish . skeleton . xml .
2010-03-03 16:08:27 +00:00
@ subsection material Materials
2012-02-20 10:27:27 +00:00
The material file can have the same name as the mesh file ( if the file is model . mesh or model . mesh . xml the
loader will try to load model . material ) ,
or you can use Importer : : Importer : : SetPropertyString ( AI_CONFIG_IMPORT_OGRE_MATERIAL_FILE , " materiafile.material " )
to specify the name of the material file . This is especially usefull if multiply materials a stored in a single file .
2009-09-05 12:04:32 +00:00
The importer will first try to load the material with the same name as the mesh and only if this can ' t be open try
to load the alternate material file . The default material filename is " Scene.material " .
2009-09-05 15:49:23 +00:00
We suggest that you use custom materials , because they support multiple textures ( like colormap and normalmap ) . First of all you
should read the custom material sektion in the Ogre Blender exporter Help File , and than use the assimp . tlp template , which you
2010-03-03 16:08:27 +00:00
can find in scripts / OgreImpoter / Assimp . tlp in the assimp source . If you don ' t set all values , don ' t worry , they will be ignored during import .
2009-09-05 12:04:32 +00:00
2010-03-03 16:08:27 +00:00
If you want more properties in custom materials , you can easily expand the ogre material loader , it will be just a few lines for each property .
2012-02-20 10:27:27 +00:00
Just look in OgreImporterMaterial . cpp
2010-11-09 18:13:08 +00:00
2012-06-03 18:01:32 +00:00
@ subsection Importer Properties
- IMPORT_OGRE_TEXTURETYPE_FROM_FILENAME : Normally , a texture is loaded as a colormap , if no
target is specified in the
materialfile . Is this switch is enabled , texture names ending with _n , _l , _s
2015-04-20 22:36:47 +00:00
are used as normalmaps , lightmaps or specularmaps .
2012-06-03 18:01:32 +00:00
< br >
Property type : Bool . Default value : false .
- IMPORT_OGRE_MATERIAL_FILE : Ogre Meshes contain only the MaterialName , not the MaterialFile .
2015-04-20 22:36:47 +00:00
If there
is no material file with the same name as the material , Ogre Importer will
2012-06-03 18:01:32 +00:00
try to load this file and search the material in it .
< br >
Property type : String . Default value : guessed .
2010-11-09 18:13:08 +00:00
@ subsection todo Todo
- Load colors in custom materials
- extend custom and normal material loading
- fix bone hierarchy bug
2012-06-03 11:06:47 +00:00
- test everything elaboratly
2010-11-09 18:13:08 +00:00
- check for non existent animation keys ( what happens if a one time not all bones have a key ? )
2011-07-14 17:46:05 +00:00
*/
/**
@ page extend Extending the Library
@ section General
Or - how to write your own loaders . It ' s easy . You just need to implement the # Assimp : : BaseImporter class ,
which defines a few abstract methods , register your loader , test it carefully and provide test models for it .
OK , that sounds too easy : - ) . The whole procedure for a new loader merely looks like this :
< ul >
< li > Create a header ( < tt > < i > FormatName < / i > Importer . h < / tt > ) and a unit ( < tt > < i > FormatName < / i > Importer . cpp < / tt > ) in the < tt > & lt ; root & gt ; / code / < / tt > directory < / li >
< li > Add them to the following workspaces : vc8 and vc9 ( the files are in the workspaces directory ) , CMAKE ( code / CMakeLists . txt , create a new
source group for your importer and put them also to ADD_LIBRARY ( assimp SHARED ) ) < / li >
< li > Include < i > AssimpPCH . h < / i > - this is the PCH file , and it includes already most Assimp - internal stuff . < / li >
2015-04-20 22:36:47 +00:00
< li > Open Importer . cpp and include your header just below the < i > ( include_new_importers_here ) < / i > line ,
guarded by a # define
2011-07-14 17:46:05 +00:00
@ code
2012-02-03 17:26:06 +00:00
# if (!defined assimp_BUILD_NO_FormatName_IMPORTER)
2011-07-14 17:46:05 +00:00
. . .
# endif
@ endcode
Wrap the same guard around your . cpp ! < / li >
< li > Now advance to the < i > ( register_new_importers_here ) < / i > line in the Importer . cpp and register your importer there - just like all the others do . < / li >
2015-04-20 22:36:47 +00:00
< li > Setup a suitable test environment ( i . e . use AssimpView or your own application ) , make sure to enable
2011-07-14 17:46:05 +00:00
the # aiProcess_ValidateDataStructure flag and enable verbose logging . That is , simply call before you import anything :
@ code
DefaultLogger : : create ( " AssimpLog.txt " , Logger : : VERBOSE )
@ endcode
< / li >
< li >
2015-04-20 22:36:47 +00:00
Implement the Assimp : : BaseImporter : : CanRead ( ) , Assimp : : BaseImporter : : InternReadFile ( ) and Assimp : : BaseImporter : : GetExtensionList ( ) .
2011-07-14 17:46:05 +00:00
Just copy ' n ' paste the template from Appendix A and adapt it for your needs .
< / li >
< li > For error handling , throw a dynamic allocated ImportErrorException ( see Appendix A ) for critical errors , and log errors , warnings , infos and debuginfos
with DefaultLogger : : get ( ) - > [ error , warn , debug , info ] .
< / li >
< li >
Make sure that your loader compiles against all build configurations on all supported platforms . This includes < i > - noboost < / i > ! To avoid problems ,
see the boost section on this page for a list of all ' allowed ' boost classes ( again , this grew historically when we had to accept that boost
is not THAT widely spread that one could rely on it being available everywhere ) .
< / li >
< li >
Provide some _free_ test models in < tt > & lt ; root & gt ; / test / models / & lt ; FormatName & gt ; / < / tt > and credit their authors .
Test files for a file format shouldn ' t be too large ( < i > ~ 500 KiB in total < / i > ) , and not too repetive . Try to cover all format features with test data .
< / li >
< li >
Done ! Please , share your loader that everyone can profit from it !
< / li >
< / ul >
@ section properties Properties
You can use properties to chance the behavior of you importer . In order to do so , you have to overide BaseImporter : : SetupProperties , and specify
2012-02-03 17:26:06 +00:00
you custom properties in config . h . Just have a look to the other AI_CONFIG_IMPORT_ * defines and you will understand , how it works .
2011-07-14 17:46:05 +00:00
The properties can be set with Importer : : SetProperty * * * ( ) and can be accessed in your SetupProperties function with Importer : : GetProperty * * * ( ) . You can
store the properties as a member variable of your importer , they are thread safe .
@ section tnote Notes for text importers
< ul >
< li > Try to make your parser as flexible as possible . Don ' t rely on particular layout , whitespace / tab style ,
except if the file format has a strict definition , in which case you should always warn about spec violations .
But the general rule of thumb is < i > be strict in what you write and tolerant in what you accept < / i > . < / li >
2015-04-20 22:36:47 +00:00
< li > Call Assimp : : BaseImporter : : ConvertToUTF8 ( ) before you parse anything to convert foreign encodings to UTF - 8.
2011-07-14 17:46:05 +00:00
That ' s not necessary for XML importers , which must use the provided IrrXML for reading . < / li >
< / ul >
@ section bnote Notes for binary importers
< ul >
< li >
Take care of endianess issues ! Assimp importers mostly support big - endian platforms , which define the < tt > AI_BUILD_BIG_ENDIAN < / tt > constant .
See the next section for a list of utilities to simplify this task .
< / li >
< li >
Don ' t trust the input data ! Check all offsets !
< / li >
< / ul >
@ section util Utilities
Mixed stuff for internal use by loaders , mostly documented ( most of them are already included by < i > AssimpPCH . h < / i > ) :
< ul >
2015-04-20 22:36:47 +00:00
< li > < b > ByteSwapper < / b > ( < i > ByteSwapper . h < / i > ) - manual byte swapping stuff for binary loaders . < / li >
2011-07-14 17:46:05 +00:00
< li > < b > StreamReader < / b > ( < i > StreamReader . h < / i > ) - safe , endianess - correct , binary reading . < / li >
< li > < b > IrrXML < / b > ( < i > irrXMLWrapper . h < / i > ) - for XML - parsing ( SAX . < / li >
< li > < b > CommentRemover < / b > ( < i > RemoveComments . h < / i > ) - remove single - line and multi - line comments from a text file . < / li >
2015-04-20 22:36:47 +00:00
< li > fast_atof , strtoul10 , strtoul16 , SkipSpaceAndLineEnd , SkipToNextToken . . large family of low - level
2011-07-14 17:46:05 +00:00
parsing functions , mostly declared in < i > fast_atof . h < / i > , < i > StringComparison . h < / i > and < i > ParsingUtils . h < / i > ( a collection that grew
historically , so don ' t expect perfect organization ) . < / li >
< li > < b > ComputeNormalsWithSmoothingsGroups ( ) < / b > ( < i > SmoothingGroups . h < / i > ) - Computes normal vectors from plain old smoothing groups . < / li >
< li > < b > SkeletonMeshBuilder < / b > ( < i > SkeletonMeshBuilder . h < / i > ) - generate a dummy mesh from a given ( animation ) skeleton . < / li >
< li > < b > StandardShapes < / b > ( < i > StandardShapes . h < / i > ) - generate meshes for standard solids , such as platonic primitives , cylinders or spheres . < / li >
< li > < b > BatchLoader < / b > ( < i > BaseImporter . h < / i > ) - manage imports from external files . Useful for file formats
which spread their data across multiple files . < / li >
< li > < b > SceneCombiner < / b > ( < i > SceneCombiner . h < / i > ) - exhaustive toolset to merge multiple scenes . Useful for file formats
which spread their data across multiple files . < / li >
< / ul >
@ section mat Filling materials
The required definitions zo set / remove / query keys in # aiMaterial structures are declared in < i > MaterialSystem . h < / i > , in a
2011-08-22 20:22:51 +00:00
# aiMaterial derivate called #aiMaterial. The header is included by AssimpPCH.h, so you don't need to bother.
2011-07-14 17:46:05 +00:00
@ code
2011-08-22 20:22:51 +00:00
aiMaterial * mat = new aiMaterial ( ) ;
2011-07-14 17:46:05 +00:00
const float spec = 16.f ;
mat - > AddProperty ( & spec , 1 , AI_MATKEY_SHININESS ) ;
//set the name of the material:
NewMaterial - > AddProperty ( & aiString ( MaterialName . c_str ( ) ) , AI_MATKEY_NAME ) ; //MaterialName is a std::string
//set the first diffuse texture
NewMaterial - > AddProperty ( & aiString ( Texturename . c_str ( ) ) , AI_MATKEY_TEXTURE ( aiTextureType_DIFFUSE , 0 ) ) ; //again, Texturename is a std::string
@ endcode
@ section boost Boost
The boost whitelist :
< ul >
< li > < i > boost . scoped_ptr < / i > < / li >
< li > < i > boost . scoped_array < / i > < / li >
< li > < i > boost . format < / i > < / li >
< li > < i > boost . random < / i > < / li >
< li > < i > boost . common_factor < / i > < / li >
< li > < i > boost . foreach < / i > < / li >
< li > < i > boost . tuple < / i > < / li >
< / ul >
( if you happen to need something else , i . e . boost : : thread , make this an optional feature .
2012-02-03 17:26:06 +00:00
< tt > assimp_BUILD_BOOST_WORKAROUND < / tt > is defined for < i > - noboost < / i > builds )
2011-07-14 17:46:05 +00:00
@ section appa Appendix A - Template for BaseImporter ' s abstract methods
@ code
// -------------------------------------------------------------------------------
2015-04-20 22:36:47 +00:00
// Returns whether the class can handle the format of the given file.
bool xxxxImporter : : CanRead ( const std : : string & pFile , IOSystem * pIOHandler ,
2011-07-14 17:46:05 +00:00
bool checkSig ) const
{
const std : : string extension = GetExtension ( pFile ) ;
if ( extension = = " xxxx " ) {
return true ;
}
if ( ! extension . length ( ) | | checkSig ) {
2015-04-20 22:36:47 +00:00
// no extension given, or we're called a second time because no
// suitable loader was found yet. This means, we're trying to open
2011-07-14 17:46:05 +00:00
// the file and look for and hints to identify the file format.
// #Assimp::BaseImporter provides some utilities:
//
// #Assimp::BaseImporter::SearchFileHeaderForToken - for text files.
// It reads the first lines of the file and does a substring check
// against a given list of 'magic' strings.
//
// #Assimp::BaseImporter::CheckMagicToken - for binary files. It goes
2015-04-20 22:36:47 +00:00
// to a particular offset in the file and and compares the next words
2011-07-14 17:46:05 +00:00
// against a given list of 'magic' tokens.
2015-04-20 22:36:47 +00:00
// These checks MUST be done (even if !checkSig) if the file extension
// is not exclusive to your format. For example, .xml is very common
2011-07-14 17:46:05 +00:00
// and (co)used by many formats.
}
return false ;
}
// -------------------------------------------------------------------------------
// Get list of file extensions handled by this loader
void xxxxImporter : : GetExtensionList ( std : : set < std : : string > & extensions )
{
extensions . insert ( " xxx " ) ;
}
// -------------------------------------------------------------------------------
2015-04-20 22:36:47 +00:00
void xxxxImporter : : InternReadFile ( const std : : string & pFile ,
2011-07-14 17:46:05 +00:00
aiScene * pScene , IOSystem * pIOHandler )
{
boost : : scoped_ptr < IOStream > file ( pIOHandler - > Open ( pFile , " rb " ) ) ;
// Check whether we can read from the file
if ( file . get ( ) = = NULL ) {
throw DeadlyImportError ( " Failed to open xxxx file " + pFile + " . " ) ;
}
2015-04-20 22:36:47 +00:00
2011-07-14 17:46:05 +00:00
// Your task: fill pScene
2015-04-20 22:36:47 +00:00
// Throw a ImportErrorException with a meaningful (!) error message if
2011-07-14 17:46:05 +00:00
// something goes wrong.
}
@ endcode
2011-12-18 20:54:50 +00:00
*/
2012-06-26 19:46:18 +00:00
2015-04-20 22:36:47 +00:00
2012-06-26 19:46:18 +00:00
/**
@ page AnimationOverview Animation Overview
\ section Transformations
This diagram shows how you can calculate your transformationmatrices for an animated character :
< img src = " AnimationOverview.png " / >
2015-04-20 22:36:47 +00:00
* */