GLXWorkstation.st
author claus
Sat, 08 Jan 1994 18:17:39 +0100
changeset 24 e810b1be068b
parent 20 ab35d92b9a4b
child 29 c218ef0ae2b0
permissions -rw-r--r--
*** empty log message ***

"
COPYRIGHT (c) 1993 by Claus Gittinger
              All Rights Reserved

 This software is furnished under a license and may be used
 only in accordance with the terms of that license and with the
 inclusion of the above copyright notice.   This software may not
 be provided or otherwise made available to, or used by, any
 other person.  No title to or ownership of the software is
 hereby transferred.
"

XWorkstation subclass:#GLXWorkstation
       instanceVariableNames:'activeWindow'
       classVariableNames:   ''
       poolDictionaries:''
       category:'Interface-Graphics'
!

GLXWorkstation comment:'

COPYRIGHT (c) 1993 by Claus Gittinger
              All Rights Reserved

$Header: /cvs/stx/stx/libview/GLXWorkstation.st,v 1.6 1994-01-08 17:16:42 claus Exp $
written dec 93 by claus
'!

%{
/*
 * 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

#ifdef GLX
# include <gl/glws.h>
# include <gl/sphere.h>
#else
# include <vogl.h>
# include <X11/Xlib.h>
#endif

typedef enum {
    GLXcolorIndexSingleBuffer,
    GLXcolorIndexDoubleBuffer,
    GLXrgbSingleBuffer,
    GLXrgbDoubleBuffer
} GLXWindowType;

extern Window GLXCreateWindow(Display*,Window,int,int,int,int,int,GLXWindowType);

#undef String

/*
 * some defines - tired of typing ...
 */
#define MKDPY(o)       (Display *)(_intVal(o))
#define MKWIN(o)       (Window)(_intVal(o))
#define MKGC(o)        (GC)(_intVal(o))
#define MKCURS(o)      (Cursor)(_intVal(o))
#define MKFONT(o)      (XFontStruct *)(_intVal(o))
#define MKDPSContext(o)      (DPSContext)(_intVal(o))

#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));  \
    else if (_isSmallInteger(arg))      \
        dst = (Coord)(_intVal(arg));    \
    else break;

#define _FLOAT_(arg, dst)               \
    if (_isFloat(arg))                  \
        dst = (float)(_floatVal(arg));  \
    else if (_isSmallInteger(arg))      \
        dst = (float)(_intVal(arg));    \
    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))           \
        dst = (Angle)(_intVal(arg));    \
    else break;

#define _INT_(arg, dst)                 \
    if (_isSmallInteger(arg))           \
        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;
   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:
        /*
         * 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);
            pElem += sizeof(double);
        }
        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 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;
    }
    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;
}

/*
 * helper to fetch a matrix with 16 floats from an object
 */
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)) {
                    (*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++;
            }
        }
        return mp;
    }
    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
    |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
    ].

%{
    Display *dpy = myDpy;
    int screen = _intVal(_INST(screen));
    Window newWindow, parentWindow;
    extern Window GLXCreateWindow();
    int t;

    if (_isSmallInteger(xpos) && _isSmallInteger(ypos)
     && _isSmallInteger(wwidth) && _isSmallInteger(wheight)) {
        if (_isSmallInteger(wsuperViewId)) {
            parentWindow = MKWIN(wsuperViewId);
        } else {
            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, t);

        if (! newWindow) {
            RETURN ( nil );
        }

        windowId = MKOBJ(newWindow);
    }
%}
.
    windowId notNil ifTrue:[
        self addKnownView:aView withId:windowId.
    ].
    ^ windowId
!

unlinkGLXView:aGLXWindowId
    "remove X/GLX link"
%{
    if (_isSmallInteger(aGLXWindowId))
        GLXUnlinkWindow(myDpy, MKWIN(aGLXWindowId));
%}
! !

!GLXWorkstation methodsFor:'glx access'!

glxPerspectiveFovy:fovy aspect:aspect near:near far:far in:aGLXWindowId
    "define perspective projection"

%{  /* NOCONTEXT */

    Angle a_fovy;
    Coord c_near, c_far;
    float f_aspect;

    do {
        _ANGLE_ (fovy, a_fovy);
        _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);
    } 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);
%}
.
    ^ false
!

glxTranslateX:x y:y z:z in:aGLXWindowId
    "translate current matrix"

%{  /* NOCONTEXT */

    Coord c_x, c_y, c_z;

    do {
        _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);
%}
.
    ^ false
!

glxScaleX:x y:y z:z in:aGLXWindowId
    "scale & mirror current matrix"

