diff options
Diffstat (limited to 'utils/nvtristriplib/nvtristrip.cpp')
| -rw-r--r-- | utils/nvtristriplib/nvtristrip.cpp | 315 |
1 files changed, 315 insertions, 0 deletions
diff --git a/utils/nvtristriplib/nvtristrip.cpp b/utils/nvtristriplib/nvtristrip.cpp new file mode 100644 index 0000000..72df833 --- /dev/null +++ b/utils/nvtristriplib/nvtristrip.cpp @@ -0,0 +1,315 @@ + +#pragma warning( disable : 4786 4018 4530 ) + +#include "NvTriStripObjects.h" +#include "NvTriStrip.h" +#include <assert.h> + +static inline unsigned short AsUShort( int nValue ) +{ + assert( nValue >= 0 && nValue <= 65535 ); + return (unsigned short)( nValue ); +} + +static inline unsigned short AsUShort( unsigned int nValue ) +{ + assert( nValue <= 65535 ); + return (unsigned short)( nValue ); +} + +//////////////////////////////////////////////////////////////////////////////////////// +//private data +static unsigned int cacheSize = CACHESIZE_GEFORCE1_2; +static bool bStitchStrips = true; +static unsigned int minStripSize = 0; +static bool bListsOnly = false; + +//////////////////////////////////////////////////////////////////////////////////////// +// SetListsOnly() +// +// If set to true, will return an optimized list, with no strips at all. +// +// Default value: false +// +void SetListsOnly(const bool _bListsOnly) +{ + bListsOnly = _bListsOnly; +} + +//////////////////////////////////////////////////////////////////////////////////////// +// SetCacheSize() +// +// Sets the cache size which the stripfier uses to optimize the data. +// Controls the length of the generated individual strips. +// This is the "actual" cache size, so 24 for GeForce3 and 16 for GeForce1/2 +// You may want to play around with this number to tweak performance. +// +// Default value: 16 +// +void SetCacheSize(const unsigned int _cacheSize) +{ + cacheSize = _cacheSize; +} + + +//////////////////////////////////////////////////////////////////////////////////////// +// SetStitchStrips() +// +// bool to indicate whether to stitch together strips into one huge strip or not. +// If set to true, you'll get back one huge strip stitched together using degenerate +// triangles. +// If set to false, you'll get back a large number of separate strips. +// +// Default value: true +// +void SetStitchStrips(const bool _bStitchStrips) +{ + bStitchStrips = _bStitchStrips; +} + + +//////////////////////////////////////////////////////////////////////////////////////// +// SetMinStripSize() +// +// Sets the minimum acceptable size for a strip, in triangles. +// All strips generated which are shorter than this will be thrown into one big, separate list. +// +// Default value: 0 +// +void SetMinStripSize(const unsigned int _minStripSize) +{ + minStripSize = _minStripSize; +} + +//////////////////////////////////////////////////////////////////////////////////////// +// 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 unsigned short* in_indices, const unsigned int in_numIndices, + PrimitiveGroup** primGroups, unsigned short* numGroups) +{ + //put data in format that the stripifier likes + WordVec tempIndices; + tempIndices.resize(in_numIndices); + unsigned short maxIndex = 0; + for(int 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; + 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(int i = 0; i < tempStrips.size(); i++) + { + numIndices += (unsigned int)( tempStrips[i]->m_faces.size() * 3 ); + } + + //add in the list + numIndices += (unsigned int)( 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(int 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++] = AsUShort( tempStrips[i]->m_faces[j]->m_v0 ); + primGroupArray[0].indices[indexCtr++] = AsUShort( tempStrips[i]->m_faces[j]->m_v1 ); + primGroupArray[0].indices[indexCtr++] = AsUShort( 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(int i = 0; i < tempFaces.size(); i++) + { + primGroupArray[0].indices[indexCtr++] = AsUShort( tempFaces[i]->m_v0 ); + primGroupArray[0].indices[indexCtr++] = AsUShort( tempFaces[i]->m_v1 ); + primGroupArray[0].indices[indexCtr++] = AsUShort( 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 = AsUShort( 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) + { + //if we've got multiple strips, we need to figure out the correct length + int i = startingLoc; + for(i; i < stripIndices.size(); i++) + { + if(stripIndices[i] == -1) + break; + } + + stripLength = i - startingLoc; + } + else + { + stripLength = (int)( 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++] = AsUShort( 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 = (unsigned int)( tempFaces.size() * 3 ); + int indexCtr = 0; + for(int i = 0; i < tempFaces.size(); i++) + { + primGroupArray[faceGroupLoc].indices[indexCtr++] = AsUShort( tempFaces[i]->m_v0 ); + primGroupArray[faceGroupLoc].indices[indexCtr++] = AsUShort( tempFaces[i]->m_v1 ); + primGroupArray[faceGroupLoc].indices[indexCtr++] = AsUShort( tempFaces[i]->m_v2 ); + } + } + } + + //clean up everything + + //delete strips + for(int i = 0; i < tempStrips.size(); i++) + { + for(int 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(int i = 0; i < tempFaces.size(); i++) + { + delete tempFaces[i]; + tempFaces[i] = NULL; + } +} + + +//////////////////////////////////////////////////////////////////////////////////////// +// RemapIndices() +// +// Function to remap your indices to improve spatial locality in your vertex buffer. +// +// in_primGroups: array of PrimitiveGroups you want remapped +// numGroups: number of entries in in_primGroups +// numVerts: number of vertices in your vertex buffer, also can be thought of as the range +// of acceptable values for indices in your primitive groups. +// remappedGroups: array of remapped PrimitiveGroups +// +// Note that, according to the remapping handed back to you, you must reorder your +// vertex buffer. +// +void RemapIndices(const PrimitiveGroup* in_primGroups, const unsigned short numGroups, + const unsigned short numVerts, PrimitiveGroup** remappedGroups) +{ + (*remappedGroups) = new PrimitiveGroup[numGroups]; + + //caches oldIndex --> newIndex conversion + int *indexCache; + indexCache = new int[numVerts]; + memset(indexCache, -1, sizeof(int)*numVerts); + + //loop over primitive groups + unsigned int indexCtr = 0; + for(int i = 0; i < numGroups; i++) + { + unsigned int numIndices = in_primGroups[i].numIndices; + + //init remapped group + (*remappedGroups)[i].type = in_primGroups[i].type; + (*remappedGroups)[i].numIndices = numIndices; + (*remappedGroups)[i].indices = new unsigned short[numIndices]; + + for(int j = 0; j < numIndices; j++) + { + int cachedIndex = indexCache[in_primGroups[i].indices[j]]; + if(cachedIndex == -1) //we haven't seen this index before + { + //point to "last" vertex in VB + (*remappedGroups)[i].indices[j] = AsUShort( indexCtr ); + + //add to index cache, increment + indexCache[in_primGroups[i].indices[j]] = indexCtr++; + } + else + { + //we've seen this index before + (*remappedGroups)[i].indices[j] = AsUShort( cachedIndex ); + } + } + } + + delete[] indexCache; +}
\ No newline at end of file |