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.
@@ -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
@@ -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
+ }