%{  /* NOCONTEXT */

    float f_x, f_y, f_z;

    do {
        _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);
%}
.
    ^ 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
!

glxRotate:angle axis:axis in:aGLXWindowId
    "rotate the current matrix"

    "{ Symbol: x }"
    "{ Symbol: y }"
    "{ Symbol: z }"

%{  /* NOCONTEXT */

    char c_axis;

    do {
        if (axis == _x)
            c_axis = 'x';
        else if (axis == _y)
            c_axis = 'y';
        else if (axis == _z)
            c_axis = 'z';
        else break;

        SETWIN(aGLXWindowId)
        RETURN ( doRotate(angle, c_axis) );
    } while(0);
%}
.
    ^ false
!

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 */

    Coord f_vx, f_vy, f_vz, f_px, f_py, f_pz;
    Angle a_twist;

    do {
        _COORD_ (vx, f_vx);
        _COORD_ (vy, f_vy);
        _COORD_ (vz, f_vz);
        _COORD_ (px, f_px);
        _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);
%}
.
    ^ false
!

glxLmdef:what index:index np:np props:props in:aGLXWindowId
    "define a material, light source or lighting model;
     props must be a FloatArray"

    "{ Symbol: material }"
    "{ Symbol: light }"
    "{ Symbol: lightModel }"

%{  /* NOCONTEXT */
#ifdef GLX
    short defType;
    short i_index, i_np;
    extern OBJ FloatArray;
    float *fp;

    do {
        if (what == _material)
            defType = DEFMATERIAL;
        else if (what == _light)
            defType = DEFLIGHT;
        else if (what == _lightModel)
            defType = DEFLMODEL;
        else break;

        _INT_ (index, i_index);
        _INT_ (np, i_np);

        if (props == nil) fp = NULL;
        else if (_Class(props) == FloatArray)
            fp = _FloatArrayInstPtr(props)->f_element;
        else break;

        SETWIN(aGLXWindowId)
        lmdef(defType, i_index, i_np, fp);
        RETURN (true);
    } while(0);
#endif
%}
.
    ^ false
!

glxLmbind:target index:index in:aGLXWindowId
    "select a material, lighyt or lighting model"

    "{ Symbol: material }"
    "{ Symbol: backMaterial }"
    "{ Symbol: light0 }"
    "{ Symbol: light1 }"
    "{ Symbol: light2 }"
    "{ Symbol: light3 }"
    "{ Symbol: light4 }"
    "{ Symbol: light5 }"
    "{ Symbol: light6 }"
    "{ Symbol: light7 }"
    "{ Symbol: lightModel }"

%{  /* NOCONTEXT */
#ifdef GLX
    short defType;
    short i_index;

    do {
        if (target == _material)
            defType = MATERIAL;
        else if (target == _backMaterial)
            defType = BACKMATERIAL;
        else if (target == _light0)
            defType = LIGHT0;
        else if (target == _light1)
            defType = LIGHT1;
        else if (target == _light2)
            defType = LIGHT2;
        else if (target == _light3)
            defType = LIGHT3;
        else if (target == _light4)
            defType = LIGHT4;
        else if (target == _light5)
            defType = LIGHT5;
        else if (target == _light6)
            defType = LIGHT6;
        else if (target == _light7)
            defType = LIGHT7;
        else if (target == _lightModel)
            defType = LMODEL;
        else break;

        _INT_ (index, i_index);
        SETWIN(aGLXWindowId)
        lmbind(defType, i_index);
        RETURN (true);
    } while(0);
#endif
%}
.
    ^ false
!

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."

%{  /* NOCONTEXT */

    SETWIN(aGLXWindowId)
    if (_isSmallInteger(index)) {
        color((Colorindex)(_intVal(index)));
        RETURN (true);
    }
    if (_isFloat(index)) {
        colorf((float)(_floatVal(index)));
        RETURN (true);
    }
%}
.
    ^ false
!

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 */
    SETWIN(aGLXWindowId)
    clear();
    RETURN (true);
%}
.
    ^ false
!

glxZClearIn:aGLXWindowId
    "clear z buffer"

%{  /* NOCONTEXT */
#ifdef GLX
    SETWIN(aGLXWindowId)
    zclear();
    RETURN (true);
#endif
%}
.
    ^ false
!

glxPushmatrixIn:aGLXWindowId
    "push down transformation stack"

%{  /* NOCONTEXT */
    SETWIN(aGLXWindowId)
    pushmatrix();
    RETURN (true);
%}
.
    ^ false
!

glxPopmatrixIn:aGLXWindowId
    "pop transformation stack"

