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