This repository has been archived on 2025-02-27. You can view files and clone it, but cannot push or open issues or pull requests.
CnC_Renegade/Code/ww3d2/dynamesh.cpp

830 lines
25 KiB
C++

/*
** 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 <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 : 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();
}