diff options
author | David Walter Seikel | 2013-01-13 18:54:10 +1000 |
---|---|---|
committer | David Walter Seikel | 2013-01-13 18:54:10 +1000 |
commit | 959831f4ef5a3e797f576c3de08cd65032c997ad (patch) | |
tree | e7351908be5995f0b325b2ebeaa02d5a34b82583 /libraries/irrlicht-1.8/source/Irrlicht/CColladaMeshWriter.cpp | |
parent | Add info about changes to Irrlicht. (diff) | |
download | SledjHamr-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.cpp | 4490 |
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 | ||
25 | namespace irr | 25 | namespace irr |
26 | { | 26 | { |
27 | namespace scene | 27 | namespace 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) |
31 | E_COLLADA_TECHNIQUE_FX CColladaMeshWriterProperties::getTechniqueFx(const video::SMaterial& material) const | 31 | E_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. |
37 | s32 CColladaMeshWriterProperties::getTextureIdx(const video::SMaterial & material, E_COLLADA_COLOR_SAMPLER cs) const | 37 | s32 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 | ||
60 | E_COLLADA_IRR_COLOR CColladaMeshWriterProperties::getColorMapping(const video::SMaterial & material, E_COLLADA_COLOR_SAMPLER cs) const | 60 | E_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. |
82 | video::SColor CColladaMeshWriterProperties::getCustomColor(const video::SMaterial & material, E_COLLADA_COLOR_SAMPLER cs) const | 82 | video::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 |
89 | E_COLLADA_TRANSPARENT_FX CColladaMeshWriterProperties::getTransparentFx(const video::SMaterial& material) const | 89 | E_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. |
96 | f32 CColladaMeshWriterProperties::getTransparency(const video::SMaterial& material) const | 96 | f32 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 |
103 | f32 CColladaMeshWriterProperties::getReflectivity(const video::SMaterial& material) const | 103 | f32 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 |
110 | f32 CColladaMeshWriterProperties::getIndexOfRefraction(const video::SMaterial& material) const | 110 | f32 CColladaMeshWriterProperties::getIndexOfRefraction(const video::SMaterial& material) const |
111 | { | 111 | { |
112 | return -1.f; | 112 | return -1.f; |
113 | } | 113 | } |
114 | 114 | ||
115 | bool CColladaMeshWriterProperties::isExportable(const irr::scene::ISceneNode * node) const | 115 | bool CColladaMeshWriterProperties::isExportable(const irr::scene::ISceneNode * node) const |
116 | { | 116 | { |
117 | return node && node->isVisible(); | 117 | return node && node->isVisible(); |
118 | } | 118 | } |
119 | 119 | ||
120 | IMesh* CColladaMeshWriterProperties::getMesh(irr::scene::ISceneNode * node) | 120 | IMesh* 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 |
140 | bool CColladaMeshWriterProperties::useNodeMaterial(const scene::ISceneNode* node) const | 140 | bool 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 | ||
161 | CColladaMeshWriterNames::CColladaMeshWriterNames(IColladaMeshWriter * writer) | 161 | CColladaMeshWriterNames::CColladaMeshWriterNames(IColladaMeshWriter * writer) |
162 | : ColladaMeshWriter(writer) | 162 | : ColladaMeshWriter(writer) |
163 | { | 163 | { |
164 | } | 164 | } |
165 | 165 | ||
166 | irr::core::stringw CColladaMeshWriterNames::nameForMesh(const scene::IMesh* mesh, int instance) | 166 | irr::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 | ||
178 | irr::core::stringw CColladaMeshWriterNames::nameForNode(const scene::ISceneNode* node) | 178 | irr::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 | ||
194 | irr::core::stringw CColladaMeshWriterNames::nameForMaterial(const video::SMaterial & material, int materialId, const scene::IMesh* mesh, const scene::ISceneNode* node) | 194 | irr::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 | ||
211 | irr::core::stringw CColladaMeshWriterNames::nameForPtr(const void* ptr) const | 211 | irr::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 | ||
220 | CColladaMeshWriter::CColladaMeshWriter( ISceneManager * smgr, video::IVideoDriver* driver, | 220 | CColladaMeshWriter::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 | ||
250 | CColladaMeshWriter::~CColladaMeshWriter() | 250 | CColladaMeshWriter::~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 | ||
260 | void CColladaMeshWriter::reset() | 260 | void 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 |
272 | EMESH_WRITER_TYPE CColladaMeshWriter::getType() const | 272 | EMESH_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 |
278 | bool CColladaMeshWriter::writeScene(io::IWriteFile* file, scene::ISceneNode* root) | 278 | bool 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 | ||
414 | void CColladaMeshWriter::makeMeshNames(irr::scene::ISceneNode * node) | 414 | void 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 | ||
437 | void CColladaMeshWriter::writeNodeMaterials(irr::scene::ISceneNode * node) | 437 | void 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 | ||
498 | void CColladaMeshWriter::writeMaterial(const irr::core::stringw& materialname) | 498 | void 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 | ||
521 | void CColladaMeshWriter::writeNodeEffects(irr::scene::ISceneNode * node) | 521 | void 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 | ||
559 | void CColladaMeshWriter::writeNodeLights(irr::scene::ISceneNode * node) | 559 | void 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 | ||
639 | void CColladaMeshWriter::writeNodeCameras(irr::scene::ISceneNode * node) | 639 | void 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 | ||
704 | void CColladaMeshWriter::writeAllMeshGeometries() | 704 | void 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 | ||
726 | void CColladaMeshWriter::writeSceneNode(irr::scene::ISceneNode * node ) | 726 | void 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 |
799 | bool CColladaMeshWriter::writeMesh(io::IWriteFile* file, scene::IMesh* mesh, s32 flags) | 799 | bool 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 | ||
906 | void CColladaMeshWriter::writeMeshInstanceGeometry(const irr::core::stringw& meshname, scene::IMesh* mesh, scene::ISceneNode* node) | 906 | void 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 | ||
949 | void CColladaMeshWriter::writeLightInstance(const irr::core::stringw& lightName) | 949 | void 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 | ||
955 | void CColladaMeshWriter::writeCameraInstance(const irr::core::stringw& cameraName) | 955 | void 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 | ||
961 | bool CColladaMeshWriter::hasSecondTextureCoordinates(video::E_VERTEX_TYPE type) const | 961 | bool 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 | ||
966 | void CColladaMeshWriter::writeVector(const irr::core::vector3df& vec) | 966 | void 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 | ||
974 | void CColladaMeshWriter::writeUv(const irr::core::vector2df& vec) | 974 | void 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 | ||
983 | void CColladaMeshWriter::writeVector(const irr::core::vector2df& vec) | 983 | void 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 | ||
991 | void CColladaMeshWriter::writeColor(const irr::video::SColorf& colorf, bool writeAlpha) | 991 | void 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 | ||
1002 | irr::core::stringw CColladaMeshWriter::toString(const irr::video::ECOLOR_FORMAT format) const | 1002 | irr::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 | ||
1014 | irr::core::stringw CColladaMeshWriter::toString(const irr::video::E_TEXTURE_CLAMP clamp) const | 1014 | irr::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 | ||
1034 | irr::core::stringw CColladaMeshWriter::toString(const irr::scene::E_COLLADA_TRANSPARENT_FX transparent) const | 1034 | irr::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 | ||
1042 | irr::core::stringw CColladaMeshWriter::toRef(const irr::core::stringw& source) const | 1042 | irr::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 | ||
1049 | bool CColladaMeshWriter::isCamera(const scene::ISceneNode* node) const | 1049 | bool 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 | ||
1059 | irr::core::stringw CColladaMeshWriter::nameForMesh(const scene::IMesh* mesh, int instance) const | 1059 | irr::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 | ||
1069 | irr::core::stringw CColladaMeshWriter::nameForNode(const scene::ISceneNode* node) const | 1069 | irr::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 | ||
1079 | irr::core::stringw CColladaMeshWriter::nameForMaterial(const video::SMaterial & material, int materialId, const scene::IMesh* mesh, const scene::ISceneNode* node) | 1079 | irr::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 |
1103 | irr::core::stringw CColladaMeshWriter::nameForMaterialSymbol(const scene::IMesh* mesh, int materialId) const | 1103 | irr::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 | ||
1110 | irr::core::stringw CColladaMeshWriter::findCachedMaterialName(const irr::video::SMaterial& material) const | 1110 | irr::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 | ||
1120 | irr::core::stringw CColladaMeshWriter::minTexfilterToString(bool bilinear, bool trilinear) const | 1120 | irr::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 | ||
1130 | inline irr::core::stringw CColladaMeshWriter::magTexfilterToString(bool bilinear, bool trilinear) const | 1130 | inline 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 | ||
1138 | bool CColladaMeshWriter::isXmlNameStartChar(wchar_t c) const | 1138 | bool 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 | ||
1160 | bool CColladaMeshWriter::isXmlNameChar(wchar_t c) const | 1160 | bool 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. |
1172 | irr::core::stringw CColladaMeshWriter::toNCName(const irr::core::stringw& oldString, const irr::core::stringw& prefix) const | 1172 | irr::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. |
1193 | irr::core::stringw CColladaMeshWriter::pathToURI(const irr::io::path& path) const | 1193 | irr::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 | ||
1217 | void CColladaMeshWriter::writeAsset() | 1217 | void 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 | ||
1251 | void CColladaMeshWriter::writeMeshMaterials(scene::IMesh* mesh, irr::core::array<irr::core::stringw> * materialNamesOut) | 1251 | void 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 | ||
1264 | void CColladaMeshWriter::writeMaterialEffect(const irr::core::stringw& materialfxname, const video::SMaterial & material) | 1264 | void 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 | ||
1398 | void CColladaMeshWriter::writeMeshEffects(scene::IMesh* mesh) | 1398 | void 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 | ||
1409 | void CColladaMeshWriter::writeMeshGeometry(const irr::core::stringw& meshname, scene::IMesh* mesh) | 1409 | void 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 | ||
1899 | void CColladaMeshWriter::writeLibraryImages() | 1899 | void 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 | ||
1928 | void CColladaMeshWriter::writeColorElement(const video::SColorf & col, bool writeAlpha) | 1928 | void 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 | ||
1938 | void CColladaMeshWriter::writeColorElement(const video::SColor & col, bool writeAlpha) | 1938 | void 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 | ||
1943 | void CColladaMeshWriter::writeAmbientLightElement(const video::SColorf & col) | 1943 | void 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 | ||
1966 | s32 CColladaMeshWriter::getCheckedTextureIdx(const video::SMaterial & material, E_COLLADA_COLOR_SAMPLER cs) | 1966 | s32 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 | ||
1979 | video::SColor CColladaMeshWriter::getColorMapping(const video::SMaterial & material, E_COLLADA_COLOR_SAMPLER cs, E_COLLADA_IRR_COLOR colType) | 1979 | video::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 | ||
2004 | void CColladaMeshWriter::writeTextureSampler(s32 textureIdx) | 2004 | void 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 | ||
2015 | void CColladaMeshWriter::writeFxElement(const video::SMaterial & material, E_COLLADA_TECHNIQUE_FX techFx) | 2015 | void 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 | ||
2144 | void CColladaMeshWriter::writeColorFx(const video::SMaterial & material, const wchar_t * colorname, E_COLLADA_COLOR_SAMPLER cs, const wchar_t* attr1Name, const wchar_t* attr1Value) | 2144 | void 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 | ||
2161 | void CColladaMeshWriter::writeNode(const wchar_t * nodeName, const wchar_t * content) | 2161 | void 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 | ||
2169 | void CColladaMeshWriter::writeFloatElement(irr::f32 value) | 2169 | void 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 | ||
2177 | void CColladaMeshWriter::writeRotateElement(const irr::core::vector3df& axis, irr::f32 angle) | 2177 | void 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 | ||
2192 | void CColladaMeshWriter::writeScaleElement(const irr::core::vector3df& scale) | 2192 | void 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 | ||
2205 | void CColladaMeshWriter::writeTranslateElement(const irr::core::vector3df& translate) | 2205 | void 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 | ||
2218 | void CColladaMeshWriter::writeMatrixElement(const irr::core::matrix4& matrix) | 2218 | void 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 | ||