@ -149,19 +149,82 @@ template<class T> struct OptionalButAlsoPointer: Containers::Optional<T> {
/**
/**
@ brief Base for importer plugins
@ brief Base for importer plugins
Provides interface for importing 2 D / 3 D scene , camera , light , animation , mesh ,
Provides interface for importing generic scene data such as images , meshes or
material , texture and image data .
animations .
A scene file can generally have an arbitrary amount of data of particular kind
and so the importer provides a set of @ cpp thing ( id ) @ ce accessors , where the
ID is from @ cpp 0 @ ce to @ cpp thingCount ( ) - 1 @ ce . Certain kinds of data
can also reference each other via the ID ( for example a material specifies the
ID of a texture it uses ) . The following kinds of data can be imported :
- @ ref AnimationData using @ ref animation ( UnsignedInt ) up to
@ ref animationCount ( ) . Each animation then references the 2 D / 3 D object
transformation it affects via its ID .
- @ ref CameraData using @ ref camera ( UnsignedInt ) up to @ ref cameraCount ( )
- @ ref ImageData1D / @ ref ImageData2D / @ ref ImageData3D using
@ ref image1D ( UnsignedInt , UnsignedInt ) /
@ ref image2D ( UnsignedInt , UnsignedInt ) /
@ ref image3D ( UnsignedInt , UnsignedInt ) up to @ ref image1DCount ( ) /
@ ref image2DCount ( ) / @ ref image3DCount ( ) . Each image can also have
multiple ( mip ) levels which are requested through the second parameter up
to @ ref image1DLevelCount ( ) / @ ref image2DLevelCount ( ) /
@ ref image3DLevelCount ( ) .
- @ ref LightData using @ ref light ( UnsignedInt ) up to @ ref lightCount ( )
- @ ref MaterialData using @ ref material ( UnsignedInt ) up to
@ ref materialCount ( ) . A material can then reference textures via their IDs .
- @ ref MeshData using @ ref mesh ( UnsignedInt , UnsignedInt ) up to
@ ref meshCount ( ) . Similarly as with images , each mesh can also have
multiple levels ( LODs or for example separate edge / face data ) , which are
requested through the second parameter up to @ ref meshLevelCount ( ) .
- @ ref ObjectData2D / @ ref ObjectData3D using
@ ref object2D ( UnsignedInt ) / @ ref object3D ( UnsignedInt ) up to
@ ref object2DCount ( ) / @ ref object3DCount ( ) . An object can then reference
its child objects , mesh and a material , camera , light or a skin associated
with it via their IDs .
- @ ref SceneData using @ ref scene ( UnsignedInt ) up to @ ref sceneCount ( ) , with
the default scene index exposed through @ ref defaultScene ( ) . A scene then
references its child 2 D / 3 D objects via their IDs .
- @ ref SkinData2D / @ ref SkinData3D using @ ref skin2D ( UnsignedInt ) /
@ ref skin3D ( UnsignedInt ) up to @ ref skin2DCount ( ) / @ ref skin3DCount ( )
- @ ref TextureData using @ ref texture ( UnsignedInt ) up to @ ref textureCount ( ) .
Each texture then references the 1 D / 2 D / 3 D image it uses via its ID .
Except for pure image formats that always have at least one image , in general
there ' s no guarantee that an imported file has always a mesh , a scene or a
camera . So unless the particular importer documentation says otherwise , you ' re
expected to always check the count before attempting an import .
@ section Trade - AbstractImporter - usage Usage
@ section Trade - AbstractImporter - usage Usage
Importers are most commonly implemented as plugins . For example , loading an
Importers are commonly implemented as plugins , which means the concrete
image from the filesystem using the @ ref AnyImageImporter plugin can be done
importer implementation is loaded and instantiated through a @ relativeref { Corrade , PluginManager : : Manager } . A file is opened using either
like this , completely with all error handling :
@ ref openFile ( ) , @ ref openData ( ) or , in rare cases , @ ref openState ( ) amd it
stays open until the importer is destroyed , @ ref close ( ) is called or another
file is opened .
With a file open you can then query the importer for particular data . Where
possible , the import is performed lazily only when you actually request that
particular data , and thus it can be assumed that opening a file is relatively
cheap .
Since the importers deal with untrusted external data , it ' s needed to perform
explicit error handling on the application side . There are two cases where it
can fail - - - during opening , in which case the function returns @ cpp false @ ce ,
and during the actual data import , in which case you get an empty @ relativeref { Corrade , Containers : : Optional } . In both cases the actual failure
reason is printed to the error output . Everything else ( IDs out of bounds ,
calling functions without a file open , accessing an empty optional , . . . ) is
treated as a programmer error and will produce the usual assertions .
In the following example an image is loaded from the filesystem using the
@ ref AnyImageImporter plugin , completely with all needed error handling :
@ snippet MagnumTrade . cpp AbstractImporter - usage
@ snippet MagnumTrade . cpp AbstractImporter - usage
See @ ref plugins for more information about general plugin usage and
See @ ref plugins for more information about general plugin usage ,
` * Importer ` classes in the @ ref Trade namespace for available importer plugins .
@ ref file - formats to compare implementations of common file formats and the
list of @ m_class { m - doc } [ derived classes ] ( # derived - classes ) for all available
importer plugins .
@ m_class { m - note m - success }
@ m_class { m - note m - success }
@ -170,6 +233,46 @@ See @ref plugins for more information about general plugin usage and
@ ref magnum - sceneconverter " magnum-sceneconverter " tools which you can use
@ ref magnum - sceneconverter " magnum-sceneconverter " tools which you can use
to perform introspection of image and scene files .
to perform introspection of image and scene files .
@ subsection Trade - AbstractImporter - usage - name - mapping Mapping between IDs and string names
Certain file formats have the ability to assign string names to objects ,
materials and other parts of the scene . These are not imported as part of the
various @ ref Trade : : MeshData etc . structures , instead the importer itself
allows you to map IDs to names and vice versa . As a convenience feature , it ' s
also possible to import data directly using their name instead of having to map
the name to an IDs first . In that case the function will return an empty
@ relativeref { Corrade , Containers : : Optional } both if the import failed or if the
name doesn ' t exist .
- Animation names can be retrieved using @ ref animationName ( ) and mapped to
an ID using @ ref animationForName ( ) , imported with @ ref animation ( const std : : string & )
- Camera names using @ ref cameraName ( ) & @ ref cameraForName ( ) , imported with
@ ref camera ( const std : : string & )
- Image names using @ ref image1DName ( ) / @ ref image2DName ( ) /
@ ref image3DName ( ) & @ ref image1DForName ( ) / @ ref image2DForName ( ) /
@ ref image3DForName ( ) , imported with
@ ref image1D ( const std : : string & , UnsignedInt ) /
@ ref image2D ( const std : : string & , UnsignedInt ) /
@ ref image3D ( const std : : string & , UnsignedInt )
- Light names using @ ref lightName ( ) & @ ref lightForName ( ) , imported with
@ ref light ( const std : : string & )
- Material names using @ ref materialName ( ) & @ ref materialForName ( ) , imported
with @ ref material ( const std : : string & )
- Mesh names using @ ref meshName ( ) & @ ref meshForName ( ) , imported with
@ ref mesh ( const std : : string & , UnsignedInt ) . Meshes themselves can have
custom attributes , for which the name mapping can be retrieved using
@ ref meshAttributeName ( ) and @ ref meshAttributeForName ( ) .
- Objects names using @ ref object2DName ( ) / @ ref object3DName ( ) &
@ ref object2DForName ( ) / @ ref object3DForName ( ) , imported with
@ ref object2D ( const std : : string & ) / @ ref object3D ( const std : : string & )
- Scene names using @ ref sceneName ( ) & @ ref sceneForName ( ) , imported with
@ ref scene ( const std : : string & )
- Skin names using @ ref skin2DName ( ) / @ ref skin3DName ( ) &
@ ref skin2DForName ( ) / @ ref skin3DForName ( ) , imported with
@ ref skin2D ( const std : : string & ) / @ ref skin3D ( const std : : string & )
- Texture names using @ ref textureName ( ) & @ ref textureForName ( ) , imported
with @ ref texture ( const std : : string & )
@ subsection Trade - AbstractImporter - usage - callbacks Loading data from memory , using file callbacks
@ subsection Trade - AbstractImporter - usage - callbacks Loading data from memory , using file callbacks
Besides loading data directly from the filesystem using @ ref openFile ( ) like
Besides loading data directly from the filesystem using @ ref openFile ( ) like
@ -239,17 +342,17 @@ details about concrete types returned and accepted by these functions.
@ subsection Trade - AbstractImporter - usage - casting Polymorphic imported data types
@ subsection Trade - AbstractImporter - usage - casting Polymorphic imported data types
Some data access functions return @ ref Corrade : : Containers : : Pointer instead of
Some data access functions return @ relativeref { Corrade , Containers : : Pointer }
@ ref Corrade : : Containers : : Optional because the result might be a particular
instead of @ relativeref { Corrade , Containers : : Optional } because the result might
subclass of given type . Those functions are @ ref material ( ) , @ ref object2D ( )
be a particular subclass of given type . Those functions are @ ref object2D ( )
and @ ref object3D ( ) . You can cast the abstract base to a concrete type
and @ ref object3D ( ) . You can cast the abstract base to a concrete type
depending on its reported type , for example :
depending on its reported type , for example :
@ snippet MagnumTrade . cpp AbstractImporter - usage - cast
@ snippet MagnumTrade . cpp AbstractImporter - usage - cast
Another option is making use of the @ ref Containers : : pointerCast ( ) utility , but
Another option is making use of the @ ref Containers : : pointerCast ( ) utility , but
note that in that case the original @ ref Corrade : : Containers : : Pointer will be
note that in that case the original @ relativeref { Corrade , Containers : : Pointer }
* * moved into * a new instance and that might not be desirable .
will have to be * moved into * a new instance , which might not be desirable .
@ section Trade - AbstractImporter - data - dependency Data dependency
@ section Trade - AbstractImporter - data - dependency Data dependency
@ -257,12 +360,12 @@ The `*Data` instances returned from various functions *by design* have no
dependency on the importer instance and neither on the dynamic plugin module .
dependency on the importer instance and neither on the dynamic plugin module .
In other words , you don ' t need to keep the importer instance ( or the plugin
In other words , you don ' t need to keep the importer instance ( or the plugin
manager instance ) around in order to have the ` * Data ` instances valid .
manager instance ) around in order to have the ` * Data ` instances valid .
Moreover , all @ ref Corrade : : Containers : : Array instances returned through
Moreover , all @ relativeref { Corrade , Containers : : Array } instances returned
@ ref ImageData , @ ref AnimationData , @ ref MaterialData , @ ref MeshData and
through @ ref ImageData , @ ref AnimationData , @ ref MaterialData , @ ref MeshData
@ ref SkinData are only allowed to have default deleters ( or be non - owning
and @ ref SkinData are only allowed to have default deleters ( or be non - owning
instances created from @ ref Corrade : : Containers : : ArrayView ) - - - this is to
instances created from @ relativeref { Corrade , Containers : : ArrayView } ) - - - this is
avoid potential dangling function pointer calls when destructing such instances
to avoid potential dangling function pointer calls when destructing such
after the plugin module has been unloaded .
instances after the plugin module has been unloaded .
The only exception are various ` importerState ( ) ` functions
The only exception are various ` importerState ( ) ` functions
@ ref Trade - AbstractImporter - usage - state " described above " , but in that case the
@ ref Trade - AbstractImporter - usage - state " described above " , but in that case the
@ -317,7 +420,7 @@ checked by the implementation:
@ par Dangling function pointers on plugin unload
@ par Dangling function pointers on plugin unload
As @ ref Trade - AbstractImporter - data - dependency " mentioned above " ,
As @ ref Trade - AbstractImporter - data - dependency " mentioned above " ,
@ ref Corrade : : Containers : : Array instances returned from plugin
@ relativeref { Corrade , Containers : : Array } instances returned from plugin
implementations are not allowed to use anything else than the default
implementations are not allowed to use anything else than the default
deleter or the deleter used by @ ref Trade : : ArrayAllocator , otherwise this
deleter or the deleter used by @ ref Trade : : ArrayAllocator , otherwise this
could cause dangling function pointer call on array destruction if the
could cause dangling function pointer call on array destruction if the
@ -602,7 +705,8 @@ class MAGNUM_TRADE_EXPORT AbstractImporter: public PluginManager::AbstractManagi
* @ brief Scene name
* @ brief Scene name
* @ param id Scene ID , from range [ 0 , @ ref sceneCount ( ) ) .
* @ param id Scene ID , from range [ 0 , @ ref sceneCount ( ) ) .
*
*
* Expects that a file is opened .
* Expects that a file is opened . If the scene has no name or the
* importer doesn ' t support scene names , returns an empty string .
* @ see @ ref sceneForName ( )
* @ see @ ref sceneForName ( )
*/
*/
std : : string sceneName ( UnsignedInt id ) ;
std : : string sceneName ( UnsignedInt id ) ;
@ -649,7 +753,8 @@ class MAGNUM_TRADE_EXPORT AbstractImporter: public PluginManager::AbstractManagi
* @ brief Animation name
* @ brief Animation name
* @ param id Animation ID , from range [ 0 , @ ref animationCount ( ) ) .
* @ param id Animation ID , from range [ 0 , @ ref animationCount ( ) ) .
*
*
* Expects that a file is opened .
* Expects that a file is opened . If the animation has no name or the
* importer doesn ' t support animation names , returns an empty string .
* @ see @ ref animationForName ( )
* @ see @ ref animationForName ( )
*/
*/
std : : string animationName ( UnsignedInt id ) ;
std : : string animationName ( UnsignedInt id ) ;
@ -696,7 +801,8 @@ class MAGNUM_TRADE_EXPORT AbstractImporter: public PluginManager::AbstractManagi
* @ brief Light name
* @ brief Light name
* @ param id Light ID , from range [ 0 , @ ref lightCount ( ) ) .
* @ param id Light ID , from range [ 0 , @ ref lightCount ( ) ) .
*
*
* Expects that a file is opened .
* Expects that a file is opened . If the light has no name or the
* importer doesn ' t support light names , returns an empty string .
* @ see @ ref lightForName ( )
* @ see @ ref lightForName ( )
*/
*/
std : : string lightName ( UnsignedInt id ) ;
std : : string lightName ( UnsignedInt id ) ;
@ -743,7 +849,8 @@ class MAGNUM_TRADE_EXPORT AbstractImporter: public PluginManager::AbstractManagi
* @ brief Camera name
* @ brief Camera name
* @ param id Camera ID , from range [ 0 , @ ref cameraCount ( ) ) .
* @ param id Camera ID , from range [ 0 , @ ref cameraCount ( ) ) .
*
*
* Expects that a file is opened .
* Expects that a file is opened . If the camera has no name or the
* importer doesn ' t support camera names , returns an empty string .
* @ see @ ref cameraForName ( )
* @ see @ ref cameraForName ( )
*/
*/
std : : string cameraName ( UnsignedInt id ) ;
std : : string cameraName ( UnsignedInt id ) ;
@ -790,7 +897,8 @@ class MAGNUM_TRADE_EXPORT AbstractImporter: public PluginManager::AbstractManagi
* @ brief Two - dimensional object name
* @ brief Two - dimensional object name
* @ param id Object ID , from range [ 0 , @ ref object2DCount ( ) ) .
* @ param id Object ID , from range [ 0 , @ ref object2DCount ( ) ) .
*
*
* Expects that a file is opened .
* Expects that a file is opened . If the object has no name or the
* importer doesn ' t support object names , returns an empty string .
* @ see @ ref object2DForName ( )
* @ see @ ref object2DForName ( )
*/
*/
std : : string object2DName ( UnsignedInt id ) ;
std : : string object2DName ( UnsignedInt id ) ;
@ -837,7 +945,8 @@ class MAGNUM_TRADE_EXPORT AbstractImporter: public PluginManager::AbstractManagi
* @ brief Three - dimensional object name
* @ brief Three - dimensional object name
* @ param id Object ID , from range [ 0 , @ ref object3DCount ( ) ) .
* @ param id Object ID , from range [ 0 , @ ref object3DCount ( ) ) .
*
*
* Expects that a file is opened .
* Expects that a file is opened . If the object has no name or the
* importer doesn ' t support object names , returns an empty string .
* @ see @ ref object3DForName ( )
* @ see @ ref object3DForName ( )
*/
*/
std : : string object3DName ( UnsignedInt id ) ;
std : : string object3DName ( UnsignedInt id ) ;
@ -887,7 +996,8 @@ class MAGNUM_TRADE_EXPORT AbstractImporter: public PluginManager::AbstractManagi
* @ param id Skin ID , from range [ 0 , @ ref skin2DCount ( ) ) .
* @ param id Skin ID , from range [ 0 , @ ref skin2DCount ( ) ) .
* @ m_since_latest
* @ m_since_latest
*
*
* Expects that a file is opened .
* Expects that a file is opened . If the skin has no name or the
* importer doesn ' t support skin names , returns an empty string .
* @ see @ ref skin2DForName ( )
* @ see @ ref skin2DForName ( )
*/
*/
std : : string skin2DName ( UnsignedInt id ) ;
std : : string skin2DName ( UnsignedInt id ) ;
@ -938,7 +1048,8 @@ class MAGNUM_TRADE_EXPORT AbstractImporter: public PluginManager::AbstractManagi
* @ param id Skin ID , from range [ 0 , @ ref skin3DCount ( ) ) .
* @ param id Skin ID , from range [ 0 , @ ref skin3DCount ( ) ) .
* @ m_since_latest
* @ m_since_latest
*
*
* Expects that a file is opened .
* Expects that a file is opened . If the skin has no name or the
* importer doesn ' t support skin names , returns an empty string .
* @ see @ ref skin3DForName ( )
* @ see @ ref skin3DForName ( )
*/
*/
std : : string skin3DName ( UnsignedInt id ) ;
std : : string skin3DName ( UnsignedInt id ) ;
@ -1000,7 +1111,8 @@ class MAGNUM_TRADE_EXPORT AbstractImporter: public PluginManager::AbstractManagi
* @ param id Mesh ID , from range [ 0 , @ ref meshCount ( ) ) .
* @ param id Mesh ID , from range [ 0 , @ ref meshCount ( ) ) .
* @ m_since { 2020 , 06 }
* @ m_since { 2020 , 06 }
*
*
* Expects that a file is opened .
* Expects that a file is opened . If the mesh has no name or the
* importer doesn ' t support mesh names , returns an empty string .
* @ see @ ref meshForName ( )
* @ see @ ref meshForName ( )
*/
*/
std : : string meshName ( UnsignedInt id ) ;
std : : string meshName ( UnsignedInt id ) ;
@ -1164,7 +1276,8 @@ class MAGNUM_TRADE_EXPORT AbstractImporter: public PluginManager::AbstractManagi
* @ brief Material name
* @ brief Material name
* @ param id Material ID , from range [ 0 , @ ref materialCount ( ) ) .
* @ param id Material ID , from range [ 0 , @ ref materialCount ( ) ) .
*
*
* Expects that a file is opened .
* Expects that a file is opened . If the material has no name or the
* importer doesn ' t support material names , returns an empty string .
* @ see @ ref materialForName ( ) , @ ref material ( const std : : string & )
* @ see @ ref materialForName ( ) , @ ref material ( const std : : string & )
*/
*/
std : : string materialName ( UnsignedInt id ) ;
std : : string materialName ( UnsignedInt id ) ;
@ -1221,7 +1334,8 @@ class MAGNUM_TRADE_EXPORT AbstractImporter: public PluginManager::AbstractManagi
* @ brief Texture name
* @ brief Texture name
* @ param id Texture ID , from range [ 0 , @ ref textureCount ( ) ) .
* @ param id Texture ID , from range [ 0 , @ ref textureCount ( ) ) .
*
*
* Expects that a file is opened .
* Expects that a file is opened . If the texture has no name or the
* importer doesn ' t support texture names , returns an empty string .
* @ see @ ref textureForName ( )
* @ see @ ref textureForName ( )
*/
*/
std : : string textureName ( UnsignedInt id ) ;
std : : string textureName ( UnsignedInt id ) ;
@ -1279,7 +1393,8 @@ class MAGNUM_TRADE_EXPORT AbstractImporter: public PluginManager::AbstractManagi
* @ brief One - dimensional image name
* @ brief One - dimensional image name
* @ param id Image ID , from range [ 0 , @ ref image1DCount ( ) ) .
* @ param id Image ID , from range [ 0 , @ ref image1DCount ( ) ) .
*
*
* Expects that a file is opened .
* Expects that a file is opened . If the image has no name or the
* importer doesn ' t support image names , returns an empty string .
* @ see @ ref image1DForName ( )
* @ see @ ref image1DForName ( )
*/
*/
std : : string image1DName ( UnsignedInt id ) ;
std : : string image1DName ( UnsignedInt id ) ;
@ -1339,7 +1454,8 @@ class MAGNUM_TRADE_EXPORT AbstractImporter: public PluginManager::AbstractManagi
* @ brief Two - dimensional image name
* @ brief Two - dimensional image name
* @ param id Image ID , from range [ 0 , @ ref image2DCount ( ) ) .
* @ param id Image ID , from range [ 0 , @ ref image2DCount ( ) ) .
*
*
* Expects that a file is opened .
* Expects that a file is opened . If the image has no name or the
* importer doesn ' t support image names , returns an empty string .
* @ see @ ref image2DForName ( )
* @ see @ ref image2DForName ( )
*/
*/
std : : string image2DName ( UnsignedInt id ) ;
std : : string image2DName ( UnsignedInt id ) ;
@ -1399,7 +1515,8 @@ class MAGNUM_TRADE_EXPORT AbstractImporter: public PluginManager::AbstractManagi
* @ brief Three - dimensional image name
* @ brief Three - dimensional image name
* @ param id Image ID , from range [ 0 , @ ref image3DCount ( ) ) .
* @ param id Image ID , from range [ 0 , @ ref image3DCount ( ) ) .
*
*
* Expects that a file is opened .
* Expects that a file is opened . If the image has no name or the
* importer doesn ' t support image names , returns an empty string .
* @ see @ ref image3DForName ( )
* @ see @ ref image3DForName ( )
*/
*/
std : : string image3DName ( UnsignedInt id ) ;
std : : string image3DName ( UnsignedInt id ) ;