/***********************************************************************/        /***********************************************************************/
/* FreeVR OpenGL tutorial example 14f: ex14f_pushbut.c                 */        /* FreeVR OpenGL tutorial example 15: ex15_control.c                   */
/* Last tested with: FreeVR version 0.6a                               */        /* Last tested with: FreeVR version 0.6a                               */
/* Last Modified: January 11, 2007                                     */        /* Last Modified: July 19, 2004                                        */
/* URL: http://freevr.org                                              */        /* URL: http://freevr.org                                              */
/***********************************************************************/        /***********************************************************************/
/* This example code demonstrates a VR application program that        */        /* This example code demonstrates a VR application program that        */
/*   allows the user to use special objects in the virtual world.      */        /*   allows the user to control the location of the blue box using     */
/*   Specifically, this example introduces a button widget that behaves*/        /*   different types of control mechanisms.  Specifically, it shows    */
/*   a little differently than the toggle button in that it only gives */        /*   how to use: direct, physical, virtual and agent methods of        */
/*   a value of one when it is being touched, and goes immediately back*/        /*   control.                                                          */
/*   to zero when not touched -- this is similar to the snapback option*/        /*                                                                     */
/*   for the lever and joystick.                                       */        /*   Direct control: make contact and left-press to grab object        */
                                                                                 /*   Physical control: left/right-press to select, joystick to move    */
                                                                                 /*   Virtual control: radio button to select, virtual joystick to move */
                                                                                 /*         - radio buttons -- select an object (or none)               */
                                                                                 /*         - joystick -- move object in x/z plane                      */ 
                                                                                 /*   Agent control: text/voice commands to select and move             */
                                                                                 /*         - control? -- report which method of control is active      */
                                                                                 /*         - control <0..3> -- set the active method of control        */
                                                                                 /*         - object? -- report which object is selected                */
                                                                                 /*         - object <num> -- select object <num>                       */
                                                                                 /*         - up <dist> -- move selected object up distance <dist>      */
                                                                                 /*         - down <dist> -- move selected object down distance <dist>  */
                                                                                 /*         - left <dist> -- move selected object left distance <dist>  */
                                                                                 /*         - right <dist> -- move selected object right distance <dist>*/
                                                                                 /*         - in <dist> -- move selected object in distance <dist>      */
                                                                                 /*         - out <dist> -- move selected object out distance <dist>    */
/*                                                                     */        /*                                                                     */
/*                                                                     */        /*                                                                     */
/* The new features of this example include:                           */        /* The new features of this example include:                           */
/*   - nothing new provided by the library.                            */        /*   - nothing new provided by the library.                            */
/*                                                                     */        /*                                                                     */
/* Considerations:                                                     */        /* Considerations:                                                     */
                                                                                 /*   - VW or RW coord system must be determined when rendering each obj*/
                                                                                 /*    ... */
/*                                                                     */        /*                                                                     */
/* This application uses the files:                                    */        /* This application uses the files:                                    */
/*   - wrs_shapes.c  (Bill Sherman's simple OpenGL shapes)             */        /*   - wrs_shapes.c  (Bill Sherman's simple OpenGL shapes)             */
/*                                                                     */        /*                                                                     */
/* Copyright 2010, William R. Sherman, All Rights Reserved.            */        /* Copyright 2010, William R. Sherman, All Rights Reserved.            */
/*   In particular, the right to republish this file in whole or in    */        /*   In particular, the right to republish this file in whole or in    */
/*   part, in any form (including electronic forms) is prohibited      */        /*   part, in any form (including electronic forms) is prohibited      */
/*   without written consent of the copyright holder.                  */        /*   without written consent of the copyright holder.                  */
/***********************************************************************/        /***********************************************************************/
#include <stdio.h>      /* needed for printf(), etc. */                          #include <stdio.h>      /* needed for printf(), etc. */
#include <stdlib.h>     /* needed for exit() & getenv() */                       #include <stdlib.h>     /* needed for exit() & getenv() */
#include <signal.h>     /* needed for signal() and its arguments */              #include <signal.h>     /* needed for signal() and its arguments */
#include <unistd.h>     /* not sure why/whether this is needed */                #include <unistd.h>     /* not sure why/whether this is needed */
#include <math.h>       /* needed for fabs() & trig functions */                 #include <math.h>       /* needed for fabs() & trig functions */
 
#include <GL/gl.h>      /* needed for all OpenGL functions & values */           #include <GL/gl.h>      /* needed for all OpenGL functions & values */
 
#include "freevr.h"     /* needed for FreeVR functions & values */               #include "freevr.h"     /* needed for FreeVR functions & values */
#define WAND_SENSOR     1       /* TODO: this should really be based on the c    #define WAND_SENSOR     1       /* TODO: this should really be based on the c
 
