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 Wed Nov 19 02:47:03 2025 for VMD (current) by doxygen1.2.14 written by Dimitri van Heesch, © 1997-2002

AltStyle によって変換されたページ (->オリジナル) /