GLXWorkstation.st
changeset 12 9f0995fac1fa
parent 5 e5942fea6925
child 19 74683e998f36
--- a/GLXWorkstation.st	Sat Dec 11 02:34:56 1993 +0100
+++ b/GLXWorkstation.st	Sat Dec 11 02:36:44 1993 +0100
@@ -11,7 +11,7 @@
 "
 
 XWorkstation subclass:#GLXWorkstation
-       instanceVariableNames:''
+       instanceVariableNames:'activeWindow'
        classVariableNames:   ''
        poolDictionaries:''
        category:'Interface-Graphics'
@@ -24,7 +24,7 @@
 
 this class just to give a hint of what could be ...
 
-$Header: /cvs/stx/stx/libview/GLXWorkstation.st,v 1.2 1993-10-13 00:45:42 claus Exp $
+$Header: /cvs/stx/stx/libview/GLXWorkstation.st,v 1.3 1993-12-11 01:29:27 claus Exp $
 written june 93 by claus
 '!
 
@@ -36,6 +36,7 @@
  */
 # define String GLX_String
 # include <gl/glws.h>
+# include <gl/sphere.h>
 
 typedef enum {
     GLXcolorIndexSingleBuffer,
@@ -49,6 +50,8 @@
 
 #endif
 
+#define OLD
+
 /*
  * some defines - tired of typing ...
  */
@@ -61,6 +64,14 @@
 
 #define myDpy MKDPY(_INST(displayId))
 
+#define SETWIN(aGLXWindowId)                             \
+    if (_INST(activeWindow) != aGLXWindowId) {           \
+        if (GLXwinset(myDpy, MKWIN(aGLXWindowId)) < 0) { \
+            RETURN (false);                              \
+        }                                                \
+        _INST(activeWindow) = aGLXWindowId;              \
+    }
+
 #define _COORD_(arg, dst)               \
     if (_isFloat(arg))                  \
         dst = (Coord)(_floatVal(arg));  \
@@ -85,17 +96,167 @@
         dst = (int)(_intVal(arg));      \
     else break;
 
+static float *
+getFloatsFromInto(obj, vec, count)
+   OBJ obj;
+   float *vec;
+{
+    OBJ cls;
+    int nByte;
+    OBJ o;
+    int i, ninstVars, nInstBytes;
+    char *pElem;
+
+    if (! _isNonNilObject(obj)) return (float *)0;
+
+    cls = _qClass(obj);
+    ninstVars = _intVal(_ClassInstPtr(cls)->c_ninstvars);
+    nInstBytes = OHDR_SIZE + ninstVars * sizeof(OBJ);
+    nByte = _qSize(obj) - nInstBytes;
+    pElem = (char *)(_InstPtr(obj)) + nInstBytes;
+
+    switch (_intVal(_ClassInstPtr(cls)->c_flags) & ARRAYMASK) {
+      case FLOATARRAY:
+        /* best speed for float array - the data is already as we want it */
+        if (nByte < (count * sizeof(float))) return (float *)0;
+        return (float *)pElem;
+
+      case DOUBLEARRAY:
+        if (nByte < (count * sizeof(double))) return (float *)0;
+        for (i=0; i<count; i++) {
+            vec[i] = *((double *)pElem);
+            pElem += sizeof(double);
+        }
+        return vec;
+
+      case POINTERARRAY:
+        if (nByte < (count * sizeof(OBJ))) return (float *)0;
+        /* get elements one-by-one */
+        for (i=0; i<count; i++) {
+            o = *(OBJ *)pElem;
+            if (_isFloat(o)) vec[i] = _floatVal(o);
+            else if (_isSmallInteger(o)) vec[i] = (float)(_intVal(o));
+            else return 0;
+            pElem += sizeof(OBJ);
+        }
+        return vec;
+    }
+    return (float *)0;
+}
+
+static
+putFloatsFromInto(vec, obj, count)
+   OBJ obj;
+   float *vec;
+{
+    OBJ cls;
+    int nByte;
+    OBJ o;
+    int i, ninstVars, nInstBytes;
+    char *pElem;
+
+    if (! _isNonNilObject(obj)) return 0;
+
+    cls = _qClass(obj);
+    ninstVars = _intVal(_ClassInstPtr(cls)->c_ninstvars);
+    nInstBytes = OHDR_SIZE + ninstVars * sizeof(OBJ);
+    nByte = _qSize(obj) - nInstBytes;
+    pElem = (char *)(_InstPtr(obj)) + nInstBytes;
+
+    switch (_intVal(_ClassInstPtr(cls)->c_flags) & ARRAYMASK) {
+      case FLOATARRAY:
+        if (nByte < (count * sizeof(float))) return 0;
+        for (i=0; i<count; i++) {
+            *(float *)pElem = vec[i];
+            pElem += sizeof(float);
+        }
+        return 1;
+
+      case DOUBLEARRAY:
+        if (nByte < (count * sizeof(float))) return 0;
+        for (i=0; i<count; i++) {
+            *(double *)pElem = vec[i];
+            pElem += sizeof(double);
+        }
+        return 1;
+    }
+    /* not implemented for others */
+
+    return 0;
+}
+
+static Matrix*
+getFloatsFromMatrixInto(obj, mp)
+    OBJ obj;
+    Matrix *mp;
+{
+    OBJ cls;
+    extern OBJ FloatArray, DoubleArray, Array;
+    int nByte;
+    OBJ o;
+
+    if (! _isNonNilObject(obj)) return (Matrix *)0;
+
+    cls = _qClass(obj);
+    nByte = _qSize(obj) - OHDR_SIZE;
+
+    if (cls == FloatArray) {
+        int x = 0;
+        int i,j;
+
+        if (nByte < (16 * sizeof(float))) return (Matrix *)0;
+        return (Matrix *) _FloatArrayInstPtr(obj)->f_element;
+    }
+    
+    if (cls == DoubleArray) {
+        int x = 0;
+        int i,j;
+
+        if (nByte < (16 * sizeof(double))) return (Matrix *)0;
+        for (i=0; i<4; i++) {
+            for (j=0; j<4; j++) {
+                (*mp)[i][j] = _DoubleArrayInstPtr(obj)->d_element[x];
+                x++;
+            }
+        }
+        return mp;
+    }
+    
+    if (cls == Array) {
+        int x = 0;
+        int i,j;
+
+        if (nByte < (16 * sizeof(OBJ))) return (Matrix *)0;
+        /* get elements one-by-one */
+        for (i=0; i<4; i++) {
+            for (j=0; j<4; j++) {
+                o = _ArrayInstPtr(obj)->a_element[x];
+                if (! _isFloat(o)) return (Matrix *)0;
+                (*mp)[i][j] = _floatVal(o);
+                x++;
+            }
+        }
+        return mp;
+    }
+    return (Matrix *)0;
+}
+
 %}
 
 !GLXWorkstation methodsFor:'window creation'!
 
