Main Page   Class Hierarchy   Alphabetical List   Compound List   File List   Compound Members   File Members   Related Pages  

DisplayDevice.C

Go to the documentation of this file.
00001 /***************************************************************************
00002  *cr                                                                       
00003  *cr            (C) Copyright 1995-2008 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: DisplayDevice.C,v $
00013  *      $Author: johns $        $Locker:  $             $State: Exp $
00014  *      $Revision: 1.121 $      $Date: 2008/03/27 19:36:37 $
00015  *
00016  ***************************************************************************
00017  * DESCRIPTION:
00018  *
00019  * DisplayDevice - abstract base class for all particular objects which
00020  *      can process a list of drawing commands and render the drawing
00021  *      to some device (screen, file, preprocessing script, etc.)
00022  *
00023  ***************************************************************************/
00024 
00025 #include <math.h>
00026 #include "DisplayDevice.h"
00027 #include "Inform.h"
00028 #include "DispCmds.h"
00029 #include "utilities.h"
00030 #include "Mouse.h"     // for WAIT_CURSOR
00031 #include "VMDDisplayList.h"
00032 #include "Scene.h"
00033 
00034 // static data for this object (yuck)
00035 static const char *cacheNameStr[1]  = { "Off" };
00036 static const char *renderNameStr[1] = { "Normal" };
00037 static const char *stereoNameStr[1] = { "Stereo Off" };
00038 
00039 const char *DisplayDevice::projNames[NUM_PROJECTIONS] = {
00040   "Perspective", "Orthographic"
00041 };
00042 
00043 const char *DisplayDevice::cueModeNames[NUM_CUE_MODES] = {
00044   "Linear", "Exp", "Exp2"
00045 };
00046 
00048 DisplayDevice::DisplayDevice (const char *nm) 
00049 : transMat(16) {
00050 
00051   name = stringdup(nm);       // save the string name of this display device
00052   num_display_processes  = 1; // set number of rendering processes etc
00053   renderer_process = 1;       // we're a rendering process until told otherwise
00054   _needRedraw = 0;            // Start life not needing to be redrawn. 
00055 
00056   // set default background drawing mode
00057   backgroundmode = 0;
00058 
00059   // set drawing characteristics default values
00060   lineStyle = ::SOLIDLINE;
00061   lineWidth = 1;
00062   sphereRes = 3;
00063   cylinderRes = 6;
00064   sphereMode = ::SOLIDSPHERE;
00065 
00066   // set scalar values
00067   aaAvailable = cueingAvailable = FALSE;
00068   aaPrevious = aaEnabled = cueingEnabled = FALSE;
00069   xOrig = yOrig = xSize = ySize = 0;
00070   screenX = screenY = 0;
00071 
00072   // set viewing geometry ... looking from z-axis in negative direction,
00073   // with 90-degree field of view and assuming the origin is in the
00074   // center of the viewer's 'screen'
00075   nearClip = 0.5f;
00076   farClip = 10.0f;
00077   eyePos[0] = eyePos[1] = 0.0f;  eyePos[2] = 2.0f;
00078   set_screen_pos(2.0f * eyePos[2], 0.0f, 4.0f/3.0f);
00079 
00080   // set initial depth cueing parameters 
00081   // (defaults are compatible with old revs of VMD)
00082   cueMode = CUE_EXP2;
00083   cueDensity = 0.4f;
00084   cueStart = 0.5f;
00085   cueEnd = 10.0f;
00086 
00087   // XXX stereo modes and rendering modes should be enumerated 
00088   // dynamically not hard-coded, to allow much greater flexibility
00089 
00090   // Setup stereo options ... while there is no stereo mode by default,
00091   // set up normal values for stereo data
00092   inStereo = 0;
00093   stereoModes = 1;
00094   stereoNames = stereoNameStr;
00095 
00096   // Setup caching mode options
00097   cacheMode = 0;
00098   cacheModes = 1;
00099   cacheNames = cacheNameStr;
00100 
00101   // Setup rendering mode options
00102   renderMode = 0;
00103   renderModes = 1;
00104   renderNames = renderNameStr;
00105 
00106   // default view/projection settings
00107   eyeSep = 0.065f;               // default eye seperation
00108   eyeDist = eyePos[2];           // assumes viewer on pos z-axis
00109 
00110   float lookatorigin[3];
00111   vec_scale(&lookatorigin[0], -1, &eyePos[0]); // calc dir to origin
00112   set_eye_dir(&lookatorigin[0]);               // point camera at origin
00113   upDir[0] = upDir[2] = 0.0;  upDir[1] = 1.0;
00114   calc_eyedir();                 // determines eye separation direction
00115   my_projection = PERSPECTIVE;
00116 
00117   // load identity matrix onto top of transformation matrix stack
00118   Matrix4 temp_ident;
00119   transMat.push(temp_ident);
00120 
00121   mouseX = mouseY = 0;
00122 }
00123 
00124 // destructor
00125 DisplayDevice::~DisplayDevice(void) {
00126   set_stereo_mode(0);           // return to non-stereo, if necessary
00127   delete [] name;
00128 }
00129 
00130 int DisplayDevice::set_eye_defaults() {
00131   float defaultDir[3];
00132   float defaultPos[3] = {0, 0, 2};           // camera 2 units back from origin
00133   float defaultUp[3] = {0, 1, 0};            // Y is up
00134 
00135   vec_scale(&defaultDir[0], -1, &eyePos[0]); // calc dir to origin
00136   set_eye_dir(&defaultDir[0]);               // point camera at origin
00137 
00138   set_eye_pos(&defaultPos[0]);
00139   set_eye_dir(&defaultDir[0]);
00140   set_eye_up(&defaultUp[0]);
00141 
00142   return TRUE;
00143 }
00144 
00146 // calculate the position of the near frustum plane, based on current values
00147 // of Aspect, vSize, zDist, nearClip and eyePosition
00148 // Assumes the viewer is looking toward the xy-plane
00149 void DisplayDevice::calc_frustum(void) {
00150   float d; 
00151   float halfvsize = 0.5f * vSize;       
00152   float halfhsize = Aspect * halfvsize; // width = aspect * height
00153 
00154   // if the frustum parameters don't cause division by zero,
00155   // calculate the new view frustum
00156   if(eyePos[2] - zDist != 0.0f) {
00157     // scaling ratio for the view frustum, essentially the amount of 
00158     // perspective to apply.  Since we define the nearClip plane in
00159     // the user interface, we can control how strong the perspective
00160     // is by varying (eyePos[2] - zDist) or by scaling d by some other
00161     // user controllable factor.  In order to make this more transparent
00162     // to the user however, we'd need to automatically apply a scaling 
00163     // operation on the molecular geometry so that it looks about the same
00164     // despite the perspective change.  We should also be able to calculate
00165     // the field of view angles (vertical, horizontal, and diagonal) based
00166     // on all of these variables.
00167     d = nearClip / (eyePos[2] - zDist);
00168 
00169     cpRight = d * halfhsize;     // right side is at half width
00170      cpLeft = -cpRight;          // left side is at negative half width
00171        cpUp = d * halfvsize;     // top side is at half height              
00172      cpDown = -cpUp;             // bottom is at negative half height
00173   }
00174 }
00175 
00176 
00177 // calculate eyeSepDir, based on up vector and look vector
00178 // eyeSepDir = 1/2 * eyeSep * (lookdir x updir) / mag(lookdir x updir)
00179 void DisplayDevice::calc_eyedir(void) {
00180   float *L = eyeDir;
00181   float *U = upDir;
00182   float m, A = 0.5f * eyeSep;
00183   eyeSepDir[0] = L[1] * U[2] - L[2] * U[1];
00184   eyeSepDir[1] = L[2] * U[0] - L[0] * U[2];
00185   eyeSepDir[2] = L[0] * U[1] - L[1] * U[0];
00186   m = sqrtf(eyeSepDir[0] * eyeSepDir[0] + eyeSepDir[1] * eyeSepDir[1] +
00187             eyeSepDir[2] * eyeSepDir[2]);
00188   if(m > 0.0)
00189     A /= m;
00190   else
00191     A = 0.0;
00192   eyeSepDir[0] *= A;
00193   eyeSepDir[1] *= A;
00194   eyeSepDir[2] *= A;
00195 }
00196 
00198 
00199 // Copy all relevant properties from one DisplayDevice to another
00200 DisplayDevice& DisplayDevice::operator=( DisplayDevice &display) {
00201   int i;
00202   
00203   xOrig = display.xOrig;
00204   yOrig = display.yOrig;
00205   xSize = display.xSize;
00206   ySize = display.ySize;
00207   
00208   // Do something about the stack.  For the moment, only copy the top
00209   // item on the stack.
00210   if(transMat.num() > 0) {
00211     transMat.pop();
00212   }
00213   transMat.push( (display.transMat).top() );
00214   
00215   for(i=0; i<3; i++) {
00216       eyePos[i] = display.eyePos[i];
00217       eyeDir[i] = display.eyeDir[i];
00218       upDir[i] = display.upDir[i];
00219       eyeSepDir[i] = display.eyeSepDir[i];
00220   }
00221   
00222   whichEye = display.whichEye;
00223   nearClip = display.nearClip;
00224   farClip = display.farClip;
00225   vSize = display.vSize;
00226   zDist = display.zDist;
00227   Aspect = display.Aspect;
00228   cpUp = display.cpUp;
00229   cpDown = display.cpDown;
00230   cpLeft = display.cpLeft;
00231   cpRight = display.cpRight;
00232   inStereo = display.inStereo;
00233   eyeSep = display.eyeSep;
00234   eyeDist = display.eyeDist;
00235   lineStyle = display.lineStyle;
00236   lineWidth = display.lineWidth;
00237   my_projection = display.my_projection;
00238   cueingEnabled = display.cueingEnabled;
00239   cueMode = display.cueMode;
00240   cueDensity = display.cueDensity;
00241   cueStart = display.cueStart;
00242   cueEnd = display.cueEnd;
00243  
00244   return *this;
00245 }
00246 
00248 
00249 void DisplayDevice::do_resize_window(int w, int h) {
00250   xSize = w;
00251   ySize = h;
00252   set_screen_pos((float)xSize / (float)ySize);
00253 }
00254 
00255 //
00256 // event handling routines
00257 //
00258 
00259 // queue the standard events (need only be called once ... but this is
00260 // not done automatically by the window because it may not be necessary or
00261 // even wanted)
00262 void DisplayDevice::queue_events(void) { return; }
00263 
00264 // read the next event ... returns an event type (one of the above ones),
00265 // and a value.  Returns success, and sets arguments.
00266 int DisplayDevice::read_event(long &, long &) { return FALSE; }
00267 
00268 //
00269 // get the current state of the device's pointer (i.e. cursor if it has one)
00270 //
00271 
00272 // abs pos of cursor from lower-left corner
00273 int DisplayDevice::x(void) { return mouseX; }
00274 
00275 // same, for y direction
00276 int DisplayDevice::y(void) { return mouseY; }
00277 
00278 // the shift state (shift key, control key, and/or alt key)
00279 int DisplayDevice::shift_state(void) {
00280   return 0; // by default, nothing is down
00281 }
00282 
00283 // set the Nth cursor shape as the current one.  If no arg given, the
00284 // default shape (n=0) is used.
00285 void DisplayDevice::set_cursor(int) { }
00286 
00287 // virtual functions to turn on/off depth cuing and antialiasing
00288 void DisplayDevice::aa_on(void) { }
00289 void DisplayDevice::aa_off(void) { }
00290 void DisplayDevice::cueing_on(void) { }
00291 void DisplayDevice::cueing_off(void) { }
00292 void DisplayDevice::culling_on(void) { }
00293 void DisplayDevice::culling_off(void) { }
00294 
00295 // return absolute 2D screen coordinates, given 2D or 3D world coordinates.
00296 void DisplayDevice::abs_screen_loc_3D(float *wloc, long *sloc) {
00297   // just return world coords
00298   for(int i=0; i < 2; i++)
00299     sloc[i] = (long)(wloc[i]);
00300 }
00301 
00302 void DisplayDevice::abs_screen_loc_2D(float *wloc, long *sloc) {
00303   // just return world coords
00304   for(int i=0; i < 2; i++)
00305     sloc[i] = (long)(wloc[i]);
00306 }
00307 
00308 // change to a different stereo mode (0 means 'off')
00309 void DisplayDevice::set_stereo_mode(int sm) {
00310   if(sm != 0) {
00311     msgErr << "DisplayDevice: Illegal stereo mode " << sm << " specified."
00312            << sendmsg;
00313   } else {
00314     inStereo = sm;
00315   }
00316 }
00317 
00318 // change to a different rendering mode (0 means 'normal')
00319 void DisplayDevice::set_cache_mode(int sm) {
00320   if(sm != 0) {
00321     msgErr << "DisplayDevice: Illegal caching mode " << sm << " specified."
00322            << sendmsg;
00323   } else {
00324     cacheMode = sm;
00325   }
00326 }
00327 
00328 // change to a different rendering mode (0 means 'normal')
00329 void DisplayDevice::set_render_mode(int sm) {
00330   if(sm != 0) {
00331     msgErr << "DisplayDevice: Illegal rendering mode " << sm << " specified."
00332            << sendmsg;
00333   } else {
00334     renderMode = sm;
00335   }
00336 }
00337 
00338 // replace the current trans matrix with the given one
00339 void DisplayDevice::loadmatrix(const Matrix4 &m) {
00340   (transMat.top()).loadmatrix(m);
00341 }
00342 
00343 // multiply the current trans matrix with the given one
00344 void DisplayDevice::multmatrix(const Matrix4 &m) {
00345   (transMat.top()).multmatrix(m);
00346 }
00347 
00348 //
00349 // virtual routines for preparing to draw, drawing, and finishing drawing
00350 //
00351   
00352 int DisplayDevice::prepare3D(int) { return 1;}  // ready to draw 3D
00353 void DisplayDevice::clear(void) { }             // erase the device
00354 void DisplayDevice::left(void) {                // ready to draw left eye
00355   whichEye = LEFTEYE; 
00356 }
00357 void DisplayDevice::right(void) {               // ready to draw right eye
00358   whichEye = RIGHTEYE;
00359 }
00360 void DisplayDevice::normal(void) {              // ready to draw non-stereo
00361   whichEye = NOSTEREO;
00362 }
00363 void DisplayDevice::update(int) { }             // finish up after drawing
00364 void DisplayDevice::reshape(void) { }           // refresh device after change
00365 
00366 // Grab the screen
00367 unsigned char * DisplayDevice::readpixels(int &x, int &y) { 
00368   x = 0;
00369   y = 0;
00370 
00371   return NULL;
00372 }
00373 
00374 void DisplayDevice::find_pbc_images(const VMDDisplayList *cmdList, 
00375                                     ResizeArray<Matrix4> &pbcImages) {
00376   if (cmdList->pbc == PBC_NONE) {
00377     pbcImages.append(Matrix4());
00378     return;
00379   }
00380   ResizeArray<int> pbcCells;
00381   find_pbc_cells(cmdList, pbcCells);
00382   for (int i=0; i<pbcCells.num(); i += 3) {
00383     int nx=pbcCells[i  ];
00384     int ny=pbcCells[i+1];
00385     int nz=pbcCells[i+2];
00386     Matrix4 mat;
00387     for (int i1=1; i1<=nx; i1++) mat.multmatrix(cmdList->transX);
00388     for (int i2=-1; i2>=nx; i2--) mat.multmatrix(cmdList->transXinv);
00389     for (int i3=1; i3<=ny; i3++) mat.multmatrix(cmdList->transY);
00390     for (int i4=-1; i4>=ny; i4--) mat.multmatrix(cmdList->transYinv);
00391     for (int i5=1; i5<=nz; i5++) mat.multmatrix(cmdList->transZ);
00392     for (int i6=-1; i6>=nz; i6--) mat.multmatrix(cmdList->transZinv);
00393     pbcImages.append(mat);
00394   }
00395 }
00396 
00397 void DisplayDevice::find_pbc_cells(const VMDDisplayList *cmdList, 
00398                                     ResizeArray<int> &pbcCells) {
00399   int pbc = cmdList->pbc;
00400   if (pbc == PBC_NONE) {
00401     pbcCells.append(0);
00402     pbcCells.append(0);
00403     pbcCells.append(0);
00404   } else {
00405     int npbc = cmdList->npbc;
00406     int nx = pbc & PBC_X ? npbc : 0;
00407     int ny = pbc & PBC_Y ? npbc : 0;
00408     int nz = pbc & PBC_Z ? npbc : 0;
00409     int nox = pbc & PBC_OPX ? -npbc : 0;
00410     int noy = pbc & PBC_OPY ? -npbc : 0;
00411     int noz = pbc & PBC_OPZ ? -npbc : 0;
00412     int i, j, k;
00413     for (i=nox; i<=nx; i++) {
00414       for (j=noy; j<=ny; j++) {
00415         for (k=noz; k<=nz; k++) {
00416           if (! (pbc & PBC_NOSELF && !i && !j && !k)) {
00417             pbcCells.append(i);
00418             pbcCells.append(j);
00419             pbcCells.append(k);
00420           }
00421         }
00422       }
00423     }
00424   }
00425 }
00426 
00427 //
00428 //*******************  the picking routine  *********************
00429 //
00430 // This scans the given command list until the end, finding which item is
00431 // closest to the given pointer position.
00432 //
00433 // arguments are dimension of picking (2 or 3), position of pointer,
00434 // draw command list, and returned distance from object to eye position.
00435 // Returns ID code ('tag') for item closest to pointer, or (-1) if no pick.
00436 // If an object is picked, the eye distance argument is set to the distance
00437 // from the display's eye position to the object (after its position has been
00438 // found from the transformation matrix).  If the value of the argument when
00439 // 'pick' is called is <= 0, a pick will be generated if any item is near the
00440 // pointer.  If the value of the argument is > 0, a pick will be generated
00441 // only if an item is closer to the eye position than the value of the
00442 // argument.
00443 // For 2D picking, coordinates are relative position in window from
00444 //      lower-left corner (both in range 0 ... 1)
00445 // For 3D picking, coordinates are the world coords of the pointer.  They
00446 //      are the coords of the pointer after its transformation matrix has been
00447 //      applied, and these coordinates are compared to the coords of the objects
00448 //      when their transformation matrices are applied.
00449 
00450 // but first, a macro for returning the distance^2 from the eyepos to the
00451 // given position
00452 #define DTOEYE(x,y,z) ( (x-eyePos[0])*(x-eyePos[0]) + \
00453                         (y-eyePos[1])*(y-eyePos[1]) + \
00454                         (z-eyePos[2])*(z-eyePos[2]) )
00455 #define DTOPOINT(x,y,z) ( (x-pos[0])*(x-pos[0]) + \
00456                         (y-pos[1])*(y-pos[1]) + \
00457                         (z-pos[2])*(z-pos[2]) )
00458 
00459 int DisplayDevice::pick(int dim, const float *pos, const VMDDisplayList *cmdList,
00460                         float &eyedist, int *unitcell, float window_size) {
00461   char *cmdptr = NULL;
00462   int tok;
00463   float newEyeDist, currEyeDist = eyedist;
00464   int tag = (-1), inRegion, currTag;
00465   int minX=0, minY=0, maxX=0, maxY=0;
00466   float fminX=0.0f, fminY=0.0f, fminZ=0.0f, fmaxX=0.0f, fmaxY=0.0f, fmaxZ=0.0f;
00467   float pntpos[3];
00468   long cpos[2];
00469 
00470   if(!cmdList)
00471     return (-1);
00472   
00473   // initialize picking: find screen region to look for object
00474   if (dim == 2) {
00475     fminX = pos[0] - window_size;
00476     fmaxX = pos[0] + window_size;
00477     fminY = pos[1] - window_size;
00478     fmaxY = pos[1] + window_size;
00479     abs_screen_pos(fminX, fminY);
00480     abs_screen_pos(fmaxX, fmaxY);
00481     minX = (int)fminX;
00482     maxX = (int)fmaxX;
00483     minY = (int)fminY;
00484     maxY = (int)fmaxY;
00485   } else {
00486     fminX = pos[0] - window_size;
00487     fmaxX = pos[0] + window_size;
00488     fminY = pos[1] - window_size;
00489     fmaxY = pos[1] + window_size;
00490     fminZ = pos[2] - window_size;
00491     fmaxZ = pos[2] + window_size;
00492   }
00493 
00494   // make sure we do not disturb the regular transformation matrix
00495   transMat.dup();
00496   (transMat.top()).multmatrix(cmdList->mat);
00497 
00498   // Transform the current pick point for each periodic image 
00499   ResizeArray<Matrix4> pbcImages;
00500   ResizeArray<int> pbcCells;
00501   find_pbc_images(cmdList, pbcImages);
00502   find_pbc_cells(cmdList, pbcCells);
00503   int pbcimg;
00504   for (pbcimg=0; pbcimg<pbcImages.num(); pbcimg++) {
00505     transMat.dup();
00506     (transMat.top()).multmatrix(pbcImages[pbcimg]);
00507 
00508     // scan through the list, getting each command and executing it, until
00509     // the end of commands token is found
00510     VMDDisplayList::VMDLinkIter cmditer;
00511     cmdList->first(&cmditer);
00512     float *dataBlock=NULL;
00513     while((tok = cmdList->next(&cmditer, cmdptr)) != DLASTCOMMAND) {
00514       switch (tok) {
00515         case DDATABLOCK:
00516 #ifdef VMDCAVE
00517           dataBlock = (float *)cmdptr;
00518 #else
00519           dataBlock = ((DispCmdDataBlock *)cmdptr)->data;
00520 #endif
00521           break;
00522 
00523         case DPICKPOINT:
00524         case DPICKPOINT_I:
00525           // calculate the transformed position of the point
00526           if(tok == DPICKPOINT) {
00527             DispCmdPickPoint *cmd = (DispCmdPickPoint *)cmdptr;
00528             (transMat.top()).multpoint3d(cmd->postag, pntpos);
00529             currTag = cmd->tag;
00530           } else {
00531             DispCmdPickPointIndex *cmd = (DispCmdPickPointIndex *)cmdptr;
00532             (transMat.top()).multpoint3d(dataBlock + cmd->pos, pntpos);
00533             currTag = cmd->tag; 
00534           }
00535 
00536           // check if in picking region ... different for 2D and 3D
00537           if (dim == 2) {
00538             // convert the 3D world coordinate to 2D absolute screen coord
00539             abs_screen_loc_3D(pntpos, cpos);
00540       
00541             // check to see if the position falls in our picking region
00542             inRegion = (cpos[0] >= minX && cpos[0] <= maxX &&
00543                         cpos[1] >= minY && cpos[1] <= maxY);
00544           } else {
00545             // just check to see if the position is in a box centered on our
00546             // pointer.  The pointer position should already be transformed.
00547             inRegion = (pntpos[0] >= fminX && pntpos[0] <= fmaxX &&     
00548                         pntpos[1] >= fminY && pntpos[1] <= fmaxY &&
00549                         pntpos[2] >= fminZ && pntpos[2] <= fmaxZ);
00550           }
00551       
00552           // has a hit occurred?
00553           if (inRegion) {
00554             // yes, see if it is closer to the eye position than earlier objects
00555             if(dim==2) 
00556               newEyeDist = DTOEYE(pntpos[0], pntpos[1], pntpos[2]);
00557             else 
00558               newEyeDist = DTOPOINT(pntpos[0],pntpos[1],pntpos[2]);
00559 
00560             if(currEyeDist < 0.0 || newEyeDist < currEyeDist) {
00561               currEyeDist = newEyeDist;
00562               tag = currTag;
00563               if (unitcell) {
00564                 unitcell[0] = pbcCells[3*pbcimg  ];
00565                 unitcell[1] = pbcCells[3*pbcimg+1];
00566                 unitcell[2] = pbcCells[3*pbcimg+2];
00567               }
00568             }
00569           }
00570           break;
00571 
00572         case DPICKPOINT_IARRAY:
00573           // loop over all of the pick points in the pick point index array
00574           DispCmdPickPointIndexArray *cmd = (DispCmdPickPointIndexArray *)cmdptr;
00575           float *pickpos;
00576           int *indices;
00577           cmd->getpointers(indices); 
00578 
00579           int i;
00580           for (i=0; i<cmd->numpicks; i++) {
00581             if (cmd->allselected) {
00582               pickpos = dataBlock + i*3;
00583               currTag = i;
00584             } else {
00585               pickpos = dataBlock + indices[i]*3;
00586               currTag = indices[i];
00587             }
00588 
00589             (transMat.top()).multpoint3d(pickpos, pntpos);
00590 
00591             // check if in picking region ... different for 2D and 3D
00592             if (dim == 2) {
00593               // convert the 3D world coordinate to 2D absolute screen coord
00594               abs_screen_loc_3D(pntpos, cpos);
00595 
00596               // check to see if the position falls in our picking region
00597               inRegion = (cpos[0] >= minX && cpos[0] <= maxX &&
00598                           cpos[1] >= minY && cpos[1] <= maxY);
00599             } else {
00600               // just check to see if the position is in a box centered on our
00601               // pointer.  The pointer position should already be transformed.
00602               inRegion = (pntpos[0] >= fminX && pntpos[0] <= fmaxX &&
00603                           pntpos[1] >= fminY && pntpos[1] <= fmaxY &&
00604                           pntpos[2] >= fminZ && pntpos[2] <= fmaxZ);
00605             }
00606 
00607             // has a hit occurred?
00608             if (inRegion) {
00609               // yes, see if it is closer to the eye than earlier hits
00610               if (dim==2)
00611                 newEyeDist = DTOEYE(pntpos[0], pntpos[1], pntpos[2]);
00612               else
00613                 newEyeDist = DTOPOINT(pntpos[0],pntpos[1],pntpos[2]);
00614 
00615               if (currEyeDist < 0.0 || newEyeDist < currEyeDist) {
00616                 currEyeDist = newEyeDist;
00617                 tag = currTag;
00618                 if (unitcell) {
00619                   unitcell[0] = pbcCells[3*pbcimg  ];
00620                   unitcell[1] = pbcCells[3*pbcimg+1];
00621                   unitcell[2] = pbcCells[3*pbcimg+2];
00622                 }
00623               }
00624             }
00625           }
00626           break;
00627       }
00628     }
00629 
00630     // Pop the PBC image transform
00631     transMat.pop();
00632   } // end of loop over PBC images
00633 
00634   // make sure we do not disturb the regular transformation matrix
00635   transMat.pop();
00636 
00637   // return result; if tag >= 0, we found something
00638   eyedist = currEyeDist;
00639   return tag;
00640 }
00641 
00642 
00643 

Generated on Sat Aug 30 01:26:37 2008 for VMD (current) by doxygen1.2.14 written by Dimitri van Heesch, © 1997-2002