Support retextured images.

Code based on www.quakewiki.net/quakesrc/39.html
Code ignores skin images, and is disabled by default.
This commit is contained in:
Denis Pauk 2018-11-12 23:02:23 +02:00
parent 0307361101
commit 25498be7ca
2 changed files with 227 additions and 70 deletions

View file

@ -20,6 +20,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#include "header/local.h" #include "header/local.h"
extern cvar_t *sw_retexturing;
#define MAX_RIMAGES 1024 #define MAX_RIMAGES 1024
static image_t r_images[MAX_RIMAGES]; static image_t r_images[MAX_RIMAGES];
@ -96,7 +97,7 @@ R_FindFreeImage (void)
if (i == numr_images) if (i == numr_images)
{ {
if (numr_images == MAX_RIMAGES) if (numr_images == MAX_RIMAGES)
ri.Sys_Error (ERR_DROP, "MAX_RIMAGES"); ri.Sys_Error(ERR_DROP, "MAX_RIMAGES");
numr_images++; numr_images++;
} }
image = &r_images[i]; image = &r_images[i];
@ -104,6 +105,25 @@ R_FindFreeImage (void)
return image; return image;
} }
static void
R_ImageShrink(const unsigned char* src, unsigned char *dst, int width, int realwidth, int height, int realheight)
{
int x, y;
float xstep, ystep;
xstep = (float)height / realheight;
ystep = (float)width / realwidth;
for (y=0; y<realheight; y++)
{
for (x=0; x<realwidth; x++)
{
// inplace update
dst[x + y * realwidth] = src[(int)(x * xstep) + (int)(y * ystep) * width];
}
}
}
/* /*
================ ================
R_LoadPic R_LoadPic
@ -114,9 +134,9 @@ static image_t *
R_LoadPic (char *name, byte *pic, int width, int height, imagetype_t type) R_LoadPic (char *name, byte *pic, int width, int height, imagetype_t type)
{ {
image_t *image; image_t *image;
size_t i, size; size_t i, size, full_size;
image = R_FindFreeImage (); image = R_FindFreeImage();
if (strlen(name) >= sizeof(image->name)) if (strlen(name) >= sizeof(image->name))
ri.Sys_Error(ERR_DROP, "Draw_LoadPic: \"%s\" is too long", name); ri.Sys_Error(ERR_DROP, "Draw_LoadPic: \"%s\" is too long", name);
strcpy (image->name, name); strcpy (image->name, name);
@ -126,8 +146,9 @@ R_LoadPic (char *name, byte *pic, int width, int height, imagetype_t type)
image->height = height; image->height = height;
image->type = type; image->type = type;
size = width*height; size = width * height;
image->pixels[0] = malloc (size); full_size = size * (256+64+16+4)/256;
image->pixels[0] = malloc(full_size);
image->transparent = false; image->transparent = false;
for (i=0 ; i<size ; i++) for (i=0 ; i<size ; i++)
{ {
@ -139,22 +160,23 @@ R_LoadPic (char *name, byte *pic, int width, int height, imagetype_t type)
} }
memcpy(image->pixels[0], pic, size); memcpy(image->pixels[0], pic, size);
// restore mips
image->pixels[1] = image->pixels[0] + image->width*image->height;
image->pixels[2] = image->pixels[1] + image->width*image->height/4;
image->pixels[3] = image->pixels[2] + image->width*image->height/16;
// restore everything from first image
R_ImageShrink(image->pixels[0], image->pixels[1],
image->height, image->height/2,
image->width, image->width/2);
R_ImageShrink(image->pixels[1], image->pixels[2],
image->height/2, image->height/4,
image->width/2, image->width/4);
R_ImageShrink(image->pixels[2], image->pixels[3],
image->height/4, image->height/8,
image->width/4, image->width/8);
return image; return image;
} }
static void
R_Restore_Mip(unsigned char* src, unsigned char *dst, int height, int width)
{
int x, y;
for (y=0; y<height; y++)
{
for (x=0; x<width; x++)
{
dst[x + y * width] = src[(x + y * width)*2];
}
}
}
/* /*
================ ================
R_LoadWal R_LoadWal
@ -178,7 +200,7 @@ R_LoadWal (char *name, imagetype_t type)
if (file_size < sizeof(miptex_t)) if (file_size < sizeof(miptex_t))
{ {
R_Printf(PRINT_ALL, "R_LoadWal: can't load %s, small header\n", name); R_Printf(PRINT_ALL, "R_LoadWal: can't load %s, small header\n", name);
ri.FS_FreeFile ((void *)mt); ri.FS_FreeFile((void *)mt);
return r_notexture_mip; return r_notexture_mip;
} }
@ -188,7 +210,7 @@ R_LoadWal (char *name, imagetype_t type)
image->height = LittleLong (mt->height); image->height = LittleLong (mt->height);
image->type = type; image->type = type;
image->registration_sequence = registration_sequence; image->registration_sequence = registration_sequence;
ofs = LittleLong (mt->offsets[0]); ofs = LittleLong(mt->offsets[0]);
size = image->width * image->height * (256+64+16+4)/256; size = image->width * image->height * (256+64+16+4)/256;
if ((ofs <= 0) || (image->width <= 0) || (image->height <= 0) || if ((ofs <= 0) || (image->width <= 0) || (image->height <= 0) ||
@ -206,22 +228,147 @@ R_LoadWal (char *name, imagetype_t type)
if (size > (file_size - ofs)) if (size > (file_size - ofs))
{ {
memcpy ( image->pixels[0], (byte *)mt + ofs, file_size - ofs); memcpy(image->pixels[0], (byte *)mt + ofs, file_size - ofs);
// looks to short restore everything from first image // looks short, restore everything from first image
R_Restore_Mip(image->pixels[0], image->pixels[1], image->height/2, image->width/2); R_ImageShrink(image->pixels[0], image->pixels[1],
R_Restore_Mip(image->pixels[1], image->pixels[2], image->height/4, image->width/4); image->height, image->height/2,
R_Restore_Mip(image->pixels[2], image->pixels[3], image->height/8, image->width/8); image->width, image->width/2);
R_ImageShrink(image->pixels[1], image->pixels[2],
image->height/2, image->height/4,
image->width/2, image->width/4);
R_ImageShrink(image->pixels[2], image->pixels[3],
image->height/4, image->height/8,
image->width/4, image->width/8);
} }
else else
{ {
memcpy ( image->pixels[0], (byte *)mt + ofs, size); memcpy(image->pixels[0], (byte *)mt + ofs, size);
} }
ri.FS_FreeFile ((void *)mt); ri.FS_FreeFile((void *)mt);
return image; return image;
} }
static unsigned char *d_16to8table; // 16 to 8 bit conversion table
static void
R_Convert32To8bit(unsigned char* pic_in, unsigned char* pic_out, size_t size)
{
size_t i;
if (!d_16to8table)
return;
for(i=0; i<size; i++)
{
unsigned int r, g, b, c;
r = ( pic_in[i * 4 + 0] >> 3 ) & 31;
g = ( pic_in[i * 4 + 1] >> 2 ) & 63;
b = ( pic_in[i * 4 + 2] >> 3 ) & 31;
c = r | ( g << 5 ) | ( b << 11 );
pic_out[i] = d_16to8table[c & 0xFFFF];
}
}
static image_t *
R_LoadHiColorImage(char *name, const char* namewe, const char *ext, imagetype_t type)
{
image_t *image = NULL;
byte *pic = NULL;
int realwidth = 0, realheight = 0;
int width = 0, height = 0;
if (strcmp(ext, "pcx") == 0)
{
/* Get size of the original texture */
GetPCXInfo(name, &realwidth, &realheight);
}
else if (strcmp(ext, "wal") == 0)
{
/* Get size of the original texture */
GetWalInfo(name, &realwidth, &realheight);
}
/* try to load a tga, png or jpg (in that order/priority) */
if ( LoadSTB(namewe, "tga", &pic, &width, &height)
|| LoadSTB(namewe, "png", &pic, &width, &height)
|| LoadSTB(namewe, "jpg", &pic, &width, &height) )
{
if (width >= realwidth && height >= realheight)
{
byte* pic8 = NULL;
int size;
if (realheight == 0 || realwidth == 0)
{
realheight = height;
realwidth = width;
}
size = width * height * (256+64+16+4)/256;
pic8 = malloc(size);
R_Convert32To8bit(pic, pic8, width * height);
if (width != realwidth || height != realheight)
{
R_ImageShrink(pic8, pic8, width, realwidth, height, realheight);
}
image = R_LoadPic(name, pic8, realwidth, realheight, type);
free(pic8);
}
}
if (!pic)
{
free(pic);
}
return image;
}
static image_t *
R_LoadImage(char *name, const char* namewe, const char *ext, imagetype_t type)
{
image_t *image = NULL;
// with retexturing and not skin
if (sw_retexturing->value && type != it_skin)
{
image = R_LoadHiColorImage(name, namewe, ext, type);
}
if (!image)
{
if (strcmp(ext, "pcx") == 0)
{
byte *pic = NULL;
byte *palette = NULL;
int width = 0, height = 0;
LoadPCX (name, &pic, &palette, &width, &height);
if (!pic)
return NULL;
image = R_LoadPic(name, pic, width, height, type);
if (palette)
{
free(palette);
}
if (!pic)
{
free(pic);
}
}
else if (strcmp(ext, "wal") == 0)
{
image = R_LoadWal(name, type);
}
}
return image;
}
/* /*
=============== ===============
@ -231,27 +378,42 @@ Finds or loads the given image
=============== ===============
*/ */
image_t * image_t *
R_FindImage (char *name, imagetype_t type) R_FindImage(char *name, imagetype_t type)
{ {
image_t *image; image_t *image;
int i, len; int i, len;
byte *pic, *palette; char *ptr;
int width, height; char namewe[256];
const char* ext;
if (!name) if (!name)
return NULL; // ri.Sys_Error (ERR_DROP, "R_FindImage: NULL name"); {
return NULL;
}
ext = COM_FileExtension(name);
if(!ext[0])
{
/* file has no extension */
return NULL;
}
len = strlen(name); len = strlen(name);
if (len<5)
return NULL; // ri.Sys_Error (ERR_DROP, "R_FindImage: bad name: %s", name);
#ifndef _WIN32 /* Remove the extension */
char *ptr; memset(namewe, 0, 256);
memcpy(namewe, name, len - (strlen(ext) + 1));
// fix backslashes if (len < 5)
while ((ptr=strchr(name,'\\'))) { {
return NULL;
}
/* fix backslashes */
while ((ptr = strchr(name, '\\')))
{
*ptr = '/'; *ptr = '/';
} }
#endif
// look for it // look for it
for (i=0, image=r_images ; i<numr_images ; i++,image++) for (i=0, image=r_images ; i<numr_images ; i++,image++)
@ -266,30 +428,7 @@ R_FindImage (char *name, imagetype_t type)
// //
// load the pic from disk // load the pic from disk
// //
pic = NULL; return R_LoadImage(name, namewe, ext, type);
palette = NULL;
if (!strcmp(name+len-4, ".pcx"))
{
LoadPCX (name, &pic, &palette, &width, &height);
if (!pic)
return NULL; // ri.Sys_Error (ERR_DROP, "R_FindImage: can't load %s", name);
image = R_LoadPic (name, pic, width, height, type);
}
else if (!strcmp(name+len-4, ".wal"))
{
image = R_LoadWal (name, type);
}
else if (!strcmp(name+len-4, ".tga"))
return NULL; // ri.Sys_Error (ERR_DROP, "R_FindImage: can't load %s in software renderer", name);
else
return NULL; // ri.Sys_Error (ERR_DROP, "R_FindImage: bad extension on: %s", name);
if (pic)
free(pic);
if (palette)
free(palette);
return image;
} }
/* /*
@ -318,12 +457,10 @@ R_FreeUnusedImages (void)
continue; // don't free pics continue; // don't free pics
// free it // free it
free (image->pixels[0]); // the other mip levels just follow free (image->pixels[0]); // the other mip levels just follow
memset (image, 0, sizeof(*image)); memset(image, 0, sizeof(*image));
} }
} }
/* /*
=============== ===============
R_InitImages R_InitImages
@ -332,7 +469,19 @@ R_InitImages
void void
R_InitImages (void) R_InitImages (void)
{ {
unsigned char * table16to8;
registration_sequence = 1; registration_sequence = 1;
d_16to8table = NULL;
ri.FS_LoadFile("pics/16to8.dat", (void **)&table16to8);
if ( !table16to8 )
{
ri.Sys_Error(ERR_FATAL, "Couldn't load pics/16to8.dat");
}
d_16to8table = malloc(0x10000);
memcpy(d_16to8table, table16to8, 0x10000);
ri.FS_FreeFile((void *)table16to8);
} }
/* /*
@ -350,8 +499,14 @@ R_ShutdownImages (void)
{ {
if (!image->registration_sequence) if (!image->registration_sequence)
continue; // free texture continue; // free texture
// free it // free it
free (image->pixels[0]); // the other mip levels just follow if (image->pixels[0])
memset (image, 0, sizeof(*image)); free(image->pixels[0]); // the other mip levels just follow
memset(image, 0, sizeof(*image));
} }
if (d_16to8table)
free(d_16to8table);
} }

View file

@ -129,6 +129,7 @@ cvar_t *sw_waterwarp;
static cvar_t *sw_overbrightbits; static cvar_t *sw_overbrightbits;
cvar_t *sw_custom_particles; cvar_t *sw_custom_particles;
cvar_t *sw_texture_filtering; cvar_t *sw_texture_filtering;
cvar_t *sw_retexturing;
cvar_t *r_drawworld; cvar_t *r_drawworld;
static cvar_t *r_drawentities; static cvar_t *r_drawentities;
@ -259,7 +260,7 @@ void R_ImageList_f(void);
static void R_ScreenShot_f(void); static void R_ScreenShot_f(void);
static void static void
R_Register (void) R_RegisterVariables (void)
{ {
sw_aliasstats = ri.Cvar_Get ("sw_polymodelstats", "0", 0); sw_aliasstats = ri.Cvar_Get ("sw_polymodelstats", "0", 0);
sw_clearcolor = ri.Cvar_Get ("sw_clearcolor", "2", 0); sw_clearcolor = ri.Cvar_Get ("sw_clearcolor", "2", 0);
@ -273,6 +274,7 @@ R_Register (void)
sw_overbrightbits = ri.Cvar_Get("sw_overbrightbits", "1.0", CVAR_ARCHIVE); sw_overbrightbits = ri.Cvar_Get("sw_overbrightbits", "1.0", CVAR_ARCHIVE);
sw_custom_particles = ri.Cvar_Get("sw_custom_particles", "0", CVAR_ARCHIVE); sw_custom_particles = ri.Cvar_Get("sw_custom_particles", "0", CVAR_ARCHIVE);
sw_texture_filtering = ri.Cvar_Get("sw_texture_filtering", "0", CVAR_ARCHIVE); sw_texture_filtering = ri.Cvar_Get("sw_texture_filtering", "0", CVAR_ARCHIVE);
sw_retexturing = ri.Cvar_Get("sw_retexturing", "0", CVAR_ARCHIVE);
r_mode = ri.Cvar_Get( "r_mode", "0", CVAR_ARCHIVE ); r_mode = ri.Cvar_Get( "r_mode", "0", CVAR_ARCHIVE );
r_lefthand = ri.Cvar_Get( "hand", "0", CVAR_USERINFO | CVAR_ARCHIVE ); r_lefthand = ri.Cvar_Get( "hand", "0", CVAR_USERINFO | CVAR_ARCHIVE );
@ -326,6 +328,7 @@ R_Init
static qboolean static qboolean
RE_Init(void) RE_Init(void)
{ {
R_RegisterVariables ();
R_InitImages (); R_InitImages ();
Mod_Init (); Mod_Init ();
Draw_InitLocal (); Draw_InitLocal ();
@ -343,7 +346,6 @@ RE_Init(void)
r_aliasuvscale = 1.0; r_aliasuvscale = 1.0;
R_Register ();
Draw_GetPalette (); Draw_GetPalette ();
// create the window // create the window