glu2 8.4.0

Sign up to get free protection for your applications and to get access to all the features.
data/ext/glu/glu.c ADDED
@@ -0,0 +1,1543 @@
1
+ /*
2
+ * Last edit by previous maintainer:
3
+ * 2003/10/25 15:25:05, yoshi
4
+ *
5
+ * Copyright (C) 1999 - 2005 Yoshi <yoshi@giganet.net>
6
+ * Copyright (C) 2006 John M. Gabriele <jmg3000@gmail.com>
7
+ *
8
+ * This program is distributed under the terms of the MIT license.
9
+ * See the included COPYRIGHT file for the terms of this license.
10
+ *
11
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
12
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
13
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
14
+ * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
15
+ * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
16
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
17
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
18
+ */
19
+
20
+ #include "common.h"
21
+
22
+ static VALUE module;
23
+
24
+ VALUE Class_GLUError;
25
+
26
+ void glu_init_enums(VALUE);
27
+
28
+ typedef GLUtesselator tesselatorObj;
29
+
30
+ /* pointers passed to gluNurbsCurve/Surface etc.,
31
+ - some implementations (Mesa) needs these to be valid
32
+ at EndCurve/Surface etc. call., so we store them here
33
+ and free them after that call */
34
+
35
+ struct glu_MesaStack {
36
+ int len;
37
+ GLfloat **ptr;
38
+ };
39
+
40
+ static struct glu_MesaStack gms = {0, NULL};
41
+
42
+ struct nurbsdata {
43
+ GLUnurbsObj *nobj;
44
+ VALUE n_ref;
45
+ };
46
+ struct tessdata {
47
+ tesselatorObj *tobj;
48
+ VALUE t_ref;
49
+ };
50
+
51
+ struct quaddata {
52
+ GLUquadricObj *qobj;
53
+ VALUE q_ref;
54
+ };
55
+
56
+ static VALUE cNurbs;
57
+ static VALUE cTess;
58
+ static VALUE cQuad;
59
+
60
+ #define REF_LAST 15
61
+
62
+ #define GetNURBS(obj, ndata) {\
63
+ Data_Get_Struct(obj, struct nurbsdata, ndata);\
64
+ if (ndata->nobj == NULL) rb_raise(rb_eRuntimeError, "Nurbs Object already deleted!");\
65
+ }
66
+
67
+ #define GetTESS(obj, tdata) {\
68
+ Data_Get_Struct(obj, struct tessdata, tdata);\
69
+ if (tdata->tobj == NULL) rb_raise(rb_eRuntimeError, "Triangulator Object already deleted!");\
70
+ }
71
+
72
+ #define GetQUAD(obj, qdata) {\
73
+ Data_Get_Struct(obj, struct quaddata, qdata);\
74
+ if (qdata->qobj == NULL) rb_raise(rb_eRuntimeError, "Quadric Object already deleted!");\
75
+ }
76
+
77
+ static ID callId;
78
+ static ID refId;
79
+
80
+ /*
81
+ * GLU Implementation
82
+ */
83
+
84
+ /*
85
+ * Nurbs
86
+ */
87
+ /* from nurbscrv.c */
88
+ static int
89
+ get_curve_dim(type)
90
+ GLenum type;
91
+ {
92
+ switch(type)
93
+ {
94
+ case GL_MAP1_VERTEX_3: return 3;
95
+ case GL_MAP1_VERTEX_4: return 4;
96
+ case GL_MAP1_INDEX: return 1;
97
+ case GL_MAP1_COLOR_4: return 4;
98
+ case GL_MAP1_NORMAL: return 3;
99
+ case GL_MAP1_TEXTURE_COORD_1: return 1;
100
+ case GL_MAP1_TEXTURE_COORD_2: return 2;
101
+ case GL_MAP1_TEXTURE_COORD_3: return 3;
102
+ case GL_MAP1_TEXTURE_COORD_4: return 4;
103
+ default:
104
+ rb_raise(rb_eArgError,"Unknown curve type '%i'",type);
105
+ }
106
+ return 0; /* never gets here */
107
+ }
108
+ /* from nurbssrf.c */
109
+ static int
110
+ get_surface_dim(GLenum type)
111
+ {
112
+ switch(type)
113
+ {
114
+ case GL_MAP2_VERTEX_3: return 3;
115
+ case GL_MAP2_VERTEX_4: return 4;
116
+ case GL_MAP2_INDEX: return 1;
117
+ case GL_MAP2_COLOR_4: return 4;
118
+ case GL_MAP2_NORMAL: return 3;
119
+ case GL_MAP2_TEXTURE_COORD_1: return 1;
120
+ case GL_MAP2_TEXTURE_COORD_2: return 2;
121
+ case GL_MAP2_TEXTURE_COORD_3: return 3;
122
+ case GL_MAP2_TEXTURE_COORD_4: return 4;
123
+ default:
124
+ rb_raise(rb_eArgError,"Unknown surface type '%i'",type);
125
+ }
126
+ return 0; /* never gets here */
127
+ }
128
+
129
+ VALUE GLUError_initialize(VALUE obj,VALUE message, VALUE error_id)
130
+ {
131
+ rb_call_super(1, &message);
132
+ rb_iv_set(obj, "@id", error_id);
133
+
134
+ return obj;
135
+ }
136
+
137
+ void check_for_gluerror(GLenum error)
138
+ {
139
+ const char *error_string;
140
+ VALUE exc;
141
+
142
+ /* no error */
143
+ if (error==0)
144
+ return;
145
+
146
+ switch(error) {
147
+ case GLU_INVALID_ENUM: error_string = "invalid enumerant"; break;
148
+ case GLU_INVALID_VALUE: error_string = "invalid value"; break;
149
+ case GLU_INVALID_OPERATION: error_string = "invalid operation"; break;
150
+ case GLU_OUT_OF_MEMORY: error_string = "out of memory"; break;
151
+ default: error_string = "unknown error"; break;
152
+ }
153
+
154
+ exc = rb_funcall(Class_GLUError, rb_intern("new"), 2, rb_str_new2(error_string), UINT2NUM(error));
155
+ rb_funcall(rb_cObject, rb_intern("raise"), 1, exc);
156
+ }
157
+
158
+ /*
159
+ * NURBS API
160
+ */
161
+ static VALUE n_current;
162
+
163
+ static void
164
+ free_nurbs(ndata)
165
+ struct nurbsdata *ndata;
166
+ {
167
+ if (ndata->nobj) gluDeleteNurbsRenderer(ndata->nobj);
168
+ ndata->nobj = NULL;
169
+ ndata->n_ref = Qnil;
170
+ }
171
+ static void
172
+ mark_nurbs(ndata)
173
+ struct nurbsdata* ndata;
174
+ {
175
+ if (ndata->nobj)
176
+ rb_gc_mark(ndata->n_ref);
177
+ }
178
+
179
+ static void CALLBACK
180
+ n_error(errorno)
181
+ GLenum errorno;
182
+ {
183
+ VALUE nurbs;
184
+ struct nurbsdata *ndata;
185
+ nurbs = rb_ary_entry(n_current, -1);
186
+ if (nurbs == Qnil)
187
+ return;
188
+ GetNURBS(nurbs, ndata);
189
+ rb_funcall(rb_ary_entry(ndata->n_ref, GLU_ERROR), callId, 1, INT2NUM(errorno));
190
+ }
191
+
192
+ static VALUE
193
+ glu_NurbsCallback(obj, arg1, arg2, arg3)
194
+ VALUE obj, arg1, arg2, arg3;
195
+ {
196
+ struct nurbsdata* ndata;
197
+ GLenum type;
198
+ GetNURBS(arg1, ndata);
199
+ type = (GLenum)NUM2INT(arg2);
200
+ if (!rb_obj_is_kind_of(arg3,rb_cProc) && !NIL_P(arg3))
201
+ rb_raise(rb_eTypeError, "gluNurbsCallback needs Proc Object:%s",rb_class2name(CLASS_OF(arg3)));
202
+
203
+ if (type!=GLU_ERROR)
204
+ return Qnil;
205
+
206
+ rb_ary_store(ndata->n_ref, type, arg3);
207
+ if (NIL_P(arg3))
208
+ gluNurbsCallback(ndata->nobj, type, NULL);
209
+ else
210
+ gluNurbsCallback(ndata->nobj, type, n_error);
211
+
212
+ return Qnil;
213
+ }
214
+
215
+
216
+ static VALUE
217
+ glu_NewNurbsRenderer(obj)
218
+ VALUE obj;
219
+ {
220
+ VALUE ret;
221
+ struct nurbsdata *ndata;
222
+ ret = Data_Make_Struct(cNurbs, struct nurbsdata, mark_nurbs, free_nurbs, ndata);
223
+ ndata->nobj = gluNewNurbsRenderer();
224
+ ndata->n_ref = rb_ary_new2(REF_LAST);
225
+
226
+ return ret;
227
+ }
228
+ static VALUE
229
+ glu_DeleteNurbsRenderer(obj, arg1)
230
+ VALUE obj, arg1;
231
+ {
232
+ struct nurbsdata *ndata;
233
+ GetNURBS(arg1, ndata);
234
+ free_nurbs(ndata);
235
+
236
+ return Qnil;
237
+ }
238
+ static VALUE
239
+ glu_NurbsProperty(obj, arg1, arg2, arg3)
240
+ VALUE obj, arg1, arg2, arg3;
241
+ {
242
+ struct nurbsdata *ndata;
243
+ GLenum property;
244
+ GLfloat value;
245
+ GetNURBS(arg1, ndata);
246
+ property = (GLenum)NUM2INT(arg2);
247
+ value = (GLfloat)NUM2DBL(arg3);
248
+ gluNurbsProperty(ndata->nobj, property, value);
249
+
250
+ return Qnil;
251
+ }
252
+ static VALUE
253
+ glu_GetNurbsProperty(obj, arg1, arg2)
254
+ VALUE obj, arg1, arg2;
255
+ {
256
+ struct nurbsdata *ndata;
257
+ GLenum property;
258
+ GLfloat value;
259
+ GetNURBS(arg1, ndata);
260
+ property = (GLenum)NUM2INT(arg2);
261
+ gluGetNurbsProperty(ndata->nobj, property, &value);
262
+
263
+ return cond_GLBOOL2RUBY_F(property,value);
264
+ }
265
+ static VALUE
266
+ glu_BeginCurve(obj, arg1)
267
+ VALUE obj, arg1;
268
+ {
269
+ struct nurbsdata *ndata;
270
+ GetNURBS(arg1, ndata);
271
+ rb_ary_push(n_current, arg1);
272
+ gluBeginCurve(ndata->nobj);
273
+
274
+ return Qnil;
275
+ }
276
+ static VALUE
277
+ glu_EndCurve(obj, arg1)
278
+ VALUE obj, arg1;
279
+ {
280
+ struct nurbsdata *ndata;
281
+ GetNURBS(arg1, ndata);
282
+ gluEndCurve(ndata->nobj);
283
+
284
+ for (;gms.len>0;gms.len--)
285
+ free(gms.ptr[gms.len-1]);
286
+ free(gms.ptr);
287
+ gms.ptr = NULL;
288
+
289
+ rb_ary_pop(n_current);
290
+
291
+
292
+ return Qnil;
293
+ }
294
+ static VALUE
295
+ glu_NurbsCurve(argc,argv,obj)
296
+ int argc;
297
+ VALUE *argv;
298
+ VALUE obj;
299
+ {
300
+ struct nurbsdata *ndata;
301
+ GLint uknot_count;
302
+ GLfloat *uknot;
303
+ GLint u_stride;
304
+ GLint uorder;
305
+ GLfloat *ctlarray;
306
+ GLenum type;
307
+ GLfloat **gms_ptr;
308
+
309
+ VALUE args[7];
310
+ VALUE ary_ctl1;
311
+
312
+ switch (rb_scan_args(argc, argv, "52", &args[0], &args[1], &args[2], &args[3], &args[4], &args[5], &args[6])) {
313
+ case 5:
314
+ uknot_count = (GLint)RARRAY_LENINT(args[1]);
315
+ uorder = (GLenum)NUM2INT(args[3]);
316
+ type = (GLenum)NUM2INT(args[4]);
317
+ u_stride = get_curve_dim(type);
318
+
319
+ uknot = ALLOC_N(GLfloat, uknot_count);
320
+ ary2cflt(args[1], uknot, uknot_count);
321
+
322
+ ary_ctl1 = rb_funcall(args[2],rb_intern("flatten"),0);
323
+ break;
324
+ case 7:
325
+ uknot_count = (GLint)NUM2INT(args[1]);
326
+ u_stride = (GLint)NUM2INT(args[3]);
327
+ uorder = (GLint)NUM2INT(args[5]);
328
+ type = (GLenum)NUM2INT(args[6]);
329
+
330
+ uknot = ALLOC_N(GLfloat, uknot_count);
331
+ ary2cflt(args[2], uknot, uknot_count);
332
+
333
+ ary_ctl1 = rb_funcall(args[4],rb_intern("flatten"),0);
334
+ break;
335
+ default:
336
+ rb_raise(rb_eArgError, "gluNurbsCurve needs 5 or 7 arguments");
337
+ }
338
+ ctlarray = ALLOC_N(GLfloat, u_stride*(uknot_count-uorder));
339
+ ary2cflt((VALUE)ary_ctl1, ctlarray, (uknot_count-uorder)*u_stride);
340
+
341
+ GetNURBS(args[0], ndata);
342
+ gluNurbsCurve(ndata->nobj, uknot_count, uknot, u_stride, ctlarray, uorder, type);
343
+
344
+ /* store the pointers */
345
+ gms_ptr = gms.ptr;
346
+ gms.ptr = REALLOC_N(gms_ptr, GLfloat*, gms.len+=2);
347
+ gms.ptr[gms.len - 2] = uknot;
348
+ gms.ptr[gms.len - 1] = ctlarray;
349
+
350
+ return Qnil;
351
+ }
352
+ static VALUE
353
+ glu_BeginSurface(obj, arg1)
354
+ VALUE obj, arg1;
355
+ {
356
+ struct nurbsdata *ndata;
357
+ GetNURBS(arg1, ndata);
358
+ rb_ary_push(n_current, arg1);
359
+ gluBeginSurface(ndata->nobj);
360
+
361
+ return Qnil;
362
+ }
363
+ static VALUE
364
+ glu_EndSurface(obj, arg1)
365
+ VALUE obj, arg1;
366
+ {
367
+ struct nurbsdata *ndata;
368
+ GetNURBS(arg1, ndata);
369
+ gluEndSurface(ndata->nobj);
370
+
371
+ for(; gms.len>0; gms.len--)
372
+ free(gms.ptr[gms.len-1]);
373
+ free(gms.ptr);
374
+ gms.ptr = NULL;
375
+
376
+ rb_ary_pop(n_current);
377
+
378
+
379
+ return Qnil;
380
+ }
381
+
382
+ static VALUE
383
+ glu_NurbsSurface(argc, argv, obj)
384
+ int argc;
385
+ VALUE *argv;
386
+ VALUE obj;
387
+ {
388
+ struct nurbsdata *ndata;
389
+ GLint sknot_count;
390
+ GLfloat *sknot;
391
+ GLint tknot_count;
392
+ GLfloat *tknot;
393
+ GLint s_stride;
394
+ GLint t_stride;
395
+ GLfloat *ctlarray;
396
+ GLint sorder;
397
+ GLint torder;
398
+ GLenum type;
399
+ GLfloat **gms_ptr;
400
+
401
+ VALUE args[11];
402
+ VALUE ary_ctl1;
403
+ int type_len;
404
+
405
+ switch (rb_scan_args(argc, argv, "74", &args[0], &args[1], &args[2], &args[3], &args[4], &args[5], &args[6], &args[7], &args[8], &args[9], &args[10])) {
406
+ case 7:
407
+ sknot_count = (GLint)RARRAY_LENINT(args[1]);
408
+ sknot = ALLOC_N(GLfloat, sknot_count);
409
+ ary2cflt(args[1], sknot, sknot_count);
410
+
411
+ tknot_count = (GLint)RARRAY_LENINT(args[2]);
412
+ tknot = ALLOC_N(GLfloat, tknot_count);
413
+ ary2cflt(args[2], tknot, tknot_count);
414
+
415
+ sorder = (GLint)NUM2INT(args[4]);
416
+ torder = (GLint)NUM2INT(args[5]);
417
+ type = (GLenum)NUM2INT(args[6]);
418
+
419
+ t_stride = get_surface_dim(type);
420
+ s_stride = t_stride * sorder;
421
+
422
+ ctlarray = ALLOC_N(GLfloat, (sknot_count-sorder)*(tknot_count-torder)*t_stride);
423
+ ary_ctl1 = rb_funcall(args[3],rb_intern("flatten"),0);
424
+ ary2cflt(ary_ctl1, ctlarray, (sknot_count-sorder)*(tknot_count-torder)*t_stride);
425
+ break;
426
+ case 11:
427
+ sknot_count = (GLint)NUM2INT(args[1]);
428
+ sknot = ALLOC_N(GLfloat, sknot_count);
429
+ ary2cflt(args[2], sknot, sknot_count);
430
+
431
+ tknot_count = (GLint)NUM2INT(args[3]);
432
+ tknot = ALLOC_N(GLfloat, tknot_count);
433
+ ary2cflt(args[4], tknot, tknot_count);
434
+
435
+ s_stride = (GLint)NUM2INT(args[5]);
436
+ t_stride = (GLint)NUM2INT(args[6]);
437
+ sorder = (GLint)NUM2INT(args[8]);
438
+ torder = (GLint)NUM2INT(args[9]);
439
+ type = (GLint)NUM2INT(args[10]);
440
+ type_len = get_surface_dim(type);
441
+
442
+ ctlarray = ALLOC_N(GLfloat, (sknot_count-sorder)*(tknot_count-torder)*type_len);
443
+ ary_ctl1 = rb_funcall(args[7],rb_intern("flatten"),0);
444
+ ary2cflt(ary_ctl1, ctlarray, (sknot_count-sorder)*(tknot_count-torder)*type_len);
445
+ break;
446
+ default:
447
+ rb_raise(rb_eArgError, "gluNurbsSurface needs 7 or 11 arguments");
448
+ return Qnil; /* not reached */
449
+ }
450
+ GetNURBS(args[0], ndata);
451
+ gluNurbsSurface(ndata->nobj, sknot_count, sknot, tknot_count, tknot,
452
+ s_stride, t_stride, ctlarray, sorder, torder, type);
453
+
454
+ /* store the pointers */
455
+
456
+ gms_ptr = gms.ptr;
457
+ gms.ptr = REALLOC_N(gms_ptr, GLfloat*, gms.len+=3);
458
+ gms.ptr[gms.len-3] = sknot;
459
+ gms.ptr[gms.len-2] = tknot;
460
+ gms.ptr[gms.len-1] = ctlarray;
461
+
462
+
463
+ return Qnil;
464
+ }
465
+ static VALUE
466
+ glu_BeginTrim(obj, arg1)
467
+ VALUE obj, arg1;
468
+ {
469
+ struct nurbsdata *ndata;
470
+ GetNURBS(arg1, ndata);
471
+ rb_ary_push(n_current, arg1);
472
+ gluBeginTrim(ndata->nobj);
473
+
474
+ return Qnil;
475
+ }
476
+ static VALUE
477
+ glu_EndTrim(obj, arg1)
478
+ VALUE obj, arg1;
479
+ {
480
+ struct nurbsdata *ndata;
481
+ GetNURBS(arg1, ndata);
482
+ gluEndTrim(ndata->nobj);
483
+ rb_ary_pop(n_current);
484
+
485
+ return Qnil;
486
+ }
487
+ static VALUE
488
+ glu_PwlCurve(argc, argv, obj)
489
+ int argc;
490
+ VALUE *argv;
491
+ VALUE obj;
492
+ {
493
+ struct nurbsdata *ndata;
494
+ GLint count;
495
+ GLfloat *array;
496
+ GLint stride;
497
+ GLenum type;
498
+
499
+ VALUE args[5];
500
+ VALUE ary_ctl1;
501
+
502
+ switch (rb_scan_args(argc, argv, "32", &args[0], &args[1], &args[2], &args[3], &args[4])) {
503
+ case 3:
504
+ count = (GLint)RARRAY_LENINT(args[1]);
505
+ type = NUM2INT(args[2]);
506
+ stride = (type == GLU_MAP1_TRIM_2 ? 2 : 3);
507
+
508
+ array = ALLOC_N(GLfloat, count*stride);
509
+ ary_ctl1 = rb_funcall(args[1],rb_intern("flatten"),0);
510
+ ary2cflt(ary_ctl1, array, count*stride);
511
+ break;
512
+ case 5:
513
+ count = NUM2INT(args[1]);
514
+ stride = NUM2INT(args[3]);
515
+ type = NUM2INT(args[4]);
516
+
517
+ array = ALLOC_N(GLfloat, count*stride);
518
+ ary_ctl1 = rb_funcall(args[2],rb_intern("flatten"),0);
519
+ ary2cflt(ary_ctl1, array, count*stride);
520
+ break;
521
+ default:
522
+ rb_raise(rb_eArgError, "gluPwlCurve needs 3 or 5 arguments");
523
+ return Qnil; /* not reached */
524
+ }
525
+
526
+ GetNURBS(args[0], ndata);
527
+ gluPwlCurve(ndata->nobj, count, array, stride, type);
528
+ free(array);
529
+
530
+ return Qnil;
531
+ }
532
+
533
+ static VALUE glu_LoadSamplingMatrices(obj,arg1,arg2,arg3,arg4)
534
+ VALUE obj, arg1,arg2,arg3,arg4;
535
+ {
536
+ struct nurbsdata *ndata;
537
+ GLfloat mdl_mtx[4*4];
538
+ GLfloat persp_mtx[4*4];
539
+ GLint viewport[4];
540
+
541
+ GetNURBS(arg1, ndata);
542
+ ary2cmatfloat(arg2,mdl_mtx,4,4);
543
+ ary2cmatfloat(arg3,persp_mtx,4,4);
544
+ ary2cint(arg4,viewport,4);
545
+
546
+ gluLoadSamplingMatrices(ndata->nobj,mdl_mtx,persp_mtx,viewport);
547
+
548
+
549
+ return Qnil;
550
+ }
551
+
552
+ /*
553
+ * Tesselation API
554
+ */
555
+ static VALUE t_current;
556
+ #define TESS_DATA 0
557
+ #define TESS_BEGIN 1
558
+ #define TESS_VERTEX 2
559
+ #define TESS_END 3
560
+ #define TESS_ERROR 4
561
+ #define TESS_EDGE_FLAG 5
562
+ #define TESS_OUTDATA 6
563
+ #define TESS_COMBINE 7
564
+ #define TESS_BEGIN_DATA 8
565
+ #define TESS_VERTEX_DATA 9
566
+ #define TESS_END_DATA 10
567
+ #define TESS_ERROR_DATA 11
568
+ #define TESS_EDGE_FLAG_DATA 12
569
+ #define TESS_COMBINE_DATA 13
570
+ #define TESS_USERDATA 14
571
+
572
+ static void
573
+ mark_tess(tdata)
574
+ struct tessdata* tdata;
575
+ {
576
+ if (tdata->tobj)
577
+ rb_gc_mark(tdata->t_ref);
578
+ }
579
+ static void
580
+ free_tess(tdata)
581
+ struct tessdata *tdata;
582
+ {
583
+ if (tdata->tobj)
584
+ gluDeleteTess(tdata->tobj);
585
+ tdata->t_ref = Qnil;
586
+ tdata->tobj = NULL;
587
+ }
588
+ static VALUE
589
+ glu_NewTess(obj)
590
+ VALUE obj;
591
+ {
592
+ VALUE ret;
593
+ struct tessdata *tdata;
594
+ ret = Data_Make_Struct(cTess, struct tessdata, mark_tess, free_tess, tdata);
595
+ tdata->tobj = gluNewTess();
596
+ tdata->t_ref = rb_ary_new2(REF_LAST);
597
+
598
+ return ret;
599
+ }
600
+ static VALUE
601
+ glu_DeleteTess(obj, arg1)
602
+ VALUE obj, arg1;
603
+ {
604
+ struct tessdata *tdata;
605
+ GetTESS(arg1, tdata);
606
+ free_tess(tdata);
607
+
608
+ return Qnil;
609
+ }
610
+
611
+ /* tess* callback function wrappers */
612
+ #define TESS_CALLBACK_COMMON \
613
+ VALUE tess; \
614
+ struct tessdata *tdata; \
615
+ tess = rb_ary_entry(t_current, -1); \
616
+ if (tess == Qnil) \
617
+ return; \
618
+ GetTESS(tess, tdata);
619
+
620
+ static void CALLBACK
621
+ t_begin(type)
622
+ GLenum type;
623
+ {
624
+ TESS_CALLBACK_COMMON
625
+ rb_funcall(rb_ary_entry(tdata->t_ref, TESS_BEGIN), callId, 1, INT2NUM(type));
626
+ }
627
+ static void CALLBACK
628
+ t_edgeFlag(flag)
629
+ GLboolean flag;
630
+ {
631
+ TESS_CALLBACK_COMMON
632
+ rb_funcall(rb_ary_entry(tdata->t_ref, TESS_EDGE_FLAG), callId, 1, GLBOOL2RUBY(flag));
633
+ }
634
+ static void CALLBACK
635
+ t_vertex(data)
636
+ void* data;
637
+ {
638
+ TESS_CALLBACK_COMMON
639
+ rb_funcall(rb_ary_entry(tdata->t_ref, TESS_VERTEX), callId, 1, (VALUE) data);
640
+ }
641
+ static void CALLBACK
642
+ t_end()
643
+ {
644
+ TESS_CALLBACK_COMMON
645
+ rb_funcall(rb_ary_entry(tdata->t_ref, TESS_END), callId, 0);
646
+ }
647
+ static void CALLBACK
648
+ t_error(errorno)
649
+ GLenum errorno;
650
+ {
651
+ TESS_CALLBACK_COMMON
652
+ rb_funcall(rb_ary_entry(tdata->t_ref, TESS_ERROR), callId, 1, INT2NUM(errorno));
653
+ }
654
+ static void CALLBACK
655
+ t_begin_data(type, user_data)
656
+ GLenum type;
657
+ void* user_data;
658
+ {
659
+ TESS_CALLBACK_COMMON
660
+ // TODO error_data was not cast before
661
+ rb_funcall(rb_ary_entry(tdata->t_ref, TESS_BEGIN_DATA), callId, 2, INT2NUM(type), (VALUE) user_data);
662
+ }
663
+ static void CALLBACK
664
+ t_edgeFlag_data(flag, user_data)
665
+ GLboolean flag;
666
+ void* user_data;
667
+ {
668
+ TESS_CALLBACK_COMMON
669
+ // TODO error_data was not cast before
670
+ rb_funcall(rb_ary_entry(tdata->t_ref, TESS_EDGE_FLAG_DATA), callId, 2, GLBOOL2RUBY(flag),(VALUE) user_data);
671
+ }
672
+ static void CALLBACK
673
+ t_vertex_data(data, user_data)
674
+ void* data;
675
+ void* user_data;
676
+ {
677
+ TESS_CALLBACK_COMMON
678
+ // TODO error_data was not cast before
679
+ rb_funcall(rb_ary_entry(tdata->t_ref, TESS_VERTEX_DATA), callId, 2, (VALUE) data, (VALUE) user_data);
680
+ }
681
+ static void CALLBACK
682
+ t_end_data(user_data)
683
+ void* user_data;
684
+ {
685
+ TESS_CALLBACK_COMMON
686
+ // TODO error_data was not cast before
687
+ rb_funcall(rb_ary_entry(tdata->t_ref, TESS_END_DATA), callId, 1, (VALUE) user_data);
688
+ }
689
+ static void CALLBACK
690
+ t_error_data(errorno, user_data)
691
+ GLenum errorno;
692
+ void* user_data;
693
+ {
694
+ TESS_CALLBACK_COMMON
695
+ // TODO error_data was not cast before
696
+ rb_funcall(rb_ary_entry(tdata->t_ref, TESS_ERROR_DATA), callId, 2, INT2NUM(errorno), (VALUE) user_data);
697
+ }
698
+
699
+ static void CALLBACK
700
+ t_combine(coords, vertex_data, weight, outData)
701
+ GLdouble coords[3];
702
+ void* vertex_data[4];
703
+ GLfloat weight[4];
704
+ void** outData;
705
+ {
706
+ VALUE rb_coord, rb_vertex_data, rb_weight;
707
+ int i;
708
+ TESS_CALLBACK_COMMON
709
+
710
+ rb_coord = rb_ary_new2(3);
711
+ for (i = 0; i < 3; i++)
712
+ rb_ary_store(rb_coord, i, rb_float_new(coords[i]));
713
+ rb_vertex_data = rb_ary_new2(4);
714
+ for (i = 0; i < 4; i++)
715
+ rb_ary_store(rb_vertex_data, i, (VALUE)vertex_data[i]);
716
+ rb_weight = rb_ary_new2(4);
717
+ for (i = 0; i < 4; i++)
718
+ rb_ary_store(rb_weight, i, rb_float_new(weight[i]));
719
+ *outData = (void*)rb_funcall(rb_ary_entry(tdata->t_ref, TESS_COMBINE), callId, 3, rb_coord, rb_vertex_data, rb_weight);
720
+ rb_ary_push(rb_ary_entry(tdata->t_ref, TESS_OUTDATA), (VALUE)*outData);
721
+ }
722
+
723
+ static void CALLBACK
724
+ t_combine_data(coords, vertex_data, weight, outData, user_data)
725
+ GLdouble coords[3];
726
+ void* vertex_data[4];
727
+ GLfloat weight[4];
728
+ void** outData;
729
+ void* user_data;
730
+ {
731
+ VALUE rb_coord, rb_vertex_data, rb_weight;
732
+ int i;
733
+ TESS_CALLBACK_COMMON
734
+
735
+ rb_coord = rb_ary_new2(3);
736
+ for (i = 0; i < 3; i++)
737
+ rb_ary_store(rb_coord, i, rb_float_new(coords[i]));
738
+ rb_vertex_data = rb_ary_new2(4);
739
+ for (i = 0; i < 4; i++)
740
+ rb_ary_store(rb_vertex_data, i, (VALUE)vertex_data[i]);
741
+ rb_weight = rb_ary_new2(4);
742
+ for (i = 0; i < 4; i++)
743
+ rb_ary_store(rb_weight, i, rb_float_new(weight[i]));
744
+
745
+ *outData = (void*)rb_funcall(rb_ary_entry(tdata->t_ref, TESS_COMBINE_DATA), callId, 4, rb_coord, rb_vertex_data, rb_weight, (VALUE)user_data);
746
+
747
+ rb_ary_push(rb_ary_entry(tdata->t_ref, TESS_OUTDATA), (VALUE)*outData);
748
+ }
749
+
750
+ #undef TESS_CALLBACK_COMMON
751
+
752
+ static VALUE
753
+ glu_TessProperty(obj, arg1, arg2, arg3)
754
+ VALUE obj, arg1, arg2, arg3;
755
+ {
756
+ struct tessdata* tdata;
757
+ GLenum property;
758
+ GLdouble value;
759
+ GetTESS(arg1, tdata);
760
+ property = (GLenum)NUM2INT(arg2);
761
+ if (property == GLU_TESS_BOUNDARY_ONLY) {
762
+ value = (GLdouble)RUBYBOOL2GL(arg3);
763
+ } else {
764
+ value = (GLdouble)NUM2DBL(arg3);
765
+ }
766
+ gluTessProperty(tdata->tobj, property, value);
767
+
768
+ return Qnil;
769
+ }
770
+ static VALUE
771
+ glu_GetTessProperty(obj, arg1, arg2)
772
+ VALUE obj, arg1, arg2;
773
+ {
774
+ struct tessdata* tdata;
775
+ GLenum property;
776
+ GLdouble value;
777
+ GetTESS(arg1, tdata);
778
+ property = (GLenum)NUM2INT(arg2);
779
+ gluGetTessProperty(tdata->tobj, property, &value);
780
+
781
+ return cond_GLBOOL2RUBY_D(property,value);
782
+ }
783
+ static VALUE
784
+ glu_TessNormal(obj, arg1, arg2, arg3, arg4)
785
+ VALUE obj, arg1, arg2, arg3, arg4;
786
+ {
787
+ struct tessdata* tdata;
788
+ GLdouble x, y, z;
789
+ GetTESS(arg1, tdata);
790
+ x = (GLdouble)NUM2DBL(arg2);
791
+ y = (GLdouble)NUM2DBL(arg3);
792
+ z = (GLdouble)NUM2DBL(arg4);
793
+ gluTessNormal(tdata->tobj, x, y, z);
794
+
795
+ return Qnil;
796
+ }
797
+ static VALUE
798
+ glu_TessBeginPolygon(obj, arg1, arg2)
799
+ VALUE obj, arg1, arg2;
800
+ {
801
+ struct tessdata* tdata;
802
+ GetTESS(arg1, tdata);
803
+ rb_ary_store(tdata->t_ref, TESS_USERDATA, arg2);
804
+ rb_ary_store(tdata->t_ref, TESS_OUTDATA, rb_ary_new());
805
+ rb_ary_store(tdata->t_ref, TESS_DATA, rb_ary_new());
806
+ rb_ary_push(t_current, arg1);
807
+ gluTessBeginPolygon(tdata->tobj, (void*)arg2);
808
+
809
+ return Qnil;
810
+ }
811
+ static VALUE
812
+ glu_TessEndPolygon(obj, arg1)
813
+ VALUE obj, arg1;
814
+ {
815
+ struct tessdata* tdata;
816
+ GetTESS(arg1, tdata);
817
+ gluTessEndPolygon(tdata->tobj);
818
+ rb_ary_store(tdata->t_ref, TESS_USERDATA, Qnil);
819
+ rb_ary_store(tdata->t_ref, TESS_OUTDATA, Qnil);
820
+ rb_ary_store(tdata->t_ref, TESS_DATA, Qnil);
821
+ rb_ary_pop(t_current);
822
+
823
+ return Qnil;
824
+ }
825
+ static VALUE
826
+ glu_TessBeginContour(obj, arg1)
827
+ VALUE obj, arg1;
828
+ {
829
+ struct tessdata* tdata;
830
+ GetTESS(arg1, tdata);
831
+ gluTessBeginContour(tdata->tobj);
832
+
833
+ return Qnil;
834
+ }
835
+ static VALUE
836
+ glu_TessEndContour(obj, arg1)
837
+ VALUE obj, arg1;
838
+ {
839
+ struct tessdata* tdata;
840
+ GetTESS(arg1, tdata);
841
+ gluTessEndContour(tdata->tobj);
842
+
843
+ return Qnil;
844
+ }
845
+
846
+ #define TESS_CALLBACK_CASE(_type_,_function_) \
847
+ case GLU_##_type_: \
848
+ rb_ary_store(tdata->t_ref, _type_, arg3); \
849
+ if (NIL_P(arg3)) \
850
+ gluTessCallback(tdata->tobj, type, NULL); \
851
+ else \
852
+ gluTessCallback(tdata->tobj, type, _function_); \
853
+ break;
854
+
855
+ static VALUE
856
+ glu_TessCallback(obj, arg1, arg2, arg3)
857
+ VALUE obj, arg1, arg2, arg3;
858
+ {
859
+ struct tessdata* tdata;
860
+ GLenum type;
861
+ GetTESS(arg1, tdata);
862
+ type = (GLenum)NUM2INT(arg2);
863
+ if (!rb_obj_is_kind_of(arg3,rb_cProc) && !NIL_P(arg3))
864
+ rb_raise(rb_eTypeError, "gluTessCallback needs Proc Object:%s",rb_class2name(CLASS_OF(arg3)));
865
+
866
+ switch (type) {
867
+ TESS_CALLBACK_CASE(TESS_BEGIN,t_begin)
868
+ TESS_CALLBACK_CASE(TESS_BEGIN_DATA,t_begin_data)
869
+ TESS_CALLBACK_CASE(TESS_EDGE_FLAG,t_edgeFlag)
870
+ TESS_CALLBACK_CASE(TESS_EDGE_FLAG_DATA,t_edgeFlag_data)
871
+ TESS_CALLBACK_CASE(TESS_VERTEX,t_vertex)
872
+ TESS_CALLBACK_CASE(TESS_VERTEX_DATA,t_vertex_data)
873
+ TESS_CALLBACK_CASE(TESS_END,t_end)
874
+ TESS_CALLBACK_CASE(TESS_END_DATA,t_end_data)
875
+ TESS_CALLBACK_CASE(TESS_ERROR,t_error)
876
+ TESS_CALLBACK_CASE(TESS_ERROR_DATA,t_error_data)
877
+ TESS_CALLBACK_CASE(TESS_COMBINE,t_combine)
878
+ TESS_CALLBACK_CASE(TESS_COMBINE_DATA,t_combine_data)
879
+ }
880
+
881
+ return Qnil;
882
+ }
883
+ #undef TESS_CALLBACK_CASE
884
+
885
+ static VALUE
886
+ glu_BeginPolygon(obj, arg1)
887
+ VALUE obj, arg1;
888
+ {
889
+ struct tessdata* tdata;
890
+ GetTESS(arg1, tdata);
891
+ rb_ary_store(tdata->t_ref, TESS_DATA, rb_ary_new());
892
+ rb_ary_push(t_current, arg1);
893
+ gluBeginPolygon(tdata->tobj);
894
+
895
+ return Qnil;
896
+ }
897
+ static VALUE
898
+ glu_TessVertex(obj, arg1, arg2, arg3)
899
+ VALUE obj, arg1, arg2, arg3;
900
+ {
901
+ struct tessdata* tdata;
902
+ GLdouble v[3] = {0.0,0.0,0.0};
903
+ GetTESS(arg1, tdata);
904
+ rb_ary_push(rb_ary_entry(tdata->t_ref, TESS_DATA), arg3);
905
+ Check_Type(arg2,T_ARRAY);
906
+ ary2cdbl(arg2, v, 3);
907
+ gluTessVertex(tdata->tobj, v,(void *)arg3);
908
+
909
+ return Qnil;
910
+ }
911
+ static VALUE
912
+ glu_NextContour(obj, arg1, arg2)
913
+ VALUE obj, arg1, arg2;
914
+ {
915
+ struct tessdata* tdata;
916
+ GLenum type;
917
+ GetTESS(arg1, tdata);
918
+ type = (GLenum)NUM2INT(arg2);
919
+ gluNextContour(tdata->tobj, type);
920
+
921
+ return Qnil;
922
+ }
923
+ static VALUE
924
+ glu_EndPolygon(obj, arg1)
925
+ VALUE obj, arg1;
926
+ {
927
+ struct tessdata* tdata;
928
+ GetTESS(arg1, tdata);
929
+ gluEndPolygon(tdata->tobj);
930
+ rb_ary_store(tdata->t_ref, TESS_DATA, Qnil);
931
+ rb_ary_pop(t_current);
932
+
933
+ return Qnil;
934
+ }
935
+
936
+ /*
937
+ * Quadric API
938
+ */
939
+ static VALUE q_current;
940
+
941
+ static void CALLBACK
942
+ q_error(errorno)
943
+ GLenum errorno;
944
+ {
945
+ VALUE quad;
946
+ struct quaddata *qdata;
947
+ quad = rb_ary_entry(q_current, -1);
948
+ if (quad == Qnil)
949
+ return;
950
+ GetQUAD(quad, qdata);
951
+ rb_funcall(rb_ary_entry(qdata->q_ref, GLU_ERROR), callId, 1, INT2NUM(errorno));
952
+ }
953
+
954
+ static VALUE
955
+ glu_QuadricCallback(obj, arg1, arg2, arg3)
956
+ VALUE obj, arg1, arg2, arg3;
957
+ {
958
+ struct quaddata* qdata;
959
+ GLenum type;
960
+ GetQUAD(arg1, qdata);
961
+ type = (GLenum)NUM2INT(arg2);
962
+ if (!rb_obj_is_kind_of(arg3,rb_cProc) && !NIL_P(arg3))
963
+ rb_raise(rb_eTypeError, "gluQuadricCallback needs Proc Object:%s",rb_class2name(CLASS_OF(arg3)));
964
+
965
+
966
+ if (type!=GLU_ERROR)
967
+ return Qnil;
968
+
969
+ rb_ary_store(qdata->q_ref, type, arg3);
970
+ if (NIL_P(arg3))
971
+ gluQuadricCallback(qdata->qobj, type, NULL);
972
+ else
973
+ gluQuadricCallback(qdata->qobj, type, q_error);
974
+
975
+
976
+ return Qnil;
977
+ }
978
+
979
+ static void
980
+ free_quad(qdata)
981
+ struct quaddata *qdata;
982
+ {
983
+ if (qdata->qobj) gluDeleteQuadric(qdata->qobj);
984
+ qdata->qobj = NULL;
985
+ qdata->q_ref = Qnil;
986
+ }
987
+ static void
988
+ mark_quad(qdata)
989
+ struct quaddata* qdata;
990
+ {
991
+ if (qdata->qobj)
992
+ rb_gc_mark(qdata->q_ref);
993
+ }
994
+ static VALUE
995
+ glu_NewQuadric(obj)
996
+ VALUE obj;
997
+ {
998
+ VALUE ret;
999
+ struct quaddata *qdata;
1000
+ ret = Data_Make_Struct(cQuad, struct quaddata, mark_quad, free_quad, qdata);
1001
+ qdata->qobj = gluNewQuadric();
1002
+ qdata->q_ref = rb_ary_new2(REF_LAST);
1003
+
1004
+ return ret;
1005
+ }
1006
+ static VALUE
1007
+ glu_DeleteQuadric(obj, arg1)
1008
+ VALUE obj, arg1;
1009
+ {
1010
+ struct quaddata *qdata;
1011
+ GetQUAD(arg1, qdata);
1012
+ free_quad(qdata);
1013
+
1014
+ return Qnil;
1015
+ }
1016
+ static VALUE
1017
+ glu_QuadricNormals(obj, arg1, arg2)
1018
+ VALUE obj, arg1, arg2;
1019
+ {
1020
+ struct quaddata* qdata;
1021
+ GLenum normals;
1022
+ GetQUAD(arg1, qdata);
1023
+ normals = (GLenum)NUM2INT(arg2);
1024
+ gluQuadricNormals(qdata->qobj, normals);
1025
+
1026
+ return Qnil;
1027
+ }
1028
+ static VALUE
1029
+ glu_QuadricTexture(obj, arg1, arg2)
1030
+ VALUE obj, arg1, arg2;
1031
+ {
1032
+ struct quaddata* qdata;
1033
+ GLboolean textureCoords;
1034
+ GetQUAD(arg1, qdata);
1035
+ textureCoords = (GLboolean)RUBYBOOL2GL(arg2);
1036
+ gluQuadricTexture(qdata->qobj, textureCoords);
1037
+
1038
+ return Qnil;
1039
+ }
1040
+ static VALUE
1041
+ glu_QuadricOrientation(obj, arg1, arg2)
1042
+ VALUE obj, arg1, arg2;
1043
+ {
1044
+ struct quaddata* qdata;
1045
+ GLenum orientation;
1046
+ GetQUAD(arg1, qdata);
1047
+ orientation = (GLenum)NUM2INT(arg2);
1048
+ gluQuadricOrientation(qdata->qobj, orientation);
1049
+
1050
+ return Qnil;
1051
+ }
1052
+ static VALUE
1053
+ glu_QuadricDrawStyle(obj, arg1, arg2)
1054
+ VALUE obj, arg1, arg2;
1055
+ {
1056
+ struct quaddata* qdata;
1057
+ GLenum drawStyle;
1058
+ GetQUAD(arg1, qdata);
1059
+ drawStyle = (GLenum)NUM2INT(arg2);
1060
+ gluQuadricDrawStyle(qdata->qobj, drawStyle);
1061
+
1062
+ return Qnil;
1063
+ }
1064
+ static VALUE
1065
+ glu_Cylinder(obj, arg1, arg2, arg3, arg4, arg5, arg6)
1066
+ VALUE obj, arg1, arg2, arg3, arg4, arg5, arg6;
1067
+ {
1068
+ struct quaddata* qdata;
1069
+ GLdouble baseRadius;
1070
+ GLdouble topRadius;
1071
+ GLdouble height;
1072
+ GLint slices;
1073
+ GLint stacks;
1074
+
1075
+ GetQUAD(arg1, qdata);
1076
+ baseRadius = (GLdouble)NUM2DBL(arg2);
1077
+ topRadius = (GLdouble)NUM2DBL(arg3);
1078
+ height = (GLdouble)NUM2DBL(arg4);
1079
+ slices = (GLint)NUM2INT(arg5);
1080
+ stacks = (GLint)NUM2INT(arg6);
1081
+
1082
+ rb_ary_push(q_current, arg1);
1083
+ gluCylinder(qdata->qobj, baseRadius, topRadius, height, slices, stacks);
1084
+ rb_ary_pop(q_current);
1085
+
1086
+ return Qnil;
1087
+ }
1088
+ static VALUE
1089
+ glu_Disk(obj, arg1, arg2, arg3, arg4, arg5)
1090
+ VALUE obj, arg1, arg2, arg3, arg4, arg5;
1091
+ {
1092
+ struct quaddata* qdata;
1093
+ GLdouble innerRadius;
1094
+ GLdouble outerRadius;
1095
+ GLint slices;
1096
+ GLint loops;
1097
+
1098
+ GetQUAD(arg1, qdata);
1099
+ innerRadius = (GLdouble)NUM2DBL(arg2);
1100
+ outerRadius = (GLdouble)NUM2DBL(arg3);
1101
+ slices = (GLint)NUM2INT(arg4);
1102
+ loops = (GLint)NUM2INT(arg5);
1103
+
1104
+ rb_ary_push(q_current, arg1);
1105
+
1106
+ gluDisk(qdata->qobj, innerRadius, outerRadius, slices, loops);
1107
+ rb_ary_pop(q_current);
1108
+
1109
+ return Qnil;
1110
+ }
1111
+ static VALUE
1112
+ glu_PartialDisk(obj, arg1, arg2, arg3, arg4, arg5, arg6, arg7)
1113
+ VALUE obj, arg1, arg2, arg3, arg4, arg5, arg6, arg7;
1114
+ {
1115
+ struct quaddata* qdata;
1116
+ GLdouble innerRadius;
1117
+ GLdouble outerRadius;
1118
+ GLint slices;
1119
+ GLint loops;
1120
+ GLdouble startAngle;
1121
+ GLdouble sweepAngle;
1122
+
1123
+ GetQUAD(arg1, qdata);
1124
+ innerRadius = (GLdouble)NUM2DBL(arg2);
1125
+ outerRadius = (GLdouble)NUM2DBL(arg3);
1126
+ slices = (GLint)NUM2INT(arg4);
1127
+ loops = (GLint)NUM2INT(arg5);
1128
+ startAngle = (GLdouble)NUM2DBL(arg6);
1129
+ sweepAngle = (GLdouble)NUM2DBL(arg7);
1130
+
1131
+ rb_ary_push(q_current, arg1);
1132
+ gluPartialDisk(qdata->qobj, innerRadius, outerRadius, slices, loops, startAngle, sweepAngle);
1133
+ rb_ary_pop(q_current);
1134
+
1135
+ return Qnil;
1136
+ }
1137
+ static VALUE
1138
+ glu_Sphere(obj, arg1, arg2, arg3, arg4)
1139
+ VALUE obj, arg1, arg2, arg3, arg4;
1140
+ {
1141
+ struct quaddata* qdata;
1142
+ GLdouble radius;
1143
+ GLint slices;
1144
+ GLint stacks;
1145
+
1146
+ GetQUAD(arg1, qdata);
1147
+ radius = (GLdouble)NUM2DBL(arg2);
1148
+ slices = (GLint)NUM2INT(arg3);
1149
+ stacks = (GLint)NUM2INT(arg4);
1150
+
1151
+ rb_ary_push(q_current, arg1);
1152
+ gluSphere(qdata->qobj, radius, slices, stacks);
1153
+ rb_ary_pop(q_current);
1154
+
1155
+ return Qnil;
1156
+ }
1157
+
1158
+ /* */
1159
+
1160
+ static VALUE
1161
+ glu_LookAt(obj,arg1,arg2,arg3,arg4,arg5,arg6,arg7,arg8,arg9)
1162
+ VALUE obj,arg1,arg2,arg3,arg4,arg5,arg6,arg7,arg8,arg9;
1163
+ {
1164
+ GLdouble eyex;
1165
+ GLdouble eyey;
1166
+ GLdouble eyez;
1167
+ GLdouble centerx;
1168
+ GLdouble centery;
1169
+ GLdouble centerz;
1170
+ GLdouble upx;
1171
+ GLdouble upy;
1172
+ GLdouble upz;
1173
+ eyex = (GLdouble)NUM2DBL(arg1);
1174
+ eyey = (GLdouble)NUM2DBL(arg2);
1175
+ eyez = (GLdouble)NUM2DBL(arg3);
1176
+ centerx = (GLdouble)NUM2DBL(arg4);
1177
+ centery = (GLdouble)NUM2DBL(arg5);
1178
+ centerz = (GLdouble)NUM2DBL(arg6);
1179
+ upx = (GLdouble)NUM2DBL(arg7);
1180
+ upy = (GLdouble)NUM2DBL(arg8);
1181
+ upz = (GLdouble)NUM2DBL(arg9);
1182
+ gluLookAt( eyex, eyey, eyez, centerx, centery, centerz, upx, upy, upz );
1183
+
1184
+ return Qnil;
1185
+ }
1186
+ static VALUE
1187
+ glu_Ortho2D(obj,arg1,arg2,arg3,arg4)
1188
+ VALUE obj,arg1,arg2,arg3,arg4;
1189
+ {
1190
+ GLdouble left;
1191
+ GLdouble right;
1192
+ GLdouble bottom;
1193
+ GLdouble top;
1194
+ left = (GLdouble)NUM2DBL(arg1);
1195
+ right = (GLdouble)NUM2DBL(arg2);
1196
+ bottom = (GLdouble)NUM2DBL(arg3);
1197
+ top = (GLdouble)NUM2DBL(arg4);
1198
+ gluOrtho2D(left,right,bottom,top);
1199
+
1200
+ return Qnil;
1201
+ }
1202
+ static VALUE
1203
+ glu_Perspective(obj,arg1,arg2,arg3,arg4)
1204
+ VALUE obj,arg1,arg2,arg3,arg4;
1205
+ {
1206
+ GLdouble fovy;
1207
+ GLdouble aspect;
1208
+ GLdouble zNear;
1209
+ GLdouble zFar;
1210
+ fovy = (GLdouble)NUM2DBL(arg1);
1211
+ aspect = (GLdouble)NUM2DBL(arg2);
1212
+ zNear = (GLdouble)NUM2DBL(arg3);
1213
+ zFar = (GLdouble)NUM2DBL(arg4);
1214
+ gluPerspective(fovy,aspect,zNear,zFar);
1215
+
1216
+ return Qnil;
1217
+ }
1218
+ static VALUE
1219
+ glu_PickMatrix(argc,argv,obj)
1220
+ int argc;
1221
+ VALUE* argv;
1222
+ VALUE obj;
1223
+ {
1224
+ GLdouble x;
1225
+ GLdouble y;
1226
+ GLdouble width;
1227
+ GLdouble height;
1228
+ GLint viewport[4];
1229
+
1230
+ VALUE args[5];
1231
+
1232
+ switch (rb_scan_args(argc, argv, "23", &args[0], &args[1], &args[2], &args[3], &args[4])) {
1233
+ case 2:
1234
+ width = 5.0f;
1235
+ height = 5.0f;
1236
+ glGetIntegerv(GL_VIEWPORT, viewport);
1237
+ break;
1238
+ case 4:
1239
+ width = (GLdouble)NUM2DBL(args[2]);
1240
+ height = (GLdouble)NUM2DBL(args[3]);
1241
+ glGetIntegerv(GL_VIEWPORT, viewport);
1242
+ break;
1243
+ case 5:
1244
+ width = (GLdouble)NUM2DBL(args[2]);
1245
+ height = (GLdouble)NUM2DBL(args[3]);
1246
+ ary2cint(args[4], viewport, 4);
1247
+ break;
1248
+ default:
1249
+ rb_raise(rb_eArgError, "gluPickMatrix needs 2,4 or 5 parameters");
1250
+ }
1251
+ x = (GLdouble)NUM2DBL(args[0]);
1252
+ y = (GLdouble)NUM2DBL(args[1]);
1253
+ gluPickMatrix(x, y, width, height, viewport);
1254
+
1255
+ return Qnil;
1256
+ }
1257
+
1258
+ static VALUE
1259
+ glu_Project(argc,argv,obj)
1260
+ int argc;
1261
+ VALUE* argv;
1262
+ VALUE obj;
1263
+ {
1264
+ GLdouble ox;
1265
+ GLdouble oy;
1266
+ GLdouble oz;
1267
+ GLdouble mdl_mtx[4*4];
1268
+ GLdouble prj_mtx[4*4];
1269
+ GLint vport[4];
1270
+ GLdouble wx;
1271
+ GLdouble wy;
1272
+ GLdouble wz;
1273
+
1274
+ VALUE args[6];
1275
+
1276
+ switch (rb_scan_args(argc, argv, "33", &args[0], &args[1], &args[2], &args[3], &args[4], &args[5])) {
1277
+ case 3:
1278
+ glGetDoublev(GL_MODELVIEW_MATRIX, mdl_mtx);
1279
+ glGetDoublev(GL_PROJECTION_MATRIX, prj_mtx);
1280
+ glGetIntegerv(GL_VIEWPORT, vport);
1281
+ break;
1282
+ case 6:
1283
+ ary2cmatdouble(args[3], mdl_mtx, 4, 4);
1284
+ ary2cmatdouble(args[4], prj_mtx, 4, 4);
1285
+ ary2cint(args[5], vport, 4);
1286
+ break;
1287
+ default:
1288
+ rb_raise(rb_eArgError, "gluProject needs 3 or 6 parameters");
1289
+ }
1290
+ ox = (GLdouble)NUM2DBL(args[0]);
1291
+ oy = (GLdouble)NUM2DBL(args[1]);
1292
+ oz = (GLdouble)NUM2DBL(args[2]);
1293
+
1294
+ if (gluProject(ox, oy, oz, mdl_mtx, prj_mtx, vport, &wx, &wy, &wz) == GL_TRUE) {
1295
+
1296
+ return rb_ary_new3(3, rb_float_new(wx), rb_float_new(wy), rb_float_new(wz));
1297
+ } else {
1298
+
1299
+ check_for_gluerror(GLU_INVALID_VALUE);
1300
+ return Qnil; /* not reached */
1301
+ }
1302
+ }
1303
+ static VALUE
1304
+ glu_UnProject(argc,argv,obj)
1305
+ int argc;
1306
+ VALUE* argv;
1307
+ VALUE obj;
1308
+ {
1309
+ GLdouble wx;
1310
+ GLdouble wy;
1311
+ GLdouble wz;
1312
+ GLdouble mdl_mtx[4*4];
1313
+ GLdouble prj_mtx[4*4];
1314
+ GLint vport[4];
1315
+ GLdouble ox;
1316
+ GLdouble oy;
1317
+ GLdouble oz;
1318
+
1319
+ VALUE args[6];
1320
+
1321
+ switch (rb_scan_args(argc, argv, "33", &args[0], &args[1], &args[2], &args[3], &args[4], &args[5])) {
1322
+ case 3:
1323
+ glGetDoublev(GL_MODELVIEW_MATRIX, mdl_mtx);
1324
+ glGetDoublev(GL_PROJECTION_MATRIX, prj_mtx);
1325
+ glGetIntegerv(GL_VIEWPORT, vport);
1326
+ break;
1327
+ case 6:
1328
+ ary2cmatdouble(args[3], mdl_mtx, 4, 4);
1329
+ ary2cmatdouble(args[4], prj_mtx, 4, 4);
1330
+ ary2cint(args[5], vport, 4);
1331
+ break;
1332
+ default:
1333
+ rb_raise(rb_eArgError, "gluUnProject needs 3 or 6 parameters");
1334
+ }
1335
+ wx = (GLdouble)NUM2DBL(args[0]);
1336
+ wy = (GLdouble)NUM2DBL(args[1]);
1337
+ wz = (GLdouble)NUM2DBL(args[2]);
1338
+
1339
+ if (gluUnProject(wx, wy, wz, mdl_mtx, prj_mtx, vport, &ox, &oy, &oz) == GL_TRUE) {
1340
+
1341
+ return rb_ary_new3(3, rb_float_new(ox), rb_float_new(oy), rb_float_new(oz));
1342
+ } else {
1343
+
1344
+ check_for_gluerror(GLU_INVALID_VALUE);
1345
+ return Qnil; /* not reached */
1346
+ }
1347
+ }
1348
+
1349
+ static VALUE
1350
+ glu_Build1DMipmaps(obj, arg1, arg2, arg3, arg4, arg5, arg6)
1351
+ VALUE obj, arg1, arg2, arg3, arg4, arg5, arg6;
1352
+ {
1353
+ GLenum target;
1354
+ GLint components;
1355
+ GLint width;
1356
+ GLenum format;
1357
+ GLenum type;
1358
+ int ret;
1359
+
1360
+ target = (GLenum)NUM2INT(arg1);
1361
+ components = (GLint)NUM2INT(arg2);
1362
+ width = (GLint)NUM2INT(arg3);
1363
+ format = (GLenum)NUM2INT(arg4);
1364
+ type = (GLenum)NUM2INT(arg5);
1365
+ Check_Type(arg6,T_STRING);
1366
+ CheckDataSize(type,format,width,arg6);
1367
+
1368
+ ret = gluBuild1DMipmaps(target, components, width, format, type, RSTRING_PTR(arg6));
1369
+ check_for_gluerror(ret);
1370
+
1371
+ return INT2NUM(ret);
1372
+ }
1373
+
1374
+ static VALUE
1375
+ glu_Build2DMipmaps(obj, arg1, arg2, arg3, arg4, arg5, arg6, arg7)
1376
+ VALUE obj, arg1, arg2, arg3, arg4, arg5, arg6, arg7;
1377
+ {
1378
+ GLenum target;
1379
+ GLint components;
1380
+ GLint width;
1381
+ GLint height;
1382
+ GLenum format;
1383
+ GLenum type;
1384
+ int ret;
1385
+
1386
+ target = (GLenum)NUM2INT(arg1);
1387
+ components = (GLint)NUM2INT(arg2);
1388
+ width = (GLint)NUM2INT(arg3);
1389
+ height = (GLint)NUM2INT(arg4);
1390
+ format = (GLenum)NUM2INT(arg5);
1391
+ type = (GLenum)NUM2INT(arg6);
1392
+ Check_Type(arg7,T_STRING);
1393
+ CheckDataSize(type,format,width*height,arg7);
1394
+
1395
+ ret = gluBuild2DMipmaps(target, components, width, height, format, type, RSTRING_PTR(arg7));
1396
+ check_for_gluerror(ret);
1397
+
1398
+ return INT2NUM(ret);
1399
+ }
1400
+
1401
+ static VALUE
1402
+ glu_ScaleImage(obj, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8)
1403
+ VALUE obj, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8;
1404
+ {
1405
+ GLenum format;
1406
+ GLint widthin;
1407
+ GLint heightin;
1408
+ GLenum typein;
1409
+ void* datain;
1410
+ GLint widthout;
1411
+ GLint heightout;
1412
+ GLenum typeout;
1413
+ VALUE ret;
1414
+ GLint retcode;
1415
+
1416
+ format = (GLenum)NUM2INT(arg1);
1417
+ widthin = (GLint)NUM2INT(arg2);
1418
+ heightin = (GLint)NUM2INT(arg3);
1419
+ typein = (GLenum)NUM2INT(arg4);
1420
+ Check_Type(arg5,T_STRING);
1421
+ CheckDataSize(typein,format,heightin*widthin,arg5);
1422
+ datain = RSTRING_PTR(arg5);
1423
+ widthout = (GLint)NUM2INT(arg6);
1424
+ heightout = (GLint)NUM2INT(arg7);
1425
+ typeout = (GLenum)NUM2INT(arg8);
1426
+ ret = allocate_buffer_with_string(GetDataSize(typeout,format,widthout*heightout));
1427
+ retcode = gluScaleImage(format, widthin, heightin, typein, datain,
1428
+ widthout, heightout, typeout, (GLvoid*)RSTRING_PTR(ret));
1429
+
1430
+ check_for_gluerror(retcode);
1431
+
1432
+ return ret;
1433
+ }
1434
+
1435
+ static VALUE
1436
+ glu_ErrorString(obj, arg1)
1437
+ VALUE obj, arg1;
1438
+ {
1439
+ GLenum errorCode;
1440
+ GLubyte* error;
1441
+ errorCode = (GLenum)NUM2INT(arg1);
1442
+ error = (GLubyte*)gluErrorString(errorCode);
1443
+
1444
+ if (error)
1445
+ return rb_str_new2((char *)error);
1446
+ else
1447
+ return Qnil;
1448
+ }
1449
+ static VALUE
1450
+ glu_GetString(obj, arg1)
1451
+ VALUE obj, arg1;
1452
+ {
1453
+ GLenum name;
1454
+ GLubyte* str;
1455
+ name = (GLenum)NUM2INT(arg1);
1456
+ str = (GLubyte*)gluGetString(name);
1457
+
1458
+ if (str)
1459
+ return rb_str_new2((char *)str);
1460
+ else
1461
+ return Qnil;
1462
+ }
1463
+
1464
+ static VALUE module;
1465
+
1466
+ DLLEXPORT void Init_glu()
1467
+ {
1468
+ callId = rb_intern("call");
1469
+ refId = rb_intern("[]");
1470
+ module = rb_define_module("Glu");
1471
+
1472
+ glu_init_enums(module);
1473
+
1474
+ rb_define_module_function(module, "gluNewNurbsRenderer", glu_NewNurbsRenderer, 0);
1475
+ rb_define_module_function(module, "gluDeleteNurbsRenderer", glu_DeleteNurbsRenderer, 1);
1476
+ rb_define_module_function(module, "gluNurbsProperty", glu_NurbsProperty, 3);
1477
+ rb_define_module_function(module, "gluGetNurbsProperty", glu_GetNurbsProperty, 2);
1478
+ rb_define_module_function(module, "gluBeginCurve", glu_BeginCurve, 1);
1479
+ rb_define_module_function(module, "gluEndCurve", glu_EndCurve, 1);
1480
+ rb_define_module_function(module, "gluNurbsCurve", glu_NurbsCurve, -1);
1481
+ rb_define_module_function(module, "gluBeginSurface", glu_BeginSurface, 1);
1482
+ rb_define_module_function(module, "gluEndSurface", glu_EndSurface, 1);
1483
+ rb_define_module_function(module, "gluNurbsSurface", glu_NurbsSurface, -1);
1484
+ rb_define_module_function(module, "gluBeginTrim", glu_BeginTrim, 1);
1485
+ rb_define_module_function(module, "gluEndTrim", glu_EndTrim, 1);
1486
+ rb_define_module_function(module, "gluPwlCurve", glu_PwlCurve, -1);
1487
+ rb_define_module_function(module, "gluNewTess", glu_NewTess, 0);
1488
+ rb_define_module_function(module, "gluDeleteTess", glu_DeleteTess, 1);
1489
+ rb_define_module_function(module, "gluTessCallback", glu_TessCallback, 3);
1490
+ rb_define_module_function(module, "gluBeginPolygon", glu_BeginPolygon, 1);
1491
+ rb_define_module_function(module, "gluTessVertex", glu_TessVertex, 3);
1492
+ rb_define_module_function(module, "gluNextContour", glu_NextContour, 2);
1493
+ rb_define_module_function(module, "gluEndPolygon", glu_EndPolygon, 1);
1494
+ rb_define_module_function(module, "gluTessBeginPolygon", glu_TessBeginPolygon, 2);
1495
+ rb_define_module_function(module, "gluTessBeginContour", glu_TessBeginContour, 1);
1496
+ rb_define_module_function(module, "gluTessEndContour", glu_TessEndContour, 1);
1497
+ rb_define_module_function(module, "gluTessEndPolygon", glu_TessEndPolygon, 1);
1498
+ rb_define_module_function(module, "gluTessProperty", glu_TessProperty, 3);
1499
+ rb_define_module_function(module, "gluTessNormal", glu_TessNormal, 4);
1500
+ rb_define_module_function(module, "gluGetTessProperty", glu_GetTessProperty, 2);
1501
+ rb_define_module_function(module, "gluNewQuadric", glu_NewQuadric, 0);
1502
+ rb_define_module_function(module, "gluDeleteQuadric", glu_DeleteQuadric, 1);
1503
+ rb_define_module_function(module, "gluQuadricNormals", glu_QuadricNormals, 2);
1504
+ rb_define_module_function(module, "gluQuadricTexture", glu_QuadricTexture, 2);
1505
+ rb_define_module_function(module, "gluQuadricOrientation", glu_QuadricOrientation, 2);
1506
+ rb_define_module_function(module, "gluQuadricDrawStyle", glu_QuadricDrawStyle, 2);
1507
+ rb_define_module_function(module, "gluCylinder", glu_Cylinder, 6);
1508
+ rb_define_module_function(module, "gluDisk", glu_Disk, 5);
1509
+ rb_define_module_function(module, "gluPartialDisk", glu_PartialDisk, 7);
1510
+ rb_define_module_function(module, "gluSphere", glu_Sphere, 4);
1511
+
1512
+ rb_define_module_function(module, "gluLookAt", glu_LookAt, 9);
1513
+ rb_define_module_function(module, "gluOrtho2D", glu_Ortho2D, 4);
1514
+ rb_define_module_function(module, "gluPerspective", glu_Perspective, 4);
1515
+ rb_define_module_function(module, "gluPickMatrix", glu_PickMatrix, -1);
1516
+ rb_define_module_function(module, "gluProject", glu_Project, -1);
1517
+ rb_define_module_function(module, "gluUnProject", glu_UnProject, -1);
1518
+ rb_define_module_function(module, "gluBuild1DMipmaps", glu_Build1DMipmaps, 6);
1519
+ rb_define_module_function(module, "gluBuild2DMipmaps", glu_Build2DMipmaps, 7);
1520
+ rb_define_module_function(module, "gluScaleImage", glu_ScaleImage, 8);
1521
+ rb_define_module_function(module, "gluErrorString", glu_ErrorString, 1);
1522
+ rb_define_module_function(module, "gluGetString", glu_GetString, 1);
1523
+
1524
+ rb_define_module_function(module, "gluLoadSamplingMatrices",glu_LoadSamplingMatrices,4);
1525
+ rb_define_module_function(module, "gluQuadricCallback", glu_QuadricCallback, 3);
1526
+ rb_define_module_function(module, "gluNurbsCallback", glu_NurbsCallback, 3);
1527
+
1528
+ Class_GLUError = rb_define_class_under(module, "Error", rb_eStandardError);
1529
+
1530
+ rb_define_method(Class_GLUError, "initialize", GLUError_initialize, 2);
1531
+ rb_define_attr(Class_GLUError, "id", 1, 0);
1532
+
1533
+ cNurbs = rb_define_class("Nurbs", rb_cObject);
1534
+ cTess = rb_define_class("Tess", rb_cObject);
1535
+ cQuad = rb_define_class("Quadric", rb_cObject);
1536
+
1537
+ rb_global_variable(&t_current); /* current active tesselator, nurbs and quadric, used for callbacks */
1538
+ t_current = rb_ary_new();
1539
+ rb_global_variable(&n_current);
1540
+ n_current = rb_ary_new();
1541
+ rb_global_variable(&q_current);
1542
+ q_current = rb_ary_new();
1543
+ }