GLXWorkstation.st
changeset 24 e810b1be068b
parent 20 ab35d92b9a4b
child 29 c218ef0ae2b0
--- a/GLXWorkstation.st	Sat Jan 08 18:12:58 1994 +0100
+++ b/GLXWorkstation.st	Sat Jan 08 18:17:39 1994 +0100
@@ -22,21 +22,27 @@
 COPYRIGHT (c) 1993 by Claus Gittinger
               All Rights Reserved
 
-this class just to give a hint of what could be ...
-
-$Header: /cvs/stx/stx/libview/GLXWorkstation.st,v 1.5 1993-12-19 23:42:20 claus Exp $
-written june 93 by claus
+$Header: /cvs/stx/stx/libview/GLXWorkstation.st,v 1.6 1994-01-08 17:16:42 claus Exp $
+written dec 93 by claus
 '!
 
 %{
-#ifdef GLX
-
+/*
+ * on SGI, this class is compiled with -DGLX, while
+ * for simulation, this is compiled with -DVGL
+ */
 /*
  * this is stupid, GLX defines String, which is also defined here ...
  */
-# define String GLX_String
+#define String GLX_String
+
+#ifdef GLX
 # include <gl/glws.h>
 # include <gl/sphere.h>
+#else
+# include <vogl.h>
+# include <X11/Xlib.h>
+#endif
 
 typedef enum {
     GLXcolorIndexSingleBuffer,
@@ -46,10 +52,9 @@
 } GLXWindowType;
 
 extern Window GLXCreateWindow(Display*,Window,int,int,int,int,int,GLXWindowType);
+
 #undef String
 
-#endif
-
 /*
  * some defines - tired of typing ...
  */
@@ -82,7 +87,14 @@
         dst = (float)(_floatVal(arg));  \
     else if (_isSmallInteger(arg))      \
         dst = (float)(_intVal(arg));    \
-    else break;
+    else if (_isFraction(arg)             \
+          && _isSmallInteger(_FractionInstPtr(arg)->f_numerator)      \
+          && _isSmallInteger(_FractionInstPtr(arg)->f_denominator)) { \
+        float n, d;                                                   \
+        n = (float)(_intVal(_FractionInstPtr(arg)->f_numerator));     \
+        d = (float)(_intVal(_FractionInstPtr(arg)->f_denominator));   \
+        dst = n / d;                                                  \
+    } else break;
 
 #define _ANGLE_(arg, dst)               \
     if (_isSmallInteger(arg))           \
@@ -94,6 +106,14 @@
         dst = (int)(_intVal(arg));      \
     else break;
 
+/*
+ * helper to fetch count floats from the object obj
+ * space is provided in vec.
+ * returns a pointer to the floats,
+ * which is obj itself, if it is a FloatArray
+ * the object may be a FloatArray, DoubleArray or an array of
+ * floats/smallintegers
+ */
 static float *
 getFloatsFromInto(obj, vec, count)
    OBJ obj;
@@ -115,11 +135,17 @@
 
     switch (_intVal(_ClassInstPtr(cls)->c_flags) & ARRAYMASK) {
       case FLOATARRAY:
-        /* best speed for float array - the data is already as we want it */
+        /* 
+         * 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:
+        /*
+         * for double array, have to copy-and-cast
+         */
         if (nByte < (count * sizeof(double))) return (float *)0;
         for (i=0; i<count; i++) {
             vec[i] = *((double *)pElem);
@@ -128,13 +154,28 @@
         return vec;
 
       case POINTERARRAY:
+        /*
+         * for other array, have to fetch, check and store
+         * the elements can be floats, smallintegers or fractions
+         */
         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;
+            if (_isFloat(o)) {
+                vec[i] = _floatVal(o);
+            } else if (_isSmallInteger(o)) {
+                vec[i] = (float)(_intVal(o));
+            } else if (_isFraction(o) 
+                    && _isSmallInteger(_FractionInstPtr(o)->f_numerator)
+                    && _isSmallInteger(_FractionInstPtr(o)->f_denominator)) {
+                float n, d;
+
+                n = (float)(_intVal(_FractionInstPtr(o)->f_numerator));
+                d = (float)(_intVal(_FractionInstPtr(o)->f_denominator));
+                vec[i] = n / d;
+            } else 
+                return 0;
             pElem += sizeof(OBJ);
         }
         return vec;
@@ -183,6 +224,9 @@
     return 0;
 }
 
+/*
+ * helper to fetch a matrix with 16 floats from an object
+ */
 static Matrix*
 getFloatsFromMatrixInto(obj, mp)
     OBJ obj;
@@ -229,8 +273,21 @@
         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);
