/* ** Command & Conquer Renegade(tm) ** Copyright 2025 Electronic Arts Inc. ** ** This program is free software: you can redistribute it and/or modify ** it under the terms of the GNU General Public License as published by ** the Free Software Foundation, either version 3 of the License, or ** (at your option) any later version. ** ** This program is distributed in the hope that it will be useful, ** but WITHOUT ANY WARRANTY; without even the implied warranty of ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ** GNU General Public License for more details. ** ** You should have received a copy of the GNU General Public License ** along with this program. If not, see . */ /*************************************************************************** *** C O N F I D E N T I A L --- W E S T W O O D S T U D I O S *** *************************************************************************** * * * Project Name : Commando * * * * $Archive:: /Commando/Code/ww3d2/dynamesh.cpp $* * * * $Author:: Greg_h $* * * * $Modtime:: 12/03/01 4:50p $* * * * $Revision:: 25 $* * * *-------------------------------------------------------------------------* * Functions: * * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ #include "dynamesh.h" #include "dx8vertexbuffer.h" #include "dx8indexbuffer.h" #include "dx8wrapper.h" #include "sortingrenderer.h" #include "rinfo.h" #include "camera.h" #include "dx8fvf.h" /* ** DynamicMeshModel implementation */ DynamicMeshModel::DynamicMeshModel(unsigned int max_polys, unsigned int max_verts) : MeshGeometryClass(), DynamicMeshPNum(0), DynamicMeshVNum(0), MatDesc(NULL), MatInfo(NULL) { MatInfo = NEW_REF(MaterialInfoClass, ()); MatDesc = new MeshMatDescClass; MatDesc->Set_Polygon_Count(max_polys); MatDesc->Set_Vertex_Count(max_verts); Reset_Geometry(max_polys, max_verts); } DynamicMeshModel::DynamicMeshModel(unsigned int max_polys, unsigned int max_verts, MaterialInfoClass *mat_info) : MeshGeometryClass(), DynamicMeshPNum(0), DynamicMeshVNum(0), MatDesc(NULL), MatInfo(NULL) { MatInfo = mat_info; MatInfo->Add_Ref(); MatDesc = new MeshMatDescClass; MatDesc->Set_Polygon_Count(max_polys); MatDesc->Set_Vertex_Count(max_verts); Reset_Geometry(max_polys, max_verts); } DynamicMeshModel::DynamicMeshModel(const DynamicMeshModel &src) : MeshGeometryClass(src), DynamicMeshPNum(src.DynamicMeshPNum), DynamicMeshVNum(src.DynamicMeshVNum), MatDesc(NULL), MatInfo(NULL) { // Copy the material info structure. MatInfo = NEW_REF(MaterialInfoClass, (*(src.MatInfo))); // remap! MaterialRemapperClass remapper(src.MatInfo, MatInfo); remapper.Remap_Mesh(src.MatDesc, MatDesc); MatDesc = new MeshMatDescClass; } DynamicMeshModel::~DynamicMeshModel(void) { if (MatDesc) { delete MatDesc; MatDesc = NULL; } REF_PTR_RELEASE(MatInfo); } void DynamicMeshModel::Compute_Plane_Equations(void) { // Make sure the arrays are allocated before we do this get_vert_normals(); Vector4 * planes = get_planes(true); // Set the poly and vertex counts to the dynamic counts, call the base class function, then // set them back. int old_poly_count = PolyCount; int old_vert_count = VertexCount; PolyCount = DynamicMeshPNum; VertexCount = DynamicMeshVNum; MeshGeometryClass::Compute_Plane_Equations(planes); PolyCount = old_poly_count; VertexCount = old_vert_count; } void DynamicMeshModel::Compute_Vertex_Normals(void) { // Make sure the arrays are allocated before we do this Vector3 * vnorms = get_vert_normals(); get_planes(true); // Set the poly and vertex counts to the dynamic counts, call the base class function, then // set them back. int old_poly_count = PolyCount; int old_vert_count = VertexCount; PolyCount = DynamicMeshPNum; VertexCount = DynamicMeshVNum; MeshGeometryClass::Compute_Vertex_Normals(vnorms); PolyCount = old_poly_count; VertexCount = old_vert_count; } void DynamicMeshModel::Compute_Bounds(Vector3 * verts) { // Set the poly and vertex counts to the dynamic counts, call the base class function, then // set them back. int old_poly_count = PolyCount; int old_vert_count = VertexCount; PolyCount = DynamicMeshPNum; VertexCount = DynamicMeshVNum; MeshGeometryClass::Compute_Bounds(verts); PolyCount = old_poly_count; VertexCount = old_vert_count; } void DynamicMeshModel::Reset(void) { Set_Counts(0, 0); int polycount = Get_Polygon_Count(); int vertcount = Get_Vertex_Count(); Reset_Geometry(polycount, vertcount); MatDesc->Reset(polycount, vertcount, 1); REF_PTR_RELEASE(MatInfo); MatInfo = NEW_REF(MaterialInfoClass, ()); } void DynamicMeshModel::Render(RenderInfoClass & rinfo) { // Process texture reductions: // MatInfo->Process_Texture_Reduction(); unsigned buffer_type=(Get_Flag(MeshGeometryClass::SORT)&& WW3D::Is_Sorting_Enabled()) ? BUFFER_TYPE_DYNAMIC_SORTING : BUFFER_TYPE_DYNAMIC_DX8; /* ** Write the vertex data to the vertex buffer. We assume the FVF contains positions, normals, ** one texture channel, and the diffuse color channel (color0). If it does not contain all ** these components, the code will fail. */ DynamicVBAccessClass dynamic_vb(buffer_type,dynamic_fvf_type,DynamicMeshVNum); const FVFInfoClass &fvf_info = dynamic_vb.FVF_Info(); { // scope for lock DynamicVBAccessClass::WriteLockClass lock(&dynamic_vb); unsigned char *vertices = (unsigned char*)lock.Get_Formatted_Vertex_Array(); const Vector3 *locs = Get_Vertex_Array(); const Vector3 *normals = Get_Vertex_Normal_Array(); const Vector2 *uvs = MatDesc->Get_UV_Array_By_Index(0, false); const Vector2 *uv1s = MatDesc->Get_UV_Array_By_Index(1, false); const unsigned *colors = MatDesc->Get_Color_Array(0, false); const static Vector3 default_normal(0.0f, 0.0f, 0.0f); const static Vector2 default_uv(0.0f, 0.0f); const unsigned int default_color = 0xFFFFFFFF; for (int i=0; i < DynamicMeshVNum; i++) { *(Vector3 *)(vertices + fvf_info.Get_Location_Offset()) = locs[i]; *(Vector3 *)(vertices + fvf_info.Get_Normal_Offset()) = normals[i]; if (uvs) { *(Vector2 *)(vertices + fvf_info.Get_Tex_Offset(0)) = uvs[i]; } else { *(Vector2 *)(vertices + fvf_info.Get_Tex_Offset(0)) = default_uv; } if (uv1s) { *(Vector2 *)(vertices + fvf_info.Get_Tex_Offset(1)) = uv1s[i]; } else { *(Vector2 *)(vertices + fvf_info.Get_Tex_Offset(1)) = default_uv; } if (colors) { *(unsigned int *)(vertices + fvf_info.Get_Diffuse_Offset()) = colors[i]; } else { *(unsigned int *)(vertices + fvf_info.Get_Diffuse_Offset()) = default_color; } vertices += fvf_info.Get_FVF_Size(); } } // end scope for lock /* ** Write index data to index buffers */ DynamicIBAccessClass dynamic_ib(buffer_type,DynamicMeshPNum * 3); const TriIndex *tris = Get_Polygon_Array(); { // scope for lock DynamicIBAccessClass::WriteLockClass lock(&dynamic_ib); unsigned short * indices = lock.Get_Index_Array(); for (int i=0; i < DynamicMeshPNum; i++) { indices[i*3 + 0] = (unsigned short)tris[i][0]; indices[i*3 + 1] = (unsigned short)tris[i][1]; indices[i*3 + 2] = (unsigned short)tris[i][2]; } } // end scope for lock /* ** Set vertex and index buffers */ DX8Wrapper::Set_Vertex_Buffer(dynamic_vb); DX8Wrapper::Set_Index_Buffer(dynamic_ib,0); /* ** Draw dynamesh, one pass at a time */ unsigned int pass_count = Get_Pass_Count(); for (unsigned int pass = 0; pass < pass_count; pass++) { /* ** Set current render states (texture, vertex material, shader). Scan triangles until one ** of these changes, and then draw. */ // The vertex index range used unsigned short min_vert_idx = DynamicMeshVNum - 1; unsigned short max_vert_idx = 0; unsigned short start_tri_idx = 0; unsigned short cur_tri_idx = 0; bool done = false; bool texture_changed = false; bool texture1_changed = false; bool material_changed = false; bool shader_changed = false; TextureClass **texture_array0 = NULL; TexBufferClass * tex_buf = MatDesc->Get_Texture_Array(pass, 0, false); if (tex_buf) { texture_array0 = tex_buf->Get_Array(); } else { texture_array0 = NULL; } TextureClass **texture_array1 = NULL; TexBufferClass * tex_buf1 = MatDesc->Get_Texture_Array(pass, 1, false); if (tex_buf1) { texture_array1 = tex_buf1->Get_Array(); } else { texture_array1 = NULL; } VertexMaterialClass **material_array = NULL; MatBufferClass * mat_buf = MatDesc->Get_Material_Array(pass, false); if (mat_buf) { material_array = mat_buf->Get_Array(); } else { material_array = NULL; } ShaderClass *shader_array = MatDesc->Get_Shader_Array(pass, false); // Set the DX8 state to the first triangle's state if (texture_array0) { DX8Wrapper::Set_Texture(0,texture_array0[0]); } else { DX8Wrapper::Set_Texture(0,MatDesc->Peek_Single_Texture(pass, 0)); } if (texture_array1) { DX8Wrapper::Set_Texture(1,texture_array1[0]); } else { DX8Wrapper::Set_Texture(1,MatDesc->Peek_Single_Texture(pass, 1)); } if (material_array) { DX8Wrapper::Set_Material(material_array[tris[0].I]); } else { DX8Wrapper::Set_Material(MatDesc->Peek_Single_Material(pass)); } if (shader_array) { DX8Wrapper::Set_Shader(shader_array[0]); } else { DX8Wrapper::Set_Shader(MatDesc->Get_Single_Shader(pass)); } SphereClass sphere(Vector3(0.0f,0.0f,0.0f),0.0f); Get_Bounding_Sphere(&sphere); // If no texture, shader or material arrays for this pass just draw and go to next pass if (!texture_array0 && !texture_array1 && !material_array && !shader_array) { if (buffer_type==BUFFER_TYPE_DYNAMIC_SORTING) { SortingRendererClass::Insert_Triangles(sphere,0, DynamicMeshPNum, 0, DynamicMeshVNum); } else { DX8Wrapper::Draw_Triangles(0, DynamicMeshPNum, 0, DynamicMeshVNum); } continue; } while (!done) { // Add vertex indices of tri[cur_tri_idx] to min_vert_idx, max_vert_idx const TriIndex &tri = tris[cur_tri_idx]; unsigned short min_idx = (unsigned short)MIN(MIN(tri.I, tri.J), tri.K); unsigned short max_idx = (unsigned short)MAX(MAX(tri.I, tri.J), tri.K); min_vert_idx = MIN(min_vert_idx, min_idx); max_vert_idx = MAX(max_vert_idx, max_idx); // Check the next triangle to see if the current run has ended. unsigned short next_tri_idx = cur_tri_idx + 1; done = next_tri_idx >= DynamicMeshPNum; if (done) { texture_changed = false; texture1_changed = false; material_changed = false; shader_changed = false; } else { texture_changed = texture_array0 && texture_array0[cur_tri_idx] != texture_array0[next_tri_idx]; texture1_changed = texture_array1 && texture_array1[cur_tri_idx] != texture_array1[next_tri_idx]; material_changed = material_array && material_array[tris[cur_tri_idx].I] != material_array[tris[next_tri_idx].I]; shader_changed = shader_array && shader_array[cur_tri_idx] != shader_array[next_tri_idx]; } // If run ends (mesh ends or state changes) draw, reset indices, set state for next run. if (done || texture_changed || material_changed || shader_changed) { if (buffer_type==BUFFER_TYPE_DYNAMIC_SORTING) { SortingRendererClass::Insert_Triangles( sphere, (start_tri_idx * 3), (1 + cur_tri_idx - start_tri_idx), min_vert_idx, 1 + max_vert_idx - min_vert_idx); } else { DX8Wrapper::Draw_Triangles( (start_tri_idx * 3), (1 + cur_tri_idx - start_tri_idx), min_vert_idx, 1 + max_vert_idx - min_vert_idx); } start_tri_idx = next_tri_idx; min_vert_idx = DynamicMeshVNum - 1; max_vert_idx = 0; if (texture_changed) DX8Wrapper::Set_Texture(0,texture_array0[next_tri_idx]); if (texture1_changed) DX8Wrapper::Set_Texture(1,texture_array1[next_tri_idx]); if (material_changed) DX8Wrapper::Set_Material(material_array[tris[next_tri_idx].I]); if (shader_changed) DX8Wrapper::Set_Shader(shader_array[next_tri_idx]); } cur_tri_idx = next_tri_idx; } // while (!done) } // for (pass) } void DynamicMeshModel::Initialize_Texture_Array(int pass, int stage, TextureClass *texture) { TexBufferClass * texlist = MatDesc->Get_Texture_Array(pass, 0, true); for (int lp = 0; lp < PolyCount; lp++) { texlist->Set_Element(lp, texture); } } void DynamicMeshModel::Initialize_Material_Array(int pass, VertexMaterialClass *vmat) { MatBufferClass * vertmatlist = MatDesc->Get_Material_Array(pass, true); for (int lp = 0; lp < VertexCount; lp++) { vertmatlist->Set_Element(lp, vmat); } } void DynamicMeshClass::Render(RenderInfoClass & rinfo) { if (Is_Not_Hidden_At_All() == false) return; // test for an empty mesh.. if (PolyCount == 0 ) return; // If static sort lists are enabled and this mesh has a sort level, put it on the list instead // of rendering it. if (WW3D::Are_Static_Sort_Lists_Enabled() && SortLevel != SORT_LEVEL_NONE) { WW3D::Add_To_Static_Sort_List(this, SortLevel); } else { const FrustumClass & frustum = rinfo.Camera.Get_Frustum(); if (CollisionMath::Overlap_Test(frustum, Get_Bounding_Box()) != CollisionMath::OUTSIDE) { DX8Wrapper::Set_Transform(D3DTS_WORLD, Transform); Model->Render(rinfo); } } } bool DynamicMeshClass::End_Vertex() { // check that we have room for a new vertex WWASSERT(VertCount < Model->Get_Vertex_Count()); // if we are a multi-material object record the material int pass = Get_Pass_Count(); while (pass--) { if (MultiVertexMaterial[pass]) { VertexMaterialClass *mat = Peek_Material_Info()->Get_Vertex_Material(VertexMaterialIdx[pass]); Model->Set_Material(VertCount, mat, pass); REF_PTR_RELEASE(mat); } } // if we are multi colored, record the color for (int color_array_index = 0; color_array_index < MAX_COLOR_ARRAYS; color_array_index++) { if (MultiVertexColor[color_array_index]) { // Vector4 * color = &((Model->Get_Color_Array(color_array_index))[VertCount]); // color->X = CurVertexColor[color_array_index].X; // color->Y = CurVertexColor[color_array_index].Y; // color->Z = CurVertexColor[color_array_index].Z; // color->W = CurVertexColor[color_array_index].W; unsigned * color = &((Model->Get_Color_Array(color_array_index))[VertCount]); *color=DX8Wrapper::Convert_Color_Clamp(CurVertexColor[color_array_index]); } } // mark this vertex as being complete VertCount++; TriVertexCount++; // if we have 3 or more vertices, add a new poly if (TriVertexCount >= 3) { // check that we have room for a new poly WWASSERT(PolyCount < Model->Get_Polygon_Count()); // set vertex indices TriIndex *poly = &(Model->Get_Non_Const_Polygon_Array())[PolyCount]; if (TriMode == TRI_MODE_STRIPS) { (*poly)[0] = VertCount-3; (*poly)[1] = VertCount-2; (*poly)[2] = VertCount-1; // for every other tri, reverse vertex order if (Flip_Face()) { (*poly)[1] = VertCount-1; (*poly)[2] = VertCount-2; } } else { (*poly)[0] = FanVertex; (*poly)[1] = VertCount-2; (*poly)[2] = VertCount-1; } // check each pass int pass = Get_Pass_Count(); while (pass--) { // If we are multi texture if (MultiTexture[pass]) { TextureClass *tex = Peek_Material_Info()->Get_Texture(TextureIdx[pass]); Model->Set_Texture(PolyCount, tex, pass); REF_PTR_RELEASE(tex); } } // increase the count and record that we have a new material PolyCount++; Model->Set_Counts(PolyCount, VertCount); } return true; } /****************************************************************** ** ** DynamicMeshClass ** *******************************************************************/ DynamicMeshClass::DynamicMeshClass(int max_poly, int max_vert) : Model(NULL), PolyCount(0), VertCount(0), TriVertexCount(0), FanVertex(0), TriMode(TRI_MODE_STRIPS), SortLevel(SORT_LEVEL_NONE) { int pass = MAX_PASSES; while (pass--) { MultiTexture[pass] = false; TextureIdx[pass] = -1; MultiVertexMaterial[pass] = false; VertexMaterialIdx[pass] = -1; } for (int color_array_index = 0; color_array_index < MAX_COLOR_ARRAYS; color_array_index++) { MultiVertexColor[color_array_index] = false; CurVertexColor[color_array_index].Set(1.0f, 1.0f, 1.0f, 1.0f); } Model = NEW_REF(DynamicMeshModel, (max_poly, max_vert)); } DynamicMeshClass::DynamicMeshClass(int max_poly, int max_vert, MaterialInfoClass *mat_info) : Model(NULL), PolyCount(0), VertCount(0), TriVertexCount(0), FanVertex(0), TriMode(TRI_MODE_STRIPS), SortLevel(SORT_LEVEL_NONE) { int pass = MAX_PASSES; while (pass--) { MultiTexture[pass] = false; TextureIdx[pass] = -1; MultiVertexMaterial[pass] = false; VertexMaterialIdx[pass] = -1; } for (int color_array_index = 0; color_array_index < MAX_COLOR_ARRAYS; color_array_index++) { MultiVertexColor[color_array_index] = false; CurVertexColor[color_array_index].Set(1.0f, 1.0f, 1.0f, 1.0f); } Model = NEW_REF(DynamicMeshModel, (max_poly, max_vert, mat_info)); } DynamicMeshClass::DynamicMeshClass(const DynamicMeshClass & src) : RenderObjClass(src), Model(NULL), PolyCount(src.PolyCount), VertCount(src.VertCount), TriVertexCount(src.TriVertexCount), FanVertex(src.FanVertex), TriMode(src.TriMode), SortLevel(src.SortLevel) { int pass = MAX_PASSES; while (pass--) { MultiTexture[pass] = src.MultiTexture[pass]; TextureIdx[pass] = src.TextureIdx[pass]; MultiVertexMaterial[pass] = src.MultiVertexMaterial[pass]; VertexMaterialIdx[pass] = src.VertexMaterialIdx[pass]; MultiVertexColor[pass] = src.MultiVertexColor[pass]; CurVertexColor[pass] = src.CurVertexColor[pass]; } for (int color_array_index = 0; color_array_index < MAX_COLOR_ARRAYS; color_array_index++) { MultiVertexColor[color_array_index] = src.MultiVertexColor[color_array_index]; CurVertexColor[color_array_index] = src.CurVertexColor[color_array_index]; } Model = NEW_REF(DynamicMeshModel, (*(src.Model))); } void DynamicMeshClass::Resize(int max_polys, int max_verts) { Reset(); REF_PTR_RELEASE(Model); Model = NEW_REF(DynamicMeshModel, (max_polys, max_verts)); // reset all the texture & vertex material indices int pass = MAX_PASSES; while (pass--) { TextureIdx[pass] = -1; VertexMaterialIdx[pass] = -1; MultiVertexMaterial[pass] = false; } } DynamicMeshClass::~DynamicMeshClass() { REF_PTR_RELEASE(Model); } RenderObjClass * DynamicMeshClass::Clone(void) const { return NEW_REF(DynamicMeshClass, (*this)); } void DynamicMeshClass::Location(float x, float y, float z) { Vector3 * loc = Model->Get_Vertex_Array(); assert(loc); loc[VertCount].X = x; loc[VertCount].Y = y; loc[VertCount].Z = z; } /* ** For moving a vertex after the DynaMesh has already been created. */ void DynamicMeshClass::Move_Vertex(int index, float x, float y, float z) { Vector3 * loc = Model->Get_Vertex_Array(); assert(loc); loc[index][0] = x; loc[index][1] = y; loc[index][2] = z; } /* ** Get a vertex value. */ void DynamicMeshClass::Get_Vertex(int index, float &x, float &y, float &z) { Vector3 * loc = Model->Get_Vertex_Array(); assert(loc); x = loc[index][0]; y = loc[index][1]; z = loc[index][2]; } /* ** Offset the entire mesh */ void DynamicMeshClass::Translate_Vertices(const Vector3 & offset) { Vector3 * loc = Model->Get_Vertex_Array(); assert(loc); for (int i=0; i < Get_Num_Vertices(); i++) { loc[i].X += offset.X; loc[i].Y += offset.Y; loc[i].Z += offset.Z; } Set_Dirty_Bounds(); Set_Dirty_Planes(); } int DynamicMeshClass::Set_Vertex_Material(int idx, int pass) { assert(idx < Peek_Material_Info()->Vertex_Material_Count()); VertexMaterialIdx[pass] = idx; if (!MultiVertexMaterial[pass]) { // WWASSERT( VertexMaterialIdx[pass] == 0); VertexMaterialClass *mat = Peek_Material_Info()->Get_Vertex_Material(VertexMaterialIdx[pass]); Model->Set_Single_Material(mat, pass); mat->Release_Ref(); } return VertexMaterialIdx[pass]; } int DynamicMeshClass::Set_Vertex_Material(VertexMaterialClass *material, bool dont_search, int pass) { // Check if same as the last vertex material if (Peek_Material_Info()->Vertex_Material_Count() && (VertexMaterialIdx[pass] != -1) && Peek_Material_Info()->Peek_Vertex_Material(VertexMaterialIdx[pass]) == material) { return VertexMaterialIdx[pass]; } // if there are vertex materials in the list then we may have just jumped // to becoming a multi-vertex-material object. Take care of that here. if ((!MultiVertexMaterial[pass]) && Peek_Material_Info()->Vertex_Material_Count() && (VertexMaterialIdx[pass] != -1) && Peek_Material_Info()->Peek_Vertex_Material(VertexMaterialIdx[pass]) != material) { // allocate the array of per-vertex vertex material overrides VertexMaterialClass *mat = Peek_Material_Info()->Get_Vertex_Material(VertexMaterialIdx[pass]); Model->Initialize_Material_Array(pass, mat); mat->Release_Ref(); // flag that we need to write the per -vertex vertex material override array MultiVertexMaterial[pass] = true; } // add the material to the material info class if we cant find it in the // list. if we are not supposed to search the list for it then just add // it. if (!dont_search) { for (int lp = 0, found = 0; lp < Peek_Material_Info()->Vertex_Material_Count(); lp ++) { VertexMaterialClass *mat = Peek_Material_Info()->Get_Vertex_Material(lp); if (material == mat) { VertexMaterialIdx[pass] = lp; found = true; mat->Release_Ref(); break; } mat->Release_Ref(); } if (!found) { Peek_Material_Info()->Add_Vertex_Material(material); VertexMaterialIdx[pass] = Peek_Material_Info()->Vertex_Material_Count() - 1; } } else { Peek_Material_Info()->Add_Vertex_Material(material); VertexMaterialIdx[pass] = Peek_Material_Info()->Vertex_Material_Count() - 1; } if (!MultiVertexMaterial[pass]) { Model->Set_Single_Material(Peek_Material_Info()->Peek_Vertex_Material(VertexMaterialIdx[pass]), pass); } return(VertexMaterialIdx[pass]); } int DynamicMeshClass::Set_Texture(int idx, int pass) { WWASSERT(idx < Peek_Material_Info()->Texture_Count()); TextureIdx[pass] = idx; if (!MultiTexture[pass]) { TextureClass *tex = Peek_Material_Info()->Get_Texture(TextureIdx[pass]); Model->Set_Single_Texture(tex, pass); tex->Release_Ref(); } return TextureIdx[pass]; } int DynamicMeshClass::Set_Texture(TextureClass *texture, bool dont_search, int pass) { // Check if same as the last texture if (Peek_Material_Info()->Texture_Count() && (TextureIdx[pass] != -1) && Peek_Material_Info()->Peek_Texture(TextureIdx[pass]) == texture) { return TextureIdx[pass]; } // if there are textures in the list then we may have just jumped // to becoming a multi-texture object. Take care of that here. if ((!MultiTexture[pass]) && Peek_Material_Info()->Texture_Count() && (TextureIdx[pass] != -1) && Peek_Material_Info()->Peek_Texture(TextureIdx[pass]) != texture) { // allocate the array of per polygon material over-rides TextureClass *tex = Peek_Material_Info()->Get_Texture(TextureIdx[pass]); Model->Initialize_Texture_Array(pass, 0, tex); tex->Release_Ref(); // flag that we need to write the per polygon material overide array MultiTexture[pass] = true; } // add the material to the material info class if we cant find it in the // list. if we are not supposed to search the list for it then just add // it. if (!dont_search) { for (int lp = 0, found = 0; lp < Peek_Material_Info()->Texture_Count(); lp ++) { TextureClass *tex = Peek_Material_Info()->Get_Texture(lp); if (texture == tex) { TextureIdx[pass] = lp; found = true; tex->Release_Ref(); break; } tex->Release_Ref(); } if (!found) { Peek_Material_Info()->Add_Texture(texture); TextureIdx[pass] = Peek_Material_Info()->Texture_Count() - 1; } } else { Peek_Material_Info()->Add_Texture(texture); TextureIdx[pass] = Peek_Material_Info()->Texture_Count() - 1; } if (!MultiTexture[pass]) { TextureClass *tex = Peek_Material_Info()->Get_Texture(TextureIdx[pass]); Model->Set_Single_Texture(tex, pass); tex->Release_Ref(); } return(TextureIdx[pass]); } /* ** */ // Remap locations to match a screen void DynamicScreenMeshClass::Location( float x, float y, float z) { DynamicMeshClass::Location( (x * 2) - 1, Aspect - (y * 2 * Aspect), 0); } // For moving a vertex after the DynaMesh has already been created. void DynamicScreenMeshClass::Move_Vertex(int index, float x, float y, float z) { DynamicMeshClass::Move_Vertex( index, (x * 2) - 1, Aspect - (y * 2 * Aspect), 0); } // Set position void DynamicScreenMeshClass::Set_Position(const Vector3 &v) { DynamicMeshClass::Set_Position(Vector3(v.X * 2, -(v.Y * 2 * Aspect), 0)); } void DynamicScreenMeshClass::Reset( void ) { Reset_Flags(); Reset_Mesh_Counters(); }