nvtristrip-ruby 0.5.0

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