1 /*
2 Copyright (C) 1999-2006 Id Software, Inc. and contributors.
3 For a list of contributors, see the accompanying CONTRIBUTORS file.
4 
5 This file is part of GtkRadiant.
6 
7 GtkRadiant is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2 of the License, or
10 (at your option) any later version.
11 
12 GtkRadiant is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15 GNU General Public License for more details.
16 
17 You should have received a copy of the GNU General Public License
18 along with GtkRadiant; if not, write to the Free Software
19 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
20 */
21 
22 
23 #include "qdata.h"
24 #include <assert.h>
25 #include "jointed.h"
26 #include "fmodel.h"
27 
28 //=================================================================
29 
30 typedef struct
31 {
32 	int		numnormals;
33 	vec3_t	normalsum;
34 } vertexnormals_t;
35 
36 typedef struct
37 {
38 	vec3_t		v;
39 	int			lightnormalindex;
40 } trivert_t;
41 
42 typedef struct
43 {
44 	vec3_t		mins, maxs;
45 	char		name[16];
46 	trivert_t	v[MAX_VERTS];
47 	QDataJoint_t	joints[NUM_CLUSTERS]; // ,this
48 } frame_t;
49 
50 // ,and all of this should get out of here, need to use new stuff in fmodels instead
51 
52 typedef struct IntListNode_s
53 {
54 	int data;
55 	struct IntListNode_s *next;
56 } IntListNode_t;  // gaak
57 
58 typedef struct
59 {
60 	float		scale[3];	// multiply byte verts by this
61 	float		translate[3];	// then add this
62 } PartialAliasFrame_t;
63 
64 int jointed;
65 int clustered;
66 
67 int *clusters[NUM_CLUSTERS];
68 IntListNode_t *vertLists[NUM_CLUSTERS];
69 int		num_verts[NUM_CLUSTERS + 1];
70 int		new_num_verts[NUM_CLUSTERS + 1];
71 
72 // end that
73 
74 //================================================================
75 
76 extern frame_t		g_frames[MAX_FRAMES];
77 //frame_t		*g_frames;
78 
79 static dmdl_t		model;
80 
81 
82 float		scale_up;			// set by $scale
83 vec3_t		adjust;				// set by $origin
84 int			g_fixedwidth, g_fixedheight;	// set by $skinsize
85 
86 
87 //
88 // base frame info
89 //
90 dstvert_t	base_st[MAX_VERTS];
91 dtriangle_t	triangles[MAX_TRIANGLES];
92 
93 static int			triangle_st[MAX_TRIANGLES][3][2];
94 
95 // the command list holds counts, s/t values, and xyz indexes
96 // that are valid for every frame
97 int			commands[16384];
98 int			numcommands;
99 int			numglverts;
100 int			used[MAX_TRIANGLES];
101 
102 char		g_skins[MAX_MD2SKINS][64];
103 
104 char		cdarchive[1024];
105 char		cdpartial[1024];
106 char		cddir[1024];
107 
108 char		modelname[64];	// empty unless $modelname issued (players)
109 
110 extern 	char		*g_outputDir;
111 
112 #define NUMVERTEXNORMALS	162
113 
114 float	avertexnormals[NUMVERTEXNORMALS][3] =
115 {
116 	#include "anorms.h"
117 };
118 
119 unsigned char pic[SKINPAGE_HEIGHT*SKINPAGE_WIDTH], pic_palette[768];
120 
121 FILE	*headerouthandle = NULL;
122 
123 //==============================================================
124 
125 /*
126 ===============
127 ClearModel
128 ===============
129 */
ClearModel(void)130 static void ClearModel (void)
131 {
132 	memset (&model, 0, sizeof(model));
133 
134 	modelname[0] = 0;
135 	jointed = NOT_JOINTED;
136 	clustered = 0;
137 	scale_up = 1.0;
138 	VectorCopy (vec3_origin, adjust);
139 	g_fixedwidth = g_fixedheight = 0;
140 	g_skipmodel = false;
141 }
142 
143 
H_printf(char * fmt,...)144 void H_printf(char *fmt, ...)
145 {
146 	va_list argptr;
147 	char	name[1024];
148 
149 	if (!headerouthandle)
150 	{
151 		sprintf (name, "%s/tris.h", cddir);
152 		headerouthandle = SafeOpenWrite (name);
153 		fprintf(headerouthandle, "// %s\n\n", cddir);
154 		fprintf(headerouthandle, "// This file generated by qdata - Do NOT Modify\n\n");
155 	}
156 
157 	va_start (argptr, fmt);
158 	vfprintf (headerouthandle, fmt, argptr);
159 	va_end (argptr);
160 }
161 
162 #if 1
163 /*
164 ============
165 WriteModelFile
166 ============
167 */
WriteCommonModelFile(FILE * modelouthandle,PartialAliasFrame_t * outFrames)168 void WriteCommonModelFile (FILE *modelouthandle, PartialAliasFrame_t *outFrames)
169 {
170 	int				i;
171 	dmdl_t			modeltemp;
172 	int				j, k;
173 	frame_t			*in;
174 	daliasframe_t	*out;
175 	byte			buffer[MAX_VERTS*4+128];
176 	float			v;
177 	int				c_on, c_off;
178 
179 	model.version = ALIAS_VERSION;
180 	model.framesize = (int)&((daliasframe_t *)0)->verts[model.num_xyz];
181 	model.num_glcmds = numcommands;
182 	model.ofs_skins = sizeof(dmdl_t);
183 	model.ofs_st = model.ofs_skins + model.num_skins * MAX_SKINNAME;
184 	model.ofs_tris = model.ofs_st + model.num_st*sizeof(dstvert_t);
185 	model.ofs_frames = model.ofs_tris + model.num_tris*sizeof(dtriangle_t);
186 	model.ofs_glcmds = model.ofs_frames + model.num_frames*model.framesize;
187 	model.ofs_end = model.ofs_glcmds + model.num_glcmds*sizeof(int);
188 	//
189 	// write out the model header
190 	//
191 	for (i=0 ; i<sizeof(dmdl_t)/4 ; i++)
192 		((int *)&modeltemp)[i] = LittleLong (((int *)&model)[i]);
193 
194 	SafeWrite (modelouthandle, &modeltemp, sizeof(modeltemp));
195 
196 	//
197 	// write out the skin names
198 	//
199 	SafeWrite (modelouthandle, g_skins, model.num_skins * MAX_SKINNAME);
200 
201 	//
202 	// write out the texture coordinates
203 	//
204 	c_on = c_off = 0;
205 	for (i=0 ; i<model.num_st ; i++)
206 	{
207 		base_st[i].s = LittleShort (base_st[i].s);
208 		base_st[i].t = LittleShort (base_st[i].t);
209 	}
210 
211 	SafeWrite (modelouthandle, base_st, model.num_st * sizeof(base_st[0]));
212 
213 	//
214 	// write out the triangles
215 	//
216 	for (i=0 ; i<model.num_tris ; i++)
217 	{
218 		int			j;
219 		dtriangle_t	tri;
220 
221 		for (j=0 ; j<3 ; j++)
222 		{
223 			tri.index_xyz[j] = LittleShort (triangles[i].index_xyz[j]);
224 			tri.index_st[j] = LittleShort (triangles[i].index_st[j]);
225 		}
226 
227 		SafeWrite (modelouthandle, &tri, sizeof(tri));
228 	}
229 
230 	//
231 	// write out the frames
232 	//
233 	for (i=0 ; i<model.num_frames ; i++)
234 	{
235 		in = &g_frames[i];
236 		out = (daliasframe_t *)buffer;
237 
238 		strcpy (out->name, in->name);
239 		for (j=0 ; j<3 ; j++)
240 		{
241 			out->scale[j] = (in->maxs[j] - in->mins[j])/255;
242 			out->translate[j] = in->mins[j];
243 
244 			if(outFrames)
245 			{
246 				outFrames[i].scale[j] = out->scale[j];
247 				outFrames[i].translate[j] = out->translate[j];
248 			}
249 		}
250 
251 		for (j=0 ; j<model.num_xyz ; j++)
252 		{
253 		// all of these are byte values, so no need to deal with endianness
254 			out->verts[j].lightnormalindex = in->v[j].lightnormalindex;
255 
256 			for (k=0 ; k<3 ; k++)
257 			{
258 			// scale to byte values & min/max check
259 				v = Q_rint ( (in->v[j].v[k] - out->translate[k]) / out->scale[k] );
260 
261 			// clamp, so rounding doesn't wrap from 255.6 to 0
262 				if (v > 255.0)
263 					v = 255.0;
264 				if (v < 0)
265 					v = 0;
266 				out->verts[j].v[k] = v;
267 			}
268 		}
269 
270 		for (j=0 ; j<3 ; j++)
271 		{
272 			out->scale[j] = LittleFloat (out->scale[j]);
273 			out->translate[j] = LittleFloat (out->translate[j]);
274 		}
275 
276 		SafeWrite (modelouthandle, out, model.framesize);
277 	}
278 
279 	//
280 	// write out glcmds
281 	//
282 	SafeWrite (modelouthandle, commands, numcommands*4);
283 }
284 
285 /*
286 ============
287 WriteModelFile
288 ============
289 */
WriteModelFile(FILE * modelouthandle)290 void WriteModelFile (FILE *modelouthandle)
291 {
292 	model.ident = IDALIASHEADER;
293 
294 	WriteCommonModelFile(modelouthandle, NULL);
295 }
296 
297 /*
298 ============
299 WriteJointedModelFile
300 ============
301 */
WriteJointedModelFile(FILE * modelouthandle)302 void WriteJointedModelFile (FILE *modelouthandle)
303 {
304 	int				i;
305 	int				j, k;
306 	frame_t			*in;
307 	float			v;
308 	IntListNode_t	*current, *toFree;
309 	PartialAliasFrame_t outFrames[MAX_FRAMES];
310 
311 	model.ident = IDJOINTEDALIASHEADER;
312 
313 	WriteCommonModelFile(modelouthandle, outFrames);
314 
315 	// Skeletal Type
316 	SafeWrite(modelouthandle, &jointed, sizeof(int));
317 
318 	// number of joints
319 	SafeWrite(modelouthandle, &numJointsForSkeleton[jointed], sizeof(int));
320 
321 	// number of verts in each cluster
322 	SafeWrite(modelouthandle, &new_num_verts[1], sizeof(int)*numJointsForSkeleton[jointed]);
323 
324 	// cluster verts
325 	for(i = 0; i < new_num_verts[0]; ++i)
326 	{
327 		current = vertLists[i];
328 		while(current)
329 		{
330 			SafeWrite (modelouthandle, &current->data, sizeof(int));
331 			toFree = current;
332 			current = current->next;
333 			free(toFree);  // freeing of memory allocated in ReplaceClusterIndex called in Cmd_Base
334 		}
335 	}
336 
337 	for (i=0 ; i<model.num_frames ; i++)
338 	{
339 		in = &g_frames[i];
340 
341 		for (j = 0 ; j < new_num_verts[0]; ++j)
342 		{
343 			for (k=0 ; k<3 ; k++)
344 			{
345 				// scale to byte values & min/max check
346 				v = Q_rint ( (in->joints[j].placement.origin[k] - outFrames[i].translate[k]) / outFrames[i].scale[k] );
347 
348 				// clamp, so rounding doesn't wrap from 255.6 to 0
349 				if (v > 255.0)
350 				{
351 					v = 255.0;
352 				}
353 
354 				if (v < 0)
355 				{
356 					v = 0;
357 				}
358 
359 				// write out origin as a float (there's only a few per model, so it's not really
360 				// a size issue)
361 				SafeWrite (modelouthandle, &v, sizeof(float));
362 			}
363 
364 			for (k=0 ; k<3 ; k++)
365 			{
366 				v = Q_rint ( (in->joints[j].placement.direction[k] - outFrames[i].translate[k]) / outFrames[i].scale[k] );
367 
368 				// clamp, so rounding doesn't wrap from 255.6 to 0
369 				if (v > 255.0)
370 				{
371 					v = 255.0;
372 				}
373 
374 				if (v < 0)
375 				{
376 					v = 0;
377 				}
378 
379 				// write out origin as a float (there's only a few per model, so it's not really
380 				// a size issue)
381 				SafeWrite (modelouthandle, &v, sizeof(float));
382 			}
383 
384 			for (k=0 ; k<3 ; k++)
385 			{
386 				v = Q_rint ( (in->joints[j].placement.up[k] - outFrames[i].translate[k]) / outFrames[i].scale[k] );
387 
388 				// clamp, so rounding doesn't wrap from 255.6 to 0
389 				if (v > 255.0)
390 				{
391 					v = 255.0;
392 				}
393 
394 				if (v < 0)
395 				{
396 					v = 0;
397 				}
398 
399 				// write out origin as a float (there's only a few per model, so it's not really
400 				// a size issue)
401 				SafeWrite (modelouthandle, &v, sizeof(float));
402 			}
403 		}
404 	}
405 }
406 #else
407 /*
408 ============
409 WriteModelFile
410 ============
411 */
WriteModelFile(FILE * modelouthandle)412 static void WriteModelFile (FILE *modelouthandle)
413 {
414 	int				i;
415 	dmdl_t			modeltemp;
416 	int				j, k;
417 	frame_t			*in;
418 	daliasframe_t	*out;
419 	byte			buffer[MAX_VERTS*4+128];
420 	float			v;
421 	int				c_on, c_off;
422 
423 	model.ident = IDALIASHEADER;
424 	model.version = ALIAS_VERSION;
425 	model.framesize = (int)&((daliasframe_t *)0)->verts[model.num_xyz];
426 	model.num_glcmds = numcommands;
427 	model.ofs_skins = sizeof(dmdl_t);
428 	model.ofs_st = model.ofs_skins + model.num_skins * MAX_SKINNAME;
429 	model.ofs_tris = model.ofs_st + model.num_st*sizeof(dstvert_t);
430 	model.ofs_frames = model.ofs_tris + model.num_tris*sizeof(dtriangle_t);
431 	model.ofs_glcmds = model.ofs_frames + model.num_frames*model.framesize;
432 	model.ofs_end = model.ofs_glcmds + model.num_glcmds*4;
433 
434 	//
435 	// write out the model header
436 	//
437 	for (i=0 ; i<sizeof(dmdl_t)/4 ; i++)
438 		((int *)&modeltemp)[i] = LittleLong (((int *)&model)[i]);
439 
440 	SafeWrite (modelouthandle, &modeltemp, sizeof(modeltemp));
441 
442 	//
443 	// write out the skin names
444 	//
445 	SafeWrite (modelouthandle, g_skins, model.num_skins * MAX_SKINNAME);
446 
447 	//
448 	// write out the texture coordinates
449 	//
450 	c_on = c_off = 0;
451 	for (i=0 ; i<model.num_st ; i++)
452 	{
453 		base_st[i].s = LittleShort (base_st[i].s);
454 		base_st[i].t = LittleShort (base_st[i].t);
455 	}
456 
457 	SafeWrite (modelouthandle, base_st, model.num_st * sizeof(base_st[0]));
458 
459 	//
460 	// write out the triangles
461 	//
462 	for (i=0 ; i<model.num_tris ; i++)
463 	{
464 		int			j;
465 		dtriangle_t	tri;
466 
467 		for (j=0 ; j<3 ; j++)
468 		{
469 			tri.index_xyz[j] = LittleShort (triangles[i].index_xyz[j]);
470 			tri.index_st[j] = LittleShort (triangles[i].index_st[j]);
471 		}
472 
473 		SafeWrite (modelouthandle, &tri, sizeof(tri));
474 	}
475 
476 	//
477 	// write out the frames
478 	//
479 	for (i=0 ; i<model.num_frames ; i++)
480 	{
481 		in = &g_frames[i];
482 		out = (daliasframe_t *)buffer;
483 
484 		strcpy (out->name, in->name);
485 		for (j=0 ; j<3 ; j++)
486 		{
487 			out->scale[j] = (in->maxs[j] - in->mins[j])/255;
488 			out->translate[j] = in->mins[j];
489 		}
490 
491 		for (j=0 ; j<model.num_xyz ; j++)
492 		{
493 		// all of these are byte values, so no need to deal with endianness
494 			out->verts[j].lightnormalindex = in->v[j].lightnormalindex;
495 
496 			for (k=0 ; k<3 ; k++)
497 			{
498 			// scale to byte values & min/max check
499 				v = Q_rint ( (in->v[j].v[k] - out->translate[k]) / out->scale[k] );
500 
501 			// clamp, so rounding doesn't wrap from 255.6 to 0
502 				if (v > 255.0)
503 					v = 255.0;
504 				if (v < 0)
505 					v = 0;
506 				out->verts[j].v[k] = v;
507 			}
508 		}
509 
510 		for (j=0 ; j<3 ; j++)
511 		{
512 			out->scale[j] = LittleFloat (out->scale[j]);
513 			out->translate[j] = LittleFloat (out->translate[j]);
514 		}
515 
516 		SafeWrite (modelouthandle, out, model.framesize);
517 	}
518 
519 	//
520 	// write out glcmds
521 	//
522 	SafeWrite (modelouthandle, commands, numcommands*4);
523 }
524 #endif
525 
526 /*
527 ===============
528 FinishModel
529 ===============
530 */
FinishModel(void)531 void FinishModel (void)
532 {
533 	FILE		*modelouthandle;
534 	int			i;
535 	char		name[1024];
536 
537 	if (!model.num_frames)
538 		return;
539 
540 //
541 // copy to release directory tree if doing a release build
542 //
543 	if (g_release)
544 	{
545 		if (modelname[0])
546 			sprintf (name, "%s", modelname);
547 		else
548 			sprintf (name, "%s/tris.md2", cdpartial);
549 		ReleaseFile (name);
550 
551 		for (i=0 ; i<model.num_skins ; i++)
552 		{
553 			ReleaseFile (g_skins[i]);
554 		}
555 		model.num_frames = 0;
556 		return;
557 	}
558 
559 //
560 // write the model output file
561 //
562 	if (modelname[0])
563 		sprintf (name, "%s%s", g_outputDir, modelname);
564 	else
565 		sprintf (name, "%s/tris.md2", g_outputDir);
566 	printf ("saving to %s\n", name);
567 	CreatePath (name);
568 	modelouthandle = SafeOpenWrite (name);
569 
570 #if 1
571 	if(jointed != NOT_JOINTED)
572 		WriteJointedModelFile(modelouthandle);
573 	else
574 #endif
575 		WriteModelFile(modelouthandle);
576 
577 	printf ("%3dx%3d skin\n", model.skinwidth, model.skinheight);
578 	printf ("First frame boundaries:\n");
579 	printf ("	minimum x: %3f\n", g_frames[0].mins[0]);
580 	printf ("	maximum x: %3f\n", g_frames[0].maxs[0]);
581 	printf ("	minimum y: %3f\n", g_frames[0].mins[1]);
582 	printf ("	maximum y: %3f\n", g_frames[0].maxs[1]);
583 	printf ("	minimum z: %3f\n", g_frames[0].mins[2]);
584 	printf ("	maximum z: %3f\n", g_frames[0].maxs[2]);
585 	printf ("%4d vertices\n", model.num_xyz);
586 	printf ("%4d triangles\n", model.num_tris);
587 	printf ("%4d frame\n", model.num_frames);
588 	printf ("%4d glverts\n", numglverts);
589 	printf ("%4d glcmd\n", model.num_glcmds);
590 	printf ("%4d skins\n", model.num_skins);
591 	printf ("file size: %d\n", (int)ftell (modelouthandle) );
592 	printf ("---------------------\n");
593 
594 	fclose (modelouthandle);
595 
596 	// finish writing header file
597 	H_printf("\n");
598 
599 	// scale_up is usefull to allow step distances to be adjusted
600 	H_printf("#define MODEL_SCALE\t\t%f\n", scale_up);
601 
602 	fclose (headerouthandle);
603 	headerouthandle = NULL;
604 }
605 
606 
607 /*
608 =================================================================
609 
610 ALIAS MODEL DISPLAY LIST GENERATION
611 
612 =================================================================
613 */
614 
615 int		strip_xyz[128];
616 int		strip_st[128];
617 int		strip_tris[128];
618 int		stripcount;
619 
620 /*
621 ================
622 StripLength
623 ================
624 */
StripLength(int starttri,int startv)625 static int	StripLength (int starttri, int startv)
626 {
627 	int			m1, m2;
628 	int			st1, st2;
629 	int			j;
630 	dtriangle_t	*last, *check;
631 	int			k;
632 
633 	used[starttri] = 2;
634 
635 	last = &triangles[starttri];
636 
637 	strip_xyz[0] = last->index_xyz[(startv)%3];
638 	strip_xyz[1] = last->index_xyz[(startv+1)%3];
639 	strip_xyz[2] = last->index_xyz[(startv+2)%3];
640 	strip_st[0] = last->index_st[(startv)%3];
641 	strip_st[1] = last->index_st[(startv+1)%3];
642 	strip_st[2] = last->index_st[(startv+2)%3];
643 
644 	strip_tris[0] = starttri;
645 	stripcount = 1;
646 
647 	m1 = last->index_xyz[(startv+2)%3];
648 	st1 = last->index_st[(startv+2)%3];
649 	m2 = last->index_xyz[(startv+1)%3];
650 	st2 = last->index_st[(startv+1)%3];
651 
652 	// look for a matching triangle
653 nexttri:
654 	for (j=starttri+1, check=&triangles[starttri+1]
655 		; j<model.num_tris ; j++, check++)
656 	{
657 		for (k=0 ; k<3 ; k++)
658 		{
659 			if (check->index_xyz[k] != m1)
660 				continue;
661 			if (check->index_st[k] != st1)
662 				continue;
663 			if (check->index_xyz[ (k+1)%3 ] != m2)
664 				continue;
665 			if (check->index_st[ (k+1)%3 ] != st2)
666 				continue;
667 
668 			// this is the next part of the fan
669 
670 			// if we can't use this triangle, this tristrip is done
671 			if (used[j])
672 				goto done;
673 
674 			// the new edge
675 			if (stripcount & 1)
676 			{
677 				m2 = check->index_xyz[ (k+2)%3 ];
678 				st2 = check->index_st[ (k+2)%3 ];
679 			}
680 			else
681 			{
682 				m1 = check->index_xyz[ (k+2)%3 ];
683 				st1 = check->index_st[ (k+2)%3 ];
684 			}
685 
686 			strip_xyz[stripcount+2] = check->index_xyz[ (k+2)%3 ];
687 			strip_st[stripcount+2] = check->index_st[ (k+2)%3 ];
688 			strip_tris[stripcount] = j;
689 			stripcount++;
690 
691 			used[j] = 2;
692 			goto nexttri;
693 		}
694 	}
695 done:
696 
697 	// clear the temp used flags
698 	for (j=starttri+1 ; j<model.num_tris ; j++)
699 		if (used[j] == 2)
700 			used[j] = 0;
701 
702 	return stripcount;
703 }
704 
705 
706 /*
707 ===========
708 FanLength
709 ===========
710 */
FanLength(int starttri,int startv)711 static int	FanLength (int starttri, int startv)
712 {
713 	int		m1, m2;
714 	int		st1, st2;
715 	int		j;
716 	dtriangle_t	*last, *check;
717 	int		k;
718 
719 	used[starttri] = 2;
720 
721 	last = &triangles[starttri];
722 
723 	strip_xyz[0] = last->index_xyz[(startv)%3];
724 	strip_xyz[1] = last->index_xyz[(startv+1)%3];
725 	strip_xyz[2] = last->index_xyz[(startv+2)%3];
726 	strip_st[0] = last->index_st[(startv)%3];
727 	strip_st[1] = last->index_st[(startv+1)%3];
728 	strip_st[2] = last->index_st[(startv+2)%3];
729 
730 	strip_tris[0] = starttri;
731 	stripcount = 1;
732 
733 	m1 = last->index_xyz[(startv+0)%3];
734 	st1 = last->index_st[(startv+0)%3];
735 	m2 = last->index_xyz[(startv+2)%3];
736 	st2 = last->index_st[(startv+2)%3];
737 
738 
739 	// look for a matching triangle
740 nexttri:
741 	for (j=starttri+1, check=&triangles[starttri+1]
742 		; j<model.num_tris ; j++, check++)
743 	{
744 		for (k=0 ; k<3 ; k++)
745 		{
746 			if (check->index_xyz[k] != m1)
747 				continue;
748 			if (check->index_st[k] != st1)
749 				continue;
750 			if (check->index_xyz[ (k+1)%3 ] != m2)
751 				continue;
752 			if (check->index_st[ (k+1)%3 ] != st2)
753 				continue;
754 
755 			// this is the next part of the fan
756 
757 			// if we can't use this triangle, this tristrip is done
758 			if (used[j])
759 				goto done;
760 
761 			// the new edge
762 			m2 = check->index_xyz[ (k+2)%3 ];
763 			st2 = check->index_st[ (k+2)%3 ];
764 
765 			strip_xyz[stripcount+2] = m2;
766 			strip_st[stripcount+2] = st2;
767 			strip_tris[stripcount] = j;
768 			stripcount++;
769 
770 			used[j] = 2;
771 			goto nexttri;
772 		}
773 	}
774 done:
775 
776 	// clear the temp used flags
777 	for (j=starttri+1 ; j<model.num_tris ; j++)
778 		if (used[j] == 2)
779 			used[j] = 0;
780 
781 	return stripcount;
782 }
783 
784 
785 
786 /*
787 ================
788 BuildGlCmds
789 
790 Generate a list of trifans or strips
791 for the model, which holds for all frames
792 ================
793 */
BuildGlCmds(void)794 static void BuildGlCmds (void)
795 {
796 	int		i, j, k;
797 	int		startv;
798 	float	s, t;
799 	int		len, bestlen, besttype;
800 	int		best_xyz[1024];
801 	int		best_st[1024];
802 	int		best_tris[1024];
803 	int		type;
804 
805 	//
806 	// build tristrips
807 	//
808 	numcommands = 0;
809 	numglverts = 0;
810 	memset (used, 0, sizeof(used));
811 	for (i=0 ; i<model.num_tris ; i++)
812 	{
813 		// pick an unused triangle and start the trifan
814 		if (used[i])
815 			continue;
816 
817 		bestlen = 0;
818 		for (type = 0 ; type < 2 ; type++)
819 //	type = 1;
820 		{
821 			for (startv =0 ; startv < 3 ; startv++)
822 			{
823 				if (type == 1)
824 					len = StripLength (i, startv);
825 				else
826 					len = FanLength (i, startv);
827 				if (len > bestlen)
828 				{
829 					besttype = type;
830 					bestlen = len;
831 					for (j=0 ; j<bestlen+2 ; j++)
832 					{
833 						best_st[j] = strip_st[j];
834 						best_xyz[j] = strip_xyz[j];
835 					}
836 					for (j=0 ; j<bestlen ; j++)
837 						best_tris[j] = strip_tris[j];
838 				}
839 			}
840 		}
841 
842 		// mark the tris on the best strip/fan as used
843 		for (j=0 ; j<bestlen ; j++)
844 			used[best_tris[j]] = 1;
845 
846 		if (besttype == 1)
847 			commands[numcommands++] = (bestlen+2);
848 		else
849 			commands[numcommands++] = -(bestlen+2);
850 
851 		numglverts += bestlen+2;
852 
853 		for (j=0 ; j<bestlen+2 ; j++)
854 		{
855 			// emit a vertex into the reorder buffer
856 			k = best_st[j];
857 
858 			// emit s/t coords into the commands stream
859 			s = base_st[k].s;
860 			t = base_st[k].t;
861 
862 			s = (s + 0.5) / model.skinwidth;
863 			t = (t + 0.5) / model.skinheight;
864 
865 			*(float *)&commands[numcommands++] = s;
866 			*(float *)&commands[numcommands++] = t;
867 			*(int *)&commands[numcommands++] = best_xyz[j];
868 		}
869 	}
870 
871 	commands[numcommands++] = 0;		// end of list marker
872 }
873 
874 
875 /*
876 ===============================================================
877 
878 BASE FRAME SETUP
879 
880 ===============================================================
881 */
882 
883 /*
884 ============
885 BuildST
886 
887 Builds the triangle_st array for the base frame and
888 model.skinwidth / model.skinheight
889 
890   FIXME: allow this to be loaded from a file for
891   arbitrary mappings
892 ============
893 */
894 #if 0
895 static void OldBuildST (triangle_t *ptri, int numtri)
896 {
897 	int			i, j;
898 	int			width, height, iwidth, iheight, swidth;
899 	float		basex, basey;
900 	float		s_scale, t_scale;
901 	float		scale;
902 	vec3_t		mins, maxs;
903 	float		*pbasevert;
904 	vec3_t		vtemp1, vtemp2, normal;
905 
906 	//
907 	// find bounds of all the verts on the base frame
908 	//
909 	ClearBounds (mins, maxs);
910 
911 	for (i=0 ; i<numtri ; i++)
912 		for (j=0 ; j<3 ; j++)
913 			AddPointToBounds (ptri[i].verts[j], mins, maxs);
914 
915 	for (i=0 ; i<3 ; i++)
916 	{
917 		mins[i] = floor(mins[i]);
918 		maxs[i] = ceil(maxs[i]);
919 	}
920 
921 	width = maxs[0] - mins[0];
922 	height = maxs[2] - mins[2];
923 
924 	if (!g_fixedwidth)
925 	{	// old style
926 		scale = 8;
927 		if (width*scale >= 150)
928 			scale = 150.0 / width;
929 		if (height*scale >= 190)
930 			scale = 190.0 / height;
931 
932 		s_scale = t_scale = scale;
933 
934 		iwidth = ceil(width*s_scale);
935 		iheight = ceil(height*t_scale);
936 
937 		iwidth += 4;
938 		iheight += 4;
939 	}
940 	else
941 	{	// new style
942 		iwidth = g_fixedwidth / 2;
943 		iheight = g_fixedheight;
944 
945 		s_scale = (float)(iwidth-4) / width;
946 		t_scale = (float)(iheight-4) / height;
947 	}
948 
949 //
950 // determine which side of each triangle to map the texture to
951 //
952 	for (i=0 ; i<numtri ; i++)
953 	{
954 		VectorSubtract (ptri[i].verts[0], ptri[i].verts[1], vtemp1);
955 		VectorSubtract (ptri[i].verts[2], ptri[i].verts[1], vtemp2);
956 		CrossProduct (vtemp1, vtemp2, normal);
957 
958 		if (normal[1] > 0)
959 		{
960 			basex = iwidth + 2;
961 		}
962 		else
963 		{
964 			basex = 2;
965 		}
966 		basey = 2;
967 
968 		for (j=0 ; j<3 ; j++)
969 		{
970 			pbasevert = ptri[i].verts[j];
971 
972 			triangle_st[i][j][0] = Q_rint((pbasevert[0] - mins[0]) * s_scale + basex);
973 			triangle_st[i][j][1] = Q_rint((maxs[2] - pbasevert[2]) * t_scale + basey);
974 		}
975 	}
976 
977 // make the width a multiple of 4; some hardware requires this, and it ensures
978 // dword alignment for each scan
979 	swidth = iwidth*2;
980 	model.skinwidth = (swidth + 3) & ~3;
981 	model.skinheight = iheight;
982 }
983 #endif
984 
985 //==========================================================================
986 //
987 // DrawScreen
988 //
989 //==========================================================================
990 
DrawScreen(float s_scale,float t_scale,float iwidth,float iheight)991 void DrawScreen(float s_scale, float t_scale, float iwidth, float iheight)
992 {
993 	int i;
994 	byte *scrpos;
995 	char buffer[256];
996 
997 	// Divider
998 	scrpos = &pic[(INFO_Y-2)*SKINPAGE_WIDTH];
999 	for(i = 0; i < SKINPAGE_WIDTH; i++)
1000 	{
1001 		*scrpos++ = 255;
1002 	}
1003 
1004 	sprintf(buffer, "GENSKIN:  ");
1005 	DrawTextChar(16, INFO_Y, buffer);
1006 
1007 	sprintf(buffer, "( %03d * %03d )   SCALE %f %f, SKINWIDTH %d,"
1008 		" SKINHEIGHT %d", (int)ScaleWidth, (int)ScaleHeight, s_scale, t_scale, (int)iwidth*2, (int)iheight);
1009 	DrawTextChar(80, INFO_Y, buffer);
1010 }
1011 
1012 /*
1013 ============
1014 BuildST
1015 
1016 Builds the triangle_st array for the base frame and
1017 model.skinwidth / model.skinheight
1018 
1019   FIXME: allow this to be loaded from a file for
1020   arbitrary mappings
1021 ============
1022 */
BuildST(triangle_t * ptri,int numtri,qboolean DrawSkin)1023 void BuildST (triangle_t *ptri, int numtri, qboolean DrawSkin)
1024 {
1025 	int			i, j;
1026 	int			width, height, iwidth, iheight, swidth;
1027 	float		basex, basey;
1028 	float		scale;
1029 	vec3_t		mins, maxs;
1030 	float		*pbasevert;
1031 	vec3_t		vtemp1, vtemp2, normal;
1032 	float		s_scale, t_scale;
1033 	float		scWidth;
1034 	float		scHeight;
1035 
1036 	//
1037 	// find bounds of all the verts on the base frame
1038 	//
1039 	ClearBounds (mins, maxs);
1040 
1041 	for (i=0 ; i<numtri ; i++)
1042 		for (j=0 ; j<3 ; j++)
1043 			AddPointToBounds (ptri[i].verts[j], mins, maxs);
1044 
1045 	for (i=0 ; i<3 ; i++)
1046 	{
1047 		mins[i] = floor(mins[i]);
1048 		maxs[i] = ceil(maxs[i]);
1049 	}
1050 
1051 	width = maxs[0] - mins[0];
1052 	height = maxs[2] - mins[2];
1053 
1054 
1055 	scWidth = (ScaleWidth/2)*SCALE_ADJUST_FACTOR;
1056 	scHeight = ScaleHeight*SCALE_ADJUST_FACTOR;
1057 
1058 	scale = scWidth/width;
1059 
1060 	if(height*scale >= scHeight)
1061 	{
1062 		scale = scHeight/height;
1063 	}
1064 
1065 	iwidth = ceil(width*scale)+4;
1066 	iheight = ceil(height*scale)+4;
1067 
1068 	s_scale = (float)(iwidth-4) / width;
1069 	t_scale = (float)(iheight-4) / height;
1070 	t_scale = s_scale;
1071 
1072 	if (DrawSkin)
1073 		DrawScreen(s_scale, t_scale, iwidth, iheight);
1074 
1075 
1076 /*	if (!g_fixedwidth)
1077 	{	// old style
1078 		scale = 8;
1079 		if (width*scale >= 150)
1080 			scale = 150.0 / width;
1081 		if (height*scale >= 190)
1082 			scale = 190.0 / height;
1083 
1084 		s_scale = t_scale = scale;
1085 
1086 		iwidth = ceil(width*s_scale);
1087 		iheight = ceil(height*t_scale);
1088 
1089 		iwidth += 4;
1090 		iheight += 4;
1091 	}
1092 	else
1093 	{	// new style
1094 		iwidth = g_fixedwidth / 2;
1095 		iheight = g_fixedheight;
1096 
1097 		s_scale = (float)(iwidth-4) / width;
1098 		t_scale = (float)(iheight-4) / height;
1099 	}*/
1100 
1101 //
1102 // determine which side of each triangle to map the texture to
1103 //
1104 	for (i=0 ; i<numtri ; i++)
1105 	{
1106 		if (ptri[i].HasUV)
1107 		{
1108 			for (j=0 ; j<3 ; j++)
1109 			{
1110 				triangle_st[i][j][0] = Q_rint(ptri[i].uv[j][0]*iwidth);
1111 				triangle_st[i][j][1] = Q_rint((1.0f-ptri[i].uv[j][1])*iheight);
1112 			}
1113 		}
1114 		else
1115 		{
1116 			VectorSubtract (ptri[i].verts[0], ptri[i].verts[1], vtemp1);
1117 			VectorSubtract (ptri[i].verts[2], ptri[i].verts[1], vtemp2);
1118 			CrossProduct (vtemp1, vtemp2, normal);
1119 
1120 			if (normal[1] > 0)
1121 			{
1122 				basex = iwidth + 2;
1123 			}
1124 			else
1125 			{
1126 				basex = 2;
1127 			}
1128 			basey = 2;
1129 
1130 			for (j=0 ; j<3 ; j++)
1131 			{
1132 				pbasevert = ptri[i].verts[j];
1133 
1134 				triangle_st[i][j][0] = Q_rint((pbasevert[0] - mins[0]) * s_scale + basex);
1135 				triangle_st[i][j][1] = Q_rint((maxs[2] - pbasevert[2]) * t_scale + basey);
1136 			}
1137 		}
1138 
1139 		DrawLine(triangle_st[i][0][0], triangle_st[i][0][1],
1140 			triangle_st[i][1][0], triangle_st[i][1][1]);
1141 		DrawLine(triangle_st[i][1][0], triangle_st[i][1][1],
1142 			triangle_st[i][2][0], triangle_st[i][2][1]);
1143 		DrawLine(triangle_st[i][2][0], triangle_st[i][2][1],
1144 			triangle_st[i][0][0], triangle_st[i][0][1]);
1145 	}
1146 
1147 // make the width a multiple of 4; some hardware requires this, and it ensures
1148 // dword alignment for each scan
1149 
1150 	swidth = iwidth*2;
1151 	model.skinwidth = (swidth + 3) & ~3;
1152 	model.skinheight = iheight;
1153 }
1154 
1155 
ReplaceClusterIndex(int newIndex,int oldindex,int ** clusters,IntListNode_t ** vertLists,int * num_verts,int * new_num_verts)1156 static void ReplaceClusterIndex(int newIndex, int oldindex, int **clusters,
1157 	IntListNode_t **vertLists, int *num_verts, int *new_num_verts)
1158 {
1159 	int i, j;
1160 	IntListNode_t *next;
1161 
1162 	for(j = 0; j < num_verts[0]; ++j)
1163 	{
1164 		for(i = 0; i < num_verts[j+1]; ++i)
1165 		{
1166 			if(clusters[j][i] == oldindex)
1167 			{
1168 				++new_num_verts[j+1];
1169 
1170 				next = vertLists[j];
1171 
1172 				vertLists[j] = (IntListNode_t *) SafeMalloc(sizeof(IntListNode_t), "ReplaceClusterIndex");
1173 				// Currently freed in WriteJointedModelFile only
1174 
1175 				vertLists[j]->data = newIndex;
1176 				vertLists[j]->next = next;
1177 			}
1178 		}
1179 	}
1180 }
1181 
1182 /*
1183 =================
1184 Cmd_Base
1185 =================
1186 */
Cmd_Base(void)1187 void Cmd_Base (void)
1188 {
1189 	vec3_t		base_xyz[MAX_VERTS];
1190 	triangle_t	*ptri;
1191 	int			i, j, k;
1192 #if 1
1193 #else
1194 	int		time1;
1195 #endif
1196 	char	file1[1024];
1197 	char	file2[1024];
1198 
1199 	GetScriptToken (false);
1200 
1201 	if (g_skipmodel || g_release || g_archive)
1202 		return;
1203 
1204 	printf ("---------------------\n");
1205 #if 1
1206 	sprintf (file1, "%s/%s", cdpartial, token);
1207 	printf ("%s  ", file1);
1208 
1209 	ExpandPathAndArchive (file1);
1210 
1211 	sprintf (file1, "%s/%s", cddir, token);
1212 #else
1213 	sprintf (file1, "%s/%s.%s", cdarchive, token, trifileext);
1214 	printf ("%s\n", file1);
1215 
1216 	ExpandPathAndArchive (file1);
1217 
1218 	sprintf (file1, "%s/%s.%s", cddir, token, trifileext);
1219 
1220 	time1 = FileTime (file1);
1221 	if (time1 == -1)
1222 		Error ("%s doesn't exist", file1);
1223 #endif
1224 //
1225 // load the base triangles
1226 //
1227 	if (do3ds)
1228 		Load3DSTriangleList (file1, &ptri, &model.num_tris, NULL, NULL);
1229 	else
1230 		LoadTriangleList (file1, &ptri, &model.num_tris, NULL, NULL);
1231 
1232 
1233 	GetScriptToken (false);
1234 	sprintf (file2, "%s/%s.pcx", cddir, token);
1235 //	sprintf (trans_file, "%s/!%s_a.pcx", cddir, token);
1236 
1237 	printf ("skin: %s\n", file2);
1238  	Load256Image (file2, &BasePixels, &BasePalette, &BaseWidth, &BaseHeight);
1239 
1240 	if (BaseWidth != SKINPAGE_WIDTH || BaseHeight != SKINPAGE_HEIGHT)
1241 	{
1242 		if (g_allow_newskin)
1243 		{
1244 			ScaleWidth = BaseWidth;
1245 			ScaleHeight = BaseHeight;
1246 		}
1247 		else
1248 		{
1249 			Error("Invalid skin page size: (%d,%d) should be (%d,%d)",
1250 				BaseWidth,BaseHeight,SKINPAGE_WIDTH,SKINPAGE_HEIGHT);
1251 		}
1252 	}
1253 	else
1254 	{
1255 		ScaleWidth = (float)ExtractNumber(BasePixels, ENCODED_WIDTH_X,
1256 			ENCODED_WIDTH_Y);
1257 		ScaleHeight = (float)ExtractNumber(BasePixels, ENCODED_HEIGHT_X,
1258 			ENCODED_HEIGHT_Y);
1259 	}
1260 
1261 //
1262 // get the ST values
1263 //
1264 	BuildST (ptri, model.num_tris,false);
1265 
1266 //
1267 // run through all the base triangles, storing each unique vertex in the
1268 // base vertex list and setting the indirect triangles to point to the base
1269 // vertices
1270 //
1271 	for (i=0 ; i<model.num_tris ; i++)
1272 	{
1273 		for (j=0 ; j<3 ; j++)
1274 		{
1275 			// get the xyz index
1276 			for (k=0 ; k<model.num_xyz ; k++)
1277 				if (VectorCompare (ptri[i].verts[j], base_xyz[k]))
1278 					break;	// this vertex is already in the base vertex list
1279 
1280 			if (k == model.num_xyz)
1281 			{ // new index
1282 				VectorCopy (ptri[i].verts[j], base_xyz[model.num_xyz]);
1283 
1284 				if(clustered)
1285 					ReplaceClusterIndex(k, ptri[i].indicies[j], (int **)&clusters, (IntListNode_t **)&vertLists, (int *)&num_verts, (int *)&new_num_verts);
1286 
1287 				model.num_xyz++;
1288 			}
1289 
1290 			triangles[i].index_xyz[j] = k;
1291 
1292 			// get the st index
1293 			for (k=0 ; k<model.num_st ; k++)
1294 				if (triangle_st[i][j][0] == base_st[k].s
1295 				&& triangle_st[i][j][1] == base_st[k].t)
1296 					break;	// this vertex is already in the base vertex list
1297 
1298 			if (k == model.num_st)
1299 			{ // new index
1300 				base_st[model.num_st].s = triangle_st[i][j][0];
1301 				base_st[model.num_st].t = triangle_st[i][j][1];
1302 				model.num_st++;
1303 			}
1304 
1305 			triangles[i].index_st[j] = k;
1306 		}
1307 	}
1308 
1309 	// build triangle strips / fans
1310 	BuildGlCmds ();
1311 }
1312 
1313 //===============================================================
1314 
FindFrameFile(char * frame)1315 char	*FindFrameFile (char *frame)
1316 {
1317 	int				time1;
1318 	char			file1[1024];
1319 	static char		retname[1024];
1320 	char			base[32];
1321 	char			suffix[32];
1322 	char			*s;
1323 
1324 	if (strstr (frame, "."))
1325 		return frame;		// allready in dot format
1326 
1327 	// split 'run1' into 'run' and '1'
1328 	s = frame + strlen(frame)-1;
1329 
1330 	while (s != frame && *s >= '0' && *s <= '9')
1331 		s--;
1332 
1333 	strcpy (suffix, s+1);
1334 	strcpy (base, frame);
1335 	base[s-frame+1] = 0;
1336 
1337 	sprintf (file1, "%s/%s%s.%s",cddir, base, suffix, "hrc");
1338 	time1 = FileTime (file1);
1339 	if (time1 != -1)
1340 	{
1341 		sprintf (retname, "%s%s.%s", base, suffix, "hrc");
1342 		return retname;
1343 	}
1344 
1345 	sprintf (file1, "%s/%s%s.%s",cddir, base, suffix, "asc");
1346 	time1 = FileTime (file1);
1347 	if (time1 != -1)
1348 	{
1349 		sprintf (retname, "%s%s.%s", base, suffix, "asc");
1350 		return retname;
1351 	}
1352 
1353 	sprintf (file1, "%s/%s%s.%s",cddir, base, suffix, "tri");
1354 	time1 = FileTime (file1);
1355 	if (time1 != -1)
1356 	{
1357 		sprintf (retname, "%s%s.%s", base, suffix, "tri");
1358 		return retname;
1359 	}
1360 
1361 	sprintf (file1, "%s/%s%s.%s",cddir, base, suffix, "3ds");
1362 	time1 = FileTime (file1);
1363 	if (time1 != -1)
1364 	{
1365 		sprintf (retname, "%s%s.%s", base, suffix, "3ds");
1366 		return retname;
1367 	}
1368 
1369 	sprintf (file1, "%s/%s%s.%s",cddir, base, suffix, "htr");
1370 	time1 = FileTime (file1);
1371 	if (time1 != -1)
1372 	{
1373 		sprintf (retname, "%s%s.%s", base, suffix, "htr");
1374 		return retname;
1375 	}
1376 
1377 	// check for 'run.1'
1378 	sprintf (file1, "%s/%s.%s",cddir, base, suffix);
1379 	time1 = FileTime (file1);
1380 	if (time1 != -1)
1381 	{
1382 		sprintf (retname, "%s.%s", base, suffix);
1383 		return retname;
1384 	}
1385 
1386 	Error ("frame %s could not be found",frame);
1387 	return NULL;
1388 }
1389 
1390 /*
1391 ===============
1392 GrabFrame
1393 ===============
1394 */
GrabFrame(char * frame)1395 static void GrabFrame (char *frame)
1396 {
1397 	triangle_t		*ptri;
1398 	int				i, j;
1399 	trivert_t		*ptrivert;
1400 	int				num_tris;
1401 	char			file1[1024];
1402 	frame_t			*fr;
1403 	vertexnormals_t	vnorms[MAX_VERTS];
1404 	int				index_xyz;
1405 	char			*framefile;
1406 
1407 	// the frame 'run1' will be looked for as either
1408 	// run.1 or run1.tri, so the new alias sequence save
1409 	// feature an be used
1410 	framefile = FindFrameFile (frame);
1411 
1412 	sprintf (file1, "%s/%s", cdarchive, framefile);
1413 	ExpandPathAndArchive (file1);
1414 
1415 	sprintf (file1, "%s/%s",cddir, framefile);
1416 
1417 	printf ("grabbing %s  ", file1);
1418 
1419 	if (model.num_frames >= MAX_FRAMES)
1420 		Error ("model.num_frames >= MAX_FRAMES");
1421 	fr = &g_frames[model.num_frames];
1422 	model.num_frames++;
1423 
1424 	strcpy (fr->name, frame);
1425 
1426 //
1427 // load the frame
1428 //
1429 	if (do3ds)
1430 		Load3DSTriangleList (file1, &ptri, &num_tris, NULL, NULL);
1431 	else
1432 		LoadTriangleList (file1, &ptri, &num_tris, NULL, NULL);
1433 
1434 	if (num_tris != model.num_tris)
1435 		Error ("%s: number of triangles doesn't match base frame\n", file1);
1436 
1437 //
1438 // allocate storage for the frame's vertices
1439 //
1440 	ptrivert = fr->v;
1441 
1442 	for (i=0 ; i<model.num_xyz ; i++)
1443 	{
1444 		vnorms[i].numnormals = 0;
1445 		VectorClear (vnorms[i].normalsum);
1446 	}
1447 	ClearBounds (fr->mins, fr->maxs);
1448 
1449 //
1450 // store the frame's vertices in the same order as the base. This assumes the
1451 // triangles and vertices in this frame are in exactly the same order as in the
1452 // base
1453 //
1454 	for (i=0 ; i<num_tris ; i++)
1455 	{
1456 		vec3_t	vtemp1, vtemp2, normal;
1457 		float	ftemp;
1458 
1459 		VectorSubtract (ptri[i].verts[0], ptri[i].verts[1], vtemp1);
1460 		VectorSubtract (ptri[i].verts[2], ptri[i].verts[1], vtemp2);
1461 		CrossProduct (vtemp1, vtemp2, normal);
1462 
1463 		VectorNormalize (normal, normal);
1464 
1465 	// rotate the normal so the model faces down the positive x axis
1466 		ftemp = normal[0];
1467 		normal[0] = -normal[1];
1468 		normal[1] = ftemp;
1469 
1470 		for (j=0 ; j<3 ; j++)
1471 		{
1472 			index_xyz = triangles[i].index_xyz[j];
1473 
1474 		// rotate the vertices so the model faces down the positive x axis
1475 		// also adjust the vertices to the desired origin
1476 			ptrivert[index_xyz].v[0] = ((-ptri[i].verts[j][1]) * scale_up) +
1477 										adjust[0];
1478 			ptrivert[index_xyz].v[1] = (ptri[i].verts[j][0] * scale_up) +
1479 										adjust[1];
1480 			ptrivert[index_xyz].v[2] = (ptri[i].verts[j][2] * scale_up) +
1481 										adjust[2];
1482 
1483 			AddPointToBounds (ptrivert[index_xyz].v, fr->mins, fr->maxs);
1484 
1485 			VectorAdd (vnorms[index_xyz].normalsum, normal, vnorms[index_xyz].normalsum);
1486 			vnorms[index_xyz].numnormals++;
1487 		}
1488 	}
1489 
1490 //
1491 // calculate the vertex normals, match them to the template list, and store the
1492 // index of the best match
1493 //
1494 	for (i=0 ; i<model.num_xyz ; i++)
1495 	{
1496 		int		j;
1497 		vec3_t	v;
1498 		float	maxdot;
1499 		int		maxdotindex;
1500 		int		c;
1501 
1502 		c = vnorms[i].numnormals;
1503 		if (!c)
1504 			Error ("Vertex with no triangles attached");
1505 
1506 		VectorScale (vnorms[i].normalsum, 1.0/c, v);
1507 		VectorNormalize (v, v);
1508 
1509 		maxdot = -999999.0;
1510 		maxdotindex = -1;
1511 
1512 		for (j=0 ; j<NUMVERTEXNORMALS ; j++)
1513 		{
1514 			float	dot;
1515 
1516 			dot = DotProduct (v, avertexnormals[j]);
1517 			if (dot > maxdot)
1518 			{
1519 				maxdot = dot;
1520 				maxdotindex = j;
1521 			}
1522 		}
1523 
1524 		ptrivert[i].lightnormalindex = maxdotindex;
1525 	}
1526 
1527 	free (ptri);
1528 }
1529 
1530 /*
1531 ===============
1532 GrabJointedFrame
1533 ===============
1534 */
GrabJointedFrame(char * frame)1535 void GrabJointedFrame(char *frame)
1536 {
1537 	char	file1[1024];
1538 	char	*framefile;
1539 	frame_t		*fr;
1540 
1541 	framefile = FindFrameFile (frame);
1542 
1543 	sprintf (file1, "%s/%s", cdarchive, framefile);
1544 	ExpandPathAndArchive (file1);
1545 
1546 	sprintf (file1, "%s/%s",cddir, framefile);
1547 
1548 	printf ("grabbing %s\n", file1);
1549 
1550 	fr = &g_frames[model.num_frames - 1]; // last frame read in
1551 
1552 	LoadJointList(file1, fr->joints, jointed);
1553 }
1554 
1555 /*
1556 ===============
1557 GrabGlobals
1558 ===============
1559 */
GrabGlobals(char * frame)1560 void GrabGlobals(char *frame)
1561 {
1562 	char	file1[1024];
1563 	char	*framefile;
1564 	frame_t		*fr;
1565 
1566 	framefile = FindFrameFile (frame);
1567 
1568 	sprintf (file1, "%s/%s", cdarchive, framefile);
1569 	ExpandPathAndArchive (file1);
1570 
1571 	sprintf (file1, "%s/%s",cddir, framefile);
1572 
1573 	printf ("grabbing %s\n", file1);
1574 
1575 	fr = &g_frames[model.num_frames - 1]; // last frame read in
1576 
1577 	LoadGlobals(file1);
1578 }
1579 
1580 /*
1581 ===============
1582 Cmd_Frame
1583 ===============
1584 */
Cmd_Frame(void)1585 void Cmd_Frame (void)
1586 {
1587 	while (ScriptTokenAvailable())
1588 	{
1589 		GetScriptToken (false);
1590 		if (g_skipmodel)
1591 			continue;
1592 		if (g_release || g_archive)
1593 		{
1594 			model.num_frames = 1;	// don't skip the writeout
1595 			continue;
1596 		}
1597 
1598 		H_printf("#define FRAME_%-16s\t%i\n", token, model.num_frames);
1599 
1600 		GrabFrame (token);
1601 	}
1602 }
1603 
1604 /*
1605 ===============
1606 Cmd_Skin
1607 
1608 Skins aren't actually stored in the file, only a reference
1609 is saved out to the header file.
1610 ===============
1611 */
Cmd_Skin(void)1612 void Cmd_Skin (void)
1613 {
1614 	byte	*palette;
1615 	byte	*pixels;
1616 	int		width, height;
1617 	byte	*cropped;
1618 	int		y;
1619 	char	name[1024], savename[1024];
1620 
1621 	GetScriptToken (false);
1622 
1623 	if (model.num_skins == MAX_MD2SKINS)
1624 		Error ("model.num_skins == MAX_MD2SKINS");
1625 
1626 	if (g_skipmodel)
1627 		return;
1628 
1629 #if 1
1630 	sprintf (name, "%s/%s.pcx", cddir, token);
1631 	sprintf (savename, "%s/!%s.pcx", g_outputDir, token);
1632 	sprintf (g_skins[model.num_skins], "%s/!%s.pcx", cdpartial, token);
1633 #else
1634 	sprintf (name, "%s/%s.lbm", cdarchive, token);
1635 	strcpy (name, ExpandPathAndArchive( name ) );
1636 //	sprintf (name, "%s/%s.lbm", cddir, token);
1637 
1638 	if (ScriptTokenAvailable())
1639 	{
1640 		GetScriptToken (false);
1641 		sprintf (g_skins[model.num_skins], "%s.pcx", token);
1642 		sprintf (savename, "%s%s.pcx", g_outputDir, g_skins[model.num_skins]);
1643 	}
1644 	else
1645 	{
1646 		sprintf (savename, "%s/%s.pcx", g_outputDir, token);
1647 		sprintf (g_skins[model.num_skins], "%s/%s.pcx", cdpartial, token);
1648 	}
1649 #endif
1650 
1651 	model.num_skins++;
1652 
1653 	if (g_skipmodel || g_release || g_archive)
1654 		return;
1655 
1656 	// load the image
1657 	printf ("loading %s\n", name);
1658 	Load256Image (name, &pixels, &palette, &width, &height);
1659 //	RemapZero (pixels, palette, width, height);
1660 
1661 	// crop it to the proper size
1662 	cropped = (byte *) SafeMalloc (model.skinwidth*model.skinheight, "Cmd_Skin");
1663 	for (y=0 ; y<model.skinheight ; y++)
1664 	{
1665 		memcpy (cropped+y*model.skinwidth,
1666 			pixels+y*width, model.skinwidth);
1667 	}
1668 
1669 	// save off the new image
1670 	printf ("saving %s\n", savename);
1671 	CreatePath (savename);
1672 	WritePCXfile (savename, cropped, model.skinwidth,
1673 		model.skinheight, palette);
1674 
1675 	free (pixels);
1676 	free (palette);
1677 	free (cropped);
1678 }
1679 
1680 
1681 /*
1682 =================
1683 Cmd_Origin
1684 =================
1685 */
Cmd_Origin(void)1686 void Cmd_Origin (void)
1687 {
1688 	// rotate points into frame of reference so model points down the
1689 	// positive x axis
1690 	GetScriptToken (false);
1691 	adjust[1] = -atof (token);
1692 
1693 	GetScriptToken (false);
1694 	adjust[0] = atof (token);
1695 
1696 	GetScriptToken (false);
1697 	adjust[2] = -atof (token);
1698 }
1699 
1700 
1701 /*
1702 =================
1703 Cmd_ScaleUp
1704 =================
1705 */
Cmd_ScaleUp(void)1706 void Cmd_ScaleUp (void)
1707 {
1708 	GetScriptToken (false);
1709 	scale_up = atof (token);
1710 	if (g_skipmodel || g_release || g_archive)
1711 		return;
1712 
1713 	printf ("Scale up: %f\n", scale_up);
1714 }
1715 
1716 
1717 /*
1718 =================
1719 Cmd_Skinsize
1720 
1721 Set a skin size other than the default
1722 =================
1723 */
Cmd_Skinsize(void)1724 void Cmd_Skinsize (void)
1725 {
1726 	GetScriptToken (false);
1727 	g_fixedwidth = atoi(token);
1728 	GetScriptToken (false);
1729 	g_fixedheight = atoi(token);
1730 }
1731 
1732 /*
1733 =================
1734 Cmd_Modelname
1735 
1736 Gives a different name/location for the file, instead of the cddir
1737 =================
1738 */
Cmd_Modelname(void)1739 void Cmd_Modelname (void)
1740 {
1741 	GetScriptToken (false);
1742 	strcpy (modelname, token);
1743 }
1744 
1745 /*
1746 ===============
1747 Cmd_Cd
1748 ===============
1749 */
Cmd_Cd(void)1750 void Cmd_Cd (void)
1751 {
1752 	char temp[256];
1753 
1754 	FinishModel ();
1755 	ClearModel ();
1756 
1757 	GetScriptToken (false);
1758 
1759 	// this is a silly mess...
1760 	sprintf (cdpartial, "models/%s", token);
1761 	sprintf (cdarchive, "%smodels/%s", gamedir+strlen(qdir), token);
1762 	sprintf (cddir, "%s%s", gamedir, cdpartial);
1763 
1764 	// Since we also changed directories on the output side (for mirror) make sure the outputdir is set properly too.
1765 	sprintf(temp, "%s%s", g_outputDir, cdpartial);
1766 	strcpy(g_outputDir, temp);
1767 
1768 	// if -only was specified and this cd doesn't match,
1769 	// skip the model (you only need to match leading chars,
1770 	// so you could regrab all monsters with -only monsters)
1771 	if (!g_only[0])
1772 		return;
1773 	if (strncmp(token, g_only, strlen(g_only)))
1774 	{
1775 		g_skipmodel = true;
1776 		printf ("skipping %s\n", cdpartial);
1777 	}
1778 }
1779 
1780 /*
1781 =================
1782 Cmd_Cluster
1783 =================
1784 */
Cmd_Cluster()1785 void Cmd_Cluster()
1786 {
1787 	char file1[1024];
1788 
1789 	GetScriptToken (false);
1790 
1791 	printf ("---------------------\n");
1792 	sprintf (file1, "%s/%s", cdpartial, token);
1793 	printf ("%s\n", file1);
1794 
1795 	ExpandPathAndArchive (file1);
1796 
1797 	sprintf (file1, "%s/%s", cddir, token);
1798 
1799 	LoadClusters(file1, (int **)&clusters, (int *)&num_verts, jointed);
1800 
1801 	new_num_verts[0] = num_verts[0];
1802 
1803 	clustered = 1;
1804 }
1805 
1806 // Model construction cover functions.
MODELCMD_Modelname(int modeltype)1807 void MODELCMD_Modelname (int modeltype)
1808 {
1809 	if (g_forcemodel)
1810 		modeltype = g_forcemodel;
1811 
1812 	Cmd_Modelname ();
1813 /*
1814 	switch(modeltype)
1815 	{
1816 	case MODEL_MD2:
1817 		Cmd_Modelname ();
1818 		break;
1819 	case MODEL_FM:
1820 		Cmd_FMModelname ();
1821 		break;
1822 	}
1823 */
1824 }
1825 
MODELCMD_Cd(int modeltype)1826 void MODELCMD_Cd (int modeltype)
1827 {
1828 	if (g_forcemodel)
1829 		modeltype = g_forcemodel;
1830 
1831 	switch(modeltype)
1832 	{
1833 	case MODEL_MD2:
1834 		Cmd_Cd ();
1835 		break;
1836 	case MODEL_FM:
1837 		Cmd_FMCd ();
1838 		break;
1839 	}
1840 }
1841 
MODELCMD_Origin(int modeltype)1842 void MODELCMD_Origin (int modeltype)
1843 {
1844 	if (g_forcemodel)
1845 		modeltype = g_forcemodel;
1846 
1847 	Cmd_Origin ();
1848 /*	switch(modeltype)
1849 	{
1850 	case MODEL_MD2:
1851 		Cmd_Origin ();
1852 		break;
1853 	case MODEL_FM:
1854 		Cmd_FMOrigin ();
1855 		break;
1856 	}
1857 */
1858 }
1859 
MODELCMD_Cluster(int modeltype)1860 void MODELCMD_Cluster (int modeltype)
1861 {
1862 	if (g_forcemodel)
1863 		modeltype = g_forcemodel;
1864 
1865 	switch(modeltype)
1866 	{
1867 	case MODEL_MD2:
1868 		Cmd_Cluster ();
1869 		break;
1870 	case MODEL_FM:
1871 		Cmd_FMCluster ();
1872 		break;
1873 	}
1874 }
1875 
MODELCMD_Base(int modeltype)1876 void MODELCMD_Base (int modeltype)
1877 {
1878 	if (g_forcemodel)
1879 		modeltype = g_forcemodel;
1880 
1881 	switch(modeltype)
1882 	{
1883 	case MODEL_MD2:
1884 		Cmd_Base ();
1885 		break;
1886 	case MODEL_FM:
1887 		Cmd_FMBase (false);
1888 		break;
1889 	}
1890 }
1891 
MODELCMD_BaseST(int modeltype)1892 void MODELCMD_BaseST (int modeltype)
1893 {
1894 	if (g_forcemodel)
1895 		modeltype = g_forcemodel;
1896 
1897 	switch(modeltype)
1898 	{
1899 	case MODEL_MD2:
1900 		Cmd_Base ();
1901 		break;
1902 	case MODEL_FM:
1903 		Cmd_FMBase (true);
1904 		break;
1905 	}
1906 }
1907 
MODELCMD_ScaleUp(int modeltype)1908 void MODELCMD_ScaleUp (int modeltype)
1909 {
1910 	if (g_forcemodel)
1911 		modeltype = g_forcemodel;
1912 
1913 	Cmd_ScaleUp ();
1914 /*	switch(modeltype)
1915 	{
1916 	case MODEL_MD2:
1917 		Cmd_ScaleUp ();
1918 		break;
1919 	case MODEL_FM:
1920 		Cmd_FMScaleUp ();
1921 		break;
1922 	}
1923 */
1924 }
1925 
MODELCMD_Frame(int modeltype)1926 void MODELCMD_Frame (int modeltype)
1927 {
1928 	if (g_forcemodel)
1929 		modeltype = g_forcemodel;
1930 
1931 	switch(modeltype)
1932 	{
1933 	case MODEL_MD2:
1934 		Cmd_Frame ();
1935 		break;
1936 	case MODEL_FM:
1937 		Cmd_FMFrame ();
1938 		break;
1939 	}
1940 }
1941 
MODELCMD_Skin(int modeltype)1942 void MODELCMD_Skin (int modeltype)
1943 {
1944 	if (g_forcemodel)
1945 		modeltype = g_forcemodel;
1946 
1947 	switch(modeltype)
1948 	{
1949 	case MODEL_MD2:
1950 		Cmd_Skin ();
1951 		break;
1952 	case MODEL_FM:
1953 		Cmd_FMSkin ();
1954 		break;
1955 	}
1956 }
1957 
MODELCMD_Skinsize(int modeltype)1958 void MODELCMD_Skinsize (int modeltype)
1959 {
1960 	if (g_forcemodel)
1961 		modeltype = g_forcemodel;
1962 
1963 	Cmd_Skinsize ();
1964 /*
1965 	switch(modeltype)
1966 	{
1967 	case MODEL_MD2:
1968 		Cmd_Skinsize ();
1969 		break;
1970 	case MODEL_FM:
1971 		Cmd_FMSkinsize ();
1972 		break;
1973 	}
1974 */
1975 }
1976 
MODELCMD_Skeleton(int modeltype)1977 void MODELCMD_Skeleton (int modeltype)
1978 {
1979 	if (g_forcemodel)
1980 		modeltype = g_forcemodel;
1981 
1982 	switch(modeltype)
1983 	{
1984 	case MODEL_MD2:
1985 		break;
1986 	case MODEL_FM:
1987 		Cmd_FMSkeleton ();
1988 		break;
1989 	}
1990 }
1991 
MODELCMD_BeginGroup(int modeltype)1992 void MODELCMD_BeginGroup(int modeltype)
1993 {
1994 	if (g_forcemodel)
1995 		modeltype = g_forcemodel;
1996 
1997 	switch(modeltype)
1998 	{
1999 	case MODEL_MD2:
2000 		break;
2001 	case MODEL_FM:
2002 		Cmd_FMBeginGroup();
2003 		break;
2004 	}
2005 }
2006 
MODELCMD_EndGroup(int modeltype)2007 void MODELCMD_EndGroup(int modeltype)
2008 {
2009 	if (g_forcemodel)
2010 		modeltype = g_forcemodel;
2011 
2012 	switch(modeltype)
2013 	{
2014 	case MODEL_MD2:
2015 		break;
2016 	case MODEL_FM:
2017 		Cmd_FMEndGroup();
2018 		break;
2019 	}
2020 }
2021 
MODELCMD_Referenced(int modeltype)2022 void MODELCMD_Referenced(int modeltype)
2023 {
2024 	if (g_forcemodel)
2025 		modeltype = g_forcemodel;
2026 
2027 	switch(modeltype)
2028 	{
2029 	case MODEL_MD2:
2030 		break;
2031 	case MODEL_FM:
2032 		Cmd_FMReferenced();
2033 		break;
2034 	}
2035 }
2036 
MODELCMD_NodeOrder(int modeltype)2037 void MODELCMD_NodeOrder(int modeltype)
2038 {
2039 	if (g_forcemodel)
2040 		modeltype = g_forcemodel;
2041 
2042 	switch(modeltype)
2043 	{
2044 	case MODEL_MD2:
2045 		break;
2046 	case MODEL_FM:
2047 		Cmd_FMNodeOrder();
2048 		break;
2049 	}
2050 }
2051