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