aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/libraries/irrlicht-1.8/source/Irrlicht/CColladaMeshWriter.cpp
diff options
context:
space:
mode:
authorDavid Walter Seikel2013-01-13 18:54:10 +1000
committerDavid Walter Seikel2013-01-13 18:54:10 +1000
commit959831f4ef5a3e797f576c3de08cd65032c997ad (patch)
treee7351908be5995f0b325b2ebeaa02d5a34b82583 /libraries/irrlicht-1.8/source/Irrlicht/CColladaMeshWriter.cpp
parentAdd info about changes to Irrlicht. (diff)
downloadSledjHamr-959831f4ef5a3e797f576c3de08cd65032c997ad.zip
SledjHamr-959831f4ef5a3e797f576c3de08cd65032c997ad.tar.gz
SledjHamr-959831f4ef5a3e797f576c3de08cd65032c997ad.tar.bz2
SledjHamr-959831f4ef5a3e797f576c3de08cd65032c997ad.tar.xz
Remove damned ancient DOS line endings from Irrlicht. Hopefully I did not go overboard.
Diffstat (limited to '')
-rw-r--r--libraries/irrlicht-1.8/source/Irrlicht/CColladaMeshWriter.cpp4490
1 files changed, 2245 insertions, 2245 deletions
diff --git a/libraries/irrlicht-1.8/source/Irrlicht/CColladaMeshWriter.cpp b/libraries/irrlicht-1.8/source/Irrlicht/CColladaMeshWriter.cpp
index e5b6df5..860f0d3 100644
--- a/libraries/irrlicht-1.8/source/Irrlicht/CColladaMeshWriter.cpp
+++ b/libraries/irrlicht-1.8/source/Irrlicht/CColladaMeshWriter.cpp
@@ -1,2245 +1,2245 @@
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// TODO: second UV-coordinates currently ignored in textures 5// TODO: second UV-coordinates currently ignored in textures
6 6
7#include "IrrCompileConfig.h" 7#include "IrrCompileConfig.h"
8 8
9#ifdef _IRR_COMPILE_WITH_COLLADA_WRITER_ 9#ifdef _IRR_COMPILE_WITH_COLLADA_WRITER_
10 10
11#include "CColladaMeshWriter.h" 11#include "CColladaMeshWriter.h"
12#include "os.h" 12#include "os.h"
13#include "IFileSystem.h" 13#include "IFileSystem.h"
14#include "IWriteFile.h" 14#include "IWriteFile.h"
15#include "IXMLWriter.h" 15#include "IXMLWriter.h"
16#include "IMesh.h" 16#include "IMesh.h"
17#include "IAttributes.h" 17#include "IAttributes.h"
18#include "IAnimatedMeshSceneNode.h" 18#include "IAnimatedMeshSceneNode.h"
19#include "IMeshSceneNode.h" 19#include "IMeshSceneNode.h"
20#include "ITerrainSceneNode.h" 20#include "ITerrainSceneNode.h"
21#include "ILightSceneNode.h" 21#include "ILightSceneNode.h"
22#include "ICameraSceneNode.h" 22#include "ICameraSceneNode.h"
23#include "ISceneManager.h" 23#include "ISceneManager.h"
24 24
25namespace irr 25namespace irr
26{ 26{
27namespace scene 27namespace scene
28{ 28{
29 29
30//! Which lighting model should be used in the technique (FX) section when exporting effects (materials) 30//! Which lighting model should be used in the technique (FX) section when exporting effects (materials)
31E_COLLADA_TECHNIQUE_FX CColladaMeshWriterProperties::getTechniqueFx(const video::SMaterial& material) const 31E_COLLADA_TECHNIQUE_FX CColladaMeshWriterProperties::getTechniqueFx(const video::SMaterial& material) const
32{ 32{
33 return ECTF_BLINN; 33 return ECTF_BLINN;
34} 34}
35 35
36//! Which texture index should be used when writing the texture of the given sampler color. 36//! Which texture index should be used when writing the texture of the given sampler color.
37s32 CColladaMeshWriterProperties::getTextureIdx(const video::SMaterial & material, E_COLLADA_COLOR_SAMPLER cs) const 37s32 CColladaMeshWriterProperties::getTextureIdx(const video::SMaterial & material, E_COLLADA_COLOR_SAMPLER cs) const
38{ 38{
39 // So far we just export in a way which is similar to how we import colladas. 39 // So far we just export in a way which is similar to how we import colladas.
40 // There might be better ways to do this, but I suppose it depends a lot for which target 40 // There might be better ways to do this, but I suppose it depends a lot for which target
41 // application we export, so in most cases it will have to be done in user-code anyway. 41 // application we export, so in most cases it will have to be done in user-code anyway.
42 switch ( cs ) 42 switch ( cs )
43 { 43 {
44 case ECCS_DIFFUSE: 44 case ECCS_DIFFUSE:
45 return 2; 45 return 2;
46 case ECCS_AMBIENT: 46 case ECCS_AMBIENT:
47 return 1; 47 return 1;
48 case ECCS_EMISSIVE: 48 case ECCS_EMISSIVE:
49 return 0; 49 return 0;
50 case ECCS_SPECULAR: 50 case ECCS_SPECULAR:
51 return 3; 51 return 3;
52 case ECCS_TRANSPARENT: 52 case ECCS_TRANSPARENT:
53 return -1; 53 return -1;
54 case ECCS_REFLECTIVE: 54 case ECCS_REFLECTIVE:
55 return -1; 55 return -1;
56 }; 56 };
57 return -1; 57 return -1;
58} 58}
59 59
60E_COLLADA_IRR_COLOR CColladaMeshWriterProperties::getColorMapping(const video::SMaterial & material, E_COLLADA_COLOR_SAMPLER cs) const 60E_COLLADA_IRR_COLOR CColladaMeshWriterProperties::getColorMapping(const video::SMaterial & material, E_COLLADA_COLOR_SAMPLER cs) const
61{ 61{
62 switch ( cs ) 62 switch ( cs )
63 { 63 {
64 case ECCS_DIFFUSE: 64 case ECCS_DIFFUSE:
65 return ECIC_DIFFUSE; 65 return ECIC_DIFFUSE;
66 case ECCS_AMBIENT: 66 case ECCS_AMBIENT:
67 return ECIC_AMBIENT; 67 return ECIC_AMBIENT;
68 case ECCS_EMISSIVE: 68 case ECCS_EMISSIVE:
69 return ECIC_EMISSIVE; 69 return ECIC_EMISSIVE;
70 case ECCS_SPECULAR: 70 case ECCS_SPECULAR:
71 return ECIC_SPECULAR; 71 return ECIC_SPECULAR;
72 case ECCS_TRANSPARENT: 72 case ECCS_TRANSPARENT:
73 return ECIC_NONE; 73 return ECIC_NONE;
74 case ECCS_REFLECTIVE: 74 case ECCS_REFLECTIVE:
75 return ECIC_CUSTOM; 75 return ECIC_CUSTOM;
76 }; 76 };
77 77
78 return ECIC_NONE; 78 return ECIC_NONE;
79} 79}
80 80
81//! Return custom colors for certain color types requested by collada. 81//! Return custom colors for certain color types requested by collada.
82video::SColor CColladaMeshWriterProperties::getCustomColor(const video::SMaterial & material, E_COLLADA_COLOR_SAMPLER cs) const 82video::SColor CColladaMeshWriterProperties::getCustomColor(const video::SMaterial & material, E_COLLADA_COLOR_SAMPLER cs) const
83{ 83{
84 return video::SColor(255, 0, 0, 0); 84 return video::SColor(255, 0, 0, 0);
85} 85}
86 86
87 87
88//! Return the settings for transparence 88//! Return the settings for transparence
89E_COLLADA_TRANSPARENT_FX CColladaMeshWriterProperties::getTransparentFx(const video::SMaterial& material) const 89E_COLLADA_TRANSPARENT_FX CColladaMeshWriterProperties::getTransparentFx(const video::SMaterial& material) const
90{ 90{
91 // TODO: figure out best default mapping 91 // TODO: figure out best default mapping
92 return ECOF_A_ONE; 92 return ECOF_A_ONE;
93} 93}
94 94
95//! Transparency value for the material. 95//! Transparency value for the material.
96f32 CColladaMeshWriterProperties::getTransparency(const video::SMaterial& material) const 96f32 CColladaMeshWriterProperties::getTransparency(const video::SMaterial& material) const
97{ 97{
98 // TODO: figure out best default mapping 98 // TODO: figure out best default mapping
99 return -1.f; 99 return -1.f;
100} 100}
101 101
102//! Reflectivity value for that material 102//! Reflectivity value for that material
103f32 CColladaMeshWriterProperties::getReflectivity(const video::SMaterial& material) const 103f32 CColladaMeshWriterProperties::getReflectivity(const video::SMaterial& material) const
104{ 104{
105 // TODO: figure out best default mapping 105 // TODO: figure out best default mapping
106 return 0.f; 106 return 0.f;
107} 107}
108 108
109//! Return index of refraction for that material 109//! Return index of refraction for that material
110f32 CColladaMeshWriterProperties::getIndexOfRefraction(const video::SMaterial& material) const 110f32 CColladaMeshWriterProperties::getIndexOfRefraction(const video::SMaterial& material) const
111{ 111{
112 return -1.f; 112 return -1.f;
113} 113}
114 114
115bool CColladaMeshWriterProperties::isExportable(const irr::scene::ISceneNode * node) const 115bool CColladaMeshWriterProperties::isExportable(const irr::scene::ISceneNode * node) const
116{ 116{
117 return node && node->isVisible(); 117 return node && node->isVisible();
118} 118}
119 119
120IMesh* CColladaMeshWriterProperties::getMesh(irr::scene::ISceneNode * node) 120IMesh* CColladaMeshWriterProperties::getMesh(irr::scene::ISceneNode * node)
121{ 121{
122 if ( !node ) 122 if ( !node )
123 return 0; 123 return 0;
124 if ( node->getType() == ESNT_ANIMATED_MESH ) 124 if ( node->getType() == ESNT_ANIMATED_MESH )
125 return static_cast<IAnimatedMeshSceneNode*>(node)->getMesh()->getMesh(0); 125 return static_cast<IAnimatedMeshSceneNode*>(node)->getMesh()->getMesh(0);
126 // TODO: we need some ISceneNode::hasType() function to get rid of those checks 126 // TODO: we need some ISceneNode::hasType() function to get rid of those checks
127 if ( node->getType() == ESNT_MESH 127 if ( node->getType() == ESNT_MESH
128 || node->getType() == ESNT_CUBE 128 || node->getType() == ESNT_CUBE
129 || node->getType() == ESNT_SPHERE 129 || node->getType() == ESNT_SPHERE
130 || node->getType() == ESNT_WATER_SURFACE 130 || node->getType() == ESNT_WATER_SURFACE
131 || node->getType() == ESNT_Q3SHADER_SCENE_NODE 131 || node->getType() == ESNT_Q3SHADER_SCENE_NODE
132 ) 132 )
133 return static_cast<IMeshSceneNode*>(node)->getMesh(); 133 return static_cast<IMeshSceneNode*>(node)->getMesh();
134 if ( node->getType() == ESNT_TERRAIN ) 134 if ( node->getType() == ESNT_TERRAIN )
135 return static_cast<ITerrainSceneNode*>(node)->getMesh(); 135 return static_cast<ITerrainSceneNode*>(node)->getMesh();
136 return 0; 136 return 0;
137} 137}
138 138
139// Check if the node has it's own material overwriting the mesh-materials 139// Check if the node has it's own material overwriting the mesh-materials
140bool CColladaMeshWriterProperties::useNodeMaterial(const scene::ISceneNode* node) const 140bool CColladaMeshWriterProperties::useNodeMaterial(const scene::ISceneNode* node) const
141{ 141{
142 if ( !node ) 142 if ( !node )
143 return false; 143 return false;
144 144
145 // TODO: we need some ISceneNode::hasType() function to get rid of those checks 145 // TODO: we need some ISceneNode::hasType() function to get rid of those checks
146 bool useMeshMaterial = ( (node->getType() == ESNT_MESH || 146 bool useMeshMaterial = ( (node->getType() == ESNT_MESH ||
147 node->getType() == ESNT_CUBE || 147 node->getType() == ESNT_CUBE ||
148 node->getType() == ESNT_SPHERE || 148 node->getType() == ESNT_SPHERE ||
149 node->getType() == ESNT_WATER_SURFACE || 149 node->getType() == ESNT_WATER_SURFACE ||
150 node->getType() == ESNT_Q3SHADER_SCENE_NODE) 150 node->getType() == ESNT_Q3SHADER_SCENE_NODE)
151 && static_cast<const IMeshSceneNode*>(node)->isReadOnlyMaterials()) 151 && static_cast<const IMeshSceneNode*>(node)->isReadOnlyMaterials())
152 152
153 || (node->getType() == ESNT_ANIMATED_MESH 153 || (node->getType() == ESNT_ANIMATED_MESH
154 && static_cast<const IAnimatedMeshSceneNode*>(node)->isReadOnlyMaterials() ); 154 && static_cast<const IAnimatedMeshSceneNode*>(node)->isReadOnlyMaterials() );
155 155
156 return !useMeshMaterial; 156 return !useMeshMaterial;
157} 157}
158 158
159 159
160 160
161CColladaMeshWriterNames::CColladaMeshWriterNames(IColladaMeshWriter * writer) 161CColladaMeshWriterNames::CColladaMeshWriterNames(IColladaMeshWriter * writer)
162 : ColladaMeshWriter(writer) 162 : ColladaMeshWriter(writer)
163{ 163{
164} 164}
165 165
166irr::core::stringw CColladaMeshWriterNames::nameForMesh(const scene::IMesh* mesh, int instance) 166irr::core::stringw CColladaMeshWriterNames::nameForMesh(const scene::IMesh* mesh, int instance)
167{ 167{
168 irr::core::stringw name(L"mesh"); 168 irr::core::stringw name(L"mesh");
169 name += nameForPtr(mesh); 169 name += nameForPtr(mesh);
170 if ( instance > 0 ) 170 if ( instance > 0 )
171 { 171 {
172 name += L"i"; 172 name += L"i";
173 name += irr::core::stringw(instance); 173 name += irr::core::stringw(instance);
174 } 174 }
175 return ColladaMeshWriter->toNCName(name); 175 return ColladaMeshWriter->toNCName(name);
176} 176}
177 177
178irr::core::stringw CColladaMeshWriterNames::nameForNode(const scene::ISceneNode* node) 178irr::core::stringw CColladaMeshWriterNames::nameForNode(const scene::ISceneNode* node)
179{ 179{
180 irr::core::stringw name; 180 irr::core::stringw name;
181 // Prefix, because xs::ID can't start with a number, also nicer name 181 // Prefix, because xs::ID can't start with a number, also nicer name
182 if ( node && node->getType() == ESNT_LIGHT ) 182 if ( node && node->getType() == ESNT_LIGHT )
183 name = L"light"; 183 name = L"light";
184 else 184 else
185 name = L"node"; 185 name = L"node";
186 name += nameForPtr(node); 186 name += nameForPtr(node);
187 if ( node ) 187 if ( node )
188 { 188 {
189 name += irr::core::stringw(node->getName()); 189 name += irr::core::stringw(node->getName());
190 } 190 }
191 return ColladaMeshWriter->toNCName(name); 191 return ColladaMeshWriter->toNCName(name);
192} 192}
193 193
194irr::core::stringw CColladaMeshWriterNames::nameForMaterial(const video::SMaterial & material, int materialId, const scene::IMesh* mesh, const scene::ISceneNode* node) 194irr::core::stringw CColladaMeshWriterNames::nameForMaterial(const video::SMaterial & material, int materialId, const scene::IMesh* mesh, const scene::ISceneNode* node)
195{ 195{
196 core::stringw strMat(L"mat"); 196 core::stringw strMat(L"mat");
197 197
198 bool nodeMaterial = ColladaMeshWriter->getProperties()->useNodeMaterial(node); 198 bool nodeMaterial = ColladaMeshWriter->getProperties()->useNodeMaterial(node);
199 if ( nodeMaterial ) 199 if ( nodeMaterial )
200 { 200 {
201 strMat += L"node"; 201 strMat += L"node";
202 strMat += nameForPtr(node); 202 strMat += nameForPtr(node);
203 strMat += irr::core::stringw(node->getName()); 203 strMat += irr::core::stringw(node->getName());
204 } 204 }
205 strMat += L"mesh"; 205 strMat += L"mesh";
206 strMat += nameForPtr(mesh); 206 strMat += nameForPtr(mesh);
207 strMat += materialId; 207 strMat += materialId;
208 return ColladaMeshWriter->toNCName(strMat); 208 return ColladaMeshWriter->toNCName(strMat);
209} 209}
210 210
211irr::core::stringw CColladaMeshWriterNames::nameForPtr(const void* ptr) const 211irr::core::stringw CColladaMeshWriterNames::nameForPtr(const void* ptr) const
212{ 212{
213 wchar_t buf[32]; 213 wchar_t buf[32];
214 swprintf(buf, 32, L"%p", ptr); 214 swprintf(buf, 32, L"%p", ptr);
215 return irr::core::stringw(buf); 215 return irr::core::stringw(buf);
216} 216}
217 217
218 218
219 219
220CColladaMeshWriter::CColladaMeshWriter( ISceneManager * smgr, video::IVideoDriver* driver, 220CColladaMeshWriter::CColladaMeshWriter( ISceneManager * smgr, video::IVideoDriver* driver,
221 io::IFileSystem* fs) 221 io::IFileSystem* fs)
222 : FileSystem(fs), VideoDriver(driver), Writer(0) 222 : FileSystem(fs), VideoDriver(driver), Writer(0)
223{ 223{
224 224
225 #ifdef _DEBUG 225 #ifdef _DEBUG
226 setDebugName("CColladaMeshWriter"); 226 setDebugName("CColladaMeshWriter");
227 #endif 227 #endif
228 228
229 if (VideoDriver) 229 if (VideoDriver)
230 VideoDriver->grab(); 230 VideoDriver->grab();
231 231
232 if (FileSystem) 232 if (FileSystem)
233 FileSystem->grab(); 233 FileSystem->grab();
234 234
235 if ( smgr ) 235 if ( smgr )
236 setAmbientLight( smgr->getAmbientLight() ); 236 setAmbientLight( smgr->getAmbientLight() );
237 237
238 CColladaMeshWriterProperties * p = new CColladaMeshWriterProperties(); 238 CColladaMeshWriterProperties * p = new CColladaMeshWriterProperties();
239 setDefaultProperties(p); 239 setDefaultProperties(p);
240 setProperties(p); 240 setProperties(p);
241 p->drop(); 241 p->drop();
242 242
243 CColladaMeshWriterNames * nameGenerator = new CColladaMeshWriterNames(this); 243 CColladaMeshWriterNames * nameGenerator = new CColladaMeshWriterNames(this);
244 setDefaultNameGenerator(nameGenerator); 244 setDefaultNameGenerator(nameGenerator);
245 setNameGenerator(nameGenerator); 245 setNameGenerator(nameGenerator);
246 nameGenerator->drop(); 246 nameGenerator->drop();
247} 247}
248 248
249 249
250CColladaMeshWriter::~CColladaMeshWriter() 250CColladaMeshWriter::~CColladaMeshWriter()
251{ 251{
252 if (VideoDriver) 252 if (VideoDriver)
253 VideoDriver->drop(); 253 VideoDriver->drop();
254 254
255 if (FileSystem) 255 if (FileSystem)
256 FileSystem->drop(); 256 FileSystem->drop();
257} 257}
258 258
259 259
260void CColladaMeshWriter::reset() 260void CColladaMeshWriter::reset()
261{ 261{
262 LibraryImages.clear(); 262 LibraryImages.clear();
263 Meshes.clear(); 263 Meshes.clear();
264 LightNodes.clear(); 264 LightNodes.clear();
265 CameraNodes.clear(); 265 CameraNodes.clear();
266 MaterialsWritten.clear(); 266 MaterialsWritten.clear();
267 EffectsWritten.clear(); 267 EffectsWritten.clear();
268 MaterialNameCache.clear(); 268 MaterialNameCache.clear();
269} 269}
270 270
271//! Returns the type of the mesh writer 271//! Returns the type of the mesh writer
272EMESH_WRITER_TYPE CColladaMeshWriter::getType() const 272EMESH_WRITER_TYPE CColladaMeshWriter::getType() const
273{ 273{
274 return EMWT_COLLADA; 274 return EMWT_COLLADA;
275} 275}
276 276
277//! writes a scene starting with the given node 277//! writes a scene starting with the given node
278bool CColladaMeshWriter::writeScene(io::IWriteFile* file, scene::ISceneNode* root) 278bool CColladaMeshWriter::writeScene(io::IWriteFile* file, scene::ISceneNode* root)
279{ 279{
280 if (!file || !root) 280 if (!file || !root)
281 return false; 281 return false;
282 282
283 reset(); 283 reset();
284 284
285 Writer = FileSystem->createXMLWriter(file); 285 Writer = FileSystem->createXMLWriter(file);
286 286
287 if (!Writer) 287 if (!Writer)
288 { 288 {
289 os::Printer::log("Could not write file", file->getFileName()); 289 os::Printer::log("Could not write file", file->getFileName());
290 return false; 290 return false;
291 } 291 }
292 292
293 Directory = FileSystem->getFileDir(FileSystem->getAbsolutePath( file->getFileName() )); 293 Directory = FileSystem->getFileDir(FileSystem->getAbsolutePath( file->getFileName() ));
294 294
295 // make names for all nodes with exportable meshes 295 // make names for all nodes with exportable meshes
296 makeMeshNames(root); 296 makeMeshNames(root);
297 297
298 os::Printer::log("Writing scene", file->getFileName()); 298 os::Printer::log("Writing scene", file->getFileName());
299 299
300 // write COLLADA header 300 // write COLLADA header
301 301
302 Writer->writeXMLHeader(); 302 Writer->writeXMLHeader();
303 303
304 Writer->writeElement(L"COLLADA", false, 304 Writer->writeElement(L"COLLADA", false,
305 L"xmlns", L"http://www.collada.org/2005/11/COLLADASchema", 305 L"xmlns", L"http://www.collada.org/2005/11/COLLADASchema",
306 L"version", L"1.4.1"); 306 L"version", L"1.4.1");
307 Writer->writeLineBreak(); 307 Writer->writeLineBreak();
308 308
309 // write asset data 309 // write asset data
310 writeAsset(); 310 writeAsset();
311 311
312 // write all materials 312 // write all materials
313 Writer->writeElement(L"library_materials", false); 313 Writer->writeElement(L"library_materials", false);
314 Writer->writeLineBreak(); 314 Writer->writeLineBreak();
315 writeNodeMaterials(root); 315 writeNodeMaterials(root);
316 Writer->writeClosingTag(L"library_materials"); 316 Writer->writeClosingTag(L"library_materials");
317 Writer->writeLineBreak(); 317 Writer->writeLineBreak();
318 318
319 Writer->writeElement(L"library_effects", false); 319 Writer->writeElement(L"library_effects", false);
320 Writer->writeLineBreak(); 320 Writer->writeLineBreak();
321 writeNodeEffects(root); 321 writeNodeEffects(root);
322 Writer->writeClosingTag(L"library_effects"); 322 Writer->writeClosingTag(L"library_effects");
323 Writer->writeLineBreak(); 323 Writer->writeLineBreak();
324 324
325 325
326 // images 326 // images
327 writeLibraryImages(); 327 writeLibraryImages();
328 328
329 // lights 329 // lights
330 Writer->writeElement(L"library_lights", false); 330 Writer->writeElement(L"library_lights", false);
331 Writer->writeLineBreak(); 331 Writer->writeLineBreak();
332 332
333 writeAmbientLightElement( getAmbientLight() ); 333 writeAmbientLightElement( getAmbientLight() );
334 writeNodeLights(root); 334 writeNodeLights(root);
335 335
336 Writer->writeClosingTag(L"library_lights"); 336 Writer->writeClosingTag(L"library_lights");
337 Writer->writeLineBreak(); 337 Writer->writeLineBreak();
338 338
339 // cameras 339 // cameras
340 Writer->writeElement(L"library_cameras", false); 340 Writer->writeElement(L"library_cameras", false);
341 Writer->writeLineBreak(); 341 Writer->writeLineBreak();
342 writeNodeCameras(root); 342 writeNodeCameras(root);
343 Writer->writeClosingTag(L"library_cameras"); 343 Writer->writeClosingTag(L"library_cameras");
344 Writer->writeLineBreak(); 344 Writer->writeLineBreak();
345 345
346 // write meshes 346 // write meshes
347 Writer->writeElement(L"library_geometries", false); 347 Writer->writeElement(L"library_geometries", false);
348 Writer->writeLineBreak(); 348 Writer->writeLineBreak();
349 writeAllMeshGeometries(); 349 writeAllMeshGeometries();
350 Writer->writeClosingTag(L"library_geometries"); 350 Writer->writeClosingTag(L"library_geometries");
351 Writer->writeLineBreak(); 351 Writer->writeLineBreak();
352 352
353 // write scene 353 // write scene
354 Writer->writeElement(L"library_visual_scenes", false); 354 Writer->writeElement(L"library_visual_scenes", false);
355 Writer->writeLineBreak(); 355 Writer->writeLineBreak();
356 Writer->writeElement(L"visual_scene", false, L"id", L"default_scene"); 356 Writer->writeElement(L"visual_scene", false, L"id", L"default_scene");
357 Writer->writeLineBreak(); 357 Writer->writeLineBreak();
358 358
359 // ambient light (instance_light also needs a node as parent so we have to create one) 359 // ambient light (instance_light also needs a node as parent so we have to create one)
360 Writer->writeElement(L"node", false); 360 Writer->writeElement(L"node", false);
361 Writer->writeLineBreak(); 361 Writer->writeLineBreak();
362 Writer->writeElement(L"instance_light", true, L"url", L"#ambientlight"); 362 Writer->writeElement(L"instance_light", true, L"url", L"#ambientlight");
363 Writer->writeLineBreak(); 363 Writer->writeLineBreak();
364 Writer->writeClosingTag(L"node"); 364 Writer->writeClosingTag(L"node");
365 Writer->writeLineBreak(); 365 Writer->writeLineBreak();
366 366
367 // Write the scenegraph. 367 // Write the scenegraph.
368 if ( root->getType() != ESNT_SCENE_MANAGER ) 368 if ( root->getType() != ESNT_SCENE_MANAGER )
369 { 369 {
370 // TODO: Not certain if we should really write the root or if we should just always only write the children. 370 // TODO: Not certain if we should really write the root or if we should just always only write the children.
371 // For now writing root to keep backward compatibility for this case, but if anyone needs to _not_ write 371 // For now writing root to keep backward compatibility for this case, but if anyone needs to _not_ write
372 // that root-node we can add a parameter for this later on in writeScene. 372 // that root-node we can add a parameter for this later on in writeScene.
373 writeSceneNode(root); 373 writeSceneNode(root);
374 } 374 }
375 else 375 else
376 { 376 {
377 // The visual_scene element is identical to our scenemanager and acts as root, 377 // The visual_scene element is identical to our scenemanager and acts as root,
378 // so we do not write the root itself if it points to the scenemanager. 378 // so we do not write the root itself if it points to the scenemanager.
379 const core::list<ISceneNode*>& rootChildren = root->getChildren(); 379 const core::list<ISceneNode*>& rootChildren = root->getChildren();
380 for ( core::list<ISceneNode*>::ConstIterator it = rootChildren.begin(); 380 for ( core::list<ISceneNode*>::ConstIterator it = rootChildren.begin();
381 it != rootChildren.end(); 381 it != rootChildren.end();
382 ++ it ) 382 ++ it )
383 { 383 {
384 writeSceneNode(*it); 384 writeSceneNode(*it);
385 } 385 }
386 } 386 }
387 387
388 388
389 Writer->writeClosingTag(L"visual_scene"); 389 Writer->writeClosingTag(L"visual_scene");
390 Writer->writeLineBreak(); 390 Writer->writeLineBreak();
391 Writer->writeClosingTag(L"library_visual_scenes"); 391 Writer->writeClosingTag(L"library_visual_scenes");
392 Writer->writeLineBreak(); 392 Writer->writeLineBreak();
393 393
394 394
395 // instance scene 395 // instance scene
396 Writer->writeElement(L"scene", false); 396 Writer->writeElement(L"scene", false);
397 Writer->writeLineBreak(); 397 Writer->writeLineBreak();
398 398
399 Writer->writeElement(L"instance_visual_scene", true, L"url", L"#default_scene"); 399 Writer->writeElement(L"instance_visual_scene", true, L"url", L"#default_scene");
400 Writer->writeLineBreak(); 400 Writer->writeLineBreak();
401 401
402 Writer->writeClosingTag(L"scene"); 402 Writer->writeClosingTag(L"scene");
403 Writer->writeLineBreak(); 403 Writer->writeLineBreak();
404 404
405 405
406 // close everything 406 // close everything
407 407
408 Writer->writeClosingTag(L"COLLADA"); 408 Writer->writeClosingTag(L"COLLADA");
409 Writer->drop(); 409 Writer->drop();
410 410
411 return true; 411 return true;
412} 412}
413 413
414void CColladaMeshWriter::makeMeshNames(irr::scene::ISceneNode * node) 414void CColladaMeshWriter::makeMeshNames(irr::scene::ISceneNode * node)
415{ 415{
416 if ( !node || !getProperties() || !getProperties()->isExportable(node) || !getNameGenerator()) 416 if ( !node || !getProperties() || !getProperties()->isExportable(node) || !getNameGenerator())
417 return; 417 return;
418 418
419 IMesh* mesh = getProperties()->getMesh(node); 419 IMesh* mesh = getProperties()->getMesh(node);
420 if ( mesh ) 420 if ( mesh )
421 { 421 {
422 if ( !Meshes.find(mesh) ) 422 if ( !Meshes.find(mesh) )
423 { 423 {
424 SColladaMesh cm; 424 SColladaMesh cm;
425 cm.Name = nameForMesh(mesh, 0); 425 cm.Name = nameForMesh(mesh, 0);
426 Meshes.insert(mesh, cm); 426 Meshes.insert(mesh, cm);
427 } 427 }
428 } 428 }
429 429
430 const core::list<ISceneNode*>& children = node->getChildren(); 430 const core::list<ISceneNode*>& children = node->getChildren();
431 for ( core::list<ISceneNode*>::ConstIterator it = children.begin(); it != children.end(); ++it ) 431 for ( core::list<ISceneNode*>::ConstIterator it = children.begin(); it != children.end(); ++it )
432 { 432 {
433 makeMeshNames(*it); 433 makeMeshNames(*it);
434 } 434 }
435} 435}
436 436
437void CColladaMeshWriter::writeNodeMaterials(irr::scene::ISceneNode * node) 437void CColladaMeshWriter::writeNodeMaterials(irr::scene::ISceneNode * node)
438{ 438{
439 if ( !node || !getProperties() || !getProperties()->isExportable(node) ) 439 if ( !node || !getProperties() || !getProperties()->isExportable(node) )
440 return; 440 return;
441 441
442 core::array<irr::core::stringw> materialNames; 442 core::array<irr::core::stringw> materialNames;
443 443
444 IMesh* mesh = getProperties()->getMesh(node); 444 IMesh* mesh = getProperties()->getMesh(node);
445 if ( mesh ) 445 if ( mesh )
446 { 446 {
447 MeshNode * n = Meshes.find(mesh); 447 MeshNode * n = Meshes.find(mesh);
448 if ( !getProperties()->useNodeMaterial(node) ) 448 if ( !getProperties()->useNodeMaterial(node) )
449 { 449 {
450 // no material overrides - write mesh materials 450 // no material overrides - write mesh materials
451 if ( n && !n->getValue().MaterialsWritten ) 451 if ( n && !n->getValue().MaterialsWritten )
452 { 452 {
453 writeMeshMaterials(mesh, getGeometryWriting() == ECGI_PER_MESH_AND_MATERIAL ? &materialNames : NULL); 453 writeMeshMaterials(mesh, getGeometryWriting() == ECGI_PER_MESH_AND_MATERIAL ? &materialNames : NULL);
454 n->getValue().MaterialsWritten = true; 454 n->getValue().MaterialsWritten = true;
455 } 455 }
456 } 456 }
457 else 457 else
458 { 458 {
459 // write node materials 459 // write node materials
460 for (u32 i=0; i<node->getMaterialCount(); ++i) 460 for (u32 i=0; i<node->getMaterialCount(); ++i)
461 { 461 {
462 video::SMaterial & material = node->getMaterial(i); 462 video::SMaterial & material = node->getMaterial(i);
463 core::stringw strMat(nameForMaterial(material, i, mesh, node)); 463 core::stringw strMat(nameForMaterial(material, i, mesh, node));
464 writeMaterial(strMat); 464 writeMaterial(strMat);
465 if ( getGeometryWriting() == ECGI_PER_MESH_AND_MATERIAL ) 465 if ( getGeometryWriting() == ECGI_PER_MESH_AND_MATERIAL )
466 materialNames.push_back(strMat); 466 materialNames.push_back(strMat);
467 } 467 }
468 } 468 }
469 469
470 // When we write another mesh-geometry for each new material-list we have 470 // When we write another mesh-geometry for each new material-list we have
471 // to figure out here if we need another geometry copy and create a new name here. 471 // to figure out here if we need another geometry copy and create a new name here.
472 if ( n && getGeometryWriting() == ECGI_PER_MESH_AND_MATERIAL ) 472 if ( n && getGeometryWriting() == ECGI_PER_MESH_AND_MATERIAL )
473 { 473 {
474 SGeometryMeshMaterials * geomMat = n->getValue().findGeometryMeshMaterials(materialNames); 474 SGeometryMeshMaterials * geomMat = n->getValue().findGeometryMeshMaterials(materialNames);
475 if ( geomMat ) 475 if ( geomMat )
476 geomMat->MaterialOwners.push_back(node); 476 geomMat->MaterialOwners.push_back(node);
477 else 477 else
478 { 478 {
479 SGeometryMeshMaterials gmm; 479 SGeometryMeshMaterials gmm;
480 if ( n->getValue().GeometryMeshMaterials.empty() ) 480 if ( n->getValue().GeometryMeshMaterials.empty() )
481 gmm.GeometryName = n->getValue().Name; // first one can use the original name 481 gmm.GeometryName = n->getValue().Name; // first one can use the original name
482 else 482 else
483 gmm.GeometryName = nameForMesh(mesh, n->getValue().GeometryMeshMaterials.size()); 483 gmm.GeometryName = nameForMesh(mesh, n->getValue().GeometryMeshMaterials.size());
484 gmm.MaterialNames = materialNames; 484 gmm.MaterialNames = materialNames;
485 gmm.MaterialOwners.push_back(node); 485 gmm.MaterialOwners.push_back(node);
486 n->getValue().GeometryMeshMaterials.push_back(gmm); 486 n->getValue().GeometryMeshMaterials.push_back(gmm);
487 } 487 }
488 } 488 }
489 } 489 }
490 490
491 const core::list<ISceneNode*>& children = node->getChildren(); 491 const core::list<ISceneNode*>& children = node->getChildren();
492 for ( core::list<ISceneNode*>::ConstIterator it = children.begin(); it != children.end(); ++it ) 492 for ( core::list<ISceneNode*>::ConstIterator it = children.begin(); it != children.end(); ++it )
493 { 493 {
494 writeNodeMaterials( *it ); 494 writeNodeMaterials( *it );
495 } 495 }
496} 496}
497 497
498void CColladaMeshWriter::writeMaterial(const irr::core::stringw& materialname) 498void CColladaMeshWriter::writeMaterial(const irr::core::stringw& materialname)
499{ 499{
500 if ( MaterialsWritten.find(materialname) ) 500 if ( MaterialsWritten.find(materialname) )
501 return; 501 return;
502 MaterialsWritten.insert(materialname, true); 502 MaterialsWritten.insert(materialname, true);
503 503
504 Writer->writeElement(L"material", false, 504 Writer->writeElement(L"material", false,
505 L"id", materialname.c_str(), 505 L"id", materialname.c_str(),
506 L"name", materialname.c_str()); 506 L"name", materialname.c_str());
507 Writer->writeLineBreak(); 507 Writer->writeLineBreak();
508 508
509 // We don't make a difference between material and effect on export. 509 // We don't make a difference between material and effect on export.
510 // Every material is just using an instance of an effect. 510 // Every material is just using an instance of an effect.
511 core::stringw strFx(materialname); 511 core::stringw strFx(materialname);
512 strFx += L"-fx"; 512 strFx += L"-fx";
513 Writer->writeElement(L"instance_effect", true, 513 Writer->writeElement(L"instance_effect", true,
514 L"url", (core::stringw(L"#") + strFx).c_str()); 514 L"url", (core::stringw(L"#") + strFx).c_str());
515 Writer->writeLineBreak(); 515 Writer->writeLineBreak();
516 516
517 Writer->writeClosingTag(L"material"); 517 Writer->writeClosingTag(L"material");
518 Writer->writeLineBreak(); 518 Writer->writeLineBreak();
519} 519}
520 520
521void CColladaMeshWriter::writeNodeEffects(irr::scene::ISceneNode * node) 521void CColladaMeshWriter::writeNodeEffects(irr::scene::ISceneNode * node)
522{ 522{
523 if ( !node || !getProperties() || !getProperties()->isExportable(node) || !getNameGenerator() ) 523 if ( !node || !getProperties() || !getProperties()->isExportable(node) || !getNameGenerator() )
524 return; 524 return;
525 525
526 IMesh* mesh = getProperties()->getMesh(node); 526 IMesh* mesh = getProperties()->getMesh(node);
527 if ( mesh ) 527 if ( mesh )
528 { 528 {
529 if ( !getProperties()->useNodeMaterial(node) ) 529 if ( !getProperties()->useNodeMaterial(node) )
530 { 530 {
531 // no material overrides - write mesh materials 531 // no material overrides - write mesh materials
532 MeshNode * n = Meshes.find(mesh); 532 MeshNode * n = Meshes.find(mesh);
533 if ( n && !n->getValue().EffectsWritten ) 533 if ( n && !n->getValue().EffectsWritten )
534 { 534 {
535 writeMeshEffects(mesh); 535 writeMeshEffects(mesh);
536 n->getValue().EffectsWritten = true; 536 n->getValue().EffectsWritten = true;
537 } 537 }
538 } 538 }
539 else 539 else
540 { 540 {
541 // write node materials 541 // write node materials
542 for (u32 i=0; i<node->getMaterialCount(); ++i) 542 for (u32 i=0; i<node->getMaterialCount(); ++i)
543 { 543 {
544 video::SMaterial & material = node->getMaterial(i); 544 video::SMaterial & material = node->getMaterial(i);
545 irr::core::stringw materialfxname(nameForMaterial(material, i, mesh, node)); 545 irr::core::stringw materialfxname(nameForMaterial(material, i, mesh, node));
546 materialfxname += L"-fx"; 546 materialfxname += L"-fx";
547 writeMaterialEffect(materialfxname, material); 547 writeMaterialEffect(materialfxname, material);
548 } 548 }
549 } 549 }
550 } 550 }
551 551
552 const core::list<ISceneNode*>& children = node->getChildren(); 552 const core::list<ISceneNode*>& children = node->getChildren();
553 for ( core::list<ISceneNode*>::ConstIterator it = children.begin(); it != children.end(); ++it ) 553 for ( core::list<ISceneNode*>::ConstIterator it = children.begin(); it != children.end(); ++it )
554 { 554 {
555 writeNodeEffects( *it ); 555 writeNodeEffects( *it );
556 } 556 }
557} 557}
558 558
559void CColladaMeshWriter::writeNodeLights(irr::scene::ISceneNode * node) 559void CColladaMeshWriter::writeNodeLights(irr::scene::ISceneNode * node)
560{ 560{
561 if ( !node || !getProperties() || !getProperties()->isExportable(node)) 561 if ( !node || !getProperties() || !getProperties()->isExportable(node))
562 return; 562 return;
563 563
564 if ( node->getType() == ESNT_LIGHT ) 564 if ( node->getType() == ESNT_LIGHT )
565 { 565 {
566 ILightSceneNode * lightNode = static_cast<ILightSceneNode*>(node); 566 ILightSceneNode * lightNode = static_cast<ILightSceneNode*>(node);
567 const video::SLight& lightData = lightNode->getLightData(); 567 const video::SLight& lightData = lightNode->getLightData();
568 568
569 SColladaLight cLight; 569 SColladaLight cLight;
570 cLight.Name = nameForNode(node); 570 cLight.Name = nameForNode(node);
571 LightNodes.insert(node, cLight); 571 LightNodes.insert(node, cLight);
572 572
573 Writer->writeElement(L"light", false, L"id", cLight.Name.c_str()); 573 Writer->writeElement(L"light", false, L"id", cLight.Name.c_str());
574 Writer->writeLineBreak(); 574 Writer->writeLineBreak();
575 575
576 Writer->writeElement(L"technique_common", false); 576 Writer->writeElement(L"technique_common", false);
577 Writer->writeLineBreak(); 577 Writer->writeLineBreak();
578 578
579 switch ( lightNode->getLightType() ) 579 switch ( lightNode->getLightType() )
580 { 580 {
581 case video::ELT_POINT: 581 case video::ELT_POINT:
582 Writer->writeElement(L"point", false); 582 Writer->writeElement(L"point", false);
583 Writer->writeLineBreak(); 583 Writer->writeLineBreak();
584 584
585 writeColorElement(lightData.DiffuseColor, false); 585 writeColorElement(lightData.DiffuseColor, false);
586 writeNode(L"constant_attenuation ", core::stringw(lightData.Attenuation.X).c_str()); 586 writeNode(L"constant_attenuation ", core::stringw(lightData.Attenuation.X).c_str());
587 writeNode(L"linear_attenuation ", core::stringw(lightData.Attenuation.Y).c_str()); 587 writeNode(L"linear_attenuation ", core::stringw(lightData.Attenuation.Y).c_str());
588 writeNode(L"quadratic_attenuation", core::stringw(lightData.Attenuation.Z).c_str()); 588 writeNode(L"quadratic_attenuation", core::stringw(lightData.Attenuation.Z).c_str());
589 589
590 Writer->writeClosingTag(L"point"); 590 Writer->writeClosingTag(L"point");
591 Writer->writeLineBreak(); 591 Writer->writeLineBreak();
592 break; 592 break;
593 593
594 case video::ELT_SPOT: 594 case video::ELT_SPOT:
595 Writer->writeElement(L"spot", false); 595 Writer->writeElement(L"spot", false);
596 Writer->writeLineBreak(); 596 Writer->writeLineBreak();
597 597
598 writeColorElement(lightData.DiffuseColor, false); 598 writeColorElement(lightData.DiffuseColor, false);
599 599
600 writeNode(L"constant_attenuation ", core::stringw(lightData.Attenuation.X).c_str()); 600 writeNode(L"constant_attenuation ", core::stringw(lightData.Attenuation.X).c_str());
601 writeNode(L"linear_attenuation ", core::stringw(lightData.Attenuation.Y).c_str()); 601 writeNode(L"linear_attenuation ", core::stringw(lightData.Attenuation.Y).c_str());
602 writeNode(L"quadratic_attenuation", core::stringw(lightData.Attenuation.Z).c_str()); 602 writeNode(L"quadratic_attenuation", core::stringw(lightData.Attenuation.Z).c_str());
603 603
604 writeNode(L"falloff_angle", core::stringw(lightData.OuterCone * core::RADTODEG).c_str()); 604 writeNode(L"falloff_angle", core::stringw(lightData.OuterCone * core::RADTODEG).c_str());
605 writeNode(L"falloff_exponent", core::stringw(lightData.Falloff).c_str()); 605 writeNode(L"falloff_exponent", core::stringw(lightData.Falloff).c_str());
606 606
607 Writer->writeClosingTag(L"spot"); 607 Writer->writeClosingTag(L"spot");
608 Writer->writeLineBreak(); 608 Writer->writeLineBreak();
609 break; 609 break;
610 610
611 case video::ELT_DIRECTIONAL: 611 case video::ELT_DIRECTIONAL:
612 Writer->writeElement(L"directional", false); 612 Writer->writeElement(L"directional", false);
613 Writer->writeLineBreak(); 613 Writer->writeLineBreak();
614 614
615 writeColorElement(lightData.DiffuseColor, false); 615 writeColorElement(lightData.DiffuseColor, false);
616 616
617 Writer->writeClosingTag(L"directional"); 617 Writer->writeClosingTag(L"directional");
618 Writer->writeLineBreak(); 618 Writer->writeLineBreak();
619 break; 619 break;
620 default: 620 default:
621 break; 621 break;
622 } 622 }
623 623
624 Writer->writeClosingTag(L"technique_common"); 624 Writer->writeClosingTag(L"technique_common");
625 Writer->writeLineBreak(); 625 Writer->writeLineBreak();
626 626
627 Writer->writeClosingTag(L"light"); 627 Writer->writeClosingTag(L"light");
628 Writer->writeLineBreak(); 628 Writer->writeLineBreak();
629 629
630 } 630 }
631 631
632 const core::list<ISceneNode*>& children = node->getChildren(); 632 const core::list<ISceneNode*>& children = node->getChildren();
633 for ( core::list<ISceneNode*>::ConstIterator it = children.begin(); it != children.end(); ++it ) 633 for ( core::list<ISceneNode*>::ConstIterator it = children.begin(); it != children.end(); ++it )
634 { 634 {
635 writeNodeLights( *it ); 635 writeNodeLights( *it );
636 } 636 }
637} 637}
638 638
639void CColladaMeshWriter::writeNodeCameras(irr::scene::ISceneNode * node) 639void CColladaMeshWriter::writeNodeCameras(irr::scene::ISceneNode * node)
640{ 640{
641 if ( !node || !getProperties() || !getProperties()->isExportable(node) ) 641 if ( !node || !getProperties() || !getProperties()->isExportable(node) )
642 return; 642 return;
643 643
644 if ( isCamera(node) ) 644 if ( isCamera(node) )
645 { 645 {
646 ICameraSceneNode * cameraNode = static_cast<ICameraSceneNode*>(node); 646 ICameraSceneNode * cameraNode = static_cast<ICameraSceneNode*>(node);
647 irr::core::stringw name = nameForNode(node); 647 irr::core::stringw name = nameForNode(node);
648 CameraNodes.insert(cameraNode, name); 648 CameraNodes.insert(cameraNode, name);
649 649
650 Writer->writeElement(L"camera", false, L"id", name.c_str()); 650 Writer->writeElement(L"camera", false, L"id", name.c_str());
651 Writer->writeLineBreak(); 651 Writer->writeLineBreak();
652 652
653 Writer->writeElement(L"optics", false); 653 Writer->writeElement(L"optics", false);
654 Writer->writeLineBreak(); 654 Writer->writeLineBreak();
655 655
656 Writer->writeElement(L"technique_common", false); 656 Writer->writeElement(L"technique_common", false);
657 Writer->writeLineBreak(); 657 Writer->writeLineBreak();
658 658
659 if ( cameraNode->isOrthogonal() ) 659 if ( cameraNode->isOrthogonal() )
660 { 660 {
661 Writer->writeElement(L"orthographic", false); 661 Writer->writeElement(L"orthographic", false);
662 Writer->writeLineBreak(); 662 Writer->writeLineBreak();
663 663
664// writeNode(L"xmag", core::stringw("1.0").c_str()); // TODO: do we need xmag, ymag? 664// writeNode(L"xmag", core::stringw("1.0").c_str()); // TODO: do we need xmag, ymag?
665// writeNode(L"ymag", core::stringw("1.0").c_str()); 665// writeNode(L"ymag", core::stringw("1.0").c_str());
666 writeNode(L"aspect_ratio", core::stringw(cameraNode->getAspectRatio()).c_str()); 666 writeNode(L"aspect_ratio", core::stringw(cameraNode->getAspectRatio()).c_str());
667 writeNode(L"znear", core::stringw(cameraNode->getNearValue()).c_str()); 667 writeNode(L"znear", core::stringw(cameraNode->getNearValue()).c_str());
668 writeNode(L"zfar", core::stringw(cameraNode->getFarValue()).c_str()); 668 writeNode(L"zfar", core::stringw(cameraNode->getFarValue()).c_str());
669 669
670 Writer->writeClosingTag(L"orthographic"); 670 Writer->writeClosingTag(L"orthographic");
671 Writer->writeLineBreak(); 671 Writer->writeLineBreak();
672 } 672 }
673 else 673 else
674 { 674 {
675 Writer->writeElement(L"perspective", false); 675 Writer->writeElement(L"perspective", false);
676 Writer->writeLineBreak(); 676 Writer->writeLineBreak();
677 677
678 writeNode(L"yfov", core::stringw(cameraNode->getFOV()*core::RADTODEG).c_str()); 678 writeNode(L"yfov", core::stringw(cameraNode->getFOV()*core::RADTODEG).c_str());
679 writeNode(L"aspect_ratio", core::stringw(cameraNode->getAspectRatio()).c_str()); 679 writeNode(L"aspect_ratio", core::stringw(cameraNode->getAspectRatio()).c_str());
680 writeNode(L"znear", core::stringw(cameraNode->getNearValue()).c_str()); 680 writeNode(L"znear", core::stringw(cameraNode->getNearValue()).c_str());
681 writeNode(L"zfar", core::stringw(cameraNode->getFarValue()).c_str()); 681 writeNode(L"zfar", core::stringw(cameraNode->getFarValue()).c_str());
682 682
683 Writer->writeClosingTag(L"perspective"); 683 Writer->writeClosingTag(L"perspective");
684 Writer->writeLineBreak(); 684 Writer->writeLineBreak();
685 } 685 }
686 686
687 Writer->writeClosingTag(L"technique_common"); 687 Writer->writeClosingTag(L"technique_common");
688 Writer->writeLineBreak(); 688 Writer->writeLineBreak();
689 689
690 Writer->writeClosingTag(L"optics"); 690 Writer->writeClosingTag(L"optics");
691 Writer->writeLineBreak(); 691 Writer->writeLineBreak();
692 692
693 Writer->writeClosingTag(L"camera"); 693 Writer->writeClosingTag(L"camera");
694 Writer->writeLineBreak(); 694 Writer->writeLineBreak();
695 } 695 }
696 696
697 const core::list<ISceneNode*>& children = node->getChildren(); 697 const core::list<ISceneNode*>& children = node->getChildren();
698 for ( core::list<ISceneNode*>::ConstIterator it = children.begin(); it != children.end(); ++it ) 698 for ( core::list<ISceneNode*>::ConstIterator it = children.begin(); it != children.end(); ++it )
699 { 699 {
700 writeNodeCameras( *it ); 700 writeNodeCameras( *it );
701 } 701 }
702} 702}
703 703
704void CColladaMeshWriter::writeAllMeshGeometries() 704void CColladaMeshWriter::writeAllMeshGeometries()
705{ 705{
706 core::map<IMesh*, SColladaMesh>::ConstIterator it = Meshes.getConstIterator(); 706 core::map<IMesh*, SColladaMesh>::ConstIterator it = Meshes.getConstIterator();
707 for(; !it.atEnd(); it++ ) 707 for(; !it.atEnd(); it++ )
708 { 708 {
709 IMesh* mesh = it->getKey(); 709 IMesh* mesh = it->getKey();
710 const SColladaMesh& colladaMesh = it->getValue(); 710 const SColladaMesh& colladaMesh = it->getValue();
711 711
712 if ( getGeometryWriting() == ECGI_PER_MESH_AND_MATERIAL && colladaMesh.GeometryMeshMaterials.size() > 1 ) 712 if ( getGeometryWriting() == ECGI_PER_MESH_AND_MATERIAL && colladaMesh.GeometryMeshMaterials.size() > 1 )
713 { 713 {
714 for ( u32 i=0; i<colladaMesh.GeometryMeshMaterials.size(); ++i ) 714 for ( u32 i=0; i<colladaMesh.GeometryMeshMaterials.size(); ++i )
715 { 715 {
716 writeMeshGeometry(colladaMesh.GeometryMeshMaterials[i].GeometryName, mesh); 716 writeMeshGeometry(colladaMesh.GeometryMeshMaterials[i].GeometryName, mesh);
717 } 717 }
718 } 718 }
719 else 719 else
720 { 720 {
721 writeMeshGeometry(colladaMesh.Name, mesh); 721 writeMeshGeometry(colladaMesh.Name, mesh);
722 } 722 }
723 } 723 }
724} 724}
725 725
726void CColladaMeshWriter::writeSceneNode(irr::scene::ISceneNode * node ) 726void CColladaMeshWriter::writeSceneNode(irr::scene::ISceneNode * node )
727{ 727{
728 if ( !node || !getProperties() || !getProperties()->isExportable(node) ) 728 if ( !node || !getProperties() || !getProperties()->isExportable(node) )
729 return; 729 return;
730 730
731 // Collada doesn't require to set the id, but some other tools have problems if none exists, so we just add it. 731 // Collada doesn't require to set the id, but some other tools have problems if none exists, so we just add it.
732 irr::core::stringw nameId(nameForNode(node)); 732 irr::core::stringw nameId(nameForNode(node));
733 Writer->writeElement(L"node", false, L"id", nameId.c_str()); 733 Writer->writeElement(L"node", false, L"id", nameId.c_str());
734 Writer->writeLineBreak(); 734 Writer->writeLineBreak();
735 735
736 // DummyTransformationSceneNode don't have rotation, position, scale information 736 // DummyTransformationSceneNode don't have rotation, position, scale information
737 // But also don't always export the transformation matrix as that forces us creating 737 // But also don't always export the transformation matrix as that forces us creating
738 // new DummyTransformationSceneNode's on import. 738 // new DummyTransformationSceneNode's on import.
739 if ( node->getType() == ESNT_DUMMY_TRANSFORMATION ) 739 if ( node->getType() == ESNT_DUMMY_TRANSFORMATION )
740 { 740 {
741 writeMatrixElement(node->getRelativeTransformation()); 741 writeMatrixElement(node->getRelativeTransformation());
742 } 742 }
743 else 743 else
744 { 744 {
745 irr::core::vector3df rot(node->getRotation()); 745 irr::core::vector3df rot(node->getRotation());
746 if ( isCamera(node) && !static_cast<ICameraSceneNode*>(node)->getTargetAndRotationBinding() ) 746 if ( isCamera(node) && !static_cast<ICameraSceneNode*>(node)->getTargetAndRotationBinding() )
747 { 747 {
748 ICameraSceneNode * camNode = static_cast<ICameraSceneNode*>(node); 748 ICameraSceneNode * camNode = static_cast<ICameraSceneNode*>(node);
749 const core::vector3df toTarget = camNode->getTarget() - camNode->getAbsolutePosition(); 749 const core::vector3df toTarget = camNode->getTarget() - camNode->getAbsolutePosition();
750 rot = toTarget.getHorizontalAngle(); 750 rot = toTarget.getHorizontalAngle();
751 } 751 }
752 752
753 writeTranslateElement( node->getPosition() ); 753 writeTranslateElement( node->getPosition() );
754 writeRotateElement( irr::core::vector3df(1.f, 0.f, 0.f), rot.X ); 754 writeRotateElement( irr::core::vector3df(1.f, 0.f, 0.f), rot.X );
755 writeRotateElement( irr::core::vector3df(0.f, 1.f, 0.f), rot.Y ); 755 writeRotateElement( irr::core::vector3df(0.f, 1.f, 0.f), rot.Y );
756 writeRotateElement( irr::core::vector3df(0.f, 0.f, 1.f), rot.Z ); 756 writeRotateElement( irr::core::vector3df(0.f, 0.f, 1.f), rot.Z );
757 writeScaleElement( node->getScale() ); 757 writeScaleElement( node->getScale() );
758 } 758 }
759 759
760 // instance geometry 760 // instance geometry
761 IMesh* mesh = getProperties()->getMesh(node); 761 IMesh* mesh = getProperties()->getMesh(node);
762 if ( mesh ) 762 if ( mesh )
763 { 763 {
764 MeshNode * n = Meshes.find(mesh); 764 MeshNode * n = Meshes.find(mesh);
765 if ( n ) 765 if ( n )
766 { 766 {
767 const SColladaMesh& colladaMesh = n->getValue(); 767 const SColladaMesh& colladaMesh = n->getValue();
768 writeMeshInstanceGeometry(colladaMesh.findGeometryNameForNode(node), mesh, node); 768 writeMeshInstanceGeometry(colladaMesh.findGeometryNameForNode(node), mesh, node);
769 } 769 }
770 } 770 }
771 771
772 // instance light 772 // instance light
773 if ( node->getType() == ESNT_LIGHT ) 773 if ( node->getType() == ESNT_LIGHT )
774 { 774 {
775 LightNode * n = LightNodes.find(node); 775 LightNode * n = LightNodes.find(node);
776 if ( n ) 776 if ( n )
777 writeLightInstance(n->getValue().Name); 777 writeLightInstance(n->getValue().Name);
778 } 778 }
779 779
780 // instance camera 780 // instance camera
781 if ( isCamera(node) ) 781 if ( isCamera(node) )
782 { 782 {
783 CameraNode * camNode = CameraNodes.find(node); 783 CameraNode * camNode = CameraNodes.find(node);
784 if ( camNode ) 784 if ( camNode )
785 writeCameraInstance(camNode->getValue()); 785 writeCameraInstance(camNode->getValue());
786 } 786 }
787 787
788 const core::list<ISceneNode*>& children = node->getChildren(); 788 const core::list<ISceneNode*>& children = node->getChildren();
789 for ( core::list<ISceneNode*>::ConstIterator it = children.begin(); it != children.end(); ++it ) 789 for ( core::list<ISceneNode*>::ConstIterator it = children.begin(); it != children.end(); ++it )
790 { 790 {
791 writeSceneNode( *it ); 791 writeSceneNode( *it );
792 } 792 }
793 793
794 Writer->writeClosingTag(L"node"); 794 Writer->writeClosingTag(L"node");
795 Writer->writeLineBreak(); 795 Writer->writeLineBreak();
796} 796}
797 797
798//! writes a mesh 798//! writes a mesh
799bool CColladaMeshWriter::writeMesh(io::IWriteFile* file, scene::IMesh* mesh, s32 flags) 799bool CColladaMeshWriter::writeMesh(io::IWriteFile* file, scene::IMesh* mesh, s32 flags)
800{ 800{
801 if (!file) 801 if (!file)
802 return false; 802 return false;
803 803
804 reset(); 804 reset();
805 805
806 Writer = FileSystem->createXMLWriter(file); 806 Writer = FileSystem->createXMLWriter(file);
807 807
808 if (!Writer) 808 if (!Writer)
809 { 809 {
810 os::Printer::log("Could not write file", file->getFileName()); 810 os::Printer::log("Could not write file", file->getFileName());
811 return false; 811 return false;
812 } 812 }
813 813
814 Directory = FileSystem->getFileDir(FileSystem->getAbsolutePath( file->getFileName() )); 814 Directory = FileSystem->getFileDir(FileSystem->getAbsolutePath( file->getFileName() ));
815 815
816 os::Printer::log("Writing mesh", file->getFileName()); 816 os::Printer::log("Writing mesh", file->getFileName());
817 817
818 // write COLLADA header 818 // write COLLADA header
819 819
820 Writer->writeXMLHeader(); 820 Writer->writeXMLHeader();
821 821
822 Writer->writeElement(L"COLLADA", false, 822 Writer->writeElement(L"COLLADA", false,
823 L"xmlns", L"http://www.collada.org/2005/11/COLLADASchema", 823 L"xmlns", L"http://www.collada.org/2005/11/COLLADASchema",
824 L"version", L"1.4.1"); 824 L"version", L"1.4.1");
825 Writer->writeLineBreak(); 825 Writer->writeLineBreak();
826 826
827 // write asset data 827 // write asset data
828 writeAsset(); 828 writeAsset();
829 829
830 // write all materials 830 // write all materials
831 831
832 Writer->writeElement(L"library_materials", false); 832 Writer->writeElement(L"library_materials", false);
833 Writer->writeLineBreak(); 833 Writer->writeLineBreak();
834 834
835 writeMeshMaterials(mesh); 835 writeMeshMaterials(mesh);
836 836
837 Writer->writeClosingTag(L"library_materials"); 837 Writer->writeClosingTag(L"library_materials");
838 Writer->writeLineBreak(); 838 Writer->writeLineBreak();
839 839
840 Writer->writeElement(L"library_effects", false); 840 Writer->writeElement(L"library_effects", false);
841 Writer->writeLineBreak(); 841 Writer->writeLineBreak();
842 842
843 writeMeshEffects(mesh); 843 writeMeshEffects(mesh);
844 844
845 Writer->writeClosingTag(L"library_effects"); 845 Writer->writeClosingTag(L"library_effects");
846 Writer->writeLineBreak(); 846 Writer->writeLineBreak();
847 847
848 // images 848 // images
849 writeLibraryImages(); 849 writeLibraryImages();
850 850
851 // write mesh 851 // write mesh
852 852
853 Writer->writeElement(L"library_geometries", false); 853 Writer->writeElement(L"library_geometries", false);
854 Writer->writeLineBreak(); 854 Writer->writeLineBreak();
855 855
856 irr::core::stringw meshname(nameForMesh(mesh, 0)); 856 irr::core::stringw meshname(nameForMesh(mesh, 0));
857 writeMeshGeometry(meshname, mesh); 857 writeMeshGeometry(meshname, mesh);
858 858
859 Writer->writeClosingTag(L"library_geometries"); 859 Writer->writeClosingTag(L"library_geometries");
860 Writer->writeLineBreak(); 860 Writer->writeLineBreak();
861 861
862 // write scene_library 862 // write scene_library
863 if ( getWriteDefaultScene() ) 863 if ( getWriteDefaultScene() )
864 { 864 {
865 Writer->writeElement(L"library_visual_scenes", false); 865 Writer->writeElement(L"library_visual_scenes", false);
866 Writer->writeLineBreak(); 866 Writer->writeLineBreak();
867 867
868 Writer->writeElement(L"visual_scene", false, L"id", L"default_scene"); 868 Writer->writeElement(L"visual_scene", false, L"id", L"default_scene");
869 Writer->writeLineBreak(); 869 Writer->writeLineBreak();
870 870
871 Writer->writeElement(L"node", false); 871 Writer->writeElement(L"node", false);
872 Writer->writeLineBreak(); 872 Writer->writeLineBreak();
873 873
874 writeMeshInstanceGeometry(meshname, mesh); 874 writeMeshInstanceGeometry(meshname, mesh);
875 875
876 Writer->writeClosingTag(L"node"); 876 Writer->writeClosingTag(L"node");
877 Writer->writeLineBreak(); 877 Writer->writeLineBreak();
878 878
879 Writer->writeClosingTag(L"visual_scene"); 879 Writer->writeClosingTag(L"visual_scene");
880 Writer->writeLineBreak(); 880 Writer->writeLineBreak();
881 881
882 Writer->writeClosingTag(L"library_visual_scenes"); 882 Writer->writeClosingTag(L"library_visual_scenes");
883 Writer->writeLineBreak(); 883 Writer->writeLineBreak();
884 884
885 885
886 // write scene 886 // write scene
887 Writer->writeElement(L"scene", false); 887 Writer->writeElement(L"scene", false);
888 Writer->writeLineBreak(); 888 Writer->writeLineBreak();
889 889
890 Writer->writeElement(L"instance_visual_scene", true, L"url", L"#default_scene"); 890 Writer->writeElement(L"instance_visual_scene", true, L"url", L"#default_scene");
891 Writer->writeLineBreak(); 891 Writer->writeLineBreak();
892 892
893 Writer->writeClosingTag(L"scene"); 893 Writer->writeClosingTag(L"scene");
894 Writer->writeLineBreak(); 894 Writer->writeLineBreak();
895 } 895 }
896 896
897 897
898 // close everything 898 // close everything
899 899
900 Writer->writeClosingTag(L"COLLADA"); 900 Writer->writeClosingTag(L"COLLADA");
901 Writer->drop(); 901 Writer->drop();
902 902
903 return true; 903 return true;
904} 904}
905 905
906void CColladaMeshWriter::writeMeshInstanceGeometry(const irr::core::stringw& meshname, scene::IMesh* mesh, scene::ISceneNode* node) 906void CColladaMeshWriter::writeMeshInstanceGeometry(const irr::core::stringw& meshname, scene::IMesh* mesh, scene::ISceneNode* node)
907{ 907{
908 //<instance_geometry url="#mesh"> 908 //<instance_geometry url="#mesh">
909 Writer->writeElement(L"instance_geometry", false, L"url", toRef(meshname).c_str()); 909 Writer->writeElement(L"instance_geometry", false, L"url", toRef(meshname).c_str());
910 Writer->writeLineBreak(); 910 Writer->writeLineBreak();
911 911
912 Writer->writeElement(L"bind_material", false); 912 Writer->writeElement(L"bind_material", false);
913 Writer->writeLineBreak(); 913 Writer->writeLineBreak();
914 914
915 Writer->writeElement(L"technique_common", false); 915 Writer->writeElement(L"technique_common", false);
916 Writer->writeLineBreak(); 916 Writer->writeLineBreak();
917 917
918 // instance materials 918 // instance materials
919 // <instance_material symbol="leaf" target="#MidsummerLeaf01"/> 919 // <instance_material symbol="leaf" target="#MidsummerLeaf01"/>
920 bool useNodeMaterials = node && node->getMaterialCount() == mesh->getMeshBufferCount(); 920 bool useNodeMaterials = node && node->getMaterialCount() == mesh->getMeshBufferCount();
921 for (u32 i=0; i<mesh->getMeshBufferCount(); ++i) 921 for (u32 i=0; i<mesh->getMeshBufferCount(); ++i)
922 { 922 {
923 irr::core::stringw strMatSymbol(nameForMaterialSymbol(mesh, i)); 923 irr::core::stringw strMatSymbol(nameForMaterialSymbol(mesh, i));
924 core::stringw strMatTarget = "#"; 924 core::stringw strMatTarget = "#";
925 video::SMaterial & material = useNodeMaterials ? node->getMaterial(i) : mesh->getMeshBuffer(i)->getMaterial(); 925 video::SMaterial & material = useNodeMaterials ? node->getMaterial(i) : mesh->getMeshBuffer(i)->getMaterial();
926 strMatTarget += nameForMaterial(material, i, mesh, node); 926 strMatTarget += nameForMaterial(material, i, mesh, node);
927 Writer->writeElement(L"instance_material", false, L"symbol", strMatSymbol.c_str(), L"target", strMatTarget.c_str()); 927 Writer->writeElement(L"instance_material", false, L"symbol", strMatSymbol.c_str(), L"target", strMatTarget.c_str());
928 Writer->writeLineBreak(); 928 Writer->writeLineBreak();
929 929
930 // TODO: need to handle second UV-set 930 // TODO: need to handle second UV-set
931 // <bind_vertex_input semantic="uv" input_semantic="TEXCOORD" input_set="0"/> 931 // <bind_vertex_input semantic="uv" input_semantic="TEXCOORD" input_set="0"/>
932 Writer->writeElement(L"bind_vertex_input", true, L"semantic", L"uv", L"input_semantic", L"TEXCOORD", L"input_set", L"0" ); 932 Writer->writeElement(L"bind_vertex_input", true, L"semantic", L"uv", L"input_semantic", L"TEXCOORD", L"input_set", L"0" );
933 Writer->writeLineBreak(); 933 Writer->writeLineBreak();
934 934
935 Writer->writeClosingTag(L"instance_material"); 935 Writer->writeClosingTag(L"instance_material");
936 Writer->writeLineBreak(); 936 Writer->writeLineBreak();
937 } 937 }
938 938
939 Writer->writeClosingTag(L"technique_common"); 939 Writer->writeClosingTag(L"technique_common");
940 Writer->writeLineBreak(); 940 Writer->writeLineBreak();
941 941
942 Writer->writeClosingTag(L"bind_material"); 942 Writer->writeClosingTag(L"bind_material");
943 Writer->writeLineBreak(); 943 Writer->writeLineBreak();
944 944
945 Writer->writeClosingTag(L"instance_geometry"); 945 Writer->writeClosingTag(L"instance_geometry");
946 Writer->writeLineBreak(); 946 Writer->writeLineBreak();
947} 947}
948 948
949void CColladaMeshWriter::writeLightInstance(const irr::core::stringw& lightName) 949void CColladaMeshWriter::writeLightInstance(const irr::core::stringw& lightName)
950{ 950{
951 Writer->writeElement(L"instance_light", true, L"url", toRef(lightName).c_str()); 951 Writer->writeElement(L"instance_light", true, L"url", toRef(lightName).c_str());
952 Writer->writeLineBreak(); 952 Writer->writeLineBreak();
953} 953}
954 954
955void CColladaMeshWriter::writeCameraInstance(const irr::core::stringw& cameraName) 955void CColladaMeshWriter::writeCameraInstance(const irr::core::stringw& cameraName)
956{ 956{
957 Writer->writeElement(L"instance_camera", true, L"url", toRef(cameraName).c_str()); 957 Writer->writeElement(L"instance_camera", true, L"url", toRef(cameraName).c_str());
958 Writer->writeLineBreak(); 958 Writer->writeLineBreak();
959} 959}
960 960
961bool CColladaMeshWriter::hasSecondTextureCoordinates(video::E_VERTEX_TYPE type) const 961bool CColladaMeshWriter::hasSecondTextureCoordinates(video::E_VERTEX_TYPE type) const
962{ 962{
963 return type == video::EVT_2TCOORDS; 963 return type == video::EVT_2TCOORDS;
964} 964}
965 965
966void CColladaMeshWriter::writeVector(const irr::core::vector3df& vec) 966void CColladaMeshWriter::writeVector(const irr::core::vector3df& vec)
967{ 967{
968 wchar_t tmpbuf[255]; 968 wchar_t tmpbuf[255];
969 swprintf(tmpbuf, 255, L"%f %f %f", vec.X, vec.Y, vec.Z); 969 swprintf(tmpbuf, 255, L"%f %f %f", vec.X, vec.Y, vec.Z);
970 970
971 Writer->writeText(tmpbuf); 971 Writer->writeText(tmpbuf);
972} 972}
973 973
974void CColladaMeshWriter::writeUv(const irr::core::vector2df& vec) 974void CColladaMeshWriter::writeUv(const irr::core::vector2df& vec)
975{ 975{
976 // change handedness 976 // change handedness
977 wchar_t tmpbuf[255]; 977 wchar_t tmpbuf[255];
978 swprintf(tmpbuf, 255, L"%f %f", vec.X, 1.f-vec.Y); 978 swprintf(tmpbuf, 255, L"%f %f", vec.X, 1.f-vec.Y);
979 979
980 Writer->writeText(tmpbuf); 980 Writer->writeText(tmpbuf);
981} 981}
982 982
983void CColladaMeshWriter::writeVector(const irr::core::vector2df& vec) 983void CColladaMeshWriter::writeVector(const irr::core::vector2df& vec)
984{ 984{
985 wchar_t tmpbuf[255]; 985 wchar_t tmpbuf[255];
986 swprintf(tmpbuf, 255, L"%f %f", vec.X, vec.Y); 986 swprintf(tmpbuf, 255, L"%f %f", vec.X, vec.Y);
987 987
988 Writer->writeText(tmpbuf); 988 Writer->writeText(tmpbuf);
989} 989}
990 990
991void CColladaMeshWriter::writeColor(const irr::video::SColorf& colorf, bool writeAlpha) 991void CColladaMeshWriter::writeColor(const irr::video::SColorf& colorf, bool writeAlpha)
992{ 992{
993 wchar_t tmpbuf[255]; 993 wchar_t tmpbuf[255];
994 if ( writeAlpha ) 994 if ( writeAlpha )
995 swprintf(tmpbuf, 255, L"%f %f %f %f", colorf.getRed(), colorf.getGreen(), colorf.getBlue(), colorf.getAlpha()); 995 swprintf(tmpbuf, 255, L"%f %f %f %f", colorf.getRed(), colorf.getGreen(), colorf.getBlue(), colorf.getAlpha());
996 else 996 else
997 swprintf(tmpbuf, 255, L"%f %f %f", colorf.getRed(), colorf.getGreen(), colorf.getBlue()); 997 swprintf(tmpbuf, 255, L"%f %f %f", colorf.getRed(), colorf.getGreen(), colorf.getBlue());
998 998
999 Writer->writeText(tmpbuf); 999 Writer->writeText(tmpbuf);
1000} 1000}
1001 1001
1002irr::core::stringw CColladaMeshWriter::toString(const irr::video::ECOLOR_FORMAT format) const 1002irr::core::stringw CColladaMeshWriter::toString(const irr::video::ECOLOR_FORMAT format) const
1003{ 1003{
1004 switch ( format ) 1004 switch ( format )
1005 { 1005 {
1006 case video::ECF_A1R5G5B5: return irr::core::stringw(L"A1R5G5B5"); 1006 case video::ECF_A1R5G5B5: return irr::core::stringw(L"A1R5G5B5");
1007 case video::ECF_R5G6B5: return irr::core::stringw(L"R5G6B5"); 1007 case video::ECF_R5G6B5: return irr::core::stringw(L"R5G6B5");
1008 case video::ECF_R8G8B8: return irr::core::stringw(L"R8G8B8"); 1008 case video::ECF_R8G8B8: return irr::core::stringw(L"R8G8B8");
1009 case video::ECF_A8R8G8B8: return irr::core::stringw(L"A8R8G8B8"); 1009 case video::ECF_A8R8G8B8: return irr::core::stringw(L"A8R8G8B8");
1010 default: return irr::core::stringw(L""); 1010 default: return irr::core::stringw(L"");
1011 } 1011 }
1012} 1012}
1013 1013
1014irr::core::stringw CColladaMeshWriter::toString(const irr::video::E_TEXTURE_CLAMP clamp) const 1014irr::core::stringw CColladaMeshWriter::toString(const irr::video::E_TEXTURE_CLAMP clamp) const
1015{ 1015{
1016 switch ( clamp ) 1016 switch ( clamp )
1017 { 1017 {
1018 case video::ETC_REPEAT: 1018 case video::ETC_REPEAT:
1019 return core::stringw(L"WRAP"); 1019 return core::stringw(L"WRAP");
1020 case video::ETC_CLAMP: 1020 case video::ETC_CLAMP:
1021 case video::ETC_CLAMP_TO_EDGE: 1021 case video::ETC_CLAMP_TO_EDGE:
1022 return core::stringw(L"CLAMP"); 1022 return core::stringw(L"CLAMP");
1023 case video::ETC_CLAMP_TO_BORDER: 1023 case video::ETC_CLAMP_TO_BORDER:
1024 return core::stringw(L"BORDER"); 1024 return core::stringw(L"BORDER");
1025 case video::ETC_MIRROR: 1025 case video::ETC_MIRROR:
1026 case video::ETC_MIRROR_CLAMP: 1026 case video::ETC_MIRROR_CLAMP:
1027 case video::ETC_MIRROR_CLAMP_TO_EDGE: 1027 case video::ETC_MIRROR_CLAMP_TO_EDGE:
1028 case video::ETC_MIRROR_CLAMP_TO_BORDER: 1028 case video::ETC_MIRROR_CLAMP_TO_BORDER:
1029 return core::stringw(L"MIRROR"); 1029 return core::stringw(L"MIRROR");
1030 } 1030 }
1031 return core::stringw(L"NONE"); 1031 return core::stringw(L"NONE");
1032} 1032}
1033 1033
1034irr::core::stringw CColladaMeshWriter::toString(const irr::scene::E_COLLADA_TRANSPARENT_FX transparent) const 1034irr::core::stringw CColladaMeshWriter::toString(const irr::scene::E_COLLADA_TRANSPARENT_FX transparent) const
1035{ 1035{
1036 if ( transparent & ECOF_RGB_ZERO ) 1036 if ( transparent & ECOF_RGB_ZERO )
1037 return core::stringw(L"RGB_ZERO"); 1037 return core::stringw(L"RGB_ZERO");
1038 else 1038 else
1039 return core::stringw(L"A_ONE"); 1039 return core::stringw(L"A_ONE");
1040} 1040}
1041 1041
1042irr::core::stringw CColladaMeshWriter::toRef(const irr::core::stringw& source) const 1042irr::core::stringw CColladaMeshWriter::toRef(const irr::core::stringw& source) const
1043{ 1043{
1044 irr::core::stringw ref(L"#"); 1044 irr::core::stringw ref(L"#");
1045 ref += source; 1045 ref += source;
1046 return ref; 1046 return ref;
1047} 1047}
1048 1048
1049bool CColladaMeshWriter::isCamera(const scene::ISceneNode* node) const 1049bool CColladaMeshWriter::isCamera(const scene::ISceneNode* node) const
1050{ 1050{
1051 // TODO: we need some ISceneNode::hasType() function to get rid of those checks 1051 // TODO: we need some ISceneNode::hasType() function to get rid of those checks
1052 if ( node->getType() == ESNT_CAMERA 1052 if ( node->getType() == ESNT_CAMERA
1053 || node->getType() == ESNT_CAMERA_MAYA 1053 || node->getType() == ESNT_CAMERA_MAYA
1054 || node->getType() == ESNT_CAMERA_FPS ) 1054 || node->getType() == ESNT_CAMERA_FPS )
1055 return true; 1055 return true;
1056 return false; 1056 return false;
1057} 1057}
1058 1058
1059irr::core::stringw CColladaMeshWriter::nameForMesh(const scene::IMesh* mesh, int instance) const 1059irr::core::stringw CColladaMeshWriter::nameForMesh(const scene::IMesh* mesh, int instance) const
1060{ 1060{
1061 IColladaMeshWriterNames * nameGenerator = getNameGenerator(); 1061 IColladaMeshWriterNames * nameGenerator = getNameGenerator();
1062 if ( nameGenerator ) 1062 if ( nameGenerator )
1063 { 1063 {
1064 return nameGenerator->nameForMesh(mesh, instance); 1064 return nameGenerator->nameForMesh(mesh, instance);
1065 } 1065 }
1066 return irr::core::stringw(L"missing_name_generator"); 1066 return irr::core::stringw(L"missing_name_generator");
1067} 1067}
1068 1068
1069irr::core::stringw CColladaMeshWriter::nameForNode(const scene::ISceneNode* node) const 1069irr::core::stringw CColladaMeshWriter::nameForNode(const scene::ISceneNode* node) const
1070{ 1070{
1071 IColladaMeshWriterNames * nameGenerator = getNameGenerator(); 1071 IColladaMeshWriterNames * nameGenerator = getNameGenerator();
1072 if ( nameGenerator ) 1072 if ( nameGenerator )
1073 { 1073 {
1074 return nameGenerator->nameForNode(node); 1074 return nameGenerator->nameForNode(node);
1075 } 1075 }
1076 return irr::core::stringw(L"missing_name_generator"); 1076 return irr::core::stringw(L"missing_name_generator");
1077} 1077}
1078 1078
1079irr::core::stringw CColladaMeshWriter::nameForMaterial(const video::SMaterial & material, int materialId, const scene::IMesh* mesh, const scene::ISceneNode* node) 1079irr::core::stringw CColladaMeshWriter::nameForMaterial(const video::SMaterial & material, int materialId, const scene::IMesh* mesh, const scene::ISceneNode* node)
1080{ 1080{
1081 irr::core::stringw matName; 1081 irr::core::stringw matName;
1082 if ( getExportSMaterialsOnlyOnce() ) 1082 if ( getExportSMaterialsOnlyOnce() )
1083 { 1083 {
1084 matName = findCachedMaterialName(material); 1084 matName = findCachedMaterialName(material);
1085 if ( !matName.empty() ) 1085 if ( !matName.empty() )
1086 return matName; 1086 return matName;
1087 } 1087 }
1088 1088
1089 IColladaMeshWriterNames * nameGenerator = getNameGenerator(); 1089 IColladaMeshWriterNames * nameGenerator = getNameGenerator();
1090 if ( nameGenerator ) 1090 if ( nameGenerator )
1091 { 1091 {
1092 matName = nameGenerator->nameForMaterial(material, materialId, mesh, node); 1092 matName = nameGenerator->nameForMaterial(material, materialId, mesh, node);
1093 } 1093 }
1094 else 1094 else
1095 matName = irr::core::stringw(L"missing_name_generator"); 1095 matName = irr::core::stringw(L"missing_name_generator");
1096 1096
1097 if ( getExportSMaterialsOnlyOnce() ) 1097 if ( getExportSMaterialsOnlyOnce() )
1098 MaterialNameCache.push_back (MaterialName(material, matName)); 1098 MaterialNameCache.push_back (MaterialName(material, matName));
1099 return matName; 1099 return matName;
1100} 1100}
1101 1101
1102// Each mesh-material has one symbol which is replaced on instantiation 1102// Each mesh-material has one symbol which is replaced on instantiation
1103irr::core::stringw CColladaMeshWriter::nameForMaterialSymbol(const scene::IMesh* mesh, int materialId) const 1103irr::core::stringw CColladaMeshWriter::nameForMaterialSymbol(const scene::IMesh* mesh, int materialId) const
1104{ 1104{
1105 wchar_t buf[100]; 1105 wchar_t buf[100];
1106 swprintf(buf, 100, L"mat_symb_%p_%d", mesh, materialId); 1106 swprintf(buf, 100, L"mat_symb_%p_%d", mesh, materialId);
1107 return irr::core::stringw(buf); 1107 return irr::core::stringw(buf);
1108} 1108}
1109 1109
1110irr::core::stringw CColladaMeshWriter::findCachedMaterialName(const irr::video::SMaterial& material) const 1110irr::core::stringw CColladaMeshWriter::findCachedMaterialName(const irr::video::SMaterial& material) const
1111{ 1111{
1112 for ( u32 i=0; i<MaterialNameCache.size(); ++i ) 1112 for ( u32 i=0; i<MaterialNameCache.size(); ++i )
1113 { 1113 {
1114 if ( MaterialNameCache[i].Material == material ) 1114 if ( MaterialNameCache[i].Material == material )
1115 return MaterialNameCache[i].Name; 1115 return MaterialNameCache[i].Name;
1116 } 1116 }
1117 return irr::core::stringw(); 1117 return irr::core::stringw();
1118} 1118}
1119 1119
1120irr::core::stringw CColladaMeshWriter::minTexfilterToString(bool bilinear, bool trilinear) const 1120irr::core::stringw CColladaMeshWriter::minTexfilterToString(bool bilinear, bool trilinear) const
1121{ 1121{
1122 if ( trilinear ) 1122 if ( trilinear )
1123 return core::stringw(L"LINEAR_MIPMAP_LINEAR"); 1123 return core::stringw(L"LINEAR_MIPMAP_LINEAR");
1124 else if ( bilinear ) 1124 else if ( bilinear )
1125 return core::stringw(L"LINEAR_MIPMAP_NEAREST"); 1125 return core::stringw(L"LINEAR_MIPMAP_NEAREST");
1126 1126
1127 return core::stringw(L"NONE"); 1127 return core::stringw(L"NONE");
1128} 1128}
1129 1129
1130inline irr::core::stringw CColladaMeshWriter::magTexfilterToString(bool bilinear, bool trilinear) const 1130inline irr::core::stringw CColladaMeshWriter::magTexfilterToString(bool bilinear, bool trilinear) const
1131{ 1131{
1132 if ( bilinear || trilinear ) 1132 if ( bilinear || trilinear )
1133 return core::stringw(L"LINEAR"); 1133 return core::stringw(L"LINEAR");
1134 1134
1135 return core::stringw(L"NONE"); 1135 return core::stringw(L"NONE");
1136} 1136}
1137 1137
1138bool CColladaMeshWriter::isXmlNameStartChar(wchar_t c) const 1138bool CColladaMeshWriter::isXmlNameStartChar(wchar_t c) const
1139{ 1139{
1140 return (c >= 'A' && c <= 'Z') 1140 return (c >= 'A' && c <= 'Z')
1141 || c == L'_' 1141 || c == L'_'
1142 || (c >= 'a' && c <= 'z') 1142 || (c >= 'a' && c <= 'z')
1143 || (c >= 0xC0 && c <= 0xD6) 1143 || (c >= 0xC0 && c <= 0xD6)
1144 || (c >= 0xD8 && c <= 0xF6) 1144 || (c >= 0xD8 && c <= 0xF6)
1145 || (c >= 0xF8 && c <= 0x2FF) 1145 || (c >= 0xF8 && c <= 0x2FF)
1146 || (c >= 0x370 && c <= 0x37D) 1146 || (c >= 0x370 && c <= 0x37D)
1147 || (c >= 0x37F && c <= 0x1FFF) 1147 || (c >= 0x37F && c <= 0x1FFF)
1148 || (c >= 0x200C && c <= 0x200D) 1148 || (c >= 0x200C && c <= 0x200D)
1149 || (c >= 0x2070 && c <= 0x218F) 1149 || (c >= 0x2070 && c <= 0x218F)
1150 || (c >= 0x2C00 && c <= 0x2FEF) 1150 || (c >= 0x2C00 && c <= 0x2FEF)
1151 || (c >= 0x3001 && c <= 0xD7FF) 1151 || (c >= 0x3001 && c <= 0xD7FF)
1152 || (c >= 0xF900 && c <= 0xFDCF) 1152 || (c >= 0xF900 && c <= 0xFDCF)
1153 || (c >= 0xFDF0 && c <= 0xFFFD) 1153 || (c >= 0xFDF0 && c <= 0xFFFD)
1154#if __SIZEOF_WCHAR_T__ == 4 || __WCHAR_MAX__ > 0x10000 1154#if __SIZEOF_WCHAR_T__ == 4 || __WCHAR_MAX__ > 0x10000
1155 || (c >= 0x10000 && c <= 0xEFFFF) 1155 || (c >= 0x10000 && c <= 0xEFFFF)
1156#endif 1156#endif
1157 ; 1157 ;
1158} 1158}
1159 1159
1160bool CColladaMeshWriter::isXmlNameChar(wchar_t c) const 1160bool CColladaMeshWriter::isXmlNameChar(wchar_t c) const
1161{ 1161{
1162 return isXmlNameStartChar(c) 1162 return isXmlNameStartChar(c)
1163 || c == L'-' 1163 || c == L'-'
1164 || c == L'.' 1164 || c == L'.'
1165 || (c >= '0' && c <= '9') 1165 || (c >= '0' && c <= '9')
1166 || c == 0xB7 1166 || c == 0xB7
1167 || (c >= 0x0300 && c <= 0x036F) 1167 || (c >= 0x0300 && c <= 0x036F)
1168 || (c >= 0x203F && c <= 0x2040); 1168 || (c >= 0x203F && c <= 0x2040);
1169} 1169}
1170 1170
1171// Restrict the characters to a set of allowed characters in xs::NCName. 1171// Restrict the characters to a set of allowed characters in xs::NCName.
1172irr::core::stringw CColladaMeshWriter::toNCName(const irr::core::stringw& oldString, const irr::core::stringw& prefix) const 1172irr::core::stringw CColladaMeshWriter::toNCName(const irr::core::stringw& oldString, const irr::core::stringw& prefix) const
1173{ 1173{
1174 irr::core::stringw result(prefix); // help to ensure id starts with a valid char and reduce chance of name-conflicts 1174 irr::core::stringw result(prefix); // help to ensure id starts with a valid char and reduce chance of name-conflicts
1175 if ( oldString.empty() ) 1175 if ( oldString.empty() )
1176 return result; 1176 return result;
1177 1177
1178 result.append( oldString ); 1178 result.append( oldString );
1179 1179
1180 // We replace all characters not allowed by a replacement char 1180 // We replace all characters not allowed by a replacement char
1181 const wchar_t REPLACMENT = L'-'; 1181 const wchar_t REPLACMENT = L'-';
1182 for ( irr::u32 i=1; i < result.size(); ++i ) 1182 for ( irr::u32 i=1; i < result.size(); ++i )
1183 { 1183 {
1184 if ( result[i] == L':' || !isXmlNameChar(result[i]) ) 1184 if ( result[i] == L':' || !isXmlNameChar(result[i]) )
1185 { 1185 {
1186 result[i] = REPLACMENT; 1186 result[i] = REPLACMENT;
1187 } 1187 }
1188 } 1188 }
1189 return result; 1189 return result;
1190} 1190}
1191 1191
1192// Restrict the characters to a set of allowed characters in xs::NCName. 1192// Restrict the characters to a set of allowed characters in xs::NCName.
1193irr::core::stringw CColladaMeshWriter::pathToURI(const irr::io::path& path) const 1193irr::core::stringw CColladaMeshWriter::pathToURI(const irr::io::path& path) const
1194{ 1194{
1195 irr::core::stringw result; 1195 irr::core::stringw result;
1196 1196
1197 // is this a relative path? 1197 // is this a relative path?
1198 if ( path.size() > 1 1198 if ( path.size() > 1
1199 && path[0] != _IRR_TEXT('/') 1199 && path[0] != _IRR_TEXT('/')
1200 && path[0] != _IRR_TEXT('\\') 1200 && path[0] != _IRR_TEXT('\\')
1201 && path[1] != _IRR_TEXT(':') ) 1201 && path[1] != _IRR_TEXT(':') )
1202 { 1202 {
1203 // not already starting with "./" ? 1203 // not already starting with "./" ?
1204 if ( path[0] != _IRR_TEXT('.') 1204 if ( path[0] != _IRR_TEXT('.')
1205 || path[1] != _IRR_TEXT('/') ) 1205 || path[1] != _IRR_TEXT('/') )
1206 { 1206 {
1207 result.append(L"./"); 1207 result.append(L"./");
1208 } 1208 }
1209 } 1209 }
1210 result.append(path); 1210 result.append(path);
1211 1211
1212 // TODO: make correct URI (without whitespaces) 1212 // TODO: make correct URI (without whitespaces)
1213 1213
1214 return result; 1214 return result;
1215} 1215}
1216 1216
1217void CColladaMeshWriter::writeAsset() 1217void CColladaMeshWriter::writeAsset()
1218{ 1218{
1219 Writer->writeElement(L"asset", false); 1219 Writer->writeElement(L"asset", false);
1220 Writer->writeLineBreak(); 1220 Writer->writeLineBreak();
1221 1221
1222 Writer->writeElement(L"contributor", false); 1222 Writer->writeElement(L"contributor", false);
1223 Writer->writeLineBreak(); 1223 Writer->writeLineBreak();
1224 Writer->writeElement(L"authoring_tool", false); 1224 Writer->writeElement(L"authoring_tool", false);
1225 Writer->writeText(L"Irrlicht Engine / irrEdit"); // this code has originated from irrEdit 0.7 1225 Writer->writeText(L"Irrlicht Engine / irrEdit"); // this code has originated from irrEdit 0.7
1226 Writer->writeClosingTag(L"authoring_tool"); 1226 Writer->writeClosingTag(L"authoring_tool");
1227 Writer->writeLineBreak(); 1227 Writer->writeLineBreak();
1228 Writer->writeClosingTag(L"contributor"); 1228 Writer->writeClosingTag(L"contributor");
1229 Writer->writeLineBreak(); 1229 Writer->writeLineBreak();
1230 1230
1231 // The next two are required 1231 // The next two are required
1232 Writer->writeElement(L"created", false); 1232 Writer->writeElement(L"created", false);
1233 Writer->writeText(L"2008-01-31T00:00:00Z"); 1233 Writer->writeText(L"2008-01-31T00:00:00Z");
1234 Writer->writeClosingTag(L"created"); 1234 Writer->writeClosingTag(L"created");
1235 Writer->writeLineBreak(); 1235 Writer->writeLineBreak();
1236 1236
1237 Writer->writeElement(L"modified", false); 1237 Writer->writeElement(L"modified", false);
1238 Writer->writeText(L"2008-01-31T00:00:00Z"); 1238 Writer->writeText(L"2008-01-31T00:00:00Z");
1239 Writer->writeClosingTag(L"modified"); 1239 Writer->writeClosingTag(L"modified");
1240 Writer->writeLineBreak(); 1240 Writer->writeLineBreak();
1241 1241
1242 Writer->writeElement(L"revision", false); 1242 Writer->writeElement(L"revision", false);
1243 Writer->writeText(L"1.0"); 1243 Writer->writeText(L"1.0");
1244 Writer->writeClosingTag(L"revision"); 1244 Writer->writeClosingTag(L"revision");
1245 Writer->writeLineBreak(); 1245 Writer->writeLineBreak();
1246 1246
1247 Writer->writeClosingTag(L"asset"); 1247 Writer->writeClosingTag(L"asset");
1248 Writer->writeLineBreak(); 1248 Writer->writeLineBreak();
1249} 1249}
1250 1250
1251void CColladaMeshWriter::writeMeshMaterials(scene::IMesh* mesh, irr::core::array<irr::core::stringw> * materialNamesOut) 1251void CColladaMeshWriter::writeMeshMaterials(scene::IMesh* mesh, irr::core::array<irr::core::stringw> * materialNamesOut)
1252{ 1252{
1253 u32 i; 1253 u32 i;
1254 for (i=0; i<mesh->getMeshBufferCount(); ++i) 1254 for (i=0; i<mesh->getMeshBufferCount(); ++i)
1255 { 1255 {
1256 video::SMaterial & material = mesh->getMeshBuffer(i)->getMaterial(); 1256 video::SMaterial & material = mesh->getMeshBuffer(i)->getMaterial();
1257 core::stringw strMat(nameForMaterial(material, i, mesh, NULL)); 1257 core::stringw strMat(nameForMaterial(material, i, mesh, NULL));
1258 writeMaterial(strMat); 1258 writeMaterial(strMat);
1259 if ( materialNamesOut ) 1259 if ( materialNamesOut )
1260 materialNamesOut->push_back(strMat); 1260 materialNamesOut->push_back(strMat);
1261 } 1261 }
1262} 1262}
1263 1263
1264void CColladaMeshWriter::writeMaterialEffect(const irr::core::stringw& materialfxname, const video::SMaterial & material) 1264void CColladaMeshWriter::writeMaterialEffect(const irr::core::stringw& materialfxname, const video::SMaterial & material)
1265{ 1265{
1266 if ( EffectsWritten.find(materialfxname) ) 1266 if ( EffectsWritten.find(materialfxname) )
1267 return; 1267 return;
1268 EffectsWritten.insert(materialfxname, true); 1268 EffectsWritten.insert(materialfxname, true);
1269 1269
1270 Writer->writeElement(L"effect", false, 1270 Writer->writeElement(L"effect", false,
1271 L"id", materialfxname.c_str(), 1271 L"id", materialfxname.c_str(),
1272 L"name", materialfxname.c_str()); 1272 L"name", materialfxname.c_str());
1273 Writer->writeLineBreak(); 1273 Writer->writeLineBreak();
1274 Writer->writeElement(L"profile_COMMON", false); 1274 Writer->writeElement(L"profile_COMMON", false);
1275 Writer->writeLineBreak(); 1275 Writer->writeLineBreak();
1276 1276
1277 int numTextures = 0; 1277 int numTextures = 0;
1278 if ( getWriteTextures() ) 1278 if ( getWriteTextures() )
1279 { 1279 {
1280 // write texture surfaces and samplers and buffer all used imagess 1280 // write texture surfaces and samplers and buffer all used imagess
1281 for ( int t=0; t<4; ++t ) 1281 for ( int t=0; t<4; ++t )
1282 { 1282 {
1283 const video::SMaterialLayer& layer = material.TextureLayer[t]; 1283 const video::SMaterialLayer& layer = material.TextureLayer[t];
1284 if ( !layer.Texture ) 1284 if ( !layer.Texture )
1285 break; 1285 break;
1286 ++numTextures; 1286 ++numTextures;
1287 1287
1288 if ( LibraryImages.linear_search(layer.Texture) < 0 ) 1288 if ( LibraryImages.linear_search(layer.Texture) < 0 )
1289 LibraryImages.push_back( layer.Texture ); 1289 LibraryImages.push_back( layer.Texture );
1290 1290
1291 irr::core::stringw texName("tex"); 1291 irr::core::stringw texName("tex");
1292 texName += irr::core::stringw(t); 1292 texName += irr::core::stringw(t);
1293 1293
1294 // write texture surface 1294 // write texture surface
1295 //<newparam sid="tex0-surface"> 1295 //<newparam sid="tex0-surface">
1296 irr::core::stringw texSurface(texName); 1296 irr::core::stringw texSurface(texName);
1297 texSurface += L"-surface"; 1297 texSurface += L"-surface";
1298 Writer->writeElement(L"newparam", false, L"sid", texSurface.c_str()); 1298 Writer->writeElement(L"newparam", false, L"sid", texSurface.c_str());
1299 Writer->writeLineBreak(); 1299 Writer->writeLineBreak();
1300 // <surface type="2D"> 1300 // <surface type="2D">
1301 Writer->writeElement(L"surface", false, L"type", L"2D"); 1301 Writer->writeElement(L"surface", false, L"type", L"2D");
1302 Writer->writeLineBreak(); 1302 Writer->writeLineBreak();
1303 1303
1304 // <init_from>internal_texturename</init_from> 1304 // <init_from>internal_texturename</init_from>
1305 Writer->writeElement(L"init_from", false); 1305 Writer->writeElement(L"init_from", false);
1306 irr::io::path p(FileSystem->getRelativeFilename(layer.Texture->getName().getPath(), Directory)); 1306 irr::io::path p(FileSystem->getRelativeFilename(layer.Texture->getName().getPath(), Directory));
1307 Writer->writeText(toNCName(irr::core::stringw(p)).c_str()); 1307 Writer->writeText(toNCName(irr::core::stringw(p)).c_str());
1308 Writer->writeClosingTag(L"init_from"); 1308 Writer->writeClosingTag(L"init_from");
1309 Writer->writeLineBreak(); 1309 Writer->writeLineBreak();
1310 1310
1311 // <format>A8R8G8B8</format> 1311 // <format>A8R8G8B8</format>
1312 Writer->writeElement(L"format", false); 1312 Writer->writeElement(L"format", false);
1313 video::ECOLOR_FORMAT format = layer.Texture->getColorFormat(); 1313 video::ECOLOR_FORMAT format = layer.Texture->getColorFormat();
1314 Writer->writeText(toString(format).c_str()); 1314 Writer->writeText(toString(format).c_str());
1315 Writer->writeClosingTag(L"format"); 1315 Writer->writeClosingTag(L"format");
1316 Writer->writeLineBreak(); 1316 Writer->writeLineBreak();
1317 // </surface> 1317 // </surface>
1318 Writer->writeClosingTag(L"surface"); 1318 Writer->writeClosingTag(L"surface");
1319 Writer->writeLineBreak(); 1319 Writer->writeLineBreak();
1320 // </newparam> 1320 // </newparam>
1321 Writer->writeClosingTag(L"newparam"); 1321 Writer->writeClosingTag(L"newparam");
1322 Writer->writeLineBreak(); 1322 Writer->writeLineBreak();
1323 1323
1324 // write texture sampler 1324 // write texture sampler
1325 // <newparam sid="tex0-sampler"> 1325 // <newparam sid="tex0-sampler">
1326 irr::core::stringw texSampler(texName); 1326 irr::core::stringw texSampler(texName);
1327 texSampler += L"-sampler"; 1327 texSampler += L"-sampler";
1328 Writer->writeElement(L"newparam", false, L"sid", texSampler.c_str()); 1328 Writer->writeElement(L"newparam", false, L"sid", texSampler.c_str());
1329 Writer->writeLineBreak(); 1329 Writer->writeLineBreak();
1330 // <sampler2D> 1330 // <sampler2D>
1331 Writer->writeElement(L"sampler2D", false); 1331 Writer->writeElement(L"sampler2D", false);
1332 Writer->writeLineBreak(); 1332 Writer->writeLineBreak();
1333 1333
1334 // <source>tex0-surface</source> 1334 // <source>tex0-surface</source>
1335 Writer->writeElement(L"source", false); 1335 Writer->writeElement(L"source", false);
1336 Writer->writeText(texSurface.c_str()); 1336 Writer->writeText(texSurface.c_str());
1337 Writer->writeClosingTag(L"source"); 1337 Writer->writeClosingTag(L"source");
1338 Writer->writeLineBreak(); 1338 Writer->writeLineBreak();
1339 1339
1340 // <wrap_s>WRAP</wrap_s> 1340 // <wrap_s>WRAP</wrap_s>
1341 Writer->writeElement(L"wrap_s", false); 1341 Writer->writeElement(L"wrap_s", false);
1342 Writer->writeText(toString((video::E_TEXTURE_CLAMP)layer.TextureWrapU).c_str()); 1342 Writer->writeText(toString((video::E_TEXTURE_CLAMP)layer.TextureWrapU).c_str());
1343 Writer->writeClosingTag(L"wrap_s"); 1343 Writer->writeClosingTag(L"wrap_s");
1344 Writer->writeLineBreak(); 1344 Writer->writeLineBreak();
1345 1345
1346 // <wrap_t>WRAP</wrap_t> 1346 // <wrap_t>WRAP</wrap_t>
1347 Writer->writeElement(L"wrap_t", false); 1347 Writer->writeElement(L"wrap_t", false);
1348 Writer->writeText(toString((video::E_TEXTURE_CLAMP)layer.TextureWrapV).c_str()); 1348 Writer->writeText(toString((video::E_TEXTURE_CLAMP)layer.TextureWrapV).c_str());
1349 Writer->writeClosingTag(L"wrap_t"); 1349 Writer->writeClosingTag(L"wrap_t");
1350 Writer->writeLineBreak(); 1350 Writer->writeLineBreak();
1351 1351
1352 // <minfilter>LINEAR_MIPMAP_LINEAR</minfilter> 1352 // <minfilter>LINEAR_MIPMAP_LINEAR</minfilter>
1353 Writer->writeElement(L"minfilter", false); 1353 Writer->writeElement(L"minfilter", false);
1354 Writer->writeText(minTexfilterToString(layer.BilinearFilter, layer.TrilinearFilter).c_str()); 1354 Writer->writeText(minTexfilterToString(layer.BilinearFilter, layer.TrilinearFilter).c_str());
1355 Writer->writeClosingTag(L"minfilter"); 1355 Writer->writeClosingTag(L"minfilter");
1356 Writer->writeLineBreak(); 1356 Writer->writeLineBreak();
1357 1357
1358 // <magfilter>LINEAR</magfilter> 1358 // <magfilter>LINEAR</magfilter>
1359 Writer->writeElement(L"magfilter", false); 1359 Writer->writeElement(L"magfilter", false);
1360 Writer->writeText(magTexfilterToString(layer.BilinearFilter, layer.TrilinearFilter).c_str()); 1360 Writer->writeText(magTexfilterToString(layer.BilinearFilter, layer.TrilinearFilter).c_str());
1361 Writer->writeClosingTag(L"magfilter"); 1361 Writer->writeClosingTag(L"magfilter");
1362 Writer->writeLineBreak(); 1362 Writer->writeLineBreak();
1363 1363
1364 // TBD - actually not sure how anisotropic should be written, so for now it writes in a way 1364 // TBD - actually not sure how anisotropic should be written, so for now it writes in a way
1365 // that works with the way the loader reads it again. 1365 // that works with the way the loader reads it again.
1366 if ( layer.AnisotropicFilter ) 1366 if ( layer.AnisotropicFilter )
1367 { 1367 {
1368 // <mipfilter>LINEAR_MIPMAP_LINEAR</mipfilter> 1368 // <mipfilter>LINEAR_MIPMAP_LINEAR</mipfilter>
1369 Writer->writeElement(L"mipfilter", false); 1369 Writer->writeElement(L"mipfilter", false);
1370 Writer->writeText(L"LINEAR_MIPMAP_LINEAR"); 1370 Writer->writeText(L"LINEAR_MIPMAP_LINEAR");
1371 Writer->writeClosingTag(L"mipfilter"); 1371 Writer->writeClosingTag(L"mipfilter");
1372 Writer->writeLineBreak(); 1372 Writer->writeLineBreak();
1373 } 1373 }
1374 1374
1375 // </sampler2D> 1375 // </sampler2D>
1376 Writer->writeClosingTag(L"sampler2D"); 1376 Writer->writeClosingTag(L"sampler2D");
1377 Writer->writeLineBreak(); 1377 Writer->writeLineBreak();
1378 // </newparam> 1378 // </newparam>
1379 Writer->writeClosingTag(L"newparam"); 1379 Writer->writeClosingTag(L"newparam");
1380 Writer->writeLineBreak(); 1380 Writer->writeLineBreak();
1381 } 1381 }
1382 } 1382 }
1383 1383
1384 Writer->writeElement(L"technique", false, L"sid", L"common"); 1384 Writer->writeElement(L"technique", false, L"sid", L"common");
1385 Writer->writeLineBreak(); 1385 Writer->writeLineBreak();
1386 1386
1387 E_COLLADA_TECHNIQUE_FX techFx = getProperties() ? getProperties()->getTechniqueFx(material) : ECTF_BLINN; 1387 E_COLLADA_TECHNIQUE_FX techFx = getProperties() ? getProperties()->getTechniqueFx(material) : ECTF_BLINN;
1388 writeFxElement(material, techFx); 1388 writeFxElement(material, techFx);
1389 1389
1390 Writer->writeClosingTag(L"technique"); 1390 Writer->writeClosingTag(L"technique");
1391 Writer->writeLineBreak(); 1391 Writer->writeLineBreak();
1392 Writer->writeClosingTag(L"profile_COMMON"); 1392 Writer->writeClosingTag(L"profile_COMMON");
1393 Writer->writeLineBreak(); 1393 Writer->writeLineBreak();
1394 Writer->writeClosingTag(L"effect"); 1394 Writer->writeClosingTag(L"effect");
1395 Writer->writeLineBreak(); 1395 Writer->writeLineBreak();
1396} 1396}
1397 1397
1398void CColladaMeshWriter::writeMeshEffects(scene::IMesh* mesh) 1398void CColladaMeshWriter::writeMeshEffects(scene::IMesh* mesh)
1399{ 1399{
1400 for (u32 i=0; i<mesh->getMeshBufferCount(); ++i) 1400 for (u32 i=0; i<mesh->getMeshBufferCount(); ++i)
1401 { 1401 {
1402 video::SMaterial & material = mesh->getMeshBuffer(i)->getMaterial(); 1402 video::SMaterial & material = mesh->getMeshBuffer(i)->getMaterial();
1403 irr::core::stringw materialfxname(nameForMaterial(material, i, mesh, NULL)); 1403 irr::core::stringw materialfxname(nameForMaterial(material, i, mesh, NULL));
1404 materialfxname += L"-fx"; 1404 materialfxname += L"-fx";
1405 writeMaterialEffect(materialfxname, material); 1405 writeMaterialEffect(materialfxname, material);
1406 } 1406 }
1407} 1407}
1408 1408
1409void CColladaMeshWriter::writeMeshGeometry(const irr::core::stringw& meshname, scene::IMesh* mesh) 1409void CColladaMeshWriter::writeMeshGeometry(const irr::core::stringw& meshname, scene::IMesh* mesh)
1410{ 1410{
1411 core::stringw meshId(meshname); 1411 core::stringw meshId(meshname);
1412 1412
1413 Writer->writeElement(L"geometry", false, L"id", meshId.c_str(), L"name", meshId.c_str()); 1413 Writer->writeElement(L"geometry", false, L"id", meshId.c_str(), L"name", meshId.c_str());
1414 Writer->writeLineBreak(); 1414 Writer->writeLineBreak();
1415 Writer->writeElement(L"mesh"); 1415 Writer->writeElement(L"mesh");
1416 Writer->writeLineBreak(); 1416 Writer->writeLineBreak();
1417 1417
1418 // do some statistics for the mesh to know which stuff needs to be saved into 1418 // do some statistics for the mesh to know which stuff needs to be saved into
1419 // the file: 1419 // the file:
1420 // - count vertices 1420 // - count vertices
1421 // - check for the need of a second texture coordinate 1421 // - check for the need of a second texture coordinate
1422 // - count amount of second texture coordinates 1422 // - count amount of second texture coordinates
1423 // - check for the need of tangents (TODO) 1423 // - check for the need of tangents (TODO)
1424 1424
1425 u32 totalVertexCount = 0; 1425 u32 totalVertexCount = 0;
1426 u32 totalTCoords2Count = 0; 1426 u32 totalTCoords2Count = 0;
1427 bool needsTangents = false; // TODO: tangents not supported here yet 1427 bool needsTangents = false; // TODO: tangents not supported here yet
1428 u32 i=0; 1428 u32 i=0;
1429 for (i=0; i<mesh->getMeshBufferCount(); ++i) 1429 for (i=0; i<mesh->getMeshBufferCount(); ++i)
1430 { 1430 {
1431 totalVertexCount += mesh->getMeshBuffer(i)->getVertexCount(); 1431 totalVertexCount += mesh->getMeshBuffer(i)->getVertexCount();
1432 1432
1433 if (hasSecondTextureCoordinates(mesh->getMeshBuffer(i)->getVertexType())) 1433 if (hasSecondTextureCoordinates(mesh->getMeshBuffer(i)->getVertexType()))
1434 totalTCoords2Count += mesh->getMeshBuffer(i)->getVertexCount(); 1434 totalTCoords2Count += mesh->getMeshBuffer(i)->getVertexCount();
1435 1435
1436 if (!needsTangents) 1436 if (!needsTangents)
1437 needsTangents = mesh->getMeshBuffer(i)->getVertexType() == video::EVT_TANGENTS; 1437 needsTangents = mesh->getMeshBuffer(i)->getVertexType() == video::EVT_TANGENTS;
1438 } 1438 }
1439 1439
1440 SComponentGlobalStartPos* globalIndices = new SComponentGlobalStartPos[mesh->getMeshBufferCount()]; 1440 SComponentGlobalStartPos* globalIndices = new SComponentGlobalStartPos[mesh->getMeshBufferCount()];
1441 1441
1442 // write positions 1442 // write positions
1443 core::stringw meshPosId(meshId); 1443 core::stringw meshPosId(meshId);
1444 meshPosId += L"-Pos"; 1444 meshPosId += L"-Pos";
1445 Writer->writeElement(L"source", false, L"id", meshPosId.c_str()); 1445 Writer->writeElement(L"source", false, L"id", meshPosId.c_str());
1446 Writer->writeLineBreak(); 1446 Writer->writeLineBreak();
1447 1447
1448 core::stringw vertexCountStr(totalVertexCount*3); 1448 core::stringw vertexCountStr(totalVertexCount*3);
1449 core::stringw meshPosArrayId(meshPosId); 1449 core::stringw meshPosArrayId(meshPosId);
1450 meshPosArrayId += L"-array"; 1450 meshPosArrayId += L"-array";
1451 Writer->writeElement(L"float_array", false, L"id", meshPosArrayId.c_str(), 1451 Writer->writeElement(L"float_array", false, L"id", meshPosArrayId.c_str(),
1452 L"count", vertexCountStr.c_str()); 1452 L"count", vertexCountStr.c_str());
1453 Writer->writeLineBreak(); 1453 Writer->writeLineBreak();
1454 1454
1455 for (i=0; i<mesh->getMeshBufferCount(); ++i) 1455 for (i=0; i<mesh->getMeshBufferCount(); ++i)
1456 { 1456 {
1457 scene::IMeshBuffer* buffer = mesh->getMeshBuffer(i); 1457 scene::IMeshBuffer* buffer = mesh->getMeshBuffer(i);
1458 video::E_VERTEX_TYPE vtxType = buffer->getVertexType(); 1458 video::E_VERTEX_TYPE vtxType = buffer->getVertexType();
1459 u32 vertexCount = buffer->getVertexCount(); 1459 u32 vertexCount = buffer->getVertexCount();
1460 1460
1461 globalIndices[i].PosStartIndex = 0; 1461 globalIndices[i].PosStartIndex = 0;
1462 1462
1463 if (i!=0) 1463 if (i!=0)
1464 globalIndices[i].PosStartIndex = globalIndices[i-1].PosLastIndex + 1; 1464 globalIndices[i].PosStartIndex = globalIndices[i-1].PosLastIndex + 1;
1465 1465
1466 globalIndices[i].PosLastIndex = globalIndices[i].PosStartIndex + vertexCount - 1; 1466 globalIndices[i].PosLastIndex = globalIndices[i].PosStartIndex + vertexCount - 1;
1467 1467
1468 switch(vtxType) 1468 switch(vtxType)
1469 { 1469 {
1470 case video::EVT_STANDARD: 1470 case video::EVT_STANDARD:
1471 { 1471 {
1472 video::S3DVertex* vtx = (video::S3DVertex*)buffer->getVertices(); 1472 video::S3DVertex* vtx = (video::S3DVertex*)buffer->getVertices();
1473 for (u32 j=0; j<vertexCount; ++j) 1473 for (u32 j=0; j<vertexCount; ++j)
1474 { 1474 {
1475 writeVector(vtx[j].Pos); 1475 writeVector(vtx[j].Pos);
1476 Writer->writeLineBreak(); 1476 Writer->writeLineBreak();
1477 } 1477 }
1478 } 1478 }
1479 break; 1479 break;
1480 case video::EVT_2TCOORDS: 1480 case video::EVT_2TCOORDS:
1481 { 1481 {
1482 video::S3DVertex2TCoords* vtx = (video::S3DVertex2TCoords*)buffer->getVertices(); 1482 video::S3DVertex2TCoords* vtx = (video::S3DVertex2TCoords*)buffer->getVertices();
1483 for (u32 j=0; j<vertexCount; ++j) 1483 for (u32 j=0; j<vertexCount; ++j)
1484 { 1484 {
1485 writeVector(vtx[j].Pos); 1485 writeVector(vtx[j].Pos);
1486 Writer->writeLineBreak(); 1486 Writer->writeLineBreak();
1487 } 1487 }
1488 } 1488 }
1489 break; 1489 break;
1490 case video::EVT_TANGENTS: 1490 case video::EVT_TANGENTS:
1491 { 1491 {
1492 video::S3DVertexTangents* vtx = (video::S3DVertexTangents*)buffer->getVertices(); 1492 video::S3DVertexTangents* vtx = (video::S3DVertexTangents*)buffer->getVertices();
1493 for (u32 j=0; j<vertexCount; ++j) 1493 for (u32 j=0; j<vertexCount; ++j)
1494 { 1494 {
1495 writeVector(vtx[j].Pos); 1495 writeVector(vtx[j].Pos);
1496 Writer->writeLineBreak(); 1496 Writer->writeLineBreak();
1497 } 1497 }
1498 } 1498 }
1499 break; 1499 break;
1500 } 1500 }
1501 } 1501 }
1502 1502
1503 Writer->writeClosingTag(L"float_array"); 1503 Writer->writeClosingTag(L"float_array");
1504 Writer->writeLineBreak(); 1504 Writer->writeLineBreak();
1505 1505
1506 Writer->writeElement(L"technique_common", false); 1506 Writer->writeElement(L"technique_common", false);
1507 Writer->writeLineBreak(); 1507 Writer->writeLineBreak();
1508 1508
1509 vertexCountStr = core::stringw(totalVertexCount); 1509 vertexCountStr = core::stringw(totalVertexCount);
1510 1510
1511 Writer->writeElement(L"accessor", false, L"source", toRef(meshPosArrayId).c_str(), 1511 Writer->writeElement(L"accessor", false, L"source", toRef(meshPosArrayId).c_str(),
1512 L"count", vertexCountStr.c_str(), L"stride", L"3"); 1512 L"count", vertexCountStr.c_str(), L"stride", L"3");
1513 Writer->writeLineBreak(); 1513 Writer->writeLineBreak();
1514 1514
1515 Writer->writeElement(L"param", true, L"name", L"X", L"type", L"float"); 1515 Writer->writeElement(L"param", true, L"name", L"X", L"type", L"float");
1516 Writer->writeLineBreak(); 1516 Writer->writeLineBreak();
1517 Writer->writeElement(L"param", true, L"name", L"Y", L"type", L"float"); 1517 Writer->writeElement(L"param", true, L"name", L"Y", L"type", L"float");
1518 Writer->writeLineBreak(); 1518 Writer->writeLineBreak();
1519 Writer->writeElement(L"param", true, L"name", L"Z", L"type", L"float"); 1519 Writer->writeElement(L"param", true, L"name", L"Z", L"type", L"float");
1520 Writer->writeLineBreak(); 1520 Writer->writeLineBreak();
1521 1521
1522 Writer->writeClosingTag(L"accessor"); 1522 Writer->writeClosingTag(L"accessor");
1523 Writer->writeLineBreak(); 1523 Writer->writeLineBreak();
1524 1524
1525 Writer->writeClosingTag(L"technique_common"); 1525 Writer->writeClosingTag(L"technique_common");
1526 Writer->writeLineBreak(); 1526 Writer->writeLineBreak();
1527 1527
1528 Writer->writeClosingTag(L"source"); 1528 Writer->writeClosingTag(L"source");
1529 Writer->writeLineBreak(); 1529 Writer->writeLineBreak();
1530 1530
1531 // write texture coordinates 1531 // write texture coordinates
1532 1532
1533 core::stringw meshTexCoord0Id(meshId); 1533 core::stringw meshTexCoord0Id(meshId);
1534 meshTexCoord0Id += L"-TexCoord0"; 1534 meshTexCoord0Id += L"-TexCoord0";
1535 Writer->writeElement(L"source", false, L"id", meshTexCoord0Id.c_str()); 1535 Writer->writeElement(L"source", false, L"id", meshTexCoord0Id.c_str());
1536 Writer->writeLineBreak(); 1536 Writer->writeLineBreak();
1537 1537
1538 vertexCountStr = core::stringw(totalVertexCount*2); 1538 vertexCountStr = core::stringw(totalVertexCount*2);
1539 core::stringw meshTexCoordArrayId(meshTexCoord0Id); 1539 core::stringw meshTexCoordArrayId(meshTexCoord0Id);
1540 meshTexCoordArrayId += L"-array"; 1540 meshTexCoordArrayId += L"-array";
1541 Writer->writeElement(L"float_array", false, L"id", meshTexCoordArrayId.c_str(), 1541 Writer->writeElement(L"float_array", false, L"id", meshTexCoordArrayId.c_str(),
1542 L"count", vertexCountStr.c_str()); 1542 L"count", vertexCountStr.c_str());
1543 Writer->writeLineBreak(); 1543 Writer->writeLineBreak();
1544 1544
1545 for (i=0; i<mesh->getMeshBufferCount(); ++i) 1545 for (i=0; i<mesh->getMeshBufferCount(); ++i)
1546 { 1546 {
1547 scene::IMeshBuffer* buffer = mesh->getMeshBuffer(i); 1547 scene::IMeshBuffer* buffer = mesh->getMeshBuffer(i);
1548 video::E_VERTEX_TYPE vtxType = buffer->getVertexType(); 1548 video::E_VERTEX_TYPE vtxType = buffer->getVertexType();
1549 u32 vertexCount = buffer->getVertexCount(); 1549 u32 vertexCount = buffer->getVertexCount();
1550 1550
1551 globalIndices[i].TCoord0StartIndex = 0; 1551 globalIndices[i].TCoord0StartIndex = 0;
1552 1552
1553 if (i!=0) 1553 if (i!=0)
1554 globalIndices[i].TCoord0StartIndex = globalIndices[i-1].TCoord0LastIndex + 1; 1554 globalIndices[i].TCoord0StartIndex = globalIndices[i-1].TCoord0LastIndex + 1;
1555 1555
1556 globalIndices[i].TCoord0LastIndex = globalIndices[i].TCoord0StartIndex + vertexCount - 1; 1556 globalIndices[i].TCoord0LastIndex = globalIndices[i].TCoord0StartIndex + vertexCount - 1;
1557 1557
1558 switch(vtxType) 1558 switch(vtxType)
1559 { 1559 {
1560 case video::EVT_STANDARD: 1560 case video::EVT_STANDARD:
1561 { 1561 {
1562 video::S3DVertex* vtx = (video::S3DVertex*)buffer->getVertices(); 1562 video::S3DVertex* vtx = (video::S3DVertex*)buffer->getVertices();
1563 for (u32 j=0; j<vertexCount; ++j) 1563 for (u32 j=0; j<vertexCount; ++j)
1564 { 1564 {
1565 writeUv(vtx[j].TCoords); 1565 writeUv(vtx[j].TCoords);
1566 Writer->writeLineBreak(); 1566 Writer->writeLineBreak();
1567 } 1567 }
1568 } 1568 }
1569 break; 1569 break;
1570 case video::EVT_2TCOORDS: 1570 case video::EVT_2TCOORDS:
1571 { 1571 {
1572 video::S3DVertex2TCoords* vtx = (video::S3DVertex2TCoords*)buffer->getVertices(); 1572 video::S3DVertex2TCoords* vtx = (video::S3DVertex2TCoords*)buffer->getVertices();
1573 for (u32 j=0; j<vertexCount; ++j) 1573 for (u32 j=0; j<vertexCount; ++j)
1574 { 1574 {
1575 writeUv(vtx[j].TCoords); 1575 writeUv(vtx[j].TCoords);
1576 Writer->writeLineBreak(); 1576 Writer->writeLineBreak();
1577 } 1577 }
1578 } 1578 }
1579 break; 1579 break;
1580 case video::EVT_TANGENTS: 1580 case video::EVT_TANGENTS:
1581 { 1581 {
1582 video::S3DVertexTangents* vtx = (video::S3DVertexTangents*)buffer->getVertices(); 1582 video::S3DVertexTangents* vtx = (video::S3DVertexTangents*)buffer->getVertices();
1583 for (u32 j=0; j<vertexCount; ++j) 1583 for (u32 j=0; j<vertexCount; ++j)
1584 { 1584 {
1585 writeUv(vtx[j].TCoords); 1585 writeUv(vtx[j].TCoords);
1586 Writer->writeLineBreak(); 1586 Writer->writeLineBreak();
1587 } 1587 }
1588 } 1588 }
1589 break; 1589 break;
1590 } 1590 }
1591 } 1591 }
1592 1592
1593 Writer->writeClosingTag(L"float_array"); 1593 Writer->writeClosingTag(L"float_array");
1594 Writer->writeLineBreak(); 1594 Writer->writeLineBreak();
1595 1595
1596 Writer->writeElement(L"technique_common", false); 1596 Writer->writeElement(L"technique_common", false);
1597 Writer->writeLineBreak(); 1597 Writer->writeLineBreak();
1598 1598
1599 vertexCountStr = core::stringw(totalVertexCount); 1599 vertexCountStr = core::stringw(totalVertexCount);
1600 1600
1601 Writer->writeElement(L"accessor", false, L"source", toRef(meshTexCoordArrayId).c_str(), 1601 Writer->writeElement(L"accessor", false, L"source", toRef(meshTexCoordArrayId).c_str(),
1602 L"count", vertexCountStr.c_str(), L"stride", L"2"); 1602 L"count", vertexCountStr.c_str(), L"stride", L"2");
1603 Writer->writeLineBreak(); 1603 Writer->writeLineBreak();
1604 1604
1605 Writer->writeElement(L"param", true, L"name", L"U", L"type", L"float"); 1605 Writer->writeElement(L"param", true, L"name", L"U", L"type", L"float");
1606 Writer->writeLineBreak(); 1606 Writer->writeLineBreak();
1607 Writer->writeElement(L"param", true, L"name", L"V", L"type", L"float"); 1607 Writer->writeElement(L"param", true, L"name", L"V", L"type", L"float");
1608 Writer->writeLineBreak(); 1608 Writer->writeLineBreak();
1609 1609
1610 Writer->writeClosingTag(L"accessor"); 1610 Writer->writeClosingTag(L"accessor");
1611 Writer->writeLineBreak(); 1611 Writer->writeLineBreak();
1612 1612
1613 Writer->writeClosingTag(L"technique_common"); 1613 Writer->writeClosingTag(L"technique_common");
1614 Writer->writeLineBreak(); 1614 Writer->writeLineBreak();
1615 1615
1616 Writer->writeClosingTag(L"source"); 1616 Writer->writeClosingTag(L"source");
1617 Writer->writeLineBreak(); 1617 Writer->writeLineBreak();
1618 1618
1619 // write normals 1619 // write normals
1620 core::stringw meshNormalId(meshId); 1620 core::stringw meshNormalId(meshId);
1621 meshNormalId += L"-Normal"; 1621 meshNormalId += L"-Normal";
1622 Writer->writeElement(L"source", false, L"id", meshNormalId.c_str()); 1622 Writer->writeElement(L"source", false, L"id", meshNormalId.c_str());
1623 Writer->writeLineBreak(); 1623 Writer->writeLineBreak();
1624 1624
1625 vertexCountStr = core::stringw(totalVertexCount*3); 1625 vertexCountStr = core::stringw(totalVertexCount*3);
1626 core::stringw meshNormalArrayId(meshNormalId); 1626 core::stringw meshNormalArrayId(meshNormalId);
1627 meshNormalArrayId += L"-array"; 1627 meshNormalArrayId += L"-array";
1628 Writer->writeElement(L"float_array", false, L"id", meshNormalArrayId.c_str(), 1628 Writer->writeElement(L"float_array", false, L"id", meshNormalArrayId.c_str(),
1629 L"count", vertexCountStr.c_str()); 1629 L"count", vertexCountStr.c_str());
1630 Writer->writeLineBreak(); 1630 Writer->writeLineBreak();
1631 1631
1632 for (i=0; i<mesh->getMeshBufferCount(); ++i) 1632 for (i=0; i<mesh->getMeshBufferCount(); ++i)
1633 { 1633 {
1634 scene::IMeshBuffer* buffer = mesh->getMeshBuffer(i); 1634 scene::IMeshBuffer* buffer = mesh->getMeshBuffer(i);
1635 video::E_VERTEX_TYPE vtxType = buffer->getVertexType(); 1635 video::E_VERTEX_TYPE vtxType = buffer->getVertexType();
1636 u32 vertexCount = buffer->getVertexCount(); 1636 u32 vertexCount = buffer->getVertexCount();
1637 1637
1638 globalIndices[i].NormalStartIndex = 0; 1638 globalIndices[i].NormalStartIndex = 0;
1639 1639
1640 if (i!=0) 1640 if (i!=0)
1641 globalIndices[i].NormalStartIndex = globalIndices[i-1].NormalLastIndex + 1; 1641 globalIndices[i].NormalStartIndex = globalIndices[i-1].NormalLastIndex + 1;
1642 1642
1643 globalIndices[i].NormalLastIndex = globalIndices[i].NormalStartIndex + vertexCount - 1; 1643 globalIndices[i].NormalLastIndex = globalIndices[i].NormalStartIndex + vertexCount - 1;
1644 1644
1645 switch(vtxType) 1645 switch(vtxType)
1646 { 1646 {
1647 case video::EVT_STANDARD: 1647 case video::EVT_STANDARD:
1648 { 1648 {
1649 video::S3DVertex* vtx = (video::S3DVertex*)buffer->getVertices(); 1649 video::S3DVertex* vtx = (video::S3DVertex*)buffer->getVertices();
1650 for (u32 j=0; j<vertexCount; ++j) 1650 for (u32 j=0; j<vertexCount; ++j)
1651 { 1651 {
1652 writeVector(vtx[j].Normal); 1652 writeVector(vtx[j].Normal);
1653 Writer->writeLineBreak(); 1653 Writer->writeLineBreak();
1654 } 1654 }
1655 } 1655 }
1656 break; 1656 break;
1657 case video::EVT_2TCOORDS: 1657 case video::EVT_2TCOORDS:
1658 { 1658 {
1659 video::S3DVertex2TCoords* vtx = (video::S3DVertex2TCoords*)buffer->getVertices(); 1659 video::S3DVertex2TCoords* vtx = (video::S3DVertex2TCoords*)buffer->getVertices();
1660 for (u32 j=0; j<vertexCount; ++j) 1660 for (u32 j=0; j<vertexCount; ++j)
1661 { 1661 {
1662 writeVector(vtx[j].Normal); 1662 writeVector(vtx[j].Normal);
1663 Writer->writeLineBreak(); 1663 Writer->writeLineBreak();
1664 } 1664 }
1665 } 1665 }
1666 break; 1666 break;
1667 case video::EVT_TANGENTS: 1667 case video::EVT_TANGENTS:
1668 { 1668 {
1669 video::S3DVertexTangents* vtx = (video::S3DVertexTangents*)buffer->getVertices(); 1669 video::S3DVertexTangents* vtx = (video::S3DVertexTangents*)buffer->getVertices();
1670 for (u32 j=0; j<vertexCount; ++j) 1670 for (u32 j=0; j<vertexCount; ++j)
1671 { 1671 {
1672 writeVector(vtx[j].Normal); 1672 writeVector(vtx[j].Normal);
1673 Writer->writeLineBreak(); 1673 Writer->writeLineBreak();
1674 } 1674 }
1675 } 1675 }
1676 break; 1676 break;
1677 } 1677 }
1678 } 1678 }
1679 1679
1680 Writer->writeClosingTag(L"float_array"); 1680 Writer->writeClosingTag(L"float_array");
1681 Writer->writeLineBreak(); 1681 Writer->writeLineBreak();
1682 1682
1683 Writer->writeElement(L"technique_common", false); 1683 Writer->writeElement(L"technique_common", false);
1684 Writer->writeLineBreak(); 1684 Writer->writeLineBreak();
1685 1685
1686 vertexCountStr = core::stringw(totalVertexCount); 1686 vertexCountStr = core::stringw(totalVertexCount);
1687 1687
1688 Writer->writeElement(L"accessor", false, L"source", toRef(meshNormalArrayId).c_str(), 1688 Writer->writeElement(L"accessor", false, L"source", toRef(meshNormalArrayId).c_str(),
1689 L"count", vertexCountStr.c_str(), L"stride", L"3"); 1689 L"count", vertexCountStr.c_str(), L"stride", L"3");
1690 Writer->writeLineBreak(); 1690 Writer->writeLineBreak();
1691 1691
1692 Writer->writeElement(L"param", true, L"name", L"X", L"type", L"float"); 1692 Writer->writeElement(L"param", true, L"name", L"X", L"type", L"float");
1693 Writer->writeLineBreak(); 1693 Writer->writeLineBreak();
1694 Writer->writeElement(L"param", true, L"name", L"Y", L"type", L"float"); 1694 Writer->writeElement(L"param", true, L"name", L"Y", L"type", L"float");
1695 Writer->writeLineBreak(); 1695 Writer->writeLineBreak();
1696 Writer->writeElement(L"param", true, L"name", L"Z", L"type", L"float"); 1696 Writer->writeElement(L"param", true, L"name", L"Z", L"type", L"float");
1697 Writer->writeLineBreak(); 1697 Writer->writeLineBreak();
1698 1698
1699 Writer->writeClosingTag(L"accessor"); 1699 Writer->writeClosingTag(L"accessor");
1700 Writer->writeLineBreak(); 1700 Writer->writeLineBreak();
1701 1701
1702 Writer->writeClosingTag(L"technique_common"); 1702 Writer->writeClosingTag(L"technique_common");
1703 Writer->writeLineBreak(); 1703 Writer->writeLineBreak();
1704 1704
1705 Writer->writeClosingTag(L"source"); 1705 Writer->writeClosingTag(L"source");
1706 Writer->writeLineBreak(); 1706 Writer->writeLineBreak();
1707 1707
1708 // write second set of texture coordinates 1708 // write second set of texture coordinates
1709 core::stringw meshTexCoord1Id(meshId); 1709 core::stringw meshTexCoord1Id(meshId);
1710 meshTexCoord1Id += L"-TexCoord1"; 1710 meshTexCoord1Id += L"-TexCoord1";
1711 if (totalTCoords2Count) 1711 if (totalTCoords2Count)
1712 { 1712 {
1713 Writer->writeElement(L"source", false, L"id", meshTexCoord1Id.c_str()); 1713 Writer->writeElement(L"source", false, L"id", meshTexCoord1Id.c_str());
1714 Writer->writeLineBreak(); 1714 Writer->writeLineBreak();
1715 1715
1716 vertexCountStr = core::stringw(totalTCoords2Count*2); 1716 vertexCountStr = core::stringw(totalTCoords2Count*2);
1717 core::stringw meshTexCoord1ArrayId(meshTexCoord1Id); 1717 core::stringw meshTexCoord1ArrayId(meshTexCoord1Id);
1718 meshTexCoord1ArrayId += L"-array"; 1718 meshTexCoord1ArrayId += L"-array";
1719 Writer->writeElement(L"float_array", false, L"id", meshTexCoord1ArrayId.c_str(), 1719 Writer->writeElement(L"float_array", false, L"id", meshTexCoord1ArrayId.c_str(),
1720 L"count", vertexCountStr.c_str()); 1720 L"count", vertexCountStr.c_str());
1721 Writer->writeLineBreak(); 1721 Writer->writeLineBreak();
1722 1722
1723 for (i=0; i<mesh->getMeshBufferCount(); ++i) 1723 for (i=0; i<mesh->getMeshBufferCount(); ++i)
1724 { 1724 {
1725 scene::IMeshBuffer* buffer = mesh->getMeshBuffer(i); 1725 scene::IMeshBuffer* buffer = mesh->getMeshBuffer(i);
1726 video::E_VERTEX_TYPE vtxType = buffer->getVertexType(); 1726 video::E_VERTEX_TYPE vtxType = buffer->getVertexType();
1727 u32 vertexCount = buffer->getVertexCount(); 1727 u32 vertexCount = buffer->getVertexCount();
1728 1728
1729 if (hasSecondTextureCoordinates(vtxType)) 1729 if (hasSecondTextureCoordinates(vtxType))
1730 { 1730 {
1731 globalIndices[i].TCoord1StartIndex = 0; 1731 globalIndices[i].TCoord1StartIndex = 0;
1732 1732
1733 if (i!=0 && globalIndices[i-1].TCoord1LastIndex != -1) 1733 if (i!=0 && globalIndices[i-1].TCoord1LastIndex != -1)
1734 globalIndices[i].TCoord1StartIndex = globalIndices[i-1].TCoord1LastIndex + 1; 1734 globalIndices[i].TCoord1StartIndex = globalIndices[i-1].TCoord1LastIndex + 1;
1735 1735
1736 globalIndices[i].TCoord1LastIndex = globalIndices[i].TCoord1StartIndex + vertexCount - 1; 1736 globalIndices[i].TCoord1LastIndex = globalIndices[i].TCoord1StartIndex + vertexCount - 1;
1737 1737
1738 switch(vtxType) 1738 switch(vtxType)
1739 { 1739 {
1740 case video::EVT_2TCOORDS: 1740 case video::EVT_2TCOORDS:
1741 { 1741 {
1742 video::S3DVertex2TCoords* vtx = (video::S3DVertex2TCoords*)buffer->getVertices(); 1742 video::S3DVertex2TCoords* vtx = (video::S3DVertex2TCoords*)buffer->getVertices();
1743 for (u32 j=0; j<vertexCount; ++j) 1743 for (u32 j=0; j<vertexCount; ++j)
1744 { 1744 {
1745 writeVector(vtx[j].TCoords2); 1745 writeVector(vtx[j].TCoords2);
1746 Writer->writeLineBreak(); 1746 Writer->writeLineBreak();
1747 } 1747 }
1748 } 1748 }
1749 break; 1749 break;
1750 default: 1750 default:
1751 break; 1751 break;
1752 } 1752 }
1753 } // end this buffer has 2 texture coordinates 1753 } // end this buffer has 2 texture coordinates
1754 } 1754 }
1755 1755
1756 Writer->writeClosingTag(L"float_array"); 1756 Writer->writeClosingTag(L"float_array");
1757 Writer->writeLineBreak(); 1757 Writer->writeLineBreak();
1758 1758
1759 Writer->writeElement(L"technique_common", false); 1759 Writer->writeElement(L"technique_common", false);
1760 Writer->writeLineBreak(); 1760 Writer->writeLineBreak();
1761 1761
1762 vertexCountStr = core::stringw(totalTCoords2Count); 1762 vertexCountStr = core::stringw(totalTCoords2Count);
1763 1763
1764 Writer->writeElement(L"accessor", false, L"source", toRef(meshTexCoord1ArrayId).c_str(), 1764 Writer->writeElement(L"accessor", false, L"source", toRef(meshTexCoord1ArrayId).c_str(),
1765 L"count", vertexCountStr.c_str(), L"stride", L"2"); 1765 L"count", vertexCountStr.c_str(), L"stride", L"2");
1766 Writer->writeLineBreak(); 1766 Writer->writeLineBreak();
1767 1767
1768 Writer->writeElement(L"param", true, L"name", L"U", L"type", L"float"); 1768 Writer->writeElement(L"param", true, L"name", L"U", L"type", L"float");
1769 Writer->writeLineBreak(); 1769 Writer->writeLineBreak();
1770 Writer->writeElement(L"param", true, L"name", L"V", L"type", L"float"); 1770 Writer->writeElement(L"param", true, L"name", L"V", L"type", L"float");
1771 Writer->writeLineBreak(); 1771 Writer->writeLineBreak();
1772 1772
1773 Writer->writeClosingTag(L"accessor"); 1773 Writer->writeClosingTag(L"accessor");
1774 Writer->writeLineBreak(); 1774 Writer->writeLineBreak();
1775 1775
1776 Writer->writeClosingTag(L"technique_common"); 1776 Writer->writeClosingTag(L"technique_common");
1777 Writer->writeLineBreak(); 1777 Writer->writeLineBreak();
1778 1778
1779 Writer->writeClosingTag(L"source"); 1779 Writer->writeClosingTag(L"source");
1780 Writer->writeLineBreak(); 1780 Writer->writeLineBreak();
1781 } 1781 }
1782 1782
1783 // write tangents 1783 // write tangents
1784 1784
1785 // TODO 1785 // TODO
1786 1786
1787 // write vertices 1787 // write vertices
1788 core::stringw meshVtxId(meshId); 1788 core::stringw meshVtxId(meshId);
1789 meshVtxId += L"-Vtx"; 1789 meshVtxId += L"-Vtx";
1790 Writer->writeElement(L"vertices", false, L"id", meshVtxId.c_str()); 1790 Writer->writeElement(L"vertices", false, L"id", meshVtxId.c_str());
1791 Writer->writeLineBreak(); 1791 Writer->writeLineBreak();
1792 1792
1793 Writer->writeElement(L"input", true, L"semantic", L"POSITION", L"source", toRef(meshPosId).c_str()); 1793 Writer->writeElement(L"input", true, L"semantic", L"POSITION", L"source", toRef(meshPosId).c_str());
1794 Writer->writeLineBreak(); 1794 Writer->writeLineBreak();
1795 1795
1796 Writer->writeClosingTag(L"vertices"); 1796 Writer->writeClosingTag(L"vertices");
1797 Writer->writeLineBreak(); 1797 Writer->writeLineBreak();
1798 1798
1799 // write polygons 1799 // write polygons
1800 1800
1801 for (i=0; i<mesh->getMeshBufferCount(); ++i) 1801 for (i=0; i<mesh->getMeshBufferCount(); ++i)
1802 { 1802 {
1803 scene::IMeshBuffer* buffer = mesh->getMeshBuffer(i); 1803 scene::IMeshBuffer* buffer = mesh->getMeshBuffer(i);
1804 1804
1805 const u32 polyCount = buffer->getIndexCount() / 3; 1805 const u32 polyCount = buffer->getIndexCount() / 3;
1806 core::stringw strPolyCount(polyCount); 1806 core::stringw strPolyCount(polyCount);
1807 irr::core::stringw strMat(nameForMaterialSymbol(mesh, i)); 1807 irr::core::stringw strMat(nameForMaterialSymbol(mesh, i));
1808 1808
1809 Writer->writeElement(L"triangles", false, L"count", strPolyCount.c_str(), 1809 Writer->writeElement(L"triangles", false, L"count", strPolyCount.c_str(),
1810 L"material", strMat.c_str()); 1810 L"material", strMat.c_str());
1811 Writer->writeLineBreak(); 1811 Writer->writeLineBreak();
1812 1812
1813 Writer->writeElement(L"input", true, L"semantic", L"VERTEX", L"source", toRef(meshVtxId).c_str(), L"offset", L"0"); 1813 Writer->writeElement(L"input", true, L"semantic", L"VERTEX", L"source", toRef(meshVtxId).c_str(), L"offset", L"0");
1814 Writer->writeLineBreak(); 1814 Writer->writeLineBreak();
1815 Writer->writeElement(L"input", true, L"semantic", L"TEXCOORD", L"source", toRef(meshTexCoord0Id).c_str(), L"offset", L"1", L"set", L"0"); 1815 Writer->writeElement(L"input", true, L"semantic", L"TEXCOORD", L"source", toRef(meshTexCoord0Id).c_str(), L"offset", L"1", L"set", L"0");
1816 Writer->writeLineBreak(); 1816 Writer->writeLineBreak();
1817 Writer->writeElement(L"input", true, L"semantic", L"NORMAL", L"source", toRef(meshNormalId).c_str(), L"offset", L"2"); 1817 Writer->writeElement(L"input", true, L"semantic", L"NORMAL", L"source", toRef(meshNormalId).c_str(), L"offset", L"2");
1818 Writer->writeLineBreak(); 1818 Writer->writeLineBreak();
1819 1819
1820 bool has2ndTexCoords = hasSecondTextureCoordinates(buffer->getVertexType()); 1820 bool has2ndTexCoords = hasSecondTextureCoordinates(buffer->getVertexType());
1821 if (has2ndTexCoords) 1821 if (has2ndTexCoords)
1822 { 1822 {
1823 // TODO: when working on second uv-set - my suspicion is that this one should be called "TEXCOORD2" 1823 // TODO: when working on second uv-set - my suspicion is that this one should be called "TEXCOORD2"
1824 // to allow bind_vertex_input to differentiate the uv-sets. 1824 // to allow bind_vertex_input to differentiate the uv-sets.
1825 Writer->writeElement(L"input", true, L"semantic", L"TEXCOORD", L"source", toRef(meshTexCoord1Id).c_str(), L"idx", L"3"); 1825 Writer->writeElement(L"input", true, L"semantic", L"TEXCOORD", L"source", toRef(meshTexCoord1Id).c_str(), L"idx", L"3");
1826 Writer->writeLineBreak(); 1826 Writer->writeLineBreak();
1827 } 1827 }
1828 1828
1829 // write indices now 1829 // write indices now
1830 1830
1831 s32 posIdx = globalIndices[i].PosStartIndex; 1831 s32 posIdx = globalIndices[i].PosStartIndex;
1832 s32 tCoordIdx = globalIndices[i].TCoord0StartIndex; 1832 s32 tCoordIdx = globalIndices[i].TCoord0StartIndex;
1833 s32 normalIdx = globalIndices[i].NormalStartIndex; 1833 s32 normalIdx = globalIndices[i].NormalStartIndex;
1834 s32 tCoord2Idx = globalIndices[i].TCoord1StartIndex; 1834 s32 tCoord2Idx = globalIndices[i].TCoord1StartIndex;
1835 1835
1836 Writer->writeElement(L"p", false); 1836 Writer->writeElement(L"p", false);
1837 1837
1838 core::stringw strP; 1838 core::stringw strP;
1839 strP.reserve(100); 1839 strP.reserve(100);
1840 for (u32 p=0; p<polyCount; ++p) 1840 for (u32 p=0; p<polyCount; ++p)
1841 { 1841 {
1842 strP = ""; 1842 strP = "";
1843 strP += buffer->getIndices()[(p*3) + 0] + posIdx; 1843 strP += buffer->getIndices()[(p*3) + 0] + posIdx;
1844 strP += " "; 1844 strP += " ";
1845 strP += buffer->getIndices()[(p*3) + 0] + tCoordIdx; 1845 strP += buffer->getIndices()[(p*3) + 0] + tCoordIdx;
1846 strP += " "; 1846 strP += " ";
1847 strP += buffer->getIndices()[(p*3) + 0] + normalIdx; 1847 strP += buffer->getIndices()[(p*3) + 0] + normalIdx;
1848 strP += " "; 1848 strP += " ";
1849 if (has2ndTexCoords) 1849 if (has2ndTexCoords)
1850 { 1850 {
1851 strP += buffer->getIndices()[(p*3) + 0] + tCoord2Idx; 1851 strP += buffer->getIndices()[(p*3) + 0] + tCoord2Idx;
1852 strP += " "; 1852 strP += " ";
1853 } 1853 }
1854 1854
1855 strP += buffer->getIndices()[(p*3) + 1] + posIdx; 1855 strP += buffer->getIndices()[(p*3) + 1] + posIdx;
1856 strP += " "; 1856 strP += " ";
1857 strP += buffer->getIndices()[(p*3) + 1] + tCoordIdx; 1857 strP += buffer->getIndices()[(p*3) + 1] + tCoordIdx;
1858 strP += " "; 1858 strP += " ";
1859 strP += buffer->getIndices()[(p*3) + 1] + normalIdx; 1859 strP += buffer->getIndices()[(p*3) + 1] + normalIdx;
1860 strP += " "; 1860 strP += " ";
1861 if (has2ndTexCoords) 1861 if (has2ndTexCoords)
1862 { 1862 {
1863 strP += buffer->getIndices()[(p*3) + 1] + tCoord2Idx; 1863 strP += buffer->getIndices()[(p*3) + 1] + tCoord2Idx;
1864 strP += " "; 1864 strP += " ";
1865 } 1865 }
1866 1866
1867 strP += buffer->getIndices()[(p*3) + 2] + posIdx; 1867 strP += buffer->getIndices()[(p*3) + 2] + posIdx;
1868 strP += " "; 1868 strP += " ";
1869 strP += buffer->getIndices()[(p*3) + 2] + tCoordIdx; 1869 strP += buffer->getIndices()[(p*3) + 2] + tCoordIdx;
1870 strP += " "; 1870 strP += " ";
1871 strP += buffer->getIndices()[(p*3) + 2] + normalIdx; 1871 strP += buffer->getIndices()[(p*3) + 2] + normalIdx;
1872 if (has2ndTexCoords) 1872 if (has2ndTexCoords)
1873 { 1873 {
1874 strP += " "; 1874 strP += " ";
1875 strP += buffer->getIndices()[(p*3) + 2] + tCoord2Idx; 1875 strP += buffer->getIndices()[(p*3) + 2] + tCoord2Idx;
1876 } 1876 }
1877 strP += " "; 1877 strP += " ";
1878 1878
1879 Writer->writeText(strP.c_str()); 1879 Writer->writeText(strP.c_str());
1880 } 1880 }
1881 1881
1882 Writer->writeClosingTag(L"p"); 1882 Writer->writeClosingTag(L"p");
1883 Writer->writeLineBreak(); 1883 Writer->writeLineBreak();
1884 1884
1885 // close index buffer section 1885 // close index buffer section
1886 1886
1887 Writer->writeClosingTag(L"triangles"); 1887 Writer->writeClosingTag(L"triangles");
1888 Writer->writeLineBreak(); 1888 Writer->writeLineBreak();
1889 } 1889 }
1890 1890
1891 // close mesh and geometry 1891 // close mesh and geometry
1892 delete [] globalIndices; 1892 delete [] globalIndices;
1893 Writer->writeClosingTag(L"mesh"); 1893 Writer->writeClosingTag(L"mesh");
1894 Writer->writeLineBreak(); 1894 Writer->writeLineBreak();
1895 Writer->writeClosingTag(L"geometry"); 1895 Writer->writeClosingTag(L"geometry");
1896 Writer->writeLineBreak(); 1896 Writer->writeLineBreak();
1897} 1897}
1898 1898
1899void CColladaMeshWriter::writeLibraryImages() 1899void CColladaMeshWriter::writeLibraryImages()
1900{ 1900{
1901 if ( getWriteTextures() && !LibraryImages.empty() ) 1901 if ( getWriteTextures() && !LibraryImages.empty() )
1902 { 1902 {
1903 Writer->writeElement(L"library_images", false); 1903 Writer->writeElement(L"library_images", false);
1904 Writer->writeLineBreak(); 1904 Writer->writeLineBreak();
1905 1905
1906 for ( irr::u32 i=0; i<LibraryImages.size(); ++i ) 1906 for ( irr::u32 i=0; i<LibraryImages.size(); ++i )
1907 { 1907 {
1908 irr::io::path p(FileSystem->getRelativeFilename(LibraryImages[i]->getName().getPath(), Directory)); 1908 irr::io::path p(FileSystem->getRelativeFilename(LibraryImages[i]->getName().getPath(), Directory));
1909 //<image name="rose01"> 1909 //<image name="rose01">
1910 irr::core::stringw ncname( toNCName(irr::core::stringw(p)) ); 1910 irr::core::stringw ncname( toNCName(irr::core::stringw(p)) );
1911 Writer->writeElement(L"image", false, L"id", ncname.c_str(), L"name", ncname.c_str()); 1911 Writer->writeElement(L"image", false, L"id", ncname.c_str(), L"name", ncname.c_str());
1912 Writer->writeLineBreak(); 1912 Writer->writeLineBreak();
1913 // <init_from>../flowers/rose01.jpg</init_from> 1913 // <init_from>../flowers/rose01.jpg</init_from>
1914 Writer->writeElement(L"init_from", false); 1914 Writer->writeElement(L"init_from", false);
1915 Writer->writeText(pathToURI(p).c_str()); 1915 Writer->writeText(pathToURI(p).c_str());
1916 Writer->writeClosingTag(L"init_from"); 1916 Writer->writeClosingTag(L"init_from");
1917 Writer->writeLineBreak(); 1917 Writer->writeLineBreak();
1918 // </image> 1918 // </image>
1919 Writer->writeClosingTag(L"image"); 1919 Writer->writeClosingTag(L"image");
1920 Writer->writeLineBreak(); 1920 Writer->writeLineBreak();
1921 } 1921 }
1922 1922
1923 Writer->writeClosingTag(L"library_images"); 1923 Writer->writeClosingTag(L"library_images");
1924 Writer->writeLineBreak(); 1924 Writer->writeLineBreak();
1925 } 1925 }
1926} 1926}
1927 1927
1928void CColladaMeshWriter::writeColorElement(const video::SColorf & col, bool writeAlpha) 1928void CColladaMeshWriter::writeColorElement(const video::SColorf & col, bool writeAlpha)
1929{ 1929{
1930 Writer->writeElement(L"color", false); 1930 Writer->writeElement(L"color", false);
1931 1931
1932 writeColor(col, writeAlpha); 1932 writeColor(col, writeAlpha);
1933 1933
1934 Writer->writeClosingTag(L"color"); 1934 Writer->writeClosingTag(L"color");
1935 Writer->writeLineBreak(); 1935 Writer->writeLineBreak();
1936} 1936}
1937 1937
1938void CColladaMeshWriter::writeColorElement(const video::SColor & col, bool writeAlpha) 1938void CColladaMeshWriter::writeColorElement(const video::SColor & col, bool writeAlpha)
1939{ 1939{
1940 writeColorElement( video::SColorf(col), writeAlpha ); 1940 writeColorElement( video::SColorf(col), writeAlpha );
1941} 1941}
1942 1942
1943void CColladaMeshWriter::writeAmbientLightElement(const video::SColorf & col) 1943void CColladaMeshWriter::writeAmbientLightElement(const video::SColorf & col)
1944{ 1944{
1945 Writer->writeElement(L"light", false, L"id", L"ambientlight"); 1945 Writer->writeElement(L"light", false, L"id", L"ambientlight");
1946 Writer->writeLineBreak(); 1946 Writer->writeLineBreak();
1947 1947
1948 Writer->writeElement(L"technique_common", false); 1948 Writer->writeElement(L"technique_common", false);
1949 Writer->writeLineBreak(); 1949 Writer->writeLineBreak();
1950 1950
1951 Writer->writeElement(L"ambient", false); 1951 Writer->writeElement(L"ambient", false);
1952 Writer->writeLineBreak(); 1952 Writer->writeLineBreak();
1953 1953
1954 writeColorElement(col, false); 1954 writeColorElement(col, false);
1955 1955
1956 Writer->writeClosingTag(L"ambient"); 1956 Writer->writeClosingTag(L"ambient");
1957 Writer->writeLineBreak(); 1957 Writer->writeLineBreak();
1958 1958
1959 Writer->writeClosingTag(L"technique_common"); 1959 Writer->writeClosingTag(L"technique_common");
1960 Writer->writeLineBreak(); 1960 Writer->writeLineBreak();
1961 1961
1962 Writer->writeClosingTag(L"light"); 1962 Writer->writeClosingTag(L"light");
1963 Writer->writeLineBreak(); 1963 Writer->writeLineBreak();
1964} 1964}
1965 1965
1966s32 CColladaMeshWriter::getCheckedTextureIdx(const video::SMaterial & material, E_COLLADA_COLOR_SAMPLER cs) 1966s32 CColladaMeshWriter::getCheckedTextureIdx(const video::SMaterial & material, E_COLLADA_COLOR_SAMPLER cs)
1967{ 1967{
1968 if ( !getWriteTextures() 1968 if ( !getWriteTextures()
1969 || !getProperties() ) 1969 || !getProperties() )
1970 return -1; 1970 return -1;
1971 1971
1972 s32 idx = getProperties()->getTextureIdx(material, cs); 1972 s32 idx = getProperties()->getTextureIdx(material, cs);
1973 if ( idx >= 0 && !material.TextureLayer[idx].Texture ) 1973 if ( idx >= 0 && !material.TextureLayer[idx].Texture )
1974 return -1; 1974 return -1;
1975 1975
1976 return idx; 1976 return idx;
1977} 1977}
1978 1978
1979video::SColor CColladaMeshWriter::getColorMapping(const video::SMaterial & material, E_COLLADA_COLOR_SAMPLER cs, E_COLLADA_IRR_COLOR colType) 1979video::SColor CColladaMeshWriter::getColorMapping(const video::SMaterial & material, E_COLLADA_COLOR_SAMPLER cs, E_COLLADA_IRR_COLOR colType)
1980{ 1980{
1981 switch ( colType ) 1981 switch ( colType )
1982 { 1982 {
1983 case ECIC_NONE: 1983 case ECIC_NONE:
1984 return video::SColor(255, 0, 0, 0); 1984 return video::SColor(255, 0, 0, 0);
1985 1985
1986 case ECIC_CUSTOM: 1986 case ECIC_CUSTOM:
1987 return getProperties()->getCustomColor(material, cs); 1987 return getProperties()->getCustomColor(material, cs);
1988 1988
1989 case ECIC_DIFFUSE: 1989 case ECIC_DIFFUSE:
1990 return material.DiffuseColor; 1990 return material.DiffuseColor;
1991 1991
1992 case ECIC_AMBIENT: 1992 case ECIC_AMBIENT:
1993 return material.AmbientColor; 1993 return material.AmbientColor;
1994 1994
1995 case ECIC_EMISSIVE: 1995 case ECIC_EMISSIVE:
1996 return material.EmissiveColor; 1996 return material.EmissiveColor;
1997 1997
1998 case ECIC_SPECULAR: 1998 case ECIC_SPECULAR:
1999 return material.SpecularColor; 1999 return material.SpecularColor;
2000 } 2000 }
2001 return video::SColor(255, 0, 0, 0); 2001 return video::SColor(255, 0, 0, 0);
2002} 2002}
2003 2003
2004void CColladaMeshWriter::writeTextureSampler(s32 textureIdx) 2004void CColladaMeshWriter::writeTextureSampler(s32 textureIdx)
2005{ 2005{
2006 irr::core::stringw sampler(L"tex"); 2006 irr::core::stringw sampler(L"tex");
2007 sampler += irr::core::stringw(textureIdx); 2007 sampler += irr::core::stringw(textureIdx);
2008 sampler += L"-sampler"; 2008 sampler += L"-sampler";
2009 2009
2010 // <texture texture="sampler" texcoord="texCoordUv"/> 2010 // <texture texture="sampler" texcoord="texCoordUv"/>
2011 Writer->writeElement(L"texture", true, L"texture", sampler.c_str(), L"texcoord", L"uv" ); 2011 Writer->writeElement(L"texture", true, L"texture", sampler.c_str(), L"texcoord", L"uv" );
2012 Writer->writeLineBreak(); 2012 Writer->writeLineBreak();
2013} 2013}
2014 2014
2015void CColladaMeshWriter::writeFxElement(const video::SMaterial & material, E_COLLADA_TECHNIQUE_FX techFx) 2015void CColladaMeshWriter::writeFxElement(const video::SMaterial & material, E_COLLADA_TECHNIQUE_FX techFx)
2016{ 2016{
2017 core::stringw fxLabel; 2017 core::stringw fxLabel;
2018 bool writeEmission = true; 2018 bool writeEmission = true;
2019 bool writeAmbient = true; 2019 bool writeAmbient = true;
2020 bool writeDiffuse = true; 2020 bool writeDiffuse = true;
2021 bool writeSpecular = true; 2021 bool writeSpecular = true;
2022 bool writeShininess = true; 2022 bool writeShininess = true;
2023 bool writeReflective = true; 2023 bool writeReflective = true;
2024 bool writeReflectivity = true; 2024 bool writeReflectivity = true;
2025 bool writeTransparent = true; 2025 bool writeTransparent = true;
2026 bool writeTransparency = true; 2026 bool writeTransparency = true;
2027 bool writeIndexOfRefraction = true; 2027 bool writeIndexOfRefraction = true;
2028 switch ( techFx ) 2028 switch ( techFx )
2029 { 2029 {
2030 case ECTF_BLINN: 2030 case ECTF_BLINN:
2031 fxLabel = L"blinn"; 2031 fxLabel = L"blinn";
2032 break; 2032 break;
2033 case ECTF_PHONG: 2033 case ECTF_PHONG:
2034 fxLabel = L"phong"; 2034 fxLabel = L"phong";
2035 break; 2035 break;
2036 case ECTF_LAMBERT: 2036 case ECTF_LAMBERT:
2037 fxLabel = L"lambert"; 2037 fxLabel = L"lambert";
2038 writeSpecular = false; 2038 writeSpecular = false;
2039 writeShininess = false; 2039 writeShininess = false;
2040 break; 2040 break;
2041 case ECTF_CONSTANT: 2041 case ECTF_CONSTANT:
2042 fxLabel = L"constant"; 2042 fxLabel = L"constant";
2043 writeAmbient = false; 2043 writeAmbient = false;
2044 writeDiffuse = false; 2044 writeDiffuse = false;
2045 writeSpecular = false; 2045 writeSpecular = false;
2046 writeShininess = false; 2046 writeShininess = false;
2047 break; 2047 break;
2048 } 2048 }
2049 2049
2050 Writer->writeElement(fxLabel.c_str(), false); 2050 Writer->writeElement(fxLabel.c_str(), false);
2051 Writer->writeLineBreak(); 2051 Writer->writeLineBreak();
2052 2052
2053 // write all interesting material parameters 2053 // write all interesting material parameters
2054 // attributes must be written in fixed order 2054 // attributes must be written in fixed order
2055 if ( getProperties() ) 2055 if ( getProperties() )
2056 { 2056 {
2057 if ( writeEmission ) 2057 if ( writeEmission )
2058 { 2058 {
2059 writeColorFx(material, L"emission", ECCS_EMISSIVE); 2059 writeColorFx(material, L"emission", ECCS_EMISSIVE);
2060 } 2060 }
2061 2061
2062 if ( writeAmbient ) 2062 if ( writeAmbient )
2063 { 2063 {
2064 writeColorFx(material, L"ambient", ECCS_AMBIENT); 2064 writeColorFx(material, L"ambient", ECCS_AMBIENT);
2065 } 2065 }
2066 2066
2067 if ( writeDiffuse ) 2067 if ( writeDiffuse )
2068 { 2068 {
2069 writeColorFx(material, L"diffuse", ECCS_DIFFUSE); 2069 writeColorFx(material, L"diffuse", ECCS_DIFFUSE);
2070 } 2070 }
2071 2071
2072 if ( writeSpecular ) 2072 if ( writeSpecular )
2073 { 2073 {
2074 writeColorFx(material, L"specular", ECCS_SPECULAR); 2074 writeColorFx(material, L"specular", ECCS_SPECULAR);
2075 } 2075 }
2076 2076
2077 if ( writeShininess ) 2077 if ( writeShininess )
2078 { 2078 {
2079 Writer->writeElement(L"shininess", false); 2079 Writer->writeElement(L"shininess", false);
2080 Writer->writeLineBreak(); 2080 Writer->writeLineBreak();
2081 writeFloatElement(material.Shininess); 2081 writeFloatElement(material.Shininess);
2082 Writer->writeClosingTag(L"shininess"); 2082 Writer->writeClosingTag(L"shininess");
2083 Writer->writeLineBreak(); 2083 Writer->writeLineBreak();
2084 } 2084 }
2085 2085
2086 if ( writeReflective ) 2086 if ( writeReflective )
2087 { 2087 {
2088 writeColorFx(material, L"reflective", ECCS_REFLECTIVE); 2088 writeColorFx(material, L"reflective", ECCS_REFLECTIVE);
2089 } 2089 }
2090 2090
2091 if ( writeReflectivity ) 2091 if ( writeReflectivity )
2092 { 2092 {
2093 f32 t = getProperties()->getReflectivity(material); 2093 f32 t = getProperties()->getReflectivity(material);
2094 if ( t >= 0.f ) 2094 if ( t >= 0.f )
2095 { 2095 {
2096 // <transparency> <float>1.000000</float> </transparency> 2096 // <transparency> <float>1.000000</float> </transparency>
2097 Writer->writeElement(L"reflectivity", false); 2097 Writer->writeElement(L"reflectivity", false);
2098 Writer->writeLineBreak(); 2098 Writer->writeLineBreak();
2099 writeFloatElement(t); 2099 writeFloatElement(t);
2100 Writer->writeClosingTag(L"reflectivity"); 2100 Writer->writeClosingTag(L"reflectivity");
2101 Writer->writeLineBreak(); 2101 Writer->writeLineBreak();
2102 } 2102 }
2103 } 2103 }
2104 2104
2105 if ( writeTransparent ) 2105 if ( writeTransparent )
2106 { 2106 {
2107 E_COLLADA_TRANSPARENT_FX transparentFx = getProperties()->getTransparentFx(material); 2107 E_COLLADA_TRANSPARENT_FX transparentFx = getProperties()->getTransparentFx(material);
2108 writeColorFx(material, L"transparent", ECCS_TRANSPARENT, L"opaque", toString(transparentFx).c_str()); 2108 writeColorFx(material, L"transparent", ECCS_TRANSPARENT, L"opaque", toString(transparentFx).c_str());
2109 } 2109 }
2110 2110
2111 if ( writeTransparency ) 2111 if ( writeTransparency )
2112 { 2112 {
2113 f32 t = getProperties()->getTransparency(material); 2113 f32 t = getProperties()->getTransparency(material);
2114 if ( t >= 0.f ) 2114 if ( t >= 0.f )
2115 { 2115 {
2116 // <transparency> <float>1.000000</float> </transparency> 2116 // <transparency> <float>1.000000</float> </transparency>
2117 Writer->writeElement(L"transparency", false); 2117 Writer->writeElement(L"transparency", false);
2118 Writer->writeLineBreak(); 2118 Writer->writeLineBreak();
2119 writeFloatElement(t); 2119 writeFloatElement(t);
2120 Writer->writeClosingTag(L"transparency"); 2120 Writer->writeClosingTag(L"transparency");
2121 Writer->writeLineBreak(); 2121 Writer->writeLineBreak();
2122 } 2122 }
2123 } 2123 }
2124 2124
2125 if ( writeIndexOfRefraction ) 2125 if ( writeIndexOfRefraction )
2126 { 2126 {
2127 f32 t = getProperties()->getIndexOfRefraction(material); 2127 f32 t = getProperties()->getIndexOfRefraction(material);
2128 if ( t >= 0.f ) 2128 if ( t >= 0.f )
2129 { 2129 {
2130 Writer->writeElement(L"index_of_refraction", false); 2130 Writer->writeElement(L"index_of_refraction", false);
2131 Writer->writeLineBreak(); 2131 Writer->writeLineBreak();
2132 writeFloatElement(t); 2132 writeFloatElement(t);
2133 Writer->writeClosingTag(L"index_of_refraction"); 2133 Writer->writeClosingTag(L"index_of_refraction");
2134 Writer->writeLineBreak(); 2134 Writer->writeLineBreak();
2135 } 2135 }
2136 } 2136 }
2137 } 2137 }
2138 2138
2139 2139
2140 Writer->writeClosingTag(fxLabel.c_str()); 2140 Writer->writeClosingTag(fxLabel.c_str());
2141 Writer->writeLineBreak(); 2141 Writer->writeLineBreak();
2142} 2142}
2143 2143
2144void CColladaMeshWriter::writeColorFx(const video::SMaterial & material, const wchar_t * colorname, E_COLLADA_COLOR_SAMPLER cs, const wchar_t* attr1Name, const wchar_t* attr1Value) 2144void CColladaMeshWriter::writeColorFx(const video::SMaterial & material, const wchar_t * colorname, E_COLLADA_COLOR_SAMPLER cs, const wchar_t* attr1Name, const wchar_t* attr1Value)
2145{ 2145{
2146 irr::s32 idx = getCheckedTextureIdx(material, cs); 2146 irr::s32 idx = getCheckedTextureIdx(material, cs);
2147 E_COLLADA_IRR_COLOR colType = idx < 0 ? getProperties()->getColorMapping(material, cs) : ECIC_NONE; 2147 E_COLLADA_IRR_COLOR colType = idx < 0 ? getProperties()->getColorMapping(material, cs) : ECIC_NONE;
2148 if ( idx >= 0 || colType != ECIC_NONE ) 2148 if ( idx >= 0 || colType != ECIC_NONE )
2149 { 2149 {
2150 Writer->writeElement(colorname, false, attr1Name, attr1Value); 2150 Writer->writeElement(colorname, false, attr1Name, attr1Value);
2151 Writer->writeLineBreak(); 2151 Writer->writeLineBreak();
2152 if ( idx >= 0 ) 2152 if ( idx >= 0 )
2153 writeTextureSampler(idx); 2153 writeTextureSampler(idx);
2154 else 2154 else
2155 writeColorElement(getColorMapping(material, cs, colType)); 2155 writeColorElement(getColorMapping(material, cs, colType));
2156 Writer->writeClosingTag(colorname); 2156 Writer->writeClosingTag(colorname);
2157 Writer->writeLineBreak(); 2157 Writer->writeLineBreak();
2158 } 2158 }
2159} 2159}
2160 2160
2161void CColladaMeshWriter::writeNode(const wchar_t * nodeName, const wchar_t * content) 2161void CColladaMeshWriter::writeNode(const wchar_t * nodeName, const wchar_t * content)
2162{ 2162{
2163 Writer->writeElement(nodeName, false); 2163 Writer->writeElement(nodeName, false);
2164 Writer->writeText(content); 2164 Writer->writeText(content);
2165 Writer->writeClosingTag(nodeName); 2165 Writer->writeClosingTag(nodeName);
2166 Writer->writeLineBreak(); 2166 Writer->writeLineBreak();
2167} 2167}
2168 2168
2169void CColladaMeshWriter::writeFloatElement(irr::f32 value) 2169void CColladaMeshWriter::writeFloatElement(irr::f32 value)
2170{ 2170{
2171 Writer->writeElement(L"float", false); 2171 Writer->writeElement(L"float", false);
2172 Writer->writeText(core::stringw((double)value).c_str()); 2172 Writer->writeText(core::stringw((double)value).c_str());
2173 Writer->writeClosingTag(L"float"); 2173 Writer->writeClosingTag(L"float");
2174 Writer->writeLineBreak(); 2174 Writer->writeLineBreak();
2175} 2175}
2176 2176
2177void CColladaMeshWriter::writeRotateElement(const irr::core::vector3df& axis, irr::f32 angle) 2177void CColladaMeshWriter::writeRotateElement(const irr::core::vector3df& axis, irr::f32 angle)
2178{ 2178{
2179 Writer->writeElement(L"rotate", false); 2179 Writer->writeElement(L"rotate", false);
2180 irr::core::stringw txt(axis.X); 2180 irr::core::stringw txt(axis.X);
2181 txt += L" "; 2181 txt += L" ";
2182 txt += irr::core::stringw(axis.Y); 2182 txt += irr::core::stringw(axis.Y);
2183 txt += L" "; 2183 txt += L" ";
2184 txt += irr::core::stringw(axis.Z); 2184 txt += irr::core::stringw(axis.Z);
2185 txt += L" "; 2185 txt += L" ";
2186 txt += irr::core::stringw((double)angle); 2186 txt += irr::core::stringw((double)angle);
2187 Writer->writeText(txt.c_str()); 2187 Writer->writeText(txt.c_str());
2188 Writer->writeClosingTag(L"rotate"); 2188 Writer->writeClosingTag(L"rotate");
2189 Writer->writeLineBreak(); 2189 Writer->writeLineBreak();
2190} 2190}
2191 2191
2192void CColladaMeshWriter::writeScaleElement(const irr::core::vector3df& scale) 2192void CColladaMeshWriter::writeScaleElement(const irr::core::vector3df& scale)
2193{ 2193{
2194 Writer->writeElement(L"scale", false); 2194 Writer->writeElement(L"scale", false);
2195 irr::core::stringw txt(scale.X); 2195 irr::core::stringw txt(scale.X);
2196 txt += L" "; 2196 txt += L" ";
2197 txt += irr::core::stringw(scale.Y); 2197 txt += irr::core::stringw(scale.Y);
2198 txt += L" "; 2198 txt += L" ";
2199 txt += irr::core::stringw(scale.Z); 2199 txt += irr::core::stringw(scale.Z);
2200 Writer->writeText(txt.c_str()); 2200 Writer->writeText(txt.c_str());
2201 Writer->writeClosingTag(L"scale"); 2201 Writer->writeClosingTag(L"scale");
2202 Writer->writeLineBreak(); 2202 Writer->writeLineBreak();
2203} 2203}
2204 2204
2205void CColladaMeshWriter::writeTranslateElement(const irr::core::vector3df& translate) 2205void CColladaMeshWriter::writeTranslateElement(const irr::core::vector3df& translate)
2206{ 2206{
2207 Writer->writeElement(L"translate", false); 2207 Writer->writeElement(L"translate", false);
2208 irr::core::stringw txt(translate.X); 2208 irr::core::stringw txt(translate.X);
2209 txt += L" "; 2209 txt += L" ";
2210 txt += irr::core::stringw(translate.Y); 2210 txt += irr::core::stringw(translate.Y);
2211 txt += L" "; 2211 txt += L" ";
2212 txt += irr::core::stringw(translate.Z); 2212 txt += irr::core::stringw(translate.Z);
2213 Writer->writeText(txt.c_str()); 2213 Writer->writeText(txt.c_str());
2214 Writer->writeClosingTag(L"translate"); 2214 Writer->writeClosingTag(L"translate");
2215 Writer->writeLineBreak(); 2215 Writer->writeLineBreak();
2216} 2216}
2217 2217
2218void CColladaMeshWriter::writeMatrixElement(const irr::core::matrix4& matrix) 2218void CColladaMeshWriter::writeMatrixElement(const irr::core::matrix4& matrix)
2219{ 2219{
2220 Writer->writeElement(L"matrix", false); 2220 Writer->writeElement(L"matrix", false);
2221 Writer->writeLineBreak(); 2221 Writer->writeLineBreak();
2222 2222
2223 for ( int a=0; a<4; ++a ) 2223 for ( int a=0; a<4; ++a )
2224 { 2224 {
2225 irr::core::stringw txt; 2225 irr::core::stringw txt;
2226 for ( int b=0; b<4; ++b ) 2226 for ( int b=0; b<4; ++b )
2227 { 2227 {
2228 if ( b > 0 ) 2228 if ( b > 0 )
2229 txt += " "; 2229 txt += " ";
2230 // row-column switched compared to Irrlicht 2230 // row-column switched compared to Irrlicht
2231 txt += irr::core::stringw(matrix[b*4+a]); 2231 txt += irr::core::stringw(matrix[b*4+a]);
2232 } 2232 }
2233 Writer->writeText(txt.c_str()); 2233 Writer->writeText(txt.c_str());
2234 Writer->writeLineBreak(); 2234 Writer->writeLineBreak();
2235 } 2235 }
2236 2236
2237 Writer->writeClosingTag(L"matrix"); 2237 Writer->writeClosingTag(L"matrix");
2238 Writer->writeLineBreak(); 2238 Writer->writeLineBreak();
2239} 2239}
2240 2240
2241} // end namespace 2241} // end namespace
2242} // end namespace 2242} // end namespace
2243 2243
2244#endif 2244#endif
2245 2245