void SimpleOverlayEffectsDemo::RenderMeshes() { GraphicsDevice().Enable( RenderStateType::DEPTH_TEST ); ShaderManager *pShaderMgr = m_Shader.GetShaderManager(); if(!pShaderMgr) return; ShaderManager& shader_mgr = *pShaderMgr;// pShaderMgr ? *pShaderMgr : FixedFunctionPipelineManager(); // render the scene shader_mgr.SetViewerPosition( GetCurrentCamera().GetPosition() ); // GetShaderManagerHub().PushViewAndProjectionMatrices( GetCurrentCamera() ); shader_mgr.SetTechnique( m_MeshTechnique ); for( auto& mesh : m_Meshes ) { shader_mgr.SetWorldTransform( Matrix44Identity() ); BasicMesh *pMesh = mesh.GetMesh().get(); if( pMesh ) pMesh->Render( shader_mgr ); } // GetShaderManagerHub().PopViewAndProjectionMatrices_NoRestore(); }
Result::Name RegisterAsPlanarMirror( CCopyEntity& entity, BasicMesh& mesh, int subset_index ) { const AABB3& aabb = mesh.GetAABB(subset_index); EntityRenderManager& entity_render_mgr = *(entity.GetStage()->GetEntitySet()->GetRenderManager()); // >>> TODO: support planes that are not axis-aligned or facing along the negative half-space SPlane plane; int plane_axis = 1; if( aabb.vMax.x - aabb.vMin.x < 0.001f ) plane_axis = 0; else if( aabb.vMax.y - aabb.vMin.y < 0.001f ) plane_axis = 1; else if( aabb.vMax.z - aabb.vMin.z < 0.001f ) plane_axis = 2; else plane_axis = 1; plane.normal = Vector3(0,0,0); plane.normal[plane_axis] = 1; plane.dist = aabb.vMax[plane_axis]; Result::Name res = entity_render_mgr.AddPlanarReflector( EntityHandle<>( entity.Self() ), plane ); if( res != Result::SUCCESS ) return Result::UNKNOWN_ERROR; entity.RaiseEntityFlags( BETYPE_PLANAR_REFLECTOR ); // Create shader variable loader for mirror if( !entity.m_pMeshRenderMethod ) { if( entity.pBaseEntity->MeshProperty().m_pMeshRenderMethod ) { entity.m_pMeshRenderMethod = entity.pBaseEntity->MeshProperty().m_pMeshRenderMethod->CreateCopy(); if( !entity.m_pMeshRenderMethod ) return Result::UNKNOWN_ERROR; } else return Result::UNKNOWN_ERROR; } // create a planar reflection entity // shared_ptr<MeshContainerRenderMethod> pMeshRenderMethodCopy // = entity.m_pMeshRenderMethod->CreateCopy(); shared_ptr<MirroredSceneTextureParam> pTexParam; pTexParam.reset( new MirroredSceneTextureParam( EntityHandle<>( entity.Self() ) ) ); pTexParam->m_fReflection = mesh.GetMaterial(subset_index).m_Mat.fReflection; // pMeshRenderMethodCopy->SetShaderParamsLoaderToAllMeshRenderMethods( pTexParam ); // test - we assume that the entity's mesh is composed of polygons that belong to a single plane. entity.m_pMeshRenderMethod->SetShaderParamsLoaderToAllMeshRenderMethods( pTexParam ); // Move the indices of the planar reflection subset(s) // to the render method of the planar reflection entity return Result::SUCCESS; }
void MeshContainerRenderMethod::RenderMeshOrMeshSubsets( BasicMesh &mesh, const vector<int>& subset_indices, // ShaderManager& shader_mgr, SubsetRenderMethod& render_method, const Matrix34& world_transform ) { // Render with a single shader & a single technique // ShaderManager *pShaderMgr = m_vecMeshRenderMethod[lod_index].m_Shader.GetShaderManager(); ShaderManager *pShaderMgr = render_method.m_Shader.GetShaderManager(); if( !pShaderMgr ) return; ShaderManager& shader_mgr = (*pShaderMgr); shader_mgr.SetWorldTransform( world_transform ); /* if( true )//sg_iPrevShaderManagerID != pShaderMgr->GetShaderManagerID() ) { for( size_t i=0; i<vecpShaderParamsWriter.size(); i++ ) vecpShaderParamsWriter[i]->UpdateShaderParams( *pShaderMgr ); }*/ // SubsetRenderMethod& render_method = m_vecMeshRenderMethod[lod_index]; // update shader params for( size_t i=0; i<render_method.m_vecpShaderParamsLoader.size(); i++ ) { render_method.m_vecpShaderParamsLoader[i]->UpdateShaderParams( shader_mgr ); } // render Result::Name res = shader_mgr.SetTechnique( render_method.m_Technique ); if( subset_indices.size() == 0 ) { // Render all the mesh subsets with a single shader & a single technique mesh.Render( shader_mgr ); } else { // render only the specified subsets with a single shader & a single technique for( int i=0; i<(int)subset_indices.size(); i++ ) { mesh.RenderSubset( shader_mgr, subset_indices[i] ); } } // reset shader params if necessary for( size_t i=0; i<render_method.m_vecpShaderParamsLoader.size(); i++ ) { render_method.m_vecpShaderParamsLoader[i]->ResetShaderParams( shader_mgr ); } }
BasicMesh* MeshFactory::LoadMeshObjectFromFile( const std::string& filepath, U32 load_option_flags, MeshType::Name mesh_type ) { BasicMesh* pMesh = InitMeshInstance( mesh_type, load_option_flags ); bool loaded = pMesh->LoadFromFile( filepath, load_option_flags ); if( loaded ) return pMesh; else { SafeDelete( pMesh ); return NULL; } }
void ExtremalQuery3BSP<Real>::CreateSphericalBisectors (BasicMesh& mesh, std::multiset<SphericalArc>& arcs) { // For each vertex, sort the normals into a counterclockwise spherical // polygon when viewed from outside the sphere. SortVertexAdjacents(mesh); int numVertices = mesh.GetNumVertices(); const BasicMesh::Vertex* vertices = mesh.GetVertices(); std::queue<std::pair<int,int> > queue; for (int i = 0; i < numVertices; ++i) { const BasicMesh::Vertex& vertex = vertices[i]; queue.push(std::make_pair(0, vertex.NumTriangles)); while (!queue.empty()) { std::pair<int,int> arc = queue.front(); queue.pop(); int i0 = arc.first, i1 = arc.second; int separation = i1 - i0; if (separation > 1 && separation != vertex.NumTriangles - 1) { if (i1 < vertex.NumTriangles) { SphericalArc arc; arc.NIndex[0] = vertex.T[i0]; arc.NIndex[1] = vertex.T[i1]; arc.Separation = separation; arc.Normal = mFaceNormals[arc.NIndex[0]].Cross( mFaceNormals[arc.NIndex[1]]); arc.PosVertex = i; arc.NegVertex = i; arcs.insert(arc); } int iMid = (i0 + i1 + 1)/2; if (iMid != i1) { queue.push(std::make_pair(i0, iMid)); queue.push(std::make_pair(iMid, i1)); } } } } }
void ExtremalQuery3BSP<Real>::SortVertexAdjacents (BasicMesh& mesh) { // The typecast is to allow modifying the vertices. As long as the // sorting algorithm is correct, this is a safe thing to do. int numVertices = mesh.GetNumVertices(); BasicMesh::Vertex* vertices = (BasicMesh::Vertex*)mesh.GetVertices(); const BasicMesh::Triangle* triangles = mesh.GetTriangles(); for (int i = 0; i < numVertices; ++i) { // This copy circumvents the constness of the mesh vertices, which // allows the sorting of the mesh triangles shared by a mesh vertex. BasicMesh::Vertex& vertex = vertices[i]; // This is a consequence of the mesh being a polyhedron. assertion(vertex.NumVertices == vertex.NumTriangles, "Unexpected condition\n"); // Once we have the first vertex to sort and an initial triangle // sharing it, we can walk around the vertex following triangle // adjacency links. It is safe to overwrite the vertex data. int t = vertex.T[0]; const BasicMesh::Triangle* tri = &triangles[t]; for (int adj = 0; adj < vertex.NumVertices; ++adj) { int prev, curr; for (prev = 2, curr = 0; curr < 3; prev = curr++) { if (tri->V[curr] == i) { vertex.V[adj] = tri->V[prev]; vertex.E[adj] = tri->E[prev]; vertex.T[adj] = t; // The next triangle to visit. t = tri->T[prev]; tri = &triangles[t]; break; } } assertion(curr < 3, "Unexpected condition\n"); } } }
void ExtremalQuery3BSP<Real>::CreateSphericalArcs (BasicMesh& mesh, std::multiset<SphericalArc>& arcs) { int numEdges = mesh.GetNumEdges(); const BasicMesh::Edge* edges = mesh.GetEdges(); const BasicMesh::Triangle* triangles = mesh.GetTriangles(); const int prev[3] = { 2, 0, 1 }; const int next[3] = { 1, 2, 0 }; for (int i = 0; i < numEdges; ++i) { const BasicMesh::Edge& edge = edges[i]; SphericalArc arc; arc.NIndex[0] = edge.T[0]; arc.NIndex[1] = edge.T[1]; arc.Separation = 1; arc.Normal = mFaceNormals[arc.NIndex[0]].Cross( mFaceNormals[arc.NIndex[1]]); const BasicMesh::Triangle& adj = triangles[edge.T[0]]; int j; for (j = 0; j < 3; ++j) { if (adj.V[j] != edge.V[0] && adj.V[j] != edge.V[1]) { arc.PosVertex = adj.V[prev[j]]; arc.NegVertex = adj.V[next[j]]; break; } } assertion(j < 3, "Unexpected condition\n"); arcs.insert(arc); } CreateSphericalBisectors(mesh, arcs); }
void _findBoundaries(Vector& low, Vector& high, const BasicMesh& from) { assert(sizeof(Vector) == 3*sizeof(*(from.getVertices()))); low.x = low.y = low.z = std::numeric_limits<float>::max(); high.x = high.y = high.z = -std::numeric_limits<float>::max(); // numeric::min is actually minimal *positive* value const Vector* vertex = reinterpret_cast<const Vector*>(from.getVertices()); for(int i = 0; i < from.getVerticesCount(); ++i) { if(low.x > vertex->x) low.x = vertex->x; if(low.y > vertex->y) low.y = vertex->y; if(low.z > vertex->z) low.z = vertex->z; if(high.x < vertex->x) high.x = vertex->x; if(high.y < vertex->y) high.y = vertex->y; if(high.z < vertex->z) high.z = vertex->z; ++vertex; } }
void SharedMeshContainer::ValidateShaderTechniqueTable() { BasicMesh *pMeshObject = m_MeshObjectHandle.GetMesh().get(); if( !pMeshObject ) return; if( m_ShaderTechnique.size_y() == 0 ) { m_ShaderTechnique.resize(1,1); m_ShaderTechnique(0,0).SetTechniqueName( "NoShader" ); } else if( m_ShaderTechnique.size_y() == 1 && 2 <= pMeshObject->GetNumMaterials() ) { // only one technique and 2 or more materials // - assumes the user wants to render all the materials with the same shader technique m_PropertyFlags |= PF_USE_SINGLE_TECHNIQUE_FOR_ALL_MATERIALS; } else if( m_ShaderTechnique.size_y() < pMeshObject->GetNumMaterials() ) { int num_orig_rows = m_ShaderTechnique.size_y(); // (the number of techniques) < (the number of materials) // - copy the last technique and make sure there are as many techniques as materials // increase the columns to cover all the materials m_ShaderTechnique.increase_y( pMeshObject->GetNumMaterials() - m_ShaderTechnique.size_y() ); // overwrite increased rows with the last technique for each LOD int lod, num_lods = m_ShaderTechnique.size_x(); // columns: for LODs int row, num_rows = m_ShaderTechnique.size_y(); // rows: for materials for( lod=0; lod<num_lods; lod++ ) { for( row=num_orig_rows; row<num_rows; row++ ) { m_ShaderTechnique( lod, row ) = m_ShaderTechnique( lod, num_orig_rows - 1 ); } } } }
void MeshManager::createMesh(const std::string& name, const FloatDataContainer& vertices, const FloatDataContainer& uvs, const FloatDataContainer& normals, const ShortDataContainer& indices, CollisionShape type ) { assert(m_meshes.find(name) == m_meshes.end()); BasicMesh* result = new BasicMesh(); result->m_name = name; _copyData(vertices, result->m_vertices); result->m_verticesCount = vertices.size() / 3; _copyData(indices, result->m_indices); _copyData(uvs, result->m_uvs); _copyData(normals, result->m_normals); _copyData(indices, result->m_indices); result->m_indicesCount = indices.size() / 3; result->setCollisionType(type); m_meshes[name] = result; }
bool RegisterAsMirrorIfReflective( CCopyEntity& entity, BasicMesh& mesh, int subset_index, GenericShaderDesc& shader_desc ) { if( mesh.GetMaterial(subset_index).m_Mat.fReflection < 0.001f ) return false; const MeshMaterial& mat = mesh.GetMaterial(subset_index); const AABB3& aabb = mesh.GetAABB(subset_index); bool subset_triangles_on_plane = false; if( aabb.vMax.x - aabb.vMin.x < 0.001f || aabb.vMax.y - aabb.vMin.y < 0.001f || aabb.vMax.z - aabb.vMin.z < 0.001f ) { // The triangles of the i-th subset is on an axis-aligned plane. subset_triangles_on_plane = true; } // else if( IsSubsetTrianglesOnSinglePlane(pMesh,i) ) // { // subset_triangles_on_plane = true; // } if( subset_triangles_on_plane ) { RegisterAsPlanarMirror( entity, mesh, subset_index ); shader_desc.PlanarReflection = PlanarReflectionOption::FLAT; return true; } else { // TODO: Register as an envmap target? // entity.RaiseEntityFlags( BETYPE_ENVMAPTARGET ); // shader_desc.EnvMap = EnvMapOption::ENABLED; return false; } return false; }
bool BasicMesh::intersects(BasicMesh& other) { if (abs(getPosition().x - other.getPosition().x) < getScale().x + other.getScale().x) { if (abs(getPosition().y - other.getPosition().y) < getScale().y + other.getScale().y) { if (abs(getPosition().z - other.getPosition().z) < getScale().z + other.getScale().z) { return true; } } } return false; }
void CBE_Skybox::Draw(CCopyEntity* pCopyEnt) { BasicMesh* pMeshObject = m_MeshProperty.m_MeshObjectHandle.GetMesh().get(); if( !pMeshObject ) { ONCE( LOG_PRINT_WARNING( " An invlid mesh object: base entity '%s'", m_strName.c_str() ) ); return; } // set the world transform Matrix44 world( Matrix44Scaling( 10.0f, 10.0f, 10.0f ) ); Vector3 vPos; Camera* pCamera = m_pStage->GetCurrentCamera(); if( pCamera ) vPos = pCamera->GetPosition(); else vPos = Vector3(0,0,0); world(0,3) = vPos.x; world(1,3) = vPos.y; world(2,3) = vPos.z; world(3,3) = 1; FixedFunctionPipelineManager().SetWorldTransform( world ); pMeshObject->SetVertexDeclaration(); int num_materials = pMeshObject->GetNumMaterials(); bool shift_camera_height = true; // ShaderParameter<float> cam_height_param( "g_CameraHeight" ); // Disable depth-test and writing to depth buffer. // These 2 settings and restored after rendering skybox because they are changed only when necessary. // This is not required if you are using HLSL effect of Direct3D, and the technique to render // the skybox defines the same render states. // If you are using OpenGL, you have to do this whether you are using GLSL or not? GraphicsDevice().Disable( RenderStateType::DEPTH_TEST ); GraphicsDevice().Disable( RenderStateType::WRITING_INTO_DEPTH_BUFFER ); GraphicsDevice().Disable( RenderStateType::LIGHTING ); // save the original texture and temporarily overwrite it with the sky texture TextureHandle orig_tex; if( 0 < num_materials ) { if( pMeshObject->Material(0).Texture.empty() ) pMeshObject->Material(0).Texture.resize( 1 ); orig_tex = pMeshObject->Material(0).Texture[0]; pMeshObject->Material(0).Texture[0] = m_SkyboxTexture; } ShaderManager *pShaderManager = m_MeshProperty.m_ShaderHandle.GetShaderManager(); if( pShaderManager ) // && pShaderManager->IsValid() ) // check if pEffect is present? { if( shift_camera_height ) { Camera *pCam = m_pStage->GetCurrentCamera(); float fCamHeight; if( pCam ) fCamHeight = pCam->GetPosition().y; else fCamHeight = 5.0f; pShaderManager->GetEffect()->SetFloat( "g_CameraHeight", fCamHeight ); // pShaderManager->SetParam( "g_CameraHeight", fCamHeight ); // pEffect->SetFloat( "g_TexVShiftFactor", 0.000005f ); // pShaderManager->SetParam( "g_TexVShiftFactor", 0.000005f ); // cam_height_param.Parameter() = fCamHeight; // pShaderManager->SetParam( cam_height_param ); } // render the skybox mesh with an HLSL shader pShaderManager->SetWorldTransform( world ); Result::Name res = pShaderManager->SetTechnique( m_MeshProperty.m_ShaderTechnique(0,0) ); // Meshes are divided into subsets by materials. Render each subset in a loop pMeshObject->Render( *pShaderManager ); } else { // RenderAsSkybox( m_MeshProperty.m_MeshObjectHandle, vPos ); pMeshObject->Render(); } if( 0 < num_materials && 0 < pMeshObject->Material(0).Texture.size() ) { // restore the original texture pMeshObject->Material(0).Texture[0] = orig_tex; } GraphicsDevice().Enable( RenderStateType::DEPTH_TEST ); GraphicsDevice().Enable( RenderStateType::WRITING_INTO_DEPTH_BUFFER ); }
// - Set the world transform 'world_transform' to shader // - Update shader params // - Set technique void MeshContainerRenderMethod::RenderMesh( BasicMesh &mesh, const Matrix34& world_transform ) { if( !m_RenderMethodsAndSubsetIndices.empty() ) { if( m_RenderMethodsAndSubsetIndices.size() == 1 && m_RenderMethodsAndSubsetIndices[0].second.empty() ) { // render all the subsets at once RenderMeshOrMeshSubsets( mesh, m_RenderMethodsAndSubsetIndices[0].second, m_RenderMethodsAndSubsetIndices[0].first, world_transform ); } else { for( int i=0; i<(int)m_RenderMethodsAndSubsetIndices.size(); i++ ) { SubsetRenderMethod& render_method = m_RenderMethodsAndSubsetIndices[i].first; const vector<int>& subset_indices = m_RenderMethodsAndSubsetIndices[i].second; for( int j=0; j<(int)subset_indices.size(); j++ ) { RenderMeshOrMeshSubsets( mesh, subset_indices, render_method, world_transform ); } } } } else if( 0 < m_vecSubsetNameToRenderMethod.size() ) { // render subsets one by one // set different shaders / techniques for each subset const int num_subsets = mesh.GetNumMaterials(); std::vector<int> *pvecIndicesOfSubsetsToRender = NULL; if( m_vecIndicesOfSubsetsToRender.size() == 0 ) { // render all the subsets // - create the full indices list // - For the same mesh, this is done only once. for( int j=(int)m_vecFullIndicesOfSubsets.size(); j<num_subsets; j++ ) m_vecFullIndicesOfSubsets.push_back( j ); pvecIndicesOfSubsetsToRender = &m_vecFullIndicesOfSubsets; } else { pvecIndicesOfSubsetsToRender = &m_vecIndicesOfSubsetsToRender; } int lod_index = 0; // for( i=0; i<num_subsets; i++ ) for( size_t i=0; i<pvecIndicesOfSubsetsToRender->size(); i++ ) { int index = (*pvecIndicesOfSubsetsToRender)[i]; map< string, SubsetRenderMethod >::iterator itr = m_vecSubsetNameToRenderMethod[lod_index].find( mesh.GetMaterial(index).Name ); if( itr == m_vecSubsetNameToRenderMethod[lod_index].end() ) continue; SubsetRenderMethod& subset_render_method = (*itr).second; ShaderManager *pShaderMgr = subset_render_method.m_Shader.GetShaderManager(); if( !pShaderMgr ) continue; pShaderMgr->SetWorldTransform( world_transform ); pShaderMgr->SetTechnique( subset_render_method.m_Technique ); for( size_t j=0; j<subset_render_method.m_vecpShaderParamsLoader.size(); j++ ) { subset_render_method.m_vecpShaderParamsLoader[j]->UpdateShaderParams( *pShaderMgr ); } mesh.RenderSubset( *pShaderMgr, index ); for( size_t j=0; j<subset_render_method.m_vecpShaderParamsLoader.size(); j++ ) { subset_render_method.m_vecpShaderParamsLoader[j]->ResetShaderParams( *pShaderMgr ); } } } }
BasicMesh MeshTransferer::transfer(const vector<PhGUtils::Matrix3x3d> &S1grad) { if( !(S0set && T0set) ) { throw "S0 or T0 not set."; } auto &S = S1grad; auto &T = T0grad; int nfaces = S0.faces.nrow; int nverts = S0.verts.nrow; // assemble sparse matrix A int nrowsA = nfaces * 3; int nsv = stationary_vertices.size(); int nrowsC = nsv; int nrows = nrowsA + nrowsC; int ncols = nverts; int ntermsA = nfaces*9; int ntermsC = stationary_vertices.size(); int nterms = ntermsA + ntermsC; SparseMatrix A(nrows, ncols, nterms); // fill in the deformation gradient part for(int i=0, ioffset=0;i<nfaces;++i) { /* * Ai: * 1 2 3 4 5 ... nfaces*3 * 1 2 3 4 5 ... nfaces*3 * 1 2 3 4 5 ... nfaces*3 * Ai = reshape(Ai, 1, nfaces*9) * * Aj = reshape(repmat(S0.faces', 3, 1), 1, nfaces*9) * Av = reshape(cell2mat(T)', 1, nfaces*9) */ int *f = S0.faces.rowptr(i); auto Ti = T[i]; A.append(ioffset, f[0], Ti(0)); A.append(ioffset, f[1], Ti(1)); A.append(ioffset, f[2], Ti(2)); ++ioffset; A.append(ioffset, f[0], Ti(3)); A.append(ioffset, f[1], Ti(4)); A.append(ioffset, f[2], Ti(5)); ++ioffset; A.append(ioffset, f[0], Ti(6)); A.append(ioffset, f[1], Ti(7)); A.append(ioffset, f[2], Ti(8)); ++ioffset; } // fill in the lower part of A, stationary vertices part for(int i=0;i<nsv;++i) { A.append(nrowsA+i, stationary_vertices[i], 1); } ofstream fA("A.txt"); fA<<A; fA.close(); // fill in c matrix DenseMatrix c(nrows, 3); for(int i=0;i<3;++i) { for(int j=0, joffset=0;j<nfaces;++j) { auto &Sj = S[j]; c(joffset, i) = Sj(0, i); ++joffset; c(joffset, i) = Sj(1, i); ++joffset; c(joffset, i) = Sj(2, i); ++joffset; } } for(int i=0;i<3;++i) { for(int j=0, joffset=nrowsA;j<nsv;++j,++joffset) { auto vj = T0.verts.rowptr(stationary_vertices[j]); c(joffset, i) = vj[i]; } } cholmod_sparse *G = A.to_sparse(); cholmod_sparse *Gt = cholmod_transpose(G, 2, global::cm); // compute GtD // just multiply Dsi to corresponding elemenets double *Gtx = (double*)Gt->x; const int* Gtp = (const int*)(Gt->p); for(int i=0;i<nrowsA;++i) { int fidx = i/3; for(int j=Gtp[i];j<Gtp[i+1];++j) { Gtx[j] *= Ds(fidx); } } // compute GtDG cholmod_sparse *GtDG = cholmod_ssmult(Gt, G, 0, 1, 1, global::cm); GtDG->stype = 1; // compute GtD * c cholmod_dense *GtDc = cholmod_allocate_dense(ncols, 3, ncols, CHOLMOD_REAL, global::cm); double alpha[2] = {1, 0}; double beta[2] = {0, 0}; cholmod_sdmult(Gt, 0, alpha, beta, c.to_dense(), GtDc, global::cm); // solve for GtDG \ GtDc cholmod_factor *L = cholmod_analyze(GtDG, global::cm); cholmod_factorize(GtDG, L, global::cm); cholmod_dense *x = cholmod_solve(CHOLMOD_A, L, GtDc, global::cm); // make a copy of T0 BasicMesh Td = T0; // change the vertices with x double *Vx = (double*)x->x; for(int i=0;i<nverts;++i) { Td.verts(i, 0) = Vx[i]; Td.verts(i, 1) = Vx[i+nverts]; Td.verts(i, 2) = Vx[i+nverts*2]; } // release memory cholmod_free_sparse(&G, global::cm); cholmod_free_sparse(&Gt, global::cm); cholmod_free_sparse(&GtDG, global::cm); cholmod_free_dense(&GtDc, global::cm); cholmod_free_factor(&L, global::cm); cholmod_free_dense(&x, global::cm); return Td; }
BasicMesh* MeshManager::loadMesh(const std::string& fileName, const std::string meshName) { shared_ptr<GameFile> file = GameFile::openFile(fileName, "r"); std::string readLine; BasicMesh* result = new BasicMesh(); std::string collisionLine; while(!(file->eof())) { readLine = file->readLine(); if(readLine.size() == 0 || readLine == "\n") { continue; } if(readLine.find(NAME_SECTION) == 0) { loadName(result, readLine); continue; } else if(readLine.find(VERTICES_SECTION) == 0) { loadVertices(result, readLine, file.get()); continue; } else if(readLine.find(UVS_SECTION) == 0) { loadUvs(result, readLine, file.get()); continue; } else if(readLine.find(NORMALS_SECTION) == 0) { loadNormals(result, readLine, file.get()); continue; } else if(readLine.find(INDICES_SECTION) == 0) { loadIndices(result, readLine, file.get()); continue; } else if(readLine.find(COLLISION_SECTION) == 0) { collisionLine = readLine; // it has to be calculated after all the geometry continue; } else { Log("Skipping unknown line in mesh file - %s", readLine.c_str()); } } if(collisionLine.size() != 0) { setCollision(result, collisionLine); } else { // by default create box collision result->setCollisionType(CS_BOX); result->m_collisionShape = createCollisionShape(result); } return result; }