/* Define some values to adjust the compilation of this example */               /* Define some values to adjust the compilation of this example */
#define DRAW_UITEXT                                                              #define DRAW_UITEXT
#define USE_SOCKETS                                                              #define USE_SOCKETS
#define MAX_OBJECTS     1000                                                     #define MAX_OBJECTS     1000
#define RADIO_SEP         0.7                                                    #define RADIO_SEP         0.7
#define SLIDER_LENGTH     3.0                                                    #define SLIDER_LENGTH     3.0
#define LEVER_MAX_ANGLE  50.0                                                    #define LEVER_MAX_ANGLE  50.0
#define LEVER_KNOB_SIZE   0.5                                                    #define LEVER_KNOB_SIZE   0.5
#define LEVER_ARM_LENGTH  1.0                                                    #define LEVER_ARM_LENGTH  1.0
#undef  LEVER_SNAPBACK                                                           #define LEVER_SNAPBACK
#define JOYST_MAX_ANGLE  40.0                                                    #define JOYST_MAX_ANGLE  40.0
#define JOYST_KNOB_SIZE   0.5                                                    #define JOYST_KNOB_SIZE   0.5
#define JOYST_ARM_LENGTH  0.7                                                    #define JOYST_ARM_LENGTH  0.7
#undef  JOY_SNAPBACK                                                             #define JOY_SNAPBACK
 
 
/* Define a structure for information about each individual object. */           /* Define a structure for information about each individual object. */
typedef struct {                                                                 typedef struct {
                float                   x, y, z;                /* location o                    float                   x, y, z;                /* location o
                float                   size;                   /* size of th                    float                   size;                   /* size of th
                GLubyte                 color[3];               /* color of t                    GLubyte                 color[3];               /* color of t
                enum {  cube,                                                                    enum {  cube,
                        sphere,                                                                          sphere,
                        pyramid,                                                                         pyramid,
                        ud_pyramid }    shape;                  /* shape of t                            ud_pyramid }    shape;                  /* shape of t
                enum {  vw_normal,                                                               enum {  vw_normal,
                        ui_button,                                                                       ui_button,
                        ui_pushbut,                                                                      ui_pushbut,
                        ui_radio,                                                                        ui_radio,
                        ui_slider,                                                                       ui_slider,
                        ui_lever,                                                                        ui_lever,
                        ui_joyst }      type;                   /* type of th                            ui_joyst }      type;                   /* type of th
                int                     ui_button_value;        /* button val                    int                     ui_button_value;        /* button val
                int                     ui_button_jp_value;     /* the just-p                    int                     ui_button_jp_value;     /* the just-p
                float                   ui_valuator_value;      /* valuator v                    float                   ui_valuator_value;      /* valuator v
                float                   ui_valuator2_value;     /* valuator v                    float                   ui_valuator2_value;     /* valuator v
                int                     ui_num_buttons;         /* number of                     int                     ui_num_buttons;         /* number of 
                char                    *ui_radio_names[10];    /* must be al                    char                    *ui_radio_names[10];    /* must be al
        } ObjectType;                                                                    } ObjectType;
 
/* Define a structure for holding a database of the virtual world. */            /* Define a structure for holding a database of the virtual world. */
typedef struct {                                                                 typedef struct {
                int             quit_bit;                       /* a flag to                     int             quit_bit;                       /* a flag to 
                int             number_of_objects;              /* number of                     int             number_of_objects;              /* number of 
                int             contacted_object;               /* object con                    int             contacted_object;               /* object con
                int             last_contacted_object;          /* object pre                    int             last_contacted_object;          /* object pre
                ObjectType      object[MAX_OBJECTS];            /* array of o                    ObjectType      object[MAX_OBJECTS];            /* array of o
                                                                                                 int             selected_object;        /* TODO: I need to de
                vrLock          lock;                           /* to avoid b                    vrLock          lock;                           /* to avoid b
        } WorldDataType;                                                                 } WorldDataType;
 
 
/****************************************************************************    /****************************************************************************
/* These function declarations are very important -- they will be used as arg    /* These function declarations are very important -- they will be used as arg
void    exit_application(int signal);           /* cleanly close down operati    void    exit_application(int signal);           /* cleanly close down operati
 
void    init_gfx();                             /* initialize the graphics       void    init_gfx();                             /* initialize the graphics   
void    draw_world(WorldDataType *wd, vrRenderInfo *rendinfo); /* render the     void    draw_world(WorldDataType *wd, vrRenderInfo *rendinfo); /* render the 
void    init_world(WorldDataType *wd);          /* initialize the world param    void    init_world(WorldDataType *wd);          /* initialize the world param
void    update_world(WorldDataType *wd);        /* perform the world simulati    void    update_world(WorldDataType *wd);        /* perform the world simulati
 
void    end_world();                            /* close down the world opera    void    end_world();                            /* close down the world opera
void    init_objects(WorldDataType *wd);        /* initalize the objects in t    void    init_objects(WorldDataType *wd);        /* initalize the objects in t
 
 
/***********************************************************************/        /***********************************************************************/
main(int argc, char* argv[])                                                     main(int argc, char* argv[])
{                                                                                {
        WorldDataType   *wd;                                                             WorldDataType   *wd;
 
        /**********************************/                                             /**********************************/
        /*** initialize FreeVR routines ***/                                             /*** initialize FreeVR routines ***/
        /**********************************/                                             /**********************************/
        signal(SIGINT, SIG_IGN);                                                         signal(SIGINT, SIG_IGN);
        vrConfigure(&argc, argv, NULL);         /* allow CLAs to affect confi            vrConfigure(&argc, argv, NULL);         /* allow CLAs to affect confi
        vrStart();                                                                       vrStart();
        signal(SIGINT, exit_application);                                                signal(SIGINT, exit_application);
 
        /********************/                                                           /********************/
        /* create the world */                                                           /* create the world */
        wd = (WorldDataType *)vrShmemAlloc0(sizeof(WorldDataType));                      wd = (WorldDataType *)vrShmemAlloc0(sizeof(WorldDataType));
        wd->lock = vrLockCreate();                                                       wd->lock = vrLockCreate();
        init_world(wd);                                                                  init_world(wd);
 
        /***************************************/                                        /***************************************/
        /* set up the FreeVR library functions */                                        /* set up the FreeVR library functions */
        vrFunctionSetCallback(VRFUNC_DISPLAY_INIT, vrCallbackCreate(init_gfx,            vrFunctionSetCallback(VRFUNC_DISPLAY_INIT, vrCallbackCreate(init_gfx,
        vrFunctionSetCallback(VRFUNC_DISPLAY, vrCallbackCreate(draw_world, 1,            vrFunctionSetCallback(VRFUNC_DISPLAY, vrCallbackCreate(draw_world, 1,
 
        /********************************************************/                       /********************************************************/
        /* define the application name, authors, controls, etc. */                       /* define the application name, authors, controls, etc. */
        vrSystemSetName("example 14f -- push button widget");                            vrSystemSetName("example 15 -- control method comparison example");
        vrSystemSetAuthors("Bill Sherman");                                              vrSystemSetAuthors("Bill Sherman");
        vrSystemSetExtraInfo("An example to demonstrate a push button virtual            vrSystemSetExtraInfo("An example to demonstrate the four categories o
        vrSystemSetStatusDescription("Application running fine");                        vrSystemSetStatusDescription("Application running fine");
        vrInputSet2switchDescription(0, "Terminate the application");                    vrInputSet2switchDescription(0, "Terminate the application");
        vrInputSet2switchDescription(1, "Move the selected object");                     vrInputSet2switchDescription(1, "Move the selected object");
        vrInputSet2switchDescription(3, "Reset the travel matrix (take us hom            vrInputSet2switchDescription(3, "Reset the travel matrix (take us hom
        vrInputSetValuatorDescription(0, "Rotate us in the world about the Y-            vrInputSetValuatorDescription(0, "Rotate us in the world about the Y-
        vrInputSetValuatorDescription(1, "Move us though the world in the dir            vrInputSetValuatorDescription(1, "Move us though the world in the dir
        vrInputSet6sensorDescription(WAND_SENSOR, "Move a short cyan pointer             vrInputSet6sensorDescription(WAND_SENSOR, "Move a short cyan pointer 
 
        /***************************/                                                    /***************************/
        /*** do world simulation ***/                                                    /*** do world simulation ***/
        /***************************/                                                    /***************************/
        vrUserTravelReset(VR_ALLUSERS);                                                  vrUserTravelReset(VR_ALLUSERS);
        /* run until the user has indicated it's time not to */                          /* run until the user has indicated it's time not to */
        while(!wd->quit_bit) {                                                           while(!wd->quit_bit) {
                vrFrame();                                                                       vrFrame();
                update_world(wd);                                                                update_world(wd);
        }                                                                                }
 
        /*********************/                                                          /*********************/
        /*** close up shop ***/                                                          /*** close up shop ***/
        /*********************/                                                          /*********************/
        exit_application(0);                                                             exit_application(0);
}                                                                                }
 
 
/********************************************************************/           /********************************************************************/
/* exit_application(): clean up anything started by the application */           /* exit_application(): clean up anything started by the application */
/*   (forked processes, open files, open sockets, etc.)             */           /*   (forked processes, open files, open sockets, etc.)             */
/********************************************************************/           /********************************************************************/
void exit_application(int signal)                                                void exit_application(int signal)
{                                                                                {
        end_world();                                                                     end_world();
 
        vrExit();                                                                        vrExit();
 
        exit(0);                                                                         exit(0);
}                                                                                }
 
 
 
/* ----------------8<-----------------8<-----------------8<----------------*/    /* ----------------8<-----------------8<-----------------8<----------------*/
/* In a non-example applicatation, the following would be a separate file. */    /* In a non-example applicatation, the following would be a separate file. */
 
                /**********************************/                                             /**********************************/
                /**********************************/                                             /**********************************/
                /** The World Simulation section **/                                             /** The World Simulation section **/
                /**********************************/                                             /**********************************/
                /**********************************/                                             /**********************************/
 
#ifdef USE_SOCKETS /* { */                                                       #ifdef USE_SOCKETS /* { */
static int      listen_sock = -1;       /* socket to receive commands */         static int      listen_sock = -1;       /* socket to receive commands */
                                        /*   listen_sock is not in wd                                                    /*   listen_sock is not in wd        
                                        /*   because it needs to be                                                      /*   because it needs to be          
                                        /*   available to exit_application()                                             /*   available to exit_application() 
                                        /*   which can have no arguments.                                                /*   which can have no arguments.    
#endif /* } USE_SOCKETS */                                                       #endif /* } USE_SOCKETS */
 
 
/****************************************************************/               /****************************************************************/
/* init_world(): create the initial conditions of the dynamic   */               /* init_world(): create the initial conditions of the dynamic   */
/*   simulation.  If the "VR_PORT" environment variable is set, */               /*   simulation.  If the "VR_PORT" environment variable is set, */
/*   then its value is used as the initial server socket port.  */               /*   then its value is used as the initial server socket port.  */
/*   Otherwise, the arbitrarily chosen port number 4000 is used.*/               /*   Otherwise, the arbitrarily chosen port number 4000 is used.*/
/*   Since IRIX, and perhaps other Unicies have a "feature" in  */               /*   Since IRIX, and perhaps other Unicies have a "feature" in  */
/*   which a socket port isn't usable again until after 60      */               /*   which a socket port isn't usable again until after 60      */
/*   seconds have passed since the connection was closed, if the*/               /*   seconds have passed since the connection was closed, if the*/
/*   initial socket isn't available, we try the next two ports  */               /*   initial socket isn't available, we try the next two ports  */
/*   in succession.  The selected port is reported to the tty.  */               /*   in succession.  The selected port is reported to the tty.  */
/****************************************************************/               /****************************************************************/
void init_world(WorldDataType *wd)                                               void init_world(WorldDataType *wd)
{                                                                                {
#ifdef USE_SOCKETS /* { */                                                       #ifdef USE_SOCKETS /* { */
        int     inet_port;                                                               int     inet_port;
        int     inet_port_max;                                                           int     inet_port_max;
        char    host_machine[128];                                                       char    host_machine[128];
#endif /* } USE_SOCKETS */                                                       #endif /* } USE_SOCKETS */
 
        /*************************/                                                      /*************************/
        /* set world state flags */                                                      /* set world state flags */
        vrLockWriteSet(wd->lock);                                                        vrLockWriteSet(wd->lock);
        wd->quit_bit = 0;                                                                wd->quit_bit = 0;
        vrLockWriteRelease(wd->lock);                                                    vrLockWriteRelease(wd->lock);
 
        /***************************/                                                    /***************************/
        /* setup the world content */                                                    /* setup the world content */
        init_objects(wd);                                                                init_objects(wd);
 
#ifdef USE_SOCKETS /* { */                                                       #ifdef USE_SOCKETS /* { */
        /******************************/                                                 /******************************/
        /* initialize the socket port */                                                 /* initialize the socket port */
        gethostname(host_machine, 128);                                                  gethostname(host_machine, 128);
 
        /* loop through N possible internet ports to hopefully find one that             /* loop through N possible internet ports to hopefully find one that 
        if (getenv("VR_PORT") != NULL)                                                   if (getenv("VR_PORT") != NULL)
                inet_port = atoi(getenv("VR_PORT"));                                             inet_port = atoi(getenv("VR_PORT"));
        else    inet_port = 4000;                                                        else    inet_port = 4000;
        for (inet_port_max = inet_port + 2; listen_sock < 0 && inet_port <= i            for (inet_port_max = inet_port + 2; listen_sock < 0 && inet_port <= i
                printf("Port %d -- ", inet_port);                                                printf("Port %d -- ", inet_port);
                fflush(stdout);                                                                  fflush(stdout);
                listen_sock = vrSocketCreateListen(&inet_port, 0);                               listen_sock = vrSocketCreateListen(&inet_port, 0);
        }                                                                                }
        inet_port--;                                                                     inet_port--;
        if (listen_sock < 0)                                                             if (listen_sock < 0)
                printf("WARNING: Unable to find an open socket port.\n");                        printf("WARNING: Unable to find an open socket port.\n");
        else    printf("\rConnect to '%s:%d' to send commands to the simulati            else    printf("\rConnect to '%s:%d' to send commands to the simulati
#endif /* } USE_SOCKETS */                                                       #endif /* } USE_SOCKETS */
}                                                                                }
 
 
/***************************************************************/                /***************************************************************/
/* init_objects(): place objects into the world data structure */                /* init_objects(): place objects into the world data structure */
/*   at some initial positions.                                */                /*   at some initial positions.                                */
/***************************************************************/                /***************************************************************/
void init_objects(WorldDataType *wd)                                             void init_objects(WorldDataType *wd)
{                                                                                {
        int     objnum = 0;                                                              int     objnum = 0;
 
        vrLockWriteSet(wd->lock);                                                        vrLockWriteSet(wd->lock);
 
        /* object 1 - a blue cube */                                                     /* object 1 - a blue cube */
        wd->object[objnum].type = vw_normal;                                             wd->object[objnum].type = vw_normal;    /* for C++, use ObjectType::v
        wd->object[objnum].shape = cube;                                                 wd->object[objnum].shape = cube;
        wd->object[objnum].size = 1.0;                                                   wd->object[objnum].size = 0.5;
        wd->object[objnum].color[0] = 100;                                               wd->object[objnum].color[0] = 100;
        wd->object[objnum].color[1] = 100;                                               wd->object[objnum].color[1] = 100;
        wd->object[objnum].color[2] = 255;                                               wd->object[objnum].color[2] = 255;
        wd->object[objnum].x =  0.0;                                                     wd->object[objnum].x =  0.0;
        wd->object[objnum].y =  5.0;                                                     wd->object[objnum].y =  5.0;
        wd->object[objnum].z = -4.0;                                                     wd->object[objnum].z = -4.0;
        objnum++;                                                                        objnum++;
 
        /* object 2 - a red pyramid */                                                   /* object 2 - a red pyramid */
        wd->object[objnum].type = vw_normal;                                             wd->object[objnum].type = vw_normal;
        wd->object[objnum].shape = pyramid;                                              wd->object[objnum].shape = pyramid;
        wd->object[objnum].size = 1.0;                                                   wd->object[objnum].size = 1.0;
        wd->object[objnum].color[0] = 255;                                               wd->object[objnum].color[0] = 255;
        wd->object[objnum].color[1] = 100;                                               wd->object[objnum].color[1] = 100;
        wd->object[objnum].color[2] = 100;                                               wd->object[objnum].color[2] = 100;
        wd->object[objnum].x = -4.0;                                                     wd->object[objnum].x = -4.0;
        wd->object[objnum].y =  5.0;                                                     wd->object[objnum].y =  5.0;
        wd->object[objnum].z = -4.0;                                                     wd->object[objnum].z = -4.0;
        objnum++;                                                                        objnum++;
 
        /* object 3 - an upside-down green pyramid */                                    /* object 3 - an upside-down green pyramid */
        wd->object[objnum].type = vw_normal;                                             wd->object[objnum].type = vw_normal;
        wd->object[objnum].shape = ud_pyramid;                                           wd->object[objnum].shape = ud_pyramid;
        wd->object[objnum].size = 1.0;                                                   wd->object[objnum].size = 1.0;
        wd->object[objnum].color[0] = 100;                                               wd->object[objnum].color[0] = 100;
        wd->object[objnum].color[1] = 255;                                               wd->object[objnum].color[1] = 255;
        wd->object[objnum].color[2] = 100;                                               wd->object[objnum].color[2] = 100;
        wd->object[objnum].x =  4.0;                                                     wd->object[objnum].x =  4.0;
        wd->object[objnum].y =  5.0;                                                     wd->object[objnum].y =  5.0;
        wd->object[objnum].z = -4.0;                                                     wd->object[objnum].z = -4.0;
        objnum++;                                                                        objnum++;
 
        /* object 4 - a user interface button */                                         /* object 4 - a user interface radio button to select control method 
        wd->object[objnum].type = ui_button;                                             wd->object[objnum].type = ui_radio;
        wd->object[objnum].shape = cube;                                                 wd->object[objnum].shape = cube;
        wd->object[objnum].size = 0.4;                                                   wd->object[objnum].size = 0.4;
        wd->object[objnum].ui_button_value = 1;                                          wd->object[objnum].ui_button_value = 0;
        wd->object[objnum].color[0] = 200;                                               wd->object[objnum].color[0] = 212;      /* rose */
        wd->object[objnum].color[1] = 100;                                               wd->object[objnum].color[1] =  42;
        wd->object[objnum].color[2] = 255;                                               wd->object[objnum].color[2] =  95;
        wd->object[objnum].x = -4.0;                                                     wd->object[objnum].x = -4.0;
        wd->object[objnum].y =  4.0;                                                     wd->object[objnum].y =  5.0;
        wd->object[objnum].z = -2.0;                                                     wd->object[objnum].z = -2.0;
                                                                                         wd->object[objnum].ui_num_buttons = 4;
                                                                                         wd->object[objnum].ui_radio_names[0] = vrShmemStrDup("direct");
                                                                                         wd->object[objnum].ui_radio_names[1] = vrShmemStrDup("physical");
                                                                                         wd->object[objnum].ui_radio_names[2] = vrShmemStrDup("virtual");
                                                                                         wd->object[objnum].ui_radio_names[3] = vrShmemStrDup("agent");
        objnum++;                                                                        objnum++;
 
        /* object 5 - a user interface slider */                                         /* object 5 - a user interface radio button to select object */
        wd->object[objnum].type = ui_slider;                                  
        wd->object[objnum].shape = cube;                                      
        wd->object[objnum].size = 0.4;                                        
        wd->object[objnum].ui_valuator_value = 1.0;                           
        wd->object[objnum].color[0] = 208;                                    
        wd->object[objnum].color[1] = 113;                                    
        wd->object[objnum].color[2] =  33;                                    
        wd->object[objnum].x = -4.0;                                          
        wd->object[objnum].y =  4.0;                                          
        wd->object[objnum].z = -1.0;                                          
        objnum++;                                                             
                                                                              
        /* object 6 - a user interface lever */                               
        wd->object[objnum].type = ui_lever;                                   
        wd->object[objnum].shape = cube;                                      
        wd->object[objnum].size = 1.0;                                        
        wd->object[objnum].ui_valuator_value = 0.0;                           
        wd->object[objnum].color[0] = 101;                                    
        wd->object[objnum].color[1] = 167;                                    
        wd->object[objnum].color[2] = 107;                                    
        wd->object[objnum].x = -1.5;                                          
        wd->object[objnum].y =  3.5;                                          
        wd->object[objnum].z = -3.0;                                          
        objnum++;                                                             
                                                                              
        /* object 7 - a user interface radio button */                        
        wd->object[objnum].type = ui_radio;                                              wd->object[objnum].type = ui_radio;
        wd->object[objnum].shape = cube;                                                 wd->object[objnum].shape = cube;
        wd->object[objnum].size = 0.4;                                                   wd->object[objnum].size = 0.4;
        wd->object[objnum].ui_button_value = 0;                                          wd->object[objnum].ui_button_value = 0;
        wd->object[objnum].color[0] = 212;      /* rose */                               wd->object[objnum].color[0] =  74;
        wd->object[objnum].color[1] =  42;                                               wd->object[objnum].color[1] = 103;
        wd->object[objnum].color[2] =  95;                                               wd->object[objnum].color[2] = 130;
        wd->object[objnum].x = -4.0;                                                     wd->object[objnum].x = -4.0;
        wd->object[objnum].y =  5.0;                                                     wd->object[objnum].y =  5.0;
        wd->object[objnum].z =  1.0;                                                     wd->object[objnum].z =  0.0;
        wd->object[objnum].ui_num_buttons = 4;                                           wd->object[objnum].ui_num_buttons = 4;
        wd->object[objnum].ui_radio_names[0] = vrShmemStrDup("choice 1");                wd->object[objnum].ui_radio_names[0] = vrShmemStrDup("-none-");
        wd->object[objnum].ui_radio_names[1] = vrShmemStrDup("choice 2");                wd->object[objnum].ui_radio_names[1] = vrShmemStrDup("blue");
        wd->object[objnum].ui_radio_names[2] = vrShmemStrDup("choice 3");                wd->object[objnum].ui_radio_names[2] = vrShmemStrDup("red");
        wd->object[objnum].ui_radio_names[3] = vrShmemStrDup("choice 4");                wd->object[objnum].ui_radio_names[3] = vrShmemStrDup("green");
        objnum++;                                                                        objnum++;
 
        /* object 8 - a user interface joystick */                                       /* object 6 - a user interface joystick */
                                                                                         /* NOTE: we'll only render this in "virtual" control mode */
        wd->object[objnum].type = ui_joyst;                                              wd->object[objnum].type = ui_joyst;
        wd->object[objnum].shape = cube;                                                 wd->object[objnum].shape = cube;
        wd->object[objnum].size = 0.5;                                                   wd->object[objnum].size = 0.5;
        wd->object[objnum].ui_valuator_value  = 0.0;                                     wd->object[objnum].ui_valuator_value  = 0.0;
        wd->object[objnum].ui_valuator2_value = 0.0;                                     wd->object[objnum].ui_valuator2_value = 0.0;
        wd->object[objnum].color[0] =  74;                                               wd->object[objnum].color[0] =  74;
        wd->object[objnum].color[1] = 103;                                               wd->object[objnum].color[1] = 103;
        wd->object[objnum].color[2] = 130;                                               wd->object[objnum].color[2] = 130;
        wd->object[objnum].x =  1.5;                                                     wd->object[objnum].x = -1.5;
        wd->object[objnum].y =  3.5;                                                     wd->object[objnum].y =  3.5;
        wd->object[objnum].z = -3.0;                                                     wd->object[objnum].z = -1.5;
        objnum++;                                                                        objnum++;
 
        /* object 9 - a user interface push-button */                                    /* object 7 - a user interface push button */
                                                                                         /* NOTE: we'll only render this in "virtual" control mode */
        wd->object[objnum].type = ui_pushbut;                                            wd->object[objnum].type = ui_pushbut;
        wd->object[objnum].shape = cube;                                                 wd->object[objnum].shape = cube;
        wd->object[objnum].size = 0.4;                                                   wd->object[objnum].size = 0.3;
        wd->object[objnum].ui_button_value  = 0;                                         wd->object[objnum].ui_button_value  = 0;
        wd->object[objnum].ui_button_jp_value = 0;                                       wd->object[objnum].ui_button_jp_value = 0;
        wd->object[objnum].color[0] =  87;      /* lime green */                         wd->object[objnum].color[0] =  74;
        wd->object[objnum].color[1] = 212;                                               wd->object[objnum].color[1] = 103;
        wd->object[objnum].color[2] =   0;                                               wd->object[objnum].color[2] = 130;
        wd->object[objnum].x = -2.7;                                                     wd->object[objnum].x = -2.5;
        wd->object[objnum].y =  4.0;                                                     wd->object[objnum].y =  3.5;
        wd->object[objnum].z = -2.0;                                                     wd->object[objnum].z = -1.5;
        objnum++;                                                                        objnum++;
 
        wd->number_of_objects = objnum;                                                  wd->number_of_objects = objnum;
        wd->contacted_object = -1;                                                       wd->contacted_object = -1;
        wd->last_contacted_object = wd->contacted_object;                                wd->last_contacted_object = wd->contacted_object;
                                                                                         wd->selected_object = -1;
 
        /* sanity test */                                                                /* sanity test */
        if (objnum > MAX_OBJECTS) {                                                      if (objnum > MAX_OBJECTS) {
                printf("DANGER: Number of objects (%d), exceeds maximum allow                    printf("DANGER: Number of objects (%d), exceeds maximum allow
        }                                                                                }
 
        vrLockWriteRelease(wd->lock);                                                    vrLockWriteRelease(wd->lock);
}                                                                                }
 
 
/*******************************************************/                        /*******************************************************/
/* end_world(): clean up anything opened by simulation */                        /* end_world(): clean up anything opened by simulation */
/*******************************************************/                        /*******************************************************/
void end_world()                                                                 void end_world()
{                                                                                {
#ifdef USE_SOCKETS /* { */                                                       #ifdef USE_SOCKETS /* { */
        vrSocketClose(listen_sock);                                                      vrSocketClose(listen_sock);
#endif /* } USE_SOCKETS */                                                       #endif /* } USE_SOCKETS */
}                                                                                }
 
 
/*********************************************************************/          /*********************************************************************/
/* update_world(): In this version, we handle the user interactions. */          /* update_world(): In this version, we handle the user interactions. */
/*   Both selecting, and moving the contacted object.                */          /*   Both selecting, and moving the contacted object.                */
/*********************************************************************/          /*********************************************************************/
void update_world(WorldDataType *wd)                                             void update_world(WorldDataType *wd)
{                                                                                {
#define JS_EPSILON      0.125                           /* the dead-zone befo    #define JS_EPSILON      0.125                           /* the dead-zone befo
#define MOVE_FACTOR     2.5                             /* a scale factor to     #define MOVE_FACTOR     2.5                             /* a scale factor to 
#define TURN_FACTOR     25.0                            /* a scale factor to     #define TURN_FACTOR     25.0                            /* a scale factor to 
#define SUB_JS_EPSILON(a)       ((a)-copysign(JS_EPSILON,(a)))  /* a macro to    #define SUB_JS_EPSILON(a)       ((a)-copysign(JS_EPSILON,(a)))  /* a macro to
#ifdef USE_SOCKETS /* { */                                                       #ifdef USE_SOCKETS /* { */
static  char    *help_msg = "Socket commands:\n"                                 /* TODO: has help been eliminated from this point forward?  A: no, it looks l
                                "\thelp -- this message\n"                    
                                "\tquit -- quit the application\n"            
                                "\tclose -- close the connection\n"           
                                "\treset -- reset the application\n"          
                                "\tbutton? -- report the value of the UI butt 
                                "\tbutton on -- set the value of the UI butto 
                                "\tbutton off -- set the value of the UI butt 
                                "\tpushbutton? -- report the value of the UI  
                                "\tpushbutton on -- set the value of the UI p 
                                "\tpushbutton off -- set the value of the UI  
                                "\tradio? -- report the value of the UI radio 
                                "\tradio <n> -- set the value of the UI radio 
                                "\tslider? -- report the value of the UI slid 
                                "\tslider <n> -- set the value of the UI slid 
                                "\tlever? -- report the value of the UI lever 
                                "\tlever <n> -- set the value of the UI lever 
                                "\tjoyst? -- report the values of the UI joys 
                                "\tjoyst1 <n> -- set X value of the UI joysti 
                                "\tjoyst2 <n> -- set Y value of the UI joysti 
                                "\tmove cube up -- translate the cube up 2 fe 
                                "\tmove cube down -- translate the cube down  
                                "\twhere -- report the user's position in the 
                                "\twhere am i -- report the user's position i 
                                "\tshow ActiveWalls -- report some CAVE confi 
                "";                                                           
static  int     cmd_socket = -1;        /* socket to get commands from */        static  int     cmd_socket = -1;        /* socket to get commands from */
static  char    buf[128];               /* socket read buffer          */        static  char    buf[128];               /* socket read buffer          */
static  char    msg[128];               /* socket send buffer          */        static  char    msg[128];               /* socket send buffer          */
        int     result;                 /* result of reading a socket  */                int     result;                 /* result of reading a socket  */
#endif /* } USE_SOCKETS */                                                       #endif /* } USE_SOCKETS */
 
static  vrTime          last_time = -1.0;               /* initially set to a    static  vrTime          last_time = -1.0;               /* initially set to a
        vrTime          sim_time = vrCurrentSimTime();  /* the current time o            vrTime          sim_time = vrCurrentSimTime();  /* the current time o
static  vrPoint         last_wand_vw_locpnt;            /* VW location of the    static  vrPoint         last_wand_vw_locpnt;            /* VW location of the
        vrPoint         wand_vw_locpnt;                 /* current location o            vrPoint         wand_vw_locpnt;                 /* current location o
        vrPoint         wand_rw_locpnt;                 /* current location o            vrPoint         wand_rw_locpnt;                 /* current location o
#define last_wand_vw_loc last_wand_vw_locpnt.v                                   #define last_wand_vw_loc last_wand_vw_locpnt.v
#define wand_vw_location wand_vw_locpnt.v                                        #define wand_vw_location wand_vw_locpnt.v
#define wand_rw_location wand_rw_locpnt.v                                        #define wand_rw_location wand_rw_locpnt.v
        vrVector        wand_rw_pointvec;               /* current vector poi            vrVector        wand_rw_pointvec;               /* current vector poi
        double          delta_time;                     /* time since last up            double          delta_time;                     /* time since last up
        double          delta_move;                     /* distance an object            double          delta_move;                     /* distance an object
        double          joy_x, joy_y;                   /* Joystick values */            double          joy_x, joy_y;                   /* Joystick values */
        int             touch_obj = -1;                 /* the currently touc            int             touch_obj = -1;                 /* the currently touc
                                                                                         int             selected_object_num;            /* the object selecte
        int             objnum;                         /* for looping throuh            int             objnum;                         /* for looping throuh
        ObjectType      *object;                        /* pointer to object             ObjectType      *object;                        /* pointer to object 
        float           size;                           /* size of object --             float           size;                           /* size of object -- 
        int             button_value;                                                    int             travel_active = 1;
        int             pushbutton_value;                                                int             control_type;
        float           slider_value;                                         
        float           joyst1_value;                                                    float           joyst1_value;
        float           joyst2_value;                                                    float           joyst2_value;
        float           value_sin;                                                       float           value_sin;
        float           value_cos;                                                       float           value_cos;
        float           value2_sin;                                                      float           value2_sin;
        float           value2_cos;                                                      float           value2_cos;
 
        /*****************************************************/                          /*****************************************************/
        /** Determine delta time from last simulation frame **/                          /** Determine delta time from last simulation frame **/
        /*****************************************************/                          /*****************************************************/
        if (last_time == -1.0)                                                           if (last_time == -1.0)
                delta_time = 0.0;                                                                delta_time = 0.0;
        else    delta_time = sim_time - last_time;                                       else    delta_time = sim_time - last_time;
        last_time = sim_time;                           /* now that delta_tim            last_time = sim_time;                           /* now that delta_tim
 
        /* skip the update if the delta isn't big enough */                              /* skip the update if the delta isn't big enough */
        if (delta_time <= 0.0)  /* can also choose a non-zero epsilon */                 if (delta_time <= 0.0)  /* can also choose a non-zero epsilon */
                return;                                                                          return;
 
        /**********************************/                                             /**********************************/
        /** Handle Manipulation via wand **/                                             /** Handle Manipulation via wand **/
        /**********************************/                                             /**********************************/
 
        /**********************************************************/                     /**********************************************************/
        /* check for contact between the wand and all the objects */                     /* check for contact between the wand and all the objects */
        vrLockReadSet(wd->lock);                                                         vrLockReadSet(wd->lock);
 
        vrPointGetVWFromUser6sensor(&wand_vw_locpnt, 0, WAND_SENSOR);                    vrPointGetVWFromUser6sensor(&wand_vw_locpnt, 0, WAND_SENSOR);
        vrPointGetRWFrom6sensor(&wand_rw_locpnt, WAND_SENSOR);                           vrPointGetRWFrom6sensor(&wand_rw_locpnt, WAND_SENSOR);
 
        for (objnum = 0; objnum < wd->number_of_objects; objnum++) {                     for (objnum = 0; objnum < wd->number_of_objects; objnum++) {
                object = &(wd->object[objnum]);                                                  object = &(wd->object[objnum]);
                size = object->size;                                                             size = object->size;
 
                switch (object->type) {                                                          switch (object->type) {
                case vw_normal: /* determine contact with normal object */                       case vw_normal: /* determine contact with normal object */
                        if ( (wand_vw_location[VR_X] < object->x + size)                                 if ( (wand_vw_location[VR_X] < object->x + size)
                          && (wand_vw_location[VR_X] > object->x - size)                                   && (wand_vw_location[VR_X] > object->x - size)
                          && (wand_vw_location[VR_Y] < object->y + size)                                   && (wand_vw_location[VR_Y] < object->y + size)
                          && (wand_vw_location[VR_Y] > object->y - size)                                   && (wand_vw_location[VR_Y] > object->y - size)
                          && (wand_vw_location[VR_Z] < object->z + size)                                   && (wand_vw_location[VR_Z] < object->z + size)
                          && (wand_vw_location[VR_Z] > object->z - size) ) {                               && (wand_vw_location[VR_Z] > object->z - size) ) {
                                touch_obj = objnum;                                                              touch_obj = objnum;
                        }                                                                                }
                        break;                                                                           break;
                                                                                                 
                case ui_button: /* determine contact with button widget */                       case ui_button: /* determine contact with button widget */
                        if ( (wand_rw_location[VR_X] < object->x + size)                                 if ( (wand_rw_location[VR_X] < object->x + size)
                          && (wand_rw_location[VR_X] > object->x - size)                                   && (wand_rw_location[VR_X] > object->x - size)
                          && (wand_rw_location[VR_Y] < object->y + size)                                   && (wand_rw_location[VR_Y] < object->y + size)
                          && (wand_rw_location[VR_Y] > object->y - size)                                   && (wand_rw_location[VR_Y] > object->y - size)
                          && (wand_rw_location[VR_Z] < object->z + size)                                   && (wand_rw_location[VR_Z] < object->z + size)
                          && (wand_rw_location[VR_Z] > object->z - size) ) {                               && (wand_rw_location[VR_Z] > object->z - size) ) {
                                touch_obj = objnum;                                                              touch_obj = objnum;
                        }                                                                                }
                        break;                                                                           break;
 
                case ui_pushbut: /* determine contact with button widget */                      case ui_pushbut: /* determine contact with button widget */
                        if ( (wand_rw_location[VR_X] < object->x + size)                                 if ( (wand_rw_location[VR_X] < object->x + size)
                          && (wand_rw_location[VR_X] > object->x - size)                                   && (wand_rw_location[VR_X] > object->x - size)
                          && (wand_rw_location[VR_Y] < object->y + size)                                   && (wand_rw_location[VR_Y] < object->y + size)
                          && (wand_rw_location[VR_Y] > object->y - size)                                   && (wand_rw_location[VR_Y] > object->y - size)
                          && (wand_rw_location[VR_Z] < object->z + size)                                   && (wand_rw_location[VR_Z] < object->z + size)
                          && (wand_rw_location[VR_Z] > object->z - size) ) {                               && (wand_rw_location[VR_Z] > object->z - size) ) {
                                touch_obj = objnum;                                                              touch_obj = objnum;
                        } else {                                                                         } else {
                                /* if this object is not in-contact, then set                                    /* if this object is not in-contact, then set
                                /*   ie. this is the snapback feature of a pu                                    /*   ie. this is the snapback feature of a pu
                                object->ui_button_value = 0;                                                     object->ui_button_value = 0;
                                object->ui_button_jp_value = 0;                                                  object->ui_button_jp_value = 0;
                        }                                                                                }
                        break;                                                                           break;
 
                case ui_radio: /* determine contact with radio-button widget                     case ui_radio: /* determine contact with radio-button widget 
                        if ( (wand_rw_location[VR_X] < object->x + size)                                 if ( (wand_rw_location[VR_X] < object->x + size)
                          && (wand_rw_location[VR_X] > object->x - size)                                   && (wand_rw_location[VR_X] > object->x - size)
                          && (wand_rw_location[VR_Y] < object->y + (object->u                              && (wand_rw_location[VR_Y] < object->y + (object->u
                          && (wand_rw_location[VR_Y] > object->y - (object->u                              && (wand_rw_location[VR_Y] > object->y - (object->u
                          && (wand_rw_location[VR_Z] < object->z + size)                                   && (wand_rw_location[VR_Z] < object->z + size)
                          && (wand_rw_location[VR_Z] > object->z - size) ) {                               && (wand_rw_location[VR_Z] > object->z - size) ) {
                                touch_obj = objnum;                                                              touch_obj = objnum;
                        }                                                                                }
                        break;                                                                           break;
 
                case ui_slider: /* determine contact with slider widget */                       case ui_slider: /* determine contact with slider widget */
                        /* check intersection with the (moving) grab bar */                              /* check intersection with the (moving) grab bar */
                        /* NOTE: this crudely assumes vertically aligned slid                            /* NOTE: this crudely assumes vertically aligned slid
                        if (                                                                             if (
                                /* contact with the grab-plate */                                                /* contact with the grab-plate */
                            ((wand_rw_location[VR_X] < object->x + size)                                     ((wand_rw_location[VR_X] < object->x + size)
                          && (wand_rw_location[VR_X] > object->x - size)                                   && (wand_rw_location[VR_X] > object->x - size)
                          && (wand_rw_location[VR_Y] < (object->y + object->u                              && (wand_rw_location[VR_Y] < (object->y + object->u
                          && (wand_rw_location[VR_Y] > (object->y + object->u                              && (wand_rw_location[VR_Y] > (object->y + object->u
                          && (wand_rw_location[VR_Z] < object->z + size)                                   && (wand_rw_location[VR_Z] < object->z + size)
                          && (wand_rw_location[VR_Z] > object->z - size))                                  && (wand_rw_location[VR_Z] > object->z - size))
                         ||     /* or contact with the slider-bar */                                      ||     /* or contact with the slider-bar */
                            ((wand_rw_location[VR_X] < object->x + size * 0.2                                ((wand_rw_location[VR_X] < object->x + size * 0.2
                          && (wand_rw_location[VR_X] > object->x - size * 0.2                              && (wand_rw_location[VR_X] > object->x - size * 0.2
                          && (wand_rw_location[VR_Y] < object->y + size * SLI                              && (wand_rw_location[VR_Y] < object->y + size * SLI
                          && (wand_rw_location[VR_Y] > object->y - size * SLI                              && (wand_rw_location[VR_Y] > object->y - size * SLI
                          && (wand_rw_location[VR_Z] < object->z + size * 0.2                              && (wand_rw_location[VR_Z] < object->z + size * 0.2
                          && (wand_rw_location[VR_Z] > object->z - size * 0.2                              && (wand_rw_location[VR_Z] > object->z - size * 0.2
                                ) {                                                                              ) {
                                touch_obj = objnum;                                                              touch_obj = objnum;
                        }                                                                                }
                        break;                                                                           break;
 
                case ui_lever: /* determine contact with lever widget */                         case ui_lever: /* determine contact with lever widget */
                        /* check intersection with the (moving) lever knob */                            /* check intersection with the (moving) lever knob */
                        /* NOTE: this crudely assumes horizontally aligned le                            /* NOTE: this crudely assumes horizontally aligned le
 
                        /* calculate the sine & cosine for the tip of the lev                            /* calculate the sine & cosine for the tip of the lev
                        value_sin = sinf(object->ui_valuator_value * LEVER_MA                            value_sin = sinf(object->ui_valuator_value * LEVER_MA
                        value_cos = cosf(object->ui_valuator_value * LEVER_MA                            value_cos = cosf(object->ui_valuator_value * LEVER_MA
                        if ( (wand_rw_location[VR_X] < (object->x + (value_si                            if ( (wand_rw_location[VR_X] < (object->x + (value_si
                          && (wand_rw_location[VR_X] > (object->x + (value_si                              && (wand_rw_location[VR_X] > (object->x + (value_si
                          && (wand_rw_location[VR_Y] < (object->y                                          && (wand_rw_location[VR_Y] < (object->y            
                          && (wand_rw_location[VR_Y] > (object->y                                          && (wand_rw_location[VR_Y] > (object->y            
                          && (wand_rw_location[VR_Z] < (object->z + (value_co                              && (wand_rw_location[VR_Z] < (object->z + (value_co
                          && (wand_rw_location[VR_Z] > (object->z + (value_co                              && (wand_rw_location[VR_Z] > (object->z + (value_co
                                touch_obj = objnum;                                                              touch_obj = objnum;
                        } else {                                                                         } else {
#ifdef LEVER_SNAPBACK                                                            #ifdef LEVER_SNAPBACK
                                object->ui_valuator_value  =  0.0;                                               object->ui_valuator_value  =  0.0;
#endif                                                                           #endif
                        }                                                                                }
                        break;                                                                           break;
 
                case ui_joyst: /* determine contact with joystick widget */                      case ui_joyst: /* determine contact with joystick widget */
                        /* check intersection with the (moving) joystick knob                            /* check intersection with the (moving) joystick knob
                        /* NOTE: this crudely assumes aligned joystick along                             /* NOTE: this crudely assumes aligned joystick along 
 
                        /* calculate the sines & cosines for the tip of the s                            /* calculate the sines & cosines for the tip of the s
                        value_sin  = sinf(object->ui_valuator_value  *  JOYST                            value_sin  = sinf(object->ui_valuator_value  *  JOYST
                        value_cos  = cosf(object->ui_valuator_value  *  JOYST                            value_cos  = cosf(object->ui_valuator_value  *  JOYST
                        value2_sin = sinf(object->ui_valuator2_value * -JOYST                            value2_sin = sinf(object->ui_valuator2_value * -JOYST
                        value2_cos = cosf(object->ui_valuator2_value * -JOYST                            value2_cos = cosf(object->ui_valuator2_value * -JOYST
                        if ( (wand_rw_location[VR_X] < (object->x + ((value_s                            if ( (wand_rw_location[VR_X] < (object->x + ((value_s
                          && (wand_rw_location[VR_X] > (object->x + ((value_s                              && (wand_rw_location[VR_X] > (object->x + ((value_s
                          && (wand_rw_location[VR_Y] < (object->y + ((value_c                              && (wand_rw_location[VR_Y] < (object->y + ((value_c
                          && (wand_rw_location[VR_Y] > (object->y + ((value_c                              && (wand_rw_location[VR_Y] > (object->y + ((value_c
                          && (wand_rw_location[VR_Z] < (object->z + ((value2_                              && (wand_rw_location[VR_Z] < (object->z + ((value2_
                          && (wand_rw_location[VR_Z] > (object->z + ((value2_                              && (wand_rw_location[VR_Z] > (object->z + ((value2_
                                touch_obj = objnum;                                                              touch_obj = objnum;
                        } else {                                                                         } else {
#ifdef JOY_SNAPBACK                                                              #ifdef JOY_SNAPBACK
                                object->ui_valuator_value  =  0.0;                                               object->ui_valuator_value  =  0.0;
                                object->ui_valuator2_value =  0.0;                                               object->ui_valuator2_value =  0.0;
#endif                                                                           #endif
                        }                                                                                }
                        break;                                                                           break;
                }                                                                                }
        }                                                                                }
        vrLockReadRelease(wd->lock);                                                     vrLockReadRelease(wd->lock);
 
 
        /*************************************************************/                  /*************************************************************/
        /* perform type-appropriate actions for the contacted object */                  /* perform type-appropriate actions for the contacted object */
 
        /* NOTE: ideally we would use write-locks specific to each */                    /* NOTE: ideally we would use write-locks specific to each */
        /*   object, and only where that object is being changed.  */                    /*   object, and only where that object is being changed.  */
        vrLockWriteSet(wd->lock);       /* lock while changing an object's lo            vrLockWriteSet(wd->lock);       /* lock while changing an object's lo
        wd->last_contacted_object = wd->contacted_object;                                wd->last_contacted_object = wd->contacted_object;
        wd->contacted_object = touch_obj;                                                wd->contacted_object = touch_obj;
        if (wd->contacted_object != -1) {                                       
                object = &(wd->object[wd->contacted_object]);                            touch_obj = wd->contacted_object;
                                                                                         control_type = wd->object[3].ui_button_value;
                                                                                
                                                                                         /* first we determine the selected object -- based on control type */
                                                                                         switch (control_type) {
                                                                                
                                                                                         case 0: /* direct control -- must make contact to select */
                                                                                                 /* don't select UI objects */
                                                                                                 if (touch_obj <= 2)
                                                                                                         wd->selected_object = touch_obj;
                                                                                                 break;
                                                                                
                                                                                         case 1: /* physical control -- button presses increment/decrement sel
                                                                                                 if (vrGet2switchValue(1)) {
                                                                                                         if (wd->selected_object > 0)    /* Notice this limits
                                                                                                                 wd->selected_object--;
                                                                                                 }
                                                                                                 if (vrGet2switchDelta(3)) {
                                                                                                         if (wd->selected_object < 2)
                                                                                                                 wd->selected_object++;
                                                                                                 }
                                                                                                 break;
                                                                                
                                                                                         case 2: /* virtual control -- radio button to select object, joystick
                                                                                                 wd->selected_object = wd->object[4].ui_button_value - 1;
                                                                                                 break;
                                                                                
                                                                                         case 3: /* agent control -- voice (ie. text) commands to select and m
                                                                                                 /* no need to do anything here, selection is done in the sock
                                                                                                 break;
                                                                                         }
                                                                                
                                                                                
                                                                                         /*************************************/
                                                                                         /* handle the selected normal object */
                                                                                         selected_object_num = wd->selected_object;
                                                                                
                                                                                         if (selected_object_num != -1) {
                                                                                                 selected_object_num = wd->selected_object;
                                                                                                 object = &(wd->object[selected_object_num]);
                size = object->size;                                                             size = object->size;
 
                switch (object->type) {                                                          switch (object->type) {
                case vw_normal: /* perform manipulation on normal object */                      case vw_normal: /* perform manipulation on normal object */
                        /* when left wand button is pressed, a contacted VW o                            /* The means of moving the selected object depends on
                        if (vrGet2switchValue(1)) {                           
 
                                object->x += (wand_vw_location[VR_X] - last_w                            switch (control_type) {
                                object->y += (wand_vw_location[VR_Y] - last_w   
                                object->z += (wand_vw_location[VR_Z] - last_w                            case 0: /* direct control */
                                                                                                                 /* when left wand button is pressed, a contac
                                                                                                                 if (vrGet2switchValue(1)) {
                                                                                
                                                                                                                         object->x += (wand_vw_location[VR_X] 
                                                                                                                         object->y += (wand_vw_location[VR_Y] 
                                                                                                                         object->z += (wand_vw_location[VR_Z] 
                                                                                                                 }
                                                                                                                 break;
                                                                                
                                                                                                         case 1: /* physical control */
                                                                                                                 /* use the wand joystick to fly the object */
                                                                                                                 joy_x = vrGetValuatorValue(0);
                                                                                                                 joy_y = vrGetValuatorValue(1);
                                                                                                                 object->x += joy_x * 0.0001;    /* TODO: idea
                                                                                                                 object->z -= joy_y * 0.0001;
                                                                                
                                                                                                                 if (vrGet2switchValue(2)) {
                                                                                                                         object->x += (wand_vw_location[VR_X] 
                                                                                                                         object->y += (wand_vw_location[VR_Y] 
                                                                                                                         object->z += (wand_vw_location[VR_Z] 
                                                                                                                 }
                                                                                
                                                                                                                 break;
                                                                                
                                                                                                         case 2: /* virtual control */
                                                                                                                 object->x += wd->object[5].ui_valuator_value 
                                                                                                                 object->z -= wd->object[5].ui_valuator2_value
                                                                                                                 if (wd->object[6].ui_button_jp_value == 1) {
                                                                                                                         object->x += (wand_vw_location[VR_X] 
                                                                                                                         object->y += (wand_vw_location[VR_Y] 
                                                                                                                         object->z += (wand_vw_location[VR_Z] 
                                                                                                                         wd->object[6].ui_button_jp_value = 0;
                                                                                                                 }
                                                                                                                 break;
                                                                                
                                                                                                         case 3: /* agent control */
                                                                                                                 break;
                        }                                                                                }
                        break;                                                                           break;
 
                                                                                                 default:
                                                                                                         /* for all the ui objects, we work from contacted obj
                                                                                                         break;
                                                                                                 }
                                                                                         }
                                                                                
                                                                                
                                                                                         /****************************************************/
                                                                                         /* handle the UI objects based on contact-to-select */
                                                                                         if (touch_obj != -1) {
                                                                                                 object = &(wd->object[touch_obj]);
                                                                                                 size = object->size;
                                                                                
                                                                                                 switch (object->type) {
                                                                                                 case vw_normal: /* perform manipulation on normal object */
                                                                                                         /* Normal objects are handled above */
                                                                                                         break;
                                                                                
                case ui_button: /* perform manipulation on button widget */                      case ui_button: /* perform manipulation on button widget */
                        /* this code only needed for direct-control of button                            /* this code only needed for direct-control of button
 
                        /* CONTACT-trigger: when we begin to touch a button,                             /* CONTACT-trigger: when we begin to touch a button, 
                        if (wd->contacted_object != wd->last_contacted_object                            if (wd->contacted_object != wd->last_contacted_object
                                object->ui_button_value ^= 1;                                                    object->ui_button_value ^= 1;
                        }                                                                                }
                        break;                                                                           break;
 
                case ui_pushbut: /* perform manipulation on button widget */                     case ui_pushbut: /* perform manipulation on button widget */
                        /* this code only needed for direct-control of button                            /* this code only needed for direct-control of button
 
                        /* CONTACT-trigger: when we touch the button, set it                             /* CONTACT-trigger: when we touch the button, set it 
 
                        /* if the object was off before this contact, then al                            /* if the object was off before this contact, then al
                        if (object->ui_button_value == 0)                                                if (object->ui_button_value == 0)
                                object->ui_button_jp_value = 1;                                                  object->ui_button_jp_value = 1;
 
                        /* always set the value to 1 when pressed */                                     /* always set the value to 1 when pressed */
                        object->ui_button_value = 1;                                                     object->ui_button_value = 1;
 
                        break;                                                                           break;
 
                case ui_radio: { /* perform manipulation on radio-button widg                    case ui_radio: { /* perform manipulation on radio-button widg
                        /* this code only needed for direct-control of button                            /* this code only needed for direct-control of button
                        int     count;                                                                   int     count;
 
                        /* CONTACT-trigger: when we begin to touch a button,                             /* CONTACT-trigger: when we begin to touch a button, 
                        if (1) {                                                                         if (1) {
                                for (count = 0; count < object->ui_num_button                                    for (count = 0; count < object->ui_num_button
 
                                        if ( (wand_rw_location[VR_X] < object                                            if ( (wand_rw_location[VR_X] < object
                                          && (wand_rw_location[VR_X] > object                                              && (wand_rw_location[VR_X] > object
                                          && (wand_rw_location[VR_Y] < object                                              && (wand_rw_location[VR_Y] < object
                                          && (wand_rw_location[VR_Y] > object                                              && (wand_rw_location[VR_Y] > object
                                          && (wand_rw_location[VR_Z] < object                                              && (wand_rw_location[VR_Z] < object
                                          && (wand_rw_location[VR_Z] > object                                              && (wand_rw_location[VR_Z] > object
                                                object->ui_button_value = cou                                                    object->ui_button_value = cou
                                        }                                                                                }
                                }                                                                                }
                        }                                                                                }
                 }                                                                                }
                        break;                                                                           break;
 
                case ui_slider: /* perform manipulation on slider widget */                      case ui_slider: /* perform manipulation on slider widget */
                        /* this code only needed for direct-control of slider                            /* this code only needed for direct-control of slider
                        /* NOTE: this crudely assumes vertically aligned slid                            /* NOTE: this crudely assumes vertically aligned slid
 
                        /* BUTTON-trigger: when left button is pressed, grab                             /* BUTTON-trigger: when left button is pressed, grab 
                        /* NOTE: should also have a contact-trigger version *                            /* NOTE: should also have a contact-trigger version *
                        if (vrGet2switchValue(1)) {                                                      if (vrGet2switchValue(1)) {
                                object->ui_valuator_value = (wand_rw_location                                    object->ui_valuator_value = (wand_rw_location
                                /* put limits on how far the grab-bar moves *                                    /* put limits on how far the grab-bar moves *
                                if (object->ui_valuator_value > 1.0)                                             if (object->ui_valuator_value > 1.0)
                                        object->ui_valuator_value = 1.0;                                                 object->ui_valuator_value = 1.0;
                                if (object->ui_valuator_value < -1.0)                                            if (object->ui_valuator_value < -1.0)
                                        object->ui_valuator_value = -1.0;                                                object->ui_valuator_value = -1.0;
                        }                                                                                }
                        break;                                                                           break;
 
                case ui_lever: /* perform manipulation on lever widget */                        case ui_lever: /* perform manipulation on lever widget */
                        /* this code only needed for direct-control of lever                             /* this code only needed for direct-control of lever 
                        /* NOTE: this crudely assumes horizontally aligned le                            /* NOTE: this crudely assumes horizontally aligned le
 
                        /* BUTTON-trigger: when left button is pressed, lever                            /* BUTTON-trigger: when left button is pressed, lever
                        /* NOTE: should also have a contact-trigger version *                            /* NOTE: should also have a contact-trigger version *
                        if (vrGet2switchValue(1)) {                                                      if (vrGet2switchValue(1)) {
                                object->ui_valuator_value = atanf((wand_rw_lo                                    object->ui_valuator_value = atanf((wand_rw_lo
 
                                /* put limits on how far the grab-bar moves *                                    /* put limits on how far the grab-bar moves *
                                if (object->ui_valuator_value > 1.0)                                             if (object->ui_valuator_value > 1.0)
                                        object->ui_valuator_value = 1.0;                                                 object->ui_valuator_value = 1.0;
                                if (object->ui_valuator_value < -1.0)                                            if (object->ui_valuator_value < -1.0)
                                        object->ui_valuator_value = -1.0;                                                object->ui_valuator_value = -1.0;
                        } else {                                                                         } else {
#ifdef LEVER_SNAPBACK                                                            #ifdef LEVER_SNAPBACK
                                object->ui_valuator_value  =  0.0;                                               object->ui_valuator_value  =  0.0;
#endif                                                                           #endif
                        }                                                                                }
                        break;                                                                           break;
 
                case ui_joyst: /* perform manipulation on joystick widget */                     case ui_joyst: /* perform manipulation on joystick widget */
                        /* this code only needed for direct-control of joysti                            /* this code only needed for direct-control of joysti
                        /* NOTE: this crudely assumes aligned joystick along                             /* NOTE: this crudely assumes aligned joystick along 
 
                        /* BUTTON-trigger: when left button is pressed, lever                            /* BUTTON-trigger: when left button is pressed, lever
                        /* NOTE: should also have a contact-trigger version *                            /* NOTE: should also have a contact-trigger version *
                        if (vrGet2switchValue(1)) {                                                      if (vrGet2switchValue(1)) {
                                object->ui_valuator_value  =  atanf((wand_rw_                                    object->ui_valuator_value  =  atanf((wand_rw_
                                object->ui_valuator2_value = -atanf((wand_rw_                                    object->ui_valuator2_value = -atanf((wand_rw_
 
                                /* put limits on how far the grab-bar moves *                                    /* put limits on how far the grab-bar moves *
                                if (object->ui_valuator_value > 1.0)                                             if (object->ui_valuator_value > 1.0)
                                        object->ui_valuator_value = 1.0;                                                 object->ui_valuator_value = 1.0;
                                if (object->ui_valuator_value < -1.0)                                            if (object->ui_valuator_value < -1.0)
                                        object->ui_valuator_value = -1.0;                                                object->ui_valuator_value = -1.0;
                                if (object->ui_valuator2_value > 1.0)                                            if (object->ui_valuator2_value > 1.0)
                                        object->ui_valuator2_value = 1.0;                                                object->ui_valuator2_value = 1.0;
                                if (object->ui_valuator2_value < -1.0)                                           if (object->ui_valuator2_value < -1.0)
                                        object->ui_valuator2_value = -1.0;                                               object->ui_valuator2_value = -1.0;
                        } else {                                                                         } else {
#ifdef JOY_SNAPBACK                                                              #ifdef JOY_SNAPBACK
                                object->ui_valuator_value  =  0.0;                                               object->ui_valuator_value  =  0.0;
                                object->ui_valuator2_value =  0.0;                                               object->ui_valuator2_value =  0.0;
#endif                                                                           #endif
                        }                                                                                }
                        break;                                                                           break;
                }                                                                                }
        }                                                                                }
        vrLockWriteRelease(wd->lock);                                                    vrLockWriteRelease(wd->lock);
 
        /******************************************************************/             /******************************************************************/
        /* store the current wand location for next time through the loop */             /* store the current wand location for next time through the loop */
        last_wand_vw_loc[VR_X] = wand_vw_location[VR_X];                                 last_wand_vw_loc[VR_X] = wand_vw_location[VR_X];
        last_wand_vw_loc[VR_Y] = wand_vw_location[VR_Y];                                 last_wand_vw_loc[VR_Y] = wand_vw_location[VR_Y];
        last_wand_vw_loc[VR_Z] = wand_vw_location[VR_Z];                                 last_wand_vw_loc[VR_Z] = wand_vw_location[VR_Z];
 
 
        /************************************************/                               /****************************/
        /** Handle Travel via wand and virtual devices **/                               /** Handle Travel via wand **/
        /************************************************/                               /****************************/
                                                                              
                                                                              
#if 0 /* set to one to demonstrate virtual device control of the joystick (it 
        vrLockWriteSet(wd->lock);                                             
        /* set the joystick's position from the slider and lever -- virtual d 
        wd->object[7].ui_valuator_value = wd->object[4].ui_valuator_value;    
        wd->object[7].ui_valuator2_value = wd->object[5].ui_valuator_value;   
        vrLockWriteRelease(wd->lock);                                         
#endif                                                                        
 
        vrLockReadSet(wd->lock);        /* lock while getting the UI values *            vrLockReadSet(wd->lock);        /* lock while getting the UI values *
        button_value = wd->object[3].ui_button_value;                                    joyst1_value = wd->object[4].ui_valuator_value;
        pushbutton_value = wd->object[8].ui_button_value;                                joyst2_value = wd->object[4].ui_valuator2_value;
        slider_value = wd->object[4].ui_valuator_value;                          /* TODO: obviously something needs fixing here -- one version was probably a 
        joyst1_value = wd->object[7].ui_valuator_value;                                  joyst1_value = 0.0;
        joyst2_value = wd->object[7].ui_valuator2_value;                                 joyst2_value = 0.0;
        vrLockReadRelease(wd->lock);                                                     vrLockReadRelease(wd->lock);
 
        /* only travel if UI-button is on */                                             /* only travel if travel is activated */
        if (button_value) {                                                              if (travel_active) {
                /* use wand joystick to fly through world */                                     /* use wand joystick to fly through world */
                joy_x = joyst1_value;                                                            joy_x = joyst1_value;
                joy_y = joyst2_value;                                                            joy_y = joyst2_value;
 
                if (fabs(joy_x) > JS_EPSILON)                                                    if (fabs(joy_x) > JS_EPSILON)
                        vrUserTravelRotateId(VR_ALLUSERS, VR_Y, (delta_time *                            vrUserTravelRotateId(VR_ALLUSERS, VR_Y, (delta_time *
 
                if (fabs(joy_y) > JS_EPSILON) {                                                  if (fabs(joy_y) > JS_EPSILON) {
                        delta_move = delta_time * SUB_JS_EPSILON(joy_y) * MOV                            delta_move = delta_time * SUB_JS_EPSILON(joy_y) * MOV
                        vrVectorGetRWFrom6sensorDir(&wand_rw_pointvec, WAND_S                            vrVectorGetRWFrom6sensorDir(&wand_rw_pointvec, WAND_S
                        vrUserTravelTranslate3d(VR_ALLUSERS,                                             vrUserTravelTranslate3d(VR_ALLUSERS,
                                wand_rw_pointvec.v[VR_X] * delta_move,                                           wand_rw_pointvec.v[VR_X] * delta_move,
                                wand_rw_pointvec.v[VR_Y] * delta_move,                                           wand_rw_pointvec.v[VR_Y] * delta_move,
                                wand_rw_pointvec.v[VR_Z] * delta_move);                                          wand_rw_pointvec.v[VR_Z] * delta_move);
                }                                                                                }
 
                /* pressing the right wand button or virtual push button rese                    /* pressing the right wand button resets us to the initial po
                /*   Do this last to avoid jitter effect */                                      if (vrGet2switchValue(2)) {
                if (vrGet2switchValue(3) || pushbutton_value) {               
                        vrUserTravelReset(VR_ALLUSERS);                                                  vrUserTravelReset(VR_ALLUSERS);
                }                                                                                }
        }                                                                                }
 
 
#ifdef USE_SOCKETS /* { */                                                       #ifdef USE_SOCKETS /* { */
        /*******************************/                                                /*******************************/
        /* Handle Commands from socket */                                                /* Handle Commands from socket */
 
        /* if no connection (and a listen socket is open), see if someone is             /* if no connection (and a listen socket is open), see if someone is 
        if (cmd_socket < 0 && listen_sock >= 0) {                                        if (cmd_socket < 0 && listen_sock >= 0) {
                /* cmd_socket will be -1 when no one is connected */                             /* cmd_socket will be -1 when no one is connected */
                cmd_socket = vrSocketAnswer(listen_sock);                                        cmd_socket = vrSocketAnswer(listen_sock);
                if (cmd_socket > 0) {                                                            if (cmd_socket > 0) {
                        printf("New client connected.\n");                                               printf("New client connected.\n");
                        vrSocketSendMsg(cmd_socket, "Your wish is my command                             vrSocketSendMsg(cmd_socket, "Your wish is my command 
                }                                                                                }
        }                                                                                }
 
        /* if a connection, see if client sent a command.  If so, act on it *            /* if a connection, see if client sent a command.  If so, act on it *
        if (cmd_socket > 0) {                                                            if (cmd_socket > 0) {
                result = vrSocketReadMsgClean(cmd_socket, buf, 128);                             result = vrSocketReadMsgClean(cmd_socket, buf, 128);
                switch (result) {                                                                switch (result) {
                case -1:                                                                         case -1:
                        break;                                                                           break;
                case  0:                                                                         case  0:
                        printf("Client stopped communicating.\n");                                       printf("Client stopped communicating.\n");
                        close(cmd_socket);                                                               close(cmd_socket);
                        cmd_socket = -1;                                                                 cmd_socket = -1;
                        break;                                                                           break;
                default:                                                                         default:
                        printf("socket cmd = '%s'\n", buf);                                              printf("socket cmd = '%s'\n", buf);
                        /* parse command here -- very simple-minded parsing *                            /* parse command here -- very simple-minded parsing *
                        if (strcmp(buf, "quit") == 0) {                                                  if (strcmp(buf, "quit") == 0) {
                                /* set the world for termination */                                              /* set the world for termination */
                                wd->quit_bit = 1;                                                                wd->quit_bit = 1;
                        } else                                                                           } else
                        if (strcmp(buf, "help") == 0 || strcmp(buf, "?") == 0 
                                /* give usage information */                  
                                vrSocketSendMsg(cmd_socket, help_msg);        
                        } else                                                
                        if (strcmp(buf, "close") == 0) {                                                 if (strcmp(buf, "close") == 0) {
                                /* close socket connection */                                                    /* close socket connection */
                                printf("Client ending communication.\n");                                        printf("Client ending communication.\n");
                                close(cmd_socket);                                                               close(cmd_socket);
                                cmd_socket = -1;                                                                 cmd_socket = -1;
                        } else                                                                           } else
                        if (strcmp(buf, "reset") == 0) {                                                 if (strcmp(buf, "reset") == 0) {
                                /* make the world as it was in the beginning                                     /* make the world as it was in the beginning 
                                init_objects(wd);                                                                init_objects(wd);
                                vrUserTravelReset(VR_ALLUSERS);                                                  vrUserTravelReset(VR_ALLUSERS);
                        } else                                                                           } else
                        if (strcmp(buf, "button?") == 0) {                                               if (strcmp(buf, "button?") == 0) {
                                /* report the user-interface button value */                                     /* report the user-interface button value */
                                sprintf(msg, "The button is %s.\n", (wd->obje                                    sprintf(msg, "The button is %s.\n", (wd->obje
                                vrSocketSendMsg(cmd_socket, msg);                                                vrSocketSendMsg(cmd_socket, msg);
                        } else                                                                           } else
                        if (strcmp(buf, "button on") == 0) {                                             if (strcmp(buf, "control?") == 0) {
                                /* turn the user-interface button on */       
                                wd->object[3].ui_button_value = 1;            
                        } else                                                
                        if (strcmp(buf, "button off") == 0) {                 
                                /* turn the user-interface button on */       
                                wd->object[3].ui_button_value = 0;            
                        } else                                                
                        if (strcmp(buf, "pushbutton?") == 0) {                
                                /* report the user-interface pushbutton value 
                                sprintf(msg, "The pushbutton is %s.\n", (wd-> 
                                vrSocketSendMsg(cmd_socket, msg);             
                        } else                                                
                        if (strcmp(buf, "pushbutton on") == 0) {              
                                /* turn the user-interface pushbutton on */   
                                wd->object[8].ui_button_value = 1;            
                        } else                                                
                        if (strcmp(buf, "pushbutton off") == 0) {             
                                /* turn the user-interface pushbutton on */   
                                wd->object[8].ui_button_value = 0;            
                        } else                                                
                        if (strcmp(buf, "radio?") == 0) {                     
                                /* report the user-interface radio-button val                                    /* report the user-interface radio-button val
                                sprintf(msg, "The radio button is %d.\n", wd-                                    sprintf(msg, "The radio button is %d.\n", wd-
                                vrSocketSendMsg(cmd_socket, msg);                                                vrSocketSendMsg(cmd_socket, msg);
                        } else                                                                           } else
                        if (strncmp(buf, "radio ", 6) == 0) {                                            if (strncmp(buf, "control ", 8) == 0) {
                                /* set the user-interface radio-button value                                     /* set the user-interface radio-button value 
                                wd->object[6].ui_button_value = atoi(&(buf[6]                                    wd->object[3].ui_button_value = atoi(&(buf[8]
                        } else                                                
                        if (strcmp(buf, "slider?") == 0) {                    
                                /* report the user-interface slider value */  
                                sprintf(msg, "The slider is at %.2f.\n", wd-> 
                                vrSocketSendMsg(cmd_socket, msg);             
                        } else                                                
                        if (strncmp(buf, "slider ", 7) == 0) {                
                                /* set the user-interface slider value */     
                                wd->object[4].ui_valuator_value = atof(&(buf[ 
                        } else                                                
                        if (strcmp(buf, "lever?") == 0) {                     
                                /* report the user-interface lever value */   
                                sprintf(msg, "The lever is at %.2f.\n", wd->o 
                                vrSocketSendMsg(cmd_socket, msg);             
                        } else                                                
                        if (strncmp(buf, "lever ", 6) == 0) {                 
                                /* set the user-interface lever value */      
                                wd->object[5].ui_valuator_value = atof(&(buf[ 
                        } else                                                                           } else
                        if (strcmp(buf, "joyst?") == 0) {                                                if (strcmp(buf, "joyst?") == 0) {
                                /* report the user-interface joystick value *                                    /* report the user-interface joystick value *
                                sprintf(msg, "The joystick is at %.2f, %.2f.\                                    sprintf(msg, "The joystick is at %.2f, %.2f.\
                                vrSocketSendMsg(cmd_socket, msg);                                                vrSocketSendMsg(cmd_socket, msg);
                        } else                                                                           } else
                        if (strncmp(buf, "joyst1 ", 7) == 0) {                                           if (strncmp(buf, "joyst1 ", 7) == 0) {
                                /* set the user-interface joystick value */                                      /* set the user-interface joystick value */
                                wd->object[7].ui_valuator_value = atof(&(buf[                                    wd->object[5].ui_valuator_value = atof(&(buf[
                        } else                                                                           } else
                        if (strncmp(buf, "joyst2 ", 7) == 0) {                                           if (strncmp(buf, "joyst2 ", 7) == 0) {
                                /* set the user-interface joystick value */                                      /* set the user-interface joystick value */
                                wd->object[7].ui_valuator2_value = atof(&(buf                                    wd->object[5].ui_valuator2_value = atof(&(buf
                        } else                                                                           } else
                        if (strcmp(buf, "move cube up") == 0) {                                          if (strcmp(buf, "object?") == 0) {
                                /* move the blue cube up 2.0 units */                                            /* report the selected object */
                                wd->object[0].y += 2.0;                                                          sprintf(msg, "Object %d is currently selected
                                                                                                                 vrSocketSendMsg(cmd_socket, msg);
                        } else                                                                           } else
                        if (strcmp(buf, "move cube down") == 0) {                                        if (strncmp(buf, "object ", 7) == 0) {
                                /* move the blue cube down 2.0 units */                                          /* set the selected object */
                                wd->object[0].y -= 2.0;                                                          wd->selected_object = atoi(&(buf[7]));
                                                                                                                 wd->object[4].ui_button_value = wd->selected_
                                                                                                         } else
                                                                                                         if (strcmp(buf, "obj?") == 0) {
                                                                                                                 /* report the selected object */
                                                                                                                 if (wd->selected_object != -1)
                                                                                                                         sprintf(msg, "Object %d is currently 
                                                                                                                                 wd->selected_object,
                                                                                                                                 wd->object[wd->selected_objec
                                                                                                                                 wd->object[wd->selected_objec
                                                                                                                                 wd->object[wd->selected_objec
                                                                                                                 else    sprintf(msg, "No object is currently 
                                                                                                                 vrSocketSendMsg(cmd_socket, msg);
                                                                                                         } else
                                                                                                         if (strncmp(buf, "up ", 3) == 0) {
                                                                                                                 /* move the selected object up 1.0 units */
                                                                                                                 if (wd->selected_object != -1)
                                                                                                                         wd->object[wd->selected_object].y += 
                                                                                                         } else
                                                                                                         if (strncmp(buf, "down ", 5) == 0) {
                                                                                                                 /* move the selected object down 1.0 units */
                                                                                                                 if (wd->selected_object != -1)
                                                                                                                         wd->object[wd->selected_object].y -= 
                                                                                                         } else
                                                                                                         if (strncmp(buf, "left ", 5) == 0) {
                                                                                                                 /* move the selected object up 1.0 units */
                                                                                                                 if (wd->selected_object != -1)
                                                                                                                         wd->object[wd->selected_object].x -= 
                                                                                                         } else
                                                                                                         if (strncmp(buf, "right ", 6) == 0) {
                                                                                                                 /* move the selected object down 1.0 units */
                                                                                                                 if (wd->selected_object != -1)
                                                                                                                         wd->object[wd->selected_object].x += 
                                                                                                         } else
                                                                                                         if (strncmp(buf, "in ", 3) == 0) {
                                                                                                                 /* move the selected object down 1.0 units */
                                                                                                                 if (wd->selected_object != -1)
                                                                                                                         wd->object[wd->selected_object].z -= 
                                                                                                         } else
                                                                                                         if (strncmp(buf, "out ", 4) == 0) {
                                                                                                                 /* move the selected object up 1.0 units */
                                                                                                                 if (wd->selected_object != -1)
                                                                                                                         wd->object[wd->selected_object].z += 
                        } else                                                                           } else
                        if (strcmp(buf, "where") == 0 || strcmp(buf, "where a                            if (strcmp(buf, "where") == 0 || strcmp(buf, "where a
                                /* report the user's location */                                                 /* report the user's location */
                                vrMatrix        *headmat;                                                        vrMatrix        *headmat;
                                vrPoint         headloc;                                                         vrPoint         headloc;
 
                                headmat = vrMatrixCreate();                                                      headmat = vrMatrixCreate();
                                vrMatrixGetRWFromUserHead(headmat, 0);                                           vrMatrixGetRWFromUserHead(headmat, 0);
                                vrPointGetVWFromUserMatrix(&headloc, 0, headm                                    vrPointGetVWFromUserMatrix(&headloc, 0, headm
                                sprintf(msg, "You are at (%f %f %f).\n", head                                    sprintf(msg, "You are at (%f %f %f).\n", head
                                vrSocketSendMsg(cmd_socket, msg);                                                vrSocketSendMsg(cmd_socket, msg);
                        } else                                                                           } else
                        if (strcmp(buf, "show ActiveWalls") == 0) {                                      if (strcmp(buf, "show ActiveWalls") == 0) {
                                /* report the type of graphics (VR) display *                                    /* report the type of graphics (VR) display *
                                sprintf(msg, "Application has %d active walls                                    sprintf(msg, "Application has %d active walls
                                vrSocketSendMsg(cmd_socket, msg);                                                vrSocketSendMsg(cmd_socket, msg);
                        } else                                                                           } else
                        /* default: */ {                                                                 /* default: */ {
                                vrSocketSendMsg(cmd_socket, "Unknown command.                                    vrSocketSendMsg(cmd_socket, "Unknown command.
                        }                                                                                }
 
                        /* prompt for another command (if socket still open)                             /* prompt for another command (if socket still open) 
                        if (cmd_socket > 0) {                                                            if (cmd_socket > 0) {
                                vrSocketSendMsg(cmd_socket, "Your wish is my                                     vrSocketSendMsg(cmd_socket, "Your wish is my 
                        }                                                                                }
                }                                                                                }
        }                                                                                }
#endif /* } USE_SOCKETS */                                                       #endif /* } USE_SOCKETS */
 
        /*********************************/                                              /*********************************/
        /* Handle Commands from keyboard */                                              /* Handle Commands from keyboard */
        if (vrGet2switchValue(0)) {                                                      if (vrGet2switchValue(0)) {
                wd->quit_bit = 1;                                                                wd->quit_bit = 1;
        }                                                                                }
 
        /****************************************************/                           /****************************************************/
        /* yield to allow other processes access to the CPU */                           /* yield to allow other processes access to the CPU */
        vrSleep(0);                                                                      vrSleep(0);
}                                                                                }
 
 
 
/* ----------------8<-----------------8<-----------------8<----------------*/    /* ----------------8<-----------------8<-----------------8<----------------*/
/* In a non-example applicatation, the following would be a separate file. */    /* In a non-example applicatation, the following would be a separate file. */
 
                /**************************/                                                     /**************************/
                /**************************/                                                     /**************************/
                /** The Graphics section **/                                                     /** The Graphics section **/
                /**************************/                                                     /**************************/
                /**************************/                                                     /**************************/
 
/* functions from wrs_shapes.c */                                                /* functions from wrs_shapes.c */
void    draw_floor();                                                            void    draw_floor();
void    draw_cube();                                                             void    draw_cube();
void    draw_pyramid();                                                          void    draw_pyramid();
void    draw_cube_outline();                                                     void    draw_cube_outline();
void    draw_pyramid_outline();                                                  void    draw_pyramid_outline();
void    draw_box_outlineonly(float x2, float x1, float y2, float y1, float z2    void    draw_box_outlineonly(float x2, float x1, float y2, float y1, float z2
 
 
/*********************************************************************/          /*********************************************************************/
/* init_gfx(): initialize general graphics properties (eg. lighting) */          /* init_gfx(): initialize general graphics properties (eg. lighting) */
/*********************************************************************/          /*********************************************************************/
void init_gfx()                                                                  void init_gfx()
{                                                                                {
        GLfloat location_0[4] = { 0.0, 10.0, 10.0, 1.0 /* 0 = directional, 1             GLfloat location_0[4] = { 0.0, 10.0, 10.0, 1.0 /* 0 = directional, 1 
                ambient_0[4] = { 0.2, 0.2, 0.2, 1.0 },                                           ambient_0[4] = { 0.2, 0.2, 0.2, 1.0 },
                diffuse_0[4] = { 0.8, 0.8, 0.8, 1.0 },                                           diffuse_0[4] = { 0.8, 0.8, 0.8, 1.0 },
                specular_0[4] = { 0.2, 0.2, 0.2, 1.0 };                                          specular_0[4] = { 0.2, 0.2, 0.2, 1.0 };
 
        /****************************************/                                       /****************************************/
        /* set the render initialization values */                                       /* set the render initialization values */
        glClearColor(0.0, 0.0, 0.0, 0.0);                                                glClearColor(0.0, 0.0, 0.0, 0.0);
        glClearDepth(1.0);                                                               glClearDepth(1.0);
 
        /********************************************************/                       /********************************************************/
        /* set the polygon shading/lighting/material parameters */                       /* set the polygon shading/lighting/material parameters */
        glShadeModel(GL_SMOOTH);                                                         glShadeModel(GL_SMOOTH);
 
        glEnable(GL_LIGHTING);                                                           glEnable(GL_LIGHTING);
 
        glLightfv(GL_LIGHT0, GL_POSITION, location_0);                                   glLightfv(GL_LIGHT0, GL_POSITION, location_0);
        glLightfv(GL_LIGHT0, GL_AMBIENT, ambient_0);                                     glLightfv(GL_LIGHT0, GL_AMBIENT, ambient_0);
        glLightfv(GL_LIGHT0, GL_DIFFUSE, diffuse_0);                                     glLightfv(GL_LIGHT0, GL_DIFFUSE, diffuse_0);
        glLightfv(GL_LIGHT0, GL_SPECULAR, specular_0);                                   glLightfv(GL_LIGHT0, GL_SPECULAR, specular_0);
        glEnable(GL_LIGHT0);                                                             glEnable(GL_LIGHT0);
 
        /* These two lines cause the vertex colors to be used (otherwise all             /* These two lines cause the vertex colors to be used (otherwise all 
        glColorMaterial(GL_FRONT, GL_AMBIENT_AND_DIFFUSE);                               glColorMaterial(GL_FRONT, GL_AMBIENT_AND_DIFFUSE);
        glEnable(GL_COLOR_MATERIAL);                                                     glEnable(GL_COLOR_MATERIAL);
 
        glEnable(GL_NORMALIZE); /* this is required when calling glScalef() w            glEnable(GL_NORMALIZE); /* this is required when calling glScalef() w
 
        /***************************/                                                    /***************************/
        /* set the line parameters */                                                    /* set the line parameters */
        glEnable(GL_LINE_SMOOTH);                                                        glEnable(GL_LINE_SMOOTH);
        glLineWidth(2.0);                                                                glLineWidth(2.0);
}                                                                                }
 
 
/*******************************************************************/            /*******************************************************************/
/* draw_world(): Now will render how ever many objects are in the  */            /* draw_world(): Now will render how ever many objects are in the  */
/*   world data structure.  The color, type (and maybe rotation)   */            /*   world data structure.  The color, type (and maybe rotation)   */
/*   are all now stored for each object, in addition to location.  */            /*   are all now stored for each object, in addition to location.  */
/*******************************************************************/            /*******************************************************************/
void draw_world(WorldDataType *wd, vrRenderInfo *rendinfo)                       void draw_world(WorldDataType *wd, vrRenderInfo *rendinfo)
{                                                                                {
static  GLfloat         location_0[4] = { 0.0, 10.0, 0.0, 1.0 /* 0 = directio    static  GLfloat         location_0[4] = { 0.0, 10.0, 0.0, 1.0 /* 0 = directio
static  char            msg[128];                       /* memory for text st    static  char            msg[128];                       /* memory for text st
        int             objnum;                         /* object counter */             int             objnum;                         /* object counter */
        ObjectType      *object;                        /* pointer to current            ObjectType      *object;                        /* pointer to current
        float           size;                           /* size of current ob            float           size;                           /* size of current ob
 
        /**************************************/                                         /**************************************/
        /* clear the screen -- very important */                                         /* clear the screen -- very important */
        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);                              glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
 
        /********************************************************************            /********************************************************************
        /* update the light's location -- must be done independently for each            /* update the light's location -- must be done independently for each
        glLightfv(GL_LIGHT0, GL_POSITION, location_0);                                   glLightfv(GL_LIGHT0, GL_POSITION, location_0);
 
        /************************************/                                           /************************************/
        /* draw a short pointer at the wand */                                           /* draw a short pointer at the wand */
        glPushMatrix();                                                                  glPushMatrix();
                glColor3ub(100, 255, 255);      /* cyan */                                       glColor3ub(100, 255, 255);      /* cyan */
                vrRenderTransform6sensor(rendinfo, WAND_SENSOR);                                 vrRenderTransform6sensor(rendinfo, WAND_SENSOR);
                glRotatef(-90.0, 1.0, 0.0, 0.0);                                                 glRotatef(-90.0, 1.0, 0.0, 0.0);
                glScalef(0.15, 0.15, 0.15);                                                      glScalef(0.15, 0.15, 0.15);
                glTranslatef(0.0, -1.0, 0.0);   /* move the tip to (0,0,0) */                    glTranslatef(0.0, -1.0, 0.0);   /* move the tip to (0,0,0) */
                draw_pyramid_outline();                                                          draw_pyramid_outline();
        glPopMatrix();                                                                   glPopMatrix();
 
        /********************************************************/                       /********************************************************/
        /* draw all the objects, taking care to put each one in */                       /* draw all the objects, taking care to put each one in */
        /*   the proper coordinate system (virtual world space  */                       /*   the proper coordinate system (virtual world space  */
        /*   vs. real world space for the user-interface).      */                       /*   vs. real world space for the user-interface).      */
 
        /* draw the floor */                                                             /* draw the floor */
        glPushMatrix();                                                                  glPushMatrix();
                vrRenderTransformUserTravel(rendinfo);  /* change to virtual-                    vrRenderTransformUserTravel(rendinfo);  /* change to virtual-
                draw_floor();                                                                    draw_floor();
        glPopMatrix();                                                                   glPopMatrix();
 
        vrLockReadSet(wd->lock);        /* lock while reading info about obje            vrLockReadSet(wd->lock);        /* lock while reading info about obje
        for (objnum = 0; objnum < wd->number_of_objects; objnum++) {                     for (objnum = 0; objnum < wd->number_of_objects; objnum++) {
                object = &(wd->object[objnum]);                                                  object = &(wd->object[objnum]);
 
                                                                                                 /* some UI objects we hide when unused */
                                                                                                 if (wd->object[3].ui_button_value != 2) {
                                                                                
                                                                                                         /* unless doing virtual control, don't show the selec
                                                                                                         if (objnum == 4 || objnum == 5 /* || objnum == 6 not 
                                                                                                                 continue;
                                                                                                 }
                                                                                
                                                                                                 /* now render the object */
                glColor3ubv(object->color);                                                      glColor3ubv(object->color);
                glPushMatrix();                                                                  glPushMatrix();
                        size = object->size;                                                             size = object->size;
 
                        switch (object->type) {                                                          switch (object->type) {
 
                        case vw_normal: /* render normal object (in virtual w                            case vw_normal: /* render normal object (in virtual w
                                vrRenderTransformUserTravel(rendinfo);  /* ch                                    vrRenderTransformUserTravel(rendinfo);  /* ch
                                glTranslatef(object->x, object->y, object->z)                                    glTranslatef(object->x, object->y, object->z)
                                glScalef(size, size, size);                                                      glScalef(size, size, size);
 
                                switch (object->shape) {                                                         switch (object->shape) {
                                case cube:                                                                       case cube:
                                        if (objnum == wd->contacted_object)                                              if (objnum == wd->selected_object)
                                                draw_cube_outline();                                                             draw_cube_outline();
                                        else    draw_cube();                                                             else    draw_cube();
                                        break;                                                                           break;
                                case sphere:                                                                     case sphere:
                                        if (objnum == wd->contacted_object)                                              if (objnum == wd->selected_object)
                                                draw_sphere_outline();                                                           draw_sphere_outline();
                                        else    draw_sphere();                                                           else    draw_sphere();
                                        break;                                                                           break;
                                case pyramid:                                                                    case pyramid:
                                        if (objnum == wd->contacted_object)                                              if (objnum == wd->selected_object)
                                                draw_pyramid_outline();                                                          draw_pyramid_outline();
                                        else    draw_pyramid();                                                          else    draw_pyramid();
                                        break;                                                                           break;
                                case ud_pyramid:                                                                 case ud_pyramid:
                                        glScalef(1.0, -1.0, 1.0);                                                        glScalef(1.0, -1.0, 1.0);
                                        if (objnum == wd->contacted_object)                                              if (objnum == wd->selected_object)
                                                draw_pyramid_outline();                                                          draw_pyramid_outline();
                                        else    draw_pyramid();                                                          else    draw_pyramid();
                                        break;                                                                           break;
                                }                                                                                }
                                break;                                                                           break;
 
                        case ui_button: /* render button widget (in real worl                            case ui_button: /* render button widget (in real worl
                                /* widgets remain in real-world coordinates *                                    /* widgets remain in real-world coordinates *
                                glTranslatef(object->x, object->y, object->z)                                    glTranslatef(object->x, object->y, object->z)
#ifdef DRAW_UITEXT /* { */                                                       #ifdef DRAW_UITEXT /* { */
                                glPushMatrix();                                                                  glPushMatrix();
                                        glTranslatef(0.0, -(size + 0.5), 0.0)                                            glTranslatef(0.0, -(size + 0.5), 0.0)
 
                                        glRasterPos3f(0.0, 0.0, 0.0);   /* go                                            glRasterPos3f(0.0, 0.0, 0.0);   /* go
                                        if (object->ui_button_value)                                                     if (object->ui_button_value)
                                                vrRenderText(rendinfo, "on");                                                    vrRenderText(rendinfo, "on");
                                        else    vrRenderText(rendinfo, "off")                                            else    vrRenderText(rendinfo, "off")
                                glPopMatrix();                                                                   glPopMatrix();
#endif /* } DRAW_UITEXT */                                                       #endif /* } DRAW_UITEXT */
                                glScalef(size, size, size);                                                      glScalef(size, size, size);
                                glPushMatrix();                                                                  glPushMatrix();
 
                                        /* for now we'll ignore shape and all                                            /* for now we'll ignore shape and all
 
                                        /* draw the base box */                                                          /* draw the base box */
                                        if (objnum == wd->contacted_object)                                              if (objnum == wd->contacted_object)
                                                draw_cube_outline();                                                             draw_cube_outline();
                                        else    draw_cube();                                                             else    draw_cube();
 
                                        /* draw the button part */                                                       /* draw the button part */
                                        if (object->ui_button_value) {                                                   if (object->ui_button_value) {
                                                /* button is pressed (so bare                                                    /* button is pressed (so bare
 
                                                glTranslatef(0.4, 0.0, 0.0);                                                     glTranslatef(0.4, 0.0, 0.0);
                                                /* move color halfway to whit                                                    /* move color halfway to whit
                                                glColor3ub(                                                                      glColor3ub(     
                                                        object->color[0] + ((                                                            object->color[0] + ((
                                                        object->color[1] + ((                                                            object->color[1] + ((
                                                        object->color[2] + ((                                                            object->color[2] + ((
                                        } else {                                                                         } else {
                                                /* button is not pressed (so                                                     /* button is not pressed (so 
 
                                                glTranslatef(0.8, 0.0, 0.0);                                                     glTranslatef(0.8, 0.0, 0.0);
                                                /* move color halfway to blac                                                    /* move color halfway to blac
                                                glColor3ub(object->color[0]/2                                                    glColor3ub(object->color[0]/2
                                        }                                                                                }
                                        glScalef(0.7, 0.7, 0.7);                                                         glScalef(0.7, 0.7, 0.7);
                                        draw_cube_outline();                                                             draw_cube_outline();
                                glPopMatrix();                                                                   glPopMatrix();
 
                                break;                                                                           break;
 
                        case ui_pushbut: /* render button widget (in real wor                            case ui_pushbut: /* render button widget (in real wor
                                /* push buttons are rendered a little differe                                    /* push buttons are rendered a little differe
                                /*   button surface is on the top, and is sph                                    /*   button surface is on the top, and is sph
                                /*   cubic.                                                                      /*   cubic.                                  
                                glTranslatef(object->x, object->y, object->z)                                    glTranslatef(object->x, object->y, object->z)
#ifdef DRAW_UITEXT /* { */                                                       #ifdef DRAW_UITEXT /* { */
                                glPushMatrix();                                                                  glPushMatrix();
                                        glTranslatef(0.0, -(size + 0.5), 0.0)                                            glTranslatef(0.0, -(size + 0.5), 0.0)
 
                                        glRasterPos3f(0.0, 0.0, 0.0);   /* go                                            glRasterPos3f(0.0, 0.0, 0.0);   /* go
                                        if (object->ui_button_value)                                                     if (object->ui_button_value)
                                                vrRenderText(rendinfo, "on");                                                    vrRenderText(rendinfo, "on");
                                        else    vrRenderText(rendinfo, "off")                                            else    vrRenderText(rendinfo, "off")
                                glPopMatrix();                                                                   glPopMatrix();
#endif /* } DRAW_UITEXT */                                                       #endif /* } DRAW_UITEXT */
                                glScalef(size, size, size);                                                      glScalef(size, size, size);
                                glPushMatrix();                                                                  glPushMatrix();
 
                                        /* for now we'll ignore shape and all                                            /* for now we'll ignore shape and all
 
                                        /* draw the base box */                                                          /* draw the base box */
                                        if (objnum == wd->contacted_object)                                              if (objnum == wd->contacted_object)
                                                draw_cube_outline();                                                             draw_cube_outline();
                                        else    draw_cube();                                                             else    draw_cube();
 
                                        /* draw the button part */                                                       /* draw the button part */
                                        if (object->ui_button_value) {                                                   if (object->ui_button_value) {
                                                /* button is pressed (so bare                                                    /* button is pressed (so bare
 
                                                glTranslatef(0.0, 0.6, 0.0);                                                     glTranslatef(0.0, 0.6, 0.0);
                                                /* move color halfway to whit                                                    /* move color halfway to whit
                                                glColor3ub(                                                                      glColor3ub(     
                                                        object->color[0] + ((                                                            object->color[0] + ((
                                                        object->color[1] + ((                                                            object->color[1] + ((
                                                        object->color[2] + ((                                                            object->color[2] + ((
                                        } else {                                                                         } else {
                                                /* button is not pressed (so                                                     /* button is not pressed (so 
 
                                                glTranslatef(0.0, 0.9, 0.0);                                                     glTranslatef(0.0, 0.9, 0.0);
                                                /* move color halfway to blac                                                    /* move color halfway to blac
                                                glColor3ub(object->color[0]/2                                                    glColor3ub(object->color[0]/2
                                        }                                                                                }
                                        glScalef(0.7, 0.7, 0.7);                                                         glScalef(0.7, 0.7, 0.7);
                                        draw_sphere_outline();                                                           draw_sphere_outline();
                                glPopMatrix();                                                                   glPopMatrix();
 
                                break;                                                                           break;
 
                        case ui_radio: { /* render radio-button widget (in re                            case ui_radio: { /* render radio-button widget (in re
                                int     count;                                                                   int     count;
 
                                glTranslatef(object->x, object->y, object->z)                                    glTranslatef(object->x, object->y, object->z)
                                glScalef(size, size, size);                                                      glScalef(size, size, size);
 
                                /* for now we'll ignore shape and all buttons                                    /* for now we'll ignore shape and all buttons
                                for (count = 0; count < object->ui_num_button                                    for (count = 0; count < object->ui_num_button
                                        glPushMatrix();                                                                  glPushMatrix();
                                                glTranslatef(0.0, ((object->u                                                    glTranslatef(0.0, ((object->u
 
                                                /* draw the base box */                                                          /* draw the base box */
                                                glColor3ubv(object->color);                                                      glColor3ubv(object->color);
                                                glScalef(1.0, 1.0, 1.0);                                                         glScalef(1.0, 1.0, 1.0);
                                                if (objnum == wd->contacted_o                                                    if (objnum == wd->contacted_o
                                                        draw_cube_outline();                                                             draw_cube_outline();
                                                else    draw_cube();                                                             else    draw_cube();
 
                                                /* draw the button part */                                                       /* draw the button part */
                                                if (object->ui_button_value =                                                    if (object->ui_button_value =
                                                        /* this button is pre                                                            /* this button is pre
 
                                                        glTranslatef(0.4, 0.0                                                            glTranslatef(0.4, 0.0
                                                        /* move color halfway                                                            /* move color halfway
                                                        glColor3ub(                                                                      glColor3ub(     
                                                                object->color                                                                    object->color
                                                                object->color                                                                    object->color
                                                                object->color                                                                    object->color
                                                } else {                                                                         } else {
                                                        /* this button is not                                                            /* this button is not
 
                                                        glTranslatef(0.8, 0.0                                                            glTranslatef(0.8, 0.0
                                                        /* move color halfway                                                            /* move color halfway
                                                        glColor3ub(object->co                                                            glColor3ub(object->co
                                                }                                                                                }
#ifdef DRAW_UITEXT /* { */                                                       #ifdef DRAW_UITEXT /* { */
                                                glPushMatrix();                                                                  glPushMatrix();
                                                glTranslatef(0.0, 0.0, -1.5);                                                    glTranslatef(0.0, 0.0, -1.5);
                                                glRasterPos3f(0.0, 0.0, 0.0);                                                    glRasterPos3f(0.0, 0.0, 0.0);
                                                vrRenderText(rendinfo, object                                                    vrRenderText(rendinfo, object
                                                glPopMatrix();                                                                   glPopMatrix();
#endif /* } DRAW_UITEXT */                                                       #endif /* } DRAW_UITEXT */
                                                glScalef(0.7, 0.7, 0.7);                                                         glScalef(0.7, 0.7, 0.7);
                                                draw_cube_outline();                                                             draw_cube_outline();
                                        glPopMatrix();                                                                   glPopMatrix();
                                }                                                                                }
                          }                                                                                }
                                break;                                                                           break;
 
                        case ui_slider: /* render slider widget (in real worl                            case ui_slider: /* render slider widget (in real worl
                                glTranslatef(object->x, object->y, object->z)                                    glTranslatef(object->x, object->y, object->z)
#ifdef DRAW_UITEXT /* { */                                                       #ifdef DRAW_UITEXT /* { */
                                glPushMatrix();                                                                  glPushMatrix();
                                        glTranslatef(0.0, -SLIDER_LENGTH * si                                            glTranslatef(0.0, -SLIDER_LENGTH * si
 
                                        sprintf(msg, "%5.2f", object->ui_valu                                            sprintf(msg, "%5.2f", object->ui_valu
                                        glRasterPos3f(0.0, 0.0, 0.0);   /* go                                            glRasterPos3f(0.0, 0.0, 0.0);   /* go
                                        vrRenderText(rendinfo, msg);                                                     vrRenderText(rendinfo, msg);
                                glPopMatrix();                                                                   glPopMatrix();
#endif /* } DRAW_UITEXT */                                                       #endif /* } DRAW_UITEXT */
                                glScalef(size, size, size);                                                      glScalef(size, size, size);
 
                                /* for now we'll ignore shape and all sliders                                    /* for now we'll ignore shape and all sliders
                                glPushMatrix();                                                                  glPushMatrix();
                                        /* the sliding rod */                                                            /* the sliding rod */
                                        glScalef(0.2, SLIDER_LENGTH, 0.2);                                               glScalef(0.2, SLIDER_LENGTH, 0.2);
                                        if (objnum == wd->contacted_object)                                              if (objnum == wd->contacted_object)
                                                draw_cube_outline();                                                             draw_cube_outline();
                                        else    draw_cube();                                                             else    draw_cube();
                                glPopMatrix();                                                                   glPopMatrix();
 
                                glPushMatrix();                                                                  glPushMatrix();
                                        /* the value marker */                                                           /* the value marker */
                                        glColor3ub(object->color[0]/2, object                                            glColor3ub(object->color[0]/2, object
                                        glTranslatef(0.0, object->ui_valuator                                            glTranslatef(0.0, object->ui_valuator
                                        glScalef(1.0, 0.2, 1.0);                                                         glScalef(1.0, 0.2, 1.0);
                                        draw_cube_outline();                                                             draw_cube_outline();
                                glPopMatrix();                                                                   glPopMatrix();
                                glPushMatrix();                                                                  glPushMatrix();
                                        glTranslatef(0.0, object->ui_valuator                                            glTranslatef(0.0, object->ui_valuator
                                        glScalef(0.201, 0.201, 0.201);                                                   glScalef(0.201, 0.201, 0.201);
                                        draw_cube_outline();                                                             draw_cube_outline();
                                glPopMatrix();                                                                   glPopMatrix();
 
                                break;                                                                           break;
 
                        case ui_lever: /* render lever widget (in real world                             case ui_lever: /* render lever widget (in real world 
                                glTranslatef(object->x, object->y, object->z)                                    glTranslatef(object->x, object->y, object->z)
#ifdef DRAW_UITEXT /* { */                                                       #ifdef DRAW_UITEXT /* { */
                                glPushMatrix();                                                                  glPushMatrix();
                                        glTranslatef(0.0, -1.0 * size - 0.5,                                             glTranslatef(0.0, -1.0 * size - 0.5, 
 
                                        sprintf(msg, "%5.2f", object->ui_valu                                            sprintf(msg, "%5.2f", object->ui_valu
                                        glRasterPos3f(0.0, 0.0, 0.0);   /* go                                            glRasterPos3f(0.0, 0.0, 0.0);   /* go
                                        vrRenderText(rendinfo, msg);                                                     vrRenderText(rendinfo, msg);
                                glPopMatrix();                                                                   glPopMatrix();
#endif /* } DRAW_UITEXT */                                                       #endif /* } DRAW_UITEXT */
                                glScalef(size, size, size);                                                      glScalef(size, size, size);
 
                                /* for now we'll ignore shape and all sliders                                    /* for now we'll ignore shape and all sliders
                                glPushMatrix();                                                                  glPushMatrix();
                                        /* the lever base */                                                             /* the lever base */
                                        glScalef(1.0, 0.5, 0.2);                                                         glScalef(1.0, 0.5, 0.2);
                                        if (objnum == wd->contacted_object)                                              if (objnum == wd->contacted_object)
                                                draw_cube_outline();                                                             draw_cube_outline();
                                        else    draw_cube();                                                             else    draw_cube();
                                glPopMatrix();                                                                   glPopMatrix();
 
                                glPushMatrix();                                                                  glPushMatrix();
                                        /* the lever */                                                                  /* the lever */
                                        glColor3ub(object->color[0]/2, object                                            glColor3ub(object->color[0]/2, object
                                        glRotatef(90.0, 1.0, 0.0, 0.0);                                                  glRotatef(90.0, 1.0, 0.0, 0.0);
 
                                        glRotatef(object->ui_valuator_value *                                            glRotatef(object->ui_valuator_value *
                                        glTranslatef(0.0, LEVER_ARM_LENGTH, 0                                            glTranslatef(0.0, LEVER_ARM_LENGTH, 0
                                        glPushMatrix();                                                                  glPushMatrix();
                                                glScalef(0.1, LEVER_ARM_LENGT                                                    glScalef(0.1, LEVER_ARM_LENGT
                                                draw_pyramid_outline();                                                          draw_pyramid_outline();
                                        glPopMatrix();                                                                   glPopMatrix();
 
                                        /* a knob at the end of the lever */                                             /* a knob at the end of the lever */
                                        glColor3ubv(wd->object[objnum].color)                                            glColor3ubv(wd->object[objnum].color)
                                        glPushMatrix();                                                                  glPushMatrix();
                                                glTranslatef(0.0, LEVER_ARM_L                                                    glTranslatef(0.0, LEVER_ARM_L
                                                glScalef(LEVER_KNOB_SIZE, LEV                                                    glScalef(LEVER_KNOB_SIZE, LEV
                                                draw_sphere_outline();                                                           draw_sphere_outline();
                                        glPopMatrix();                                                                   glPopMatrix();
                                glPopMatrix();                                                                   glPopMatrix();
                                break;                                                                           break;
 
                        case ui_joyst: /* render joystick widget (in real wor                            case ui_joyst: /* render joystick widget (in real wor
                                /* similar to lever, but the stick is up (+y)                                    /* similar to lever, but the stick is up (+y)
                                glTranslatef(object->x, object->y, object->z)                                    glTranslatef(object->x, object->y, object->z)
#ifdef DRAW_UITEXT /* { */                                                       #ifdef DRAW_UITEXT /* { */
                                glPushMatrix();                                                                  glPushMatrix();
                                        glTranslatef(0.0, -1.0 * size - 0.5,                                             glTranslatef(0.0, -1.0 * size - 0.5, 
 
                                        sprintf(msg, "%5.2f, %5.2f", object->                                            sprintf(msg, "%5.2f, %5.2f", object->
                                        glRasterPos3f(0.0, 0.0, 0.0);   /* go                                            glRasterPos3f(0.0, 0.0, 0.0);   /* go
                                        vrRenderText(rendinfo, msg);                                                     vrRenderText(rendinfo, msg);
                                glPopMatrix();                                                                   glPopMatrix();
#endif /* } DRAW_UITEXT */                                                       #endif /* } DRAW_UITEXT */
                                glScalef(size, size, size);                                                      glScalef(size, size, size);
 
                                /* for now we'll ignore shape and all sliders                                    /* for now we'll ignore shape and all sliders
                                glPushMatrix();                                                                  glPushMatrix();
                                        /* the lever base */                                                             /* the lever base */
                                        glScalef(1.0, 0.2, 1.0);                                                         glScalef(1.0, 0.2, 1.0);
                                        if (objnum == wd->contacted_object)                                              if (objnum == wd->contacted_object)
                                                draw_cube_outline();                                                             draw_cube_outline();
                                        else    draw_cube();                                                             else    draw_cube();
                                glPopMatrix();                                                                   glPopMatrix();
 
                                glPushMatrix();                                                                  glPushMatrix();
                                        /* the lever */                                                                  /* the lever */
                                        glColor3ub(object->color[0]/2, object                                            glColor3ub(object->color[0]/2, object
                                        glRotatef(000.0, 1.0, 0.0, 0.0);                                                 glRotatef(000.0, 1.0, 0.0, 0.0);
 
                                        glRotatef(object->ui_valuator_value                                              glRotatef(object->ui_valuator_value  
                                        glRotatef(object->ui_valuator2_value                                             glRotatef(object->ui_valuator2_value 
                                        glTranslatef(0.0, JOYST_ARM_LENGTH, 0                                            glTranslatef(0.0, JOYST_ARM_LENGTH, 0
                                        glPushMatrix();                                                                  glPushMatrix();
                                                glScalef(0.15, -JOYST_ARM_LEN                                                    glScalef(0.15, -JOYST_ARM_LEN
                                                draw_pyramid_outline();                                                          draw_pyramid_outline();
                                        glPopMatrix();                                                                   glPopMatrix();
 
                                        /* a knob at the end of the lever */                                             /* a knob at the end of the lever */
                                        glColor3ubv(wd->object[objnum].color)                                            glColor3ubv(wd->object[objnum].color)
                                        glPushMatrix();                                                                  glPushMatrix();
                                                glTranslatef(0.0, JOYST_ARM_L                                                    glTranslatef(0.0, JOYST_ARM_L
                                                glScalef(JOYST_KNOB_SIZE, JOY                                                    glScalef(JOYST_KNOB_SIZE, JOY
                                                draw_sphere_outline();                                                           draw_sphere_outline();
                                        glPopMatrix();                                                                   glPopMatrix();
                                glPopMatrix();                                                                   glPopMatrix();
                                break;                                                                           break;
                        }                                                                                }
                glPopMatrix();                                                                   glPopMatrix();
        }                                                                                }
        /* NOTE: 2-D text is best rendered in a fixed location in the world *            /* NOTE: 2-D text is best rendered in a fixed location in the world *
 
        /*************************************************/                              /*************************************************/
        /* draw text indicating which object is contacted */                             /* draw text indicating which object is contacted */
        if (wd->contacted_object < 0) {                                                  if (wd->contacted_object < 0) {
                sprintf(msg, "Object contacted: none");                                          sprintf(msg, "Object contacted: none");
        } else {                                                                         } else {
                sprintf(msg, "Object contacted: %d", wd->contacted_object);                      sprintf(msg, "Object contacted: %d", wd->contacted_object);
        }                                                                                }
 
        vrLockReadRelease(wd->lock);                                                     vrLockReadRelease(wd->lock);
 
        glDisable(GL_LIGHTING);         /* make the text bright regardless of            glDisable(GL_LIGHTING);         /* make the text bright regardless of
        glColor3ub(255, 255, 255);      /* white */                                      glColor3ub(255, 255, 255);      /* white */
        glPushMatrix();                                                                  glPushMatrix();
                glTranslatef(-4.0, 7.0, -5.0);  /* on the front screen */                        glTranslatef(-4.0, 7.0, -5.0);  /* on the front screen */
 
                glRasterPos3f(0.0, 0.0, 0.0);   /* go to the 3D location */                      glRasterPos3f(0.0, 0.0, 0.0);   /* go to the 3D location */
                vrRenderText(rendinfo, msg);                                                     vrRenderText(rendinfo, msg);
        glPopMatrix();                                                                   glPopMatrix();
        glEnable(GL_LIGHTING);                                                           glEnable(GL_LIGHTING);
}                                                                                }