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