ASEParser.cpp 71 KB

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