00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053 #include "Spaceball.h"
00054 #include "DisplayDevice.h"
00055 #include "TextEvent.h"
00056 #include "CommandQueue.h"
00057 #include "Inform.h"
00058 #include "PickList.h"
00059 #include "Animation.h"
00060 #include "VMDApp.h"
00061 #include "math.h"
00062 #include "stdlib.h"
00063
00064
00065
00066
00067 #if defined(VMDTDCONNEXION) && defined(__APPLE__)
00068 #include <unistd.h>
00069 #include <Carbon/Carbon.h>
00070 #include <stdio.h>
00071 #include <stdlib.h>
00072
00073
00074 #include "3DconnexionClient/ConnexionClientAPI.h"
00075
00076 extern "C" {
00077 extern OSErr InstallConnexionHandlers(ConnexionMessageHandlerProc messageHandler, ConnexionAddedHandlerProc addedHandler, ConnexionRemovedHandlerProc removedHandler) __attribute__((weak_import));
00078 }
00079
00080
00081
00082
00083 #if defined(ARCH_MACOSX)
00084 static UInt8 *executablename = (UInt8 *) "\pvmd_MACOSX";
00085 #elif defined(ARCH_MACOSXX86)
00086 static UInt8 *executablename = (UInt8 *) "\pvmd_MACOSXX86";
00087 #elif defined(ARCH_MACOSXX86_64)
00088 static UInt8 *executablename = (UInt8 *) "\pvmd_MACOSXX86_64";
00089 #else
00090 #error
00091 #endif
00092
00093 typedef struct {
00094 int enabled;
00095 UInt16 client;
00096 int tx;
00097 int ty;
00098 int tz;
00099 int rx;
00100 int ry;
00101 int rz;
00102 int buttons;
00103 int eventcount;
00104 } tdx_data;
00105
00106
00107 static tdx_data tdxevent;
00108
00109
00110
00111
00112
00113
00114
00115
00116
00117 static void tdx_msghandler(io_connect_t connection,
00118 natural_t msgtype, void *msgarg) {
00119 ConnexionDeviceState *state = NULL;
00120 switch (msgtype) {
00121 case kConnexionMsgDeviceState:
00122 state = (ConnexionDeviceState *) msgarg;
00123 if (state->client == tdxevent.client) {
00124 switch (state->command) {
00125 case kConnexionCmdHandleAxis:
00126 tdxevent.tx += state->axis[0];
00127 tdxevent.ty += -state->axis[2];
00128 tdxevent.tz += -state->axis[1];
00129 tdxevent.rx += state->axis[3];
00130 tdxevent.ry += -state->axis[5];
00131 tdxevent.rz += -state->axis[4];
00132 tdxevent.eventcount++;
00133 break;
00134
00135 case kConnexionCmdHandleButtons:
00136 tdxevent.buttons = state->buttons;
00137 tdxevent.eventcount++;
00138 break;
00139 }
00140 }
00141 break;
00142
00143 default:
00144
00145 break;
00146 }
00147 }
00148
00149 static void tdx_clear() {
00150 memset(&tdxevent, 0, sizeof(tdxevent));
00151 }
00152
00153 static int tdx_enable() {
00154 UInt16 clientID;
00155
00156 if (InstallConnexionHandlers == NULL) {
00157 msgInfo << "No 3DConnexion driver on this system." << sendmsg;
00158 return -1;
00159 }
00160 OSErr result = InstallConnexionHandlers(tdx_msghandler, 0L, 0L);
00161 if (result != noErr) {
00162 msgInfo << "Unable to register with 3DConnexion driver." << sendmsg;
00163 return -1;
00164 }
00165
00166 #if 1
00167
00168 clientID = RegisterConnexionClient(0, executablename,
00169 kConnexionClientModeTakeOver, kConnexionMaskAll);
00170 #else
00171
00172 clientID = RegisterConnexionClient(kConnexionClientWildcard, NULL,
00173 kConnexionClientModeTakeOver, kConnexionMaskAll);
00174 #endif
00175
00176 tdxevent.enabled = 1;
00177 tdxevent.client = clientID;
00178
00179 return 0;
00180 }
00181
00182 static int tdx_detach() {
00183 if (tdxevent.enabled) {
00184 UnregisterConnexionClient(tdxevent.client);
00185 CleanupConnexionHandlers();
00186 }
00187 tdx_clear();
00188 }
00189
00190 int tdx_getstatus(int &tx, int &ty, int &tz, int &rx, int &ry, int &rz, int &buttons) {
00191 int eventcount = tdxevent.eventcount;
00192
00193 tx = tdxevent.tx;
00194 ty = tdxevent.ty;
00195 tz = tdxevent.tz;
00196 rx = tdxevent.rx;
00197 ry = tdxevent.ry;
00198 rz = tdxevent.rz;
00199 buttons = tdxevent.buttons;
00200
00201 tdxevent.tx = 0;
00202 tdxevent.ty = 0;
00203 tdxevent.tz = 0;
00204 tdxevent.rx = 0;
00205 tdxevent.ry = 0;
00206 tdxevent.rz = 0;
00207 tdxevent.eventcount = 0;
00208
00209 return eventcount;
00210 }
00211
00212 #endif
00213
00214
00215
00216
00217 Spaceball::Spaceball(VMDApp *vmdapp)
00218 : UIObject(vmdapp) {
00219
00220 #if defined(VMDTDCONNEXION) && defined(__APPLE__)
00221
00222 tdx_clear();
00223 if (tdx_enable() == 0)
00224 msgInfo << "3DConnexion SpaceNavigator enabled." << sendmsg;
00225 #endif
00226
00227 #if defined(VMDLIBSBALL) && !defined(VMDSPACEWARE)
00228 sball=NULL;
00229 if (getenv("VMDSPACEBALLPORT") != NULL) {
00230 msgInfo << "Opening Spaceball (direct I/O) on port: "
00231 << getenv("VMDSPACEBALLPORT") << sendmsg;
00232 sball = sball_open(getenv("VMDSPACEBALLPORT"));
00233 if (sball == NULL)
00234 msgErr << "Failed to open Spaceball direct I/O serial port, device disabled."
00235 << sendmsg;
00236 }
00237 #endif
00238
00239 buttonDown = 0;
00240
00241 reset();
00242 }
00243
00244
00245
00246 Spaceball::~Spaceball(void) {
00247 #if defined(VMDTDCONNEXION) && defined(__APPLE__)
00248
00249 tdx_detach();
00250 #endif
00251
00252 #if defined(VMDLIBSBALL) && !defined(VMDSPACEWARE)
00253 if (sball != NULL)
00254 sball_close(sball);
00255 #endif
00256 }
00257
00258
00260
00261
00262 void Spaceball::reset(void) {
00263
00264 move_mode(NORMAL);
00265
00266
00267
00268 set_sensitivity(1.0f);
00269
00270
00271 set_null_region(16);
00272
00273
00274 set_max_stride(20);
00275
00276
00277
00278 transInc = 1.0f / 25000.0f;
00279 rotInc = 1.0f / 200.0f;
00280 scaleInc = 1.0f / 25000.0f;
00281 animInc = 1.0f / 75.0f;
00282 }
00283
00284
00285
00286
00287
00288 int Spaceball::act_on_command(int type, Command *cmd) {
00289 return FALSE;
00290 }
00291
00292
00293
00294
00295 int Spaceball::check_event(void) {
00296 int tx, ty, tz, rx, ry, rz, buttons;
00297 int buttonchanged;
00298 int win_event=FALSE;
00299 int direct_event=FALSE;
00300
00301 DisplayDevice::EventCodes keydev=DisplayDevice::WIN_KBD;
00302
00303
00304 rx=ry=rz=tx=ty=tz=buttons=0;
00305
00306 #if defined(VMDTDCONNEXION) && defined(__APPLE__)
00307 if (tdx_getstatus(tx, ty, tz, rx, ry, rz, buttons))
00308 win_event = TRUE;
00309 #else
00310 if (app->display->spaceball(&rx, &ry, &rz, &tx, &ty, &tz, &buttons))
00311 win_event = TRUE;
00312 #endif
00313
00314
00315 #if defined(VMDLIBSBALL)
00316
00317 if (sball != NULL) {
00318 int rx2, ry2, rz2, tx2, ty2, tz2, buttons2;
00319 if (sball_getstatus(sball, &tx2, &ty2, &tz2, &rx2, &ry2, &rz2, &buttons2)) {
00320 direct_event = TRUE;
00321 rx += rx2;
00322 ry += ry2;
00323 rz += rz2;
00324 tx += tx2;
00325 ty += ty2;
00326 tz += tz2;
00327 buttons |= buttons2;
00328 }
00329 }
00330 #endif
00331
00332 if (!win_event && !direct_event)
00333 return FALSE;
00334
00335
00336 buttonchanged = buttons ^ buttonDown;
00337
00338
00339
00340 #if defined(VMDLIBSBALL) && !defined(VMDSPACEWARE)
00341 if (((buttonchanged & SBALL_BUTTON_1) && (buttons & SBALL_BUTTON_1)) ||
00342 ((buttonchanged & SBALL_BUTTON_LEFT) && (buttons & SBALL_BUTTON_LEFT))){
00343 #else
00344
00345 if ((buttonchanged & 2) && (buttons & 2)) {
00346 #endif
00347
00348 app->scene_resetview();
00349 msgInfo << "Spaceball reset view orientation" << sendmsg;
00350 }
00351
00352
00353 #if defined(VMDLIBSBALL) && !defined(VMDSPACEWARE)
00354 if (((buttonchanged & SBALL_BUTTON_2) && (buttons & SBALL_BUTTON_2)) ||
00355 ((buttonchanged & SBALL_BUTTON_RIGHT) && (buttons & SBALL_BUTTON_RIGHT))) {
00356 #else
00357
00358 if ((buttonchanged & 4) && (buttons & 4)) {
00359 #endif
00360
00361 switch (moveMode) {
00362 case NORMAL:
00363 move_mode(MAXAXIS);
00364 msgInfo << "Spaceball set to dominant axis rotation/translation mode" << sendmsg;
00365 break;
00366
00367 case MAXAXIS:
00368 move_mode(SCALING);
00369 msgInfo << "Spaceball set to scaling mode" << sendmsg;
00370 break;
00371
00372 case SCALING:
00373 move_mode(ANIMATE);
00374 msgInfo << "Spaceball set to animate mode" << sendmsg;
00375 break;
00376
00377 case ANIMATE:
00378 move_mode(TRACKER);
00379 msgInfo << "Spaceball set to tracker mode" << sendmsg;
00380 break;
00381
00382 case TRACKER:
00383 move_mode(USER);
00384 msgInfo << "Spaceball set to user mode" << sendmsg;
00385 break;
00386
00387 default:
00388 move_mode(NORMAL);
00389 msgInfo << "Spaceball set to rotation/translation mode" << sendmsg;
00390 break;
00391 }
00392 }
00393
00394
00395 #if defined(VMDLIBSBALL) && !defined(VMDSPACEWARE)
00396 if ((buttonchanged & SBALL_BUTTON_3) && (buttons & SBALL_BUTTON_3)) {
00397 runcommand(new UserKeyEvent(keydev, '3', (int) DisplayDevice::AUX));
00398 }
00399 if ((buttonchanged & SBALL_BUTTON_4) && (buttons & SBALL_BUTTON_4)) {
00400 runcommand(new UserKeyEvent(keydev, '4', (int) DisplayDevice::AUX));
00401 }
00402 if ((buttonchanged & SBALL_BUTTON_5) && (buttons & SBALL_BUTTON_5)) {
00403 runcommand(new UserKeyEvent(keydev, '5', (int) DisplayDevice::AUX));
00404 }
00405 if ((buttonchanged & SBALL_BUTTON_6) && (buttons & SBALL_BUTTON_6)) {
00406 runcommand(new UserKeyEvent(keydev, '6', (int) DisplayDevice::AUX));
00407 }
00408 if ((buttonchanged & SBALL_BUTTON_7) && (buttons & SBALL_BUTTON_7)) {
00409 runcommand(new UserKeyEvent(keydev, '7', (int) DisplayDevice::AUX));
00410 }
00411 if ((buttonchanged & SBALL_BUTTON_8) && (buttons & SBALL_BUTTON_8)) {
00412 runcommand(new UserKeyEvent(keydev, '8', (int) DisplayDevice::AUX));
00413 }
00414
00415 #else
00416 if ((buttonchanged & 8) && (buttons & 8)) {
00417 runcommand(new UserKeyEvent(keydev, '3', (int) DisplayDevice::AUX));
00418 }
00419 if ((buttonchanged & 16) && (buttons & 16)) {
00420 runcommand(new UserKeyEvent(keydev, '4', (int) DisplayDevice::AUX));
00421 }
00422 if ((buttonchanged & 32) && (buttons & 32)) {
00423 runcommand(new UserKeyEvent(keydev, '5', (int) DisplayDevice::AUX));
00424 }
00425 if ((buttonchanged & 64) && (buttons & 64)) {
00426 runcommand(new UserKeyEvent(keydev, '6', (int) DisplayDevice::AUX));
00427 }
00428 if ((buttonchanged & 128) && (buttons & 128)) {
00429 runcommand(new UserKeyEvent(keydev, '7', (int) DisplayDevice::AUX));
00430 }
00431 if ((buttonchanged & 256) && (buttons & 256)) {
00432 runcommand(new UserKeyEvent(keydev, '8', (int) DisplayDevice::AUX));
00433 }
00434 #endif
00435
00436
00437
00438 int atx, aty, atz, arx, ary, arz;
00439 atx = abs(tx);
00440 aty = abs(ty);
00441 atz = abs(tz);
00442 arx = abs(rx);
00443 ary = abs(ry);
00444 arz = abs(rz);
00445
00446
00447
00448 if (atx > null_region) {
00449 tx = ((tx > 0) ? (tx - null_region) : (tx + null_region));
00450 } else {
00451 tx = 0;
00452 }
00453 if (aty > null_region) {
00454 ty = ((ty > 0) ? (ty - null_region) : (ty + null_region));
00455 } else {
00456 ty = 0;
00457 }
00458 if (atz > null_region) {
00459 tz = ((tz > 0) ? (tz - null_region) : (tz + null_region));
00460 } else {
00461 tz = 0;
00462 }
00463 if (arx > null_region) {
00464 rx = ((rx > 0) ? (rx - null_region) : (rx + null_region));
00465 } else {
00466 rx = 0;
00467 }
00468 if (ary > null_region) {
00469 ry = ((ry > 0) ? (ry - null_region) : (ry + null_region));
00470 } else {
00471 ry = 0;
00472 }
00473 if (arz > null_region) {
00474 rz = ((rz > 0) ? (rz - null_region) : (rz + null_region));
00475 } else {
00476 rz = 0;
00477 }
00478
00479
00480
00481
00482
00483
00484 if ((arx+ary+arz+atx+aty+atz) > 0) {
00485 float ftx = tx * sensitivity;
00486 float fty = ty * sensitivity;
00487 float ftz = tz * sensitivity;
00488 float frx = rx * sensitivity;
00489 float fry = ry * sensitivity;
00490 float frz = rz * sensitivity;
00491 char rmaxaxis = 'x';
00492 float rmaxval = 0.0f;
00493 float tmaxval = 0.0f;
00494 float tmaxvec[3] = { 0.0f, 0.0f, 0.0f };
00495 tmaxvec[0] = tmaxvec[1] = tmaxvec[2] = 0.0f;
00496
00497 switch(moveMode) {
00498 case NORMAL:
00499
00500 app->scene_rotate_by(frx * rotInc, 'x');
00501 app->scene_rotate_by(fry * rotInc, 'y');
00502 app->scene_rotate_by(-frz * rotInc, 'z');
00503 if (app->display_projection_is_perspective()) {
00504 app->scene_translate_by(ftx * transInc, fty * transInc, -ftz * transInc);
00505 } else {
00506 app->scene_scale_by((1.0f + scaleInc * -ftz > 0.0f) ?
00507 1.0f + scaleInc * -ftz : 0.0f);
00508 app->scene_translate_by(ftx * transInc, fty * transInc, 0);
00509 }
00510
00511 break;
00512
00513 case MAXAXIS:
00514
00515
00516 if (arx > ary) {
00517 if (arx > arz) {
00518 rmaxaxis = 'x';
00519 rmaxval = frx;
00520 } else {
00521 rmaxaxis = 'z';
00522 rmaxval = -frz;
00523 }
00524 } else {
00525 if (ary > arz) {
00526 rmaxaxis = 'y';
00527 rmaxval = fry;
00528 } else {
00529 rmaxaxis = 'z';
00530 rmaxval = -frz;
00531 }
00532 }
00533
00534
00535 if (atx > aty) {
00536 if (atx > atz) {
00537 tmaxval = ftx;
00538 tmaxvec[0] = ftx;
00539 } else {
00540 tmaxval = ftz;
00541 tmaxvec[2] = ftz;
00542 }
00543 } else {
00544 if (aty > atz) {
00545 tmaxval = fty;
00546 tmaxvec[1] = fty;
00547 } else {
00548 tmaxval = ftz;
00549 tmaxvec[2] = ftz;
00550 }
00551 }
00552
00553
00554 if (fabs(rmaxval) > fabs(tmaxval)) {
00555 app->scene_rotate_by(rmaxval * rotInc, rmaxaxis);
00556 } else {
00557 app->scene_translate_by(tmaxvec[0] * transInc,
00558 tmaxvec[1] * transInc,
00559 -tmaxvec[2] * transInc);
00560 }
00561 break;
00562
00563 case SCALING:
00564 app->scene_scale_by((1.0f + scaleInc * ftz > 0.0f) ?
00565 1.0f + scaleInc * ftz : 0.0f);
00566 break;
00567
00568 case ANIMATE:
00569
00570 if (abs(ry) > 0) {
00571 #if 1
00572
00573 float speed = fabsf(expf(fabsf((fabsf(fry) * animInc) / 1.7f))) - 1.0f;
00574 #else
00575
00576 float speed = fabsf(fry) * animInc;
00577 #endif
00578
00579 if (speed > 0) {
00580 if (speed < 1.0)
00581 app->animation_set_speed(speed);
00582 else
00583 app->animation_set_speed(1.0f);
00584
00585 int stride = 1;
00586 if (fabs(speed - 1.0) > (double) maxstride)
00587 stride = maxstride;
00588 else
00589 stride = 1 + (int) fabs(speed-1.0);
00590 if (stride < 1)
00591 stride = 1;
00592 app->animation_set_stride(stride);
00593
00594
00595 if (fry < 0)
00596 app->animation_set_dir(Animation::ANIM_FORWARD1);
00597 else
00598 app->animation_set_dir(Animation::ANIM_REVERSE1);
00599 } else {
00600 app->animation_set_dir(Animation::ANIM_PAUSE);
00601 app->animation_set_speed(1.0f);
00602 }
00603 } else {
00604 app->animation_set_dir(Animation::ANIM_PAUSE);
00605 app->animation_set_speed(1.0f);
00606 }
00607 break;
00608
00609 case TRACKER:
00610 trtx = ftx;
00611 trty = fty;
00612 trtz = ftz;
00613 trrx = frx;
00614 trry = fry;
00615 trrz = frz;
00616 trbuttons = buttons;
00617 break;
00618
00619 case USER:
00620
00621 app->commandQueue->runcommand(new SpaceballEvent(ftx, fty, ftz,
00622 frx, fry, frz,
00623 buttons));
00624 break;
00625 }
00626 }
00627
00628
00629 buttonDown = buttons;
00630
00631 return TRUE;
00632 }
00633
00634
00636
00637 const char* Spaceball::get_mode_str(MoveMode mm) {
00638 const char* modestr;
00639
00640 switch (mm) {
00641 default:
00642 case NORMAL: modestr = "rotate"; break;
00643 case MAXAXIS: modestr = "maxaxis"; break;
00644 case SCALING: modestr = "scale"; break;
00645 case ANIMATE: modestr = "animate"; break;
00646 case TRACKER: modestr = "tracker"; break;
00647 case USER: modestr = "user"; break;
00648 }
00649
00650 return modestr;
00651 }
00652
00653
00654 void Spaceball::get_tracker_status(float &tx, float &ty, float &tz,
00655 float &rx, float &ry, float &rz,
00656 int &buttons) {
00657 tx = trtx * transInc;
00658 ty = trty * transInc;
00659 tz = -trtz * transInc;
00660 rx = trrx * rotInc;
00661 ry = trry * rotInc;
00662 rz = -trrz * rotInc;
00663 buttons = trbuttons;
00664 }
00665
00666
00667
00668 int Spaceball::move_mode(MoveMode mm) {
00669
00670 moveMode = mm;
00671
00673 if (moveMode != TRACKER) {
00674 trtx=trty=trtz=trrx=trry=trrz=0.0f;
00675 trbuttons=0;
00676 }
00677
00678 return TRUE;
00679 }
00680
00681
00682