diff options
Diffstat (limited to '')
-rw-r--r-- | libraries/irrlicht-1.8.1/source/Irrlicht/COgreMeshFileLoader.cpp | 1592 |
1 files changed, 1592 insertions, 0 deletions
diff --git a/libraries/irrlicht-1.8.1/source/Irrlicht/COgreMeshFileLoader.cpp b/libraries/irrlicht-1.8.1/source/Irrlicht/COgreMeshFileLoader.cpp new file mode 100644 index 0000000..7a2be26 --- /dev/null +++ b/libraries/irrlicht-1.8.1/source/Irrlicht/COgreMeshFileLoader.cpp | |||
@@ -0,0 +1,1592 @@ | |||
1 | // Copyright (C) 2002-2012 Nikolaus Gebhardt | ||
2 | // This file is part of the "Irrlicht Engine". | ||
3 | // For conditions of distribution and use, see copyright notice in irrlicht.h | ||
4 | // orginally written by Christian Stehno, modified by Nikolaus Gebhardt | ||
5 | |||
6 | #include "IrrCompileConfig.h" | ||
7 | #ifdef _IRR_COMPILE_WITH_OGRE_LOADER_ | ||
8 | |||
9 | #include "COgreMeshFileLoader.h" | ||
10 | #include "os.h" | ||
11 | #include "SMeshBuffer.h" | ||
12 | #include "SAnimatedMesh.h" | ||
13 | #include "IReadFile.h" | ||
14 | #include "fast_atof.h" | ||
15 | #include "coreutil.h" | ||
16 | |||
17 | #ifdef _DEBUG | ||
18 | #define IRR_OGRE_LOADER_DEBUG | ||
19 | #endif | ||
20 | |||
21 | namespace irr | ||
22 | { | ||
23 | namespace scene | ||
24 | { | ||
25 | |||
26 | namespace | ||
27 | { | ||
28 | enum OGRE_CHUNKS | ||
29 | { | ||
30 | // Main Chunks | ||
31 | COGRE_HEADER= 0x1000, | ||
32 | COGRE_SKELETON= 0x2000, | ||
33 | COGRE_MESH= 0x3000, | ||
34 | |||
35 | // sub chunks of COGRE_MESH | ||
36 | COGRE_SUBMESH= 0x4000, | ||
37 | COGRE_GEOMETRY= 0x5000, | ||
38 | COGRE_SKELETON_LINK= 0x6000, | ||
39 | COGRE_BONE_ASSIGNMENT= 0x7000, | ||
40 | COGRE_MESH_LOD= 0x8000, | ||
41 | COGRE_MESH_BOUNDS= 0x9000, | ||
42 | COGRE_MESH_SUBMESH_NAME_TABLE= 0xA000, | ||
43 | COGRE_MESH_EDGE_LISTS= 0xB000, | ||
44 | |||
45 | // sub chunks of COGRE_SKELETON | ||
46 | COGRE_BONE_PARENT= 0x3000, | ||
47 | COGRE_ANIMATION= 0x4000, | ||
48 | COGRE_ANIMATION_TRACK= 0x4100, | ||
49 | COGRE_ANIMATION_KEYFRAME= 0x4110, | ||
50 | COGRE_ANIMATION_LINK= 0x5000, | ||
51 | |||
52 | // sub chunks of COGRE_SUBMESH | ||
53 | COGRE_SUBMESH_OPERATION= 0x4010, | ||
54 | COGRE_SUBMESH_BONE_ASSIGNMENT= 0x4100, | ||
55 | COGRE_SUBMESH_TEXTURE_ALIAS= 0x4200, | ||
56 | |||
57 | // sub chunks of COGRE_GEOMETRY | ||
58 | COGRE_GEOMETRY_VERTEX_DECLARATION= 0x5100, | ||
59 | COGRE_GEOMETRY_VERTEX_ELEMENT= 0x5110, | ||
60 | COGRE_GEOMETRY_VERTEX_BUFFER= 0x5200, | ||
61 | COGRE_GEOMETRY_VERTEX_BUFFER_DATA= 0x5210 | ||
62 | }; | ||
63 | } | ||
64 | |||
65 | //! Constructor | ||
66 | COgreMeshFileLoader::COgreMeshFileLoader(io::IFileSystem* fs, video::IVideoDriver* driver) | ||
67 | : FileSystem(fs), Driver(driver), SwapEndian(false), Mesh(0), NumUV(0) | ||
68 | { | ||
69 | |||
70 | #ifdef _DEBUG | ||
71 | setDebugName("COgreMeshFileLoader"); | ||
72 | #endif | ||
73 | |||
74 | if (FileSystem) | ||
75 | FileSystem->grab(); | ||
76 | |||
77 | if (Driver) | ||
78 | Driver->grab(); | ||
79 | } | ||
80 | |||
81 | |||
82 | //! destructor | ||
83 | COgreMeshFileLoader::~COgreMeshFileLoader() | ||
84 | { | ||
85 | clearMeshes(); | ||
86 | |||
87 | if (FileSystem) | ||
88 | FileSystem->drop(); | ||
89 | |||
90 | if (Driver) | ||
91 | Driver->drop(); | ||
92 | |||
93 | if (Mesh) | ||
94 | Mesh->drop(); | ||
95 | } | ||
96 | |||
97 | |||
98 | //! returns true if the file maybe is able to be loaded by this class | ||
99 | //! based on the file extension (e.g. ".bsp") | ||
100 | bool COgreMeshFileLoader::isALoadableFileExtension(const io::path& filename) const | ||
101 | { | ||
102 | return core::hasFileExtension ( filename, "mesh" ); | ||
103 | } | ||
104 | |||
105 | |||
106 | //! creates/loads an animated mesh from the file. | ||
107 | //! \return Pointer to the created mesh. Returns 0 if loading failed. | ||
108 | //! If you no longer need the mesh, you should call IAnimatedMesh::drop(). | ||
109 | //! See IReferenceCounted::drop() for more information. | ||
110 | IAnimatedMesh* COgreMeshFileLoader::createMesh(io::IReadFile* file) | ||
111 | { | ||
112 | s16 id; | ||
113 | |||
114 | file->read(&id, 2); | ||
115 | |||
116 | if (id == COGRE_HEADER) | ||
117 | SwapEndian=false; | ||
118 | else if (id == 0x0010) | ||
119 | SwapEndian=true; | ||
120 | else | ||
121 | return 0; | ||
122 | ChunkData data; | ||
123 | readString(file, data, Version); | ||
124 | if ((Version != "[MeshSerializer_v1.30]") && (Version != "[MeshSerializer_v1.40]") && (Version != "[MeshSerializer_v1.41]")) | ||
125 | return 0; | ||
126 | |||
127 | clearMeshes(); | ||
128 | if (Mesh) | ||
129 | Mesh->drop(); | ||
130 | |||
131 | CurrentlyLoadingFromPath = FileSystem->getFileDir(file->getFileName()); | ||
132 | loadMaterials(file); | ||
133 | |||
134 | if (readChunk(file)) | ||
135 | { | ||
136 | // delete data loaded from file | ||
137 | clearMeshes(); | ||
138 | |||
139 | if (Skeleton.Bones.size()) | ||
140 | { | ||
141 | ISkinnedMesh* tmp = static_cast<CSkinnedMesh*>(Mesh); | ||
142 | static_cast<CSkinnedMesh*>(Mesh)->updateBoundingBox(); | ||
143 | Skeleton.Animations.clear(); | ||
144 | Skeleton.Bones.clear(); | ||
145 | Mesh=0; | ||
146 | return tmp; | ||
147 | } | ||
148 | else | ||
149 | { | ||
150 | for (u32 i=0; i<Mesh->getMeshBufferCount(); ++i) | ||
151 | ((SMeshBuffer*)Mesh->getMeshBuffer(i))->recalculateBoundingBox(); | ||
152 | |||
153 | ((SMesh*)Mesh)->recalculateBoundingBox(); | ||
154 | SAnimatedMesh* am = new SAnimatedMesh(); | ||
155 | am->Type = EAMT_3DS; | ||
156 | am->addMesh(Mesh); | ||
157 | am->recalculateBoundingBox(); | ||
158 | Mesh->drop(); | ||
159 | Mesh = 0; | ||
160 | return am; | ||
161 | } | ||
162 | } | ||
163 | |||
164 | Mesh->drop(); | ||
165 | Mesh = 0; | ||
166 | |||
167 | return 0; | ||
168 | } | ||
169 | |||
170 | |||
171 | bool COgreMeshFileLoader::readChunk(io::IReadFile* file) | ||
172 | { | ||
173 | while(file->getPos() < file->getSize()) | ||
174 | { | ||
175 | ChunkData data; | ||
176 | readChunkData(file, data); | ||
177 | |||
178 | switch(data.header.id) | ||
179 | { | ||
180 | case COGRE_MESH: | ||
181 | { | ||
182 | Meshes.push_back(OgreMesh()); | ||
183 | readObjectChunk(file, data, Meshes.getLast()); | ||
184 | if (Skeleton.Bones.size()) | ||
185 | Mesh = new CSkinnedMesh(); | ||
186 | else | ||
187 | Mesh = new SMesh(); | ||
188 | composeObject(); | ||
189 | } | ||
190 | break; | ||
191 | default: | ||
192 | return true; | ||
193 | } | ||
194 | } | ||
195 | |||
196 | return true; | ||
197 | } | ||
198 | |||
199 | |||
200 | bool COgreMeshFileLoader::readObjectChunk(io::IReadFile* file, ChunkData& parent, OgreMesh& mesh) | ||
201 | { | ||
202 | #ifdef IRR_OGRE_LOADER_DEBUG | ||
203 | os::Printer::log("Read Object Chunk", ELL_DEBUG); | ||
204 | #endif | ||
205 | readBool(file, parent, mesh.SkeletalAnimation); | ||
206 | bool skeleton_loaded=false; | ||
207 | while ((parent.read < parent.header.length)&&(file->getPos() < file->getSize())) | ||
208 | { | ||
209 | ChunkData data; | ||
210 | readChunkData(file, data); | ||
211 | |||
212 | switch(data.header.id) | ||
213 | { | ||
214 | case COGRE_GEOMETRY: | ||
215 | readGeometry(file, data, mesh.Geometry); | ||
216 | break; | ||
217 | case COGRE_SUBMESH: | ||
218 | mesh.SubMeshes.push_back(OgreSubMesh()); | ||
219 | readSubMesh(file, data, mesh.SubMeshes.getLast()); | ||
220 | break; | ||
221 | case COGRE_MESH_BOUNDS: | ||
222 | { | ||
223 | #ifdef IRR_OGRE_LOADER_DEBUG | ||
224 | os::Printer::log("Read Mesh Bounds", ELL_DEBUG); | ||
225 | #endif | ||
226 | readVector(file, data, mesh.BBoxMinEdge); | ||
227 | readVector(file, data, mesh.BBoxMaxEdge); | ||
228 | readFloat(file, data, &mesh.BBoxRadius); | ||
229 | } | ||
230 | break; | ||
231 | case COGRE_SKELETON_LINK: | ||
232 | { | ||
233 | #ifdef IRR_OGRE_LOADER_DEBUG | ||
234 | os::Printer::log("Read Skeleton link", ELL_DEBUG); | ||
235 | #endif | ||
236 | core::stringc name; | ||
237 | readString(file, data, name); | ||
238 | loadSkeleton(file, name); | ||
239 | skeleton_loaded=true; | ||
240 | } | ||
241 | break; | ||
242 | case COGRE_BONE_ASSIGNMENT: | ||
243 | { | ||
244 | mesh.BoneAssignments.push_back(OgreBoneAssignment()); | ||
245 | readInt(file, data, &mesh.BoneAssignments.getLast().VertexID); | ||
246 | readShort(file, data, &mesh.BoneAssignments.getLast().BoneID); | ||
247 | readFloat(file, data, &mesh.BoneAssignments.getLast().Weight); | ||
248 | } | ||
249 | break; | ||
250 | case COGRE_MESH_LOD: | ||
251 | case COGRE_MESH_SUBMESH_NAME_TABLE: | ||
252 | case COGRE_MESH_EDGE_LISTS: | ||
253 | // ignore chunk | ||
254 | file->seek(data.header.length-data.read, true); | ||
255 | data.read += data.header.length-data.read; | ||
256 | break; | ||
257 | default: | ||
258 | #ifdef IRR_OGRE_LOADER_DEBUG | ||
259 | os::Printer::log("Skipping", core::stringc(data.header.id), ELL_DEBUG); | ||
260 | #endif | ||
261 | // ignore chunk | ||
262 | file->seek(data.header.length-data.read, true); | ||
263 | data.read += data.header.length-data.read; | ||
264 | break; | ||
265 | } | ||
266 | parent.read += data.read; | ||
267 | } | ||
268 | if (!skeleton_loaded) | ||
269 | loadSkeleton(file, FileSystem->getFileBasename(file->getFileName(), false)); | ||
270 | return true; | ||
271 | } | ||
272 | |||
273 | |||
274 | bool COgreMeshFileLoader::readGeometry(io::IReadFile* file, ChunkData& parent, OgreGeometry& geometry) | ||
275 | { | ||
276 | #ifdef IRR_OGRE_LOADER_DEBUG | ||
277 | os::Printer::log("Read Geometry", ELL_DEBUG); | ||
278 | #endif | ||
279 | readInt(file, parent, &geometry.NumVertex); | ||
280 | while(parent.read < parent.header.length) | ||
281 | { | ||
282 | ChunkData data; | ||
283 | readChunkData(file, data); | ||
284 | |||
285 | switch(data.header.id) | ||
286 | { | ||
287 | case COGRE_GEOMETRY_VERTEX_DECLARATION: | ||
288 | readVertexDeclaration(file, data, geometry); | ||
289 | break; | ||
290 | case COGRE_GEOMETRY_VERTEX_BUFFER: | ||
291 | readVertexBuffer(file, data, geometry); | ||
292 | break; | ||
293 | default: | ||
294 | // ignore chunk | ||
295 | #ifdef IRR_OGRE_LOADER_DEBUG | ||
296 | os::Printer::log("Skipping", core::stringc(data.header.id), ELL_DEBUG); | ||
297 | #endif | ||
298 | file->seek(data.header.length-data.read, true); | ||
299 | data.read += data.header.length-data.read; | ||
300 | } | ||
301 | parent.read += data.read; | ||
302 | } | ||
303 | if (parent.read != parent.header.length) | ||
304 | os::Printer::log("Incorrect geometry length. File might be corrupted."); | ||
305 | return true; | ||
306 | } | ||
307 | |||
308 | |||
309 | bool COgreMeshFileLoader::readVertexDeclaration(io::IReadFile* file, ChunkData& parent, OgreGeometry& geometry) | ||
310 | { | ||
311 | #ifdef IRR_OGRE_LOADER_DEBUG | ||
312 | os::Printer::log("Read Vertex Declaration", ELL_DEBUG); | ||
313 | #endif | ||
314 | NumUV = 0; | ||
315 | while(parent.read < parent.header.length) | ||
316 | { | ||
317 | ChunkData data; | ||
318 | readChunkData(file, data); | ||
319 | |||
320 | switch(data.header.id) | ||
321 | { | ||
322 | case COGRE_GEOMETRY_VERTEX_ELEMENT: | ||
323 | { | ||
324 | geometry.Elements.push_back(OgreVertexElement()); | ||
325 | OgreVertexElement& elem = geometry.Elements.getLast(); | ||
326 | readShort(file, data, &elem.Source); | ||
327 | readShort(file, data, &elem.Type); | ||
328 | readShort(file, data, &elem.Semantic); | ||
329 | if (elem.Semantic == 7) //Tex coords | ||
330 | { | ||
331 | ++NumUV; | ||
332 | } | ||
333 | readShort(file, data, &elem.Offset); | ||
334 | elem.Offset /= sizeof(f32); | ||
335 | readShort(file, data, &elem.Index); | ||
336 | } | ||
337 | break; | ||
338 | default: | ||
339 | // ignore chunk | ||
340 | file->seek(data.header.length-data.read, true); | ||
341 | data.read += data.header.length-data.read; | ||
342 | } | ||
343 | parent.read += data.read; | ||
344 | } | ||
345 | if (parent.read != parent.header.length) | ||
346 | os::Printer::log("Incorrect vertex declaration length. File might be corrupted."); | ||
347 | return true; | ||
348 | } | ||
349 | |||
350 | |||
351 | bool COgreMeshFileLoader::readVertexBuffer(io::IReadFile* file, ChunkData& parent, OgreGeometry& geometry) | ||
352 | { | ||
353 | #ifdef IRR_OGRE_LOADER_DEBUG | ||
354 | os::Printer::log("Read Vertex Buffer", ELL_DEBUG); | ||
355 | #endif | ||
356 | OgreVertexBuffer buf; | ||
357 | readShort(file, parent, &buf.BindIndex); | ||
358 | readShort(file, parent, &buf.VertexSize); | ||
359 | buf.VertexSize /= sizeof(f32); | ||
360 | ChunkData data; | ||
361 | readChunkData(file, data); | ||
362 | |||
363 | if (data.header.id == COGRE_GEOMETRY_VERTEX_BUFFER_DATA) | ||
364 | { | ||
365 | buf.Data.set_used(geometry.NumVertex*buf.VertexSize); | ||
366 | readFloat(file, data, buf.Data.pointer(), geometry.NumVertex*buf.VertexSize); | ||
367 | } | ||
368 | |||
369 | geometry.Buffers.push_back(buf); | ||
370 | parent.read += data.read; | ||
371 | if (parent.read != parent.header.length) | ||
372 | os::Printer::log("Incorrect vertex buffer length. File might be corrupted."); | ||
373 | return true; | ||
374 | } | ||
375 | |||
376 | |||
377 | bool COgreMeshFileLoader::readSubMesh(io::IReadFile* file, ChunkData& parent, OgreSubMesh& subMesh) | ||
378 | { | ||
379 | #ifdef IRR_OGRE_LOADER_DEBUG | ||
380 | os::Printer::log("Read Submesh", ELL_DEBUG); | ||
381 | #endif | ||
382 | readString(file, parent, subMesh.Material); | ||
383 | #ifdef IRR_OGRE_LOADER_DEBUG | ||
384 | os::Printer::log("using material", subMesh.Material, ELL_DEBUG); | ||
385 | #endif | ||
386 | readBool(file, parent, subMesh.SharedVertices); | ||
387 | |||
388 | s32 numIndices; | ||
389 | readInt(file, parent, &numIndices); | ||
390 | subMesh.Indices.set_used(numIndices); | ||
391 | |||
392 | readBool(file, parent, subMesh.Indices32Bit); | ||
393 | |||
394 | if (subMesh.Indices32Bit) | ||
395 | readInt(file, parent, subMesh.Indices.pointer(), numIndices); | ||
396 | else | ||
397 | { | ||
398 | for (s32 i=0; i<numIndices; ++i) | ||
399 | { | ||
400 | u16 num; | ||
401 | readShort(file, parent, &num); | ||
402 | subMesh.Indices[i]=num; | ||
403 | } | ||
404 | } | ||
405 | |||
406 | while(parent.read < parent.header.length) | ||
407 | { | ||
408 | ChunkData data; | ||
409 | readChunkData(file, data); | ||
410 | |||
411 | switch(data.header.id) | ||
412 | { | ||
413 | case COGRE_GEOMETRY: | ||
414 | readGeometry(file, data, subMesh.Geometry); | ||
415 | break; | ||
416 | case COGRE_SUBMESH_OPERATION: | ||
417 | readShort(file, data, &subMesh.Operation); | ||
418 | #ifdef IRR_OGRE_LOADER_DEBUG | ||
419 | os::Printer::log("Read Submesh Operation",core::stringc(subMesh.Operation), ELL_DEBUG); | ||
420 | #endif | ||
421 | if (subMesh.Operation != 4) | ||
422 | os::Printer::log("Primitive type != trilist not yet implemented", ELL_WARNING); | ||
423 | break; | ||
424 | case COGRE_SUBMESH_TEXTURE_ALIAS: | ||
425 | { | ||
426 | #ifdef IRR_OGRE_LOADER_DEBUG | ||
427 | os::Printer::log("Read Submesh Texture Alias", ELL_DEBUG); | ||
428 | #endif | ||
429 | core::stringc texture, alias; | ||
430 | readString(file, data, texture); | ||
431 | readString(file, data, alias); | ||
432 | subMesh.TextureAliases.push_back(OgreTextureAlias(texture,alias)); | ||
433 | } | ||
434 | break; | ||
435 | case COGRE_SUBMESH_BONE_ASSIGNMENT: | ||
436 | { | ||
437 | subMesh.BoneAssignments.push_back(OgreBoneAssignment()); | ||
438 | readInt(file, data, &subMesh.BoneAssignments.getLast().VertexID); | ||
439 | readShort(file, data, &subMesh.BoneAssignments.getLast().BoneID); | ||
440 | readFloat(file, data, &subMesh.BoneAssignments.getLast().Weight); | ||
441 | } | ||
442 | break; | ||
443 | default: | ||
444 | #ifdef IRR_OGRE_LOADER_DEBUG | ||
445 | os::Printer::log("Skipping", core::stringc(data.header.id), ELL_DEBUG); | ||
446 | #endif | ||
447 | parent.read=parent.header.length; | ||
448 | file->seek(-(long)sizeof(ChunkHeader), true); | ||
449 | return true; | ||
450 | } | ||
451 | parent.read += data.read; | ||
452 | } | ||
453 | if (parent.read != parent.header.length) | ||
454 | os::Printer::log("Incorrect submesh length. File might be corrupted."); | ||
455 | #ifdef IRR_OGRE_LOADER_DEBUG | ||
456 | os::Printer::log("Done with submesh", ELL_DEBUG); | ||
457 | #endif | ||
458 | return true; | ||
459 | } | ||
460 | |||
461 | |||
462 | void COgreMeshFileLoader::composeMeshBufferMaterial(scene::IMeshBuffer* mb, const core::stringc& materialName) | ||
463 | { | ||
464 | video::SMaterial& material=mb->getMaterial(); | ||
465 | for (u32 k=0; k<Materials.size(); ++k) | ||
466 | { | ||
467 | if ((materialName==Materials[k].Name)&&(Materials[k].Techniques.size())&&(Materials[k].Techniques[0].Passes.size())) | ||
468 | { | ||
469 | material=Materials[k].Techniques[0].Passes[0].Material; | ||
470 | for (u32 i=0; i<Materials[k].Techniques[0].Passes[0].Texture.Filename.size(); ++i) | ||
471 | { | ||
472 | if (FileSystem->existFile(Materials[k].Techniques[0].Passes[0].Texture.Filename[i])) | ||
473 | material.setTexture(i, Driver->getTexture(Materials[k].Techniques[0].Passes[0].Texture.Filename[i])); | ||
474 | else | ||
475 | material.setTexture(i, Driver->getTexture((CurrentlyLoadingFromPath+"/"+FileSystem->getFileBasename(Materials[k].Techniques[0].Passes[0].Texture.Filename[i])))); | ||
476 | } | ||
477 | break; | ||
478 | } | ||
479 | } | ||
480 | } | ||
481 | |||
482 | |||
483 | scene::SMeshBuffer* COgreMeshFileLoader::composeMeshBuffer(const core::array<s32>& indices, const OgreGeometry& geom) | ||
484 | { | ||
485 | scene::SMeshBuffer *mb=new scene::SMeshBuffer(); | ||
486 | |||
487 | u32 i; | ||
488 | mb->Indices.set_used(indices.size()); | ||
489 | for (i=0; i<indices.size(); ++i) | ||
490 | mb->Indices[i]=indices[i]; | ||
491 | |||
492 | mb->Vertices.set_used(geom.NumVertex); | ||
493 | for (i=0; i<geom.Elements.size(); ++i) | ||
494 | { | ||
495 | if (geom.Elements[i].Semantic==1) //Pos | ||
496 | { | ||
497 | for (u32 j=0; j<geom.Buffers.size(); ++j) | ||
498 | { | ||
499 | if (geom.Elements[i].Source==geom.Buffers[j].BindIndex) | ||
500 | { | ||
501 | u32 eSize=geom.Buffers[j].VertexSize; | ||
502 | u32 ePos=geom.Elements[i].Offset; | ||
503 | for (s32 k=0; k<geom.NumVertex; ++k) | ||
504 | { | ||
505 | mb->Vertices[k].Color=mb->Material.DiffuseColor; | ||
506 | mb->Vertices[k].Pos.set(geom.Buffers[j].Data[ePos],geom.Buffers[j].Data[ePos+1],geom.Buffers[j].Data[ePos+2]); | ||
507 | ePos += eSize; | ||
508 | } | ||
509 | } | ||
510 | } | ||
511 | } | ||
512 | |||
513 | if (geom.Elements[i].Semantic==4) //Normal | ||
514 | { | ||
515 | for (u32 j=0; j<geom.Buffers.size(); ++j) | ||
516 | { | ||
517 | if (geom.Elements[i].Source==geom.Buffers[j].BindIndex) | ||
518 | { | ||
519 | u32 eSize=geom.Buffers[j].VertexSize; | ||
520 | u32 ePos=geom.Elements[i].Offset; | ||
521 | for (s32 k=0; k<geom.NumVertex; ++k) | ||
522 | { | ||
523 | mb->Vertices[k].Normal.set(geom.Buffers[j].Data[ePos],geom.Buffers[j].Data[ePos+1],geom.Buffers[j].Data[ePos+2]); | ||
524 | ePos += eSize; | ||
525 | } | ||
526 | } | ||
527 | } | ||
528 | } | ||
529 | |||
530 | if (geom.Elements[i].Semantic==7) //TexCoord | ||
531 | { | ||
532 | for (u32 j=0; j<geom.Buffers.size(); ++j) | ||
533 | { | ||
534 | if (geom.Elements[i].Source==geom.Buffers[j].BindIndex) | ||
535 | { | ||
536 | u32 eSize=geom.Buffers[j].VertexSize; | ||
537 | u32 ePos=geom.Elements[i].Offset; | ||
538 | for (s32 k=0; k<geom.NumVertex; ++k) | ||
539 | { | ||
540 | mb->Vertices[k].TCoords.set(geom.Buffers[j].Data[ePos],geom.Buffers[j].Data[ePos+1]); | ||
541 | ePos += eSize; | ||
542 | } | ||
543 | } | ||
544 | } | ||
545 | } | ||
546 | } | ||
547 | return mb; | ||
548 | } | ||
549 | |||
550 | |||
551 | scene::SMeshBufferLightMap* COgreMeshFileLoader::composeMeshBufferLightMap(const core::array<s32>& indices, const OgreGeometry& geom) | ||
552 | { | ||
553 | scene::SMeshBufferLightMap *mb=new scene::SMeshBufferLightMap(); | ||
554 | |||
555 | u32 i; | ||
556 | mb->Indices.set_used(indices.size()); | ||
557 | for (i=0; i<indices.size(); ++i) | ||
558 | mb->Indices[i]=indices[i]; | ||
559 | |||
560 | mb->Vertices.set_used(geom.NumVertex); | ||
561 | |||
562 | for (i=0; i<geom.Elements.size(); ++i) | ||
563 | { | ||
564 | if (geom.Elements[i].Semantic==1) //Pos | ||
565 | { | ||
566 | for (u32 j=0; j<geom.Buffers.size(); ++j) | ||
567 | { | ||
568 | if (geom.Elements[i].Source==geom.Buffers[j].BindIndex) | ||
569 | { | ||
570 | u32 eSize=geom.Buffers[j].VertexSize; | ||
571 | u32 ePos=geom.Elements[i].Offset; | ||
572 | for (s32 k=0; k<geom.NumVertex; ++k) | ||
573 | { | ||
574 | mb->Vertices[k].Color=mb->Material.DiffuseColor; | ||
575 | mb->Vertices[k].Pos.set(geom.Buffers[j].Data[ePos],geom.Buffers[j].Data[ePos+1],geom.Buffers[j].Data[ePos+2]); | ||
576 | ePos += eSize; | ||
577 | } | ||
578 | } | ||
579 | } | ||
580 | } | ||
581 | |||
582 | if (geom.Elements[i].Semantic==4) //Normal | ||
583 | { | ||
584 | for (u32 j=0; j<geom.Buffers.size(); ++j) | ||
585 | { | ||
586 | if (geom.Elements[i].Source==geom.Buffers[j].BindIndex) | ||
587 | { | ||
588 | u32 eSize=geom.Buffers[j].VertexSize; | ||
589 | u32 ePos=geom.Elements[i].Offset; | ||
590 | for (s32 k=0; k<geom.NumVertex; ++k) | ||
591 | { | ||
592 | mb->Vertices[k].Normal.set(geom.Buffers[j].Data[ePos],geom.Buffers[j].Data[ePos+1],geom.Buffers[j].Data[ePos+2]); | ||
593 | ePos += eSize; | ||
594 | } | ||
595 | } | ||
596 | } | ||
597 | } | ||
598 | |||
599 | if (geom.Elements[i].Semantic==7) //TexCoord | ||
600 | { | ||
601 | for (u32 j=0; j<geom.Buffers.size(); ++j) | ||
602 | { | ||
603 | if (geom.Elements[i].Source==geom.Buffers[j].BindIndex) | ||
604 | { | ||
605 | u32 eSize=geom.Buffers[j].VertexSize; | ||
606 | u32 ePos=geom.Elements[i].Offset; | ||
607 | // make sure we have data for a second texture coord | ||
608 | const bool secondCoord = (eSize>ePos+3); | ||
609 | for (s32 k=0; k<geom.NumVertex; ++k) | ||
610 | { | ||
611 | mb->Vertices[k].TCoords.set(geom.Buffers[j].Data[ePos], geom.Buffers[j].Data[ePos+1]); | ||
612 | if (secondCoord) | ||
613 | mb->Vertices[k].TCoords2.set(geom.Buffers[j].Data[ePos+2], geom.Buffers[j].Data[ePos+3]); | ||
614 | else | ||
615 | mb->Vertices[k].TCoords2.set(geom.Buffers[j].Data[ePos], geom.Buffers[j].Data[ePos+1]); | ||
616 | ePos += eSize; | ||
617 | } | ||
618 | } | ||
619 | } | ||
620 | } | ||
621 | } | ||
622 | |||
623 | return mb; | ||
624 | } | ||
625 | |||
626 | |||
627 | scene::IMeshBuffer* COgreMeshFileLoader::composeMeshBufferSkinned(scene::CSkinnedMesh& mesh, const core::array<s32>& indices, const OgreGeometry& geom) | ||
628 | { | ||
629 | scene::SSkinMeshBuffer *mb=mesh.addMeshBuffer(); | ||
630 | if (NumUV>1) | ||
631 | { | ||
632 | mb->convertTo2TCoords(); | ||
633 | mb->Vertices_2TCoords.set_used(geom.NumVertex); | ||
634 | } | ||
635 | else | ||
636 | mb->Vertices_Standard.set_used(geom.NumVertex); | ||
637 | |||
638 | u32 i; | ||
639 | mb->Indices.set_used(indices.size()); | ||
640 | for (i=0; i<indices.size(); i+=3) | ||
641 | { | ||
642 | mb->Indices[i+0]=indices[i+2]; | ||
643 | mb->Indices[i+1]=indices[i+1]; | ||
644 | mb->Indices[i+2]=indices[i+0]; | ||
645 | } | ||
646 | |||
647 | for (i=0; i<geom.Elements.size(); ++i) | ||
648 | { | ||
649 | if (geom.Elements[i].Semantic==1) //Pos | ||
650 | { | ||
651 | for (u32 j=0; j<geom.Buffers.size(); ++j) | ||
652 | { | ||
653 | if (geom.Elements[i].Source==geom.Buffers[j].BindIndex) | ||
654 | { | ||
655 | u32 eSize=geom.Buffers[j].VertexSize; | ||
656 | u32 ePos=geom.Elements[i].Offset; | ||
657 | for (s32 k=0; k<geom.NumVertex; ++k) | ||
658 | { | ||
659 | if (NumUV>1) | ||
660 | mb->Vertices_2TCoords[k].Color=mb->Material.DiffuseColor; | ||
661 | else | ||
662 | mb->Vertices_Standard[k].Color=mb->Material.DiffuseColor; | ||
663 | mb->getPosition(k).set(-geom.Buffers[j].Data[ePos],geom.Buffers[j].Data[ePos+1],geom.Buffers[j].Data[ePos+2]); | ||
664 | ePos += eSize; | ||
665 | } | ||
666 | } | ||
667 | } | ||
668 | } | ||
669 | |||
670 | if (geom.Elements[i].Semantic==4) //Normal | ||
671 | { | ||
672 | for (u32 j=0; j<geom.Buffers.size(); ++j) | ||
673 | { | ||
674 | if (geom.Elements[i].Source==geom.Buffers[j].BindIndex) | ||
675 | { | ||
676 | u32 eSize=geom.Buffers[j].VertexSize; | ||
677 | u32 ePos=geom.Elements[i].Offset; | ||
678 | for (s32 k=0; k<geom.NumVertex; ++k) | ||
679 | { | ||
680 | mb->getNormal(k).set(-geom.Buffers[j].Data[ePos],geom.Buffers[j].Data[ePos+1],geom.Buffers[j].Data[ePos+2]); | ||
681 | ePos += eSize; | ||
682 | } | ||
683 | } | ||
684 | } | ||
685 | } | ||
686 | |||
687 | if (geom.Elements[i].Semantic==7) //TexCoord | ||
688 | { | ||
689 | for (u32 j=0; j<geom.Buffers.size(); ++j) | ||
690 | { | ||
691 | if (geom.Elements[i].Source==geom.Buffers[j].BindIndex) | ||
692 | { | ||
693 | u32 eSize=geom.Buffers[j].VertexSize; | ||
694 | u32 ePos=geom.Elements[i].Offset; | ||
695 | // make sure we have data for a second texture coord | ||
696 | const bool secondCoord = (eSize>ePos+3); | ||
697 | for (s32 k=0; k<geom.NumVertex; ++k) | ||
698 | { | ||
699 | mb->getTCoords(k).set(geom.Buffers[j].Data[ePos], geom.Buffers[j].Data[ePos+1]); | ||
700 | if (NumUV>1) | ||
701 | { | ||
702 | if (secondCoord) | ||
703 | mb->Vertices_2TCoords[k].TCoords2.set(geom.Buffers[j].Data[ePos+2], geom.Buffers[j].Data[ePos+3]); | ||
704 | else | ||
705 | mb->Vertices_2TCoords[k].TCoords2.set(geom.Buffers[j].Data[ePos], geom.Buffers[j].Data[ePos+1]); | ||
706 | } | ||
707 | ePos += eSize; | ||
708 | } | ||
709 | } | ||
710 | } | ||
711 | } | ||
712 | } | ||
713 | |||
714 | return mb; | ||
715 | } | ||
716 | |||
717 | |||
718 | void COgreMeshFileLoader::composeObject(void) | ||
719 | { | ||
720 | for (u32 i=0; i<Meshes.size(); ++i) | ||
721 | { | ||
722 | for (u32 j=0; j<Meshes[i].SubMeshes.size(); ++j) | ||
723 | { | ||
724 | IMeshBuffer* mb; | ||
725 | if (Meshes[i].SubMeshes[j].SharedVertices) | ||
726 | { | ||
727 | if (Skeleton.Bones.size()) | ||
728 | { | ||
729 | mb = composeMeshBufferSkinned(*(CSkinnedMesh*)Mesh, Meshes[i].SubMeshes[j].Indices, Meshes[i].Geometry); | ||
730 | } | ||
731 | else if (NumUV < 2) | ||
732 | { | ||
733 | mb = composeMeshBuffer(Meshes[i].SubMeshes[j].Indices, Meshes[i].Geometry); | ||
734 | } | ||
735 | else | ||
736 | { | ||
737 | mb = composeMeshBufferLightMap(Meshes[i].SubMeshes[j].Indices, Meshes[i].Geometry); | ||
738 | } | ||
739 | } | ||
740 | else | ||
741 | { | ||
742 | if (Skeleton.Bones.size()) | ||
743 | { | ||
744 | mb = composeMeshBufferSkinned(*(CSkinnedMesh*)Mesh, Meshes[i].SubMeshes[j].Indices, Meshes[i].SubMeshes[j].Geometry); | ||
745 | } | ||
746 | else if (NumUV < 2) | ||
747 | { | ||
748 | mb = composeMeshBuffer(Meshes[i].SubMeshes[j].Indices, Meshes[i].SubMeshes[j].Geometry); | ||
749 | } | ||
750 | else | ||
751 | { | ||
752 | mb = composeMeshBufferLightMap(Meshes[i].SubMeshes[j].Indices, Meshes[i].SubMeshes[j].Geometry); | ||
753 | } | ||
754 | } | ||
755 | |||
756 | if (mb != 0) | ||
757 | { | ||
758 | composeMeshBufferMaterial(mb, Meshes[i].SubMeshes[j].Material); | ||
759 | if (!Skeleton.Bones.size()) | ||
760 | { | ||
761 | ((SMesh*)Mesh)->addMeshBuffer(mb); | ||
762 | mb->drop(); | ||
763 | } | ||
764 | } | ||
765 | } | ||
766 | } | ||
767 | if (Skeleton.Bones.size()) | ||
768 | { | ||
769 | CSkinnedMesh* m = (CSkinnedMesh*)Mesh; | ||
770 | // Create Joints | ||
771 | for (u32 i=0; i<Skeleton.Bones.size(); ++i) | ||
772 | { | ||
773 | ISkinnedMesh::SJoint* joint = m->addJoint(); | ||
774 | joint->Name=Skeleton.Bones[i].Name; | ||
775 | |||
776 | // IRR_TEST_BROKEN_QUATERNION_USE: TODO - switched to getMatrix_transposed instead of getMatrix for downward compatibility. | ||
777 | // Not tested so far if this was correct or wrong before quaternion fix! | ||
778 | Skeleton.Bones[i].Orientation.getMatrix_transposed(joint->LocalMatrix); | ||
779 | |||
780 | if (Skeleton.Bones[i].Scale != core::vector3df(1,1,1)) | ||
781 | { | ||
782 | core::matrix4 scaleMatrix; | ||
783 | scaleMatrix.setScale( Skeleton.Bones[i].Scale ); | ||
784 | joint->LocalMatrix *= scaleMatrix; | ||
785 | } | ||
786 | joint->LocalMatrix.setTranslation( Skeleton.Bones[i].Position ); | ||
787 | } | ||
788 | // Joints hierarchy | ||
789 | for (u32 i=0; i<Skeleton.Bones.size(); ++i) | ||
790 | { | ||
791 | if (Skeleton.Bones[i].Parent<m->getJointCount()) | ||
792 | { | ||
793 | m->getAllJoints()[Skeleton.Bones[i].Parent]->Children.push_back(m->getAllJoints()[Skeleton.Bones[i].Handle]); | ||
794 | } | ||
795 | } | ||
796 | |||
797 | // Weights | ||
798 | u32 bufCount=0; | ||
799 | for (u32 i=0; i<Meshes.size(); ++i) | ||
800 | { | ||
801 | for (u32 j=0; j<Meshes[i].SubMeshes.size(); ++j) | ||
802 | { | ||
803 | for (u32 k=0; k<Meshes[i].SubMeshes[j].BoneAssignments.size(); ++k) | ||
804 | { | ||
805 | const OgreBoneAssignment& ba = Meshes[i].SubMeshes[j].BoneAssignments[k]; | ||
806 | if (ba.BoneID<m->getJointCount()) | ||
807 | { | ||
808 | ISkinnedMesh::SWeight* w = m->addWeight(m->getAllJoints()[ba.BoneID]); | ||
809 | w->strength=ba.Weight; | ||
810 | w->vertex_id=ba.VertexID; | ||
811 | w->buffer_id=bufCount; | ||
812 | } | ||
813 | } | ||
814 | ++bufCount; | ||
815 | } | ||
816 | } | ||
817 | |||
818 | for (u32 i=0; i<Skeleton.Animations.size(); ++i) | ||
819 | { | ||
820 | for (u32 j=0; j<Skeleton.Animations[i].Keyframes.size(); ++j) | ||
821 | { | ||
822 | OgreKeyframe& frame = Skeleton.Animations[i].Keyframes[j]; | ||
823 | ISkinnedMesh::SJoint* keyjoint = m->getAllJoints()[frame.BoneID]; | ||
824 | ISkinnedMesh::SPositionKey* poskey = m->addPositionKey(keyjoint); | ||
825 | poskey->frame=frame.Time*25; | ||
826 | poskey->position=keyjoint->LocalMatrix.getTranslation()+frame.Position; | ||
827 | ISkinnedMesh::SRotationKey* rotkey = m->addRotationKey(keyjoint); | ||
828 | rotkey->frame=frame.Time*25; | ||
829 | |||
830 | // IRR_TEST_BROKEN_QUATERNION_USE: TODO - switched from keyjoint->LocalMatrix to keyjoint->LocalMatrix.getTransposed() for downward compatibility. | ||
831 | // Not tested so far if this was correct or wrong before quaternion fix! | ||
832 | rotkey->rotation=core::quaternion(keyjoint->LocalMatrix.getTransposed())*frame.Orientation; | ||
833 | |||
834 | ISkinnedMesh::SScaleKey* scalekey = m->addScaleKey(keyjoint); | ||
835 | scalekey->frame=frame.Time*25; | ||
836 | scalekey->scale=frame.Scale; | ||
837 | } | ||
838 | } | ||
839 | m->finalize(); | ||
840 | } | ||
841 | } | ||
842 | |||
843 | |||
844 | void COgreMeshFileLoader::getMaterialToken(io::IReadFile* file, core::stringc& token, bool noNewLine) | ||
845 | { | ||
846 | bool parseString=false; | ||
847 | c8 c=0; | ||
848 | token = ""; | ||
849 | |||
850 | if (file->getPos() >= file->getSize()) | ||
851 | return; | ||
852 | |||
853 | file->read(&c, sizeof(c8)); | ||
854 | // search for word beginning | ||
855 | while ( core::isspace(c) && (file->getPos() < file->getSize())) | ||
856 | { | ||
857 | if (noNewLine && c=='\n') | ||
858 | { | ||
859 | file->seek(-1, true); | ||
860 | return; | ||
861 | } | ||
862 | file->read(&c, sizeof(c8)); | ||
863 | } | ||
864 | // check if we read a string | ||
865 | if (c=='"') | ||
866 | { | ||
867 | parseString = true; | ||
868 | file->read(&c, sizeof(c8)); | ||
869 | } | ||
870 | do | ||
871 | { | ||
872 | if (c=='/') | ||
873 | { | ||
874 | file->read(&c, sizeof(c8)); | ||
875 | // check for comments, cannot be part of strings | ||
876 | if (!parseString && (c=='/')) | ||
877 | { | ||
878 | // skip comments | ||
879 | while(c!='\n') | ||
880 | file->read(&c, sizeof(c8)); | ||
881 | if (!token.size()) | ||
882 | { | ||
883 | // if we start with a comment we need to skip | ||
884 | // following whitespaces, so restart | ||
885 | getMaterialToken(file, token, noNewLine); | ||
886 | return; | ||
887 | } | ||
888 | else | ||
889 | { | ||
890 | // else continue with next character | ||
891 | file->read(&c, sizeof(c8)); | ||
892 | continue; | ||
893 | } | ||
894 | } | ||
895 | else | ||
896 | { | ||
897 | // else append first slash and check if second char | ||
898 | // ends this token | ||
899 | token.append('/'); | ||
900 | if ((!parseString && core::isspace(c)) || | ||
901 | (parseString && (c=='"'))) | ||
902 | return; | ||
903 | } | ||
904 | } | ||
905 | token.append(c); | ||
906 | file->read(&c, sizeof(c8)); | ||
907 | // read until a token delimiter is found | ||
908 | } | ||
909 | while (((!parseString && !core::isspace(c)) || (parseString && (c!='"'))) && | ||
910 | (file->getPos() < file->getSize())); | ||
911 | // we want to skip the last quotes of a string , but other chars might be the next | ||
912 | // token already. | ||
913 | if (!parseString) | ||
914 | file->seek(-1, true); | ||
915 | } | ||
916 | |||
917 | |||
918 | bool COgreMeshFileLoader::readColor(io::IReadFile* file, video::SColor& col) | ||
919 | { | ||
920 | core::stringc token; | ||
921 | |||
922 | getMaterialToken(file, token); | ||
923 | if (token!="vertexcolour") | ||
924 | { | ||
925 | video::SColorf col_f; | ||
926 | col_f.r=core::fast_atof(token.c_str()); | ||
927 | getMaterialToken(file, token); | ||
928 | col_f.g=core::fast_atof(token.c_str()); | ||
929 | getMaterialToken(file, token); | ||
930 | col_f.b=core::fast_atof(token.c_str()); | ||
931 | getMaterialToken(file, token, true); | ||
932 | if (token.size()) | ||
933 | col_f.a=core::fast_atof(token.c_str()); | ||
934 | else | ||
935 | col_f.a=1.0f; | ||
936 | if ((col_f.r==0.0f)&&(col_f.g==0.0f)&&(col_f.b==0.0f)) | ||
937 | col.set(255,255,255,255); | ||
938 | else | ||
939 | col=col_f.toSColor(); | ||
940 | return false; | ||
941 | } | ||
942 | return true; | ||
943 | } | ||
944 | |||
945 | |||
946 | void COgreMeshFileLoader::readPass(io::IReadFile* file, OgreTechnique& technique) | ||
947 | { | ||
948 | #ifdef IRR_OGRE_LOADER_DEBUG | ||
949 | os::Printer::log("Read Pass"); | ||
950 | #endif | ||
951 | core::stringc token; | ||
952 | technique.Passes.push_back(OgrePass()); | ||
953 | OgrePass& pass=technique.Passes.getLast(); | ||
954 | |||
955 | getMaterialToken(file, token); //open brace or name | ||
956 | if (token != "{") | ||
957 | getMaterialToken(file, token); //open brace | ||
958 | |||
959 | getMaterialToken(file, token); | ||
960 | if (token == "}") | ||
961 | return; | ||
962 | u32 inBlocks=1; | ||
963 | u32 textureUnit=0; | ||
964 | while(inBlocks) | ||
965 | { | ||
966 | if (token=="ambient") | ||
967 | pass.AmbientTokenColor=readColor(file, pass.Material.AmbientColor); | ||
968 | else if (token=="diffuse") | ||
969 | pass.DiffuseTokenColor=readColor(file, pass.Material.DiffuseColor); | ||
970 | else if (token=="specular") | ||
971 | { | ||
972 | pass.SpecularTokenColor=readColor(file, pass.Material.SpecularColor); | ||
973 | getMaterialToken(file, token); | ||
974 | pass.Material.Shininess=core::fast_atof(token.c_str()); | ||
975 | } | ||
976 | else if (token=="emissive") | ||
977 | pass.EmissiveTokenColor=readColor(file, pass.Material.EmissiveColor); | ||
978 | else if (token=="scene_blend") | ||
979 | { // TODO: Choose correct values | ||
980 | getMaterialToken(file, token); | ||
981 | if (token=="add") | ||
982 | pass.Material.MaterialType=video::EMT_TRANSPARENT_ADD_COLOR; | ||
983 | else if (token=="modulate") | ||
984 | pass.Material.MaterialType=video::EMT_SOLID; | ||
985 | else if (token=="alpha_blend") | ||
986 | pass.Material.MaterialType=video::EMT_TRANSPARENT_ALPHA_CHANNEL; | ||
987 | else if (token=="colour_blend") | ||
988 | pass.Material.MaterialType=video::EMT_TRANSPARENT_VERTEX_ALPHA; | ||
989 | else | ||
990 | getMaterialToken(file, token); | ||
991 | } | ||
992 | else if (token=="depth_check") | ||
993 | { | ||
994 | getMaterialToken(file, token); | ||
995 | if (token!="on") | ||
996 | pass.Material.ZBuffer=video::ECFN_NEVER; | ||
997 | } | ||
998 | else if (token=="depth_write") | ||
999 | { | ||
1000 | getMaterialToken(file, token); | ||
1001 | pass.Material.ZWriteEnable=(token=="on"); | ||
1002 | } | ||
1003 | else if (token=="depth_func") | ||
1004 | { | ||
1005 | getMaterialToken(file, token); // Function name | ||
1006 | if (token=="always_fail") | ||
1007 | pass.Material.ZBuffer=video::ECFN_NEVER; | ||
1008 | else if (token=="always_pass") | ||
1009 | pass.Material.ZBuffer=video::ECFN_ALWAYS; | ||
1010 | else if (token=="equal") | ||
1011 | pass.Material.ZBuffer=video::ECFN_EQUAL; | ||
1012 | else if (token=="greater") | ||
1013 | pass.Material.ZBuffer=video::ECFN_GREATER; | ||
1014 | else if (token=="greater_equal") | ||
1015 | pass.Material.ZBuffer=video::ECFN_GREATEREQUAL; | ||
1016 | else if (token=="less") | ||
1017 | pass.Material.ZBuffer=video::ECFN_LESS; | ||
1018 | else if (token=="less_equal") | ||
1019 | pass.Material.ZBuffer=video::ECFN_LESSEQUAL; | ||
1020 | else if (token=="not_equal") | ||
1021 | pass.Material.ZBuffer=video::ECFN_NOTEQUAL; | ||
1022 | } | ||
1023 | else if (token=="normalise_normals") | ||
1024 | { | ||
1025 | getMaterialToken(file, token); | ||
1026 | pass.Material.NormalizeNormals=(token=="on"); | ||
1027 | } | ||
1028 | else if (token=="depth_bias") | ||
1029 | { | ||
1030 | getMaterialToken(file, token); // bias value | ||
1031 | } | ||
1032 | else if (token=="alpha_rejection") | ||
1033 | { | ||
1034 | getMaterialToken(file, token); // function name | ||
1035 | getMaterialToken(file, token); // value | ||
1036 | pass.Material.MaterialTypeParam=core::fast_atof(token.c_str()); | ||
1037 | } | ||
1038 | else if (token=="alpha_to_coverage") | ||
1039 | { | ||
1040 | getMaterialToken(file, token); | ||
1041 | if (token=="on") | ||
1042 | pass.Material.AntiAliasing |= video::EAAM_ALPHA_TO_COVERAGE; | ||
1043 | } | ||
1044 | else if (token=="colour_write") | ||
1045 | { | ||
1046 | getMaterialToken(file, token); | ||
1047 | pass.Material.ColorMask = (token=="on")?video::ECP_ALL:video::ECP_NONE; | ||
1048 | } | ||
1049 | else if (token=="cull_hardware") | ||
1050 | { | ||
1051 | getMaterialToken(file, token); // rotation name | ||
1052 | } | ||
1053 | else if (token=="cull_software") | ||
1054 | { | ||
1055 | getMaterialToken(file, token); // culling side | ||
1056 | } | ||
1057 | else if (token=="lighting") | ||
1058 | { | ||
1059 | getMaterialToken(file, token); | ||
1060 | pass.Material.Lighting=(token=="on"); | ||
1061 | } | ||
1062 | else if (token=="shading") | ||
1063 | { | ||
1064 | getMaterialToken(file, token); | ||
1065 | // We take phong as gouraud | ||
1066 | pass.Material.GouraudShading=(token!="flat"); | ||
1067 | } | ||
1068 | else if (token=="polygon_mode") | ||
1069 | { | ||
1070 | getMaterialToken(file, token); | ||
1071 | pass.Material.Wireframe=(token=="wireframe"); | ||
1072 | pass.Material.PointCloud=(token=="points"); | ||
1073 | } | ||
1074 | else if (token=="max_lights") | ||
1075 | { | ||
1076 | getMaterialToken(file, token); | ||
1077 | pass.MaxLights=core::strtoul10(token.c_str()); | ||
1078 | } | ||
1079 | else if (token=="point_size") | ||
1080 | { | ||
1081 | getMaterialToken(file, token); | ||
1082 | pass.PointSize=core::fast_atof(token.c_str()); | ||
1083 | } | ||
1084 | else if (token=="point_sprites") | ||
1085 | { | ||
1086 | getMaterialToken(file, token); | ||
1087 | pass.PointSprites=(token=="on"); | ||
1088 | } | ||
1089 | else if (token=="point_size_min") | ||
1090 | { | ||
1091 | getMaterialToken(file, token); | ||
1092 | pass.PointSizeMin=core::strtoul10(token.c_str()); | ||
1093 | } | ||
1094 | else if (token=="point_size_max") | ||
1095 | { | ||
1096 | getMaterialToken(file, token); | ||
1097 | pass.PointSizeMax=core::strtoul10(token.c_str()); | ||
1098 | } | ||
1099 | else if (token=="texture_unit") | ||
1100 | { | ||
1101 | #ifdef IRR_OGRE_LOADER_DEBUG | ||
1102 | os::Printer::log("Read Texture unit", ELL_DEBUG); | ||
1103 | #endif | ||
1104 | getMaterialToken(file, token); //open brace | ||
1105 | getMaterialToken(file, token); | ||
1106 | while(token != "}") | ||
1107 | { | ||
1108 | if (token=="texture") | ||
1109 | { | ||
1110 | getMaterialToken(file, token); | ||
1111 | pass.Texture.Filename.push_back(token); | ||
1112 | #ifdef IRR_OGRE_LOADER_DEBUG | ||
1113 | os::Printer::log("Read Texture", token, ELL_DEBUG); | ||
1114 | #endif | ||
1115 | getMaterialToken(file, pass.Texture.CoordsType, true); | ||
1116 | getMaterialToken(file, pass.Texture.MipMaps, true); | ||
1117 | getMaterialToken(file, pass.Texture.Alpha, true); | ||
1118 | // Hmm, we might need more hints for other material types using two textures... | ||
1119 | if (textureUnit>0) | ||
1120 | pass.Material.MaterialType=video::EMT_LIGHTMAP; | ||
1121 | } | ||
1122 | else if (token=="filtering") | ||
1123 | { | ||
1124 | getMaterialToken(file, token); | ||
1125 | pass.Material.TextureLayer[textureUnit].AnisotropicFilter=0; | ||
1126 | if (token=="point") | ||
1127 | { | ||
1128 | pass.Material.TextureLayer[textureUnit].BilinearFilter=false; | ||
1129 | pass.Material.TextureLayer[textureUnit].TrilinearFilter=false; | ||
1130 | getMaterialToken(file, token); | ||
1131 | getMaterialToken(file, token); | ||
1132 | } | ||
1133 | else if (token=="linear") | ||
1134 | { | ||
1135 | getMaterialToken(file, token); | ||
1136 | if (token=="point") | ||
1137 | { | ||
1138 | pass.Material.TextureLayer[textureUnit].BilinearFilter=false; | ||
1139 | pass.Material.TextureLayer[textureUnit].TrilinearFilter=false; | ||
1140 | getMaterialToken(file, token); | ||
1141 | } | ||
1142 | else | ||
1143 | { | ||
1144 | pass.Material.TextureLayer[textureUnit].BilinearFilter=true; | ||
1145 | getMaterialToken(file, token); | ||
1146 | pass.Material.TextureLayer[textureUnit].TrilinearFilter=(token=="linear"); | ||
1147 | } | ||
1148 | } | ||
1149 | else | ||
1150 | { | ||
1151 | pass.Material.TextureLayer[textureUnit].BilinearFilter=(token=="bilinear"); | ||
1152 | pass.Material.TextureLayer[textureUnit].TrilinearFilter=(token=="trilinear"); | ||
1153 | pass.Material.TextureLayer[textureUnit].AnisotropicFilter=(token=="anisotropic")?2:1; | ||
1154 | } | ||
1155 | } | ||
1156 | else if (token=="max_anisotropy") | ||
1157 | { | ||
1158 | getMaterialToken(file, token); | ||
1159 | pass.Material.TextureLayer[textureUnit].AnisotropicFilter=(u8)core::strtoul10(token.c_str()); | ||
1160 | } | ||
1161 | else if (token=="texture_alias") | ||
1162 | { | ||
1163 | getMaterialToken(file, pass.Texture.Alias); | ||
1164 | } | ||
1165 | else if (token=="mipmap_bias") | ||
1166 | { | ||
1167 | getMaterialToken(file, token); | ||
1168 | pass.Material.TextureLayer[textureUnit].LODBias=(s8)core::fast_atof(token.c_str()); | ||
1169 | } | ||
1170 | else if (token=="colour_op") | ||
1171 | { // TODO: Choose correct values | ||
1172 | getMaterialToken(file, token); | ||
1173 | if (token=="add") | ||
1174 | pass.Material.MaterialType=video::EMT_TRANSPARENT_ADD_COLOR; | ||
1175 | else if (token=="modulate") | ||
1176 | pass.Material.MaterialType=video::EMT_SOLID; | ||
1177 | else if (token=="alpha_blend") | ||
1178 | pass.Material.MaterialType=video::EMT_TRANSPARENT_ALPHA_CHANNEL; | ||
1179 | else if (token=="colour_blend") | ||
1180 | pass.Material.MaterialType=video::EMT_TRANSPARENT_VERTEX_ALPHA; | ||
1181 | else | ||
1182 | getMaterialToken(file, token); | ||
1183 | } | ||
1184 | getMaterialToken(file, token); | ||
1185 | } | ||
1186 | ++textureUnit; | ||
1187 | } | ||
1188 | else if (token=="shadow_caster_program_ref") | ||
1189 | { | ||
1190 | do | ||
1191 | { | ||
1192 | getMaterialToken(file, token); | ||
1193 | } while (token != "}"); | ||
1194 | } | ||
1195 | else if (token=="shadow_caster_vertex_program_ref") | ||
1196 | { | ||
1197 | do | ||
1198 | { | ||
1199 | getMaterialToken(file, token); | ||
1200 | } while (token != "}"); | ||
1201 | } | ||
1202 | else if (token=="vertex_program_ref") | ||
1203 | { | ||
1204 | do | ||
1205 | { | ||
1206 | getMaterialToken(file, token); | ||
1207 | } while (token != "}"); | ||
1208 | } | ||
1209 | //fog_override, iteration, point_size_attenuation | ||
1210 | //not considered yet! | ||
1211 | getMaterialToken(file, token); | ||
1212 | if (token=="{") | ||
1213 | ++inBlocks; | ||
1214 | else if (token=="}") | ||
1215 | --inBlocks; | ||
1216 | } | ||
1217 | } | ||
1218 | |||
1219 | |||
1220 | void COgreMeshFileLoader::readTechnique(io::IReadFile* file, OgreMaterial& mat) | ||
1221 | { | ||
1222 | #ifdef IRR_OGRE_LOADER_DEBUG | ||
1223 | os::Printer::log("Read Technique"); | ||
1224 | #endif | ||
1225 | core::stringc token; | ||
1226 | mat.Techniques.push_back(OgreTechnique()); | ||
1227 | OgreTechnique& technique=mat.Techniques.getLast(); | ||
1228 | |||
1229 | getMaterialToken(file, technique.Name); //open brace or name | ||
1230 | if (technique.Name != "{") | ||
1231 | getMaterialToken(file, token); //open brace | ||
1232 | else | ||
1233 | technique.Name=core::stringc((int)mat.Techniques.size()); | ||
1234 | |||
1235 | getMaterialToken(file, token); | ||
1236 | while (token != "}") | ||
1237 | { | ||
1238 | if (token == "pass") | ||
1239 | readPass(file, technique); | ||
1240 | else if (token == "scheme") | ||
1241 | getMaterialToken(file, token); | ||
1242 | else if (token == "lod_index") | ||
1243 | getMaterialToken(file, token); | ||
1244 | getMaterialToken(file, token); | ||
1245 | } | ||
1246 | } | ||
1247 | |||
1248 | |||
1249 | void COgreMeshFileLoader::loadMaterials(io::IReadFile* meshFile) | ||
1250 | { | ||
1251 | #ifdef IRR_OGRE_LOADER_DEBUG | ||
1252 | os::Printer::log("Load Materials", ELL_DEBUG); | ||
1253 | #endif | ||
1254 | core::stringc token; | ||
1255 | io::IReadFile* file = 0; | ||
1256 | io::path filename = FileSystem->getFileBasename(meshFile->getFileName(), false) + ".material"; | ||
1257 | if (FileSystem->existFile(filename)) | ||
1258 | file = FileSystem->createAndOpenFile(filename); | ||
1259 | else | ||
1260 | file = FileSystem->createAndOpenFile(FileSystem->getFileDir(meshFile->getFileName())+"/"+filename); | ||
1261 | |||
1262 | if (!file) | ||
1263 | { | ||
1264 | os::Printer::log("Could not load OGRE material", filename); | ||
1265 | return; | ||
1266 | } | ||
1267 | |||
1268 | getMaterialToken(file, token); | ||
1269 | |||
1270 | while (file->getPos() < file->getSize()) | ||
1271 | { | ||
1272 | if ((token == "fragment_program") || (token == "vertex_program")) | ||
1273 | { | ||
1274 | // skip whole block | ||
1275 | u32 blocks=1; | ||
1276 | do | ||
1277 | { | ||
1278 | getMaterialToken(file, token); | ||
1279 | } while (token != "{"); | ||
1280 | do | ||
1281 | { | ||
1282 | getMaterialToken(file, token); | ||
1283 | if (token == "{") | ||
1284 | ++blocks; | ||
1285 | else if (token == "}") | ||
1286 | --blocks; | ||
1287 | } while (blocks); | ||
1288 | getMaterialToken(file, token); | ||
1289 | continue; | ||
1290 | } | ||
1291 | if (token != "material") | ||
1292 | { | ||
1293 | if (token.trim().size()) | ||
1294 | os::Printer::log("Unknown material group", token.c_str()); | ||
1295 | break; | ||
1296 | } | ||
1297 | |||
1298 | Materials.push_back(OgreMaterial()); | ||
1299 | OgreMaterial& mat = Materials.getLast(); | ||
1300 | |||
1301 | getMaterialToken(file, mat.Name); | ||
1302 | #ifdef IRR_OGRE_LOADER_DEBUG | ||
1303 | os::Printer::log("Load Material", mat.Name.c_str(), ELL_DEBUG); | ||
1304 | #endif | ||
1305 | getMaterialToken(file, token); //open brace | ||
1306 | getMaterialToken(file, token); | ||
1307 | while(token != "}") | ||
1308 | { | ||
1309 | if (token=="lod_distances") // can have several items | ||
1310 | getMaterialToken(file, token); | ||
1311 | else if (token=="receive_shadows") | ||
1312 | { | ||
1313 | getMaterialToken(file, token); | ||
1314 | mat.ReceiveShadows=(token=="on"); | ||
1315 | } | ||
1316 | else if (token=="transparency_casts_shadows") | ||
1317 | { | ||
1318 | getMaterialToken(file, token); | ||
1319 | mat.TransparencyCastsShadows=(token=="on"); | ||
1320 | } | ||
1321 | else if (token=="set_texture_alias") | ||
1322 | { | ||
1323 | getMaterialToken(file, token); | ||
1324 | getMaterialToken(file, token); | ||
1325 | } | ||
1326 | else if (token=="technique") | ||
1327 | readTechnique(file, mat); | ||
1328 | getMaterialToken(file, token); | ||
1329 | } | ||
1330 | getMaterialToken(file, token); | ||
1331 | } | ||
1332 | |||
1333 | file->drop(); | ||
1334 | #ifdef IRR_OGRE_LOADER_DEBUG | ||
1335 | os::Printer::log("Finished loading Materials", ELL_DEBUG); | ||
1336 | #endif | ||
1337 | } | ||
1338 | |||
1339 | |||
1340 | bool COgreMeshFileLoader::loadSkeleton(io::IReadFile* meshFile, const core::stringc& name) | ||
1341 | { | ||
1342 | #ifdef IRR_OGRE_LOADER_DEBUG | ||
1343 | os::Printer::log("Load Skeleton", name, ELL_DEBUG); | ||
1344 | #endif | ||
1345 | io::IReadFile* file = 0; | ||
1346 | io::path filename; | ||
1347 | if (FileSystem->existFile(name)) | ||
1348 | file = FileSystem->createAndOpenFile(name); | ||
1349 | else if (FileSystem->existFile(filename = FileSystem->getFileDir(meshFile->getFileName())+"/"+name)) | ||
1350 | file = FileSystem->createAndOpenFile(filename); | ||
1351 | else if (FileSystem->existFile(filename = FileSystem->getFileBasename(meshFile->getFileName(), false) + ".skeleton")) | ||
1352 | file = FileSystem->createAndOpenFile(filename); | ||
1353 | else | ||
1354 | file = FileSystem->createAndOpenFile(FileSystem->getFileDir(meshFile->getFileName())+"/"+filename); | ||
1355 | if (!file) | ||
1356 | { | ||
1357 | os::Printer::log("Could not load matching skeleton", name); | ||
1358 | return false; | ||
1359 | } | ||
1360 | |||
1361 | s16 id; | ||
1362 | file->read(&id, 2); | ||
1363 | if (SwapEndian) | ||
1364 | id = os::Byteswap::byteswap(id); | ||
1365 | if (id != COGRE_HEADER) | ||
1366 | { | ||
1367 | file->drop(); | ||
1368 | return false; | ||
1369 | } | ||
1370 | |||
1371 | core::stringc skeletonVersion; | ||
1372 | ChunkData head; | ||
1373 | readString(file, head, skeletonVersion); | ||
1374 | if (skeletonVersion != "[Serializer_v1.10]") | ||
1375 | { | ||
1376 | file->drop(); | ||
1377 | return false; | ||
1378 | } | ||
1379 | |||
1380 | u16 bone=0; | ||
1381 | f32 animationTotal=0.f; | ||
1382 | while(file->getPos() < file->getSize()) | ||
1383 | { | ||
1384 | ChunkData data; | ||
1385 | readChunkData(file, data); | ||
1386 | |||
1387 | switch(data.header.id) | ||
1388 | { | ||
1389 | case COGRE_SKELETON: | ||
1390 | { | ||
1391 | Skeleton.Bones.push_back(OgreBone()); | ||
1392 | OgreBone& bone = Skeleton.Bones.getLast(); | ||
1393 | readString(file, data, bone.Name); | ||
1394 | readShort(file, data, &bone.Handle); | ||
1395 | readVector(file, data, bone.Position); | ||
1396 | readQuaternion(file, data, bone.Orientation); | ||
1397 | #ifdef IRR_OGRE_LOADER_DEBUG | ||
1398 | os::Printer::log("Bone", bone.Name+" ("+core::stringc(bone.Handle)+")", ELL_DEBUG); | ||
1399 | os::Printer::log("Position", core::stringc(bone.Position.X)+" "+core::stringc(bone.Position.Y)+" "+core::stringc(bone.Position.Z), ELL_DEBUG); | ||
1400 | os::Printer::log("Rotation quat", core::stringc(bone.Orientation.W)+" "+core::stringc(bone.Orientation.X)+" "+core::stringc(bone.Orientation.Y)+" "+core::stringc(bone.Orientation.Z), ELL_DEBUG); | ||
1401 | // core::vector3df rot; | ||
1402 | // bone.Orientation.toEuler(rot); | ||
1403 | // rot *= core::RADTODEG; | ||
1404 | // os::Printer::log("Rotation", core::stringc(rot.X)+" "+core::stringc(rot.Y)+" "+core::stringc(rot.Z)); | ||
1405 | #endif | ||
1406 | if (data.read<(data.header.length-bone.Name.size())) | ||
1407 | { | ||
1408 | readVector(file, data, bone.Scale); | ||
1409 | bone.Scale.X *= -1.f; | ||
1410 | } | ||
1411 | else | ||
1412 | bone.Scale=core::vector3df(1,1,1); | ||
1413 | bone.Parent=0xffff; | ||
1414 | } | ||
1415 | break; | ||
1416 | case COGRE_BONE_PARENT: | ||
1417 | { | ||
1418 | u16 parent; | ||
1419 | readShort(file, data, &bone); | ||
1420 | readShort(file, data, &parent); | ||
1421 | if (bone<Skeleton.Bones.size() && parent<Skeleton.Bones.size()) | ||
1422 | Skeleton.Bones[bone].Parent=parent; | ||
1423 | } | ||
1424 | break; | ||
1425 | case COGRE_ANIMATION: | ||
1426 | { | ||
1427 | if (Skeleton.Animations.size()) | ||
1428 | animationTotal+=Skeleton.Animations.getLast().Length; | ||
1429 | Skeleton.Animations.push_back(OgreAnimation()); | ||
1430 | OgreAnimation& anim = Skeleton.Animations.getLast(); | ||
1431 | readString(file, data, anim.Name); | ||
1432 | readFloat(file, data, &anim.Length); | ||
1433 | #ifdef IRR_OGRE_LOADER_DEBUG | ||
1434 | os::Printer::log("Animation", anim.Name, ELL_DEBUG); | ||
1435 | os::Printer::log("Length", core::stringc(anim.Length), ELL_DEBUG); | ||
1436 | #endif | ||
1437 | } | ||
1438 | break; | ||
1439 | case COGRE_ANIMATION_TRACK: | ||
1440 | #ifdef IRR_OGRE_LOADER_DEBUG | ||
1441 | os::Printer::log("for Bone ", core::stringc(bone), ELL_DEBUG); | ||
1442 | #endif | ||
1443 | readShort(file, data, &bone); // store current bone | ||
1444 | break; | ||
1445 | case COGRE_ANIMATION_KEYFRAME: | ||
1446 | { | ||
1447 | Skeleton.Animations.getLast().Keyframes.push_back(OgreKeyframe()); | ||
1448 | OgreKeyframe& keyframe = Skeleton.Animations.getLast().Keyframes.getLast(); | ||
1449 | readFloat(file, data, &keyframe.Time); | ||
1450 | keyframe.Time+=animationTotal; | ||
1451 | readQuaternion(file, data, keyframe.Orientation); | ||
1452 | readVector(file, data, keyframe.Position); | ||
1453 | if (data.read<data.header.length) | ||
1454 | { | ||
1455 | readVector(file, data, keyframe.Scale); | ||
1456 | keyframe.Scale.X *= -1.f; | ||
1457 | } | ||
1458 | else | ||
1459 | keyframe.Scale=core::vector3df(1,1,1); | ||
1460 | keyframe.BoneID=bone; | ||
1461 | } | ||
1462 | break; | ||
1463 | case COGRE_ANIMATION_LINK: | ||
1464 | #ifdef IRR_OGRE_LOADER_DEBUG | ||
1465 | os::Printer::log("Animation link", ELL_DEBUG); | ||
1466 | #endif | ||
1467 | break; | ||
1468 | default: | ||
1469 | break; | ||
1470 | } | ||
1471 | } | ||
1472 | file->drop(); | ||
1473 | return true; | ||
1474 | } | ||
1475 | |||
1476 | |||
1477 | void COgreMeshFileLoader::readChunkData(io::IReadFile* file, ChunkData& data) | ||
1478 | { | ||
1479 | file->read(&data.header, sizeof(ChunkHeader)); | ||
1480 | if (SwapEndian) | ||
1481 | { | ||
1482 | data.header.id = os::Byteswap::byteswap(data.header.id); | ||
1483 | data.header.length = os::Byteswap::byteswap(data.header.length); | ||
1484 | } | ||
1485 | data.read += sizeof(ChunkHeader); | ||
1486 | } | ||
1487 | |||
1488 | |||
1489 | void COgreMeshFileLoader::readString(io::IReadFile* file, ChunkData& data, core::stringc& out) | ||
1490 | { | ||
1491 | c8 c = 0; | ||
1492 | out = ""; | ||
1493 | |||
1494 | while (c!='\n') | ||
1495 | { | ||
1496 | file->read(&c, sizeof(c8)); | ||
1497 | if (c!='\n') | ||
1498 | out.append(c); | ||
1499 | |||
1500 | } | ||
1501 | data.read+=out.size()+1; | ||
1502 | } | ||
1503 | |||
1504 | |||
1505 | void COgreMeshFileLoader::readBool(io::IReadFile* file, ChunkData& data, bool& out) | ||
1506 | { | ||
1507 | // normal C type because we read a bit string | ||
1508 | char c = 0; | ||
1509 | file->read(&c, sizeof(char)); | ||
1510 | out=(c!=0); | ||
1511 | ++data.read; | ||
1512 | } | ||
1513 | |||
1514 | |||
1515 | void COgreMeshFileLoader::readInt(io::IReadFile* file, ChunkData& data, s32* out, u32 num) | ||
1516 | { | ||
1517 | // normal C type because we read a bit string | ||
1518 | file->read(out, sizeof(int)*num); | ||
1519 | if (SwapEndian) | ||
1520 | { | ||
1521 | for (u32 i=0; i<num; ++i) | ||
1522 | out[i] = os::Byteswap::byteswap(out[i]); | ||
1523 | } | ||
1524 | data.read+=sizeof(int)*num; | ||
1525 | } | ||
1526 | |||
1527 | |||
1528 | void COgreMeshFileLoader::readShort(io::IReadFile* file, ChunkData& data, u16* out, u32 num) | ||
1529 | { | ||
1530 | // normal C type because we read a bit string | ||
1531 | file->read(out, sizeof(short)*num); | ||
1532 | if (SwapEndian) | ||
1533 | { | ||
1534 | for (u32 i=0; i<num; ++i) | ||
1535 | out[i] = os::Byteswap::byteswap(out[i]); | ||
1536 | } | ||
1537 | data.read+=sizeof(short)*num; | ||
1538 | } | ||
1539 | |||
1540 | |||
1541 | void COgreMeshFileLoader::readFloat(io::IReadFile* file, ChunkData& data, f32* out, u32 num) | ||
1542 | { | ||
1543 | // normal C type because we read a bit string | ||
1544 | file->read(out, sizeof(float)*num); | ||
1545 | if (SwapEndian) | ||
1546 | { | ||
1547 | for (u32 i=0; i<num; ++i) | ||
1548 | out[i] = os::Byteswap::byteswap(out[i]); | ||
1549 | } | ||
1550 | data.read+=sizeof(float)*num; | ||
1551 | } | ||
1552 | |||
1553 | |||
1554 | void COgreMeshFileLoader::readVector(io::IReadFile* file, ChunkData& data, core::vector3df& out) | ||
1555 | { | ||
1556 | readFloat(file, data, &out.X); | ||
1557 | readFloat(file, data, &out.Y); | ||
1558 | readFloat(file, data, &out.Z); | ||
1559 | out.X *= -1.f; | ||
1560 | } | ||
1561 | |||
1562 | |||
1563 | void COgreMeshFileLoader::readQuaternion(io::IReadFile* file, ChunkData& data, core::quaternion& out) | ||
1564 | { | ||
1565 | readVector(file, data, *((core::vector3df*)&out.X)); | ||
1566 | readFloat(file, data, &out.W); | ||
1567 | } | ||
1568 | |||
1569 | |||
1570 | void COgreMeshFileLoader::clearMeshes() | ||
1571 | { | ||
1572 | for (u32 i=0; i<Meshes.size(); ++i) | ||
1573 | { | ||
1574 | for (int k=0; k<(int)Meshes[i].Geometry.Buffers.size(); ++k) | ||
1575 | Meshes[i].Geometry.Buffers[k].Data.clear(); | ||
1576 | |||
1577 | for (u32 j=0; j<Meshes[i].SubMeshes.size(); ++j) | ||
1578 | { | ||
1579 | for (int h=0; h<(int)Meshes[i].SubMeshes[j].Geometry.Buffers.size(); ++h) | ||
1580 | Meshes[i].SubMeshes[j].Geometry.Buffers[h].Data.clear(); | ||
1581 | } | ||
1582 | } | ||
1583 | |||
1584 | Meshes.clear(); | ||
1585 | } | ||
1586 | |||
1587 | |||
1588 | } // end namespace scene | ||
1589 | } // end namespace irr | ||
1590 | |||
1591 | #endif // _IRR_COMPILE_WITH_OGRE_LOADER_ | ||
1592 | |||