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