void
 DisplayDevice::find_pbc_images (const VMDDisplayList *cmdList,
     ResizeArray<Matrix4> &pbcImages)
 {
   if (cmdList->pbc == PBC_NONE)
   {
     pbcImages.append (Matrix4 ());
     return;
   }
   ResizeArray<int> pbcCells;
   find_pbc_cells (cmdList, pbcCells);
   for (int i = 0; i < pbcCells.num (); i += 3)
   {
     int nx = pbcCells[i];
     int ny = pbcCells[i + 1];
     int nz = pbcCells[i + 2];
     Matrix4 mat;
     for (int i1 = 1; i1 <= nx; i1++)
       mat.multmatrix (cmdList->transX);
     for (int i2 = -1; i2 >= nx; i2--)
       mat.multmatrix (cmdList->transXinv);
     for (int i3 = 1; i3 <= ny; i3++)
       mat.multmatrix (cmdList->transY);
     for (int i4 = -1; i4 >= ny; i4--)
       mat.multmatrix (cmdList->transYinv);
     for (int i5 = 1; i5 <= nz; i5++)
       mat.multmatrix (cmdList->transZ);
     for (int i6 = -1; i6 >= nz; i6--)
       mat.multmatrix (cmdList->transZinv);
     pbcImages.append (mat);
   }
 }
