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 char mip_prefix[1024]; // directory to dump the textures in
40 qboolean colormap_issued;
41 byte colormap_palette[768];
45 unsigned total_textures = 0;
47 #define MAX_IMAGE_SIZE 512
54 Replaces all 0 bytes in an image with the closest palette entry.
55 This is because NT won't let us change index 0, so any palette
56 animation leaves those pixels untouched.
59 void RemapZero( byte *pixels, byte *palette, int width, int height ){
66 for ( i = 1 ; i < 255 ; i++ )
68 value = palette[i * 3 + 0] + palette[i * 3 + 1] + palette[i * 3 + 2];
76 for ( i = 0 ; i < c ; i++ )
77 if ( pixels[i] == 0 ) {
85 // ********************************************************************
86 // ** Mip Map Pre-Processing Routines
87 // ********************************************************************
89 #define intensity_value 1
91 static unsigned image_pal[256];
95 long palette_r[256], palette_g[256], palette_b[256];
96 long last_r[MAX_LAST],last_g[MAX_LAST],last_b[MAX_LAST], last_i[MAX_LAST], last_place;
100 void PrepareConvert( unsigned *palette ){
103 for ( i = 0; i < 256; i++ )
105 palette_r[i] = ( palette[i] & 0x00ff0000 ) >> 16;
106 palette_g[i] = ( palette[i] & 0x0000ff00 ) >> 8;
107 palette_b[i] = ( palette[i] & 0x000000ff );
110 for ( i = 0; i < MAX_LAST; i++ )
116 int ConvertTrueColorToPal( unsigned r, unsigned g, unsigned b ){
121 long dr, dg, db, biggest_delta;
123 for ( i = 0; i < MAX_LAST; i++ )
124 if ( r == last_r[i] && g == last_g[i] && b == last_b[i] ) {
129 min_dist = 256 * 256 + 256 * 256 + 256 * 256;
130 biggest_delta = 256 * 256;
133 for ( i = 0; i < 256; i++ )
135 dr = abs( palette_r[i] - r );
136 if ( dr > biggest_delta ) {
139 dg = abs( palette_g[i] - g );
140 if ( dg > biggest_delta ) {
143 db = abs( palette_b[i] - b );
144 if ( db > biggest_delta ) {
148 dist = dr * dr + dg * dg + db * db;
149 if ( dist < min_dist ) {
152 if ( min_dist == 0 ) {
163 if ( dist < biggest_delta ) {
164 biggest_delta = dist;
170 if ( last_place >= MAX_LAST ) {
174 last_r[last_place] = r;
175 last_g[last_place] = g;
176 last_b[last_place] = b;
177 last_i[last_place] = min_index;
183 void GL_ResampleTexture8P( byte *in, int inwidth, int inheight, byte *out,
184 int outwidth, int outheight, palette_t *palette ){
186 byte *inrow, *inrow2;
187 unsigned frac, fracstep;
188 unsigned p1[1024], p2[1024], *p1p, *p2p;
189 palette_t *c1,*c2,*c3,*c4;
192 fracstep = inwidth * 0x10000 / outwidth;
194 frac = fracstep >> 2;
195 for ( i = 0 ; i < outwidth ; i++ )
200 frac = 3 * ( fracstep >> 2 );
201 for ( i = 0 ; i < outwidth ; i++ )
209 for ( i = 0 ; i < outheight ; i++ ) //, out += outwidth)
211 inrow = in + inwidth * (int)( ( i + 0.25 ) * inheight / outheight );
212 inrow2 = in + inwidth * (int)( ( i + 0.75 ) * inheight / outheight );
216 for ( j = 0 ; j < outwidth ; j++ )
218 c1 = &palette[*( (byte *)inrow + ( *p1p ) )];
219 c2 = &palette[*( (byte *)inrow + ( *p2p ) )];
220 c3 = &palette[*( (byte *)inrow2 + ( *p1p++ ) )];
221 c4 = &palette[*( (byte *)inrow2 + ( *p2p++ ) )];
223 r = ( (unsigned)c1->r + (unsigned)c2->r + (unsigned)c3->r + (unsigned)c4->r ) >> 2;
224 g = ( (unsigned)c1->g + (unsigned)c2->g + (unsigned)c3->g + (unsigned)c4->g ) >> 2;
225 b = ( (unsigned)c1->b + (unsigned)c2->b + (unsigned)c3->b + (unsigned)c4->b ) >> 2;
227 *out++ = ConvertTrueColorToPal( r,g,b );
232 void GL_MipMap8P( byte *out, byte *in, int width, int height, palette_t *palette ){
234 palette_t *c1,*c2,*c3,*c4;
238 memset( out, 0, 256 * 256 );
242 for ( i = 0; i < height; i += 2, in += width )
244 for ( j = 0; j < width; j += 2 )
246 c1 = &palette[in[0]];
247 c3 = &palette[in[width]];
249 c2 = &palette[in[0]];
250 c4 = &palette[in[width]];
253 r = ( (unsigned)c1->r + (unsigned)c2->r + (unsigned)c3->r + (unsigned)c4->r ) >> 2;
254 g = ( (unsigned)c1->g + (unsigned)c2->g + (unsigned)c3->g + (unsigned)c4->g ) >> 2;
255 b = ( (unsigned)c1->b + (unsigned)c2->b + (unsigned)c3->b + (unsigned)c4->b ) >> 2;
257 *out++ = ConvertTrueColorToPal( r, g, b );
263 miptex_t *CreateMip( byte *data, unsigned width, unsigned height, byte *palette, int *FinalSize, qboolean mip ){
264 int scaled_width, scaled_height;
266 byte intensitytable[256];
267 byte scaled[256 * 256];
274 for ( i = 0 ; i < 256 ; i++ )
276 j = i * intensity_value;
280 intensitytable[i] = j;
283 for ( scaled_width = 1 ; scaled_width < width ; scaled_width <<= 1 )
285 if ( 1 && scaled_width > width && 1 ) {
288 for ( scaled_height = 1 ; scaled_height < height ; scaled_height <<= 1 )
290 if ( 1 && scaled_height > height && 1 ) {
294 // don't ever bother with >256 textures
295 if ( scaled_width > 256 ) {
298 if ( scaled_height > 256 ) {
302 if ( scaled_width < 1 ) {
305 if ( scaled_height < 1 ) {
309 size = sizeof( *mp ) + ( scaled_width * scaled_height * 3 );
310 mp = (miptex_t *)SafeMalloc( size, "CreateMip" );
313 mp->version = MIP_VERSION;
315 for ( i = j = 0; i < 256; i++,j += 3 )
317 mp->palette[i].r = r = intensitytable[palette[j]];
318 mp->palette[i].g = g = intensitytable[palette[j + 1]];
319 mp->palette[i].b = b = intensitytable[palette[j + 2]];
320 image_pal[i] = 0xff000000 | ( r << 16 ) | ( g << 8 ) | ( b );
323 PrepareConvert( image_pal );
325 if ( scaled_width == width && scaled_height == height ) {
326 memcpy( scaled, data, width * height );
329 GL_ResampleTexture8P( data, width, height, scaled, scaled_width, scaled_height, mp->palette );
332 pos = (byte *)( mp + 1 );
335 while ( ( scaled_width >= 1 || scaled_height >= 1 ) && ( miplevel <= MIPLEVELS - 1 ) && ( !miplevel || mip ) )
337 if ( scaled_width < 1 ) {
340 if ( scaled_height < 1 ) {
344 if ( miplevel > 0 ) {
345 GL_MipMap8P( out, (byte *)scaled, scaled_width, scaled_height, mp->palette );
348 memcpy( out, scaled, 256 * 256 );
351 mp->width[miplevel] = scaled_width;
352 mp->height[miplevel] = scaled_height;
353 mp->offsets[miplevel] = pos - ( (byte *)( mp ) );
354 memcpy( pos, out, scaled_width * scaled_height );
355 memcpy( scaled, out, 256 * 256 );
356 pos += scaled_width * scaled_height;
364 *FinalSize = pos - ( (byte *)( mp ) );
370 void GL_ResampleTexture( unsigned *in, int inwidth, int inheight, unsigned *out, int outwidth, int outheight ){
372 unsigned *inrow, *inrow2;
373 unsigned frac, fracstep;
374 unsigned p1[1024], p2[1024];
375 byte *pix1, *pix2, *pix3, *pix4;
377 fracstep = inwidth * 0x10000 / outwidth;
379 frac = fracstep >> 2;
380 for ( i = 0 ; i < outwidth ; i++ )
382 p1[i] = 4 * ( frac >> 16 );
385 frac = 3 * ( fracstep >> 2 );
386 for ( i = 0 ; i < outwidth ; i++ )
388 p2[i] = 4 * ( frac >> 16 );
392 for ( i = 0 ; i < outheight ; i++, out += outwidth )
394 inrow = in + inwidth * (int)( ( i + 0.25 ) * inheight / outheight );
395 inrow2 = in + inwidth * (int)( ( i + 0.75 ) * inheight / outheight );
396 frac = fracstep >> 1;
397 for ( j = 0 ; j < outwidth ; j++ )
399 pix1 = (byte *)inrow + p1[j];
400 pix2 = (byte *)inrow + p2[j];
401 pix3 = (byte *)inrow2 + p1[j];
402 pix4 = (byte *)inrow2 + p2[j];
403 ( (byte *)( out + j ) )[0] = ( pix1[0] + pix2[0] + pix3[0] + pix4[0] ) >> 2;
404 ( (byte *)( out + j ) )[1] = ( pix1[1] + pix2[1] + pix3[1] + pix4[1] ) >> 2;
405 ( (byte *)( out + j ) )[2] = ( pix1[2] + pix2[2] + pix3[2] + pix4[2] ) >> 2;
406 ( (byte *)( out + j ) )[3] = ( pix1[3] + pix2[3] + pix3[3] + pix4[3] ) >> 2;
411 void GL_MipMap( byte *out, byte *in, int width, int height ){
416 for ( i = 0 ; i < height ; i++, in += width )
418 for ( j = 0 ; j < width ; j += 8, out += 4, in += 8 )
420 out[0] = ( in[0] + in[4] + in[width + 0] + in[width + 4] ) >> 2;
421 out[1] = ( in[1] + in[5] + in[width + 1] + in[width + 5] ) >> 2;
422 out[2] = ( in[2] + in[6] + in[width + 2] + in[width + 6] ) >> 2;
423 out[3] = ( in[3] + in[7] + in[width + 3] + in[width + 7] ) >> 2;
428 miptex32_t *CreateMip32( unsigned *data, unsigned width, unsigned height, int *FinalSize, qboolean mip ){
429 int scaled_width, scaled_height;
430 unsigned scaled[MAX_IMAGE_SIZE * MAX_IMAGE_SIZE];
431 unsigned out[MAX_IMAGE_SIZE * MAX_IMAGE_SIZE];
438 for ( scaled_width = 1 ; scaled_width < width ; scaled_width <<= 1 )
440 if ( 1 && scaled_width > width && 1 ) {
443 for ( scaled_height = 1 ; scaled_height < height ; scaled_height <<= 1 )
445 if ( 1 && scaled_height > height && 1 ) {
449 // don't ever bother with >256 textures
450 if ( scaled_width > MAX_IMAGE_SIZE ) {
451 scaled_width = MAX_IMAGE_SIZE;
453 if ( scaled_height > MAX_IMAGE_SIZE ) {
454 scaled_height = MAX_IMAGE_SIZE;
457 if ( scaled_width < 1 ) {
460 if ( scaled_height < 1 ) {
464 size = sizeof( *mp ) + ( scaled_width * scaled_height * 3 * 4 );
465 mp = (miptex32_t *)SafeMalloc( size, "CreateMip" );
468 mp->version = MIP32_VERSION;
470 size = width * height;
471 test = (paletteRGBA_t *)data;
474 if ( test->a != 255 ) {
475 mp->flags |= LittleLong( SURF_ALPHA_TEXTURE );
483 if ( scaled_width == width && scaled_height == height ) {
484 memcpy( scaled, data, width * height * 4 );
487 GL_ResampleTexture( data, width, height, scaled, scaled_width, scaled_height );
490 pos = (byte *)( mp + 1 );
493 while ( ( scaled_width >= 1 || scaled_height >= 1 ) && ( miplevel <= MIPLEVELS - 1 ) && ( !miplevel || mip ) )
495 if ( scaled_width < 1 ) {
498 if ( scaled_height < 1 ) {
502 if ( miplevel > 0 ) {
503 GL_MipMap( (byte *)out, (byte *)scaled, scaled_width, scaled_height );
507 memcpy( out, scaled, MAX_IMAGE_SIZE * MAX_IMAGE_SIZE * 4 );
510 mp->width[miplevel] = scaled_width;
511 mp->height[miplevel] = scaled_height;
512 mp->offsets[miplevel] = pos - ( (byte *)( mp ) );
513 memcpy( pos, out, scaled_width * scaled_height * 4 );
514 memcpy( scaled, out, MAX_IMAGE_SIZE * MAX_IMAGE_SIZE * 4 );
515 pos += scaled_width * scaled_height * 4;
523 *FinalSize = pos - ( (byte *)( mp ) );
532 $grab filename x y width height
535 void Cmd_Grab( void ){
541 GetScriptToken( false );
543 if ( token[0] == '/' || token[0] == '\\' ) {
544 sprintf( savename, "%s%s.pcx", gamedir, token + 1 );
547 sprintf( savename, "%spics/%s.pcx", gamedir, token );
551 if ( token[0] == '/' || token[0] == '\\' ) {
552 sprintf( dest, "%s.pcx", token + 1 );
555 sprintf( dest, "pics/%s.pcx", token );
562 GetScriptToken( false );
564 GetScriptToken( false );
566 GetScriptToken( false );
568 GetScriptToken( false );
571 if ( xl < 0 || yl < 0 || w < 0 || h < 0 || xl + w > byteimagewidth || yl + h > byteimageheight ) {
572 Error( "GrabPic: Bad size: %i, %i, %i, %i",xl,yl,w,h );
575 // crop it to the proper size
576 cropped = (byte *) SafeMalloc( w * h, "Cmd_Grab" );
577 for ( y = 0 ; y < h ; y++ )
579 memcpy( cropped + y * w, byteimage + ( y + yl ) * byteimagewidth + xl, w );
582 // save off the new image
583 printf( "saving %s\n", savename );
584 CreatePath( savename );
585 WritePCXfile( savename, cropped, w, h, lbmpalette );
594 $grab filename x y width height
597 void Cmd_Raw( void ){
603 GetScriptToken( false );
605 sprintf( savename, "%s%s.lmp", gamedir, token );
608 sprintf( dest, "%s.lmp", token );
613 GetScriptToken( false );
615 GetScriptToken( false );
617 GetScriptToken( false );
619 GetScriptToken( false );
622 if ( xl < 0 || yl < 0 || w < 0 || h < 0 || xl + w > byteimagewidth || yl + h > byteimageheight ) {
623 Error( "GrabPic: Bad size: %i, %i, %i, %i",xl,yl,w,h );
626 // crop it to the proper size
627 cropped = (byte *) SafeMalloc( w * h, "Cmd_Raw" );
628 for ( y = 0 ; y < h ; y++ )
630 memcpy( cropped + y * w, byteimage + ( y + yl ) * byteimagewidth + xl, w );
633 // save off the new image
634 printf( "saving %s\n", savename );
635 CreatePath( savename );
637 SaveFile( savename, cropped, w * h );
643 =============================================================================
647 =============================================================================
655 byte BestColor( int r, int g, int b, int start, int stop ){
658 int bestdistortion, distortion;
663 // let any color go to 0 as a last resort
665 bestdistortion = 256 * 256 * 4;
668 pal = colormap_palette + start * 3;
669 for ( i = start ; i <= stop ; i++ )
671 dr = r - (int)pal[0];
672 dg = g - (int)pal[1];
673 db = b - (int)pal[2];
675 distortion = dr * dr + dg * dg + db * db;
676 if ( distortion < bestdistortion ) {
678 return i; // perfect match
681 bestdistortion = distortion;
696 the brightes colormap is first in the table (FIXME: reverse this now?)
698 64 rows of 256 : lightmaps
699 256 rows of 256 : translucency table
702 void Cmd_Colormap( void ){
705 float frac, red, green, blue;
707 byte *cropped, *lump_p;
711 colormap_issued = true;
713 memcpy( colormap_palette, lbmpalette, 768 );
716 if ( !ScriptTokenAvailable() ) { // just setting colormap_issued
720 GetScriptToken( false );
721 sprintf( savename, "%spics/%s.pcx", gamedir, token );
724 sprintf( dest, "pics/%s.pcx", token );
731 brights = 1; // ignore 255 (transparent)
733 cropped = (byte *) SafeMalloc( ( levels + 256 ) * 256, "Cmd_ColorMap" );
737 for ( l = 0; l < levels; l++ )
739 frac = range - range * (float)l / ( levels - 1 );
740 for ( c = 0 ; c < 256 - brights ; c++ )
742 red = lbmpalette[c * 3];
743 green = lbmpalette[c * 3 + 1];
744 blue = lbmpalette[c * 3 + 2];
746 red = (int)( red * frac + 0.5 );
747 green = (int)( green * frac + 0.5 );
748 blue = (int)( blue * frac + 0.5 );
751 // note: 254 instead of 255 because 255 is the transparent color, and we
752 // don't want anything remapping to that
753 // don't use color 0, because NT can't remap that (or 255)
755 *lump_p++ = BestColor( red,green,blue, 1, 254 );
758 // fullbrights allways stay the same
759 for ( ; c < 256 ; c++ )
763 // 66% transparancy table
764 for ( l = 0; l < 255; l++ )
766 for ( c = 0 ; c < 255 ; c++ )
768 red = lbmpalette[c * 3] * 0.33 + lbmpalette[l * 3] * 0.66;
769 green = lbmpalette[c * 3 + 1] * 0.33 + lbmpalette[l * 3 + 1] * 0.66;
770 blue = lbmpalette[c * 3 + 2] * 0.33 + lbmpalette[l * 3 + 2] * 0.66;
772 *lump_p++ = BestColor( red,green,blue, 1, 254 );
776 for ( c = 0 ; c < 256 ; c++ )
779 // save off the new image
780 printf( "saving %s\n", savename );
781 CreatePath( savename );
782 WritePCXfile( savename, cropped, 256, levels + 256, lbmpalette );
788 =============================================================================
792 =============================================================================
797 int d_red, d_green, d_blue;
799 byte palmap[32][32][32];
800 qboolean palmap_built;
807 int FindColor( int r, int g, int b ){
829 bestcolor = BestColor( r, g, b, 0, 254 );
831 bestcolor = palmap[r >> 3][g >> 3][b >> 3];
838 void BuildPalmap( void ){
843 if ( palmap_built ) {
848 for ( r = 4 ; r < 256 ; r += 8 )
850 for ( g = 4 ; g < 256 ; g += 8 )
852 for ( b = 4 ; b < 256 ; b += 8 )
854 bestcolor = BestColor( r, g, b, 1, 254 );
855 palmap[r >> 3][g >> 3][b >> 3] = bestcolor;
861 if ( !colormap_issued ) {
862 Error( "You must issue a $colormap command first" );
872 byte AveragePixels( int count ){
884 for ( i = 0 ; i < count ; i++ )
888 r += lbmpalette[pix * 3];
889 g += lbmpalette[pix * 3 + 1];
890 b += lbmpalette[pix * 3 + 2];
904 // find the best color
906 bestcolor = FindColor( r, g, b );
909 pal = colormap_palette + bestcolor * 3;
910 d_red = r - (int)pal[0];
911 d_green = g - (int)pal[1];
912 d_blue = b - (int)pal[2];
942 mipparm_t mipparms[] =
944 // utility content attributes
945 {"pushpull",CONTENTS_PUSHPULL, pt_contents},
946 {"water", CONTENTS_WATER, pt_contents},
947 {"slime", CONTENTS_SLIME, pt_contents}, // mildly damaging
948 {"lava", CONTENTS_LAVA, pt_contents}, // very damaging
949 {"window", CONTENTS_WINDOW, pt_contents}, // solid, but doesn't eat internal textures
950 {"mist", CONTENTS_MIST, pt_contents}, // non-solid window
951 {"origin", CONTENTS_ORIGIN, pt_contents}, // center of rotating brushes
952 {"playerclip", CONTENTS_PLAYERCLIP, pt_contents},
953 {"monsterclip", CONTENTS_MONSTERCLIP, pt_contents},
955 // utility surface attributes
956 {"hint", SURF_HINT, pt_flags},
957 {"skip", SURF_SKIP, pt_flags},
958 {"light", SURF_LIGHT, pt_flagvalue}, // value is the light quantity
960 {"animspeed",SURF_ANIMSPEED, pt_flagvalue}, // value will hold the anim speed in fps
963 {"anim", 0, pt_animvalue}, // animname is the next animation
964 {"alt", 0, pt_altnamevalue}, // altname is the alternate texture
965 {"damage", 0, pt_damagenamevalue}, // damagename is the damage texture
966 {"scale", 0, pt_scale}, // next two values are for scale
968 {"detail", 0, pt_detail},
970 {"GL_ZERO", GL_ZERO, pt_gl},
971 {"GL_ONE", GL_ONE, pt_gl},
972 {"GL_SRC_COLOR", GL_SRC_COLOR, pt_gl},
973 {"GL_ONE_MINUS_SRC_COLOR", GL_ONE_MINUS_SRC_COLOR, pt_gl},
974 {"GL_DST_COLOR", GL_DST_COLOR, pt_gl},
975 {"GL_ONE_MINUS_DST_COLOR", GL_ONE_MINUS_DST_COLOR, pt_gl},
976 {"GL_SRC_ALPHA", GL_SRC_ALPHA, pt_gl},
977 {"GL_ONE_MINUS_SRC_ALPHA", GL_ONE_MINUS_SRC_ALPHA, pt_gl},
978 {"GL_DST_ALPHA", GL_DST_ALPHA, pt_gl},
979 {"GL_ONE_MINUS_DST_ALPHA", GL_ONE_MINUS_DST_ALPHA, pt_gl},
980 {"GL_SRC_ALPHA_SATURATE", GL_SRC_ALPHA_SATURATE, pt_gl},
983 {"slick", SURF_SLICK, pt_flags},
985 // drawing attributes
986 {"sky", SURF_SKY, pt_flags},
987 {"warping", SURF_WARP, pt_flags}, // only valid with 64x64 textures
988 {"trans33", SURF_TRANS33, pt_flags}, // translucent should allso set fullbright
989 {"trans66", SURF_TRANS66, pt_flags},
990 {"flowing", SURF_FLOWING, pt_flags}, // flow direction towards angle 0
991 {"nodraw", SURF_NODRAW, pt_flags}, // for clip textures and trigger textures
992 {"alpha", SURF_ALPHA_TEXTURE, pt_flags},
993 {"undulate", SURF_UNDULATE, pt_flags}, // rock surface up and down...
994 {"skyreflect", SURF_SKYREFLECT, pt_flags}, // liquid will somewhat reflect the sky - not quite finished....
996 {"material", SURF_MATERIAL, pt_materialvalue},
997 {"metal", SURF_TYPE_METAL, pt_flags},
998 {"stone", SURF_TYPE_STONE, pt_flags},
999 {"wood", SURF_TYPE_WOOD, pt_flags},
1001 {"m_nomip", 0, pt_nomip},
1002 {"m_detail", 0, pt_detailer},
1004 {NULL, 0, pt_contents}
1011 $mip filename x y width height <OPTIONS>
1012 must be multiples of sixteen
1017 void Cmd_Mip( void ){
1018 int xl,yl,xh,yh,w,h;
1019 byte *dest, *source;
1020 int flags, value, contents;
1025 char damagename[128];
1026 byte buffer[MAX_IMAGE_SIZE * MAX_IMAGE_SIZE];
1027 unsigned bufferl[MAX_IMAGE_SIZE * MAX_IMAGE_SIZE];
1028 materialtype_t *mat;
1029 char filename[1024];
1030 unsigned *destl, *sourcel;
1031 int linedelta, x, y;
1035 float scale_x, scale_y;
1039 float dt_scale_x, dt_scale_y;
1042 int dt_src_blend_mode, dt_dst_blend_mode;
1046 GetScriptToken( false );
1047 strcpy( lumpname, token );
1049 GetScriptToken( false );
1051 GetScriptToken( false );
1053 GetScriptToken( false );
1055 GetScriptToken( false );
1062 if ( ( w & 15 ) || ( h & 15 ) ) {
1063 Error( "line %i: miptex sizes must be multiples of 16", scriptline );
1072 altname[0] = animname[0] = damagename[0] = 0;
1074 scale_x = scale_y = 0.5;
1078 dt_scale_x = dt_scale_y = 0.0;
1081 dt_src_blend_mode = dt_dst_blend_mode = 0;
1083 // get optional flags and values
1084 while ( ScriptTokenAvailable() )
1086 GetScriptToken( false );
1088 for ( mp = mipparms ; mp->name ; mp++ )
1090 if ( !strcmp( mp->name, token ) ) {
1094 GetScriptToken( false ); // specify the next animation frame
1095 strcpy( animname, token );
1097 case pt_altnamevalue:
1098 GetScriptToken( false ); // specify the alternate texture
1099 strcpy( altname, token );
1101 case pt_damagenamevalue:
1102 GetScriptToken( false ); // specify the damage texture
1103 strcpy( damagename, token );
1109 contents |= mp->flags;
1113 GetScriptToken( false ); // specify the light value
1114 value = atoi( token );
1116 case pt_materialvalue:
1117 GetScriptToken( false );
1118 for ( mat = materialtypes ; mat->name ; mat++ )
1120 if ( !strcmp( mat->name, token ) ) {
1121 // assumes SURF_MATERIAL is in top 8 bits
1122 flags = ( flags & 0x0FFFFFF ) | ( mat->value << 24 );
1128 GetScriptToken( false ); // specify the x scale
1129 scale_x = atof( token );
1130 GetScriptToken( false ); // specify the y scale
1131 scale_y = atof( token );
1139 flags2 |= MIP32_DETAILER_FLAG2;
1143 flags2 |= MIP32_NOMIP_FLAG2;
1147 GetScriptToken( false );
1148 strcpy( dt_name, token );
1149 GetScriptToken( false );
1150 dt_scale_x = atof( token );
1151 GetScriptToken( false );
1152 dt_scale_y = atof( token );
1153 GetScriptToken( false );
1154 dt_u = atof( token );
1155 GetScriptToken( false );
1156 dt_v = atof( token );
1157 GetScriptToken( false );
1158 dt_alpha = atof( token );
1159 GetScriptToken( false );
1160 for ( mp = mipparms ; mp->name ; mp++ )
1162 if ( !strcmp( mp->name, token ) ) {
1163 if ( mp->type == pt_gl ) {
1164 dt_src_blend_mode = mp->flags;
1170 Error( "line %i: invalid gl blend mode %s", scriptline, token );
1172 GetScriptToken( false );
1173 for ( mp = mipparms ; mp->name ; mp++ )
1175 if ( !strcmp( mp->name, token ) ) {
1176 if ( mp->type == pt_gl ) {
1177 dt_dst_blend_mode = mp->flags;
1183 Error( "line %i: invalid gl blend mode %s", scriptline, token );
1191 Error( "line %i: unknown parm %s", scriptline, token );
1196 return; // textures are only released by $maps
1201 if ( xh * yh > MAX_IMAGE_SIZE * MAX_IMAGE_SIZE ) {
1202 Error( "line %i image %s: image is too big!", scriptline, lumpname );
1205 if ( TrueColorImage ) {
1206 if ( xl >= longimagewidth || xh > longimagewidth ||
1207 yl >= longimageheight || yh > longimageheight ) {
1208 Error( "line %i image %s: bad clip dimmensions (%d,%d) (%d,%d) > image (%d,%d)", scriptline, lumpname, xl,yl,w,h,longimagewidth,longimageheight );
1211 sourcel = longimage + ( yl * longimagewidth ) + xl;
1213 linedelta = ( longimagewidth - w );
1215 for ( y = yl ; y < yh ; y++ )
1217 for ( x = xl ; x < xh ; x++ )
1219 *destl++ = *sourcel++; // RGBA
1221 sourcel += linedelta;
1224 qtex32 = CreateMip32( bufferl, w, h, &size, true );
1226 qtex32->flags |= LittleLong( flags );
1227 qtex32->flags2 |= LittleLong( flags2 );
1228 qtex32->contents = LittleLong( contents );
1229 qtex32->value = LittleLong( value );
1230 qtex32->scale_x = scale_x;
1231 qtex32->scale_y = scale_y;
1232 qtex32->mip_scale = mip_scale;
1233 sprintf( qtex32->name, "%s/%s", mip_prefix, lumpname );
1234 if ( animname[0] ) {
1235 sprintf( qtex32->animname, "%s/%s", mip_prefix, animname );
1238 sprintf( qtex32->altname, "%s/%s", mip_prefix, altname );
1240 if ( damagename[0] ) {
1241 sprintf( qtex32->damagename, "%s/%s", mip_prefix, damagename );
1243 if ( dt_name[0] & ( ( flags2 & MIP32_DETAILER_FLAG2 ) == 0 ) ) {
1244 sprintf( qtex32->dt_name, "%s/%s", mip_prefix, dt_name );
1245 qtex32->dt_scale_x = dt_scale_x;
1246 qtex32->dt_scale_y = dt_scale_y;
1247 qtex32->dt_u = dt_u;
1248 qtex32->dt_v = dt_v;
1249 qtex32->dt_alpha = dt_alpha;
1250 qtex32->dt_src_blend_mode = dt_src_blend_mode;
1251 qtex32->dt_dst_blend_mode = dt_dst_blend_mode;
1257 sprintf( filename, "%stextures/%s/%s.m32", g_outputDir, mip_prefix, lumpname );
1258 if ( qtex32->flags & ( SURF_ALPHA_TEXTURE ) ) {
1259 printf( "writing %s with ALPHA\n", filename );
1262 printf( "writing %s\n", filename );
1264 SaveFile( filename, (byte *)qtex32, size );
1270 if ( xl >= byteimagewidth || xh > byteimagewidth ||
1271 yl >= byteimageheight || yh > byteimageheight ) {
1272 Error( "line %i: bad clip dimmensions (%d,%d) (%d,%d) > image (%d,%d)", scriptline, xl,yl,w,h,byteimagewidth,byteimageheight );
1275 source = byteimage + yl * byteimagewidth + xl;
1277 linedelta = byteimagewidth - w;
1279 for ( y = yl ; y < yh ; y++ )
1281 for ( x = xl ; x < xh ; x++ )
1283 *dest++ = *source++;
1285 source += linedelta;
1288 qtex = CreateMip( buffer, w, h, lbmpalette, &size, true );
1290 qtex->flags = LittleLong( flags );
1291 qtex->contents = LittleLong( contents );
1292 qtex->value = LittleLong( value );
1293 sprintf( qtex->name, "%s/%s", mip_prefix, lumpname );
1294 if ( animname[0] ) {
1295 sprintf( qtex->animname, "%s/%s", mip_prefix, animname );
1301 sprintf( filename, "%stextures/%s/%s.m8", g_outputDir, mip_prefix, lumpname );
1302 printf( "writing %s\n", filename );
1303 SaveFile( filename, (byte *)qtex, size );
1314 void Cmd_Mippal( void ){
1315 colormap_issued = true;
1320 memcpy( colormap_palette, lbmpalette, 768 );
1331 void Cmd_Mipdir( void ){
1332 char filename[1024];
1334 GetScriptToken( false );
1335 strcpy( mip_prefix, token );
1336 // create the directory if needed
1337 sprintf( filename, "%stextures", g_outputDir );
1338 Q_mkdir( filename );
1339 sprintf( filename, "%stextures/%s", g_outputDir, mip_prefix );
1340 Q_mkdir( filename );
1345 =============================================================================
1347 ENVIRONMENT MAP GRABBING
1349 Creates six pcx files from tga files without any palette edge seams
1350 also copies the tga files for GL rendering.
1351 =============================================================================
1354 // 3dstudio environment map suffixes
1355 char *suf[6] = {"rt", "ft", "lf", "bk", "up", "dn"};
1362 void Cmd_Environment( void ){
1365 byte image[256 * 256];
1368 GetScriptToken( false );
1371 for ( i = 0 ; i < 6 ; i++ )
1373 sprintf( name, "env/%s%s.pcx", token, suf[i] );
1374 ReleaseFile( name );
1375 sprintf( name, "env/%s%s.tga", token, suf[i] );
1376 ReleaseFile( name );
1383 sprintf( name, "%senv/", gamedir );
1386 // convert the images
1387 for ( i = 0 ; i < 6 ; i++ )
1389 sprintf( name, "%senv/%s%s.tga", gamedir, token, suf[i] );
1390 printf( "loading %s...\n", name );
1391 LoadTGA( name, &tga, NULL, NULL );
1393 for ( y = 0 ; y < 256 ; y++ )
1395 for ( x = 0 ; x < 256 ; x++ )
1397 image[y * 256 + x] = FindColor( tga[( y * 256 + x ) * 4 + 0],tga[( y * 256 + x ) * 4 + 1],tga[( y * 256 + x ) * 4 + 2] );
1401 sprintf( name, "%senv/%s%s.pcx", gamedir, token, suf[i] );
1402 if ( FileTime( name ) != -1 ) {
1403 printf( "%s already exists, not overwriting.\n", name );
1406 WritePCXfile( name, image, 256, 256, colormap_palette );