//========= Copyright Valve Corporation, All rights reserved. ============// // // Purpose: Local header for CVTFTexture class declaration - allows platform-specific // implementation to be placed in separate cpp files. // // $NoKeywords: $ //===========================================================================// #ifndef CVTF_H #define CVTF_H #ifdef _WIN32 #pragma once #endif #include "s3tc_decode.h" #include "vtf/vtf.h" #include "byteswap.h" #include "filesystem.h" class CEdgePos { public: CEdgePos() {} CEdgePos( int ix, int iy ) { x = ix; y = iy; } void operator +=( const CEdgePos &other ) { x += other.x; y += other.y; } void operator /=( int val ) { x /= val; y /= val; } CEdgePos operator >>( int shift ) { return CEdgePos( x >> shift, y >> shift ); } CEdgePos operator *( int shift ) { return CEdgePos( x * shift, y * shift ); } CEdgePos operator -( const CEdgePos &other ) { return CEdgePos( x - other.x, y - other.y ); } CEdgePos operator +( const CEdgePos &other ) { return CEdgePos( x + other.x, y + other.y ); } bool operator!=( const CEdgePos &other ) { return !( *this == other ); } bool operator==( const CEdgePos &other ) { return x==other.x && y==other.y; } int x, y; }; class CEdgeIncrements { public: CEdgePos iFace1Start, iFace1End; CEdgePos iFace1Inc, iFace2Inc; CEdgePos iFace2Start, iFace2End; }; class CEdgeMatch { public: int m_iFaces[2]; // Which faces are touching. int m_iEdges[2]; // Which edge on each face is touching. int m_iCubeVerts[2];// Which of the cube's verts comprise this edge? bool m_bFlipFace2Edge; }; class CCornerMatch { public: // The info for the 3 edges that match at this corner. int m_iFaces[3]; int m_iFaceEdges[3]; }; class CEdgeFaceIndex { public: int m_iEdge; int m_iFace; }; #define NUM_EDGE_MATCHES 12 #define NUM_CORNER_MATCHES 8 //----------------------------------------------------------------------------- // Implementation of the VTF Texture //----------------------------------------------------------------------------- class CVTFTexture : public IVTFTexture { public: CVTFTexture(); virtual ~CVTFTexture(); virtual bool Init( int nWidth, int nHeight, int nDepth, ImageFormat fmt, int iFlags, int iFrameCount, int nForceMipCount ); // Methods to initialize the low-res image virtual void InitLowResImage( int nWidth, int nHeight, ImageFormat fmt ); virtual void *SetResourceData( uint32 eType, void const *pData, size_t nDataSize ); virtual void *GetResourceData( uint32 eType, size_t *pDataSize ) const; // Locates the resource entry info if it's present, easier than crawling array types virtual bool HasResourceEntry( uint32 eType ) const; // Retrieve available resource types of this IVTFTextures // arrTypesBuffer buffer to be filled with resource types available. // numTypesBufferElems how many resource types the buffer can accomodate. // Returns: // number of resource types available (can be greater than "numTypesBufferElems" // in which case only first "numTypesBufferElems" are copied to "arrTypesBuffer") virtual unsigned int GetResourceTypes( uint32 *arrTypesBuffer, int numTypesBufferElems ) const; // Methods to set other texture fields virtual void SetBumpScale( float flScale ); virtual void SetReflectivity( const Vector &vecReflectivity ); // These are methods to help with optimization of file access virtual void LowResFileInfo( int *pStartLocation, int *pSizeInBytes ) const; virtual void ImageFileInfo( int nFrame, int nFace, int nMip, int *pStartLocation, int *pSizeInBytes) const; virtual int FileSize( int nMipSkipCount = 0 ) const; // When unserializing, we can skip a certain number of mip levels, // and we also can just load everything but the image data virtual bool Unserialize( CUtlBuffer &buf, bool bBufferHeaderOnly = false, int nSkipMipLevels = 0 ); virtual bool UnserializeEx( CUtlBuffer &buf, bool bHeaderOnly = false, int nForceFlags = 0, int nSkipMipLevels = 0 ); virtual bool Serialize( CUtlBuffer &buf ); virtual void GetMipmapRange( int* pOutFinest, int* pOutCoarsest ); // Attributes... virtual int Width() const; virtual int Height() const; virtual int Depth() const; virtual int MipCount() const; virtual int RowSizeInBytes( int nMipLevel ) const; virtual int FaceSizeInBytes( int nMipLevel ) const; virtual ImageFormat Format() const; virtual int FaceCount() const; virtual int FrameCount() const; virtual int Flags() const; virtual float BumpScale() const; virtual const Vector &Reflectivity() const; virtual bool IsCubeMap() const; virtual bool IsNormalMap() const; virtual bool IsVolumeTexture() const; virtual int LowResWidth() const; virtual int LowResHeight() const; virtual ImageFormat LowResFormat() const; // Computes the size (in bytes) of a single mipmap of a single face of a single frame virtual int ComputeMipSize( int iMipLevel ) const; // Computes the size (in bytes) of a single face of a single frame // All mip levels starting at the specified mip level are included virtual int ComputeFaceSize( int iStartingMipLevel = 0 ) const; // Computes the total size of all faces, all frames virtual int ComputeTotalSize( ) const; // Computes the dimensions of a particular mip level virtual void ComputeMipLevelDimensions( int iMipLevel, int *pWidth, int *pHeight, int *pMipDepth ) const; // Computes the size of a subrect (specified at the top mip level) at a particular lower mip level virtual void ComputeMipLevelSubRect( Rect_t* pSrcRect, int nMipLevel, Rect_t *pSubRect ) const; // Returns the base address of the image data virtual unsigned char *ImageData(); // Returns a pointer to the data associated with a particular frame, face, and mip level virtual unsigned char *ImageData( int iFrame, int iFace, int iMipLevel ); // Returns a pointer to the data associated with a particular frame, face, mip level, and offset virtual unsigned char *ImageData( int iFrame, int iFace, int iMipLevel, int x, int y, int z ); // Returns the base address of the low-res image data virtual unsigned char *LowResImageData(); // Converts the texture's image format. Use IMAGE_FORMAT_DEFAULT virtual void ConvertImageFormat( ImageFormat fmt, bool bNormalToDUDV ); // Generate spheremap based on the current cube faces (only works for cubemaps) // The look dir indicates the direction of the center of the sphere virtual void GenerateSpheremap( LookDir_t lookDir ); virtual void GenerateHemisphereMap( unsigned char *pSphereMapBitsRGBA, int targetWidth, int targetHeight, LookDir_t lookDir, int iFrame ); // Fixes the cubemap faces orientation from our standard to the // standard the material system needs. virtual void FixCubemapFaceOrientation( ); // Normalize the top mip level if necessary virtual void NormalizeTopMipLevel(); // Generates mipmaps from the base mip levels virtual void GenerateMipmaps(); // Put 1/miplevel (1..n) into alpha. virtual void PutOneOverMipLevelInAlpha(); // Computes the reflectivity virtual void ComputeReflectivity( ); // Computes the alpha flags virtual void ComputeAlphaFlags(); // Gets the texture all internally consistent assuming you've loaded // mip 0 of all faces of all frames virtual void PostProcess(bool bGenerateSpheremap, LookDir_t lookDir = LOOK_DOWN_Z, bool bAllowFixCubemapOrientation = true); virtual void SetPostProcessingSettings( VtfProcessingOptions const *pOptions ); // Generate the low-res image bits virtual bool ConstructLowResImage(); virtual void MatchCubeMapBorders( int iStage, ImageFormat finalFormat, bool bSkybox ); // Sets threshhold values for alphatest mipmapping virtual void SetAlphaTestThreshholds( float flBase, float flHighFreq ); #if defined( _X360 ) virtual int UpdateOrCreate( const char *pFilename, const char *pPathID = NULL, bool bForce = false ); virtual int FileSize( bool bPreloadOnly, int nMipSkipCount ) const; virtual bool UnserializeFromBuffer( CUtlBuffer &buf, bool bBufferIsVolatile, bool bHeaderOnly, bool bPreloadOnly, int nMipSkipCount ); virtual bool IsPreTiled() const; virtual int MappingWidth() const; virtual int MappingHeight() const; virtual int MappingDepth() const; virtual int MipSkipCount() const; virtual unsigned char *LowResImageSample(); virtual void ReleaseImageMemory(); #endif private: // Unserialization bool ReadHeader( CUtlBuffer &buf, VTFFileHeader_t &header ); void BlendCubeMapEdgePalettes( int iFrame, int iMipLevel, const CEdgeMatch *pMatch ); void BlendCubeMapCornerPalettes( int iFrame, int iMipLevel, const CCornerMatch *pMatch ); void MatchCubeMapS3TCPalettes( CEdgeMatch edgeMatches[NUM_EDGE_MATCHES], CCornerMatch cornerMatches[NUM_CORNER_MATCHES] ); void SetupFaceVert( int iMipLevel, int iVert, CEdgePos &out ); void SetupEdgeIncrement( CEdgePos &start, CEdgePos &end, CEdgePos &inc ); void SetupTextureEdgeIncrements( int iMipLevel, int iFace1Edge, int iFace2Edge, bool bFlipFace2Edge, CEdgeIncrements *incs ); void BlendCubeMapFaceEdges( int iFrame, int iMipLevel, const CEdgeMatch *pMatch ); void BlendCubeMapFaceCorners( int iFrame, int iMipLevel, const CCornerMatch *pMatch ); void BuildCubeMapMatchLists( CEdgeMatch edgeMatches[NUM_EDGE_MATCHES], CCornerMatch cornerMatches[NUM_CORNER_MATCHES], bool bSkybox ); // Allocate image data blocks with an eye toward re-using memory bool AllocateImageData( int nMemorySize ); bool AllocateLowResImageData( int nMemorySize ); // Compute the mip count based on the size + flags int ComputeMipCount( ) const; // Unserialization of low-res data bool LoadLowResData( CUtlBuffer &buf ); // Unserialization of new resource data bool LoadNewResources( CUtlBuffer &buf ); // Unserialization of image data bool LoadImageData( CUtlBuffer &buf, const VTFFileHeader_t &header, int nSkipMipLevels ); // Shutdown void Shutdown(); void ReleaseResources(); // Makes a single frame of spheremap void ComputeSpheremapFrame( unsigned char **ppCubeFaces, unsigned char *pSpheremap, LookDir_t lookDir ); // Makes a single frame of spheremap void ComputeHemispheremapFrame( unsigned char **ppCubeFaces, unsigned char *pSpheremap, LookDir_t lookDir ); // Serialization of image data bool WriteImageData( CUtlBuffer &buf ); // Computes the size (in bytes) of a single mipmap of a single face of a single frame int ComputeMipSize( int iMipLevel, ImageFormat fmt ) const; // Computes the size (in bytes) of a single face of a single frame // All mip levels starting at the specified mip level are included int ComputeFaceSize( int iStartingMipLevel, ImageFormat fmt ) const; // Computes the total size of all faces, all frames int ComputeTotalSize( ImageFormat fmt ) const; // Computes the location of a particular face, frame, and mip level int GetImageOffset( int iFrame, int iFace, int iMipLevel, ImageFormat fmt ) const; // Determines if the vtf or vtfx file needs to be swapped to the current platform bool SetupByteSwap( CUtlBuffer &buf ); // Locates the resource entry info if it's present ResourceEntryInfo *FindResourceEntryInfo( unsigned int eType ); ResourceEntryInfo const *FindResourceEntryInfo( unsigned int eType ) const; // Inserts the resource entry info if it's not present ResourceEntryInfo *FindOrCreateResourceEntryInfo( unsigned int eType ); // Removes the resource entry info if it's present bool RemoveResourceEntryInfo( unsigned int eType ); #if defined( _X360 ) bool ReadHeader( CUtlBuffer &buf, VTFFileHeaderX360_t &header ); bool LoadImageData( CUtlBuffer &buf, bool bBufferIsVolatile, int nMipSkipCount ); #endif private: // This is to make sure old-format .vtf files are read properly int m_nVersion[2]; int m_nWidth; int m_nHeight; int m_nDepth; ImageFormat m_Format; int m_nMipCount; int m_nFaceCount; int m_nFrameCount; int m_nImageAllocSize; int m_nFlags; unsigned char *m_pImageData; Vector m_vecReflectivity; float m_flBumpScale; // FIXME: Do I need this? int m_iStartFrame; // Low res data int m_nLowResImageAllocSize; ImageFormat m_LowResImageFormat; int m_nLowResImageWidth; int m_nLowResImageHeight; unsigned char *m_pLowResImageData; // Used while fixing mipmap edges. CUtlVector m_OriginalData; // Alpha threshholds float m_flAlphaThreshhold; float m_flAlphaHiFreqThreshhold; CByteswap m_Swap; int m_nFinestMipmapLevel; int m_nCoarsestMipmapLevel; #if defined( _X360 ) int m_iPreloadDataSize; int m_iCompressedSize; // resolves actual dimensions to/from mapping dimensions due to pre-picmipping int m_nMipSkipCount; unsigned char m_LowResImageSample[4]; #endif CUtlVector< ResourceEntryInfo > m_arrResourcesInfo; struct ResourceMemorySection { ResourceMemorySection() { memset( this, 0, sizeof( *this ) ); } int m_nDataAllocSize; int m_nDataLength; unsigned char *m_pData; bool AllocateData( int nMemorySize ); bool LoadData( CUtlBuffer &buf, CByteswap &byteSwap ); bool WriteData( CUtlBuffer &buf ) const; }; CUtlVector< ResourceMemorySection > m_arrResourcesData; CUtlVector< ResourceMemorySection > m_arrResourcesData_ForReuse; // Maintained to keep allocated memory blocks when unserializing from files VtfProcessingOptions m_Options; }; #endif // CVTF_H