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