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