2 Copyright (C) 1999-2006 Id Software, Inc. and contributors.
3 For a list of contributors, see the accompanying CONTRIBUTORS file.
5 This file is part of GtkRadiant.
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.
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.
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
28 //=================================================================
46 trivert_t v[MAX_VERTS];
47 QDataJoint_t joints[NUM_CLUSTERS]; // ,this
50 // ,and all of this should get out of here, need to use new stuff in fmodels instead
52 typedef struct IntListNode_s
55 struct IntListNode_s *next;
56 } IntListNode_t; // gaak
60 float scale[3]; // multiply byte verts by this
61 float translate[3]; // then add this
62 } PartialAliasFrame_t;
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];
74 //================================================================
76 frame_t g_frames[MAX_FRAMES];
82 float scale_up; // set by $scale
83 vec3_t adjust; // set by $origin
84 int g_fixedwidth, g_fixedheight; // set by $skinsize
90 dstvert_t base_st[MAX_VERTS];
91 dtriangle_t triangles[MAX_TRIANGLES];
93 static int triangle_st[MAX_TRIANGLES][3][2];
95 // the command list holds counts, s/t values, and xyz indexes
96 // that are valid for every frame
100 int used[MAX_TRIANGLES];
102 char g_skins[MAX_MD2SKINS][64];
104 char cdarchive[1024];
105 char cdpartial[1024];
108 char modelname[64]; // empty unless $modelname issued (players)
110 extern char *g_outputDir;
112 #define NUMVERTEXNORMALS 162
114 float avertexnormals[NUMVERTEXNORMALS][3] =
119 unsigned char pic[SKINPAGE_HEIGHT * SKINPAGE_WIDTH], pic_palette[768];
121 FILE *headerouthandle = NULL;
123 //==============================================================
130 static void ClearModel( void ){
131 memset( &model, 0, sizeof( model ) );
134 jointed = NOT_JOINTED;
137 VectorCopy( vec3_origin, adjust );
138 g_fixedwidth = g_fixedheight = 0;
143 void H_printf( char *fmt, ... ){
147 if ( !headerouthandle ) {
148 sprintf( name, "%s/tris.h", cddir );
149 headerouthandle = SafeOpenWrite( name );
150 fprintf( headerouthandle, "// %s\n\n", cddir );
151 fprintf( headerouthandle, "// This file generated by qdata - Do NOT Modify\n\n" );
154 va_start( argptr, fmt );
155 vfprintf( headerouthandle, fmt, argptr );
165 void WriteCommonModelFile( FILE *modelouthandle, PartialAliasFrame_t *outFrames ){
171 byte buffer[MAX_VERTS * 4 + 128];
175 model.version = ALIAS_VERSION;
176 model.framesize = (int)&( (daliasframe_t *)0 )->verts[model.num_xyz];
177 model.num_glcmds = numcommands;
178 model.ofs_skins = sizeof( dmdl_t );
179 model.ofs_st = model.ofs_skins + model.num_skins * MAX_SKINNAME;
180 model.ofs_tris = model.ofs_st + model.num_st * sizeof( dstvert_t );
181 model.ofs_frames = model.ofs_tris + model.num_tris * sizeof( dtriangle_t );
182 model.ofs_glcmds = model.ofs_frames + model.num_frames * model.framesize;
183 model.ofs_end = model.ofs_glcmds + model.num_glcmds * sizeof( int );
185 // write out the model header
187 for ( i = 0 ; i < sizeof( dmdl_t ) / 4 ; i++ )
188 ( (int *)&modeltemp )[i] = LittleLong( ( (int *)&model )[i] );
190 SafeWrite( modelouthandle, &modeltemp, sizeof( modeltemp ) );
193 // write out the skin names
195 SafeWrite( modelouthandle, g_skins, model.num_skins * MAX_SKINNAME );
198 // write out the texture coordinates
201 for ( i = 0 ; i < model.num_st ; i++ )
203 base_st[i].s = LittleShort( base_st[i].s );
204 base_st[i].t = LittleShort( base_st[i].t );
207 SafeWrite( modelouthandle, base_st, model.num_st * sizeof( base_st[0] ) );
210 // write out the triangles
212 for ( i = 0 ; i < model.num_tris ; i++ )
217 for ( j = 0 ; j < 3 ; j++ )
219 tri.index_xyz[j] = LittleShort( triangles[i].index_xyz[j] );
220 tri.index_st[j] = LittleShort( triangles[i].index_st[j] );
223 SafeWrite( modelouthandle, &tri, sizeof( tri ) );
227 // write out the frames
229 for ( i = 0 ; i < model.num_frames ; i++ )
232 out = (daliasframe_t *)buffer;
234 strcpy( out->name, in->name );
235 for ( j = 0 ; j < 3 ; j++ )
237 out->scale[j] = ( in->maxs[j] - in->mins[j] ) / 255;
238 out->translate[j] = in->mins[j];
241 outFrames[i].scale[j] = out->scale[j];
242 outFrames[i].translate[j] = out->translate[j];
246 for ( j = 0 ; j < model.num_xyz ; j++ )
248 // all of these are byte values, so no need to deal with endianness
249 out->verts[j].lightnormalindex = in->v[j].lightnormalindex;
251 for ( k = 0 ; k < 3 ; k++ )
253 // scale to byte values & min/max check
254 v = Q_rint( ( in->v[j].v[k] - out->translate[k] ) / out->scale[k] );
256 // clamp, so rounding doesn't wrap from 255.6 to 0
263 out->verts[j].v[k] = v;
267 for ( j = 0 ; j < 3 ; j++ )
269 out->scale[j] = LittleFloat( out->scale[j] );
270 out->translate[j] = LittleFloat( out->translate[j] );
273 SafeWrite( modelouthandle, out, model.framesize );
279 SafeWrite( modelouthandle, commands, numcommands * 4 );
287 void WriteModelFile( FILE *modelouthandle ){
288 model.ident = IDALIASHEADER;
290 WriteCommonModelFile( modelouthandle, NULL );
295 WriteJointedModelFile
298 void WriteJointedModelFile( FILE *modelouthandle ){
303 IntListNode_t *current, *toFree;
304 PartialAliasFrame_t outFrames[MAX_FRAMES];
306 model.ident = IDJOINTEDALIASHEADER;
308 WriteCommonModelFile( modelouthandle, outFrames );
311 SafeWrite( modelouthandle, &jointed, sizeof( int ) );
314 SafeWrite( modelouthandle, &numJointsForSkeleton[jointed], sizeof( int ) );
316 // number of verts in each cluster
317 SafeWrite( modelouthandle, &new_num_verts[1], sizeof( int ) * numJointsForSkeleton[jointed] );
320 for ( i = 0; i < new_num_verts[0]; ++i )
322 current = vertLists[i];
325 SafeWrite( modelouthandle, ¤t->data, sizeof( int ) );
327 current = current->next;
328 free( toFree ); // freeing of memory allocated in ReplaceClusterIndex called in Cmd_Base
332 for ( i = 0 ; i < model.num_frames ; i++ )
336 for ( j = 0 ; j < new_num_verts[0]; ++j )
338 for ( k = 0 ; k < 3 ; k++ )
340 // scale to byte values & min/max check
341 v = Q_rint( ( in->joints[j].placement.origin[k] - outFrames[i].translate[k] ) / outFrames[i].scale[k] );
343 // clamp, so rounding doesn't wrap from 255.6 to 0
352 // write out origin as a float (there's only a few per model, so it's not really
354 SafeWrite( modelouthandle, &v, sizeof( float ) );
357 for ( k = 0 ; k < 3 ; k++ )
359 v = Q_rint( ( in->joints[j].placement.direction[k] - outFrames[i].translate[k] ) / outFrames[i].scale[k] );
361 // clamp, so rounding doesn't wrap from 255.6 to 0
370 // write out origin as a float (there's only a few per model, so it's not really
372 SafeWrite( modelouthandle, &v, sizeof( float ) );
375 for ( k = 0 ; k < 3 ; k++ )
377 v = Q_rint( ( in->joints[j].placement.up[k] - outFrames[i].translate[k] ) / outFrames[i].scale[k] );
379 // clamp, so rounding doesn't wrap from 255.6 to 0
388 // write out origin as a float (there's only a few per model, so it's not really
390 SafeWrite( modelouthandle, &v, sizeof( float ) );
401 static void WriteModelFile( FILE *modelouthandle ){
407 byte buffer[MAX_VERTS * 4 + 128];
411 model.ident = IDALIASHEADER;
412 model.version = ALIAS_VERSION;
413 model.framesize = (int)&( (daliasframe_t *)0 )->verts[model.num_xyz];
414 model.num_glcmds = numcommands;
415 model.ofs_skins = sizeof( dmdl_t );
416 model.ofs_st = model.ofs_skins + model.num_skins * MAX_SKINNAME;
417 model.ofs_tris = model.ofs_st + model.num_st * sizeof( dstvert_t );
418 model.ofs_frames = model.ofs_tris + model.num_tris * sizeof( dtriangle_t );
419 model.ofs_glcmds = model.ofs_frames + model.num_frames * model.framesize;
420 model.ofs_end = model.ofs_glcmds + model.num_glcmds * 4;
423 // write out the model header
425 for ( i = 0 ; i < sizeof( dmdl_t ) / 4 ; i++ )
426 ( (int *)&modeltemp )[i] = LittleLong( ( (int *)&model )[i] );
428 SafeWrite( modelouthandle, &modeltemp, sizeof( modeltemp ) );
431 // write out the skin names
433 SafeWrite( modelouthandle, g_skins, model.num_skins * MAX_SKINNAME );
436 // write out the texture coordinates
439 for ( i = 0 ; i < model.num_st ; i++ )
441 base_st[i].s = LittleShort( base_st[i].s );
442 base_st[i].t = LittleShort( base_st[i].t );
445 SafeWrite( modelouthandle, base_st, model.num_st * sizeof( base_st[0] ) );
448 // write out the triangles
450 for ( i = 0 ; i < model.num_tris ; i++ )
455 for ( j = 0 ; j < 3 ; j++ )
457 tri.index_xyz[j] = LittleShort( triangles[i].index_xyz[j] );
458 tri.index_st[j] = LittleShort( triangles[i].index_st[j] );
461 SafeWrite( modelouthandle, &tri, sizeof( tri ) );
465 // write out the frames
467 for ( i = 0 ; i < model.num_frames ; i++ )
470 out = (daliasframe_t *)buffer;
472 strcpy( out->name, in->name );
473 for ( j = 0 ; j < 3 ; j++ )
475 out->scale[j] = ( in->maxs[j] - in->mins[j] ) / 255;
476 out->translate[j] = in->mins[j];
479 for ( j = 0 ; j < model.num_xyz ; j++ )
481 // all of these are byte values, so no need to deal with endianness
482 out->verts[j].lightnormalindex = in->v[j].lightnormalindex;
484 for ( k = 0 ; k < 3 ; k++ )
486 // scale to byte values & min/max check
487 v = Q_rint( ( in->v[j].v[k] - out->translate[k] ) / out->scale[k] );
489 // clamp, so rounding doesn't wrap from 255.6 to 0
496 out->verts[j].v[k] = v;
500 for ( j = 0 ; j < 3 ; j++ )
502 out->scale[j] = LittleFloat( out->scale[j] );
503 out->translate[j] = LittleFloat( out->translate[j] );
506 SafeWrite( modelouthandle, out, model.framesize );
512 SafeWrite( modelouthandle, commands, numcommands * 4 );
521 void FinishModel( void ){
522 FILE *modelouthandle;
526 if ( !model.num_frames ) {
531 // copy to release directory tree if doing a release build
534 if ( modelname[0] ) {
535 sprintf( name, "%s", modelname );
538 sprintf( name, "%s/tris.md2", cdpartial );
542 for ( i = 0 ; i < model.num_skins ; i++ )
544 ReleaseFile( g_skins[i] );
546 model.num_frames = 0;
551 // write the model output file
553 if ( modelname[0] ) {
554 sprintf( name, "%s%s", g_outputDir, modelname );
557 sprintf( name, "%s/tris.md2", g_outputDir );
559 printf( "saving to %s\n", name );
561 modelouthandle = SafeOpenWrite( name );
564 if ( jointed != NOT_JOINTED ) {
565 WriteJointedModelFile( modelouthandle );
569 WriteModelFile( modelouthandle );
571 printf( "%3dx%3d skin\n", model.skinwidth, model.skinheight );
572 printf( "First frame boundaries:\n" );
573 printf( " minimum x: %3f\n", g_frames[0].mins[0] );
574 printf( " maximum x: %3f\n", g_frames[0].maxs[0] );
575 printf( " minimum y: %3f\n", g_frames[0].mins[1] );
576 printf( " maximum y: %3f\n", g_frames[0].maxs[1] );
577 printf( " minimum z: %3f\n", g_frames[0].mins[2] );
578 printf( " maximum z: %3f\n", g_frames[0].maxs[2] );
579 printf( "%4d vertices\n", model.num_xyz );
580 printf( "%4d triangles\n", model.num_tris );
581 printf( "%4d frame\n", model.num_frames );
582 printf( "%4d glverts\n", numglverts );
583 printf( "%4d glcmd\n", model.num_glcmds );
584 printf( "%4d skins\n", model.num_skins );
585 printf( "file size: %d\n", (int)ftell( modelouthandle ) );
586 printf( "---------------------\n" );
588 fclose( modelouthandle );
590 // finish writing header file
593 // scale_up is usefull to allow step distances to be adjusted
594 H_printf( "#define MODEL_SCALE\t\t%f\n", scale_up );
596 fclose( headerouthandle );
597 headerouthandle = NULL;
602 =================================================================
604 ALIAS MODEL DISPLAY LIST GENERATION
606 =================================================================
619 static int StripLength( int starttri, int startv ){
623 dtriangle_t *last, *check;
628 last = &triangles[starttri];
630 strip_xyz[0] = last->index_xyz[( startv ) % 3];
631 strip_xyz[1] = last->index_xyz[( startv + 1 ) % 3];
632 strip_xyz[2] = last->index_xyz[( startv + 2 ) % 3];
633 strip_st[0] = last->index_st[( startv ) % 3];
634 strip_st[1] = last->index_st[( startv + 1 ) % 3];
635 strip_st[2] = last->index_st[( startv + 2 ) % 3];
637 strip_tris[0] = starttri;
640 m1 = last->index_xyz[( startv + 2 ) % 3];
641 st1 = last->index_st[( startv + 2 ) % 3];
642 m2 = last->index_xyz[( startv + 1 ) % 3];
643 st2 = last->index_st[( startv + 1 ) % 3];
645 // look for a matching triangle
647 for ( j = starttri + 1, check = &triangles[starttri + 1]
648 ; j < model.num_tris ; j++, check++ )
650 for ( k = 0 ; k < 3 ; k++ )
652 if ( check->index_xyz[k] != m1 ) {
655 if ( check->index_st[k] != st1 ) {
658 if ( check->index_xyz[ ( k + 1 ) % 3 ] != m2 ) {
661 if ( check->index_st[ ( k + 1 ) % 3 ] != st2 ) {
665 // this is the next part of the fan
667 // if we can't use this triangle, this tristrip is done
673 if ( stripcount & 1 ) {
674 m2 = check->index_xyz[ ( k + 2 ) % 3 ];
675 st2 = check->index_st[ ( k + 2 ) % 3 ];
679 m1 = check->index_xyz[ ( k + 2 ) % 3 ];
680 st1 = check->index_st[ ( k + 2 ) % 3 ];
683 strip_xyz[stripcount + 2] = check->index_xyz[ ( k + 2 ) % 3 ];
684 strip_st[stripcount + 2] = check->index_st[ ( k + 2 ) % 3 ];
685 strip_tris[stripcount] = j;
694 // clear the temp used flags
695 for ( j = starttri + 1 ; j < model.num_tris ; j++ )
696 if ( used[j] == 2 ) {
709 static int FanLength( int starttri, int startv ){
713 dtriangle_t *last, *check;
718 last = &triangles[starttri];
720 strip_xyz[0] = last->index_xyz[( startv ) % 3];
721 strip_xyz[1] = last->index_xyz[( startv + 1 ) % 3];
722 strip_xyz[2] = last->index_xyz[( startv + 2 ) % 3];
723 strip_st[0] = last->index_st[( startv ) % 3];
724 strip_st[1] = last->index_st[( startv + 1 ) % 3];
725 strip_st[2] = last->index_st[( startv + 2 ) % 3];
727 strip_tris[0] = starttri;
730 m1 = last->index_xyz[( startv + 0 ) % 3];
731 st1 = last->index_st[( startv + 0 ) % 3];
732 m2 = last->index_xyz[( startv + 2 ) % 3];
733 st2 = last->index_st[( startv + 2 ) % 3];
736 // look for a matching triangle
738 for ( j = starttri + 1, check = &triangles[starttri + 1]
739 ; j < model.num_tris ; j++, check++ )
741 for ( k = 0 ; k < 3 ; k++ )
743 if ( check->index_xyz[k] != m1 ) {
746 if ( check->index_st[k] != st1 ) {
749 if ( check->index_xyz[ ( k + 1 ) % 3 ] != m2 ) {
752 if ( check->index_st[ ( k + 1 ) % 3 ] != st2 ) {
756 // this is the next part of the fan
758 // if we can't use this triangle, this tristrip is done
764 m2 = check->index_xyz[ ( k + 2 ) % 3 ];
765 st2 = check->index_st[ ( k + 2 ) % 3 ];
767 strip_xyz[stripcount + 2] = m2;
768 strip_st[stripcount + 2] = st2;
769 strip_tris[stripcount] = j;
778 // clear the temp used flags
779 for ( j = starttri + 1 ; j < model.num_tris ; j++ )
780 if ( used[j] == 2 ) {
793 Generate a list of trifans or strips
794 for the model, which holds for all frames
797 static void BuildGlCmds( void ){
801 int len, bestlen, besttype;
812 memset( used, 0, sizeof( used ) );
813 for ( i = 0 ; i < model.num_tris ; i++ )
815 // pick an unused triangle and start the trifan
821 for ( type = 0 ; type < 2 ; type++ )
824 for ( startv = 0 ; startv < 3 ; startv++ )
827 len = StripLength( i, startv );
830 len = FanLength( i, startv );
832 if ( len > bestlen ) {
835 for ( j = 0 ; j < bestlen + 2 ; j++ )
837 best_st[j] = strip_st[j];
838 best_xyz[j] = strip_xyz[j];
840 for ( j = 0 ; j < bestlen ; j++ )
841 best_tris[j] = strip_tris[j];
846 // mark the tris on the best strip/fan as used
847 for ( j = 0 ; j < bestlen ; j++ )
848 used[best_tris[j]] = 1;
850 if ( besttype == 1 ) {
851 commands[numcommands++] = ( bestlen + 2 );
854 commands[numcommands++] = -( bestlen + 2 );
857 numglverts += bestlen + 2;
859 for ( j = 0 ; j < bestlen + 2 ; j++ )
861 // emit a vertex into the reorder buffer
864 // emit s/t coords into the commands stream
868 s = ( s + 0.5 ) / model.skinwidth;
869 t = ( t + 0.5 ) / model.skinheight;
871 *(float *)&commands[numcommands++] = s;
872 *(float *)&commands[numcommands++] = t;
873 *(int *)&commands[numcommands++] = best_xyz[j];
877 commands[numcommands++] = 0; // end of list marker
882 ===============================================================
886 ===============================================================
893 Builds the triangle_st array for the base frame and
894 model.skinwidth / model.skinheight
896 FIXME: allow this to be loaded from a file for
901 static void OldBuildST( triangle_t *ptri, int numtri ){
903 int width, height, iwidth, iheight, swidth;
905 float s_scale, t_scale;
909 vec3_t vtemp1, vtemp2, normal;
912 // find bounds of all the verts on the base frame
914 ClearBounds( mins, maxs );
916 for ( i = 0 ; i < numtri ; i++ )
917 for ( j = 0 ; j < 3 ; j++ )
918 AddPointToBounds( ptri[i].verts[j], mins, maxs );
920 for ( i = 0 ; i < 3 ; i++ )
922 mins[i] = floor( mins[i] );
923 maxs[i] = ceil( maxs[i] );
926 width = maxs[0] - mins[0];
927 height = maxs[2] - mins[2];
929 if ( !g_fixedwidth ) { // old style
931 if ( width * scale >= 150 ) {
932 scale = 150.0 / width;
934 if ( height * scale >= 190 ) {
935 scale = 190.0 / height;
938 s_scale = t_scale = scale;
940 iwidth = ceil( width * s_scale );
941 iheight = ceil( height * t_scale );
948 iwidth = g_fixedwidth / 2;
949 iheight = g_fixedheight;
951 s_scale = (float)( iwidth - 4 ) / width;
952 t_scale = (float)( iheight - 4 ) / height;
956 // determine which side of each triangle to map the texture to
958 for ( i = 0 ; i < numtri ; i++ )
960 VectorSubtract( ptri[i].verts[0], ptri[i].verts[1], vtemp1 );
961 VectorSubtract( ptri[i].verts[2], ptri[i].verts[1], vtemp2 );
962 CrossProduct( vtemp1, vtemp2, normal );
964 if ( normal[1] > 0 ) {
973 for ( j = 0 ; j < 3 ; j++ )
975 pbasevert = ptri[i].verts[j];
977 triangle_st[i][j][0] = Q_rint( ( pbasevert[0] - mins[0] ) * s_scale + basex );
978 triangle_st[i][j][1] = Q_rint( ( maxs[2] - pbasevert[2] ) * t_scale + basey );
982 // make the width a multiple of 4; some hardware requires this, and it ensures
983 // dword alignment for each scan
985 model.skinwidth = ( swidth + 3 ) & ~3;
986 model.skinheight = iheight;
990 //==========================================================================
994 //==========================================================================
996 void DrawScreen( float s_scale, float t_scale, float iwidth, float iheight ){
1002 scrpos = &pic[( INFO_Y - 2 ) * SKINPAGE_WIDTH];
1003 for ( i = 0; i < SKINPAGE_WIDTH; i++ )
1008 sprintf( buffer, "GENSKIN: " );
1009 DrawTextChar( 16, INFO_Y, buffer );
1011 sprintf( buffer, "( %03d * %03d ) SCALE %f %f, SKINWIDTH %d,"
1012 " SKINHEIGHT %d", (int)ScaleWidth, (int)ScaleHeight, s_scale, t_scale, (int)iwidth * 2, (int)iheight );
1013 DrawTextChar( 80, INFO_Y, buffer );
1020 Builds the triangle_st array for the base frame and
1021 model.skinwidth / model.skinheight
1023 FIXME: allow this to be loaded from a file for
1027 void BuildST( triangle_t *ptri, int numtri, qboolean DrawSkin ){
1029 int width, height, iwidth, iheight, swidth;
1034 vec3_t vtemp1, vtemp2, normal;
1035 float s_scale, t_scale;
1040 // find bounds of all the verts on the base frame
1042 ClearBounds( mins, maxs );
1044 for ( i = 0 ; i < numtri ; i++ )
1045 for ( j = 0 ; j < 3 ; j++ )
1046 AddPointToBounds( ptri[i].verts[j], mins, maxs );
1048 for ( i = 0 ; i < 3 ; i++ )
1050 mins[i] = floor( mins[i] );
1051 maxs[i] = ceil( maxs[i] );
1054 width = maxs[0] - mins[0];
1055 height = maxs[2] - mins[2];
1058 scWidth = ( ScaleWidth / 2 ) * SCALE_ADJUST_FACTOR;
1059 scHeight = ScaleHeight * SCALE_ADJUST_FACTOR;
1061 scale = scWidth / width;
1063 if ( height * scale >= scHeight ) {
1064 scale = scHeight / height;
1067 iwidth = ceil( width * scale ) + 4;
1068 iheight = ceil( height * scale ) + 4;
1070 s_scale = (float)( iwidth - 4 ) / width;
1071 t_scale = (float)( iheight - 4 ) / height;
1075 DrawScreen( s_scale, t_scale, iwidth, iheight );
1079 /* if (!g_fixedwidth)
1082 if (width*scale >= 150)
1083 scale = 150.0 / width;
1084 if (height*scale >= 190)
1085 scale = 190.0 / height;
1087 s_scale = t_scale = scale;
1089 iwidth = ceil(width*s_scale);
1090 iheight = ceil(height*t_scale);
1097 iwidth = g_fixedwidth / 2;
1098 iheight = g_fixedheight;
1100 s_scale = (float)(iwidth-4) / width;
1101 t_scale = (float)(iheight-4) / height;
1105 // determine which side of each triangle to map the texture to
1107 for ( i = 0 ; i < numtri ; i++ )
1109 if ( ptri[i].HasUV ) {
1110 for ( j = 0 ; j < 3 ; j++ )
1112 triangle_st[i][j][0] = Q_rint( ptri[i].uv[j][0] * iwidth );
1113 triangle_st[i][j][1] = Q_rint( ( 1.0f - ptri[i].uv[j][1] ) * iheight );
1118 VectorSubtract( ptri[i].verts[0], ptri[i].verts[1], vtemp1 );
1119 VectorSubtract( ptri[i].verts[2], ptri[i].verts[1], vtemp2 );
1120 CrossProduct( vtemp1, vtemp2, normal );
1122 if ( normal[1] > 0 ) {
1131 for ( j = 0 ; j < 3 ; j++ )
1133 pbasevert = ptri[i].verts[j];
1135 triangle_st[i][j][0] = Q_rint( ( pbasevert[0] - mins[0] ) * s_scale + basex );
1136 triangle_st[i][j][1] = Q_rint( ( maxs[2] - pbasevert[2] ) * t_scale + basey );
1140 DrawLine( triangle_st[i][0][0], triangle_st[i][0][1],
1141 triangle_st[i][1][0], triangle_st[i][1][1] );
1142 DrawLine( triangle_st[i][1][0], triangle_st[i][1][1],
1143 triangle_st[i][2][0], triangle_st[i][2][1] );
1144 DrawLine( triangle_st[i][2][0], triangle_st[i][2][1],
1145 triangle_st[i][0][0], triangle_st[i][0][1] );
1148 // make the width a multiple of 4; some hardware requires this, and it ensures
1149 // dword alignment for each scan
1151 swidth = iwidth * 2;
1152 model.skinwidth = ( swidth + 3 ) & ~3;
1153 model.skinheight = iheight;
1157 static void ReplaceClusterIndex( int newIndex, int oldindex, int **clusters,
1158 IntListNode_t **vertLists, int *num_verts, int *new_num_verts ){
1160 IntListNode_t *next;
1162 for ( j = 0; j < num_verts[0]; ++j )
1164 for ( i = 0; i < num_verts[j + 1]; ++i )
1166 if ( clusters[j][i] == oldindex ) {
1167 ++new_num_verts[j + 1];
1169 next = vertLists[j];
1171 vertLists[j] = (IntListNode_t *) SafeMalloc( sizeof( IntListNode_t ), "ReplaceClusterIndex" );
1172 // Currently freed in WriteJointedModelFile only
1174 vertLists[j]->data = newIndex;
1175 vertLists[j]->next = next;
1186 void Cmd_Base( void ){
1187 vec3_t base_xyz[MAX_VERTS];
1197 GetScriptToken( false );
1199 if ( g_skipmodel || g_release || g_archive ) {
1203 printf( "---------------------\n" );
1205 sprintf( file1, "%s/%s", cdpartial, token );
1206 printf( "%s ", file1 );
1208 ExpandPathAndArchive( file1 );
1210 sprintf( file1, "%s/%s", cddir, token );
1212 sprintf( file1, "%s/%s.%s", cdarchive, token, trifileext );
1213 printf( "%s\n", file1 );
1215 ExpandPathAndArchive( file1 );
1217 sprintf( file1, "%s/%s.%s", cddir, token, trifileext );
1219 time1 = FileTime( file1 );
1220 if ( time1 == -1 ) {
1221 Error( "%s doesn't exist", file1 );
1225 // load the base triangles
1228 Load3DSTriangleList( file1, &ptri, &model.num_tris, NULL, NULL );
1231 LoadTriangleList( file1, &ptri, &model.num_tris, NULL, NULL );
1235 GetScriptToken( false );
1236 sprintf( file2, "%s/%s.pcx", cddir, token );
1237 // sprintf (trans_file, "%s/!%s_a.pcx", cddir, token);
1239 printf( "skin: %s\n", file2 );
1240 Load256Image( file2, &BasePixels, &BasePalette, &BaseWidth, &BaseHeight );
1242 if ( BaseWidth != SKINPAGE_WIDTH || BaseHeight != SKINPAGE_HEIGHT ) {
1243 if ( g_allow_newskin ) {
1244 ScaleWidth = BaseWidth;
1245 ScaleHeight = BaseHeight;
1249 Error( "Invalid skin page size: (%d,%d) should be (%d,%d)",
1250 BaseWidth,BaseHeight,SKINPAGE_WIDTH,SKINPAGE_HEIGHT );
1255 ScaleWidth = (float)ExtractNumber( BasePixels, ENCODED_WIDTH_X,
1257 ScaleHeight = (float)ExtractNumber( BasePixels, ENCODED_HEIGHT_X,
1262 // get the ST values
1264 BuildST( ptri, model.num_tris,false );
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
1271 for ( i = 0 ; i < model.num_tris ; i++ )
1273 for ( j = 0 ; j < 3 ; j++ )
1275 // get the xyz index
1276 for ( k = 0 ; k < model.num_xyz ; k++ )
1277 if ( VectorCompare( ptri[i].verts[j], base_xyz[k] ) ) {
1279 } // this vertex is already in the base vertex list
1281 if ( k == model.num_xyz ) { // new index
1282 VectorCopy( ptri[i].verts[j], base_xyz[model.num_xyz] );
1285 ReplaceClusterIndex( k, ptri[i].indicies[j], (int **)&clusters, (IntListNode_t **)&vertLists, (int *)&num_verts, (int *)&new_num_verts );
1291 triangles[i].index_xyz[j] = k;
1294 for ( k = 0 ; k < model.num_st ; k++ )
1295 if ( triangle_st[i][j][0] == base_st[k].s
1296 && triangle_st[i][j][1] == base_st[k].t ) {
1298 } // this vertex is already in the base vertex list
1300 if ( k == model.num_st ) { // new index
1301 base_st[model.num_st].s = triangle_st[i][j][0];
1302 base_st[model.num_st].t = triangle_st[i][j][1];
1306 triangles[i].index_st[j] = k;
1310 // build triangle strips / fans
1314 //===============================================================
1316 char *FindFrameFile( char *frame ){
1319 static char retname[1024];
1324 if ( strstr( frame, "." ) ) {
1325 return frame; // allready in dot format
1328 // split 'run1' into 'run' and '1'
1329 s = frame + strlen( frame ) - 1;
1331 while ( s != frame && *s >= '0' && *s <= '9' )
1334 strcpy( suffix, s + 1 );
1335 strcpy( base, frame );
1336 base[s - frame + 1] = 0;
1338 sprintf( file1, "%s/%s%s.%s",cddir, base, suffix, "hrc" );
1339 time1 = FileTime( file1 );
1340 if ( time1 != -1 ) {
1341 sprintf( retname, "%s%s.%s", base, suffix, "hrc" );
1345 sprintf( file1, "%s/%s%s.%s",cddir, base, suffix, "asc" );
1346 time1 = FileTime( file1 );
1347 if ( time1 != -1 ) {
1348 sprintf( retname, "%s%s.%s", base, suffix, "asc" );
1352 sprintf( file1, "%s/%s%s.%s",cddir, base, suffix, "tri" );
1353 time1 = FileTime( file1 );
1354 if ( time1 != -1 ) {
1355 sprintf( retname, "%s%s.%s", base, suffix, "tri" );
1359 sprintf( file1, "%s/%s%s.%s",cddir, base, suffix, "3ds" );
1360 time1 = FileTime( file1 );
1361 if ( time1 != -1 ) {
1362 sprintf( retname, "%s%s.%s", base, suffix, "3ds" );
1366 sprintf( file1, "%s/%s%s.%s",cddir, base, suffix, "htr" );
1367 time1 = FileTime( file1 );
1368 if ( time1 != -1 ) {
1369 sprintf( retname, "%s%s.%s", base, suffix, "htr" );
1373 // check for 'run.1'
1374 sprintf( file1, "%s/%s.%s",cddir, base, suffix );
1375 time1 = FileTime( file1 );
1376 if ( time1 != -1 ) {
1377 sprintf( retname, "%s.%s", base, suffix );
1381 Error( "frame %s could not be found",frame );
1390 static void GrabFrame( char *frame ){
1393 trivert_t *ptrivert;
1397 vertexnormals_t vnorms[MAX_VERTS];
1401 // the frame 'run1' will be looked for as either
1402 // run.1 or run1.tri, so the new alias sequence save
1403 // feature an be used
1404 framefile = FindFrameFile( frame );
1406 sprintf( file1, "%s/%s", cdarchive, framefile );
1407 ExpandPathAndArchive( file1 );
1409 sprintf( file1, "%s/%s",cddir, framefile );
1411 printf( "grabbing %s ", file1 );
1413 if ( model.num_frames >= MAX_FRAMES ) {
1414 Error( "model.num_frames >= MAX_FRAMES" );
1416 fr = &g_frames[model.num_frames];
1419 strcpy( fr->name, frame );
1425 Load3DSTriangleList( file1, &ptri, &num_tris, NULL, NULL );
1428 LoadTriangleList( file1, &ptri, &num_tris, NULL, NULL );
1431 if ( num_tris != model.num_tris ) {
1432 Error( "%s: number of triangles doesn't match base frame\n", file1 );
1436 // allocate storage for the frame's vertices
1440 for ( i = 0 ; i < model.num_xyz ; i++ )
1442 vnorms[i].numnormals = 0;
1443 VectorClear( vnorms[i].normalsum );
1445 ClearBounds( fr->mins, fr->maxs );
1448 // store the frame's vertices in the same order as the base. This assumes the
1449 // triangles and vertices in this frame are in exactly the same order as in the
1452 for ( i = 0 ; i < num_tris ; i++ )
1454 vec3_t vtemp1, vtemp2, normal;
1457 VectorSubtract( ptri[i].verts[0], ptri[i].verts[1], vtemp1 );
1458 VectorSubtract( ptri[i].verts[2], ptri[i].verts[1], vtemp2 );
1459 CrossProduct( vtemp1, vtemp2, normal );
1461 VectorNormalize( normal, normal );
1463 // rotate the normal so the model faces down the positive x axis
1465 normal[0] = -normal[1];
1468 for ( j = 0 ; j < 3 ; j++ )
1470 index_xyz = triangles[i].index_xyz[j];
1472 // rotate the vertices so the model faces down the positive x axis
1473 // also adjust the vertices to the desired origin
1474 ptrivert[index_xyz].v[0] = ( ( -ptri[i].verts[j][1] ) * scale_up ) +
1476 ptrivert[index_xyz].v[1] = ( ptri[i].verts[j][0] * scale_up ) +
1478 ptrivert[index_xyz].v[2] = ( ptri[i].verts[j][2] * scale_up ) +
1481 AddPointToBounds( ptrivert[index_xyz].v, fr->mins, fr->maxs );
1483 VectorAdd( vnorms[index_xyz].normalsum, normal, vnorms[index_xyz].normalsum );
1484 vnorms[index_xyz].numnormals++;
1489 // calculate the vertex normals, match them to the template list, and store the
1490 // index of the best match
1492 for ( i = 0 ; i < model.num_xyz ; i++ )
1500 c = vnorms[i].numnormals;
1502 Error( "Vertex with no triangles attached" );
1505 VectorScale( vnorms[i].normalsum, 1.0 / c, v );
1506 VectorNormalize( v, v );
1511 for ( j = 0 ; j < NUMVERTEXNORMALS ; j++ )
1515 dot = DotProduct( v, avertexnormals[j] );
1516 if ( dot > maxdot ) {
1522 ptrivert[i].lightnormalindex = maxdotindex;
1533 void GrabJointedFrame( char *frame ){
1538 framefile = FindFrameFile( frame );
1540 sprintf( file1, "%s/%s", cdarchive, framefile );
1541 ExpandPathAndArchive( file1 );
1543 sprintf( file1, "%s/%s",cddir, framefile );
1545 printf( "grabbing %s\n", file1 );
1547 fr = &g_frames[model.num_frames - 1]; // last frame read in
1549 LoadJointList( file1, fr->joints, jointed );
1557 void GrabGlobals( char *frame ){
1562 framefile = FindFrameFile( frame );
1564 sprintf( file1, "%s/%s", cdarchive, framefile );
1565 ExpandPathAndArchive( file1 );
1567 sprintf( file1, "%s/%s",cddir, framefile );
1569 printf( "grabbing %s\n", file1 );
1571 fr = &g_frames[model.num_frames - 1]; // last frame read in
1573 LoadGlobals( file1 );
1581 void Cmd_Frame( void ){
1582 while ( ScriptTokenAvailable() )
1584 GetScriptToken( false );
1585 if ( g_skipmodel ) {
1588 if ( g_release || g_archive ) {
1589 model.num_frames = 1; // don't skip the writeout
1593 H_printf( "#define FRAME_%-16s\t%i\n", token, model.num_frames );
1603 Skins aren't actually stored in the file, only a reference
1604 is saved out to the header file.
1607 void Cmd_Skin( void ){
1613 char name[1024], savename[1024];
1615 GetScriptToken( false );
1617 if ( model.num_skins == MAX_MD2SKINS ) {
1618 Error( "model.num_skins == MAX_MD2SKINS" );
1621 if ( g_skipmodel ) {
1626 sprintf( name, "%s/%s.pcx", cddir, token );
1627 sprintf( savename, "%s/!%s.pcx", g_outputDir, token );
1628 sprintf( g_skins[model.num_skins], "%s/!%s.pcx", cdpartial, token );
1630 sprintf( name, "%s/%s.lbm", cdarchive, token );
1631 strcpy( name, ExpandPathAndArchive( name ) );
1632 // sprintf (name, "%s/%s.lbm", cddir, token);
1634 if ( ScriptTokenAvailable() ) {
1635 GetScriptToken( false );
1636 sprintf( g_skins[model.num_skins], "%s.pcx", token );
1637 sprintf( savename, "%s%s.pcx", g_outputDir, g_skins[model.num_skins] );
1641 sprintf( savename, "%s/%s.pcx", g_outputDir, token );
1642 sprintf( g_skins[model.num_skins], "%s/%s.pcx", cdpartial, token );
1648 if ( g_skipmodel || g_release || g_archive ) {
1653 printf( "loading %s\n", name );
1654 Load256Image( name, &pixels, &palette, &width, &height );
1655 // RemapZero (pixels, palette, width, height);
1657 // crop it to the proper size
1658 cropped = (byte *) SafeMalloc( model.skinwidth * model.skinheight, "Cmd_Skin" );
1659 for ( y = 0 ; y < model.skinheight ; y++ )
1661 memcpy( cropped + y * model.skinwidth,
1662 pixels + y * width, model.skinwidth );
1665 // save off the new image
1666 printf( "saving %s\n", savename );
1667 CreatePath( savename );
1668 WritePCXfile( savename, cropped, model.skinwidth,
1669 model.skinheight, palette );
1682 void Cmd_Origin( void ){
1683 // rotate points into frame of reference so model points down the
1685 GetScriptToken( false );
1686 adjust[1] = -atof( token );
1688 GetScriptToken( false );
1689 adjust[0] = atof( token );
1691 GetScriptToken( false );
1692 adjust[2] = -atof( token );
1701 void Cmd_ScaleUp( void ){
1702 GetScriptToken( false );
1703 scale_up = atof( token );
1704 if ( g_skipmodel || g_release || g_archive ) {
1708 printf( "Scale up: %f\n", scale_up );
1716 Set a skin size other than the default
1719 void Cmd_Skinsize( void ){
1720 GetScriptToken( false );
1721 g_fixedwidth = atoi( token );
1722 GetScriptToken( false );
1723 g_fixedheight = atoi( token );
1730 Gives a different name/location for the file, instead of the cddir
1733 void Cmd_Modelname( void ){
1734 GetScriptToken( false );
1735 strcpy( modelname, token );
1743 void Cmd_Cd( void ){
1749 GetScriptToken( false );
1751 // this is a silly mess...
1752 sprintf( cdpartial, "models/%s", token );
1753 sprintf( cdarchive, "%smodels/%s", gamedir + strlen( qdir ), token );
1754 sprintf( cddir, "%s%s", gamedir, cdpartial );
1756 // Since we also changed directories on the output side (for mirror) make sure the outputdir is set properly too.
1757 sprintf( temp, "%s%s", g_outputDir, cdpartial );
1758 strcpy( g_outputDir, temp );
1760 // if -only was specified and this cd doesn't match,
1761 // skip the model (you only need to match leading chars,
1762 // so you could regrab all monsters with -only monsters)
1766 if ( strncmp( token, g_only, strlen( g_only ) ) ) {
1768 printf( "skipping %s\n", cdpartial );
1780 GetScriptToken( false );
1782 printf( "---------------------\n" );
1783 sprintf( file1, "%s/%s", cdpartial, token );
1784 printf( "%s\n", file1 );
1786 ExpandPathAndArchive( file1 );
1788 sprintf( file1, "%s/%s", cddir, token );
1790 LoadClusters( file1, (int **)&clusters, (int *)&num_verts, jointed );
1792 new_num_verts[0] = num_verts[0];
1797 // Model construction cover functions.
1798 void MODELCMD_Modelname( int modeltype ){
1799 if ( g_forcemodel ) {
1800 modeltype = g_forcemodel;
1817 void MODELCMD_Cd( int modeltype ){
1818 if ( g_forcemodel ) {
1819 modeltype = g_forcemodel;
1822 switch ( modeltype )
1833 void MODELCMD_Origin( int modeltype ){
1834 if ( g_forcemodel ) {
1835 modeltype = g_forcemodel;
1839 /* switch(modeltype)
1851 void MODELCMD_Cluster( int modeltype ){
1852 if ( g_forcemodel ) {
1853 modeltype = g_forcemodel;
1856 switch ( modeltype )
1867 void MODELCMD_Base( int modeltype ){
1868 if ( g_forcemodel ) {
1869 modeltype = g_forcemodel;
1872 switch ( modeltype )
1878 Cmd_FMBase( false );
1883 void MODELCMD_BaseST( int modeltype ){
1884 if ( g_forcemodel ) {
1885 modeltype = g_forcemodel;
1888 switch ( modeltype )
1899 void MODELCMD_ScaleUp( int modeltype ){
1900 if ( g_forcemodel ) {
1901 modeltype = g_forcemodel;
1905 /* switch(modeltype)
1917 void MODELCMD_Frame( int modeltype ){
1918 if ( g_forcemodel ) {
1919 modeltype = g_forcemodel;
1922 switch ( modeltype )
1933 void MODELCMD_Skin( int modeltype ){
1934 if ( g_forcemodel ) {
1935 modeltype = g_forcemodel;
1938 switch ( modeltype )
1949 void MODELCMD_Skinsize( int modeltype ){
1950 if ( g_forcemodel ) {
1951 modeltype = g_forcemodel;
1968 void MODELCMD_Skeleton( int modeltype ){
1969 if ( g_forcemodel ) {
1970 modeltype = g_forcemodel;
1973 switch ( modeltype )
1983 void MODELCMD_BeginGroup( int modeltype ){
1984 if ( g_forcemodel ) {
1985 modeltype = g_forcemodel;
1988 switch ( modeltype )
1998 void MODELCMD_EndGroup( int modeltype ){
1999 if ( g_forcemodel ) {
2000 modeltype = g_forcemodel;
2003 switch ( modeltype )
2013 void MODELCMD_Referenced( int modeltype ){
2014 if ( g_forcemodel ) {
2015 modeltype = g_forcemodel;
2018 switch ( modeltype )
2028 void MODELCMD_NodeOrder( int modeltype ){
2029 if ( g_forcemodel ) {
2030 modeltype = g_forcemodel;
2033 switch ( modeltype )