Skip to content

Commit

Permalink
* Rewrite of R_LoadImage to make it more generic and data driven
Browse files Browse the repository at this point in the history
  • Loading branch information
timangus committed Aug 26, 2007
1 parent 6993861 commit 034e6e8
Show file tree
Hide file tree
Showing 6 changed files with 117 additions and 44 deletions.
17 changes: 16 additions & 1 deletion README
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
1 change: 0 additions & 1 deletion code/qcommon/files.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
22 changes: 22 additions & 0 deletions code/qcommon/q_shared.c
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
1 change: 1 addition & 0 deletions code/qcommon/q_shared.h
Original file line number Diff line number Diff line change
Expand Up @@ -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 );

Expand Down
111 changes: 75 additions & 36 deletions code/renderer/tr_image.c
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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;
}

if ( !Q_stricmp( name+len-4, ".tga" ) ) {
LoadTGA( name, pic, width, height );
Q_strncpyz( localName, name, MAX_QPATH );

// 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];
ext = COM_GetExtension( localName );

strcpy( altname, name );
len = strlen( altname );
altname[len-3] = 'j';
altname[len-2] = 'p';
altname[len-1] = 'g';
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;
}
}

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") )
{
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" ) )

// Try and find a suitable match using all
// the image formats supported
for( i = 0; i < numImageLoaders; i++ )
{
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;
}
}
}

Expand Down
9 changes: 3 additions & 6 deletions code/renderer/tr_shader.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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();
}
Expand Down

0 comments on commit 034e6e8

Please sign in to comment.