Model_ase.cpp 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924
  1. /*
  2. ===========================================================================
  3. Doom 3 BFG Edition GPL Source Code
  4. Copyright (C) 1993-2012 id Software LLC, a ZeniMax Media company.
  5. This file is part of the Doom 3 BFG Edition GPL Source Code ("Doom 3 BFG Edition Source Code").
  6. Doom 3 BFG Edition Source Code is free software: you can redistribute it and/or modify
  7. it under the terms of the GNU General Public License as published by
  8. the Free Software Foundation, either version 3 of the License, or
  9. (at your option) any later version.
  10. Doom 3 BFG Edition Source Code is distributed in the hope that it will be useful,
  11. but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. GNU General Public License for more details.
  14. You should have received a copy of the GNU General Public License
  15. along with Doom 3 BFG Edition Source Code. If not, see <http://www.gnu.org/licenses/>.
  16. In addition, the Doom 3 BFG Edition Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the Doom 3 BFG Edition Source Code. If not, please request a copy in writing from id Software at the address below.
  17. If you have questions concerning this license or the applicable additional terms, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA.
  18. ===========================================================================
  19. */
  20. #pragma hdrstop
  21. #include "../idlib/precompiled.h"
  22. #include "Model_ase.h"
  23. /*
  24. ======================================================================
  25. Parses 3D Studio Max ASCII export files.
  26. The goal is to parse the information into memory exactly as it is
  27. represented in the file. Users of the data will then move it
  28. into a form that is more convenient for them.
  29. ======================================================================
  30. */
  31. #define VERBOSE( x ) { if ( ase.verbose ) { common->Printf x ; } }
  32. // working variables used during parsing
  33. typedef struct {
  34. const char *buffer;
  35. const char *curpos;
  36. int len;
  37. char token[1024];
  38. bool verbose;
  39. aseModel_t *model;
  40. aseObject_t *currentObject;
  41. aseMesh_t *currentMesh;
  42. aseMaterial_t *currentMaterial;
  43. int currentFace;
  44. int currentVertex;
  45. } ase_t;
  46. static ase_t ase;
  47. static aseMesh_t *ASE_GetCurrentMesh()
  48. {
  49. return ase.currentMesh;
  50. }
  51. static int CharIsTokenDelimiter( int ch )
  52. {
  53. if ( ch <= 32 )
  54. return 1;
  55. return 0;
  56. }
  57. static int ASE_GetToken( bool restOfLine )
  58. {
  59. int i = 0;
  60. if ( ase.buffer == 0 )
  61. return 0;
  62. if ( ( ase.curpos - ase.buffer ) == ase.len )
  63. return 0;
  64. // skip over crap
  65. while ( ( ( ase.curpos - ase.buffer ) < ase.len ) &&
  66. ( *ase.curpos <= 32 ) )
  67. {
  68. ase.curpos++;
  69. }
  70. while ( ( ase.curpos - ase.buffer ) < ase.len )
  71. {
  72. ase.token[i] = *ase.curpos;
  73. ase.curpos++;
  74. i++;
  75. if ( ( CharIsTokenDelimiter( ase.token[i-1] ) && !restOfLine ) ||
  76. ( ( ase.token[i-1] == '\n' ) || ( ase.token[i-1] == '\r' ) ) )
  77. {
  78. ase.token[i-1] = 0;
  79. break;
  80. }
  81. }
  82. ase.token[i] = 0;
  83. return 1;
  84. }
  85. static void ASE_ParseBracedBlock( void (*parser)( const char *token ) )
  86. {
  87. int indent = 0;
  88. while ( ASE_GetToken( false ) )
  89. {
  90. if ( !strcmp( ase.token, "{" ) )
  91. {
  92. indent++;
  93. }
  94. else if ( !strcmp( ase.token, "}" ) )
  95. {
  96. --indent;
  97. if ( indent == 0 )
  98. break;
  99. else if ( indent < 0 )
  100. common->Error( "Unexpected '}'" );
  101. }
  102. else
  103. {
  104. if ( parser )
  105. parser( ase.token );
  106. }
  107. }
  108. }
  109. static void ASE_SkipEnclosingBraces()
  110. {
  111. int indent = 0;
  112. while ( ASE_GetToken( false ) )
  113. {
  114. if ( !strcmp( ase.token, "{" ) )
  115. {
  116. indent++;
  117. }
  118. else if ( !strcmp( ase.token, "}" ) )
  119. {
  120. indent--;
  121. if ( indent == 0 )
  122. break;
  123. else if ( indent < 0 )
  124. common->Error( "Unexpected '}'" );
  125. }
  126. }
  127. }
  128. static void ASE_SkipRestOfLine()
  129. {
  130. ASE_GetToken( true );
  131. }
  132. static void ASE_KeyMAP_DIFFUSE( const char *token )
  133. {
  134. aseMaterial_t *material;
  135. if ( !strcmp( token, "*BITMAP" ) )
  136. {
  137. idStr qpath;
  138. idStr matname;
  139. ASE_GetToken( false );
  140. // remove the quotes
  141. char *s = strstr( ase.token + 1, "\"" );
  142. if ( s ) {
  143. *s = 0;
  144. }
  145. matname = ase.token + 1;
  146. // convert the 3DSMax material pathname to a qpath
  147. matname.BackSlashesToSlashes();
  148. qpath = fileSystem->OSPathToRelativePath( matname );
  149. idStr::Copynz( ase.currentMaterial->name, qpath, sizeof( ase.currentMaterial->name ) );
  150. }
  151. else if ( !strcmp( token, "*UVW_U_OFFSET" ) )
  152. {
  153. material = ase.model->materials[ase.model->materials.Num() - 1];
  154. ASE_GetToken( false );
  155. material->uOffset = atof( ase.token );
  156. }
  157. else if ( !strcmp( token, "*UVW_V_OFFSET" ) )
  158. {
  159. material = ase.model->materials[ase.model->materials.Num() - 1];
  160. ASE_GetToken( false );
  161. material->vOffset = atof( ase.token );
  162. }
  163. else if ( !strcmp( token, "*UVW_U_TILING" ) )
  164. {
  165. material = ase.model->materials[ase.model->materials.Num() - 1];
  166. ASE_GetToken( false );
  167. material->uTiling = atof( ase.token );
  168. }
  169. else if ( !strcmp( token, "*UVW_V_TILING" ) )
  170. {
  171. material = ase.model->materials[ase.model->materials.Num() - 1];
  172. ASE_GetToken( false );
  173. material->vTiling = atof( ase.token );
  174. }
  175. else if ( !strcmp( token, "*UVW_ANGLE" ) )
  176. {
  177. material = ase.model->materials[ase.model->materials.Num() - 1];
  178. ASE_GetToken( false );
  179. material->angle = atof( ase.token );
  180. }
  181. else
  182. {
  183. }
  184. }
  185. static void ASE_KeyMATERIAL( const char *token )
  186. {
  187. if ( !strcmp( token, "*MAP_DIFFUSE" ) )
  188. {
  189. ASE_ParseBracedBlock( ASE_KeyMAP_DIFFUSE );
  190. }
  191. else
  192. {
  193. }
  194. }
  195. static void ASE_KeyMATERIAL_LIST( const char *token )
  196. {
  197. if ( !strcmp( token, "*MATERIAL_COUNT" ) )
  198. {
  199. ASE_GetToken( false );
  200. VERBOSE( ( "..num materials: %s\n", ase.token ) );
  201. }
  202. else if ( !strcmp( token, "*MATERIAL" ) )
  203. {
  204. VERBOSE( ( "..material %d\n", ase.model->materials.Num() ) );
  205. ase.currentMaterial = (aseMaterial_t *)Mem_Alloc( sizeof( aseMaterial_t ), TAG_MODEL );
  206. memset( ase.currentMaterial, 0, sizeof( aseMaterial_t ) );
  207. ase.currentMaterial->uTiling = 1;
  208. ase.currentMaterial->vTiling = 1;
  209. ase.model->materials.Append(ase.currentMaterial);
  210. ASE_ParseBracedBlock( ASE_KeyMATERIAL );
  211. }
  212. }
  213. static void ASE_KeyNODE_TM( const char *token )
  214. {
  215. int i;
  216. if ( !strcmp( token, "*TM_ROW0" ) ) {
  217. for ( i = 0 ; i < 3 ; i++ ) {
  218. ASE_GetToken( false );
  219. ase.currentObject->mesh.transform[0][i] = atof( ase.token );
  220. }
  221. } else if ( !strcmp( token, "*TM_ROW1" ) ) {
  222. for ( i = 0 ; i < 3 ; i++ ) {
  223. ASE_GetToken( false );
  224. ase.currentObject->mesh.transform[1][i] = atof( ase.token );
  225. }
  226. } else if ( !strcmp( token, "*TM_ROW2" ) ) {
  227. for ( i = 0 ; i < 3 ; i++ ) {
  228. ASE_GetToken( false );
  229. ase.currentObject->mesh.transform[2][i] = atof( ase.token );
  230. }
  231. } else if ( !strcmp( token, "*TM_ROW3" ) ) {
  232. for ( i = 0 ; i < 3 ; i++ ) {
  233. ASE_GetToken( false );
  234. ase.currentObject->mesh.transform[3][i] = atof( ase.token );
  235. }
  236. }
  237. }
  238. static void ASE_KeyMESH_VERTEX_LIST( const char *token )
  239. {
  240. aseMesh_t *pMesh = ASE_GetCurrentMesh();
  241. if ( !strcmp( token, "*MESH_VERTEX" ) )
  242. {
  243. ASE_GetToken( false ); // skip number
  244. ASE_GetToken( false );
  245. pMesh->vertexes[ase.currentVertex].x = atof( ase.token );
  246. ASE_GetToken( false );
  247. pMesh->vertexes[ase.currentVertex].y = atof( ase.token );
  248. ASE_GetToken( false );
  249. pMesh->vertexes[ase.currentVertex].z = atof( ase.token );
  250. ase.currentVertex++;
  251. if ( ase.currentVertex > pMesh->numVertexes )
  252. {
  253. common->Error( "ase.currentVertex >= pMesh->numVertexes" );
  254. }
  255. }
  256. else
  257. {
  258. common->Error( "Unknown token '%s' while parsing MESH_VERTEX_LIST", token );
  259. }
  260. }
  261. static void ASE_KeyMESH_FACE_LIST( const char *token )
  262. {
  263. aseMesh_t *pMesh = ASE_GetCurrentMesh();
  264. if ( !strcmp( token, "*MESH_FACE" ) )
  265. {
  266. ASE_GetToken( false ); // skip face number
  267. // we are flipping the order here to change the front/back facing
  268. // from 3DS to our standard (clockwise facing out)
  269. ASE_GetToken( false ); // skip label
  270. ASE_GetToken( false ); // first vertex
  271. pMesh->faces[ase.currentFace].vertexNum[0] = atoi( ase.token );
  272. ASE_GetToken( false ); // skip label
  273. ASE_GetToken( false ); // second vertex
  274. pMesh->faces[ase.currentFace].vertexNum[2] = atoi( ase.token );
  275. ASE_GetToken( false ); // skip label
  276. ASE_GetToken( false ); // third vertex
  277. pMesh->faces[ase.currentFace].vertexNum[1] = atoi( ase.token );
  278. ASE_GetToken( true );
  279. // we could parse material id and smoothing groups here
  280. /*
  281. if ( ( p = strstr( ase.token, "*MESH_MTLID" ) ) != 0 )
  282. {
  283. p += strlen( "*MESH_MTLID" ) + 1;
  284. mtlID = atoi( p );
  285. }
  286. else
  287. {
  288. common->Error( "No *MESH_MTLID found for face!" );
  289. }
  290. */
  291. ase.currentFace++;
  292. }
  293. else
  294. {
  295. common->Error( "Unknown token '%s' while parsing MESH_FACE_LIST", token );
  296. }
  297. }
  298. static void ASE_KeyTFACE_LIST( const char *token )
  299. {
  300. aseMesh_t *pMesh = ASE_GetCurrentMesh();
  301. if ( !strcmp( token, "*MESH_TFACE" ) )
  302. {
  303. int a, b, c;
  304. ASE_GetToken( false );
  305. ASE_GetToken( false );
  306. a = atoi( ase.token );
  307. ASE_GetToken( false );
  308. c = atoi( ase.token );
  309. ASE_GetToken( false );
  310. b = atoi( ase.token );
  311. pMesh->faces[ase.currentFace].tVertexNum[0] = a;
  312. pMesh->faces[ase.currentFace].tVertexNum[1] = b;
  313. pMesh->faces[ase.currentFace].tVertexNum[2] = c;
  314. ase.currentFace++;
  315. }
  316. else
  317. {
  318. common->Error( "Unknown token '%s' in MESH_TFACE", token );
  319. }
  320. }
  321. static void ASE_KeyCFACE_LIST( const char *token )
  322. {
  323. aseMesh_t *pMesh = ASE_GetCurrentMesh();
  324. if ( !strcmp( token, "*MESH_CFACE" ) )
  325. {
  326. ASE_GetToken( false );
  327. for ( int i = 0 ; i < 3 ; i++ ) {
  328. ASE_GetToken( false );
  329. int a = atoi( ase.token );
  330. // we flip the vertex order to change the face direction to our style
  331. static int remap[3] = { 0, 2, 1 };
  332. pMesh->faces[ase.currentFace].vertexColors[remap[i]][0] = pMesh->cvertexes[a][0] * 255;
  333. pMesh->faces[ase.currentFace].vertexColors[remap[i]][1] = pMesh->cvertexes[a][1] * 255;
  334. pMesh->faces[ase.currentFace].vertexColors[remap[i]][2] = pMesh->cvertexes[a][2] * 255;
  335. }
  336. ase.currentFace++;
  337. }
  338. else
  339. {
  340. common->Error( "Unknown token '%s' in MESH_CFACE", token );
  341. }
  342. }
  343. static void ASE_KeyMESH_TVERTLIST( const char *token )
  344. {
  345. aseMesh_t *pMesh = ASE_GetCurrentMesh();
  346. if ( !strcmp( token, "*MESH_TVERT" ) )
  347. {
  348. const int maxLength = 80;
  349. char u[maxLength], v[maxLength], w[maxLength];
  350. ASE_GetToken( false );
  351. ASE_GetToken( false );
  352. strncpy( u, ase.token, maxLength ); u[maxLength-1] = '\0';
  353. ASE_GetToken( false );
  354. strncpy( v, ase.token, maxLength ); v[maxLength-1] = '\0';
  355. ASE_GetToken( false );
  356. strncpy( w, ase.token, maxLength ); w[maxLength-1] = '\0';
  357. pMesh->tvertexes[ase.currentVertex].x = atof( u );
  358. // our OpenGL second texture axis is inverted from MAX's sense
  359. pMesh->tvertexes[ase.currentVertex].y = 1.0f - atof( v );
  360. ase.currentVertex++;
  361. if ( ase.currentVertex > pMesh->numTVertexes )
  362. {
  363. common->Error( "ase.currentVertex > pMesh->numTVertexes" );
  364. }
  365. }
  366. else
  367. {
  368. common->Error( "Unknown token '%s' while parsing MESH_TVERTLIST", token );
  369. }
  370. }
  371. static void ASE_KeyMESH_CVERTLIST( const char *token )
  372. {
  373. aseMesh_t *pMesh = ASE_GetCurrentMesh();
  374. pMesh->colorsParsed = true;
  375. if ( !strcmp( token, "*MESH_VERTCOL" ) )
  376. {
  377. ASE_GetToken( false );
  378. ASE_GetToken( false );
  379. pMesh->cvertexes[ase.currentVertex][0] = atof( token );
  380. ASE_GetToken( false );
  381. pMesh->cvertexes[ase.currentVertex][1] = atof( token );
  382. ASE_GetToken( false );
  383. pMesh->cvertexes[ase.currentVertex][2] = atof( token );
  384. ase.currentVertex++;
  385. if ( ase.currentVertex > pMesh->numCVertexes )
  386. {
  387. common->Error( "ase.currentVertex > pMesh->numCVertexes" );
  388. }
  389. }
  390. else {
  391. common->Error( "Unknown token '%s' while parsing MESH_CVERTLIST", token );
  392. }
  393. }
  394. static void ASE_KeyMESH_NORMALS( const char *token )
  395. {
  396. aseMesh_t *pMesh = ASE_GetCurrentMesh();
  397. aseFace_t *f;
  398. idVec3 n;
  399. pMesh->normalsParsed = true;
  400. f = &pMesh->faces[ase.currentFace];
  401. if ( !strcmp( token, "*MESH_FACENORMAL" ) )
  402. {
  403. int num;
  404. ASE_GetToken( false );
  405. num = atoi( ase.token );
  406. if ( num >= pMesh->numFaces || num < 0 ) {
  407. common->Error( "MESH_NORMALS face index out of range: %i", num );
  408. }
  409. if ( num != ase.currentFace ) {
  410. common->Error( "MESH_NORMALS face index != currentFace" );
  411. }
  412. ASE_GetToken( false );
  413. n[0] = atof( ase.token );
  414. ASE_GetToken( false );
  415. n[1] = atof( ase.token );
  416. ASE_GetToken( false );
  417. n[2]= atof( ase.token );
  418. f->faceNormal[0] = n[0] * pMesh->transform[0][0] + n[1] * pMesh->transform[1][0] + n[2] * pMesh->transform[2][0];
  419. f->faceNormal[1] = n[0] * pMesh->transform[0][1] + n[1] * pMesh->transform[1][1] + n[2] * pMesh->transform[2][1];
  420. f->faceNormal[2] = n[0] * pMesh->transform[0][2] + n[1] * pMesh->transform[1][2] + n[2] * pMesh->transform[2][2];
  421. f->faceNormal.Normalize();
  422. ase.currentFace++;
  423. }
  424. else if ( !strcmp( token, "*MESH_VERTEXNORMAL" ) )
  425. {
  426. int num;
  427. int v;
  428. ASE_GetToken( false );
  429. num = atoi( ase.token );
  430. if ( num >= pMesh->numVertexes || num < 0 ) {
  431. common->Error( "MESH_NORMALS vertex index out of range: %i", num );
  432. }
  433. f = &pMesh->faces[ ase.currentFace - 1 ];
  434. for ( v = 0 ; v < 3 ; v++ ) {
  435. if ( num == f->vertexNum[ v ] ) {
  436. break;
  437. }
  438. }
  439. if ( v >= 3 ) {
  440. common->Error( "MESH_NORMALS vertex index doesn't match face" );
  441. return;
  442. }
  443. ASE_GetToken( false );
  444. n[0] = atof( ase.token );
  445. ASE_GetToken( false );
  446. n[1] = atof( ase.token );
  447. ASE_GetToken( false );
  448. n[2]= atof( ase.token );
  449. f->vertexNormals[ v ][0] = n[0] * pMesh->transform[0][0] + n[1] * pMesh->transform[1][0] + n[2] * pMesh->transform[2][0];
  450. f->vertexNormals[ v ][1] = n[0] * pMesh->transform[0][1] + n[1] * pMesh->transform[1][1] + n[2] * pMesh->transform[2][1];
  451. f->vertexNormals[ v ][2] = n[0] * pMesh->transform[0][2] + n[1] * pMesh->transform[1][2] + n[2] * pMesh->transform[2][2];
  452. f->vertexNormals[v].Normalize();
  453. }
  454. }
  455. static void ASE_KeyMESH( const char *token )
  456. {
  457. aseMesh_t *pMesh = ASE_GetCurrentMesh();
  458. if ( !strcmp( token, "*TIMEVALUE" ) )
  459. {
  460. ASE_GetToken( false );
  461. pMesh->timeValue = atoi( ase.token );
  462. VERBOSE( ( ".....timevalue: %d\n", pMesh->timeValue ) );
  463. }
  464. else if ( !strcmp( token, "*MESH_NUMVERTEX" ) )
  465. {
  466. ASE_GetToken( false );
  467. pMesh->numVertexes = atoi( ase.token );
  468. VERBOSE( ( ".....num vertexes: %d\n", pMesh->numVertexes ) );
  469. }
  470. else if ( !strcmp( token, "*MESH_NUMTVERTEX" ) )
  471. {
  472. ASE_GetToken( false );
  473. pMesh->numTVertexes = atoi( ase.token );
  474. VERBOSE( ( ".....num tvertexes: %d\n", pMesh->numTVertexes ) );
  475. }
  476. else if ( !strcmp( token, "*MESH_NUMCVERTEX" ) )
  477. {
  478. ASE_GetToken( false );
  479. pMesh->numCVertexes = atoi( ase.token );
  480. VERBOSE( ( ".....num cvertexes: %d\n", pMesh->numCVertexes ) );
  481. }
  482. else if ( !strcmp( token, "*MESH_NUMFACES" ) )
  483. {
  484. ASE_GetToken( false );
  485. pMesh->numFaces = atoi( ase.token );
  486. VERBOSE( ( ".....num faces: %d\n", pMesh->numFaces ) );
  487. }
  488. else if ( !strcmp( token, "*MESH_NUMTVFACES" ) )
  489. {
  490. ASE_GetToken( false );
  491. pMesh->numTVFaces = atoi( ase.token );
  492. VERBOSE( ( ".....num tvfaces: %d\n", pMesh->numTVFaces ) );
  493. if ( pMesh->numTVFaces != pMesh->numFaces )
  494. {
  495. common->Error( "MESH_NUMTVFACES != MESH_NUMFACES" );
  496. }
  497. }
  498. else if ( !strcmp( token, "*MESH_NUMCVFACES" ) )
  499. {
  500. ASE_GetToken( false );
  501. pMesh->numCVFaces = atoi( ase.token );
  502. VERBOSE( ( ".....num cvfaces: %d\n", pMesh->numCVFaces ) );
  503. if ( pMesh->numTVFaces != pMesh->numFaces )
  504. {
  505. common->Error( "MESH_NUMCVFACES != MESH_NUMFACES" );
  506. }
  507. }
  508. else if ( !strcmp( token, "*MESH_VERTEX_LIST" ) )
  509. {
  510. pMesh->vertexes = (idVec3 *)Mem_Alloc( sizeof( idVec3 ) * pMesh->numVertexes, TAG_MODEL );
  511. ase.currentVertex = 0;
  512. VERBOSE( ( ".....parsing MESH_VERTEX_LIST\n" ) );
  513. ASE_ParseBracedBlock( ASE_KeyMESH_VERTEX_LIST );
  514. }
  515. else if ( !strcmp( token, "*MESH_TVERTLIST" ) )
  516. {
  517. ase.currentVertex = 0;
  518. pMesh->tvertexes = (idVec2 *)Mem_Alloc( sizeof( idVec2 ) * pMesh->numTVertexes, TAG_MODEL );
  519. VERBOSE( ( ".....parsing MESH_TVERTLIST\n" ) );
  520. ASE_ParseBracedBlock( ASE_KeyMESH_TVERTLIST );
  521. }
  522. else if ( !strcmp( token, "*MESH_CVERTLIST" ) )
  523. {
  524. ase.currentVertex = 0;
  525. pMesh->cvertexes = (idVec3 *)Mem_Alloc( sizeof( idVec3 ) * pMesh->numCVertexes, TAG_MODEL );
  526. VERBOSE( ( ".....parsing MESH_CVERTLIST\n" ) );
  527. ASE_ParseBracedBlock( ASE_KeyMESH_CVERTLIST );
  528. }
  529. else if ( !strcmp( token, "*MESH_FACE_LIST" ) )
  530. {
  531. pMesh->faces = (aseFace_t *)Mem_Alloc( sizeof( aseFace_t ) * pMesh->numFaces, TAG_MODEL );
  532. ase.currentFace = 0;
  533. VERBOSE( ( ".....parsing MESH_FACE_LIST\n" ) );
  534. ASE_ParseBracedBlock( ASE_KeyMESH_FACE_LIST );
  535. }
  536. else if ( !strcmp( token, "*MESH_TFACELIST" ) )
  537. {
  538. if ( !pMesh->faces ) {
  539. common->Error( "*MESH_TFACELIST before *MESH_FACE_LIST" );
  540. }
  541. ase.currentFace = 0;
  542. VERBOSE( ( ".....parsing MESH_TFACE_LIST\n" ) );
  543. ASE_ParseBracedBlock( ASE_KeyTFACE_LIST );
  544. }
  545. else if ( !strcmp( token, "*MESH_CFACELIST" ) )
  546. {
  547. if ( !pMesh->faces ) {
  548. common->Error( "*MESH_CFACELIST before *MESH_FACE_LIST" );
  549. }
  550. ase.currentFace = 0;
  551. VERBOSE( ( ".....parsing MESH_CFACE_LIST\n" ) );
  552. ASE_ParseBracedBlock( ASE_KeyCFACE_LIST );
  553. }
  554. else if ( !strcmp( token, "*MESH_NORMALS" ) )
  555. {
  556. if ( !pMesh->faces ) {
  557. common->Warning( "*MESH_NORMALS before *MESH_FACE_LIST" );
  558. }
  559. ase.currentFace = 0;
  560. VERBOSE( ( ".....parsing MESH_NORMALS\n" ) );
  561. ASE_ParseBracedBlock( ASE_KeyMESH_NORMALS );
  562. }
  563. }
  564. static void ASE_KeyMESH_ANIMATION( const char *token )
  565. {
  566. aseMesh_t *mesh;
  567. // loads a single animation frame
  568. if ( !strcmp( token, "*MESH" ) )
  569. {
  570. VERBOSE( ( "...found MESH\n" ) );
  571. mesh = (aseMesh_t *)Mem_Alloc( sizeof( aseMesh_t ), TAG_MODEL );
  572. memset( mesh, 0, sizeof( aseMesh_t ) );
  573. ase.currentMesh = mesh;
  574. ase.currentObject->frames.Append( mesh );
  575. ASE_ParseBracedBlock( ASE_KeyMESH );
  576. }
  577. else
  578. {
  579. common->Error( "Unknown token '%s' while parsing MESH_ANIMATION", token );
  580. }
  581. }
  582. static void ASE_KeyGEOMOBJECT( const char *token )
  583. {
  584. aseObject_t *object;
  585. object = ase.currentObject;
  586. if ( !strcmp( token, "*NODE_NAME" ) )
  587. {
  588. ASE_GetToken( true );
  589. VERBOSE( ( " %s\n", ase.token ) );
  590. idStr::Copynz( object->name, ase.token, sizeof( object->name ) );
  591. }
  592. else if ( !strcmp( token, "*NODE_PARENT" ) )
  593. {
  594. ASE_SkipRestOfLine();
  595. }
  596. // ignore unused data blocks
  597. else if ( !strcmp( token, "*NODE_TM" ) ||
  598. !strcmp( token, "*TM_ANIMATION" ) )
  599. {
  600. ASE_ParseBracedBlock( ASE_KeyNODE_TM );
  601. }
  602. // ignore regular meshes that aren't part of animation
  603. else if ( !strcmp( token, "*MESH" ) )
  604. {
  605. ase.currentMesh = &ase.currentObject->mesh;
  606. idVec3 transforms[ 4 ];
  607. for ( int i = 0; i < 4; ++i ) {
  608. transforms[ i ] = ase.currentMesh->transform[ i ];
  609. }
  610. memset( ase.currentMesh, 0, sizeof( *ase.currentMesh ) );
  611. for ( int i = 0; i < 4; ++i ) {
  612. ase.currentMesh->transform[ i ] = transforms[ i ];
  613. }
  614. ASE_ParseBracedBlock( ASE_KeyMESH );
  615. }
  616. // according to spec these are obsolete
  617. else if ( !strcmp( token, "*MATERIAL_REF" ) )
  618. {
  619. ASE_GetToken( false );
  620. object->materialRef = atoi( ase.token );
  621. }
  622. // loads a sequence of animation frames
  623. else if ( !strcmp( token, "*MESH_ANIMATION" ) )
  624. {
  625. VERBOSE( ( "..found MESH_ANIMATION\n" ) );
  626. ASE_ParseBracedBlock( ASE_KeyMESH_ANIMATION );
  627. }
  628. // skip unused info
  629. else if ( !strcmp( token, "*PROP_MOTIONBLUR" ) ||
  630. !strcmp( token, "*PROP_CASTSHADOW" ) ||
  631. !strcmp( token, "*PROP_RECVSHADOW" ) )
  632. {
  633. ASE_SkipRestOfLine();
  634. }
  635. }
  636. void ASE_ParseGeomObject() {
  637. aseObject_t *object;
  638. VERBOSE( ("GEOMOBJECT" ) );
  639. object = (aseObject_t *)Mem_Alloc( sizeof( aseObject_t ), TAG_MODEL );
  640. memset( object, 0, sizeof( aseObject_t ) );
  641. ase.model->objects.Append( object );
  642. ase.currentObject = object;
  643. object->frames.Resize(32, 32);
  644. ASE_ParseBracedBlock( ASE_KeyGEOMOBJECT );
  645. }
  646. static void ASE_KeyGROUP( const char *token )
  647. {
  648. if ( !strcmp( token, "*GEOMOBJECT" ) ) {
  649. ASE_ParseGeomObject();
  650. }
  651. }
  652. /*
  653. =================
  654. ASE_Parse
  655. =================
  656. */
  657. aseModel_t *ASE_Parse( const char *buffer, bool verbose ) {
  658. memset( &ase, 0, sizeof( ase ) );
  659. ase.verbose = verbose;
  660. ase.buffer = buffer;
  661. ase.len = strlen( buffer );
  662. ase.curpos = ase.buffer;
  663. ase.currentObject = NULL;
  664. // NOTE: using new operator because aseModel_t contains idList class objects
  665. ase.model = new (TAG_MODEL) aseModel_t;
  666. memset( ase.model, 0, sizeof( aseModel_t ) );
  667. ase.model->objects.Resize( 32, 32 );
  668. ase.model->materials.Resize( 32, 32 );
  669. while ( ASE_GetToken( false ) ) {
  670. if ( !strcmp( ase.token, "*3DSMAX_ASCIIEXPORT" ) ||
  671. !strcmp( ase.token, "*COMMENT" ) ) {
  672. ASE_SkipRestOfLine();
  673. } else if ( !strcmp( ase.token, "*SCENE" ) ) {
  674. ASE_SkipEnclosingBraces();
  675. } else if ( !strcmp( ase.token, "*GROUP" ) ) {
  676. ASE_GetToken( false ); // group name
  677. ASE_ParseBracedBlock( ASE_KeyGROUP );
  678. } else if ( !strcmp( ase.token, "*SHAPEOBJECT" ) ) {
  679. ASE_SkipEnclosingBraces();
  680. } else if ( !strcmp( ase.token, "*CAMERAOBJECT" ) ) {
  681. ASE_SkipEnclosingBraces();
  682. } else if ( !strcmp( ase.token, "*MATERIAL_LIST" ) ) {
  683. VERBOSE( ("MATERIAL_LIST\n") );
  684. ASE_ParseBracedBlock( ASE_KeyMATERIAL_LIST );
  685. } else if ( !strcmp( ase.token, "*GEOMOBJECT" ) ) {
  686. ASE_ParseGeomObject();
  687. } else if ( ase.token[0] ) {
  688. common->Printf( "Unknown token '%s'\n", ase.token );
  689. }
  690. }
  691. return ase.model;
  692. }
  693. /*
  694. =================
  695. ASE_Load
  696. =================
  697. */
  698. aseModel_t *ASE_Load( const char *fileName ) {
  699. char *buf;
  700. ID_TIME_T timeStamp;
  701. aseModel_t *ase;
  702. fileSystem->ReadFile( fileName, (void **)&buf, &timeStamp );
  703. if ( !buf ) {
  704. return NULL;
  705. }
  706. ase = ASE_Parse( buf, false );
  707. ase->timeStamp = timeStamp;
  708. fileSystem->FreeFile( buf );
  709. return ase;
  710. }
  711. /*
  712. =================
  713. ASE_Free
  714. =================
  715. */
  716. void ASE_Free( aseModel_t *ase ) {
  717. int i, j;
  718. aseObject_t *obj;
  719. aseMesh_t *mesh;
  720. aseMaterial_t *material;
  721. if ( !ase ) {
  722. return;
  723. }
  724. for ( i = 0; i < ase->objects.Num(); i++ ) {
  725. obj = ase->objects[i];
  726. for ( j = 0; j < obj->frames.Num(); j++ ) {
  727. mesh = obj->frames[j];
  728. if ( mesh->vertexes ) {
  729. Mem_Free( mesh->vertexes );
  730. }
  731. if ( mesh->tvertexes ) {
  732. Mem_Free( mesh->tvertexes );
  733. }
  734. if ( mesh->cvertexes ) {
  735. Mem_Free( mesh->cvertexes );
  736. }
  737. if ( mesh->faces ) {
  738. Mem_Free( mesh->faces );
  739. }
  740. Mem_Free( mesh );
  741. }
  742. obj->frames.Clear();
  743. // free the base nesh
  744. mesh = &obj->mesh;
  745. if ( mesh->vertexes ) {
  746. Mem_Free( mesh->vertexes );
  747. }
  748. if ( mesh->tvertexes ) {
  749. Mem_Free( mesh->tvertexes );
  750. }
  751. if ( mesh->cvertexes ) {
  752. Mem_Free( mesh->cvertexes );
  753. }
  754. if ( mesh->faces ) {
  755. Mem_Free( mesh->faces );
  756. }
  757. Mem_Free( obj );
  758. }
  759. ase->objects.Clear();
  760. for ( i = 0; i < ase->materials.Num(); i++ ) {
  761. material = ase->materials[i];
  762. Mem_Free( material );
  763. }
  764. ase->materials.Clear();
  765. delete ase;
  766. }