#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;
}