Quake-III-Arena

Quake III Arena GPL Source Release
Log | Files | Refs

trilib.c (5931B)


      1 /*
      2 ===========================================================================
      3 Copyright (C) 1999-2005 Id Software, Inc.
      4 
      5 This file is part of Quake III Arena source code.
      6 
      7 Quake III Arena source code is free software; you can redistribute it
      8 and/or modify it under the terms of the GNU General Public License as
      9 published by the Free Software Foundation; either version 2 of the License,
     10 or (at your option) any later version.
     11 
     12 Quake III Arena source code is distributed in the hope that it will be
     13 useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
     14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     15 GNU General Public License for more details.
     16 
     17 You should have received a copy of the GNU General Public License
     18 along with Foobar; if not, write to the Free Software
     19 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
     20 ===========================================================================
     21 */
     22 //
     23 // trilib.c: library for loading triangles from an Alias triangle file
     24 //
     25 
     26 #include <stdio.h>
     27 #include "cmdlib.h"
     28 #include "mathlib.h"
     29 #include "polyset.h"
     30 #include "trilib.h"
     31 
     32 // on disk representation of a face
     33 
     34 
     35 #define	FLOAT_START	99999.0
     36 #define	FLOAT_END	-FLOAT_START
     37 #define MAGIC       123322
     38 
     39 //#define NOISY 1
     40 
     41 typedef struct {
     42 	float v[3];
     43 } vector;
     44 
     45 typedef struct
     46 {
     47 	vector n;    /* normal */
     48 	vector p;    /* point */
     49 	vector c;    /* color */
     50 	float  u;    /* u */
     51 	float  v;    /* v */
     52 } aliaspoint_t;
     53 
     54 typedef struct {
     55 	aliaspoint_t	pt[3];
     56 } tf_triangle;
     57 
     58 
     59 static void ByteSwapTri (tf_triangle *tri)
     60 {
     61 	int		i;
     62 	
     63 	for (i=0 ; i<sizeof(tf_triangle)/4 ; i++)
     64 	{
     65 		((int *)tri)[i] = BigLong (((int *)tri)[i]);
     66 	}
     67 }
     68 
     69 static void ReadPolysetGeometry( triangle_t *tripool, FILE *input, int count, triangle_t *ptri )
     70 {
     71 	tf_triangle tri;
     72 	int i;
     73 
     74 	for (i = 0; i < count; ++i) {
     75 		int		j;
     76 
     77 		fread( &tri, sizeof(tf_triangle), 1, input );
     78 		ByteSwapTri (&tri);
     79 		for (j=0 ; j<3 ; j++)
     80 		{
     81 			int		k;
     82 
     83 			for (k=0 ; k<3 ; k++)
     84 			{
     85 				ptri->verts[j][k] = tri.pt[j].p.v[k];
     86 				ptri->normals[j][k] = tri.pt[j].n.v[k];
     87 //				ptri->colors[j][k] = tri.pt[j].c.v[k];
     88 			}
     89 
     90 			ptri->texcoords[j][0] = tri.pt[j].u;
     91 			ptri->texcoords[j][1] = tri.pt[j].v;
     92 		}
     93 
     94 		ptri++;
     95 		if ((ptri - tripool ) >= POLYSET_MAXTRIANGLES)
     96 			Error ("Error: too many triangles; increase POLYSET_MAXTRIANGLES\n");
     97 	}
     98 }
     99 
    100 void TRI_LoadPolysets( const char *filename, polyset_t **ppPSET, int *numpsets )
    101 {
    102 	FILE        *input;
    103 	float       start;
    104 	char        name[256], tex[256];
    105 	int         i, count, magic, pset = 0;
    106 	triangle_t	*ptri;
    107 	polyset_t	*pPSET;
    108 	int			iLevel;
    109 	int			exitpattern;
    110 	float		t;
    111 
    112 	t = -FLOAT_START;
    113 	*((unsigned char *)&exitpattern + 0) = *((unsigned char *)&t + 3);
    114 	*((unsigned char *)&exitpattern + 1) = *((unsigned char *)&t + 2);
    115 	*((unsigned char *)&exitpattern + 2) = *((unsigned char *)&t + 1);
    116 	*((unsigned char *)&exitpattern + 3) = *((unsigned char *)&t + 0);
    117 
    118 	if ((input = fopen(filename, "rb")) == 0)
    119 		Error ("reader: could not open file '%s'", filename);
    120 
    121 	iLevel = 0;
    122 
    123 	fread(&magic, sizeof(int), 1, input);
    124 	if (BigLong(magic) != MAGIC)
    125 		Error ("%s is not a Alias object separated triangle file, magic number is wrong.", filename);
    126 
    127 	pPSET = calloc( 1, POLYSET_MAXPOLYSETS * sizeof( polyset_t ) );
    128 	ptri = calloc( 1, POLYSET_MAXTRIANGLES * sizeof( triangle_t ) );
    129 
    130 	*ppPSET = pPSET;
    131 
    132 	while (feof(input) == 0) {
    133 		if (fread(&start,  sizeof(float), 1, input) < 1)
    134 			break;
    135 		*(int *)&start = BigLong(*(int *)&start);
    136 		if (*(int *)&start != exitpattern)
    137 		{
    138 			if (start == FLOAT_START) {
    139 				/* Start of an object or group of objects. */
    140 				i = -1;
    141 				do {
    142 					/* There are probably better ways to read a string from */
    143 					/* a file, but this does allow you to do error checking */
    144 					/* (which I'm not doing) on a per character basis.      */
    145 					++i;
    146 					fread( &(name[i]), sizeof( char ), 1, input);
    147 				} while( name[i] != '\0' );
    148 	
    149 				if ( i != 0 )
    150 					strncpy( pPSET[pset].name, name, sizeof( pPSET[pset].name ) - 1 );
    151 				else
    152 					strcpy( pPSET[pset].name , "(unnamed)" );
    153 				strlwr( pPSET[pset].name );
    154 
    155 //				indent();
    156 //				fprintf(stdout,"OBJECT START: %s\n",name);
    157 				fread( &count, sizeof(int), 1, input);
    158 				count = BigLong(count);
    159 				++iLevel;
    160 				if (count != 0) {
    161 //					indent();
    162 //					fprintf(stdout,"NUMBER OF TRIANGLES: %d\n",count);
    163 	
    164 					i = -1;
    165 					do {
    166 						++i;
    167 						fread( &(tex[i]), sizeof( char ), 1, input);
    168 					} while( tex[i] != '\0' );
    169 
    170 /*
    171 					if ( i != 0 )
    172 						strncpy( pPSET[pset].texname, tex, sizeof( pPSET[pset].texname ) - 1 );
    173 					else
    174 						strcpy( pPSET[pset].texname, "(unnamed)" );
    175 					strlwr( pPSET[pset].texname );
    176 */
    177 
    178 //					indent();
    179 //					fprintf(stdout,"  Object texture name: '%s'\n",tex);
    180 				}
    181 	
    182 				/* Else (count == 0) this is the start of a group, and */
    183 				/* no texture name is present. */
    184 			}
    185 			else if (start == FLOAT_END) {
    186 				/* End of an object or group. Yes, the name should be */
    187 				/* obvious from context, but it is in here just to be */
    188 				/* safe and to provide a little extra information for */
    189 				/* those who do not wish to write a recursive reader. */
    190 				/* Mea culpa. */
    191 				--iLevel;
    192 				i = -1;
    193 				do {
    194 					++i;
    195 					fread( &(name[i]), sizeof( char ), 1, input);
    196 				} while( name[i] != '\0' );
    197 
    198 				if ( i != 0 )
    199 					strncpy( pPSET[pset].name, name, sizeof( pPSET[pset].name ) - 1 );
    200 				else
    201 					strcpy( pPSET[pset].name , "(unnamed)" );
    202 
    203 				strlwr( pPSET[pset].name );
    204 	
    205 //				indent();
    206 //				fprintf(stdout,"OBJECT END: %s\n",name);
    207 				continue;
    208 			}
    209 		}
    210 
    211 //
    212 // read the triangles
    213 //		
    214 		if ( count > 0 )
    215 		{
    216 			pPSET[pset].triangles = ptri;
    217 			ReadPolysetGeometry( pPSET[0].triangles, input, count, ptri );
    218 			ptri += count;
    219 			pPSET[pset].numtriangles = count;
    220 			if ( ++pset >= POLYSET_MAXPOLYSETS )
    221 			{
    222 				Error ("Error: too many polysets; increase POLYSET_MAXPOLYSETS\n");
    223 			}
    224 		}
    225 	}
    226 
    227 	*numpsets = pset;
    228 
    229 	fclose (input);
    230 }
    231