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