/***********************************************************************/ /***********************************************************************/ /* 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); } }