2008-05-22 04:51:37 -07:00
// Copyright (C) 2002-2008 Nikolaus Gebhardt
2007-05-20 11:03:49 -07:00
// This file is part of the "Irrlicht Engine".
// For conditions of distribution and use, see copyright notice in irrlicht.h
2008-01-23 09:15:15 -08:00
# include "IrrCompileConfig.h"
2007-09-04 11:51:42 -07:00
# ifdef _IRR_COMPILE_WITH_COLLADA_LOADER_
2007-05-20 11:03:49 -07:00
# include "CColladaFileLoader.h"
# include "os.h"
# include "IXMLReader.h"
# include "IDummyTransformationSceneNode.h"
# include "SAnimatedMesh.h"
# include "fast_atof.h"
# include "quaternion.h"
# include "ILightSceneNode.h"
# include "ICameraSceneNode.h"
# include "IMeshManipulator.h"
# include "IReadFile.h"
# include "IAttributes.h"
# include "IMeshCache.h"
# include "IMeshSceneNode.h"
# include "SMeshBufferLightMap.h"
2008-01-20 16:35:47 -08:00
# include "irrMap.h"
2007-05-20 11:03:49 -07:00
2008-11-16 16:39:33 -08:00
# ifdef _DEBUG
# define COLLADA_READER_DEBUG
# endif
2007-05-20 11:03:49 -07:00
namespace irr
{
namespace scene
{
// currently supported COLLADA tag names
const core : : stringc colladaSectionName = " COLLADA " ;
const core : : stringc librarySectionName = " library " ;
2008-01-23 09:15:15 -08:00
const core : : stringc libraryNodesSectionName = " library_nodes " ;
2008-01-20 16:35:47 -08:00
const core : : stringc libraryGeometriesSectionName = " library_geometries " ;
const core : : stringc libraryMaterialsSectionName = " library_materials " ;
const core : : stringc libraryImagesSectionName = " library_images " ;
const core : : stringc libraryVisualScenesSectionName = " library_visual_scenes " ;
2008-01-23 09:15:15 -08:00
const core : : stringc libraryCamerasSectionName = " library_cameras " ;
const core : : stringc libraryLightsSectionName = " library_lights " ;
const core : : stringc libraryEffectsSectionName = " library_effects " ;
2007-05-20 11:03:49 -07:00
const core : : stringc assetSectionName = " asset " ;
const core : : stringc sceneSectionName = " scene " ;
2008-01-20 16:35:47 -08:00
const core : : stringc visualSceneSectionName = " visual_scene " ;
2007-05-20 11:03:49 -07:00
const core : : stringc lightPrefabName = " light " ;
const core : : stringc cameraPrefabName = " camera " ;
const core : : stringc materialSectionName = " material " ;
const core : : stringc geometrySectionName = " geometry " ;
2007-08-08 09:30:10 -07:00
const core : : stringc imageSectionName = " image " ;
const core : : stringc textureSectionName = " texture " ;
2008-01-23 09:15:15 -08:00
const core : : stringc effectSectionName = " effect " ;
2007-05-20 11:03:49 -07:00
2008-11-13 09:35:17 -08:00
const core : : stringc pointSectionName = " point " ;
const core : : stringc directionalSectionName = " directional " ;
const core : : stringc spotSectionName = " spot " ;
const core : : stringc ambientSectionName = " ambient " ;
2007-05-20 11:03:49 -07:00
const core : : stringc meshSectionName = " mesh " ;
2008-01-20 16:35:47 -08:00
const core : : stringc sourceSectionName = " source " ;
2007-05-20 11:03:49 -07:00
const core : : stringc arraySectionName = " array " ;
2008-01-20 16:35:47 -08:00
const core : : stringc floatArraySectionName = " float_array " ;
const core : : stringc intArraySectionName = " int_array " ;
2008-01-24 09:24:52 -08:00
const core : : stringc techniqueCommonSectionName = " technique_common " ;
2007-05-20 11:03:49 -07:00
const core : : stringc accessorSectionName = " accessor " ;
const core : : stringc verticesSectionName = " vertices " ;
const core : : stringc inputTagName = " input " ;
2008-01-20 16:35:47 -08:00
const core : : stringc polylistSectionName = " polylist " ;
const core : : stringc trianglesSectionName = " triangles " ;
2007-05-20 11:03:49 -07:00
const core : : stringc polygonsSectionName = " polygons " ;
2008-01-20 16:24:28 -08:00
const core : : stringc primitivesName = " p " ;
2008-01-20 16:35:47 -08:00
const core : : stringc vcountName = " vcount " ;
2008-11-13 09:35:17 -08:00
const core : : stringc upAxisNodeName = " up_axis " ;
2007-05-20 11:03:49 -07:00
const core : : stringc nodeSectionName = " node " ;
const core : : stringc lookatNodeName = " lookat " ;
const core : : stringc matrixNodeName = " matrix " ;
const core : : stringc perspectiveNodeName = " perspective " ;
const core : : stringc rotateNodeName = " rotate " ;
const core : : stringc scaleNodeName = " scale " ;
const core : : stringc translateNodeName = " translate " ;
const core : : stringc skewNodeName = " skew " ;
2008-01-13 16:23:02 -08:00
const core : : stringc bboxNodeName = " boundingbox " ;
const core : : stringc minNodeName = " min " ;
const core : : stringc maxNodeName = " max " ;
2008-01-23 09:15:15 -08:00
const core : : stringc instanceName = " instance " ;
2008-01-20 16:35:47 -08:00
const core : : stringc instanceGeometryName = " instance_geometry " ;
const core : : stringc instanceSceneName = " instance_visual_scene " ;
2008-01-23 09:15:15 -08:00
const core : : stringc instanceEffectName = " instance_effect " ;
const core : : stringc instanceMaterialName = " instance_material " ;
const core : : stringc instanceLightName = " instance_light " ;
const core : : stringc instanceNodeName = " instance_node " ;
2008-01-20 16:35:47 -08:00
const core : : stringc bindMaterialName = " bind_material " ;
2008-01-20 16:24:28 -08:00
const core : : stringc extraNodeName = " extra " ;
2008-01-23 09:15:15 -08:00
const core : : stringc techniqueNodeName = " technique " ;
const core : : stringc colorNodeName = " color " ;
const core : : stringc floatNodeName = " float " ;
2008-01-24 09:24:52 -08:00
const core : : stringc float2NodeName = " float2 " ;
const core : : stringc float3NodeName = " float3 " ;
2007-05-20 11:03:49 -07:00
2008-01-24 09:24:52 -08:00
const core : : stringc newParamName = " newparam " ;
2007-05-20 11:03:49 -07:00
const core : : stringc paramTagName = " param " ;
2008-01-20 16:35:47 -08:00
const core : : stringc initFromName = " init_from " ;
2008-01-24 09:24:52 -08:00
const core : : stringc dataName = " data " ;
2008-11-13 09:35:17 -08:00
const core : : stringc wrapsName = " wrap_s " ;
const core : : stringc wraptName = " wrap_t " ;
const core : : stringc minfilterName = " minfilter " ;
const core : : stringc magfilterName = " magfilter " ;
const core : : stringc mipfilterName = " mipfilter " ;
2007-05-20 11:03:49 -07:00
2008-01-23 16:38:59 -08:00
const core : : stringc textureNodeName = " texture " ;
2008-11-13 09:35:17 -08:00
const core : : stringc doubleSidedNodeName = " double_sided " ;
const core : : stringc constantAttenuationNodeName = " constant_attenuation " ;
const core : : stringc linearAttenuationNodeName = " linear_attenuation " ;
const core : : stringc quadraticAttenuationNodeName = " quadratic_attenuation " ;
const core : : stringc falloffAngleNodeName = " falloff_angle " ;
const core : : stringc falloffExponentNodeName = " falloff_exponent " ;
2008-01-23 09:15:15 -08:00
const core : : stringc profileCOMMONSectionName = " profile_COMMON " ;
2007-05-20 11:03:49 -07:00
const char * const inputSemanticNames [ ] = { " POSITION " , " VERTEX " , " NORMAL " , " TEXCOORD " ,
2007-08-08 09:30:10 -07:00
" UV " , " TANGENT " , " IMAGE " , " TEXTURE " , 0 } ;
2007-05-20 11:03:49 -07:00
2008-01-20 16:35:47 -08:00
//! following class is for holding and creating instances of library
//! objects, named prefabs in this loader.
2007-05-20 11:03:49 -07:00
class CPrefab : public IColladaPrefab
{
public :
2008-01-24 09:24:52 -08:00
CPrefab ( const core : : stringc & id ) : Id ( id )
2007-05-20 11:03:49 -07:00
{
}
//! creates an instance of this prefab
virtual scene : : ISceneNode * addInstance ( scene : : ISceneNode * parent ,
scene : : ISceneManager * mgr )
{
// empty implementation
return 0 ;
}
//! returns id of this prefab
2008-01-24 09:24:52 -08:00
virtual const core : : stringc & getId ( )
2007-05-20 11:03:49 -07:00
{
2008-01-24 09:24:52 -08:00
return Id ;
2007-05-20 11:03:49 -07:00
}
protected :
core : : stringc Id ;
} ;
//! prefab for a light scene node
class CLightPrefab : public CPrefab
{
public :
2008-01-24 09:24:52 -08:00
CLightPrefab ( const core : : stringc & id ) : CPrefab ( id )
2007-05-20 11:03:49 -07:00
{
# ifdef COLLADA_READER_DEBUG
2008-11-13 09:35:17 -08:00
os : : Printer : : log ( " COLLADA: loaded light prefab " , Id . c_str ( ) ) ;
2007-05-20 11:03:49 -07:00
# endif
}
video : : SLight LightData ; // publically accessible
//! creates an instance of this prefab
virtual scene : : ISceneNode * addInstance ( scene : : ISceneNode * parent ,
scene : : ISceneManager * mgr )
{
# ifdef COLLADA_READER_DEBUG
2008-11-13 09:35:17 -08:00
os : : Printer : : log ( " COLLADA: Constructing light instance " , Id . c_str ( ) ) ;
2007-05-20 11:03:49 -07:00
# endif
scene : : ILightSceneNode * l = mgr - > addLightSceneNode ( parent ) ;
2008-11-13 09:35:17 -08:00
if ( l )
{
l - > setLightData ( LightData ) ;
l - > setName ( getId ( ) ) ;
}
2007-05-20 11:03:49 -07:00
return l ;
}
} ;
//! prefab for a mesh scene node
class CGeometryPrefab : public CPrefab
{
public :
2008-01-24 09:24:52 -08:00
CGeometryPrefab ( const core : : stringc & id ) : CPrefab ( id )
2007-05-20 11:03:49 -07:00
{
}
2008-01-23 09:15:15 -08:00
scene : : IMesh * Mesh ;
2007-05-20 11:03:49 -07:00
//! creates an instance of this prefab
virtual scene : : ISceneNode * addInstance ( scene : : ISceneNode * parent ,
scene : : ISceneManager * mgr )
{
# ifdef COLLADA_READER_DEBUG
2008-11-13 09:35:17 -08:00
os : : Printer : : log ( " COLLADA: Constructing mesh instance " , Id . c_str ( ) ) ;
2007-05-20 11:03:49 -07:00
# endif
scene : : ISceneNode * m = mgr - > addMeshSceneNode ( Mesh , parent ) ;
2008-11-13 09:35:17 -08:00
if ( m )
{
m - > setName ( getId ( ) ) ;
// m->setDebugDataVisible(scene::EDS_FULL);
}
2007-05-20 11:03:49 -07:00
return m ;
}
} ;
//! prefab for a camera scene node
class CCameraPrefab : public CPrefab
{
public :
2008-01-24 09:24:52 -08:00
CCameraPrefab ( const core : : stringc & id )
2007-05-20 11:03:49 -07:00
: CPrefab ( id ) , YFov ( core : : PI / 2.5f ) , ZNear ( 1.0f ) , ZFar ( 3000.0f )
{
# ifdef COLLADA_READER_DEBUG
2008-11-13 09:35:17 -08:00
os : : Printer : : log ( " COLLADA: loaded camera prefab " , Id . c_str ( ) ) ;
2007-05-20 11:03:49 -07:00
# endif
}
2008-01-20 16:35:47 -08:00
// publicly accessible data
2007-05-20 11:03:49 -07:00
f32 YFov ;
f32 ZNear ;
f32 ZFar ;
//! creates an instance of this prefab
virtual scene : : ISceneNode * addInstance ( scene : : ISceneNode * parent ,
scene : : ISceneManager * mgr )
{
# ifdef COLLADA_READER_DEBUG
2008-11-13 09:35:17 -08:00
os : : Printer : : log ( " COLLADA: Constructing camera instance " , Id . c_str ( ) ) ;
2007-05-20 11:03:49 -07:00
# endif
scene : : ICameraSceneNode * c = mgr - > addCameraSceneNode ( parent ) ;
2008-11-13 09:35:17 -08:00
if ( c )
{
c - > setFOV ( YFov ) ;
c - > setNearValue ( ZNear ) ;
c - > setFarValue ( ZFar ) ;
c - > setName ( getId ( ) ) ;
}
2007-05-20 11:03:49 -07:00
return c ;
}
} ;
2008-01-20 16:35:47 -08:00
//! prefab for a container scene node
//! Collects other prefabs and instantiates them upon instantiation
//! Uses a dummy scene node to return the childs as one scene node
class CScenePrefab : public CPrefab
{
public :
2008-01-24 09:24:52 -08:00
CScenePrefab ( const core : : stringc & id ) : CPrefab ( id )
2008-01-20 16:35:47 -08:00
{
# ifdef COLLADA_READER_DEBUG
2008-11-13 09:35:17 -08:00
os : : Printer : : log ( " COLLADA: loaded scene prefab " , Id . c_str ( ) ) ;
2008-01-20 16:35:47 -08:00
# endif
}
//! creates an instance of this prefab
virtual scene : : ISceneNode * addInstance ( scene : : ISceneNode * parent ,
scene : : ISceneManager * mgr )
{
# ifdef COLLADA_READER_DEBUG
2008-11-13 09:35:17 -08:00
os : : Printer : : log ( " COLLADA: Constructing scene instance " , Id . c_str ( ) ) ;
2008-01-20 16:35:47 -08:00
# endif
if ( Childs . size ( ) = = 0 )
return 0 ;
2008-11-13 09:35:17 -08:00
scene : : IDummyTransformationSceneNode * s = mgr - > addDummyTransformationSceneNode ( parent ) ;
if ( s )
2008-01-23 09:15:15 -08:00
{
2008-11-13 09:35:17 -08:00
s - > setName ( getId ( ) ) ;
s - > getRelativeTransformationMatrix ( ) = Transformation ;
core : : stringc t ;
for ( u32 i = 0 ; i < 16 ; + + i )
{
t + = core : : stringc ( Transformation [ i ] ) ;
t + = " " ;
}
os : : Printer : : log ( " COLLADA: Transformation " , t . c_str ( ) ) ;
2008-01-23 09:15:15 -08:00
for ( u32 i = 0 ; i < Childs . size ( ) ; + + i )
2008-11-13 09:35:17 -08:00
Childs [ i ] - > addInstance ( s , mgr ) ;
2008-01-23 09:15:15 -08:00
}
2008-01-20 16:35:47 -08:00
2008-11-13 09:35:17 -08:00
return s ;
2008-01-20 16:35:47 -08:00
}
core : : array < IColladaPrefab * > Childs ;
2008-01-23 09:15:15 -08:00
core : : matrix4 Transformation ;
2008-01-20 16:35:47 -08:00
} ;
2008-01-23 09:15:15 -08:00
2007-05-20 11:03:49 -07:00
//! Constructor
2008-01-29 08:59:36 -08:00
CColladaFileLoader : : CColladaFileLoader ( scene : : ISceneManager * smgr ,
io : : IFileSystem * fs )
: SceneManager ( smgr ) , FileSystem ( fs ) , DummyMesh ( 0 ) ,
2007-05-20 11:03:49 -07:00
FirstLoadedMesh ( 0 ) , LoadedMeshCount ( 0 ) , CreateInstances ( false )
{
2008-04-29 13:54:12 -07:00
# ifdef _DEBUG
setDebugName ( " CColladaFileLoader " ) ;
# endif
2007-05-20 11:03:49 -07:00
}
//! destructor
CColladaFileLoader : : ~ CColladaFileLoader ( )
{
if ( DummyMesh )
DummyMesh - > drop ( ) ;
if ( FirstLoadedMesh )
FirstLoadedMesh - > drop ( ) ;
}
//! Returns true if the file maybe is able to be loaded by this class.
/** This decision should be based only on the file extension (e.g. ".cob") */
2007-09-16 16:41:55 -07:00
bool CColladaFileLoader : : isALoadableFileExtension ( const c8 * fileName ) const
2007-05-20 11:03:49 -07:00
{
2008-01-20 16:35:47 -08:00
return strstr ( fileName , " .xml " ) | | strstr ( fileName , " .dae " ) ;
2007-05-20 11:03:49 -07:00
}
//! creates/loads an animated mesh from the file.
//! \return Pointer to the created mesh. Returns 0 if loading failed.
//! If you no longer need the mesh, you should call IAnimatedMesh::drop().
2007-09-06 23:11:47 -07:00
//! See IReferenceCounted::drop() for more information.
2007-09-19 07:08:28 -07:00
IAnimatedMesh * CColladaFileLoader : : createMesh ( io : : IReadFile * file )
2007-05-20 11:03:49 -07:00
{
io : : IXMLReaderUTF8 * reader = FileSystem - > createXMLReaderUTF8 ( file ) ;
if ( ! reader )
return 0 ;
CurrentlyLoadingMesh = file - > getFileName ( ) ;
CreateInstances = SceneManager - > getParameters ( ) - > getAttributeAsBool (
scene : : COLLADA_CREATE_SCENE_INSTANCES ) ;
2008-11-13 09:35:17 -08:00
Version = 0 ;
FlipAxis = false ;
2007-05-20 11:03:49 -07:00
// read until COLLADA section, skip other parts
while ( reader - > read ( ) )
{
if ( reader - > getNodeType ( ) = = io : : EXN_ELEMENT )
{
if ( colladaSectionName = = reader - > getNodeName ( ) )
readColladaSection ( reader ) ;
else
skipSection ( reader , true ) ; // unknown section
}
}
reader - > drop ( ) ;
2008-11-13 09:35:17 -08:00
if ( ! Version )
return 0 ;
2007-05-20 11:03:49 -07:00
// because this loader loads and creates a complete scene instead of
// a single mesh, return an empty dummy mesh to make the scene manager
// know that everything went well.
if ( ! DummyMesh )
DummyMesh = new SAnimatedMesh ( ) ;
2008-11-13 09:35:17 -08:00
scene : : IAnimatedMesh * returnMesh = DummyMesh ;
2007-05-20 11:03:49 -07:00
// add the first loaded mesh into the mesh cache too, if more than one
// meshes have been loaded from the file
if ( LoadedMeshCount > 1 & & FirstLoadedMesh )
{
os : : Printer : : log ( " Added COLLADA mesh " , FirstLoadedMeshName . c_str ( ) ) ;
SceneManager - > getMeshCache ( ) - > addMesh ( FirstLoadedMeshName . c_str ( ) , FirstLoadedMesh ) ;
}
// clean up temporary loaded data
clearData ( ) ;
returnMesh - > grab ( ) ; // store until this loader is destroyed
DummyMesh - > drop ( ) ;
DummyMesh = 0 ;
if ( FirstLoadedMesh )
FirstLoadedMesh - > drop ( ) ;
FirstLoadedMesh = 0 ;
LoadedMeshCount = 0 ;
return returnMesh ;
}
//! skips an (unknown) section in the collada document
void CColladaFileLoader : : skipSection ( io : : IXMLReaderUTF8 * reader , bool reportSkipping )
{
# ifndef COLLADA_READER_DEBUG
if ( reportSkipping ) // always report in COLLADA_READER_DEBUG mode
# endif
os : : Printer : : log ( " COLLADA skipping section " , core : : stringc ( reader - > getNodeName ( ) ) . c_str ( ) ) ;
// skip if this element is empty anyway.
if ( reader - > isEmptyElement ( ) )
return ;
// read until we've reached the last element in this section
2007-08-08 09:30:10 -07:00
u32 tagCounter = 1 ;
2007-05-20 11:03:49 -07:00
while ( tagCounter & & reader - > read ( ) )
{
if ( reader - > getNodeType ( ) = = io : : EXN_ELEMENT & &
! reader - > isEmptyElement ( ) )
{
# ifdef COLLADA_READER_DEBUG
if ( reportSkipping )
2008-01-20 16:35:47 -08:00
os : : Printer : : log ( " Skipping COLLADA unknown element: " , core : : stringc ( reader - > getNodeName ( ) ) . c_str ( ) ) ;
2007-05-20 11:03:49 -07:00
# endif // COLLADA_READER_DEBUG
+ + tagCounter ;
}
else
if ( reader - > getNodeType ( ) = = io : : EXN_ELEMENT_END )
- - tagCounter ;
}
}
//! reads the <COLLADA> section and its content
void CColladaFileLoader : : readColladaSection ( io : : IXMLReaderUTF8 * reader )
{
if ( reader - > isEmptyElement ( ) )
return ;
2008-01-20 16:35:47 -08:00
const f32 version = core : : fast_atof ( core : : stringc ( reader - > getAttributeValue ( " version " ) ) . c_str ( ) ) ;
Version = core : : floor32 ( version ) * 10000 + core : : ceil32 ( core : : fract ( version ) * 1000.0f ) ;
2008-01-26 16:35:01 -08:00
// Version 1.4 can be checked for by if (Version >= 10400)
2007-05-20 11:03:49 -07:00
while ( reader - > read ( ) )
if ( reader - > getNodeType ( ) = = io : : EXN_ELEMENT )
{
if ( assetSectionName = = reader - > getNodeName ( ) )
readAssetSection ( reader ) ;
else
2008-01-20 16:24:28 -08:00
if ( librarySectionName = = reader - > getNodeName ( ) )
readLibrarySection ( reader ) ;
else
2008-01-23 09:15:15 -08:00
if ( libraryNodesSectionName = = reader - > getNodeName ( ) )
readLibrarySection ( reader ) ;
else
2008-01-20 16:35:47 -08:00
if ( libraryGeometriesSectionName = = reader - > getNodeName ( ) )
readLibrarySection ( reader ) ;
else
if ( libraryMaterialsSectionName = = reader - > getNodeName ( ) )
readLibrarySection ( reader ) ;
else
2008-01-23 09:15:15 -08:00
if ( libraryEffectsSectionName = = reader - > getNodeName ( ) )
readLibrarySection ( reader ) ;
else
2008-01-20 16:35:47 -08:00
if ( libraryImagesSectionName = = reader - > getNodeName ( ) )
readLibrarySection ( reader ) ;
else
2008-01-23 09:15:15 -08:00
if ( libraryCamerasSectionName = = reader - > getNodeName ( ) )
readLibrarySection ( reader ) ;
else
if ( libraryLightsSectionName = = reader - > getNodeName ( ) )
readLibrarySection ( reader ) ;
else
2008-01-20 16:35:47 -08:00
if ( libraryVisualScenesSectionName = = reader - > getNodeName ( ) )
2008-01-23 09:15:15 -08:00
readVisualSceneLibrary ( reader ) ;
2008-01-20 16:35:47 -08:00
else
if ( assetSectionName = = reader - > getNodeName ( ) )
readAssetSection ( reader ) ;
else
2007-05-20 11:03:49 -07:00
if ( sceneSectionName = = reader - > getNodeName ( ) )
readSceneSection ( reader ) ;
else
2008-01-20 16:24:28 -08:00
{
os : : Printer : : log ( " COLLADA loader warning: Wrong tag usage found " , reader - > getNodeName ( ) , ELL_WARNING ) ;
2007-05-20 11:03:49 -07:00
skipSection ( reader , true ) ; // unknown section
2008-01-20 16:24:28 -08:00
}
2007-05-20 11:03:49 -07:00
}
}
//! reads a <library> section and its content
void CColladaFileLoader : : readLibrarySection ( io : : IXMLReaderUTF8 * reader )
{
2007-08-29 09:09:32 -07:00
# ifdef COLLADA_READER_DEBUG
os : : Printer : : log ( " COLLADA reading library " ) ;
# endif
2008-01-23 09:15:15 -08:00
if ( reader - > isEmptyElement ( ) )
return ;
2007-05-20 11:03:49 -07:00
while ( reader - > read ( ) )
{
2008-01-23 09:15:15 -08:00
if ( reader - > getNodeType ( ) = = io : : EXN_ELEMENT )
{
// animation section tbd
if ( cameraPrefabName = = reader - > getNodeName ( ) )
readCameraPrefab ( reader ) ;
else
// code section tbd
// controller section tbd
if ( geometrySectionName = = reader - > getNodeName ( ) )
readGeometry ( reader ) ;
else
if ( imageSectionName = = reader - > getNodeName ( ) )
readImage ( reader ) ;
else
if ( lightPrefabName = = reader - > getNodeName ( ) )
readLightPrefab ( reader ) ;
else
if ( materialSectionName = = reader - > getNodeName ( ) )
readMaterial ( reader ) ;
else
if ( nodeSectionName = = reader - > getNodeName ( ) )
{
CScenePrefab p ( " " ) ;
readNodeSection ( reader , SceneManager - > getRootSceneNode ( ) , & p ) ;
}
else
if ( effectSectionName = = reader - > getNodeName ( ) )
readEffect ( reader ) ;
else
// program section tbd
if ( textureSectionName = = reader - > getNodeName ( ) )
readTexture ( reader ) ;
else
skipSection ( reader , true ) ; // unknown section, not all allowed supported yet
}
2007-05-20 11:03:49 -07:00
else
2008-01-23 09:15:15 -08:00
if ( reader - > getNodeType ( ) = = io : : EXN_ELEMENT_END )
{
if ( librarySectionName = = reader - > getNodeName ( ) )
break ; // end reading.
if ( libraryNodesSectionName = = reader - > getNodeName ( ) )
break ; // end reading.
if ( libraryGeometriesSectionName = = reader - > getNodeName ( ) )
break ; // end reading.
if ( libraryMaterialsSectionName = = reader - > getNodeName ( ) )
break ; // end reading.
if ( libraryEffectsSectionName = = reader - > getNodeName ( ) )
break ; // end reading.
if ( libraryImagesSectionName = = reader - > getNodeName ( ) )
break ; // end reading.
if ( libraryLightsSectionName = = reader - > getNodeName ( ) )
break ; // end reading.
if ( libraryCamerasSectionName = = reader - > getNodeName ( ) )
break ; // end reading.
}
2008-01-20 16:35:47 -08:00
}
}
//! reads a <visual_scene> element and stores it as a prefab
2008-01-23 09:15:15 -08:00
void CColladaFileLoader : : readVisualSceneLibrary ( io : : IXMLReaderUTF8 * reader )
2008-01-20 16:35:47 -08:00
{
CScenePrefab * p = 0 ;
while ( reader - > read ( ) )
{
if ( reader - > getNodeType ( ) = = io : : EXN_ELEMENT )
{
if ( visualSceneSectionName = = reader - > getNodeName ( ) )
2008-01-24 09:24:52 -08:00
p = new CScenePrefab ( readId ( reader ) ) ;
2008-01-20 16:35:47 -08:00
else
2008-01-23 09:15:15 -08:00
if ( p & & nodeSectionName = = reader - > getNodeName ( ) ) // as a child of visual_scene
readNodeSection ( reader , SceneManager - > getRootSceneNode ( ) , p ) ;
2008-01-20 16:35:47 -08:00
else
if ( assetSectionName = = reader - > getNodeName ( ) )
readAssetSection ( reader ) ;
else
2008-01-23 09:15:15 -08:00
if ( extraNodeName = = reader - > getNodeName ( ) )
skipSection ( reader , false ) ; // ignore all other sections
else
{
os : : Printer : : log ( " COLLADA loader warning: Wrong tag usage found " , reader - > getNodeName ( ) , ELL_WARNING ) ;
2008-01-20 16:35:47 -08:00
skipSection ( reader , true ) ; // ignore all other sections
2008-01-23 09:15:15 -08:00
}
2008-01-20 16:35:47 -08:00
}
else
if ( reader - > getNodeType ( ) = = io : : EXN_ELEMENT_END )
{
if ( libraryVisualScenesSectionName = = reader - > getNodeName ( ) )
return ;
else
if ( ( visualSceneSectionName = = reader - > getNodeName ( ) ) & & p )
{
Prefabs . push_back ( p ) ;
p = 0 ;
}
}
2007-05-20 11:03:49 -07:00
}
}
//! reads a <scene> section and its content
void CColladaFileLoader : : readSceneSection ( io : : IXMLReaderUTF8 * reader )
{
# ifdef COLLADA_READER_DEBUG
os : : Printer : : log ( " COLLADA reading scene " ) ;
# endif
if ( reader - > isEmptyElement ( ) )
return ;
// read the scene
2008-01-13 16:23:02 -08:00
core : : matrix4 transform ; // transformation of this node
core : : aabbox3df bbox ;
scene : : IDummyTransformationSceneNode * node = 0 ;
2007-05-20 11:03:49 -07:00
while ( reader - > read ( ) )
{
2008-01-20 16:35:47 -08:00
if ( reader - > getNodeType ( ) = = io : : EXN_ELEMENT )
2008-01-13 16:23:02 -08:00
{
2008-01-20 16:35:47 -08:00
if ( lookatNodeName = = reader - > getNodeName ( ) )
transform * = readLookAtNode ( reader ) ;
else
if ( matrixNodeName = = reader - > getNodeName ( ) )
transform * = readMatrixNode ( reader ) ;
else
if ( perspectiveNodeName = = reader - > getNodeName ( ) )
transform * = readPerspectiveNode ( reader ) ;
else
if ( rotateNodeName = = reader - > getNodeName ( ) )
transform * = readRotateNode ( reader ) ;
else
if ( scaleNodeName = = reader - > getNodeName ( ) )
transform * = readScaleNode ( reader ) ;
else
if ( skewNodeName = = reader - > getNodeName ( ) )
transform * = readSkewNode ( reader ) ;
else
2008-01-23 09:15:15 -08:00
if ( translateNodeName = = reader - > getNodeName ( ) )
transform * = readTranslateNode ( reader ) ;
else
2008-01-20 16:35:47 -08:00
if ( bboxNodeName = = reader - > getNodeName ( ) )
readBboxNode ( reader , bbox ) ;
else
if ( nodeSectionName = = reader - > getNodeName ( ) )
{
// create dummy node if there is none yet.
if ( ! node )
node = SceneManager - > addDummyTransformationSceneNode ( SceneManager - > getRootSceneNode ( ) ) ;
2008-01-13 16:23:02 -08:00
2008-01-20 16:35:47 -08:00
readNodeSection ( reader , node ) ;
}
else
if ( ( instanceSceneName = = reader - > getNodeName ( ) ) )
readInstanceNode ( reader , SceneManager - > getRootSceneNode ( ) , 0 ) ;
else
if ( extraNodeName = = reader - > getNodeName ( ) )
skipSection ( reader , false ) ;
else
{
os : : Printer : : log ( " COLLADA loader warning: Wrong tag usage found " , reader - > getNodeName ( ) , ELL_WARNING ) ;
skipSection ( reader , true ) ; // ignore all other sections
}
2008-01-13 16:23:02 -08:00
}
2007-05-20 11:03:49 -07:00
else
2008-01-20 16:35:47 -08:00
if ( ( reader - > getNodeType ( ) = = io : : EXN_ELEMENT_END ) & &
( sceneSectionName = = reader - > getNodeName ( ) ) )
return ;
2007-05-20 11:03:49 -07:00
}
2008-01-13 16:23:02 -08:00
if ( node )
node - > getRelativeTransformationMatrix ( ) = transform ;
2007-05-20 11:03:49 -07:00
}
//! reads a <asset> section and its content
void CColladaFileLoader : : readAssetSection ( io : : IXMLReaderUTF8 * reader )
{
# ifdef COLLADA_READER_DEBUG
os : : Printer : : log ( " COLLADA reading asset " ) ;
# endif
2008-11-13 09:35:17 -08:00
if ( reader - > isEmptyElement ( ) )
return ;
while ( reader - > read ( ) )
{
if ( reader - > getNodeType ( ) = = io : : EXN_ELEMENT )
{
if ( upAxisNodeName = = reader - > getNodeName ( ) )
{
reader - > read ( ) ;
FlipAxis = ( core : : stringc ( " Z_UP " ) = = reader - > getNodeData ( ) ) ;
}
}
else
if ( ( reader - > getNodeType ( ) = = io : : EXN_ELEMENT_END ) & &
( assetSectionName = = reader - > getNodeName ( ) ) )
return ;
}
2007-05-20 11:03:49 -07:00
}
//! reads a <node> section and its content
2008-01-23 09:15:15 -08:00
void CColladaFileLoader : : readNodeSection ( io : : IXMLReaderUTF8 * reader , scene : : ISceneNode * parent , CScenePrefab * p )
2007-05-20 11:03:49 -07:00
{
# ifdef COLLADA_READER_DEBUG
os : : Printer : : log ( " COLLADA reading node " ) ;
# endif
if ( reader - > isEmptyElement ( ) )
return ;
2008-01-24 09:24:52 -08:00
core : : stringc name = readId ( reader ) ;
2008-01-23 09:15:15 -08:00
2007-05-20 11:03:49 -07:00
core : : matrix4 transform ; // transformation of this node
2008-01-13 16:23:02 -08:00
core : : aabbox3df bbox ;
2007-05-20 11:03:49 -07:00
scene : : ISceneNode * node = 0 ; // instance
2008-01-23 09:15:15 -08:00
CScenePrefab * nodeprefab = 0 ; // prefab for library_nodes usage
if ( p )
{
2008-01-24 09:24:52 -08:00
nodeprefab = new CScenePrefab ( readId ( reader ) ) ;
2008-01-23 09:15:15 -08:00
p - > Childs . push_back ( nodeprefab ) ;
2008-01-25 09:01:42 -08:00
Prefabs . push_back ( nodeprefab ) ; // in order to delete them later on
2008-01-23 09:15:15 -08:00
}
2007-05-20 11:03:49 -07:00
// read the node
while ( reader - > read ( ) )
2008-01-13 16:23:02 -08:00
{
2008-01-23 09:15:15 -08:00
if ( reader - > getNodeType ( ) = = io : : EXN_ELEMENT )
2007-05-20 11:03:49 -07:00
{
2008-01-23 09:15:15 -08:00
if ( assetSectionName = = reader - > getNodeName ( ) )
readAssetSection ( reader ) ;
else
if ( lookatNodeName = = reader - > getNodeName ( ) )
transform * = readLookAtNode ( reader ) ;
else
if ( matrixNodeName = = reader - > getNodeName ( ) )
transform * = readMatrixNode ( reader ) ;
else
if ( perspectiveNodeName = = reader - > getNodeName ( ) )
transform * = readPerspectiveNode ( reader ) ;
else
if ( rotateNodeName = = reader - > getNodeName ( ) )
transform * = readRotateNode ( reader ) ;
else
if ( scaleNodeName = = reader - > getNodeName ( ) )
transform * = readScaleNode ( reader ) ;
else
if ( skewNodeName = = reader - > getNodeName ( ) )
transform * = readSkewNode ( reader ) ;
else
if ( translateNodeName = = reader - > getNodeName ( ) )
transform * = readTranslateNode ( reader ) ;
else
if ( bboxNodeName = = reader - > getNodeName ( ) )
readBboxNode ( reader , bbox ) ;
else
if ( ( instanceName = = reader - > getNodeName ( ) ) | |
( instanceNodeName = = reader - > getNodeName ( ) ) | |
( instanceGeometryName = = reader - > getNodeName ( ) ) | |
( instanceLightName = = reader - > getNodeName ( ) ) )
{
scene : : ISceneNode * newnode = 0 ;
readInstanceNode ( reader , parent , & newnode , nodeprefab ) ;
2007-05-20 11:03:49 -07:00
2008-01-23 09:15:15 -08:00
if ( node & & newnode )
{
// move children from dummy to new node
core : : list < ISceneNode * > : : ConstIterator it = node - > getChildren ( ) . begin ( ) ;
for ( ; it ! = node - > getChildren ( ) . end ( ) ; it = node - > getChildren ( ) . begin ( ) )
( * it ) - > setParent ( newnode ) ;
// remove previous dummy node
node - > remove ( ) ;
2008-11-13 09:35:17 -08:00
node = newnode ;
2008-01-23 09:15:15 -08:00
}
}
else
if ( nodeSectionName = = reader - > getNodeName ( ) )
2007-05-20 11:03:49 -07:00
{
2008-01-23 09:15:15 -08:00
// create dummy node if there is none yet.
2008-11-13 09:35:17 -08:00
if ( CreateInstances & & ! node )
2008-01-23 09:15:15 -08:00
{
scene : : IDummyTransformationSceneNode * dummy =
SceneManager - > addDummyTransformationSceneNode ( parent ) ;
dummy - > getRelativeTransformationMatrix ( ) = transform ;
node = dummy ;
}
2008-11-13 09:35:17 -08:00
else
node = parent ;
2007-05-20 11:03:49 -07:00
2008-01-23 09:15:15 -08:00
// read and add child
readNodeSection ( reader , node , nodeprefab ) ;
2007-05-20 11:03:49 -07:00
}
2008-01-23 09:15:15 -08:00
else
if ( extraNodeName = = reader - > getNodeName ( ) )
skipSection ( reader , false ) ;
else
skipSection ( reader , true ) ; // ignore all other sections
2007-05-20 11:03:49 -07:00
2008-01-23 09:15:15 -08:00
} // end if node
2007-05-20 11:03:49 -07:00
else
2008-01-23 09:15:15 -08:00
if ( reader - > getNodeType ( ) = = io : : EXN_ELEMENT_END )
2007-05-20 11:03:49 -07:00
{
2008-01-23 09:15:15 -08:00
if ( nodeSectionName = = reader - > getNodeName ( ) )
break ;
2007-05-20 11:03:49 -07:00
}
2008-01-13 16:23:02 -08:00
}
2007-05-20 11:03:49 -07:00
2008-11-13 09:35:17 -08:00
if ( nodeprefab )
nodeprefab - > Transformation = transform ;
2008-01-23 09:15:15 -08:00
else
2007-05-20 11:03:49 -07:00
if ( node )
{
2008-01-13 16:23:02 -08:00
// set transformation correctly into node.
node - > setPosition ( transform . getTranslation ( ) ) ;
node - > setRotation ( transform . getRotationDegrees ( ) ) ;
node - > setScale ( transform . getScale ( ) ) ;
2007-05-20 11:03:49 -07:00
node - > updateAbsolutePosition ( ) ;
2008-11-13 09:35:17 -08:00
node - > setName ( name ) ;
2007-05-20 11:03:49 -07:00
}
}
//! reads a <lookat> element and its content and creates a matrix from it
core : : matrix4 CColladaFileLoader : : readLookAtNode ( io : : IXMLReaderUTF8 * reader )
{
core : : matrix4 mat ;
if ( reader - > isEmptyElement ( ) )
return mat ;
# ifdef COLLADA_READER_DEBUG
os : : Printer : : log ( " COLLADA reading look at node " ) ;
# endif
f32 floats [ 9 ] ;
readFloatsInsideElement ( reader , floats , 9 ) ;
mat . buildCameraLookAtMatrixLH (
core : : vector3df ( floats [ 0 ] , floats [ 1 ] , floats [ 2 ] ) ,
core : : vector3df ( floats [ 3 ] , floats [ 4 ] , floats [ 5 ] ) ,
core : : vector3df ( floats [ 6 ] , floats [ 7 ] , floats [ 8 ] ) ) ;
return mat ;
}
2008-01-13 16:23:02 -08:00
2007-05-20 11:03:49 -07:00
//! reads a <skew> element and its content and creates a matrix from it
core : : matrix4 CColladaFileLoader : : readSkewNode ( io : : IXMLReaderUTF8 * reader )
{
2007-08-29 09:09:32 -07:00
# ifdef COLLADA_READER_DEBUG
os : : Printer : : log ( " COLLADA reading skew node " ) ;
# endif
2007-05-20 11:03:49 -07:00
core : : matrix4 mat ;
if ( reader - > isEmptyElement ( ) )
return mat ;
2008-01-13 16:23:02 -08:00
f32 floats [ 7 ] ; // angle rotation-axis translation-axis
2007-05-20 11:03:49 -07:00
readFloatsInsideElement ( reader , floats , 7 ) ;
2008-01-13 16:23:02 -08:00
// build skew matrix from these 7 floats
core : : quaternion q ;
q . fromAngleAxis ( floats [ 0 ] * core : : DEGTORAD , core : : vector3df ( floats [ 1 ] , floats [ 2 ] , floats [ 3 ] ) ) ;
2008-11-13 09:35:17 -08:00
mat = q . getMatrix ( ) ;
2007-05-20 11:03:49 -07:00
2008-01-13 16:23:02 -08:00
if ( floats [ 4 ] = = 1.f ) // along x-axis
{
mat [ 4 ] = 0.f ;
mat [ 6 ] = 0.f ;
mat [ 8 ] = 0.f ;
mat [ 9 ] = 0.f ;
}
else
if ( floats [ 5 ] = = 1.f ) // along y-axis
{
mat [ 1 ] = 0.f ;
mat [ 2 ] = 0.f ;
mat [ 8 ] = 0.f ;
mat [ 9 ] = 0.f ;
}
else
if ( floats [ 6 ] = = 1.f ) // along z-axis
{
mat [ 1 ] = 0.f ;
mat [ 2 ] = 0.f ;
mat [ 4 ] = 0.f ;
mat [ 6 ] = 0.f ;
}
2007-05-20 11:03:49 -07:00
return mat ;
}
2008-01-13 16:23:02 -08:00
//! reads a <boundingbox> element and its content and stores it in bbox
void CColladaFileLoader : : readBboxNode ( io : : IXMLReaderUTF8 * reader ,
core : : aabbox3df & bbox )
{
# ifdef COLLADA_READER_DEBUG
os : : Printer : : log ( " COLLADA reading boundingbox node " ) ;
# endif
bbox . reset ( core : : aabbox3df ( ) ) ;
if ( reader - > isEmptyElement ( ) )
return ;
f32 floats [ 3 ] ;
while ( reader - > read ( ) )
{
if ( reader - > getNodeType ( ) = = io : : EXN_ELEMENT )
{
if ( minNodeName = = reader - > getNodeName ( ) )
{
readFloatsInsideElement ( reader , floats , 3 ) ;
bbox . MinEdge . set ( floats [ 0 ] , floats [ 1 ] , floats [ 2 ] ) ;
}
else
if ( maxNodeName = = reader - > getNodeName ( ) )
{
readFloatsInsideElement ( reader , floats , 3 ) ;
bbox . MaxEdge . set ( floats [ 0 ] , floats [ 1 ] , floats [ 2 ] ) ;
}
else
skipSection ( reader , true ) ; // ignore all other sections
}
else
if ( reader - > getNodeType ( ) = = io : : EXN_ELEMENT_END )
{
if ( bboxNodeName = = reader - > getNodeName ( ) )
break ;
}
}
}
2007-05-20 11:03:49 -07:00
//! reads a <matrix> element and its content and creates a matrix from it
core : : matrix4 CColladaFileLoader : : readMatrixNode ( io : : IXMLReaderUTF8 * reader )
{
2007-08-29 09:09:32 -07:00
# ifdef COLLADA_READER_DEBUG
os : : Printer : : log ( " COLLADA reading matrix node " ) ;
# endif
2007-05-20 11:03:49 -07:00
core : : matrix4 mat ;
if ( reader - > isEmptyElement ( ) )
return mat ;
readFloatsInsideElement ( reader , mat . pointer ( ) , 16 ) ;
2008-01-23 09:15:15 -08:00
// put translation into the correct place
2008-11-13 09:35:17 -08:00
if ( FlipAxis )
{
2008-11-16 16:39:33 -08:00
core : : matrix4 mat2 ( mat , core : : matrix4 : : EM4CONST_TRANSPOSED ) ;
mat2 [ 1 ] = mat [ 8 ] ;
mat2 [ 2 ] = mat [ 4 ] ;
mat2 [ 4 ] = mat [ 2 ] ;
2008-11-13 09:35:17 -08:00
mat2 [ 5 ] = mat [ 10 ] ;
2008-11-16 16:39:33 -08:00
mat2 [ 6 ] = mat [ 6 ] ;
mat2 [ 8 ] = mat [ 1 ] ;
mat2 [ 9 ] = mat [ 9 ] ;
2008-11-13 09:35:17 -08:00
mat2 [ 10 ] = mat [ 5 ] ;
2008-11-16 16:39:33 -08:00
mat2 [ 12 ] = mat [ 3 ] ;
mat2 [ 13 ] = mat [ 11 ] ;
mat2 [ 14 ] = mat [ 7 ] ;
2008-11-13 09:35:17 -08:00
return mat2 ;
}
else
2008-11-16 16:39:33 -08:00
return core : : matrix4 ( mat , core : : matrix4 : : EM4CONST_TRANSPOSED ) ;
2007-05-20 11:03:49 -07:00
}
2008-01-13 16:23:02 -08:00
2007-05-20 11:03:49 -07:00
//! reads a <perspective> element and its content and creates a matrix from it
core : : matrix4 CColladaFileLoader : : readPerspectiveNode ( io : : IXMLReaderUTF8 * reader )
{
2007-08-29 09:09:32 -07:00
# ifdef COLLADA_READER_DEBUG
os : : Printer : : log ( " COLLADA reading perspective node " ) ;
# endif
2007-05-20 11:03:49 -07:00
core : : matrix4 mat ;
if ( reader - > isEmptyElement ( ) )
return mat ;
f32 floats [ 1 ] ;
readFloatsInsideElement ( reader , floats , 1 ) ;
// TODO: build perspecitve matrix from this float
os : : Printer : : log ( " COLLADA loader warning: <perspective> not implemented yet. " , ELL_WARNING ) ;
return mat ;
}
2008-01-13 16:23:02 -08:00
2007-05-20 11:03:49 -07:00
//! reads a <rotate> element and its content and creates a matrix from it
core : : matrix4 CColladaFileLoader : : readRotateNode ( io : : IXMLReaderUTF8 * reader )
{
2007-08-29 09:09:32 -07:00
# ifdef COLLADA_READER_DEBUG
os : : Printer : : log ( " COLLADA reading rotate node " ) ;
# endif
2007-05-20 11:03:49 -07:00
core : : matrix4 mat ;
if ( reader - > isEmptyElement ( ) )
return mat ;
f32 floats [ 4 ] ;
readFloatsInsideElement ( reader , floats , 4 ) ;
2008-01-20 16:24:28 -08:00
if ( ! core : : iszero ( floats [ 3 ] ) )
{
core : : quaternion q ;
2008-11-13 09:35:17 -08:00
if ( FlipAxis )
q . fromAngleAxis ( floats [ 3 ] * core : : DEGTORAD , core : : vector3df ( floats [ 0 ] , floats [ 2 ] , floats [ 1 ] ) ) ;
else
q . fromAngleAxis ( floats [ 3 ] * core : : DEGTORAD , core : : vector3df ( floats [ 0 ] , floats [ 1 ] , floats [ 2 ] ) ) ;
2008-01-20 16:24:28 -08:00
return q . getMatrix ( ) ;
}
else
return core : : IdentityMatrix ;
2007-05-20 11:03:49 -07:00
}
2008-01-13 16:23:02 -08:00
2007-05-20 11:03:49 -07:00
//! reads a <scale> element and its content and creates a matrix from it
core : : matrix4 CColladaFileLoader : : readScaleNode ( io : : IXMLReaderUTF8 * reader )
{
2007-08-29 09:09:32 -07:00
# ifdef COLLADA_READER_DEBUG
os : : Printer : : log ( " COLLADA reading scale node " ) ;
# endif
2007-05-20 11:03:49 -07:00
core : : matrix4 mat ;
if ( reader - > isEmptyElement ( ) )
return mat ;
f32 floats [ 3 ] ;
readFloatsInsideElement ( reader , floats , 3 ) ;
2008-11-13 09:35:17 -08:00
if ( FlipAxis )
mat . setScale ( core : : vector3df ( floats [ 0 ] , floats [ 2 ] , floats [ 1 ] ) ) ;
else
mat . setScale ( core : : vector3df ( floats [ 0 ] , floats [ 1 ] , floats [ 2 ] ) ) ;
2007-05-20 11:03:49 -07:00
return mat ;
}
//! reads a <translate> element and its content and creates a matrix from it
core : : matrix4 CColladaFileLoader : : readTranslateNode ( io : : IXMLReaderUTF8 * reader )
{
2007-08-29 09:09:32 -07:00
# ifdef COLLADA_READER_DEBUG
os : : Printer : : log ( " COLLADA reading translate node " ) ;
# endif
2007-05-20 11:03:49 -07:00
core : : matrix4 mat ;
if ( reader - > isEmptyElement ( ) )
return mat ;
f32 floats [ 3 ] ;
readFloatsInsideElement ( reader , floats , 3 ) ;
2008-11-13 09:35:17 -08:00
if ( FlipAxis )
mat . setTranslation ( core : : vector3df ( floats [ 0 ] , floats [ 2 ] , floats [ 1 ] ) ) ;
else
mat . setTranslation ( core : : vector3df ( floats [ 0 ] , floats [ 1 ] , floats [ 2 ] ) ) ;
2007-05-20 11:03:49 -07:00
return mat ;
}
2008-01-13 16:23:02 -08:00
2008-01-20 16:35:47 -08:00
//! reads any kind of <instance*> node and creates a scene node from it
2007-05-20 11:03:49 -07:00
void CColladaFileLoader : : readInstanceNode ( io : : IXMLReaderUTF8 * reader , scene : : ISceneNode * parent ,
2008-01-23 09:15:15 -08:00
scene : : ISceneNode * * outNode , CScenePrefab * p )
2007-05-20 11:03:49 -07:00
{
# ifdef COLLADA_READER_DEBUG
os : : Printer : : log ( " COLLADA reading instance " ) ;
# endif
// find prefab of the specified id
core : : stringc url = reader - > getAttributeValue ( " url " ) ;
uriToId ( url ) ;
2008-01-20 16:35:47 -08:00
if ( ! reader - > isEmptyElement ( ) )
{
while ( reader - > read ( ) )
{
if ( reader - > getNodeType ( ) = = io : : EXN_ELEMENT )
{
if ( bindMaterialName = = reader - > getNodeName ( ) )
2008-01-23 09:15:15 -08:00
readBindMaterialSection ( reader , url ) ;
else
if ( extraNodeName = = reader - > getNodeName ( ) )
skipSection ( reader , false ) ;
2008-01-20 16:35:47 -08:00
}
else
if ( reader - > getNodeType ( ) = = io : : EXN_ELEMENT_END )
2008-01-23 09:15:15 -08:00
break ;
2008-01-20 16:35:47 -08:00
}
}
2008-01-23 09:15:15 -08:00
for ( u32 i = 0 ; i < Prefabs . size ( ) ; + + i )
2008-01-20 16:35:47 -08:00
{
2008-01-23 09:15:15 -08:00
if ( url = = Prefabs [ i ] - > getId ( ) )
2007-05-20 11:03:49 -07:00
{
2008-01-23 09:15:15 -08:00
if ( p )
p - > Childs . push_back ( Prefabs [ i ] ) ;
else
if ( CreateInstances )
2008-01-20 16:35:47 -08:00
{
2008-01-23 09:15:15 -08:00
scene : : ISceneNode * newNode
= Prefabs [ i ] - > addInstance ( parent , SceneManager ) ;
if ( outNode )
{
* outNode = newNode ;
if ( * outNode )
2008-11-13 09:35:17 -08:00
( * outNode ) - > setName ( readId ( reader ) ) ;
2008-01-23 09:15:15 -08:00
}
2008-01-20 16:35:47 -08:00
}
2008-01-23 09:15:15 -08:00
return ;
2007-05-20 11:03:49 -07:00
}
2008-01-20 16:35:47 -08:00
}
2007-05-20 11:03:49 -07:00
}
2008-01-23 09:15:15 -08:00
2007-05-20 11:03:49 -07:00
//! reads a <camera> element and stores it as prefab
void CColladaFileLoader : : readCameraPrefab ( io : : IXMLReaderUTF8 * reader )
{
2007-08-29 09:09:32 -07:00
# ifdef COLLADA_READER_DEBUG
os : : Printer : : log ( " COLLADA reading camera prefab " ) ;
# endif
2008-01-24 09:24:52 -08:00
CCameraPrefab * prefab = new CCameraPrefab ( readId ( reader ) ) ;
2007-05-20 11:03:49 -07:00
if ( ! reader - > isEmptyElement ( ) )
{
2008-01-20 16:24:28 -08:00
// read techniques optics and imager (the latter is completely ignored, though)
2007-05-20 11:03:49 -07:00
readColladaParameters ( reader , cameraPrefabName ) ;
SColladaParam * p ;
2008-01-20 16:24:28 -08:00
// XFOV not yet supported
2007-05-20 11:03:49 -07:00
p = getColladaParameter ( ECPN_YFOV ) ;
if ( p & & p - > Type = = ECPT_FLOAT )
prefab - > YFov = p - > Floats [ 0 ] ;
p = getColladaParameter ( ECPN_ZNEAR ) ;
if ( p & & p - > Type = = ECPT_FLOAT )
prefab - > ZNear = p - > Floats [ 0 ] ;
p = getColladaParameter ( ECPN_ZFAR ) ;
if ( p & & p - > Type = = ECPT_FLOAT )
prefab - > ZFar = p - > Floats [ 0 ] ;
2008-01-20 16:24:28 -08:00
// orthographic camera uses LEFT, RIGHT, TOP, and BOTTOM
2007-05-20 11:03:49 -07:00
}
Prefabs . push_back ( prefab ) ;
}
2007-08-08 09:30:10 -07:00
//! reads a <image> element and stores it in the image section
void CColladaFileLoader : : readImage ( io : : IXMLReaderUTF8 * reader )
{
2007-08-29 09:09:32 -07:00
# ifdef COLLADA_READER_DEBUG
os : : Printer : : log ( " COLLADA reading image " ) ;
# endif
2008-01-24 09:24:52 -08:00
// add image to list of loaded images.
Images . push_back ( SColladaImage ( ) ) ;
SColladaImage & image = Images . getLast ( ) ;
image . Id = readId ( reader ) ;
2008-01-24 16:12:46 -08:00
image . Dimension . Height = ( u32 ) reader - > getAttributeValueAsInt ( " height " ) ;
image . Dimension . Width = ( u32 ) reader - > getAttributeValueAsInt ( " width " ) ;
2008-01-24 09:24:52 -08:00
2008-01-20 16:35:47 -08:00
if ( Version > = 10400 ) // start with 1.4
{
while ( reader - > read ( ) )
{
2008-01-24 09:24:52 -08:00
if ( reader - > getNodeType ( ) = = io : : EXN_ELEMENT )
2008-01-20 16:35:47 -08:00
{
2008-01-24 09:24:52 -08:00
if ( assetSectionName = = reader - > getNodeName ( ) )
skipSection ( reader , false ) ;
else
if ( initFromName = = reader - > getNodeName ( ) )
{
2008-01-24 16:12:46 -08:00
reader - > read ( ) ;
2008-01-24 09:24:52 -08:00
image . Source = reader - > getNodeData ( ) ;
image . Source . trim ( ) ;
image . SourceIsFilename = true ;
}
else
if ( dataName = = reader - > getNodeName ( ) )
{
2008-01-24 16:12:46 -08:00
reader - > read ( ) ;
2008-01-24 09:24:52 -08:00
image . Source = reader - > getNodeData ( ) ;
image . Source . trim ( ) ;
image . SourceIsFilename = false ;
}
else
if ( extraNodeName = = reader - > getNodeName ( ) )
skipSection ( reader , false ) ;
2008-01-20 16:35:47 -08:00
}
else
if ( reader - > getNodeType ( ) = = io : : EXN_ELEMENT_END )
{
if ( initFromName = = reader - > getNodeName ( ) )
return ;
}
2008-01-24 09:24:52 -08:00
}
2008-01-20 16:35:47 -08:00
}
else
2008-01-24 09:24:52 -08:00
{
image . Source = reader - > getAttributeValue ( " source " ) ;
image . Source . trim ( ) ;
image . SourceIsFilename = false ;
}
2007-08-08 09:30:10 -07:00
}
//! reads a <texture> element and stores it in the texture section
void CColladaFileLoader : : readTexture ( io : : IXMLReaderUTF8 * reader )
{
2007-08-29 09:09:32 -07:00
# ifdef COLLADA_READER_DEBUG
os : : Printer : : log ( " COLLADA reading texture " ) ;
# endif
2008-01-24 09:24:52 -08:00
// add texture to list of loaded textures.
Textures . push_back ( SColladaTexture ( ) ) ;
SColladaTexture & texture = Textures . getLast ( ) ;
texture . Id = readId ( reader ) ;
2007-08-08 09:30:10 -07:00
if ( ! reader - > isEmptyElement ( ) )
{
readColladaInputs ( reader , textureSectionName ) ;
SColladaInput * input = getColladaInput ( ECIS_IMAGE ) ;
if ( input )
{
2008-01-24 09:24:52 -08:00
const core : : stringc imageName = input - > Source ;
texture . Texture = getTextureFromImage ( imageName ) ;
2007-08-08 09:30:10 -07:00
}
}
}
2007-05-20 11:03:49 -07:00
//! reads a <material> element and stores it in the material section
void CColladaFileLoader : : readMaterial ( io : : IXMLReaderUTF8 * reader )
{
2007-08-29 09:09:32 -07:00
# ifdef COLLADA_READER_DEBUG
os : : Printer : : log ( " COLLADA reading material " ) ;
# endif
2008-11-13 09:35:17 -08:00
// add material to list of loaded materials.
Materials . push_back ( SColladaMaterial ( ) ) ;
SColladaMaterial & material = Materials . getLast ( ) ;
2008-01-24 09:24:52 -08:00
material . Id = readId ( reader ) ;
2007-05-20 11:03:49 -07:00
2008-01-23 09:15:15 -08:00
if ( Version > = 10400 )
2007-05-20 11:03:49 -07:00
{
2008-01-23 09:15:15 -08:00
while ( reader - > read ( ) )
2007-08-08 09:30:10 -07:00
{
2008-01-23 09:15:15 -08:00
if ( reader - > getNodeType ( ) = = io : : EXN_ELEMENT & &
instanceEffectName = = reader - > getNodeName ( ) )
{
material . InstanceEffectId = reader - > getAttributeValue ( " url " ) ;
uriToId ( material . InstanceEffectId ) ;
}
else
if ( reader - > getNodeType ( ) = = io : : EXN_ELEMENT_END & &
materialSectionName = = reader - > getNodeName ( ) )
{
break ;
}
} // end while reader->read();
}
else
{
if ( ! reader - > isEmptyElement ( ) )
{
readColladaInputs ( reader , materialSectionName ) ;
SColladaInput * input = getColladaInput ( ECIS_TEXTURE ) ;
if ( input )
{
core : : stringc textureName = input - > Source ;
uriToId ( textureName ) ;
for ( u32 i = 0 ; i < Textures . size ( ) ; + + i )
if ( textureName = = Textures [ i ] . Id )
{
material . Mat . setTexture ( 0 , Textures [ i ] . Texture ) ;
break ;
}
}
//does not work because the wrong start node is chosen due to reading of inputs before
#if 0
readColladaParameters ( reader , materialSectionName ) ;
SColladaParam * p ;
p = getColladaParameter ( ECPN_AMBIENT ) ;
if ( p & & p - > Type = = ECPT_FLOAT3 )
material . Mat . AmbientColor = video : : SColorf ( p - > Floats [ 0 ] , p - > Floats [ 1 ] , p - > Floats [ 2 ] ) . toSColor ( ) ;
p = getColladaParameter ( ECPN_DIFFUSE ) ;
if ( p & & p - > Type = = ECPT_FLOAT3 )
material . Mat . DiffuseColor = video : : SColorf ( p - > Floats [ 0 ] , p - > Floats [ 1 ] , p - > Floats [ 2 ] ) . toSColor ( ) ;
p = getColladaParameter ( ECPN_SPECULAR ) ;
if ( p & & p - > Type = = ECPT_FLOAT3 )
material . Mat . DiffuseColor = video : : SColorf ( p - > Floats [ 0 ] , p - > Floats [ 1 ] , p - > Floats [ 2 ] ) . toSColor ( ) ;
p = getColladaParameter ( ECPN_SHININESS ) ;
if ( p & & p - > Type = = ECPT_FLOAT )
material . Mat . Shininess = p - > Floats [ 0 ] ;
# endif
}
}
}
void CColladaFileLoader : : readEffect ( io : : IXMLReaderUTF8 * reader , SColladaEffect * effect )
{
# ifdef COLLADA_READER_DEBUG
if ( ! effect ) os : : Printer : : log ( " COLLADA reading effect " ) ;
# endif
static const core : : stringc constantNode ( " constant " ) ;
static const core : : stringc lambertNode ( " lambert " ) ;
static const core : : stringc phongNode ( " phong " ) ;
static const core : : stringc blinnNode ( " blinn " ) ;
static const core : : stringc emissionNode ( " emission " ) ;
static const core : : stringc ambientNode ( " ambient " ) ;
static const core : : stringc diffuseNode ( " diffuse " ) ;
static const core : : stringc specularNode ( " specular " ) ;
static const core : : stringc shininessNode ( " shininess " ) ;
static const core : : stringc reflectiveNode ( " reflective " ) ;
static const core : : stringc reflectivityNode ( " reflectivity " ) ;
static const core : : stringc transparentNode ( " transparent " ) ;
static const core : : stringc transparencyNode ( " transparency " ) ;
static const core : : stringc indexOfRefractionNode ( " index_of_refraction " ) ;
if ( ! effect )
{
Effects . push_back ( SColladaEffect ( ) ) ;
effect = & Effects . getLast ( ) ;
2008-01-24 09:24:52 -08:00
effect - > Id = readId ( reader ) ;
2008-01-25 09:01:42 -08:00
effect - > Transparency = 1.f ;
2008-11-13 09:35:17 -08:00
effect - > Mat . Lighting = true ;
effect - > Mat . NormalizeNormals = true ;
2008-01-23 09:15:15 -08:00
}
while ( reader - > read ( ) )
{
if ( reader - > getNodeType ( ) = = io : : EXN_ELEMENT )
{
2008-01-24 09:24:52 -08:00
// first come the tags we descend, but ignore the top-levels
2008-01-24 16:12:46 -08:00
if ( ! reader - > isEmptyElement ( ) & & ( ( profileCOMMONSectionName = = reader - > getNodeName ( ) ) | |
( techniqueNodeName = = reader - > getNodeName ( ) ) ) )
2008-01-23 09:15:15 -08:00
readEffect ( reader , effect ) ;
else
2008-01-24 09:24:52 -08:00
if ( newParamName = = reader - > getNodeName ( ) )
readParameter ( reader ) ;
2008-01-23 09:15:15 -08:00
else
2008-01-24 09:24:52 -08:00
// these are the actual materials inside technique
2008-01-23 09:15:15 -08:00
if ( constantNode = = reader - > getNodeName ( ) | |
lambertNode = = reader - > getNodeName ( ) | |
phongNode = = reader - > getNodeName ( ) | |
blinnNode = = reader - > getNodeName ( ) )
{
2008-01-24 09:24:52 -08:00
# ifdef COLLADA_READER_DEBUG
os : : Printer : : log ( " COLLADA reading effect part " , reader - > getNodeName ( ) ) ;
# endif
2008-01-23 09:15:15 -08:00
effect - > Mat . setFlag ( irr : : video : : EMF_GOURAUD_SHADING ,
phongNode = = reader - > getNodeName ( ) | |
blinnNode = = reader - > getNodeName ( ) ) ;
while ( reader - > read ( ) )
2007-08-08 09:30:10 -07:00
{
2008-01-23 09:15:15 -08:00
if ( reader - > getNodeType ( ) = = io : : EXN_ELEMENT )
{
2008-01-24 09:24:52 -08:00
const core : : stringc node = reader - > getNodeName ( ) ;
2008-01-23 09:15:15 -08:00
if ( emissionNode = = node | | ambientNode = = node | |
diffuseNode = = node | | specularNode = = node | |
reflectiveNode = = node | | transparentNode = = node )
{
// color or texture types
while ( reader - > read ( ) )
{
if ( reader - > getNodeType ( ) = = io : : EXN_ELEMENT & &
colorNodeName = = reader - > getNodeName ( ) )
{
const video : : SColorf colorf = readColorNode ( reader ) ;
const video : : SColor color = colorf . toSColor ( ) ;
if ( emissionNode = = node )
effect - > Mat . EmissiveColor = color ;
else
if ( ambientNode = = node )
effect - > Mat . AmbientColor = color ;
else
if ( diffuseNode = = node )
effect - > Mat . DiffuseColor = color ;
else
if ( specularNode = = node )
effect - > Mat . SpecularColor = color ;
else
if ( transparentNode = = node )
2008-11-13 09:35:17 -08:00
effect - > Transparency = colorf . getAlpha ( ) ;
2008-01-23 09:15:15 -08:00
}
else
2008-01-23 16:38:59 -08:00
if ( reader - > getNodeType ( ) = = io : : EXN_ELEMENT & &
textureNodeName = = reader - > getNodeName ( ) )
{
const core : : stringc tname = reader - > getAttributeValue ( " texture " ) ;
2008-01-24 09:24:52 -08:00
effect - > Mat . setTexture ( 0 , getTextureFromImage ( tname ) ) ;
break ;
2008-01-23 16:38:59 -08:00
}
else
2008-01-23 09:15:15 -08:00
if ( reader - > getNodeType ( ) = = io : : EXN_ELEMENT )
skipSection ( reader , false ) ;
else
if ( reader - > getNodeType ( ) = = io : : EXN_ELEMENT_END & &
node = = reader - > getNodeName ( ) )
break ;
}
}
else
if ( shininessNode = = node | | reflectivityNode = = node | |
transparencyNode = = node | | indexOfRefractionNode = = node )
{
// float or param types
while ( reader - > read ( ) )
{
if ( reader - > getNodeType ( ) = = io : : EXN_ELEMENT & &
floatNodeName = = reader - > getNodeName ( ) )
{
f32 f = readFloatNode ( reader ) ;
if ( shininessNode = = node )
effect - > Mat . Shininess = f ;
else
if ( transparencyNode = = node )
2008-01-25 09:01:42 -08:00
effect - > Transparency * = f ;
2008-01-23 09:15:15 -08:00
}
else
if ( reader - > getNodeType ( ) = = io : : EXN_ELEMENT )
skipSection ( reader , false ) ;
else
if ( reader - > getNodeType ( ) = = io : : EXN_ELEMENT_END & &
node = = reader - > getNodeName ( ) )
break ;
}
}
else
skipSection ( reader , true ) ; // ignore all other nodes
}
else
if ( reader - > getNodeType ( ) = = io : : EXN_ELEMENT_END & & (
constantNode = = reader - > getNodeName ( ) | |
lambertNode = = reader - > getNodeName ( ) | |
phongNode = = reader - > getNodeName ( ) | |
blinnNode = = reader - > getNodeName ( )
) )
break ;
}
}
else
2008-01-24 16:12:46 -08:00
if ( ! reader - > isEmptyElement ( ) & & ( extraNodeName = = reader - > getNodeName ( ) ) )
2008-01-23 09:15:15 -08:00
readEffect ( reader , effect ) ;
else
2008-11-13 09:35:17 -08:00
if ( doubleSidedNodeName = = reader - > getNodeName ( ) )
2008-01-23 09:15:15 -08:00
{
// read the GoogleEarth extra flag for double sided polys
s32 doubleSided = 0 ;
readIntsInsideElement ( reader , & doubleSided , 1 ) ;
if ( doubleSided )
{
effect - > Mat . setFlag ( irr : : video : : EMF_BACK_FACE_CULLING , false ) ;
2007-08-08 09:30:10 -07:00
}
2008-01-23 09:15:15 -08:00
}
else
skipSection ( reader , true ) ; // ignore all other sections
2007-08-08 09:30:10 -07:00
}
2008-01-23 09:15:15 -08:00
else
if ( reader - > getNodeType ( ) = = io : : EXN_ELEMENT_END )
{
if ( effectSectionName = = reader - > getNodeName ( ) )
break ;
else
if ( profileCOMMONSectionName = = reader - > getNodeName ( ) )
break ;
else
if ( techniqueNodeName = = reader - > getNodeName ( ) )
break ;
else
if ( extraNodeName = = reader - > getNodeName ( ) )
break ;
}
}
2008-01-24 09:24:52 -08:00
2008-01-23 09:15:15 -08:00
if ( effect - > Mat . AmbientColor = = video : : SColor ( 0 ) & &
effect - > Mat . DiffuseColor ! = video : : SColor ( 0 ) )
effect - > Mat . AmbientColor = effect - > Mat . DiffuseColor ;
if ( effect - > Mat . DiffuseColor = = video : : SColor ( 0 ) & &
effect - > Mat . AmbientColor ! = video : : SColor ( 0 ) )
effect - > Mat . DiffuseColor = effect - > Mat . AmbientColor ;
2008-11-16 16:56:07 -08:00
if ( ( effect - > Transparency ! = 0.0f ) & & ( effect - > Transparency ! = 1.0f ) )
2008-11-16 16:39:33 -08:00
{
2008-01-25 09:01:42 -08:00
effect - > Mat . MaterialType = irr : : video : : EMT_TRANSPARENT_VERTEX_ALPHA ;
2008-11-16 16:39:33 -08:00
effect - > Mat . ZWriteEnable = false ;
}
2008-11-13 09:35:17 -08:00
effect - > Mat . setFlag ( video : : EMF_TEXTURE_WRAP , ! Parameters . getAttributeAsBool ( " wrap_s " ) ) ;
effect - > Mat . setFlag ( video : : EMF_BILINEAR_FILTER , Parameters . getAttributeAsBool ( " bilinear " ) ) ;
effect - > Mat . setFlag ( video : : EMF_TRILINEAR_FILTER , Parameters . getAttributeAsBool ( " trilinear " ) ) ;
effect - > Mat . setFlag ( video : : EMF_ANISOTROPIC_FILTER , Parameters . getAttributeAsBool ( " anisotropic " ) ) ;
2008-01-23 09:15:15 -08:00
}
2007-08-08 09:30:10 -07:00
2008-01-23 16:38:59 -08:00
2008-11-13 09:35:17 -08:00
const SColladaMaterial * CColladaFileLoader : : findMaterial ( const core : : stringc & materialName )
2008-01-23 09:15:15 -08:00
{
// do a quick lookup in the materials
SColladaMaterial matToFind ;
matToFind . Id = materialName ;
s32 mat = Materials . binary_search ( matToFind ) ;
2008-01-25 09:01:42 -08:00
if ( mat = = - 1 )
2008-01-23 09:15:15 -08:00
return 0 ;
2008-01-25 09:01:42 -08:00
// instantiate the material effect if needed
2008-11-13 09:35:17 -08:00
if ( Materials [ mat ] . InstanceEffectId . size ( ) ! = 0 )
2008-01-23 09:15:15 -08:00
{
// do a quick lookup in the effects
SColladaEffect effectToFind ;
effectToFind . Id = Materials [ mat ] . InstanceEffectId ;
s32 effect = Effects . binary_search ( effectToFind ) ;
2008-01-25 09:01:42 -08:00
if ( effect ! = - 1 )
2008-01-23 09:15:15 -08:00
{
2008-01-25 09:01:42 -08:00
// found the effect, instantiate by copying into the material
2008-01-23 09:15:15 -08:00
Materials [ mat ] . Mat = Effects [ effect ] . Mat ;
2008-01-25 09:01:42 -08:00
Materials [ mat ] . Transparency = Effects [ effect ] . Transparency ;
// and indicate the material is instantiated by removing the effect ref
2008-01-23 09:15:15 -08:00
Materials [ mat ] . InstanceEffectId = " " ;
}
2008-01-25 09:01:42 -08:00
else
return 0 ;
2008-01-23 09:15:15 -08:00
}
return & Materials [ mat ] ;
}
2007-08-08 09:30:10 -07:00
2008-01-23 16:38:59 -08:00
2008-01-23 09:15:15 -08:00
void CColladaFileLoader : : readBindMaterialSection ( io : : IXMLReaderUTF8 * reader , const core : : stringc & id )
{
# ifdef COLLADA_READER_DEBUG
os : : Printer : : log ( " COLLADA reading bind material " ) ;
# endif
2007-08-08 09:30:10 -07:00
2008-01-23 09:15:15 -08:00
while ( reader - > read ( ) )
{
if ( reader - > getNodeType ( ) = = io : : EXN_ELEMENT )
{
if ( instanceMaterialName = = reader - > getNodeName ( ) )
{
// the symbol to retarget, and the target material
2008-11-13 09:35:17 -08:00
core : : stringc meshbufferReference = reader - > getAttributeValue ( " symbol " ) ;
if ( meshbufferReference . size ( ) = = 0 )
2008-01-23 09:15:15 -08:00
continue ;
core : : stringc target = reader - > getAttributeValue ( " target " ) ;
uriToId ( target ) ;
if ( target . size ( ) = = 0 )
continue ;
const SColladaMaterial * material = findMaterial ( target ) ;
if ( ! material )
continue ;
// bind any pending materials for this node
2008-11-13 09:35:17 -08:00
meshbufferReference = id + " / " + meshbufferReference ;
2008-01-23 09:15:15 -08:00
# ifdef COLLADA_READER_DEBUG
2008-11-13 09:35:17 -08:00
os : : Printer : : log ( ( core : : stringc ( " Material binding: " ) + meshbufferReference + " " + target ) . c_str ( ) ) ;
2007-08-08 09:30:10 -07:00
# endif
2008-11-13 09:35:17 -08:00
if ( MaterialsToBind . find ( meshbufferReference ) )
2008-01-23 09:15:15 -08:00
{
core : : array < irr : : scene : : IMeshBuffer * > & toBind
2008-11-13 09:35:17 -08:00
= MeshesToBind [ MaterialsToBind [ meshbufferReference ] ] ;
# ifdef COLLADA_READER_DEBUG
os : : Printer : : log ( " Material binding now " , material - > Id . c_str ( ) ) ;
os : : Printer : : log ( " #meshbuffers " , core : : stringc ( toBind . size ( ) ) . c_str ( ) ) ;
# endif
2008-01-25 09:01:42 -08:00
SMesh tmpmesh ;
2008-01-23 09:15:15 -08:00
for ( u32 i = 0 ; i < toBind . size ( ) ; + + i )
{
toBind [ i ] - > getMaterial ( ) = material - > Mat ;
2008-11-13 09:35:17 -08:00
tmpmesh . addMeshBuffer ( toBind [ i ] ) ;
2008-11-16 16:56:07 -08:00
2008-11-13 09:35:17 -08:00
if ( ( material - > Transparency ! = 0.0f ) & & ( material - > Transparency ! = 1.0f ) )
2008-11-16 16:39:33 -08:00
{
2008-11-13 09:35:17 -08:00
toBind [ i ] - > getMaterial ( ) . MaterialType = video : : EMT_TRANSPARENT_VERTEX_ALPHA ;
2008-11-16 16:39:33 -08:00
toBind [ i ] - > getMaterial ( ) . ZWriteEnable = false ;
}
2008-01-25 09:01:42 -08:00
}
2008-11-13 09:35:17 -08:00
SceneManager - > getMeshManipulator ( ) - > setVertexColors ( & tmpmesh , material - > Mat . DiffuseColor ) ;
if ( ( material - > Transparency ! = 0.0f ) & & ( material - > Transparency ! = 1.0f ) )
2008-01-25 09:01:42 -08:00
{
# ifdef COLLADA_READER_DEBUG
os : : Printer : : log ( " COLLADA found transparency material " , core : : stringc ( material - > Transparency ) . c_str ( ) ) ;
# endif
SceneManager - > getMeshManipulator ( ) - > setVertexColorAlpha ( & tmpmesh , core : : floor32 ( material - > Transparency * 255.0f ) ) ;
2008-01-23 09:15:15 -08:00
}
}
}
}
else
if ( reader - > getNodeType ( ) = = io : : EXN_ELEMENT_END & &
bindMaterialName = = reader - > getNodeName ( ) )
break ;
2007-05-20 11:03:49 -07:00
}
}
2008-01-23 09:15:15 -08:00
2007-05-20 11:03:49 -07:00
//! reads a <geometry> element and stores it as mesh if possible
void CColladaFileLoader : : readGeometry ( io : : IXMLReaderUTF8 * reader )
{
2007-08-29 09:09:32 -07:00
# ifdef COLLADA_READER_DEBUG
os : : Printer : : log ( " COLLADA reading geometry " ) ;
# endif
2008-01-24 09:24:52 -08:00
core : : stringc id = readId ( reader ) ;
2007-05-20 11:03:49 -07:00
core : : stringc VertexPositionSource ; // each mesh has exactly one <vertex> member, containing
// a POSITION input. This string stores the source of this input.
core : : array < SSource > sources ;
bool okToReadArray = false ;
SAnimatedMesh * amesh = new SAnimatedMesh ( ) ;
scene : : SMesh * mesh = new SMesh ( ) ;
amesh - > addMesh ( mesh ) ;
2008-01-20 16:24:28 -08:00
// handles geometry node and the mesh childs in this loop
2007-05-20 11:03:49 -07:00
// read sources with arrays and accessor for each mesh
if ( ! reader - > isEmptyElement ( ) )
while ( reader - > read ( ) )
{
if ( reader - > getNodeType ( ) = = io : : EXN_ELEMENT )
{
const char * nodeName = reader - > getNodeName ( ) ;
if ( meshSectionName = = nodeName )
{
// inside a mesh section. Don't have to do anything here.
}
else
if ( sourceSectionName = = nodeName )
{
// create a new source
sources . push_back ( SSource ( ) ) ;
2008-01-24 09:24:52 -08:00
sources . getLast ( ) . Id = readId ( reader ) ;
2007-05-20 11:03:49 -07:00
# ifdef COLLADA_READER_DEBUG
2008-01-24 09:24:52 -08:00
os : : Printer : : log ( " Reading source " , sources . getLast ( ) . Id . c_str ( ) ) ;
2007-05-20 11:03:49 -07:00
# endif
}
else
2008-01-20 16:35:47 -08:00
if ( arraySectionName = = nodeName | | floatArraySectionName = = nodeName | | intArraySectionName = = nodeName )
2007-05-20 11:03:49 -07:00
{
// create a new array and read it.
if ( ! sources . empty ( ) )
{
2008-01-24 09:24:52 -08:00
sources . getLast ( ) . Array . Name = readId ( reader ) ;
2007-05-20 11:03:49 -07:00
int count = reader - > getAttributeValueAsInt ( " count " ) ;
sources . getLast ( ) . Array . Data . set_used ( count ) ; // pre allocate
// check if type of array is ok
const char * type = reader - > getAttributeValue ( " type " ) ;
2008-01-20 16:35:47 -08:00
okToReadArray = ( type & & ( ! strcmp ( " float " , type ) | | ! strcmp ( " int " , type ) ) ) | | floatArraySectionName = = nodeName | | intArraySectionName = = nodeName ;
2007-05-20 11:03:49 -07:00
# ifdef COLLADA_READER_DEBUG
os : : Printer : : log ( " Read array " , sources . getLast ( ) . Array . Name . c_str ( ) ) ;
# endif
}
# ifdef COLLADA_READER_DEBUG
else
2008-01-24 09:24:52 -08:00
os : : Printer : : log ( " Warning, array outside source found " ,
readId ( reader ) . c_str ( ) ) ;
2007-05-20 11:03:49 -07:00
# endif
}
else
2008-01-20 16:24:28 -08:00
if ( accessorSectionName = = nodeName ) // child of source (below a technique tag)
2007-05-20 11:03:49 -07:00
{
2008-01-24 09:24:52 -08:00
# ifdef COLLADA_READER_DEBUG
os : : Printer : : log ( " Reading accessor " ) ;
# endif
2007-05-20 11:03:49 -07:00
SAccessor accessor ;
accessor . Count = reader - > getAttributeValueAsInt ( " count " ) ;
accessor . Offset = reader - > getAttributeValueAsInt ( " offset " ) ;
accessor . Stride = reader - > getAttributeValueAsInt ( " stride " ) ;
if ( accessor . Stride = = 0 )
accessor . Stride = 1 ;
// the accessor contains some information on how to access (boi!) the array,
// the info is stored in collada style parameters, so just read them.
readColladaParameters ( reader , accessorSectionName ) ;
if ( ! sources . empty ( ) )
{
sources . getLast ( ) . Accessors . push_back ( accessor ) ;
2008-01-24 09:24:52 -08:00
sources . getLast ( ) . Accessors . getLast ( ) . Parameters = ColladaParameters ;
2007-05-20 11:03:49 -07:00
}
}
else
if ( verticesSectionName = = nodeName )
{
2008-01-24 09:24:52 -08:00
# ifdef COLLADA_READER_DEBUG
os : : Printer : : log ( " Reading vertices " ) ;
# endif
2007-05-20 11:03:49 -07:00
// read vertex input position source
readColladaInputs ( reader , verticesSectionName ) ;
SColladaInput * input = getColladaInput ( ECIS_POSITION ) ;
if ( input )
VertexPositionSource = input - > Source ;
}
else
2008-01-20 16:24:28 -08:00
// lines and linestrips missing
2008-01-23 09:15:15 -08:00
if ( polygonsSectionName = = nodeName | |
2008-01-24 09:24:52 -08:00
polylistSectionName = = nodeName | |
2008-01-20 16:35:47 -08:00
trianglesSectionName = = nodeName )
2007-05-20 11:03:49 -07:00
{
// read polygons section
2008-01-23 09:15:15 -08:00
readPolygonSection ( reader , VertexPositionSource , sources , mesh , id ) ;
2007-05-20 11:03:49 -07:00
}
2008-01-20 16:24:28 -08:00
else
2008-01-23 09:15:15 -08:00
// trifans, and tristrips missing
2008-01-20 16:24:28 -08:00
if ( extraNodeName = = reader - > getNodeName ( ) )
skipSection ( reader , false ) ;
else
2008-01-24 09:24:52 -08:00
if ( techniqueCommonSectionName ! = nodeName ) // techniqueCommon must not be skipped
2008-01-20 16:24:28 -08:00
{
// os::Printer::log("COLLADA loader warning: Wrong tag usage found", reader->getNodeName(), ELL_WARNING);
skipSection ( reader , true ) ; // ignore all other sections
}
2007-05-20 11:03:49 -07:00
} // end if node type is element
else
if ( reader - > getNodeType ( ) = = io : : EXN_TEXT )
{
// read array data
if ( okToReadArray & & ! sources . empty ( ) )
{
core : : array < f32 > & a = sources . getLast ( ) . Array . Data ;
core : : stringc data = reader - > getNodeData ( ) ;
2008-01-23 09:15:15 -08:00
data . trim ( ) ;
2007-05-20 11:03:49 -07:00
const c8 * p = & data [ 0 ] ;
2007-08-08 09:30:10 -07:00
for ( u32 i = 0 ; i < a . size ( ) ; + + i )
2007-05-20 11:03:49 -07:00
{
findNextNoneWhiteSpace ( & p ) ;
2007-08-08 09:30:10 -07:00
if ( * p )
a [ i ] = readFloat ( & p ) ;
else
a [ i ] = 0.0f ;
2007-05-20 11:03:49 -07:00
}
} // end reading array
okToReadArray = false ;
} // end if node type is text
else
if ( reader - > getNodeType ( ) = = io : : EXN_ELEMENT_END )
{
if ( geometrySectionName = = reader - > getNodeName ( ) )
{
// end of geometry section reached, cancel out
break ;
}
}
} // end while reader->read();
// add mesh as geometry
mesh - > recalculateBoundingBox ( ) ;
2008-01-23 09:15:15 -08:00
amesh - > recalculateBoundingBox ( ) ;
2007-05-20 11:03:49 -07:00
// create virtual file name
core : : stringc filename = CurrentlyLoadingMesh ;
filename + = ' # ' ;
filename + = id ;
// add to scene manager
if ( LoadedMeshCount )
{
SceneManager - > getMeshCache ( ) - > addMesh ( filename . c_str ( ) , amesh ) ;
os : : Printer : : log ( " Added COLLADA mesh " , filename . c_str ( ) ) ;
}
else
{
FirstLoadedMeshName = filename ;
FirstLoadedMesh = amesh ;
FirstLoadedMesh - > grab ( ) ;
}
+ + LoadedMeshCount ;
mesh - > drop ( ) ;
amesh - > drop ( ) ;
// create geometry prefab
CGeometryPrefab * prefab = new CGeometryPrefab ( id . c_str ( ) ) ;
prefab - > Mesh = mesh ;
Prefabs . push_back ( prefab ) ;
// store as dummy mesh if no instances will be created
if ( ! CreateInstances & & ! DummyMesh )
{
DummyMesh = amesh ;
DummyMesh - > grab ( ) ;
}
}
struct SPolygon
{
2007-08-08 09:30:10 -07:00
core : : array < s32 > Indices ;
2007-05-20 11:03:49 -07:00
} ;
//! reads a polygons section and creates a mesh from it
void CColladaFileLoader : : readPolygonSection ( io : : IXMLReaderUTF8 * reader ,
2007-08-29 09:09:32 -07:00
const core : : stringc & vertexPositionSource , core : : array < SSource > & sources ,
2008-01-23 09:15:15 -08:00
scene : : SMesh * mesh , const core : : stringc & geometryId )
2007-05-20 11:03:49 -07:00
{
2007-08-29 09:09:32 -07:00
# ifdef COLLADA_READER_DEBUG
os : : Printer : : log ( " COLLADA reading polygon section " ) ;
# endif
2007-08-08 09:30:10 -07:00
core : : stringc materialName = reader - > getAttributeValue ( " material " ) ;
2008-01-23 09:15:15 -08:00
core : : stringc polygonType = reader - > getNodeName ( ) ;
2008-11-13 09:35:17 -08:00
const int polygonCount = reader - > getAttributeValueAsInt ( " count " ) ; // Not useful because it only determines the number of primitives, which have arbitrary vertices in case of polygon
2007-05-20 11:03:49 -07:00
core : : array < SPolygon > polygons ;
2008-01-20 16:35:47 -08:00
core : : array < int > vCounts ;
2007-05-20 11:03:49 -07:00
bool parsePolygonOK = false ;
2008-01-20 16:35:47 -08:00
bool parseVcountOK = false ;
2007-08-08 09:30:10 -07:00
u32 inputSemanticCount = 0 ;
2008-01-24 09:24:52 -08:00
bool unresolvedInput = false ;
u32 maxOffset = 0 ;
Inputs . clear ( ) ;
2007-05-20 11:03:49 -07:00
2008-01-24 09:24:52 -08:00
// read all <input> and primitives
2007-05-20 11:03:49 -07:00
if ( ! reader - > isEmptyElement ( ) )
while ( reader - > read ( ) )
{
const char * nodeName = reader - > getNodeName ( ) ;
if ( reader - > getNodeType ( ) = = io : : EXN_ELEMENT )
{
2008-01-20 16:24:28 -08:00
// polygon node may contain params
2007-05-20 11:03:49 -07:00
if ( inputTagName = = nodeName )
{
// read input tag
readColladaInput ( reader ) ;
2008-01-24 09:24:52 -08:00
// resolve input source
SColladaInput & inp = Inputs . getLast ( ) ;
core : : stringc sourceArrayURI ;
2007-05-20 11:03:49 -07:00
2008-01-24 09:24:52 -08:00
// get input source array id, if it is a vertex input, take
// the <vertex><input>-source attribute.
if ( inp . Semantic = = ECIS_VERTEX )
sourceArrayURI = vertexPositionSource ;
else
sourceArrayURI = inp . Source ;
2007-05-20 11:03:49 -07:00
2008-01-24 09:24:52 -08:00
uriToId ( sourceArrayURI ) ;
2007-05-20 11:03:49 -07:00
2008-01-24 09:24:52 -08:00
// find source array (we'll ignore accessors for this implementation)
u32 s ;
for ( s = 0 ; s < sources . size ( ) ; + + s )
{
if ( sources [ s ] . Id = = sourceArrayURI )
{
// slot found
inp . Data = sources [ s ] . Array . Data . pointer ( ) ;
inp . Stride = sources [ s ] . Accessors [ 0 ] . Stride ;
break ;
}
}
2007-05-20 11:03:49 -07:00
2008-01-24 09:24:52 -08:00
if ( s = = sources . size ( ) )
{
os : : Printer : : log ( " COLLADA Warning, polygon input source not found " ,
sourceArrayURI . c_str ( ) ) ;
unresolvedInput = true ;
}
else
{
2007-05-20 11:03:49 -07:00
# ifdef COLLADA_READER_DEBUG
// print slot
2008-01-23 09:15:15 -08:00
core : : stringc tmp = " Added slot " ;
2008-01-24 09:24:52 -08:00
tmp + = inputSemanticNames [ inp . Semantic ] ;
2008-01-23 09:15:15 -08:00
tmp + = " sourceArray: " ;
tmp + = sourceArrayURI ;
os : : Printer : : log ( tmp . c_str ( ) ) ;
2007-05-20 11:03:49 -07:00
# endif
}
2008-01-24 09:24:52 -08:00
maxOffset = core : : max_ ( maxOffset , inp . Offset ) ;
+ + inputSemanticCount ;
}
2007-05-20 11:03:49 -07:00
else
2008-01-20 16:24:28 -08:00
if ( primitivesName = = nodeName )
2007-05-20 11:03:49 -07:00
{
parsePolygonOK = true ;
polygons . push_back ( SPolygon ( ) ) ;
2008-11-13 09:35:17 -08:00
}
2008-01-20 16:35:47 -08:00
else
if ( vcountName = = nodeName )
{
parseVcountOK = true ;
} // end is polygon node
2007-05-20 11:03:49 -07:00
} // end is element node
else
if ( reader - > getNodeType ( ) = = io : : EXN_ELEMENT_END )
{
2008-01-20 16:24:28 -08:00
if ( primitivesName = = nodeName )
2007-05-20 11:03:49 -07:00
parsePolygonOK = false ; // end parsing a polygon
else
2008-01-20 16:35:47 -08:00
if ( vcountName = = nodeName )
parseVcountOK = false ; // end parsing vcounts
else
2008-01-23 09:15:15 -08:00
if ( polygonType = = nodeName )
2007-05-20 11:03:49 -07:00
break ; // cancel out and create mesh
} // end is element end
else
if ( reader - > getNodeType ( ) = = io : : EXN_TEXT )
{
2008-01-20 16:35:47 -08:00
if ( parseVcountOK )
2007-05-20 11:03:49 -07:00
{
core : : stringc data = reader - > getNodeData ( ) ;
2008-01-23 09:15:15 -08:00
data . trim ( ) ;
2007-05-20 11:03:49 -07:00
const c8 * p = & data [ 0 ] ;
while ( * p )
{
findNextNoneWhiteSpace ( & p ) ;
2007-08-08 09:30:10 -07:00
if ( * p )
2008-01-20 16:35:47 -08:00
vCounts . push_back ( readInt ( & p ) ) ;
}
parseVcountOK = false ;
}
else
if ( parsePolygonOK & & polygons . size ( ) )
{
core : : stringc data = reader - > getNodeData ( ) ;
2008-01-23 09:15:15 -08:00
data . trim ( ) ;
2008-01-20 16:35:47 -08:00
const c8 * p = & data [ 0 ] ;
SPolygon & poly = polygons . getLast ( ) ;
2008-11-13 09:35:17 -08:00
poly . Indices . reallocate ( polygonCount * ( maxOffset + 1 ) * 3 ) ;
2008-01-23 09:15:15 -08:00
2008-01-20 16:35:47 -08:00
if ( vCounts . empty ( ) )
{
while ( * p )
{
findNextNoneWhiteSpace ( & p ) ;
2007-08-08 09:30:10 -07:00
poly . Indices . push_back ( readInt ( & p ) ) ;
2008-01-20 16:35:47 -08:00
}
}
else
{
for ( u32 i = 0 ; i < vCounts . size ( ) ; i + + )
{
int polyVCount = vCounts [ i ] ;
2008-01-23 09:15:15 -08:00
2008-01-20 16:35:47 -08:00
core : : array < int > polyCorners ;
for ( u32 j = 0 ; j < polyVCount * inputSemanticCount ; j + + )
{
if ( ! * p )
break ;
findNextNoneWhiteSpace ( & p ) ;
polyCorners . push_back ( readInt ( & p ) ) ;
}
while ( polyCorners . size ( ) > = 3 * inputSemanticCount )
{
// add one triangle's worth of indices
for ( u32 k = 0 ; k < inputSemanticCount * 3 ; + + k )
{
poly . Indices . push_back ( polyCorners [ k ] ) ;
}
// remove one corner from our poly
polyCorners . erase ( inputSemanticCount , inputSemanticCount ) ;
}
polyCorners . clear ( ) ;
}
vCounts . clear ( ) ;
2007-05-20 11:03:49 -07:00
}
parsePolygonOK = false ;
}
}
} // end while reader->read()
2008-01-24 09:24:52 -08:00
if ( inputSemanticCount = = 0 | | unresolvedInput )
2007-05-20 11:03:49 -07:00
return ; // we cannot create the mesh if one of the input semantics wasn't found.
if ( ! polygons . size ( ) )
return ; // cancel if there are no polygons anyway.
2008-01-24 09:24:52 -08:00
// analyze content of Inputs to create a fitting mesh buffer
2007-05-20 11:03:49 -07:00
2007-09-06 22:55:34 -07:00
u32 u ;
2007-08-08 09:30:10 -07:00
u32 textureCoordSetCount = 0 ;
bool normalSlotCount = false ;
u32 secondTexCoordSetIndex = 0xFFFFFFFF ;
2007-05-20 11:03:49 -07:00
2008-01-24 09:24:52 -08:00
for ( u = 0 ; u < Inputs . size ( ) ; + + u )
2007-05-20 11:03:49 -07:00
{
2008-01-24 09:24:52 -08:00
if ( Inputs [ u ] . Semantic = = ECIS_TEXCOORD | | Inputs [ u ] . Semantic = = ECIS_UV )
2007-05-20 11:03:49 -07:00
{
+ + textureCoordSetCount ;
if ( textureCoordSetCount = = 2 )
2007-09-06 22:55:34 -07:00
secondTexCoordSetIndex = u ;
2007-05-20 11:03:49 -07:00
}
else
2008-01-24 09:24:52 -08:00
if ( Inputs [ u ] . Semantic = = ECIS_NORMAL )
2007-08-08 09:30:10 -07:00
normalSlotCount = true ;
2007-05-20 11:03:49 -07:00
}
// if there is more than one texture coordinate set, create a lightmap mesh buffer,
// otherwise use a standard mesh buffer
scene : : IMeshBuffer * buffer = 0 ;
2008-01-24 09:24:52 -08:00
+ + maxOffset ; // +1 to jump to the next value
2007-05-20 11:03:49 -07:00
2008-11-13 09:35:17 -08:00
if ( textureCoordSetCount < 2 )
2007-05-20 11:03:49 -07:00
{
// standard mesh buffer
scene : : SMeshBuffer * mbuffer = new SMeshBuffer ( ) ;
buffer = mbuffer ;
2008-01-20 16:35:47 -08:00
core : : map < video : : S3DVertex , int > vertMap ;
2007-09-06 22:55:34 -07:00
for ( u32 i = 0 ; i < polygons . size ( ) ; + + i )
2007-05-20 11:03:49 -07:00
{
2008-01-23 09:15:15 -08:00
core : : array < u16 > indices ;
2008-01-24 16:12:46 -08:00
const u32 vertexCount = polygons [ i ] . Indices . size ( ) / maxOffset ;
mbuffer - > Vertices . reallocate ( mbuffer - > Vertices . size ( ) + vertexCount ) ;
2008-01-23 09:15:15 -08:00
2007-08-08 09:30:10 -07:00
// for all index/semantic groups
2008-01-24 09:24:52 -08:00
for ( u32 v = 0 ; v < polygons [ i ] . Indices . size ( ) ; v + = maxOffset )
2007-05-20 11:03:49 -07:00
{
video : : S3DVertex vtx ;
2007-08-08 09:30:10 -07:00
vtx . Color . set ( 255 , 255 , 255 , 255 ) ;
2007-05-20 11:03:49 -07:00
// for all input semantics
2008-01-24 09:24:52 -08:00
for ( u32 k = 0 ; k < Inputs . size ( ) ; + + k )
2007-05-20 11:03:49 -07:00
{
2008-01-24 09:24:52 -08:00
if ( ! Inputs [ k ] . Data )
2007-08-29 09:09:32 -07:00
continue ;
2007-05-20 11:03:49 -07:00
// build vertex from input semantics.
2008-01-24 09:24:52 -08:00
const u32 idx = Inputs [ k ] . Stride * polygons [ i ] . Indices [ v + Inputs [ k ] . Offset ] ;
2007-05-20 11:03:49 -07:00
2008-01-24 09:24:52 -08:00
switch ( Inputs [ k ] . Semantic )
2007-05-20 11:03:49 -07:00
{
case ECIS_POSITION :
case ECIS_VERTEX :
2008-01-24 09:24:52 -08:00
vtx . Pos . X = Inputs [ k ] . Data [ idx + 0 ] ;
2008-11-13 09:35:17 -08:00
if ( FlipAxis )
{
vtx . Pos . Z = Inputs [ k ] . Data [ idx + 1 ] ;
vtx . Pos . Y = Inputs [ k ] . Data [ idx + 2 ] ;
}
else
{
vtx . Pos . Y = Inputs [ k ] . Data [ idx + 1 ] ;
vtx . Pos . Z = Inputs [ k ] . Data [ idx + 2 ] ;
}
2007-05-20 11:03:49 -07:00
break ;
case ECIS_NORMAL :
2008-01-24 09:24:52 -08:00
vtx . Normal . X = Inputs [ k ] . Data [ idx + 0 ] ;
2008-11-13 09:35:17 -08:00
if ( FlipAxis )
{
vtx . Normal . Z = Inputs [ k ] . Data [ idx + 1 ] ;
vtx . Normal . Y = Inputs [ k ] . Data [ idx + 2 ] ;
}
else
{
vtx . Normal . Y = Inputs [ k ] . Data [ idx + 1 ] ;
vtx . Normal . Z = Inputs [ k ] . Data [ idx + 2 ] ;
}
2007-05-20 11:03:49 -07:00
break ;
case ECIS_TEXCOORD :
case ECIS_UV :
2008-01-24 09:24:52 -08:00
vtx . TCoords . X = Inputs [ k ] . Data [ idx + 0 ] ;
2008-11-13 09:35:17 -08:00
vtx . TCoords . Y = - Inputs [ k ] . Data [ idx + 1 ] ;
2007-05-20 11:03:49 -07:00
break ;
case ECIS_TANGENT :
break ;
default :
break ;
}
}
2008-01-20 16:35:47 -08:00
//first, try to find this vertex in the mesh
core : : map < video : : S3DVertex , int > : : Node * n = vertMap . find ( vtx ) ;
if ( n )
{
2008-01-23 09:15:15 -08:00
indices . push_back ( n - > getValue ( ) ) ;
2008-01-20 16:35:47 -08:00
}
else
{
2008-01-23 09:15:15 -08:00
indices . push_back ( mbuffer - > getVertexCount ( ) ) ;
2008-01-20 16:35:47 -08:00
mbuffer - > Vertices . push_back ( vtx ) ;
vertMap . insert ( vtx , mbuffer - > getVertexCount ( ) - 1 ) ;
}
2007-05-20 11:03:49 -07:00
} // end for all vertices
2008-01-23 09:15:15 -08:00
if ( polygonsSectionName = = polygonType & &
2008-11-13 09:35:17 -08:00
indices . size ( ) > 3 )
2008-01-23 09:15:15 -08:00
{
// need to tesselate for polygons of 4 or more vertices
// for now we naively turn interpret it as a triangle fan
// as full tesselation is problematic
2008-11-13 09:35:17 -08:00
if ( FlipAxis )
{
for ( u32 i = indices . size ( ) - 3 ; i > 0 ; - - i )
{
mbuffer - > Indices . push_back ( indices [ 0 ] ) ;
mbuffer - > Indices . push_back ( indices [ i + 2 ] ) ;
mbuffer - > Indices . push_back ( indices [ i + 1 ] ) ;
}
}
else
2008-01-23 09:15:15 -08:00
{
2008-11-13 09:35:17 -08:00
for ( u32 i = 0 ; i + 2 < indices . size ( ) ; + + i )
{
mbuffer - > Indices . push_back ( indices [ 0 ] ) ;
mbuffer - > Indices . push_back ( indices [ i + 1 ] ) ;
mbuffer - > Indices . push_back ( indices [ i + 2 ] ) ;
}
2008-01-23 09:15:15 -08:00
}
}
else
{
// it's just triangles
2008-11-13 09:35:17 -08:00
for ( u32 i = 0 ; i < indices . size ( ) ; i + = 3 )
2008-01-23 09:15:15 -08:00
{
2008-11-13 09:35:17 -08:00
if ( FlipAxis )
{
mbuffer - > Indices . push_back ( indices [ i + 2 ] ) ;
mbuffer - > Indices . push_back ( indices [ i + 1 ] ) ;
2008-11-16 16:39:33 -08:00
mbuffer - > Indices . push_back ( indices [ i + 0 ] ) ;
2008-11-13 09:35:17 -08:00
}
else
{
mbuffer - > Indices . push_back ( indices [ i + 0 ] ) ;
mbuffer - > Indices . push_back ( indices [ i + 1 ] ) ;
mbuffer - > Indices . push_back ( indices [ i + 2 ] ) ;
}
2008-01-23 09:15:15 -08:00
}
}
2007-05-20 11:03:49 -07:00
} // end for all polygons
}
else
{
// lightmap mesh buffer
scene : : SMeshBufferLightMap * mbuffer = new SMeshBufferLightMap ( ) ;
buffer = mbuffer ;
2007-09-07 01:40:19 -07:00
for ( u32 i = 0 ; i < polygons . size ( ) ; + + i )
2007-05-20 11:03:49 -07:00
{
2008-01-24 16:12:46 -08:00
const u32 vertexCount = polygons [ i ] . Indices . size ( ) / maxOffset ;
mbuffer - > Vertices . reallocate ( mbuffer - > Vertices . size ( ) + vertexCount ) ;
2007-05-20 11:03:49 -07:00
// for all vertices in array
2008-01-24 09:24:52 -08:00
for ( u32 v = 0 ; v < polygons [ i ] . Indices . size ( ) ; v + = maxOffset )
2007-05-20 11:03:49 -07:00
{
video : : S3DVertex2TCoords vtx ;
vtx . Color . set ( 100 , 255 , 255 , 255 ) ;
// for all input semantics
2008-01-24 09:24:52 -08:00
for ( u32 k = 0 ; k < Inputs . size ( ) ; + + k )
2007-05-20 11:03:49 -07:00
{
// build vertex from input semantics.
2008-01-24 09:24:52 -08:00
const u32 idx = Inputs [ k ] . Stride * polygons [ i ] . Indices [ v + Inputs [ k ] . Offset ] ;
2007-05-20 11:03:49 -07:00
2008-01-24 09:24:52 -08:00
switch ( Inputs [ k ] . Semantic )
2007-05-20 11:03:49 -07:00
{
case ECIS_POSITION :
case ECIS_VERTEX :
2008-01-24 09:24:52 -08:00
vtx . Pos . X = Inputs [ k ] . Data [ idx + 0 ] ;
2008-11-13 09:35:17 -08:00
if ( FlipAxis )
{
vtx . Pos . Z = Inputs [ k ] . Data [ idx + 1 ] ;
vtx . Pos . Y = Inputs [ k ] . Data [ idx + 2 ] ;
}
else
{
vtx . Pos . Y = Inputs [ k ] . Data [ idx + 1 ] ;
vtx . Pos . Z = Inputs [ k ] . Data [ idx + 2 ] ;
}
2007-05-20 11:03:49 -07:00
break ;
case ECIS_NORMAL :
2008-01-24 09:24:52 -08:00
vtx . Normal . X = Inputs [ k ] . Data [ idx + 0 ] ;
2008-11-13 09:35:17 -08:00
if ( FlipAxis )
{
vtx . Normal . Z = Inputs [ k ] . Data [ idx + 1 ] ;
vtx . Normal . Y = Inputs [ k ] . Data [ idx + 2 ] ;
}
else
{
vtx . Normal . Y = Inputs [ k ] . Data [ idx + 1 ] ;
vtx . Normal . Z = Inputs [ k ] . Data [ idx + 2 ] ;
}
2007-05-20 11:03:49 -07:00
break ;
case ECIS_TEXCOORD :
case ECIS_UV :
if ( k = = secondTexCoordSetIndex )
{
2008-01-24 09:24:52 -08:00
vtx . TCoords2 . X = Inputs [ k ] . Data [ idx + 0 ] ;
2008-11-13 09:35:17 -08:00
vtx . TCoords2 . Y = - Inputs [ k ] . Data [ idx + 1 ] ;
2007-05-20 11:03:49 -07:00
}
else
{
2008-01-24 09:24:52 -08:00
vtx . TCoords . X = Inputs [ k ] . Data [ idx + 0 ] ;
2008-11-13 09:35:17 -08:00
vtx . TCoords . Y = - Inputs [ k ] . Data [ idx + 1 ] ;
2007-05-20 11:03:49 -07:00
}
break ;
case ECIS_TANGENT :
break ;
default :
break ;
}
}
mbuffer - > Vertices . push_back ( vtx ) ;
} // end for all vertices
// add vertex indices
2007-08-08 09:30:10 -07:00
const u32 oldVertexCount = mbuffer - > Vertices . size ( ) - vertexCount ;
for ( u32 face = 0 ; face < vertexCount - 2 ; + + face )
2007-05-20 11:03:49 -07:00
{
mbuffer - > Indices . push_back ( oldVertexCount + 0 ) ;
mbuffer - > Indices . push_back ( oldVertexCount + 1 + face ) ;
mbuffer - > Indices . push_back ( oldVertexCount + 2 + face ) ;
}
} // end for all polygons
}
2008-01-24 16:12:46 -08:00
const SColladaMaterial * m = findMaterial ( materialName ) ;
if ( m )
2008-01-25 09:01:42 -08:00
{
2008-01-24 16:12:46 -08:00
buffer - > getMaterial ( ) = m - > Mat ;
2008-11-13 09:35:17 -08:00
SMesh tmpmesh ;
tmpmesh . addMeshBuffer ( buffer ) ;
SceneManager - > getMeshManipulator ( ) - > setVertexColors ( & tmpmesh , m - > Mat . DiffuseColor ) ;
2008-01-25 09:01:42 -08:00
if ( m - > Transparency ! = 1.0f )
SceneManager - > getMeshManipulator ( ) - > setVertexColorAlpha ( & tmpmesh , core : : floor32 ( m - > Transparency * 255.0f ) ) ;
}
2008-01-23 09:15:15 -08:00
// add future bind reference for the material
2008-11-13 09:35:17 -08:00
core : : stringc meshbufferReference = geometryId + " / " + materialName ;
if ( ! MaterialsToBind . find ( meshbufferReference ) )
2008-01-23 09:15:15 -08:00
{
2008-11-13 09:35:17 -08:00
MaterialsToBind [ meshbufferReference ] = MeshesToBind . size ( ) ;
2008-01-23 09:15:15 -08:00
MeshesToBind . push_back ( core : : array < irr : : scene : : IMeshBuffer * > ( ) ) ;
}
2008-11-13 09:35:17 -08:00
MeshesToBind [ MaterialsToBind [ meshbufferReference ] ] . push_back ( buffer ) ;
2008-01-23 09:15:15 -08:00
2007-05-20 11:03:49 -07:00
// calculate normals if there is no slot for it
if ( ! normalSlotCount )
2008-11-13 09:35:17 -08:00
SceneManager - > getMeshManipulator ( ) - > recalculateNormals ( buffer , true ) ;
2007-05-20 11:03:49 -07:00
// recalculate bounding box
2007-08-13 16:53:12 -07:00
buffer - > recalculateBoundingBox ( ) ;
2007-05-20 11:03:49 -07:00
// add mesh buffer
mesh - > addMeshBuffer ( buffer ) ;
buffer - > drop ( ) ;
}
//! reads a <light> element and stores it as prefab
void CColladaFileLoader : : readLightPrefab ( io : : IXMLReaderUTF8 * reader )
{
2007-08-29 09:09:32 -07:00
# ifdef COLLADA_READER_DEBUG
os : : Printer : : log ( " COLLADA reading light prefab " ) ;
# endif
2008-01-24 09:24:52 -08:00
CLightPrefab * prefab = new CLightPrefab ( readId ( reader ) ) ;
2007-05-20 11:03:49 -07:00
if ( ! reader - > isEmptyElement ( ) )
{
2008-11-13 09:35:17 -08:00
if ( Version > = 10400 ) // start with 1.4
{
while ( reader - > read ( ) )
{
if ( reader - > getNodeType ( ) = = io : : EXN_ELEMENT )
{
if ( pointSectionName = = reader - > getNodeName ( ) )
prefab - > LightData . Type = video : : ELT_POINT ;
else
if ( directionalSectionName = = reader - > getNodeName ( ) )
prefab - > LightData . Type = video : : ELT_DIRECTIONAL ;
else
if ( spotSectionName = = reader - > getNodeName ( ) )
prefab - > LightData . Type = video : : ELT_SPOT ;
else
if ( ambientSectionName = = reader - > getNodeName ( ) )
prefab - > LightData . Type = video : : ELT_POINT ; // TODO: This needs some change
else
if ( colorNodeName = = reader - > getNodeName ( ) )
prefab - > LightData . DiffuseColor = readColorNode ( reader ) ;
else
if ( constantAttenuationNodeName = = reader - > getNodeName ( ) )
readFloatsInsideElement ( reader , & prefab - > LightData . Attenuation . X , 1 ) ;
else
if ( linearAttenuationNodeName = = reader - > getNodeName ( ) )
readFloatsInsideElement ( reader , & prefab - > LightData . Attenuation . Y , 1 ) ;
else
if ( quadraticAttenuationNodeName = = reader - > getNodeName ( ) )
readFloatsInsideElement ( reader , & prefab - > LightData . Attenuation . Z , 1 ) ;
else
if ( falloffAngleNodeName = = reader - > getNodeName ( ) )
{
readFloatsInsideElement ( reader , & prefab - > LightData . OuterCone , 1 ) ;
prefab - > LightData . OuterCone * = core : : DEGTORAD ;
}
else
if ( falloffExponentNodeName = = reader - > getNodeName ( ) )
readFloatsInsideElement ( reader , & prefab - > LightData . Falloff , 1 ) ;
}
else
if ( reader - > getNodeType ( ) = = io : : EXN_ELEMENT_END )
{
if ( ( pointSectionName = = reader - > getNodeName ( ) ) | |
( directionalSectionName = = reader - > getNodeName ( ) ) | |
( spotSectionName = = reader - > getNodeName ( ) ) | |
( ambientSectionName = = reader - > getNodeName ( ) ) )
break ;
}
}
}
else
{
readColladaParameters ( reader , lightPrefabName ) ;
2007-05-20 11:03:49 -07:00
2008-11-13 09:35:17 -08:00
SColladaParam * p = getColladaParameter ( ECPN_COLOR ) ;
if ( p & & p - > Type = = ECPT_FLOAT3 )
prefab - > LightData . DiffuseColor . set ( p - > Floats [ 0 ] , p - > Floats [ 1 ] , p - > Floats [ 2 ] ) ;
}
2007-05-20 11:03:49 -07:00
}
Prefabs . push_back ( prefab ) ;
}
//! returns a collada parameter or none if not found
SColladaParam * CColladaFileLoader : : getColladaParameter ( ECOLLADA_PARAM_NAME name )
{
2008-01-24 09:24:52 -08:00
for ( u32 i = 0 ; i < ColladaParameters . size ( ) ; + + i )
if ( ColladaParameters [ i ] . Name = = name )
return & ColladaParameters [ i ] ;
2007-05-20 11:03:49 -07:00
return 0 ;
}
//! returns a collada input or none if not found
SColladaInput * CColladaFileLoader : : getColladaInput ( ECOLLADA_INPUT_SEMANTIC input )
{
2007-08-08 09:30:10 -07:00
for ( u32 i = 0 ; i < Inputs . size ( ) ; + + i )
2007-05-20 11:03:49 -07:00
if ( Inputs [ i ] . Semantic = = input )
return & Inputs [ i ] ;
return 0 ;
}
//! reads a collada input tag and adds it to the input parameter
void CColladaFileLoader : : readColladaInput ( io : : IXMLReaderUTF8 * reader )
{
// parse param
SColladaInput p ;
// get type
core : : stringc semanticName = reader - > getAttributeValue ( " semantic " ) ;
2007-08-08 09:30:10 -07:00
for ( u32 i = 0 ; inputSemanticNames [ i ] ; + + i )
2008-01-24 09:24:52 -08:00
{
2007-05-20 11:03:49 -07:00
if ( semanticName = = inputSemanticNames [ i ] )
{
p . Semantic = ( ECOLLADA_INPUT_SEMANTIC ) i ;
break ;
}
2008-01-24 09:24:52 -08:00
}
2007-05-20 11:03:49 -07:00
// get source
p . Source = reader - > getAttributeValue ( " source " ) ;
2008-01-24 09:24:52 -08:00
p . Offset = ( u32 ) reader - > getAttributeValueAsInt ( " offset " ) ;
p . Set = ( u32 ) reader - > getAttributeValueAsInt ( " set " ) ;
2007-05-20 11:03:49 -07:00
// add input
Inputs . push_back ( p ) ;
}
2007-08-08 09:30:10 -07:00
//! parses all collada inputs inside an element and stores them in Inputs
2007-05-20 11:03:49 -07:00
void CColladaFileLoader : : readColladaInputs ( io : : IXMLReaderUTF8 * reader , const core : : stringc & parentName )
{
Inputs . clear ( ) ;
while ( reader - > read ( ) )
{
if ( reader - > getNodeType ( ) = = io : : EXN_ELEMENT & &
inputTagName = = reader - > getNodeName ( ) )
{
readColladaInput ( reader ) ;
}
else
if ( reader - > getNodeType ( ) = = io : : EXN_ELEMENT_END )
{
if ( parentName = = reader - > getNodeName ( ) )
return ; // end of parent reached
}
} // end while reader->read();
}
//! parses all collada parameters inside an element and stores them in Parameters
void CColladaFileLoader : : readColladaParameters ( io : : IXMLReaderUTF8 * reader ,
2007-08-29 09:09:32 -07:00
const core : : stringc & parentName )
2007-05-20 11:03:49 -07:00
{
2008-01-24 09:24:52 -08:00
ColladaParameters . clear ( ) ;
2007-05-20 11:03:49 -07:00
const char * const paramNames [ ] = { " COLOR " , " AMBIENT " , " DIFFUSE " ,
" SPECULAR " , " SHININESS " , " YFOV " , " ZNEAR " , " ZFAR " , 0 } ;
const char * const typeNames [ ] = { " float " , " float2 " , " float3 " , 0 } ;
while ( reader - > read ( ) )
{
const char * nodeName = reader - > getNodeName ( ) ;
if ( reader - > getNodeType ( ) = = io : : EXN_ELEMENT & &
paramTagName = = nodeName )
{
// parse param
SColladaParam p ;
// get type
2007-08-08 09:30:10 -07:00
u32 i ;
2007-05-20 11:03:49 -07:00
core : : stringc typeName = reader - > getAttributeValue ( " type " ) ;
for ( i = 0 ; typeNames [ i ] ; + + i )
if ( typeName = = typeNames [ i ] )
{
p . Type = ( ECOLLADA_PARAM_TYPE ) i ;
break ;
}
// get name
core : : stringc nameName = reader - > getAttributeValue ( " name " ) ;
for ( i = 0 ; typeNames [ i ] ; + + i )
if ( nameName = = paramNames [ i ] )
{
p . Name = ( ECOLLADA_PARAM_NAME ) i ;
break ;
}
// read parameter data inside parameter tags
switch ( p . Type )
{
case ECPT_FLOAT :
case ECPT_FLOAT2 :
case ECPT_FLOAT3 :
case ECPT_FLOAT4 :
readFloatsInsideElement ( reader , p . Floats , p . Type - ECPT_FLOAT + 1 ) ;
break ;
// TODO: other types of data (ints, bools or whatever)
default :
break ;
}
// add param
2008-01-24 09:24:52 -08:00
ColladaParameters . push_back ( p ) ;
2007-05-20 11:03:49 -07:00
}
else
if ( reader - > getNodeType ( ) = = io : : EXN_ELEMENT_END )
{
if ( parentName = = reader - > getNodeName ( ) )
return ; // end of parent reached
}
} // end while reader->read();
}
//! parses a float from a char pointer and moves the pointer
//! to the end of the parsed float
inline f32 CColladaFileLoader : : readFloat ( const c8 * * p )
{
f32 ftmp ;
* p = core : : fast_atof_move ( * p , ftmp ) ;
return ftmp ;
}
2008-01-23 09:15:15 -08:00
2007-05-20 11:03:49 -07:00
//! parses an int from a char pointer and moves the pointer to
//! the end of the parsed float
inline s32 CColladaFileLoader : : readInt ( const c8 * * p )
{
return ( s32 ) readFloat ( p ) ;
}
2008-01-23 09:15:15 -08:00
2007-05-20 11:03:49 -07:00
//! places pointer to next begin of a token
void CColladaFileLoader : : findNextNoneWhiteSpace ( const c8 * * start )
{
const c8 * p = * start ;
while ( * p & & ( * p = = ' ' | | * p = = ' \n ' | | * p = = ' \r ' | | * p = = ' \t ' ) )
+ + p ;
// TODO: skip comments <!-- -->
* start = p ;
}
//! reads floats from inside of xml element until end of xml element
2007-08-08 09:30:10 -07:00
void CColladaFileLoader : : readFloatsInsideElement ( io : : IXMLReaderUTF8 * reader , f32 * floats , u32 count )
2007-05-20 11:03:49 -07:00
{
if ( reader - > isEmptyElement ( ) )
return ;
while ( reader - > read ( ) )
{
// TODO: check for comments inside the element
// and ignore them.
if ( reader - > getNodeType ( ) = = io : : EXN_TEXT )
{
// parse float data
core : : stringc data = reader - > getNodeData ( ) ;
2008-01-23 09:15:15 -08:00
data . trim ( ) ;
2007-05-20 11:03:49 -07:00
const c8 * p = & data [ 0 ] ;
2007-08-08 09:30:10 -07:00
for ( u32 i = 0 ; i < count ; + + i )
2007-05-20 11:03:49 -07:00
{
findNextNoneWhiteSpace ( & p ) ;
2007-08-08 09:30:10 -07:00
if ( * p )
floats [ i ] = readFloat ( & p ) ;
else
floats [ i ] = 0.0f ;
2007-05-20 11:03:49 -07:00
}
}
else
if ( reader - > getNodeType ( ) = = io : : EXN_ELEMENT_END )
break ; // end parsing text
}
}
2008-01-23 09:15:15 -08:00
//! reads ints from inside of xml element until end of xml element
void CColladaFileLoader : : readIntsInsideElement ( io : : IXMLReaderUTF8 * reader , s32 * ints , u32 count )
{
if ( reader - > isEmptyElement ( ) )
return ;
while ( reader - > read ( ) )
{
// TODO: check for comments inside the element
// and ignore them.
if ( reader - > getNodeType ( ) = = io : : EXN_TEXT )
{
// parse float data
core : : stringc data = reader - > getNodeData ( ) ;
data . trim ( ) ;
const c8 * p = & data [ 0 ] ;
for ( u32 i = 0 ; i < count ; + + i )
{
findNextNoneWhiteSpace ( & p ) ;
if ( * p )
ints [ i ] = readInt ( & p ) ;
else
ints [ i ] = 0 ;
}
}
else
if ( reader - > getNodeType ( ) = = io : : EXN_ELEMENT_END )
break ; // end parsing text
}
}
video : : SColorf CColladaFileLoader : : readColorNode ( io : : IXMLReaderUTF8 * reader )
{
if ( reader - > getNodeType ( ) = = io : : EXN_ELEMENT & &
colorNodeName = = reader - > getNodeName ( ) )
{
f32 color [ 4 ] ;
readFloatsInsideElement ( reader , color , 4 ) ;
2008-11-13 09:35:17 -08:00
return video : : SColorf ( color [ 0 ] , color [ 1 ] , color [ 2 ] , color [ 3 ] ) ;
2008-01-23 09:15:15 -08:00
}
2008-11-13 09:35:17 -08:00
return video : : SColorf ( ) ;
2008-01-23 09:15:15 -08:00
}
f32 CColladaFileLoader : : readFloatNode ( io : : IXMLReaderUTF8 * reader )
{
2008-01-24 09:24:52 -08:00
# ifdef COLLADA_READER_DEBUG
os : : Printer : : log ( " COLLADA reading <float> " ) ;
# endif
2008-01-23 09:15:15 -08:00
f32 result = 0.0f ;
if ( reader - > getNodeType ( ) = = io : : EXN_ELEMENT & &
floatNodeName = = reader - > getNodeName ( ) )
{
readFloatsInsideElement ( reader , & result , 1 ) ;
}
return result ;
}
2007-05-20 11:03:49 -07:00
//! clears all loaded data
void CColladaFileLoader : : clearData ( )
{
// delete all prefabs
2007-08-08 09:30:10 -07:00
for ( u32 i = 0 ; i < Prefabs . size ( ) ; + + i )
2007-05-20 11:03:49 -07:00
Prefabs [ i ] - > drop ( ) ;
Prefabs . clear ( ) ;
// clear all parameters
2008-01-24 09:24:52 -08:00
ColladaParameters . clear ( ) ;
2007-05-20 11:03:49 -07:00
2007-08-08 09:30:10 -07:00
// clear all materials
Images . clear ( ) ;
// clear all materials
Textures . clear ( ) ;
2007-05-20 11:03:49 -07:00
// clear all materials
Materials . clear ( ) ;
// clear all inputs
Inputs . clear ( ) ;
2008-01-23 09:15:15 -08:00
// clear all effects
Effects . clear ( ) ;
// clear all the materials to bind
MaterialsToBind . clear ( ) ;
MeshesToBind . clear ( ) ;
2007-05-20 11:03:49 -07:00
}
2008-01-23 09:15:15 -08:00
2007-05-20 11:03:49 -07:00
//! changes the XML URI into an internal id
void CColladaFileLoader : : uriToId ( core : : stringc & str )
{
// currently, we only remove the # from the begin if there
// because we simply don't support referencing other files.
if ( ! str . size ( ) )
return ;
if ( str [ 0 ] = = ' # ' )
str . erase ( 0 ) ;
}
2008-01-24 09:24:52 -08:00
//! read Collada Id, uses id or name if id is missing
core : : stringc CColladaFileLoader : : readId ( io : : IXMLReaderUTF8 * reader )
{
core : : stringc id = reader - > getAttributeValue ( " id " ) ;
if ( id . size ( ) = = 0 )
id = reader - > getAttributeValue ( " name " ) ;
return id ;
}
//! create an Irrlicht texture from the reference
video : : ITexture * CColladaFileLoader : : getTextureFromImage ( core : : stringc uri )
{
2008-01-25 09:01:42 -08:00
# ifdef COLLADA_READER_DEBUG
os : : Printer : : log ( " COLLADA searching texture " , uri . c_str ( ) ) ;
# endif
2008-01-29 08:59:36 -08:00
video : : IVideoDriver * driver = SceneManager - > getVideoDriver ( ) ;
2008-01-24 09:24:52 -08:00
for ( ; ; )
{
uriToId ( uri ) ;
for ( u32 i = 0 ; i < Images . size ( ) ; + + i )
{
if ( uri = = Images [ i ] . Id )
{
if ( Images [ i ] . Source . size ( ) & & Images [ i ] . SourceIsFilename )
2008-02-20 09:17:42 -08:00
{
if ( FileSystem - > existFile ( Images [ i ] . Source . c_str ( ) ) )
return driver - > getTexture ( Images [ i ] . Source . c_str ( ) ) ;
return driver - > getTexture ( ( FileSystem - > getFileDir ( CurrentlyLoadingMesh ) + " / " + Images [ i ] . Source ) . c_str ( ) ) ;
}
2008-01-24 09:24:52 -08:00
else
if ( Images [ i ] . Source . size ( ) )
{
//const u32 size = Images[i].Dimension.getArea();
const u32 size = Images [ i ] . Dimension . Width * Images [ i ] . Dimension . Height ; ;
u32 * data = new u32 [ size ] ; // we assume RGBA
u32 * ptrdest = data ;
const c8 * ptrsrc = Images [ i ] . Source . c_str ( ) ;
for ( u32 j = 0 ; j < size ; + + j )
{
sscanf ( ptrsrc , " %x " , ptrdest ) ;
+ + ptrdest ;
ptrsrc + = 4 ;
}
2008-01-29 08:59:36 -08:00
video : : IImage * img = driver - > createImageFromData ( video : : ECF_A8R8G8B8 , Images [ i ] . Dimension , data , true , true ) ;
video : : ITexture * tex = driver - > addTexture ( ( CurrentlyLoadingMesh + " # " + Images [ i ] . Id ) . c_str ( ) , img ) ;
2008-01-24 09:24:52 -08:00
img - > drop ( ) ;
return tex ;
}
break ;
}
}
if ( Parameters . getAttributeType ( uri . c_str ( ) ) = = io : : EAT_STRING )
2008-01-25 09:01:42 -08:00
{
2008-01-24 09:24:52 -08:00
uri = Parameters . getAttributeAsString ( uri . c_str ( ) ) ;
2008-01-25 09:01:42 -08:00
# ifdef COLLADA_READER_DEBUG
os : : Printer : : log ( " COLLADA now searching texture " , uri . c_str ( ) ) ;
# endif
}
2008-01-24 09:24:52 -08:00
else
break ;
}
return 0 ;
}
//! read a parameter and value
void CColladaFileLoader : : readParameter ( io : : IXMLReaderUTF8 * reader )
{
# ifdef COLLADA_READER_DEBUG
os : : Printer : : log ( " COLLADA reading parameter " ) ;
# endif
2008-11-13 09:35:17 -08:00
const core : : stringc name = reader - > getAttributeValue ( " sid " ) ;
if ( ! reader - > isEmptyElement ( ) )
2008-01-24 09:24:52 -08:00
{
2008-11-13 09:35:17 -08:00
while ( reader - > read ( ) )
2008-01-24 09:24:52 -08:00
{
2008-11-13 09:35:17 -08:00
if ( reader - > getNodeType ( ) = = io : : EXN_ELEMENT )
2008-01-24 09:24:52 -08:00
{
2008-11-13 09:35:17 -08:00
if ( floatNodeName = = reader - > getNodeName ( ) )
2008-01-24 09:24:52 -08:00
{
2008-11-13 09:35:17 -08:00
const f32 f = readFloatNode ( reader ) ;
Parameters . addFloat ( name . c_str ( ) , f ) ;
}
else
if ( float2NodeName = = reader - > getNodeName ( ) )
{
f32 f [ 2 ] ;
readFloatsInsideElement ( reader , f , 2 ) ;
2008-01-24 09:24:52 -08:00
// Parameters.addVector2d(name.c_str(), core::vector2df(f[0],f[1]));
2008-11-13 09:35:17 -08:00
}
else
if ( float3NodeName = = reader - > getNodeName ( ) )
{
f32 f [ 3 ] ;
readFloatsInsideElement ( reader , f , 3 ) ;
Parameters . addVector3d ( name . c_str ( ) , core : : vector3df ( f [ 0 ] , f [ 1 ] , f [ 2 ] ) ) ;
}
else
if ( ( initFromName = = reader - > getNodeName ( ) ) | |
( sourceSectionName = = reader - > getNodeName ( ) ) )
{
reader - > read ( ) ;
Parameters . addString ( name . c_str ( ) , reader - > getNodeData ( ) ) ;
}
else
if ( wrapsName = = reader - > getNodeName ( ) )
{
reader - > read ( ) ;
const core : : stringc val = reader - > getNodeData ( ) ;
if ( val = = " WRAP " )
Parameters . addBool ( " wrap_s " , true ) ;
}
else
if ( wraptName = = reader - > getNodeName ( ) )
{
reader - > read ( ) ;
const core : : stringc val = reader - > getNodeData ( ) ;
if ( val = = " WRAP " )
Parameters . addBool ( " wrap_t " , true ) ;
}
else
if ( minfilterName = = reader - > getNodeName ( ) )
{
reader - > read ( ) ;
const core : : stringc val = reader - > getNodeData ( ) ;
if ( val = = " LINEAR_MIPMAP_LINEAR " )
Parameters . addBool ( " trilinear " , true ) ;
2008-01-24 09:24:52 -08:00
else
2008-11-13 09:35:17 -08:00
if ( val = = " LINEAR_MIPMAP_NEAREST " )
Parameters . addBool ( " bilinear " , true ) ;
}
else
if ( magfilterName = = reader - > getNodeName ( ) )
{
reader - > read ( ) ;
const core : : stringc val = reader - > getNodeData ( ) ;
if ( val ! = " LINEAR " )
2008-01-24 09:24:52 -08:00
{
2008-11-13 09:35:17 -08:00
Parameters . addBool ( " bilinear " , false ) ;
Parameters . addBool ( " trilinear " , false ) ;
2008-01-24 09:24:52 -08:00
}
}
else
2008-11-13 09:35:17 -08:00
if ( mipfilterName = = reader - > getNodeName ( ) )
2008-01-24 09:24:52 -08:00
{
2008-11-13 09:35:17 -08:00
Parameters . addBool ( " anisotropic " , true ) ;
2008-01-24 09:24:52 -08:00
}
}
2008-11-13 09:35:17 -08:00
else
if ( reader - > getNodeType ( ) = = io : : EXN_ELEMENT_END )
{
if ( newParamName = = reader - > getNodeName ( ) )
break ;
}
2008-01-24 09:24:52 -08:00
}
}
}
2007-05-20 11:03:49 -07:00
} // end namespace scene
} // end namespace irr
2007-09-04 11:51:42 -07:00
# endif // _IRR_COMPILE_WITH_COLLADA_LOADER_
2008-01-23 09:15:15 -08:00