Files
firestorm/Gameleap/code/mw4/Libraries/Proxies/PolygonProxy.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

758 lines
18 KiB
C++

#include "ProxyHeaders.hpp"
//
//############################################################################
//########################### Multistate #############################
//############################################################################
//
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
bool
MultiState::IsEqualTo(const MultiState& multi_state)
{
if(GetLength() != multi_state.GetLength())
{
return false;
}
for(unsigned i=0;i<GetLength();++i)
{
if(!((*this)[i]->IsEqualTo(multi_state[i])))
{
return false;
}
}
return true;
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
MultiState::MultiState(const MultiState& multi_state)
{
Check_Object(this);
unsigned state_count = multi_state.GetLength();
SetLength(state_count);
for (unsigned i=0; i<state_count; ++i)
{
(*this)[i] = multi_state[i];
(*this)[i]->AttachReference();
}
isInverted = multi_state.isInverted;
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
MultiState&
MultiState::operator=(const MultiState& multi_state)
{
Check_Object(this);
unsigned state_count = multi_state.GetLength();
SetLength(state_count);
for (unsigned i=0; i<state_count; ++i)
{
(*this)[i] = multi_state[i];
(*this)[i]->AttachReference();
}
isInverted = multi_state.isInverted;
return *this;
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/*
unsigned
MultiState::UseStateArray(MultiState *states)
{
Check_Object(this);
unsigned state_count = GetLength();
states->SetLength(state_count);
for (unsigned i=0; i<state_count; ++i)
{
(*states)[i] = (*this)[i];
(*states)[i]->AttachReference();
}
return state_count;
}
*/
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
MultiState::DetachReferences()
{
for(unsigned i=0;i<GetLength();++i)
{
(*this)[i]->DetachReference();
}
SetLength(0);
}
//
//############################################################################
//########################### PolygonProxy #############################
//############################################################################
//
PolygonProxy::ClassData*
PolygonProxy::DefaultData = NULL;
MemoryBlock*
PolygonProxy::AllocatedMemory = NULL;
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
PolygonProxy::InitializeClass()
{
Verify(!AllocatedMemory);
AllocatedMemory =
new MemoryBlock(
sizeof(PolygonProxy),
100,
100,
"PolygonProxy"
);
Register_Object(AllocatedMemory);
Verify(!DefaultData);
DefaultData =
new ClassData(
PolygonProxyClassID,
"PolygonProxy",
GenericProxy::DefaultData
);
Register_Object(DefaultData);
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
PolygonProxy::TerminateClass()
{
Unregister_Object(DefaultData);
delete DefaultData;
DefaultData = NULL;
Unregister_Object(AllocatedMemory);
delete AllocatedMemory;
AllocatedMemory = NULL;
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
PolygonProxy::PolygonProxy(
ClassData *class_data,
PolygonMeshProxy *mesh
):
GenericProxy(class_data),
meshProxy(mesh),
activeIndexProxies(NULL)
{
Check_Pointer(this);
Check_Object(meshProxy);
meshProxy->AttachPolygonProxy(this);
Check_Object(this);
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
PolygonProxy::PolygonProxy():
GenericProxy(DefaultData),
meshProxy(NULL),
activeIndexProxies(NULL)
{
Check_Object(this);
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
PolygonProxy::~PolygonProxy()
{
Check_Object(this);
//
//---------------------------------------
// Detach the state array if there is one
//---------------------------------------
//
unsigned i;
stateArray.DetachReferences();
//
//----------------------------------------
// Detach the vertex array if there is one
//----------------------------------------
//
unsigned vertex_count = vertexArray.GetLength();
for (i=0; i<vertex_count; ++i)
{
Verify(GetClassID() == PolygonProxyClassID);
Check_Object(vertexArray[i]);
vertexArray[i]->DetachReference();
}
//
//--------------------------------------
// Detach the mesh proxy if there is one
//--------------------------------------
//
if (meshProxy)
{
Check_Object(meshProxy);
Verify(activeIndexProxies.IsEmpty());
meshProxy->DetachPolygonProxy(this);
}
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
PolygonProxy::Destroy()
{
Check_Object(this);
Verify(referenceCount == 1);
Verify(activeIndexProxies.IsEmpty());
DetachReference();
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
PolygonProxy::TestInstance() const
{
Verify(IsDerivedFrom(DefaultData));
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
unsigned
PolygonProxy::UseMultiState(MultiState *states)
{
Check_Object(this);
Verify(GetClassID() == PolygonProxyClassID);
*states = stateArray;
return stateArray.GetLength();
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
PolygonProxy::SetStatesToMatch(const MultiState &states)
{
Check_Object(this);
Verify(GetClassID() == PolygonProxyClassID);
Verify(states.GetLength() > 0);
stateArray = states;
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
PolygonProxy::AddToCollection(const char *group)
{
Check_Object(this);
Check_Pointer(group);
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
PolygonProxy::AddToCollections(MStringChain &group_list)
{
Check_Object(this);
Check_Object(&group_list);
MStringChainIterator groups(&group_list);
PlugOf<MString> *group;
while ((group = groups.ReadAndNext()) != NULL)
{
Check_Object(group);
AddToCollection(group->GetItem());
}
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
PolygonProxy::RemoveFromCollection(const char *group)
{
Check_Object(this);
Check_Pointer(group);
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
PolygonProxy::RemoveFromCollections(MStringChain &group_list)
{
Check_Object(this);
Check_Object(&group_list);
MStringChainIterator groups(&group_list);
PlugOf<MString> *group;
while ((group = groups.ReadAndNext()) != NULL)
{
Check_Object(group);
RemoveFromCollection(group->GetItem());
}
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
PolygonProxy::GetCollections(MStringChain *group_list)
{
Check_Object(this);
Check_Pointer(group_list);
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
bool
PolygonProxy::IsMemberOf(const char* group)
{
Check_Object(this);
Check_Pointer(group);
return false;
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
PolygonProxy::DetachIndexProxy(IndexProxy* proxy)
{
Check_Object(this);
activeIndexProxies.RemovePlug(proxy);
Verify(referenceCount > 1);
DetachReference();
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
PolygonProxy::GetNormal(Normal3D *normal)
{
Check_Object(this);
Check_Pointer(normal);
//
//-----------------
// Get the vertices
//-----------------
//
DynamicArrayOf<IndexProxy*> indices;
#if defined(_ARMOR)
unsigned index_count = UseIndexArray(&indices);
Verify(index_count == indices.GetLength());
Verify(index_count >= 3);
#endif
IndexProxy *index_a = indices[0];
Check_Object(index_a);
IndexProxy *index_b = indices[1];
Check_Object(index_b);
IndexProxy *index_c = indices[2];
Check_Object(index_c);
//
//------------------------------------------
// Get the positions and release the proxies
//------------------------------------------
//
VertexProxy *vertex = index_a->GetVertexProxy();
Check_Object(vertex);
Point3D position_a;
vertex->GetPosition(&position_a);
vertex = index_b->GetVertexProxy();
Check_Object(vertex);
Point3D position_b;
vertex->GetPosition(&position_b);
vertex = index_c->GetVertexProxy();
Check_Object(vertex);
Point3D position_c;
vertex->GetPosition(&position_c);
DetachArrayReferences(&indices);
//
//--------------------
// Get the leg vectors
//--------------------
//
Vector3D
leg_1,
leg_2;
leg_1.Subtract(position_b, position_a);
leg_2.Subtract(position_c, position_a);
//
//----------------------------------------------------------------------
// Compute the cross-product of the two legs to get the direction of the
// normal
//----------------------------------------------------------------------
//
Vector3D v;
v.Cross(leg_1, leg_2);
*normal = v;
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
Scalar
PolygonProxy::GetArea()
{
Check_Object(this);
//
//---------------------
// Set up the variables
//---------------------
//
Point3D
position_a = Point3D::Identity,
position_b,
position_c = Point3D::Identity;
VertexProxy
*vertex_a = NULL,
*vertex_b = NULL,
*vertex_c = NULL;
Vector3D
leg_1,
leg_2 = Vector3D::Identity;
//
//-----------------------------------
// Spin through, testing the vertices
//-----------------------------------
//
Scalar area = 0.0f;
DynamicArrayOf<IndexProxy*> indices;
unsigned index_count = UseIndexArray(&indices);
Verify(index_count == indices.GetLength());
Verify(index_count >= 3);
for (unsigned i=0; i<index_count-2; ++i)
{
//
//-----------------------------------------------
// Generate all the information on the first pass
//-----------------------------------------------
//
if (!i)
{
Check_Object(indices[0]);
vertex_a = indices[0]->GetVertexProxy();
Check_Object(vertex_a);
Check_Object(indices[1]);
vertex_b = indices[1]->GetVertexProxy();
Check_Object(vertex_b);
Check_Object(indices[2]);
vertex_c = indices[2]->GetVertexProxy();
Check_Object(vertex_c);
vertex_a->GetPosition(&position_a);
vertex_b->GetPosition(&position_b);
vertex_c->GetPosition(&position_c);
leg_1.Subtract(position_b, position_a);
leg_2.Subtract(position_c, position_a);
}
//
//--------------------------------------------------------------
// Get the index info. If this is not the first pass, copy the
// information from last pass
//--------------------------------------------------------------
//
else
{
Check_Object(vertex_c);
vertex_b = vertex_c;
Check_Object(indices[i+2]);
vertex_c = indices[i+2]->GetVertexProxy();
Check_Object(vertex_c);
position_b = position_c;
vertex_c->GetPosition(&position_c);
leg_1 = leg_2;
leg_2.Subtract(position_c, position_a);
}
//
//-----------------------------------------------------------------
// Compute the cross-product of the two legs to get the area of the
// triangle
//-----------------------------------------------------------------
//
Vector3D v;
v.Cross(leg_1, leg_2);
area += v.GetLength();
}
//
//-----------------------------
// Delete the remaining proxies
//-----------------------------
//
DetachArrayReferences(&indices);
return 0.5f * area;
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
PolygonProxy::GetVertexCentroid(Point3D *center)
{
Check_Object(this);
Check_Pointer(center);
//
//------------------------------
// Add all the vertices together
//------------------------------
//
*center = Point3D::Identity;
DynamicArrayOf<IndexProxy*> indices;
unsigned index_count = UseIndexArray(&indices);
Verify(index_count >= 3);
Verify(index_count == indices.GetLength());
for (unsigned i=0; i<index_count; ++i)
{
IndexProxy *index = indices[i];
Check_Object(index);
VertexProxy *vertex = index->GetVertexProxy();
Check_Object(vertex);
Point3D position;
vertex->GetPosition(&position);
*center += position;
}
DetachArrayReferences(&indices);
//
//----------------------
// Now, average them all
//----------------------
//
*center /= static_cast<Scalar>(index_count);
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
Scalar
PolygonProxy::GetSurfaceAreaAndCentroid(Point3D *center)
{
Check_Object(this);
//
//---------------------
// Set up the variables
//---------------------
//
Point3D
position_a = Point3D::Identity,
position_b,
position_c = Point3D::Identity;
VertexProxy
*vertex_a = NULL,
*vertex_b = NULL,
*vertex_c = NULL;
Vector3D
leg_1,
leg_2 = Vector3D::Identity;
//
//-----------------------------------
// Spin through, testing the vertices
//-----------------------------------
//
Scalar area = 0.0f;
DynamicArrayOf<IndexProxy*> indices;
unsigned index_count = UseIndexArray(&indices);
Verify(index_count == indices.GetLength());
Verify(index_count >= 3);
*center = Point3D::Identity;
for (unsigned i=0; i<index_count-2; ++i)
{
//
//-----------------------------------------------
// Generate all the information on the first pass
//-----------------------------------------------
//
if (!i)
{
Check_Object(indices[0]);
vertex_a = indices[0]->GetVertexProxy();
Check_Object(vertex_a);
Check_Object(indices[1]);
vertex_b = indices[1]->GetVertexProxy();
Check_Object(vertex_b);
Check_Object(indices[2]);
vertex_c = indices[2]->GetVertexProxy();
Check_Object(vertex_c);
vertex_a->GetPosition(&position_a);
vertex_b->GetPosition(&position_b);
vertex_c->GetPosition(&position_c);
leg_1.Subtract(position_b, position_a);
leg_2.Subtract(position_c, position_a);
}
//
//--------------------------------------------------------------
// Get the index info. If this is not the first pass, copy the
// information from last pass
//--------------------------------------------------------------
//
else
{
Check_Object(vertex_c);
vertex_b = vertex_c;
Check_Object(indices[i+2]);
vertex_c = indices[i+2]->GetVertexProxy();
Check_Object(vertex_c);
position_b = position_c;
vertex_c->GetPosition(&position_c);
leg_1 = leg_2;
leg_2.Subtract(position_c, position_a);
}
//
//-----------------------------------------------------------------
// Compute the cross-product of the two legs to get the area of the
// triangle
//-----------------------------------------------------------------
//
Vector3D v;
v.Cross(leg_1, leg_2);
//
//-------------------------------------------------------------------
// Add the three triangle points together and multiply by the area of
// the triangle to give a weighted sum for the polygon centroid
//-------------------------------------------------------------------
//
Point3D centroid;
centroid.Add(position_a, position_b);
centroid += position_c;
Scalar wedge_area = v.GetLength() * 0.5f;
if (area <= SMALL)
{
if (wedge_area > SMALL)
{
area += wedge_area;
centroid *= wedge_area;
}
*center = centroid;
}
else
{
if (wedge_area > SMALL)
{
area += wedge_area;
centroid *= wedge_area;
*center += centroid;
}
}
}
//
//-----------------------------
// Delete the remaining proxies
//-----------------------------
//
DetachArrayReferences(&indices);
*center *= 1.0f/3.0f;
return area;
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
unsigned
PolygonProxy::UseIndexArray(Stuff::DynamicArrayOf<IndexProxy*> *indices)
{
Verify(GetClassID() == PolygonProxyClassID);
unsigned vertex_count = vertexArray.GetLength();
indices->SetLength(vertex_count);
for (unsigned i=0; i<vertex_count; ++i)
{
(*indices)[i] = IndexProxy::MakeProxy(this, vertexArray[i]);
Register_Object((*indices)[i]);
}
return vertex_count;
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
PolygonProxy::DetachArrayReferences(DynamicArrayOf<IndexProxy*> *indices)
{
Check_Object(this);
Check_Object(indices);
unsigned index_count = indices->GetLength();
for (unsigned i=0; i<index_count; ++i)
{
Check_Object((*indices)[i]);
(*indices)[i]->DetachReference();
}
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
PolygonProxy::SetPolygonIndices(
const Stuff::DynamicArrayOf<VertexProxy*> &vertices
)
{
Check_Object(this);
Check_Object(&vertices);
Verify(GetClassID() == PolygonProxyClassID);
//
//---------------------------------------
// Detach the index array if there is one
//---------------------------------------
//
unsigned vertex_count = vertexArray.GetLength();
unsigned i;
for (i=0; i<vertex_count; ++i)
{
Check_Object(vertexArray[i]);
vertexArray[i]->DetachReference();
}
//
//-------------------------------------------------------------------
// Set the length of the index array, then spin through and create an
// index proxy for each vertex
//-------------------------------------------------------------------
//
vertex_count = vertices.GetLength();
vertexArray.SetLength(vertex_count);
for (i=0; i<vertex_count; ++i)
{
Check_Object(vertices[i]);
vertexArray[i] = vertices[i];
vertexArray[i]->AttachReference();
}
}