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.
250 lines
7.3 KiB
C++
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;
|
|
}
|