* Rewrite of R_LoadImage to make it more generic and data driven

This commit is contained in:
Tim Angus 2007-08-26 21:27:46 +00:00
parent 6993861080
commit 034e6e8f20
6 changed files with 117 additions and 44 deletions

17
README
View file

@ -314,10 +314,25 @@ SDL Keyboard Differences
PNG support
ioquake3 supports the use of PNG (Portable Network Graphic) images as
textures. It should be noted that the use of such images in a maps will
textures. It should be noted that the use of such images in a map will
result in missing placeholder textures where the map is used with the id
Quake 3 client or earlier versions of ioquake3.
Recent versions of GtkRadiant and q3map2 support PNG images without
modification. However GtkRadiant is not aware that PNG textures are supported
by ioquake3. To change this behaviour open the file 'q3.game' in the 'games'
directory of the GtkRadiant base directory with an editor and change the
line:
texturetypes="tga jpg"
to
texturetypes="tga jpg png"
Restart GtkRadiant and PNG textures are now available.
------------------------------------------------------------- Contributing -----
Please send all patches to bugzilla (https://bugzilla.icculus.org), or join the

View file

@ -1207,7 +1207,6 @@ int FS_FOpenFileRead( const char *filename, fileHandle_t *file, qboolean uniqueF
}
}
Com_DPrintf ("Can't find %s\n", filename);
#ifdef FS_MISSING
if (missingFiles) {
fprintf(missingFiles, "%s\n", filename);

View file

@ -53,6 +53,28 @@ char *COM_SkipPath (char *pathname)
return last;
}
/*
============
COM_GetExtension
============
*/
const char *COM_GetExtension( const char *name ) {
int length, i;
length = strlen(name)-1;
i = length;
while (name[i] != '.')
{
i--;
if (name[i] == '/' || i == 0)
return ""; // no extension
}
return &name[i+1];
}
/*
============
COM_StripExtension

View file

@ -599,6 +599,7 @@ int Q_isnan( float x );
float Com_Clamp( float min, float max, float value );
char *COM_SkipPath( char *pathname );
const char *COM_GetExtension( const char *name );
void COM_StripExtension(const char *in, char *out, int destsize);
void COM_DefaultExtension( char *path, int maxSize, const char *extension );

View file

@ -4376,6 +4376,27 @@ static void LoadPNG(const char *name, byte **pic, int *width, int *height)
//===================================================================
typedef struct
{
char *ext;
void (*ImageLoader)( const char *, unsigned char **, int *, int * );
} imageExtToLoaderMap_t;
// Note that the ordering indicates the order of preference used
// when there are multiple images of different formats available
static imageExtToLoaderMap_t imageLoaders[ ] =
{
{ "tga", LoadTGA },
{ "jpg", LoadJPG },
{ "jpeg", LoadJPG },
{ "png", LoadPNG },
{ "pcx", LoadPCX32 },
{ "bmp", LoadBMP }
};
static int numImageLoaders = sizeof( imageLoaders ) /
sizeof( imageLoaders[ 0 ] );
/*
=================
R_LoadImage
@ -4384,53 +4405,71 @@ Loads any of the supported image types into a cannonical
32 bit format.
=================
*/
void R_LoadImage( const char *name, byte **pic, int *width, int *height ) {
int len;
void R_LoadImage( const char *name, byte **pic, int *width, int *height )
{
qboolean orgNameFailed = qfalse;
int i;
char localName[ MAX_QPATH ];
const char *ext;
*pic = NULL;
*width = 0;
*height = 0;
len = strlen(name);
if (len<5) {
return;
}
Q_strncpyz( localName, name, MAX_QPATH );
if ( !Q_stricmp( name+len-4, ".tga" ) ) {
LoadTGA( name, pic, width, height );
ext = COM_GetExtension( localName );
// This is a hack to get around the fact that some
// baseq3 shaders refer to tga files where the images
// are actually jpgs
if (!*pic) {
// try jpg in place of tga
char altname[MAX_QPATH];
if( *ext )
{
// Look for the correct loader and use it
for( i = 0; i < numImageLoaders; i++ )
{
if( !Q_stricmp( ext, imageLoaders[ i ].ext ) )
{
// Load
imageLoaders[ i ].ImageLoader( localName, pic, width, height );
break;
}
}
strcpy( altname, name );
len = strlen( altname );
altname[len-3] = 'j';
altname[len-2] = 'p';
altname[len-1] = 'g';
ri.Printf( PRINT_DEVELOPER, "WARNING: %s failed, trying %s\n", name, altname );
LoadJPG( altname, pic, width, height );
// A loader was found
if( i < numImageLoaders )
{
if( *pic == NULL )
{
// Loader failed, most likely because the file isn't there;
// try again without the extension
orgNameFailed = qtrue;
COM_StripExtension( name, localName, MAX_QPATH );
}
else
{
// Something loaded
return;
}
}
}
else if ( !Q_stricmp(name+len-4, ".pcx") )
// Try and find a suitable match using all
// the image formats supported
for( i = 0; i < numImageLoaders; i++ )
{
LoadPCX32( name, pic, width, height );
}
else if ( !Q_stricmp( name+len-4, ".bmp" ) )
{
LoadBMP( name, pic, width, height );
}
else if ( !Q_stricmp( name+len-4, ".jpg" ) )
{
LoadJPG( name, pic, width, height );
}
else if ( !Q_stricmp( name+len-4, ".png" ) )
{
LoadPNG( name, pic, width, height );
char *altName = va( "%s.%s", localName, imageLoaders[ i ].ext );
// Load
imageLoaders[ i ].ImageLoader( altName, pic, width, height );
if( *pic )
{
if( orgNameFailed )
{
ri.Printf( PRINT_DEVELOPER, "WARNING: %s not present, using %s instead\n",
name, altName );
}
break;
}
}
}

View file

@ -2416,7 +2416,6 @@ most world construction surfaces.
*/
shader_t *R_FindShader( const char *name, int lightmapIndex, qboolean mipRawImage ) {
char strippedName[MAX_QPATH];
char fileName[MAX_QPATH];
int i, hash;
char *shaderText;
image_t *image;
@ -2494,13 +2493,11 @@ shader_t *R_FindShader( const char *name, int lightmapIndex, qboolean mipRawImag
//
// if not defined in the in-memory shader descriptions,
// look for a single TGA, BMP, or PCX
// look for a single supported image file
//
Q_strncpyz( fileName, name, sizeof( fileName ) );
COM_DefaultExtension( fileName, sizeof( fileName ), ".tga" );
image = R_FindImageFile( fileName, mipRawImage, mipRawImage, mipRawImage ? GL_REPEAT : GL_CLAMP );
image = R_FindImageFile( name, mipRawImage, mipRawImage, mipRawImage ? GL_REPEAT : GL_CLAMP );
if ( !image ) {
ri.Printf( PRINT_DEVELOPER, "Couldn't find image for shader %s\n", name );
ri.Printf( PRINT_DEVELOPER, "Couldn't find image file for shader %s\n", name );
shader.defaultShader = qtrue;
return FinishShader();
}