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

P_Tool.C

Go to the documentation of this file.
00001 /***************************************************************************
00002  *cr                                                                       
00003  *cr            (C) Copyright 1995-2019 The Board of Trustees of the           
00004  *cr                        University of Illinois                       
00005  *cr                         All Rights Reserved                        
00006  *cr                                                                   
00007  ***************************************************************************/
00008 
00009 /***************************************************************************
00010  * RCS INFORMATION:
00011  *
00012  *      $RCSfile: P_Tool.C,v $
00013  *      $Author: johns $        $Locker:  $             $State: Exp $
00014  *      $Revision: 1.84 $       $Date: 2019/01/24 04:57:13 $
00015  *
00016  ***************************************************************************
00017  * DESCRIPTION:
00018  * This is Paul's new Tracker code -- pgrayson@ks.uiuc.edu
00019  *
00020  *
00021  ***************************************************************************/
00022 
00023 #include "P_Tracker.h"
00024 #include "P_Feedback.h"
00025 #include "P_Buttons.h"
00026 #include "P_Tool.h"
00027 #include "DispCmds.h"
00028 #include "Scene.h"
00029 #include "VMDApp.h"
00030 #include "AtomSel.h"
00031 #include "MoleculeList.h"
00032 #include "PickList.h"
00033 #include "Displayable.h"
00034 
00036 class DrawTool : public Displayable {
00037 public:
00038   DrawTool(Displayable *aParent) 
00039   : Displayable(aParent) {
00040      
00041     rot_off();  // don't listen to anyone else's transformations
00042     scale_on();
00043     set_scale(1);
00044     scale_off();
00045     glob_trans_off();
00046     cent_trans_off();
00047 
00048     // set up the display list once, since it never changes
00049     DispCmdCone cone;
00050     DispCmdColorIndex drawcolor;
00051     float base[3] = {0, 0.0, 0.0};
00052     float tip[3] = {-0.7f, 0.0, 0.0};
00053     append(DMATERIALON);
00054     drawcolor.putdata(REGTAN, cmdList);
00055     cone.putdata(tip, base, 0.07f, 0, 40, cmdList);
00056     tip[0] = -0.6f;
00057   
00058     base[0] = -0.6f;
00059     base[1] =  0.1f;
00060     base[2] =  0.0f;
00061     cone.putdata(base, tip, 0.04f, 0, 20, cmdList);
00062   }
00063 };
00064 
00065 
00066 Tool::Tool(int serialno, VMDApp *vmdapp, Displayable *aParent)
00067   : UIObject(vmdapp), my_id(serialno) {
00068 
00069   tracker = NULL;
00070   buttons = NULL;
00071   feedback = NULL;
00072   amalive = 1;
00073  
00074   lost_sensor=0;
00075   wasgrabbing=0;
00076   forcescale = 1;
00077   springscale = 1;
00078 
00079   targeted_atom = targeted_molecule = -1;
00080   // As long as a rep is targeted, the targeted molecule must be valid and
00081   // not change.
00082   targeted_rep = NULL;
00083   sel_total_mass = 0;
00084 
00085   dtool = new DrawTool(aParent);
00086 }
00087 
00088 Tool::~Tool() {
00089   delete dtool;
00090   delete [] targeted_rep;
00091   if (!lost_sensor) {
00092     delete tracker;
00093     delete buttons;
00094     delete feedback;
00095   } 
00096 }
00097 
00098 void Tool::clear_devices() {
00099   forceoff();
00100   delete tracker; tracker = NULL; 
00101   delete buttons; buttons = NULL; 
00102   delete feedback; feedback = NULL;
00103 }
00104 
00105 int Tool::add_tracker(VMDTracker *t, const SensorConfig *config) {
00106   delete tracker;
00107   tracker = t;
00108   if (tracker) {
00109     trackerDev = (char *)config->getdevice();
00110     return tracker->start(config);
00111   } 
00112   return TRUE;
00113 }
00114 int Tool::add_feedback(Feedback *f, const SensorConfig *config) {
00115   delete feedback;
00116   feedback = f;
00117   if (feedback) {
00118     feedbackDev = (char *)config->getdevice();
00119     return feedback->start(config);
00120   } 
00121   return TRUE;
00122 }
00123 int Tool::add_buttons(Buttons *b, const SensorConfig *config) {
00124   delete buttons;
00125   buttons = b;
00126   if (buttons) {
00127     buttonDev = (char *)config->getdevice();
00128     return buttons->start(config);
00129   } 
00130   return TRUE;
00131 }
00132 
00133 int Tool::remove_device(const char *device) {
00134   if (tracker && !strcmp(device, (const char *)trackerDev)) {
00135     delete tracker;
00136     tracker = NULL;
00137   } else if (feedback && !strcmp(device, (const char *)feedbackDev)) {
00138     delete feedback;
00139     feedback = NULL;
00140   } else if (buttons && !strcmp(device, (const char *)buttonDev)) {
00141     delete buttons;
00142     buttons = NULL;
00143   } else {
00144     return 0;
00145   }
00146   return 1;
00147 }
00148 
00149 int Tool::steal_sensor(Tool *from) {
00150   clear_devices();
00151   tracker = from->tracker;
00152   buttons = from->buttons;
00153   feedback = from->feedback;
00154   trackerDev = from->trackerDev;
00155   buttonDev = from->buttonDev;
00156   feedbackDev = from->feedbackDev;
00157 
00158   springscale = from->springscale;
00159   forcescale = from->forcescale;
00160   from->lost_sensor = 1;
00161   return TRUE;
00162 }
00163 void Tool::getdevices(char **ret) {
00164   int i=0;
00165   if (tracker) ret[i++] = (char *)(const char *)trackerDev;
00166   if (buttons) ret[i++] = (char *)(const char *)buttonDev;
00167   if (feedback) ret[i++] = (char *)(const char *)feedbackDev;
00168   ret[i] = NULL;
00169 }
00170 
00171 int Tool::isgrabbing() {
00172   if (buttons) return buttons->state(0);
00173   return 0;
00174 }
00175 
00176 const float *Tool::position() const {
00177   if (tracker) return pos;
00178   return NULL;
00179 }
00180 
00181 const Matrix4 *Tool::orientation() {
00182   if (tracker) return &orient;
00183   return NULL;
00184 }
00185 
00186 void Tool::update() {
00187   if (tracker) {
00188     tracker->update();
00189     if (!tracker->alive()) {
00190       msgWarn << "Tool: lost connection to tracker " << tracker->device_name() 
00191               << sendmsg;
00192       amalive = 0;
00193       delete tracker;
00194       tracker = NULL;
00195     } else {
00196       const float *tmp = tracker->position();
00197       for (int i=0; i<tracker->dimension(); i++) pos[i] = tmp[i];
00198       orient.loadmatrix(tracker->orientation());
00199     }
00200   }
00201   if (buttons) buttons->update();
00202   if (feedback) feedback->update();
00203 }
00204 
00205 int Tool::check_event() {
00206   update();
00207 
00208   // subclass-specific action
00209   do_event();
00210 
00211   // update the visual orientation of the tool if there is a tracker
00212   if (tracker) {
00213     dtool->rot_on();
00214     dtool->glob_trans_on();
00215     dtool->set_rot(*orientation());
00216     dtool->set_glob_trans(position()[0], position()[1], position()[2]);
00217     dtool->rot_off();
00218     dtool->glob_trans_off();
00219   }
00220   return 1;
00221 }
00222 
00223 void Tool::setscale(float sc) {
00224   if (tracker) tracker->set_scale(sc);
00225 }
00226 float Tool::getscale() {
00227   if (tracker) return tracker->get_scale();
00228   return 0;
00229 }
00230 
00231 void Tool::setoffset(float *offset) {
00232   if (tracker) tracker->set_offset(offset);
00233 }
00234 const float *Tool::getoffset() {
00235   if (tracker) return tracker->get_offset();
00236   return NULL;
00237 }
00238 
00239 int Tool::assign_rep(int mol, int rep) {
00240   Molecule *m = app->moleculeList->mol_from_id(mol);
00241   if (!m) return FALSE;
00242   DrawMolItem *item = m->component(rep);
00243   if (!item) return FALSE;
00244   clear_rep();
00245   targeted_rep = stringdup(item->name);
00246   targeted_molecule = mol;
00247   const AtomSel *sel = item->atomSel;
00248 
00249   // get the total mass
00250   sel_total_mass=0;
00251   const float *mass = m->mass();
00252   for (int i=sel->firstsel; i<=sel->lastsel; i++) {
00253     if (sel->on[i]) {
00254       sel_total_mass += mass[i];
00255     }
00256   }
00257 
00258   // kill the highlight
00259   if (app->pickList) {
00260     app->pickList->pick_callback_clear((char *)"uivr");
00261   }  
00262   return TRUE;
00263 }
00264  
00265 int Tool::get_targeted_atom(int *molret, int *atomret) const {
00266   if (targeted_rep != NULL) return 0; // must be an atom
00267   if (targeted_molecule == -1) return 0; // must be targeted
00268   *molret = targeted_molecule;
00269   *atomret = targeted_atom;
00270   return 1;
00271 }
00272 
00273 void Tool::tool_location_update() {
00274   int tag;
00275 
00276   // pick a nearby atom if necessary
00277   if(position() && make_callbacks && !targeted_rep) 
00278     app->pickList->pick_check(3, position(), tag, NULL,
00279                     0.2f,(char *)"uivr");
00280 }
00281 
00282 int Tool::target(int target_type, float *mpos, int just_checking) {
00283   int mol = -1;
00284   int atom = -1;
00285   int tag = -1;
00286   Molecule *m;
00287   Matrix4 globm;
00288 
00289   mpos[0]=mpos[1]=mpos[2]=0;
00290 
00291   // is the position NULL?
00292   if(!position()) return 0;
00293 
00294   // are we selecting something?
00295   if(targeted_rep && target_type == TARGET_TUG) {
00296     // Check that the targeted rep still exists
00297     int repid = app->molrep_get_by_name(targeted_molecule, targeted_rep);
00298     if (repid >= 0 && app->molecule_numframes(targeted_molecule) > 0) {
00299       Molecule *m = app->moleculeList->mol_from_id(targeted_molecule);
00300       Timestep *ts = m->current();
00301       const AtomSel *sel = m->component(repid)->atomSel;
00302       
00303       // Loop over each atom in the selection to get the COM.
00304       float com[3] = {0,0,0};
00305       const float *amass = m->mass();
00306       for (int i=sel->firstsel; i<=sel->lastsel; i++) {
00307         if (sel->on[i]) {
00308           float mass = amass[i];
00309           float *p = ts->pos + 3*i;
00310           com[0] += p[0]*mass;
00311           com[1] += p[1]*mass;
00312           com[2] += p[2]*mass;
00313         }
00314       }
00315       vec_scale(com,1/sel_total_mass,com);
00316     
00317       // Now transform the coordinates for the tracker
00318       globm = m->tm; // use centering as well, so we find the exact atom
00319       globm.multpoint3d(com,mpos);
00320   
00321       return 1;
00322     } else {
00323       // Our targeted rep has flown the coop.  Fall back on regular target
00324       clear_rep();
00325     }
00326   }
00327 
00328   if(targeted_molecule == -1) {
00329     Pickable *p=NULL;
00330     if (app->display) {
00331       if(make_callbacks) {
00332         p = app->pickList->pick_check(3, position(), tag, NULL, 0.2f,
00333                                     (char *)"uivr");
00334       } else {
00335         p = app->pickList->pick_check(3, position(), tag, NULL, 0.2f);
00336       }
00337 
00338       if (p) {
00339         Molecule *m = app->moleculeList->check_pickable(p);
00340         if (m) {
00341           mol = m->id();
00342           atom = tag;
00343         }
00344       }
00345     }
00346   
00347     if (atom == -1 || mol == -1) return 0;
00348 
00349     if(!just_checking) {
00350       targeted_atom = atom;
00351       targeted_molecule = mol;
00352     }
00353   }
00354   else {
00355     atom = targeted_atom;
00356     mol = targeted_molecule;
00357   }
00358 
00359   m = app->moleculeList->mol_from_id(mol);
00360 
00361   /* verify sanity */
00362   if(m==NULL) {
00363     msgErr << "Tool: Bad molecule ID found." << sendmsg;
00364     let_go();
00365     return 0;
00366   }
00367 
00368   /* Now return the correct position to the targeting tool */
00369   if(target_type == TARGET_GRAB) { // target a molecule
00370     globm.translate(m->globt);
00371     vec_copy(mpos, m->globt);
00372   } else { // target an atom
00373     globm = m->tm; // use centering as well, so we find the exact atom
00374     Timestep *ts = m->current();
00375     if(ts->pos == NULL) {
00376       msgErr << "Timestep has NULL position." << sendmsg;
00377     }
00378 
00379     float *p = ts->pos + 3*atom;
00380 
00381     globm.multpoint3d(p,mpos);
00382   }    
00383 
00384   return 1;
00385 }
00386 
00387 void Tool::tug(const float *theforce) {
00388   Molecule *m = app->moleculeList->mol_from_id(targeted_molecule);  
00389   if (!m) return;
00390 
00391   Matrix4 rot = m->rotm;
00392   // since this is an orthogonal matrix, a transpose is an inverse
00393   rot.transpose();
00394   float force[3];
00395   rot.multpoint3d(theforce, force);
00396 
00397   if (targeted_rep) {
00398     // if there is a selection, pull with a total force <force>
00399     const AtomSel *sel = m->component(
00400       app->molrep_get_by_name(targeted_molecule, targeted_rep))->atomSel;
00401     const float *amass = m->mass();
00402     for (int i=sel->firstsel; i<=sel->lastsel; i++) {
00403       if (sel->on[i]) {
00404         float mass = amass[i];
00405         float atomforce[3];
00406         vec_scale(atomforce,mass/sel_total_mass,force);
00407         m->addForce(i, atomforce);
00408       }
00409     }
00410   }
00411   else {
00412     // otherwise just pull with a simple force
00413     m->addForce(targeted_atom, force);
00414   }
00415 }
00416 
00417 void Tool::dograb() {
00418   Molecule *m;
00419   Matrix4 rot;
00420   float p[3], mpos[3], mdiff[3], mrotdiff[3], mchange[3], futurepos[3];
00421 
00422   m = app->moleculeList->mol_from_id(targeted_molecule);
00423   if(m==NULL) return;
00424 
00425   mpos[0] = m->globt[0];
00426   mpos[1] = m->globt[1];
00427   mpos[2] = m->globt[2];
00428 
00429   if (grabs) {
00430     last_rot.inverse();
00431     rot=*orientation();
00432     rot.multmatrix(last_rot);
00433     p[0] = position()[0] - last_pos[0];
00434     p[1] = position()[1] - last_pos[1];
00435     p[2] = position()[2] - last_pos[2];
00436 
00437     // apply the translation due to translation of the tracker
00438     app->scene_translate_by(p[0], p[1], p[2]);
00439     // where the molecule will be after that command
00440     vec_add(futurepos,p,mpos);
00441 
00442     // rotate the molecule about its center
00443     app->scene_rotate_by(rot.mat);
00444 
00445     // compute the vector between the molecule and the tracker
00446     vec_sub(mdiff,futurepos,position());
00447     // rotate that
00448     rot.multpoint3d(mdiff, mrotdiff);
00449     // and subtract
00450     vec_sub(mchange,mrotdiff,mdiff);
00451     
00452     // giving us the translation for the molecule due to rotation
00453     app->scene_translate_by(mchange[0],mchange[1], mchange[2]);
00454   } else {
00455     int i;
00456 #ifdef VMDVRJUGGLER
00457     // VR Juggler: 
00458     // do this through VMDApp, so the cmd is sent to the slaves as well
00459     for(i=0; i<app->moleculeList->num(); i++) {
00460       int id = app->moleculeList->molecule(i)->id();
00461       app->molecule_fix(id, true);
00462     }
00463     int id = m->id();
00464     app->molecule_fix(id, false);
00465 #else
00466     for(i=0; i<app->moleculeList->num(); i++)
00467       app->moleculeList->molecule(i)->fix();
00468     m->unfix();
00469 #endif
00470   }
00471 
00472   last_rot = *orientation();
00473   last_pos[0] = position()[0];
00474   last_pos[1] = position()[1];
00475   last_pos[2] = position()[2];
00476 }
00477 
00478 void Tool::ungrab() {
00479   int i;
00480   if (!targeted_molecule)
00481     targeted_molecule = -1;
00482 #ifdef VMDVRJUGGLER
00483   // VR Juggler: 
00484   // do this through VMDApp, so the cmd is sent to the slaves as well
00485   for(i=0; i<app->moleculeList->num(); i++) {
00486     int id = app->moleculeList->molecule(i)->id();
00487     app->molecule_fix(id, false);
00488   }
00489 #else
00490   for(i=0;i<app->moleculeList->num();i++)
00491     app->moleculeList->molecule(i)->unfix();
00492 #endif
00493 }
00494 
00495 float Tool::getTargetScale() {
00496   if (targeted_molecule != -1) {
00497     return app->moleculeList->mol_from_id(targeted_molecule)->scale;
00498   }
00499   return 0;
00500 }
00501 
00502 int Tool::dimension() {
00503   if (tracker) return tracker->dimension();
00504   return 0;
00505 }
00506 
00507 void Tool::setplaneconstraint(float k, const float *p, const float *n) {
00508   float scaledpoint[3];
00509   if (!feedback) return;
00510   if (!tracker) return; 
00511   const float *offset = tracker->get_offset();
00512   const float scale = tracker->get_scale();
00513   scaledpoint[0] = p[0]/scale-offset[0];
00514   scaledpoint[1] = p[1]/scale-offset[1];
00515   scaledpoint[2] = p[2]/scale-offset[2];
00516   feedback->zeroforce();
00517   feedback->addplaneconstraint(springscale*k,scaledpoint,n);
00518 }
00519 
00520 void Tool::addplaneconstraint(float k, const float *p, const float *n) {
00521   float scaledpoint[3];
00522   if (!feedback) return;
00523   if (!tracker) return; 
00524   const float *offset = tracker->get_offset();
00525   const float scale = tracker->get_scale();
00526   scaledpoint[0] = p[0]/scale-offset[0];
00527   scaledpoint[1] = p[1]/scale-offset[1];
00528   scaledpoint[2] = p[2]/scale-offset[2];
00529   feedback->addplaneconstraint(springscale*k,scaledpoint,n);
00530 }
00531 
00532 void Tool::setconstraint(float k, const float *p) {
00533   float scaledcenter[3];
00534   if (!feedback) return;
00535   if (!tracker) return; 
00536   const float *offset = tracker->get_offset();
00537   const float scale = tracker->get_scale();
00538   scaledcenter[0] = p[0]/scale-offset[0];
00539   scaledcenter[1] = p[1]/scale-offset[1];
00540   scaledcenter[2] = p[2]/scale-offset[2];
00541   feedback->zeroforce();
00542   feedback->addconstraint(springscale*k,scaledcenter);
00543 }
00544 
00545 void Tool::setforcefield(const float *o, const float *force, 
00546                          const float *jacobian) {
00547 
00548   float sforce[3];
00549   float scaledjacobian[9];
00550   int i;
00551   if (!tracker) return;
00552   if (!feedback) return;
00553   const float scale = tracker->get_scale();
00554   for (i=0; i<3; i++) sforce[i] = force[i]*springscale;
00555   for(i=0;i<9;i++) scaledjacobian[i] = jacobian[i]*springscale/scale;
00556   feedback->zeroforce();
00557   feedback->addforcefield(o, sforce, scaledjacobian);
00558 }
00559 
00560 void Tool::sendforce() {
00561   if (tracker && feedback) feedback->sendforce(position());
00562 }
00563 void Tool::forceoff() {
00564   if (feedback) feedback->forceoff();
00565 }
00566 

Generated on Thu Mar 28 02:43:57 2024 for VMD (current) by doxygen1.2.14 written by Dimitri van Heesch, © 1997-2002