//////////////////////////////////////////////////////////////////////////////////////// // GenerateStrips() // // in_indices: input index list, the indices you would use to render // in_numIndices: number of entries in in_indices // primGroups: array of optimized/stripified PrimitiveGroups // numGroups: number of groups returned // // Be sure to call delete[] on the returned primGroups to avoid leaking mem // bool GenerateStrips(const unsigned short* in_indices, const unsigned int in_numIndices, PrimitiveGroup** primGroups, unsigned short* numGroups, bool validateEnabled) { int i = 0; //put data in format that the stripifier likes WordVec tempIndices; tempIndices.resize(in_numIndices); unsigned short maxIndex = 0; unsigned short minIndex = 0xFFFF; for(i = 0; i < in_numIndices; i++) { tempIndices[i] = in_indices[i]; if (in_indices[i] > maxIndex) maxIndex = in_indices[i]; if (in_indices[i] < minIndex) minIndex = in_indices[i]; } NvStripInfoVec tempStrips; NvFaceInfoVec tempFaces; NvStripifier stripifier; //do actual stripification stripifier.Stripify(tempIndices, cacheSize, minStripSize, maxIndex, tempStrips, tempFaces); //stitch strips together IntVec stripIndices; unsigned int numSeparateStrips = 0; if(bListsOnly) { //if we're outputting only lists, we're done *numGroups = 1; (*primGroups) = new PrimitiveGroup[*numGroups]; PrimitiveGroup* primGroupArray = *primGroups; //count the total number of indices unsigned int numIndices = 0; for(i = 0; i < tempStrips.size(); i++) { numIndices += tempStrips[i]->m_faces.size() * 3; } //add in the list numIndices += tempFaces.size() * 3; primGroupArray[0].type = PT_LIST; primGroupArray[0].numIndices = numIndices; primGroupArray[0].indices = new unsigned short[numIndices]; //do strips unsigned int indexCtr = 0; for(i = 0; i < tempStrips.size(); i++) { for(int j = 0; j < tempStrips[i]->m_faces.size(); j++) { //degenerates are of no use with lists if(!NvStripifier::IsDegenerate(tempStrips[i]->m_faces[j])) { primGroupArray[0].indices[indexCtr++] = tempStrips[i]->m_faces[j]->m_v0; primGroupArray[0].indices[indexCtr++] = tempStrips[i]->m_faces[j]->m_v1; primGroupArray[0].indices[indexCtr++] = tempStrips[i]->m_faces[j]->m_v2; } else { //we've removed a tri, reduce the number of indices primGroupArray[0].numIndices -= 3; } } } //do lists for(i = 0; i < tempFaces.size(); i++) { primGroupArray[0].indices[indexCtr++] = tempFaces[i]->m_v0; primGroupArray[0].indices[indexCtr++] = tempFaces[i]->m_v1; primGroupArray[0].indices[indexCtr++] = tempFaces[i]->m_v2; } } else { stripifier.CreateStrips(tempStrips, stripIndices, bStitchStrips, numSeparateStrips, bRestart, restartVal); //if we're stitching strips together, we better get back only one strip from CreateStrips() assert( (bStitchStrips && (numSeparateStrips == 1)) || !bStitchStrips); //convert to output format *numGroups = numSeparateStrips; //for the strips if(tempFaces.size() != 0) (*numGroups)++; //we've got a list as well, increment (*primGroups) = new PrimitiveGroup[*numGroups]; PrimitiveGroup* primGroupArray = *primGroups; //first, the strips int startingLoc = 0; for(int stripCtr = 0; stripCtr < numSeparateStrips; stripCtr++) { int stripLength = 0; if(!bStitchStrips) { int i; //if we've got multiple strips, we need to figure out the correct length for(i = startingLoc; i < stripIndices.size(); i++) { if(stripIndices[i] == -1) break; } stripLength = i - startingLoc; } else stripLength = stripIndices.size(); primGroupArray[stripCtr].type = PT_STRIP; primGroupArray[stripCtr].indices = new unsigned short[stripLength]; primGroupArray[stripCtr].numIndices = stripLength; int indexCtr = 0; for(int i = startingLoc; i < stripLength + startingLoc; i++) primGroupArray[stripCtr].indices[indexCtr++] = stripIndices[i]; //we add 1 to account for the -1 separating strips //this doesn't break the stitched case since we'll exit the loop startingLoc += stripLength + 1; } //next, the list if(tempFaces.size() != 0) { int faceGroupLoc = (*numGroups) - 1; //the face group is the last one primGroupArray[faceGroupLoc].type = PT_LIST; primGroupArray[faceGroupLoc].indices = new unsigned short[tempFaces.size() * 3]; primGroupArray[faceGroupLoc].numIndices = tempFaces.size() * 3; int indexCtr = 0; for(int i = 0; i < tempFaces.size(); i++) { primGroupArray[faceGroupLoc].indices[indexCtr++] = tempFaces[i]->m_v0; primGroupArray[faceGroupLoc].indices[indexCtr++] = tempFaces[i]->m_v1; primGroupArray[faceGroupLoc].indices[indexCtr++] = tempFaces[i]->m_v2; } } } //validate generated data against input if (validateEnabled) { const int NUMBINS = 100; std::vector<NvFaceInfo> in_bins[NUMBINS]; //hash input indices on first index for (i = 0; i < in_numIndices; i += 3) { NvFaceInfo faceInfo(in_indices[i], in_indices[i + 1], in_indices[i + 2]); in_bins[in_indices[i] % NUMBINS].push_back(faceInfo); } for (i = 0; i < *numGroups; ++i) { switch ((*primGroups)[i].type) { case PT_LIST: { for (int j = 0; j < (*primGroups)[i].numIndices; j += 3) { unsigned short v0 = (*primGroups)[i].indices[j]; unsigned short v1 = (*primGroups)[i].indices[j + 1]; unsigned short v2 = (*primGroups)[i].indices[j + 2]; //ignore degenerates if (NvStripifier::IsDegenerate(v0, v1, v2)) continue; if (!TestTriangle(v0, v1, v2, in_bins, NUMBINS)) { Cleanup(tempStrips, tempFaces); return false; } } break; } case PT_STRIP: { //int brokenCtr = 0; bool flip = false; for (int j = 2; j < (*primGroups)[i].numIndices; ++j) { unsigned short v0 = (*primGroups)[i].indices[j - 2]; unsigned short v1 = (*primGroups)[i].indices[j - 1]; unsigned short v2 = (*primGroups)[i].indices[j]; if (flip) { //swap v1 and v2 unsigned short swap = v1; v1 = v2; v2 = swap; } //ignore degenerates if (NvStripifier::IsDegenerate(v0, v1, v2)) { flip = !flip; continue; } if (!TestTriangle(v0, v1, v2, in_bins, NUMBINS)) { Cleanup(tempStrips, tempFaces); return false; } flip = !flip; } break; } case PT_FAN: default: break; } } } //clean up everything Cleanup(tempStrips, tempFaces); return true; }
//////////////////////////////////////////////////////////////////////////////////////// // GenerateStrips() // // in_indices: input index list, the indices you would use to render // in_numIndices: number of entries in in_indices // primGroups: array of optimized/stripified PrimitiveGroups // numGroups: number of groups returned // // Be sure to call delete[] on the returned primGroups to avoid leaking mem // void GenerateStrips(const U16* in_indices, const U32 in_numIndices, PrimitiveGroup** primGroups, U16* numGroups) { //put data in format that the stripifier likes WordVec tempIndices; tempIndices.resize(in_numIndices); U16 maxIndex = 0; U32 i; for(i = 0; i < in_numIndices; i++) { tempIndices[i] = in_indices[i]; if(in_indices[i] > maxIndex) maxIndex = in_indices[i]; } NvStripInfoVec tempStrips; NvFaceInfoVec tempFaces; NvStripifier stripifier; //do actual stripification stripifier.Stripify(tempIndices, cacheSize, minStripSize, maxIndex, tempStrips, tempFaces); //stitch strips together IntVec stripIndices; U32 numSeparateStrips = 0; if(bListsOnly) { //if we're outputting only lists, we're done *numGroups = 1; (*primGroups) = new PrimitiveGroup[*numGroups]; PrimitiveGroup* primGroupArray = *primGroups; //count the total number of indices U32 numIndices = 0; U32 i; for(i = 0; i < tempStrips.size(); i++) { numIndices += tempStrips[i]->m_faces.size() * 3; } //add in the list numIndices += tempFaces.size() * 3; primGroupArray[0].type = PT_LIST; primGroupArray[0].numIndices = numIndices; primGroupArray[0].indices = new U16[numIndices]; //do strips U32 indexCtr = 0; for(U32 k = 0; k < tempStrips.size(); k++) { for(U32 j = 0; j < tempStrips[i]->m_faces.size(); j++) { //degenerates are of no use with lists if(!NvStripifier::IsDegenerate(tempStrips[i]->m_faces[j])) { primGroupArray[0].indices[indexCtr++] = tempStrips[k]->m_faces[j]->m_v0; primGroupArray[0].indices[indexCtr++] = tempStrips[k]->m_faces[j]->m_v1; primGroupArray[0].indices[indexCtr++] = tempStrips[k]->m_faces[j]->m_v2; } else { //we've removed a tri, reduce the number of indices primGroupArray[0].numIndices -= 3; } } } //do lists for(i = 0; i < tempFaces.size(); i++) { primGroupArray[0].indices[indexCtr++] = tempFaces[i]->m_v0; primGroupArray[0].indices[indexCtr++] = tempFaces[i]->m_v1; primGroupArray[0].indices[indexCtr++] = tempFaces[i]->m_v2; } } else { stripifier.CreateStrips(tempStrips, stripIndices, bStitchStrips, numSeparateStrips); //if we're stitching strips together, we better get back only one strip from CreateStrips() assert( (bStitchStrips && (numSeparateStrips == 1)) || !bStitchStrips); //convert to output format *numGroups = numSeparateStrips; //for the strips if(tempFaces.size() != 0) (*numGroups)++; //we've got a list as well, increment (*primGroups) = new PrimitiveGroup[*numGroups]; PrimitiveGroup* primGroupArray = *primGroups; //first, the strips S32 startingLoc = 0; for(U32 stripCtr = 0; stripCtr < numSeparateStrips; stripCtr++) { S32 stripLength = 0; if(!bStitchStrips) { //if we've got multiple strips, we need to figure out the correct length U32 i; for(i = startingLoc; i < stripIndices.size(); i++) { if(stripIndices[i] == -1) break; } stripLength = i - startingLoc; } else stripLength = stripIndices.size(); primGroupArray[stripCtr].type = PT_STRIP; primGroupArray[stripCtr].indices = new U16[stripLength]; primGroupArray[stripCtr].numIndices = stripLength; S32 indexCtr = 0; for(S32 i = startingLoc; i < stripLength + startingLoc; i++) primGroupArray[stripCtr].indices[indexCtr++] = stripIndices[i]; //we add 1 to account for the -1 separating strips //this doesn't break the stitched case since we'll exit the loop startingLoc += stripLength + 1; } //next, the list if(tempFaces.size() != 0) { S32 faceGroupLoc = (*numGroups) - 1; //the face group is the last one primGroupArray[faceGroupLoc].type = PT_LIST; primGroupArray[faceGroupLoc].indices = new U16[tempFaces.size() * 3]; primGroupArray[faceGroupLoc].numIndices = tempFaces.size() * 3; S32 indexCtr = 0; for(U32 i = 0; i < tempFaces.size(); i++) { primGroupArray[faceGroupLoc].indices[indexCtr++] = tempFaces[i]->m_v0; primGroupArray[faceGroupLoc].indices[indexCtr++] = tempFaces[i]->m_v1; primGroupArray[faceGroupLoc].indices[indexCtr++] = tempFaces[i]->m_v2; } } } //clean up everything //delete strips for(i = 0; i < tempStrips.size(); i++) { for(U32 j = 0; j < tempStrips[i]->m_faces.size(); j++) { delete tempStrips[i]->m_faces[j]; tempStrips[i]->m_faces[j] = NULL; } delete tempStrips[i]; tempStrips[i] = NULL; } //delete faces for(i = 0; i < tempFaces.size(); i++) { delete tempFaces[i]; tempFaces[i] = NULL; } }