]> de.git.xonotic.org Git - xonotic/netradiant.git/blob - tools/quake2/common/l3dslib.c
reduce more diff noise
[xonotic/netradiant.git] / tools / quake2 / common / l3dslib.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 // l3dslib.c: library for loading triangles from an Alias triangle file
23 //
24
25 #include <stdio.h>
26 #include "cmdlib.h"
27 #include "inout.h"
28 #include "mathlib.h"
29 #include "trilib.h"
30 #include "l3dslib.h"
31
32 #define MAIN3DS       0x4D4D
33 #define EDIT3DS       0x3D3D  // this is the start of the editor config
34 #define EDIT_OBJECT   0x4000
35 #define OBJ_TRIMESH   0x4100
36 #define TRI_VERTEXL   0x4110
37 #define TRI_FACEL1    0x4120
38
39 #define MAXVERTS    2000
40
41 typedef struct {
42         int v[4];
43 } tri;
44
45 float fverts[MAXVERTS][3];
46 tri tris[MAXTRIANGLES];
47
48 int bytesread, level, numtris, totaltris;
49 int vertsfound, trisfound;
50
51 triangle_t  *ptri;
52
53
54 // Alias stores triangles as 3 explicit vertices in .tri files, so even though we
55 // start out with a vertex pool and vertex indices for triangles, we have to convert
56 // to raw, explicit triangles
57 void StoreAliasTriangles( void ){
58         int i, j, k;
59
60         if ( ( totaltris + numtris ) > MAXTRIANGLES ) {
61                 Error( "Error: Too many triangles" );
62         }
63
64         for ( i = 0; i < numtris ; i++ )
65         {
66                 for ( j = 0 ; j < 3 ; j++ )
67                 {
68                         for ( k = 0 ; k < 3 ; k++ )
69                         {
70                                 ptri[i + totaltris].verts[j][k] = fverts[tris[i].v[j]][k];
71                         }
72                 }
73         }
74
75         totaltris += numtris;
76         numtris = 0;
77         vertsfound = 0;
78         trisfound = 0;
79 }
80
81
82 int ParseVertexL( FILE *input ){
83         int i, j, startbytesread, numverts;
84         unsigned short tshort;
85
86         if ( vertsfound ) {
87                 Error( "Error: Multiple vertex chunks" );
88         }
89
90         vertsfound = 1;
91         startbytesread = bytesread;
92
93         if ( feof( input ) ) {
94                 Error( "Error: unexpected end of file" );
95         }
96
97         fread( &tshort, sizeof( tshort ), 1, input );
98         bytesread += sizeof( tshort );
99         numverts = (int)tshort;
100
101         if ( numverts > MAXVERTS ) {
102                 Error( "Error: Too many vertices" );
103         }
104
105         for ( i = 0 ; i < numverts ; i++ )
106         {
107                 for ( j = 0 ; j < 3 ; j++ )
108                 {
109                         if ( feof( input ) ) {
110                                 Error( "Error: unexpected end of file" );
111                         }
112
113                         fread( &fverts[i][j], sizeof( float ), 1, input );
114                         bytesread += sizeof( float );
115                 }
116         }
117
118         if ( vertsfound && trisfound ) {
119                 StoreAliasTriangles();
120         }
121
122         return bytesread - startbytesread;
123 }
124
125
126 int ParseFaceL1( FILE *input ){
127
128         int i, j, startbytesread;
129         unsigned short tshort;
130
131         if ( trisfound ) {
132                 Error( "Error: Multiple face chunks" );
133         }
134
135         trisfound = 1;
136         startbytesread = bytesread;
137
138         if ( feof( input ) ) {
139                 Error( "Error: unexpected end of file" );
140         }
141
142         fread( &tshort, sizeof( tshort ), 1, input );
143         bytesread += sizeof( tshort );
144         numtris = (int)tshort;
145
146         if ( numtris > MAXTRIANGLES ) {
147                 Error( "Error: Too many triangles" );
148         }
149
150         for ( i = 0 ; i < numtris ; i++ )
151         {
152                 for ( j = 0 ; j < 4 ; j++ )
153                 {
154                         if ( feof( input ) ) {
155                                 Error( "Error: unexpected end of file" );
156                         }
157
158                         fread( &tshort, sizeof( tshort ), 1, input );
159                         bytesread += sizeof( tshort );
160                         tris[i].v[j] = (int)tshort;
161                 }
162         }
163
164         if ( vertsfound && trisfound ) {
165                 StoreAliasTriangles();
166         }
167
168         return bytesread - startbytesread;
169 }
170
171
172 int ParseChunk( FILE *input ){
173 #define BLOCK_SIZE  4096
174         char temp[BLOCK_SIZE];
175         unsigned short type;
176         int i, length, w, t, retval;
177
178         level++;
179         retval = 0;
180
181 // chunk type
182         if ( feof( input ) ) {
183                 Error( "Error: unexpected end of file" );
184         }
185
186         fread( &type, sizeof( type ), 1, input );
187         bytesread += sizeof( type );
188
189 // chunk length
190         if ( feof( input ) ) {
191                 Error( "Error: unexpected end of file" );
192         }
193
194         fread( &length, sizeof( length ), 1, input );
195         bytesread += sizeof( length );
196         w = length - 6;
197
198 // process chunk if we care about it, otherwise skip it
199         switch ( type )
200         {
201         case TRI_VERTEXL:
202                 w -= ParseVertexL( input );
203                 goto ParseSubchunk;
204
205         case TRI_FACEL1:
206                 w -= ParseFaceL1( input );
207                 goto ParseSubchunk;
208
209         case EDIT_OBJECT:
210                 // read the name
211                 i = 0;
212
213                 do
214                 {
215                         if ( feof( input ) ) {
216                                 Error( "Error: unexpected end of file" );
217                         }
218
219                         fread( &temp[i], 1, 1, input );
220                         i++;
221                         w--;
222                         bytesread++;
223                 } while ( temp[i - 1] );
224
225         case MAIN3DS:
226         case OBJ_TRIMESH:
227         case EDIT3DS:
228                 // parse through subchunks
229 ParseSubchunk:
230                 while ( w > 0 )
231                 {
232                         w -= ParseChunk( input );
233                 }
234
235                 retval = length;
236                 goto Done;
237
238         default:
239                 // skip other chunks
240                 while ( w > 0 )
241                 {
242                         t = w;
243
244                         if ( t > BLOCK_SIZE ) {
245                                 t = BLOCK_SIZE;
246                         }
247
248                         if ( feof( input ) ) {
249                                 Error( "Error: unexpected end of file" );
250                         }
251
252                         fread( &temp, t, 1, input );
253                         bytesread += t;
254
255                         w -= t;
256                 }
257
258                 retval = length;
259                 goto Done;
260         }
261
262 Done:
263         level--;
264         return retval;
265 }
266
267
268 void Load3DSTriangleList( char *filename, triangle_t **pptri, int *numtriangles ){
269         FILE        *input;
270         short int tshort;
271
272         bytesread = 0;
273         level = 0;
274         numtris = 0;
275         totaltris = 0;
276         vertsfound = 0;
277         trisfound = 0;
278
279         if ( ( input = fopen( filename, "rb" ) ) == 0 ) {
280                 fprintf( stderr,"reader: could not open file '%s'\n", filename );
281                 exit( 0 );
282         }
283
284         fread( &tshort, sizeof( tshort ), 1, input );
285
286 // should only be MAIN3DS, but some files seem to start with EDIT3DS, with
287 // no MAIN3DS
288         if ( ( tshort != MAIN3DS ) && ( tshort != EDIT3DS ) ) {
289                 fprintf( stderr,"File is not a 3DS file.\n" );
290                 exit( 0 );
291         }
292
293 // back to top of file so we can parse the first chunk descriptor
294         fseek( input, 0, SEEK_SET );
295
296         ptri = malloc( MAXTRIANGLES * sizeof( triangle_t ) );
297
298         *pptri = ptri;
299
300 // parse through looking for the relevant chunk tree (MAIN3DS | EDIT3DS | EDIT_OBJECT |
301 // OBJ_TRIMESH | {TRI_VERTEXL, TRI_FACEL1}) and skipping other chunks
302         ParseChunk( input );
303
304         if ( vertsfound || trisfound ) {
305                 Error( "Incomplete triangle set" );
306         }
307
308         *numtriangles = totaltris;
309
310         fclose( input );
311 }