vrshoot
view libs/assimp/PlyParser.cpp @ 1:e7ca128b8713
looks nice :)
author | John Tsiombikas <nuclear@member.fsf.org> |
---|---|
date | Sun, 02 Feb 2014 00:35:22 +0200 |
parents | |
children |
line source
1 /*
2 ---------------------------------------------------------------------------
3 Open Asset Import Library (assimp)
4 ---------------------------------------------------------------------------
6 Copyright (c) 2006-2012, assimp team
8 All rights reserved.
10 Redistribution and use of this software in source and binary forms,
11 with or without modification, are permitted provided that the following
12 conditions are met:
14 * Redistributions of source code must retain the above
15 copyright notice, this list of conditions and the
16 following disclaimer.
18 * Redistributions in binary form must reproduce the above
19 copyright notice, this list of conditions and the
20 following disclaimer in the documentation and/or other
21 materials provided with the distribution.
23 * Neither the name of the assimp team, nor the names of its
24 contributors may be used to endorse or promote products
25 derived from this software without specific prior
26 written permission of the assimp team.
28 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
29 "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
30 LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
31 A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
32 OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
33 SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
34 LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
35 DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
36 THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
37 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
38 OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
39 ---------------------------------------------------------------------------
40 */
42 /** @file Implementation of the PLY parser class */
44 #include "AssimpPCH.h"
45 #ifndef ASSIMP_BUILD_NO_PLY_IMPORTER
47 #include "PlyLoader.h"
48 #include "fast_atof.h"
50 using namespace Assimp;
52 // ------------------------------------------------------------------------------------------------
53 PLY::EDataType PLY::Property::ParseDataType(const char* pCur,const char** pCurOut)
54 {
55 ai_assert(NULL != pCur && NULL != pCurOut);
56 PLY::EDataType eOut = PLY::EDT_INVALID;
58 if (TokenMatch(pCur,"char",4) ||
59 TokenMatch(pCur,"int8",4))
60 {
61 eOut = PLY::EDT_Char;
62 }
63 else if (TokenMatch(pCur,"uchar",5) ||
64 TokenMatch(pCur,"uint8",5))
65 {
66 eOut = PLY::EDT_UChar;
67 }
68 else if (TokenMatch(pCur,"short",5) ||
69 TokenMatch(pCur,"int16",5))
70 {
71 eOut = PLY::EDT_Short;
72 }
73 else if (TokenMatch(pCur,"ushort",6) ||
74 TokenMatch(pCur,"uint16",6))
75 {
76 eOut = PLY::EDT_UShort;
77 }
78 else if (TokenMatch(pCur,"int32",5) || TokenMatch(pCur,"int",3))
79 {
80 eOut = PLY::EDT_Int;
81 }
82 else if (TokenMatch(pCur,"uint32",6) || TokenMatch(pCur,"uint",4))
83 {
84 eOut = PLY::EDT_UInt;
85 }
86 else if (TokenMatch(pCur,"float",5) || TokenMatch(pCur,"float32",7))
87 {
88 eOut = PLY::EDT_Float;
89 }
90 else if (TokenMatch(pCur,"double64",8) || TokenMatch(pCur,"double",6) ||
91 TokenMatch(pCur,"float64",7))
92 {
93 eOut = PLY::EDT_Double;
94 }
95 if (PLY::EDT_INVALID == eOut)
96 {
97 DefaultLogger::get()->info("Found unknown data type in PLY file. This is OK");
98 }
99 *pCurOut = pCur;
100 return eOut;
101 }
103 // ------------------------------------------------------------------------------------------------
104 PLY::ESemantic PLY::Property::ParseSemantic(const char* pCur,const char** pCurOut)
105 {
106 ai_assert(NULL != pCur && NULL != pCurOut);
108 PLY::ESemantic eOut = PLY::EST_INVALID;
109 if (TokenMatch(pCur,"red",3))
110 {
111 eOut = PLY::EST_Red;
112 }
113 else if (TokenMatch(pCur,"green",5))
114 {
115 eOut = PLY::EST_Green;
116 }
117 else if (TokenMatch(pCur,"blue",4))
118 {
119 eOut = PLY::EST_Blue;
120 }
121 else if (TokenMatch(pCur,"alpha",5))
122 {
123 eOut = PLY::EST_Alpha;
124 }
125 else if (TokenMatch(pCur,"vertex_index",12) || TokenMatch(pCur,"vertex_indices",14))
126 {
127 eOut = PLY::EST_VertexIndex;
128 }
129 else if (TokenMatch(pCur,"material_index",14))
130 {
131 eOut = PLY::EST_MaterialIndex;
132 }
133 else if (TokenMatch(pCur,"ambient_red",11))
134 {
135 eOut = PLY::EST_AmbientRed;
136 }
137 else if (TokenMatch(pCur,"ambient_green",13))
138 {
139 eOut = PLY::EST_AmbientGreen;
140 }
141 else if (TokenMatch(pCur,"ambient_blue",12))
142 {
143 eOut = PLY::EST_AmbientBlue;
144 }
145 else if (TokenMatch(pCur,"ambient_alpha",13))
146 {
147 eOut = PLY::EST_AmbientAlpha;
148 }
149 else if (TokenMatch(pCur,"diffuse_red",11))
150 {
151 eOut = PLY::EST_DiffuseRed;
152 }
153 else if (TokenMatch(pCur,"diffuse_green",13))
154 {
155 eOut = PLY::EST_DiffuseGreen;
156 }
157 else if (TokenMatch(pCur,"diffuse_blue",12))
158 {
159 eOut = PLY::EST_DiffuseBlue;
160 }
161 else if (TokenMatch(pCur,"diffuse_alpha",13))
162 {
163 eOut = PLY::EST_DiffuseAlpha;
164 }
165 else if (TokenMatch(pCur,"specular_red",12))
166 {
167 eOut = PLY::EST_SpecularRed;
168 }
169 else if (TokenMatch(pCur,"specular_green",14))
170 {
171 eOut = PLY::EST_SpecularGreen;
172 }
173 else if (TokenMatch(pCur,"specular_blue",13))
174 {
175 eOut = PLY::EST_SpecularBlue;
176 }
177 else if (TokenMatch(pCur,"specular_alpha",14))
178 {
179 eOut = PLY::EST_SpecularAlpha;
180 }
181 else if (TokenMatch(pCur,"opacity",7))
182 {
183 eOut = PLY::EST_Opacity;
184 }
185 else if (TokenMatch(pCur,"specular_power",6))
186 {
187 eOut = PLY::EST_PhongPower;
188 }
189 else if (TokenMatch(pCur,"r",1))
190 {
191 eOut = PLY::EST_Red;
192 }
193 else if (TokenMatch(pCur,"g",1))
194 {
195 eOut = PLY::EST_Green;
196 }
197 else if (TokenMatch(pCur,"b",1))
198 {
199 eOut = PLY::EST_Blue;
200 }
201 // NOTE: Blender3D exports texture coordinates as s,t tuples
202 else if (TokenMatch(pCur,"u",1) || TokenMatch(pCur,"s",1) || TokenMatch(pCur,"tx",2))
203 {
204 eOut = PLY::EST_UTextureCoord;
205 }
206 else if (TokenMatch(pCur,"v",1) || TokenMatch(pCur,"t",1) || TokenMatch(pCur,"ty",2))
207 {
208 eOut = PLY::EST_VTextureCoord;
209 }
210 else if (TokenMatch(pCur,"x",1))
211 {
212 eOut = PLY::EST_XCoord;
213 }
214 else if (TokenMatch(pCur,"y",1))
215 {
216 eOut = PLY::EST_YCoord;
217 }
218 else if (TokenMatch(pCur,"z",1))
219 {
220 eOut = PLY::EST_ZCoord;
221 }
222 else if (TokenMatch(pCur,"nx",2))
223 {
224 eOut = PLY::EST_XNormal;
225 }
226 else if (TokenMatch(pCur,"ny",2))
227 {
228 eOut = PLY::EST_YNormal;
229 }
230 else if (TokenMatch(pCur,"nz",2))
231 {
232 eOut = PLY::EST_ZNormal;
233 }
234 else
235 {
236 DefaultLogger::get()->info("Found unknown property semantic in file. This is ok");
237 SkipLine(&pCur);
238 }
239 *pCurOut = pCur;
240 return eOut;
241 }
243 // ------------------------------------------------------------------------------------------------
244 bool PLY::Property::ParseProperty (const char* pCur,
245 const char** pCurOut,
246 PLY::Property* pOut)
247 {
248 ai_assert(NULL != pCur && NULL != pCurOut);
250 // Forms supported:
251 // "property float x"
252 // "property list uchar int vertex_index"
253 *pCurOut = pCur;
255 // skip leading spaces
256 if (!SkipSpaces(pCur,&pCur))return false;
258 // skip the "property" string at the beginning
259 if (!TokenMatch(pCur,"property",8))
260 {
261 // seems not to be a valid property entry
262 return false;
263 }
264 // get next word
265 if (!SkipSpaces(pCur,&pCur))return false;
266 if (TokenMatch(pCur,"list",4))
267 {
268 pOut->bIsList = true;
270 // seems to be a list.
271 if(EDT_INVALID == (pOut->eFirstType = PLY::Property::ParseDataType(pCur, &pCur)))
272 {
273 // unable to parse list size data type
274 SkipLine(pCur,&pCur);
275 *pCurOut = pCur;
276 return false;
277 }
278 if (!SkipSpaces(pCur,&pCur))return false;
279 if(EDT_INVALID == (pOut->eType = PLY::Property::ParseDataType(pCur, &pCur)))
280 {
281 // unable to parse list data type
282 SkipLine(pCur,&pCur);
283 *pCurOut = pCur;
284 return false;
285 }
286 }
287 else
288 {
289 if(EDT_INVALID == (pOut->eType = PLY::Property::ParseDataType(pCur, &pCur)))
290 {
291 // unable to parse data type. Skip the property
292 SkipLine(pCur,&pCur);
293 *pCurOut = pCur;
294 return false;
295 }
296 }
298 if (!SkipSpaces(pCur,&pCur))return false;
299 const char* szCur = pCur;
300 pOut->Semantic = PLY::Property::ParseSemantic(pCur, &pCur);
302 if (PLY::EST_INVALID == pOut->Semantic)
303 {
304 // store the name of the semantic
305 uintptr_t iDiff = (uintptr_t)pCur - (uintptr_t)szCur;
307 DefaultLogger::get()->info("Found unknown semantic in PLY file. This is OK");
308 pOut->szName = std::string(szCur,iDiff);
309 }
311 SkipSpacesAndLineEnd(pCur,&pCur);
312 *pCurOut = pCur;
313 return true;
314 }
316 // ------------------------------------------------------------------------------------------------
317 PLY::EElementSemantic PLY::Element::ParseSemantic(const char* pCur,
318 const char** pCurOut)
319 {
320 ai_assert(NULL != pCur && NULL != pCurOut);
321 PLY::EElementSemantic eOut = PLY::EEST_INVALID;
322 if (TokenMatch(pCur,"vertex",6))
323 {
324 eOut = PLY::EEST_Vertex;
325 }
326 else if (TokenMatch(pCur,"face",4))
327 {
328 eOut = PLY::EEST_Face;
329 }
330 #if 0
331 // TODO: maybe implement this?
332 else if (TokenMatch(pCur,"range_grid",10))
333 {
334 eOut = PLY::EEST_Face;
335 }
336 #endif
337 else if (TokenMatch(pCur,"tristrips",9))
338 {
339 eOut = PLY::EEST_TriStrip;
340 }
341 else if (TokenMatch(pCur,"edge",4))
342 {
343 eOut = PLY::EEST_Edge;
344 }
345 else if (TokenMatch(pCur,"material",8))
346 {
347 eOut = PLY::EEST_Material;
348 }
349 *pCurOut = pCur;
350 return eOut;
351 }
353 // ------------------------------------------------------------------------------------------------
354 bool PLY::Element::ParseElement (const char* pCur,
355 const char** pCurOut,
356 PLY::Element* pOut)
357 {
358 ai_assert(NULL != pCur && NULL != pCurOut && NULL != pOut);
360 // Example format: "element vertex 8"
361 *pCurOut = pCur;
363 // skip leading spaces
364 if (!SkipSpaces(&pCur))return false;
366 // skip the "element" string at the beginning
367 if (!TokenMatch(pCur,"element",7))
368 {
369 // seems not to be a valid property entry
370 return false;
371 }
372 // get next word
373 if (!SkipSpaces(&pCur))return false;
375 // parse the semantic of the element
376 const char* szCur = pCur;
377 pOut->eSemantic = PLY::Element::ParseSemantic(pCur,&pCur);
378 if (PLY::EEST_INVALID == pOut->eSemantic)
379 {
380 // if the exact semantic can't be determined, just store
381 // the original string identifier
382 uintptr_t iDiff = (uintptr_t)pCur - (uintptr_t)szCur;
383 pOut->szName = std::string(szCur,iDiff);
384 }
386 if (!SkipSpaces(&pCur))return false;
388 //parse the number of occurences of this element
389 pOut->NumOccur = strtoul10(pCur,&pCur);
391 // go to the next line
392 SkipSpacesAndLineEnd(pCur,&pCur);
394 // now parse all properties of the element
395 while(true)
396 {
397 // skip all comments
398 PLY::DOM::SkipComments(pCur,&pCur);
400 PLY::Property prop;
401 if(!PLY::Property::ParseProperty(pCur,&pCur,&prop))break;
402 pOut->alProperties.push_back(prop);
403 }
404 *pCurOut = pCur;
405 return true;
406 }
408 // ------------------------------------------------------------------------------------------------
409 bool PLY::DOM::SkipComments (const char* pCur,
410 const char** pCurOut)
411 {
412 ai_assert(NULL != pCur && NULL != pCurOut);
413 *pCurOut = pCur;
415 // skip spaces
416 if (!SkipSpaces(pCur,&pCur))return false;
418 if (TokenMatch(pCur,"comment",7))
419 {
420 SkipLine(pCur,&pCur);
421 SkipComments(pCur,&pCur);
422 *pCurOut = pCur;
423 return true;
424 }
425 *pCurOut = pCur;
426 return false;
427 }
429 // ------------------------------------------------------------------------------------------------
430 bool PLY::DOM::ParseHeader (const char* pCur,const char** pCurOut)
431 {
432 ai_assert(NULL != pCur && NULL != pCurOut);
433 DefaultLogger::get()->debug("PLY::DOM::ParseHeader() begin");
435 // after ply and format line
436 *pCurOut = pCur;
438 // parse all elements
439 while (true)
440 {
441 // skip all comments
442 PLY::DOM::SkipComments(pCur,&pCur);
444 PLY::Element out;
445 if(PLY::Element::ParseElement(pCur,&pCur,&out))
446 {
447 // add the element to the list of elements
448 alElements.push_back(out);
449 }
450 else if (TokenMatch(pCur,"end_header",10))
451 {
452 // we have reached the end of the header
453 break;
454 }
455 else
456 {
457 // ignore unknown header elements
458 SkipLine(&pCur);
459 }
460 }
461 SkipSpacesAndLineEnd(pCur,&pCur);
462 *pCurOut = pCur;
464 DefaultLogger::get()->debug("PLY::DOM::ParseHeader() succeeded");
465 return true;
466 }
468 // ------------------------------------------------------------------------------------------------
469 bool PLY::DOM::ParseElementInstanceLists (
470 const char* pCur,
471 const char** pCurOut)
472 {
473 ai_assert(NULL != pCur && NULL != pCurOut);
475 DefaultLogger::get()->debug("PLY::DOM::ParseElementInstanceLists() begin");
476 *pCurOut = pCur;
478 alElementData.resize(alElements.size());
480 std::vector<PLY::Element>::const_iterator i = alElements.begin();
481 std::vector<PLY::ElementInstanceList>::iterator a = alElementData.begin();
483 // parse all element instances
484 for (;i != alElements.end();++i,++a)
485 {
486 (*a).alInstances.resize((*i).NumOccur);
487 PLY::ElementInstanceList::ParseInstanceList(pCur,&pCur,&(*i),&(*a));
488 }
490 DefaultLogger::get()->debug("PLY::DOM::ParseElementInstanceLists() succeeded");
491 *pCurOut = pCur;
492 return true;
493 }
495 // ------------------------------------------------------------------------------------------------
496 bool PLY::DOM::ParseElementInstanceListsBinary (
497 const char* pCur,
498 const char** pCurOut,
499 bool p_bBE)
500 {
501 ai_assert(NULL != pCur && NULL != pCurOut);
503 DefaultLogger::get()->debug("PLY::DOM::ParseElementInstanceListsBinary() begin");
504 *pCurOut = pCur;
506 alElementData.resize(alElements.size());
508 std::vector<PLY::Element>::const_iterator i = alElements.begin();
509 std::vector<PLY::ElementInstanceList>::iterator a = alElementData.begin();
511 // parse all element instances
512 for (;i != alElements.end();++i,++a)
513 {
514 (*a).alInstances.resize((*i).NumOccur);
515 PLY::ElementInstanceList::ParseInstanceListBinary(pCur,&pCur,&(*i),&(*a),p_bBE);
516 }
518 DefaultLogger::get()->debug("PLY::DOM::ParseElementInstanceListsBinary() succeeded");
519 *pCurOut = pCur;
520 return true;
521 }
523 // ------------------------------------------------------------------------------------------------
524 bool PLY::DOM::ParseInstanceBinary (const char* pCur,DOM* p_pcOut,bool p_bBE)
525 {
526 ai_assert(NULL != pCur && NULL != p_pcOut);
528 DefaultLogger::get()->debug("PLY::DOM::ParseInstanceBinary() begin");
530 if(!p_pcOut->ParseHeader(pCur,&pCur))
531 {
532 DefaultLogger::get()->debug("PLY::DOM::ParseInstanceBinary() failure");
533 return false;
534 }
535 if(!p_pcOut->ParseElementInstanceListsBinary(pCur,&pCur,p_bBE))
536 {
537 DefaultLogger::get()->debug("PLY::DOM::ParseInstanceBinary() failure");
538 return false;
539 }
540 DefaultLogger::get()->debug("PLY::DOM::ParseInstanceBinary() succeeded");
541 return true;
542 }
544 // ------------------------------------------------------------------------------------------------
545 bool PLY::DOM::ParseInstance (const char* pCur,DOM* p_pcOut)
546 {
547 ai_assert(NULL != pCur);
548 ai_assert(NULL != p_pcOut);
550 DefaultLogger::get()->debug("PLY::DOM::ParseInstance() begin");
553 if(!p_pcOut->ParseHeader(pCur,&pCur))
554 {
555 DefaultLogger::get()->debug("PLY::DOM::ParseInstance() failure");
556 return false;
557 }
558 if(!p_pcOut->ParseElementInstanceLists(pCur,&pCur))
559 {
560 DefaultLogger::get()->debug("PLY::DOM::ParseInstance() failure");
561 return false;
562 }
563 DefaultLogger::get()->debug("PLY::DOM::ParseInstance() succeeded");
564 return true;
565 }
567 // ------------------------------------------------------------------------------------------------
568 bool PLY::ElementInstanceList::ParseInstanceList (
569 const char* pCur,
570 const char** pCurOut,
571 const PLY::Element* pcElement,
572 PLY::ElementInstanceList* p_pcOut)
573 {
574 ai_assert(NULL != pCur && NULL != pCurOut && NULL != pcElement && NULL != p_pcOut);
576 if (EEST_INVALID == pcElement->eSemantic || pcElement->alProperties.empty())
577 {
578 // if the element has an unknown semantic we can skip all lines
579 // However, there could be comments
580 for (unsigned int i = 0; i < pcElement->NumOccur;++i)
581 {
582 PLY::DOM::SkipComments(pCur,&pCur);
583 SkipLine(pCur,&pCur);
584 }
585 }
586 else
587 {
588 // be sure to have enough storage
589 for (unsigned int i = 0; i < pcElement->NumOccur;++i)
590 {
591 PLY::DOM::SkipComments(pCur,&pCur);
592 PLY::ElementInstance::ParseInstance(pCur, &pCur,pcElement,
593 &p_pcOut->alInstances[i]);
594 }
595 }
596 *pCurOut = pCur;
597 return true;
598 }
600 // ------------------------------------------------------------------------------------------------
601 bool PLY::ElementInstanceList::ParseInstanceListBinary (
602 const char* pCur,
603 const char** pCurOut,
604 const PLY::Element* pcElement,
605 PLY::ElementInstanceList* p_pcOut,
606 bool p_bBE /* = false */)
607 {
608 ai_assert(NULL != pCur && NULL != pCurOut && NULL != pcElement && NULL != p_pcOut);
610 // we can add special handling code for unknown element semantics since
611 // we can't skip it as a whole block (we don't know its exact size
612 // due to the fact that lists could be contained in the property list
613 // of the unknown element)
614 for (unsigned int i = 0; i < pcElement->NumOccur;++i)
615 {
616 PLY::ElementInstance::ParseInstanceBinary(pCur, &pCur,pcElement,
617 &p_pcOut->alInstances[i], p_bBE);
618 }
619 *pCurOut = pCur;
620 return true;
621 }
623 // ------------------------------------------------------------------------------------------------
624 bool PLY::ElementInstance::ParseInstance (
625 const char* pCur,
626 const char** pCurOut,
627 const PLY::Element* pcElement,
628 PLY::ElementInstance* p_pcOut)
629 {
630 ai_assert(NULL != pCur && NULL != pCurOut && NULL != pcElement && NULL != p_pcOut);
632 if (!SkipSpaces(pCur, &pCur))return false;
634 // allocate enough storage
635 p_pcOut->alProperties.resize(pcElement->alProperties.size());
637 std::vector<PLY::PropertyInstance>::iterator i = p_pcOut->alProperties.begin();
638 std::vector<PLY::Property>::const_iterator a = pcElement->alProperties.begin();
639 for (;i != p_pcOut->alProperties.end();++i,++a)
640 {
641 if(!(PLY::PropertyInstance::ParseInstance(pCur, &pCur,&(*a),&(*i))))
642 {
643 DefaultLogger::get()->warn("Unable to parse property instance. "
644 "Skipping this element instance");
646 // skip the rest of the instance
647 SkipLine(pCur, &pCur);
649 PLY::PropertyInstance::ValueUnion v = PLY::PropertyInstance::DefaultValue((*a).eType);
650 (*i).avList.push_back(v);
651 }
652 }
653 *pCurOut = pCur;
654 return true;
655 }
657 // ------------------------------------------------------------------------------------------------
658 bool PLY::ElementInstance::ParseInstanceBinary (
659 const char* pCur,
660 const char** pCurOut,
661 const PLY::Element* pcElement,
662 PLY::ElementInstance* p_pcOut,
663 bool p_bBE /* = false */)
664 {
665 ai_assert(NULL != pCur && NULL != pCurOut && NULL != pcElement && NULL != p_pcOut);
667 // allocate enough storage
668 p_pcOut->alProperties.resize(pcElement->alProperties.size());
670 std::vector<PLY::PropertyInstance>::iterator i = p_pcOut->alProperties.begin();
671 std::vector<PLY::Property>::const_iterator a = pcElement->alProperties.begin();
672 for (;i != p_pcOut->alProperties.end();++i,++a)
673 {
674 if(!(PLY::PropertyInstance::ParseInstanceBinary(pCur, &pCur,&(*a),&(*i),p_bBE)))
675 {
676 DefaultLogger::get()->warn("Unable to parse binary property instance. "
677 "Skipping this element instance");
679 (*i).avList.push_back(PLY::PropertyInstance::DefaultValue((*a).eType));
680 }
681 }
682 *pCurOut = pCur;
683 return true;
684 }
686 // ------------------------------------------------------------------------------------------------
687 bool PLY::PropertyInstance::ParseInstance (const char* pCur,const char** pCurOut,
688 const PLY::Property* prop, PLY::PropertyInstance* p_pcOut)
689 {
690 ai_assert(NULL != pCur && NULL != pCurOut && NULL != prop && NULL != p_pcOut);
692 *pCurOut = pCur;
694 // skip spaces at the beginning
695 if (!SkipSpaces(pCur, &pCur))return false;
697 if (prop->bIsList)
698 {
699 // parse the number of elements in the list
700 PLY::PropertyInstance::ValueUnion v;
701 PLY::PropertyInstance::ParseValue(pCur, &pCur,prop->eFirstType,&v);
703 // convert to unsigned int
704 unsigned int iNum = PLY::PropertyInstance::ConvertTo<unsigned int>(v,prop->eFirstType);
706 // parse all list elements
707 p_pcOut->avList.resize(iNum);
708 for (unsigned int i = 0; i < iNum;++i)
709 {
710 if (!SkipSpaces(pCur, &pCur))return false;
711 PLY::PropertyInstance::ParseValue(pCur, &pCur,prop->eType,&p_pcOut->avList[i]);
712 }
713 }
714 else
715 {
716 // parse the property
717 PLY::PropertyInstance::ValueUnion v;
719 PLY::PropertyInstance::ParseValue(pCur, &pCur,prop->eType,&v);
720 p_pcOut->avList.push_back(v);
721 }
722 SkipSpacesAndLineEnd(pCur, &pCur);
723 *pCurOut = pCur;
724 return true;
725 }
727 // ------------------------------------------------------------------------------------------------
728 bool PLY::PropertyInstance::ParseInstanceBinary (
729 const char* pCur,
730 const char** pCurOut,
731 const PLY::Property* prop,
732 PLY::PropertyInstance* p_pcOut,
733 bool p_bBE)
734 {
735 ai_assert(NULL != pCur && NULL != pCurOut && NULL != prop && NULL != p_pcOut);
737 if (prop->bIsList)
738 {
739 // parse the number of elements in the list
740 PLY::PropertyInstance::ValueUnion v;
741 PLY::PropertyInstance::ParseValueBinary(pCur, &pCur,prop->eFirstType,&v,p_bBE);
743 // convert to unsigned int
744 unsigned int iNum = PLY::PropertyInstance::ConvertTo<unsigned int>(v,prop->eFirstType);
746 // parse all list elements
747 p_pcOut->avList.resize(iNum);
748 for (unsigned int i = 0; i < iNum;++i){
749 PLY::PropertyInstance::ParseValueBinary(pCur, &pCur,prop->eType,&p_pcOut->avList[i],p_bBE);
750 }
751 }
752 else
753 {
754 // parse the property
755 PLY::PropertyInstance::ValueUnion v;
756 PLY::PropertyInstance::ParseValueBinary(pCur, &pCur,prop->eType,&v,p_bBE);
757 p_pcOut->avList.push_back(v);
758 }
759 *pCurOut = pCur;
760 return true;
761 }
763 // ------------------------------------------------------------------------------------------------
764 PLY::PropertyInstance::ValueUnion PLY::PropertyInstance::DefaultValue(
765 PLY::EDataType eType)
766 {
767 PLY::PropertyInstance::ValueUnion out;
769 switch (eType)
770 {
771 case EDT_Float:
772 out.fFloat = 0.f;
773 return out;
775 case EDT_Double:
776 out.fDouble = 0.;
777 return out;
779 default: ;
780 };
781 out.iUInt = 0;
782 return out;
783 }
785 // ------------------------------------------------------------------------------------------------
786 bool PLY::PropertyInstance::ParseValue(
787 const char* pCur,
788 const char** pCurOut,
789 PLY::EDataType eType,
790 PLY::PropertyInstance::ValueUnion* out)
791 {
792 ai_assert(NULL != pCur && NULL != pCurOut && NULL != out);
794 register bool ret = true;
795 *pCurOut = pCur;
796 switch (eType)
797 {
798 case EDT_UInt:
799 case EDT_UShort:
800 case EDT_UChar:
802 out->iUInt = (uint32_t)strtoul10(pCur, &pCur);
803 break;
805 case EDT_Int:
806 case EDT_Short:
807 case EDT_Char:
809 out->iInt = (int32_t)strtol10(pCur, &pCur);
810 break;
812 case EDT_Float:
814 pCur = fast_atoreal_move<float>(pCur,out->fFloat);
815 break;
817 case EDT_Double:
819 float f;
820 pCur = fast_atoreal_move<float>(pCur,f);
821 out->fDouble = (double)f;
822 break;
824 default:
825 ret = false;
826 }
827 *pCurOut = pCur;
828 return ret;
829 }
831 // ------------------------------------------------------------------------------------------------
832 bool PLY::PropertyInstance::ParseValueBinary(
833 const char* pCur,
834 const char** pCurOut,
835 PLY::EDataType eType,
836 PLY::PropertyInstance::ValueUnion* out,
837 bool p_bBE)
838 {
839 ai_assert(NULL != pCur && NULL != pCurOut && NULL != out);
841 register bool ret = true;
842 switch (eType)
843 {
844 case EDT_UInt:
845 out->iUInt = (uint32_t)*((uint32_t*)pCur);
846 pCur += 4;
848 // Swap endianess
849 if (p_bBE)ByteSwap::Swap((int32_t*)&out->iUInt);
850 break;
852 case EDT_UShort:
853 {
854 int16_t i = *((uint16_t*)pCur);
856 // Swap endianess
857 if (p_bBE)ByteSwap::Swap(&i);
858 out->iUInt = (uint32_t)i;
859 pCur += 2;
860 break;
861 }
863 case EDT_UChar:
864 {
865 out->iUInt = (uint32_t)(*((uint8_t*)pCur));
866 pCur ++;
867 break;
868 }
870 case EDT_Int:
871 out->iInt = *((int32_t*)pCur);
872 pCur += 4;
874 // Swap endianess
875 if (p_bBE)ByteSwap::Swap(&out->iInt);
876 break;
878 case EDT_Short:
879 {
880 int16_t i = *((int16_t*)pCur);
882 // Swap endianess
883 if (p_bBE)ByteSwap::Swap(&i);
884 out->iInt = (int32_t)i;
885 pCur += 2;
886 break;
887 }
889 case EDT_Char:
890 out->iInt = (int32_t)*((int8_t*)pCur);
891 pCur ++;
892 break;
894 case EDT_Float:
895 {
896 out->fFloat = *((float*)pCur);
898 // Swap endianess
899 if (p_bBE)ByteSwap::Swap((int32_t*)&out->fFloat);
900 pCur += 4;
901 break;
902 }
903 case EDT_Double:
904 {
905 out->fDouble = *((double*)pCur);
907 // Swap endianess
908 if (p_bBE)ByteSwap::Swap((int64_t*)&out->fDouble);
909 pCur += 8;
910 break;
911 }
912 default:
913 ret = false;
914 }
915 *pCurOut = pCur;
916 return ret;
917 }
919 #endif // !! ASSIMP_BUILD_NO_PLY_IMPORTER