1 /*
2  * loadtri.c
3  * $Id: loadtri.c,v 1.14 2010-02-22 22:30:33 sezero Exp $
4  *
5  * Copyright (C) 1996-1997  Id Software, Inc.
6  * Copyright (C) 1997-1998  Raven Software Corp.
7  *
8  * This program is free software; you can redistribute it and/or modify
9  * it under the terms of the GNU General Public License as published by
10  * the Free Software Foundation; either version 2 of the License, or (at
11  * your option) any later version.
12  *
13  * This program is distributed in the hope that it will be useful, but
14  * WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
16  *
17  * See the GNU General Public License for more details.
18  *
19  * You should have received a copy of the GNU General Public License along
20  * with this program; if not, write to the Free Software Foundation, Inc.,
21  * 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
22  */
23 
24 // HEADER FILES ------------------------------------------------------------
25 
26 #include "q_stdinc.h"
27 #include "compiler.h"
28 #include "arch_def.h"
29 #include "cmdlib.h"
30 #include "pathutil.h"
31 #include "mathlib.h"
32 #include "loadtri.h"
33 #include "token.h"
34 #include "q_endian.h"
35 
36 // MACROS ------------------------------------------------------------------
37 
38 //#undef M_PI
39 //#define M_PI	3.14159265
40 #define MY_PI	3.14159265
41 
42 // 3DS binary files
43 #define _3DS_MAIN3DS		0x4D4D
44 #define _3DS_EDIT3DS		0x3D3D
45 #define _3DS_EDIT_MATERIAL	0xAFFF
46 #define _3DS_EDIT_VIEW1		0x7001
47 #define _3DS_EDIT_BACKGR	0x1200
48 #define _3DS_EDIT_AMBIENT	0x2100
49 #define _3DS_EDIT_UNKNW01	0x1100
50 #define _3DS_EDIT_UNKNW02	0x1201
51 #define _3DS_EDIT_UNKNW03	0x1300
52 #define _3DS_EDIT_UNKNW04	0x1400
53 #define _3DS_EDIT_UNKNW05	0x1420
54 #define _3DS_EDIT_UNKNW06	0x1450
55 #define _3DS_EDIT_UNKNW07	0x1500
56 #define _3DS_EDIT_UNKNW08	0x2200
57 #define _3DS_EDIT_UNKNW09	0x2201
58 #define _3DS_EDIT_UNKNW10	0x2210
59 #define _3DS_EDIT_UNKNW11	0x2300
60 #define _3DS_EDIT_UNKNW12	0x2302
61 #define _3DS_EDIT_UNKNW13	0x3000
62 #define _3DS_EDIT_UNKNW14	0xAFFF
63 #define _3DS_EDIT_OBJECT	0x4000
64 #define _3DS_OBJ_LIGHT		0x4600
65 #define _3DS_OBJ_CAMERA		0x4700
66 #define _3DS_OBJ_UNKNWN01	0x4010
67 #define _3DS_OBJ_UNKNWN02	0x4012
68 #define _3DS_OBJ_TRIMESH	0x4100
69 #define _3DS_TRI_FACEL2		0x4111
70 #define _3DS_TRI_VISIBLE	0x4165
71 #define _3DS_TRI_VERTEXL	0x4110
72 #define _3DS_TRI_FACEL1		0x4120
73 
74 // TRI binary files
75 #define FLOAT_START	99999.0
76 #define FLOAT_END	-FLOAT_START
77 #define TRI_MAGIC	123322
78 
79 // TYPES -------------------------------------------------------------------
80 
81 typedef struct
82 {
83 	float	v[3];
84 } vector;
85 
86 typedef struct
87 {
88 	vector	n;	// normal
89 	vector	p;	// point
90 	vector	c;	// color
91 	float	u;	// u
92 	float	v;	// v
93 } aliaspoint_t;
94 
95 typedef struct
96 {
97 	aliaspoint_t	pt[3];
98 } tf_triangle;
99 
100 // EXTERNAL FUNCTION PROTOTYPES --------------------------------------------
101 
102 // PUBLIC FUNCTION PROTOTYPES ----------------------------------------------
103 
104 // PRIVATE FUNCTION PROTOTYPES ---------------------------------------------
105 
106 static void LoadHRC(char *fileName, triangle_t **triList, int *triangleCount);
107 static void LoadASC(char *fileName, triangle_t **triList, int *triangleCount);
108 static void LoadHTR(char *fileName, triangle_t **triList, int *triangleCount);
109 static void LoadTRI(FILE *input, triangle_t **triList, int *triangleCount);
110 
111 static void ByteSwapTri(tf_triangle *tri);
112 
113 #if 0	/* unused 3DS stuff */
114 static void Load3DS(FILE *input, triangle_t **triList, int *triangleCount);
115 static void _3DSError(char *message);
116 
117 static float ReadFloat(void);
118 static unsigned long ReadLong(void);
119 static unsigned short ReadShort(void);
120 static unsigned char ReadByte(void);
121 static void SkipName(void);
122 static void SeekTo(int position);
123 static unsigned long FilePosition(void);
124 #endif
125 
126 // EXTERNAL DATA DECLARATIONS ----------------------------------------------
127 
128 // PUBLIC DATA DEFINITIONS -------------------------------------------------
129 
130 char	InputFileName[1024];
131 FILE	*InputFile;
132 float	FixHTRRotateX = 0.0;
133 float	FixHTRRotateY = 0.0;
134 float	FixHTRRotateZ = 0.0;
135 float	FixHTRTranslateX = 0.0;
136 float	FixHTRTranslateY = 0.0;
137 float	FixHTRTranslateZ = 0.0;
138 
139 // PRIVATE DATA DEFINITIONS ------------------------------------------------
140 
141 // CODE --------------------------------------------------------------------
142 
143 //==========================================================================
144 //
145 // LoadTriangleList
146 //
147 //==========================================================================
148 
LoadTriangleList(const char * fileName,triangle_t ** triList,int * triangleCount)149 void LoadTriangleList(const char *fileName, triangle_t **triList, int *triangleCount)
150 {
151 	FILE	*input;
152 
153 	q_strlcpy(InputFileName, fileName, sizeof(InputFileName));
154 
155 	StripExtension(InputFileName);
156 	q_strlcat(InputFileName, ".asc", sizeof(InputFileName));
157 	if ((input = fopen(InputFileName, "rb")) != NULL)
158 	{
159 		fclose(input);
160 		LoadASC(InputFileName, triList, triangleCount);
161 		return;
162 	}
163 
164 	StripExtension(InputFileName);
165 	q_strlcat(InputFileName, ".hrc", sizeof(InputFileName));
166 	if ((input = fopen(InputFileName, "rb")) != NULL)
167 	{
168 		fclose(input);
169 		LoadHRC(InputFileName, triList, triangleCount);
170 		return;
171 	}
172 
173 	StripExtension(InputFileName);
174 	q_strlcat(InputFileName, ".htr", sizeof(InputFileName));
175 	if ((input = fopen(InputFileName, "rb")) != NULL)
176 	{
177 		fclose(input);
178 		LoadHTR(InputFileName, triList, triangleCount);
179 		return;
180 	}
181 
182 	StripExtension(InputFileName);
183 	q_strlcat(InputFileName, ".tri", sizeof(InputFileName));
184 	if ((input = fopen(InputFileName, "rb")) != NULL)
185 	{
186 		LoadTRI(input, triList, triangleCount);
187 		fclose(input);
188 		return;
189 	}
190 
191 	COM_Error("Could not open file '%s':\n"
192 		"No ASC, HRC, HTR, or TRI match.\n", fileName);
193 }
194 
195 //==========================================================================
196 //
197 // LoadHRC
198 //
199 //==========================================================================
200 
LoadHRC(char * fileName,triangle_t ** triList,int * triangleCount)201 static void LoadHRC(char *fileName, triangle_t **triList, int *triangleCount)
202 {
203 	int		i, j;
204 	int		vertexCount;
205 	struct vList_s
206 	{
207 		float v[3];
208 	} *vList;
209 	int		triCount;
210 	triangle_t	*tList;
211 	float	scaling[3];
212 	float	rotation[3];
213 	float	translation[3];
214 	float	x, y, z;
215 	float	x2, y2, z2;
216 	float	rx, ry, rz;
217 
218 	TK_Init();
219 	TK_OpenSource(fileName);
220 	TK_FetchRequire(TK_HRCH);
221 	TK_FetchRequire(TK_COLON);
222 	TK_FetchRequire(TK_SOFTIMAGE);
223 	TK_Beyond(TK_MODEL);
224 	TK_Beyond(TK_SCALING);
225 	for (i = 0; i < 3; i++)
226 	{
227 		TK_Require(TK_FLOATNUMBER);
228 		scaling[i] = tk_FloatNumber;
229 		TK_Fetch();
230 	}
231 	TK_Beyond(TK_ROTATION);
232 	for (i = 0; i < 3; i++)
233 	{
234 		TK_Require(TK_FLOATNUMBER);
235 		rotation[i] = tk_FloatNumber;
236 		TK_Fetch();
237 	}
238 	TK_Beyond(TK_TRANSLATION);
239 	for (i = 0; i < 3; i++)
240 	{
241 		TK_Require(TK_FLOATNUMBER);
242 		translation[i] = tk_FloatNumber;
243 		TK_Fetch();
244 	}
245 
246 	rx = (float)(((rotation[0]-90.0)/360.0)*2.0*MY_PI);
247 	ry = (float)((rotation[1]/360.0)*2.0*MY_PI);
248 	rz = (float)((rotation[2]/360.0)*2.0*MY_PI);
249 
250 	TK_Beyond(TK_MESH);
251 	TK_BeyondRequire(TK_VERTICES, TK_INTNUMBER);
252 	vertexCount = tk_IntNumber;
253 	vList = (struct vList_s *) SafeMalloc(vertexCount * sizeof(vList[0]));
254 	for (i = 0; i < vertexCount; i++)
255 	{
256 		TK_BeyondRequire(TK_LBRACKET, TK_INTNUMBER);
257 		if (tk_IntNumber != i)
258 		{
259 			COM_Error("File '%s', line %d:\nVertex index mismatch.\n",
260 						tk_SourceName, tk_Line);
261 		}
262 		TK_Beyond(TK_POSITION);
263 		// Apply the scaling, rotation, and translation in the order
264 		// specified in the HRC file.  This could be wrong.
265 		TK_Require(TK_FLOATNUMBER);
266 		x = tk_FloatNumber*scaling[0];
267 		TK_FetchRequire(TK_FLOATNUMBER);
268 		y = tk_FloatNumber*scaling[1];
269 		TK_FetchRequire(TK_FLOATNUMBER);
270 		z = tk_FloatNumber*scaling[2];
271 
272 		y2 = (float)(y*cos(rx)+z*sin(rx));
273 		z2 = (float)(-y*sin(rx)+z*cos(rx));
274 		y = y2;
275 		z = z2;
276 
277 		x2 = (float)(x*cos(ry)-z*sin(ry));
278 		z2 = (float)(x*sin(ry)+z*cos(ry));
279 		x = x2;
280 		z = z2;
281 
282 		x2 = (float)(x*cos(rz)+y*sin(rz));
283 		y2 = (float)(-x*sin(rz)+y*cos(rz));
284 		x = x2;
285 		y = y2;
286 
287 		vList[i].v[0] = x+translation[0];
288 		vList[i].v[1] = y+translation[1];
289 		vList[i].v[2] = z+translation[2];
290 	}
291 	TK_BeyondRequire(TK_POLYGONS, TK_INTNUMBER);
292 	triCount = tk_IntNumber;
293 	if (triCount >= MAXTRIANGLES)
294 	{
295 		COM_Error("Too many triangles in file %s\n", InputFileName);
296 	}
297 	*triangleCount = triCount;
298 	tList = (triangle_t *) SafeMalloc(MAXTRIANGLES * sizeof(triangle_t));
299 	*triList = tList;
300 	for (i = 0; i < triCount; i++)
301 	{
302 		TK_BeyondRequire(TK_LBRACKET, TK_INTNUMBER);
303 		if (tk_IntNumber != i)
304 		{
305 			COM_Error("File '%s', line %d:\nTriangle index mismatch.\n",
306 						tk_SourceName, tk_Line);
307 		}
308 		TK_BeyondRequire(TK_NODES, TK_INTNUMBER);
309 		if (tk_IntNumber != 3)
310 		{
311 			COM_Error("File '%s', line %d:\nBad polygon vertex count: %d.",
312 					tk_SourceName, tk_Line, tk_IntNumber);
313 		}
314 		for (j = 0; j < 3; j++)
315 		{
316 			TK_BeyondRequire(TK_LBRACKET, TK_INTNUMBER);
317 			if (tk_IntNumber != j)
318 			{
319 				COM_Error("File '%s', line %d:\nTriangle vertex index"
320 					" mismatch.  %d should be %d\n", tk_SourceName, tk_Line,
321 					tk_IntNumber, j);
322 			}
323 			TK_BeyondRequire(TK_VERTEX, TK_INTNUMBER);
324 			tList[i].verts[2-j][0] = vList[tk_IntNumber].v[0];
325 			tList[i].verts[2-j][1] = vList[tk_IntNumber].v[1];
326 			tList[i].verts[2-j][2] = vList[tk_IntNumber].v[2];
327 		}
328 
329 /*		printf("Face %i:\n  v0: %f, %f, %f\n  v1: %f, %f, %f\n"
330 			"  v2: %f, %f, %f\n", i,
331 			tList[i].verts[0][0],
332 			tList[i].verts[0][1],
333 			tList[i].verts[0][2],
334 			tList[i].verts[1][0],
335 			tList[i].verts[1][1],
336 			tList[i].verts[1][2],
337 			tList[i].verts[2][0],
338 			tList[i].verts[2][1],
339 			tList[i].verts[2][2]);
340 */
341 	}
342 }
343 
344 //==========================================================================
345 //
346 // LoadASC
347 //
348 //==========================================================================
349 
LoadASC(char * fileName,triangle_t ** triList,int * triangleCount)350 static void LoadASC(char *fileName, triangle_t **triList, int *triangleCount)
351 {
352 	int		i, j;
353 	int		vertexCount;
354 	struct vList_s
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 	TK_Init();
366 	TK_OpenSource(fileName);
367 
368 	goodObject = false;
369 	while (goodObject == false)
370 	{
371 		TK_Beyond(TK_C_NAMED);
372 		TK_Beyond(TK_OBJECT);
373 		TK_Beyond(TK_C_TRI);
374 		TK_Beyond(TK_MESH);
375 		TK_BeyondRequire(TK_C_VERTICES, TK_COLON);
376 		TK_FetchRequire(TK_INTNUMBER);
377 		vertexCount = tk_IntNumber;
378 		if (vertexCount > 0)
379 		{
380 			goodObject = true;
381 		}
382 	}
383 	TK_BeyondRequire(TK_C_FACES, TK_COLON);
384 	TK_FetchRequire(TK_INTNUMBER);
385 	triCount = tk_IntNumber;
386 	if (triCount >= MAXTRIANGLES)
387 	{
388 		COM_Error("Too many triangles in file %s\n", InputFileName);
389 	}
390 	*triangleCount = triCount;
391 	tList = (triangle_t *) SafeMalloc(MAXTRIANGLES * sizeof(triangle_t));
392 	*triList = tList;
393 	TK_BeyondRequire(TK_C_VERTEX, TK_LIST);
394 
395 /*	rx = ((rotation[0]+90.0)/360.0)*2.0*MY_PI;
396 	//rx = (rotation[0]/360.0)*2.0*MY_PI;
397 	ry = (rotation[1]/360.0)*2.0*MY_PI;
398 	rz = (rotation[2]/360.0)*2.0*MY_PI;
399 */
400 	vList = (struct vList_s *) SafeMalloc(vertexCount * sizeof(vList[0]));
401 	for (i = 0; i < vertexCount; i++)
402 	{
403 		TK_BeyondRequire(TK_C_VERTEX, TK_INTNUMBER);
404 		if (tk_IntNumber != i)
405 		{
406 			COM_Error("File '%s', line %d:\nVertex index mismatch.\n",
407 						tk_SourceName, tk_Line);
408 		}
409 		TK_FetchRequireFetch(TK_COLON);
410 
411 		TK_BeyondRequire(TK_COLON, TK_FLOATNUMBER);
412 		x = tk_FloatNumber;
413 		TK_BeyondRequire(TK_COLON, TK_FLOATNUMBER);
414 		y = tk_FloatNumber;
415 		TK_BeyondRequire(TK_COLON, TK_FLOATNUMBER);
416 		z = tk_FloatNumber;
417 
418 /*		x2 = x*cos(rz)+y*sin(rz);
419 		y2 = -x*sin(rz)+y*cos(rz);
420 		x = x2;
421 		y = y2;
422 		y2 = y*cos(rx)+z*sin(rx);
423 		z2 = -y*sin(rx)+z*cos(rx);
424 		y = y2;
425 		z = z2;
426 		x2 = x*cos(ry)-z*sin(ry);
427 		z2 = x*sin(ry)+z*cos(ry);
428 		x = x2;
429 		z = z2;
430 */
431 		vList[i].v[0] = x;
432 		vList[i].v[1] = y;
433 		vList[i].v[2] = z;
434 	}
435 	TK_BeyondRequire(TK_C_FACE, TK_LIST);
436 	for (i = 0; i < triCount; i++)
437 	{
438 		TK_BeyondRequire(TK_C_FACE, TK_INTNUMBER);
439 		if (tk_IntNumber != i)
440 		{
441 			COM_Error("File '%s', line %d:\nTriangle index mismatch.\n",
442 						tk_SourceName, tk_Line);
443 		}
444 		for (j = 0; j < 3; j++)
445 		{
446 			TK_BeyondRequire(TK_IDENTIFIER, TK_COLON);
447 			TK_FetchRequire(TK_INTNUMBER);
448 			if (tk_IntNumber >= vertexCount)
449 			{
450 				COM_Error("File '%s', line %d:\nVertex number"
451 					" > vertexCount: %d\n", tk_SourceName, tk_Line,
452 					tk_IntNumber);
453 			}
454 			tList[i].verts[2-j][0] = vList[tk_IntNumber].v[0];
455 			tList[i].verts[2-j][1] = vList[tk_IntNumber].v[1];
456 			tList[i].verts[2-j][2] = vList[tk_IntNumber].v[2];
457 		}
458 
459 /*		printf("Face %i:\n  v0: %f, %f, %f\n  v1: %f, %f, %f\n"
460 			"  v2: %f, %f, %f\n", i,
461 			tList[i].verts[0][0],
462 			tList[i].verts[0][1],
463 			tList[i].verts[0][2],
464 			tList[i].verts[1][0],
465 			tList[i].verts[1][1],
466 			tList[i].verts[1][2],
467 			tList[i].verts[2][0],
468 			tList[i].verts[2][1],
469 			tList[i].verts[2][2]);
470 */
471 	}
472 }
473 
474 //==========================================================================
475 //
476 // LoadHTR
477 //
478 //==========================================================================
479 
LoadHTR(char * fileName,triangle_t ** triList,int * triangleCount)480 static void LoadHTR(char *fileName, triangle_t **triList, int *triangleCount)
481 {
482 	int		i, j;
483 	int		vertexCount;
484 	int		vertexNum;
485 	struct vList_s
486 	{
487 		float v[3];
488 	} *vList;
489 	int		triCount;
490 	float	origin[3];
491 	triangle_t	*tList;
492 	float	x, y, z;
493 	float	x2, y2, z2;
494 	float	rx, ry, rz;
495 
496 	TK_Init();
497 	TK_OpenSource(fileName);
498 
499 	TK_Beyond(TK_C_HEXEN);
500 	TK_Beyond(TK_C_TRIANGLES);
501 	TK_BeyondRequire(TK_C_VERSION, TK_INTNUMBER);
502 	if (tk_IntNumber != 1)
503 	{
504 		COM_Error("Unsupported version (%d) in file %s\n", tk_IntNumber,
505 							InputFileName);
506 	}
507 
508 	// Get vertex count
509 	TK_BeyondRequire(TK_VERTICES, TK_INTNUMBER);
510 	vertexCount = tk_IntNumber;
511 	vList = (struct vList_s *) SafeMalloc(vertexCount * sizeof(vList[0]));
512 
513 	// Get triangle count
514 	TK_BeyondRequire(TK_FACES, TK_INTNUMBER);
515 	triCount = tk_IntNumber;
516 	if (triCount >= MAXTRIANGLES)
517 	{
518 		COM_Error("Too many triangles in file %s\n", InputFileName);
519 	}
520 	*triangleCount = triCount;
521 	tList = (triangle_t *) SafeMalloc(MAXTRIANGLES * sizeof(triangle_t));
522 	*triList = tList;
523 
524 	// Get origin
525 	TK_Beyond(TK_ORIGIN);
526 	TK_Require(TK_FLOATNUMBER);
527 	origin[0] = tk_FloatNumber;
528 	TK_FetchRequire(TK_FLOATNUMBER);
529 	origin[1] = tk_FloatNumber;
530 	TK_FetchRequire(TK_FLOATNUMBER);
531 	origin[2] = tk_FloatNumber;
532 
533 	//rx = 90.0/360.0*2.0*MY_PI;
534 	rx =(float)(FixHTRRotateX/360.0*2.0*MY_PI);
535 	ry =(float)(FixHTRRotateY/360.0*2.0*MY_PI);
536 	rz =(float)(FixHTRRotateZ/360.0*2.0*MY_PI);
537 
538 	// Get vertex list
539 	for (i = 0; i < vertexCount; i++)
540 	{
541 		TK_FetchRequire(TK_VERTEX);
542 		TK_FetchRequire(TK_FLOATNUMBER);
543 		x = tk_FloatNumber-origin[0];
544 		TK_FetchRequire(TK_FLOATNUMBER);
545 		y = tk_FloatNumber-origin[1];
546 		TK_FetchRequire(TK_FLOATNUMBER);
547 		z = tk_FloatNumber-origin[2];
548 
549 		x += FixHTRTranslateX;
550 		y += FixHTRTranslateY;
551 		z += FixHTRTranslateZ;
552 
553 		y2 = (float)(y*cos(rx)-z*sin(rx));
554 		z2 = (float)(y*sin(rx)+z*cos(rx));
555 		y = y2;
556 		z = z2;
557 		x2 = (float)(x*cos(ry)+z*sin(ry));
558 		z2 = (float)(-x*sin(ry)+z*cos(ry));
559 		x = x2;
560 		z = z2;
561 		x2 = (float)(x*cos(rz)-y*sin(rz));
562 		y2 = (float)(x*sin(rz)+y*cos(rz));
563 		x = x2;
564 		y = y2;
565 
566 		vList[i].v[0] = x;
567 		vList[i].v[1] = y;
568 		vList[i].v[2] = z;
569 	}
570 
571 	// Get face list
572 	for (i = 0; i < triCount; i++)
573 	{
574 		TK_FetchRequire(TK_FACE);
575 		TK_FetchRequire(TK_LPAREN);
576 		for (j = 0; j < 3; j++)
577 		{
578 			TK_FetchRequire(TK_INTNUMBER);
579 			vertexNum = tk_IntNumber-1;
580 			if (vertexNum >= vertexCount)
581 			{
582 				COM_Error("File '%s', line %d:\nVertex number"
583 					" >= vertexCount: %d\n", tk_SourceName, tk_Line,
584 					tk_IntNumber);
585 			}
586 			tList[i].verts[2-j][0] = vList[vertexNum].v[0];
587 			tList[i].verts[2-j][1] = vList[vertexNum].v[1];
588 			tList[i].verts[2-j][2] = vList[vertexNum].v[2];
589 		}
590 		TK_FetchRequire(TK_RPAREN);
591 
592 /*		printf("Face %i:\n  v0: %f, %f, %f\n  v1: %f, %f, %f\n"
593 			"  v2: %f, %f, %f\n", i,
594 			tList[i].verts[0][0],
595 			tList[i].verts[0][1],
596 			tList[i].verts[0][2],
597 			tList[i].verts[1][0],
598 			tList[i].verts[1][1],
599 			tList[i].verts[1][2],
600 			tList[i].verts[2][0],
601 			tList[i].verts[2][1],
602 			tList[i].verts[2][2]);
603 */
604 	}
605 }
606 
607 //==========================================================================
608 //
609 // Load3DS
610 //
611 //==========================================================================
612 #if 0	/* 3DS stuff is unused. don't even know whether it's working */
613 static void Load3DS(FILE *input, triangle_t **triList, int *triangleCount)
614 {
615 	unsigned int i, j;
616 	qboolean stop;
617 	qboolean foundVertexList;
618 	unsigned int chunkType, chunkPos, chunkSize;
619 	unsigned int editChunkSize, editChunkPos;
620 	unsigned int objectChunkSize, objectChunkPos;
621 	unsigned int meshChunkSize, meshChunkPos;
622 	unsigned int vertex;
623 	unsigned int vertexCount;
624 	struct vList_s
625 	{
626 		float v[3];
627 	} *vList;
628 	unsigned int triCount;
629 	triangle_t	*tList;
630 
631 	InputFile = input;
632 	if (ReadShort() != _3DS_MAIN3DS)
633 	{
634 		_3DSError("Missing 3DS main chunk header.\n");
635 	}
636 	SeekTo(16);
637 	if (ReadShort() != _3DS_EDIT3DS)
638 	{
639 		_3DSError("Missing 3DS edit chunk header.\n");
640 	}
641 
642 	editChunkSize = ReadLong();
643 	editChunkPos = FilePosition()-6;
644 	stop = false;
645 	while (stop == false)
646 	{
647 		chunkPos = FilePosition();
648 		chunkType = ReadShort();
649 		switch (chunkType)
650 		{
651 			case _3DS_EDIT_UNKNW01:
652 			case _3DS_EDIT_UNKNW02:
653 			case _3DS_EDIT_UNKNW03:
654 			case _3DS_EDIT_UNKNW04:
655 			case _3DS_EDIT_UNKNW05:
656 			case _3DS_EDIT_UNKNW06:
657 			case _3DS_EDIT_UNKNW07:
658 			case _3DS_EDIT_UNKNW08:
659 			case _3DS_EDIT_UNKNW09:
660 			case _3DS_EDIT_UNKNW10:
661 			case _3DS_EDIT_UNKNW11:
662 			case _3DS_EDIT_UNKNW12:
663 			case _3DS_EDIT_UNKNW13:
664 			case _3DS_EDIT_MATERIAL:
665 			case _3DS_EDIT_VIEW1:
666 			case _3DS_EDIT_BACKGR:
667 			case _3DS_EDIT_AMBIENT:
668 				SeekTo(chunkPos+ReadLong());
669 				break;
670 			case _3DS_EDIT_OBJECT:
671 				stop = true;
672 			default:
673 				break;
674 		}
675 		if (FilePosition()-editChunkPos >= editChunkSize)
676 		{
677 			_3DSError("Couldn't find OBJECT chunk.\n");
678 		}
679 	}
680 
681 	objectChunkSize = ReadLong();
682 	objectChunkPos = FilePosition()-6;
683 	SkipName();
684 	stop = false;
685 	while (stop == false)
686 	{
687 		chunkPos = FilePosition();
688 		chunkType = ReadShort();
689 		switch (chunkType)
690 		{
691 			case _3DS_OBJ_UNKNWN01:
692 			case _3DS_OBJ_UNKNWN02:
693 			case _3DS_OBJ_LIGHT:
694 			case _3DS_OBJ_CAMERA:
695 				SeekTo(chunkPos+ReadLong());
696 				break;
697 			case _3DS_OBJ_TRIMESH:
698 				stop = true;
699 			default:
700 				break;
701 		}
702 		if (FilePosition()-objectChunkPos >= objectChunkSize)
703 		{
704 			_3DSError("Couldn't find TRIMESH chunk.\n");
705 		}
706 	}
707 
708 	meshChunkSize = ReadLong();
709 	meshChunkPos = FilePosition()-6;
710 	stop = false;
711 	foundVertexList = false;
712 	while (stop == false)
713 	{
714 		chunkPos = FilePosition();
715 		chunkType = ReadShort();
716 		switch (chunkType)
717 		{
718 			case _3DS_TRI_FACEL2:
719 			case _3DS_TRI_VISIBLE:
720 				SeekTo(chunkPos+ReadLong());
721 				break;
722 			case _3DS_TRI_VERTEXL:
723 				chunkSize = ReadLong();
724 				vertexCount = ReadShort();
725 				vList = (struct vList_s *) SafeMalloc(vertexCount * sizeof(vList[0]));
726 				for (i = 0; i < vertexCount; i++)
727 				{
728 					vList[i].v[0] = ReadFloat();
729 					vList[i].v[1] = -ReadFloat();
730 					vList[i].v[2] = ReadFloat();
731 				}
732 				SeekTo(chunkPos+chunkSize);
733 				foundVertexList = true;
734 				break;
735 			case _3DS_TRI_FACEL1:
736 				chunkSize = ReadLong();
737 				triCount = ReadShort();
738 				if (triCount >= MAXTRIANGLES)
739 				{
740 					COM_Error("Too many triangles in file %s\n",
741 								InputFileName);
742 				}
743 				*triangleCount = triCount;
744 				tList = (triangle_t *) SafeMalloc(MAXTRIANGLES * sizeof(triangle_t));
745 				*triList = tList;
746 				for (i = 0; i < triCount; i++)
747 				{
748 					for (j = 0; j < 3; j++)
749 					{
750 						vertex = ReadShort();
751 						tList[i].verts[j][0] = vList[vertex].v[0];
752 						tList[i].verts[j][1] = vList[vertex].v[1];
753 						tList[i].verts[j][2] = vList[vertex].v[2];
754 					}
755 					ReadShort(); // Skip face flags
756 				}
757 				stop = true;
758 				break;
759 			default:
760 				break;
761 		}
762 		if (FilePosition()-meshChunkPos >= meshChunkSize)
763 		{
764 			if (foundVertexList == false)
765 			{
766 				_3DSError("Couldn't find TRI_VERTEXL chunk.\n");
767 			}
768 			else
769 			{
770 				_3DSError("Couldn't find TRI_FACEL1 chunk.\n");
771 			}
772 		}
773 	}
774 }
775 
776 static void _3DSError(char *message)
777 {
778 	COM_Error(message);
779 }
780 
781 static float ReadFloat(void)
782 {
783 	float	t;
784 
785 	fread(&t, sizeof(float), 1, InputFile);
786 	return t;
787 }
788 
789 static unsigned long ReadLong(void)
790 {
791 	unsigned long	t;
792 
793 	fread(&t, sizeof(unsigned long), 1, InputFile);
794 	return t;
795 }
796 
797 static unsigned short ReadShort(void)
798 {
799 	unsigned short	t;
800 
801 	fread(&t, sizeof(unsigned short), 1, InputFile);
802 	return t;
803 }
804 
805 static unsigned char ReadByte(void)
806 {
807 	unsigned char	t;
808 
809 	fread(&t, sizeof(unsigned char), 1, InputFile);
810 	return t;
811 }
812 
813 static void SkipName(void)
814 {
815 	int		i;
816 	int		c;
817 
818 	for (i = 0, c = 1; i < 12 && c != 0; i++)
819 	{
820 		c = ReadByte();
821 	}
822 }
823 
824 static void SeekTo(int position)
825 {
826 	fseek(InputFile, position, SEEK_SET);
827 }
828 
829 static unsigned long FilePosition(void)
830 {
831 	return ftell(InputFile);
832 }
833 #endif	// end of unused 3DS stuff
834 
835 //==========================================================================
836 //
837 // LoadTRI
838 //
839 //==========================================================================
840 
LoadTRI(FILE * input,triangle_t ** triList,int * triangleCount)841 static void LoadTRI(FILE *input, triangle_t **triList, int *triangleCount)
842 {
843 	int		i, j, k;
844 	char	text[256];
845 	int		count;
846 	int		magic;
847 	tf_triangle	tri;
848 	triangle_t	*ptri;
849 	int		exitpattern;
850 	float		t;
851 	union {
852 		float	_f;
853 		int	_i;
854 	} start;
855 
856 	t = -FLOAT_START;
857 	*((unsigned char *)&exitpattern + 0) = *((unsigned char *)&t + 3);
858 	*((unsigned char *)&exitpattern + 1) = *((unsigned char *)&t + 2);
859 	*((unsigned char *)&exitpattern + 2) = *((unsigned char *)&t + 1);
860 	*((unsigned char *)&exitpattern + 3) = *((unsigned char *)&t + 0);
861 
862 	fread(&magic, sizeof(int), 1, input);
863 	if (BigLong(magic) != TRI_MAGIC)
864 	{
865 		COM_Error("Bad .TRI file: %s\n", InputFileName);
866 	}
867 
868 	ptri = (triangle_t *) SafeMalloc(MAXTRIANGLES * sizeof(triangle_t));
869 	*triList = ptri;
870 
871 	count = 0; // make static analyzers happy
872 	while (feof(input) == 0)
873 	{
874 		fread(&start._f, sizeof(float), 1, input);
875 		start._i = BigLong(start._i);
876 
877 		if (start._i != exitpattern)
878 		{
879 			if (start._f == FLOAT_START)
880 			{ // Start of an object or group of objects
881 				i = -1;
882 				do
883 				{
884 					++i;
885 					fread(&(text[i]), sizeof(char), 1, input);
886 				} while (text[i] != '\0');
887 				//fprintf(stdout,"OBJECT START: %s\n", text);
888 
889 				fread(&count, sizeof(int), 1, input);
890 				count = BigLong(count);
891 				if (count != 0)
892 				{
893 					//fprintf(stdout,"NUMBER OF TRIANGLES: %d\n", count);
894 					i = -1;
895 					do
896 					{
897 						++i;
898 						fread(&(text[i]), sizeof( char ), 1, input);
899 					} while (text[i] != '\0');
900 					//fprintf(stdout,"  Object texture name: '%s'\n", text);
901 				}
902 			}
903 			else if (start._f == FLOAT_END)
904 			{
905 				i = -1;
906 				do
907 				{
908 					++i;
909 					fread(&(text[i]), sizeof(char), 1, input);
910 				} while (text[i] != '\0');
911 				//fprintf(stdout,"OBJECT END: %s\n", text);
912 				continue;
913 			}
914 		}
915 
916 		// Read the triangles
917 		for (i = 0; i < count; ++i)
918 		{
919 			fread(&tri, sizeof(tf_triangle), 1, input);
920 			ByteSwapTri(&tri);
921 			for (j = 0; j < 3; j++)
922 			{
923 				for (k = 0; k < 3; k++)
924 				{
925 					ptri->verts[j][k] = tri.pt[j].p.v[k];
926 				}
927 			}
928 
929 /*			printf("Face %i:\n  v0: %f, %f, %f\n  v1: %f, %f, %f\n"
930 				"  v2: %f, %f, %f\n", i,
931 				ptri->verts[0][0],
932 				ptri->verts[0][1],
933 				ptri->verts[0][2],
934 				ptri->verts[1][0],
935 				ptri->verts[1][1],
936 				ptri->verts[1][2],
937 				ptri->verts[2][0],
938 				ptri->verts[2][1],
939 				ptri->verts[2][2]);
940 */
941 			ptri++;
942 			if ((ptri - *triList) >= MAXTRIANGLES)
943 			{
944 				COM_Error("Error: too many triangles; increase MAXTRIANGLES\n");
945 			}
946 		}
947 	}
948 	*triangleCount = ptri - *triList;
949 }
950 
951 //==========================================================================
952 //
953 // ByteSwapTri
954 //
955 //==========================================================================
956 
ByteSwapTri(tf_triangle * tri)957 static void ByteSwapTri(tf_triangle *tri)
958 {
959 	int		i;
960 
961 	for (i = 0; i < (int) sizeof(tf_triangle)/4; i++)
962 	{
963 		((int *)tri)[i] = BigLong(((int *)tri)[i]);
964 	}
965 }
966 
967