ASEParser.cpp 53 KB

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