/////////////////////////////////////////////////////////////////////////////////////////// // 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; } }
/////////////////////////////////////////////////////////////////////////////////////////// // 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; } } } }
/////////////////////////////////////////////////////////////////////////////////////////// // 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); }