static void mol_delete_cb(Fl_Widget *w, void *v) {
  VMDApp *app = (VMDApp *)w->user_data();
  MolBrowser *browser = (MolBrowser *)v;
  ResizeArray<int> idlist;
  for (int i=0; i<browser->size(); i++) {
    if (browser->selected(i+1)) {
      idlist.append(app->molecule_id(i));
    }
  }
  for (int j=0; j<idlist.num(); j++)
    app->molecule_delete(idlist[j]);
}
Exemple #3
0
ResizeArray<JString *> *generic_get_names(const T &devList) {

  ResizeArray<JString *> *names = SensorConfig::getnames();
  ResizeArray<JString *> *devnames = new ResizeArray<JString *>;
  for (int i=0; i<names->num(); i++) {
    JString *jstr = (*names)[i];
    SensorConfig config(*jstr);
    const char *type = config.gettype();
    if (devList.typecode(type) >= 0)
      devnames->append(jstr); 
    else
      delete jstr;
  } 
  delete names;
  return devnames;
}
int DisplayDevice::pick(int dim, const float *pos, const VMDDisplayList *cmdList,
			float &eyedist, int *unitcell, float window_size) {
  char *cmdptr = NULL;
  int tok;
  float newEyeDist, currEyeDist = eyedist;
  int tag = (-1), inRegion, currTag;
  float minX=0.0f, minY=0.0f, maxX=0.0f, maxY=0.0f;
  float fminX=0.0f, fminY=0.0f, fminZ=0.0f, fmaxX=0.0f, fmaxY=0.0f, fmaxZ=0.0f;
  float wpntpos[3], pntpos[3], cpos[3];

  if(!cmdList)
    return (-1);

  // initialize picking: find screen region to look for object
  if (dim == 2) {
    fminX = pos[0] - window_size;
    fmaxX = pos[0] + window_size;
    fminY = pos[1] - window_size;
    fmaxY = pos[1] + window_size;
    abs_screen_pos(fminX, fminY);
    abs_screen_pos(fmaxX, fmaxY);
#if defined(_MSC_VER)
    // Win32 lacks the C99 round() routine
    // Add +/- 0.5 then then round towards zero.
#if 1
    minX = (int) ((float) (fminX + (fminX >= 0.0f ?  0.5f : -0.5f)));
    maxX = (int) ((float) (fmaxX + (fmaxX >= 0.0f ?  0.5f : -0.5f)));
    minY = (int) ((float) (fminY + (fminY >= 0.0f ?  0.5f : -0.5f)));
    maxY = (int) ((float) (fmaxY + (fmaxY >= 0.0f ?  0.5f : -0.5f)));
#else
    minX = truncf(fminX + (fminX >= 0.0f ?  0.5f : -0.5f));
    maxX = truncf(fmaxX + (fmaxX >= 0.0f ?  0.5f : -0.5f));
    minY = truncf(fminY + (fminY >= 0.0f ?  0.5f : -0.5f));
    maxY = truncf(fmaxY + (fmaxY >= 0.0f ?  0.5f : -0.5f));
//    minX = floor(fminX + 0.5);
//    maxX = floor(fmaxX + 0.5);
//    minY = floor(fminY + 0.5);
//    maxY = floor(fmaxY + 0.5);
#endif
#else
    minX = round(fminX);
    maxX = round(fmaxX);
    minY = round(fminY);
    maxY = round(fmaxY);
#endif

  } else {
    fminX = pos[0] - window_size;
    fmaxX = pos[0] + window_size;
    fminY = pos[1] - window_size;
    fmaxY = pos[1] + window_size;
    fminZ = pos[2] - window_size;
    fmaxZ = pos[2] + window_size;
  }

  // make sure we do not disturb the regular transformation matrix
  transMat.dup();
  (transMat.top()).multmatrix(cmdList->mat);

  // Transform the current pick point for each periodic image 
  ResizeArray<Matrix4> pbcImages;
  ResizeArray<int> pbcCells;
  find_pbc_images(cmdList, pbcImages);
  find_pbc_cells(cmdList, pbcCells);
  int pbcimg;
  for (pbcimg=0; pbcimg<pbcImages.num(); pbcimg++) {
    transMat.dup();
    (transMat.top()).multmatrix(pbcImages[pbcimg]);

    // scan through the list, getting each command and executing it, until
    // the end of commands token is found
    VMDDisplayList::VMDLinkIter cmditer;
    cmdList->first(&cmditer);
    while((tok = cmdList->next(&cmditer, cmdptr)) != DLASTCOMMAND) {
      switch (tok) {
        case DPICKPOINT:
          // calculate the transformed position of the point
          {
            DispCmdPickPoint *cmd = (DispCmdPickPoint *)cmdptr;
            vec_copy(wpntpos, cmd->postag);
            currTag = cmd->tag;
          }
          (transMat.top()).multpoint3d(wpntpos, pntpos);

          // check if in picking region ... different for 2D and 3D
          if (dim == 2) {
            // convert the 3D world coordinate to 2D (XY) absolute screen 
            // coordinate, and a normalized Z coordinate.
            abs_screen_loc_3D(pntpos, cpos);
      
            // check to see if the projected picking position falls within the 
            // view frustum, with the XY coords falling within the displayed 
            // window, and the Z coordinate falling within the view volume
            // between the front and rear clipping planes.
            inRegion = (cpos[0] >= minX && cpos[0] <= maxX &&
                        cpos[1] >= minY && cpos[1] <= maxY &&
                        cpos[2] >= 0.0  && cpos[2] <= 1.0);
          } else {
            // just check to see if the position is in a box centered on our
            // pointer.  The pointer position should already be transformed.
            inRegion = (pntpos[0] >= fminX && pntpos[0] <= fmaxX &&	
                        pntpos[1] >= fminY && pntpos[1] <= fmaxY &&
                        pntpos[2] >= fminZ && pntpos[2] <= fmaxZ);
          }

          // Clip still-viable pick points against all active clipping planes
          if (inRegion) {
            // We must perform a check against all of the active
            // user-defined clipping planes to ensure that only pick points
            // associated with visible geometry can be selected.
            int cp;
            for (cp=0; cp < VMD_MAX_CLIP_PLANE; cp++) {
              // The final result is the intersection of all of the
              // individual clipping plane tests...
              if (cmdList->clipplanes[cp].mode) {
                float cpdist[3];
                vec_sub(cpdist, wpntpos, cmdList->clipplanes[cp].center);
                inRegion &= (dot_prod(cpdist, 
                                      cmdList->clipplanes[cp].normal) > 0.0f);
              }
            }
          }
      
          // has a hit occurred?
          if (inRegion) {
            // yes, see if it is closer to the eye position than earlier objects
            if(dim==2) 
              newEyeDist = DTOEYE(pntpos[0], pntpos[1], pntpos[2]);
            else 
              newEyeDist = DTOPOINT(pntpos[0],pntpos[1],pntpos[2]);

            if(currEyeDist < 0.0 || newEyeDist < currEyeDist) {
              currEyeDist = newEyeDist;
              tag = currTag;
              if (unitcell) {
                unitcell[0] = pbcCells[3*pbcimg  ];
                unitcell[1] = pbcCells[3*pbcimg+1];
                unitcell[2] = pbcCells[3*pbcimg+2];
              }
            }
          }
          break;

        case DPICKPOINT_ARRAY:
          // loop over all of the pick points in the pick point index array
          DispCmdPickPointArray *cmd = (DispCmdPickPointArray *)cmdptr;
          float *pickpos=NULL;
          float *crds=NULL;
          int *indices=NULL;
          cmd->getpointers(crds, indices); 

          int i;
          for (i=0; i<cmd->numpicks; i++) {
            pickpos = crds + i*3;
            if (cmd->allselected) {
              currTag = i + cmd->firstindex;
            } else {
              currTag = indices[i];
            }
            vec_copy(wpntpos, pickpos);

            (transMat.top()).multpoint3d(pickpos, pntpos);

            // check if in picking region ... different for 2D and 3D
            if (dim == 2) {
              // convert the 3D world coordinate to 2D absolute screen coord
              abs_screen_loc_3D(pntpos, cpos);

              // check to see if the position falls in our picking region
              // including the clipping region (cpos[2])
              inRegion = (cpos[0] >= minX && cpos[0] <= maxX &&
                          cpos[1] >= minY && cpos[1] <= maxY &&
                          cpos[2] >= 0.0  && cpos[2] <= 1.0);
            } else {
              // just check to see if the position is in a box centered on our
              // pointer.  The pointer position should already be transformed.
              inRegion = (pntpos[0] >= fminX && pntpos[0] <= fmaxX &&
                          pntpos[1] >= fminY && pntpos[1] <= fmaxY &&
                          pntpos[2] >= fminZ && pntpos[2] <= fmaxZ);
            }

            // Clip still-viable pick points against all active clipping planes
            if (inRegion) {
              // We must perform a check against all of the active
              // user-defined clipping planes to ensure that only pick points
              // associated with visible geometry can be selected.
              int cp;
              for (cp=0; cp < VMD_MAX_CLIP_PLANE; cp++) {
                // The final result is the intersection of all of the
                // individual clipping plane tests...
                if (cmdList->clipplanes[cp].mode) {
                  float cpdist[3];
                  vec_sub(cpdist, wpntpos, cmdList->clipplanes[cp].center);
                  inRegion &= (dot_prod(cpdist, 
                                        cmdList->clipplanes[cp].normal) > 0.0f);
                }
              }
            }

            // has a hit occurred?
            if (inRegion) {
              // yes, see if it is closer to the eye than earlier hits
              if (dim==2)
                newEyeDist = DTOEYE(pntpos[0], pntpos[1], pntpos[2]);
              else
                newEyeDist = DTOPOINT(pntpos[0],pntpos[1],pntpos[2]);

              if (currEyeDist < 0.0 || newEyeDist < currEyeDist) {
                currEyeDist = newEyeDist;
                tag = currTag;
                if (unitcell) {
                  unitcell[0] = pbcCells[3*pbcimg  ];
                  unitcell[1] = pbcCells[3*pbcimg+1];
                  unitcell[2] = pbcCells[3*pbcimg+2];
                }
              }
            }
          }
          break;
      }
    }

    // Pop the PBC image transform
    transMat.pop();
  } // end of loop over PBC images

  // make sure we do not disturb the regular transformation matrix
  transMat.pop();

  // return result; if tag >= 0, we found something
  eyedist = currEyeDist;
  return tag;
}
static PyObject *sasa(PyObject *self, PyObject *args, PyObject *keywds) {
  int molid = -1, frame = -1;
  float srad = 0;
  PyObject *selobj = NULL, *restrictobj = NULL;
  int samples = -1;
  const int *sampleptr = NULL;
  PyObject *pointsobj = NULL;

  static char *kwlist[] = {
    (char *)"srad", (char *)"molid", (char *)"frame", (char *)"selected",
    (char *)"samples", (char *)"points", (char *)"restrict"
  };
  if (!PyArg_ParseTupleAndKeywords(args, keywds, 
        (char *)"fiiO!|iO!O!:atomselection.sasa", kwlist, 
        &srad, &molid, &frame, &PyTuple_Type, &selobj, 
        &samples, &PyList_Type, &pointsobj, &PyTuple_Type, &restrictobj))
    return NULL;

  // validate srad
  if (srad < 0) {
    PyErr_SetString(PyExc_ValueError, (char *)"atomselect.sasa: srad must be non-negative.");
    return NULL;
  }

  // validate selection
  VMDApp *app = get_vmdapp();
  AtomSel *sel = sel_from_py(molid, frame, selobj, app);
  if (!sel) return NULL;

  // fetch the radii and coordinates
  const float *radii = 
    app->moleculeList->mol_from_id(sel->molid())->extraflt.data("radius");
  const float *coords = sel->coordinates(app->moleculeList);

  // if samples was given and is valid, use it
  if (samples > 1) sampleptr = &samples;

  // if restrict is given, validate it
  AtomSel *restrictsel = NULL;
  if (restrictobj) {
    if (!(restrictsel = sel_from_py(molid, frame, restrictobj, app))) {
      delete sel;
      return NULL;
    }
  }

  // if points are requested, fetch them
  ResizeArray<float> sasapts;
  ResizeArray<float> *sasaptsptr = pointsobj ? &sasapts : NULL;
 
  // go!
  float sasa = 0;
  int rc = measure_sasa(sel, coords, radii, srad, &sasa, 
        sasaptsptr, restrictsel, sampleptr);
  delete sel;
  delete restrictsel;
  if (rc) {
    PyErr_SetString(PyExc_ValueError, (char *)measure_error(rc));
    return NULL;
  }

  // append surface points to the provided list object.
  if (pointsobj) {
    for (int i=0; i<sasapts.num(); i++) {
      PyList_Append(pointsobj, PyFloat_FromDouble(sasapts[i]));
    }
  }

  // return the total SASA.
  return PyFloat_FromDouble(sasa);
}
Exemple #6
0
void PSDisplayDevice::render(const VMDDisplayList *display_list) {
   DepthSortObject depth_obj;
   char *cmd_ptr;
   int draw;
   int tok;
   int nc;
   float a[3], b[3], c[3], d[3];
   float cent[3];
   float r;
   Matrix4 ident;
   float textsize=1.0f; // default text size

   // first we want to clear the transformation matrix stack
   while (transMat.num())
      transMat.pop();

   // push on the identity matrix
   transMat.push(ident);

   // load the display list's transformation matrix
   super_multmatrix(display_list->mat.mat);

   // Now we need to calculate the normalized position of the light
   // so we can compute angles of surfaces to that light for shading
   norm_light[0] = lightState[0].pos[0];
   norm_light[1] = lightState[0].pos[1];
   norm_light[2] = lightState[0].pos[2];
   if (norm_light[0] || norm_light[1] || norm_light[2])
      vec_normalize(norm_light);

   // Computer periodic images
   ResizeArray<Matrix4> pbcImages;
   find_pbc_images(display_list, pbcImages);
   int nimages = pbcImages.num();

   for (int pbcimage = 0; pbcimage < nimages; pbcimage++) {
     transMat.dup();
     super_multmatrix(pbcImages[pbcimage].mat);

   // Loop through the display list and add each object to our
   // depth-sort list for final rendering.
   VMDDisplayList::VMDLinkIter cmditer;
   display_list->first(&cmditer);
   while ((tok = display_list->next(&cmditer, cmd_ptr)) != DLASTCOMMAND) {
      draw = 0;
      nc = -1;

      switch (tok) {
         case DPOINT:
            // allocate memory
            depth_obj.points = (float *) malloc(sizeof(float) * 2);
            if (!depth_obj.points) {
               // memory error
               if (!memerror) {
                  memerror = 1;
                  msgErr << "PSDisplayDevice: Out of memory. Some " <<
                     "objects were not drawn." << sendmsg;
               }
               break;
            }

            // copy data
            depth_obj.npoints = 1;
            depth_obj.color = colorIndex;
            (transMat.top()).multpoint3d(((DispCmdPoint *) cmd_ptr)->pos, a);
            memcpy(depth_obj.points, a, sizeof(float) * 2);

            // compute the distance to the eye
            depth_obj.dist = compute_dist(a);

            // valid object to depth sort
            draw = 1;
            break;

         case DSPHERE:
         {
            (transMat.top()).multpoint3d(((DispCmdSphere *) cmd_ptr)->pos_r, c);
            r = scale_radius(((DispCmdSphere *) cmd_ptr)->pos_r[3]);

            sphere_approx(c, r);
            break;
         }

         case DSPHEREARRAY:
         {
            DispCmdSphereArray *sa = (DispCmdSphereArray *) cmd_ptr;
            int cIndex, rIndex; // cIndex: index of colors & centers
                                // rIndex: index of radii.
            float * centers;
            float * radii;
            float * colors;
            sa->getpointers(centers, radii, colors);

            set_sphere_res(sa->sphereres);

            for (cIndex = 0, rIndex=0; rIndex < sa->numspheres; 
                 cIndex+=3, rIndex++)
            {
                colorIndex = nearest_index(colors[cIndex],
                                           colors[cIndex+1],
                                           colors[cIndex+2]);
                (transMat.top()).multpoint3d(&centers[cIndex] , c);
                r = scale_radius(radii[rIndex]);

                sphere_approx(c, r);
            }

            break;
         }   

         case DLINE:
            // check for zero-length line (degenerate)
            if (!memcmp(((DispCmdLine *) cmd_ptr)->pos1,
                        ((DispCmdLine *) cmd_ptr)->pos2,
                        sizeof(float) * 3)) {
               // degenerate line
               break;
            }

            // allocate memory
            depth_obj.points = (float *) malloc(sizeof(float) * 4);
            if (!depth_obj.points) {
               // memory error
               if (!memerror) {
                  memerror = 1;
                  msgErr << "PSDisplayDevice: Out of memory. Some " <<
                     "objects were not drawn." << sendmsg;
               }
               break;
            }

            // copy data
            depth_obj.npoints = 2;
            depth_obj.color = colorIndex;
            (transMat.top()).multpoint3d(((DispCmdLine *) cmd_ptr)->pos1, a);
            (transMat.top()).multpoint3d(((DispCmdLine *) cmd_ptr)->pos2, b);
            memcpy(depth_obj.points, a, sizeof(float) * 2);
            memcpy(&depth_obj.points[2], b, sizeof(float) * 2);

            // compute the centerpoint of the object
            cent[0] = (a[0] + b[0]) / 2;
            cent[1] = (a[1] + b[1]) / 2;
            cent[2] = (a[2] + b[2]) / 2;

            // compute the distance to the eye
            depth_obj.dist = compute_dist(cent);

            // valid object to depth sort
            draw = 1;
            break;

         case DLINEARRAY:
           {
            // XXX much replicated code from DLINE
            float *v = (float *)cmd_ptr;
            int nlines = (int)v[0];
            v++;
            for (int i=0; i<nlines; i++) {
              // check for degenerate line
              if (!memcmp(v,v+3,3*sizeof(float)))
                break;

              // allocate memory
              depth_obj.points = (float *) malloc(sizeof(float) * 4);
              if (!depth_obj.points) {
                 // memory error
                 if (!memerror) {
                    memerror = 1;
                    msgErr << "PSDisplayDevice: Out of memory. Some " <<
                       "objects were not drawn." << sendmsg;
                 }
                 break;
              }

              // copy data
              depth_obj.npoints = 2;
              depth_obj.color = colorIndex;
              (transMat.top()).multpoint3d(v, a);
              (transMat.top()).multpoint3d(v+3, b);
              memcpy(depth_obj.points, a, sizeof(float) * 2);
              memcpy(&depth_obj.points[2], b, sizeof(float) * 2);
  
              // compute the centerpoint of the object
              cent[0] = (a[0] + b[0]) / 2;
              cent[1] = (a[1] + b[1]) / 2;
              cent[2] = (a[2] + b[2]) / 2;
  
              // compute the distance to the eye
              depth_obj.dist = compute_dist(cent);
 
              // we'll add the object here, since we have multiple objects 
              draw = 0;
              memusage += sizeof(float) * 2 * depth_obj.npoints;
              points += depth_obj.npoints;
              objects++;
              depth_list.append(depth_obj);

              v += 6;
            } 
           }
           break;           

         case DPOLYLINEARRAY:
           {
            // XXX much replicated code from DLINE / DLINEARRAY
            float *v = (float *)cmd_ptr;
            int nverts = (int)v[0];
            v++;
            for (int i=0; i<nverts-1; i++) {
              // check for degenerate line
              if (!memcmp(v,v+3,3*sizeof(float)))
                break;

              // allocate memory
              depth_obj.points = (float *) malloc(sizeof(float) * 4);
              if (!depth_obj.points) {
                 // memory error
                 if (!memerror) {
                    memerror = 1;
                    msgErr << "PSDisplayDevice: Out of memory. Some " <<
                       "objects were not drawn." << sendmsg;
                 }
                 break;
              }

              // copy data
              depth_obj.npoints = 2;
              depth_obj.color = colorIndex;
              (transMat.top()).multpoint3d(v, a);
              (transMat.top()).multpoint3d(v+3, b);
              memcpy(depth_obj.points, a, sizeof(float) * 2);
              memcpy(&depth_obj.points[2], b, sizeof(float) * 2);
  
              // compute the centerpoint of the object
              cent[0] = (a[0] + b[0]) / 2;
              cent[1] = (a[1] + b[1]) / 2;
              cent[2] = (a[2] + b[2]) / 2;
  
              // compute the distance to the eye
              depth_obj.dist = compute_dist(cent);
 
              // we'll add the object here, since we have multiple objects 
              draw = 0;
              memusage += sizeof(float) * 2 * depth_obj.npoints;
              points += depth_obj.npoints;
              objects++;
              depth_list.append(depth_obj);

              v += 3;
            } 
           }
           break;           
 
         case DCYLINDER:
         {
            int res;

            (transMat.top()).multpoint3d((float *) cmd_ptr, a);
            (transMat.top()).multpoint3d(&((float *) cmd_ptr)[3], b);
            r = scale_radius(((float *) cmd_ptr)[6]);
            res = (int) ((float *) cmd_ptr)[7];

            cylinder_approx(a, b, r, res, (int) ((float *) cmd_ptr)[8]);
            break;
         }

         case DCONE:
         {
            (transMat.top()).multpoint3d(((DispCmdCone *) cmd_ptr)->pos1, a);
            (transMat.top()).multpoint3d(((DispCmdCone *) cmd_ptr)->pos2, b);
            float r1 = scale_radius(((DispCmdCone *) cmd_ptr)->radius);
            float r2 = scale_radius(((DispCmdCone *) cmd_ptr)->radius2);

            // XXX current implementation can't draw truncated cones.
            if (r2 > 0.0f) {
              msgWarn << "PSDisplayDevice) can't draw truncated cones" 
                      << sendmsg;
            }
            cone_approx(a, b, r1);
            break;
         }

        case DTEXTSIZE:
          textsize = ((DispCmdTextSize *)cmd_ptr)->size;
          break;

        case DTEXT:
        {
            float* pos = (float *)cmd_ptr;
#if 0
            // thickness not implemented yet
            float thickness = pos[3];    // thickness is stored in 4th slot
#endif
            char* txt = (char *)(pos+4);
            int   txtlen = strlen(txt);
            // allocate memory
            depth_obj.points = (float *) malloc(sizeof(float) * 2);
            depth_obj.text   = (char  *) malloc(sizeof(char) * (txtlen+1));
            if ( !(depth_obj.points || depth_obj.text) ) {
              // memory error
              if (!memerror) {
                 memerror = 1;
                 msgErr << "PSDisplayDevice: Out of memory. Some " <<
                    "objects were not drawn." << sendmsg;
              }
              break;
           }

            // copy data
            depth_obj.npoints = 1;
            depth_obj.color = colorIndex;
            (transMat.top()).multpoint3d(((DispCmdPoint *) cmd_ptr)->pos, a);
            memcpy(depth_obj.points, a, sizeof(float) * 2);
            strcpy(depth_obj.text , txt);

            // note scale factor, stored into "light_scale", so we didn't
            // have to add a new structure member just for this.
            depth_obj.light_scale = textsize * 15;

            // compute the distance to the eye
            depth_obj.dist = compute_dist(a);

            // valid object to depth sort
            draw = 1;
            break;
         }

         case DTRIANGLE:
            // check for degenerate triangle
            if (!memcmp(((DispCmdTriangle *) cmd_ptr)->pos1,
                        ((DispCmdTriangle *) cmd_ptr)->pos2,
                        sizeof(float) * 3) ||
                !memcmp(((DispCmdTriangle *) cmd_ptr)->pos2,
                        ((DispCmdTriangle *) cmd_ptr)->pos3,
                        sizeof(float) * 3) ||
                !memcmp(((DispCmdTriangle *) cmd_ptr)->pos2,
                        ((DispCmdTriangle *) cmd_ptr)->pos3,
                        sizeof(float) * 3)) {
               // degenerate triangle
               break;
            }

            // allocate memory
            depth_obj.points = (float *) malloc(sizeof(float) * 6);
            if (!depth_obj.points) {
               // memory error
               if (!memerror) {
                  memerror = 1;
                  msgErr << "PSDisplayDevice: Out of memory. Some " <<
                     "objects were not drawn." << sendmsg;
               }
               break;
            }

            // copy data
            depth_obj.npoints = 3;
            depth_obj.color = (nc >= 0) ? nc : colorIndex;
            (transMat.top()).multpoint3d(((DispCmdTriangle *) cmd_ptr)->pos1, a);
            (transMat.top()).multpoint3d(((DispCmdTriangle *) cmd_ptr)->pos2, b);
            (transMat.top()).multpoint3d(((DispCmdTriangle *) cmd_ptr)->pos3, c);
            memcpy(depth_obj.points, a, sizeof(float) * 2);
            memcpy(&depth_obj.points[2], b, sizeof(float) * 2);
            memcpy(&depth_obj.points[4], c, sizeof(float) * 2);

            // compute the centerpoint of the object
            cent[0] = (a[0] + b[0] + c[0]) / 3;
            cent[1] = (a[1] + b[1] + c[1]) / 3;
            cent[2] = (a[2] + b[2] + c[2]) / 3;

            // compute the distance to the eye for depth sorting
            depth_obj.dist = compute_dist(cent);

            // compute a light shading factor
            depth_obj.light_scale = compute_light(a, b, c);

            // valid object to depth sort
            draw = 1;
            break;

         case DTRIMESH_C4F_N3F_V3F:
            // call a separate routine to break up the mesh into
            // its component triangles
            decompose_mesh((DispCmdTriMesh *) cmd_ptr);
            break;

         case DTRISTRIP:
            // call a separate routine to break up the strip into
            // its component triangles
            decompose_tristrip((DispCmdTriStrips *) cmd_ptr);
            break;

         case DSQUARE:
            // check for degenerate quadrilateral
            if (!memcmp(((DispCmdSquare *) cmd_ptr)->pos1,
                        ((DispCmdSquare *) cmd_ptr)->pos2,
                        sizeof(float) * 3) ||
                !memcmp(((DispCmdSquare *) cmd_ptr)->pos1,
                        ((DispCmdSquare *) cmd_ptr)->pos3,
                        sizeof(float) * 3) ||
                !memcmp(((DispCmdSquare *) cmd_ptr)->pos1,
                        ((DispCmdSquare *) cmd_ptr)->pos4,
                        sizeof(float) * 3) ||
                !memcmp(((DispCmdSquare *) cmd_ptr)->pos2,
                        ((DispCmdSquare *) cmd_ptr)->pos3,
                        sizeof(float) * 3) ||
                !memcmp(((DispCmdSquare *) cmd_ptr)->pos2,
                        ((DispCmdSquare *) cmd_ptr)->pos4,
                        sizeof(float) * 3) ||
                !memcmp(((DispCmdSquare *) cmd_ptr)->pos3,
                        ((DispCmdSquare *) cmd_ptr)->pos4,
                        sizeof(float) * 3)) {
               // degenerate quadrilateral
               break;
            }

            // allocate memory
            depth_obj.points = (float *) malloc(sizeof(float) * 8);
            if (!depth_obj.points) {
               // memory error
               if (!memerror) {
                  memerror = 1;
                  msgErr << "PSDisplayDevice: Out of memory. Some " <<
                     "objects were not drawn." << sendmsg;
               }
               break;
            }

            // copy data
            depth_obj.npoints = 4;
            depth_obj.color = colorIndex;
            (transMat.top()).multpoint3d(((DispCmdSquare *) cmd_ptr)->pos1, a);
            (transMat.top()).multpoint3d(((DispCmdSquare *) cmd_ptr)->pos2, b);
            (transMat.top()).multpoint3d(((DispCmdSquare *) cmd_ptr)->pos3, c);
            (transMat.top()).multpoint3d(((DispCmdSquare *) cmd_ptr)->pos4, d);
            memcpy(depth_obj.points, a, sizeof(float) * 2);
            memcpy(&depth_obj.points[2], b, sizeof(float) * 2);
            memcpy(&depth_obj.points[4], c, sizeof(float) * 2);
            memcpy(&depth_obj.points[6], d, sizeof(float) * 2);

            // compute the centerpoint of the object
            cent[0] = (a[0] + b[0] + c[0] + d[0]) / 4;
            cent[1] = (a[1] + b[1] + c[1] + d[1]) / 4;
            cent[2] = (a[2] + b[2] + c[2] + d[2]) / 4;

            // compute the distance to the eye for depth sorting
            depth_obj.dist = compute_dist(cent);

            // compute a light shading factor
            depth_obj.light_scale = compute_light(a, b, c);

            // valid object to depth sort
            draw = 1;
            break;

         case DCOLORINDEX:
            colorIndex = ((DispCmdColorIndex *) cmd_ptr)->color;
            break;

         case DSPHERERES:
            set_sphere_res(((int *) cmd_ptr)[0]);
            break;

         default:
            // unknown object, so just skip it
            break;
      }

      // if we have a valid object to add to the depth sort list
      if (draw && depth_obj.npoints) {
         memusage += sizeof(float) * 2 * depth_obj.npoints;
         if ( depth_obj.text )
           memusage += sizeof(char) * (1+strlen(depth_obj.text));
         points += depth_obj.npoints;
         objects++;
         depth_list.append(depth_obj);
      }

      depth_obj.npoints = 0;
      depth_obj.points = NULL;

   } // while (tok != DLASTCOMMAND)

     transMat.pop();
   } // end for() [periodic images]
}
Exemple #7
0
// To write an X3DOM-compatible scene file, we cannot include
// LineProperties nodes.
void X3DOMDisplayDevice::text(float *pos, float size, float thickness,
                               const char *str) {
  float textpos[3];
  float textsize;
  hersheyhandle hh;

  // transform the world coordinates
  (transMat.top()).multpoint3d(pos, textpos);
  textsize = size * 1.5f;

  ResizeArray<int>   idxs; 
  ResizeArray<float> pnts;
  idxs.clear();
  pnts.clear();

  int idx=0;
  while (*str != '\0') {
    float lm, rm, x, y;
    int draw;
    x=y=0.0f;
    draw=0;

    hersheyDrawInitLetter(&hh, *str, &lm, &rm);
    textpos[0] -= lm * textsize;

    while (!hersheyDrawNextLine(&hh, &draw, &x, &y)) {
      float pt[3];

      if (draw) {
        // add another connected point to the line strip
        idxs.append(idx);

        pt[0] = textpos[0] + textsize * x;
        pt[1] = textpos[1] + textsize * y;
        pt[2] = textpos[2];

        pnts.append(pt[0]);
        pnts.append(pt[1]);
        pnts.append(pt[2]);

        idx++;
      } else {
        idxs.append(-1); // pen-up, end of the line strip
      }
    }
    idxs.append(-1); // pen-up, end of the line strip
    textpos[0] += rm * textsize;
    str++;
  }

  fprintf(outfile, "<Shape>\n");
  fprintf(outfile, "  ");

  // 
  // Emit the line properties
  // 
  fprintf(outfile, "<Appearance><Material ");
  fprintf(outfile, "ambientIntensity='%g' ", mat_ambient);
  fprintf(outfile, "diffuseColor='0 0 0' "); 

  const float *rgb = matData[colorIndex];
  fprintf(outfile, "emissiveColor='%g %g %g' ",
          mat_diffuse * rgb[0], mat_diffuse * rgb[1], mat_diffuse * rgb[2]);
  fprintf(outfile, "/>");

#if 0
  // XXX X3DOM v1.1 doesn't handle LineProperties nodes
  // emit a line thickness directive, if needed
  if (thickness < 0.99f || thickness > 1.01f) {
    fprintf(outfile, "  <LineProperties linewidthScaleFactor=\"%g\" "
            "containerField=\"lineProperties\"/>\n",
            (double) thickness);
  }
#endif
  fprintf(outfile, "</Appearance>\n");

  //
  // Emit the line set
  // 
  fprintf(outfile, "  <IndexedLineSet coordIndex='");
  int i, cnt;
  cnt = idxs.num();
  for (i=0; i<cnt; i++) {
    fprintf(outfile, "%d ", idxs[i]);
  }
  fprintf(outfile, "'>\n");

  fprintf(outfile, "    <Coordinate point='");
  cnt = pnts.num();
  for (i=0; i<cnt; i+=3) {
    fprintf(outfile, "%c%g %g %g", 
            (i==0) ? ' ' : ',',
            pnts[i], pnts[i+1], pnts[i+2]);
  }
  fprintf(outfile, "'/>\n");
  fprintf(outfile, "  </IndexedLineSet>\n");
  fprintf(outfile, "</Shape>\n");
}
  int
  DisplayDevice::pick (int dim, const float *pos, const VMDDisplayList *cmdList,
      float &eyedist, int *unitcell, float window_size)
  {
    char *cmdptr = NULL;
    int tok;
    float newEyeDist, currEyeDist = eyedist;
    int tag = (-1), inRegion, currTag;
    int minX = 0, minY = 0, maxX = 0, maxY = 0;
    float fminX = 0.0f, fminY = 0.0f, fminZ = 0.0f, fmaxX = 0.0f, fmaxY = 0.0f,
        fmaxZ = 0.0f;
    float pntpos[3];
    long cpos[2];

    if (!cmdList)
      return (-1);

    // initialize picking: find screen region to look for object
    if (dim == 2)
    {
      fminX = pos[0] - window_size;
      fmaxX = pos[0] + window_size;
      fminY = pos[1] - window_size;
      fmaxY = pos[1] + window_size;
      abs_screen_pos (fminX, fminY);
      abs_screen_pos (fmaxX, fmaxY);
      minX = (int) fminX;
      maxX = (int) fmaxX;
      minY = (int) fminY;
      maxY = (int) fmaxY;
    }
    else
    {
      fminX = pos[0] - window_size;
      fmaxX = pos[0] + window_size;
      fminY = pos[1] - window_size;
      fmaxY = pos[1] + window_size;
      fminZ = pos[2] - window_size;
      fmaxZ = pos[2] + window_size;
    }

    // make sure we do not disturb the regular transformation matrix
    transMat.dup ();
    (transMat.top ()).multmatrix (cmdList->mat);

    // Transform the current pick point for each periodic image
    ResizeArray<Matrix4> pbcImages;
    ResizeArray<int> pbcCells;
    find_pbc_images (cmdList, pbcImages);
    find_pbc_cells (cmdList, pbcCells);
    int pbcimg;
    for (pbcimg = 0; pbcimg < pbcImages.num (); pbcimg++)
    {
      transMat.dup ();
      (transMat.top ()).multmatrix (pbcImages[pbcimg]);

      // scan through the list, getting each command and executing it, until
      // the end of commands token is found
      VMDDisplayList::VMDLinkIter cmditer;
      cmdList->first (&cmditer);
      float *dataBlock = NULL;
      while ((tok = cmdList->next (&cmditer, cmdptr)) != DLASTCOMMAND)
      {
        switch (tok)
        {
          case DDATABLOCK:
#ifdef VMDCAVE
            dataBlock = (float *)cmdptr;
#else
            dataBlock = ((DispCmdDataBlock *) cmdptr)->data;
#endif
            break;

          case DPICKPOINT:
          case DPICKPOINT_I:
            // calculate the transformed position of the point
            if (tok == DPICKPOINT)
            {
              DispCmdPickPoint *cmd = (DispCmdPickPoint *) cmdptr;
              (transMat.top ()).multpoint3d (cmd->postag, pntpos);
              currTag = cmd->tag;
            }
            else
            {
              DispCmdPickPointIndex *cmd = (DispCmdPickPointIndex *) cmdptr;
              (transMat.top ()).multpoint3d (dataBlock + cmd->pos, pntpos);
              currTag = cmd->tag;
            }

            // check if in picking region ... different for 2D and 3D
            if (dim == 2)
            {
              // convert the 3D world coordinate to 2D absolute screen coord
              abs_screen_loc_3D (pntpos, cpos);

              // check to see if the position falls in our picking region
              inRegion = (cpos[0] >= minX && cpos[0] <= maxX && cpos[1] >= minY
                  && cpos[1] <= maxY);
            }
            else
            {
              // just check to see if the position is in a box centered on our
              // pointer.  The pointer position should already be transformed.
              inRegion = (pntpos[0] >= fminX && pntpos[0] <= fmaxX
                  && pntpos[1] >= fminY && pntpos[1] <= fmaxY
                  && pntpos[2] >= fminZ && pntpos[2] <= fmaxZ);
            }

            // has a hit occurred?
            if (inRegion)
            {
              // yes, see if it is closer to the eye position than earlier objects
              if (dim == 2)
                newEyeDist = DTOEYE(pntpos[0], pntpos[1], pntpos[2]);
              else
                newEyeDist = DTOPOINT(pntpos[0],pntpos[1],pntpos[2]);

              if (currEyeDist < 0.0 || newEyeDist < currEyeDist)
              {
                currEyeDist = newEyeDist;
                tag = currTag;
                if (unitcell)
                {
                  unitcell[0] = pbcCells[3 * pbcimg];
                  unitcell[1] = pbcCells[3 * pbcimg + 1];
                  unitcell[2] = pbcCells[3 * pbcimg + 2];
                }
              }
            }
            break;

          case DPICKPOINT_IARRAY:
            // loop over all of the pick points in the pick point index array
            DispCmdPickPointIndexArray *cmd =
                (DispCmdPickPointIndexArray *) cmdptr;
            float *pickpos;
            int *indices;
            cmd->getpointers (indices);

            int i;
            for (i = 0; i < cmd->numpicks; i++)
            {
              if (cmd->allselected)
              {
                pickpos = dataBlock + i * 3;
                currTag = i;
              }
              else
              {
                pickpos = dataBlock + indices[i] * 3;
                currTag = indices[i];
              }

              (transMat.top ()).multpoint3d (pickpos, pntpos);

              // check if in picking region ... different for 2D and 3D
              if (dim == 2)
              {
                // convert the 3D world coordinate to 2D absolute screen coord
                abs_screen_loc_3D (pntpos, cpos);

                // check to see if the position falls in our picking region
                inRegion = (cpos[0] >= minX && cpos[0] <= maxX
                    && cpos[1] >= minY && cpos[1] <= maxY);
              }
              else
              {
                // just check to see if the position is in a box centered on our
                // pointer.  The pointer position should already be transformed.
                inRegion = (pntpos[0] >= fminX && pntpos[0] <= fmaxX
                    && pntpos[1] >= fminY && pntpos[1] <= fmaxY
                    && pntpos[2] >= fminZ && pntpos[2] <= fmaxZ);
              }

              // has a hit occurred?
              if (inRegion)
              {
                // yes, see if it is closer to the eye than earlier hits
                if (dim == 2)
                  newEyeDist = DTOEYE(pntpos[0], pntpos[1], pntpos[2]);
                else
                  newEyeDist = DTOPOINT(pntpos[0],pntpos[1],pntpos[2]);

                if (currEyeDist < 0.0 || newEyeDist < currEyeDist)
                {
                  currEyeDist = newEyeDist;
                  tag = currTag;
                  if (unitcell)
                  {
                    unitcell[0] = pbcCells[3 * pbcimg];
                    unitcell[1] = pbcCells[3 * pbcimg + 1];
                    unitcell[2] = pbcCells[3 * pbcimg + 2];
                  }
                }
              }
            }
            break;
        }
      }

      // Pop the PBC image transform
      transMat.pop ();
    } // end of loop over PBC images

    // make sure we do not disturb the regular transformation matrix
    transMat.pop ();

    // return result; if tag >= 0, we found something
    eyedist = currEyeDist;
    return tag;
  }
