From 0c7545066e9b808c3818138eee4cd84299854985 Mon Sep 17 00:00:00 2001 From: Aron Helser Date: Mon, 16 May 2022 21:31:26 -0400 Subject: [PATCH] Add SpaceMouseInteractor plugin, controlling the camera with a SpaceMouse Using the 3DxWareSDK provided by 3Dconnexion, connect to a SpaceMouse if it is available, and use it to manipulate the camera in the active renderview. The 3Dconnexion Settings app provided with the driver can be used to change the style of interaction from object-centered to camera-centered (flying). Only works on Windows currently and provides an empty placeholder for linux/mac. A Mac implementation is planned as a follow-up. 3Dconnexion does not provide an equivalent SDK for linux. --- .../release/dev/spacemouse-plugin.md | 10 + Plugins/SpaceMouseInteractor/CMakeLists.txt | 52 ++ .../cmake/Find3DxWareSDK.cmake | 87 ++++ Plugins/SpaceMouseInteractor/paraview.plugin | 18 + .../pqSpaceMouseAutoStart.cxx | 85 ++++ .../pqSpaceMouseAutoStart.h | 61 +++ .../pqSpaceMouseImplLinux.cxx | 83 +++ .../pqSpaceMouseImplLinux.h | 62 +++ .../pqSpaceMouseImplWin.cxx | 480 ++++++++++++++++++ .../pqSpaceMouseImplWin.h | 115 +++++ 10 files changed, 1053 insertions(+) create mode 100644 Documentation/release/dev/spacemouse-plugin.md create mode 100644 Plugins/SpaceMouseInteractor/CMakeLists.txt create mode 100644 Plugins/SpaceMouseInteractor/cmake/Find3DxWareSDK.cmake create mode 100644 Plugins/SpaceMouseInteractor/paraview.plugin create mode 100644 Plugins/SpaceMouseInteractor/pqSpaceMouseAutoStart.cxx create mode 100644 Plugins/SpaceMouseInteractor/pqSpaceMouseAutoStart.h create mode 100644 Plugins/SpaceMouseInteractor/pqSpaceMouseImplLinux.cxx create mode 100644 Plugins/SpaceMouseInteractor/pqSpaceMouseImplLinux.h create mode 100644 Plugins/SpaceMouseInteractor/pqSpaceMouseImplWin.cxx create mode 100644 Plugins/SpaceMouseInteractor/pqSpaceMouseImplWin.h diff --git a/Documentation/release/dev/spacemouse-plugin.md b/Documentation/release/dev/spacemouse-plugin.md new file mode 100644 index 0000000000..3c6050c0c9 --- /dev/null +++ b/Documentation/release/dev/spacemouse-plugin.md @@ -0,0 +1,10 @@ +## Add SpaceMouseInteractor plugin, controlling the camera with a SpaceMouse + +Using the 3DxWareSDK provided by 3Dconnexion, connect to a SpaceMouse +if it is available, and use it to manipulate the camera in the active +renderview. The 3Dconnexion Settings app provided with the driver +can be used to change the style of interaction from object-centered +to camera-centered (flying). + +Only works on Windows currently. A linux SDK is not available, but +an equivalent Mac implementation is planned. diff --git a/Plugins/SpaceMouseInteractor/CMakeLists.txt b/Plugins/SpaceMouseInteractor/CMakeLists.txt new file mode 100644 index 0000000000..8e12ddc8a3 --- /dev/null +++ b/Plugins/SpaceMouseInteractor/CMakeLists.txt @@ -0,0 +1,52 @@ +# so we can use our local Find3DxWareSDK.cmake +list(INSERT CMAKE_MODULE_PATH 0 + "${CMAKE_CURRENT_SOURCE_DIR}/cmake") +set(interfaces) +set(sources) +if (PARAVIEW_USE_QT) + list(APPEND sources + pqSpaceMouseAutoStart.cxx + pqSpaceMouseAutoStart.h) + paraview_plugin_add_auto_start( + CLASS_NAME pqSpaceMouseAutoStart + INTERFACES autostart_interface + SOURCES autostart_sources) + list(APPEND interfaces + ${autostart_interface}) + list(APPEND sources + ${autostart_sources}) + if (WIN32) + list(APPEND sources + pqSpaceMouseImplWin.cxx + pqSpaceMouseImplWin.h) + find_package(3DxWareSDK) + else() + # this is a do-nothing implementation for now + list(APPEND sources + pqSpaceMouseImplLinux.cxx + pqSpaceMouseImplLinux.h) + endif() +endif () + + +set(CMAKE_CXX_STANDARD 11) +paraview_add_plugin(SpaceMouseInteractor + VERSION "1.0" + UI_INTERFACES ${interfaces} + SOURCES ${sources}) + +if (PARAVIEW_USE_QT) + target_link_libraries(SpaceMouseInteractor + PRIVATE + ParaView::RemotingApplication + ParaView::RemotingCore + ParaView::RemotingServerManager + ParaView::RemotingViews + ParaView::pqApplicationComponents) + if (WIN32) + target_link_libraries(SpaceMouseInteractor + PRIVATE + 3Dconnexion::3DxWareSDK) + endif() + target_compile_definitions(SpaceMouseInteractor PRIVATE QT_NO_KEYWORDS) +endif () diff --git a/Plugins/SpaceMouseInteractor/cmake/Find3DxWareSDK.cmake b/Plugins/SpaceMouseInteractor/cmake/Find3DxWareSDK.cmake new file mode 100644 index 0000000000..bfc387c120 --- /dev/null +++ b/Plugins/SpaceMouseInteractor/cmake/Find3DxWareSDK.cmake @@ -0,0 +1,87 @@ +#[=======================================================================[ +Find3DxWareSDK +-------- + +Find 3DxWareSDK. + +IMPORTED Targets +^^^^^^^^^^^^^^^^ + +This module defines :prop_tgt:`IMPORTED` target ``3Dconnexion::3DxWareSDK`` +if 3DxWareSDK has been found. + +Result Variables +^^^^^^^^^^^^^^^^ + +This module will set the following variables in your project: + +``3DxWareSDK_FOUND`` + True if 3DxWareSDK is found. +``3DxWareSDK_INCLUDE_DIRS`` + Include directories for 3DxWareSDK headers. +``3DxWareSDK_LIBRARIES`` + Libraries to link to 3DxWareSDK. + +Cache variables +^^^^^^^^^^^^^^^ + +The following cache variables may also be set: + +``3DxWareSDK_LIBRARY`` + The lib3DxWareSDK library file. +``3DxWareSDK_INCLUDE_DIR`` + The directory containing ``3DxWareSDK.h``. + +Hints +^^^^^ + +Set ``3DxWareSDK_DIR`` or ``3DxWareSDK_ROOT`` in the environment to specify the +3DxWareSDK installation prefix. +example : 3DxWareSDK_DIR = C:/projects/3DxWare_SDK_v4-0-2_r17624 +#]=======================================================================] +# +# This makes the presumption that you include navlib.h like +# +#include "navlib/navlib.h" + +find_path(3DxWareSDK_INCLUDE_DIR navlib/navlib.h + HINTS + ${3DxWareSDK_ROOT} + ENV 3DxWareSDK_DIR + ENV 3DxWareSDK_ROOT + PATH_SUFFIXES + inc + include + DOC "Path to the 3DxWareSDK include directory" +) +mark_as_advanced(3DxWareSDK_INCLUDE_DIR) + +find_library(3DxWareSDK_LIBRARY + NAMES TDxNavLib + HINTS + ${3DxWareSDK_ROOT} + ENV 3DxWareSDK_DIR + ENV 3DxWareSDK_ROOT + PATH_SUFFIXES + lib/x64 + lib/x86 + lib + DOC "Path to the 3DxWareSDK library" +) +mark_as_advanced(3DxWareSDK_LIBRARY) + +include(FindPackageHandleStandardArgs) +find_package_handle_standard_args(3DxWareSDK + REQUIRED_VARS 3DxWareSDK_LIBRARY 3DxWareSDK_INCLUDE_DIR) + +if (3DxWareSDK_FOUND) + set(3DxWareSDK_LIBRARIES ${3DxWareSDK_LIBRARY}) + set(3DxWareSDK_INCLUDE_DIRS ${3DxWareSDK_INCLUDE_DIR}) + + if (NOT TARGET 3Dconnexion::3DxWareSDK) + add_library(3Dconnexion::3DxWareSDK UNKNOWN IMPORTED) + set_target_properties(3Dconnexion::3DxWareSDK PROPERTIES + IMPORTED_LOCATION "${3DxWareSDK_LIBRARY}" + INTERFACE_INCLUDE_DIRECTORIES "${3DxWareSDK_INCLUDE_DIR}") + endif () +endif () diff --git a/Plugins/SpaceMouseInteractor/paraview.plugin b/Plugins/SpaceMouseInteractor/paraview.plugin new file mode 100644 index 0000000000..84ee479752 --- /dev/null +++ b/Plugins/SpaceMouseInteractor/paraview.plugin @@ -0,0 +1,18 @@ +NAME + SpaceMouseInteractor +DESCRIPTION + SpaceMouse from 3Dconnexion +REQUIRES_MODULES + ParaView::RemotingApplication + ParaView::RemotingCore + ParaView::RemotingServerManager + ParaView::RemotingViews + ParaView::pqApplicationComponents + ParaView::VTKExtensionsMisc + VTK::CommonCore + VTK::CommonDataModel + VTK::CommonExecutionModel + VTK::CommonMath + VTK::CommonTransforms + VTK::FiltersGeneral + VTK::ImagingCore diff --git a/Plugins/SpaceMouseInteractor/pqSpaceMouseAutoStart.cxx b/Plugins/SpaceMouseInteractor/pqSpaceMouseAutoStart.cxx new file mode 100644 index 0000000000..452a3ce89e --- /dev/null +++ b/Plugins/SpaceMouseInteractor/pqSpaceMouseAutoStart.cxx @@ -0,0 +1,85 @@ +/*========================================================================= + + Program: ParaView + Module: pqSpaceMouseAutoStart.cxx + + Copyright (c) 2005,2006 Sandia Corporation, Kitware Inc. + All rights reserved. + + ParaView is a free software; you can redistribute it and/or modify it + under the terms of the ParaView license version 1.2. + + See License_v1.2.txt for the full ParaView license. + A copy of this license can be obtained by contacting + Kitware Inc. + 28 Corporate Drive + Clifton Park, NY 12065 + USA + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR +CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +========================================================================*/ +#ifdef _MSC_VER +#pragma warning(push) +#pragma warning(disable : 4201) // nonstandard extension, nameless union +#endif + +#include "pqSpaceMouseAutoStart.h" +#ifdef _MSC_VER +#include "pqSpaceMouseImplWin.h" +#else +#include "pqSpaceMouseImplLinux.h" +#endif + +#ifdef _MSC_VER +#pragma warning(pop) +#endif + +#include "pqActiveObjects.h" + +#include "vtkLogger.h" +#include "vtkObject.h" + +#include + +//----------------------------------------------------------------------------- +pqSpaceMouseAutoStart::pqSpaceMouseAutoStart(QObject* parentObject) + : Superclass(parentObject) + , m_p(new pqSpaceMouseImpl()) +{ +} + +//----------------------------------------------------------------------------- +pqSpaceMouseAutoStart::~pqSpaceMouseAutoStart() +{ + delete m_p; +} + +//----------------------------------------------------------------------------- +void pqSpaceMouseAutoStart::startup() +{ + connect(&pqActiveObjects::instance(), &pqActiveObjects::viewChanged, m_p, + &pqSpaceMouseImpl::setActiveView); + m_p->setActiveView(pqActiveObjects::instance().activeView()); +} + +//----------------------------------------------------------------------------- +void pqSpaceMouseAutoStart::shutdown() +{ + m_p->setActiveView(nullptr); +} + +// void pqSpaceMouseAutoStart::setActiveView(pqView* view) +// { +// m_p->setActiveView(view); +// } diff --git a/Plugins/SpaceMouseInteractor/pqSpaceMouseAutoStart.h b/Plugins/SpaceMouseInteractor/pqSpaceMouseAutoStart.h new file mode 100644 index 0000000000..7188761120 --- /dev/null +++ b/Plugins/SpaceMouseInteractor/pqSpaceMouseAutoStart.h @@ -0,0 +1,61 @@ +/*========================================================================= + + Program: ParaView + Module: pqSpaceMouseAutoStart.h + + Copyright (c) 2005,2006 Sandia Corporation, Kitware Inc. + All rights reserved. + + ParaView is a free software; you can redistribute it and/or modify it + under the terms of the ParaView license version 1.2. + + See License_v1.2.txt for the full ParaView license. + A copy of this license can be obtained by contacting + Kitware Inc. + 28 Corporate Drive + Clifton Park, NY 12065 + USA + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR +CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +========================================================================*/ +#ifndef pqSpaceMouseAutoStart_h +#define pqSpaceMouseAutoStart_h + +#include + +class pqSpaceMouseImpl; +class pqView; + +class pqSpaceMouseAutoStart : public QObject +{ + Q_OBJECT + typedef QObject Superclass; + +public: + pqSpaceMouseAutoStart(QObject* parent = nullptr); + ~pqSpaceMouseAutoStart() override; + + void startup(); + void shutdown(); + + // public Q_SLOTS: + // void setActiveView(pqView* view); + +private: + Q_DISABLE_COPY(pqSpaceMouseAutoStart) + + pqSpaceMouseImpl* m_p; +}; + +#endif diff --git a/Plugins/SpaceMouseInteractor/pqSpaceMouseImplLinux.cxx b/Plugins/SpaceMouseInteractor/pqSpaceMouseImplLinux.cxx new file mode 100644 index 0000000000..69a7e2cb68 --- /dev/null +++ b/Plugins/SpaceMouseInteractor/pqSpaceMouseImplLinux.cxx @@ -0,0 +1,83 @@ +/*========================================================================= + + Program: ParaView + Module: pqSpaceMouseImpl.cxx + + Copyright (c) 2005,2006 Sandia Corporation, Kitware Inc. + All rights reserved. + + ParaView is a free software; you can redistribute it and/or modify it + under the terms of the ParaView license version 1.2. + + See License_v1.2.txt for the full ParaView license. + A copy of this license can be obtained by contacting + Kitware Inc. + 28 Corporate Drive + Clifton Park, NY 12065 + USA + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR +CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +========================================================================*/ +#include "pqSpaceMouseImplLinux.h" + +#include "pqActiveObjects.h" +#include "pqCoreUtilities.h" +#include "pqRenderView.h" +#include "vtkSMPropertyHelper.h" +#include "vtkSMRenderViewProxy.h" + +#include "vtkLogger.h" +#include "vtkMatrix4x4.h" +#include "vtkObject.h" +#include "vtkTransform.h" + +#include + +pqSpaceMouseImpl::pqSpaceMouseImpl() {} + +pqSpaceMouseImpl::~pqSpaceMouseImpl() = default; + +void pqSpaceMouseImpl::setActiveView(pqView* view) +{ + pqRenderView* rview = qobject_cast(view); + vtkSMRenderViewProxy* renPxy = rview ? rview->getRenderViewProxy() : nullptr; + + this->Camera = nullptr; + if (renPxy) + { + // this->Enable3DNavigation(); + this->Camera = renPxy->GetActiveCamera(); + // if (this->Camera) + // { + // pqCoreUtilities::connect( + // this->Camera, vtkCommand::ModifiedEvent, this, SLOT(cameraChanged())); + // } + // this->cameraChanged(); + } + else + { + // this->Disable3DNavigation(); + } +} + +void pqSpaceMouseImpl::cameraChanged() {} + +void pqSpaceMouseImpl::render() +{ + pqRenderView* view = qobject_cast(pqActiveObjects::instance().activeView()); + if (view) + { + view->render(); + } +} diff --git a/Plugins/SpaceMouseInteractor/pqSpaceMouseImplLinux.h b/Plugins/SpaceMouseInteractor/pqSpaceMouseImplLinux.h new file mode 100644 index 0000000000..e75ab037a0 --- /dev/null +++ b/Plugins/SpaceMouseInteractor/pqSpaceMouseImplLinux.h @@ -0,0 +1,62 @@ +/*========================================================================= + + Program: ParaView + Module: pqSpaceMouseImplLinux.h + + Copyright (c) 2005,2006 Sandia Corporation, Kitware Inc. + All rights reserved. + + ParaView is a free software; you can redistribute it and/or modify it + under the terms of the ParaView license version 1.2. + + See License_v1.2.txt for the full ParaView license. + A copy of this license can be obtained by contacting + Kitware Inc. + 28 Corporate Drive + Clifton Park, NY 12065 + USA + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR +CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +========================================================================*/ +#ifndef pqSpaceMouseImplLinux_h +#define pqSpaceMouseImplLinux_h +#include "vtkCamera.h" +#include "vtkWeakPointer.h" + +#include +class pqView; + +/// Placeholder for non-windows platforms +class pqSpaceMouseImpl : public QObject +{ + Q_OBJECT + +public: + pqSpaceMouseImpl(); + ~pqSpaceMouseImpl() override; + +public Q_SLOTS: + /// which view are we controlling? The active one. + void setActiveView(pqView* view); + /// the active camera changed. + void cameraChanged(); + +public: + void render(); + +protected: + vtkWeakPointer Camera; +}; + +#endif diff --git a/Plugins/SpaceMouseInteractor/pqSpaceMouseImplWin.cxx b/Plugins/SpaceMouseInteractor/pqSpaceMouseImplWin.cxx new file mode 100644 index 0000000000..a23d9a9533 --- /dev/null +++ b/Plugins/SpaceMouseInteractor/pqSpaceMouseImplWin.cxx @@ -0,0 +1,480 @@ +/*========================================================================= + + Program: ParaView + Module: pqSpaceMouseImpl.cxx + + Copyright (c) 2005,2006 Sandia Corporation, Kitware Inc. + All rights reserved. + + ParaView is a free software; you can redistribute it and/or modify it + under the terms of the ParaView license version 1.2. + + See License_v1.2.txt for the full ParaView license. + A copy of this license can be obtained by contacting + Kitware Inc. + 28 Corporate Drive + Clifton Park, NY 12065 + USA + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR +CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +========================================================================*/ +#ifdef _MSC_VER +#pragma warning(push) +#pragma warning(disable : 4201) // nonstandard extension, nameless union +// #pragma warning(disable: 4100) // unused params +#endif + +#include "pqSpaceMouseImplWin.h" + +#include "pqActiveObjects.h" +#include "pqCoreUtilities.h" +#include "pqRenderView.h" +#include "vtkInitializationHelper.h" +#include "vtkSMPropertyHelper.h" +#include "vtkSMRenderViewProxy.h" + +#include "vtkLogger.h" +#include "vtkMatrix4x4.h" +#include "vtkObject.h" +#include "vtkTransform.h" + +#include + +#define _USE_MATH_DEFINES +#include +#ifndef M_PI +#define M_PI 3.14159265358979323846264338327950288 +#endif + +#define APPLICATION_HAS_ANIMATION_LOOP 0 + +pqSpaceMouseImpl::pqSpaceMouseImpl() + : CNavigation3D(false, true) +{ +} + +pqSpaceMouseImpl::~pqSpaceMouseImpl() = default; + +void pqSpaceMouseImpl::setActiveView(pqView* view) +{ + pqRenderView* rview = qobject_cast(view); + vtkSMRenderViewProxy* renPxy = rview ? rview->getRenderViewProxy() : nullptr; + + this->Camera = nullptr; + if (renPxy) + { + this->Enable3DNavigation(); + this->Camera = renPxy->GetActiveCamera(); + // if (this->Camera) + // { + // pqCoreUtilities::connect( + // this->Camera, vtkCommand::ModifiedEvent, this, SLOT(cameraChanged())); + // } + // this->cameraChanged(); + } + else + { + this->Disable3DNavigation(); + } +} + +void pqSpaceMouseImpl::cameraChanged() +{ + // vtkWarningWithObjectMacro(nullptr, "CameraChanged"); + if (this->Camera) + { + double pos[3]; + this->Camera->GetPosition(pos); + double dp[3]; + this->Camera->GetDirectionOfProjection(dp); + double vu[3]; + this->Camera->GetViewUp(vu); + // auto* fp = this->Camera->GetFocalPoint(); + // vtkWarningWithObjectMacro(nullptr, << "ps " << pos[0] << " " << pos[1] << " " << pos[2] ); + // vtkWarningWithObjectMacro(nullptr, << "dp " << dp[0] << " " << dp[1] << " " << dp[2] ); + // vtkWarningWithObjectMacro(nullptr, << "vu " << vu[0] << " " << vu[1] << " " << vu[2] ); + // double m[16], n[16]; + // vtkMatrix4x4::DeepCopy(m, this->Camera->GetModelViewTransformMatrix()); + // vtkWarningWithObjectMacro(nullptr, << "vtkCM [" << m[0] << ", " << m[1] << ", " << m[2] << ", + // " << m[3] << "] [" << m[4] << ", " << m[5] << ", " << m[6] << ", " << m[7] << "] [" << m[8] + // << ", " << m[9] << ", " << m[10] << ", " << m[11] << "] [" << m[12] << ", " << m[13] << ", " + // << m[14] << ", " << m[15] << "] " ); vtkMatrix4x4::Invert(m, n); + // vtkWarningWithObjectMacro(nullptr, << "invCM [" << n[0] << ", " << n[1] << ", " << n[2] << ", + // " << n[3] << "] [" << n[4] << ", " << n[5] << ", " << n[6] << ", " << n[7] << "] [" << n[8] + // << ", " << n[9] << ", " << n[10] << ", " << n[11] << "] [" << n[12] << ", " << n[13] << ", " + // << n[14] << ", " << n[15] << "] " ); + } +} + +void pqSpaceMouseImpl::render() +{ + pqRenderView* view = qobject_cast(pqActiveObjects::instance().activeView()); + if (view) + { + view->render(); + } +} + +// Following methods were copied from +// 3DxWare_SDK_v4-0-2_r17624/samples/navlib_viewer/src/mainfrm.cpp and follow the recommendations of +// 3DxWare_SDK_v4-0-2_r17624/doc/quick_guide.pdf + +///////////////////////////////////////////////////////////////////////////// +// navlib + +/// Shutdown the connection to the navlib +void pqSpaceMouseImpl::Disable3DNavigation() +{ + nav3d::Enable = false; +} + +/// Open the connection to the navlib and expose the property interface +/// functions +bool pqSpaceMouseImpl::Enable3DNavigation() +{ + try + { + // Set the hint/title for the '3Dconnexion Properties' Utility. + std::string title = vtkInitializationHelper::GetApplicationName(); + nav3d::Profile = title.empty() ? "ParaView" : title; + + // Enable input from / output to the Navigation3D controller. + nav3d::Enable = true; + +#if APPLICATION_HAS_ANIMATION_LOOP + // Use the application render loop as the timing source for the frames + nav3d::FrameTiming = TimingSource::Application; +#else + // Use the SpaceMouse as the timing source for the frames. + nav3d::FrameTiming = TimingSource::SpaceMouse; +#endif + } + catch (const std::exception&) + { + return false; + } + + return true; +} + +////////////////////////////////////////////////////////////////////////////// +// The get property assessors +long pqSpaceMouseImpl::GetModelExtents(navlib::box_t& bbox) const +{ + pqRenderView* view = qobject_cast(pqActiveObjects::instance().activeView()); + if (view) + { + // by moving some default bounds to the center-of-rotation, navlib uses our CoR. + std::vector cor = + vtkSMPropertyHelper(view->getProxy(), "CenterOfRotation").GetDoubleArray(); + bbox.min = { { cor[0] - 1., cor[1] - 1., cor[2] - 1. } }; + bbox.max = { { cor[0] + 1., cor[1] + 1., cor[2] + 1. } }; + return 0; + } + return navlib::make_result_code(navlib::navlib_errc::invalid_operation); +} + +long pqSpaceMouseImpl::GetIsSelectionEmpty(navlib::bool_t& /*empty*/) const +{ + return navlib::make_result_code(navlib::navlib_errc::invalid_operation); +} + +long pqSpaceMouseImpl::GetSelectionExtents(navlib::box_t& /*bbox*/) const +{ + return navlib::make_result_code(navlib::navlib_errc::invalid_operation); +} + +long pqSpaceMouseImpl::GetViewConstructionPlane(navlib::plane_t& /*plane*/) const +{ + return navlib::make_result_code(navlib::navlib_errc::invalid_operation); +} + +long pqSpaceMouseImpl::GetViewExtents(navlib::box_t& /*extents*/) const +{ + return navlib::make_result_code(navlib::navlib_errc::invalid_operation); +} + +long pqSpaceMouseImpl::GetViewFOV(double& fov) const +{ + if (this->Camera) + { + fov = this->Camera->GetViewAngle() * M_PI / 180.0; + return 0; + } + return navlib::make_result_code(navlib::navlib_errc::invalid_operation); +} + +long pqSpaceMouseImpl::GetViewFrustum(navlib::frustum_t& /*frustum*/) const +{ + return navlib::make_result_code(navlib::navlib_errc::invalid_operation); +} + +/// Get whether the view can be rotated +/// true if the view can be rotated +/// 0 on success otherwise an error +long pqSpaceMouseImpl::GetIsViewRotatable(navlib::bool_t& rotatable) const +{ + if (this->Camera) + { + rotatable = true; + return 0; + } + + return navlib::make_result_code(navlib::navlib_errc::invalid_operation); +} + +long pqSpaceMouseImpl::IsUserPivot(navlib::bool_t& userPivot) const +{ + // pivot is always the center-of-rotation supplied by PV + userPivot = true; + return 0; +} + +/// Get the affine of the coordinate system +/// the world to navlib transformation +/// 0 on success otherwise an error +long pqSpaceMouseImpl::GetCoordinateSystem(navlib::matrix_t& affine) const +{ + // Y-Up rhs + navlib::matrix_t cs = { 1., 0., 0., 0., 0., 1., 0., 0., 0., 0., 1., 0., 0., 0., 0., 1. }; + + affine = cs; + + return 0; +} + +/// Get the affine of the view +/// the camera to world transformation +/// 0 on success, otherwise an error. +long pqSpaceMouseImpl::GetCameraMatrix(navlib::matrix_t& affine) const +{ + if (this->Camera) + { + double* m = this->Camera->GetModelViewTransformMatrix()->GetData(); + // vtkWarningWithObjectMacro(nullptr, << "vtkCM [" << m[0] << ", " << m[1] << ", " << m[2] << ", + // " << m[3] << "] [" << m[4] << ", " << m[5] << ", " << m[6] << ", " << m[7] << "] [" << m[8] + // << ", " << m[9] << ", " << m[10] << ", " << m[11] << "] [" << m[12] << ", " << m[13] << ", " + // << m[14] << ", " << m[15] << "] " ); VTK supplies the world-to-camera tranform, so we must + // invert. + vtkMatrix4x4::Invert(m, affine.m); + return 0; + } + return navlib::make_result_code(navlib::navlib_errc::invalid_operation); +} + +/////////////////////////////////////////////////////////////////////////// +// Handle navlib hit testing requests + +/// Get the position of the point hit +/// the hit point +/// 0 when something is hit, otherwise navlib::navlib_errc::no_data_available +long pqSpaceMouseImpl::GetHitLookAt(navlib::point_t& /*position*/) const +{ + return navlib::make_result_code(navlib::navlib_errc::invalid_operation); +} + +/// Get the position of the rotation pivot in world coordinates +/// the position of the pivot +/// 0 on success, otherwise an error. +long pqSpaceMouseImpl::GetPivotPosition(navlib::point_t& position) const +{ + pqRenderView* view = qobject_cast(pqActiveObjects::instance().activeView()); + if (view) + { + std::vector cor = + vtkSMPropertyHelper(view->getProxy(), "CenterOfRotation").GetDoubleArray(); + position.x = cor[0]; + position.y = cor[1]; + position.z = cor[2]; + return 0; + } + return navlib::make_result_code(navlib::navlib_errc::invalid_operation); +} + +long pqSpaceMouseImpl::GetPivotVisible(navlib::bool_t& /*visible*/) const +{ + return navlib::make_result_code(navlib::navlib_errc::invalid_operation); +} + +/// Get the position of the mouse cursor on the projection plane in world +/// coordinates +/// the position of the mouse cursor +/// 0 on success, otherwise an error. +long pqSpaceMouseImpl::GetPointerPosition(navlib::point_t& /*position*/) const +{ + return navlib::make_result_code(navlib::navlib_errc::invalid_operation); +} + +/// Get the whether the view is a perspective projection +/// true when the projection is perspective +/// 0 on success, otherwise an error. +long pqSpaceMouseImpl::GetIsViewPerspective(navlib::bool_t& persp) const +{ + if (this->Camera) + { + persp = !this->Camera->GetParallelProjection(); + return 0; + } + return navlib::make_result_code(navlib::navlib_errc::invalid_operation); +} + +/////////////////////////////////////////////////////////////////////////////////////////////////// +// set property handlers (mutators) +// + +/// Sets the moving property value. +/// true when moving. +/// 0 on success, otherwise an error. +/// The navlib sets this to true at the beginning of navigation. +long pqSpaceMouseImpl::SetMotionFlag(bool /*value*/) +{ + return 0; +} + +/// Sets the transaction property value +/// !0 at the beginning of a frame;0 at the end of a +/// frame 0 on success, otherwise an error. +long pqSpaceMouseImpl::SetTransaction(long /*value*/) +{ + return 0; +} + +/// Sets the affine of the view +/// The camera to world transformation +/// 0 on success, otherwise an error. +long pqSpaceMouseImpl::SetCameraMatrix(const navlib::matrix_t& affine) +{ + if (this->Camera) + { + // VTK wants the world-to-camera transform, so invert to retrieve the + // position in world coords. + double m[16]; + double inv[16]; + vtkMatrix4x4::Invert(affine.m, m); + vtkMatrix4x4::DeepCopy(inv, affine.m); + + double pos[3] = { inv[3], inv[7], inv[11] }; + double lk[3] = { -m[8], -m[9], -m[10] }; + double vu[3] = { m[4], m[5], m[6] }; + // vtkWarningWithObjectMacro(nullptr, << "SM ps " << pos[0] << " " << pos[1] << " " << pos[2] ); + // vtkWarningWithObjectMacro(nullptr, << "SM lk " << lk[0] << " " << lk[1] << " " << lk[2] ); + // vtkWarningWithObjectMacro(nullptr, << "SM vu " << vu[0] << " " << vu[1] << " " << vu[2] ); + double dist = this->Camera->GetDistance(); + // Set the new values on the camera. + double fp[3] = { pos[0] + dist * lk[0], pos[1] + dist * lk[1], pos[2] + dist * lk[2] }; + this->Camera->SetPosition(pos); + this->Camera->SetFocalPoint(fp); + this->Camera->SetViewUp(vu); + this->render(); + return 0; + } + + return navlib::make_result_code(navlib::navlib_errc::invalid_operation); +} + +long pqSpaceMouseImpl::GetSelectionTransform(navlib::matrix_t& /*affine*/) const +{ + return navlib::make_result_code(navlib::navlib_errc::function_not_supported); +} + +long pqSpaceMouseImpl::SetSelectionTransform(const navlib::matrix_t& /*affine*/) +{ + return navlib::make_result_code(navlib::navlib_errc::invalid_operation); +} + +/// Sets the extents of the view +/// The view extents +/// 0 on success, otherwise an error. +long pqSpaceMouseImpl::SetViewExtents(const navlib::box_t& /*extents*/) +{ + return navlib::make_result_code(navlib::navlib_errc::invalid_operation); +} + +/// Sets the visibility of the pivot +/// true to display the pivot +/// 0 on success, otherwise an error. +long pqSpaceMouseImpl::SetPivotVisible(bool /*show*/) +{ + return navlib::make_result_code(navlib::navlib_errc::invalid_operation); +} + +/// Sets the position of the pivot +/// The position of the pivot in world +/// coordinates 0 on success, otherwise an error. +long pqSpaceMouseImpl::SetPivotPosition(const navlib::point_t& /*position*/) +{ + return 0; +} + +/// Sets the vertical field of view +/// The fov in radians +/// 0 on success, otherwise an error. +long pqSpaceMouseImpl::SetViewFOV(double /*fov*/) +{ + return navlib::make_result_code(navlib::navlib_errc::invalid_operation); +} + +long pqSpaceMouseImpl::SetViewFrustum(const navlib::frustum_t& /*frustum*/) +{ + return navlib::make_result_code(navlib::navlib_errc::function_not_supported); +} + +/////////////////////////////////////////////////////////////////////////// +// Handle navlib hit testing parameters + +/// Sets the diameter of the aperture in the projection plane to look through. +/// The diameter of the hole/ray in world units. +long pqSpaceMouseImpl::SetHitAperture(double /*diameter*/) +{ + return navlib::make_result_code(navlib::navlib_errc::invalid_operation); +} + +/// Sets the direction to look +/// Unit vector in world coordinates +long pqSpaceMouseImpl::SetHitDirection(const navlib::vector_t& /*direction*/) +{ + return navlib::make_result_code(navlib::navlib_errc::invalid_operation); +} + +/// Sets the position to look from +/// Position in world coordinates +long pqSpaceMouseImpl::SetHitLookFrom(const navlib::point_t& /*position*/) +{ + return navlib::make_result_code(navlib::navlib_errc::invalid_operation); +} + +/// Sets the selection only hit filter +/// If true then filter non-selected objects +long pqSpaceMouseImpl::SetHitSelectionOnly(bool /*value*/) +{ + return navlib::make_result_code(navlib::navlib_errc::invalid_operation); +} + +////////////////////////////////////////////////////////////////////////////////////// + +/// Handle when a command is activated by a mouse button press +long pqSpaceMouseImpl::SetActiveCommand(std::string /*commandId*/) +{ + return 0; +} + +/// Handler for settings_changed event +long pqSpaceMouseImpl::SetSettingsChanged(long /*change*/) +{ + return 0; +} + +#ifdef _MSC_VER +#pragma warning(pop) +#endif diff --git a/Plugins/SpaceMouseInteractor/pqSpaceMouseImplWin.h b/Plugins/SpaceMouseInteractor/pqSpaceMouseImplWin.h new file mode 100644 index 0000000000..0277057c75 --- /dev/null +++ b/Plugins/SpaceMouseInteractor/pqSpaceMouseImplWin.h @@ -0,0 +1,115 @@ +/*========================================================================= + + Program: ParaView + Module: pqSpaceMouseImpl.h + + Copyright (c) 2005,2006 Sandia Corporation, Kitware Inc. + All rights reserved. + + ParaView is a free software; you can redistribute it and/or modify it + under the terms of the ParaView license version 1.2. + + See License_v1.2.txt for the full ParaView license. + A copy of this license can be obtained by contacting + Kitware Inc. + 28 Corporate Drive + Clifton Park, NY 12065 + USA + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR +CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +========================================================================*/ +#ifndef pqSpaceMouseImpl_h +#define pqSpaceMouseImpl_h + +// This header is provided in the 3DxWare SDK, in samples/navlib_viewer/src/SpaceMouse +// If you are not using paraview superbuild, it is simplest to copy the entire +// SpaceMouse directory to the ${3DxWareSDK_INCLUDE_DIR} directory +#include "SpaceMouse/CNavigation3D.hpp" +#include "vtkCamera.h" +#include "vtkWeakPointer.h" + +#include +class pqView; + +/// Communicate with the TDxNavlib SDK provided by 3DConnexion to move the camera with a SpaceMouse +class pqSpaceMouseImpl + : public QObject + , public TDx::SpaceMouse::Navigation3D::CNavigation3D +{ + Q_OBJECT + typedef TDx::SpaceMouse::Navigation3D::CNavigation3D nav3d; + typedef TDx::SpaceMouse::Navigation3D::CNavigation3D Superclass; + +public: + pqSpaceMouseImpl(); + ~pqSpaceMouseImpl() override; + +public Q_SLOTS: + /// which view are we controlling? The active one. + void setActiveView(pqView* view); + /// the active camera changed. + void cameraChanged(); + +public: + void render(); + + // navlib initialization + bool Enable3DNavigation(); + void Disable3DNavigation(); + + ///////////////////////////////////////////////////////////////////////////////////////////////// + // accessors and mutators used by the navlib + // These are the functions supplied to the navlib in the accessors structure so that the navlib + // can query and update our (the clients) values. + long GetCoordinateSystem(navlib::matrix_t& affine) const override; + long GetViewConstructionPlane(navlib::plane_t& plane) const override; + long GetCameraMatrix(navlib::matrix_t& affine) const override; + long GetViewExtents(navlib::box_t& affine) const override; + long GetViewFrustum(navlib::frustum_t& frustum) const override; + long GetViewFOV(double& fov) const override; + long GetIsViewRotatable(navlib::bool_t& rotatble) const override; + long IsUserPivot(navlib::bool_t& userPivot) const override; + long GetPivotVisible(navlib::bool_t& visible) const override; + long GetPivotPosition(navlib::point_t& position) const override; + long GetPointerPosition(navlib::point_t& position) const override; + long GetIsViewPerspective(navlib::bool_t& persp) const override; + long GetModelExtents(navlib::box_t& extents) const override; + long GetIsSelectionEmpty(navlib::bool_t& empty) const override; + long GetSelectionExtents(navlib::box_t& extents) const override; + long GetSelectionTransform(navlib::matrix_t&) const override; + long GetHitLookAt(navlib::point_t& position) const override; + + long SetSettingsChanged(long change) override; + + long SetMotionFlag(bool value) override; + long SetTransaction(long value) override; + long SetCameraMatrix(const navlib::matrix_t& affine) override; + long SetSelectionTransform(const navlib::matrix_t& affine) override; + long SetViewExtents(const navlib::box_t& extents) override; + long SetViewFOV(double fov) override; + long SetViewFrustum(const navlib::frustum_t& frustum) override; + long SetPivotPosition(const navlib::point_t& position) override; + long SetPivotVisible(bool visible) override; + + long SetHitLookFrom(const navlib::point_t& position) override; + long SetHitDirection(const navlib::vector_t& direction) override; + long SetHitAperture(double diameter) override; + long SetHitSelectionOnly(bool value) override; + long SetActiveCommand(std::string commandId) override; + +protected: + vtkWeakPointer Camera; +}; + +#endif -- GitLab