#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(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; mFind(m); Check_Object(mesh); const Point3D *verts; int count; mesh->GetCoordData(&verts, &count); for (int v=0; v= 0.0f); } } #endif } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // unsigned ElementPolygonMeshProxy::UsePolygonArray(DynamicArrayOf *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; primitiveSetLength(poly_count); // //------------------ // Fill in the array //------------------ // poly_count = 0; for (primitive=0; primitive &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 existing_polygons; unsigned existing_polys = UsePolygonArray(&existing_polygons); unsigned source_polys = source_polygons.GetLength(); unsigned total_polys = existing_polys + source_polys; DynamicArrayOf new_polys(total_polys); unsigned i; for (i=0; i > indices(total_polys); for (i=0; iUseIndexArray(&indices[i]); } // //------------------------------------------------- // Now do the state analysis of the new polygon set //------------------------------------------------- // DynamicArrayOf match; DynamicArrayOf count; DynamicArrayOf 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; primitiveGetLength() >= 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 polygons(count[primitive]); DynamicArrayOf 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; iGetVertexProxy(); 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; jGetVertexProxy(); 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; iDetachArrayReferences(&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; iSetReferenceState(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; iSetReferenceState(our_proxy->GetMLRState()); primitiveArray[i]->SetReferenceState(our_proxy1->GetMLRState(), 1); } } } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // unsigned ElementPolygonMeshProxy::UseVertexArray(DynamicArrayOf *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; primitiveSetLength(vertex_count); // //------------------ // Fill in the array //------------------ // vertex_count = 0; for (primitive=0; primitive(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(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; primitiveFind(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 *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 &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 > source_indices(poly_count); DynamicArrayOf index_counts(poly_count); unsigned index_count = 0, polygon; for (polygon=0; polygonUseIndexArray(&source_indices[polygon]); Verify(count < 256); index_counts[polygon] = static_cast(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 vertices(Limits::Max_Number_Vertices_Per_Mesh); DynamicArrayOf indices(index_count); unsigned vertex_count = 0; unsigned current_index = 0; for (polygon=0; polygonGetVertexProxy(); 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(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 positions(vertex_count); DynamicArrayOf normals(vertex_count); DynamicArrayOf uvs(vertex_count); DynamicArrayOf temp_uvs; DynamicArrayOf colors(vertex_count); current_index=0; bool has_normal = false; for (current_index=0; current_indexGetPosition(&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; polygonDetachArrayReferences(&source_indices[polygon]); } } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // void ElementPolygonMeshProxy::SetPolyMeshArrays( MLR_I_L_DT_PMesh *mesh, DynamicArrayOf &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 > source_indices(poly_count); DynamicArrayOf index_counts(poly_count); unsigned index_count = 0, polygon; for (polygon=0; polygonUseIndexArray(&source_indices[polygon]); Verify(count < 256); index_counts[polygon] = static_cast(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 vertices(Limits::Max_Number_Vertices_Per_Mesh); DynamicArrayOf indices(index_count); unsigned vertex_count = 0; unsigned current_index = 0; for (polygon=0; polygonGetVertexProxy(); 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(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 positions(vertex_count); DynamicArrayOf normals(vertex_count); DynamicArrayOf uvs(2*vertex_count); DynamicArrayOf temp_uvs; DynamicArrayOf colors(vertex_count); current_index=0; bool has_normal = false; for (current_index=0; current_indexGetPosition(&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; polygonDetachArrayReferences(&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; }