aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/libraries/irrlicht-1.8/source/Irrlicht/CColladaFileLoader.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'libraries/irrlicht-1.8/source/Irrlicht/CColladaFileLoader.cpp')
-rw-r--r--libraries/irrlicht-1.8/source/Irrlicht/CColladaFileLoader.cpp5914
1 files changed, 2957 insertions, 2957 deletions
diff --git a/libraries/irrlicht-1.8/source/Irrlicht/CColladaFileLoader.cpp b/libraries/irrlicht-1.8/source/Irrlicht/CColladaFileLoader.cpp
index 6509812..210a59b 100644
--- a/libraries/irrlicht-1.8/source/Irrlicht/CColladaFileLoader.cpp
+++ b/libraries/irrlicht-1.8/source/Irrlicht/CColladaFileLoader.cpp
@@ -1,2957 +1,2957 @@
1// Copyright (C) 2002-2012 Nikolaus Gebhardt 1// Copyright (C) 2002-2012 Nikolaus Gebhardt
2// This file is part of the "Irrlicht Engine". 2// This file is part of the "Irrlicht Engine".
3// For conditions of distribution and use, see copyright notice in irrlicht.h 3// For conditions of distribution and use, see copyright notice in irrlicht.h
4 4
5#include "IrrCompileConfig.h" 5#include "IrrCompileConfig.h"
6#ifdef _IRR_COMPILE_WITH_COLLADA_LOADER_ 6#ifdef _IRR_COMPILE_WITH_COLLADA_LOADER_
7 7
8#include "CColladaFileLoader.h" 8#include "CColladaFileLoader.h"
9#include "os.h" 9#include "os.h"
10#include "IXMLReader.h" 10#include "IXMLReader.h"
11#include "IDummyTransformationSceneNode.h" 11#include "IDummyTransformationSceneNode.h"
12#include "SAnimatedMesh.h" 12#include "SAnimatedMesh.h"
13#include "fast_atof.h" 13#include "fast_atof.h"
14#include "quaternion.h" 14#include "quaternion.h"
15#include "ILightSceneNode.h" 15#include "ILightSceneNode.h"
16#include "ICameraSceneNode.h" 16#include "ICameraSceneNode.h"
17#include "IMeshManipulator.h" 17#include "IMeshManipulator.h"
18#include "IReadFile.h" 18#include "IReadFile.h"
19#include "IAttributes.h" 19#include "IAttributes.h"
20#include "IMeshCache.h" 20#include "IMeshCache.h"
21#include "IMeshSceneNode.h" 21#include "IMeshSceneNode.h"
22#include "SMeshBufferLightMap.h" 22#include "SMeshBufferLightMap.h"
23#include "irrMap.h" 23#include "irrMap.h"
24 24
25#ifdef _DEBUG 25#ifdef _DEBUG
26#define COLLADA_READER_DEBUG 26#define COLLADA_READER_DEBUG
27#endif 27#endif
28namespace irr 28namespace irr
29{ 29{
30namespace scene 30namespace scene
31{ 31{
32namespace 32namespace
33{ 33{
34 // currently supported COLLADA tag names 34 // currently supported COLLADA tag names
35 const core::stringc colladaSectionName = "COLLADA"; 35 const core::stringc colladaSectionName = "COLLADA";
36 const core::stringc librarySectionName = "library"; 36 const core::stringc librarySectionName = "library";
37 const core::stringc libraryNodesSectionName = "library_nodes"; 37 const core::stringc libraryNodesSectionName = "library_nodes";
38 const core::stringc libraryGeometriesSectionName = "library_geometries"; 38 const core::stringc libraryGeometriesSectionName = "library_geometries";
39 const core::stringc libraryMaterialsSectionName = "library_materials"; 39 const core::stringc libraryMaterialsSectionName = "library_materials";
40 const core::stringc libraryImagesSectionName = "library_images"; 40 const core::stringc libraryImagesSectionName = "library_images";
41 const core::stringc libraryVisualScenesSectionName = "library_visual_scenes"; 41 const core::stringc libraryVisualScenesSectionName = "library_visual_scenes";
42 const core::stringc libraryCamerasSectionName = "library_cameras"; 42 const core::stringc libraryCamerasSectionName = "library_cameras";
43 const core::stringc libraryLightsSectionName = "library_lights"; 43 const core::stringc libraryLightsSectionName = "library_lights";
44 const core::stringc libraryEffectsSectionName = "library_effects"; 44 const core::stringc libraryEffectsSectionName = "library_effects";
45 const core::stringc assetSectionName = "asset"; 45 const core::stringc assetSectionName = "asset";
46 const core::stringc sceneSectionName = "scene"; 46 const core::stringc sceneSectionName = "scene";
47 const core::stringc visualSceneSectionName = "visual_scene"; 47 const core::stringc visualSceneSectionName = "visual_scene";
48 48
49 const core::stringc lightPrefabName = "light"; 49 const core::stringc lightPrefabName = "light";
50 const core::stringc cameraPrefabName = "camera"; 50 const core::stringc cameraPrefabName = "camera";
51 const core::stringc materialSectionName = "material"; 51 const core::stringc materialSectionName = "material";
52 const core::stringc geometrySectionName = "geometry"; 52 const core::stringc geometrySectionName = "geometry";
53 const core::stringc imageSectionName = "image"; 53 const core::stringc imageSectionName = "image";
54 const core::stringc textureSectionName = "texture"; 54 const core::stringc textureSectionName = "texture";
55 const core::stringc effectSectionName = "effect"; 55 const core::stringc effectSectionName = "effect";
56 56
57 const core::stringc pointSectionName = "point"; 57 const core::stringc pointSectionName = "point";
58 const core::stringc directionalSectionName ="directional"; 58 const core::stringc directionalSectionName ="directional";
59 const core::stringc spotSectionName = "spot"; 59 const core::stringc spotSectionName = "spot";
60 const core::stringc ambientSectionName = "ambient"; 60 const core::stringc ambientSectionName = "ambient";
61 const core::stringc meshSectionName = "mesh"; 61 const core::stringc meshSectionName = "mesh";
62 const core::stringc sourceSectionName = "source"; 62 const core::stringc sourceSectionName = "source";
63 const core::stringc arraySectionName = "array"; 63 const core::stringc arraySectionName = "array";
64 const core::stringc floatArraySectionName ="float_array"; 64 const core::stringc floatArraySectionName ="float_array";
65 const core::stringc intArraySectionName = "int_array"; 65 const core::stringc intArraySectionName = "int_array";
66 const core::stringc techniqueCommonSectionName = "technique_common"; 66 const core::stringc techniqueCommonSectionName = "technique_common";
67 const core::stringc accessorSectionName = "accessor"; 67 const core::stringc accessorSectionName = "accessor";
68 const core::stringc verticesSectionName = "vertices"; 68 const core::stringc verticesSectionName = "vertices";
69 const core::stringc inputTagName = "input"; 69 const core::stringc inputTagName = "input";
70 const core::stringc polylistSectionName = "polylist"; 70 const core::stringc polylistSectionName = "polylist";
71 const core::stringc trianglesSectionName = "triangles"; 71 const core::stringc trianglesSectionName = "triangles";
72 const core::stringc polygonsSectionName = "polygons"; 72 const core::stringc polygonsSectionName = "polygons";
73 const core::stringc primitivesName = "p"; 73 const core::stringc primitivesName = "p";
74 const core::stringc vcountName = "vcount"; 74 const core::stringc vcountName = "vcount";
75 75
76 const core::stringc upAxisNodeName = "up_axis"; 76 const core::stringc upAxisNodeName = "up_axis";
77 const core::stringc nodeSectionName = "node"; 77 const core::stringc nodeSectionName = "node";
78 const core::stringc lookatNodeName = "lookat"; 78 const core::stringc lookatNodeName = "lookat";
79 const core::stringc matrixNodeName = "matrix"; 79 const core::stringc matrixNodeName = "matrix";
80 const core::stringc perspectiveNodeName = "perspective"; 80 const core::stringc perspectiveNodeName = "perspective";
81 const core::stringc rotateNodeName = "rotate"; 81 const core::stringc rotateNodeName = "rotate";
82 const core::stringc scaleNodeName = "scale"; 82 const core::stringc scaleNodeName = "scale";
83 const core::stringc translateNodeName = "translate"; 83 const core::stringc translateNodeName = "translate";
84 const core::stringc skewNodeName = "skew"; 84 const core::stringc skewNodeName = "skew";
85 const core::stringc bboxNodeName = "boundingbox"; 85 const core::stringc bboxNodeName = "boundingbox";
86 const core::stringc minNodeName = "min"; 86 const core::stringc minNodeName = "min";
87 const core::stringc maxNodeName = "max"; 87 const core::stringc maxNodeName = "max";
88 const core::stringc instanceName = "instance"; 88 const core::stringc instanceName = "instance";
89 const core::stringc instanceGeometryName = "instance_geometry"; 89 const core::stringc instanceGeometryName = "instance_geometry";
90 const core::stringc instanceSceneName = "instance_visual_scene"; 90 const core::stringc instanceSceneName = "instance_visual_scene";
91 const core::stringc instanceEffectName = "instance_effect"; 91 const core::stringc instanceEffectName = "instance_effect";
92 const core::stringc instanceMaterialName = "instance_material"; 92 const core::stringc instanceMaterialName = "instance_material";
93 const core::stringc instanceLightName = "instance_light"; 93 const core::stringc instanceLightName = "instance_light";
94 const core::stringc instanceNodeName = "instance_node"; 94 const core::stringc instanceNodeName = "instance_node";
95 const core::stringc bindMaterialName = "bind_material"; 95 const core::stringc bindMaterialName = "bind_material";
96 const core::stringc extraNodeName = "extra"; 96 const core::stringc extraNodeName = "extra";
97 const core::stringc techniqueNodeName = "technique"; 97 const core::stringc techniqueNodeName = "technique";
98 const core::stringc colorNodeName = "color"; 98 const core::stringc colorNodeName = "color";
99 const core::stringc floatNodeName = "float"; 99 const core::stringc floatNodeName = "float";
100 const core::stringc float2NodeName = "float2"; 100 const core::stringc float2NodeName = "float2";
101 const core::stringc float3NodeName = "float3"; 101 const core::stringc float3NodeName = "float3";
102 102
103 const core::stringc newParamName = "newparam"; 103 const core::stringc newParamName = "newparam";
104 const core::stringc paramTagName = "param"; 104 const core::stringc paramTagName = "param";
105 const core::stringc initFromName = "init_from"; 105 const core::stringc initFromName = "init_from";
106 const core::stringc dataName = "data"; 106 const core::stringc dataName = "data";
107 const core::stringc wrapsName = "wrap_s"; 107 const core::stringc wrapsName = "wrap_s";
108 const core::stringc wraptName = "wrap_t"; 108 const core::stringc wraptName = "wrap_t";
109 const core::stringc minfilterName = "minfilter"; 109 const core::stringc minfilterName = "minfilter";
110 const core::stringc magfilterName = "magfilter"; 110 const core::stringc magfilterName = "magfilter";
111 const core::stringc mipfilterName = "mipfilter"; 111 const core::stringc mipfilterName = "mipfilter";
112 112
113 const core::stringc textureNodeName = "texture"; 113 const core::stringc textureNodeName = "texture";
114 const core::stringc doubleSidedNodeName = "double_sided"; 114 const core::stringc doubleSidedNodeName = "double_sided";
115 const core::stringc constantAttenuationNodeName = "constant_attenuation"; 115 const core::stringc constantAttenuationNodeName = "constant_attenuation";
116 const core::stringc linearAttenuationNodeName = "linear_attenuation"; 116 const core::stringc linearAttenuationNodeName = "linear_attenuation";
117 const core::stringc quadraticAttenuationNodeName = "quadratic_attenuation"; 117 const core::stringc quadraticAttenuationNodeName = "quadratic_attenuation";
118 const core::stringc falloffAngleNodeName = "falloff_angle"; 118 const core::stringc falloffAngleNodeName = "falloff_angle";
119 const core::stringc falloffExponentNodeName = "falloff_exponent"; 119 const core::stringc falloffExponentNodeName = "falloff_exponent";
120 120
121 const core::stringc profileCOMMONSectionName = "profile_COMMON"; 121 const core::stringc profileCOMMONSectionName = "profile_COMMON";
122 const core::stringc profileCOMMONAttributeName = "COMMON"; 122 const core::stringc profileCOMMONAttributeName = "COMMON";
123 123
124 const char* const inputSemanticNames[] = {"POSITION", "VERTEX", "NORMAL", "TEXCOORD", 124 const char* const inputSemanticNames[] = {"POSITION", "VERTEX", "NORMAL", "TEXCOORD",
125 "UV", "TANGENT", "IMAGE", "TEXTURE", 0}; 125 "UV", "TANGENT", "IMAGE", "TEXTURE", 0};
126 126
127 // We have to read ambient lights like other light types here, so we need a type for it 127 // We have to read ambient lights like other light types here, so we need a type for it
128 const video::E_LIGHT_TYPE ELT_AMBIENT = video::E_LIGHT_TYPE(video::ELT_COUNT+1); 128 const video::E_LIGHT_TYPE ELT_AMBIENT = video::E_LIGHT_TYPE(video::ELT_COUNT+1);
129} 129}
130 130
131 //! following class is for holding and creating instances of library 131 //! following class is for holding and creating instances of library
132 //! objects, named prefabs in this loader. 132 //! objects, named prefabs in this loader.
133 class CPrefab : public IColladaPrefab 133 class CPrefab : public IColladaPrefab
134 { 134 {
135 public: 135 public:
136 136
137 CPrefab(const core::stringc& id) : Id(id) 137 CPrefab(const core::stringc& id) : Id(id)
138 { 138 {
139 } 139 }
140 140
141 //! creates an instance of this prefab 141 //! creates an instance of this prefab
142 virtual scene::ISceneNode* addInstance(scene::ISceneNode* parent, 142 virtual scene::ISceneNode* addInstance(scene::ISceneNode* parent,
143 scene::ISceneManager* mgr) 143 scene::ISceneManager* mgr)
144 { 144 {
145 // empty implementation 145 // empty implementation
146 return 0; 146 return 0;
147 } 147 }
148 148
149 //! returns id of this prefab 149 //! returns id of this prefab
150 virtual const core::stringc& getId() 150 virtual const core::stringc& getId()
151 { 151 {
152 return Id; 152 return Id;
153 } 153 }
154 154
155 protected: 155 protected:
156 156
157 core::stringc Id; 157 core::stringc Id;
158 }; 158 };
159 159
160 160
161 //! prefab for a light scene node 161 //! prefab for a light scene node
162 class CLightPrefab : public CPrefab 162 class CLightPrefab : public CPrefab
163 { 163 {
164 public: 164 public:
165 165
166 CLightPrefab(const core::stringc& id) : CPrefab(id) 166 CLightPrefab(const core::stringc& id) : CPrefab(id)
167 { 167 {
168 #ifdef COLLADA_READER_DEBUG 168 #ifdef COLLADA_READER_DEBUG
169 os::Printer::log("COLLADA: loaded light prefab", Id.c_str(), ELL_DEBUG); 169 os::Printer::log("COLLADA: loaded light prefab", Id.c_str(), ELL_DEBUG);
170 #endif 170 #endif
171 } 171 }
172 172
173 video::SLight LightData; // publically accessible 173 video::SLight LightData; // publically accessible
174 174
175 //! creates an instance of this prefab 175 //! creates an instance of this prefab
176 virtual scene::ISceneNode* addInstance(scene::ISceneNode* parent, 176 virtual scene::ISceneNode* addInstance(scene::ISceneNode* parent,
177 scene::ISceneManager* mgr) 177 scene::ISceneManager* mgr)
178 { 178 {
179 #ifdef COLLADA_READER_DEBUG 179 #ifdef COLLADA_READER_DEBUG
180 os::Printer::log("COLLADA: Constructing light instance", Id.c_str(), ELL_DEBUG); 180 os::Printer::log("COLLADA: Constructing light instance", Id.c_str(), ELL_DEBUG);
181 #endif 181 #endif
182 182
183 if ( LightData.Type == ELT_AMBIENT ) 183 if ( LightData.Type == ELT_AMBIENT )
184 { 184 {
185 mgr->setAmbientLight( LightData.DiffuseColor ); 185 mgr->setAmbientLight( LightData.DiffuseColor );
186 return 0; 186 return 0;
187 } 187 }
188 188
189 scene::ILightSceneNode* l = mgr->addLightSceneNode(parent); 189 scene::ILightSceneNode* l = mgr->addLightSceneNode(parent);
190 if (l) 190 if (l)
191 { 191 {
192 l->setLightData ( LightData ); 192 l->setLightData ( LightData );
193 l->setName(getId()); 193 l->setName(getId());
194 } 194 }
195 return l; 195 return l;
196 } 196 }
197 }; 197 };
198 198
199 199
200 //! prefab for a mesh scene node 200 //! prefab for a mesh scene node
201 class CGeometryPrefab : public CPrefab 201 class CGeometryPrefab : public CPrefab
202 { 202 {
203 public: 203 public:
204 204
205 CGeometryPrefab(const core::stringc& id) : CPrefab(id) 205 CGeometryPrefab(const core::stringc& id) : CPrefab(id)
206 { 206 {
207 } 207 }
208 208
209 scene::IMesh* Mesh; 209 scene::IMesh* Mesh;
210 210
211 //! creates an instance of this prefab 211 //! creates an instance of this prefab
212 virtual scene::ISceneNode* addInstance(scene::ISceneNode* parent, 212 virtual scene::ISceneNode* addInstance(scene::ISceneNode* parent,
213 scene::ISceneManager* mgr) 213 scene::ISceneManager* mgr)
214 { 214 {
215 #ifdef COLLADA_READER_DEBUG 215 #ifdef COLLADA_READER_DEBUG
216 os::Printer::log("COLLADA: Constructing mesh instance", Id.c_str(), ELL_DEBUG); 216 os::Printer::log("COLLADA: Constructing mesh instance", Id.c_str(), ELL_DEBUG);
217 #endif 217 #endif
218 218
219 scene::ISceneNode* m = mgr->addMeshSceneNode(Mesh, parent); 219 scene::ISceneNode* m = mgr->addMeshSceneNode(Mesh, parent);
220 if (m) 220 if (m)
221 { 221 {
222 m->setName(getId()); 222 m->setName(getId());
223// m->setMaterialFlag(video::EMF_BACK_FACE_CULLING, false); 223// m->setMaterialFlag(video::EMF_BACK_FACE_CULLING, false);
224// m->setDebugDataVisible(scene::EDS_FULL); 224// m->setDebugDataVisible(scene::EDS_FULL);
225 } 225 }
226 return m; 226 return m;
227 } 227 }
228 }; 228 };
229 229
230 230
231 //! prefab for a camera scene node 231 //! prefab for a camera scene node
232 class CCameraPrefab : public CPrefab 232 class CCameraPrefab : public CPrefab
233 { 233 {
234 public: 234 public:
235 235
236 CCameraPrefab(const core::stringc& id) 236 CCameraPrefab(const core::stringc& id)
237 : CPrefab(id), YFov(core::PI / 2.5f), ZNear(1.0f), ZFar(3000.0f) 237 : CPrefab(id), YFov(core::PI / 2.5f), ZNear(1.0f), ZFar(3000.0f)
238 { 238 {
239 #ifdef COLLADA_READER_DEBUG 239 #ifdef COLLADA_READER_DEBUG
240 os::Printer::log("COLLADA: loaded camera prefab", Id.c_str(), ELL_DEBUG); 240 os::Printer::log("COLLADA: loaded camera prefab", Id.c_str(), ELL_DEBUG);
241 #endif 241 #endif
242 } 242 }
243 243
244 // publicly accessible data 244 // publicly accessible data
245 f32 YFov; 245 f32 YFov;
246 f32 ZNear; 246 f32 ZNear;
247 f32 ZFar; 247 f32 ZFar;
248 248
249 //! creates an instance of this prefab 249 //! creates an instance of this prefab
250 virtual scene::ISceneNode* addInstance(scene::ISceneNode* parent, 250 virtual scene::ISceneNode* addInstance(scene::ISceneNode* parent,
251 scene::ISceneManager* mgr) 251 scene::ISceneManager* mgr)
252 { 252 {
253 #ifdef COLLADA_READER_DEBUG 253 #ifdef COLLADA_READER_DEBUG
254 os::Printer::log("COLLADA: Constructing camera instance", Id.c_str(), ELL_DEBUG); 254 os::Printer::log("COLLADA: Constructing camera instance", Id.c_str(), ELL_DEBUG);
255 #endif 255 #endif
256 256
257 scene::ICameraSceneNode* c = mgr->addCameraSceneNode(parent); 257 scene::ICameraSceneNode* c = mgr->addCameraSceneNode(parent);
258 if (c) 258 if (c)
259 { 259 {
260 c->setFOV(YFov); 260 c->setFOV(YFov);
261 c->setNearValue(ZNear); 261 c->setNearValue(ZNear);
262 c->setFarValue(ZFar); 262 c->setFarValue(ZFar);
263 c->setName(getId()); 263 c->setName(getId());
264 } 264 }
265 return c; 265 return c;
266 } 266 }
267 }; 267 };
268 268
269 269
270 //! prefab for a container scene node 270 //! prefab for a container scene node
271 //! Collects other prefabs and instantiates them upon instantiation 271 //! Collects other prefabs and instantiates them upon instantiation
272 //! Uses a dummy scene node to return the children as one scene node 272 //! Uses a dummy scene node to return the children as one scene node
273 class CScenePrefab : public CPrefab 273 class CScenePrefab : public CPrefab
274 { 274 {
275 public: 275 public:
276 CScenePrefab(const core::stringc& id) : CPrefab(id) 276 CScenePrefab(const core::stringc& id) : CPrefab(id)
277 { 277 {
278 #ifdef COLLADA_READER_DEBUG 278 #ifdef COLLADA_READER_DEBUG
279 os::Printer::log("COLLADA: loaded scene prefab", Id.c_str(), ELL_DEBUG); 279 os::Printer::log("COLLADA: loaded scene prefab", Id.c_str(), ELL_DEBUG);
280 #endif 280 #endif
281 } 281 }
282 282
283 //! creates an instance of this prefab 283 //! creates an instance of this prefab
284 virtual scene::ISceneNode* addInstance(scene::ISceneNode* parent, 284 virtual scene::ISceneNode* addInstance(scene::ISceneNode* parent,
285 scene::ISceneManager* mgr) 285 scene::ISceneManager* mgr)
286 { 286 {
287 #ifdef COLLADA_READER_DEBUG 287 #ifdef COLLADA_READER_DEBUG
288 os::Printer::log("COLLADA: Constructing scene instance", Id.c_str(), ELL_DEBUG); 288 os::Printer::log("COLLADA: Constructing scene instance", Id.c_str(), ELL_DEBUG);
289 #endif 289 #endif
290 290
291 if (Children.size()==0) 291 if (Children.size()==0)
292 return 0; 292 return 0;
293 293
294 scene::IDummyTransformationSceneNode* s = mgr->addDummyTransformationSceneNode(parent); 294 scene::IDummyTransformationSceneNode* s = mgr->addDummyTransformationSceneNode(parent);
295 if (s) 295 if (s)
296 { 296 {
297 s->setName(getId()); 297 s->setName(getId());
298 s->getRelativeTransformationMatrix() = Transformation; 298 s->getRelativeTransformationMatrix() = Transformation;
299 s->updateAbsolutePosition(); 299 s->updateAbsolutePosition();
300 core::stringc t; 300 core::stringc t;
301 for (u32 i=0; i<16; ++i) 301 for (u32 i=0; i<16; ++i)
302 { 302 {
303 t+=core::stringc((double)Transformation[i]); 303 t+=core::stringc((double)Transformation[i]);
304 t+=" "; 304 t+=" ";
305 } 305 }
306 #ifdef COLLADA_READER_DEBUG 306 #ifdef COLLADA_READER_DEBUG
307 os::Printer::log("COLLADA: Transformation", t.c_str(), ELL_DEBUG); 307 os::Printer::log("COLLADA: Transformation", t.c_str(), ELL_DEBUG);
308 #endif 308 #endif
309 309
310 for (u32 i=0; i<Children.size(); ++i) 310 for (u32 i=0; i<Children.size(); ++i)
311 Children[i]->addInstance(s, mgr); 311 Children[i]->addInstance(s, mgr);
312 } 312 }
313 313
314 return s; 314 return s;
315 } 315 }
316 316
317 core::array<IColladaPrefab*> Children; 317 core::array<IColladaPrefab*> Children;
318 core::matrix4 Transformation; 318 core::matrix4 Transformation;
319 }; 319 };
320 320
321 321
322//! Constructor 322//! Constructor
323CColladaFileLoader::CColladaFileLoader(scene::ISceneManager* smgr, 323CColladaFileLoader::CColladaFileLoader(scene::ISceneManager* smgr,
324 io::IFileSystem* fs) 324 io::IFileSystem* fs)
325: SceneManager(smgr), FileSystem(fs), DummyMesh(0), 325: SceneManager(smgr), FileSystem(fs), DummyMesh(0),
326 FirstLoadedMesh(0), LoadedMeshCount(0), CreateInstances(false) 326 FirstLoadedMesh(0), LoadedMeshCount(0), CreateInstances(false)
327{ 327{
328 #ifdef _DEBUG 328 #ifdef _DEBUG
329 setDebugName("CColladaFileLoader"); 329 setDebugName("CColladaFileLoader");
330 #endif 330 #endif
331} 331}
332 332
333 333
334//! destructor 334//! destructor
335CColladaFileLoader::~CColladaFileLoader() 335CColladaFileLoader::~CColladaFileLoader()
336{ 336{
337 if (DummyMesh) 337 if (DummyMesh)
338 DummyMesh->drop(); 338 DummyMesh->drop();
339 339
340 if (FirstLoadedMesh) 340 if (FirstLoadedMesh)
341 FirstLoadedMesh->drop(); 341 FirstLoadedMesh->drop();
342} 342}
343 343
344 344
345//! Returns true if the file maybe is able to be loaded by this class. 345//! Returns true if the file maybe is able to be loaded by this class.
346/** This decision should be based only on the file extension (e.g. ".cob") */ 346/** This decision should be based only on the file extension (e.g. ".cob") */
347bool CColladaFileLoader::isALoadableFileExtension(const io::path& filename) const 347bool CColladaFileLoader::isALoadableFileExtension(const io::path& filename) const
348{ 348{
349 return core::hasFileExtension ( filename, "xml", "dae" ); 349 return core::hasFileExtension ( filename, "xml", "dae" );
350} 350}
351 351
352 352
353//! creates/loads an animated mesh from the file. 353//! creates/loads an animated mesh from the file.
354//! \return Pointer to the created mesh. Returns 0 if loading failed. 354//! \return Pointer to the created mesh. Returns 0 if loading failed.
355//! If you no longer need the mesh, you should call IAnimatedMesh::drop(). 355//! If you no longer need the mesh, you should call IAnimatedMesh::drop().
356//! See IReferenceCounted::drop() for more information. 356//! See IReferenceCounted::drop() for more information.
357IAnimatedMesh* CColladaFileLoader::createMesh(io::IReadFile* file) 357IAnimatedMesh* CColladaFileLoader::createMesh(io::IReadFile* file)
358{ 358{
359 io::IXMLReaderUTF8* reader = FileSystem->createXMLReaderUTF8(file); 359 io::IXMLReaderUTF8* reader = FileSystem->createXMLReaderUTF8(file);
360 if (!reader) 360 if (!reader)
361 return 0; 361 return 0;
362 362
363 CurrentlyLoadingMesh = file->getFileName(); 363 CurrentlyLoadingMesh = file->getFileName();
364 CreateInstances = SceneManager->getParameters()->getAttributeAsBool( 364 CreateInstances = SceneManager->getParameters()->getAttributeAsBool(
365 scene::COLLADA_CREATE_SCENE_INSTANCES); 365 scene::COLLADA_CREATE_SCENE_INSTANCES);
366 Version = 0; 366 Version = 0;
367 FlipAxis = false; 367 FlipAxis = false;
368 368
369 // read until COLLADA section, skip other parts 369 // read until COLLADA section, skip other parts
370 370
371 while(reader->read()) 371 while(reader->read())
372 { 372 {
373 if (reader->getNodeType() == io::EXN_ELEMENT) 373 if (reader->getNodeType() == io::EXN_ELEMENT)
374 { 374 {
375 if (colladaSectionName == reader->getNodeName()) 375 if (colladaSectionName == reader->getNodeName())
376 readColladaSection(reader); 376 readColladaSection(reader);
377 else 377 else
378 skipSection(reader, true); // unknown section 378 skipSection(reader, true); // unknown section
379 } 379 }
380 } 380 }
381 381
382 reader->drop(); 382 reader->drop();
383 if (!Version) 383 if (!Version)
384 return 0; 384 return 0;
385 385
386 // because this loader loads and creates a complete scene instead of 386 // because this loader loads and creates a complete scene instead of
387 // a single mesh, return an empty dummy mesh to make the scene manager 387 // a single mesh, return an empty dummy mesh to make the scene manager
388 // know that everything went well. 388 // know that everything went well.
389 if (!DummyMesh) 389 if (!DummyMesh)
390 DummyMesh = new SAnimatedMesh(); 390 DummyMesh = new SAnimatedMesh();
391 scene::IAnimatedMesh* returnMesh = DummyMesh; 391 scene::IAnimatedMesh* returnMesh = DummyMesh;
392 392
393 if (Version < 10400) 393 if (Version < 10400)
394 instantiateNode(SceneManager->getRootSceneNode()); 394 instantiateNode(SceneManager->getRootSceneNode());
395 395
396 // add the first loaded mesh into the mesh cache too, if more than one 396 // add the first loaded mesh into the mesh cache too, if more than one
397 // meshes have been loaded from the file 397 // meshes have been loaded from the file
398 if (LoadedMeshCount>1 && FirstLoadedMesh) 398 if (LoadedMeshCount>1 && FirstLoadedMesh)
399 { 399 {
400 os::Printer::log("Added COLLADA mesh", FirstLoadedMeshName.c_str()); 400 os::Printer::log("Added COLLADA mesh", FirstLoadedMeshName.c_str());
401 SceneManager->getMeshCache()->addMesh(FirstLoadedMeshName.c_str(), FirstLoadedMesh); 401 SceneManager->getMeshCache()->addMesh(FirstLoadedMeshName.c_str(), FirstLoadedMesh);
402 } 402 }
403 403
404 // clean up temporary loaded data 404 // clean up temporary loaded data
405 clearData(); 405 clearData();
406 406
407 returnMesh->grab(); // store until this loader is destroyed 407 returnMesh->grab(); // store until this loader is destroyed
408 408
409 DummyMesh->drop(); 409 DummyMesh->drop();
410 DummyMesh = 0; 410 DummyMesh = 0;
411 411
412 if (FirstLoadedMesh) 412 if (FirstLoadedMesh)
413 FirstLoadedMesh->drop(); 413 FirstLoadedMesh->drop();
414 FirstLoadedMesh = 0; 414 FirstLoadedMesh = 0;
415 LoadedMeshCount = 0; 415 LoadedMeshCount = 0;
416 416
417 return returnMesh; 417 return returnMesh;
418} 418}
419 419
420 420
421//! skips an (unknown) section in the collada document 421//! skips an (unknown) section in the collada document
422void CColladaFileLoader::skipSection(io::IXMLReaderUTF8* reader, bool reportSkipping) 422void CColladaFileLoader::skipSection(io::IXMLReaderUTF8* reader, bool reportSkipping)
423{ 423{
424 #ifndef COLLADA_READER_DEBUG 424 #ifndef COLLADA_READER_DEBUG
425 if (reportSkipping) // always report in COLLADA_READER_DEBUG mode 425 if (reportSkipping) // always report in COLLADA_READER_DEBUG mode
426 #endif 426 #endif
427 os::Printer::log("COLLADA skipping section", core::stringc(reader->getNodeName()).c_str(), ELL_DEBUG); 427 os::Printer::log("COLLADA skipping section", core::stringc(reader->getNodeName()).c_str(), ELL_DEBUG);
428 428
429 // skip if this element is empty anyway. 429 // skip if this element is empty anyway.
430 if (reader->isEmptyElement()) 430 if (reader->isEmptyElement())
431 return; 431 return;
432 432
433 // read until we've reached the last element in this section 433 // read until we've reached the last element in this section
434 u32 tagCounter = 1; 434 u32 tagCounter = 1;
435 435
436 while(tagCounter && reader->read()) 436 while(tagCounter && reader->read())
437 { 437 {
438 if (reader->getNodeType() == io::EXN_ELEMENT && 438 if (reader->getNodeType() == io::EXN_ELEMENT &&
439 !reader->isEmptyElement()) 439 !reader->isEmptyElement())
440 { 440 {
441 #ifdef COLLADA_READER_DEBUG 441 #ifdef COLLADA_READER_DEBUG
442 if (reportSkipping) 442 if (reportSkipping)
443 os::Printer::log("Skipping COLLADA unknown element", core::stringc(reader->getNodeName()).c_str(), ELL_DEBUG); 443 os::Printer::log("Skipping COLLADA unknown element", core::stringc(reader->getNodeName()).c_str(), ELL_DEBUG);
444 #endif 444 #endif
445 445
446 ++tagCounter; 446 ++tagCounter;
447 } 447 }
448 else 448 else
449 if (reader->getNodeType() == io::EXN_ELEMENT_END) 449 if (reader->getNodeType() == io::EXN_ELEMENT_END)
450 --tagCounter; 450 --tagCounter;
451 } 451 }
452} 452}
453 453
454 454
455//! reads the <COLLADA> section and its content 455//! reads the <COLLADA> section and its content
456void CColladaFileLoader::readColladaSection(io::IXMLReaderUTF8* reader) 456void CColladaFileLoader::readColladaSection(io::IXMLReaderUTF8* reader)
457{ 457{
458 if (reader->isEmptyElement()) 458 if (reader->isEmptyElement())
459 return; 459 return;
460 460
461 // todo: patch level needs to be handled 461 // todo: patch level needs to be handled
462 const f32 version = core::fast_atof(core::stringc(reader->getAttributeValue("version")).c_str()); 462 const f32 version = core::fast_atof(core::stringc(reader->getAttributeValue("version")).c_str());
463 Version = core::floor32(version)*10000+core::round32(core::fract(version)*1000.0f); 463 Version = core::floor32(version)*10000+core::round32(core::fract(version)*1000.0f);
464 // Version 1.4 can be checked for by if (Version >= 10400) 464 // Version 1.4 can be checked for by if (Version >= 10400)
465 465
466 while(reader->read()) 466 while(reader->read())
467 if (reader->getNodeType() == io::EXN_ELEMENT) 467 if (reader->getNodeType() == io::EXN_ELEMENT)
468 { 468 {
469 if (assetSectionName == reader->getNodeName()) 469 if (assetSectionName == reader->getNodeName())
470 readAssetSection(reader); 470 readAssetSection(reader);
471 else 471 else
472 if (librarySectionName == reader->getNodeName()) 472 if (librarySectionName == reader->getNodeName())
473 readLibrarySection(reader); 473 readLibrarySection(reader);
474 else 474 else
475 if (libraryNodesSectionName == reader->getNodeName()) 475 if (libraryNodesSectionName == reader->getNodeName())
476 readLibrarySection(reader); 476 readLibrarySection(reader);
477 else 477 else
478 if (libraryGeometriesSectionName == reader->getNodeName()) 478 if (libraryGeometriesSectionName == reader->getNodeName())
479 readLibrarySection(reader); 479 readLibrarySection(reader);
480 else 480 else
481 if (libraryMaterialsSectionName == reader->getNodeName()) 481 if (libraryMaterialsSectionName == reader->getNodeName())
482 readLibrarySection(reader); 482 readLibrarySection(reader);
483 else 483 else
484 if (libraryEffectsSectionName == reader->getNodeName()) 484 if (libraryEffectsSectionName == reader->getNodeName())
485 readLibrarySection(reader); 485 readLibrarySection(reader);
486 else 486 else
487 if (libraryImagesSectionName == reader->getNodeName()) 487 if (libraryImagesSectionName == reader->getNodeName())
488 readLibrarySection(reader); 488 readLibrarySection(reader);
489 else 489 else
490 if (libraryCamerasSectionName == reader->getNodeName()) 490 if (libraryCamerasSectionName == reader->getNodeName())
491 readLibrarySection(reader); 491 readLibrarySection(reader);
492 else 492 else
493 if (libraryLightsSectionName == reader->getNodeName()) 493 if (libraryLightsSectionName == reader->getNodeName())
494 readLibrarySection(reader); 494 readLibrarySection(reader);
495 else 495 else
496 if (libraryVisualScenesSectionName == reader->getNodeName()) 496 if (libraryVisualScenesSectionName == reader->getNodeName())
497 readVisualScene(reader); 497 readVisualScene(reader);
498 else 498 else
499 if (assetSectionName == reader->getNodeName()) 499 if (assetSectionName == reader->getNodeName())
500 readAssetSection(reader); 500 readAssetSection(reader);
501 else 501 else
502 if (sceneSectionName == reader->getNodeName()) 502 if (sceneSectionName == reader->getNodeName())
503 readSceneSection(reader); 503 readSceneSection(reader);
504 else 504 else
505 { 505 {
506 os::Printer::log("COLLADA loader warning: Wrong tag usage found", reader->getNodeName(), ELL_WARNING); 506 os::Printer::log("COLLADA loader warning: Wrong tag usage found", reader->getNodeName(), ELL_WARNING);
507 skipSection(reader, true); // unknown section 507 skipSection(reader, true); // unknown section
508 } 508 }
509 } 509 }
510} 510}
511 511
512 512
513//! reads a <library> section and its content 513//! reads a <library> section and its content
514void CColladaFileLoader::readLibrarySection(io::IXMLReaderUTF8* reader) 514void CColladaFileLoader::readLibrarySection(io::IXMLReaderUTF8* reader)
515{ 515{
516 #ifdef COLLADA_READER_DEBUG 516 #ifdef COLLADA_READER_DEBUG
517 os::Printer::log("COLLADA reading library", ELL_DEBUG); 517 os::Printer::log("COLLADA reading library", ELL_DEBUG);
518 #endif 518 #endif
519 519
520 if (reader->isEmptyElement()) 520 if (reader->isEmptyElement())
521 return; 521 return;
522 522
523 while(reader->read()) 523 while(reader->read())
524 { 524 {
525 if (reader->getNodeType() == io::EXN_ELEMENT) 525 if (reader->getNodeType() == io::EXN_ELEMENT)
526 { 526 {
527 // animation section tbd 527 // animation section tbd
528 if (cameraPrefabName == reader->getNodeName()) 528 if (cameraPrefabName == reader->getNodeName())
529 readCameraPrefab(reader); 529 readCameraPrefab(reader);
530 else 530 else
531 // code section tbd 531 // code section tbd
532 // controller section tbd 532 // controller section tbd
533 if (geometrySectionName == reader->getNodeName()) 533 if (geometrySectionName == reader->getNodeName())
534 readGeometry(reader); 534 readGeometry(reader);
535 else 535 else
536 if (imageSectionName == reader->getNodeName()) 536 if (imageSectionName == reader->getNodeName())
537 readImage(reader); 537 readImage(reader);
538 else 538 else
539 if (lightPrefabName == reader->getNodeName()) 539 if (lightPrefabName == reader->getNodeName())
540 readLightPrefab(reader); 540 readLightPrefab(reader);
541 else 541 else
542 if (materialSectionName == reader->getNodeName()) 542 if (materialSectionName == reader->getNodeName())
543 readMaterial(reader); 543 readMaterial(reader);
544 else 544 else
545 if (nodeSectionName == reader->getNodeName()) 545 if (nodeSectionName == reader->getNodeName())
546 { 546 {
547 CScenePrefab p(""); 547 CScenePrefab p("");
548 548
549 readNodeSection(reader, SceneManager->getRootSceneNode(), &p); 549 readNodeSection(reader, SceneManager->getRootSceneNode(), &p);
550 } 550 }
551 else 551 else
552 if (effectSectionName == reader->getNodeName()) 552 if (effectSectionName == reader->getNodeName())
553 readEffect(reader); 553 readEffect(reader);
554 else 554 else
555 // program section tbd 555 // program section tbd
556 if (textureSectionName == reader->getNodeName()) 556 if (textureSectionName == reader->getNodeName())
557 readTexture(reader); 557 readTexture(reader);
558 else 558 else
559 skipSection(reader, true); // unknown section, not all allowed supported yet 559 skipSection(reader, true); // unknown section, not all allowed supported yet
560 } 560 }
561 else 561 else
562 if (reader->getNodeType() == io::EXN_ELEMENT_END) 562 if (reader->getNodeType() == io::EXN_ELEMENT_END)
563 { 563 {
564 if (librarySectionName == reader->getNodeName()) 564 if (librarySectionName == reader->getNodeName())
565 break; // end reading. 565 break; // end reading.
566 if (libraryNodesSectionName == reader->getNodeName()) 566 if (libraryNodesSectionName == reader->getNodeName())
567 break; // end reading. 567 break; // end reading.
568 if (libraryGeometriesSectionName == reader->getNodeName()) 568 if (libraryGeometriesSectionName == reader->getNodeName())
569 break; // end reading. 569 break; // end reading.
570 if (libraryMaterialsSectionName == reader->getNodeName()) 570 if (libraryMaterialsSectionName == reader->getNodeName())
571 break; // end reading. 571 break; // end reading.
572 if (libraryEffectsSectionName == reader->getNodeName()) 572 if (libraryEffectsSectionName == reader->getNodeName())
573 break; // end reading. 573 break; // end reading.
574 if (libraryImagesSectionName == reader->getNodeName()) 574 if (libraryImagesSectionName == reader->getNodeName())
575 break; // end reading. 575 break; // end reading.
576 if (libraryLightsSectionName == reader->getNodeName()) 576 if (libraryLightsSectionName == reader->getNodeName())
577 break; // end reading. 577 break; // end reading.
578 if (libraryCamerasSectionName == reader->getNodeName()) 578 if (libraryCamerasSectionName == reader->getNodeName())
579 break; // end reading. 579 break; // end reading.
580 } 580 }
581 } 581 }
582} 582}
583 583
584 584
585//! reads a <visual_scene> element and stores it as a prefab 585//! reads a <visual_scene> element and stores it as a prefab
586void CColladaFileLoader::readVisualScene(io::IXMLReaderUTF8* reader) 586void CColladaFileLoader::readVisualScene(io::IXMLReaderUTF8* reader)
587{ 587{
588 CScenePrefab* p = 0; 588 CScenePrefab* p = 0;
589 while(reader->read()) 589 while(reader->read())
590 { 590 {
591 if (reader->getNodeType() == io::EXN_ELEMENT) 591 if (reader->getNodeType() == io::EXN_ELEMENT)
592 { 592 {
593 if (visualSceneSectionName == reader->getNodeName()) 593 if (visualSceneSectionName == reader->getNodeName())
594 p = new CScenePrefab(readId(reader)); 594 p = new CScenePrefab(readId(reader));
595 else 595 else
596 if (p && nodeSectionName == reader->getNodeName()) // as a child of visual_scene 596 if (p && nodeSectionName == reader->getNodeName()) // as a child of visual_scene
597 readNodeSection(reader, SceneManager->getRootSceneNode(), p); 597 readNodeSection(reader, SceneManager->getRootSceneNode(), p);
598 else 598 else
599 if (assetSectionName == reader->getNodeName()) 599 if (assetSectionName == reader->getNodeName())
600 readAssetSection(reader); 600 readAssetSection(reader);
601 else 601 else
602 if (extraNodeName == reader->getNodeName()) 602 if (extraNodeName == reader->getNodeName())
603 skipSection(reader, false); // ignore all other sections 603 skipSection(reader, false); // ignore all other sections
604 else 604 else
605 { 605 {
606 os::Printer::log("COLLADA loader warning: Wrong tag usage found", reader->getNodeName(), ELL_WARNING); 606 os::Printer::log("COLLADA loader warning: Wrong tag usage found", reader->getNodeName(), ELL_WARNING);
607 skipSection(reader, true); // ignore all other sections 607 skipSection(reader, true); // ignore all other sections
608 } 608 }
609 } 609 }
610 else 610 else
611 if (reader->getNodeType() == io::EXN_ELEMENT_END) 611 if (reader->getNodeType() == io::EXN_ELEMENT_END)
612 { 612 {
613 if (libraryVisualScenesSectionName == reader->getNodeName()) 613 if (libraryVisualScenesSectionName == reader->getNodeName())
614 return; 614 return;
615 else 615 else
616 if ((visualSceneSectionName == reader->getNodeName()) && p) 616 if ((visualSceneSectionName == reader->getNodeName()) && p)
617 { 617 {
618 Prefabs.push_back(p); 618 Prefabs.push_back(p);
619 p = 0; 619 p = 0;
620 } 620 }
621 } 621 }
622 } 622 }
623} 623}
624 624
625 625
626//! reads a <scene> section and its content 626//! reads a <scene> section and its content
627void CColladaFileLoader::readSceneSection(io::IXMLReaderUTF8* reader) 627void CColladaFileLoader::readSceneSection(io::IXMLReaderUTF8* reader)
628{ 628{
629 #ifdef COLLADA_READER_DEBUG 629 #ifdef COLLADA_READER_DEBUG
630 os::Printer::log("COLLADA reading scene", ELL_DEBUG); 630 os::Printer::log("COLLADA reading scene", ELL_DEBUG);
631 #endif 631 #endif
632 632
633 if (reader->isEmptyElement()) 633 if (reader->isEmptyElement())
634 return; 634 return;
635 635
636 // read the scene 636 // read the scene
637 637
638 core::matrix4 transform; // transformation of this node 638 core::matrix4 transform; // transformation of this node
639 core::aabbox3df bbox; 639 core::aabbox3df bbox;
640 scene::IDummyTransformationSceneNode* node = 0; 640 scene::IDummyTransformationSceneNode* node = 0;
641 641
642 while(reader->read()) 642 while(reader->read())
643 { 643 {
644 if (reader->getNodeType() == io::EXN_ELEMENT) 644 if (reader->getNodeType() == io::EXN_ELEMENT)
645 { 645 {
646 if (lookatNodeName == reader->getNodeName()) 646 if (lookatNodeName == reader->getNodeName())
647 transform *= readLookAtNode(reader); 647 transform *= readLookAtNode(reader);
648 else 648 else
649 if (matrixNodeName == reader->getNodeName()) 649 if (matrixNodeName == reader->getNodeName())
650 transform *= readMatrixNode(reader); 650 transform *= readMatrixNode(reader);
651 else 651 else
652 if (perspectiveNodeName == reader->getNodeName()) 652 if (perspectiveNodeName == reader->getNodeName())
653 transform *= readPerspectiveNode(reader); 653 transform *= readPerspectiveNode(reader);
654 else 654 else
655 if (rotateNodeName == reader->getNodeName()) 655 if (rotateNodeName == reader->getNodeName())
656 transform *= readRotateNode(reader); 656 transform *= readRotateNode(reader);
657 else 657 else
658 if (scaleNodeName == reader->getNodeName()) 658 if (scaleNodeName == reader->getNodeName())
659 transform *= readScaleNode(reader); 659 transform *= readScaleNode(reader);
660 else 660 else
661 if (skewNodeName == reader->getNodeName()) 661 if (skewNodeName == reader->getNodeName())
662 transform *= readSkewNode(reader); 662 transform *= readSkewNode(reader);
663 else 663 else
664 if (translateNodeName == reader->getNodeName()) 664 if (translateNodeName == reader->getNodeName())
665 transform *= readTranslateNode(reader); 665 transform *= readTranslateNode(reader);
666 else 666 else
667 if (bboxNodeName == reader->getNodeName()) 667 if (bboxNodeName == reader->getNodeName())
668 readBboxNode(reader, bbox); 668 readBboxNode(reader, bbox);
669 else 669 else
670 if (nodeSectionName == reader->getNodeName()) 670 if (nodeSectionName == reader->getNodeName())
671 { 671 {
672 // create dummy node if there is none yet. 672 // create dummy node if there is none yet.
673 if (!node) 673 if (!node)
674 node = SceneManager->addDummyTransformationSceneNode(SceneManager->getRootSceneNode()); 674 node = SceneManager->addDummyTransformationSceneNode(SceneManager->getRootSceneNode());
675 675
676 readNodeSection(reader, node); 676 readNodeSection(reader, node);
677 } 677 }
678 else 678 else
679 if ((instanceSceneName == reader->getNodeName())) 679 if ((instanceSceneName == reader->getNodeName()))
680 readInstanceNode(reader, SceneManager->getRootSceneNode(), 0, 0,instanceSceneName); 680 readInstanceNode(reader, SceneManager->getRootSceneNode(), 0, 0,instanceSceneName);
681 else 681 else
682 if (extraNodeName == reader->getNodeName()) 682 if (extraNodeName == reader->getNodeName())
683 skipSection(reader, false); 683 skipSection(reader, false);
684 else 684 else
685 { 685 {
686 os::Printer::log("COLLADA loader warning: Wrong tag usage found", reader->getNodeName(), ELL_WARNING); 686 os::Printer::log("COLLADA loader warning: Wrong tag usage found", reader->getNodeName(), ELL_WARNING);
687 skipSection(reader, true); // ignore all other sections 687 skipSection(reader, true); // ignore all other sections
688 } 688 }
689 } 689 }
690 else 690 else
691 if ((reader->getNodeType() == io::EXN_ELEMENT_END) && 691 if ((reader->getNodeType() == io::EXN_ELEMENT_END) &&
692 (sceneSectionName == reader->getNodeName())) 692 (sceneSectionName == reader->getNodeName()))
693 return; 693 return;
694 } 694 }
695 if (node) 695 if (node)
696 node->getRelativeTransformationMatrix() = transform; 696 node->getRelativeTransformationMatrix() = transform;
697} 697}
698 698
699 699
700//! reads a <asset> section and its content 700//! reads a <asset> section and its content
701void CColladaFileLoader::readAssetSection(io::IXMLReaderUTF8* reader) 701void CColladaFileLoader::readAssetSection(io::IXMLReaderUTF8* reader)
702{ 702{
703 #ifdef COLLADA_READER_DEBUG 703 #ifdef COLLADA_READER_DEBUG
704 os::Printer::log("COLLADA reading asset", ELL_DEBUG); 704 os::Printer::log("COLLADA reading asset", ELL_DEBUG);
705 #endif 705 #endif
706 706
707 if (reader->isEmptyElement()) 707 if (reader->isEmptyElement())
708 return; 708 return;
709 709
710 while(reader->read()) 710 while(reader->read())
711 { 711 {
712 if (reader->getNodeType() == io::EXN_ELEMENT) 712 if (reader->getNodeType() == io::EXN_ELEMENT)
713 { 713 {
714 if (upAxisNodeName == reader->getNodeName()) 714 if (upAxisNodeName == reader->getNodeName())
715 { 715 {
716 reader->read(); 716 reader->read();
717 FlipAxis = (core::stringc("Z_UP") == reader->getNodeData()); 717 FlipAxis = (core::stringc("Z_UP") == reader->getNodeData());
718 } 718 }
719 } 719 }
720 else 720 else
721 if ((reader->getNodeType() == io::EXN_ELEMENT_END) && 721 if ((reader->getNodeType() == io::EXN_ELEMENT_END) &&
722 (assetSectionName == reader->getNodeName())) 722 (assetSectionName == reader->getNodeName()))
723 return; 723 return;
724 } 724 }
725} 725}
726 726
727 727
728//! reads a <node> section and its content 728//! reads a <node> section and its content
729void CColladaFileLoader::readNodeSection(io::IXMLReaderUTF8* reader, scene::ISceneNode* parent, CScenePrefab* p) 729void CColladaFileLoader::readNodeSection(io::IXMLReaderUTF8* reader, scene::ISceneNode* parent, CScenePrefab* p)
730{ 730{
731 if (reader->isEmptyElement()) 731 if (reader->isEmptyElement())
732 { 732 {
733 return; 733 return;
734 #ifdef COLLADA_READER_DEBUG 734 #ifdef COLLADA_READER_DEBUG
735 os::Printer::log("COLLADA reading empty node", ELL_DEBUG); 735 os::Printer::log("COLLADA reading empty node", ELL_DEBUG);
736 #endif 736 #endif
737 } 737 }
738 738
739 core::stringc name = readId(reader); 739 core::stringc name = readId(reader);
740 #ifdef COLLADA_READER_DEBUG 740 #ifdef COLLADA_READER_DEBUG
741 os::Printer::log("COLLADA reading node", name, ELL_DEBUG); 741 os::Printer::log("COLLADA reading node", name, ELL_DEBUG);
742 #endif 742 #endif
743 743
744 core::matrix4 transform; // transformation of this node 744 core::matrix4 transform; // transformation of this node
745 core::aabbox3df bbox; 745 core::aabbox3df bbox;
746 scene::ISceneNode* node = 0; // instance 746 scene::ISceneNode* node = 0; // instance
747 CScenePrefab* nodeprefab = 0; // prefab for library_nodes usage 747 CScenePrefab* nodeprefab = 0; // prefab for library_nodes usage
748 748
749 if (p) 749 if (p)
750 { 750 {
751 nodeprefab = new CScenePrefab(readId(reader)); 751 nodeprefab = new CScenePrefab(readId(reader));
752 p->Children.push_back(nodeprefab); 752 p->Children.push_back(nodeprefab);
753 Prefabs.push_back(nodeprefab); // in order to delete them later on 753 Prefabs.push_back(nodeprefab); // in order to delete them later on
754 } 754 }
755 755
756 // read the node 756 // read the node
757 757
758 while(reader->read()) 758 while(reader->read())
759 { 759 {
760 if (reader->getNodeType() == io::EXN_ELEMENT) 760 if (reader->getNodeType() == io::EXN_ELEMENT)
761 { 761 {
762 if (assetSectionName == reader->getNodeName()) 762 if (assetSectionName == reader->getNodeName())
763 readAssetSection(reader); 763 readAssetSection(reader);
764 else 764 else
765 if (lookatNodeName == reader->getNodeName()) 765 if (lookatNodeName == reader->getNodeName())
766 transform *= readLookAtNode(reader); 766 transform *= readLookAtNode(reader);
767 else 767 else
768 if (matrixNodeName == reader->getNodeName()) 768 if (matrixNodeName == reader->getNodeName())
769 transform *= readMatrixNode(reader); 769 transform *= readMatrixNode(reader);
770 else 770 else
771 if (perspectiveNodeName == reader->getNodeName()) 771 if (perspectiveNodeName == reader->getNodeName())
772 transform *= readPerspectiveNode(reader); 772 transform *= readPerspectiveNode(reader);
773 else 773 else
774 if (rotateNodeName == reader->getNodeName()) 774 if (rotateNodeName == reader->getNodeName())
775 transform *= readRotateNode(reader); 775 transform *= readRotateNode(reader);
776 else 776 else
777 if (scaleNodeName == reader->getNodeName()) 777 if (scaleNodeName == reader->getNodeName())
778 transform *= readScaleNode(reader); 778 transform *= readScaleNode(reader);
779 else 779 else
780 if (skewNodeName == reader->getNodeName()) 780 if (skewNodeName == reader->getNodeName())
781 transform *= readSkewNode(reader); 781 transform *= readSkewNode(reader);
782 else 782 else
783 if (translateNodeName == reader->getNodeName()) 783 if (translateNodeName == reader->getNodeName())
784 transform *= readTranslateNode(reader); 784 transform *= readTranslateNode(reader);
785 else 785 else
786 if (bboxNodeName == reader->getNodeName()) 786 if (bboxNodeName == reader->getNodeName())
787 readBboxNode(reader, bbox); 787 readBboxNode(reader, bbox);
788 else 788 else
789 if ((instanceName == reader->getNodeName()) || 789 if ((instanceName == reader->getNodeName()) ||
790 (instanceNodeName == reader->getNodeName()) || 790 (instanceNodeName == reader->getNodeName()) ||
791 (instanceGeometryName == reader->getNodeName()) || 791 (instanceGeometryName == reader->getNodeName()) ||
792 (instanceLightName == reader->getNodeName())) 792 (instanceLightName == reader->getNodeName()))
793 { 793 {
794 scene::ISceneNode* newnode = 0; 794 scene::ISceneNode* newnode = 0;
795 readInstanceNode(reader, parent, &newnode, nodeprefab, reader->getNodeName()); 795 readInstanceNode(reader, parent, &newnode, nodeprefab, reader->getNodeName());
796 796
797 if (node && newnode) 797 if (node && newnode)
798 { 798 {
799 // move children from dummy to new node 799 // move children from dummy to new node
800 ISceneNodeList::ConstIterator it = node->getChildren().begin(); 800 ISceneNodeList::ConstIterator it = node->getChildren().begin();
801 for (; it != node->getChildren().end(); it = node->getChildren().begin()) 801 for (; it != node->getChildren().end(); it = node->getChildren().begin())
802 (*it)->setParent(newnode); 802 (*it)->setParent(newnode);
803 803
804 // remove previous dummy node 804 // remove previous dummy node
805 node->remove(); 805 node->remove();
806 node = newnode; 806 node = newnode;
807 } 807 }
808 } 808 }
809 else 809 else
810 if (nodeSectionName == reader->getNodeName()) 810 if (nodeSectionName == reader->getNodeName())
811 { 811 {
812 // create dummy node if there is none yet. 812 // create dummy node if there is none yet.
813 if (CreateInstances && !node) 813 if (CreateInstances && !node)
814 { 814 {
815 scene::IDummyTransformationSceneNode* dummy = 815 scene::IDummyTransformationSceneNode* dummy =
816 SceneManager->addDummyTransformationSceneNode(parent); 816 SceneManager->addDummyTransformationSceneNode(parent);
817 dummy->getRelativeTransformationMatrix() = transform; 817 dummy->getRelativeTransformationMatrix() = transform;
818 node = dummy; 818 node = dummy;
819 } 819 }
820 else 820 else
821 node = parent; 821 node = parent;
822 822
823 // read and add child 823 // read and add child
824 readNodeSection(reader, node, nodeprefab); 824 readNodeSection(reader, node, nodeprefab);
825 } 825 }
826 else 826 else
827 if (extraNodeName == reader->getNodeName()) 827 if (extraNodeName == reader->getNodeName())
828 skipSection(reader, false); 828 skipSection(reader, false);
829 else 829 else
830 skipSection(reader, true); // ignore all other sections 830 skipSection(reader, true); // ignore all other sections
831 831
832 } // end if node 832 } // end if node
833 else 833 else
834 if (reader->getNodeType() == io::EXN_ELEMENT_END) 834 if (reader->getNodeType() == io::EXN_ELEMENT_END)
835 { 835 {
836 if (nodeSectionName == reader->getNodeName()) 836 if (nodeSectionName == reader->getNodeName())
837 break; 837 break;
838 } 838 }
839 } 839 }
840 840
841 if (nodeprefab) 841 if (nodeprefab)
842 nodeprefab->Transformation = transform; 842 nodeprefab->Transformation = transform;
843 else 843 else
844 if (node) 844 if (node)
845 { 845 {
846 // set transformation correctly into node. 846 // set transformation correctly into node.
847 node->setPosition(transform.getTranslation()); 847 node->setPosition(transform.getTranslation());
848 node->setRotation(transform.getRotationDegrees()); 848 node->setRotation(transform.getRotationDegrees());
849 node->setScale(transform.getScale()); 849 node->setScale(transform.getScale());
850 node->updateAbsolutePosition(); 850 node->updateAbsolutePosition();
851 851
852 node->setName(name); 852 node->setName(name);
853 } 853 }
854} 854}
855 855
856 856
857//! reads a <lookat> element and its content and creates a matrix from it 857//! reads a <lookat> element and its content and creates a matrix from it
858core::matrix4 CColladaFileLoader::readLookAtNode(io::IXMLReaderUTF8* reader) 858core::matrix4 CColladaFileLoader::readLookAtNode(io::IXMLReaderUTF8* reader)
859{ 859{
860 core::matrix4 mat; 860 core::matrix4 mat;
861 if (reader->isEmptyElement()) 861 if (reader->isEmptyElement())
862 return mat; 862 return mat;
863 863
864 #ifdef COLLADA_READER_DEBUG 864 #ifdef COLLADA_READER_DEBUG
865 os::Printer::log("COLLADA reading look at node", ELL_DEBUG); 865 os::Printer::log("COLLADA reading look at node", ELL_DEBUG);
866 #endif 866 #endif
867 867
868 f32 floats[9]; 868 f32 floats[9];
869 readFloatsInsideElement(reader, floats, 9); 869 readFloatsInsideElement(reader, floats, 9);
870 870
871 mat.buildCameraLookAtMatrixLH( 871 mat.buildCameraLookAtMatrixLH(
872 core::vector3df(floats[0], floats[1], floats[2]), 872 core::vector3df(floats[0], floats[1], floats[2]),
873 core::vector3df(floats[3], floats[4], floats[5]), 873 core::vector3df(floats[3], floats[4], floats[5]),
874 core::vector3df(floats[6], floats[7], floats[8])); 874 core::vector3df(floats[6], floats[7], floats[8]));
875 875
876 return mat; 876 return mat;
877} 877}
878 878
879 879
880//! reads a <skew> element and its content and creates a matrix from it 880//! reads a <skew> element and its content and creates a matrix from it
881core::matrix4 CColladaFileLoader::readSkewNode(io::IXMLReaderUTF8* reader) 881core::matrix4 CColladaFileLoader::readSkewNode(io::IXMLReaderUTF8* reader)
882{ 882{
883 #ifdef COLLADA_READER_DEBUG 883 #ifdef COLLADA_READER_DEBUG
884 os::Printer::log("COLLADA reading skew node", ELL_DEBUG); 884 os::Printer::log("COLLADA reading skew node", ELL_DEBUG);
885 #endif 885 #endif
886 886
887 core::matrix4 mat; 887 core::matrix4 mat;
888 if (reader->isEmptyElement()) 888 if (reader->isEmptyElement())
889 return mat; 889 return mat;
890 890
891 f32 floats[7]; // angle rotation-axis translation-axis 891 f32 floats[7]; // angle rotation-axis translation-axis
892 readFloatsInsideElement(reader, floats, 7); 892 readFloatsInsideElement(reader, floats, 7);
893 893
894 // build skew matrix from these 7 floats 894 // build skew matrix from these 7 floats
895 core::quaternion q; 895 core::quaternion q;
896 q.fromAngleAxis(floats[0]*core::DEGTORAD, core::vector3df(floats[1], floats[2], floats[3])); 896 q.fromAngleAxis(floats[0]*core::DEGTORAD, core::vector3df(floats[1], floats[2], floats[3]));
897 mat = q.getMatrix(); 897 mat = q.getMatrix();
898 898
899 if (floats[4]==1.f) // along x-axis 899 if (floats[4]==1.f) // along x-axis
900 { 900 {
901 mat[4]=0.f; 901 mat[4]=0.f;
902 mat[6]=0.f; 902 mat[6]=0.f;
903 mat[8]=0.f; 903 mat[8]=0.f;
904 mat[9]=0.f; 904 mat[9]=0.f;
905 } 905 }
906 else 906 else
907 if (floats[5]==1.f) // along y-axis 907 if (floats[5]==1.f) // along y-axis
908 { 908 {
909 mat[1]=0.f; 909 mat[1]=0.f;
910 mat[2]=0.f; 910 mat[2]=0.f;
911 mat[8]=0.f; 911 mat[8]=0.f;
912 mat[9]=0.f; 912 mat[9]=0.f;
913 } 913 }
914 else 914 else
915 if (floats[6]==1.f) // along z-axis 915 if (floats[6]==1.f) // along z-axis
916 { 916 {
917 mat[1]=0.f; 917 mat[1]=0.f;
918 mat[2]=0.f; 918 mat[2]=0.f;
919 mat[4]=0.f; 919 mat[4]=0.f;
920 mat[6]=0.f; 920 mat[6]=0.f;
921 } 921 }
922 922
923 return mat; 923 return mat;
924} 924}
925 925
926 926
927//! reads a <boundingbox> element and its content and stores it in bbox 927//! reads a <boundingbox> element and its content and stores it in bbox
928void CColladaFileLoader::readBboxNode(io::IXMLReaderUTF8* reader, 928void CColladaFileLoader::readBboxNode(io::IXMLReaderUTF8* reader,
929 core::aabbox3df& bbox) 929 core::aabbox3df& bbox)
930{ 930{
931 #ifdef COLLADA_READER_DEBUG 931 #ifdef COLLADA_READER_DEBUG
932 os::Printer::log("COLLADA reading boundingbox node", ELL_DEBUG); 932 os::Printer::log("COLLADA reading boundingbox node", ELL_DEBUG);
933 #endif 933 #endif
934 934
935 bbox.reset(core::aabbox3df()); 935 bbox.reset(core::aabbox3df());
936 936
937 if (reader->isEmptyElement()) 937 if (reader->isEmptyElement())
938 return; 938 return;
939 939
940 f32 floats[3]; 940 f32 floats[3];
941 941
942 while(reader->read()) 942 while(reader->read())
943 { 943 {
944 if (reader->getNodeType() == io::EXN_ELEMENT) 944 if (reader->getNodeType() == io::EXN_ELEMENT)
945 { 945 {
946 if (minNodeName == reader->getNodeName()) 946 if (minNodeName == reader->getNodeName())
947 { 947 {
948 readFloatsInsideElement(reader, floats, 3); 948 readFloatsInsideElement(reader, floats, 3);
949 bbox.MinEdge.set(floats[0], floats[1], floats[2]); 949 bbox.MinEdge.set(floats[0], floats[1], floats[2]);
950 } 950 }
951 else 951 else
952 if (maxNodeName == reader->getNodeName()) 952 if (maxNodeName == reader->getNodeName())
953 { 953 {
954 readFloatsInsideElement(reader, floats, 3); 954 readFloatsInsideElement(reader, floats, 3);
955 bbox.MaxEdge.set(floats[0], floats[1], floats[2]); 955 bbox.MaxEdge.set(floats[0], floats[1], floats[2]);
956 } 956 }
957 else 957 else
958 skipSection(reader, true); // ignore all other sections 958 skipSection(reader, true); // ignore all other sections
959 } 959 }
960 else 960 else
961 if (reader->getNodeType() == io::EXN_ELEMENT_END) 961 if (reader->getNodeType() == io::EXN_ELEMENT_END)
962 { 962 {
963 if (bboxNodeName == reader->getNodeName()) 963 if (bboxNodeName == reader->getNodeName())
964 break; 964 break;
965 } 965 }
966 } 966 }
967} 967}
968 968
969 969
970//! reads a <matrix> element and its content and creates a matrix from it 970//! reads a <matrix> element and its content and creates a matrix from it
971core::matrix4 CColladaFileLoader::readMatrixNode(io::IXMLReaderUTF8* reader) 971core::matrix4 CColladaFileLoader::readMatrixNode(io::IXMLReaderUTF8* reader)
972{ 972{
973 #ifdef COLLADA_READER_DEBUG 973 #ifdef COLLADA_READER_DEBUG
974 os::Printer::log("COLLADA reading matrix node", ELL_DEBUG); 974 os::Printer::log("COLLADA reading matrix node", ELL_DEBUG);
975 #endif 975 #endif
976 976
977 core::matrix4 mat; 977 core::matrix4 mat;
978 if (reader->isEmptyElement()) 978 if (reader->isEmptyElement())
979 return mat; 979 return mat;
980 980
981 readFloatsInsideElement(reader, mat.pointer(), 16); 981 readFloatsInsideElement(reader, mat.pointer(), 16);
982 // put translation into the correct place 982 // put translation into the correct place
983 if (FlipAxis) 983 if (FlipAxis)
984 { 984 {
985 core::matrix4 mat2(mat, core::matrix4::EM4CONST_TRANSPOSED); 985 core::matrix4 mat2(mat, core::matrix4::EM4CONST_TRANSPOSED);
986 mat2[1]=mat[8]; 986 mat2[1]=mat[8];
987 mat2[2]=mat[4]; 987 mat2[2]=mat[4];
988 mat2[4]=mat[2]; 988 mat2[4]=mat[2];
989 mat2[5]=mat[10]; 989 mat2[5]=mat[10];
990 mat2[6]=mat[6]; 990 mat2[6]=mat[6];
991 mat2[8]=mat[1]; 991 mat2[8]=mat[1];
992 mat2[9]=mat[9]; 992 mat2[9]=mat[9];
993 mat2[10]=mat[5]; 993 mat2[10]=mat[5];
994 mat2[12]=mat[3]; 994 mat2[12]=mat[3];
995 mat2[13]=mat[11]; 995 mat2[13]=mat[11];
996 mat2[14]=mat[7]; 996 mat2[14]=mat[7];
997 return mat2; 997 return mat2;
998 } 998 }
999 else 999 else
1000 return core::matrix4(mat, core::matrix4::EM4CONST_TRANSPOSED); 1000 return core::matrix4(mat, core::matrix4::EM4CONST_TRANSPOSED);
1001} 1001}
1002 1002
1003 1003
1004//! reads a <perspective> element and its content and creates a matrix from it 1004//! reads a <perspective> element and its content and creates a matrix from it
1005core::matrix4 CColladaFileLoader::readPerspectiveNode(io::IXMLReaderUTF8* reader) 1005core::matrix4 CColladaFileLoader::readPerspectiveNode(io::IXMLReaderUTF8* reader)
1006{ 1006{
1007 #ifdef COLLADA_READER_DEBUG 1007 #ifdef COLLADA_READER_DEBUG
1008 os::Printer::log("COLLADA reading perspective node", ELL_DEBUG); 1008 os::Printer::log("COLLADA reading perspective node", ELL_DEBUG);
1009 #endif 1009 #endif
1010 1010
1011 core::matrix4 mat; 1011 core::matrix4 mat;
1012 if (reader->isEmptyElement()) 1012 if (reader->isEmptyElement())
1013 return mat; 1013 return mat;
1014 1014
1015 f32 floats[1]; 1015 f32 floats[1];
1016 readFloatsInsideElement(reader, floats, 1); 1016 readFloatsInsideElement(reader, floats, 1);
1017 1017
1018 // TODO: build perspecitve matrix from this float 1018 // TODO: build perspecitve matrix from this float
1019 1019
1020 os::Printer::log("COLLADA loader warning: <perspective> not implemented yet.", ELL_WARNING); 1020 os::Printer::log("COLLADA loader warning: <perspective> not implemented yet.", ELL_WARNING);
1021 1021
1022 return mat; 1022 return mat;
1023} 1023}
1024 1024
1025 1025
1026//! reads a <rotate> element and its content and creates a matrix from it 1026//! reads a <rotate> element and its content and creates a matrix from it
1027core::matrix4 CColladaFileLoader::readRotateNode(io::IXMLReaderUTF8* reader) 1027core::matrix4 CColladaFileLoader::readRotateNode(io::IXMLReaderUTF8* reader)
1028{ 1028{
1029 #ifdef COLLADA_READER_DEBUG 1029 #ifdef COLLADA_READER_DEBUG
1030 os::Printer::log("COLLADA reading rotate node", ELL_DEBUG); 1030 os::Printer::log("COLLADA reading rotate node", ELL_DEBUG);
1031 #endif 1031 #endif
1032 1032
1033 core::matrix4 mat; 1033 core::matrix4 mat;
1034 if (reader->isEmptyElement()) 1034 if (reader->isEmptyElement())
1035 return mat; 1035 return mat;
1036 1036
1037 f32 floats[4]; 1037 f32 floats[4];
1038 readFloatsInsideElement(reader, floats, 4); 1038 readFloatsInsideElement(reader, floats, 4);
1039 1039
1040 if (!core::iszero(floats[3])) 1040 if (!core::iszero(floats[3]))
1041 { 1041 {
1042 core::quaternion q; 1042 core::quaternion q;
1043 if (FlipAxis) 1043 if (FlipAxis)
1044 q.fromAngleAxis(floats[3]*core::DEGTORAD, core::vector3df(floats[0], floats[2], floats[1])); 1044 q.fromAngleAxis(floats[3]*core::DEGTORAD, core::vector3df(floats[0], floats[2], floats[1]));
1045 else 1045 else
1046 q.fromAngleAxis(floats[3]*core::DEGTORAD, core::vector3df(floats[0], floats[1], floats[2])); 1046 q.fromAngleAxis(floats[3]*core::DEGTORAD, core::vector3df(floats[0], floats[1], floats[2]));
1047 return q.getMatrix(); 1047 return q.getMatrix();
1048 } 1048 }
1049 else 1049 else
1050 return core::IdentityMatrix; 1050 return core::IdentityMatrix;
1051} 1051}
1052 1052
1053 1053
1054//! reads a <scale> element and its content and creates a matrix from it 1054//! reads a <scale> element and its content and creates a matrix from it
1055core::matrix4 CColladaFileLoader::readScaleNode(io::IXMLReaderUTF8* reader) 1055core::matrix4 CColladaFileLoader::readScaleNode(io::IXMLReaderUTF8* reader)
1056{ 1056{
1057 #ifdef COLLADA_READER_DEBUG 1057 #ifdef COLLADA_READER_DEBUG
1058 os::Printer::log("COLLADA reading scale node", ELL_DEBUG); 1058 os::Printer::log("COLLADA reading scale node", ELL_DEBUG);
1059 #endif 1059 #endif
1060 1060
1061 core::matrix4 mat; 1061 core::matrix4 mat;
1062 if (reader->isEmptyElement()) 1062 if (reader->isEmptyElement())
1063 return mat; 1063 return mat;
1064 1064
1065 f32 floats[3]; 1065 f32 floats[3];
1066 readFloatsInsideElement(reader, floats, 3); 1066 readFloatsInsideElement(reader, floats, 3);
1067 1067
1068 if (FlipAxis) 1068 if (FlipAxis)
1069 mat.setScale(core::vector3df(floats[0], floats[2], floats[1])); 1069 mat.setScale(core::vector3df(floats[0], floats[2], floats[1]));
1070 else 1070 else
1071 mat.setScale(core::vector3df(floats[0], floats[1], floats[2])); 1071 mat.setScale(core::vector3df(floats[0], floats[1], floats[2]));
1072 1072
1073 return mat; 1073 return mat;
1074} 1074}
1075 1075
1076 1076
1077//! reads a <translate> element and its content and creates a matrix from it 1077//! reads a <translate> element and its content and creates a matrix from it
1078core::matrix4 CColladaFileLoader::readTranslateNode(io::IXMLReaderUTF8* reader) 1078core::matrix4 CColladaFileLoader::readTranslateNode(io::IXMLReaderUTF8* reader)
1079{ 1079{
1080 #ifdef COLLADA_READER_DEBUG 1080 #ifdef COLLADA_READER_DEBUG
1081 os::Printer::log("COLLADA reading translate node", ELL_DEBUG); 1081 os::Printer::log("COLLADA reading translate node", ELL_DEBUG);
1082 #endif 1082 #endif
1083 1083
1084 core::matrix4 mat; 1084 core::matrix4 mat;
1085 if (reader->isEmptyElement()) 1085 if (reader->isEmptyElement())
1086 return mat; 1086 return mat;
1087 1087
1088 f32 floats[3]; 1088 f32 floats[3];
1089 readFloatsInsideElement(reader, floats, 3); 1089 readFloatsInsideElement(reader, floats, 3);
1090 1090
1091 if (FlipAxis) 1091 if (FlipAxis)
1092 mat.setTranslation(core::vector3df(floats[0], floats[2], floats[1])); 1092 mat.setTranslation(core::vector3df(floats[0], floats[2], floats[1]));
1093 else 1093 else
1094 mat.setTranslation(core::vector3df(floats[0], floats[1], floats[2])); 1094 mat.setTranslation(core::vector3df(floats[0], floats[1], floats[2]));
1095 1095
1096 return mat; 1096 return mat;
1097} 1097}
1098 1098
1099 1099
1100//! reads any kind of <instance*> node 1100//! reads any kind of <instance*> node
1101void CColladaFileLoader::readInstanceNode(io::IXMLReaderUTF8* reader, 1101void CColladaFileLoader::readInstanceNode(io::IXMLReaderUTF8* reader,
1102 scene::ISceneNode* parent, scene::ISceneNode** outNode, 1102 scene::ISceneNode* parent, scene::ISceneNode** outNode,
1103 CScenePrefab* p, const core::stringc& type) 1103 CScenePrefab* p, const core::stringc& type)
1104{ 1104{
1105 // find prefab of the specified id 1105 // find prefab of the specified id
1106 core::stringc url = reader->getAttributeValue("url"); 1106 core::stringc url = reader->getAttributeValue("url");
1107 uriToId(url); 1107 uriToId(url);
1108 1108
1109 #ifdef COLLADA_READER_DEBUG 1109 #ifdef COLLADA_READER_DEBUG
1110 os::Printer::log("COLLADA reading instance", url, ELL_DEBUG); 1110 os::Printer::log("COLLADA reading instance", url, ELL_DEBUG);
1111 #endif 1111 #endif
1112 1112
1113 if (!reader->isEmptyElement()) 1113 if (!reader->isEmptyElement())
1114 { 1114 {
1115 while(reader->read()) 1115 while(reader->read())
1116 { 1116 {
1117 if (reader->getNodeType() == io::EXN_ELEMENT) 1117 if (reader->getNodeType() == io::EXN_ELEMENT)
1118 { 1118 {
1119 if (bindMaterialName == reader->getNodeName()) 1119 if (bindMaterialName == reader->getNodeName())
1120 readBindMaterialSection(reader,url); 1120 readBindMaterialSection(reader,url);
1121 else 1121 else
1122 if (extraNodeName == reader->getNodeName()) 1122 if (extraNodeName == reader->getNodeName())
1123 skipSection(reader, false); 1123 skipSection(reader, false);
1124 } 1124 }
1125 else 1125 else
1126 if (reader->getNodeType() == io::EXN_ELEMENT_END) 1126 if (reader->getNodeType() == io::EXN_ELEMENT_END)
1127 break; 1127 break;
1128 } 1128 }
1129 } 1129 }
1130 instantiateNode(parent, outNode, p, url, type); 1130 instantiateNode(parent, outNode, p, url, type);
1131} 1131}
1132 1132
1133 1133
1134void CColladaFileLoader::instantiateNode(scene::ISceneNode* parent, 1134void CColladaFileLoader::instantiateNode(scene::ISceneNode* parent,
1135 scene::ISceneNode** outNode, CScenePrefab* p, const core::stringc& url, 1135 scene::ISceneNode** outNode, CScenePrefab* p, const core::stringc& url,
1136 const core::stringc& type) 1136 const core::stringc& type)
1137{ 1137{
1138 #ifdef COLLADA_READER_DEBUG 1138 #ifdef COLLADA_READER_DEBUG
1139 os::Printer::log("COLLADA instantiate node", ELL_DEBUG); 1139 os::Printer::log("COLLADA instantiate node", ELL_DEBUG);
1140 #endif 1140 #endif
1141 1141
1142 for (u32 i=0; i<Prefabs.size(); ++i) 1142 for (u32 i=0; i<Prefabs.size(); ++i)
1143 { 1143 {
1144 if (url == "" || url == Prefabs[i]->getId()) 1144 if (url == "" || url == Prefabs[i]->getId())
1145 { 1145 {
1146 if (p) 1146 if (p)
1147 p->Children.push_back(Prefabs[i]); 1147 p->Children.push_back(Prefabs[i]);
1148 else 1148 else
1149 if (CreateInstances) 1149 if (CreateInstances)
1150 { 1150 {
1151 scene::ISceneNode * newNode 1151 scene::ISceneNode * newNode
1152 = Prefabs[i]->addInstance(parent, SceneManager); 1152 = Prefabs[i]->addInstance(parent, SceneManager);
1153 if (outNode) 1153 if (outNode)
1154 { 1154 {
1155 *outNode = newNode; 1155 *outNode = newNode;
1156 if (*outNode) 1156 if (*outNode)
1157 (*outNode)->setName(url); 1157 (*outNode)->setName(url);
1158 } 1158 }
1159 } 1159 }
1160 return; 1160 return;
1161 } 1161 }
1162 } 1162 }
1163 if (p) 1163 if (p)
1164 { 1164 {
1165 if (instanceGeometryName==type) 1165 if (instanceGeometryName==type)
1166 { 1166 {
1167 Prefabs.push_back(new CGeometryPrefab(url)); 1167 Prefabs.push_back(new CGeometryPrefab(url));
1168 p->Children.push_back(Prefabs.getLast()); 1168 p->Children.push_back(Prefabs.getLast());
1169 } 1169 }
1170 } 1170 }
1171} 1171}
1172 1172
1173 1173
1174//! reads a <camera> element and stores it as prefab 1174//! reads a <camera> element and stores it as prefab
1175void CColladaFileLoader::readCameraPrefab(io::IXMLReaderUTF8* reader) 1175void CColladaFileLoader::readCameraPrefab(io::IXMLReaderUTF8* reader)
1176{ 1176{
1177 #ifdef COLLADA_READER_DEBUG 1177 #ifdef COLLADA_READER_DEBUG
1178 os::Printer::log("COLLADA reading camera prefab", ELL_DEBUG); 1178 os::Printer::log("COLLADA reading camera prefab", ELL_DEBUG);
1179 #endif 1179 #endif
1180 1180
1181 CCameraPrefab* prefab = new CCameraPrefab(readId(reader)); 1181 CCameraPrefab* prefab = new CCameraPrefab(readId(reader));
1182 1182
1183 if (!reader->isEmptyElement()) 1183 if (!reader->isEmptyElement())
1184 { 1184 {
1185 // read techniques optics and imager (the latter is completely ignored, though) 1185 // read techniques optics and imager (the latter is completely ignored, though)
1186 readColladaParameters(reader, cameraPrefabName); 1186 readColladaParameters(reader, cameraPrefabName);
1187 1187
1188 SColladaParam* p; 1188 SColladaParam* p;
1189 1189
1190 // XFOV not yet supported 1190 // XFOV not yet supported
1191 p = getColladaParameter(ECPN_YFOV); 1191 p = getColladaParameter(ECPN_YFOV);
1192 if (p && p->Type == ECPT_FLOAT) 1192 if (p && p->Type == ECPT_FLOAT)
1193 prefab->YFov = p->Floats[0]; 1193 prefab->YFov = p->Floats[0];
1194 1194
1195 p = getColladaParameter(ECPN_ZNEAR); 1195 p = getColladaParameter(ECPN_ZNEAR);
1196 if (p && p->Type == ECPT_FLOAT) 1196 if (p && p->Type == ECPT_FLOAT)
1197 prefab->ZNear = p->Floats[0]; 1197 prefab->ZNear = p->Floats[0];
1198 1198
1199 p = getColladaParameter(ECPN_ZFAR); 1199 p = getColladaParameter(ECPN_ZFAR);
1200 if (p && p->Type == ECPT_FLOAT) 1200 if (p && p->Type == ECPT_FLOAT)
1201 prefab->ZFar = p->Floats[0]; 1201 prefab->ZFar = p->Floats[0];
1202 // orthographic camera uses LEFT, RIGHT, TOP, and BOTTOM 1202 // orthographic camera uses LEFT, RIGHT, TOP, and BOTTOM
1203 } 1203 }
1204 1204
1205 Prefabs.push_back(prefab); 1205 Prefabs.push_back(prefab);
1206} 1206}
1207 1207
1208 1208
1209//! reads a <image> element and stores it in the image section 1209//! reads a <image> element and stores it in the image section
1210void CColladaFileLoader::readImage(io::IXMLReaderUTF8* reader) 1210void CColladaFileLoader::readImage(io::IXMLReaderUTF8* reader)
1211{ 1211{
1212 // add image to list of loaded images. 1212 // add image to list of loaded images.
1213 Images.push_back(SColladaImage()); 1213 Images.push_back(SColladaImage());
1214 SColladaImage& image=Images.getLast(); 1214 SColladaImage& image=Images.getLast();
1215 1215
1216 image.Id = readId(reader); 1216 image.Id = readId(reader);
1217 #ifdef COLLADA_READER_DEBUG 1217 #ifdef COLLADA_READER_DEBUG
1218 os::Printer::log("COLLADA reading image", core::stringc(image.Id), ELL_DEBUG); 1218 os::Printer::log("COLLADA reading image", core::stringc(image.Id), ELL_DEBUG);
1219 #endif 1219 #endif
1220 image.Dimension.Height = (u32)reader->getAttributeValueAsInt("height"); 1220 image.Dimension.Height = (u32)reader->getAttributeValueAsInt("height");
1221 image.Dimension.Width = (u32)reader->getAttributeValueAsInt("width"); 1221 image.Dimension.Width = (u32)reader->getAttributeValueAsInt("width");
1222 1222
1223 if (Version >= 10400) // start with 1.4 1223 if (Version >= 10400) // start with 1.4
1224 { 1224 {
1225 while(reader->read()) 1225 while(reader->read())
1226 { 1226 {
1227 if (reader->getNodeType() == io::EXN_ELEMENT) 1227 if (reader->getNodeType() == io::EXN_ELEMENT)
1228 { 1228 {
1229 if (assetSectionName == reader->getNodeName()) 1229 if (assetSectionName == reader->getNodeName())
1230 skipSection(reader, false); 1230 skipSection(reader, false);
1231 else 1231 else
1232 if (initFromName == reader->getNodeName()) 1232 if (initFromName == reader->getNodeName())
1233 { 1233 {
1234 reader->read(); 1234 reader->read();
1235 image.Source = reader->getNodeData(); 1235 image.Source = reader->getNodeData();
1236 image.Source.trim(); 1236 image.Source.trim();
1237 image.SourceIsFilename=true; 1237 image.SourceIsFilename=true;
1238 } 1238 }
1239 else 1239 else
1240 if (dataName == reader->getNodeName()) 1240 if (dataName == reader->getNodeName())
1241 { 1241 {
1242 reader->read(); 1242 reader->read();
1243 image.Source = reader->getNodeData(); 1243 image.Source = reader->getNodeData();
1244 image.Source.trim(); 1244 image.Source.trim();
1245 image.SourceIsFilename=false; 1245 image.SourceIsFilename=false;
1246 } 1246 }
1247 else 1247 else
1248 if (extraNodeName == reader->getNodeName()) 1248 if (extraNodeName == reader->getNodeName())
1249 skipSection(reader, false); 1249 skipSection(reader, false);
1250 } 1250 }
1251 else 1251 else
1252 if (reader->getNodeType() == io::EXN_ELEMENT_END) 1252 if (reader->getNodeType() == io::EXN_ELEMENT_END)
1253 { 1253 {
1254 if (initFromName == reader->getNodeName()) 1254 if (initFromName == reader->getNodeName())
1255 return; 1255 return;
1256 } 1256 }
1257 } 1257 }
1258 } 1258 }
1259 else 1259 else
1260 { 1260 {
1261 image.Source = reader->getAttributeValue("source"); 1261 image.Source = reader->getAttributeValue("source");
1262 image.Source.trim(); 1262 image.Source.trim();
1263 image.SourceIsFilename=false; 1263 image.SourceIsFilename=false;
1264 } 1264 }
1265} 1265}
1266 1266
1267 1267
1268//! reads a <texture> element and stores it in the texture section 1268//! reads a <texture> element and stores it in the texture section
1269void CColladaFileLoader::readTexture(io::IXMLReaderUTF8* reader) 1269void CColladaFileLoader::readTexture(io::IXMLReaderUTF8* reader)
1270{ 1270{
1271 // add texture to list of loaded textures. 1271 // add texture to list of loaded textures.
1272 Textures.push_back(SColladaTexture()); 1272 Textures.push_back(SColladaTexture());
1273 SColladaTexture& texture=Textures.getLast(); 1273 SColladaTexture& texture=Textures.getLast();
1274 1274
1275 texture.Id = readId(reader); 1275 texture.Id = readId(reader);
1276 #ifdef COLLADA_READER_DEBUG 1276 #ifdef COLLADA_READER_DEBUG
1277 os::Printer::log("COLLADA reading texture", core::stringc(texture.Id), ELL_DEBUG); 1277 os::Printer::log("COLLADA reading texture", core::stringc(texture.Id), ELL_DEBUG);
1278 #endif 1278 #endif
1279 1279
1280 if (!reader->isEmptyElement()) 1280 if (!reader->isEmptyElement())
1281 { 1281 {
1282 readColladaInputs(reader, textureSectionName); 1282 readColladaInputs(reader, textureSectionName);
1283 SColladaInput* input = getColladaInput(ECIS_IMAGE); 1283 SColladaInput* input = getColladaInput(ECIS_IMAGE);
1284 if (input) 1284 if (input)
1285 { 1285 {
1286 const core::stringc imageName = input->Source; 1286 const core::stringc imageName = input->Source;
1287 texture.Texture = getTextureFromImage(imageName, NULL); 1287 texture.Texture = getTextureFromImage(imageName, NULL);
1288 } 1288 }
1289 } 1289 }
1290} 1290}
1291 1291
1292 1292
1293//! reads a <material> element and stores it in the material section 1293//! reads a <material> element and stores it in the material section
1294void CColladaFileLoader::readMaterial(io::IXMLReaderUTF8* reader) 1294void CColladaFileLoader::readMaterial(io::IXMLReaderUTF8* reader)
1295{ 1295{
1296 // add material to list of loaded materials. 1296 // add material to list of loaded materials.
1297 Materials.push_back(SColladaMaterial()); 1297 Materials.push_back(SColladaMaterial());
1298 1298
1299 SColladaMaterial& material = Materials.getLast(); 1299 SColladaMaterial& material = Materials.getLast();
1300 material.Id = readId(reader); 1300 material.Id = readId(reader);
1301 #ifdef COLLADA_READER_DEBUG 1301 #ifdef COLLADA_READER_DEBUG
1302 os::Printer::log("COLLADA reading material", core::stringc(material.Id), ELL_DEBUG); 1302 os::Printer::log("COLLADA reading material", core::stringc(material.Id), ELL_DEBUG);
1303 #endif 1303 #endif
1304 1304
1305 if (Version >= 10400) 1305 if (Version >= 10400)
1306 { 1306 {
1307 while(reader->read()) 1307 while(reader->read())
1308 { 1308 {
1309 if (reader->getNodeType() == io::EXN_ELEMENT && 1309 if (reader->getNodeType() == io::EXN_ELEMENT &&
1310 instanceEffectName == reader->getNodeName()) 1310 instanceEffectName == reader->getNodeName())
1311 { 1311 {
1312 material.InstanceEffectId = reader->getAttributeValue("url"); 1312 material.InstanceEffectId = reader->getAttributeValue("url");
1313 uriToId(material.InstanceEffectId); 1313 uriToId(material.InstanceEffectId);
1314 } 1314 }
1315 else 1315 else
1316 if (reader->getNodeType() == io::EXN_ELEMENT_END && 1316 if (reader->getNodeType() == io::EXN_ELEMENT_END &&
1317 materialSectionName == reader->getNodeName()) 1317 materialSectionName == reader->getNodeName())
1318 { 1318 {
1319 break; 1319 break;
1320 } 1320 }
1321 } // end while reader->read(); 1321 } // end while reader->read();
1322 } 1322 }
1323 else 1323 else
1324 { 1324 {
1325 if (!reader->isEmptyElement()) 1325 if (!reader->isEmptyElement())
1326 { 1326 {
1327 readColladaInputs(reader, materialSectionName); 1327 readColladaInputs(reader, materialSectionName);
1328 SColladaInput* input = getColladaInput(ECIS_TEXTURE); 1328 SColladaInput* input = getColladaInput(ECIS_TEXTURE);
1329 if (input) 1329 if (input)
1330 { 1330 {
1331 core::stringc textureName = input->Source; 1331 core::stringc textureName = input->Source;
1332 uriToId(textureName); 1332 uriToId(textureName);
1333 for (u32 i=0; i<Textures.size(); ++i) 1333 for (u32 i=0; i<Textures.size(); ++i)
1334 if (textureName == Textures[i].Id) 1334 if (textureName == Textures[i].Id)
1335 { 1335 {
1336 material.Mat.setTexture(0, Textures[i].Texture); 1336 material.Mat.setTexture(0, Textures[i].Texture);
1337 break; 1337 break;
1338 } 1338 }
1339 } 1339 }
1340 1340
1341 //does not work because the wrong start node is chosen due to reading of inputs before 1341 //does not work because the wrong start node is chosen due to reading of inputs before
1342#if 0 1342#if 0
1343 readColladaParameters(reader, materialSectionName); 1343 readColladaParameters(reader, materialSectionName);
1344 1344
1345 SColladaParam* p; 1345 SColladaParam* p;
1346 1346
1347 p = getColladaParameter(ECPN_AMBIENT); 1347 p = getColladaParameter(ECPN_AMBIENT);
1348 if (p && p->Type == ECPT_FLOAT3) 1348 if (p && p->Type == ECPT_FLOAT3)
1349 material.Mat.AmbientColor = video::SColorf(p->Floats[0],p->Floats[1],p->Floats[2]).toSColor(); 1349 material.Mat.AmbientColor = video::SColorf(p->Floats[0],p->Floats[1],p->Floats[2]).toSColor();
1350 p = getColladaParameter(ECPN_DIFFUSE); 1350 p = getColladaParameter(ECPN_DIFFUSE);
1351 if (p && p->Type == ECPT_FLOAT3) 1351 if (p && p->Type == ECPT_FLOAT3)
1352 material.Mat.DiffuseColor = video::SColorf(p->Floats[0],p->Floats[1],p->Floats[2]).toSColor(); 1352 material.Mat.DiffuseColor = video::SColorf(p->Floats[0],p->Floats[1],p->Floats[2]).toSColor();
1353 p = getColladaParameter(ECPN_SPECULAR); 1353 p = getColladaParameter(ECPN_SPECULAR);
1354 if (p && p->Type == ECPT_FLOAT3) 1354 if (p && p->Type == ECPT_FLOAT3)
1355 material.Mat.DiffuseColor = video::SColorf(p->Floats[0],p->Floats[1],p->Floats[2]).toSColor(); 1355 material.Mat.DiffuseColor = video::SColorf(p->Floats[0],p->Floats[1],p->Floats[2]).toSColor();
1356 p = getColladaParameter(ECPN_SHININESS); 1356 p = getColladaParameter(ECPN_SHININESS);
1357 if (p && p->Type == ECPT_FLOAT) 1357 if (p && p->Type == ECPT_FLOAT)
1358 material.Mat.Shininess = p->Floats[0]; 1358 material.Mat.Shininess = p->Floats[0];
1359#endif 1359#endif
1360 } 1360 }
1361 } 1361 }
1362} 1362}
1363 1363
1364void CColladaFileLoader::readEffect(io::IXMLReaderUTF8* reader, SColladaEffect * effect) 1364void CColladaFileLoader::readEffect(io::IXMLReaderUTF8* reader, SColladaEffect * effect)
1365{ 1365{
1366 static const core::stringc constantNode("constant"); 1366 static const core::stringc constantNode("constant");
1367 static const core::stringc lambertNode("lambert"); 1367 static const core::stringc lambertNode("lambert");
1368 static const core::stringc phongNode("phong"); 1368 static const core::stringc phongNode("phong");
1369 static const core::stringc blinnNode("blinn"); 1369 static const core::stringc blinnNode("blinn");
1370 static const core::stringc emissionNode("emission"); 1370 static const core::stringc emissionNode("emission");
1371 static const core::stringc ambientNode("ambient"); 1371 static const core::stringc ambientNode("ambient");
1372 static const core::stringc diffuseNode("diffuse"); 1372 static const core::stringc diffuseNode("diffuse");
1373 static const core::stringc specularNode("specular"); 1373 static const core::stringc specularNode("specular");
1374 static const core::stringc shininessNode("shininess"); 1374 static const core::stringc shininessNode("shininess");
1375 static const core::stringc reflectiveNode("reflective"); 1375 static const core::stringc reflectiveNode("reflective");
1376 static const core::stringc reflectivityNode("reflectivity"); 1376 static const core::stringc reflectivityNode("reflectivity");
1377 static const core::stringc transparentNode("transparent"); 1377 static const core::stringc transparentNode("transparent");
1378 static const core::stringc transparencyNode("transparency"); 1378 static const core::stringc transparencyNode("transparency");
1379 static const core::stringc indexOfRefractionNode("index_of_refraction"); 1379 static const core::stringc indexOfRefractionNode("index_of_refraction");
1380 1380
1381 if (!effect) 1381 if (!effect)
1382 { 1382 {
1383 Effects.push_back(SColladaEffect()); 1383 Effects.push_back(SColladaEffect());
1384 effect = &Effects.getLast(); 1384 effect = &Effects.getLast();
1385 effect->Parameters = new io::CAttributes(); 1385 effect->Parameters = new io::CAttributes();
1386 effect->Id = readId(reader); 1386 effect->Id = readId(reader);
1387 effect->Transparency = 1.f; 1387 effect->Transparency = 1.f;
1388 effect->Mat.Lighting=true; 1388 effect->Mat.Lighting=true;
1389 effect->Mat.NormalizeNormals=true; 1389 effect->Mat.NormalizeNormals=true;
1390 #ifdef COLLADA_READER_DEBUG 1390 #ifdef COLLADA_READER_DEBUG
1391 os::Printer::log("COLLADA reading effect", core::stringc(effect->Id), ELL_DEBUG); 1391 os::Printer::log("COLLADA reading effect", core::stringc(effect->Id), ELL_DEBUG);
1392 #endif 1392 #endif
1393 } 1393 }
1394 while(reader->read()) 1394 while(reader->read())
1395 { 1395 {
1396 if (reader->getNodeType() == io::EXN_ELEMENT) 1396 if (reader->getNodeType() == io::EXN_ELEMENT)
1397 { 1397 {
1398 // first come the tags we descend, but ignore the top-levels 1398 // first come the tags we descend, but ignore the top-levels
1399 if (!reader->isEmptyElement() && ((profileCOMMONSectionName == reader->getNodeName()) || 1399 if (!reader->isEmptyElement() && ((profileCOMMONSectionName == reader->getNodeName()) ||
1400 (techniqueNodeName == reader->getNodeName()))) 1400 (techniqueNodeName == reader->getNodeName())))
1401 readEffect(reader,effect); 1401 readEffect(reader,effect);
1402 else 1402 else
1403 if (newParamName == reader->getNodeName()) 1403 if (newParamName == reader->getNodeName())
1404 readParameter(reader, effect->Parameters); 1404 readParameter(reader, effect->Parameters);
1405 else 1405 else
1406 // these are the actual materials inside technique 1406 // these are the actual materials inside technique
1407 if (constantNode == reader->getNodeName() || 1407 if (constantNode == reader->getNodeName() ||
1408 lambertNode == reader->getNodeName() || 1408 lambertNode == reader->getNodeName() ||
1409 phongNode == reader->getNodeName() || 1409 phongNode == reader->getNodeName() ||
1410 blinnNode == reader->getNodeName()) 1410 blinnNode == reader->getNodeName())
1411 { 1411 {
1412 #ifdef COLLADA_READER_DEBUG 1412 #ifdef COLLADA_READER_DEBUG
1413 os::Printer::log("COLLADA reading effect part", reader->getNodeName(), ELL_DEBUG); 1413 os::Printer::log("COLLADA reading effect part", reader->getNodeName(), ELL_DEBUG);
1414 #endif 1414 #endif
1415 effect->Mat.setFlag(irr::video::EMF_GOURAUD_SHADING, 1415 effect->Mat.setFlag(irr::video::EMF_GOURAUD_SHADING,
1416 phongNode == reader->getNodeName() || 1416 phongNode == reader->getNodeName() ||
1417 blinnNode == reader->getNodeName()); 1417 blinnNode == reader->getNodeName());
1418 while(reader->read()) 1418 while(reader->read())
1419 { 1419 {
1420 if (reader->getNodeType() == io::EXN_ELEMENT) 1420 if (reader->getNodeType() == io::EXN_ELEMENT)
1421 { 1421 {
1422 const core::stringc node = reader->getNodeName(); 1422 const core::stringc node = reader->getNodeName();
1423 if (emissionNode == node || ambientNode == node || 1423 if (emissionNode == node || ambientNode == node ||
1424 diffuseNode == node || specularNode == node || 1424 diffuseNode == node || specularNode == node ||
1425 reflectiveNode == node || transparentNode == node ) 1425 reflectiveNode == node || transparentNode == node )
1426 { 1426 {
1427 // color or texture types 1427 // color or texture types
1428 while(reader->read()) 1428 while(reader->read())
1429 { 1429 {
1430 if (reader->getNodeType() == io::EXN_ELEMENT && 1430 if (reader->getNodeType() == io::EXN_ELEMENT &&
1431 colorNodeName == reader->getNodeName()) 1431 colorNodeName == reader->getNodeName())
1432 { 1432 {
1433 const video::SColorf colorf = readColorNode(reader); 1433 const video::SColorf colorf = readColorNode(reader);
1434 const video::SColor color = colorf.toSColor(); 1434 const video::SColor color = colorf.toSColor();
1435 if (emissionNode == node) 1435 if (emissionNode == node)
1436 effect->Mat.EmissiveColor = color; 1436 effect->Mat.EmissiveColor = color;
1437 else 1437 else
1438 if (ambientNode == node) 1438 if (ambientNode == node)
1439 effect->Mat.AmbientColor = color; 1439 effect->Mat.AmbientColor = color;
1440 else 1440 else
1441 if (diffuseNode == node) 1441 if (diffuseNode == node)
1442 effect->Mat.DiffuseColor = color; 1442 effect->Mat.DiffuseColor = color;
1443 else 1443 else
1444 if (specularNode == node) 1444 if (specularNode == node)
1445 effect->Mat.SpecularColor = color; 1445 effect->Mat.SpecularColor = color;
1446 else 1446 else
1447 if (transparentNode == node) 1447 if (transparentNode == node)
1448 effect->Transparency = colorf.getAlpha(); 1448 effect->Transparency = colorf.getAlpha();
1449 } 1449 }
1450 else 1450 else
1451 if (reader->getNodeType() == io::EXN_ELEMENT && 1451 if (reader->getNodeType() == io::EXN_ELEMENT &&
1452 textureNodeName == reader->getNodeName()) 1452 textureNodeName == reader->getNodeName())
1453 { 1453 {
1454 effect->Textures.push_back(reader->getAttributeValue("texture")); 1454 effect->Textures.push_back(reader->getAttributeValue("texture"));
1455 break; 1455 break;
1456 } 1456 }
1457 else 1457 else
1458 if (reader->getNodeType() == io::EXN_ELEMENT) 1458 if (reader->getNodeType() == io::EXN_ELEMENT)
1459 skipSection(reader, false); 1459 skipSection(reader, false);
1460 else 1460 else
1461 if (reader->getNodeType() == io::EXN_ELEMENT_END && 1461 if (reader->getNodeType() == io::EXN_ELEMENT_END &&
1462 node == reader->getNodeName()) 1462 node == reader->getNodeName())
1463 break; 1463 break;
1464 } 1464 }
1465 } 1465 }
1466 else 1466 else
1467 if (shininessNode == node || reflectivityNode == node || 1467 if (shininessNode == node || reflectivityNode == node ||
1468 transparencyNode == node || indexOfRefractionNode == node ) 1468 transparencyNode == node || indexOfRefractionNode == node )
1469 { 1469 {
1470 // float or param types 1470 // float or param types
1471 while(reader->read()) 1471 while(reader->read())
1472 { 1472 {
1473 if (reader->getNodeType() == io::EXN_ELEMENT && 1473 if (reader->getNodeType() == io::EXN_ELEMENT &&
1474 floatNodeName == reader->getNodeName()) 1474 floatNodeName == reader->getNodeName())
1475 { 1475 {
1476 f32 f = readFloatNode(reader); 1476 f32 f = readFloatNode(reader);
1477 if (shininessNode == node) 1477 if (shininessNode == node)
1478 effect->Mat.Shininess = f; 1478 effect->Mat.Shininess = f;
1479 else 1479 else
1480 if (transparencyNode == node) 1480 if (transparencyNode == node)
1481 effect->Transparency *= f; 1481 effect->Transparency *= f;
1482 } 1482 }
1483 else 1483 else
1484 if (reader->getNodeType() == io::EXN_ELEMENT) 1484 if (reader->getNodeType() == io::EXN_ELEMENT)
1485 skipSection(reader, false); 1485 skipSection(reader, false);
1486 else 1486 else
1487 if (reader->getNodeType() == io::EXN_ELEMENT_END && 1487 if (reader->getNodeType() == io::EXN_ELEMENT_END &&
1488 node == reader->getNodeName()) 1488 node == reader->getNodeName())
1489 break; 1489 break;
1490 } 1490 }
1491 } 1491 }
1492 else 1492 else
1493 skipSection(reader, true); // ignore all other nodes 1493 skipSection(reader, true); // ignore all other nodes
1494 } 1494 }
1495 else 1495 else
1496 if (reader->getNodeType() == io::EXN_ELEMENT_END && ( 1496 if (reader->getNodeType() == io::EXN_ELEMENT_END && (
1497 constantNode == reader->getNodeName() || 1497 constantNode == reader->getNodeName() ||
1498 lambertNode == reader->getNodeName() || 1498 lambertNode == reader->getNodeName() ||
1499 phongNode == reader->getNodeName() || 1499 phongNode == reader->getNodeName() ||
1500 blinnNode == reader->getNodeName() 1500 blinnNode == reader->getNodeName()
1501 )) 1501 ))
1502 break; 1502 break;
1503 } 1503 }
1504 } 1504 }
1505 else 1505 else
1506 if (!reader->isEmptyElement() && (extraNodeName == reader->getNodeName())) 1506 if (!reader->isEmptyElement() && (extraNodeName == reader->getNodeName()))
1507 readEffect(reader,effect); 1507 readEffect(reader,effect);
1508 else 1508 else
1509 if (doubleSidedNodeName == reader->getNodeName()) 1509 if (doubleSidedNodeName == reader->getNodeName())
1510 { 1510 {
1511 // read the GoogleEarth extra flag for double sided polys 1511 // read the GoogleEarth extra flag for double sided polys
1512 s32 doubleSided = 0; 1512 s32 doubleSided = 0;
1513 readIntsInsideElement(reader,&doubleSided,1); 1513 readIntsInsideElement(reader,&doubleSided,1);
1514 if (doubleSided) 1514 if (doubleSided)
1515 { 1515 {
1516 #ifdef COLLADA_READER_DEBUG 1516 #ifdef COLLADA_READER_DEBUG
1517 os::Printer::log("Setting double sided flag for effect.", ELL_DEBUG); 1517 os::Printer::log("Setting double sided flag for effect.", ELL_DEBUG);
1518 #endif 1518 #endif
1519 1519
1520 effect->Mat.setFlag(irr::video::EMF_BACK_FACE_CULLING,false); 1520 effect->Mat.setFlag(irr::video::EMF_BACK_FACE_CULLING,false);
1521 } 1521 }
1522 } 1522 }
1523 else 1523 else
1524 skipSection(reader, true); // ignore all other sections 1524 skipSection(reader, true); // ignore all other sections
1525 } 1525 }
1526 else 1526 else
1527 if (reader->getNodeType() == io::EXN_ELEMENT_END) 1527 if (reader->getNodeType() == io::EXN_ELEMENT_END)
1528 { 1528 {
1529 if (effectSectionName == reader->getNodeName()) 1529 if (effectSectionName == reader->getNodeName())
1530 break; 1530 break;
1531 else 1531 else
1532 if (profileCOMMONSectionName == reader->getNodeName()) 1532 if (profileCOMMONSectionName == reader->getNodeName())
1533 break; 1533 break;
1534 else 1534 else
1535 if (techniqueNodeName == reader->getNodeName()) 1535 if (techniqueNodeName == reader->getNodeName())
1536 break; 1536 break;
1537 else 1537 else
1538 if (extraNodeName == reader->getNodeName()) 1538 if (extraNodeName == reader->getNodeName())
1539 break; 1539 break;
1540 } 1540 }
1541 } 1541 }
1542 1542
1543 if (effect->Mat.AmbientColor == video::SColor(0) && 1543 if (effect->Mat.AmbientColor == video::SColor(0) &&
1544 effect->Mat.DiffuseColor != video::SColor(0)) 1544 effect->Mat.DiffuseColor != video::SColor(0))
1545 effect->Mat.AmbientColor = effect->Mat.DiffuseColor; 1545 effect->Mat.AmbientColor = effect->Mat.DiffuseColor;
1546 if (effect->Mat.DiffuseColor == video::SColor(0) && 1546 if (effect->Mat.DiffuseColor == video::SColor(0) &&
1547 effect->Mat.AmbientColor != video::SColor(0)) 1547 effect->Mat.AmbientColor != video::SColor(0))
1548 effect->Mat.DiffuseColor = effect->Mat.AmbientColor; 1548 effect->Mat.DiffuseColor = effect->Mat.AmbientColor;
1549 if ((effect->Transparency != 0.0f) && (effect->Transparency != 1.0f)) 1549 if ((effect->Transparency != 0.0f) && (effect->Transparency != 1.0f))
1550 { 1550 {
1551 effect->Mat.MaterialType = irr::video::EMT_TRANSPARENT_VERTEX_ALPHA; 1551 effect->Mat.MaterialType = irr::video::EMT_TRANSPARENT_VERTEX_ALPHA;
1552 effect->Mat.ZWriteEnable = false; 1552 effect->Mat.ZWriteEnable = false;
1553 } 1553 }
1554 1554
1555 video::E_TEXTURE_CLAMP twu = video::ETC_REPEAT; 1555 video::E_TEXTURE_CLAMP twu = video::ETC_REPEAT;
1556 s32 idx = effect->Parameters->findAttribute(wrapsName.c_str()); 1556 s32 idx = effect->Parameters->findAttribute(wrapsName.c_str());
1557 if ( idx >= 0 ) 1557 if ( idx >= 0 )
1558 twu = (video::E_TEXTURE_CLAMP)(effect->Parameters->getAttributeAsInt(idx)); 1558 twu = (video::E_TEXTURE_CLAMP)(effect->Parameters->getAttributeAsInt(idx));
1559 video::E_TEXTURE_CLAMP twv = video::ETC_REPEAT; 1559 video::E_TEXTURE_CLAMP twv = video::ETC_REPEAT;
1560 idx = effect->Parameters->findAttribute(wraptName.c_str()); 1560 idx = effect->Parameters->findAttribute(wraptName.c_str());
1561 if ( idx >= 0 ) 1561 if ( idx >= 0 )
1562 twv = (video::E_TEXTURE_CLAMP)(effect->Parameters->getAttributeAsInt(idx)); 1562 twv = (video::E_TEXTURE_CLAMP)(effect->Parameters->getAttributeAsInt(idx));
1563 1563
1564 for (u32 i=0; i<video::MATERIAL_MAX_TEXTURES; ++i) 1564 for (u32 i=0; i<video::MATERIAL_MAX_TEXTURES; ++i)
1565 { 1565 {
1566 effect->Mat.TextureLayer[i].TextureWrapU = twu; 1566 effect->Mat.TextureLayer[i].TextureWrapU = twu;
1567 effect->Mat.TextureLayer[i].TextureWrapV = twv; 1567 effect->Mat.TextureLayer[i].TextureWrapV = twv;
1568 } 1568 }
1569 1569
1570 effect->Mat.setFlag(video::EMF_BILINEAR_FILTER, effect->Parameters->getAttributeAsBool("bilinear")); 1570 effect->Mat.setFlag(video::EMF_BILINEAR_FILTER, effect->Parameters->getAttributeAsBool("bilinear"));
1571 effect->Mat.setFlag(video::EMF_TRILINEAR_FILTER, effect->Parameters->getAttributeAsBool("trilinear")); 1571 effect->Mat.setFlag(video::EMF_TRILINEAR_FILTER, effect->Parameters->getAttributeAsBool("trilinear"));
1572 effect->Mat.setFlag(video::EMF_ANISOTROPIC_FILTER, effect->Parameters->getAttributeAsBool("anisotropic")); 1572 effect->Mat.setFlag(video::EMF_ANISOTROPIC_FILTER, effect->Parameters->getAttributeAsBool("anisotropic"));
1573} 1573}
1574 1574
1575 1575
1576const SColladaMaterial* CColladaFileLoader::findMaterial(const core::stringc& materialName) 1576const SColladaMaterial* CColladaFileLoader::findMaterial(const core::stringc& materialName)
1577{ 1577{
1578 #ifdef COLLADA_READER_DEBUG 1578 #ifdef COLLADA_READER_DEBUG
1579 os::Printer::log("COLLADA find material", materialName, ELL_DEBUG); 1579 os::Printer::log("COLLADA find material", materialName, ELL_DEBUG);
1580 #endif 1580 #endif
1581 1581
1582 // do a quick lookup in the materials 1582 // do a quick lookup in the materials
1583 SColladaMaterial matToFind; 1583 SColladaMaterial matToFind;
1584 matToFind.Id = materialName; 1584 matToFind.Id = materialName;
1585 s32 mat = Materials.binary_search(matToFind); 1585 s32 mat = Materials.binary_search(matToFind);
1586 if (mat == -1) 1586 if (mat == -1)
1587 return 0; 1587 return 0;
1588 // instantiate the material effect if needed 1588 // instantiate the material effect if needed
1589 if (Materials[mat].InstanceEffectId.size() != 0) 1589 if (Materials[mat].InstanceEffectId.size() != 0)
1590 { 1590 {
1591 // do a quick lookup in the effects 1591 // do a quick lookup in the effects
1592 SColladaEffect effectToFind; 1592 SColladaEffect effectToFind;
1593 effectToFind.Id = Materials[mat].InstanceEffectId; 1593 effectToFind.Id = Materials[mat].InstanceEffectId;
1594 s32 effect = Effects.binary_search(effectToFind); 1594 s32 effect = Effects.binary_search(effectToFind);
1595 if (effect != -1) 1595 if (effect != -1)
1596 { 1596 {
1597 // found the effect, instantiate by copying into the material 1597 // found the effect, instantiate by copying into the material
1598 Materials[mat].Mat = Effects[effect].Mat; 1598 Materials[mat].Mat = Effects[effect].Mat;
1599 if (Effects[effect].Textures.size()) 1599 if (Effects[effect].Textures.size())
1600 Materials[mat].Mat.setTexture(0, getTextureFromImage(Effects[effect].Textures[0], &(Effects[effect]))); 1600 Materials[mat].Mat.setTexture(0, getTextureFromImage(Effects[effect].Textures[0], &(Effects[effect])));
1601 Materials[mat].Transparency = Effects[effect].Transparency; 1601 Materials[mat].Transparency = Effects[effect].Transparency;
1602 // and indicate the material is instantiated by removing the effect ref 1602 // and indicate the material is instantiated by removing the effect ref
1603 Materials[mat].InstanceEffectId = ""; 1603 Materials[mat].InstanceEffectId = "";
1604 } 1604 }
1605 else 1605 else
1606 return 0; 1606 return 0;
1607 } 1607 }
1608 return &Materials[mat]; 1608 return &Materials[mat];
1609} 1609}
1610 1610
1611 1611
1612void CColladaFileLoader::readBindMaterialSection(io::IXMLReaderUTF8* reader, const core::stringc & id) 1612void CColladaFileLoader::readBindMaterialSection(io::IXMLReaderUTF8* reader, const core::stringc & id)
1613{ 1613{
1614 #ifdef COLLADA_READER_DEBUG 1614 #ifdef COLLADA_READER_DEBUG
1615 os::Printer::log("COLLADA reading bind material", ELL_DEBUG); 1615 os::Printer::log("COLLADA reading bind material", ELL_DEBUG);
1616 #endif 1616 #endif
1617 1617
1618 while(reader->read()) 1618 while(reader->read())
1619 { 1619 {
1620 if (reader->getNodeType() == io::EXN_ELEMENT) 1620 if (reader->getNodeType() == io::EXN_ELEMENT)
1621 { 1621 {
1622 if (instanceMaterialName == reader->getNodeName()) 1622 if (instanceMaterialName == reader->getNodeName())
1623 { 1623 {
1624 // the symbol to retarget, and the target material 1624 // the symbol to retarget, and the target material
1625 core::stringc meshbufferReference = reader->getAttributeValue("symbol"); 1625 core::stringc meshbufferReference = reader->getAttributeValue("symbol");
1626 if (meshbufferReference.size()==0) 1626 if (meshbufferReference.size()==0)
1627 continue; 1627 continue;
1628 core::stringc target = reader->getAttributeValue("target"); 1628 core::stringc target = reader->getAttributeValue("target");
1629 uriToId(target); 1629 uriToId(target);
1630 if (target.size()==0) 1630 if (target.size()==0)
1631 continue; 1631 continue;
1632 const SColladaMaterial * material = findMaterial(target); 1632 const SColladaMaterial * material = findMaterial(target);
1633 if (!material) 1633 if (!material)
1634 continue; 1634 continue;
1635 // bind any pending materials for this node 1635 // bind any pending materials for this node
1636 meshbufferReference = id+"/"+meshbufferReference; 1636 meshbufferReference = id+"/"+meshbufferReference;
1637#ifdef COLLADA_READER_DEBUG 1637#ifdef COLLADA_READER_DEBUG
1638 os::Printer::log((core::stringc("Material binding: ")+meshbufferReference+" "+target).c_str(), ELL_DEBUG); 1638 os::Printer::log((core::stringc("Material binding: ")+meshbufferReference+" "+target).c_str(), ELL_DEBUG);
1639#endif 1639#endif
1640 if (MaterialsToBind.find(meshbufferReference)) 1640 if (MaterialsToBind.find(meshbufferReference))
1641 { 1641 {
1642 core::array<irr::scene::IMeshBuffer*> & toBind 1642 core::array<irr::scene::IMeshBuffer*> & toBind
1643 = MeshesToBind[MaterialsToBind[meshbufferReference]]; 1643 = MeshesToBind[MaterialsToBind[meshbufferReference]];
1644#ifdef COLLADA_READER_DEBUG 1644#ifdef COLLADA_READER_DEBUG
1645 os::Printer::log("Material binding now ",material->Id.c_str(), ELL_DEBUG); 1645 os::Printer::log("Material binding now ",material->Id.c_str(), ELL_DEBUG);
1646 os::Printer::log("#meshbuffers",core::stringc(toBind.size()).c_str(), ELL_DEBUG); 1646 os::Printer::log("#meshbuffers",core::stringc(toBind.size()).c_str(), ELL_DEBUG);
1647#endif 1647#endif
1648 SMesh tmpmesh; 1648 SMesh tmpmesh;
1649 for (u32 i = 0; i < toBind.size(); ++i) 1649 for (u32 i = 0; i < toBind.size(); ++i)
1650 { 1650 {
1651 toBind[i]->getMaterial() = material->Mat; 1651 toBind[i]->getMaterial() = material->Mat;
1652 tmpmesh.addMeshBuffer(toBind[i]); 1652 tmpmesh.addMeshBuffer(toBind[i]);
1653 1653
1654 if ((material->Transparency!=0.0f) && (material->Transparency!=1.0f)) 1654 if ((material->Transparency!=0.0f) && (material->Transparency!=1.0f))
1655 { 1655 {
1656 toBind[i]->getMaterial().MaterialType = video::EMT_TRANSPARENT_VERTEX_ALPHA; 1656 toBind[i]->getMaterial().MaterialType = video::EMT_TRANSPARENT_VERTEX_ALPHA;
1657 toBind[i]->getMaterial().ZWriteEnable = false; 1657 toBind[i]->getMaterial().ZWriteEnable = false;
1658 } 1658 }
1659 } 1659 }
1660 SceneManager->getMeshManipulator()->setVertexColors(&tmpmesh,material->Mat.DiffuseColor); 1660 SceneManager->getMeshManipulator()->setVertexColors(&tmpmesh,material->Mat.DiffuseColor);
1661 if ((material->Transparency!=0.0f) && (material->Transparency!=1.0f)) 1661 if ((material->Transparency!=0.0f) && (material->Transparency!=1.0f))
1662 { 1662 {
1663 #ifdef COLLADA_READER_DEBUG 1663 #ifdef COLLADA_READER_DEBUG
1664 os::Printer::log("COLLADA found transparency material", core::stringc(material->Transparency).c_str(), ELL_DEBUG); 1664 os::Printer::log("COLLADA found transparency material", core::stringc(material->Transparency).c_str(), ELL_DEBUG);
1665 #endif 1665 #endif
1666 SceneManager->getMeshManipulator()->setVertexColorAlpha(&tmpmesh, core::floor32(material->Transparency*255.0f)); 1666 SceneManager->getMeshManipulator()->setVertexColorAlpha(&tmpmesh, core::floor32(material->Transparency*255.0f));
1667 } 1667 }
1668 } 1668 }
1669 } 1669 }
1670 } 1670 }
1671 else 1671 else
1672 if (reader->getNodeType() == io::EXN_ELEMENT_END && 1672 if (reader->getNodeType() == io::EXN_ELEMENT_END &&
1673 bindMaterialName == reader->getNodeName()) 1673 bindMaterialName == reader->getNodeName())
1674 break; 1674 break;
1675 } 1675 }
1676} 1676}
1677 1677
1678 1678
1679//! reads a <geometry> element and stores it as mesh if possible 1679//! reads a <geometry> element and stores it as mesh if possible
1680void CColladaFileLoader::readGeometry(io::IXMLReaderUTF8* reader) 1680void CColladaFileLoader::readGeometry(io::IXMLReaderUTF8* reader)
1681{ 1681{
1682 core::stringc id = readId(reader); 1682 core::stringc id = readId(reader);
1683 #ifdef COLLADA_READER_DEBUG 1683 #ifdef COLLADA_READER_DEBUG
1684 os::Printer::log("COLLADA reading geometry", id, ELL_DEBUG); 1684 os::Printer::log("COLLADA reading geometry", id, ELL_DEBUG);
1685 #endif 1685 #endif
1686 1686
1687 SAnimatedMesh* amesh = new SAnimatedMesh(); 1687 SAnimatedMesh* amesh = new SAnimatedMesh();
1688 scene::SMesh* mesh = new SMesh(); 1688 scene::SMesh* mesh = new SMesh();
1689 amesh->addMesh(mesh); 1689 amesh->addMesh(mesh);
1690 core::array<SSource> sources; 1690 core::array<SSource> sources;
1691 bool okToReadArray = false; 1691 bool okToReadArray = false;
1692 1692
1693 // handles geometry node and the mesh children in this loop 1693 // handles geometry node and the mesh children in this loop
1694 // read sources with arrays and accessor for each mesh 1694 // read sources with arrays and accessor for each mesh
1695 if (!reader->isEmptyElement()) 1695 if (!reader->isEmptyElement())
1696 while(reader->read()) 1696 while(reader->read())
1697 { 1697 {
1698 if (reader->getNodeType() == io::EXN_ELEMENT) 1698 if (reader->getNodeType() == io::EXN_ELEMENT)
1699 { 1699 {
1700 const char* nodeName = reader->getNodeName(); 1700 const char* nodeName = reader->getNodeName();
1701 if (meshSectionName == nodeName) 1701 if (meshSectionName == nodeName)
1702 { 1702 {
1703 // inside a mesh section. Don't have to do anything here. 1703 // inside a mesh section. Don't have to do anything here.
1704 } 1704 }
1705 else 1705 else
1706 if (sourceSectionName == nodeName) 1706 if (sourceSectionName == nodeName)
1707 { 1707 {
1708 // create a new source 1708 // create a new source
1709 sources.push_back(SSource()); 1709 sources.push_back(SSource());
1710 sources.getLast().Id = readId(reader); 1710 sources.getLast().Id = readId(reader);
1711 1711
1712 #ifdef COLLADA_READER_DEBUG 1712 #ifdef COLLADA_READER_DEBUG
1713 os::Printer::log("Reading source", sources.getLast().Id.c_str(), ELL_DEBUG); 1713 os::Printer::log("Reading source", sources.getLast().Id.c_str(), ELL_DEBUG);
1714 #endif 1714 #endif
1715 } 1715 }
1716 else 1716 else
1717 if (arraySectionName == nodeName || floatArraySectionName == nodeName || intArraySectionName == nodeName) 1717 if (arraySectionName == nodeName || floatArraySectionName == nodeName || intArraySectionName == nodeName)
1718 { 1718 {
1719 // create a new array and read it. 1719 // create a new array and read it.
1720 if (!sources.empty()) 1720 if (!sources.empty())
1721 { 1721 {
1722 sources.getLast().Array.Name = readId(reader); 1722 sources.getLast().Array.Name = readId(reader);
1723 1723
1724 int count = reader->getAttributeValueAsInt("count"); 1724 int count = reader->getAttributeValueAsInt("count");
1725 sources.getLast().Array.Data.set_used(count); // pre allocate 1725 sources.getLast().Array.Data.set_used(count); // pre allocate
1726 1726
1727 // check if type of array is ok 1727 // check if type of array is ok
1728 const char* type = reader->getAttributeValue("type"); 1728 const char* type = reader->getAttributeValue("type");
1729 okToReadArray = (type && (!strcmp("float", type) || !strcmp("int", type))) || floatArraySectionName == nodeName || intArraySectionName == nodeName; 1729 okToReadArray = (type && (!strcmp("float", type) || !strcmp("int", type))) || floatArraySectionName == nodeName || intArraySectionName == nodeName;
1730 1730
1731 #ifdef COLLADA_READER_DEBUG 1731 #ifdef COLLADA_READER_DEBUG
1732 os::Printer::log("Read array", sources.getLast().Array.Name.c_str(), ELL_DEBUG); 1732 os::Printer::log("Read array", sources.getLast().Array.Name.c_str(), ELL_DEBUG);
1733 #endif 1733 #endif
1734 } 1734 }
1735 #ifdef COLLADA_READER_DEBUG 1735 #ifdef COLLADA_READER_DEBUG
1736 else 1736 else
1737 os::Printer::log("Warning, array outside source found", 1737 os::Printer::log("Warning, array outside source found",
1738 readId(reader).c_str(), ELL_DEBUG); 1738 readId(reader).c_str(), ELL_DEBUG);
1739 #endif 1739 #endif
1740 1740
1741 } 1741 }
1742 else 1742 else
1743 if (accessorSectionName == nodeName) // child of source (below a technique tag) 1743 if (accessorSectionName == nodeName) // child of source (below a technique tag)
1744 { 1744 {
1745 #ifdef COLLADA_READER_DEBUG 1745 #ifdef COLLADA_READER_DEBUG
1746 os::Printer::log("Reading accessor", ELL_DEBUG); 1746 os::Printer::log("Reading accessor", ELL_DEBUG);
1747 #endif 1747 #endif
1748 SAccessor accessor; 1748 SAccessor accessor;
1749 accessor.Count = reader->getAttributeValueAsInt("count"); 1749 accessor.Count = reader->getAttributeValueAsInt("count");
1750 accessor.Offset = reader->getAttributeValueAsInt("offset"); 1750 accessor.Offset = reader->getAttributeValueAsInt("offset");
1751 accessor.Stride = reader->getAttributeValueAsInt("stride"); 1751 accessor.Stride = reader->getAttributeValueAsInt("stride");
1752 if (accessor.Stride == 0) 1752 if (accessor.Stride == 0)
1753 accessor.Stride = 1; 1753 accessor.Stride = 1;
1754 1754
1755 // the accessor contains some information on how to access (boi!) the array, 1755 // the accessor contains some information on how to access (boi!) the array,
1756 // the info is stored in collada style parameters, so just read them. 1756 // the info is stored in collada style parameters, so just read them.
1757 readColladaParameters(reader, accessorSectionName); 1757 readColladaParameters(reader, accessorSectionName);
1758 if (!sources.empty()) 1758 if (!sources.empty())
1759 { 1759 {
1760 sources.getLast().Accessors.push_back(accessor); 1760 sources.getLast().Accessors.push_back(accessor);
1761 sources.getLast().Accessors.getLast().Parameters = ColladaParameters; 1761 sources.getLast().Accessors.getLast().Parameters = ColladaParameters;
1762 } 1762 }
1763 } 1763 }
1764 else 1764 else
1765 if (verticesSectionName == nodeName) 1765 if (verticesSectionName == nodeName)
1766 { 1766 {
1767 #ifdef COLLADA_READER_DEBUG 1767 #ifdef COLLADA_READER_DEBUG
1768 os::Printer::log("Reading vertices", ELL_DEBUG); 1768 os::Printer::log("Reading vertices", ELL_DEBUG);
1769 #endif 1769 #endif
1770 // read vertex input position source 1770 // read vertex input position source
1771 readColladaInputs(reader, verticesSectionName); 1771 readColladaInputs(reader, verticesSectionName);
1772 } 1772 }
1773 else 1773 else
1774 // lines and linestrips missing 1774 // lines and linestrips missing
1775 if (polygonsSectionName == nodeName || 1775 if (polygonsSectionName == nodeName ||
1776 polylistSectionName == nodeName || 1776 polylistSectionName == nodeName ||
1777 trianglesSectionName == nodeName) 1777 trianglesSectionName == nodeName)
1778 { 1778 {
1779 // read polygons section 1779 // read polygons section
1780 readPolygonSection(reader, sources, mesh, id); 1780 readPolygonSection(reader, sources, mesh, id);
1781 } 1781 }
1782 else 1782 else
1783 // trifans, and tristrips missing 1783 // trifans, and tristrips missing
1784 if (doubleSidedNodeName == reader->getNodeName()) 1784 if (doubleSidedNodeName == reader->getNodeName())
1785 { 1785 {
1786 // read the extra flag for double sided polys 1786 // read the extra flag for double sided polys
1787 s32 doubleSided = 0; 1787 s32 doubleSided = 0;
1788 readIntsInsideElement(reader,&doubleSided,1); 1788 readIntsInsideElement(reader,&doubleSided,1);
1789 if (doubleSided) 1789 if (doubleSided)
1790 { 1790 {
1791 #ifdef COLLADA_READER_DEBUG 1791 #ifdef COLLADA_READER_DEBUG
1792 os::Printer::log("Setting double sided flag for mesh.", ELL_DEBUG); 1792 os::Printer::log("Setting double sided flag for mesh.", ELL_DEBUG);
1793 #endif 1793 #endif
1794 amesh->setMaterialFlag(irr::video::EMF_BACK_FACE_CULLING,false); 1794 amesh->setMaterialFlag(irr::video::EMF_BACK_FACE_CULLING,false);
1795 } 1795 }
1796 } 1796 }
1797 else 1797 else
1798 // techniqueCommon or 'technique profile=common' must not be skipped 1798 // techniqueCommon or 'technique profile=common' must not be skipped
1799 if ((techniqueCommonSectionName != nodeName) // Collada 1.2/1.3 1799 if ((techniqueCommonSectionName != nodeName) // Collada 1.2/1.3
1800 && (techniqueNodeName != nodeName) // Collada 1.4+ 1800 && (techniqueNodeName != nodeName) // Collada 1.4+
1801 && (extraNodeName != nodeName)) 1801 && (extraNodeName != nodeName))
1802 { 1802 {
1803 os::Printer::log("COLLADA loader warning: Wrong tag usage found in geometry", reader->getNodeName(), ELL_WARNING); 1803 os::Printer::log("COLLADA loader warning: Wrong tag usage found in geometry", reader->getNodeName(), ELL_WARNING);
1804 skipSection(reader, true); // ignore all other sections 1804 skipSection(reader, true); // ignore all other sections
1805 } 1805 }
1806 } // end if node type is element 1806 } // end if node type is element
1807 else 1807 else
1808 if (reader->getNodeType() == io::EXN_TEXT) 1808 if (reader->getNodeType() == io::EXN_TEXT)
1809 { 1809 {
1810 // read array data 1810 // read array data
1811 if (okToReadArray && !sources.empty()) 1811 if (okToReadArray && !sources.empty())
1812 { 1812 {
1813 core::array<f32>& a = sources.getLast().Array.Data; 1813 core::array<f32>& a = sources.getLast().Array.Data;
1814 core::stringc data = reader->getNodeData(); 1814 core::stringc data = reader->getNodeData();
1815 data.trim(); 1815 data.trim();
1816 const c8* p = &data[0]; 1816 const c8* p = &data[0];
1817 1817
1818 for (u32 i=0; i<a.size(); ++i) 1818 for (u32 i=0; i<a.size(); ++i)
1819 { 1819 {
1820 findNextNoneWhiteSpace(&p); 1820 findNextNoneWhiteSpace(&p);
1821 if (*p) 1821 if (*p)
1822 a[i] = readFloat(&p); 1822 a[i] = readFloat(&p);
1823 else 1823 else
1824 a[i] = 0.0f; 1824 a[i] = 0.0f;
1825 } 1825 }
1826 } // end reading array 1826 } // end reading array
1827 1827
1828 okToReadArray = false; 1828 okToReadArray = false;
1829 1829
1830 } // end if node type is text 1830 } // end if node type is text
1831 else 1831 else
1832 if (reader->getNodeType() == io::EXN_ELEMENT_END) 1832 if (reader->getNodeType() == io::EXN_ELEMENT_END)
1833 { 1833 {
1834 if (geometrySectionName == reader->getNodeName()) 1834 if (geometrySectionName == reader->getNodeName())
1835 { 1835 {
1836 // end of geometry section reached, cancel out 1836 // end of geometry section reached, cancel out
1837 break; 1837 break;
1838 } 1838 }
1839 } 1839 }
1840 } // end while reader->read(); 1840 } // end while reader->read();
1841 1841
1842 // add mesh as geometry 1842 // add mesh as geometry
1843 1843
1844 mesh->recalculateBoundingBox(); 1844 mesh->recalculateBoundingBox();
1845 amesh->recalculateBoundingBox(); 1845 amesh->recalculateBoundingBox();
1846 1846
1847 // create virtual file name 1847 // create virtual file name
1848 io::path filename = CurrentlyLoadingMesh; 1848 io::path filename = CurrentlyLoadingMesh;
1849 filename += '#'; 1849 filename += '#';
1850 filename += id; 1850 filename += id;
1851 1851
1852 // add to scene manager 1852 // add to scene manager
1853 if (LoadedMeshCount) 1853 if (LoadedMeshCount)
1854 { 1854 {
1855 SceneManager->getMeshCache()->addMesh(filename.c_str(), amesh); 1855 SceneManager->getMeshCache()->addMesh(filename.c_str(), amesh);
1856 os::Printer::log("Added COLLADA mesh", filename.c_str(), ELL_DEBUG); 1856 os::Printer::log("Added COLLADA mesh", filename.c_str(), ELL_DEBUG);
1857 } 1857 }
1858 else 1858 else
1859 { 1859 {
1860 FirstLoadedMeshName = filename; 1860 FirstLoadedMeshName = filename;
1861 FirstLoadedMesh = amesh; 1861 FirstLoadedMesh = amesh;
1862 FirstLoadedMesh->grab(); 1862 FirstLoadedMesh->grab();
1863 } 1863 }
1864 1864
1865 ++LoadedMeshCount; 1865 ++LoadedMeshCount;
1866 mesh->drop(); 1866 mesh->drop();
1867 amesh->drop(); 1867 amesh->drop();
1868 1868
1869 // create geometry prefab 1869 // create geometry prefab
1870 u32 i; 1870 u32 i;
1871 for (i=0; i<Prefabs.size(); ++i) 1871 for (i=0; i<Prefabs.size(); ++i)
1872 { 1872 {
1873 if (Prefabs[i]->getId()==id) 1873 if (Prefabs[i]->getId()==id)
1874 { 1874 {
1875 ((CGeometryPrefab*)Prefabs[i])->Mesh=mesh; 1875 ((CGeometryPrefab*)Prefabs[i])->Mesh=mesh;
1876 break; 1876 break;
1877 } 1877 }
1878 } 1878 }
1879 if (i==Prefabs.size()) 1879 if (i==Prefabs.size())
1880 { 1880 {
1881 CGeometryPrefab* prefab = new CGeometryPrefab(id); 1881 CGeometryPrefab* prefab = new CGeometryPrefab(id);
1882 prefab->Mesh = mesh; 1882 prefab->Mesh = mesh;
1883 Prefabs.push_back(prefab); 1883 Prefabs.push_back(prefab);
1884 } 1884 }
1885 1885
1886 // store as dummy mesh if no instances will be created 1886 // store as dummy mesh if no instances will be created
1887 if (!CreateInstances && !DummyMesh) 1887 if (!CreateInstances && !DummyMesh)
1888 { 1888 {
1889 DummyMesh = amesh; 1889 DummyMesh = amesh;
1890 DummyMesh->grab(); 1890 DummyMesh->grab();
1891 } 1891 }
1892} 1892}
1893 1893
1894 1894
1895struct SPolygon 1895struct SPolygon
1896{ 1896{
1897 core::array<s32> Indices; 1897 core::array<s32> Indices;
1898}; 1898};
1899 1899
1900//! reads a polygons section and creates a mesh from it 1900//! reads a polygons section and creates a mesh from it
1901void CColladaFileLoader::readPolygonSection(io::IXMLReaderUTF8* reader, 1901void CColladaFileLoader::readPolygonSection(io::IXMLReaderUTF8* reader,
1902 core::array<SSource>& sources, scene::SMesh* mesh, 1902 core::array<SSource>& sources, scene::SMesh* mesh,
1903 const core::stringc& geometryId) 1903 const core::stringc& geometryId)
1904{ 1904{
1905 #ifdef COLLADA_READER_DEBUG 1905 #ifdef COLLADA_READER_DEBUG
1906 os::Printer::log("COLLADA reading polygon section", ELL_DEBUG); 1906 os::Printer::log("COLLADA reading polygon section", ELL_DEBUG);
1907 #endif 1907 #endif
1908 1908
1909 core::stringc materialName = reader->getAttributeValue("material"); 1909 core::stringc materialName = reader->getAttributeValue("material");
1910 1910
1911 core::stringc polygonType = reader->getNodeName(); 1911 core::stringc polygonType = reader->getNodeName();
1912 const int polygonCount = reader->getAttributeValueAsInt("count"); // Not useful because it only determines the number of primitives, which have arbitrary vertices in case of polygon 1912 const int polygonCount = reader->getAttributeValueAsInt("count"); // Not useful because it only determines the number of primitives, which have arbitrary vertices in case of polygon
1913 core::array<SPolygon> polygons; 1913 core::array<SPolygon> polygons;
1914 if (polygonType == polygonsSectionName) 1914 if (polygonType == polygonsSectionName)
1915 polygons.reallocate(polygonCount); 1915 polygons.reallocate(polygonCount);
1916 core::array<int> vCounts; 1916 core::array<int> vCounts;
1917 bool parsePolygonOK = false; 1917 bool parsePolygonOK = false;
1918 bool parseVcountOK = false; 1918 bool parseVcountOK = false;
1919 u32 inputSemanticCount = 0; 1919 u32 inputSemanticCount = 0;
1920 bool unresolvedInput=false; 1920 bool unresolvedInput=false;
1921 u32 maxOffset = 0; 1921 u32 maxOffset = 0;
1922 core::array<SColladaInput> localInputs; 1922 core::array<SColladaInput> localInputs;
1923 1923
1924 // read all <input> and primitives 1924 // read all <input> and primitives
1925 if (!reader->isEmptyElement()) 1925 if (!reader->isEmptyElement())
1926 while(reader->read()) 1926 while(reader->read())
1927 { 1927 {
1928 const char* nodeName = reader->getNodeName(); 1928 const char* nodeName = reader->getNodeName();
1929 1929
1930 if (reader->getNodeType() == io::EXN_ELEMENT) 1930 if (reader->getNodeType() == io::EXN_ELEMENT)
1931 { 1931 {
1932 // polygon node may contain params 1932 // polygon node may contain params
1933 if (inputTagName == nodeName) 1933 if (inputTagName == nodeName)
1934 { 1934 {
1935 // read input tag 1935 // read input tag
1936 readColladaInput(reader, localInputs); 1936 readColladaInput(reader, localInputs);
1937 1937
1938 // resolve input source 1938 // resolve input source
1939 SColladaInput& inp = localInputs.getLast(); 1939 SColladaInput& inp = localInputs.getLast();
1940 1940
1941 // get input source array id, if it is a vertex input, take 1941 // get input source array id, if it is a vertex input, take
1942 // the <vertex><input>-source attribute. 1942 // the <vertex><input>-source attribute.
1943 if (inp.Semantic == ECIS_VERTEX) 1943 if (inp.Semantic == ECIS_VERTEX)
1944 { 1944 {
1945 inp.Source = Inputs[0].Source; 1945 inp.Source = Inputs[0].Source;
1946 for (u32 i=1; i<Inputs.size(); ++i) 1946 for (u32 i=1; i<Inputs.size(); ++i)
1947 { 1947 {
1948 localInputs.push_back(Inputs[i]); 1948 localInputs.push_back(Inputs[i]);
1949 uriToId(localInputs.getLast().Source); 1949 uriToId(localInputs.getLast().Source);
1950 maxOffset = core::max_(maxOffset,localInputs.getLast().Offset); 1950 maxOffset = core::max_(maxOffset,localInputs.getLast().Offset);
1951 ++inputSemanticCount; 1951 ++inputSemanticCount;
1952 } 1952 }
1953 } 1953 }
1954 uriToId(inp.Source); 1954 uriToId(inp.Source);
1955 maxOffset = core::max_(maxOffset,inp.Offset); 1955 maxOffset = core::max_(maxOffset,inp.Offset);
1956 ++inputSemanticCount; 1956 ++inputSemanticCount;
1957 } 1957 }
1958 else 1958 else
1959 if (primitivesName == nodeName) 1959 if (primitivesName == nodeName)
1960 { 1960 {
1961 parsePolygonOK = true; 1961 parsePolygonOK = true;
1962 polygons.push_back(SPolygon()); 1962 polygons.push_back(SPolygon());
1963 } 1963 }
1964 else 1964 else
1965 if (vcountName == nodeName) 1965 if (vcountName == nodeName)
1966 { 1966 {
1967 parseVcountOK = true; 1967 parseVcountOK = true;
1968 } // end is polygon node 1968 } // end is polygon node
1969 } // end is element node 1969 } // end is element node
1970 else 1970 else
1971 if (reader->getNodeType() == io::EXN_ELEMENT_END) 1971 if (reader->getNodeType() == io::EXN_ELEMENT_END)
1972 { 1972 {
1973 if (primitivesName == nodeName) 1973 if (primitivesName == nodeName)
1974 parsePolygonOK = false; // end parsing a polygon 1974 parsePolygonOK = false; // end parsing a polygon
1975 else 1975 else
1976 if (vcountName == nodeName) 1976 if (vcountName == nodeName)
1977 parseVcountOK = false; // end parsing vcounts 1977 parseVcountOK = false; // end parsing vcounts
1978 else 1978 else
1979 if (polygonType == nodeName) 1979 if (polygonType == nodeName)
1980 break; // cancel out and create mesh 1980 break; // cancel out and create mesh
1981 1981
1982 } // end is element end 1982 } // end is element end
1983 else 1983 else
1984 if (reader->getNodeType() == io::EXN_TEXT) 1984 if (reader->getNodeType() == io::EXN_TEXT)
1985 { 1985 {
1986 if (parseVcountOK) 1986 if (parseVcountOK)
1987 { 1987 {
1988 core::stringc data = reader->getNodeData(); 1988 core::stringc data = reader->getNodeData();
1989 data.trim(); 1989 data.trim();
1990 const c8* p = &data[0]; 1990 const c8* p = &data[0];
1991 while(*p) 1991 while(*p)
1992 { 1992 {
1993 findNextNoneWhiteSpace(&p); 1993 findNextNoneWhiteSpace(&p);
1994 if (*p) 1994 if (*p)
1995 vCounts.push_back(readInt(&p)); 1995 vCounts.push_back(readInt(&p));
1996 } 1996 }
1997 parseVcountOK = false; 1997 parseVcountOK = false;
1998 } 1998 }
1999 else 1999 else
2000 if (parsePolygonOK && polygons.size()) 2000 if (parsePolygonOK && polygons.size())
2001 { 2001 {
2002 core::stringc data = reader->getNodeData(); 2002 core::stringc data = reader->getNodeData();
2003 data.trim(); 2003 data.trim();
2004 const c8* p = &data[0]; 2004 const c8* p = &data[0];
2005 SPolygon& poly = polygons.getLast(); 2005 SPolygon& poly = polygons.getLast();
2006 if (polygonType == polygonsSectionName) 2006 if (polygonType == polygonsSectionName)
2007 poly.Indices.reallocate((maxOffset+1)*3); 2007 poly.Indices.reallocate((maxOffset+1)*3);
2008 else 2008 else
2009 poly.Indices.reallocate(polygonCount*(maxOffset+1)*3); 2009 poly.Indices.reallocate(polygonCount*(maxOffset+1)*3);
2010 2010
2011 if (vCounts.empty()) 2011 if (vCounts.empty())
2012 { 2012 {
2013 while(*p) 2013 while(*p)
2014 { 2014 {
2015 findNextNoneWhiteSpace(&p); 2015 findNextNoneWhiteSpace(&p);
2016 poly.Indices.push_back(readInt(&p)); 2016 poly.Indices.push_back(readInt(&p));
2017 } 2017 }
2018 } 2018 }
2019 else 2019 else
2020 { 2020 {
2021 for (u32 i = 0; i < vCounts.size(); i++) 2021 for (u32 i = 0; i < vCounts.size(); i++)
2022 { 2022 {
2023 const int polyVCount = vCounts[i]; 2023 const int polyVCount = vCounts[i];
2024 core::array<int> polyCorners; 2024 core::array<int> polyCorners;
2025 2025
2026 for (u32 j = 0; j < polyVCount * inputSemanticCount; j++) 2026 for (u32 j = 0; j < polyVCount * inputSemanticCount; j++)
2027 { 2027 {
2028 if (!*p) 2028 if (!*p)
2029 break; 2029 break;
2030 findNextNoneWhiteSpace(&p); 2030 findNextNoneWhiteSpace(&p);
2031 polyCorners.push_back(readInt(&p)); 2031 polyCorners.push_back(readInt(&p));
2032 } 2032 }
2033 2033
2034 while (polyCorners.size() >= 3 * inputSemanticCount) 2034 while (polyCorners.size() >= 3 * inputSemanticCount)
2035 { 2035 {
2036 // add one triangle's worth of indices 2036 // add one triangle's worth of indices
2037 for (u32 k = 0; k < inputSemanticCount * 3; ++k) 2037 for (u32 k = 0; k < inputSemanticCount * 3; ++k)
2038 { 2038 {
2039 poly.Indices.push_back(polyCorners[k]); 2039 poly.Indices.push_back(polyCorners[k]);
2040 } 2040 }
2041 2041
2042 // remove one corner from our poly 2042 // remove one corner from our poly
2043 polyCorners.erase(inputSemanticCount,inputSemanticCount); 2043 polyCorners.erase(inputSemanticCount,inputSemanticCount);
2044 } 2044 }
2045 polyCorners.clear(); 2045 polyCorners.clear();
2046 } 2046 }
2047 vCounts.clear(); 2047 vCounts.clear();
2048 } 2048 }
2049 parsePolygonOK = false; 2049 parsePolygonOK = false;
2050 } 2050 }
2051 } 2051 }
2052 } // end while reader->read() 2052 } // end while reader->read()
2053 2053
2054 // find source array (we'll ignore accessors for this implementation) 2054 // find source array (we'll ignore accessors for this implementation)
2055 for (u32 i=0; i<localInputs.size(); ++i) 2055 for (u32 i=0; i<localInputs.size(); ++i)
2056 { 2056 {
2057 SColladaInput& inp = localInputs[i]; 2057 SColladaInput& inp = localInputs[i];
2058 u32 s; 2058 u32 s;
2059 for (s=0; s<sources.size(); ++s) 2059 for (s=0; s<sources.size(); ++s)
2060 { 2060 {
2061 if (sources[s].Id == inp.Source) 2061 if (sources[s].Id == inp.Source)
2062 { 2062 {
2063 // slot found 2063 // slot found
2064 inp.Data = sources[s].Array.Data.pointer(); 2064 inp.Data = sources[s].Array.Data.pointer();
2065 inp.Stride = sources[s].Accessors[0].Stride; 2065 inp.Stride = sources[s].Accessors[0].Stride;
2066 break; 2066 break;
2067 } 2067 }
2068 } 2068 }
2069 2069
2070 if (s == sources.size()) 2070 if (s == sources.size())
2071 { 2071 {
2072 os::Printer::log("COLLADA Warning, polygon input source not found", 2072 os::Printer::log("COLLADA Warning, polygon input source not found",
2073 inp.Source.c_str(), ELL_DEBUG); 2073 inp.Source.c_str(), ELL_DEBUG);
2074 inp.Semantic=ECIS_COUNT; // for unknown 2074 inp.Semantic=ECIS_COUNT; // for unknown
2075 unresolvedInput=true; 2075 unresolvedInput=true;
2076 } 2076 }
2077 else 2077 else
2078 { 2078 {
2079 #ifdef COLLADA_READER_DEBUG 2079 #ifdef COLLADA_READER_DEBUG
2080 // print slot 2080 // print slot
2081 core::stringc tmp = "Added slot "; 2081 core::stringc tmp = "Added slot ";
2082 tmp += inputSemanticNames[inp.Semantic]; 2082 tmp += inputSemanticNames[inp.Semantic];
2083 tmp += " sourceArray:"; 2083 tmp += " sourceArray:";
2084 tmp += inp.Source; 2084 tmp += inp.Source;
2085 os::Printer::log(tmp.c_str(), ELL_DEBUG); 2085 os::Printer::log(tmp.c_str(), ELL_DEBUG);
2086 #endif 2086 #endif
2087 } 2087 }
2088 } 2088 }
2089 2089
2090 if ((inputSemanticCount == 0) || !polygons.size()) 2090 if ((inputSemanticCount == 0) || !polygons.size())
2091 return; // cancel if there are no polygons anyway. 2091 return; // cancel if there are no polygons anyway.
2092 2092
2093 // analyze content of Inputs to create a fitting mesh buffer 2093 // analyze content of Inputs to create a fitting mesh buffer
2094 2094
2095 u32 u; 2095 u32 u;
2096 u32 textureCoordSetCount = 0; 2096 u32 textureCoordSetCount = 0;
2097 bool normalSlotCount = false; 2097 bool normalSlotCount = false;
2098 u32 secondTexCoordSetIndex = 0xFFFFFFFF; 2098 u32 secondTexCoordSetIndex = 0xFFFFFFFF;
2099 2099
2100 for (u=0; u<Inputs.size(); ++u) 2100 for (u=0; u<Inputs.size(); ++u)
2101 { 2101 {
2102 if (Inputs[u].Semantic == ECIS_TEXCOORD || Inputs[u].Semantic == ECIS_UV ) 2102 if (Inputs[u].Semantic == ECIS_TEXCOORD || Inputs[u].Semantic == ECIS_UV )
2103 { 2103 {
2104 ++textureCoordSetCount; 2104 ++textureCoordSetCount;
2105 2105
2106 if (textureCoordSetCount==2) 2106 if (textureCoordSetCount==2)
2107 secondTexCoordSetIndex = u; 2107 secondTexCoordSetIndex = u;
2108 } 2108 }
2109 else 2109 else
2110 if (Inputs[u].Semantic == ECIS_NORMAL) 2110 if (Inputs[u].Semantic == ECIS_NORMAL)
2111 normalSlotCount=true; 2111 normalSlotCount=true;
2112 } 2112 }
2113 2113
2114 // if there is more than one texture coordinate set, create a lightmap mesh buffer, 2114 // if there is more than one texture coordinate set, create a lightmap mesh buffer,
2115 // otherwise use a standard mesh buffer 2115 // otherwise use a standard mesh buffer
2116 2116
2117 scene::IMeshBuffer* buffer = 0; 2117 scene::IMeshBuffer* buffer = 0;
2118 ++maxOffset; // +1 to jump to the next value 2118 ++maxOffset; // +1 to jump to the next value
2119 2119
2120 if ( textureCoordSetCount < 2 ) 2120 if ( textureCoordSetCount < 2 )
2121 { 2121 {
2122 // standard mesh buffer 2122 // standard mesh buffer
2123 2123
2124 scene::SMeshBuffer* mbuffer = new SMeshBuffer(); 2124 scene::SMeshBuffer* mbuffer = new SMeshBuffer();
2125 buffer = mbuffer; 2125 buffer = mbuffer;
2126 2126
2127 core::map<video::S3DVertex, int> vertMap; 2127 core::map<video::S3DVertex, int> vertMap;
2128 2128
2129 for (u32 i=0; i<polygons.size(); ++i) 2129 for (u32 i=0; i<polygons.size(); ++i)
2130 { 2130 {
2131 core::array<u16> indices; 2131 core::array<u16> indices;
2132 const u32 vertexCount = polygons[i].Indices.size() / maxOffset; 2132 const u32 vertexCount = polygons[i].Indices.size() / maxOffset;
2133 mbuffer->Vertices.reallocate(mbuffer->Vertices.size()+vertexCount); 2133 mbuffer->Vertices.reallocate(mbuffer->Vertices.size()+vertexCount);
2134 2134
2135 // for all index/semantic groups 2135 // for all index/semantic groups
2136 for (u32 v=0; v<polygons[i].Indices.size(); v+=maxOffset) 2136 for (u32 v=0; v<polygons[i].Indices.size(); v+=maxOffset)
2137 { 2137 {
2138 video::S3DVertex vtx; 2138 video::S3DVertex vtx;
2139 vtx.Color.set(255,255,255,255); 2139 vtx.Color.set(255,255,255,255);
2140 2140
2141 // for all input semantics 2141 // for all input semantics
2142 for (u32 k=0; k<localInputs.size(); ++k) 2142 for (u32 k=0; k<localInputs.size(); ++k)
2143 { 2143 {
2144 if (!localInputs[k].Data) 2144 if (!localInputs[k].Data)
2145 continue; 2145 continue;
2146 // build vertex from input semantics. 2146 // build vertex from input semantics.
2147 2147
2148 const u32 idx = localInputs[k].Stride*polygons[i].Indices[v+localInputs[k].Offset]; 2148 const u32 idx = localInputs[k].Stride*polygons[i].Indices[v+localInputs[k].Offset];
2149 2149
2150 switch(localInputs[k].Semantic) 2150 switch(localInputs[k].Semantic)
2151 { 2151 {
2152 case ECIS_POSITION: 2152 case ECIS_POSITION:
2153 case ECIS_VERTEX: 2153 case ECIS_VERTEX:
2154 vtx.Pos.X = localInputs[k].Data[idx+0]; 2154 vtx.Pos.X = localInputs[k].Data[idx+0];
2155 if (FlipAxis) 2155 if (FlipAxis)
2156 { 2156 {
2157 vtx.Pos.Z = localInputs[k].Data[idx+1]; 2157 vtx.Pos.Z = localInputs[k].Data[idx+1];
2158 vtx.Pos.Y = localInputs[k].Data[idx+2]; 2158 vtx.Pos.Y = localInputs[k].Data[idx+2];
2159 } 2159 }
2160 else 2160 else
2161 { 2161 {
2162 vtx.Pos.Y = localInputs[k].Data[idx+1]; 2162 vtx.Pos.Y = localInputs[k].Data[idx+1];
2163 vtx.Pos.Z = localInputs[k].Data[idx+2]; 2163 vtx.Pos.Z = localInputs[k].Data[idx+2];
2164 } 2164 }
2165 break; 2165 break;
2166 case ECIS_NORMAL: 2166 case ECIS_NORMAL:
2167 vtx.Normal.X = localInputs[k].Data[idx+0]; 2167 vtx.Normal.X = localInputs[k].Data[idx+0];
2168 if (FlipAxis) 2168 if (FlipAxis)
2169 { 2169 {
2170 vtx.Normal.Z = localInputs[k].Data[idx+1]; 2170 vtx.Normal.Z = localInputs[k].Data[idx+1];
2171 vtx.Normal.Y = localInputs[k].Data[idx+2]; 2171 vtx.Normal.Y = localInputs[k].Data[idx+2];
2172 } 2172 }
2173 else 2173 else
2174 { 2174 {
2175 vtx.Normal.Y = localInputs[k].Data[idx+1]; 2175 vtx.Normal.Y = localInputs[k].Data[idx+1];
2176 vtx.Normal.Z = localInputs[k].Data[idx+2]; 2176 vtx.Normal.Z = localInputs[k].Data[idx+2];
2177 } 2177 }
2178 break; 2178 break;
2179 case ECIS_TEXCOORD: 2179 case ECIS_TEXCOORD:
2180 case ECIS_UV: 2180 case ECIS_UV:
2181 vtx.TCoords.X = localInputs[k].Data[idx+0]; 2181 vtx.TCoords.X = localInputs[k].Data[idx+0];
2182 vtx.TCoords.Y = 1-localInputs[k].Data[idx+1]; 2182 vtx.TCoords.Y = 1-localInputs[k].Data[idx+1];
2183 break; 2183 break;
2184 case ECIS_TANGENT: 2184 case ECIS_TANGENT:
2185 break; 2185 break;
2186 default: 2186 default:
2187 break; 2187 break;
2188 } 2188 }
2189 } 2189 }
2190 2190
2191 //first, try to find this vertex in the mesh 2191 //first, try to find this vertex in the mesh
2192 core::map<video::S3DVertex, int>::Node* n = vertMap.find(vtx); 2192 core::map<video::S3DVertex, int>::Node* n = vertMap.find(vtx);
2193 if (n) 2193 if (n)
2194 { 2194 {
2195 indices.push_back(n->getValue()); 2195 indices.push_back(n->getValue());
2196 } 2196 }
2197 else 2197 else
2198 { 2198 {
2199 indices.push_back(mbuffer->getVertexCount()); 2199 indices.push_back(mbuffer->getVertexCount());
2200 mbuffer->Vertices.push_back(vtx); 2200 mbuffer->Vertices.push_back(vtx);
2201 vertMap.insert(vtx, mbuffer->getVertexCount()-1); 2201 vertMap.insert(vtx, mbuffer->getVertexCount()-1);
2202 } 2202 }
2203 } // end for all vertices 2203 } // end for all vertices
2204 2204
2205 if (polygonsSectionName == polygonType && 2205 if (polygonsSectionName == polygonType &&
2206 indices.size() > 3) 2206 indices.size() > 3)
2207 { 2207 {
2208 // need to tesselate for polygons of 4 or more vertices 2208 // need to tesselate for polygons of 4 or more vertices
2209 // for now we naively turn interpret it as a triangle fan 2209 // for now we naively turn interpret it as a triangle fan
2210 // as full tesselation is problematic 2210 // as full tesselation is problematic
2211 if (FlipAxis) 2211 if (FlipAxis)
2212 { 2212 {
2213 for (u32 ind = indices.size()-3; ind>0 ; --ind) 2213 for (u32 ind = indices.size()-3; ind>0 ; --ind)
2214 { 2214 {
2215 mbuffer->Indices.push_back(indices[0]); 2215 mbuffer->Indices.push_back(indices[0]);
2216 mbuffer->Indices.push_back(indices[ind+2]); 2216 mbuffer->Indices.push_back(indices[ind+2]);
2217 mbuffer->Indices.push_back(indices[ind+1]); 2217 mbuffer->Indices.push_back(indices[ind+1]);
2218 } 2218 }
2219 } 2219 }
2220 else 2220 else
2221 { 2221 {
2222 for (u32 ind = 0; ind+2 < indices.size(); ++ind) 2222 for (u32 ind = 0; ind+2 < indices.size(); ++ind)
2223 { 2223 {
2224 mbuffer->Indices.push_back(indices[0]); 2224 mbuffer->Indices.push_back(indices[0]);
2225 mbuffer->Indices.push_back(indices[ind+1]); 2225 mbuffer->Indices.push_back(indices[ind+1]);
2226 mbuffer->Indices.push_back(indices[ind+2]); 2226 mbuffer->Indices.push_back(indices[ind+2]);
2227 } 2227 }
2228 } 2228 }
2229 } 2229 }
2230 else 2230 else
2231 { 2231 {
2232 // it's just triangles 2232 // it's just triangles
2233 for (u32 ind = 0; ind < indices.size(); ind+=3) 2233 for (u32 ind = 0; ind < indices.size(); ind+=3)
2234 { 2234 {
2235 if (FlipAxis) 2235 if (FlipAxis)
2236 { 2236 {
2237 mbuffer->Indices.push_back(indices[ind+2]); 2237 mbuffer->Indices.push_back(indices[ind+2]);
2238 mbuffer->Indices.push_back(indices[ind+1]); 2238 mbuffer->Indices.push_back(indices[ind+1]);
2239 mbuffer->Indices.push_back(indices[ind+0]); 2239 mbuffer->Indices.push_back(indices[ind+0]);
2240 } 2240 }
2241 else 2241 else
2242 { 2242 {
2243 mbuffer->Indices.push_back(indices[ind+0]); 2243 mbuffer->Indices.push_back(indices[ind+0]);
2244 mbuffer->Indices.push_back(indices[ind+1]); 2244 mbuffer->Indices.push_back(indices[ind+1]);
2245 mbuffer->Indices.push_back(indices[ind+2]); 2245 mbuffer->Indices.push_back(indices[ind+2]);
2246 } 2246 }
2247 } 2247 }
2248 } 2248 }
2249 2249
2250 } // end for all polygons 2250 } // end for all polygons
2251 } 2251 }
2252 else 2252 else
2253 { 2253 {
2254 // lightmap mesh buffer 2254 // lightmap mesh buffer
2255 2255
2256 scene::SMeshBufferLightMap* mbuffer = new SMeshBufferLightMap(); 2256 scene::SMeshBufferLightMap* mbuffer = new SMeshBufferLightMap();
2257 buffer = mbuffer; 2257 buffer = mbuffer;
2258 2258
2259 for (u32 i=0; i<polygons.size(); ++i) 2259 for (u32 i=0; i<polygons.size(); ++i)
2260 { 2260 {
2261 const u32 vertexCount = polygons[i].Indices.size() / maxOffset; 2261 const u32 vertexCount = polygons[i].Indices.size() / maxOffset;
2262 mbuffer->Vertices.reallocate(mbuffer->Vertices.size()+vertexCount); 2262 mbuffer->Vertices.reallocate(mbuffer->Vertices.size()+vertexCount);
2263 // for all vertices in array 2263 // for all vertices in array
2264 for (u32 v=0; v<polygons[i].Indices.size(); v+=maxOffset) 2264 for (u32 v=0; v<polygons[i].Indices.size(); v+=maxOffset)
2265 { 2265 {
2266 video::S3DVertex2TCoords vtx; 2266 video::S3DVertex2TCoords vtx;
2267 vtx.Color.set(100,255,255,255); 2267 vtx.Color.set(100,255,255,255);
2268 2268
2269 // for all input semantics 2269 // for all input semantics
2270 for (u32 k=0; k<Inputs.size(); ++k) 2270 for (u32 k=0; k<Inputs.size(); ++k)
2271 { 2271 {
2272 // build vertex from input semantics. 2272 // build vertex from input semantics.
2273 2273
2274 const u32 idx = localInputs[k].Stride*polygons[i].Indices[v+Inputs[k].Offset]; 2274 const u32 idx = localInputs[k].Stride*polygons[i].Indices[v+Inputs[k].Offset];
2275 2275
2276 switch(localInputs[k].Semantic) 2276 switch(localInputs[k].Semantic)
2277 { 2277 {
2278 case ECIS_POSITION: 2278 case ECIS_POSITION:
2279 case ECIS_VERTEX: 2279 case ECIS_VERTEX:
2280 vtx.Pos.X = localInputs[k].Data[idx+0]; 2280 vtx.Pos.X = localInputs[k].Data[idx+0];
2281 if (FlipAxis) 2281 if (FlipAxis)
2282 { 2282 {
2283 vtx.Pos.Z = localInputs[k].Data[idx+1]; 2283 vtx.Pos.Z = localInputs[k].Data[idx+1];
2284 vtx.Pos.Y = localInputs[k].Data[idx+2]; 2284 vtx.Pos.Y = localInputs[k].Data[idx+2];
2285 } 2285 }
2286 else 2286 else
2287 { 2287 {
2288 vtx.Pos.Y = localInputs[k].Data[idx+1]; 2288 vtx.Pos.Y = localInputs[k].Data[idx+1];
2289 vtx.Pos.Z = localInputs[k].Data[idx+2]; 2289 vtx.Pos.Z = localInputs[k].Data[idx+2];
2290 } 2290 }
2291 break; 2291 break;
2292 case ECIS_NORMAL: 2292 case ECIS_NORMAL:
2293 vtx.Normal.X = localInputs[k].Data[idx+0]; 2293 vtx.Normal.X = localInputs[k].Data[idx+0];
2294 if (FlipAxis) 2294 if (FlipAxis)
2295 { 2295 {
2296 vtx.Normal.Z = localInputs[k].Data[idx+1]; 2296 vtx.Normal.Z = localInputs[k].Data[idx+1];
2297 vtx.Normal.Y = localInputs[k].Data[idx+2]; 2297 vtx.Normal.Y = localInputs[k].Data[idx+2];
2298 } 2298 }
2299 else 2299 else
2300 { 2300 {
2301 vtx.Normal.Y = localInputs[k].Data[idx+1]; 2301 vtx.Normal.Y = localInputs[k].Data[idx+1];
2302 vtx.Normal.Z = localInputs[k].Data[idx+2]; 2302 vtx.Normal.Z = localInputs[k].Data[idx+2];
2303 } 2303 }
2304 break; 2304 break;
2305 case ECIS_TEXCOORD: 2305 case ECIS_TEXCOORD:
2306 case ECIS_UV: 2306 case ECIS_UV:
2307 if (k==secondTexCoordSetIndex) 2307 if (k==secondTexCoordSetIndex)
2308 { 2308 {
2309 vtx.TCoords2.X = localInputs[k].Data[idx+0]; 2309 vtx.TCoords2.X = localInputs[k].Data[idx+0];
2310 vtx.TCoords2.Y = 1-localInputs[k].Data[idx+1]; 2310 vtx.TCoords2.Y = 1-localInputs[k].Data[idx+1];
2311 } 2311 }
2312 else 2312 else
2313 { 2313 {
2314 vtx.TCoords.X = localInputs[k].Data[idx+0]; 2314 vtx.TCoords.X = localInputs[k].Data[idx+0];
2315 vtx.TCoords.Y = 1-localInputs[k].Data[idx+1]; 2315 vtx.TCoords.Y = 1-localInputs[k].Data[idx+1];
2316 } 2316 }
2317 break; 2317 break;
2318 case ECIS_TANGENT: 2318 case ECIS_TANGENT:
2319 break; 2319 break;
2320 default: 2320 default:
2321 break; 2321 break;
2322 } 2322 }
2323 } 2323 }
2324 2324
2325 mbuffer->Vertices.push_back(vtx); 2325 mbuffer->Vertices.push_back(vtx);
2326 2326
2327 } // end for all vertices 2327 } // end for all vertices
2328 2328
2329 // add vertex indices 2329 // add vertex indices
2330 const u32 oldVertexCount = mbuffer->Vertices.size() - vertexCount; 2330 const u32 oldVertexCount = mbuffer->Vertices.size() - vertexCount;
2331 for (u32 face=0; face<vertexCount-2; ++face) 2331 for (u32 face=0; face<vertexCount-2; ++face)
2332 { 2332 {
2333 mbuffer->Indices.push_back(oldVertexCount + 0); 2333 mbuffer->Indices.push_back(oldVertexCount + 0);
2334 mbuffer->Indices.push_back(oldVertexCount + 1 + face); 2334 mbuffer->Indices.push_back(oldVertexCount + 1 + face);
2335 mbuffer->Indices.push_back(oldVertexCount + 2 + face); 2335 mbuffer->Indices.push_back(oldVertexCount + 2 + face);
2336 } 2336 }
2337 2337
2338 } // end for all polygons 2338 } // end for all polygons
2339 } 2339 }
2340 2340
2341 const SColladaMaterial* m = findMaterial(materialName); 2341 const SColladaMaterial* m = findMaterial(materialName);
2342 if (m) 2342 if (m)
2343 { 2343 {
2344 buffer->getMaterial() = m->Mat; 2344 buffer->getMaterial() = m->Mat;
2345 SMesh tmpmesh; 2345 SMesh tmpmesh;
2346 tmpmesh.addMeshBuffer(buffer); 2346 tmpmesh.addMeshBuffer(buffer);
2347 SceneManager->getMeshManipulator()->setVertexColors(&tmpmesh,m->Mat.DiffuseColor); 2347 SceneManager->getMeshManipulator()->setVertexColors(&tmpmesh,m->Mat.DiffuseColor);
2348 if (m->Transparency != 1.0f) 2348 if (m->Transparency != 1.0f)
2349 SceneManager->getMeshManipulator()->setVertexColorAlpha(&tmpmesh,core::floor32(m->Transparency*255.0f)); 2349 SceneManager->getMeshManipulator()->setVertexColorAlpha(&tmpmesh,core::floor32(m->Transparency*255.0f));
2350 } 2350 }
2351 // add future bind reference for the material 2351 // add future bind reference for the material
2352 core::stringc meshbufferReference = geometryId+"/"+materialName; 2352 core::stringc meshbufferReference = geometryId+"/"+materialName;
2353 if (!MaterialsToBind.find(meshbufferReference)) 2353 if (!MaterialsToBind.find(meshbufferReference))
2354 { 2354 {
2355 MaterialsToBind[meshbufferReference] = MeshesToBind.size(); 2355 MaterialsToBind[meshbufferReference] = MeshesToBind.size();
2356 MeshesToBind.push_back(core::array<irr::scene::IMeshBuffer*>()); 2356 MeshesToBind.push_back(core::array<irr::scene::IMeshBuffer*>());
2357 } 2357 }
2358 MeshesToBind[MaterialsToBind[meshbufferReference]].push_back(buffer); 2358 MeshesToBind[MaterialsToBind[meshbufferReference]].push_back(buffer);
2359 2359
2360 // calculate normals if there is no slot for it 2360 // calculate normals if there is no slot for it
2361 2361
2362 if (!normalSlotCount) 2362 if (!normalSlotCount)
2363 SceneManager->getMeshManipulator()->recalculateNormals(buffer, true); 2363 SceneManager->getMeshManipulator()->recalculateNormals(buffer, true);
2364 2364
2365 // recalculate bounding box 2365 // recalculate bounding box
2366 buffer->recalculateBoundingBox(); 2366 buffer->recalculateBoundingBox();
2367 2367
2368 // add mesh buffer 2368 // add mesh buffer
2369 mesh->addMeshBuffer(buffer); 2369 mesh->addMeshBuffer(buffer);
2370 #ifdef COLLADA_READER_DEBUG 2370 #ifdef COLLADA_READER_DEBUG
2371 os::Printer::log("COLLADA added meshbuffer", core::stringc(buffer->getVertexCount())+" vertices, "+core::stringc(buffer->getIndexCount())+" indices.", ELL_DEBUG); 2371 os::Printer::log("COLLADA added meshbuffer", core::stringc(buffer->getVertexCount())+" vertices, "+core::stringc(buffer->getIndexCount())+" indices.", ELL_DEBUG);
2372 #endif 2372 #endif
2373 2373
2374 buffer->drop(); 2374 buffer->drop();
2375} 2375}
2376 2376
2377 2377
2378//! reads a <light> element and stores it as prefab 2378//! reads a <light> element and stores it as prefab
2379void CColladaFileLoader::readLightPrefab(io::IXMLReaderUTF8* reader) 2379void CColladaFileLoader::readLightPrefab(io::IXMLReaderUTF8* reader)
2380{ 2380{
2381 #ifdef COLLADA_READER_DEBUG 2381 #ifdef COLLADA_READER_DEBUG
2382 os::Printer::log("COLLADA reading light prefab", ELL_DEBUG); 2382 os::Printer::log("COLLADA reading light prefab", ELL_DEBUG);
2383 #endif 2383 #endif
2384 2384
2385 CLightPrefab* prefab = new CLightPrefab(readId(reader)); 2385 CLightPrefab* prefab = new CLightPrefab(readId(reader));
2386 2386
2387 if (!reader->isEmptyElement()) 2387 if (!reader->isEmptyElement())
2388 { 2388 {
2389 if (Version >= 10400) // start with 1.4 2389 if (Version >= 10400) // start with 1.4
2390 { 2390 {
2391 while(reader->read()) 2391 while(reader->read())
2392 { 2392 {
2393 if (reader->getNodeType() == io::EXN_ELEMENT) 2393 if (reader->getNodeType() == io::EXN_ELEMENT)
2394 { 2394 {
2395 if (pointSectionName == reader->getNodeName()) 2395 if (pointSectionName == reader->getNodeName())
2396 prefab->LightData.Type=video::ELT_POINT; 2396 prefab->LightData.Type=video::ELT_POINT;
2397 else 2397 else
2398 if (directionalSectionName == reader->getNodeName()) 2398 if (directionalSectionName == reader->getNodeName())
2399 prefab->LightData.Type=video::ELT_DIRECTIONAL; 2399 prefab->LightData.Type=video::ELT_DIRECTIONAL;
2400 else 2400 else
2401 if (spotSectionName == reader->getNodeName()) 2401 if (spotSectionName == reader->getNodeName())
2402 prefab->LightData.Type=video::ELT_SPOT; 2402 prefab->LightData.Type=video::ELT_SPOT;
2403 else 2403 else
2404 if (ambientSectionName == reader->getNodeName()) 2404 if (ambientSectionName == reader->getNodeName())
2405 prefab->LightData.Type=ELT_AMBIENT; 2405 prefab->LightData.Type=ELT_AMBIENT;
2406 else 2406 else
2407 if (colorNodeName == reader->getNodeName()) 2407 if (colorNodeName == reader->getNodeName())
2408 prefab->LightData.DiffuseColor=readColorNode(reader); 2408 prefab->LightData.DiffuseColor=readColorNode(reader);
2409 else 2409 else
2410 if (constantAttenuationNodeName == reader->getNodeName()) 2410 if (constantAttenuationNodeName == reader->getNodeName())
2411 readFloatsInsideElement(reader,&prefab->LightData.Attenuation.X,1); 2411 readFloatsInsideElement(reader,&prefab->LightData.Attenuation.X,1);
2412 else 2412 else
2413 if (linearAttenuationNodeName == reader->getNodeName()) 2413 if (linearAttenuationNodeName == reader->getNodeName())
2414 readFloatsInsideElement(reader,&prefab->LightData.Attenuation.Y,1); 2414 readFloatsInsideElement(reader,&prefab->LightData.Attenuation.Y,1);
2415 else 2415 else
2416 if (quadraticAttenuationNodeName == reader->getNodeName()) 2416 if (quadraticAttenuationNodeName == reader->getNodeName())
2417 readFloatsInsideElement(reader,&prefab->LightData.Attenuation.Z,1); 2417 readFloatsInsideElement(reader,&prefab->LightData.Attenuation.Z,1);
2418 else 2418 else
2419 if (falloffAngleNodeName == reader->getNodeName()) 2419 if (falloffAngleNodeName == reader->getNodeName())
2420 { 2420 {
2421 readFloatsInsideElement(reader,&prefab->LightData.OuterCone,1); 2421 readFloatsInsideElement(reader,&prefab->LightData.OuterCone,1);
2422 prefab->LightData.OuterCone *= core::DEGTORAD; 2422 prefab->LightData.OuterCone *= core::DEGTORAD;
2423 } 2423 }
2424 else 2424 else
2425 if (falloffExponentNodeName == reader->getNodeName()) 2425 if (falloffExponentNodeName == reader->getNodeName())
2426 readFloatsInsideElement(reader,&prefab->LightData.Falloff,1); 2426 readFloatsInsideElement(reader,&prefab->LightData.Falloff,1);
2427 } 2427 }
2428 else 2428 else
2429 if (reader->getNodeType() == io::EXN_ELEMENT_END) 2429 if (reader->getNodeType() == io::EXN_ELEMENT_END)
2430 { 2430 {
2431 if ((pointSectionName == reader->getNodeName()) || 2431 if ((pointSectionName == reader->getNodeName()) ||
2432 (directionalSectionName == reader->getNodeName()) || 2432 (directionalSectionName == reader->getNodeName()) ||
2433 (spotSectionName == reader->getNodeName()) || 2433 (spotSectionName == reader->getNodeName()) ||
2434 (ambientSectionName == reader->getNodeName())) 2434 (ambientSectionName == reader->getNodeName()))
2435 break; 2435 break;
2436 } 2436 }
2437 } 2437 }
2438 } 2438 }
2439 else 2439 else
2440 { 2440 {
2441 readColladaParameters(reader, lightPrefabName); 2441 readColladaParameters(reader, lightPrefabName);
2442 2442
2443 SColladaParam* p = getColladaParameter(ECPN_COLOR); 2443 SColladaParam* p = getColladaParameter(ECPN_COLOR);
2444 if (p && p->Type == ECPT_FLOAT3) 2444 if (p && p->Type == ECPT_FLOAT3)
2445 prefab->LightData.DiffuseColor.set(p->Floats[0], p->Floats[1], p->Floats[2]); 2445 prefab->LightData.DiffuseColor.set(p->Floats[0], p->Floats[1], p->Floats[2]);
2446 } 2446 }
2447 } 2447 }
2448 2448
2449 Prefabs.push_back(prefab); 2449 Prefabs.push_back(prefab);
2450} 2450}
2451 2451
2452 2452
2453//! returns a collada parameter or none if not found 2453//! returns a collada parameter or none if not found
2454SColladaParam* CColladaFileLoader::getColladaParameter(ECOLLADA_PARAM_NAME name) 2454SColladaParam* CColladaFileLoader::getColladaParameter(ECOLLADA_PARAM_NAME name)
2455{ 2455{
2456 for (u32 i=0; i<ColladaParameters.size(); ++i) 2456 for (u32 i=0; i<ColladaParameters.size(); ++i)
2457 if (ColladaParameters[i].Name == name) 2457 if (ColladaParameters[i].Name == name)
2458 return &ColladaParameters[i]; 2458 return &ColladaParameters[i];
2459 2459
2460 return 0; 2460 return 0;
2461} 2461}
2462 2462
2463//! returns a collada input or none if not found 2463//! returns a collada input or none if not found
2464SColladaInput* CColladaFileLoader::getColladaInput(ECOLLADA_INPUT_SEMANTIC input) 2464SColladaInput* CColladaFileLoader::getColladaInput(ECOLLADA_INPUT_SEMANTIC input)
2465{ 2465{
2466 for (u32 i=0; i<Inputs.size(); ++i) 2466 for (u32 i=0; i<Inputs.size(); ++i)
2467 if (Inputs[i].Semantic == input) 2467 if (Inputs[i].Semantic == input)
2468 return &Inputs[i]; 2468 return &Inputs[i];
2469 2469
2470 return 0; 2470 return 0;
2471} 2471}
2472 2472
2473 2473
2474//! reads a collada input tag and adds it to the input parameter 2474//! reads a collada input tag and adds it to the input parameter
2475void CColladaFileLoader::readColladaInput(io::IXMLReaderUTF8* reader, core::array<SColladaInput>& inputs) 2475void CColladaFileLoader::readColladaInput(io::IXMLReaderUTF8* reader, core::array<SColladaInput>& inputs)
2476{ 2476{
2477 // parse param 2477 // parse param
2478 SColladaInput p; 2478 SColladaInput p;
2479 2479
2480 // get type 2480 // get type
2481 core::stringc semanticName = reader->getAttributeValue("semantic"); 2481 core::stringc semanticName = reader->getAttributeValue("semantic");
2482 for (u32 i=0; inputSemanticNames[i]; ++i) 2482 for (u32 i=0; inputSemanticNames[i]; ++i)
2483 { 2483 {
2484 if (semanticName == inputSemanticNames[i]) 2484 if (semanticName == inputSemanticNames[i])
2485 { 2485 {
2486 p.Semantic = (ECOLLADA_INPUT_SEMANTIC)i; 2486 p.Semantic = (ECOLLADA_INPUT_SEMANTIC)i;
2487 break; 2487 break;
2488 } 2488 }
2489 } 2489 }
2490 2490
2491 // get source 2491 // get source
2492 p.Source = reader->getAttributeValue("source"); 2492 p.Source = reader->getAttributeValue("source");
2493 if (reader->getAttributeValue("offset")) // Collada 1.4+ 2493 if (reader->getAttributeValue("offset")) // Collada 1.4+
2494 p.Offset = (u32)reader->getAttributeValueAsInt("offset"); 2494 p.Offset = (u32)reader->getAttributeValueAsInt("offset");
2495 else // Collada 1.2/1.3 2495 else // Collada 1.2/1.3
2496 p.Offset = (u32)reader->getAttributeValueAsInt("idx"); 2496 p.Offset = (u32)reader->getAttributeValueAsInt("idx");
2497 p.Set = (u32)reader->getAttributeValueAsInt("set"); 2497 p.Set = (u32)reader->getAttributeValueAsInt("set");
2498 2498
2499 // add input 2499 // add input
2500 inputs.push_back(p); 2500 inputs.push_back(p);
2501} 2501}
2502 2502
2503//! parses all collada inputs inside an element and stores them in Inputs 2503//! parses all collada inputs inside an element and stores them in Inputs
2504void CColladaFileLoader::readColladaInputs(io::IXMLReaderUTF8* reader, const core::stringc& parentName) 2504void CColladaFileLoader::readColladaInputs(io::IXMLReaderUTF8* reader, const core::stringc& parentName)
2505{ 2505{
2506 Inputs.clear(); 2506 Inputs.clear();
2507 2507
2508 while(reader->read()) 2508 while(reader->read())
2509 { 2509 {
2510 if (reader->getNodeType() == io::EXN_ELEMENT && 2510 if (reader->getNodeType() == io::EXN_ELEMENT &&
2511 inputTagName == reader->getNodeName()) 2511 inputTagName == reader->getNodeName())
2512 { 2512 {
2513 readColladaInput(reader, Inputs); 2513 readColladaInput(reader, Inputs);
2514 } 2514 }
2515 else 2515 else
2516 if (reader->getNodeType() == io::EXN_ELEMENT_END) 2516 if (reader->getNodeType() == io::EXN_ELEMENT_END)
2517 { 2517 {
2518 if (parentName == reader->getNodeName()) 2518 if (parentName == reader->getNodeName())
2519 return; // end of parent reached 2519 return; // end of parent reached
2520 } 2520 }
2521 2521
2522 } // end while reader->read(); 2522 } // end while reader->read();
2523} 2523}
2524 2524
2525//! parses all collada parameters inside an element and stores them in ColladaParameters 2525//! parses all collada parameters inside an element and stores them in ColladaParameters
2526void CColladaFileLoader::readColladaParameters(io::IXMLReaderUTF8* reader, 2526void CColladaFileLoader::readColladaParameters(io::IXMLReaderUTF8* reader,
2527 const core::stringc& parentName) 2527 const core::stringc& parentName)
2528{ 2528{
2529 ColladaParameters.clear(); 2529 ColladaParameters.clear();
2530 2530
2531 const char* const paramNames[] = {"COLOR", "AMBIENT", "DIFFUSE", 2531 const char* const paramNames[] = {"COLOR", "AMBIENT", "DIFFUSE",
2532 "SPECULAR", "SHININESS", "YFOV", "ZNEAR", "ZFAR", 0}; 2532 "SPECULAR", "SHININESS", "YFOV", "ZNEAR", "ZFAR", 0};
2533 2533
2534 const char* const typeNames[] = {"float", "float2", "float3", 0}; 2534 const char* const typeNames[] = {"float", "float2", "float3", 0};
2535 2535
2536 while(reader->read()) 2536 while(reader->read())
2537 { 2537 {
2538 const char* nodeName = reader->getNodeName(); 2538 const char* nodeName = reader->getNodeName();
2539 if (reader->getNodeType() == io::EXN_ELEMENT && 2539 if (reader->getNodeType() == io::EXN_ELEMENT &&
2540 paramTagName == nodeName) 2540 paramTagName == nodeName)
2541 { 2541 {
2542 // parse param 2542 // parse param
2543 SColladaParam p; 2543 SColladaParam p;
2544 2544
2545 // get type 2545 // get type
2546 u32 i; 2546 u32 i;
2547 core::stringc typeName = reader->getAttributeValue("type"); 2547 core::stringc typeName = reader->getAttributeValue("type");
2548 for (i=0; typeNames[i]; ++i) 2548 for (i=0; typeNames[i]; ++i)
2549 if (typeName == typeNames[i]) 2549 if (typeName == typeNames[i])
2550 { 2550 {
2551 p.Type = (ECOLLADA_PARAM_TYPE)i; 2551 p.Type = (ECOLLADA_PARAM_TYPE)i;
2552 break; 2552 break;
2553 } 2553 }
2554 2554
2555 // get name 2555 // get name
2556 core::stringc nameName = reader->getAttributeValue("name"); 2556 core::stringc nameName = reader->getAttributeValue("name");
2557 for (i=0; typeNames[i]; ++i) 2557 for (i=0; typeNames[i]; ++i)
2558 if (nameName == paramNames[i]) 2558 if (nameName == paramNames[i])
2559 { 2559 {
2560 p.Name = (ECOLLADA_PARAM_NAME)i; 2560 p.Name = (ECOLLADA_PARAM_NAME)i;
2561 break; 2561 break;
2562 } 2562 }
2563 2563
2564 // read parameter data inside parameter tags 2564 // read parameter data inside parameter tags
2565 switch(p.Type) 2565 switch(p.Type)
2566 { 2566 {
2567 case ECPT_FLOAT: 2567 case ECPT_FLOAT:
2568 case ECPT_FLOAT2: 2568 case ECPT_FLOAT2:
2569 case ECPT_FLOAT3: 2569 case ECPT_FLOAT3:
2570 case ECPT_FLOAT4: 2570 case ECPT_FLOAT4:
2571 readFloatsInsideElement(reader, p.Floats, p.Type - ECPT_FLOAT + 1); 2571 readFloatsInsideElement(reader, p.Floats, p.Type - ECPT_FLOAT + 1);
2572 break; 2572 break;
2573 2573
2574 // TODO: other types of data (ints, bools or whatever) 2574 // TODO: other types of data (ints, bools or whatever)
2575 default: 2575 default:
2576 break; 2576 break;
2577 } 2577 }
2578 2578
2579 // add param 2579 // add param
2580 ColladaParameters.push_back(p); 2580 ColladaParameters.push_back(p);
2581 } 2581 }
2582 else 2582 else
2583 if (reader->getNodeType() == io::EXN_ELEMENT_END) 2583 if (reader->getNodeType() == io::EXN_ELEMENT_END)
2584 { 2584 {
2585 if (parentName == reader->getNodeName()) 2585 if (parentName == reader->getNodeName())
2586 return; // end of parent reached 2586 return; // end of parent reached
2587 } 2587 }
2588 2588
2589 } // end while reader->read(); 2589 } // end while reader->read();
2590} 2590}
2591 2591
2592 2592
2593//! parses a float from a char pointer and moves the pointer 2593//! parses a float from a char pointer and moves the pointer
2594//! to the end of the parsed float 2594//! to the end of the parsed float
2595inline f32 CColladaFileLoader::readFloat(const c8** p) 2595inline f32 CColladaFileLoader::readFloat(const c8** p)
2596{ 2596{
2597 f32 ftmp; 2597 f32 ftmp;
2598 *p = core::fast_atof_move(*p, ftmp); 2598 *p = core::fast_atof_move(*p, ftmp);
2599 return ftmp; 2599 return ftmp;
2600} 2600}
2601 2601
2602 2602
2603//! parses an int from a char pointer and moves the pointer to 2603//! parses an int from a char pointer and moves the pointer to
2604//! the end of the parsed float 2604//! the end of the parsed float
2605inline s32 CColladaFileLoader::readInt(const c8** p) 2605inline s32 CColladaFileLoader::readInt(const c8** p)
2606{ 2606{
2607 return (s32)readFloat(p); 2607 return (s32)readFloat(p);
2608} 2608}
2609 2609
2610 2610
2611//! places pointer to next begin of a token 2611//! places pointer to next begin of a token
2612void CColladaFileLoader::findNextNoneWhiteSpace(const c8** start) 2612void CColladaFileLoader::findNextNoneWhiteSpace(const c8** start)
2613{ 2613{
2614 const c8* p = *start; 2614 const c8* p = *start;
2615 2615
2616 while(*p && (*p==' ' || *p=='\n' || *p=='\r' || *p=='\t')) 2616 while(*p && (*p==' ' || *p=='\n' || *p=='\r' || *p=='\t'))
2617 ++p; 2617 ++p;
2618 2618
2619 // TODO: skip comments <!-- --> 2619 // TODO: skip comments <!-- -->
2620 2620
2621 *start = p; 2621 *start = p;
2622} 2622}
2623 2623
2624 2624
2625//! reads floats from inside of xml element until end of xml element 2625//! reads floats from inside of xml element until end of xml element
2626void CColladaFileLoader::readFloatsInsideElement(io::IXMLReaderUTF8* reader, f32* floats, u32 count) 2626void CColladaFileLoader::readFloatsInsideElement(io::IXMLReaderUTF8* reader, f32* floats, u32 count)
2627{ 2627{
2628 if (reader->isEmptyElement()) 2628 if (reader->isEmptyElement())
2629 return; 2629 return;
2630 2630
2631 while(reader->read()) 2631 while(reader->read())
2632 { 2632 {
2633 // TODO: check for comments inside the element 2633 // TODO: check for comments inside the element
2634 // and ignore them. 2634 // and ignore them.
2635 2635
2636 if (reader->getNodeType() == io::EXN_TEXT) 2636 if (reader->getNodeType() == io::EXN_TEXT)
2637 { 2637 {
2638 // parse float data 2638 // parse float data
2639 core::stringc data = reader->getNodeData(); 2639 core::stringc data = reader->getNodeData();
2640 data.trim(); 2640 data.trim();
2641 const c8* p = &data[0]; 2641 const c8* p = &data[0];
2642 2642
2643 for (u32 i=0; i<count; ++i) 2643 for (u32 i=0; i<count; ++i)
2644 { 2644 {
2645 findNextNoneWhiteSpace(&p); 2645 findNextNoneWhiteSpace(&p);
2646 if (*p) 2646 if (*p)
2647 floats[i] = readFloat(&p); 2647 floats[i] = readFloat(&p);
2648 else 2648 else
2649 floats[i] = 0.0f; 2649 floats[i] = 0.0f;
2650 } 2650 }
2651 } 2651 }
2652 else 2652 else
2653 if (reader->getNodeType() == io::EXN_ELEMENT_END) 2653 if (reader->getNodeType() == io::EXN_ELEMENT_END)
2654 break; // end parsing text 2654 break; // end parsing text
2655 } 2655 }
2656} 2656}
2657 2657
2658 2658
2659//! reads ints from inside of xml element until end of xml element 2659//! reads ints from inside of xml element until end of xml element
2660void CColladaFileLoader::readIntsInsideElement(io::IXMLReaderUTF8* reader, s32* ints, u32 count) 2660void CColladaFileLoader::readIntsInsideElement(io::IXMLReaderUTF8* reader, s32* ints, u32 count)
2661{ 2661{
2662 if (reader->isEmptyElement()) 2662 if (reader->isEmptyElement())
2663 return; 2663 return;
2664 2664
2665 while(reader->read()) 2665 while(reader->read())
2666 { 2666 {
2667 // TODO: check for comments inside the element 2667 // TODO: check for comments inside the element
2668 // and ignore them. 2668 // and ignore them.
2669 2669
2670 if (reader->getNodeType() == io::EXN_TEXT) 2670 if (reader->getNodeType() == io::EXN_TEXT)
2671 { 2671 {
2672 // parse float data 2672 // parse float data
2673 core::stringc data = reader->getNodeData(); 2673 core::stringc data = reader->getNodeData();
2674 data.trim(); 2674 data.trim();
2675 const c8* p = &data[0]; 2675 const c8* p = &data[0];
2676 2676
2677 for (u32 i=0; i<count; ++i) 2677 for (u32 i=0; i<count; ++i)
2678 { 2678 {
2679 findNextNoneWhiteSpace(&p); 2679 findNextNoneWhiteSpace(&p);
2680 if (*p) 2680 if (*p)
2681 ints[i] = readInt(&p); 2681 ints[i] = readInt(&p);
2682 else 2682 else
2683 ints[i] = 0; 2683 ints[i] = 0;
2684 } 2684 }
2685 } 2685 }
2686 else 2686 else
2687 if (reader->getNodeType() == io::EXN_ELEMENT_END) 2687 if (reader->getNodeType() == io::EXN_ELEMENT_END)
2688 break; // end parsing text 2688 break; // end parsing text
2689 } 2689 }
2690} 2690}
2691 2691
2692 2692
2693video::SColorf CColladaFileLoader::readColorNode(io::IXMLReaderUTF8* reader) 2693video::SColorf CColladaFileLoader::readColorNode(io::IXMLReaderUTF8* reader)
2694{ 2694{
2695 if (reader->getNodeType() == io::EXN_ELEMENT && 2695 if (reader->getNodeType() == io::EXN_ELEMENT &&
2696 colorNodeName == reader->getNodeName()) 2696 colorNodeName == reader->getNodeName())
2697 { 2697 {
2698 f32 color[4]; 2698 f32 color[4];
2699 readFloatsInsideElement(reader,color,4); 2699 readFloatsInsideElement(reader,color,4);
2700 return video::SColorf(color[0], color[1], color[2], color[3]); 2700 return video::SColorf(color[0], color[1], color[2], color[3]);
2701 } 2701 }
2702 2702
2703 return video::SColorf(); 2703 return video::SColorf();
2704} 2704}
2705 2705
2706 2706
2707f32 CColladaFileLoader::readFloatNode(io::IXMLReaderUTF8* reader) 2707f32 CColladaFileLoader::readFloatNode(io::IXMLReaderUTF8* reader)
2708{ 2708{
2709 #ifdef COLLADA_READER_DEBUG 2709 #ifdef COLLADA_READER_DEBUG
2710 os::Printer::log("COLLADA reading <float>", ELL_DEBUG); 2710 os::Printer::log("COLLADA reading <float>", ELL_DEBUG);
2711 #endif 2711 #endif
2712 2712
2713 f32 result = 0.0f; 2713 f32 result = 0.0f;
2714 if (reader->getNodeType() == io::EXN_ELEMENT && 2714 if (reader->getNodeType() == io::EXN_ELEMENT &&
2715 floatNodeName == reader->getNodeName()) 2715 floatNodeName == reader->getNodeName())
2716 { 2716 {
2717 readFloatsInsideElement(reader,&result,1); 2717 readFloatsInsideElement(reader,&result,1);
2718 } 2718 }
2719 2719
2720 return result; 2720 return result;
2721} 2721}
2722 2722
2723 2723
2724//! clears all loaded data 2724//! clears all loaded data
2725void CColladaFileLoader::clearData() 2725void CColladaFileLoader::clearData()
2726{ 2726{
2727 // delete all prefabs 2727 // delete all prefabs
2728 2728
2729 for (u32 i=0; i<Prefabs.size(); ++i) 2729 for (u32 i=0; i<Prefabs.size(); ++i)
2730 Prefabs[i]->drop(); 2730 Prefabs[i]->drop();
2731 2731
2732 Prefabs.clear(); 2732 Prefabs.clear();
2733 2733
2734 // clear all parameters 2734 // clear all parameters
2735 ColladaParameters.clear(); 2735 ColladaParameters.clear();
2736 2736
2737 // clear all materials 2737 // clear all materials
2738 Images.clear(); 2738 Images.clear();
2739 2739
2740 // clear all materials 2740 // clear all materials
2741 Textures.clear(); 2741 Textures.clear();
2742 2742
2743 // clear all materials 2743 // clear all materials
2744 Materials.clear(); 2744 Materials.clear();
2745 2745
2746 // clear all inputs 2746 // clear all inputs
2747 Inputs.clear(); 2747 Inputs.clear();
2748 2748
2749 // clear all effects 2749 // clear all effects
2750 for ( u32 i=0; i<Effects.size(); ++i ) 2750 for ( u32 i=0; i<Effects.size(); ++i )
2751 Effects[i].Parameters->drop(); 2751 Effects[i].Parameters->drop();
2752 Effects.clear(); 2752 Effects.clear();
2753 2753
2754 // clear all the materials to bind 2754 // clear all the materials to bind
2755 MaterialsToBind.clear(); 2755 MaterialsToBind.clear();
2756 MeshesToBind.clear(); 2756 MeshesToBind.clear();
2757} 2757}
2758 2758
2759 2759
2760//! changes the XML URI into an internal id 2760//! changes the XML URI into an internal id
2761void CColladaFileLoader::uriToId(core::stringc& str) 2761void CColladaFileLoader::uriToId(core::stringc& str)
2762{ 2762{
2763 // currently, we only remove the # from the begin if there 2763 // currently, we only remove the # from the begin if there
2764 // because we simply don't support referencing other files. 2764 // because we simply don't support referencing other files.
2765 if (!str.size()) 2765 if (!str.size())
2766 return; 2766 return;
2767 2767
2768 if (str[0] == '#') 2768 if (str[0] == '#')
2769 str.erase(0); 2769 str.erase(0);
2770} 2770}
2771 2771
2772 2772
2773//! read Collada Id, uses id or name if id is missing 2773//! read Collada Id, uses id or name if id is missing
2774core::stringc CColladaFileLoader::readId(io::IXMLReaderUTF8* reader) 2774core::stringc CColladaFileLoader::readId(io::IXMLReaderUTF8* reader)
2775{ 2775{
2776 core::stringc id = reader->getAttributeValue("id"); 2776 core::stringc id = reader->getAttributeValue("id");
2777 if (id.size()==0) 2777 if (id.size()==0)
2778 id = reader->getAttributeValue("name"); 2778 id = reader->getAttributeValue("name");
2779 return id; 2779 return id;
2780} 2780}
2781 2781
2782 2782
2783//! create an Irrlicht texture from the reference 2783//! create an Irrlicht texture from the reference
2784video::ITexture* CColladaFileLoader::getTextureFromImage(core::stringc uri, SColladaEffect * effect) 2784video::ITexture* CColladaFileLoader::getTextureFromImage(core::stringc uri, SColladaEffect * effect)
2785{ 2785{
2786 #ifdef COLLADA_READER_DEBUG 2786 #ifdef COLLADA_READER_DEBUG
2787 os::Printer::log("COLLADA searching texture", uri, ELL_DEBUG); 2787 os::Printer::log("COLLADA searching texture", uri, ELL_DEBUG);
2788 #endif 2788 #endif
2789 video::IVideoDriver* driver = SceneManager->getVideoDriver(); 2789 video::IVideoDriver* driver = SceneManager->getVideoDriver();
2790 for (;;) 2790 for (;;)
2791 { 2791 {
2792 uriToId(uri); 2792 uriToId(uri);
2793 for (u32 i=0; i<Images.size(); ++i) 2793 for (u32 i=0; i<Images.size(); ++i)
2794 { 2794 {
2795 if (uri == Images[i].Id) 2795 if (uri == Images[i].Id)
2796 { 2796 {
2797 if (Images[i].Source.size() && Images[i].SourceIsFilename) 2797 if (Images[i].Source.size() && Images[i].SourceIsFilename)
2798 { 2798 {
2799 if (FileSystem->existFile(Images[i].Source)) 2799 if (FileSystem->existFile(Images[i].Source))
2800 return driver->getTexture(Images[i].Source); 2800 return driver->getTexture(Images[i].Source);
2801 return driver->getTexture((FileSystem->getFileDir(CurrentlyLoadingMesh)+"/"+Images[i].Source)); 2801 return driver->getTexture((FileSystem->getFileDir(CurrentlyLoadingMesh)+"/"+Images[i].Source));
2802 } 2802 }
2803 else 2803 else
2804 if (Images[i].Source.size()) 2804 if (Images[i].Source.size())
2805 { 2805 {
2806 //const u32 size = Images[i].Dimension.getArea(); 2806 //const u32 size = Images[i].Dimension.getArea();
2807 const u32 size = Images[i].Dimension.Width * Images[i].Dimension.Height;; 2807 const u32 size = Images[i].Dimension.Width * Images[i].Dimension.Height;;
2808 u32* data = new u32[size]; // we assume RGBA 2808 u32* data = new u32[size]; // we assume RGBA
2809 u32* ptrdest = data; 2809 u32* ptrdest = data;
2810 const c8* ptrsrc = Images[i].Source.c_str(); 2810 const c8* ptrsrc = Images[i].Source.c_str();
2811 for (u32 j=0; j<size; ++j) 2811 for (u32 j=0; j<size; ++j)
2812 { 2812 {
2813 sscanf(ptrsrc, "%x", ptrdest); 2813 sscanf(ptrsrc, "%x", ptrdest);
2814 ++ptrdest; 2814 ++ptrdest;
2815 ptrsrc += 4; 2815 ptrsrc += 4;
2816 } 2816 }
2817 video::IImage* img = driver->createImageFromData(video::ECF_A8R8G8B8, Images[i].Dimension, data, true, true); 2817 video::IImage* img = driver->createImageFromData(video::ECF_A8R8G8B8, Images[i].Dimension, data, true, true);
2818 video::ITexture* tex = driver->addTexture((CurrentlyLoadingMesh+"#"+Images[i].Id).c_str(), img); 2818 video::ITexture* tex = driver->addTexture((CurrentlyLoadingMesh+"#"+Images[i].Id).c_str(), img);
2819 img->drop(); 2819 img->drop();
2820 return tex; 2820 return tex;
2821 } 2821 }
2822 break; 2822 break;
2823 } 2823 }
2824 } 2824 }
2825 if (effect && effect->Parameters->getAttributeType(uri.c_str())==io::EAT_STRING) 2825 if (effect && effect->Parameters->getAttributeType(uri.c_str())==io::EAT_STRING)
2826 { 2826 {
2827 uri = effect->Parameters->getAttributeAsString(uri.c_str()); 2827 uri = effect->Parameters->getAttributeAsString(uri.c_str());
2828#ifdef COLLADA_READER_DEBUG 2828#ifdef COLLADA_READER_DEBUG
2829 os::Printer::log("COLLADA now searching texture", uri.c_str(), ELL_DEBUG); 2829 os::Printer::log("COLLADA now searching texture", uri.c_str(), ELL_DEBUG);
2830#endif 2830#endif
2831 } 2831 }
2832 else 2832 else
2833 break; 2833 break;
2834 } 2834 }
2835 return 0; 2835 return 0;
2836} 2836}
2837 2837
2838 2838
2839//! read a parameter and value 2839//! read a parameter and value
2840void CColladaFileLoader::readParameter(io::IXMLReaderUTF8* reader, io::IAttributes* parameters) 2840void CColladaFileLoader::readParameter(io::IXMLReaderUTF8* reader, io::IAttributes* parameters)
2841{ 2841{
2842 #ifdef COLLADA_READER_DEBUG 2842 #ifdef COLLADA_READER_DEBUG
2843 os::Printer::log("COLLADA reading parameter", ELL_DEBUG); 2843 os::Printer::log("COLLADA reading parameter", ELL_DEBUG);
2844 #endif 2844 #endif
2845 2845
2846 if ( !parameters ) 2846 if ( !parameters )
2847 return; 2847 return;
2848 2848
2849 const core::stringc name = reader->getAttributeValue("sid"); 2849 const core::stringc name = reader->getAttributeValue("sid");
2850 if (!reader->isEmptyElement()) 2850 if (!reader->isEmptyElement())
2851 { 2851 {
2852 while(reader->read()) 2852 while(reader->read())
2853 { 2853 {
2854 if (reader->getNodeType() == io::EXN_ELEMENT) 2854 if (reader->getNodeType() == io::EXN_ELEMENT)
2855 { 2855 {
2856 if (floatNodeName == reader->getNodeName()) 2856 if (floatNodeName == reader->getNodeName())
2857 { 2857 {
2858 const f32 f = readFloatNode(reader); 2858 const f32 f = readFloatNode(reader);
2859 parameters->addFloat(name.c_str(), f); 2859 parameters->addFloat(name.c_str(), f);
2860 } 2860 }
2861 else 2861 else
2862 if (float2NodeName == reader->getNodeName()) 2862 if (float2NodeName == reader->getNodeName())
2863 { 2863 {
2864 f32 f[2]; 2864 f32 f[2];
2865 readFloatsInsideElement(reader, f, 2); 2865 readFloatsInsideElement(reader, f, 2);
2866// Parameters.addVector2d(name.c_str(), core::vector2df(f[0],f[1])); 2866// Parameters.addVector2d(name.c_str(), core::vector2df(f[0],f[1]));
2867 } 2867 }
2868 else 2868 else
2869 if (float3NodeName == reader->getNodeName()) 2869 if (float3NodeName == reader->getNodeName())
2870 { 2870 {
2871 f32 f[3]; 2871 f32 f[3];
2872 readFloatsInsideElement(reader, f, 3); 2872 readFloatsInsideElement(reader, f, 3);
2873 parameters->addVector3d(name.c_str(), core::vector3df(f[0],f[1],f[2])); 2873 parameters->addVector3d(name.c_str(), core::vector3df(f[0],f[1],f[2]));
2874 } 2874 }
2875 else 2875 else
2876 if ((initFromName == reader->getNodeName()) || 2876 if ((initFromName == reader->getNodeName()) ||
2877 (sourceSectionName == reader->getNodeName())) 2877 (sourceSectionName == reader->getNodeName()))
2878 { 2878 {
2879 reader->read(); 2879 reader->read();
2880 parameters->addString(name.c_str(), reader->getNodeData()); 2880 parameters->addString(name.c_str(), reader->getNodeData());
2881 } 2881 }
2882 else 2882 else
2883 if (wrapsName == reader->getNodeName()) 2883 if (wrapsName == reader->getNodeName())
2884 { 2884 {
2885 reader->read(); 2885 reader->read();
2886 const core::stringc val = reader->getNodeData(); 2886 const core::stringc val = reader->getNodeData();
2887 if (val == "WRAP") 2887 if (val == "WRAP")
2888 parameters->addInt(wrapsName.c_str(), (int)video::ETC_REPEAT); 2888 parameters->addInt(wrapsName.c_str(), (int)video::ETC_REPEAT);
2889 else if ( val== "MIRROR") 2889 else if ( val== "MIRROR")
2890 parameters->addInt(wrapsName.c_str(), (int)video::ETC_MIRROR); 2890 parameters->addInt(wrapsName.c_str(), (int)video::ETC_MIRROR);
2891 else if ( val== "CLAMP") 2891 else if ( val== "CLAMP")
2892 parameters->addInt(wrapsName.c_str(), (int)video::ETC_CLAMP_TO_EDGE); 2892 parameters->addInt(wrapsName.c_str(), (int)video::ETC_CLAMP_TO_EDGE);
2893 else if ( val== "BORDER") 2893 else if ( val== "BORDER")
2894 parameters->addInt(wrapsName.c_str(), (int)video::ETC_CLAMP_TO_BORDER); 2894 parameters->addInt(wrapsName.c_str(), (int)video::ETC_CLAMP_TO_BORDER);
2895 else if ( val== "NONE") 2895 else if ( val== "NONE")
2896 parameters->addInt(wrapsName.c_str(), (int)video::ETC_CLAMP_TO_BORDER); 2896 parameters->addInt(wrapsName.c_str(), (int)video::ETC_CLAMP_TO_BORDER);
2897 } 2897 }
2898 else 2898 else
2899 if (wraptName == reader->getNodeName()) 2899 if (wraptName == reader->getNodeName())
2900 { 2900 {
2901 reader->read(); 2901 reader->read();
2902 const core::stringc val = reader->getNodeData(); 2902 const core::stringc val = reader->getNodeData();
2903 if (val == "WRAP") 2903 if (val == "WRAP")
2904 parameters->addInt(wraptName.c_str(), (int)video::ETC_REPEAT); 2904 parameters->addInt(wraptName.c_str(), (int)video::ETC_REPEAT);
2905 else if ( val== "MIRROR") 2905 else if ( val== "MIRROR")
2906 parameters->addInt(wraptName.c_str(), (int)video::ETC_MIRROR); 2906 parameters->addInt(wraptName.c_str(), (int)video::ETC_MIRROR);
2907 else if ( val== "CLAMP") 2907 else if ( val== "CLAMP")
2908 parameters->addInt(wraptName.c_str(), (int)video::ETC_CLAMP_TO_EDGE); 2908 parameters->addInt(wraptName.c_str(), (int)video::ETC_CLAMP_TO_EDGE);
2909 else if ( val== "BORDER") 2909 else if ( val== "BORDER")
2910 parameters->addInt(wraptName.c_str(), (int)video::ETC_CLAMP_TO_BORDER); 2910 parameters->addInt(wraptName.c_str(), (int)video::ETC_CLAMP_TO_BORDER);
2911 else if ( val== "NONE") 2911 else if ( val== "NONE")
2912 parameters->addInt(wraptName.c_str(), (int)video::ETC_CLAMP_TO_BORDER); 2912 parameters->addInt(wraptName.c_str(), (int)video::ETC_CLAMP_TO_BORDER);
2913 } 2913 }
2914 else 2914 else
2915 if (minfilterName == reader->getNodeName()) 2915 if (minfilterName == reader->getNodeName())
2916 { 2916 {
2917 reader->read(); 2917 reader->read();
2918 const core::stringc val = reader->getNodeData(); 2918 const core::stringc val = reader->getNodeData();
2919 if (val == "LINEAR_MIPMAP_LINEAR") 2919 if (val == "LINEAR_MIPMAP_LINEAR")
2920 parameters->addBool("trilinear", true); 2920 parameters->addBool("trilinear", true);
2921 else 2921 else
2922 if (val == "LINEAR_MIPMAP_NEAREST") 2922 if (val == "LINEAR_MIPMAP_NEAREST")
2923 parameters->addBool("bilinear", true); 2923 parameters->addBool("bilinear", true);
2924 } 2924 }
2925 else 2925 else
2926 if (magfilterName == reader->getNodeName()) 2926 if (magfilterName == reader->getNodeName())
2927 { 2927 {
2928 reader->read(); 2928 reader->read();
2929 const core::stringc val = reader->getNodeData(); 2929 const core::stringc val = reader->getNodeData();
2930 if (val != "LINEAR") 2930 if (val != "LINEAR")
2931 { 2931 {
2932 parameters->addBool("bilinear", false); 2932 parameters->addBool("bilinear", false);
2933 parameters->addBool("trilinear", false); 2933 parameters->addBool("trilinear", false);
2934 } 2934 }
2935 } 2935 }
2936 else 2936 else
2937 if (mipfilterName == reader->getNodeName()) 2937 if (mipfilterName == reader->getNodeName())
2938 { 2938 {
2939 parameters->addBool("anisotropic", true); 2939 parameters->addBool("anisotropic", true);
2940 } 2940 }
2941 } 2941 }
2942 else 2942 else
2943 if(reader->getNodeType() == io::EXN_ELEMENT_END) 2943 if(reader->getNodeType() == io::EXN_ELEMENT_END)
2944 { 2944 {
2945 if (newParamName == reader->getNodeName()) 2945 if (newParamName == reader->getNodeName())
2946 break; 2946 break;
2947 } 2947 }
2948 } 2948 }
2949 } 2949 }
2950} 2950}
2951 2951
2952 2952
2953} // end namespace scene 2953} // end namespace scene
2954} // end namespace irr 2954} // end namespace irr
2955 2955
2956#endif // _IRR_COMPILE_WITH_COLLADA_LOADER_ 2956#endif // _IRR_COMPILE_WITH_COLLADA_LOADER_
2957 2957