home *** CD-ROM | disk | FTP | other *** search
/ PC PowerPlay 22 / PCPP #22.iso / Quake2 / q2source_12_11 / utils3 / common / l3dslib.c < prev    next >
Encoding:
C/C++ Source or Header  |  1997-06-28  |  5.2 KB  |  280 lines

  1. //
  2. // l3dslib.c: library for loading triangles from an Alias triangle file
  3. //
  4.  
  5. #include <stdio.h>
  6. #include "cmdlib.h"
  7. #include "mathlib.h"
  8. #include "trilib.h"
  9. #include "l3dslib.h"
  10.  
  11. #define MAIN3DS       0x4D4D
  12. #define EDIT3DS       0x3D3D  // this is the start of the editor config
  13. #define EDIT_OBJECT   0x4000
  14. #define OBJ_TRIMESH   0x4100
  15. #define TRI_VERTEXL   0x4110
  16. #define TRI_FACEL1    0x4120
  17.  
  18. #define MAXVERTS    2000
  19.  
  20. typedef struct {
  21.     int    v[4];
  22. } tri;
  23.  
  24. float    fverts[MAXVERTS][3];
  25. tri        tris[MAXTRIANGLES];
  26.  
  27. int    bytesread, level, numtris, totaltris;
  28. int    vertsfound, trisfound;
  29.  
  30. triangle_t    *ptri;
  31.  
  32.  
  33. // Alias stores triangles as 3 explicit vertices in .tri files, so even though we
  34. // start out with a vertex pool and vertex indices for triangles, we have to convert
  35. // to raw, explicit triangles
  36. void StoreAliasTriangles (void)
  37. {
  38.     int        i, j, k;
  39.  
  40.     if ((totaltris + numtris) > MAXTRIANGLES)
  41.         Error ("Error: Too many triangles");
  42.  
  43.     for (i=0; i<numtris ; i++)
  44.     {
  45.         for (j=0 ; j<3 ; j++)
  46.         {
  47.             for (k=0 ; k<3 ; k++)
  48.             {
  49.                 ptri[i+totaltris].verts[j][k] = fverts[tris[i].v[j]][k];
  50.             }
  51.         }
  52.     }
  53.     
  54.     totaltris += numtris;
  55.     numtris = 0;
  56.     vertsfound = 0;
  57.     trisfound = 0;
  58. }
  59.  
  60.  
  61. int ParseVertexL (FILE *input)
  62. {
  63.     int                i, j, startbytesread, numverts;
  64.     unsigned short    tshort;
  65.  
  66.     if (vertsfound)
  67.         Error ("Error: Multiple vertex chunks");
  68.  
  69.     vertsfound = 1;
  70.     startbytesread = bytesread;
  71.  
  72.     if (feof(input))
  73.         Error ("Error: unexpected end of file");
  74.  
  75.     fread(&tshort, sizeof(tshort), 1, input);
  76.     bytesread += sizeof(tshort);
  77.     numverts = (int)tshort;
  78.  
  79.     if (numverts > MAXVERTS)
  80.         Error ("Error: Too many vertices");
  81.  
  82.     for (i=0 ; i<numverts ; i++)
  83.     {
  84.         for (j=0 ; j<3 ; j++)
  85.         {
  86.             if (feof(input))
  87.                 Error ("Error: unexpected end of file");
  88.  
  89.             fread(&fverts[i][j], sizeof(float), 1, input);
  90.             bytesread += sizeof(float);
  91.         }
  92.     }
  93.  
  94.     if (vertsfound && trisfound)
  95.         StoreAliasTriangles ();
  96.  
  97.     return bytesread - startbytesread;
  98. }
  99.  
  100.  
  101. int ParseFaceL1 (FILE *input)
  102. {
  103.  
  104.     int                i, j, startbytesread;
  105.     unsigned short    tshort;
  106.  
  107.     if (trisfound)
  108.         Error ("Error: Multiple face chunks");
  109.  
  110.     trisfound = 1;
  111.     startbytesread = bytesread;
  112.  
  113.     if (feof(input))
  114.         Error ("Error: unexpected end of file");
  115.  
  116.     fread(&tshort, sizeof(tshort), 1, input);
  117.     bytesread += sizeof(tshort);
  118.     numtris = (int)tshort;
  119.  
  120.     if (numtris > MAXTRIANGLES)
  121.         Error ("Error: Too many triangles");
  122.  
  123.     for (i=0 ; i<numtris ; i++)
  124.     {
  125.         for (j=0 ; j<4 ; j++)
  126.         {
  127.             if (feof(input))
  128.                 Error ("Error: unexpected end of file");
  129.  
  130.             fread(&tshort, sizeof(tshort), 1, input);
  131.             bytesread += sizeof(tshort);
  132.             tris[i].v[j] = (int)tshort;
  133.         }
  134.     }
  135.  
  136.     if (vertsfound && trisfound)
  137.         StoreAliasTriangles ();
  138.  
  139.     return bytesread - startbytesread;
  140. }
  141.  
  142.  
  143. int ParseChunk (FILE *input)
  144. {
  145. #define BLOCK_SIZE    4096
  146.     char            temp[BLOCK_SIZE];
  147.     unsigned short    type;
  148.     int                i, length, w, t, retval;
  149.  
  150.     level++;
  151.     retval = 0;
  152.  
  153. // chunk type
  154.     if (feof(input))
  155.         Error ("Error: unexpected end of file");
  156.  
  157.     fread(&type, sizeof(type), 1, input);
  158.     bytesread += sizeof(type);
  159.  
  160. // chunk length
  161.     if (feof(input))
  162.         Error ("Error: unexpected end of file");
  163.  
  164.     fread (&length, sizeof(length), 1, input);
  165.     bytesread += sizeof(length);
  166.     w = length - 6;
  167.  
  168. // process chunk if we care about it, otherwise skip it
  169.     switch (type)
  170.     {
  171.     case TRI_VERTEXL:
  172.         w -= ParseVertexL (input);
  173.         goto ParseSubchunk;
  174.  
  175.     case TRI_FACEL1:
  176.         w -= ParseFaceL1 (input);
  177.         goto ParseSubchunk;
  178.  
  179.     case EDIT_OBJECT:
  180.     // read the name
  181.         i = 0;
  182.  
  183.         do
  184.         {
  185.             if (feof(input))
  186.                 Error ("Error: unexpected end of file");
  187.  
  188.             fread (&temp[i], 1, 1, input);
  189.             i++;
  190.             w--;
  191.             bytesread++;
  192.         } while (temp[i-1]);
  193.  
  194.     case MAIN3DS:
  195.     case OBJ_TRIMESH:
  196.     case EDIT3DS:
  197.     // parse through subchunks
  198. ParseSubchunk:
  199.         while (w > 0)
  200.         {
  201.             w -= ParseChunk (input);
  202.         }
  203.  
  204.         retval = length;
  205.         goto Done;
  206.  
  207.     default:
  208.     // skip other chunks
  209.         while (w > 0)
  210.         {
  211.             t = w;
  212.  
  213.             if (t > BLOCK_SIZE)
  214.                 t = BLOCK_SIZE;
  215.  
  216.             if (feof(input))
  217.                 Error ("Error: unexpected end of file");
  218.  
  219.             fread (&temp, t, 1, input);
  220.             bytesread += t;
  221.  
  222.             w -= t;
  223.         }
  224.  
  225.         retval = length;
  226.         goto Done;
  227.     }
  228.  
  229. Done:
  230.     level--;
  231.     return retval;
  232. }
  233.  
  234.  
  235. void Load3DSTriangleList (char *filename, triangle_t **pptri, int *numtriangles)
  236. {
  237.     FILE        *input;
  238.     short int    tshort;
  239.  
  240.     bytesread = 0;
  241.     level = 0;
  242.     numtris = 0;
  243.     totaltris = 0;
  244.     vertsfound = 0;
  245.     trisfound = 0;
  246.  
  247.     if ((input = fopen(filename, "rb")) == 0) {
  248.         fprintf(stderr,"reader: could not open file '%s'\n", filename);
  249.         exit(0);
  250.     }
  251.  
  252.     fread(&tshort, sizeof(tshort), 1, input);
  253.  
  254. // should only be MAIN3DS, but some files seem to start with EDIT3DS, with
  255. // no MAIN3DS
  256.     if ((tshort != MAIN3DS) && (tshort != EDIT3DS)) {
  257.         fprintf(stderr,"File is not a 3DS file.\n");
  258.         exit(0);
  259.     }
  260.  
  261. // back to top of file so we can parse the first chunk descriptor
  262.     fseek(input, 0, SEEK_SET);
  263.  
  264.     ptri = malloc (MAXTRIANGLES * sizeof(triangle_t));
  265.  
  266.     *pptri = ptri;
  267.  
  268. // parse through looking for the relevant chunk tree (MAIN3DS | EDIT3DS | EDIT_OBJECT |
  269. // OBJ_TRIMESH | {TRI_VERTEXL, TRI_FACEL1}) and skipping other chunks
  270.     ParseChunk (input);
  271.  
  272.     if (vertsfound || trisfound)
  273.         Error ("Incomplete triangle set");
  274.  
  275.     *numtriangles = totaltris;
  276.  
  277.     fclose (input);
  278. }
  279.  
  280.