00001 /*************************************************************************** 00002 *cr 00003 *cr (C) Copyright 1995-2019 The Board of Trustees of the 00004 *cr University of Illinois 00005 *cr All Rights Reserved 00006 *cr 00007 ***************************************************************************/ 00008 00009 /*************************************************************************** 00010 * RCS INFORMATION: 00011 * 00012 * $RCSfile: FreeVRDisplayDevice.C,v $ 00013 * $Author: johns $ $Locker: $ $State: Exp $ 00014 * $Revision: 1.33 $ $Date: 2019年01月17日 21:20:59 $ 00015 * 00016 *************************************************************************** 00017 * DESCRIPTION: 00018 * 00019 * a FreeVR specific display device for VMD 00020 ***************************************************************************/ 00021 00022 #include <freevr.h> // include FreeVR library prototypes 00023 #include "Inform.h" 00024 #include "FreeVRDisplayDevice.h" 00025 00026 // static string storage used for returning stereo modes 00027 static const char *freevrStereoNameStr[1] = {"FreeVR"}; 00028 00030 FreeVRDisplayDevice::FreeVRDisplayDevice(void) : OpenGLRenderer("FreeVR") { 00031 stereoNames = freevrStereoNameStr; 00032 stereoModes = 1; 00033 doneGLInit = FALSE; 00034 num_display_processes = vrContext->config->num_windows; 00035 00036 // XXX migrated some initialization code into the constructor due 00037 // to the order of initialization in CAVE/FreeVR builds 00038 aaAvailable = TRUE; // enable antialiasing 00039 cueingAvailable = FALSE; // disable depth cueing 00040 cullingAvailable = FALSE; // disable culling 00041 ext->hasstereo = TRUE; // stereo is on initially 00042 ext->stereodrawforced = FALSE; // no need for force stereo draws 00043 00044 ogl_useblendedtrans = 0; 00045 ogl_transpass = 0; 00046 ogl_useglslshader = 0; 00047 ogl_acrobat3dcapture = 0; 00048 ogl_lightingenabled = 0; 00049 ogl_rendstateserial = 1; // force GLSL update on 1st pass 00050 ogl_glslserial = 0; // force GLSL update on 1st pass 00051 ogl_glsltoggle = 1; // force GLSL update on 1st pass 00052 ogl_glslmaterialindex = -1; // force GLSL update on 1st pass 00053 ogl_glslprojectionmode = DisplayDevice::PERSPECTIVE; 00054 ogl_glsltexturemode = 0; // initialize GLSL projection to off 00055 00056 00057 // leave everything else up to the freevr_gl_init_fn 00058 } 00059 00061 FreeVRDisplayDevice::~FreeVRDisplayDevice(void) { 00062 // nothing to do 00063 } 00064 00065 00067 00068 // set up the graphics on the seperate FreeVR displays 00069 void FreeVRDisplayDevice::freevr_gl_init_fn(void) { 00070 setup_initial_opengl_state(); // do all OpenGL setup/initialization now 00071 00072 // follow up with mode settings 00073 aaAvailable = TRUE; // enable antialiasing 00074 cueingAvailable = FALSE; // disable depth cueing 00075 cullingAvailable = FALSE; // disable culling 00076 ext->hasstereo = TRUE; // stereo is on initially 00077 ext->stereodrawforced = FALSE; // no need for force stereo draws 00078 00079 glClearColor(0.0, 0.0, 0.0, 0.0); // set clear color to black 00080 00081 aa_on(); // force antialiasing on if possible 00082 cueing_off(); // force depth cueing off 00083 00084 // set default settings 00085 set_sphere_mode(sphereMode); 00086 set_sphere_res(sphereRes); 00087 set_line_width(lineWidth); 00088 set_line_style(lineStyle); 00089 00090 clear(); // clear screen 00091 update(); // swap buffers 00092 00093 // we want the CAVE to be centered at the origin, and in the range -1, +1 00094 (transMat.top()).translate(0.0, 3.0, -2.0); 00095 (transMat.top()).scale(VMD_PI); 00096 00097 doneGLInit = TRUE; // only do this once 00098 } 00099 00100 void FreeVRDisplayDevice::set_stereo_mode(int) { 00101 // cannot change to stereo mode in FreeVR, it is setup at init time 00102 } 00103 00104 void FreeVRDisplayDevice::normal(void) { 00105 // prevent the OpenGLRenderer implementation of this routine 00106 // from overriding the projection matrices provided by the 00107 // FreeVR library. 00108 } 00109 00110 // special render routine to check for graphics initialization 00111 void FreeVRDisplayDevice::render(const VMDDisplayList *cmdlist) { 00112 if(!doneGLInit) { 00113 freevr_gl_init_fn(); 00114 } 00115 00116 // prepare for rendering 00117 glPushMatrix(); 00118 multmatrix((transMat.top())); // add our FreeVR adjustment transformation 00119 00120 // update the cached transformation matrices for use in text display, etc. 00121 // In FreeVR, we have to do this separately for all of the processors. 00122 // Would be nice to do this outside of the render routine however, 00123 // amortized over several Displayables. 00124 glGetFloatv(GL_PROJECTION_MATRIX, ogl_pmatrix); 00125 glGetFloatv(GL_MODELVIEW_MATRIX, ogl_mvmatrix); 00126 ogl_textMat.identity(); 00127 ogl_textMat.multmatrix(ogl_pmatrix); 00128 ogl_textMat.multmatrix(ogl_mvmatrix); 00129 00130 // call OpenGLRenderer to do the rest of the rendering the normal way 00131 OpenGLRenderer::render(cmdlist); 00132 glPopMatrix(); 00133 } 00134 00135 // update after drawing 00136 void FreeVRDisplayDevice::update(int do_update) { 00137 // XXX don't do buffer swaps in FreeVR!!! 00138 // Though not well documented, it is implicitly illegal 00139 // to call glxSwapBuffers() or to call glDrawBuffer() 00140 // in a FreeVR application, since FreeVR does this for you. 00141 #if 0 /* BS: my proof of concept code */ 00142 vrSystemSetStatusDescription("in update!"); 00143 if (vrGet2switchValue(2)) { 00144 vrUserTravelTranslate3d(VR_ALLUSERS, 0.0, 0.0, 0.1); 00145 } 00146 #endif 00147 00148 /****************************************************/ 00149 /* Do some (global) world navigation */ 00150 /* BS: this is from my ex12_travel.c tutorial code. */ 00151 #define WAND_SENSOR 1 /* TODO: this should really be based on the concept of props */ 00152 #define JS_EPSILON 0.125 /* the dead-zone before joystick movement is recognized */ 00153 #define MOVE_FACTOR 2.5 /* a scale factor to tune travel movement */ 00154 #define TURN_FACTOR 25.0 /* a scale factor to tune travel movement */ 00155 #define SUB_JS_EPSILON(a) ((a)-copysign(JS_EPSILON,(a))) /* a macro to remove the joystick epsilon range */ 00156 static vrTime last_time = -1.0; /* initially set to an invalid value as a flag */ 00157 vrTime sim_time = vrCurrentSimTime(); /* the current time of the simulation */ 00158 double delta_time; /* time since last update (in seconds) */ 00159 double delta_move; /* distance an object should be moved */ 00160 double joy_x, joy_y; /* Joystick values */ 00161 vrVector wand_rw_pointvec; /* current vector pointing out of the wand (in RW coords) */ 00162 00163 /* These variables are for the grab-the-world travel */ 00164 static vrMatrix wand_at_grab; /* the wand matrix as it was when the grab action was triggered */ 00165 static vrMatrix travel_at_grab; /* the value of the travel matrix when the grab action was triggered */ 00166 static int world_grabbed = 0; /* whether or not we're in the middle of a grab action */ 00167 vrMatrix new_world_matrix; /* the matrix into which we calculate the world transformation */ 00168 vrMatrix current_wand_matrix; 00169 vrMatrix invmat; 00170 00171 /*****************************************************/ 00173 /*****************************************************/ 00174 if (last_time == -1.0) 00175 delta_time = 0.0; 00176 else delta_time = sim_time - last_time; 00177 last_time = sim_time; /* now that delta_time has been calculated, we won't use last_time until next time */ 00178 00179 /* skip the update if the delta isn't big enough */ 00180 if (delta_time <= 0.0) /* can also choose a non-zero epsilon */ 00181 return; 00182 00183 /****************************/ 00185 /****************************/ 00186 00187 /* pressing the right wand button resets us to the initial position */ 00188 if (vrGet2switchValue(3)) { 00189 vrUserTravelReset(VR_ALLUSERS); 00190 } 00191 00192 /* use wand joystick to fly through world */ 00193 /* (but not while the world is grabbed!) */ 00194 joy_x = vrGetValuatorValue(0); 00195 joy_y = vrGetValuatorValue(1); 00196 00197 if (fabs(joy_x) > JS_EPSILON && !world_grabbed) 00198 vrUserTravelRotateId(VR_ALLUSERS, VR_Y, (delta_time * SUB_JS_EPSILON(joy_x) * -TURN_FACTOR)); 00199 00200 if (fabs(joy_y) > JS_EPSILON && !world_grabbed) { 00201 delta_move = delta_time * SUB_JS_EPSILON(joy_y) * MOVE_FACTOR; 00202 vrVectorGetRWFrom6sensorDir(&wand_rw_pointvec, WAND_SENSOR, VRDIR_FORE); 00203 vrUserTravelTranslate3d(VR_ALLUSERS, 00204 wand_rw_pointvec.v[VR_X] * delta_move, 00205 wand_rw_pointvec.v[VR_Y] * delta_move, 00206 wand_rw_pointvec.v[VR_Z] * delta_move); 00207 } 00208 00209 /* New full-grab-the-world with matrix operations travel example */ 00210 /* BS: NOTE that this can probably be done more cleanly/efficiently, and I will work on that in the future */ 00211 switch (vrGet2switchDelta(2)) { 00212 case 1: /* just pressed */ 00213 /* store the current location of the wand */ 00214 /* TODO: we should "subtract-out" the current travel matrix */ 00215 vrMatrixGet6sensorValues(&wand_at_grab, WAND_SENSOR); 00216 vrMatrixGetUserTravel(&travel_at_grab, 0); 00217 world_grabbed = 1; 00218 break; 00219 case 0: /* no change in state */ 00220 if (world_grabbed) { 00221 /* move the world with the wand */ 00222 vrMatrixGet6sensorValues(¤t_wand_matrix, WAND_SENSOR); 00223 vrMatrixInvert(&invmat, &wand_at_grab); 00224 vrMatrixPostMult(&invmat, ¤t_wand_matrix); 00225 new_world_matrix = invmat; 00226 00227 /* use locks to make the travel manipulations atomic */ 00228 vrUserTravelLockSet(VR_ALLUSERS); 00229 vrUserTravelReset(VR_ALLUSERS); 00230 vrUserTravelTransformMatrix(VR_ALLUSERS, &travel_at_grab); /* first put back the inital travel */ 00231 vrUserTravelTransformMatrix(VR_ALLUSERS, &new_world_matrix); /* now add in the wand-delta */ 00232 vrUserTravelLockRelease(VR_ALLUSERS); 00233 } 00234 break; 00235 case -1: /* just released */ 00236 world_grabbed = 0; 00237 break; 00238 } 00239 00240 } 00241