Exemple #9
0
// read in the startup script, execute it, and then execute any other commands
// which might be necessary (i.e. to load any molecules at start)
// This searches for the startup file in the following
// places (and in this order), reading only the FIRST one found:
//		1. Current directory
//		2. Home directory
//		3. 'Default' directory (here, /usr/local/vmd)
// If a name was given in the -startup switch, that file is checked for ONLY.
void VMDreadStartup(VMDApp *app) {
  char namebuf[512], *envtxt;
  int found = FALSE;
  FILE * tfp;
  char *DataPath; // path of last resort to find a .vmdrc file

  // These options were set by environment variables or command line options
  app->display_set_screen_height(displayHeight);
  app->display_set_screen_distance(displayDist);
  app->set_eofexit(eofexit);
  if (showTitle == TITLE_ON && which_display != DISPLAY_TEXT) {
    app->display_titlescreen();
  }

  if((envtxt = getenv("VMDDIR")) != NULL)
    DataPath = stringdup(envtxt);
  else
    DataPath = stringdup(DEF_VMDENVVAR);
  stripslashes(DataPath); // strip out ending '/' chars.

  // check if the file is available
  if(startupFileStr) {	// name specified by -startup
    if((tfp = fopen(startupFileStr, "rb")) != NULL) {
      found = TRUE;
      fclose(tfp);
      strcpy(namebuf, startupFileStr);
    }
  } else {	// search in different directories, for default file
    const char *def_startup = VMD_STARTUP;
    // first, look in current dir
    strcpy(namebuf, def_startup);
    if((tfp = fopen(namebuf, "rb")) != NULL) {
      found = TRUE;
      fclose(tfp);
    } else {
      // not found in current dir; look in home dir
      if((envtxt = getenv("HOME")) != NULL)
        strcpy(namebuf,envtxt);
      else
        strcpy(namebuf,".");
      strcat(namebuf,"/");
      strcat(namebuf,def_startup);
      if((tfp = fopen(namebuf, "rb")) != NULL) {
        found = TRUE;
        fclose(tfp);
      } else {
        // not found in home dir; look in default dir
	strcpy(namebuf, DataPath);
	strcat(namebuf,"/");
	strcat(namebuf, def_startup);
        if((tfp = fopen(namebuf, "rb")) != NULL) {
          found = TRUE;
          fclose(tfp);
	}
      }
    }
  }
  delete [] DataPath; DataPath = NULL;

  //
  // execute any commands needed at start
  //
  
  // read in molecules requested via command-line switches
  FileSpec spec;
  spec.waitfor = -1; // wait for all files to load before proceeding
  int molid = -1;    // set sentinel value to determine if files were loaded

  if (startNewMoleculeFlags.num() > 0) {
    msgInfo << "File loading in progress, please wait." << sendmsg;
  }

  for (int i=0; i<startNewMoleculeFlags.num(); i++) {
    const char *filename = initFilenames[i];
    const char *filetype = initFiletypes[i];
    if (!filetype) {
      filetype = app->guess_filetype(filename);
      if (!filetype) {
        // assume pdb 
        msgErr << "Unable to determine file type for file '"
          << filename << "'.  Assuming pdb." << sendmsg;
        filetype = "pdb";
      }
    }
    if (startNewMoleculeFlags[i]) {
      molid = app->molecule_load(-1, filename, filetype, &spec);
    } else {
      molid = app->molecule_load(molid, filename, filetype, &spec);
    }
    if (molid < 0) {
      msgErr  << "Loading of startup molecule files aborted." << sendmsg;
      break;
    }
  }

  // if the startup file was found, read in the commands there
  if(found) {
    app->logfile_read(namebuf);
  }

  // Load the extension packages here, _after_ reading the .vmdrc file,
  // so that the search path for extensions can be customized.
  app->commandQueue->runcommand(
    new TclEvalEvent("vmd_load_extension_packages"));   
  
  // Switch to Python if requested, before reading beginCmdFile
  if (cmdFileUsesPython) {
    if (!app->textinterp_change("python")) {
      // bail out since Python scripts won't be readable by Tcl.
      msgErr << "Skipping startup script because Python could not be started." 
             << sendmsg;
      return;
    }
  }
  // after reading in startup file and loading any molecule, the file
  // specified by the -e option is set up to be executed.  
  if(beginCmdFile) {
    app->logfile_read(beginCmdFile);
  } 
}
Exemple #10
0
int VMDinitialize(int *argc, char ***argv) {
  int i;

#if defined VMDMPI
  // hack to fix up env vars if necessary
  for (i=0; i<(*argc); i++) {
    if(!strupcmp((*argv)[i], "-vmddir")) {
      if((*argc) > (i + 1)) {
        setenv("VMDDIR", (*argv)[++i], 1);
      } else {
        msgErr << "-vmddir must specify a fully qualified path." << sendmsg;
      }
    }
  }

  vmd_mpi_init(argc, argv);  // initialize MPI, fix up env vars, etc.
#endif

#if defined(_MSC_VER) && !defined(VMDSEPARATESTARTUP)
  win32vmdstart(); // get registry info etc
#endif

#if !defined(VMDNOMACBUNDLE) && defined(__APPLE__)
  macosxvmdstart(*argc, *argv); // get env variables etc
#endif

  // Tell Tcl where the executable is located
  const char *argv0 = vmd_initialize_tcl((*argv)[0]);

#ifdef VMDTCL
  // register signal handler
  tclhandler = Tcl_AsyncCreate(VMDTclAsyncProc, (ClientData)NULL); 
  signal(SIGINT, (sighandler_t) VMDTclSigHandler);  
#endif

  // Let people know who we are.
  VMDtitle();

  // Tell the user what we think about the hardware we're running on.
  // If VMD is compiled for MPI, then we don't print any of the normal
  // standalone startup messages and instead we use the special MPI-specific
  // node scan startup messages only.
#if !defined(VMDMPI)
#if defined(VMDTHREADS) 
  int vmdnumcpus = wkf_thread_numprocessors();
  msgInfo << "Multithreading available, " << vmdnumcpus <<
             ((vmdnumcpus > 1) ? " CPUs" : " CPU") <<  " detected." 
          << sendmsg;
#endif

  long vmdcorefree = vmd_get_avail_physmem_mb();
  if (vmdcorefree >= 0) {
    long vmdcorepcnt = vmd_get_avail_physmem_percent();
    msgInfo << "Free system memory: " << vmdcorefree 
            << "MB (" << vmdcorepcnt << "%)" << sendmsg;
  }
#endif

  // Read environment variables and command line options.
  // Initialize customArgv with just argv0 to avoid problems with
  // Tcl extension.
  customArgv.append((char *)argv0);
  VMDGetOptions(*argc, *argv); 

#if (!defined(__APPLE__) && !defined(_MSC_VER)) && (defined(VMDOPENGL) || defined(VMDFLTK))
  // If we're using X-windows, we autodetect if the DISPLAY environment
  // variable is unset, and automatically switch back to text mode without
  // requiring the user to pass the "-dispdev text" command line parameters
  if ((which_display == DISPLAY_WIN) && (getenv("DISPLAY") == NULL)) {
    which_display = DISPLAY_TEXT;
  }
#endif

#if defined(VMDTKCON)
  vmdcon_init();
  msgInfo << "Using VMD Console redirection interface." << sendmsg;
  // we default to a widget mode console, unless text mode is requested.
  // we don't have an tcl interpreter registered yet, so it is set to NULL.
  // flushing pending messages to the screen, is only in text mode possible.
  if ((which_display == DISPLAY_TEXT) || just_print_help) {
    vmdcon_use_text(NULL);
    vmdcon_purge();
  } else {
    vmdcon_use_widget(NULL);
  }
#endif

#ifdef VMDFLTK
  // Do various special FLTK initialization stuff here
  if ((which_display != DISPLAY_TEXT)) {
    // Cause FLTK to to use 24-bit color for all windows if possible
    // This must be done before any FLTK windows are shown for the first time.
    if (!Fl::visual(FL_DOUBLE | FL_RGB8)) {
      if (!Fl::visual(FL_RGB8)) {
        Fl::visual(FL_RGB); 
      }
    }

    // Disable the use of the arrow keys for navigating buttons and other
    // non-text widgets, we'll try it out and see how it pans out
    Fl::visible_focus(0);

    // Disable Drag 'n Drop since the only text field in VMD is the
    // atomselection input and DND severely gets in the way there.
    Fl::dnd_text_ops(0);
  }
#endif

  // Quit now if the user just wanted a list of command line options.
  if (just_print_help) {
    vmd_sleep(10);  // This is here so that the user can see the message 
                    // before the terminal/shell exits...
    return 0;
  }

  // Set up default allocators; these may be overridden by cave or freevr. 
  vmd_alloc   = malloc;  // system malloc() in the default case
  vmd_dealloc = free;    // system free() in the default case
  vmd_realloc = realloc; // system realloc(), set to NULL when not available 

  // check for a CAVE display
  if (DISPLAY_USES_CAVE(which_display)) {
#ifdef VMDCAVE
    // allocate shared memory pool used to communicate with child renderers
    int megs = 2048;
    if (getenv("VMDCAVEMEM") != NULL) {
      megs = atoi(getenv("VMDCAVEMEM"));
    } 
    msgInfo << "Attempting to get " << megs << 
            "MB of CAVE Shared Memory" << sendmsg;
    grab_CAVE_memory(megs);

    CAVEConfigure(argc, *argv, NULL); // configure cave walls and memory use

    // point VMD shared memory allocators to CAVE routines
    vmd_alloc = malloc_from_CAVE_memory;
    vmd_dealloc = free_to_CAVE_memory;
    vmd_realloc = NULL; // no realloc() functionality is available presently
#else
    msgErr << "Not compiled with the CAVE options set." << sendmsg;
    which_display = DISPLAY_WIN;    
#endif
  }

  // check for a FreeVR display
  if (DISPLAY_USES_FREEVR(which_display)) {
#ifdef VMDFREEVR
    int megs = 2048;
    if (getenv("VMDFREEVRMEM") != NULL) {
      megs = atoi(getenv("VMDFREEVRMEM"));
    } 
    msgInfo << "Attempting to get " << megs << 
            "MB of FreeVR Shared Memory" << sendmsg;
    grab_FreeVR_memory(megs); // have to do this *before* vrConfigure() if
                              // we want more than the default shared mem.
    vrConfigure(NULL, NULL, NULL); // configure FreeVR walls

    // point shared memory allocators to FreeVR routines
    vmd_alloc = malloc_from_FreeVR_memory;
    vmd_dealloc = free_to_FreeVR_memory;
    vmd_realloc = NULL; // no realloc() functionality is available presently
#else
    msgErr << "Not compiled with the FREEVR options set." << sendmsg;
    which_display = DISPLAY_WIN;    
#endif
  }

  // return custom argc/argv
  *argc = customArgv.num();
  for (i=0; i<customArgv.num(); i++) {
    (*argv)[i] = customArgv[i];
  }
  return 1; // successful startup
}
int text_cmd_mobile(ClientData cd, Tcl_Interp *interp, int argc,
                            const char *argv[]) {

  VMDApp *app = (VMDApp *)cd;

  if (argc < 3 || argc > 6) {
    // if here, something went wrong, so return an error message
    mobile_usage(interp);
    return TCL_ERROR;
  }

  if (!strupncmp(argv[1], "mode", CMDLEN)) {
    int m1 = Mobile::OFF;
    // see if these are string values
    if (!strupncmp(argv[2], "off", CMDLEN))          m1 = Mobile::OFF;
    else if (!strupncmp(argv[2], "move", CMDLEN))    m1 = Mobile::MOVE;
    else if (!strupncmp(argv[2], "animate", CMDLEN)) m1 = Mobile::ANIMATE;
    else if (!strupncmp(argv[2], "tracker", CMDLEN)) m1 = Mobile::TRACKER;
    else if (!strupncmp(argv[2], "user", CMDLEN))    m1 = Mobile::USER;
    else mobile_usage(interp); // error 

    if (!app->mobile_set_mode(m1)) {
      Tcl_AppendResult(interp, "Unable to set Mobile mode to ",
          argv[2], argc > 3 ? argv[3] : NULL, NULL);

      // if here, something went wrong, so return an error message
      mobile_usage(interp);
      return TCL_ERROR;
    }
  } else if(!strupncmp(argv[1], "port", CMDLEN)) {
    int port;
    if (sscanf(argv[2], "%d", &port) == 1) {
      if (!app->mobile_network_port(port)) {
        // if here, something went wrong, so return an error message
        mobile_usage(interp);
        return TCL_ERROR;
      }
    } else {
      // if here, something went wrong, so return an error message
      mobile_usage(interp);
      return TCL_ERROR;
    }
  } else if(!strupncmp(argv[1], "get", CMDLEN)) {
    if (!strupncmp(argv[2], "mode", CMDLEN))          
    {
       Tcl_AppendResult(interp, Mobile::get_mode_str((Mobile::MoveMode)app->mobile_get_mode()), NULL);
    } else if (!strupncmp(argv[2], "clientList", CMDLEN)) {
       ResizeArray <JString *>* ip;
       ResizeArray <JString *>* nick;
       ResizeArray <bool>* active;
       app->mobile_get_client_list( nick, ip, active);
       for (int i=0; i<nick->num(); i++)
       {
          Tcl_AppendResult(interp, " {", NULL);

          Tcl_AppendResult(interp, " {", NULL);
          // here's what we've got..
          //   (const char *)(*(*nick)[i])
          //      now to explain it....
          //   (const char *)               Tcl_AppendResult needs a char*
          //                 (*          )  We have a JString* in ResizeArray that we want to be a JString   
          //                   (*nick)      we have a ResizeArray ptr that we want to be a ResizeArray
          //                          [i]   specific array elem
          Tcl_AppendResult(interp, (const char *)(*(*nick)[i]), NULL);
          Tcl_AppendResult(interp, "}", NULL);

          Tcl_AppendResult(interp, " {", NULL);
          Tcl_AppendResult(interp, (const char *)(*(*ip)[i]), NULL);
          Tcl_AppendResult(interp, "}", NULL);

          Tcl_AppendResult(interp, " {", NULL);
          char tmp[10]; sprintf(tmp, "%d", (*active)[i]);
          Tcl_AppendResult(interp, tmp, NULL);
          Tcl_AppendResult(interp, "}", NULL);

          Tcl_AppendResult(interp, " }", NULL);
       }

    } else if (!strupncmp(argv[2], "port", CMDLEN)) {
       char tmpstr[20];
       sprintf(tmpstr, "%d", app->mobile_get_network_port());
       Tcl_AppendResult(interp, tmpstr, NULL);
    } else if (!strupncmp(argv[2], "APIsupported", CMDLEN)) {
       char tmpstr[20];
       sprintf(tmpstr, "%d", app->mobile_get_APIsupported());
       Tcl_AppendResult(interp, tmpstr, NULL);
    } else mobile_usage(interp); // error 

  } else if(!strupncmp(argv[1], "sendMsg", CMDLEN)) {
    if (argc >= 6)
    {
       if (!app->mobile_sendMsg(argv[2], argv[3], argv[4], argv[5])) {

            // if here, something went wrong, so return an error message
         mobile_usage(interp);
         return TCL_ERROR;
       }
    } else mobile_usage(interp); // error 

  } else if(!strupncmp(argv[1], "set", CMDLEN)) {
    if (!strupncmp(argv[2], "activeClient", CMDLEN))          
    {
       if (argc >= 5)
       {
          if (!app->mobile_set_activeClient(argv[3], argv[4])) {
//         Tcl_AppendResult(interp, "Unable to set activeClient to ",
//             argv[2], argc > 3 ? argv[3] : NULL, NULL);

            // if here, something went wrong, so return an error message
            mobile_usage(interp);
            return TCL_ERROR;
          }
       } else mobile_usage(interp); // error 

    } else mobile_usage(interp); // error 

  } else {
    // if here, something went wrong, so return an error message
    mobile_usage(interp);
    return TCL_ERROR;
  }
  
  // if here, everything worked out ok
  return TCL_OK;
}