// SPDX-FileCopyrightText: Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen // SPDX-License-Identifier: BSD-3-Clause /** * @class vtkOpenVRRenderWindow * @brief OpenVR rendering window * * * vtkOpenVRRenderWindow is a concrete implementation of the abstract * class vtkVRRenderWindow. vtkOpenVRRenderer interfaces to the * OpenVR graphics library * * This class handles the bulk of interfacing to OpenVR. It supports one * renderer currently. The renderer is assumed to cover the entire window * which is what makes sense to VR. Overlay renderers can probably be * made to work with this but consider how overlays will appear in a * HMD if they do not track the viewpoint etc. This class is based on * sample code from the OpenVR project. * * OpenVR provides HMD and controller positions in "Physical" coordinate * system. * Origin: user's eye position at the time of calibration. * Axis directions: x = user's right; y = user's up; z = user's back. * Unit: meter. * * Renderer shows actors in World coordinate system. Transformation between * Physical and World coordinate systems is defined by PhysicalToWorldMatrix. * This matrix determines the user's position and orientation in the rendered * scene and scaling (magnification) of rendered actors. * */ #ifndef vtkOpenVRRenderWindow_h #define vtkOpenVRRenderWindow_h #include "vtkEventData.h" // for enums #include "vtkOpenVROverlay.h" // used for ivars #include "vtkRenderingOpenVRModule.h" // For export macro #include "vtkSmartPointer.h" // used for ivars #include "vtkVRRenderWindow.h" #include // for ivars VTK_ABI_NAMESPACE_BEGIN class vtkMatrix4x4; class vtkOpenVRModel; class VTKRENDERINGOPENVR_EXPORT vtkOpenVRRenderWindow : public vtkVRRenderWindow { public: static vtkOpenVRRenderWindow* New(); vtkTypeMacro(vtkOpenVRRenderWindow, vtkVRRenderWindow); /** * Returns true if the system believes that an HMD is present on the system. */ static bool IsHMDPresent(); /** * Initialize the rendering window. */ void Initialize() override; /** * Finalize the rendering window. This will shutdown all system-specific * resources. After having called this, it should be possible to destroy * a window that was used for a SetWindowId() call without any ill effects. */ void Finalize() override; /** * Get the system pointer */ vr::IVRSystem* GetHMD() { return this->HMD; } /** * Create an interactor specific to OpenVR to control renderers in this window. */ vtkRenderWindowInteractor* MakeRenderWindowInteractor() override; /** * Overridden to not release resources that would interfere with an external * application's rendering. Avoiding round trip. */ void Render() override; /** * Intermediate method performs operations required between the rendering * of the left and right eye. */ void StereoMidpoint() override; /** * Handles work required once both views have been rendered when using * stereo rendering. */ void StereoRenderComplete() override; /** * Draw the overlay */ void RenderOverlay(); /* * Get the overlay to use on the VR dashboard. */ vtkGetSmartPointerMacro(DashboardOverlay, vtkOpenVROverlay); /** * Update the HMD pose based on hardware pose and physical to world transform. * VR camera properties are directly modified based on physical to world to * simulate \sa PhysicalTranslation, \sa PhysicalScale, etc. */ void UpdateHMDMatrixPose() override; /** * Convert an OpenVR pose struct to a vtkMatrix4x4 object. */ void SetMatrixFromOpenVRPose(vtkMatrix4x4* result, const vr::TrackedDevicePose_t& vrPose); /** * Get the openVR Render Models */ vr::IVRRenderModels* GetOpenVRRenderModels() { return this->OpenVRRenderModels; } /** * Render the controller and base station models. */ void RenderModels() override; uint32_t GetDeviceHandleForOpenVRHandle(vr::TrackedDeviceIndex_t index); vtkEventDataDevice GetDeviceForOpenVRHandle(vr::TrackedDeviceIndex_t ohandle); ///@{ /** * Get the most recent OpenVR pose for a given device. index is used to * disambiguate when there are multiple device handles that map to a * device. */ void GetOpenVRPose(vtkEventDataDevice dev, vr::TrackedDevicePose_t** pose) { this->GetOpenVRPose(dev, 0, pose); } void GetOpenVRPose(vtkEventDataDevice dev, uint32_t index, vr::TrackedDevicePose_t** pose); ///@} protected: vtkOpenVRRenderWindow(); ~vtkOpenVRRenderWindow() override; std::string GetWindowTitleFromAPI() override; bool GetSizeFromAPI() override; bool CreateFramebuffers(uint32_t viewCount = 2) override; void RenderFramebuffer(FramebufferDesc& framebufferDesc) override; bool CreateOneFramebuffer(int nWidth, int nHeight, FramebufferDesc& framebufferDesc); /** * Convert a device index to a human-readable string. */ std::string GetTrackedDeviceString(vr::IVRSystem* pHmd, vr::TrackedDeviceIndex_t unDevice, vr::TrackedDeviceProperty prop, vr::TrackedPropertyError* peError = nullptr); /** * Find a render model that has already been loaded or load a new one. */ vtkOpenVRModel* FindOrLoadRenderModel(const char* modelName); vtkSmartPointer DashboardOverlay; vr::IVRSystem* HMD = nullptr; vr::IVRRenderModels* OpenVRRenderModels = nullptr; vr::TrackedDevicePose_t OpenVRTrackedDevicePoses[vr::k_unMaxTrackedDeviceCount]; private: vtkOpenVRRenderWindow(const vtkOpenVRRenderWindow&) = delete; void operator=(const vtkOpenVRRenderWindow&) = delete; }; VTK_ABI_NAMESPACE_END #endif