+                if (_isFloat(o)) {
+                    (*mp)[i][j] = _floatVal(o);
+                } else if (_isSmallInteger(o)) {
+                    (*mp)[i][j] = (float)(_intVal(o));
+                } else if (_isFraction(o) 
+                        && _isSmallInteger(_FractionInstPtr(o)->f_numerator)
+                        && _isSmallInteger(_FractionInstPtr(o)->f_denominator)) {
+                    float n, d;
+
+                    n = (float)(_intVal(_FractionInstPtr(o)->f_numerator));
+                    d = (float)(_intVal(_FractionInstPtr(o)->f_denominator));
+                    (*mp)[i][j] = n / d;
+                } else {
+                    return (Matrix *)0;
+                }
                 x++;
             }
         }
@@ -239,8 +296,60 @@
     return (Matrix *)0;
 }
 
+/*
+ * helper for rotation
+ */
+static OBJ
+doRotate(angle, axis)
+    OBJ angle;
+    char axis;
+{
+    Angle a_angle;
+    float f_angle;
+
+    if (_isFloat(angle)) {
+        f_angle = (float)(_floatVal(angle));
+        rot(f_angle, axis);
+        return (true);
+    }
+    if (_isFraction(angle)
+     && _isSmallInteger(_FractionInstPtr(angle)->f_numerator)
+     && _isSmallInteger(_FractionInstPtr(angle)->f_denominator)) {
+        float n, d;
+
+        n = (float)(_intVal(_FractionInstPtr(angle)->f_numerator));
+        d = (float)(_intVal(_FractionInstPtr(angle)->f_denominator));
+        f_angle = n / d;
+        rot(f_angle, axis);
+        return (true);
+    }
+    if (_isSmallInteger(angle)) {
+        a_angle = (Angle)(_intVal(angle));
+        rotate(a_angle, axis);
+        return (true);
+    }
+    return false;
+}
+
 %}
 
+!GLXWorkstation methodsFor:'queries'!
+
+supportsRGB
+    "return true, if this gl workstation supports rgb
+     (in addition to indexed) colors."
+
+%{  /* NOCONTEXT */
+
+#ifdef VGL
+    RETURN ( false );
+#endif
+#ifdef GLX
+    RETURN ( true );
+#endif
+%}
+! !
+
 !GLXWorkstation methodsFor:'window creation'!
 
 createGLXWindowFor:aView left:xpos top:ypos width:wwidth height:wheight type:glxType
@@ -261,7 +370,6 @@
     ].
 
 %{
-#ifdef GLX
     Display *dpy = myDpy;
     int screen = _intVal(_INST(screen));
     Window newWindow, parentWindow;
@@ -299,7 +407,6 @@
 
         windowId = MKOBJ(newWindow);
     }
-#endif
 %}
 .
     windowId notNil ifTrue:[
@@ -316,22 +423,13 @@
 %}
 ! !
 
-!GLXWorkstation methodsFor:'queries'!
-
-supportsRGB
-    ^ true
-! !
-
 !GLXWorkstation methodsFor:'glx access'!
 
