]> de.git.xonotic.org Git - xonotic/netradiant.git/blob - tools/quake2/qdata_heretic2/common/trilib.c
tools: reduce diff noise
[xonotic/netradiant.git] / tools / quake2 / qdata_heretic2 / 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 "inout.h"
29 #include "mathlib.h"
30 #include "trilib.h"
31 #include "token.h"
32 #include "l3dslib.h"
33 #include "fmodel.h"
34 #if 1
35 #include "qd_skeletons.h"
36 #endif
37
38 // on disk representation of a face
39 #define FLOAT_START 99999.0
40 #define FLOAT_END   -FLOAT_START
41 #define MAGIC       123322
42 #ifndef M_PI
43   #define M_PI      3.14159265
44 #endif
45
46 float FixHTRRotateX = 0.0;
47 float FixHTRRotateY = 0.0;
48 float FixHTRRotateZ = 0.0;
49 float FixHTRTranslateX = 0.0;
50 float FixHTRTranslateY = 0.0;
51 float FixHTRTranslateZ = 0.0;
52
53 //#define NOISY 1
54
55 typedef struct {
56         float v[3];
57 } vector;
58
59 typedef struct
60 {
61         vector n;    /* normal */
62         vector p;    /* point */
63         vector c;    /* color */
64         float u;     /* u */
65         float v;     /* v */
66 } aliaspoint_t;
67
68 typedef struct {
69         aliaspoint_t pt[3];
70 } tf_triangle;
71
72
73 void ByteSwapTri( tf_triangle *tri ){
74         int i;
75
76         for ( i = 0 ; i < sizeof( tf_triangle ) / 4 ; i++ )
77         {
78                 ( (int *)tri )[i] = BigLong( ( (int *)tri )[i] );
79         }
80 }
81
82 void LoadTRI( char *filename, triangle_t **pptri, int *numtriangles, mesh_node_t **nodesList, int *num_mesh_nodes ){
83         FILE        *input;
84         float start;
85         char name[256], tex[256];
86         int i, count, magic;
87         tf_triangle tri;
88         triangle_t  *ptri;
89         int iLevel;
90         int exitpattern;
91         float t;
92
93         if ( nodesList ) {
94                 *num_mesh_nodes = 0;
95                 *nodesList = (mesh_node_t *) SafeMalloc( MAX_FM_MESH_NODES * sizeof( mesh_node_t ), "Mesh Node List" );
96         }
97
98         t = -FLOAT_START;
99         *( (unsigned char *)&exitpattern + 0 ) = *( (unsigned char *)&t + 3 );
100         *( (unsigned char *)&exitpattern + 1 ) = *( (unsigned char *)&t + 2 );
101         *( (unsigned char *)&exitpattern + 2 ) = *( (unsigned char *)&t + 1 );
102         *( (unsigned char *)&exitpattern + 3 ) = *( (unsigned char *)&t + 0 );
103
104         if ( ( input = fopen( filename, "rb" ) ) == 0 ) {
105                 Error( "reader: could not open file '%s'", filename );
106         }
107
108         iLevel = 0;
109
110         fread( &magic, sizeof( int ), 1, input );
111         if ( BigLong( magic ) != MAGIC ) {
112                 Error( "%s is not a Alias object separated triangle file, magic number is wrong.", filename );
113         }
114
115         ptri = malloc( MAXTRIANGLES * sizeof( triangle_t ) );
116
117         *pptri = ptri;
118
119         while ( feof( input ) == 0 ) {
120                 if ( fread( &start,  sizeof( float ), 1, input ) < 1 ) {
121                         break;
122                 }
123                 *(int *)&start = BigLong( *(int *)&start );
124                 if ( *(int *)&start != exitpattern ) {
125                         if ( start == FLOAT_START ) {
126                                 /* Start of an object or group of objects. */
127                                 i = -1;
128                                 do {
129                                         /* There are probably better ways to read a string from */
130                                         /* a file, but this does allow you to do error checking */
131                                         /* (which I'm not doing) on a per character basis.      */
132                                         ++i;
133                                         fread( &( name[i] ), sizeof( char ), 1, input );
134                                 } while ( name[i] != '\0' );
135
136 //                              indent();
137 //                              fprintf(stdout,"OBJECT START: %s\n",name);
138                                 fread( &count, sizeof( int ), 1, input );
139                                 count = BigLong( count );
140                                 ++iLevel;
141                                 if ( count != 0 ) {
142 //                                      indent();
143 //                                      fprintf(stdout,"NUMBER OF TRIANGLES: %d\n",count);
144
145                                         i = -1;
146                                         do {
147                                                 ++i;
148                                                 fread( &( tex[i] ), sizeof( char ), 1, input );
149                                         } while ( tex[i] != '\0' );
150
151 //                                      indent();
152 //                                      fprintf(stdout,"  Object texture name: '%s'\n",tex);
153                                 }
154
155                                 /* Else (count == 0) this is the start of a group, and */
156                                 /* no texture name is present. */
157                         }
158                         else if ( start == FLOAT_END ) {
159                                 /* End of an object or group. Yes, the name should be */
160                                 /* obvious from context, but it is in here just to be */
161                                 /* safe and to provide a little extra information for */
162                                 /* those who do not wish to write a recursive reader. */
163                                 /* Mia culpa. */
164                                 --iLevel;
165                                 i = -1;
166                                 do {
167                                         ++i;
168                                         fread( &( name[i] ), sizeof( char ), 1, input );
169                                 } while ( name[i] != '\0' );
170
171 //                              indent();
172 //                              fprintf(stdout,"OBJECT END: %s\n",name);
173                                 continue;
174                         }
175                 }
176
177 //
178 // read the triangles
179 //
180                 for ( i = 0; i < count; ++i ) {
181                         int j;
182
183                         fread( &tri, sizeof( tf_triangle ), 1, input );
184                         ByteSwapTri( &tri );
185                         for ( j = 0 ; j < 3 ; j++ )
186                         {
187                                 int k;
188
189                                 for ( k = 0 ; k < 3 ; k++ )
190                                 {
191                                         ptri->verts[j][k] = tri.pt[j].p.v[k];
192                                 }
193                         }
194
195                         ptri++;
196
197                         if ( ( ptri - *pptri ) >= MAXTRIANGLES ) {
198                                 Error( "Error: too many triangles; increase MAXTRIANGLES\n" );
199                         }
200                 }
201         }
202
203         *numtriangles = ptri - *pptri;
204
205         fclose( input );
206
207         DefaultNodesList( nodesList,num_mesh_nodes,numtriangles );
208 }
209
210
211 //==========================================================================
212 //
213 // LoadHRC
214 //
215 //==========================================================================
216
217 float scaling[3];
218 float rotation[3];
219 float translation[3];
220 static char     *hrc_name;
221
222 struct
223 {
224         float v[3];
225 } vList[8192];
226
227 void HandleHRCModel( triangle_t **triList, int *triangleCount, mesh_node_t **nodesList, int *num_mesh_nodes,
228                                          int ActiveNode, int Depth, int numVerts ){
229         void ReadHRCClusterList( mesh_node_t *meshNode, int baseIndex );
230
231         int i, j;
232         int vertexCount;
233         int triCount;
234         triangle_t  *tList;
235         mesh_node_t *meshNode;
236         float x, y, z;
237         float x2, y2, z2;
238         float rx, ry, rz;
239         tokenType_t nextToken;
240         float orig_scaling[3];
241         float orig_rotation[3];
242         float orig_translation[3];
243         int start_tri;
244         int pos,bit;
245         int vertIndexBase;
246
247         // Update Node Info
248         if ( nodesList ) {
249                 TK_BeyondRequire( TK_NAME, TK_STRING );
250
251                 if ( Depth == 0 || tk_String[0] == '_' ) { // Root
252                         ActiveNode = *num_mesh_nodes;
253                         ( *num_mesh_nodes )++;
254                         if ( ( *num_mesh_nodes ) > MAX_FM_MESH_NODES ) {
255                                 Error( "Too many mesh nodes in file %s\n", hrc_name );
256                         }
257                         meshNode = &( *nodesList )[ActiveNode];
258
259 //                      memset(meshNode, 0, sizeof(mesh_node_t));
260                         strcpy( meshNode->name, tk_String );
261
262                         memset( meshNode->tris, 0, sizeof( meshNode->tris ) );
263                         memset( meshNode->verts, 0, sizeof( meshNode->verts ) );
264
265                         meshNode->start_glcmds = 0;
266                         meshNode->num_glcmds = 0;
267                         vertIndexBase = 0;
268                 }
269                 else
270                 {   // Childs under the children
271                         meshNode = &( *nodesList )[ActiveNode];
272                         vertIndexBase = numVerts;
273                 }
274         }
275         else
276         {
277                 meshNode = NULL;
278         }
279
280
281         // Get the scaling, rotation, and translation values
282         TK_Beyond( TK_SCALING );
283         for ( i = 0; i < 3; i++ )
284         {
285                 orig_scaling[i] = scaling[i];
286
287                 TK_Require( TK_FLOATNUMBER );
288                 scaling[i] *= tk_FloatNumber;
289
290                 TK_Fetch();
291         }
292         TK_Beyond( TK_ROTATION );
293         for ( i = 0; i < 3; i++ )
294         {
295                 orig_rotation[i] = rotation[i];
296
297                 TK_Require( TK_FLOATNUMBER );
298                 rotation[i] = tk_FloatNumber;
299
300                 TK_Fetch();
301         }
302         TK_Beyond( TK_TRANSLATION );
303         for ( i = 0; i < 3; i++ )
304         {
305                 orig_translation[i] = translation[i];
306
307                 TK_Require( TK_FLOATNUMBER );
308                 translation[i] += tk_FloatNumber;
309
310                 TK_Fetch();
311         }
312
313         rx = ( ( rotation[0] - 90.0 ) / 360.0 ) * 2.0 * M_PI;
314         ry = ( rotation[2] / 360.0 ) * 2.0 * M_PI;
315         rz = ( rotation[1] / 360.0 ) * 2.0 * M_PI;
316
317         // rjr - might not work if there an item doesn't have a mesh
318         nextToken = tk_Token;
319         if ( nextToken == TK_ACTOR_DATA ) {
320                 while ( nextToken != TK_MODEL && nextToken != TK_RBRACE )
321                 {
322                         nextToken = TK_Fetch();
323                 }
324         }
325
326         while ( nextToken == TK_SPLINE )
327         {   // spline node has two right braces
328                 nextToken = TK_Beyond( TK_RBRACE );
329                 nextToken = TK_Beyond( TK_RBRACE );
330         }
331
332         while ( nextToken == TK_MATERIAL )
333         {
334                 nextToken = TK_Beyond( TK_RBRACE );
335         }
336
337         while ( nextToken == TK_MODEL )
338         {
339                 HandleHRCModel( triList,triangleCount,nodesList,num_mesh_nodes,ActiveNode, Depth + 1, 0 );
340
341                 nextToken = TK_Fetch();
342         }
343
344         if ( nextToken == TK_MESH ) {
345                 // Get all the tri and vertex info
346                 TK_BeyondRequire( TK_VERTICES, TK_INTNUMBER );
347                 vertexCount = tk_IntNumber;
348                 for ( i = 0; i < vertexCount; i++ )
349                 {
350                         TK_BeyondRequire( TK_LBRACKET, TK_INTNUMBER );
351                         if ( tk_IntNumber != i ) {
352                                 Error( "File '%s', line %d:\nVertex index mismatch.\n",
353                                            tk_SourceName, tk_Line );
354                         }
355                         TK_Beyond( TK_POSITION );
356                         // Apply the scaling, rotation, and translation in the order
357                         // specified in the HRC file.  This could be wrong.
358                         TK_Require( TK_FLOATNUMBER );
359                         x = tk_FloatNumber * scaling[0];
360                         TK_FetchRequire( TK_FLOATNUMBER );
361                         y = tk_FloatNumber * scaling[1];
362                         TK_FetchRequire( TK_FLOATNUMBER );
363                         z = tk_FloatNumber * scaling[2];
364
365                         y2 = y * cos( rx ) + z*sin( rx );
366                         z2 = -y*sin( rx ) + z*cos( rx );
367                         y = y2;
368                         z = z2;
369
370                         x2 = x * cos( ry ) - z*sin( ry );
371                         z2 = x * sin( ry ) + z*cos( ry );
372                         x = x2;
373                         z = z2;
374
375                         x2 = x * cos( rz ) + y*sin( rz );
376                         y2 = -x*sin( rz ) + y*cos( rz );
377                         x = x2;
378                         y = y2;
379
380                         vList[i].v[0] = x + translation[0];
381                         vList[i].v[1] = y - translation[2];
382                         vList[i].v[2] = z + translation[1];
383                 }
384                 TK_BeyondRequire( TK_POLYGONS, TK_INTNUMBER );
385                 triCount = tk_IntNumber;
386                 if ( triCount >= MAXTRIANGLES ) {
387                         Error( "Too many triangles in file %s\n", hrc_name );
388                 }
389
390                 start_tri = *triangleCount;
391                 *triangleCount += triCount;
392
393                 tList = *triList;
394
395                 for ( i = 0; i < triCount; i++ )
396                 {
397                         if ( meshNode ) { // Update the node
398                                 pos = ( i + start_tri ) >> 3;
399                                 bit = 1 << ( ( i + start_tri ) & 7 );
400                                 meshNode->tris[pos] |= bit;
401                         }
402
403                         TK_BeyondRequire( TK_LBRACKET, TK_INTNUMBER );
404                         if ( tk_IntNumber != i ) {
405                                 Error( "File '%s', line %d:\nTriangle index mismatch.\n",
406                                            tk_SourceName, tk_Line );
407                         }
408                         TK_BeyondRequire( TK_NODES, TK_INTNUMBER );
409                         if ( tk_IntNumber != 3 ) {
410                                 Error( "File '%s', line %d:\nBad polygon vertex count: %d.",
411                                            tk_SourceName, tk_Line, tk_IntNumber );
412                         }
413                         tList[i + start_tri].HasUV = true;
414                         for ( j = 0; j < 3; j++ )
415                         {
416                                 TK_BeyondRequire( TK_LBRACKET, TK_INTNUMBER );
417                                 if ( tk_IntNumber != j ) {
418                                         Error( "File '%s', line %d:\nTriangle vertex index"
419                                                    " mismatch.  %d should be %d\n", tk_SourceName, tk_Line,
420                                                    tk_IntNumber, j );
421                                 }
422                                 TK_BeyondRequire( TK_VERTEX, TK_INTNUMBER );
423
424                                 tList[i + start_tri].verts[2 - j][0] = vList[tk_IntNumber].v[0];
425                                 tList[i + start_tri].verts[2 - j][1] = vList[tk_IntNumber].v[1];
426                                 tList[i + start_tri].verts[2 - j][2] = vList[tk_IntNumber].v[2];
427 #if 1
428                                 tList[i + start_tri].indicies[2 - j] = tk_IntNumber + vertIndexBase;
429 #endif
430                                 TK_BeyondRequire( TK_UVTEXTURE, TK_FLOATNUMBER );
431                                 tList[i + start_tri].uv[2 - j][0] = tk_FloatNumber;
432                                 TK_Fetch();
433                                 TK_Require( TK_FLOATNUMBER );
434                                 tList[i + start_tri].uv[2 - j][1] = tk_FloatNumber;
435                         }
436
437                         /*              printf("Face %i:\n  v0: %f, %f, %f\n  v1: %f, %f, %f\n"
438                                     "  v2: %f, %f, %f\n", i,
439                                     tList[i].verts[0][0],
440                                     tList[i].verts[0][1],
441                                     tList[i].verts[0][2],
442                                     tList[i].verts[1][0],
443                                     tList[i].verts[1][1],
444                                     tList[i].verts[1][2],
445                                     tList[i].verts[2][0],
446                                     tList[i].verts[2][1],
447                                     tList[i].verts[2][2]);
448                          */
449                 }
450
451                 TK_Beyond( TK_RBRACE );
452                 TK_Beyond( TK_RBRACE );
453
454                 if ( tk_Token == TK_EDGES ) {
455                         //      TK_Beyond(TK_EDGES);
456                         TK_Beyond( TK_RBRACE );
457                 }
458
459                 scaling[0] = scaling[1] = scaling[2] = 1.0;
460                 //      rotation[0] = rotation[1] = rotation[2] = 0.0;
461                 //      translation[0] = translation[1] = translation[2] = 0.0;
462
463                 // See if there are any other models belonging to this node
464
465 #if 1
466                 TK_Fetch();
467
468                 nextToken = tk_Token;
469                 if ( nextToken == TK_CLUSTERS ) {
470                         if ( g_skelModel.clustered == -1 ) {
471                                 ReadHRCClusterList( meshNode, vertIndexBase );
472                         }
473                         else
474                         {
475                                 nextToken = TK_Get( TK_CLUSTER_NAME );
476
477                                 while ( nextToken == TK_CLUSTER_NAME )
478                                 {
479                                         TK_BeyondRequire( TK_CLUSTER_STATE, TK_INTNUMBER );
480                                         nextToken = TK_Fetch();
481                                 }
482                         }
483
484                         // one right brace follow the list of clusters
485                         nextToken = TK_Beyond( TK_RBRACE );
486                 }
487                 else
488                 {
489                         if ( g_skelModel.clustered == -1 && !vertIndexBase ) {
490                                 meshNode->clustered = false;
491                         }
492                 }
493 #endif
494
495                 nextToken = tk_Token;
496                 if ( nextToken == TK_SPLINE ) {
497                         while ( nextToken == TK_SPLINE )
498                         {   // spline node has two right braces
499                                 nextToken = TK_Beyond( TK_RBRACE );
500                                 nextToken = TK_Beyond( TK_RBRACE );
501                         }
502
503                         nextToken = TK_Beyond( TK_RBRACE );
504                 }
505
506                 while ( nextToken == TK_MATERIAL )
507                 {
508                         nextToken = TK_Beyond( TK_RBRACE );
509                 }
510
511                 while ( nextToken == TK_MODEL )
512                 {
513                         HandleHRCModel( triList,triangleCount,nodesList, num_mesh_nodes, ActiveNode, Depth + 1, vertexCount + vertIndexBase );
514
515                         nextToken = TK_Fetch();
516                 }
517         }
518
519         for ( i = 0; i < 3; i++ )
520         {
521                 scaling[i] = orig_scaling[i];
522                 rotation[i] = orig_rotation[i];
523                 translation[i] = orig_translation[i];
524         }
525 }
526
527 static void LoadHRC( char *fileName, triangle_t **triList, int *triangleCount, mesh_node_t **nodesList, int *num_mesh_nodes ){
528         if ( nodesList ) {
529                 *num_mesh_nodes = 0;
530
531                 if ( !*nodesList ) {
532                         *nodesList = (mesh_node_t *) SafeMalloc( MAX_FM_MESH_NODES * sizeof( mesh_node_t ), "Mesh Node List" );
533                 }
534         }
535
536         hrc_name = fileName;
537
538         scaling[0] = scaling[1] = scaling[2] = 1.0;
539         rotation[0] = rotation[1] = rotation[2] = 0.0;
540         translation[0] = translation[1] = translation[2] = 0.0;
541
542         *triangleCount = 0;
543         *triList = (triangle_t *) SafeMalloc( MAXTRIANGLES * sizeof( triangle_t ), "Triangle list" );
544         memset( *triList,0,MAXTRIANGLES * sizeof( triangle_t ) );
545
546         TK_OpenSource( fileName );
547         TK_FetchRequire( TK_HRCH );
548         TK_FetchRequire( TK_COLON );
549         TK_FetchRequire( TK_SOFTIMAGE );
550
551         // prime it
552         TK_Beyond( TK_MODEL );
553
554         HandleHRCModel( triList, triangleCount, nodesList, num_mesh_nodes, 0, 0, 0 );
555         TK_CloseSource();
556 }
557
558 //==========================================================================
559 //
560 // LoadHTR
561 //
562 //==========================================================================
563 /*
564    static int Version2;
565
566    void HandleHTRModel(triangle_t **triList, int *triangleCount, mesh_node_t **nodesList, int *num_mesh_nodes,
567                            int ActiveNode, int Depth, int numVerts)
568    {
569     int                 i, j;
570     int                 vertexCount;
571     int                 vertexNum;
572     int                 triCount;
573     float               origin[3];
574     triangle_t  *tList;
575     float               x, y, z;
576     float               x2, y2, z2;
577     float               rx, ry, rz;
578     mesh_node_t *meshNode;
579     int                 pos,bit;
580     int                 vertIndexBase;
581     int                 start_tri;
582
583     if (nodesList)
584     {
585         TK_BeyondRequire(TK_NAME, TK_STRING);
586
587         if (Depth == 0 || tk_String[0] == '_')
588         {       // Root
589             ActiveNode = *num_mesh_nodes;
590             (*num_mesh_nodes)++;
591             if ((*num_mesh_nodes) > MAX_FM_MESH_NODES)
592             {
593                 Error("Too many mesh nodes in file %s\n", hrc_name);
594             }
595             meshNode = &(*nodesList)[ActiveNode];
596
597    //                   memset(meshNode, 0, sizeof(mesh_node_t));
598             strcpy(meshNode->name, tk_String);
599
600             memset(meshNode->tris, 0, sizeof(meshNode->tris));
601             memset(meshNode->verts, 0, sizeof(meshNode->verts));
602
603             meshNode->start_glcmds = 0;
604             meshNode->num_glcmds = 0;
605             vertIndexBase = 0;
606         }
607         else
608         {       // Childs under the children
609             meshNode = &(*nodesList)[ActiveNode];
610             vertIndexBase = numVerts;
611         }
612     }
613     else
614     {
615         meshNode = NULL;
616     }
617
618     // Get vertex count
619     TK_BeyondRequire(TK_VERTICES, TK_INTNUMBER);
620     vertexCount = tk_IntNumber;
621
622     // Get triangle count
623     TK_BeyondRequire(TK_FACES, TK_INTNUMBER);
624     triCount = tk_IntNumber;
625     if(triCount >= MAXTRIANGLES)
626     {
627         Error("Too many triangles in file %s\n", hrc_name);
628     }
629
630     // Get origin
631     TK_Beyond(TK_ORIGIN);
632     TK_Require(TK_FLOATNUMBER);
633     origin[0] = tk_FloatNumber;
634     TK_FetchRequire(TK_FLOATNUMBER);
635     origin[1] = tk_FloatNumber;
636     TK_FetchRequire(TK_FLOATNUMBER);
637     origin[2] = tk_FloatNumber;
638
639     //rx = 90.0/360.0*2.0*M_PI;
640     rx = FixHTRRotateX/360.0*2.0*M_PI;
641     ry = FixHTRRotateY/360.0*2.0*M_PI;
642     rz = FixHTRRotateZ/360.0*2.0*M_PI;
643
644     // Get vertex list
645     for(i = 0; i < vertexCount; i++)
646     {
647         TK_FetchRequire(TK_VERTEX);
648         TK_FetchRequire(TK_FLOATNUMBER);
649         x = tk_FloatNumber-origin[0];
650         TK_FetchRequire(TK_FLOATNUMBER);
651         y = tk_FloatNumber-origin[1];
652         TK_FetchRequire(TK_FLOATNUMBER);
653         z = tk_FloatNumber-origin[2];
654
655         x += FixHTRTranslateX;
656         y += FixHTRTranslateY;
657         z += FixHTRTranslateZ;
658
659         y2 = y*cos(rx)-z*sin(rx);
660         z2 = y*sin(rx)+z*cos(rx);
661         y = y2;
662         z = z2;
663         x2 = x*cos(ry)+z*sin(ry);
664         z2 = -x*sin(ry)+z*cos(ry);
665         x = x2;
666         z = z2;
667         x2 = x*cos(rz)-y*sin(rz);
668         y2 = x*sin(rz)+y*cos(rz);
669         x = x2;
670         y = y2;
671
672         vList[i].v[0] = x;
673         vList[i].v[1] = y;
674         vList[i].v[2] = z;
675     }
676
677     start_tri = *triangleCount;
678    *triangleCount += triCount;
679
680     tList = *triList;
681
682     // Get face list
683     for(i = 0; i < triCount; i++)
684     {
685         if (meshNode)
686         {       // Update the node
687             pos = (i + start_tri) >> 3;
688             bit = 1 << ((i + start_tri) & 7 );
689             meshNode->tris[pos] |= bit;
690         }
691
692         TK_FetchRequire(TK_FACE);
693         TK_FetchRequire(TK_LPAREN);
694         for(j = 0; j < 3; j++)
695         {
696             TK_FetchRequire(TK_INTNUMBER);
697             vertexNum = tk_IntNumber-1;
698             if(vertexNum >= vertexCount)
699             {
700                 Error("File '%s', line %d:\nVertex number"
701                     " >= vertexCount: %d\n", tk_SourceName, tk_Line,
702                     tk_IntNumber);
703             }
704             tList[i+start_tri].verts[2-j][0] = vList[vertexNum].v[0];
705             tList[i+start_tri].verts[2-j][1] = vList[vertexNum].v[1];
706             tList[i+start_tri].verts[2-j][2] = vList[vertexNum].v[2];
707         }
708         TK_FetchRequire(TK_RPAREN);
709    #ifdef _QDATA
710         if (Version2)
711         {
712             TK_FetchRequire(TK_FLOATNUMBER);
713             tList[i+start_tri].uv[0][0]=tk_FloatNumber;
714             TK_FetchRequire(TK_FLOATNUMBER);
715             tList[i+start_tri].uv[0][1]=tk_FloatNumber;
716             TK_FetchRequire(TK_FLOATNUMBER);
717             tList[i+start_tri].uv[1][0]=tk_FloatNumber;
718             TK_FetchRequire(TK_FLOATNUMBER);
719             tList[i+start_tri].uv[1][1]=tk_FloatNumber;
720             TK_FetchRequire(TK_FLOATNUMBER);
721             tList[i+start_tri].uv[2][0]=tk_FloatNumber;
722             TK_FetchRequire(TK_FLOATNUMBER);
723             tList[i+start_tri].uv[2][1]=tk_FloatNumber;
724             tList[i+start_tri].HasUV=1;
725         }
726         else
727             tList[i+start_tri].HasUV=0;
728    #endif
729    //           printf("Face %i:\n  v0: %f, %f, %f\n  v1: %f, %f, %f\n"
730    //                   "  v2: %f, %f, %f\n", i,
731    //                   tList[i].verts[0][0],
732    //                   tList[i].verts[0][1],
733    //                   tList[i].verts[0][2],
734    //                   tList[i].verts[1][0],
735    //                   tList[i].verts[1][1],
736    //                   tList[i].verts[1][2],
737    //                   tList[i].verts[2][0],
738    //                   tList[i].verts[2][1],
739    //                   tList[i].verts[2][2]);
740
741     }
742
743     TK_Fetch();
744
745     if (tk_Token == TK_VERTICES)
746     {
747         HandleHTRModel(triList,triangleCount,nodesList, num_mesh_nodes, ActiveNode, Depth+1, vertexCount+vertIndexBase);
748     }
749    }
750
751    static void LoadHTR(char *fileName, triangle_t **triList, int *triangleCount, mesh_node_t **nodesList, int *num_mesh_nodes)
752    {
753     if (nodesList)
754     {
755    *num_mesh_nodes = 0;
756
757         if(!*nodesList)
758         {
759    *nodesList = SafeMalloc(MAX_FM_MESH_NODES * sizeof(mesh_node_t), "Mesh Node List");
760         }
761     }
762
763     hrc_name = fileName;
764
765     scaling[0] = scaling[1] = scaling[2] = 1.0;
766     rotation[0] = rotation[1] = rotation[2] = 0.0;
767     translation[0] = translation[1] = translation[2] = 0.0;
768
769    *triangleCount = 0;
770    *triList = SafeMalloc(MAXTRIANGLES*sizeof(triangle_t), "Triangle list");
771     memset(*triList,0,MAXTRIANGLES*sizeof(triangle_t));
772
773     TK_OpenSource(fileName);
774
775     TK_Beyond(TK_C_HEXEN);
776     TK_Beyond(TK_C_TRIANGLES);
777     TK_BeyondRequire(TK_C_VERSION, TK_INTNUMBER);
778     if(tk_IntNumber != 1&&tk_IntNumber != 2)
779     {
780         Error("Unsupported version (%d) in file %s\n", tk_IntNumber,
781             fileName);
782     }
783     Version2=(tk_IntNumber==2);
784
785
786     HandleHTRModel(triList, triangleCount, nodesList, num_mesh_nodes, 0, 0, 0);
787    }
788
789  */
790
791 static void LoadHTR( char *fileName, triangle_t **triList, int *triangleCount, mesh_node_t **nodesList, int *num_mesh_nodes ){
792         int Version2 = 0;
793         int i, j;
794         int vertexCount;
795         int vertexNum;
796         struct
797         {
798                 float v[3];
799         }           *vList;
800         int triCount;
801         float origin[3];
802         triangle_t  *tList;
803         float x, y, z;
804         float x2, y2, z2;
805         float rx, ry, rz;
806
807         if ( nodesList ) {
808                 *num_mesh_nodes = 0;
809                 *nodesList = (mesh_node_t *) SafeMalloc( MAX_FM_MESH_NODES * sizeof( mesh_node_t ), "Mesh Node List" );
810         }
811
812         TK_OpenSource( fileName );
813
814         TK_Beyond( TK_C_HEXEN );
815         TK_Beyond( TK_C_TRIANGLES );
816         TK_BeyondRequire( TK_C_VERSION, TK_INTNUMBER );
817         if ( tk_IntNumber != 1 && tk_IntNumber != 2 ) {
818                 Error( "Unsupported version (%d) in file %s\n", tk_IntNumber,
819                            fileName );
820         }
821         Version2 = ( tk_IntNumber == 2 );
822
823
824         // Get vertex count
825         TK_BeyondRequire( TK_VERTICES, TK_INTNUMBER );
826         vertexCount = tk_IntNumber;
827         vList = (void *) SafeMalloc( vertexCount * sizeof vList[0], "Vertex list" );
828
829         // Get triangle count
830         TK_BeyondRequire( TK_FACES, TK_INTNUMBER );
831         triCount = tk_IntNumber;
832         if ( triCount >= MAXTRIANGLES ) {
833                 Error( "Too many triangles in file %s\n", fileName );
834         }
835         *triangleCount = triCount;
836         tList = (triangle_t *) SafeMalloc( MAXTRIANGLES * sizeof( triangle_t ), "Triangle list" );
837         *triList = tList;
838         memset( *triList,0,MAXTRIANGLES * sizeof( triangle_t ) );
839
840         // Get origin
841         TK_Beyond( TK_ORIGIN );
842         TK_Require( TK_FLOATNUMBER );
843         origin[0] = tk_FloatNumber;
844         TK_FetchRequire( TK_FLOATNUMBER );
845         origin[1] = tk_FloatNumber;
846         TK_FetchRequire( TK_FLOATNUMBER );
847         origin[2] = tk_FloatNumber;
848
849         //rx = 90.0/360.0*2.0*M_PI;
850         rx = FixHTRRotateX / 360.0 * 2.0 * M_PI;
851         ry = FixHTRRotateY / 360.0 * 2.0 * M_PI;
852         rz = FixHTRRotateZ / 360.0 * 2.0 * M_PI;
853
854         // Get vertex list
855         for ( i = 0; i < vertexCount; i++ )
856         {
857                 TK_FetchRequire( TK_VERTEX );
858                 TK_FetchRequire( TK_FLOATNUMBER );
859                 x = tk_FloatNumber - origin[0];
860                 TK_FetchRequire( TK_FLOATNUMBER );
861                 y = tk_FloatNumber - origin[1];
862                 TK_FetchRequire( TK_FLOATNUMBER );
863                 z = tk_FloatNumber - origin[2];
864
865                 x += FixHTRTranslateX;
866                 y += FixHTRTranslateY;
867                 z += FixHTRTranslateZ;
868
869                 y2 = y * cos( rx ) - z*sin( rx );
870                 z2 = y * sin( rx ) + z*cos( rx );
871                 y = y2;
872                 z = z2;
873                 x2 = x * cos( ry ) + z*sin( ry );
874                 z2 = -x*sin( ry ) + z*cos( ry );
875                 x = x2;
876                 z = z2;
877                 x2 = x * cos( rz ) - y*sin( rz );
878                 y2 = x * sin( rz ) + y*cos( rz );
879                 x = x2;
880                 y = y2;
881
882                 vList[i].v[0] = x;
883                 vList[i].v[1] = y;
884                 vList[i].v[2] = z;
885         }
886
887         // Get face list
888         for ( i = 0; i < triCount; i++ )
889         {
890                 TK_FetchRequire( TK_FACE );
891                 TK_FetchRequire( TK_LPAREN );
892                 for ( j = 0; j < 3; j++ )
893                 {
894                         TK_FetchRequire( TK_INTNUMBER );
895                         vertexNum = tk_IntNumber - 1;
896                         if ( vertexNum >= vertexCount ) {
897                                 Error( "File '%s', line %d:\nVertex number"
898                                            " >= vertexCount: %d\n", tk_SourceName, tk_Line,
899                                            tk_IntNumber );
900                         }
901                         tList[i].verts[2 - j][0] = vList[vertexNum].v[0];
902                         tList[i].verts[2 - j][1] = vList[vertexNum].v[1];
903                         tList[i].verts[2 - j][2] = vList[vertexNum].v[2];
904                 }
905                 TK_FetchRequire( TK_RPAREN );
906 #if 1
907                 if ( Version2 ) {
908                         TK_FetchRequire( TK_FLOATNUMBER );
909                         tList[i].uv[2][0] = fmod( 1000 + tk_FloatNumber,1 );
910                         TK_FetchRequire( TK_FLOATNUMBER );
911                         tList[i].uv[2][1] = fmod( 1000 + tk_FloatNumber,1 );
912                         TK_FetchRequire( TK_FLOATNUMBER );
913                         tList[i].uv[1][0] = fmod( 1000 + tk_FloatNumber,1 );
914                         TK_FetchRequire( TK_FLOATNUMBER );
915                         tList[i].uv[1][1] = fmod( 1000 + tk_FloatNumber,1 );
916                         TK_FetchRequire( TK_FLOATNUMBER );
917                         tList[i].uv[0][0] = fmod( 1000 + tk_FloatNumber,1 );
918                         TK_FetchRequire( TK_FLOATNUMBER );
919                         tList[i].uv[0][1] = fmod( 1000 + tk_FloatNumber,1 );
920                         tList[i].HasUV = 1;
921                 }
922                 else{
923                         tList[i].HasUV = 0;
924                 }
925 #endif
926 /*              printf("Face %i:\n  v0: %f, %f, %f\n  v1: %f, %f, %f\n"
927             "  v2: %f, %f, %f\n", i,
928             tList[i].verts[0][0],
929             tList[i].verts[0][1],
930             tList[i].verts[0][2],
931             tList[i].verts[1][0],
932             tList[i].verts[1][1],
933             tList[i].verts[1][2],
934             tList[i].verts[2][0],
935             tList[i].verts[2][1],
936             tList[i].verts[2][2]);
937  */
938         }
939
940         free( vList );
941         TK_CloseSource();
942         DefaultNodesList( nodesList,num_mesh_nodes,triangleCount );
943 }
944
945 //==========================================================================
946 //
947 // LoadTriangleList
948 //
949 //==========================================================================
950
951 void LoadTriangleList( char *fileName, triangle_t **triList, int *triangleCount, mesh_node_t **ppmnodes, int *num_mesh_nodes ){
952         FILE    *file1;
953         int dot = '.';
954         char    *dotstart;
955         char InputFileName[256];
956
957         dotstart = strrchr( fileName,dot ); // Does it already have an extension on the file name?
958
959         if ( !dotstart ) {
960                 strcpy( InputFileName, fileName );
961                 strcat( InputFileName, ".hrc" );
962                 if ( ( file1 = fopen( InputFileName, "rb" ) ) != NULL ) {
963                         fclose( file1 );
964                         LoadHRC( InputFileName, triList, triangleCount, ppmnodes, num_mesh_nodes );
965                         printf( " - assuming .HRC\n" );
966                         return;
967                 }
968
969                 strcpy( InputFileName, fileName );
970                 strcat( InputFileName, ".asc" );
971                 if ( ( file1 = fopen( InputFileName, "rb" ) ) != NULL ) {
972                         fclose( file1 );
973                         LoadASC( InputFileName, triList, triangleCount, ppmnodes, num_mesh_nodes );
974                         printf( " - assuming .ASC\n" );
975                         return;
976                 }
977
978                 strcpy( InputFileName, fileName );
979                 strcat( InputFileName, ".tri" );
980                 if ( ( file1 = fopen( InputFileName, "rb" ) ) != NULL ) {
981                         fclose( file1 );
982                         LoadTRI( InputFileName, triList, triangleCount, ppmnodes, num_mesh_nodes );
983                         printf( " - assuming .TRI\n" );
984                         return;
985                 }
986
987                 strcpy( InputFileName, fileName );
988                 strcat( InputFileName, ".3ds" );
989                 if ( ( file1 = fopen( InputFileName, "rb" ) ) != NULL ) {
990                         fclose( file1 );
991                         Load3DSTriangleList( InputFileName, triList, triangleCount, ppmnodes, num_mesh_nodes );
992                         printf( " - assuming .3DS\n" );
993                         return;
994                 }
995
996                 strcpy( InputFileName, fileName );
997                 strcat( InputFileName, ".htr" );
998                 if ( ( file1 = fopen( InputFileName, "rb" ) ) != NULL ) {
999                         fclose( file1 );
1000                         LoadHTR( InputFileName, triList, triangleCount, ppmnodes, num_mesh_nodes );
1001                         printf( " - assuming .HTR\n" );
1002                         return;
1003                 }
1004                 Error( "\n Could not open file '%s':\n"
1005                            "No HRC, ASC, 3DS, HTR, or TRI match.\n", fileName );
1006         }
1007         else
1008         {
1009                 if ( ( file1 = fopen( fileName, "rb" ) ) != NULL ) {
1010                         printf( "\n" );
1011                         fclose( file1 );
1012                         if ( strcmp( dotstart,".hrc" ) == 0 || strcmp( dotstart,".HRC" ) == 0 ) {
1013                                 LoadHRC( fileName, triList, triangleCount, ppmnodes, num_mesh_nodes );
1014                         }
1015                         else if ( strcmp( dotstart,".asc" ) == 0 || strcmp( dotstart,".ASC" ) == 0 ) {
1016                                 LoadASC( fileName, triList, triangleCount, ppmnodes, num_mesh_nodes );
1017                         }
1018                         else if ( strcmp( dotstart,".tri" ) == 0 || strcmp( dotstart,".TRI" ) == 0 ) {
1019                                 LoadTRI( fileName, triList, triangleCount, ppmnodes, num_mesh_nodes );
1020                         }
1021                         else if ( strcmp( dotstart,".3ds" ) == 0 || strcmp( dotstart,".3DS" ) == 0 ) {
1022                                 Load3DSTriangleList( fileName, triList, triangleCount, ppmnodes, num_mesh_nodes );
1023                         }
1024                         else if ( strcmp( dotstart,".htr" ) == 0 || strcmp( dotstart,".HTR" ) == 0 ) {
1025                                 LoadHTR( fileName, triList, triangleCount, ppmnodes, num_mesh_nodes );
1026                         }
1027                         else
1028                         {
1029                                 Error( "Could not open file '%s':\n",fileName );
1030                                 return;
1031                         }
1032                 }
1033                 else    //failed to load file
1034                 {
1035                         Error( "Could not open file '%s':\n",fileName );
1036                 }
1037
1038         }
1039 }