/* ** 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 . */ /* $Header: /Commando/Code/Tools/max2w3d/GameMtl.cpp 52 8/10/01 2:18p Ian_l $ */ /*********************************************************************************************** *** Confidential - Westwood Studios *** *********************************************************************************************** * * * Project Name : Commando / G 3D engine * * * * File Name : GAMEMTL.CPP * * * * Programmer : Greg Hjelstrom * * * * Start Date : 06/26/97 * * * * Last Update : 10/26/1999997 [GH] * * * *---------------------------------------------------------------------------------------------* * Functions: * * GameMtl::GameMtl -- constructor * * GameMtl::~GameMtl -- destructor * * GameMtl::ClassID -- returns the max ClassID of the material plugin * * GameMtl::SuperClassID -- returns the super class ID * * GameMtl::GetClassName -- returns the name of this plugin clas * * GameMtl::NumSubs -- returns the number of sub animations * * GameMtl::SubAnimName -- returns the name of the i'th sub animation * * GameMtl::SubAnim -- returns the i'th sub-anim * * GameMtl::Clone -- clones this material * * GameMtl::NotifyRefChanged -- NotifyRefChanged handler * * GameMtl::SetReference -- set the i'th reference * * GameMtl::GetReference -- returnst the i'th reference * * GameMtl::NumSubTexmaps -- returns the number of texture maps in this material * * GameMtl::SetSubTexmap -- set the i'th texture map * * GameMtl::GetSubTexmap -- returns the i'th texture map * * GameMtl::CreateParamDlg -- creates the material editor dialog box * * GameMtl::Notify_Changed -- someone has changed this material * * GameMtl::Reset -- reset this material to default settings * * GameMtl::Update -- time has changed * * GameMtl::Validity -- return the validity of the material at time t * * GameMtl::Requirements -- what requirements does this material have? * * GameMtl::Load -- loading from a MAX file * * GameMtl::Save -- Saving into a MAX file * * GameMtl::Shade -- evaluate the material for the renderer. * * GameMtl::ps2_shade -- Emulate the PS2 shader. * * GameMtl::Compute_PC_Shader_From_PS2_Shader -- Determine if a PC shader can be created. * * GameMtl::Compute_PS2_Shader_From_PC_Shader -- Change a W3D material to a PS2 W3D material.* * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ #include "gamemtl.h" #include #include #include #include "GameMtlDlg.h" #include "dllmain.h" #include "resource.h" #include "util.h" #include "meshsave.h" #include "gamemaps.h" /***************************************************************** * * GameMtl Class Descriptor * *****************************************************************/ Class_ID GameMaterialClassID(GAMEMTL_ID_PARTA, GAMEMTL_ID_PARTB); class GameMaterialClassDesc:public ClassDesc { public: int IsPublic() { return 1; } void * Create(BOOL loading) { return new GameMtl(loading); } const TCHAR * ClassName() { return Get_String(IDS_GAMEMTL); } SClass_ID SuperClassID() { return MATERIAL_CLASS_ID; } Class_ID ClassID() { return GameMaterialClassID; } const TCHAR* Category() { return _T(""); } }; static GameMaterialClassDesc _GameMaterialCD; ClassDesc * Get_Game_Material_Desc() { return &_GameMaterialCD; } /****************************************************************************** * * PostLoadCallback for GameMtl * ******************************************************************************/ class GameMtlPostLoad : public PostLoadCallback { public: GameMtl *m; GameMtlPostLoad(GameMtl *b) { m=b; IsOld = false;} void proc(ILoad *iload); /* ** Data from the previous version of GameMtl */ bool IsOld; ULONG Attributes; Color Diffuse; Color Specular; Color AmbientCoeff; Color DiffuseCoeff; Color SpecularCoeff; Color EmissiveCoeff; float FogCoeff; int DCTFrames; int DITFrames; int SCTFrames; int SITFrames; float DCTFrameRate; float DITFrameRate; float SCTFrameRate; float SITFrameRate; int DCTMappingType; int DITMappingType; int SCTMappingType; int SITMappingType; float Opacity; float Translucency; float Shininess; }; /****************************************************************************** * * GameMtl * * Notes: * Prior to Nov, 1998 I was storing everything about the material in custom * chunks. As part of the upgrade to surrender 1.4x, I'm going to use * a parameter block for each pass (combination of shader and vertex material) * ******************************************************************************/ #define MTL_HDR_CHUNK 0x4000 /* ** Custom Chunk IDs */ #define GAMEMTL_FLAGS_CHUNK 0x0000 #define GAMEMTL_GAMEFLAGS_CHUNK 0x0001 // OBSOLETE! #define GAMEMTL_COLORS_CHUNK 0x0002 // OBSOLETE! #define GAMEMTL_TEXTURE_FRAMES_CHUNK 0x0003 #define GAMEMTL_ENVMAP_FRAMES_CHUNK 0x0004 #define GAMEMTL_DCT_FRAMES_CHUNK GAMEMTL_TEXTURE_FRAMES_CHUNK #define GAMEMTL_DIT_FRAMES_CHUNK GAMEMTL_ENVMAP_FRAMES_CHUNK #define GAMEMTL_SCT_FRAMES_CHUNK 0x0005 #define GAMEMTL_SIT_FRAMES_CHUNK 0x0006 #define GAMEMTL_DCT_FRAME_RATE_CHUNK 0x0010 #define GAMEMTL_DIT_FRAME_RATE_CHUNK 0x0011 #define GAMEMTL_SCT_FRAME_RATE_CHUNK 0x0012 #define GAMEMTL_SIT_FRAME_RATE_CHUNK 0x0013 #define GAMEMTL_DCT_MAPPING_CHUNK 0x0020 #define GAMEMTL_DIT_MAPPING_CHUNK 0x0021 #define GAMEMTL_SCT_MAPPING_CHUNK 0x0022 #define GAMEMTL_SIT_MAPPING_CHUNK 0x0023 #define GAMEMTL_ATTRIBUTES_CHUNK 0x0030 #define GAMEMTL_DIFFUSE_COLOR_CHUNK 0x0031 #define GAMEMTL_SPECULAR_COLOR_CHUNK 0x0032 #define GAMEMTL_AMBIENT_COEFF_CHUNK 0x0040 #define GAMEMTL_DIFFUSE_COEFF_CHUNK 0x0041 #define GAMEMTL_SPECULAR_COEFF_CHUNK 0x0042 #define GAMEMTL_EMISSIVE_COEFF_CHUNK 0x0043 #define GAMEMTL_OPACITY_CHUNK 0x0050 #define GAMEMTL_TRANSLUCENCY_CHUNK 0x0051 #define GAMEMTL_SHININESS_CHUNK 0x0052 #define GAMEMTL_FOG_CHUNK 0x0053 #define GAMEMTL_PASS0_CUR_PAGE 0x0060 #define GAMEMTL_PASS1_CUR_PAGE 0x0061 #define GAMEMTL_PASS2_CUR_PAGE 0x0062 #define GAMEMTL_PASS3_CUR_PAGE 0x0064 #define GAMEMTL_PASS0_STAGE0_MAPPER_ARGS 0x0070 #define GAMEMTL_PASS1_STAGE0_MAPPER_ARGS 0x0071 #define GAMEMTL_PASS2_STAGE0_MAPPER_ARGS 0x0072 #define GAMEMTL_PASS3_STAGE0_MAPPER_ARGS 0x0073 #define GAMEMTL_SURFACE_TYPE_CHUNK 0x0080 #define GAMEMTL_SORT_LEVEL_CHUNK 0x0090 #define GAMEMTL_PASS0_STAGE1_MAPPER_ARGS 0x0100 #define GAMEMTL_PASS1_STAGE1_MAPPER_ARGS 0x0101 #define GAMEMTL_PASS2_STAGE1_MAPPER_ARGS 0x0102 #define GAMEMTL_PASS3_STAGE1_MAPPER_ARGS 0x0103 /* ** Main Parameter Block Definition */ static ParamBlockDescID MainParameterBlockDesc[] = { { TYPE_INT, NULL, FALSE, 0 }, // Pass Count }; /* ** ID numbers for parameter block entries. As of version 4 of the ** parameter block definitions, these enums should be used directly ** in the pblock defs to avoid accidental ID mismatches. ** ** Note: You should DO NOTHING TO CHANGE THE VALUES OF THE ENUM ** (except adding at the end of course). Following these constraints ** will preserve backwards compatibility with all pblock versions. ** ** Since this enum is now just a series of ID numbers, we must ** manually keep the PASS_PARAMBLOCK_LENGTH up to date. Believe it ** or not, but this is less error-prone than the previous way of ** doing things. ** ** (gth) Aug 6, 2000 ** IMPORTANT -PLEASE READ- ** The following enums are basically the index into the array of ** ParamBlockDescID's that we are using. It is critical that this ** enumeration does not skip indexes and that the value for each ** symbol in this list matches the position in the param block ** for that variable. This enumeration is does not define the ** id for the new variable, only its position in the array. ** ** When you add a new variable to the parameter block, you should ** find an id for it higher than any existing id (look through the ** rest of the entries in the parameter block). That id will not ** usually be able to be the same as its array index due to the ** evolution of this structure. The id I'm referring to is the ** number in the 4th element of each of the ParamBlockDescIDs. ** ** If you remove an entry from our array of ParamBlockDescIDs you ** will need to update all of the PB_xxx enumeration below so that ** they match their position in the array again. */ enum { PB_AMBIENT = 0, PB_DIFFUSE = 1, PB_SPECULAR = 2, PB_EMISSIVE = 3, PB_SHININESS = 4, PB_OPACITY = 5, PB_TRANSLUCENCY = 6, PB_COPY_SPECULAR_TO_DIFFUSE = 7, PB_STAGE0_MAPPING_TYPE = 8, PB_PSX_TRANSLUCENCY = 9, PB_PSX_LIGHTING = 10, PB_DEPTH_COMPARE = 11, PB_DEPTH_MASK = 12, PB_COLOR_MASK = 13, // obsolete (ignored) PB_DEST_BLEND = 14, PB_FOG_FUNC = 15, // obsolete (ignored) PB_PRI_GRADIENT = 16, PB_SEC_GRADIENT = 17, PB_SRC_BLEND = 18, PB_DETAIL_COLOR_FUNC = 19, PB_DETAIL_ALPHA_FUNC = 20, PB_STAGE0_TEXTURE_ENABLE = 21, PB_STAGE0_TEXTURE_PUBLISH = 22, PB_STAGE0_TEXTURE_RESIZE = 23, // obsolete (ignored) PB_STAGE0_TEXTURE_NO_MIPMAP = 24, // obsolete (ignored) PB_STAGE0_TEXTURE_CLAMP_U = 25, PB_STAGE0_TEXTURE_CLAMP_V = 26, PB_STAGE0_TEXTURE_HINT = 27, PB_STAGE0_TEXTURE_DISPLAY = 28, PB_STAGE0_TEXTURE_FRAME_RATE = 29, PB_STAGE0_TEXTURE_FRAME_COUNT = 30, PB_STAGE0_TEXTURE_ANIM_TYPE = 31, PB_STAGE1_TEXTURE_ENABLE = 32, PB_STAGE1_TEXTURE_PUBLISH = 33, PB_STAGE1_TEXTURE_RESIZE = 34, // obsolete (ignored) PB_STAGE1_TEXTURE_NO_MIPMAP = 35, // obsolete (ignored) PB_STAGE1_TEXTURE_CLAMP_U = 36, PB_STAGE1_TEXTURE_CLAMP_V = 37, PB_STAGE1_TEXTURE_HINT = 38, PB_STAGE1_TEXTURE_DISPLAY = 39, PB_STAGE1_TEXTURE_FRAME_RATE = 40, PB_STAGE1_TEXTURE_FRAME_COUNT = 41, PB_STAGE1_TEXTURE_ANIM_TYPE = 42, PB_STAGE0_TEXTURE_ALPHA_BITMAP = 43, PB_STAGE1_TEXTURE_ALPHA_BITMAP = 44, PB_ALPHA_TEST = 45, PB_SHADER_PRESET = 46, // obsolete (ignored) // For the Playstation 2. PB_PS2_SHADER_PARAM_A = 47, PB_PS2_SHADER_PARAM_B = 48, PB_PS2_SHADER_PARAM_C = 49, PB_PS2_SHADER_PARAM_D = 50, // UV Channel selection PB_STAGE0_MAP_CHANNEL = 51, PB_STAGE1_MAP_CHANNEL = 52, PB_STAGE1_MAPPING_TYPE = 53, // (gth) this can't be 55, it is used as an array index // = 55, // yes, 55 // textures can now disable LOD PB_STAGE0_TEXTURE_NO_LOD = 54, PB_STAGE1_TEXTURE_NO_LOD = 55, }; /* ** Per-Pass Parameter Block Definition */ // Version 0 (old version) static ParamBlockDescID PassParameterBlockDescVer0[] = { { TYPE_POINT3, NULL, TRUE, 0 }, // Ambient { TYPE_POINT3, NULL, TRUE, 1 }, // Diffuse { TYPE_POINT3, NULL, TRUE, 2 }, // Specular { TYPE_POINT3, NULL, TRUE, 3 }, // Emissive { TYPE_FLOAT, NULL, TRUE, 4 }, // Shininess { TYPE_FLOAT, NULL, TRUE, 5 }, // Opacity { TYPE_FLOAT, NULL, TRUE, 6 }, // Translucency { TYPE_INT, NULL, FALSE, 7 }, // Mapping Type { TYPE_INT, NULL, FALSE, 8 }, // PSX Translucency Type { TYPE_BOOL, NULL, FALSE, 9 }, // PSX Lighting Flag { TYPE_INT, NULL, FALSE, 10}, // Depth Compare { TYPE_INT, NULL, FALSE, 11}, // Depth Mask { TYPE_INT, NULL, FALSE, 12}, // Color Mask { TYPE_INT, NULL, FALSE, 13}, // Dest Blend { TYPE_INT, NULL, FALSE, 14}, // FogFunc { TYPE_INT, NULL, FALSE, 15}, // PriGradient { TYPE_INT, NULL, FALSE, 16}, // SecGradient { TYPE_INT, NULL, FALSE, 17}, // SrcBlend { TYPE_INT, NULL, FALSE, 18}, // DetailColorFunc { TYPE_INT, NULL, FALSE, 19}, // DetailAlphaFunc { TYPE_INT, NULL, FALSE, 20}, // DitherMask { TYPE_INT, NULL, FALSE, 21}, // Shade Model { TYPE_BOOL, NULL, FALSE, 22}, // Stage0 Texture Enable { TYPE_BOOL, NULL, FALSE, 23}, // Stage0 Texture Publish { TYPE_BOOL, NULL, FALSE, 24}, // Stage0 Texture Display (in viewport...) { TYPE_FLOAT, NULL, FALSE, 25}, // Stage0 Frame Rate { TYPE_INT, NULL, FALSE, 26}, // Stage0 Frame Count { TYPE_INT, NULL, FALSE, 27}, // Stage0 Animation Type { TYPE_BOOL, NULL, FALSE, 28}, // Stage1 Texture Enable { TYPE_BOOL, NULL, FALSE, 29}, // Stage1 Texture Publish { TYPE_BOOL, NULL, FALSE, 30}, // Stage1 Texture Display (in viewport...) { TYPE_FLOAT, NULL, FALSE, 31}, // Stage1 Frame Rate { TYPE_INT, NULL, FALSE, 32}, // Stage1 Frame Count { TYPE_INT, NULL, FALSE, 33}, // Stage1 Animation Type }; // Version 1 static ParamBlockDescID PassParameterBlockDescVer1[] = { { TYPE_POINT3, NULL, TRUE, 0 }, // Ambient { TYPE_POINT3, NULL, TRUE, 1 }, // Diffuse { TYPE_POINT3, NULL, TRUE, 2 }, // Specular { TYPE_POINT3, NULL, TRUE, 3 }, // Emissive { TYPE_FLOAT, NULL, TRUE, 4 }, // Shininess { TYPE_FLOAT, NULL, TRUE, 5 }, // Opacity { TYPE_FLOAT, NULL, TRUE, 6 }, // Translucency { TYPE_BOOL, NULL, FALSE, 34}, // Copy specular to diffuse (new to version 1) { TYPE_INT, NULL, FALSE, 7 }, // Mapping Type { TYPE_INT, NULL, FALSE, 8 }, // PSX Translucency Type { TYPE_BOOL, NULL, FALSE, 9 }, // PSX Lighting Flag { TYPE_INT, NULL, FALSE, 10}, // Depth Compare { TYPE_INT, NULL, FALSE, 11}, // Depth Mask { TYPE_INT, NULL, FALSE, 12}, // Color Mask (now obsolete and ignored) { TYPE_INT, NULL, FALSE, 13}, // Dest Blend { TYPE_INT, NULL, FALSE, 14}, // FogFunc (now obsolete and ignored) { TYPE_INT, NULL, FALSE, 15}, // PriGradient { TYPE_INT, NULL, FALSE, 16}, // SecGradient { TYPE_INT, NULL, FALSE, 17}, // SrcBlend { TYPE_INT, NULL, FALSE, 18}, // DetailColorFunc { TYPE_INT, NULL, FALSE, 19}, // DetailAlphaFunc { TYPE_BOOL, NULL, FALSE, 22}, // Stage0 Texture Enable { TYPE_BOOL, NULL, FALSE, 23}, // Stage0 Texture Publish { TYPE_BOOL, NULL, FALSE, 35}, // Stage0 Texture Resize (new to version 1) { TYPE_BOOL, NULL, FALSE, 36}, // Stage0 Texture No Mipmap (new to version 1) { TYPE_BOOL, NULL, FALSE, 37}, // Stage0 Texture Clamp U (new to version 1) { TYPE_BOOL, NULL, FALSE, 38}, // Stage0 Texture Clamp V (new to version 1) { TYPE_INT, NULL, FALSE, 39}, // Stage0 Texture Hint (new to version 1) { TYPE_BOOL, NULL, FALSE, 24}, // Stage0 Texture Display (in viewport...) { TYPE_FLOAT, NULL, FALSE, 25}, // Stage0 Frame Rate { TYPE_INT, NULL, FALSE, 26}, // Stage0 Frame Count { TYPE_INT, NULL, FALSE, 27}, // Stage0 Animation Type { TYPE_BOOL, NULL, FALSE, 28}, // Stage1 Texture Enable { TYPE_BOOL, NULL, FALSE, 29}, // Stage1 Texture Publish { TYPE_BOOL, NULL, FALSE, 40}, // Stage1 Texture Resize (new to version 1) { TYPE_BOOL, NULL, FALSE, 41}, // Stage1 Texture No Mipmap (new to version 1) { TYPE_BOOL, NULL, FALSE, 42}, // Stage1 Texture Clamp U (new to version 1) { TYPE_BOOL, NULL, FALSE, 43}, // Stage1 Texture Clamp V (new to version 1) { TYPE_INT, NULL, FALSE, 44}, // Stage1 Texture Hint (new to version 1) { TYPE_BOOL, NULL, FALSE, 30}, // Stage1 Texture Display (in viewport...) { TYPE_FLOAT, NULL, FALSE, 31}, // Stage1 Frame Rate { TYPE_INT, NULL, FALSE, 32}, // Stage1 Frame Count { TYPE_INT, NULL, FALSE, 33}, // Stage1 Animation Type { TYPE_BOOL, NULL, FALSE, 45}, // Stage0 Texture Alpha Bitmap (new to version 1) { TYPE_BOOL, NULL, FALSE, 46}, // Stage1 Texture Alpha Bitmap (new to version 1) { TYPE_BOOL, NULL, FALSE, 47}, // Alpha Test (new to version 1) { TYPE_INT, NULL, FALSE, 48}, // Shader preset (new to version 1) (now obsolete and ignored) }; // Version 2 (old version) static ParamBlockDescID PassParameterBlockDescVer2[] = { { TYPE_POINT3, NULL, TRUE, 0 }, // Ambient { TYPE_POINT3, NULL, TRUE, 1 }, // Diffuse { TYPE_POINT3, NULL, TRUE, 2 }, // Specular { TYPE_POINT3, NULL, TRUE, 3 }, // Emissive { TYPE_FLOAT, NULL, TRUE, 4 }, // Shininess { TYPE_FLOAT, NULL, TRUE, 5 }, // Opacity { TYPE_FLOAT, NULL, TRUE, 6 }, // Translucency { TYPE_BOOL, NULL, FALSE, 34}, // Copy specular to diffuse (new to version 1) { TYPE_INT, NULL, FALSE, 7 }, // Mapping Type { TYPE_INT, NULL, FALSE, 8 }, // PSX Translucency Type { TYPE_BOOL, NULL, FALSE, 9 }, // PSX Lighting Flag { TYPE_INT, NULL, FALSE, 10}, // Depth Compare { TYPE_INT, NULL, FALSE, 11}, // Depth Mask { TYPE_INT, NULL, FALSE, 12}, // Color Mask (now obsolete and ignored) { TYPE_INT, NULL, FALSE, 13}, // Dest Blend { TYPE_INT, NULL, FALSE, 14}, // FogFunc (now obsolete and ignored) { TYPE_INT, NULL, FALSE, 15}, // PriGradient { TYPE_INT, NULL, FALSE, 16}, // SecGradient { TYPE_INT, NULL, FALSE, 17}, // SrcBlend { TYPE_INT, NULL, FALSE, 18}, // DetailColorFunc { TYPE_INT, NULL, FALSE, 19}, // DetailAlphaFunc { TYPE_BOOL, NULL, FALSE, 22}, // Stage0 Texture Enable { TYPE_BOOL, NULL, FALSE, 23}, // Stage0 Texture Publish { TYPE_BOOL, NULL, FALSE, 35}, // Stage0 Texture Resize (new to version 1) { TYPE_BOOL, NULL, FALSE, 36}, // Stage0 Texture No Mipmap (new to version 1) { TYPE_BOOL, NULL, FALSE, 37}, // Stage0 Texture Clamp U (new to version 1) { TYPE_BOOL, NULL, FALSE, 38}, // Stage0 Texture Clamp V (new to version 1) { TYPE_INT, NULL, FALSE, 39}, // Stage0 Texture Hint (new to version 1) { TYPE_BOOL, NULL, FALSE, 24}, // Stage0 Texture Display (in viewport...) { TYPE_FLOAT, NULL, FALSE, 25}, // Stage0 Frame Rate { TYPE_INT, NULL, FALSE, 26}, // Stage0 Frame Count { TYPE_INT, NULL, FALSE, 27}, // Stage0 Animation Type { TYPE_BOOL, NULL, FALSE, 28}, // Stage1 Texture Enable { TYPE_BOOL, NULL, FALSE, 29}, // Stage1 Texture Publish { TYPE_BOOL, NULL, FALSE, 40}, // Stage1 Texture Resize (new to version 1) { TYPE_BOOL, NULL, FALSE, 41}, // Stage1 Texture No Mipmap (new to version 1) { TYPE_BOOL, NULL, FALSE, 42}, // Stage1 Texture Clamp U (new to version 1) { TYPE_BOOL, NULL, FALSE, 43}, // Stage1 Texture Clamp V (new to version 1) { TYPE_INT, NULL, FALSE, 44}, // Stage1 Texture Hint (new to version 1) { TYPE_BOOL, NULL, FALSE, 30}, // Stage1 Texture Display (in viewport...) { TYPE_FLOAT, NULL, FALSE, 31}, // Stage1 Frame Rate { TYPE_INT, NULL, FALSE, 32}, // Stage1 Frame Count { TYPE_INT, NULL, FALSE, 33}, // Stage1 Animation Type { TYPE_BOOL, NULL, FALSE, 45}, // Stage0 Texture Alpha Bitmap (new to version 1) { TYPE_BOOL, NULL, FALSE, 46}, // Stage1 Texture Alpha Bitmap (new to version 1) { TYPE_BOOL, NULL, FALSE, 47}, // Alpha Test (new to version 1) { TYPE_INT, NULL, FALSE, 48}, // Shader preset (new to version 1) (now obsolete and ignored) { TYPE_INT, NULL, FALSE, 49}, // PS2 Shader Param A { TYPE_INT, NULL, FALSE, 50}, // PS2 Shader Param B { TYPE_INT, NULL, FALSE, 51}, // PS2 Shader Param C { TYPE_INT, NULL, FALSE, 52}, // PS2 Shader Param D }; // Version 3 (old version) static ParamBlockDescID PassParameterBlockDescVer3[] = { { TYPE_POINT3, NULL, TRUE, 0 }, // Ambient { TYPE_POINT3, NULL, TRUE, 1 }, // Diffuse { TYPE_POINT3, NULL, TRUE, 2 }, // Specular { TYPE_POINT3, NULL, TRUE, 3 }, // Emissive { TYPE_FLOAT, NULL, TRUE, 4 }, // Shininess { TYPE_FLOAT, NULL, TRUE, 5 }, // Opacity { TYPE_FLOAT, NULL, TRUE, 6 }, // Translucency { TYPE_BOOL, NULL, FALSE, 34}, // Copy specular to diffuse (new to version 1) { TYPE_INT, NULL, FALSE, 7 }, // Mapping Type { TYPE_INT, NULL, FALSE, 8 }, // PSX Translucency Type { TYPE_BOOL, NULL, FALSE, 9 }, // PSX Lighting Flag { TYPE_INT, NULL, FALSE, 10}, // Depth Compare { TYPE_INT, NULL, FALSE, 11}, // Depth Mask { TYPE_INT, NULL, FALSE, 12}, // Color Mask (now obsolete and ignored) { TYPE_INT, NULL, FALSE, 13}, // Dest Blend { TYPE_INT, NULL, FALSE, 14}, // FogFunc (now obsolete and ignored) { TYPE_INT, NULL, FALSE, 15}, // PriGradient { TYPE_INT, NULL, FALSE, 16}, // SecGradient { TYPE_INT, NULL, FALSE, 17}, // SrcBlend { TYPE_INT, NULL, FALSE, 18}, // DetailColorFunc { TYPE_INT, NULL, FALSE, 19}, // DetailAlphaFunc { TYPE_BOOL, NULL, FALSE, 22}, // Stage0 Texture Enable { TYPE_BOOL, NULL, FALSE, 23}, // Stage0 Texture Publish { TYPE_BOOL, NULL, FALSE, 35}, // Stage0 Texture Resize (new to version 1) { TYPE_BOOL, NULL, FALSE, 36}, // Stage0 Texture No Mipmap (new to version 1) { TYPE_BOOL, NULL, FALSE, 37}, // Stage0 Texture Clamp U (new to version 1) { TYPE_BOOL, NULL, FALSE, 38}, // Stage0 Texture Clamp V (new to version 1) { TYPE_INT, NULL, FALSE, 39}, // Stage0 Texture Hint (new to version 1) { TYPE_BOOL, NULL, FALSE, 24}, // Stage0 Texture Display (in viewport...) { TYPE_FLOAT, NULL, FALSE, 25}, // Stage0 Frame Rate { TYPE_INT, NULL, FALSE, 26}, // Stage0 Frame Count { TYPE_INT, NULL, FALSE, 27}, // Stage0 Animation Type { TYPE_BOOL, NULL, FALSE, 28}, // Stage1 Texture Enable { TYPE_BOOL, NULL, FALSE, 29}, // Stage1 Texture Publish { TYPE_BOOL, NULL, FALSE, 40}, // Stage1 Texture Resize (new to version 1) { TYPE_BOOL, NULL, FALSE, 41}, // Stage1 Texture No Mipmap (new to version 1) { TYPE_BOOL, NULL, FALSE, 42}, // Stage1 Texture Clamp U (new to version 1) { TYPE_BOOL, NULL, FALSE, 43}, // Stage1 Texture Clamp V (new to version 1) { TYPE_INT, NULL, FALSE, 44}, // Stage1 Texture Hint (new to version 1) { TYPE_BOOL, NULL, FALSE, 30}, // Stage1 Texture Display (in viewport...) { TYPE_FLOAT, NULL, FALSE, 31}, // Stage1 Frame Rate { TYPE_INT, NULL, FALSE, 32}, // Stage1 Frame Count { TYPE_INT, NULL, FALSE, 33}, // Stage1 Animation Type { TYPE_BOOL, NULL, FALSE, 45}, // Stage0 Texture Alpha Bitmap (new to version 1) { TYPE_BOOL, NULL, FALSE, 46}, // Stage1 Texture Alpha Bitmap (new to version 1) { TYPE_BOOL, NULL, FALSE, 47}, // Alpha Test (new to version 1) { TYPE_INT, NULL, FALSE, 48}, // Shader preset (new to version 1) (now obsolete and ignored) { TYPE_INT, NULL, FALSE, 49}, // PS2 Shader Param A { TYPE_INT, NULL, FALSE, 50}, // PS2 Shader Param B { TYPE_INT, NULL, FALSE, 51}, // PS2 Shader Param C { TYPE_INT, NULL, FALSE, 52}, // PS2 Shader Param D { TYPE_INT, NULL, FALSE, 53}, // Stage0 UV Channel { TYPE_INT, NULL, FALSE, 54}, // Stage1 UV Channel }; // Version 4 (old version) static ParamBlockDescID PassParameterBlockDescVer4[] = { { TYPE_POINT3, NULL, TRUE, 0 }, // Ambient { TYPE_POINT3, NULL, TRUE, 1 }, // Diffuse { TYPE_POINT3, NULL, TRUE, 2 }, // Specular { TYPE_POINT3, NULL, TRUE, 3 }, // Emissive { TYPE_FLOAT, NULL, TRUE, 4 }, // Shininess { TYPE_FLOAT, NULL, TRUE, 5 }, // Opacity { TYPE_FLOAT, NULL, TRUE, 6 }, // Translucency { TYPE_BOOL, NULL, FALSE, 34}, // Copy specular to diffuse (new to version 1) { TYPE_INT, NULL, FALSE, 7 }, // Stage0 Mapping Type { TYPE_INT, NULL, FALSE, 8 }, // PSX Translucency Type { TYPE_BOOL, NULL, FALSE, 9 }, // PSX Lighting Flag { TYPE_INT, NULL, FALSE, 10}, // Depth Compare { TYPE_INT, NULL, FALSE, 11}, // Depth Mask { TYPE_INT, NULL, FALSE, 12}, // Color Mask (now obsolete and ignored) { TYPE_INT, NULL, FALSE, 13}, // Dest Blend { TYPE_INT, NULL, FALSE, 14}, // FogFunc (now obsolete and ignored) { TYPE_INT, NULL, FALSE, 15}, // PriGradient { TYPE_INT, NULL, FALSE, 16}, // SecGradient { TYPE_INT, NULL, FALSE, 17}, // SrcBlend { TYPE_INT, NULL, FALSE, 18}, // DetailColorFunc { TYPE_INT, NULL, FALSE, 19}, // DetailAlphaFunc { TYPE_BOOL, NULL, FALSE, 22}, // Stage0 Texture Enable { TYPE_BOOL, NULL, FALSE, 23}, // Stage0 Texture Publish { TYPE_BOOL, NULL, FALSE, 35}, // Stage0 Texture Resize (new to version 1) { TYPE_BOOL, NULL, FALSE, 36}, // Stage0 Texture No Mipmap (new to version 1) { TYPE_BOOL, NULL, FALSE, 37}, // Stage0 Texture Clamp U (new to version 1) { TYPE_BOOL, NULL, FALSE, 38}, // Stage0 Texture Clamp V (new to version 1) { TYPE_INT, NULL, FALSE, 39}, // Stage0 Texture Hint (new to version 1) { TYPE_BOOL, NULL, FALSE, 24}, // Stage0 Texture Display (in viewport...) { TYPE_FLOAT, NULL, FALSE, 25}, // Stage0 Frame Rate { TYPE_INT, NULL, FALSE, 26}, // Stage0 Frame Count { TYPE_INT, NULL, FALSE, 27}, // Stage0 Animation Type { TYPE_BOOL, NULL, FALSE, 28}, // Stage1 Texture Enable { TYPE_BOOL, NULL, FALSE, 29}, // Stage1 Texture Publish { TYPE_BOOL, NULL, FALSE, 40}, // Stage1 Texture Resize (new to version 1) { TYPE_BOOL, NULL, FALSE, 41}, // Stage1 Texture No Mipmap (new to version 1) { TYPE_BOOL, NULL, FALSE, 42}, // Stage1 Texture Clamp U (new to version 1) { TYPE_BOOL, NULL, FALSE, 43}, // Stage1 Texture Clamp V (new to version 1) { TYPE_INT, NULL, FALSE, 44}, // Stage1 Texture Hint (new to version 1) { TYPE_BOOL, NULL, FALSE, 30}, // Stage1 Texture Display (in viewport...) { TYPE_FLOAT, NULL, FALSE, 31}, // Stage1 Frame Rate { TYPE_INT, NULL, FALSE, 32}, // Stage1 Frame Count { TYPE_INT, NULL, FALSE, 33}, // Stage1 Animation Type { TYPE_BOOL, NULL, FALSE, 45}, // Stage0 Texture Alpha Bitmap (new to version 1) { TYPE_BOOL, NULL, FALSE, 46}, // Stage1 Texture Alpha Bitmap (new to version 1) { TYPE_BOOL, NULL, FALSE, 47}, // Alpha Test (new to version 1) { TYPE_INT, NULL, FALSE, 48}, // Shader preset (new to version 1) (now obsolete and ignored) { TYPE_INT, NULL, FALSE, 49}, // PS2 Shader Param A { TYPE_INT, NULL, FALSE, 50}, // PS2 Shader Param B { TYPE_INT, NULL, FALSE, 51}, // PS2 Shader Param C { TYPE_INT, NULL, FALSE, 52}, // PS2 Shader Param D { TYPE_INT, NULL, FALSE, 53}, // Stage0 UV Channel { TYPE_INT, NULL, FALSE, 54}, // Stage1 UV Channel { TYPE_INT, NULL, FALSE, 9998}, // foo { TYPE_INT, NULL, FALSE, 9999}, // bar { TYPE_INT, NULL, FALSE, 55}, // Stage1 Mapping Type (new to version 4) }; // Version 5 (current version) static ParamBlockDescID PassParameterBlockDescVer5[] = { { TYPE_POINT3, NULL, TRUE, 0 }, // Ambient { TYPE_POINT3, NULL, TRUE, 1 }, // Diffuse { TYPE_POINT3, NULL, TRUE, 2 }, // Specular { TYPE_POINT3, NULL, TRUE, 3 }, // Emissive { TYPE_FLOAT, NULL, TRUE, 4 }, // Shininess { TYPE_FLOAT, NULL, TRUE, 5 }, // Opacity { TYPE_FLOAT, NULL, TRUE, 6 }, // Translucency { TYPE_BOOL, NULL, FALSE, 34}, // Copy specular to diffuse (new to version 1) { TYPE_INT, NULL, FALSE, 7 }, // Stage0 Mapping Type { TYPE_INT, NULL, FALSE, 8 }, // PSX Translucency Type { TYPE_BOOL, NULL, FALSE, 9 }, // PSX Lighting Flag { TYPE_INT, NULL, FALSE, 10}, // Depth Compare { TYPE_INT, NULL, FALSE, 11}, // Depth Mask { TYPE_INT, NULL, FALSE, 12}, // Color Mask (now obsolete and ignored) { TYPE_INT, NULL, FALSE, 13}, // Dest Blend { TYPE_INT, NULL, FALSE, 14}, // FogFunc (now obsolete and ignored) { TYPE_INT, NULL, FALSE, 15}, // PriGradient { TYPE_INT, NULL, FALSE, 16}, // SecGradient { TYPE_INT, NULL, FALSE, 17}, // SrcBlend { TYPE_INT, NULL, FALSE, 18}, // DetailColorFunc { TYPE_INT, NULL, FALSE, 19}, // DetailAlphaFunc { TYPE_BOOL, NULL, FALSE, 22}, // Stage0 Texture Enable { TYPE_BOOL, NULL, FALSE, 23}, // Stage0 Texture Publish { TYPE_BOOL, NULL, FALSE, 35}, // Stage0 Texture Resize (new to version 1) OBSOLETE! { TYPE_BOOL, NULL, FALSE, 36}, // Stage0 Texture No Mipmap (new to version 1) OBSOLETE! { TYPE_BOOL, NULL, FALSE, 37}, // Stage0 Texture Clamp U (new to version 1) { TYPE_BOOL, NULL, FALSE, 38}, // Stage0 Texture Clamp V (new to version 1) { TYPE_INT, NULL, FALSE, 39}, // Stage0 Texture Hint (new to version 1) { TYPE_BOOL, NULL, FALSE, 24}, // Stage0 Texture Display (in viewport...) { TYPE_FLOAT, NULL, FALSE, 25}, // Stage0 Frame Rate { TYPE_INT, NULL, FALSE, 26}, // Stage0 Frame Count { TYPE_INT, NULL, FALSE, 27}, // Stage0 Animation Type { TYPE_BOOL, NULL, FALSE, 28}, // Stage1 Texture Enable { TYPE_BOOL, NULL, FALSE, 29}, // Stage1 Texture Publish { TYPE_BOOL, NULL, FALSE, 40}, // Stage1 Texture Resize (new to version 1) OBSOLETE! { TYPE_BOOL, NULL, FALSE, 41}, // Stage1 Texture No Mipmap (new to version 1) OBSOLETE! { TYPE_BOOL, NULL, FALSE, 42}, // Stage1 Texture Clamp U (new to version 1) { TYPE_BOOL, NULL, FALSE, 43}, // Stage1 Texture Clamp V (new to version 1) { TYPE_INT, NULL, FALSE, 44}, // Stage1 Texture Hint (new to version 1) { TYPE_BOOL, NULL, FALSE, 30}, // Stage1 Texture Display (in viewport...) { TYPE_FLOAT, NULL, FALSE, 31}, // Stage1 Frame Rate { TYPE_INT, NULL, FALSE, 32}, // Stage1 Frame Count { TYPE_INT, NULL, FALSE, 33}, // Stage1 Animation Type { TYPE_BOOL, NULL, FALSE, 45}, // Stage0 Texture Alpha Bitmap (new to version 1) { TYPE_BOOL, NULL, FALSE, 46}, // Stage1 Texture Alpha Bitmap (new to version 1) { TYPE_BOOL, NULL, FALSE, 47}, // Alpha Test (new to version 1) { TYPE_INT, NULL, FALSE, 48}, // Shader preset (new to version 1) (now obsolete and ignored) { TYPE_INT, NULL, FALSE, 49}, // PS2 Shader Param A { TYPE_INT, NULL, FALSE, 50}, // PS2 Shader Param B { TYPE_INT, NULL, FALSE, 51}, // PS2 Shader Param C { TYPE_INT, NULL, FALSE, 52}, // PS2 Shader Param D { TYPE_INT, NULL, FALSE, 53}, // Stage0 UV Channel { TYPE_INT, NULL, FALSE, 54}, // Stage1 UV Channel { TYPE_INT, NULL, FALSE, 55 }, // Stage1 Mapping Type (new to version 4) { TYPE_BOOL, NULL, FALSE, 56 }, // Stage0 no texture reduction (new to version 5) { TYPE_BOOL, NULL, FALSE, 57 }, // Stage0 no texture reduction (new to version 5) }; // Array of old pass parameter block versions (for backwards compatibility) const int NUM_OLDVERSIONS = 5; static ParamVersionDesc PassParameterBlockVersions[] = { ParamVersionDesc(PassParameterBlockDescVer0, 34, 0), ParamVersionDesc(PassParameterBlockDescVer1, 47, 1), ParamVersionDesc(PassParameterBlockDescVer2, 51, 2), ParamVersionDesc(PassParameterBlockDescVer3, 53, 3), ParamVersionDesc(PassParameterBlockDescVer4, 56, 4) }; // Current pass parameter block version const int CURRENT_VERSION = 5; static ParamVersionDesc CurrentPassParameterBlockVersion( PassParameterBlockDescVer5, sizeof(PassParameterBlockDescVer5) / sizeof(ParamBlockDescID), CURRENT_VERSION); const int DISPLACEMENT_INDEX = (W3dMaterialClass::MAX_PASSES * W3dMaterialClass::MAX_STAGES); Color scale(const Color& a, const Color& b) { return Color(a.r * b.r, a.g * b.g, a.b * b.b); } /*********************************************************************************************** * GameMtl::GameMtl -- constructor * * * * INPUT: * * * * OUTPUT: * * * * WARNINGS: * * * * HISTORY: * * 11/23/98 GTH : Created. * *=============================================================================================*/ GameMtl::GameMtl(BOOL loading) { MaterialDialog = NULL; SurfaceType = SURFACE_TYPE_DEFAULT; SortLevel = SORT_LEVEL_NONE; Ivalid.SetEmpty(); RollScroll = 0; Flags = 0; Flags |= GAMEMTL_PASSCOUNT_ROLLUP_OPEN; Set_Flag(GAMEMTL_CONVERTED_TO_NOLOD,true); DisplacementMap = NULL; DisplacementAmt = 0.0F; Maps = NULL; MainParameterBlock = NULL; for (int pass=0; passReplaceReference(REF_MAIN,remap.CloneRef(MainParameterBlock)); // Clone the displacment map's settings mnew->ReplaceReference (REF_TEXTURE + DISPLACEMENT_INDEX, DisplacementMap); mnew->DisplacementAmt = DisplacementAmt; // Maintain the shader type. mnew->Set_Shader_Type(ShaderType); // replace each pass's parameter block and the textures for (int pass=0; pass < W3dMaterialClass::MAX_PASSES; pass++) { IParamBlock * pblock = NULL; if (PassParameterBlock[pass]) { pblock = (IParamBlock *)remap.CloneRef(PassParameterBlock[pass]); } mnew->ReplaceReference(pass_ref_index(pass), pblock); mnew->PassParameterBlock[pass] = pblock; for (int stage=0; stage < W3dMaterialClass::MAX_STAGES; stage++) { if (Texture[pass][stage]) { mnew->ReplaceReference(texture_ref_index(pass,stage),Texture[pass][stage]->Clone()); } else { mnew->ReplaceReference(texture_ref_index(pass,stage),NULL); } // Copy mapper arg strings and lengths if (MapperArgLen[pass][stage] > 0) { char *temp = new char[MapperArgLen[pass][stage] + 1]; assert(strlen(MapperArg[pass][stage]) <= MapperArgLen[pass][stage]); strcpy(temp, MapperArg[pass][stage]); mnew->MapperArg[pass][stage] = temp; mnew->MapperArgLen[pass][stage] = MapperArgLen[pass][stage]; } } } mnew->Ivalid = Ivalid; return mnew; } /*********************************************************************************************** * GameMtl::NotifyRefChanged -- NotifyRefChanged handler * * * * INPUT: * * * * OUTPUT: * * * * WARNINGS: * * * * HISTORY: * * 11/23/98 GTH : Created. * *=============================================================================================*/ RefResult GameMtl::NotifyRefChanged ( Interval changeInt, RefTargetHandle hTarget, PartID & partID, RefMessage message ) { switch (message) { case REFMSG_CHANGE: { Ivalid.SetEmpty(); // if any refs changed, clear the validity if (MaterialDialog && (MaterialDialog->TheMtl == this)) { MaterialDialog->Invalidate(); // if the dialog is up, refresh it } break; } case REFMSG_GET_PARAM_DIM: { GetParamDim *gpd = (GetParamDim*)partID; gpd->dim = defaultDim; return REF_STOP; } case REFMSG_GET_PARAM_NAME: { GetParamName *gpn = (GetParamName*)partID; bool pass_parameter = false; for(int pass = 0; pass < Get_Pass_Count(); pass++) { if(hTarget == (RefTargetHandle)PassParameterBlock[pass]) pass_parameter = true; } if (pass_parameter) { switch (gpn->index) { case PB_AMBIENT: gpn->name = _T("Ambient"); break; case PB_DIFFUSE: gpn->name = _T("Diffuse"); break; case PB_SPECULAR: gpn->name = _T("Specular"); break; case PB_EMISSIVE: gpn->name = _T("Emissive"); break; case PB_SHININESS: gpn->name = _T("Shininess"); break; case PB_OPACITY: gpn->name = _T("Opacity"); break; case PB_TRANSLUCENCY: gpn->name = _T("Translucency"); break; default: gpn->name = _T(""); break; } } return REF_STOP; } } return(REF_SUCCEED); } /*********************************************************************************************** * GameMtl::SetReference -- set the i'th reference * * * * INPUT: * * * * OUTPUT: * * * * WARNINGS: * * * * HISTORY: * * 11/23/98 GTH : Created. * *=============================================================================================*/ void GameMtl::SetReference(int i, RefTargetHandle rtarg) { assert(i < REF_COUNT); if (i == REF_MAPS) { Maps = (GameMapsClass *)rtarg; return; } if (i == REF_MAIN) { MainParameterBlock = (IParamBlock*)rtarg; return; } if ((i >= REF_PASS_PARAMETERS) && (i < REF_PASS_PARAMETERS + W3dMaterialClass::MAX_PASSES)) { PassParameterBlock[i - REF_PASS_PARAMETERS] = (IParamBlock*)rtarg; return; } if ((i >= REF_TEXTURE) && (i < REF_TEXTURE + 9)) { if (i == REF_TEXTURE + DISPLACEMENT_INDEX) { DisplacementMap = (Texmap *)rtarg; } else { int offset = i - REF_TEXTURE; int pass = offset / 2; int stage = offset % 2; Texture[pass][stage] = (Texmap *)rtarg; } return; } } /*********************************************************************************************** * GameMtl::GetReference -- returnst the i'th reference * * * * INPUT: * * * * OUTPUT: * * * * WARNINGS: * * * * HISTORY: * * 11/23/98 GTH : Created. * *=============================================================================================*/ RefTargetHandle GameMtl::GetReference(int i) { if (i == REF_MAPS) { return Maps; } if (i == REF_MAIN) { return MainParameterBlock; } if ((i >= REF_PASS_PARAMETERS) && (i < REF_PASS_PARAMETERS + W3dMaterialClass::MAX_PASSES)) { return PassParameterBlock[i - REF_PASS_PARAMETERS]; } if ((i >= REF_TEXTURE) && (i < REF_TEXTURE + 9)) { if (i == REF_TEXTURE + DISPLACEMENT_INDEX) { return DisplacementMap; } else { int offset = i - REF_TEXTURE; int pass = offset / 2; int stage = offset % 2; return Texture[pass][stage]; } } return NULL; } /*********************************************************************************************** * GameMtl::NumSubTexmaps -- returns the number of texture maps in this material * * * * INPUT: * * * * OUTPUT: * * * * WARNINGS: * * * * HISTORY: * * 11/23/98 GTH : Created. * *=============================================================================================*/ int GameMtl::NumSubTexmaps(void) { return (W3dMaterialClass::MAX_PASSES * W3dMaterialClass::MAX_STAGES) + 1; } /*********************************************************************************************** * GameMtl::Get_Displacement_Map_Index -- returns the Sub-texmap index for the displacement map. * * * INPUT: * * * * OUTPUT: * * * * WARNINGS: * * * * HISTORY: * * 7/01/99 PDS : Created. * *=============================================================================================*/ int GameMtl::Get_Displacement_Map_Index(void) const { return DISPLACEMENT_INDEX; } /*********************************************************************************************** * GameMtl::SetSubTexmap -- set the i'th texture map * * * * INPUT: * * * * OUTPUT: * * * * WARNINGS: * * * * HISTORY: * * 11/23/98 GTH : Created. * *=============================================================================================*/ void GameMtl::SetSubTexmap(int i, Texmap * m) { ReplaceReference(REF_TEXTURE + i, m); int pass,stage; texmap_index_to_pass_stage(i,&pass,&stage); if (Texture[pass][stage] != NULL) { UVGen * uvgen = Texture[pass][stage]->GetTheUVGen(); if (uvgen != NULL) { uvgen->SetMapChannel(Get_Map_Channel(pass,stage)); } } NotifyDependents(FOREVER, PART_ALL, REFMSG_CHANGE); } /*********************************************************************************************** * GameMtl::GetSubTexmap -- returns the i'th texture map * * * * INPUT: * * * * OUTPUT: * * * * WARNINGS: * * * * HISTORY: * * 11/23/98 GTH : Created. * *=============================================================================================*/ Texmap * GameMtl::GetSubTexmap(int i) { if (i == DISPLACEMENT_INDEX) { return DisplacementMap; } int pass; int stage; texmap_index_to_pass_stage(i,&pass,&stage); return Texture[pass][stage]; } /*********************************************************************************************** * GameMtl::CreateParamDlg -- creates the material editor dialog box * * * * INPUT: * * * * OUTPUT: * * * * WARNINGS: * * * * HISTORY: * * 11/23/98 GTH : Created. * *=============================================================================================*/ ParamDlg * GameMtl::CreateParamDlg(HWND hwnd_mtl_edit, IMtlParams *imp) { GameMtlDlg *dlg = new GameMtlDlg(hwnd_mtl_edit, imp, this); SetParamDlg(dlg); return dlg; } /*********************************************************************************************** * GameMtl::Notify_Changed -- someone has changed this material * * * * INPUT: * * * * OUTPUT: * * * * WARNINGS: * * * * HISTORY: * * 11/23/98 GTH : Created. * *=============================================================================================*/ void GameMtl::Notify_Changed(void) { NotifyDependents(FOREVER, PART_ALL, REFMSG_CHANGE); if (MaterialDialog != NULL) { MaterialDialog->Update_Display(); } } /*********************************************************************************************** * GameMtl::Reset -- reset this material to default settings * * * * INPUT: * * * * OUTPUT: * * * * WARNINGS: * * * * HISTORY: * * 11/23/98 GTH : Created. * *=============================================================================================*/ void GameMtl::Reset() { DebugPrint("GameMtl::Reset()\n"); ReplaceReference(REF_MAIN,CreateParameterBlock(MainParameterBlockDesc,1,CURRENT_VERSION)); for (int pass = 0; pass < W3dMaterialClass::MAX_PASSES; pass++) { // Install a parameter block for each pass IParamBlock * pblock = CreateParameterBlock( PassParameterBlockDescVer5, sizeof(PassParameterBlockDescVer5)/sizeof(ParamBlockDescID), CURRENT_VERSION); ReplaceReference(pass_ref_index(pass), pblock); for (int stage = 0;stage < W3dMaterialClass::MAX_STAGES; stage++) { ReplaceReference(texture_ref_index(pass,stage), NULL); Set_Texture_Enable(pass,stage,false); Set_Texture_Publish(pass,stage,false); Set_Texture_Resize(pass,stage,false); Set_Texture_No_Mipmap(pass,stage,false); Set_Texture_Clamp_U(pass,stage,false); Set_Texture_Clamp_V(pass,stage,false); Set_Texture_No_LOD(pass,stage,false); Set_Texture_Alpha_Bitmap(pass,stage,false); Set_Texture_Hint(pass,stage,W3DTEXTURE_HINT_BASE); Set_Texture_Display(pass,stage,false); Set_Texture_Frame_Rate(pass,stage,15.0f); Set_Texture_Frame_Count(pass,stage,1); Set_Texture_Anim_Type(pass,stage,W3DTEXTURE_ANIM_LOOP); Set_Map_Channel(pass,stage,1); if (MapperArg[pass][stage]) { delete [] (MapperArg[pass][stage]); MapperArg[pass][stage] = NULL; MapperArgLen[pass][stage] = 0; } } Set_Sort_Level(SORT_LEVEL_NONE); Set_Ambient(pass,0,(pass == 0 ? Color(1.0,1.0,1.0) : Color(0,0,0))); Set_Diffuse(pass,0,(pass == 0 ? Color(1.0,1.0,1.0) : Color(0,0,0))); Set_Specular(pass,0,Color(0,0,0)); Set_Emissive(pass,0,Color(0,0,0)); Set_Shininess(pass,0,0.0f); Set_Opacity(pass,0,1.0f); Set_Translucency(pass,0,0.0f); Set_Copy_Specular_To_Diffuse(pass,false); Set_Mapping_Type(pass,0,W3DMAPPING_UV); Set_Mapping_Type(pass,1,W3DMAPPING_UV); Set_PSX_Translucency(pass,GAMEMTL_PSX_TRANS_NONE); Set_PSX_Lighting(pass,true); Set_Depth_Compare(pass,W3DSHADER_DEPTHCOMPARE_DEFAULT); Set_Depth_Mask(pass,W3DSHADER_DEPTHMASK_DEFAULT); Set_Alpha_Test(pass,W3DSHADER_ALPHATEST_DEFAULT); Set_Dest_Blend(pass,W3DSHADER_DESTBLENDFUNC_DEFAULT); Set_Pri_Gradient(pass,W3DSHADER_PRIGRADIENT_DEFAULT); Set_Sec_Gradient(pass,W3DSHADER_SECGRADIENT_DEFAULT); Set_Src_Blend(pass,W3DSHADER_SRCBLENDFUNC_DEFAULT); Set_Detail_Color_Func(pass,W3DSHADER_DETAILCOLORFUNC_DEFAULT); Set_Detail_Alpha_Func(pass,W3DSHADER_DETAILCOLORFUNC_DEFAULT); // Playstation 2 default for opaque. Set_PS2_Shader_Param_A(pass, PSS_SRC); Set_PS2_Shader_Param_B(pass, PSS_ZERO); Set_PS2_Shader_Param_C(pass, PSS_ONE); Set_PS2_Shader_Param_D(pass, PSS_ZERO); } Ivalid.SetEmpty(); Set_Pass_Count(1); // set default value for the main param block } /*********************************************************************************************** * GameMtl::Update -- time has changed * * * * INPUT: * * * * OUTPUT: * * * * WARNINGS: * * * * HISTORY: * * 11/23/98 GTH : Created. * *=============================================================================================*/ void GameMtl::Update(TimeValue t, Interval &ivalid) { // This function is called by the system prior to rendering // Its purpose is to let you pre-calculate anything you can to // speed up the subsequent 'Shade' calls. Ivalid = FOREVER; ivalid &= Ivalid; } /*********************************************************************************************** * GameMtl::Validity -- return the validity of the material at time t * * * * INPUT: * * * * OUTPUT: * * * * WARNINGS: * * * * HISTORY: * * 11/23/98 GTH : Created. * *=============================================================================================*/ Interval GameMtl::Validity(TimeValue t) { return FOREVER; } /*********************************************************************************************** * GameMtl::Requirements -- what requirements does this material have? * * * * INPUT: * * * * OUTPUT: * * * * WARNINGS: * * * * HISTORY: * * 11/23/98 GTH : Created. * *=============================================================================================*/ ULONG GameMtl::Requirements(int subMtlNum) { ULONG req = 0; for (int pass = 0; pass < W3dMaterialClass::MAX_PASSES; pass++) { for (int stage = 0; stage < W3dMaterialClass::MAX_STAGES; stage++) { if (Texture[pass][stage]) { req |= Texture[pass][stage]->Requirements(subMtlNum); } } } req |= MTLREQ_BGCOL; req |= MTLREQ_NOATMOS; #ifdef WANT_DISPLACEMENT_MAPS req |= MTLREQ_DISPLACEMAP; #endif //WANT_DISPLACEMENT_MAPS return req; } /*********************************************************************************************** * GameMtl::Load -- loading from a MAX file * * * * INPUT: * * * * OUTPUT: * * * * WARNINGS: * * * * HISTORY: * * 11/23/98 GTH : Created. * *=============================================================================================*/ IOResult GameMtl::Load(ILoad *iload) { ULONG nb; int id; int passindex = 0; int len = 0; unsigned char tmp8; unsigned short tmp16; char * tmpstring = NULL; float tmpfloat; IOResult res; GameMtlPostLoad * lc = new GameMtlPostLoad(this); iload->RegisterPostLoadCallback(lc); // Register automatic translation callbacks for the pass parameter blocks for (int i = 0; i < W3dMaterialClass::MAX_PASSES; i++) { iload->RegisterPostLoadCallback( new ParamBlockPLCB(PassParameterBlockVersions, NUM_OLDVERSIONS, &CurrentPassParameterBlockVersion, this, REF_PASS_PARAMETERS + i) ); } while (IO_OK==(res=iload->OpenChunk())) { switch (id = iload->CurChunkID()) { case MTL_HDR_CHUNK: res = MtlBase::Load(iload); Ivalid.SetEmpty(); break; case GAMEMTL_FLAGS_CHUNK: res = iload->Read(&Flags,sizeof(Flags), &nb); break; case GAMEMTL_SURFACE_TYPE_CHUNK: res = iload->Read(&SurfaceType,sizeof(SurfaceType),&nb); break; case GAMEMTL_SORT_LEVEL_CHUNK: res = iload->Read(&SortLevel,sizeof(SortLevel),&nb); break; case GAMEMTL_PASS0_CUR_PAGE: case GAMEMTL_PASS1_CUR_PAGE: case GAMEMTL_PASS2_CUR_PAGE: case GAMEMTL_PASS3_CUR_PAGE: res = iload->Read(&tmp8,sizeof(tmp8),&nb); CurPage[id - GAMEMTL_PASS0_CUR_PAGE] = tmp8; break; case GAMEMTL_PASS0_STAGE0_MAPPER_ARGS: case GAMEMTL_PASS1_STAGE0_MAPPER_ARGS: case GAMEMTL_PASS2_STAGE0_MAPPER_ARGS: case GAMEMTL_PASS3_STAGE0_MAPPER_ARGS: len = iload->CurChunkLength(); passindex = id - GAMEMTL_PASS0_STAGE0_MAPPER_ARGS; tmpstring = Get_Mapping_Arg_Buffer(passindex, 0, len); res = iload->Read(tmpstring, len, &nb); break; case GAMEMTL_PASS0_STAGE1_MAPPER_ARGS: case GAMEMTL_PASS1_STAGE1_MAPPER_ARGS: case GAMEMTL_PASS2_STAGE1_MAPPER_ARGS: case GAMEMTL_PASS3_STAGE1_MAPPER_ARGS: len = iload->CurChunkLength(); passindex = id - GAMEMTL_PASS0_STAGE1_MAPPER_ARGS; tmpstring = Get_Mapping_Arg_Buffer(passindex, 1, len); res = iload->Read(tmpstring, len, &nb); break; /* ** All chunks below here are for the obsolete material plugin... */ case GAMEMTL_GAMEFLAGS_CHUNK: break; case GAMEMTL_ATTRIBUTES_CHUNK: res = iload->Read(&lc->Attributes,sizeof(lc->Attributes),&nb); lc->IsOld = true; break; case GAMEMTL_COLORS_CHUNK: res = iload->Read(&lc->Diffuse,sizeof(lc->Diffuse),&nb); lc->IsOld = true; break; case GAMEMTL_DCT_FRAMES_CHUNK: res = iload->Read(&tmp16,sizeof(unsigned short),&nb); lc->DCTFrames = tmp16; lc->IsOld = true; break; case GAMEMTL_DCT_FRAME_RATE_CHUNK: res = iload->Read(&tmpfloat,sizeof(float),&nb); lc->DCTFrameRate = tmpfloat; lc->IsOld = true; break; case GAMEMTL_DIT_FRAMES_CHUNK: res = iload->Read(&tmp16,sizeof(unsigned short),&nb); lc->DITFrames = tmp16; lc->IsOld = true; break; case GAMEMTL_DIT_FRAME_RATE_CHUNK: res = iload->Read(&tmpfloat,sizeof(float),&nb); lc->DITFrameRate = tmpfloat; lc->IsOld = true; break; case GAMEMTL_SCT_FRAMES_CHUNK: res = iload->Read(&tmp16,sizeof(unsigned short),&nb); lc->SCTFrames = tmp16; lc->IsOld = true; break; case GAMEMTL_SCT_FRAME_RATE_CHUNK: res = iload->Read(&tmpfloat,sizeof(float),&nb); lc->SCTFrameRate = tmpfloat; lc->IsOld = true; break; case GAMEMTL_SIT_FRAMES_CHUNK: res = iload->Read(&tmp16,sizeof(unsigned short),&nb); lc->SITFrames = tmp16; lc->IsOld = true; break; case GAMEMTL_SIT_FRAME_RATE_CHUNK: res = iload->Read(&tmpfloat,sizeof(float),&nb); lc->SITFrameRate = tmpfloat; lc->IsOld = true; break; case GAMEMTL_DCT_MAPPING_CHUNK: res = iload->Read(&tmp8,sizeof(unsigned char),&nb); lc->DCTMappingType = tmp8; lc->IsOld = true; break; case GAMEMTL_DIT_MAPPING_CHUNK: res = iload->Read(&tmp8,sizeof(unsigned char),&nb); lc->DITMappingType = tmp8; lc->IsOld = true; break; case GAMEMTL_SCT_MAPPING_CHUNK: res = iload->Read(&tmp8,sizeof(unsigned char),&nb); lc->SCTMappingType = tmp8; lc->IsOld = true; break; case GAMEMTL_SIT_MAPPING_CHUNK: res = iload->Read(&tmp8,sizeof(unsigned char),&nb); lc->SITMappingType = tmp8; lc->IsOld = true; break; case GAMEMTL_DIFFUSE_COLOR_CHUNK: res = iload->Read(&lc->Diffuse,sizeof(lc->Diffuse),&nb); lc->IsOld = true; break; case GAMEMTL_SPECULAR_COLOR_CHUNK: res = iload->Read(&lc->Specular,sizeof(lc->Specular),&nb); lc->IsOld = true; break; case GAMEMTL_AMBIENT_COEFF_CHUNK: res = iload->Read(&lc->AmbientCoeff,sizeof(lc->AmbientCoeff),&nb); lc->IsOld = true; break; case GAMEMTL_DIFFUSE_COEFF_CHUNK: res = iload->Read(&lc->DiffuseCoeff,sizeof(lc->DiffuseCoeff),&nb); lc->IsOld = true; break; case GAMEMTL_SPECULAR_COEFF_CHUNK: res = iload->Read(&lc->SpecularCoeff,sizeof(lc->SpecularCoeff),&nb); lc->IsOld = true; break; case GAMEMTL_EMISSIVE_COEFF_CHUNK: res = iload->Read(&lc->EmissiveCoeff,sizeof(lc->EmissiveCoeff),&nb); lc->IsOld = true; break; case GAMEMTL_OPACITY_CHUNK: res = iload->Read(&lc->Opacity,sizeof(lc->Opacity),&nb); lc->IsOld = true; break; case GAMEMTL_TRANSLUCENCY_CHUNK: res = iload->Read(&lc->Translucency,sizeof(lc->Translucency),&nb); lc->IsOld = true; break; case GAMEMTL_SHININESS_CHUNK: res = iload->Read(&lc->Shininess,sizeof(lc->Shininess),&nb); lc->IsOld = true; break; case GAMEMTL_FOG_CHUNK: res = iload->Read(&lc->FogCoeff,sizeof(lc->FogCoeff),&nb); lc->IsOld = true; break; default: break; } iload->CloseChunk(); if (res!=IO_OK) { return res; } } return IO_OK; } /*********************************************************************************************** * GameMtl::Save -- Saving into a MAX file * * * * INPUT: * * * * OUTPUT: * * * * WARNINGS: * * * * HISTORY: * * 11/23/98 GTH : Created. * *=============================================================================================*/ IOResult GameMtl::Save(ISave *isave) { IOResult res; ULONG nb; /* ** Save the base class stuff */ isave->BeginChunk(MTL_HDR_CHUNK); res = MtlBase::Save(isave); if (res!=IO_OK) return res; isave->EndChunk(); /* ** Save the flags */ isave->BeginChunk(GAMEMTL_FLAGS_CHUNK); isave->Write(&Flags,sizeof(Flags),&nb); isave->EndChunk(); /* ** Save the "cur-pages" */ uint8 tmp8; int pass; for (pass=0; pass < W3dMaterialClass::MAX_PASSES; pass++) { isave->BeginChunk(GAMEMTL_PASS0_CUR_PAGE + pass); tmp8 = CurPage[pass]; isave->Write(&tmp8,sizeof(tmp8),&nb); isave->EndChunk(); } /* ** Save any Mapper Args */ for (pass=0; pass < W3dMaterialClass::MAX_PASSES; pass++) { char *buffer = Get_Mapping_Arg_Buffer(pass, 0); if (buffer) { isave->BeginChunk(GAMEMTL_PASS0_STAGE0_MAPPER_ARGS + pass); isave->Write(buffer, strlen(buffer) + 1, &nb); isave->EndChunk(); } buffer = Get_Mapping_Arg_Buffer(pass, 1); if (buffer) { isave->BeginChunk(GAMEMTL_PASS0_STAGE1_MAPPER_ARGS + pass); isave->Write(buffer, strlen(buffer) + 1, &nb); isave->EndChunk(); } } /* ** Save the surface type */ isave->BeginChunk(GAMEMTL_SURFACE_TYPE_CHUNK); isave->Write(&SurfaceType,sizeof(SurfaceType),&nb); isave->EndChunk(); /* ** Save the sort level */ isave->BeginChunk(GAMEMTL_SORT_LEVEL_CHUNK); isave->Write(&SortLevel,sizeof(SortLevel),&nb); isave->EndChunk(); return IO_OK; } /*********************************************************************************************** * GameMtl::Shade -- evaluate the material for the renderer. * * * * INPUT: * * * * OUTPUT: * * * * WARNINGS: * * This function could use a little work. It doesn't always produce correct results. * * * * HISTORY: * * 11/23/98 GTH : Created. * *=============================================================================================*/ void GameMtl::Shade(ShadeContext& sc) { if (ShaderType == STE_PS2_SHADER) { ps2_shade(sc); return; } if (gbufID) sc.SetGBufferID(gbufID); /* ** Shadowing, return black */ if (sc.mode==SCMODE_SHADOW) { sc.out.t = Color(0,0,0); return; } /* ** Render each pass, initialize dest with the current background */ Color back_c; Color back_t; Color dest; Color src; float alpha; sc.GetBGColor(back_c,back_t, FALSE); dest = back_c; for (int pass=0; pass < Get_Pass_Count(); pass++) { /* ** Computing the Primary and Secondary Gradients */ Color ambient = sc.ambientLight; Color diffuse(0,0,0); Color specular(0,0,0); for(int light_index = 0; light_index < sc.nLights; light_index++) { Color light_color; Point3 light_dir; float dot_nl; float diffuse_coef; LightDesc * light = sc.Light(light_index); if(light->Illuminate(sc, sc.Normal(), light_color, light_dir, dot_nl, diffuse_coef)) { //ambient += light_color; if (dot_nl > 0.0f) diffuse += dot_nl * light_color; float c = DotProd(light_dir, sc.ReflectVector()); if(c > 0.f) { specular += (float)pow(c, Get_Shininess(pass, sc.CurTime())) * light_color; } } } ambient = ambient * Get_Ambient(pass,sc.CurTime()); diffuse = diffuse * Get_Diffuse(pass,sc.CurTime()); specular = specular * Get_Specular(pass,sc.CurTime()); Color pri_gradient = ambient + diffuse + Get_Emissive(pass,sc.CurTime()); if (pri_gradient.r > 1.0f) pri_gradient.r = 1.0f; if (pri_gradient.g > 1.0f) pri_gradient.g = 1.0f; if (pri_gradient.b > 1.0f) pri_gradient.b = 1.0f; Color sec_gradient = specular * Get_Specular(pass,sc.CurTime()); /* ** Sampling the Texture(s) */ AColor texel(1,1,1,1); if (Get_Texture_Enable(pass,0) && Texture[pass][0]) { // if (Get_Mapping_Type(pass) == GAMEMTL_MAPPING_UV) { texel = Texture[pass][0]->EvalColor(sc); // } } if (Get_Texture_Enable(pass,1) && Texture[pass][1]) { AColor detail_texel = Texture[pass][1]->EvalColor(sc); switch (Get_Detail_Color_Func(pass)) { case W3DSHADER_DETAILCOLORFUNC_DISABLE: break; case W3DSHADER_DETAILCOLORFUNC_DETAIL: texel = detail_texel; break; case W3DSHADER_DETAILCOLORFUNC_SCALE: texel.r = detail_texel.r * texel.r; texel.g = detail_texel.g * texel.g; texel.b = detail_texel.b * texel.b; break; case W3DSHADER_DETAILCOLORFUNC_INVSCALE: texel.r = texel.r + (1.0f - texel.r) * detail_texel.r; texel.g = texel.g + (1.0f - texel.g) * detail_texel.g; texel.b = texel.b + (1.0f - texel.b) * detail_texel.b; break; case W3DSHADER_DETAILCOLORFUNC_ADD: texel.r = detail_texel.r + texel.r; texel.g = detail_texel.g + texel.g; texel.b = detail_texel.b + texel.b; break; case W3DSHADER_DETAILCOLORFUNC_SUB: texel.r = texel.r - detail_texel.r; texel.g = texel.g - detail_texel.g; texel.b = texel.b - detail_texel.b; break; case W3DSHADER_DETAILCOLORFUNC_SUBR: texel.r = detail_texel.r - texel.r; texel.g = detail_texel.g - texel.g; texel.b = detail_texel.b - texel.b; break; case W3DSHADER_DETAILCOLORFUNC_BLEND: texel.r = (texel.a * texel.r) + ((1.0f - texel.a)*detail_texel.r); texel.g = (texel.a * texel.g) + ((1.0f - texel.a)*detail_texel.g); texel.b = (texel.a * texel.b) + ((1.0f - texel.a)*detail_texel.b); break; case W3DSHADER_DETAILCOLORFUNC_DETAILBLEND: texel.r = (detail_texel.a * texel.r) + ((1.0f - detail_texel.a)*detail_texel.r); texel.g = (detail_texel.a * texel.g) + ((1.0f - detail_texel.a)*detail_texel.g); texel.b = (detail_texel.a * texel.b) + ((1.0f - detail_texel.a)*detail_texel.b); break; } switch (Get_Detail_Alpha_Func(pass)) { case W3DSHADER_DETAILALPHAFUNC_DISABLE: break; case W3DSHADER_DETAILALPHAFUNC_DETAIL: texel.a = detail_texel.a; break; case W3DSHADER_DETAILALPHAFUNC_SCALE: texel.a = texel.a * detail_texel.a; break; case W3DSHADER_DETAILALPHAFUNC_INVSCALE: texel.a = texel.a + (1.0f - texel.a) * detail_texel.a; break; } } /* ** Shader parameters define combination... */ src.r = texel.r; src.g = texel.g; src.b = texel.b; alpha = texel.a * Get_Opacity(pass,sc.CurTime()); switch (Get_Pri_Gradient(pass)) { case W3DSHADER_PRIGRADIENT_DISABLE: break; case W3DSHADER_PRIGRADIENT_MODULATE: src = src * pri_gradient; break; case W3DSHADER_PRIGRADIENT_ADD: src = src + pri_gradient; break; } switch (Get_Sec_Gradient(pass)) { case W3DSHADER_SECGRADIENT_DISABLE: break; case W3DSHADER_SECGRADIENT_ENABLE: src = src + sec_gradient; break; } if (src.r > 1.0f) src.r = 1.0f; if (src.g > 1.0f) src.g = 1.0f; if (src.b > 1.0f) src.b = 1.0f; if (src.r < 0.0f) src.r = 0.0f; if (src.g < 0.0f) src.g = 0.0f; if (src.b < 0.0f) src.b = 0.0f; Color dest_blend; switch (Get_Dest_Blend(pass)) { case W3DSHADER_DESTBLENDFUNC_ZERO: dest_blend = Color(0,0,0); break; case W3DSHADER_DESTBLENDFUNC_ONE: dest_blend = Color(1,1,1); break; case W3DSHADER_DESTBLENDFUNC_SRC_COLOR: dest_blend = src; break; case W3DSHADER_DESTBLENDFUNC_ONE_MINUS_SRC_COLOR: dest_blend = Color(1.0f-src.r,1.0f-src.g, 1.0f-src.b); break; case W3DSHADER_DESTBLENDFUNC_SRC_ALPHA: dest_blend = Color(alpha,alpha,alpha); break; case W3DSHADER_DESTBLENDFUNC_ONE_MINUS_SRC_ALPHA: dest_blend = Color(1.0f-alpha,1.0f-alpha,1.0f-alpha); break; case W3DSHADER_DESTBLENDFUNC_SRC_COLOR_PREFOG: dest_blend = src; break; } Color src_blend; switch (Get_Src_Blend(pass)) { case W3DSHADER_SRCBLENDFUNC_ZERO: src_blend = Color(0,0,0); break; case W3DSHADER_SRCBLENDFUNC_ONE: src_blend = Color(1,1,1); break; case W3DSHADER_SRCBLENDFUNC_SRC_ALPHA: src_blend = Color(alpha,alpha,alpha); break; case W3DSHADER_SRCBLENDFUNC_ONE_MINUS_SRC_ALPHA: src_blend = Color(1.0f-alpha,1.0f-alpha,1.0f-alpha); break; } src = scale(src_blend,src) + scale(dest_blend,dest); /* ** Dest becomes Src and we repeat! */ dest = src; } sc.out.t = Color(0.0f, 0.0f, 0.0f); sc.out.c = dest; } /*********************************************************************************************** * GameMtl::ps2_shade -- Emulate the PS2 shader. * * * * * * * * * * HISTORY: * * 10/12/1999MLL: Created. * *=============================================================================================*/ void GameMtl::ps2_shade(ShadeContext& sc) { if (gbufID) sc.SetGBufferID(gbufID); /* ** Shadowing, return black */ if (sc.mode == SCMODE_SHADOW) { sc.out.t = Color(0,0,0); return; } /* ** Render each pass, initialize dest with the current background */ // Background transparency. ??? Color back_t; Color back_c; AColor dest; AColor src(1,1,1,1); sc.GetBGColor(back_c, back_t, FALSE); dest.r = back_c.r; dest.g = back_c.g; dest.b = back_c.b; dest.a = 0.0f; for (int pass=0; pass < Get_Pass_Count(); pass++) { // Compute the gradients. Color ambient = sc.ambientLight; Color diffuse(0,0,0); Color specular(0,0,0); for (int light_index = 0; light_index < sc.nLights; light_index++) { Color light_color; Point3 light_dir; float dot_nl; float diffuse_coef; LightDesc * light = sc.Light(light_index); assert(light); if(light->Illuminate(sc, sc.Normal(), light_color, light_dir, dot_nl, diffuse_coef)) { if (dot_nl > 0.0f) diffuse += dot_nl * light_color; float c = DotProd(light_dir, sc.ReflectVector()); if (c > 0.f) { specular += (float)pow(c, Get_Shininess(pass, sc.CurTime())) * light_color; } } } ambient = ambient * Get_Ambient(pass,sc.CurTime()); diffuse = diffuse * Get_Diffuse(pass,sc.CurTime()); specular = specular * Get_Specular(pass,sc.CurTime()); Color gradient = ambient + diffuse + Get_Emissive(pass,sc.CurTime()); AColor pri_gradient; pri_gradient.r = gradient.r; pri_gradient.g = gradient.g; pri_gradient.b = gradient.b; pri_gradient.a = 1.0f; if (pri_gradient.r > 1.0f) pri_gradient.r = 1.0f; if (pri_gradient.g > 1.0f) pri_gradient.g = 1.0f; if (pri_gradient.b > 1.0f) pri_gradient.b = 1.0f; /* ** Sampling the Texture(s) */ if (Get_Texture_Enable(pass,0) && Texture[pass][0]) { src = Texture[pass][0]->EvalColor(sc); } /* ** Shader parameters define combination... */ src.a *= Get_Opacity(pass,sc.CurTime()); switch (Get_Pri_Gradient(pass)) { case PSS_PRIGRADIENT_MODULATE: src = src * pri_gradient; break; case PSS_PRIGRADIENT_HIGHLIGHT: src = src * pri_gradient; src += back_t; // ??? break; case PSS_PRIGRADIENT_HIGHLIGHT2: src = src * pri_gradient; src += back_t; // ??? break; } if (src.r > 1.0f) src.r = 1.0f; if (src.g > 1.0f) src.g = 1.0f; if (src.b > 1.0f) src.b = 1.0f; if (src.b > 1.0f) src.a = 1.0f; if (src.r < 0.0f) src.r = 0.0f; if (src.g < 0.0f) src.g = 0.0f; if (src.b < 0.0f) src.b = 0.0f; if (src.a < 0.0f) src.a = 0.0f; AColor param_a; AColor param_b; AColor param_c; AColor param_d; int a_value = Get_PS2_Shader_Param_A(pass); int b_value = Get_PS2_Shader_Param_B(pass); int c_value = Get_PS2_Shader_Param_C(pass); int d_value = Get_PS2_Shader_Param_D(pass); switch (a_value) { case PSS_SRC: param_a = src; break; case PSS_DEST: param_a = dest; break; case PSS_ZERO: param_a = AColor(0, 0, 0, 0); break; } switch (b_value) { case PSS_SRC: param_b = src; break; case PSS_DEST: param_b = dest; break; case PSS_ZERO: param_b = AColor(0, 0, 0, 0); break; } switch (c_value) { case PSS_SRC_ALPHA: param_c = AColor(src.a, src.a, src.a, src.a); break; case PSS_DEST_ALPHA: param_c = back_t; // ??? break; case PSS_ONE: param_c = AColor(1, 1, 1, 1); break; } switch (d_value) { case PSS_SRC: param_d = src; break; case PSS_DEST: param_d = dest; break; case PSS_ZERO: param_d = AColor(0, 0, 0); break; } src = scale((param_a - param_b), param_c) + param_d; if (src.r > 1.0f) src.r = 1.0f; if (src.g > 1.0f) src.g = 1.0f; if (src.b > 1.0f) src.b = 1.0f; if (src.b > 1.0f) src.a = 1.0f; if (src.r < 0.0f) src.r = 0.0f; if (src.g < 0.0f) src.g = 0.0f; if (src.b < 0.0f) src.b = 0.0f; if (src.a < 0.0f) src.a = 0.0f; /* ** Dest becomes Src and we repeat! */ dest = src; } sc.out.t = Color(0.0f, 0.0f, 0.0f); sc.out.c.r = dest.r; sc.out.c.g = dest.g; sc.out.c.b = dest.b; } // PS2 equation paramaters. // They are set to primes to avoid multiple equation solutions. enum Shader_Translation { ST_ZERO, ST_ONE, ST_SRC = 7, ST_DEST = 31, ST_SRC_ALPHA = 101, ST_DEST_ALPHA = 2999, }; /*********************************************************************************************** * GameMtl::Compute_PC_Shader_From_PS2_Shader -- Determine if a PC shader can be created. * * * * * * * * * * HISTORY: * * 10/13/1999MLL: Created. * *=============================================================================================*/ int GameMtl::Compute_PC_Shader_From_PS2_Shader(int pass) { int param_value[4]; // These match the PC equation paramaters. static const int src_blend[4] = { ST_ZERO, ST_ONE, ST_SRC_ALPHA, 1 - ST_SRC_ALPHA }; static const int dest_blend[6] = { ST_ZERO, ST_ONE, ST_SRC, 1 - ST_SRC, ST_SRC_ALPHA, 1 - ST_SRC_ALPHA }; int i = 0; int j = 0; int equation_value = 0; // Get the PS2 shader values. param_value[0] = Get_PS2_Shader_Param_A(pass); param_value[1] = Get_PS2_Shader_Param_B(pass); param_value[2] = Get_PS2_Shader_Param_D(pass); param_value[3] = Get_PS2_Shader_Param_C(pass); // Convert them to the enumeration. for (i = 0; i < 3; i++) { switch(param_value[i]) { case PSS_SRC: param_value[i] = ST_SRC; break; case PSS_DEST: param_value[i] = ST_DEST; break; case PSS_ZERO: param_value[i] = ST_ZERO; break; } } // The alpha paramater. switch(param_value[3]) { case PSS_SRC_ALPHA: param_value[3] = ST_SRC_ALPHA; break; case PSS_DEST_ALPHA: param_value[3] = ST_DEST_ALPHA; break; case PSS_ONE: param_value[3] = ST_ONE; break; } // Calculate the PS2 shader. equation_value = ((param_value[0] - param_value[1]) * param_value[3]) + param_value[2]; for (i = 0; i < 4; i++) { for (j = 0; j < 6; j++) { // Calculate the PC shader. If equal, we have found a conversion. if (((src_blend[i] * ST_SRC) + (dest_blend[j] * ST_DEST)) == equation_value) { break; } } if (j != 6) { break; } } if ((j == 6) && (i == 4)) { // Set the W3D shader to opaque. Set_Dest_Blend(pass, W3DSHADER_DESTBLENDFUNC_ZERO); Set_Src_Blend(pass, W3DSHADER_SRCBLENDFUNC_ONE); // No matches. return (FALSE); } // Set the PC shader to an equivalant of the PS2 shader. switch (dest_blend[j]) { case ST_ZERO: Set_Dest_Blend(pass, W3DSHADER_DESTBLENDFUNC_ZERO); break; case ST_ONE: Set_Dest_Blend(pass, W3DSHADER_DESTBLENDFUNC_ONE); break; case ST_SRC: Set_Dest_Blend(pass, W3DSHADER_DESTBLENDFUNC_SRC_COLOR); break; case (1 - ST_SRC): Set_Dest_Blend(pass, W3DSHADER_DESTBLENDFUNC_ONE_MINUS_SRC_COLOR); break; case ST_SRC_ALPHA: Set_Dest_Blend(pass, W3DSHADER_DESTBLENDFUNC_SRC_ALPHA); break; case (1 - ST_SRC_ALPHA): Set_Dest_Blend(pass, W3DSHADER_DESTBLENDFUNC_ONE_MINUS_SRC_ALPHA); break; } switch (src_blend[i]) { case ST_ZERO: Set_Src_Blend(pass, W3DSHADER_SRCBLENDFUNC_ZERO); break; case ST_ONE: Set_Src_Blend(pass, W3DSHADER_SRCBLENDFUNC_ONE); break; case ST_SRC_ALPHA: Set_Src_Blend(pass, W3DSHADER_SRCBLENDFUNC_SRC_ALPHA); break; case (1 - ST_SRC_ALPHA): Set_Src_Blend(pass, W3DSHADER_SRCBLENDFUNC_ONE_MINUS_SRC_ALPHA); break; } // A match was made. return (TRUE); } /*********************************************************************************************** * GameMtl::Compute_PS2_Shader_From_PC_Shader -- Change a W3D material to a PS2 W3D material. * W3DSHADER_PRIGRADIENT_ * * * * * * * * * HISTORY: * * 10/26/1999MLL: Created. * *=============================================================================================*/ int GameMtl::Compute_PS2_Shader_From_PC_Shader(int pass) { // These match the PC equation paramaters. static const int a_blend[3] = { ST_ZERO, ST_SRC, ST_DEST, }; static const int b_blend[3] = { ST_ZERO, ST_SRC, ST_DEST, }; static const int d_blend[3] = { ST_ZERO, ST_SRC, ST_DEST, }; static const int c_blend[6] = { ST_ONE, ST_SRC_ALPHA, ST_DEST_ALPHA, }; int i = 0; int j = 0; int k = 0; int l = 0; int equation_value = 0; int param_value[2]; // Get the PC shader values. param_value[0] = Get_Src_Blend(pass); param_value[1] = Get_Dest_Blend(pass); switch (param_value[0]) { case W3DSHADER_SRCBLENDFUNC_ZERO: param_value[0] = ST_ZERO; break; case W3DSHADER_SRCBLENDFUNC_ONE: param_value[0] = ST_ONE; break; case W3DSHADER_SRCBLENDFUNC_SRC_ALPHA: param_value[0] = ST_SRC_ALPHA; break; case W3DSHADER_SRCBLENDFUNC_ONE_MINUS_SRC_ALPHA: param_value[0] = 1 - ST_SRC_ALPHA; break; } // Convert them to the enumeration. switch (param_value[1]) { case W3DSHADER_DESTBLENDFUNC_ZERO: param_value[1] = ST_ZERO; break; case W3DSHADER_DESTBLENDFUNC_ONE: param_value[1] = ST_ONE; break; case W3DSHADER_DESTBLENDFUNC_SRC_COLOR: param_value[1] = ST_SRC; break; case W3DSHADER_DESTBLENDFUNC_ONE_MINUS_SRC_COLOR: param_value[1] = 1 - ST_SRC; break; case W3DSHADER_DESTBLENDFUNC_SRC_ALPHA: param_value[1] = ST_SRC_ALPHA; break; case W3DSHADER_DESTBLENDFUNC_ONE_MINUS_SRC_ALPHA: param_value[1] = 1 - ST_SRC_ALPHA; break; case W3DSHADER_DESTBLENDFUNC_SRC_COLOR_PREFOG: assert(true); break; } // Calculate the PC shader. equation_value = param_value[0] * ST_SRC + param_value[1] * ST_DEST; // Set the shader to be a PS2 Shader. ShaderType = STE_PS2_SHADER; // Find a match for the depth compare test. switch (Get_Depth_Compare(pass)) { case W3DSHADER_DEPTHCOMPARE_PASS_NEVER: Set_Depth_Compare(pass, PSS_DEPTHCOMPARE_PASS_NEVER); break; case W3DSHADER_DEPTHCOMPARE_PASS_LESS: Set_Depth_Compare(pass, PSS_DEPTHCOMPARE_PASS_LESS); break; case W3DSHADER_DEPTHCOMPARE_PASS_LEQUAL: Set_Depth_Compare(pass, PSS_DEPTHCOMPARE_PASS_LEQUAL); break; case W3DSHADER_DEPTHCOMPARE_PASS_ALWAYS: Set_Depth_Compare(pass, PSS_DEPTHCOMPARE_PASS_ALWAYS); break; default: Set_Depth_Compare(pass, PSS_DEPTHCOMPARE_PASS_LEQUAL); break; } // Only 1 gradient matches between the PC and PS2. switch (Get_Pri_Gradient(pass)) { case W3DSHADER_PRIGRADIENT_MODULATE: Set_Pri_Gradient(pass, PSS_PRIGRADIENT_MODULATE); break; default: Set_Pri_Gradient(pass, PSS_PRIGRADIENT_MODULATE); break; } for (i = 0; i < 3; i++) { for (j = 0; j < 3; j++) { for (k = 0; k < 3; k++) { for (l = 0; l < 3; l++) { // Calculate the PS2 shader. If equal, we have found a conversion. if (equation_value == ((a_blend[i] - b_blend[j]) * c_blend[k]) + d_blend[l]) { goto finished; } } } } } // Set the PS2 W3D shader to opaque. Set_PS2_Shader_Param_A(pass, PSS_SRC); Set_PS2_Shader_Param_B(pass, PSS_ZERO); Set_PS2_Shader_Param_C(pass, PSS_ONE); Set_PS2_Shader_Param_D(pass, PSS_ZERO); Set_Depth_Mask(pass,W3DSHADER_DEPTHMASK_DEFAULT); // No matches. return (FALSE); finished: // Set the PS2 shader to an equivalant of the PC shader. switch (a_blend[i]) { case ST_ZERO: Set_PS2_Shader_Param_A(pass, PSS_ZERO); break; case ST_SRC: Set_PS2_Shader_Param_A(pass, PSS_SRC); break; case ST_DEST: Set_PS2_Shader_Param_A(pass, PSS_DEST); break; } switch (b_blend[j]) { case ST_ZERO: Set_PS2_Shader_Param_B(pass, PSS_ZERO); break; case ST_SRC: Set_PS2_Shader_Param_B(pass, PSS_SRC); break; case ST_DEST: Set_PS2_Shader_Param_B(pass, PSS_DEST); break; } switch (d_blend[l]) { case ST_ZERO: Set_PS2_Shader_Param_D(pass, PSS_ZERO); break; case ST_SRC: Set_PS2_Shader_Param_D(pass, PSS_SRC); break; case ST_DEST: Set_PS2_Shader_Param_D(pass, PSS_DEST); break; } switch (c_blend[k]) { case ST_ONE: Set_PS2_Shader_Param_C(pass, PSS_ONE); break; case ST_SRC_ALPHA: Set_PS2_Shader_Param_C(pass, PSS_SRC_ALPHA); break; case ST_DEST_ALPHA: Set_PS2_Shader_Param_C(pass, PSS_DEST_ALPHA); break; } // A match was made. return (TRUE); } void GameMtl::Set_Pass_Count(int passcount) { assert(MainParameterBlock); MainParameterBlock->SetValue(0, TimeValue(0), passcount); } int GameMtl::Get_Pass_Count(void) { assert(MainParameterBlock); int pcount; MainParameterBlock->GetValue(0, TimeValue(0), pcount, FOREVER); return pcount; } Color GameMtl::Get_Ambient(int pass,TimeValue t) { Color val; PassParameterBlock[pass]->GetValue(PB_AMBIENT,t,val,FOREVER); return val; } Color GameMtl::Get_Diffuse(int pass,TimeValue t) { Color val; PassParameterBlock[pass]->GetValue(PB_DIFFUSE,t,val,FOREVER); return val; } Color GameMtl::Get_Specular(int pass,TimeValue t) { Color val; PassParameterBlock[pass]->GetValue(PB_SPECULAR,t,val,FOREVER); return val; } Color GameMtl::Get_Emissive(int pass,TimeValue t) { Color val; PassParameterBlock[pass]->GetValue(PB_EMISSIVE,t,val,FOREVER); return val; } float GameMtl::Get_Shininess(int pass,TimeValue t) { float val; PassParameterBlock[pass]->GetValue(PB_SHININESS,t,val,FOREVER); return val; } float GameMtl::Get_Opacity(int pass,TimeValue t) { float val; PassParameterBlock[pass]->GetValue(PB_OPACITY,t,val,FOREVER); return val; } float GameMtl::Get_Translucency(int pass,TimeValue t) { float val; PassParameterBlock[pass]->GetValue(PB_TRANSLUCENCY,t,val,FOREVER); return val; } int GameMtl::Get_Copy_Specular_To_Diffuse(int pass) { int val; PassParameterBlock[pass]->GetValue(PB_COPY_SPECULAR_TO_DIFFUSE,0,val,FOREVER); return val; } int GameMtl::Get_Mapping_Type(int pass, int stage) { int val = -1; if (stage == 0) PassParameterBlock[pass]->GetValue(PB_STAGE0_MAPPING_TYPE,0,val,FOREVER); else if (stage == 1) PassParameterBlock[pass]->GetValue(PB_STAGE1_MAPPING_TYPE,0,val,FOREVER); return val; } int GameMtl::Get_PSX_Translucency(int pass) { int val; PassParameterBlock[pass]->GetValue(PB_PSX_TRANSLUCENCY,0,val,FOREVER); return val; } int GameMtl::Get_PSX_Lighting(int pass) { int val; PassParameterBlock[pass]->GetValue(PB_PSX_LIGHTING,0,val,FOREVER); return val; } int GameMtl::Get_Depth_Compare(int pass) { int val; PassParameterBlock[pass]->GetValue(PB_DEPTH_COMPARE,0,val,FOREVER); return val; } int GameMtl::Get_Depth_Mask(int pass) { int val; PassParameterBlock[pass]->GetValue(PB_DEPTH_MASK,0,val,FOREVER); return val; } int GameMtl::Get_Alpha_Test(int pass) { int val; PassParameterBlock[pass]->GetValue(PB_ALPHA_TEST,0,val,FOREVER); return val; } int GameMtl::Get_Dest_Blend(int pass) { int val; PassParameterBlock[pass]->GetValue(PB_DEST_BLEND,0,val,FOREVER); return val; } int GameMtl::Get_Pri_Gradient(int pass) { int val; PassParameterBlock[pass]->GetValue(PB_PRI_GRADIENT,0,val,FOREVER); return val; } int GameMtl::Get_Sec_Gradient(int pass) { int val; PassParameterBlock[pass]->GetValue(PB_SEC_GRADIENT,0,val,FOREVER); return val; } int GameMtl::Get_Src_Blend(int pass) { int val; PassParameterBlock[pass]->GetValue(PB_SRC_BLEND,0,val,FOREVER); return val; } int GameMtl::Get_Detail_Color_Func(int pass) { int val; PassParameterBlock[pass]->GetValue(PB_DETAIL_COLOR_FUNC,0,val,FOREVER); return val; } int GameMtl::Get_Detail_Alpha_Func(int pass) { int val; PassParameterBlock[pass]->GetValue(PB_DETAIL_ALPHA_FUNC,0,val,FOREVER); return val; } int GameMtl::Get_Texture_Enable(int pass,int stage) { int val; if (stage == 0) { PassParameterBlock[pass]->GetValue(PB_STAGE0_TEXTURE_ENABLE,0,val,FOREVER); } else { PassParameterBlock[pass]->GetValue(PB_STAGE1_TEXTURE_ENABLE,0,val,FOREVER); } return val; } int GameMtl::Get_Texture_Publish(int pass,int stage) { int val; if (stage == 0) { PassParameterBlock[pass]->GetValue(PB_STAGE0_TEXTURE_PUBLISH,0,val,FOREVER); } else { PassParameterBlock[pass]->GetValue(PB_STAGE1_TEXTURE_PUBLISH,0,val,FOREVER); } return val; } int GameMtl::Get_Texture_Resize(int pass,int stage) { int val; if (stage == 0) { PassParameterBlock[pass]->GetValue(PB_STAGE0_TEXTURE_RESIZE,0,val,FOREVER); } else { PassParameterBlock[pass]->GetValue(PB_STAGE1_TEXTURE_RESIZE,0,val,FOREVER); } return val; } int GameMtl::Get_Texture_No_Mipmap(int pass,int stage) { int val; if (stage == 0) { PassParameterBlock[pass]->GetValue(PB_STAGE0_TEXTURE_NO_MIPMAP,0,val,FOREVER); } else { PassParameterBlock[pass]->GetValue(PB_STAGE1_TEXTURE_NO_MIPMAP,0,val,FOREVER); } return val; } int GameMtl::Get_Texture_Clamp_U(int pass,int stage) { int val; if (stage == 0) { PassParameterBlock[pass]->GetValue(PB_STAGE0_TEXTURE_CLAMP_U,0,val,FOREVER); } else { PassParameterBlock[pass]->GetValue(PB_STAGE1_TEXTURE_CLAMP_U,0,val,FOREVER); } return val; } int GameMtl::Get_Texture_Clamp_V(int pass,int stage) { int val; if (stage == 0) { PassParameterBlock[pass]->GetValue(PB_STAGE0_TEXTURE_CLAMP_V,0,val,FOREVER); } else { PassParameterBlock[pass]->GetValue(PB_STAGE1_TEXTURE_CLAMP_V,0,val,FOREVER); } return val; } int GameMtl::Get_Texture_No_LOD(int pass,int stage) { int val; if (stage == 0) { PassParameterBlock[pass]->GetValue(PB_STAGE0_TEXTURE_NO_LOD,0,val,FOREVER); } else { PassParameterBlock[pass]->GetValue(PB_STAGE1_TEXTURE_NO_LOD,0,val,FOREVER); } return val; } int GameMtl::Get_Texture_Alpha_Bitmap(int pass,int stage) { int val; if (stage == 0) { PassParameterBlock[pass]->GetValue(PB_STAGE0_TEXTURE_ALPHA_BITMAP,0,val,FOREVER); } else { PassParameterBlock[pass]->GetValue(PB_STAGE1_TEXTURE_ALPHA_BITMAP,0,val,FOREVER); } return val; } int GameMtl::Get_Texture_Hint(int pass,int stage) { int val; if (stage == 0) { PassParameterBlock[pass]->GetValue(PB_STAGE0_TEXTURE_HINT,0,val,FOREVER); } else { PassParameterBlock[pass]->GetValue(PB_STAGE1_TEXTURE_HINT,0,val,FOREVER); } return val; } int GameMtl::Get_Texture_Display(int pass,int stage) { int val; if (stage == 0) { PassParameterBlock[pass]->GetValue(PB_STAGE0_TEXTURE_DISPLAY,0,val,FOREVER); } else { PassParameterBlock[pass]->GetValue(PB_STAGE1_TEXTURE_DISPLAY,0,val,FOREVER); } return val; } float GameMtl::Get_Texture_Frame_Rate(int pass,int stage) { float val; if (stage == 0) { PassParameterBlock[pass]->GetValue(PB_STAGE0_TEXTURE_FRAME_RATE,0,val,FOREVER); } else { PassParameterBlock[pass]->GetValue(PB_STAGE1_TEXTURE_FRAME_RATE,0,val,FOREVER); } return val; } int GameMtl::Get_Texture_Frame_Count(int pass,int stage) { int val; if (stage == 0) { PassParameterBlock[pass]->GetValue(PB_STAGE0_TEXTURE_FRAME_COUNT,0,val,FOREVER); } else { PassParameterBlock[pass]->GetValue(PB_STAGE1_TEXTURE_FRAME_COUNT,0,val,FOREVER); } return val; } int GameMtl::Get_Texture_Anim_Type(int pass,int stage) { int val; if (stage == 0) { PassParameterBlock[pass]->GetValue(PB_STAGE0_TEXTURE_ANIM_TYPE,0,val,FOREVER); } else { PassParameterBlock[pass]->GetValue(PB_STAGE1_TEXTURE_ANIM_TYPE,0,val,FOREVER); } return val; } Texmap * GameMtl::Get_Texture(int pass,int stage) { return GetSubTexmap(pass_stage_to_texmap_index(pass,stage)); } int GameMtl::Get_PS2_Shader_Param_A(int pass) { int val; PassParameterBlock[pass]->GetValue(PB_PS2_SHADER_PARAM_A,0,val,FOREVER); return val; } int GameMtl::Get_PS2_Shader_Param_B(int pass) { int val; PassParameterBlock[pass]->GetValue(PB_PS2_SHADER_PARAM_B,0,val,FOREVER); return val; } int GameMtl::Get_PS2_Shader_Param_C(int pass) { int val; PassParameterBlock[pass]->GetValue(PB_PS2_SHADER_PARAM_C,0,val,FOREVER); return val; } int GameMtl::Get_PS2_Shader_Param_D(int pass) { int val; PassParameterBlock[pass]->GetValue(PB_PS2_SHADER_PARAM_D,0,val,FOREVER); return val; } int GameMtl::Get_Map_Channel(int pass,int stage) { int val; if (stage == 0) { PassParameterBlock[pass]->GetValue(PB_STAGE0_MAP_CHANNEL,0,val,FOREVER); } else { PassParameterBlock[pass]->GetValue(PB_STAGE1_MAP_CHANNEL,0,val,FOREVER); } return val; } void GameMtl::Set_Ambient(int pass,TimeValue t,Color val) { assert((pass >=0) && (pass < W3dMaterialClass::MAX_PASSES)); assert(PassParameterBlock[pass]); PassParameterBlock[pass]->SetValue(PB_AMBIENT, t, val); } void GameMtl::Set_Diffuse(int pass,TimeValue t,Color val) { assert((pass >=0) && (pass < W3dMaterialClass::MAX_PASSES)); assert(PassParameterBlock[pass]); PassParameterBlock[pass]->SetValue(PB_DIFFUSE, t, val); } void GameMtl::Set_Specular(int pass,TimeValue t,Color val) { assert((pass >=0) && (pass < W3dMaterialClass::MAX_PASSES)); assert(PassParameterBlock[pass]); PassParameterBlock[pass]->SetValue(PB_SPECULAR, t, val); } void GameMtl::Set_Emissive(int pass,TimeValue t,Color val) { assert((pass >=0) && (pass < W3dMaterialClass::MAX_PASSES)); assert(PassParameterBlock[pass]); PassParameterBlock[pass]->SetValue(PB_EMISSIVE, t, val); } void GameMtl::Set_Shininess(int pass,TimeValue t,float val) { assert((pass >=0) && (pass < W3dMaterialClass::MAX_PASSES)); assert(PassParameterBlock[pass]); PassParameterBlock[pass]->SetValue(PB_SHININESS, t, val); } void GameMtl::Set_Opacity(int pass,TimeValue t,float val) { assert((pass >=0) && (pass < W3dMaterialClass::MAX_PASSES)); assert(PassParameterBlock[pass]); PassParameterBlock[pass]->SetValue(PB_OPACITY, t, val); } void GameMtl::Set_Translucency(int pass,TimeValue t,float val) { assert((pass >=0) && (pass < W3dMaterialClass::MAX_PASSES)); assert(PassParameterBlock[pass]); PassParameterBlock[pass]->SetValue(PB_TRANSLUCENCY, t, val); } void GameMtl::Set_Copy_Specular_To_Diffuse(int pass,bool val) { assert((pass >=0) && (pass < W3dMaterialClass::MAX_PASSES)); assert(PassParameterBlock[pass]); PassParameterBlock[pass]->SetValue(PB_COPY_SPECULAR_TO_DIFFUSE, 0, val); } void GameMtl::Set_Mapping_Type(int pass,int stage,int val) { assert((pass >=0) && (pass < W3dMaterialClass::MAX_PASSES)); assert(PassParameterBlock[pass]); if (stage == 0) PassParameterBlock[pass]->SetValue(PB_STAGE0_MAPPING_TYPE, 0, val); else if (stage == 1) PassParameterBlock[pass]->SetValue(PB_STAGE1_MAPPING_TYPE, 0, val); } void GameMtl::Set_PSX_Translucency(int pass,int val) { assert((pass >=0) && (pass < W3dMaterialClass::MAX_PASSES)); assert(PassParameterBlock[pass]); PassParameterBlock[pass]->SetValue(PB_PSX_TRANSLUCENCY, 0, val); } void GameMtl::Set_PSX_Lighting(int pass,bool val) { assert((pass >=0) && (pass < W3dMaterialClass::MAX_PASSES)); assert(PassParameterBlock[pass]); PassParameterBlock[pass]->SetValue(PB_PSX_LIGHTING, 0, val); } void GameMtl::Set_Depth_Compare(int pass,int val) { assert((pass >=0) && (pass < W3dMaterialClass::MAX_PASSES)); assert(PassParameterBlock[pass]); PassParameterBlock[pass]->SetValue(PB_DEPTH_COMPARE, 0, val); } void GameMtl::Set_Depth_Mask(int pass,int val) { assert((pass >=0) && (pass < W3dMaterialClass::MAX_PASSES)); assert(PassParameterBlock[pass]); PassParameterBlock[pass]->SetValue(PB_DEPTH_MASK, 0, val); } void GameMtl::Set_Alpha_Test(int pass,int val) { assert((pass >=0) && (pass < W3dMaterialClass::MAX_PASSES)); assert(PassParameterBlock[pass]); PassParameterBlock[pass]->SetValue(PB_ALPHA_TEST, 0, val); } void GameMtl::Set_Dest_Blend(int pass,int val) { assert((pass >=0) && (pass < W3dMaterialClass::MAX_PASSES)); assert(PassParameterBlock[pass]); PassParameterBlock[pass]->SetValue(PB_DEST_BLEND, 0, val); } void GameMtl::Set_Pri_Gradient(int pass,int val) { assert((pass >=0) && (pass < W3dMaterialClass::MAX_PASSES)); assert(PassParameterBlock[pass]); PassParameterBlock[pass]->SetValue(PB_PRI_GRADIENT, 0, val); } void GameMtl::Set_Sec_Gradient(int pass,int val) { assert((pass >=0) && (pass < W3dMaterialClass::MAX_PASSES)); assert(PassParameterBlock[pass]); PassParameterBlock[pass]->SetValue(PB_SEC_GRADIENT, 0, val); } void GameMtl::Set_Src_Blend(int pass,int val) { assert((pass >=0) && (pass < W3dMaterialClass::MAX_PASSES)); assert(PassParameterBlock[pass]); PassParameterBlock[pass]->SetValue(PB_SRC_BLEND, 0, val); } void GameMtl::Set_Detail_Color_Func(int pass,int val) { assert((pass >=0) && (pass < W3dMaterialClass::MAX_PASSES)); assert(PassParameterBlock[pass]); PassParameterBlock[pass]->SetValue(PB_DETAIL_COLOR_FUNC, 0, val); } void GameMtl::Set_Detail_Alpha_Func(int pass,int val) { assert((pass >=0) && (pass < W3dMaterialClass::MAX_PASSES)); assert(PassParameterBlock[pass]); PassParameterBlock[pass]->SetValue(PB_DETAIL_ALPHA_FUNC, 0, val); } void GameMtl::Set_Texture_Enable(int pass,int stage,bool val) { assert((pass >=0) && (pass < W3dMaterialClass::MAX_PASSES)); assert(PassParameterBlock[pass]); if (stage == 0) { PassParameterBlock[pass]->SetValue(PB_STAGE0_TEXTURE_ENABLE, 0, val); } else { PassParameterBlock[pass]->SetValue(PB_STAGE1_TEXTURE_ENABLE, 0, val); } } void GameMtl::Set_Texture_Publish(int pass,int stage,bool val) { assert((pass >=0) && (pass < W3dMaterialClass::MAX_PASSES)); assert(PassParameterBlock[pass]); if (stage == 0) { PassParameterBlock[pass]->SetValue(PB_STAGE0_TEXTURE_PUBLISH, 0, val); } else { PassParameterBlock[pass]->SetValue(PB_STAGE1_TEXTURE_PUBLISH, 0, val); } } void GameMtl::Set_Texture_Resize(int pass,int stage,bool val) { assert((pass >=0) && (pass < W3dMaterialClass::MAX_PASSES)); assert(PassParameterBlock[pass]); if (stage == 0) { PassParameterBlock[pass]->SetValue(PB_STAGE0_TEXTURE_RESIZE, 0, val); } else { PassParameterBlock[pass]->SetValue(PB_STAGE1_TEXTURE_RESIZE, 0, val); } } void GameMtl::Set_Texture_No_Mipmap(int pass,int stage,bool val) { assert((pass >=0) && (pass < W3dMaterialClass::MAX_PASSES)); assert(PassParameterBlock[pass]); if (stage == 0) { PassParameterBlock[pass]->SetValue(PB_STAGE0_TEXTURE_NO_MIPMAP, 0, val); } else { PassParameterBlock[pass]->SetValue(PB_STAGE1_TEXTURE_NO_MIPMAP, 0, val); } } void GameMtl::Set_Texture_Clamp_U(int pass,int stage,bool val) { assert((pass >=0) && (pass < W3dMaterialClass::MAX_PASSES)); assert(PassParameterBlock[pass]); if (stage == 0) { PassParameterBlock[pass]->SetValue(PB_STAGE0_TEXTURE_CLAMP_U, 0, val); } else { PassParameterBlock[pass]->SetValue(PB_STAGE1_TEXTURE_CLAMP_U, 0, val); } } void GameMtl::Set_Texture_Clamp_V(int pass,int stage,bool val) { assert((pass >=0) && (pass < W3dMaterialClass::MAX_PASSES)); assert(PassParameterBlock[pass]); if (stage == 0) { PassParameterBlock[pass]->SetValue(PB_STAGE0_TEXTURE_CLAMP_V, 0, val); } else { PassParameterBlock[pass]->SetValue(PB_STAGE1_TEXTURE_CLAMP_V, 0, val); } } void GameMtl::Set_Texture_No_LOD(int pass,int stage,bool val) { assert((pass >=0) && (pass < W3dMaterialClass::MAX_PASSES)); assert(PassParameterBlock[pass]); if (stage == 0) { PassParameterBlock[pass]->SetValue(PB_STAGE0_TEXTURE_NO_LOD, 0, val); } else { PassParameterBlock[pass]->SetValue(PB_STAGE1_TEXTURE_NO_LOD, 0, val); } } void GameMtl::Set_Texture_Alpha_Bitmap(int pass,int stage,bool val) { assert((pass >=0) && (pass < W3dMaterialClass::MAX_PASSES)); assert(PassParameterBlock[pass]); if (stage == 0) { PassParameterBlock[pass]->SetValue(PB_STAGE0_TEXTURE_ALPHA_BITMAP, 0, val); } else { PassParameterBlock[pass]->SetValue(PB_STAGE1_TEXTURE_ALPHA_BITMAP, 0, val); } } void GameMtl::Set_Texture_Hint(int pass,int stage,int val) { assert((pass >=0) && (pass < W3dMaterialClass::MAX_PASSES)); assert(PassParameterBlock[pass]); if (stage == 0) { PassParameterBlock[pass]->SetValue(PB_STAGE0_TEXTURE_HINT, 0, val); } else { PassParameterBlock[pass]->SetValue(PB_STAGE1_TEXTURE_HINT, 0, val); } } void GameMtl::Set_Texture_Display(int pass,int stage,bool val) { assert((pass >=0) && (pass < W3dMaterialClass::MAX_PASSES)); assert(PassParameterBlock[pass]); // clear all tex display flags for (int pi = 0; piSetValue(PB_STAGE0_TEXTURE_DISPLAY, 0, false); PassParameterBlock[pi]->SetValue(PB_STAGE1_TEXTURE_DISPLAY, 0, false); } // set the one we want if (val == true) { if (stage == 0) { PassParameterBlock[pass]->SetValue(PB_STAGE0_TEXTURE_DISPLAY, 0, val); } else { PassParameterBlock[pass]->SetValue(PB_STAGE1_TEXTURE_DISPLAY, 0, val); } SetMtlFlag( MTL_TEX_DISPLAY_ENABLED, TRUE ); SetActiveTexmap(Texture[pass][stage]); NotifyDependents(FOREVER,PART_ALL,REFMSG_CHANGE); } else { SetMtlFlag( MTL_TEX_DISPLAY_ENABLED, FALSE ); SetActiveTexmap(NULL); NotifyDependents(FOREVER,PART_ALL,REFMSG_CHANGE); } // tell dialog to refresh... if (MaterialDialog) { MaterialDialog->ReloadDialog(); } if (IsMultiMtl()) { // Loop through all sub materials of the multi-material. for (unsigned mi = 0; mi < NumSubMtls(); mi++) { // Only change those that are W3D materials. if (GetSubMtl(mi)->ClassID() == GameMaterialClassID) { int pass; for (pass = 0; pass < ((GameMtl*)(GetSubMtl(mi)))->Get_Pass_Count(); pass++) { if (((GameMtl*)(GetSubMtl(mi)))->Get_Texture_Enable(pass, stage)) { (GetSubMtl(mi))->SetMtlFlag(MTL_TEX_DISPLAY_ENABLED, TRUE); } } } } } } void GameMtl::Set_Texture_Frame_Rate(int pass,int stage,float val) { assert((pass >=0) && (pass < W3dMaterialClass::MAX_PASSES)); assert(PassParameterBlock[pass]); if (stage == 0) { PassParameterBlock[pass]->SetValue(PB_STAGE0_TEXTURE_FRAME_RATE, 0, val); } else { PassParameterBlock[pass]->SetValue(PB_STAGE1_TEXTURE_FRAME_RATE, 0, val); } } void GameMtl::Set_Texture_Frame_Count(int pass,int stage,int val) { assert((pass >=0) && (pass < W3dMaterialClass::MAX_PASSES)); assert(PassParameterBlock[pass]); if (stage == 0) { PassParameterBlock[pass]->SetValue(PB_STAGE0_TEXTURE_FRAME_COUNT, 0, val); } else { PassParameterBlock[pass]->SetValue(PB_STAGE1_TEXTURE_FRAME_COUNT, 0, val); } } void GameMtl::Set_Texture_Anim_Type(int pass,int stage,int val) { assert((pass >=0) && (pass < W3dMaterialClass::MAX_PASSES)); assert(PassParameterBlock[pass]); if (stage == 0) { PassParameterBlock[pass]->SetValue(PB_STAGE0_TEXTURE_ANIM_TYPE, 0, val); } else { PassParameterBlock[pass]->SetValue(PB_STAGE1_TEXTURE_ANIM_TYPE, 0, val); } } void GameMtl::Set_Texture(int pass,int stage,Texmap * tex) { SetSubTexmap(pass_stage_to_texmap_index(pass,stage),tex); } void GameMtl::Set_PS2_Shader_Param_A(int pass,int val) { assert((pass >=0) && (pass < W3dMaterialClass::MAX_PASSES)); assert(PassParameterBlock[pass]); PassParameterBlock[pass]->SetValue(PB_PS2_SHADER_PARAM_A, 0, val); } void GameMtl::Set_PS2_Shader_Param_B(int pass,int val) { assert((pass >=0) && (pass < W3dMaterialClass::MAX_PASSES)); assert(PassParameterBlock[pass]); PassParameterBlock[pass]->SetValue(PB_PS2_SHADER_PARAM_B, 0, val); } void GameMtl::Set_PS2_Shader_Param_C(int pass,int val) { assert((pass >=0) && (pass < W3dMaterialClass::MAX_PASSES)); assert(PassParameterBlock[pass]); PassParameterBlock[pass]->SetValue(PB_PS2_SHADER_PARAM_C, 0, val); } void GameMtl::Set_PS2_Shader_Param_D(int pass,int val) { assert((pass >=0) && (pass < W3dMaterialClass::MAX_PASSES)); assert(PassParameterBlock[pass]); PassParameterBlock[pass]->SetValue(PB_PS2_SHADER_PARAM_D, 0, val); } void GameMtl::Set_Map_Channel(int pass,int stage,int val) { assert((pass >=0) && (pass < W3dMaterialClass::MAX_PASSES)); assert(PassParameterBlock[pass]); if (stage == 0) { PassParameterBlock[pass]->SetValue(PB_STAGE0_MAP_CHANNEL, 0, val); } else { PassParameterBlock[pass]->SetValue(PB_STAGE1_MAP_CHANNEL, 0, val); } if (Texture[pass][stage] != NULL) { UVGen * uvgen = Texture[pass][stage]->GetTheUVGen(); if (uvgen != NULL) { uvgen->SetMapChannel(val); } } NotifyDependents(FOREVER,PART_ALL,REFMSG_CHANGE); } // This returns the mapping args string buffer for that pass (and stage) after // assuring that it can contain a string of length 'len' (if len is 0 no // resizing will be performed).. char * GameMtl::Get_Mapping_Arg_Buffer(int pass, int stage, unsigned int len) { assert(pass >= 0); assert(pass < W3dMaterialClass::MAX_PASSES); assert(stage >= 0); assert(stage < W3dMaterialClass::MAX_STAGES); if (MapperArgLen[pass][stage] < len) { MapperArgLen[pass][stage] = len + 10; // New length char *temp = new char[MapperArgLen[pass][stage] + 1]; if (MapperArg[pass][stage]) { assert(strlen(MapperArg[pass][stage]) <= MapperArgLen[pass][stage]); strcpy(temp, MapperArg[pass][stage]); delete [] (MapperArg[pass][stage]); MapperArg[pass][stage] = NULL; } MapperArg[pass][stage] = temp; } return MapperArg[pass][stage]; } int GameMtl::pass_stage_to_texmap_index(int pass,int stage) { assert((pass >= 0) && (pass < W3dMaterialClass::MAX_PASSES)); assert((stage >= 0) && (stage < W3dMaterialClass::MAX_STAGES)); return pass * W3dMaterialClass::MAX_STAGES + stage; } void GameMtl::texmap_index_to_pass_stage(int index,int * set_pass,int * set_stage) { *set_pass = index / W3dMaterialClass::MAX_STAGES; *set_stage = index % W3dMaterialClass::MAX_STAGES; } float GameMtl::EvalDisplacement(ShadeContext& sc) { float displacement = 0.0F; if (DisplacementMap != NULL) { displacement = DisplacementMap->EvalMono(sc); displacement = displacement * DisplacementAmt; } return displacement; } Interval GameMtl::DisplacementValidity(TimeValue t) { return FOREVER; } void GameMtlPostLoad::proc(ILoad *iload) { if (IsOld) { m->Reset(); m->Set_Pass_Count(1); m->Set_Ambient(0,0,AmbientCoeff); m->Set_Diffuse(0,0,Diffuse * DiffuseCoeff); m->Set_Specular(0,0,Specular * SpecularCoeff); m->Set_Emissive(0,0,EmissiveCoeff); m->Set_Opacity(0,0,Opacity); m->Set_Translucency(0,0,Translucency); m->Set_Shininess(0,0,Shininess); m->Set_Mapping_Type(0,0,DCTMappingType); Texmap * tex = (*(m->Maps))[ID_DI].Map; if ((tex) && (tex->ClassID() == Class_ID(BMTEX_CLASS_ID,0))) { m->Set_Texture(0,0,tex); m->Set_Texture_Enable(0,0,true); m->Set_Texture_Frame_Rate(0,0,DCTFrameRate); m->Set_Texture_Frame_Count(0,0,DCTFrames); if (m->TestMtlFlag(MTL_TEX_DISPLAY_ENABLED)) { m->Set_Texture_Display(0,0,true); } } m->ReplaceReference(GameMtl::REF_MAPS,NULL); } // older material formats did not save the map channel and will default to zero, // we need to change the map channel to one in this case. for (int pass = 0; pass < W3dMaterialClass::MAX_PASSES; pass++) { for (int stage = 0; stage < W3dMaterialClass::MAX_STAGES; stage++) { if ((m->Get_Map_Channel(pass,stage) < 1) || (m->Get_Map_Channel(pass,stage) > 99)) { m->Set_Map_Channel(pass,stage,1); } } } // Now that I've removed the UI for the RESIZE and NO_MIPMAP options in the texture // pane, we initialize the No_LOD setting to the existing NO_MIPMAP setting // NOTE: I created a new flag for gamemtl which gets set when this conversion takes // place for the first time. if (m->Get_Flag(GAMEMTL_CONVERTED_TO_NOLOD) == false) { for (int pass = 0; pass < W3dMaterialClass::MAX_PASSES; pass++) { for (int stage = 0; stage < W3dMaterialClass::MAX_STAGES; stage++) { bool no_lod = m->Get_Texture_No_Mipmap(pass,stage) != 0; m->Set_Texture_No_LOD(pass,stage,no_lod); } } m->Set_Flag(GAMEMTL_CONVERTED_TO_NOLOD,true); } delete this; }