%{  /* NOCONTEXT */
    SETWIN(aGLXWindowId)
    popmatrix();
    RETURN (true);
%}
.
    ^ false
!

glxSwapBuffersIn:aGLXWindowId
    "swap double buffers"

%{  /* NOCONTEXT */
    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
!

glxRGBmodeIn:aGLXWindowId
    "set true color mode (no colormap)"

%{  /* NOCONTEXT */
#ifdef GLX
    SETWIN(aGLXWindowId)
    RGBmode();
    RETURN (true);
#endif
%}
.
    ^ false
!

glxDoubleBufferIn:aGLXWindowId
    "set double buffer mode"

%{  /* NOCONTEXT */
    SETWIN(aGLXWindowId)
    doublebuffer();
    RETURN (true);
%}
.
    ^ false
!

glxGconfigIn:aGLXWindowId
    "must be sent after RGBmode, doubleBuffer etc. to have these
     changes really take effect. See GLX manual"

%{  /* NOCONTEXT */
    SETWIN(aGLXWindowId)
    gconfig();
    RETURN (true);
%}
.
    ^ false
!

glxZbuffer:aBoolean in:aGLXWindowId
    "enable/disable z-buffer operation"

%{  /* NOCONTEXT */
#ifdef GLX
    SETWIN(aGLXWindowId)
    zbuffer(aBoolean == false ? FALSE : TRUE);
    RETURN (true);
#endif
%}
.
    ^ false
!

glxBackFace:aBoolean in:aGLXWindowId
    "enable/disable backface"

%{  /* NOCONTEXT */
    SETWIN(aGLXWindowId)                                     
    backface(aBoolean == false ? FALSE : TRUE);
    RETURN (true);
%}
.
    ^ 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 }"
    "{ Symbol: viewing }"
    "{ Symbol: projection }"
    "{ Symbol: texture }"

%{  /* NOCONTEXT */
#ifdef GLX
    if (aSymbol == _single) {
        mmode(MSINGLE);
        RETURN (true);
    }
    if (aSymbol == _viewing) {
        mmode(MVIEWING);
        RETURN (true);
    }
    if (aSymbol == _projection) {
        mmode(MPROJECTION);
        RETURN (true);
    }
    if (aSymbol == _texture) {
        mmode(MTEXTURE);
        RETURN (true);
    }
#endif
%}
.
    ^ false
!

glxBeginPolygonIn:aGLXWindowId
    "start a polygon"

%{  /* NOCONTEXT */
    SETWIN(aGLXWindowId)
    bgnpolygon();
    RETURN (true);
%}
.
    ^ false
!

glxEndPolygonIn:aGLXWindowId
    "end a polygon"

%{  /* NOCONTEXT */
    SETWIN(aGLXWindowId)
    endpolygon();
    RETURN (true);
%}
.
    ^ false
!

glxBeginPointIn:aGLXWindowId
    "start a point-group"

%{  /* NOCONTEXT */
    SETWIN(aGLXWindowId)
    bgnpoint();
    RETURN (true);
%}
.
    ^ false
!

glxEndPointIn:aGLXWindowId
    "end a point group"

%{  /* NOCONTEXT */
    SETWIN(aGLXWindowId)
    endpoint();
    RETURN (true);
%}
.
    ^ false
!

glxBeginClosedLineIn:aGLXWindowId
    "start a closed line"

%{  /* NOCONTEXT */
    SETWIN(aGLXWindowId)
    bgnclosedline();
    RETURN (true);
%}
.
    ^ false
!

glxEndClosedLineIn:aGLXWindowId
    "end a closed line"

%{  /* NOCONTEXT */
    SETWIN(aGLXWindowId)
    endclosedline();
    RETURN (true);
%}
.
    ^ false
!

glxBeginLineIn:aGLXWindowId
    "start a line group"

%{  /* NOCONTEXT */
    SETWIN(aGLXWindowId)
    bgnline();
    RETURN (true);
%}
.
    ^ false
!

glxEndLineIn:aGLXWindowId
    "end a line group"

%{  /* NOCONTEXT */
    SETWIN(aGLXWindowId)
    endline();
    RETURN (true);
%}
.
    ^ false
!

glxBeginTriangleMeshIn:aGLXWindowId
    "start a triangle mesh"

%{  /* NOCONTEXT */
    SETWIN(aGLXWindowId)
    bgntmesh();
    RETURN (true);
%}
.
    ^ false
!

glxEndTriangleMeshIn:aGLXWindowId
    "end a triangle mesh"

%{  /* NOCONTEXT */
    SETWIN(aGLXWindowId)
    endtmesh();
    RETURN (true);
%}
.
    ^ false