-glxPerspectiveFovy:fovy aspect:aspect 
-              near:near far:far
-                in:aGLXWindowId
+glxPerspectiveFovy:fovy aspect:aspect near:near far:far in:aGLXWindowId
     "define perspective projection"
 
 %{  /* NOCONTEXT */
 
-#ifdef GLX
     Angle a_fovy;
     Coord c_near, c_far;
     float f_aspect;
@@ -343,10 +441,31 @@
         _COORD_ (far, c_far);
         SETWIN(aGLXWindowId)
         perspective(a_fovy, f_aspect, c_near, c_far);
+        RETURN (true);
+    } while(0);
+%}
+.
+    ^ false
+!
+
+glxWindowLeft:left right:right top:top bottom:bottom near:near far:far in:aGLXWindowId
+    "define perspective viewing pyramid"
+
+%{  /* NOCONTEXT */
+    Coord c_left, c_right, c_top, c_bot, c_near, c_far;
+
+    do {
+        _COORD_ (left, c_left);
+        _COORD_ (right, c_right);
+        _COORD_ (top, c_top);
+        _COORD_ (bottom, c_bot);
+        _COORD_ (near, c_near);
+        _COORD_ (far, c_far);
+        SETWIN(aGLXWindowId)
+        window(c_left, c_right, c_bot, c_top, c_near, c_far);
 
         RETURN (true);
     } while(0);
-#endif
 %}
 .
     ^ false
@@ -357,7 +476,6 @@
 
 %{  /* NOCONTEXT */
 
-#ifdef GLX
     Coord c_x, c_y, c_z;
 
     do {
@@ -368,7 +486,6 @@
         translate(c_x, c_y, c_z);
         RETURN (true);
     } while(0);
-#endif
 %}
 .
     ^ false
@@ -379,7 +496,6 @@
 
 %{  /* NOCONTEXT */
 
-#ifdef GLX
     float f_x, f_y, f_z;
 
     do {
@@ -390,7 +506,42 @@
         scale(f_x, f_y, f_z);
         RETURN (true);
     } while(0);
-#endif
+%}
+.
+    ^ false
+!
+
+glxRotateX:angle in:aGLXWindowId
+    "rotate the current matrix on x axis"
+
+%{  /* NOCONTEXT */
+
+    SETWIN(aGLXWindowId)
+    RETURN (doRotate(angle, 'x'));
+%}
+.
+    ^ false
+!
+
+glxRotateY:angle in:aGLXWindowId
+    "rotate the current matrix on y axis"
+
+%{  /* NOCONTEXT */
+
+    SETWIN(aGLXWindowId)
+    RETURN (doRotate(angle, 'y'));
+%}
+.
+    ^ false
+!
+
+glxRotateZ:angle in:aGLXWindowId
+    "rotate the current matrix on z axis"
+
+%{  /* NOCONTEXT */
+
+    SETWIN(aGLXWindowId)
+    RETURN (doRotate(angle, 'z'));
 %}
 .
     ^ false
@@ -405,9 +556,6 @@
 
 %{  /* NOCONTEXT */
 
-#ifdef GLX
-    Angle a_angle;
-    float f_angle;
     char c_axis;
 
     do {
@@ -420,33 +568,34 @@
         else break;
 
         SETWIN(aGLXWindowId)
-        if (_isFloat(angle)) {
-            f_angle = (float)(_floatVal(angle));
-            rot(f_angle, c_axis);
-            RETURN (true);
-        } else {
-            if (_isSmallInteger(angle)) {
-                a_angle = (Angle)(_intVal(angle));
-                rotate(a_angle, c_axis);
-                RETURN (true);
-            }
-        }
+        RETURN ( doRotate(angle, c_axis) );
     } while(0);
-#endif
 %}
 .
     ^ false
 !
 
