[ruby-talk:21202] Re: OpenGL under windows
From:
"Anthony Cagle" <acagle@...>
Date:
2001-09-15 02:39:48 UTC
List:
ruby-talk #21202
I have finally managed to get Ruby OpenGL interface working on Windows ME
using Cygwin 1.3.1. Although I am not knowledgeable about Cygwin, Windows
or OpenGL., the steps I had to follow may be useful to someone else faced
with the same predicament.
First, without the help of Noboyuki Horie and Bill Kelly I would never have
gotten this working.. Both the glu.c and the glu.h files must be altered
inorder for the compile to run successfully. Since I do not really
understand how all of this works, I have simply included both files with
comments indicating where I made the changes. Search for "acc change
comment" to see the changes.
Thanks for all the help from everybody,
Anthony
****************************************************************************
*******
/* glu.ht */
/*
** License Applicability. Except to the extent portions of this file are
** made subject to an alternative license as permitted in the SGI Free
** Software License B, Version 1.1 (the "License"), the contents of this
** file are subject only to the provisions of the License. You may not use
** this file except in compliance with the License. You may obtain a copy
** of the License at Silicon Graphics, Inc., attn: Legal Services, 1600
** Amphitheatre Parkway, Mountain View, CA 94043-1351, or at:
**
** http://oss.sgi.com/projects/FreeB
**
** Note that, as provided in the License, the Software is distributed on an
** "AS IS" basis, with ALL EXPRESS AND IMPLIED WARRANTIES AND CONDITIONS
** DISCLAIMED, INCLUDING, WITHOUT LIMITATION, ANY IMPLIED WARRANTIES AND
** CONDITIONS OF MERCHANTABILITY, SATISFACTORY QUALITY, FITNESS FOR A
** PARTICULAR PURPOSE, AND NON-INFRINGEMENT.
**
** Original Code. The Original Code is: OpenGL Sample Implementation,
** Version 1.2.1, released January 26, 2000, developed by Silicon Graphics,
** Inc. The Original Code is Copyright (c) 1991-2000 Silicon Graphics, Inc.
** Copyright in any portions created by third parties is as indicated
** elsewhere herein. All Rights Reserved.
**
** Additional Notice Provisions: This software was created using the
** OpenGL(R) version 1.2.1 Sample Implementation published by SGI, but has
** not been independently verified as being compliant with the OpenGL(R)
** version 1.2.1 Specification.
*/
/*
** Modified to provide correct APIENTRY definition
** for Cygwin and Mingw
**
** 1.3 additional functionality segregated
**
** Cygwin's OpenGL package 1.1.0-4, Andre Bleau, April 24, 2001
*/
#ifndef __glu_h__
#define __glu_h__
#include <GL/gl.h>
#ifdef __cplusplus
extern "C" {
#endif
/*************************************************************/
#ifndef APIENTRY
# if defined(__CYGWIN__) || defined(__MINGW32__)
# define APIENTRY __attribute__ ((__stdcall__))
# else /* define APIENTRY to null string if we aren't on Cygwin or Mingw */
# define APIENTRY
# endif
# define GLU_APIENTRY_DEFINED
#endif
#ifndef CALLBACK
# if defined(__CYGWIN__) || defined(__MINGW32__)
# define CALLBACK __attribute__ ((__stdcall__))
# else /* define CALLBACK to null string if we aren't on Cygwin or Mingw */
# define CALLBACK
# endif
# define GLU_CALLBACK_DEFINED
#endif
#ifndef GLU_VERSION_1_3
#ifdef UNICODE
#define gluErrorStringWIN(errCode) ((LPCSTR)
gluErrorUnicodeStringEXT(errCode))
#else
#define gluErrorStringWIN(errCode) ((LPCWSTR) gluErrorString(errCode))
#endif
/**** Callback function prototypes ****/
/* gluQuadricCallback */
typedef void (CALLBACK* GLUquadricErrorProc) (GLenum);
/* gluTessCallback */
typedef void (CALLBACK* GLUtessBeginProc) (GLenum);
typedef void (CALLBACK* GLUtessEdgeFlagProc) (GLboolean);
typedef void (CALLBACK* GLUtessVertexProc) (void *);
typedef void (CALLBACK* GLUtessEndProc) (void);
typedef void (CALLBACK* GLUtessErrorProc) (GLenum);
typedef void (CALLBACK* GLUtessCombineProc) (GLdouble[3],
void*[4],
GLfloat[4],
void** );
typedef void (CALLBACK* GLUtessBeginDataProc) (GLenum, void *);
typedef void (CALLBACK* GLUtessEdgeFlagDataProc) (GLboolean, void *);
typedef void (CALLBACK* GLUtessVertexDataProc) (void *, void *);
typedef void (CALLBACK* GLUtessEndDataProc) (void *);
typedef void (CALLBACK* GLUtessErrorDataProc) (GLenum, void *);
typedef void (CALLBACK* GLUtessCombineDataProc) (GLdouble[3],
void*[4],
GLfloat[4],
void**,
void* );
/* gluNurbsCallback */
typedef void (CALLBACK* GLUnurbsErrorProc) (GLenum);
#endif /* #ifndef GLU_VERSION_1_3 */
/* Boolean */
#define GLU_FALSE 0
#define GLU_TRUE 1
/* Version */
#define GLU_VERSION_1_1 1
#define GLU_VERSION_1_2 1
/* StringName */
#define GLU_VERSION 100800
#define GLU_EXTENSIONS 100801
/* ErrorCode */
#define GLU_INVALID_ENUM 100900
#define GLU_INVALID_VALUE 100901
#define GLU_OUT_OF_MEMORY 100902
#ifdef GLU_VERSION_1_3
#define GLU_INVALID_OPERATION 100904
#else
#define GLU_INCOMPATIBLE_GL_VERSION 100903
#endif
/* NurbsDisplay */
/* GLU_FILL */
#define GLU_OUTLINE_POLYGON 100240
#define GLU_OUTLINE_PATCH 100241
/* NurbsCallback */
/* #define GLU_NURBS_ERROR 100103 */
/* NurbsError */
#define GLU_NURBS_ERROR1 100251
#define GLU_NURBS_ERROR2 100252
#define GLU_NURBS_ERROR3 100253
#define GLU_NURBS_ERROR4 100254
#define GLU_NURBS_ERROR5 100255
#define GLU_NURBS_ERROR6 100256
#define GLU_NURBS_ERROR7 100257
#define GLU_NURBS_ERROR8 100258
#define GLU_NURBS_ERROR9 100259
#define GLU_NURBS_ERROR10 100260
#define GLU_NURBS_ERROR11 100261
#define GLU_NURBS_ERROR12 100262
#define GLU_NURBS_ERROR13 100263
#define GLU_NURBS_ERROR14 100264
#define GLU_NURBS_ERROR15 100265
#define GLU_NURBS_ERROR16 100266
#define GLU_NURBS_ERROR17 100267
#define GLU_NURBS_ERROR18 100268
#define GLU_NURBS_ERROR19 100269
#define GLU_NURBS_ERROR20 100270
#define GLU_NURBS_ERROR21 100271
#define GLU_NURBS_ERROR22 100272
#define GLU_NURBS_ERROR23 100273
#define GLU_NURBS_ERROR24 100274
#define GLU_NURBS_ERROR25 100275
#define GLU_NURBS_ERROR26 100276
#define GLU_NURBS_ERROR27 100277
#define GLU_NURBS_ERROR28 100278
#define GLU_NURBS_ERROR29 100279
#define GLU_NURBS_ERROR30 100280
#define GLU_NURBS_ERROR31 100281
#define GLU_NURBS_ERROR32 100282
#define GLU_NURBS_ERROR33 100283
#define GLU_NURBS_ERROR34 100284
#define GLU_NURBS_ERROR35 100285
#define GLU_NURBS_ERROR36 100286
#define GLU_NURBS_ERROR37 100287
/* NurbsProperty */
#define GLU_AUTO_LOAD_MATRIX 100200
#define GLU_CULLING 100201
#define GLU_SAMPLING_TOLERANCE 100203
#define GLU_DISPLAY_MODE 100204
#define GLU_PARAMETRIC_TOLERANCE 100202
#define GLU_SAMPLING_METHOD 100205
#define GLU_U_STEP 100206
#define GLU_V_STEP 100207
/* NurbsSampling */
#define GLU_PATH_LENGTH 100215
#define GLU_PARAMETRIC_ERROR 100216
#define GLU_DOMAIN_DISTANCE 100217
/* NurbsTrim */
#define GLU_MAP1_TRIM_2 100210
#define GLU_MAP1_TRIM_3 100211
/* QuadricDrawStyle */
#define GLU_POINT 100010
#define GLU_LINE 100011
#define GLU_FILL 100012
#define GLU_SILHOUETTE 100013
/* QuadricCallback */
/* GLU_ERROR */
/* QuadricNormal */
#define GLU_SMOOTH 100000
#define GLU_FLAT 100001
#define GLU_NONE 100002
/* QuadricOrientation */
#define GLU_OUTSIDE 100020
#define GLU_INSIDE 100021
/* TessCallback */
#define GLU_TESS_BEGIN 100100
#define GLU_TESS_VERTEX 100101
#define GLU_TESS_END 100102
#define GLU_TESS_ERROR 100103
#define GLU_TESS_EDGE_FLAG 100104
#define GLU_TESS_COMBINE 100105
#define GLU_TESS_BEGIN_DATA 100106
#define GLU_TESS_VERTEX_DATA 100107
#define GLU_TESS_END_DATA 100108
#define GLU_TESS_ERROR_DATA 100109
#define GLU_TESS_EDGE_FLAG_DATA 100110
#define GLU_TESS_COMBINE_DATA 100111
/* TessProperty */
#define GLU_TESS_WINDING_RULE 100140
#define GLU_TESS_BOUNDARY_ONLY 100141
#define GLU_TESS_TOLERANCE 100142
/* TessError */
#define GLU_TESS_ERROR1 100151
#define GLU_TESS_ERROR2 100152
#define GLU_TESS_ERROR3 100153
#define GLU_TESS_ERROR4 100154
#define GLU_TESS_ERROR5 100155
#define GLU_TESS_ERROR6 100156
#define GLU_TESS_ERROR7 100157
#define GLU_TESS_ERROR8 100158
#define GLU_TESS_MISSING_BEGIN_POLYGON 100151
#define GLU_TESS_MISSING_BEGIN_CONTOUR 100152
#define GLU_TESS_MISSING_END_POLYGON 100153
#define GLU_TESS_MISSING_END_CONTOUR 100154
#define GLU_TESS_COORD_TOO_LARGE 100155
#define GLU_TESS_NEED_COMBINE_CALLBACK 100156
/* TessWinding */
#define GLU_TESS_WINDING_ODD 100130
#define GLU_TESS_WINDING_NONZERO 100131
#define GLU_TESS_WINDING_POSITIVE 100132
#define GLU_TESS_WINDING_NEGATIVE 100133
#define GLU_TESS_WINDING_ABS_GEQ_TWO 100134
/*************************************************************/
#ifdef __cplusplus
class GLUnurbs;
class GLUquadric;
class GLUtesselator;
#else
typedef struct GLUnurbs GLUnurbs;
typedef struct GLUquadric GLUquadric;
typedef struct GLUtesselator GLUtesselator;
#endif
typedef struct GLUnurbs GLUnurbsObj;
typedef struct GLUquadric GLUquadricObj;
typedef struct GLUtesselator GLUtesselatorObj;
typedef struct GLUtesselator GLUtriangulatorObj;
#define GLU_TESS_MAX_COORD 1.0e150
#ifndef GLU_VERSION_1_3
extern void APIENTRY gluNurbsCallback (GLUnurbs *nobj, GLenum which, void
(CALLBACK* fn)());
extern void APIENTRY gluQuadricCallback (GLUquadric *qobj, GLenum which,
void (CALLBACK* fn)());
extern void APIENTRY gluTessCallback(GLUtesselator *tess, GLenum which,
void (CALLBACK *fn)());
#endif /* #ifndef GLU_VERSION_1_3 */
extern void APIENTRY gluBeginCurve (GLUnurbs* nurb);
extern void APIENTRY gluBeginPolygon (GLUtesselator* tess);
extern void APIENTRY gluBeginSurface (GLUnurbs* nurb);
extern void APIENTRY gluBeginTrim (GLUnurbs* nurb);
extern GLint APIENTRY gluBuild1DMipmaps (GLenum target, GLint
internalFormat, GLsizei width, GLenum format, GLenum type, const void
*data);
extern GLint APIENTRY gluBuild2DMipmaps (GLenum target, GLint
internalFormat, GLsizei width, GLsizei height, GLenum format, GLenum type,
const void *data);
extern void APIENTRY gluCylinder (GLUquadric* quad, GLdouble base,
GLdouble top, GLdouble height, GLint slices, GLint stacks);
extern void APIENTRY gluDeleteNurbsRenderer (GLUnurbs* nurb);
extern void APIENTRY gluDeleteQuadric (GLUquadric* quad);
extern void APIENTRY gluDeleteTess (GLUtesselator* tess);
extern void APIENTRY gluDisk (GLUquadric* quad, GLdouble inner, GLdouble
outer, GLint slices, GLint loops);
extern void APIENTRY gluEndCurve (GLUnurbs* nurb);
extern void APIENTRY gluEndPolygon (GLUtesselator* tess);
extern void APIENTRY gluEndSurface (GLUnurbs* nurb);
extern void APIENTRY gluEndTrim (GLUnurbs* nurb);
extern const GLubyte * APIENTRY gluErrorString (GLenum error);
extern void APIENTRY gluGetNurbsProperty (GLUnurbs* nurb, GLenum
property, GLfloat* data);
extern const GLubyte * APIENTRY gluGetString (GLenum name);
extern void APIENTRY gluGetTessProperty (GLUtesselator* tess, GLenum
which, GLdouble* data);
extern void APIENTRY gluLoadSamplingMatrices (GLUnurbs* nurb, const
GLfloat *model, const GLfloat *perspective, const GLint *view);
extern void APIENTRY gluLookAt (GLdouble eyeX, GLdouble eyeY, GLdouble
eyeZ, GLdouble centerX, GLdouble centerY, GLdouble centerZ, GLdouble upX,
GLdouble upY, GLdouble upZ);
extern GLUnurbs* APIENTRY gluNewNurbsRenderer (void);
extern GLUquadric* APIENTRY gluNewQuadric (void);
extern GLUtesselator* APIENTRY gluNewTess (void);
extern void APIENTRY gluNextContour (GLUtesselator* tess, GLenum type);
extern void APIENTRY gluNurbsCurve (GLUnurbs* nurb, GLint knotCount,
GLfloat *knots, GLint stride, GLfloat *control, GLint order, GLenum type);
extern void APIENTRY gluNurbsProperty (GLUnurbs* nurb, GLenum property,
GLfloat value);
extern void APIENTRY gluNurbsSurface (GLUnurbs* nurb, GLint sKnotCount,
GLfloat* sKnots, GLint tKnotCount, GLfloat* tKnots, GLint sStride, GLint
tStride, GLfloat* control, GLint sOrder, GLint tOrder, GLenum type);
extern void APIENTRY gluOrtho2D (GLdouble left, GLdouble right, GLdouble
bottom, GLdouble top);
extern void APIENTRY gluPartialDisk (GLUquadric* quad, GLdouble inner,
GLdouble outer, GLint slices, GLint loops, GLdouble start, GLdouble sweep);
extern void APIENTRY gluPerspective (GLdouble fovy, GLdouble aspect,
GLdouble zNear, GLdouble zFar);
extern void APIENTRY gluPickMatrix (GLdouble x, GLdouble y, GLdouble
delX, GLdouble delY, GLint *viewport);
extern GLint APIENTRY gluProject (GLdouble objX, GLdouble objY, GLdouble
objZ, const GLdouble *model, const GLdouble *proj, const GLint *view,
GLdouble* winX, GLdouble* winY, GLdouble* winZ);
extern void APIENTRY gluPwlCurve (GLUnurbs* nurb, GLint count, GLfloat*
data, GLint stride, GLenum type);
extern void APIENTRY gluQuadricDrawStyle (GLUquadric* quad, GLenum draw);
extern void APIENTRY gluQuadricNormals (GLUquadric* quad, GLenum normal);
extern void APIENTRY gluQuadricOrientation (GLUquadric* quad, GLenum
orientation);
extern void APIENTRY gluQuadricTexture (GLUquadric* quad, GLboolean
texture);
extern GLint APIENTRY gluScaleImage (GLenum format, GLsizei wIn, GLsizei
hIn, GLenum typeIn, const void *dataIn, GLsizei wOut, GLsizei hOut, GLenum
typeOut, GLvoid* dataOut);
extern void APIENTRY gluSphere (GLUquadric* quad, GLdouble radius, GLint
slices, GLint stacks);
extern void APIENTRY gluTessBeginContour (GLUtesselator* tess);
extern void APIENTRY gluTessBeginPolygon (GLUtesselator* tess, GLvoid*
data);
extern void APIENTRY gluTessEndContour (GLUtesselator* tess);
extern void APIENTRY gluTessEndPolygon (GLUtesselator* tess);
extern void APIENTRY gluTessNormal (GLUtesselator* tess, GLdouble valueX,
GLdouble valueY, GLdouble valueZ);
extern void APIENTRY gluTessProperty (GLUtesselator* tess, GLenum which,
GLdouble data);
extern void APIENTRY gluTessVertex (GLUtesselator* tess, GLdouble
*location, GLvoid* data);
extern GLint APIENTRY gluUnProject (GLdouble winX, GLdouble winY,
GLdouble winZ, const GLdouble *model, const GLdouble *proj, const GLint
*view, GLdouble* objX, GLdouble* objY, GLdouble* objZ);
/* acc change comment
* the following three sections were originally after the
* #ifdef GLU_VERSION_1_3
* statement which immediately follows. Apparently, the correct version
number is 1_2,
* but changing all the
* statements that tested for 1_3 to 1_2 seemed to cause additional
problems.
* Therefore, I just pulled the #define statements that were generating
error messages out of the
* #ifdef and put them inline.
*/
/* acc begin change */
/* NurbsCallback */
#define GLU_ERROR 100103
/* TessCallback */
#define GLU_BEGIN 100100
#define GLU_VERTEX 100101
#define GLU_END 100102
#define GLU_EDGE_FLAG 100104
/* TessContour */
#define GLU_CW 100120
#define GLU_CCW 100121
#define GLU_INTERIOR 100122
#define GLU_EXTERIOR 100123
#define GLU_UNKNOWN 100124
/* end acc change */
#ifdef GLU_VERSION_1_3
/* Extensions */
#define GLU_EXT_object_space_tess 1
#define GLU_EXT_nurbs_tessellator 1
/* NurbsCallback */
#define GLU_NURBS_ERROR 100103
#define GLU_NURBS_BEGIN 100164
#define GLU_NURBS_BEGIN_EXT 100164
#define GLU_NURBS_VERTEX 100165
#define GLU_NURBS_VERTEX_EXT 100165
#define GLU_NURBS_NORMAL 100166
#define GLU_NURBS_NORMAL_EXT 100166
#define GLU_NURBS_COLOR 100167
#define GLU_NURBS_COLOR_EXT 100167
#define GLU_NURBS_TEXTURE_COORD 100168
#define GLU_NURBS_TEX_COORD_EXT 100168
#define GLU_NURBS_END 100169
#define GLU_NURBS_END_EXT 100169
#define GLU_NURBS_BEGIN_DATA 100170
#define GLU_NURBS_BEGIN_DATA_EXT 100170
#define GLU_NURBS_VERTEX_DATA 100171
#define GLU_NURBS_VERTEX_DATA_EXT 100171
#define GLU_NURBS_NORMAL_DATA 100172
#define GLU_NURBS_NORMAL_DATA_EXT 100172
#define GLU_NURBS_COLOR_DATA 100173
#define GLU_NURBS_COLOR_DATA_EXT 100173
#define GLU_NURBS_TEXTURE_COORD_DATA 100174
#define GLU_NURBS_TEX_COORD_DATA_EXT 100174
#define GLU_NURBS_END_DATA 100175
#define GLU_NURBS_END_DATA_EXT 100175
/* NurbsProperty */
#define GLU_NURBS_MODE 100160
#define GLU_NURBS_MODE_EXT 100160
#define GLU_NURBS_TESSELLATOR 100161
#define GLU_NURBS_TESSELLATOR_EXT 100161
#define GLU_NURBS_RENDERER 100162
#define GLU_NURBS_RENDERER_EXT 100162
/* NurbsSampling */
#define GLU_OBJECT_PARAMETRIC_ERROR 100208
#define GLU_OBJECT_PARAMETRIC_ERROR_EXT 100208
#define GLU_OBJECT_PATH_LENGTH 100209
#define GLU_OBJECT_PATH_LENGTH_EXT 100209
/* For compatibility with OpenGL v1.0 */
#define GL_LOGIC_OP GL_INDEX_LOGIC_OP
#define GL_TEXTURE_COMPONENTS GL_TEXTURE_INTERNAL_FORMAT
extern GLint APIENTRY gluBuild1DMipmapLevels (GLenum target, GLint
internalFormat, GLsizei width, GLenum format, GLenum type, GLint level,
GLint base, GLint max, const void *data);
extern GLint APIENTRY gluBuild2DMipmapLevels (GLenum target, GLint
internalFormat, GLsizei width, GLsizei height, GLenum format, GLenum type,
GLint level, GLint base, GLint max, const void *data);
extern GLint APIENTRY gluBuild3DMipmapLevels (GLenum target, GLint
internalFormat, GLsizei width, GLsizei height, GLsizei depth, GLenum format,
GLenum type, GLint level, GLint base, GLint max, const void *data);
extern GLint APIENTRY gluBuild3DMipmaps (GLenum target, GLint
internalFormat, GLsizei width, GLsizei height, GLsizei depth, GLenum format,
GLenum type, const void *data);
extern GLboolean APIENTRY gluCheckExtension (const GLubyte *extName,
const GLubyte *extString);
extern void APIENTRY gluNurbsCallbackData (GLUnurbs* nurb, GLvoid*
userData);
extern void APIENTRY gluNurbsCallback (GLUnurbs* nurb, GLenum which,
_GLfuncptr CallBackFunc);
extern void APIENTRY gluNurbsCallbackDataEXT (GLUnurbs* nurb, GLvoid*
userData);
extern void APIENTRY gluQuadricCallback (GLUquadric* quad, GLenum which,
_GLfuncptr CallBackFunc);
extern void APIENTRY gluTessCallback (GLUtesselator* tess, GLenum which,
_GLfuncptr CallBackFunc);
extern GLint APIENTRY gluUnProject4 (GLdouble winX, GLdouble winY,
GLdouble winZ, GLdouble clipW, const GLdouble *model, const GLdouble *proj,
const GLint *view, GLdouble near, GLdouble far, GLdouble* objX, GLdouble*
objY, GLdouble* objZ, GLdouble* objW);
#endif /* #ifdef GLU_VERSION_1_3 */
#ifdef GLU_APIENTRY_DEFINED
# undef GLU_APIENTRY_DEFINED
# undef APIENTRY
#endif
#ifdef GLU_CALLBACK_DEFINED
# undef GLU_CALLBACK_DEFINED
# undef CALLBACK
#endif
#ifdef __cplusplus
}
#endif
#endif /* __glu_h__ */
****************************************************************************
*******
/*
* $Date: 2001/04/30 04:10:30 $
* $Author: yoshi $
*/
#if defined(WIN32)
# include "windows.h"
#endif
#include "GL/gl.h"
#include "GL/glu.h"
#include "rbogl.h"
/* acc change comment
* create definition of VOIDFUNC here
* search for VOIDFUNC to see where it has been added to later statements
* also check [ruby-talk:21179]
*
*/
#ifdef WIN32
typedef void (CALLBACK*(VOIDFUNC))();
#else
typedef void (*VOIDFUNC)();
#endif
#if defined(GLU_VERSION_1_2)
typedef GLUtesselator tesselatorObj;
#else /* GLU_VERSION_1_2 */
typedef GLUtriangulatorObj tesselatorObj;
#endif /* !GLU_VERSION_1_2 */
#ifdef MESA
struct glu_MesaStack {
int len;
GLfloat **ptr;
};
static struct glu_MesaStack gms = {0, NULL};
#endif
struct nurbsdata {
GLUnurbsObj *nobj;
};
struct tessdata {
tesselatorObj *tobj;
VALUE t_ref;
};
struct quaddata {
GLUquadricObj *qobj;
};
static VALUE cNurbs;
static VALUE cTess;
static VALUE cQuad;
#define GetNURBS(obj, ndata) {\
Data_Get_Struct(obj, struct nurbsdata, ndata);\
if (ndata->nobj == NULL) rb_raise(rb_eRuntimeError, "Nurbs Object
already deleted!");\
}
#define GetTESS(obj, tdata) {\
Data_Get_Struct(obj, struct tessdata, tdata);\
if (tdata->tobj == NULL) rb_raise(rb_eRuntimeError, "Triangulator Object
already deleted!");\
}
#define GetQUAD(obj, qdata) {\
Data_Get_Struct(obj, struct quaddata, qdata);\
if (qdata->qobj == NULL) rb_raise(rb_eRuntimeError, "Quadric Object
already deleted!");\
}
static ID callId;
static ID refId;
/*
* GLU Implementation
*/
/*
* Nurbs
*/
/* from nurbscrv.c */
static int
get_curve_dim(type)
GLenum type;
{
switch(type)
{
case GL_MAP1_VERTEX_3: return 3;
case GL_MAP1_VERTEX_4: return 4;
case GL_MAP1_INDEX: return 1;
case GL_MAP1_COLOR_4: return 4;
case GL_MAP1_NORMAL: return 3;
case GL_MAP1_TEXTURE_COORD_1: return 1;
case GL_MAP1_TEXTURE_COORD_2: return 2;
case GL_MAP1_TEXTURE_COORD_3: return 3;
case GL_MAP1_TEXTURE_COORD_4: return 4;
default: abort(); /* TODO: is this OK? */
}
return 0; /*never get here*/
}
/* from nurbssrf.c */
static int
get_surface_dim(GLenum type)
{
switch(type)
{
case GL_MAP2_VERTEX_3: return 3;
case GL_MAP2_VERTEX_4: return 4;
case GL_MAP2_INDEX: return 1;
case GL_MAP2_COLOR_4: return 4;
case GL_MAP2_NORMAL: return 3;
case GL_MAP2_TEXTURE_COORD_1: return 1;
case GL_MAP2_TEXTURE_COORD_2: return 2;
case GL_MAP2_TEXTURE_COORD_3: return 3;
case GL_MAP2_TEXTURE_COORD_4: return 4;
default: abort(); /* TODO: is this OK? */
}
return 0; /*never get here*/
}
/*
* NURBS API
*/
static void
free_nurbs(ndata)
struct nurbsdata *ndata;
{
if (ndata->nobj) gluDeleteNurbsRenderer(ndata->nobj);
ndata->nobj = NULL;
}
static VALUE
glu_NewNurbsRenderer(obj)
VALUE obj;
{
VALUE ret;
struct nurbsdata *ndata;
ret = Data_Make_Struct(cNurbs, struct nurbsdata, 0, free_nurbs, ndata);
ndata->nobj = gluNewNurbsRenderer();
return ret;
}
static VALUE
glu_DeleteNurbsRenderer(obj, arg1)
VALUE obj, arg1;
{
struct nurbsdata *ndata;
GetNURBS(arg1, ndata);
free_nurbs(ndata);
return Qnil;
}
static VALUE
glu_NurbsProperty(obj, arg1, arg2, arg3)
VALUE obj, arg1, arg2, arg3;
{
struct nurbsdata *ndata;
GLenum property;
GLfloat value;
GetNURBS(arg1, ndata);
property = (GLenum)NUM2INT(arg2);
value = (GLfloat)NUM2DBL(arg3);
gluNurbsProperty(ndata->nobj, property, value);
return Qnil;
}
static VALUE
glu_GetNurbsProperty(obj, arg1, arg2)
VALUE obj, arg1, arg2;
{
struct nurbsdata *ndata;
GLenum property;
GLfloat value;
GetNURBS(arg1, ndata);
property = (GLenum)NUM2INT(arg2);
gluGetNurbsProperty(ndata->nobj, property, &value);
return rb_float_new(value);
}
static VALUE
glu_BeginCurve(obj, arg1)
VALUE obj, arg1;
{
struct nurbsdata *ndata;
GetNURBS(arg1, ndata);
gluBeginCurve(ndata->nobj);
return Qnil;
}
static VALUE
glu_EndCurve(obj, arg1)
VALUE obj, arg1;
{
struct nurbsdata *ndata;
GetNURBS(arg1, ndata);
gluEndCurve(ndata->nobj);
/* hack for Mesa 3.1 */
#ifdef MESA
for (gms.len;gms.len>0;gms.len--)
free(gms.ptr[gms.len-1]);
free(gms.ptr);
gms.ptr = NULL;
#endif
return Qnil;
}
static VALUE
glu_NurbsCurve(argc,argv,obj)
int argc;
VALUE *argv;
VALUE obj;
{
struct nurbsdata *ndata;
GLint uknot_count;
GLfloat *uknot;
GLint u_stride;
GLint uorder;
GLfloat *ctlarray;
GLenum type;
VALUE args[7];
GLfloat tmp[4];
int i;
struct RArray *ary_ctl1;
switch (rb_scan_args(argc, argv, "43", &args[0], &args[1], &args[2],
&args[3], &args[4], &args[5], &args[6])) {
case 3:
uknot_count = RARRAY(rb_Array(args[1]))->len;
uknot = ALLOC_N(GLfloat, uknot_count);
ary2cflt(args[1], uknot, uknot_count);
ary_ctl1 = RARRAY(rb_Array(args[2]));
type = (GLenum)NUM2INT(args[3]);
u_stride = get_curve_dim(type);
uorder = ary_ctl1->len;
ctlarray = ALLOC_N(GLfloat, u_stride*uorder);
for (i = 0; i < ary_ctl1->len; i++) {
ary2cflt(ary_ctl1->ptr[i], tmp, 4);
memcpy(&ctlarray[i*u_stride], tmp, u_stride);
}
break;
case 7:
uknot_count = (GLint)NUM2INT(args[1]);
uknot = ALLOC_N(GLfloat, uknot_count);
ary2cflt(args[2], uknot, uknot_count);
u_stride = (GLint)NUM2INT(args[3]);
uorder = (GLint)NUM2INT(args[5]);
ctlarray = ALLOC_N(GLfloat, u_stride*uorder);
ary_ctl1 = RARRAY(rb_Array(args[4]));
if (TYPE(ary_ctl1->ptr[0]) == T_ARRAY)
for (i = 0; i < ary_ctl1->len; i++) {
ary2cflt(ary_ctl1->ptr[i], tmp, 4);
memcpy(&ctlarray[i*u_stride], tmp, u_stride);
}
else
ary2cflt((VALUE)ary_ctl1, ctlarray, u_stride*uorder);
break;
default:
rb_raise(rb_eArgError, "arg num:%d",argc);
}
GetNURBS(args[0], ndata);
gluNurbsCurve(ndata->nobj, uknot_count, uknot, u_stride, ctlarray,
uorder, type);
/* as of Mesa 3.1, Mesa assumes all data that following pointers
points to is valid at gluEndCurve. so, free them in
glu_EndCurve() */
#ifdef MESA
gms.ptr = REALLOC_N(gms.ptr, GLfloat*, gms.len+=2);
gms.ptr[gms.len - 2] = uknot;
gms.ptr[gms.len - 1] = ctlarray;
#else
free(uknot);
free(ctlarray);
#endif
return Qnil;
}
static VALUE
glu_BeginSurface(obj, arg1)
VALUE obj, arg1;
{
struct nurbsdata *ndata;
GetNURBS(arg1, ndata);
gluBeginSurface(ndata->nobj);
return Qnil;
}
static VALUE
glu_EndSurface(obj, arg1)
VALUE obj, arg1;
{
struct nurbsdata *ndata;
GetNURBS(arg1, ndata);
gluEndSurface(ndata->nobj);
/* hack for Mesa 3.1 */
#ifdef MESA
for(gms.len; gms.len>0; gms.len--)
free(gms.ptr[gms.len-1]);
free(gms.ptr);
gms.ptr = NULL;
#endif
return Qnil;
}
static VALUE
glu_NurbsSurface(argc, argv, obj)
int argc;
VALUE *argv;
VALUE obj;
{
struct nurbsdata *ndata;
GLint sknot_count;
GLfloat *sknot;
GLint tknot_count;
GLfloat *tknot;
GLint s_stride;
GLint t_stride;
GLfloat *ctlarray;
GLint sorder;
GLint torder;
GLenum type;
VALUE work_ary;
VALUE args[11];
struct RArray *ary_ctl1;
int type_len;
switch (rb_scan_args(argc, argv, "56", &args[0], &args[1], &args[2],
&args[3], &args[4], &args[5], &args[6], &args[7], &args[8], &args[9],
&args[10])) {
case 5:
sknot_count = RARRAY(rb_Array(args[1]))->len;
sknot = ALLOC_N(GLfloat, sknot_count);
ary2cflt(args[1], sknot, sknot_count);
tknot_count = RARRAY(rb_Array(args[2]))->len;
tknot = ALLOC_N(GLfloat, tknot_count);
ary2cflt(args[2], tknot, tknot_count);
ary_ctl1 = RARRAY(rb_Array(args[3]));
sorder = ary_ctl1->len;
torder = RARRAY(rb_Array(ary_ctl1->ptr[0]))->len;
type = (GLenum)NUM2INT(args[4]);
t_stride = get_surface_dim(type);
s_stride = t_stride * sorder;
ctlarray = ALLOC_N(GLfloat, t_stride*s_stride);
work_ary = rb_ary_new();
mary2ary((VALUE)ary_ctl1, work_ary);
ary2cflt(work_ary, ctlarray, t_stride*s_stride);
case 11:
sknot_count = (GLint)NUM2INT(args[1]);
sknot = ALLOC_N(GLfloat, sknot_count);
ary2cflt(args[2], sknot, sknot_count);
tknot_count = (GLint)NUM2INT(args[3]);
tknot = ALLOC_N(GLfloat, tknot_count);
ary2cflt(args[4], tknot, tknot_count);
s_stride = (GLint)NUM2INT(args[5]);
t_stride = (GLint)NUM2INT(args[6]);
sorder = (GLint)NUM2INT(args[8]);
torder = (GLint)NUM2INT(args[9]);
type = (GLint)NUM2INT(args[10]);
type_len = get_surface_dim(type);
ctlarray = ALLOC_N(GLfloat, sorder*torder*type_len);
ary_ctl1 = RARRAY(rb_Array(args[7]));
if (TYPE(ary_ctl1->ptr[0]) == T_ARRAY) {
work_ary = rb_ary_new();
mary2ary((VALUE)ary_ctl1, work_ary);
ary2cflt(work_ary, ctlarray, sorder*torder*type_len);
}
else
ary2cflt((VALUE)ary_ctl1, ctlarray, sorder*torder*type_len);
break;
default:
rb_raise(rb_eArgError, "arg num:%d",argc);
}
GetNURBS(args[0], ndata);
gluNurbsSurface(ndata->nobj, sknot_count, sknot, tknot_count, tknot,
s_stride, t_stride, ctlarray, sorder, torder, type);
/* as of Mesa 3.1, Mesa assumes all data that following pointers
points to is valid at gluEndSurface. so, free them in
glu_EndSurface() */
#ifdef MESA
gms.ptr = REALLOC_N(gms.ptr, GLfloat*, gms.len+=3);
gms.ptr[gms.len-3] = sknot;
gms.ptr[gms.len-2] = tknot;
gms.ptr[gms.len-1] = ctlarray;
#else
free(sknot);
free(tknot);
free(ctlarray);
#endif
return Qnil;
}
static VALUE
glu_BeginTrim(obj, arg1)
VALUE obj, arg1;
{
struct nurbsdata *ndata;
GetNURBS(arg1, ndata);
gluBeginTrim(ndata->nobj);
return Qnil;
}
static VALUE
glu_EndTrim(obj, arg1)
VALUE obj, arg1;
{
struct nurbsdata *ndata;
GetNURBS(arg1, ndata);
gluEndTrim(ndata->nobj);
return Qnil;
}
static VALUE
glu_PwlCurve(argc, argv, obj)
int argc;
VALUE *argv;
VALUE obj;
{
struct nurbsdata *ndata;
GLint count;
GLfloat *array;
GLint stride;
GLenum type;
VALUE args[5];
GLfloat tmp[3];
struct RArray* ary_ctl1;
int i;
switch (rb_scan_args(argc, argv, "32", &args[0], &args[1], &args[2],
&args[3], &args[4])) {
case 3:
ary_ctl1 = RARRAY(rb_Array(args[2]));
count = ary_ctl1->len;
type = NUM2INT(args[2]);
stride = (type == GLU_MAP1_TRIM_2 ? 2 : 3);
array = ALLOC_N(GLfloat, count*stride);
for (i = 0; i < ary_ctl1->len; i++) {
ary2cflt(ary_ctl1->ptr[i], tmp, 3);
memcpy(&array[i*stride], tmp, stride);
}
break;
case 5:
count = NUM2INT(args[1]);
stride = NUM2INT(args[3]);
type = NUM2INT(args[4]);
array = ALLOC_N(GLfloat, count*stride);
ary_ctl1 = RARRAY(rb_Array(args[2]));
if (TYPE(ary_ctl1->ptr[0]) == T_ARRAY)
for (i = 0; i < ary_ctl1->len; i++) {
ary2cflt(ary_ctl1->ptr[i], tmp, 3);
memcpy(&array[i*stride], tmp, stride);
}
else
ary2cflt((VALUE)ary_ctl1, array, count*stride);
break;
default:
rb_raise(rb_eArgError, "arg num:%d",argc);
}
GetNURBS(args[0], ndata);
gluPwlCurve(ndata->nobj, count, array, stride, type);
free(array);
return Qnil;
}
/*
* Tesselation API
*/
static VALUE t_current;
#define TESS_DATA 0
#define TESS_BEGIN 1
#define TESS_VERTEX 2
#define TESS_END 3
#define TESS_ERROR 4
#define TESS_EDGE 5
#if defined(GLU_VERSION_1_2)
# define TESS_OUTDATA 6
# define TESS_COMBINE 7
# define TESS_BEGIN_DATA 8
# define TESS_VERTEX_DATA 9
# define TESS_END_DATA 10
# define TESS_ERROR_DATA 11
# define TESS_EDGE_DATA 12
# define TESS_COMBINE_DATA 13
# define TESS_USERDATA 14
# define REF_LAST 15
#else /* !GLU_VERSION_1_2 */
# define REF_LAST 6
#endif /* GLU_VERSION_1_2 */
static void
mark_tess(tdata)
struct tessdata* tdata;
{
if (tdata->tobj)
rb_gc_mark(tdata->t_ref);
}
static void
free_tess(tdata)
struct tessdata *tdata;
{
ID id;
VALUE call_key;
if (tdata->tobj) {
gluDeleteTess(tdata->tobj);
}
tdata->t_ref = Qnil;
tdata->tobj = NULL;
}
static VALUE
glu_NewTess(obj)
VALUE obj;
{
VALUE ret;
struct tessdata *tdata;
ret = Data_Make_Struct(cTess, struct tessdata, mark_tess, free_tess,
tdata);
tdata->tobj = gluNewTess();
tdata->t_ref = rb_ary_new2(REF_LAST);
return ret;
}
static VALUE
glu_DeleteTess(obj, arg1)
VALUE obj, arg1;
{
struct tessdata *tdata;
GetTESS(arg1, tdata);
free_tess(tdata);
return Qnil;
}
void
t_begin(type)
GLenum type;
{
VALUE tess;
struct tessdata *tdata;
tess = rb_ary_entry(t_current, -1);
if (tess != Qnil) {
GetTESS(tess, tdata);
rb_funcall(rb_ary_entry(tdata->t_ref, TESS_BEGIN), callId, 1,
INT2NUM(type));
}
}
static void
t_edgeFlag(flag)
GLboolean flag;
{
VALUE tess;
struct tessdata *tdata;
tess = rb_ary_entry(t_current, -1);
if (tess != Qnil) {
GetTESS(tess, tdata);
rb_funcall(rb_ary_entry(tdata->t_ref, TESS_EDGE), callId, 1,
INT2NUM(flag));
}
}
static void
t_vertex(data)
void* data;
{
VALUE tess;
struct tessdata *tdata;
tess = rb_ary_entry(t_current, -1);
if (tess != Qnil) {
GetTESS(tess, tdata);
rb_funcall(rb_ary_entry(tdata->t_ref, TESS_VERTEX), callId, 1,
data);
}
}
static void
t_end()
{
VALUE tess;
struct tessdata *tdata;
tess = rb_ary_entry(t_current, -1);
if (tess != Qnil) {
GetTESS(tess, tdata);
rb_funcall(rb_ary_entry(tdata->t_ref, TESS_END), callId, 0);
}
}
static void
t_error(errorno)
GLenum errorno;
{
VALUE tess;
struct tessdata *tdata;
tess = rb_ary_entry(t_current, -1);
if (tess != Qnil) {
GetTESS(tess, tdata);
rb_funcall(rb_ary_entry(tdata->t_ref, TESS_ERROR), callId, 1,
INT2NUM(errorno));
}
}
#if defined(GLU_VERSION_1_2)
static void
t_begin_data(type, user_data)
GLenum type;
void* user_data;
{
VALUE tess;
struct tessdata *tdata;
tess = rb_ary_entry(t_current, -1);
if (tess != Qnil) {
GetTESS(tess, tdata);
rb_funcall(rb_ary_entry(tdata->t_ref, TESS_BEGIN_DATA), callId, 2,
INT2NUM(type), user_data);
}
}
static void
t_edgeFlag_data(flag, user_data)
GLboolean flag;
void* user_data;
{
VALUE tess;
struct tessdata *tdata;
tess = rb_ary_entry(t_current, -1);
if (tess != Qnil) {
GetTESS(tess, tdata);
rb_funcall(rb_ary_entry(tdata->t_ref, TESS_EDGE_DATA), callId, 2,
INT2NUM(flag), user_data);
}
}
static void
t_vertex_data(data, user_data)
void* data;
void* user_data;
{
VALUE tess;
struct tessdata *tdata;
tess = rb_ary_entry(t_current, -1);
if (tess != Qnil) {
GetTESS(tess, tdata);
rb_funcall(rb_ary_entry(tdata->t_ref, TESS_VERTEX_DATA), callId, 2,
data, user_data);
}
}
static void
t_end_data(user_data)
void* user_data;
{
VALUE tess;
struct tessdata *tdata;
tess = rb_ary_entry(t_current, -1);
if (tess != Qnil) {
GetTESS(tess, tdata);
rb_funcall(rb_ary_entry(tdata->t_ref, TESS_END_DATA), callId, 1,
user_data);
}
}
static void
t_error_data(errorno, user_data)
GLenum errorno;
void* user_data;
{
VALUE tess;
struct tessdata *tdata;
tess = rb_ary_entry(t_current, -1);
if (tess != Qnil) {
GetTESS(tess, tdata);
rb_funcall(rb_ary_entry(tdata->t_ref, TESS_ERROR_DATA), callId, 2,
INT2NUM(errorno), user_data);
}
}
static void
t_combine(coords, vertex_data, weight, outData)
GLdouble coords[3];
void* vertex_data[4];
GLfloat weight[4];
void** outData;
{
VALUE tess;
struct tessdata *tdata;
VALUE rb_coord, rb_vertex_data, rb_weight;
int i;
tess = rb_ary_entry(t_current, -1);
if (tess != Qnil) {
GetTESS(tess, tdata);
rb_coord = rb_ary_new2(3);
for (i = 0; i < 3; i++)
rb_ary_store(rb_coord, i, rb_float_new(coords[i]));
rb_vertex_data = rb_ary_new2(4);
for (i = 0; i < 4; i++)
rb_ary_store(rb_vertex_data, i, (VALUE)vertex_data[i]);
rb_weight = rb_ary_new2(4);
for (i = 0; i < 4; i++)
rb_ary_store(rb_weight, i, rb_float_new(weight[i]));
*outData = (void*)rb_funcall(rb_ary_entry(tdata->t_ref,
TESS_COMBINE), callId, 3, rb_coord, rb_vertex_data, rb_weight);
rb_ary_push(rb_ary_entry(tdata->t_ref, TESS_OUTDATA),
(VALUE)*outData);
}
}
static void
t_combine_data(coords, vertex_data, weight, outData, user_data)
GLdouble coords[3];
void* vertex_data[4];
GLfloat weight[4];
void** outData;
void* user_data;
{
VALUE tess;
struct tessdata *tdata;
VALUE rb_coord, rb_vertex_data, rb_weight;
int i;
tess = rb_ary_entry(t_current, -1);
if (tess != Qnil) {
GetTESS(tess, tdata);
rb_coord = rb_ary_new2(3);
for (i = 0; i < 3; i++)
rb_ary_store(rb_coord, i, rb_float_new(coords[i]));
rb_vertex_data = rb_ary_new2(4);
for (i = 0; i < 4; i++)
rb_ary_store(rb_vertex_data, i, (VALUE)vertex_data[i]);
rb_weight = rb_ary_new2(4);
for (i = 0; i < 4; i++)
rb_ary_store(rb_weight, i, rb_float_new(weight[i]));
*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);
rb_ary_push(rb_ary_entry(tdata->t_ref, TESS_OUTDATA),
(VALUE)*outData);
}
}
static VALUE
glu_TessProperty(obj, arg1, arg2, arg3)
VALUE obj, arg1, arg2;
{
struct tessdata* tdata;
GLenum property;
GLdouble value;
GetTESS(arg1, tdata);
property = (GLenum)NUM2INT(arg2);
value = (GLdouble)NUM2DBL(arg3);
gluTessProperty(tdata->tobj, property, value);
return Qnil;
}
static VALUE
glu_GetTessProperty(obj, arg1, arg2)
VALUE obj, arg1, arg2;
{
struct tessdata* tdata;
GLenum property;
GLdouble value;
GetTESS(arg1, tdata);
property = (GLenum)NUM2INT(arg2);
gluGetTessProperty(tdata->tobj, property, &value);
return rb_float_new(value);
}
static VALUE
glu_TessNormal(obj, arg1, arg2, arg3, arg4)
VALUE obj, arg1, arg2, arg3, arg4;
{
struct tessdata* tdata;
GLdouble x, y, z;
GetTESS(arg1, tdata);
x = (GLdouble)NUM2DBL(arg2);
y = (GLdouble)NUM2DBL(arg3);
z = (GLdouble)NUM2DBL(arg4);
gluTessNormal(tdata->tobj, x, y, z);
return Qnil;
}
static VALUE
glu_TessBeginPolygon(obj, arg1, arg2)
VALUE obj, arg1, arg2;
{
struct tessdata* tdata;
GetTESS(arg1, tdata);
rb_ary_store(tdata->t_ref, TESS_USERDATA, arg2);
rb_ary_store(tdata->t_ref, TESS_OUTDATA, rb_ary_new());
rb_ary_store(tdata->t_ref, TESS_DATA, rb_ary_new());
rb_ary_push(t_current, arg1);
gluTessBeginPolygon(tdata->tobj, (void*)arg2);
return Qnil;
}
static VALUE
glu_TessEndPolygon(obj, arg1)
VALUE obj, arg1;
{
struct tessdata* tdata;
GetTESS(arg1, tdata);
gluTessEndPolygon(tdata->tobj);
rb_ary_store(tdata->t_ref, TESS_USERDATA, Qnil);
rb_ary_store(tdata->t_ref, TESS_OUTDATA, Qnil);
rb_ary_store(tdata->t_ref, TESS_DATA, Qnil);
rb_ary_pop(t_current);
return Qnil;
}
static VALUE
glu_TessBeginContour(obj, arg1)
VALUE obj, arg1;
{
struct tessdata* tdata;
GetTESS(arg1, tdata);
gluTessBeginContour(tdata->tobj);
return Qnil;
}
static VALUE
glu_TessEndContour(obj, arg1)
{
struct tessdata* tdata;
GetTESS(arg1, tdata);
gluTessEndContour(tdata->tobj);
return Qnil;
}
#endif /* GLU_VERSION_1_2 */
static VALUE
glu_TessCallback(obj, arg1, arg2, arg3)
VALUE obj, arg1, arg2, arg3;
{
struct tessdata* tdata;
GLenum type;
ID id;
GetTESS(arg1, tdata);
type = (GLenum)NUM2INT(arg2);
id = rb_intern("[]=");
if (!rb_obj_is_kind_of(arg3,rb_cProc) && NIL_P(arg3))
rb_raise(rb_eTypeError, "GLU.TessCallback needs Proc
Object:%s",rb_class2name(CLASS_OF(arg3)));
switch (type) {
#if defined(GLU_VERSION_1_2)
case GLU_TESS_BEGIN:
#else
case GLU_BEGIN:
#endif
rb_ary_store(tdata->t_ref, TESS_BEGIN, arg3);
if (NIL_P(arg3))
gluTessCallback(tdata->tobj, type, NULL);
else
gluTessCallback(tdata->tobj, type, (VOIDFUNC)(t_begin));
break;
#if defined(GLU_VERSION_1_2)
case GLU_TESS_EDGE_FLAG:
#else
case GLU_EDGE_FLAG:
#endif
rb_ary_store(tdata->t_ref, TESS_EDGE, arg3);
if (NIL_P(arg3))
gluTessCallback(tdata->tobj, type, NULL);
else
gluTessCallback(tdata->tobj, type, (VOIDFUNC)(t_edgeFlag));
break;
#if defined(GLU_VERSION_1_2)
case GLU_TESS_VERTEX:
#else
case GLU_VERTEX:
#endif
rb_ary_store(tdata->t_ref, TESS_VERTEX, arg3);
if (NIL_P(arg3))
gluTessCallback(tdata->tobj, type, NULL);
else
gluTessCallback(tdata->tobj, type, (VOIDFUNC)(t_vertex));
break;
#if defined(GLU_VERSION_1_2)
case GLU_TESS_END:
#else
case GLU_END:
#endif
rb_ary_store(tdata->t_ref, TESS_END, arg3);
if (NIL_P(arg3))
gluTessCallback(tdata->tobj, type, NULL);
else
gluTessCallback(tdata->tobj, type, (VOIDFUNC)(t_end));
break;
#if defined(GLU_VERSION_1_2)
case GLU_TESS_ERROR:
#else
case GLU_ERROR:
#endif
rb_ary_store(tdata->t_ref, TESS_ERROR, arg3);
if (NIL_P(arg3))
gluTessCallback(tdata->tobj, type, NULL);
else
gluTessCallback(tdata->tobj, type, (VOIDFUNC)(t_error));
break;
#if defined(GLU_VERSION_1_2)
case GLU_TESS_COMBINE:
rb_ary_store(tdata->t_ref, TESS_COMBINE, arg3);
if (NIL_P(arg3))
gluTessCallback(tdata->tobj, type, NULL);
else
gluTessCallback(tdata->tobj, type, (VOIDFUNC)(t_combine));
break;
case GLU_TESS_BEGIN_DATA:
rb_ary_store(tdata->t_ref, TESS_BEGIN_DATA, arg3);
if (NIL_P(arg3))
gluTessCallback(tdata->tobj, type, NULL);
else
gluTessCallback(tdata->tobj, type,
(VOIDFUNC)(t_begin_data));
break;
case GLU_TESS_VERTEX_DATA:
rb_ary_store(tdata->t_ref, TESS_VERTEX_DATA, arg3);
if (NIL_P(arg3))
gluTessCallback(tdata->tobj, type, NULL);
else
gluTessCallback(tdata->tobj, type,
(VOIDFUNC)(t_vertex_data));
break;
case GLU_TESS_END_DATA:
rb_ary_store(tdata->t_ref, TESS_END_DATA, arg3);
if (NIL_P(arg3))
gluTessCallback(tdata->tobj, type, NULL);
else
gluTessCallback(tdata->tobj, type, (VOIDFUNC)(t_end_data));
break;
case GLU_TESS_ERROR_DATA:
rb_ary_store(tdata->t_ref, TESS_ERROR_DATA, arg3);
if (NIL_P(arg3))
gluTessCallback(tdata->tobj, type, NULL);
else
gluTessCallback(tdata->tobj, type,
(VOIDFUNC)(t_error_data));
break;
case GLU_TESS_EDGE_FLAG_DATA:
rb_ary_store(tdata->t_ref, TESS_EDGE_DATA, arg3);
if (NIL_P(arg3))
gluTessCallback(tdata->tobj, type, NULL);
else
gluTessCallback(tdata->tobj, type,
(VOIDFUNC)(t_edgeFlag_data));
break;
case GLU_TESS_COMBINE_DATA:
rb_ary_store(tdata->t_ref, TESS_COMBINE_DATA, arg3);
if (NIL_P(arg3))
gluTessCallback(tdata->tobj, type, NULL);
else
gluTessCallback(tdata->tobj, type,
(VOIDFUNC)(t_combine_data));
break;
#endif /* GLU_VERSION_1_2 */
}
return Qnil;
}
static VALUE
glu_BeginPolygon(obj, arg1)
VALUE obj, arg1;
{
struct tessdata* tdata;
GetTESS(arg1, tdata);
rb_ary_store(tdata->t_ref, TESS_DATA, rb_ary_new());
rb_ary_push(t_current, arg1);
gluBeginPolygon(tdata->tobj);
return Qnil;
}
static VALUE
glu_TessVertex(obj, arg1, arg2, arg3)
VALUE obj, arg1, arg2, arg3;
{
struct tessdata* tdata;
GLdouble v[3];
VALUE call_key;
ID id;
GetTESS(arg1, tdata);
rb_ary_push(rb_ary_entry(tdata->t_ref, TESS_DATA), arg3);
ary2cdbl(arg2, v, 3);
gluTessVertex(tdata->tobj, v,(void *)arg3);
return Qnil;
}
static VALUE
glu_NextContour(obj, arg1, arg2)
VALUE obj, arg1, arg2;
{
struct tessdata* tdata;
GLenum type;
GetTESS(arg1, tdata);
type = (GLenum)NUM2INT(arg2);
gluNextContour(tdata->tobj, type);
return Qnil;
}
static VALUE
glu_EndPolygon(obj, arg1)
VALUE obj, arg1;
{
struct tessdata* tdata;
GetTESS(arg1, tdata);
gluEndPolygon(tdata->tobj);
rb_ary_store(tdata->t_ref, TESS_DATA, Qnil);
rb_ary_pop(t_current);
return Qnil;
}
/*
* Quadric API
*/
static void
free_quad(qdata)
struct quaddata *qdata;
{
if (qdata->qobj) gluDeleteQuadric(qdata->qobj);
qdata->qobj = NULL;
}
static VALUE
glu_NewQuadric(obj)
VALUE obj;
{
VALUE ret;
struct quaddata *qdata;
ret = Data_Make_Struct(cQuad, struct quaddata, 0, free_quad, qdata);
qdata->qobj = gluNewQuadric();
return ret;
}
static VALUE
glu_DeleteQuadric(obj, arg1)
VALUE obj, arg1;
{
struct quaddata *qdata;
GetQUAD(arg1, qdata);
free_quad(qdata);
return Qnil;
}
static VALUE
glu_QuadricNormals(obj, arg1, arg2)
VALUE obj, arg1, arg2;
{
struct quaddata* qdata;
GLenum normals;
GetQUAD(arg1, qdata);
normals = (GLenum)NUM2INT(arg2);
gluQuadricNormals(qdata->qobj, normals);
return Qnil;
}
static VALUE
glu_QuadricTexture(obj, arg1, arg2)
VALUE obj, arg1, arg2;
{
struct quaddata* qdata;
GLboolean textureCoords;
GetQUAD(arg1, qdata);
textureCoords = (GLboolean)NUM2INT(arg2);
gluQuadricTexture(qdata->qobj, textureCoords);
return Qnil;
}
static VALUE
glu_QuadricOrientation(obj, arg1, arg2)
VALUE obj, arg1, arg2;
{
struct quaddata* qdata;
GLenum orientation;
GetQUAD(arg1, qdata);
orientation = (GLenum)NUM2INT(arg2);
gluQuadricOrientation(qdata->qobj, orientation);
return Qnil;
}
static VALUE
glu_QuadricDrawStyle(obj, arg1, arg2)
VALUE obj, arg1, arg2;
{
struct quaddata* qdata;
GLenum drawStyle;
GetQUAD(arg1, qdata);
drawStyle = (GLenum)NUM2INT(arg2);
gluQuadricDrawStyle(qdata->qobj, drawStyle);
return Qnil;
}
static VALUE
glu_Cylinder(obj, arg1, arg2, arg3, arg4, arg5, arg6)
VALUE obj, arg1, arg2, arg3, arg4, arg5, arg6;
{
struct quaddata* qdata;
GLdouble baseRadius;
GLdouble topRadius;
GLdouble height;
GLint slices;
GLint stacks;
GetQUAD(arg1, qdata);
baseRadius = (GLdouble)NUM2DBL(arg2);
topRadius = (GLdouble)NUM2DBL(arg3);
height = (GLdouble)NUM2DBL(arg4);
slices = (GLint)NUM2INT(arg5);
stacks = (GLint)NUM2INT(arg6);
gluCylinder(qdata->qobj, baseRadius, topRadius, height, slices, stacks);
return Qnil;
}
static VALUE
glu_Disk(obj, arg1, arg2, arg3, arg4, arg5)
VALUE obj, arg1, arg2, arg3, arg4, arg5;
{
struct quaddata* qdata;
GLdouble innerRadius;
GLdouble outerRadius;
GLint slices;
GLint loops;
GetQUAD(arg1, qdata);
innerRadius = (GLdouble)NUM2DBL(arg2);
outerRadius = (GLdouble)NUM2DBL(arg3);
slices = (GLint)NUM2INT(arg4);
loops = (GLint)NUM2INT(arg5);
gluDisk(qdata->qobj, innerRadius, outerRadius, slices, loops);
return Qnil;
}
static VALUE
glu_PartialDisk(obj, arg1, arg2, arg3, arg4, arg5, arg6, arg7)
VALUE obj, arg1, arg2, arg3, arg4, arg5, arg6, arg7;
{
struct quaddata* qdata;
GLdouble innerRadius;
GLdouble outerRadius;
GLint slices;
GLint loops;
GLdouble startAngle;
GLdouble sweepAngle;
GetQUAD(arg1, qdata);
innerRadius = (GLdouble)NUM2DBL(arg2);
outerRadius = (GLdouble)NUM2DBL(arg3);
slices = (GLint)NUM2INT(arg4);
loops = (GLint)NUM2INT(arg5);
startAngle = (GLdouble)NUM2DBL(arg6);
sweepAngle = (GLdouble)NUM2DBL(arg7);
gluPartialDisk(qdata->qobj, innerRadius, outerRadius, slices, loops,
startAngle, sweepAngle);
return Qnil;
}
static VALUE
glu_Sphere(obj, arg1, arg2, arg3, arg4)
VALUE obj, arg1, arg2, arg3, arg4;
{
struct quaddata* qdata;
GLdouble radius;
GLint slices;
GLint stacks;
GetQUAD(arg1, qdata);
radius = (GLdouble)NUM2DBL(arg2);
slices = (GLint)NUM2INT(arg3);
stacks = (GLint)NUM2INT(arg4);
gluSphere(qdata->qobj, radius, slices, stacks);
return Qnil;
}
static VALUE
glu_LookAt(obj,arg1,arg2,arg3,arg4,arg5,arg6,arg7,arg8,arg9)
VALUE obj,arg1,arg2,arg3,arg4,arg5,arg6,arg7,arg8,arg9;
{
GLdouble eyex;
GLdouble eyey;
GLdouble eyez;
GLdouble centerx;
GLdouble centery;
GLdouble centerz;
GLdouble upx;
GLdouble upy;
GLdouble upz;
eyex = (GLdouble)NUM2DBL(arg1);
eyey = (GLdouble)NUM2DBL(arg2);
eyez = (GLdouble)NUM2DBL(arg3);
centerx = (GLdouble)NUM2DBL(arg4);
centery = (GLdouble)NUM2DBL(arg5);
centerz = (GLdouble)NUM2DBL(arg6);
upx = (GLdouble)NUM2DBL(arg7);
upy = (GLdouble)NUM2DBL(arg8);
upz = (GLdouble)NUM2DBL(arg9);
gluLookAt( eyex, eyey, eyez, centerx, centery, centerz, upx, upy, upz );
return Qnil;
}
static VALUE
glu_Ortho2D(obj,arg1,arg2,arg3,arg4)
VALUE obj,arg1,arg2,arg3,arg4;
{
GLdouble left;
GLdouble right;
GLdouble bottom;
GLdouble top;
left = (GLdouble)NUM2DBL(arg1);
right = (GLdouble)NUM2DBL(arg2);
bottom = (GLdouble)NUM2DBL(arg3);
top = (GLdouble)NUM2DBL(arg4);
gluOrtho2D(left,right,bottom,top);
return Qnil;
}
static VALUE
glu_Perspective(obj,arg1,arg2,arg3,arg4)
VALUE obj,arg1,arg2,arg3,arg4;
{
GLdouble fovy;
GLdouble aspect;
GLdouble zNear;
GLdouble zFar;
fovy = (GLdouble)NUM2DBL(arg1);
aspect = (GLdouble)NUM2DBL(arg2);
zNear = (GLdouble)NUM2DBL(arg3);
zFar = (GLdouble)NUM2DBL(arg4);
gluPerspective(fovy,aspect,zNear,zFar);
return Qnil;
}
static VALUE
glu_PickMatrix(argc,argv,obj)
int argc;
VALUE* argv;
VALUE obj;
{
GLdouble x;
GLdouble y;
GLdouble width;
GLdouble height;
GLint viewport[4];
VALUE args[5];
switch (rb_scan_args(argc, argv, "23", &args[0], &args[1], &args[2],
&args[3], &args[4])) {
case 2:
width = 5.0f;
height = 5.0f;
glGetIntegerv(GL_VIEWPORT, viewport);
break;
case 4:
width = (GLdouble)NUM2DBL(args[2]);
height = (GLdouble)NUM2DBL(args[3]);
glGetIntegerv(GL_VIEWPORT, viewport);
break;
case 5:
width = (GLdouble)NUM2DBL(args[2]);
height = (GLdouble)NUM2DBL(args[3]);
ary2cint(args[4], viewport, 4);
break;
default:
rb_raise(rb_eArgError, "GLU.PickMatrix args len:%d",argc);
}
x = (GLdouble)NUM2DBL(args[0]);
y = (GLdouble)NUM2DBL(args[1]);
gluPickMatrix(x, y, width, height, viewport);
return Qnil;
}
static VALUE
glu_Project(argc,argv,obj)
int argc;
VALUE* argv;
VALUE obj;
{
GLdouble ox;
GLdouble oy;
GLdouble oz;
GLdouble mdl_mtx[4*4];
GLdouble prj_mtx[4*4];
GLint vport[4];
GLdouble wx;
GLdouble wy;
GLdouble wz;
VALUE args[6];
VALUE ret;
switch (rb_scan_args(argc, argv, "33", &args[0], &args[1], &args[2],
&args[3], &args[4], &args[5])) {
case 3:
glGetDoublev(GL_MODELVIEW_MATRIX, mdl_mtx);
glGetDoublev(GL_PROJECTION_MATRIX, prj_mtx);
glGetIntegerv(GL_VIEWPORT, vport);
break;
case 6:
ary2cmat4x4(args[3], mdl_mtx);
ary2cmat4x4(args[4], prj_mtx);
ary2cint(args[5], vport, 4);
break;
default:
rb_raise(rb_eArgError, "GLU.Project args len:%d",argc);
}
ox = (GLdouble)NUM2DBL(args[0]);
oy = (GLdouble)NUM2DBL(args[1]);
oz = (GLdouble)NUM2DBL(args[2]);
if (gluProject(ox, oy, oz, mdl_mtx, prj_mtx, vport, &wx, &wy, &wz)
== GL_TRUE) {
ret = rb_ary_new3(3, rb_float_new(wx), rb_float_new(wy),
rb_float_new(wz));
return ret;
}
else
return Qnil;
}
static VALUE
glu_UnProject(argc,argv,obj)
int argc;
VALUE* argv;
VALUE obj;
{
GLdouble wx;
GLdouble wy;
GLdouble wz;
GLdouble mdl_mtx[4*4];
GLdouble prj_mtx[4*4];
GLint vport[4];
GLdouble ox;
GLdouble oy;
GLdouble oz;
VALUE args[6];
VALUE ret;
switch (rb_scan_args(argc, argv, "33", &args[0], &args[1], &args[2],
&args[3], &args[4], &args[5])) {
case 3:
glGetDoublev(GL_MODELVIEW_MATRIX, mdl_mtx);
glGetDoublev(GL_PROJECTION_MATRIX, prj_mtx);
glGetIntegerv(GL_VIEWPORT, vport);
break;
case 6:
ary2cmat4x4(args[3], mdl_mtx);
ary2cmat4x4(args[4], prj_mtx);
ary2cint(args[5], vport, 4);
break;
default:
rb_raise(rb_eArgError, "GLU.UnProject args len:%d",argc);
}
wx = (GLdouble)NUM2DBL(args[0]);
wy = (GLdouble)NUM2DBL(args[1]);
wz = (GLdouble)NUM2DBL(args[2]);
if (gluUnProject(wx, wy, wz, mdl_mtx, prj_mtx, vport, &ox, &oy, &oz)
== GL_TRUE) {
ret = rb_ary_new3(3, rb_float_new(ox), rb_float_new(oy),
rb_float_new(oz));
return ret;
}
else
return Qnil;
}
static VALUE
glu_Build2DMipmaps(obj, arg1, arg2, arg3, arg4, arg5, arg6, arg7)
VALUE obj, arg1, arg2, arg3, arg4, arg5, arg6, arg7;
{
GLenum target;
GLint components;
GLint width;
GLint height;
GLenum format;
GLenum type;
void* data;
int type_size;
int format_size;
int size;
target = (GLenum)NUM2INT(arg1);
components = (GLint)NUM2INT(arg2);
width = (GLint)NUM2INT(arg3);
height = (GLint)NUM2INT(arg4);
format = (GLenum)NUM2INT(arg5);
type = (GLenum)NUM2INT(arg6);
if (TYPE(arg7) == T_STRING) {
type_size = gltype_size(type) / 8;
format_size = glformat_size(format);
if (type_size == -1 || format_size == -1)
return Qnil;
size = type_size*format_size*height*width;
if (RSTRING(arg7)->len < size)
rb_raise(rb_eArgError, "string length:%d",RSTRING(arg7)->len);
data = RSTRING(arg7)->ptr;
} else
rb_raise(rb_eTypeError, "type mismatch:%s",rb_class2name(arg7));
return INT2NUM(gluBuild2DMipmaps(target, components, width, height,
format, type, data));
}
static VALUE
glu_ScaleImage(obj, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8)
VALUE obj, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8;
{
GLenum format;
GLint widthin;
GLint heightin;
GLenum typein;
void* datain;
GLint widthout;
GLint heightout;
GLenum typeout;
int type_size;
int format_size;
int size;
VALUE ret;
format = (GLenum)NUM2INT(arg1);
widthin = (GLint)NUM2INT(arg2);
heightin = (GLint)NUM2INT(arg3);
typein = (GLenum)NUM2INT(arg4);
if (TYPE(arg5) == T_STRING) {
type_size = gltype_size(typein) / 8;
format_size = glformat_size(format);
if (type_size == -1 || format_size == -1)
return Qnil;
size = type_size*format_size*heightin*widthin;
if (RSTRING(arg5)->len < size)
rb_raise(rb_eArgError, "string length:%d",RSTRING(arg5)->len);
datain = RSTRING(arg5)->ptr;
} else
rb_raise(rb_eTypeError, "type mismatch:%s",rb_class2name(arg5));
widthout = (GLint)NUM2INT(arg6);
heightout = (GLint)NUM2INT(arg7);
typeout = (GLenum)NUM2INT(arg8);
type_size = gltype_size(typeout) / 8;
ret =
allocate_buffer_with_string(widthout*heightout*format_size*type_size);
gluScaleImage(format, widthin, heightin, typein, datain,
widthout, heightout, typeout, (GLvoid*)RSTRING(ret)->ptr);
return ret;
}
static VALUE
glu_ErrorString(obj, arg1)
VALUE obj, arg1;
{
GLenum errorCode;
GLubyte* error;
errorCode = (GLenum)NUM2INT(arg1);
error = (GLubyte*)gluErrorString(errorCode);
if (error)
return rb_str_new2(error);
else
return Qnil;
}
#if defined(GLU_VERSION_1_1)
static VALUE
glu_GetString(obj, arg1)
VALUE obj, arg1;
{
GLenum name;
GLubyte* str;
name = (GLenum)NUM2INT(arg1);
str = (GLubyte*)gluGetString(name);
if (str)
return rb_str_new2(str);
else
return Qnil;
}
#endif
static VALUE mGLU;
void
InitializeGLU()
{
callId = rb_intern("call");
refId = rb_intern("[]");
mGLU = rb_define_module("GLU");
rb_define_module_function(mGLU, "NewNurbsRenderer",
glu_NewNurbsRenderer, 0);
rb_define_module_function(mGLU, "DeleteNurbsRenderer",
glu_DeleteNurbsRenderer, 1);
rb_define_module_function(mGLU, "NurbsProperty", glu_NurbsProperty, 3);
rb_define_module_function(mGLU, "GetNurbsProperty",
glu_GetNurbsProperty, 2);
rb_define_module_function(mGLU, "BeginCurve", glu_BeginCurve, 1);
rb_define_module_function(mGLU, "EndCurve", glu_EndCurve, 1);
rb_define_module_function(mGLU, "NurbsCurve", glu_NurbsCurve, -1);
rb_define_module_function(mGLU, "BeginSurface", glu_BeginSurface, 1);
rb_define_module_function(mGLU, "EndSurface", glu_EndSurface, 1);
rb_define_module_function(mGLU, "NurbsSurface", glu_NurbsSurface, -1);
rb_define_module_function(mGLU, "BeginTrim", glu_BeginTrim, 1);
rb_define_module_function(mGLU, "EndTrim", glu_EndTrim, 1);
rb_define_module_function(mGLU, "PwlCurve", glu_PwlCurve, -1);
rb_define_module_function(mGLU, "NewTess", glu_NewTess, 0);
rb_define_module_function(mGLU, "DeleteTess", glu_DeleteTess, 1);
rb_define_module_function(mGLU, "TessCallback", glu_TessCallback, 3);
rb_define_module_function(mGLU, "BeginPolygon", glu_BeginPolygon, 1);
rb_define_module_function(mGLU, "TessVertex", glu_TessVertex, 3);
rb_define_module_function(mGLU, "NextContour", glu_NextContour, 2);
rb_define_module_function(mGLU, "EndPolygon", glu_EndPolygon, 1);
#if defined(GLU_VERSION_1_2)
rb_define_module_function(mGLU, "TessBeginPolygon",
glu_TessBeginPolygon, 2);
rb_define_module_function(mGLU, "TessBeginContour",
glu_TessBeginContour, 1);
rb_define_module_function(mGLU, "TessEndContour", glu_TessEndContour,
1);
rb_define_module_function(mGLU, "TessEndPolygon", glu_TessEndPolygon,
1);
rb_define_module_function(mGLU, "TessProperty", glu_TessProperty, 3);
rb_define_module_function(mGLU, "TessNormal", glu_TessNormal, 4);
rb_define_module_function(mGLU, "GetTessProperty", glu_GetTessProperty,
2);
#endif /* GLU_VERSION_1_2 */
rb_define_module_function(mGLU, "NewQuadric", glu_NewQuadric, 0);
rb_define_module_function(mGLU, "DeleteQuadric", glu_DeleteQuadric, 1);
rb_define_module_function(mGLU, "QuadricNormals", glu_QuadricNormals,
2);
rb_define_module_function(mGLU, "QuadricTexture", glu_QuadricTexture,
2);
rb_define_module_function(mGLU, "QuadricOrientation",
glu_QuadricOrientation, 2);
rb_define_module_function(mGLU, "QuadricDrawStyle",
glu_QuadricDrawStyle, 2);
rb_define_module_function(mGLU, "Cylinder", glu_Cylinder, 6);
rb_define_module_function(mGLU, "Disk", glu_Disk, 5);
rb_define_module_function(mGLU, "PartialDisk", glu_PartialDisk, 7);
rb_define_module_function(mGLU, "Sphere", glu_Sphere, 4);
rb_define_module_function(mGLU, "LookAt", glu_LookAt, 9);
rb_define_module_function(mGLU, "Ortho2D", glu_Ortho2D, 4);
rb_define_module_function(mGLU, "Perspective", glu_Perspective, 4);
rb_define_module_function(mGLU, "PickMatrix", glu_PickMatrix, -1);
rb_define_module_function(mGLU, "Project", glu_Project, -1);
rb_define_module_function(mGLU, "UnProject", glu_UnProject, -1);
rb_define_module_function(mGLU, "Build2DMipmaps", glu_Build2DMipmaps,
7);
rb_define_module_function(mGLU, "ScaleImage", glu_ScaleImage, 8);
rb_define_module_function(mGLU, "ErrorString", glu_ErrorString, 1);
#if defined(GLU_VERSION_1_1)
rb_define_module_function(mGLU, "GetString", glu_GetString, 1);
#endif
rb_define_const(mGLU, "SMOOTH", INT2NUM(GLU_SMOOTH));
rb_define_const(mGLU, "FLAT", INT2NUM(GLU_FLAT));
rb_define_const(mGLU, "NONE", INT2NUM(GLU_NONE));
rb_define_const(mGLU, "POINT", INT2NUM(GLU_POINT));
rb_define_const(mGLU, "LINE", INT2NUM(GLU_LINE));
rb_define_const(mGLU, "FILL", INT2NUM(GLU_FILL));
rb_define_const(mGLU, "SILHOUETTE", INT2NUM(GLU_SILHOUETTE));
rb_define_const(mGLU, "OUTSIDE", INT2NUM(GLU_OUTSIDE));
rb_define_const(mGLU, "INSIDE", INT2NUM(GLU_INSIDE));
#if defined(GLU_VERSION_1_2)
rb_define_const(mGLU, "TESS_BEGIN", INT2NUM(GLU_TESS_BEGIN));
rb_define_const(mGLU, "TESS_VERTEX", INT2NUM(GLU_TESS_VERTEX));
rb_define_const(mGLU, "TESS_END", INT2NUM(GLU_TESS_END));
rb_define_const(mGLU, "TESS_ERROR", INT2NUM(GLU_TESS_ERROR));
rb_define_const(mGLU, "TESS_EDGE_FLAG", INT2NUM(GLU_TESS_EDGE_FLAG));
rb_define_const(mGLU, "TESS_COMBINE", INT2NUM(GLU_TESS_COMBINE));
rb_define_const(mGLU, "TESS_BEGIN_DATA", INT2NUM(GLU_TESS_BEGIN_DATA));
rb_define_const(mGLU, "TESS_VERTEX_DATA",
INT2NUM(GLU_TESS_VERTEX_DATA));
rb_define_const(mGLU, "TESS_END_DATA", INT2NUM(GLU_TESS_END_DATA));
rb_define_const(mGLU, "TESS_ERROR_DATA", INT2NUM(GLU_TESS_ERROR_DATA));
rb_define_const(mGLU, "TESS_EDGE_FLAG_DATA",
INT2NUM(GLU_TESS_EDGE_FLAG_DATA));
rb_define_const(mGLU, "TESS_COMBINE_DATA",
INT2NUM(GLU_TESS_COMBINE_DATA));
/* Winding rules */
rb_define_const(mGLU, "TESS_WINDING_ODD",
INT2NUM(GLU_TESS_WINDING_ODD));
rb_define_const(mGLU, "TESS_WINDING_NONZERO",
INT2NUM(GLU_TESS_WINDING_NONZERO));
rb_define_const(mGLU, "TESS_WINDING_POSITIVE",
INT2NUM(GLU_TESS_WINDING_POSITIVE));
rb_define_const(mGLU, "TESS_WINDING_NEGATIVE",
INT2NUM(GLU_TESS_WINDING_NEGATIVE));
rb_define_const(mGLU, "TESS_WINDING_ABS_GEQ_TWO",
INT2NUM(GLU_TESS_WINDING_ABS_GEQ_TWO));
/* Tessellation properties */
rb_define_const(mGLU, "TESS_WINDING_RULE",
INT2NUM(GLU_TESS_WINDING_RULE));
rb_define_const(mGLU, "TESS_BOUNDARY_ONLY",
INT2NUM(GLU_TESS_BOUNDARY_ONLY));
rb_define_const(mGLU, "TESS_TOLERANCE", INT2NUM(GLU_TESS_TOLERANCE));
#endif /* GLU_VERSION_1_2 */
rb_define_const(mGLU, "BEGIN", INT2NUM(GLU_BEGIN));
rb_define_const(mGLU, "VERTEX", INT2NUM(GLU_VERTEX));
rb_define_const(mGLU, "END", INT2NUM(GLU_END));
rb_define_const(mGLU, "ERROR", INT2NUM(GLU_ERROR));
rb_define_const(mGLU, "EDGE_FLAG", INT2NUM(GLU_EDGE_FLAG));
rb_define_const(mGLU, "CW", INT2NUM(GLU_CW));
rb_define_const(mGLU, "CCW", INT2NUM(GLU_CCW));
rb_define_const(mGLU, "INTERIOR", INT2NUM(GLU_INTERIOR));
rb_define_const(mGLU, "EXTERIOR", INT2NUM(GLU_EXTERIOR));
rb_define_const(mGLU, "UNKNOWN", INT2NUM(GLU_UNKNOWN));
rb_define_const(mGLU, "TESS_ERROR1", INT2NUM(GLU_TESS_ERROR1));
rb_define_const(mGLU, "TESS_ERROR2", INT2NUM(GLU_TESS_ERROR2));
rb_define_const(mGLU, "TESS_ERROR3", INT2NUM(GLU_TESS_ERROR3));
rb_define_const(mGLU, "TESS_ERROR4", INT2NUM(GLU_TESS_ERROR4));
rb_define_const(mGLU, "TESS_ERROR5", INT2NUM(GLU_TESS_ERROR5));
rb_define_const(mGLU, "TESS_ERROR6", INT2NUM(GLU_TESS_ERROR6));
rb_define_const(mGLU, "TESS_ERROR7", INT2NUM(GLU_TESS_ERROR7));
rb_define_const(mGLU, "TESS_ERROR8", INT2NUM(GLU_TESS_ERROR8));
#if defined(TESS_ERROR9)
rb_define_const(mGLU, "TESS_ERROR9", INT2NUM(GLU_TESS_ERROR9));
#endif
rb_define_const(mGLU, "AUTO_LOAD_MATRIX",
INT2NUM(GLU_AUTO_LOAD_MATRIX));
rb_define_const(mGLU, "CULLING", INT2NUM(GLU_CULLING));
rb_define_const(mGLU, "SAMPLING_TOLERANCE",
INT2NUM(GLU_SAMPLING_TOLERANCE));
rb_define_const(mGLU, "DISPLAY_MODE", INT2NUM(GLU_DISPLAY_MODE));
rb_define_const(mGLU, "SAMPLING_METHOD", INT2NUM(GLU_SAMPLING_METHOD));
rb_define_const(mGLU, "U_STEP", INT2NUM(GLU_U_STEP));
rb_define_const(mGLU, "V_STEP", INT2NUM(GLU_V_STEP));
rb_define_const(mGLU, "PATH_LENGTH", INT2NUM(GLU_PATH_LENGTH));
rb_define_const(mGLU, "PARAMETRIC_ERROR",
INT2NUM(GLU_PARAMETRIC_ERROR));
rb_define_const(mGLU, "DOMAIN_DISTANCE", INT2NUM(GLU_DOMAIN_DISTANCE));
rb_define_const(mGLU, "MAP1_TRIM_2", INT2NUM(GLU_MAP1_TRIM_2));
rb_define_const(mGLU, "MAP1_TRIM_3", INT2NUM(GLU_MAP1_TRIM_3));
rb_define_const(mGLU, "OUTLINE_POLYGON", INT2NUM(GLU_OUTLINE_POLYGON));
rb_define_const(mGLU, "OUTLINE_PATCH", INT2NUM(GLU_OUTLINE_PATCH));
rb_define_const(mGLU, "NURBS_ERROR1", INT2NUM(GLU_NURBS_ERROR1));
rb_define_const(mGLU, "NURBS_ERROR2", INT2NUM(GLU_NURBS_ERROR2));
rb_define_const(mGLU, "NURBS_ERROR3", INT2NUM(GLU_NURBS_ERROR3));
rb_define_const(mGLU, "NURBS_ERROR4", INT2NUM(GLU_NURBS_ERROR4));
rb_define_const(mGLU, "NURBS_ERROR5", INT2NUM(GLU_NURBS_ERROR5));
rb_define_const(mGLU, "NURBS_ERROR6", INT2NUM(GLU_NURBS_ERROR6));
rb_define_const(mGLU, "NURBS_ERROR7", INT2NUM(GLU_NURBS_ERROR7));
rb_define_const(mGLU, "NURBS_ERROR8", INT2NUM(GLU_NURBS_ERROR8));
rb_define_const(mGLU, "NURBS_ERROR9", INT2NUM(GLU_NURBS_ERROR9));
rb_define_const(mGLU, "NURBS_ERROR10", INT2NUM(GLU_NURBS_ERROR10));
rb_define_const(mGLU, "NURBS_ERROR11", INT2NUM(GLU_NURBS_ERROR11));
rb_define_const(mGLU, "NURBS_ERROR12", INT2NUM(GLU_NURBS_ERROR12));
rb_define_const(mGLU, "NURBS_ERROR13", INT2NUM(GLU_NURBS_ERROR13));
rb_define_const(mGLU, "NURBS_ERROR14", INT2NUM(GLU_NURBS_ERROR14));
rb_define_const(mGLU, "NURBS_ERROR15", INT2NUM(GLU_NURBS_ERROR15));
rb_define_const(mGLU, "NURBS_ERROR16", INT2NUM(GLU_NURBS_ERROR16));
rb_define_const(mGLU, "NURBS_ERROR17", INT2NUM(GLU_NURBS_ERROR17));
rb_define_const(mGLU, "NURBS_ERROR18", INT2NUM(GLU_NURBS_ERROR18));
rb_define_const(mGLU, "NURBS_ERROR19", INT2NUM(GLU_NURBS_ERROR19));
rb_define_const(mGLU, "NURBS_ERROR20", INT2NUM(GLU_NURBS_ERROR20));
rb_define_const(mGLU, "NURBS_ERROR21", INT2NUM(GLU_NURBS_ERROR21));
rb_define_const(mGLU, "NURBS_ERROR22", INT2NUM(GLU_NURBS_ERROR22));
rb_define_const(mGLU, "NURBS_ERROR23", INT2NUM(GLU_NURBS_ERROR23));
rb_define_const(mGLU, "NURBS_ERROR24", INT2NUM(GLU_NURBS_ERROR24));
rb_define_const(mGLU, "NURBS_ERROR25", INT2NUM(GLU_NURBS_ERROR25));
rb_define_const(mGLU, "NURBS_ERROR26", INT2NUM(GLU_NURBS_ERROR26));
rb_define_const(mGLU, "NURBS_ERROR27", INT2NUM(GLU_NURBS_ERROR27));
rb_define_const(mGLU, "NURBS_ERROR28", INT2NUM(GLU_NURBS_ERROR28));
rb_define_const(mGLU, "NURBS_ERROR29", INT2NUM(GLU_NURBS_ERROR29));
rb_define_const(mGLU, "NURBS_ERROR30", INT2NUM(GLU_NURBS_ERROR30));
rb_define_const(mGLU, "NURBS_ERROR31", INT2NUM(GLU_NURBS_ERROR31));
rb_define_const(mGLU, "NURBS_ERROR32", INT2NUM(GLU_NURBS_ERROR32));
rb_define_const(mGLU, "NURBS_ERROR33", INT2NUM(GLU_NURBS_ERROR33));
rb_define_const(mGLU, "NURBS_ERROR34", INT2NUM(GLU_NURBS_ERROR34));
rb_define_const(mGLU, "NURBS_ERROR35", INT2NUM(GLU_NURBS_ERROR35));
rb_define_const(mGLU, "NURBS_ERROR36", INT2NUM(GLU_NURBS_ERROR36));
rb_define_const(mGLU, "NURBS_ERROR37", INT2NUM(GLU_NURBS_ERROR37));
rb_define_const(mGLU, "INVALID_ENUM", INT2NUM(GLU_INVALID_ENUM));
rb_define_const(mGLU, "INVALID_VALUE", INT2NUM(GLU_INVALID_VALUE));
rb_define_const(mGLU, "OUT_OF_MEMORY", INT2NUM(GLU_OUT_OF_MEMORY));
#ifdef GLU_INCOMPATIBLE_GL_VERSION
rb_define_const(mGLU, "INCOMPATIBLE_GL_VERSION",
INT2NUM(GLU_INCOMPATIBLE_GL_VERSION));
#endif
rb_define_const(mGLU, "VERSION", INT2NUM(GLU_VERSION));
rb_define_const(mGLU, "EXTENSIONS", INT2NUM(GLU_EXTENSIONS));
cNurbs = rb_define_class("Nurbs", rb_cObject);
cTess = rb_define_class("Tess", rb_cObject);
cQuad = rb_define_class("Quadric", rb_cObject);
rb_global_variable(&t_current);
t_current = rb_ary_new();
}