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/README +50 -0
- data/README.nvtristrip +32 -0
- data/Rakefile +76 -0
- data/TODO +7 -0
- data/ext/NvTriStrip.cpp +501 -0
- data/ext/NvTriStrip.h +145 -0
- data/ext/NvTriStripObjects.cpp +1773 -0
- data/ext/NvTriStripObjects.h +248 -0
- data/ext/RbTriStrip.cpp +324 -0
- data/ext/VertexCache.h +81 -0
- data/ext/extconf.rb +5 -0
- data/setup.rb +1585 -0
- data/test/test_nvtristrip.rb +46 -0
- metadata +59 -0
@@ -0,0 +1,248 @@
|
|
1
|
+
|
2
|
+
#ifndef NV_TRISTRIP_OBJECTS_H
|
3
|
+
#define NV_TRISTRIP_OBJECTS_H
|
4
|
+
|
5
|
+
#include <assert.h>
|
6
|
+
|
7
|
+
#include <stdint.h>
|
8
|
+
#define UINT uint32_t
|
9
|
+
#define WORD uint16_t
|
10
|
+
|
11
|
+
#include <vector>
|
12
|
+
#include <list>
|
13
|
+
#include "VertexCache.h"
|
14
|
+
|
15
|
+
/////////////////////////////////////////////////////////////////////////////////
|
16
|
+
//
|
17
|
+
// Types defined for stripification
|
18
|
+
//
|
19
|
+
/////////////////////////////////////////////////////////////////////////////////
|
20
|
+
|
21
|
+
struct MyVertex {
|
22
|
+
float x, y, z;
|
23
|
+
float nx, ny, nz;
|
24
|
+
};
|
25
|
+
|
26
|
+
typedef MyVertex MyVector;
|
27
|
+
|
28
|
+
struct MyFace {
|
29
|
+
int v1, v2, v3;
|
30
|
+
float nx, ny, nz;
|
31
|
+
};
|
32
|
+
|
33
|
+
|
34
|
+
class NvFaceInfo {
|
35
|
+
public:
|
36
|
+
|
37
|
+
// vertex indices
|
38
|
+
NvFaceInfo(int v0, int v1, int v2, bool bIsFake = false){
|
39
|
+
m_v0 = v0; m_v1 = v1; m_v2 = v2;
|
40
|
+
m_stripId = -1;
|
41
|
+
m_testStripId = -1;
|
42
|
+
m_experimentId = -1;
|
43
|
+
m_bIsFake = bIsFake;
|
44
|
+
}
|
45
|
+
|
46
|
+
// data members are left public
|
47
|
+
int m_v0, m_v1, m_v2;
|
48
|
+
int m_stripId; // real strip Id
|
49
|
+
int m_testStripId; // strip Id in an experiment
|
50
|
+
int m_experimentId; // in what experiment was it given an experiment Id?
|
51
|
+
bool m_bIsFake; //if true, will be deleted when the strip it's in is deleted
|
52
|
+
};
|
53
|
+
|
54
|
+
// nice and dumb edge class that points knows its
|
55
|
+
// indices, the two faces, and the next edge using
|
56
|
+
// the lesser of the indices
|
57
|
+
class NvEdgeInfo {
|
58
|
+
public:
|
59
|
+
|
60
|
+
// constructor puts 1 ref on us
|
61
|
+
NvEdgeInfo (int v0, int v1){
|
62
|
+
m_v0 = v0;
|
63
|
+
m_v1 = v1;
|
64
|
+
m_face0 = NULL;
|
65
|
+
m_face1 = NULL;
|
66
|
+
m_nextV0 = NULL;
|
67
|
+
m_nextV1 = NULL;
|
68
|
+
|
69
|
+
// we will appear in 2 lists. this is a good
|
70
|
+
// way to make sure we delete it the second time
|
71
|
+
// we hit it in the edge infos
|
72
|
+
m_refCount = 2;
|
73
|
+
|
74
|
+
}
|
75
|
+
|
76
|
+
// ref and unref
|
77
|
+
void Unref () { if (--m_refCount == 0) delete this; }
|
78
|
+
|
79
|
+
// data members are left public
|
80
|
+
UINT m_refCount;
|
81
|
+
NvFaceInfo *m_face0, *m_face1;
|
82
|
+
int m_v0, m_v1;
|
83
|
+
NvEdgeInfo *m_nextV0, *m_nextV1;
|
84
|
+
};
|
85
|
+
|
86
|
+
|
87
|
+
// This class is a quick summary of parameters used
|
88
|
+
// to begin a triangle strip. Some operations may
|
89
|
+
// want to create lists of such items, so they were
|
90
|
+
// pulled out into a class
|
91
|
+
class NvStripStartInfo {
|
92
|
+
public:
|
93
|
+
NvStripStartInfo(NvFaceInfo *startFace, NvEdgeInfo *startEdge, bool toV1){
|
94
|
+
m_startFace = startFace;
|
95
|
+
m_startEdge = startEdge;
|
96
|
+
m_toV1 = toV1;
|
97
|
+
}
|
98
|
+
NvFaceInfo *m_startFace;
|
99
|
+
NvEdgeInfo *m_startEdge;
|
100
|
+
bool m_toV1;
|
101
|
+
};
|
102
|
+
|
103
|
+
|
104
|
+
typedef std::vector<NvFaceInfo*> NvFaceInfoVec;
|
105
|
+
typedef std::list <NvFaceInfo*> NvFaceInfoList;
|
106
|
+
typedef std::list <NvFaceInfoVec*> NvStripList;
|
107
|
+
typedef std::vector<NvEdgeInfo*> NvEdgeInfoVec;
|
108
|
+
|
109
|
+
typedef std::vector<WORD> WordVec;
|
110
|
+
typedef std::vector<int> IntVec;
|
111
|
+
typedef std::vector<MyVertex> MyVertexVec;
|
112
|
+
typedef std::vector<MyFace> MyFaceVec;
|
113
|
+
|
114
|
+
template<class T>
|
115
|
+
inline void SWAP(T& first, T& second)
|
116
|
+
{
|
117
|
+
T temp = first;
|
118
|
+
first = second;
|
119
|
+
second = temp;
|
120
|
+
}
|
121
|
+
|
122
|
+
// This is a summary of a strip that has been built
|
123
|
+
class NvStripInfo {
|
124
|
+
public:
|
125
|
+
|
126
|
+
// A little information about the creation of the triangle strips
|
127
|
+
NvStripInfo(const NvStripStartInfo &startInfo, int stripId, int experimentId = -1) :
|
128
|
+
m_startInfo(startInfo)
|
129
|
+
{
|
130
|
+
m_stripId = stripId;
|
131
|
+
m_experimentId = experimentId;
|
132
|
+
visited = false;
|
133
|
+
m_numDegenerates = 0;
|
134
|
+
}
|
135
|
+
|
136
|
+
// This is an experiment if the experiment id is >= 0
|
137
|
+
inline bool IsExperiment () const { return m_experimentId >= 0; }
|
138
|
+
|
139
|
+
inline bool IsInStrip (const NvFaceInfo *faceInfo) const
|
140
|
+
{
|
141
|
+
if(faceInfo == NULL)
|
142
|
+
return false;
|
143
|
+
|
144
|
+
return (m_experimentId >= 0 ? faceInfo->m_testStripId == m_stripId : faceInfo->m_stripId == m_stripId);
|
145
|
+
}
|
146
|
+
|
147
|
+
bool SharesEdge(const NvFaceInfo* faceInfo, NvEdgeInfoVec &edgeInfos);
|
148
|
+
|
149
|
+
// take the given forward and backward strips and combine them together
|
150
|
+
void Combine(const NvFaceInfoVec &forward, const NvFaceInfoVec &backward);
|
151
|
+
|
152
|
+
//returns true if the face is "unique", i.e. has a vertex which doesn't exist in the faceVec
|
153
|
+
bool Unique(NvFaceInfoVec& faceVec, NvFaceInfo* face);
|
154
|
+
|
155
|
+
// mark the triangle as taken by this strip
|
156
|
+
bool IsMarked (NvFaceInfo *faceInfo);
|
157
|
+
void MarkTriangle(NvFaceInfo *faceInfo);
|
158
|
+
|
159
|
+
// build the strip
|
160
|
+
void Build(NvEdgeInfoVec &edgeInfos, NvFaceInfoVec &faceInfos);
|
161
|
+
|
162
|
+
// public data members
|
163
|
+
NvStripStartInfo m_startInfo;
|
164
|
+
NvFaceInfoVec m_faces;
|
165
|
+
int m_stripId;
|
166
|
+
int m_experimentId;
|
167
|
+
|
168
|
+
bool visited;
|
169
|
+
|
170
|
+
int m_numDegenerates;
|
171
|
+
};
|
172
|
+
|
173
|
+
typedef std::vector<NvStripInfo*> NvStripInfoVec;
|
174
|
+
|
175
|
+
|
176
|
+
//The actual stripifier
|
177
|
+
class NvStripifier {
|
178
|
+
public:
|
179
|
+
|
180
|
+
// Constructor
|
181
|
+
NvStripifier();
|
182
|
+
~NvStripifier();
|
183
|
+
|
184
|
+
//the target vertex cache size, the structure to place the strips in, and the input indices
|
185
|
+
void Stripify(const WordVec &in_indices, const int in_cacheSize, const int in_minStripLength,
|
186
|
+
const unsigned short maxIndex, NvStripInfoVec &allStrips, NvFaceInfoVec &allFaces);
|
187
|
+
void CreateStrips(const NvStripInfoVec& allStrips, IntVec& stripIndices, const bool bStitchStrips, unsigned int& numSeparateStrips, const bool bRestart, const unsigned int restartVal);
|
188
|
+
|
189
|
+
static int GetUniqueVertexInB(NvFaceInfo *faceA, NvFaceInfo *faceB);
|
190
|
+
//static int GetSharedVertex(NvFaceInfo *faceA, NvFaceInfo *faceB);
|
191
|
+
static void GetSharedVertices(NvFaceInfo *faceA, NvFaceInfo *faceB, int* vertex0, int* vertex1);
|
192
|
+
|
193
|
+
static bool IsDegenerate(const NvFaceInfo* face);
|
194
|
+
static bool IsDegenerate(const unsigned short v0, const unsigned short v1, const unsigned short v2);
|
195
|
+
|
196
|
+
protected:
|
197
|
+
|
198
|
+
WordVec indices;
|
199
|
+
int cacheSize;
|
200
|
+
int minStripLength;
|
201
|
+
float meshJump;
|
202
|
+
bool bFirstTimeResetPoint;
|
203
|
+
|
204
|
+
/////////////////////////////////////////////////////////////////////////////////
|
205
|
+
//
|
206
|
+
// Big mess of functions called during stripification
|
207
|
+
//
|
208
|
+
/////////////////////////////////////////////////////////////////////////////////
|
209
|
+
|
210
|
+
//********************
|
211
|
+
bool IsMoneyFace(const NvFaceInfo& face);
|
212
|
+
bool FaceContainsIndex(const NvFaceInfo& face, const unsigned int index);
|
213
|
+
|
214
|
+
bool IsCW(NvFaceInfo *faceInfo, int v0, int v1);
|
215
|
+
bool NextIsCW(const int numIndices);
|
216
|
+
|
217
|
+
static int GetNextIndex(const WordVec &indices, NvFaceInfo *face);
|
218
|
+
static NvEdgeInfo *FindEdgeInfo(NvEdgeInfoVec &edgeInfos, int v0, int v1);
|
219
|
+
static NvFaceInfo *FindOtherFace(NvEdgeInfoVec &edgeInfos, int v0, int v1, NvFaceInfo *faceInfo);
|
220
|
+
NvFaceInfo *FindGoodResetPoint(NvFaceInfoVec &faceInfos, NvEdgeInfoVec &edgeInfos);
|
221
|
+
|
222
|
+
void FindAllStrips(NvStripInfoVec &allStrips, NvFaceInfoVec &allFaceInfos, NvEdgeInfoVec &allEdgeInfos, int numSamples);
|
223
|
+
void SplitUpStripsAndOptimize(NvStripInfoVec &allStrips, NvStripInfoVec &outStrips, NvEdgeInfoVec& edgeInfos, NvFaceInfoVec& outFaceList);
|
224
|
+
void RemoveSmallStrips(NvStripInfoVec& allStrips, NvStripInfoVec& allBigStrips, NvFaceInfoVec& faceList);
|
225
|
+
|
226
|
+
bool FindTraversal(NvFaceInfoVec &faceInfos, NvEdgeInfoVec &edgeInfos, NvStripInfo *strip, NvStripStartInfo &startInfo);
|
227
|
+
int CountRemainingTris(std::list<NvStripInfo*>::iterator iter, std::list<NvStripInfo*>::iterator end);
|
228
|
+
|
229
|
+
void CommitStrips(NvStripInfoVec &allStrips, const NvStripInfoVec &strips);
|
230
|
+
|
231
|
+
float AvgStripSize(const NvStripInfoVec &strips);
|
232
|
+
int FindStartPoint(NvFaceInfoVec &faceInfos, NvEdgeInfoVec &edgeInfos);
|
233
|
+
|
234
|
+
void UpdateCacheStrip(VertexCache* vcache, NvStripInfo* strip);
|
235
|
+
void UpdateCacheFace(VertexCache* vcache, NvFaceInfo* face);
|
236
|
+
float CalcNumHitsStrip(VertexCache* vcache, NvStripInfo* strip);
|
237
|
+
int CalcNumHitsFace(VertexCache* vcache, NvFaceInfo* face);
|
238
|
+
int NumNeighbors(NvFaceInfo* face, NvEdgeInfoVec& edgeInfoVec);
|
239
|
+
|
240
|
+
void BuildStripifyInfo(NvFaceInfoVec &faceInfos, NvEdgeInfoVec &edgeInfos, const unsigned short maxIndex);
|
241
|
+
bool AlreadyExists(NvFaceInfo* faceInfo, NvFaceInfoVec& faceInfos);
|
242
|
+
|
243
|
+
// let our strip info classes and the other classes get
|
244
|
+
// to these protected stripificaton methods if they want
|
245
|
+
friend class NvStripInfo;
|
246
|
+
};
|
247
|
+
|
248
|
+
#endif
|
data/ext/RbTriStrip.cpp
ADDED
@@ -0,0 +1,324 @@
|
|
1
|
+
/*
|
2
|
+
RbTriStrip.c -
|
3
|
+
|
4
|
+
Author: scoopr
|
5
|
+
|
6
|
+
*/
|
7
|
+
#include "NvTriStrip.h"
|
8
|
+
#include <ruby.h>
|
9
|
+
#include <string.h>
|
10
|
+
|
11
|
+
|
12
|
+
/* Document-module: NvTriStrip
|
13
|
+
*
|
14
|
+
* NvTriStrip module.
|
15
|
+
*/
|
16
|
+
|
17
|
+
|
18
|
+
/* Document-class: PrimitiveGroup
|
19
|
+
*
|
20
|
+
* Return value for strip generator
|
21
|
+
*/
|
22
|
+
|
23
|
+
typedef struct {
|
24
|
+
PrimitiveGroup *pg;
|
25
|
+
} PrimitiveGroupWrap;
|
26
|
+
|
27
|
+
VALUE primitiveGroupClass;
|
28
|
+
|
29
|
+
void primitivegroup_free(PrimitiveGroupWrap *pgw) {
|
30
|
+
delete pgw->pg;
|
31
|
+
}
|
32
|
+
|
33
|
+
|
34
|
+
/* Creates an PrimitiveGroup of given number and type of indices, rarely used directly */
|
35
|
+
VALUE primitivegroup_new(VALUE klass, VALUE type, VALUE numIndices) {
|
36
|
+
|
37
|
+
PrimitiveGroupWrap *pgw;
|
38
|
+
VALUE rpg=Data_Make_Struct(klass, PrimitiveGroupWrap, 0, primitivegroup_free, pgw);
|
39
|
+
pgw->pg=new PrimitiveGroup;
|
40
|
+
pgw->pg->type=(PrimType)NUM2INT(type);
|
41
|
+
pgw->pg->numIndices=NUM2INT(numIndices);
|
42
|
+
pgw->pg->indices=new unsigned short[pgw->pg->numIndices];
|
43
|
+
memset(pgw->pg->indices, 0, pgw->pg->numIndices * sizeof(unsigned short));
|
44
|
+
|
45
|
+
return rpg;
|
46
|
+
}
|
47
|
+
|
48
|
+
|
49
|
+
/* call-seq: pg.set_at index,val
|
50
|
+
* pg[index]=val
|
51
|
+
*
|
52
|
+
* Set value at _index_ */
|
53
|
+
VALUE primitivegroup_set_at(VALUE self, VALUE index, VALUE val) {
|
54
|
+
PrimitiveGroupWrap *pgw;
|
55
|
+
Data_Get_Struct(self, PrimitiveGroupWrap, pgw);
|
56
|
+
int v=NUM2INT(val);
|
57
|
+
int i=NUM2INT(index);
|
58
|
+
if(i<0 || i>pgw->pg->numIndices-1) rb_raise(rb_eIndexError,"Index out of bounds");
|
59
|
+
if(v<0 || v>65535) rb_raise(rb_eArgError, "Indices need to be between 0 and 65535");
|
60
|
+
pgw->pg->indices[i]=v;
|
61
|
+
|
62
|
+
return val;
|
63
|
+
}
|
64
|
+
|
65
|
+
/* call-seq: pg.get_at index -> val
|
66
|
+
* pg[index] -> val
|
67
|
+
*
|
68
|
+
* Value at _index_ */
|
69
|
+
VALUE primitivegroup_get_at(VALUE self, VALUE index) {
|
70
|
+
PrimitiveGroupWrap *pgw;
|
71
|
+
Data_Get_Struct(self, PrimitiveGroupWrap, pgw);
|
72
|
+
int i=NUM2INT(index);
|
73
|
+
if(i<0 || i>pgw->pg->numIndices-1) rb_raise(rb_eIndexError,"Index out of bounds");
|
74
|
+
|
75
|
+
return INT2NUM(pgw->pg->indices[i]);
|
76
|
+
|
77
|
+
}
|
78
|
+
|
79
|
+
/* call-seq: pg.num_indices -> how_many
|
80
|
+
* pg.size -> how_many
|
81
|
+
*
|
82
|
+
* Number of indices */
|
83
|
+
VALUE primitivegroup_num_indices(VALUE self) {
|
84
|
+
PrimitiveGroupWrap *pgw;
|
85
|
+
Data_Get_Struct(self, PrimitiveGroupWrap, pgw);
|
86
|
+
|
87
|
+
return INT2NUM(pgw->pg->numIndices);
|
88
|
+
|
89
|
+
}
|
90
|
+
|
91
|
+
/* Iterate through all indices
|
92
|
+
*/
|
93
|
+
VALUE primitivegroup_each(VALUE self) {
|
94
|
+
PrimitiveGroupWrap *pgw;
|
95
|
+
Data_Get_Struct(self, PrimitiveGroupWrap, pgw);
|
96
|
+
|
97
|
+
for(int i=0;i<pgw->pg->numIndices;i++) {
|
98
|
+
rb_yield(INT2NUM(pgw->pg->indices[i]));
|
99
|
+
}
|
100
|
+
|
101
|
+
}
|
102
|
+
|
103
|
+
|
104
|
+
VALUE copy_pg(PrimitiveGroup *pg) {
|
105
|
+
VALUE npg=primitivegroup_new(primitiveGroupClass, INT2NUM((int)pg->type), INT2NUM(pg->numIndices));
|
106
|
+
PrimitiveGroupWrap *pgw;
|
107
|
+
Data_Get_Struct(npg, PrimitiveGroupWrap, pgw);
|
108
|
+
if(pg->indices!=NULL) {
|
109
|
+
memcpy(pgw->pg->indices, pg->indices, sizeof(unsigned short)*pg->numIndices);
|
110
|
+
}
|
111
|
+
return npg;
|
112
|
+
}
|
113
|
+
|
114
|
+
|
115
|
+
/*
|
116
|
+
* call-seq:
|
117
|
+
* generate_strips indices, validate -> stripified_primitivegroup_ary
|
118
|
+
*
|
119
|
+
* This function generates stripified indices for given list of triangle indices.
|
120
|
+
* The index list should be an array (or anything that responds to #length and #[])
|
121
|
+
* of separate triangles, three indices per triangle.
|
122
|
+
*/
|
123
|
+
VALUE rbtristripper_generate_strips(VALUE self, VALUE indices, VALUE validateEnabled) {
|
124
|
+
|
125
|
+
ID sGet=rb_intern("[]");
|
126
|
+
ID sSize=rb_intern("length");
|
127
|
+
|
128
|
+
unsigned int size=NUM2INT(rb_funcall(indices,sSize,0));
|
129
|
+
unsigned short ind[size];
|
130
|
+
|
131
|
+
for(int i=0;i<size;i++) {
|
132
|
+
int v=NUM2INT( rb_funcall(indices, sGet, 1, INT2NUM(i)) );
|
133
|
+
if(v<0 || v>65535) {
|
134
|
+
rb_raise(rb_eArgError, "Value of out range (0..65535)");
|
135
|
+
}
|
136
|
+
ind[i]=v;
|
137
|
+
}
|
138
|
+
unsigned short groups;
|
139
|
+
PrimitiveGroup *p;
|
140
|
+
GenerateStrips(ind, size, &p, &groups, validateEnabled==Qtrue);
|
141
|
+
|
142
|
+
VALUE ary=rb_ary_new2(groups);
|
143
|
+
for(int i=0;i<groups;i++) {
|
144
|
+
VALUE v=copy_pg(&p[i]);
|
145
|
+
rb_ary_push(ary, v);
|
146
|
+
}
|
147
|
+
|
148
|
+
delete[] p;
|
149
|
+
|
150
|
+
return ary;
|
151
|
+
}
|
152
|
+
|
153
|
+
|
154
|
+
/**
|
155
|
+
* call-seq:
|
156
|
+
* remap_indices primitivegroup_ary, max_verts -> remapped_primitivegroup_ary
|
157
|
+
*
|
158
|
+
* Remaps indices to improve spatial locality in your vertex buffer
|
159
|
+
* With the indices handed back, you need to reorder your vertex buffer.
|
160
|
+
*/
|
161
|
+
VALUE rbtristripper_remap_indices(VALUE self, VALUE prims, VALUE maxVerts) {
|
162
|
+
|
163
|
+
|
164
|
+
ID sGet=rb_intern("[]");
|
165
|
+
ID sSize=rb_intern("length");
|
166
|
+
|
167
|
+
unsigned short size=NUM2INT(rb_funcall(prims,sSize,0));
|
168
|
+
|
169
|
+
PrimitiveGroup groups[size];
|
170
|
+
for(int i=0;i<size;i++) {
|
171
|
+
|
172
|
+
PrimitiveGroupWrap *pgw;
|
173
|
+
Data_Get_Struct(rb_funcall(prims, sGet, 1, INT2NUM(i)), PrimitiveGroupWrap, pgw);
|
174
|
+
groups[i]=*(pgw->pg); // Copies the object for our own array
|
175
|
+
}
|
176
|
+
|
177
|
+
|
178
|
+
PrimitiveGroup *remappedGroups=new PrimitiveGroup[size];
|
179
|
+
|
180
|
+
RemapIndices(groups, size, NUM2INT(maxVerts), &remappedGroups);
|
181
|
+
|
182
|
+
VALUE remapped=rb_ary_new2(size);
|
183
|
+
|
184
|
+
|
185
|
+
for(int i=0;i<size;i++) {
|
186
|
+
// Copy resulting array to ruby array
|
187
|
+
VALUE v=copy_pg(&remappedGroups[i]);
|
188
|
+
rb_ary_push(remapped, v);
|
189
|
+
|
190
|
+
// Remove reference to index array, because we don't own it,
|
191
|
+
// and would be removed when leaving this function
|
192
|
+
groups[i].indices=NULL;
|
193
|
+
}
|
194
|
+
|
195
|
+
delete[] remappedGroups;
|
196
|
+
return remapped;
|
197
|
+
}
|
198
|
+
|
199
|
+
|
200
|
+
|
201
|
+
/* call-seq: set_lists_only boolean
|
202
|
+
*
|
203
|
+
* If set to true, will return an optimized list, with no strips at all.
|
204
|
+
* Default is false.
|
205
|
+
*/
|
206
|
+
VALUE rbtristripper_set_lists_only(VALUE self, VALUE val) {
|
207
|
+
SetListsOnly(val==Qtrue?true:false);
|
208
|
+
return Qnil;
|
209
|
+
}
|
210
|
+
|
211
|
+
/* call-seq: set_min_strip_size val
|
212
|
+
*
|
213
|
+
* Sets the minimum acceptable size for a strip, in triangles.
|
214
|
+
* All strips generated which are shorter than this will be thrown into one big, separate list.
|
215
|
+
*/
|
216
|
+
VALUE rbtristripper_set_min_strip_size(VALUE self, VALUE val) {
|
217
|
+
SetMinStripSize( NUM2INT(val) );
|
218
|
+
return Qnil;
|
219
|
+
}
|
220
|
+
|
221
|
+
/* call-seq: set_stitch_strips boolean
|
222
|
+
*
|
223
|
+
* Boolean to indicate whether to stitch together strips into one huge strip or not.
|
224
|
+
* If set to true, you'll get back one huge strip stitched together using degenerate triangles.
|
225
|
+
* If set to false, you'll get back a large number of separate strips.
|
226
|
+
*
|
227
|
+
* Default is true.
|
228
|
+
*/
|
229
|
+
VALUE rbtristripper_set_stitch_strips(VALUE self, VALUE val) {
|
230
|
+
SetStitchStrips(val==Qtrue?true:false);
|
231
|
+
return Qnil;
|
232
|
+
}
|
233
|
+
|
234
|
+
/* call-seq: set_cache_size val
|
235
|
+
*
|
236
|
+
* Sets the cache size which the stripfier uses to optimize the data.
|
237
|
+
* Controls the length of the generated individual strips.
|
238
|
+
* This is the "actual" cache size, so 24 for GeForce3 and 16 for GeForce1/2
|
239
|
+
* You may want to play around with this number to tweak performance.
|
240
|
+
*
|
241
|
+
* Default is 16.
|
242
|
+
*/
|
243
|
+
VALUE rbtristripper_set_cache_size(VALUE self, VALUE val) {
|
244
|
+
SetCacheSize(NUM2INT(val));
|
245
|
+
return Qnil;
|
246
|
+
}
|
247
|
+
|
248
|
+
/* call-seq: disable_restart
|
249
|
+
*
|
250
|
+
* For GPUs that support primitive restart, this disables using primitive restart
|
251
|
+
*
|
252
|
+
*/
|
253
|
+
VALUE rbtristripper_disable_restart(VALUE self) {
|
254
|
+
DisableRestart();
|
255
|
+
return Qnil;
|
256
|
+
}
|
257
|
+
|
258
|
+
/* call-seq: enable_restart val
|
259
|
+
*
|
260
|
+
* For GPUs that support primitive restart, this sets a value as the restart index.
|
261
|
+
* (For OpenGL, the extension would be GL_NV_primitive_restart)
|
262
|
+
*
|
263
|
+
* Restart is meaningless if strips are not being stitched together, so enabling restart
|
264
|
+
* makes NvTriStrip forcing stitching. So, you'll get back one strip.
|
265
|
+
*
|
266
|
+
* Default value is disabled.
|
267
|
+
*/
|
268
|
+
VALUE rbtristripper_enable_restart(VALUE self, VALUE val) {
|
269
|
+
EnableRestart(NUM2INT(val));
|
270
|
+
return Qnil;
|
271
|
+
}
|
272
|
+
|
273
|
+
|
274
|
+
extern "C" void Init_nvtristrip() {
|
275
|
+
|
276
|
+
VALUE stripperModule=rb_define_module("NvTriStrip");
|
277
|
+
|
278
|
+
/* Constant for list type indices */
|
279
|
+
rb_define_const(stripperModule, "PT_LIST", INT2NUM(PT_LIST) );
|
280
|
+
/* Constant for strip type indices */
|
281
|
+
rb_define_const(stripperModule, "PT_STRIP", INT2NUM(PT_STRIP) );
|
282
|
+
/* Constant for fan type indices */
|
283
|
+
rb_define_const(stripperModule, "PT_FAN", INT2NUM(PT_FAN) );
|
284
|
+
|
285
|
+
primitiveGroupClass=rb_define_class_under(stripperModule, "PrimitiveGroup", rb_cObject);
|
286
|
+
rb_define_singleton_method(primitiveGroupClass, "new", RUBY_METHOD_FUNC(primitivegroup_new), 2);
|
287
|
+
|
288
|
+
|
289
|
+
rb_define_method(primitiveGroupClass, "num_indices", RUBY_METHOD_FUNC(primitivegroup_num_indices),0);
|
290
|
+
rb_define_method(primitiveGroupClass, "get_at", RUBY_METHOD_FUNC(primitivegroup_get_at),1);
|
291
|
+
rb_define_method(primitiveGroupClass, "set_at", RUBY_METHOD_FUNC(primitivegroup_set_at),2);
|
292
|
+
|
293
|
+
// Ruby friendly aliases
|
294
|
+
rb_define_alias(primitiveGroupClass, "length", "num_indices");
|
295
|
+
rb_define_alias(primitiveGroupClass, "size", "num_indices");
|
296
|
+
rb_define_alias(primitiveGroupClass, "[]", "get_at");
|
297
|
+
rb_define_alias(primitiveGroupClass, "[]=", "set_at");
|
298
|
+
|
299
|
+
// Make PrimitiveGroup act even more like a ruby array
|
300
|
+
rb_define_method(primitiveGroupClass, "each", RUBY_METHOD_FUNC(primitivegroup_each), 0);
|
301
|
+
rb_include_module(primitiveGroupClass, rb_mEnumerable);
|
302
|
+
|
303
|
+
/* Size of Geforce 1 and 2 families cachesize, value is 16 */
|
304
|
+
rb_define_const(stripperModule, "CACHESIZE_GEFORCE1_2", INT2NUM(CACHESIZE_GEFORCE1_2) );
|
305
|
+
/* Size of Geforce 3 family cachesize, value is 24 */
|
306
|
+
rb_define_const(stripperModule, "CACHESIZE_GEFORCE3", INT2NUM(CACHESIZE_GEFORCE3) );
|
307
|
+
|
308
|
+
|
309
|
+
// Hard work
|
310
|
+
rb_define_singleton_method(stripperModule, "generate_strips", RUBY_METHOD_FUNC(rbtristripper_generate_strips), 2);
|
311
|
+
rb_define_singleton_method(stripperModule, "remap_indices", RUBY_METHOD_FUNC(rbtristripper_remap_indices), 2);
|
312
|
+
|
313
|
+
|
314
|
+
// Options
|
315
|
+
rb_define_singleton_method(stripperModule, "set_lists_only", RUBY_METHOD_FUNC(rbtristripper_set_lists_only),1);
|
316
|
+
rb_define_singleton_method(stripperModule, "set_min_strip_size", RUBY_METHOD_FUNC(rbtristripper_set_min_strip_size),1);
|
317
|
+
rb_define_singleton_method(stripperModule, "set_stitch_strips", RUBY_METHOD_FUNC(rbtristripper_set_stitch_strips),1);
|
318
|
+
rb_define_singleton_method(stripperModule, "set_cache_size", RUBY_METHOD_FUNC(rbtristripper_set_cache_size),1);
|
319
|
+
rb_define_singleton_method(stripperModule, "disable_restart", RUBY_METHOD_FUNC(rbtristripper_disable_restart),0);
|
320
|
+
rb_define_singleton_method(stripperModule, "enable_restart", RUBY_METHOD_FUNC(rbtristripper_enable_restart),1);
|
321
|
+
|
322
|
+
|
323
|
+
|
324
|
+
}
|