-glxLookatVx:vx vy:vy vz:vz 
-         px:px py:py pz:pz 
-      twist:twist
-         in:aGLXWindowId
+glxRotateX:xAngle y:yAngle z:zAngle in:aGLXWindowId
+    "rotate the current matrix on all axis"
+
+%{  /* NOCONTEXT */
+
+    SETWIN(aGLXWindowId)
+    if ( doRotate(xAngle, 'x') == true) {
+        if ( doRotate(yAngle, 'y') == true) {
+            RETURN (doRotate(zAngle, 'z'));
+        }
+    }
+%}
+.
+    ^ false
+!
+
+glxLookatVx:vx vy:vy vz:vz px:px py:py pz:pz twist:twist in:aGLXWindowId
     "define viewing transformation"
 
 %{  /* NOCONTEXT */
 
-#ifdef GLX
     Coord f_vx, f_vy, f_vz, f_px, f_py, f_pz;
     Angle a_twist;
 
@@ -462,7 +611,6 @@
         lookat(f_vx, f_vy, f_vz, f_px, f_py, f_pz, a_twist);
         RETURN (true);
     } while(0);
-#endif
 %}
 .
     ^ false
@@ -573,7 +721,6 @@
 
 %{  /* NOCONTEXT */
 
-#ifdef GLX
     SETWIN(aGLXWindowId)
     if (_isSmallInteger(index)) {
         color((Colorindex)(_intVal(index)));
@@ -583,7 +730,6 @@
         colorf((float)(_floatVal(index)));
         RETURN (true);
     }
-#endif
 %}
 .
     ^ false