-createGLXWindowFor:aView left:xpos top:ypos width:wwidth height:wheight
+createGLXWindowFor:aView left:xpos top:ypos width:wwidth height:wheight type:glxType
     |ext minWidth minHeight maxWidth maxHeight 
      bWidth bColor viewBg viewBgId wsuperView wsuperViewId wcreateOnTop 
      winputOnly wlabel wcursor wcursorId wicon wiconId windowId
      weventMask wiconView wiconViewId bitGravity viewGravity vBgColor
      vBgForm deepForm|
 
+    "{ Symbol: colorIndexSingleBuffer }"
+    "{ Symbol: colorIndexDoubleBuffer }"
+    "{ Symbol: rgbSingleBuffer }"
+    "{ Symbol: rgbDoubleBuffer }"
+
     wsuperView := aView superView.
     wsuperView notNil ifTrue:[
         wsuperViewId := wsuperView id
@@ -107,6 +268,7 @@
     int screen = _intVal(_INST(screen));
     Window newWindow, parentWindow;
     extern Window GLXCreateWindow();
+    int t;
 
     if (_isSmallInteger(xpos) && _isSmallInteger(ypos)
      && _isSmallInteger(wwidth) && _isSmallInteger(wheight)) {
@@ -116,10 +278,22 @@
             parentWindow = RootWindow(dpy, screen);
         }
 
+        if (glxType == _colorIndexSingleBuffer)
+            t = GLXcolorIndexSingleBuffer;
+        else if (glxType == _colorIndexDoubleBuffer)
+            t = GLXcolorIndexDoubleBuffer;
+        else if (glxType == _rgbSingleBuffer)
+            t = GLXrgbSingleBuffer;
+        else if (glxType == _rgbDoubleBuffer)
+            t = GLXrgbDoubleBuffer;
+        else {
+            RETURN ( nil );
+        }
+
         newWindow = GLXCreateWindow(dpy, parentWindow,
-                           _intVal(xpos), _intVal(ypos),
-                           _intVal(wwidth), _intVal(wheight),
-                           0, GLXrgbSingleBuffer);
+                                    _intVal(xpos), _intVal(ypos),
+                                    _intVal(wwidth), _intVal(wheight),
+                                    0, t);
 
         if (! newWindow) {
             RETURN ( nil );
@@ -138,20 +312,9 @@
 
 !GLXWorkstation methodsFor:'glx access'!
 
-glxWinSet:aGLXWindowId 
-    "set the current graphics window"
-
-%{  /* NOCONTEXT */
-#ifdef GLX
-    if (GLXwinset(myDpy, MKWIN(aGLXWindowId)) >= 0)
-        RETURN (true);
-#endif
-%}
-.
-    ^ false
-!
-
-glxPerspectiveFovy:fovy aspect:aspect near:near far:far
+glxPerspectiveFovy:fovy aspect:aspect 
+              near:near far:far
+                in:aGLXWindowId
     "define perspective projection"
 
 %{  /* NOCONTEXT */
@@ -166,6 +329,7 @@
         _FLOAT_ (aspect, f_aspect);
         _COORD_ (near, c_near);
         _COORD_ (far, c_far);
+        SETWIN(aGLXWindowId)
         perspective(a_fovy, f_aspect, c_near, c_far);
 
         RETURN (true);
@@ -176,7 +340,7 @@
     ^ false
 !
 
-glxTranslateX:x y:y z:z
+glxTranslateX:x y:y z:z in:aGLXWindowId
     "translate current matrix"
 
 %{  /* NOCONTEXT */
@@ -188,6 +352,7 @@
         _COORD_ (x, c_x);
         _COORD_ (y, c_y);
         _COORD_ (z, c_z);
+        SETWIN(aGLXWindowId)
         translate(c_x, c_y, c_z);
         RETURN (true);
     } while(0);
@@ -197,7 +362,7 @@
     ^ false
 !
 
-glxScaleX:x y:y z:z
+glxScaleX:x y:y z:z in:aGLXWindowId
     "scale & mirror current matrix"
 
 %{  /* NOCONTEXT */
@@ -209,6 +374,7 @@
         _FLOAT_ (x, f_x);
         _FLOAT_ (y, f_y);
         _FLOAT_ (z, f_z);
+        SETWIN(aGLXWindowId)
         scale(f_x, f_y, f_z);
         RETURN (true);
     } while(0);
@@ -218,7 +384,7 @@
     ^ false
 !
 
-glxRotate:angle axis:axis
+glxRotate:angle axis:axis in:aGLXWindowId
     "rotate the current matrix"
 
     "{ Symbol: x }"
@@ -241,6 +407,7 @@
             c_axis = 'z';
         else break;
 
+        SETWIN(aGLXWindowId)
         if (_isFloat(angle)) {
             f_angle = (float)(_floatVal(angle));
             rot(f_angle, c_axis);
@@ -259,7 +426,10 @@
     ^ false
 !
 
-glxLookatVx:vx vy:vy vz:vz px:px py:py pz:pz twist:twist
+glxLookatVx:vx vy:vy vz:vz 
+         px:px py:py pz:pz 
+      twist:twist
+         in:aGLXWindowId
     "define viewing transformation"
 
 %{  /* NOCONTEXT */
@@ -276,6 +446,7 @@
         _COORD_ (py, f_py);
         _COORD_ (pz, f_pz);
         _ANGLE_ (twist, a_twist);
+        SETWIN(aGLXWindowId)
         lookat(f_vx, f_vy, f_vz, f_px, f_py, f_pz, a_twist);
         RETURN (true);
     } while(0);
@@ -285,7 +456,7 @@
     ^ false
 !
 
-glxLmdef:what index:index np:np props:props
+glxLmdef:what index:index np:np props:props in:aGLXWindowId
     "define a material, light source or lighting model;
      props must be a FloatArray"
 
@@ -317,6 +488,7 @@
             fp = _FloatArrayInstPtr(props)->f_element;
         else break;
 
+        SETWIN(aGLXWindowId)
         lmdef(defType, i_index, i_np, fp);
         RETURN (true);
     } while(0);
@@ -326,7 +498,7 @@
     ^ false
 !
 
-glxLmbind:target index:index
+glxLmbind:target index:index in:aGLXWindowId
     "select a material, lighyt or lighting model"
 
     "{ Symbol: material }"
@@ -372,6 +544,7 @@
         else break;
 
         _INT_ (index, i_index);
+        SETWIN(aGLXWindowId)
         lmbind(defType, i_index);
         RETURN (true);
     } while(0);
@@ -381,7 +554,7 @@
     ^ false
 !
 
-glxColor:index
+glxColor:index in:aGLXWindowId
     "set color, for non gouraud shading, we dont care if the
      argument is integer or float; otherwise, better results are
      expected with float values."
@@ -389,6 +562,7 @@
 %{  /* NOCONTEXT */
 
 #ifdef GLX
+    SETWIN(aGLXWindowId)
     if (_isSmallInteger(index)) {
         color((Colorindex)(_intVal(index)));
         RETURN (true);
@@ -403,11 +577,34 @@
     ^ false
 !
 
-glxClear
+glxColorRed:r green:g blue:b in:aGLXWindowId
+    "set color, args must be integer values"
+
+%{  /* NOCONTEXT */
+
+#ifdef GLX
+    short s_r, s_g, s_b;
+
+    do {
+        _INT_(r, s_r);
+        _INT_(g, s_g);
+        _INT_(b, s_b);
+        SETWIN(aGLXWindowId)
+        RGBcolor(s_r, s_g, s_b);
+        RETURN (true);
+    } while(0);
+#endif
+%}
+.
+    ^ false
+!
+
+glxClearIn:aGLXWindowId
     "clear to current color"
 
 %{  /* NOCONTEXT */
 #ifdef GLX
+    SETWIN(aGLXWindowId)
     clear();
     RETURN (true);
 #endif
@@ -416,11 +613,12 @@
     ^ false
 !
 
-glxZClear
+glxZClearIn:aGLXWindowId
     "clear z buffer"
 
 %{  /* NOCONTEXT */
 #ifdef GLX
+    SETWIN(aGLXWindowId)
     zclear();
     RETURN (true);
 #endif
@@ -429,11 +627,12 @@
     ^ false
 !
 
-glxPushmatrix
+glxPushmatrixIn:aGLXWindowId
     "push down transformation stack"
 
 %{  /* NOCONTEXT */
 #ifdef GLX
+    SETWIN(aGLXWindowId)
     pushmatrix();
     RETURN (true);
 #endif
@@ -442,11 +641,12 @@
     ^ false
 !
 
-glxPopmatrix
+glxPopmatrixIn:aGLXWindowId
     "pop transformation stack"
 
 %{  /* NOCONTEXT */
 #ifdef GLX
+    SETWIN(aGLXWindowId)
     popmatrix();
     RETURN (true);
 #endif
@@ -455,11 +655,12 @@
     ^ false
 !
 
-glxSwapBuffers
+glxSwapBuffersIn:aGLXWindowId
     "swap double buffers"
 
 %{  /* NOCONTEXT */
 #ifdef GLX
+    SETWIN(aGLXWindowId)
     swapbuffers();
     RETURN (true);
 #endif
@@ -468,11 +669,12 @@
     ^ false
 !
 
-glxRGBmode
+glxRGBmodeIn:aGLXWindowId
     "set true color mode (no colormap)"
 
 %{  /* NOCONTEXT */
 #ifdef GLX
+    SETWIN(aGLXWindowId)
     RGBmode();
     RETURN (true);
 #endif
@@ -481,11 +683,12 @@
     ^ false
 !
 
-glxDoubleBuffer
+glxDoubleBufferIn:aGLXWindowId
     "set double buffer mode"
 
 %{  /* NOCONTEXT */
 #ifdef GLX
+    SETWIN(aGLXWindowId)
     doublebuffer();
     RETURN (true);
 #endif
@@ -494,12 +697,13 @@
     ^ false
 !
 
-glxGconfig
+glxGconfigIn:aGLXWindowId
     "must be sent after RGBmode, doubleBuffer etc. to have these
      changes really take effect. See GLX manual"
 
 %{  /* NOCONTEXT */
 #ifdef GLX
+    SETWIN(aGLXWindowId)
     gconfig();
     RETURN (true);
 #endif
@@ -508,11 +712,12 @@
     ^ false
 !
 
-glxZbuffer:aBoolean
+glxZbuffer:aBoolean in:aGLXWindowId
     "enable/disable z-buffer operation"
 
 %{  /* NOCONTEXT */
 #ifdef GLX
+    SETWIN(aGLXWindowId)
     zbuffer(aBoolean == false ? FALSE : TRUE);
     RETURN (true);
 #endif
@@ -521,7 +726,43 @@
     ^ false
 !
 
-glxMmode:aSymbol
+glxBackface:aBoolean in:aGLXWindowId
+    "enable/disable backface"
+
+%{  /* NOCONTEXT */
+#ifdef GLX
+    SETWIN(aGLXWindowId)
+    backface(aBoolean == false ? FALSE : TRUE);
+    RETURN (true);
+#endif
+%}
+.
+    ^ false
+!
+
+glxNmode:aSymbol in:aGLXWindowId
+    "set normalize mode: #auto, #normalize"
+
+    "{ Symbol: auto }"
+    "{ Symbol: normalize }"
+
+%{  /* NOCONTEXT */
+#ifdef GLX
+    if (aSymbol == _auto) {
+        nmode(NAUTO);
+        RETURN (true);
+    }
+    if (aSymbol == _normalize) {
+        nmode(NNORMALIZE);
+        RETURN (true);
+    }
+#endif
+%}
+.
+    ^ false
+!
+
+glxMmode:aSymbol in:aGLXWindowId
     "set matrix mode: #single, #viewing, #projection or #texture"
 
     "{ Symbol: single }"
@@ -553,11 +794,12 @@
     ^ false
 !
 
-glxBeginPolygon
-    "start a polygon definition"
+glxBeginPolygonIn:aGLXWindowId
+    "start a polygon"
 
 %{  /* NOCONTEXT */
 #ifdef GLX
+    SETWIN(aGLXWindowId)
     bgnpolygon();
     RETURN (true);
 #endif
@@ -566,11 +808,12 @@
     ^ false
 !
 
-glxEndPolygon
-    "end a polygon definition"
+glxEndPolygonIn:aGLXWindowId
+    "end a polygon"
 
 %{  /* NOCONTEXT */
 #ifdef GLX
+    SETWIN(aGLXWindowId)
     endpolygon();
     RETURN (true);
 #endif
@@ -579,232 +822,406 @@
     ^ false
 !
 
-glxLoadMatrix:arrayOf16Floats
-    "argument must be an array(a matrix) of 16 floats containing the
-     transformation matrix"
+glxBeginPointIn:aGLXWindowId
+    "start a point-group"
+
+%{  /* NOCONTEXT */
+#ifdef GLX
+    SETWIN(aGLXWindowId)
+    bgnpoint();
+    RETURN (true);
+#endif
+%}
+.
+    ^ false
+!
+
+glxEndPointIn:aGLXWindowId
+    "end a point group"
+
+%{  /* NOCONTEXT */
+#ifdef GLX
+    SETWIN(aGLXWindowId)
+    endpoint();
+    RETURN (true);
+#endif
+%}
+.
+    ^ false
+!
+
+glxBeginCloseLineIn:aGLXWindowId
+    "start a closed line"
+
+%{  /* NOCONTEXT */
+#ifdef GLX
+    SETWIN(aGLXWindowId)
+    bgnclosedline();
+    RETURN (true);
+#endif
+%}
+.
+    ^ false
+!
+
+glxEndClosedLineIn:aGLXWindowId
+    "end a closed line"
+
+%{  /* NOCONTEXT */
+#ifdef GLX
+    SETWIN(aGLXWindowId)
+    endclosedline();
+    RETURN (true);
+#endif
+%}
+.
+    ^ false
+!
+
+glxBeginLineIn:aGLXWindowId
+    "start a line group"
+
+%{  /* NOCONTEXT */
+#ifdef GLX
+    SETWIN(aGLXWindowId)
+    bgnline();
+    RETURN (true);
+#endif
+%}
+.
+    ^ false
+!
+
+glxEndLineIn:aGLXWindowId
+    "end a line group"
+
+%{  /* NOCONTEXT */
+#ifdef GLX
+    SETWIN(aGLXWindowId)
+    endline();
+    RETURN (true);
+#endif
+%}
+.
+    ^ false
+!
+
+glxBeginTriangleMeshIn:aGLXWindowId
+    "start a triangle mesh"
 
 %{  /* NOCONTEXT */
 #ifdef GLX
-    OBJ cls;
-    extern OBJ FloatArray, DoubleArray, Array;
-    Matrix matrix;
-    int nByte;
-    OBJ o;
+    SETWIN(aGLXWindowId)
+    bgntmesh();
+    RETURN (true);
+#endif
+%}
+.
+    ^ false
+!
 
-    cls = _Class(arrayOf16Floats);
-    nByte = _qSize(arrayOf16Floats) - OHDR_SIZE;
+glxEndTriangleMeshIn:aGLXWindowId
+    "end a triangle mesh"
 
-    do {
-        /* best speed for float array */
-        if (cls == FloatArray) {
-            int x = 0;
-            int i,j;
+%{  /* NOCONTEXT */
+#ifdef GLX
+    SETWIN(aGLXWindowId)
+    endtmesh();
+    RETURN (true);
+#endif
+%}
+.
+    ^ false
+!
 
-            if (nByte < (16 * sizeof(float))) break;
-            for (i=0; i<4; i++) {
-                for (j=0; j<4; j++) {
-                    matrix[i][j] = _FloatArrayInstPtr(arrayOf16Floats)->f_element[x];
-                    x++;
-                }
-            }
-            loadmatrix(matrix);
-            RETURN (true);
-        }
-        /* a little bit slower for double array */
-        if (cls == DoubleArray) {
-            int x = 0;
-            int i,j;
+glxBeginSurfaceIn:aGLXWindowId
+    "start a NURBS surface def"
+
+%{  /* NOCONTEXT */
+#ifdef GLX
+    SETWIN(aGLXWindowId)
+    bgnsurface();
+    RETURN (true);
+#endif
+%}
+.
+    ^ false
+!
+
+glxEndSurfaceIn:aGLXWindowId
+    "end a NURBS surface def"
+
+%{  /* NOCONTEXT */
+#ifdef GLX
+    SETWIN(aGLXWindowId)
+    endsurface();
+    RETURN (true);
+#endif
+%}
+.
+    ^ false
+!
 
-            if (nByte < (16 * sizeof(double))) break;
-            for (i=0; i<4; i++) {
-                for (j=0; j<4; j++) {
-                    matrix[i][j] = _DoubleArrayInstPtr(arrayOf16Floats)->d_element[x];
-                    x++;
-                }
-            }
-            loadmatrix(matrix);
-            RETURN (true);
-        }
-        /* a little bit slower for normal array of floats */
-        if (cls == Array) {
-            int x = 0;
-            int i,j;
+glxBeginQuadrilateralStripIn:aGLXWindowId
+    "start a quadrilateral strip"
+
+%{  /* NOCONTEXT */
+#ifdef GLX
+    SETWIN(aGLXWindowId)
+    bgnqstrip();
+    RETURN (true);
+#endif
+%}
+.
+    ^ false
+!
+
+glxEndQuadrilateralStripIn:aGLXWindowId
+    "end a quadrilateral strip"
 
-            if (nByte < (16 * sizeof(OBJ))) break;
-            /* get elements one-by-one */
-            for (i=0; i<4; i++) {
-                for (j=0; j<4; j++) {
-                    o = _ArrayInstPtr(arrayOf16Floats)->a_element[x];
-                    if (! _isFloat(o)) goto bad;
-                    matrix[i][j] = _floatVal(o);
-                    x++;
-                }
-            }
-            loadmatrix(matrix);
-            RETURN (true);
-        }
-bad: ;
-    } while(0);
+%{  /* NOCONTEXT */
+#ifdef GLX
+    SETWIN(aGLXWindowId)
+    endqstrip();
+    RETURN (true);
+#endif
+%}
+.
+    ^ false
+!
+
+glxBeginCurveIn:aGLXWindowId
+    "start a NURBS curve def"
+
+%{  /* NOCONTEXT */
+#ifdef GLX
+    SETWIN(aGLXWindowId)
+    bgncurve();
+    RETURN (true);
+#endif
+%}
+.
+    ^ false
+!
+
+glxEndCurveIn:aGLXWindowId
+    "end a NURBS curve def"
+
+%{  /* NOCONTEXT */
+#ifdef GLX
+    SETWIN(aGLXWindowId)
+    endcurve();
+    RETURN (true);
 #endif
 %}
 .
     ^ false
 !
 
-glxN3f:arrayOf3FloatsWithNormal
-    "argument must be an array of 3 floats containing the
-     current vertex normal"
+glxSphDraw:arrayOf4Floats in:aGLXWindowId
+    "argument must be an array(a matrix) of 4 floats containing the
+     sphere"
 
 %{  /* NOCONTEXT */
 #ifdef GLX
-    OBJ cls;
-    extern OBJ FloatArray, DoubleArray, Array;
-    float vector[3];
-    int nByte;
-    OBJ o;
+    float vec[4], *v;
+
+    if (! (v = getFloatsFromInto(arrayOf4Floats, vec, 4))) RETURN(false);
+    SETWIN(aGLXWindowId)
+    sphdraw(v);
+    RETURN (true);
+#endif
+%}
+.
+    ^ false
+!
 
-    cls = _Class(arrayOf3FloatsWithNormal);
-    nByte = _qSize(arrayOf3FloatsWithNormal) - OHDR_SIZE;
+glxDefBasis:id mat:aMatrix in:aGLXWindowId
+    "define the basis"
+%{  /* NOCONTEXT */
+#ifdef GLX
+    Matrix matrix;
+    Matrix *m;
+
+    if (! (m = getFloatsFromMatrixInto(aMatrix, &matrix))) RETURN (false);
+    if (_isSmallInteger(id)) {
+        SETWIN(aGLXWindowId)
+        defbasis((short)(_intVal(id)), *m);
+        RETURN (true);
+    }
+#endif
+%}
+.
+    ^ false
+!
 
-    do {
-        /* best speed for float array */
-        if (cls == FloatArray) {
-            if (nByte < (3 * sizeof(float))) break;
-            n3f(_FloatArrayInstPtr(arrayOf3FloatsWithNormal)->f_element);
-            RETURN (true);
-        }
-        /* a little bit slower for double array */
-        if (cls == DoubleArray) {
-            if (nByte < (3 * sizeof(double))) break;
-            vector[0] = _DoubleArrayInstPtr(arrayOf3FloatsWithNormal)->d_element[0];
-            vector[1] = _DoubleArrayInstPtr(arrayOf3FloatsWithNormal)->d_element[1];
-            vector[2] = _DoubleArrayInstPtr(arrayOf3FloatsWithNormal)->d_element[2];
-            n3f(vector);
-            RETURN (true);
-        }
-        /* a little bit slower for normal array of floats */
-        if (cls == Array) {
-            if (nByte < (3 * sizeof(OBJ))) break;
-            /* get elements one-by-one */
-            o = _ArrayInstPtr(arrayOf3FloatsWithNormal)->a_element[0];
-            if (! _isFloat(o)) break;
-            vector[0] = _floatVal(o);
-            o = _ArrayInstPtr(arrayOf3FloatsWithNormal)->a_element[1];
-            if (! _isFloat(o)) break;
-            vector[1] = _floatVal(o);
-            o = _ArrayInstPtr(arrayOf3FloatsWithNormal)->a_element[2];
-            if (! _isFloat(o)) break;
-            vector[2] = _floatVal(o);
-            n3f(vector);
-            RETURN (true);
-        }
-    } while(0);
+glxPatchCurvesU:u v:v in:aGLXWindowId
+    "set the number of curves in a patch"
+%{  /* NOCONTEXT */
+#ifdef GLX
+    if (_isSmallInteger(u) && _isSmallInteger(v)) {
+        SETWIN(aGLXWindowId)
+        patchcurves((long)_intVal(u), (long)_intVal(v));
+        RETURN (true);
+    }
+#endif
+%}
+.
+    ^ false
+!
+
+glxPatchPrecisionU:u v:v in:aGLXWindowId
+    "set the patch precision"
+%{  /* NOCONTEXT */
+#ifdef GLX
+    if (_isSmallInteger(u) && _isSmallInteger(v)) {
+        SETWIN(aGLXWindowId)
+        patchprecision((long)_intVal(u), (long)_intVal(v));
+        RETURN (true);
+    }
+#endif
+%}
+.
+    ^ false
+!
+
+glxPatchBasisU:u v:v in:aGLXWindowId
+    "set the current basis matrices"
+%{  /* NOCONTEXT */
+#ifdef GLX
+    if (_isSmallInteger(u) && _isSmallInteger(v)) {
+        SETWIN(aGLXWindowId)
+        patchbasis((long)_intVal(u), (long)_intVal(v));
+        RETURN (true);
+    }
+#endif
+%}
+.
+    ^ false
+!
+
+glxPatchX:arrayOf16XFloats y:arrayOf16YFloats z:arrayOf16ZFloats in:aGLXWindowId
+    "arguments must be arrays of 16 floats containing the patch"
+
+%{  /* NOCONTEXT */
+#ifdef GLX
+    Matrix matrixX, matrixY, matrixZ;
+    Matrix *mX, *mY, *mZ;
+
+    if (! (mX = getFloatsFromMatrixInto(arrayOf16XFloats, &matrixX))) RETURN (false);
+    if (! (mY = getFloatsFromMatrixInto(arrayOf16YFloats, &matrixY))) RETURN (false);
+    if (! (mZ = getFloatsFromMatrixInto(arrayOf16ZFloats, &matrixZ))) RETURN (false);
+    SETWIN(aGLXWindowId)
+    patch(*mX, *mY, *mZ);
+    RETURN (true);
 #endif
 %}
 .
     ^ false
 !
 
-glxC3f:arrayOf3FloatsWithColor
-    "argument must be an array of 3 floats containing the color"
+glxGetMatrix:arrayOf16Floats in:aGLXWindowId
+    "argument must be an array(a matrix) of 16 floats containing the
+     matrix"
 
 %{  /* NOCONTEXT */
 #ifdef GLX
-    OBJ cls;
-    extern OBJ FloatArray, DoubleArray, Array;
-    float vector[3];
-    int nByte;
-    OBJ o;
+    Matrix matrix;
 
-    cls = _Class(arrayOf3FloatsWithColor);
-    nByte = _qSize(arrayOf3FloatsWithColor) - OHDR_SIZE;
+    SETWIN(aGLXWindowId)
+    getmatrix(matrix);
+    if (! putFloatsFromInto(matrix, arrayOf16Floats, 16)) RETURN(false);
+    RETURN (true);
+#endif
+%}
+.
+    ^ false
+!
 
-    do {
-        /* best speed for float array */
-        if (cls == FloatArray) {
-            if (nByte < (3 * sizeof(float))) break;
-            c3f(_FloatArrayInstPtr(arrayOf3FloatsWithColor)->f_element);
-            RETURN (true);
-        }
-        /* a little bit slower for double array */
-        if (cls == DoubleArray) {
-            if (nByte < (3 * sizeof(double))) break;
-            vector[0] = _DoubleArrayInstPtr(arrayOf3FloatsWithColor)->d_element[0];
-            vector[1] = _DoubleArrayInstPtr(arrayOf3FloatsWithColor)->d_element[1];
-            vector[2] = _DoubleArrayInstPtr(arrayOf3FloatsWithColor)->d_element[2];
-            c3f(vector);
-            RETURN (true);
-        }
-        /* a little bit slower for normal array of floats */
-        if (cls == Array) {
-            if (nByte < (3 * sizeof(OBJ))) break;
-            /* get elements one-by-one */
-            o = _ArrayInstPtr(arrayOf3FloatsWithColor)->a_element[0];
-            if (! _isFloat(o)) break;
-            vector[0] = _floatVal(o);
-            o = _ArrayInstPtr(arrayOf3FloatsWithColor)->a_element[1];
-            if (! _isFloat(o)) break;
-            vector[1] = _floatVal(o);
-            o = _ArrayInstPtr(arrayOf3FloatsWithColor)->a_element[2];
-            if (! _isFloat(o)) break;
-            vector[2] = _floatVal(o);
-            c3f(vector);
-            RETURN (true);
-        }
-    } while(0);
+glxLoadMatrix:arrayOf16Floats in:aGLXWindowId
+    "argument must be an array(a matrix) of 16 floats containing the
+     transformation matrix"
+
+%{  /* NOCONTEXT */
+#ifdef GLX
+    Matrix matrix;
+    Matrix *m;
+
+    if (! (m = getFloatsFromMatrixInto(arrayOf16Floats, &matrix))) RETURN (false);
+    SETWIN(aGLXWindowId)
+    loadmatrix(*m);
+    RETURN (true);
 #endif
 %}
 .
     ^ false
 !
 
-glxV3f:arrayOf3FloatsWithVertex
+glxMultMatrix:arrayOf16Floats in:aGLXWindowId
+    "argument must be an array(a matrix) of 16 floats containing the
+     matrix"
+
+%{  /* NOCONTEXT */
+#ifdef GLX
+    Matrix matrix;
+    Matrix *m;
+
+    if (! (m = getFloatsFromMatrixInto(arrayOf16Floats, &matrix))) RETURN (false);
+    SETWIN(aGLXWindowId)
+    multmatrix(*m);
+    RETURN (true);
+#endif
+%}
+.
+    ^ false
+!
+
+glxN3f:arrayOf3Floats in:aGLXWindowId
+    "argument must be an array of 3 floats containing the
+     current vertex normal"
+
+%{  /* NOCONTEXT */
+#ifdef GLX
+    float vec[3], *v;
+
+    if (! (v = getFloatsFromInto(arrayOf3Floats, vec, 3))) RETURN(false);
+    SETWIN(aGLXWindowId)
+    n3f(v);
+    RETURN (true);
+#endif
+%}
+.
+    ^ false
+!
+
+glxC3f:arrayOf3Floats in:aGLXWindowId
+    "argument must be an array of 3 floats containing the color"
+
+%{  /* NOCONTEXT */
+#ifdef GLX
+    float vec[3], *v;
+
+    if (! (v = getFloatsFromInto(arrayOf3Floats, vec, 3))) RETURN(false);
+    SETWIN(aGLXWindowId)
+    c3f(v);
+    RETURN (true);
+#endif
+%}
+.
+    ^ false
+!
+
+glxV3f:arrayOf3Floats in:aGLXWindowId
     "argument must be an array of 3 floats containing the vertex"
 
 %{  /* NOCONTEXT */
 #ifdef GLX
-    OBJ cls;
-    extern OBJ FloatArray, DoubleArray, Array;
-    float vector[3];
-    int nByte;
-    OBJ o;
-
-    cls = _Class(arrayOf3FloatsWithVertex);
-    nByte = _qSize(arrayOf3FloatsWithVertex) - OHDR_SIZE;
+    float vec[3], *v;
 
-    do {
-        /* best speed for float array */
-        if (cls == FloatArray) {
-            if (nByte < (3 * sizeof(float))) break;
-            n3f(_FloatArrayInstPtr(arrayOf3FloatsWithVertex)->f_element);
-            RETURN (true);
-        }
-        /* a little bit slower for double array */
-        if (cls == DoubleArray) {
-            if (nByte < (3 * sizeof(double))) break;
-            vector[0] = _DoubleArrayInstPtr(arrayOf3FloatsWithVertex)->d_element[0];
-            vector[1] = _DoubleArrayInstPtr(arrayOf3FloatsWithVertex)->d_element[1];
-            vector[2] = _DoubleArrayInstPtr(arrayOf3FloatsWithVertex)->d_element[2];
-            n3f(vector);
-            RETURN (true);
-        }
-        /* a little bit slower for normal array of floats */
-        if (cls == Array) {
-            if (nByte < (3 * sizeof(OBJ))) break;
-            /* get elements one-by-one */
-            o = _ArrayInstPtr(arrayOf3FloatsWithVertex)->a_element[0];
-            if (! _isFloat(o)) break;
-            vector[0] = _floatVal(o);
-            o = _ArrayInstPtr(arrayOf3FloatsWithVertex)->a_element[1];
-            if (! _isFloat(o)) break;
-            vector[1] = _floatVal(o);
-            o = _ArrayInstPtr(arrayOf3FloatsWithVertex)->a_element[2];
-            if (! _isFloat(o)) break;
-            vector[2] = _floatVal(o);
-            n3f(vector);
-            RETURN (true);
-        }
-    } while(0);
+    if (! (v = getFloatsFromInto(arrayOf3Floats, vec, 3))) RETURN(false);
+    SETWIN(aGLXWindowId)
+    v3f(v);
+    RETURN (true);
 #endif
 %}
 .