2 Copyright (C) 1999-2007 id Software, Inc. and contributors.
\r
3 For a list of contributors, see the accompanying CONTRIBUTORS file.
\r
5 This file is part of GtkRadiant.
\r
7 GtkRadiant is free software; you can redistribute it and/or modify
\r
8 it under the terms of the GNU General Public License as published by
\r
9 the Free Software Foundation; either version 2 of the License, or
\r
10 (at your option) any later version.
\r
12 GtkRadiant is distributed in the hope that it will be useful,
\r
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
\r
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
\r
15 GNU General Public License for more details.
\r
17 You should have received a copy of the GNU General Public License
\r
18 along with GtkRadiant; if not, write to the Free Software
\r
19 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
\r
25 #include <windows.h>
\r
31 extern char *g_outputDir;
\r
34 char mip_prefix[1024]; // directory to dump the textures in
\r
36 qboolean colormap_issued;
\r
37 byte colormap_palette[768];
\r
39 unsigned total_x = 0;
\r
40 unsigned total_y = 0;
\r
41 unsigned total_textures = 0;
\r
43 #define MAX_IMAGE_SIZE 512
\r
50 Replaces all 0 bytes in an image with the closest palette entry.
\r
51 This is because NT won't let us change index 0, so any palette
\r
52 animation leaves those pixels untouched.
\r
55 void RemapZero (byte *pixels, byte *palette, int width, int height)
\r
63 for (i=1 ; i<255 ; i++)
\r
65 value = palette[i*3+0]+palette[i*3+1]+palette[i*3+2];
\r
74 for (i=0 ; i<c ; i++)
\r
76 pixels[i] = alt_zero;
\r
82 // ********************************************************************
\r
83 // ** Mip Map Pre-Processing Routines
\r
84 // ********************************************************************
\r
86 #define intensity_value 1
\r
88 static unsigned image_pal[256];
\r
92 long palette_r[256], palette_g[256], palette_b[256];
\r
93 long last_r[MAX_LAST],last_g[MAX_LAST],last_b[MAX_LAST], last_i[MAX_LAST], last_place;
\r
97 void PrepareConvert(unsigned *palette)
\r
103 palette_r[i] = (palette[i] & 0x00ff0000) >> 16;
\r
104 palette_g[i] = (palette[i] & 0x0000ff00) >> 8;
\r
105 palette_b[i] = (palette[i] & 0x000000ff);
\r
108 for(i=0;i<MAX_LAST;i++)
\r
114 int ConvertTrueColorToPal(unsigned r, unsigned g, unsigned b)
\r
120 long dr, dg, db, biggest_delta;
\r
122 for(i=0;i<MAX_LAST;i++)
\r
123 if (r == last_r[i] && g == last_g[i] && b == last_b[i])
\r
129 min_dist = 256 * 256 + 256 * 256 + 256 * 256;
\r
130 biggest_delta = 256*256;
\r
133 for (i=0;i<256;i++)
\r
135 dr = abs(palette_r[i] - r);
\r
136 if (dr > biggest_delta)
\r
138 dg = abs(palette_g[i] - g);
\r
139 if (dg > biggest_delta)
\r
141 db = abs(palette_b[i] - b);
\r
142 if (db > biggest_delta)
\r
145 dist = dr * dr + dg * dg + db * db;
\r
146 if (dist < min_dist)
\r
150 if (min_dist == 0) break;
\r
153 if (dg > dist) dist = dg;
\r
154 if (db > dist) dist = db;
\r
155 if (dist < biggest_delta)
\r
156 biggest_delta = dist;
\r
161 if (last_place >= MAX_LAST)
\r
164 last_r[last_place] = r;
\r
165 last_g[last_place] = g;
\r
166 last_b[last_place] = b;
\r
167 last_i[last_place] = min_index;
\r
173 void GL_ResampleTexture8P (byte *in, int inwidth, int inheight, byte *out,
\r
174 int outwidth, int outheight, palette_t *palette)
\r
177 byte *inrow, *inrow2;
\r
178 unsigned frac, fracstep;
\r
179 unsigned p1[1024], p2[1024], *p1p, *p2p;
\r
180 palette_t *c1,*c2,*c3,*c4;
\r
183 fracstep = inwidth*0x10000/outwidth;
\r
185 frac = fracstep>>2;
\r
186 for (i=0 ; i<outwidth ; i++)
\r
191 frac = 3*(fracstep>>2);
\r
192 for (i=0 ; i<outwidth ; i++)
\r
200 for (i=0 ; i<outheight ; i++)//, out += outwidth)
\r
202 inrow = in + inwidth*(int)((i+0.25)*inheight/outheight);
\r
203 inrow2 = in + inwidth*(int)((i+0.75)*inheight/outheight);
\r
207 for (j=0 ; j<outwidth ; j++)
\r
209 c1 = &palette[*((byte *)inrow + (*p1p))];
\r
210 c2 = &palette[*((byte *)inrow + (*p2p))];
\r
211 c3 = &palette[*((byte *)inrow2 + (*p1p++))];
\r
212 c4 = &palette[*((byte *)inrow2 + (*p2p++))];
\r
214 r = ((unsigned)c1->r + (unsigned)c2->r + (unsigned)c3->r + (unsigned)c4->r)>>2;
\r
215 g = ((unsigned)c1->g + (unsigned)c2->g + (unsigned)c3->g + (unsigned)c4->g)>>2;
\r
216 b = ((unsigned)c1->b + (unsigned)c2->b + (unsigned)c3->b + (unsigned)c4->b)>>2;
\r
218 *out++ = ConvertTrueColorToPal(r,g,b);
\r
223 void GL_MipMap8P(byte *out, byte *in, int width, int height, palette_t *palette)
\r
226 palette_t *c1,*c2,*c3,*c4;
\r
230 memset(out, 0, 256 * 256);
\r
234 for (i = 0; i < height; i += 2, in += width)
\r
236 for (j = 0; j < width; j += 2)
\r
238 c1 = &palette[in[0]];
\r
239 c3 = &palette[in[width]];
\r
241 c2 = &palette[in[0]];
\r
242 c4 = &palette[in[width]];
\r
245 r = ((unsigned)c1->r + (unsigned)c2->r + (unsigned)c3->r + (unsigned)c4->r) >> 2;
\r
246 g = ((unsigned)c1->g + (unsigned)c2->g + (unsigned)c3->g + (unsigned)c4->g) >> 2;
\r
247 b = ((unsigned)c1->b + (unsigned)c2->b + (unsigned)c3->b + (unsigned)c4->b) >> 2;
\r
249 *out++ = ConvertTrueColorToPal(r, g, b);
\r
255 miptex_t *CreateMip(byte *data, unsigned width, unsigned height, byte *palette, int *FinalSize, qboolean mip)
\r
257 int scaled_width, scaled_height;
\r
259 byte intensitytable[256];
\r
260 byte scaled[256*256];
\r
267 for (i=0 ; i<256 ; i++)
\r
269 j = i * intensity_value;
\r
272 intensitytable[i] = j;
\r
275 for (scaled_width = 1 ; scaled_width < width ; scaled_width<<=1)
\r
277 if (1 && scaled_width > width && 1)
\r
278 scaled_width >>= 1;
\r
279 for (scaled_height = 1 ; scaled_height < height ; scaled_height<<=1)
\r
281 if (1 && scaled_height > height && 1)
\r
282 scaled_height >>= 1;
\r
284 // don't ever bother with >256 textures
\r
285 if (scaled_width > 256)
\r
286 scaled_width = 256;
\r
287 if (scaled_height > 256)
\r
288 scaled_height = 256;
\r
290 if (scaled_width < 1)
\r
292 if (scaled_height < 1)
\r
295 size = sizeof(*mp) + (scaled_width*scaled_height*3);
\r
296 mp = (miptex_t *)SafeMalloc(size, "CreateMip");
\r
299 mp->version = MIP_VERSION;
\r
301 for(i=j=0;i<256;i++,j+=3)
\r
303 mp->palette[i].r = r = intensitytable[palette[j]];
\r
304 mp->palette[i].g = g = intensitytable[palette[j+1]];
\r
305 mp->palette[i].b = b = intensitytable[palette[j+2]];
\r
306 image_pal[i] = 0xff000000 | (r<<16) | (g<<8) | (b);
\r
309 PrepareConvert(image_pal);
\r
311 if (scaled_width == width && scaled_height == height)
\r
313 memcpy (scaled, data, width*height);
\r
316 GL_ResampleTexture8P (data, width, height, scaled, scaled_width, scaled_height, mp->palette);
\r
318 pos = (byte *)(mp + 1);
\r
321 while ((scaled_width >= 1 || scaled_height >= 1) && (miplevel <= MIPLEVELS-1) && (!miplevel || mip))
\r
323 if (scaled_width < 1)
\r
325 if (scaled_height < 1)
\r
329 GL_MipMap8P(out, (byte *)scaled, scaled_width, scaled_height, mp->palette);
\r
331 memcpy(out, scaled, 256 * 256);
\r
333 mp->width[miplevel] = scaled_width;
\r
334 mp->height[miplevel] = scaled_height;
\r
335 mp->offsets[miplevel] = pos - ((byte *)(mp));
\r
336 memcpy(pos, out, scaled_width * scaled_height);
\r
337 memcpy(scaled, out, 256 * 256);
\r
338 pos += scaled_width * scaled_height;
\r
340 scaled_width >>= 1;
\r
341 scaled_height >>= 1;
\r
346 *FinalSize = pos - ((byte *)(mp));
\r
352 void GL_ResampleTexture (unsigned *in, int inwidth, int inheight, unsigned *out, int outwidth, int outheight)
\r
355 unsigned *inrow, *inrow2;
\r
356 unsigned frac, fracstep;
\r
357 unsigned p1[1024], p2[1024];
\r
358 byte *pix1, *pix2, *pix3, *pix4;
\r
360 fracstep = inwidth*0x10000/outwidth;
\r
362 frac = fracstep>>2;
\r
363 for (i=0 ; i<outwidth ; i++)
\r
365 p1[i] = 4*(frac>>16);
\r
368 frac = 3*(fracstep>>2);
\r
369 for (i=0 ; i<outwidth ; i++)
\r
371 p2[i] = 4*(frac>>16);
\r
375 for (i=0 ; i<outheight ; i++, out += outwidth)
\r
377 inrow = in + inwidth*(int)((i+0.25)*inheight/outheight);
\r
378 inrow2 = in + inwidth*(int)((i+0.75)*inheight/outheight);
\r
379 frac = fracstep >> 1;
\r
380 for (j=0 ; j<outwidth ; j++)
\r
382 pix1 = (byte *)inrow + p1[j];
\r
383 pix2 = (byte *)inrow + p2[j];
\r
384 pix3 = (byte *)inrow2 + p1[j];
\r
385 pix4 = (byte *)inrow2 + p2[j];
\r
386 ((byte *)(out+j))[0] = (pix1[0] + pix2[0] + pix3[0] + pix4[0])>>2;
\r
387 ((byte *)(out+j))[1] = (pix1[1] + pix2[1] + pix3[1] + pix4[1])>>2;
\r
388 ((byte *)(out+j))[2] = (pix1[2] + pix2[2] + pix3[2] + pix4[2])>>2;
\r
389 ((byte *)(out+j))[3] = (pix1[3] + pix2[3] + pix3[3] + pix4[3])>>2;
\r
394 void GL_MipMap (byte *out, byte *in, int width, int height)
\r
400 for (i=0 ; i<height ; i++, in+=width)
\r
402 for (j=0 ; j<width ; j+=8, out+=4, in+=8)
\r
404 out[0] = (in[0] + in[4] + in[width+0] + in[width+4])>>2;
\r
405 out[1] = (in[1] + in[5] + in[width+1] + in[width+5])>>2;
\r
406 out[2] = (in[2] + in[6] + in[width+2] + in[width+6])>>2;
\r
407 out[3] = (in[3] + in[7] + in[width+3] + in[width+7])>>2;
\r
412 miptex32_t *CreateMip32(unsigned *data, unsigned width, unsigned height, int *FinalSize, qboolean mip)
\r
414 int scaled_width, scaled_height;
\r
415 unsigned scaled[MAX_IMAGE_SIZE*MAX_IMAGE_SIZE];
\r
416 unsigned out[MAX_IMAGE_SIZE*MAX_IMAGE_SIZE];
\r
421 paletteRGBA_t *test;
\r
423 for (scaled_width = 1 ; scaled_width < width ; scaled_width<<=1)
\r
425 if (1 && scaled_width > width && 1)
\r
426 scaled_width >>= 1;
\r
427 for (scaled_height = 1 ; scaled_height < height ; scaled_height<<=1)
\r
429 if (1 && scaled_height > height && 1)
\r
430 scaled_height >>= 1;
\r
432 // don't ever bother with >256 textures
\r
433 if (scaled_width > MAX_IMAGE_SIZE)
\r
434 scaled_width = MAX_IMAGE_SIZE;
\r
435 if (scaled_height > MAX_IMAGE_SIZE)
\r
436 scaled_height = MAX_IMAGE_SIZE;
\r
438 if (scaled_width < 1)
\r
440 if (scaled_height < 1)
\r
443 size = sizeof(*mp) + (scaled_width*scaled_height*3*4);
\r
444 mp = (miptex32_t *)SafeMalloc(size, "CreateMip");
\r
447 mp->version = MIP32_VERSION;
\r
449 size = width*height;
\r
450 test = (paletteRGBA_t *)data;
\r
453 if (test->a != 255)
\r
455 mp->flags |= LittleLong(SURF_ALPHA_TEXTURE);
\r
463 if (scaled_width == width && scaled_height == height)
\r
465 memcpy (scaled, data, width*height*4);
\r
468 GL_ResampleTexture (data, width, height, scaled, scaled_width, scaled_height);
\r
470 pos = (byte *)(mp + 1);
\r
473 while ((scaled_width >= 1 || scaled_height >= 1) && (miplevel <= MIPLEVELS-1) && (!miplevel || mip))
\r
475 if (scaled_width < 1)
\r
477 if (scaled_height < 1)
\r
482 GL_MipMap((byte *)out, (byte *)scaled, scaled_width, scaled_height);
\r
486 memcpy(out, scaled, MAX_IMAGE_SIZE * MAX_IMAGE_SIZE * 4);
\r
489 mp->width[miplevel] = scaled_width;
\r
490 mp->height[miplevel] = scaled_height;
\r
491 mp->offsets[miplevel] = pos - ((byte *)(mp));
\r
492 memcpy(pos, out, scaled_width * scaled_height * 4);
\r
493 memcpy(scaled, out, MAX_IMAGE_SIZE * MAX_IMAGE_SIZE * 4);
\r
494 pos += scaled_width * scaled_height * 4;
\r
496 scaled_width >>= 1;
\r
497 scaled_height >>= 1;
\r
502 *FinalSize = pos - ((byte *)(mp));
\r
511 $grab filename x y width height
\r
514 void Cmd_Grab (void)
\r
518 char savename[1024];
\r
521 GetScriptToken (false);
\r
523 if (token[0] == '/' || token[0] == '\\')
\r
524 sprintf (savename, "%s%s.pcx", gamedir, token+1);
\r
526 sprintf (savename, "%spics/%s.pcx", gamedir, token);
\r
530 if (token[0] == '/' || token[0] == '\\')
\r
531 sprintf (dest, "%s.pcx", token+1);
\r
533 sprintf (dest, "pics/%s.pcx", token);
\r
535 ReleaseFile (dest);
\r
539 GetScriptToken (false);
\r
541 GetScriptToken (false);
\r
543 GetScriptToken (false);
\r
545 GetScriptToken (false);
\r
548 if (xl<0 || yl<0 || w<0 || h<0 || xl+w>byteimagewidth || yl+h>byteimageheight)
\r
549 Error ("GrabPic: Bad size: %i, %i, %i, %i",xl,yl,w,h);
\r
551 // crop it to the proper size
\r
552 cropped = (byte *) SafeMalloc (w*h, "Cmd_Grab");
\r
553 for (y=0 ; y<h ; y++)
\r
555 memcpy (cropped+y*w, byteimage+(y+yl)*byteimagewidth+xl, w);
\r
558 // save off the new image
\r
559 printf ("saving %s\n", savename);
\r
560 CreatePath (savename);
\r
561 WritePCXfile (savename, cropped, w, h, lbmpalette);
\r
570 $grab filename x y width height
\r
573 void Cmd_Raw (void)
\r
577 char savename[1024];
\r
580 GetScriptToken (false);
\r
582 sprintf (savename, "%s%s.lmp", gamedir, token);
\r
586 sprintf (dest, "%s.lmp", token);
\r
587 ReleaseFile (dest);
\r
591 GetScriptToken (false);
\r
593 GetScriptToken (false);
\r
595 GetScriptToken (false);
\r
597 GetScriptToken (false);
\r
600 if (xl<0 || yl<0 || w<0 || h<0 || xl+w>byteimagewidth || yl+h>byteimageheight)
\r
601 Error ("GrabPic: Bad size: %i, %i, %i, %i",xl,yl,w,h);
\r
603 // crop it to the proper size
\r
604 cropped = (byte *) SafeMalloc (w*h, "Cmd_Raw");
\r
605 for (y=0 ; y<h ; y++)
\r
607 memcpy (cropped+y*w, byteimage+(y+yl)*byteimagewidth+xl, w);
\r
610 // save off the new image
\r
611 printf ("saving %s\n", savename);
\r
612 CreatePath (savename);
\r
614 SaveFile (savename, cropped, w*h);
\r
620 =============================================================================
\r
624 =============================================================================
\r
632 byte BestColor (int r, int g, int b, int start, int stop)
\r
636 int bestdistortion, distortion;
\r
641 // let any color go to 0 as a last resort
\r
643 bestdistortion = 256*256*4;
\r
646 pal = colormap_palette + start*3;
\r
647 for (i=start ; i<= stop ; i++)
\r
649 dr = r - (int)pal[0];
\r
650 dg = g - (int)pal[1];
\r
651 db = b - (int)pal[2];
\r
653 distortion = dr*dr + dg*dg + db*db;
\r
654 if (distortion < bestdistortion)
\r
657 return i; // perfect match
\r
659 bestdistortion = distortion;
\r
674 the brightes colormap is first in the table (FIXME: reverse this now?)
\r
676 64 rows of 256 : lightmaps
\r
677 256 rows of 256 : translucency table
\r
680 void Cmd_Colormap (void)
\r
682 int levels, brights;
\r
684 float frac, red, green, blue;
\r
686 byte *cropped, *lump_p;
\r
687 char savename[1024];
\r
690 colormap_issued = true;
\r
692 memcpy (colormap_palette, lbmpalette, 768);
\r
694 if (!ScriptTokenAvailable ())
\r
695 { // just setting colormap_issued
\r
699 GetScriptToken (false);
\r
700 sprintf (savename, "%spics/%s.pcx", gamedir, token);
\r
704 sprintf (dest, "pics/%s.pcx", token);
\r
705 ReleaseFile (dest);
\r
711 brights = 1; // ignore 255 (transparent)
\r
713 cropped = (byte *) SafeMalloc((levels+256)*256, "Cmd_ColorMap");
\r
717 for (l=0;l<levels;l++)
\r
719 frac = range - range*(float)l/(levels-1);
\r
720 for (c=0 ; c<256-brights ; c++)
\r
722 red = lbmpalette[c*3];
\r
723 green = lbmpalette[c*3+1];
\r
724 blue = lbmpalette[c*3+2];
\r
726 red = (int)(red*frac+0.5);
\r
727 green = (int)(green*frac+0.5);
\r
728 blue = (int)(blue*frac+0.5);
\r
731 // note: 254 instead of 255 because 255 is the transparent color, and we
\r
732 // don't want anything remapping to that
\r
733 // don't use color 0, because NT can't remap that (or 255)
\r
735 *lump_p++ = BestColor(red,green,blue, 1, 254);
\r
738 // fullbrights allways stay the same
\r
739 for ( ; c<256 ; c++)
\r
743 // 66% transparancy table
\r
744 for (l=0;l<255;l++)
\r
746 for (c=0 ; c<255 ; c++)
\r
748 red = lbmpalette[c*3]*0.33 + lbmpalette[l*3]*0.66;
\r
749 green = lbmpalette[c*3+1]*0.33 + lbmpalette[l*3+1]*0.66;
\r
750 blue = lbmpalette[c*3+2]*0.33 + lbmpalette[l*3+2]*0.66;
\r
752 *lump_p++ = BestColor(red,green,blue, 1, 254);
\r
756 for (c=0 ; c<256 ; c++)
\r
759 // save off the new image
\r
760 printf ("saving %s\n", savename);
\r
761 CreatePath (savename);
\r
762 WritePCXfile (savename, cropped, 256, levels+256, lbmpalette);
\r
768 =============================================================================
\r
772 =============================================================================
\r
777 int d_red, d_green, d_blue;
\r
779 byte palmap[32][32][32];
\r
780 qboolean palmap_built;
\r
787 int FindColor (int r, int g, int b)
\r
803 #ifndef TABLECOLORS
\r
804 bestcolor = BestColor (r, g, b, 0, 254);
\r
806 bestcolor = palmap[r>>3][g>>3][b>>3];
\r
813 void BuildPalmap (void)
\r
821 palmap_built = true;
\r
823 for (r=4 ; r<256 ; r+=8)
\r
825 for (g=4 ; g<256 ; g+=8)
\r
827 for (b=4 ; b<256 ; b+=8)
\r
829 bestcolor = BestColor (r, g, b, 1, 254);
\r
830 palmap[r>>3][g>>3][b>>3] = bestcolor;
\r
836 if (!colormap_issued)
\r
837 Error ("You must issue a $colormap command first");
\r
846 byte AveragePixels (int count)
\r
859 for (i=0 ; i<count ; i++)
\r
863 r += lbmpalette[pix*3];
\r
864 g += lbmpalette[pix*3+1];
\r
865 b += lbmpalette[pix*3+2];
\r
879 // find the best color
\r
881 bestcolor = FindColor (r, g, b);
\r
884 pal = colormap_palette + bestcolor*3;
\r
885 d_red = r - (int)pal[0];
\r
886 d_green = g - (int)pal[1];
\r
887 d_blue = b - (int)pal[2];
\r
899 pt_damagenamevalue,
\r
917 mipparm_t mipparms[] =
\r
919 // utility content attributes
\r
920 {"pushpull",CONTENTS_PUSHPULL, pt_contents},
\r
921 {"water", CONTENTS_WATER, pt_contents},
\r
922 {"slime", CONTENTS_SLIME, pt_contents}, // mildly damaging
\r
923 {"lava", CONTENTS_LAVA, pt_contents}, // very damaging
\r
924 {"window", CONTENTS_WINDOW, pt_contents}, // solid, but doesn't eat internal textures
\r
925 {"mist", CONTENTS_MIST, pt_contents}, // non-solid window
\r
926 {"origin", CONTENTS_ORIGIN, pt_contents}, // center of rotating brushes
\r
927 {"playerclip", CONTENTS_PLAYERCLIP, pt_contents},
\r
928 {"monsterclip", CONTENTS_MONSTERCLIP, pt_contents},
\r
930 // utility surface attributes
\r
931 {"hint", SURF_HINT, pt_flags},
\r
932 {"skip", SURF_SKIP, pt_flags},
\r
933 {"light", SURF_LIGHT, pt_flagvalue}, // value is the light quantity
\r
935 {"animspeed",SURF_ANIMSPEED, pt_flagvalue}, // value will hold the anim speed in fps
\r
937 // texture chaining
\r
938 {"anim", 0, pt_animvalue}, // animname is the next animation
\r
939 {"alt", 0, pt_altnamevalue}, // altname is the alternate texture
\r
940 {"damage", 0, pt_damagenamevalue}, // damagename is the damage texture
\r
941 {"scale", 0, pt_scale}, // next two values are for scale
\r
942 {"mip", 0, pt_mip},
\r
943 {"detail", 0, pt_detail},
\r
945 {"GL_ZERO", GL_ZERO, pt_gl},
\r
946 {"GL_ONE", GL_ONE, pt_gl},
\r
947 {"GL_SRC_COLOR", GL_SRC_COLOR, pt_gl},
\r
948 {"GL_ONE_MINUS_SRC_COLOR", GL_ONE_MINUS_SRC_COLOR, pt_gl},
\r
949 {"GL_DST_COLOR", GL_DST_COLOR, pt_gl},
\r
950 {"GL_ONE_MINUS_DST_COLOR", GL_ONE_MINUS_DST_COLOR, pt_gl},
\r
951 {"GL_SRC_ALPHA", GL_SRC_ALPHA, pt_gl},
\r
952 {"GL_ONE_MINUS_SRC_ALPHA", GL_ONE_MINUS_SRC_ALPHA, pt_gl},
\r
953 {"GL_DST_ALPHA", GL_DST_ALPHA, pt_gl},
\r
954 {"GL_ONE_MINUS_DST_ALPHA", GL_ONE_MINUS_DST_ALPHA, pt_gl},
\r
955 {"GL_SRC_ALPHA_SATURATE", GL_SRC_ALPHA_SATURATE, pt_gl},
\r
957 // server attributes
\r
958 {"slick", SURF_SLICK, pt_flags},
\r
960 // drawing attributes
\r
961 {"sky", SURF_SKY, pt_flags},
\r
962 {"warping", SURF_WARP, pt_flags}, // only valid with 64x64 textures
\r
963 {"trans33", SURF_TRANS33, pt_flags}, // translucent should allso set fullbright
\r
964 {"trans66", SURF_TRANS66, pt_flags},
\r
965 {"flowing", SURF_FLOWING, pt_flags}, // flow direction towards angle 0
\r
966 {"nodraw", SURF_NODRAW, pt_flags}, // for clip textures and trigger textures
\r
967 {"alpha", SURF_ALPHA_TEXTURE, pt_flags},
\r
968 {"undulate", SURF_UNDULATE, pt_flags}, // rock surface up and down...
\r
969 {"skyreflect", SURF_SKYREFLECT, pt_flags}, // liquid will somewhat reflect the sky - not quite finished....
\r
971 {"material", SURF_MATERIAL, pt_materialvalue},
\r
972 {"metal", SURF_TYPE_METAL, pt_flags},
\r
973 {"stone", SURF_TYPE_STONE, pt_flags},
\r
974 {"wood", SURF_TYPE_WOOD, pt_flags},
\r
976 {"m_nomip", 0, pt_nomip},
\r
977 {"m_detail", 0, pt_detailer},
\r
979 {NULL, 0, pt_contents}
\r
986 $mip filename x y width height <OPTIONS>
\r
987 must be multiples of sixteen
\r
992 void Cmd_Mip (void)
\r
994 int xl,yl,xh,yh,w,h;
\r
995 byte *dest, *source;
\r
996 int flags, value, contents;
\r
998 char lumpname[128];
\r
1000 char animname[128];
\r
1001 char damagename[128];
\r
1002 byte buffer[MAX_IMAGE_SIZE*MAX_IMAGE_SIZE];
\r
1003 unsigned bufferl[MAX_IMAGE_SIZE*MAX_IMAGE_SIZE];
\r
1004 materialtype_t *mat;
\r
1005 char filename[1024];
\r
1006 unsigned *destl, *sourcel;
\r
1007 int linedelta, x, y;
\r
1010 miptex32_t *qtex32;
\r
1011 float scale_x, scale_y;
\r
1013 // detail texturing
\r
1014 char dt_name[128];
\r
1015 float dt_scale_x, dt_scale_y;
\r
1018 int dt_src_blend_mode, dt_dst_blend_mode;
\r
1022 GetScriptToken (false);
\r
1023 strcpy (lumpname, token);
\r
1025 GetScriptToken (false);
\r
1026 xl = atoi (token);
\r
1027 GetScriptToken (false);
\r
1028 yl = atoi (token);
\r
1029 GetScriptToken (false);
\r
1031 GetScriptToken (false);
\r
1038 if ( (w & 15) || (h & 15) )
\r
1039 Error ("line %i: miptex sizes must be multiples of 16", scriptline);
\r
1047 altname[0] = animname[0] = damagename[0] = 0;
\r
1049 scale_x = scale_y = 0.5;
\r
1051 // detail texturing
\r
1053 dt_scale_x = dt_scale_y = 0.0;
\r
1054 dt_u = dt_v = 0.0;
\r
1056 dt_src_blend_mode = dt_dst_blend_mode = 0;
\r
1058 // get optional flags and values
\r
1059 while (ScriptTokenAvailable ())
\r
1061 GetScriptToken (false);
\r
1063 for (mp=mipparms ; mp->name ; mp++)
\r
1065 if (!strcmp(mp->name, token))
\r
1069 case pt_animvalue:
\r
1070 GetScriptToken (false); // specify the next animation frame
\r
1071 strcpy (animname, token);
\r
1073 case pt_altnamevalue:
\r
1074 GetScriptToken (false); // specify the alternate texture
\r
1075 strcpy (altname, token);
\r
1077 case pt_damagenamevalue:
\r
1078 GetScriptToken (false); // specify the damage texture
\r
1079 strcpy (damagename, token);
\r
1082 flags |= mp->flags;
\r
1085 contents |= mp->flags;
\r
1087 case pt_flagvalue:
\r
1088 flags |= mp->flags;
\r
1089 GetScriptToken (false); // specify the light value
\r
1090 value = atoi(token);
\r
1092 case pt_materialvalue:
\r
1093 GetScriptToken(false);
\r
1094 for (mat=materialtypes ; mat->name ; mat++)
\r
1096 if (!strcmp(mat->name, token))
\r
1098 // assumes SURF_MATERIAL is in top 8 bits
\r
1099 flags = (flags & 0x0FFFFFF) | (mat->value << 24);
\r
1105 GetScriptToken (false); // specify the x scale
\r
1106 scale_x = atof(token);
\r
1107 GetScriptToken (false); // specify the y scale
\r
1108 scale_y = atof(token);
\r
1116 flags2 |= MIP32_DETAILER_FLAG2;
\r
1120 flags2 |= MIP32_NOMIP_FLAG2;
\r
1124 GetScriptToken(false);
\r
1125 strcpy(dt_name, token);
\r
1126 GetScriptToken(false);
\r
1127 dt_scale_x = atof(token);
\r
1128 GetScriptToken(false);
\r
1129 dt_scale_y = atof(token);
\r
1130 GetScriptToken(false);
\r
1131 dt_u = atof(token);
\r
1132 GetScriptToken(false);
\r
1133 dt_v = atof(token);
\r
1134 GetScriptToken(false);
\r
1135 dt_alpha = atof(token);
\r
1136 GetScriptToken(false);
\r
1137 for (mp=mipparms ; mp->name ; mp++)
\r
1139 if (!strcmp(mp->name, token))
\r
1141 if (mp->type == pt_gl)
\r
1143 dt_src_blend_mode = mp->flags;
\r
1150 Error ("line %i: invalid gl blend mode %s", scriptline, token);
\r
1152 GetScriptToken (false);
\r
1153 for (mp=mipparms ; mp->name ; mp++)
\r
1155 if (!strcmp(mp->name, token))
\r
1157 if (mp->type == pt_gl)
\r
1159 dt_dst_blend_mode = mp->flags;
\r
1166 Error ("line %i: invalid gl blend mode %s", scriptline, token);
\r
1174 Error ("line %i: unknown parm %s", scriptline, token);
\r
1178 return; // textures are only released by $maps
\r
1182 if (xh*yh > MAX_IMAGE_SIZE*MAX_IMAGE_SIZE)
\r
1184 Error("line %i image %s: image is too big!", scriptline, lumpname);
\r
1187 if (TrueColorImage)
\r
1189 if (xl >= longimagewidth || xh > longimagewidth ||
\r
1190 yl >= longimageheight || yh > longimageheight)
\r
1192 Error ("line %i image %s: bad clip dimmensions (%d,%d) (%d,%d) > image (%d,%d)", scriptline, lumpname, xl,yl,w,h,longimagewidth,longimageheight);
\r
1195 sourcel = longimage + (yl*longimagewidth) + xl;
\r
1197 linedelta = (longimagewidth - w);
\r
1199 for (y=yl ; y<yh ; y++)
\r
1201 for (x=xl ; x<xh ; x++)
\r
1203 *destl++ = *sourcel++; // RGBA
\r
1205 sourcel += linedelta;
\r
1208 qtex32 = CreateMip32(bufferl, w, h, &size, true);
\r
1210 qtex32->flags |= LittleLong(flags);
\r
1211 qtex32->flags2 |= LittleLong(flags2);
\r
1212 qtex32->contents = LittleLong(contents);
\r
1213 qtex32->value = LittleLong(value);
\r
1214 qtex32->scale_x = scale_x;
\r
1215 qtex32->scale_y = scale_y;
\r
1216 qtex32->mip_scale = mip_scale;
\r
1217 sprintf (qtex32->name, "%s/%s", mip_prefix, lumpname);
\r
1220 sprintf (qtex32->animname, "%s/%s", mip_prefix, animname);
\r
1224 sprintf (qtex32->altname, "%s/%s", mip_prefix, altname);
\r
1226 if (damagename[0])
\r
1228 sprintf (qtex32->damagename, "%s/%s", mip_prefix, damagename);
\r
1230 if (dt_name[0] & ((flags2 & MIP32_DETAILER_FLAG2) == 0))
\r
1232 sprintf (qtex32->dt_name, "%s/%s", mip_prefix, dt_name);
\r
1233 qtex32->dt_scale_x = dt_scale_x;
\r
1234 qtex32->dt_scale_y = dt_scale_y;
\r
1235 qtex32->dt_u = dt_u;
\r
1236 qtex32->dt_v = dt_v;
\r
1237 qtex32->dt_alpha = dt_alpha;
\r
1238 qtex32->dt_src_blend_mode = dt_src_blend_mode;
\r
1239 qtex32->dt_dst_blend_mode = dt_dst_blend_mode;
\r
1245 sprintf (filename, "%stextures/%s/%s.m32", g_outputDir, mip_prefix, lumpname);
\r
1246 if(qtex32->flags & (SURF_ALPHA_TEXTURE))
\r
1247 printf ("writing %s with ALPHA\n", filename);
\r
1249 printf ("writing %s\n", filename);
\r
1250 SaveFile (filename, (byte *)qtex32, size);
\r
1256 if (xl >= byteimagewidth || xh > byteimagewidth ||
\r
1257 yl >= byteimageheight || yh > byteimageheight)
\r
1259 Error ("line %i: bad clip dimmensions (%d,%d) (%d,%d) > image (%d,%d)", scriptline, xl,yl,w,h,byteimagewidth,byteimageheight);
\r
1262 source = byteimage + yl*byteimagewidth + xl;
\r
1264 linedelta = byteimagewidth - w;
\r
1266 for (y=yl ; y<yh ; y++)
\r
1268 for (x=xl ; x<xh ; x++)
\r
1270 *dest++ = *source++;
\r
1272 source += linedelta;
\r
1275 qtex = CreateMip(buffer, w, h, lbmpalette, &size, true);
\r
1277 qtex->flags = LittleLong(flags);
\r
1278 qtex->contents = LittleLong(contents);
\r
1279 qtex->value = LittleLong(value);
\r
1280 sprintf (qtex->name, "%s/%s", mip_prefix, lumpname);
\r
1282 sprintf (qtex->animname, "%s/%s", mip_prefix, animname);
\r
1287 sprintf (filename, "%stextures/%s/%s.m8", g_outputDir, mip_prefix, lumpname);
\r
1288 printf ("writing %s\n", filename);
\r
1289 SaveFile (filename, (byte *)qtex, size);
\r
1300 void Cmd_Mippal (void)
\r
1302 colormap_issued = true;
\r
1306 memcpy (colormap_palette, lbmpalette, 768);
\r
1317 void Cmd_Mipdir (void)
\r
1319 char filename[1024];
\r
1321 GetScriptToken (false);
\r
1322 strcpy (mip_prefix, token);
\r
1323 // create the directory if needed
\r
1324 sprintf (filename, "%stextures", g_outputDir);
\r
1325 Q_mkdir (filename);
\r
1326 sprintf (filename, "%stextures/%s", g_outputDir, mip_prefix);
\r
1327 Q_mkdir (filename);
\r
1332 =============================================================================
\r
1334 ENVIRONMENT MAP GRABBING
\r
1336 Creates six pcx files from tga files without any palette edge seams
\r
1337 also copies the tga files for GL rendering.
\r
1338 =============================================================================
\r
1341 // 3dstudio environment map suffixes
\r
1342 char *suf[6] = {"rt", "ft", "lf", "bk", "up", "dn"};
\r
1349 void Cmd_Environment (void)
\r
1353 byte image[256*256];
\r
1356 GetScriptToken (false);
\r
1360 for (i=0 ; i<6 ; i++)
\r
1362 sprintf (name, "env/%s%s.pcx", token, suf[i]);
\r
1363 ReleaseFile (name);
\r
1364 sprintf (name, "env/%s%s.tga", token, suf[i]);
\r
1365 ReleaseFile (name);
\r
1369 // get the palette
\r
1372 sprintf (name, "%senv/", gamedir);
\r
1373 CreatePath (name);
\r
1375 // convert the images
\r
1376 for (i=0 ; i<6 ; i++)
\r
1378 sprintf (name, "%senv/%s%s.tga", gamedir, token, suf[i]);
\r
1379 printf ("loading %s...\n", name);
\r
1380 LoadTGA (name, &tga, NULL, NULL);
\r
1382 for (y=0 ; y<256 ; y++)
\r
1384 for (x=0 ; x<256 ; x++)
\r
1386 image[y*256+x] = FindColor (tga[(y*256+x)*4+0],tga[(y*256+x)*4+1],tga[(y*256+x)*4+2]);
\r
1390 sprintf (name, "%senv/%s%s.pcx", gamedir, token, suf[i]);
\r
1391 if (FileTime (name) != -1)
\r
1392 printf ("%s already exists, not overwriting.\n", name);
\r
1394 WritePCXfile (name, image, 256, 256, colormap_palette);
\r