ASEParser.cpp 52 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792
  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 "ASELoader.h"
  36. #include "MaterialSystem.h"
  37. #include "../include/DefaultLogger.h"
  38. #include "fast_atof.h"
  39. #include "../include/IOStream.h"
  40. #include "../include/IOSystem.h"
  41. #include "../include/aiMesh.h"
  42. #include "../include/aiScene.h"
  43. #include "../include/aiAssert.h"
  44. #include <boost/scoped_ptr.hpp>
  45. using namespace Assimp;
  46. using namespace Assimp::ASE;
  47. #if (defined BLUBB)
  48. # undef BLUBB
  49. #endif
  50. #define BLUBB(_message_) \
  51. {this->LogError(_message_);return;}
  52. // ------------------------------------------------------------------------------------------------
  53. Parser::Parser (const char* szFile)
  54. {
  55. ai_assert(NULL != szFile);
  56. this->m_szFile = szFile;
  57. // makre sure that the color values are invalid
  58. this->m_clrBackground.r = std::numeric_limits<float>::quiet_NaN();
  59. this->m_clrAmbient.r = std::numeric_limits<float>::quiet_NaN();
  60. this->iLineNumber = 0;
  61. }
  62. // ------------------------------------------------------------------------------------------------
  63. void Parser::LogWarning(const char* szWarn)
  64. {
  65. ai_assert(NULL != szWarn);
  66. ai_assert(strlen(szWarn) < 950);
  67. char szTemp[1024];
  68. sprintf(szTemp,"Line %i: %s",this->iLineNumber,szWarn);
  69. // output the warning to the logger ...
  70. DefaultLogger::get()->warn(szTemp);
  71. }
  72. // ------------------------------------------------------------------------------------------------
  73. void Parser::LogError(const char* szWarn)
  74. {
  75. ai_assert(NULL != szWarn);
  76. ai_assert(strlen(szWarn) < 950);
  77. char szTemp[1024];
  78. sprintf(szTemp,"Line %i: %s",this->iLineNumber,szWarn);
  79. // throw an exception
  80. throw new ImportErrorException(szTemp);
  81. }
  82. // ------------------------------------------------------------------------------------------------
  83. bool Parser::SkipToNextToken()
  84. {
  85. while (true)
  86. {
  87. if ('*' == *this->m_szFile || '}' == *this->m_szFile || '{' == *this->m_szFile)return true;
  88. if ('\0' == *this->m_szFile)return false;
  89. ++this->m_szFile;
  90. }
  91. }
  92. // ------------------------------------------------------------------------------------------------
  93. bool Parser::SkipOpeningBracket()
  94. {
  95. if (!SkipSpaces(this->m_szFile,&this->m_szFile))return false;
  96. if ('{' != *this->m_szFile)
  97. {
  98. this->LogWarning("Unable to parse block: Unexpected character, \'{\' expected [#1]");
  99. return false;
  100. }
  101. this->SkipToNextToken();
  102. return true;
  103. }
  104. // ------------------------------------------------------------------------------------------------
  105. bool Parser::SkipSection()
  106. {
  107. // must handle subsections ...
  108. int iCnt = 0;
  109. while (true)
  110. {
  111. if ('}' == *this->m_szFile)
  112. {
  113. --iCnt;
  114. if (0 == iCnt)
  115. {
  116. // go to the next valid token ...
  117. ++this->m_szFile;
  118. this->SkipToNextToken();
  119. return true;
  120. }
  121. }
  122. else if ('{' == *this->m_szFile)
  123. {
  124. ++iCnt;
  125. }
  126. else if ('\0' == *this->m_szFile)
  127. {
  128. this->LogWarning("Unable to parse block: Unexpected EOF, closing bracket \'}\' was expected [#1]");
  129. return false;
  130. }
  131. else if(IsLineEnd(*this->m_szFile))++this->iLineNumber;
  132. ++this->m_szFile;
  133. }
  134. }
  135. // ------------------------------------------------------------------------------------------------
  136. void Parser::Parse()
  137. {
  138. int iDepth = 0;
  139. while (true)
  140. {
  141. if ('*' == *this->m_szFile)
  142. {
  143. // version should be 200. Validate this ...
  144. if (0 == strncmp(this->m_szFile,"*3DSMAX_ASCIIEXPORT",19) &&
  145. IsSpaceOrNewLine(*(this->m_szFile+19)))
  146. {
  147. this->m_szFile+=20;
  148. unsigned int iVersion;
  149. this->ParseLV4MeshLong(iVersion);
  150. if (200 != iVersion)
  151. {
  152. this->LogWarning("Unknown file format version: *3DSMAX_ASCIIEXPORT should \
  153. be 200. Continuing happily ...");
  154. }
  155. }
  156. // main scene information
  157. if (0 == strncmp(this->m_szFile,"*SCENE",6) &&
  158. IsSpaceOrNewLine(*(this->m_szFile+6)))
  159. {
  160. this->m_szFile+=7;
  161. this->ParseLV1SceneBlock();
  162. }
  163. // material list
  164. if (0 == strncmp(this->m_szFile,"*MATERIAL_LIST",14) &&
  165. IsSpaceOrNewLine(*(this->m_szFile+14)))
  166. {
  167. this->m_szFile+=15;
  168. this->ParseLV1MaterialListBlock();
  169. }
  170. // geometric object (mesh)
  171. if (0 == strncmp(this->m_szFile,"*GEOMOBJECT",11) &&
  172. IsSpaceOrNewLine(*(this->m_szFile+11)))
  173. {
  174. this->m_szFile+=12;
  175. this->m_vMeshes.push_back(Mesh());
  176. this->ParseLV1GeometryObjectBlock(this->m_vMeshes.back());
  177. }
  178. // ignore comments, lights and cameras
  179. }
  180. if ('{' == *this->m_szFile)iDepth++;
  181. if ('}' == *this->m_szFile)
  182. {
  183. if (0 == --iDepth){++this->m_szFile;this->SkipToNextToken();return;}
  184. }
  185. if ('\0' == *this->m_szFile)
  186. {
  187. // END OF FILE ... why not?
  188. return;
  189. }
  190. else if(IsLineEnd(*this->m_szFile))++this->iLineNumber;
  191. ++this->m_szFile;
  192. }
  193. return;
  194. }
  195. // ------------------------------------------------------------------------------------------------
  196. void Parser::ParseLV1SceneBlock()
  197. {
  198. int iDepth = 0;
  199. while (true)
  200. {
  201. if ('*' == *this->m_szFile)
  202. {
  203. if (0 == strncmp(this->m_szFile,"*SCENE_BACKGROUND_STATIC",24) &&
  204. IsSpaceOrNewLine(*(this->m_szFile+24)))
  205. {
  206. this->m_szFile+=25;
  207. // parse a color triple and assume it is really the bg color
  208. this->ParseLV4MeshFloatTriple( &this->m_clrBackground.r );
  209. }
  210. if (0 == strncmp(this->m_szFile,"*SCENE_AMBIENT_STATIC",21) &&
  211. IsSpaceOrNewLine(*(this->m_szFile+21)))
  212. {
  213. this->m_szFile+=22;
  214. // parse a color triple and assume it is really the bg color
  215. this->ParseLV4MeshFloatTriple( &this->m_clrAmbient.r );
  216. }
  217. }
  218. if ('{' == *this->m_szFile)iDepth++;
  219. if ('}' == *this->m_szFile)
  220. {
  221. if (0 == --iDepth){++this->m_szFile;this->SkipToNextToken();return;}
  222. }
  223. else if ('\0' == *this->m_szFile)
  224. {
  225. // END OF FILE ... why not?
  226. return;
  227. }
  228. else if(IsLineEnd(*this->m_szFile))++this->iLineNumber;
  229. ++this->m_szFile;
  230. }
  231. return;
  232. }
  233. // ------------------------------------------------------------------------------------------------
  234. void Parser::ParseLV1MaterialListBlock()
  235. {
  236. int iDepth = 0;
  237. unsigned int iMaterialCount = 0;
  238. while (true)
  239. {
  240. if ('*' == *this->m_szFile)
  241. {
  242. if (0 == strncmp(this->m_szFile,"*MATERIAL_COUNT",15) &&
  243. IsSpaceOrNewLine(*(this->m_szFile+15)))
  244. {
  245. this->m_szFile+=16;
  246. this->ParseLV4MeshLong(iMaterialCount);
  247. // now allocate enough storage to hold all materials
  248. this->m_vMaterials.resize(iMaterialCount);
  249. }
  250. if (0 == strncmp(this->m_szFile,"*MATERIAL",9) &&
  251. IsSpaceOrNewLine(*(this->m_szFile+9)))
  252. {
  253. this->m_szFile+=10;
  254. unsigned int iIndex = 0;
  255. this->ParseLV4MeshLong(iIndex);
  256. if (iIndex >= iMaterialCount)
  257. {
  258. this->LogWarning("Out of range: material index is too large");
  259. iIndex = iMaterialCount-1;
  260. }
  261. // get a reference to the material
  262. Material& sMat = this->m_vMaterials[iIndex];
  263. // skip the '{'
  264. this->SkipOpeningBracket();
  265. // parse the material block
  266. this->ParseLV2MaterialBlock(sMat);
  267. }
  268. }
  269. if ('{' == *this->m_szFile)iDepth++;
  270. if ('}' == *this->m_szFile)
  271. {
  272. if (0 == --iDepth){++this->m_szFile;this->SkipToNextToken();return;}
  273. }
  274. else if ('\0' == *this->m_szFile)
  275. {
  276. // END OF FILE ... why not?
  277. return;
  278. }
  279. else if(IsLineEnd(*this->m_szFile))++this->iLineNumber;
  280. ++this->m_szFile;
  281. }
  282. return;
  283. }
  284. // ------------------------------------------------------------------------------------------------
  285. void Parser::ParseLV2MaterialBlock(ASE::Material& mat)
  286. {
  287. int iDepth = 0;
  288. unsigned int iNumSubMaterials = 0;
  289. while (true)
  290. {
  291. if ('*' == *this->m_szFile)
  292. {
  293. if (0 == strncmp(this->m_szFile,"*MATERIAL_NAME",14) &&
  294. IsSpaceOrNewLine(*(this->m_szFile+14)))
  295. {
  296. this->m_szFile+=15;
  297. // NOTE: The name could also be the texture in some cases
  298. // be prepared that this might occur ...
  299. if (!SkipSpaces(this->m_szFile,&this->m_szFile))
  300. BLUBB("Unable to parse *MATERIAL_NAME block: Unexpected EOL")
  301. const char* sz = this->m_szFile;
  302. while (!IsSpaceOrNewLine(*sz))sz++;
  303. mat.mName = std::string(this->m_szFile,(uintptr_t)sz-(uintptr_t)this->m_szFile);
  304. this->m_szFile = sz;
  305. }
  306. // ambient material color
  307. if (0 == strncmp(this->m_szFile,"*MATERIAL_AMBIENT",17) &&
  308. IsSpaceOrNewLine(*(this->m_szFile+17)))
  309. {
  310. this->m_szFile+=18;
  311. this->ParseLV4MeshFloatTriple(&mat.mAmbient.r);
  312. }
  313. // diffuse material color
  314. if (0 == strncmp(this->m_szFile,"*MATERIAL_DIFFUSE",17) &&
  315. IsSpaceOrNewLine(*(this->m_szFile+17)))
  316. {
  317. this->m_szFile+=18;
  318. this->ParseLV4MeshFloatTriple(&mat.mDiffuse.r);
  319. }
  320. // specular material color
  321. if (0 == strncmp(this->m_szFile,"*MATERIAL_SPECULAR",18) &&
  322. IsSpaceOrNewLine(*(this->m_szFile+18)))
  323. {
  324. this->m_szFile+=19;
  325. this->ParseLV4MeshFloatTriple(&mat.mSpecular.r);
  326. }
  327. // material shading type
  328. if (0 == strncmp(this->m_szFile,"*MATERIAL_SHADING",17) &&
  329. IsSpaceOrNewLine(*(this->m_szFile+17)))
  330. {
  331. this->m_szFile+=18;
  332. if (0 == strncmp(this->m_szFile,"Blinn",5) &&
  333. IsSpaceOrNewLine(*(this->m_szFile+5)))
  334. {
  335. mat.mShading = Dot3DSFile::Blinn;
  336. this->m_szFile+=6;
  337. }
  338. else if (0 == strncmp(this->m_szFile,"Phong",5) &&
  339. IsSpaceOrNewLine(*(this->m_szFile+5)))
  340. {
  341. mat.mShading = Dot3DSFile::Phong;
  342. this->m_szFile+=6;
  343. }
  344. else if (0 == strncmp(this->m_szFile,"Flat",4) &&
  345. IsSpaceOrNewLine(*(this->m_szFile+4)))
  346. {
  347. mat.mShading = Dot3DSFile::Flat;
  348. this->m_szFile+=5;
  349. }
  350. else if (0 == strncmp(this->m_szFile,"Wire",4) &&
  351. IsSpaceOrNewLine(*(this->m_szFile+4)))
  352. {
  353. mat.mShading = Dot3DSFile::Wire;
  354. this->m_szFile+=5;
  355. }
  356. else
  357. {
  358. // assume gouraud shading
  359. mat.mShading = Dot3DSFile::Gouraud;
  360. this->SkipToNextToken();
  361. }
  362. }
  363. // material transparency
  364. if (0 == strncmp(this->m_szFile,"*MATERIAL_TRANSPARENCY",22) &&
  365. IsSpaceOrNewLine(*(this->m_szFile+22)))
  366. {
  367. this->m_szFile+=23;
  368. this->ParseLV4MeshFloat(mat.mTransparency);
  369. mat.mTransparency = 1.0f - mat.mTransparency;
  370. }
  371. // material self illumination
  372. if (0 == strncmp(this->m_szFile,"*MATERIAL_SELFILLUM",19) &&
  373. IsSpaceOrNewLine(*(this->m_szFile+19)))
  374. {
  375. this->m_szFile+=20;
  376. float f = 0.0f;
  377. this->ParseLV4MeshFloat(f);
  378. mat.mEmissive.r = f;
  379. mat.mEmissive.g = f;
  380. mat.mEmissive.b = f;
  381. }
  382. // material shininess
  383. if (0 == strncmp(this->m_szFile,"*MATERIAL_SHINE",15) &&
  384. IsSpaceOrNewLine(*(this->m_szFile+15)))
  385. {
  386. this->m_szFile+=16;
  387. this->ParseLV4MeshFloat(mat.mSpecularExponent);
  388. mat.mSpecularExponent *= 15;
  389. }
  390. // material shininess strength
  391. if (0 == strncmp(this->m_szFile,"*MATERIAL_SHINESTRENGTH",23) &&
  392. IsSpaceOrNewLine(*(this->m_szFile+23)))
  393. {
  394. this->m_szFile+=24;
  395. this->ParseLV4MeshFloat(mat.mShininessStrength);
  396. }
  397. // diffuse color map
  398. if (0 == strncmp(this->m_szFile,"*MAP_DIFFUSE",12) &&
  399. IsSpaceOrNewLine(*(this->m_szFile+12)))
  400. {
  401. this->m_szFile+=13;
  402. // skip the opening bracket
  403. this->SkipOpeningBracket();
  404. // parse the texture block
  405. this->ParseLV3MapBlock(mat.sTexDiffuse);
  406. }
  407. // ambient color map
  408. if (0 == strncmp(this->m_szFile,"*MAP_AMBIENT",12) &&
  409. IsSpaceOrNewLine(*(this->m_szFile+12)))
  410. {
  411. this->m_szFile+=13;
  412. // skip the opening bracket
  413. this->SkipOpeningBracket();
  414. // parse the texture block
  415. this->ParseLV3MapBlock(mat.sTexAmbient);
  416. }
  417. // specular color map
  418. if (0 == strncmp(this->m_szFile,"*MAP_SPECULAR",13) &&
  419. IsSpaceOrNewLine(*(this->m_szFile+13)))
  420. {
  421. this->m_szFile+=14;
  422. // skip the opening bracket
  423. this->SkipOpeningBracket();
  424. // parse the texture block
  425. this->ParseLV3MapBlock(mat.sTexSpecular);
  426. }
  427. // opacity map
  428. if (0 == strncmp(this->m_szFile,"*MAP_OPACITY",12) &&
  429. IsSpaceOrNewLine(*(this->m_szFile+12)))
  430. {
  431. this->m_szFile+=13;
  432. // skip the opening bracket
  433. this->SkipOpeningBracket();
  434. // parse the texture block
  435. this->ParseLV3MapBlock(mat.sTexOpacity);
  436. }
  437. // emissive map
  438. if (0 == strncmp(this->m_szFile,"*MAP_SELFILLUM",14) &&
  439. IsSpaceOrNewLine(*(this->m_szFile+14)))
  440. {
  441. this->m_szFile+=15;
  442. // skip the opening bracket
  443. this->SkipOpeningBracket();
  444. // parse the texture block
  445. this->ParseLV3MapBlock(mat.sTexEmissive);
  446. }
  447. // bump map
  448. if (0 == strncmp(this->m_szFile,"*MAP_BUMP",9) &&
  449. IsSpaceOrNewLine(*(this->m_szFile+9)))
  450. {
  451. this->m_szFile+=10;
  452. // skip the opening bracket
  453. this->SkipOpeningBracket();
  454. // parse the texture block
  455. this->ParseLV3MapBlock(mat.sTexBump);
  456. }
  457. // specular/shininess map
  458. if (0 == strncmp(this->m_szFile,"*MAP_SHINE",10) &&
  459. IsSpaceOrNewLine(*(this->m_szFile+10)))
  460. {
  461. this->m_szFile+=11;
  462. // skip the opening bracket
  463. this->SkipOpeningBracket();
  464. // parse the texture block
  465. this->ParseLV3MapBlock(mat.sTexShininess);
  466. }
  467. // number of submaterials
  468. if (0 == strncmp(this->m_szFile,"*NUMSUBMTLS",11) &&
  469. IsSpaceOrNewLine(*(this->m_szFile+11)))
  470. {
  471. this->m_szFile+=12;
  472. this->ParseLV4MeshLong(iNumSubMaterials);
  473. // allocate enough storage
  474. mat.avSubMaterials.resize(iNumSubMaterials);
  475. }
  476. // submaterial chunks
  477. if (0 == strncmp(this->m_szFile,"*SUBMATERIAL",12) &&
  478. IsSpaceOrNewLine(*(this->m_szFile+12)))
  479. {
  480. this->m_szFile+=13;
  481. unsigned int iIndex = 0;
  482. this->ParseLV4MeshLong(iIndex);
  483. if (iIndex >= iNumSubMaterials)
  484. {
  485. this->LogWarning("Out of range: submaterial index is too large");
  486. iIndex = iNumSubMaterials-1;
  487. }
  488. // get a reference to the material
  489. Material& sMat = mat.avSubMaterials[iIndex];
  490. // skip the '{'
  491. this->SkipOpeningBracket();
  492. // parse the material block
  493. this->ParseLV2MaterialBlock(sMat);
  494. }
  495. }
  496. if ('{' == *this->m_szFile)iDepth++;
  497. if ('}' == *this->m_szFile)
  498. {
  499. if (0 == --iDepth){++this->m_szFile;this->SkipToNextToken();return;}
  500. }
  501. else if ('\0' == *this->m_szFile)
  502. {
  503. // END OF FILE ... this is a level2 block, this can't be
  504. BLUBB("Unable to finish parsing a lv2 material block. Unexpected EOF")
  505. }
  506. else if(IsLineEnd(*this->m_szFile))++this->iLineNumber;
  507. ++this->m_szFile;
  508. }
  509. return;
  510. }
  511. // ------------------------------------------------------------------------------------------------
  512. void Parser::ParseLV3MapBlock(Texture& map)
  513. {
  514. int iDepth = 0;
  515. unsigned int iNumSubMaterials = 0;
  516. while (true)
  517. {
  518. if ('*' == *this->m_szFile)
  519. {
  520. // path to the texture
  521. if (0 == strncmp(this->m_szFile,"*BITMAP" ,7) &&
  522. IsSpaceOrNewLine(*(this->m_szFile+7)))
  523. {
  524. this->m_szFile+=8;
  525. // NOTE: The name could also be the texture in some cases
  526. // be prepared that this might occur ...
  527. if (!SkipSpaces(this->m_szFile,&this->m_szFile))
  528. BLUBB("Unable to parse *BITMAP block: Unexpected EOL")
  529. // there must be "
  530. if ('\"' != *this->m_szFile)
  531. BLUBB("Unable to parse *BITMAP block: Path is expected to be enclosed in double quotation marks")
  532. ++this->m_szFile;
  533. const char* sz = this->m_szFile;
  534. while (true)
  535. {
  536. if ('\"' == *sz)break;
  537. else if ('\0' == sz)
  538. {
  539. BLUBB("Unable to parse *BITMAP block: Path is expected to be enclosed in double quotation marks \
  540. but EOF was reached before a closing quotation mark was found")
  541. }
  542. sz++;
  543. }
  544. map.mMapName = std::string(this->m_szFile,(uintptr_t)sz-(uintptr_t)this->m_szFile);
  545. this->m_szFile = sz;
  546. }
  547. // offset on the u axis
  548. if (0 == strncmp(this->m_szFile,"*UVW_U_OFFSET" ,13) &&
  549. IsSpaceOrNewLine(*(this->m_szFile+13)))
  550. {
  551. this->m_szFile+=14;
  552. this->ParseLV4MeshFloat(map.mOffsetU);
  553. }
  554. // offset on the v axis
  555. if (0 == strncmp(this->m_szFile,"*UVW_V_OFFSET" ,13) &&
  556. IsSpaceOrNewLine(*(this->m_szFile+13)))
  557. {
  558. this->m_szFile+=14;
  559. this->ParseLV4MeshFloat(map.mOffsetV);
  560. }
  561. // tiling on the u axis
  562. if (0 == strncmp(this->m_szFile,"*UVW_U_TILING" ,13) &&
  563. IsSpaceOrNewLine(*(this->m_szFile+13)))
  564. {
  565. this->m_szFile+=14;
  566. this->ParseLV4MeshFloat(map.mScaleU);
  567. }
  568. // tiling on the v axis
  569. if (0 == strncmp(this->m_szFile,"*UVW_V_TILING" ,13) &&
  570. IsSpaceOrNewLine(*(this->m_szFile+13)))
  571. {
  572. this->m_szFile+=14;
  573. this->ParseLV4MeshFloat(map.mScaleV);
  574. }
  575. // rotation around the z-axis
  576. if (0 == strncmp(this->m_szFile,"*UVW_ANGLE" ,10) &&
  577. IsSpaceOrNewLine(*(this->m_szFile+10)))
  578. {
  579. this->m_szFile+=11;
  580. this->ParseLV4MeshFloat(map.mRotation);
  581. }
  582. // map blending factor
  583. if (0 == strncmp(this->m_szFile,"*MAP_AMOUNT" ,11) &&
  584. IsSpaceOrNewLine(*(this->m_szFile+11)))
  585. {
  586. this->m_szFile+=12;
  587. this->ParseLV4MeshFloat(map.mTextureBlend);
  588. }
  589. }
  590. if ('{' == *this->m_szFile)iDepth++;
  591. if ('}' == *this->m_szFile)
  592. {
  593. if (0 == --iDepth){++this->m_szFile;this->SkipToNextToken();return;}
  594. }
  595. else if ('\0' == *this->m_szFile)
  596. {
  597. // END OF FILE ... this is a level3 block, this can't be
  598. BLUBB("Unable to finish parsing a lv3 map block. Unexpected EOF")
  599. }
  600. else if(IsLineEnd(*this->m_szFile))++this->iLineNumber;
  601. ++this->m_szFile;
  602. }
  603. return;
  604. }
  605. // ------------------------------------------------------------------------------------------------
  606. bool Parser::ParseString(std::string& out,const char* szName)
  607. {
  608. char szBuffer[1024];
  609. ai_assert(strlen(szName < 750));
  610. // NOTE: The name could also be the texture in some cases
  611. // be prepared that this might occur ...
  612. if (!SkipSpaces(this->m_szFile,&this->m_szFile))
  613. {
  614. sprintf(szBuffer,"Unable to parse %s block: Unexpected EOL",szName);
  615. this->LogWarning(szBuffer);
  616. return false;
  617. }
  618. // there must be "
  619. if ('\"' != *this->m_szFile)
  620. {
  621. sprintf(szBuffer,"Unable to parse %s block: String is expected "
  622. "to be enclosed in double quotation marks",szName);
  623. this->LogWarning(szBuffer);
  624. return false;
  625. }
  626. ++this->m_szFile;
  627. const char* sz = this->m_szFile;
  628. while (true)
  629. {
  630. if ('\"' == *sz)break;
  631. else if ('\0' == sz)
  632. {
  633. sprintf(szBuffer,"Unable to parse %s block: String is expected to be "
  634. "enclosed in double quotation marks but EOF was reached before a closing "
  635. "quotation mark was found",szName);
  636. this->LogWarning(szBuffer);
  637. return false;
  638. }
  639. sz++;
  640. }
  641. out = std::string(this->m_szFile,(uintptr_t)sz-(uintptr_t)this->m_szFile);
  642. this->m_szFile = sz;
  643. return true;
  644. }
  645. // ------------------------------------------------------------------------------------------------
  646. void Parser::ParseLV1GeometryObjectBlock(ASE::Mesh& mesh)
  647. {
  648. int iDepth = 0;
  649. while (true)
  650. {
  651. if ('*' == *this->m_szFile)
  652. {
  653. // name of the mesh/node
  654. if (0 == strncmp(this->m_szFile,"*NODE_NAME" ,10) &&
  655. IsSpaceOrNewLine(*(this->m_szFile+10)))
  656. {
  657. this->m_szFile+=11;
  658. if(!this->ParseString(mesh.mName,"*NODE_NAME"))
  659. {
  660. this->SkipToNextToken();
  661. continue;
  662. }
  663. }
  664. // name of the parent of the node
  665. if (0 == strncmp(this->m_szFile,"*NODE_PARENT" ,12) &&
  666. IsSpaceOrNewLine(*(this->m_szFile+12)))
  667. {
  668. this->m_szFile+=13;
  669. if(!this->ParseString(mesh.mParent,"*NODE_PARENT"))
  670. {
  671. this->SkipToNextToken();
  672. continue;
  673. }
  674. }
  675. // transformation matrix of the node
  676. if (0 == strncmp(this->m_szFile,"*NODE_TM" ,8) &&
  677. IsSpaceOrNewLine(*(this->m_szFile+8)))
  678. {
  679. this->m_szFile+=9;
  680. this->ParseLV2NodeTransformBlock(mesh);
  681. }
  682. // mesh data
  683. if (0 == strncmp(this->m_szFile,"*MESH" ,5) &&
  684. IsSpaceOrNewLine(*(this->m_szFile+5)))
  685. {
  686. this->m_szFile+=6;
  687. this->ParseLV2MeshBlock(mesh);
  688. }
  689. // mesh material index
  690. else if (0 == strncmp(this->m_szFile,"*MATERIAL_REF" ,13) &&
  691. IsSpaceOrNewLine(*(this->m_szFile+13)))
  692. {
  693. this->m_szFile+=14;
  694. this->ParseLV4MeshLong(mesh.iMaterialIndex);
  695. }
  696. }
  697. if ('{' == *this->m_szFile)iDepth++;
  698. if ('}' == *this->m_szFile)
  699. {
  700. if (0 == --iDepth){++this->m_szFile;this->SkipToNextToken();return;}
  701. }
  702. else if ('\0' == *this->m_szFile)
  703. {
  704. // END OF FILE ... this is a level1 block, this can be
  705. return;
  706. }
  707. else if(IsLineEnd(*this->m_szFile))++this->iLineNumber;
  708. ++this->m_szFile;
  709. }
  710. return;
  711. }
  712. // ------------------------------------------------------------------------------------------------
  713. void Parser::ParseLV2NodeTransformBlock(ASE::Mesh& mesh)
  714. {
  715. int iDepth = 0;
  716. while (true)
  717. {
  718. if ('*' == *this->m_szFile)
  719. {
  720. // first row of the transformation matrix
  721. if (0 == strncmp(this->m_szFile,"*TM_ROW0" ,8) &&
  722. IsSpaceOrNewLine(*(this->m_szFile+8)))
  723. {
  724. this->m_szFile+=9;
  725. this->ParseLV4MeshFloatTriple(mesh.mTransform[0]);
  726. }
  727. // second row of the transformation matrix
  728. if (0 == strncmp(this->m_szFile,"*TM_ROW1" ,8) &&
  729. IsSpaceOrNewLine(*(this->m_szFile+8)))
  730. {
  731. this->m_szFile+=9;
  732. this->ParseLV4MeshFloatTriple(mesh.mTransform[1]);
  733. }
  734. // third row of the transformation matrix
  735. if (0 == strncmp(this->m_szFile,"*TM_ROW2" ,8) &&
  736. IsSpaceOrNewLine(*(this->m_szFile+8)))
  737. {
  738. this->m_szFile+=9;
  739. this->ParseLV4MeshFloatTriple(mesh.mTransform[2]);
  740. }
  741. // fourth row of the transformation matrix
  742. if (0 == strncmp(this->m_szFile,"*TM_ROW3" ,8) &&
  743. IsSpaceOrNewLine(*(this->m_szFile+8)))
  744. {
  745. this->m_szFile+=9;
  746. this->ParseLV4MeshFloatTriple(mesh.mTransform[3]);
  747. }
  748. }
  749. if ('{' == *this->m_szFile)iDepth++;
  750. if ('}' == *this->m_szFile)
  751. {
  752. if (0 == --iDepth){++this->m_szFile;this->SkipToNextToken();return;}
  753. }
  754. else if ('\0' == *this->m_szFile)
  755. {
  756. // END OF FILE ... this is a level2 block, this can't be
  757. BLUBB("Unable to finish parsing a lv2 node transform block. Unexpected EOF")
  758. }
  759. else if(IsLineEnd(*this->m_szFile))++this->iLineNumber;
  760. ++this->m_szFile;
  761. }
  762. return;
  763. }
  764. // ------------------------------------------------------------------------------------------------
  765. void Parser::ParseLV2MeshBlock(ASE::Mesh& mesh)
  766. {
  767. unsigned int iNumVertices = 0;
  768. unsigned int iNumFaces = 0;
  769. unsigned int iNumTVertices = 0;
  770. unsigned int iNumTFaces = 0;
  771. unsigned int iNumCVertices = 0;
  772. unsigned int iNumCFaces = 0;
  773. int iDepth = 0;
  774. while (true)
  775. {
  776. if ('*' == *this->m_szFile)
  777. {
  778. // Number of vertices in the mesh
  779. if (0 == strncmp(this->m_szFile,"*MESH_NUMVERTEX" ,15) &&
  780. IsSpaceOrNewLine(*(this->m_szFile+15)))
  781. {
  782. this->m_szFile+=16;
  783. this->ParseLV4MeshLong(iNumVertices);
  784. }
  785. // Number of texture coordinates in the mesh
  786. if (0 == strncmp(this->m_szFile,"*MESH_NUMTVERTEX" ,16) &&
  787. IsSpaceOrNewLine(*(this->m_szFile+16)))
  788. {
  789. this->m_szFile+=17;
  790. this->ParseLV4MeshLong(iNumTVertices);
  791. }
  792. // Number of vertex colors in the mesh
  793. if (0 == strncmp(this->m_szFile,"*MESH_NUMCVERTEX" ,16) &&
  794. IsSpaceOrNewLine(*(this->m_szFile+16)))
  795. {
  796. this->m_szFile+=17;
  797. this->ParseLV4MeshLong(iNumCVertices);
  798. }
  799. // Number of regular faces in the mesh
  800. if (0 == strncmp(this->m_szFile,"*MESH_NUMFACES" ,14) &&
  801. IsSpaceOrNewLine(*(this->m_szFile+14)))
  802. {
  803. this->m_szFile+=15;
  804. this->ParseLV4MeshLong(iNumFaces);
  805. }
  806. // Number of UVWed faces in the mesh
  807. if (0 == strncmp(this->m_szFile,"*MESH_NUMTVFACES" ,16) &&
  808. IsSpaceOrNewLine(*(this->m_szFile+16)))
  809. {
  810. this->m_szFile+=17;
  811. this->ParseLV4MeshLong(iNumTFaces);
  812. }
  813. // Number of colored faces in the mesh
  814. if (0 == strncmp(this->m_szFile,"*MESH_NUMCVFACES" ,16) &&
  815. IsSpaceOrNewLine(*(this->m_szFile+16)))
  816. {
  817. this->m_szFile+=17;
  818. this->ParseLV4MeshLong(iNumCFaces);
  819. }
  820. // mesh vertex list block
  821. if (0 == strncmp(this->m_szFile,"*MESH_VERTEX_LIST" ,17) &&
  822. IsSpaceOrNewLine(*(this->m_szFile+17)))
  823. {
  824. this->m_szFile+=18;
  825. this->ParseLV3MeshVertexListBlock(iNumVertices,mesh);
  826. }
  827. // mesh face list block
  828. if (0 == strncmp(this->m_szFile,"*MESH_FACE_LIST" ,15) &&
  829. IsSpaceOrNewLine(*(this->m_szFile+15)))
  830. {
  831. this->m_szFile+=16;
  832. this->SkipOpeningBracket();
  833. this->ParseLV3MeshFaceListBlock(iNumFaces,mesh);
  834. }
  835. // mesh texture vertex list block
  836. if (0 == strncmp(this->m_szFile,"*MESH_TVERTLIST" ,15) &&
  837. IsSpaceOrNewLine(*(this->m_szFile+15)))
  838. {
  839. this->m_szFile+=16;
  840. this->SkipOpeningBracket();
  841. this->ParseLV3MeshTListBlock(iNumTVertices,mesh);
  842. }
  843. // mesh texture face block
  844. if (0 == strncmp(this->m_szFile,"*MESH_TFACELIST" ,15) &&
  845. IsSpaceOrNewLine(*(this->m_szFile+15)))
  846. {
  847. this->m_szFile+=16;
  848. this->SkipOpeningBracket();
  849. this->ParseLV3MeshTFaceListBlock(iNumTFaces,mesh);
  850. }
  851. // mesh color vertex list block
  852. if (0 == strncmp(this->m_szFile,"*MESH_CVERTLIST" ,15) &&
  853. IsSpaceOrNewLine(*(this->m_szFile+15)))
  854. {
  855. this->m_szFile+=16;
  856. this->SkipOpeningBracket();
  857. this->ParseLV3MeshCListBlock(iNumCVertices,mesh);
  858. }
  859. // mesh color face block
  860. if (0 == strncmp(this->m_szFile,"*MESH_CFACELIST" ,15) &&
  861. IsSpaceOrNewLine(*(this->m_szFile+15)))
  862. {
  863. this->m_szFile+=16;
  864. this->SkipOpeningBracket();
  865. this->ParseLV3MeshCFaceListBlock(iNumCFaces,mesh);
  866. }
  867. // another mesh UV channel ...
  868. if (0 == strncmp(this->m_szFile,"*MESH_MAPPINGCHANNEL" ,20) &&
  869. IsSpaceOrNewLine(*(this->m_szFile+20)))
  870. {
  871. this->m_szFile+=21;
  872. unsigned int iIndex = 0;
  873. this->ParseLV4MeshLong(iIndex);
  874. if (iIndex < 2)
  875. {
  876. this->LogWarning("Mapping channel has an invalid index. Skipping UV channel");
  877. // skip it ...
  878. this->SkipOpeningBracket();
  879. this->SkipSection();
  880. }
  881. if (iIndex > AI_MAX_NUMBER_OF_TEXTURECOORDS)
  882. {
  883. this->LogWarning("Too many UV channels specified. Skipping channel ..");
  884. // skip it ...
  885. this->SkipOpeningBracket();
  886. this->SkipSection();
  887. }
  888. else
  889. {
  890. // skip the '{'
  891. this->SkipOpeningBracket();
  892. // parse the mapping channel
  893. this->ParseLV3MappingChannel(iIndex-1,mesh);
  894. }
  895. }
  896. // mesh animation keyframe. Not supported
  897. else if (0 == strncmp(this->m_szFile,"*MESH_ANIMATION" ,15) &&
  898. IsSpaceOrNewLine(*(this->m_szFile+15)))
  899. {
  900. this->m_szFile+=16;
  901. this->LogWarning("Found *MESH_ANIMATION element in ASE/ASK file. "
  902. "Keyframe animation is not supported by Assimp, this element "
  903. "will be ignored");
  904. }
  905. // mesh animation keyframe. Not supported
  906. else if (0 == strncmp(this->m_szFile,"*MESH_WEIGHTS" ,13) &&
  907. IsSpaceOrNewLine(*(this->m_szFile+13)))
  908. {
  909. this->m_szFile+=14;
  910. this->ParseLV3MeshWeightsBlock(mesh);
  911. }
  912. }
  913. if ('{' == *this->m_szFile)iDepth++;
  914. if ('}' == *this->m_szFile)
  915. {
  916. if (0 == --iDepth){++this->m_szFile;this->SkipToNextToken();return;}
  917. }
  918. else if ('\0' == *this->m_szFile)
  919. {
  920. // END OF FILE ... this is a level2 block, this can't be
  921. BLUBB("Unable to finish parsing a lv2 mesh block. Unexpected EOF")
  922. }
  923. else if(IsLineEnd(*this->m_szFile))++this->iLineNumber;
  924. ++this->m_szFile;
  925. }
  926. return;
  927. }
  928. // ------------------------------------------------------------------------------------------------
  929. void Parser::ParseLV3MeshWeightsBlock(ASE::Mesh& mesh)
  930. {
  931. unsigned int iNumVertices = 0;
  932. unsigned int iNumBones = 0;
  933. int iDepth = 0;
  934. while (true)
  935. {
  936. if ('*' == *this->m_szFile)
  937. {
  938. // Number of bone vertices ...
  939. if (0 == strncmp(this->m_szFile,"*MESH_NUMVERTEX" ,15) &&
  940. IsSpaceOrNewLine(*(this->m_szFile+15)))
  941. {
  942. this->m_szFile+=16;
  943. this->ParseLV4MeshLong(iNumVertices);
  944. }
  945. // Number of bones
  946. if (0 == strncmp(this->m_szFile,"*MESH_NUMBONE" ,13) &&
  947. IsSpaceOrNewLine(*(this->m_szFile+13)))
  948. {
  949. this->m_szFile+=14;
  950. this->ParseLV4MeshLong(iNumBones);
  951. }
  952. // parse the list of bones
  953. if (0 == strncmp(this->m_szFile,"*MESH_BONE_LIST" ,15) &&
  954. IsSpaceOrNewLine(*(this->m_szFile+15)))
  955. {
  956. this->m_szFile+=16;
  957. this->SkipOpeningBracket();
  958. this->ParseLV4MeshBones(iNumBones,mesh);
  959. }
  960. // parse the list of bones vertices
  961. if (0 == strncmp(this->m_szFile,"*MESH_BONE_VERTEX_LIST" ,22) &&
  962. IsSpaceOrNewLine(*(this->m_szFile+22)))
  963. {
  964. this->m_szFile+=23;
  965. this->SkipOpeningBracket();
  966. this->ParseLV4MeshBonesVertices(iNumVertices,mesh);
  967. }
  968. }
  969. if ('{' == *this->m_szFile)iDepth++;
  970. if ('}' == *this->m_szFile)
  971. {
  972. if (0 == --iDepth){++this->m_szFile;this->SkipToNextToken();return;}
  973. }
  974. else if ('\0' == *this->m_szFile)
  975. {
  976. // END OF FILE ... this is a level2 block, this can't be
  977. BLUBB("Unable to finish parsing a lv2 *MESH_WEIGHTS block. Unexpected EOF")
  978. }
  979. else if(IsLineEnd(*this->m_szFile))++this->iLineNumber;
  980. ++this->m_szFile;
  981. }
  982. return;
  983. }
  984. // ------------------------------------------------------------------------------------------------
  985. void Parser::ParseLV4MeshBones(unsigned int iNumBones,ASE::Mesh& mesh)
  986. {
  987. mesh.mBones.resize(iNumBones);
  988. int iDepth = 0;
  989. while (true)
  990. {
  991. if ('*' == *this->m_szFile)
  992. {
  993. // Mesh bone with name ...
  994. if (0 == strncmp(this->m_szFile,"*MESH_BONE_NAME" ,17) &&
  995. IsSpaceOrNewLine(*(this->m_szFile+17)))
  996. {
  997. this->m_szFile+=18;
  998. // parse an index ...
  999. if(SkipSpaces(this->m_szFile,&this->m_szFile))
  1000. {
  1001. unsigned int iIndex = strtol10(this->m_szFile,&this->m_szFile);
  1002. if (iIndex >= iNumBones)
  1003. {
  1004. iIndex = iNumBones-1;
  1005. this->LogWarning("Bone index is out of bounds. Using the largest valid "
  1006. "bone index instead");
  1007. }
  1008. if (!this->ParseString(mesh.mBones[iIndex].mName,"*MESH_BONE_NAME"))
  1009. {
  1010. this->SkipToNextToken();
  1011. continue;
  1012. }
  1013. }
  1014. }
  1015. }
  1016. if ('{' == *this->m_szFile)iDepth++;
  1017. else if ('}' == *this->m_szFile)
  1018. {
  1019. if (0 == --iDepth){++this->m_szFile;this->SkipToNextToken();return;}
  1020. }
  1021. else if ('\0' == *this->m_szFile)
  1022. {
  1023. // END OF FILE ... this is a level4 block, this can't be
  1024. BLUBB("Unable to finish parsing a lv4 *MESH_BONE_LIST block. Unexpected EOF")
  1025. }
  1026. else if(IsLineEnd(*this->m_szFile))++this->iLineNumber;
  1027. ++this->m_szFile;
  1028. }
  1029. }
  1030. // ------------------------------------------------------------------------------------------------
  1031. void Parser::ParseLV4MeshBonesVertices(unsigned int iNumVertices,ASE::Mesh& mesh)
  1032. {
  1033. mesh.mBoneVertices.resize(iNumVertices);
  1034. int iDepth = 0;
  1035. while (true)
  1036. {
  1037. if ('*' == *this->m_szFile)
  1038. {
  1039. // Mesh bone vertex
  1040. if (0 == strncmp(this->m_szFile,"*MESH_BONE_VERTEX" ,17) &&
  1041. IsSpaceOrNewLine(*(this->m_szFile+17)))
  1042. {
  1043. this->m_szFile+=18;
  1044. // read the vertex index
  1045. unsigned int iIndex = strtol10(this->m_szFile,&this->m_szFile);
  1046. if (iIndex >= mesh.mPositions.size())
  1047. {
  1048. iIndex = mesh.mPositions.size()-1;
  1049. this->LogWarning("Bone vertex index is out of bounds. Using the largest valid "
  1050. "bone vertex index instead");
  1051. }
  1052. // now there there are 3 normal floats, the
  1053. // should be identical to the vertex positions
  1054. // contained in the *VERTEX_LIST block. Well, we check this
  1055. // in debug builds to be sure ;-)
  1056. float afVert[3];
  1057. this->ParseLV4MeshFloatTriple(afVert);
  1058. std::pair<int,float> pairOut;
  1059. while (true)
  1060. {
  1061. // first parse the bone index ...
  1062. if (!SkipSpaces(this->m_szFile,&this->m_szFile))break;
  1063. pairOut.first = strtol10(this->m_szFile,&this->m_szFile);
  1064. // then parse the vertex weight
  1065. if (!SkipSpaces(this->m_szFile,&this->m_szFile))break;
  1066. this->m_szFile = fast_atof_move(this->m_szFile,pairOut.second);
  1067. // -1 designates unused entries
  1068. if (-1 != pairOut.first)
  1069. {
  1070. mesh.mBoneVertices[iIndex].mBoneWeights.push_back(pairOut);
  1071. }
  1072. }
  1073. }
  1074. }
  1075. if ('{' == *this->m_szFile)iDepth++;
  1076. else if ('}' == *this->m_szFile)
  1077. {
  1078. if (0 == --iDepth){++this->m_szFile;this->SkipToNextToken();return;}
  1079. }
  1080. else if ('\0' == *this->m_szFile)
  1081. {
  1082. // END OF FILE ... this is a level4 block, this can't be
  1083. BLUBB("Unable to finish parsing a lv4 *MESH_BONE_VERTEX_LIST block. Unexpected EOF")
  1084. }
  1085. else if(IsLineEnd(*this->m_szFile))++this->iLineNumber;
  1086. ++this->m_szFile;
  1087. }
  1088. return;
  1089. }
  1090. // ------------------------------------------------------------------------------------------------
  1091. void Parser::ParseLV3MeshVertexListBlock(
  1092. unsigned int iNumVertices, ASE::Mesh& mesh)
  1093. {
  1094. // allocate enough storage in the array
  1095. mesh.mPositions.resize(iNumVertices);
  1096. int iDepth = 0;
  1097. while (true)
  1098. {
  1099. if ('*' == *this->m_szFile)
  1100. {
  1101. // Vertex entry
  1102. if (0 == strncmp(this->m_szFile,"*MESH_VERTEX" ,12) &&
  1103. IsSpaceOrNewLine(*(this->m_szFile+12)))
  1104. {
  1105. this->m_szFile+=13;
  1106. aiVector3D vTemp;
  1107. unsigned int iIndex;
  1108. this->ParseLV4MeshFloatTriple(&vTemp.x,iIndex);
  1109. if (iIndex >= iNumVertices)
  1110. {
  1111. this->LogWarning("Vertex has an invalid index. It will be ignored");
  1112. }
  1113. else mesh.mPositions[iIndex] = vTemp;
  1114. }
  1115. }
  1116. if ('{' == *this->m_szFile)iDepth++;
  1117. else if ('}' == *this->m_szFile)
  1118. {
  1119. if (0 == --iDepth){++this->m_szFile;this->SkipToNextToken();return;}
  1120. }
  1121. else if ('\0' == *this->m_szFile)
  1122. {
  1123. // END OF FILE ... this is a level3 block, this can't be
  1124. BLUBB("Unable to finish parsing a lv3 vertex list block. Unexpected EOF")
  1125. }
  1126. else if(IsLineEnd(*this->m_szFile))++this->iLineNumber;
  1127. ++this->m_szFile;
  1128. }
  1129. return;
  1130. }
  1131. // ------------------------------------------------------------------------------------------------
  1132. void Parser::ParseLV3MeshFaceListBlock(unsigned int iNumFaces, ASE::Mesh& mesh)
  1133. {
  1134. // allocate enough storage in the face array
  1135. mesh.mFaces.resize(iNumFaces);
  1136. int iDepth = 0;
  1137. while (true)
  1138. {
  1139. if ('*' == *this->m_szFile)
  1140. {
  1141. // Face entry
  1142. if (0 == strncmp(this->m_szFile,"*MESH_FACE" ,10) &&
  1143. IsSpaceOrNewLine(*(this->m_szFile+10)))
  1144. {
  1145. this->m_szFile+=11;
  1146. ASE::Face mFace;
  1147. this->ParseLV4MeshFace(mFace);
  1148. if (mFace.iFace >= iNumFaces)
  1149. {
  1150. this->LogWarning("Face has an invalid index. It will be ignored");
  1151. }
  1152. else mesh.mFaces[mFace.iFace] = mFace;
  1153. }
  1154. }
  1155. if ('{' == *this->m_szFile)iDepth++;
  1156. if ('}' == *this->m_szFile)
  1157. {
  1158. if (0 == --iDepth){++this->m_szFile;this->SkipToNextToken();return;}
  1159. }
  1160. else if ('\0' == *this->m_szFile)
  1161. {
  1162. // END OF FILE ... this is a level3 block, this can't be
  1163. BLUBB("Unable to finish parsing LV3 *MESH_FACE_LIST block. Unexpected EOF")
  1164. }
  1165. else if(IsLineEnd(*this->m_szFile))++this->iLineNumber;
  1166. ++this->m_szFile;
  1167. }
  1168. return;
  1169. }
  1170. // ------------------------------------------------------------------------------------------------
  1171. void Parser::ParseLV3MeshTListBlock(unsigned int iNumVertices,
  1172. ASE::Mesh& mesh, unsigned int iChannel)
  1173. {
  1174. // allocate enough storage in the array
  1175. mesh.amTexCoords[iChannel].resize(iNumVertices);
  1176. int iDepth = 0;
  1177. while (true)
  1178. {
  1179. if ('*' == *this->m_szFile)
  1180. {
  1181. // Vertex entry
  1182. if (0 == strncmp(this->m_szFile,"*MESH_TVERT" ,11) &&
  1183. IsSpaceOrNewLine(*(this->m_szFile+11)))
  1184. {
  1185. this->m_szFile+=12;
  1186. aiVector3D vTemp;
  1187. unsigned int iIndex;
  1188. this->ParseLV4MeshFloatTriple(&vTemp.x,iIndex);
  1189. if (iIndex >= iNumVertices)
  1190. {
  1191. this->LogWarning("Tvertex has an invalid index. It will be ignored");
  1192. }
  1193. else mesh.amTexCoords[iChannel][iIndex] = vTemp;
  1194. if (0.0f != vTemp.z)
  1195. {
  1196. // we need 3 coordinate channels
  1197. mesh.mNumUVComponents[iChannel] = 3;
  1198. }
  1199. }
  1200. }
  1201. if ('{' == *this->m_szFile)iDepth++;
  1202. if ('}' == *this->m_szFile)
  1203. {
  1204. if (0 == --iDepth){++this->m_szFile;this->SkipToNextToken();return;}
  1205. }
  1206. else if ('\0' == *this->m_szFile)
  1207. {
  1208. // END OF FILE ... this is a level3 block, this can't be
  1209. BLUBB("Unable to finish parsing LV3 *MESH_VERTEX_LIST block. Unexpected EOF")
  1210. }
  1211. else if(IsLineEnd(*this->m_szFile))++this->iLineNumber;
  1212. ++this->m_szFile;
  1213. }
  1214. return;
  1215. }
  1216. // ------------------------------------------------------------------------------------------------
  1217. void Parser::ParseLV3MeshTFaceListBlock(unsigned int iNumFaces,
  1218. ASE::Mesh& mesh, unsigned int iChannel)
  1219. {
  1220. int iDepth = 0;
  1221. while (true)
  1222. {
  1223. if ('*' == *this->m_szFile)
  1224. {
  1225. // Face entry
  1226. if (0 == strncmp(this->m_szFile,"*MESH_TFACE" ,12) &&
  1227. IsSpaceOrNewLine(*(this->m_szFile+12)))
  1228. {
  1229. this->m_szFile+=13;
  1230. unsigned int aiValues[3];
  1231. unsigned int iIndex = 0;
  1232. this->ParseLV4MeshLongTriple(aiValues,iIndex);
  1233. if (iIndex >= iNumFaces || iIndex >= mesh.mFaces.size())
  1234. {
  1235. this->LogWarning("UV-Face has an invalid index. It will be ignored");
  1236. }
  1237. else
  1238. {
  1239. // copy UV indices
  1240. mesh.mFaces[iIndex].amUVIndices[iChannel][0] = aiValues[0];
  1241. mesh.mFaces[iIndex].amUVIndices[iChannel][1] = aiValues[1];
  1242. mesh.mFaces[iIndex].amUVIndices[iChannel][2] = aiValues[2];
  1243. }
  1244. }
  1245. }
  1246. if ('{' == *this->m_szFile)iDepth++;
  1247. if ('}' == *this->m_szFile)
  1248. {
  1249. if (0 == --iDepth){++this->m_szFile;this->SkipToNextToken();return;}
  1250. }
  1251. else if ('\0' == *this->m_szFile)
  1252. {
  1253. // END OF FILE ... this is a level3 block, this can't be
  1254. BLUBB("Unable to finish parsing LV3 *MESH_TFACELIST block. Unexpected EOF")
  1255. }
  1256. else if(IsLineEnd(*this->m_szFile))++this->iLineNumber;
  1257. ++this->m_szFile;
  1258. }
  1259. return;
  1260. }
  1261. // ------------------------------------------------------------------------------------------------
  1262. void Parser::ParseLV3MappingChannel(unsigned int iChannel, ASE::Mesh& mesh)
  1263. {
  1264. unsigned int iNumTVertices = 0;
  1265. unsigned int iNumTFaces = 0;
  1266. int iDepth = 0;
  1267. while (true)
  1268. {
  1269. if ('*' == *this->m_szFile)
  1270. {
  1271. // Number of texture coordinates in the mesh
  1272. if (0 == strncmp(this->m_szFile,"*MESH_NUMTVERTEX" ,16) &&
  1273. IsSpaceOrNewLine(*(this->m_szFile+16)))
  1274. {
  1275. this->m_szFile+=17;
  1276. this->ParseLV4MeshLong(iNumTVertices);
  1277. }
  1278. // Number of UVWed faces in the mesh
  1279. if (0 == strncmp(this->m_szFile,"*MESH_NUMTVFACES" ,16) &&
  1280. IsSpaceOrNewLine(*(this->m_szFile+16)))
  1281. {
  1282. this->m_szFile+=17;
  1283. this->ParseLV4MeshLong(iNumTFaces);
  1284. }
  1285. // mesh texture vertex list block
  1286. if (0 == strncmp(this->m_szFile,"*MESH_TVERTLIST" ,15) &&
  1287. IsSpaceOrNewLine(*(this->m_szFile+15)))
  1288. {
  1289. this->m_szFile+=16;
  1290. this->SkipOpeningBracket();
  1291. this->ParseLV3MeshTListBlock(iNumTVertices,mesh,iChannel);
  1292. }
  1293. // mesh texture face block
  1294. if (0 == strncmp(this->m_szFile,"*MESH_TFACELIST" ,15) &&
  1295. IsSpaceOrNewLine(*(this->m_szFile+15)))
  1296. {
  1297. this->m_szFile+=16;
  1298. this->SkipOpeningBracket();
  1299. this->ParseLV3MeshTFaceListBlock(iNumTFaces,mesh, iChannel);
  1300. }
  1301. }
  1302. if ('{' == *this->m_szFile)iDepth++;
  1303. if ('}' == *this->m_szFile)
  1304. {
  1305. if (0 == --iDepth){++this->m_szFile;this->SkipToNextToken();return;}
  1306. }
  1307. else if ('\0' == *this->m_szFile)
  1308. {
  1309. // END OF FILE ... this is a level2 block, this can't be
  1310. BLUBB("Unable to finish parsing a LV3 *MESH_MAPPINGCHANNEL block. Unexpected EOF")
  1311. }
  1312. else if(IsLineEnd(*this->m_szFile))++this->iLineNumber;
  1313. ++this->m_szFile;
  1314. }
  1315. return;
  1316. }
  1317. // ------------------------------------------------------------------------------------------------
  1318. void Parser::ParseLV3MeshCListBlock(unsigned int iNumVertices, ASE::Mesh& mesh)
  1319. {
  1320. // allocate enough storage in the array
  1321. mesh.mVertexColors.resize(iNumVertices);
  1322. int iDepth = 0;
  1323. while (true)
  1324. {
  1325. if ('*' == *this->m_szFile)
  1326. {
  1327. // Vertex entry
  1328. if (0 == strncmp(this->m_szFile,"*MESH_VERTCOL" ,13) &&
  1329. IsSpaceOrNewLine(*(this->m_szFile+13)))
  1330. {
  1331. this->m_szFile+=14;
  1332. aiColor4D vTemp;
  1333. vTemp.a = 1.0f;
  1334. unsigned int iIndex;
  1335. this->ParseLV4MeshFloatTriple(&vTemp.r,iIndex);
  1336. if (iIndex >= iNumVertices)
  1337. {
  1338. this->LogWarning("Vertex color has an invalid index. It will be ignored");
  1339. }
  1340. else mesh.mVertexColors[iIndex] = vTemp;
  1341. }
  1342. }
  1343. if ('{' == *this->m_szFile)iDepth++;
  1344. if ('}' == *this->m_szFile)
  1345. {
  1346. if (0 == --iDepth){++this->m_szFile;this->SkipToNextToken();return;}
  1347. }
  1348. else if ('\0' == *this->m_szFile)
  1349. {
  1350. // END OF FILE ... this is a level3 block, this can't be
  1351. BLUBB("Unable to finish parsing LV3 *MESH_CVERTLIST block. Unexpected EOF")
  1352. }
  1353. else if(IsLineEnd(*this->m_szFile))++this->iLineNumber;
  1354. ++this->m_szFile;
  1355. }
  1356. return;
  1357. }
  1358. // ------------------------------------------------------------------------------------------------
  1359. void Parser::ParseLV3MeshCFaceListBlock(unsigned int iNumFaces, ASE::Mesh& mesh)
  1360. {
  1361. int iDepth = 0;
  1362. while (true)
  1363. {
  1364. if ('*' == *this->m_szFile)
  1365. {
  1366. // Face entry
  1367. if (0 == strncmp(this->m_szFile,"*MESH_CFACE" ,12) &&
  1368. IsSpaceOrNewLine(*(this->m_szFile+12)))
  1369. {
  1370. this->m_szFile+=13;
  1371. unsigned int aiValues[3];
  1372. unsigned int iIndex = 0;
  1373. this->ParseLV4MeshLongTriple(aiValues,iIndex);
  1374. if (iIndex >= iNumFaces || iIndex >= mesh.mFaces.size())
  1375. {
  1376. this->LogWarning("UV-Face has an invalid index. It will be ignored");
  1377. }
  1378. else
  1379. {
  1380. // copy color indices
  1381. mesh.mFaces[iIndex].mColorIndices[0] = aiValues[0];
  1382. mesh.mFaces[iIndex].mColorIndices[1] = aiValues[1];
  1383. mesh.mFaces[iIndex].mColorIndices[2] = aiValues[2];
  1384. }
  1385. }
  1386. }
  1387. if ('{' == *this->m_szFile)iDepth++;
  1388. if ('}' == *this->m_szFile)
  1389. {
  1390. if (0 == --iDepth){++this->m_szFile;this->SkipToNextToken();return;}
  1391. }
  1392. else if ('\0' == *this->m_szFile)
  1393. {
  1394. // END OF FILE ... this is a level3 block, this can't be
  1395. BLUBB("Unable to finish parsing LV3 *MESH_CFACELIST block. Unexpected EOF")
  1396. }
  1397. else if(IsLineEnd(*this->m_szFile))++this->iLineNumber;
  1398. ++this->m_szFile;
  1399. }
  1400. return;
  1401. }
  1402. // ------------------------------------------------------------------------------------------------
  1403. void Parser::ParseLV3MeshNormalListBlock(ASE::Mesh& sMesh)
  1404. {
  1405. // allocate enough storage for the normals
  1406. sMesh.mNormals.resize(sMesh.mPositions.size());
  1407. int iDepth = 0;
  1408. // we need the *MESH_VERTEXNORMAL blocks, ignore the face normals
  1409. // if there are only face normals we calculate them outselfes using the SGs
  1410. while (true)
  1411. {
  1412. if ('*' == *this->m_szFile)
  1413. {
  1414. if (0 == strncmp(this->m_szFile,"*MESH_VERTEXNORMAL",18) && IsSpaceOrNewLine(*(this->m_szFile+18)))
  1415. {
  1416. this->m_szFile += 19;
  1417. // parse a simple float triple
  1418. aiVector3D vNormal;
  1419. unsigned int iIndex = 0;
  1420. this->ParseLV4MeshFloatTriple(&vNormal.x,iIndex);
  1421. if (iIndex >= sMesh.mNormals.size())
  1422. {
  1423. this->LogWarning("Normal index is too large");
  1424. iIndex = sMesh.mNormals.size()-1;
  1425. }
  1426. // important: this->m_szFile might now point to '}' ...
  1427. sMesh.mNormals[iIndex] = vNormal;
  1428. }
  1429. }
  1430. if ('{' == *this->m_szFile)iDepth++;
  1431. if ('}' == *this->m_szFile)
  1432. {
  1433. if (0 == --iDepth){++this->m_szFile;this->SkipToNextToken();return;}
  1434. }
  1435. // seems we have reached the end of the file ...
  1436. else if ('\0' == *this->m_szFile)
  1437. {
  1438. BLUBB("Unable to parse *MESH_NORMALS Element: Unexpected EOL [#1]")
  1439. }
  1440. this->m_szFile++;
  1441. }
  1442. return;
  1443. }
  1444. // ------------------------------------------------------------------------------------------------
  1445. void Parser::ParseLV4MeshFace(ASE::Face& out)
  1446. {
  1447. // skip spaces and tabs
  1448. if(!SkipSpaces(this->m_szFile,&this->m_szFile))
  1449. BLUBB("Unable to parse *MESH_FACE Element: Unexpected EOL [#1]")
  1450. // parse the face index
  1451. out.iFace = strtol10(this->m_szFile,&this->m_szFile);
  1452. // next character should be ':'
  1453. if(!SkipSpaces(this->m_szFile,&this->m_szFile) || ':' != *this->m_szFile)
  1454. BLUBB("Unable to parse *MESH_FACE Element: Unexpected EOL. \':\' expected [#2]")
  1455. // parse all mesh indices
  1456. ++this->m_szFile;
  1457. for (unsigned int i = 0; i < 3;++i)
  1458. {
  1459. unsigned int iIndex = 0;
  1460. if(!SkipSpaces(this->m_szFile,&this->m_szFile))
  1461. {
  1462. // LOG
  1463. __EARTHQUAKE_XXL:
  1464. BLUBB("Unable to parse *MESH_FACE Element: Unexpected EOL. A,B or C expected [#3]")
  1465. }
  1466. switch (*this->m_szFile)
  1467. {
  1468. case 'A':
  1469. case 'a':
  1470. break;
  1471. case 'B':
  1472. case 'b':
  1473. iIndex = 1;
  1474. break;
  1475. case 'C':
  1476. case 'c':
  1477. iIndex = 2;
  1478. break;
  1479. default: goto __EARTHQUAKE_XXL;
  1480. };
  1481. ++this->m_szFile;
  1482. // next character should be ':'
  1483. if(!SkipSpaces(this->m_szFile,&this->m_szFile) || ':' != *this->m_szFile)
  1484. BLUBB("Unable to parse *MESH_FACE Element: Unexpected EOL. \':\' expected [#2]")
  1485. ++this->m_szFile;
  1486. if(!SkipSpaces(this->m_szFile,&this->m_szFile))
  1487. BLUBB("Unable to parse *MESH_FACE Element: Unexpected EOL. Vertex index ecpected [#4]")
  1488. out.mIndices[iIndex] = strtol10(this->m_szFile,&this->m_szFile);
  1489. }
  1490. // now we need to skip the AB, BC, CA blocks.
  1491. while (true)
  1492. {
  1493. if ('*' == *this->m_szFile)break;
  1494. if (IsLineEnd(*this->m_szFile))
  1495. {
  1496. //this->iLineNumber++;
  1497. return;
  1498. }
  1499. this->m_szFile++;
  1500. }
  1501. // parse the smoothing group of the face
  1502. if (0 == strncmp(this->m_szFile,"*MESH_SMOOTHING",15) && IsSpaceOrNewLine(*(this->m_szFile+15)))
  1503. {
  1504. this->m_szFile+=16;
  1505. if(!SkipSpaces(this->m_szFile,&this->m_szFile))
  1506. BLUBB("Unable to parse *MESH_SMOOTHING Element: Unexpected EOL. Smoothing group(s) expected [#5]")
  1507. // parse smoothing groups until we don_t anymore see commas
  1508. // FIX: There needn't always be a value, sad but true
  1509. while (true)
  1510. {
  1511. if (*this->m_szFile < '9' && *this->m_szFile >= '0')
  1512. {
  1513. out.iSmoothGroup |= (1 << strtol10(this->m_szFile,&this->m_szFile));
  1514. }
  1515. SkipSpaces(this->m_szFile,&this->m_szFile);
  1516. if (',' != *this->m_szFile)
  1517. {
  1518. break;
  1519. }
  1520. ++this->m_szFile;
  1521. SkipSpaces(this->m_szFile,&this->m_szFile);
  1522. }
  1523. }
  1524. // *MESH_MTLID is optional, too
  1525. while (true)
  1526. {
  1527. if ('*' == *this->m_szFile)break;
  1528. if (IsLineEnd(*this->m_szFile))
  1529. {
  1530. //this->iLineNumber++;
  1531. return;
  1532. }
  1533. this->m_szFile++;
  1534. }
  1535. if (0 == strncmp(this->m_szFile,"*MESH_MTLID",11) && IsSpaceOrNewLine(*(this->m_szFile+11)))
  1536. {
  1537. this->m_szFile+=12;
  1538. if(!SkipSpaces(this->m_szFile,&this->m_szFile))
  1539. BLUBB("Unable to parse *MESH_MTLID Element: Unexpected EOL. Material index expected [#6]")
  1540. out.iMaterial = strtol10(this->m_szFile,&this->m_szFile);
  1541. }
  1542. //this->SkipToNextToken();
  1543. return;
  1544. }
  1545. // ------------------------------------------------------------------------------------------------
  1546. void Parser::ParseLV4MeshLongTriple(unsigned int* apOut)
  1547. {
  1548. ai_assert(NULL != apOut);
  1549. // skip spaces and tabs
  1550. if(!SkipSpaces(this->m_szFile,&this->m_szFile))
  1551. {
  1552. // LOG
  1553. this->LogWarning("Unable to parse indexable long triple: unexpected EOL [#1]");
  1554. ++this->iLineNumber;
  1555. apOut[0] = apOut[1] = apOut[2] = 0;
  1556. return;
  1557. }
  1558. apOut[0] = strtol10(this->m_szFile,&this->m_szFile);
  1559. // skip spaces and tabs
  1560. if(!SkipSpaces(this->m_szFile,&this->m_szFile))
  1561. {
  1562. // LOG
  1563. this->LogWarning("Unable to parse indexable long triple: unexpected EOL [#2]");
  1564. ++this->iLineNumber;
  1565. apOut[1] = apOut[2] = 0;
  1566. return;
  1567. }
  1568. apOut[1] = strtol10(this->m_szFile,&this->m_szFile);
  1569. // skip spaces and tabs
  1570. if(!SkipSpaces(this->m_szFile,&this->m_szFile))
  1571. {
  1572. // LOG
  1573. this->LogWarning("Unable to parse indexable long triple: unexpected EOL [#3]");
  1574. apOut[2] = 0;
  1575. ++this->iLineNumber;
  1576. return;
  1577. }
  1578. apOut[2] = strtol10(this->m_szFile,&this->m_szFile);
  1579. // go to the next valid sequence
  1580. //SkipSpacesAndLineEnd(this->m_szFile,&this->m_szFile);
  1581. }
  1582. // ------------------------------------------------------------------------------------------------
  1583. void Parser::ParseLV4MeshLongTriple(unsigned int* apOut, unsigned int& rIndexOut)
  1584. {
  1585. ai_assert(NULL != apOut);
  1586. // skip spaces and tabs
  1587. if(!SkipSpaces(this->m_szFile,&this->m_szFile))
  1588. {
  1589. // LOG
  1590. this->LogWarning("Unable to parse indexable long triple: unexpected EOL [#4]");
  1591. rIndexOut = 0;
  1592. apOut[0] = apOut[1] = apOut[2] = 0;
  1593. ++this->iLineNumber;
  1594. return;
  1595. }
  1596. // parse the index
  1597. rIndexOut = strtol10(this->m_szFile,&this->m_szFile);
  1598. // parse the three others
  1599. this->ParseLV4MeshLongTriple(apOut);
  1600. return;
  1601. }
  1602. // ------------------------------------------------------------------------------------------------
  1603. void Parser::ParseLV4MeshFloatTriple(float* apOut, unsigned int& rIndexOut)
  1604. {
  1605. ai_assert(NULL != apOut);
  1606. // skip spaces and tabs
  1607. if(!SkipSpaces(this->m_szFile,&this->m_szFile))
  1608. {
  1609. // LOG
  1610. this->LogWarning("Unable to parse indexable float triple: unexpected EOL [#1]");
  1611. rIndexOut = 0;
  1612. apOut[0] = apOut[1] = apOut[2] = 0.0f;
  1613. ++this->iLineNumber;
  1614. return;
  1615. }
  1616. // parse the index
  1617. rIndexOut = strtol10(this->m_szFile,&this->m_szFile);
  1618. // parse the three others
  1619. this->ParseLV4MeshFloatTriple(apOut);
  1620. return;
  1621. }
  1622. // ------------------------------------------------------------------------------------------------
  1623. void Parser::ParseLV4MeshFloatTriple(float* apOut)
  1624. {
  1625. ai_assert(NULL != apOut);
  1626. // skip spaces and tabs
  1627. if(!SkipSpaces(this->m_szFile,&this->m_szFile))
  1628. {
  1629. // LOG
  1630. this->LogWarning("Unable to parse float triple: unexpected EOL [#5]");
  1631. apOut[0] = apOut[1] = apOut[2] = 0.0f;
  1632. ++this->iLineNumber;
  1633. return;
  1634. }
  1635. // parse the first float
  1636. this->m_szFile = fast_atof_move(this->m_szFile,apOut[0]);
  1637. // skip spaces and tabs
  1638. if(!SkipSpaces(this->m_szFile,&this->m_szFile))
  1639. {
  1640. // LOG
  1641. this->LogWarning("Unable to parse float triple: unexpected EOL [#6]");
  1642. apOut[1] = apOut[2] = 0.0f;
  1643. ++this->iLineNumber;
  1644. return;
  1645. }
  1646. // parse the second float
  1647. this->m_szFile = fast_atof_move(this->m_szFile,apOut[1]);
  1648. // skip spaces and tabs
  1649. if(!SkipSpaces(this->m_szFile,&this->m_szFile))
  1650. {
  1651. // LOG
  1652. this->LogWarning("Unable to parse float triple: unexpected EOL [#7]");
  1653. apOut[2] = 0.0f;
  1654. ++this->iLineNumber;
  1655. return;
  1656. }
  1657. // parse the third float
  1658. this->m_szFile = fast_atof_move(this->m_szFile,apOut[2]);
  1659. // go to the next valid sequence
  1660. //this->SkipToNextToken();
  1661. return;
  1662. }
  1663. // ------------------------------------------------------------------------------------------------
  1664. void Parser::ParseLV4MeshFloat(float& fOut)
  1665. {
  1666. // skip spaces and tabs
  1667. if(!SkipSpaces(this->m_szFile,&this->m_szFile))
  1668. {
  1669. // LOG
  1670. this->LogWarning("Unable to parse float: unexpected EOL [#1]");
  1671. fOut = 0.0f;
  1672. ++this->iLineNumber;
  1673. return;
  1674. }
  1675. // parse the first float
  1676. this->m_szFile = fast_atof_move(this->m_szFile,fOut);
  1677. // go to the next valid sequence
  1678. //this->SkipToNextToken();
  1679. return;
  1680. }
  1681. // ------------------------------------------------------------------------------------------------
  1682. void Parser::ParseLV4MeshLong(unsigned int& iOut)
  1683. {
  1684. // skip spaces and tabs
  1685. if(!SkipSpaces(this->m_szFile,&this->m_szFile))
  1686. {
  1687. // LOG
  1688. this->LogWarning("Unable to parse long: unexpected EOL [#1]");
  1689. iOut = 0;
  1690. ++this->iLineNumber;
  1691. return;
  1692. }
  1693. // parse the value
  1694. iOut = strtol10(this->m_szFile,&this->m_szFile);
  1695. // go to the next valid sequence
  1696. //this->SkipToNextToken();
  1697. return;
  1698. }