nvtristrip-ruby 0.5.0

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