2 Copyright (C) 1999-2007 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
31 extern char *g_outputDir;
34 char mip_prefix[1024]; // directory to dump the textures in
36 qboolean colormap_issued;
37 byte colormap_palette[768];
41 unsigned total_textures = 0;
43 #define MAX_IMAGE_SIZE 512
50 Replaces all 0 bytes in an image with the closest palette entry.
51 This is because NT won't let us change index 0, so any palette
52 animation leaves those pixels untouched.
55 void RemapZero( byte *pixels, byte *palette, int width, int height ){
62 for ( i = 1 ; i < 255 ; i++ )
64 value = palette[i * 3 + 0] + palette[i * 3 + 1] + palette[i * 3 + 2];
72 for ( i = 0 ; i < c ; i++ )
73 if ( pixels[i] == 0 ) {
81 // ********************************************************************
82 // ** Mip Map Pre-Processing Routines
83 // ********************************************************************
85 #define intensity_value 1
87 static unsigned image_pal[256];
91 long palette_r[256], palette_g[256], palette_b[256];
92 long last_r[MAX_LAST],last_g[MAX_LAST],last_b[MAX_LAST], last_i[MAX_LAST], last_place;
96 void PrepareConvert( unsigned *palette ){
99 for ( i = 0; i < 256; i++ )
101 palette_r[i] = ( palette[i] & 0x00ff0000 ) >> 16;
102 palette_g[i] = ( palette[i] & 0x0000ff00 ) >> 8;
103 palette_b[i] = ( palette[i] & 0x000000ff );
106 for ( i = 0; i < MAX_LAST; i++ )
112 int ConvertTrueColorToPal( unsigned r, unsigned g, unsigned b ){
117 long dr, dg, db, biggest_delta;
119 for ( i = 0; i < MAX_LAST; i++ )
120 if ( r == last_r[i] && g == last_g[i] && b == last_b[i] ) {
125 min_dist = 256 * 256 + 256 * 256 + 256 * 256;
126 biggest_delta = 256 * 256;
129 for ( i = 0; i < 256; i++ )
131 dr = abs( palette_r[i] - r );
132 if ( dr > biggest_delta ) {
135 dg = abs( palette_g[i] - g );
136 if ( dg > biggest_delta ) {
139 db = abs( palette_b[i] - b );
140 if ( db > biggest_delta ) {
144 dist = dr * dr + dg * dg + db * db;
145 if ( dist < min_dist ) {
148 if ( min_dist == 0 ) {
159 if ( dist < biggest_delta ) {
160 biggest_delta = dist;
166 if ( last_place >= MAX_LAST ) {
170 last_r[last_place] = r;
171 last_g[last_place] = g;
172 last_b[last_place] = b;
173 last_i[last_place] = min_index;
179 void GL_ResampleTexture8P( byte *in, int inwidth, int inheight, byte *out,
180 int outwidth, int outheight, palette_t *palette ){
182 byte *inrow, *inrow2;
183 unsigned frac, fracstep;
184 unsigned p1[1024], p2[1024], *p1p, *p2p;
185 palette_t *c1,*c2,*c3,*c4;
188 fracstep = inwidth * 0x10000 / outwidth;
190 frac = fracstep >> 2;
191 for ( i = 0 ; i < outwidth ; i++ )
196 frac = 3 * ( fracstep >> 2 );
197 for ( i = 0 ; i < outwidth ; i++ )
205 for ( i = 0 ; i < outheight ; i++ ) //, out += outwidth)
207 inrow = in + inwidth * (int)( ( i + 0.25 ) * inheight / outheight );
208 inrow2 = in + inwidth * (int)( ( i + 0.75 ) * inheight / outheight );
212 for ( j = 0 ; j < outwidth ; j++ )
214 c1 = &palette[*( (byte *)inrow + ( *p1p ) )];
215 c2 = &palette[*( (byte *)inrow + ( *p2p ) )];
216 c3 = &palette[*( (byte *)inrow2 + ( *p1p++ ) )];
217 c4 = &palette[*( (byte *)inrow2 + ( *p2p++ ) )];
219 r = ( (unsigned)c1->r + (unsigned)c2->r + (unsigned)c3->r + (unsigned)c4->r ) >> 2;
220 g = ( (unsigned)c1->g + (unsigned)c2->g + (unsigned)c3->g + (unsigned)c4->g ) >> 2;
221 b = ( (unsigned)c1->b + (unsigned)c2->b + (unsigned)c3->b + (unsigned)c4->b ) >> 2;
223 *out++ = ConvertTrueColorToPal( r,g,b );
228 void GL_MipMap8P( byte *out, byte *in, int width, int height, palette_t *palette ){
230 palette_t *c1,*c2,*c3,*c4;
234 memset( out, 0, 256 * 256 );
238 for ( i = 0; i < height; i += 2, in += width )
240 for ( j = 0; j < width; j += 2 )
242 c1 = &palette[in[0]];
243 c3 = &palette[in[width]];
245 c2 = &palette[in[0]];
246 c4 = &palette[in[width]];
249 r = ( (unsigned)c1->r + (unsigned)c2->r + (unsigned)c3->r + (unsigned)c4->r ) >> 2;
250 g = ( (unsigned)c1->g + (unsigned)c2->g + (unsigned)c3->g + (unsigned)c4->g ) >> 2;
251 b = ( (unsigned)c1->b + (unsigned)c2->b + (unsigned)c3->b + (unsigned)c4->b ) >> 2;
253 *out++ = ConvertTrueColorToPal( r, g, b );
259 miptex_t *CreateMip( byte *data, unsigned width, unsigned height, byte *palette, int *FinalSize, qboolean mip ){
260 int scaled_width, scaled_height;
262 byte intensitytable[256];
263 byte scaled[256 * 256];
270 for ( i = 0 ; i < 256 ; i++ )
272 j = i * intensity_value;
276 intensitytable[i] = j;
279 for ( scaled_width = 1 ; scaled_width < width ; scaled_width <<= 1 )
281 if ( 1 && scaled_width > width && 1 ) {
284 for ( scaled_height = 1 ; scaled_height < height ; scaled_height <<= 1 )
286 if ( 1 && scaled_height > height && 1 ) {
290 // don't ever bother with >256 textures
291 if ( scaled_width > 256 ) {
294 if ( scaled_height > 256 ) {
298 if ( scaled_width < 1 ) {
301 if ( scaled_height < 1 ) {
305 size = sizeof( *mp ) + ( scaled_width * scaled_height * 3 );
306 mp = (miptex_t *)SafeMalloc( size, "CreateMip" );
309 mp->version = MIP_VERSION;
311 for ( i = j = 0; i < 256; i++,j += 3 )
313 mp->palette[i].r = r = intensitytable[palette[j]];
314 mp->palette[i].g = g = intensitytable[palette[j + 1]];
315 mp->palette[i].b = b = intensitytable[palette[j + 2]];
316 image_pal[i] = 0xff000000 | ( r << 16 ) | ( g << 8 ) | ( b );
319 PrepareConvert( image_pal );
321 if ( scaled_width == width && scaled_height == height ) {
322 memcpy( scaled, data, width * height );
325 GL_ResampleTexture8P( data, width, height, scaled, scaled_width, scaled_height, mp->palette );
328 pos = (byte *)( mp + 1 );
331 while ( ( scaled_width >= 1 || scaled_height >= 1 ) && ( miplevel <= MIPLEVELS - 1 ) && ( !miplevel || mip ) )
333 if ( scaled_width < 1 ) {
336 if ( scaled_height < 1 ) {
340 if ( miplevel > 0 ) {
341 GL_MipMap8P( out, (byte *)scaled, scaled_width, scaled_height, mp->palette );
344 memcpy( out, scaled, 256 * 256 );
347 mp->width[miplevel] = scaled_width;
348 mp->height[miplevel] = scaled_height;
349 mp->offsets[miplevel] = pos - ( (byte *)( mp ) );
350 memcpy( pos, out, scaled_width * scaled_height );
351 memcpy( scaled, out, 256 * 256 );
352 pos += scaled_width * scaled_height;
360 *FinalSize = pos - ( (byte *)( mp ) );
366 void GL_ResampleTexture( unsigned *in, int inwidth, int inheight, unsigned *out, int outwidth, int outheight ){
368 unsigned *inrow, *inrow2;
369 unsigned frac, fracstep;
370 unsigned p1[1024], p2[1024];
371 byte *pix1, *pix2, *pix3, *pix4;
373 fracstep = inwidth * 0x10000 / outwidth;
375 frac = fracstep >> 2;
376 for ( i = 0 ; i < outwidth ; i++ )
378 p1[i] = 4 * ( frac >> 16 );
381 frac = 3 * ( fracstep >> 2 );
382 for ( i = 0 ; i < outwidth ; i++ )
384 p2[i] = 4 * ( frac >> 16 );
388 for ( i = 0 ; i < outheight ; i++, out += outwidth )
390 inrow = in + inwidth * (int)( ( i + 0.25 ) * inheight / outheight );
391 inrow2 = in + inwidth * (int)( ( i + 0.75 ) * inheight / outheight );
392 frac = fracstep >> 1;
393 for ( j = 0 ; j < outwidth ; j++ )
395 pix1 = (byte *)inrow + p1[j];
396 pix2 = (byte *)inrow + p2[j];
397 pix3 = (byte *)inrow2 + p1[j];
398 pix4 = (byte *)inrow2 + p2[j];
399 ( (byte *)( out + j ) )[0] = ( pix1[0] + pix2[0] + pix3[0] + pix4[0] ) >> 2;
400 ( (byte *)( out + j ) )[1] = ( pix1[1] + pix2[1] + pix3[1] + pix4[1] ) >> 2;
401 ( (byte *)( out + j ) )[2] = ( pix1[2] + pix2[2] + pix3[2] + pix4[2] ) >> 2;
402 ( (byte *)( out + j ) )[3] = ( pix1[3] + pix2[3] + pix3[3] + pix4[3] ) >> 2;
407 void GL_MipMap( byte *out, byte *in, int width, int height ){
412 for ( i = 0 ; i < height ; i++, in += width )
414 for ( j = 0 ; j < width ; j += 8, out += 4, in += 8 )
416 out[0] = ( in[0] + in[4] + in[width + 0] + in[width + 4] ) >> 2;
417 out[1] = ( in[1] + in[5] + in[width + 1] + in[width + 5] ) >> 2;
418 out[2] = ( in[2] + in[6] + in[width + 2] + in[width + 6] ) >> 2;
419 out[3] = ( in[3] + in[7] + in[width + 3] + in[width + 7] ) >> 2;
424 miptex32_t *CreateMip32( unsigned *data, unsigned width, unsigned height, int *FinalSize, qboolean mip ){
425 int scaled_width, scaled_height;
426 unsigned scaled[MAX_IMAGE_SIZE * MAX_IMAGE_SIZE];
427 unsigned out[MAX_IMAGE_SIZE * MAX_IMAGE_SIZE];
434 for ( scaled_width = 1 ; scaled_width < width ; scaled_width <<= 1 )
436 if ( 1 && scaled_width > width && 1 ) {
439 for ( scaled_height = 1 ; scaled_height < height ; scaled_height <<= 1 )
441 if ( 1 && scaled_height > height && 1 ) {
445 // don't ever bother with >256 textures
446 if ( scaled_width > MAX_IMAGE_SIZE ) {
447 scaled_width = MAX_IMAGE_SIZE;
449 if ( scaled_height > MAX_IMAGE_SIZE ) {
450 scaled_height = MAX_IMAGE_SIZE;
453 if ( scaled_width < 1 ) {
456 if ( scaled_height < 1 ) {
460 size = sizeof( *mp ) + ( scaled_width * scaled_height * 3 * 4 );
461 mp = (miptex32_t *)SafeMalloc( size, "CreateMip" );
464 mp->version = MIP32_VERSION;
466 size = width * height;
467 test = (paletteRGBA_t *)data;
470 if ( test->a != 255 ) {
471 mp->flags |= LittleLong( SURF_ALPHA_TEXTURE );
479 if ( scaled_width == width && scaled_height == height ) {
480 memcpy( scaled, data, width * height * 4 );
483 GL_ResampleTexture( data, width, height, scaled, scaled_width, scaled_height );
486 pos = (byte *)( mp + 1 );
489 while ( ( scaled_width >= 1 || scaled_height >= 1 ) && ( miplevel <= MIPLEVELS - 1 ) && ( !miplevel || mip ) )
491 if ( scaled_width < 1 ) {
494 if ( scaled_height < 1 ) {
498 if ( miplevel > 0 ) {
499 GL_MipMap( (byte *)out, (byte *)scaled, scaled_width, scaled_height );
503 memcpy( out, scaled, MAX_IMAGE_SIZE * MAX_IMAGE_SIZE * 4 );
506 mp->width[miplevel] = scaled_width;
507 mp->height[miplevel] = scaled_height;
508 mp->offsets[miplevel] = pos - ( (byte *)( mp ) );
509 memcpy( pos, out, scaled_width * scaled_height * 4 );
510 memcpy( scaled, out, MAX_IMAGE_SIZE * MAX_IMAGE_SIZE * 4 );
511 pos += scaled_width * scaled_height * 4;
519 *FinalSize = pos - ( (byte *)( mp ) );
528 $grab filename x y width height
531 void Cmd_Grab( void ){
537 GetScriptToken( false );
539 if ( token[0] == '/' || token[0] == '\\' ) {
540 sprintf( savename, "%s%s.pcx", gamedir, token + 1 );
543 sprintf( savename, "%spics/%s.pcx", gamedir, token );
547 if ( token[0] == '/' || token[0] == '\\' ) {
548 sprintf( dest, "%s.pcx", token + 1 );
551 sprintf( dest, "pics/%s.pcx", token );
558 GetScriptToken( false );
560 GetScriptToken( false );
562 GetScriptToken( false );
564 GetScriptToken( false );
567 if ( xl < 0 || yl < 0 || w < 0 || h < 0 || xl + w > byteimagewidth || yl + h > byteimageheight ) {
568 Error( "GrabPic: Bad size: %i, %i, %i, %i",xl,yl,w,h );
571 // crop it to the proper size
572 cropped = (byte *) SafeMalloc( w * h, "Cmd_Grab" );
573 for ( y = 0 ; y < h ; y++ )
575 memcpy( cropped + y * w, byteimage + ( y + yl ) * byteimagewidth + xl, w );
578 // save off the new image
579 printf( "saving %s\n", savename );
580 CreatePath( savename );
581 WritePCXfile( savename, cropped, w, h, lbmpalette );
590 $grab filename x y width height
593 void Cmd_Raw( void ){
599 GetScriptToken( false );
601 sprintf( savename, "%s%s.lmp", gamedir, token );
604 sprintf( dest, "%s.lmp", token );
609 GetScriptToken( false );
611 GetScriptToken( false );
613 GetScriptToken( false );
615 GetScriptToken( false );
618 if ( xl < 0 || yl < 0 || w < 0 || h < 0 || xl + w > byteimagewidth || yl + h > byteimageheight ) {
619 Error( "GrabPic: Bad size: %i, %i, %i, %i",xl,yl,w,h );
622 // crop it to the proper size
623 cropped = (byte *) SafeMalloc( w * h, "Cmd_Raw" );
624 for ( y = 0 ; y < h ; y++ )
626 memcpy( cropped + y * w, byteimage + ( y + yl ) * byteimagewidth + xl, w );
629 // save off the new image
630 printf( "saving %s\n", savename );
631 CreatePath( savename );
633 SaveFile( savename, cropped, w * h );
639 =============================================================================
643 =============================================================================
651 byte BestColor( int r, int g, int b, int start, int stop ){
654 int bestdistortion, distortion;
659 // let any color go to 0 as a last resort
661 bestdistortion = 256 * 256 * 4;
664 pal = colormap_palette + start * 3;
665 for ( i = start ; i <= stop ; i++ )
667 dr = r - (int)pal[0];
668 dg = g - (int)pal[1];
669 db = b - (int)pal[2];
671 distortion = dr * dr + dg * dg + db * db;
672 if ( distortion < bestdistortion ) {
674 return i; // perfect match
677 bestdistortion = distortion;
692 the brightes colormap is first in the table (FIXME: reverse this now?)
694 64 rows of 256 : lightmaps
695 256 rows of 256 : translucency table
698 void Cmd_Colormap( void ){
701 float frac, red, green, blue;
703 byte *cropped, *lump_p;
707 colormap_issued = true;
709 memcpy( colormap_palette, lbmpalette, 768 );
712 if ( !ScriptTokenAvailable() ) { // just setting colormap_issued
716 GetScriptToken( false );
717 sprintf( savename, "%spics/%s.pcx", gamedir, token );
720 sprintf( dest, "pics/%s.pcx", token );
727 brights = 1; // ignore 255 (transparent)
729 cropped = (byte *) SafeMalloc( ( levels + 256 ) * 256, "Cmd_ColorMap" );
733 for ( l = 0; l < levels; l++ )
735 frac = range - range * (float)l / ( levels - 1 );
736 for ( c = 0 ; c < 256 - brights ; c++ )
738 red = lbmpalette[c * 3];
739 green = lbmpalette[c * 3 + 1];
740 blue = lbmpalette[c * 3 + 2];
742 red = (int)( red * frac + 0.5 );
743 green = (int)( green * frac + 0.5 );
744 blue = (int)( blue * frac + 0.5 );
747 // note: 254 instead of 255 because 255 is the transparent color, and we
748 // don't want anything remapping to that
749 // don't use color 0, because NT can't remap that (or 255)
751 *lump_p++ = BestColor( red,green,blue, 1, 254 );
754 // fullbrights allways stay the same
755 for ( ; c < 256 ; c++ )
759 // 66% transparancy table
760 for ( l = 0; l < 255; l++ )
762 for ( c = 0 ; c < 255 ; c++ )
764 red = lbmpalette[c * 3] * 0.33 + lbmpalette[l * 3] * 0.66;
765 green = lbmpalette[c * 3 + 1] * 0.33 + lbmpalette[l * 3 + 1] * 0.66;
766 blue = lbmpalette[c * 3 + 2] * 0.33 + lbmpalette[l * 3 + 2] * 0.66;
768 *lump_p++ = BestColor( red,green,blue, 1, 254 );
772 for ( c = 0 ; c < 256 ; c++ )
775 // save off the new image
776 printf( "saving %s\n", savename );
777 CreatePath( savename );
778 WritePCXfile( savename, cropped, 256, levels + 256, lbmpalette );
784 =============================================================================
788 =============================================================================
793 int d_red, d_green, d_blue;
795 byte palmap[32][32][32];
796 qboolean palmap_built;
803 int FindColor( int r, int g, int b ){
825 bestcolor = BestColor( r, g, b, 0, 254 );
827 bestcolor = palmap[r >> 3][g >> 3][b >> 3];
834 void BuildPalmap( void ){
839 if ( palmap_built ) {
844 for ( r = 4 ; r < 256 ; r += 8 )
846 for ( g = 4 ; g < 256 ; g += 8 )
848 for ( b = 4 ; b < 256 ; b += 8 )
850 bestcolor = BestColor( r, g, b, 1, 254 );
851 palmap[r >> 3][g >> 3][b >> 3] = bestcolor;
857 if ( !colormap_issued ) {
858 Error( "You must issue a $colormap command first" );
868 byte AveragePixels( int count ){
880 for ( i = 0 ; i < count ; i++ )
884 r += lbmpalette[pix * 3];
885 g += lbmpalette[pix * 3 + 1];
886 b += lbmpalette[pix * 3 + 2];
900 // find the best color
902 bestcolor = FindColor( r, g, b );
905 pal = colormap_palette + bestcolor * 3;
906 d_red = r - (int)pal[0];
907 d_green = g - (int)pal[1];
908 d_blue = b - (int)pal[2];
938 mipparm_t mipparms[] =
940 // utility content attributes
941 {"pushpull",CONTENTS_PUSHPULL, pt_contents},
942 {"water", CONTENTS_WATER, pt_contents},
943 {"slime", CONTENTS_SLIME, pt_contents}, // mildly damaging
944 {"lava", CONTENTS_LAVA, pt_contents}, // very damaging
945 {"window", CONTENTS_WINDOW, pt_contents}, // solid, but doesn't eat internal textures
946 {"mist", CONTENTS_MIST, pt_contents}, // non-solid window
947 {"origin", CONTENTS_ORIGIN, pt_contents}, // center of rotating brushes
948 {"playerclip", CONTENTS_PLAYERCLIP, pt_contents},
949 {"monsterclip", CONTENTS_MONSTERCLIP, pt_contents},
951 // utility surface attributes
952 {"hint", SURF_HINT, pt_flags},
953 {"skip", SURF_SKIP, pt_flags},
954 {"light", SURF_LIGHT, pt_flagvalue}, // value is the light quantity
956 {"animspeed",SURF_ANIMSPEED, pt_flagvalue}, // value will hold the anim speed in fps
959 {"anim", 0, pt_animvalue}, // animname is the next animation
960 {"alt", 0, pt_altnamevalue}, // altname is the alternate texture
961 {"damage", 0, pt_damagenamevalue}, // damagename is the damage texture
962 {"scale", 0, pt_scale}, // next two values are for scale
964 {"detail", 0, pt_detail},
966 {"GL_ZERO", GL_ZERO, pt_gl},
967 {"GL_ONE", GL_ONE, pt_gl},
968 {"GL_SRC_COLOR", GL_SRC_COLOR, pt_gl},
969 {"GL_ONE_MINUS_SRC_COLOR", GL_ONE_MINUS_SRC_COLOR, pt_gl},
970 {"GL_DST_COLOR", GL_DST_COLOR, pt_gl},
971 {"GL_ONE_MINUS_DST_COLOR", GL_ONE_MINUS_DST_COLOR, pt_gl},
972 {"GL_SRC_ALPHA", GL_SRC_ALPHA, pt_gl},
973 {"GL_ONE_MINUS_SRC_ALPHA", GL_ONE_MINUS_SRC_ALPHA, pt_gl},
974 {"GL_DST_ALPHA", GL_DST_ALPHA, pt_gl},
975 {"GL_ONE_MINUS_DST_ALPHA", GL_ONE_MINUS_DST_ALPHA, pt_gl},
976 {"GL_SRC_ALPHA_SATURATE", GL_SRC_ALPHA_SATURATE, pt_gl},
979 {"slick", SURF_SLICK, pt_flags},
981 // drawing attributes
982 {"sky", SURF_SKY, pt_flags},
983 {"warping", SURF_WARP, pt_flags}, // only valid with 64x64 textures
984 {"trans33", SURF_TRANS33, pt_flags}, // translucent should allso set fullbright
985 {"trans66", SURF_TRANS66, pt_flags},
986 {"flowing", SURF_FLOWING, pt_flags}, // flow direction towards angle 0
987 {"nodraw", SURF_NODRAW, pt_flags}, // for clip textures and trigger textures
988 {"alpha", SURF_ALPHA_TEXTURE, pt_flags},
989 {"undulate", SURF_UNDULATE, pt_flags}, // rock surface up and down...
990 {"skyreflect", SURF_SKYREFLECT, pt_flags}, // liquid will somewhat reflect the sky - not quite finished....
992 {"material", SURF_MATERIAL, pt_materialvalue},
993 {"metal", SURF_TYPE_METAL, pt_flags},
994 {"stone", SURF_TYPE_STONE, pt_flags},
995 {"wood", SURF_TYPE_WOOD, pt_flags},
997 {"m_nomip", 0, pt_nomip},
998 {"m_detail", 0, pt_detailer},
1000 {NULL, 0, pt_contents}
1007 $mip filename x y width height <OPTIONS>
1008 must be multiples of sixteen
1013 void Cmd_Mip( void ){
1014 int xl,yl,xh,yh,w,h;
1015 byte *dest, *source;
1016 int flags, value, contents;
1021 char damagename[128];
1022 byte buffer[MAX_IMAGE_SIZE * MAX_IMAGE_SIZE];
1023 unsigned bufferl[MAX_IMAGE_SIZE * MAX_IMAGE_SIZE];
1024 materialtype_t *mat;
1025 char filename[1024];
1026 unsigned *destl, *sourcel;
1027 int linedelta, x, y;
1031 float scale_x, scale_y;
1035 float dt_scale_x, dt_scale_y;
1038 int dt_src_blend_mode, dt_dst_blend_mode;
1042 GetScriptToken( false );
1043 strcpy( lumpname, token );
1045 GetScriptToken( false );
1047 GetScriptToken( false );
1049 GetScriptToken( false );
1051 GetScriptToken( false );
1058 if ( ( w & 15 ) || ( h & 15 ) ) {
1059 Error( "line %i: miptex sizes must be multiples of 16", scriptline );
1068 altname[0] = animname[0] = damagename[0] = 0;
1070 scale_x = scale_y = 0.5;
1074 dt_scale_x = dt_scale_y = 0.0;
1077 dt_src_blend_mode = dt_dst_blend_mode = 0;
1079 // get optional flags and values
1080 while ( ScriptTokenAvailable() )
1082 GetScriptToken( false );
1084 for ( mp = mipparms ; mp->name ; mp++ )
1086 if ( !strcmp( mp->name, token ) ) {
1090 GetScriptToken( false ); // specify the next animation frame
1091 strcpy( animname, token );
1093 case pt_altnamevalue:
1094 GetScriptToken( false ); // specify the alternate texture
1095 strcpy( altname, token );
1097 case pt_damagenamevalue:
1098 GetScriptToken( false ); // specify the damage texture
1099 strcpy( damagename, token );
1105 contents |= mp->flags;
1109 GetScriptToken( false ); // specify the light value
1110 value = atoi( token );
1112 case pt_materialvalue:
1113 GetScriptToken( false );
1114 for ( mat = materialtypes ; mat->name ; mat++ )
1116 if ( !strcmp( mat->name, token ) ) {
1117 // assumes SURF_MATERIAL is in top 8 bits
1118 flags = ( flags & 0x0FFFFFF ) | ( mat->value << 24 );
1124 GetScriptToken( false ); // specify the x scale
1125 scale_x = atof( token );
1126 GetScriptToken( false ); // specify the y scale
1127 scale_y = atof( token );
1135 flags2 |= MIP32_DETAILER_FLAG2;
1139 flags2 |= MIP32_NOMIP_FLAG2;
1143 GetScriptToken( false );
1144 strcpy( dt_name, token );
1145 GetScriptToken( false );
1146 dt_scale_x = atof( token );
1147 GetScriptToken( false );
1148 dt_scale_y = atof( token );
1149 GetScriptToken( false );
1150 dt_u = atof( token );
1151 GetScriptToken( false );
1152 dt_v = atof( token );
1153 GetScriptToken( false );
1154 dt_alpha = atof( token );
1155 GetScriptToken( false );
1156 for ( mp = mipparms ; mp->name ; mp++ )
1158 if ( !strcmp( mp->name, token ) ) {
1159 if ( mp->type == pt_gl ) {
1160 dt_src_blend_mode = mp->flags;
1166 Error( "line %i: invalid gl blend mode %s", scriptline, token );
1168 GetScriptToken( false );
1169 for ( mp = mipparms ; mp->name ; mp++ )
1171 if ( !strcmp( mp->name, token ) ) {
1172 if ( mp->type == pt_gl ) {
1173 dt_dst_blend_mode = mp->flags;
1179 Error( "line %i: invalid gl blend mode %s", scriptline, token );
1187 Error( "line %i: unknown parm %s", scriptline, token );
1192 return; // textures are only released by $maps
1197 if ( xh * yh > MAX_IMAGE_SIZE * MAX_IMAGE_SIZE ) {
1198 Error( "line %i image %s: image is too big!", scriptline, lumpname );
1201 if ( TrueColorImage ) {
1202 if ( xl >= longimagewidth || xh > longimagewidth ||
1203 yl >= longimageheight || yh > longimageheight ) {
1204 Error( "line %i image %s: bad clip dimmensions (%d,%d) (%d,%d) > image (%d,%d)", scriptline, lumpname, xl,yl,w,h,longimagewidth,longimageheight );
1207 sourcel = longimage + ( yl * longimagewidth ) + xl;
1209 linedelta = ( longimagewidth - w );
1211 for ( y = yl ; y < yh ; y++ )
1213 for ( x = xl ; x < xh ; x++ )
1215 *destl++ = *sourcel++; // RGBA
1217 sourcel += linedelta;
1220 qtex32 = CreateMip32( bufferl, w, h, &size, true );
1222 qtex32->flags |= LittleLong( flags );
1223 qtex32->flags2 |= LittleLong( flags2 );
1224 qtex32->contents = LittleLong( contents );
1225 qtex32->value = LittleLong( value );
1226 qtex32->scale_x = scale_x;
1227 qtex32->scale_y = scale_y;
1228 qtex32->mip_scale = mip_scale;
1229 sprintf( qtex32->name, "%s/%s", mip_prefix, lumpname );
1230 if ( animname[0] ) {
1231 sprintf( qtex32->animname, "%s/%s", mip_prefix, animname );
1234 sprintf( qtex32->altname, "%s/%s", mip_prefix, altname );
1236 if ( damagename[0] ) {
1237 sprintf( qtex32->damagename, "%s/%s", mip_prefix, damagename );
1239 if ( dt_name[0] & ( ( flags2 & MIP32_DETAILER_FLAG2 ) == 0 ) ) {
1240 sprintf( qtex32->dt_name, "%s/%s", mip_prefix, dt_name );
1241 qtex32->dt_scale_x = dt_scale_x;
1242 qtex32->dt_scale_y = dt_scale_y;
1243 qtex32->dt_u = dt_u;
1244 qtex32->dt_v = dt_v;
1245 qtex32->dt_alpha = dt_alpha;
1246 qtex32->dt_src_blend_mode = dt_src_blend_mode;
1247 qtex32->dt_dst_blend_mode = dt_dst_blend_mode;
1253 sprintf( filename, "%stextures/%s/%s.m32", g_outputDir, mip_prefix, lumpname );
1254 if ( qtex32->flags & ( SURF_ALPHA_TEXTURE ) ) {
1255 printf( "writing %s with ALPHA\n", filename );
1258 printf( "writing %s\n", filename );
1260 SaveFile( filename, (byte *)qtex32, size );
1266 if ( xl >= byteimagewidth || xh > byteimagewidth ||
1267 yl >= byteimageheight || yh > byteimageheight ) {
1268 Error( "line %i: bad clip dimmensions (%d,%d) (%d,%d) > image (%d,%d)", scriptline, xl,yl,w,h,byteimagewidth,byteimageheight );
1271 source = byteimage + yl * byteimagewidth + xl;
1273 linedelta = byteimagewidth - w;
1275 for ( y = yl ; y < yh ; y++ )
1277 for ( x = xl ; x < xh ; x++ )
1279 *dest++ = *source++;
1281 source += linedelta;
1284 qtex = CreateMip( buffer, w, h, lbmpalette, &size, true );
1286 qtex->flags = LittleLong( flags );
1287 qtex->contents = LittleLong( contents );
1288 qtex->value = LittleLong( value );
1289 sprintf( qtex->name, "%s/%s", mip_prefix, lumpname );
1290 if ( animname[0] ) {
1291 sprintf( qtex->animname, "%s/%s", mip_prefix, animname );
1297 sprintf( filename, "%stextures/%s/%s.m8", g_outputDir, mip_prefix, lumpname );
1298 printf( "writing %s\n", filename );
1299 SaveFile( filename, (byte *)qtex, size );
1310 void Cmd_Mippal( void ){
1311 colormap_issued = true;
1316 memcpy( colormap_palette, lbmpalette, 768 );
1327 void Cmd_Mipdir( void ){
1328 char filename[1024];
1330 GetScriptToken( false );
1331 strcpy( mip_prefix, token );
1332 // create the directory if needed
1333 sprintf( filename, "%stextures", g_outputDir );
1334 Q_mkdir( filename );
1335 sprintf( filename, "%stextures/%s", g_outputDir, mip_prefix );
1336 Q_mkdir( filename );
1341 =============================================================================
1343 ENVIRONMENT MAP GRABBING
1345 Creates six pcx files from tga files without any palette edge seams
1346 also copies the tga files for GL rendering.
1347 =============================================================================
1350 // 3dstudio environment map suffixes
1351 char *suf[6] = {"rt", "ft", "lf", "bk", "up", "dn"};
1358 void Cmd_Environment( void ){
1361 byte image[256 * 256];
1364 GetScriptToken( false );
1367 for ( i = 0 ; i < 6 ; i++ )
1369 sprintf( name, "env/%s%s.pcx", token, suf[i] );
1370 ReleaseFile( name );
1371 sprintf( name, "env/%s%s.tga", token, suf[i] );
1372 ReleaseFile( name );
1379 sprintf( name, "%senv/", gamedir );
1382 // convert the images
1383 for ( i = 0 ; i < 6 ; i++ )
1385 sprintf( name, "%senv/%s%s.tga", gamedir, token, suf[i] );
1386 printf( "loading %s...\n", name );
1387 LoadTGA( name, &tga, NULL, NULL );
1389 for ( y = 0 ; y < 256 ; y++ )
1391 for ( x = 0 ; x < 256 ; x++ )
1393 image[y * 256 + x] = FindColor( tga[( y * 256 + x ) * 4 + 0],tga[( y * 256 + x ) * 4 + 1],tga[( y * 256 + x ) * 4 + 2] );
1397 sprintf( name, "%senv/%s%s.pcx", gamedir, token, suf[i] );
1398 if ( FileTime( name ) != -1 ) {
1399 printf( "%s already exists, not overwriting.\n", name );
1402 WritePCXfile( name, image, 256, 256, colormap_palette );