vtf: 7.5 version support ( fixes #83 )
This commit is contained in:
parent
6bc71d1491
commit
eb78802b5d
@ -784,6 +784,50 @@ bool ResampleRGB323232F( const ResampleInfo_t& info )
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ResampleRGBA32323232F( const ResampleInfo_t& info )
|
||||
{
|
||||
// HDRFIXME: This is some lame shit right here. (We need to get NICE working, etc, etc.)
|
||||
|
||||
// Make sure everything is power of two.
|
||||
Assert( ( info.m_nSrcWidth & ( info.m_nSrcWidth - 1 ) ) == 0 );
|
||||
Assert( ( info.m_nSrcHeight & ( info.m_nSrcHeight - 1 ) ) == 0 );
|
||||
Assert( ( info.m_nDestWidth & ( info.m_nDestWidth - 1 ) ) == 0 );
|
||||
Assert( ( info.m_nDestHeight & ( info.m_nDestHeight - 1 ) ) == 0 );
|
||||
|
||||
// Make sure that we aren't upscaling the image. . .we don't support that very well.
|
||||
Assert( info.m_nSrcWidth >= info.m_nDestWidth );
|
||||
Assert( info.m_nSrcHeight >= info.m_nDestHeight );
|
||||
|
||||
int nSampleWidth = info.m_nSrcWidth / info.m_nDestWidth;
|
||||
int nSampleHeight = info.m_nSrcHeight / info.m_nDestHeight;
|
||||
|
||||
float *pSrc = ( float * )info.m_pSrc;
|
||||
float *pDst = ( float * )info.m_pDest;
|
||||
for( int y = 0; y < info.m_nDestHeight; y++ )
|
||||
{
|
||||
for( int x = 0; x < info.m_nDestWidth; x++ )
|
||||
{
|
||||
float accum[4] = { 0.0f, 0.0f, 0.0f, 0.0f };
|
||||
for( int nSampleY = 0; nSampleY < nSampleHeight; nSampleY++ )
|
||||
{
|
||||
for( int nSampleX = 0; nSampleX < nSampleWidth; nSampleX++ )
|
||||
{
|
||||
accum[0] += pSrc[((x*nSampleWidth+nSampleX)+(y*nSampleHeight+nSampleY)*info.m_nSrcWidth)*4+0];
|
||||
accum[1] += pSrc[((x*nSampleWidth+nSampleX)+(y*nSampleHeight+nSampleY)*info.m_nSrcWidth)*4+1];
|
||||
accum[2] += pSrc[((x*nSampleWidth+nSampleX)+(y*nSampleHeight+nSampleY)*info.m_nSrcWidth)*4+2];
|
||||
accum[3] += pSrc[((x*nSampleWidth+nSampleX)+(y*nSampleHeight+nSampleY)*info.m_nSrcWidth)*4+3];
|
||||
}
|
||||
}
|
||||
for( int i = 0; i < 4; i++ )
|
||||
{
|
||||
accum[i] /= ( nSampleWidth * nSampleHeight );
|
||||
pDst[(x+y*info.m_nDestWidth)*4+i] = accum[i];
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Generates mipmap levels
|
||||
//-----------------------------------------------------------------------------
|
||||
|
@ -459,6 +459,7 @@ namespace ImageLoader
|
||||
bool ResampleRGBA8888( const ResampleInfo_t &info );
|
||||
bool ResampleRGBA16161616( const ResampleInfo_t &info );
|
||||
bool ResampleRGB323232F( const ResampleInfo_t &info );
|
||||
bool ResampleRGBA32323232F( const ResampleInfo_t& info );
|
||||
|
||||
void ConvertNormalMapRGBA8888ToDUDVMapUVLX8888( const unsigned char *src, int width, int height,
|
||||
unsigned char *dst_ );
|
||||
|
@ -440,7 +440,7 @@ bool GetVTFPreload360Data( const char *pDebugName, CUtlBuffer &fileBufferIn, CUt
|
||||
|
||||
// version number for the disk texture cache
|
||||
#define VTF_MAJOR_VERSION 7
|
||||
#define VTF_MINOR_VERSION 4
|
||||
#define VTF_MINOR_VERSION 5
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// !!!!CRITICAL!!!! BEFORE YOU CHANGE THE FORMAT
|
||||
|
120
vtf/vtf.cpp
120
vtf/vtf.cpp
@ -190,7 +190,11 @@ IVTFTexture *CreateVTFTexture()
|
||||
|
||||
void DestroyVTFTexture( IVTFTexture *pTexture )
|
||||
{
|
||||
delete pTexture;
|
||||
CVTFTexture *pTex = static_cast<CVTFTexture*>(pTexture);
|
||||
if ( pTex )
|
||||
{
|
||||
delete pTex;
|
||||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
@ -220,6 +224,7 @@ int VTFFileHeaderSize( int nMajorVersion, int nMinorVersion )
|
||||
return sizeof( VTFFileHeaderV7_2_t );
|
||||
case 3:
|
||||
return sizeof( VTFFileHeaderV7_3_t ) + sizeof( ResourceEntryInfo ) * MAX_RSRC_DICTIONARY_ENTRIES;
|
||||
case 4:
|
||||
case VTF_MINOR_VERSION:
|
||||
int size1 = sizeof( VTFFileHeader_t );
|
||||
int size2 = sizeof( ResourceEntryInfo ) * MAX_RSRC_DICTIONARY_ENTRIES;
|
||||
@ -388,11 +393,15 @@ bool CVTFTexture::Init( int nWidth, int nHeight, int nDepth, ImageFormat fmt, in
|
||||
}
|
||||
}
|
||||
|
||||
if ( ( fmt == IMAGE_FORMAT_DXT1 ) || ( fmt == IMAGE_FORMAT_DXT3 ) || ( fmt == IMAGE_FORMAT_DXT5 ) ||
|
||||
( fmt == IMAGE_FORMAT_DXT1_RUNTIME ) || ( fmt == IMAGE_FORMAT_DXT5_RUNTIME ) )
|
||||
{
|
||||
if ( !IsMultipleOf4( nWidth ) || !IsMultipleOf4( nHeight ) || !IsMultipleOf4( nDepth ) )
|
||||
{
|
||||
Warning( "Image dimensions must be multiple of 4!\n" );
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if ( fmt == IMAGE_FORMAT_DEFAULT )
|
||||
{
|
||||
@ -676,56 +685,28 @@ bool CVTFTexture::LoadImageData( CUtlBuffer &buf, const VTFFileHeader_t &header,
|
||||
int iImageSize = ComputeFaceSize();
|
||||
iImageSize *= m_nFaceCount * m_nFrameCount;
|
||||
|
||||
// For backwards compatibility, we don't read in the spheremap fallback on
|
||||
// older format .VTF files...
|
||||
int nFacesToRead = m_nFaceCount;
|
||||
if ( IsCubeMap() )
|
||||
{
|
||||
if ((header.version[0] == 7) && (header.version[1] < 1))
|
||||
nFacesToRead = 6;
|
||||
}
|
||||
|
||||
// Even if we are preloading partial data, always do the full allocation here. We'll use LOD clamping to ensure we only
|
||||
// reference data that is available.
|
||||
if ( !AllocateImageData( iImageSize ) )
|
||||
return false;
|
||||
|
||||
// We may only have part of the data available--if so we will stream in the rest later.
|
||||
// If we have the data available but we're ignoring it (for example during development), then we
|
||||
// need to skip over the data we're ignoring below, otherwise we'll be sad pandas.
|
||||
bool bMipDataPresent = true;
|
||||
int nFirstAvailableMip = 0;
|
||||
int nLastAvailableMip = m_nMipCount - 1;
|
||||
TextureStreamSettings_t const *pStreamSettings = ( TextureStreamSettings_t const * ) GetResourceData( VTF_RSRC_TEXTURE_STREAM_SETTINGS, NULL );
|
||||
if ( pStreamSettings )
|
||||
{
|
||||
nFirstAvailableMip = Max( 0, pStreamSettings->m_firstAvailableMip - nSkipMipLevels );
|
||||
nLastAvailableMip = Max( 0, pStreamSettings->m_lastAvailableMip - nSkipMipLevels );
|
||||
bMipDataPresent = false;
|
||||
}
|
||||
|
||||
// If we have coarse mips but not the fine mips (yet)
|
||||
if ( ( header.flags & TEXTUREFLAGS_STREAMABLE ) == TEXTUREFLAGS_STREAMABLE_COARSE )
|
||||
{
|
||||
nFirstAvailableMip = Max( 0, Max( nFirstAvailableMip, STREAMING_START_MIPMAP ) - nSkipMipLevels );
|
||||
}
|
||||
|
||||
if ( header.flags & TEXTUREFLAGS_STREAMABLE_FINE )
|
||||
{
|
||||
// Don't need to subtract nSkipMipLevels: m_nMipCount has subtracted that above--assuming this assert doesn't fire.
|
||||
Assert( m_nMipCount == header.numMipLevels - nSkipMipLevels );
|
||||
nLastAvailableMip = Min( nLastAvailableMip, STREAMING_START_MIPMAP - 1 );
|
||||
}
|
||||
|
||||
// Valid settings?
|
||||
Assert( nFirstAvailableMip >= 0 && nFirstAvailableMip <= nLastAvailableMip && nLastAvailableMip < m_nMipCount );
|
||||
|
||||
// Store the clamp settings
|
||||
m_nFinestMipmapLevel = nFirstAvailableMip;
|
||||
m_nCoarsestMipmapLevel = nLastAvailableMip;
|
||||
|
||||
// NOTE: The mip levels are stored ascending from smallest (1x1) to largest (NxN)
|
||||
// in order to allow for truncated reads of the minimal required data
|
||||
|
||||
// NOTE: I checked in a bad version 4 where it stripped out the spheremap.
|
||||
// To make it all work, need to check for that bad case.
|
||||
bool bNoSkip = false;
|
||||
if ( IsCubeMap() && ( header.version[0] == 7 ) && ( header.version[1] == 4 ) )
|
||||
{
|
||||
int nBytesRemaining = buf.TellMaxPut() - buf.TellGet();
|
||||
int nFileSize = ComputeFaceSize( nSkipMipLevels ) * m_nFaceCount * m_nFrameCount;
|
||||
if ( nBytesRemaining == nFileSize )
|
||||
{
|
||||
bNoSkip = true;
|
||||
}
|
||||
}
|
||||
|
||||
int nGet = buf.TellGet();
|
||||
|
||||
retryCubemapLoad:
|
||||
for (int iMip = m_nMipCount; --iMip >= 0; )
|
||||
{
|
||||
// NOTE: This is for older versions...
|
||||
@ -734,31 +715,35 @@ bool CVTFTexture::LoadImageData( CUtlBuffer &buf, const VTFFileHeader_t &header,
|
||||
|
||||
int iMipSize = ComputeMipSize( iMip );
|
||||
|
||||
// Skip over any levels we don't have data for--we'll get them later.
|
||||
if ( iMip > nLastAvailableMip || iMip < nFirstAvailableMip )
|
||||
{
|
||||
// If the data is there but we're ignoring it, need to update the get pointer.
|
||||
if ( bMipDataPresent )
|
||||
{
|
||||
for ( int iFrame = 0; iFrame < m_nFrameCount; ++iFrame )
|
||||
for ( int iFace = 0; iFace < nFacesToRead; ++iFace )
|
||||
buf.SeekGet( CUtlBuffer::SEEK_CURRENT, iMipSize );
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
for (int iFrame = 0; iFrame < m_nFrameCount; ++iFrame)
|
||||
{
|
||||
for (int iFace = 0; iFace < nFacesToRead; ++iFace)
|
||||
for (int iFace = 0; iFace < m_nFaceCount; ++iFace)
|
||||
{
|
||||
// printf("\n tex %p mip %i frame %i face %i size %i buf offset %i", this, iMip, iFrame, iFace, iMipSize, buf.TellGet() );
|
||||
unsigned char *pMipBits = ImageData( iFrame, iFace, iMip );
|
||||
buf.Get( pMipBits, iMipSize );
|
||||
}
|
||||
|
||||
// Strip out the spheremap in older versions
|
||||
if ( IsCubeMap() && !bNoSkip && ( header.version[0] == 7 ) && ( header.version[1] >= 1 ) && ( header.version[1] < 5 ) )
|
||||
{
|
||||
buf.SeekGet( CUtlBuffer::SEEK_CURRENT, iMipSize );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return buf.IsValid();
|
||||
bool bOk = buf.IsValid();
|
||||
if ( !bOk && IsCubeMap() && ( header.version[0] == 7 ) && ( header.version[1] <= 4 ) )
|
||||
{
|
||||
if ( !bNoSkip )
|
||||
{
|
||||
bNoSkip = true;
|
||||
buf.SeekGet( CUtlBuffer::SEEK_HEAD, nGet );
|
||||
goto retryCubemapLoad;
|
||||
}
|
||||
Warning( "** Encountered stale cubemap! Please rebuild the following vtf:\n" );
|
||||
}
|
||||
return bOk;
|
||||
}
|
||||
|
||||
void *CVTFTexture::SetResourceData( uint32 eType, void const *pData, size_t nNumBytes )
|
||||
@ -912,7 +897,7 @@ bool CVTFTexture::SetupByteSwap( CUtlBuffer &buf )
|
||||
static bool ReadHeaderFromBufferPastBaseHeader( CUtlBuffer &buf, VTFFileHeader_t &header )
|
||||
{
|
||||
unsigned char *pBuf = (unsigned char*)(&header) + sizeof(VTFFileBaseHeader_t);
|
||||
if ( header.version[1] == VTF_MINOR_VERSION )
|
||||
if ( header.version[1] <= VTF_MINOR_VERSION && header.version[1] >= 4 )
|
||||
{
|
||||
buf.Get( pBuf, sizeof(VTFFileHeader_t) - sizeof(VTFFileBaseHeader_t) );
|
||||
}
|
||||
@ -974,7 +959,7 @@ bool CVTFTexture::ReadHeader( CUtlBuffer &buf, VTFFileHeader_t &header )
|
||||
{
|
||||
m_Swap.SwapFieldsToTargetEndian( (VTFFileHeaderV7_3_t*)buf.PeekGet() );
|
||||
}
|
||||
else if ( baseHeader.version[1] == VTF_MINOR_VERSION )
|
||||
else if ( baseHeader.version[1] >= 4 && baseHeader.version[1] <= VTF_MINOR_VERSION )
|
||||
{
|
||||
m_Swap.SwapFieldsToTargetEndian( (VTFFileHeader_t*)buf.PeekGet() );
|
||||
}
|
||||
@ -1021,6 +1006,7 @@ bool CVTFTexture::ReadHeader( CUtlBuffer &buf, VTFFileHeader_t &header )
|
||||
case 3:
|
||||
header.flags &= VERSIONED_VTF_FLAGS_MASK_7_3;
|
||||
// fall-through
|
||||
case 4:
|
||||
case VTF_MINOR_VERSION:
|
||||
break;
|
||||
}
|
||||
@ -2528,7 +2514,7 @@ void CVTFTexture::GenerateMipmaps()
|
||||
// return;
|
||||
// }
|
||||
|
||||
Assert( m_Format == IMAGE_FORMAT_RGBA8888 || m_Format == IMAGE_FORMAT_RGB323232F );
|
||||
Assert( m_Format == IMAGE_FORMAT_RGBA8888 || m_Format == IMAGE_FORMAT_RGB323232F || m_Format == IMAGE_FORMAT_RGBA32323232F );
|
||||
|
||||
// FIXME: Should we be doing anything special for normalmaps other than a final normalization pass?
|
||||
ImageLoader::ResampleInfo_t info;
|
||||
@ -2667,7 +2653,11 @@ void CVTFTexture::GenerateMipmaps()
|
||||
info.m_pSrc = pSrcLevel;
|
||||
info.m_pDest = pDstLevel;
|
||||
ComputeMipLevelDimensions( nSrcMipLevel, &info.m_nSrcWidth, &info.m_nSrcHeight, &info.m_nSrcDepth );
|
||||
if( m_Format == IMAGE_FORMAT_RGB323232F )
|
||||
if( m_Format == IMAGE_FORMAT_RGBA32323232F )
|
||||
{
|
||||
ImageLoader::ResampleRGBA32323232F( info );
|
||||
}
|
||||
else if( m_Format == IMAGE_FORMAT_RGB323232F )
|
||||
{
|
||||
ImageLoader::ResampleRGB323232F( info );
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user