/* ** Command & Conquer Renegade(tm) ** Copyright 2025 Electronic Arts Inc. ** ** This program is free software: you can redistribute it and/or modify ** it under the terms of the GNU General Public License as published by ** the Free Software Foundation, either version 3 of the License, or ** (at your option) any later version. ** ** This program is distributed in the hope that it will be useful, ** but WITHOUT ANY WARRANTY; without even the implied warranty of ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ** GNU General Public License for more details. ** ** You should have received a copy of the GNU General Public License ** along with this program. If not, see . */ /*********************************************************************************************** *** C O N F I D E N T I A L --- W E S T W O O D S T U D I O S *** *********************************************************************************************** * * * Project Name : WW3D * * * * $Archive:: /Commando/Code/ww3d2/texture.cpp $* * * * $Author:: Steve_t $* * * * $Modtime:: 1/09/02 2:57p $* * * * $Revision:: 83 $* * * *---------------------------------------------------------------------------------------------* * Functions: * * FileListTextureClass::Load_Frame_Surface -- Load source texture * * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ #include "texture.h" #include #include #include #include "dx8wrapper.h" #include "targa.h" #include #include "w3d_file.h" #include "assetmgr.h" #include "formconv.h" #include "textureloader.h" #include "missingtexture.h" #include "ffactory.h" #include "dx8caps.h" #include "dx8texman.h" #include "meshmatdesc.h" #include "texturethumbnail.h" const unsigned DEFAULT_INACTIVATION_TIME=20000; /* ** Definitions of static members: */ static unsigned unused_texture_id; unsigned _MinTextureFilters[MAX_TEXTURE_STAGES][TextureClass::FILTER_TYPE_COUNT]; unsigned _MagTextureFilters[MAX_TEXTURE_STAGES][TextureClass::FILTER_TYPE_COUNT]; unsigned _MipMapFilters[MAX_TEXTURE_STAGES][TextureClass::FILTER_TYPE_COUNT]; // ---------------------------------------------------------------------------- static int Calculate_Texture_Memory_Usage(const TextureClass* texture,int red_factor=0) { // Set performance statistics int size=0; IDirect3DTexture8* d3d_texture=const_cast(texture)->Peek_DX8_Texture(); if (!d3d_texture) return 0; for (unsigned i=red_factor;iGetLevelCount();++i) { D3DSURFACE_DESC desc; DX8_ErrorCode(d3d_texture->GetLevelDesc(i,&desc)); size+=desc.Size; } return size; } /************************************************************************* ** TextureClass *************************************************************************/ TextureClass::TextureClass(unsigned width, unsigned height, WW3DFormat format, MipCountType mip_level_count, PoolType pool,bool rendertarget) : D3DTexture(NULL), texture_id(unused_texture_id++), Initialized(true), TextureMinFilter(FILTER_TYPE_DEFAULT), TextureMagFilter(FILTER_TYPE_DEFAULT), MipMapFilter((mip_level_count!=MIP_LEVELS_1) ? FILTER_TYPE_DEFAULT : FILTER_TYPE_NONE), UAddressMode(TEXTURE_ADDRESS_REPEAT), VAddressMode(TEXTURE_ADDRESS_REPEAT), MipLevelCount(mip_level_count), Pool(pool), Dirty(false), IsLightmap(false), IsProcedural(true), Name(""), TextureFormat(format), IsCompressionAllowed(false), TextureLoadTask(NULL), ThumbnailLoadTask(NULL), Width(width), Height(height), InactivationTime(0), // Don't inactivate! ExtendedInactivationTime(0), LastInactivationSyncTime(0) { switch (format) { case WW3D_FORMAT_DXT1: case WW3D_FORMAT_DXT2: case WW3D_FORMAT_DXT3: case WW3D_FORMAT_DXT4: case WW3D_FORMAT_DXT5: IsCompressionAllowed=true; break; default: break; } D3DPOOL d3dpool=(D3DPOOL) 0; switch(pool) { case POOL_DEFAULT: d3dpool=D3DPOOL_DEFAULT; break; case POOL_MANAGED: d3dpool=D3DPOOL_MANAGED; break; case POOL_SYSTEMMEM: d3dpool=D3DPOOL_SYSTEMMEM; break; default: WWASSERT(0); } D3DTexture = DX8Wrapper::_Create_DX8_Texture(width, height, format, mip_level_count,d3dpool,rendertarget); if (pool==POOL_DEFAULT) { Dirty=true; DX8TextureTrackerClass *track=new DX8TextureTrackerClass(width, height, format, mip_level_count,rendertarget, this); DX8TextureManagerClass::Add(track); } LastAccessed=WW3D::Get_Sync_Time(); } // ---------------------------------------------------------------------------- TextureClass::TextureClass( const char *name, const char *full_path, MipCountType mip_level_count, WW3DFormat texture_format, bool allow_compression) : D3DTexture(NULL), texture_id(unused_texture_id++), Initialized(false), TextureMinFilter(FILTER_TYPE_DEFAULT), TextureMagFilter(FILTER_TYPE_DEFAULT), MipMapFilter((mip_level_count!=MIP_LEVELS_1) ? FILTER_TYPE_DEFAULT : FILTER_TYPE_NONE), UAddressMode(TEXTURE_ADDRESS_REPEAT), VAddressMode(TEXTURE_ADDRESS_REPEAT), MipLevelCount(mip_level_count), Pool(POOL_MANAGED), Dirty(false), IsLightmap(false), IsProcedural(false), TextureFormat(texture_format), IsCompressionAllowed(allow_compression), TextureLoadTask(NULL), ThumbnailLoadTask(NULL), Width(0), Height(0), InactivationTime(DEFAULT_INACTIVATION_TIME), // Default inactivation time 30 seconds ExtendedInactivationTime(0), LastInactivationSyncTime(0) { switch (TextureFormat) { case WW3D_FORMAT_DXT1: case WW3D_FORMAT_DXT2: case WW3D_FORMAT_DXT3: case WW3D_FORMAT_DXT4: case WW3D_FORMAT_DXT5: IsCompressionAllowed=true; break; case WW3D_FORMAT_U8V8: // Bumpmap case WW3D_FORMAT_L6V5U5: // Bumpmap case WW3D_FORMAT_X8L8V8U8: // Bumpmap // If requesting bumpmap format that isn't available we'll just return the surface in whatever color // format the texture file is in. (This is illegal case, the format support should always be queried // before creating a bump texture!) if (!DX8Wrapper::Is_Initted() || !DX8Wrapper::Get_Current_Caps()->Support_Texture_Format(TextureFormat)) { TextureFormat=WW3D_FORMAT_UNKNOWN; } // If bump format is valid, make sure compression is not allowed so that we don't even attempt to load // from a compressed file (quality isn't good enough for bump map). Also disable mipmapping. else { IsCompressionAllowed=false; MipLevelCount=MIP_LEVELS_1; MipMapFilter=FILTER_TYPE_NONE; } break; default: break; } WWASSERT_PRINT(name && name[0], "TextureClass CTor: NULL or empty texture name\n"); int len=strlen(name); for (int i=0;iPeek_Thumbnail_Instance(Get_Full_Path()); if (thumb) { Width=thumb->Get_Original_Texture_Width(); Height=thumb->Get_Original_Texture_Height(); break; } thumb_man=thumb_man->Succ(); } LastAccessed=WW3D::Get_Sync_Time(); // If the thumbnails are not enabled, init the texture at this point to avoid stalling when the // mesh is rendered. if (!WW3D::Get_Thumbnail_Enabled()) { if (TextureLoader::Is_DX8_Thread()) { Init(); } } } // ---------------------------------------------------------------------------- TextureClass::TextureClass(SurfaceClass *surface, MipCountType mip_level_count) : D3DTexture(NULL), texture_id(unused_texture_id++), Initialized(true), TextureMinFilter(FILTER_TYPE_DEFAULT), TextureMagFilter(FILTER_TYPE_DEFAULT), MipMapFilter((mip_level_count!=MIP_LEVELS_1) ? FILTER_TYPE_DEFAULT : FILTER_TYPE_NONE), UAddressMode(TEXTURE_ADDRESS_REPEAT), VAddressMode(TEXTURE_ADDRESS_REPEAT), MipLevelCount(mip_level_count), Pool(POOL_MANAGED), Dirty(false), IsLightmap(false), Name(""), IsProcedural(true), TextureFormat(surface->Get_Surface_Format()), IsCompressionAllowed(false), TextureLoadTask(NULL), ThumbnailLoadTask(NULL), Width(0), Height(0), InactivationTime(0), // Don't inactivate ExtendedInactivationTime(0), LastInactivationSyncTime(0) { SurfaceClass::SurfaceDescription sd; surface->Get_Description(sd); Width=sd.Width; Height=sd.Height; switch (sd.Format) { case WW3D_FORMAT_DXT1: case WW3D_FORMAT_DXT2: case WW3D_FORMAT_DXT3: case WW3D_FORMAT_DXT4: case WW3D_FORMAT_DXT5: IsCompressionAllowed=true; break; default: break; } D3DTexture = DX8Wrapper::_Create_DX8_Texture(surface->Peek_D3D_Surface(), mip_level_count); LastAccessed=WW3D::Get_Sync_Time(); } // ---------------------------------------------------------------------------- TextureClass::TextureClass(IDirect3DTexture8* d3d_texture) : D3DTexture(d3d_texture), texture_id(unused_texture_id++), Initialized(true), TextureMinFilter(FILTER_TYPE_DEFAULT), TextureMagFilter(FILTER_TYPE_DEFAULT), MipMapFilter((d3d_texture->GetLevelCount()!=1) ? FILTER_TYPE_DEFAULT : FILTER_TYPE_NONE), UAddressMode(TEXTURE_ADDRESS_REPEAT), VAddressMode(TEXTURE_ADDRESS_REPEAT), MipLevelCount((MipCountType)d3d_texture->GetLevelCount()), Pool(POOL_MANAGED), Dirty(false), IsLightmap(false), Name(""), IsProcedural(true), IsCompressionAllowed(false), TextureLoadTask(NULL), ThumbnailLoadTask(NULL), Width(0), Height(0), InactivationTime(0), // Don't inactivate! ExtendedInactivationTime(0), LastInactivationSyncTime(0) { D3DTexture->AddRef(); IDirect3DSurface8* surface; DX8_ErrorCode(D3DTexture->GetSurfaceLevel(0,&surface)); D3DSURFACE_DESC d3d_desc; ::ZeroMemory(&d3d_desc, sizeof(D3DSURFACE_DESC)); DX8_ErrorCode(surface->GetDesc(&d3d_desc)); Width=d3d_desc.Width; Height=d3d_desc.Height; TextureFormat=D3DFormat_To_WW3DFormat(d3d_desc.Format); switch (TextureFormat) { case WW3D_FORMAT_DXT1: case WW3D_FORMAT_DXT2: case WW3D_FORMAT_DXT3: case WW3D_FORMAT_DXT4: case WW3D_FORMAT_DXT5: IsCompressionAllowed=true; break; default: break; } LastAccessed=WW3D::Get_Sync_Time(); } // ---------------------------------------------------------------------------- TextureClass::~TextureClass(void) { delete TextureLoadTask; TextureLoadTask=NULL; delete ThumbnailLoadTask; ThumbnailLoadTask=NULL; if (D3DTexture) { D3DTexture->Release(); D3DTexture = NULL; } DX8TextureManagerClass::Remove(this); } void TextureClass::Invalidate_Old_Unused_Textures(unsigned invalidation_time_override) { unsigned synctime=WW3D::Get_Sync_Time(); HashTemplateIterator ite(WW3DAssetManager::Get_Instance()->Texture_Hash()); // Loop through all the textures in the manager for (ite.First ();!ite.Is_Done();ite.Next ()) { TextureClass* tex=ite.Peek_Value(); // Consider invalidating if texture has been initialized and defines inactivation time if (tex->Initialized && tex->InactivationTime) { unsigned age=synctime-tex->LastAccessed; if (invalidation_time_override) { if (age>invalidation_time_override) { tex->Invalidate(); tex->LastInactivationSyncTime=synctime; } } else { // Not used in the last n milliseconds? if (age>(tex->InactivationTime+tex->ExtendedInactivationTime)) { tex->Invalidate(); tex->LastInactivationSyncTime=synctime; } } } } } // ---------------------------------------------------------------------------- void TextureClass::Init() { // If the texture has already been initialised we should exit now if (Initialized) return; // If the texture has recently been inactivated, increase the inactivation time (this texture obviously // should not have been inactivated yet). if (InactivationTime && LastInactivationSyncTime) { if ((WW3D::Get_Sync_Time()-LastInactivationSyncTime)Release(); D3DTexture = NULL; } Initialized=false; LastAccessed=WW3D::Get_Sync_Time(); } // ---------------------------------------------------------------------------- void TextureClass::Load_Locked_Surface() { if (D3DTexture) D3DTexture->Release(); D3DTexture=0; TextureLoader::Request_Thumbnail(this); Initialized=false; } // ---------------------------------------------------------------------------- bool TextureClass::Is_Missing_Texture() { bool flag = false; IDirect3DTexture8 *missing_texture = MissingTexture::_Get_Missing_Texture(); if(D3DTexture == missing_texture) flag = true; if(missing_texture) { missing_texture->Release(); } return flag; } // ---------------------------------------------------------------------------- void TextureClass::Set_Texture_Name(const char * name) { Name=name; } // ---------------------------------------------------------------------------- unsigned int TextureClass::Get_Mip_Level_Count(void) { if (!D3DTexture) { WWASSERT_PRINT(0, "Get_Mip_Level_Count: D3DTexture is NULL!\n"); return 0; } return D3DTexture->GetLevelCount(); } // ---------------------------------------------------------------------------- SurfaceClass *TextureClass::Get_Surface_Level(unsigned int level) { if (!D3DTexture) { WWASSERT_PRINT(0, "Get_Surface_Level: D3DTexture is NULL!\n"); return 0; } IDirect3DSurface8 *d3d_surface = NULL; DX8_ErrorCode(D3DTexture->GetSurfaceLevel(level, &d3d_surface)); SurfaceClass *surface = new SurfaceClass(d3d_surface); d3d_surface->Release(); return surface; } // ---------------------------------------------------------------------------- IDirect3DSurface8 *TextureClass::Get_D3D_Surface_Level(unsigned int level) { if (!D3DTexture) { WWASSERT_PRINT(0, "Get_D3D_Surface_Level: D3DTexture is NULL!\n"); return 0; } IDirect3DSurface8 *d3d_surface = NULL; DX8_ErrorCode(D3DTexture->GetSurfaceLevel(level, &d3d_surface)); return d3d_surface; } // ---------------------------------------------------------------------------- unsigned int TextureClass::Get_Priority(void) { if (!D3DTexture) { WWASSERT_PRINT(0, "Get_Priority: D3DTexture is NULL!\n"); return 0; } return D3DTexture->GetPriority(); } // ---------------------------------------------------------------------------- unsigned int TextureClass::Set_Priority(unsigned int priority) { if (!D3DTexture) { WWASSERT_PRINT(0, "Set_Priority: D3DTexture is NULL!\n"); return 0; } return D3DTexture->SetPriority(priority); } // ---------------------------------------------------------------------------- void TextureClass::Set_Mip_Mapping(FilterType mipmap) { if (mipmap != FILTER_TYPE_NONE && Get_Mip_Level_Count() <= 1) { WWASSERT_PRINT(0, "Trying to enable MipMapping on texture w/o Mip levels!\n"); return; } MipMapFilter=mipmap; } unsigned TextureClass::Get_Reduction() const { if (MipLevelCount==MIP_LEVELS_1) return 0; int reduction=WW3D::Get_Texture_Reduction(); if (MipLevelCount && reduction>MipLevelCount) { reduction=MipLevelCount; } return reduction; } // ---------------------------------------------------------------------------- void TextureClass::Apply(unsigned int stage) { if (!Initialized) { Init(); } LastAccessed=WW3D::Get_Sync_Time(); DX8_RECORD_TEXTURE(this); // Set texture itself if (WW3D::Is_Texturing_Enabled()) { DX8Wrapper::Set_DX8_Texture(stage, D3DTexture); } else { DX8Wrapper::Set_DX8_Texture(stage, NULL); } DX8Wrapper::Set_DX8_Texture_Stage_State(stage,D3DTSS_MINFILTER,_MinTextureFilters[stage][TextureMinFilter]); DX8Wrapper::Set_DX8_Texture_Stage_State(stage,D3DTSS_MAGFILTER,_MagTextureFilters[stage][TextureMagFilter]); DX8Wrapper::Set_DX8_Texture_Stage_State(stage,D3DTSS_MIPFILTER,_MipMapFilters[stage][MipMapFilter]); switch (Get_U_Addr_Mode()) { case TEXTURE_ADDRESS_REPEAT: DX8Wrapper::Set_DX8_Texture_Stage_State(stage, D3DTSS_ADDRESSU, D3DTADDRESS_WRAP); break; case TEXTURE_ADDRESS_CLAMP: DX8Wrapper::Set_DX8_Texture_Stage_State(stage, D3DTSS_ADDRESSU, D3DTADDRESS_CLAMP); break; } switch (Get_V_Addr_Mode()) { case TEXTURE_ADDRESS_REPEAT: DX8Wrapper::Set_DX8_Texture_Stage_State(stage, D3DTSS_ADDRESSV, D3DTADDRESS_WRAP); break; case TEXTURE_ADDRESS_CLAMP: DX8Wrapper::Set_DX8_Texture_Stage_State(stage, D3DTSS_ADDRESSV, D3DTADDRESS_CLAMP); break; } } // ---------------------------------------------------------------------------- void TextureClass::Apply_Null(unsigned int stage) { // This function sets the render states for a "NULL" texture DX8Wrapper::Set_DX8_Texture(stage, NULL); } // ---------------------------------------------------------------------------- void TextureClass::Apply_New_Surface(IDirect3DTexture8* d3d_texture,bool initialized) { if (D3DTexture) D3DTexture->Release(); D3DTexture=d3d_texture;//TextureLoadTask->Peek_D3D_Texture(); D3DTexture->AddRef(); if (initialized) Initialized=true; WWASSERT(D3DTexture); IDirect3DSurface8* surface; DX8_ErrorCode(D3DTexture->GetSurfaceLevel(0,&surface)); D3DSURFACE_DESC d3d_desc; ::ZeroMemory(&d3d_desc, sizeof(D3DSURFACE_DESC)); DX8_ErrorCode(surface->GetDesc(&d3d_desc)); if (initialized) { TextureFormat=D3DFormat_To_WW3DFormat(d3d_desc.Format); Width=d3d_desc.Width; Height=d3d_desc.Height; } surface->Release(); } // ---------------------------------------------------------------------------- unsigned TextureClass::Get_Texture_Memory_Usage() const { if (!Initialized) return Calculate_Texture_Memory_Usage(this,0); return Calculate_Texture_Memory_Usage(this,0); } // ---------------------------------------------------------------------------- int TextureClass::_Get_Total_Locked_Surface_Size() { int total_locked_surface_size=0; HashTemplateIterator ite(WW3DAssetManager::Get_Instance()->Texture_Hash()); // Loop through all the textures in the manager for (ite.First ();!ite.Is_Done();ite.Next ()) { // Get the current texture TextureClass* tex=ite.Peek_Value(); if (!tex->Initialized) { total_locked_surface_size+=tex->Get_Texture_Memory_Usage(); } } return total_locked_surface_size; } // ---------------------------------------------------------------------------- int TextureClass::_Get_Total_Texture_Size() { int total_texture_size=0; HashTemplateIterator ite(WW3DAssetManager::Get_Instance()->Texture_Hash()); // Loop through all the textures in the manager for (ite.First ();!ite.Is_Done();ite.Next ()) { // Get the current texture TextureClass* tex=ite.Peek_Value(); total_texture_size+=tex->Get_Texture_Memory_Usage(); } return total_texture_size; } // ---------------------------------------------------------------------------- int TextureClass::_Get_Total_Lightmap_Texture_Size() { int total_texture_size=0; HashTemplateIterator ite(WW3DAssetManager::Get_Instance()->Texture_Hash()); // Loop through all the textures in the manager for (ite.First ();!ite.Is_Done();ite.Next ()) { // Get the current texture TextureClass* tex=ite.Peek_Value(); if (tex->Is_Lightmap()) { total_texture_size+=tex->Get_Texture_Memory_Usage(); } } return total_texture_size; } // ---------------------------------------------------------------------------- int TextureClass::_Get_Total_Procedural_Texture_Size() { int total_texture_size=0; HashTemplateIterator ite(WW3DAssetManager::Get_Instance()->Texture_Hash()); // Loop through all the textures in the manager for (ite.First ();!ite.Is_Done();ite.Next ()) { // Get the current texture TextureClass* tex=ite.Peek_Value(); if (tex->Is_Procedural()) { total_texture_size+=tex->Get_Texture_Memory_Usage(); } } return total_texture_size; } // ---------------------------------------------------------------------------- int TextureClass::_Get_Total_Texture_Count() { int texture_count=0; HashTemplateIterator ite(WW3DAssetManager::Get_Instance()->Texture_Hash()); // Loop through all the textures in the manager for (ite.First ();!ite.Is_Done();ite.Next ()) { texture_count++; } return texture_count; } // ---------------------------------------------------------------------------- int TextureClass::_Get_Total_Lightmap_Texture_Count() { int texture_count=0; HashTemplateIterator ite(WW3DAssetManager::Get_Instance()->Texture_Hash()); // Loop through all the textures in the manager for (ite.First ();!ite.Is_Done();ite.Next ()) { if (ite.Peek_Value()->Is_Lightmap()) { texture_count++; } } return texture_count; } // ---------------------------------------------------------------------------- int TextureClass::_Get_Total_Procedural_Texture_Count() { int texture_count=0; HashTemplateIterator ite(WW3DAssetManager::Get_Instance()->Texture_Hash()); // Loop through all the textures in the manager for (ite.First ();!ite.Is_Done();ite.Next ()) { if (ite.Peek_Value()->Is_Procedural()) { texture_count++; } } return texture_count; } // ---------------------------------------------------------------------------- int TextureClass::_Get_Total_Locked_Surface_Count() { int texture_count=0; HashTemplateIterator ite(WW3DAssetManager::Get_Instance()->Texture_Hash()); // Loop through all the textures in the manager for (ite.First ();!ite.Is_Done();ite.Next ()) { // Get the current texture TextureClass* tex=ite.Peek_Value(); if (!tex->Initialized) { texture_count++; } } return texture_count; } void TextureClass::_Init_Filters(TextureClass::TextureFilterMode filter_type) { const D3DCAPS8& dx8caps=DX8Wrapper::Get_Current_Caps()->Get_DX8_Caps(); _MinTextureFilters[0][FILTER_TYPE_NONE]=D3DTEXF_POINT; _MagTextureFilters[0][FILTER_TYPE_NONE]=D3DTEXF_POINT; _MipMapFilters[0][FILTER_TYPE_NONE]=D3DTEXF_NONE; _MinTextureFilters[0][FILTER_TYPE_FAST]=D3DTEXF_LINEAR; _MagTextureFilters[0][FILTER_TYPE_FAST]=D3DTEXF_LINEAR; _MipMapFilters[0][FILTER_TYPE_FAST]=D3DTEXF_POINT; _MagTextureFilters[0][FILTER_TYPE_BEST]=D3DTEXF_POINT; _MinTextureFilters[0][FILTER_TYPE_BEST]=D3DTEXF_POINT; _MipMapFilters[0][FILTER_TYPE_BEST]=D3DTEXF_POINT; if (dx8caps.TextureFilterCaps&D3DPTFILTERCAPS_MAGFLINEAR) _MagTextureFilters[0][FILTER_TYPE_BEST]=D3DTEXF_LINEAR; if (dx8caps.TextureFilterCaps&D3DPTFILTERCAPS_MINFLINEAR) _MinTextureFilters[0][FILTER_TYPE_BEST]=D3DTEXF_LINEAR; // Set anisotropic filtering only if requested and available if (filter_type==TextureClass::TEXTURE_FILTER_ANISOTROPIC) { if (dx8caps.TextureFilterCaps&D3DPTFILTERCAPS_MAGFANISOTROPIC) _MagTextureFilters[0][FILTER_TYPE_BEST]=D3DTEXF_ANISOTROPIC; if (dx8caps.TextureFilterCaps&D3DPTFILTERCAPS_MINFANISOTROPIC) _MinTextureFilters[0][FILTER_TYPE_BEST]=D3DTEXF_ANISOTROPIC; } // Set linear mip filter only if requested trilinear or anisotropic, and linear available if (filter_type==TextureClass::TEXTURE_FILTER_ANISOTROPIC || filter_type==TextureClass::TEXTURE_FILTER_TRILINEAR) { if (dx8caps.TextureFilterCaps&D3DPTFILTERCAPS_MIPFLINEAR) _MipMapFilters[0][FILTER_TYPE_BEST]=D3DTEXF_LINEAR; } // For stages above zero, set best filter to the same as the stage zero, except if anisotropic for (int i=1;iSupport_Bump_Envmap()) { // No mipmaps to bumpmap for now mipcount=TextureClass::MIP_LEVELS_1; if (DX8Wrapper::Get_Current_Caps()->Support_Texture_Format(WW3D_FORMAT_U8V8)) format=WW3D_FORMAT_U8V8; else if (DX8Wrapper::Get_Current_Caps()->Support_Texture_Format(WW3D_FORMAT_X8L8V8U8)) format=WW3D_FORMAT_X8L8V8U8; else if (DX8Wrapper::Get_Current_Caps()->Support_Texture_Format(WW3D_FORMAT_L6V5U5)) format=WW3D_FORMAT_L6V5U5; } break; } default: WWASSERT (false); break; } newtex = WW3DAssetManager::Get_Instance()->Get_Texture (name, mipcount, format); if (no_lod) { newtex->Set_Mip_Mapping(TextureClass::FILTER_TYPE_NONE); } bool u_clamp = ((texinfo.Attributes & W3DTEXTURE_CLAMP_U) != 0); newtex->Set_U_Addr_Mode(u_clamp ? TextureClass::TEXTURE_ADDRESS_CLAMP : TextureClass::TEXTURE_ADDRESS_REPEAT); bool v_clamp = ((texinfo.Attributes & W3DTEXTURE_CLAMP_V) != 0); newtex->Set_V_Addr_Mode(v_clamp ? TextureClass::TEXTURE_ADDRESS_CLAMP : TextureClass::TEXTURE_ADDRESS_REPEAT); } else { newtex = WW3DAssetManager::Get_Instance()->Get_Texture(name); } WWASSERT(newtex); } // Return a pointer to the new texture return newtex; } // Utility function used by Save_Texture void setup_texture_attributes(TextureClass * tex, W3dTextureInfoStruct * texinfo) { texinfo->Attributes = 0; if (tex->Get_Mip_Mapping() == TextureClass::FILTER_TYPE_NONE) texinfo->Attributes |= W3DTEXTURE_NO_LOD; if (tex->Get_U_Addr_Mode() == TextureClass::TEXTURE_ADDRESS_CLAMP) texinfo->Attributes |= W3DTEXTURE_CLAMP_U; if (tex->Get_V_Addr_Mode() == TextureClass::TEXTURE_ADDRESS_CLAMP) texinfo->Attributes |= W3DTEXTURE_CLAMP_V; } void Save_Texture(TextureClass * texture,ChunkSaveClass & csave) { const char * filename; W3dTextureInfoStruct texinfo; memset(&texinfo,0,sizeof(texinfo)); filename = texture->Get_Full_Path(); setup_texture_attributes(texture, &texinfo); csave.Begin_Chunk(W3D_CHUNK_TEXTURE_NAME); csave.Write(filename,strlen(filename)+1); csave.End_Chunk(); if ((texinfo.Attributes != 0) || (texinfo.AnimType != 0) || (texinfo.FrameCount != 0)) { csave.Begin_Chunk(W3D_CHUNK_TEXTURE_INFO); csave.Write(&texinfo, sizeof(texinfo)); csave.End_Chunk(); } }