Ejemplo n.º 1
0
/*------------------------------------------------------------------------------*/
void GW_Mesh::FlipOrientation()
{
	for( GW_U32 i=0; i<this->GetNbrFace(); ++i )
	{
		GW_Face* pFace = this->GetFace(i);	GW_ASSERT( pFace!=NULL );
		pFace->SetVertex( *pFace->GetVertex(1), *pFace->GetVertex(0), *pFace->GetVertex(2) );
		pFace->SetFaceNeighbor( pFace->GetFaceNeighbor(1), pFace->GetFaceNeighbor(0), pFace->GetFaceNeighbor(2) );
	}	
}
Ejemplo n.º 2
0
/*------------------------------------------------------------------------------*/
void GW_Mesh::ReOrientMesh( GW_Face& start_face )
{
	/* march on the voronoi diagram */
	T_FaceList FaceToProceed;
	FaceToProceed.push_back( &start_face );
	T_FaceMap FaceDone;
	FaceDone[ start_face.GetID() ] = &start_face;


	while( !FaceToProceed.empty() )
	{
		GW_Face* pFace = FaceToProceed.front();
		GW_ASSERT( pFace!=NULL );
		FaceToProceed.pop_front();

		/* add neighbors */
		for( GW_U32 i=0; i<3; ++i )
		{
			GW_Vertex* pVertDir = pFace->GetVertex(i);	GW_ASSERT( pVertDir!=NULL );
			GW_Face* pNewFace = pFace->GetFaceNeighbor(*pVertDir);
			if( pNewFace!=NULL && FaceDone.find(pNewFace->GetID())==FaceDone.end() )
			{				
				/* find the two other vertices */
				GW_U32 i1 = (i+1)%3;
				GW_U32 i2 = (i+2)%3;
				GW_Vertex* pNewVert[3];
				pNewVert[0] = pFace->GetVertex(i2);						GW_ASSERT( pNewVert[0]!=NULL );
				pNewVert[1] = pFace->GetVertex(i1);						GW_ASSERT( pNewVert[1]!=NULL );
				pNewVert[2] = pNewFace->GetVertex(*pNewVert[0], *pNewVert[1]);	GW_ASSERT( pNewVert[2]!=NULL );
				GW_Face* pNeigh[3];
				pNeigh[0] = pNewFace->GetFaceNeighbor( *pNewVert[0] );
				pNeigh[1] = pNewFace->GetFaceNeighbor( *pNewVert[1] );
				pNeigh[2] = pNewFace->GetFaceNeighbor( *pNewVert[2] );
				/* reorient the face */
				pNewFace->SetVertex( *pNewVert[0], *pNewVert[1], *pNewVert[2] );
				pNewFace->SetFaceNeighbor( pNeigh[0], pNeigh[1], pNeigh[2] );
				FaceToProceed.push_back( pNewFace );
				FaceDone[ pNewFace->GetID() ] = pNewFace;	// so that it won't be added anymore
			}
		}
	}

	/* check for global orientation (just an heuristic) */
	GW_Face* pFace = this->GetFace(0);	GW_ASSERT( pFace!=NULL );
	GW_Vector3D v = pFace->GetVertex(0)->GetPosition() +
					pFace->GetVertex(1)->GetPosition() +
					pFace->GetVertex(2)->GetPosition();
	GW_Vector3D n = pFace->ComputeNormal();
	if( n*v<0 )
		this->FlipOrientation();
}
GW_I32 GW_ASELoader::Load(GW_Mesh& Mesh, const char *name, GW_I32 bits)
{
	FILE *strm = fopen(name, "r");

	if (!strm)
		return GW_Error_Opening_File;

	Release();

	want = bits;

	GetInfo(strm);
	Allocate();
	GetData(strm);

	fclose(strm);

	if (want & kNormals)
		MakeNormals();

	if (want & kTexCoord && numTexVerts)
		Align();
	else if (want & kTexCoord && !numTexVerts)
		return 0;

	numIndex = numFaces * 3;

	/* retrieve information */
	Mesh.SetNbrVertex( this->GetNumVerts() );
	Mesh.SetNbrFace( this->GetNumFaces() );
	GW_U32* pFace = this->GetFaces();
	GW_Real32* pVert = this->GetVerts();
	GW_Real32* pNormal = this->GetVertNormals();
	GW_Real32* pTexture = this->GetTexture();
	GW_Vertex* pCurVert = NULL;
	GW_Vector3D Pos, Normal;

	std::map<int, int> VertCorrespondance;

	/* load vertex */
	for( GW_I32 i=0; i<this->GetNumVerts(); ++i )
	{
		Pos = GW_Vector3D( pVert[3*i], pVert[3*i+1], pVert[3*i+2] );
		/* this is to avoid an annoying problem of vertex duplication */
		for( GW_I32 j=0; j<i; ++j )
		{
			if( GW_ABS(pVert[3*i+0] - pVert[3*j+0])<GW_EPSILON && 
				GW_ABS(pVert[3*i+1] - pVert[3*j+1])<GW_EPSILON && 
				GW_ABS(pVert[3*i+2] - pVert[3*j+2])<GW_EPSILON )
				VertCorrespondance[j] = i;
		}
		if( pNormal!=NULL )
			Normal = GW_Vector3D( pNormal[3*i], pNormal[3*i+1], pNormal[3*i+2] );
		pCurVert = &Mesh.CreateNewVertex();
		pCurVert->SetPosition( Pos );
		pCurVert->SetNormal( Normal );
		if( want & kTexCoord )
		{
			for( GW_U32 s=0; s<1; ++s )
			{
				if( pTexture[2*i+s]<0 )
					pTexture[2*i+s] += 1;
				if( pTexture[2*i+s]>1 )
					pTexture[2*i+s] -= 1;
			}
			pCurVert->SetTexCoords( pTexture[2*i+0], pTexture[2*i+1] );
		} 
		Mesh.SetVertex( i, pCurVert );
	}
	/* load faces */
	GW_Face* pCurFace = NULL;
	for( GW_I32 i=0; i<this->GetNumFaces(); ++i )
	{
		pCurFace = &Mesh.CreateNewFace();
		GW_U32 FaceNumber[3];
		for( GW_U32 s=0; s<3; ++s  )
		{
			FaceNumber[s] = pFace[3*i+s];
			if( VertCorrespondance.find(FaceNumber[s])!=VertCorrespondance.end() )
				FaceNumber[s] = VertCorrespondance[FaceNumber[s]];
		}

		pCurFace->SetVertex( *Mesh.GetVertex(FaceNumber[0]), 
			*Mesh.GetVertex(FaceNumber[1]), 
			*Mesh.GetVertex(FaceNumber[2]) );
		Mesh.SetFace( i, pCurFace );
	}

	return GW_OK;
}
/*------------------------------------------------------------------------------*/
void GW_VoronoiMesh::BuildMesh( GW_GeodesicMesh& Mesh, GW_Bool bFixHole )
{
	/* Create Vornoi vertex and make the inverse map GeodesicVertex->VoronoiVertex */
	this->CreateVoronoiVertex();

#if 1	// simple method

	GW_OutputComment("Recomputing the whole Voronoi diagram.");
	GW_VoronoiMesh::PerformFastMarching( Mesh, BaseVertexList_ );

	/* find the faces */
	GW_OutputComment("Building the faces.");
	T_FaceMap FaceMap;	// to store the faces already built.
	for( GW_U32 i=0; i<Mesh.GetNbrFace(); ++i )
	{
		GW_Face* pFace = Mesh.GetFace(i);	GW_ASSERT( pFace!=NULL );
		GW_GeodesicVertex* pGeo[3];
		GW_GeodesicVertex* pFront[3];
		for( GW_U32 j=0; j<3; ++j )
		{
			pGeo[j] = (GW_GeodesicVertex*) pFace->GetVertex(j); GW_ASSERT( pGeo[j]!=NULL );
			pFront[j] = pGeo[j]->GetFront();
		}
		if( pFront[0]!=pFront[1] && pFront[1]!=pFront[2] && pFront[2]!=pFront[0] )
		{
			GW_U32 nID = GW_Vertex::ComputeUniqueId( *pFront[0], *pFront[1], *pFront[2] );
			if( FaceMap.find(nID)==FaceMap.end() )
			{
				/* create the face */
				GW_Face& Face = this->CreateNewFace();
				FaceMap[nID] = &Face;
				for( GW_U32 j=0; j<3; ++j )		// assign the vertices
				{
					GW_U32 nID = pFront[j]->GetID();
					GW_ASSERT( VoronoiVertexMap_.find(nID)!=VoronoiVertexMap_.end() );
					GW_VoronoiVertex* pVorVert = VoronoiVertexMap_[nID];	GW_ASSERT( pVorVert!=NULL );
					Face.SetVertex( *pVorVert, j );
				}
			}
		}
	}

#else

	GW_OutputComment("Computing voronoi diagrams.");
	/* perform once more a firestart to set up connectivity */		
	Mesh.RegisterNewDeadVertexCallbackFunction( GW_VoronoiMesh::FastMarchingCallbackFunction_MeshBuilding );
	Mesh.ResetGeodesicMesh();
	GW_VoronoiMesh::PerformFastMarching( Mesh, BaseVertexList_ );
	Mesh.RegisterNewDeadVertexCallbackFunction( NULL );

	/* build the faces */
	T_FaceMap FaceMap;	// to store the faces already built.

	GW_OutputComment("Building voronoi mesh faces.");
	for( IT_GeodesicVertexList it = BaseVertexList_.begin(); it!=BaseVertexList_.end(); ++it )
	{
		GW_GeodesicVertex* pVert0 = *it;
		GW_ASSERT( pVert0!=NULL );
		/* retrive the corresponding voronoi vertex */
		GW_VoronoiVertex* pVoronoiVert0 = GW_VoronoiMesh::GetVoronoiFromGeodesic( *pVert0 );
		GW_ASSERT( pVoronoiVert0!=NULL );
		for( IT_VoronoiVertexList itVoronoi1=pVoronoiVert0->BeginNeighborIterator(); itVoronoi1!=pVoronoiVert0->EndNeighborIterator(); ++itVoronoi1 )
		{
			GW_VoronoiVertex* pVoronoiVert1 = *itVoronoi1;
			GW_ASSERT( pVoronoiVert1!=NULL );
			GW_U32 nNumTriangle = 0;
			for( IT_VoronoiVertexList itVoronoi2=pVoronoiVert1->BeginNeighborIterator(); itVoronoi2!=pVoronoiVert1->EndNeighborIterator(); ++itVoronoi2 )
			{
				GW_VoronoiVertex* pVoronoiVert2 = *itVoronoi2;
				GW_ASSERT( pVoronoiVert2!=NULL );
				if( pVoronoiVert2!=pVoronoiVert0 && pVoronoiVert0->IsNeighbor(*pVoronoiVert2) )
				{
					/* yes, we find a triangle ! Test if it wasn't already constructed */
					GW_U32 nUniqueId = GW_Vertex::ComputeUniqueId( *pVoronoiVert0, *pVoronoiVert1, *pVoronoiVert2 );
					if( FaceMap.find(nUniqueId)==FaceMap.end() )
					{
						nNumTriangle++;
						GW_ASSERT( nNumTriangle<=2 );	// assert manifold structure
						/* this is the 1st time we encounter this face. */
						GW_Face* pFace = &Mesh.CreateNewFace();
						/* set up the face */
						pFace->SetVertex( *pVoronoiVert0, *pVoronoiVert1, *pVoronoiVert2 );
						FaceMap[nUniqueId] = pFace;
					}
				}
			}
		}
	}

#endif

	
	/* assign the faces */
	this->SetNbrFace( (GW_U32) FaceMap.size() );
	GW_U32 nNum = 0;
	for( IT_FaceMap it = FaceMap.begin(); it!=FaceMap.end(); ++it )
	{
		this->SetFace( nNum, it->second );
		nNum++;
	}
	/* rebuild connectivity */
	GW_OutputComment("Building connectivity.");
	this->BuildConnectivity();
	/* try to fill the holes */
	if( bFixHole )
	{
		GW_OutputComment("Fixing holes.");
		this->FixHole();
		/* re-rebuild connectivity */
		this->BuildConnectivity();
	}

}