/* ** Command & Conquer Generals Zero Hour(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 : Max2W3d * * * * $Archive:: /Commando/Code/Tools/max2w3d/w3dmtl.cpp $* * * * $Author:: Greg_h $* * * * $Modtime:: 8/22/01 7:47a $* * * * $Revision:: 32 $* * * *---------------------------------------------------------------------------------------------* * Functions: * * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ #include "w3dmtl.h" #include #include #include "gamemtl.h" #include "realcrc.h" static W3dRGBStruct Color_To_W3d(Color & c) { W3dRGBStruct wc; wc.R = (c.r * 255.0f); wc.G = (c.g * 255.0f); wc.B = (c.b * 255.0f); wc.pad = 0; return wc; } /* Implementation of W3dMapClass */ W3dMapClass::W3dMapClass(const W3dMapClass & that) { Set_Filename(that.Filename); if (that.AnimInfo) { Set_Anim_Info(that.AnimInfo); } } W3dMapClass & W3dMapClass::operator = (const W3dMapClass & that) { if (this != &that) { Set_Filename(that.Filename); Set_Anim_Info(that.AnimInfo); } return *this; } W3dMapClass::~W3dMapClass(void) { if (Filename) free(Filename); if (AnimInfo) delete AnimInfo; } void W3dMapClass::Reset(void) { if (Filename) free(Filename); if (AnimInfo) delete AnimInfo; Filename = NULL; AnimInfo = NULL; } void W3dMapClass::Set_Filename(const char * fullpath) { if (Filename) { free(Filename); } if (fullpath) { char name[_MAX_FNAME]; char exten[_MAX_EXT]; char fname[_MAX_FNAME+_MAX_EXT+2]; _splitpath(fullpath,NULL,NULL,name,exten); _makepath(fname,NULL,NULL,name,exten); //strupr(fname); (gth) need to preserve case since unix/PS2 is case sensitive... Filename = strdup(fname); } else { Filename = NULL; } } void W3dMapClass::Set_Anim_Info(const W3dTextureInfoStruct * info) { if (info == NULL) { if (AnimInfo) { delete AnimInfo; AnimInfo = NULL; return; } } else { if (AnimInfo == NULL) { AnimInfo = new W3dTextureInfoStruct; } *AnimInfo = *info; } } void W3dMapClass::Set_Anim_Info(int framecount,float framerate) { if (AnimInfo == NULL) { AnimInfo = new W3dTextureInfoStruct; } AnimInfo->FrameCount = framecount; AnimInfo->FrameRate = framerate; } /* Implementation of W3dMaterialClass */ W3dMaterialClass::W3dMaterialClass(void) { PassCount = 0; SortLevel = SORT_LEVEL_NONE; for (int pass = 0; pass < MAX_PASSES; pass++) { Materials[pass] = NULL; W3d_Shader_Reset(&(Shaders[pass])); for (int stage = 0; stage < MAX_STAGES; stage++) { Textures[pass][stage] = NULL; MapChannel[pass][stage] = 1; MapperArgs[pass][stage] = NULL; } } } W3dMaterialClass::~W3dMaterialClass(void) { Free(); } void W3dMaterialClass::Free(void) { for (int pass = 0; pass < MAX_PASSES; pass++) { if (Materials[pass]) { delete Materials[pass]; Materials[pass] = NULL; } for (int stage = 0; stage < MAX_STAGES; stage++) { if (Textures[pass][stage]) { delete Textures[pass][stage]; Textures[pass][stage] = NULL; } if (MapperArgs[pass][stage]) { delete [] MapperArgs[pass][stage]; MapperArgs[pass][stage] = NULL; } } } } void W3dMaterialClass::Reset(void) { Free(); SortLevel = SORT_LEVEL_NONE; for (int pass=0; pass < MAX_PASSES; pass++) { W3d_Shader_Reset(&(Shaders[pass])); for (int stage=0; stage < MAX_STAGES; stage++) { MapChannel[pass][stage] = 1; } } } void W3dMaterialClass::Set_Surface_Type(unsigned int type) { SurfaceType = type; } void W3dMaterialClass::Set_Sort_Level(int level) { assert(level <= MAX_SORT_LEVEL); SortLevel = level; } void W3dMaterialClass::Set_Pass_Count(int count) { assert(count >= 0); assert(count < MAX_PASSES); PassCount = count; } void W3dMaterialClass::Set_Vertex_Material(const W3dVertexMaterialStruct & vmat,int pass) { assert(pass >= 0); assert(pass < PassCount); if (Materials[pass] == NULL) { Materials[pass] = new W3dVertexMaterialStruct; } *(Materials[pass]) = vmat; } void W3dMaterialClass::Set_Mapper_Args(const char *args_buffer, int pass, int stage) { assert(pass >= 0); assert(pass < PassCount); assert(stage >= 0); assert(stage < MAX_STAGES); if (MapperArgs[pass][stage] != NULL) { delete [] MapperArgs[pass][stage]; MapperArgs[pass][stage] = NULL; } if (args_buffer) { int len = strlen(args_buffer); MapperArgs[pass][stage] = new char [len + 1]; strcpy(MapperArgs[pass][stage], args_buffer); } } void W3dMaterialClass::Set_Shader(const W3dShaderStruct & shader,int pass) { assert(pass >= 0); assert(pass < PassCount); Shaders[pass] = shader; } void W3dMaterialClass::Set_Texture(const W3dMapClass & map,int pass,int stage) { assert(pass >= 0); assert(pass < PassCount); if (Textures[pass][stage] == NULL) { Textures[pass][stage] = new W3dMapClass; } *(Textures[pass][stage]) = map; } void W3dMaterialClass::Set_Map_Channel(int pass,int stage,int channel) { assert(pass >= 0); assert(pass < PassCount); MapChannel[pass][stage] = channel; } unsigned int W3dMaterialClass::Get_Surface_Type(void) const { return SurfaceType; } int W3dMaterialClass::Get_Sort_Level(void) const { return SortLevel; } int W3dMaterialClass::Get_Pass_Count(void) const { return PassCount; } W3dVertexMaterialStruct * W3dMaterialClass::Get_Vertex_Material(int pass ) const { assert(pass >= 0); assert(pass < PassCount); return Materials[pass]; } const char * W3dMaterialClass::Get_Mapper_Args(int pass, int stage) const { assert(pass >= 0); assert(pass < PassCount); assert(stage >= 0); assert(stage < MAX_STAGES); return MapperArgs[pass][stage]; } W3dShaderStruct W3dMaterialClass::Get_Shader(int pass) const { assert(pass >= 0); assert(pass < PassCount); return Shaders[pass]; } W3dMapClass * W3dMaterialClass::Get_Texture(int pass,int stage) const { assert(pass >= 0); assert(pass < PassCount); assert(stage >= 0); assert(stage < MAX_STAGES); return Textures[pass][stage]; } int W3dMaterialClass::Get_Map_Channel(int pass,int stage) const { assert(pass >= 0); assert(pass < PassCount); assert(stage >= 0); assert(stage < MAX_STAGES); return MapChannel[pass][stage]; } void W3dMaterialClass::Init(Mtl * mtl, char *materialColorTexture) { bool ps2_mat = false; Reset(); if (mtl->ClassID() == PS2GameMaterialClassID) { ps2_mat = true; } if ((mtl->ClassID() == GameMaterialClassID) || ps2_mat) { Init((GameMtl*)mtl, materialColorTexture); ///@todo: Fix this for substituted textures. return; } Texmap * tmap; PassCount = 1; tmap = mtl->GetSubTexmap(ID_RL); if (tmap && tmap->ClassID() == Class_ID(BMTEX_CLASS_ID,0)) { PassCount++; } W3dVertexMaterialStruct mat; W3dShaderStruct shader; W3dMapClass tex; /* ** Setting up the diffuse color pass */ W3d_Shader_Reset(&shader); mat.Attributes = 0; mat.Emissive.R = mat.Emissive.G = mat.Emissive.B = 0; //(uint8)(255 .0f * mtl->GetSelfIllum()); Color diffuse = mtl->GetDiffuse(); mat.Diffuse.R = (uint8)(diffuse.r * 255.0f); mat.Diffuse.G = (uint8)(diffuse.g * 255.0f); mat.Diffuse.B = (uint8)(diffuse.b * 255.0f); mat.Ambient = mat.Diffuse; Color specular = mtl->GetSpecular(); mat.Specular.R = (uint8)(specular.r * 255.0f); mat.Specular.G = (uint8)(specular.g * 255.0f); mat.Specular.B = (uint8)(specular.b * 255.0f); mat.Shininess = mtl->GetShininess(); mat.Opacity = 1.0f - mtl->GetXParency(); mat.Translucency = 0.0f; tmap = mtl->GetSubTexmap(ID_DI); if (tmap && tmap->ClassID() == Class_ID(BMTEX_CLASS_ID,0)) { char * tname = ((BitmapTex *)tmap)->GetMapName(); if (tname) { tex.Set_Filename(tname); mat.Diffuse.R = mat.Diffuse.G = mat.Diffuse.B = 255; W3d_Shader_Set_Texturing(&shader,W3DSHADER_TEXTURING_ENABLE); Set_Texture(tex,0,0); } } if (materialColorTexture && !mtl->GetSubTexmap(ID_DI) && !mtl->GetSubTexmap(ID_RL)) { //no textures on material, substitute textures to improve rendering speed. tex.Set_Filename(materialColorTexture); ///@todo: Fix this to procedural name/path W3d_Shader_Set_Texturing(&shader,W3DSHADER_TEXTURING_ENABLE); //This texture will hold solid pixels of material color, don't need any filtering. // W3dTextureInfoStruct texinfo; // memset(&texinfo,0,sizeof(texinfo)); // texinfo.Attributes = texinfo.Attributes | /*W3DTEXTURE_NO_LOD|*/W3DTEXTURE_CLAMP_U | W3DTEXTURE_CLAMP_V; // tex.Set_Anim_Info(&texinfo); Set_Texture(tex,0,0); } if (mat.Opacity != 1.0f) { W3d_Shader_Set_Dest_Blend_Func(&shader,W3DSHADER_DESTBLENDFUNC_ONE_MINUS_SRC_ALPHA); W3d_Shader_Set_Src_Blend_Func(&shader,W3DSHADER_SRCBLENDFUNC_SRC_ALPHA); } Set_Vertex_Material(mat,0); Set_Shader(shader,0); /* ** Setting up the reflection pass (envmap) */ if (PassCount == 2) { W3d_Shader_Reset(&shader); if (ps2_mat) { W3d_Shader_Set_Pri_Gradient(&shader,PSS_PRIGRADIENT_MODULATE); } else { W3d_Shader_Set_Pri_Gradient(&shader,W3DSHADER_PRIGRADIENT_MODULATE); } W3d_Shader_Set_Sec_Gradient(&shader,W3DSHADER_SECGRADIENT_DISABLE); W3d_Shader_Set_Depth_Mask(&shader,W3DSHADER_DEPTHMASK_WRITE_DISABLE); W3d_Shader_Set_Dest_Blend_Func(&shader,W3DSHADER_DESTBLENDFUNC_ONE); W3d_Shader_Set_Src_Blend_Func(&shader,W3DSHADER_SRCBLENDFUNC_ONE); W3d_Shader_Set_Texturing(&shader,W3DSHADER_TEXTURING_ENABLE); // PS2 specific paramaters. W3d_Shader_Set_PS2_Param_A(&shader, PSS_SRC); W3d_Shader_Set_PS2_Param_B(&shader, PSS_ZERO); W3d_Shader_Set_PS2_Param_B(&shader, PSS_ONE); W3d_Shader_Set_PS2_Param_B(&shader, PSS_DEST); W3d_Vertex_Material_Reset(&mat); mat.Diffuse.R = mat.Diffuse.G = mat.Diffuse.B = 128; mat.Attributes &= W3DVERTMAT_STAGE0_MAPPING_MASK; mat.Attributes |= W3DVERTMAT_STAGE0_MAPPING_ENVIRONMENT; tmap = mtl->GetSubTexmap(ID_RL); if (tmap && tmap->ClassID() == Class_ID(BMTEX_CLASS_ID,0)) { char * tname = ((BitmapTex *)tmap)->GetMapName(); if (tname) { tex.Set_Filename(tname); Set_Texture(tex,1); } } Set_Vertex_Material(mat,1); Set_Shader(shader,1); } } void W3dMaterialClass::Init(GameMtl * gamemtl, char *materialColorTexture) { Reset(); PassCount = gamemtl->Get_Pass_Count(); Set_Surface_Type (gamemtl->Get_Surface_Type ()); Set_Sort_Level(gamemtl->Get_Sort_Level()); for (int pass=0;passGet_Pass_Count(); pass++) { /* ** set up the shader */ W3dShaderStruct shader; W3d_Shader_Reset(&shader); shader.DepthCompare = gamemtl->Get_Depth_Compare(pass); shader.DepthMask = gamemtl->Get_Depth_Mask(pass); shader.AlphaTest = gamemtl->Get_Alpha_Test(pass); shader.DestBlend = gamemtl->Get_Dest_Blend(pass); shader.PriGradient = gamemtl->Get_Pri_Gradient(pass); shader.SecGradient = gamemtl->Get_Sec_Gradient(pass); shader.SrcBlend = gamemtl->Get_Src_Blend(pass); shader.DetailColorFunc = gamemtl->Get_Detail_Color_Func(pass); shader.DetailAlphaFunc = gamemtl->Get_Detail_Alpha_Func(pass); shader.Texturing = W3DSHADER_TEXTURING_DISABLE; shader.PostDetailColorFunc = gamemtl->Get_Detail_Color_Func(pass); // (gth) set up the post-detail options shader.PostDetailAlphaFunc = gamemtl->Get_Detail_Alpha_Func(pass); // PS2 specific paramaters. W3d_Shader_Set_PS2_Param_A(&shader, gamemtl->Get_PS2_Shader_Param_A(pass)); W3d_Shader_Set_PS2_Param_B(&shader, gamemtl->Get_PS2_Shader_Param_B(pass)); W3d_Shader_Set_PS2_Param_C(&shader, gamemtl->Get_PS2_Shader_Param_C(pass)); W3d_Shader_Set_PS2_Param_D(&shader, gamemtl->Get_PS2_Shader_Param_D(pass)); /* ** set up the vertex material */ W3dVertexMaterialStruct mat; mat.Attributes = 0; if (gamemtl->Get_Copy_Specular_To_Diffuse(pass)) { mat.Attributes |= W3DVERTMAT_COPY_SPECULAR_TO_DIFFUSE; } // mapping type for stage 0 switch(gamemtl->Get_Mapping_Type(pass, 0)) { case GAMEMTL_MAPPING_UV: mat.Attributes |= W3DVERTMAT_STAGE0_MAPPING_UV; break; case GAMEMTL_MAPPING_ENV: mat.Attributes |= W3DVERTMAT_STAGE0_MAPPING_ENVIRONMENT; break; case GAMEMTL_MAPPING_CHEAP_ENV: mat.Attributes |= W3DVERTMAT_STAGE0_MAPPING_CHEAP_ENVIRONMENT; break; case GAMEMTL_MAPPING_SCREEN: mat.Attributes |= W3DVERTMAT_STAGE0_MAPPING_SCREEN; break; case GAMEMTL_MAPPING_LINEAR_OFFSET: mat.Attributes |= W3DVERTMAT_STAGE0_MAPPING_LINEAR_OFFSET; break; case GAMEMTL_MAPPING_SILHOUETTE: mat.Attributes |= W3DVERTMAT_STAGE0_MAPPING_SILHOUETTE; break; case GAMEMTL_MAPPING_SCALE: mat.Attributes |= W3DVERTMAT_STAGE0_MAPPING_SCALE; break; case GAMEMTL_MAPPING_GRID: mat.Attributes |= W3DVERTMAT_STAGE0_MAPPING_GRID; break; case GAMEMTL_MAPPING_ROTATE: mat.Attributes |= W3DVERTMAT_STAGE0_MAPPING_ROTATE; break; case GAMEMTL_MAPPING_SINE_LINEAR_OFFSET: mat.Attributes |= W3DVERTMAT_STAGE0_MAPPING_SINE_LINEAR_OFFSET; break; case GAMEMTL_MAPPING_STEP_LINEAR_OFFSET: mat.Attributes |= W3DVERTMAT_STAGE0_MAPPING_STEP_LINEAR_OFFSET; break; case GAMEMTL_MAPPING_ZIGZAG_LINEAR_OFFSET: mat.Attributes |= W3DVERTMAT_STAGE0_MAPPING_ZIGZAG_LINEAR_OFFSET; break; case GAMEMTL_MAPPING_WS_CLASSIC_ENV: mat.Attributes |= W3DVERTMAT_STAGE0_MAPPING_WS_CLASSIC_ENV; break; case GAMEMTL_MAPPING_WS_ENVIRONMENT: mat.Attributes |= W3DVERTMAT_STAGE0_MAPPING_WS_ENVIRONMENT; break; case GAMEMTL_MAPPING_GRID_CLASSIC_ENV: mat.Attributes |= W3DVERTMAT_STAGE0_MAPPING_GRID_CLASSIC_ENV; break; case GAMEMTL_MAPPING_GRID_ENVIRONMENT: mat.Attributes |= W3DVERTMAT_STAGE0_MAPPING_GRID_ENVIRONMENT; break; case GAMEMTL_MAPPING_RANDOM: mat.Attributes |= W3DVERTMAT_STAGE0_MAPPING_RANDOM; break; case GAMEMTL_MAPPING_EDGE: mat.Attributes |= W3DVERTMAT_STAGE0_MAPPING_EDGE; break; case GAMEMTL_MAPPING_BUMPENV: mat.Attributes |= W3DVERTMAT_STAGE0_MAPPING_BUMPENV; break; }; // mapping type for stage 1 switch(gamemtl->Get_Mapping_Type(pass, 1)) { case GAMEMTL_MAPPING_UV: mat.Attributes |= W3DVERTMAT_STAGE1_MAPPING_UV; break; case GAMEMTL_MAPPING_ENV: mat.Attributes |= W3DVERTMAT_STAGE1_MAPPING_ENVIRONMENT; break; case GAMEMTL_MAPPING_CHEAP_ENV: mat.Attributes |= W3DVERTMAT_STAGE1_MAPPING_CHEAP_ENVIRONMENT; break; case GAMEMTL_MAPPING_SCREEN: mat.Attributes |= W3DVERTMAT_STAGE1_MAPPING_SCREEN; break; case GAMEMTL_MAPPING_LINEAR_OFFSET: mat.Attributes |= W3DVERTMAT_STAGE1_MAPPING_LINEAR_OFFSET; break; case GAMEMTL_MAPPING_SILHOUETTE: mat.Attributes |= W3DVERTMAT_STAGE1_MAPPING_SILHOUETTE; break; case GAMEMTL_MAPPING_SCALE: mat.Attributes |= W3DVERTMAT_STAGE1_MAPPING_SCALE; break; case GAMEMTL_MAPPING_GRID: mat.Attributes |= W3DVERTMAT_STAGE1_MAPPING_GRID; break; case GAMEMTL_MAPPING_ROTATE: mat.Attributes |= W3DVERTMAT_STAGE1_MAPPING_ROTATE; break; case GAMEMTL_MAPPING_SINE_LINEAR_OFFSET: mat.Attributes |= W3DVERTMAT_STAGE1_MAPPING_SINE_LINEAR_OFFSET; break; case GAMEMTL_MAPPING_STEP_LINEAR_OFFSET: mat.Attributes |= W3DVERTMAT_STAGE1_MAPPING_STEP_LINEAR_OFFSET; break; case GAMEMTL_MAPPING_ZIGZAG_LINEAR_OFFSET: mat.Attributes |= W3DVERTMAT_STAGE1_MAPPING_ZIGZAG_LINEAR_OFFSET; break; case GAMEMTL_MAPPING_WS_CLASSIC_ENV: mat.Attributes |= W3DVERTMAT_STAGE1_MAPPING_WS_CLASSIC_ENV; break; case GAMEMTL_MAPPING_WS_ENVIRONMENT: mat.Attributes |= W3DVERTMAT_STAGE1_MAPPING_WS_ENVIRONMENT; break; case GAMEMTL_MAPPING_GRID_CLASSIC_ENV: mat.Attributes |= W3DVERTMAT_STAGE1_MAPPING_GRID_CLASSIC_ENV; break; case GAMEMTL_MAPPING_GRID_ENVIRONMENT: mat.Attributes |= W3DVERTMAT_STAGE1_MAPPING_GRID_ENVIRONMENT; break; case GAMEMTL_MAPPING_RANDOM: mat.Attributes |= W3DVERTMAT_STAGE1_MAPPING_RANDOM; break; case GAMEMTL_MAPPING_EDGE: mat.Attributes |= W3DVERTMAT_STAGE1_MAPPING_EDGE; break; case GAMEMTL_MAPPING_BUMPENV: mat.Attributes |= W3DVERTMAT_STAGE1_MAPPING_BUMPENV; break; }; switch(gamemtl->Get_PSX_Translucency(pass)) { case GAMEMTL_PSX_TRANS_NONE: mat.Attributes |= W3DVERTMAT_PSX_TRANS_NONE; break; case GAMEMTL_PSX_TRANS_100: mat.Attributes |= W3DVERTMAT_PSX_TRANS_100; break; case GAMEMTL_PSX_TRANS_50: mat.Attributes |= W3DVERTMAT_PSX_TRANS_50; break; case GAMEMTL_PSX_TRANS_25: mat.Attributes |= W3DVERTMAT_PSX_TRANS_25; break; case GAMEMTL_PSX_TRANS_MINUS_100:mat.Attributes |= W3DVERTMAT_PSX_TRANS_MINUS_100; break; }; if (!gamemtl->Get_PSX_Lighting(pass)) { mat.Attributes |= W3DVERTMAT_PSX_NO_RT_LIGHTING; } mat.Ambient = Color_To_W3d(gamemtl->Get_Ambient(pass,0)); mat.Diffuse = Color_To_W3d(gamemtl->Get_Diffuse(pass,0)); mat.Specular = Color_To_W3d(gamemtl->Get_Specular(pass,0)); mat.Emissive = Color_To_W3d(gamemtl->Get_Emissive(pass,0)); mat.Shininess = gamemtl->Get_Shininess(pass,0); mat.Opacity = gamemtl->Get_Opacity(pass,0); mat.Translucency = gamemtl->Get_Translucency(pass,0); /* ** install the two textures if present */ W3dMapClass w3dmap; BitmapTex * tex = NULL; for (int stage=0; stage < MAX_STAGES; stage++) { if (gamemtl->Get_Texture_Enable(pass,stage) && gamemtl->Get_Texture(pass,stage)) { w3dmap.Reset(); // get the filename for the w3dmap texture tex = (BitmapTex *)gamemtl->Get_Texture(pass,stage); assert(tex->GetMapName()); w3dmap.Set_Filename(tex->GetMapName()); // get the animation and flags for the w3dmap texture W3dTextureInfoStruct texinfo; memset(&texinfo,0,sizeof(texinfo)); texinfo.AnimType = gamemtl->Get_Texture_Anim_Type(pass,stage); if (gamemtl->Get_Texture_Publish(pass,stage)) { texinfo.Attributes = texinfo.Attributes | W3DTEXTURE_PUBLISH; } if (gamemtl->Get_Texture_No_LOD(pass,stage)) { texinfo.Attributes = texinfo.Attributes | W3DTEXTURE_NO_LOD; } if (gamemtl->Get_Texture_Clamp_U(pass,stage)) { texinfo.Attributes = texinfo.Attributes | W3DTEXTURE_CLAMP_U; } if (gamemtl->Get_Texture_Clamp_V(pass,stage)) { texinfo.Attributes = texinfo.Attributes | W3DTEXTURE_CLAMP_V; } if (gamemtl->Get_Texture_Alpha_Bitmap(pass,stage)) { texinfo.Attributes = texinfo.Attributes | W3DTEXTURE_ALPHA_BITMAP; } texinfo.Attributes = texinfo.Attributes | ( (gamemtl->Get_Texture_Hint(pass,stage) << W3DTEXTURE_HINT_SHIFT) & W3DTEXTURE_HINT_MASK); // If the shader indicates bump-environment mapping mark this texture as a bumpmap. if ((stage == 0) && (gamemtl->Get_Pri_Gradient (pass) == W3DSHADER_PRIGRADIENT_BUMPENVMAP)) { texinfo.Attributes |= W3DTEXTURE_TYPE_BUMPMAP; } texinfo.FrameCount = gamemtl->Get_Texture_Frame_Count(pass,stage); texinfo.FrameRate = gamemtl->Get_Texture_Frame_Rate(pass,stage); if ((texinfo.FrameCount > 1) || (texinfo.Attributes != 0)) { w3dmap.Set_Anim_Info(&texinfo); } // plug it in and turn on texturing in the shader Set_Texture(w3dmap,pass,stage); shader.Texturing = W3DSHADER_TEXTURING_ENABLE; // copy over the mapping channel Set_Map_Channel(pass,stage,gamemtl->Get_Map_Channel(pass,stage)); // copy over the mapper args Set_Mapper_Args(gamemtl->Get_Mapping_Arg_Buffer(pass, stage), pass, stage); } else { if (materialColorTexture) { //no textures on material, substitute textures to improve rendering speed. w3dmap.Reset(); w3dmap.Set_Filename(materialColorTexture); // plug it in and turn on texturing in the shader Set_Texture(w3dmap,pass,stage); shader.Texturing = W3DSHADER_TEXTURING_ENABLE; } break; // break out of the loop (and dont put in stage 1 if stage 0 is missing...) } } Set_Shader(shader,pass); Set_Vertex_Material(mat,pass); } } bool W3dMaterialClass::Is_Multi_Pass_Transparent(void) const { return ((PassCount >= 2) && (Get_Shader(0).DestBlend != W3DSHADER_DESTBLENDFUNC_ZERO)); } /* Implementation of W3dMaterialDescClass::VertClass */ W3dMaterialDescClass::VertMatClass::VertMatClass(void) : PassIndex(-1), Crc(0), Name(NULL) { for (int stage=0; stage < W3dMaterialClass::MAX_STAGES; ++stage) { MapperArgs[stage] = NULL; } } W3dMaterialDescClass::VertMatClass::~VertMatClass(void) { if (Name) free(Name); for (int stage=0; stage < W3dMaterialClass::MAX_STAGES; ++stage) { if (MapperArgs[stage]) { delete [] (MapperArgs[stage]); MapperArgs[stage] = NULL; } } } W3dMaterialDescClass::VertMatClass & W3dMaterialDescClass::VertMatClass::operator = (const VertMatClass & that) { if (this != &that) { Material = that.Material; PassIndex = that.PassIndex; Crc = that.Crc; Set_Name(that.Name); for (int stage=0; stage < W3dMaterialClass::MAX_STAGES; stage++) { Set_Mapper_Args(that.MapperArgs[stage], stage); } } return *this; } bool W3dMaterialDescClass::VertMatClass::operator != (const VertMatClass & that) { return !(*this == that); } bool W3dMaterialDescClass::VertMatClass::operator == (const VertMatClass & that) { assert(0); return false; } void W3dMaterialDescClass::VertMatClass::Set_Name(const char * name) { if (Name) free(Name); if (name) { Name = strdup(name); } else { Name = NULL; } } void W3dMaterialDescClass::VertMatClass::Set_Mapper_Args(const char * args, int stage) { if (MapperArgs[stage]) { delete [] (MapperArgs[stage]); MapperArgs[stage] = NULL; } if (args) { int len = strlen(args); MapperArgs[stage] = new char [len + 1]; strcpy(MapperArgs[stage], args); } else { MapperArgs[stage] = NULL; } } /* Implementation of W3dMaterialDescClass */ W3dMaterialDescClass::MaterialRemapClass::MaterialRemapClass(void) { PassCount = -1; for (int pass=0; pass= 0); assert(vmat_index < VertexMaterials.Count()); return &(VertexMaterials[vmat_index].Material); } const char * W3dMaterialDescClass::Get_Mapper_Args(int vmat_index, int stage) { assert(vmat_index >= 0); assert(vmat_index < VertexMaterials.Count()); assert(stage >= 0); assert(stage < W3dMaterialClass::MAX_STAGES); return VertexMaterials[vmat_index].MapperArgs[stage]; } W3dShaderStruct * W3dMaterialDescClass::Get_Shader(int shader_index) { assert(shader_index >= 0); assert(shader_index < Shaders.Count()); return &(Shaders[shader_index].Shader); } W3dMapClass * W3dMaterialDescClass::Get_Texture(int texture_index) { assert(texture_index >= 0); assert(texture_index < Textures.Count()); return &(Textures[texture_index].Map); } int W3dMaterialDescClass::Get_Vertex_Material_Index(int mat_index,int pass) { assert(mat_index >= 0); assert(mat_index < MaterialRemaps.Count()); assert(pass >= 0); assert(pass < PassCount); return MaterialRemaps[mat_index].VertexMaterialIdx[pass]; } int W3dMaterialDescClass::Get_Shader_Index(int mat_index,int pass) { assert(mat_index >= 0); assert(mat_index < MaterialRemaps.Count()); assert(pass >= 0); assert(pass < PassCount); return MaterialRemaps[mat_index].ShaderIdx[pass]; } int W3dMaterialDescClass::Get_Texture_Index(int mat_index,int pass,int stage) { assert(mat_index >= 0); assert(mat_index < MaterialRemaps.Count()); assert(pass >= 0); assert(pass < PassCount); assert(stage >= 0); assert(stage < W3dMaterialClass::MAX_STAGES); return MaterialRemaps[mat_index].TextureIdx[pass][stage]; } W3dVertexMaterialStruct * W3dMaterialDescClass::Get_Vertex_Material(int mat_index,int pass) { int index = Get_Vertex_Material_Index(mat_index,pass); if (index == -1) { return NULL; } else { return Get_Vertex_Material(index); } } const char * W3dMaterialDescClass::Get_Mapper_Args(int mat_index,int pass,int stage) { int index = Get_Vertex_Material_Index(mat_index,pass); if (index == -1) { return NULL; } else { return Get_Mapper_Args(index,stage); } } W3dShaderStruct * W3dMaterialDescClass::Get_Shader(int mat_index,int pass) { int index = Get_Shader_Index(mat_index,pass); if (index == -1) { return NULL; } else { return Get_Shader(index); } } W3dMapClass * W3dMaterialDescClass::Get_Texture(int mat_index,int pass,int stage) { int index = Get_Texture_Index(mat_index,pass,stage); if (index == -1) { return NULL; } else { return Get_Texture(index); } } int W3dMaterialDescClass::Get_Map_Channel(int mat_index,int pass,int stage) { return MaterialRemaps[mat_index].MapChannel[pass][stage]; } const char * W3dMaterialDescClass::Get_Vertex_Material_Name(int mat_index,int pass) { int index = Get_Vertex_Material_Index(mat_index,pass); if (index == -1) { return NULL; } else { return VertexMaterials[index].Name; } } const char * W3dMaterialDescClass::Get_Vertex_Material_Name(int vmat_index) { return VertexMaterials[vmat_index].Name; } bool W3dMaterialDescClass::Stage_Needs_Texture_Coordinates(int pass,int stage) { for (int mi=0; miFilename == NULL)) { return -1; } int crc = Compute_Crc(*map); for (int ti=0; tiAttributes,sizeof(map.AnimInfo->Attributes),crc); crc = CRC_Memory((const unsigned char *)&map.AnimInfo->AnimType,sizeof(map.AnimInfo->AnimType),crc); crc = CRC_Memory((const unsigned char *)&map.AnimInfo->FrameCount,sizeof(map.AnimInfo->FrameCount),crc); crc = CRC_Memory((const unsigned char *)&map.AnimInfo->FrameRate,sizeof(map.AnimInfo->FrameRate),crc); } crc = CRC_Stringi(map.Filename, crc); return crc; } unsigned long W3dMaterialDescClass::Add_String_To_Crc(const char *str, unsigned long in_crc) { unsigned long out_crc = in_crc; if (str) { int len = strlen(str); char *temp = new char[len + 1]; const char *p_in = str; // skip leading spaces, tabs, newlines for (; *p_in == ' ' || *p_in == '\t' || *p_in == '\r' || *p_in == '\n'; p_in++); // copy string, skipping spaces and tabs char * p_out = temp; int count = 0; for (; *p_in; p_in++) { for (; *p_in == ' ' || *p_in == '\t'; p_in++); if (!(*p_in)) break; *p_out = *p_in; p_out++; count++; } *p_out = 0; // Erase any trailing newlines: if (count) { // p_out now points to the ending null - make it point to the // character before it (the last character of the string proper) p_out--; for (; *p_out == '\r' || *p_out == '\n'; p_out--) { *p_out = '\000'; count--; } } out_crc = CRC_Memory((const unsigned char *)temp,count,in_crc); delete [] temp; } return out_crc; }