@@ -593,7 +739,6 @@
     "set color, args must be integer values"
 
 %{  /* NOCONTEXT */
-
 #ifdef GLX
     short s_r, s_g, s_b;
 
@@ -615,11 +760,9 @@
     "clear to current color"
 
 %{  /* NOCONTEXT */
-#ifdef GLX
     SETWIN(aGLXWindowId)
     clear();
     RETURN (true);
-#endif
 %}
 .
     ^ false
@@ -643,11 +786,9 @@
     "push down transformation stack"
 
 %{  /* NOCONTEXT */
-#ifdef GLX
     SETWIN(aGLXWindowId)
     pushmatrix();
     RETURN (true);
-#endif
 %}
 .
     ^ false
@@ -657,11 +798,9 @@
     "pop transformation stack"
 
 %{  /* NOCONTEXT */
-#ifdef GLX
     SETWIN(aGLXWindowId)
     popmatrix();
     RETURN (true);
-#endif
 %}
 .
     ^ false
@@ -671,11 +810,39 @@
     "swap double buffers"
 
 %{  /* NOCONTEXT */
-#ifdef GLX
     SETWIN(aGLXWindowId)
     swapbuffers();
     RETURN (true);
+%}
+.
+    ^ false
+!
+
+glxFrontBufferIn:aGLXWindowId
+    "switch to front buffer"
+
+%{  /* NOCONTEXT */
+    SETWIN(aGLXWindowId)
+#ifdef GLX
+    backbuffer(FALSE);
 #endif
+    frontbuffer(TRUE);
+    RETURN (true);
+%}
+.
+    ^ false
+!
+
+glxBackBufferIn:aGLXWindowId
+    "switch to back buffer"
+
+%{  /* NOCONTEXT */
+    SETWIN(aGLXWindowId)
+#ifdef GLX
+    frontbuffer(FALSE);
+#endif
+    backbuffer(TRUE);
+    RETURN (true);
 %}
 .
     ^ false
@@ -699,11 +866,9 @@
     "set double buffer mode"
 
 %{  /* NOCONTEXT */
-#ifdef GLX
     SETWIN(aGLXWindowId)
     doublebuffer();
     RETURN (true);
-#endif
 %}
 .
     ^ false
@@ -714,11 +879,9 @@
      changes really take effect. See GLX manual"
 
 %{  /* NOCONTEXT */
-#ifdef GLX
     SETWIN(aGLXWindowId)
     gconfig();
     RETURN (true);
-#endif
 %}
 .
     ^ false
@@ -738,15 +901,13 @@
     ^ false
 !
 
-glxBackface:aBoolean in:aGLXWindowId
+glxBackFace:aBoolean in:aGLXWindowId
     "enable/disable backface"
 
 %{  /* NOCONTEXT */
-#ifdef GLX
-    SETWIN(aGLXWindowId)
+    SETWIN(aGLXWindowId)                                     
     backface(aBoolean == false ? FALSE : TRUE);
     RETURN (true);
-#endif
 %}
 .
     ^ false
@@ -810,11 +971,9 @@
     "start a polygon"
 
 %{  /* NOCONTEXT */
-#ifdef GLX
     SETWIN(aGLXWindowId)
     bgnpolygon();
     RETURN (true);
-#endif
 %}
 .
     ^ false
@@ -824,11 +983,9 @@
     "end a polygon"
 
 %{  /* NOCONTEXT */
-#ifdef GLX
     SETWIN(aGLXWindowId)
     endpolygon();
     RETURN (true);
-#endif
 %}
 .
     ^ false
@@ -838,11 +995,9 @@
     "start a point-group"
 
 %{  /* NOCONTEXT */
-#ifdef GLX
     SETWIN(aGLXWindowId)
     bgnpoint();
     RETURN (true);
-#endif
 %}
 .
     ^ false
@@ -852,25 +1007,21 @@
     "end a point group"
 
 %{  /* NOCONTEXT */
-#ifdef GLX
     SETWIN(aGLXWindowId)
     endpoint();
     RETURN (true);
-#endif
 %}
 .
     ^ false
 !
 
-glxBeginCloseLineIn:aGLXWindowId
+glxBeginClosedLineIn:aGLXWindowId
     "start a closed line"
 
 %{  /* NOCONTEXT */
-#ifdef GLX
     SETWIN(aGLXWindowId)
     bgnclosedline();
     RETURN (true);
-#endif
 %}
 .
     ^ false
@@ -880,11 +1031,9 @@
     "end a closed line"
 
 %{  /* NOCONTEXT */
-#ifdef GLX
     SETWIN(aGLXWindowId)
     endclosedline();
     RETURN (true);
-#endif
 %}
 .
     ^ false
@@ -894,11 +1043,9 @@
     "start a line group"
 
 %{  /* NOCONTEXT */
-#ifdef GLX
     SETWIN(aGLXWindowId)
     bgnline();
     RETURN (true);
-#endif
 %}
 .
     ^ false
@@ -908,11 +1055,9 @@
     "end a line group"
 
 %{  /* NOCONTEXT */
-#ifdef GLX
     SETWIN(aGLXWindowId)
     endline();
     RETURN (true);
-#endif
 %}
 .
     ^ false
@@ -922,11 +1067,9 @@
     "start a triangle mesh"
 
 %{  /* NOCONTEXT */
-#ifdef GLX
     SETWIN(aGLXWindowId)
     bgntmesh();
     RETURN (true);
-#endif
 %}
 .
     ^ false
@@ -936,11 +1079,9 @@
     "end a triangle mesh"
 
 %{  /* NOCONTEXT */
-#ifdef GLX
     SETWIN(aGLXWindowId)
     endtmesh();
     RETURN (true);
-#endif
 %}
 .
     ^ false
@@ -978,11 +1119,9 @@
     "start a quadrilateral strip"
 
 %{  /* NOCONTEXT */
-#ifdef GLX
     SETWIN(aGLXWindowId)
     bgnqstrip();
     RETURN (true);
-#endif
 %}
 .
     ^ false
@@ -992,11 +1131,9 @@
     "end a quadrilateral strip"
 
 %{  /* NOCONTEXT */
-#ifdef GLX
     SETWIN(aGLXWindowId)
     endqstrip();
     RETURN (true);
-#endif
 %}
 .
     ^ false
@@ -1030,6 +1167,97 @@
     ^ false
 !
 
+glxMoveX:x y:y z:z in:aGLXWindowId
+    "arguments must specify a point"
+
+%{  /* NOCONTEXT */
+    if (_isFloat(x) && _isFloat(y) && _isFloat(z)) {
+        SETWIN(aGLXWindowId)                                     
+        move( (float)_floatVal(x), (float)_floatVal(y), (float)_floatVal(z) );
+        RETURN (true);
+    }
+%}
+.
+    ^ false
+!
+
+glxMove:arrayOf3Floats in:aGLXWindowId
+    "argument must be an array of 3 floats containing the point"
+
+%{  /* NOCONTEXT */
+    float vec[3], *v;
+
+    if (! (v = getFloatsFromInto(arrayOf3Floats, vec, 3))) RETURN(false);
+    SETWIN(aGLXWindowId)
+    move( v[0], v[1], v[2] );
+    RETURN (true);
+%}
+.
+    ^ false
+!
+
+glxDrawX:x y:y z:z in:aGLXWindowId
+    "arguments must specify a point"
+
+%{  /* NOCONTEXT */
+
+    if (_isFloat(x) && _isFloat(y) && _isFloat(z)) {
+        SETWIN(aGLXWindowId)                                     
+        draw( (float)_floatVal(x), (float)_floatVal(y), (float)_floatVal(z) );
+        RETURN (true);
+    }
+%}
+.
+    ^ false
+!
+
+glxDraw:arrayOf3Floats in:aGLXWindowId
+    "argument must be an array of 3 floats containing the point"
+
+%{  /* NOCONTEXT */
+    float vec[3], *v;
+
+    if (! (v = getFloatsFromInto(arrayOf3Floats, vec, 3))) RETURN(false);
+    SETWIN(aGLXWindowId)
+    draw( v[0], v[1], v[2]);
+    RETURN (true);
+%}
+.
+    ^ false
+!
+
+glxRectX1:x1 y1:y1 x2:x2 y2:y2 in:aGLXWindowId
+    "arguments must specify 2 opposite corners of the rectangle"
+
+%{  /* NOCONTEXT */
+    float f_x1, f_x2, f_y1, f_y2;
+
+    if (_isFloat(x1) && _isFloat(x2) && _isFloat(y1) && _isFloat(y2)) {
+        SETWIN(aGLXWindowId)                                     
+        rect( (float)_floatVal(x1), (float)_floatVal(y1), (float)_floatVal(x2), (float)_floatVal(y2) );
+        RETURN (true);
+    }
+%}
+.
+    ^ false
+!
+
+glxRectFX1:x1 y1:y1 x2:x2 y2:y2 in:aGLXWindowId
+    "arguments must specify 2 opposite corners of the filled rectangle"
+
+%{  /* NOCONTEXT */
+    float f_x1, f_x2, f_y1, f_y2;
+
+    if (_isFloat(x1) && _isFloat(x2) && _isFloat(y1) && _isFloat(y2)) {
+        SETWIN(aGLXWindowId)                                     
+        rectf( (float)_floatVal(x1), (float)_floatVal(y1), (float)_floatVal(x2), (float)_floatVal(y2) );
+        RETURN (true);
+    }
+%}
+.
+    ^ false
+!
+
 glxSphDraw:arrayOf4Floats in:aGLXWindowId
     "argument must be an array(a matrix) of 4 floats containing the
      sphere"
@@ -1050,8 +1278,8 @@
 
 glxDefBasis:id mat:aMatrix in:aGLXWindowId
     "define the basis"
+
 %{  /* NOCONTEXT */
-#ifdef GLX
     Matrix matrix;
     Matrix *m;
 
@@ -1061,7 +1289,6 @@
         defbasis((short)(_intVal(id)), *m);
         RETURN (true);
     }
-#endif
 %}
 .
     ^ false
