]> git.lizzy.rs Git - irrlicht.git/blob - source/Irrlicht/CPLYMeshFileLoader.cpp
Merging r6128 through r6139 from trunk to ogl-es branch.
[irrlicht.git] / source / Irrlicht / CPLYMeshFileLoader.cpp
1 // Copyright (C) 2009-2012 Gaz Davidson\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 #include "IrrCompileConfig.h"\r
6 #ifdef _IRR_COMPILE_WITH_PLY_LOADER_\r
7 \r
8 #include "CPLYMeshFileLoader.h"\r
9 #include "IMeshManipulator.h"\r
10 #include "SMesh.h"\r
11 #include "CDynamicMeshBuffer.h"\r
12 #include "SAnimatedMesh.h"\r
13 #include "IReadFile.h"\r
14 #include "fast_atof.h"\r
15 #include "os.h"\r
16 \r
17 namespace irr\r
18 {\r
19 namespace scene\r
20 {\r
21 \r
22 // input buffer must be at least twice as long as the longest line in the file\r
23 #define PLY_INPUT_BUFFER_SIZE 51200 // file is loaded in 50k chunks\r
24 \r
25 // constructor\r
26 CPLYMeshFileLoader::CPLYMeshFileLoader(scene::ISceneManager* smgr)\r
27 : SceneManager(smgr), File(0), Buffer(0)\r
28 {\r
29 }\r
30 \r
31 \r
32 CPLYMeshFileLoader::~CPLYMeshFileLoader()\r
33 {\r
34         // delete the buffer in case we didn't earlier\r
35         // (we do, but this could be disabled to increase the speed of loading hundreds of meshes)\r
36         if (Buffer)\r
37         {\r
38                 delete [] Buffer;\r
39                 Buffer = 0;\r
40         }\r
41 \r
42         // Destroy the element list if it exists\r
43         for (u32 i=0; i<ElementList.size(); ++i)\r
44                 delete ElementList[i];\r
45         ElementList.clear();\r
46 }\r
47 \r
48 \r
49 //! returns true if the file maybe is able to be loaded by this class\r
50 bool CPLYMeshFileLoader::isALoadableFileExtension(const io::path& filename) const\r
51 {\r
52         return core::hasFileExtension(filename, "ply");\r
53 }\r
54 \r
55 \r
56 //! creates/loads an animated mesh from the file.\r
57 IAnimatedMesh* CPLYMeshFileLoader::createMesh(io::IReadFile* file)\r
58 {\r
59         if (!file)\r
60                 return 0;\r
61 \r
62         File = file;\r
63         File->grab();\r
64 \r
65         // attempt to allocate the buffer and fill with data\r
66         if (!allocateBuffer())\r
67         {\r
68                 File->drop();\r
69                 File = 0;\r
70                 return 0;\r
71         }\r
72 \r
73         // start with empty mesh\r
74         SAnimatedMesh* animMesh = 0;\r
75         u32 vertCount=0;\r
76 \r
77         // Currently only supports ASCII meshes\r
78         if (strcmp(getNextLine(), "ply"))\r
79         {\r
80                 os::Printer::log("Not a valid PLY file", file->getFileName().c_str(), ELL_ERROR);\r
81         }\r
82         else\r
83         {\r
84                 // cut the next line out\r
85                 getNextLine();\r
86                 // grab the word from this line\r
87                 c8 *word = getNextWord();\r
88 \r
89                 // ignore comments\r
90                 while (strcmp(word, "comment") == 0)\r
91                 {\r
92                         getNextLine();\r
93                         word = getNextWord();\r
94                 }\r
95 \r
96                 bool readingHeader = true;\r
97                 bool continueReading = true;\r
98                 IsBinaryFile = false;\r
99                 IsWrongEndian= false;\r
100 \r
101                 do\r
102                 {\r
103                         if (strcmp(word, "format") == 0)\r
104                         {\r
105                                 word = getNextWord();\r
106 \r
107                                 if (strcmp(word, "binary_little_endian") == 0)\r
108  {\r
109                                         IsBinaryFile = true;\r
110 #ifdef __BIG_ENDIAN__\r
111                                         IsWrongEndian = true;\r
112 #endif\r
113 \r
114                                 }\r
115                                 else if (strcmp(word, "binary_big_endian") == 0)\r
116                                 {\r
117                                         IsBinaryFile = true;\r
118 #ifndef __BIG_ENDIAN__\r
119                                         IsWrongEndian = true;\r
120 #endif\r
121                                 }\r
122                                 else if (strcmp(word, "ascii"))\r
123                                 {\r
124                                         // abort if this isn't an ascii or a binary mesh\r
125                                         os::Printer::log("Unsupported PLY mesh format", word, ELL_ERROR);\r
126                                         continueReading = false;\r
127                                 }\r
128 \r
129                                 if (continueReading)\r
130                                 {\r
131                                         word = getNextWord();\r
132                                         if (strcmp(word, "1.0"))\r
133                                         {\r
134                                                 os::Printer::log("Unsupported PLY mesh version", word, ELL_WARNING);\r
135                                         }\r
136                                 }\r
137                         }\r
138                         else if (strcmp(word, "property") == 0)\r
139                         {\r
140                                 word = getNextWord();\r
141 \r
142                                 if (!ElementList.size())\r
143                                 {\r
144                                         os::Printer::log("PLY property found before element", word, ELL_WARNING);\r
145                                 }\r
146                                 else\r
147                                 {\r
148                                         // get element\r
149                                         SPLYElement* el = ElementList[ElementList.size()-1];\r
150 \r
151                                         // fill property struct\r
152                                         SPLYProperty prop;\r
153                                         prop.Type = getPropertyType(word);\r
154                                         el->KnownSize += prop.size();\r
155 \r
156                                         if (prop.Type == EPLYPT_LIST)\r
157                                         {\r
158                                                 el->IsFixedWidth = false;\r
159 \r
160                                                 word = getNextWord();\r
161 \r
162                                                 prop.Data.List.CountType = getPropertyType(word);\r
163                                                 if (IsBinaryFile && prop.Data.List.CountType == EPLYPT_UNKNOWN)\r
164                                                 {\r
165                                                         os::Printer::log("Cannot read binary PLY file containing data types of unknown length", word, ELL_ERROR);\r
166                                                         continueReading = false;\r
167                                                 }\r
168                                                 else\r
169                                                 {\r
170                                                         word = getNextWord();\r
171                                                         prop.Data.List.ItemType = getPropertyType(word);\r
172                                                         if (IsBinaryFile && prop.Data.List.ItemType == EPLYPT_UNKNOWN)\r
173                                                         {\r
174                                                                 os::Printer::log("Cannot read binary PLY file containing data types of unknown length", word, ELL_ERROR);\r
175                                                                 continueReading = false;\r
176                                                         }\r
177                                                 }\r
178                                         }\r
179                                         else if (IsBinaryFile && prop.Type == EPLYPT_UNKNOWN)\r
180                                         {\r
181                                                 os::Printer::log("Cannot read binary PLY file containing data types of unknown length", word, ELL_ERROR);\r
182                                                 continueReading = false;\r
183                                         }\r
184 \r
185                                         prop.Name = getNextWord();\r
186 \r
187                                         // add property to element\r
188                                         el->Properties.push_back(prop);\r
189                                 }\r
190                         }\r
191                         else if (strcmp(word, "element") == 0)\r
192                         {\r
193                                 SPLYElement* el = new SPLYElement;\r
194                                 el->Name = getNextWord();\r
195                                 el->Count = atoi(getNextWord());\r
196                                 el->IsFixedWidth = true;\r
197                                 el->KnownSize = 0;\r
198                                 ElementList.push_back(el);\r
199 \r
200                                 if (el->Name == "vertex")\r
201                                         vertCount = el->Count;\r
202 \r
203                         }\r
204                         else if (strcmp(word, "end_header") == 0)\r
205                         {\r
206                                 readingHeader = false;\r
207                                 if (IsBinaryFile)\r
208                                 {\r
209                                         StartPointer = LineEndPointer + 1;\r
210                                 }\r
211                         }\r
212                         else if (strcmp(word, "comment") == 0)\r
213                         {\r
214                                 // ignore line\r
215                         }\r
216                         else\r
217                         {\r
218                                 os::Printer::log("Unknown item in PLY file", word, ELL_WARNING);\r
219                         }\r
220 \r
221                         if (readingHeader && continueReading)\r
222                         {\r
223                                 getNextLine();\r
224                                 word = getNextWord();\r
225                         }\r
226                 }\r
227                 while (readingHeader && continueReading);\r
228 \r
229                 // now to read the actual data from the file\r
230                 if (continueReading)\r
231                 {\r
232                         // create a mesh buffer\r
233                         CDynamicMeshBuffer *mb = new CDynamicMeshBuffer(video::EVT_STANDARD, vertCount > 65536 ? video::EIT_32BIT : video::EIT_16BIT);\r
234                         mb->getVertexBuffer().reallocate(vertCount);\r
235                         mb->getIndexBuffer().reallocate(vertCount);\r
236                         mb->setHardwareMappingHint(EHM_STATIC);\r
237 \r
238                         bool hasNormals=true;\r
239                         // loop through each of the elements\r
240                         for (u32 i=0; i<ElementList.size(); ++i)\r
241                         {\r
242                                 // do we want this element type?\r
243                                 if (ElementList[i]->Name == "vertex")\r
244                                 {\r
245                                         // loop through vertex properties\r
246                                         for (u32 j=0; j < ElementList[i]->Count; ++j)\r
247                                                 hasNormals &= readVertex(*ElementList[i], mb);\r
248                                 }\r
249                                 else if (ElementList[i]->Name == "face")\r
250                                 {\r
251                                         // read faces\r
252                                         for (u32 j=0; j < ElementList[i]->Count; ++j)\r
253                                                 readFace(*ElementList[i], mb);\r
254                                 }\r
255                                 else\r
256                                 {\r
257                                         // skip these elements\r
258                                         for (u32 j=0; j < ElementList[i]->Count; ++j)\r
259                                                 skipElement(*ElementList[i]);\r
260                                 }\r
261                         }\r
262                         mb->recalculateBoundingBox();\r
263                         if (!hasNormals)\r
264                                 SceneManager->getMeshManipulator()->recalculateNormals(mb);\r
265                         SMesh* m = new SMesh();\r
266                         m->addMeshBuffer(mb);\r
267                         m->recalculateBoundingBox();\r
268                         mb->drop();\r
269                         animMesh = new SAnimatedMesh();\r
270                         animMesh->addMesh(m);\r
271                         animMesh->recalculateBoundingBox();\r
272                         m->drop();\r
273                 }\r
274         }\r
275 \r
276 \r
277         // free the buffer\r
278         delete [] Buffer;\r
279         Buffer = 0;\r
280         File->drop();\r
281         File = 0;\r
282 \r
283         // if we managed to create a mesh, return it\r
284         return animMesh;\r
285 }\r
286 \r
287 \r
288 bool CPLYMeshFileLoader::readVertex(const SPLYElement &Element, scene::CDynamicMeshBuffer* mb)\r
289 {\r
290         if (!IsBinaryFile)\r
291                 getNextLine();\r
292 \r
293         video::S3DVertex vert;\r
294         vert.Color.set(255,255,255,255);\r
295         vert.TCoords.X = 0.0f;\r
296         vert.TCoords.Y = 0.0f;\r
297         vert.Normal.X = 0.0f;\r
298         vert.Normal.Y = 1.0f;\r
299         vert.Normal.Z = 0.0f;\r
300 \r
301         bool result=false;\r
302         for (u32 i=0; i < Element.Properties.size(); ++i)\r
303         {\r
304                 E_PLY_PROPERTY_TYPE t = Element.Properties[i].Type;\r
305                 const core::stringc& name = Element.Properties[i].Name;\r
306 \r
307                 if (name == "x")\r
308                         vert.Pos.X = getFloat(t);\r
309                 else if (name == "y")\r
310                         vert.Pos.Z = getFloat(t);\r
311                 else if (name == "z")\r
312                         vert.Pos.Y = getFloat(t);\r
313                 else if (name == "nx")\r
314                 {\r
315                         vert.Normal.X = getFloat(t);\r
316                         result=true;\r
317                 }\r
318                 else if (name == "ny")\r
319                 {\r
320                         vert.Normal.Z = getFloat(t);\r
321                         result=true;\r
322                 }\r
323                 else if (name == "nz")\r
324                 {\r
325                         vert.Normal.Y = getFloat(t);\r
326                         result=true;\r
327                 }\r
328                  // There isn't a single convention for the UV, some software like Blender or Assimp uses "st" instead of "uv"\r
329                  // Not sure which tool creates texture_u/texture_v, but those exist as well.\r
330                 else if (name == "u" || name == "s" || name == "texture_u")\r
331                         vert.TCoords.X = getFloat(t);\r
332                 else if (name == "v" || name == "t" || name == "texture_v")\r
333                         vert.TCoords.Y = getFloat(t);\r
334                 else if (name == "red")\r
335                 {\r
336                         u32 value = Element.Properties[i].isFloat() ? (u32)(getFloat(t)*255.0f) : getInt(t);\r
337                         vert.Color.setRed(value);\r
338                 }\r
339                 else if (name == "green")\r
340                 {\r
341                         u32 value = Element.Properties[i].isFloat() ? (u32)(getFloat(t)*255.0f) : getInt(t);\r
342                         vert.Color.setGreen(value);\r
343                 }\r
344                 else if (name == "blue")\r
345                 {\r
346                         u32 value = Element.Properties[i].isFloat() ? (u32)(getFloat(t)*255.0f) : getInt(t);\r
347                         vert.Color.setBlue(value);\r
348                 }\r
349                 else if (name == "alpha")\r
350                 {\r
351                         u32 value = Element.Properties[i].isFloat() ? (u32)(getFloat(t)*255.0f) : getInt(t);\r
352                         vert.Color.setAlpha(value);\r
353                 }\r
354                 else\r
355                         skipProperty(Element.Properties[i]);\r
356         }\r
357 \r
358         mb->getVertexBuffer().push_back(vert);\r
359 \r
360         return result;\r
361 }\r
362 \r
363 \r
364 bool CPLYMeshFileLoader::readFace(const SPLYElement &Element, scene::CDynamicMeshBuffer* mb)\r
365 {\r
366         if (!IsBinaryFile)\r
367                 getNextLine();\r
368 \r
369         for (u32 i=0; i < Element.Properties.size(); ++i)\r
370         {\r
371                 const SPLYProperty& property = Element.Properties[i];\r
372                 if ( (property.Name == "vertex_indices" || property.Name == "vertex_index")\r
373                         && property.Type == EPLYPT_LIST)\r
374                 {\r
375                         // get count\r
376                         s32 count = getInt(property.Data.List.CountType);\r
377                         u32 a = getInt(property.Data.List.ItemType),\r
378                                 b = getInt(property.Data.List.ItemType),\r
379                                 c = getInt(property.Data.List.ItemType);\r
380                         s32 j = 3;\r
381 \r
382                         mb->getIndexBuffer().push_back(a);\r
383                         mb->getIndexBuffer().push_back(c);\r
384                         mb->getIndexBuffer().push_back(b);\r
385 \r
386                         for (; j < count; ++j)\r
387                         {\r
388                                 b = c;\r
389                                 c = getInt(property.Data.List.ItemType);\r
390                                 mb->getIndexBuffer().push_back(a);\r
391                                 mb->getIndexBuffer().push_back(c);\r
392                                 mb->getIndexBuffer().push_back(b);\r
393                         }\r
394                 }\r
395                 else if (property.Name == "intensity")\r
396                 {\r
397                         // todo: face intensity\r
398                         skipProperty(property);\r
399                 }\r
400                 else\r
401                         skipProperty(property);\r
402         }\r
403         return true;\r
404 }\r
405 \r
406 \r
407 // skips an element and all properties. return false on EOF\r
408 void CPLYMeshFileLoader::skipElement(const SPLYElement &Element)\r
409 {\r
410         if (IsBinaryFile)\r
411                 if (Element.IsFixedWidth)\r
412                         moveForward(Element.KnownSize);\r
413                 else\r
414                         for (u32 i=0; i < Element.Properties.size(); ++i)\r
415                                 skipProperty(Element.Properties[i]);\r
416         else\r
417                 getNextLine();\r
418 }\r
419 \r
420 \r
421 void CPLYMeshFileLoader::skipProperty(const SPLYProperty &Property)\r
422 {\r
423         if (Property.Type == EPLYPT_LIST)\r
424         {\r
425                 s32 count = getInt(Property.Data.List.CountType);\r
426 \r
427                 for (s32 i=0; i < count; ++i)\r
428                         getInt(Property.Data.List.CountType);\r
429         }\r
430         else\r
431         {\r
432                 if (IsBinaryFile)\r
433                         moveForward(Property.size());\r
434                 else\r
435                         getNextWord();\r
436         }\r
437 }\r
438 \r
439 \r
440 bool CPLYMeshFileLoader::allocateBuffer()\r
441 {\r
442         // Destroy the element list if it exists\r
443         for (u32 i=0; i<ElementList.size(); ++i)\r
444                 delete ElementList[i];\r
445         ElementList.clear();\r
446 \r
447         if (!Buffer)\r
448                 Buffer = new c8[PLY_INPUT_BUFFER_SIZE];\r
449 \r
450         // not enough memory?\r
451         if (!Buffer)\r
452                 return false;\r
453 \r
454         // blank memory\r
455         memset(Buffer, 0, PLY_INPUT_BUFFER_SIZE);\r
456 \r
457         StartPointer = Buffer;\r
458         EndPointer = Buffer;\r
459         LineEndPointer = Buffer-1;\r
460         WordLength = -1;\r
461         EndOfFile = false;\r
462 \r
463         // get data from the file\r
464         fillBuffer();\r
465 \r
466         return true;\r
467 }\r
468 \r
469 \r
470 // gets more data from the file. returns false on EOF\r
471 void CPLYMeshFileLoader::fillBuffer()\r
472 {\r
473         if (EndOfFile)\r
474                 return;\r
475 \r
476         size_t length = (size_t)(EndPointer - StartPointer);\r
477         if (length && StartPointer != Buffer)\r
478         {\r
479                 // copy the remaining data to the start of the buffer\r
480                 memcpy(Buffer, StartPointer, length);\r
481         }\r
482         // reset start position\r
483         StartPointer = Buffer;\r
484         EndPointer = StartPointer + length;\r
485 \r
486         if (File->getPos() == File->getSize())\r
487         {\r
488                 EndOfFile = true;\r
489         }\r
490         else\r
491         {\r
492                 // read data from the file\r
493                 size_t count = File->read(EndPointer, PLY_INPUT_BUFFER_SIZE - length);\r
494 \r
495                 // increment the end pointer by the number of bytes read\r
496                 EndPointer = EndPointer + count;\r
497 \r
498                 // if we didn't completely fill the buffer\r
499                 if (count != PLY_INPUT_BUFFER_SIZE - length)\r
500                 {\r
501                         // blank the rest of the memory\r
502                         memset(EndPointer, 0, Buffer + PLY_INPUT_BUFFER_SIZE - EndPointer);\r
503 \r
504                         // end of file\r
505                         EndOfFile = true;\r
506                 }\r
507         }\r
508 }\r
509 \r
510 \r
511 // skips x bytes in the file, getting more data if required\r
512 void CPLYMeshFileLoader::moveForward(u32 bytes)\r
513 {\r
514         if (StartPointer + bytes >= EndPointer)\r
515                 fillBuffer();\r
516         if (StartPointer + bytes < EndPointer)\r
517                 StartPointer += bytes;\r
518         else\r
519                 StartPointer = EndPointer;\r
520 }\r
521 \r
522 \r
523 E_PLY_PROPERTY_TYPE CPLYMeshFileLoader::getPropertyType(const c8* typeString) const\r
524 {\r
525         if (strcmp(typeString, "char") == 0 ||\r
526                 strcmp(typeString, "uchar") == 0 ||\r
527                 strcmp(typeString, "int8") == 0 ||\r
528                 strcmp(typeString, "uint8") == 0)\r
529         {\r
530                 return EPLYPT_INT8;\r
531         }\r
532         else if (strcmp(typeString, "uint") == 0 ||\r
533                 strcmp(typeString, "int16") == 0 ||\r
534                 strcmp(typeString, "uint16") == 0 ||\r
535                 strcmp(typeString, "short") == 0 ||\r
536                 strcmp(typeString, "ushort") == 0)\r
537         {\r
538                 return EPLYPT_INT16;\r
539         }\r
540         else if (strcmp(typeString, "int") == 0 ||\r
541                 strcmp(typeString, "long") == 0 ||\r
542                 strcmp(typeString, "ulong") == 0 ||\r
543                 strcmp(typeString, "int32") == 0 ||\r
544                 strcmp(typeString, "uint32") == 0)\r
545         {\r
546                 return EPLYPT_INT32;\r
547         }\r
548         else if (strcmp(typeString, "float") == 0 ||\r
549                 strcmp(typeString, "float32") == 0)\r
550         {\r
551                 return EPLYPT_FLOAT32;\r
552         }\r
553         else if (strcmp(typeString, "float64") == 0 ||\r
554                 strcmp(typeString, "double") == 0)\r
555         {\r
556                 return EPLYPT_FLOAT64;\r
557         }\r
558         else if ( strcmp(typeString, "list") == 0 )\r
559         {\r
560                 return EPLYPT_LIST;\r
561         }\r
562         else\r
563         {\r
564                 // unsupported type.\r
565                 // cannot be loaded in binary mode\r
566                 return EPLYPT_UNKNOWN;\r
567         }\r
568 }\r
569 \r
570 \r
571 // Split the string data into a line in place by terminating it instead of copying.\r
572 c8* CPLYMeshFileLoader::getNextLine()\r
573 {\r
574         // move the start pointer along\r
575         StartPointer = LineEndPointer + 1;\r
576 \r
577         // crlf split across buffer move\r
578         if (StartPointer<EndPointer && *StartPointer == '\n')\r
579         {\r
580                 *StartPointer = '\0';\r
581                 ++StartPointer;\r
582         }\r
583 \r
584         // begin at the start of the next line\r
585         c8* pos = StartPointer;\r
586         while (pos < EndPointer && *pos && *pos != '\r' && *pos != '\n')\r
587                 ++pos;\r
588 \r
589         if ( (pos+1) < EndPointer && ( *(pos+1) == '\r' || *(pos+1) == '\n') )\r
590         {\r
591                 *pos = '\0';\r
592                 ++pos;\r
593         }\r
594 \r
595         // we have reached the end of the buffer\r
596         if (pos >= EndPointer)\r
597         {\r
598                 // get data from the file\r
599                 if (!EndOfFile)\r
600                 {\r
601                         fillBuffer();\r
602                         // reset line end pointer\r
603                         LineEndPointer = StartPointer - 1;\r
604 \r
605                         if (StartPointer != EndPointer)\r
606                                 return getNextLine();\r
607                         else\r
608                                 return Buffer;\r
609                 }\r
610                 else\r
611                 {\r
612                         // EOF\r
613                         StartPointer = EndPointer-1;\r
614                         *StartPointer = '\0';\r
615                         return StartPointer;\r
616                 }\r
617         }\r
618         else\r
619         {\r
620                 // null terminate the string in place\r
621                 *pos = '\0';\r
622                 LineEndPointer = pos;\r
623                 WordLength = -1;\r
624                 // return pointer to the start of the line\r
625                 return StartPointer;\r
626         }\r
627 }\r
628 \r
629 \r
630 // null terminate the next word on the previous line and move the next word pointer along\r
631 // since we already have a full line in the buffer, we never need to retrieve more data\r
632 c8* CPLYMeshFileLoader::getNextWord()\r
633 {\r
634         // move the start pointer along\r
635         StartPointer += WordLength + 1;\r
636 \r
637         if (StartPointer == LineEndPointer)\r
638         {\r
639                 WordLength = -1; //\r
640                 return LineEndPointer;\r
641         }\r
642         // begin at the start of the next word\r
643         c8* pos = StartPointer;\r
644         while (*pos && pos < LineEndPointer && pos < EndPointer && *pos != ' ' && *pos != '\t')\r
645                 ++pos;\r
646 \r
647         while(*pos && pos < LineEndPointer && pos < EndPointer && (*pos == ' ' || *pos == '\t') )\r
648         {\r
649                 // null terminate the string in place\r
650                 *pos = '\0';\r
651                 ++pos;\r
652         }\r
653         --pos;\r
654         WordLength = (s32)(pos-StartPointer);\r
655         // return pointer to the start of the word\r
656         return StartPointer;\r
657 }\r
658 \r
659 \r
660 // read the next float from the file and move the start pointer along\r
661 f32 CPLYMeshFileLoader::getFloat(E_PLY_PROPERTY_TYPE t)\r
662 {\r
663         f32 retVal = 0.0f;\r
664 \r
665         if (IsBinaryFile)\r
666         {\r
667                 if (EndPointer - StartPointer < 8)\r
668                         fillBuffer();\r
669 \r
670                 if (EndPointer - StartPointer > 0)\r
671                 {\r
672                         switch (t)\r
673                         {\r
674                         case EPLYPT_INT8:\r
675                                 retVal = *StartPointer;\r
676                                 StartPointer++;\r
677                                 break;\r
678                         case EPLYPT_INT16:\r
679                                 if (IsWrongEndian)\r
680                                         retVal = os::Byteswap::byteswap(*(reinterpret_cast<s16*>(StartPointer)));\r
681                                 else\r
682                                         retVal = *(reinterpret_cast<s16*>(StartPointer));\r
683                                 StartPointer += 2;\r
684                                 break;\r
685                         case EPLYPT_INT32:\r
686                                 if (IsWrongEndian)\r
687                                         retVal = f32(os::Byteswap::byteswap(*(reinterpret_cast<s32*>(StartPointer))));\r
688                                 else\r
689                                         retVal = f32(*(reinterpret_cast<s32*>(StartPointer)));\r
690                                 StartPointer += 4;\r
691                                 break;\r
692                         case EPLYPT_FLOAT32:\r
693                                 if (IsWrongEndian)\r
694                                         retVal = os::Byteswap::byteswap(*(reinterpret_cast<f32*>(StartPointer)));\r
695                                 else\r
696                                         retVal = *(reinterpret_cast<f32*>(StartPointer));\r
697                                 StartPointer += 4;\r
698                                 break;\r
699                         case EPLYPT_FLOAT64:\r
700                                 // todo: byteswap 64-bit\r
701                                 retVal = f32(*(reinterpret_cast<f64*>(StartPointer)));\r
702                                 StartPointer += 8;\r
703                                 break;\r
704                         case EPLYPT_LIST:\r
705                         case EPLYPT_UNKNOWN:\r
706                         default:\r
707                                 retVal = 0.0f;\r
708                                 StartPointer++; // ouch!\r
709                         }\r
710                 }\r
711                 else\r
712                         retVal = 0.0f;\r
713         }\r
714         else\r
715         {\r
716                 c8* word = getNextWord();\r
717                 switch (t)\r
718                 {\r
719                 case EPLYPT_INT8:\r
720                 case EPLYPT_INT16:\r
721                 case EPLYPT_INT32:\r
722                         retVal = f32(atoi(word));\r
723                         break;\r
724                 case EPLYPT_FLOAT32:\r
725                 case EPLYPT_FLOAT64:\r
726                         retVal = f32(atof(word));\r
727                         break;\r
728                 case EPLYPT_LIST:\r
729                 case EPLYPT_UNKNOWN:\r
730                 default:\r
731                         retVal = 0.0f;\r
732                 }\r
733         }\r
734         return retVal;\r
735 }\r
736 \r
737 \r
738 // read the next int from the file and move the start pointer along\r
739 u32 CPLYMeshFileLoader::getInt(E_PLY_PROPERTY_TYPE t)\r
740 {\r
741         u32 retVal = 0;\r
742 \r
743         if (IsBinaryFile)\r
744         {\r
745                 if (!EndOfFile && EndPointer - StartPointer < 8)\r
746                         fillBuffer();\r
747 \r
748                 if (EndPointer - StartPointer)\r
749                 {\r
750                         switch (t)\r
751                         {\r
752                         case EPLYPT_INT8:\r
753                                 retVal = *StartPointer;\r
754                                 StartPointer++;\r
755                                 break;\r
756                         case EPLYPT_INT16:\r
757                                 if (IsWrongEndian)\r
758                                         retVal = os::Byteswap::byteswap(*(reinterpret_cast<u16*>(StartPointer)));\r
759                                 else\r
760                                         retVal = *(reinterpret_cast<u16*>(StartPointer));\r
761                                 StartPointer += 2;\r
762                                 break;\r
763                         case EPLYPT_INT32:\r
764                                 if (IsWrongEndian)\r
765                                         retVal = os::Byteswap::byteswap(*(reinterpret_cast<s32*>(StartPointer)));\r
766                                 else\r
767                                         retVal = *(reinterpret_cast<s32*>(StartPointer));\r
768                                 StartPointer += 4;\r
769                                 break;\r
770                         case EPLYPT_FLOAT32:\r
771                                 if (IsWrongEndian)\r
772                                         retVal = (u32)os::Byteswap::byteswap(*(reinterpret_cast<f32*>(StartPointer)));\r
773                                 else\r
774                                         retVal = (u32)(*(reinterpret_cast<f32*>(StartPointer)));\r
775                                 StartPointer += 4;\r
776                                 break;\r
777                         case EPLYPT_FLOAT64:\r
778                                 // todo: byteswap 64-bit\r
779                                 retVal = (u32)(*(reinterpret_cast<f64*>(StartPointer)));\r
780                                 StartPointer += 8;\r
781                                 break;\r
782                         case EPLYPT_LIST:\r
783                         case EPLYPT_UNKNOWN:\r
784                         default:\r
785                                 retVal = 0;\r
786                                 StartPointer++; // ouch!\r
787                         }\r
788                 }\r
789                 else\r
790                         retVal = 0;\r
791         }\r
792         else\r
793         {\r
794                 c8* word = getNextWord();\r
795                 switch (t)\r
796                 {\r
797                 case EPLYPT_INT8:\r
798                 case EPLYPT_INT16:\r
799                 case EPLYPT_INT32:\r
800                         retVal = atoi(word);\r
801                         break;\r
802                 case EPLYPT_FLOAT32:\r
803                 case EPLYPT_FLOAT64:\r
804                         retVal = u32(atof(word));\r
805                         break;\r
806                 case EPLYPT_LIST:\r
807                 case EPLYPT_UNKNOWN:\r
808                 default:\r
809                         retVal = 0;\r
810                 }\r
811         }\r
812         return retVal;\r
813 }\r
814 \r
815 \r
816 \r
817 } // end namespace scene\r
818 } // end namespace irr\r
819 \r
820 #endif // _IRR_COMPILE_WITH_PLY_LOADER_\r
821 \r