VTK  9.3.1
vtkOpenXRManager.h
Go to the documentation of this file.
1 // SPDX-FileCopyrightText: Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen
2 // SPDX-License-Identifier: BSD-3-Clause
13 #ifndef vtkOpenXRManager_h
14 #define vtkOpenXRManager_h
15 
16 #include "vtkRenderingOpenXRModule.h" // needed for exports
17 
18 #include "vtkNew.h"
19 #include "vtkOpenXR.h"
22 #include "vtkSmartPointer.h"
23 
24 #include <array>
25 #include <cstdint>
26 #include <memory>
27 #include <string>
28 #include <vector>
29 
30 VTK_ABI_NAMESPACE_BEGIN
32 
33 class VTKRENDERINGOPENXR_EXPORT vtkOpenXRManager
34 {
35 public:
37 
41  {
42  static vtkOpenXRManager UniqueInstance;
43  return UniqueInstance;
44  }
46 
48  {
49  DebugOutput = 0,
50  WarningOutput = 1,
51  ErrorOutput = 2
52  };
53 
55 
59  bool XrCheckOutput(OutputLevel level, const XrResult&, const std::string& message);
61 
63 
67  void PrintSystemProperties(XrSystemProperties* system_properties);
69  void PrintViewConfigViewInfo(const std::vector<XrViewConfigurationView>&);
72 
74 
81 
83 
86  void Finalize();
88 
90 
93  std::tuple<uint32_t, uint32_t> GetRecommendedImageRectSize();
95 
97 
102 
106  uint32_t GetViewCount()
107  {
108  return static_cast<uint32_t>(this->RenderResources->ConfigViews.size());
109  }
110 
112 
118 
120 
126  const XrPosef* GetViewPose(uint32_t eye)
127  {
128  if (eye >= this->GetViewCount())
129  {
130  return nullptr;
131  }
132  return &(this->RenderResources->Views[eye].pose);
133  }
135 
137 
142  const XrFovf* GetProjectionFov(uint32_t eye)
143  {
144  if (eye >= this->GetViewCount())
145  {
146  return nullptr;
147  }
148  return &(this->RenderResources->Views[eye].fov);
149  }
151 
153 
156  bool IsDepthExtensionSupported() { return this->OptionalExtensions.DepthExtensionSupported; }
158 
160 
165  bool GetShouldRenderCurrentFrame() { return this->ShouldRenderCurrentFrame; }
167 
169 
173  bool BeginSession();
175 
177 
180  const XrSession& GetSession() { return this->Session; }
182 
184 
187  const XrInstance& GetXrRuntimeInstance() { return this->Instance; }
189 
191 
195  bool IsSessionRunning() { return this->SessionRunning; }
197 
199 
206 
208 
214  bool PrepareRendering(uint32_t eye, void* colorTextureId, void* depthTextureId);
216 
218 
222  void ReleaseSwapchainImage(uint32_t eye);
224 
226 
230  bool EndFrame();
232 
234 
237  bool PollEvent(XrEventDataBuffer& eventData);
239 
241 
244  XrPath GetXrPath(const std::string& path);
246 
247  const std::array<XrPath, 2>& GetSubactionPaths() { return this->SubactionPaths; }
248 
250 
253  bool CreateActionSet(const std::string& actionSetName, const std::string& localizedActionSetName);
255 
257 
261  bool SelectActiveActionSet(unsigned int index);
263 
265 
270 
272 
277 
278  struct Action_t;
279 
281 
287  Action_t& actionT, const std::string& name, const std::string& localizedName);
289 
291 
295  const std::string& profile, std::vector<XrActionSuggestedBinding>& actionSuggestedBindings);
297 
299 
303  bool SyncActions();
305 
307 
314  bool UpdateActionData(Action_t& action_t, int hand);
316 
322  bool ApplyVibration(const Action_t& actionT, int hand, float amplitude = 0.5f,
323  float duration = 25000000.0f, float frequency = XR_FREQUENCY_UNSPECIFIED);
324 
326  {
327  Inactive = -1,
328  Left = 0,
329  Right = 1,
330  Head = 2,
331  Generic = 3,
332  NumberOfControllers = 4
333  };
334 
335  struct Action_t
336  {
337  XrAction Action;
338  XrActionType ActionType;
339 
340  union {
341  XrActionStateFloat _float;
342  XrActionStateBoolean _boolean;
343  XrActionStatePose _pose;
344  XrActionStateVector2f _vec2f;
345  } States[ControllerIndex::NumberOfControllers];
346 
347  XrSpace PoseSpaces[ControllerIndex::NumberOfControllers];
348  XrSpaceLocation PoseLocations[ControllerIndex::NumberOfControllers];
349  XrSpaceVelocity PoseVelocities[ControllerIndex::NumberOfControllers];
350  };
351 
353 
356  void SetGraphicsStrategy(vtkOpenXRManagerGraphics* gs) { this->GraphicsStrategy = gs; }
357  vtkOpenXRManagerGraphics* GetGraphicsStrategy() { return this->GraphicsStrategy; }
359 
361 
364  void SetConnectionStrategy(vtkOpenXRManagerConnection* cs) { this->ConnectionStrategy = cs; }
365  vtkOpenXRManagerConnection* GetConnectionStrategy() { return this->ConnectionStrategy; }
367 
368 protected:
370  ~vtkOpenXRManager() = default;
371 
373 
379  std::vector<const char*> SelectExtensions();
381 
383 
388 
390 
393  bool CreateSystem();
395 
397 
403 
405 
412 
414 
420 
422 
428 
430 
436  std::tuple<int64_t, int64_t> SelectSwapchainPixelFormats();
438 
439  struct Swapchain_t;
440 
442 
446  Swapchain_t CreateSwapchain(int64_t format, uint32_t width, uint32_t height, uint32_t sampleCount,
447  XrSwapchainCreateFlags createFlags, XrSwapchainUsageFlags usageFlags);
449 
451 
456 
458 
460 
463  bool CreateOneActionSpace(const XrAction& action, const XrPath& subactionPath,
464  const XrPosef& poseInActionSpace, XrSpace& space);
466 
468 
473 
475 
479  uint32_t WaitAndAcquireSwapchainImage(const XrSwapchain& swapchainHandle);
481 
482  // Currently VTK only supports HeadMountedDisplay (HMD)
483  constexpr static XrFormFactor FormFactor = XR_FORM_FACTOR_HEAD_MOUNTED_DISPLAY;
484 
485  // Pick the view type to be stereo rather than mono or anything else
486  constexpr static XrViewConfigurationType ViewType = XR_VIEW_CONFIGURATION_TYPE_PRIMARY_STEREO;
487 
488  // PRIMARY_STEREO view configuration always has 2 views
489  constexpr static uint32_t StereoViewCount = 2;
490 
491  // Three available types: VIEW, LOCAL and STAGE. We use LOCAL space which
492  // establishes a world-locked origin, rather than VIEW space, which tracks the
493  // view origin.
494  XrReferenceSpaceType ReferenceSpaceType = XR_REFERENCE_SPACE_TYPE_STAGE;
495 
496  // Communication with the runtime happens through this instance
497  XrInstance Instance;
498 
499  // A system is defined by an id and is used to create a session
500  XrSystemId SystemId;
501 
502  XrSession Session;
503  XrSessionState SessionState;
504  XrSpace ReferenceSpace;
505 
506  // At the end of a frame, we must select en environment blend mode
507  // to tell the runtime how we want to blend the image with the user's
508  // view of the physical world. For example, in VR, we will generally
509  // choose XR_ENVIRONMENT_BLEND_MODE_OPAQUE while AR will generally
510  // choose XR_ENVIRONMENT_BLEND_MODE_ADDITIVE or XR_ENVIRONMENT_BLEND_MODE_ALPHA_BLEND
511  XrEnvironmentBlendMode EnvironmentBlendMode;
512 
513  // Non optional extension
514  bool RenderingBackendExtensionSupported = false;
515 
517 
521  struct
522  {
523  bool DepthExtensionSupported{ false };
524  bool ControllerModelExtensionSupported{ false };
525  bool UnboundedRefSpaceSupported{ false };
526  bool SpatialAnchorSupported{ false };
527  bool HandInteractionSupported{ false };
528  bool HandTrackingSupported{ false };
529  bool RemotingSupported{ false };
530  } OptionalExtensions;
532 
537  struct Swapchain_t
538  {
539  XrSwapchain Swapchain;
540  int64_t Format{ 0 };
541  uint32_t Width{ 0 };
542  uint32_t Height{ 0 };
543  };
544 
546 
553  {
554  XrViewState ViewState{ XR_TYPE_VIEW_STATE };
555  // Each physical Display/Eye is described by a view
556  std::vector<XrView> Views;
557  // One configuration view per view : this store
558  std::vector<XrViewConfigurationView> ConfigViews;
559 
560  std::vector<Swapchain_t> ColorSwapchains;
561  std::vector<Swapchain_t> DepthSwapchains;
562 
563  std::vector<XrCompositionLayerProjectionView> ProjectionLayerViews;
564  std::vector<XrCompositionLayerDepthInfoKHR> DepthInfoViews;
565  };
566  std::unique_ptr<RenderResources_t> RenderResources{};
568 
569  // There is one subaction path for each hand.
570  std::array<XrPath, 2> SubactionPaths;
571 
572  std::vector<XrActionSet> ActionSets;
573  XrActionSet* ActiveActionSet = nullptr;
574 
580 
581  bool SessionRunning = false;
582  // After each WaitAndBeginFrame, the OpenXR runtime may inform us that
583  // the current frame should not be rendered. Store it to avoid a render
584  bool ShouldRenderCurrentFrame = false;
585  // If true, the function UpdateActionData will store
586  // pose velocities for pose actions
587  bool StorePoseVelocities = false;
588 
590 
592 
593 private:
594  vtkOpenXRManager(const vtkOpenXRManager&) = delete;
595  void operator=(const vtkOpenXRManager&) = delete;
596 };
597 
598 VTK_ABI_NAMESPACE_END
599 #endif
600 // VTK-HeaderTest-Exclude: vtkOpenXRManager.h
OpenGL rendering window.
OpenXR manager connection no-op implementation.
OpenXR manager graphics implementation.
Singleton class that holds a collection of utility functions and member variables to communicate with...
void PrintViewConfigViewInfo(const std::vector< XrViewConfigurationView > &)
Utility functions to print information about OpenXR manager internal structures.
bool CreateOneActionSpace(const XrAction &action, const XrPath &subactionPath, const XrPosef &poseInActionSpace, XrSpace &space)
For pose actions, we must create an action space to locate it.
XrTime PredictedDisplayTime
Store the frame predicted display time in WaitAndBeginFrame To get the action data at this time and t...
bool Initialize(vtkOpenGLRenderWindow *)
Initialize the OpenXR SDK to render images in a virtual reality device.
vtkOpenXRManagerGraphics * GetGraphicsStrategy()
Set/Get the rendering backend strategy.
bool BeginSession()
Start the OpenXR session.
void PrintOptionalExtensions()
Print the optional extensions which were found and enabled.
bool GetShouldRenderCurrentFrame()
Return true if the current frame should be rendered.
void PrintInstanceProperties()
Utility functions to print information about OpenXR manager internal structures.
void PrintSystemProperties(XrSystemProperties *system_properties)
Utility functions to print information about OpenXR manager internal structures.
bool WaitAndBeginFrame()
This function is used to start a frame.
bool AttachSessionActionSets()
Attach all action sets in the ActionSets vector to the session.
vtkOpenXRManagerConnection * GetConnectionStrategy()
Set/Get the connection strategy.
~vtkOpenXRManager()=default
bool IsSessionRunning()
Return true if the OpenXR session is currently running, ie.
bool CreateSystem()
OpenXR System creation.
bool CreateReferenceSpace()
Creates the reference space of type ReferenceSpaceType that will be used to locate views.
void SetGraphicsStrategy(vtkOpenXRManagerGraphics *gs)
Set/Get the rendering backend strategy.
bool IsDepthExtensionSupported()
Return true if the runtime supports the depth extension.
uint32_t GetViewCount()
Return the number of OpenXR views (typically one per physical display / eye)
XrPath GetXrPath(const std::string &path)
Get the XrPath from the well-formed string path.
uint32_t WaitAndAcquireSwapchainImage(const XrSwapchain &swapchainHandle)
When preparing the rendering for an eye, we must ask the runtime for a texture to draw in it.
const XrPosef * GetViewPose(uint32_t eye)
Returns a pointer to the view pose that contains the view orientation and position for the specified ...
const std::array< XrPath, 2 > & GetSubactionPaths()
vtkSmartPointer< vtkOpenXRManagerConnection > ConnectionStrategy
bool EndFrame()
Submit the composition layers for the predicted display time of the current frame.
bool CreateInstance()
OpenXR Instance creation.
bool PollEvent(XrEventDataBuffer &eventData)
Store in eventData the result of xrPollEvent.
bool CreateOneAction(Action_t &actionT, const std::string &name, const std::string &localizedName)
Creates one action with name name and localizedName localizedName and store the action handle inside ...
uint32_t GetRecommendedSampleCount()
Return the recommended swapchain sample count.
std::array< XrPath, 2 > SubactionPaths
bool ApplyVibration(const Action_t &actionT, int hand, float amplitude=0.5f, float duration=25000000.0f, float frequency=XR_FREQUENCY_UNSPECIFIED)
Apply haptic vibration action to emit vibration on hand to emit on amplitude 0.0 to 1....
bool SyncActions()
Update the action states using the active action set.
const XrFovf * GetProjectionFov(uint32_t eye)
Returns a pointer to the projection field of view for the specified eye, or nullptr if eye exceeds or...
bool CreateActionSet(const std::string &actionSetName, const std::string &localizedActionSetName)
Creates an action set and add it to the vector of action sets.
Swapchain_t CreateSwapchain(int64_t format, uint32_t width, uint32_t height, uint32_t sampleCount, XrSwapchainCreateFlags createFlags, XrSwapchainUsageFlags usageFlags)
Create an XrSwapchain handle used to present rendered image to the user with the given parameters for...
bool CreateSystemProperties()
Enable system properties such as hand tracking, and choose environment blend modes.
bool PrepareRendering(uint32_t eye, void *colorTextureId, void *depthTextureId)
Prepare the rendering resources for the specified eye and store in colorTextureId and in depthTexture...
std::string GetOpenXRPropertiesAsString()
Return the OpenXR properties as a string, with format "RuntimeName MAJOR.MINOR.PATCH".
void Finalize()
End the OpenXR session and destroy it and the OpenXR instance.
bool XrCheckOutput(OutputLevel level, const XrResult &, const std::string &message)
Utility function to check the XrResult, print the result message as a debug, warning or error message...
void SetConnectionStrategy(vtkOpenXRManagerConnection *cs)
Set/Get the connection strategy.
void ReleaseSwapchainImage(uint32_t eye)
When the rendering in a swapchain image is done, it must be released with this function.
bool SelectActiveActionSet(unsigned int index)
Selects the current active action set from the ActionSets vector using its index.
bool CreateConfigViews()
There is one configuration view per view, and it contains the recommended texture resolution in pixel...
XrSessionState SessionState
std::vector< const char * > SelectExtensions()
OpenXR Instance creation.
bool CreateSwapchains()
Swapchaines creation : there is one swapchain per view / display.
void DestroyActionSets()
Iterate over and destroy all action sets that have been created.
bool CreateSession()
Create the session and pass the GraphicsBinding to the next pointer of the XrSessionCreateInfo.
std::vector< XrActionSet > ActionSets
void PrintSupportedViewConfigs()
Utility functions to print information about OpenXR manager internal structures.
std::tuple< int64_t, int64_t > SelectSwapchainPixelFormats()
During the creation of the swapchains, we need to check the runtime available pixels formats,...
XrEnvironmentBlendMode EnvironmentBlendMode
bool LoadControllerModels()
bool UpdateActionData(Action_t &action_t, int hand)
Update the action data and store it in action_t.States for one hand.
bool SuggestActions(const std::string &profile, std::vector< XrActionSuggestedBinding > &actionSuggestedBindings)
Suggest actions stored in actionSuggestedBindings for the interaction profile profile.
std::tuple< uint32_t, uint32_t > GetRecommendedImageRectSize()
Return as a tuple the OpenXR recommended texture size to be sent to the device.
const XrInstance & GetXrRuntimeInstance()
Return the instance used to communicate with the runtime.
bool CreateSubactionPaths()
Creates one subaction path for each hand.
bool PrintReferenceSpaces()
Utility functions to print information about OpenXR manager internal structures.
static vtkOpenXRManager & GetInstance()
Return the singleton instance.
const XrSession & GetSession()
Return the OpenXR Session.
vtkSmartPointer< vtkOpenXRManagerGraphics > GraphicsStrategy
@ profile
Definition: vtkX3D.h:451
@ level
Definition: vtkX3D.h:395
@ frequency
Definition: vtkX3D.h:359
@ height
Definition: vtkX3D.h:254
@ name
Definition: vtkX3D.h:219
@ index
Definition: vtkX3D.h:246
@ string
Definition: vtkX3D.h:490
XrActionStateVector2f _vec2f
XrActionStateBoolean _boolean
This struct stores all needed information to render the images and send it to the user We can't make ...
std::vector< Swapchain_t > ColorSwapchains
std::vector< XrViewConfigurationView > ConfigViews
std::vector< Swapchain_t > DepthSwapchains
std::vector< XrCompositionLayerProjectionView > ProjectionLayerViews
std::vector< XrCompositionLayerDepthInfoKHR > DepthInfoViews
Swapchain structure storing information common to all rendering backend.
Defines the OpenXR types and extensions common to all platforms.