@@ -1069,14 +1296,13 @@
 
 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
@@ -1084,14 +1310,13 @@
 
 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
@@ -1099,14 +1324,13 @@
 
 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
@@ -1116,7 +1340,6 @@
     "arguments must be arrays of 16 floats containing the patch"
 
 %{  /* NOCONTEXT */
-#ifdef GLX
     Matrix matrixX, matrixY, matrixZ;
     Matrix *mX, *mY, *mZ;
 
@@ -1126,7 +1349,6 @@
     SETWIN(aGLXWindowId)
     patch(*mX, *mY, *mZ);
     RETURN (true);
-#endif
 %}
 .
     ^ false
@@ -1137,14 +1359,12 @@
      matrix"
 
 %{  /* NOCONTEXT */
-#ifdef GLX
     Matrix matrix;
 
     SETWIN(aGLXWindowId)
     getmatrix(matrix);
     if (! putFloatsFromInto(matrix, arrayOf16Floats, 16)) RETURN(false);
     RETURN (true);
-#endif
 %}
 .
     ^ false
@@ -1155,7 +1375,6 @@
      transformation matrix"
 
 %{  /* NOCONTEXT */
-#ifdef GLX
     Matrix matrix;
     Matrix *m;
 
@@ -1163,7 +1382,6 @@
     SETWIN(aGLXWindowId)
     loadmatrix(*m);
     RETURN (true);
-#endif
 %}
 .
     ^ false
