123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301 |
- /*
- ===========================================================================
- Copyright (C) 1999-2005 Id Software, Inc.
- This file is part of Quake III Arena source code.
- Quake III Arena source code is free software; you can redistribute it
- and/or modify it under the terms of the GNU General Public License as
- published by the Free Software Foundation; either version 2 of the License,
- or (at your option) any later version.
- Quake III Arena source code is distributed in the hope that it will be
- useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
- You should have received a copy of the GNU General Public License
- along with Foobar; if not, write to the Free Software
- Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
- ===========================================================================
- */
- //
- // l3dslib.c: library for loading triangles from an Alias triangle file
- //
- #include <stdio.h>
- #include "cmdlib.h"
- #include "mathlib.h"
- #include "trilib.h"
- #include "l3dslib.h"
- #define MAIN3DS 0x4D4D
- #define EDIT3DS 0x3D3D // this is the start of the editor config
- #define EDIT_OBJECT 0x4000
- #define OBJ_TRIMESH 0x4100
- #define TRI_VERTEXL 0x4110
- #define TRI_FACEL1 0x4120
- #define MAXVERTS 2000
- typedef struct {
- int v[4];
- } tri;
- float fverts[MAXVERTS][3];
- tri tris[MAXTRIANGLES];
- int bytesread, level, numtris, totaltris;
- int vertsfound, trisfound;
- triangle_t *ptri;
- // Alias stores triangles as 3 explicit vertices in .tri files, so even though we
- // start out with a vertex pool and vertex indices for triangles, we have to convert
- // to raw, explicit triangles
- void StoreAliasTriangles (void)
- {
- int i, j, k;
- if ((totaltris + numtris) > MAXTRIANGLES)
- Error ("Error: Too many triangles");
- for (i=0; i<numtris ; i++)
- {
- for (j=0 ; j<3 ; j++)
- {
- for (k=0 ; k<3 ; k++)
- {
- ptri[i+totaltris].verts[j][k] = fverts[tris[i].v[j]][k];
- }
- }
- }
-
- totaltris += numtris;
- numtris = 0;
- vertsfound = 0;
- trisfound = 0;
- }
- int ParseVertexL (FILE *input)
- {
- int i, j, startbytesread, numverts;
- unsigned short tshort;
- if (vertsfound)
- Error ("Error: Multiple vertex chunks");
- vertsfound = 1;
- startbytesread = bytesread;
- if (feof(input))
- Error ("Error: unexpected end of file");
- fread(&tshort, sizeof(tshort), 1, input);
- bytesread += sizeof(tshort);
- numverts = (int)tshort;
- if (numverts > MAXVERTS)
- Error ("Error: Too many vertices");
- for (i=0 ; i<numverts ; i++)
- {
- for (j=0 ; j<3 ; j++)
- {
- if (feof(input))
- Error ("Error: unexpected end of file");
- fread(&fverts[i][j], sizeof(float), 1, input);
- bytesread += sizeof(float);
- }
- }
- if (vertsfound && trisfound)
- StoreAliasTriangles ();
- return bytesread - startbytesread;
- }
- int ParseFaceL1 (FILE *input)
- {
- int i, j, startbytesread;
- unsigned short tshort;
- if (trisfound)
- Error ("Error: Multiple face chunks");
- trisfound = 1;
- startbytesread = bytesread;
- if (feof(input))
- Error ("Error: unexpected end of file");
- fread(&tshort, sizeof(tshort), 1, input);
- bytesread += sizeof(tshort);
- numtris = (int)tshort;
- if (numtris > MAXTRIANGLES)
- Error ("Error: Too many triangles");
- for (i=0 ; i<numtris ; i++)
- {
- for (j=0 ; j<4 ; j++)
- {
- if (feof(input))
- Error ("Error: unexpected end of file");
- fread(&tshort, sizeof(tshort), 1, input);
- bytesread += sizeof(tshort);
- tris[i].v[j] = (int)tshort;
- }
- }
- if (vertsfound && trisfound)
- StoreAliasTriangles ();
- return bytesread - startbytesread;
- }
- int ParseChunk (FILE *input)
- {
- #define BLOCK_SIZE 4096
- char temp[BLOCK_SIZE];
- unsigned short type;
- int i, length, w, t, retval;
- level++;
- retval = 0;
- // chunk type
- if (feof(input))
- Error ("Error: unexpected end of file");
- fread(&type, sizeof(type), 1, input);
- bytesread += sizeof(type);
- // chunk length
- if (feof(input))
- Error ("Error: unexpected end of file");
- fread (&length, sizeof(length), 1, input);
- bytesread += sizeof(length);
- w = length - 6;
- // process chunk if we care about it, otherwise skip it
- switch (type)
- {
- case TRI_VERTEXL:
- w -= ParseVertexL (input);
- goto ParseSubchunk;
- case TRI_FACEL1:
- w -= ParseFaceL1 (input);
- goto ParseSubchunk;
- case EDIT_OBJECT:
- // read the name
- i = 0;
- do
- {
- if (feof(input))
- Error ("Error: unexpected end of file");
- fread (&temp[i], 1, 1, input);
- i++;
- w--;
- bytesread++;
- } while (temp[i-1]);
- case MAIN3DS:
- case OBJ_TRIMESH:
- case EDIT3DS:
- // parse through subchunks
- ParseSubchunk:
- while (w > 0)
- {
- w -= ParseChunk (input);
- }
- retval = length;
- goto Done;
- default:
- // skip other chunks
- while (w > 0)
- {
- t = w;
- if (t > BLOCK_SIZE)
- t = BLOCK_SIZE;
- if (feof(input))
- Error ("Error: unexpected end of file");
- fread (&temp, t, 1, input);
- bytesread += t;
- w -= t;
- }
- retval = length;
- goto Done;
- }
- Done:
- level--;
- return retval;
- }
- void Load3DSTriangleList (char *filename, triangle_t **pptri, int *numtriangles)
- {
- FILE *input;
- short int tshort;
- bytesread = 0;
- level = 0;
- numtris = 0;
- totaltris = 0;
- vertsfound = 0;
- trisfound = 0;
- if ((input = fopen(filename, "rb")) == 0) {
- fprintf(stderr,"reader: could not open file '%s'\n", filename);
- exit(0);
- }
- fread(&tshort, sizeof(tshort), 1, input);
- // should only be MAIN3DS, but some files seem to start with EDIT3DS, with
- // no MAIN3DS
- if ((tshort != MAIN3DS) && (tshort != EDIT3DS)) {
- fprintf(stderr,"File is not a 3DS file.\n");
- exit(0);
- }
- // back to top of file so we can parse the first chunk descriptor
- fseek(input, 0, SEEK_SET);
- ptri = malloc (MAXTRIANGLES * sizeof(triangle_t));
- *pptri = ptri;
- // parse through looking for the relevant chunk tree (MAIN3DS | EDIT3DS | EDIT_OBJECT |
- // OBJ_TRIMESH | {TRI_VERTEXL, TRI_FACEL1}) and skipping other chunks
- ParseChunk (input);
- if (vertsfound || trisfound)
- Error ("Incomplete triangle set");
- *numtriangles = totaltris;
- fclose (input);
- }
|