Exemplo n.º 1
0
void GW_Mesh::CheckIntegrity()
{
	for( GW_U32 i=0; i<this->GetNbrVertex(); ++i ) 
	{
		GW_Vertex* pVert = this->GetVertex(i); GW_ASSERT( pVert!=NULL );
		GW_Face* pFace = pVert->GetFace();	GW_ASSERT( pFace!=NULL );
		if( pFace!=NULL && pFace->GetVertex(0)!=pVert &&
			pFace->GetVertex(1)!=pVert &&
			pFace->GetVertex(2)!=pVert )
			GW_ASSERT( GW_False );
	}
	for( GW_U32 i=0; i<this->GetNbrFace(); ++i )
	{
		GW_Face* pFace = this->GetFace(i);	GW_ASSERT( pFace!=NULL );
		for( GW_U32 k=0; k<3; ++k )
		{
			GW_U32 k1 = (k+1)%3;
			GW_U32 k2 = (k+2)%3;
			GW_Face* pNeighFace = pFace->GetFaceNeighbor(k);
			GW_Vertex* pV1 = pFace->GetVertex(k1);	GW_ASSERT( pV1!=NULL );
			GW_Vertex* pV2 = pFace->GetVertex(k2);	GW_ASSERT( pV2!=NULL );
			if( pNeighFace!=NULL )
			{
				GW_ASSERT( pNeighFace->GetFaceNeighbor(*pV1, *pV2)==pFace );
				GW_ASSERT( pFace->GetFaceNeighbor(*pV1, *pV2)==pNeighFace);
			}
		}
	}
}
Exemplo n.º 2
0
/*------------------------------------------------------------------------------*/
void GW_Mesh::FlipNormals()
{
	for( GW_U32 i=0; i<this->GetNbrVertex(); ++i )
	{
		GW_Vertex* pVert = this->GetVertex(i);	GW_ASSERT( pVert!=NULL );
		GW_Vector3D& n = pVert->GetNormal();
		n = -n;
	}
}
Exemplo n.º 3
0
/*------------------------------------------------------------------------------*/
void GW_Mesh::BuildRawNormal()
{
	for( IT_VertexVector it=VertexVector_.begin(); it!=VertexVector_.end(); ++it )
	{
		GW_Vertex* pVert = *it;
		GW_ASSERT( pVert!=NULL );
		pVert->BuildRawNormal();
	}
}
Exemplo n.º 4
0
/*------------------------------------------------------------------------------*/
void GW_Mesh::BuildCurvatureData()
{
	for( IT_VertexVector it=VertexVector_.begin(); it!=VertexVector_.end(); ++it )
	{
		GW_Vertex* pVert = *it;
		GW_ASSERT( pVert!=NULL );
		pVert->BuildCurvatureData();
	}

	GW_Float rArea = this->GetArea();
	GW_Float rTotalArea = GW_Vertex::rTotalArea_;
}
Exemplo n.º 5
0
/*------------------------------------------------------------------------------*/
GW_Vertex* GW_Mesh::InsertVertexInFace( GW_Face& Face, GW_Float x, GW_Float y, GW_Float z )
{
	GW_Vertex* pVert0 = Face.GetVertex(0);
	GW_Vertex* pVert1 = Face.GetVertex(1);
	GW_Vertex* pVert2 = Face.GetVertex(2);
	GW_ASSERT( pVert0!=NULL );
	GW_ASSERT( pVert1!=NULL );
	GW_ASSERT( pVert2!=NULL );
	/* create two new-faces */
	GW_Face* pFace1 = &this->CreateNewFace();
	GW_Face* pFace2 = &this->CreateNewFace();
	this->SetNbrFace( this->GetNbrFace()+2 );
	this->SetFace( this->GetNbrFace()-2, pFace1 );
	this->SetFace( this->GetNbrFace()-1, pFace2 );
	/* create one new vertex */
	GW_Vertex* pNewVert = &this->CreateNewVertex();
	GW_Vector3D pos = pVert0->GetPosition()*x + pVert1->GetPosition()*y + pVert2->GetPosition()*z;
	pNewVert->SetPosition( pos );
	pNewVert->BuildRawNormal();
	this->SetNbrVertex( this->GetNbrVertex()+1 );
	this->SetVertex( this->GetNbrVertex()-1, pNewVert );
	/* assign vertex to faces */
	pFace1->SetVertex( *pVert0, *pVert1, *pNewVert );
	pFace2->SetVertex( *pNewVert, *pVert1, *pVert2 );
	Face.SetVertex( *pVert0, *pNewVert, *pVert2 );
	/* assign dependance vertex->mother face */
	pNewVert->SetFace( Face );
	pVert0->SetFace( Face );
	pVert1->SetFace( *pFace1 );
	pVert2->SetFace( Face );
	/* outer faces */
	if( Face.GetFaceNeighbor(2)!=NULL )
	{
		GW_I32 nEdgeNumber = Face.GetFaceNeighbor(2)->GetEdgeNumber( Face );
		GW_ASSERT( nEdgeNumber>=0 );
		Face.GetFaceNeighbor(2)->SetFaceNeighbor( pFace1, nEdgeNumber );
	}
	if( Face.GetFaceNeighbor(0)!=NULL )
	{
		GW_I32 nEdgeNumber = Face.GetFaceNeighbor(0)->GetEdgeNumber( Face );
		GW_ASSERT( nEdgeNumber>=0 );
		Face.GetFaceNeighbor(0)->SetFaceNeighbor( pFace2, nEdgeNumber );
	}
	/* build connectivity of inner faces */
	pFace1->SetFaceNeighbor( pFace2, &Face, Face.GetFaceNeighbor(2) );
	pFace2->SetFaceNeighbor( Face.GetFaceNeighbor(0), &Face,  pFace1 );
	GW_Face* pTempFace = Face.GetFaceNeighbor(1);
	Face.SetFaceNeighbor(  pFace2, pTempFace, pFace1 );

	return pNewVert;
}
Exemplo n.º 6
0
void GW_Mesh::ExtractAllBoundaries( std::list<T_VertexList>& boundary_list )
{
	T_VertexMap AlreadyExtracted;
	for( GW_U32 i=0; i<this->GetNbrVertex(); ++i )
	{
		GW_Vertex* pVert = this->GetVertex(i);	GW_ASSERT( pVert!=NULL );
        if( pVert->IsBoundaryVertex() && AlreadyExtracted.find(i)==AlreadyExtracted.end() )
		{
			T_VertexList boundary;
			this->ExtractBoundary( *pVert, boundary, &AlreadyExtracted );
			boundary_list.push_back( boundary );
		}
	}
}
Exemplo n.º 7
0
/*------------------------------------------------------------------------------*/
GW_Vertex* GW_Mesh::GetRandomVertex()
{
	GW_U32 nNumber = 0;
	GW_Vertex* pStartVertex = NULL;
	while( pStartVertex==NULL )
	{
		if( nNumber>=this->GetNbrVertex()/10 )
			return NULL;
		GW_U32 nNumVert = (GW_U32) floor(GW_RAND*this->GetNbrVertex());
		pStartVertex = this->GetVertex( nNumVert );
		if( pStartVertex->GetFace()==NULL )
			pStartVertex = NULL;
		nNumber++;
	}
	return pStartVertex;
}
Exemplo n.º 8
0
void GW_Mesh::ExtractBoundary( GW_Vertex& seed, T_VertexList& boundary, T_VertexMap* pExtracted )
{
	GW_ASSERT( seed.IsBoundaryVertex() );
	GW_Vertex* pPrev = NULL;
	GW_Vertex* pCur = &seed;
	GW_Vertex* pNext = NULL;
	GW_U32 num = 0;
	do
	{
		num++;
		boundary.push_back(pCur);
		if( pExtracted!=NULL )
			(*pExtracted)[ pCur->GetID() ] = pCur;
		pNext = NULL;
		for( GW_VertexIterator it = pCur->BeginVertexIterator(); 
				(it!=pCur->EndVertexIterator()) && (pNext==NULL); ++it )
		{
			GW_Vertex* pVert = *it;
            if( pVert->IsBoundaryVertex() && pVert!=pPrev )
				pNext = pVert;
		}
		GW_ASSERT( pNext!=NULL );
		pPrev = pCur;
		pCur = pNext;
	}
	while( pCur!=&seed && pNext!=NULL && num<this->GetNbrVertex() );
}
Exemplo n.º 9
0
/*------------------------------------------------------------------------------*/
void GW_Mesh::IterateConnectedComponent_Vertex( GW_Vertex& start_vert, VertexIterate_Callback pCallback )
{
	/* march on the voronoi diagram */
	T_VertexList VertexToProceed;
	VertexToProceed.push_back( &start_vert );
	T_VertexMap VertexDone;
	VertexDone[ start_vert.GetID() ] = &start_vert;


	while( !VertexToProceed.empty() )
	{
		GW_Vertex* pVert = VertexToProceed.front();
		GW_ASSERT( pVert!=NULL );
		VertexToProceed.pop_front();

		/* cut the face */
		pCallback( *pVert );

		/* add neighbors */
		for( GW_VertexIterator it = pVert->BeginVertexIterator(); it!=pVert->EndVertexIterator(); ++it )
		{
			GW_Vertex* pNewVert = (GW_Vertex*) *it;
			if( pNewVert==NULL )
				break;
			GW_ASSERT( pNewVert!=NULL );
			if( VertexDone.find(pNewVert->GetID())==VertexDone.end() )
			{				
				VertexToProceed.push_back( pNewVert );
				VertexDone[ pNewVert->GetID() ] = pNewVert;	// so that it won't be added anymore
			}
		}
	}
}
Exemplo n.º 10
0
GW_Float GW_Mesh::GetPerimeter( T_VertexList& boundary, GW_Bool bCyclic )
{
	GW_Float rPerimeter = 0;
	GW_Vertex* pPrev = NULL;
	GW_Vertex* pVert = NULL;
	for( IT_VertexList it = boundary.begin(); it!=boundary.end(); ++it )
	{
		pVert = *it;
		if( pPrev!=NULL )
		{
			rPerimeter += (pPrev->GetPosition()-pVert->GetPosition()).Norm();
		}
		pPrev = pVert;
	}
	if( boundary.size()>1 && bCyclic )
	{
		rPerimeter += (boundary.front()->GetPosition()-pVert->GetPosition()).Norm();
	}
	return rPerimeter;
}
/*------------------------------------------------------------------------------*/
void GW_GeodesicDisplayer::AddFrontColor( GW_Vertex& VertFront, GW_Vector3D& Color )
{
	GW_U32 nID = VertFront.GetID();
	VertexColorMap_[nID] = Color;
}
/*------------------------------------------------------------------------------*/
void GW_GeodesicDisplayer::RemoveFrontColor( GW_Vertex& VertFront )
{
	VertexColorMap_.erase( VertFront.GetID() );
}
Exemplo n.º 13
0
/*------------------------------------------------------------------------------*/
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_GeodesicDisplayer::DisplayPath( GW_GeodesicPath& CurPath, GW_Vector3D& Color, GW_Float rLineWidth )
{
	glLineWidth( (GLfloat) rLineWidth );
	glPointSize( (GLfloat) rLineWidth );
	T_GeodesicPointList& PointList = CurPath.GetPointList();
	glDisable( GL_LIGHTING );
	glColor( Color );
	glBegin( GL_LINE_STRIP );
	for( IT_GeodesicPointList it = PointList.begin(); it!=PointList.end(); ++it )
	{
		GW_GeodesicPoint* pPoint = *it;
		GW_ASSERT( pPoint->GetVertex1()!=NULL );
		GW_ASSERT( pPoint->GetVertex2()!=NULL );
		GW_Vector3D Pos = pPoint->GetVertex1()->GetPosition()*pPoint->GetCoord() + 
						  pPoint->GetVertex2()->GetPosition()*(1-pPoint->GetCoord());
		glColor( Color );
		glVertex( Pos );
		GW_GeodesicFace* pFace = pPoint->GetCurFace();
		GW_ASSERT( pFace!=NULL );
		T_SubPointVector& SubPointVector = pPoint->GetSubPointVector();
		GW_Vector3D& v0 = pPoint->GetVertex1()->GetPosition();
		GW_Vector3D& v1 = pPoint->GetVertex2()->GetPosition();
		GW_Vertex* pLastVert = pFace->GetVertex( *pPoint->GetVertex1(), *pPoint->GetVertex2() );
		GW_ASSERT( pLastVert!=NULL );
		GW_Vector3D& v2 = pLastVert->GetPosition();
		for( IT_SubPointVector it=SubPointVector.begin(); it!=SubPointVector.end(); ++it )
		{
			GW_Vector3D& coord = *it;
			Pos = v0*coord[0] + v1*coord[1] + v2*coord[2];
			glVertex( Pos );
		}
	}
	glEnd();
#if 0
	glColor3f( 0,0,0 );
	glPointSize(4);
	glBegin( GL_POINTS );
	for( IT_GeodesicPointList it = PointList.begin(); it!=PointList.end(); ++it )
	{
		GW_GeodesicPoint* pPoint = *it;
		GW_ASSERT( pPoint->GetVertex1()!=NULL );
		GW_ASSERT( pPoint->GetVertex2()!=NULL );
		GW_Vector3D Pos = pPoint->GetVertex1()->GetPosition()*pPoint->GetCoord() + 
			pPoint->GetVertex2()->GetPosition()*(1-pPoint->GetCoord());
		glVertex( Pos );
		GW_GeodesicFace* pFace = pPoint->GetCurFace();
		GW_ASSERT( pFace!=NULL );
		T_SubPointVector& SubPointVector = pPoint->GetSubPointVector();
		GW_Vector3D& v0 = pPoint->GetVertex1()->GetPosition();
		GW_Vector3D& v1 = pPoint->GetVertex2()->GetPosition();
		GW_Vertex* pLastVert = pFace->GetVertex( *pPoint->GetVertex1(), *pPoint->GetVertex2() );
		GW_ASSERT( pLastVert!=NULL );
		GW_Vector3D& v2 = pLastVert->GetPosition();
		for( IT_SubPointVector it=SubPointVector.begin(); it!=SubPointVector.end(); ++it )
		{
			GW_Vector3D& coord = *it;
			Pos = v0*coord[0] + v1*coord[1] + v2*coord[2];
			glVertex( Pos );
		}
	}
	glEnd();

	glEnable( GL_LIGHTING );
	glLineWidth( 1 );
#endif
}
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;
}
Exemplo n.º 16
0
/*------------------------------------------------------------------------------*/
void GW_Vertex::ComputeCurvatureDirections( GW_Float rArea )
{
	GW_Vector3D CurEdge;
	GW_Vector3D CurEdgeNormalized;
	GW_Float rCurEdgeLength;
	GW_Float rCotan;
	GW_Vector3D TempEdge1, TempEdge2;
	GW_Vertex* pTempVert = NULL;
	GW_Float rDotP;

	/***********************************************************************************/
	/* compute the two curvature directions */
	/* (v1,v2) form a basis of the tangent plante */
	GW_Vector3D v1 = Normal_ ^ GW_Vector3D(0,0,1);
	GW_Float rNorm = v1.Norm();
	if( rNorm<GW_EPSILON )
	{
		/* orthogonalize using another direction */
		v1 = Normal_ ^ GW_Vector3D(0,1,0);
		rNorm = v1.Norm();
		GW_ASSERT( rNorm>GW_EPSILON );
	}
	v1 /= rNorm;
	GW_Vector3D v2 = Normal_ ^ v1;

	/* now we must find the curvature matrix entry by minimising a mean square problem 
	the 3 entry of the symetric curvature matrix in (v1,v2) basis are (a,b,c), stored in vector x.
	IMPORTANT : we must ensure a<c, so that eigenvalues are in correct order. */
	GW_Float a = 0, b = 0, c = 0;			// the vector (a,b,c) we are searching. We use a+c=2*MeanCurv so we don't take care of c.
	GW_Float D[2] = {0,0};					// the right side of the equation.
	GW_Float M00 = 0, M11 = 0, M01 = 0;		// the positive-definite matrix entries of the mean-square problem.
	GW_Float d1, d2;	// decomposition of current edge on (v1,v2) basis
	GW_Float w, k;		// current weight and current approximated directional curvature.

	/* now build the matrix by iterating around the vertex */
	for( GW_VertexIterator it = this->BeginVertexIterator(); it!=this->EndVertexIterator(); ++it )
	{
		GW_Vertex* pVert = *it;
		GW_ASSERT( pVert!=NULL );
		CurEdge = pVert->GetPosition() - this->GetPosition();
		rCurEdgeLength = CurEdge.Norm();
		CurEdgeNormalized = CurEdge/rCurEdgeLength;

		/* here we store the value of the sum of the cotan */
		rCotan = 0;

		/* compute projection onto v1,v2 basis */
		d1 = v1*CurEdge;
		d2 = v2*CurEdge;
		rNorm = sqrt(d1*d1 + d2*d2);
		if( rNorm>0 )
		{
			d1 /= rNorm;
			d2 /= rNorm;
		}

		/* compute left angle */
		pTempVert = it.GetLeftVertex();
		if( pTempVert!=NULL )
		{
			TempEdge1 = this->GetPosition() -  pTempVert->GetPosition();
			TempEdge2 = pVert->GetPosition() - pTempVert->GetPosition();
			TempEdge1.Normalize();
			TempEdge2.Normalize();
			/* we use tan(acos(x))=sqrt(1-x^2)/x */
			rDotP = TempEdge1*TempEdge2;
			if( rDotP!=1 && rDotP!=-1 )
				rCotan += rDotP/sqrt(1-rDotP*rDotP);
		}

		/* compute right angle AND Gaussian contribution */
		pTempVert = it.GetRightVertex();
		if( pTempVert!=NULL )
		{
			TempEdge1 = this->GetPosition() -  pTempVert->GetPosition();
			TempEdge2 = pVert->GetPosition() - pTempVert->GetPosition();
			TempEdge1.Normalize();
			TempEdge2.Normalize();
			/* we use tan(acos(x))=sqrt(1-x^2)/x */
			rDotP = TempEdge1*TempEdge2;
			if( rDotP!=1 && rDotP!=-1 )
				rCotan += (GW_Float) rDotP/sqrt(1-rDotP*rDotP);

		}
		GW_CHECK_MATHSBIT();

		/*compute weight */
		w = 0.125/rArea*rCotan*rCurEdgeLength*rCurEdgeLength;
		/* compute directional curvature */
		k = -2*(CurEdge*Normal_)/(rCurEdgeLength*rCurEdgeLength);
		k = k-(rMinCurv_+rMaxCurv_);	// modified by the fact that we use a+c=2*MeanCurv
		/* add contribution to M matrix and D vector*/ 
		M00		+=   w*(d1*d1-d2*d2)*(d1*d1-d2*d2);
		M11		+= 4*w*d1*d1*d2*d2;
		M01		+= 2*w*(d1*d1-d2*d2)*d1*d2;
		D[0]    +=   w*k*( d1*d1-d2*d2);
		D[1]    += 2*w*k*d1*d2;
	}
	GW_CHECK_MATHSBIT();

	/* solve the system */
	GW_Float rDet = M00*M11 - M01*M01;
	if( rDet!=0 )
	{
		/*	The inverse matrix is :      | M11 -M01|
								1/rDet * |-M01  M00| */
		a = 1/rDet * ( M11*D[0] - M01*D[1] );
		b = 1/rDet * (-M01*D[0] + M00*D[1] );
	}

	c = (rMinCurv_+rMaxCurv_) - a;
	// GW_ORDER(a,c);

	/* compute the direction via Givens rotations */
	GW_Float rTheta;
	if( GW_ABS(c-a) < GW_EPSILON )
	{
		if( b==0 )
			rTheta = 0;
		else
			rTheta = GW_HALFPI;
	}
	else
	{
		rTheta = (GW_Float) 2.0f*b/(c-a);
		rTheta = (GW_Float) 0.5f*atan(rTheta);
	}

	GW_CHECK_MATHSBIT();

	CurvDirMin_ = v1*cos(rTheta) - v2*sin(rTheta);
	CurvDirMax_ = v1*sin(rTheta) + v2*cos(rTheta);

	GW_Float vp1 = 0, vp2 = 0;
	if( rTheta!=0 )
	{
		GW_Float r1 = a*cos(rTheta) - b*sin(rTheta);
		GW_Float r2 = b*cos(rTheta) - c*sin(rTheta);
		r1 =(GW_Float)  r1/cos(rTheta);
		r2 = (GW_Float) -r2/sin(rTheta);
		vp1 = r1;
//		GW_ASSERT( GW_ABS(r1-r2)<0.001*GW_ABS(r1) );

		r1 = (GW_Float) a*sin(rTheta) + b*cos(rTheta);
		r2 = (GW_Float) b*sin(rTheta) + c*cos(rTheta);
		r1 = (GW_Float) r1/sin(rTheta);
		r2 = (GW_Float) r2/cos(rTheta);
		vp2 = r2;
//		GW_ASSERT( GW_ABS(r1-r2)<0.001*GW_ABS(r1) );
	}

	if( vp1>vp2 )
	{
		GW_Vector3D vtemp = CurvDirMin_;
		CurvDirMin_ = CurvDirMax_;
		CurvDirMax_ = vtemp;
	}
}
/*------------------------------------------------------------------------------*/
void GW_TriangularInterpolation_Cubic::ComputeLocalGradient(  GW_GeodesicVertex& Vert )
{
    /* compute the total angle */
    GW_Vector3D PrevEdge;
    GW_Float rTotalAngle = 0;
    for( GW_VertexIterator it=Vert.BeginVertexIterator(); it!=Vert.EndVertexIterator(); ++it )
    {
        GW_Vertex* pVert = *it;
        GW_ASSERT( pVert!=NULL );
        if( it==Vert.BeginVertexIterator() )
        {
            PrevEdge = pVert->GetPosition() - Vert.GetPosition();
            PrevEdge.Normalize();
        }
        else
        {
            GW_Vector3D NextEdge = pVert->GetPosition() - Vert.GetPosition();
            NextEdge.Normalize();
            rTotalAngle += acos( NextEdge*PrevEdge );
            PrevEdge = NextEdge;
        }
    }

    /* matrix and RHS for least square minimusation */
    GW_Float M[2][2] = {{0,0},{0,0}};
    GW_Float b[2] = {0,0};

    GW_Float rCurAngle = 0;
    PrevEdge.SetZero();
    for( GW_VertexIterator it=Vert.BeginVertexIterator(); it!=Vert.EndVertexIterator(); ++it )
    {
        GW_GeodesicVertex* pVert = (GW_GeodesicVertex*) *it;
        GW_ASSERT( pVert!=NULL );

        GW_Vector3D Edge = pVert->GetPosition() - Vert.GetPosition();
        GW_Float a = Edge.Norm();
        Edge /= a;

        if( it!=Vert.BeginVertexIterator() )
        {
            /* update the angle */
            rCurAngle += acos( Edge*PrevEdge );
        }

        /* directional gradient estimation */
        GW_Float delta = (pVert->GetDistance() - Vert.GetDistance())/a;
        /* coordonate of the edge on (u,v) [flatened coords] */
        GW_Float eu = a*cos( rCurAngle/rTotalAngle );
        GW_Float ev = a*sin( rCurAngle/rTotalAngle );
        /* update the matrix */
        M[0][0] += eu*eu;
        M[0][1] += eu*ev;
        M[1][0] += eu*ev;
        M[1][1] += ev*ev;
        b[0] += delta*eu;
        b[1] += delta*ev;

        PrevEdge = Edge;
    }

    /* invert the system */
    GW_Float det = M[0][0]*M[1][1] - M[0][1]*M[1][0];
    GW_ASSERT( det!=0 );
    GW_Float gu = 1/det * ( M[1][1]*b[0] - M[0][1]*b[1] );
    GW_Float gv = 1/det * (-M[1][0]*b[0] + M[0][0]*b[1] );

    /* set the gradient in local coords for each surrounding face */
    rCurAngle = 0;
    for( GW_FaceIterator it = Vert.BeginFaceIterator(); it!=Vert.EndFaceIterator(); ++it )
    {
        GW_GeodesicFace* pFace = (GW_GeodesicFace*) *it;
        GW_ASSERT( pFace!=NULL );
        GW_Vertex* pVert1 = it.GetLeftVertex();        GW_ASSERT( pVert1!=NULL );
        GW_Vertex* pVert2 = it.GetRightVertex();    GW_ASSERT( pVert1!=NULL );
        GW_Vector3D e1 = pVert1->GetPosition() - Vert.GetPosition();
        GW_Vector3D e2 = pVert2->GetPosition() - Vert.GetPosition();
        GW_Float a1 = e1.Norm();
        GW_Float a2 = e2.Norm();
        e1 /= a1;
        e2 /= a2;
        GW_Float rInnerAngle = acos( e1*e2 );
        /* flattened position of the two vertex */
        GW_Float p1[2], p2[2];
        p1[0] = cos( rCurAngle );
        p1[1] = sin( rCurAngle );
        p2[0] = cos( rCurAngle+rInnerAngle );
        p2[1] = sin( rCurAngle+rInnerAngle );

        /* we have                    grad = gu*u + gv*v
           we are searching for        grad = g1*p1 + g2*p2, so:
                gu = g1*<p1,u> + g2*<p2,u>
                gv = g1*<p1,v> + g2*<p2,v>
            i.e.
                |p1[0] p2[0]| |g1|   |gu|
                |p1[1] p2[1]|*|g2| = |gv|
        */
        det = p1[0]*p2[1]-p1[1]*p2[0];
        GW_ASSERT( det!=0 );
        GW_Float g1 = 1/det * ( p2[1]*gu - p2[0]*gv );
        GW_Float g2 = 1/det * (-p1[1]*gu + p1[0]*gv );

        /* now compute the gradient in world coords */
        GW_Vector3D LocGrad = e1*g1 + e2*g2;

        GW_TriangularInterpolation_ABC* pInterp = pFace->GetTriangularInterpolation();
        if( pInterp==NULL )
        {
            pInterp = new GW_TriangularInterpolation_Cubic;
            pFace->SetTriangularInterpolation( *pInterp );
        }
        GW_ASSERT( pInterp->GetType()==kCubicTriangulationInterpolation );

        ((GW_TriangularInterpolation_Cubic*) pInterp)->SetLocalGradient( LocGrad, *pFace, Vert );

        rCurAngle += rInnerAngle;
    }

}
Exemplo n.º 18
0
/*------------------------------------------------------------------------------*/
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 );
}
Exemplo n.º 19
0
/*------------------------------------------------------------------------------*/
void GW_Vertex::ComputeNormalAndCurvature( GW_Float& rArea )
{
	GW_Vector3D CurEdge;
	GW_Vector3D CurEdgeNormalized;
	GW_Float rCurEdgeLength;
	GW_Float rCotan;
	GW_Vector3D TempEdge1, TempEdge2;
	GW_Float rTempEdge1Length, rTempEdge2Length;
	GW_Float rAngle, rInnerAngle;
	GW_Vertex* pTempVert = NULL;
	GW_Float rDotP;

	Normal_.SetZero();
	rArea = 0;
	GW_Float rGaussianCurv = 0;

	for( GW_VertexIterator it = this->BeginVertexIterator(); it!=this->EndVertexIterator(); ++it )
	{
		GW_Vertex* pVert = *it;
		GW_ASSERT( pVert!=NULL );
		CurEdge = pVert->GetPosition() - this->GetPosition();
		rCurEdgeLength = CurEdge.Norm();
		CurEdgeNormalized = CurEdge/rCurEdgeLength;

		/* here we store the value of the sum of the cotan */
		rCotan = 0;

		/* compute left angle */
		pTempVert = it.GetLeftVertex();
		if( pTempVert!=NULL )
		{
			TempEdge1 = this->GetPosition() -  pTempVert->GetPosition();
			TempEdge2 = pVert->GetPosition() - pTempVert->GetPosition();

			TempEdge1.Normalize();
			TempEdge2.Normalize();
			/* we use tan(acos(x))=sqrt(1-x^2)/x */
			rDotP = TempEdge1*TempEdge2;
			if( rDotP!=1 && rDotP!=-1 )
				rCotan += (GW_Float) rDotP/((GW_Float) sqrt(1-rDotP*rDotP));
		}

		/* compute right angle AND Gaussian contribution */
		pTempVert = it.GetRightVertex();
		if( pTempVert!=NULL )
		{
			TempEdge1 = this->GetPosition() -  pTempVert->GetPosition();
			TempEdge2 = pVert->GetPosition() - pTempVert->GetPosition();
			rTempEdge1Length = TempEdge1.Norm();
			rTempEdge2Length = TempEdge2.Norm();
			TempEdge1 /= rTempEdge1Length;
			TempEdge2 /= rTempEdge2Length;
			rAngle      = (GW_Float) acos( -(TempEdge1 * CurEdgeNormalized) );
			/* we use tan(acos(x))=sqrt(1-x^2)/x */
			rDotP = TempEdge1*TempEdge2;
			rInnerAngle = (GW_Float) acos( rDotP  );
			if( rDotP!=1 && rDotP!=-1 )
				rCotan += rDotP/((GW_Float) sqrt(1-rDotP*rDotP));

			rGaussianCurv += rAngle;

			/* compute the contribution to area, testing for special obtuse angle */
			if(	   rAngle<GW_HALFPI							// condition on 1st angle
				&& rInnerAngle<GW_HALFPI					// condition on 2nd angle
				&& (GW_PI-rAngle-rInnerAngle)<GW_HALFPI )	// condition on 3rd angle
			{
				/* non-obtuse : 1/8*( |PR|²cot(Q)+|PQ|²cot(R) ) where P=this, Q=pVert, R=pTempVert   */
				rArea += ( rCurEdgeLength*rCurEdgeLength*rDotP/sqrt(1-rDotP*rDotP)
					+ rTempEdge1Length*rTempEdge1Length/tan(GW_PI-rAngle-rInnerAngle) )*0.125;
			}
			else if( rAngle>=GW_HALFPI )
			{
				/* obtuse at the central vertex : 0.5*area(T) */
				rArea += 0.25*rCurEdgeLength*rTempEdge1Length* ~(CurEdgeNormalized^TempEdge1);
			}
			else
			{
				/* obtuse at one of side vertex */
				rArea += 0.125*rCurEdgeLength*rTempEdge1Length* ~(CurEdgeNormalized^TempEdge1);
			}
		}
		GW_CHECK_MATHSBIT();

		/* add the contribution to Normal */
		Normal_ -= CurEdge*rCotan;
	}
	GW_CHECK_MATHSBIT();

	GW_ASSERT( rArea!=0 );	// remove this !

	/* the Gaussian curv */
	rGaussianCurv = (GW_TWOPI - rGaussianCurv)/rArea;
	/* compute Normal and mean curv */
	Normal_ /= 4.0*rArea;
	GW_Float rMeanCurv = Normal_.Norm();
	if( GW_ABS(rMeanCurv)>GW_EPSILON )
	{
		GW_Vector3D Normal = Normal_/rMeanCurv;
		/* see if we need to flip the normal */
		this->BuildRawNormal();
		if( Normal*Normal_<0 )
			Normal_ = -Normal;
		else
			Normal_ = Normal;
	}
	else
	{
		/* we must use another method to compute normal */
		this->BuildRawNormal();
	}

	GW_Vertex::rTotalArea_ += rArea;

	/* compute the two curv values */
	GW_Float rDelta = rMeanCurv*rMeanCurv - rGaussianCurv;
	if( rDelta<0 )
		rDelta = 0;
	rDelta = sqrt(rDelta);
	rMinCurv_ = rMeanCurv - rDelta;
	rMaxCurv_ = rMeanCurv + rDelta;
}