ASEParser.cpp 50 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964
  1. /*
  2. ---------------------------------------------------------------------------
  3. Open Asset Import Library (ASSIMP)
  4. ---------------------------------------------------------------------------
  5. Copyright (c) 2006-2008, ASSIMP Development Team
  6. All rights reserved.
  7. Redistribution and use of this software in source and binary forms,
  8. with or without modification, are permitted provided that the following
  9. conditions are met:
  10. * Redistributions of source code must retain the above
  11. copyright notice, this list of conditions and the
  12. following disclaimer.
  13. * Redistributions in binary form must reproduce the above
  14. copyright notice, this list of conditions and the
  15. following disclaimer in the documentation and/or other
  16. materials provided with the distribution.
  17. * Neither the name of the ASSIMP team, nor the names of its
  18. contributors may be used to endorse or promote products
  19. derived from this software without specific prior
  20. written permission of the ASSIMP Development Team.
  21. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  22. "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  23. LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
  24. A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
  25. OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
  26. SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
  27. LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
  28. DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
  29. THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  30. (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
  31. OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  32. ---------------------------------------------------------------------------
  33. */
  34. /** @file Implementation of the ASE parser class */
  35. #include "AssimpPCH.h"
  36. // internal headers
  37. #include "TextureTransform.h"
  38. #include "ASELoader.h"
  39. #include "MaterialSystem.h"
  40. #include "fast_atof.h"
  41. using namespace Assimp;
  42. using namespace Assimp::ASE;
  43. #if (defined BLUBB)
  44. # undef BLUBB
  45. #endif
  46. #define BLUBB(_message_) \
  47. {LogError(_message_);return;}
  48. // ------------------------------------------------------------------------------------------------
  49. #define AI_ASE_HANDLE_TOP_LEVEL_SECTION(iDepth) \
  50. else if ('{' == *m_szFile)iDepth++; \
  51. else if ('}' == *m_szFile) \
  52. { \
  53. if (0 == --iDepth) \
  54. { \
  55. ++m_szFile; \
  56. SkipToNextToken(); \
  57. return; \
  58. } \
  59. } \
  60. else if ('\0' == *m_szFile) \
  61. { \
  62. return; \
  63. } \
  64. if(IsLineEnd(*m_szFile) && !bLastWasEndLine) \
  65. { \
  66. ++iLineNumber; \
  67. bLastWasEndLine = true; \
  68. } else bLastWasEndLine = false; \
  69. ++m_szFile;
  70. // ------------------------------------------------------------------------------------------------
  71. #define AI_ASE_HANDLE_SECTION(iDepth, level, msg) \
  72. if ('{' == *m_szFile)iDepth++; \
  73. else if ('}' == *m_szFile) \
  74. { \
  75. if (0 == --iDepth) \
  76. { \
  77. ++m_szFile; \
  78. SkipToNextToken(); \
  79. return; \
  80. } \
  81. } \
  82. else if ('\0' == *m_szFile) \
  83. { \
  84. LogError("Encountered unexpected EOL while parsing a " msg \
  85. " chunk (Level " level ")"); \
  86. } \
  87. if(IsLineEnd(*m_szFile) && !bLastWasEndLine) \
  88. { \
  89. ++iLineNumber; \
  90. bLastWasEndLine = true; \
  91. } else bLastWasEndLine = false; \
  92. ++m_szFile;
  93. #ifdef _MSC_VER
  94. # define sprintf sprintf_s
  95. #endif
  96. // ------------------------------------------------------------------------------------------------
  97. Parser::Parser (const char* szFile)
  98. {
  99. ai_assert(NULL != szFile);
  100. m_szFile = szFile;
  101. // makre sure that the color values are invalid
  102. m_clrBackground.r = std::numeric_limits<float>::quiet_NaN();
  103. m_clrAmbient.r = std::numeric_limits<float>::quiet_NaN();
  104. iLineNumber = 0;
  105. iFirstFrame = 0;
  106. iLastFrame = 0;
  107. iFrameSpeed = 30; // use 30 as default value for this property
  108. iTicksPerFrame = 1; // use 1 as default value for this property
  109. bLastWasEndLine = false; // need to handle \r\n seqs due to binary file mapping
  110. }
  111. // ------------------------------------------------------------------------------------------------
  112. void Parser::LogWarning(const char* szWarn)
  113. {
  114. ai_assert(NULL != szWarn);
  115. char szTemp[1024];
  116. #if _MSC_VER >= 1400
  117. sprintf_s(szTemp,"Line %i: %s",iLineNumber,szWarn);
  118. #else
  119. snprintf(szTemp,1024,"Line %i: %s",iLineNumber,szWarn);
  120. #endif
  121. // output the warning to the logger ...
  122. DefaultLogger::get()->warn(szTemp);
  123. }
  124. // ------------------------------------------------------------------------------------------------
  125. void Parser::LogInfo(const char* szWarn)
  126. {
  127. ai_assert(NULL != szWarn);
  128. char szTemp[1024];
  129. #if _MSC_VER >= 1400
  130. sprintf_s(szTemp,"Line %i: %s",iLineNumber,szWarn);
  131. #else
  132. snprintf(szTemp,1024,"Line %i: %s",iLineNumber,szWarn);
  133. #endif
  134. // output the information to the logger ...
  135. DefaultLogger::get()->info(szTemp);
  136. }
  137. // ------------------------------------------------------------------------------------------------
  138. void Parser::LogError(const char* szWarn)
  139. {
  140. ai_assert(NULL != szWarn);
  141. char szTemp[1024];
  142. #if _MSC_VER >= 1400
  143. sprintf_s(szTemp,"Line %i: %s",iLineNumber,szWarn);
  144. #else
  145. snprintf(szTemp,1024,"Line %i: %s",iLineNumber,szWarn);
  146. #endif
  147. // throw an exception
  148. throw new ImportErrorException(szTemp);
  149. }
  150. // ------------------------------------------------------------------------------------------------
  151. bool Parser::SkipToNextToken()
  152. {
  153. while (true)
  154. {
  155. char me = *m_szFile;
  156. // increase the line number counter if necessary
  157. if (IsLineEnd(me) && !bLastWasEndLine)
  158. {
  159. ++iLineNumber;
  160. bLastWasEndLine = true;
  161. }
  162. else bLastWasEndLine = false;
  163. if ('*' == me || '}' == me || '{' == me)return true;
  164. if ('\0' == me)return false;
  165. ++m_szFile;
  166. }
  167. }
  168. // ------------------------------------------------------------------------------------------------
  169. bool Parser::SkipSection()
  170. {
  171. // must handle subsections ...
  172. int iCnt = 0;
  173. while (true)
  174. {
  175. if ('}' == *m_szFile)
  176. {
  177. --iCnt;
  178. if (0 == iCnt)
  179. {
  180. // go to the next valid token ...
  181. ++m_szFile;
  182. SkipToNextToken();
  183. return true;
  184. }
  185. }
  186. else if ('{' == *m_szFile)
  187. {
  188. ++iCnt;
  189. }
  190. else if ('\0' == *m_szFile)
  191. {
  192. LogWarning("Unable to parse block: Unexpected EOF, closing bracket \'}\' was expected [#1]");
  193. return false;
  194. }
  195. else if(IsLineEnd(*m_szFile))++iLineNumber;
  196. ++m_szFile;
  197. }
  198. }
  199. // ------------------------------------------------------------------------------------------------
  200. void Parser::Parse()
  201. {
  202. int iDepth = 0;
  203. while (true)
  204. {
  205. if ('*' == *m_szFile)
  206. {
  207. ++m_szFile;
  208. // version should be 200. Validate this ...
  209. if (TokenMatch(m_szFile,"3DSMAX_ASCIIEXPORT",18))
  210. {
  211. unsigned int iVersion;
  212. ParseLV4MeshLong(iVersion);
  213. if (iVersion > 200)
  214. {
  215. LogWarning("Unknown file format version: *3DSMAX_ASCIIEXPORT should \
  216. be <=200. Continuing happily ...");
  217. }
  218. continue;
  219. }
  220. // main scene information
  221. if (TokenMatch(m_szFile,"SCENE",5))
  222. {
  223. ParseLV1SceneBlock();
  224. continue;
  225. }
  226. // "group" - no implementation yet, in facte
  227. // we're just ignoring them for the moment
  228. if (TokenMatch(m_szFile,"GROUP",5))
  229. {
  230. Parse();
  231. continue;
  232. }
  233. // material list
  234. if (TokenMatch(m_szFile,"MATERIAL_LIST",13))
  235. {
  236. ParseLV1MaterialListBlock();
  237. continue;
  238. }
  239. // geometric object (mesh)
  240. if (TokenMatch(m_szFile,"GEOMOBJECT",10))
  241. {
  242. m_vMeshes.push_back(Mesh());
  243. ParseLV1ObjectBlock(m_vMeshes.back());
  244. continue;
  245. }
  246. // helper object = dummy in the hierarchy
  247. if (TokenMatch(m_szFile,"HELPEROBJECT",12))
  248. {
  249. m_vDummies.push_back(Dummy());
  250. ParseLV1ObjectBlock(m_vDummies.back());
  251. continue;
  252. }
  253. // light object
  254. if (TokenMatch(m_szFile,"LIGHTOBJECT",11))
  255. {
  256. m_vLights.push_back(Light());
  257. ParseLV1ObjectBlock(m_vLights.back());
  258. continue;
  259. }
  260. // camera object
  261. if (TokenMatch(m_szFile,"CAMERAOBJECT",12))
  262. {
  263. m_vCameras.push_back(Camera());
  264. ParseLV1ObjectBlock(m_vCameras.back());
  265. continue;
  266. }
  267. // comment - print it on the console
  268. if (TokenMatch(m_szFile,"COMMENT",7))
  269. {
  270. std::string out = "<unknown>";
  271. ParseString(out,"*COMMENT");
  272. LogInfo(("Comment: " + out).c_str());
  273. continue;
  274. }
  275. }
  276. AI_ASE_HANDLE_TOP_LEVEL_SECTION(iDepth);
  277. }
  278. return;
  279. }
  280. // ------------------------------------------------------------------------------------------------
  281. void Parser::ParseLV1SceneBlock()
  282. {
  283. int iDepth = 0;
  284. while (true)
  285. {
  286. if ('*' == *m_szFile)
  287. {
  288. ++m_szFile;
  289. if (TokenMatch(m_szFile,"SCENE_BACKGROUND_STATIC",23))
  290. {
  291. // parse a color triple and assume it is really the bg color
  292. ParseLV4MeshFloatTriple( &m_clrBackground.r );
  293. continue;
  294. }
  295. if (TokenMatch(m_szFile,"SCENE_AMBIENT_STATIC",20))
  296. {
  297. // parse a color triple and assume it is really the bg color
  298. ParseLV4MeshFloatTriple( &m_clrAmbient.r );
  299. continue;
  300. }
  301. if (TokenMatch(m_szFile,"SCENE_FIRSTFRAME",16))
  302. {
  303. ParseLV4MeshLong(iFirstFrame);
  304. continue;
  305. }
  306. if (TokenMatch(m_szFile,"SCENE_LASTFRAME",15))
  307. {
  308. ParseLV4MeshLong(iLastFrame);
  309. continue;
  310. }
  311. if (TokenMatch(m_szFile,"SCENE_FRAMESPEED",16))
  312. {
  313. ParseLV4MeshLong(iFrameSpeed);
  314. continue;
  315. }
  316. if (TokenMatch(m_szFile,"SCENE_TICKSPERFRAME",19))
  317. {
  318. ParseLV4MeshLong(iTicksPerFrame);
  319. continue;
  320. }
  321. }
  322. AI_ASE_HANDLE_TOP_LEVEL_SECTION(iDepth);
  323. }
  324. }
  325. // ------------------------------------------------------------------------------------------------
  326. void Parser::ParseLV1MaterialListBlock()
  327. {
  328. int iDepth = 0;
  329. unsigned int iMaterialCount = 0;
  330. unsigned int iOldMaterialCount = (unsigned int)m_vMaterials.size();
  331. while (true)
  332. {
  333. if ('*' == *m_szFile)
  334. {
  335. ++m_szFile;
  336. if (TokenMatch(m_szFile,"MATERIAL_COUNT",14))
  337. {
  338. ParseLV4MeshLong(iMaterialCount);
  339. // now allocate enough storage to hold all materials
  340. m_vMaterials.resize(iOldMaterialCount+iMaterialCount);
  341. continue;
  342. }
  343. if (TokenMatch(m_szFile,"MATERIAL",8))
  344. {
  345. unsigned int iIndex = 0;
  346. ParseLV4MeshLong(iIndex);
  347. if (iIndex >= iMaterialCount)
  348. {
  349. LogWarning("Out of range: material index is too large");
  350. iIndex = iMaterialCount-1;
  351. }
  352. // get a reference to the material
  353. Material& sMat = m_vMaterials[iIndex+iOldMaterialCount];
  354. // parse the material block
  355. ParseLV2MaterialBlock(sMat);
  356. continue;
  357. }
  358. }
  359. AI_ASE_HANDLE_TOP_LEVEL_SECTION(iDepth);
  360. }
  361. }
  362. // ------------------------------------------------------------------------------------------------
  363. void Parser::ParseLV2MaterialBlock(ASE::Material& mat)
  364. {
  365. int iDepth = 0;
  366. unsigned int iNumSubMaterials = 0;
  367. while (true)
  368. {
  369. if ('*' == *m_szFile)
  370. {
  371. ++m_szFile;
  372. if (TokenMatch(m_szFile,"MATERIAL_NAME",13))
  373. {
  374. if (!ParseString(mat.mName,"*MATERIAL_NAME"))
  375. SkipToNextToken();
  376. continue;
  377. }
  378. // ambient material color
  379. if (TokenMatch(m_szFile,"MATERIAL_AMBIENT",16))
  380. {
  381. ParseLV4MeshFloatTriple(&mat.mAmbient.r);
  382. continue;
  383. }
  384. // diffuse material color
  385. if (TokenMatch(m_szFile,"MATERIAL_DIFFUSE",16) )
  386. {
  387. ParseLV4MeshFloatTriple(&mat.mDiffuse.r);
  388. continue;
  389. }
  390. // specular material color
  391. if (TokenMatch(m_szFile,"MATERIAL_SPECULAR",17))
  392. {
  393. ParseLV4MeshFloatTriple(&mat.mSpecular.r);
  394. continue;
  395. }
  396. // material shading type
  397. if (TokenMatch(m_szFile,"MATERIAL_SHADING",16))
  398. {
  399. if (TokenMatch(m_szFile,"Blinn",5))
  400. {
  401. mat.mShading = Discreet3DS::Blinn;
  402. }
  403. else if (TokenMatch(m_szFile,"Phong",5))
  404. {
  405. mat.mShading = Discreet3DS::Phong;
  406. }
  407. else if (TokenMatch(m_szFile,"Flat",4))
  408. {
  409. mat.mShading = Discreet3DS::Flat;
  410. }
  411. else if (TokenMatch(m_szFile,"Wire",4))
  412. {
  413. mat.mShading = Discreet3DS::Wire;
  414. }
  415. else
  416. {
  417. // assume gouraud shading
  418. mat.mShading = Discreet3DS::Gouraud;
  419. SkipToNextToken();
  420. }
  421. continue;
  422. }
  423. // material transparency
  424. if (TokenMatch(m_szFile,"MATERIAL_TRANSPARENCY",21))
  425. {
  426. ParseLV4MeshFloat(mat.mTransparency);
  427. mat.mTransparency = 1.0f - mat.mTransparency;continue;
  428. }
  429. // material self illumination
  430. if (TokenMatch(m_szFile,"MATERIAL_SELFILLUM",18))
  431. {
  432. float f = 0.0f;
  433. ParseLV4MeshFloat(f);
  434. mat.mEmissive.r = f;
  435. mat.mEmissive.g = f;
  436. mat.mEmissive.b = f;
  437. continue;
  438. }
  439. // material shininess
  440. if (TokenMatch(m_szFile,"MATERIAL_SHINE",14) )
  441. {
  442. ParseLV4MeshFloat(mat.mSpecularExponent);
  443. mat.mSpecularExponent *= 15;
  444. continue;
  445. }
  446. // material shininess strength
  447. if (TokenMatch(m_szFile,"MATERIAL_SHINESTRENGTH",22))
  448. {
  449. ParseLV4MeshFloat(mat.mShininessStrength);
  450. continue;
  451. }
  452. // diffuse color map
  453. if (TokenMatch(m_szFile,"MAP_DIFFUSE",11))
  454. {
  455. // parse the texture block
  456. ParseLV3MapBlock(mat.sTexDiffuse);
  457. continue;
  458. }
  459. // ambient color map
  460. if (TokenMatch(m_szFile,"MAP_AMBIENT",11))
  461. {
  462. // parse the texture block
  463. ParseLV3MapBlock(mat.sTexAmbient);
  464. continue;
  465. }
  466. // specular color map
  467. if (TokenMatch(m_szFile,"MAP_SPECULAR",12))
  468. {
  469. // parse the texture block
  470. ParseLV3MapBlock(mat.sTexSpecular);
  471. continue;
  472. }
  473. // opacity map
  474. if (TokenMatch(m_szFile,"MAP_OPACITY",11))
  475. {
  476. // parse the texture block
  477. ParseLV3MapBlock(mat.sTexOpacity);
  478. continue;
  479. }
  480. // emissive map
  481. if (TokenMatch(m_szFile,"MAP_SELFILLUM",13))
  482. {
  483. // parse the texture block
  484. ParseLV3MapBlock(mat.sTexEmissive);
  485. continue;
  486. }
  487. // bump map
  488. if (TokenMatch(m_szFile,"MAP_BUMP",8))
  489. {
  490. // parse the texture block
  491. ParseLV3MapBlock(mat.sTexBump);
  492. }
  493. // specular/shininess map
  494. if (TokenMatch(m_szFile,"MAP_SHINESTRENGTH",17))
  495. {
  496. // parse the texture block
  497. ParseLV3MapBlock(mat.sTexShininess);
  498. continue;
  499. }
  500. // number of submaterials
  501. if (TokenMatch(m_szFile,"NUMSUBMTLS",10))
  502. {
  503. ParseLV4MeshLong(iNumSubMaterials);
  504. // allocate enough storage
  505. mat.avSubMaterials.resize(iNumSubMaterials);
  506. }
  507. // submaterial chunks
  508. if (TokenMatch(m_szFile,"SUBMATERIAL",11))
  509. {
  510. unsigned int iIndex = 0;
  511. ParseLV4MeshLong(iIndex);
  512. if (iIndex >= iNumSubMaterials)
  513. {
  514. LogWarning("Out of range: submaterial index is too large");
  515. iIndex = iNumSubMaterials-1;
  516. }
  517. // get a reference to the material
  518. Material& sMat = mat.avSubMaterials[iIndex];
  519. // parse the material block
  520. ParseLV2MaterialBlock(sMat);
  521. continue;
  522. }
  523. }
  524. AI_ASE_HANDLE_SECTION(iDepth,"2","*MATERIAL");
  525. }
  526. }
  527. // ------------------------------------------------------------------------------------------------
  528. void Parser::ParseLV3MapBlock(Texture& map)
  529. {
  530. int iDepth = 0;
  531. // *BITMAP should not be there if *MAP_CLASS is not BITMAP,
  532. // but we need to expect that case ... if the path is
  533. // empty the texture won't be used later.
  534. bool parsePath = true;
  535. while (true)
  536. {
  537. if ('*' == *m_szFile)
  538. {
  539. ++m_szFile;
  540. // type of map
  541. if (TokenMatch(m_szFile,"MAP_CLASS" ,9))
  542. {
  543. std::string temp;
  544. if(!ParseString(temp,"*MAP_CLASS"))
  545. SkipToNextToken();
  546. if (temp != "Bitmap")
  547. {
  548. DefaultLogger::get()->warn("ASE: Skipping unknown map type: " + temp);
  549. parsePath = false;
  550. }
  551. continue;
  552. }
  553. // path to the texture
  554. if (parsePath && TokenMatch(m_szFile,"BITMAP" ,6))
  555. {
  556. if(!ParseString(map.mMapName,"*BITMAP"))
  557. SkipToNextToken();
  558. if (map.mMapName == "None")
  559. {
  560. // Files with 'None' as map name are produced by
  561. // an Maja to ASE exporter which name I forgot ..
  562. DefaultLogger::get()->warn("ASE: Skipping invalid map entry");
  563. map.mMapName = "";
  564. }
  565. continue;
  566. }
  567. // offset on the u axis
  568. if (TokenMatch(m_szFile,"UVW_U_OFFSET" ,12))
  569. {
  570. ParseLV4MeshFloat(map.mOffsetU);
  571. continue;
  572. }
  573. // offset on the v axis
  574. if (TokenMatch(m_szFile,"UVW_V_OFFSET" ,12))
  575. {
  576. ParseLV4MeshFloat(map.mOffsetV);
  577. continue;
  578. }
  579. // tiling on the u axis
  580. if (TokenMatch(m_szFile,"UVW_U_TILING" ,12))
  581. {
  582. ParseLV4MeshFloat(map.mScaleU);
  583. continue;
  584. }
  585. // tiling on the v axis
  586. if (TokenMatch(m_szFile,"UVW_V_TILING" ,12))
  587. {
  588. ParseLV4MeshFloat(map.mScaleV);
  589. continue;
  590. }
  591. // rotation around the z-axis
  592. if (TokenMatch(m_szFile,"UVW_ANGLE" ,9))
  593. {
  594. ParseLV4MeshFloat(map.mRotation);
  595. continue;
  596. }
  597. // map blending factor
  598. if (TokenMatch(m_szFile,"MAP_AMOUNT" ,10))
  599. {
  600. ParseLV4MeshFloat(map.mTextureBlend);
  601. continue;
  602. }
  603. }
  604. AI_ASE_HANDLE_SECTION(iDepth,"3","*MAP_XXXXXX");
  605. }
  606. return;
  607. }
  608. // ------------------------------------------------------------------------------------------------
  609. bool Parser::ParseString(std::string& out,const char* szName)
  610. {
  611. char szBuffer[1024];
  612. if (!SkipSpaces(&m_szFile))
  613. {
  614. sprintf(szBuffer,"Unable to parse %s block: Unexpected EOL",szName);
  615. LogWarning(szBuffer);
  616. return false;
  617. }
  618. // there must be "
  619. if ('\"' != *m_szFile)
  620. {
  621. sprintf(szBuffer,"Unable to parse %s block: Strings are expected "
  622. "to be enclosed in double quotation marks",szName);
  623. LogWarning(szBuffer);
  624. return false;
  625. }
  626. ++m_szFile;
  627. const char* sz = m_szFile;
  628. while (true)
  629. {
  630. if ('\"' == *sz)break;
  631. else if ('\0' == sz)
  632. {
  633. sprintf(szBuffer,"Unable to parse %s block: Strings are expected to be "
  634. "enclosed in double quotation marks but EOF was reached before a closing "
  635. "quotation mark was found",szName);
  636. LogWarning(szBuffer);
  637. return false;
  638. }
  639. sz++;
  640. }
  641. out = std::string(m_szFile,(uintptr_t)sz-(uintptr_t)m_szFile);
  642. m_szFile = sz;
  643. return true;
  644. }
  645. // ------------------------------------------------------------------------------------------------
  646. void Parser::ParseLV1ObjectBlock(ASE::BaseNode& node)
  647. {
  648. int iDepth = 0;
  649. while (true)
  650. {
  651. if ('*' == *m_szFile)
  652. {
  653. ++m_szFile;
  654. // first process common tokens such as node name and transform
  655. // name of the mesh/node
  656. if (TokenMatch(m_szFile,"NODE_NAME" ,9))
  657. {
  658. if(!ParseString(node.mName,"*NODE_NAME"))
  659. SkipToNextToken();
  660. continue;
  661. }
  662. // name of the parent of the node
  663. if (TokenMatch(m_szFile,"NODE_PARENT" ,11) )
  664. {
  665. if(!ParseString(node.mParent,"*NODE_PARENT"))
  666. SkipToNextToken();
  667. continue;
  668. }
  669. // transformation matrix of the node
  670. if (TokenMatch(m_szFile,"NODE_TM" ,7))
  671. {
  672. ParseLV2NodeTransformBlock(node);
  673. continue;
  674. }
  675. // animation data of the node
  676. if (TokenMatch(m_szFile,"TM_ANIMATION" ,12))
  677. {
  678. ParseLV2AnimationBlock(node);
  679. continue;
  680. }
  681. if (node.mType == BaseNode::Light)
  682. {
  683. // light settings
  684. if (TokenMatch(m_szFile,"LIGHT_SETTINGS" ,14))
  685. {
  686. ParseLV2LightSettingsBlock((ASE::Light&)node);
  687. continue;
  688. }
  689. // type of the light source
  690. if (TokenMatch(m_szFile,"LIGHT_TYPE" ,10))
  691. {
  692. if (!ASSIMP_strincmp("omni",m_szFile,4))
  693. {
  694. ((ASE::Light&)node).mLightType = ASE::Light::OMNI;
  695. }
  696. else if (!ASSIMP_strincmp("target",m_szFile,6))
  697. {
  698. ((ASE::Light&)node).mLightType = ASE::Light::TARGET;
  699. }
  700. else if (!ASSIMP_strincmp("free",m_szFile,4))
  701. {
  702. ((ASE::Light&)node).mLightType = ASE::Light::FREE;
  703. }
  704. else if (!ASSIMP_strincmp("directional",m_szFile,11))
  705. {
  706. ((ASE::Light&)node).mLightType = ASE::Light::DIRECTIONAL;
  707. }
  708. else
  709. {
  710. // TODO: use std::string as parameter for LogWarning
  711. LogWarning("Unknown kind of light source");
  712. }
  713. continue;
  714. }
  715. }
  716. else if (node.mType == BaseNode::Camera)
  717. {
  718. // Camera settings
  719. if (TokenMatch(m_szFile,"CAMERA_SETTINGS" ,15))
  720. {
  721. ParseLV2CameraSettingsBlock((ASE::Camera&)node);
  722. continue;
  723. }
  724. }
  725. else if (node.mType == BaseNode::Mesh)
  726. {
  727. // mesh data
  728. if (TokenMatch(m_szFile,"MESH" ,4))
  729. {
  730. ParseLV2MeshBlock((ASE::Mesh&)node);
  731. continue;
  732. }
  733. // mesh material index
  734. if (TokenMatch(m_szFile,"MATERIAL_REF" ,12))
  735. {
  736. ParseLV4MeshLong(((ASE::Mesh&)node).iMaterialIndex);
  737. continue;
  738. }
  739. }
  740. }
  741. AI_ASE_HANDLE_TOP_LEVEL_SECTION(iDepth);
  742. }
  743. return;
  744. }
  745. // ------------------------------------------------------------------------------------------------
  746. void Parser::ParseLV2CameraSettingsBlock(ASE::Camera& camera)
  747. {
  748. int iDepth = 0;
  749. while (true)
  750. {
  751. if ('*' == *m_szFile)
  752. {
  753. ++m_szFile;
  754. if (TokenMatch(m_szFile,"CAMERA_NEAR" ,11))
  755. {
  756. ParseLV4MeshFloat(camera.mNear);
  757. continue;
  758. }
  759. if (TokenMatch(m_szFile,"CAMERA_FAR" ,10))
  760. {
  761. ParseLV4MeshFloat(camera.mFar);
  762. continue;
  763. }
  764. if (TokenMatch(m_szFile,"CAMERA_FOV" ,10))
  765. {
  766. ParseLV4MeshFloat(camera.mFOV);
  767. continue;
  768. }
  769. }
  770. AI_ASE_HANDLE_SECTION(iDepth,"2","CAMERA_SETTINGS");
  771. }
  772. return;
  773. }
  774. // ------------------------------------------------------------------------------------------------
  775. void Parser::ParseLV2LightSettingsBlock(ASE::Light& light)
  776. {
  777. int iDepth = 0;
  778. while (true)
  779. {
  780. if ('*' == *m_szFile)
  781. {
  782. ++m_szFile;
  783. if (TokenMatch(m_szFile,"LIGHT_COLOR" ,11))
  784. {
  785. ParseLV4MeshFloatTriple(&light.mColor.r);
  786. continue;
  787. }
  788. if (TokenMatch(m_szFile,"LIGHT_INTENS" ,12))
  789. {
  790. ParseLV4MeshFloat(light.mIntensity);
  791. continue;
  792. }
  793. if (TokenMatch(m_szFile,"LIGHT_HOTSPOT" ,13))
  794. {
  795. ParseLV4MeshFloat(light.mAngle);
  796. continue;
  797. }
  798. if (TokenMatch(m_szFile,"LIGHT_FALLOFF" ,13))
  799. {
  800. ParseLV4MeshFloat(light.mFalloff);
  801. continue;
  802. }
  803. }
  804. AI_ASE_HANDLE_SECTION(iDepth,"2","LIGHT_SETTINGS");
  805. }
  806. return;
  807. }
  808. // ------------------------------------------------------------------------------------------------
  809. void Parser::ParseLV2AnimationBlock(ASE::BaseNode& mesh)
  810. {
  811. int iDepth = 0;
  812. ASE::Animation* anim = &mesh.mAnim;
  813. while (true)
  814. {
  815. if ('*' == *m_szFile)
  816. {
  817. ++m_szFile;
  818. if (TokenMatch(m_szFile,"NODE_NAME" ,9))
  819. {
  820. std::string temp;
  821. if(!ParseString(temp,"*NODE_NAME"))
  822. SkipToNextToken();
  823. // If the name of the node contains .target it
  824. // represents an animated camera or spot light
  825. // target.
  826. if (std::string::npos != temp.find(".Target"))
  827. {
  828. if (mesh.mType != BaseNode::Camera &&
  829. (mesh.mType != BaseNode::Light ||
  830. ((ASE::Light&)mesh).mLightType != ASE::Light::TARGET))
  831. { /* it is not absolutely sure we know the type of the light source yet */
  832. DefaultLogger::get()->error("ASE: Found target animation channel "
  833. "but the node is neither a camera nor a spot light");
  834. anim = NULL;
  835. }
  836. else anim = &mesh.mTargetAnim;
  837. }
  838. continue;
  839. }
  840. // position keyframes
  841. if (TokenMatch(m_szFile,"CONTROL_POS_TRACK" ,17) ||
  842. TokenMatch(m_szFile,"CONTROL_POS_BEZIER" ,18) ||
  843. TokenMatch(m_szFile,"CONTROL_POS_TCB" ,15))
  844. {
  845. if (!anim)SkipSection();
  846. else ParseLV3PosAnimationBlock(*anim);
  847. continue;
  848. }
  849. // scaling keyframes
  850. if (TokenMatch(m_szFile,"CONTROL_SCALE_TRACK" ,19) ||
  851. TokenMatch(m_szFile,"CONTROL_SCALE_BEZIER" ,20) ||
  852. TokenMatch(m_szFile,"CONTROL_SCALE_TCB" ,17))
  853. {
  854. if (!anim || anim == &mesh.mTargetAnim)
  855. {
  856. // Target animation channels may have no rotation channels
  857. DefaultLogger::get()->error("ASE: Ignoring scaling channel in target animation");
  858. SkipSection();
  859. }
  860. else ParseLV3ScaleAnimationBlock(*anim);
  861. continue;
  862. }
  863. // rotation keyframes
  864. if (TokenMatch(m_szFile,"CONTROL_ROT_TRACK" ,17) ||
  865. TokenMatch(m_szFile,"CONTROL_ROT_BEZIER" ,18) ||
  866. TokenMatch(m_szFile,"CONTROL_ROT_TCB" ,15))
  867. {
  868. if (!anim || anim == &mesh.mTargetAnim)
  869. {
  870. // Target animation channels may have no rotation channels
  871. DefaultLogger::get()->error("ASE: Ignoring rotation channel in target animation");
  872. SkipSection();
  873. }
  874. else ParseLV3RotAnimationBlock(*anim);
  875. continue;
  876. }
  877. }
  878. AI_ASE_HANDLE_SECTION(iDepth,"2","TM_ANIMATION");
  879. }
  880. }
  881. // ------------------------------------------------------------------------------------------------
  882. void Parser::ParseLV3ScaleAnimationBlock(ASE::Animation& anim)
  883. {
  884. int iDepth = 0;
  885. unsigned int iIndex;
  886. while (true)
  887. {
  888. if ('*' == *m_szFile)
  889. {
  890. ++m_szFile;
  891. bool b = false;
  892. // For the moment we're just reading the three floats -
  893. // we ignore the ádditional information for bezier's and TCBs
  894. // simple scaling keyframe
  895. if (TokenMatch(m_szFile,"CONTROL_SCALE_SAMPLE" ,20))
  896. {
  897. b = true;
  898. anim.mScalingType = ASE::Animation::TRACK;
  899. }
  900. // Bezier scaling keyframe
  901. if (TokenMatch(m_szFile,"CONTROL_BEZIER_SCALE_KEY" ,24))
  902. {
  903. b = true;
  904. anim.mScalingType = ASE::Animation::BEZIER;
  905. }
  906. // TCB scaling keyframe
  907. if (TokenMatch(m_szFile,"CONTROL_TCB_SCALE_KEY" ,21))
  908. {
  909. b = true;
  910. anim.mScalingType = ASE::Animation::TCB;
  911. }
  912. if (b)
  913. {
  914. anim.akeyScaling.push_back(aiVectorKey());
  915. aiVectorKey& key = anim.akeyScaling.back();
  916. ParseLV4MeshFloatTriple(&key.mValue.x,iIndex);
  917. key.mTime = (double)iIndex;
  918. }
  919. }
  920. AI_ASE_HANDLE_SECTION(iDepth,"3","*CONTROL_POS_TRACK");
  921. }
  922. }
  923. // ------------------------------------------------------------------------------------------------
  924. void Parser::ParseLV3PosAnimationBlock(ASE::Animation& anim)
  925. {
  926. int iDepth = 0;
  927. unsigned int iIndex;
  928. while (true)
  929. {
  930. if ('*' == *m_szFile)
  931. {
  932. ++m_szFile;
  933. bool b = false;
  934. // For the moment we're just reading the three floats -
  935. // we ignore the ádditional information for bezier's and TCBs
  936. // simple scaling keyframe
  937. if (TokenMatch(m_szFile,"CONTROL_POS_SAMPLE" ,18))
  938. {
  939. b = true;
  940. anim.mPositionType = ASE::Animation::TRACK;
  941. }
  942. // Bezier scaling keyframe
  943. if (TokenMatch(m_szFile,"CONTROL_BEZIER_POS_KEY" ,22))
  944. {
  945. b = true;
  946. anim.mPositionType = ASE::Animation::BEZIER;
  947. }
  948. // TCB scaling keyframe
  949. if (TokenMatch(m_szFile,"CONTROL_TCB_POS_KEY" ,19))
  950. {
  951. b = true;
  952. anim.mPositionType = ASE::Animation::TCB;
  953. }
  954. if (b)
  955. {
  956. anim.akeyPositions.push_back(aiVectorKey());
  957. aiVectorKey& key = anim.akeyPositions.back();
  958. ParseLV4MeshFloatTriple(&key.mValue.x,iIndex);
  959. key.mTime = (double)iIndex;
  960. }
  961. }
  962. AI_ASE_HANDLE_SECTION(iDepth,"3","*CONTROL_POS_TRACK");
  963. }
  964. }
  965. // ------------------------------------------------------------------------------------------------
  966. void Parser::ParseLV3RotAnimationBlock(ASE::Animation& anim)
  967. {
  968. int iDepth = 0;
  969. unsigned int iIndex;
  970. while (true)
  971. {
  972. if ('*' == *m_szFile)
  973. {
  974. ++m_szFile;
  975. bool b = false;
  976. // For the moment we're just reading the floats -
  977. // we ignore the ádditional information for bezier's and TCBs
  978. // simple scaling keyframe
  979. if (TokenMatch(m_szFile,"CONTROL_ROT_SAMPLE" ,18))
  980. {
  981. b = true;
  982. anim.mRotationType = ASE::Animation::TRACK;
  983. }
  984. // Bezier scaling keyframe
  985. if (TokenMatch(m_szFile,"CONTROL_BEZIER_ROT_KEY" ,22))
  986. {
  987. b = true;
  988. anim.mRotationType = ASE::Animation::BEZIER;
  989. }
  990. // TCB scaling keyframe
  991. if (TokenMatch(m_szFile,"CONTROL_TCB_ROT_KEY" ,19))
  992. {
  993. b = true;
  994. anim.mRotationType = ASE::Animation::TCB;
  995. }
  996. if (b)
  997. {
  998. anim.akeyRotations.push_back(aiQuatKey());
  999. aiQuatKey& key = anim.akeyRotations.back();
  1000. aiVector3D v;float f;
  1001. ParseLV4MeshFloatTriple(&v.x,iIndex);
  1002. ParseLV4MeshFloat(f);
  1003. key.mTime = (double)iIndex;
  1004. key.mValue = aiQuaternion(v,f);
  1005. }
  1006. }
  1007. AI_ASE_HANDLE_SECTION(iDepth,"3","*CONTROL_ROT_TRACK");
  1008. }
  1009. }
  1010. // ------------------------------------------------------------------------------------------------
  1011. void Parser::ParseLV2NodeTransformBlock(ASE::BaseNode& mesh)
  1012. {
  1013. int iDepth = 0;
  1014. int mode = 0;
  1015. while (true)
  1016. {
  1017. if ('*' == *m_szFile)
  1018. {
  1019. ++m_szFile;
  1020. // name of the node
  1021. if (TokenMatch(m_szFile,"NODE_NAME" ,9))
  1022. {
  1023. std::string temp;
  1024. if(!ParseString(temp,"*NODE_NAME"))
  1025. SkipToNextToken();
  1026. std::string::size_type s;
  1027. if (temp == mesh.mName)
  1028. {
  1029. mode = 1;
  1030. }
  1031. else if (std::string::npos != (s = temp.find(".Target")) &&
  1032. mesh.mName == temp.substr(0,s))
  1033. {
  1034. // This should be either a target light or a target camera
  1035. if ( mesh.mType == BaseNode::Light && ((ASE::Light&)mesh) .mLightType == ASE::Light::TARGET ||
  1036. mesh.mType == BaseNode::Camera && ((ASE::Camera&)mesh).mCameraType == ASE::Camera::TARGET)
  1037. {
  1038. mode = 2;
  1039. }
  1040. else DefaultLogger::get()->error("ASE: Ignoring target transform, "
  1041. "this is no spot light or target camera");
  1042. }
  1043. else
  1044. {
  1045. DefaultLogger::get()->error("ASE: Unknown node transformation: " + temp);
  1046. // mode = 0
  1047. }
  1048. continue;
  1049. }
  1050. if (mode)
  1051. {
  1052. // fourth row of the transformation matrix - and also the
  1053. // only information here that is interesting for targets
  1054. if (TokenMatch(m_szFile,"TM_ROW3" ,7))
  1055. {
  1056. ParseLV4MeshFloatTriple((mode == 1 ? mesh.mTransform[3] : &mesh.mTargetPosition.x));
  1057. continue;
  1058. }
  1059. if (mode == 1)
  1060. {
  1061. // first row of the transformation matrix
  1062. if (TokenMatch(m_szFile,"TM_ROW0" ,7))
  1063. {
  1064. ParseLV4MeshFloatTriple(mesh.mTransform[0]);
  1065. continue;
  1066. }
  1067. // second row of the transformation matrix
  1068. if (TokenMatch(m_szFile,"TM_ROW1" ,7))
  1069. {
  1070. ParseLV4MeshFloatTriple(mesh.mTransform[1]);
  1071. continue;
  1072. }
  1073. // third row of the transformation matrix
  1074. if (TokenMatch(m_szFile,"TM_ROW2" ,7))
  1075. {
  1076. ParseLV4MeshFloatTriple(mesh.mTransform[2]);
  1077. continue;
  1078. }
  1079. // inherited position axes
  1080. if (TokenMatch(m_szFile,"INHERIT_POS" ,11))
  1081. {
  1082. unsigned int aiVal[3];
  1083. ParseLV4MeshLongTriple(aiVal);
  1084. for (unsigned int i = 0; i < 3;++i)
  1085. mesh.inherit.abInheritPosition[i] = aiVal[i] != 0;
  1086. continue;
  1087. }
  1088. // inherited rotation axes
  1089. if (TokenMatch(m_szFile,"INHERIT_ROT" ,11))
  1090. {
  1091. unsigned int aiVal[3];
  1092. ParseLV4MeshLongTriple(aiVal);
  1093. for (unsigned int i = 0; i < 3;++i)
  1094. mesh.inherit.abInheritRotation[i] = aiVal[i] != 0;
  1095. continue;
  1096. }
  1097. // inherited scaling axes
  1098. if (TokenMatch(m_szFile,"INHERIT_SCL" ,11))
  1099. {
  1100. unsigned int aiVal[3];
  1101. ParseLV4MeshLongTriple(aiVal);
  1102. for (unsigned int i = 0; i < 3;++i)
  1103. mesh.inherit.abInheritScaling[i] = aiVal[i] != 0;
  1104. continue;
  1105. }
  1106. }
  1107. }
  1108. }
  1109. AI_ASE_HANDLE_SECTION(iDepth,"2","*NODE_TM");
  1110. }
  1111. return;
  1112. }
  1113. // ------------------------------------------------------------------------------------------------
  1114. void Parser::ParseLV2MeshBlock(ASE::Mesh& mesh)
  1115. {
  1116. unsigned int iNumVertices = 0;
  1117. unsigned int iNumFaces = 0;
  1118. unsigned int iNumTVertices = 0;
  1119. unsigned int iNumTFaces = 0;
  1120. unsigned int iNumCVertices = 0;
  1121. unsigned int iNumCFaces = 0;
  1122. int iDepth = 0;
  1123. while (true)
  1124. {
  1125. if ('*' == *m_szFile)
  1126. {
  1127. ++m_szFile;
  1128. // Number of vertices in the mesh
  1129. if (TokenMatch(m_szFile,"MESH_NUMVERTEX" ,14))
  1130. {
  1131. ParseLV4MeshLong(iNumVertices);
  1132. continue;
  1133. }
  1134. // Number of texture coordinates in the mesh
  1135. if (TokenMatch(m_szFile,"MESH_NUMTVERTEX" ,15))
  1136. {
  1137. ParseLV4MeshLong(iNumTVertices);
  1138. continue;
  1139. }
  1140. // Number of vertex colors in the mesh
  1141. if (TokenMatch(m_szFile,"MESH_NUMCVERTEX" ,14))
  1142. {
  1143. ParseLV4MeshLong(iNumCVertices);
  1144. continue;
  1145. }
  1146. // Number of regular faces in the mesh
  1147. if (TokenMatch(m_szFile,"MESH_NUMFACES" ,13))
  1148. {
  1149. ParseLV4MeshLong(iNumFaces);
  1150. continue;
  1151. }
  1152. // Number of UVWed faces in the mesh
  1153. if (TokenMatch(m_szFile,"MESH_NUMTVFACES" ,15))
  1154. {
  1155. ParseLV4MeshLong(iNumTFaces);
  1156. continue;
  1157. }
  1158. // Number of colored faces in the mesh
  1159. if (TokenMatch(m_szFile,"MESH_NUMCVFACES" ,15))
  1160. {
  1161. ParseLV4MeshLong(iNumCFaces);
  1162. continue;
  1163. }
  1164. // mesh vertex list block
  1165. if (TokenMatch(m_szFile,"MESH_VERTEX_LIST" ,16))
  1166. {
  1167. ParseLV3MeshVertexListBlock(iNumVertices,mesh);
  1168. continue;
  1169. }
  1170. // mesh face list block
  1171. if (TokenMatch(m_szFile,"MESH_FACE_LIST" ,14))
  1172. {
  1173. ParseLV3MeshFaceListBlock(iNumFaces,mesh);
  1174. continue;
  1175. }
  1176. // mesh texture vertex list block
  1177. if (TokenMatch(m_szFile,"MESH_TVERTLIST" ,14))
  1178. {
  1179. ParseLV3MeshTListBlock(iNumTVertices,mesh);
  1180. continue;
  1181. }
  1182. // mesh texture face block
  1183. if (TokenMatch(m_szFile,"MESH_TFACELIST" ,14))
  1184. {
  1185. ParseLV3MeshTFaceListBlock(iNumTFaces,mesh);
  1186. continue;
  1187. }
  1188. // mesh color vertex list block
  1189. if (TokenMatch(m_szFile,"MESH_CVERTLIST" ,14))
  1190. {
  1191. ParseLV3MeshCListBlock(iNumCVertices,mesh);
  1192. continue;
  1193. }
  1194. // mesh color face block
  1195. if (TokenMatch(m_szFile,"MESH_CFACELIST" ,14))
  1196. {
  1197. ParseLV3MeshCFaceListBlock(iNumCFaces,mesh);
  1198. continue;
  1199. }
  1200. // mesh normals
  1201. if (TokenMatch(m_szFile,"MESH_NORMALS" ,12))
  1202. {
  1203. ParseLV3MeshNormalListBlock(mesh);
  1204. continue;
  1205. }
  1206. // another mesh UV channel ...
  1207. if (TokenMatch(m_szFile,"MESH_MAPPINGCHANNEL" ,19))
  1208. {
  1209. unsigned int iIndex = 0;
  1210. ParseLV4MeshLong(iIndex);
  1211. if (iIndex < 2)
  1212. {
  1213. LogWarning("Mapping channel has an invalid index. Skipping UV channel");
  1214. // skip it ...
  1215. SkipSection();
  1216. }
  1217. if (iIndex > AI_MAX_NUMBER_OF_TEXTURECOORDS)
  1218. {
  1219. LogWarning("Too many UV channels specified. Skipping channel ..");
  1220. // skip it ...
  1221. SkipSection();
  1222. }
  1223. else
  1224. {
  1225. // parse the mapping channel
  1226. ParseLV3MappingChannel(iIndex-1,mesh);
  1227. }
  1228. continue;
  1229. }
  1230. // mesh animation keyframe. Not supported
  1231. if (TokenMatch(m_szFile,"MESH_ANIMATION" ,14))
  1232. {
  1233. LogWarning("Found *MESH_ANIMATION element in ASE/ASK file. "
  1234. "Keyframe animation is not supported by Assimp, this element "
  1235. "will be ignored");
  1236. //SkipSection();
  1237. continue;
  1238. }
  1239. if (TokenMatch(m_szFile,"MESH_WEIGHTS" ,12))
  1240. {
  1241. ParseLV3MeshWeightsBlock(mesh);continue;
  1242. }
  1243. }
  1244. AI_ASE_HANDLE_SECTION(iDepth,"2","*MESH");
  1245. }
  1246. return;
  1247. }
  1248. // ------------------------------------------------------------------------------------------------
  1249. void Parser::ParseLV3MeshWeightsBlock(ASE::Mesh& mesh)
  1250. {
  1251. unsigned int iNumVertices = 0;
  1252. unsigned int iNumBones = 0;
  1253. int iDepth = 0;
  1254. while (true)
  1255. {
  1256. if ('*' == *m_szFile)
  1257. {
  1258. ++m_szFile;
  1259. // Number of bone vertices ...
  1260. if (TokenMatch(m_szFile,"MESH_NUMVERTEX" ,14))
  1261. {
  1262. ParseLV4MeshLong(iNumVertices);
  1263. continue;
  1264. }
  1265. // Number of bones
  1266. if (TokenMatch(m_szFile,"MESH_NUMBONE" ,11))
  1267. {
  1268. ParseLV4MeshLong(iNumBones);
  1269. continue;
  1270. }
  1271. // parse the list of bones
  1272. if (TokenMatch(m_szFile,"MESH_BONE_LIST" ,14))
  1273. {
  1274. ParseLV4MeshBones(iNumBones,mesh);
  1275. continue;
  1276. }
  1277. // parse the list of bones vertices
  1278. if (TokenMatch(m_szFile,"MESH_BONE_VERTEX_LIST" ,21) )
  1279. {
  1280. ParseLV4MeshBonesVertices(iNumVertices,mesh);
  1281. continue;
  1282. }
  1283. }
  1284. AI_ASE_HANDLE_SECTION(iDepth,"3","*MESH_WEIGHTS");
  1285. }
  1286. return;
  1287. }
  1288. // ------------------------------------------------------------------------------------------------
  1289. void Parser::ParseLV4MeshBones(unsigned int iNumBones,ASE::Mesh& mesh)
  1290. {
  1291. mesh.mBones.resize(iNumBones);
  1292. int iDepth = 0;
  1293. while (true)
  1294. {
  1295. if ('*' == *m_szFile)
  1296. {
  1297. ++m_szFile;
  1298. // Mesh bone with name ...
  1299. if (TokenMatch(m_szFile,"MESH_BONE_NAME" ,16))
  1300. {
  1301. // parse an index ...
  1302. if(SkipSpaces(&m_szFile))
  1303. {
  1304. unsigned int iIndex = strtol10(m_szFile,&m_szFile);
  1305. if (iIndex >= iNumBones)
  1306. {
  1307. continue;
  1308. LogWarning("Bone index is out of bounds");
  1309. }
  1310. if (!ParseString(mesh.mBones[iIndex].mName,"*MESH_BONE_NAME"))
  1311. SkipToNextToken();
  1312. continue;
  1313. }
  1314. }
  1315. }
  1316. AI_ASE_HANDLE_SECTION(iDepth,"3","*MESH_BONE_LIST");
  1317. }
  1318. }
  1319. // ------------------------------------------------------------------------------------------------
  1320. void Parser::ParseLV4MeshBonesVertices(unsigned int iNumVertices,ASE::Mesh& mesh)
  1321. {
  1322. mesh.mBoneVertices.resize(iNumVertices);
  1323. int iDepth = 0;
  1324. while (true)
  1325. {
  1326. if ('*' == *m_szFile)
  1327. {
  1328. ++m_szFile;
  1329. // Mesh bone vertex
  1330. if (TokenMatch(m_szFile,"MESH_BONE_VERTEX" ,16))
  1331. {
  1332. // read the vertex index
  1333. unsigned int iIndex = strtol10(m_szFile,&m_szFile);
  1334. if (iIndex >= mesh.mPositions.size())
  1335. {
  1336. iIndex = (unsigned int)mesh.mPositions.size()-1;
  1337. LogWarning("Bone vertex index is out of bounds. Using the largest valid "
  1338. "bone vertex index instead");
  1339. }
  1340. // --- ignored
  1341. float afVert[3];
  1342. ParseLV4MeshFloatTriple(afVert);
  1343. std::pair<int,float> pairOut;
  1344. while (true)
  1345. {
  1346. // first parse the bone index ...
  1347. if (!SkipSpaces(&m_szFile))break;
  1348. pairOut.first = strtol10(m_szFile,&m_szFile);
  1349. // then parse the vertex weight
  1350. if (!SkipSpaces(&m_szFile))break;
  1351. m_szFile = fast_atof_move(m_szFile,pairOut.second);
  1352. // -1 designates unused entries
  1353. if (-1 != pairOut.first)
  1354. {
  1355. mesh.mBoneVertices[iIndex].mBoneWeights.push_back(pairOut);
  1356. }
  1357. }
  1358. continue;
  1359. }
  1360. }
  1361. AI_ASE_HANDLE_SECTION(iDepth,"4","*MESH_BONE_VERTEX");
  1362. }
  1363. return;
  1364. }
  1365. // ------------------------------------------------------------------------------------------------
  1366. void Parser::ParseLV3MeshVertexListBlock(
  1367. unsigned int iNumVertices, ASE::Mesh& mesh)
  1368. {
  1369. // allocate enough storage in the array
  1370. mesh.mPositions.resize(iNumVertices);
  1371. int iDepth = 0;
  1372. while (true)
  1373. {
  1374. if ('*' == *m_szFile)
  1375. {
  1376. ++m_szFile;
  1377. // Vertex entry
  1378. if (TokenMatch(m_szFile,"MESH_VERTEX" ,11))
  1379. {
  1380. aiVector3D vTemp;
  1381. unsigned int iIndex;
  1382. ParseLV4MeshFloatTriple(&vTemp.x,iIndex);
  1383. if (iIndex >= iNumVertices)
  1384. {
  1385. LogWarning("Invalid vertex index. It will be ignored");
  1386. }
  1387. else mesh.mPositions[iIndex] = vTemp;
  1388. continue;
  1389. }
  1390. }
  1391. AI_ASE_HANDLE_SECTION(iDepth,"3","*MESH_VERTEX_LIST");
  1392. }
  1393. return;
  1394. }
  1395. // ------------------------------------------------------------------------------------------------
  1396. void Parser::ParseLV3MeshFaceListBlock(unsigned int iNumFaces, ASE::Mesh& mesh)
  1397. {
  1398. // allocate enough storage in the face array
  1399. mesh.mFaces.resize(iNumFaces);
  1400. int iDepth = 0;
  1401. while (true)
  1402. {
  1403. if ('*' == *m_szFile)
  1404. {
  1405. ++m_szFile;
  1406. // Face entry
  1407. if (TokenMatch(m_szFile,"MESH_FACE" ,9))
  1408. {
  1409. ASE::Face mFace;
  1410. ParseLV4MeshFace(mFace);
  1411. if (mFace.iFace >= iNumFaces)
  1412. {
  1413. LogWarning("Face has an invalid index. It will be ignored");
  1414. }
  1415. else mesh.mFaces[mFace.iFace] = mFace;
  1416. continue;
  1417. }
  1418. }
  1419. AI_ASE_HANDLE_SECTION(iDepth,"3","*MESH_FACE_LIST");
  1420. }
  1421. return;
  1422. }
  1423. // ------------------------------------------------------------------------------------------------
  1424. void Parser::ParseLV3MeshTListBlock(unsigned int iNumVertices,
  1425. ASE::Mesh& mesh, unsigned int iChannel)
  1426. {
  1427. // allocate enough storage in the array
  1428. mesh.amTexCoords[iChannel].resize(iNumVertices);
  1429. int iDepth = 0;
  1430. while (true)
  1431. {
  1432. if ('*' == *m_szFile)
  1433. {
  1434. ++m_szFile;
  1435. // Vertex entry
  1436. if (TokenMatch(m_szFile,"MESH_TVERT" ,10))
  1437. {
  1438. aiVector3D vTemp;
  1439. unsigned int iIndex;
  1440. ParseLV4MeshFloatTriple(&vTemp.x,iIndex);
  1441. if (iIndex >= iNumVertices)
  1442. {
  1443. LogWarning("Tvertex has an invalid index. It will be ignored");
  1444. }
  1445. else mesh.amTexCoords[iChannel][iIndex] = vTemp;
  1446. if (0.0f != vTemp.z)
  1447. {
  1448. // we need 3 coordinate channels
  1449. mesh.mNumUVComponents[iChannel] = 3;
  1450. }
  1451. continue;
  1452. }
  1453. }
  1454. AI_ASE_HANDLE_SECTION(iDepth,"3","*MESH_TVERT_LIST");
  1455. }
  1456. return;
  1457. }
  1458. // ------------------------------------------------------------------------------------------------
  1459. void Parser::ParseLV3MeshTFaceListBlock(unsigned int iNumFaces,
  1460. ASE::Mesh& mesh, unsigned int iChannel)
  1461. {
  1462. int iDepth = 0;
  1463. while (true)
  1464. {
  1465. if ('*' == *m_szFile)
  1466. {
  1467. ++m_szFile;
  1468. // Face entry
  1469. if (TokenMatch(m_szFile,"MESH_TFACE" ,10))
  1470. {
  1471. unsigned int aiValues[3];
  1472. unsigned int iIndex = 0;
  1473. ParseLV4MeshLongTriple(aiValues,iIndex);
  1474. if (iIndex >= iNumFaces || iIndex >= mesh.mFaces.size())
  1475. {
  1476. LogWarning("UV-Face has an invalid index. It will be ignored");
  1477. }
  1478. else
  1479. {
  1480. // copy UV indices
  1481. mesh.mFaces[iIndex].amUVIndices[iChannel][0] = aiValues[0];
  1482. mesh.mFaces[iIndex].amUVIndices[iChannel][1] = aiValues[1];
  1483. mesh.mFaces[iIndex].amUVIndices[iChannel][2] = aiValues[2];
  1484. }
  1485. continue;
  1486. }
  1487. }
  1488. AI_ASE_HANDLE_SECTION(iDepth,"3","*MESH_TFACE_LIST");
  1489. }
  1490. return;
  1491. }
  1492. // ------------------------------------------------------------------------------------------------
  1493. void Parser::ParseLV3MappingChannel(unsigned int iChannel, ASE::Mesh& mesh)
  1494. {
  1495. unsigned int iNumTVertices = 0;
  1496. unsigned int iNumTFaces = 0;
  1497. int iDepth = 0;
  1498. while (true)
  1499. {
  1500. if ('*' == *m_szFile)
  1501. {
  1502. ++m_szFile;
  1503. // Number of texture coordinates in the mesh
  1504. if (TokenMatch(m_szFile,"MESH_NUMTVERTEX" ,15))
  1505. {
  1506. ParseLV4MeshLong(iNumTVertices);
  1507. continue;
  1508. }
  1509. // Number of UVWed faces in the mesh
  1510. if (TokenMatch(m_szFile,"MESH_NUMTVFACES" ,15))
  1511. {
  1512. ParseLV4MeshLong(iNumTFaces);
  1513. continue;
  1514. }
  1515. // mesh texture vertex list block
  1516. if (TokenMatch(m_szFile,"MESH_TVERTLIST" ,14))
  1517. {
  1518. ParseLV3MeshTListBlock(iNumTVertices,mesh,iChannel);
  1519. continue;
  1520. }
  1521. // mesh texture face block
  1522. if (TokenMatch(m_szFile,"MESH_TFACELIST" ,14))
  1523. {
  1524. ParseLV3MeshTFaceListBlock(iNumTFaces,mesh, iChannel);
  1525. continue;
  1526. }
  1527. }
  1528. AI_ASE_HANDLE_SECTION(iDepth,"3","*MESH_MAPPING_CHANNEL");
  1529. }
  1530. return;
  1531. }
  1532. // ------------------------------------------------------------------------------------------------
  1533. void Parser::ParseLV3MeshCListBlock(unsigned int iNumVertices, ASE::Mesh& mesh)
  1534. {
  1535. // allocate enough storage in the array
  1536. mesh.mVertexColors.resize(iNumVertices);
  1537. int iDepth = 0;
  1538. while (true)
  1539. {
  1540. if ('*' == *m_szFile)
  1541. {
  1542. ++m_szFile;
  1543. // Vertex entry
  1544. if (TokenMatch(m_szFile,"MESH_VERTCOL" ,12))
  1545. {
  1546. aiColor4D vTemp;
  1547. vTemp.a = 1.0f;
  1548. unsigned int iIndex;
  1549. ParseLV4MeshFloatTriple(&vTemp.r,iIndex);
  1550. if (iIndex >= iNumVertices)
  1551. {
  1552. LogWarning("Vertex color has an invalid index. It will be ignored");
  1553. }
  1554. else mesh.mVertexColors[iIndex] = vTemp;
  1555. continue;
  1556. }
  1557. }
  1558. AI_ASE_HANDLE_SECTION(iDepth,"3","*MESH_CVERTEX_LIST");
  1559. }
  1560. return;
  1561. }
  1562. // ------------------------------------------------------------------------------------------------
  1563. void Parser::ParseLV3MeshCFaceListBlock(unsigned int iNumFaces, ASE::Mesh& mesh)
  1564. {
  1565. int iDepth = 0;
  1566. while (true)
  1567. {
  1568. if ('*' == *m_szFile)
  1569. {
  1570. ++m_szFile;
  1571. // Face entry
  1572. if (TokenMatch(m_szFile,"MESH_CFACE" ,11))
  1573. {
  1574. unsigned int aiValues[3];
  1575. unsigned int iIndex = 0;
  1576. ParseLV4MeshLongTriple(aiValues,iIndex);
  1577. if (iIndex >= iNumFaces || iIndex >= mesh.mFaces.size())
  1578. {
  1579. LogWarning("UV-Face has an invalid index. It will be ignored");
  1580. }
  1581. else
  1582. {
  1583. // copy color indices
  1584. mesh.mFaces[iIndex].mColorIndices[0] = aiValues[0];
  1585. mesh.mFaces[iIndex].mColorIndices[1] = aiValues[1];
  1586. mesh.mFaces[iIndex].mColorIndices[2] = aiValues[2];
  1587. }
  1588. continue;
  1589. }
  1590. }
  1591. AI_ASE_HANDLE_SECTION(iDepth,"3","*MESH_CFACE_LIST");
  1592. }
  1593. return;
  1594. }
  1595. // ------------------------------------------------------------------------------------------------
  1596. void Parser::ParseLV3MeshNormalListBlock(ASE::Mesh& sMesh)
  1597. {
  1598. // allocate enough storage for the normals
  1599. sMesh.mNormals.resize(sMesh.mFaces.size()*3,aiVector3D( 0.f, 0.f, 0.f ));
  1600. int iDepth = 0;
  1601. unsigned int iIndex = 0, faceIdx = 0xffffffff;
  1602. // just smooth both vertex and face normals together, so it will still
  1603. // work if one one of the two is missing ...
  1604. while (true)
  1605. {
  1606. if ('*' == *m_szFile)
  1607. {
  1608. ++m_szFile;
  1609. if (0xffffffff != faceIdx && TokenMatch(m_szFile,"MESH_VERTEXNORMAL",17))
  1610. {
  1611. aiVector3D vNormal;
  1612. ParseLV4MeshFloatTriple(&vNormal.x,iIndex);
  1613. if (iIndex == sMesh.mFaces[faceIdx].mIndices[0])
  1614. {
  1615. iIndex = 0;
  1616. }
  1617. else if (iIndex != sMesh.mFaces[faceIdx].mIndices[1])
  1618. {
  1619. iIndex = 1;
  1620. }
  1621. else if (iIndex != sMesh.mFaces[faceIdx].mIndices[2])
  1622. {
  1623. iIndex = 2;
  1624. }
  1625. else
  1626. {
  1627. LogWarning("Normal index doesn't fit to face index");
  1628. continue;
  1629. }
  1630. // We'll renormalized later
  1631. sMesh.mNormals[faceIdx*3 + iIndex] += vNormal;
  1632. continue;
  1633. }
  1634. if (TokenMatch(m_szFile,"MESH_FACENORMAL",15))
  1635. {
  1636. aiVector3D vNormal;
  1637. ParseLV4MeshFloatTriple(&vNormal.x,faceIdx);
  1638. if (iIndex >= sMesh.mFaces.size())
  1639. {
  1640. LogWarning("Face normal index is too large");
  1641. faceIdx = 0xffffffff;
  1642. continue;
  1643. }
  1644. sMesh.mNormals[faceIdx*3] += vNormal;
  1645. sMesh.mNormals[faceIdx*3 +1] += vNormal;
  1646. sMesh.mNormals[faceIdx*3 +2] += vNormal;
  1647. continue;
  1648. }
  1649. }
  1650. AI_ASE_HANDLE_SECTION(iDepth,"3","*MESH_NORMALS");
  1651. }
  1652. return;
  1653. }
  1654. // ------------------------------------------------------------------------------------------------
  1655. void Parser::ParseLV4MeshFace(ASE::Face& out)
  1656. {
  1657. // skip spaces and tabs
  1658. if(!SkipSpaces(&m_szFile))
  1659. {
  1660. LogWarning("Unable to parse *MESH_FACE Element: Unexpected EOL [#1]");
  1661. SkipToNextToken();
  1662. return;
  1663. }
  1664. // parse the face index
  1665. out.iFace = strtol10(m_szFile,&m_szFile);
  1666. // next character should be ':'
  1667. if(!SkipSpaces(&m_szFile))
  1668. {
  1669. // FIX: there are some ASE files which haven't got : here ....
  1670. LogWarning("Unable to parse *MESH_FACE Element: Unexpected EOL. \':\' expected [#2]");
  1671. SkipToNextToken();
  1672. return;
  1673. }
  1674. // FIX: there are some ASE files which haven't got : here ....
  1675. if(':' == *m_szFile)++m_szFile;
  1676. // parse all mesh indices
  1677. for (unsigned int i = 0; i < 3;++i)
  1678. {
  1679. unsigned int iIndex = 0;
  1680. if(!SkipSpaces(&m_szFile))
  1681. {
  1682. // LOG
  1683. __EARTHQUAKE_XXL:
  1684. LogWarning("Unable to parse *MESH_FACE Element: Unexpected EOL. "
  1685. "A,B or C expected [#3]");
  1686. SkipToNextToken();
  1687. return;
  1688. }
  1689. switch (*m_szFile)
  1690. {
  1691. case 'A':
  1692. case 'a':
  1693. break;
  1694. case 'B':
  1695. case 'b':
  1696. iIndex = 1;
  1697. break;
  1698. case 'C':
  1699. case 'c':
  1700. iIndex = 2;
  1701. break;
  1702. default: goto __EARTHQUAKE_XXL;
  1703. };
  1704. ++m_szFile;
  1705. // next character should be ':'
  1706. if(!SkipSpaces(&m_szFile) || ':' != *m_szFile)
  1707. {
  1708. LogWarning("Unable to parse *MESH_FACE Element: "
  1709. "Unexpected EOL. \':\' expected [#2]");
  1710. SkipToNextToken();
  1711. return;
  1712. }
  1713. ++m_szFile;
  1714. if(!SkipSpaces(&m_szFile))
  1715. {
  1716. LogWarning("Unable to parse *MESH_FACE Element: Unexpected EOL. "
  1717. "Vertex index ecpected [#4]");
  1718. SkipToNextToken();
  1719. return;
  1720. }
  1721. out.mIndices[iIndex] = strtol10(m_szFile,&m_szFile);
  1722. }
  1723. // now we need to skip the AB, BC, CA blocks.
  1724. while (true)
  1725. {
  1726. if ('*' == *m_szFile)break;
  1727. if (IsLineEnd(*m_szFile))
  1728. {
  1729. //iLineNumber++;
  1730. return;
  1731. }
  1732. m_szFile++;
  1733. }
  1734. // parse the smoothing group of the face
  1735. if (TokenMatch(m_szFile,"*MESH_SMOOTHING",15))
  1736. {
  1737. if(!SkipSpaces(&m_szFile))
  1738. {
  1739. LogWarning("Unable to parse *MESH_SMOOTHING Element: "
  1740. "Unexpected EOL. Smoothing group(s) expected [#5]");
  1741. SkipToNextToken();
  1742. return;
  1743. }
  1744. // parse smoothing groups until we don_t anymore see commas
  1745. // FIX: There needn't always be a value, sad but true
  1746. while (true)
  1747. {
  1748. if (*m_szFile < '9' && *m_szFile >= '0')
  1749. {
  1750. out.iSmoothGroup |= (1 << strtol10(m_szFile,&m_szFile));
  1751. }
  1752. SkipSpaces(&m_szFile);
  1753. if (',' != *m_szFile)
  1754. {
  1755. break;
  1756. }
  1757. ++m_szFile;
  1758. SkipSpaces(&m_szFile);
  1759. }
  1760. }
  1761. // *MESH_MTLID is optional, too
  1762. while (true)
  1763. {
  1764. if ('*' == *m_szFile)break;
  1765. if (IsLineEnd(*m_szFile))
  1766. {
  1767. return;
  1768. }
  1769. m_szFile++;
  1770. }
  1771. if (TokenMatch(m_szFile,"*MESH_MTLID",11))
  1772. {
  1773. if(!SkipSpaces(&m_szFile))
  1774. {
  1775. LogWarning("Unable to parse *MESH_MTLID Element: Unexpected EOL. "
  1776. "Material index expected [#6]");
  1777. SkipToNextToken();
  1778. return;
  1779. }
  1780. out.iMaterial = strtol10(m_szFile,&m_szFile);
  1781. }
  1782. return;
  1783. }
  1784. // ------------------------------------------------------------------------------------------------
  1785. void Parser::ParseLV4MeshLongTriple(unsigned int* apOut)
  1786. {
  1787. ai_assert(NULL != apOut);
  1788. for (unsigned int i = 0; i < 3;++i)
  1789. ParseLV4MeshLong(apOut[i]);
  1790. }
  1791. // ------------------------------------------------------------------------------------------------
  1792. void Parser::ParseLV4MeshLongTriple(unsigned int* apOut, unsigned int& rIndexOut)
  1793. {
  1794. ai_assert(NULL != apOut);
  1795. // parse the index
  1796. ParseLV4MeshLong(rIndexOut);
  1797. // parse the three others
  1798. ParseLV4MeshLongTriple(apOut);
  1799. }
  1800. // ------------------------------------------------------------------------------------------------
  1801. void Parser::ParseLV4MeshFloatTriple(float* apOut, unsigned int& rIndexOut)
  1802. {
  1803. ai_assert(NULL != apOut);
  1804. // parse the index
  1805. ParseLV4MeshLong(rIndexOut);
  1806. // parse the three others
  1807. ParseLV4MeshFloatTriple(apOut);
  1808. }
  1809. // ------------------------------------------------------------------------------------------------
  1810. void Parser::ParseLV4MeshFloatTriple(float* apOut)
  1811. {
  1812. ai_assert(NULL != apOut);
  1813. for (unsigned int i = 0; i < 3;++i)
  1814. ParseLV4MeshFloat(apOut[i]);
  1815. }
  1816. // ------------------------------------------------------------------------------------------------
  1817. void Parser::ParseLV4MeshFloat(float& fOut)
  1818. {
  1819. // skip spaces and tabs
  1820. if(!SkipSpaces(&m_szFile))
  1821. {
  1822. // LOG
  1823. LogWarning("Unable to parse float: unexpected EOL [#1]");
  1824. fOut = 0.0f;
  1825. ++iLineNumber;
  1826. return;
  1827. }
  1828. // parse the first float
  1829. m_szFile = fast_atof_move(m_szFile,fOut);
  1830. }
  1831. // ------------------------------------------------------------------------------------------------
  1832. void Parser::ParseLV4MeshLong(unsigned int& iOut)
  1833. {
  1834. // skip spaces and tabs
  1835. if(!SkipSpaces(&m_szFile))
  1836. {
  1837. // LOG
  1838. LogWarning("Unable to parse long: unexpected EOL [#1]");
  1839. iOut = 0;
  1840. ++iLineNumber;
  1841. return;
  1842. }
  1843. // parse the value
  1844. iOut = strtol10(m_szFile,&m_szFile);
  1845. }