1 /*=========================================================================
2 
3 Program:   Visualization Toolkit
4 
5 Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen
6 All rights reserved.
7 See Copyright.txt or http://www.kitware.com/Copyright.htm for details.
8 
9 This software is distributed WITHOUT ANY WARRANTY; without even
10 the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
11 PURPOSE.  See the above copyright notice for more information.
12 
13 =========================================================================*/
14 /**
15  * @class   vtkOpenVRRenderWindow
16  * @brief   OpenVR rendering window
17  *
18  *
19  * vtkOpenVRRenderWindow is a concrete implementation of the abstract
20  * class vtkRenderWindow. vtkOpenVRRenderer interfaces to the
21  * OpenVR graphics library
22  *
23  * This class and its similar classes are designed to be drop in
24  * replacements for VTK. If you link to this module and turn on
25  * the CMake option VTK_OPENVR_OBJECT_FACTORY, the object
26  * factory mechanism should replace the core rendering classes such as
27  * RenderWindow with OpenVR specialized versions. The goal is for VTK
28  * programs to be able to use the OpenVR library with little to no
29  * changes.
30  *
31  * This class handles the bulk of interfacing to OpenVR. It supports one
32  * renderer currently. The renderer is assumed to cover the entire window
33  * which is what makes sense to VR. Overlay renderers can probably be
34  * made to work with this but consider how overlays will appear in a
35  * HMD if they do not track the viewpoint etc. This class is based on
36  * sample code from the OpenVR project.
37  *
38  * OpenVR provides HMD and controller positions in "Physical" coordinate
39  * system.
40  * Origin: user's eye position at the time of calibration.
41  * Axis directions: x = user's right; y = user's up; z = user's back.
42  * Unit: meter.
43  *
44  * Renderer shows actors in World coordinate system. Transformation between
45  * Physical and World coordinate systems is defined by PhysicalToWorldMatrix.
46  * This matrix determines the user's position and orientation in the rendered
47  * scene and scaling (magnification) of rendered actors.
48  *
49  */
50 
51 #ifndef vtkOpenVRRenderWindow_h
52 #define vtkOpenVRRenderWindow_h
53 
54 #include "vtkRenderingOpenVRModule.h" // For export macro
55 #include "vtkVRRenderWindow.h"
56 
57 #include "vtkEventData.h"    // for enums
58 #include "vtkOpenGLHelper.h" // used for ivars
59 #include "vtk_glew.h"        // used for methods
60 #include <openvr.h>          // for ivars
61 #include <vector>            // ivars
62 
63 class vtkCamera;
64 class vtkMatrix4x4;
65 class vtkOpenVRModel;
66 class vtkOpenVROverlay;
67 class vtkOpenGLVertexBufferObject;
68 class vtkTransform;
69 
70 class VTKRENDERINGOPENVR_EXPORT vtkOpenVRRenderWindow : public vtkVRRenderWindow
71 {
72 public:
73   static vtkOpenVRRenderWindow* New();
74   vtkTypeMacro(vtkOpenVRRenderWindow, vtkVRRenderWindow);
75 
76   void Initialize(void) override;
77 
78   void ReleaseGraphicsResources(vtkWindow* renWin) override;
79 
80   /**
81    * Get the system pointer
82    */
GetHMD()83   vr::IVRSystem* GetHMD() { return this->HMD; }
84 
85   static bool IsHMDPresent();
86 
87   /**
88    * Create an interactor to control renderers in this window.
89    * Creates one specific to OpenVR
90    */
91   vtkRenderWindowInteractor* MakeRenderWindowInteractor() override;
92 
93   void Render() override;
94 
95   /**
96    * Intermediate method performs operations required between the rendering
97    * of the left and right eye.
98    */
99   void StereoMidpoint() override;
100 
101   /**
102    * Handles work required once both views have been rendered when using
103    * stereo rendering.
104    */
105   void StereoRenderComplete() override;
106 
107   /**
108    * Draw the overlay
109    */
110   void RenderOverlay();
111 
112   ///@{
113   /*
114    * Set/Get the overlay to use on the VR dashboard
115    */
116   vtkGetObjectMacro(DashboardOverlay, vtkOpenVROverlay);
117   void SetDashboardOverlay(vtkOpenVROverlay*);
118   ///@}
119 
120   //@{
121   /**
122    * Set/Get the visibility of the base stations. Defaults to false
123    */
124   vtkGetMacro(BaseStationVisibility, bool);
125   vtkSetMacro(BaseStationVisibility, bool);
126   vtkBooleanMacro(BaseStationVisibility, bool);
127   //@}
128 
129   /**
130    * Update the HMD pose based on hardware pose and physical to world transform.
131    * VR camera properties are directly modified based on physical to world to
132    * simulate \sa PhysicalTranslation, \sa PhysicalScale, etc.
133    */
134   void UpdateHMDMatrixPose() override;
135 
136   using vtkVRRenderWindow::GetTrackedDeviceModel;
137 
138   /**
139    * Get the VRModel corresponding to the tracked device
140    */
141   vtkVRModel* GetTrackedDeviceModel(vtkEventDataDevice idx, uint32_t index) override;
142 
143   /**
144    * Get the openVR Render Models
145    */
GetOpenVRRenderModels()146   vr::IVRRenderModels* GetOpenVRRenderModels() { return this->OpenVRRenderModels; }
147 
148   /**
149    * Get the EventDataDevice corresponding to the OpenVR index
150    */
151   vtkEventDataDevice GetDeviceFromDeviceIndex(vr::TrackedDeviceIndex_t index);
152 
153   /**
154    * Get the index corresponding to the tracked device
155    */
GetTrackedDeviceIndexForDevice(vtkEventDataDevice dev)156   vr::TrackedDeviceIndex_t GetTrackedDeviceIndexForDevice(vtkEventDataDevice dev)
157   {
158     return this->GetTrackedDeviceIndexForDevice(dev, 0);
159   }
160   vr::TrackedDeviceIndex_t GetTrackedDeviceIndexForDevice(vtkEventDataDevice dev, uint32_t index);
161   uint32_t GetNumberOfTrackedDevicesForDevice(vtkEventDataDevice dev);
162 
163   /**
164    * Get the most recent pose corresponding to the tracked device
165    */
GetTrackedDevicePose(vtkEventDataDevice idx)166   vr::TrackedDevicePose_t* GetTrackedDevicePose(vtkEventDataDevice idx)
167   {
168     return this->GetTrackedDevicePose(idx, 0);
169   }
170   vr::TrackedDevicePose_t* GetTrackedDevicePose(vtkEventDataDevice idx, uint32_t index);
GetTrackedDevicePose(vr::TrackedDeviceIndex_t idx)171   vr::TrackedDevicePose_t& GetTrackedDevicePose(vr::TrackedDeviceIndex_t idx)
172   {
173     return this->TrackedDevicePose[idx];
174   }
175 
176   /**
177    * Render the controller and base station models
178    */
179   void RenderModels() override;
180 
181   bool GetPoseMatrixWorldFromDevice(
182     vtkEventDataDevice device, vtkMatrix4x4* poseMatrixWorld) override;
183 
184   void ConvertOpenVRPoseToMatrices(const vr::TrackedDevicePose_t& tdPose,
185     vtkMatrix4x4* poseMatrixWorld, vtkMatrix4x4* poseMatrixPhysical = nullptr);
186 
187 protected:
188   vtkOpenVRRenderWindow();
189   ~vtkOpenVRRenderWindow() override;
190 
191   std::string GetWindowTitleFromAPI() override;
192 
193   bool GetSizeFromAPI() override;
194 
195   bool BaseStationVisibility;
196 
197   vr::IVRSystem* HMD;
198   vr::IVRRenderModels* OpenVRRenderModels;
199 
200   bool CreateFramebuffers() override;
201 
202   bool CreateOneFramebuffer(int nWidth, int nHeight, FramebufferDesc& framebufferDesc);
203 
204   // convert a device index to a human string
205   std::string GetTrackedDeviceString(vr::IVRSystem* pHmd, vr::TrackedDeviceIndex_t unDevice,
206     vr::TrackedDeviceProperty prop, vr::TrackedPropertyError* peError = nullptr);
207 
208   // devices may have polygonal models
209   // load them
210   vtkOpenVRModel* FindOrLoadRenderModel(const char* modelName);
211 
212   vr::TrackedDevicePose_t TrackedDevicePose[vr::k_unMaxTrackedDeviceCount];
213 
214   vtkOpenVROverlay* DashboardOverlay;
215 
216 private:
217   vtkOpenVRRenderWindow(const vtkOpenVRRenderWindow&) = delete;
218   void operator=(const vtkOpenVRRenderWindow&) = delete;
219 };
220 
221 #endif
222