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