123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764 |
- /*
- ===========================================================================
- Copyright (C) 1997-2006 Id Software, Inc.
- This file is part of Quake 2 Tools source code.
- Quake 2 Tools source code is free software; you can redistribute it
- and/or modify it under the terms of the GNU General Public License as
- published by the Free Software Foundation; either version 2 of the License,
- or (at your option) any later version.
- Quake 2 Tools source code is distributed in the hope that it will be
- useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
- You should have received a copy of the GNU General Public License
- along with Quake 2 Tools source code; if not, write to the Free Software
- Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
- ===========================================================================
- */
- #include "qdata.h"
- char mip_prefix[1024]; // directory to dump the textures in
- qboolean colormap_issued;
- byte colormap_palette[768];
- /*
- ==============
- RemapZero
- Replaces all 0 bytes in an image with the closest palette entry.
- This is because NT won't let us change index 0, so any palette
- animation leaves those pixels untouched.
- ==============
- */
- void RemapZero (byte *pixels, byte *palette, int width, int height)
- {
- int i, c;
- int alt_zero;
- int value, best;
- alt_zero = 0;
- best = 9999999;
- for (i=1 ; i<255 ; i++)
- {
- value = palette[i*3+0]+palette[i*3+1]+palette[i*3+2];
- if (value < best)
- {
- best = value;
- alt_zero = i;
- }
- }
- c = width*height;
- for (i=0 ; i<c ; i++)
- if (pixels[i] == 0)
- pixels[i] = alt_zero;
- }
- /*
- ==============
- Cmd_Grab
- $grab filename x y width height
- ==============
- */
- void Cmd_Grab (void)
- {
- int xl,yl,w,h,y;
- byte *cropped;
- char savename[1024];
- char dest[1024];
- GetToken (false);
- if (token[0] == '/' || token[0] == '\\')
- sprintf (savename, "%s%s.pcx", gamedir, token+1);
- else
- sprintf (savename, "%spics/%s.pcx", gamedir, token);
- if (g_release)
- {
- if (token[0] == '/' || token[0] == '\\')
- sprintf (dest, "%s.pcx", token+1);
- else
- sprintf (dest, "pics/%s.pcx", token);
- ReleaseFile (dest);
- return;
- }
- GetToken (false);
- xl = atoi (token);
- GetToken (false);
- yl = atoi (token);
- GetToken (false);
- w = atoi (token);
- GetToken (false);
- h = atoi (token);
- if (xl<0 || yl<0 || w<0 || h<0 || xl+w>byteimagewidth || yl+h>byteimageheight)
- Error ("GrabPic: Bad size: %i, %i, %i, %i",xl,yl,w,h);
- // crop it to the proper size
- cropped = malloc (w*h);
- for (y=0 ; y<h ; y++)
- {
- memcpy (cropped+y*w, byteimage+(y+yl)*byteimagewidth+xl, w);
- }
- // save off the new image
- printf ("saving %s\n", savename);
- CreatePath (savename);
- WritePCXfile (savename, cropped, w, h, lbmpalette);
- free (cropped);
- }
- /*
- ==============
- Cmd_Raw
- $grab filename x y width height
- ==============
- */
- void Cmd_Raw (void)
- {
- int xl,yl,w,h,y;
- byte *cropped;
- char savename[1024];
- char dest[1024];
- GetToken (false);
- sprintf (savename, "%s%s.lmp", gamedir, token);
- if (g_release)
- {
- sprintf (dest, "%s.lmp", token);
- ReleaseFile (dest);
- return;
- }
- GetToken (false);
- xl = atoi (token);
- GetToken (false);
- yl = atoi (token);
- GetToken (false);
- w = atoi (token);
- GetToken (false);
- h = atoi (token);
- if (xl<0 || yl<0 || w<0 || h<0 || xl+w>byteimagewidth || yl+h>byteimageheight)
- Error ("GrabPic: Bad size: %i, %i, %i, %i",xl,yl,w,h);
- // crop it to the proper size
- cropped = malloc (w*h);
- for (y=0 ; y<h ; y++)
- {
- memcpy (cropped+y*w, byteimage+(y+yl)*byteimagewidth+xl, w);
- }
- // save off the new image
- printf ("saving %s\n", savename);
- CreatePath (savename);
- SaveFile (savename, cropped, w*h);
- free (cropped);
- }
- /*
- =============================================================================
- COLORMAP GRABBING
- =============================================================================
- */
- /*
- ===============
- BestColor
- ===============
- */
- byte BestColor (int r, int g, int b, int start, int stop)
- {
- int i;
- int dr, dg, db;
- int bestdistortion, distortion;
- int bestcolor;
- byte *pal;
- //
- // let any color go to 0 as a last resort
- //
- bestdistortion = 256*256*4;
- bestcolor = 0;
- pal = colormap_palette + start*3;
- for (i=start ; i<= stop ; i++)
- {
- dr = r - (int)pal[0];
- dg = g - (int)pal[1];
- db = b - (int)pal[2];
- pal += 3;
- distortion = dr*dr + dg*dg + db*db;
- if (distortion < bestdistortion)
- {
- if (!distortion)
- return i; // perfect match
- bestdistortion = distortion;
- bestcolor = i;
- }
- }
- return bestcolor;
- }
- /*
- ==============
- Cmd_Colormap
- $colormap filename
- the brightes colormap is first in the table (FIXME: reverse this now?)
- 64 rows of 256 : lightmaps
- 256 rows of 256 : translucency table
- ==============
- */
- void Cmd_Colormap (void)
- {
- int levels, brights;
- int l, c;
- float frac, red, green, blue;
- float range;
- byte *cropped, *lump_p;
- char savename[1024];
- char dest[1024];
- colormap_issued = true;
- if (!g_release)
- memcpy (colormap_palette, lbmpalette, 768);
- if (!TokenAvailable ())
- { // just setting colormap_issued
- return;
- }
- GetToken (false);
- sprintf (savename, "%spics/%s.pcx", gamedir, token);
- if (g_release)
- {
- sprintf (dest, "pics/%s.pcx", token);
- ReleaseFile (dest);
- return;
- }
- range = 2;
- levels = 64;
- brights = 1; // ignore 255 (transparent)
- cropped = malloc((levels+256)*256);
- lump_p = cropped;
- // shaded levels
- for (l=0;l<levels;l++)
- {
- frac = range - range*(float)l/(levels-1);
- for (c=0 ; c<256-brights ; c++)
- {
- red = lbmpalette[c*3];
- green = lbmpalette[c*3+1];
- blue = lbmpalette[c*3+2];
- red = (int)(red*frac+0.5);
- green = (int)(green*frac+0.5);
- blue = (int)(blue*frac+0.5);
- //
- // note: 254 instead of 255 because 255 is the transparent color, and we
- // don't want anything remapping to that
- // don't use color 0, because NT can't remap that (or 255)
- //
- *lump_p++ = BestColor(red,green,blue, 1, 254);
- }
- // fullbrights allways stay the same
- for ( ; c<256 ; c++)
- *lump_p++ = c;
- }
- // 66% transparancy table
- for (l=0;l<255;l++)
- {
- for (c=0 ; c<255 ; c++)
- {
- red = lbmpalette[c*3]*0.33 + lbmpalette[l*3]*0.66;
- green = lbmpalette[c*3+1]*0.33 + lbmpalette[l*3+1]*0.66;
- blue = lbmpalette[c*3+2]*0.33 + lbmpalette[l*3+2]*0.66;
- *lump_p++ = BestColor(red,green,blue, 1, 254);
- }
- *lump_p++ = 255;
- }
- for (c=0 ; c<256 ; c++)
- *lump_p++ = 255;
- // save off the new image
- printf ("saving %s\n", savename);
- CreatePath (savename);
- WritePCXfile (savename, cropped, 256, levels+256, lbmpalette);
- free (cropped);
- }
- /*
- =============================================================================
- MIPTEX GRABBING
- =============================================================================
- */
- byte pixdata[256];
- int d_red, d_green, d_blue;
- byte palmap[32][32][32];
- qboolean palmap_built;
- /*
- =============
- FindColor
- =============
- */
- int FindColor (int r, int g, int b)
- {
- int bestcolor;
- if (r > 255)
- r = 255;
- if (r < 0)
- r = 0;
- if (g > 255)
- g = 255;
- if (g < 0)
- g = 0;
- if (b > 255)
- b = 255;
- if (b < 0)
- b = 0;
- #ifndef TABLECOLORS
- bestcolor = BestColor (r, g, b, 0, 254);
- #else
- bestcolor = palmap[r>>3][g>>3][b>>3];
- #endif
- return bestcolor;
- }
- void BuildPalmap (void)
- {
- #ifdef TABLECOLORS
- int r, g, b;
- int bestcolor;
- if (palmap_built)
- return;
- palmap_built = true;
- for (r=4 ; r<256 ; r+=8)
- {
- for (g=4 ; g<256 ; g+=8)
- {
- for (b=4 ; b<256 ; b+=8)
- {
- bestcolor = BestColor (r, g, b, 1, 254);
- palmap[r>>3][g>>3][b>>3] = bestcolor;
- }
- }
- }
- #endif
- if (!colormap_issued)
- Error ("You must issue a $colormap command first");
- }
- /*
- =============
- AveragePixels
- =============
- */
- byte AveragePixels (int count)
- {
- int r,g,b;
- int i;
- int vis;
- int pix;
- int bestcolor;
- byte *pal;
- int fullbright;
- vis = 0;
- r = g = b = 0;
- fullbright = 0;
- for (i=0 ; i<count ; i++)
- {
- pix = pixdata[i];
- r += lbmpalette[pix*3];
- g += lbmpalette[pix*3+1];
- b += lbmpalette[pix*3+2];
- vis++;
- }
- r /= vis;
- g /= vis;
- b /= vis;
- // error diffusion
- r += d_red;
- g += d_green;
- b += d_blue;
- //
- // find the best color
- //
- bestcolor = FindColor (r, g, b);
- // error diffusion
- pal = colormap_palette + bestcolor*3;
- d_red = r - (int)pal[0];
- d_green = g - (int)pal[1];
- d_blue = b - (int)pal[2];
- return bestcolor;
- }
- typedef enum
- {
- pt_contents,
- pt_flags,
- pt_animvalue,
- pt_flagvalue
- } parmtype_t;
- typedef struct
- {
- char *name;
- int flags;
- parmtype_t type;
- } mipparm_t;
- mipparm_t mipparms[] =
- {
- // utility content attributes
- {"water", CONTENTS_WATER, pt_contents},
- {"slime", CONTENTS_SLIME, pt_contents}, // mildly damaging
- {"lava", CONTENTS_LAVA, pt_contents}, // very damaging
- {"window", CONTENTS_WINDOW, pt_contents}, // solid, but doesn't eat internal textures
- {"mist", CONTENTS_MIST, pt_contents}, // non-solid window
- {"origin", CONTENTS_ORIGIN, pt_contents}, // center of rotating brushes
- {"playerclip", CONTENTS_PLAYERCLIP, pt_contents},
- {"monsterclip", CONTENTS_MONSTERCLIP, pt_contents},
- // utility surface attributes
- {"hint", SURF_HINT, pt_flags},
- {"skip", SURF_SKIP, pt_flags},
- {"light", SURF_LIGHT, pt_flagvalue}, // value is the light quantity
- // texture chaining
- {"anim", 0, pt_animvalue}, // value is the next animation
- // server attributes
- {"slick", SURF_SLICK, pt_flags},
- // drawing attributes
- {"sky", SURF_SKY, pt_flags},
- {"warping", SURF_WARP, pt_flags}, // only valid with 64x64 textures
- {"trans33", SURF_TRANS33, pt_flags}, // translucent should allso set fullbright
- {"trans66", SURF_TRANS66, pt_flags},
- {"flowing", SURF_FLOWING, pt_flags}, // flow direction towards angle 0
- {"nodraw", SURF_NODRAW, pt_flags}, // for clip textures and trigger textures
- {NULL, 0, pt_contents}
- };
- /*
- ==============
- Cmd_Mip
- $mip filename x y width height <OPTIONS>
- must be multiples of sixteen
- SURF_WINDOW
- ==============
- */
- void Cmd_Mip (void)
- {
- int x,y,xl,yl,xh,yh,w,h;
- byte *screen_p, *source;
- int linedelta;
- miptex_t *qtex;
- int miplevel, mipstep;
- int xx, yy, pix;
- int count;
- int flags, value, contents;
- mipparm_t *mp;
- char lumpname[64];
- byte *lump_p;
- char filename[1024];
- char animname[64];
- GetToken (false);
- strcpy (lumpname, token);
- GetToken (false);
- xl = atoi (token);
- GetToken (false);
- yl = atoi (token);
- GetToken (false);
- w = atoi (token);
- GetToken (false);
- h = atoi (token);
- if ( (w & 15) || (h & 15) )
- Error ("line %i: miptex sizes must be multiples of 16", scriptline);
- flags = 0;
- contents = 0;
- value = 0;
- animname[0] = 0;
- // get optional flags and values
- while (TokenAvailable ())
- {
- GetToken (false);
- for (mp=mipparms ; mp->name ; mp++)
- {
- if (!strcmp(mp->name, token))
- {
- switch (mp->type)
- {
- case pt_animvalue:
- GetToken (false); // specify the next animation frame
- strcpy (animname, token);
- break;
- case pt_flags:
- flags |= mp->flags;
- break;
- case pt_contents:
- contents |= mp->flags;
- break;
- case pt_flagvalue:
- flags |= mp->flags;
- GetToken (false); // specify the light value
- value = atoi(token);
- break;
- }
- break;
- }
- }
- if (!mp->name)
- Error ("line %i: unknown parm %s", scriptline, token);
- }
- sprintf (filename, "%stextures/%s/%s.wal", gamedir, mip_prefix, lumpname);
- if (g_release)
- return; // textures are only released by $maps
- xh = xl+w;
- yh = yl+h;
- qtex = malloc (sizeof(miptex_t) + w*h*2);
- memset (qtex, 0, sizeof(miptex_t));
- qtex->width = LittleLong(w);
- qtex->height = LittleLong(h);
- qtex->flags = LittleLong(flags);
- qtex->contents = LittleLong(contents);
- qtex->value = LittleLong(value);
- sprintf (qtex->name, "%s/%s", mip_prefix, lumpname);
- if (animname[0])
- sprintf (qtex->animname, "%s/%s", mip_prefix, animname);
- lump_p = (byte *)(&qtex->value+1);
- screen_p = byteimage + yl*byteimagewidth + xl;
- linedelta = byteimagewidth - w;
- source = lump_p;
- qtex->offsets[0] = LittleLong(lump_p - (byte *)qtex);
- for (y=yl ; y<yh ; y++)
- {
- for (x=xl ; x<xh ; x++)
- {
- pix = *screen_p++;
- if (pix == 255)
- pix = 1; // should never happen
- *lump_p++ = pix;
- }
- screen_p += linedelta;
- }
- //
- // subsample for greater mip levels
- //
- d_red = d_green = d_blue = 0; // no distortion yet
- for (miplevel = 1 ; miplevel<4 ; miplevel++)
- {
- qtex->offsets[miplevel] = LittleLong(lump_p - (byte *)qtex);
- mipstep = 1<<miplevel;
- for (y=0 ; y<h ; y+=mipstep)
- {
- for (x = 0 ; x<w ; x+= mipstep)
- {
- count = 0;
- for (yy=0 ; yy<mipstep ; yy++)
- for (xx=0 ; xx<mipstep ; xx++)
- {
- pixdata[count] = source[ (y+yy)*w + x + xx ];
- count++;
- }
- *lump_p++ = AveragePixels (count);
- }
- }
- }
- //
- // dword align the size
- //
- while ((int)lump_p&3)
- *lump_p++ = 0;
- //
- // write it out
- //
- printf ("writing %s\n", filename);
- SaveFile (filename, (byte *)qtex, lump_p - (byte *)qtex);
- free (qtex);
- }
- /*
- ===============
- Cmd_Mippal
- ===============
- */
- void Cmd_Mippal (void)
- {
- colormap_issued = true;
- if (g_release)
- return;
- memcpy (colormap_palette, lbmpalette, 768);
- BuildPalmap();
- }
- /*
- ===============
- Cmd_Mipdir
- ===============
- */
- void Cmd_Mipdir (void)
- {
- char filename[1024];
- GetToken (false);
- strcpy (mip_prefix, token);
- // create the directory if needed
- sprintf (filename, "%stextures", gamedir, mip_prefix);
- Q_mkdir (filename);
- sprintf (filename, "%stextures/%s", gamedir, mip_prefix);
- Q_mkdir (filename);
- }
- /*
- =============================================================================
- ENVIRONMENT MAP GRABBING
- Creates six pcx files from tga files without any palette edge seams
- also copies the tga files for GL rendering.
- =============================================================================
- */
- // 3dstudio environment map suffixes
- char *suf[6] = {"rt", "ft", "lf", "bk", "up", "dn"};
- /*
- =================
- Cmd_Environment
- =================
- */
- void Cmd_Environment (void)
- {
- char name[1024];
- int i, x, y;
- byte image[256*256];
- byte *tga;
- GetToken (false);
- if (g_release)
- {
- for (i=0 ; i<6 ; i++)
- {
- sprintf (name, "env/%s%s.pcx", token, suf[i]);
- ReleaseFile (name);
- sprintf (name, "env/%s%s.tga", token, suf[i]);
- ReleaseFile (name);
- }
- return;
- }
- // get the palette
- BuildPalmap ();
- sprintf (name, "%senv/", gamedir);
- CreatePath (name);
- // convert the images
- for (i=0 ; i<6 ; i++)
- {
- sprintf (name, "%senv/%s%s.tga", gamedir, token, suf[i]);
- printf ("loading %s...\n", name);
- LoadTGA (name, &tga, NULL, NULL);
- for (y=0 ; y<256 ; y++)
- {
- for (x=0 ; x<256 ; x++)
- {
- image[y*256+x] = FindColor (tga[(y*256+x)*4+0],tga[(y*256+x)*4+1],tga[(y*256+x)*4+2]);
- }
- }
- free (tga);
- sprintf (name, "%senv/%s%s.pcx", gamedir, token, suf[i]);
- if (FileTime (name) != -1)
- printf ("%s already exists, not overwriting.\n", name);
- else
- WritePCXfile (name, image, 256, 256, colormap_palette);
- }
- }
|