| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967 |
- /*
- ** Command & Conquer Generals(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 <http://www.gnu.org/licenses/>.
- */
- /***********************************************************************************************
- *** C O N F I D E N T I A L --- W E S T W O O D S T U D I O S ***
- ***********************************************************************************************
- * *
- * Project Name : ww3d *
- * *
- * $Archive:: /Commando/Code/ww3d2/meshmatdesc.cpp $*
- * *
- * Original Author:: Greg Hjelstrom *
- * *
- * $Author:: Jani_p $*
- * *
- * $Modtime:: 7/13/01 1:38p $*
- * *
- * $Revision:: 20 $*
- * *
- *---------------------------------------------------------------------------------------------*
- * Functions: *
- * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
- #include "meshmatdesc.h"
- #include "texture.h"
- #include "vertmaterial.h"
- #include "realcrc.h"
- #include "dx8wrapper.h"
- #include "dx8caps.h"
- /**************************************************************************************************
- **
- **
- ** MatBufferClass Implementation
- **
- **
- **************************************************************************************************/
- MatBufferClass::MatBufferClass(const MatBufferClass & that) :
- ShareBufferClass<VertexMaterialClass *>(that)
- {
- // add a reference for each pointer that was copied...
- for (int i=0; i<Count; i++) {
- if (Array[i]) {
- Array[i]->Add_Ref();
- }
- }
- }
- MatBufferClass::~MatBufferClass(void)
- {
- for (int i=0; i<Count; i++) {
- REF_PTR_RELEASE(Array[i]);
- }
- }
- void MatBufferClass::Set_Element(int index,VertexMaterialClass * mat)
- {
- REF_PTR_SET(Array[index],mat);
- }
- VertexMaterialClass * MatBufferClass::Get_Element(int index)
- {
- if (Array[index]) {
- Array[index]->Add_Ref();
- }
- return Array[index];
- }
- VertexMaterialClass * MatBufferClass::Peek_Element(int index)
- {
- return Array[index];
- }
- /**************************************************************************************************
- **
- **
- ** TexBufferClass Implementation
- **
- **
- **************************************************************************************************/
- TexBufferClass::TexBufferClass(const TexBufferClass & that) :
- ShareBufferClass<TextureClass *>(that)
- {
- // add a reference for each pointer that was copied...
- for (int i=0; i<Count; i++) {
- if (Array[i]) {
- Array[i]->Add_Ref();
- }
- }
- }
- TexBufferClass::~TexBufferClass(void)
- {
- for (int i=0;i<Count;i++) {
- REF_PTR_RELEASE(Array[i]);
- }
- }
- void TexBufferClass::Set_Element(int index,TextureClass * tex)
- {
- REF_PTR_SET(Array[index],tex);
- }
- TextureClass * TexBufferClass::Get_Element(int index)
- {
- if (Array[index]) {
- Array[index]->Add_Ref();
- }
- return Array[index];
- }
- TextureClass * TexBufferClass::Peek_Element(int index)
- {
- return Array[index];
- }
- /**************************************************************************************************
- **
- **
- ** UVBufferClass Implementation
- **
- **
- **************************************************************************************************/
- UVBufferClass::UVBufferClass(const UVBufferClass & that) :
- ShareBufferClass<Vector2>(that)
- {
- CRC = that.CRC;
- }
- bool UVBufferClass::operator == (const UVBufferClass & that)
- {
- // NOTE: this only works if you've properly called Update_CRC after filling the array
- return (CRC == that.CRC);
- }
- bool UVBufferClass::Is_Equal_To(const UVBufferClass & that)
- {
- // NOTE: this only works if you've properly called Update_CRC after filling the array
- return (CRC == that.CRC);
- }
- void UVBufferClass::Update_CRC(void)
- {
- CRC = CRC_Memory((unsigned char *)Get_Array(),Get_Count() * sizeof(Vector2));
- }
- /**************************************************************************************************
- **
- **
- ** MeshMatDescClass Implementation
- **
- **
- **************************************************************************************************/
- ShaderClass MeshMatDescClass::NullShader(0); // Used to mark no shader data
- MeshMatDescClass::MeshMatDescClass(void) :
- PassCount(1),
- VertexCount(0),
- PolyCount(0)
- {
- for (int array=0;array < MAX_COLOR_ARRAYS; array++) {
- ColorArray[array] = NULL;
- }
- for (int uvarray=0;uvarray<MAX_UV_ARRAYS;uvarray++) {
- UV[uvarray] = NULL;
- }
- for (int pass=0; pass < MAX_PASSES; pass++) {
- for (int stage=0; stage < MAX_TEX_STAGES; stage++) {
- UVSource[pass][stage] = -1;
- Texture[pass][stage] = NULL;
- TextureArray[pass][stage] = NULL;
- }
- // UVIndex[pass] = NULL;
- DCGSource[pass] = VertexMaterialClass::MATERIAL;
- DIGSource[pass] = VertexMaterialClass::MATERIAL;
- Shader[pass] = 0; //ShaderClass::_PresetOpaqueSolidShader;
- Material[pass] = NULL;
- ShaderArray[pass] = NULL;
- MaterialArray[pass] = NULL;
- }
- }
- MeshMatDescClass::MeshMatDescClass(const MeshMatDescClass & that) :
- PassCount(1),
- VertexCount(0),
- PolyCount(0)
- {
- int pass;
- int stage;
- int array;
- // init everything to NULL
- for (array=0;array < MAX_COLOR_ARRAYS; array++) {
- ColorArray[array] = NULL;
- }
- for (array=0;array < MAX_UV_ARRAYS; array++) {
- UV[array] = NULL;
- }
- for (pass=0; pass < MAX_PASSES; pass++) {
- for (stage=0; stage < MAX_TEX_STAGES; stage++) {
- UVSource[pass][stage] = -1;
- Texture[pass][stage] = NULL;
- TextureArray[pass][stage] = NULL;
- }
- // UVIndex[pass] = NULL;
- DCGSource[pass] = VertexMaterialClass::MATERIAL;
- DIGSource[pass] = VertexMaterialClass::MATERIAL;
- Shader[pass] = 0; //ShaderClass::_PresetOpaqueSolidShader;
- Material[pass] = NULL;
- ShaderArray[pass] = NULL;
- MaterialArray[pass] = NULL;
- }
- *this = that;
- }
- MeshMatDescClass &
- MeshMatDescClass::operator = (const MeshMatDescClass & that)
- {
- if (this != &that) {
-
- PassCount = that.PassCount;
- VertexCount = that.VertexCount;
- PolyCount = that.PolyCount;
- for (int array=0; array<MAX_COLOR_ARRAYS; array++) {
- REF_PTR_SET(ColorArray[array],that.ColorArray[array]);
- }
- for (int uvarray=0; uvarray<MAX_UV_ARRAYS; uvarray++) {
- REF_PTR_SET(UV[uvarray],that.UV[uvarray]);
- }
- for (int pass=0; pass<MAX_PASSES; pass++) {
- for (int stage=0; stage < MAX_TEX_STAGES; stage++) {
- UVSource[pass][stage] = that.UVSource[pass][stage];
- REF_PTR_SET(Texture[pass][stage],that.Texture[pass][stage]);
-
- // make our own array of texture pointers.
- REF_PTR_RELEASE(TextureArray[pass][stage]);
- if (that.TextureArray[pass][stage]) {
- TextureArray[pass][stage] = NEW_REF(TexBufferClass,(*that.TextureArray[pass][stage]));
- }
- }
- // REF_PTR_SET(UVIndex [pass], that.UVIndex [pass]);
- DCGSource[pass] = that.DCGSource[pass];
- DIGSource[pass] = that.DIGSource[pass];
- Shader[pass] = that.Shader[pass];
- REF_PTR_SET(Material[pass],that.Material[pass]);
- // make our own arrays of shaders and vertex material pointers
- // NOTE: We don't just add-ref these arrays, we make our own copies.
- // The only time we add-ref these arrays are when we make alternate material
- // representations within this mesh... Then we re-use the same arrays in different
- // passes...
- REF_PTR_RELEASE(MaterialArray[pass]);
- if (that.MaterialArray[pass]) {
- MaterialArray[pass] = NEW_REF(MatBufferClass,(*that.MaterialArray[pass]));
- }
- REF_PTR_RELEASE(ShaderArray[pass]);
- if (that.ShaderArray[pass]) {
- ShaderArray[pass] = NEW_REF(ShareBufferClass<ShaderClass>,(*that.ShaderArray[pass]));
- }
- }
- }
- return *this;
- }
- MeshMatDescClass::~MeshMatDescClass(void)
- {
- Reset(0,0,0);
- }
- TextureClass * MeshMatDescClass::Get_Single_Texture(int pass,int stage) const
- {
- if (Texture[pass][stage]) {
- Texture[pass][stage]->Add_Ref();
- }
- return Texture[pass][stage];
- }
- void MeshMatDescClass::Reset(int polycount,int vertcount,int passcount)
- {
- PolyCount = polycount;
- VertexCount = vertcount;
- PassCount = passcount;
- for (int array=0; array<MAX_COLOR_ARRAYS; array++) {
- REF_PTR_RELEASE(ColorArray[array]);
- }
- for (int uvarray=0; uvarray<MAX_UV_ARRAYS; uvarray++) {
- REF_PTR_RELEASE(UV[uvarray]);
- }
- for (int pass=0;pass<MAX_PASSES;pass++) {
- for (int stage=0; stage < MAX_TEX_STAGES; stage++) {
- UVSource[pass][stage] = -1;
- REF_PTR_RELEASE(Texture[pass][stage]);
- REF_PTR_RELEASE(TextureArray[pass][stage]);
- }
-
- // REF_PTR_RELEASE(UVIndex[pass]);
- DCGSource[pass] = VertexMaterialClass::MATERIAL;
- DIGSource[pass] = VertexMaterialClass::MATERIAL;
- Shader[pass] = 0;
- REF_PTR_RELEASE(ShaderArray[pass]);
-
- REF_PTR_RELEASE(Material[pass]);
- REF_PTR_RELEASE(MaterialArray[pass]);
-
- }
- }
- void MeshMatDescClass::Init_Alternate(MeshMatDescClass & default_materials,MeshMatDescClass & alternate_materials)
- {
- // just copy the counts
- PassCount = default_materials.PassCount;
- VertexCount = default_materials.VertexCount;
- PolyCount = default_materials.PolyCount;
- // Color arrays
- for (int array=0; array<MAX_COLOR_ARRAYS; array++) {
- if (alternate_materials.ColorArray[array] != NULL) {
- REF_PTR_SET(ColorArray[array],alternate_materials.ColorArray[array]);
- } else {
- REF_PTR_SET(ColorArray[array],default_materials.ColorArray[array]);
- }
- }
- // Copy the uv-arrays from the alternate materials to start. Needed uv arrays from
- // the default material set will be brought over as encountered below
- for (int i=0; i<alternate_materials.Get_UV_Array_Count(); i++) {
- REF_PTR_SET(UV[i],alternate_materials.UV[i]);
- }
- // add-ref the arrays in default_materials except when the same array is present in alternate_materials
- for (int pass = 0; pass < MAX_PASSES; pass++) {
- for (int stage = 0; stage < MAX_TEX_STAGES; stage++) {
- // UV Coorindate arrays, Each UVSource[pass][stage] which is -1 in the alternate_materials
- // but not -1 in the default_materials causes us to copy over a uv array from the default_materials
- // and set its index into our UVSource array.
- if (alternate_materials.UVSource[pass][stage] == -1) {
- if (default_materials.UVSource[pass][stage] != -1) {
-
- // Look up the uv array in default_materials that we need to bring over.
- int default_uv_source = default_materials.UVSource[pass][stage];
- UVBufferClass * uvarray = default_materials.UV[default_uv_source];
- int found_index = -1;
- // Check if we already have it.
- for (int i=0; i<Get_UV_Array_Count(); i++) {
- if (uvarray->Get_CRC() == UV[i]->Get_CRC()) {
- found_index = i;
- break;
- }
- }
- // If we already have it, just set the source index. Otherwise add-ref it
- // into a new slot in our uv array and set that index.
- if (found_index != -1) {
- UVSource[pass][stage] = found_index;
- } else {
- int new_index = Get_UV_Array_Count();
- REF_PTR_SET(UV[new_index],default_materials.UV[default_uv_source]);
- UVSource[pass][stage] = new_index;
- }
- }
- } else {
- UVSource[pass][stage] = alternate_materials.UVSource[pass][stage];
- }
- // Texture pointer(s): If alternate_materials has either a single texture or an array of textures,
- // then add-ref only the texture data it contains. Otherwise, add-ref the data in default_materials.
- if ((alternate_materials.Texture[pass][stage] != NULL) || (alternate_materials.TextureArray[pass][stage])) {
- REF_PTR_SET(Texture[pass][stage] , alternate_materials.Texture[pass][stage]);
- REF_PTR_SET(TextureArray[pass][stage] , alternate_materials.TextureArray[pass][stage]);
- } else {
- REF_PTR_SET(Texture[pass][stage] , default_materials.Texture[pass][stage]);
- REF_PTR_SET(TextureArray[pass][stage] , default_materials.TextureArray[pass][stage]);
- }
- }
-
- // UV Index array
- // if (alternate_materials.UVIndex[pass] != NULL) {
- // REF_PTR_SET(UVIndex[pass],alternate_materials.UVIndex[pass]);
- // } else {
- // REF_PTR_SET(UVIndex[pass],default_materials.UVIndex[pass]);
- // }
- // Vertex color configuration
- if (alternate_materials.DCGSource[pass] == VertexMaterialClass::MATERIAL) {
- DCGSource[pass] = default_materials.DCGSource[pass];
- } else {
- DCGSource[pass] = alternate_materials.DCGSource[pass];
- }
-
- // Shaders, currently I can't tell if the alternate data has a shader... Can't override the shader for now.
- Shader[pass] = default_materials.Shader[pass];
- REF_PTR_SET(ShaderArray[pass],default_materials.ShaderArray[pass]);
- // Vertex Materials. If alternate_materials has either a single or array of materials, then copy them
- if ((alternate_materials.Material[pass] != NULL) || (alternate_materials.MaterialArray[pass] != NULL)) {
- REF_PTR_SET(Material[pass],alternate_materials.Material[pass]);
- REF_PTR_SET(MaterialArray[pass],alternate_materials.MaterialArray[pass]);
- } else {
- // Dont share vertex materials! (because the UVSources can be different!)
- if (default_materials.Material[pass]) {
- Material[pass] = NEW_REF(VertexMaterialClass,(*(default_materials.Material[pass])));
- } else {
- if (default_materials.MaterialArray[pass]) {
- WWDEBUG_SAY(("Unimplemented case: mesh has more than one default vertex material but no alternate vertex materials have been defined.\r\n"));
- }
- Material[pass] = NULL;
- }
- }
- }
- }
- bool MeshMatDescClass::Is_Empty(void)
- {
- for (int array=0; array<MAX_COLOR_ARRAYS; array++) {
- if (ColorArray[array] != NULL) return false;
- }
- for (int uvarray=0; uvarray<MAX_UV_ARRAYS; uvarray++) {
- if (UV[uvarray] != NULL) return false;
- }
- for (int pass=0; pass<MAX_PASSES; pass++) {
- for (int stage=0; stage<MAX_TEX_STAGES; stage++) {
- if (Texture[pass][stage] != NULL) return false;
- if (TextureArray[pass][stage] != NULL) return false;
- }
- // if (UVIndex[pass] != NULL) return false;
- if (Material[pass] != NULL) return false;
- if (MaterialArray[pass] != NULL) return false;
- }
-
- return true;
- }
- void MeshMatDescClass::Set_Single_Material(VertexMaterialClass * vmat,int pass)
- {
- REF_PTR_SET(Material[pass],vmat);
- }
- void MeshMatDescClass::Set_Single_Texture(TextureClass * tex,int pass,int stage)
- {
- REF_PTR_SET(Texture[pass][stage],tex);
- }
- void MeshMatDescClass::Set_Single_Shader(ShaderClass shader,int pass)
- {
- Shader[pass] = shader;
- }
- void MeshMatDescClass::Set_Material(int vidx,VertexMaterialClass * vmat,int pass)
- {
- MatBufferClass * mats = Get_Material_Array(pass,true);
- mats->Set_Element(vidx,vmat);
- }
- void MeshMatDescClass::Set_Shader(int pidx,ShaderClass shader,int pass)
- {
- ShaderClass * shaders = Get_Shader_Array(pass,true);
- shaders[pidx] = shader;
- }
- void MeshMatDescClass::Set_Texture(int pidx,TextureClass * tex,int pass,int stage)
- {
- TexBufferClass * textures = Get_Texture_Array(pass,stage,true);
- textures->Set_Element(pidx,tex);
- }
- VertexMaterialClass * MeshMatDescClass::Get_Material(int vidx,int pass) const
- {
- if (MaterialArray[pass]) {
- return MaterialArray[pass]->Get_Element(vidx);
- } else if (Material[pass] != NULL) {
- Material[pass]->Add_Ref();
- return Material[pass];
-
- }
- return NULL;
- }
- ShaderClass MeshMatDescClass::Get_Shader(int pidx,int pass) const
- {
- if (ShaderArray[pass]) {
- return ShaderArray[pass]->Get_Element(pidx);
- }
- return Shader[pass];
- }
- TextureClass * MeshMatDescClass::Get_Texture(int pidx,int pass,int stage) const
- {
- if (TextureArray[pass][stage]) {
- return TextureArray[pass][stage]->Get_Element(pidx);
-
- } else if (Texture[pass][stage] != NULL) {
- Texture[pass][stage]->Add_Ref();
- return Texture[pass][stage];
-
- }
- return NULL;
- }
- VertexMaterialClass * MeshMatDescClass::Peek_Material(int vidx,int pass) const
- {
- if (MaterialArray[pass]) {
- return MaterialArray[pass]->Peek_Element(vidx);
- }
- return Material[pass];
- }
- TextureClass * MeshMatDescClass::Peek_Texture(int pidx,int pass,int stage) const
- {
- if (TextureArray[pass][stage]) {
- return TextureArray[pass][stage]->Peek_Element(pidx);
- }
- return Texture[pass][stage];
- }
- TexBufferClass * MeshMatDescClass::Get_Texture_Array(int pass,int stage,bool create)
- {
- if (create && TextureArray[pass][stage] == NULL) {
- TextureArray[pass][stage] = NEW_REF(TexBufferClass,(PolyCount, "MeshMatDescClass::TextureArray"));
- }
- return TextureArray[pass][stage];
- }
- MatBufferClass * MeshMatDescClass::Get_Material_Array(int pass,bool create)
- {
- if (create && MaterialArray[pass] == NULL) {
- MaterialArray[pass] = NEW_REF(MatBufferClass,(VertexCount, "MeshMatDescClass::MaterialArray"));
- }
- return MaterialArray[pass];
- }
- ShaderClass * MeshMatDescClass::Get_Shader_Array(int pass,bool create)
- {
- if (create && ShaderArray[pass] == NULL) {
- ShaderArray[pass] = NEW_REF(ShareBufferClass<ShaderClass>,(PolyCount, "MeshMatDescClass::ShaderArray"));
- ShaderArray[pass]->Clear();
- }
- if (ShaderArray[pass]) {
- return ShaderArray[pass]->Get_Array();
- }
- return NULL;
- }
- void MeshMatDescClass::Make_UV_Array_Unique(int pass,int stage)
- {
- int uvindex = UVSource[pass][stage];
- if (UV[uvindex]->Num_Refs() > 1) {
- UVBufferClass * unique_uv = NEW_REF(UVBufferClass,(*UV[uvindex]));
- UV[uvindex]->Release_Ref();
- UV[uvindex] = unique_uv;
- }
- }
- void MeshMatDescClass::Make_Color_Array_Unique(int array)
- {
- if ((ColorArray[array] != NULL) && (ColorArray[array]->Num_Refs() > 1)) {
- ShareBufferClass<unsigned> * unique_color_array = NEW_REF(ShareBufferClass<unsigned>,(*ColorArray[array]));
- ColorArray[array]->Release_Ref();
- ColorArray[array] = unique_color_array;
- }
- }
- void MeshMatDescClass::Install_UV_Array(int pass,int stage,Vector2 * uvs,int count)
- {
- /*
- ** Compute the crc of this uv array
- */
- unsigned int crc = CRC_Memory((unsigned char *)uvs,count * sizeof(Vector2));
- /*
- ** See if there is an existing uv-array that matches the one just loaded
- */
- bool found = false;
- for (int i=0; i<Get_UV_Array_Count(); i++) {
- if (UV[i]->Get_CRC() == crc) {
- found = true;
- Set_UV_Source(pass,stage,i);
- break;
- }
- }
- /*
- ** If there was no existing uv array, install this one
- */
- if (found == false) {
- /*
- ** Find the first empty UV-array slot
- */
- int new_index = 0;
- while ((UV[new_index] != NULL) && (new_index < MAX_UV_ARRAYS)) {
- new_index++;
- }
- if (new_index < MAX_UV_ARRAYS) {
- WWASSERT(UV[new_index] == NULL);
- UV[new_index] = NEW_REF(UVBufferClass,(count, "MeshMatDescClass::UV"));
- memcpy(UV[new_index]->Get_Array(),uvs,count * sizeof(Vector2));
- UV[new_index]->Update_CRC(); // update the crc for future comparision
- Set_UV_Source(pass,stage,new_index);
- }
- }
- }
- void MeshMatDescClass::Post_Load_Process(bool lighting_enabled)
- {
- /*
- ** Configure all vertex materials to source the uv coordinates and colors from the correct arrays
- ** Pre-multiply the vertex color arrays.
- */
- for (int pass=0; pass<PassCount; pass++) {
- /*
- ** If this pass doesn't have a vertex material, create one
- */
- if ((Material[pass] == NULL) && (MaterialArray[pass] == NULL)) {
- Material[pass] = NEW_REF(VertexMaterialClass,());
- }
- /*
- ** Configure the materials to source the uv coordinates and colors
- */
- if (Material[pass] != NULL) {
- Configure_Material(Material[pass],pass,lighting_enabled);
- } else {
- VertexMaterialClass * prev_mtl = NULL;
- VertexMaterialClass * mtl = Peek_Material(pass,0);
-
- for (int vidx=0; vidx<VertexCount; vidx++) {
-
- mtl = Peek_Material(vidx,pass);
- if ((mtl != prev_mtl) && (mtl != NULL)) {
- Configure_Material(mtl,pass,lighting_enabled);
- prev_mtl = mtl;
- }
- }
- }
- // Analyze material array types and apply hacks for supporting SR-lighting pipeline if possible.
- if (!ColorArray[0] && !ColorArray[1]) continue; // If no color arrays, we don't have a problem
- Vector3 single_diffuse(0.0f,0.0f,0.0f);
- Vector3 single_ambient(0.0f,0.0f,0.0f);
- Vector3 single_emissive(0.0f,0.0f,0.0f);
- float single_opacity=1.0f;
- bool single_diffuse_used=true;
- bool single_ambient_used=true;
- bool single_emissive_used=true;
- bool single_opacity_used=true;
- bool diffuse_used=false;
- bool ambient_used=false;
- bool emissive_used=false;
- bool opacity_used=false;
- Vector3 mtl_diffuse;
- Vector3 mtl_ambient;
- Vector3 mtl_emissive;
- float mtl_opacity = 1.0f;
- VertexMaterialClass * prev_mtl = NULL;
- VertexMaterialClass * mtl = Peek_Material(0, pass);
- if (mtl) {
- mtl->Get_Diffuse(&single_diffuse);
- single_opacity = mtl->Get_Opacity();
- mtl->Get_Ambient(&single_ambient);
- mtl->Get_Emissive(&single_emissive);
- if (single_diffuse.X || single_diffuse.Y || single_diffuse.Z) diffuse_used=true;
- if (single_ambient.X || single_ambient.Y || single_ambient.Z) ambient_used=true;
- if (single_emissive.X || single_emissive.Y || single_emissive.Z) emissive_used=true;
- if (single_opacity!=1.0f) opacity_used=true;
- }
- for (int vidx=0; vidx<VertexCount; vidx++) {
- mtl = Peek_Material(vidx,pass);
- if (mtl != prev_mtl) {
- prev_mtl = mtl;
- mtl->Get_Diffuse(&mtl_diffuse);
- mtl_opacity = mtl->Get_Opacity();
- mtl->Get_Ambient(&mtl_ambient);
- mtl->Get_Emissive(&mtl_emissive);
- }
- if (mtl_diffuse.X!=single_diffuse.X || mtl_diffuse.Y!=single_diffuse.Y || mtl_diffuse.Z!=single_diffuse.Z) {
- single_diffuse_used=false;
- }
- if (mtl_ambient.X!=single_ambient.X || mtl_ambient.Y!=single_ambient.Y || mtl_ambient.Z!=single_ambient.Z) {
- single_ambient_used=false;
- }
- if (mtl_emissive.X!=single_emissive.X || mtl_emissive.Y!=single_emissive.Y || mtl_emissive.Z!=single_emissive.Z) {
- single_emissive_used=false;
- }
- if (mtl_opacity!=single_opacity) {
- single_opacity_used=false;
- }
- if (mtl_diffuse.X || mtl_diffuse.Y || mtl_diffuse.Z) diffuse_used=true;
- if (mtl_ambient.X || mtl_ambient.Y || mtl_ambient.Z) ambient_used=true;
- if (mtl_emissive.X || mtl_emissive.Y || mtl_emissive.Z) emissive_used=true;
- if (mtl_opacity!=1.0f) opacity_used=true;
- }
- // If both DCG and DIG arrays are submitted, multiply them together to DCG channel
- if ((DCGSource[pass] != VertexMaterialClass::MATERIAL) && (ColorArray[0] != NULL) &&
- (DIGSource[pass] != VertexMaterialClass::MATERIAL) && (ColorArray[1] != NULL)) {
- unsigned * diffuse_array = ColorArray[0]->Get_Array();
- unsigned * emissive_array = ColorArray[1]->Get_Array();
- for (int vidx=0; vidx<VertexCount; vidx++) {
- Vector4 diffuse=DX8Wrapper::Convert_Color(diffuse_array[vidx]);
- Vector4 emissive=DX8Wrapper::Convert_Color(emissive_array[vidx]);
- diffuse.X *= emissive.X;
- diffuse.Y *= emissive.Y;
- diffuse.Z *= emissive.Z;
- diffuse_array[vidx]=DX8Wrapper::Convert_Color(diffuse);
- }
- }
- DIGSource[pass]=VertexMaterialClass::MATERIAL; // DIG channel no more
- if ((DCGSource[pass] != VertexMaterialClass::MATERIAL) && (ColorArray[0] != NULL)) {
- unsigned * diffuse_array = ColorArray[0]->Get_Array();
- Vector3 mtl_diffuse;
- float mtl_opacity = 1.0f;
- VertexMaterialClass * prev_mtl = NULL;
- VertexMaterialClass * mtl = Peek_Material(0,pass);
- for (int vidx=0; vidx<VertexCount; vidx++) {
-
- mtl = Peek_Material(vidx,pass);
- if (mtl != prev_mtl) {
- prev_mtl = mtl;
- mtl->Get_Diffuse(&mtl_diffuse);
- mtl_opacity = mtl->Get_Opacity();
- }
- // If only diffuse is used apply diffuse to color channel and set diffuse source to color 1
- if (diffuse_used && !ambient_used && !emissive_used) {
- Vector4 diffuse=DX8Wrapper::Convert_Color(diffuse_array[vidx]);
- diffuse.X *= mtl_diffuse.X;
- diffuse.Y *= mtl_diffuse.Y;
- diffuse.Z *= mtl_diffuse.Z;
- diffuse.W *= mtl_opacity;
- diffuse_array[vidx]=DX8Wrapper::Convert_Color(diffuse);
- mtl->Set_Ambient_Color_Source(VertexMaterialClass::MATERIAL);
- mtl->Set_Diffuse_Color_Source(VertexMaterialClass::COLOR1);
- mtl->Set_Emissive_Color_Source(VertexMaterialClass::MATERIAL);
- }
- // If diffuse and ambient are used, apply diffuse to color channel and set diffuse
- // and ambient sources to color 1. (this is not completely correct if diffuse and
- // ambient are different but is probably the most reasonable thing to do. Why set
- // diffuse and ambient differently anyway?)
- if (diffuse_used && ambient_used && !emissive_used) {
- Vector4 diffuse=DX8Wrapper::Convert_Color(diffuse_array[vidx]);
- diffuse.X *= mtl_diffuse.X;
- diffuse.Y *= mtl_diffuse.Y;
- diffuse.Z *= mtl_diffuse.Z;
- diffuse.W *= mtl_opacity;
- diffuse_array[vidx]=DX8Wrapper::Convert_Color(diffuse);
- mtl->Set_Ambient_Color_Source(VertexMaterialClass::COLOR1);
- mtl->Set_Diffuse_Color_Source(VertexMaterialClass::COLOR1);
- mtl->Set_Emissive_Color_Source(VertexMaterialClass::MATERIAL);
- }
- // If only ambient is used apply ambient to color channel and set ambient source to color 1
- if (!diffuse_used && ambient_used && !emissive_used) {
- Vector4 diffuse=DX8Wrapper::Convert_Color(diffuse_array[vidx]);
- diffuse.X *= mtl_ambient.X;
- diffuse.Y *= mtl_ambient.Y;
- diffuse.Z *= mtl_ambient.Z;
- diffuse.W *= mtl_opacity;
- diffuse_array[vidx]=DX8Wrapper::Convert_Color(diffuse);
- mtl->Set_Ambient_Color_Source(VertexMaterialClass::COLOR1);
- mtl->Set_Diffuse_Color_Source(VertexMaterialClass::MATERIAL);
- mtl->Set_Emissive_Color_Source(VertexMaterialClass::MATERIAL);
- }
- // If only emissive is used apply emissive to color channel, set diffuse source to color 1, and turn off lighting
- if (!diffuse_used && !ambient_used && emissive_used) {
- Vector4 diffuse=DX8Wrapper::Convert_Color(diffuse_array[vidx]);
- diffuse.X *= mtl_emissive.X;
- diffuse.Y *= mtl_emissive.Y;
- diffuse.Z *= mtl_emissive.Z;
- diffuse.W *= mtl_opacity;
- diffuse_array[vidx]=DX8Wrapper::Convert_Color(diffuse);
- mtl->Set_Ambient_Color_Source(VertexMaterialClass::MATERIAL);
- mtl->Set_Diffuse_Color_Source(VertexMaterialClass::COLOR1);
- mtl->Set_Emissive_Color_Source(VertexMaterialClass::MATERIAL);
- //MW: Vegas guys asked me to disable this because it can cause z-fighting if lighting is disabled in multi-pass
- // mtl->Set_Lighting(false);
- }
- }
- }
- /*
- ** If a DCG array is present, pre multiply the alpha value from the material into
- ** the vertex color array. Experimentation on GeForce hardware showed that we
- ** don't need to pre-multiply the color values; hopefully this is the behavior on
- ** other hardware as well!
- */
- /* if ((DCGSource[pass] != VertexMaterialClass::MATERIAL) && (ColorArray[0] != NULL)) {
- unsigned * diffuse_array = ColorArray[0]->Get_Array();
- Vector3 mtl_diffuse;
- float mtl_opacity = 1.0f;
- VertexMaterialClass * prev_mtl = NULL;
- VertexMaterialClass * mtl = Peek_Material(0,pass);
- for (int vidx=0; vidx<VertexCount; vidx++) {
-
- mtl = Peek_Material(vidx,pass);
- if (mtl != prev_mtl) {
- prev_mtl = mtl;
- mtl->Get_Diffuse(&mtl_diffuse);
- mtl_opacity = mtl->Get_Opacity();
- }
- Vector4 diffuse=DX8Wrapper::Convert_Color(diffuse_array[vidx]);
- diffuse.X *= mtl_diffuse.X;
- diffuse.Y *= mtl_diffuse.Y;
- diffuse.Z *= mtl_diffuse.Z;
- diffuse.W *= mtl_opacity;
- diffuse_array[vidx]=DX8Wrapper::Convert_Color(diffuse);
-
- }
- }
- */ /*
- ** If needed, pre-multiply the emissive color array with the material color
- */
- /* if ((DIGSource[pass] != VertexMaterialClass::MATERIAL) && (ColorArray[1] != NULL)) {
- unsigned * emissive_array = ColorArray[1]->Get_Array();
- Vector3 mtl_emissive;
- VertexMaterialClass * prev_mtl = NULL;
- VertexMaterialClass * mtl = Peek_Material(0,pass);
- for (int vidx=0; vidx<VertexCount; vidx++) {
-
- mtl = Peek_Material(vidx,pass);
- if (mtl != prev_mtl) {
- prev_mtl = mtl;
- mtl->Get_Emissive(&mtl_emissive);
- }
- Vector4 emissive=DX8Wrapper::Convert_Color(emissive_array[vidx]);
- emissive.X *= mtl_emissive.X;
- emissive.Y *= mtl_emissive.Y;
- emissive.Z *= mtl_emissive.Z;
- emissive_array[vidx]=DX8Wrapper::Convert_Color(emissive);
-
- }
- }
- */
- }
- }
- void MeshMatDescClass::Configure_Material(VertexMaterialClass * mtl,int pass,bool lighting_enabled)
- {
- mtl->Set_Diffuse_Color_Source(DCGSource[pass]);
- mtl->Set_Emissive_Color_Source(DIGSource[pass]);
- mtl->Set_Lighting(lighting_enabled);
- for (int stage=0; stage<MAX_TEX_STAGES; stage++) {
- int src = UVSource[pass][stage];
- if (src == -1) {
- src = 0;
- }
- mtl->Set_UV_Source(stage,src);
- }
- }
- bool MeshMatDescClass::Do_Mappers_Need_Normals(void)
- {
- if (DX8Caps::Support_NPatches() && WW3D::Get_NPatches_Level()>1) return true;
- for (int pass=0; pass<PassCount; pass++) {
- /*
- ** Check the materials on this pass to see if any have mappers which require normals
- */
- if (Material[pass] != NULL) {
- if (Material[pass]->Do_Mappers_Need_Normals()) return true;
- } else {
- VertexMaterialClass * prev_mtl = NULL;
- VertexMaterialClass * mtl = Peek_Material(pass,0);
-
- for (int vidx=0; vidx<VertexCount; vidx++) {
-
- mtl = Peek_Material(vidx,pass);
- if ((mtl != prev_mtl) && (mtl != NULL)) {
- if (mtl->Do_Mappers_Need_Normals()) return true;
- prev_mtl = mtl;
- }
- }
- }
- }
-
- return false;
- }
|