diff --git a/openscad.pro b/openscad.pro index 6b32afc..b663a62 100644 --- a/openscad.pro +++ b/openscad.pro @@ -247,6 +247,8 @@ HEADERS += src/typedefs.h \ src/ThrownTogetherRenderer.h \ src/CGAL_OGL_Polyhedron.h \ src/OGL_helper.h \ + src/hidapi.h \ + src/SpaceNav.h \ src/QGLView.h \ src/GLView.h \ src/MainWindow.h \ @@ -404,6 +406,8 @@ SOURCES += src/version_check.cc \ src/OpenCSGWarningDialog.cc \ src/editor.cc \ src/GLView.cc \ + src/hid.c \ + src/SpaceNav.cc \ src/QGLView.cc \ src/AutoUpdater.cc \ \ diff --git a/src/MainWindow.h b/src/MainWindow.h index 5e1e023..75de2ac 100644 --- a/src/MainWindow.h +++ b/src/MainWindow.h @@ -174,6 +174,7 @@ private slots: // Mac OSX FindBuffer support void findBufferChanged(); void updateFindBuffer(QString); + bool event(QEvent* event); protected: virtual bool eventFilter(QObject* obj, QEvent *event); diff --git a/src/QGLView.cc b/src/QGLView.cc index bef5744..785c56b 100644 --- a/src/QGLView.cc +++ b/src/QGLView.cc @@ -225,65 +225,35 @@ void QGLView::mouseMoveEvent(QMouseEvent *event) ) { // Left button rotates in xz, Shift-left rotates in xy // On Mac, Ctrl-Left is handled as right button on other platforms - cam.object_rot.x() += dy; if ((QApplication::keyboardModifiers() & Qt::ShiftModifier) != 0) - cam.object_rot.y() += dx; + rotate( dy, dx, 0.0); else - cam.object_rot.z() += dx; - - normalizeAngle(cam.object_rot.x()); - normalizeAngle(cam.object_rot.y()); - normalizeAngle(cam.object_rot.z()); + rotate( dy, 0.0, dx); } else { // Right button pans in the xz plane // Middle button pans in the xy plane // Shift-right and Shift-middle zooms if ((QApplication::keyboardModifiers() & Qt::ShiftModifier) != 0) { - cam.zoom(-12.0 * dy); + translate( 0.0, -12.0 * dy, 0.0); } else { - - double mx = +(dx) * 3.0 * cam.zoomValue() / QWidget::width(); - double mz = -(dy) * 3.0 * cam.zoomValue() / QWidget::height(); - - double my = 0; + double mx = +(dx) * 3.0 * cam.zoomValue() / QWidget::width(); + double mz = -(dy) * 3.0 * cam.zoomValue() / QWidget::height(); + double my = 0; #if (QT_VERSION < QT_VERSION_CHECK(4, 7, 0)) - if (event->buttons() & Qt::MidButton) { + if (event->buttons() & Qt::MidButton) #else - if (event->buttons() & Qt::MiddleButton) { + if (event->buttons() & Qt::MiddleButton) #endif - my = mz; - mz = 0; - // actually lock the x-position - // (turns out to be easier to use than xy panning) - mx = 0; - } - - Matrix3d aax, aay, aaz, tm3; - aax = Eigen::AngleAxisd(-(cam.object_rot.x()/180) * M_PI, Vector3d::UnitX()); - aay = Eigen::AngleAxisd(-(cam.object_rot.y()/180) * M_PI, Vector3d::UnitY()); - aaz = Eigen::AngleAxisd(-(cam.object_rot.z()/180) * M_PI, Vector3d::UnitZ()); - tm3 = Matrix3d::Identity(); - tm3 = aaz * (aay * (aax * tm3)); - - Matrix4d tm; - tm = Matrix4d::Identity(); - for (int i=0;i<3;i++) for (int j=0;j<3;j++) tm(j,i)=tm3(j,i); - - Matrix4d vec; - vec << - 0, 0, 0, mx, - 0, 0, 0, my, - 0, 0, 0, mz, - 0, 0, 0, 1 - ; - tm = tm * vec; - cam.object_trans.x() += tm(0,3); - cam.object_trans.y() += tm(1,3); - cam.object_trans.z() += tm(2,3); + { + my = mz; + mz = 0; + // actually lock the x-position + // (turns out to be easier to use than xy panning) + mx = 0; + } + translate( mx, my, mz); } } - updateGL(); - emit doAnimateUpdate(); } last_mouse = this_mouse; } @@ -333,3 +303,82 @@ void QGLView::setOrthoMode(bool enabled) { if (enabled) this->cam.setProjection(Camera::ORTHOGONAL); else this->cam.setProjection(Camera::PERSPECTIVE); } + + +void +QGLView::SpaceNav_translate( SpaceNavEventTranslate* event) { + if (event->x == 0 && event->y == 0 && event->z == 0) { + return; + } + translate( event->x * 0.0001 * cam.zoomValue(), event->y * 0.1, -event->z * 0.0001 * cam.zoomValue()); +} + + +void +QGLView::SpaceNav_rotate( SpaceNavEventRotate* event) { + if (event->x == 0 && event->y == 0 && event->z == 0) { + return; + } + rotate( event->x * 0.01, event->y * -0.01, event->z * -0.01); +} + + +void +QGLView::SpaceNav_button( SpaceNavEventButton* event) { + std::cout << "QGLView::SpaceNav_button: down=" << event->down << " up=" << event->up << std::endl; + if ((event->down & 1) != 0) { + cam.object_trans << 0,0,0; + updateGL(); + } + if ((event->down & 2) != 0) { + resetView(); + updateGL(); + } +} + + +void +QGLView::translate( double x, double y, double z) { + cam.zoom( y); + y = 0; + Matrix3d aax, aay, aaz, tm3; + aax = Eigen::AngleAxisd( -(cam.object_rot.x() / 180) * M_PI, Vector3d::UnitX()); + aay = Eigen::AngleAxisd( -(cam.object_rot.y() / 180) * M_PI, Vector3d::UnitY()); + aaz = Eigen::AngleAxisd( -(cam.object_rot.z() / 180) * M_PI, Vector3d::UnitZ()); + tm3 = Matrix3d::Identity(); + tm3 = aaz * (aay * (aax * tm3)); + Matrix4d tm; + tm = Matrix4d::Identity(); + for (int i = 0; i < 3; ++i) { + for (int j = 0; j < 3; ++j) { + tm( j, i) = tm3( j, i); + } + } + Matrix4d vec; + vec << + 0, 0, 0, x, + 0, 0, 0, y, + 0, 0, 0, z, + 0, 0, 0, 1 + ; + tm = tm * vec; + cam.object_trans.x() += tm( 0, 3); + cam.object_trans.y() += tm( 1, 3); + cam.object_trans.z() += tm( 2, 3); + updateGL(); + emit doAnimateUpdate(); +} + + +void +QGLView::rotate( double x, double y, double z) { + cam.object_rot.x() += x; + cam.object_rot.y() += y; + cam.object_rot.z() += z; + normalizeAngle( cam.object_rot.x()); + normalizeAngle( cam.object_rot.y()); + normalizeAngle( cam.object_rot.z()); + updateGL(); + emit doAnimateUpdate(); +} + diff --git a/src/QGLView.h b/src/QGLView.h index 697d3b5..767f7f9 100644 --- a/src/QGLView.h +++ b/src/QGLView.h @@ -8,8 +8,9 @@ #include #include "GLView.h" #include "renderer.h" +#include "SpaceNav.h" -class QGLView : public QGLWidget, public GLView +class QGLView : public QGLWidget, public GLView, public SpaceNavEventHandler { Q_OBJECT Q_PROPERTY(bool showFaces READ showFaces WRITE setShowFaces); @@ -52,6 +53,10 @@ public slots: void ZoomIn(void); void ZoomOut(void); + void SpaceNav_translate( SpaceNavEventTranslate* event); + void SpaceNav_rotate( SpaceNavEventRotate* event); + void SpaceNav_button( SpaceNavEventButton* event); + public: QLabel *statusLabel; @@ -67,6 +72,8 @@ private: void mouseMoveEvent(QMouseEvent *event); void mouseReleaseEvent(QMouseEvent *event); void mouseDoubleClickEvent(QMouseEvent *event); + void translate( double x, double y, double z); + void rotate( double x, double y, double z); void initializeGL(); void resizeGL(int w, int h); diff --git a/src/mainwin.cc b/src/mainwin.cc index 5735622..26e20da 100644 --- a/src/mainwin.cc +++ b/src/mainwin.cc @@ -59,6 +59,7 @@ #include "ThrownTogetherRenderer.h" #include "csgtermnormalizer.h" #include "QGLView.h" +#include "SpaceNav.h" #ifdef Q_OS_MAC #include "CocoaUtils.h" #endif @@ -1550,6 +1551,17 @@ void MainWindow::findBufferChanged() { } +bool +MainWindow::event(QEvent* event) { + if (event->type() == SpaceNavEvent::my_type) { + static_cast< SpaceNavEvent*>( event)->deliver( qglview); + event->accept(); + return true; + } + return QMainWindow::event( event); +} + + bool MainWindow::eventFilter(QObject* obj, QEvent *event) { if (obj == find_panel) diff --git a/src/openscad.cc b/src/openscad.cc index 80c5b9e..d589ded 100644 --- a/src/openscad.cc +++ b/src/openscad.cc @@ -42,6 +42,7 @@ #include "stackcheck.h" #include "CocoaUtils.h" #include "FontCache.h" +#include "SpaceNav.h" #include #include @@ -743,6 +744,7 @@ int gui(vector &inputFiles, const fs::path &original_path, int argc, cha } app.connect(&app, SIGNAL(lastWindowClosed()), &app, SLOT(quit())); + spacenav(); int rc = app.exec(); QSet *windows = MainWindow::getWindows(); foreach (MainWindow *mainw, *windows) {