///////////////////////////////////////////////////////////////////////////////////////////
// FindOtherFace
//
// find the other face sharing these vertices
// exactly like the edge info above
//
NvFaceInfo * NvStripifier::FindOtherFace(NvEdgeInfoVec &edgeInfos, int v0, int v1, NvFaceInfo *faceInfo){
	NvEdgeInfo *edgeInfo = FindEdgeInfo(edgeInfos, v0, v1);

	if( (edgeInfo == NULL) && (v0 == v1))
	{
		//we've hit a degenerate
		return NULL;
	}

	return (edgeInfo->m_face0 == faceInfo ? edgeInfo->m_face1 : edgeInfo->m_face0);
}
///////////////////////////////////////////////////////////////////////////////////////////
// BuildStripifyInfo()
//
// Builds the list of all face and edge infos
//
void NvStripifier::BuildStripifyInfo(NvFaceInfoVec &faceInfos, NvEdgeInfoVec &edgeInfos,
									 const unsigned short maxIndex)
{
	// reserve space for the face infos, but do not resize them.
	int numIndices = indices.size();
	faceInfos.reserve(numIndices / 3);
	
	// we actually resize the edge infos, so we must initialize to NULL
	edgeInfos.resize(maxIndex + 1);
	for (unsigned short i = 0; i < maxIndex + 1; i++)
		edgeInfos[i] = NULL;
	
	// iterate through the triangles of the triangle list
	int numTriangles = numIndices / 3;
	int index        = 0;
	bool bFaceUpdated[3];

	for (int i = 0; i < numTriangles; i++)
	{	
		bool bMightAlreadyExist = true;
		bFaceUpdated[0] = false;
		bFaceUpdated[1] = false;
		bFaceUpdated[2] = false;

		// grab the indices
		int v0 = indices[index++];
		int v1 = indices[index++];
		int v2 = indices[index++];

		//we disregard degenerates
		if(IsDegenerate(v0, v1, v2))
			continue;
		
		// create the face info and add it to the list of faces, but only if this exact face doesn't already 
		//  exist in the list
		NvFaceInfo *faceInfo = new NvFaceInfo(v0, v1, v2);
		
		// grab the edge infos, creating them if they do not already exist
		NvEdgeInfo *edgeInfo01 = FindEdgeInfo(edgeInfos, v0, v1);
		if (edgeInfo01 == NULL)
		{
			//since one of it's edges isn't in the edge data structure, it can't already exist in the face structure
			bMightAlreadyExist = false;

			// create the info
			edgeInfo01 = new NvEdgeInfo(v0, v1);
			
			// update the linked list on both 
			edgeInfo01->m_nextV0 = edgeInfos[v0];
			edgeInfo01->m_nextV1 = edgeInfos[v1];
			edgeInfos[v0] = edgeInfo01;
			edgeInfos[v1] = edgeInfo01;
			
			// set face 0
			edgeInfo01->m_face0 = faceInfo;
		}
		else 
		{
			if (edgeInfo01->m_face1 != NULL)
			{
				printf("BuildStripifyInfo: > 2 triangles on an edge... uncertain consequences\n");
			}
			else
			{
				edgeInfo01->m_face1 = faceInfo;
				bFaceUpdated[0] = true;
			}
		}
		
		// grab the edge infos, creating them if they do not already exist
		NvEdgeInfo *edgeInfo12 = FindEdgeInfo(edgeInfos, v1, v2);
		if (edgeInfo12 == NULL)
		{
			bMightAlreadyExist = false;
			
			// create the info
			edgeInfo12 = new NvEdgeInfo(v1, v2);
			
			// update the linked list on both 
			edgeInfo12->m_nextV0 = edgeInfos[v1];
			edgeInfo12->m_nextV1 = edgeInfos[v2];
			edgeInfos[v1] = edgeInfo12;
			edgeInfos[v2] = edgeInfo12;
			
			// set face 0
			edgeInfo12->m_face0 = faceInfo;
		}
		else 
		{
			if (edgeInfo12->m_face1 != NULL)
			{
				printf("BuildStripifyInfo: > 2 triangles on an edge... uncertain consequences\n");
			}
			else
			{
				edgeInfo12->m_face1 = faceInfo;
				bFaceUpdated[1] = true;
			}
		}
		
		// grab the edge infos, creating them if they do not already exist
		NvEdgeInfo *edgeInfo20 = FindEdgeInfo(edgeInfos, v2, v0);
		if (edgeInfo20 == NULL)
		{
			bMightAlreadyExist = false;

			// create the info
			edgeInfo20 = new NvEdgeInfo(v2, v0);
			
			// update the linked list on both 
			edgeInfo20->m_nextV0 = edgeInfos[v2];
			edgeInfo20->m_nextV1 = edgeInfos[v0];
			edgeInfos[v2] = edgeInfo20;
			edgeInfos[v0] = edgeInfo20;
			
			// set face 0
			edgeInfo20->m_face0 = faceInfo;
		}
		else 
		{
			if (edgeInfo20->m_face1 != NULL)
			{
				printf("BuildStripifyInfo: > 2 triangles on an edge... uncertain consequences\n");
			}
			else
			{
				edgeInfo20->m_face1 = faceInfo;
				bFaceUpdated[2] = true;
			}
		}

		if(bMightAlreadyExist)
		{
			if(!AlreadyExists(faceInfo, faceInfos))
				faceInfos.push_back(faceInfo);
			else
			{
				delete faceInfo;

				//cleanup pointers that point to this deleted face
				if(bFaceUpdated[0])
					edgeInfo01->m_face1 = NULL;
				if(bFaceUpdated[1])
					edgeInfo12->m_face1 = NULL;
				if(bFaceUpdated[2])
					edgeInfo20->m_face1 = NULL;
			}
		}
		else
		{
			faceInfos.push_back(faceInfo);
		}

	}
}
///////////////////////////////////////////////////////////////////////////////////////////
// FindAllStrips()
//
// Does the stripification, puts output strips into vector allStrips
//
// Works by setting runnning a number of experiments in different areas of the mesh, and
//  accepting the one which results in the longest strips.  It then accepts this, and moves
//  on to a different area of the mesh.  We try to jump around the mesh some, to ensure that
//  large open spans of strips get generated.
//
void NvStripifier::FindAllStrips(NvStripInfoVec &allStrips,
								 NvFaceInfoVec &allFaceInfos,
								 NvEdgeInfoVec &allEdgeInfos,
								 int numSamples){
	// the experiments
	int experimentId = 0;
	int stripId      = 0;
	bool done        = false;

	int loopCtr = 0;
	
	while (!done)
	{
		loopCtr++;
		
		//
		// PHASE 1: Set up numSamples * numEdges experiments
		//
		NvStripInfoVec *experiments = new NvStripInfoVec [numSamples * 6];
		int experimentIndex = 0;
		std::set   <NvFaceInfo*>  resetPoints;
		for (int i = 0; i < numSamples; i++)
		{
			
			// Try to find another good reset point.
			// If there are none to be found, we are done
			NvFaceInfo *nextFace = FindGoodResetPoint(allFaceInfos, allEdgeInfos);
			if (nextFace == NULL){
				done = true;
				break;
			}
			// If we have already evaluated starting at this face in this slew
			// of experiments, then skip going any further
			else if (resetPoints.find(nextFace) != resetPoints.end()){
				continue;
			}
			
			// trying it now...
			resetPoints.insert(nextFace);
			
			// otherwise, we shall now try experiments for starting on the 01,12, and 20 edges
			assert(nextFace->m_stripId < 0);
			
			// build the strip off of this face's 0-1 edge
			NvEdgeInfo *edge01 = FindEdgeInfo(allEdgeInfos, nextFace->m_v0, nextFace->m_v1);
			NvStripInfo *strip01 = new NvStripInfo(NvStripStartInfo(nextFace, edge01, true), stripId++, experimentId++);
			experiments[experimentIndex++].push_back(strip01);
			
			// build the strip off of this face's 1-0 edge
			NvEdgeInfo *edge10 = FindEdgeInfo(allEdgeInfos, nextFace->m_v0, nextFace->m_v1);
			NvStripInfo *strip10 = new NvStripInfo(NvStripStartInfo(nextFace, edge10, false), stripId++, experimentId++);
			experiments[experimentIndex++].push_back(strip10);
			
			// build the strip off of this face's 1-2 edge
			NvEdgeInfo *edge12 = FindEdgeInfo(allEdgeInfos, nextFace->m_v1, nextFace->m_v2);
			NvStripInfo *strip12 = new NvStripInfo(NvStripStartInfo(nextFace, edge12, true), stripId++, experimentId++);
			experiments[experimentIndex++].push_back(strip12);
			
			// build the strip off of this face's 2-1 edge
			NvEdgeInfo *edge21 = FindEdgeInfo(allEdgeInfos, nextFace->m_v1, nextFace->m_v2);
			NvStripInfo *strip21 = new NvStripInfo(NvStripStartInfo(nextFace, edge21, false), stripId++, experimentId++);
			experiments[experimentIndex++].push_back(strip21);
			
			// build the strip off of this face's 2-0 edge
			NvEdgeInfo *edge20 = FindEdgeInfo(allEdgeInfos, nextFace->m_v2, nextFace->m_v0);
			NvStripInfo *strip20 = new NvStripInfo(NvStripStartInfo(nextFace, edge20, true), stripId++, experimentId++);
			experiments[experimentIndex++].push_back(strip20);
			
			// build the strip off of this face's 0-2 edge
			NvEdgeInfo *edge02 = FindEdgeInfo(allEdgeInfos, nextFace->m_v2, nextFace->m_v0);
			NvStripInfo *strip02 = new NvStripInfo(NvStripStartInfo(nextFace, edge02, false), stripId++, experimentId++);
			experiments[experimentIndex++].push_back(strip02);
		}
		
		//
		// PHASE 2: Iterate through that we setup in the last phase
		// and really build each of the strips and strips that follow to see how
		// far we get
		//
		int numExperiments = experimentIndex;
		for (int i = 0; i < numExperiments; i++){
			
			// get the strip set
			
			// build the first strip of the list
			experiments[i][0]->Build(allEdgeInfos, allFaceInfos);
			int experimentId = experiments[i][0]->m_experimentId;
			
			NvStripInfo *stripIter = experiments[i][0];
			NvStripStartInfo startInfo(NULL, NULL, false);
			while (FindTraversal(allFaceInfos, allEdgeInfos, stripIter, startInfo)){
				
				// create the new strip info
				stripIter = new NvStripInfo(startInfo, stripId++, experimentId);
				
				// build the next strip
				stripIter->Build(allEdgeInfos, allFaceInfos);
				
				// add it to the list
				experiments[i].push_back(stripIter);
			}
		}
		
		//
		// Phase 3: Find the experiment that has the most promise
		//
		int bestIndex = 0;
		double bestValue = 0;
		for (int i = 0; i < numExperiments; i++)
		{
			const float avgStripSizeWeight = 1.0f;
			const float numTrisWeight      = 0.0f;
			const float numStripsWeight    = 0.0f;
			float avgStripSize = AvgStripSize(experiments[i]);
			float numStrips    = (float) experiments[i].size();
			float value        = avgStripSize * avgStripSizeWeight + (numStrips * numStripsWeight);
			//float value = 1.f / numStrips;
			//float value = numStrips * avgStripSize;
				
			if (value > bestValue)
			{
				bestValue = value;
				bestIndex = i;
			}
		}

		//
		// Phase 4: commit the best experiment of the bunch
		//
		CommitStrips(allStrips, experiments[bestIndex]);
		
		// and destroy all of the others
		for (int i = 0; i < numExperiments; i++)
		{
			if (i != bestIndex)
			{
				int numStrips = experiments[i].size();
				for (int j = 0; j < numStrips; j++)
				{
					NvStripInfo* currStrip = experiments[i][j];
					//delete all bogus faces in the experiments
					for (size_t k = 0; k < currStrip->m_faces.size(); ++k)
					{
						if(currStrip->m_faces[k]->m_bIsFake)
						{
							delete currStrip->m_faces[k], currStrip->m_faces[k] = NULL;
						}
					}
					delete currStrip, currStrip = NULL, experiments[i][j] = NULL;
				}
			}
		}
		
		// delete the array that we used for all experiments
		delete [] experiments;
  }
}
Exemple #4
0
///////////////////////////////////////////////////////////////////////////////////////////
// BuildStripifyInfo()
//
// Builds the list of all face and edge infos
//
void NvStripifier::BuildStripifyInfo(NvFaceInfoVec &faceInfos, NvEdgeInfoVec &edgeInfos){
	
	// reserve space for the face infos, but do not resize them.
	int numIndices = indices.size();
	faceInfos.reserve(numIndices);
	
	// we actually resize the edge infos, so we must initialize to NULL
	edgeInfos.resize (numIndices);
	for (int i = 0; i < numIndices; i++)
		edgeInfos[i] = NULL;
	
	// iterate through the triangles of the triangle list
	int numTriangles = numIndices / 3;
	int index        = 0;
	for (u32 i = 0; i < numTriangles; i++)
	{	
		// grab the indices
		int v0 = indices[index++];
		int v1 = indices[index++];
		int v2 = indices[index++];
		
		// create the face info and add it to the list of faces, but only if this exact face doesn't already 
		//  exist in the list
		NvFaceInfo *faceInfo = xr_new<NvFaceInfo>(v0, v1, v2);
		if(!AlreadyExists(faceInfo, faceInfos))
		{
			faceInfos.push_back(faceInfo);
			
			// grab the edge infos, creating them if they do not already exist
			NvEdgeInfo *edgeInfo01 = FindEdgeInfo(edgeInfos, v0, v1);
			if (edgeInfo01 == NULL){
				
				// create the info
				edgeInfo01 = xr_new<NvEdgeInfo>(v0, v1);
				
				// update the linked list on both 
				edgeInfo01->m_nextV0 = edgeInfos[v0];
				edgeInfo01->m_nextV1 = edgeInfos[v1];
				edgeInfos[v0] = edgeInfo01;
				edgeInfos[v1] = edgeInfo01;
				
				// set face 0
				edgeInfo01->m_face0 = faceInfo;
			}
			else {
				if (edgeInfo01->m_face1 != NULL)	;
					//Msg("! WARNING: BuildStripifyInfo: > 2 triangles on an edge... uncertain consequences");
				else
					edgeInfo01->m_face1 = faceInfo;
			}
			
			// grab the edge infos, creating them if they do not already exist
			NvEdgeInfo *edgeInfo12 = FindEdgeInfo(edgeInfos, v1, v2);
			if (edgeInfo12 == NULL){
				
				// create the info
				edgeInfo12 = xr_new<NvEdgeInfo> (v1, v2);
				
				// update the linked list on both 
				edgeInfo12->m_nextV0 = edgeInfos[v1];
				edgeInfo12->m_nextV1 = edgeInfos[v2];
				edgeInfos[v1] = edgeInfo12;
				edgeInfos[v2] = edgeInfo12;
				
				// set face 0
				edgeInfo12->m_face0 = faceInfo;
			}
			else {
				if (edgeInfo12->m_face1 != NULL)	;
					//Msg("! WARNING: BuildStripifyInfo: > 2 triangles on an edge... uncertain consequences");
				else
					edgeInfo12->m_face1 = faceInfo;
			}
			
			// grab the edge infos, creating them if they do not already exist
			NvEdgeInfo *edgeInfo20 = FindEdgeInfo(edgeInfos, v2, v0);
			if (edgeInfo20 == NULL){
				
				// create the info
				edgeInfo20 = xr_new<NvEdgeInfo>(v2, v0);
				
				// update the linked list on both 
				edgeInfo20->m_nextV0 = edgeInfos[v2];
				edgeInfo20->m_nextV1 = edgeInfos[v0];
				edgeInfos[v2] = edgeInfo20;
				edgeInfos[v0] = edgeInfo20;
				
				// set face 0
				edgeInfo20->m_face0 = faceInfo;
			}
			else {
				if (edgeInfo20->m_face1 != NULL)	;
					//Msg("! WARNING: BuildStripifyInfo: > 2 triangles on an edge... uncertain consequences");
				else
					edgeInfo20->m_face1 = faceInfo;
			}
			
		}
	}
}
Exemple #5
0
///////////////////////////////////////////////////////////////////////////////////////////
// FindOtherFace
//
// find the other face sharing these vertices
// exactly like the edge info above
//
NvFaceInfo * NvStripifier::FindOtherFace(NvEdgeInfoVec &edgeInfos, int v0, int v1, NvFaceInfo *faceInfo){
	NvEdgeInfo *edgeInfo = FindEdgeInfo(edgeInfos, v0, v1);
	assert(edgeInfo != NULL);
	return (edgeInfo->m_face0 == faceInfo ? edgeInfo->m_face1 : edgeInfo->m_face0);
}