1 /*=========================================================================
2 
3 Program:   Visualization Toolkit
4 Module:    vtkOpenVRInteractorStyle.cxx
5 
6 Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen
7 All rights reserved.
8 See Copyright.txt or http://www.kitware.com/Copyright.htm for details.
9 
10 This software is distributed WITHOUT ANY WARRANTY; without even
11 the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
12 PURPOSE.  See the above copyright notice for more information.
13 
14 =========================================================================*/
15 #include "vtkOpenVRInteractorStyle.h"
16 
17 #include "vtkCompositeDataSet.h"
18 #include "vtkDataObjectTreeIterator.h"
19 
20 #include "vtkBillboardTextActor3D.h"
21 #include "vtkCoordinate.h"
22 #include "vtkTextActor.h"
23 #include "vtkTextActor3D.h"
24 
25 #include "vtkAssemblyPath.h"
26 #include "vtkCallbackCommand.h"
27 #include "vtkCamera.h"
28 #include "vtkCellData.h"
29 #include "vtkCellPicker.h"
30 #include "vtkDataObject.h"
31 #include "vtkDataSet.h"
32 #include "vtkHardwareSelector.h"
33 #include "vtkIdTypeArray.h"
34 #include "vtkInformation.h"
35 #include "vtkMapper.h"
36 #include "vtkNew.h"
37 #include "vtkObjectFactory.h"
38 #include "vtkOpenVRCamera.h"
39 #include "vtkOpenVRControlsHelper.h"
40 #include "vtkOpenVRModel.h"
41 #include "vtkOpenVROverlay.h"
42 #include "vtkOpenVRRenderWindow.h"
43 #include "vtkOpenVRRenderWindowInteractor.h"
44 #include "vtkPlane.h"
45 #include "vtkPolyData.h"
46 #include "vtkPolyDataMapper.h"
47 #include "vtkPropPicker.h"
48 #include "vtkProperty.h"
49 #include "vtkRenderWindow.h"
50 #include "vtkRenderer.h"
51 #include "vtkSelection.h"
52 #include "vtkSelectionNode.h"
53 #include "vtkSphereSource.h"
54 #include "vtkStringArray.h"
55 #include "vtkTextProperty.h"
56 #include "vtkTimerLog.h"
57 #include "vtkVRHardwarePicker.h"
58 #include "vtkVRModel.h"
59 
60 #include "vtkVRMenuRepresentation.h"
61 #include "vtkVRMenuWidget.h"
62 
63 #include <sstream>
64 
65 // Map controller inputs to interaction states
66 vtkStandardNewMacro(vtkOpenVRInteractorStyle);
67 
68 //------------------------------------------------------------------------------
vtkOpenVRInteractorStyle()69 vtkOpenVRInteractorStyle::vtkOpenVRInteractorStyle()
70 {
71   for (int d = 0; d < vtkEventDataNumberOfDevices; ++d)
72   {
73     this->InteractionState[d] = VTKIS_NONE;
74     this->InteractionProps[d] = nullptr;
75     this->ClippingPlanes[d] = nullptr;
76 
77     for (int i = 0; i < vtkEventDataNumberOfInputs; i++)
78     {
79       this->ControlsHelpers[d][i] = nullptr;
80     }
81   }
82 
83   // Create default inputs mapping
84   this->MapInputToAction(vtkCommand::ViewerMovement3DEvent, VTKIS_DOLLY);
85   this->MapInputToAction(vtkCommand::Menu3DEvent, VTKIS_MENU);
86   this->MapInputToAction(vtkCommand::NextPose3DEvent, VTKIS_LOAD_CAMERA_POSE);
87   this->MapInputToAction(vtkCommand::Select3DEvent, VTKIS_POSITION_PROP);
88 
89   this->MenuCommand = vtkCallbackCommand::New();
90   this->MenuCommand->SetClientData(this);
91   this->MenuCommand->SetCallback(vtkOpenVRInteractorStyle::MenuCallback);
92 
93   this->Menu->SetRepresentation(this->MenuRepresentation);
94   this->Menu->PushFrontMenuItem("exit", "Exit", this->MenuCommand);
95   this->Menu->PushFrontMenuItem("clipmode", "Clipping Mode", this->MenuCommand);
96   this->Menu->PushFrontMenuItem("probemode", "Probe Mode", this->MenuCommand);
97   this->Menu->PushFrontMenuItem("grabmode", "Grab Mode", this->MenuCommand);
98 
99   vtkNew<vtkPolyDataMapper> pdm;
100   this->PickActor->SetMapper(pdm);
101   this->PickActor->GetProperty()->SetLineWidth(4);
102   this->PickActor->GetProperty()->RenderLinesAsTubesOn();
103   this->PickActor->GetProperty()->SetRepresentationToWireframe();
104   this->PickActor->DragableOff();
105 
106   this->HoverPickOff();
107   this->GrabWithRayOff();
108 
109   vtkNew<vtkCellPicker> exactPicker;
110   this->SetInteractionPicker(exactPicker);
111 }
112 
113 //------------------------------------------------------------------------------
~vtkOpenVRInteractorStyle()114 vtkOpenVRInteractorStyle::~vtkOpenVRInteractorStyle()
115 {
116   for (int d = 0; d < vtkEventDataNumberOfDevices; ++d)
117   {
118     if (this->ClippingPlanes[d])
119     {
120       this->ClippingPlanes[d]->Delete();
121       this->ClippingPlanes[d] = nullptr;
122     }
123   }
124   for (int d = 0; d < vtkEventDataNumberOfDevices; ++d)
125   {
126     for (int i = 0; i < vtkEventDataNumberOfInputs; i++)
127     {
128       if (this->ControlsHelpers[d][i])
129       {
130         this->ControlsHelpers[d][i]->Delete();
131         this->ControlsHelpers[d][i] = nullptr;
132       }
133     }
134   }
135   this->MenuCommand->Delete();
136 }
137 
SetInteractor(vtkRenderWindowInteractor * iren)138 void vtkOpenVRInteractorStyle::SetInteractor(vtkRenderWindowInteractor* iren)
139 {
140   this->Superclass::SetInteractor(iren);
141 
142   // hook up default bindings?
143   auto oiren = vtkOpenVRRenderWindowInteractor::SafeDownCast(iren);
144   if (!oiren)
145   {
146     return;
147   }
148 
149   oiren->AddAction("/actions/vtk/in/StartMovement", vtkCommand::ViewerMovement3DEvent, false);
150   oiren->AddAction("/actions/vtk/in/Movement", vtkCommand::ViewerMovement3DEvent, true);
151   oiren->AddAction("/actions/vtk/in/NextCameraPose", vtkCommand::NextPose3DEvent, false);
152   oiren->AddAction("/actions/vtk/in/TriggerAction", vtkCommand::Select3DEvent, false);
153   oiren->AddAction("/actions/vtk/in/PositionProp", vtkCommand::PositionProp3DEvent, false);
154   oiren->AddAction("/actions/vtk/in/ShowMenu", vtkCommand::Menu3DEvent, false);
155 }
156 
157 //------------------------------------------------------------------------------
PrintSelf(ostream & os,vtkIndent indent)158 void vtkOpenVRInteractorStyle::PrintSelf(ostream& os, vtkIndent indent)
159 {
160   this->Superclass::PrintSelf(os, indent);
161 }
162 
163 //------------------------------------------------------------------------------
MenuCallback(vtkObject * vtkNotUsed (object),unsigned long,void * clientdata,void * calldata)164 void vtkOpenVRInteractorStyle::MenuCallback(
165   vtkObject* vtkNotUsed(object), unsigned long, void* clientdata, void* calldata)
166 {
167   std::string name = static_cast<const char*>(calldata);
168   vtkOpenVRInteractorStyle* self = static_cast<vtkOpenVRInteractorStyle*>(clientdata);
169 
170   if (name == "exit")
171   {
172     if (self->Interactor)
173     {
174       self->Interactor->ExitCallback();
175     }
176   }
177   if (name == "togglelabel")
178   {
179     self->ToggleDrawControls();
180   }
181   if (name == "clipmode")
182   {
183     self->MapInputToAction(vtkCommand::Select3DEvent, VTKIS_CLIP);
184   }
185   if (name == "grabmode")
186   {
187     self->MapInputToAction(vtkCommand::Select3DEvent, VTKIS_POSITION_PROP);
188   }
189   if (name == "probemode")
190   {
191     self->MapInputToAction(vtkCommand::Select3DEvent, VTKIS_PICK);
192   }
193 }
194 
OnNextPose3D(vtkEventData * edata)195 void vtkOpenVRInteractorStyle::OnNextPose3D(vtkEventData* edata)
196 {
197   vtkEventDataDevice3D* edd = edata->GetAsEventDataDevice3D();
198   if (!edd)
199   {
200     return;
201   }
202   if (edd->GetAction() == vtkEventDataAction::Press)
203   {
204     this->LoadNextCameraPose();
205   }
206 }
207 
OnViewerMovement3D(vtkEventData * edata)208 void vtkOpenVRInteractorStyle::OnViewerMovement3D(vtkEventData* edata)
209 {
210   vtkEventDataDevice3D* edd = edata->GetAsEventDataDevice3D();
211   if (!edd)
212   {
213     return;
214   }
215 
216   // joystick moves?
217   int idev = static_cast<int>(edd->GetDevice());
218 
219   // Update current state
220   int x = this->Interactor->GetEventPosition()[0];
221   int y = this->Interactor->GetEventPosition()[1];
222   this->FindPokedRenderer(x, y);
223 
224   // Set current state and interaction prop
225   this->InteractionProp = this->InteractionProps[idev];
226 
227   double const* pos = edd->GetTrackPadPosition();
228 
229   if (edd->GetAction() == vtkEventDataAction::Press)
230   {
231     this->StartAction(VTKIS_DOLLY, edd);
232     this->LastTrackPadPosition[0] = 0.0;
233     this->LastTrackPadPosition[1] = 0.0;
234     return;
235   }
236 
237   if (edd->GetAction() == vtkEventDataAction::Release)
238   {
239     this->EndAction(VTKIS_DOLLY, edd);
240     return;
241   }
242 
243   // if the event is joystick and it is away from the center then
244   // call start, when returning to center call end
245   if (edd->GetInput() == vtkEventDataDeviceInput::Joystick &&
246     this->InteractionState[idev] != VTKIS_DOLLY && pos[1] != 0.0)
247   {
248     this->StartAction(VTKIS_DOLLY, edd);
249     this->LastTrackPadPosition[0] = 0.0;
250     this->LastTrackPadPosition[1] = 0.0;
251     return;
252   }
253 
254   if (this->InteractionState[idev] == VTKIS_DOLLY)
255   {
256     // strop when returning to zero on joystick
257     if (edd->GetInput() == vtkEventDataDeviceInput::Joystick && pos[1] == 0.0)
258     {
259       this->EndAction(VTKIS_DOLLY, edd);
260       return;
261     }
262     this->Dolly3D(edata);
263     this->InvokeEvent(vtkCommand::InteractionEvent, nullptr);
264   }
265 }
266 
267 //------------------------------------------------------------------------------
268 // Generic events binding
269 //------------------------------------------------------------------------------
OnMove3D(vtkEventData * edata)270 void vtkOpenVRInteractorStyle::OnMove3D(vtkEventData* edata)
271 {
272   vtkEventDataDevice3D* edd = edata->GetAsEventDataDevice3D();
273   if (!edd)
274   {
275     return;
276   }
277 
278   // joystick moves?
279   int idev = static_cast<int>(edd->GetDevice());
280 
281   // Update current state
282   int x = this->Interactor->GetEventPosition()[0];
283   int y = this->Interactor->GetEventPosition()[1];
284 
285   // Set current state and interaction prop
286   this->InteractionProp = this->InteractionProps[idev];
287 
288   switch (this->InteractionState[idev])
289   {
290     case VTKIS_POSITION_PROP:
291       this->FindPokedRenderer(x, y);
292       this->PositionProp(edd);
293       this->InvokeEvent(vtkCommand::InteractionEvent, nullptr);
294       break;
295     case VTKIS_DOLLY:
296       this->FindPokedRenderer(x, y);
297       this->Dolly3D(edata);
298       this->InvokeEvent(vtkCommand::InteractionEvent, nullptr);
299       break;
300     case VTKIS_CLIP:
301       this->FindPokedRenderer(x, y);
302       this->Clip(edd);
303       this->InvokeEvent(vtkCommand::InteractionEvent, nullptr);
304       break;
305   }
306 
307   // Update rays
308   this->UpdateRay(edd->GetDevice());
309 }
310 
311 //------------------------------------------------------------------------------
OnMenu3D(vtkEventData * edata)312 void vtkOpenVRInteractorStyle::OnMenu3D(vtkEventData* edata)
313 {
314   vtkEventDataDevice3D* edd = edata->GetAsEventDataDevice3D();
315   if (!edd)
316   {
317     return;
318   }
319 
320   int x = this->Interactor->GetEventPosition()[0];
321   int y = this->Interactor->GetEventPosition()[1];
322   this->FindPokedRenderer(x, y);
323 
324   if (edd->GetAction() == vtkEventDataAction::Press)
325   {
326     this->StartAction(VTKIS_MENU, edd);
327     return;
328   }
329 
330   if (edd->GetAction() == vtkEventDataAction::Release)
331   {
332     this->EndAction(VTKIS_MENU, edd);
333     return;
334   }
335 }
336 
337 //------------------------------------------------------------------------------
OnSelect3D(vtkEventData * edata)338 void vtkOpenVRInteractorStyle::OnSelect3D(vtkEventData* edata)
339 {
340   vtkEventDataDevice3D* bd = edata->GetAsEventDataDevice3D();
341   if (!bd)
342   {
343     return;
344   }
345 
346   int x = this->Interactor->GetEventPosition()[0];
347   int y = this->Interactor->GetEventPosition()[1];
348   this->FindPokedRenderer(x, y);
349 
350   decltype(this->InputMap)::key_type key(vtkCommand::Select3DEvent, bd->GetAction());
351   auto it = this->InputMap.find(key);
352   if (it == this->InputMap.end())
353   {
354     return;
355   }
356 
357   int state = it->second;
358 
359   // if grab mode then convert event data into where the ray is intersecting geometry
360 
361   if (bd->GetAction() == vtkEventDataAction::Press)
362   {
363     this->StartAction(state, bd);
364   }
365   if (bd->GetAction() == vtkEventDataAction::Release)
366   {
367     this->EndAction(state, bd);
368   }
369   if (bd->GetAction() == vtkEventDataAction::Touch)
370   {
371     this->StartAction(state, bd);
372   }
373   if (bd->GetAction() == vtkEventDataAction::Untouch)
374   {
375     this->EndAction(state, bd);
376   }
377 }
378 //------------------------------------------------------------------------------
379 
380 //------------------------------------------------------------------------------
381 // Interaction entry points
382 //------------------------------------------------------------------------------
StartPick(vtkEventDataDevice3D * edata)383 void vtkOpenVRInteractorStyle::StartPick(vtkEventDataDevice3D* edata)
384 {
385   this->HideBillboard();
386   this->HidePickActor();
387 
388   this->InteractionState[static_cast<int>(edata->GetDevice())] = VTKIS_PICK;
389 
390   // update ray
391   this->UpdateRay(edata->GetDevice());
392 }
393 //------------------------------------------------------------------------------
EndPick(vtkEventDataDevice3D * edata)394 void vtkOpenVRInteractorStyle::EndPick(vtkEventDataDevice3D* edata)
395 {
396   // perform probe
397   this->ProbeData(edata->GetDevice());
398 
399   this->InteractionState[static_cast<int>(edata->GetDevice())] = VTKIS_NONE;
400 
401   // turn off ray
402   this->UpdateRay(edata->GetDevice());
403 }
404 
405 //------------------------------------------------------------------------------
StartLoadCamPose(vtkEventDataDevice3D * edata)406 void vtkOpenVRInteractorStyle::StartLoadCamPose(vtkEventDataDevice3D* edata)
407 {
408   int iDevice = static_cast<int>(edata->GetDevice());
409   this->InteractionState[iDevice] = VTKIS_LOAD_CAMERA_POSE;
410 }
411 //------------------------------------------------------------------------------
EndLoadCamPose(vtkEventDataDevice3D * edata)412 void vtkOpenVRInteractorStyle::EndLoadCamPose(vtkEventDataDevice3D* edata)
413 {
414   this->LoadNextCameraPose();
415 
416   int iDevice = static_cast<int>(edata->GetDevice());
417   this->InteractionState[iDevice] = VTKIS_NONE;
418 }
419 
420 //------------------------------------------------------------------------------
HardwareSelect(vtkEventDataDevice controller,bool actorPassOnly)421 bool vtkOpenVRInteractorStyle::HardwareSelect(vtkEventDataDevice controller, bool actorPassOnly)
422 {
423   vtkRenderer* ren = this->CurrentRenderer;
424   vtkOpenVRRenderWindow* renWin =
425     vtkOpenVRRenderWindow::SafeDownCast(this->Interactor->GetRenderWindow());
426   vtkOpenVRRenderWindowInteractor* iren =
427     static_cast<vtkOpenVRRenderWindowInteractor*>(this->Interactor);
428 
429   if (!ren || !renWin || !iren)
430   {
431     return false;
432   }
433 
434   vtkOpenVRModel* cmodel = vtkOpenVRModel::SafeDownCast(renWin->GetTrackedDeviceModel(controller));
435   if (!cmodel)
436   {
437     return false;
438   }
439 
440   cmodel->SetVisibility(false);
441 
442   // Compute controller position and world orientation
443   double p0[3];   // Ray start point
444   double wxyz[4]; // Controller orientation
445   double dummy_ppos[3];
446   double wdir[3];
447   vr::TrackedDevicePose_t* tdPose = renWin->GetTrackedDevicePose(cmodel->TrackedDevice);
448   iren->ConvertPoseToWorldCoordinates(*tdPose, p0, wxyz, dummy_ppos, wdir);
449 
450   this->HardwarePicker->PickProp(p0, wxyz, ren, ren->GetViewProps(), actorPassOnly);
451 
452   cmodel->SetVisibility(true);
453 
454   return true;
455 }
456 
457 //------------------------------------------------------------------------------
StartPositionProp(vtkEventDataDevice3D * edata)458 void vtkOpenVRInteractorStyle::StartPositionProp(vtkEventDataDevice3D* edata)
459 {
460   if (this->GrabWithRay)
461   {
462     if (!this->HardwareSelect(edata->GetDevice(), true))
463     {
464       return;
465     }
466 
467     vtkSelection* selection = this->HardwarePicker->GetSelection();
468 
469     if (!selection || selection->GetNumberOfNodes() == 0)
470     {
471       return;
472     }
473 
474     vtkSelectionNode* node = selection->GetNode(0);
475     this->InteractionProp =
476       vtkProp3D::SafeDownCast(node->GetProperties()->Get(vtkSelectionNode::PROP()));
477   }
478   else
479   {
480     double pos[3];
481     edata->GetWorldPosition(pos);
482     this->FindPickedActor(pos, nullptr);
483   }
484 
485   if (this->InteractionProp == nullptr)
486   {
487     return;
488   }
489 
490   this->InteractionState[static_cast<int>(edata->GetDevice())] = VTKIS_POSITION_PROP;
491   this->InteractionProps[static_cast<int>(edata->GetDevice())] = this->InteractionProp;
492 
493   // Don't start action if a controller is already positioning the prop
494   int rc = static_cast<int>(vtkEventDataDevice::RightController);
495   int lc = static_cast<int>(vtkEventDataDevice::LeftController);
496   if (this->InteractionProps[rc] == this->InteractionProps[lc])
497   {
498     this->EndPositionProp(edata);
499     return;
500   }
501 }
502 
503 //------------------------------------------------------------------------------
EndPositionProp(vtkEventDataDevice3D * edata)504 void vtkOpenVRInteractorStyle::EndPositionProp(vtkEventDataDevice3D* edata)
505 {
506   vtkEventDataDevice dev = edata->GetDevice();
507   this->InteractionState[static_cast<int>(dev)] = VTKIS_NONE;
508   this->InteractionProps[static_cast<int>(dev)] = nullptr;
509 }
510 
511 //------------------------------------------------------------------------------
StartClip(vtkEventDataDevice3D * ed)512 void vtkOpenVRInteractorStyle::StartClip(vtkEventDataDevice3D* ed)
513 {
514   if (this->CurrentRenderer == nullptr)
515   {
516     return;
517   }
518 
519   vtkEventDataDevice dev = ed->GetDevice();
520   this->InteractionState[static_cast<int>(dev)] = VTKIS_CLIP;
521 
522   if (!this->ClippingPlanes[static_cast<int>(dev)])
523   {
524     this->ClippingPlanes[static_cast<int>(dev)] = vtkPlane::New();
525   }
526 
527   vtkActorCollection* ac;
528   vtkActor *anActor, *aPart;
529   vtkAssemblyPath* path;
530   if (this->CurrentRenderer != nullptr)
531   {
532     ac = this->CurrentRenderer->GetActors();
533     vtkCollectionSimpleIterator ait;
534     for (ac->InitTraversal(ait); (anActor = ac->GetNextActor(ait));)
535     {
536       for (anActor->InitPathTraversal(); (path = anActor->GetNextPath());)
537       {
538         aPart = static_cast<vtkActor*>(path->GetLastNode()->GetViewProp());
539         if (aPart->GetMapper())
540         {
541           aPart->GetMapper()->AddClippingPlane(this->ClippingPlanes[static_cast<int>(dev)]);
542           continue;
543         }
544       }
545     }
546   }
547   else
548   {
549     vtkWarningMacro(<< "no current renderer on the interactor style.");
550   }
551 }
552 
553 //------------------------------------------------------------------------------
EndClip(vtkEventDataDevice3D * ed)554 void vtkOpenVRInteractorStyle::EndClip(vtkEventDataDevice3D* ed)
555 {
556   vtkEventDataDevice dev = ed->GetDevice();
557   this->InteractionState[static_cast<int>(dev)] = VTKIS_NONE;
558 
559   vtkActorCollection* ac;
560   vtkActor *anActor, *aPart;
561   vtkAssemblyPath* path;
562   if (this->CurrentRenderer != nullptr)
563   {
564     ac = this->CurrentRenderer->GetActors();
565     vtkCollectionSimpleIterator ait;
566     for (ac->InitTraversal(ait); (anActor = ac->GetNextActor(ait));)
567     {
568       for (anActor->InitPathTraversal(); (path = anActor->GetNextPath());)
569       {
570         aPart = static_cast<vtkActor*>(path->GetLastNode()->GetViewProp());
571         if (aPart->GetMapper())
572         {
573           aPart->GetMapper()->RemoveClippingPlane(this->ClippingPlanes[static_cast<int>(dev)]);
574           continue;
575         }
576       }
577     }
578   }
579   else
580   {
581     vtkWarningMacro(<< "no current renderer on the interactor style.");
582   }
583 }
584 
585 //------------------------------------------------------------------------------
StartDolly3D(vtkEventDataDevice3D * ed)586 void vtkOpenVRInteractorStyle::StartDolly3D(vtkEventDataDevice3D* ed)
587 {
588   if (this->CurrentRenderer == nullptr)
589   {
590     return;
591   }
592   vtkEventDataDevice dev = ed->GetDevice();
593   this->InteractionState[static_cast<int>(dev)] = VTKIS_DOLLY;
594   this->LastDolly3DEventTime->StartTimer();
595 
596   // this->GrabFocus(this->EventCallbackCommand);
597 }
598 //------------------------------------------------------------------------------
EndDolly3D(vtkEventDataDevice3D * ed)599 void vtkOpenVRInteractorStyle::EndDolly3D(vtkEventDataDevice3D* ed)
600 {
601   vtkEventDataDevice dev = ed->GetDevice();
602   this->InteractionState[static_cast<int>(dev)] = VTKIS_NONE;
603 
604   this->LastDolly3DEventTime->StopTimer();
605 }
606 
607 //------------------------------------------------------------------------------
ToggleDrawControls()608 void vtkOpenVRInteractorStyle::ToggleDrawControls()
609 {
610   if (this->CurrentRenderer == nullptr)
611   {
612     return;
613   }
614 
615   // Enable helpers
616   for (int d = 0; d < vtkEventDataNumberOfDevices; ++d)
617   {
618     // No helper for HMD
619     if (static_cast<vtkEventDataDevice>(d) == vtkEventDataDevice::HeadMountedDisplay)
620     {
621       continue;
622     }
623 
624     for (int i = 0; i < vtkEventDataNumberOfInputs; i++)
625     {
626       if (this->ControlsHelpers[d][i])
627       {
628         if (this->ControlsHelpers[d][i]->GetRenderer() != this->CurrentRenderer)
629         {
630           vtkRenderer* ren = this->ControlsHelpers[d][i]->GetRenderer();
631           if (ren)
632           {
633             ren->RemoveViewProp(this->ControlsHelpers[d][i]);
634           }
635           this->ControlsHelpers[d][i]->SetRenderer(this->CurrentRenderer);
636           this->ControlsHelpers[d][i]->BuildRepresentation();
637           // this->ControlsHelpers[iDevice][iInput]->SetEnabled(false);
638           this->CurrentRenderer->AddViewProp(this->ControlsHelpers[d][i]);
639         }
640 
641         this->ControlsHelpers[d][i]->SetEnabled(!this->ControlsHelpers[d][i]->GetEnabled());
642       }
643     }
644   }
645 }
646 
SetDrawControls(bool val)647 void vtkOpenVRInteractorStyle::SetDrawControls(bool val)
648 {
649   if (this->CurrentRenderer == nullptr)
650   {
651     return;
652   }
653 
654   // Enable helpers
655   for (int d = 0; d < vtkEventDataNumberOfDevices; ++d)
656   {
657     // No helper for HMD
658     if (static_cast<vtkEventDataDevice>(d) == vtkEventDataDevice::HeadMountedDisplay)
659     {
660       continue;
661     }
662 
663     for (int i = 0; i < vtkEventDataNumberOfInputs; i++)
664     {
665       if (this->ControlsHelpers[d][i])
666       {
667         if (this->ControlsHelpers[d][i]->GetRenderer() != this->CurrentRenderer)
668         {
669           vtkRenderer* ren = this->ControlsHelpers[d][i]->GetRenderer();
670           if (ren)
671           {
672             ren->RemoveViewProp(this->ControlsHelpers[d][i]);
673           }
674           this->ControlsHelpers[d][i]->SetRenderer(this->CurrentRenderer);
675           this->ControlsHelpers[d][i]->BuildRepresentation();
676           // this->ControlsHelpers[iDevice][iInput]->SetEnabled(false);
677           this->CurrentRenderer->AddViewProp(this->ControlsHelpers[d][i]);
678         }
679 
680         this->ControlsHelpers[d][i]->SetEnabled(val);
681       }
682     }
683   }
684 }
685 
686 //------------------------------------------------------------------------------
687 // Interaction methods
688 //------------------------------------------------------------------------------
ProbeData(vtkEventDataDevice controller)689 void vtkOpenVRInteractorStyle::ProbeData(vtkEventDataDevice controller)
690 {
691   // Invoke start pick method if defined
692   this->InvokeEvent(vtkCommand::StartPickEvent, nullptr);
693 
694   if (!this->HardwareSelect(controller, false))
695   {
696     return;
697   }
698 
699   // Invoke end pick method if defined
700   if (this->HandleObservers && this->HasObserver(vtkCommand::EndPickEvent))
701   {
702     this->InvokeEvent(vtkCommand::EndPickEvent, this->HardwarePicker->GetSelection());
703   }
704   else
705   {
706     this->EndPickCallback(this->HardwarePicker->GetSelection());
707   }
708 }
709 
EndPickCallback(vtkSelection * sel)710 void vtkOpenVRInteractorStyle::EndPickCallback(vtkSelection* sel)
711 {
712   if (!sel)
713   {
714     return;
715   }
716 
717   vtkSelectionNode* node = sel->GetNode(0);
718   if (!node || !node->GetProperties()->Has(vtkSelectionNode::PROP()))
719   {
720     return;
721   }
722 
723   vtkProp3D* prop = vtkProp3D::SafeDownCast(node->GetProperties()->Get(vtkSelectionNode::PROP()));
724   if (!prop)
725   {
726     return;
727   }
728   this->ShowPickSphere(prop->GetCenter(), prop->GetLength() / 2.0, nullptr);
729 }
730 
731 //------------------------------------------------------------------------------
LoadNextCameraPose()732 void vtkOpenVRInteractorStyle::LoadNextCameraPose()
733 {
734   vtkOpenVRRenderWindow* renWin =
735     vtkOpenVRRenderWindow::SafeDownCast(this->Interactor->GetRenderWindow());
736   if (!renWin)
737   {
738     return;
739   }
740   vtkOpenVROverlay* ovl = renWin->GetDashboardOverlay();
741   ovl->LoadNextCameraPose();
742 }
743 
744 //------------------------------------------------------------------------------
PositionProp(vtkEventData * ed,double * lwpos,double * lwori)745 void vtkOpenVRInteractorStyle::PositionProp(vtkEventData* ed, double* lwpos, double* lwori)
746 {
747   if (this->InteractionProp == nullptr || !this->InteractionProp->GetDragable())
748   {
749     return;
750   }
751   this->Superclass::PositionProp(ed, lwpos, lwori);
752 }
753 
754 //------------------------------------------------------------------------------
Clip(vtkEventDataDevice3D * ed)755 void vtkOpenVRInteractorStyle::Clip(vtkEventDataDevice3D* ed)
756 {
757   if (this->CurrentRenderer == nullptr)
758   {
759     return;
760   }
761 
762   const double* wpos = ed->GetWorldPosition();
763   const double* wori = ed->GetWorldOrientation();
764 
765   double ori[4];
766   ori[0] = vtkMath::RadiansFromDegrees(wori[0]);
767   ori[1] = wori[1];
768   ori[2] = wori[2];
769   ori[3] = wori[3];
770 
771   // we have a position and a normal, that defines our plane
772   // plane->SetOrigin(wpos[0], wpos[1], wpos[2]);
773 
774   double r[3];
775   double up[3];
776   up[0] = 0;
777   up[1] = -1;
778   up[2] = 0;
779   vtkMath::RotateVectorByWXYZ(up, ori, r);
780   // plane->SetNormal(r);
781 
782   vtkEventDataDevice dev = ed->GetDevice();
783   int idev = static_cast<int>(dev);
784   this->ClippingPlanes[idev]->SetNormal(r);
785   this->ClippingPlanes[idev]->SetOrigin(wpos[0], wpos[1], wpos[2]);
786 }
787 
788 //------------------------------------------------------------------------------
789 
790 //------------------------------------------------------------------------------
791 // Multitouch interaction methods
792 //------------------------------------------------------------------------------
OnPan()793 void vtkOpenVRInteractorStyle::OnPan()
794 {
795   int rc = static_cast<int>(vtkEventDataDevice::RightController);
796   int lc = static_cast<int>(vtkEventDataDevice::LeftController);
797 
798   if (!this->InteractionProps[rc] && !this->InteractionProps[lc])
799   {
800     this->InteractionState[rc] = VTKIS_PAN;
801     this->InteractionState[lc] = VTKIS_PAN;
802 
803     int pointer = this->Interactor->GetPointerIndex();
804 
805     this->FindPokedRenderer(this->Interactor->GetEventPositions(pointer)[0],
806       this->Interactor->GetEventPositions(pointer)[1]);
807 
808     if (this->CurrentRenderer == nullptr)
809     {
810       return;
811     }
812 
813     vtkCamera* camera = this->CurrentRenderer->GetActiveCamera();
814     vtkRenderWindowInteractor3D* rwi = static_cast<vtkRenderWindowInteractor3D*>(this->Interactor);
815 
816     double t[3] = { rwi->GetTranslation3D()[0] - rwi->GetLastTranslation3D()[0],
817       rwi->GetTranslation3D()[1] - rwi->GetLastTranslation3D()[1],
818       rwi->GetTranslation3D()[2] - rwi->GetLastTranslation3D()[2] };
819 
820     double* ptrans = rwi->GetPhysicalTranslation(camera);
821 
822     rwi->SetPhysicalTranslation(camera, ptrans[0] + t[0], ptrans[1] + t[1], ptrans[2] + t[2]);
823 
824     // clean up
825     if (this->Interactor->GetLightFollowCamera())
826     {
827       this->CurrentRenderer->UpdateLightsGeometryToFollowCamera();
828     }
829   }
830 }
831 //------------------------------------------------------------------------------
OnPinch()832 void vtkOpenVRInteractorStyle::OnPinch()
833 {
834   int rc = static_cast<int>(vtkEventDataDevice::RightController);
835   int lc = static_cast<int>(vtkEventDataDevice::LeftController);
836 
837   if (!this->InteractionProps[rc] && !this->InteractionProps[lc])
838   {
839     this->InteractionState[rc] = VTKIS_ZOOM;
840     this->InteractionState[lc] = VTKIS_ZOOM;
841 
842     int pointer = this->Interactor->GetPointerIndex();
843 
844     this->FindPokedRenderer(this->Interactor->GetEventPositions(pointer)[0],
845       this->Interactor->GetEventPositions(pointer)[1]);
846 
847     if (this->CurrentRenderer == nullptr)
848     {
849       return;
850     }
851 
852     double dyf = this->Interactor->GetScale() / this->Interactor->GetLastScale();
853     vtkCamera* camera = this->CurrentRenderer->GetActiveCamera();
854     vtkRenderWindowInteractor3D* rwi = static_cast<vtkRenderWindowInteractor3D*>(this->Interactor);
855     double physicalScale = rwi->GetPhysicalScale();
856 
857     this->SetScale(camera, physicalScale / dyf);
858   }
859 }
860 //------------------------------------------------------------------------------
OnRotate()861 void vtkOpenVRInteractorStyle::OnRotate()
862 {
863   int rc = static_cast<int>(vtkEventDataDevice::RightController);
864   int lc = static_cast<int>(vtkEventDataDevice::LeftController);
865 
866   // Rotate only when one controller is not interacting
867   if (!this->InteractionProps[rc] && !this->InteractionProps[lc])
868   {
869     this->InteractionState[rc] = VTKIS_ROTATE;
870     this->InteractionState[lc] = VTKIS_ROTATE;
871 
872     double angle = this->Interactor->GetRotation() - this->Interactor->GetLastRotation();
873     if (fabs(angle) > 90)
874     {
875       // return;
876     }
877 
878     // rotate the world, aka rotate the physicalViewDirection about the physicalViewUp
879     vtkOpenVRRenderWindow* renWin =
880       vtkOpenVRRenderWindow::SafeDownCast(this->Interactor->GetRenderWindow());
881     if (!renWin)
882     {
883       return;
884     }
885 
886     double* vup = renWin->GetPhysicalViewUp();
887     double* dop = renWin->GetPhysicalViewDirection();
888     double newDOP[3];
889     double wxyz[4];
890     wxyz[0] = vtkMath::RadiansFromDegrees(angle);
891     wxyz[1] = vup[0];
892     wxyz[2] = vup[1];
893     wxyz[3] = vup[2];
894     vtkMath::RotateVectorByWXYZ(dop, wxyz, newDOP);
895     renWin->SetPhysicalViewDirection(newDOP);
896   }
897 }
898 //------------------------------------------------------------------------------
899 
900 //------------------------------------------------------------------------------
901 // Utility routines
902 //------------------------------------------------------------------------------
MapInputToAction(vtkCommand::EventIds eid,vtkEventDataAction action,int state)903 void vtkOpenVRInteractorStyle::MapInputToAction(
904   vtkCommand::EventIds eid, vtkEventDataAction action, int state)
905 {
906   if (state < VTKIS_NONE)
907   {
908     return;
909   }
910 
911   decltype(this->InputMap)::key_type key(eid, action);
912   auto it = this->InputMap.find(key);
913   if (it != this->InputMap.end())
914   {
915     if (it->second == state)
916     {
917       return;
918     }
919   }
920 
921   this->InputMap[key] = state;
922 
923   this->Modified();
924 }
925 
MapInputToAction(vtkCommand::EventIds eid,int state)926 void vtkOpenVRInteractorStyle::MapInputToAction(vtkCommand::EventIds eid, int state)
927 {
928   this->MapInputToAction(eid, vtkEventDataAction::Press, state);
929   this->MapInputToAction(eid, vtkEventDataAction::Release, state);
930 }
931 
932 //------------------------------------------------------------------------------
StartAction(int state,vtkEventDataDevice3D * edata)933 void vtkOpenVRInteractorStyle::StartAction(int state, vtkEventDataDevice3D* edata)
934 {
935   switch (state)
936   {
937     case VTKIS_POSITION_PROP:
938       this->StartPositionProp(edata);
939       break;
940     case VTKIS_DOLLY:
941       this->StartDolly3D(edata);
942       break;
943     case VTKIS_CLIP:
944       this->StartClip(edata);
945       break;
946     case VTKIS_PICK:
947       this->StartPick(edata);
948       break;
949     case VTKIS_LOAD_CAMERA_POSE:
950       this->StartLoadCamPose(edata);
951       break;
952   }
953 }
954 //------------------------------------------------------------------------------
EndAction(int state,vtkEventDataDevice3D * edata)955 void vtkOpenVRInteractorStyle::EndAction(int state, vtkEventDataDevice3D* edata)
956 {
957   switch (state)
958   {
959     case VTKIS_POSITION_PROP:
960       this->EndPositionProp(edata);
961       break;
962     case VTKIS_DOLLY:
963       this->EndDolly3D(edata);
964       break;
965     case VTKIS_CLIP:
966       this->EndClip(edata);
967       break;
968     case VTKIS_PICK:
969       this->EndPick(edata);
970       break;
971     case VTKIS_MENU:
972       this->Menu->SetInteractor(this->Interactor);
973       this->Menu->Show(edata);
974       break;
975     case VTKIS_LOAD_CAMERA_POSE:
976       this->EndLoadCamPose(edata);
977       break;
978     case VTKIS_TOGGLE_DRAW_CONTROLS:
979       this->ToggleDrawControls();
980       break;
981     case VTKIS_EXIT:
982       if (this->Interactor)
983       {
984         this->Interactor->ExitCallback();
985       }
986       break;
987   }
988 
989   // Reset multitouch state because a button has been released
990   for (int d = 0; d < vtkEventDataNumberOfDevices; ++d)
991   {
992     switch (this->InteractionState[d])
993     {
994       case VTKIS_PAN:
995       case VTKIS_ZOOM:
996       case VTKIS_ROTATE:
997         this->InteractionState[d] = VTKIS_NONE;
998         break;
999     }
1000   }
1001 }
1002 //------------------------------------------------------------------------------
1003 
1004 //------------------------------------------------------------------------------
1005 // Handle Ray drawing and update
1006 //------------------------------------------------------------------------------
ShowRay(vtkEventDataDevice controller)1007 void vtkOpenVRInteractorStyle::ShowRay(vtkEventDataDevice controller)
1008 {
1009   vtkOpenVRRenderWindow* renWin =
1010     vtkOpenVRRenderWindow::SafeDownCast(this->Interactor->GetRenderWindow());
1011   if (!renWin ||
1012     (controller != vtkEventDataDevice::LeftController &&
1013       controller != vtkEventDataDevice::RightController))
1014   {
1015     return;
1016   }
1017   vtkVRModel* cmodel = renWin->GetTrackedDeviceModel(controller);
1018   if (cmodel)
1019   {
1020     cmodel->SetShowRay(true);
1021   }
1022 }
1023 //------------------------------------------------------------------------------
HideRay(vtkEventDataDevice controller)1024 void vtkOpenVRInteractorStyle::HideRay(vtkEventDataDevice controller)
1025 {
1026   vtkOpenVRRenderWindow* renWin =
1027     vtkOpenVRRenderWindow::SafeDownCast(this->Interactor->GetRenderWindow());
1028   if (!renWin ||
1029     (controller != vtkEventDataDevice::LeftController &&
1030       controller != vtkEventDataDevice::RightController))
1031   {
1032     return;
1033   }
1034   vtkVRModel* cmodel = renWin->GetTrackedDeviceModel(controller);
1035   if (cmodel)
1036   {
1037     cmodel->SetShowRay(false);
1038   }
1039 }
1040 //------------------------------------------------------------------------------
UpdateRay(vtkEventDataDevice controller)1041 void vtkOpenVRInteractorStyle::UpdateRay(vtkEventDataDevice controller)
1042 {
1043   if (!this->Interactor)
1044   {
1045     return;
1046   }
1047 
1048   vtkRenderer* ren = this->CurrentRenderer;
1049   vtkOpenVRRenderWindow* renWin =
1050     vtkOpenVRRenderWindow::SafeDownCast(this->Interactor->GetRenderWindow());
1051   vtkOpenVRRenderWindowInteractor* iren =
1052     static_cast<vtkOpenVRRenderWindowInteractor*>(this->Interactor);
1053 
1054   if (!ren || !renWin || !iren)
1055   {
1056     return;
1057   }
1058 
1059   vr::TrackedDeviceIndex_t idx = renWin->GetTrackedDeviceIndexForDevice(controller);
1060   if (idx == vr::k_unTrackedDeviceIndexInvalid)
1061   {
1062     return;
1063   }
1064   vtkOpenVRModel* mod = vtkOpenVRModel::SafeDownCast(renWin->GetTrackedDeviceModel(idx));
1065   if (!mod)
1066   {
1067     return;
1068   }
1069 
1070   int idev = static_cast<int>(controller);
1071 
1072   // Keep the same ray if a controller is interacting with a prop
1073   if (this->InteractionProps[idev] != nullptr)
1074   {
1075     return;
1076   }
1077 
1078   // Check if interacting with a widget
1079   vtkPropCollection* props = ren->GetViewProps();
1080 
1081   vtkIdType nbProps = props->GetNumberOfItems();
1082   for (vtkIdType i = 0; i < nbProps; i++)
1083   {
1084     vtkWidgetRepresentation* rep = vtkWidgetRepresentation::SafeDownCast(props->GetItemAsObject(i));
1085 
1086     if (rep && rep->IsA("vtkQWidgetRepresentation") && rep->GetInteractionState() != 0)
1087     {
1088       mod->SetShowRay(true);
1089       mod->SetRayLength(ren->GetActiveCamera()->GetClippingRange()[1]);
1090       mod->SetRayColor(0.0, 0.0, 1.0);
1091       return;
1092     }
1093   }
1094 
1095   if (this->GetGrabWithRay() || this->InteractionState[idev] == VTKIS_PICK)
1096   {
1097     mod->SetShowRay(true);
1098   }
1099   else
1100   {
1101     mod->SetShowRay(false);
1102     return;
1103   }
1104 
1105   // Set length to its max if interactive picking is off
1106   if (!this->HoverPick)
1107   {
1108     mod->SetRayColor(1.0, 0.0, 0.0);
1109     mod->SetRayLength(ren->GetActiveCamera()->GetClippingRange()[1]);
1110     return;
1111   }
1112 
1113   // Compute controller position and world orientation
1114   double p0[3];   // Ray start point
1115   double wxyz[4]; // Controller orientation
1116   double dummy_ppos[3];
1117   double wdir[3];
1118   vr::TrackedDevicePose_t* tdPose = renWin->GetTrackedDevicePose(mod->TrackedDevice);
1119   iren->ConvertPoseToWorldCoordinates(*tdPose, p0, wxyz, dummy_ppos, wdir);
1120 
1121   // Compute ray length.
1122   this->InteractionPicker->Pick3DRay(p0, wxyz, ren);
1123 
1124   // If something is picked, set the length accordingly
1125   vtkProp3D* prop = this->InteractionPicker->GetProp3D();
1126   if (prop)
1127   {
1128     double p1[3];
1129     this->InteractionPicker->GetPickPosition(p1);
1130     mod->SetRayLength(sqrt(vtkMath::Distance2BetweenPoints(p0, p1)));
1131     mod->SetRayColor(0.0, 1.0, 0.0);
1132   }
1133   // Otherwise set the length to its max
1134   else
1135   {
1136     mod->SetRayLength(ren->GetActiveCamera()->GetClippingRange()[1]);
1137     mod->SetRayColor(1.0, 0.0, 0.0);
1138   }
1139 }
1140 //------------------------------------------------------------------------------
1141 
ShowBillboard(const std::string & text)1142 void vtkOpenVRInteractorStyle::ShowBillboard(const std::string& text)
1143 {
1144   vtkOpenVRRenderWindow* renWin =
1145     vtkOpenVRRenderWindow::SafeDownCast(this->Interactor->GetRenderWindow());
1146   vtkRenderer* ren = this->CurrentRenderer;
1147   if (!renWin || !ren)
1148   {
1149     return;
1150   }
1151 
1152   renWin->UpdateHMDMatrixPose();
1153   double dop[3];
1154   ren->GetActiveCamera()->GetDirectionOfProjection(dop);
1155   double vr[3];
1156   double* vup = renWin->GetPhysicalViewUp();
1157   double dtmp[3];
1158   double vupdot = vtkMath::Dot(dop, vup);
1159   if (fabs(vupdot) < 0.999)
1160   {
1161     dtmp[0] = dop[0] - vup[0] * vupdot;
1162     dtmp[1] = dop[1] - vup[1] * vupdot;
1163     dtmp[2] = dop[2] - vup[2] * vupdot;
1164     vtkMath::Normalize(dtmp);
1165   }
1166   else
1167   {
1168     renWin->GetPhysicalViewDirection(dtmp);
1169   }
1170   vtkMath::Cross(dtmp, vup, vr);
1171   vtkNew<vtkMatrix4x4> rot;
1172   for (int i = 0; i < 3; ++i)
1173   {
1174     rot->SetElement(0, i, vr[i]);
1175     rot->SetElement(1, i, vup[i]);
1176     rot->SetElement(2, i, -dtmp[i]);
1177   }
1178   rot->Transpose();
1179   double orient[3];
1180   vtkTransform::GetOrientation(orient, rot);
1181   vtkTextProperty* prop = this->TextActor3D->GetTextProperty();
1182   this->TextActor3D->SetOrientation(orient);
1183   this->TextActor3D->RotateX(-30.0);
1184 
1185   double tpos[3];
1186   double scale = renWin->GetPhysicalScale();
1187   ren->GetActiveCamera()->GetPosition(tpos);
1188   tpos[0] += (0.7 * scale * dop[0] - 0.1 * scale * vr[0] - 0.4 * scale * vup[0]);
1189   tpos[1] += (0.7 * scale * dop[1] - 0.1 * scale * vr[1] - 0.4 * scale * vup[1]);
1190   tpos[2] += (0.7 * scale * dop[2] - 0.1 * scale * vr[2] - 0.4 * scale * vup[2]);
1191   this->TextActor3D->SetPosition(tpos);
1192   // scale should cover 10% of FOV
1193   double fov = ren->GetActiveCamera()->GetViewAngle();
1194   double tsize = 0.1 * 2.0 * atan(fov * 0.5); // 10% of fov
1195   tsize /= 200.0;                             // about 200 pixel texture map
1196   scale *= tsize;
1197   this->TextActor3D->SetScale(scale, scale, scale);
1198   this->TextActor3D->SetInput(text.c_str());
1199   this->CurrentRenderer->AddActor(this->TextActor3D);
1200 
1201   prop->SetFrame(1);
1202   prop->SetFrameColor(1.0, 1.0, 1.0);
1203   prop->SetBackgroundOpacity(1.0);
1204   prop->SetBackgroundColor(0.0, 0.0, 0.0);
1205   prop->SetFontSize(14);
1206 }
1207 
HideBillboard()1208 void vtkOpenVRInteractorStyle::HideBillboard()
1209 {
1210   this->CurrentRenderer->RemoveActor(this->TextActor3D);
1211 }
1212 
ShowPickSphere(double * pos,double radius,vtkProp3D * prop)1213 void vtkOpenVRInteractorStyle::ShowPickSphere(double* pos, double radius, vtkProp3D* prop)
1214 {
1215   this->PickActor->GetProperty()->SetColor(this->PickColor);
1216 
1217   this->Sphere->SetCenter(pos);
1218   this->Sphere->SetRadius(radius);
1219   this->PickActor->GetMapper()->SetInputConnection(this->Sphere->GetOutputPort());
1220   if (prop)
1221   {
1222     this->PickActor->SetPosition(prop->GetPosition());
1223     this->PickActor->SetScale(prop->GetScale());
1224   }
1225   else
1226   {
1227     this->PickActor->SetPosition(0.0, 0.0, 0.0);
1228     this->PickActor->SetScale(1.0, 1.0, 1.0);
1229   }
1230   this->CurrentRenderer->AddActor(this->PickActor);
1231 }
1232 
ShowPickCell(vtkCell * cell,vtkProp3D * prop)1233 void vtkOpenVRInteractorStyle::ShowPickCell(vtkCell* cell, vtkProp3D* prop)
1234 {
1235   vtkNew<vtkPolyData> pd;
1236   vtkNew<vtkPoints> pdpts;
1237   pdpts->SetDataTypeToDouble();
1238   vtkNew<vtkCellArray> lines;
1239 
1240   this->PickActor->GetProperty()->SetColor(this->PickColor);
1241 
1242   int nedges = cell->GetNumberOfEdges();
1243 
1244   if (nedges)
1245   {
1246     for (int edgenum = 0; edgenum < nedges; ++edgenum)
1247     {
1248       vtkCell* edge = cell->GetEdge(edgenum);
1249       vtkPoints* pts = edge->GetPoints();
1250       int npts = edge->GetNumberOfPoints();
1251       lines->InsertNextCell(npts);
1252       for (int ep = 0; ep < npts; ++ep)
1253       {
1254         vtkIdType newpt = pdpts->InsertNextPoint(pts->GetPoint(ep));
1255         lines->InsertCellPoint(newpt);
1256       }
1257     }
1258   }
1259   else if (cell->GetCellType() == VTK_LINE || cell->GetCellType() == VTK_POLY_LINE)
1260   {
1261     vtkPoints* pts = cell->GetPoints();
1262     int npts = cell->GetNumberOfPoints();
1263     lines->InsertNextCell(npts);
1264     for (int ep = 0; ep < npts; ++ep)
1265     {
1266       vtkIdType newpt = pdpts->InsertNextPoint(pts->GetPoint(ep));
1267       lines->InsertCellPoint(newpt);
1268     }
1269   }
1270   else
1271   {
1272     return;
1273   }
1274 
1275   pd->SetPoints(pdpts.Get());
1276   pd->SetLines(lines.Get());
1277 
1278   if (prop)
1279   {
1280     this->PickActor->SetPosition(prop->GetPosition());
1281     this->PickActor->SetScale(prop->GetScale());
1282     this->PickActor->SetUserMatrix(prop->GetUserMatrix());
1283   }
1284   else
1285   {
1286     this->PickActor->SetPosition(0.0, 0.0, 0.0);
1287     this->PickActor->SetScale(1.0, 1.0, 1.0);
1288   }
1289   this->PickActor->SetOrientation(prop->GetOrientation());
1290   static_cast<vtkPolyDataMapper*>(this->PickActor->GetMapper())->SetInputData(pd);
1291   this->CurrentRenderer->AddActor(this->PickActor);
1292 }
1293 
HidePickActor()1294 void vtkOpenVRInteractorStyle::HidePickActor()
1295 {
1296   if (this->CurrentRenderer)
1297   {
1298     this->CurrentRenderer->RemoveActor(this->PickActor);
1299   }
1300 }
1301 
1302 //------------------------------------------------------------------------------
AddTooltipForInput(vtkEventDataDevice device,vtkEventDataDeviceInput input)1303 void vtkOpenVRInteractorStyle::AddTooltipForInput(
1304   vtkEventDataDevice device, vtkEventDataDeviceInput input)
1305 {
1306   this->AddTooltipForInput(device, input, "");
1307 }
1308 
1309 //------------------------------------------------------------------------------
AddTooltipForInput(vtkEventDataDevice device,vtkEventDataDeviceInput input,const std::string & text)1310 void vtkOpenVRInteractorStyle::AddTooltipForInput(
1311   vtkEventDataDevice device, vtkEventDataDeviceInput input, const std::string& text)
1312 {
1313   int iInput = static_cast<int>(input);
1314   int iDevice = static_cast<int>(device);
1315 
1316   vtkStdString controlName = vtkStdString();
1317   vtkStdString controlText = vtkStdString();
1318   int drawSide = -1;
1319   int buttonSide = -1;
1320 
1321   // Setup default text and layout
1322   switch (input)
1323   {
1324     case vtkEventDataDeviceInput::Trigger:
1325       controlName = "trigger";
1326       drawSide = vtkOpenVRControlsHelper::Left;
1327       buttonSide = vtkOpenVRControlsHelper::Back;
1328       controlText = "Trigger :\n";
1329       break;
1330     case vtkEventDataDeviceInput::TrackPad:
1331       controlName = "trackpad";
1332       drawSide = vtkOpenVRControlsHelper::Right;
1333       buttonSide = vtkOpenVRControlsHelper::Front;
1334       controlText = "Trackpad :\n";
1335       break;
1336     case vtkEventDataDeviceInput::Grip:
1337       controlName = "lgrip";
1338       drawSide = vtkOpenVRControlsHelper::Right;
1339       buttonSide = vtkOpenVRControlsHelper::Back;
1340       controlText = "Grip :\n";
1341       break;
1342     case vtkEventDataDeviceInput::ApplicationMenu:
1343       controlName = "button";
1344       drawSide = vtkOpenVRControlsHelper::Left;
1345       buttonSide = vtkOpenVRControlsHelper::Front;
1346       controlText = "Application Menu :\n";
1347       break;
1348   }
1349 
1350   controlText += text;
1351 
1352   // Clean already existing helpers
1353   if (this->ControlsHelpers[iDevice][iInput] != nullptr)
1354   {
1355     if (this->CurrentRenderer)
1356     {
1357       this->CurrentRenderer->RemoveViewProp(this->ControlsHelpers[iDevice][iInput]);
1358     }
1359     this->ControlsHelpers[iDevice][iInput]->Delete();
1360     this->ControlsHelpers[iDevice][iInput] = nullptr;
1361   }
1362 
1363   // Create an input helper and add it to the renderer
1364   vtkOpenVRControlsHelper* inputHelper = vtkOpenVRControlsHelper::New();
1365   inputHelper->SetTooltipInfo(controlName.c_str(), buttonSide, drawSide, controlText.c_str());
1366 
1367   this->ControlsHelpers[iDevice][iInput] = inputHelper;
1368   this->ControlsHelpers[iDevice][iInput]->SetDevice(device);
1369 
1370   if (this->CurrentRenderer)
1371   {
1372     this->ControlsHelpers[iDevice][iInput]->SetRenderer(this->CurrentRenderer);
1373     this->ControlsHelpers[iDevice][iInput]->BuildRepresentation();
1374     // this->ControlsHelpers[iDevice][iInput]->SetEnabled(false);
1375     this->CurrentRenderer->AddViewProp(this->ControlsHelpers[iDevice][iInput]);
1376   }
1377 }
1378