VTK  9.3.0
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 <memory>
26 #include <string>
27 #include <vector>
28 
29 VTK_ABI_NAMESPACE_BEGIN
31 
32 class VTKRENDERINGOPENXR_EXPORT vtkOpenXRManager
33 {
34 public:
36 
40  {
41  static vtkOpenXRManager UniqueInstance;
42  return UniqueInstance;
43  }
45 
47  {
48  DebugOutput = 0,
49  WarningOutput = 1,
50  ErrorOutput = 2
51  };
52 
54 
58  bool XrCheckOutput(OutputLevel level, const XrResult&, const std::string& message);
60 
62 
66  void PrintSystemProperties(XrSystemProperties* system_properties);
68  void PrintViewConfigViewInfo(const std::vector<XrViewConfigurationView>&);
71 
73 
80 
82 
85  void Finalize();
87 
89 
92  std::tuple<uint32_t, uint32_t> GetRecommendedImageRectSize();
94 
96 
101 
105  uint32_t GetViewCount()
106  {
107  return static_cast<uint32_t>(this->RenderResources->ConfigViews.size());
108  }
109 
111 
117 
119 
125  const XrPosef* GetViewPose(uint32_t eye)
126  {
127  if (eye >= this->GetViewCount())
128  {
129  return nullptr;
130  }
131  return &(this->RenderResources->Views[eye].pose);
132  }
134 
136 
141  const XrFovf* GetProjectionFov(uint32_t eye)
142  {
143  if (eye >= this->GetViewCount())
144  {
145  return nullptr;
146  }
147  return &(this->RenderResources->Views[eye].fov);
148  }
150 
152 
155  bool IsDepthExtensionSupported() { return this->OptionalExtensions.DepthExtensionSupported; }
157 
159 
164  bool GetShouldRenderCurrentFrame() { return this->ShouldRenderCurrentFrame; }
166 
168 
172  bool BeginSession();
174 
176 
179  const XrSession& GetSession() { return this->Session; }
181 
183 
186  const XrInstance& GetXrRuntimeInstance() { return this->Instance; }
188 
190 
194  bool IsSessionRunning() { return this->SessionRunning; }
196 
198 
205 
207 
213  bool PrepareRendering(uint32_t eye, void* colorTextureId, void* depthTextureId);
215 
217 
221  void ReleaseSwapchainImage(uint32_t eye);
223 
225 
229  bool EndFrame();
231 
233 
236  bool PollEvent(XrEventDataBuffer& eventData);
238 
240 
243  XrPath GetXrPath(const std::string& path);
245 
246  const std::array<XrPath, 2>& GetSubactionPaths() { return this->SubactionPaths; }
247 
249 
252  bool CreateActionSet(const std::string& actionSetName, const std::string& localizedActionSetName);
254 
256 
260  bool SelectActiveActionSet(unsigned int index);
262 
264 
269 
271 
276 
277  struct Action_t;
278 
280 
286  Action_t& actionT, const std::string& name, const std::string& localizedName);
288 
290 
294  const std::string& profile, std::vector<XrActionSuggestedBinding>& actionSuggestedBindings);
296 
298 
302  bool SyncActions();
304 
306 
313  bool UpdateActionData(Action_t& action_t, int hand);
315 
321  bool ApplyVibration(const Action_t& actionT, int hand, float amplitude = 0.5f,
322  float duration = 25000000.0f, float frequency = XR_FREQUENCY_UNSPECIFIED);
323 
325  {
326  Inactive = -1,
327  Left = 0,
328  Right = 1,
329  Head = 2,
330  Generic = 3,
331  NumberOfControllers = 4
332  };
333 
334  struct Action_t
335  {
336  XrAction Action;
337  XrActionType ActionType;
338 
339  union {
340  XrActionStateFloat _float;
341  XrActionStateBoolean _boolean;
342  XrActionStatePose _pose;
343  XrActionStateVector2f _vec2f;
344  } States[ControllerIndex::NumberOfControllers];
345 
346  XrSpace PoseSpaces[ControllerIndex::NumberOfControllers];
347  XrSpaceLocation PoseLocations[ControllerIndex::NumberOfControllers];
348  XrSpaceVelocity PoseVelocities[ControllerIndex::NumberOfControllers];
349  };
350 
352 
355  void SetGraphicsStrategy(vtkOpenXRManagerGraphics* gs) { this->GraphicsStrategy = gs; }
356  vtkOpenXRManagerGraphics* GetGraphicsStrategy() { return this->GraphicsStrategy; }
358 
360 
363  void SetConnectionStrategy(vtkOpenXRManagerConnection* cs) { this->ConnectionStrategy = cs; }
364  vtkOpenXRManagerConnection* GetConnectionStrategy() { return this->ConnectionStrategy; }
366 
367 protected:
369  ~vtkOpenXRManager() = default;
370 
372 
378  std::vector<const char*> SelectExtensions();
380 
382 
387 
389 
392  bool CreateSystem();
394 
396 
402 
404 
411 
413 
419 
421 
427 
429 
435  std::tuple<int64_t, int64_t> SelectSwapchainPixelFormats();
437 
438  struct Swapchain_t;
439 
441 
445  Swapchain_t CreateSwapchain(int64_t format, uint32_t width, uint32_t height, uint32_t sampleCount,
446  XrSwapchainCreateFlags createFlags, XrSwapchainUsageFlags usageFlags);
448 
450 
455 
457 
459 
462  bool CreateOneActionSpace(const XrAction& action, const XrPath& subactionPath,
463  const XrPosef& poseInActionSpace, XrSpace& space);
465 
467 
472 
474 
478  uint32_t WaitAndAcquireSwapchainImage(const XrSwapchain& swapchainHandle);
480 
481  // Currently VTK only supports HeadMountedDisplay (HMD)
482  constexpr static XrFormFactor FormFactor = XR_FORM_FACTOR_HEAD_MOUNTED_DISPLAY;
483 
484  // Pick the view type to be stereo rather than mono or anything else
485  constexpr static XrViewConfigurationType ViewType = XR_VIEW_CONFIGURATION_TYPE_PRIMARY_STEREO;
486 
487  // PRIMARY_STEREO view configuration always has 2 views
488  constexpr static uint32_t StereoViewCount = 2;
489 
490  // Three available types: VIEW, LOCAL and STAGE. We use LOCAL space which
491  // establishes a world-locked origin, rather than VIEW space, which tracks the
492  // view origin.
493  XrReferenceSpaceType ReferenceSpaceType = XR_REFERENCE_SPACE_TYPE_STAGE;
494 
495  // Communication with the runtime happens through this instance
496  XrInstance Instance;
497 
498  // A system is defined by an id and is used to create a session
499  XrSystemId SystemId;
500 
501  XrSession Session;
502  XrSessionState SessionState;
503  XrSpace ReferenceSpace;
504 
505  // At the end of a frame, we must select en environment blend mode
506  // to tell the runtime how we want to blend the image with the user's
507  // view of the physical world. For example, in VR, we will generally
508  // choose XR_ENVIRONMENT_BLEND_MODE_OPAQUE while AR will generally
509  // choose XR_ENVIRONMENT_BLEND_MODE_ADDITIVE or XR_ENVIRONMENT_BLEND_MODE_ALPHA_BLEND
510  XrEnvironmentBlendMode EnvironmentBlendMode;
511 
512  // Non optional extension
513  bool RenderingBackendExtensionSupported = false;
514 
516 
520  struct
521  {
522  bool DepthExtensionSupported{ false };
523  bool ControllerModelExtensionSupported{ false };
524  bool UnboundedRefSpaceSupported{ false };
525  bool SpatialAnchorSupported{ false };
526  bool HandInteractionSupported{ false };
527  bool HandTrackingSupported{ false };
528  bool RemotingSupported{ false };
529  } OptionalExtensions;
531 
536  struct Swapchain_t
537  {
538  XrSwapchain Swapchain;
539  int64_t Format{ 0 };
540  uint32_t Width{ 0 };
541  uint32_t Height{ 0 };
542  };
543 
545 
552  {
553  XrViewState ViewState{ XR_TYPE_VIEW_STATE };
554  // Each physical Display/Eye is described by a view
555  std::vector<XrView> Views;
556  // One configuration view per view : this store
557  std::vector<XrViewConfigurationView> ConfigViews;
558 
559  std::vector<Swapchain_t> ColorSwapchains;
560  std::vector<Swapchain_t> DepthSwapchains;
561 
562  std::vector<XrCompositionLayerProjectionView> ProjectionLayerViews;
563  std::vector<XrCompositionLayerDepthInfoKHR> DepthInfoViews;
564  };
565  std::unique_ptr<RenderResources_t> RenderResources{};
567 
568  // There is one subaction path for each hand.
569  std::array<XrPath, 2> SubactionPaths;
570 
571  std::vector<XrActionSet> ActionSets;
572  XrActionSet* ActiveActionSet = nullptr;
573 
579 
580  bool SessionRunning = false;
581  // After each WaitAndBeginFrame, the OpenXR runtime may inform us that
582  // the current frame should not be rendered. Store it to avoid a render
583  bool ShouldRenderCurrentFrame = false;
584  // If true, the function UpdateActionData will store
585  // pose velocities for pose actions
586  bool StorePoseVelocities = false;
587 
589 
591 
592 private:
593  vtkOpenXRManager(const vtkOpenXRManager&) = delete;
594  void operator=(const vtkOpenXRManager&) = delete;
595 };
596 
597 VTK_ABI_NAMESPACE_END
598 #endif
599 // 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.