From ecb028869235460d65020fc6405a295ae555c8a8 Mon Sep 17 00:00:00 2001 From: Tazpn <tazpn@users.sourceforge.net> Date: Mon, 18 Sep 2006 03:20:28 +0000 Subject: [PATCH] 0.2.5 ----- o Exporter - Rewrote animation export dialogs and procedures to write files similar to Civilation exporter. - Removed seperate *.kf and merged with *.nif like Civ4 - Fixed issues with NiStencilProperty (via niflib) for Morrowind - Add option to optionally export accum nodes - Add options for exporting skin partition in different ways - Expose the Auto detect parameter to allow game to be saved o Importer - Add option to ignore root - Expose the Time Tag and Key Note params on nif dialog - Expose the Auto detect parameter to allow game to be saved --- NifExport/NvTriStrip/NvTriStrip.cpp | 498 ----- NifExport/NvTriStrip/NvTriStrip.h | 143 -- NifExport/NvTriStrip/NvTriStripObjects.cpp | 1769 ----------------- NifExport/NvTriStrip/NvTriStripObjects.h | 243 --- NifExport/NvTriStrip/VertexCache.cpp | 88 - NifExport/NvTriStrip/VertexCache.h | 27 - NifExport/TriStripper/connectivity_graph.cpp | 132 -- .../TriStripper/detail/cache_simulator.h | 154 -- .../TriStripper/detail/connectivity_graph.h | 36 - NifExport/TriStripper/detail/graph_array.h | 460 ----- NifExport/TriStripper/detail/heap_array.h | 297 --- NifExport/TriStripper/detail/policy.h | 66 - NifExport/TriStripper/detail/types.h | 101 - NifExport/TriStripper/policy.cpp | 63 - NifExport/TriStripper/tri_stripper.cpp | 554 ------ 15 files changed, 4631 deletions(-) delete mode 100755 NifExport/NvTriStrip/NvTriStrip.cpp delete mode 100755 NifExport/NvTriStrip/NvTriStrip.h delete mode 100755 NifExport/NvTriStrip/NvTriStripObjects.cpp delete mode 100755 NifExport/NvTriStrip/NvTriStripObjects.h delete mode 100755 NifExport/NvTriStrip/VertexCache.cpp delete mode 100755 NifExport/NvTriStrip/VertexCache.h delete mode 100644 NifExport/TriStripper/connectivity_graph.cpp delete mode 100644 NifExport/TriStripper/detail/cache_simulator.h delete mode 100644 NifExport/TriStripper/detail/connectivity_graph.h delete mode 100644 NifExport/TriStripper/detail/graph_array.h delete mode 100644 NifExport/TriStripper/detail/heap_array.h delete mode 100644 NifExport/TriStripper/detail/policy.h delete mode 100644 NifExport/TriStripper/detail/types.h delete mode 100644 NifExport/TriStripper/policy.cpp delete mode 100755 NifExport/TriStripper/tri_stripper.cpp diff --git a/NifExport/NvTriStrip/NvTriStrip.cpp b/NifExport/NvTriStrip/NvTriStrip.cpp deleted file mode 100755 index fb942c2..0000000 --- a/NifExport/NvTriStrip/NvTriStrip.cpp +++ /dev/null @@ -1,498 +0,0 @@ - -#include "NvTriStripObjects.h" -#include "NvTriStrip.h" - -//////////////////////////////////////////////////////////////////////////////////////// -//private data -static unsigned int cacheSize = CACHESIZE_GEFORCE1_2; -static bool bStitchStrips = true; -static unsigned int minStripSize = 0; -static bool bListsOnly = false; -static unsigned int restartVal = 0; -static bool bRestart = false; - -void EnableRestart(const unsigned int _restartVal) -{ - bRestart = true; - restartVal = _restartVal; -} - -void DisableRestart() -{ - bRestart = 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; -} - - -//////////////////////////////////////////////////////////////////////////////////////// -//Cleanup strips / faces, used by generatestrips -void Cleanup(NvStripInfoVec& tempStrips, NvFaceInfoVec& tempFaces) -{ - //delete strips - for(size_t i = 0; i < tempStrips.size(); i++) - { - for(size_t j = 0; j < tempStrips[i]->m_faces.size(); j++) - { - delete tempStrips[i]->m_faces[j]; - tempStrips[i]->m_faces[j] = NULL; - } - tempStrips[i]->m_faces.resize(0); - delete tempStrips[i]; - tempStrips[i] = NULL; - } - - //delete faces - for(size_t i = 0; i < tempFaces.size(); i++) - { - delete tempFaces[i]; - tempFaces[i] = NULL; - } -} - - -//////////////////////////////////////////////////////////////////////////////////////// -//SameTriangle() -// -//Returns true if the two triangles defined by firstTri and secondTri are the same -// The "same" is defined in this case as having the same indices with the same winding order -// -bool SameTriangle(unsigned short firstTri0, unsigned short firstTri1, unsigned short firstTri2, - unsigned short secondTri0, unsigned short secondTri1, unsigned short secondTri2) -{ - bool isSame = false; - - if (firstTri0 == secondTri0) - { - if (firstTri1 == secondTri1) - { - if (firstTri2 == secondTri2) - isSame = true; - } - } - else if (firstTri0 == secondTri1) - { - if (firstTri1 == secondTri2) - { - if (firstTri2 == secondTri0) - isSame = true; - } - } - else if (firstTri0 == secondTri2) - { - if (firstTri1 == secondTri0) - { - if (firstTri2 == secondTri1) - isSame = true; - } - } - - return isSame; -} - - -bool TestTriangle(const unsigned short v0, const unsigned short v1, const unsigned short v2, const std::vector<NvFaceInfo>* in_bins, const int NUMBINS) -{ - //hash this triangle - bool isLegit = false; - int ctr = v0 % NUMBINS; - for (size_t k = 0; k < in_bins[ctr].size(); ++k) - { - //check triangles in this bin - if (SameTriangle(in_bins[ctr][k].m_v0, in_bins[ctr][k].m_v1, in_bins[ctr][k].m_v2, - v0, v1, v2)) - { - isLegit = true; - break; - } - } - if (!isLegit) - { - ctr = v1 % NUMBINS; - for (size_t k = 0; k < in_bins[ctr].size(); ++k) - { - //check triangles in this bin - if (SameTriangle(in_bins[ctr][k].m_v0, in_bins[ctr][k].m_v1, in_bins[ctr][k].m_v2, - v0, v1, v2)) - { - isLegit = true; - break; - } - } - - if (!isLegit) - { - ctr = v2 % NUMBINS; - for (size_t k = 0; k < in_bins[ctr].size(); ++k) - { - //check triangles in this bin - if (SameTriangle(in_bins[ctr][k].m_v0, in_bins[ctr][k].m_v1, in_bins[ctr][k].m_v2, - v0, v1, v2)) - { - isLegit = true; - break; - } - } - - } - } - - return isLegit; -} - - -//////////////////////////////////////////////////////////////////////////////////////// -// 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) -{ - //put data in format that the stripifier likes - WordVec tempIndices; - tempIndices.resize(in_numIndices); - unsigned short maxIndex = 0; - unsigned short minIndex = 0xFFFF; - for(size_t 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(size_t 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(size_t i = 0; i < tempStrips.size(); i++) - { - for(size_t 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(size_t 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(size_t stripCtr = 0; stripCtr < numSeparateStrips; stripCtr++) - { - int stripLength = 0; - - if(!bStitchStrips) - { - //if we've got multiple strips, we need to figure out the correct length - size_t 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 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(size_t 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 (size_t 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 (int i = 0; i < *numGroups; ++i) - { - switch ((*primGroups)[i].type) - { - case PT_LIST: - { - for (size_t 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 (size_t 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; -} - - -//////////////////////////////////////////////////////////////////////////////////////// -// 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(size_t 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] = indexCtr; - - //add to index cache, increment - indexCache[in_primGroups[i].indices[j]] = indexCtr++; - } - else - { - //we've seen this index before - (*remappedGroups)[i].indices[j] = cachedIndex; - } - } - } - - delete[] indexCache; -} \ No newline at end of file diff --git a/NifExport/NvTriStrip/NvTriStrip.h b/NifExport/NvTriStrip/NvTriStrip.h deleted file mode 100755 index 3e17c47..0000000 --- a/NifExport/NvTriStrip/NvTriStrip.h +++ /dev/null @@ -1,143 +0,0 @@ -#ifndef NVTRISTRIP_H -#define NVTRISTRIP_H - -#ifndef NULL -#define NULL 0 -#endif - -//////////////////////////////////////////////////////////////////////////////////////// -// Public interface for stripifier -//////////////////////////////////////////////////////////////////////////////////////// - -//GeForce1 and 2 cache size -#define CACHESIZE_GEFORCE1_2 16 - -//GeForce3 cache size -#define CACHESIZE_GEFORCE3 24 - -enum PrimType -{ - PT_LIST, - PT_STRIP, - PT_FAN -}; - -struct PrimitiveGroup -{ - PrimType type; - unsigned int numIndices; - unsigned short* indices; - -//////////////////////////////////////////////////////////////////////////////////////// - - PrimitiveGroup() : type(PT_STRIP), numIndices(0), indices(NULL) {} - ~PrimitiveGroup() - { - if(indices) - delete[] indices; - indices = NULL; - } -}; - - -//////////////////////////////////////////////////////////////////////////////////////// -// EnableRestart() -// -// For GPUs that support primitive restart, this sets a value as the restart index -// -// Restart is meaningless if strips are not being stitched together, so enabling restart -// makes NvTriStrip forcing stitching. So, you'll get back one strip. -// -// Default value: disabled -// -void EnableRestart(const unsigned int restartVal); - -//////////////////////////////////////////////////////////////////////////////////////// -// DisableRestart() -// -// For GPUs that support primitive restart, this disables using primitive restart -// -void DisableRestart(); - - -//////////////////////////////////////////////////////////////////////////////////////// -// 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); - - -//////////////////////////////////////////////////////////////////////////////////////// -// 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); - - -//////////////////////////////////////////////////////////////////////////////////////// -// 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 minSize); - - -//////////////////////////////////////////////////////////////////////////////////////// -// SetListsOnly() -// -// If set to true, will return an optimized list, with no strips at all. -// -// Default value: false -// -void SetListsOnly(const bool bListsOnly); - - -//////////////////////////////////////////////////////////////////////////////////////// -// 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 = false); - - -//////////////////////////////////////////////////////////////////////////////////////// -// 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. -// -// Credit goes to the MS Xbox crew for the idea for this interface. -// -void RemapIndices(const PrimitiveGroup* in_primGroups, const unsigned short numGroups, - const unsigned short numVerts, PrimitiveGroup** remappedGroups); - -#endif \ No newline at end of file diff --git a/NifExport/NvTriStrip/NvTriStripObjects.cpp b/NifExport/NvTriStrip/NvTriStripObjects.cpp deleted file mode 100755 index 474d530..0000000 --- a/NifExport/NvTriStrip/NvTriStripObjects.cpp +++ /dev/null @@ -1,1769 +0,0 @@ - -#pragma warning( disable : 4786 ) - -#include <assert.h> -#include <set> -#include "NvTriStripObjects.h" -#include "VertexCache.h" - -#define CACHE_INEFFICIENCY 6 - -NvStripifier::NvStripifier() -{ - -} - -NvStripifier::~NvStripifier() -{ - -} - - -/////////////////////////////////////////////////////////////////////////////////////////// -// FindEdgeInfo() -// -// find the edge info for these two indices -// -NvEdgeInfo * NvStripifier::FindEdgeInfo(NvEdgeInfoVec &edgeInfos, int v0, int v1){ - - // we can get to it through either array - // because the edge infos have a v0 and v1 - // and there is no order except how it was - // first created. - NvEdgeInfo *infoIter = edgeInfos[v0]; - while (infoIter != NULL){ - if (infoIter->m_v0 == v0){ - if (infoIter->m_v1 == v1) - return infoIter; - else - infoIter = infoIter->m_nextV0; - } - else { - assert(infoIter->m_v1 == v0); - if (infoIter->m_v0 == v1) - return infoIter; - else - infoIter = infoIter->m_nextV1; - } - } - return NULL; -} - - -/////////////////////////////////////////////////////////////////////////////////////////// -// 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; - } - - assert(edgeInfo != NULL); - return (edgeInfo->m_face0 == faceInfo ? edgeInfo->m_face1 : edgeInfo->m_face0); -} - - -bool NvStripifier::AlreadyExists(NvFaceInfo* faceInfo, NvFaceInfoVec& faceInfos) -{ - for(size_t i = 0; i < faceInfos.size(); ++i) - { - if( (faceInfos[i]->m_v0 == faceInfo->m_v0) && - (faceInfos[i]->m_v1 == faceInfo->m_v1) && - (faceInfos[i]->m_v2 == faceInfo->m_v2) ) - return true; - } - - return false; -} - -/////////////////////////////////////////////////////////////////////////////////////////// -// 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 (int 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); - } - - } -} - - -/////////////////////////////////////////////////////////////////////////////////////////// -// FindStartPoint() -// -// Finds a good starting point, namely one which has only one neighbor -// -int NvStripifier::FindStartPoint(NvFaceInfoVec &faceInfos, NvEdgeInfoVec &edgeInfos) -{ - int bestCtr = -1; - int bestIndex = -1; - - for(size_t i = 0; i < faceInfos.size(); i++) - { - int ctr = 0; - - if(FindOtherFace(edgeInfos, faceInfos[i]->m_v0, faceInfos[i]->m_v1, faceInfos[i]) == NULL) - ctr++; - if(FindOtherFace(edgeInfos, faceInfos[i]->m_v1, faceInfos[i]->m_v2, faceInfos[i]) == NULL) - ctr++; - if(FindOtherFace(edgeInfos, faceInfos[i]->m_v2, faceInfos[i]->m_v0, faceInfos[i]) == NULL) - ctr++; - if(ctr > bestCtr) - { - bestCtr = ctr; - bestIndex = i; - //return i; - } - } - //return -1; - - if(bestCtr == 0) - return -1; - else - return bestIndex; -} - - -/////////////////////////////////////////////////////////////////////////////////////////// -// FindGoodResetPoint() -// -// A good reset point is one near other commited areas so that -// we know that when we've made the longest strips its because -// we're stripifying in the same general orientation. -// -NvFaceInfo* NvStripifier::FindGoodResetPoint(NvFaceInfoVec &faceInfos, NvEdgeInfoVec &edgeInfos){ - // we hop into different areas of the mesh to try to get - // other large open spans done. Areas of small strips can - // just be left to triangle lists added at the end. - NvFaceInfo *result = NULL; - - if(result == NULL) - { - int numFaces = faceInfos.size(); - if (numFaces == 0) - return NULL; - - int startPoint; - if(bFirstTimeResetPoint) - { - //first time, find a face with few neighbors (look for an edge of the mesh) - startPoint = FindStartPoint(faceInfos, edgeInfos); - bFirstTimeResetPoint = false; - } - else - startPoint = (int)(((float) numFaces - 1) * meshJump); - - if(startPoint == -1) - { - startPoint = (int)(((float) numFaces - 1) * meshJump); - - //meshJump += 0.1f; - //if (meshJump > 1.0f) - // meshJump = .05f; - } - - int i = startPoint; - do { - - // if this guy isn't visited, try him - if (faceInfos[i]->m_stripId < 0){ - result = faceInfos[i]; - break; - } - - // update the index and clamp to 0-(numFaces-1) - if (++i >= numFaces) - i = 0; - - } while (i != startPoint); - - // update the meshJump - meshJump += 0.1f; - if (meshJump > 1.0f) - meshJump = .05f; - } - - // return the best face we found - return result; -} - - -/////////////////////////////////////////////////////////////////////////////////////////// -// GetUniqueVertexInB() -// -// Returns the vertex unique to faceB -// -int NvStripifier::GetUniqueVertexInB(NvFaceInfo *faceA, NvFaceInfo *faceB){ - - int facev0 = faceB->m_v0; - if (facev0 != faceA->m_v0 && - facev0 != faceA->m_v1 && - facev0 != faceA->m_v2) - return facev0; - - int facev1 = faceB->m_v1; - if (facev1 != faceA->m_v0 && - facev1 != faceA->m_v1 && - facev1 != faceA->m_v2) - return facev1; - - int facev2 = faceB->m_v2; - if (facev2 != faceA->m_v0 && - facev2 != faceA->m_v1 && - facev2 != faceA->m_v2) - return facev2; - - // nothing is different - return -1; -} - - -/////////////////////////////////////////////////////////////////////////////////////////// -// GetSharedVertices() -// -// Returns the (at most) two vertices shared between the two faces -// -void NvStripifier::GetSharedVertices(NvFaceInfo *faceA, NvFaceInfo *faceB, int* vertex0, int* vertex1) -{ - *vertex0 = -1; - *vertex1 = -1; - - int facev0 = faceB->m_v0; - if (facev0 == faceA->m_v0 || - facev0 == faceA->m_v1 || - facev0 == faceA->m_v2) - { - if(*vertex0 == -1) - *vertex0 = facev0; - else - { - *vertex1 = facev0; - return; - } - } - - int facev1 = faceB->m_v1; - if (facev1 == faceA->m_v0 || - facev1 == faceA->m_v1 || - facev1 == faceA->m_v2) - { - if(*vertex0 == -1) - *vertex0 = facev1; - else - { - *vertex1 = facev1; - return; - } - } - - int facev2 = faceB->m_v2; - if (facev2 == faceA->m_v0 || - facev2 == faceA->m_v1 || - facev2 == faceA->m_v2) - { - if(*vertex0 == -1) - *vertex0 = facev2; - else - { - *vertex1 = facev2; - return; - } - } - -} - - -/////////////////////////////////////////////////////////////////////////////////////////// -// GetNextIndex() -// -// Returns vertex of the input face which is "next" in the input index list -// -inline int NvStripifier::GetNextIndex(const WordVec &indices, NvFaceInfo *face){ - - int numIndices = indices.size(); - assert(numIndices >= 2); - - int v0 = indices[numIndices-2]; - int v1 = indices[numIndices-1]; - - int fv0 = face->m_v0; - int fv1 = face->m_v1; - int fv2 = face->m_v2; - - if (fv0 != v0 && fv0 != v1){ - if ((fv1 != v0 && fv1 != v1) || (fv2 != v0 && fv2 != v1)){ - printf("GetNextIndex: Triangle doesn't have all of its vertices\n"); - printf("GetNextIndex: Duplicate triangle probably got us derailed\n"); - } - return fv0; - } - if (fv1 != v0 && fv1 != v1){ - if ((fv0 != v0 && fv0 != v1) || (fv2 != v0 && fv2 != v1)){ - printf("GetNextIndex: Triangle doesn't have all of its vertices\n"); - printf("GetNextIndex: Duplicate triangle probably got us derailed\n"); - } - return fv1; - } - if (fv2 != v0 && fv2 != v1){ - if ((fv0 != v0 && fv0 != v1) || (fv1 != v0 && fv1 != v1)){ - printf("GetNextIndex: Triangle doesn't have all of its vertices\n"); - printf("GetNextIndex: Duplicate triangle probably got us derailed\n"); - } - return fv2; - } - - // shouldn't get here, but let's try and fail gracefully - if( (fv0 == fv1) || (fv0 == fv2) ) - return fv0; - else if( (fv1 == fv0) || (fv1 == fv2) ) - return fv1; - else if( (fv2 == fv0) || (fv2 == fv1) ) - return fv2; - else - return -1; -} - - -/////////////////////////////////////////////////////////////////////////////////////////// -// IsMarked() -// -// If either the faceInfo has a real strip index because it is -// already assign to a committed strip OR it is assigned in an -// experiment and the experiment index is the one we are building -// for, then it is marked and unavailable -inline bool NvStripInfo::IsMarked(NvFaceInfo *faceInfo){ - return (faceInfo->m_stripId >= 0) || (IsExperiment() && faceInfo->m_experimentId == m_experimentId); -} - - -/////////////////////////////////////////////////////////////////////////////////////////// -// MarkTriangle() -// -// Marks the face with the current strip ID -// -inline void NvStripInfo::MarkTriangle(NvFaceInfo *faceInfo){ - assert(!IsMarked(faceInfo)); - if (IsExperiment()){ - faceInfo->m_experimentId = m_experimentId; - faceInfo->m_testStripId = m_stripId; - } - else{ - assert(faceInfo->m_stripId == -1); - faceInfo->m_experimentId = -1; - faceInfo->m_stripId = m_stripId; - } -} - - -bool NvStripInfo::Unique(NvFaceInfoVec& faceVec, NvFaceInfo* face) -{ - bool bv0, bv1, bv2; //bools to indicate whether a vertex is in the faceVec or not - bv0 = bv1 = bv2 = false; - - for(size_t i = 0; i < faceVec.size(); i++) - { - if(!bv0) - { - if( (faceVec[i]->m_v0 == face->m_v0) || - (faceVec[i]->m_v1 == face->m_v0) || - (faceVec[i]->m_v2 == face->m_v0) ) - bv0 = true; - } - - if(!bv1) - { - if( (faceVec[i]->m_v0 == face->m_v1) || - (faceVec[i]->m_v1 == face->m_v1) || - (faceVec[i]->m_v2 == face->m_v1) ) - bv1 = true; - } - - if(!bv2) - { - if( (faceVec[i]->m_v0 == face->m_v2) || - (faceVec[i]->m_v1 == face->m_v2) || - (faceVec[i]->m_v2 == face->m_v2) ) - bv2 = true; - } - - //the face is not unique, all it's vertices exist in the face vector - if(bv0 && bv1 && bv2) - return false; - } - - //if we get out here, it's unique - return true; -} - - -/////////////////////////////////////////////////////////////////////////////////////////// -// Build() -// -// Builds a strip forward as far as we can go, then builds backwards, and joins the two lists -// -void NvStripInfo::Build(NvEdgeInfoVec &edgeInfos, NvFaceInfoVec &faceInfos) -{ - // used in building the strips forward and backward - WordVec scratchIndices; - - // build forward... start with the initial face - NvFaceInfoVec forwardFaces, backwardFaces; - forwardFaces.push_back(m_startInfo.m_startFace); - - MarkTriangle(m_startInfo.m_startFace); - - int v0 = (m_startInfo.m_toV1 ? m_startInfo.m_startEdge->m_v0 : m_startInfo.m_startEdge->m_v1); - int v1 = (m_startInfo.m_toV1 ? m_startInfo.m_startEdge->m_v1 : m_startInfo.m_startEdge->m_v0); - - // easiest way to get v2 is to use this function which requires the - // other indices to already be in the list. - scratchIndices.push_back(v0); - scratchIndices.push_back(v1); - int v2 = NvStripifier::GetNextIndex(scratchIndices, m_startInfo.m_startFace); - scratchIndices.push_back(v2); - - // - // build the forward list - // - int nv0 = v1; - int nv1 = v2; - - NvFaceInfo *nextFace = NvStripifier::FindOtherFace(edgeInfos, nv0, nv1, m_startInfo.m_startFace); - while (nextFace != NULL && !IsMarked(nextFace)) - { - //check to see if this next face is going to cause us to die soon - int testnv0 = nv1; - int testnv1 = NvStripifier::GetNextIndex(scratchIndices, nextFace); - - NvFaceInfo* nextNextFace = NvStripifier::FindOtherFace(edgeInfos, testnv0, testnv1, nextFace); - - if( (nextNextFace == NULL) || (IsMarked(nextNextFace)) ) - { - //uh, oh, we're following a dead end, try swapping - NvFaceInfo* testNextFace = NvStripifier::FindOtherFace(edgeInfos, nv0, testnv1, nextFace); - - if( ((testNextFace != NULL) && !IsMarked(testNextFace)) ) - { - //we only swap if it buys us something - - //add a "fake" degenerate face - NvFaceInfo* tempFace = new NvFaceInfo(nv0, nv1, nv0, true); - - forwardFaces.push_back(tempFace); - MarkTriangle(tempFace); - - scratchIndices.push_back(nv0); - testnv0 = nv0; - - ++m_numDegenerates; - } - - } - - // add this to the strip - forwardFaces.push_back(nextFace); - - MarkTriangle(nextFace); - - // add the index - //nv0 = nv1; - //nv1 = NvStripifier::GetNextIndex(scratchIndices, nextFace); - scratchIndices.push_back(testnv1); - - // and get the next face - nv0 = testnv0; - nv1 = testnv1; - - nextFace = NvStripifier::FindOtherFace(edgeInfos, nv0, nv1, nextFace); - - } - - // tempAllFaces is going to be forwardFaces + backwardFaces - // it's used for Unique() - NvFaceInfoVec tempAllFaces; - for(size_t i = 0; i < forwardFaces.size(); i++) - tempAllFaces.push_back(forwardFaces[i]); - - // - // reset the indices for building the strip backwards and do so - // - scratchIndices.resize(0); - scratchIndices.push_back(v2); - scratchIndices.push_back(v1); - scratchIndices.push_back(v0); - nv0 = v1; - nv1 = v0; - nextFace = NvStripifier::FindOtherFace(edgeInfos, nv0, nv1, m_startInfo.m_startFace); - while (nextFace != NULL && !IsMarked(nextFace)) - { - //this tests to see if a face is "unique", meaning that its vertices aren't already in the list - // so, strips which "wrap-around" are not allowed - if(!Unique(tempAllFaces, nextFace)) - break; - - //check to see if this next face is going to cause us to die soon - int testnv0 = nv1; - int testnv1 = NvStripifier::GetNextIndex(scratchIndices, nextFace); - - NvFaceInfo* nextNextFace = NvStripifier::FindOtherFace(edgeInfos, testnv0, testnv1, nextFace); - - if( (nextNextFace == NULL) || (IsMarked(nextNextFace)) ) - { - //uh, oh, we're following a dead end, try swapping - NvFaceInfo* testNextFace = NvStripifier::FindOtherFace(edgeInfos, nv0, testnv1, nextFace); - if( ((testNextFace != NULL) && !IsMarked(testNextFace)) ) - { - //we only swap if it buys us something - - //add a "fake" degenerate face - NvFaceInfo* tempFace = new NvFaceInfo(nv0, nv1, nv0, true); - - backwardFaces.push_back(tempFace); - MarkTriangle(tempFace); - scratchIndices.push_back(nv0); - testnv0 = nv0; - - ++m_numDegenerates; - } - - } - - // add this to the strip - backwardFaces.push_back(nextFace); - - //this is just so Unique() will work - tempAllFaces.push_back(nextFace); - - MarkTriangle(nextFace); - - // add the index - //nv0 = nv1; - //nv1 = NvStripifier::GetNextIndex(scratchIndices, nextFace); - scratchIndices.push_back(testnv1); - - // and get the next face - nv0 = testnv0; - nv1 = testnv1; - nextFace = NvStripifier::FindOtherFace(edgeInfos, nv0, nv1, nextFace); - } - - // Combine the forward and backwards stripification lists and put into our own face vector - Combine(forwardFaces, backwardFaces); -} - - -/////////////////////////////////////////////////////////////////////////////////////////// -// Combine() -// -// Combines the two input face vectors and puts the result into m_faces -// -void NvStripInfo::Combine(const NvFaceInfoVec &forward, const NvFaceInfoVec &backward){ - - // add backward faces - int numFaces = backward.size(); - for (int i = numFaces - 1; i >= 0; i--) - m_faces.push_back(backward[i]); - - // add forward faces - numFaces = forward.size(); - for (int i = 0; i < numFaces; i++) - m_faces.push_back(forward[i]); -} - - -/////////////////////////////////////////////////////////////////////////////////////////// -// SharesEdge() -// -// Returns true if the input face and the current strip share an edge -// -bool NvStripInfo::SharesEdge(const NvFaceInfo* faceInfo, NvEdgeInfoVec &edgeInfos) -{ - //check v0->v1 edge - NvEdgeInfo* currEdge = NvStripifier::FindEdgeInfo(edgeInfos, faceInfo->m_v0, faceInfo->m_v1); - - if(IsInStrip(currEdge->m_face0) || IsInStrip(currEdge->m_face1)) - return true; - - //check v1->v2 edge - currEdge = NvStripifier::FindEdgeInfo(edgeInfos, faceInfo->m_v1, faceInfo->m_v2); - - if(IsInStrip(currEdge->m_face0) || IsInStrip(currEdge->m_face1)) - return true; - - //check v2->v0 edge - currEdge = NvStripifier::FindEdgeInfo(edgeInfos, faceInfo->m_v2, faceInfo->m_v0); - - if(IsInStrip(currEdge->m_face0) || IsInStrip(currEdge->m_face1)) - return true; - - return false; - -} - - -/////////////////////////////////////////////////////////////////////////////////////////// -// CommitStrips() -// -// "Commits" the input strips by setting their m_experimentId to -1 and adding to the allStrips -// vector -// -void NvStripifier::CommitStrips(NvStripInfoVec &allStrips, const NvStripInfoVec &strips) -{ - // Iterate through strips - int numStrips = strips.size(); - for (int i = 0; i < numStrips; i++){ - - // Tell the strip that it is now real - NvStripInfo *strip = strips[i]; - strip->m_experimentId = -1; - - // add to the list of real strips - allStrips.push_back(strip); - - // Iterate through the faces of the strip - // Tell the faces of the strip that they belong to a real strip now - const NvFaceInfoVec &faces = strips[i]->m_faces; - int numFaces = faces.size(); - - for (int j = 0; j < numFaces; j++) - { - strip->MarkTriangle(faces[j]); - } - } -} - - -/////////////////////////////////////////////////////////////////////////////////////////// -// FindTraversal() -// -// Finds the next face to start the next strip on. -// -bool NvStripifier::FindTraversal(NvFaceInfoVec &faceInfos, - NvEdgeInfoVec &edgeInfos, - NvStripInfo *strip, - NvStripStartInfo &startInfo){ - - // if the strip was v0->v1 on the edge, then v1 will be a vertex in the next edge. - int v = (strip->m_startInfo.m_toV1 ? strip->m_startInfo.m_startEdge->m_v1 : strip->m_startInfo.m_startEdge->m_v0); - - NvFaceInfo *untouchedFace = NULL; - NvEdgeInfo *edgeIter = edgeInfos[v]; - while (edgeIter != NULL){ - NvFaceInfo *face0 = edgeIter->m_face0; - NvFaceInfo *face1 = edgeIter->m_face1; - if ((face0 != NULL && !strip->IsInStrip(face0)) && face1 != NULL && !strip->IsMarked(face1)) - { - untouchedFace = face1; - break; - } - if ((face1 != NULL && !strip->IsInStrip(face1)) && face0 != NULL && !strip->IsMarked(face0)){ - untouchedFace = face0; - break; - } - - // find the next edgeIter - edgeIter = (edgeIter->m_v0 == v ? edgeIter->m_nextV0 : edgeIter->m_nextV1); - } - - startInfo.m_startFace = untouchedFace; - startInfo.m_startEdge = edgeIter; - if (edgeIter != NULL) - { - if(strip->SharesEdge(startInfo.m_startFace, edgeInfos)) - startInfo.m_toV1 = (edgeIter->m_v0 == v); //note! used to be m_v1 - else - startInfo.m_toV1 = (edgeIter->m_v1 == v); - } - return (startInfo.m_startFace != NULL); -} - - -//////////////////////////////////////////////////////////////////////////////////////// -// RemoveSmallStrips() -// -// allStrips is the whole strip vector...all small strips will be deleted from this list, to avoid leaking mem -// allBigStrips is an out parameter which will contain all strips above minStripLength -// faceList is an out parameter which will contain all faces which were removed from the striplist -// -void NvStripifier::RemoveSmallStrips(NvStripInfoVec& allStrips, NvStripInfoVec& allBigStrips, NvFaceInfoVec& faceList) -{ - faceList.clear(); - allBigStrips.clear(); //make sure these are empty - NvFaceInfoVec tempFaceList; - - for(size_t i = 0; i < allStrips.size(); i++) - { - if(allStrips[i]->m_faces.size() < size_t(minStripLength)) - { - //strip is too small, add faces to faceList - for(size_t j = 0; j < allStrips[i]->m_faces.size(); j++) - tempFaceList.push_back(allStrips[i]->m_faces[j]); - - //and free memory - delete allStrips[i]; - } - else - { - allBigStrips.push_back(allStrips[i]); - } - } - - if(tempFaceList.size()) - { - bool *bVisitedList = new bool[tempFaceList.size()]; - memset(bVisitedList, 0, tempFaceList.size()*sizeof(bool)); - - VertexCache* vcache = new VertexCache(cacheSize); - - int bestNumHits = -1; - int numHits; - int bestIndex = -1; - - while(1) - { - bestNumHits = -1; - - //find best face to add next, given the current cache - for(size_t i = 0; i < tempFaceList.size(); i++) - { - if(bVisitedList[i]) - continue; - - numHits = CalcNumHitsFace(vcache, tempFaceList[i]); - if(numHits > bestNumHits) - { - bestNumHits = numHits; - bestIndex = i; - } - } - - if(bestNumHits == -1.0f) - break; - bVisitedList[bestIndex] = true; - UpdateCacheFace(vcache, tempFaceList[bestIndex]); - faceList.push_back(tempFaceList[bestIndex]); - } - - delete vcache; - delete[] bVisitedList; - } -} - - -/////////////////////////////////////////////////////////////////////////////////////////// -// NextIsCW() -// -// Returns true if the next face should be ordered in CW fashion -// -bool NvStripifier::NextIsCW(const int numIndices) -{ - return ((numIndices % 2) == 0); -} - - -/////////////////////////////////////////////////////////////////////////////////////////// -// IsCW() -// -// Returns true if the face is ordered in CW fashion -// -bool NvStripifier::IsCW(NvFaceInfo *faceInfo, int v0, int v1) -{ - if (faceInfo->m_v0 == v0) - return (faceInfo->m_v1 == v1); - - else if (faceInfo->m_v1 == v0) - return (faceInfo->m_v2 == v1); - - else - return (faceInfo->m_v0 == v1); - - // shouldn't get here - assert(0); - return false; -} - -bool NvStripifier::FaceContainsIndex(const NvFaceInfo& face, const unsigned int index) -{ - return ( (size_t(face.m_v0) == index) || (size_t(face.m_v1) == index) || (size_t(face.m_v2) == index) ); -} - -bool NvStripifier::IsMoneyFace(const NvFaceInfo& face) -{ - if(FaceContainsIndex(face, 800) && - FaceContainsIndex(face, 812) && - FaceContainsIndex(face, 731)) - return true; - - return false; -} - -//////////////////////////////////////////////////////////////////////////////////////// -// CreateStrips() -// -// Generates actual strips from the list-in-strip-order. -// -void NvStripifier::CreateStrips(const NvStripInfoVec& allStrips, IntVec& stripIndices, - const bool bStitchStrips, unsigned int& numSeparateStrips, - const bool bRestart, const unsigned int restartVal) -{ - assert(numSeparateStrips == 0); - - NvFaceInfo tLastFace(0, 0, 0); - NvFaceInfo tPrevStripLastFace(0, 0, 0); - int nStripCount = allStrips.size(); - assert(nStripCount > 0); - - //we infer the cw/ccw ordering depending on the number of indices - //this is screwed up by the fact that we insert -1s to denote changing strips - //this is to account for that - int accountForNegatives = 0; - - for (int i = 0; i < nStripCount; i++) - { - NvStripInfo *strip = allStrips[i]; - int nStripFaceCount = strip->m_faces.size(); - assert(nStripFaceCount > 0); - - // Handle the first face in the strip - { - NvFaceInfo tFirstFace(strip->m_faces[0]->m_v0, strip->m_faces[0]->m_v1, strip->m_faces[0]->m_v2); - - // If there is a second face, reorder vertices such that the - // unique vertex is first - if (nStripFaceCount > 1) - { - int nUnique = NvStripifier::GetUniqueVertexInB(strip->m_faces[1], &tFirstFace); - if (nUnique == tFirstFace.m_v1) - { - SWAP(tFirstFace.m_v0, tFirstFace.m_v1); - } - else if (nUnique == tFirstFace.m_v2) - { - SWAP(tFirstFace.m_v0, tFirstFace.m_v2); - } - - // If there is a third face, reorder vertices such that the - // shared vertex is last - if (nStripFaceCount > 2) - { - if(IsDegenerate(strip->m_faces[1])) - { - int pivot = strip->m_faces[1]->m_v1; - if(tFirstFace.m_v1 == pivot) - { - SWAP(tFirstFace.m_v1, tFirstFace.m_v2); - } - } - else - { - int nShared0, nShared1; - GetSharedVertices(strip->m_faces[2], &tFirstFace, &nShared0, &nShared1); - if ( (nShared0 == tFirstFace.m_v1) && (nShared1 == -1) ) - { - SWAP(tFirstFace.m_v1, tFirstFace.m_v2); - } - } - } - } - - if( (i == 0) || !bStitchStrips || bRestart) - { - if(!IsCW(strip->m_faces[0], tFirstFace.m_v0, tFirstFace.m_v1)) - stripIndices.push_back(tFirstFace.m_v0); - } - else - { - // Double tap the first in the new strip - stripIndices.push_back(tFirstFace.m_v0); - - // Check CW/CCW ordering - if (NextIsCW(stripIndices.size() - accountForNegatives) != IsCW(strip->m_faces[0], tFirstFace.m_v0, tFirstFace.m_v1)) - { - stripIndices.push_back(tFirstFace.m_v0); - } - } - - stripIndices.push_back(tFirstFace.m_v0); - stripIndices.push_back(tFirstFace.m_v1); - stripIndices.push_back(tFirstFace.m_v2); - - // Update last face info - tLastFace = tFirstFace; - } - - for (int j = 1; j < nStripFaceCount; j++) - { - int nUnique = GetUniqueVertexInB(&tLastFace, strip->m_faces[j]); - if (nUnique != -1) - { - stripIndices.push_back(nUnique); - - // Update last face info - tLastFace.m_v0 = tLastFace.m_v1; - tLastFace.m_v1 = tLastFace.m_v2; - tLastFace.m_v2 = nUnique; - } - else - { - //we've hit a degenerate - stripIndices.push_back(strip->m_faces[j]->m_v2); - tLastFace.m_v0 = strip->m_faces[j]->m_v0;//tLastFace.m_v1; - tLastFace.m_v1 = strip->m_faces[j]->m_v1;//tLastFace.m_v2; - tLastFace.m_v2 = strip->m_faces[j]->m_v2;//tLastFace.m_v1; - - } - } - - // Double tap between strips. - if (bStitchStrips && !bRestart) - { - if (i != nStripCount - 1) - stripIndices.push_back(tLastFace.m_v2); - } - else if (bRestart) - { - stripIndices.push_back(restartVal); - } - else - { - //-1 index indicates next strip - stripIndices.push_back(-1); - accountForNegatives++; - numSeparateStrips++; - } - - // Update last face info - tLastFace.m_v0 = tLastFace.m_v1; - tLastFace.m_v1 = tLastFace.m_v2; - tLastFace.m_v2 = tLastFace.m_v2; - } - - if(bStitchStrips || bRestart) - numSeparateStrips = 1; -} - - -/////////////////////////////////////////////////////////////////////////////////////////// -// Stripify() -// -// -// in_indices are the input indices of the mesh to stripify -// in_cacheSize is the target cache size -// -void NvStripifier::Stripify(const WordVec &in_indices, const int in_cacheSize, - const int in_minStripLength, const unsigned short maxIndex, - NvStripInfoVec &outStrips, NvFaceInfoVec& outFaceList) -{ - meshJump = 0.0f; - bFirstTimeResetPoint = true; //used in FindGoodResetPoint() - - //the number of times to run the experiments - int numSamples = 10; - - //the cache size, clamped to one - if ( in_cacheSize - CACHE_INEFFICIENCY < 1 ) cacheSize = 1; - else cacheSize = in_cacheSize - CACHE_INEFFICIENCY; - - minStripLength = in_minStripLength; //this is the strip size threshold below which we dump the strip into a list - - indices = in_indices; - - // build the stripification info - NvFaceInfoVec allFaceInfos; - NvEdgeInfoVec allEdgeInfos; - - BuildStripifyInfo(allFaceInfos, allEdgeInfos, maxIndex); - - NvStripInfoVec allStrips; - - // stripify - FindAllStrips(allStrips, allFaceInfos, allEdgeInfos, numSamples); - - //split up the strips into cache friendly pieces, optimize them, then dump these into outStrips - SplitUpStripsAndOptimize(allStrips, outStrips, allEdgeInfos, outFaceList); - - //clean up - for(size_t i = 0; i < allStrips.size(); i++) - { - delete allStrips[i]; - } - - for (size_t i = 0; i < allEdgeInfos.size(); i++) - { - NvEdgeInfo *info = allEdgeInfos[i]; - while (info != NULL) - { - NvEdgeInfo *next = (size_t(info->m_v0) == i ? info->m_nextV0 : info->m_nextV1); - info->Unref(); - info = next; - } - } - -} - - -bool NvStripifier::IsDegenerate(const NvFaceInfo* face) -{ - if(face->m_v0 == face->m_v1) - return true; - else if(face->m_v0 == face->m_v2) - return true; - else if(face->m_v1 == face->m_v2) - return true; - else - return false; -} - -bool NvStripifier::IsDegenerate(const unsigned short v0, const unsigned short v1, const unsigned short v2) -{ - if(v0 == v1) - return true; - else if(v0 == v2) - return true; - else if(v1 == v2) - return true; - else - return false; -} - -/////////////////////////////////////////////////////////////////////////////////////////// -// SplitUpStripsAndOptimize() -// -// Splits the input vector of strips (allBigStrips) into smaller, cache friendly pieces, then -// reorders these pieces to maximize cache hits -// The final strips are output through outStrips -// -void NvStripifier::SplitUpStripsAndOptimize(NvStripInfoVec &allStrips, NvStripInfoVec &outStrips, - NvEdgeInfoVec& edgeInfos, NvFaceInfoVec& outFaceList) -{ - int threshold = cacheSize; - NvStripInfoVec tempStrips; - - //split up strips into threshold-sized pieces - for(size_t i = 0; i < allStrips.size(); i++) - { - NvStripInfo* currentStrip; - NvStripStartInfo startInfo(NULL, NULL, false); - - int actualStripSize = 0; - for(size_t j = 0; j < allStrips[i]->m_faces.size(); ++j) - { - if( !IsDegenerate(allStrips[i]->m_faces[j]) ) - actualStripSize++; - } - - if(actualStripSize /*allStrips[i]->m_faces.size()*/ > threshold) - { - - int numTimes = actualStripSize /*allStrips[i]->m_faces.size()*/ / threshold; - int numLeftover = actualStripSize /*allStrips[i]->m_faces.size()*/ % threshold; - - int degenerateCount = 0; - int j; - for(j = 0; j < numTimes; j++) - { - currentStrip = new NvStripInfo(startInfo, 0, -1); - - int faceCtr = j*threshold + degenerateCount; - bool bFirstTime = true; - while(faceCtr < threshold+(j*threshold)+degenerateCount) - { - if(IsDegenerate(allStrips[i]->m_faces[faceCtr])) - { - degenerateCount++; - - //last time or first time through, no need for a degenerate - if( (((faceCtr + 1) != threshold+(j*threshold)+degenerateCount) || - ((j == numTimes - 1) && (numLeftover < 4) && (numLeftover > 0))) && - !bFirstTime) - { - currentStrip->m_faces.push_back(allStrips[i]->m_faces[faceCtr++]); - } - else - { - //but, we do need to delete the degenerate, if it's marked fake, to avoid leaking - if(allStrips[i]->m_faces[faceCtr]->m_bIsFake) - { - delete allStrips[i]->m_faces[faceCtr], allStrips[i]->m_faces[faceCtr] = NULL; - } - ++faceCtr; - } - } - else - { - currentStrip->m_faces.push_back(allStrips[i]->m_faces[faceCtr++]); - bFirstTime = false; - } - } - /* - for(int faceCtr = j*threshold; faceCtr < threshold+(j*threshold); faceCtr++) - { - currentStrip->m_faces.push_back(allStrips[i]->m_faces[faceCtr]); - } - */ - if(j == numTimes - 1) //last time through - { - if( (numLeftover < 4) && (numLeftover > 0) ) //way too small - { - //just add to last strip - int ctr = 0; - while(ctr < numLeftover) - { - IsDegenerate( allStrips[i]->m_faces[faceCtr] ) ? ++degenerateCount : ++ctr; - currentStrip->m_faces.push_back(allStrips[i]->m_faces[faceCtr++]); - } - numLeftover = 0; - } - } - tempStrips.push_back(currentStrip); - } - - int leftOff = j * threshold + degenerateCount; - - if(numLeftover != 0) - { - currentStrip = new NvStripInfo(startInfo, 0, -1); - - int ctr = 0; - bool bFirstTime = true; - while(ctr < numLeftover) - { - if( !IsDegenerate(allStrips[i]->m_faces[leftOff]) ) - { - ctr++; - bFirstTime = false; - currentStrip->m_faces.push_back(allStrips[i]->m_faces[leftOff++]); - } - else if(!bFirstTime) - currentStrip->m_faces.push_back(allStrips[i]->m_faces[leftOff++]); - else - { - //don't leak - if(allStrips[i]->m_faces[leftOff]->m_bIsFake) - { - delete allStrips[i]->m_faces[leftOff], allStrips[i]->m_faces[leftOff] = NULL; - } - - leftOff++; - } - } - /* - for(int k = 0; k < numLeftover; k++) - { - currentStrip->m_faces.push_back(allStrips[i]->m_faces[leftOff++]); - } - */ - - tempStrips.push_back(currentStrip); - } - } - else - { - //we're not just doing a tempStrips.push_back(allBigStrips[i]) because - // this way we can delete allBigStrips later to free the memory - currentStrip = new NvStripInfo(startInfo, 0, -1); - - for(size_t j = 0; j < allStrips[i]->m_faces.size(); j++) - currentStrip->m_faces.push_back(allStrips[i]->m_faces[j]); - - tempStrips.push_back(currentStrip); - } - } - - //add small strips to face list - NvStripInfoVec tempStrips2; - RemoveSmallStrips(tempStrips, tempStrips2, outFaceList); - - outStrips.clear(); - //screw optimization for now -// for(i = 0; i < tempStrips.size(); ++i) -// outStrips.push_back(tempStrips[i]); - - if(tempStrips2.size() != 0) - { - //Optimize for the vertex cache - VertexCache* vcache = new VertexCache(cacheSize); - - float bestNumHits = -1.0f; - float numHits; - int bestIndex = -1; - //bool done = false; - - int firstIndex = 0; - float minCost = 10000.0f; - - for(size_t i = 0; i < tempStrips2.size(); i++) - { - int numNeighbors = 0; - - //find strip with least number of neighbors per face - for(size_t j = 0; j < tempStrips2[i]->m_faces.size(); j++) - { - numNeighbors += NumNeighbors(tempStrips2[i]->m_faces[j], edgeInfos); - } - - float currCost = (float)numNeighbors / (float)tempStrips2[i]->m_faces.size(); - if(currCost < minCost) - { - minCost = currCost; - firstIndex = i; - } - } - - UpdateCacheStrip(vcache, tempStrips2[firstIndex]); - outStrips.push_back(tempStrips2[firstIndex]); - - tempStrips2[firstIndex]->visited = true; - - bool bWantsCW = (tempStrips2[firstIndex]->m_faces.size() % 2) == 0; - - //this n^2 algo is what slows down stripification so much.... - // needs to be improved - while(1) - { - bestNumHits = -1.0f; - - //find best strip to add next, given the current cache - for(size_t i = 0; i < tempStrips2.size(); i++) - { - if(tempStrips2[i]->visited) - continue; - - numHits = CalcNumHitsStrip(vcache, tempStrips2[i]); - if(numHits > bestNumHits) - { - bestNumHits = numHits; - bestIndex = i; - } - else if(numHits >= bestNumHits) - { - //check previous strip to see if this one requires it to switch polarity - NvStripInfo *strip = tempStrips2[i]; - int nStripFaceCount = strip->m_faces.size(); - - NvFaceInfo tFirstFace(strip->m_faces[0]->m_v0, strip->m_faces[0]->m_v1, strip->m_faces[0]->m_v2); - - // If there is a second face, reorder vertices such that the - // unique vertex is first - if (nStripFaceCount > 1) - { - int nUnique = NvStripifier::GetUniqueVertexInB(strip->m_faces[1], &tFirstFace); - if (nUnique == tFirstFace.m_v1) - { - SWAP(tFirstFace.m_v0, tFirstFace.m_v1); - } - else if (nUnique == tFirstFace.m_v2) - { - SWAP(tFirstFace.m_v0, tFirstFace.m_v2); - } - - // If there is a third face, reorder vertices such that the - // shared vertex is last - if (nStripFaceCount > 2) - { - int nShared0, nShared1; - GetSharedVertices(strip->m_faces[2], &tFirstFace, &nShared0, &nShared1); - if ( (nShared0 == tFirstFace.m_v1) && (nShared1 == -1) ) - { - SWAP(tFirstFace.m_v1, tFirstFace.m_v2); - } - } - } - - // Check CW/CCW ordering - if (bWantsCW == IsCW(strip->m_faces[0], tFirstFace.m_v0, tFirstFace.m_v1)) - { - //I like this one! - bestIndex = i; - } - } - } - - if(bestNumHits == -1.0f) - break; - tempStrips2[bestIndex]->visited = true; - UpdateCacheStrip(vcache, tempStrips2[bestIndex]); - outStrips.push_back(tempStrips2[bestIndex]); - bWantsCW = (tempStrips2[bestIndex]->m_faces.size() % 2 == 0) ? bWantsCW : !bWantsCW; - } - - delete vcache; - } -} - - -/////////////////////////////////////////////////////////////////////////////////////////// -// UpdateCacheStrip() -// -// Updates the input vertex cache with this strip's vertices -// -void NvStripifier::UpdateCacheStrip(VertexCache* vcache, NvStripInfo* strip) -{ - for(size_t i = 0; i < strip->m_faces.size(); ++i) - { - if(!vcache->InCache(strip->m_faces[i]->m_v0)) - vcache->AddEntry(strip->m_faces[i]->m_v0); - - if(!vcache->InCache(strip->m_faces[i]->m_v1)) - vcache->AddEntry(strip->m_faces[i]->m_v1); - - if(!vcache->InCache(strip->m_faces[i]->m_v2)) - vcache->AddEntry(strip->m_faces[i]->m_v2); - } -} - -/////////////////////////////////////////////////////////////////////////////////////////// -// UpdateCacheFace() -// -// Updates the input vertex cache with this face's vertices -// -void NvStripifier::UpdateCacheFace(VertexCache* vcache, NvFaceInfo* face) -{ - if(!vcache->InCache(face->m_v0)) - vcache->AddEntry(face->m_v0); - - if(!vcache->InCache(face->m_v1)) - vcache->AddEntry(face->m_v1); - - if(!vcache->InCache(face->m_v2)) - vcache->AddEntry(face->m_v2); -} - - -/////////////////////////////////////////////////////////////////////////////////////////// -// CalcNumHitsStrip() -// -// returns the number of cache hits per face in the strip -// -float NvStripifier::CalcNumHitsStrip(VertexCache* vcache, NvStripInfo* strip) -{ - int numHits = 0; - int numFaces = 0; - - for(size_t i = 0; i < strip->m_faces.size(); i++) - { - if(vcache->InCache(strip->m_faces[i]->m_v0)) - ++numHits; - - if(vcache->InCache(strip->m_faces[i]->m_v1)) - ++numHits; - - if(vcache->InCache(strip->m_faces[i]->m_v2)) - ++numHits; - - numFaces++; - } - - return ((float)numHits / (float)numFaces); -} - - -/////////////////////////////////////////////////////////////////////////////////////////// -// CalcNumHitsFace() -// -// returns the number of cache hits in the face -// -int NvStripifier::CalcNumHitsFace(VertexCache* vcache, NvFaceInfo* face) -{ - int numHits = 0; - - if(vcache->InCache(face->m_v0)) - numHits++; - - if(vcache->InCache(face->m_v1)) - numHits++; - - if(vcache->InCache(face->m_v2)) - numHits++; - - return numHits; -} - - -/////////////////////////////////////////////////////////////////////////////////////////// -// NumNeighbors() -// -// Returns the number of neighbors that this face has -// -int NvStripifier::NumNeighbors(NvFaceInfo* face, NvEdgeInfoVec& edgeInfoVec) -{ - int numNeighbors = 0; - - if(FindOtherFace(edgeInfoVec, face->m_v0, face->m_v1, face) != NULL) - { - numNeighbors++; - } - - if(FindOtherFace(edgeInfoVec, face->m_v1, face->m_v2, face) != NULL) - { - numNeighbors++; - } - - if(FindOtherFace(edgeInfoVec, face->m_v2, face->m_v0, face) != NULL) - { - numNeighbors++; - } - - return numNeighbors; -} - - -/////////////////////////////////////////////////////////////////////////////////////////// -// AvgStripSize() -// -// Finds the average strip size of the input vector of strips -// -float NvStripifier::AvgStripSize(const NvStripInfoVec &strips){ - int sizeAccum = 0; - int numStrips = strips.size(); - for (int i = 0; i < numStrips; i++){ - NvStripInfo *strip = strips[i]; - sizeAccum += strip->m_faces.size(); - sizeAccum -= strip->m_numDegenerates; - } - return ((float)sizeAccum) / ((float)numStrips); -} - - -/////////////////////////////////////////////////////////////////////////////////////////// -// 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; - } -} - - -/////////////////////////////////////////////////////////////////////////////////////////// -// CountRemainingTris() -// -// This will count the number of triangles left in the -// strip list starting at iter and finishing up at end -// -int NvStripifier::CountRemainingTris(std::list<NvStripInfo*>::iterator iter, - std::list<NvStripInfo*>::iterator end){ - int count = 0; - while (iter != end){ - count += (*iter)->m_faces.size(); - iter++; - } - return count; -} - diff --git a/NifExport/NvTriStrip/NvTriStripObjects.h b/NifExport/NvTriStrip/NvTriStripObjects.h deleted file mode 100755 index 3b0e66d..0000000 --- a/NifExport/NvTriStrip/NvTriStripObjects.h +++ /dev/null @@ -1,243 +0,0 @@ - -#ifndef NV_TRISTRIP_OBJECTS_H -#define NV_TRISTRIP_OBJECTS_H - -#include <assert.h> -#include <vector> -#include <list> -#include "VertexCache.h" - -///////////////////////////////////////////////////////////////////////////////// -// -// Types defined for stripification -// -///////////////////////////////////////////////////////////////////////////////// - -struct MyVertex { - float x, y, z; - float nx, ny, nz; -}; - -typedef MyVertex MyVector; - -struct MyFace { - int v1, v2, v3; - float nx, ny, nz; -}; - - -class NvFaceInfo { -public: - - // vertex indices - NvFaceInfo(int v0, int v1, int v2, bool bIsFake = false){ - m_v0 = v0; m_v1 = v1; m_v2 = v2; - m_stripId = -1; - m_testStripId = -1; - m_experimentId = -1; - m_bIsFake = bIsFake; - } - - // data members are left public - int m_v0, m_v1, m_v2; - int m_stripId; // real strip Id - int m_testStripId; // strip Id in an experiment - int m_experimentId; // in what experiment was it given an experiment Id? - bool m_bIsFake; //if true, will be deleted when the strip it's in is deleted -}; - -// nice and dumb edge class that points knows its -// indices, the two faces, and the next edge using -// the lesser of the indices -class NvEdgeInfo { -public: - - // constructor puts 1 ref on us - NvEdgeInfo (int v0, int v1){ - m_v0 = v0; - m_v1 = v1; - m_face0 = NULL; - m_face1 = NULL; - m_nextV0 = NULL; - m_nextV1 = NULL; - - // we will appear in 2 lists. this is a good - // way to make sure we delete it the second time - // we hit it in the edge infos - m_refCount = 2; - - } - - // ref and unref - void Unref () { if (--m_refCount == 0) delete this; } - - // data members are left public - unsigned int m_refCount; - NvFaceInfo *m_face0, *m_face1; - int m_v0, m_v1; - NvEdgeInfo *m_nextV0, *m_nextV1; -}; - - -// This class is a quick summary of parameters used -// to begin a triangle strip. Some operations may -// want to create lists of such items, so they were -// pulled out into a class -class NvStripStartInfo { -public: - NvStripStartInfo(NvFaceInfo *startFace, NvEdgeInfo *startEdge, bool toV1){ - m_startFace = startFace; - m_startEdge = startEdge; - m_toV1 = toV1; - } - NvFaceInfo *m_startFace; - NvEdgeInfo *m_startEdge; - bool m_toV1; -}; - - -typedef std::vector<NvFaceInfo*> NvFaceInfoVec; -typedef std::list <NvFaceInfo*> NvFaceInfoList; -typedef std::list <NvFaceInfoVec*> NvStripList; -typedef std::vector<NvEdgeInfo*> NvEdgeInfoVec; - -typedef std::vector<short> WordVec; -typedef std::vector<int> IntVec; -typedef std::vector<MyVertex> MyVertexVec; -typedef std::vector<MyFace> MyFaceVec; - -template<class T> -inline void SWAP(T& first, T& second) -{ - T temp = first; - first = second; - second = temp; -} - -// This is a summary of a strip that has been built -class NvStripInfo { -public: - - // A little information about the creation of the triangle strips - NvStripInfo(const NvStripStartInfo &startInfo, int stripId, int experimentId = -1) : - m_startInfo(startInfo) - { - m_stripId = stripId; - m_experimentId = experimentId; - visited = false; - m_numDegenerates = 0; - } - - // This is an experiment if the experiment id is >= 0 - inline bool IsExperiment () const { return m_experimentId >= 0; } - - inline bool IsInStrip (const NvFaceInfo *faceInfo) const - { - if(faceInfo == NULL) - return false; - - return (m_experimentId >= 0 ? faceInfo->m_testStripId == m_stripId : faceInfo->m_stripId == m_stripId); - } - - bool SharesEdge(const NvFaceInfo* faceInfo, NvEdgeInfoVec &edgeInfos); - - // take the given forward and backward strips and combine them together - void Combine(const NvFaceInfoVec &forward, const NvFaceInfoVec &backward); - - //returns true if the face is "unique", i.e. has a vertex which doesn't exist in the faceVec - bool Unique(NvFaceInfoVec& faceVec, NvFaceInfo* face); - - // mark the triangle as taken by this strip - bool IsMarked (NvFaceInfo *faceInfo); - void MarkTriangle(NvFaceInfo *faceInfo); - - // build the strip - void Build(NvEdgeInfoVec &edgeInfos, NvFaceInfoVec &faceInfos); - - // public data members - NvStripStartInfo m_startInfo; - NvFaceInfoVec m_faces; - int m_stripId; - int m_experimentId; - - bool visited; - - int m_numDegenerates; -}; - -typedef std::vector<NvStripInfo*> NvStripInfoVec; - - -//The actual stripifier -class NvStripifier { -public: - - // Constructor - NvStripifier(); - ~NvStripifier(); - - //the target vertex cache size, the structure to place the strips in, and the input indices - void Stripify(const WordVec &in_indices, const int in_cacheSize, const int in_minStripLength, - const unsigned short maxIndex, NvStripInfoVec &allStrips, NvFaceInfoVec &allFaces); - void CreateStrips(const NvStripInfoVec& allStrips, IntVec& stripIndices, const bool bStitchStrips, unsigned int& numSeparateStrips, const bool bRestart, const unsigned int restartVal); - - static int GetUniqueVertexInB(NvFaceInfo *faceA, NvFaceInfo *faceB); - //static int GetSharedVertex(NvFaceInfo *faceA, NvFaceInfo *faceB); - static void GetSharedVertices(NvFaceInfo *faceA, NvFaceInfo *faceB, int* vertex0, int* vertex1); - - static bool IsDegenerate(const NvFaceInfo* face); - static bool IsDegenerate(const unsigned short v0, const unsigned short v1, const unsigned short v2); - -protected: - - WordVec indices; - int cacheSize; - int minStripLength; - float meshJump; - bool bFirstTimeResetPoint; - - ///////////////////////////////////////////////////////////////////////////////// - // - // Big mess of functions called during stripification - // - ///////////////////////////////////////////////////////////////////////////////// - - //******************** - bool IsMoneyFace(const NvFaceInfo& face); - bool FaceContainsIndex(const NvFaceInfo& face, const unsigned int index); - - bool IsCW(NvFaceInfo *faceInfo, int v0, int v1); - bool NextIsCW(const int numIndices); - - static int GetNextIndex(const WordVec &indices, NvFaceInfo *face); - static NvEdgeInfo *FindEdgeInfo(NvEdgeInfoVec &edgeInfos, int v0, int v1); - static NvFaceInfo *FindOtherFace(NvEdgeInfoVec &edgeInfos, int v0, int v1, NvFaceInfo *faceInfo); - NvFaceInfo *FindGoodResetPoint(NvFaceInfoVec &faceInfos, NvEdgeInfoVec &edgeInfos); - - void FindAllStrips(NvStripInfoVec &allStrips, NvFaceInfoVec &allFaceInfos, NvEdgeInfoVec &allEdgeInfos, int numSamples); - void SplitUpStripsAndOptimize(NvStripInfoVec &allStrips, NvStripInfoVec &outStrips, NvEdgeInfoVec& edgeInfos, NvFaceInfoVec& outFaceList); - void RemoveSmallStrips(NvStripInfoVec& allStrips, NvStripInfoVec& allBigStrips, NvFaceInfoVec& faceList); - - bool FindTraversal(NvFaceInfoVec &faceInfos, NvEdgeInfoVec &edgeInfos, NvStripInfo *strip, NvStripStartInfo &startInfo); - int CountRemainingTris(std::list<NvStripInfo*>::iterator iter, std::list<NvStripInfo*>::iterator end); - - void CommitStrips(NvStripInfoVec &allStrips, const NvStripInfoVec &strips); - - float AvgStripSize(const NvStripInfoVec &strips); - int FindStartPoint(NvFaceInfoVec &faceInfos, NvEdgeInfoVec &edgeInfos); - - void UpdateCacheStrip(VertexCache* vcache, NvStripInfo* strip); - void UpdateCacheFace(VertexCache* vcache, NvFaceInfo* face); - float CalcNumHitsStrip(VertexCache* vcache, NvStripInfo* strip); - int CalcNumHitsFace(VertexCache* vcache, NvFaceInfo* face); - int NumNeighbors(NvFaceInfo* face, NvEdgeInfoVec& edgeInfoVec); - - void BuildStripifyInfo(NvFaceInfoVec &faceInfos, NvEdgeInfoVec &edgeInfos, const unsigned short maxIndex); - bool AlreadyExists(NvFaceInfo* faceInfo, NvFaceInfoVec& faceInfos); - - // let our strip info classes and the other classes get - // to these protected stripificaton methods if they want - friend class NvStripInfo; -}; - -#endif diff --git a/NifExport/NvTriStrip/VertexCache.cpp b/NifExport/NvTriStrip/VertexCache.cpp deleted file mode 100755 index a89548d..0000000 --- a/NifExport/NvTriStrip/VertexCache.cpp +++ /dev/null @@ -1,88 +0,0 @@ - - -#include "VertexCache.h" - -VertexCache::VertexCache() -{ - VertexCache(16); -} - - -VertexCache::VertexCache(int size) -{ - numEntries = size; - - entries = new int[numEntries]; - - for(int i = 0; i < numEntries; i++) - entries[i] = -1; -} - - -VertexCache::~VertexCache() -{ - delete[] entries; -} - - -int VertexCache::At(int index) -{ - return entries[index]; -} - - -void VertexCache::Set(int index, int value) -{ - entries[index] = value; -} - - -void VertexCache::Clear() -{ - for(int i = 0; i < numEntries; i++) - entries[i] = -1; -} - -void VertexCache::Copy(VertexCache* inVcache) -{ - for(int i = 0; i < numEntries; i++) - { - inVcache->Set(i, entries[i]); - } -} - -bool VertexCache::InCache(int entry) -{ - bool returnVal = false; - - for(int i = 0; i < numEntries; i++) - { - if(entries[i] == entry) - { - returnVal = true; - break; - } - } - - return returnVal; -} - - -int VertexCache::AddEntry(int entry) -{ - int removed; - - removed = entries[numEntries - 1]; - - //push everything right one - for(int i = numEntries - 2; i >= 0; i--) - { - entries[i + 1] = entries[i]; - } - - entries[0] = entry; - - return removed; -} - - \ No newline at end of file diff --git a/NifExport/NvTriStrip/VertexCache.h b/NifExport/NvTriStrip/VertexCache.h deleted file mode 100755 index 0d3066b..0000000 --- a/NifExport/NvTriStrip/VertexCache.h +++ /dev/null @@ -1,27 +0,0 @@ - -#ifndef VERTEX_CACHE_H - -#define VERTEX_CACHE_H - -class VertexCache -{ - -public: - VertexCache(int size); - VertexCache(); - ~VertexCache(); - bool InCache(int entry); - int AddEntry(int entry); - void Clear(); - void Copy(VertexCache* inVcache) ; - int At(int index); - void Set(int index, int value); - -private: - - int *entries; - int numEntries; - -}; - -#endif diff --git a/NifExport/TriStripper/connectivity_graph.cpp b/NifExport/TriStripper/connectivity_graph.cpp deleted file mode 100644 index 9d0b389..0000000 --- a/NifExport/TriStripper/connectivity_graph.cpp +++ /dev/null @@ -1,132 +0,0 @@ -// -// Copyright (C) 2004 Tanguy Fautré. -// For conditions of distribution and use, -// see copyright notice in tri_stripper.h -// -////////////////////////////////////////////////////////////////////// -// SVN: $Id: connectivity_graph.cpp 86 2005-06-08 17:47:27Z gpsnoopy $ -////////////////////////////////////////////////////////////////////// - -#include "detail/connectivity_graph.h" - -#include <algorithm> - - - - -namespace triangle_stripper { - - namespace detail { - - - - -namespace -{ - - class tri_edge : public triangle_edge - { - public: - tri_edge(index A, index B, size_t TriPos) - : triangle_edge(A, B), m_TriPos(TriPos) { } - - size_t TriPos() const { return m_TriPos; } - - private: - size_t m_TriPos; - }; - - - class cmp_tri_edge_lt - { - public: - bool operator() (const tri_edge & a, const tri_edge & b) const; - }; - - - typedef std::vector<tri_edge> edge_map; - - - void LinkNeighbours(graph_array<triangle> & Triangles, const edge_map & EdgeMap, const tri_edge Edge); - -} - - - - -void make_connectivity_graph(graph_array<triangle> & Triangles, const indices & Indices) -{ - assert(Triangles.size() == (Indices.size() / 3)); - - // Fill the triangle data - for (size_t i = 0; i < Triangles.size(); ++i) - Triangles[i] = triangle(Indices[i * 3 + 0], Indices[i * 3 + 1], Indices[i * 3 + 2]); - - // Build an edge lookup table - edge_map EdgeMap; - EdgeMap.reserve(Triangles.size() * 3); - - for (size_t i = 0; i < Triangles.size(); ++i) { - - const triangle & Tri = * Triangles[i]; - - EdgeMap.push_back(tri_edge(Tri.A(), Tri.B(), i)); - EdgeMap.push_back(tri_edge(Tri.B(), Tri.C(), i)); - EdgeMap.push_back(tri_edge(Tri.C(), Tri.A(), i)); - } - - std::sort(EdgeMap.begin(), EdgeMap.end(), cmp_tri_edge_lt()); - - // Link neighbour triangles together using the lookup table - for (size_t i = 0; i < Triangles.size(); ++i) { - - const triangle & Tri = * Triangles[i]; - - LinkNeighbours(Triangles, EdgeMap, tri_edge(Tri.B(), Tri.A(), i)); - LinkNeighbours(Triangles, EdgeMap, tri_edge(Tri.C(), Tri.B(), i)); - LinkNeighbours(Triangles, EdgeMap, tri_edge(Tri.A(), Tri.C(), i)); - } -} - - - -namespace -{ - - inline bool cmp_tri_edge_lt::operator() (const tri_edge & a, const tri_edge & b) const - { - const index A1 = a.A(); - const index B1 = a.B(); - const index A2 = b.A(); - const index B2 = b.B(); - - if ((A1 < A2) || ((A1 == A2) && (B1 < B2))) - return true; - else - return false; - } - - - void LinkNeighbours(graph_array<triangle> & Triangles, const edge_map & EdgeMap, const tri_edge Edge) - { - // Find the first edge equal to Edge - edge_map::const_iterator it = std::lower_bound(EdgeMap.begin(), EdgeMap.end(), Edge, cmp_tri_edge_lt()); - - // See if there are any other edges that are equal - // (if so, it means that more than 2 triangles are sharing the same edge, - // which is unlikely but not impossible) - for (; (it != EdgeMap.end()) && (Edge == (* it)); ++it) - Triangles.insert_arc(Edge.TriPos(), it->TriPos()); - - // Note: degenerated triangles will also point themselves as neighbour triangles - } - -} - - - - - } // namespace detail - -} // namespace detail - diff --git a/NifExport/TriStripper/detail/cache_simulator.h b/NifExport/TriStripper/detail/cache_simulator.h deleted file mode 100644 index 1281d51..0000000 --- a/NifExport/TriStripper/detail/cache_simulator.h +++ /dev/null @@ -1,154 +0,0 @@ -// -// Copyright (C) 2004 Tanguy Fautré. -// For conditions of distribution and use, -// see copyright notice in tri_stripper.h -// -////////////////////////////////////////////////////////////////////// -// SVN: $Id: cache_simulator.h 86 2005-06-08 17:47:27Z gpsnoopy $ -////////////////////////////////////////////////////////////////////// - -#ifndef TRI_STRIPPER_HEADER_GUARD_CACHE_SIMULATOR_H -#define TRI_STRIPPER_HEADER_GUARD_CACHE_SIMULATOR_H - -#include <algorithm> -#include <limits> -#include <deque> - - - - -namespace triangle_stripper { - - namespace detail { - - - - -class cache_simulator -{ -public: - cache_simulator(); - - void clear(); - void resize(size_t Size); - void reset(); - void push_cache_hits(bool Enabled = true); - size_t size() const; - - void push(index i, bool CountCacheHit = false); - void merge(const cache_simulator & Backward, size_t PossibleOverlap); - - void reset_hitcount(); - size_t hitcount() const; - -protected: - typedef std::deque<index> indices_deque; - - indices_deque m_Cache; - size_t m_NbHits; - bool m_PushHits; -}; - - - - - -////////////////////////////////////////////////////////////////////////// -// cache_simulator inline functions -////////////////////////////////////////////////////////////////////////// - -inline cache_simulator::cache_simulator() - : m_NbHits(0), - m_PushHits(true) -{ - -} - - -inline void cache_simulator::clear() -{ - reset_hitcount(); - m_Cache.clear(); -} - - -inline void cache_simulator::resize(const size_t Size) -{ - m_Cache.resize(Size, std::numeric_limits<index>::max()); -} - - -inline void cache_simulator::reset() -{ - std::fill(m_Cache.begin(), m_Cache.end(), std::numeric_limits<index>::max()); - reset_hitcount(); -} - - -inline void cache_simulator::push_cache_hits(bool Enabled) -{ - m_PushHits = Enabled; -} - - -inline size_t cache_simulator::size() const -{ - return m_Cache.size(); -} - - -inline void cache_simulator::push(const index i, const bool CountCacheHit) -{ - if (CountCacheHit || m_PushHits) { - - if (std::find(m_Cache.begin(), m_Cache.end(), i) != m_Cache.end()) { - - // Should we count the cache hits? - if (CountCacheHit) - ++m_NbHits; - - // Should we not push the index into the cache if it's a cache hit? - if (! m_PushHits) - return; - } - } - - // Manage the indices cache as a FIFO structure - m_Cache.push_front(i); - m_Cache.pop_back(); -} - - -inline void cache_simulator::merge(const cache_simulator & Backward, const size_t PossibleOverlap) -{ - const size_t Overlap = std::min(PossibleOverlap, size()); - - for (size_t i = 0; i < Overlap; ++i) - push(Backward.m_Cache[i], true); - - m_NbHits += Backward.m_NbHits; -} - - -inline void cache_simulator::reset_hitcount() -{ - m_NbHits = 0; -} - - -inline size_t cache_simulator::hitcount() const -{ - return m_NbHits; -} - - - - - } // namespace detail - -} // namespace triangle_stripper - - - - -#endif // TRI_STRIPPER_HEADER_GUARD_CACHE_SIMULATOR_H diff --git a/NifExport/TriStripper/detail/connectivity_graph.h b/NifExport/TriStripper/detail/connectivity_graph.h deleted file mode 100644 index e5cbc46..0000000 --- a/NifExport/TriStripper/detail/connectivity_graph.h +++ /dev/null @@ -1,36 +0,0 @@ -// -// Copyright (C) 2004 Tanguy Fautré. -// For conditions of distribution and use, -// see copyright notice in tri_stripper.h -// -////////////////////////////////////////////////////////////////////// -// SVN: $Id: connectivity_graph.h 86 2005-06-08 17:47:27Z gpsnoopy $ -////////////////////////////////////////////////////////////////////// - -#ifndef TRI_STRIPPER_HEADER_GUARD_CONNECTIVITY_GRAPH_H -#define TRI_STRIPPER_HEADER_GUARD_CONNECTIVITY_GRAPH_H - -#include "public_types.h" - -#include "graph_array.h" -#include "types.h" - - - - -namespace triangle_stripper -{ - - namespace detail - { - - void make_connectivity_graph(graph_array<triangle> & Triangles, const indices & Indices); - - } - -} - - - - -#endif // TRI_STRIPPER_HEADER_GUARD_CONNECTIVITY_GRAPH_H diff --git a/NifExport/TriStripper/detail/graph_array.h b/NifExport/TriStripper/detail/graph_array.h deleted file mode 100644 index 764998e..0000000 --- a/NifExport/TriStripper/detail/graph_array.h +++ /dev/null @@ -1,460 +0,0 @@ -// -// Copyright (C) 2004 Tanguy Fautré. -// For conditions of distribution and use, -// see copyright notice in tri_stripper.h -// -////////////////////////////////////////////////////////////////////// -// SVN: $Id: graph_array.h 86 2005-06-08 17:47:27Z gpsnoopy $ -////////////////////////////////////////////////////////////////////// - -#ifndef TRI_STRIPPER_HEADER_GUARD_GRAPH_ARRAY_H -#define TRI_STRIPPER_HEADER_GUARD_GRAPH_ARRAY_H - -#include <cassert> -#include <algorithm> -#include <functional> -#include <limits> -#include <vector> - - - - -namespace triangle_stripper { - - namespace detail { - - - - -// graph_array main class -template <class nodetype> -class graph_array -{ -public: - - class arc; - class node; - - // New types - typedef size_t nodeid; - typedef nodetype value_type; - typedef std::vector<node> node_vector; - typedef typename node_vector::iterator node_iterator; - typedef typename node_vector::const_iterator const_node_iterator; - typedef typename node_vector::reverse_iterator node_reverse_iterator; - typedef typename node_vector::const_reverse_iterator const_node_reverse_iterator; - - typedef graph_array<nodetype> graph_type; - - - // graph_array::arc class - class arc - { - public: - node_iterator terminal() const; - - protected: - friend class graph_array<nodetype>; - - arc(node_iterator Terminal); - - node_iterator m_Terminal; - }; - - - // New types - typedef std::vector<arc> arc_list; - typedef typename arc_list::iterator out_arc_iterator; - typedef typename arc_list::const_iterator const_out_arc_iterator; - - - // graph_array::node class - class node - { - public: - void mark(); - void unmark(); - bool marked() const; - - bool out_empty() const; - size_t out_size() const; - - out_arc_iterator out_begin(); - out_arc_iterator out_end(); - const_out_arc_iterator out_begin() const; - const_out_arc_iterator out_end() const; - - value_type & operator * (); - value_type * operator -> (); - const value_type & operator * () const; - const value_type * operator -> () const; - - value_type & operator = (const value_type & Elem); - - protected: - friend class graph_array<nodetype>; - friend class std::vector<node>; - - node(arc_list & Arcs); - - arc_list & m_Arcs; - size_t m_Begin; - size_t m_End; - - value_type m_Elem; - bool m_Marker; - }; - - - graph_array(); - explicit graph_array(size_t NbNodes); - - // Node related member functions - bool empty() const; - size_t size() const; - - node & operator [] (nodeid i); - const node & operator [] (nodeid i) const; - - node_iterator begin(); - node_iterator end(); - const_node_iterator begin() const; - const_node_iterator end() const; - - node_reverse_iterator rbegin(); - node_reverse_iterator rend(); - const_node_reverse_iterator rbegin() const; - const_node_reverse_iterator rend() const; - - // Arc related member functions - out_arc_iterator insert_arc(nodeid Initial, nodeid Terminal); - out_arc_iterator insert_arc(node_iterator Initial, node_iterator Terminal); - - // Optimized (overloaded) functions - void swap(graph_type & Right); - friend void swap(graph_type & Left, graph_type & Right) { Left.swap(Right); } - -protected: - graph_array(const graph_type &); - graph_type & operator = (const graph_type &); - - node_vector m_Nodes; - arc_list m_Arcs; -}; - - - -// Additional "low level", graph related, functions -template <class nodetype> -void unmark_nodes(graph_array<nodetype> & G); - - - - - -////////////////////////////////////////////////////////////////////////// -// graph_array::arc inline functions -////////////////////////////////////////////////////////////////////////// - -template <class N> -inline graph_array<N>::arc::arc(node_iterator Terminal) - : m_Terminal(Terminal) { } - - -template <class N> -inline typename graph_array<N>::node_iterator graph_array<N>::arc::terminal() const -{ - return m_Terminal; -} - - - -////////////////////////////////////////////////////////////////////////// -// graph_array::node inline functions -////////////////////////////////////////////////////////////////////////// - -template <class N> -inline graph_array<N>::node::node(arc_list & Arcs) - : m_Arcs(Arcs), - m_Begin(std::numeric_limits<size_t>::max()), - m_End(std::numeric_limits<size_t>::max()), - m_Marker(false) -{ - -} - - -template <class N> -inline void graph_array<N>::node::mark() -{ - m_Marker = true; -} - - -template <class N> -inline void graph_array<N>::node::unmark() -{ - m_Marker = false; -} - - -template <class N> -inline bool graph_array<N>::node::marked() const -{ - return m_Marker; -} - - -template <class N> -inline bool graph_array<N>::node::out_empty() const -{ - return (m_Begin == m_End); -} - - -template <class N> -inline size_t graph_array<N>::node::out_size() const -{ - return (m_End - m_Begin); -} - - -template <class N> -inline typename graph_array<N>::out_arc_iterator graph_array<N>::node::out_begin() -{ - return (m_Arcs.begin() + m_Begin); -} - - -template <class N> -inline typename graph_array<N>::out_arc_iterator graph_array<N>::node::out_end() -{ - return (m_Arcs.begin() + m_End); -} - - -template <class N> -inline typename graph_array<N>::const_out_arc_iterator graph_array<N>::node::out_begin() const -{ - return (m_Arcs.begin() + m_Begin); -} - - -template <class N> -inline typename graph_array<N>::const_out_arc_iterator graph_array<N>::node::out_end() const -{ - return (m_Arcs.begin() + m_End); -} - - -template <class N> -inline N & graph_array<N>::node::operator * () -{ - return m_Elem; -} - - -template <class N> -inline N * graph_array<N>::node::operator -> () -{ - return &m_Elem; -} - - -template <class N> -inline const N & graph_array<N>::node::operator * () const -{ - return m_Elem; -} - - -template <class N> -inline const N * graph_array<N>::node::operator -> () const -{ - return &m_Elem; -} - - -template <class N> -inline N & graph_array<N>::node::operator = (const N & Elem) -{ - return (m_Elem = Elem); -} - - - -////////////////////////////////////////////////////////////////////////// -// graph_array inline functions -////////////////////////////////////////////////////////////////////////// - -template <class N> -inline graph_array<N>::graph_array() { } - - -template <class N> -inline graph_array<N>::graph_array(const size_t NbNodes) - : m_Nodes(NbNodes, node(m_Arcs)) -{ - // optimisation: we consider that, averagely, a triangle may have at least 2 neighbours - // otherwise we are just wasting a bit of memory, but not that much - m_Arcs.reserve(NbNodes * 2); -} - - -template <class N> -inline bool graph_array<N>::empty() const -{ - return m_Nodes.empty(); -} - - -template <class N> -inline size_t graph_array<N>::size() const -{ - return m_Nodes.size(); -} - - -template <class N> -inline typename graph_array<N>::node & graph_array<N>::operator [] (const nodeid i) -{ - assert(i < size()); - - return m_Nodes[i]; -} - - -template <class N> -inline const typename graph_array<N>::node & graph_array<N>::operator [] (const nodeid i) const -{ - assert(i < size()); - - return m_Nodes[i]; -} - - -template <class N> -inline typename graph_array<N>::node_iterator graph_array<N>::begin() -{ - return m_Nodes.begin(); -} - - -template <class N> -inline typename graph_array<N>::node_iterator graph_array<N>::end() -{ - return m_Nodes.end(); -} - - -template <class N> -inline typename graph_array<N>::const_node_iterator graph_array<N>::begin() const -{ - return m_Nodes.begin(); -} - - -template <class N> -inline typename graph_array<N>::const_node_iterator graph_array<N>::end() const -{ - return m_Nodes.end(); -} - - -template <class N> -inline typename graph_array<N>::node_reverse_iterator graph_array<N>::rbegin() -{ - return m_Nodes.rbegin(); -} - - -template <class N> -inline typename graph_array<N>::node_reverse_iterator graph_array<N>::rend() -{ - return m_Nodes.rend(); -} - - -template <class N> -inline typename graph_array<N>::const_node_reverse_iterator graph_array<N>::rbegin() const -{ - return m_Nodes.rbegin(); -} - - -template <class N> -inline typename graph_array<N>::const_node_reverse_iterator graph_array<N>::rend() const -{ - return m_Nodes.rend(); -} - - -template <class N> -inline typename graph_array<N>::out_arc_iterator graph_array<N>::insert_arc(const nodeid Initial, const nodeid Terminal) -{ - assert(Initial < size()); - assert(Terminal < size()); - - return insert_arc(m_Nodes.begin() + Initial, m_Nodes.begin() + Terminal); -} - - -template <class N> -inline typename graph_array<N>::out_arc_iterator graph_array<N>::insert_arc(const node_iterator Initial, const node_iterator Terminal) -{ - assert((Initial >= begin()) && (Initial < end())); - assert((Terminal >= begin()) && (Terminal < end())); - - node & Node = * Initial; - - if (Node.out_empty()) { - - Node.m_Begin = m_Arcs.size(); - Node.m_End = m_Arcs.size() + 1; - - } else { - - // we optimise here for make_connectivity_graph() - // we know all the arcs for a given node are successively and sequentially added - assert(Node.m_End == m_Arcs.size()); - - ++(Node.m_End); - } - - m_Arcs.push_back(arc(Terminal)); - - out_arc_iterator it = m_Arcs.end(); - return (--it); -} - - -template <class N> -inline void graph_array<N>::swap(graph_type & Right) -{ - std::swap(m_Nodes, Right.m_Nodes); - std::swap(m_Arcs, Right.m_Arcs); -} - - - -////////////////////////////////////////////////////////////////////////// -// additional functions -////////////////////////////////////////////////////////////////////////// - -template <class N> -inline void unmark_nodes(graph_array<N> & G) -{ - std::for_each(G.begin(), G.end(), std::mem_fun_ref(&graph_array<N>::node::unmark)); -} - - - - - } // namespace detail - -} // namespace triangle_stripper - - - - -#endif // TRI_STRIPPER_HEADER_GUARD_GRAPH_ARRAY_H diff --git a/NifExport/TriStripper/detail/heap_array.h b/NifExport/TriStripper/detail/heap_array.h deleted file mode 100644 index 598d40b..0000000 --- a/NifExport/TriStripper/detail/heap_array.h +++ /dev/null @@ -1,297 +0,0 @@ -// -// Copyright (C) 2004 Tanguy Fautré. -// For conditions of distribution and use, -// see copyright notice in tri_stripper.h -// -////////////////////////////////////////////////////////////////////// -// SVN: $Id: heap_array.h 86 2005-06-08 17:47:27Z gpsnoopy $ -////////////////////////////////////////////////////////////////////// - -#ifndef TRI_STRIPPER_HEADER_GUARD_HEAP_ARRAY_H -#define TRI_STRIPPER_HEADER_GUARD_HEAP_ARRAY_H - -#include <vector> - - - - -namespace triangle_stripper { - - namespace detail { - - - - -// mutable heap -// can be interfaced pretty muck like an array -template <class T, class CmpT = std::less<T> > -class heap_array -{ -public: - - // Pre = PreCondition, Post = PostCondition - - heap_array() : m_Locked(false) { } // Post: ((size() == 0) && ! locked()) - - void clear(); // Post: ((size() == 0) && ! locked()) - - void reserve(size_t Size); - size_t size() const; - - bool empty() const; - bool locked() const; - bool removed(size_t i) const; // Pre: (valid(i)) - bool valid(size_t i) const; - - size_t position(size_t i) const; // Pre: (valid(i)) - - const T & top() const; // Pre: (! empty()) - const T & peek(size_t i) const; // Pre: (! removed(i)) - const T & operator [] (size_t i) const; // Pre: (! removed(i)) - - void lock(); // Pre: (! locked()) Post: (locked()) - size_t push(const T & Elem); // Pre: (! locked()) - - void pop(); // Pre: (locked() && ! empty()) - void erase(size_t i); // Pre: (locked() && ! removed(i)) - void update(size_t i, const T & Elem); // Pre: (locked() && ! removed(i)) - -protected: - - heap_array(const heap_array &); - heap_array & operator = (const heap_array &); - - class linker - { - public: - linker(const T & Elem, size_t i) - : m_Elem(Elem), m_Index(i) { } - - T m_Elem; - size_t m_Index; - }; - - typedef std::vector<linker> linked_heap; - typedef std::vector<size_t> finder; - - void Adjust(size_t i); - void Swap(size_t a, size_t b); - bool Less(const linker & a, const linker & b) const; - - linked_heap m_Heap; - finder m_Finder; - CmpT m_Compare; - bool m_Locked; -}; - - - - - -////////////////////////////////////////////////////////////////////////// -// heap_indexed inline functions -////////////////////////////////////////////////////////////////////////// - -template <class T, class CmpT> -inline void heap_array<T, CmpT>::clear() -{ - m_Heap.clear(); - m_Finder.clear(); - m_Locked = false; -} - - -template <class T, class CmpT> -inline bool heap_array<T, CmpT>::empty() const -{ - return m_Heap.empty(); -} - - -template <class T, class CmpT> -inline bool heap_array<T, CmpT>::locked() const -{ - return m_Locked; -} - - -template <class T, class CmpT> -inline void heap_array<T, CmpT>::reserve(const size_t Size) -{ - m_Heap.reserve(Size); - m_Finder.reserve(Size); -} - - -template <class T, class CmpT> -inline size_t heap_array<T, CmpT>::size() const -{ - return m_Heap.size(); -} - - -template <class T, class CmpT> -inline const T & heap_array<T, CmpT>::top() const -{ - assert(! empty()); - - return m_Heap.front().m_Elem; -} - - -template <class T, class CmpT> -inline const T & heap_array<T, CmpT>::peek(const size_t i) const -{ - assert(! removed(i)); - - return (m_Heap[m_Finder[i]].m_Elem); -} - - -template <class T, class CmpT> -inline const T & heap_array<T, CmpT>::operator [] (const size_t i) const -{ - return peek(i); -} - - -template <class T, class CmpT> -inline void heap_array<T, CmpT>::pop() -{ - assert(locked()); - assert(! empty()); - - Swap(0, size() - 1); - m_Heap.pop_back(); - - if (! empty()) - Adjust(0); -} - - -template <class T, class CmpT> -inline void heap_array<T, CmpT>::lock() -{ - assert(! locked()); - - m_Locked =true; -} - - -template <class T, class CmpT> -inline size_t heap_array<T, CmpT>::push(const T & Elem) -{ - assert(! locked()); - - const size_t Id = size(); - m_Finder.push_back(Id); - m_Heap.push_back(linker(Elem, Id)); - Adjust(Id); - - return Id; -} - - -template <class T, class CmpT> -inline void heap_array<T, CmpT>::erase(const size_t i) -{ - assert(locked()); - assert(! removed(i)); - - const size_t j = m_Finder[i]; - Swap(j, size() - 1); - m_Heap.pop_back(); - - if (j != size()) - Adjust(j); -} - - -template <class T, class CmpT> -inline bool heap_array<T, CmpT>::removed(const size_t i) const -{ - assert(valid(i)); - - return (m_Finder[i] >= m_Heap.size()); -} - - -template <class T, class CmpT> -inline bool heap_array<T, CmpT>::valid(const size_t i) const -{ - return (i < m_Finder.size()); -} - - -template <class T, class CmpT> -inline size_t heap_array<T, CmpT>::position(const size_t i) const -{ - assert(valid(i)); - - return (m_Heap[i].m_Index); -} - - -template <class T, class CmpT> -inline void heap_array<T, CmpT>::update(const size_t i, const T & Elem) -{ - assert(locked()); - assert(! removed(i)); - - const size_t j = m_Finder[i]; - m_Heap[j].m_Elem = Elem; - Adjust(j); -} - - -template <class T, class CmpT> -inline void heap_array<T, CmpT>::Adjust(size_t i) -{ - assert(i < m_Heap.size()); - - size_t j; - - // Check the upper part of the heap - for (j = i; (j > 0) && (Less(m_Heap[(j - 1) / 2], m_Heap[j])); j = ((j - 1) / 2)) - Swap(j, (j - 1) / 2); - - // Check the lower part of the heap - for (i = j; (j = 2 * i + 1) < size(); i = j) { - if ((j + 1 < size()) && (Less(m_Heap[j], m_Heap[j + 1]))) - ++j; - - if (Less(m_Heap[j], m_Heap[i])) - return; - - Swap(i, j); - } -} - - -template <class T, class CmpT> -inline void heap_array<T, CmpT>::Swap(const size_t a, const size_t b) -{ - std::swap(m_Heap[a], m_Heap[b]); - - m_Finder[(m_Heap[a].m_Index)] = a; - m_Finder[(m_Heap[b].m_Index)] = b; -} - - -template <class T, class CmpT> -inline bool heap_array<T, CmpT>::Less(const linker & a, const linker & b) const -{ - return m_Compare(a.m_Elem, b.m_Elem); -} - - - - - } // namespace detail - -} // namespace triangle_stripper - - - - -#endif // TRI_STRIPPER_HEADER_GUARD_HEAP_ARRAY_H diff --git a/NifExport/TriStripper/detail/policy.h b/NifExport/TriStripper/detail/policy.h deleted file mode 100644 index c1a7c0a..0000000 --- a/NifExport/TriStripper/detail/policy.h +++ /dev/null @@ -1,66 +0,0 @@ -// -// Copyright (C) 2004 Tanguy Fautré. -// For conditions of distribution and use, -// see copyright notice in tri_stripper.h -// -////////////////////////////////////////////////////////////////////// -// SVN: $Id: policy.h 86 2005-06-08 17:47:27Z gpsnoopy $ -////////////////////////////////////////////////////////////////////// - -#ifndef TRI_STRIPPER_HEADER_GUARD_POLICY_H -#define TRI_STRIPPER_HEADER_GUARD_POLICY_H - -#include "public_types.h" -#include "types.h" - - - - -namespace triangle_stripper { - - namespace detail { - - - - -class policy -{ -public: - policy(size_t MinStripSize, bool Cache); - - strip BestStrip() const; - void Challenge(strip Strip, size_t Degree, size_t CacheHits); - -private: - strip m_Strip; - size_t m_Degree; - size_t m_CacheHits; - - const size_t m_MinStripSize; - const bool m_Cache; -}; - - - - - -inline policy::policy(size_t MinStripSize, bool Cache) -: m_Degree(0), m_CacheHits(0), m_MinStripSize(MinStripSize), m_Cache(Cache) { } - - -inline strip policy::BestStrip() const -{ - return m_Strip; -} - - - - - } // namespace detail - -} // namespace triangle_stripper - - - - -#endif // TRI_STRIPPER_HEADER_GUARD_POLICY_H diff --git a/NifExport/TriStripper/detail/types.h b/NifExport/TriStripper/detail/types.h deleted file mode 100644 index 5b0419f..0000000 --- a/NifExport/TriStripper/detail/types.h +++ /dev/null @@ -1,101 +0,0 @@ -// -// Copyright (C) 2004 Tanguy Fautré. -// For conditions of distribution and use, -// see copyright notice in tri_stripper.h -// -////////////////////////////////////////////////////////////////////// -// SVN: $Id: types.h 86 2005-06-08 17:47:27Z gpsnoopy $ -////////////////////////////////////////////////////////////////////// - -#ifndef TRI_STRIPPER_HEADER_GUARD_TYPES_H -#define TRI_STRIPPER_HEADER_GUARD_TYPES_H - - - - -namespace triangle_stripper { - - namespace detail { - - - - -class triangle -{ -public: - triangle() { } - triangle(index A, index B, index C) - : m_A(A), m_B(B), m_C(C), m_StripID(0) { } - - void ResetStripID() { m_StripID = 0; } - void SetStripID(size_t StripID) { m_StripID = StripID; } - size_t StripID() const { return m_StripID; } - - index A() const { return m_A; } - index B() const { return m_B; } - index C() const { return m_C; } - -private: - index m_A; - index m_B; - index m_C; - - size_t m_StripID; -}; - - - -class triangle_edge -{ -public: - triangle_edge(index A, index B) - : m_A(A), m_B(B) { } - - index A() const { return m_A; } - index B() const { return m_B; } - - bool operator == (const triangle_edge & Right) const { - return ((A() == Right.A()) && (B() == Right.B())); - } - -private: - index m_A; - index m_B; -}; - - - -enum triangle_order { ABC, BCA, CAB }; - - - -class strip -{ -public: - strip() - : m_Start(0), m_Order(ABC), m_Size(0) { } - - strip(size_t Start, triangle_order Order, size_t Size) - : m_Start(Start), m_Order(Order), m_Size(Size) { } - - size_t Start() const { return m_Start; } - triangle_order Order() const { return m_Order; } - size_t Size() const { return m_Size; } - -private: - size_t m_Start; - triangle_order m_Order; - size_t m_Size; -}; - - - - - } // namespace detail - -} // namespace triangle_stripper - - - - -#endif // TRI_STRIPPER_HEADER_GUARD_TYPES_H diff --git a/NifExport/TriStripper/policy.cpp b/NifExport/TriStripper/policy.cpp deleted file mode 100644 index cd62563..0000000 --- a/NifExport/TriStripper/policy.cpp +++ /dev/null @@ -1,63 +0,0 @@ -// -// Copyright (C) 2004 Tanguy Fautré. -// For conditions of distribution and use, -// see copyright notice in tri_stripper.h -// -////////////////////////////////////////////////////////////////////// -// SVN: $Id: policy.cpp 86 2005-06-08 17:47:27Z gpsnoopy $ -////////////////////////////////////////////////////////////////////// - -#include "detail/policy.h" - - - - -namespace triangle_stripper { - - namespace detail { - - - - -void policy::Challenge(strip Strip, size_t Degree, size_t CacheHits) -{ - if (Strip.Size() < m_MinStripSize) - return; - - // Cache is disabled, take the longest strip - if (! m_Cache) { - - if (Strip.Size() > m_Strip.Size()) - m_Strip = Strip; - - // Cache simulator enabled - } else { - - // Priority 1: Keep the strip with the best cache hit count - if (CacheHits > m_CacheHits) { - m_Strip = Strip; - m_Degree = Degree; - m_CacheHits = CacheHits; - - } else if (CacheHits == m_CacheHits) { - - // Priority 2: Keep the strip with the loneliest start triangle - if ((m_Strip.Size() != 0) && (Degree < m_Degree)) { - m_Strip = Strip; - m_Degree = Degree; - - // Priority 3: Keep the longest strip - } else if (Strip.Size() > m_Strip.Size()) { - m_Strip = Strip; - m_Degree = Degree; - } - } - } -} - - - - - } // namespace detail - -} // namespace triangle_stripper diff --git a/NifExport/TriStripper/tri_stripper.cpp b/NifExport/TriStripper/tri_stripper.cpp deleted file mode 100755 index feb17ac..0000000 --- a/NifExport/TriStripper/tri_stripper.cpp +++ /dev/null @@ -1,554 +0,0 @@ -// -// Copyright (C) 2004 Tanguy Fautré. -// For conditions of distribution and use, -// see copyright notice in tri_stripper.h -// -////////////////////////////////////////////////////////////////////// -// SVN: $Id: tri_stripper.cpp 86 2005-06-08 17:47:27Z gpsnoopy $ -////////////////////////////////////////////////////////////////////// - -#include "tri_stripper.h" - -#include "detail/connectivity_graph.h" -#include "detail/policy.h" - -#include <cassert> - - - - -namespace triangle_stripper { - - using namespace detail; - - - - -tri_stripper::tri_stripper(const indices & TriIndices) - : m_Triangles(TriIndices.size() / 3), // Silently ignore extra indices if (Indices.size() % 3 != 0) - m_StripID(0), - m_FirstRun(true) -{ - SetCacheSize(); - SetMinStripSize(); - SetBackwardSearch(); - SetPushCacheHits(); - - make_connectivity_graph(m_Triangles, TriIndices); -} - - - -void tri_stripper::Strip(primitive_vector * out_pPrimitivesVector) -{ - assert(out_pPrimitivesVector); - - if (! m_FirstRun) { - unmark_nodes(m_Triangles); - ResetStripIDs(); - m_Cache.reset(); - m_TriHeap.clear(); - m_Candidates.clear(); - m_StripID = 0; - - m_FirstRun = false; - } - - out_pPrimitivesVector->clear(); - - InitTriHeap(); - - Stripify(); - AddLeftTriangles(); - - std::swap(m_PrimitivesVector, (* out_pPrimitivesVector)); -} - - - -void tri_stripper::InitTriHeap() -{ - m_TriHeap.reserve(m_Triangles.size()); - - // Set up the triangles priority queue - // The lower the number of available neighbour triangles, the higher the priority. - for (size_t i = 0; i < m_Triangles.size(); ++i) - m_TriHeap.push(m_Triangles[i].out_size()); - - // We're not going to add new elements anymore - m_TriHeap.lock(); - - // Remove useless triangles - // Note: we had to put all of them into the heap before to ensure coherency of the heap_array object - while ((! m_TriHeap.empty()) && (m_TriHeap.top() == 0)) - m_TriHeap.pop(); -} - - - -void tri_stripper::ResetStripIDs() -{ - for (triangle_graph::node_iterator it = m_Triangles.begin(); it != m_Triangles.end(); ++it) - (**it).ResetStripID(); -} - - - -void tri_stripper::Stripify() -{ - while (! m_TriHeap.empty()) { - - // There is no triangle in the candidates list, refill it with the loneliest triangle - const size_t HeapTop = m_TriHeap.position(0); - m_Candidates.push_back(HeapTop); - - while (! m_Candidates.empty()) { - - // Note: FindBestStrip empties the candidate list, while BuildStrip refills it - const strip TriStrip = FindBestStrip(); - - if (TriStrip.Size() >= m_MinStripSize) - BuildStrip(TriStrip); - } - - if (! m_TriHeap.removed(HeapTop)) - m_TriHeap.erase(HeapTop); - - // Eliminate all the triangles that have now become useless - while ((! m_TriHeap.empty()) && (m_TriHeap.top() == 0)) - m_TriHeap.pop(); - } -} - - - -inline strip tri_stripper::FindBestStrip() -{ - // Allow to restore the cache (modified by ExtendTriToStrip) and implicitly reset the cache hit count - const cache_simulator CacheBackup = m_Cache; - - policy Policy(m_MinStripSize, Cache()); - - while (! m_Candidates.empty()) { - - const size_t Candidate = m_Candidates.back(); - m_Candidates.pop_back(); - - // Discard useless triangles from the candidate list - if ((m_Triangles[Candidate].marked()) || (m_TriHeap[Candidate] == 0)) - continue; - - // Try to extend the triangle in the 3 possible forward directions - for (size_t i = 0; i < 3; ++i) { - - const strip Strip = ExtendToStrip(Candidate, triangle_order(i)); - Policy.Challenge(Strip, m_TriHeap[Strip.Start()], m_Cache.hitcount()); - - m_Cache = CacheBackup; - } - - // Try to extend the triangle in the 6 possible backward directions - if (m_BackwardSearch) { - - for (size_t i = 0; i < 3; ++i) { - - const strip Strip = BackExtendToStrip(Candidate, triangle_order(i), false); - Policy.Challenge(Strip, m_TriHeap[Strip.Start()], m_Cache.hitcount()); - - m_Cache = CacheBackup; - } - - for (size_t i = 0; i < 3; ++i) { - - const strip Strip = BackExtendToStrip(Candidate, triangle_order(i), true); - Policy.Challenge(Strip, m_TriHeap[Strip.Start()], m_Cache.hitcount()); - - m_Cache = CacheBackup; - } - } - - } - - return Policy.BestStrip(); -} - - - -strip tri_stripper::ExtendToStrip(const size_t Start, triangle_order Order) -{ - const triangle_order StartOrder = Order; - - // Begin a new strip - m_Triangles[Start]->SetStripID(++m_StripID); - AddTriangle(* m_Triangles[Start], Order, false); - - size_t Size = 1; - bool ClockWise = false; - - // Loop while we can further extend the strip - for (tri_iterator Node = (m_Triangles.begin() + Start); - (Node != m_Triangles.end()) && (!Cache() || ((Size + 2) < CacheSize())); - ++Size) { - - const const_link_iterator Link = LinkToNeighbour(Node, ClockWise, Order, false); - - // Is it the end of the strip? - if (Link == Node->out_end()) { - - Node = m_Triangles.end(); - --Size; - - } else { - - Node = Link->terminal(); - (* Node)->SetStripID(m_StripID); - ClockWise = ! ClockWise; - - } - } - - return strip(Start, StartOrder, Size); -} - - - -strip tri_stripper::BackExtendToStrip(size_t Start, triangle_order Order, bool ClockWise) -{ - // Begin a new strip - m_Triangles[Start]->SetStripID(++m_StripID); - BackAddIndex(LastEdge(* m_Triangles[Start], Order).B()); - size_t Size = 1; - - tri_iterator Node; - - // Loop while we can further extend the strip - for (Node = (m_Triangles.begin() + Start); - !Cache() || ((Size + 2) < CacheSize()); - ++Size) { - - const const_link_iterator Link = BackLinkToNeighbour(Node, ClockWise, Order); - - // Is it the end of the strip? - if (Link == Node->out_end()) - break; - - else { - Node = Link->terminal(); - (* Node)->SetStripID(m_StripID); - ClockWise = ! ClockWise; - } - } - - // We have to start from a counterclockwise triangle. - // Simply return an empty strip in the case where the first triangle is clockwise. - // Even though we could discard the first triangle and start from the next counterclockwise triangle, - // this often leads to more lonely triangles afterward. - if (ClockWise) - return strip(); - - if (Cache()) { - m_Cache.merge(m_BackCache, Size); - m_BackCache.reset(); - } - - return strip(Node - m_Triangles.begin(), Order, Size); -} - - - -void tri_stripper::BuildStrip(const strip Strip) -{ - const size_t Start = Strip.Start(); - - bool ClockWise = false; - triangle_order Order = Strip.Order(); - - // Create a new strip - m_PrimitivesVector.push_back(primitive_group()); - m_PrimitivesVector.back().Type = TRIANGLE_STRIP; - AddTriangle(* m_Triangles[Start], Order, true); - MarkTriAsTaken(Start); - - // Loop while we can further extend the strip - tri_iterator Node = (m_Triangles.begin() + Start); - - for (size_t Size = 1; Size < Strip.Size(); ++Size) { - - const const_link_iterator Link = LinkToNeighbour(Node, ClockWise, Order, true); - - assert(Link != Node->out_end()); - - // Go to the next triangle - Node = Link->terminal(); - MarkTriAsTaken(Node - m_Triangles.begin()); - ClockWise = ! ClockWise; - } -} - - - -inline tri_stripper::const_link_iterator tri_stripper::LinkToNeighbour(const const_tri_iterator Node, const bool ClockWise, triangle_order & Order, const bool NotSimulation) -{ - const triangle_edge Edge = LastEdge(** Node, Order); - - for (const_link_iterator Link = Node->out_begin(); Link != Node->out_end(); ++Link) { - - // Get the reference to the possible next triangle - const triangle & Tri = ** Link->terminal(); - - // Check whether it's already been used - if (NotSimulation || (Tri.StripID() != m_StripID)) { - - if (! Link->terminal()->marked()) { - - // Does the current candidate triangle match the required position for the strip? - - if ((Edge.B() == Tri.A()) && (Edge.A() == Tri.B())) { - Order = (ClockWise) ? ABC : BCA; - AddIndex(Tri.C(), NotSimulation); - return Link; - } - - else if ((Edge.B() == Tri.B()) && (Edge.A() == Tri.C())) { - Order = (ClockWise) ? BCA : CAB; - AddIndex(Tri.A(), NotSimulation); - return Link; - } - - else if ((Edge.B() == Tri.C()) && (Edge.A() == Tri.A())) { - Order = (ClockWise) ? CAB : ABC; - AddIndex(Tri.B(), NotSimulation); - return Link; - } - } - } - - } - - return Node->out_end(); -} - - - -inline tri_stripper::const_link_iterator tri_stripper::BackLinkToNeighbour(const_tri_iterator Node, bool ClockWise, triangle_order & Order) -{ - const triangle_edge Edge = FirstEdge(** Node, Order); - - for (const_link_iterator Link = Node->out_begin(); Link != Node->out_end(); ++Link) { - - // Get the reference to the possible previous triangle - const triangle & Tri = ** Link->terminal(); - - // Check whether it's already been used - if ((Tri.StripID() != m_StripID) && ! Link->terminal()->marked()) { - - // Does the current candidate triangle match the required position for the strip? - - if ((Edge.B() == Tri.A()) && (Edge.A() == Tri.B())) { - Order = (ClockWise) ? CAB : BCA; - BackAddIndex(Tri.C()); - return Link; - } - - else if ((Edge.B() == Tri.B()) && (Edge.A() == Tri.C())) { - Order = (ClockWise) ? ABC : CAB; - BackAddIndex(Tri.A()); - return Link; - } - - else if ((Edge.B() == Tri.C()) && (Edge.A() == Tri.A())) { - Order = (ClockWise) ? BCA : ABC; - BackAddIndex(Tri.B()); - return Link; - } - } - - } - - return Node->out_end(); -} - - - -void tri_stripper::MarkTriAsTaken(const size_t i) -{ - typedef triangle_graph::node_iterator tri_node_iter; - typedef triangle_graph::out_arc_iterator tri_link_iter; - - // Mark the triangle node - m_Triangles[i].mark(); - - // Remove triangle from priority queue if it isn't yet - if (! m_TriHeap.removed(i)) - m_TriHeap.erase(i); - - // Adjust the degree of available neighbour triangles - for (tri_link_iter Link = m_Triangles[i].out_begin(); Link != m_Triangles[i].out_end(); ++Link) { - - const size_t j = Link->terminal() - m_Triangles.begin(); - - if ((! m_Triangles[j].marked()) && (! m_TriHeap.removed(j))) { - size_t NewDegree = m_TriHeap.peek(j); - NewDegree = NewDegree - 1; - m_TriHeap.update(j, NewDegree); - - // Update the candidate list if cache is enabled - if (Cache() && (NewDegree > 0)) - m_Candidates.push_back(j); - } - } -} - - - -inline triangle_edge tri_stripper::FirstEdge(const triangle & Triangle, const triangle_order Order) -{ - switch (Order) - { - case ABC: - return triangle_edge(Triangle.A(), Triangle.B()); - - case BCA: - return triangle_edge(Triangle.B(), Triangle.C()); - - case CAB: - return triangle_edge(Triangle.C(), Triangle.A()); - - default: - assert(false); - return triangle_edge(0, 0); - } -} - - - -inline triangle_edge tri_stripper::LastEdge(const triangle & Triangle, const triangle_order Order) -{ - switch (Order) - { - case ABC: - return triangle_edge(Triangle.B(), Triangle.C()); - - case BCA: - return triangle_edge(Triangle.C(), Triangle.A()); - - case CAB: - return triangle_edge(Triangle.A(), Triangle.B()); - - default: - assert(false); - return triangle_edge(0, 0); - } -} - - - -inline void tri_stripper::AddIndex(const index i, const bool NotSimulation) -{ - if (Cache()) - m_Cache.push(i, ! NotSimulation); - - if (NotSimulation) - m_PrimitivesVector.back().Indices.push_back(i); -} - - - -inline void tri_stripper::BackAddIndex(const index i) -{ - if (Cache()) - m_BackCache.push(i, true); -} - - - -inline void tri_stripper::AddTriangle(const triangle & Tri, const triangle_order Order, const bool NotSimulation) -{ - switch (Order) - { - case ABC: - AddIndex(Tri.A(), NotSimulation); - AddIndex(Tri.B(), NotSimulation); - AddIndex(Tri.C(), NotSimulation); - break; - - case BCA: - AddIndex(Tri.B(), NotSimulation); - AddIndex(Tri.C(), NotSimulation); - AddIndex(Tri.A(), NotSimulation); - break; - - case CAB: - AddIndex(Tri.C(), NotSimulation); - AddIndex(Tri.A(), NotSimulation); - AddIndex(Tri.B(), NotSimulation); - break; - } -} - - - -inline void tri_stripper::BackAddTriangle(const triangle & Tri, const triangle_order Order) -{ - switch (Order) - { - case ABC: - BackAddIndex(Tri.C()); - BackAddIndex(Tri.B()); - BackAddIndex(Tri.A()); - break; - - case BCA: - BackAddIndex(Tri.A()); - BackAddIndex(Tri.C()); - BackAddIndex(Tri.B()); - break; - - case CAB: - BackAddIndex(Tri.B()); - BackAddIndex(Tri.A()); - BackAddIndex(Tri.C()); - break; - } -} - - - -void tri_stripper::AddLeftTriangles() -{ - // Create the last indices array and fill it with all the triangles that couldn't be stripped - primitive_group Primitives; - Primitives.Type = TRIANGLES; - m_PrimitivesVector.push_back(Primitives); - indices & Indices = m_PrimitivesVector.back().Indices; - - for (size_t i = 0; i < m_Triangles.size(); ++i) - if (! m_Triangles[i].marked()) { - Indices.push_back(m_Triangles[i]->A()); - Indices.push_back(m_Triangles[i]->B()); - Indices.push_back(m_Triangles[i]->C()); - } - - // Undo if useless - if (Indices.size() == 0) - m_PrimitivesVector.pop_back(); -} - - - -inline bool tri_stripper::Cache() const -{ - return (m_Cache.size() != 0); -} - - - -inline size_t tri_stripper::CacheSize() const -{ - return m_Cache.size(); -} - - - - -} // namespace triangle_stripper -- GitLab