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.
1708 lines
48 KiB
C++
1708 lines
48 KiB
C++
#include "ElementProxyHeaders.hpp"
|
|
typedef int (*LPERROR_CALLBACKFN)(char *,bool);
|
|
|
|
//
|
|
//############################################################################
|
|
//######################### ElementPolygonMeshProxy #########################
|
|
//############################################################################
|
|
//
|
|
|
|
MemoryBlock*
|
|
ElementPolygonMeshProxy::AllocatedMemory = NULL;
|
|
ElementPolygonMeshProxy::ClassData*
|
|
ElementPolygonMeshProxy::DefaultData = NULL;
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
void
|
|
ElementPolygonMeshProxy::InitializeClass()
|
|
{
|
|
Verify(!AllocatedMemory);
|
|
AllocatedMemory =
|
|
new MemoryBlock(
|
|
sizeof(ElementPolygonMeshProxy),
|
|
10,
|
|
10,
|
|
"ElementPolygonMeshProxy"
|
|
);
|
|
Register_Object(AllocatedMemory);
|
|
|
|
Verify(!DefaultData);
|
|
DefaultData =
|
|
new ClassData(
|
|
ElementPolygonMeshProxyClassID,
|
|
"ElementPolygonMeshProxy",
|
|
PolygonMeshProxy::DefaultData
|
|
);
|
|
Register_Object(DefaultData);
|
|
}
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
void
|
|
ElementPolygonMeshProxy::TerminateClass()
|
|
{
|
|
Unregister_Object(DefaultData);
|
|
delete DefaultData;
|
|
DefaultData = NULL;
|
|
|
|
Unregister_Object(AllocatedMemory);
|
|
delete AllocatedMemory;
|
|
AllocatedMemory = NULL;
|
|
}
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
void
|
|
ElementPolygonMeshProxy::Destroy()
|
|
{
|
|
Check_Object(this);
|
|
Verify(referenceCount == 1);
|
|
Verify(activePolygonProxies.IsEmpty());
|
|
ShapeElement* shape = proxiedShape;
|
|
DetachReference();
|
|
Verify(shape->GetMLRShape()->GetReferenceCount() == 1);
|
|
Unregister_Object(shape);
|
|
delete shape;
|
|
}
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
ElementPolygonMeshProxy::ElementPolygonMeshProxy(
|
|
ElementSceneProxy *scene,
|
|
GroupProxy *parent,
|
|
ShapeElement *shape,
|
|
ChainIterator *iterator
|
|
):
|
|
PolygonMeshProxy(DefaultData, scene, parent),
|
|
proxiedShape(shape),
|
|
siblingIterator(iterator)
|
|
{
|
|
Check_Pointer(this);
|
|
Check_Object(scene);
|
|
Check_Object(shape);
|
|
|
|
//
|
|
//----------------------------------------------
|
|
// If the shape holds no primitives, we are done
|
|
//----------------------------------------------
|
|
//
|
|
Check_Object(proxiedShape);
|
|
mlrShape = proxiedShape->GetMLRShape();
|
|
if (mlrShape)
|
|
{
|
|
Check_Object(mlrShape);
|
|
mlrShape->AttachReference();
|
|
Verify(mlrShape->GetReferenceCount() == 2);
|
|
LoadArrays();
|
|
}
|
|
Check_Object(this);
|
|
}
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
ElementPolygonMeshProxy::~ElementPolygonMeshProxy()
|
|
{
|
|
Check_Object(this);
|
|
Unregister_Object(siblingIterator);
|
|
delete siblingIterator;
|
|
if (mlrShape)
|
|
{
|
|
Verify(mlrShape->GetReferenceCount() >= 2);
|
|
Check_Object(mlrShape);
|
|
mlrShape->DetachReference();
|
|
}
|
|
}
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
void
|
|
ElementPolygonMeshProxy::TestInstance() const
|
|
{
|
|
Verify(IsDerivedFrom(DefaultData));
|
|
Check_Object(siblingIterator);
|
|
}
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
void
|
|
ElementPolygonMeshProxy::TransferAndAppendToParentGroup(GroupProxy *parent)
|
|
{
|
|
Check_Object(this);
|
|
|
|
//
|
|
//--------------------------------------------
|
|
// Delete our attachment to our current parent
|
|
//--------------------------------------------
|
|
//
|
|
Check_Pointer(proxiedShape);
|
|
proxiedShape->DetachFromParent();
|
|
ElementGroupProxy *old_parent =
|
|
static_cast<ElementGroupProxy*>(GetParentGroupProxy());
|
|
if (old_parent)
|
|
{
|
|
Check_Object(old_parent);
|
|
old_parent->DetachChildProxy(this);
|
|
GetSceneProxy()->DetachReference();
|
|
}
|
|
else
|
|
{
|
|
Check_Object(GetSceneProxy());
|
|
GetSceneProxy()->DetachChildProxy(this);
|
|
}
|
|
|
|
//
|
|
//---------------------------------------------------------------------
|
|
// If a parent is specified, then attach to it, otherwise attach to the
|
|
// scene
|
|
//---------------------------------------------------------------------
|
|
//
|
|
GroupElement *parent_rec;
|
|
parentProxy = parent;
|
|
if (parent)
|
|
{
|
|
ElementGroupProxy *element_parent =
|
|
Cast_Object(ElementGroupProxy*, parent);
|
|
parent_rec = element_parent->GetProxiedGroup();
|
|
parent->AttachChildProxy(this);
|
|
GetSceneProxy()->AttachReference();
|
|
}
|
|
else
|
|
{
|
|
ElementSceneProxy *scene = GetSceneProxy();
|
|
Check_Object(scene);
|
|
parent_rec = scene->GetProxiedScene();
|
|
scene->AttachChildProxy(this);
|
|
}
|
|
Check_Pointer(parent_rec);
|
|
parent_rec->AttachChild(proxiedShape);
|
|
proxiedShape->Sync();
|
|
}
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
ChildProxy*
|
|
ElementPolygonMeshProxy::UseNextSiblingProxy()
|
|
{
|
|
Check_Object(this);
|
|
|
|
//
|
|
//------------------------------------------------------------------------
|
|
// Clone our iterator, then move it and have the scene figure out the type
|
|
// of proxy to create
|
|
//------------------------------------------------------------------------
|
|
//
|
|
Check_Object(siblingIterator);
|
|
ChainIterator *iterator = siblingIterator->MakeClone();
|
|
Register_Object(iterator);
|
|
iterator->Next();
|
|
return GetSceneProxy()->InterpretElement(GetParentGroupProxy(), iterator);
|
|
}
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
ChildProxy*
|
|
ElementPolygonMeshProxy::UsePreviousSiblingProxy()
|
|
{
|
|
Check_Object(this);
|
|
|
|
//
|
|
//------------------------------------------------------------------------
|
|
// Clone our iterator, then move it and have the scene figure out the type
|
|
// of proxy to create
|
|
//------------------------------------------------------------------------
|
|
//
|
|
Check_Object(siblingIterator);
|
|
ChainIterator *iterator = siblingIterator->MakeClone();
|
|
Register_Object(iterator);
|
|
iterator->Previous();
|
|
return GetSceneProxy()->InterpretElement(GetParentGroupProxy(), iterator);
|
|
}
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
bool
|
|
ElementPolygonMeshProxy::GetName(MString *name)
|
|
{
|
|
Check_Object(this);
|
|
Check_Object(name);
|
|
Check_Object(proxiedShape);
|
|
*name = m_name;
|
|
return !(!m_name);
|
|
}
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
void
|
|
ElementPolygonMeshProxy::SetName(const char* name)
|
|
{
|
|
Check_Object(this);
|
|
Check_Pointer(proxiedShape);
|
|
m_name=name;
|
|
}
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
bool
|
|
ElementPolygonMeshProxy::GetLocalToParent(LinearMatrix4D *matrix)
|
|
{
|
|
Check_Object(this);
|
|
Check_Pointer(matrix);
|
|
Check_Object(proxiedShape);
|
|
*matrix = proxiedShape->GetLocalToParent();
|
|
return *matrix != LinearMatrix4D::Identity;
|
|
}
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
void
|
|
ElementPolygonMeshProxy::SetLocalToParent(const LinearMatrix4D &matrix)
|
|
{
|
|
Check_Object(this);
|
|
Check_Object(&matrix);
|
|
Check_Object(proxiedShape);
|
|
if (matrix == LinearMatrix4D::Identity)
|
|
proxiedShape->SetLocalToParentToIdentity();
|
|
else
|
|
proxiedShape->SetLocalToParent(matrix);
|
|
proxiedShape->Sync();
|
|
}
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
void
|
|
ElementPolygonMeshProxy::GetCentroid(Point3D *center)
|
|
{
|
|
Check_Object(this);
|
|
Check_Pointer(center);
|
|
Check_Object(proxiedShape);
|
|
if (proxiedShape->m_localOBB.sphereRadius > 0.0f)
|
|
*center = proxiedShape->m_localOBB.localToParent;
|
|
else
|
|
PolygonMeshProxy::GetCentroid(center);
|
|
}
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
bool
|
|
ElementPolygonMeshProxy::GetOBB(OBB *obb)
|
|
{
|
|
Check_Object(this);
|
|
Check_Pointer(obb);
|
|
Check_Object(proxiedShape);
|
|
|
|
//
|
|
//-----------------------------------------------
|
|
// Make sure that this proxy thinks it has an OBB
|
|
//-----------------------------------------------
|
|
//
|
|
if (!proxiedShape->IsBoundedByOBB())
|
|
return false;
|
|
|
|
//
|
|
//------------------------------
|
|
// Copy the data into the sphere
|
|
//------------------------------
|
|
//
|
|
*obb = proxiedShape->m_localOBB;
|
|
return true;
|
|
}
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
void
|
|
ElementPolygonMeshProxy::SetOBB(const OBB &obb)
|
|
{
|
|
Check_Object(this);
|
|
Check_Object(&obb);
|
|
Check_Object(proxiedShape);
|
|
|
|
//
|
|
//-------------------------------------------------------------------------
|
|
// Set the element into sphere mode, and copy the sphere data into the OBB.
|
|
// Then sync it up so everyone is happy
|
|
//-------------------------------------------------------------------------
|
|
//
|
|
proxiedShape->m_localOBB = obb;
|
|
proxiedShape->SetOBBMode();
|
|
proxiedShape->SetVolumeCullMode();
|
|
proxiedShape->Sync();
|
|
}
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
bool
|
|
ElementPolygonMeshProxy::GetBoundingSphere(Sphere *sphere)
|
|
{
|
|
Check_Object(this);
|
|
Check_Pointer(sphere);
|
|
Check_Object(proxiedShape);
|
|
|
|
//
|
|
//------------------------------
|
|
// Copy the data into the sphere
|
|
//------------------------------
|
|
//
|
|
sphere->center = proxiedShape->m_localOBB.localToParent;
|
|
sphere->radius = proxiedShape->m_localOBB.sphereRadius;
|
|
return true;
|
|
}
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
void
|
|
ElementPolygonMeshProxy::SetBoundingSphere(const Sphere &sphere)
|
|
{
|
|
Check_Object(this);
|
|
Check_Object(&sphere);
|
|
Check_Object(proxiedShape);
|
|
|
|
//
|
|
//-------------------------------------------------------------------------
|
|
// Set the element into sphere mode, and copy the sphere data into the OBB.
|
|
// Then sync it up so everyone is happy
|
|
//-------------------------------------------------------------------------
|
|
//
|
|
proxiedShape->m_localOBB.localToParent.BuildTranslation(sphere.center);
|
|
proxiedShape->m_localOBB.sphereRadius = sphere.radius;
|
|
proxiedShape->SetSphereMode();
|
|
proxiedShape->SetVolumeCullMode();
|
|
proxiedShape->Sync();
|
|
|
|
//
|
|
//----------------------------------------------------------------------
|
|
// If we are running slow enough, go ahead and check our vertices to see
|
|
// that they are in the bounds
|
|
//----------------------------------------------------------------------
|
|
//
|
|
#if defined(_ARMOR)
|
|
Point3D center(proxiedShape->m_localOBB.localToParent);
|
|
Scalar radius_squared =
|
|
proxiedShape->m_localOBB.sphereRadius*proxiedShape->m_localOBB.sphereRadius;
|
|
MidLevelRenderer::MLRShape *shape = proxiedShape->GetMLRShape();
|
|
Check_Object(shape);
|
|
int meshes = shape->GetNum();
|
|
for(int m=0; m<meshes; m++)
|
|
{
|
|
MidLevelRenderer::MLRPrimitiveBase *mesh = shape->Find(m);
|
|
Check_Object(mesh);
|
|
const Point3D *verts;
|
|
int count;
|
|
mesh->GetCoordData(&verts, &count);
|
|
for (int v=0; v<count; ++v)
|
|
{
|
|
Vector3D diff;
|
|
diff.Subtract(verts[v], center);
|
|
Scalar room = radius_squared - diff.GetLengthSquared();
|
|
Verify(room >= 0.0f);
|
|
}
|
|
}
|
|
#endif
|
|
}
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
unsigned
|
|
ElementPolygonMeshProxy::UsePolygonArray(DynamicArrayOf<PolygonProxy*> *polygons)
|
|
{
|
|
Check_Object(this);
|
|
Check_Object(polygons);
|
|
|
|
//
|
|
//---------------------------------------
|
|
// Figure out how many polygons there are
|
|
//---------------------------------------
|
|
//
|
|
unsigned poly_count = 0;
|
|
unsigned primitive;
|
|
unsigned primitive_count = primitiveArray.GetLength();
|
|
for (primitive=0; primitive<primitive_count; ++primitive)
|
|
{
|
|
poly_count += polygonCountArray[primitive];
|
|
}
|
|
polygons->SetLength(poly_count);
|
|
|
|
//
|
|
//------------------
|
|
// Fill in the array
|
|
//------------------
|
|
//
|
|
poly_count = 0;
|
|
for (primitive=0; primitive<primitive_count; ++primitive)
|
|
{
|
|
for (unsigned polygon=0; polygon<polygonCountArray[primitive]; ++polygon)
|
|
{
|
|
(*polygons)[poly_count] =
|
|
MLRPolygonProxy::MakeProxy(
|
|
this,
|
|
primitive,
|
|
polygon
|
|
);
|
|
Register_Object((*polygons)[poly_count]);
|
|
++poly_count;
|
|
}
|
|
}
|
|
return poly_count;
|
|
}
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
void
|
|
ElementPolygonMeshProxy::AddPolygons(
|
|
Process *process,
|
|
Stuff::DynamicArrayOf<PolygonProxy*> &source_polygons
|
|
)
|
|
{
|
|
Check_Object(this);
|
|
Check_Object(process);
|
|
Check_Object(&source_polygons);
|
|
|
|
//
|
|
//------------------------------------------------------------------
|
|
// Make an array out of both the source polys and the existing polys
|
|
//------------------------------------------------------------------
|
|
//
|
|
DynamicArrayOf<PolygonProxy*> existing_polygons;
|
|
unsigned existing_polys = UsePolygonArray(&existing_polygons);
|
|
unsigned source_polys = source_polygons.GetLength();
|
|
unsigned total_polys = existing_polys + source_polys;
|
|
DynamicArrayOf<PolygonProxy*> new_polys(total_polys);
|
|
unsigned i;
|
|
for (i=0; i<existing_polys; ++i)
|
|
new_polys[i] = existing_polygons[i];
|
|
for (i=0; i<source_polys; ++i)
|
|
new_polys[i+existing_polys] = source_polygons[i];
|
|
|
|
//
|
|
//------------------------------------------------------------------
|
|
// Get index arrays for all the polygons
|
|
//------------------------------------------------------------------
|
|
//
|
|
DynamicArrayOf<DynamicArrayOf<IndexProxy*> > indices(total_polys);
|
|
for (i=0; i<total_polys; ++i)
|
|
{
|
|
PolygonProxy *polygon = new_polys[i];
|
|
Check_Object(polygon);
|
|
polygon->UseIndexArray(&indices[i]);
|
|
}
|
|
|
|
//
|
|
//-------------------------------------------------
|
|
// Now do the state analysis of the new polygon set
|
|
//-------------------------------------------------
|
|
//
|
|
DynamicArrayOf<unsigned> match;
|
|
DynamicArrayOf<unsigned> count;
|
|
DynamicArrayOf<MultiState*> multi_states;
|
|
unsigned unique_combinations =
|
|
UseMultiStateArray(&multi_states, &match, &count, new_polys);
|
|
Verify(unique_combinations>0);
|
|
|
|
//
|
|
//----------------------------------------------------------------
|
|
// We need to create one MLRPolyMesh object per unique combination
|
|
//----------------------------------------------------------------
|
|
//
|
|
gos_PushCurrentHeap(MidLevelRenderer::ShapeHeap);
|
|
MLRShape *new_shape = new MLRShape(unique_combinations);
|
|
Register_Object(new_shape);
|
|
|
|
int primitive;
|
|
for (primitive=0; primitive<unique_combinations; ++primitive)
|
|
{
|
|
Verify( multi_states[primitive]->GetLength() >= 0 &&
|
|
multi_states[primitive]->GetLength() <= 2);
|
|
|
|
|
|
MLRPrimitiveBase* mesh = CreateNewMesh(multi_states[primitive]);
|
|
Register_Object(mesh);
|
|
new_shape->Add(mesh);
|
|
//
|
|
//--------------------------------------------------------------------
|
|
// For each unique combination, we need to create the mesh data
|
|
// structures, so we need to first identify the polygons to be grouped
|
|
// together
|
|
//--------------------------------------------------------------------
|
|
//
|
|
Verify(count[primitive]>0);
|
|
DynamicArrayOf<PolygonProxy*> polygons(count[primitive]);
|
|
DynamicArrayOf<VertexProxy*> vertices(Limits::Max_Number_Vertices_Per_Mesh+Limits::Max_Number_Vertices_Per_Polygon);
|
|
|
|
unsigned i;
|
|
unsigned poly_count = 0;
|
|
unsigned vertex_count = 0;
|
|
for (i=0; i<total_polys && poly_count<count[primitive]; ++i)
|
|
{
|
|
PolygonProxy *polygon = new_polys[i];
|
|
Check_Object(polygon);
|
|
if (match[i] == primitive)
|
|
{
|
|
for (unsigned j=0; j<indices[i].GetLength(); ++j)
|
|
{
|
|
IndexProxy *index = indices[i][j];
|
|
Check_Object(index);
|
|
VertexProxy *vertex = index->GetVertexProxy();
|
|
Check_Object(vertex);
|
|
|
|
//
|
|
//--------------------------------------------------------------------
|
|
// Compare this vertex proxy to what is already in our pool, and if it
|
|
// matches, just use it, otherwise stuff it in the pool
|
|
//--------------------------------------------------------------------
|
|
//
|
|
VertexProxy::AddUniqueVertex(
|
|
vertices,
|
|
&vertex_count,
|
|
vertex,
|
|
process->duplicateVertexTolerance
|
|
);
|
|
}
|
|
|
|
if (vertex_count<=Limits::Max_Number_Vertices_Per_Mesh) {
|
|
polygons[poly_count++] = polygon;
|
|
}
|
|
else {
|
|
if(multi_states[primitive]->GetLength() < 2)
|
|
{
|
|
SetPolyMeshArrays(
|
|
Cast_Pointer(MLR_I_L_PMesh*, mesh),
|
|
polygons,
|
|
poly_count,
|
|
process
|
|
);
|
|
}
|
|
else
|
|
{
|
|
SetPolyMeshArrays(
|
|
Cast_Pointer(MLR_I_L_DT_PMesh*, mesh),
|
|
polygons,
|
|
poly_count,
|
|
process,
|
|
multi_states[primitive]->isInverted
|
|
);
|
|
}
|
|
|
|
mesh->DetachReference();
|
|
|
|
mesh = CreateNewMesh(multi_states[primitive]);
|
|
Register_Object(mesh);
|
|
new_shape->Add(mesh);
|
|
|
|
vertex_count=0;
|
|
for (unsigned j=0; j<indices[i].GetLength(); ++j)
|
|
{
|
|
IndexProxy *index = indices[i][j];
|
|
Check_Object(index);
|
|
VertexProxy *vertex = index->GetVertexProxy();
|
|
Check_Object(vertex);
|
|
|
|
//
|
|
//--------------------------------------------------------------------
|
|
// Compare this vertex proxy to what is already in our pool, and if it
|
|
// matches, just use it, otherwise stuff it in the pool
|
|
//--------------------------------------------------------------------
|
|
//
|
|
VertexProxy::AddUniqueVertex(
|
|
vertices,
|
|
&vertex_count,
|
|
vertex,
|
|
process->duplicateVertexTolerance
|
|
);
|
|
}
|
|
poly_count=0;
|
|
polygons[poly_count++] = polygon;
|
|
}
|
|
}
|
|
}
|
|
|
|
Verify(poly_count <= count[primitive]);
|
|
|
|
if(multi_states[primitive]->GetLength() < 2 && polygons.GetLength()>0)
|
|
{
|
|
SetPolyMeshArrays(
|
|
Cast_Pointer(MLR_I_L_PMesh*, mesh),
|
|
polygons,
|
|
poly_count,
|
|
process
|
|
);
|
|
}
|
|
else if (polygons.GetLength()>0)
|
|
{
|
|
SetPolyMeshArrays(
|
|
Cast_Pointer(MLR_I_L_DT_PMesh*, mesh),
|
|
polygons,
|
|
poly_count,
|
|
process,
|
|
multi_states[primitive]->isInverted
|
|
);
|
|
}
|
|
|
|
multi_states[primitive]->DetachReferences();
|
|
mesh->DetachReference();
|
|
}
|
|
|
|
//
|
|
//-----------------------------
|
|
// Now clean up the index array
|
|
//-----------------------------
|
|
//
|
|
for (i=0; i<total_polys; ++i)
|
|
{
|
|
Check_Object(new_polys[i]);
|
|
Check_Object(&indices[i]);
|
|
new_polys[i]->DetachArrayReferences(&indices[i]);
|
|
}
|
|
|
|
//
|
|
//-----------------------------------------------------------------------
|
|
// Now we need to clean out the shape and stick the new primitives inside
|
|
// it
|
|
//-----------------------------------------------------------------------
|
|
//
|
|
DetachArrayReferences(&existing_polygons);
|
|
mlrShape->DetachReference();
|
|
Check_Object(proxiedShape);
|
|
proxiedShape->SetMLRShape(new_shape);
|
|
mlrShape = new_shape;
|
|
// mlrShape->AttachReference();
|
|
|
|
gos_PopCurrentHeap();
|
|
|
|
//
|
|
//----------------------------------------------------------
|
|
// Clean up the proxy arrays, then load up the useful arrays
|
|
//----------------------------------------------------------
|
|
//
|
|
LoadArrays();
|
|
}
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
void
|
|
ElementPolygonMeshProxy::SetToMatchMultiState(Proxies::MultiState* multi_state)
|
|
{
|
|
Check_Object(this);
|
|
Check_Object(multi_state);
|
|
|
|
Verify(multi_state->GetLength() > 0 && multi_state->GetLength() <= 2);
|
|
|
|
if(multi_state->GetLength() == 1)
|
|
{
|
|
//
|
|
//-------------------------------------------------------------------------
|
|
// We need to get a state proxy from the state library that matches what we
|
|
// were given
|
|
//-------------------------------------------------------------------------
|
|
//
|
|
MLRStateProxy *our_proxy = Cast_Object(MLRStateProxy*, (*multi_state)[0]);
|
|
|
|
//
|
|
//-----------------------------------------------------------------------
|
|
// Now, spin through all the primitives, and set their MLRStates to match
|
|
// that of our state proxy
|
|
//-----------------------------------------------------------------------
|
|
//
|
|
unsigned primitive_count = primitiveArray.GetLength();
|
|
for (unsigned i=0; i<primitive_count; ++i)
|
|
primitiveArray[i]->SetReferenceState(our_proxy->GetMLRState());
|
|
}
|
|
else
|
|
{
|
|
//
|
|
//-------------------------------------------------------------------------
|
|
// We need to get a state proxy from the state library that matches what we
|
|
// were given
|
|
//-------------------------------------------------------------------------
|
|
//
|
|
MLRStateProxy *our_proxy = NULL, *our_proxy1 = NULL;
|
|
if(multi_state->isInverted == false)
|
|
{
|
|
our_proxy = Cast_Object(MLRStateProxy*, (*multi_state)[0]);
|
|
our_proxy1 = Cast_Object(MLRStateProxy*, (*multi_state)[1]);
|
|
}
|
|
else
|
|
{
|
|
our_proxy1 = Cast_Object(MLRStateProxy*, (*multi_state)[0]);
|
|
our_proxy = Cast_Object(MLRStateProxy*, (*multi_state)[1]);
|
|
}
|
|
|
|
//
|
|
//-----------------------------------------------------------------------
|
|
// Now, spin through all the primitives, and set their MLRStates to match
|
|
// that of our state proxy
|
|
//-----------------------------------------------------------------------
|
|
//
|
|
unsigned primitive_count = primitiveArray.GetLength();
|
|
for (unsigned i=0; i<primitive_count; ++i)
|
|
{
|
|
primitiveArray[i]->SetReferenceState(our_proxy->GetMLRState());
|
|
primitiveArray[i]->SetReferenceState(our_proxy1->GetMLRState(), 1);
|
|
}
|
|
}
|
|
}
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
unsigned
|
|
ElementPolygonMeshProxy::UseVertexArray(DynamicArrayOf<VertexProxy*> *vertices)
|
|
{
|
|
Check_Object(this);
|
|
Check_Object(vertices);
|
|
|
|
//
|
|
//---------------------------------------
|
|
// Figure out how many vertices there are
|
|
//---------------------------------------
|
|
//
|
|
unsigned vertex_count = 0;
|
|
unsigned primitive;
|
|
unsigned primitive_count = primitiveArray.GetLength();
|
|
for (primitive=0; primitive<primitive_count; ++primitive)
|
|
{
|
|
vertex_count += vertexCountArray[primitive];
|
|
}
|
|
vertices->SetLength(vertex_count);
|
|
|
|
//
|
|
//------------------
|
|
// Fill in the array
|
|
//------------------
|
|
//
|
|
vertex_count = 0;
|
|
for (primitive=0; primitive<primitive_count; ++primitive)
|
|
{
|
|
for (unsigned vertex=0; vertex<vertexCountArray[primitive]; ++vertex)
|
|
{
|
|
(*vertices)[vertex_count] =
|
|
MLRVertexProxy::MakeProxy(
|
|
this,
|
|
primitive,
|
|
vertex
|
|
);
|
|
Register_Object((*vertices)[vertex_count]);
|
|
++vertex_count;
|
|
}
|
|
}
|
|
return vertex_count;
|
|
}
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
PolygonProxy*
|
|
ElementPolygonMeshProxy::GetPolygonProxy(
|
|
int primitive_index,
|
|
int polygon_index
|
|
)
|
|
{
|
|
Check_Object(this);
|
|
Verify(static_cast<unsigned>(primitive_index) < primitiveArray.GetLength());
|
|
|
|
//
|
|
//-----------------------------------------------------------------------
|
|
// See if we have walked off the end of the primitive, and if so, we need
|
|
// to find the next primitive
|
|
//-----------------------------------------------------------------------
|
|
//
|
|
int poly_count = polygonCountArray[primitive_index];
|
|
Verify(poly_count > 0);
|
|
if (polygon_index == poly_count)
|
|
{
|
|
if (++primitive_index == primitiveArray.GetLength())
|
|
return NULL;
|
|
polygon_index = 0;
|
|
}
|
|
|
|
//
|
|
//-------------------------------
|
|
// See if we walked off backwards
|
|
//-------------------------------
|
|
//
|
|
else if (polygon_index == -1)
|
|
{
|
|
--primitive_index;
|
|
if (primitive_index < 0)
|
|
{
|
|
return NULL;
|
|
}
|
|
polygon_index = polygonCountArray[primitive_index] - 1;
|
|
}
|
|
|
|
//
|
|
//---------------------------------
|
|
// We found one, so make a new mesh
|
|
//---------------------------------
|
|
//
|
|
Verify(polygon_index >= 0 && polygon_index < poly_count);
|
|
Verify(primitive_index >= 0 && primitive_index < primitiveArray.GetLength());
|
|
PolygonProxy *proxy =
|
|
MLRPolygonProxy::MakeProxy(
|
|
this,
|
|
primitive_index,
|
|
polygon_index
|
|
);
|
|
Register_Object(proxy);
|
|
return proxy;
|
|
}
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
VertexProxy*
|
|
ElementPolygonMeshProxy::GetVertexProxy(
|
|
int primitive_index,
|
|
int vertex_index
|
|
)
|
|
{
|
|
Check_Object(this);
|
|
Verify(static_cast<unsigned>(primitive_index) < primitiveArray.GetLength());
|
|
|
|
//
|
|
//-----------------------------------------------------------------------
|
|
// See if we have walked off the end of the primitive, and if so, we need
|
|
// to find the next primitive
|
|
//-----------------------------------------------------------------------
|
|
//
|
|
int vertex_count = vertexCountArray[primitive_index];
|
|
Verify(vertex_count > 0);
|
|
if (vertex_index == vertex_count)
|
|
{
|
|
if (++primitive_index == primitiveArray.GetLength())
|
|
return NULL;
|
|
vertex_index = 0;
|
|
}
|
|
|
|
//
|
|
//-------------------------------
|
|
// See if we walked off backwards
|
|
//-------------------------------
|
|
//
|
|
else if (vertex_index == -1)
|
|
{
|
|
--primitive_index;
|
|
if (primitive_index < 0)
|
|
return NULL;
|
|
vertex_index = vertexCountArray[primitive_index] - 1;
|
|
}
|
|
|
|
//
|
|
//---------------------------------
|
|
// We found one, so make a new mesh
|
|
//---------------------------------
|
|
//
|
|
Verify(vertex_index >= 0 && vertex_index < vertex_count);
|
|
Verify(primitive_index >= 0 && primitive_index < primitiveArray.GetLength());
|
|
VertexProxy *proxy =
|
|
MLRVertexProxy::MakeProxy(
|
|
this,
|
|
primitive_index,
|
|
vertex_index
|
|
);
|
|
Register_Object(proxy);
|
|
return proxy;
|
|
}
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
void
|
|
ElementPolygonMeshProxy::LoadArrays()
|
|
{
|
|
Check_Object(this);
|
|
|
|
//
|
|
//----------------------
|
|
// Initialize the arrays
|
|
//----------------------
|
|
//
|
|
primitiveArray.SetLength(0);
|
|
polygonCountArray.SetLength(0);
|
|
vertexCountArray.SetLength(0);
|
|
indexArray.SetLength(0);
|
|
indexCountArray.SetLength(0);
|
|
positionArray.SetLength(0);
|
|
normalArray.SetLength(0);
|
|
colorArray.SetLength(0);
|
|
uvArray.SetLength(0);
|
|
|
|
//
|
|
//----------------------------------------------
|
|
// If the shape holds no primitives, we are done
|
|
//----------------------------------------------
|
|
//
|
|
if (!mlrShape)
|
|
return;
|
|
|
|
//
|
|
//----------------------------------------------------------------------
|
|
// Figure out how many primitive there are, then fill up the arrays with
|
|
// stuff from each of them
|
|
//----------------------------------------------------------------------
|
|
//
|
|
Check_Object(mlrShape);
|
|
int primitive_count = mlrShape->GetNum();
|
|
primitiveArray.SetLength(primitive_count);
|
|
polygonCountArray.SetLength(primitive_count);
|
|
vertexCountArray.SetLength(primitive_count);
|
|
indexCountArray.SetLength(primitive_count);
|
|
indexArray.SetLength(primitive_count);
|
|
positionArray.SetLength(primitive_count);
|
|
normalArray.SetLength(primitive_count);
|
|
colorArray.SetLength(primitive_count);
|
|
|
|
uvArray.SetLength(primitive_count);
|
|
|
|
int primitive;
|
|
for (primitive=0; primitive<primitive_count; ++primitive)
|
|
{
|
|
//
|
|
//-------------------
|
|
// Grab the primitive
|
|
//-------------------
|
|
//
|
|
|
|
MLRPrimitiveBase *mesh = mlrShape->Find(primitive);
|
|
|
|
if(mesh->IsDerivedFrom(MLR_I_PMesh::DefaultData))
|
|
{
|
|
primitiveArray[primitive] =
|
|
Cast_Object(MLR_I_PMesh*, mesh);
|
|
}
|
|
else
|
|
{
|
|
if(mesh->IsDerivedFrom(MLR_I_TMesh::DefaultData))
|
|
{
|
|
switch(mesh->GetClassID())
|
|
{
|
|
case MidLevelRenderer::MLR_I_TMeshClassID:
|
|
{
|
|
primitiveArray[primitive] = new MLR_I_PMesh;
|
|
primitiveArray[primitive]->Copy(Cast_Object(MLR_I_TMesh*, mesh));
|
|
}
|
|
break;
|
|
case MidLevelRenderer::MLR_I_L_TMeshClassID:
|
|
{
|
|
primitiveArray[primitive] = new MLR_I_PMesh;
|
|
primitiveArray[primitive]->Copy(Cast_Object(MLR_I_TMesh*, mesh));
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
continue;
|
|
}
|
|
}
|
|
//
|
|
//------------------------------------------------
|
|
// Create the datastorage object if it isn't there
|
|
//------------------------------------------------
|
|
//
|
|
MidLevelRenderer::DataStorage *data_store = primitiveArray[primitive]->dataStore;
|
|
if (!data_store)
|
|
{
|
|
data_store = new MidLevelRenderer::DataStorage;
|
|
primitiveArray[primitive]->dataStore = data_store;
|
|
}
|
|
Check_Pointer(data_store);
|
|
|
|
//
|
|
//---------------------
|
|
// Load up the vertices
|
|
//---------------------
|
|
//
|
|
gos_PushCurrentHeap(MidLevelRenderer::Heap);
|
|
int test_count;
|
|
const Stuff::Point3D *points;
|
|
primitiveArray[primitive]->GetCoordData(&points, &test_count);
|
|
if (points != data_store->coords.GetData())
|
|
{
|
|
data_store->coords.AssignData(points, test_count);
|
|
primitiveArray[primitive]->SetCoordData(data_store->coords.GetData(), test_count);
|
|
}
|
|
positionArray[primitive] = data_store->coords.GetData();
|
|
Check_Pointer(positionArray[primitive]);
|
|
vertexCountArray[primitive] = test_count;
|
|
|
|
//
|
|
//----------------------------------------------------------------------
|
|
// The specific primitive will tell us how to deal with normal and color
|
|
// data
|
|
//----------------------------------------------------------------------
|
|
//
|
|
if (
|
|
primitiveArray[primitive]->IsDerivedFrom(
|
|
MidLevelRenderer::MLR_I_C_PMesh::DefaultData
|
|
)
|
|
)
|
|
{
|
|
MLR_I_C_PMesh* color_primitive =
|
|
Cast_Object(MLR_I_C_PMesh*, primitiveArray[primitive]);
|
|
const MidLevelRenderer::ColorType *colors;
|
|
color_primitive->GetColorData(&colors, &test_count);
|
|
if (colors != data_store->colors.GetData())
|
|
{
|
|
data_store->colors.AssignData(colors, test_count);
|
|
color_primitive->SetColorData(data_store->colors.GetData(), test_count);
|
|
Verify(test_count == vertexCountArray[primitive]);
|
|
}
|
|
colorArray[primitive] = data_store->colors.GetData();
|
|
|
|
|
|
//
|
|
//------------------
|
|
// Are there normals
|
|
//------------------
|
|
//
|
|
if (
|
|
color_primitive->IsDerivedFrom(
|
|
MidLevelRenderer::MLR_I_L_PMesh::DefaultData
|
|
)
|
|
)
|
|
{
|
|
MLR_I_L_PMesh* lit_primitive =
|
|
Cast_Object(MLR_I_L_PMesh*, color_primitive);
|
|
const Stuff::Vector3D *normals;
|
|
lit_primitive->GetNormalData(&normals, &test_count);
|
|
if (normals != data_store->normals.GetData())
|
|
{
|
|
data_store->normals.AssignData(normals, test_count);
|
|
lit_primitive->SetNormalData(data_store->normals.GetData(), test_count);
|
|
}
|
|
normalArray[primitive] = data_store->normals.GetData();
|
|
Verify(test_count == 0 || test_count == vertexCountArray[primitive]);
|
|
}
|
|
else
|
|
normalArray[primitive] = NULL;
|
|
}
|
|
|
|
else if (
|
|
primitiveArray[primitive]->IsDerivedFrom(
|
|
MidLevelRenderer::MLR_I_C_DT_PMesh::DefaultData
|
|
)
|
|
)
|
|
{
|
|
MLR_I_C_DT_PMesh* color_primitive =
|
|
Cast_Object(MLR_I_C_DT_PMesh*, primitiveArray[primitive]);
|
|
const MidLevelRenderer::ColorType *colors;
|
|
color_primitive->GetColorData(&colors, &test_count);
|
|
if (colors != data_store->colors.GetData())
|
|
{
|
|
data_store->colors.AssignData(colors, test_count);
|
|
color_primitive->SetColorData(data_store->colors.GetData(), test_count);
|
|
Verify(test_count == vertexCountArray[primitive]);
|
|
}
|
|
colorArray[primitive] = data_store->colors.GetData();
|
|
|
|
|
|
//
|
|
//------------------
|
|
// Are there normals
|
|
//------------------
|
|
//
|
|
if (
|
|
color_primitive->IsDerivedFrom(
|
|
MidLevelRenderer::MLR_I_L_DT_PMesh::DefaultData
|
|
)
|
|
)
|
|
{
|
|
MLR_I_L_DT_PMesh* lit_primitive =
|
|
Cast_Object(MLR_I_L_DT_PMesh*, color_primitive);
|
|
const Stuff::Vector3D *normals;
|
|
lit_primitive->GetNormalData(&normals, &test_count);
|
|
if (normals != data_store->normals.GetData())
|
|
{
|
|
data_store->normals.AssignData(normals, test_count);
|
|
lit_primitive->SetNormalData(data_store->normals.GetData(), test_count);
|
|
}
|
|
normalArray[primitive] = data_store->normals.GetData();
|
|
Verify(test_count == 0 || test_count == vertexCountArray[primitive]);
|
|
}
|
|
else
|
|
normalArray[primitive] = NULL;
|
|
}
|
|
//
|
|
//---------------------
|
|
// No normals or colors
|
|
//---------------------
|
|
//
|
|
else
|
|
{
|
|
normalArray[primitive] = NULL;
|
|
colorArray[primitive] = NULL;
|
|
}
|
|
|
|
const Stuff::Vector2DOf<Scalar> *uvs;
|
|
primitiveArray[primitive]->GetTexCoordData(&uvs, &test_count);
|
|
if (uvs != data_store->texCoords.GetData())
|
|
{
|
|
data_store->texCoords.AssignData(uvs, test_count);
|
|
primitiveArray[primitive]->SetTexCoordData(data_store->texCoords.GetData(), test_count);
|
|
}
|
|
uvArray[primitive] = data_store->texCoords.GetData();
|
|
Verify(test_count == primitiveArray[primitive]->GetNumPasses() * vertexCountArray[primitive]);
|
|
|
|
//
|
|
//----------------------------
|
|
// Load up the polygon indices
|
|
//----------------------------
|
|
//
|
|
const BYTE *lengths;
|
|
primitiveArray[primitive]->GetSubprimitiveLengths(&lengths, &polygonCountArray[primitive]);
|
|
if (lengths != data_store->lengths.GetData())
|
|
{
|
|
data_store->lengths.AssignData(lengths, test_count);
|
|
primitiveArray[primitive]->SetSubprimitiveLengths(
|
|
data_store->lengths.GetData(),
|
|
polygonCountArray[primitive]
|
|
);
|
|
}
|
|
indexCountArray[primitive] = data_store->lengths.GetData();
|
|
|
|
//
|
|
//--------------------
|
|
// Load up the indices
|
|
//--------------------
|
|
//
|
|
const BYTE *indices;
|
|
primitiveArray[primitive]->GetIndexData(&indices, &test_count);
|
|
if (indices != data_store->index.GetData())
|
|
{
|
|
data_store->index.AssignData(indices, test_count);
|
|
primitiveArray[primitive]->SetIndexData(data_store->index.GetData(), test_count);
|
|
}
|
|
indexArray[primitive] = data_store->index.GetData();
|
|
gos_PopCurrentHeap();
|
|
}
|
|
|
|
Check_Object(this);
|
|
}
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
void
|
|
ElementPolygonMeshProxy::SetPolyMeshArrays(
|
|
MLR_I_L_PMesh *mesh,
|
|
DynamicArrayOf<PolygonProxy*> &polygons,
|
|
int poly_count,
|
|
Process *process
|
|
)
|
|
{
|
|
Check_Object(mesh);
|
|
Check_Object(&polygons);
|
|
Check_Object(process);
|
|
|
|
//
|
|
//---------------------------------------------------------------------
|
|
// Now that we know the polygons we will be adding, we need to create
|
|
// the data structures to fill MLR up with, so first find out the total
|
|
// number of vertex indices
|
|
//---------------------------------------------------------------------
|
|
//
|
|
//unsigned poly_count = polygons.GetLength();
|
|
DynamicArrayOf<DynamicArrayOf<IndexProxy*> > source_indices(poly_count);
|
|
DynamicArrayOf<BYTE> index_counts(poly_count);
|
|
unsigned
|
|
index_count = 0,
|
|
polygon;
|
|
for (polygon=0; polygon<poly_count; ++polygon)
|
|
{
|
|
Check_Object(polygons[polygon]);
|
|
unsigned count =
|
|
polygons[polygon]->UseIndexArray(&source_indices[polygon]);
|
|
Verify(count < 256);
|
|
index_counts[polygon] = static_cast<BYTE>(count);
|
|
Verify(index_counts[polygon] == source_indices[polygon].GetLength());
|
|
index_count += index_counts[polygon];
|
|
}
|
|
|
|
//
|
|
//--------------------------------------------------------------------------
|
|
// Create a vertex array set to the maximum size possible, then loop through
|
|
// the polygons and build the vertex array
|
|
//--------------------------------------------------------------------------
|
|
//
|
|
DynamicArrayOf<VertexProxy*> vertices(Limits::Max_Number_Vertices_Per_Mesh);
|
|
DynamicArrayOf<BYTE> indices(index_count);
|
|
unsigned vertex_count = 0;
|
|
unsigned current_index = 0;
|
|
for (polygon=0; polygon<poly_count; ++polygon)
|
|
{
|
|
Check_Object(&source_indices[polygon]);
|
|
for (unsigned i=0; i<source_indices[polygon].GetLength(); ++i)
|
|
{
|
|
IndexProxy *index = source_indices[polygon][i];
|
|
Check_Object(index);
|
|
VertexProxy *vertex = index->GetVertexProxy();
|
|
Check_Object(vertex);
|
|
|
|
//
|
|
//--------------------------------------------------------------------
|
|
// Compare this vertex proxy to what is already in our pool, and if it
|
|
// matches, just use it, otherwise stuff it in the pool
|
|
//--------------------------------------------------------------------
|
|
//
|
|
unsigned temp =
|
|
VertexProxy::AddUniqueVertex(
|
|
vertices,
|
|
&vertex_count,
|
|
vertex,
|
|
process->duplicateVertexTolerance
|
|
);
|
|
BYTE vertex_index = static_cast<BYTE>(temp);
|
|
if (temp >= Limits::Max_Number_Vertices_Per_Mesh)
|
|
STOP(("You have a mesh with more than %d vertices, exporter error, please contact fwang",Limits::Max_Number_Vertices_Per_Mesh));
|
|
|
|
|
|
//
|
|
//---------------------------------
|
|
// Set the value in the index array
|
|
//---------------------------------
|
|
//
|
|
indices[current_index++] = vertex_index;
|
|
}
|
|
}
|
|
|
|
//
|
|
//------------------------------------------------
|
|
// Create the datastorage object if it isn't there
|
|
//------------------------------------------------
|
|
//
|
|
MidLevelRenderer::DataStorage *data_store = mesh->dataStore;
|
|
if (!data_store)
|
|
{
|
|
data_store = new MidLevelRenderer::DataStorage;
|
|
mesh->dataStore = data_store;
|
|
}
|
|
Check_Pointer(data_store);
|
|
|
|
//
|
|
//---------------------------------------------------------
|
|
// Create the polygon lengths in MLR and set up the indices
|
|
//---------------------------------------------------------
|
|
//
|
|
data_store->lengths.AssignData(index_counts.GetData(), poly_count);
|
|
mesh->SetSubprimitiveLengths(
|
|
data_store->lengths.GetData(),
|
|
poly_count
|
|
);
|
|
Verify(index_count > 0);
|
|
Verify(vertex_count > 0);
|
|
Verify(index_count == current_index);
|
|
|
|
//
|
|
//------------------------------------------------
|
|
// Extract the vertex information from our proxies
|
|
//------------------------------------------------
|
|
//
|
|
DynamicArrayOf<Point3D> positions(vertex_count);
|
|
DynamicArrayOf<Vector3D> normals(vertex_count);
|
|
DynamicArrayOf<Vector2DScalar> uvs(vertex_count);
|
|
|
|
DynamicArrayOf<Vector2DScalar> temp_uvs;
|
|
|
|
DynamicArrayOf<ColorType> colors(vertex_count);
|
|
current_index=0;
|
|
bool
|
|
has_normal = false;
|
|
for (current_index=0; current_index<vertex_count; ++current_index)
|
|
{
|
|
Check_Object(vertices[current_index]);
|
|
vertices[current_index]->GetPosition(&positions[current_index]);
|
|
|
|
//
|
|
//-------------------------------------------
|
|
// If colors are missing, assume bright white
|
|
//-------------------------------------------
|
|
//
|
|
RGBAColor temp_color;
|
|
if (!vertices[current_index]->GetColor(&temp_color))
|
|
{
|
|
#if COLOR_AS_DWORD>0
|
|
colors[current_index] = 0xffffffff;
|
|
#else
|
|
colors[current_index].red = 1.0f;
|
|
colors[current_index].green = 1.0f;
|
|
colors[current_index].blue = 1.0f;
|
|
colors[current_index].alpha = 1.0f;
|
|
#endif
|
|
}
|
|
else
|
|
{
|
|
#if COLOR_AS_DWORD>0
|
|
colors[current_index] = GOSCopyColor(&temp_color);
|
|
#else
|
|
colors[current_index] = temp_color;
|
|
#endif
|
|
}
|
|
|
|
//
|
|
//-----------------------
|
|
// Missing UVs map to 0,0
|
|
//-----------------------
|
|
//
|
|
if (!vertices[current_index]->GetUVs(&temp_uvs))
|
|
{
|
|
uvs[current_index].x = 0.0f;
|
|
uvs[current_index].y = 0.0f;
|
|
}
|
|
else
|
|
{
|
|
Verify(temp_uvs.GetLength() == 1);
|
|
if (temp_uvs[0].x<-0.015625f || temp_uvs[0].x>1.015625f ||
|
|
temp_uvs[0].y<-0.015625f || temp_uvs[0].y>1.015625f)
|
|
{
|
|
char buffer[200];
|
|
MString name;
|
|
GetName(&name);
|
|
if (process->errorfn && !(!name)) {
|
|
sprintf(buffer, "%s has bad UV (%f %f) at vertex %d!", (char*)name, temp_uvs[0].x,temp_uvs[0].y,current_index);
|
|
LPERROR_CALLBACKFN fcn = (LPERROR_CALLBACKFN)process->errorfn;
|
|
fcn(buffer,process->suppress);
|
|
}
|
|
}
|
|
uvs[current_index] = temp_uvs[0];
|
|
}
|
|
|
|
//
|
|
//------------------------------------------------
|
|
// We should have either no normals or all normals
|
|
//------------------------------------------------
|
|
//
|
|
bool temp =
|
|
vertices[current_index]->GetNormal(
|
|
Cast_Pointer(Normal3D*, &normals[current_index])
|
|
);
|
|
if (!current_index)
|
|
has_normal = temp;
|
|
else
|
|
Verify(temp == has_normal);
|
|
}
|
|
|
|
//
|
|
//------------------------
|
|
// Set the data within MLR
|
|
//------------------------
|
|
//
|
|
data_store->coords.AssignData(positions.GetData(), vertex_count);
|
|
mesh->SetCoordData(data_store->coords.GetData(), vertex_count);
|
|
|
|
data_store->index.AssignData(indices.GetData(), index_count);
|
|
mesh->SetIndexData(data_store->index.GetData(), index_count);
|
|
|
|
data_store->colors.AssignData(colors.GetData(), vertex_count);
|
|
mesh->SetColorData(data_store->colors.GetData(), vertex_count);
|
|
|
|
data_store->texCoords.AssignData(uvs.GetData(), vertex_count);
|
|
mesh->SetTexCoordData(data_store->texCoords.GetData(), vertex_count);
|
|
|
|
if (has_normal)
|
|
{
|
|
data_store->normals.AssignData(normals.GetData(), vertex_count);
|
|
mesh->SetNormalData(data_store->normals.GetData(), vertex_count);
|
|
}
|
|
|
|
//
|
|
//-----------------------------
|
|
// Now clean up the index array
|
|
//-----------------------------
|
|
//
|
|
for (polygon=0; polygon<poly_count; ++polygon)
|
|
{
|
|
Check_Object(polygons[polygon]);
|
|
Check_Object(&source_indices[polygon]);
|
|
polygons[polygon]->DetachArrayReferences(&source_indices[polygon]);
|
|
}
|
|
}
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
void
|
|
ElementPolygonMeshProxy::SetPolyMeshArrays(
|
|
MLR_I_L_DT_PMesh *mesh,
|
|
DynamicArrayOf<PolygonProxy*> &polygons,
|
|
int poly_count,
|
|
Process *process,
|
|
bool isInverted
|
|
)
|
|
{
|
|
Check_Object(mesh);
|
|
Check_Object(&polygons);
|
|
Check_Object(process);
|
|
|
|
//
|
|
//---------------------------------------------------------------------
|
|
// Now that we know the polygons we will be adding, we need to create
|
|
// the data structures to fill MLR up with, so first find out the total
|
|
// number of vertex indices
|
|
//---------------------------------------------------------------------
|
|
//
|
|
//unsigned poly_count = polygons.GetLength();
|
|
DynamicArrayOf<DynamicArrayOf<IndexProxy*> > source_indices(poly_count);
|
|
DynamicArrayOf<BYTE> index_counts(poly_count);
|
|
unsigned
|
|
index_count = 0,
|
|
polygon;
|
|
for (polygon=0; polygon<poly_count; ++polygon)
|
|
{
|
|
Check_Object(polygons[polygon]);
|
|
unsigned count =
|
|
polygons[polygon]->UseIndexArray(&source_indices[polygon]);
|
|
Verify(count < 256);
|
|
index_counts[polygon] = static_cast<BYTE>(count);
|
|
Verify(index_counts[polygon] == source_indices[polygon].GetLength());
|
|
index_count += index_counts[polygon];
|
|
}
|
|
|
|
//
|
|
//--------------------------------------------------------------------------
|
|
// Create a vertex array set to the maximum size possible, then loop through
|
|
// the polygons and build the vertex array
|
|
//--------------------------------------------------------------------------
|
|
//
|
|
DynamicArrayOf<VertexProxy*> vertices(Limits::Max_Number_Vertices_Per_Mesh);
|
|
DynamicArrayOf<BYTE> indices(index_count);
|
|
unsigned vertex_count = 0;
|
|
unsigned current_index = 0;
|
|
for (polygon=0; polygon<poly_count; ++polygon)
|
|
{
|
|
Check_Object(&source_indices[polygon]);
|
|
for (unsigned i=0; i<source_indices[polygon].GetLength(); ++i)
|
|
{
|
|
IndexProxy *index = source_indices[polygon][i];
|
|
Check_Object(index);
|
|
VertexProxy *vertex = index->GetVertexProxy();
|
|
Check_Object(vertex);
|
|
|
|
//
|
|
//--------------------------------------------------------------------
|
|
// Compare this vertex proxy to what is already in our pool, and if it
|
|
// matches, just use it, otherwise stuff it in the pool
|
|
//--------------------------------------------------------------------
|
|
//
|
|
unsigned temp =
|
|
VertexProxy::AddUniqueVertex(
|
|
vertices,
|
|
&vertex_count,
|
|
vertex,
|
|
process->duplicateVertexTolerance
|
|
);
|
|
BYTE vertex_index = static_cast<BYTE>(temp);
|
|
if (temp >= Limits::Max_Number_Vertices_Per_Mesh)
|
|
STOP(("You have a mesh with more than %d vertices, exporter error, please contact fwang",Limits::Max_Number_Vertices_Per_Mesh));
|
|
|
|
|
|
//
|
|
//---------------------------------
|
|
// Set the value in the index array
|
|
//---------------------------------
|
|
//
|
|
indices[current_index++] = vertex_index;
|
|
}
|
|
}
|
|
|
|
//
|
|
//------------------------------------------------
|
|
// Create the datastorage object if it isn't there
|
|
//------------------------------------------------
|
|
//
|
|
MidLevelRenderer::DataStorage *data_store = mesh->dataStore;
|
|
if (!data_store)
|
|
{
|
|
data_store = new MidLevelRenderer::DataStorage;
|
|
mesh->dataStore = data_store;
|
|
}
|
|
Check_Pointer(data_store);
|
|
|
|
//
|
|
//---------------------------------------------------------
|
|
// Create the polygon lengths in MLR and set up the indices
|
|
//---------------------------------------------------------
|
|
//
|
|
data_store->lengths.AssignData(index_counts.GetData(), poly_count);
|
|
mesh->SetSubprimitiveLengths(
|
|
data_store->lengths.GetData(),
|
|
poly_count
|
|
);
|
|
Verify(index_count > 0);
|
|
Verify(vertex_count > 0);
|
|
Verify(index_count == current_index);
|
|
|
|
//
|
|
//------------------------------------------------
|
|
// Extract the vertex information from our proxies
|
|
//------------------------------------------------
|
|
//
|
|
DynamicArrayOf<Point3D> positions(vertex_count);
|
|
DynamicArrayOf<Vector3D> normals(vertex_count);
|
|
DynamicArrayOf<Vector2DScalar> uvs(2*vertex_count);
|
|
|
|
DynamicArrayOf<Vector2DScalar> temp_uvs;
|
|
|
|
DynamicArrayOf<ColorType> colors(vertex_count);
|
|
current_index=0;
|
|
bool
|
|
has_normal = false;
|
|
for (current_index=0; current_index<vertex_count; ++current_index)
|
|
{
|
|
Check_Object(vertices[current_index]);
|
|
vertices[current_index]->GetPosition(&positions[current_index]);
|
|
|
|
//
|
|
//-------------------------------------------
|
|
// If colors are missing, assume bright white
|
|
//-------------------------------------------
|
|
//
|
|
RGBAColor temp_color;
|
|
if (!vertices[current_index]->GetColor(&temp_color))
|
|
{
|
|
#if COLOR_AS_DWORD>0
|
|
colors[current_index] = 0xffffffff;
|
|
#else
|
|
colors[current_index].red = 1.0f;
|
|
colors[current_index].green = 1.0f;
|
|
colors[current_index].blue = 1.0f;
|
|
colors[current_index].alpha = 1.0f;
|
|
#endif
|
|
}
|
|
else
|
|
{
|
|
#if COLOR_AS_DWORD>0
|
|
colors[current_index] = GOSCopyColor(&temp_color);
|
|
#else
|
|
colors[current_index] = temp_color;
|
|
#endif
|
|
}
|
|
|
|
//
|
|
//-----------------------
|
|
// Missing UVs map to 0,0
|
|
//-----------------------
|
|
//
|
|
if (!vertices[current_index]->GetUVs(&temp_uvs))
|
|
{
|
|
uvs[current_index].x = 0.0f;
|
|
uvs[current_index].y = 0.0f;
|
|
}
|
|
else
|
|
{
|
|
Verify(temp_uvs.GetLength() <= 2);
|
|
|
|
if(isInverted==false)
|
|
{
|
|
uvs[current_index] = temp_uvs[0];
|
|
uvs[current_index+vertex_count] = temp_uvs[1];
|
|
}
|
|
else
|
|
{
|
|
uvs[current_index] = temp_uvs[1];
|
|
uvs[current_index+vertex_count] = temp_uvs[0];
|
|
}
|
|
}
|
|
|
|
//
|
|
//------------------------------------------------
|
|
// We should have either no normals or all normals
|
|
//------------------------------------------------
|
|
//
|
|
bool temp =
|
|
vertices[current_index]->GetNormal(
|
|
Cast_Pointer(Normal3D*, &normals[current_index])
|
|
);
|
|
if (!current_index)
|
|
has_normal = temp;
|
|
else
|
|
Verify(temp == has_normal);
|
|
}
|
|
|
|
//
|
|
//------------------------
|
|
// Set the data within MLR
|
|
//------------------------
|
|
//
|
|
data_store->coords.AssignData(positions.GetData(), vertex_count);
|
|
mesh->SetCoordData(data_store->coords.GetData(), vertex_count);
|
|
|
|
data_store->index.AssignData(indices.GetData(), index_count);
|
|
mesh->SetIndexData(data_store->index.GetData(), index_count);
|
|
|
|
data_store->colors.AssignData(colors.GetData(), vertex_count);
|
|
mesh->SetColorData(data_store->colors.GetData(), vertex_count);
|
|
|
|
data_store->texCoords.AssignData(uvs.GetData(), 2*vertex_count);
|
|
mesh->SetTexCoordData(data_store->texCoords.GetData(), 2*vertex_count);
|
|
|
|
if (has_normal)
|
|
{
|
|
data_store->normals.AssignData(normals.GetData(), vertex_count);
|
|
mesh->SetNormalData(data_store->normals.GetData(), vertex_count);
|
|
}
|
|
|
|
//
|
|
//-----------------------------
|
|
// Now clean up the index array
|
|
//-----------------------------
|
|
//
|
|
for (polygon=0; polygon<poly_count; ++polygon)
|
|
{
|
|
Check_Object(polygons[polygon]);
|
|
Check_Object(&source_indices[polygon]);
|
|
polygons[polygon]->DetachArrayReferences(&source_indices[polygon]);
|
|
}
|
|
}
|
|
|
|
MLRPrimitiveBase*
|
|
ElementPolygonMeshProxy::CreateNewMesh(MultiState* multiState)
|
|
{
|
|
MLRPrimitiveBase* mesh;
|
|
if(multiState->GetLength() < 2)
|
|
{
|
|
mesh = new MLR_I_L_PMesh;
|
|
}
|
|
else
|
|
{
|
|
mesh = new MLR_I_L_DT_PMesh;
|
|
}
|
|
|
|
Register_Object(mesh);
|
|
Check_Object(multiState);
|
|
|
|
ElementSceneProxy *scene = GetSceneProxy();
|
|
Check_Object(scene);
|
|
StateLibrary *state_library = scene->GetStateLibrary();
|
|
Check_Object(state_library);
|
|
|
|
|
|
if(multiState->GetLength() > 0)
|
|
{
|
|
MLRStateProxy *state =
|
|
Cast_Object(
|
|
MLRStateProxy*,
|
|
state_library->UseMatchingStateProxy((*multiState)[0])
|
|
);
|
|
Check_Object(state);
|
|
MLRState mlr_state;
|
|
mesh->SetReferenceState(state->GetMLRState());
|
|
state->DetachReference();
|
|
}
|
|
|
|
if(multiState->GetLength() > 1)
|
|
{
|
|
MLRStateProxy *state =
|
|
Cast_Object(
|
|
MLRStateProxy*,
|
|
state_library->UseMatchingStateProxy((*multiState)[1])
|
|
);
|
|
Check_Object(state);
|
|
MLRState mlr_state;
|
|
if(multiState->isInverted == false)
|
|
{
|
|
mesh->SetReferenceState(state->GetMLRState(), 1);
|
|
}
|
|
else
|
|
{
|
|
mesh->SetReferenceState(mesh->GetReferenceState(), 1);
|
|
mesh->SetReferenceState(state->GetMLRState(), 0);
|
|
}
|
|
state->DetachReference();
|
|
}
|
|
|
|
return mesh;
|
|
} |