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