!

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
!

glxBeginQuadrilateralStripIn:aGLXWindowId
    "start a quadrilateral strip"

%{  /* NOCONTEXT */
    SETWIN(aGLXWindowId)
    bgnqstrip();
    RETURN (true);
%}
.
    ^ false
!

glxEndQuadrilateralStripIn:aGLXWindowId
    "end a quadrilateral strip"

%{  /* NOCONTEXT */
    SETWIN(aGLXWindowId)
    endqstrip();
    RETURN (true);
%}
.
    ^ 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
!

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"

%{  /* NOCONTEXT */
#ifdef GLX
    float vec[4], *v;

    if (! (v = getFloatsFromInto(arrayOf4Floats, vec, 4))) RETURN(false);
    SETWIN(aGLXWindowId)
    sphdraw(v);
    RETURN (true);
#endif
%}
.
    ^ false
!

glxDefBasis:id mat:aMatrix in:aGLXWindowId
    "define the basis"

%{  /* NOCONTEXT */
    Matrix matrix;
    Matrix *m;

    if (! (m = getFloatsFromMatrixInto(aMatrix, &matrix))) RETURN (false);
    if (_isSmallInteger(id)) {
        SETWIN(aGLXWindowId)
        defbasis((short)(_intVal(id)), *m);
        RETURN (true);
    }
%}
.
    ^ false
!

glxPatchCurvesU:u v:v in:aGLXWindowId
    "set the number of curves in a patch"

%{  /* NOCONTEXT */
    if (_isSmallInteger(u) && _isSmallInteger(v)) {
        SETWIN(aGLXWindowId)
        patchcurves((long)_intVal(u), (long)_intVal(v));
        RETURN (true);
    }
%}
.
    ^ false
!

glxPatchPrecisionU:u v:v in:aGLXWindowId
    "set the patch precision"

%{  /* NOCONTEXT */
    if (_isSmallInteger(u) && _isSmallInteger(v)) {
        SETWIN(aGLXWindowId)
        patchprecision((long)_intVal(u), (long)_intVal(v));
        RETURN (true);
    }
%}
.
    ^ false
!

glxPatchBasisU:u v:v in:aGLXWindowId
    "set the current basis matrices"

%{  /* NOCONTEXT */
    if (_isSmallInteger(u) && _isSmallInteger(v)) {
        SETWIN(aGLXWindowId)
        patchbasis((long)_intVal(u), (long)_intVal(v));
        RETURN (true);
    }
%}
.
    ^ false
!

glxPatchX:arrayOf16XFloats y:arrayOf16YFloats z:arrayOf16ZFloats in:aGLXWindowId
    "arguments must be arrays of 16 floats containing the patch"

%{  /* NOCONTEXT */
    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);
%}
.
    ^ false
!

glxGetMatrix:arrayOf16Floats in:aGLXWindowId
    "argument must be an array(a matrix) of 16 floats containing the
     matrix"

%{  /* NOCONTEXT */
    Matrix matrix;

    SETWIN(aGLXWindowId)
    getmatrix(matrix);
    if (! putFloatsFromInto(matrix, arrayOf16Floats, 16)) RETURN(false);
    RETURN (true);
%}
.
    ^ false
!

glxLoadMatrix:arrayOf16Floats in:aGLXWindowId
    "argument must be an array(a matrix) of 16 floats containing the
     transformation matrix"

%{  /* NOCONTEXT */
    Matrix matrix;
    Matrix *m;

    if (! (m = getFloatsFromMatrixInto(arrayOf16Floats, &matrix))) RETURN (false);
    SETWIN(aGLXWindowId)
    loadmatrix(*m);
    RETURN (true);
%}
.
    ^ false
!

glxMultMatrix:arrayOf16Floats in:aGLXWindowId
    "argument must be an array(a matrix) of 16 floats containing the
     matrix"

%{  /* NOCONTEXT */
    Matrix matrix;
    Matrix *m;

    if (! (m = getFloatsFromMatrixInto(arrayOf16Floats, &matrix))) RETURN (false);
    SETWIN(aGLXWindowId)
    multmatrix(*m);
    RETURN (true);
%}
.
    ^ 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 indexable object with 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 indexable object with 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 indexable object with 3 floats,
     containing the vertex"

%{  /* NOCONTEXT */
    float vec[3], *v;

    if (! (v = getFloatsFromInto(arrayOf3Floats, vec, 3))) RETURN(false);
    SETWIN(aGLXWindowId)
    v3f(v);
    RETURN (true);
%}
.
    ^ false
! !