//====== Copyright © 1996-2004, Valve Corporation, All rights reserved. ======= // // A class representing a procedural texture // //============================================================================= #ifndef DMETEXTURE_H #define DMETEXTURE_H #ifdef _WIN32 #pragma once #endif #include "datamodel/dmelement.h" #include "materialsystem/materialsystemutil.h" #include "materialobjects/dmeimage.h" #include "tier1/functors.h" //----------------------------------------------------------------------------- // Forward declarations //----------------------------------------------------------------------------- enum ImageFormat; //----------------------------------------------------------------------------- // Compression types //----------------------------------------------------------------------------- enum DmeTextureCompress_t { DMETEXTURE_COMPRESS_DEFAULT = 0, DMETEXTURE_COMPRESS_NONE, DMETEXTURE_COMPRESS_DXT1, DMETEXTURE_COMPRESS_DXT5, }; //----------------------------------------------------------------------------- // Filter types //----------------------------------------------------------------------------- enum DmeTextureFilter_t { DMETEXTURE_FILTER_DEFAULT = 0, DMETEXTURE_FILTER_ANISOTROPIC, DMETEXTURE_FILTER_TRILINEAR, DMETEXTURE_FILTER_BILINEAR, DMETEXTURE_FILTER_POINT, }; //----------------------------------------------------------------------------- // Mipmap types //----------------------------------------------------------------------------- enum DmeTextureMipmap_t { DMETEXTURE_MIPMAP_DEFAULT = 0, DMETEXTURE_MIPMAP_ALL_LEVELS, DMETEXTURE_MIPMAP_NONE, }; //----------------------------------------------------------------------------- // Texture types //----------------------------------------------------------------------------- enum DmeTextureType_t { DMETEXTURE_TYPE_NORMAL = 0, DMETEXTURE_TYPE_CUBEMAP, }; //----------------------------------------------------------------------------- // A class for textures //----------------------------------------------------------------------------- class CDmeTextureFrame : public CDmElement { DEFINE_ELEMENT( CDmeTextureFrame, CDmElement ); public: int MipLevelCount() const; CDmeImageArray *GetMipLevel( int nIndex ) const; void AddMipLevel( CDmeImageArray *pImages ); CDmeImageArray *AddMipLevel( ); int ImageCount() const; private: // Mip levels for the texture CDmaElementArray< CDmeImageArray > m_MipLevels; }; //----------------------------------------------------------------------------- // Helper functors //----------------------------------------------------------------------------- template< typename ObjectType_t > class CImageMemberFunctor { public: CImageMemberFunctor( ObjectType_t *pObject, bool (ObjectType_t::*pMemberFunc)( CDmeImage * ) ) { m_pObject = pObject; m_pMemberFunc = pMemberFunc; } bool operator()( CDmeImage *pImage ) { return m_pObject->*m_pMemberFunc( pImage ); } private: ObjectType_t *m_pObject; bool (ObjectType_t::*m_pMemberFunc)( CDmeImage * ); }; class CImageFunctor { public: CImageFunctor( bool (*pMemberFunc)( CDmeImage * ) ) { m_pFunc = pMemberFunc; } bool operator()( CDmeImage *pImage ) { return m_pFunc( pImage ); } private: bool (*m_pFunc)( CDmeImage * ); }; template< typename ObjectType_t > class CImageProcessorMemberFunctor { public: CImageProcessorMemberFunctor( ObjectType_t *pObject, void (ObjectType_t::*pMemberFunc)( CDmeImage *, CDmeImage * ) ) { m_pObject = pObject; m_pMemberFunc = pMemberFunc; } void operator()( CDmeImage *pDstImage, CDmeImage *pSrcImage ) { (m_pObject->*m_pMemberFunc)( pDstImage, pSrcImage ); } private: ObjectType_t *m_pObject; void (ObjectType_t::*m_pMemberFunc)( CDmeImage *, CDmeImage * ); }; //----------------------------------------------------------------------------- // A class for textures //----------------------------------------------------------------------------- class CDmeTexture : public CDmElement { DEFINE_ELEMENT( CDmeTexture, CDmElement ); public: // Compression type void SetCompressionType( DmeTextureCompress_t type ); DmeTextureCompress_t GetCompressionType() const; // Filter type void SetFilterType( DmeTextureFilter_t type ); DmeTextureFilter_t GetFilterType() const; // Mipmap type void SetMipmapType( DmeTextureMipmap_t type ); DmeTextureMipmap_t GetMipmapType() const; // Texture type void SetTextureType( DmeTextureType_t type ); DmeTextureType_t GetTextureType() const; CDmeTextureFrame *AddFrame(); int FrameCount() const; CDmeTextureFrame *GetFrame( int nIndex ) const; void RemoveAllFrames(); // Gets dimensions int Width() const; int Height() const; int Depth() const; int MipLevelCount() const; int ImageCount() const; // Methods related to image format ImageFormat Format() const; // Returns all images associated with a particular frame + face (mip count amount) void GetImages( int nFrame, int nImageIndex, CDmeImage **ppImages, int nSize ); // Iterates over all images, processes them template< typename Functor > void ProcessTexture( CDmeTexture *pSrcTexture, Functor &func ); template< typename ObjectType_t > void ProcessTexture( CDmeTexture *pSrcTexture, ObjectType_t *pObject, void (ObjectType_t::*pMemberFunc)( CDmeImage *, CDmeImage * ) ); // Iterates over all images, runs a functor template< typename Functor > void ForEachImage( Functor &func ); template< typename ObjectType_t > void ForEachImage( ObjectType_t *pObject, bool (ObjectType_t::*pMemberFunc)( CDmeImage * ) ); void ForEachImage( bool (*pFunc)( CDmeImage * ) ); void CompressTexture( CDmeTexture *pSrcTexture, ImageFormat fmt ); //------------------------------------- // Ignore the macro! To use this nifty feature, use code that looks like this: // pTexture->ForEachImage( &CDmeImage::ConvertFormat, dstFormat ); //------------------------------------- #define DEFINE_FOR_EACH_IMAGE(N) \ template \ void ForEachImage( FUNCTION_RETTYPE ( CDmeImage::*pfnProxied )( FUNC_BASE_TEMPLATE_FUNC_PARAMS_##N ) FUNC_ARG_FORMAL_PARAMS_##N ) \ { \ int nFrameCount = FrameCount(); \ for ( int f = 0; f < nFrameCount; ++f ) \ { \ CDmeTextureFrame *pFrame = GetFrame( f ); \ if ( !pFrame ) \ continue; \ int nMipCount = pFrame->MipLevelCount(); \ for ( int m = 0; m < nMipCount; ++m ) \ { \ CDmeImageArray *pImageArray = pFrame->GetMipLevel( m ); \ if ( !pImageArray ) \ continue; \ int nImageCount = pImageArray->ImageCount(); \ for ( int i = 0; i < nImageCount; ++i ) \ { \ CDmeImage *pImage = pImageArray->GetImage( i ); \ if ( !pImage ) \ continue; \ FunctorDirectCall( pImage, pfnProxied FUNC_FUNCTOR_CALL_ARGS_##N ); \ } \ } \ } \ } FUNC_GENERATE_ALL( DEFINE_FOR_EACH_IMAGE ); #undef DEFINE_FOR_EACH_IMAGE public: virtual void Resolve(); public: CDmaVar m_bClampS; CDmaVar m_bClampT; CDmaVar m_bClampU; CDmaVar m_bNoDebugOverride; CDmaVar m_bNoLod; CDmaVar m_bNiceFiltered; CDmaVar m_bNormalMap; CDmaVar m_flBumpScale; protected: // Computes texture flags int CalcTextureFlags( int nDepth ) const; // Computes the desired texture format based on flags ImageFormat ComputeDesiredImageFormat( ImageFormat srcFormat, int nWidth, int nHeight, int nDepth, int nFlags ); CDmaVar m_nCompressType; CDmaVar m_nFilterType; CDmaVar m_nMipmapType; CDmaVar m_nTextureType; // Array of images in an animated texture CDmaElementArray< CDmeTextureFrame > m_Frames; // Computed values // CTextureReference m_Texture; // IVTFTexture *m_pVTFTexture; Vector m_vecReflectivity; }; //----------------------------------------------------------------------------- // Inline methods //----------------------------------------------------------------------------- inline void CDmeTexture::SetCompressionType( DmeTextureCompress_t type ) { m_nCompressType = type; } inline DmeTextureCompress_t CDmeTexture::GetCompressionType() const { return (DmeTextureCompress_t)m_nCompressType.Get(); } inline void CDmeTexture::SetFilterType( DmeTextureFilter_t type ) { m_nFilterType = type; } inline DmeTextureFilter_t CDmeTexture::GetFilterType() const { return (DmeTextureFilter_t)m_nFilterType.Get(); } inline void CDmeTexture::SetMipmapType( DmeTextureMipmap_t type ) { m_nMipmapType = type; } inline DmeTextureMipmap_t CDmeTexture::GetMipmapType() const { return (DmeTextureMipmap_t)m_nMipmapType.Get(); } inline void CDmeTexture::SetTextureType( DmeTextureType_t type ) { m_nTextureType = type; } inline DmeTextureType_t CDmeTexture::GetTextureType() const { return (DmeTextureType_t)m_nTextureType.Get(); } inline int CDmeTexture::FrameCount() const { return m_Frames.Count(); } inline CDmeTextureFrame *CDmeTexture::GetFrame( int nIndex ) const { return m_Frames[nIndex]; } //----------------------------------------------------------------------------- // Invokes a functor on all images in the texture //----------------------------------------------------------------------------- template< typename Functor > inline void CDmeTexture::ForEachImage( Functor &func ) { int nFrameCount = FrameCount(); for ( int f = 0; f < nFrameCount; ++f ) { CDmeTextureFrame *pFrame = GetFrame( f ); if ( !pFrame ) continue; int nMipCount = pFrame->MipLevelCount(); for ( int m = 0; m < nMipCount; ++m ) { CDmeImageArray *pImageArray = pFrame->GetMipLevel( m ); if ( !pImageArray ) continue; int nImageCount = pImageArray->ImageCount(); for ( int i = 0; i < nImageCount; ++i ) { CDmeImage *pImage = pImageArray->GetImage( i ); if ( !pImage ) continue; if ( !func( pImage ) ) break; } } } } template< typename ObjectType_t > inline void CDmeTexture::ForEachImage( ObjectType_t *pObject, bool (ObjectType_t::*pMemberFunc)( CDmeImage * ) ) { CImageMemberFunctor< ObjectType_t > functor( pObject, pMemberFunc ); ForEachImage( functor ); } inline void CDmeTexture::ForEachImage( bool (*pFunc)( CDmeImage * ) ) { CImageFunctor functor( pFunc ); ForEachImage( functor ); } // Iterates over all images, processes them template< typename Functor > inline void CDmeTexture::ProcessTexture( CDmeTexture *pSrcTexture, Functor &func ) { // FIXME: This pattern should go into some templatized type thingy pSrcTexture->CopyAttributesTo( this, TD_NONE ); // Copying will copy references to src texture frames. Remove them. RemoveAllFrames(); int nFrameCount = pSrcTexture->FrameCount(); for ( int f = 0; f < nFrameCount; ++f ) { CDmeTextureFrame *pSrcFrame = pSrcTexture->GetFrame( f ); CDmeTextureFrame *pDstFrame = AddFrame(); int nMipCount = pSrcFrame->MipLevelCount(); for ( int m = 0; m < nMipCount; ++m ) { CDmeImageArray *pSrcImageArray = pSrcFrame->GetMipLevel( m ); CDmeImageArray *pDstImageArray = pDstFrame->AddMipLevel(); if ( !pSrcImageArray ) continue; int nImageCount = pSrcImageArray->ImageCount(); for ( int i = 0; i < nImageCount; ++i ) { CDmeImage *pSrcImage = pSrcImageArray->GetImage( i ); CDmeImage *pDstImage = pDstImageArray->AddImage( ); if ( !pSrcImage ) continue; func( pDstImage, pSrcImage ); } } } } template< typename ObjectType_t > inline void CDmeTexture::ProcessTexture( CDmeTexture *pSrcTexture, ObjectType_t *pObject, void (ObjectType_t::*pMemberFunc)( CDmeImage *, CDmeImage * ) ) { CImageProcessorMemberFunctor< ObjectType_t > functor( pObject, pMemberFunc ); ProcessTexture( pSrcTexture, functor ); } #endif // DMETEXTURE_H