Files
firestorm/Gameleap/code/mw4/Libraries/ElementProxies/ElementOptimizeFlatShading.cpp
T
Cyd 2b8ca921cb Initial full mirror of c:\VWE (source + assets + toolchain + outputs) via Git LFS
Complete disaster-recovery snapshot: engine/game source, game data assets,
VC6 toolchain + DX SDKs, build outputs, deployed game, and _UNUSED archive.
Large binaries in Git LFS; text preserved byte-for-byte (core.autocrlf=false,
no eol attributes). See RECOVERY.md for the one-clone rebuild procedure.
2026-06-24 21:28:16 -05:00

250 lines
7.3 KiB
C++

#include "ElementProxyHeaders.hpp"
#include <Proxies\OptimizeFlatShading.hpp>
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
bool
ElementPolygonMeshProxy::OptimizeFlatShading(OptimizeFlatShadingProcess *process)
{
Check_Object(this);
Check_Object(process);
//
//--------------------------
// Make sure we can continue
//--------------------------
//
process->OptimizeCallback(this);
if (!process->continueProcess)
return true;
//
//------------------------------------------------------
// Make sure that we only have a single mesh to evaluate
//------------------------------------------------------
//
unsigned unique_combinations = GetPrimitiveCount();
if (!unique_combinations)
{
Destroy();
return false;
}
Verify(unique_combinations == 1);
//
//--------------------------------------------
// If we aren't in flat coloring mode, we done
//--------------------------------------------
//
MLR_I_PMesh *primitive = GetPrimitive(0);
Check_Object(primitive);
MLRState state = primitive->GetReferenceState();
if (state.GetFlatColoringMode() == MLRState::FlatColoringOffMode)
return true;
//
//-------------------------------------------
// Create a new polymesh and set its position
//-------------------------------------------
//
GroupProxy *parent = GetParentGroupProxy();
LinearMatrix4D m;
GetLocalToParent(&m);
PolygonMeshProxy *mesh;
if (parent)
{
Check_Object(parent);
mesh = parent->AppendNewPolygonMeshProxy();
}
else
mesh = GetSceneProxy()->AppendNewPolygonMeshProxy();
LinearMatrix4D matrix;
if (mesh->GetLocalToParent(&matrix))
SetLocalToParent(matrix);
//
//-----------------------------------------------------------------
// Make an array of all the vertices in the mesh and figure out the
// minimum set of base vertices
//-----------------------------------------------------------------
//
DynamicArrayOf<VertexProxy*> original_vertices;
UseVertexArray(&original_vertices);
unsigned old_vertex_count = original_vertices.GetLength();
DynamicArrayOf<VertexProxy*> new_vertices(old_vertex_count);
DynamicArrayOf<bool> locked(old_vertex_count);
unsigned new_vertex_count=0;
int v,i;
for (v=0; v<old_vertex_count; ++v)
{
VertexProxy *vertex = original_vertices[v];
Check_Object(vertex);
for (i=0; i<new_vertex_count; ++i)
{
if (vertex->IsAllButNormalEqual(new_vertices[i], 0.0f))
break;
}
//
//------------------------------------------------------
// If the vertex couldn't be matched, add it to the list
//------------------------------------------------------
//
if (i == new_vertex_count)
{
Proxies::VertexProxy *new_vertex = Proxies::VertexProxy::MakeProxy();
Check_Object(new_vertex);
Stuff::Point3D pos;
Stuff::Normal3D normal;
Stuff::RGBAColor color;
Stuff::DynamicArrayOf<Stuff::Vector2DOf<Stuff::Scalar> > uvs;
vertex->GetPosition(&pos);
new_vertex->SetPosition(pos);
if (vertex->GetNormal(&normal))
new_vertex->SetNormal(normal);
if (vertex->GetColor(&color))
new_vertex->SetColor(color);
if (vertex->GetUVs(&uvs))
new_vertex->SetUVs(uvs);
locked[new_vertex_count] = false;
new_vertices[new_vertex_count++] = new_vertex;
}
}
//
//-------------------------------------------------
// Go through the poly array and start copying them
//-------------------------------------------------
//
DynamicArrayOf<PolygonProxy*> poly_array;
int polycount = UsePolygonArray(&poly_array);
DynamicArrayOf<PolygonProxy*> newpoly_array(polycount);
for (int p=0; p<polycount; ++p)
{
PolygonProxy *polygon = poly_array[p];
Check_Object(polygon);
//
//---------------
// Copy the state
//---------------
//
MultiState multi_state;
polygon->UseMultiState(&multi_state);
PolygonProxy *new_polygon = Proxies::PolygonProxy::MakeProxy();
Check_Object(new_polygon);
new_polygon->SetStatesToMatch(multi_state);
multi_state.DetachReferences();
//
//----------------------------------------------------------
// Get the indicies, then look for the best first one to use
//----------------------------------------------------------
//
DynamicArrayOf<IndexProxy*> index_array;
int indexcount = polygon->UseIndexArray(&index_array);
DynamicArrayOf<VertexProxy*> newvertex_array(indexcount);
int roll=0;
Search_For_First:
IndexProxy *index = index_array[roll];
Check_Object(index);
Proxies::VertexProxy *old_vertex = index->GetVertexProxy();
Check_Object(old_vertex);
//
//--------------------------------------------------------------------
// Search the current vertex list looking for a match that is unlocked
//--------------------------------------------------------------------
//
for (v=0; v<new_vertex_count; ++v)
{
if (old_vertex->IsAllButNormalEqual(new_vertices[v], 0.0f) && !locked[v])
{
locked[v] = true;
Stuff::Normal3D normal;
if (old_vertex->GetNormal(&normal))
new_vertices[v]->SetNormal(normal);
break;
}
if (old_vertex->IsEqualTo(new_vertices[v], 0.0f))
break;
}
//
//----------------------------------------------------------------
// If we didn't find one, we need to see if maybe one of our other
// vertices should be first
//----------------------------------------------------------------
//
if (v == new_vertex_count)
{
#if 0
if (++roll < indexcount)
goto Search_For_First;
#endif
//
//-------------------------------------------------------------
// We looked at all of them, so now we have to make a new entry
//-------------------------------------------------------------
//
Proxies::VertexProxy *new_vertex = Proxies::VertexProxy::MakeProxy();
Check_Object(new_vertex);
roll = 0;
Stuff::Point3D pos;
Stuff::RGBAColor color;
Stuff::Normal3D normal;
Stuff::DynamicArrayOf<Stuff::Vector2DOf<Stuff::Scalar> > uvs;
old_vertex->GetPosition(&pos);
new_vertex->SetPosition(pos);
if (old_vertex->GetNormal(&normal))
new_vertex->SetNormal(normal);
if (old_vertex->GetColor(&color))
new_vertex->SetColor(color);
if (old_vertex->GetUVs(&uvs))
new_vertex->SetUVs(uvs);
v = new_vertex_count;
locked[new_vertex_count] = true;
new_vertices[new_vertex_count++] = new_vertex;
}
//
//----------------
// Set the indices
//----------------
//
newvertex_array[0] = new_vertices[v];
for (int k=1; k<indexcount; k++)
{
int t = k+roll;
if (t>=indexcount)
t -= indexcount;
old_vertex = index_array[t]->GetVertexProxy();
Check_Object(old_vertex);
for (v=0; v<new_vertex_count; ++v)
{
if (old_vertex->IsAllButNormalEqual(new_vertices[v], 0.0f))
break;
}
Verify(v < new_vertex_count);
newvertex_array[k] = new_vertices[v];
}
new_polygon->SetPolygonIndices(newvertex_array);
newpoly_array[p] = new_polygon;
polygon->DetachArrayReferences(&index_array);
}
Proxies::Process a_process;
mesh->AddPolygons(&a_process,newpoly_array);
mesh->DetachReference();
DetachArrayReferences(&newpoly_array);
DetachArrayReferences(&poly_array);
DetachArrayReferences(&original_vertices);
Destroy();
return false;
}