allow 64 directories, no longer 8
[divverent/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 <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 {
65         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 {
75         tf_triangle tri;
76         int i;
77
78         for (i = 0; i < count; ++i) {
79                 int             j;
80
81                 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 void TRI_LoadPolysets( const char *filename, polyset_t **ppPSET, int *numpsets )
105 {
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         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         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                 *(int *)&start = BigLong(*(int *)&start);
140                 if (*(int *)&start != exitpattern)
141                 {
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                                 else
156                                         strcpy( pPSET[pset].name , "(unnamed)" );
157                                 strlwr( pPSET[pset].name );
158
159 //                              indent();
160 //                              fprintf(stdout,"OBJECT START: %s\n",name);
161                                 fread( &count, sizeof(int), 1, input);
162                                 count = BigLong(count);
163                                 ++iLevel;
164                                 if (count != 0) {
165 //                                      indent();
166 //                                      fprintf(stdout,"NUMBER OF TRIANGLES: %d\n",count);
167         
168                                         i = -1;
169                                         do {
170                                                 ++i;
171                                                 fread( &(tex[i]), sizeof( char ), 1, input);
172                                         } while( tex[i] != '\0' );
173
174 /*
175                                         if ( i != 0 )
176                                                 strncpy( pPSET[pset].texname, tex, sizeof( pPSET[pset].texname ) - 1 );
177                                         else
178                                                 strcpy( pPSET[pset].texname, "(unnamed)" );
179                                         strlwr( pPSET[pset].texname );
180 */
181
182 //                                      indent();
183 //                                      fprintf(stdout,"  Object texture name: '%s'\n",tex);
184                                 }
185         
186                                 /* Else (count == 0) this is the start of a group, and */
187                                 /* no texture name is present. */
188                         }
189                         else if (start == FLOAT_END) {
190                                 /* End of an object or group. Yes, the name should be */
191                                 /* obvious from context, but it is in here just to be */
192                                 /* safe and to provide a little extra information for */
193                                 /* those who do not wish to write a recursive reader. */
194                                 /* Mea culpa. */
195                                 --iLevel;
196                                 i = -1;
197                                 do {
198                                         ++i;
199                                         fread( &(name[i]), sizeof( char ), 1, input);
200                                 } while( name[i] != '\0' );
201
202                                 if ( i != 0 )
203                                         strncpy( pPSET[pset].name, name, sizeof( pPSET[pset].name ) - 1 );
204                                 else
205                                         strcpy( pPSET[pset].name , "(unnamed)" );
206
207                                 strlwr( pPSET[pset].name );
208         
209 //                              indent();
210 //                              fprintf(stdout,"OBJECT END: %s\n",name);
211                                 continue;
212                         }
213                 }
214
215 //
216 // read the triangles
217 //              
218                 if ( count > 0 )
219                 {
220                         pPSET[pset].triangles = ptri;
221                         ReadPolysetGeometry( pPSET[0].triangles, input, count, ptri );
222                         ptri += count;
223                         pPSET[pset].numtriangles = count;
224                         if ( ++pset >= POLYSET_MAXPOLYSETS )
225                         {
226                                 Error ("Error: too many polysets; increase POLYSET_MAXPOLYSETS\n");
227                         }
228                 }
229         }
230
231         *numpsets = pset;
232
233         fclose (input);
234 }
235