]> git.lizzy.rs Git - irrlicht.git/blob - source/Irrlicht/CColladaFileLoader.h
Fix some more problems with OSX build file.
[irrlicht.git] / source / Irrlicht / CColladaFileLoader.h
1 // Copyright (C) 2002-2012 Nikolaus Gebhardt\r
2 // This file is part of the "Irrlicht Engine".\r
3 // For conditions of distribution and use, see copyright notice in irrlicht.h\r
4 \r
5 #ifndef __C_COLLADA_MESH_FILE_LOADER_H_INCLUDED__\r
6 #define __C_COLLADA_MESH_FILE_LOADER_H_INCLUDED__\r
7 \r
8 #include "IMeshLoader.h"\r
9 #include "IFileSystem.h"\r
10 #include "IVideoDriver.h"\r
11 #include "irrString.h"\r
12 #include "SMesh.h"\r
13 #include "SMeshBuffer.h"\r
14 #include "ISceneManager.h"\r
15 #include "irrMap.h"\r
16 #include "CAttributes.h"\r
17 \r
18 namespace irr\r
19 {\r
20 namespace scene\r
21 {\r
22 \r
23 #ifdef _DEBUG\r
24 //#define COLLADA_READER_DEBUG\r
25 #endif\r
26 \r
27 class IColladaPrefab;\r
28 \r
29 enum ECOLLADA_PARAM_NAME\r
30 {\r
31         ECPN_COLOR = 0,\r
32         ECPN_AMBIENT,\r
33         ECPN_DIFFUSE,\r
34         ECPN_SPECULAR,\r
35         ECPN_SHININESS,\r
36         ECPN_TRANSPARENCY,\r
37         ECPN_YFOV,\r
38         ECPN_ZNEAR,\r
39         ECPN_ZFAR,\r
40 \r
41         ECPN_COUNT\r
42 };\r
43 \r
44 enum ECOLLADA_PARAM_TYPE\r
45 {\r
46         ECPT_FLOAT = 0,\r
47         ECPT_FLOAT2,\r
48         ECPT_FLOAT3,\r
49         ECPT_FLOAT4,\r
50 \r
51         ECPT_COUNT\r
52 };\r
53 \r
54 //! Collada Parameter\r
55 struct SColladaParam\r
56 {\r
57         SColladaParam()\r
58                 : Name(ECPN_COUNT), Type(ECPT_COUNT)\r
59         {\r
60                 for (int i=0; i<4; ++i) Floats[i] = 0;\r
61         }\r
62 \r
63         ECOLLADA_PARAM_NAME Name;\r
64         ECOLLADA_PARAM_TYPE Type;\r
65 \r
66         f32 Floats[4];\r
67 };\r
68 \r
69 enum ECOLLADA_INPUT_SEMANTIC\r
70 {\r
71         ECIS_POSITION = 0,\r
72         ECIS_VERTEX,\r
73         ECIS_NORMAL,\r
74         ECIS_TEXCOORD,\r
75         ECIS_UV,\r
76         ECIS_TANGENT,\r
77         ECIS_IMAGE,\r
78         ECIS_TEXTURE,\r
79         ECIS_COLOR,\r
80 \r
81         ECIS_COUNT\r
82 };\r
83 \r
84 //! Collada Input\r
85 struct SColladaInput\r
86 {\r
87         SColladaInput()\r
88                 : Semantic(ECIS_COUNT), Data(0), Offset(0), Set(0), Stride(1)\r
89         {\r
90         }\r
91 \r
92         ECOLLADA_INPUT_SEMANTIC Semantic;\r
93         core::stringc Source;\r
94         f32* Data;\r
95         u32 Offset;\r
96         u32 Set;\r
97         u32 Stride;\r
98 };\r
99 \r
100 //! Collada images\r
101 struct SColladaImage\r
102 {\r
103         core::stringc Id;\r
104         core::stringc Source;\r
105         core::dimension2du Dimension;\r
106         bool SourceIsFilename;\r
107 };\r
108 \r
109 \r
110 //! Collada texture\r
111 struct SColladaTexture\r
112 {\r
113         video::ITexture* Texture;\r
114         core::stringc Id;\r
115 };\r
116 \r
117 \r
118 //! Collada material\r
119 struct SColladaMaterial\r
120 {\r
121         video::SMaterial Mat;\r
122         core::stringc Id;\r
123         core::stringc InstanceEffectId;\r
124         f32 Transparency;\r
125 \r
126         inline bool operator< (const SColladaMaterial & other) const\r
127         {\r
128                 return Id < other.Id;\r
129         }\r
130 };\r
131 \r
132 //! Collada effect (materials, shaders, and programs)\r
133 struct SColladaEffect\r
134 {\r
135         core::stringc Id;\r
136         f32 Transparency;\r
137         core::array<core::stringc> Textures;\r
138         video::SMaterial Mat;\r
139         // TODO: Parameters looks somewhat lazy workaround, I think we should really read all parameters correct.\r
140         io::IAttributes * Parameters;\r
141 \r
142         inline bool operator< (const SColladaEffect & other) const\r
143         {\r
144                 return Id < other.Id;\r
145         }\r
146 };\r
147 \r
148 \r
149 struct SNumberArray // for storing float and int arrays\r
150 {\r
151         core::stringc Name;\r
152         core::array<f32> Data;\r
153 };\r
154 \r
155 struct SAccessor\r
156 {\r
157         SAccessor()\r
158                 : Count(0), Offset(0), Stride(1) {}\r
159         // I don't store the source of the accessor here because I assume\r
160         // it to use the array of the source this accessor is located in.\r
161 \r
162         int Count;\r
163         int Offset;\r
164         int Stride;\r
165 \r
166         core::array<SColladaParam> Parameters; // parameters defining the accessor\r
167 };\r
168 \r
169 struct SSource\r
170 {\r
171         core::stringc Id;\r
172         SNumberArray Array;\r
173         core::array<SAccessor> Accessors;\r
174 };\r
175 \r
176 class CScenePrefab;\r
177 \r
178 //! Meshloader capable of loading COLLADA meshes and scene descriptions into Irrlicht.\r
179 class CColladaFileLoader : public IMeshLoader\r
180 {\r
181 public:\r
182 \r
183         //! Constructor\r
184         CColladaFileLoader(scene::ISceneManager* smgr, io::IFileSystem* fs);\r
185 \r
186         //! destructor\r
187         virtual ~CColladaFileLoader();\r
188 \r
189         //! returns true if the file maybe is able to be loaded by this class\r
190         //! based on the file extension (e.g. ".cob")\r
191         virtual bool isALoadableFileExtension(const io::path& filename) const _IRR_OVERRIDE_;\r
192 \r
193         //! creates/loads an animated mesh from the file.\r
194         //! \return Pointer to the created mesh. Returns 0 if loading failed.\r
195         //! If you no longer need the mesh, you should call IAnimatedMesh::drop().\r
196         //! See IReferenceCounted::drop() for more information.\r
197         virtual IAnimatedMesh* createMesh(io::IReadFile* file) _IRR_OVERRIDE_;\r
198 \r
199 private:\r
200 \r
201         //! skips an (unknown) section in the collada document\r
202         void skipSection(io::IXMLReaderUTF8* reader, bool reportSkipping);\r
203 \r
204         //! reads the <COLLADA> section and its content\r
205         void readColladaSection(io::IXMLReaderUTF8* reader);\r
206 \r
207         //! reads a <library> section and its content\r
208         void readLibrarySection(io::IXMLReaderUTF8* reader);\r
209 \r
210         //! reads a <visual_scene> element and stores it as a prefab\r
211         void readVisualScene(io::IXMLReaderUTF8* reader);\r
212 \r
213         //! reads a <scene> section and its content\r
214         void readSceneSection(io::IXMLReaderUTF8* reader);\r
215 \r
216         //! reads a <asset> section and its content\r
217         void readAssetSection(io::IXMLReaderUTF8* reader);\r
218 \r
219         //! reads a <node> section and its content\r
220         //! if a prefab pointer is passed the nodes are created as scene prefabs children of that prefab\r
221         void readNodeSection(io::IXMLReaderUTF8* reader, scene::ISceneNode* parent, CScenePrefab* p=0);\r
222 \r
223         //! reads a <lookat> element and its content and creates a matrix from it\r
224         core::matrix4 readLookAtNode(io::IXMLReaderUTF8* reader);\r
225 \r
226         //! reads a <matrix> element and its content and creates a matrix from it\r
227         core::matrix4 readMatrixNode(io::IXMLReaderUTF8* reader);\r
228 \r
229         //! reads a <perspective> element and its content and creates a matrix from it\r
230         core::matrix4 readPerspectiveNode(io::IXMLReaderUTF8* reader);\r
231 \r
232         //! reads a <rotate> element and its content and creates a matrix from it\r
233         core::matrix4 readRotateNode(io::IXMLReaderUTF8* reader);\r
234 \r
235         //! reads a <skew> element and its content and creates a matrix from it\r
236         core::matrix4 readSkewNode(io::IXMLReaderUTF8* reader);\r
237 \r
238         //! reads a <boundingbox> element and its content and stores it in bbox\r
239         void readBboxNode(io::IXMLReaderUTF8* reader, core::aabbox3df& bbox);\r
240 \r
241         //! reads a <scale> element and its content and creates a matrix from it\r
242         core::matrix4 readScaleNode(io::IXMLReaderUTF8* reader);\r
243 \r
244         //! reads a <translate> element and its content and creates a matrix from it\r
245         core::matrix4 readTranslateNode(io::IXMLReaderUTF8* reader);\r
246 \r
247         //! reads a <color> element\r
248         video::SColorf readColorNode(io::IXMLReaderUTF8* reader);\r
249 \r
250         //! reads a <float> element\r
251         f32 readFloatNode(io::IXMLReaderUTF8* reader);\r
252 \r
253         //! reads a <instance> node\r
254         void readInstanceNode(io::IXMLReaderUTF8* reader,\r
255                         scene::ISceneNode* parent, scene::ISceneNode** outNode,\r
256                         CScenePrefab* p=0, const core::stringc& type=core::stringc());\r
257 \r
258         //! creates a scene node from Prefabs (with name given in 'url')\r
259         void instantiateNode(scene::ISceneNode* parent, scene::ISceneNode** outNode=0,\r
260                         CScenePrefab* p=0, const core::stringc& url="",\r
261                         const core::stringc& type=core::stringc());\r
262 \r
263         //! reads a <light> element and stores it as prefab\r
264         void readLightPrefab(io::IXMLReaderUTF8* reader);\r
265 \r
266         //! reads a <camera> element and stores it as prefab\r
267         void readCameraPrefab(io::IXMLReaderUTF8* reader);\r
268 \r
269         //! reads a <image> element and stores it in the image section\r
270         void readImage(io::IXMLReaderUTF8* reader);\r
271 \r
272         //! reads a <texture> element and stores it in the texture section\r
273         void readTexture(io::IXMLReaderUTF8* reader);\r
274 \r
275         //! reads a <material> element and stores it in the material section\r
276         void readMaterial(io::IXMLReaderUTF8* reader);\r
277 \r
278         //! reads a <effect> element and stores it in the effects section\r
279         void readEffect(io::IXMLReaderUTF8* reader, SColladaEffect * effect = 0);\r
280 \r
281         //! reads a <geometry> element and stores it as mesh if possible\r
282         void readGeometry(io::IXMLReaderUTF8* reader);\r
283 \r
284         //! parses a float from a char pointer and moves the pointer to\r
285         //! the end of the parsed float\r
286         inline f32 readFloat(const c8** p);\r
287 \r
288         //! parses an int from a char pointer and moves the pointer to\r
289         //! the end of the parsed float\r
290         inline s32 readInt(const c8** p);\r
291 \r
292         //! places pointer to next begin of a token\r
293         void findNextNoneWhiteSpace(const c8** p);\r
294 \r
295         //! reads floats from inside of xml element until end of xml element\r
296         void readFloatsInsideElement(io::IXMLReaderUTF8* reader, f32* floats, u32 count);\r
297 \r
298         //! reads ints from inside of xml element until end of xml element\r
299         void readIntsInsideElement(io::IXMLReaderUTF8* reader, s32* ints, u32 count);\r
300 \r
301         //! clears all loaded data\r
302         void clearData();\r
303 \r
304         //! parses all collada parameters inside an element and stores them in ColladaParameters\r
305         void readColladaParameters(io::IXMLReaderUTF8* reader, const core::stringc& parentName);\r
306 \r
307         //! returns a collada parameter or none if not found\r
308         SColladaParam* getColladaParameter(ECOLLADA_PARAM_NAME name);\r
309 \r
310         //! parses all collada inputs inside an element and stores them in Inputs. Reads\r
311         //! until first tag which is not an input tag or the end of the parent is reached\r
312         void readColladaInputs(io::IXMLReaderUTF8* reader, const core::stringc& parentName);\r
313 \r
314         //! reads a collada input tag and adds it to the input parameter\r
315         void readColladaInput(io::IXMLReaderUTF8* reader, core::array<SColladaInput>& inputs);\r
316 \r
317         //! returns a collada input or none if not found\r
318         SColladaInput* getColladaInput(ECOLLADA_INPUT_SEMANTIC input);\r
319 \r
320         //! read Collada Id, uses id or name if id is missing\r
321         core::stringc readId(io::IXMLReaderUTF8* reader);\r
322 \r
323         //! changes the XML URI into an internal id\r
324         void uriToId(core::stringc& str);\r
325 \r
326         //! reads a polygons section and creates a mesh from it\r
327         void readPolygonSection(io::IXMLReaderUTF8* reader,\r
328                         core::array<SSource>& sources, scene::SMesh* mesh,\r
329                         const core::stringc& geometryId);\r
330 \r
331         //! finds a material, possible instancing it\r
332         const SColladaMaterial * findMaterial(const core::stringc & materialName);\r
333 \r
334         //! reads and bind materials as given by the symbol->target bind mapping\r
335         void readBindMaterialSection(io::IXMLReaderUTF8* reader, const core::stringc & id);\r
336 \r
337         //! create an Irrlicht texture from the SColladaImage\r
338         video::ITexture* getTextureFromImage(core::stringc uri, SColladaEffect * effect);\r
339 \r
340         //! read a parameter and value\r
341         void readParameter(io::IXMLReaderUTF8* reader, io::IAttributes* parameters);\r
342 \r
343         //! Flip z axis in matrix around to convert between right-handed and left-handed coordinate system.\r
344         //! Note that function is symmetric (no difference if called before or after a transpose).\r
345         core::matrix4 flipZAxis(const core::matrix4& m);\r
346 \r
347         //! replace escape characters with the unescaped ones\r
348         void unescape(irr::core::stringc& uri);\r
349 \r
350         scene::ISceneManager* SceneManager;\r
351         io::IFileSystem* FileSystem;\r
352 \r
353         scene::IAnimatedMesh* DummyMesh;\r
354         core::stringc CurrentlyLoadingMesh;\r
355 \r
356         scene::IAnimatedMesh* FirstLoadedMesh;\r
357         io::path FirstLoadedMeshName;\r
358         s32 LoadedMeshCount;\r
359         u32 Version;\r
360         bool FlipAxis;\r
361 \r
362         core::array<IColladaPrefab*> Prefabs;\r
363         core::array<SColladaParam> ColladaParameters;\r
364         core::array<SColladaImage> Images;\r
365         core::array<SColladaTexture> Textures;\r
366         core::array<SColladaMaterial> Materials;\r
367         core::array<SColladaInput> Inputs;\r
368         core::array<SColladaEffect> Effects;\r
369         //! meshbuffer reference ("geomid/matname") -> index into MeshesToBind\r
370         core::map<core::stringc,u32> MaterialsToBind;\r
371         //! Array of buffers for each material binding\r
372         core::array< core::array<irr::scene::IMeshBuffer*> > MeshesToBind;\r
373 \r
374         bool CreateInstances;\r
375 \r
376         struct EscapeCharacterURL\r
377         {\r
378                 EscapeCharacterURL(irr::c8 c, const irr::c8* e)\r
379                         : Character(c)\r
380                 {\r
381                         Escape = e;\r
382                 }\r
383 \r
384                 irr::c8 Character;              // unescaped (like ' ')\r
385                 irr::core::stringc Escape;      // escaped (like '%20')\r
386         };\r
387         irr::core::array<EscapeCharacterURL> EscapeCharsAnyURI;\r
388 };\r
389 \r
390 \r
391 \r
392 //! following class is for holding and createing instances of library objects,\r
393 //! named prefabs in this loader.\r
394 class IColladaPrefab : public virtual IReferenceCounted\r
395 {\r
396 public:\r
397         //! creates an instance of this prefab\r
398         virtual scene::ISceneNode* addInstance(scene::ISceneNode* parent,\r
399                 scene::ISceneManager* mgr) = 0;\r
400 \r
401         //! returns id of this prefab\r
402         virtual const core::stringc& getId() = 0;\r
403 };\r
404 \r
405 \r
406 } // end namespace scene\r
407 } // end namespace irr\r
408 \r
409 #endif\r
410 \r