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.
445 lines
11 KiB
C++
445 lines
11 KiB
C++
#include "ProxyHeaders.hpp"
|
|
|
|
struct AbstractVertex
|
|
{
|
|
Point3D position;
|
|
Normal3D normal;
|
|
Vector2DOf<Scalar> uv;
|
|
RGBAColor color;
|
|
};
|
|
|
|
//
|
|
//############################################################################
|
|
//######################### PolygonMeshProxy ###########################
|
|
//############################################################################
|
|
//
|
|
|
|
PolygonMeshProxy::ClassData*
|
|
PolygonMeshProxy::DefaultData = NULL;
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
void
|
|
PolygonMeshProxy::InitializeClass()
|
|
{
|
|
Verify(!DefaultData);
|
|
DefaultData =
|
|
new ClassData(
|
|
PolygonMeshProxyClassID,
|
|
"PolygonMeshProxy",
|
|
ChildProxy::DefaultData
|
|
);
|
|
Register_Object(DefaultData);
|
|
}
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
void
|
|
PolygonMeshProxy::TerminateClass()
|
|
{
|
|
Unregister_Object(DefaultData);
|
|
delete DefaultData;
|
|
DefaultData = NULL;
|
|
}
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
PolygonMeshProxy::PolygonMeshProxy(
|
|
ClassData *class_data,
|
|
SceneProxy *scene,
|
|
GroupProxy *parent
|
|
):
|
|
ChildProxy(class_data, scene, parent),
|
|
activePolygonProxies(NULL),
|
|
activeVertexProxies(NULL)
|
|
{
|
|
Check_Object(this);
|
|
}
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
PolygonMeshProxy::~PolygonMeshProxy()
|
|
{
|
|
Check_Object(this);
|
|
Verify(activePolygonProxies.IsEmpty());
|
|
}
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
void
|
|
PolygonMeshProxy::TestInstance() const
|
|
{
|
|
Verify(IsDerivedFrom(DefaultData));
|
|
}
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
void
|
|
PolygonMeshProxy::GetCentroid(Point3D *centroid)
|
|
{
|
|
Check_Object(this);
|
|
Check_Object(centroid);
|
|
|
|
//
|
|
//-------------------------------------------------------------------
|
|
// If we have no polygons, just return our local to world translation
|
|
//-------------------------------------------------------------------
|
|
//
|
|
DynamicArrayOf<PolygonProxy*> polygons;
|
|
unsigned polygon_count = UsePolygonArray(&polygons);
|
|
Verify(polygon_count == polygons.GetLength());
|
|
if (!polygon_count)
|
|
{
|
|
*centroid = Point3D::Identity;
|
|
return;
|
|
}
|
|
|
|
//
|
|
//---------------------------------------------
|
|
// Sum up all the polygon centroids and weights
|
|
//---------------------------------------------
|
|
//
|
|
*centroid = Point3D::Identity;
|
|
for (unsigned i=0; i<polygon_count; ++i)
|
|
{
|
|
PolygonProxy *polygon = polygons[i];
|
|
Check_Object(polygon);
|
|
Point3D center;
|
|
Scalar area = polygon->GetSurfaceAreaAndCentroid(¢er);
|
|
if (area > SMALL)
|
|
center /= area;
|
|
*centroid += center;
|
|
}
|
|
*centroid /= static_cast<Scalar>(polygon_count);
|
|
DetachArrayReferences(&polygons);
|
|
}
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
void
|
|
PolygonMeshProxy::Recenter()
|
|
{
|
|
Check_Object(this);
|
|
|
|
//
|
|
//-------------------------------------------------------------------------
|
|
// Now, get our centroid in our mesh space, and recenter the mesh around it
|
|
// in model space
|
|
//-------------------------------------------------------------------------
|
|
//
|
|
Point3D centroid;
|
|
GetCentroid(¢roid);
|
|
if (centroid != Point3D::Identity)
|
|
{
|
|
LinearMatrix4D matrix;
|
|
GetLocalToParent(&matrix);
|
|
LinearMatrix4D shift(true);
|
|
shift.BuildTranslation(centroid);
|
|
LinearMatrix4D new_origin;
|
|
new_origin.Multiply(shift, matrix);
|
|
SetLocalToParent(new_origin);
|
|
|
|
//
|
|
//-----------------------------------------------------------
|
|
// Now we have to subtract the centroid from all our vertices
|
|
//-----------------------------------------------------------
|
|
//
|
|
DynamicArrayOf<VertexProxy*> vertices;
|
|
unsigned vertex_count = UseVertexArray(&vertices);
|
|
for (unsigned i=0; i<vertex_count; ++i)
|
|
{
|
|
VertexProxy *vertex = vertices[i];
|
|
Check_Object(vertex);
|
|
Point3D position;
|
|
vertex->GetPosition(&position);
|
|
position -= centroid;
|
|
vertex->SetPosition(position);
|
|
}
|
|
DetachArrayReferences(&vertices);
|
|
}
|
|
}
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
unsigned
|
|
PolygonMeshProxy::UseMultiStateArray(
|
|
DynamicArrayOf<MultiState*> *states,
|
|
DynamicArrayOf<unsigned> *index,
|
|
DynamicArrayOf<unsigned> *count,
|
|
DynamicArrayOf<PolygonProxy*> &polygons
|
|
)
|
|
{
|
|
Check_Object(this);
|
|
Check_Object(index);
|
|
Check_Object(count);
|
|
Check_Object(states);
|
|
|
|
//
|
|
//----------------------------------------------------------------------
|
|
// We have to evaluate each polygon within the mesh to see how many have
|
|
// unique states, so set up arrays to hold proxies and matching indices
|
|
//----------------------------------------------------------------------
|
|
//
|
|
unsigned polygon_count = polygons.GetLength();
|
|
|
|
//
|
|
//-------------------------------------------------------
|
|
// Spin through the polygons, check for max. nr of states
|
|
//-------------------------------------------------------
|
|
//
|
|
unsigned poly;
|
|
|
|
states->SetLength(polygon_count);
|
|
index->SetLength(polygon_count);
|
|
count->SetLength(polygon_count);
|
|
|
|
unsigned i, j;
|
|
for (i=0; i<polygon_count; ++i)
|
|
(*count)[i] = 0;
|
|
unsigned unique_combinations = 0;
|
|
|
|
//
|
|
//------------------------------------------------------
|
|
// Spin through the polygons, looking for unique entries
|
|
//------------------------------------------------------
|
|
//
|
|
for (poly=0; poly < polygon_count; ++poly)
|
|
{
|
|
PolygonProxy *polygon = polygons[poly];
|
|
Check_Object(polygon);
|
|
MultiState poly_states;
|
|
|
|
polygon->UseMultiState(&poly_states);
|
|
|
|
//
|
|
//-------------------------------------------------------------------
|
|
// Get the state proxies, and see if they index one of
|
|
// the prior entries
|
|
//-------------------------------------------------------------------
|
|
//
|
|
for (i=0; i<unique_combinations;++i)
|
|
{
|
|
//
|
|
//--------------------------------------------------------------
|
|
// Make sure that the state combo has the same length
|
|
//--------------------------------------------------------------
|
|
//
|
|
unsigned state_count = (*states)[i]->GetLength();
|
|
if( poly_states.GetLength() != state_count)
|
|
{
|
|
continue;
|
|
}
|
|
|
|
//
|
|
//--------------------------------------------------------------
|
|
// Make sure that the state and texture exists in either both
|
|
// proxies or neither proxy
|
|
//--------------------------------------------------------------
|
|
//
|
|
for(j=0;j<state_count;++j)
|
|
{
|
|
if ((!poly_states[j] && (*(*states)[i])[j]) ||
|
|
(poly_states[j] && !(*(*states)[i])[j]))
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
|
|
if(j<state_count)
|
|
{
|
|
continue;
|
|
}
|
|
|
|
//
|
|
//-----------------------------------------------
|
|
// Make sure that the state and textures index
|
|
//-----------------------------------------------
|
|
//
|
|
if(poly_states.IsEqualTo(*(*states)[i]))
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
|
|
//
|
|
//-------------------------------------------------------------------
|
|
// If this is a new entry, bump the combo count and store the proxies
|
|
//-------------------------------------------------------------------
|
|
//
|
|
if (i == unique_combinations)
|
|
{
|
|
++unique_combinations;
|
|
(*states)[i] = new MultiState (poly_states);
|
|
// Verify((*states)[i]->GetLength() > 0);
|
|
}
|
|
|
|
//
|
|
//-------------------------
|
|
// Move to the next polygon
|
|
//-------------------------
|
|
//
|
|
(*index)[poly] = i;
|
|
++(*count)[i];
|
|
|
|
poly_states.DetachReferences();
|
|
}
|
|
|
|
//
|
|
//-------------------------------------
|
|
// Release the texture/state proxies
|
|
//-------------------------------------
|
|
//
|
|
states->SetLength(unique_combinations);
|
|
count->SetLength(unique_combinations);
|
|
return unique_combinations;
|
|
}
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
bool
|
|
PolygonMeshProxy::GetBoundingSphere(Sphere *sphere)
|
|
{
|
|
Check_Object(this);
|
|
Check_Pointer(sphere);
|
|
|
|
//
|
|
//---------------------------------------------------------------------
|
|
// Put the center of the sphere at the centroid, then set the radius to
|
|
// just contain the mesh
|
|
//---------------------------------------------------------------------
|
|
//
|
|
DynamicArrayOf<VertexProxy*> vertices;
|
|
unsigned vertex_count = UseVertexArray(&vertices);
|
|
Verify(vertex_count == vertices.GetLength());
|
|
|
|
#if 1
|
|
DynamicArrayOf<Point3D> points;
|
|
points.SetLength(vertex_count);
|
|
for (unsigned i=0; i<vertex_count; ++i)
|
|
{
|
|
VertexProxy *vertex = vertices[i];
|
|
Check_Object(vertex);
|
|
vertex->GetPosition(&points[i]);
|
|
}
|
|
DetachArrayReferences(&vertices);
|
|
sphere->ComputeBounds(points);
|
|
|
|
//
|
|
//-------------------------------------
|
|
// Make sure the radius is properly set
|
|
//-------------------------------------
|
|
//
|
|
if (sphere->radius == -1.0f)
|
|
{
|
|
sphere->radius = 0.0f;
|
|
return false;
|
|
}
|
|
return true;
|
|
#else
|
|
GetCentroid(&sphere->center);
|
|
sphere->radius = -1.0f;
|
|
for (unsigned i=0; i<vertex_count; ++i)
|
|
{
|
|
VertexProxy *vertex = vertices[i];
|
|
Check_Object(vertex);
|
|
Point3D position;
|
|
vertex->GetPosition(&position);
|
|
position -= sphere->center;
|
|
Scalar range = position.GetLengthSquared();
|
|
if (range > sphere->radius)
|
|
sphere->radius = range;
|
|
}
|
|
DetachArrayReferences(&vertices);
|
|
|
|
//
|
|
//-------------------------------------
|
|
// Make sure the radius is properly set
|
|
//-------------------------------------
|
|
//
|
|
if (sphere->radius == -1.0f)
|
|
{
|
|
sphere->radius = 0.0f;
|
|
return false;
|
|
}
|
|
sphere->radius = Sqrt(sphere->radius) + SMALL;
|
|
return true;
|
|
#endif
|
|
}
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
void
|
|
PolygonMeshProxy::DetachPolygonProxy(PolygonProxy* proxy)
|
|
{
|
|
Check_Object(this);
|
|
activePolygonProxies.RemovePlug(proxy);
|
|
Verify(referenceCount > 1);
|
|
DetachReference();
|
|
}
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
void
|
|
PolygonMeshProxy::DetachArrayReferences(
|
|
DynamicArrayOf<MultiState*> *states
|
|
)
|
|
{
|
|
Check_Object(states);
|
|
|
|
//
|
|
//------------------------------
|
|
// Add all the vertices together
|
|
//------------------------------
|
|
//
|
|
unsigned i, state_count = states->GetLength();
|
|
for (i=0; i<state_count; ++i)
|
|
{
|
|
Check_Object((*states)[i]);
|
|
(*states)[i]->DetachReferences();
|
|
}
|
|
}
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
void
|
|
PolygonMeshProxy::DetachArrayReferences(
|
|
DynamicArrayOf<PolygonProxy*> *polygons
|
|
)
|
|
{
|
|
Check_Object(polygons);
|
|
|
|
//
|
|
//------------------------------
|
|
// Add all the vertices together
|
|
//------------------------------
|
|
//
|
|
unsigned polygon_count = polygons->GetLength();
|
|
for (unsigned i=0; i<polygon_count; ++i)
|
|
{
|
|
Check_Object((*polygons)[i]);
|
|
(*polygons)[i]->DetachReference();
|
|
}
|
|
}
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
void
|
|
PolygonMeshProxy::DetachArrayReferences(
|
|
DynamicArrayOf<VertexProxy*> *vertices
|
|
)
|
|
{
|
|
Check_Object(vertices);
|
|
|
|
//
|
|
//------------------------------
|
|
// Add all the vertices together
|
|
//------------------------------
|
|
//
|
|
unsigned vertex_count = vertices->GetLength();
|
|
for (unsigned i=0; i<vertex_count; ++i)
|
|
{
|
|
Check_Object((*vertices)[i]);
|
|
(*vertices)[i]->DetachReference();
|
|
}
|
|
}
|