2009-01-14 04:37:51 -08:00
// Copyright (C) 2002-2009 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 " ;
2009-03-31 10:59:11 -07:00
const core : : stringc profileCOMMONAttributeName = " COMMON " ;
2008-01-23 09:15:15 -08:00
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") */
Changes in version 1.6, TA
- FileSystem 2.0 SUPER MASTER MAJOR API CHANGE !!!
The FileSystem is know build internally like for e.q the texture-, and the meshloaders.
There exists a known list of ArchiveLoader, which know how to produce a Archive.
The Loaders and the Archive can be attached/detached on runtime.
The FileNames are now stored as core::string<c16>. where c16 is toggled between char/wchar
with the #define flag _IRR_WCHAR_FILESYSTEM, to supported unicode backends (default:off)
I replaced all (const c8* filename) to string references.
Basically the FileSystem is divided into two regions. Native and Virtual.
Native means using the backend OS.
Virtual means only use currently attach IArchives.
Browsing
each FileSystem has it's own workdirectory and it's own methods to
- create a FileTree
- add/remove files & directory ( to be done )
Hint: store a savegame in a zip archive...
basic browsing for all archives is implemented.
Example 21. Quake3Explorer shows this
TODO:
- a file filter should be implemented.
- The IArchive should have a function to create a filetree
for now CFileList is used.
Class Hiarchy:
IArchiveLoader: is able to produce a IFileArchive
- ZipLoader
- PakLoader
- MountPointReader ( formaly known as CUnzipReader )
IFileArchive:
-ZipArchive
-PakArchive
-MountPoint (known as FolderFile)
IFileSystem
- addArchiveLoader
- changed implementation of isALoadableFileExtension in all loaders
to have consistent behavior
- added a parameter to IFileList * createFileList
setFileListSystem
allows to query files in any of the game archives
standard behavior listtype = SYSTEM ( default)
- CLimitReadFile
added multiple file random-access support.
solved problems with mixed compressed & uncompressed files in a zip
TODO:
- Big Big Testing!!
- Linux Version ( minor )
- remove all double loader interfaces where only the filename differs
(IReadFile/const char *filename). This blows up the the interface
- many loaders use their own private filesearching
we should rework this
- there are a lot of helper function ( getAbsolutePath, getFileDir )
which should be adapted to the virtual filesystem
- IrrlichtDevice
added:
virtual bool setGammaRamp( f32 red, f32 green, f32 blue, f32 brightness, f32 contrast ) = 0;
virtual bool getGammaRamp( f32 &red, f32 &green, f32 &blue ) = 0;
and calculating methods to DeviceStub.
implemented in Win32, TODO: other Devices
- irrlicht.h
changed exported irrlicht.dll routines createDevice, createDeviceEx, IdentityMatrix
to extern "C" name mangling.
for easier dynamically loading the irrlicht library and different versions
- ParticleSystem
removed the private (old?,wrong?) interface from the ParticleEffectors
to match the parent class irr::io::IAttributeExchangingObject::deserializeAttributes
TODO:
please test if the serialization works!
- Generic
- vector3d<T>& normalize()
#if 0
f32 length = (f32)(X*X + Y*Y + Z*Z);
if (core::equals(length, 0.f))
return *this;
length = core::reciprocal_squareroot ( (f32)length );
#else
const T length = core::reciprocal_squareroot ( (X*X + Y*Y + Z*Z) );
#endif
Weak checking on zero?!?! just to avoid a sqrt?. mhm, maybe not;-)
added reciprocal_squareroot for f64
- dimension2d
added operator dimension2d<T>& operator=(const dimension2d<U>& other)
to cast between different types
- vector2d
bugfix:
vector2d<T>& operator+=(const dimension2d<T>& other) { X += other.Width; Y += other.Width; return *this; }
to
vector2d<T>& operator+=(const dimension2d<T>& other) { X += other.Width; Y += other.Height; return *this; }
- C3DMeshLoader renamed chunks const u16 to a enum
removing "variable declared but never used warning"
- added a global const identity Material
changed all references *((video::SMaterial*)0) to point to IdentityMaterial
removed warning: "a NULL reference is not allowed"
- modified IRRLICHT_MATH to not support reciprocal stuff
but to use faster float-to-int conversion.
gcc troubles may they are. i'm using intel-compiler..;-)
- core::matrix4
USE_MATRIX_TEST
i tried to optimize the identity-check ( in means of performance)
i didn't succeed so well, so i made a define for the matrix isIdentity -check
for now it's sometimes faster to always calculate versus identity-check
but if there are a lot of scenenodes/ particles one can profit from the
fast_inverse matrix, when no scaling is used. further approvement could
be done on inverse for just tranlastion! ( many static scenenodes are not rotated,
they are just placed somewhere in the world)
one thing to take in account is that sizeof(matrix) is 64 byte and
with the additional bool/u32 makes it 66 byte which is not really cache-friendly..
- added buildRotateFromTo
Builds a matrix that rotates from one vector to another
- irr::array. changed allocating routine in push_back
okt, 2008. it's only allowed to alloc one element, if
default constructor has to be called.
removes existing crashes. ( MD3 Mesh ) and possible others ones.
A new list template should be made.
one with constructor/destructor calls ( safe_array ) and
one without. like the array since the beginning of irrlicht.
currently the array/string is extremly slow..
also a hint for the user has to be done, so that a struct T of
array<T> must have a copy constructor of type T ( const T&other ).
i needed hours to track that down...
added a new method setAllocStrategy,
safe ( used + 1 ), double ( used * 2 + 1)
better default strategies will be implemented
- removed binary_search_const
i added it quite a long time ago, but it doesnt make real sense
a call to a sort method should happen always. i just wanted to safe
a few cycles..
- added binary_search_multi
searches for a multi-set ( more than 1 entry in the sorted array)
returns start and end-index
- changed some identity matrix settings to use core::IdentityMatrix
- added deletePathFromFilename to generic string functions in coreutil.h and
removed from CZipReader and CPakReader
- s32 deserializeAttributes used instead of virtual void deserializeAttributes in
ParticleSystem ( wrong virtual was used)
- strings & Locale
- started to add locale support
- added verify to string
- added some helper functions
- XBOX
i have access to a XBOX development machine now. I started to compile
for the XBOX. Question: Who did the previous implementation?. There
is no XBOX-Device inhere. maybe it's forbidden because of using the offical
Microsoft XDK. I will implement a native or sdl device based on opendk.
irrlicht compiles without errors on the xbox but can't be used.
TODO:
- native XBOX Device
- Windows Mobile
reworked a little. added the mobile example to the windows solution for
cross development.
added maximal 128x128 texture size for windows mobile ( memory issues )
- Collision Speed Up
The Collision Speed Up greatly improves with many small static child-nodes
- added COctTreeTriangleSelector::getTriangles for 3dline from user Piraaate
- modified createOctTreeTriangleSelector and createTriangleSelector
to allow node == 0, to be added to a meta selector
- CSceneNodeAnimatorCollisionResponse has the same problem as CSceneNodeAnimatorFPS
on first update:
Problem. you start setting the map. (setWorld). First update cames 4000 ms later.
The Animator applies the missing force... big problem...
changed to react on first update like camera.
- add Variable FirstUpdate. if set to true ( on all changes )
then position, lasttime, and falling are initialized
-added #define OCTTREE_USE_HARDWARE in Octree.h
if defined octtree uses internally a derived scene::MeshBuffer which has
the possibility to use the Hardware Vertex Buffer for static vertices and
dirty indices;-)
if defined OCTTREE_USE_HARDWARE octree uses internally a derived scene::CMeshBuffer
so it's not just a replacement inside the octree. It also in the OctTreeSceneNode.
#if defined (OCTTREE_USE_HARDWARE)
driver->drawMeshBuffer ( &LightMapMeshes[i] );
#else
driver->drawIndexedTriangleList( &LightMapMeshes[i].Vertices[0], LightMapMeshes[i].Vertices.size(),
d[i].Indices, d[i].CurrentSize / 3);
#endif
#define OCTTREE_PARENTTEST is also used. It's skip testing on fully outside and takes everything on fully inside
- virtual void ISceneNode::updateAbsolutePosition()
- changed
inline CMatrix4<T> CMatrix4<T>::operator*(const CMatrix4<T>& m2) const
all two matrices have to be checked by isIdentity()
to let the isIdentity work always
-changed inline bool CMatrix4<T>::isIdentity() const
on full identityCheck->
to look first on Translation, because this is the most challenging element
which will likely not to be identity..
- virtual core::matrix4 getRelativeTransformation() const
Hiarchy on Identity-Check
1) ->getRelativeTransform -> 9 floating point checks to be passed as Identity
2) ->isIdentity () -> 16 floating point checks to be passed as Identity
- inline void CMatrix4<T>::transformBoxEx(core::aabbox3d<f32>& box) const
added isIdentity() check
- changed CSceneNodeAnimatorCollisionResponse
- added CSceneNodeAnimatorCollisionResponse::setGravity
needed to set the differents Forces for the Animator. for eq. water..
- added CSceneNodeAnimatorCollisionResponse::setAnimateTarget
- added CSceneNodeAnimatorCollisionResponse::getAnimateTarget
- changed CSceneNodeAnimatorCollisionResponse::animateNode to react on FirstUpdate
- changad Gravity to
- TODO: set Gravity to Physically frame independent values..
current response uses an frame depdended acceleration vector.
~9.81 m/s^2 was achieved at around 50 fps with a setting of -0.03
may effect existing application..
- SceneNodes
- CSkyDomeSceneNode
moved radius ( default 1000 ) to constructor
added Normals
added DebugInfo
added Material.ZBuffer, added SceneMaanager
- CVolumeLightSceneNode:
changed default blending OneTextureBlendgl_src_color gl_src_alpha to
EMT_TRANSPARENT_ADD_COLOR ( gl_src_color gl_one )
which gives the same effect on non-transparent-materials.
Following the unspoken guide-line, lowest effect as default
- added LensFlareSceneNode (from forum user gammaray, modified to work )
showing in example special fx
- changed SceneNode Skydome f64 to f32,
- AnimatedMesh
-Debug Data:
mesh normals didn't rotate with the scenenode fixed ( matrix-multiplication order)
- Camera SceneNode setPosition
Camera now finally allow to change position and target and updates all
effected animators..
a call to OnAnimate ( ) lastime < time or OnAnimate ( 0 ) will reset the
camera and fr. the collision animator to a new position
- Device:
added the current mousebutton state to the Mouse Event
so i need to get the current mouse state from the OS
-a dded to CIrrDeviceWin32
TODO:
- Linux and SDL Device
- GUI
- CGUIFont:
- added virtual void setInvisibleCharacters( const wchar_t *s ) = 0;
define which characters should not be drawn ( send to driver) by the font.
for example " " would not draw any space which is usually blank in most fonts
and saves rendering of ususally full blank alpha-sprites.
This saves a lot of rendering...
default:
setInvisibleCharacters ( L" " );
- added MultiLine rendering
should avoid to us CStaticText breaking text in future
- CGUIListBox
- changed Scrollbar LargeStepSize to ItemHeight
which easy enables to scroll line by line
- CGUIScrollBar
bug:
Create a Window and inside a listbox with a scrollbar or
a windowed irrlicht application
Click & hold Scrollbar Slider. move outside it's region.
Release Mouse. Go Back to Scrollbar.. it's moving always...
it's generally missing the event PRESSED_MOVED, which
leads to problem when an element is dragging, has a focus, or position loose
and gets focus back again. ( think of a drunken mouse sliding left&right during tracking )
so added the mouse Input Buttonstates on every mouse event
IrrDeviceWin32:
added event.MouseInput.ButtonStates = wParam & ( MK_LBUTTON | MK_RBUTTON | MK_MBUTTON );
TODO:
Linux & SDL
so now i can do this
case irr::EMIE_MOUSE_MOVED:
if ( !event.MouseInput.isLeftPressed () )
{
Dragging = false;
}
- bug:
Scrollbar notifyListBox notify when the scrollbar is clicked.
- changed timed event in draw to OnPostRender
Why the hell is a gui element firing a timed event
in a draw routine!!!!!. This should be corrected for all gui-elements.
- added GUI Image List from Reinhard Ostermeier, modified to work
added GUI Tree View from Reinhard Ostermeier, modified to work
shown in the Quake3MapShader Example
TODO: Spritebanks
- FileOpenDialog
changed the static text for the filename to an edit box.
- changed the interface for addEditBox to match with addStaticText
- changed the interface for addSpinBox to match with addEditBox
- added MouseWheel to Spinbox
- changed CGUITable CLICK_AREA from 3 to 12 to enable clicking on the visible marker
- CGUISpritebank
removed some crashes with empty Sprite banks
- IGUIScrollBar
added SetMin before min was always 0
changed ScrollWheel Direction on horizontal to move right on wheel up, left on wheel down
- IComboBox
-added ItemData
- removed IsVisbile check in IGUIElement::draw
- Image Loaders
- added TGA file type 2 ( grayscale uncompressed )
- added TGA file type (1) 8 Bit indexed color uncompressed
ColorConverter:
- added convert_B8G8R8toA8R8G8B8
- added convert_B8G8R8A8toA8R8G8B8
- Media Files
- added missing shaders and textures to map-20kdm2.
Taken from free implementation
- ball.wav. adjusted DC-Offset, amplified to -4dB, trim cross-zero
- impact.wav clip-restoration, trim cross-zero
- added gun.md2, gun.pcx to media-files
copyright issues!. i don't know from where this file came from...
i hope this is not from original quake2..
- added new irrlicht logo irrlicht3.png
i've taken the new layout. i should ask niko to use it.
- added Skydome picture to media files (skydome2.jpg) half/sphere
- OctTree
-added
#define OCTTREE_PARENTTEST ( default: disabled )
used to leave-out children test if the parent passed a complete frustum.
plus: leaves out children test
minus: all edges have to be checked
- added MesBuffer Hardware Hint Vertex to octtree
- CQuake3ShaderSceneNode:
- removed function releaseMesh
Shader doesn't copy the original mesh anymore ( saving memory )
so therefore this (for others often misleading ) function was removed
- changed constructor to take a (shared) destination meshbuffer for rendering
reducing vertex-memory to a half
- don't copy the original vertices anymore
- added deformvertexes autosprite
- added deformvertexes move
- added support for RTCW and Raven BSPs ( qmap2 )
- added polygonoffset (TODO: not perfect)
- added added nomipmaps
- added rgbgen const
- added alphagen
- added MesBuffer Hardware Hint Vertex/Index to Quake3: static geometry, dynamic indices
- added Quake3Explorer examples
- added wave noise
- added tcmod transform
- added whiteimage
- added collision to Quake3Explorer
- renamed SMD3QuaterionTag* to SMD3QuaternionTag* ( typo )
- updated quake3:blendfunc
- added crouch to Quake3Explorer
(modifying the ellipsiodRadius of the camera animator )
added crouch to CSceneNodeAnimatorCameraFPS
still problems with stand up and collision
- Quake3MapLoader
modified memory allocation for faster loading
- Quake3LoadParam
added Parameter to the Mesh-Loader
- added
The still existing missing caulking of curved surfaces.
using round in the coordinates doesn't solve the problem.
but for the demo bsp mesh it solves the problem... (luck)
so for now it's switchable.
TJUNCTION_SOLVER_ROUND
default:off
- BurningVideo
- pushed BurningsVideo to 0.40
- added blendfunc gl_one_minus_dst_alpha gl_one
- added blendfunc gl_dst_color gl_zero
- added blendfunc gl_dst_color src_alpha
- modified AlphaChannel_Ref renderer to support alpha test lessequal
- addded 32 Bit Index Buffer
- added sourceRect/destRect check to 2D-Blitter ( slower, but resolves crash )
- added setTextureCreationFlag video::ETCF_ALLOW_NON_POWER_2
Burning checks this flag and when set, it bypasses the power2 size check,
which is necessary on 3D but can be avoided on 2D.
used on fonts automatically.
- added Support for Destination Alpha
- OpenGL
- Fixed a bug in COpenGLExtensenionHandler where a glint was downcasted to u8!!!!!!
MaxTextureSize=static_cast<u32>(num);
- TODO: COpenGLMaterialRenderer_ONETEXTURE_BLEND to work as expected
- Direct3D8
- compile and links again
- added 32 Bit Index Buffer
- D3DSAMP_MIPMAPLODBIAS doesnt compile!. it is d3d9 i think.
- compile for XBOX
- Direc3D9
- fixed crash on RTT Textures DepthBuffer freed twice.
added deleteAllTextures to destuctor
- NullDriver
- removeallTextures. added setMaterial ( SMaterial() ) to clean pointers for freed textures
git-svn-id: svn://svn.code.sf.net/p/irrlicht/code/trunk@2147 dfc29bdd-3216-0410-991c-e03cc46cb475
2009-01-27 07:53:53 -08:00
bool CColladaFileLoader : : isALoadableFileExtension ( const core : : string < c16 > & filename ) const
2007-05-20 11:03:49 -07:00
{
Changes in version 1.6, TA
- FileSystem 2.0 SUPER MASTER MAJOR API CHANGE !!!
The FileSystem is know build internally like for e.q the texture-, and the meshloaders.
There exists a known list of ArchiveLoader, which know how to produce a Archive.
The Loaders and the Archive can be attached/detached on runtime.
The FileNames are now stored as core::string<c16>. where c16 is toggled between char/wchar
with the #define flag _IRR_WCHAR_FILESYSTEM, to supported unicode backends (default:off)
I replaced all (const c8* filename) to string references.
Basically the FileSystem is divided into two regions. Native and Virtual.
Native means using the backend OS.
Virtual means only use currently attach IArchives.
Browsing
each FileSystem has it's own workdirectory and it's own methods to
- create a FileTree
- add/remove files & directory ( to be done )
Hint: store a savegame in a zip archive...
basic browsing for all archives is implemented.
Example 21. Quake3Explorer shows this
TODO:
- a file filter should be implemented.
- The IArchive should have a function to create a filetree
for now CFileList is used.
Class Hiarchy:
IArchiveLoader: is able to produce a IFileArchive
- ZipLoader
- PakLoader
- MountPointReader ( formaly known as CUnzipReader )
IFileArchive:
-ZipArchive
-PakArchive
-MountPoint (known as FolderFile)
IFileSystem
- addArchiveLoader
- changed implementation of isALoadableFileExtension in all loaders
to have consistent behavior
- added a parameter to IFileList * createFileList
setFileListSystem
allows to query files in any of the game archives
standard behavior listtype = SYSTEM ( default)
- CLimitReadFile
added multiple file random-access support.
solved problems with mixed compressed & uncompressed files in a zip
TODO:
- Big Big Testing!!
- Linux Version ( minor )
- remove all double loader interfaces where only the filename differs
(IReadFile/const char *filename). This blows up the the interface
- many loaders use their own private filesearching
we should rework this
- there are a lot of helper function ( getAbsolutePath, getFileDir )
which should be adapted to the virtual filesystem
- IrrlichtDevice
added:
virtual bool setGammaRamp( f32 red, f32 green, f32 blue, f32 brightness, f32 contrast ) = 0;
virtual bool getGammaRamp( f32 &red, f32 &green, f32 &blue ) = 0;
and calculating methods to DeviceStub.
implemented in Win32, TODO: other Devices
- irrlicht.h
changed exported irrlicht.dll routines createDevice, createDeviceEx, IdentityMatrix
to extern "C" name mangling.
for easier dynamically loading the irrlicht library and different versions
- ParticleSystem
removed the private (old?,wrong?) interface from the ParticleEffectors
to match the parent class irr::io::IAttributeExchangingObject::deserializeAttributes
TODO:
please test if the serialization works!
- Generic
- vector3d<T>& normalize()
#if 0
f32 length = (f32)(X*X + Y*Y + Z*Z);
if (core::equals(length, 0.f))
return *this;
length = core::reciprocal_squareroot ( (f32)length );
#else
const T length = core::reciprocal_squareroot ( (X*X + Y*Y + Z*Z) );
#endif
Weak checking on zero?!?! just to avoid a sqrt?. mhm, maybe not;-)
added reciprocal_squareroot for f64
- dimension2d
added operator dimension2d<T>& operator=(const dimension2d<U>& other)
to cast between different types
- vector2d
bugfix:
vector2d<T>& operator+=(const dimension2d<T>& other) { X += other.Width; Y += other.Width; return *this; }
to
vector2d<T>& operator+=(const dimension2d<T>& other) { X += other.Width; Y += other.Height; return *this; }
- C3DMeshLoader renamed chunks const u16 to a enum
removing "variable declared but never used warning"
- added a global const identity Material
changed all references *((video::SMaterial*)0) to point to IdentityMaterial
removed warning: "a NULL reference is not allowed"
- modified IRRLICHT_MATH to not support reciprocal stuff
but to use faster float-to-int conversion.
gcc troubles may they are. i'm using intel-compiler..;-)
- core::matrix4
USE_MATRIX_TEST
i tried to optimize the identity-check ( in means of performance)
i didn't succeed so well, so i made a define for the matrix isIdentity -check
for now it's sometimes faster to always calculate versus identity-check
but if there are a lot of scenenodes/ particles one can profit from the
fast_inverse matrix, when no scaling is used. further approvement could
be done on inverse for just tranlastion! ( many static scenenodes are not rotated,
they are just placed somewhere in the world)
one thing to take in account is that sizeof(matrix) is 64 byte and
with the additional bool/u32 makes it 66 byte which is not really cache-friendly..
- added buildRotateFromTo
Builds a matrix that rotates from one vector to another
- irr::array. changed allocating routine in push_back
okt, 2008. it's only allowed to alloc one element, if
default constructor has to be called.
removes existing crashes. ( MD3 Mesh ) and possible others ones.
A new list template should be made.
one with constructor/destructor calls ( safe_array ) and
one without. like the array since the beginning of irrlicht.
currently the array/string is extremly slow..
also a hint for the user has to be done, so that a struct T of
array<T> must have a copy constructor of type T ( const T&other ).
i needed hours to track that down...
added a new method setAllocStrategy,
safe ( used + 1 ), double ( used * 2 + 1)
better default strategies will be implemented
- removed binary_search_const
i added it quite a long time ago, but it doesnt make real sense
a call to a sort method should happen always. i just wanted to safe
a few cycles..
- added binary_search_multi
searches for a multi-set ( more than 1 entry in the sorted array)
returns start and end-index
- changed some identity matrix settings to use core::IdentityMatrix
- added deletePathFromFilename to generic string functions in coreutil.h and
removed from CZipReader and CPakReader
- s32 deserializeAttributes used instead of virtual void deserializeAttributes in
ParticleSystem ( wrong virtual was used)
- strings & Locale
- started to add locale support
- added verify to string
- added some helper functions
- XBOX
i have access to a XBOX development machine now. I started to compile
for the XBOX. Question: Who did the previous implementation?. There
is no XBOX-Device inhere. maybe it's forbidden because of using the offical
Microsoft XDK. I will implement a native or sdl device based on opendk.
irrlicht compiles without errors on the xbox but can't be used.
TODO:
- native XBOX Device
- Windows Mobile
reworked a little. added the mobile example to the windows solution for
cross development.
added maximal 128x128 texture size for windows mobile ( memory issues )
- Collision Speed Up
The Collision Speed Up greatly improves with many small static child-nodes
- added COctTreeTriangleSelector::getTriangles for 3dline from user Piraaate
- modified createOctTreeTriangleSelector and createTriangleSelector
to allow node == 0, to be added to a meta selector
- CSceneNodeAnimatorCollisionResponse has the same problem as CSceneNodeAnimatorFPS
on first update:
Problem. you start setting the map. (setWorld). First update cames 4000 ms later.
The Animator applies the missing force... big problem...
changed to react on first update like camera.
- add Variable FirstUpdate. if set to true ( on all changes )
then position, lasttime, and falling are initialized
-added #define OCTTREE_USE_HARDWARE in Octree.h
if defined octtree uses internally a derived scene::MeshBuffer which has
the possibility to use the Hardware Vertex Buffer for static vertices and
dirty indices;-)
if defined OCTTREE_USE_HARDWARE octree uses internally a derived scene::CMeshBuffer
so it's not just a replacement inside the octree. It also in the OctTreeSceneNode.
#if defined (OCTTREE_USE_HARDWARE)
driver->drawMeshBuffer ( &LightMapMeshes[i] );
#else
driver->drawIndexedTriangleList( &LightMapMeshes[i].Vertices[0], LightMapMeshes[i].Vertices.size(),
d[i].Indices, d[i].CurrentSize / 3);
#endif
#define OCTTREE_PARENTTEST is also used. It's skip testing on fully outside and takes everything on fully inside
- virtual void ISceneNode::updateAbsolutePosition()
- changed
inline CMatrix4<T> CMatrix4<T>::operator*(const CMatrix4<T>& m2) const
all two matrices have to be checked by isIdentity()
to let the isIdentity work always
-changed inline bool CMatrix4<T>::isIdentity() const
on full identityCheck->
to look first on Translation, because this is the most challenging element
which will likely not to be identity..
- virtual core::matrix4 getRelativeTransformation() const
Hiarchy on Identity-Check
1) ->getRelativeTransform -> 9 floating point checks to be passed as Identity
2) ->isIdentity () -> 16 floating point checks to be passed as Identity
- inline void CMatrix4<T>::transformBoxEx(core::aabbox3d<f32>& box) const
added isIdentity() check
- changed CSceneNodeAnimatorCollisionResponse
- added CSceneNodeAnimatorCollisionResponse::setGravity
needed to set the differents Forces for the Animator. for eq. water..
- added CSceneNodeAnimatorCollisionResponse::setAnimateTarget
- added CSceneNodeAnimatorCollisionResponse::getAnimateTarget
- changed CSceneNodeAnimatorCollisionResponse::animateNode to react on FirstUpdate
- changad Gravity to
- TODO: set Gravity to Physically frame independent values..
current response uses an frame depdended acceleration vector.
~9.81 m/s^2 was achieved at around 50 fps with a setting of -0.03
may effect existing application..
- SceneNodes
- CSkyDomeSceneNode
moved radius ( default 1000 ) to constructor
added Normals
added DebugInfo
added Material.ZBuffer, added SceneMaanager
- CVolumeLightSceneNode:
changed default blending OneTextureBlendgl_src_color gl_src_alpha to
EMT_TRANSPARENT_ADD_COLOR ( gl_src_color gl_one )
which gives the same effect on non-transparent-materials.
Following the unspoken guide-line, lowest effect as default
- added LensFlareSceneNode (from forum user gammaray, modified to work )
showing in example special fx
- changed SceneNode Skydome f64 to f32,
- AnimatedMesh
-Debug Data:
mesh normals didn't rotate with the scenenode fixed ( matrix-multiplication order)
- Camera SceneNode setPosition
Camera now finally allow to change position and target and updates all
effected animators..
a call to OnAnimate ( ) lastime < time or OnAnimate ( 0 ) will reset the
camera and fr. the collision animator to a new position
- Device:
added the current mousebutton state to the Mouse Event
so i need to get the current mouse state from the OS
-a dded to CIrrDeviceWin32
TODO:
- Linux and SDL Device
- GUI
- CGUIFont:
- added virtual void setInvisibleCharacters( const wchar_t *s ) = 0;
define which characters should not be drawn ( send to driver) by the font.
for example " " would not draw any space which is usually blank in most fonts
and saves rendering of ususally full blank alpha-sprites.
This saves a lot of rendering...
default:
setInvisibleCharacters ( L" " );
- added MultiLine rendering
should avoid to us CStaticText breaking text in future
- CGUIListBox
- changed Scrollbar LargeStepSize to ItemHeight
which easy enables to scroll line by line
- CGUIScrollBar
bug:
Create a Window and inside a listbox with a scrollbar or
a windowed irrlicht application
Click & hold Scrollbar Slider. move outside it's region.
Release Mouse. Go Back to Scrollbar.. it's moving always...
it's generally missing the event PRESSED_MOVED, which
leads to problem when an element is dragging, has a focus, or position loose
and gets focus back again. ( think of a drunken mouse sliding left&right during tracking )
so added the mouse Input Buttonstates on every mouse event
IrrDeviceWin32:
added event.MouseInput.ButtonStates = wParam & ( MK_LBUTTON | MK_RBUTTON | MK_MBUTTON );
TODO:
Linux & SDL
so now i can do this
case irr::EMIE_MOUSE_MOVED:
if ( !event.MouseInput.isLeftPressed () )
{
Dragging = false;
}
- bug:
Scrollbar notifyListBox notify when the scrollbar is clicked.
- changed timed event in draw to OnPostRender
Why the hell is a gui element firing a timed event
in a draw routine!!!!!. This should be corrected for all gui-elements.
- added GUI Image List from Reinhard Ostermeier, modified to work
added GUI Tree View from Reinhard Ostermeier, modified to work
shown in the Quake3MapShader Example
TODO: Spritebanks
- FileOpenDialog
changed the static text for the filename to an edit box.
- changed the interface for addEditBox to match with addStaticText
- changed the interface for addSpinBox to match with addEditBox
- added MouseWheel to Spinbox
- changed CGUITable CLICK_AREA from 3 to 12 to enable clicking on the visible marker
- CGUISpritebank
removed some crashes with empty Sprite banks
- IGUIScrollBar
added SetMin before min was always 0
changed ScrollWheel Direction on horizontal to move right on wheel up, left on wheel down
- IComboBox
-added ItemData
- removed IsVisbile check in IGUIElement::draw
- Image Loaders
- added TGA file type 2 ( grayscale uncompressed )
- added TGA file type (1) 8 Bit indexed color uncompressed
ColorConverter:
- added convert_B8G8R8toA8R8G8B8
- added convert_B8G8R8A8toA8R8G8B8
- Media Files
- added missing shaders and textures to map-20kdm2.
Taken from free implementation
- ball.wav. adjusted DC-Offset, amplified to -4dB, trim cross-zero
- impact.wav clip-restoration, trim cross-zero
- added gun.md2, gun.pcx to media-files
copyright issues!. i don't know from where this file came from...
i hope this is not from original quake2..
- added new irrlicht logo irrlicht3.png
i've taken the new layout. i should ask niko to use it.
- added Skydome picture to media files (skydome2.jpg) half/sphere
- OctTree
-added
#define OCTTREE_PARENTTEST ( default: disabled )
used to leave-out children test if the parent passed a complete frustum.
plus: leaves out children test
minus: all edges have to be checked
- added MesBuffer Hardware Hint Vertex to octtree
- CQuake3ShaderSceneNode:
- removed function releaseMesh
Shader doesn't copy the original mesh anymore ( saving memory )
so therefore this (for others often misleading ) function was removed
- changed constructor to take a (shared) destination meshbuffer for rendering
reducing vertex-memory to a half
- don't copy the original vertices anymore
- added deformvertexes autosprite
- added deformvertexes move
- added support for RTCW and Raven BSPs ( qmap2 )
- added polygonoffset (TODO: not perfect)
- added added nomipmaps
- added rgbgen const
- added alphagen
- added MesBuffer Hardware Hint Vertex/Index to Quake3: static geometry, dynamic indices
- added Quake3Explorer examples
- added wave noise
- added tcmod transform
- added whiteimage
- added collision to Quake3Explorer
- renamed SMD3QuaterionTag* to SMD3QuaternionTag* ( typo )
- updated quake3:blendfunc
- added crouch to Quake3Explorer
(modifying the ellipsiodRadius of the camera animator )
added crouch to CSceneNodeAnimatorCameraFPS
still problems with stand up and collision
- Quake3MapLoader
modified memory allocation for faster loading
- Quake3LoadParam
added Parameter to the Mesh-Loader
- added
The still existing missing caulking of curved surfaces.
using round in the coordinates doesn't solve the problem.
but for the demo bsp mesh it solves the problem... (luck)
so for now it's switchable.
TJUNCTION_SOLVER_ROUND
default:off
- BurningVideo
- pushed BurningsVideo to 0.40
- added blendfunc gl_one_minus_dst_alpha gl_one
- added blendfunc gl_dst_color gl_zero
- added blendfunc gl_dst_color src_alpha
- modified AlphaChannel_Ref renderer to support alpha test lessequal
- addded 32 Bit Index Buffer
- added sourceRect/destRect check to 2D-Blitter ( slower, but resolves crash )
- added setTextureCreationFlag video::ETCF_ALLOW_NON_POWER_2
Burning checks this flag and when set, it bypasses the power2 size check,
which is necessary on 3D but can be avoided on 2D.
used on fonts automatically.
- added Support for Destination Alpha
- OpenGL
- Fixed a bug in COpenGLExtensenionHandler where a glint was downcasted to u8!!!!!!
MaxTextureSize=static_cast<u32>(num);
- TODO: COpenGLMaterialRenderer_ONETEXTURE_BLEND to work as expected
- Direct3D8
- compile and links again
- added 32 Bit Index Buffer
- D3DSAMP_MIPMAPLODBIAS doesnt compile!. it is d3d9 i think.
- compile for XBOX
- Direc3D9
- fixed crash on RTT Textures DepthBuffer freed twice.
added deleteAllTextures to destuctor
- NullDriver
- removeallTextures. added setMaterial ( SMaterial() ) to clean pointers for freed textures
git-svn-id: svn://svn.code.sf.net/p/irrlicht/code/trunk@2147 dfc29bdd-3216-0410-991c-e03cc46cb475
2009-01-27 07:53:53 -08:00
return core : : hasFileExtension ( filename , " xml " , " 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
2009-03-31 10:59:11 -07:00
if ( Version < 10400 )
instantiateNode ( SceneManager - > getRootSceneNode ( ) ) ;
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 )
2009-03-31 10:59:11 -07: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 ( ) ) ;
2009-04-17 09:22:43 -07:00
Version = core : : floor32 ( version ) * 10000 + core : : round32 ( 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
2009-03-31 10:59:11 -07:00
//! reads any kind of <instance*> node
void CColladaFileLoader : : readInstanceNode ( io : : IXMLReaderUTF8 * reader ,
scene : : ISceneNode * parent , 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
}
}
2009-03-31 10:59:11 -07:00
instantiateNode ( parent , outNode , p , url ) ;
}
void CColladaFileLoader : : instantiateNode ( scene : : ISceneNode * parent ,
scene : : ISceneNode * * outNode , CScenePrefab * p , const core : : stringc & url )
{
# ifdef COLLADA_READER_DEBUG
os : : Printer : : log ( " COLLADA instantiate node " ) ;
# endif
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
{
2009-03-31 10:59:11 -07:00
if ( url = = " " | | 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 )
2009-03-31 10:59:11 -07:00
( * outNode ) - > setName ( url ) ;
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
{
2008-11-20 15:07:53 -08:00
# ifdef COLLADA_READER_DEBUG
os : : Printer : : log ( " COLLADA found transparency material " , core : : stringc ( material - > Transparency ) . c_str ( ) ) ;
# endif
2008-01-25 09:01:42 -08:00
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
2009-03-31 10:59:11 -07:00
if ( extraNodeName = = nodeName )
2008-01-20 16:24:28 -08:00
skipSection ( reader , false ) ;
else
2009-03-31 10:59:11 -07:00
// techniqueCommon or 'technique profile=common' must not be skipped
if ( ( techniqueCommonSectionName ! = nodeName ) // Collada 1.4+
& & ( ( techniqueNodeName ! = nodeName ) | |
( profileCOMMONAttributeName ! = reader - > getAttributeValue ( " profile " ) ) ) ) // Collada 1.2/1.3
2008-01-20 16:24:28 -08:00
{
2009-03-31 10:59:11 -07:00
os : : Printer : : log ( " COLLADA loader warning: Wrong tag usage found in geometry " , reader - > getNodeName ( ) , ELL_WARNING ) ;
2008-01-20 16:24:28 -08:00
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
Changes in version 1.6, TA
- FileSystem 2.0 SUPER MASTER MAJOR API CHANGE !!!
The FileSystem is know build internally like for e.q the texture-, and the meshloaders.
There exists a known list of ArchiveLoader, which know how to produce a Archive.
The Loaders and the Archive can be attached/detached on runtime.
The FileNames are now stored as core::string<c16>. where c16 is toggled between char/wchar
with the #define flag _IRR_WCHAR_FILESYSTEM, to supported unicode backends (default:off)
I replaced all (const c8* filename) to string references.
Basically the FileSystem is divided into two regions. Native and Virtual.
Native means using the backend OS.
Virtual means only use currently attach IArchives.
Browsing
each FileSystem has it's own workdirectory and it's own methods to
- create a FileTree
- add/remove files & directory ( to be done )
Hint: store a savegame in a zip archive...
basic browsing for all archives is implemented.
Example 21. Quake3Explorer shows this
TODO:
- a file filter should be implemented.
- The IArchive should have a function to create a filetree
for now CFileList is used.
Class Hiarchy:
IArchiveLoader: is able to produce a IFileArchive
- ZipLoader
- PakLoader
- MountPointReader ( formaly known as CUnzipReader )
IFileArchive:
-ZipArchive
-PakArchive
-MountPoint (known as FolderFile)
IFileSystem
- addArchiveLoader
- changed implementation of isALoadableFileExtension in all loaders
to have consistent behavior
- added a parameter to IFileList * createFileList
setFileListSystem
allows to query files in any of the game archives
standard behavior listtype = SYSTEM ( default)
- CLimitReadFile
added multiple file random-access support.
solved problems with mixed compressed & uncompressed files in a zip
TODO:
- Big Big Testing!!
- Linux Version ( minor )
- remove all double loader interfaces where only the filename differs
(IReadFile/const char *filename). This blows up the the interface
- many loaders use their own private filesearching
we should rework this
- there are a lot of helper function ( getAbsolutePath, getFileDir )
which should be adapted to the virtual filesystem
- IrrlichtDevice
added:
virtual bool setGammaRamp( f32 red, f32 green, f32 blue, f32 brightness, f32 contrast ) = 0;
virtual bool getGammaRamp( f32 &red, f32 &green, f32 &blue ) = 0;
and calculating methods to DeviceStub.
implemented in Win32, TODO: other Devices
- irrlicht.h
changed exported irrlicht.dll routines createDevice, createDeviceEx, IdentityMatrix
to extern "C" name mangling.
for easier dynamically loading the irrlicht library and different versions
- ParticleSystem
removed the private (old?,wrong?) interface from the ParticleEffectors
to match the parent class irr::io::IAttributeExchangingObject::deserializeAttributes
TODO:
please test if the serialization works!
- Generic
- vector3d<T>& normalize()
#if 0
f32 length = (f32)(X*X + Y*Y + Z*Z);
if (core::equals(length, 0.f))
return *this;
length = core::reciprocal_squareroot ( (f32)length );
#else
const T length = core::reciprocal_squareroot ( (X*X + Y*Y + Z*Z) );
#endif
Weak checking on zero?!?! just to avoid a sqrt?. mhm, maybe not;-)
added reciprocal_squareroot for f64
- dimension2d
added operator dimension2d<T>& operator=(const dimension2d<U>& other)
to cast between different types
- vector2d
bugfix:
vector2d<T>& operator+=(const dimension2d<T>& other) { X += other.Width; Y += other.Width; return *this; }
to
vector2d<T>& operator+=(const dimension2d<T>& other) { X += other.Width; Y += other.Height; return *this; }
- C3DMeshLoader renamed chunks const u16 to a enum
removing "variable declared but never used warning"
- added a global const identity Material
changed all references *((video::SMaterial*)0) to point to IdentityMaterial
removed warning: "a NULL reference is not allowed"
- modified IRRLICHT_MATH to not support reciprocal stuff
but to use faster float-to-int conversion.
gcc troubles may they are. i'm using intel-compiler..;-)
- core::matrix4
USE_MATRIX_TEST
i tried to optimize the identity-check ( in means of performance)
i didn't succeed so well, so i made a define for the matrix isIdentity -check
for now it's sometimes faster to always calculate versus identity-check
but if there are a lot of scenenodes/ particles one can profit from the
fast_inverse matrix, when no scaling is used. further approvement could
be done on inverse for just tranlastion! ( many static scenenodes are not rotated,
they are just placed somewhere in the world)
one thing to take in account is that sizeof(matrix) is 64 byte and
with the additional bool/u32 makes it 66 byte which is not really cache-friendly..
- added buildRotateFromTo
Builds a matrix that rotates from one vector to another
- irr::array. changed allocating routine in push_back
okt, 2008. it's only allowed to alloc one element, if
default constructor has to be called.
removes existing crashes. ( MD3 Mesh ) and possible others ones.
A new list template should be made.
one with constructor/destructor calls ( safe_array ) and
one without. like the array since the beginning of irrlicht.
currently the array/string is extremly slow..
also a hint for the user has to be done, so that a struct T of
array<T> must have a copy constructor of type T ( const T&other ).
i needed hours to track that down...
added a new method setAllocStrategy,
safe ( used + 1 ), double ( used * 2 + 1)
better default strategies will be implemented
- removed binary_search_const
i added it quite a long time ago, but it doesnt make real sense
a call to a sort method should happen always. i just wanted to safe
a few cycles..
- added binary_search_multi
searches for a multi-set ( more than 1 entry in the sorted array)
returns start and end-index
- changed some identity matrix settings to use core::IdentityMatrix
- added deletePathFromFilename to generic string functions in coreutil.h and
removed from CZipReader and CPakReader
- s32 deserializeAttributes used instead of virtual void deserializeAttributes in
ParticleSystem ( wrong virtual was used)
- strings & Locale
- started to add locale support
- added verify to string
- added some helper functions
- XBOX
i have access to a XBOX development machine now. I started to compile
for the XBOX. Question: Who did the previous implementation?. There
is no XBOX-Device inhere. maybe it's forbidden because of using the offical
Microsoft XDK. I will implement a native or sdl device based on opendk.
irrlicht compiles without errors on the xbox but can't be used.
TODO:
- native XBOX Device
- Windows Mobile
reworked a little. added the mobile example to the windows solution for
cross development.
added maximal 128x128 texture size for windows mobile ( memory issues )
- Collision Speed Up
The Collision Speed Up greatly improves with many small static child-nodes
- added COctTreeTriangleSelector::getTriangles for 3dline from user Piraaate
- modified createOctTreeTriangleSelector and createTriangleSelector
to allow node == 0, to be added to a meta selector
- CSceneNodeAnimatorCollisionResponse has the same problem as CSceneNodeAnimatorFPS
on first update:
Problem. you start setting the map. (setWorld). First update cames 4000 ms later.
The Animator applies the missing force... big problem...
changed to react on first update like camera.
- add Variable FirstUpdate. if set to true ( on all changes )
then position, lasttime, and falling are initialized
-added #define OCTTREE_USE_HARDWARE in Octree.h
if defined octtree uses internally a derived scene::MeshBuffer which has
the possibility to use the Hardware Vertex Buffer for static vertices and
dirty indices;-)
if defined OCTTREE_USE_HARDWARE octree uses internally a derived scene::CMeshBuffer
so it's not just a replacement inside the octree. It also in the OctTreeSceneNode.
#if defined (OCTTREE_USE_HARDWARE)
driver->drawMeshBuffer ( &LightMapMeshes[i] );
#else
driver->drawIndexedTriangleList( &LightMapMeshes[i].Vertices[0], LightMapMeshes[i].Vertices.size(),
d[i].Indices, d[i].CurrentSize / 3);
#endif
#define OCTTREE_PARENTTEST is also used. It's skip testing on fully outside and takes everything on fully inside
- virtual void ISceneNode::updateAbsolutePosition()
- changed
inline CMatrix4<T> CMatrix4<T>::operator*(const CMatrix4<T>& m2) const
all two matrices have to be checked by isIdentity()
to let the isIdentity work always
-changed inline bool CMatrix4<T>::isIdentity() const
on full identityCheck->
to look first on Translation, because this is the most challenging element
which will likely not to be identity..
- virtual core::matrix4 getRelativeTransformation() const
Hiarchy on Identity-Check
1) ->getRelativeTransform -> 9 floating point checks to be passed as Identity
2) ->isIdentity () -> 16 floating point checks to be passed as Identity
- inline void CMatrix4<T>::transformBoxEx(core::aabbox3d<f32>& box) const
added isIdentity() check
- changed CSceneNodeAnimatorCollisionResponse
- added CSceneNodeAnimatorCollisionResponse::setGravity
needed to set the differents Forces for the Animator. for eq. water..
- added CSceneNodeAnimatorCollisionResponse::setAnimateTarget
- added CSceneNodeAnimatorCollisionResponse::getAnimateTarget
- changed CSceneNodeAnimatorCollisionResponse::animateNode to react on FirstUpdate
- changad Gravity to
- TODO: set Gravity to Physically frame independent values..
current response uses an frame depdended acceleration vector.
~9.81 m/s^2 was achieved at around 50 fps with a setting of -0.03
may effect existing application..
- SceneNodes
- CSkyDomeSceneNode
moved radius ( default 1000 ) to constructor
added Normals
added DebugInfo
added Material.ZBuffer, added SceneMaanager
- CVolumeLightSceneNode:
changed default blending OneTextureBlendgl_src_color gl_src_alpha to
EMT_TRANSPARENT_ADD_COLOR ( gl_src_color gl_one )
which gives the same effect on non-transparent-materials.
Following the unspoken guide-line, lowest effect as default
- added LensFlareSceneNode (from forum user gammaray, modified to work )
showing in example special fx
- changed SceneNode Skydome f64 to f32,
- AnimatedMesh
-Debug Data:
mesh normals didn't rotate with the scenenode fixed ( matrix-multiplication order)
- Camera SceneNode setPosition
Camera now finally allow to change position and target and updates all
effected animators..
a call to OnAnimate ( ) lastime < time or OnAnimate ( 0 ) will reset the
camera and fr. the collision animator to a new position
- Device:
added the current mousebutton state to the Mouse Event
so i need to get the current mouse state from the OS
-a dded to CIrrDeviceWin32
TODO:
- Linux and SDL Device
- GUI
- CGUIFont:
- added virtual void setInvisibleCharacters( const wchar_t *s ) = 0;
define which characters should not be drawn ( send to driver) by the font.
for example " " would not draw any space which is usually blank in most fonts
and saves rendering of ususally full blank alpha-sprites.
This saves a lot of rendering...
default:
setInvisibleCharacters ( L" " );
- added MultiLine rendering
should avoid to us CStaticText breaking text in future
- CGUIListBox
- changed Scrollbar LargeStepSize to ItemHeight
which easy enables to scroll line by line
- CGUIScrollBar
bug:
Create a Window and inside a listbox with a scrollbar or
a windowed irrlicht application
Click & hold Scrollbar Slider. move outside it's region.
Release Mouse. Go Back to Scrollbar.. it's moving always...
it's generally missing the event PRESSED_MOVED, which
leads to problem when an element is dragging, has a focus, or position loose
and gets focus back again. ( think of a drunken mouse sliding left&right during tracking )
so added the mouse Input Buttonstates on every mouse event
IrrDeviceWin32:
added event.MouseInput.ButtonStates = wParam & ( MK_LBUTTON | MK_RBUTTON | MK_MBUTTON );
TODO:
Linux & SDL
so now i can do this
case irr::EMIE_MOUSE_MOVED:
if ( !event.MouseInput.isLeftPressed () )
{
Dragging = false;
}
- bug:
Scrollbar notifyListBox notify when the scrollbar is clicked.
- changed timed event in draw to OnPostRender
Why the hell is a gui element firing a timed event
in a draw routine!!!!!. This should be corrected for all gui-elements.
- added GUI Image List from Reinhard Ostermeier, modified to work
added GUI Tree View from Reinhard Ostermeier, modified to work
shown in the Quake3MapShader Example
TODO: Spritebanks
- FileOpenDialog
changed the static text for the filename to an edit box.
- changed the interface for addEditBox to match with addStaticText
- changed the interface for addSpinBox to match with addEditBox
- added MouseWheel to Spinbox
- changed CGUITable CLICK_AREA from 3 to 12 to enable clicking on the visible marker
- CGUISpritebank
removed some crashes with empty Sprite banks
- IGUIScrollBar
added SetMin before min was always 0
changed ScrollWheel Direction on horizontal to move right on wheel up, left on wheel down
- IComboBox
-added ItemData
- removed IsVisbile check in IGUIElement::draw
- Image Loaders
- added TGA file type 2 ( grayscale uncompressed )
- added TGA file type (1) 8 Bit indexed color uncompressed
ColorConverter:
- added convert_B8G8R8toA8R8G8B8
- added convert_B8G8R8A8toA8R8G8B8
- Media Files
- added missing shaders and textures to map-20kdm2.
Taken from free implementation
- ball.wav. adjusted DC-Offset, amplified to -4dB, trim cross-zero
- impact.wav clip-restoration, trim cross-zero
- added gun.md2, gun.pcx to media-files
copyright issues!. i don't know from where this file came from...
i hope this is not from original quake2..
- added new irrlicht logo irrlicht3.png
i've taken the new layout. i should ask niko to use it.
- added Skydome picture to media files (skydome2.jpg) half/sphere
- OctTree
-added
#define OCTTREE_PARENTTEST ( default: disabled )
used to leave-out children test if the parent passed a complete frustum.
plus: leaves out children test
minus: all edges have to be checked
- added MesBuffer Hardware Hint Vertex to octtree
- CQuake3ShaderSceneNode:
- removed function releaseMesh
Shader doesn't copy the original mesh anymore ( saving memory )
so therefore this (for others often misleading ) function was removed
- changed constructor to take a (shared) destination meshbuffer for rendering
reducing vertex-memory to a half
- don't copy the original vertices anymore
- added deformvertexes autosprite
- added deformvertexes move
- added support for RTCW and Raven BSPs ( qmap2 )
- added polygonoffset (TODO: not perfect)
- added added nomipmaps
- added rgbgen const
- added alphagen
- added MesBuffer Hardware Hint Vertex/Index to Quake3: static geometry, dynamic indices
- added Quake3Explorer examples
- added wave noise
- added tcmod transform
- added whiteimage
- added collision to Quake3Explorer
- renamed SMD3QuaterionTag* to SMD3QuaternionTag* ( typo )
- updated quake3:blendfunc
- added crouch to Quake3Explorer
(modifying the ellipsiodRadius of the camera animator )
added crouch to CSceneNodeAnimatorCameraFPS
still problems with stand up and collision
- Quake3MapLoader
modified memory allocation for faster loading
- Quake3LoadParam
added Parameter to the Mesh-Loader
- added
The still existing missing caulking of curved surfaces.
using round in the coordinates doesn't solve the problem.
but for the demo bsp mesh it solves the problem... (luck)
so for now it's switchable.
TJUNCTION_SOLVER_ROUND
default:off
- BurningVideo
- pushed BurningsVideo to 0.40
- added blendfunc gl_one_minus_dst_alpha gl_one
- added blendfunc gl_dst_color gl_zero
- added blendfunc gl_dst_color src_alpha
- modified AlphaChannel_Ref renderer to support alpha test lessequal
- addded 32 Bit Index Buffer
- added sourceRect/destRect check to 2D-Blitter ( slower, but resolves crash )
- added setTextureCreationFlag video::ETCF_ALLOW_NON_POWER_2
Burning checks this flag and when set, it bypasses the power2 size check,
which is necessary on 3D but can be avoided on 2D.
used on fonts automatically.
- added Support for Destination Alpha
- OpenGL
- Fixed a bug in COpenGLExtensenionHandler where a glint was downcasted to u8!!!!!!
MaxTextureSize=static_cast<u32>(num);
- TODO: COpenGLMaterialRenderer_ONETEXTURE_BLEND to work as expected
- Direct3D8
- compile and links again
- added 32 Bit Index Buffer
- D3DSAMP_MIPMAPLODBIAS doesnt compile!. it is d3d9 i think.
- compile for XBOX
- Direc3D9
- fixed crash on RTT Textures DepthBuffer freed twice.
added deleteAllTextures to destuctor
- NullDriver
- removeallTextures. added setMaterial ( SMaterial() ) to clean pointers for freed textures
git-svn-id: svn://svn.code.sf.net/p/irrlicht/code/trunk@2147 dfc29bdd-3216-0410-991c-e03cc46cb475
2009-01-27 07:53:53 -08:00
core : : string < c16 > filename = CurrentlyLoadingMesh ;
2007-05-20 11:03:49 -07:00
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 + + )
{
2009-03-31 10:59:11 -07:00
const 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-20 15:07:53 -08:00
vtx . TCoords . Y = 1 - 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 )
{
2008-11-26 02:44:30 -08:00
for ( u32 ind = indices . size ( ) - 3 ; ind > 0 ; - - ind )
2008-11-13 09:35:17 -08:00
{
mbuffer - > Indices . push_back ( indices [ 0 ] ) ;
2008-11-26 02:44:30 -08:00
mbuffer - > Indices . push_back ( indices [ ind + 2 ] ) ;
mbuffer - > Indices . push_back ( indices [ ind + 1 ] ) ;
2008-11-13 09:35:17 -08:00
}
}
else
2008-01-23 09:15:15 -08:00
{
2008-11-26 02:44:30 -08:00
for ( u32 ind = 0 ; i + 2 < indices . size ( ) ; + + ind )
2008-11-13 09:35:17 -08:00
{
mbuffer - > Indices . push_back ( indices [ 0 ] ) ;
2008-11-26 02:44:30 -08:00
mbuffer - > Indices . push_back ( indices [ ind + 1 ] ) ;
mbuffer - > Indices . push_back ( indices [ ind + 2 ] ) ;
2008-11-13 09:35:17 -08:00
}
2008-01-23 09:15:15 -08:00
}
}
else
{
// it's just triangles
2008-11-26 02:44:30 -08:00
for ( u32 ind = 0 ; ind < indices . size ( ) ; ind + = 3 )
2008-01-23 09:15:15 -08:00
{
2008-11-13 09:35:17 -08:00
if ( FlipAxis )
{
2008-11-26 02:44:30 -08:00
mbuffer - > Indices . push_back ( indices [ ind + 2 ] ) ;
mbuffer - > Indices . push_back ( indices [ ind + 1 ] ) ;
mbuffer - > Indices . push_back ( indices [ ind + 0 ] ) ;
2008-11-13 09:35:17 -08:00
}
else
{
2008-11-26 02:44:30 -08:00
mbuffer - > Indices . push_back ( indices [ ind + 0 ] ) ;
mbuffer - > Indices . push_back ( indices [ ind + 1 ] ) ;
mbuffer - > Indices . push_back ( indices [ ind + 2 ] ) ;
2008-11-13 09:35:17 -08:00
}
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-20 15:07:53 -08:00
vtx . TCoords2 . Y = 1 - 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-20 15:07:53 -08:00
vtx . TCoords . Y = 1 - 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 " ) ;
2009-03-31 10:59:11 -07:00
if ( reader - > getAttributeValue ( " offset " ) ) // Collada 1.4+
p . Offset = ( u32 ) reader - > getAttributeValueAsInt ( " offset " ) ;
else // Collada 1.2/1.3
p . Offset = ( u32 ) reader - > getAttributeValueAsInt ( " idx " ) ;
2008-01-24 09:24:52 -08:00
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
{
Changes in version 1.6, TA
- FileSystem 2.0 SUPER MASTER MAJOR API CHANGE !!!
The FileSystem is know build internally like for e.q the texture-, and the meshloaders.
There exists a known list of ArchiveLoader, which know how to produce a Archive.
The Loaders and the Archive can be attached/detached on runtime.
The FileNames are now stored as core::string<c16>. where c16 is toggled between char/wchar
with the #define flag _IRR_WCHAR_FILESYSTEM, to supported unicode backends (default:off)
I replaced all (const c8* filename) to string references.
Basically the FileSystem is divided into two regions. Native and Virtual.
Native means using the backend OS.
Virtual means only use currently attach IArchives.
Browsing
each FileSystem has it's own workdirectory and it's own methods to
- create a FileTree
- add/remove files & directory ( to be done )
Hint: store a savegame in a zip archive...
basic browsing for all archives is implemented.
Example 21. Quake3Explorer shows this
TODO:
- a file filter should be implemented.
- The IArchive should have a function to create a filetree
for now CFileList is used.
Class Hiarchy:
IArchiveLoader: is able to produce a IFileArchive
- ZipLoader
- PakLoader
- MountPointReader ( formaly known as CUnzipReader )
IFileArchive:
-ZipArchive
-PakArchive
-MountPoint (known as FolderFile)
IFileSystem
- addArchiveLoader
- changed implementation of isALoadableFileExtension in all loaders
to have consistent behavior
- added a parameter to IFileList * createFileList
setFileListSystem
allows to query files in any of the game archives
standard behavior listtype = SYSTEM ( default)
- CLimitReadFile
added multiple file random-access support.
solved problems with mixed compressed & uncompressed files in a zip
TODO:
- Big Big Testing!!
- Linux Version ( minor )
- remove all double loader interfaces where only the filename differs
(IReadFile/const char *filename). This blows up the the interface
- many loaders use their own private filesearching
we should rework this
- there are a lot of helper function ( getAbsolutePath, getFileDir )
which should be adapted to the virtual filesystem
- IrrlichtDevice
added:
virtual bool setGammaRamp( f32 red, f32 green, f32 blue, f32 brightness, f32 contrast ) = 0;
virtual bool getGammaRamp( f32 &red, f32 &green, f32 &blue ) = 0;
and calculating methods to DeviceStub.
implemented in Win32, TODO: other Devices
- irrlicht.h
changed exported irrlicht.dll routines createDevice, createDeviceEx, IdentityMatrix
to extern "C" name mangling.
for easier dynamically loading the irrlicht library and different versions
- ParticleSystem
removed the private (old?,wrong?) interface from the ParticleEffectors
to match the parent class irr::io::IAttributeExchangingObject::deserializeAttributes
TODO:
please test if the serialization works!
- Generic
- vector3d<T>& normalize()
#if 0
f32 length = (f32)(X*X + Y*Y + Z*Z);
if (core::equals(length, 0.f))
return *this;
length = core::reciprocal_squareroot ( (f32)length );
#else
const T length = core::reciprocal_squareroot ( (X*X + Y*Y + Z*Z) );
#endif
Weak checking on zero?!?! just to avoid a sqrt?. mhm, maybe not;-)
added reciprocal_squareroot for f64
- dimension2d
added operator dimension2d<T>& operator=(const dimension2d<U>& other)
to cast between different types
- vector2d
bugfix:
vector2d<T>& operator+=(const dimension2d<T>& other) { X += other.Width; Y += other.Width; return *this; }
to
vector2d<T>& operator+=(const dimension2d<T>& other) { X += other.Width; Y += other.Height; return *this; }
- C3DMeshLoader renamed chunks const u16 to a enum
removing "variable declared but never used warning"
- added a global const identity Material
changed all references *((video::SMaterial*)0) to point to IdentityMaterial
removed warning: "a NULL reference is not allowed"
- modified IRRLICHT_MATH to not support reciprocal stuff
but to use faster float-to-int conversion.
gcc troubles may they are. i'm using intel-compiler..;-)
- core::matrix4
USE_MATRIX_TEST
i tried to optimize the identity-check ( in means of performance)
i didn't succeed so well, so i made a define for the matrix isIdentity -check
for now it's sometimes faster to always calculate versus identity-check
but if there are a lot of scenenodes/ particles one can profit from the
fast_inverse matrix, when no scaling is used. further approvement could
be done on inverse for just tranlastion! ( many static scenenodes are not rotated,
they are just placed somewhere in the world)
one thing to take in account is that sizeof(matrix) is 64 byte and
with the additional bool/u32 makes it 66 byte which is not really cache-friendly..
- added buildRotateFromTo
Builds a matrix that rotates from one vector to another
- irr::array. changed allocating routine in push_back
okt, 2008. it's only allowed to alloc one element, if
default constructor has to be called.
removes existing crashes. ( MD3 Mesh ) and possible others ones.
A new list template should be made.
one with constructor/destructor calls ( safe_array ) and
one without. like the array since the beginning of irrlicht.
currently the array/string is extremly slow..
also a hint for the user has to be done, so that a struct T of
array<T> must have a copy constructor of type T ( const T&other ).
i needed hours to track that down...
added a new method setAllocStrategy,
safe ( used + 1 ), double ( used * 2 + 1)
better default strategies will be implemented
- removed binary_search_const
i added it quite a long time ago, but it doesnt make real sense
a call to a sort method should happen always. i just wanted to safe
a few cycles..
- added binary_search_multi
searches for a multi-set ( more than 1 entry in the sorted array)
returns start and end-index
- changed some identity matrix settings to use core::IdentityMatrix
- added deletePathFromFilename to generic string functions in coreutil.h and
removed from CZipReader and CPakReader
- s32 deserializeAttributes used instead of virtual void deserializeAttributes in
ParticleSystem ( wrong virtual was used)
- strings & Locale
- started to add locale support
- added verify to string
- added some helper functions
- XBOX
i have access to a XBOX development machine now. I started to compile
for the XBOX. Question: Who did the previous implementation?. There
is no XBOX-Device inhere. maybe it's forbidden because of using the offical
Microsoft XDK. I will implement a native or sdl device based on opendk.
irrlicht compiles without errors on the xbox but can't be used.
TODO:
- native XBOX Device
- Windows Mobile
reworked a little. added the mobile example to the windows solution for
cross development.
added maximal 128x128 texture size for windows mobile ( memory issues )
- Collision Speed Up
The Collision Speed Up greatly improves with many small static child-nodes
- added COctTreeTriangleSelector::getTriangles for 3dline from user Piraaate
- modified createOctTreeTriangleSelector and createTriangleSelector
to allow node == 0, to be added to a meta selector
- CSceneNodeAnimatorCollisionResponse has the same problem as CSceneNodeAnimatorFPS
on first update:
Problem. you start setting the map. (setWorld). First update cames 4000 ms later.
The Animator applies the missing force... big problem...
changed to react on first update like camera.
- add Variable FirstUpdate. if set to true ( on all changes )
then position, lasttime, and falling are initialized
-added #define OCTTREE_USE_HARDWARE in Octree.h
if defined octtree uses internally a derived scene::MeshBuffer which has
the possibility to use the Hardware Vertex Buffer for static vertices and
dirty indices;-)
if defined OCTTREE_USE_HARDWARE octree uses internally a derived scene::CMeshBuffer
so it's not just a replacement inside the octree. It also in the OctTreeSceneNode.
#if defined (OCTTREE_USE_HARDWARE)
driver->drawMeshBuffer ( &LightMapMeshes[i] );
#else
driver->drawIndexedTriangleList( &LightMapMeshes[i].Vertices[0], LightMapMeshes[i].Vertices.size(),
d[i].Indices, d[i].CurrentSize / 3);
#endif
#define OCTTREE_PARENTTEST is also used. It's skip testing on fully outside and takes everything on fully inside
- virtual void ISceneNode::updateAbsolutePosition()
- changed
inline CMatrix4<T> CMatrix4<T>::operator*(const CMatrix4<T>& m2) const
all two matrices have to be checked by isIdentity()
to let the isIdentity work always
-changed inline bool CMatrix4<T>::isIdentity() const
on full identityCheck->
to look first on Translation, because this is the most challenging element
which will likely not to be identity..
- virtual core::matrix4 getRelativeTransformation() const
Hiarchy on Identity-Check
1) ->getRelativeTransform -> 9 floating point checks to be passed as Identity
2) ->isIdentity () -> 16 floating point checks to be passed as Identity
- inline void CMatrix4<T>::transformBoxEx(core::aabbox3d<f32>& box) const
added isIdentity() check
- changed CSceneNodeAnimatorCollisionResponse
- added CSceneNodeAnimatorCollisionResponse::setGravity
needed to set the differents Forces for the Animator. for eq. water..
- added CSceneNodeAnimatorCollisionResponse::setAnimateTarget
- added CSceneNodeAnimatorCollisionResponse::getAnimateTarget
- changed CSceneNodeAnimatorCollisionResponse::animateNode to react on FirstUpdate
- changad Gravity to
- TODO: set Gravity to Physically frame independent values..
current response uses an frame depdended acceleration vector.
~9.81 m/s^2 was achieved at around 50 fps with a setting of -0.03
may effect existing application..
- SceneNodes
- CSkyDomeSceneNode
moved radius ( default 1000 ) to constructor
added Normals
added DebugInfo
added Material.ZBuffer, added SceneMaanager
- CVolumeLightSceneNode:
changed default blending OneTextureBlendgl_src_color gl_src_alpha to
EMT_TRANSPARENT_ADD_COLOR ( gl_src_color gl_one )
which gives the same effect on non-transparent-materials.
Following the unspoken guide-line, lowest effect as default
- added LensFlareSceneNode (from forum user gammaray, modified to work )
showing in example special fx
- changed SceneNode Skydome f64 to f32,
- AnimatedMesh
-Debug Data:
mesh normals didn't rotate with the scenenode fixed ( matrix-multiplication order)
- Camera SceneNode setPosition
Camera now finally allow to change position and target and updates all
effected animators..
a call to OnAnimate ( ) lastime < time or OnAnimate ( 0 ) will reset the
camera and fr. the collision animator to a new position
- Device:
added the current mousebutton state to the Mouse Event
so i need to get the current mouse state from the OS
-a dded to CIrrDeviceWin32
TODO:
- Linux and SDL Device
- GUI
- CGUIFont:
- added virtual void setInvisibleCharacters( const wchar_t *s ) = 0;
define which characters should not be drawn ( send to driver) by the font.
for example " " would not draw any space which is usually blank in most fonts
and saves rendering of ususally full blank alpha-sprites.
This saves a lot of rendering...
default:
setInvisibleCharacters ( L" " );
- added MultiLine rendering
should avoid to us CStaticText breaking text in future
- CGUIListBox
- changed Scrollbar LargeStepSize to ItemHeight
which easy enables to scroll line by line
- CGUIScrollBar
bug:
Create a Window and inside a listbox with a scrollbar or
a windowed irrlicht application
Click & hold Scrollbar Slider. move outside it's region.
Release Mouse. Go Back to Scrollbar.. it's moving always...
it's generally missing the event PRESSED_MOVED, which
leads to problem when an element is dragging, has a focus, or position loose
and gets focus back again. ( think of a drunken mouse sliding left&right during tracking )
so added the mouse Input Buttonstates on every mouse event
IrrDeviceWin32:
added event.MouseInput.ButtonStates = wParam & ( MK_LBUTTON | MK_RBUTTON | MK_MBUTTON );
TODO:
Linux & SDL
so now i can do this
case irr::EMIE_MOUSE_MOVED:
if ( !event.MouseInput.isLeftPressed () )
{
Dragging = false;
}
- bug:
Scrollbar notifyListBox notify when the scrollbar is clicked.
- changed timed event in draw to OnPostRender
Why the hell is a gui element firing a timed event
in a draw routine!!!!!. This should be corrected for all gui-elements.
- added GUI Image List from Reinhard Ostermeier, modified to work
added GUI Tree View from Reinhard Ostermeier, modified to work
shown in the Quake3MapShader Example
TODO: Spritebanks
- FileOpenDialog
changed the static text for the filename to an edit box.
- changed the interface for addEditBox to match with addStaticText
- changed the interface for addSpinBox to match with addEditBox
- added MouseWheel to Spinbox
- changed CGUITable CLICK_AREA from 3 to 12 to enable clicking on the visible marker
- CGUISpritebank
removed some crashes with empty Sprite banks
- IGUIScrollBar
added SetMin before min was always 0
changed ScrollWheel Direction on horizontal to move right on wheel up, left on wheel down
- IComboBox
-added ItemData
- removed IsVisbile check in IGUIElement::draw
- Image Loaders
- added TGA file type 2 ( grayscale uncompressed )
- added TGA file type (1) 8 Bit indexed color uncompressed
ColorConverter:
- added convert_B8G8R8toA8R8G8B8
- added convert_B8G8R8A8toA8R8G8B8
- Media Files
- added missing shaders and textures to map-20kdm2.
Taken from free implementation
- ball.wav. adjusted DC-Offset, amplified to -4dB, trim cross-zero
- impact.wav clip-restoration, trim cross-zero
- added gun.md2, gun.pcx to media-files
copyright issues!. i don't know from where this file came from...
i hope this is not from original quake2..
- added new irrlicht logo irrlicht3.png
i've taken the new layout. i should ask niko to use it.
- added Skydome picture to media files (skydome2.jpg) half/sphere
- OctTree
-added
#define OCTTREE_PARENTTEST ( default: disabled )
used to leave-out children test if the parent passed a complete frustum.
plus: leaves out children test
minus: all edges have to be checked
- added MesBuffer Hardware Hint Vertex to octtree
- CQuake3ShaderSceneNode:
- removed function releaseMesh
Shader doesn't copy the original mesh anymore ( saving memory )
so therefore this (for others often misleading ) function was removed
- changed constructor to take a (shared) destination meshbuffer for rendering
reducing vertex-memory to a half
- don't copy the original vertices anymore
- added deformvertexes autosprite
- added deformvertexes move
- added support for RTCW and Raven BSPs ( qmap2 )
- added polygonoffset (TODO: not perfect)
- added added nomipmaps
- added rgbgen const
- added alphagen
- added MesBuffer Hardware Hint Vertex/Index to Quake3: static geometry, dynamic indices
- added Quake3Explorer examples
- added wave noise
- added tcmod transform
- added whiteimage
- added collision to Quake3Explorer
- renamed SMD3QuaterionTag* to SMD3QuaternionTag* ( typo )
- updated quake3:blendfunc
- added crouch to Quake3Explorer
(modifying the ellipsiodRadius of the camera animator )
added crouch to CSceneNodeAnimatorCameraFPS
still problems with stand up and collision
- Quake3MapLoader
modified memory allocation for faster loading
- Quake3LoadParam
added Parameter to the Mesh-Loader
- added
The still existing missing caulking of curved surfaces.
using round in the coordinates doesn't solve the problem.
but for the demo bsp mesh it solves the problem... (luck)
so for now it's switchable.
TJUNCTION_SOLVER_ROUND
default:off
- BurningVideo
- pushed BurningsVideo to 0.40
- added blendfunc gl_one_minus_dst_alpha gl_one
- added blendfunc gl_dst_color gl_zero
- added blendfunc gl_dst_color src_alpha
- modified AlphaChannel_Ref renderer to support alpha test lessequal
- addded 32 Bit Index Buffer
- added sourceRect/destRect check to 2D-Blitter ( slower, but resolves crash )
- added setTextureCreationFlag video::ETCF_ALLOW_NON_POWER_2
Burning checks this flag and when set, it bypasses the power2 size check,
which is necessary on 3D but can be avoided on 2D.
used on fonts automatically.
- added Support for Destination Alpha
- OpenGL
- Fixed a bug in COpenGLExtensenionHandler where a glint was downcasted to u8!!!!!!
MaxTextureSize=static_cast<u32>(num);
- TODO: COpenGLMaterialRenderer_ONETEXTURE_BLEND to work as expected
- Direct3D8
- compile and links again
- added 32 Bit Index Buffer
- D3DSAMP_MIPMAPLODBIAS doesnt compile!. it is d3d9 i think.
- compile for XBOX
- Direc3D9
- fixed crash on RTT Textures DepthBuffer freed twice.
added deleteAllTextures to destuctor
- NullDriver
- removeallTextures. added setMaterial ( SMaterial() ) to clean pointers for freed textures
git-svn-id: svn://svn.code.sf.net/p/irrlicht/code/trunk@2147 dfc29bdd-3216-0410-991c-e03cc46cb475
2009-01-27 07:53:53 -08:00
if ( FileSystem - > existFile ( Images [ i ] . Source ) )
return driver - > getTexture ( Images [ i ] . Source ) ;
return driver - > getTexture ( ( FileSystem - > getFileDir ( CurrentlyLoadingMesh ) + " / " + Images [ i ] . Source ) ) ;
2008-02-20 09:17:42 -08:00
}
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