]> git.lizzy.rs Git - irrlicht.git/blob - source/Irrlicht/CPLYMeshFileLoader.cpp
03b3e47166fa65e3b78eec131dc2ef2f8f51e3fd
[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 > 65565 ? 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 \r
306                 if (Element.Properties[i].Name == "x")\r
307                         vert.Pos.X = getFloat(t);\r
308                 else if (Element.Properties[i].Name == "y")\r
309                         vert.Pos.Z = getFloat(t);\r
310                 else if (Element.Properties[i].Name == "z")\r
311                         vert.Pos.Y = getFloat(t);\r
312                 else if (Element.Properties[i].Name == "nx")\r
313                 {\r
314                         vert.Normal.X = getFloat(t);\r
315                         result=true;\r
316                 }\r
317                 else if (Element.Properties[i].Name == "ny")\r
318                 {\r
319                         vert.Normal.Z = getFloat(t);\r
320                         result=true;\r
321                 }\r
322                 else if (Element.Properties[i].Name == "nz")\r
323                 {\r
324                         vert.Normal.Y = getFloat(t);\r
325                         result=true;\r
326                 }\r
327                  // there isn't a single convention for the UV, some software like Blender or Assimp uses "st" instead of "uv"\r
328                 else if (Element.Properties[i].Name == "u" || Element.Properties[i].Name == "s")\r
329                         vert.TCoords.X = getFloat(t);\r
330                 else if (Element.Properties[i].Name == "v" || Element.Properties[i].Name == "t")\r
331                         vert.TCoords.Y = getFloat(t);\r
332                 else if (Element.Properties[i].Name == "red")\r
333                 {\r
334                         u32 value = Element.Properties[i].isFloat() ? (u32)(getFloat(t)*255.0f) : getInt(t);\r
335                         vert.Color.setRed(value);\r
336                 }\r
337                 else if (Element.Properties[i].Name == "green")\r
338                 {\r
339                         u32 value = Element.Properties[i].isFloat() ? (u32)(getFloat(t)*255.0f) : getInt(t);\r
340                         vert.Color.setGreen(value);\r
341                 }\r
342                 else if (Element.Properties[i].Name == "blue")\r
343                 {\r
344                         u32 value = Element.Properties[i].isFloat() ? (u32)(getFloat(t)*255.0f) : getInt(t);\r
345                         vert.Color.setBlue(value);\r
346                 }\r
347                 else if (Element.Properties[i].Name == "alpha")\r
348                 {\r
349                         u32 value = Element.Properties[i].isFloat() ? (u32)(getFloat(t)*255.0f) : getInt(t);\r
350                         vert.Color.setAlpha(value);\r
351                 }\r
352                 else\r
353                         skipProperty(Element.Properties[i]);\r
354         }\r
355 \r
356         mb->getVertexBuffer().push_back(vert);\r
357 \r
358         return result;\r
359 }\r
360 \r
361 \r
362 bool CPLYMeshFileLoader::readFace(const SPLYElement &Element, scene::CDynamicMeshBuffer* mb)\r
363 {\r
364         if (!IsBinaryFile)\r
365                 getNextLine();\r
366 \r
367         for (u32 i=0; i < Element.Properties.size(); ++i)\r
368         {\r
369                 if ( (Element.Properties[i].Name == "vertex_indices" ||\r
370                         Element.Properties[i].Name == "vertex_index") && Element.Properties[i].Type == EPLYPT_LIST)\r
371                 {\r
372                         // get count\r
373                         s32 count = getInt(Element.Properties[i].Data.List.CountType);\r
374                         u32 a = getInt(Element.Properties[i].Data.List.ItemType),\r
375                                 b = getInt(Element.Properties[i].Data.List.ItemType),\r
376                                 c = getInt(Element.Properties[i].Data.List.ItemType);\r
377                         s32 j = 3;\r
378 \r
379                         mb->getIndexBuffer().push_back(a);\r
380                         mb->getIndexBuffer().push_back(c);\r
381                         mb->getIndexBuffer().push_back(b);\r
382 \r
383                         for (; j < count; ++j)\r
384                         {\r
385                                 b = c;\r
386                                 c = getInt(Element.Properties[i].Data.List.ItemType);\r
387                                 mb->getIndexBuffer().push_back(a);\r
388                                 mb->getIndexBuffer().push_back(c);\r
389                                 mb->getIndexBuffer().push_back(b);\r
390                         }\r
391                 }\r
392                 else if (Element.Properties[i].Name == "intensity")\r
393                 {\r
394                         // todo: face intensity\r
395                         skipProperty(Element.Properties[i]);\r
396                 }\r
397                 else\r
398                         skipProperty(Element.Properties[i]);\r
399         }\r
400         return true;\r
401 }\r
402 \r
403 \r
404 // skips an element and all properties. return false on EOF\r
405 void CPLYMeshFileLoader::skipElement(const SPLYElement &Element)\r
406 {\r
407         if (IsBinaryFile)\r
408                 if (Element.IsFixedWidth)\r
409                         moveForward(Element.KnownSize);\r
410                 else\r
411                         for (u32 i=0; i < Element.Properties.size(); ++i)\r
412                                 skipProperty(Element.Properties[i]);\r
413         else\r
414                 getNextLine();\r
415 }\r
416 \r
417 \r
418 void CPLYMeshFileLoader::skipProperty(const SPLYProperty &Property)\r
419 {\r
420         if (Property.Type == EPLYPT_LIST)\r
421         {\r
422                 s32 count = getInt(Property.Data.List.CountType);\r
423 \r
424                 for (s32 i=0; i < count; ++i)\r
425                         getInt(Property.Data.List.CountType);\r
426         }\r
427         else\r
428         {\r
429                 if (IsBinaryFile)\r
430                         moveForward(Property.size());\r
431                 else\r
432                         getNextWord();\r
433         }\r
434 }\r
435 \r
436 \r
437 bool CPLYMeshFileLoader::allocateBuffer()\r
438 {\r
439         // Destroy the element list if it exists\r
440         for (u32 i=0; i<ElementList.size(); ++i)\r
441                 delete ElementList[i];\r
442         ElementList.clear();\r
443 \r
444         if (!Buffer)\r
445                 Buffer = new c8[PLY_INPUT_BUFFER_SIZE];\r
446 \r
447         // not enough memory?\r
448         if (!Buffer)\r
449                 return false;\r
450 \r
451         // blank memory\r
452         memset(Buffer, 0, PLY_INPUT_BUFFER_SIZE);\r
453 \r
454         StartPointer = Buffer;\r
455         EndPointer = Buffer;\r
456         LineEndPointer = Buffer-1;\r
457         WordLength = -1;\r
458         EndOfFile = false;\r
459 \r
460         // get data from the file\r
461         fillBuffer();\r
462 \r
463         return true;\r
464 }\r
465 \r
466 \r
467 // gets more data from the file. returns false on EOF\r
468 void CPLYMeshFileLoader::fillBuffer()\r
469 {\r
470         if (EndOfFile)\r
471                 return;\r
472 \r
473         size_t length = (size_t)(EndPointer - StartPointer);\r
474         if (length && StartPointer != Buffer)\r
475         {\r
476                 // copy the remaining data to the start of the buffer\r
477                 memcpy(Buffer, StartPointer, length);\r
478         }\r
479         // reset start position\r
480         StartPointer = Buffer;\r
481         EndPointer = StartPointer + length;\r
482 \r
483         if (File->getPos() == File->getSize())\r
484         {\r
485                 EndOfFile = true;\r
486         }\r
487         else\r
488         {\r
489                 // read data from the file\r
490                 size_t count = File->read(EndPointer, PLY_INPUT_BUFFER_SIZE - length);\r
491 \r
492                 // increment the end pointer by the number of bytes read\r
493                 EndPointer = EndPointer + count;\r
494 \r
495                 // if we didn't completely fill the buffer\r
496                 if (count != PLY_INPUT_BUFFER_SIZE - length)\r
497                 {\r
498                         // blank the rest of the memory\r
499                         memset(EndPointer, 0, Buffer + PLY_INPUT_BUFFER_SIZE - EndPointer);\r
500 \r
501                         // end of file\r
502                         EndOfFile = true;\r
503                 }\r
504         }\r
505 }\r
506 \r
507 \r
508 // skips x bytes in the file, getting more data if required\r
509 void CPLYMeshFileLoader::moveForward(u32 bytes)\r
510 {\r
511         if (StartPointer + bytes >= EndPointer)\r
512                 fillBuffer();\r
513         if (StartPointer + bytes < EndPointer)\r
514                 StartPointer += bytes;\r
515         else\r
516                 StartPointer = EndPointer;\r
517 }\r
518 \r
519 \r
520 E_PLY_PROPERTY_TYPE CPLYMeshFileLoader::getPropertyType(const c8* typeString) const\r
521 {\r
522         if (strcmp(typeString, "char") == 0 ||\r
523                 strcmp(typeString, "uchar") == 0 ||\r
524                 strcmp(typeString, "int8") == 0 ||\r
525                 strcmp(typeString, "uint8") == 0)\r
526         {\r
527                 return EPLYPT_INT8;\r
528         }\r
529         else if (strcmp(typeString, "uint") == 0 ||\r
530                 strcmp(typeString, "int16") == 0 ||\r
531                 strcmp(typeString, "uint16") == 0 ||\r
532                 strcmp(typeString, "short") == 0 ||\r
533                 strcmp(typeString, "ushort") == 0)\r
534         {\r
535                 return EPLYPT_INT16;\r
536         }\r
537         else if (strcmp(typeString, "int") == 0 ||\r
538                 strcmp(typeString, "long") == 0 ||\r
539                 strcmp(typeString, "ulong") == 0 ||\r
540                 strcmp(typeString, "int32") == 0 ||\r
541                 strcmp(typeString, "uint32") == 0)\r
542         {\r
543                 return EPLYPT_INT32;\r
544         }\r
545         else if (strcmp(typeString, "float") == 0 ||\r
546                 strcmp(typeString, "float32") == 0)\r
547         {\r
548                 return EPLYPT_FLOAT32;\r
549         }\r
550         else if (strcmp(typeString, "float64") == 0 ||\r
551                 strcmp(typeString, "double") == 0)\r
552         {\r
553                 return EPLYPT_FLOAT64;\r
554         }\r
555         else if ( strcmp(typeString, "list") == 0 )\r
556         {\r
557                 return EPLYPT_LIST;\r
558         }\r
559         else\r
560         {\r
561                 // unsupported type.\r
562                 // cannot be loaded in binary mode\r
563                 return EPLYPT_UNKNOWN;\r
564         }\r
565 }\r
566 \r
567 \r
568 // Split the string data into a line in place by terminating it instead of copying.\r
569 c8* CPLYMeshFileLoader::getNextLine()\r
570 {\r
571         // move the start pointer along\r
572         StartPointer = LineEndPointer + 1;\r
573 \r
574         // crlf split across buffer move\r
575         if (*StartPointer == '\n')\r
576         {\r
577                 *StartPointer = '\0';\r
578                 ++StartPointer;\r
579         }\r
580 \r
581         // begin at the start of the next line\r
582         c8* pos = StartPointer;\r
583         while (pos < EndPointer && *pos && *pos != '\r' && *pos != '\n')\r
584                 ++pos;\r
585 \r
586         if ( pos < EndPointer && ( *(pos+1) == '\r' || *(pos+1) == '\n') )\r
587         {\r
588                 *pos = '\0';\r
589                 ++pos;\r
590         }\r
591 \r
592         // we have reached the end of the buffer\r
593         if (pos >= EndPointer)\r
594         {\r
595                 // get data from the file\r
596                 if (!EndOfFile)\r
597                 {\r
598                         fillBuffer();\r
599                         // reset line end pointer\r
600                         LineEndPointer = StartPointer - 1;\r
601 \r
602                         if (StartPointer != EndPointer)\r
603                                 return getNextLine();\r
604                         else\r
605                                 return Buffer;\r
606                 }\r
607                 else\r
608                 {\r
609                         // EOF\r
610                         StartPointer = EndPointer-1;\r
611                         *StartPointer = '\0';\r
612                         return StartPointer;\r
613                 }\r
614         }\r
615         else\r
616         {\r
617                 // null terminate the string in place\r
618                 *pos = '\0';\r
619                 LineEndPointer = pos;\r
620                 WordLength = -1;\r
621                 // return pointer to the start of the line\r
622                 return StartPointer;\r
623         }\r
624 }\r
625 \r
626 \r
627 // null terminate the next word on the previous line and move the next word pointer along\r
628 // since we already have a full line in the buffer, we never need to retrieve more data\r
629 c8* CPLYMeshFileLoader::getNextWord()\r
630 {\r
631         // move the start pointer along\r
632         StartPointer += WordLength + 1;\r
633 \r
634         if (StartPointer == LineEndPointer)\r
635         {\r
636                 WordLength = -1; //\r
637                 return LineEndPointer;\r
638         }\r
639         // begin at the start of the next word\r
640         c8* pos = StartPointer;\r
641         while (*pos && pos < LineEndPointer && pos < EndPointer && *pos != ' ' && *pos != '\t')\r
642                 ++pos;\r
643 \r
644         while(*pos && pos < LineEndPointer && pos < EndPointer && (*pos == ' ' || *pos == '\t') )\r
645         {\r
646                 // null terminate the string in place\r
647                 *pos = '\0';\r
648                 ++pos;\r
649         }\r
650         --pos;\r
651         WordLength = (s32)(pos-StartPointer);\r
652         // return pointer to the start of the word\r
653         return StartPointer;\r
654 }\r
655 \r
656 \r
657 // read the next float from the file and move the start pointer along\r
658 f32 CPLYMeshFileLoader::getFloat(E_PLY_PROPERTY_TYPE t)\r
659 {\r
660         f32 retVal = 0.0f;\r
661 \r
662         if (IsBinaryFile)\r
663         {\r
664                 if (EndPointer - StartPointer < 8)\r
665                         fillBuffer();\r
666 \r
667                 if (EndPointer - StartPointer > 0)\r
668                 {\r
669                         switch (t)\r
670                         {\r
671                         case EPLYPT_INT8:\r
672                                 retVal = *StartPointer;\r
673                                 StartPointer++;\r
674                                 break;\r
675                         case EPLYPT_INT16:\r
676                                 if (IsWrongEndian)\r
677                                         retVal = os::Byteswap::byteswap(*(reinterpret_cast<s16*>(StartPointer)));\r
678                                 else\r
679                                         retVal = *(reinterpret_cast<s16*>(StartPointer));\r
680                                 StartPointer += 2;\r
681                                 break;\r
682                         case EPLYPT_INT32:\r
683                                 if (IsWrongEndian)\r
684                                         retVal = f32(os::Byteswap::byteswap(*(reinterpret_cast<s32*>(StartPointer))));\r
685                                 else\r
686                                         retVal = f32(*(reinterpret_cast<s32*>(StartPointer)));\r
687                                 StartPointer += 4;\r
688                                 break;\r
689                         case EPLYPT_FLOAT32:\r
690                                 if (IsWrongEndian)\r
691                                         retVal = os::Byteswap::byteswap(*(reinterpret_cast<f32*>(StartPointer)));\r
692                                 else\r
693                                         retVal = *(reinterpret_cast<f32*>(StartPointer));\r
694                                 StartPointer += 4;\r
695                                 break;\r
696                         case EPLYPT_FLOAT64:\r
697                                 // todo: byteswap 64-bit\r
698                                 retVal = f32(*(reinterpret_cast<f64*>(StartPointer)));\r
699                                 StartPointer += 8;\r
700                                 break;\r
701                         case EPLYPT_LIST:\r
702                         case EPLYPT_UNKNOWN:\r
703                         default:\r
704                                 retVal = 0.0f;\r
705                                 StartPointer++; // ouch!\r
706                         }\r
707                 }\r
708                 else\r
709                         retVal = 0.0f;\r
710         }\r
711         else\r
712         {\r
713                 c8* word = getNextWord();\r
714                 switch (t)\r
715                 {\r
716                 case EPLYPT_INT8:\r
717                 case EPLYPT_INT16:\r
718                 case EPLYPT_INT32:\r
719                         retVal = f32(atoi(word));\r
720                         break;\r
721                 case EPLYPT_FLOAT32:\r
722                 case EPLYPT_FLOAT64:\r
723                         retVal = f32(atof(word));\r
724                         break;\r
725                 case EPLYPT_LIST:\r
726                 case EPLYPT_UNKNOWN:\r
727                 default:\r
728                         retVal = 0.0f;\r
729                 }\r
730         }\r
731         return retVal;\r
732 }\r
733 \r
734 \r
735 // read the next int from the file and move the start pointer along\r
736 u32 CPLYMeshFileLoader::getInt(E_PLY_PROPERTY_TYPE t)\r
737 {\r
738         u32 retVal = 0;\r
739 \r
740         if (IsBinaryFile)\r
741         {\r
742                 if (!EndOfFile && EndPointer - StartPointer < 8)\r
743                         fillBuffer();\r
744 \r
745                 if (EndPointer - StartPointer)\r
746                 {\r
747                         switch (t)\r
748                         {\r
749                         case EPLYPT_INT8:\r
750                                 retVal = *StartPointer;\r
751                                 StartPointer++;\r
752                                 break;\r
753                         case EPLYPT_INT16:\r
754                                 if (IsWrongEndian)\r
755                                         retVal = os::Byteswap::byteswap(*(reinterpret_cast<u16*>(StartPointer)));\r
756                                 else\r
757                                         retVal = *(reinterpret_cast<u16*>(StartPointer));\r
758                                 StartPointer += 2;\r
759                                 break;\r
760                         case EPLYPT_INT32:\r
761                                 if (IsWrongEndian)\r
762                                         retVal = os::Byteswap::byteswap(*(reinterpret_cast<s32*>(StartPointer)));\r
763                                 else\r
764                                         retVal = *(reinterpret_cast<s32*>(StartPointer));\r
765                                 StartPointer += 4;\r
766                                 break;\r
767                         case EPLYPT_FLOAT32:\r
768                                 if (IsWrongEndian)\r
769                                         retVal = (u32)os::Byteswap::byteswap(*(reinterpret_cast<f32*>(StartPointer)));\r
770                                 else\r
771                                         retVal = (u32)(*(reinterpret_cast<f32*>(StartPointer)));\r
772                                 StartPointer += 4;\r
773                                 break;\r
774                         case EPLYPT_FLOAT64:\r
775                                 // todo: byteswap 64-bit\r
776                                 retVal = (u32)(*(reinterpret_cast<f64*>(StartPointer)));\r
777                                 StartPointer += 8;\r
778                                 break;\r
779                         case EPLYPT_LIST:\r
780                         case EPLYPT_UNKNOWN:\r
781                         default:\r
782                                 retVal = 0;\r
783                                 StartPointer++; // ouch!\r
784                         }\r
785                 }\r
786                 else\r
787                         retVal = 0;\r
788         }\r
789         else\r
790         {\r
791                 c8* word = getNextWord();\r
792                 switch (t)\r
793                 {\r
794                 case EPLYPT_INT8:\r
795                 case EPLYPT_INT16:\r
796                 case EPLYPT_INT32:\r
797                         retVal = atoi(word);\r
798                         break;\r
799                 case EPLYPT_FLOAT32:\r
800                 case EPLYPT_FLOAT64:\r
801                         retVal = u32(atof(word));\r
802                         break;\r
803                 case EPLYPT_LIST:\r
804                 case EPLYPT_UNKNOWN:\r
805                 default:\r
806                         retVal = 0;\r
807                 }\r
808         }\r
809         return retVal;\r
810 }\r
811 \r
812 \r
813 \r
814 } // end namespace scene\r
815 } // end namespace irr\r
816 \r
817 #endif // _IRR_COMPILE_WITH_PLY_LOADER_\r
818 \r