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
28 #if GDEF_OS_MACOS && !defined( XWINDOWS )
29 #include <OpenGL/gl.h>
35 extern char *g_outputDir;
38 byte *byteimage, *lbmpalette;
39 int byteimagewidth, byteimageheight;
40 qboolean TrueColorImage;
42 int longimagewidth, longimageheight;
44 char mip_prefix[1024]; // directory to dump the textures in
46 qboolean colormap_issued;
47 byte colormap_palette[768];
51 unsigned total_textures = 0;
53 #define MAX_IMAGE_SIZE 512
60 Replaces all 0 bytes in an image with the closest palette entry.
61 This is because NT won't let us change index 0, so any palette
62 animation leaves those pixels untouched.
65 void RemapZero( byte *pixels, byte *palette, int width, int height ){
72 for ( i = 1 ; i < 255 ; i++ )
74 value = palette[i * 3 + 0] + palette[i * 3 + 1] + palette[i * 3 + 2];
82 for ( i = 0 ; i < c ; i++ )
83 if ( pixels[i] == 0 ) {
91 // ********************************************************************
92 // ** Mip Map Pre-Processing Routines
93 // ********************************************************************
95 #define intensity_value 1
97 static unsigned image_pal[256];
101 long palette_r[256], palette_g[256], palette_b[256];
102 long last_r[MAX_LAST],last_g[MAX_LAST],last_b[MAX_LAST], last_i[MAX_LAST], last_place;
106 void PrepareConvert( unsigned *palette ){
109 for ( i = 0; i < 256; i++ )
111 palette_r[i] = ( palette[i] & 0x00ff0000 ) >> 16;
112 palette_g[i] = ( palette[i] & 0x0000ff00 ) >> 8;
113 palette_b[i] = ( palette[i] & 0x000000ff );
116 for ( i = 0; i < MAX_LAST; i++ )
122 int ConvertTrueColorToPal( unsigned r, unsigned g, unsigned b ){
127 long dr, dg, db, biggest_delta;
129 for ( i = 0; i < MAX_LAST; i++ )
130 if ( r == last_r[i] && g == last_g[i] && b == last_b[i] ) {
135 min_dist = 256 * 256 + 256 * 256 + 256 * 256;
136 biggest_delta = 256 * 256;
139 for ( i = 0; i < 256; i++ )
141 dr = abs( palette_r[i] - r );
142 if ( dr > biggest_delta ) {
145 dg = abs( palette_g[i] - g );
146 if ( dg > biggest_delta ) {
149 db = abs( palette_b[i] - b );
150 if ( db > biggest_delta ) {
154 dist = dr * dr + dg * dg + db * db;
155 if ( dist < min_dist ) {
158 if ( min_dist == 0 ) {
169 if ( dist < biggest_delta ) {
170 biggest_delta = dist;
176 if ( last_place >= MAX_LAST ) {
180 last_r[last_place] = r;
181 last_g[last_place] = g;
182 last_b[last_place] = b;
183 last_i[last_place] = min_index;
189 void GL_ResampleTexture8P( byte *in, int inwidth, int inheight, byte *out,
190 int outwidth, int outheight, palette_t *palette ){
192 byte *inrow, *inrow2;
193 unsigned frac, fracstep;
194 unsigned p1[1024], p2[1024], *p1p, *p2p;
195 palette_t *c1,*c2,*c3,*c4;
198 fracstep = inwidth * 0x10000 / outwidth;
200 frac = fracstep >> 2;
201 for ( i = 0 ; i < outwidth ; i++ )
206 frac = 3 * ( fracstep >> 2 );
207 for ( i = 0 ; i < outwidth ; i++ )
215 for ( i = 0 ; i < outheight ; i++ ) //, out += outwidth)
217 inrow = in + inwidth * (int)( ( i + 0.25 ) * inheight / outheight );
218 inrow2 = in + inwidth * (int)( ( i + 0.75 ) * inheight / outheight );
222 for ( j = 0 ; j < outwidth ; j++ )
224 c1 = &palette[*( (byte *)inrow + ( *p1p ) )];
225 c2 = &palette[*( (byte *)inrow + ( *p2p ) )];
226 c3 = &palette[*( (byte *)inrow2 + ( *p1p++ ) )];
227 c4 = &palette[*( (byte *)inrow2 + ( *p2p++ ) )];
229 r = ( (unsigned)c1->r + (unsigned)c2->r + (unsigned)c3->r + (unsigned)c4->r ) >> 2;
230 g = ( (unsigned)c1->g + (unsigned)c2->g + (unsigned)c3->g + (unsigned)c4->g ) >> 2;
231 b = ( (unsigned)c1->b + (unsigned)c2->b + (unsigned)c3->b + (unsigned)c4->b ) >> 2;
233 *out++ = ConvertTrueColorToPal( r,g,b );
238 void GL_MipMap8P( byte *out, byte *in, int width, int height, palette_t *palette ){
240 palette_t *c1,*c2,*c3,*c4;
244 memset( out, 0, 256 * 256 );
248 for ( i = 0; i < height; i += 2, in += width )
250 for ( j = 0; j < width; j += 2 )
252 c1 = &palette[in[0]];
253 c3 = &palette[in[width]];
255 c2 = &palette[in[0]];
256 c4 = &palette[in[width]];
259 r = ( (unsigned)c1->r + (unsigned)c2->r + (unsigned)c3->r + (unsigned)c4->r ) >> 2;
260 g = ( (unsigned)c1->g + (unsigned)c2->g + (unsigned)c3->g + (unsigned)c4->g ) >> 2;
261 b = ( (unsigned)c1->b + (unsigned)c2->b + (unsigned)c3->b + (unsigned)c4->b ) >> 2;
263 *out++ = ConvertTrueColorToPal( r, g, b );
269 miptex_t *CreateMip( byte *data, unsigned width, unsigned height, byte *palette, int *FinalSize, qboolean mip ){
270 int scaled_width, scaled_height;
272 byte intensitytable[256];
273 byte scaled[256 * 256];
280 for ( i = 0 ; i < 256 ; i++ )
282 j = i * intensity_value;
286 intensitytable[i] = j;
289 for ( scaled_width = 1 ; scaled_width < width ; scaled_width <<= 1 )
291 if ( 1 && scaled_width > width && 1 ) {
294 for ( scaled_height = 1 ; scaled_height < height ; scaled_height <<= 1 )
296 if ( 1 && scaled_height > height && 1 ) {
300 // don't ever bother with >256 textures
301 if ( scaled_width > 256 ) {
304 if ( scaled_height > 256 ) {
308 if ( scaled_width < 1 ) {
311 if ( scaled_height < 1 ) {
315 size = sizeof( *mp ) + ( scaled_width * scaled_height * 3 );
316 mp = (miptex_t *)SafeMalloc( size, "CreateMip" );
319 mp->version = MIP_VERSION;
321 for ( i = j = 0; i < 256; i++,j += 3 )
323 mp->palette[i].r = r = intensitytable[palette[j]];
324 mp->palette[i].g = g = intensitytable[palette[j + 1]];
325 mp->palette[i].b = b = intensitytable[palette[j + 2]];
326 image_pal[i] = 0xff000000 | ( r << 16 ) | ( g << 8 ) | ( b );
329 PrepareConvert( image_pal );
331 if ( scaled_width == width && scaled_height == height ) {
332 memcpy( scaled, data, width * height );
335 GL_ResampleTexture8P( data, width, height, scaled, scaled_width, scaled_height, mp->palette );
338 pos = (byte *)( mp + 1 );
341 while ( ( scaled_width >= 1 || scaled_height >= 1 ) && ( miplevel <= MIPLEVELS - 1 ) && ( !miplevel || mip ) )
343 if ( scaled_width < 1 ) {
346 if ( scaled_height < 1 ) {
350 if ( miplevel > 0 ) {
351 GL_MipMap8P( out, (byte *)scaled, scaled_width, scaled_height, mp->palette );
354 memcpy( out, scaled, 256 * 256 );
357 mp->width[miplevel] = scaled_width;
358 mp->height[miplevel] = scaled_height;
359 mp->offsets[miplevel] = pos - ( (byte *)( mp ) );
360 memcpy( pos, out, scaled_width * scaled_height );
361 memcpy( scaled, out, 256 * 256 );
362 pos += scaled_width * scaled_height;
370 *FinalSize = pos - ( (byte *)( mp ) );
376 void GL_ResampleTexture( unsigned *in, int inwidth, int inheight, unsigned *out, int outwidth, int outheight ){
378 unsigned *inrow, *inrow2;
379 unsigned frac, fracstep;
380 unsigned p1[1024], p2[1024];
381 byte *pix1, *pix2, *pix3, *pix4;
383 fracstep = inwidth * 0x10000 / outwidth;
385 frac = fracstep >> 2;
386 for ( i = 0 ; i < outwidth ; i++ )
388 p1[i] = 4 * ( frac >> 16 );
391 frac = 3 * ( fracstep >> 2 );
392 for ( i = 0 ; i < outwidth ; i++ )
394 p2[i] = 4 * ( frac >> 16 );
398 for ( i = 0 ; i < outheight ; i++, out += outwidth )
400 inrow = in + inwidth * (int)( ( i + 0.25 ) * inheight / outheight );
401 inrow2 = in + inwidth * (int)( ( i + 0.75 ) * inheight / outheight );
402 frac = fracstep >> 1;
403 for ( j = 0 ; j < outwidth ; j++ )
405 pix1 = (byte *)inrow + p1[j];
406 pix2 = (byte *)inrow + p2[j];
407 pix3 = (byte *)inrow2 + p1[j];
408 pix4 = (byte *)inrow2 + p2[j];
409 ( (byte *)( out + j ) )[0] = ( pix1[0] + pix2[0] + pix3[0] + pix4[0] ) >> 2;
410 ( (byte *)( out + j ) )[1] = ( pix1[1] + pix2[1] + pix3[1] + pix4[1] ) >> 2;
411 ( (byte *)( out + j ) )[2] = ( pix1[2] + pix2[2] + pix3[2] + pix4[2] ) >> 2;
412 ( (byte *)( out + j ) )[3] = ( pix1[3] + pix2[3] + pix3[3] + pix4[3] ) >> 2;
417 void GL_MipMap( byte *out, byte *in, int width, int height ){
422 for ( i = 0 ; i < height ; i++, in += width )
424 for ( j = 0 ; j < width ; j += 8, out += 4, in += 8 )
426 out[0] = ( in[0] + in[4] + in[width + 0] + in[width + 4] ) >> 2;
427 out[1] = ( in[1] + in[5] + in[width + 1] + in[width + 5] ) >> 2;
428 out[2] = ( in[2] + in[6] + in[width + 2] + in[width + 6] ) >> 2;
429 out[3] = ( in[3] + in[7] + in[width + 3] + in[width + 7] ) >> 2;
434 miptex32_t *CreateMip32( unsigned *data, unsigned width, unsigned height, int *FinalSize, qboolean mip ){
435 int scaled_width, scaled_height;
436 unsigned scaled[MAX_IMAGE_SIZE * MAX_IMAGE_SIZE];
437 unsigned out[MAX_IMAGE_SIZE * MAX_IMAGE_SIZE];
444 for ( scaled_width = 1 ; scaled_width < width ; scaled_width <<= 1 )
446 if ( 1 && scaled_width > width && 1 ) {
449 for ( scaled_height = 1 ; scaled_height < height ; scaled_height <<= 1 )
451 if ( 1 && scaled_height > height && 1 ) {
455 // don't ever bother with >256 textures
456 if ( scaled_width > MAX_IMAGE_SIZE ) {
457 scaled_width = MAX_IMAGE_SIZE;
459 if ( scaled_height > MAX_IMAGE_SIZE ) {
460 scaled_height = MAX_IMAGE_SIZE;
463 if ( scaled_width < 1 ) {
466 if ( scaled_height < 1 ) {
470 size = sizeof( *mp ) + ( scaled_width * scaled_height * 3 * 4 );
471 mp = (miptex32_t *)SafeMalloc( size, "CreateMip" );
474 mp->version = MIP32_VERSION;
476 size = width * height;
477 test = (paletteRGBA_t *)data;
480 if ( test->a != 255 ) {
481 mp->flags |= LittleLong( SURF_ALPHA_TEXTURE );
489 if ( scaled_width == width && scaled_height == height ) {
490 memcpy( scaled, data, width * height * 4 );
493 GL_ResampleTexture( data, width, height, scaled, scaled_width, scaled_height );
496 pos = (byte *)( mp + 1 );
499 while ( ( scaled_width >= 1 || scaled_height >= 1 ) && ( miplevel <= MIPLEVELS - 1 ) && ( !miplevel || mip ) )
501 if ( scaled_width < 1 ) {
504 if ( scaled_height < 1 ) {
508 if ( miplevel > 0 ) {
509 GL_MipMap( (byte *)out, (byte *)scaled, scaled_width, scaled_height );
513 memcpy( out, scaled, MAX_IMAGE_SIZE * MAX_IMAGE_SIZE * 4 );
516 mp->width[miplevel] = scaled_width;
517 mp->height[miplevel] = scaled_height;
518 mp->offsets[miplevel] = pos - ( (byte *)( mp ) );
519 memcpy( pos, out, scaled_width * scaled_height * 4 );
520 memcpy( scaled, out, MAX_IMAGE_SIZE * MAX_IMAGE_SIZE * 4 );
521 pos += scaled_width * scaled_height * 4;
529 *FinalSize = pos - ( (byte *)( mp ) );
538 $grab filename x y width height
541 void Cmd_Grab( void ){
547 GetScriptToken( false );
549 if ( token[0] == '/' || token[0] == '\\' ) {
550 sprintf( savename, "%s%s.pcx", gamedir, token + 1 );
553 sprintf( savename, "%spics/%s.pcx", gamedir, token );
557 if ( token[0] == '/' || token[0] == '\\' ) {
558 sprintf( dest, "%s.pcx", token + 1 );
561 sprintf( dest, "pics/%s.pcx", token );
568 GetScriptToken( false );
570 GetScriptToken( false );
572 GetScriptToken( false );
574 GetScriptToken( false );
577 if ( xl < 0 || yl < 0 || w < 0 || h < 0 || xl + w > byteimagewidth || yl + h > byteimageheight ) {
578 Error( "GrabPic: Bad size: %i, %i, %i, %i",xl,yl,w,h );
581 // crop it to the proper size
582 cropped = (byte *) SafeMalloc( w * h, "Cmd_Grab" );
583 for ( y = 0 ; y < h ; y++ )
585 memcpy( cropped + y * w, byteimage + ( y + yl ) * byteimagewidth + xl, w );
588 // save off the new image
589 printf( "saving %s\n", savename );
590 CreatePath( savename );
591 WritePCXfile( savename, cropped, w, h, lbmpalette );
600 $grab filename x y width height
603 void Cmd_Raw( void ){
609 GetScriptToken( false );
611 sprintf( savename, "%s%s.lmp", gamedir, token );
614 sprintf( dest, "%s.lmp", token );
619 GetScriptToken( false );
621 GetScriptToken( false );
623 GetScriptToken( false );
625 GetScriptToken( false );
628 if ( xl < 0 || yl < 0 || w < 0 || h < 0 || xl + w > byteimagewidth || yl + h > byteimageheight ) {
629 Error( "GrabPic: Bad size: %i, %i, %i, %i",xl,yl,w,h );
632 // crop it to the proper size
633 cropped = (byte *) SafeMalloc( w * h, "Cmd_Raw" );
634 for ( y = 0 ; y < h ; y++ )
636 memcpy( cropped + y * w, byteimage + ( y + yl ) * byteimagewidth + xl, w );
639 // save off the new image
640 printf( "saving %s\n", savename );
641 CreatePath( savename );
643 SaveFile( savename, cropped, w * h );
649 =============================================================================
653 =============================================================================
661 byte BestColor( int r, int g, int b, int start, int stop ){
664 int bestdistortion, distortion;
669 // let any color go to 0 as a last resort
671 bestdistortion = 256 * 256 * 4;
674 pal = colormap_palette + start * 3;
675 for ( i = start ; i <= stop ; i++ )
677 dr = r - (int)pal[0];
678 dg = g - (int)pal[1];
679 db = b - (int)pal[2];
681 distortion = dr * dr + dg * dg + db * db;
682 if ( distortion < bestdistortion ) {
684 return i; // perfect match
687 bestdistortion = distortion;
702 the brightes colormap is first in the table (FIXME: reverse this now?)
704 64 rows of 256 : lightmaps
705 256 rows of 256 : translucency table
708 void Cmd_Colormap( void ){
711 float frac, red, green, blue;
713 byte *cropped, *lump_p;
717 colormap_issued = true;
719 memcpy( colormap_palette, lbmpalette, 768 );
722 if ( !ScriptTokenAvailable() ) { // just setting colormap_issued
726 GetScriptToken( false );
727 sprintf( savename, "%spics/%s.pcx", gamedir, token );
730 sprintf( dest, "pics/%s.pcx", token );
737 brights = 1; // ignore 255 (transparent)
739 cropped = (byte *) SafeMalloc( ( levels + 256 ) * 256, "Cmd_ColorMap" );
743 for ( l = 0; l < levels; l++ )
745 frac = range - range * (float)l / ( levels - 1 );
746 for ( c = 0 ; c < 256 - brights ; c++ )
748 red = lbmpalette[c * 3];
749 green = lbmpalette[c * 3 + 1];
750 blue = lbmpalette[c * 3 + 2];
752 red = (int)( red * frac + 0.5 );
753 green = (int)( green * frac + 0.5 );
754 blue = (int)( blue * frac + 0.5 );
757 // note: 254 instead of 255 because 255 is the transparent color, and we
758 // don't want anything remapping to that
759 // don't use color 0, because NT can't remap that (or 255)
761 *lump_p++ = BestColor( red,green,blue, 1, 254 );
764 // fullbrights allways stay the same
765 for ( ; c < 256 ; c++ )
769 // 66% transparancy table
770 for ( l = 0; l < 255; l++ )
772 for ( c = 0 ; c < 255 ; c++ )
774 red = lbmpalette[c * 3] * 0.33 + lbmpalette[l * 3] * 0.66;
775 green = lbmpalette[c * 3 + 1] * 0.33 + lbmpalette[l * 3 + 1] * 0.66;
776 blue = lbmpalette[c * 3 + 2] * 0.33 + lbmpalette[l * 3 + 2] * 0.66;
778 *lump_p++ = BestColor( red,green,blue, 1, 254 );
782 for ( c = 0 ; c < 256 ; c++ )
785 // save off the new image
786 printf( "saving %s\n", savename );
787 CreatePath( savename );
788 WritePCXfile( savename, cropped, 256, levels + 256, lbmpalette );
794 =============================================================================
798 =============================================================================
803 int d_red, d_green, d_blue;
805 byte palmap[32][32][32];
806 qboolean palmap_built;
813 int FindColor( int r, int g, int b ){
835 bestcolor = BestColor( r, g, b, 0, 254 );
837 bestcolor = palmap[r >> 3][g >> 3][b >> 3];
844 void BuildPalmap( void ){
849 if ( palmap_built ) {
854 for ( r = 4 ; r < 256 ; r += 8 )
856 for ( g = 4 ; g < 256 ; g += 8 )
858 for ( b = 4 ; b < 256 ; b += 8 )
860 bestcolor = BestColor( r, g, b, 1, 254 );
861 palmap[r >> 3][g >> 3][b >> 3] = bestcolor;
867 if ( !colormap_issued ) {
868 Error( "You must issue a $colormap command first" );
878 byte AveragePixels( int count ){
890 for ( i = 0 ; i < count ; i++ )
894 r += lbmpalette[pix * 3];
895 g += lbmpalette[pix * 3 + 1];
896 b += lbmpalette[pix * 3 + 2];
910 // find the best color
912 bestcolor = FindColor( r, g, b );
915 pal = colormap_palette + bestcolor * 3;
916 d_red = r - (int)pal[0];
917 d_green = g - (int)pal[1];
918 d_blue = b - (int)pal[2];
948 mipparm_t mipparms[] =
950 // utility content attributes
951 {"pushpull",CONTENTS_PUSHPULL, pt_contents},
952 {"water", CONTENTS_WATER, pt_contents},
953 {"slime", CONTENTS_SLIME, pt_contents}, // mildly damaging
954 {"lava", CONTENTS_LAVA, pt_contents}, // very damaging
955 {"window", CONTENTS_WINDOW, pt_contents}, // solid, but doesn't eat internal textures
956 {"mist", CONTENTS_MIST, pt_contents}, // non-solid window
957 {"origin", CONTENTS_ORIGIN, pt_contents}, // center of rotating brushes
958 {"playerclip", CONTENTS_PLAYERCLIP, pt_contents},
959 {"monsterclip", CONTENTS_MONSTERCLIP, pt_contents},
961 // utility surface attributes
962 {"hint", SURF_HINT, pt_flags},
963 {"skip", SURF_SKIP, pt_flags},
964 {"light", SURF_LIGHT, pt_flagvalue}, // value is the light quantity
966 {"animspeed",SURF_ANIMSPEED, pt_flagvalue}, // value will hold the anim speed in fps
969 {"anim", 0, pt_animvalue}, // animname is the next animation
970 {"alt", 0, pt_altnamevalue}, // altname is the alternate texture
971 {"damage", 0, pt_damagenamevalue}, // damagename is the damage texture
972 {"scale", 0, pt_scale}, // next two values are for scale
974 {"detail", 0, pt_detail},
976 {"GL_ZERO", GL_ZERO, pt_gl},
977 {"GL_ONE", GL_ONE, pt_gl},
978 {"GL_SRC_COLOR", GL_SRC_COLOR, pt_gl},
979 {"GL_ONE_MINUS_SRC_COLOR", GL_ONE_MINUS_SRC_COLOR, pt_gl},
980 {"GL_DST_COLOR", GL_DST_COLOR, pt_gl},
981 {"GL_ONE_MINUS_DST_COLOR", GL_ONE_MINUS_DST_COLOR, pt_gl},
982 {"GL_SRC_ALPHA", GL_SRC_ALPHA, pt_gl},
983 {"GL_ONE_MINUS_SRC_ALPHA", GL_ONE_MINUS_SRC_ALPHA, pt_gl},
984 {"GL_DST_ALPHA", GL_DST_ALPHA, pt_gl},
985 {"GL_ONE_MINUS_DST_ALPHA", GL_ONE_MINUS_DST_ALPHA, pt_gl},
986 {"GL_SRC_ALPHA_SATURATE", GL_SRC_ALPHA_SATURATE, pt_gl},
989 {"slick", SURF_SLICK, pt_flags},
991 // drawing attributes
992 {"sky", SURF_SKY, pt_flags},
993 {"warping", SURF_WARP, pt_flags}, // only valid with 64x64 textures
994 {"trans33", SURF_TRANS33, pt_flags}, // translucent should allso set fullbright
995 {"trans66", SURF_TRANS66, pt_flags},
996 {"flowing", SURF_FLOWING, pt_flags}, // flow direction towards angle 0
997 {"nodraw", SURF_NODRAW, pt_flags}, // for clip textures and trigger textures
998 {"alpha", SURF_ALPHA_TEXTURE, pt_flags},
999 {"undulate", SURF_UNDULATE, pt_flags}, // rock surface up and down...
1000 {"skyreflect", SURF_SKYREFLECT, pt_flags}, // liquid will somewhat reflect the sky - not quite finished....
1002 {"material", SURF_MATERIAL, pt_materialvalue},
1003 {"metal", SURF_TYPE_METAL, pt_flags},
1004 {"stone", SURF_TYPE_STONE, pt_flags},
1005 {"wood", SURF_TYPE_WOOD, pt_flags},
1007 {"m_nomip", 0, pt_nomip},
1008 {"m_detail", 0, pt_detailer},
1010 {NULL, 0, pt_contents}
1017 $mip filename x y width height <OPTIONS>
1018 must be multiples of sixteen
1023 void Cmd_Mip( void ){
1024 int xl,yl,xh,yh,w,h;
1025 byte *dest, *source;
1026 int flags, value, contents;
1031 char damagename[128];
1032 byte buffer[MAX_IMAGE_SIZE * MAX_IMAGE_SIZE];
1033 unsigned bufferl[MAX_IMAGE_SIZE * MAX_IMAGE_SIZE];
1034 materialtype_t *mat;
1035 char filename[1024];
1036 unsigned *destl, *sourcel;
1037 int linedelta, x, y;
1041 float scale_x, scale_y;
1045 float dt_scale_x, dt_scale_y;
1048 int dt_src_blend_mode, dt_dst_blend_mode;
1052 GetScriptToken( false );
1053 strcpy( lumpname, token );
1055 GetScriptToken( false );
1057 GetScriptToken( false );
1059 GetScriptToken( false );
1061 GetScriptToken( false );
1068 if ( ( w & 15 ) || ( h & 15 ) ) {
1069 Error( "line %i: miptex sizes must be multiples of 16", scriptline );
1078 altname[0] = animname[0] = damagename[0] = 0;
1080 scale_x = scale_y = 0.5;
1084 dt_scale_x = dt_scale_y = 0.0;
1087 dt_src_blend_mode = dt_dst_blend_mode = 0;
1089 // get optional flags and values
1090 while ( ScriptTokenAvailable() )
1092 GetScriptToken( false );
1094 for ( mp = mipparms ; mp->name ; mp++ )
1096 if ( !strcmp( mp->name, token ) ) {
1100 GetScriptToken( false ); // specify the next animation frame
1101 strcpy( animname, token );
1103 case pt_altnamevalue:
1104 GetScriptToken( false ); // specify the alternate texture
1105 strcpy( altname, token );
1107 case pt_damagenamevalue:
1108 GetScriptToken( false ); // specify the damage texture
1109 strcpy( damagename, token );
1115 contents |= mp->flags;
1119 GetScriptToken( false ); // specify the light value
1120 value = atoi( token );
1122 case pt_materialvalue:
1123 GetScriptToken( false );
1124 for ( mat = materialtypes ; mat->name ; mat++ )
1126 if ( !strcmp( mat->name, token ) ) {
1127 // assumes SURF_MATERIAL is in top 8 bits
1128 flags = ( flags & 0x0FFFFFF ) | ( mat->value << 24 );
1134 GetScriptToken( false ); // specify the x scale
1135 scale_x = atof( token );
1136 GetScriptToken( false ); // specify the y scale
1137 scale_y = atof( token );
1145 flags2 |= MIP32_DETAILER_FLAG2;
1149 flags2 |= MIP32_NOMIP_FLAG2;
1153 GetScriptToken( false );
1154 strcpy( dt_name, token );
1155 GetScriptToken( false );
1156 dt_scale_x = atof( token );
1157 GetScriptToken( false );
1158 dt_scale_y = atof( token );
1159 GetScriptToken( false );
1160 dt_u = atof( token );
1161 GetScriptToken( false );
1162 dt_v = atof( token );
1163 GetScriptToken( false );
1164 dt_alpha = atof( token );
1165 GetScriptToken( false );
1166 for ( mp = mipparms ; mp->name ; mp++ )
1168 if ( !strcmp( mp->name, token ) ) {
1169 if ( mp->type == pt_gl ) {
1170 dt_src_blend_mode = mp->flags;
1176 Error( "line %i: invalid gl blend mode %s", scriptline, token );
1178 GetScriptToken( false );
1179 for ( mp = mipparms ; mp->name ; mp++ )
1181 if ( !strcmp( mp->name, token ) ) {
1182 if ( mp->type == pt_gl ) {
1183 dt_dst_blend_mode = mp->flags;
1189 Error( "line %i: invalid gl blend mode %s", scriptline, token );
1197 Error( "line %i: unknown parm %s", scriptline, token );
1202 return; // textures are only released by $maps
1207 if ( xh * yh > MAX_IMAGE_SIZE * MAX_IMAGE_SIZE ) {
1208 Error( "line %i image %s: image is too big!", scriptline, lumpname );
1211 if ( TrueColorImage ) {
1212 if ( xl >= longimagewidth || xh > longimagewidth ||
1213 yl >= longimageheight || yh > longimageheight ) {
1214 Error( "line %i image %s: bad clip dimmensions (%d,%d) (%d,%d) > image (%d,%d)", scriptline, lumpname, xl,yl,w,h,longimagewidth,longimageheight );
1217 sourcel = longimage + ( yl * longimagewidth ) + xl;
1219 linedelta = ( longimagewidth - w );
1221 for ( y = yl ; y < yh ; y++ )
1223 for ( x = xl ; x < xh ; x++ )
1225 *destl++ = *sourcel++; // RGBA
1227 sourcel += linedelta;
1230 qtex32 = CreateMip32( bufferl, w, h, &size, true );
1232 qtex32->flags |= LittleLong( flags );
1233 qtex32->flags2 |= LittleLong( flags2 );
1234 qtex32->contents = LittleLong( contents );
1235 qtex32->value = LittleLong( value );
1236 qtex32->scale_x = scale_x;
1237 qtex32->scale_y = scale_y;
1238 qtex32->mip_scale = mip_scale;
1239 sprintf( qtex32->name, "%s/%s", mip_prefix, lumpname );
1240 if ( animname[0] ) {
1241 sprintf( qtex32->animname, "%s/%s", mip_prefix, animname );
1244 sprintf( qtex32->altname, "%s/%s", mip_prefix, altname );
1246 if ( damagename[0] ) {
1247 sprintf( qtex32->damagename, "%s/%s", mip_prefix, damagename );
1249 if ( dt_name[0] & ( ( flags2 & MIP32_DETAILER_FLAG2 ) == 0 ) ) {
1250 sprintf( qtex32->dt_name, "%s/%s", mip_prefix, dt_name );
1251 qtex32->dt_scale_x = dt_scale_x;
1252 qtex32->dt_scale_y = dt_scale_y;
1253 qtex32->dt_u = dt_u;
1254 qtex32->dt_v = dt_v;
1255 qtex32->dt_alpha = dt_alpha;
1256 qtex32->dt_src_blend_mode = dt_src_blend_mode;
1257 qtex32->dt_dst_blend_mode = dt_dst_blend_mode;
1263 sprintf( filename, "%stextures/%s/%s.m32", g_outputDir, mip_prefix, lumpname );
1264 if ( qtex32->flags & ( SURF_ALPHA_TEXTURE ) ) {
1265 printf( "writing %s with ALPHA\n", filename );
1268 printf( "writing %s\n", filename );
1270 SaveFile( filename, (byte *)qtex32, size );
1276 if ( xl >= byteimagewidth || xh > byteimagewidth ||
1277 yl >= byteimageheight || yh > byteimageheight ) {
1278 Error( "line %i: bad clip dimmensions (%d,%d) (%d,%d) > image (%d,%d)", scriptline, xl,yl,w,h,byteimagewidth,byteimageheight );
1281 source = byteimage + yl * byteimagewidth + xl;
1283 linedelta = byteimagewidth - w;
1285 for ( y = yl ; y < yh ; y++ )
1287 for ( x = xl ; x < xh ; x++ )
1289 *dest++ = *source++;
1291 source += linedelta;
1294 qtex = CreateMip( buffer, w, h, lbmpalette, &size, true );
1296 qtex->flags = LittleLong( flags );
1297 qtex->contents = LittleLong( contents );
1298 qtex->value = LittleLong( value );
1299 sprintf( qtex->name, "%s/%s", mip_prefix, lumpname );
1300 if ( animname[0] ) {
1301 sprintf( qtex->animname, "%s/%s", mip_prefix, animname );
1307 sprintf( filename, "%stextures/%s/%s.m8", g_outputDir, mip_prefix, lumpname );
1308 printf( "writing %s\n", filename );
1309 SaveFile( filename, (byte *)qtex, size );
1320 void Cmd_Mippal( void ){
1321 colormap_issued = true;
1326 memcpy( colormap_palette, lbmpalette, 768 );
1337 void Cmd_Mipdir( void ){
1338 char filename[1024];
1340 GetScriptToken( false );
1341 strcpy( mip_prefix, token );
1342 // create the directory if needed
1343 sprintf( filename, "%stextures", g_outputDir );
1344 Q_mkdir( filename );
1345 sprintf( filename, "%stextures/%s", g_outputDir, mip_prefix );
1346 Q_mkdir( filename );
1351 =============================================================================
1353 ENVIRONMENT MAP GRABBING
1355 Creates six pcx files from tga files without any palette edge seams
1356 also copies the tga files for GL rendering.
1357 =============================================================================
1360 // 3dstudio environment map suffixes
1361 char *suf[6] = {"rt", "ft", "lf", "bk", "up", "dn"};
1368 void Cmd_Environment( void ){
1371 byte image[256 * 256];
1374 GetScriptToken( false );
1377 for ( i = 0 ; i < 6 ; i++ )
1379 sprintf( name, "env/%s%s.pcx", token, suf[i] );
1380 ReleaseFile( name );
1381 sprintf( name, "env/%s%s.tga", token, suf[i] );
1382 ReleaseFile( name );
1389 sprintf( name, "%senv/", gamedir );
1392 // convert the images
1393 for ( i = 0 ; i < 6 ; i++ )
1395 sprintf( name, "%senv/%s%s.tga", gamedir, token, suf[i] );
1396 printf( "loading %s...\n", name );
1397 LoadTGA( name, &tga, NULL, NULL );
1399 for ( y = 0 ; y < 256 ; y++ )
1401 for ( x = 0 ; x < 256 ; x++ )
1403 image[y * 256 + x] = FindColor( tga[( y * 256 + x ) * 4 + 0],tga[( y * 256 + x ) * 4 + 1],tga[( y * 256 + x ) * 4 + 2] );
1407 sprintf( name, "%senv/%s%s.pcx", gamedir, token, suf[i] );
1408 if ( FileTime( name ) != -1 ) {
1409 printf( "%s already exists, not overwriting.\n", name );
1412 WritePCXfile( name, image, 256, 256, colormap_palette );