]> git.xonotic.org Git - xonotic/netradiant.git/blob - tools/quake2/qdata_heretic2/common/l3dslib.c
Q3map2:
[xonotic/netradiant.git] / tools / quake2 / qdata_heretic2 / common / l3dslib.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 // l3dslib.c: library for loading triangles from an Alias triangle file
24 //
25
26 #include <stdio.h>
27 #include "cmdlib.h"
28 #include "inout.h"
29 #include "mathlib.h"
30 #include "trilib.h"
31 #include "l3dslib.h"
32 #include "token.h"
33 #include "fmodel.h"
34 #include "bspfile.h"
35
36 #define MAIN3DS       0x4D4D
37 #define EDIT3DS       0x3D3D  // this is the start of the editor config
38 #define EDIT_OBJECT   0x4000
39 #define OBJ_TRIMESH   0x4100
40 #define TRI_VERTEXL   0x4110
41 #define TRI_FACEL1    0x4120
42
43 #define MAXVERTS    2000
44
45 typedef struct {
46         int v[4];
47 } tri;
48
49 float fverts[MAXVERTS][3];
50 tri tris[MAXTRIANGLES];
51
52 int bytesread, level, numtris, totaltris;
53 int vertsfound, trisfound;
54
55 triangle_t  *ptri;
56
57
58
59 void DefaultNodesList( mesh_node_t **nodesList, int *num_mesh_nodes, int *numtriangles ){
60         int pos, bit, i;
61
62         if ( nodesList ) {
63                 *num_mesh_nodes = 1;
64                 memset( &( *nodesList )[0], 0, sizeof( mesh_node_t ) );
65                 strcpy( ( *nodesList )[0].name, "default" );
66
67                 // set all of the tris to be used for the top node
68                 for ( i = 0; i < ( *numtriangles ); i++ )
69                 {
70                         pos = ( i ) >> 3;
71                         bit = 1 << ( ( i ) & 7 );
72
73                         ( *nodesList )[0].tris[pos] |= bit;
74                 }
75         }
76 }
77
78
79 // Alias stores triangles as 3 explicit vertices in .tri files, so even though we
80 // start out with a vertex pool and vertex indices for triangles, we have to convert
81 // to raw, explicit triangles
82 void StoreAliasTriangles( void ){
83         int i, j, k;
84
85         if ( ( totaltris + numtris ) > MAXTRIANGLES ) {
86                 Error( "Error: Too many triangles" );
87         }
88
89         for ( i = 0; i < numtris ; i++ )
90         {
91                 for ( j = 0 ; j < 3 ; j++ )
92                 {
93                         for ( k = 0 ; k < 3 ; k++ )
94                         {
95                                 ptri[i + totaltris].verts[j][k] = fverts[tris[i].v[j]][k];
96                         }
97                 }
98         }
99
100         totaltris += numtris;
101         numtris = 0;
102         vertsfound = 0;
103         trisfound = 0;
104 }
105
106
107 int ParseVertexL( FILE *input ){
108         int i, j, startbytesread, numverts;
109         unsigned short tshort;
110
111         if ( vertsfound ) {
112                 Error( "Error: Multiple vertex chunks" );
113         }
114
115         vertsfound = 1;
116         startbytesread = bytesread;
117
118         if ( feof( input ) ) {
119                 Error( "Error: unexpected end of file" );
120         }
121
122         fread( &tshort, sizeof( tshort ), 1, input );
123         bytesread += sizeof( tshort );
124         numverts = (int)tshort;
125
126         if ( numverts > MAXVERTS ) {
127                 Error( "Error: Too many vertices" );
128         }
129
130         for ( i = 0 ; i < numverts ; i++ )
131         {
132                 for ( j = 0 ; j < 3 ; j++ )
133                 {
134                         if ( feof( input ) ) {
135                                 Error( "Error: unexpected end of file" );
136                         }
137
138                         fread( &fverts[i][j], sizeof( float ), 1, input );
139                         bytesread += sizeof( float );
140                 }
141         }
142
143         if ( vertsfound && trisfound ) {
144                 StoreAliasTriangles();
145         }
146
147         return bytesread - startbytesread;
148 }
149
150
151 int ParseFaceL1( FILE *input ){
152
153         int i, j, startbytesread;
154         unsigned short tshort;
155
156         if ( trisfound ) {
157                 Error( "Error: Multiple face chunks" );
158         }
159
160         trisfound = 1;
161         startbytesread = bytesread;
162
163         if ( feof( input ) ) {
164                 Error( "Error: unexpected end of file" );
165         }
166
167         fread( &tshort, sizeof( tshort ), 1, input );
168         bytesread += sizeof( tshort );
169         numtris = (int)tshort;
170
171         if ( numtris > MAXTRIANGLES ) {
172                 Error( "Error: Too many triangles" );
173         }
174
175         for ( i = 0 ; i < numtris ; i++ )
176         {
177                 for ( j = 0 ; j < 4 ; j++ )
178                 {
179                         if ( feof( input ) ) {
180                                 Error( "Error: unexpected end of file" );
181                         }
182
183                         fread( &tshort, sizeof( tshort ), 1, input );
184                         bytesread += sizeof( tshort );
185                         tris[i].v[j] = (int)tshort;
186                 }
187         }
188
189         if ( vertsfound && trisfound ) {
190                 StoreAliasTriangles();
191         }
192
193         return bytesread - startbytesread;
194 }
195
196
197 int ParseChunk( FILE *input ){
198 #define BLOCK_SIZE  4096
199         char temp[BLOCK_SIZE];
200         unsigned short type;
201         int i, length, w, t, retval;
202
203         level++;
204         retval = 0;
205
206 // chunk type
207         if ( feof( input ) ) {
208                 Error( "Error: unexpected end of file" );
209         }
210
211         fread( &type, sizeof( type ), 1, input );
212         bytesread += sizeof( type );
213
214 // chunk length
215         if ( feof( input ) ) {
216                 Error( "Error: unexpected end of file" );
217         }
218
219         fread( &length, sizeof( length ), 1, input );
220         bytesread += sizeof( length );
221         w = length - 6;
222
223 // process chunk if we care about it, otherwise skip it
224         switch ( type )
225         {
226         case TRI_VERTEXL:
227                 w -= ParseVertexL( input );
228                 goto ParseSubchunk;
229
230         case TRI_FACEL1:
231                 w -= ParseFaceL1( input );
232                 goto ParseSubchunk;
233
234         case EDIT_OBJECT:
235                 // read the name
236                 i = 0;
237
238                 do
239                 {
240                         if ( feof( input ) ) {
241                                 Error( "Error: unexpected end of file" );
242                         }
243
244                         fread( &temp[i], 1, 1, input );
245                         i++;
246                         w--;
247                         bytesread++;
248                 } while ( temp[i - 1] );
249
250         case MAIN3DS:
251         case OBJ_TRIMESH:
252         case EDIT3DS:
253                 // parse through subchunks
254 ParseSubchunk:
255                 while ( w > 0 )
256                 {
257                         w -= ParseChunk( input );
258                 }
259
260                 retval = length;
261                 goto Done;
262
263         default:
264                 // skip other chunks
265                 while ( w > 0 )
266                 {
267                         t = w;
268
269                         if ( t > BLOCK_SIZE ) {
270                                 t = BLOCK_SIZE;
271                         }
272
273                         if ( feof( input ) ) {
274                                 Error( "Error: unexpected end of file" );
275                         }
276
277                         fread( &temp, t, 1, input );
278                         bytesread += t;
279
280                         w -= t;
281                 }
282
283                 retval = length;
284                 goto Done;
285         }
286
287 Done:
288         level--;
289         return retval;
290 }
291
292
293 void Load3DSTriangleList( char *filename, triangle_t **pptri, int *numtriangles, mesh_node_t **nodesList, int *num_mesh_nodes ){
294         FILE        *input;
295         short int tshort;
296
297         if ( nodesList ) {
298                 *num_mesh_nodes = 0;
299                 *nodesList = (mesh_node_t *) SafeMalloc( MAX_FM_MESH_NODES * sizeof( mesh_node_t ), "Mesh Node List" );
300         }
301
302         bytesread = 0;
303         level = 0;
304         numtris = 0;
305         totaltris = 0;
306         vertsfound = 0;
307         trisfound = 0;
308
309         if ( ( input = fopen( filename, "rb" ) ) == 0 ) {
310                 fprintf( stderr,"reader: could not open file '%s'\n", filename );
311                 exit( 0 );
312         }
313
314         fread( &tshort, sizeof( tshort ), 1, input );
315
316 // should only be MAIN3DS, but some files seem to start with EDIT3DS, with
317 // no MAIN3DS
318         if ( ( tshort != MAIN3DS ) && ( tshort != EDIT3DS ) ) {
319                 fprintf( stderr,"File is not a 3DS file.\n" );
320                 exit( 0 );
321         }
322
323 // back to top of file so we can parse the first chunk descriptor
324         fseek( input, 0, SEEK_SET );
325
326         ptri = malloc( MAXTRIANGLES * sizeof( triangle_t ) );
327
328         *pptri = ptri;
329
330 // parse through looking for the relevant chunk tree (MAIN3DS | EDIT3DS | EDIT_OBJECT |
331 // OBJ_TRIMESH | {TRI_VERTEXL, TRI_FACEL1}) and skipping other chunks
332         ParseChunk( input );
333
334         if ( vertsfound || trisfound ) {
335                 Error( "Incomplete triangle set" );
336         }
337
338         *numtriangles = totaltris;
339
340         fclose( input );
341
342         DefaultNodesList( nodesList,num_mesh_nodes,numtriangles );
343 }
344
345 //==========================================================================
346 //
347 // LoadASC
348 //
349 //==========================================================================
350
351 void LoadASC( char *fileName, triangle_t **triList, int *triangleCount, mesh_node_t **nodesList, int *num_mesh_nodes ){
352         int i, j;
353         int vertexCount;
354         struct
355         {
356                 float v[3];
357         }           *vList;
358         int triCount;
359         triangle_t  *tList;
360         float x, y, z;
361 //      float           x2, y2, z2;
362 //      float           rx, ry, rz;
363         qboolean goodObject;
364
365         if ( nodesList ) {
366                 *num_mesh_nodes = 0;
367                 *nodesList = (mesh_node_t *) SafeMalloc( MAX_FM_MESH_NODES * sizeof( mesh_node_t ), "Mesh Node List" );
368         }
369
370         TK_OpenSource( fileName );
371
372         goodObject = false;
373         while ( goodObject == false )
374         {
375                 TK_Beyond( TK_C_NAMED );
376                 TK_Beyond( TK_OBJECT );
377                 TK_Beyond( TK_C_TRI );
378                 TK_Beyond( TK_MESH );
379                 TK_BeyondRequire( TK_C_VERTICES, TK_COLON );
380                 TK_FetchRequire( TK_INTNUMBER );
381                 vertexCount = tk_IntNumber;
382                 if ( vertexCount > 0 ) {
383                         goodObject = true;
384                 }
385         }
386         TK_BeyondRequire( TK_C_FACES, TK_COLON );
387         TK_FetchRequire( TK_INTNUMBER );
388         triCount = tk_IntNumber;
389         if ( triCount >= MAXTRIANGLES ) {
390                 Error( "Too many triangles in file %s\n", fileName );
391         }
392         *triangleCount = triCount;
393         tList = (triangle_t *) SafeMalloc( MAXTRIANGLES * sizeof( triangle_t ), "Triangle list" );
394         *triList = tList;
395
396         memset( *triList,0,MAXTRIANGLES * sizeof( triangle_t ) );
397         TK_BeyondRequire( TK_C_VERTEX, TK_LIST );
398
399 /*      rx = ((rotation[0]+90.0)/360.0)*2.0*M_PI;
400     //rx = (rotation[0]/360.0)*2.0*M_PI;
401     ry = (rotation[1]/360.0)*2.0*M_PI;
402     rz = (rotation[2]/360.0)*2.0*M_PI;
403  */
404         vList = (void *) SafeMalloc( vertexCount * sizeof vList[0], "Vertex list" );
405         for ( i = 0; i < vertexCount; i++ )
406         {
407                 TK_BeyondRequire( TK_C_VERTEX, TK_INTNUMBER );
408                 if ( tk_IntNumber != i ) {
409                         Error( "File '%s', line %d:\nVertex index mismatch.\n",
410                                    tk_SourceName, tk_Line );
411                 }
412                 TK_FetchRequireFetch( TK_COLON );
413
414                 TK_BeyondRequire( TK_COLON, TK_FLOATNUMBER );
415                 x = tk_FloatNumber;
416                 TK_BeyondRequire( TK_COLON, TK_FLOATNUMBER );
417                 y = tk_FloatNumber;
418                 TK_BeyondRequire( TK_COLON, TK_FLOATNUMBER );
419                 z = tk_FloatNumber;
420
421 /*              x2 = x*cos(rz)+y*sin(rz);
422         y2 = -x*sin(rz)+y*cos(rz);
423         x = x2;
424         y = y2;
425         y2 = y*cos(rx)+z*sin(rx);
426         z2 = -y*sin(rx)+z*cos(rx);
427         y = y2;
428         z = z2;
429         x2 = x*cos(ry)-z*sin(ry);
430         z2 = x*sin(ry)+z*cos(ry);
431         x = x2;
432         z = z2;
433  */
434                 vList[i].v[0] = x;
435                 vList[i].v[1] = y;
436                 vList[i].v[2] = z;
437         }
438         TK_BeyondRequire( TK_C_FACE, TK_LIST );
439         for ( i = 0; i < triCount; i++ )
440         {
441                 TK_BeyondRequire( TK_C_FACE, TK_INTNUMBER );
442                 if ( tk_IntNumber != i ) {
443                         Error( "File '%s', line %d:\nTriangle index mismatch.\n",
444                                    tk_SourceName, tk_Line );
445                 }
446                 for ( j = 0; j < 3; j++ )
447                 {
448                         TK_BeyondRequire( TK_IDENTIFIER, TK_COLON );
449                         TK_FetchRequire( TK_INTNUMBER );
450                         if ( tk_IntNumber >= vertexCount ) {
451                                 Error( "File '%s', line %d:\nVertex number"
452                                            " > vertexCount: %d\n", tk_SourceName, tk_Line,
453                                            tk_IntNumber );
454                         }
455                         tList[i].verts[2 - j][0] = vList[tk_IntNumber].v[0];
456                         tList[i].verts[2 - j][1] = vList[tk_IntNumber].v[1];
457                         tList[i].verts[2 - j][2] = vList[tk_IntNumber].v[2];
458 #ifdef _QDATA
459                         tList[i].indicies[2 - j] = tk_IntNumber;
460 #endif
461                 }
462
463 /*              printf("Face %i:\n  v0: %f, %f, %f\n  v1: %f, %f, %f\n"
464             "  v2: %f, %f, %f\n", i,
465             tList[i].verts[0][0],
466             tList[i].verts[0][1],
467             tList[i].verts[0][2],
468             tList[i].verts[1][0],
469             tList[i].verts[1][1],
470             tList[i].verts[1][2],
471             tList[i].verts[2][0],
472             tList[i].verts[2][1],
473             tList[i].verts[2][2]);
474  */
475         }
476
477         DefaultNodesList( nodesList,num_mesh_nodes,triangleCount );
478 }