void DisplayDevice::find_pbc_cells(const VMDDisplayList *cmdList, 
                                    ResizeArray<int> &pbcCells) {
  int pbc = cmdList->pbc;
  if (pbc == PBC_NONE) {
    pbcCells.append(0);
    pbcCells.append(0);
    pbcCells.append(0);
  } else {
    int npbc = cmdList->npbc;
    int nx = pbc & PBC_X ? npbc : 0;
    int ny = pbc & PBC_Y ? npbc : 0;
    int nz = pbc & PBC_Z ? npbc : 0;
    int nox = pbc & PBC_OPX ? -npbc : 0;
    int noy = pbc & PBC_OPY ? -npbc : 0;
    int noz = pbc & PBC_OPZ ? -npbc : 0;
    int i, j, k;
    for (i=nox; i<=nx; i++) {
      for (j=noy; j<=ny; j++) {
        for (k=noz; k<=nz; k++) {
          if (! (pbc & PBC_NOSELF && !i && !j && !k)) {
            pbcCells.append(i);
            pbcCells.append(j);
            pbcCells.append(k);
          }
        }
      }
    }
  }
}
 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 #4
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;
}
Exemple #5
0
extern "C" void * bondsearchthread(void *voidparms) {
  int i, j, aindex;
  int paircount = 0;

  bondsearchthrparms *parms = (bondsearchthrparms *) voidparms;

  const int threadid = parms->threadid;
  const int threadcount = parms->threadcount;
  wkf_mutex_t *pairlistmutex = parms->pairlistmutex;
  const float *pos = parms->pos;
  const float *radii = parms->radii;
  const int totb = parms->totb;
  const int **boxatom = (const int **) parms->boxatom;
  const int *numinbox = parms->numinbox;
  const int **nbrlist = (const int **) parms->nbrlist; 
  const int maxpairs = parms->maxpairs;
  const float pairdist = parms->pairdist;

  ResizeArray<int> *pairs = new ResizeArray<int>;
  float sqdist = pairdist * pairdist;

  wkfmsgtimer *msgt = wkf_msg_timer_create(5);
  for (aindex = threadid; (aindex < totb) && (paircount < maxpairs); aindex+=threadcount) {
    const int *tmpbox, *nbr;
    tmpbox = boxatom[aindex];
    int anbox = numinbox[aindex];

    if (((aindex & 255) == 0) && wkf_msg_timer_timeout(msgt)) {
      char tmpbuf[128];
      sprintf(tmpbuf, "%6.2f", (100.0f * aindex) / (float) totb);
//  XXX: we have to use printf here as msgInfo is not thread-safe.
//  msgInfo << "vmd_gridsearch_bonds (thread " << threadid << "): " 
//          << tmpbuf << "% complete" << sendmsg;
      printf("vmd_gridsearch_bonds (thread %d): %s %% complete\n", 
        threadid, tmpbuf); 
    }

    for (nbr = nbrlist[aindex]; (*nbr != -1) && (paircount < maxpairs); nbr++) {
      int nnbr=*nbr;
      const int *nbrbox = boxatom[nnbr];
      int nbox=numinbox[nnbr];
      int self = (aindex == nnbr) ? 1 : 0;

      for (i=0; (i<anbox) && (paircount < maxpairs); i++) {
        int ind1 = tmpbox[i];
        const float *p1 = pos + 3L*ind1;

        // skip over self and already-tested atoms
        int startj = (self) ? i+1 : 0;

        for (j=startj; (j<nbox) && (paircount < maxpairs); j++) {
          int ind2 = nbrbox[j];
          const float *p2 = pos + 3L*ind2;
          float dx = p1[0] - p2[0];
          float dy = p1[1] - p2[1];
          float dz = p1[2] - p2[2];
          float ds2 = dx*dx + dy*dy + dz*dz;

          // perform distance test, but ignore pairs between atoms
          // with nearly identical coords
          if ((ds2 > sqdist) || (ds2 < 0.001))
            continue;

          if (radii) { // Do atom-specific distance check
            float cut = 0.6f * (radii[ind1] + radii[ind2]);
            if (ds2 > cut*cut)
              continue;
          }

          pairs->append(ind1);
          pairs->append(ind2);
          paircount++;
        }
      }
    }
  }

  // setup results pairlist node
  GridSearchPairlist *head;
  head = (GridSearchPairlist *) malloc(sizeof(GridSearchPairlist));
  head->next = NULL;
  head->pairlist = pairs;

  wkf_mutex_lock(pairlistmutex);   // lock pairlist before update
  parms->head = head;
  wkf_mutex_unlock(pairlistmutex); // unlock pairlist after update

  wkf_msg_timer_destroy(msgt);

  return NULL;
}
Exemple #6
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");
}
Exemple #7
0
// look for all environment variables VMD can use, and initialize the
// proper variables.  If an env variable is not found, use a default value.
// ENVIRONMENT VARIABLES USED BY VMD (default values set in config.h):
//	VMDDIR		directory with VMD data files and utility programs
//	VMDTMPDIR	directory in which to put temporary files (def: /tmp)
static void VMDGetOptions(int argc, char **argv) {
  char *envtxt;

  //
  // VMDDISPLAYDEVICE: which display device to use by default
  // 
  if((envtxt = getenv("VMDDISPLAYDEVICE"))) {
    for(int i=0; i < NUM_DISPLAY_TYPES; i++) {
      if(!strupcmp(envtxt, displayTypeNames[i])) {
        which_display = i;
        break;
      }
    }
  }

  // 
  // VMDTITLE: whether to enable the title screen
  //  
  if((envtxt = getenv("VMDTITLE"))) {
    for(int i=0; i < NUM_TITLE_TYPES; i++) {
      if(!strupcmp(envtxt, titleTypeNames[i])) {
        showTitle = i;
        break;
      }
    }
  }

  //
  // VMDSCRHEIGHT: height of the screen
  //
  if((envtxt = getenv("VMDSCRHEIGHT")))
    displayHeight = (float) atof(envtxt);

  //
  // VMDSCRDIST: distance to the screen
  //
  if((envtxt = getenv("VMDSCRDIST")))
    displayDist = (float) atof(envtxt); 

  // 
  // VMDSCRPOS: graphics window location
  //
  if((envtxt = getenv("VMDSCRPOS"))) {
    char * dispStr = NULL;
    char * dispArgv[64];
    int dispArgc;

    if((dispStr = str_tokenize(envtxt, &dispArgc, dispArgv)) != NULL
                && dispArgc == 2) {
      displayLoc[0] = atoi(dispArgv[0]);
      displayLoc[1] = atoi(dispArgv[1]);
    } else {
      msgErr << "Illegal VMDSCRPOS environment variable setting '" 
             << envtxt << "'." << sendmsg;
    }
    if(dispStr)  delete [] dispStr;
  }

  // 
  // VMDSCRSIZE: graphics window size
  //
  if((envtxt = getenv("VMDSCRSIZE"))) {
    char * dispStr = NULL;
    char * dispArgv[64];
    int dispArgc;
    if((dispStr = str_tokenize(envtxt, &dispArgc, dispArgv)) != NULL
                && dispArgc == 2) {
      displaySize[0] = atoi(dispArgv[0]);
      displaySize[1] = atoi(dispArgv[1]);
 
      // force users to do something that makes sense
      if (displaySize[0] < 100) 
        displaySize[0] = 100; // minimum sane width
      if (displaySize[1] < 100) 
        displaySize[1] = 100; // minimum sane height

    } else {
      msgErr << "Illegal VMDSCRSIZE environment variable setting '" 
             << envtxt << "'." << sendmsg;
    }
    if(dispStr)  delete [] dispStr;
  }

  // initialize variables which indicate how VMD starts up, and
  // parse the command-line options

  // go through the arguments
  int ev = 1;
  while(ev < argc) {
    if(!strupcmp(argv[ev], "-dist")) {
      if(argc > (ev + 1)) {
        displayDist = (float) atof(argv[++ev]);
      } else
        msgErr << "-dist must also specify a distance." << sendmsg;

    } else if(!strupcmp(argv[ev], "-e")) {
      if(argc > (ev + 1)) {
        beginCmdFile = argv[++ev];
      } else
        msgErr << "-e must also specify a filename." << sendmsg;

    } else if(!strupcmp(argv[ev], "-height")) {
      if(argc > (ev + 1)) {
        displayHeight = (float) atof(argv[++ev]);
      } else
        msgErr << "-height must also specify a distance." << sendmsg;

    } else if(!strupcmp(argv[ev], "-pos")) {
      if(argc > (ev + 2) && *(argv[ev+1]) != '-' && *(argv[ev+2]) != '-') {
        displayLoc[0] = atoi(argv[++ev]);
        displayLoc[1] = atoi(argv[++ev]);
      } else
        msgErr << "-pos must also specify an X Y pair." << sendmsg;

    } else if(!strupcmp(argv[ev], "-size")) {
      if(argc > (ev + 2) && *(argv[ev+1]) != '-' && *(argv[ev+2]) != '-') {
        displaySize[0] = atoi(argv[++ev]);
        displaySize[1] = atoi(argv[++ev]);
      } else
        msgErr << "-size must also specify an X Y pair." << sendmsg;

    } else if(!strupcmp(argv[ev], "-startup")) {
      // use next argument as startup config file name
      if(argc > (ev + 1))
        startupFileStr = argv[++ev];
      else
        msgErr << "-startup must also have a new file name specified."
	       << sendmsg;

    } else if(!strupcmp(argv[ev], "-nt")) {
      // do not print out the program title
      showTitle = TITLE_OFF;

    } else if (!strupcmp(argv[ev], "-dispdev")) {  // startup Display
      ev++;
      if (argc > ev) {
        if (!strupcmp(argv[ev], "cave")) {  
          which_display = DISPLAY_CAVE;        // use the CAVE
        } else if (!strupcmp(argv[ev], "win")) {       
          which_display = DISPLAY_WIN;         // use OpenGL, the default
        } else if (!strupcmp(argv[ev], "opengl")) {  
          which_display = DISPLAY_WINOGL;      // use OpenGL if available
        } else if (!strupcmp(argv[ev], "text")) {
          which_display = DISPLAY_TEXT;        // use text console only 
        } else if (!strupcmp(argv[ev], "caveforms")) {
          which_display = DISPLAY_CAVEFORMS;   // use CAVE+Forms
        } else if (!strupcmp(argv[ev], "freevr")) {
          which_display = DISPLAY_FREEVR;      // use FreeVR
        } else if (!strupcmp(argv[ev], "freevrforms")) {
          which_display = DISPLAY_FREEVRFORMS; // use FreeVR+Forms
        } else if (!strupcmp(argv[ev], "none")) {      
          which_display = DISPLAY_TEXT;        // use text console only
        } else {
          msgErr << "-dispdev options are 'win' (default), 'cave', 'caveforms', 'freevr', 'freevrforms', or 'text | none'" << sendmsg;
        }
      } else {
        msgErr << "-dispdev options are 'win' (default), 'cave', 'caveforms', 'freevr', 'freevrforms', or 'text | none'" << sendmsg;
      }
    } else if (!strupcmp(argv[ev], "-h") || !strupcmp(argv[ev], "--help")) {
      // print out command-line option summary
      msgInfo << "Available command-line options:" << sendmsg;
      msgInfo << "\t-dispdev <win | cave | text | none> Specify display device";
      msgInfo << sendmsg;
      msgInfo << "\t-dist <d>           Distance from origin to screen";
      msgInfo << sendmsg;
      msgInfo << "\t-e <filename>       Execute commands in <filename>\n";
      msgInfo << "\t-python             Use Python for -e file and subsequent text input\n";
      msgInfo << "\t-eofexit            Exit when end-of-file occurs on input\n";
      msgInfo << "\t-h | --help         Display this command-line summary\n";
      msgInfo << "\t-height <h>         Height of display screen";
      msgInfo << sendmsg;
      msgInfo << "\t-pos <X> <Y>        Lower-left corner position of display";
      msgInfo << sendmsg;
      msgInfo << "\t-nt                 No title display at start" << sendmsg;
      msgInfo << "\t-size <X> <Y>       Size of display" << sendmsg;
      msgInfo << "\t-startup <filename> Specify startup script file" << sendmsg;
      msgInfo << "\t-m                  Load subsequent files as separate molecules\n";
      msgInfo << "\t-f                  Load subsequent files into the same molecule\n";
      msgInfo << "\t<filename>          Load file using best-guess file type\n";
      msgInfo << "\t-<type> <filename>  Load file using specified file type\n";
      msgInfo << "\t-args               Pass subsequent arguments to text interpreter\n";
      msgInfo << sendmsg;
      just_print_help = 1;
    } else if (!strupcmp(argv[ev], "-eofexit")) {  // exit on EOF
      eofexit = 1;
    } else if (!strupcmp(argv[ev], "-node")) { 
      // start VMD process on a cluster node, next parm is node ID..
      ev++; // skip node ID parm
    } else if (!strupcmp(argv[ev], "-webhelper")) { 
      // Unix startup script doesn't run VMD in the background, so that
      // web browsers won't delete files out from under us until it really
      // exits.  We don't do anything special inside VMD itself presently
      // however.
    } else if (!strupcmp(argv[ev], "-python")) {
      cmdFileUsesPython = 1;
    } else if (!strupcmp(argv[ev], "-args")) {
      // pass the rest of the command line arguments, and only those, 
      // to the embedded text interpreters.
      while (++ev < argc)
        customArgv.append(argv[ev]);

    } else if (!strupcmp(argv[ev], "-m")) {
      loadAsMolecules = 1;
      startNewMolecule = 1;
    } else if (!strupcmp(argv[ev], "-f")) {
      loadAsMolecules = 0;
      startNewMolecule = 1;
#ifdef VMDMPI
    } else if (!strupcmp(argv[ev], "-vmddir")) {
      ev++; // skip VMDDIR directory parm, since we already handled this
            // in MPI startup before we got to this loop...
#endif
    } else {
      // any other argument is treated either as a filename or as a 
      // filetype/filename pair of the form -filetype filename.
      const char *filename, *filetype;
      if (argv[ev][0] == '-') {
        // must be filetype/filename pair
        if (argc > ev+1) {
          filetype = argv[ev]+1;
          filename = argv[ev+1];
          ev++;
        } else {
          msgErr << "filetype argument '" << argv[ev] << "' needs a filename."
            << sendmsg;
          ev++;  // because we skip past the ev++ at the bottom of the loop.
          continue; 
        }
      } else {
        // Given just a filename.  The filetype will have to be guessed.
        filename = argv[ev];
        filetype = NULL;
      }
      initFilenames.append(filename);
      initFiletypes.append(filetype);
      startNewMoleculeFlags.append(startNewMolecule);
      if (!loadAsMolecules) startNewMolecule = 0;
    }
    ev++;
  }

  // command-line options have been parsed ... any init status variables that
  // have been given initial values will have flags saying so, and their
  // values will not be changed when the init file(s) is parsed.
}
Exemple #8
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
}
// draw a 3-D field lines that follow the volume gradient
void
DrawMolItem::draw_volume_field_lines (int volid, float seedval, float minlen,
    float maxlen, float thickness)
{
  const VolumetricData * v = NULL;
  v = mol->get_volume_data (volid);
  int printdonemesg = 0;

  if (v == NULL)
  {
    msgInfo << "No volume data loaded at index " << volid << sendmsg;
    return;
  }

  int seedcount = 0;
  int pointcount = 0;
  int totalpointcount = 0;
  int usecolor;
  ResizeArray<float> seeds;

  append (DMATERIALOFF);
  usecolor = draw_volume_get_colorid ();
  cmdColorIndex.putdata (usecolor, cmdList);

  seedcount = calcseeds_gradient_magnitude (v, &seeds, seedval * 0.5f,
      seedval * 1.5f);

  // Integrate field lines starting with each of the seeds to simulate
  // particle advection.
  // Uses Euler's approximation for solving the initial value problem.
  // We could get a more accurate solution using a fourth order Runge-Kutta
  // method, but with more math per iteration.  We may want to implement 
  // the integrator as a user selected option.

  // The choice of integration step size is currently arbitrary,
  // but will become a user-defined parameter, since it affects speed
  // and accuracy.  A good default might be 0.25 times the smallest
  // grid cell spacing axis.
  float lx, ly, lz;
  v->cell_lengths (&lx, &ly, &lz);
  float mincelllen = lx;
  mincelllen = (mincelllen < ly) ? mincelllen : ly;
  mincelllen = (mincelllen < lz) ? mincelllen : lz;
  float delta = mincelllen * 0.25f; // delta per step (compensates gradient magnitude)

  // minimum gradient magnitude, before we consider that we've found
  // a critical point in the dataset.
  float mingmag = 0.0001f;

  // max gradient magnitude, before we consider it a source/sink
  float maxgmag = 5;

  ResizeArray<float> points;

  // For each seed point, integrate in both positive and
  // negative directions for a field line length up to
  // the maxlen criterion.
  msgtimer *msgt = msg_timer_create (1);
  int seed;
  for (seed = 0; seed < seedcount; seed++)
  {
    // emit UI messages as integrator runs, for long calculations...
    if (!(seed & 7) && msg_timer_timeout (msgt))
    {
      char tmpbuf[128];
      sprintf (tmpbuf, "%6.2f %% complete",
          (100.0f * seed) / (float) seedcount);
      msgInfo << "integrating " << seedcount << " field lines: " << tmpbuf
          << sendmsg;
      printdonemesg = 1;
    }

    int direction;
    for (direction = -1; direction != 1; direction = 1)
    {
      float pos[3], comsum[3];
      vec_copy (pos, &seeds[seed * 3]); // integration starting point is the seed

      // init the arrays
      points.clear ();

      // main integration loop
      pointcount = 0;
      totalpointcount++;
      float len = 0;
      int iterations = 0;
      float dir = (float) direction;

      vec_zero (comsum); // clear center of mass accumulator

      while ((len < maxlen) && (totalpointcount < 100000000))
      {
        float grad[3];

        // sample gradient at the current position
        v->voxel_gradient_interpolate_from_coord (pos, grad);

        // Early-exit if we run out of bounds (gradient returned will
        // be a vector of NANs), run into a critical point (zero gradient)
        // or a huge gradient at a source/sink point in the dataset.
        float gmag = norm (grad);
        if (gmag < mingmag || gmag > maxgmag)
          break;

        // Draw the current point only after the gradient value
        // has been checked, so we don't end up with out-of-bounds
        // vertices.
        // Only emit a fraction of integration points for display since
        // the integrator stepsize needs to be small for more numerical
        // accuracy, but the field lines themselves can be well 
        // represented with fewer sample points.
        if (!(iterations & 1))
        {
          // Add a vertex for this field line
          points.append (pos[0]);
          points.append (pos[1]);
          points.append (pos[2]);

          vec_incr (comsum, pos);

          pointcount++;
          totalpointcount++;
        }

        // adjust integration stepsize so we never move more than 
        // the distance specified by delta at each step, to compensate
        // for varying gradient magnitude
        vec_scaled_add (pos, dir * delta / gmag, grad); // integrate position
        len += delta; // accumulate distance

        iterations++;
      }

      int drawfieldline = 1;

      // only draw the field line for this seed if we have enough points.
      // If we haven't reached the minimum field line length, we'll
      // drop the whole field line.
      if (pointcount < 2 || len < minlen)
        drawfieldline = 0;

      // only draw if bounding sphere diameter exceeds minlen
      if (drawfieldline)
      {
        float com[3];
        vec_scale (com, 1.0f / (float) pointcount, comsum);
        float minlen2 = minlen * minlen;

        drawfieldline = 0;
        int p;
        for (p = 0; p < pointcount; p++)
        {
          if ((2.0f * distance2 (com, &points[p * 3])) > minlen2)
          {
            drawfieldline = 1;
            break;
          }
        }
      }

      // only draw the field line if it met all selection criteria
      if (drawfieldline)
      {
        cmdLineType.putdata (SOLIDLINE, cmdList);
        cmdLineWidth.putdata ((int) thickness, cmdList);
        cmdColorIndex.putdata (usecolor, cmdList);
        DispCmdPolyLineArray cmdPolyLineArray;
        cmdPolyLineArray.putdata (&points[0], pointcount, cmdList);
      }
    }
  }
  msg_timer_destroy (msgt);

  if (printdonemesg)
    msgInfo << "field line integration complete." << sendmsg;
}
void
DrawMolItem::draw_volume_isosurface_lit_points (const VolumetricData * v,
    float isovalue, int stepsize, int thickness)
{
  int x, y, z;
  float *addr;
  float pos[3];
  float xax[3], yax[3], zax[3];
  ResizeArray<float> centers;
  ResizeArray<float> normals;
  ResizeArray<float> colors;

  int i;
  float vorigin[3];
  for (i = 0; i < 3; i++)
  {
    vorigin[i] = float (v->origin[i]);
  }

  int pointcount = 0;
  int usecolor;
  append (DMATERIALON);
  usecolor = draw_volume_get_colorid ();
  const float *cp = scene->color_value (usecolor);
  cmdColorIndex.putdata (usecolor, cmdList);

  // calculate cell axes
  v->cell_axes (xax, yax, zax);

  for (z = 0; z < v->zsize; z += stepsize)
  {
    for (y = 0; y < v->ysize; y += stepsize)
    {
      addr = &(v->data[(z * (v->xsize * v->ysize)) + (y * v->xsize)]);

      // loop through xsize - 1 rather than the full range
      for (x = 0; x < (v->xsize - 1); x += stepsize)
      {
        float diff, isodiff;

        // draw a point if the isovalue falls between neighboring X samples
        diff = addr[x] - addr[x + 1];
        isodiff = addr[x] - isovalue;
        if ((fabs (diff) > fabs (isodiff)) && (MYSGN(diff) == MYSGN(isodiff)))
        {
          pos[0] = vorigin[0] + x * xax[0] + y * yax[0] + z * zax[0];
          pos[1] = vorigin[1] + x * xax[1] + y * yax[1] + z * zax[1];
          pos[2] = vorigin[2] + x * xax[2] + y * yax[2] + z * zax[2];

          float norm[3];
          vec_copy (norm,
              &v->gradient[(z * v->xsize * v->ysize + y * v->xsize + x) * 3]);

          // draw a point there.
          centers.append (pos[0]);
          centers.append (pos[1]);
          centers.append (pos[2]);
          normals.append (norm[0]);
          normals.append (norm[1]);
          normals.append (norm[2]);
          colors.append (cp[0]);
          colors.append (cp[1]);
          colors.append (cp[2]);

          pointcount++;
        }
      }
    }
  }

  if (pointcount > 0)
  {
    DispCmdLitPointArray cmdLitPointArray;
    cmdLitPointArray.putdata ((float *) &centers[0], (float *) &normals[0],
        (float *) &colors[0], (float) thickness, pointcount, cmdList);
  }
}