00001
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027 #include "../bsp.h"
00028 #include "shared.h"
00029 #include "aselib.h"
00030
00031 #define MAX_ASE_MATERIALS 32
00032 #define MAX_ASE_OBJECTS 64
00033 #define MAX_ASE_ANIMATIONS 32
00034 #define MAX_ASE_ANIMATION_FRAMES 512
00035
00036 #define VERBOSE(x) { if (ase.verbose) { Com_Printf x; } }
00037
00038 typedef struct {
00039 float x, y, z;
00040 float nx, ny, nz;
00041 float s, t;
00042 } aseVertex_t;
00043
00044 typedef struct {
00045 float s, t;
00046 } aseTVertex_t;
00047
00048 typedef int aseFace_t[3];
00049
00050 typedef struct {
00051 int numFaces;
00052 int numVertexes;
00053 int numTVertexes;
00054
00055 int timeValue;
00056
00057 aseVertex_t *vertexes;
00058 aseTVertex_t *tvertexes;
00059 aseFace_t *faces, *tfaces;
00060
00061 int currentFace, currentVertex;
00062 } aseMesh_t;
00063
00064 typedef struct {
00065 int numFrames;
00066 aseMesh_t frames[MAX_ASE_ANIMATION_FRAMES];
00067
00068 int currentFrame;
00069 } aseMeshAnimation_t;
00070
00071 typedef struct {
00072 char name[MAX_QPATH];
00073 } aseMaterial_t;
00074
00078 typedef struct {
00079 char name[MAX_QPATH];
00080
00081 int materialRef;
00082 int numAnimations;
00083
00084 aseMeshAnimation_t anim;
00085 } aseGeomObject_t;
00086
00087 typedef struct {
00088 int numMaterials;
00089 aseMaterial_t materials[MAX_ASE_MATERIALS];
00090 aseGeomObject_t objects[MAX_ASE_OBJECTS];
00091
00092 char *buffer;
00093 char *curpos;
00094 int len;
00095
00096 int currentObject;
00097 qboolean verbose;
00098 } ase_t;
00099
00100 static char s_token[1024];
00101 static ase_t ase;
00102
00103 static void ASE_Process(void);
00104 static void ASE_FreeGeomObject(int ndx);
00105
00106 void ASE_Load (const char *filename, qboolean verbose)
00107 {
00108 qFILE file;
00109
00110 FS_OpenFile(filename, &file, FILE_READ);
00111 if (!file.f && !file.z)
00112 Sys_Error("File not found '%s'", filename);
00113
00114 memset(&ase, 0, sizeof(ase));
00115
00116 ase.verbose = verbose;
00117 ase.len = FS_FileLength(&file);
00118
00119 ase.curpos = ase.buffer = Mem_Alloc(ase.len);
00120 if (!ase.curpos)
00121 Sys_Error("Could not allocate memory for ase loading");
00122
00123 Verb_Printf(VERB_EXTRA, "Processing '%s'\n", filename);
00124
00125 if (FS_Read(ase.buffer, ase.len, &file) != 1) {
00126 FS_CloseFile(&file);
00127 Sys_Error("fread() != -1 for '%s'", filename);
00128 }
00129
00130 FS_CloseFile(&file);
00131
00132 ASE_Process();
00133 }
00134
00135 void ASE_Free (void)
00136 {
00137 int i;
00138
00139 for (i = 0; i < ase.currentObject; i++)
00140 ASE_FreeGeomObject(i);
00141 }
00142
00143 int ASE_GetNumSurfaces (void)
00144 {
00145 return ase.currentObject;
00146 }
00147
00148 const char *ASE_GetSurfaceName (int which)
00149 {
00150 aseGeomObject_t *pObject = &ase.objects[which];
00151
00152 if (!pObject->anim.numFrames)
00153 return 0;
00154
00155 return pObject->name;
00156 }
00157
00161 polyset_t *ASE_GetSurfaceAnimation (int whichSurface)
00162 {
00163 aseGeomObject_t *pObject = &ase.objects[whichSurface];
00164 polyset_t *psets;
00165 int numFramesInAnimation;
00166 int i, f;
00167
00168 if (!pObject->anim.numFrames)
00169 return 0;
00170
00171 numFramesInAnimation = pObject->anim.numFrames;
00172
00173 psets = Mem_Alloc(sizeof(polyset_t) * numFramesInAnimation);
00174
00175 for (f = 0, i = 0; i < numFramesInAnimation; i++) {
00176 int t;
00177 aseMesh_t *pMesh = &pObject->anim.frames[i];
00178
00179 strcpy(psets[f].name, pObject->name);
00180 strcpy(psets[f].materialname, ase.materials[pObject->materialRef].name);
00181
00182 psets[f].triangles = calloc(sizeof(triangle_t) * pObject->anim.frames[i].numFaces, 1);
00183 psets[f].numtriangles = pObject->anim.frames[i].numFaces;
00184
00185 for (t = 0; t < pObject->anim.frames[i].numFaces; t++) {
00186 int k;
00187
00188 for (k = 0; k < 3; k++) {
00189 psets[f].triangles[t].verts[k][0] = pMesh->vertexes[pMesh->faces[t][k]].x;
00190 psets[f].triangles[t].verts[k][1] = pMesh->vertexes[pMesh->faces[t][k]].y;
00191 psets[f].triangles[t].verts[k][2] = pMesh->vertexes[pMesh->faces[t][k]].z;
00192
00193 if (pMesh->tvertexes && pMesh->tfaces) {
00194 psets[f].triangles[t].texcoords[k][0] = pMesh->tvertexes[pMesh->tfaces[t][k]].s;
00195 psets[f].triangles[t].texcoords[k][1] = pMesh->tvertexes[pMesh->tfaces[t][k]].t;
00196 }
00197 }
00198 }
00199
00200 f++;
00201 }
00202
00203 return psets;
00204 }
00205
00206 static void ASE_FreeGeomObject (int ndx)
00207 {
00208 aseGeomObject_t *pObject;
00209 int i;
00210
00211 pObject = &ase.objects[ndx];
00212
00213 for (i = 0; i < pObject->anim.numFrames; i++) {
00214 if (pObject->anim.frames[i].vertexes)
00215 Mem_Free(pObject->anim.frames[i].vertexes);
00216 if (pObject->anim.frames[i].tvertexes)
00217 Mem_Free(pObject->anim.frames[i].tvertexes);
00218 if (pObject->anim.frames[i].faces)
00219 Mem_Free(pObject->anim.frames[i].faces);
00220 if (pObject->anim.frames[i].tfaces)
00221 Mem_Free(pObject->anim.frames[i].tfaces);
00222 }
00223
00224 memset(pObject, 0, sizeof(*pObject));
00225 }
00226
00227 static aseMesh_t *ASE_GetCurrentMesh (void)
00228 {
00229 aseGeomObject_t *pObject;
00230
00231 if (ase.currentObject >= MAX_ASE_OBJECTS)
00232 Sys_Error("Too many GEOMOBJECTs");
00233
00234 pObject = &ase.objects[ase.currentObject];
00235
00236 if (pObject->anim.currentFrame >= MAX_ASE_ANIMATION_FRAMES)
00237 Sys_Error("Too many MESHes");
00238
00239 return &pObject->anim.frames[pObject->anim.currentFrame];
00240 }
00241
00242 static inline int CharIsTokenDelimiter (int ch)
00243 {
00244 if (ch <= ' ')
00245 return 1;
00246 return 0;
00247 }
00248
00249 static int ASE_GetToken (qboolean restOfLine)
00250 {
00251 int i = 0;
00252
00253 if (ase.buffer == 0)
00254 return 0;
00255
00256 if ((ase.curpos - ase.buffer) == ase.len)
00257 return 0;
00258
00259
00260 while (ase.curpos - ase.buffer < ase.len && *ase.curpos <= ' ') {
00261 ase.curpos++;
00262 }
00263
00264 while ((ase.curpos - ase.buffer) < ase.len) {
00265 s_token[i] = *ase.curpos;
00266
00267 ase.curpos++;
00268 i++;
00269
00270 if ((CharIsTokenDelimiter(s_token[i - 1]) && !restOfLine) ||
00271 (s_token[i - 1] == '\n' || s_token[i - 1] == '\r')) {
00272 s_token[i - 1] = 0;
00273 break;
00274 }
00275 }
00276
00277 s_token[i] = 0;
00278
00279 return 1;
00280 }
00281
00282 static void ASE_ParseBracedBlock (void (*parser)(const char *token))
00283 {
00284 int indent = 0;
00285
00286 while (ASE_GetToken(qfalse)) {
00287 if (!strcmp(s_token, "{")) {
00288 indent++;
00289 } else if (!strcmp(s_token, "}")) {
00290 --indent;
00291 if (indent == 0)
00292 break;
00293 else if (indent < 0)
00294 Sys_Error("Unexpected '}'");
00295 } else {
00296 if (parser)
00297 parser(s_token);
00298 }
00299 }
00300 }
00301
00302 static void ASE_SkipEnclosingBraces (void)
00303 {
00304 int indent = 0;
00305
00306 while (ASE_GetToken(qfalse)) {
00307 if (!strcmp(s_token, "{")) {
00308 indent++;
00309 } else if (!strcmp(s_token, "}")) {
00310 indent--;
00311 if (indent == 0)
00312 break;
00313 else if (indent < 0)
00314 Sys_Error("Unexpected '}'");
00315 }
00316 }
00317 }
00318
00319 static void ASE_SkipRestOfLine (void)
00320 {
00321 ASE_GetToken(qtrue);
00322 }
00323
00324 static void ASE_KeyMAP_DIFFUSE (const char *token)
00325 {
00326 if (!strcmp(token, "*BITMAP")) {
00327 const char *bitmap;
00328 size_t len;
00329
00330 ASE_GetToken(qfalse);
00331
00332
00333 bitmap = &s_token[1];
00334 len = strlen(bitmap) - 1;
00335 s_token[len] = '\0';
00336
00337 Com_StripExtension(bitmap, ase.materials[ase.numMaterials].name, MAX_QPATH);
00338 Verb_Printf(VERB_EXTRA, "ase material name: \'%s\'\n", ase.materials[ase.numMaterials].name);
00339 }
00340 }
00341
00342 static void ASE_KeyMATERIAL (const char *token)
00343 {
00344 if (!strcmp(token, "*MAP_DIFFUSE"))
00345 ASE_ParseBracedBlock(ASE_KeyMAP_DIFFUSE);
00346 }
00347
00348 static void ASE_KeyMATERIAL_LIST (const char *token)
00349 {
00350 if (!strcmp(token, "*MATERIAL_COUNT")) {
00351 ASE_GetToken(qfalse);
00352 VERBOSE(("..num materials: %s\n", s_token));
00353 if (atoi(s_token) > MAX_ASE_MATERIALS) {
00354 Sys_Error("Too many materials!");
00355 }
00356 ase.numMaterials = 0;
00357 } else if (!strcmp(token, "*MATERIAL")) {
00358 VERBOSE(("..material %d ", ase.numMaterials));
00359 ASE_ParseBracedBlock(ASE_KeyMATERIAL);
00360 ase.numMaterials++;
00361 }
00362 }
00363
00364 static void ASE_KeyMESH_VERTEX_LIST (const char *token)
00365 {
00366 aseMesh_t *pMesh = ASE_GetCurrentMesh();
00367
00368 if (!strcmp(token, "*MESH_VERTEX")) {
00369 ASE_GetToken(qfalse);
00370
00371 ASE_GetToken(qfalse);
00372 pMesh->vertexes[pMesh->currentVertex].y = atof(s_token);
00373
00374 ASE_GetToken(qfalse);
00375 pMesh->vertexes[pMesh->currentVertex].x = -atof(s_token);
00376
00377 ASE_GetToken(qfalse);
00378 pMesh->vertexes[pMesh->currentVertex].z = atof(s_token);
00379
00380 pMesh->currentVertex++;
00381
00382 if (pMesh->currentVertex > pMesh->numVertexes)
00383 Sys_Error("pMesh->currentVertex >= pMesh->numVertexes");
00384 } else
00385 Sys_Error("Unknown token '%s' while parsing MESH_VERTEX_LIST", token);
00386 }
00387
00388 static void ASE_KeyMESH_FACE_LIST (const char *token)
00389 {
00390 aseMesh_t *pMesh = ASE_GetCurrentMesh();
00391
00392 if (!strcmp(token, "*MESH_FACE")) {
00393 ASE_GetToken(qfalse);
00394
00395 ASE_GetToken(qfalse);
00396 ASE_GetToken(qfalse);
00397 pMesh->faces[pMesh->currentFace][0] = atoi(s_token);
00398
00399 ASE_GetToken(qfalse);
00400 ASE_GetToken(qfalse);
00401 pMesh->faces[pMesh->currentFace][2] = atoi(s_token);
00402
00403 ASE_GetToken(qfalse);
00404 ASE_GetToken(qfalse);
00405 pMesh->faces[pMesh->currentFace][1] = atoi(s_token);
00406
00407 ASE_GetToken(qtrue);
00408
00409 #if 0
00410 if ((p = strstr(s_token, "*MESH_MTLID")) != 0) {
00411 p += strlen("*MESH_MTLID") + 1;
00412 mtlID = atoi(p);
00413 } else {
00414 Sys_Error("No *MESH_MTLID found for face!");
00415 }
00416 #endif
00417
00418 pMesh->currentFace++;
00419 } else
00420 Sys_Error("Unknown token '%s' while parsing MESH_FACE_LIST", token);
00421 }
00422
00423 static void ASE_KeyTFACE_LIST (const char *token)
00424 {
00425 aseMesh_t *pMesh = ASE_GetCurrentMesh();
00426
00427 if (!strcmp(token, "*MESH_TFACE")) {
00428 int a, b, c;
00429
00430 ASE_GetToken(qfalse);
00431
00432 ASE_GetToken(qfalse);
00433 a = atoi(s_token);
00434 ASE_GetToken(qfalse);
00435 c = atoi(s_token);
00436 ASE_GetToken(qfalse);
00437 b = atoi(s_token);
00438
00439 pMesh->tfaces[pMesh->currentFace][0] = a;
00440 pMesh->tfaces[pMesh->currentFace][1] = b;
00441 pMesh->tfaces[pMesh->currentFace][2] = c;
00442
00443 pMesh->currentFace++;
00444 } else
00445 Sys_Error("Unknown token '%s' in MESH_TFACE", token);
00446 }
00447
00448 static void ASE_KeyMESH_TVERTLIST (const char *token)
00449 {
00450 aseMesh_t *pMesh = ASE_GetCurrentMesh();
00451
00452 if (!strcmp(token, "*MESH_TVERT")) {
00453 char u[80], v[80], w[80];
00454
00455 ASE_GetToken(qfalse);
00456
00457 ASE_GetToken(qfalse);
00458 strcpy(u, s_token);
00459
00460 ASE_GetToken(qfalse);
00461 strcpy(v, s_token);
00462
00463 ASE_GetToken(qfalse);
00464 strcpy(w, s_token);
00465
00466 pMesh->tvertexes[pMesh->currentVertex].s = atof(u);
00467 pMesh->tvertexes[pMesh->currentVertex].t = 1.0f - atof(v);
00468
00469 pMesh->currentVertex++;
00470
00471 if (pMesh->currentVertex > pMesh->numTVertexes) {
00472 Sys_Error("pMesh->currentVertex > pMesh->numTVertexes");
00473 }
00474 } else
00475 Sys_Error("Unknown token '%s' while parsing MESH_TVERTLIST", token);
00476 }
00477
00478 static void ASE_KeyMESH (const char *token)
00479 {
00480 aseMesh_t *pMesh = ASE_GetCurrentMesh();
00481
00482 if (!strcmp(token, "*TIMEVALUE")) {
00483 ASE_GetToken(qfalse);
00484
00485 pMesh->timeValue = atoi(s_token);
00486 VERBOSE((".....timevalue: %d\n", pMesh->timeValue));
00487 } else if (!strcmp(token, "*MESH_NUMVERTEX")) {
00488 ASE_GetToken(qfalse);
00489
00490 pMesh->numVertexes = atoi(s_token);
00491 VERBOSE((".....TIMEVALUE: %d\n", pMesh->timeValue));
00492 VERBOSE((".....num vertexes: %d\n", pMesh->numVertexes));
00493 } else if (!strcmp(token, "*MESH_NUMFACES")) {
00494 ASE_GetToken(qfalse);
00495
00496 pMesh->numFaces = atoi(s_token);
00497 VERBOSE((".....num faces: %d\n", pMesh->numFaces));
00498 } else if (!strcmp(token, "*MESH_NUMTVFACES")) {
00499 ASE_GetToken(qfalse);
00500
00501 if (atoi(s_token) != pMesh->numFaces)
00502 Sys_Error("MESH_NUMTVFACES != MESH_NUMFACES");
00503 } else if (!strcmp(token, "*MESH_NUMTVERTEX")) {
00504 ASE_GetToken(qfalse);
00505
00506 pMesh->numTVertexes = atoi(s_token);
00507 VERBOSE((".....num tvertexes: %d\n", pMesh->numTVertexes));
00508 } else if (!strcmp(token, "*MESH_VERTEX_LIST")) {
00509 pMesh->vertexes = calloc(sizeof(aseVertex_t) * pMesh->numVertexes, 1);
00510 pMesh->currentVertex = 0;
00511 VERBOSE((".....parsing MESH_VERTEX_LIST\n"));
00512 ASE_ParseBracedBlock(ASE_KeyMESH_VERTEX_LIST);
00513 } else if (!strcmp(token, "*MESH_TVERTLIST")) {
00514 pMesh->currentVertex = 0;
00515 pMesh->tvertexes = calloc(sizeof(aseTVertex_t) * pMesh->numTVertexes, 1);
00516 VERBOSE((".....parsing MESH_TVERTLIST\n"));
00517 ASE_ParseBracedBlock(ASE_KeyMESH_TVERTLIST);
00518 } else if (!strcmp(token, "*MESH_FACE_LIST")) {
00519 pMesh->faces = calloc(sizeof(aseFace_t) * pMesh->numFaces, 1);
00520 pMesh->currentFace = 0;
00521 VERBOSE((".....parsing MESH_FACE_LIST\n"));
00522 ASE_ParseBracedBlock(ASE_KeyMESH_FACE_LIST);
00523 } else if (!strcmp(token, "*MESH_TFACELIST")) {
00524 pMesh->tfaces = calloc(sizeof(aseFace_t) * pMesh->numFaces, 1);
00525 pMesh->currentFace = 0;
00526 VERBOSE((".....parsing MESH_TFACE_LIST\n"));
00527 ASE_ParseBracedBlock(ASE_KeyTFACE_LIST);
00528 } else if (!strcmp(token, "*MESH_NORMALS")) {
00529 ASE_ParseBracedBlock(0);
00530 }
00531 }
00532
00533 static void ASE_KeyGEOMOBJECT (const char *token)
00534 {
00535 if (!strcmp(token, "*NODE_NAME")) {
00536 char *name = ase.objects[ase.currentObject].name;
00537
00538 ASE_GetToken(qtrue);
00539 VERBOSE((" %s\n", s_token));
00540 strcpy(ase.objects[ase.currentObject].name, s_token + 1);
00541 if (strchr(ase.objects[ase.currentObject].name, '"'))
00542 *strchr(ase.objects[ase.currentObject].name, '"') = 0;
00543
00544 if (strstr(name, "tag") == name) {
00545 while (strchr(name, '_') != strrchr(name, '_')) {
00546 *strrchr(name, '_') = 0;
00547 }
00548 while (strrchr(name, ' ')) {
00549 *strrchr(name, ' ') = 0;
00550 }
00551 }
00552 } else if (!strcmp(token, "*NODE_PARENT")) {
00553 ASE_SkipRestOfLine();
00554 }
00555
00556 else if (!strcmp(token, "*NODE_TM") || !strcmp(token, "*TM_ANIMATION")) {
00557 ASE_ParseBracedBlock(0);
00558 }
00559
00560 else if (!strcmp(token, "*MESH")) {
00561 #if 0
00562 if (strstr(ase.objects[ase.currentObject].name, "tag_") == ase.objects[ase.currentObject].name) {
00563 s_forceStaticMesh = true;
00564 ASE_ParseBracedBlock(ASE_KeyMESH);
00565 s_forceStaticMesh = false;
00566 }
00567 #endif
00568 ASE_ParseBracedBlock(ASE_KeyMESH);
00569 if (++ase.objects[ase.currentObject].anim.currentFrame == MAX_ASE_ANIMATION_FRAMES) {
00570 Sys_Error("Too many animation frames");
00571 }
00572 ase.objects[ase.currentObject].anim.numFrames = ase.objects[ase.currentObject].anim.currentFrame;
00573 ase.objects[ase.currentObject].numAnimations++;
00574 #if 0
00575
00576 else {
00577 ASE_ParseBracedBlock(0);
00578 }
00579 #endif
00580 }
00581
00582 else if (!strcmp(token, "*MATERIAL_REF")) {
00583 ASE_GetToken(qfalse);
00584
00585 ase.objects[ase.currentObject].materialRef = atoi(s_token);
00586 }
00587
00588 else if (!strcmp(token, "*MESH_ANIMATION")) {
00589 ASE_SkipEnclosingBraces();
00590 }
00591
00592 else if (!strcmp(token, "*PROP_MOTIONBLUR") || !strcmp(token, "*PROP_CASTSHADOW") || !strcmp(token, "*PROP_RECVSHADOW")) {
00593 ASE_SkipRestOfLine();
00594 }
00595 }
00596
00597 static void ConcatenateObjects (aseGeomObject_t *pObjA, aseGeomObject_t *pObjB)
00598 {
00599 }
00600
00601 static void CollapseObjects (void)
00602 {
00603 int i;
00604 int numObjects = ase.currentObject;
00605
00606 for (i = 0; i < numObjects; i++) {
00607 int j;
00608
00609
00610 if (strstr(ase.objects[i].name, "tag") == ase.objects[i].name)
00611 continue;
00612
00613 if (!ase.objects[i].numAnimations)
00614 continue;
00615
00616 for (j = i + 1; j < numObjects; j++) {
00617 if (strstr(ase.objects[j].name, "tag") == ase.objects[j].name)
00618 continue;
00619
00620 if (ase.objects[i].materialRef == ase.objects[j].materialRef)
00621 if (ase.objects[j].numAnimations)
00622 ConcatenateObjects(&ase.objects[i], &ase.objects[j]);
00623 }
00624 }
00625 }
00626
00627 static void ASE_Process (void)
00628 {
00629 while (ASE_GetToken(qfalse)) {
00630 if (!strcmp(s_token, "*3DSMAX_ASCIIEXPORT") || !strcmp(s_token, "*COMMENT")) {
00631 ASE_SkipRestOfLine();
00632 } else if (!strcmp(s_token, "*SCENE"))
00633 ASE_SkipEnclosingBraces();
00634 else if (!strcmp(s_token, "*MATERIAL_LIST")) {
00635 VERBOSE(("MATERIAL_LIST\n"));
00636
00637 ASE_ParseBracedBlock(ASE_KeyMATERIAL_LIST);
00638 } else if (!strcmp(s_token, "*GEOMOBJECT")) {
00639 VERBOSE(("GEOMOBJECT"));
00640
00641 ASE_ParseBracedBlock(ASE_KeyGEOMOBJECT);
00642
00643 if (strstr(ase.objects[ase.currentObject].name, "Bip") ||
00644 strstr(ase.objects[ase.currentObject].name, "ignore_")) {
00645 ASE_FreeGeomObject(ase.currentObject);
00646 VERBOSE(("(discarding BIP/ignore object)\n"));
00647 } else {
00648 if (++ase.currentObject == MAX_ASE_OBJECTS) {
00649 Sys_Error("Too many GEOMOBJECTs");
00650 }
00651 }
00652 } else if (s_token[0]) {
00653 Com_Printf("Unknown token '%s'\n", s_token);
00654 }
00655 }
00656
00657 if (!ase.currentObject)
00658 Sys_Error("No animation data!");
00659
00660 CollapseObjects();
00661 }