PageRenderTime 62ms CodeModel.GetById 30ms RepoModel.GetById 0ms app.codeStats 0ms

/tools/quake3/common/aselib.c

https://gitlab.com/illwieckz/netradiant
C | 882 lines | 647 code | 150 blank | 85 comment | 175 complexity | 737cba2b2960dd24a0c4325a1f16e64f MD5 | raw file
Possible License(s): GPL-2.0, LGPL-2.1, LGPL-2.0
  1. /*
  2. Copyright (C) 1999-2007 id Software, Inc. and contributors.
  3. For a list of contributors, see the accompanying CONTRIBUTORS file.
  4. This file is part of GtkRadiant.
  5. GtkRadiant is free software; you can redistribute it and/or modify
  6. it under the terms of the GNU General Public License as published by
  7. the Free Software Foundation; either version 2 of the License, or
  8. (at your option) any later version.
  9. GtkRadiant is distributed in the hope that it will be useful,
  10. but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. GNU General Public License for more details.
  13. You should have received a copy of the GNU General Public License
  14. along with GtkRadiant; if not, write to the Free Software
  15. Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
  16. */
  17. #include "aselib.h"
  18. #include "globaldefs.h"
  19. #include "inout.h"
  20. #include <assert.h>
  21. #include <stdio.h>
  22. #include <stdlib.h>
  23. #define MAX_ASE_MATERIALS 32
  24. #define MAX_ASE_OBJECTS 64
  25. #define MAX_ASE_ANIMATIONS 32
  26. #define MAX_ASE_ANIMATION_FRAMES 512
  27. #define VERBOSE( x ) { if ( ase.verbose ) { Sys_Printf x ; } }
  28. #if !GDEF_OS_WINDOWS
  29. #define strlwr strlower
  30. #endif // !GDEF_OS_WINDOWS
  31. typedef struct
  32. {
  33. float x, y, z;
  34. float nx, ny, nz;
  35. float s, t;
  36. } aseVertex_t;
  37. typedef struct
  38. {
  39. float s, t;
  40. } aseTVertex_t;
  41. typedef int aseFace_t[3];
  42. typedef struct
  43. {
  44. int numFaces;
  45. int numVertexes;
  46. int numTVertexes;
  47. int timeValue;
  48. aseVertex_t *vertexes;
  49. aseTVertex_t *tvertexes;
  50. aseFace_t *faces, *tfaces;
  51. int currentFace, currentVertex;
  52. } aseMesh_t;
  53. typedef struct
  54. {
  55. int numFrames;
  56. aseMesh_t frames[MAX_ASE_ANIMATION_FRAMES];
  57. int currentFrame;
  58. } aseMeshAnimation_t;
  59. typedef struct
  60. {
  61. char name[128];
  62. } aseMaterial_t;
  63. /*
  64. ** contains the animate sequence of a single surface
  65. ** using a single material
  66. */
  67. typedef struct
  68. {
  69. char name[128];
  70. int materialRef;
  71. int numAnimations;
  72. aseMeshAnimation_t anim;
  73. } aseGeomObject_t;
  74. typedef struct
  75. {
  76. int numMaterials;
  77. aseMaterial_t materials[MAX_ASE_MATERIALS];
  78. aseGeomObject_t objects[MAX_ASE_OBJECTS];
  79. char *buffer;
  80. char *curpos;
  81. int len;
  82. int currentObject;
  83. qboolean verbose;
  84. qboolean grabAnims;
  85. } ase_t;
  86. static char s_token[1024];
  87. static ase_t ase;
  88. static char gl_filename[1024];
  89. static void ASE_Process( void );
  90. static void ASE_FreeGeomObject( int ndx );
  91. /*
  92. ** ASE_Load
  93. */
  94. void ASE_Load( const char *filename, qboolean verbose, qboolean grabAnims ){
  95. FILE *fp = fopen( filename, "rb" );
  96. if ( !fp ) {
  97. Error( "File not found '%s'", filename );
  98. }
  99. memset( &ase, 0, sizeof( ase ) );
  100. ase.verbose = verbose;
  101. ase.grabAnims = grabAnims;
  102. ase.len = Q_filelength( fp );
  103. ase.curpos = ase.buffer = safe_malloc( ase.len );
  104. Sys_Printf( "Processing '%s'\n", filename );
  105. if ( fread( ase.buffer, ase.len, 1, fp ) != 1 ) {
  106. fclose( fp );
  107. Error( "fread() != -1 for '%s'", filename );
  108. }
  109. fclose( fp );
  110. strcpy( gl_filename, filename );
  111. ASE_Process();
  112. }
  113. /*
  114. ** ASE_Free
  115. */
  116. void ASE_Free( void ){
  117. int i;
  118. for ( i = 0; i < ase.currentObject; i++ )
  119. {
  120. ASE_FreeGeomObject( i );
  121. }
  122. }
  123. /*
  124. ** ASE_GetNumSurfaces
  125. */
  126. int ASE_GetNumSurfaces( void ){
  127. return ase.currentObject;
  128. }
  129. /*
  130. ** ASE_GetSurfaceName
  131. */
  132. const char *ASE_GetSurfaceName( int which ){
  133. aseGeomObject_t *pObject = &ase.objects[which];
  134. if ( !pObject->anim.numFrames ) {
  135. return 0;
  136. }
  137. return pObject->name;
  138. }
  139. /*
  140. ** ASE_GetSurfaceAnimation
  141. **
  142. ** Returns an animation (sequence of polysets)
  143. */
  144. polyset_t *ASE_GetSurfaceAnimation( int which, int *pNumFrames, int skipFrameStart, int skipFrameEnd, int maxFrames ){
  145. aseGeomObject_t *pObject = &ase.objects[which];
  146. polyset_t *psets;
  147. int numFramesInAnimation;
  148. int numFramesToKeep;
  149. int i, f;
  150. if ( !pObject->anim.numFrames ) {
  151. return 0;
  152. }
  153. if ( pObject->anim.numFrames > maxFrames && maxFrames != -1 ) {
  154. numFramesInAnimation = maxFrames;
  155. }
  156. else
  157. {
  158. numFramesInAnimation = pObject->anim.numFrames;
  159. if ( maxFrames != -1 ) {
  160. Sys_FPrintf( SYS_WRN, "WARNING: ASE_GetSurfaceAnimation maxFrames > numFramesInAnimation\n" );
  161. }
  162. }
  163. if ( skipFrameEnd != -1 ) {
  164. numFramesToKeep = numFramesInAnimation - ( skipFrameEnd - skipFrameStart + 1 );
  165. }
  166. else{
  167. numFramesToKeep = numFramesInAnimation;
  168. }
  169. *pNumFrames = numFramesToKeep;
  170. psets = calloc( sizeof( polyset_t ) * numFramesToKeep, 1 );
  171. for ( f = 0, i = 0; i < numFramesInAnimation; i++ )
  172. {
  173. int t;
  174. aseMesh_t *pMesh = &pObject->anim.frames[i];
  175. if ( skipFrameStart != -1 ) {
  176. if ( i >= skipFrameStart && i <= skipFrameEnd ) {
  177. continue;
  178. }
  179. }
  180. strcpy( psets[f].name, pObject->name );
  181. strcpy( psets[f].materialname, ase.materials[pObject->materialRef].name );
  182. psets[f].triangles = calloc( sizeof( triangle_t ) * pObject->anim.frames[i].numFaces, 1 );
  183. psets[f].numtriangles = pObject->anim.frames[i].numFaces;
  184. for ( t = 0; t < pObject->anim.frames[i].numFaces; t++ )
  185. {
  186. int k;
  187. for ( k = 0; k < 3; k++ )
  188. {
  189. psets[f].triangles[t].verts[k][0] = pMesh->vertexes[pMesh->faces[t][k]].x;
  190. psets[f].triangles[t].verts[k][1] = pMesh->vertexes[pMesh->faces[t][k]].y;
  191. psets[f].triangles[t].verts[k][2] = pMesh->vertexes[pMesh->faces[t][k]].z;
  192. if ( pMesh->tvertexes && pMesh->tfaces ) {
  193. psets[f].triangles[t].texcoords[k][0] = pMesh->tvertexes[pMesh->tfaces[t][k]].s;
  194. psets[f].triangles[t].texcoords[k][1] = pMesh->tvertexes[pMesh->tfaces[t][k]].t;
  195. }
  196. }
  197. }
  198. f++;
  199. }
  200. return psets;
  201. }
  202. static void ASE_FreeGeomObject( int ndx ){
  203. aseGeomObject_t *pObject;
  204. int i;
  205. pObject = &ase.objects[ndx];
  206. for ( i = 0; i < pObject->anim.numFrames; i++ )
  207. {
  208. if ( pObject->anim.frames[i].vertexes ) {
  209. free( pObject->anim.frames[i].vertexes );
  210. }
  211. if ( pObject->anim.frames[i].tvertexes ) {
  212. free( pObject->anim.frames[i].tvertexes );
  213. }
  214. if ( pObject->anim.frames[i].faces ) {
  215. free( pObject->anim.frames[i].faces );
  216. }
  217. if ( pObject->anim.frames[i].tfaces ) {
  218. free( pObject->anim.frames[i].tfaces );
  219. }
  220. }
  221. memset( pObject, 0, sizeof( *pObject ) );
  222. }
  223. static aseMesh_t *ASE_GetCurrentMesh( void ){
  224. aseGeomObject_t *pObject;
  225. if ( ase.currentObject >= MAX_ASE_OBJECTS ) {
  226. Error( "Too many GEOMOBJECTs" );
  227. return 0; // never called
  228. }
  229. pObject = &ase.objects[ase.currentObject];
  230. if ( pObject->anim.currentFrame >= MAX_ASE_ANIMATION_FRAMES ) {
  231. Error( "Too many MESHes" );
  232. return 0;
  233. }
  234. return &pObject->anim.frames[pObject->anim.currentFrame];
  235. }
  236. static int CharIsTokenDelimiter( int ch ){
  237. if ( ch <= 32 ) {
  238. return 1;
  239. }
  240. return 0;
  241. }
  242. static int ASE_GetToken( qboolean restOfLine ){
  243. int i = 0;
  244. if ( ase.buffer == 0 ) {
  245. return 0;
  246. }
  247. if ( ( ase.curpos - ase.buffer ) == ase.len ) {
  248. return 0;
  249. }
  250. // skip over crap
  251. while ( ( ( ase.curpos - ase.buffer ) < ase.len ) &&
  252. ( *ase.curpos <= 32 ) )
  253. {
  254. ase.curpos++;
  255. }
  256. while ( ( ase.curpos - ase.buffer ) < ase.len )
  257. {
  258. s_token[i] = *ase.curpos;
  259. ase.curpos++;
  260. i++;
  261. if ( ( CharIsTokenDelimiter( s_token[i - 1] ) && !restOfLine ) ||
  262. ( ( s_token[i - 1] == '\n' ) || ( s_token[i - 1] == '\r' ) ) ) {
  263. s_token[i - 1] = 0;
  264. break;
  265. }
  266. }
  267. s_token[i] = 0;
  268. return 1;
  269. }
  270. static void ASE_ParseBracedBlock( void ( *parser )( const char *token ) ){
  271. int indent = 0;
  272. while ( ASE_GetToken( qfalse ) )
  273. {
  274. if ( !strcmp( s_token, "{" ) ) {
  275. indent++;
  276. }
  277. else if ( !strcmp( s_token, "}" ) ) {
  278. --indent;
  279. if ( indent == 0 ) {
  280. break;
  281. }
  282. else if ( indent < 0 ) {
  283. Error( "Unexpected '}'" );
  284. }
  285. }
  286. else
  287. {
  288. if ( parser ) {
  289. parser( s_token );
  290. }
  291. }
  292. }
  293. }
  294. static void ASE_SkipEnclosingBraces( void ){
  295. int indent = 0;
  296. while ( ASE_GetToken( qfalse ) )
  297. {
  298. if ( !strcmp( s_token, "{" ) ) {
  299. indent++;
  300. }
  301. else if ( !strcmp( s_token, "}" ) ) {
  302. indent--;
  303. if ( indent == 0 ) {
  304. break;
  305. }
  306. else if ( indent < 0 ) {
  307. Error( "Unexpected '}'" );
  308. }
  309. }
  310. }
  311. }
  312. static void ASE_SkipRestOfLine( void ){
  313. ASE_GetToken( qtrue );
  314. }
  315. static void ASE_KeyMAP_DIFFUSE( const char *token ){
  316. char bitmap[1024];
  317. char filename[1024];
  318. int i = 0;
  319. strcpy( filename, gl_filename );
  320. if ( !strcmp( token, "*BITMAP" ) ) {
  321. ASE_GetToken( qfalse );
  322. // the purpose of this whole chunk of code below is to extract the relative path
  323. // from a full path in the ASE
  324. strcpy( bitmap, s_token + 1 );
  325. if ( strchr( bitmap, '"' ) ) {
  326. *strchr( bitmap, '"' ) = 0;
  327. }
  328. /* convert backslash to slash */
  329. while ( bitmap[i] )
  330. {
  331. if ( bitmap[i] == '\\' ) {
  332. bitmap[i] = '/';
  333. }
  334. i++;
  335. }
  336. /* remove filename from path */
  337. for ( i = strlen( filename ); i > 0; i-- )
  338. {
  339. if ( filename[i] == '/' ) {
  340. filename[i] = '\0';
  341. break;
  342. }
  343. }
  344. /* replaces a relative path with a full path */
  345. if ( bitmap[0] == '.' && bitmap[1] == '.' && bitmap[2] == '/' ) {
  346. while ( bitmap[0] == '.' && bitmap[1] == '.' && bitmap[2] == '/' )
  347. {
  348. /* remove last item from path */
  349. for ( i = strlen( filename ); i > 0; i-- )
  350. {
  351. if ( filename[i] == '/' ) {
  352. filename[i] = '\0';
  353. break;
  354. }
  355. }
  356. strcpy( bitmap, &bitmap[3] );
  357. }
  358. strcat( filename, "/" );
  359. strcat( filename, bitmap );
  360. strcpy( bitmap, filename );
  361. }
  362. if ( strstr( bitmap, gamedir ) ) {
  363. strcpy( ase.materials[ase.numMaterials].name, strstr( bitmap, gamedir ) + strlen( gamedir ) );
  364. Sys_Printf( "material name: \'%s\'\n", strstr( bitmap, gamedir ) + strlen( gamedir ) );
  365. }
  366. else
  367. {
  368. sprintf( ase.materials[ase.numMaterials].name, "(not converted: '%s')", bitmap );
  369. Sys_FPrintf( SYS_WRN, "WARNING: illegal material name '%s'\n", bitmap );
  370. }
  371. }
  372. else
  373. {
  374. }
  375. }
  376. static void ASE_KeyMATERIAL( const char *token ){
  377. if ( !strcmp( token, "*MAP_DIFFUSE" ) ) {
  378. ASE_ParseBracedBlock( ASE_KeyMAP_DIFFUSE );
  379. }
  380. else
  381. {
  382. }
  383. }
  384. static void ASE_KeyMATERIAL_LIST( const char *token ){
  385. if ( !strcmp( token, "*MATERIAL_COUNT" ) ) {
  386. ASE_GetToken( qfalse );
  387. VERBOSE( ( "..num materials: %s\n", s_token ) );
  388. if ( atoi( s_token ) > MAX_ASE_MATERIALS ) {
  389. Error( "Too many materials!" );
  390. }
  391. ase.numMaterials = 0;
  392. }
  393. else if ( !strcmp( token, "*MATERIAL" ) ) {
  394. VERBOSE( ( "..material %d ", ase.numMaterials ) );
  395. ASE_ParseBracedBlock( ASE_KeyMATERIAL );
  396. ase.numMaterials++;
  397. }
  398. }
  399. static void ASE_KeyMESH_VERTEX_LIST( const char *token ){
  400. aseMesh_t *pMesh = ASE_GetCurrentMesh();
  401. if ( !strcmp( token, "*MESH_VERTEX" ) ) {
  402. ASE_GetToken( qfalse ); // skip number
  403. ASE_GetToken( qfalse );
  404. pMesh->vertexes[pMesh->currentVertex].y = atof( s_token );
  405. ASE_GetToken( qfalse );
  406. pMesh->vertexes[pMesh->currentVertex].x = -atof( s_token );
  407. ASE_GetToken( qfalse );
  408. pMesh->vertexes[pMesh->currentVertex].z = atof( s_token );
  409. pMesh->currentVertex++;
  410. if ( pMesh->currentVertex > pMesh->numVertexes ) {
  411. Error( "pMesh->currentVertex >= pMesh->numVertexes" );
  412. }
  413. }
  414. else
  415. {
  416. Error( "Unknown token '%s' while parsing MESH_VERTEX_LIST", token );
  417. }
  418. }
  419. static void ASE_KeyMESH_FACE_LIST( const char *token ){
  420. aseMesh_t *pMesh = ASE_GetCurrentMesh();
  421. if ( !strcmp( token, "*MESH_FACE" ) ) {
  422. ASE_GetToken( qfalse ); // skip face number
  423. ASE_GetToken( qfalse ); // skip label
  424. ASE_GetToken( qfalse ); // first vertex
  425. pMesh->faces[pMesh->currentFace][0] = atoi( s_token );
  426. ASE_GetToken( qfalse ); // skip label
  427. ASE_GetToken( qfalse ); // second vertex
  428. pMesh->faces[pMesh->currentFace][2] = atoi( s_token );
  429. ASE_GetToken( qfalse ); // skip label
  430. ASE_GetToken( qfalse ); // third vertex
  431. pMesh->faces[pMesh->currentFace][1] = atoi( s_token );
  432. ASE_GetToken( qtrue );
  433. /*
  434. if ( ( p = strstr( s_token, "*MESH_MTLID" ) ) != 0 )
  435. {
  436. p += strlen( "*MESH_MTLID" ) + 1;
  437. mtlID = atoi( p );
  438. }
  439. else
  440. {
  441. Error( "No *MESH_MTLID found for face!" );
  442. }
  443. */
  444. pMesh->currentFace++;
  445. }
  446. else
  447. {
  448. Error( "Unknown token '%s' while parsing MESH_FACE_LIST", token );
  449. }
  450. }
  451. static void ASE_KeyTFACE_LIST( const char *token ){
  452. aseMesh_t *pMesh = ASE_GetCurrentMesh();
  453. if ( !strcmp( token, "*MESH_TFACE" ) ) {
  454. int a, b, c;
  455. ASE_GetToken( qfalse );
  456. ASE_GetToken( qfalse );
  457. a = atoi( s_token );
  458. ASE_GetToken( qfalse );
  459. c = atoi( s_token );
  460. ASE_GetToken( qfalse );
  461. b = atoi( s_token );
  462. pMesh->tfaces[pMesh->currentFace][0] = a;
  463. pMesh->tfaces[pMesh->currentFace][1] = b;
  464. pMesh->tfaces[pMesh->currentFace][2] = c;
  465. pMesh->currentFace++;
  466. }
  467. else
  468. {
  469. Error( "Unknown token '%s' in MESH_TFACE", token );
  470. }
  471. }
  472. static void ASE_KeyMESH_TVERTLIST( const char *token ){
  473. aseMesh_t *pMesh = ASE_GetCurrentMesh();
  474. if ( !strcmp( token, "*MESH_TVERT" ) ) {
  475. char u[80], v[80], w[80];
  476. ASE_GetToken( qfalse );
  477. ASE_GetToken( qfalse );
  478. strcpy( u, s_token );
  479. ASE_GetToken( qfalse );
  480. strcpy( v, s_token );
  481. ASE_GetToken( qfalse );
  482. strcpy( w, s_token );
  483. pMesh->tvertexes[pMesh->currentVertex].s = atof( u );
  484. pMesh->tvertexes[pMesh->currentVertex].t = 1.0f - atof( v );
  485. pMesh->currentVertex++;
  486. if ( pMesh->currentVertex > pMesh->numTVertexes ) {
  487. Error( "pMesh->currentVertex > pMesh->numTVertexes" );
  488. }
  489. }
  490. else
  491. {
  492. Error( "Unknown token '%s' while parsing MESH_TVERTLIST", token );
  493. }
  494. }
  495. static void ASE_KeyMESH( const char *token ){
  496. aseMesh_t *pMesh = ASE_GetCurrentMesh();
  497. if ( !strcmp( token, "*TIMEVALUE" ) ) {
  498. ASE_GetToken( qfalse );
  499. pMesh->timeValue = atoi( s_token );
  500. VERBOSE( ( ".....timevalue: %d\n", pMesh->timeValue ) );
  501. }
  502. else if ( !strcmp( token, "*MESH_NUMVERTEX" ) ) {
  503. ASE_GetToken( qfalse );
  504. pMesh->numVertexes = atoi( s_token );
  505. VERBOSE( ( ".....TIMEVALUE: %d\n", pMesh->timeValue ) );
  506. VERBOSE( ( ".....num vertexes: %d\n", pMesh->numVertexes ) );
  507. }
  508. else if ( !strcmp( token, "*MESH_NUMFACES" ) ) {
  509. ASE_GetToken( qfalse );
  510. pMesh->numFaces = atoi( s_token );
  511. VERBOSE( ( ".....num faces: %d\n", pMesh->numFaces ) );
  512. }
  513. else if ( !strcmp( token, "*MESH_NUMTVFACES" ) ) {
  514. ASE_GetToken( qfalse );
  515. if ( atoi( s_token ) != pMesh->numFaces ) {
  516. Error( "MESH_NUMTVFACES != MESH_NUMFACES" );
  517. }
  518. }
  519. else if ( !strcmp( token, "*MESH_NUMTVERTEX" ) ) {
  520. ASE_GetToken( qfalse );
  521. pMesh->numTVertexes = atoi( s_token );
  522. VERBOSE( ( ".....num tvertexes: %d\n", pMesh->numTVertexes ) );
  523. }
  524. else if ( !strcmp( token, "*MESH_VERTEX_LIST" ) ) {
  525. pMesh->vertexes = calloc( sizeof( aseVertex_t ) * pMesh->numVertexes, 1 );
  526. pMesh->currentVertex = 0;
  527. VERBOSE( ( ".....parsing MESH_VERTEX_LIST\n" ) );
  528. ASE_ParseBracedBlock( ASE_KeyMESH_VERTEX_LIST );
  529. }
  530. else if ( !strcmp( token, "*MESH_TVERTLIST" ) ) {
  531. pMesh->currentVertex = 0;
  532. pMesh->tvertexes = calloc( sizeof( aseTVertex_t ) * pMesh->numTVertexes, 1 );
  533. VERBOSE( ( ".....parsing MESH_TVERTLIST\n" ) );
  534. ASE_ParseBracedBlock( ASE_KeyMESH_TVERTLIST );
  535. }
  536. else if ( !strcmp( token, "*MESH_FACE_LIST" ) ) {
  537. pMesh->faces = calloc( sizeof( aseFace_t ) * pMesh->numFaces, 1 );
  538. pMesh->currentFace = 0;
  539. VERBOSE( ( ".....parsing MESH_FACE_LIST\n" ) );
  540. ASE_ParseBracedBlock( ASE_KeyMESH_FACE_LIST );
  541. }
  542. else if ( !strcmp( token, "*MESH_TFACELIST" ) ) {
  543. pMesh->tfaces = calloc( sizeof( aseFace_t ) * pMesh->numFaces, 1 );
  544. pMesh->currentFace = 0;
  545. VERBOSE( ( ".....parsing MESH_TFACE_LIST\n" ) );
  546. ASE_ParseBracedBlock( ASE_KeyTFACE_LIST );
  547. }
  548. else if ( !strcmp( token, "*MESH_NORMALS" ) ) {
  549. ASE_ParseBracedBlock( 0 );
  550. }
  551. }
  552. static void ASE_KeyMESH_ANIMATION( const char *token ){
  553. aseMesh_t *pMesh = ASE_GetCurrentMesh();
  554. // loads a single animation frame
  555. if ( !strcmp( token, "*MESH" ) ) {
  556. VERBOSE( ( "...found MESH\n" ) );
  557. assert( pMesh->faces == 0 );
  558. assert( pMesh->vertexes == 0 );
  559. assert( pMesh->tvertexes == 0 );
  560. memset( pMesh, 0, sizeof( *pMesh ) );
  561. ASE_ParseBracedBlock( ASE_KeyMESH );
  562. if ( ++ase.objects[ase.currentObject].anim.currentFrame == MAX_ASE_ANIMATION_FRAMES ) {
  563. Error( "Too many animation frames" );
  564. }
  565. }
  566. else
  567. {
  568. Error( "Unknown token '%s' while parsing MESH_ANIMATION", token );
  569. }
  570. }
  571. static void ASE_KeyGEOMOBJECT( const char *token ){
  572. if ( !strcmp( token, "*NODE_NAME" ) ) {
  573. char *name = ase.objects[ase.currentObject].name;
  574. ASE_GetToken( qtrue );
  575. VERBOSE( ( " %s\n", s_token ) );
  576. strcpy( ase.objects[ase.currentObject].name, s_token + 1 );
  577. if ( strchr( ase.objects[ase.currentObject].name, '"' ) ) {
  578. *strchr( ase.objects[ase.currentObject].name, '"' ) = 0;
  579. }
  580. if ( strstr( name, "tag" ) == name ) {
  581. while ( strchr( name, '_' ) != strrchr( name, '_' ) )
  582. {
  583. *strrchr( name, '_' ) = 0;
  584. }
  585. while ( strrchr( name, ' ' ) )
  586. {
  587. *strrchr( name, ' ' ) = 0;
  588. }
  589. }
  590. }
  591. else if ( !strcmp( token, "*NODE_PARENT" ) ) {
  592. ASE_SkipRestOfLine();
  593. }
  594. // ignore unused data blocks
  595. else if ( !strcmp( token, "*NODE_TM" ) ||
  596. !strcmp( token, "*TM_ANIMATION" ) ) {
  597. ASE_ParseBracedBlock( 0 );
  598. }
  599. // ignore regular meshes that aren't part of animation
  600. else if ( !strcmp( token, "*MESH" ) && !ase.grabAnims ) {
  601. /*
  602. if ( strstr( ase.objects[ase.currentObject].name, "tag_" ) == ase.objects[ase.currentObject].name )
  603. {
  604. s_forceStaticMesh = true;
  605. ASE_ParseBracedBlock( ASE_KeyMESH );
  606. s_forceStaticMesh = false;
  607. }
  608. */
  609. ASE_ParseBracedBlock( ASE_KeyMESH );
  610. if ( ++ase.objects[ase.currentObject].anim.currentFrame == MAX_ASE_ANIMATION_FRAMES ) {
  611. Error( "Too many animation frames" );
  612. }
  613. ase.objects[ase.currentObject].anim.numFrames = ase.objects[ase.currentObject].anim.currentFrame;
  614. ase.objects[ase.currentObject].numAnimations++;
  615. /*
  616. // ignore meshes that aren't part of animations if this object isn't a
  617. // a tag
  618. else
  619. {
  620. ASE_ParseBracedBlock( 0 );
  621. }
  622. */
  623. }
  624. // according to spec these are obsolete
  625. else if ( !strcmp( token, "*MATERIAL_REF" ) ) {
  626. ASE_GetToken( qfalse );
  627. ase.objects[ase.currentObject].materialRef = atoi( s_token );
  628. }
  629. // loads a sequence of animation frames
  630. else if ( !strcmp( token, "*MESH_ANIMATION" ) ) {
  631. if ( ase.grabAnims ) {
  632. VERBOSE( ( "..found MESH_ANIMATION\n" ) );
  633. if ( ase.objects[ase.currentObject].numAnimations ) {
  634. Error( "Multiple MESH_ANIMATIONS within a single GEOM_OBJECT" );
  635. }
  636. ASE_ParseBracedBlock( ASE_KeyMESH_ANIMATION );
  637. ase.objects[ase.currentObject].anim.numFrames = ase.objects[ase.currentObject].anim.currentFrame;
  638. ase.objects[ase.currentObject].numAnimations++;
  639. }
  640. else
  641. {
  642. ASE_SkipEnclosingBraces();
  643. }
  644. }
  645. // skip unused info
  646. else if ( !strcmp( token, "*PROP_MOTIONBLUR" ) ||
  647. !strcmp( token, "*PROP_CASTSHADOW" ) ||
  648. !strcmp( token, "*PROP_RECVSHADOW" ) ) {
  649. ASE_SkipRestOfLine();
  650. }
  651. }
  652. static void ConcatenateObjects( aseGeomObject_t *pObjA, aseGeomObject_t *pObjB ){
  653. }
  654. static void CollapseObjects( void ){
  655. int i;
  656. int numObjects = ase.currentObject;
  657. for ( i = 0; i < numObjects; i++ )
  658. {
  659. int j;
  660. // skip tags
  661. if ( strstr( ase.objects[i].name, "tag" ) == ase.objects[i].name ) {
  662. continue;
  663. }
  664. if ( !ase.objects[i].numAnimations ) {
  665. continue;
  666. }
  667. for ( j = i + 1; j < numObjects; j++ )
  668. {
  669. if ( strstr( ase.objects[j].name, "tag" ) == ase.objects[j].name ) {
  670. continue;
  671. }
  672. if ( ase.objects[i].materialRef == ase.objects[j].materialRef ) {
  673. if ( ase.objects[j].numAnimations ) {
  674. ConcatenateObjects( &ase.objects[i], &ase.objects[j] );
  675. }
  676. }
  677. }
  678. }
  679. }
  680. /*
  681. ** ASE_Process
  682. */
  683. static void ASE_Process( void ){
  684. while ( ASE_GetToken( qfalse ) )
  685. {
  686. if ( !strcmp( s_token, "*3DSMAX_ASCIIEXPORT" ) ||
  687. !strcmp( s_token, "*COMMENT" ) ) {
  688. ASE_SkipRestOfLine();
  689. }
  690. else if ( !strcmp( s_token, "*SCENE" ) ) {
  691. ASE_SkipEnclosingBraces();
  692. }
  693. else if ( !strcmp( s_token, "*MATERIAL_LIST" ) ) {
  694. VERBOSE( ( "MATERIAL_LIST\n" ) );
  695. ASE_ParseBracedBlock( ASE_KeyMATERIAL_LIST );
  696. }
  697. else if ( !strcmp( s_token, "*GEOMOBJECT" ) ) {
  698. VERBOSE( ( "GEOMOBJECT" ) );
  699. ASE_ParseBracedBlock( ASE_KeyGEOMOBJECT );
  700. if ( strstr( ase.objects[ase.currentObject].name, "Bip" ) ||
  701. strstr( ase.objects[ase.currentObject].name, "ignore_" ) ) {
  702. ASE_FreeGeomObject( ase.currentObject );
  703. VERBOSE( ( "(discarding BIP/ignore object)\n" ) );
  704. }
  705. else if ( ( strstr( ase.objects[ase.currentObject].name, "h_" ) != ase.objects[ase.currentObject].name ) &&
  706. ( strstr( ase.objects[ase.currentObject].name, "l_" ) != ase.objects[ase.currentObject].name ) &&
  707. ( strstr( ase.objects[ase.currentObject].name, "u_" ) != ase.objects[ase.currentObject].name ) &&
  708. ( strstr( ase.objects[ase.currentObject].name, "tag" ) != ase.objects[ase.currentObject].name ) &&
  709. ase.grabAnims ) {
  710. VERBOSE( ( "(ignoring improperly labeled object '%s')\n", ase.objects[ase.currentObject].name ) );
  711. ASE_FreeGeomObject( ase.currentObject );
  712. }
  713. else
  714. {
  715. if ( ++ase.currentObject == MAX_ASE_OBJECTS ) {
  716. Error( "Too many GEOMOBJECTs" );
  717. }
  718. }
  719. }
  720. else if ( s_token[0] ) {
  721. Error( "Unknown token '%s'\n", s_token );
  722. }
  723. }
  724. if ( !ase.currentObject ) {
  725. Error( "No animation data!" );
  726. }
  727. CollapseObjects();
  728. }