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();
}
Example #2
0
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 );
	}
}
Example #4
0
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);
}
Example #8
0
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 );
			}
		}
	}
}
Example #10
0
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;
}
Example #11
0
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;
}
Example #12
0
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;
}
Example #13
0
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;
}
Example #16
0
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;
}