swh:1:snp:687ac8cdbfab3b78b7f301abee5f451127f135fc
Tip revision: dbe4ddb10315479fc00086f08e25d968b4b43c49 authored by Travis Bradshaw on 31 January 2012, 19:41:34 UTC
The Quake III Arena sources as originally released under the GPL license on August 20, 2005.
The Quake III Arena sources as originally released under the GPL license on August 20, 2005.
Tip revision: dbe4ddb
l3dslib.c
/*
===========================================================================
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);
}