Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
147 changes: 92 additions & 55 deletions src/engine/renderer/tr_image.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1611,6 +1611,60 @@ static const imageExtToLoaderMap_t imageLoaders[] =

static int numImageLoaders = ARRAY_LEN( imageLoaders );

/*
=================
R_FindImageLoader

Finds and returns an image loader for a given basename,
tells the extra prefix that may be required to load the image.
=================
*/
static int R_FindImageLoader( const char *baseName, const char **prefix ) {
const FS::PakInfo* bestPak = nullptr;
int i;

int bestLoader = -1;
*prefix = "";
// try and find a suitable match using all the image formats supported
// prioritize with the pak priority
for ( i = 0; i < numImageLoaders; i++ )
{
std::string altName = Str::Format( "%s.%s", baseName, imageLoaders[i].ext );
const FS::PakInfo* pak = FS::PakPath::LocateFile( altName );

// We found a file and its pak is better than the best pak we have
// this relies on how the filesystem works internally and should be moved
// to a more explicit interface once there is one. (FIXME)
if ( pak != nullptr && ( bestPak == nullptr || pak < bestPak ) )
{
bestPak = pak;
bestLoader = i;
}

// DarkPlaces or Doom3 packages can ship alternative texture path in the form of
// dds/<path without ext>.dds
if ( bestPak == nullptr && !Q_stricmp( "dds", imageLoaders[i].ext ) )
{
std::string prefixedName = Str::Format( "dds/%s.dds", baseName );
bestPak = FS::PakPath::LocateFile( prefixedName );
if ( bestPak != nullptr ) {
*prefix = "dds/";
bestPak = pak;
bestLoader = i;
}
}
}

return bestLoader;
}

int R_FindImageLoader( const char *baseName ) {
// not used but required by R_FindImageLoader
const char *prefix;

return R_FindImageLoader( baseName, &prefix );
}

/*
=================
R_LoadImage
Expand Down Expand Up @@ -1682,57 +1736,23 @@ static void R_LoadImage( const char **buffer, byte **pic, int *width, int *heigh
// a loader was found
if ( i < numImageLoaders )
{
if ( *pic == nullptr )
{
// loader failed, most likely because the file isn't there;
// try again without the extension
COM_StripExtension3( token, filename, MAX_QPATH );
}
else
if ( *pic != nullptr )
{
// something loaded
return;
}
}
}

int bestLoader = -1;
const FS::PakInfo* bestPak = nullptr;

// Darkplaces or Doom3 packages can ship alternative texture path in the form of
// dds/<path without ext>.dds
std::string altName = Str::Format("dds/%s.dds", filename);
bestPak = FS::PakPath::LocateFile(altName);

// If this alternative path exists, it's expected to be loaded as the best one
// except when it goes against Daemon's rule to load the hardcoded one if exists
// because this dds alternative is only supported for compatibility with
// third-party content
if ( bestPak != nullptr ) {
LoadDDS( altName.c_str(), pic, width, height, numLayers, numMips, bits, alphaByte );
return;
}

// try and find a suitable match using all the image formats supported
// prioritize with the pak priority
for ( i = 0; i < numImageLoaders; i++ )
{
std::string altName = Str::Format("%s.%s", filename, imageLoaders[i].ext);
const FS::PakInfo* pak = FS::PakPath::LocateFile(altName);
// the file isn't there, try again without the extension
COM_StripExtension3( token, filename, MAX_QPATH );

// We found a file and its pak is better than the best pak we have
// this relies on how the filesystem works internally and should be moved
// to a more explicit interface once there is one. (FIXME)
if ( pak != nullptr && (bestPak == nullptr || pak < bestPak ) )
{
bestPak = pak;
bestLoader = i;
}
}
const char *prefix;
int bestLoader = R_FindImageLoader( filename, &prefix );

if ( bestLoader >= 0 )
{
char *altName = va( "%s.%s", filename, imageLoaders[ bestLoader ].ext );
char *altName = va( "%s%s.%s", prefix, filename, imageLoaders[ bestLoader ].ext );
imageLoaders[ bestLoader ].ImageLoader( altName, pic, width, height, numLayers, numMips, bits, alphaByte );
}
}
Expand Down Expand Up @@ -1938,6 +1958,22 @@ static void R_FreeCubePics( byte **pic, int count )
}
}

struct cubeMapLoader_t
{
const char *ext;
void ( *ImageLoader )( const char *, unsigned char **, int *, int *, int *, int *, int *, byte );
};

// Note that the ordering indicates the order of preference used
// when there are multiple images of different formats available
static const cubeMapLoader_t cubeMapLoaders[] =
{
{ "crn", LoadCRN },
{ "ktx", LoadKTX },
};

static int numCubeMapLoaders = ARRAY_LEN( cubeMapLoaders );

image_t *R_FindCubeImage( const char *imageName, int bits, filterType_t filterType, wrapType_t wrapType )
{
int i;
Expand Down Expand Up @@ -1978,22 +2014,23 @@ image_t *R_FindCubeImage( const char *imageName, int bits, filterType_t f
}
}

// try to load .CRN cubemap
LoadCRN( buffer, pic, &width, &height, &numLayers, &numMips, &bits, 0 );
if( numLayers == 6 && pic[0] ) {
numPicsToFree = 1;
goto createCubeImage;
} else {
R_FreeCubePics( pic, numLayers );
}
char cubeMapBaseName[ MAX_QPATH ];
COM_StripExtension3( buffer, cubeMapBaseName, sizeof( cubeMapBaseName ) );

// try to load .KTX cubemap
LoadKTX( buffer, pic, &width, &height, &numLayers, &numMips, &bits, 0 );
if( numLayers == 6 && pic[0] ) {
numPicsToFree = 1;
goto createCubeImage;
} else {
R_FreeCubePics( pic, numLayers );
for ( i = 0; i < numCubeMapLoaders; i++ )
{
std::string cubeMapName = Str::Format( "%s.%s", cubeMapBaseName, cubeMapLoaders[ i ].ext );
if( R_FindImageLoader( cubeMapName.c_str() ) >= 0 )
{
Log::Debug( "found %s cube map '%s'", cubeMapLoaders[ i ].ext, cubeMapBaseName );
cubeMapLoaders[ i ].ImageLoader( cubeMapName.c_str(), pic, &width, &height, &numLayers, &numMips, &bits, 0 );
if( numLayers == 6 && pic[0] ) {
numPicsToFree = 1;
goto createCubeImage;
} else {
R_FreeCubePics( pic, numLayers );
}
}
}

for ( i = 0; i < 6; i++ )
Expand Down
1 change: 1 addition & 0 deletions src/engine/renderer/tr_local.h
Original file line number Diff line number Diff line change
Expand Up @@ -3150,6 +3150,7 @@ static inline void halfToFloat( const f16vec4_t in, vec4_t out )
void R_InitImages();
void R_ShutdownImages();

int R_FindImageLoader( const char *baseName );
image_t *R_FindImageFile( const char *name, int bits, filterType_t filterType, wrapType_t wrapType );
image_t *R_FindCubeImage( const char *name, int bits, filterType_t filterType, wrapType_t wrapType );

Expand Down