4 char mip_prefix[1024]; // directory to dump the textures in
6 qboolean colormap_issued;
7 byte colormap_palette[768];
13 Replaces all 0 bytes in an image with the closest palette entry.
14 This is because NT won't let us change index 0, so any palette
15 animation leaves those pixels untouched.
18 void RemapZero (byte *pixels, byte *palette, int width, int height)
26 for (i=1 ; i<255 ; i++)
28 value = palette[i*3+0]+palette[i*3+1]+palette[i*3+2];
46 $grab filename x y width height
58 if (token[0] == '/' || token[0] == '\\')
59 sprintf (savename, "%s%s.pcx", gamedir, token+1);
61 sprintf (savename, "%spics/%s.pcx", gamedir, token);
65 if (token[0] == '/' || token[0] == '\\')
66 sprintf (dest, "%s.pcx", token+1);
68 sprintf (dest, "pics/%s.pcx", token);
83 if (xl<0 || yl<0 || w<0 || h<0 || xl+w>byteimagewidth || yl+h>byteimageheight)
84 Error ("GrabPic: Bad size: %i, %i, %i, %i",xl,yl,w,h);
86 // crop it to the proper size
87 cropped = malloc (w*h);
90 memcpy (cropped+y*w, byteimage+(y+yl)*byteimagewidth+xl, w);
93 // save off the new image
94 printf ("saving %s\n", savename);
95 CreatePath (savename);
96 WritePCXfile (savename, cropped, w, h, lbmpalette);
105 $grab filename x y width height
117 sprintf (savename, "%s%s.lmp", gamedir, token);
121 sprintf (dest, "%s.lmp", token);
135 if (xl<0 || yl<0 || w<0 || h<0 || xl+w>byteimagewidth || yl+h>byteimageheight)
136 Error ("GrabPic: Bad size: %i, %i, %i, %i",xl,yl,w,h);
138 // crop it to the proper size
139 cropped = malloc (w*h);
140 for (y=0 ; y<h ; y++)
142 memcpy (cropped+y*w, byteimage+(y+yl)*byteimagewidth+xl, w);
145 // save off the new image
146 printf ("saving %s\n", savename);
147 CreatePath (savename);
149 SaveFile (savename, cropped, w*h);
155 =============================================================================
159 =============================================================================
167 byte BestColor (int r, int g, int b, int start, int stop)
171 int bestdistortion, distortion;
176 // let any color go to 0 as a last resort
178 bestdistortion = 256*256*4;
181 pal = colormap_palette + start*3;
182 for (i=start ; i<= stop ; i++)
184 dr = r - (int)pal[0];
185 dg = g - (int)pal[1];
186 db = b - (int)pal[2];
188 distortion = dr*dr + dg*dg + db*db;
189 if (distortion < bestdistortion)
192 return i; // perfect match
194 bestdistortion = distortion;
209 the brightes colormap is first in the table (FIXME: reverse this now?)
211 64 rows of 256 : lightmaps
212 256 rows of 256 : translucency table
215 void Cmd_Colormap (void)
219 float frac, red, green, blue;
221 byte *cropped, *lump_p;
225 colormap_issued = true;
227 memcpy (colormap_palette, lbmpalette, 768);
229 if (!TokenAvailable ())
230 { // just setting colormap_issued
235 sprintf (savename, "%spics/%s.pcx", gamedir, token);
239 sprintf (dest, "pics/%s.pcx", token);
246 brights = 1; // ignore 255 (transparent)
248 cropped = malloc((levels+256)*256);
252 for (l=0;l<levels;l++)
254 frac = range - range*(float)l/(levels-1);
255 for (c=0 ; c<256-brights ; c++)
257 red = lbmpalette[c*3];
258 green = lbmpalette[c*3+1];
259 blue = lbmpalette[c*3+2];
261 red = (int)(red*frac+0.5);
262 green = (int)(green*frac+0.5);
263 blue = (int)(blue*frac+0.5);
266 // note: 254 instead of 255 because 255 is the transparent color, and we
267 // don't want anything remapping to that
268 // don't use color 0, because NT can't remap that (or 255)
270 *lump_p++ = BestColor(red,green,blue, 1, 254);
273 // fullbrights allways stay the same
278 // 66% transparancy table
281 for (c=0 ; c<255 ; c++)
283 red = lbmpalette[c*3]*0.33 + lbmpalette[l*3]*0.66;
284 green = lbmpalette[c*3+1]*0.33 + lbmpalette[l*3+1]*0.66;
285 blue = lbmpalette[c*3+2]*0.33 + lbmpalette[l*3+2]*0.66;
287 *lump_p++ = BestColor(red,green,blue, 1, 254);
291 for (c=0 ; c<256 ; c++)
294 // save off the new image
295 printf ("saving %s\n", savename);
296 CreatePath (savename);
297 WritePCXfile (savename, cropped, 256, levels+256, lbmpalette);
303 =============================================================================
307 =============================================================================
312 int d_red, d_green, d_blue;
314 byte palmap[32][32][32];
315 qboolean palmap_built;
322 int FindColor (int r, int g, int b)
339 bestcolor = BestColor (r, g, b, 0, 254);
341 bestcolor = palmap[r>>3][g>>3][b>>3];
348 void BuildPalmap (void)
358 for (r=4 ; r<256 ; r+=8)
360 for (g=4 ; g<256 ; g+=8)
362 for (b=4 ; b<256 ; b+=8)
364 bestcolor = BestColor (r, g, b, 1, 254);
365 palmap[r>>3][g>>3][b>>3] = bestcolor;
371 if (!colormap_issued)
372 Error ("You must issue a $colormap command first");
381 byte AveragePixels (int count)
394 for (i=0 ; i<count ; i++)
398 r += lbmpalette[pix*3];
399 g += lbmpalette[pix*3+1];
400 b += lbmpalette[pix*3+2];
414 // find the best color
416 bestcolor = FindColor (r, g, b);
419 pal = colormap_palette + bestcolor*3;
420 d_red = r - (int)pal[0];
421 d_green = g - (int)pal[1];
422 d_blue = b - (int)pal[2];
443 mipparm_t mipparms[] =
445 // utility content attributes
446 {"water", CONTENTS_WATER, pt_contents},
447 {"slime", CONTENTS_SLIME, pt_contents}, // mildly damaging
448 {"lava", CONTENTS_LAVA, pt_contents}, // very damaging
449 {"window", CONTENTS_WINDOW, pt_contents}, // solid, but doesn't eat internal textures
450 {"mist", CONTENTS_MIST, pt_contents}, // non-solid window
451 {"origin", CONTENTS_ORIGIN, pt_contents}, // center of rotating brushes
452 {"playerclip", CONTENTS_PLAYERCLIP, pt_contents},
453 {"monsterclip", CONTENTS_MONSTERCLIP, pt_contents},
455 // utility surface attributes
456 {"hint", SURF_HINT, pt_flags},
457 {"skip", SURF_SKIP, pt_flags},
458 {"light", SURF_LIGHT, pt_flagvalue}, // value is the light quantity
461 {"anim", 0, pt_animvalue}, // value is the next animation
464 {"slick", SURF_SLICK, pt_flags},
466 // drawing attributes
467 {"sky", SURF_SKY, pt_flags},
468 {"warping", SURF_WARP, pt_flags}, // only valid with 64x64 textures
469 {"trans33", SURF_TRANS33, pt_flags}, // translucent should allso set fullbright
470 {"trans66", SURF_TRANS66, pt_flags},
471 {"flowing", SURF_FLOWING, pt_flags}, // flow direction towards angle 0
472 {"nodraw", SURF_NODRAW, pt_flags}, // for clip textures and trigger textures
474 {NULL, 0, pt_contents}
483 $mip filename x y width height <OPTIONS>
484 must be multiples of sixteen
490 int x,y,xl,yl,xh,yh,w,h;
491 byte *screen_p, *source;
494 int miplevel, mipstep;
497 int flags, value, contents;
505 strcpy (lumpname, token);
516 if ( (w & 15) || (h & 15) )
517 Error ("line %i: miptex sizes must be multiples of 16", scriptline);
525 // get optional flags and values
526 while (TokenAvailable ())
530 for (mp=mipparms ; mp->name ; mp++)
532 if (!strcmp(mp->name, token))
537 GetToken (false); // specify the next animation frame
538 strcpy (animname, token);
544 contents |= mp->flags;
548 GetToken (false); // specify the light value
556 Error ("line %i: unknown parm %s", scriptline, token);
559 sprintf (filename, "%stextures/%s/%s.wal", gamedir, mip_prefix, lumpname);
561 return; // textures are only released by $maps
566 qtex = malloc (sizeof(miptex_t) + w*h*2);
567 memset (qtex, 0, sizeof(miptex_t));
569 qtex->width = LittleLong(w);
570 qtex->height = LittleLong(h);
571 qtex->flags = LittleLong(flags);
572 qtex->contents = LittleLong(contents);
573 qtex->value = LittleLong(value);
574 sprintf (qtex->name, "%s/%s", mip_prefix, lumpname);
576 sprintf (qtex->animname, "%s/%s", mip_prefix, animname);
578 lump_p = (byte *)(&qtex->value+1);
580 screen_p = byteimage + yl*byteimagewidth + xl;
581 linedelta = byteimagewidth - w;
584 qtex->offsets[0] = LittleLong(lump_p - (byte *)qtex);
586 for (y=yl ; y<yh ; y++)
588 for (x=xl ; x<xh ; x++)
592 pix = 1; // should never happen
595 screen_p += linedelta;
599 // subsample for greater mip levels
601 d_red = d_green = d_blue = 0; // no distortion yet
603 for (miplevel = 1 ; miplevel<4 ; miplevel++)
605 qtex->offsets[miplevel] = LittleLong(lump_p - (byte *)qtex);
607 mipstep = 1<<miplevel;
608 for (y=0 ; y<h ; y+=mipstep)
611 for (x = 0 ; x<w ; x+= mipstep)
614 for (yy=0 ; yy<mipstep ; yy++)
615 for (xx=0 ; xx<mipstep ; xx++)
617 pixdata[count] = source[ (y+yy)*w + x + xx ];
620 *lump_p++ = AveragePixels (count);
626 // dword align the size
628 while ((int)lump_p&3)
634 printf ("writing %s\n", filename);
635 SaveFile (filename, (byte *)qtex, lump_p - (byte *)qtex);
645 void Cmd_Mippal (void)
647 colormap_issued = true;
651 memcpy (colormap_palette, lbmpalette, 768);
662 void Cmd_Mipdir (void)
667 strcpy (mip_prefix, token);
668 // create the directory if needed
669 sprintf (filename, "%stextures", gamedir, mip_prefix);
671 sprintf (filename, "%stextures/%s", gamedir, mip_prefix);
677 =============================================================================
679 ENVIRONMENT MAP GRABBING
681 Creates six pcx files from tga files without any palette edge seams
682 also copies the tga files for GL rendering.
683 =============================================================================
686 // 3dstudio environment map suffixes
687 char *suf[6] = {"rt", "ft", "lf", "bk", "up", "dn"};
694 void Cmd_Environment (void)
705 for (i=0 ; i<6 ; i++)
707 sprintf (name, "env/%s%s.pcx", token, suf[i]);
709 sprintf (name, "env/%s%s.tga", token, suf[i]);
717 sprintf (name, "%senv/", gamedir);
720 // convert the images
721 for (i=0 ; i<6 ; i++)
723 sprintf (name, "%senv/%s%s.tga", gamedir, token, suf[i]);
724 printf ("loading %s...\n", name);
725 LoadTGA (name, &tga, NULL, NULL);
727 for (y=0 ; y<256 ; y++)
729 for (x=0 ; x<256 ; x++)
731 image[y*256+x] = FindColor (tga[(y*256+x)*4+0],tga[(y*256+x)*4+1],tga[(y*256+x)*4+2]);
735 sprintf (name, "%senv/%s%s.pcx", gamedir, token, suf[i]);
736 if (FileTime (name) != -1)
737 printf ("%s already exists, not overwriting.\n", name);
739 WritePCXfile (name, image, 256, 256, colormap_palette);