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