mirror of
https://github.com/yquake2/yquake2remaster.git
synced 2024-11-10 07:12:07 +00:00
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:
parent
0307361101
commit
25498be7ca
2 changed files with 227 additions and 70 deletions
|
@ -20,6 +20,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
|||
|
||||
#include "header/local.h"
|
||||
|
||||
extern cvar_t *sw_retexturing;
|
||||
|
||||
#define MAX_RIMAGES 1024
|
||||
static image_t r_images[MAX_RIMAGES];
|
||||
|
@ -96,7 +97,7 @@ R_FindFreeImage (void)
|
|||
if (i == numr_images)
|
||||
{
|
||||
if (numr_images == MAX_RIMAGES)
|
||||
ri.Sys_Error (ERR_DROP, "MAX_RIMAGES");
|
||||
ri.Sys_Error(ERR_DROP, "MAX_RIMAGES");
|
||||
numr_images++;
|
||||
}
|
||||
image = &r_images[i];
|
||||
|
@ -104,6 +105,25 @@ R_FindFreeImage (void)
|
|||
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
|
||||
|
@ -114,9 +134,9 @@ static image_t *
|
|||
R_LoadPic (char *name, byte *pic, int width, int height, imagetype_t type)
|
||||
{
|
||||
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))
|
||||
ri.Sys_Error(ERR_DROP, "Draw_LoadPic: \"%s\" is too long", 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->type = type;
|
||||
|
||||
size = width*height;
|
||||
image->pixels[0] = malloc (size);
|
||||
size = width * height;
|
||||
full_size = size * (256+64+16+4)/256;
|
||||
image->pixels[0] = malloc(full_size);
|
||||
image->transparent = false;
|
||||
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);
|
||||
// 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;
|
||||
}
|
||||
|
||||
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
|
||||
|
@ -178,7 +200,7 @@ R_LoadWal (char *name, imagetype_t type)
|
|||
if (file_size < sizeof(miptex_t))
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
||||
|
@ -188,7 +210,7 @@ R_LoadWal (char *name, imagetype_t type)
|
|||
image->height = LittleLong (mt->height);
|
||||
image->type = type;
|
||||
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;
|
||||
|
||||
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))
|
||||
{
|
||||
memcpy ( image->pixels[0], (byte *)mt + ofs, file_size - ofs);
|
||||
// looks to short restore everything from first image
|
||||
R_Restore_Mip(image->pixels[0], image->pixels[1], image->height/2, image->width/2);
|
||||
R_Restore_Mip(image->pixels[1], image->pixels[2], image->height/4, image->width/4);
|
||||
R_Restore_Mip(image->pixels[2], image->pixels[3], image->height/8, image->width/8);
|
||||
memcpy(image->pixels[0], (byte *)mt + ofs, file_size - ofs);
|
||||
// looks short, 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);
|
||||
}
|
||||
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;
|
||||
}
|
||||
|
||||
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 *
|
||||
R_FindImage (char *name, imagetype_t type)
|
||||
R_FindImage(char *name, imagetype_t type)
|
||||
{
|
||||
image_t *image;
|
||||
int i, len;
|
||||
byte *pic, *palette;
|
||||
int width, height;
|
||||
int i, len;
|
||||
char *ptr;
|
||||
char namewe[256];
|
||||
const char* ext;
|
||||
|
||||
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);
|
||||
if (len<5)
|
||||
return NULL; // ri.Sys_Error (ERR_DROP, "R_FindImage: bad name: %s", name);
|
||||
|
||||
#ifndef _WIN32
|
||||
char *ptr;
|
||||
/* Remove the extension */
|
||||
memset(namewe, 0, 256);
|
||||
memcpy(namewe, name, len - (strlen(ext) + 1));
|
||||
|
||||
// fix backslashes
|
||||
while ((ptr=strchr(name,'\\'))) {
|
||||
if (len < 5)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* fix backslashes */
|
||||
while ((ptr = strchr(name, '\\')))
|
||||
{
|
||||
*ptr = '/';
|
||||
}
|
||||
#endif
|
||||
|
||||
// look for it
|
||||
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
|
||||
//
|
||||
pic = NULL;
|
||||
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;
|
||||
return R_LoadImage(name, namewe, ext, type);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -318,12 +457,10 @@ R_FreeUnusedImages (void)
|
|||
continue; // don't free pics
|
||||
// free it
|
||||
free (image->pixels[0]); // the other mip levels just follow
|
||||
memset (image, 0, sizeof(*image));
|
||||
memset(image, 0, sizeof(*image));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
===============
|
||||
R_InitImages
|
||||
|
@ -332,7 +469,19 @@ R_InitImages
|
|||
void
|
||||
R_InitImages (void)
|
||||
{
|
||||
unsigned char * table16to8;
|
||||
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)
|
||||
continue; // free texture
|
||||
|
||||
// free it
|
||||
free (image->pixels[0]); // the other mip levels just follow
|
||||
memset (image, 0, sizeof(*image));
|
||||
if (image->pixels[0])
|
||||
free(image->pixels[0]); // the other mip levels just follow
|
||||
|
||||
memset(image, 0, sizeof(*image));
|
||||
}
|
||||
|
||||
if (d_16to8table)
|
||||
free(d_16to8table);
|
||||
}
|
||||
|
|
|
@ -129,6 +129,7 @@ cvar_t *sw_waterwarp;
|
|||
static cvar_t *sw_overbrightbits;
|
||||
cvar_t *sw_custom_particles;
|
||||
cvar_t *sw_texture_filtering;
|
||||
cvar_t *sw_retexturing;
|
||||
|
||||
cvar_t *r_drawworld;
|
||||
static cvar_t *r_drawentities;
|
||||
|
@ -259,7 +260,7 @@ void R_ImageList_f(void);
|
|||
static void R_ScreenShot_f(void);
|
||||
|
||||
static void
|
||||
R_Register (void)
|
||||
R_RegisterVariables (void)
|
||||
{
|
||||
sw_aliasstats = ri.Cvar_Get ("sw_polymodelstats", "0", 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_custom_particles = ri.Cvar_Get("sw_custom_particles", "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_lefthand = ri.Cvar_Get( "hand", "0", CVAR_USERINFO | CVAR_ARCHIVE );
|
||||
|
@ -326,6 +328,7 @@ R_Init
|
|||
static qboolean
|
||||
RE_Init(void)
|
||||
{
|
||||
R_RegisterVariables ();
|
||||
R_InitImages ();
|
||||
Mod_Init ();
|
||||
Draw_InitLocal ();
|
||||
|
@ -343,7 +346,6 @@ RE_Init(void)
|
|||
|
||||
r_aliasuvscale = 1.0;
|
||||
|
||||
R_Register ();
|
||||
Draw_GetPalette ();
|
||||
|
||||
// create the window
|
||||
|
|
Loading…
Reference in a new issue