Counter Strike : Global Offensive Source Code
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1742 lines
46 KiB

  1. #pragma warning( disable : 4786 4018 4530 )
  2. #include <assert.h>
  3. #include <set>
  4. #include "NvTriStripObjects.h"
  5. #include "VertexCache.h"
  6. #include "tier0/platform.h"
  7. #define CACHE_INEFFICIENCY 6
  8. NvStripifier::NvStripifier()
  9. {
  10. }
  11. NvStripifier::~NvStripifier()
  12. {
  13. }
  14. ///////////////////////////////////////////////////////////////////////////////////////////
  15. // FindEdgeInfo()
  16. //
  17. // find the edge info for these two indices
  18. //
  19. NvEdgeInfo * NvStripifier::FindEdgeInfo(NvEdgeInfoVec &edgeInfos, int v0, int v1){
  20. // we can get to it through either array
  21. // because the edge infos have a v0 and v1
  22. // and there is no order except how it was
  23. // first created.
  24. NvEdgeInfo *infoIter = edgeInfos[v0];
  25. while (infoIter != NULL){
  26. if (infoIter->m_v0 == v0){
  27. if (infoIter->m_v1 == v1)
  28. return infoIter;
  29. else
  30. infoIter = infoIter->m_nextV0;
  31. }
  32. else {
  33. assert(infoIter->m_v1 == v0);
  34. if (infoIter->m_v0 == v1)
  35. return infoIter;
  36. else
  37. infoIter = infoIter->m_nextV1;
  38. }
  39. }
  40. return NULL;
  41. }
  42. ///////////////////////////////////////////////////////////////////////////////////////////
  43. // FindOtherFace
  44. //
  45. // find the other face sharing these vertices
  46. // exactly like the edge info above
  47. //
  48. NvFaceInfo * NvStripifier::FindOtherFace(NvEdgeInfoVec &edgeInfos, int v0, int v1, NvFaceInfo *faceInfo){
  49. NvEdgeInfo *edgeInfo = FindEdgeInfo(edgeInfos, v0, v1);
  50. if( (edgeInfo == NULL) && (v0 == v1))
  51. {
  52. //we've hit a degenerate
  53. return NULL;
  54. }
  55. assert(edgeInfo != NULL);
  56. return (edgeInfo->m_face0 == faceInfo ? edgeInfo->m_face1 : edgeInfo->m_face0);
  57. }
  58. bool NvStripifier::AlreadyExists(NvFaceInfo* faceInfo, NvFaceInfoVec& faceInfos)
  59. {
  60. for(int i = 0; i < faceInfos.size(); ++i)
  61. {
  62. if( (faceInfos[i]->m_v0 == faceInfo->m_v0) &&
  63. (faceInfos[i]->m_v1 == faceInfo->m_v1) &&
  64. (faceInfos[i]->m_v2 == faceInfo->m_v2) )
  65. return true;
  66. }
  67. return false;
  68. }
  69. ///////////////////////////////////////////////////////////////////////////////////////////
  70. // BuildStripifyInfo()
  71. //
  72. // Builds the list of all face and edge infos
  73. //
  74. void NvStripifier::BuildStripifyInfo(NvFaceInfoVec &faceInfos, NvEdgeInfoVec &edgeInfos,
  75. const unsigned short maxIndex)
  76. {
  77. // reserve space for the face infos, but do not resize them.
  78. int numIndices = indices.size();
  79. faceInfos.reserve(numIndices / 3);
  80. // we actually resize the edge infos, so we must initialize to NULL
  81. edgeInfos.resize(maxIndex + 1);
  82. for (int i = 0; i < maxIndex + 1; i++)
  83. edgeInfos[i] = NULL;
  84. // iterate through the triangles of the triangle list
  85. int numTriangles = numIndices / 3;
  86. int index = 0;
  87. bool bFaceUpdated[3];
  88. for (int i = 0; i < numTriangles; i++)
  89. {
  90. bool bMightAlreadyExist = true;
  91. bFaceUpdated[0] = false;
  92. bFaceUpdated[1] = false;
  93. bFaceUpdated[2] = false;
  94. // grab the indices
  95. int v0 = indices[index++];
  96. int v1 = indices[index++];
  97. int v2 = indices[index++];
  98. //we disregard degenerates
  99. if(IsDegenerate(v0, v1, v2))
  100. continue;
  101. // create the face info and add it to the list of faces, but only if this exact face doesn't already
  102. // exist in the list
  103. NvFaceInfo *faceInfo = new NvFaceInfo(v0, v1, v2);
  104. // grab the edge infos, creating them if they do not already exist
  105. NvEdgeInfo *edgeInfo01 = FindEdgeInfo(edgeInfos, v0, v1);
  106. if (edgeInfo01 == NULL)
  107. {
  108. //since one of it's edges isn't in the edge data structure, it can't already exist in the face structure
  109. bMightAlreadyExist = false;
  110. // create the info
  111. edgeInfo01 = new NvEdgeInfo(v0, v1);
  112. // update the linked list on both
  113. edgeInfo01->m_nextV0 = edgeInfos[v0];
  114. edgeInfo01->m_nextV1 = edgeInfos[v1];
  115. edgeInfos[v0] = edgeInfo01;
  116. edgeInfos[v1] = edgeInfo01;
  117. // set face 0
  118. edgeInfo01->m_face0 = faceInfo;
  119. }
  120. else
  121. {
  122. if (edgeInfo01->m_face1 != NULL)
  123. {
  124. // printf("BuildStripifyInfo: > 2 triangles on an edge... uncertain consequences\n");
  125. }
  126. else
  127. {
  128. edgeInfo01->m_face1 = faceInfo;
  129. bFaceUpdated[0] = true;
  130. }
  131. }
  132. // grab the edge infos, creating them if they do not already exist
  133. NvEdgeInfo *edgeInfo12 = FindEdgeInfo(edgeInfos, v1, v2);
  134. if (edgeInfo12 == NULL)
  135. {
  136. bMightAlreadyExist = false;
  137. // create the info
  138. edgeInfo12 = new NvEdgeInfo(v1, v2);
  139. // update the linked list on both
  140. edgeInfo12->m_nextV0 = edgeInfos[v1];
  141. edgeInfo12->m_nextV1 = edgeInfos[v2];
  142. edgeInfos[v1] = edgeInfo12;
  143. edgeInfos[v2] = edgeInfo12;
  144. // set face 0
  145. edgeInfo12->m_face0 = faceInfo;
  146. }
  147. else
  148. {
  149. if (edgeInfo12->m_face1 != NULL)
  150. {
  151. // printf("BuildStripifyInfo: > 2 triangles on an edge... uncertain consequences\n");
  152. }
  153. else
  154. {
  155. edgeInfo12->m_face1 = faceInfo;
  156. bFaceUpdated[1] = true;
  157. }
  158. }
  159. // grab the edge infos, creating them if they do not already exist
  160. NvEdgeInfo *edgeInfo20 = FindEdgeInfo(edgeInfos, v2, v0);
  161. if (edgeInfo20 == NULL)
  162. {
  163. bMightAlreadyExist = false;
  164. // create the info
  165. edgeInfo20 = new NvEdgeInfo(v2, v0);
  166. // update the linked list on both
  167. edgeInfo20->m_nextV0 = edgeInfos[v2];
  168. edgeInfo20->m_nextV1 = edgeInfos[v0];
  169. edgeInfos[v2] = edgeInfo20;
  170. edgeInfos[v0] = edgeInfo20;
  171. // set face 0
  172. edgeInfo20->m_face0 = faceInfo;
  173. }
  174. else
  175. {
  176. if (edgeInfo20->m_face1 != NULL)
  177. {
  178. // printf("BuildStripifyInfo: > 2 triangles on an edge... uncertain consequences\n");
  179. }
  180. else
  181. {
  182. edgeInfo20->m_face1 = faceInfo;
  183. bFaceUpdated[2] = true;
  184. }
  185. }
  186. if(bMightAlreadyExist)
  187. {
  188. if(!AlreadyExists(faceInfo, faceInfos))
  189. faceInfos.push_back(faceInfo);
  190. else
  191. {
  192. delete faceInfo;
  193. //cleanup pointers that point to this deleted face
  194. if(bFaceUpdated[0])
  195. edgeInfo01->m_face1 = NULL;
  196. if(bFaceUpdated[1])
  197. edgeInfo12->m_face1 = NULL;
  198. if(bFaceUpdated[2])
  199. edgeInfo20->m_face1 = NULL;
  200. }
  201. }
  202. else
  203. {
  204. faceInfos.push_back(faceInfo);
  205. }
  206. }
  207. }
  208. ///////////////////////////////////////////////////////////////////////////////////////////
  209. // FindStartPoint()
  210. //
  211. // Finds a good starting point, namely one which has only one neighbor
  212. //
  213. int NvStripifier::FindStartPoint(NvFaceInfoVec &faceInfos, NvEdgeInfoVec &edgeInfos)
  214. {
  215. int bestCtr = -1;
  216. int bestIndex = -1;
  217. for(int i = 0; i < faceInfos.size(); i++)
  218. {
  219. int ctr = 0;
  220. if(FindOtherFace(edgeInfos, faceInfos[i]->m_v0, faceInfos[i]->m_v1, faceInfos[i]) == NULL)
  221. ctr++;
  222. if(FindOtherFace(edgeInfos, faceInfos[i]->m_v1, faceInfos[i]->m_v2, faceInfos[i]) == NULL)
  223. ctr++;
  224. if(FindOtherFace(edgeInfos, faceInfos[i]->m_v2, faceInfos[i]->m_v0, faceInfos[i]) == NULL)
  225. ctr++;
  226. if(ctr > bestCtr)
  227. {
  228. bestCtr = ctr;
  229. bestIndex = i;
  230. //return i;
  231. }
  232. }
  233. //return -1;
  234. if(bestCtr == 0)
  235. return -1;
  236. else
  237. return bestIndex;
  238. }
  239. ///////////////////////////////////////////////////////////////////////////////////////////
  240. // FindGoodResetPoint()
  241. //
  242. // A good reset point is one near other commited areas so that
  243. // we know that when we've made the longest strips its because
  244. // we're stripifying in the same general orientation.
  245. //
  246. NvFaceInfo* NvStripifier::FindGoodResetPoint(NvFaceInfoVec &faceInfos, NvEdgeInfoVec &edgeInfos){
  247. // we hop into different areas of the mesh to try to get
  248. // other large open spans done. Areas of small strips can
  249. // just be left to triangle lists added at the end.
  250. NvFaceInfo *result = NULL;
  251. if(result == NULL)
  252. {
  253. int numFaces = faceInfos.size();
  254. int startPoint;
  255. if(bFirstTimeResetPoint)
  256. {
  257. //first time, find a face with few neighbors (look for an edge of the mesh)
  258. startPoint = FindStartPoint(faceInfos, edgeInfos);
  259. bFirstTimeResetPoint = false;
  260. }
  261. else
  262. startPoint = (int)(((float) numFaces - 1) * meshJump);
  263. if(startPoint == -1)
  264. {
  265. startPoint = (int)(((float) numFaces - 1) * meshJump);
  266. //meshJump += 0.1f;
  267. //if (meshJump > 1.0f)
  268. // meshJump = .05f;
  269. }
  270. int i = startPoint;
  271. do {
  272. // if this guy isn't visited, try him
  273. if (faceInfos[i]->m_stripId < 0){
  274. result = faceInfos[i];
  275. break;
  276. }
  277. // update the index and clamp to 0-(numFaces-1)
  278. if (++i >= numFaces)
  279. i = 0;
  280. } while (i != startPoint);
  281. // update the meshJump
  282. meshJump += 0.1f;
  283. if (meshJump > 1.0f)
  284. meshJump = .05f;
  285. }
  286. // return the best face we found
  287. return result;
  288. }
  289. ///////////////////////////////////////////////////////////////////////////////////////////
  290. // GetUniqueVertexInB()
  291. //
  292. // Returns the vertex unique to faceB
  293. //
  294. int NvStripifier::GetUniqueVertexInB(NvFaceInfo *faceA, NvFaceInfo *faceB){
  295. int facev0 = faceB->m_v0;
  296. if (facev0 != faceA->m_v0 &&
  297. facev0 != faceA->m_v1 &&
  298. facev0 != faceA->m_v2)
  299. return facev0;
  300. int facev1 = faceB->m_v1;
  301. if (facev1 != faceA->m_v0 &&
  302. facev1 != faceA->m_v1 &&
  303. facev1 != faceA->m_v2)
  304. return facev1;
  305. int facev2 = faceB->m_v2;
  306. if (facev2 != faceA->m_v0 &&
  307. facev2 != faceA->m_v1 &&
  308. facev2 != faceA->m_v2)
  309. return facev2;
  310. // nothing is different
  311. return -1;
  312. }
  313. ///////////////////////////////////////////////////////////////////////////////////////////
  314. // GetSharedVertices()
  315. //
  316. // Returns the (at most) two vertices shared between the two faces
  317. //
  318. void NvStripifier::GetSharedVertices(NvFaceInfo *faceA, NvFaceInfo *faceB, int* vertex0, int* vertex1)
  319. {
  320. *vertex0 = -1;
  321. *vertex1 = -1;
  322. int facev0 = faceB->m_v0;
  323. if (facev0 == faceA->m_v0 ||
  324. facev0 == faceA->m_v1 ||
  325. facev0 == faceA->m_v2)
  326. {
  327. if(*vertex0 == -1)
  328. *vertex0 = facev0;
  329. else
  330. {
  331. *vertex1 = facev0;
  332. return;
  333. }
  334. }
  335. int facev1 = faceB->m_v1;
  336. if (facev1 == faceA->m_v0 ||
  337. facev1 == faceA->m_v1 ||
  338. facev1 == faceA->m_v2)
  339. {
  340. if(*vertex0 == -1)
  341. *vertex0 = facev1;
  342. else
  343. {
  344. *vertex1 = facev1;
  345. return;
  346. }
  347. }
  348. int facev2 = faceB->m_v2;
  349. if (facev2 == faceA->m_v0 ||
  350. facev2 == faceA->m_v1 ||
  351. facev2 == faceA->m_v2)
  352. {
  353. if(*vertex0 == -1)
  354. *vertex0 = facev2;
  355. else
  356. {
  357. *vertex1 = facev2;
  358. return;
  359. }
  360. }
  361. }
  362. ///////////////////////////////////////////////////////////////////////////////////////////
  363. // GetNextIndex()
  364. //
  365. // Returns vertex of the input face which is "next" in the input index list
  366. //
  367. inline int NvStripifier::GetNextIndex(const WordVec &indices, NvFaceInfo *face){
  368. int numIndices = indices.size();
  369. assert(numIndices >= 2);
  370. int v0 = indices[numIndices-2];
  371. int v1 = indices[numIndices-1];
  372. int fv0 = face->m_v0;
  373. int fv1 = face->m_v1;
  374. int fv2 = face->m_v2;
  375. if (fv0 != v0 && fv0 != v1){
  376. if ((fv1 != v0 && fv1 != v1) || (fv2 != v0 && fv2 != v1)){
  377. printf("GetNextIndex: Triangle doesn't have all of its vertices\n");
  378. printf("GetNextIndex: Duplicate triangle probably got us derailed\n");
  379. }
  380. return fv0;
  381. }
  382. if (fv1 != v0 && fv1 != v1){
  383. if ((fv0 != v0 && fv0 != v1) || (fv2 != v0 && fv2 != v1)){
  384. printf("GetNextIndex: Triangle doesn't have all of its vertices\n");
  385. printf("GetNextIndex: Duplicate triangle probably got us derailed\n");
  386. }
  387. return fv1;
  388. }
  389. if (fv2 != v0 && fv2 != v1){
  390. if ((fv0 != v0 && fv0 != v1) || (fv1 != v0 && fv1 != v1)){
  391. printf("GetNextIndex: Triangle doesn't have all of its vertices\n");
  392. printf("GetNextIndex: Duplicate triangle probably got us derailed\n");
  393. }
  394. return fv2;
  395. }
  396. // shouldn't get here, but let's try and fail gracefully
  397. if( (fv0 == fv1) || (fv0 == fv2) )
  398. return fv0;
  399. else if( (fv1 == fv0) || (fv1 == fv2) )
  400. return fv1;
  401. else if( (fv2 == fv0) || (fv2 == fv1) )
  402. return fv2;
  403. else
  404. return -1;
  405. }
  406. ///////////////////////////////////////////////////////////////////////////////////////////
  407. // IsMarked()
  408. //
  409. // If either the faceInfo has a real strip index because it is
  410. // already assign to a committed strip OR it is assigned in an
  411. // experiment and the experiment index is the one we are building
  412. // for, then it is marked and unavailable
  413. inline bool NvStripInfo::IsMarked(NvFaceInfo *faceInfo){
  414. return (faceInfo->m_stripId >= 0) || (IsExperiment() && faceInfo->m_experimentId == m_experimentId);
  415. }
  416. ///////////////////////////////////////////////////////////////////////////////////////////
  417. // MarkTriangle()
  418. //
  419. // Marks the face with the current strip ID
  420. //
  421. inline void NvStripInfo::MarkTriangle(NvFaceInfo *faceInfo){
  422. assert(!IsMarked(faceInfo));
  423. if (IsExperiment()){
  424. faceInfo->m_experimentId = m_experimentId;
  425. faceInfo->m_testStripId = m_stripId;
  426. }
  427. else{
  428. assert(faceInfo->m_stripId == -1);
  429. faceInfo->m_experimentId = -1;
  430. faceInfo->m_stripId = m_stripId;
  431. }
  432. }
  433. bool NvStripInfo::Unique(NvFaceInfoVec& faceVec, NvFaceInfo* face)
  434. {
  435. bool bv0, bv1, bv2; //bools to indicate whether a vertex is in the faceVec or not
  436. bv0 = bv1 = bv2 = false;
  437. for(int i = 0; i < faceVec.size(); i++)
  438. {
  439. if(!bv0)
  440. {
  441. if( (faceVec[i]->m_v0 == face->m_v0) ||
  442. (faceVec[i]->m_v1 == face->m_v0) ||
  443. (faceVec[i]->m_v2 == face->m_v0) )
  444. bv0 = true;
  445. }
  446. if(!bv1)
  447. {
  448. if( (faceVec[i]->m_v0 == face->m_v1) ||
  449. (faceVec[i]->m_v1 == face->m_v1) ||
  450. (faceVec[i]->m_v2 == face->m_v1) )
  451. bv1 = true;
  452. }
  453. if(!bv2)
  454. {
  455. if( (faceVec[i]->m_v0 == face->m_v2) ||
  456. (faceVec[i]->m_v1 == face->m_v2) ||
  457. (faceVec[i]->m_v2 == face->m_v2) )
  458. bv2 = true;
  459. }
  460. //the face is not unique, all it's vertices exist in the face vector
  461. if(bv0 && bv1 && bv2)
  462. return false;
  463. }
  464. //if we get out here, it's unique
  465. return true;
  466. }
  467. ///////////////////////////////////////////////////////////////////////////////////////////
  468. // Build()
  469. //
  470. // Builds a strip forward as far as we can go, then builds backwards, and joins the two lists
  471. //
  472. void NvStripInfo::Build(NvEdgeInfoVec &edgeInfos, NvFaceInfoVec &faceInfos)
  473. {
  474. // used in building the strips forward and backward
  475. WordVec scratchIndices;
  476. // build forward... start with the initial face
  477. NvFaceInfoVec forwardFaces, backwardFaces;
  478. forwardFaces.push_back(m_startInfo.m_startFace);
  479. MarkTriangle(m_startInfo.m_startFace);
  480. int v0 = (m_startInfo.m_toV1 ? m_startInfo.m_startEdge->m_v0 : m_startInfo.m_startEdge->m_v1);
  481. int v1 = (m_startInfo.m_toV1 ? m_startInfo.m_startEdge->m_v1 : m_startInfo.m_startEdge->m_v0);
  482. // easiest way to get v2 is to use this function which requires the
  483. // other indices to already be in the list.
  484. scratchIndices.push_back(v0);
  485. scratchIndices.push_back(v1);
  486. int v2 = NvStripifier::GetNextIndex(scratchIndices, m_startInfo.m_startFace);
  487. scratchIndices.push_back(v2);
  488. //
  489. // build the forward list
  490. //
  491. int nv0 = v1;
  492. int nv1 = v2;
  493. NvFaceInfo *nextFace = NvStripifier::FindOtherFace(edgeInfos, nv0, nv1, m_startInfo.m_startFace);
  494. while (nextFace != NULL && !IsMarked(nextFace))
  495. {
  496. //check to see if this next face is going to cause us to die soon
  497. int testnv0 = nv1;
  498. int testnv1 = NvStripifier::GetNextIndex(scratchIndices, nextFace);
  499. NvFaceInfo* nextNextFace = NvStripifier::FindOtherFace(edgeInfos, testnv0, testnv1, nextFace);
  500. if( (nextNextFace == NULL) || (IsMarked(nextNextFace)) )
  501. {
  502. //uh, oh, we're following a dead end, try swapping
  503. NvFaceInfo* testNextFace = NvStripifier::FindOtherFace(edgeInfos, nv0, testnv1, nextFace);
  504. if( ((testNextFace != NULL) && !IsMarked(testNextFace)) )
  505. {
  506. //we only swap if it buys us something
  507. //add a "fake" degenerate face
  508. NvFaceInfo* tempFace = new NvFaceInfo(nv0, nv1, nv0);
  509. forwardFaces.push_back(tempFace);
  510. MarkTriangle(tempFace);
  511. scratchIndices.push_back(nv0);
  512. testnv0 = nv0;
  513. ++m_numDegenerates;
  514. }
  515. }
  516. // add this to the strip
  517. forwardFaces.push_back(nextFace);
  518. MarkTriangle(nextFace);
  519. // add the index
  520. //nv0 = nv1;
  521. //nv1 = NvStripifier::GetNextIndex(scratchIndices, nextFace);
  522. scratchIndices.push_back(testnv1);
  523. // and get the next face
  524. nv0 = testnv0;
  525. nv1 = testnv1;
  526. nextFace = NvStripifier::FindOtherFace(edgeInfos, nv0, nv1, nextFace);
  527. }
  528. // tempAllFaces is going to be forwardFaces + backwardFaces
  529. // it's used for Unique()
  530. NvFaceInfoVec tempAllFaces;
  531. for(int i = 0; i < forwardFaces.size(); i++)
  532. tempAllFaces.push_back(forwardFaces[i]);
  533. //
  534. // reset the indices for building the strip backwards and do so
  535. //
  536. scratchIndices.resize(0);
  537. scratchIndices.push_back(v2);
  538. scratchIndices.push_back(v1);
  539. scratchIndices.push_back(v0);
  540. nv0 = v1;
  541. nv1 = v0;
  542. nextFace = NvStripifier::FindOtherFace(edgeInfos, nv0, nv1, m_startInfo.m_startFace);
  543. while (nextFace != NULL && !IsMarked(nextFace))
  544. {
  545. //this tests to see if a face is "unique", meaning that its vertices aren't already in the list
  546. // so, strips which "wrap-around" are not allowed
  547. if(!Unique(tempAllFaces, nextFace))
  548. break;
  549. //check to see if this next face is going to cause us to die soon
  550. int testnv0 = nv1;
  551. int testnv1 = NvStripifier::GetNextIndex(scratchIndices, nextFace);
  552. NvFaceInfo* nextNextFace = NvStripifier::FindOtherFace(edgeInfos, testnv0, testnv1, nextFace);
  553. if( (nextNextFace == NULL) || (IsMarked(nextNextFace)) )
  554. {
  555. //uh, oh, we're following a dead end, try swapping
  556. NvFaceInfo* testNextFace = NvStripifier::FindOtherFace(edgeInfos, nv0, testnv1, nextFace);
  557. if( ((testNextFace != NULL) && !IsMarked(testNextFace)) )
  558. {
  559. //we only swap if it buys us something
  560. //add a "fake" degenerate face
  561. NvFaceInfo* tempFace = new NvFaceInfo(nv0, nv1, nv0);
  562. backwardFaces.push_back(tempFace);
  563. MarkTriangle(tempFace);
  564. scratchIndices.push_back(nv0);
  565. testnv0 = nv0;
  566. ++m_numDegenerates;
  567. }
  568. }
  569. // add this to the strip
  570. backwardFaces.push_back(nextFace);
  571. //this is just so Unique() will work
  572. tempAllFaces.push_back(nextFace);
  573. MarkTriangle(nextFace);
  574. // add the index
  575. //nv0 = nv1;
  576. //nv1 = NvStripifier::GetNextIndex(scratchIndices, nextFace);
  577. scratchIndices.push_back(testnv1);
  578. // and get the next face
  579. nv0 = testnv0;
  580. nv1 = testnv1;
  581. nextFace = NvStripifier::FindOtherFace(edgeInfos, nv0, nv1, nextFace);
  582. }
  583. // Combine the forward and backwards stripification lists and put into our own face vector
  584. Combine(forwardFaces, backwardFaces);
  585. }
  586. ///////////////////////////////////////////////////////////////////////////////////////////
  587. // Combine()
  588. //
  589. // Combines the two input face vectors and puts the result into m_faces
  590. //
  591. void NvStripInfo::Combine(const NvFaceInfoVec &forward, const NvFaceInfoVec &backward){
  592. // add backward faces
  593. int numFaces = backward.size();
  594. for (int i = numFaces - 1; i >= 0; i--)
  595. m_faces.push_back(backward[i]);
  596. // add forward faces
  597. numFaces = forward.size();
  598. for (int i = 0; i < numFaces; i++)
  599. m_faces.push_back(forward[i]);
  600. }
  601. ///////////////////////////////////////////////////////////////////////////////////////////
  602. // SharesEdge()
  603. //
  604. // Returns true if the input face and the current strip share an edge
  605. //
  606. bool NvStripInfo::SharesEdge(const NvFaceInfo* faceInfo, NvEdgeInfoVec &edgeInfos)
  607. {
  608. //check v0->v1 edge
  609. NvEdgeInfo* currEdge = NvStripifier::FindEdgeInfo(edgeInfos, faceInfo->m_v0, faceInfo->m_v1);
  610. if(IsInStrip(currEdge->m_face0) || IsInStrip(currEdge->m_face1))
  611. return true;
  612. //check v1->v2 edge
  613. currEdge = NvStripifier::FindEdgeInfo(edgeInfos, faceInfo->m_v1, faceInfo->m_v2);
  614. if(IsInStrip(currEdge->m_face0) || IsInStrip(currEdge->m_face1))
  615. return true;
  616. //check v2->v0 edge
  617. currEdge = NvStripifier::FindEdgeInfo(edgeInfos, faceInfo->m_v2, faceInfo->m_v0);
  618. if(IsInStrip(currEdge->m_face0) || IsInStrip(currEdge->m_face1))
  619. return true;
  620. return false;
  621. }
  622. ///////////////////////////////////////////////////////////////////////////////////////////
  623. // CommitStrips()
  624. //
  625. // "Commits" the input strips by setting their m_experimentId to -1 and adding to the allStrips
  626. // vector
  627. //
  628. void NvStripifier::CommitStrips(NvStripInfoVec &allStrips, const NvStripInfoVec &strips)
  629. {
  630. // Iterate through strips
  631. int numStrips = strips.size();
  632. for (int i = 0; i < numStrips; i++){
  633. // Tell the strip that it is now real
  634. NvStripInfo *strip = strips[i];
  635. strip->m_experimentId = -1;
  636. // add to the list of real strips
  637. allStrips.push_back(strip);
  638. // Iterate through the faces of the strip
  639. // Tell the faces of the strip that they belong to a real strip now
  640. const NvFaceInfoVec &faces = strips[i]->m_faces;
  641. int numFaces = faces.size();
  642. for (int j = 0; j < numFaces; j++)
  643. {
  644. strip->MarkTriangle(faces[j]);
  645. }
  646. }
  647. }
  648. ///////////////////////////////////////////////////////////////////////////////////////////
  649. // FindTraversal()
  650. //
  651. // Finds the next face to start the next strip on.
  652. //
  653. bool NvStripifier::FindTraversal(NvFaceInfoVec &faceInfos,
  654. NvEdgeInfoVec &edgeInfos,
  655. NvStripInfo *strip,
  656. NvStripStartInfo &startInfo){
  657. // if the strip was v0->v1 on the edge, then v1 will be a vertex in the next edge.
  658. int v = (strip->m_startInfo.m_toV1 ? strip->m_startInfo.m_startEdge->m_v1 : strip->m_startInfo.m_startEdge->m_v0);
  659. NvFaceInfo *untouchedFace = NULL;
  660. NvEdgeInfo *edgeIter = edgeInfos[v];
  661. while (edgeIter != NULL){
  662. NvFaceInfo *face0 = edgeIter->m_face0;
  663. NvFaceInfo *face1 = edgeIter->m_face1;
  664. if ((face0 != NULL && !strip->IsInStrip(face0)) && face1 != NULL && !strip->IsMarked(face1))
  665. {
  666. untouchedFace = face1;
  667. break;
  668. }
  669. if ((face1 != NULL && !strip->IsInStrip(face1)) && face0 != NULL && !strip->IsMarked(face0)){
  670. untouchedFace = face0;
  671. break;
  672. }
  673. // find the next edgeIter
  674. edgeIter = (edgeIter->m_v0 == v ? edgeIter->m_nextV0 : edgeIter->m_nextV1);
  675. }
  676. startInfo.m_startFace = untouchedFace;
  677. startInfo.m_startEdge = edgeIter;
  678. if (edgeIter != NULL)
  679. {
  680. if(strip->SharesEdge(startInfo.m_startFace, edgeInfos))
  681. startInfo.m_toV1 = (edgeIter->m_v0 == v); //note! used to be m_v1
  682. else
  683. startInfo.m_toV1 = (edgeIter->m_v1 == v);
  684. }
  685. return (startInfo.m_startFace != NULL);
  686. }
  687. ////////////////////////////////////////////////////////////////////////////////////////
  688. // RemoveSmallStrips()
  689. //
  690. // allStrips is the whole strip vector...all small strips will be deleted from this list, to avoid leaking mem
  691. // allBigStrips is an out parameter which will contain all strips above minStripLength
  692. // faceList is an out parameter which will contain all faces which were removed from the striplist
  693. //
  694. void NvStripifier::RemoveSmallStrips(NvStripInfoVec& allStrips, NvStripInfoVec& allBigStrips, NvFaceInfoVec& faceList)
  695. {
  696. faceList.clear();
  697. allBigStrips.clear(); //make sure these are empty
  698. NvFaceInfoVec tempFaceList;
  699. for(int i = 0; i < allStrips.size(); i++)
  700. {
  701. if(allStrips[i]->m_faces.size() < minStripLength)
  702. {
  703. //strip is too small, add faces to faceList
  704. for(int j = 0; j < allStrips[i]->m_faces.size(); j++)
  705. tempFaceList.push_back(allStrips[i]->m_faces[j]);
  706. //and free memory
  707. delete allStrips[i];
  708. }
  709. else
  710. {
  711. allBigStrips.push_back(allStrips[i]);
  712. }
  713. }
  714. bool *bVisitedList = new bool[tempFaceList.size()];
  715. memset(bVisitedList, 0, tempFaceList.size()*sizeof(bool));
  716. VertexCache* vcache = new VertexCache(cacheSize);
  717. int bestNumHits = -1;
  718. int numHits;
  719. int bestIndex = 0;
  720. while(1)
  721. {
  722. bestNumHits = -1;
  723. //find best face to add next, given the current cache
  724. for(int i = 0; i < tempFaceList.size(); i++)
  725. {
  726. if(bVisitedList[i])
  727. continue;
  728. numHits = CalcNumHitsFace(vcache, tempFaceList[i]);
  729. if(numHits > bestNumHits)
  730. {
  731. bestNumHits = numHits;
  732. bestIndex = i;
  733. }
  734. }
  735. if(bestNumHits == -1.0f)
  736. break;
  737. bVisitedList[bestIndex] = true;
  738. UpdateCacheFace(vcache, tempFaceList[bestIndex]);
  739. faceList.push_back(tempFaceList[bestIndex]);
  740. }
  741. delete vcache;
  742. delete[] bVisitedList;
  743. }
  744. ///////////////////////////////////////////////////////////////////////////////////////////
  745. // NextIsCW()
  746. //
  747. // Returns true if the next face should be ordered in CW fashion
  748. //
  749. bool NvStripifier::NextIsCW(const int numIndices)
  750. {
  751. return ((numIndices % 2) == 0);
  752. }
  753. ///////////////////////////////////////////////////////////////////////////////////////////
  754. // IsCW()
  755. //
  756. // Returns true if the face is ordered in CW fashion
  757. //
  758. bool NvStripifier::IsCW(NvFaceInfo *faceInfo, int v0, int v1)
  759. {
  760. if (faceInfo->m_v0 == v0)
  761. return (faceInfo->m_v1 == v1);
  762. else if (faceInfo->m_v1 == v0)
  763. return (faceInfo->m_v2 == v1);
  764. else
  765. return (faceInfo->m_v0 == v1);
  766. // shouldn't get here
  767. assert(0);
  768. return false;
  769. }
  770. bool NvStripifier::FaceContainsIndex(const NvFaceInfo& face, const unsigned int index)
  771. {
  772. return ( (face.m_v0 == (int)index) || (face.m_v1 == (int)index) || (face.m_v2 == (int)index) );
  773. }
  774. bool NvStripifier::IsMoneyFace(const NvFaceInfo& face)
  775. {
  776. if(FaceContainsIndex(face, 800) &&
  777. FaceContainsIndex(face, 812) &&
  778. FaceContainsIndex(face, 731))
  779. return true;
  780. return false;
  781. }
  782. ////////////////////////////////////////////////////////////////////////////////////////
  783. // CreateStrips()
  784. //
  785. // Generates actual strips from the list-in-strip-order.
  786. //
  787. void NvStripifier::CreateStrips(const NvStripInfoVec& allStrips, IntVec& stripIndices,
  788. const bool bStitchStrips, unsigned int& numSeparateStrips)
  789. {
  790. assert(numSeparateStrips == 0);
  791. NvFaceInfo tLastFace(0, 0, 0);
  792. NvFaceInfo tPrevStripLastFace(0, 0, 0);
  793. int nStripCount = allStrips.size();
  794. assert(nStripCount > 0);
  795. //we infer the cw/ccw ordering depending on the number of indices
  796. //this is screwed up by the fact that we insert -1s to denote changing strips
  797. //this is to account for that
  798. int accountForNegatives = 0;
  799. for (int i = 0; i < nStripCount; i++)
  800. {
  801. NvStripInfo *strip = allStrips[i];
  802. int nStripFaceCount = strip->m_faces.size();
  803. assert(nStripFaceCount > 0);
  804. // Handle the first face in the strip
  805. {
  806. NvFaceInfo tFirstFace(strip->m_faces[0]->m_v0, strip->m_faces[0]->m_v1, strip->m_faces[0]->m_v2);
  807. // If there is a second face, reorder vertices such that the
  808. // unique vertex is first
  809. if (nStripFaceCount > 1)
  810. {
  811. int nUnique = NvStripifier::GetUniqueVertexInB(strip->m_faces[1], &tFirstFace);
  812. if (nUnique == tFirstFace.m_v1)
  813. {
  814. SWAP(tFirstFace.m_v0, tFirstFace.m_v1);
  815. }
  816. else if (nUnique == tFirstFace.m_v2)
  817. {
  818. SWAP(tFirstFace.m_v0, tFirstFace.m_v2);
  819. }
  820. // If there is a third face, reorder vertices such that the
  821. // shared vertex is last
  822. if (nStripFaceCount > 2)
  823. {
  824. if(IsDegenerate(strip->m_faces[1]))
  825. {
  826. int pivot = strip->m_faces[1]->m_v1;
  827. if(tFirstFace.m_v1 == pivot)
  828. {
  829. SWAP(tFirstFace.m_v1, tFirstFace.m_v2);
  830. }
  831. }
  832. else
  833. {
  834. int nShared0, nShared1;
  835. GetSharedVertices(strip->m_faces[2], &tFirstFace, &nShared0, &nShared1);
  836. if ( (nShared0 == tFirstFace.m_v1) && (nShared1 == -1) )
  837. {
  838. SWAP(tFirstFace.m_v1, tFirstFace.m_v2);
  839. }
  840. }
  841. }
  842. }
  843. if( (i == 0) || !bStitchStrips)
  844. {
  845. if(!IsCW(strip->m_faces[0], tFirstFace.m_v0, tFirstFace.m_v1))
  846. stripIndices.push_back(tFirstFace.m_v0);
  847. }
  848. else
  849. {
  850. // Double tap the first in the new strip
  851. stripIndices.push_back(tFirstFace.m_v0);
  852. // Check CW/CCW ordering
  853. if (NextIsCW(stripIndices.size() - accountForNegatives) != IsCW(strip->m_faces[0], tFirstFace.m_v0, tFirstFace.m_v1))
  854. {
  855. stripIndices.push_back(tFirstFace.m_v0);
  856. }
  857. }
  858. stripIndices.push_back(tFirstFace.m_v0);
  859. stripIndices.push_back(tFirstFace.m_v1);
  860. stripIndices.push_back(tFirstFace.m_v2);
  861. // Update last face info
  862. tLastFace = tFirstFace;
  863. }
  864. for (int j = 1; j < nStripFaceCount; j++)
  865. {
  866. int nUnique = GetUniqueVertexInB(&tLastFace, strip->m_faces[j]);
  867. if (nUnique != -1)
  868. {
  869. stripIndices.push_back(nUnique);
  870. // Update last face info
  871. tLastFace.m_v0 = tLastFace.m_v1;
  872. tLastFace.m_v1 = tLastFace.m_v2;
  873. tLastFace.m_v2 = nUnique;
  874. }
  875. else
  876. {
  877. //we've hit a degenerate
  878. stripIndices.push_back(strip->m_faces[j]->m_v2);
  879. tLastFace.m_v0 = strip->m_faces[j]->m_v0;//tLastFace.m_v1;
  880. tLastFace.m_v1 = strip->m_faces[j]->m_v1;//tLastFace.m_v2;
  881. tLastFace.m_v2 = strip->m_faces[j]->m_v2;//tLastFace.m_v1;
  882. }
  883. }
  884. // Double tap between strips.
  885. if(bStitchStrips)
  886. {
  887. if(i != nStripCount - 1)
  888. stripIndices.push_back(tLastFace.m_v2);
  889. }
  890. else
  891. {
  892. //-1 index indicates next strip
  893. stripIndices.push_back(-1);
  894. accountForNegatives++;
  895. numSeparateStrips++;
  896. }
  897. // Update last face info
  898. tLastFace.m_v0 = tLastFace.m_v1;
  899. tLastFace.m_v1 = tLastFace.m_v2;
  900. tLastFace.m_v2 = tLastFace.m_v2;
  901. }
  902. if(bStitchStrips)
  903. numSeparateStrips = 1;
  904. }
  905. ///////////////////////////////////////////////////////////////////////////////////////////
  906. // Stripify()
  907. //
  908. //
  909. // in_indices are the input indices of the mesh to stripify
  910. // in_cacheSize is the target cache size
  911. //
  912. void NvStripifier::Stripify(const WordVec &in_indices, const int in_cacheSize,
  913. const int in_minStripLength, const unsigned short maxIndex,
  914. NvStripInfoVec &outStrips, NvFaceInfoVec& outFaceList)
  915. {
  916. meshJump = 0.0f;
  917. bFirstTimeResetPoint = true; //used in FindGoodResetPoint()
  918. //the number of times to run the experiments
  919. int numSamples = 10;
  920. //the cache size, clamped to one
  921. cacheSize = max(1, in_cacheSize - CACHE_INEFFICIENCY);
  922. minStripLength = in_minStripLength; //this is the strip size threshold below which we dump the strip into a list
  923. indices = in_indices;
  924. // build the stripification info
  925. NvFaceInfoVec allFaceInfos;
  926. NvEdgeInfoVec allEdgeInfos;
  927. BuildStripifyInfo(allFaceInfos, allEdgeInfos, maxIndex);
  928. NvStripInfoVec allStrips;
  929. // stripify
  930. FindAllStrips(allStrips, allFaceInfos, allEdgeInfos, numSamples);
  931. //split up the strips into cache friendly pieces, optimize them, then dump these into outStrips
  932. SplitUpStripsAndOptimize(allStrips, outStrips, allEdgeInfos, outFaceList);
  933. //clean up
  934. for(int i = 0; i < allStrips.size(); i++)
  935. {
  936. delete allStrips[i];
  937. }
  938. for (int i = 0; i < allEdgeInfos.size(); i++)
  939. {
  940. NvEdgeInfo *info = allEdgeInfos[i];
  941. while (info != NULL)
  942. {
  943. NvEdgeInfo *next = (info->m_v0 == i ? info->m_nextV0 : info->m_nextV1);
  944. info->Unref();
  945. info = next;
  946. }
  947. }
  948. }
  949. bool NvStripifier::IsDegenerate(const NvFaceInfo* face)
  950. {
  951. if(face->m_v0 == face->m_v1)
  952. return true;
  953. else if(face->m_v0 == face->m_v2)
  954. return true;
  955. else if(face->m_v1 == face->m_v2)
  956. return true;
  957. else
  958. return false;
  959. }
  960. bool NvStripifier::IsDegenerate(const unsigned short v0, const unsigned short v1, const unsigned short v2)
  961. {
  962. if(v0 == v1)
  963. return true;
  964. else if(v0 == v2)
  965. return true;
  966. else if(v1 == v2)
  967. return true;
  968. else
  969. return false;
  970. }
  971. ///////////////////////////////////////////////////////////////////////////////////////////
  972. // SplitUpStripsAndOptimize()
  973. //
  974. // Splits the input vector of strips (allBigStrips) into smaller, cache friendly pieces, then
  975. // reorders these pieces to maximize cache hits
  976. // The final strips are output through outStrips
  977. //
  978. void NvStripifier::SplitUpStripsAndOptimize(NvStripInfoVec &allStrips, NvStripInfoVec &outStrips,
  979. NvEdgeInfoVec& edgeInfos, NvFaceInfoVec& outFaceList)
  980. {
  981. int threshold = cacheSize;
  982. NvStripInfoVec tempStrips;
  983. //split up strips into threshold-sized pieces
  984. for(int i = 0; i < allStrips.size(); i++)
  985. {
  986. NvStripInfo* currentStrip;
  987. NvStripStartInfo startInfo(NULL, NULL, false);
  988. int actualStripSize = 0;
  989. for(int j = 0; j < allStrips[i]->m_faces.size(); ++j)
  990. {
  991. if( !IsDegenerate(allStrips[i]->m_faces[j]) )
  992. actualStripSize++;
  993. }
  994. if(actualStripSize /*allStrips[i]->m_faces.size()*/ > threshold)
  995. {
  996. int numTimes = actualStripSize /*allStrips[i]->m_faces.size()*/ / threshold;
  997. int numLeftover = actualStripSize /*allStrips[i]->m_faces.size()*/ % threshold;
  998. int degenerateCount = 0;
  999. int j = 0;
  1000. for(j; j < numTimes; j++)
  1001. {
  1002. currentStrip = new NvStripInfo(startInfo, 0, -1);
  1003. int faceCtr = j*threshold + degenerateCount;
  1004. bool bFirstTime = true;
  1005. while(faceCtr < threshold+(j*threshold)+degenerateCount)
  1006. {
  1007. if(IsDegenerate(allStrips[i]->m_faces[faceCtr]))
  1008. {
  1009. degenerateCount++;
  1010. //last time or first time through, no need for a degenerate
  1011. if( (((faceCtr + 1) != threshold+(j*threshold)+degenerateCount) ||
  1012. ((j == numTimes - 1) && (numLeftover < 4) && (numLeftover > 0))) &&
  1013. !bFirstTime)
  1014. {
  1015. currentStrip->m_faces.push_back(allStrips[i]->m_faces[faceCtr++]);
  1016. }
  1017. else
  1018. ++faceCtr;
  1019. }
  1020. else
  1021. {
  1022. currentStrip->m_faces.push_back(allStrips[i]->m_faces[faceCtr++]);
  1023. bFirstTime = false;
  1024. }
  1025. }
  1026. /*
  1027. for(int faceCtr = j*threshold; faceCtr < threshold+(j*threshold); faceCtr++)
  1028. {
  1029. currentStrip->m_faces.push_back(allStrips[i]->m_faces[faceCtr]);
  1030. }
  1031. */
  1032. ///*
  1033. if(j == numTimes - 1) //last time through
  1034. {
  1035. if( (numLeftover < 4) && (numLeftover > 0) ) //way too small
  1036. {
  1037. //just add to last strip
  1038. int ctr = 0;
  1039. while(ctr < numLeftover)
  1040. {
  1041. if(!IsDegenerate(allStrips[i]->m_faces[faceCtr]))
  1042. {
  1043. currentStrip->m_faces.push_back(allStrips[i]->m_faces[faceCtr++]);
  1044. ++ctr;
  1045. }
  1046. else
  1047. {
  1048. currentStrip->m_faces.push_back(allStrips[i]->m_faces[faceCtr++]);
  1049. ++degenerateCount;
  1050. }
  1051. }
  1052. numLeftover = 0;
  1053. }
  1054. }
  1055. //*/
  1056. tempStrips.push_back(currentStrip);
  1057. }
  1058. int leftOff = j * threshold + degenerateCount;
  1059. if(numLeftover != 0)
  1060. {
  1061. currentStrip = new NvStripInfo(startInfo, 0, -1);
  1062. int ctr = 0;
  1063. bool bFirstTime = true;
  1064. while(ctr < numLeftover)
  1065. {
  1066. if( !IsDegenerate(allStrips[i]->m_faces[leftOff]) )
  1067. {
  1068. ctr++;
  1069. bFirstTime = false;
  1070. currentStrip->m_faces.push_back(allStrips[i]->m_faces[leftOff++]);
  1071. }
  1072. else if(!bFirstTime)
  1073. currentStrip->m_faces.push_back(allStrips[i]->m_faces[leftOff++]);
  1074. else
  1075. leftOff++;
  1076. }
  1077. /*
  1078. for(int k = 0; k < numLeftover; k++)
  1079. {
  1080. currentStrip->m_faces.push_back(allStrips[i]->m_faces[leftOff++]);
  1081. }
  1082. */
  1083. tempStrips.push_back(currentStrip);
  1084. }
  1085. }
  1086. else
  1087. {
  1088. //we're not just doing a tempStrips.push_back(allBigStrips[i]) because
  1089. // this way we can delete allBigStrips later to free the memory
  1090. currentStrip = new NvStripInfo(startInfo, 0, -1);
  1091. for(int j = 0; j < allStrips[i]->m_faces.size(); j++)
  1092. currentStrip->m_faces.push_back(allStrips[i]->m_faces[j]);
  1093. tempStrips.push_back(currentStrip);
  1094. }
  1095. }
  1096. //add small strips to face list
  1097. NvStripInfoVec tempStrips2;
  1098. RemoveSmallStrips(tempStrips, tempStrips2, outFaceList);
  1099. outStrips.clear();
  1100. //screw optimization for now
  1101. // for(i = 0; i < tempStrips.size(); ++i)
  1102. // outStrips.push_back(tempStrips[i]);
  1103. if(tempStrips2.size() != 0)
  1104. {
  1105. //Optimize for the vertex cache
  1106. VertexCache* vcache = new VertexCache(cacheSize);
  1107. float bestNumHits = -1.0f;
  1108. float numHits;
  1109. int bestIndex = 0;
  1110. int firstIndex = 0;
  1111. float minCost = 10000.0f;
  1112. for(int i = 0; i < tempStrips2.size(); i++)
  1113. {
  1114. int numNeighbors = 0;
  1115. //find strip with least number of neighbors per face
  1116. for(int j = 0; j < tempStrips2[i]->m_faces.size(); j++)
  1117. {
  1118. numNeighbors += NumNeighbors(tempStrips2[i]->m_faces[j], edgeInfos);
  1119. }
  1120. float currCost = (float)numNeighbors / (float)tempStrips2[i]->m_faces.size();
  1121. if(currCost < minCost)
  1122. {
  1123. minCost = currCost;
  1124. firstIndex = i;
  1125. }
  1126. }
  1127. UpdateCacheStrip(vcache, tempStrips2[firstIndex]);
  1128. outStrips.push_back(tempStrips2[firstIndex]);
  1129. tempStrips2[firstIndex]->visited = true;
  1130. bool bWantsCW = (tempStrips2[firstIndex]->m_faces.size() % 2) == 0;
  1131. //this n^2 algo is what slows down stripification so much....
  1132. // needs to be improved
  1133. while(1)
  1134. {
  1135. bestNumHits = -1.0f;
  1136. //find best strip to add next, given the current cache
  1137. for(int i = 0; i < tempStrips2.size(); i++)
  1138. {
  1139. if(tempStrips2[i]->visited)
  1140. continue;
  1141. numHits = CalcNumHitsStrip(vcache, tempStrips2[i]);
  1142. if(numHits > bestNumHits)
  1143. {
  1144. bestNumHits = numHits;
  1145. bestIndex = i;
  1146. }
  1147. else if(numHits >= bestNumHits)
  1148. {
  1149. //check previous strip to see if this one requires it to switch polarity
  1150. NvStripInfo *strip = tempStrips2[i];
  1151. int nStripFaceCount = strip->m_faces.size();
  1152. NvFaceInfo tFirstFace(strip->m_faces[0]->m_v0, strip->m_faces[0]->m_v1, strip->m_faces[0]->m_v2);
  1153. // If there is a second face, reorder vertices such that the
  1154. // unique vertex is first
  1155. if (nStripFaceCount > 1)
  1156. {
  1157. int nUnique = NvStripifier::GetUniqueVertexInB(strip->m_faces[1], &tFirstFace);
  1158. if (nUnique == tFirstFace.m_v1)
  1159. {
  1160. SWAP(tFirstFace.m_v0, tFirstFace.m_v1);
  1161. }
  1162. else if (nUnique == tFirstFace.m_v2)
  1163. {
  1164. SWAP(tFirstFace.m_v0, tFirstFace.m_v2);
  1165. }
  1166. // If there is a third face, reorder vertices such that the
  1167. // shared vertex is last
  1168. if (nStripFaceCount > 2)
  1169. {
  1170. int nShared0, nShared1;
  1171. GetSharedVertices(strip->m_faces[2], &tFirstFace, &nShared0, &nShared1);
  1172. if ( (nShared0 == tFirstFace.m_v1) && (nShared1 == -1) )
  1173. {
  1174. SWAP(tFirstFace.m_v1, tFirstFace.m_v2);
  1175. }
  1176. }
  1177. }
  1178. // Check CW/CCW ordering
  1179. if (bWantsCW == IsCW(strip->m_faces[0], tFirstFace.m_v0, tFirstFace.m_v1))
  1180. {
  1181. //I like this one!
  1182. bestIndex = i;
  1183. }
  1184. }
  1185. }
  1186. if(bestNumHits == -1.0f)
  1187. break;
  1188. tempStrips2[bestIndex]->visited = true;
  1189. UpdateCacheStrip(vcache, tempStrips2[bestIndex]);
  1190. outStrips.push_back(tempStrips2[bestIndex]);
  1191. bWantsCW = (tempStrips2[bestIndex]->m_faces.size() % 2 == 0) ? bWantsCW : !bWantsCW;
  1192. }
  1193. delete vcache;
  1194. }
  1195. }
  1196. ///////////////////////////////////////////////////////////////////////////////////////////
  1197. // UpdateCacheStrip()
  1198. //
  1199. // Updates the input vertex cache with this strip's vertices
  1200. //
  1201. void NvStripifier::UpdateCacheStrip(VertexCache* vcache, NvStripInfo* strip)
  1202. {
  1203. for(int i = 0; i < strip->m_faces.size(); ++i)
  1204. {
  1205. if(!vcache->InCache(strip->m_faces[i]->m_v0))
  1206. vcache->AddEntry(strip->m_faces[i]->m_v0);
  1207. if(!vcache->InCache(strip->m_faces[i]->m_v1))
  1208. vcache->AddEntry(strip->m_faces[i]->m_v1);
  1209. if(!vcache->InCache(strip->m_faces[i]->m_v2))
  1210. vcache->AddEntry(strip->m_faces[i]->m_v2);
  1211. }
  1212. }
  1213. ///////////////////////////////////////////////////////////////////////////////////////////
  1214. // UpdateCacheFace()
  1215. //
  1216. // Updates the input vertex cache with this face's vertices
  1217. //
  1218. void NvStripifier::UpdateCacheFace(VertexCache* vcache, NvFaceInfo* face)
  1219. {
  1220. if(!vcache->InCache(face->m_v0))
  1221. vcache->AddEntry(face->m_v0);
  1222. if(!vcache->InCache(face->m_v1))
  1223. vcache->AddEntry(face->m_v1);
  1224. if(!vcache->InCache(face->m_v2))
  1225. vcache->AddEntry(face->m_v2);
  1226. }
  1227. ///////////////////////////////////////////////////////////////////////////////////////////
  1228. // CalcNumHitsStrip()
  1229. //
  1230. // returns the number of cache hits per face in the strip
  1231. //
  1232. float NvStripifier::CalcNumHitsStrip(VertexCache* vcache, NvStripInfo* strip)
  1233. {
  1234. int numHits = 0;
  1235. int numFaces = 0;
  1236. for(int i = 0; i < strip->m_faces.size(); i++)
  1237. {
  1238. if(vcache->InCache(strip->m_faces[i]->m_v0))
  1239. ++numHits;
  1240. if(vcache->InCache(strip->m_faces[i]->m_v1))
  1241. ++numHits;
  1242. if(vcache->InCache(strip->m_faces[i]->m_v2))
  1243. ++numHits;
  1244. numFaces++;
  1245. }
  1246. return ((float)numHits / (float)numFaces);
  1247. }
  1248. ///////////////////////////////////////////////////////////////////////////////////////////
  1249. // CalcNumHitsFace()
  1250. //
  1251. // returns the number of cache hits in the face
  1252. //
  1253. int NvStripifier::CalcNumHitsFace(VertexCache* vcache, NvFaceInfo* face)
  1254. {
  1255. int numHits = 0;
  1256. if(vcache->InCache(face->m_v0))
  1257. numHits++;
  1258. if(vcache->InCache(face->m_v1))
  1259. numHits++;
  1260. if(vcache->InCache(face->m_v2))
  1261. numHits++;
  1262. return numHits;
  1263. }
  1264. ///////////////////////////////////////////////////////////////////////////////////////////
  1265. // NumNeighbors()
  1266. //
  1267. // Returns the number of neighbors that this face has
  1268. //
  1269. int NvStripifier::NumNeighbors(NvFaceInfo* face, NvEdgeInfoVec& edgeInfoVec)
  1270. {
  1271. int numNeighbors = 0;
  1272. if(FindOtherFace(edgeInfoVec, face->m_v0, face->m_v1, face) != NULL)
  1273. {
  1274. numNeighbors++;
  1275. }
  1276. if(FindOtherFace(edgeInfoVec, face->m_v1, face->m_v2, face) != NULL)
  1277. {
  1278. numNeighbors++;
  1279. }
  1280. if(FindOtherFace(edgeInfoVec, face->m_v2, face->m_v0, face) != NULL)
  1281. {
  1282. numNeighbors++;
  1283. }
  1284. return numNeighbors;
  1285. }
  1286. ///////////////////////////////////////////////////////////////////////////////////////////
  1287. // AvgStripSize()
  1288. //
  1289. // Finds the average strip size of the input vector of strips
  1290. //
  1291. float NvStripifier::AvgStripSize(const NvStripInfoVec &strips){
  1292. int sizeAccum = 0;
  1293. int numStrips = strips.size();
  1294. for (int i = 0; i < numStrips; i++){
  1295. NvStripInfo *strip = strips[i];
  1296. sizeAccum += strip->m_faces.size();
  1297. sizeAccum -= strip->m_numDegenerates;
  1298. }
  1299. return ((float)sizeAccum) / ((float)numStrips);
  1300. }
  1301. ///////////////////////////////////////////////////////////////////////////////////////////
  1302. // FindAllStrips()
  1303. //
  1304. // Does the stripification, puts output strips into vector allStrips
  1305. //
  1306. // Works by setting runnning a number of experiments in different areas of the mesh, and
  1307. // accepting the one which results in the longest strips. It then accepts this, and moves
  1308. // on to a different area of the mesh. We try to jump around the mesh some, to ensure that
  1309. // large open spans of strips get generated.
  1310. //
  1311. void NvStripifier::FindAllStrips(NvStripInfoVec &allStrips,
  1312. NvFaceInfoVec &allFaceInfos,
  1313. NvEdgeInfoVec &allEdgeInfos,
  1314. int numSamples){
  1315. // the experiments
  1316. int experimentId = 0;
  1317. int stripId = 0;
  1318. bool done = false;
  1319. int loopCtr = 0;
  1320. while (!done)
  1321. {
  1322. loopCtr++;
  1323. //
  1324. // PHASE 1: Set up numSamples * numEdges experiments
  1325. //
  1326. NvStripInfoVec *experiments = new NvStripInfoVec [numSamples * 6];
  1327. int experimentIndex = 0;
  1328. std::set <NvFaceInfo*> resetPoints;
  1329. for (int i = 0; i < numSamples; i++)
  1330. {
  1331. // Try to find another good reset point.
  1332. // If there are none to be found, we are done
  1333. NvFaceInfo *nextFace = FindGoodResetPoint(allFaceInfos, allEdgeInfos);
  1334. if (nextFace == NULL){
  1335. done = true;
  1336. break;
  1337. }
  1338. // If we have already evaluated starting at this face in this slew
  1339. // of experiments, then skip going any further
  1340. else if (resetPoints.find(nextFace) != resetPoints.end()){
  1341. continue;
  1342. }
  1343. // trying it now...
  1344. resetPoints.insert(nextFace);
  1345. // otherwise, we shall now try experiments for starting on the 01,12, and 20 edges
  1346. assert(nextFace->m_stripId < 0);
  1347. // build the strip off of this face's 0-1 edge
  1348. NvEdgeInfo *edge01 = FindEdgeInfo(allEdgeInfos, nextFace->m_v0, nextFace->m_v1);
  1349. NvStripInfo *strip01 = new NvStripInfo(NvStripStartInfo(nextFace, edge01, true), stripId++, experimentId++);
  1350. experiments[experimentIndex++].push_back(strip01);
  1351. // build the strip off of this face's 1-0 edge
  1352. NvEdgeInfo *edge10 = FindEdgeInfo(allEdgeInfos, nextFace->m_v0, nextFace->m_v1);
  1353. NvStripInfo *strip10 = new NvStripInfo(NvStripStartInfo(nextFace, edge10, false), stripId++, experimentId++);
  1354. experiments[experimentIndex++].push_back(strip10);
  1355. // build the strip off of this face's 1-2 edge
  1356. NvEdgeInfo *edge12 = FindEdgeInfo(allEdgeInfos, nextFace->m_v1, nextFace->m_v2);
  1357. NvStripInfo *strip12 = new NvStripInfo(NvStripStartInfo(nextFace, edge12, true), stripId++, experimentId++);
  1358. experiments[experimentIndex++].push_back(strip12);
  1359. // build the strip off of this face's 2-1 edge
  1360. NvEdgeInfo *edge21 = FindEdgeInfo(allEdgeInfos, nextFace->m_v1, nextFace->m_v2);
  1361. NvStripInfo *strip21 = new NvStripInfo(NvStripStartInfo(nextFace, edge21, false), stripId++, experimentId++);
  1362. experiments[experimentIndex++].push_back(strip21);
  1363. // build the strip off of this face's 2-0 edge
  1364. NvEdgeInfo *edge20 = FindEdgeInfo(allEdgeInfos, nextFace->m_v2, nextFace->m_v0);
  1365. NvStripInfo *strip20 = new NvStripInfo(NvStripStartInfo(nextFace, edge20, true), stripId++, experimentId++);
  1366. experiments[experimentIndex++].push_back(strip20);
  1367. // build the strip off of this face's 0-2 edge
  1368. NvEdgeInfo *edge02 = FindEdgeInfo(allEdgeInfos, nextFace->m_v2, nextFace->m_v0);
  1369. NvStripInfo *strip02 = new NvStripInfo(NvStripStartInfo(nextFace, edge02, false), stripId++, experimentId++);
  1370. experiments[experimentIndex++].push_back(strip02);
  1371. }
  1372. //
  1373. // PHASE 2: Iterate through that we setup in the last phase
  1374. // and really build each of the strips and strips that follow to see how
  1375. // far we get
  1376. //
  1377. int numExperiments = experimentIndex;
  1378. for (int i = 0; i < numExperiments; i++){
  1379. // get the strip set
  1380. // build the first strip of the list
  1381. experiments[i][0]->Build(allEdgeInfos, allFaceInfos);
  1382. int experimentId = experiments[i][0]->m_experimentId;
  1383. NvStripInfo *stripIter = experiments[i][0];
  1384. NvStripStartInfo startInfo(NULL, NULL, false);
  1385. while (FindTraversal(allFaceInfos, allEdgeInfos, stripIter, startInfo)){
  1386. // create the new strip info
  1387. stripIter = new NvStripInfo(startInfo, stripId++, experimentId);
  1388. // build the next strip
  1389. stripIter->Build(allEdgeInfos, allFaceInfos);
  1390. // add it to the list
  1391. experiments[i].push_back(stripIter);
  1392. }
  1393. }
  1394. //
  1395. // Phase 3: Find the experiment that has the most promise
  1396. //
  1397. int bestIndex = 0;
  1398. double bestValue = 0;
  1399. for (int i = 0; i < numExperiments; i++)
  1400. {
  1401. const float avgStripSizeWeight = 1.0f;
  1402. // const float numTrisWeight = 0.0f;
  1403. const float numStripsWeight = 0.0f;
  1404. float avgStripSize = AvgStripSize(experiments[i]);
  1405. float numStrips = (float) experiments[i].size();
  1406. float value = avgStripSize * avgStripSizeWeight + (numStrips * numStripsWeight);
  1407. //float value = 1.f / numStrips;
  1408. //float value = numStrips * avgStripSize;
  1409. if (value > bestValue)
  1410. {
  1411. bestValue = value;
  1412. bestIndex = i;
  1413. }
  1414. }
  1415. //
  1416. // Phase 4: commit the best experiment of the bunch
  1417. //
  1418. CommitStrips(allStrips, experiments[bestIndex]);
  1419. // and destroy all of the others
  1420. for (int i = 0; i < numExperiments; i++)
  1421. {
  1422. if (i != bestIndex)
  1423. {
  1424. int numStrips = experiments[i].size();
  1425. for (int j = 0; j < numStrips; j++)
  1426. {
  1427. delete experiments[i][j];
  1428. }
  1429. }
  1430. }
  1431. // delete the array that we used for all experiments
  1432. delete [] experiments;
  1433. }
  1434. }
  1435. ///////////////////////////////////////////////////////////////////////////////////////////
  1436. // CountRemainingTris()
  1437. //
  1438. // This will count the number of triangles left in the
  1439. // strip list starting at iter and finishing up at end
  1440. //
  1441. int NvStripifier::CountRemainingTris(std::list<NvStripInfo*>::iterator iter,
  1442. std::list<NvStripInfo*>::iterator end){
  1443. int count = 0;
  1444. while (iter != end){
  1445. count += (*iter)->m_faces.size();
  1446. iter++;
  1447. }
  1448. return count;
  1449. }