iMSTK
Interactive Medical Simulation Toolkit
imstkVTKInteractorStyleVR.cpp
1 /*
2 ** This file is part of the Interactive Medical Simulation Toolkit (iMSTK)
3 ** iMSTK is distributed under the Apache License, Version 2.0.
4 ** See accompanying NOTICE for details.
5 */
6 
7 #include "imstkVTKInteractorStyleVR.h"
8 #include "imstkLogger.h"
9 #include "imstkOpenVRDeviceClient.h"
10 
11 #include <vtkMath.h>
12 #include <vtkEventData.h>
13 #include <vtkObjectFactory.h>
14 #include "imstkVtkOpenVRRenderWindowInteractorImstk.h"
15 
16 vtkStandardNewMacro(vtkInteractorStyleVR);
17 
18 vtkInteractorStyleVR::vtkInteractorStyleVR()
19 {
20  // Setup the VR device clients
21  m_leftControllerDeviceClient = imstk::OpenVRDeviceClient::New(OPENVR_LEFT_CONTROLLER);
22  m_rightControllerDeviceClient = imstk::OpenVRDeviceClient::New(OPENVR_RIGHT_CONTROLLER);
23  m_hmdDeviceClient = imstk::OpenVRDeviceClient::New(OPENVR_HMD);
24 }
25 
26 void
27 vtkInteractorStyleVR::OnButtonPress(vtkEventData* data, int buttonId)
28 {
29  vtkEventDataForDevice* eventDataButton = data->GetAsEventDataForDevice();
30  const vtkEventDataAction action = eventDataButton->GetAction();
31  const vtkEventDataDevice device = eventDataButton->GetDevice();
32 
33  if (device == vtkEventDataDevice::LeftController)
34  {
35  if (action == vtkEventDataAction::Press)
36  {
37  m_leftControllerDeviceClient->emitButtonPress(buttonId);
38  }
39  else if (action == vtkEventDataAction::Release)
40  {
41  m_leftControllerDeviceClient->emitButtonRelease(buttonId);
42  }
43  }
44  else if (device == vtkEventDataDevice::RightController)
45  {
46  if (action == vtkEventDataAction::Press)
47  {
48  m_rightControllerDeviceClient->emitButtonPress(buttonId);
49  }
50  else if (action == vtkEventDataAction::Release)
51  {
52  m_rightControllerDeviceClient->emitButtonRelease(buttonId);
53  }
54  }
55 }
56 
57 void
59 {
61  vtkOpenVRRenderWindowInteractorImstk::SafeDownCast(GetInteractor());
62  CHECK(iren->GetInitialized()) << "Cannot addMovementActions to style until "
63  "interactor has been initialized";
64  iren->AddAction("/actions/vtk/in/LeftGripMovement", true,
65  [this](vtkEventData* ed)
66  {
67  vtkEventDataDevice3D* edd = ed->GetAsEventDataDevice3D();
68  const double* pos = edd->GetTrackPadPosition();
69  m_leftControllerDeviceClient->setTrackpadPosition(imstk::Vec2d(pos[0], pos[1]));
70  });
71  iren->AddAction("/actions/vtk/in/RightGripMovement", true,
72  [this](vtkEventData* ed)
73  {
74  vtkEventDataDevice3D* edd = ed->GetAsEventDataDevice3D();
75  const double* pos = edd->GetTrackPadPosition();
76  m_rightControllerDeviceClient->setTrackpadPosition(imstk::Vec2d(pos[0], pos[1]));
77  });
78 }
79 
80 void
82 {
84  vtkOpenVRRenderWindowInteractorImstk::SafeDownCast(GetInteractor());
85  CHECK(iren->GetInitialized()) << "Cannot addButtonActions to style until "
86  "interactor has been initialized";
87 
88  // Called when buttons are pressed/released
89  // Note: grips and triggers must use separate binding
90  // else one can't fire while other is down
91  std::array<std::string, 8> buttonActionNames =
92  {
93  "/actions/vtk/in/Button0Pressed",
94  "/actions/vtk/in/Button1Pressed",
95  "/actions/vtk/in/Button2Pressed",
96  "/actions/vtk/in/Button3Pressed",
97  "/actions/vtk/in/LeftGripPressed",
98  "/actions/vtk/in/RightGripPressed",
99  "/actions/vtk/in/LeftTriggerPressed",
100  "/actions/vtk/in/RightTriggerPressed"
101  };
102  for (int i = 0; i < 8; i++)
103  {
104  iren->AddAction(buttonActionNames[i], false,
105  [this, i](vtkEventData* ed)
106  {
107  OnButtonPress(ed, i);
108  });
109  }
110 }
111 
112 void
113 vtkInteractorStyleVR::OnMove3D(vtkEventData* eventData)
114 {
115  if (eventData->GetType() != vtkCommand::Move3DEvent)
116  {
117  return;
118  }
119  vtkEventDataDevice3D* eventDataDevice = static_cast<vtkEventDataDevice3D*>(eventData);
120  if (vtkEventDataDevice::LeftController == eventDataDevice->GetDevice())
121  {
122  imstk::Vec3d pos;
123  eventDataDevice->GetWorldPosition(pos.data());
124  double orientation[4];
125  eventDataDevice->GetWorldOrientation(orientation);
126  m_leftControllerDeviceClient->setPose(pos, imstk::Quatd(imstk::Rotd(vtkMath::RadiansFromDegrees(orientation[0]),
127  imstk::Vec3d(orientation[1], orientation[2], orientation[3]))));
128  }
129  else if (vtkEventDataDevice::RightController == eventDataDevice->GetDevice())
130  {
131  imstk::Vec3d pos;
132  eventDataDevice->GetWorldPosition(pos.data());
133  double orientation[4];
134  eventDataDevice->GetWorldOrientation(orientation);
135  m_rightControllerDeviceClient->setPose(pos, imstk::Quatd(imstk::Rotd(vtkMath::RadiansFromDegrees(orientation[0]),
136  imstk::Vec3d(orientation[1], orientation[2], orientation[3]))));
137  }
138  else if (vtkEventDataDevice::HeadMountedDisplay == eventDataDevice->GetDevice())
139  {
140  imstk::Vec3d pos;
141  eventDataDevice->GetWorldPosition(pos.data());
142  double orientation[4];
143  eventDataDevice->GetWorldOrientation(orientation);
144  m_hmdDeviceClient->setPose(pos, imstk::Quatd(imstk::Rotd(vtkMath::RadiansFromDegrees(orientation[0]),
145  imstk::Vec3d(orientation[1], orientation[2], orientation[3]))));
146  }
147 }
void addButtonActions()
Adds button actions.
void AddAction(std::string path, vtkCommand::EventIds, bool isAnalog)
static std::shared_ptr< OpenVRDeviceClient > New(DeviceType deviceType)
VTK Interactor style for VR.
void addMovementActions()
Adds thumbstick movement actions.