@@ -1174,7 +1392,6 @@
      matrix"
 
 %{  /* NOCONTEXT */
-#ifdef GLX
     Matrix matrix;
     Matrix *m;
 
@@ -1182,15 +1399,57 @@
     SETWIN(aGLXWindowId)
     multmatrix(*m);
     RETURN (true);
-#endif
+%}
+.
+    ^ false
+!
+
+glxMakeObject:id in:aGLXWindowId
+    "start object definition"
+
+%{  /* NOCONTEXT */
+
+    if (_isSmallInteger(id)) {
+        SETWIN(aGLXWindowId)
+        makeobj(_intVal(id));
+        RETURN (true);
+    }
 %}
 .
     ^ false
 !
 
+glxCloseObjectIn:aGLXWindowId
+    "end object defnition"
+
+%{  /* NOCONTEXT */
+
+    SETWIN(aGLXWindowId)
+    closeobj();
+    RETURN (true);
+%}
+.
+    ^ false
+!
+
+glxCallObject:id in:aGLXWindowId
+    "do objects definition"
+
+%{  /* NOCONTEXT */
+
+    if (_isSmallInteger(id)) {
+        SETWIN(aGLXWindowId)
+        callobj(_intVal(id));
+        RETURN (true);
+    }
+%}
+.
+    ^ false
+!
+ 
 glxN3f:arrayOf3Floats in:aGLXWindowId
-    "argument must be an array of 3 floats containing the
-     current vertex normal"
+    "argument must be an indexable object with 3 floats,
+     containing the current vertex normal"
 
 %{  /* NOCONTEXT */
 #ifdef GLX
@@ -1207,7 +1466,8 @@
 !
 
 glxC3f:arrayOf3Floats in:aGLXWindowId
-    "argument must be an array of 3 floats containing the color"
+    "argument must be an indexable object with 3 floats,
+     containing the color"
 
 %{  /* NOCONTEXT */
 #ifdef GLX
@@ -1224,17 +1484,16 @@
 !
 
 glxV3f:arrayOf3Floats in:aGLXWindowId
-    "argument must be an array of 3 floats containing the vertex"
+    "argument must be an indexable object with 3 floats,
+     containing the vertex"
 
 %{  /* NOCONTEXT */
-#ifdef GLX
     float vec[3], *v;
 
     if (! (v = getFloatsFromInto(arrayOf3Floats, vec, 3))) RETURN(false);
     SETWIN(aGLXWindowId)
     v3f(v);
     RETURN (true);
-#endif
 %}
 .
     ^ false