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, ¤t->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