/*------------------------------------------------------------------------------*/ 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) ); } }
/*------------------------------------------------------------------------------*/ 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_Vertex* GW_Mesh::InsertVertexInEdge( GW_Vertex& Vert1, GW_Vertex& Vert2, GW_Float x, GW_Bool& bIsNewVertCreated ) { if( x<GW_EPSILON ) { bIsNewVertCreated = GW_False; return &Vert2; } if( x>1-GW_EPSILON ) { bIsNewVertCreated = GW_False; return &Vert1; } bIsNewVertCreated = GW_True; /* create the new vertex */ GW_Vertex* pNewVert = &this->CreateNewVertex(); this->SetNbrVertex( this->GetNbrVertex()+1 ); this->SetVertex( this->GetNbrVertex()-1, pNewVert ); /* set position */ pNewVert->SetPosition( Vert1.GetPosition()*x + Vert2.GetPosition()*(1-x) ); /* retrieve the neigbor faces face */ GW_Face* pFace1 = NULL; GW_Face* pFace2 = NULL; Vert1.GetFaces( Vert2, pFace1, pFace2 ); GW_ASSERT( pFace1!=NULL || pFace2!=NULL ); /* assign the face of new vertex */ if( pFace1!=NULL ) pNewVert->SetFace( *pFace1 ); else if( pFace2!=NULL ) pNewVert->SetFace( *pFace2 ); GW_I32 nVert1Num1, nVert1Num2, nVert1Num3, nVert2Num1, nVert2Num2, nVert2Num3; GW_Face* pNewFace1 = NULL; GW_Face* pNewFace2 = NULL; if( pFace1!=NULL ) { nVert1Num1 = pFace1->GetEdgeNumber( Vert1 ); GW_ASSERT( nVert1Num1>=0 ); nVert1Num2 = pFace1->GetEdgeNumber( Vert2 ); GW_ASSERT( nVert1Num2>=0 ); nVert1Num3 = 3-nVert1Num2-nVert1Num1; pNewFace1 = &this->CreateNewFace(); this->SetNbrFace( this->GetNbrFace()+1 ); this->SetFace( this->GetNbrFace()-1, pNewFace1 ); pNewFace1->SetVertex( *pFace1->GetVertex(nVert1Num3), nVert1Num3 ); pNewFace1->SetVertex( Vert2, nVert1Num2 ); pNewFace1->SetVertex( *pNewVert, nVert1Num1 ); /* connectivity between Face1 and new face */ GW_Face* pFaceNeighbor = pFace1->GetFaceNeighbor(nVert1Num1); pNewFace1->SetFaceNeighbor( pFaceNeighbor, nVert1Num1 ); pNewFace1->SetFaceNeighbor( pFace1, nVert1Num2 ); if( pFaceNeighbor!=NULL ) { GW_I32 nNum = pFaceNeighbor->GetEdgeNumber( Vert2, *pFace1->GetVertex(nVert1Num3) ); GW_ASSERT( nNum>=0 ); pFaceNeighbor->SetFaceNeighbor( pNewFace1, nNum ); } /* connectivity for face 1 */ pFace1->SetFaceNeighbor( pNewFace1, nVert1Num1 ); pFace1->SetVertex( *pNewVert, nVert1Num2 ); /* reassign vertex 2 */ Vert2.SetFace( *pNewFace1 ); } if( pFace2!=NULL ) { nVert2Num1 = pFace2->GetEdgeNumber( Vert1 ); GW_ASSERT( nVert2Num1>=0 ); nVert2Num2 = pFace2->GetEdgeNumber( Vert2 ); GW_ASSERT( nVert2Num2>=0 ); nVert2Num3 = 3-nVert2Num2-nVert2Num1; pNewFace2 = &this->CreateNewFace(); this->SetNbrFace( this->GetNbrFace()+1 ); this->SetFace( this->GetNbrFace()-1, pNewFace2 ); pNewFace2->SetVertex( *pFace2->GetVertex(nVert2Num3), nVert2Num3 ); pNewFace2->SetVertex( Vert2, nVert2Num2 ); pNewFace2->SetVertex( *pNewVert, nVert2Num1 ); /* connectivity between Face2 and new face */ GW_Face* pFaceNeighbor = pFace2->GetFaceNeighbor(nVert2Num1); pNewFace2->SetFaceNeighbor( pFaceNeighbor, nVert2Num1 ); pNewFace2->SetFaceNeighbor( pFace2, nVert2Num2 ); if( pFaceNeighbor!=NULL ) { GW_I32 nNum = pFaceNeighbor->GetEdgeNumber( Vert2, *pFace2->GetVertex(nVert2Num3) ); GW_ASSERT( nNum>=0 ); pFaceNeighbor->SetFaceNeighbor( pNewFace2, nNum ); } /* connectivity for face 1 */ pFace2->SetFaceNeighbor( pNewFace2, nVert2Num1 ); pFace2->SetVertex( *pNewVert, nVert2Num2 ); /* reassign vertex 2 */ Vert2.SetFace( *pNewFace2 ); } /* set inter connectivity */ if( pNewFace1!=NULL ) pNewFace1->SetFaceNeighbor( pNewFace2, nVert1Num3 ); if( pNewFace2!=NULL ) pNewFace2->SetFaceNeighbor( pNewFace1, nVert2Num3 ); /* last thing : compute normal */ pNewVert->BuildRawNormal(); return pNewVert; }
/*------------------------------------------------------------------------------*/ void GW_Mesh::BuildConnectivity() { T_FaceList* VertexToFaceMap = new T_FaceList[this->GetNbrVertex()]; /* build the inverse map vertex->face */ for( IT_FaceVector it = FaceVector_.begin(); it!=FaceVector_.end(); ++it ) { GW_Face* pFace = *it; GW_ASSERT( pFace!=NULL ); for( GW_U32 i=0; i<3; ++i ) { GW_Vertex* pVert = pFace->GetVertex(i); GW_ASSERT(pVert!=NULL); GW_ASSERT( pVert->GetID() <= this->GetNbrVertex() ); VertexToFaceMap[pVert->GetID()].push_back( pFace ); } } /* now we can set up connectivity */ for( IT_FaceVector it=FaceVector_.begin(); it!=FaceVector_.end(); ++it ) { GW_Face* pFace = *it; GW_ASSERT( pFace!=NULL ); /* set up the neigbooring faces of the 3 vertices */ T_FaceList* pFaceLists[3]; for( GW_U32 i=0; i<3; ++i ) { GW_Vertex* pVert = pFace->GetVertex(i); pFaceLists[i] = &VertexToFaceMap[pVert->GetID()]; } /* compute neighbor in the 3 directions */ for( GW_U32 i=0; i<3; ++i ) { GW_Face* pNeighbor = NULL; GW_U32 i1 = (i+1)%3; GW_U32 i2 = (i+2)%3; /* we must find the intersection of the surrounding faces of these 2 vertex */ GW_Bool bFind = GW_False; for( IT_FaceList it1 = pFaceLists[i1]->begin(); it1!=pFaceLists[i1]->end() && bFind!=GW_True; ++it1 ) { GW_Face* pFace1 = *it1; for( IT_FaceList it2 = pFaceLists[i2]->begin(); it2!=pFaceLists[i2]->end() && bFind!=GW_True; ++it2 ) { GW_Face* pFace2 = *it2; if( pFace1==pFace2 && pFace1!=pFace ) { pNeighbor = pFace1; bFind=GW_True; } } } // GW_ASSERT( pNeighbor!=NULL ); /* assign the face */ /* if( pFace->GetFaceNeighbor(i)!=NULL ) GW_ASSERT( pFace->GetFaceNeighbor(i)==pNeighbor ); */ pFace->SetFaceNeighbor( pNeighbor, i ); /* make some test on the neighbor to assure symetry in the connectivity relationship */ if( pNeighbor!=NULL ) { GW_I32 nEdgeNumber = pNeighbor->GetEdgeNumber( *pFace->GetVertex(i1),*pFace->GetVertex(i2) ); GW_ASSERT( nEdgeNumber>=0 ); #if 0 if( pNeighbor->GetFaceNeighbor( nEdgeNumber )!=NULL ) GW_ASSERT(pNeighbor->GetFaceNeighbor(nEdgeNumber)==pFace); #endif pNeighbor->SetFaceNeighbor( pFace, nEdgeNumber ); } } } GW_DELETEARRAY( VertexToFaceMap ); }