vrshoot

view libs/assimp/ASEParser.cpp @ 0:b2f14e535253

initial commit
author John Tsiombikas <nuclear@member.fsf.org>
date Sat, 01 Feb 2014 19:58:19 +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 ASEParser.cpp
43 * @brief Implementation of the ASE parser class
44 */
46 #include "AssimpPCH.h"
47 #ifndef ASSIMP_BUILD_NO_ASE_IMPORTER
49 // internal headers
50 #include "TextureTransform.h"
51 #include "ASELoader.h"
52 #include "MaterialSystem.h"
53 #include "fast_atof.h"
55 using namespace Assimp;
56 using namespace Assimp::ASE;
59 // ------------------------------------------------------------------------------------------------
60 // Begin an ASE parsing function
62 #define AI_ASE_PARSER_INIT() \
63 int iDepth = 0;
65 // ------------------------------------------------------------------------------------------------
66 // Handle a "top-level" section in the file. EOF is no error in this case.
68 #define AI_ASE_HANDLE_TOP_LEVEL_SECTION() \
69 else if ('{' == *filePtr)iDepth++; \
70 else if ('}' == *filePtr) \
71 { \
72 if (0 == --iDepth) \
73 { \
74 ++filePtr; \
75 SkipToNextToken(); \
76 return; \
77 } \
78 } \
79 else if ('\0' == *filePtr) \
80 { \
81 return; \
82 } \
83 if(IsLineEnd(*filePtr) && !bLastWasEndLine) \
84 { \
85 ++iLineNumber; \
86 bLastWasEndLine = true; \
87 } else bLastWasEndLine = false; \
88 ++filePtr;
90 // ------------------------------------------------------------------------------------------------
91 // Handle a nested section in the file. EOF is an error in this case
92 // @param level "Depth" of the section
93 // @param msg Full name of the section (including the asterisk)
95 #define AI_ASE_HANDLE_SECTION(level, msg) \
96 if ('{' == *filePtr)iDepth++; \
97 else if ('}' == *filePtr) \
98 { \
99 if (0 == --iDepth) \
100 { \
101 ++filePtr; \
102 SkipToNextToken(); \
103 return; \
104 } \
105 } \
106 else if ('\0' == *filePtr) \
107 { \
108 LogError("Encountered unexpected EOL while parsing a " msg \
109 " chunk (Level " level ")"); \
110 } \
111 if(IsLineEnd(*filePtr) && !bLastWasEndLine) \
112 { \
113 ++iLineNumber; \
114 bLastWasEndLine = true; \
115 } else bLastWasEndLine = false; \
116 ++filePtr;
118 // ------------------------------------------------------------------------------------------------
119 Parser::Parser (const char* szFile, unsigned int fileFormatDefault)
120 {
121 ai_assert(NULL != szFile);
122 filePtr = szFile;
123 iFileFormat = fileFormatDefault;
125 // make sure that the color values are invalid
126 m_clrBackground.r = get_qnan();
127 m_clrAmbient.r = get_qnan();
129 // setup some default values
130 iLineNumber = 0;
131 iFirstFrame = 0;
132 iLastFrame = 0;
133 iFrameSpeed = 30; // use 30 as default value for this property
134 iTicksPerFrame = 1; // use 1 as default value for this property
135 bLastWasEndLine = false; // need to handle \r\n seqs due to binary file mapping
136 }
138 // ------------------------------------------------------------------------------------------------
139 void Parser::LogWarning(const char* szWarn)
140 {
141 ai_assert(NULL != szWarn);
143 char szTemp[1024];
144 #if _MSC_VER >= 1400
145 sprintf_s(szTemp,"Line %i: %s",iLineNumber,szWarn);
146 #else
147 snprintf(szTemp,1024,"Line %i: %s",iLineNumber,szWarn);
148 #endif
150 // output the warning to the logger ...
151 DefaultLogger::get()->warn(szTemp);
152 }
154 // ------------------------------------------------------------------------------------------------
155 void Parser::LogInfo(const char* szWarn)
156 {
157 ai_assert(NULL != szWarn);
159 char szTemp[1024];
160 #if _MSC_VER >= 1400
161 sprintf_s(szTemp,"Line %i: %s",iLineNumber,szWarn);
162 #else
163 snprintf(szTemp,1024,"Line %i: %s",iLineNumber,szWarn);
164 #endif
166 // output the information to the logger ...
167 DefaultLogger::get()->info(szTemp);
168 }
170 // ------------------------------------------------------------------------------------------------
171 void Parser::LogError(const char* szWarn)
172 {
173 ai_assert(NULL != szWarn);
175 char szTemp[1024];
176 #if _MSC_VER >= 1400
177 sprintf_s(szTemp,"Line %i: %s",iLineNumber,szWarn);
178 #else
179 snprintf(szTemp,1024,"Line %i: %s",iLineNumber,szWarn);
180 #endif
182 // throw an exception
183 throw DeadlyImportError(szTemp);
184 }
186 // ------------------------------------------------------------------------------------------------
187 bool Parser::SkipToNextToken()
188 {
189 while (true)
190 {
191 char me = *filePtr;
193 // increase the line number counter if necessary
194 if (IsLineEnd(me) && !bLastWasEndLine)
195 {
196 ++iLineNumber;
197 bLastWasEndLine = true;
198 }
199 else bLastWasEndLine = false;
200 if ('*' == me || '}' == me || '{' == me)return true;
201 if ('\0' == me)return false;
203 ++filePtr;
204 }
205 }
207 // ------------------------------------------------------------------------------------------------
208 bool Parser::SkipSection()
209 {
210 // must handle subsections ...
211 int iCnt = 0;
212 while (true)
213 {
214 if ('}' == *filePtr)
215 {
216 --iCnt;
217 if (0 == iCnt)
218 {
219 // go to the next valid token ...
220 ++filePtr;
221 SkipToNextToken();
222 return true;
223 }
224 }
225 else if ('{' == *filePtr)
226 {
227 ++iCnt;
228 }
229 else if ('\0' == *filePtr)
230 {
231 LogWarning("Unable to parse block: Unexpected EOF, closing bracket \'}\' was expected [#1]");
232 return false;
233 }
234 else if(IsLineEnd(*filePtr))++iLineNumber;
235 ++filePtr;
236 }
237 }
239 // ------------------------------------------------------------------------------------------------
240 void Parser::Parse()
241 {
242 AI_ASE_PARSER_INIT();
243 while (true)
244 {
245 if ('*' == *filePtr)
246 {
247 ++filePtr;
249 // Version should be 200. Validate this ...
250 if (TokenMatch(filePtr,"3DSMAX_ASCIIEXPORT",18))
251 {
252 unsigned int fmt;
253 ParseLV4MeshLong(fmt);
255 if (fmt > 200)
256 {
257 LogWarning("Unknown file format version: *3DSMAX_ASCIIEXPORT should \
258 be <= 200");
259 }
260 // *************************************************************
261 // - fmt will be 0 if we're unable to read the version number
262 // there are some faulty files without a version number ...
263 // in this case we'll guess the exact file format by looking
264 // at the file extension (ASE, ASK, ASC)
265 // *************************************************************
267 if (fmt)iFileFormat = fmt;
268 continue;
269 }
270 // main scene information
271 if (TokenMatch(filePtr,"SCENE",5))
272 {
273 ParseLV1SceneBlock();
274 continue;
275 }
276 // "group" - no implementation yet, in facte
277 // we're just ignoring them for the moment
278 if (TokenMatch(filePtr,"GROUP",5))
279 {
280 Parse();
281 continue;
282 }
283 // material list
284 if (TokenMatch(filePtr,"MATERIAL_LIST",13))
285 {
286 ParseLV1MaterialListBlock();
287 continue;
288 }
289 // geometric object (mesh)
290 if (TokenMatch(filePtr,"GEOMOBJECT",10))
292 {
293 m_vMeshes.push_back(Mesh());
294 ParseLV1ObjectBlock(m_vMeshes.back());
295 continue;
296 }
297 // helper object = dummy in the hierarchy
298 if (TokenMatch(filePtr,"HELPEROBJECT",12))
300 {
301 m_vDummies.push_back(Dummy());
302 ParseLV1ObjectBlock(m_vDummies.back());
303 continue;
304 }
305 // light object
306 if (TokenMatch(filePtr,"LIGHTOBJECT",11))
308 {
309 m_vLights.push_back(Light());
310 ParseLV1ObjectBlock(m_vLights.back());
311 continue;
312 }
313 // camera object
314 if (TokenMatch(filePtr,"CAMERAOBJECT",12))
315 {
316 m_vCameras.push_back(Camera());
317 ParseLV1ObjectBlock(m_vCameras.back());
318 continue;
319 }
320 // comment - print it on the console
321 if (TokenMatch(filePtr,"COMMENT",7))
322 {
323 std::string out = "<unknown>";
324 ParseString(out,"*COMMENT");
325 LogInfo(("Comment: " + out).c_str());
326 continue;
327 }
328 // ASC bone weights
329 if (AI_ASE_IS_OLD_FILE_FORMAT() && TokenMatch(filePtr,"MESH_SOFTSKINVERTS",18))
330 {
331 ParseLV1SoftSkinBlock();
332 }
333 }
334 AI_ASE_HANDLE_TOP_LEVEL_SECTION();
335 }
336 return;
337 }
339 // ------------------------------------------------------------------------------------------------
340 void Parser::ParseLV1SoftSkinBlock()
341 {
342 // TODO: fix line counting here
344 // **************************************************************
345 // The soft skin block is formatted differently. There are no
346 // nested sections supported and the single elements aren't
347 // marked by keywords starting with an asterisk.
349 /**
350 FORMAT BEGIN
352 *MESH_SOFTSKINVERTS {
353 <nodename>
354 <number of vertices>
356 [for <number of vertices> times:]
357 <number of weights> [for <number of weights> times:] <bone name> <weight>
358 }
360 FORMAT END
361 */
362 // **************************************************************
363 while (true)
364 {
365 if (*filePtr == '}' ) {++filePtr;return;}
366 else if (*filePtr == '\0') return;
367 else if (*filePtr == '{' ) ++filePtr;
369 else // if (!IsSpace(*filePtr) && !IsLineEnd(*filePtr))
370 {
371 ASE::Mesh* curMesh = NULL;
372 unsigned int numVerts = 0;
374 const char* sz = filePtr;
375 while (!IsSpaceOrNewLine(*filePtr))++filePtr;
377 const unsigned int diff = (unsigned int)(filePtr-sz);
378 if (diff)
379 {
380 std::string name = std::string(sz,diff);
381 for (std::vector<ASE::Mesh>::iterator it = m_vMeshes.begin();
382 it != m_vMeshes.end(); ++it)
383 {
384 if ((*it).mName == name)
385 {
386 curMesh = & (*it);
387 break;
388 }
389 }
390 if (!curMesh)
391 {
392 LogWarning("Encountered unknown mesh in *MESH_SOFTSKINVERTS section");
394 // Skip the mesh data - until we find a new mesh
395 // or the end of the *MESH_SOFTSKINVERTS section
396 while (true)
397 {
398 SkipSpacesAndLineEnd(&filePtr);
399 if (*filePtr == '}')
400 {++filePtr;return;}
401 else if (!IsNumeric(*filePtr))
402 break;
404 SkipLine(&filePtr);
405 }
406 }
407 else
408 {
409 SkipSpacesAndLineEnd(&filePtr);
410 ParseLV4MeshLong(numVerts);
412 // Reserve enough storage
413 curMesh->mBoneVertices.reserve(numVerts);
415 for (unsigned int i = 0; i < numVerts;++i)
416 {
417 SkipSpacesAndLineEnd(&filePtr);
418 unsigned int numWeights;
419 ParseLV4MeshLong(numWeights);
421 curMesh->mBoneVertices.push_back(ASE::BoneVertex());
422 ASE::BoneVertex& vert = curMesh->mBoneVertices.back();
424 // Reserve enough storage
425 vert.mBoneWeights.reserve(numWeights);
427 for (unsigned int w = 0; w < numWeights;++w)
428 {
429 std::string bone;
430 ParseString(bone,"*MESH_SOFTSKINVERTS.Bone");
432 // Find the bone in the mesh's list
433 std::pair<int,float> me;
434 me.first = -1;
436 for (unsigned int n = 0; n < curMesh->mBones.size();++n)
437 {
438 if (curMesh->mBones[n].mName == bone)
439 {
440 me.first = n;
441 break;
442 }
443 }
444 if (-1 == me.first)
445 {
446 // We don't have this bone yet, so add it to the list
447 me.first = (int)curMesh->mBones.size();
448 curMesh->mBones.push_back(ASE::Bone(bone));
449 }
450 ParseLV4MeshFloat( me.second );
452 // Add the new bone weight to list
453 vert.mBoneWeights.push_back(me);
454 }
455 }
456 }
457 }
458 }
459 ++filePtr;
460 SkipSpacesAndLineEnd(&filePtr);
461 }
462 }
464 // ------------------------------------------------------------------------------------------------
465 void Parser::ParseLV1SceneBlock()
466 {
467 AI_ASE_PARSER_INIT();
468 while (true)
469 {
470 if ('*' == *filePtr)
471 {
472 ++filePtr;
473 if (TokenMatch(filePtr,"SCENE_BACKGROUND_STATIC",23))
475 {
476 // parse a color triple and assume it is really the bg color
477 ParseLV4MeshFloatTriple( &m_clrBackground.r );
478 continue;
479 }
480 if (TokenMatch(filePtr,"SCENE_AMBIENT_STATIC",20))
482 {
483 // parse a color triple and assume it is really the bg color
484 ParseLV4MeshFloatTriple( &m_clrAmbient.r );
485 continue;
486 }
487 if (TokenMatch(filePtr,"SCENE_FIRSTFRAME",16))
488 {
489 ParseLV4MeshLong(iFirstFrame);
490 continue;
491 }
492 if (TokenMatch(filePtr,"SCENE_LASTFRAME",15))
493 {
494 ParseLV4MeshLong(iLastFrame);
495 continue;
496 }
497 if (TokenMatch(filePtr,"SCENE_FRAMESPEED",16))
498 {
499 ParseLV4MeshLong(iFrameSpeed);
500 continue;
501 }
502 if (TokenMatch(filePtr,"SCENE_TICKSPERFRAME",19))
503 {
504 ParseLV4MeshLong(iTicksPerFrame);
505 continue;
506 }
507 }
508 AI_ASE_HANDLE_TOP_LEVEL_SECTION();
509 }
510 }
512 // ------------------------------------------------------------------------------------------------
513 void Parser::ParseLV1MaterialListBlock()
514 {
515 AI_ASE_PARSER_INIT();
517 unsigned int iMaterialCount = 0;
518 unsigned int iOldMaterialCount = (unsigned int)m_vMaterials.size();
519 while (true)
520 {
521 if ('*' == *filePtr)
522 {
523 ++filePtr;
524 if (TokenMatch(filePtr,"MATERIAL_COUNT",14))
525 {
526 ParseLV4MeshLong(iMaterialCount);
528 // now allocate enough storage to hold all materials
529 m_vMaterials.resize(iOldMaterialCount+iMaterialCount);
530 continue;
531 }
532 if (TokenMatch(filePtr,"MATERIAL",8))
533 {
534 unsigned int iIndex = 0;
535 ParseLV4MeshLong(iIndex);
537 if (iIndex >= iMaterialCount)
538 {
539 LogWarning("Out of range: material index is too large");
540 iIndex = iMaterialCount-1;
541 }
543 // get a reference to the material
544 Material& sMat = m_vMaterials[iIndex+iOldMaterialCount];
545 // parse the material block
546 ParseLV2MaterialBlock(sMat);
547 continue;
548 }
549 }
550 AI_ASE_HANDLE_TOP_LEVEL_SECTION();
551 }
552 }
554 // ------------------------------------------------------------------------------------------------
555 void Parser::ParseLV2MaterialBlock(ASE::Material& mat)
556 {
557 AI_ASE_PARSER_INIT();
559 unsigned int iNumSubMaterials = 0;
560 while (true)
561 {
562 if ('*' == *filePtr)
563 {
564 ++filePtr;
565 if (TokenMatch(filePtr,"MATERIAL_NAME",13))
566 {
567 if (!ParseString(mat.mName,"*MATERIAL_NAME"))
568 SkipToNextToken();
569 continue;
570 }
571 // ambient material color
572 if (TokenMatch(filePtr,"MATERIAL_AMBIENT",16))
573 {
574 ParseLV4MeshFloatTriple(&mat.mAmbient.r);
575 continue;
576 }
577 // diffuse material color
578 if (TokenMatch(filePtr,"MATERIAL_DIFFUSE",16) )
579 {
580 ParseLV4MeshFloatTriple(&mat.mDiffuse.r);
581 continue;
582 }
583 // specular material color
584 if (TokenMatch(filePtr,"MATERIAL_SPECULAR",17))
585 {
586 ParseLV4MeshFloatTriple(&mat.mSpecular.r);
587 continue;
588 }
589 // material shading type
590 if (TokenMatch(filePtr,"MATERIAL_SHADING",16))
591 {
592 if (TokenMatch(filePtr,"Blinn",5))
593 {
594 mat.mShading = Discreet3DS::Blinn;
595 }
596 else if (TokenMatch(filePtr,"Phong",5))
597 {
598 mat.mShading = Discreet3DS::Phong;
599 }
600 else if (TokenMatch(filePtr,"Flat",4))
601 {
602 mat.mShading = Discreet3DS::Flat;
603 }
604 else if (TokenMatch(filePtr,"Wire",4))
605 {
606 mat.mShading = Discreet3DS::Wire;
607 }
608 else
609 {
610 // assume gouraud shading
611 mat.mShading = Discreet3DS::Gouraud;
612 SkipToNextToken();
613 }
614 continue;
615 }
616 // material transparency
617 if (TokenMatch(filePtr,"MATERIAL_TRANSPARENCY",21))
618 {
619 ParseLV4MeshFloat(mat.mTransparency);
620 mat.mTransparency = 1.0f - mat.mTransparency;continue;
621 }
622 // material self illumination
623 if (TokenMatch(filePtr,"MATERIAL_SELFILLUM",18))
624 {
625 float f = 0.0f;
626 ParseLV4MeshFloat(f);
628 mat.mEmissive.r = f;
629 mat.mEmissive.g = f;
630 mat.mEmissive.b = f;
631 continue;
632 }
633 // material shininess
634 if (TokenMatch(filePtr,"MATERIAL_SHINE",14) )
635 {
636 ParseLV4MeshFloat(mat.mSpecularExponent);
637 mat.mSpecularExponent *= 15;
638 continue;
639 }
640 // two-sided material
641 if (TokenMatch(filePtr,"MATERIAL_TWOSIDED",17) )
642 {
643 mat.mTwoSided = true;
644 continue;
645 }
646 // material shininess strength
647 if (TokenMatch(filePtr,"MATERIAL_SHINESTRENGTH",22))
648 {
649 ParseLV4MeshFloat(mat.mShininessStrength);
650 continue;
651 }
652 // diffuse color map
653 if (TokenMatch(filePtr,"MAP_DIFFUSE",11))
654 {
655 // parse the texture block
656 ParseLV3MapBlock(mat.sTexDiffuse);
657 continue;
658 }
659 // ambient color map
660 if (TokenMatch(filePtr,"MAP_AMBIENT",11))
661 {
662 // parse the texture block
663 ParseLV3MapBlock(mat.sTexAmbient);
664 continue;
665 }
666 // specular color map
667 if (TokenMatch(filePtr,"MAP_SPECULAR",12))
668 {
669 // parse the texture block
670 ParseLV3MapBlock(mat.sTexSpecular);
671 continue;
672 }
673 // opacity map
674 if (TokenMatch(filePtr,"MAP_OPACITY",11))
675 {
676 // parse the texture block
677 ParseLV3MapBlock(mat.sTexOpacity);
678 continue;
679 }
680 // emissive map
681 if (TokenMatch(filePtr,"MAP_SELFILLUM",13))
682 {
683 // parse the texture block
684 ParseLV3MapBlock(mat.sTexEmissive);
685 continue;
686 }
687 // bump map
688 if (TokenMatch(filePtr,"MAP_BUMP",8))
689 {
690 // parse the texture block
691 ParseLV3MapBlock(mat.sTexBump);
692 }
693 // specular/shininess map
694 if (TokenMatch(filePtr,"MAP_SHINESTRENGTH",17))
695 {
696 // parse the texture block
697 ParseLV3MapBlock(mat.sTexShininess);
698 continue;
699 }
700 // number of submaterials
701 if (TokenMatch(filePtr,"NUMSUBMTLS",10))
702 {
703 ParseLV4MeshLong(iNumSubMaterials);
705 // allocate enough storage
706 mat.avSubMaterials.resize(iNumSubMaterials);
707 }
708 // submaterial chunks
709 if (TokenMatch(filePtr,"SUBMATERIAL",11))
710 {
712 unsigned int iIndex = 0;
713 ParseLV4MeshLong(iIndex);
715 if (iIndex >= iNumSubMaterials)
716 {
717 LogWarning("Out of range: submaterial index is too large");
718 iIndex = iNumSubMaterials-1;
719 }
721 // get a reference to the material
722 Material& sMat = mat.avSubMaterials[iIndex];
724 // parse the material block
725 ParseLV2MaterialBlock(sMat);
726 continue;
727 }
728 }
729 AI_ASE_HANDLE_SECTION("2","*MATERIAL");
730 }
731 }
733 // ------------------------------------------------------------------------------------------------
734 void Parser::ParseLV3MapBlock(Texture& map)
735 {
736 AI_ASE_PARSER_INIT();
738 // ***********************************************************
739 // *BITMAP should not be there if *MAP_CLASS is not BITMAP,
740 // but we need to expect that case ... if the path is
741 // empty the texture won't be used later.
742 // ***********************************************************
743 bool parsePath = true;
744 while (true)
745 {
746 if ('*' == *filePtr)
747 {
748 ++filePtr;
749 // type of map
750 if (TokenMatch(filePtr,"MAP_CLASS" ,9))
751 {
752 std::string temp;
753 if(!ParseString(temp,"*MAP_CLASS"))
754 SkipToNextToken();
755 if (temp != "Bitmap" && temp != "Normal Bump")
756 {
757 DefaultLogger::get()->warn("ASE: Skipping unknown map type: " + temp);
758 parsePath = false;
759 }
760 continue;
761 }
762 // path to the texture
763 if (parsePath && TokenMatch(filePtr,"BITMAP" ,6))
764 {
765 if(!ParseString(map.mMapName,"*BITMAP"))
766 SkipToNextToken();
768 if (map.mMapName == "None")
769 {
770 // Files with 'None' as map name are produced by
771 // an Maja to ASE exporter which name I forgot ..
772 DefaultLogger::get()->warn("ASE: Skipping invalid map entry");
773 map.mMapName = "";
774 }
776 continue;
777 }
778 // offset on the u axis
779 if (TokenMatch(filePtr,"UVW_U_OFFSET" ,12))
780 {
781 ParseLV4MeshFloat(map.mOffsetU);
782 continue;
783 }
784 // offset on the v axis
785 if (TokenMatch(filePtr,"UVW_V_OFFSET" ,12))
786 {
787 ParseLV4MeshFloat(map.mOffsetV);
788 continue;
789 }
790 // tiling on the u axis
791 if (TokenMatch(filePtr,"UVW_U_TILING" ,12))
792 {
793 ParseLV4MeshFloat(map.mScaleU);
794 continue;
795 }
796 // tiling on the v axis
797 if (TokenMatch(filePtr,"UVW_V_TILING" ,12))
798 {
799 ParseLV4MeshFloat(map.mScaleV);
800 continue;
801 }
802 // rotation around the z-axis
803 if (TokenMatch(filePtr,"UVW_ANGLE" ,9))
804 {
805 ParseLV4MeshFloat(map.mRotation);
806 continue;
807 }
808 // map blending factor
809 if (TokenMatch(filePtr,"MAP_AMOUNT" ,10))
810 {
811 ParseLV4MeshFloat(map.mTextureBlend);
812 continue;
813 }
814 }
815 AI_ASE_HANDLE_SECTION("3","*MAP_XXXXXX");
816 }
817 return;
818 }
820 // ------------------------------------------------------------------------------------------------
821 bool Parser::ParseString(std::string& out,const char* szName)
822 {
823 char szBuffer[1024];
824 if (!SkipSpaces(&filePtr))
825 {
827 sprintf(szBuffer,"Unable to parse %s block: Unexpected EOL",szName);
828 LogWarning(szBuffer);
829 return false;
830 }
831 // there must be '"'
832 if ('\"' != *filePtr)
833 {
835 sprintf(szBuffer,"Unable to parse %s block: Strings are expected "
836 "to be enclosed in double quotation marks",szName);
837 LogWarning(szBuffer);
838 return false;
839 }
840 ++filePtr;
841 const char* sz = filePtr;
842 while (true)
843 {
844 if ('\"' == *sz)break;
845 else if ('\0' == *sz)
846 {
847 sprintf(szBuffer,"Unable to parse %s block: Strings are expected to "
848 "be enclosed in double quotation marks but EOF was reached before "
849 "a closing quotation mark was encountered",szName);
850 LogWarning(szBuffer);
851 return false;
852 }
853 sz++;
854 }
855 out = std::string(filePtr,(uintptr_t)sz-(uintptr_t)filePtr);
856 filePtr = sz+1;
857 return true;
858 }
860 // ------------------------------------------------------------------------------------------------
861 void Parser::ParseLV1ObjectBlock(ASE::BaseNode& node)
862 {
863 AI_ASE_PARSER_INIT();
864 while (true)
865 {
866 if ('*' == *filePtr)
867 {
868 ++filePtr;
870 // first process common tokens such as node name and transform
871 // name of the mesh/node
872 if (TokenMatch(filePtr,"NODE_NAME" ,9))
873 {
874 if(!ParseString(node.mName,"*NODE_NAME"))
875 SkipToNextToken();
876 continue;
877 }
878 // name of the parent of the node
879 if (TokenMatch(filePtr,"NODE_PARENT" ,11) )
880 {
881 if(!ParseString(node.mParent,"*NODE_PARENT"))
882 SkipToNextToken();
883 continue;
884 }
885 // transformation matrix of the node
886 if (TokenMatch(filePtr,"NODE_TM" ,7))
887 {
888 ParseLV2NodeTransformBlock(node);
889 continue;
890 }
891 // animation data of the node
892 if (TokenMatch(filePtr,"TM_ANIMATION" ,12))
893 {
894 ParseLV2AnimationBlock(node);
895 continue;
896 }
898 if (node.mType == BaseNode::Light)
899 {
900 // light settings
901 if (TokenMatch(filePtr,"LIGHT_SETTINGS" ,14))
902 {
903 ParseLV2LightSettingsBlock((ASE::Light&)node);
904 continue;
905 }
906 // type of the light source
907 if (TokenMatch(filePtr,"LIGHT_TYPE" ,10))
908 {
909 if (!ASSIMP_strincmp("omni",filePtr,4))
910 {
911 ((ASE::Light&)node).mLightType = ASE::Light::OMNI;
912 }
913 else if (!ASSIMP_strincmp("target",filePtr,6))
914 {
915 ((ASE::Light&)node).mLightType = ASE::Light::TARGET;
916 }
917 else if (!ASSIMP_strincmp("free",filePtr,4))
918 {
919 ((ASE::Light&)node).mLightType = ASE::Light::FREE;
920 }
921 else if (!ASSIMP_strincmp("directional",filePtr,11))
922 {
923 ((ASE::Light&)node).mLightType = ASE::Light::DIRECTIONAL;
924 }
925 else
926 {
927 LogWarning("Unknown kind of light source");
928 }
929 continue;
930 }
931 }
932 else if (node.mType == BaseNode::Camera)
933 {
934 // Camera settings
935 if (TokenMatch(filePtr,"CAMERA_SETTINGS" ,15))
936 {
937 ParseLV2CameraSettingsBlock((ASE::Camera&)node);
938 continue;
939 }
940 else if (TokenMatch(filePtr,"CAMERA_TYPE" ,11))
941 {
942 if (!ASSIMP_strincmp("target",filePtr,6))
943 {
944 ((ASE::Camera&)node).mCameraType = ASE::Camera::TARGET;
945 }
946 else if (!ASSIMP_strincmp("free",filePtr,4))
947 {
948 ((ASE::Camera&)node).mCameraType = ASE::Camera::FREE;
949 }
950 else
951 {
952 LogWarning("Unknown kind of camera");
953 }
954 continue;
955 }
956 }
957 else if (node.mType == BaseNode::Mesh)
958 {
959 // mesh data
960 // FIX: Older files use MESH_SOFTSKIN
961 if (TokenMatch(filePtr,"MESH" ,4) ||
962 TokenMatch(filePtr,"MESH_SOFTSKIN",13))
963 {
964 ParseLV2MeshBlock((ASE::Mesh&)node);
965 continue;
966 }
967 // mesh material index
968 if (TokenMatch(filePtr,"MATERIAL_REF" ,12))
969 {
970 ParseLV4MeshLong(((ASE::Mesh&)node).iMaterialIndex);
971 continue;
972 }
973 }
974 }
975 AI_ASE_HANDLE_TOP_LEVEL_SECTION();
976 }
977 return;
978 }
980 // ------------------------------------------------------------------------------------------------
981 void Parser::ParseLV2CameraSettingsBlock(ASE::Camera& camera)
982 {
983 AI_ASE_PARSER_INIT();
984 while (true)
985 {
986 if ('*' == *filePtr)
987 {
988 ++filePtr;
989 if (TokenMatch(filePtr,"CAMERA_NEAR" ,11))
990 {
991 ParseLV4MeshFloat(camera.mNear);
992 continue;
993 }
994 if (TokenMatch(filePtr,"CAMERA_FAR" ,10))
995 {
996 ParseLV4MeshFloat(camera.mFar);
997 continue;
998 }
999 if (TokenMatch(filePtr,"CAMERA_FOV" ,10))
1001 ParseLV4MeshFloat(camera.mFOV);
1002 continue;
1005 AI_ASE_HANDLE_SECTION("2","CAMERA_SETTINGS");
1007 return;
1010 // ------------------------------------------------------------------------------------------------
1011 void Parser::ParseLV2LightSettingsBlock(ASE::Light& light)
1013 AI_ASE_PARSER_INIT();
1014 while (true)
1016 if ('*' == *filePtr)
1018 ++filePtr;
1019 if (TokenMatch(filePtr,"LIGHT_COLOR" ,11))
1021 ParseLV4MeshFloatTriple(&light.mColor.r);
1022 continue;
1024 if (TokenMatch(filePtr,"LIGHT_INTENS" ,12))
1026 ParseLV4MeshFloat(light.mIntensity);
1027 continue;
1029 if (TokenMatch(filePtr,"LIGHT_HOTSPOT" ,13))
1031 ParseLV4MeshFloat(light.mAngle);
1032 continue;
1034 if (TokenMatch(filePtr,"LIGHT_FALLOFF" ,13))
1036 ParseLV4MeshFloat(light.mFalloff);
1037 continue;
1040 AI_ASE_HANDLE_SECTION("2","LIGHT_SETTINGS");
1042 return;
1045 // ------------------------------------------------------------------------------------------------
1046 void Parser::ParseLV2AnimationBlock(ASE::BaseNode& mesh)
1048 AI_ASE_PARSER_INIT();
1050 ASE::Animation* anim = &mesh.mAnim;
1051 while (true)
1053 if ('*' == *filePtr)
1055 ++filePtr;
1056 if (TokenMatch(filePtr,"NODE_NAME" ,9))
1058 std::string temp;
1059 if(!ParseString(temp,"*NODE_NAME"))
1060 SkipToNextToken();
1062 // If the name of the node contains .target it
1063 // represents an animated camera or spot light
1064 // target.
1065 if (std::string::npos != temp.find(".Target"))
1067 if ((mesh.mType != BaseNode::Camera || ((ASE::Camera&)mesh).mCameraType != ASE::Camera::TARGET) &&
1068 ( mesh.mType != BaseNode::Light || ((ASE::Light&)mesh).mLightType != ASE::Light::TARGET))
1071 DefaultLogger::get()->error("ASE: Found target animation channel "
1072 "but the node is neither a camera nor a spot light");
1073 anim = NULL;
1075 else anim = &mesh.mTargetAnim;
1077 continue;
1080 // position keyframes
1081 if (TokenMatch(filePtr,"CONTROL_POS_TRACK" ,17) ||
1082 TokenMatch(filePtr,"CONTROL_POS_BEZIER" ,18) ||
1083 TokenMatch(filePtr,"CONTROL_POS_TCB" ,15))
1085 if (!anim)SkipSection();
1086 else ParseLV3PosAnimationBlock(*anim);
1087 continue;
1089 // scaling keyframes
1090 if (TokenMatch(filePtr,"CONTROL_SCALE_TRACK" ,19) ||
1091 TokenMatch(filePtr,"CONTROL_SCALE_BEZIER" ,20) ||
1092 TokenMatch(filePtr,"CONTROL_SCALE_TCB" ,17))
1094 if (!anim || anim == &mesh.mTargetAnim)
1096 // Target animation channels may have no rotation channels
1097 DefaultLogger::get()->error("ASE: Ignoring scaling channel in target animation");
1098 SkipSection();
1100 else ParseLV3ScaleAnimationBlock(*anim);
1101 continue;
1103 // rotation keyframes
1104 if (TokenMatch(filePtr,"CONTROL_ROT_TRACK" ,17) ||
1105 TokenMatch(filePtr,"CONTROL_ROT_BEZIER" ,18) ||
1106 TokenMatch(filePtr,"CONTROL_ROT_TCB" ,15))
1108 if (!anim || anim == &mesh.mTargetAnim)
1110 // Target animation channels may have no rotation channels
1111 DefaultLogger::get()->error("ASE: Ignoring rotation channel in target animation");
1112 SkipSection();
1114 else ParseLV3RotAnimationBlock(*anim);
1115 continue;
1118 AI_ASE_HANDLE_SECTION("2","TM_ANIMATION");
1121 // ------------------------------------------------------------------------------------------------
1122 void Parser::ParseLV3ScaleAnimationBlock(ASE::Animation& anim)
1124 AI_ASE_PARSER_INIT();
1125 unsigned int iIndex;
1127 while (true)
1129 if ('*' == *filePtr)
1131 ++filePtr;
1133 bool b = false;
1135 // For the moment we're just reading the three floats -
1136 // we ignore the ádditional information for bezier's and TCBs
1138 // simple scaling keyframe
1139 if (TokenMatch(filePtr,"CONTROL_SCALE_SAMPLE" ,20))
1141 b = true;
1142 anim.mScalingType = ASE::Animation::TRACK;
1145 // Bezier scaling keyframe
1146 if (TokenMatch(filePtr,"CONTROL_BEZIER_SCALE_KEY" ,24))
1148 b = true;
1149 anim.mScalingType = ASE::Animation::BEZIER;
1151 // TCB scaling keyframe
1152 if (TokenMatch(filePtr,"CONTROL_TCB_SCALE_KEY" ,21))
1154 b = true;
1155 anim.mScalingType = ASE::Animation::TCB;
1157 if (b)
1159 anim.akeyScaling.push_back(aiVectorKey());
1160 aiVectorKey& key = anim.akeyScaling.back();
1161 ParseLV4MeshFloatTriple(&key.mValue.x,iIndex);
1162 key.mTime = (double)iIndex;
1165 AI_ASE_HANDLE_SECTION("3","*CONTROL_POS_TRACK");
1168 // ------------------------------------------------------------------------------------------------
1169 void Parser::ParseLV3PosAnimationBlock(ASE::Animation& anim)
1171 AI_ASE_PARSER_INIT();
1172 unsigned int iIndex;
1173 while (true)
1175 if ('*' == *filePtr)
1177 ++filePtr;
1179 bool b = false;
1181 // For the moment we're just reading the three floats -
1182 // we ignore the ádditional information for bezier's and TCBs
1184 // simple scaling keyframe
1185 if (TokenMatch(filePtr,"CONTROL_POS_SAMPLE" ,18))
1187 b = true;
1188 anim.mPositionType = ASE::Animation::TRACK;
1191 // Bezier scaling keyframe
1192 if (TokenMatch(filePtr,"CONTROL_BEZIER_POS_KEY" ,22))
1194 b = true;
1195 anim.mPositionType = ASE::Animation::BEZIER;
1197 // TCB scaling keyframe
1198 if (TokenMatch(filePtr,"CONTROL_TCB_POS_KEY" ,19))
1200 b = true;
1201 anim.mPositionType = ASE::Animation::TCB;
1203 if (b)
1205 anim.akeyPositions.push_back(aiVectorKey());
1206 aiVectorKey& key = anim.akeyPositions.back();
1207 ParseLV4MeshFloatTriple(&key.mValue.x,iIndex);
1208 key.mTime = (double)iIndex;
1211 AI_ASE_HANDLE_SECTION("3","*CONTROL_POS_TRACK");
1214 // ------------------------------------------------------------------------------------------------
1215 void Parser::ParseLV3RotAnimationBlock(ASE::Animation& anim)
1217 AI_ASE_PARSER_INIT();
1218 unsigned int iIndex;
1219 while (true)
1221 if ('*' == *filePtr)
1223 ++filePtr;
1225 bool b = false;
1227 // For the moment we're just reading the floats -
1228 // we ignore the ádditional information for bezier's and TCBs
1230 // simple scaling keyframe
1231 if (TokenMatch(filePtr,"CONTROL_ROT_SAMPLE" ,18))
1233 b = true;
1234 anim.mRotationType = ASE::Animation::TRACK;
1237 // Bezier scaling keyframe
1238 if (TokenMatch(filePtr,"CONTROL_BEZIER_ROT_KEY" ,22))
1240 b = true;
1241 anim.mRotationType = ASE::Animation::BEZIER;
1243 // TCB scaling keyframe
1244 if (TokenMatch(filePtr,"CONTROL_TCB_ROT_KEY" ,19))
1246 b = true;
1247 anim.mRotationType = ASE::Animation::TCB;
1249 if (b)
1251 anim.akeyRotations.push_back(aiQuatKey());
1252 aiQuatKey& key = anim.akeyRotations.back();
1253 aiVector3D v;float f;
1254 ParseLV4MeshFloatTriple(&v.x,iIndex);
1255 ParseLV4MeshFloat(f);
1256 key.mTime = (double)iIndex;
1257 key.mValue = aiQuaternion(v,f);
1260 AI_ASE_HANDLE_SECTION("3","*CONTROL_ROT_TRACK");
1263 // ------------------------------------------------------------------------------------------------
1264 void Parser::ParseLV2NodeTransformBlock(ASE::BaseNode& mesh)
1266 AI_ASE_PARSER_INIT();
1267 int mode = 0;
1268 while (true)
1270 if ('*' == *filePtr)
1272 ++filePtr;
1273 // name of the node
1274 if (TokenMatch(filePtr,"NODE_NAME" ,9))
1276 std::string temp;
1277 if(!ParseString(temp,"*NODE_NAME"))
1278 SkipToNextToken();
1280 std::string::size_type s;
1281 if (temp == mesh.mName)
1283 mode = 1;
1285 else if (std::string::npos != (s = temp.find(".Target")) &&
1286 mesh.mName == temp.substr(0,s))
1288 // This should be either a target light or a target camera
1289 if ( (mesh.mType == BaseNode::Light && ((ASE::Light&)mesh) .mLightType == ASE::Light::TARGET) ||
1290 (mesh.mType == BaseNode::Camera && ((ASE::Camera&)mesh).mCameraType == ASE::Camera::TARGET))
1292 mode = 2;
1294 else DefaultLogger::get()->error("ASE: Ignoring target transform, "
1295 "this is no spot light or target camera");
1297 else
1299 DefaultLogger::get()->error("ASE: Unknown node transformation: " + temp);
1300 // mode = 0
1302 continue;
1304 if (mode)
1306 // fourth row of the transformation matrix - and also the
1307 // only information here that is interesting for targets
1308 if (TokenMatch(filePtr,"TM_ROW3" ,7))
1310 ParseLV4MeshFloatTriple((mode == 1 ? mesh.mTransform[3] : &mesh.mTargetPosition.x));
1311 continue;
1313 if (mode == 1)
1315 // first row of the transformation matrix
1316 if (TokenMatch(filePtr,"TM_ROW0" ,7))
1318 ParseLV4MeshFloatTriple(mesh.mTransform[0]);
1319 continue;
1321 // second row of the transformation matrix
1322 if (TokenMatch(filePtr,"TM_ROW1" ,7))
1324 ParseLV4MeshFloatTriple(mesh.mTransform[1]);
1325 continue;
1327 // third row of the transformation matrix
1328 if (TokenMatch(filePtr,"TM_ROW2" ,7))
1330 ParseLV4MeshFloatTriple(mesh.mTransform[2]);
1331 continue;
1333 // inherited position axes
1334 if (TokenMatch(filePtr,"INHERIT_POS" ,11))
1336 unsigned int aiVal[3];
1337 ParseLV4MeshLongTriple(aiVal);
1339 for (unsigned int i = 0; i < 3;++i)
1340 mesh.inherit.abInheritPosition[i] = aiVal[i] != 0;
1341 continue;
1343 // inherited rotation axes
1344 if (TokenMatch(filePtr,"INHERIT_ROT" ,11))
1346 unsigned int aiVal[3];
1347 ParseLV4MeshLongTriple(aiVal);
1349 for (unsigned int i = 0; i < 3;++i)
1350 mesh.inherit.abInheritRotation[i] = aiVal[i] != 0;
1351 continue;
1353 // inherited scaling axes
1354 if (TokenMatch(filePtr,"INHERIT_SCL" ,11))
1356 unsigned int aiVal[3];
1357 ParseLV4MeshLongTriple(aiVal);
1359 for (unsigned int i = 0; i < 3;++i)
1360 mesh.inherit.abInheritScaling[i] = aiVal[i] != 0;
1361 continue;
1366 AI_ASE_HANDLE_SECTION("2","*NODE_TM");
1368 return;
1370 // ------------------------------------------------------------------------------------------------
1371 void Parser::ParseLV2MeshBlock(ASE::Mesh& mesh)
1373 AI_ASE_PARSER_INIT();
1375 unsigned int iNumVertices = 0;
1376 unsigned int iNumFaces = 0;
1377 unsigned int iNumTVertices = 0;
1378 unsigned int iNumTFaces = 0;
1379 unsigned int iNumCVertices = 0;
1380 unsigned int iNumCFaces = 0;
1381 while (true)
1383 if ('*' == *filePtr)
1385 ++filePtr;
1386 // Number of vertices in the mesh
1387 if (TokenMatch(filePtr,"MESH_NUMVERTEX" ,14))
1389 ParseLV4MeshLong(iNumVertices);
1390 continue;
1392 // Number of texture coordinates in the mesh
1393 if (TokenMatch(filePtr,"MESH_NUMTVERTEX" ,15))
1395 ParseLV4MeshLong(iNumTVertices);
1396 continue;
1398 // Number of vertex colors in the mesh
1399 if (TokenMatch(filePtr,"MESH_NUMCVERTEX" ,15))
1401 ParseLV4MeshLong(iNumCVertices);
1402 continue;
1404 // Number of regular faces in the mesh
1405 if (TokenMatch(filePtr,"MESH_NUMFACES" ,13))
1407 ParseLV4MeshLong(iNumFaces);
1408 continue;
1410 // Number of UVWed faces in the mesh
1411 if (TokenMatch(filePtr,"MESH_NUMTVFACES" ,15))
1413 ParseLV4MeshLong(iNumTFaces);
1414 continue;
1416 // Number of colored faces in the mesh
1417 if (TokenMatch(filePtr,"MESH_NUMCVFACES" ,15))
1419 ParseLV4MeshLong(iNumCFaces);
1420 continue;
1422 // mesh vertex list block
1423 if (TokenMatch(filePtr,"MESH_VERTEX_LIST" ,16))
1425 ParseLV3MeshVertexListBlock(iNumVertices,mesh);
1426 continue;
1428 // mesh face list block
1429 if (TokenMatch(filePtr,"MESH_FACE_LIST" ,14))
1431 ParseLV3MeshFaceListBlock(iNumFaces,mesh);
1432 continue;
1434 // mesh texture vertex list block
1435 if (TokenMatch(filePtr,"MESH_TVERTLIST" ,14))
1437 ParseLV3MeshTListBlock(iNumTVertices,mesh);
1438 continue;
1440 // mesh texture face block
1441 if (TokenMatch(filePtr,"MESH_TFACELIST" ,14))
1443 ParseLV3MeshTFaceListBlock(iNumTFaces,mesh);
1444 continue;
1446 // mesh color vertex list block
1447 if (TokenMatch(filePtr,"MESH_CVERTLIST" ,14))
1449 ParseLV3MeshCListBlock(iNumCVertices,mesh);
1450 continue;
1452 // mesh color face block
1453 if (TokenMatch(filePtr,"MESH_CFACELIST" ,14))
1455 ParseLV3MeshCFaceListBlock(iNumCFaces,mesh);
1456 continue;
1458 // mesh normals
1459 if (TokenMatch(filePtr,"MESH_NORMALS" ,12))
1461 ParseLV3MeshNormalListBlock(mesh);
1462 continue;
1464 // another mesh UV channel ...
1465 if (TokenMatch(filePtr,"MESH_MAPPINGCHANNEL" ,19))
1468 unsigned int iIndex = 0;
1469 ParseLV4MeshLong(iIndex);
1471 if (iIndex < 2)
1473 LogWarning("Mapping channel has an invalid index. Skipping UV channel");
1474 // skip it ...
1475 SkipSection();
1477 if (iIndex > AI_MAX_NUMBER_OF_TEXTURECOORDS)
1479 LogWarning("Too many UV channels specified. Skipping channel ..");
1480 // skip it ...
1481 SkipSection();
1483 else
1485 // parse the mapping channel
1486 ParseLV3MappingChannel(iIndex-1,mesh);
1488 continue;
1490 // mesh animation keyframe. Not supported
1491 if (TokenMatch(filePtr,"MESH_ANIMATION" ,14))
1494 LogWarning("Found *MESH_ANIMATION element in ASE/ASK file. "
1495 "Keyframe animation is not supported by Assimp, this element "
1496 "will be ignored");
1497 //SkipSection();
1498 continue;
1500 if (TokenMatch(filePtr,"MESH_WEIGHTS" ,12))
1502 ParseLV3MeshWeightsBlock(mesh);continue;
1505 AI_ASE_HANDLE_SECTION("2","*MESH");
1507 return;
1509 // ------------------------------------------------------------------------------------------------
1510 void Parser::ParseLV3MeshWeightsBlock(ASE::Mesh& mesh)
1512 AI_ASE_PARSER_INIT();
1514 unsigned int iNumVertices = 0, iNumBones = 0;
1515 while (true)
1517 if ('*' == *filePtr)
1519 ++filePtr;
1521 // Number of bone vertices ...
1522 if (TokenMatch(filePtr,"MESH_NUMVERTEX" ,14))
1524 ParseLV4MeshLong(iNumVertices);
1525 continue;
1527 // Number of bones
1528 if (TokenMatch(filePtr,"MESH_NUMBONE" ,11))
1530 ParseLV4MeshLong(iNumBones);
1531 continue;
1533 // parse the list of bones
1534 if (TokenMatch(filePtr,"MESH_BONE_LIST" ,14))
1536 ParseLV4MeshBones(iNumBones,mesh);
1537 continue;
1539 // parse the list of bones vertices
1540 if (TokenMatch(filePtr,"MESH_BONE_VERTEX_LIST" ,21) )
1542 ParseLV4MeshBonesVertices(iNumVertices,mesh);
1543 continue;
1546 AI_ASE_HANDLE_SECTION("3","*MESH_WEIGHTS");
1548 return;
1550 // ------------------------------------------------------------------------------------------------
1551 void Parser::ParseLV4MeshBones(unsigned int iNumBones,ASE::Mesh& mesh)
1553 AI_ASE_PARSER_INIT();
1554 mesh.mBones.resize(iNumBones);
1555 while (true)
1557 if ('*' == *filePtr)
1559 ++filePtr;
1561 // Mesh bone with name ...
1562 if (TokenMatch(filePtr,"MESH_BONE_NAME" ,16))
1564 // parse an index ...
1565 if(SkipSpaces(&filePtr))
1567 unsigned int iIndex = strtoul10(filePtr,&filePtr);
1568 if (iIndex >= iNumBones)
1570 LogWarning("Bone index is out of bounds");
1571 continue;
1573 if (!ParseString(mesh.mBones[iIndex].mName,"*MESH_BONE_NAME"))
1574 SkipToNextToken();
1575 continue;
1579 AI_ASE_HANDLE_SECTION("3","*MESH_BONE_LIST");
1582 // ------------------------------------------------------------------------------------------------
1583 void Parser::ParseLV4MeshBonesVertices(unsigned int iNumVertices,ASE::Mesh& mesh)
1585 AI_ASE_PARSER_INIT();
1586 mesh.mBoneVertices.resize(iNumVertices);
1587 while (true)
1589 if ('*' == *filePtr)
1591 ++filePtr;
1593 // Mesh bone vertex
1594 if (TokenMatch(filePtr,"MESH_BONE_VERTEX" ,16))
1596 // read the vertex index
1597 unsigned int iIndex = strtoul10(filePtr,&filePtr);
1598 if (iIndex >= mesh.mPositions.size())
1600 iIndex = (unsigned int)mesh.mPositions.size()-1;
1601 LogWarning("Bone vertex index is out of bounds. Using the largest valid "
1602 "bone vertex index instead");
1605 // --- ignored
1606 float afVert[3];
1607 ParseLV4MeshFloatTriple(afVert);
1609 std::pair<int,float> pairOut;
1610 while (true)
1612 // first parse the bone index ...
1613 if (!SkipSpaces(&filePtr))break;
1614 pairOut.first = strtoul10(filePtr,&filePtr);
1616 // then parse the vertex weight
1617 if (!SkipSpaces(&filePtr))break;
1618 filePtr = fast_atoreal_move<float>(filePtr,pairOut.second);
1620 // -1 marks unused entries
1621 if (-1 != pairOut.first)
1623 mesh.mBoneVertices[iIndex].mBoneWeights.push_back(pairOut);
1626 continue;
1629 AI_ASE_HANDLE_SECTION("4","*MESH_BONE_VERTEX");
1631 return;
1633 // ------------------------------------------------------------------------------------------------
1634 void Parser::ParseLV3MeshVertexListBlock(
1635 unsigned int iNumVertices, ASE::Mesh& mesh)
1637 AI_ASE_PARSER_INIT();
1639 // allocate enough storage in the array
1640 mesh.mPositions.resize(iNumVertices);
1641 while (true)
1643 if ('*' == *filePtr)
1645 ++filePtr;
1647 // Vertex entry
1648 if (TokenMatch(filePtr,"MESH_VERTEX" ,11))
1651 aiVector3D vTemp;
1652 unsigned int iIndex;
1653 ParseLV4MeshFloatTriple(&vTemp.x,iIndex);
1655 if (iIndex >= iNumVertices)
1657 LogWarning("Invalid vertex index. It will be ignored");
1659 else mesh.mPositions[iIndex] = vTemp;
1660 continue;
1663 AI_ASE_HANDLE_SECTION("3","*MESH_VERTEX_LIST");
1665 return;
1667 // ------------------------------------------------------------------------------------------------
1668 void Parser::ParseLV3MeshFaceListBlock(unsigned int iNumFaces, ASE::Mesh& mesh)
1670 AI_ASE_PARSER_INIT();
1672 // allocate enough storage in the face array
1673 mesh.mFaces.resize(iNumFaces);
1674 while (true)
1676 if ('*' == *filePtr)
1678 ++filePtr;
1680 // Face entry
1681 if (TokenMatch(filePtr,"MESH_FACE" ,9))
1684 ASE::Face mFace;
1685 ParseLV4MeshFace(mFace);
1687 if (mFace.iFace >= iNumFaces)
1689 LogWarning("Face has an invalid index. It will be ignored");
1691 else mesh.mFaces[mFace.iFace] = mFace;
1692 continue;
1695 AI_ASE_HANDLE_SECTION("3","*MESH_FACE_LIST");
1697 return;
1699 // ------------------------------------------------------------------------------------------------
1700 void Parser::ParseLV3MeshTListBlock(unsigned int iNumVertices,
1701 ASE::Mesh& mesh, unsigned int iChannel)
1703 AI_ASE_PARSER_INIT();
1705 // allocate enough storage in the array
1706 mesh.amTexCoords[iChannel].resize(iNumVertices);
1707 while (true)
1709 if ('*' == *filePtr)
1711 ++filePtr;
1713 // Vertex entry
1714 if (TokenMatch(filePtr,"MESH_TVERT" ,10))
1716 aiVector3D vTemp;
1717 unsigned int iIndex;
1718 ParseLV4MeshFloatTriple(&vTemp.x,iIndex);
1720 if (iIndex >= iNumVertices)
1722 LogWarning("Tvertex has an invalid index. It will be ignored");
1724 else mesh.amTexCoords[iChannel][iIndex] = vTemp;
1726 if (0.0f != vTemp.z)
1728 // we need 3 coordinate channels
1729 mesh.mNumUVComponents[iChannel] = 3;
1731 continue;
1734 AI_ASE_HANDLE_SECTION("3","*MESH_TVERT_LIST");
1736 return;
1738 // ------------------------------------------------------------------------------------------------
1739 void Parser::ParseLV3MeshTFaceListBlock(unsigned int iNumFaces,
1740 ASE::Mesh& mesh, unsigned int iChannel)
1742 AI_ASE_PARSER_INIT();
1743 while (true)
1745 if ('*' == *filePtr)
1747 ++filePtr;
1749 // Face entry
1750 if (TokenMatch(filePtr,"MESH_TFACE" ,10))
1752 unsigned int aiValues[3];
1753 unsigned int iIndex = 0;
1755 ParseLV4MeshLongTriple(aiValues,iIndex);
1756 if (iIndex >= iNumFaces || iIndex >= mesh.mFaces.size())
1758 LogWarning("UV-Face has an invalid index. It will be ignored");
1760 else
1762 // copy UV indices
1763 mesh.mFaces[iIndex].amUVIndices[iChannel][0] = aiValues[0];
1764 mesh.mFaces[iIndex].amUVIndices[iChannel][1] = aiValues[1];
1765 mesh.mFaces[iIndex].amUVIndices[iChannel][2] = aiValues[2];
1767 continue;
1770 AI_ASE_HANDLE_SECTION("3","*MESH_TFACE_LIST");
1772 return;
1774 // ------------------------------------------------------------------------------------------------
1775 void Parser::ParseLV3MappingChannel(unsigned int iChannel, ASE::Mesh& mesh)
1777 AI_ASE_PARSER_INIT();
1779 unsigned int iNumTVertices = 0;
1780 unsigned int iNumTFaces = 0;
1781 while (true)
1783 if ('*' == *filePtr)
1785 ++filePtr;
1787 // Number of texture coordinates in the mesh
1788 if (TokenMatch(filePtr,"MESH_NUMTVERTEX" ,15))
1790 ParseLV4MeshLong(iNumTVertices);
1791 continue;
1793 // Number of UVWed faces in the mesh
1794 if (TokenMatch(filePtr,"MESH_NUMTVFACES" ,15))
1796 ParseLV4MeshLong(iNumTFaces);
1797 continue;
1799 // mesh texture vertex list block
1800 if (TokenMatch(filePtr,"MESH_TVERTLIST" ,14))
1802 ParseLV3MeshTListBlock(iNumTVertices,mesh,iChannel);
1803 continue;
1805 // mesh texture face block
1806 if (TokenMatch(filePtr,"MESH_TFACELIST" ,14))
1808 ParseLV3MeshTFaceListBlock(iNumTFaces,mesh, iChannel);
1809 continue;
1812 AI_ASE_HANDLE_SECTION("3","*MESH_MAPPING_CHANNEL");
1814 return;
1816 // ------------------------------------------------------------------------------------------------
1817 void Parser::ParseLV3MeshCListBlock(unsigned int iNumVertices, ASE::Mesh& mesh)
1819 AI_ASE_PARSER_INIT();
1821 // allocate enough storage in the array
1822 mesh.mVertexColors.resize(iNumVertices);
1823 while (true)
1825 if ('*' == *filePtr)
1827 ++filePtr;
1829 // Vertex entry
1830 if (TokenMatch(filePtr,"MESH_VERTCOL" ,12))
1832 aiColor4D vTemp;
1833 vTemp.a = 1.0f;
1834 unsigned int iIndex;
1835 ParseLV4MeshFloatTriple(&vTemp.r,iIndex);
1837 if (iIndex >= iNumVertices)
1839 LogWarning("Vertex color has an invalid index. It will be ignored");
1841 else mesh.mVertexColors[iIndex] = vTemp;
1842 continue;
1845 AI_ASE_HANDLE_SECTION("3","*MESH_CVERTEX_LIST");
1847 return;
1849 // ------------------------------------------------------------------------------------------------
1850 void Parser::ParseLV3MeshCFaceListBlock(unsigned int iNumFaces, ASE::Mesh& mesh)
1852 AI_ASE_PARSER_INIT();
1853 while (true)
1855 if ('*' == *filePtr)
1857 ++filePtr;
1859 // Face entry
1860 if (TokenMatch(filePtr,"MESH_CFACE" ,11))
1862 unsigned int aiValues[3];
1863 unsigned int iIndex = 0;
1865 ParseLV4MeshLongTriple(aiValues,iIndex);
1866 if (iIndex >= iNumFaces || iIndex >= mesh.mFaces.size())
1868 LogWarning("UV-Face has an invalid index. It will be ignored");
1870 else
1872 // copy color indices
1873 mesh.mFaces[iIndex].mColorIndices[0] = aiValues[0];
1874 mesh.mFaces[iIndex].mColorIndices[1] = aiValues[1];
1875 mesh.mFaces[iIndex].mColorIndices[2] = aiValues[2];
1877 continue;
1880 AI_ASE_HANDLE_SECTION("3","*MESH_CFACE_LIST");
1882 return;
1884 // ------------------------------------------------------------------------------------------------
1885 void Parser::ParseLV3MeshNormalListBlock(ASE::Mesh& sMesh)
1887 AI_ASE_PARSER_INIT();
1889 // Allocate enough storage for the normals
1890 sMesh.mNormals.resize(sMesh.mFaces.size()*3,aiVector3D( 0.f, 0.f, 0.f ));
1891 unsigned int index, faceIdx = UINT_MAX;
1893 // FIXME: rewrite this and find out how to interpret the normals
1894 // correctly. This is crap.
1896 // Smooth the vertex and face normals together. The result
1897 // will be edgy then, but otherwise everything would be soft ...
1898 while (true) {
1899 if ('*' == *filePtr) {
1900 ++filePtr;
1901 if (faceIdx != UINT_MAX && TokenMatch(filePtr,"MESH_VERTEXNORMAL",17)) {
1902 aiVector3D vNormal;
1903 ParseLV4MeshFloatTriple(&vNormal.x,index);
1904 if (faceIdx >= sMesh.mFaces.size())
1905 continue;
1907 // Make sure we assign it to the correct face
1908 const ASE::Face& face = sMesh.mFaces[faceIdx];
1909 if (index == face.mIndices[0])
1910 index = 0;
1911 else if (index == face.mIndices[1])
1912 index = 1;
1913 else if (index == face.mIndices[2])
1914 index = 2;
1915 else {
1916 DefaultLogger::get()->error("ASE: Invalid vertex index in MESH_VERTEXNORMAL section");
1917 continue;
1919 // We'll renormalize later
1920 sMesh.mNormals[faceIdx*3+index] += vNormal;
1921 continue;
1923 if (TokenMatch(filePtr,"MESH_FACENORMAL",15)) {
1924 aiVector3D vNormal;
1925 ParseLV4MeshFloatTriple(&vNormal.x,faceIdx);
1927 if (faceIdx >= sMesh.mFaces.size()) {
1928 DefaultLogger::get()->error("ASE: Invalid vertex index in MESH_FACENORMAL section");
1929 continue;
1932 // We'll renormalize later
1933 sMesh.mNormals[faceIdx*3] += vNormal;
1934 sMesh.mNormals[faceIdx*3+1] += vNormal;
1935 sMesh.mNormals[faceIdx*3+2] += vNormal;
1936 continue;
1939 AI_ASE_HANDLE_SECTION("3","*MESH_NORMALS");
1941 return;
1943 // ------------------------------------------------------------------------------------------------
1944 void Parser::ParseLV4MeshFace(ASE::Face& out)
1946 // skip spaces and tabs
1947 if(!SkipSpaces(&filePtr))
1949 LogWarning("Unable to parse *MESH_FACE Element: Unexpected EOL [#1]");
1950 SkipToNextToken();
1951 return;
1954 // parse the face index
1955 out.iFace = strtoul10(filePtr,&filePtr);
1957 // next character should be ':'
1958 if(!SkipSpaces(&filePtr))
1960 // FIX: there are some ASE files which haven't got : here ....
1961 LogWarning("Unable to parse *MESH_FACE Element: Unexpected EOL. \':\' expected [#2]");
1962 SkipToNextToken();
1963 return;
1965 // FIX: There are some ASE files which haven't got ':' here
1966 if(':' == *filePtr)++filePtr;
1968 // Parse all mesh indices
1969 for (unsigned int i = 0; i < 3;++i)
1971 unsigned int iIndex = 0;
1972 if(!SkipSpaces(&filePtr))
1974 LogWarning("Unable to parse *MESH_FACE Element: Unexpected EOL");
1975 SkipToNextToken();
1976 return;
1978 switch (*filePtr)
1980 case 'A':
1981 case 'a':
1982 break;
1983 case 'B':
1984 case 'b':
1985 iIndex = 1;
1986 break;
1987 case 'C':
1988 case 'c':
1989 iIndex = 2;
1990 break;
1991 default:
1992 LogWarning("Unable to parse *MESH_FACE Element: Unexpected EOL. "
1993 "A,B or C expected [#3]");
1994 SkipToNextToken();
1995 return;
1996 };
1997 ++filePtr;
1999 // next character should be ':'
2000 if(!SkipSpaces(&filePtr) || ':' != *filePtr)
2002 LogWarning("Unable to parse *MESH_FACE Element: "
2003 "Unexpected EOL. \':\' expected [#2]");
2004 SkipToNextToken();
2005 return;
2008 ++filePtr;
2009 if(!SkipSpaces(&filePtr))
2011 LogWarning("Unable to parse *MESH_FACE Element: Unexpected EOL. "
2012 "Vertex index ecpected [#4]");
2013 SkipToNextToken();
2014 return;
2016 out.mIndices[iIndex] = strtoul10(filePtr,&filePtr);
2019 // now we need to skip the AB, BC, CA blocks.
2020 while (true)
2022 if ('*' == *filePtr)break;
2023 if (IsLineEnd(*filePtr))
2025 //iLineNumber++;
2026 return;
2028 filePtr++;
2031 // parse the smoothing group of the face
2032 if (TokenMatch(filePtr,"*MESH_SMOOTHING",15))
2034 if(!SkipSpaces(&filePtr))
2036 LogWarning("Unable to parse *MESH_SMOOTHING Element: "
2037 "Unexpected EOL. Smoothing group(s) expected [#5]");
2038 SkipToNextToken();
2039 return;
2042 // Parse smoothing groups until we don't anymore see commas
2043 // FIX: There needn't always be a value, sad but true
2044 while (true)
2046 if (*filePtr < '9' && *filePtr >= '0')
2048 out.iSmoothGroup |= (1 << strtoul10(filePtr,&filePtr));
2050 SkipSpaces(&filePtr);
2051 if (',' != *filePtr)
2053 break;
2055 ++filePtr;
2056 SkipSpaces(&filePtr);
2060 // *MESH_MTLID is optional, too
2061 while (true)
2063 if ('*' == *filePtr)break;
2064 if (IsLineEnd(*filePtr))
2066 return;
2068 filePtr++;
2071 if (TokenMatch(filePtr,"*MESH_MTLID",11))
2073 if(!SkipSpaces(&filePtr))
2075 LogWarning("Unable to parse *MESH_MTLID Element: Unexpected EOL. "
2076 "Material index expected [#6]");
2077 SkipToNextToken();
2078 return;
2080 out.iMaterial = strtoul10(filePtr,&filePtr);
2082 return;
2084 // ------------------------------------------------------------------------------------------------
2085 void Parser::ParseLV4MeshLongTriple(unsigned int* apOut)
2087 ai_assert(NULL != apOut);
2089 for (unsigned int i = 0; i < 3;++i)
2090 ParseLV4MeshLong(apOut[i]);
2092 // ------------------------------------------------------------------------------------------------
2093 void Parser::ParseLV4MeshLongTriple(unsigned int* apOut, unsigned int& rIndexOut)
2095 ai_assert(NULL != apOut);
2097 // parse the index
2098 ParseLV4MeshLong(rIndexOut);
2100 // parse the three others
2101 ParseLV4MeshLongTriple(apOut);
2103 // ------------------------------------------------------------------------------------------------
2104 void Parser::ParseLV4MeshFloatTriple(float* apOut, unsigned int& rIndexOut)
2106 ai_assert(NULL != apOut);
2108 // parse the index
2109 ParseLV4MeshLong(rIndexOut);
2111 // parse the three others
2112 ParseLV4MeshFloatTriple(apOut);
2114 // ------------------------------------------------------------------------------------------------
2115 void Parser::ParseLV4MeshFloatTriple(float* apOut)
2117 ai_assert(NULL != apOut);
2119 for (unsigned int i = 0; i < 3;++i)
2120 ParseLV4MeshFloat(apOut[i]);
2122 // ------------------------------------------------------------------------------------------------
2123 void Parser::ParseLV4MeshFloat(float& fOut)
2125 // skip spaces and tabs
2126 if(!SkipSpaces(&filePtr))
2128 // LOG
2129 LogWarning("Unable to parse float: unexpected EOL [#1]");
2130 fOut = 0.0f;
2131 ++iLineNumber;
2132 return;
2134 // parse the first float
2135 filePtr = fast_atoreal_move<float>(filePtr,fOut);
2137 // ------------------------------------------------------------------------------------------------
2138 void Parser::ParseLV4MeshLong(unsigned int& iOut)
2140 // Skip spaces and tabs
2141 if(!SkipSpaces(&filePtr))
2143 // LOG
2144 LogWarning("Unable to parse long: unexpected EOL [#1]");
2145 iOut = 0;
2146 ++iLineNumber;
2147 return;
2149 // parse the value
2150 iOut = strtoul10(filePtr,&filePtr);
2153 #endif // !! ASSIMP_BUILD_NO_BASE_IMPORTER