mirror of
https://github.com/UberGames/GtkRadiant.git
synced 2024-11-25 05:11:43 +00:00
1405 lines
32 KiB
C
1405 lines
32 KiB
C
/*
|
|
Copyright (C) 1999-2007 id Software, Inc. and contributors.
|
|
For a list of contributors, see the accompanying CONTRIBUTORS file.
|
|
|
|
This file is part of GtkRadiant.
|
|
|
|
GtkRadiant 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.
|
|
|
|
GtkRadiant 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 GtkRadiant; if not, write to the Free Software
|
|
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
|
*/
|
|
|
|
#include "qdata.h"
|
|
|
|
#ifdef _WIN32
|
|
#include <windows.h>
|
|
#endif
|
|
|
|
#include <GL/gl.h>
|
|
|
|
#if 1
|
|
extern char *g_outputDir;
|
|
#endif // _QDATA
|
|
|
|
char mip_prefix[1024]; // directory to dump the textures in
|
|
|
|
qboolean colormap_issued;
|
|
byte colormap_palette[768];
|
|
|
|
unsigned total_x = 0;
|
|
unsigned total_y = 0;
|
|
unsigned total_textures = 0;
|
|
|
|
#define MAX_IMAGE_SIZE 512
|
|
|
|
#if 0
|
|
/*
|
|
==============
|
|
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;
|
|
}
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
// ********************************************************************
|
|
// ** Mip Map Pre-Processing Routines
|
|
// ********************************************************************
|
|
|
|
#define intensity_value 1
|
|
|
|
static unsigned image_pal[256];
|
|
|
|
#define MAX_LAST 25
|
|
|
|
long palette_r[256], palette_g[256], palette_b[256];
|
|
long last_r[MAX_LAST],last_g[MAX_LAST],last_b[MAX_LAST], last_i[MAX_LAST], last_place;
|
|
|
|
long cached;
|
|
|
|
void PrepareConvert( unsigned *palette ){
|
|
int i;
|
|
|
|
for ( i = 0; i < 256; i++ )
|
|
{
|
|
palette_r[i] = ( palette[i] & 0x00ff0000 ) >> 16;
|
|
palette_g[i] = ( palette[i] & 0x0000ff00 ) >> 8;
|
|
palette_b[i] = ( palette[i] & 0x000000ff );
|
|
}
|
|
|
|
for ( i = 0; i < MAX_LAST; i++ )
|
|
last_r[i] = -1;
|
|
|
|
last_place = -1;
|
|
}
|
|
|
|
int ConvertTrueColorToPal( unsigned r, unsigned g, unsigned b ){
|
|
int i;
|
|
long min_dist;
|
|
int min_index;
|
|
long dist;
|
|
long dr, dg, db, biggest_delta;
|
|
|
|
for ( i = 0; i < MAX_LAST; i++ )
|
|
if ( r == last_r[i] && g == last_g[i] && b == last_b[i] ) {
|
|
cached++;
|
|
return last_i[i];
|
|
}
|
|
|
|
min_dist = 256 * 256 + 256 * 256 + 256 * 256;
|
|
biggest_delta = 256 * 256;
|
|
min_index = 0;
|
|
|
|
for ( i = 0; i < 256; i++ )
|
|
{
|
|
dr = abs( palette_r[i] - r );
|
|
if ( dr > biggest_delta ) {
|
|
continue;
|
|
}
|
|
dg = abs( palette_g[i] - g );
|
|
if ( dg > biggest_delta ) {
|
|
continue;
|
|
}
|
|
db = abs( palette_b[i] - b );
|
|
if ( db > biggest_delta ) {
|
|
continue;
|
|
}
|
|
|
|
dist = dr * dr + dg * dg + db * db;
|
|
if ( dist < min_dist ) {
|
|
min_dist = dist;
|
|
min_index = i;
|
|
if ( min_dist == 0 ) {
|
|
break;
|
|
}
|
|
|
|
dist = dr;
|
|
if ( dg > dist ) {
|
|
dist = dg;
|
|
}
|
|
if ( db > dist ) {
|
|
dist = db;
|
|
}
|
|
if ( dist < biggest_delta ) {
|
|
biggest_delta = dist;
|
|
}
|
|
}
|
|
}
|
|
|
|
last_place++;
|
|
if ( last_place >= MAX_LAST ) {
|
|
last_place = 0;
|
|
}
|
|
|
|
last_r[last_place] = r;
|
|
last_g[last_place] = g;
|
|
last_b[last_place] = b;
|
|
last_i[last_place] = min_index;
|
|
|
|
return min_index;
|
|
}
|
|
|
|
|
|
void GL_ResampleTexture8P( byte *in, int inwidth, int inheight, byte *out,
|
|
int outwidth, int outheight, palette_t *palette ){
|
|
int i, j;
|
|
byte *inrow, *inrow2;
|
|
unsigned frac, fracstep;
|
|
unsigned p1[1024], p2[1024], *p1p, *p2p;
|
|
palette_t *c1,*c2,*c3,*c4;
|
|
unsigned r,g,b;
|
|
|
|
fracstep = inwidth * 0x10000 / outwidth;
|
|
|
|
frac = fracstep >> 2;
|
|
for ( i = 0 ; i < outwidth ; i++ )
|
|
{
|
|
p1[i] = frac >> 16;
|
|
frac += fracstep;
|
|
}
|
|
frac = 3 * ( fracstep >> 2 );
|
|
for ( i = 0 ; i < outwidth ; i++ )
|
|
{
|
|
p2[i] = frac >> 16;
|
|
frac += fracstep;
|
|
}
|
|
|
|
cached = 0;
|
|
|
|
for ( i = 0 ; i < outheight ; i++ ) //, out += outwidth)
|
|
{
|
|
inrow = in + inwidth * (int)( ( i + 0.25 ) * inheight / outheight );
|
|
inrow2 = in + inwidth * (int)( ( i + 0.75 ) * inheight / outheight );
|
|
|
|
p1p = p1;
|
|
p2p = p2;
|
|
for ( j = 0 ; j < outwidth ; j++ )
|
|
{
|
|
c1 = &palette[*( (byte *)inrow + ( *p1p ) )];
|
|
c2 = &palette[*( (byte *)inrow + ( *p2p ) )];
|
|
c3 = &palette[*( (byte *)inrow2 + ( *p1p++ ) )];
|
|
c4 = &palette[*( (byte *)inrow2 + ( *p2p++ ) )];
|
|
|
|
r = ( (unsigned)c1->r + (unsigned)c2->r + (unsigned)c3->r + (unsigned)c4->r ) >> 2;
|
|
g = ( (unsigned)c1->g + (unsigned)c2->g + (unsigned)c3->g + (unsigned)c4->g ) >> 2;
|
|
b = ( (unsigned)c1->b + (unsigned)c2->b + (unsigned)c3->b + (unsigned)c4->b ) >> 2;
|
|
|
|
*out++ = ConvertTrueColorToPal( r,g,b );
|
|
}
|
|
}
|
|
}
|
|
|
|
void GL_MipMap8P( byte *out, byte *in, int width, int height, palette_t *palette ){
|
|
int i, j;
|
|
palette_t *c1,*c2,*c3,*c4;
|
|
unsigned r,g,b;
|
|
|
|
cached = 0;
|
|
memset( out, 0, 256 * 256 );
|
|
width <<= 1;
|
|
height <<= 1;
|
|
|
|
for ( i = 0; i < height; i += 2, in += width )
|
|
{
|
|
for ( j = 0; j < width; j += 2 )
|
|
{
|
|
c1 = &palette[in[0]];
|
|
c3 = &palette[in[width]];
|
|
in++;
|
|
c2 = &palette[in[0]];
|
|
c4 = &palette[in[width]];
|
|
in++;
|
|
|
|
r = ( (unsigned)c1->r + (unsigned)c2->r + (unsigned)c3->r + (unsigned)c4->r ) >> 2;
|
|
g = ( (unsigned)c1->g + (unsigned)c2->g + (unsigned)c3->g + (unsigned)c4->g ) >> 2;
|
|
b = ( (unsigned)c1->b + (unsigned)c2->b + (unsigned)c3->b + (unsigned)c4->b ) >> 2;
|
|
|
|
*out++ = ConvertTrueColorToPal( r, g, b );
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
miptex_t *CreateMip( byte *data, unsigned width, unsigned height, byte *palette, int *FinalSize, qboolean mip ){
|
|
int scaled_width, scaled_height;
|
|
int i,j,r,g,b;
|
|
byte intensitytable[256];
|
|
byte scaled[256 * 256];
|
|
byte out[256 * 256];
|
|
int miplevel;
|
|
miptex_t *mp;
|
|
byte *pos;
|
|
int size;
|
|
|
|
for ( i = 0 ; i < 256 ; i++ )
|
|
{
|
|
j = i * intensity_value;
|
|
if ( j > 255 ) {
|
|
j = 255;
|
|
}
|
|
intensitytable[i] = j;
|
|
}
|
|
|
|
for ( scaled_width = 1 ; scaled_width < width ; scaled_width <<= 1 )
|
|
;
|
|
if ( 1 && scaled_width > width && 1 ) {
|
|
scaled_width >>= 1;
|
|
}
|
|
for ( scaled_height = 1 ; scaled_height < height ; scaled_height <<= 1 )
|
|
;
|
|
if ( 1 && scaled_height > height && 1 ) {
|
|
scaled_height >>= 1;
|
|
}
|
|
|
|
// don't ever bother with >256 textures
|
|
if ( scaled_width > 256 ) {
|
|
scaled_width = 256;
|
|
}
|
|
if ( scaled_height > 256 ) {
|
|
scaled_height = 256;
|
|
}
|
|
|
|
if ( scaled_width < 1 ) {
|
|
scaled_width = 1;
|
|
}
|
|
if ( scaled_height < 1 ) {
|
|
scaled_height = 1;
|
|
}
|
|
|
|
size = sizeof( *mp ) + ( scaled_width * scaled_height * 3 );
|
|
mp = (miptex_t *)SafeMalloc( size, "CreateMip" );
|
|
memset( mp,0,size );
|
|
|
|
mp->version = MIP_VERSION;
|
|
|
|
for ( i = j = 0; i < 256; i++,j += 3 )
|
|
{
|
|
mp->palette[i].r = r = intensitytable[palette[j]];
|
|
mp->palette[i].g = g = intensitytable[palette[j + 1]];
|
|
mp->palette[i].b = b = intensitytable[palette[j + 2]];
|
|
image_pal[i] = 0xff000000 | ( r << 16 ) | ( g << 8 ) | ( b );
|
|
}
|
|
|
|
PrepareConvert( image_pal );
|
|
|
|
if ( scaled_width == width && scaled_height == height ) {
|
|
memcpy( scaled, data, width * height );
|
|
}
|
|
else{
|
|
GL_ResampleTexture8P( data, width, height, scaled, scaled_width, scaled_height, mp->palette );
|
|
}
|
|
|
|
pos = (byte *)( mp + 1 );
|
|
miplevel = 0;
|
|
|
|
while ( ( scaled_width >= 1 || scaled_height >= 1 ) && ( miplevel <= MIPLEVELS - 1 ) && ( !miplevel || mip ) )
|
|
{
|
|
if ( scaled_width < 1 ) {
|
|
scaled_width = 1;
|
|
}
|
|
if ( scaled_height < 1 ) {
|
|
scaled_height = 1;
|
|
}
|
|
|
|
if ( miplevel > 0 ) {
|
|
GL_MipMap8P( out, (byte *)scaled, scaled_width, scaled_height, mp->palette );
|
|
}
|
|
else{
|
|
memcpy( out, scaled, 256 * 256 );
|
|
}
|
|
|
|
mp->width[miplevel] = scaled_width;
|
|
mp->height[miplevel] = scaled_height;
|
|
mp->offsets[miplevel] = pos - ( (byte *)( mp ) );
|
|
memcpy( pos, out, scaled_width * scaled_height );
|
|
memcpy( scaled, out, 256 * 256 );
|
|
pos += scaled_width * scaled_height;
|
|
|
|
scaled_width >>= 1;
|
|
scaled_height >>= 1;
|
|
|
|
miplevel++;
|
|
}
|
|
|
|
*FinalSize = pos - ( (byte *)( mp ) );
|
|
|
|
return mp;
|
|
}
|
|
|
|
|
|
void GL_ResampleTexture( unsigned *in, int inwidth, int inheight, unsigned *out, int outwidth, int outheight ){
|
|
int i, j;
|
|
unsigned *inrow, *inrow2;
|
|
unsigned frac, fracstep;
|
|
unsigned p1[1024], p2[1024];
|
|
byte *pix1, *pix2, *pix3, *pix4;
|
|
|
|
fracstep = inwidth * 0x10000 / outwidth;
|
|
|
|
frac = fracstep >> 2;
|
|
for ( i = 0 ; i < outwidth ; i++ )
|
|
{
|
|
p1[i] = 4 * ( frac >> 16 );
|
|
frac += fracstep;
|
|
}
|
|
frac = 3 * ( fracstep >> 2 );
|
|
for ( i = 0 ; i < outwidth ; i++ )
|
|
{
|
|
p2[i] = 4 * ( frac >> 16 );
|
|
frac += fracstep;
|
|
}
|
|
|
|
for ( i = 0 ; i < outheight ; i++, out += outwidth )
|
|
{
|
|
inrow = in + inwidth * (int)( ( i + 0.25 ) * inheight / outheight );
|
|
inrow2 = in + inwidth * (int)( ( i + 0.75 ) * inheight / outheight );
|
|
frac = fracstep >> 1;
|
|
for ( j = 0 ; j < outwidth ; j++ )
|
|
{
|
|
pix1 = (byte *)inrow + p1[j];
|
|
pix2 = (byte *)inrow + p2[j];
|
|
pix3 = (byte *)inrow2 + p1[j];
|
|
pix4 = (byte *)inrow2 + p2[j];
|
|
( (byte *)( out + j ) )[0] = ( pix1[0] + pix2[0] + pix3[0] + pix4[0] ) >> 2;
|
|
( (byte *)( out + j ) )[1] = ( pix1[1] + pix2[1] + pix3[1] + pix4[1] ) >> 2;
|
|
( (byte *)( out + j ) )[2] = ( pix1[2] + pix2[2] + pix3[2] + pix4[2] ) >> 2;
|
|
( (byte *)( out + j ) )[3] = ( pix1[3] + pix2[3] + pix3[3] + pix4[3] ) >> 2;
|
|
}
|
|
}
|
|
}
|
|
|
|
void GL_MipMap( byte *out, byte *in, int width, int height ){
|
|
int i, j;
|
|
|
|
width <<= 3;
|
|
height <<= 1;
|
|
for ( i = 0 ; i < height ; i++, in += width )
|
|
{
|
|
for ( j = 0 ; j < width ; j += 8, out += 4, in += 8 )
|
|
{
|
|
out[0] = ( in[0] + in[4] + in[width + 0] + in[width + 4] ) >> 2;
|
|
out[1] = ( in[1] + in[5] + in[width + 1] + in[width + 5] ) >> 2;
|
|
out[2] = ( in[2] + in[6] + in[width + 2] + in[width + 6] ) >> 2;
|
|
out[3] = ( in[3] + in[7] + in[width + 3] + in[width + 7] ) >> 2;
|
|
}
|
|
}
|
|
}
|
|
|
|
miptex32_t *CreateMip32( unsigned *data, unsigned width, unsigned height, int *FinalSize, qboolean mip ){
|
|
int scaled_width, scaled_height;
|
|
unsigned scaled[MAX_IMAGE_SIZE * MAX_IMAGE_SIZE];
|
|
unsigned out[MAX_IMAGE_SIZE * MAX_IMAGE_SIZE];
|
|
int miplevel;
|
|
miptex32_t *mp;
|
|
byte *pos;
|
|
int size;
|
|
paletteRGBA_t *test;
|
|
|
|
for ( scaled_width = 1 ; scaled_width < width ; scaled_width <<= 1 )
|
|
;
|
|
if ( 1 && scaled_width > width && 1 ) {
|
|
scaled_width >>= 1;
|
|
}
|
|
for ( scaled_height = 1 ; scaled_height < height ; scaled_height <<= 1 )
|
|
;
|
|
if ( 1 && scaled_height > height && 1 ) {
|
|
scaled_height >>= 1;
|
|
}
|
|
|
|
// don't ever bother with >256 textures
|
|
if ( scaled_width > MAX_IMAGE_SIZE ) {
|
|
scaled_width = MAX_IMAGE_SIZE;
|
|
}
|
|
if ( scaled_height > MAX_IMAGE_SIZE ) {
|
|
scaled_height = MAX_IMAGE_SIZE;
|
|
}
|
|
|
|
if ( scaled_width < 1 ) {
|
|
scaled_width = 1;
|
|
}
|
|
if ( scaled_height < 1 ) {
|
|
scaled_height = 1;
|
|
}
|
|
|
|
size = sizeof( *mp ) + ( scaled_width * scaled_height * 3 * 4 );
|
|
mp = (miptex32_t *)SafeMalloc( size, "CreateMip" );
|
|
memset( mp,0,size );
|
|
|
|
mp->version = MIP32_VERSION;
|
|
|
|
size = width * height;
|
|
test = (paletteRGBA_t *)data;
|
|
while ( size )
|
|
{
|
|
if ( test->a != 255 ) {
|
|
mp->flags |= LittleLong( SURF_ALPHA_TEXTURE );
|
|
break;
|
|
}
|
|
|
|
size--;
|
|
test++;
|
|
}
|
|
|
|
if ( scaled_width == width && scaled_height == height ) {
|
|
memcpy( scaled, data, width * height * 4 );
|
|
}
|
|
else{
|
|
GL_ResampleTexture( data, width, height, scaled, scaled_width, scaled_height );
|
|
}
|
|
|
|
pos = (byte *)( mp + 1 );
|
|
miplevel = 0;
|
|
|
|
while ( ( scaled_width >= 1 || scaled_height >= 1 ) && ( miplevel <= MIPLEVELS - 1 ) && ( !miplevel || mip ) )
|
|
{
|
|
if ( scaled_width < 1 ) {
|
|
scaled_width = 1;
|
|
}
|
|
if ( scaled_height < 1 ) {
|
|
scaled_height = 1;
|
|
}
|
|
|
|
if ( miplevel > 0 ) {
|
|
GL_MipMap( (byte *)out, (byte *)scaled, scaled_width, scaled_height );
|
|
}
|
|
else
|
|
{
|
|
memcpy( out, scaled, MAX_IMAGE_SIZE * MAX_IMAGE_SIZE * 4 );
|
|
}
|
|
|
|
mp->width[miplevel] = scaled_width;
|
|
mp->height[miplevel] = scaled_height;
|
|
mp->offsets[miplevel] = pos - ( (byte *)( mp ) );
|
|
memcpy( pos, out, scaled_width * scaled_height * 4 );
|
|
memcpy( scaled, out, MAX_IMAGE_SIZE * MAX_IMAGE_SIZE * 4 );
|
|
pos += scaled_width * scaled_height * 4;
|
|
|
|
scaled_width >>= 1;
|
|
scaled_height >>= 1;
|
|
|
|
miplevel++;
|
|
}
|
|
|
|
*FinalSize = pos - ( (byte *)( mp ) );
|
|
|
|
return mp;
|
|
}
|
|
|
|
/*
|
|
==============
|
|
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];
|
|
|
|
GetScriptToken( 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;
|
|
}
|
|
|
|
GetScriptToken( false );
|
|
xl = atoi( token );
|
|
GetScriptToken( false );
|
|
yl = atoi( token );
|
|
GetScriptToken( false );
|
|
w = atoi( token );
|
|
GetScriptToken( 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 = (byte *) SafeMalloc( w * h, "Cmd_Grab" );
|
|
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];
|
|
|
|
GetScriptToken( false );
|
|
|
|
sprintf( savename, "%s%s.lmp", gamedir, token );
|
|
|
|
if ( g_release ) {
|
|
sprintf( dest, "%s.lmp", token );
|
|
ReleaseFile( dest );
|
|
return;
|
|
}
|
|
|
|
GetScriptToken( false );
|
|
xl = atoi( token );
|
|
GetScriptToken( false );
|
|
yl = atoi( token );
|
|
GetScriptToken( false );
|
|
w = atoi( token );
|
|
GetScriptToken( 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 = (byte *) SafeMalloc( w * h, "Cmd_Raw" );
|
|
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 ( !ScriptTokenAvailable() ) { // just setting colormap_issued
|
|
return;
|
|
}
|
|
|
|
GetScriptToken( 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 = (byte *) SafeMalloc( ( levels + 256 ) * 256, "Cmd_ColorMap" );
|
|
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_altnamevalue,
|
|
pt_damagenamevalue,
|
|
pt_flagvalue,
|
|
pt_materialvalue,
|
|
pt_scale,
|
|
pt_mip,
|
|
pt_detail,
|
|
pt_gl,
|
|
pt_nomip,
|
|
pt_detailer,
|
|
} parmtype_t;
|
|
|
|
typedef struct
|
|
{
|
|
char *name;
|
|
int flags;
|
|
parmtype_t type;
|
|
} mipparm_t;
|
|
|
|
mipparm_t mipparms[] =
|
|
{
|
|
// utility content attributes
|
|
{"pushpull",CONTENTS_PUSHPULL, pt_contents},
|
|
{"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
|
|
|
|
{"animspeed",SURF_ANIMSPEED, pt_flagvalue}, // value will hold the anim speed in fps
|
|
|
|
// texture chaining
|
|
{"anim", 0, pt_animvalue}, // animname is the next animation
|
|
{"alt", 0, pt_altnamevalue}, // altname is the alternate texture
|
|
{"damage", 0, pt_damagenamevalue}, // damagename is the damage texture
|
|
{"scale", 0, pt_scale}, // next two values are for scale
|
|
{"mip", 0, pt_mip},
|
|
{"detail", 0, pt_detail},
|
|
|
|
{"GL_ZERO", GL_ZERO, pt_gl},
|
|
{"GL_ONE", GL_ONE, pt_gl},
|
|
{"GL_SRC_COLOR", GL_SRC_COLOR, pt_gl},
|
|
{"GL_ONE_MINUS_SRC_COLOR", GL_ONE_MINUS_SRC_COLOR, pt_gl},
|
|
{"GL_DST_COLOR", GL_DST_COLOR, pt_gl},
|
|
{"GL_ONE_MINUS_DST_COLOR", GL_ONE_MINUS_DST_COLOR, pt_gl},
|
|
{"GL_SRC_ALPHA", GL_SRC_ALPHA, pt_gl},
|
|
{"GL_ONE_MINUS_SRC_ALPHA", GL_ONE_MINUS_SRC_ALPHA, pt_gl},
|
|
{"GL_DST_ALPHA", GL_DST_ALPHA, pt_gl},
|
|
{"GL_ONE_MINUS_DST_ALPHA", GL_ONE_MINUS_DST_ALPHA, pt_gl},
|
|
{"GL_SRC_ALPHA_SATURATE", GL_SRC_ALPHA_SATURATE, pt_gl},
|
|
|
|
// 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
|
|
{"alpha", SURF_ALPHA_TEXTURE, pt_flags},
|
|
{"undulate", SURF_UNDULATE, pt_flags}, // rock surface up and down...
|
|
{"skyreflect", SURF_SKYREFLECT, pt_flags}, // liquid will somewhat reflect the sky - not quite finished....
|
|
|
|
{"material", SURF_MATERIAL, pt_materialvalue},
|
|
{"metal", SURF_TYPE_METAL, pt_flags},
|
|
{"stone", SURF_TYPE_STONE, pt_flags},
|
|
{"wood", SURF_TYPE_WOOD, pt_flags},
|
|
|
|
{"m_nomip", 0, pt_nomip},
|
|
{"m_detail", 0, pt_detailer},
|
|
|
|
{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 xl,yl,xh,yh,w,h;
|
|
byte *dest, *source;
|
|
int flags, value, contents;
|
|
mipparm_t *mp;
|
|
char lumpname[128];
|
|
char altname[128];
|
|
char animname[128];
|
|
char damagename[128];
|
|
byte buffer[MAX_IMAGE_SIZE * MAX_IMAGE_SIZE];
|
|
unsigned bufferl[MAX_IMAGE_SIZE * MAX_IMAGE_SIZE];
|
|
materialtype_t *mat;
|
|
char filename[1024];
|
|
unsigned *destl, *sourcel;
|
|
int linedelta, x, y;
|
|
int size;
|
|
miptex_t *qtex;
|
|
miptex32_t *qtex32;
|
|
float scale_x, scale_y;
|
|
int mip_scale;
|
|
// detail texturing
|
|
char dt_name[128];
|
|
float dt_scale_x, dt_scale_y;
|
|
float dt_u, dt_v;
|
|
float dt_alpha;
|
|
int dt_src_blend_mode, dt_dst_blend_mode;
|
|
int flags2;
|
|
|
|
|
|
GetScriptToken( false );
|
|
strcpy( lumpname, token );
|
|
|
|
GetScriptToken( false );
|
|
xl = atoi( token );
|
|
GetScriptToken( false );
|
|
yl = atoi( token );
|
|
GetScriptToken( false );
|
|
w = atoi( token );
|
|
GetScriptToken( false );
|
|
h = atoi( token );
|
|
|
|
total_x += w;
|
|
total_y += h;
|
|
total_textures++;
|
|
|
|
if ( ( w & 15 ) || ( h & 15 ) ) {
|
|
Error( "line %i: miptex sizes must be multiples of 16", scriptline );
|
|
}
|
|
|
|
flags = 0;
|
|
flags2 = 0;
|
|
contents = 0;
|
|
value = 0;
|
|
mip_scale = 0;
|
|
|
|
altname[0] = animname[0] = damagename[0] = 0;
|
|
|
|
scale_x = scale_y = 0.5;
|
|
|
|
// detail texturing
|
|
dt_name[0] = 0;
|
|
dt_scale_x = dt_scale_y = 0.0;
|
|
dt_u = dt_v = 0.0;
|
|
dt_alpha = 0.0;
|
|
dt_src_blend_mode = dt_dst_blend_mode = 0;
|
|
|
|
// get optional flags and values
|
|
while ( ScriptTokenAvailable() )
|
|
{
|
|
GetScriptToken( false );
|
|
|
|
for ( mp = mipparms ; mp->name ; mp++ )
|
|
{
|
|
if ( !strcmp( mp->name, token ) ) {
|
|
switch ( mp->type )
|
|
{
|
|
case pt_animvalue:
|
|
GetScriptToken( false ); // specify the next animation frame
|
|
strcpy( animname, token );
|
|
break;
|
|
case pt_altnamevalue:
|
|
GetScriptToken( false ); // specify the alternate texture
|
|
strcpy( altname, token );
|
|
break;
|
|
case pt_damagenamevalue:
|
|
GetScriptToken( false ); // specify the damage texture
|
|
strcpy( damagename, token );
|
|
break;
|
|
case pt_flags:
|
|
flags |= mp->flags;
|
|
break;
|
|
case pt_contents:
|
|
contents |= mp->flags;
|
|
break;
|
|
case pt_flagvalue:
|
|
flags |= mp->flags;
|
|
GetScriptToken( false ); // specify the light value
|
|
value = atoi( token );
|
|
break;
|
|
case pt_materialvalue:
|
|
GetScriptToken( false );
|
|
for ( mat = materialtypes ; mat->name ; mat++ )
|
|
{
|
|
if ( !strcmp( mat->name, token ) ) {
|
|
// assumes SURF_MATERIAL is in top 8 bits
|
|
flags = ( flags & 0x0FFFFFF ) | ( mat->value << 24 );
|
|
break;
|
|
}
|
|
}
|
|
break;
|
|
case pt_scale:
|
|
GetScriptToken( false ); // specify the x scale
|
|
scale_x = atof( token );
|
|
GetScriptToken( false ); // specify the y scale
|
|
scale_y = atof( token );
|
|
break;
|
|
|
|
case pt_mip:
|
|
mip_scale = 1;
|
|
break;
|
|
|
|
case pt_detailer:
|
|
flags2 |= MIP32_DETAILER_FLAG2;
|
|
break;
|
|
|
|
case pt_nomip:
|
|
flags2 |= MIP32_NOMIP_FLAG2;
|
|
break;
|
|
|
|
case pt_detail:
|
|
GetScriptToken( false );
|
|
strcpy( dt_name, token );
|
|
GetScriptToken( false );
|
|
dt_scale_x = atof( token );
|
|
GetScriptToken( false );
|
|
dt_scale_y = atof( token );
|
|
GetScriptToken( false );
|
|
dt_u = atof( token );
|
|
GetScriptToken( false );
|
|
dt_v = atof( token );
|
|
GetScriptToken( false );
|
|
dt_alpha = atof( token );
|
|
GetScriptToken( false );
|
|
for ( mp = mipparms ; mp->name ; mp++ )
|
|
{
|
|
if ( !strcmp( mp->name, token ) ) {
|
|
if ( mp->type == pt_gl ) {
|
|
dt_src_blend_mode = mp->flags;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
if ( !mp->name ) {
|
|
Error( "line %i: invalid gl blend mode %s", scriptline, token );
|
|
}
|
|
GetScriptToken( false );
|
|
for ( mp = mipparms ; mp->name ; mp++ )
|
|
{
|
|
if ( !strcmp( mp->name, token ) ) {
|
|
if ( mp->type == pt_gl ) {
|
|
dt_dst_blend_mode = mp->flags;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
if ( !mp->name ) {
|
|
Error( "line %i: invalid gl blend mode %s", scriptline, token );
|
|
}
|
|
break;
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
if ( !mp->name ) {
|
|
Error( "line %i: unknown parm %s", scriptline, token );
|
|
}
|
|
}
|
|
|
|
if ( g_release ) {
|
|
return; // textures are only released by $maps
|
|
|
|
}
|
|
xh = xl + w;
|
|
yh = yl + h;
|
|
if ( xh * yh > MAX_IMAGE_SIZE * MAX_IMAGE_SIZE ) {
|
|
Error( "line %i image %s: image is too big!", scriptline, lumpname );
|
|
}
|
|
|
|
if ( TrueColorImage ) {
|
|
if ( xl >= longimagewidth || xh > longimagewidth ||
|
|
yl >= longimageheight || yh > longimageheight ) {
|
|
Error( "line %i image %s: bad clip dimmensions (%d,%d) (%d,%d) > image (%d,%d)", scriptline, lumpname, xl,yl,w,h,longimagewidth,longimageheight );
|
|
}
|
|
|
|
sourcel = longimage + ( yl * longimagewidth ) + xl;
|
|
destl = bufferl;
|
|
linedelta = ( longimagewidth - w );
|
|
|
|
for ( y = yl ; y < yh ; y++ )
|
|
{
|
|
for ( x = xl ; x < xh ; x++ )
|
|
{
|
|
*destl++ = *sourcel++; // RGBA
|
|
}
|
|
sourcel += linedelta;
|
|
}
|
|
|
|
qtex32 = CreateMip32( bufferl, w, h, &size, true );
|
|
|
|
qtex32->flags |= LittleLong( flags );
|
|
qtex32->flags2 |= LittleLong( flags2 );
|
|
qtex32->contents = LittleLong( contents );
|
|
qtex32->value = LittleLong( value );
|
|
qtex32->scale_x = scale_x;
|
|
qtex32->scale_y = scale_y;
|
|
qtex32->mip_scale = mip_scale;
|
|
sprintf( qtex32->name, "%s/%s", mip_prefix, lumpname );
|
|
if ( animname[0] ) {
|
|
sprintf( qtex32->animname, "%s/%s", mip_prefix, animname );
|
|
}
|
|
if ( altname[0] ) {
|
|
sprintf( qtex32->altname, "%s/%s", mip_prefix, altname );
|
|
}
|
|
if ( damagename[0] ) {
|
|
sprintf( qtex32->damagename, "%s/%s", mip_prefix, damagename );
|
|
}
|
|
if ( dt_name[0] & ( ( flags2 & MIP32_DETAILER_FLAG2 ) == 0 ) ) {
|
|
sprintf( qtex32->dt_name, "%s/%s", mip_prefix, dt_name );
|
|
qtex32->dt_scale_x = dt_scale_x;
|
|
qtex32->dt_scale_y = dt_scale_y;
|
|
qtex32->dt_u = dt_u;
|
|
qtex32->dt_v = dt_v;
|
|
qtex32->dt_alpha = dt_alpha;
|
|
qtex32->dt_src_blend_mode = dt_src_blend_mode;
|
|
qtex32->dt_dst_blend_mode = dt_dst_blend_mode;
|
|
}
|
|
|
|
//
|
|
// write it out
|
|
//
|
|
sprintf( filename, "%stextures/%s/%s.m32", g_outputDir, mip_prefix, lumpname );
|
|
if ( qtex32->flags & ( SURF_ALPHA_TEXTURE ) ) {
|
|
printf( "writing %s with ALPHA\n", filename );
|
|
}
|
|
else{
|
|
printf( "writing %s\n", filename );
|
|
}
|
|
SaveFile( filename, (byte *)qtex32, size );
|
|
|
|
free( qtex32 );
|
|
}
|
|
else
|
|
{
|
|
if ( xl >= byteimagewidth || xh > byteimagewidth ||
|
|
yl >= byteimageheight || yh > byteimageheight ) {
|
|
Error( "line %i: bad clip dimmensions (%d,%d) (%d,%d) > image (%d,%d)", scriptline, xl,yl,w,h,byteimagewidth,byteimageheight );
|
|
}
|
|
|
|
source = byteimage + yl * byteimagewidth + xl;
|
|
dest = buffer;
|
|
linedelta = byteimagewidth - w;
|
|
|
|
for ( y = yl ; y < yh ; y++ )
|
|
{
|
|
for ( x = xl ; x < xh ; x++ )
|
|
{
|
|
*dest++ = *source++;
|
|
}
|
|
source += linedelta;
|
|
}
|
|
|
|
qtex = CreateMip( buffer, w, h, lbmpalette, &size, true );
|
|
|
|
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 );
|
|
}
|
|
|
|
//
|
|
// write it out
|
|
//
|
|
sprintf( filename, "%stextures/%s/%s.m8", g_outputDir, mip_prefix, lumpname );
|
|
printf( "writing %s\n", filename );
|
|
SaveFile( filename, (byte *)qtex, size );
|
|
|
|
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];
|
|
|
|
GetScriptToken( false );
|
|
strcpy( mip_prefix, token );
|
|
// create the directory if needed
|
|
sprintf( filename, "%stextures", g_outputDir );
|
|
Q_mkdir( filename );
|
|
sprintf( filename, "%stextures/%s", g_outputDir, 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;
|
|
|
|
GetScriptToken( 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 );
|
|
}
|
|
}
|
|
}
|