From 6caf2948b49d4e902d7707fbf51402d9399d3e7d Mon Sep 17 00:00:00 2001 From: Csaba Pinter Date: Thu, 11 Jul 2019 12:17:46 -0400 Subject: [PATCH] ENH: Convert the interactor style to use the new vtkMRMLViewInteractorStyle --- .../vtkVirtualRealityViewInteractorStyle.cxx | 112 +++++++++++++++--- .../vtkVirtualRealityViewInteractorStyle.h | 25 ++-- .../Widgets/qMRMLVirtualRealityHomeWidget.cxx | 2 +- .../Widgets/qMRMLVirtualRealityView.cxx | 46 ++++--- 4 files changed, 139 insertions(+), 46 deletions(-) diff --git a/VirtualReality/MRML/vtkVirtualRealityViewInteractorStyle.cxx b/VirtualReality/MRML/vtkVirtualRealityViewInteractorStyle.cxx index 960ad2e..7e48965 100644 --- a/VirtualReality/MRML/vtkVirtualRealityViewInteractorStyle.cxx +++ b/VirtualReality/MRML/vtkVirtualRealityViewInteractorStyle.cxx @@ -24,16 +24,17 @@ #include "vtkMRMLVirtualRealityViewNode.h" // MRML includes -#include "vtkMRMLScene.h" -#include "vtkMRMLModelNode.h" +#include "vtkMRMLAbstractThreeDViewDisplayableManager.h" +#include "vtkMRMLInteractionEventData.h" +#include "vtkMRMLLinearTransformNode.h" +#include "vtkMRMLModelDisplayableManager.h" #include "vtkMRMLModelDisplayNode.h" -#include "vtkMRMLVolumeNode.h" -#include "vtkMRMLVolumeRenderingDisplayNode.h" +#include "vtkMRMLModelNode.h" +#include "vtkMRMLScene.h" #include "vtkMRMLSegmentationNode.h" #include "vtkMRMLSegmentationDisplayNode.h" -#include "vtkMRMLLinearTransformNode.h" -#include "vtkMRMLAbstractThreeDViewDisplayableManager.h" -#include "vtkMRMLModelDisplayableManager.h" +#include "vtkMRMLVolumeNode.h" +#include "vtkMRMLVolumeRenderingDisplayNode.h" // VTK includes #include @@ -47,6 +48,7 @@ #include #include #include +#include #include "vtkOpenVRRenderWindow.h" #include "vtkOpenVRRenderWindowInteractor.h" @@ -173,7 +175,6 @@ bool vtkVirtualRealityViewInteractorStyle::vtkInternal::CalculateCombinedControl //---------------------------------------------------------------------------- vtkVirtualRealityViewInteractorStyle::vtkVirtualRealityViewInteractorStyle() - : DisplayableManagerGroup(nullptr) { this->Internal = new vtkInternal(); @@ -187,6 +188,10 @@ vtkVirtualRealityViewInteractorStyle::vtkVirtualRealityViewInteractorStyle() } } + this->AccuratePicker = vtkSmartPointer::New(); + this->AccuratePicker->SetTolerance( .005 ); + this->QuickPicker = vtkSmartPointer::New(); + // Create default inputs mapping this->MapInputToAction(vtkEventDataDevice::RightController, vtkEventDataDeviceInput::Grip, VTKIS_POSITION_PROP); @@ -202,7 +207,6 @@ vtkVirtualRealityViewInteractorStyle::vtkVirtualRealityViewInteractorStyle() //---------------------------------------------------------------------------- vtkVirtualRealityViewInteractorStyle::~vtkVirtualRealityViewInteractorStyle() { - this->SetDisplayableManagerGroup(nullptr); delete this->Internal; } @@ -210,7 +214,7 @@ vtkVirtualRealityViewInteractorStyle::~vtkVirtualRealityViewInteractorStyle() void vtkVirtualRealityViewInteractorStyle::PrintSelf(ostream& os, vtkIndent indent) { this->Superclass::PrintSelf(os,indent); -} +} //---------------------------------------------------------------------------- void vtkVirtualRealityViewInteractorStyle::SetInteractor(vtkRenderWindowInteractor *i) @@ -279,9 +283,63 @@ void vtkVirtualRealityViewInteractorStyle::ProcessEvents( // Generic events binding //---------------------------------------------------------------------------- +//---------------------------------------------------------------------------- +bool vtkVirtualRealityViewInteractorStyle::DelegateInteractionEventToDisplayableManagers(vtkEventData* inputEventData) +{ + // Get display and world position + int* displayPositionInt = this->GetInteractor()->GetEventPosition(); + vtkRenderer* pokedRenderer = this->GetInteractor()->FindPokedRenderer(displayPositionInt[0], displayPositionInt[1]); + if (!pokedRenderer || !inputEventData) + { + // can happen during application shutdown + return false; + } + + vtkNew ed; + ed->SetType(inputEventData->GetType()); + int displayPositionCorrected[2] = { displayPositionInt[0] - pokedRenderer->GetOrigin()[0], displayPositionInt[1] - pokedRenderer->GetOrigin()[1] }; + ed->SetDisplayPosition(displayPositionCorrected); + double worldPosition[3] = { 0.0, 0.0, 0.0 }; + vtkEventDataDevice3D* inputEventDataDevice3D = inputEventData->GetAsEventDataDevice3D(); + if (!inputEventDataDevice3D) + { + vtkErrorMacro("DelegateInteractionEventToDisplayableManagers: Invalid event data type"); + return false; + } + inputEventDataDevice3D->GetWorldPosition(worldPosition); + ed->SetDevice(inputEventDataDevice3D->GetDevice()); + ed->SetWorldPosition(worldPosition, true); + ed->SetWorldToPhysicalScale(this->GetMagnification()); + ed->SetAccuratePicker(this->AccuratePicker); + ed->SetRenderer(this->CurrentRenderer); + std::string interactionContextName; + if (ed->GetDevice() == vtkEventDataDevice::LeftController) + { + interactionContextName = "LeftController"; //TODO: Store these elsewhere + } + else if (ed->GetDevice() == vtkEventDataDevice::RightController) + { + interactionContextName = "RightController"; //TODO: Store these elsewhere + } + else + { + vtkErrorMacro("DelegateInteractionEventToDisplayableManagers: Unrecognized device"); + } + ed->SetInteractionContextName(interactionContextName); + + ed->SetAttributesFromInteractor(this->GetInteractor()); + + return this->DelegateInteractionEventDataToDisplayableManagers(ed); +} + //---------------------------------------------------------------------------- void vtkVirtualRealityViewInteractorStyle::OnMove3D(vtkEventData* edata) { + if (this->DelegateInteractionEventToDisplayableManagers(edata)) + { + return; + } + vtkEventDataDevice3D *edd = edata->GetAsEventDataDevice3D(); if (!edd) { @@ -322,6 +380,11 @@ void vtkVirtualRealityViewInteractorStyle::OnMove3D(vtkEventData* edata) //---------------------------------------------------------------------------- void vtkVirtualRealityViewInteractorStyle::OnButton3D(vtkEventData* edata) { + if (this->DelegateInteractionEventToDisplayableManagers(edata)) + { + return; + } + vtkEventDataDevice3D *bd = edata->GetAsEventDataDevice3D(); if (!bd) { @@ -365,7 +428,7 @@ void vtkVirtualRealityViewInteractorStyle::PositionProp(vtkEventData* ed) vtkMRMLDisplayableNode* pickedNode = this->Internal->PickedNode[deviceIndex]; if ( pickedNode == nullptr || !pickedNode->GetSelectable() - || !this->CurrentRenderer || !this->DisplayableManagerGroup ) + || !this->CurrentRenderer || !this->DisplayableManagers ) { return; } @@ -486,10 +549,10 @@ void vtkVirtualRealityViewInteractorStyle::StartPositionProp(vtkEventDataDevice3 edata->GetWorldPosition(pos); // Get MRML node to move - for (int i=0; iDisplayableManagerGroup->GetDisplayableManagerCount(); ++i) + for (int i=0; iDisplayableManagers->GetDisplayableManagerCount(); ++i) { vtkMRMLAbstractThreeDViewDisplayableManager* currentDisplayableManager = - vtkMRMLAbstractThreeDViewDisplayableManager::SafeDownCast(this->DisplayableManagerGroup->GetNthDisplayableManager(i)); + vtkMRMLAbstractThreeDViewDisplayableManager::SafeDownCast(this->DisplayableManagers->GetNthDisplayableManager(i)); if (!currentDisplayableManager) { continue; @@ -791,13 +854,13 @@ void vtkVirtualRealityViewInteractorStyle::EndAction(int state, vtkEventDataDevi //--------------------------------------------------------------------------- vtkMRMLScene* vtkVirtualRealityViewInteractorStyle::GetMRMLScene() { - if (!this->DisplayableManagerGroup - || this->DisplayableManagerGroup->GetDisplayableManagerCount() == 0) + if (!this->DisplayableManagers + || this->DisplayableManagers->GetDisplayableManagerCount() == 0) { return nullptr; } - return this->DisplayableManagerGroup->GetNthDisplayableManager(0)->GetMRMLScene(); + return this->DisplayableManagers->GetNthDisplayableManager(0)->GetMRMLScene(); } //--------------------------------------------------------------------------- @@ -883,3 +946,20 @@ double vtkVirtualRealityViewInteractorStyle::GetMagnification() return 1000.0 / rw->GetPhysicalScale(); } + +//--------------------------------------------------------------------------- +bool vtkVirtualRealityViewInteractorStyle::QuickPick(int x, int y, double pickPoint[3]) +{ + this->FindPokedRenderer(x, y); + if (this->CurrentRenderer == nullptr) + { + vtkDebugMacro("Pick: couldn't find the poked renderer at event position " << x << ", " << y); + return false; + } + + this->QuickPicker->Pick(x, y, 0, this->CurrentRenderer); + + this->QuickPicker->GetPickPosition(pickPoint); + + return true; +} diff --git a/VirtualReality/MRML/vtkVirtualRealityViewInteractorStyle.h b/VirtualReality/MRML/vtkVirtualRealityViewInteractorStyle.h index da62946..2efab94 100644 --- a/VirtualReality/MRML/vtkVirtualRealityViewInteractorStyle.h +++ b/VirtualReality/MRML/vtkVirtualRealityViewInteractorStyle.h @@ -23,30 +23,36 @@ // MRML includes #include "vtkMRMLDisplayableManagerGroup.h" +#include "vtkMRMLViewInteractorStyle.h" // VTK includes #include "vtkObject.h" -#include "vtkInteractorStyle3D.h" #include "vtkOpenVRRenderWindow.h" // for enums #include "vtkEventData.h" #include "vtkSlicerVirtualRealityModuleMRMLExport.h" class vtkMRMLScene; +class vtkCellPicker; +class vtkWorldPointPicker; /// \brief Virtual reality interactions /// /// TODO: /// class VTK_SLICER_VIRTUALREALITY_MODULE_MRML_EXPORT vtkVirtualRealityViewInteractorStyle : - public vtkInteractorStyle3D + public vtkMRMLViewInteractorStyle { public: static vtkVirtualRealityViewInteractorStyle *New(); - vtkTypeMacro(vtkVirtualRealityViewInteractorStyle,vtkInteractorStyle3D); + vtkTypeMacro(vtkVirtualRealityViewInteractorStyle,vtkMRMLViewInteractorStyle); void PrintSelf(ostream& os, vtkIndent indent) override; - /// Set the Interactor wrapper being controlled by this object. (Satisfy superclass API.) + /// Give a chance to displayable managers to process the event. + /// Return true if the event is processed. + bool DelegateInteractionEventToDisplayableManagers(vtkEventData* inputEventData) override; + + /// Set the Interactor wrapper being controlled by this object. (Satisfy superclass API.) void SetInteractor(vtkRenderWindowInteractor *interactor) override; /// Main process event method @@ -140,11 +146,6 @@ class VTK_SLICER_VIRTUALREALITY_MODULE_MRML_EXPORT vtkVirtualRealityViewInteract //vtkOpenVRMenuWidget *GetMenu() { // return this->Menu.Get(); } - /// Get the displayable managers - vtkGetObjectMacro(DisplayableManagerGroup, vtkMRMLDisplayableManagerGroup); - /// Set the displayable managers - vtkSetObjectMacro(DisplayableManagerGroup, vtkMRMLDisplayableManagerGroup); - /// Set physical to world magnification. Valid value range is [0.01, 100]. /// Note: Conversion is physicalScale = 1000 / magnification void SetMagnification(double magnification); @@ -181,6 +182,8 @@ class VTK_SLICER_VIRTUALREALITY_MODULE_MRML_EXPORT vtkVirtualRealityViewInteract //*/ //void AddTooltipForInput(vtkEventDataDevice device, vtkEventDataDeviceInput input); + bool QuickPick(int x, int y, double pickPoint[3]); + protected: ///** //* Indicates if picking should be updated every frame. If so, the interaction @@ -191,7 +194,9 @@ class VTK_SLICER_VIRTUALREALITY_MODULE_MRML_EXPORT vtkVirtualRealityViewInteract //vtkNew HardwarePicker; - vtkMRMLDisplayableManagerGroup* DisplayableManagerGroup; + /// For jump to slice feature (when mouse is moved while shift key is pressed) + vtkSmartPointer AccuratePicker; + vtkSmartPointer QuickPicker; protected: vtkVirtualRealityViewInteractorStyle(); diff --git a/VirtualReality/Widgets/qMRMLVirtualRealityHomeWidget.cxx b/VirtualReality/Widgets/qMRMLVirtualRealityHomeWidget.cxx index e35b25c..bd35834 100644 --- a/VirtualReality/Widgets/qMRMLVirtualRealityHomeWidget.cxx +++ b/VirtualReality/Widgets/qMRMLVirtualRealityHomeWidget.cxx @@ -181,7 +181,7 @@ QString qMRMLVirtualRealityHomeWidget::virtualRealityViewNodeID()const } //----------------------------------------------------------------------------- -void qMRMLVirtualRealityHomeWidget::setVirtualRealityViewNode(vtkMRMLVirtualRealityViewNode * node) +void qMRMLVirtualRealityHomeWidget::setVirtualRealityViewNode(vtkMRMLVirtualRealityViewNode* node) { Q_D(qMRMLVirtualRealityHomeWidget); diff --git a/VirtualReality/Widgets/qMRMLVirtualRealityView.cxx b/VirtualReality/Widgets/qMRMLVirtualRealityView.cxx index 4dc3da8..0e5088b 100644 --- a/VirtualReality/Widgets/qMRMLVirtualRealityView.cxx +++ b/VirtualReality/Widgets/qMRMLVirtualRealityView.cxx @@ -118,7 +118,7 @@ namespace //--------------------------------------------------------------------------- qMRMLVirtualRealityViewPrivate::qMRMLVirtualRealityViewPrivate(qMRMLVirtualRealityView& object) : q_ptr(&object) - , CamerasLogic(NULL) + , CamerasLogic(nullptr) { this->MRMLVirtualRealityViewNode = 0; this->HomeWidget = new qMRMLVirtualRealityHomeWidget(q_ptr); @@ -190,6 +190,14 @@ void qMRMLVirtualRealityViewPrivate::createRenderWindow() vtkMRMLVirtualRealityViewDisplayableManagerFactory* factory = vtkMRMLVirtualRealityViewDisplayableManagerFactory::GetInstance(); + vtkSlicerApplicationLogic* appLogic = qSlicerApplication::application()->applicationLogic(); + if (!appLogic) + { + qCritical() << Q_FUNC_INFO << ": Failed to access application logic"; + return; + } + factory->SetMRMLApplicationLogic(appLogic); + QStringList displayableManagers; displayableManagers //<< "vtkMRMLCameraDisplayableManager" //<< "vtkMRMLViewDisplayableManager" @@ -216,7 +224,7 @@ void qMRMLVirtualRealityViewPrivate::createRenderWindow() this->DisplayableManagerGroup = vtkSmartPointer::Take( factory->InstantiateDisplayableManagers(q->renderer())); this->DisplayableManagerGroup->SetMRMLDisplayableNode(this->MRMLVirtualRealityViewNode); - this->InteractorStyle->SetDisplayableManagerGroup(this->DisplayableManagerGroup); + this->InteractorStyle->SetDisplayableManagers(this->DisplayableManagerGroup); qDebug() << "this->DisplayableManagerGroup" << this->DisplayableManagerGroup->GetDisplayableManagerCount(); @@ -263,7 +271,7 @@ void qMRMLVirtualRealityViewPrivate::createRenderWindow() this->RenderWindow->Initialize(); if (!this->RenderWindow->GetHMD()) { - qWarning() << "Failed to initialize OpenVR RenderWindow"; + qWarning() << Q_FUNC_INFO << ": Failed to initialize OpenVR RenderWindow"; return; } } @@ -276,14 +284,14 @@ void qMRMLVirtualRealityViewPrivate::destroyRenderWindow() // Must break the connection between interactor and render window, // otherwise they would circularly refer to each other and would not // be deleted. - this->Interactor->SetRenderWindow(NULL); - this->Interactor = NULL; - this->InteractorStyle = NULL; - this->DisplayableManagerGroup = NULL; - this->Renderer = NULL; - this->Camera = NULL; - this->Lights = NULL; - this->RenderWindow = NULL; + this->Interactor->SetRenderWindow(nullptr); + this->Interactor = nullptr; + this->InteractorStyle = nullptr; + this->DisplayableManagerGroup = nullptr; + this->Renderer = nullptr; + this->Camera = nullptr; + this->Lights = nullptr; + this->RenderWindow = nullptr; } // -------------------------------------------------------------------------- @@ -292,7 +300,7 @@ void qMRMLVirtualRealityViewPrivate::updateWidgetFromMRML() Q_Q(qMRMLVirtualRealityView); if (!this->MRMLVirtualRealityViewNode || !this->MRMLVirtualRealityViewNode->GetVisibility()) { - if (this->RenderWindow != NULL) + if (this->RenderWindow != nullptr) { this->destroyRenderWindow(); } @@ -505,9 +513,9 @@ void qMRMLVirtualRealityViewPrivate::updateTransformNodeWithControllerPose(vtkEv { vtkMRMLLinearTransformNode* node = this->MRMLVirtualRealityViewNode->GetControllerTransformNode(device); - if (node == NULL) + if (node == nullptr) { - qCritical() << "Unable to retrieve linear transform node for device: " << (int)device; + qCritical() << Q_FUNC_INFO << ": Unable to retrieve linear transform node for device: " << (int)device; return; } @@ -549,9 +557,9 @@ void qMRMLVirtualRealityViewPrivate::updateTransformNodeWithHMDPose() { vtkMRMLLinearTransformNode* node = this->MRMLVirtualRealityViewNode->GetHMDTransformNode(); - if (node == NULL) + if (node == nullptr) { - qCritical() << "Unable to retrieve linear transform node for HMD"; + qCritical() << Q_FUNC_INFO << ": Unable to retrieve linear transform node for HMD"; return; } @@ -596,7 +604,7 @@ void qMRMLVirtualRealityViewPrivate::updateTransformNodesWithTrackerPoses() node = vtkMRMLLinearTransformNode::SafeDownCast(this->MRMLVirtualRealityViewNode->GetScene()->AddNode(vtkMRMLLinearTransformNode::New())); if (node == nullptr) { - qCritical() << "Unable to add transform node to scene. Can't update VR tracker with ID: " << dev; + qCritical() << Q_FUNC_INFO << ": Unable to add transform node to scene. Can't update VR tracker with ID: " << dev; continue; } node->SetAttribute("VirtualReality.VRDeviceID", ss.str().c_str()); @@ -793,13 +801,13 @@ void qMRMLVirtualRealityView::updateViewFromReferenceViewCamera() vtkRenderer* ren = static_cast(d->RenderWindow->GetRenderers()->GetItemAsObject(0)); if (!ren) { - qWarning() << Q_FUNC_INFO << "The renderer must be set prior to calling InitializeViewFromCamera"; + qWarning() << Q_FUNC_INFO << ": The renderer must be set prior to calling InitializeViewFromCamera"; return; } vtkOpenVRCamera* cam = vtkOpenVRCamera::SafeDownCast(ren->GetActiveCamera()); if (!cam) { - qWarning() << Q_FUNC_INFO << "The renderer's active camera must be set prior to calling InitializeViewFromCamera"; + qWarning() << Q_FUNC_INFO << ": The renderer's active camera must be set prior to calling InitializeViewFromCamera"; return; }