nvtristrip-ruby 0.5.0

Sign up to get free protection for your applications and to get access to all the features.
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
+