00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
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();
00042 scale_on();
00043 set_scale(1);
00044 scale_off();
00045 glob_trans_off();
00046 cent_trans_off();
00047
00048
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
00081
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
00209 do_event();
00210
00211
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
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
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;
00267 if (targeted_molecule == -1) return 0;
00268 *molret = targeted_molecule;
00269 *atomret = targeted_atom;
00270 return 1;
00271 }
00272
00273 void Tool::tool_location_update() {
00274 int tag;
00275
00276
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
00292 if(!position()) return 0;
00293
00294
00295 if(targeted_rep && target_type == TARGET_TUG) {
00296
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
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
00318 globm = m->tm;
00319 globm.multpoint3d(com,mpos);
00320
00321 return 1;
00322 } else {
00323
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
00362 if(m==NULL) {
00363 msgErr << "Tool: Bad molecule ID found." << sendmsg;
00364 let_go();
00365 return 0;
00366 }
00367
00368
00369 if(target_type == TARGET_GRAB) {
00370 globm.translate(m->globt);
00371 vec_copy(mpos, m->globt);
00372 } else {
00373 globm = m->tm;
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
00393 rot.transpose();
00394 float force[3];
00395 rot.multpoint3d(theforce, force);
00396
00397 if (targeted_rep) {
00398
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
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
00438 app->scene_translate_by(p[0], p[1], p[2]);
00439
00440 vec_add(futurepos,p,mpos);
00441
00442
00443 app->scene_rotate_by(rot.mat);
00444
00445
00446 vec_sub(mdiff,futurepos,position());
00447
00448 rot.multpoint3d(mdiff, mrotdiff);
00449
00450 vec_sub(mchange,mrotdiff,mdiff);
00451
00452
00453 app->scene_translate_by(mchange[0],mchange[1], mchange[2]);
00454 } else {
00455 int i;
00456 #ifdef VMDVRJUGGLER
00457
00458
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
00484
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