Ocean
Loading...
Searching...
No Matches
HandPoses.h
Go to the documentation of this file.
1/*
2 * Copyright (c) Meta Platforms, Inc. and affiliates.
3 *
4 * This source code is licensed under the MIT license found in the
5 * LICENSE file in the root directory of this source tree.
6 */
7
8#ifndef META_OCEAN_PLATFORM_META_QUEST_OPENXR_HAND_POSES_H
9#define META_OCEAN_PLATFORM_META_QUEST_OPENXR_HAND_POSES_H
10
12
14
17
18#include <openxr/openxr.h>
19
20namespace Ocean
21{
22
23namespace Platform
24{
25
26namespace Meta
27{
28
29namespace Quest
30{
31
32namespace OpenXR
33{
34
35/**
36 * This class implements a wrapper for OpenXR-based hand tracking.
37 * This object uses the Android feature 'android.hardware.vr.headtracking'
38 * @ingroup platformmetaquestopenxr
39 */
40class OCEAN_PLATFORM_META_QUEST_OPENXR_EXPORT HandPoses
41{
42 public:
43
44 /**
45 * Definition of an unordered set holding strings.
46 */
47 typedef std::unordered_set<std::string> StringSet;
48
49 /// The number of supported hands.
50 static constexpr size_t numberHands_ = 2;
51
52 /// The index of the left hand.
53 static constexpr size_t leftHandIndex_ = 0;
54
55 /// The index of the right hand.
56 static constexpr size_t rightHandIndex_ = 1;
57
58 /**
59 * This class holds the relevant information for an OpenXR hand mesh.
60 */
61 class OCEAN_PLATFORM_META_QUEST_OPENXR_EXPORT Mesh
62 {
63 friend class HandPoses;
64
65 public:
66
67 /**
68 * Definition of a vector holding radii.
69 */
70 typedef std::vector<float> Radii;
71
72 /**
73 * Definition of a vector holding signed 16-bit indices.
74 */
75 typedef std::vector<int16_t> SignedIndices16;
76
77 public:
78
79 /**
80 * Returns the vertices of the hand mesh.
81 * @return The hand mesh's vertices
82 */
84
85 /**
86 * Returns the normals of the hand mesh.
87 * @return The hand mesh's per-vertex normals
88 */
90
91 /**
92 * Returns the blend indices of the individual hand joints.
93 * @return The hand joint's blend indices
94 */
95 inline const Platform::OpenXR::XrVectors4sFB& blendIndices() const;
96
97 /**
98 * Returns the blend weights of the individual hand joints.
99 * @return The hand joint's blend weights
100 */
101 inline const Platform::OpenXR::XrVectors4f& blendWeights() const;
102
103 /**
104 * Returns the vertex indices of the hand mesh triangles.
105 * @return The mesh triangle faces, three consecutive indices define one triangle
106 */
107 inline const SignedIndices16& indices() const;
108
109 /**
110 * Returns the transformations between bind joints and wrist.
111 * @return The bind joint transformations
112 * @tparam The data type of the scalar to be used either 'float' or 'double'
113 */
114 template <typename T = Scalar>
116
117 /**
118 * Returns whether this mesh is valid
119 * @return True, if so
120 */
121 inline bool isValid() const;
122
123 protected:
124
125 /**
126 * Protected default constructor.
127 */
128 Mesh() = default;
129
130 /**
131 * Initializes this mesh with a given tracker for one hand.
132 * @param xrHandTrackerEXT The hand tracker which will be associated with this mesh, must be valid
133 * @param xrGetHandMeshFB The OpenXR get hand mesh function, must be valid
134 * @return True, if succeeded
135 */
136 bool initialize(const XrHandTrackerEXT& xrHandTrackerEXT, const PFN_xrGetHandMeshFB& xrGetHandMeshFB);
137
138 protected:
139
140 /// The OpenXR hand tracking mesh.
141 XrHandTrackingMeshFB xrHandTrackingMeshFB_ = {XR_TYPE_HAND_TRACKING_MESH_FB};
142
143 /// The joint bind poses.
145
146 /// The radii of the individual hand joints.
148
149 /// The parents of the individual joints.
151
152 /// The positions of the individual vertices.
154
155 /// The normals of the individual vertices.
157
158 /// The texture coordinates of the individual vertices.
160
161 /// The blend indices of the individual vertices.
163
164 /// The blend weights of the individual vertices.
166
167 /// The vertex indices of the hand mesh triangles, must be a multiple of 3.
169
170 /// True, if the mesh is valid.
171 bool isValid_ = false;
172 };
173
174 /**
175 * This class holds the relevant information for an OpenXR hand pose.
176 */
177 class OCEAN_PLATFORM_META_QUEST_OPENXR_EXPORT Pose
178 {
179 friend class HandPoses;
180
181 public:
182
183 /// Default flags for valid hand locations.
184 static constexpr XrSpaceLocationFlags defaultLocationFlags_ = XR_SPACE_LOCATION_ORIENTATION_VALID_BIT | XR_SPACE_LOCATION_POSITION_VALID_BIT;
185
186 public:
187
188 /**
189 * Returns the 3D positions of the hand joints in relation to the hand pose's base space.
190 * @param baseSpaceJointPositions The resulting joint locations defined in the base space, either XR_HAND_JOINT_COUNT_EXT or zero
191 * @param xrSpaceLocationFlags The location flags all hand joints must satisfy
192 * @return True, if succeeded; False, if e.g., some hand joints don't satisfy the specified location flags
193 * @tparam T The data type of the scalar to be used either 'float' or 'double'
194 */
195 template <typename T = Scalar>
196 bool jointPositions(VectorsT3<T>& baseSpaceJointPositions, const XrSpaceLocationFlags xrSpaceLocationFlags = defaultLocationFlags_) const;
197
198 /**
199 * Returns the 6DOF transformations of the hand joints in relation to the hand pose's base space.
200 * The resulting transformations do not incorporate the mesh's joint bind poses.
201 * @param baseSpace_T_joints The resulting joint transformations, either XR_HAND_JOINT_COUNT_EXT or zero
202 * @param xrSpaceLocationFlags The location flags all hand joints must satisfy
203 * @return True, if succeeded; False, if e.g., some hand joints don't satisfy the specified location flags
204 * @tparam T The data type of the scalar to be used either 'float' or 'double'
205 */
206 template <typename T = Scalar>
207 bool jointTransformations(HomogenousMatricesT4<T>& baseSpace_T_joints, const XrSpaceLocationFlags xrSpaceLocationFlags = defaultLocationFlags_) const;
208
209 /**
210 * Returns the 6DOF transformations of the hand joints in relation to the hand pose's base space.
211 * The resulting transformations incorporate the mesh's joint bind poses and thus can be used to e.g., render a hand mesh.
212 * @param mesh The hand mesh providing the joint bind poses, must be valid
213 * @param baseSpace_T_joints The resulting joint transformations, either XR_HAND_JOINT_COUNT_EXT or zero
214 * @param xrSpaceLocationFlags The location flags all hand joints must satisfy
215 * @return True, if succeeded; False, if e.g., some hand joints don't satisfy the specified location flags
216 * @tparam T The data type of the scalar to be used either 'float' or 'double'
217 */
218 template <typename T = Scalar>
219 bool jointTransformations(const Mesh& mesh, HomogenousMatricesT4<T>& baseSpace_T_joints, const XrSpaceLocationFlags xrSpaceLocationFlags = defaultLocationFlags_) const;
220
221 /**
222 * Returns the vertices of the hand mesh in relation to the hand pose's base space.
223 * The resulting vertices incorporate the mesh's joint bind poses and thus can be used to e.g., render a hand mesh without any further transformations.
224 * @param mesh The hand mesh providing the joint bind poses, must be valid
225 * @param baseSpaceMeshVertices The resulting hand mesh vertices defined in the base space
226 * @param xrSpaceLocationFlags The location flags all hand joints must satisfy
227 * @return True, if succeeded; False, if e.g., some hand joints don't satisfy the specified location flags
228 * @tparam T The data type of the scalar to be used either 'float' or 'double'
229 */
230 template <typename T = Scalar>
231 bool meshVertices(const Mesh& mesh, VectorsT3<T>& baseSpaceMeshVertices, const XrSpaceLocationFlags xrSpaceLocationFlags = defaultLocationFlags_) const;
232
233 /**
234 * Returns the OpenXR space in which relation the hand pose is determined.
235 * @return The OpenXR space
236 */
237 inline XrSpace xrBaseSpace() const;
238
239 /**
240 * Returns the XR_HAND_JOINT_COUNT_EXT hand joint locations of this pose.
241 * @return The pose' hand joint locations
242 */
243 inline const XrHandJointLocationEXT* xrHandJointLocationsEXT() const;
244
245 /**
246 * Returns the XR_HAND_JOINT_COUNT_EXT hand joint velocities of this pose.
247 * @return The pose' hand joint velocities
248 */
249 inline const XrHandJointVelocityEXT* xrHandJointVelocitiesEXT() const;
250
251 /**
252 * Returns whether this hand pose is valid.
253 * @return True, if so
254 */
255 inline bool isValid() const;
256
257 protected:
258
259 /**
260 * Protected default constructor.
261 */
262 Pose() = default;
263
264 protected:
265
266 /// The OpenXR space in which relation the hand pose is determined.
267 XrSpace xrBaseSpace_ = XR_NULL_HANDLE;
268
269 /// The hand joint locations of this hand pose.
270 XrHandJointLocationEXT xrHandJointLocationsEXT_[XR_HAND_JOINT_COUNT_EXT];
271
272 /// The hand joint velocities of this hand pose.
273 XrHandJointVelocityEXT xrHandJointVelocitiesEXT_[XR_HAND_JOINT_COUNT_EXT];
274 };
275
276 public:
277
278 /**
279 * Default constructor
280 */
281 HandPoses() = default;
282
283 /**
284 * Move constructor.
285 * @param handPoses Object to be moved
286 */
287 HandPoses(HandPoses&& handPoses);
288
289 /**
290 * Initializes the hand tracking object.
291 * @param session The OpenxR session to be used, must be valid
292 * @return True, if succeeded
293 */
294 inline bool initialize(const Platform::OpenXR::Session& session);
295
296 /**
297 * Initializes the hand tracking object.
298 * @param xrInstance The instance for which the hand poses will be created, must be valid
299 * @param xrSession The session for which the hand poses will be created, must be valid
300 * @param xrSystemId The runtime's identifier, must be valid
301 * @return True, if succeeded
302 */
303 bool initialize(const XrInstance& xrInstance, const XrSession& xrSession, const XrSystemId& xrSystemId);
304
305 /**
306 * Explicitly releases the session and all associated resources.
307 * @see initialize().
308 */
309 void release();
310
311 /**
312 * Updates the pose of the left and right hands.
313 * @param xrBaseSpace The space in which the hands will be defined, must be valid
314 * @param predictedDisplayTime The predicted display time of the next frame
315 * @return True, if succeeded
316 */
317 bool update(const XrSpace& xrBaseSpace, const XrTime& predictedDisplayTime);
318
319 /**
320 * Returns the mesh of one hand.
321 * Lock this object's lock before calling this function.
322 * @param handIndex The index of the hand for which the mesh will be returned, with range [0, numberHands_ - 1]
323 * @return The requested mesh, may be invalid
324 * @see lock().
325 */
326 inline const Mesh& mesh(const size_t handIndex) const;
327
328 /**
329 * Returns the current pose of one hand.
330 * Lock this object's lock before calling this function.<br>
331 * Call update() to ensure that the latest hand pose is provided.
332 * @param handIndex The index of the hand for which the pose will be returned, with range [0, numberHands_ - 1]
333 * @return The requested mesh, may be invalid
334 * @see lock(), update().
335 */
336 inline const Pose& pose(const size_t handIndex) const;
337
338 /**
339 * Returns the 3D positions of the joints of one hand in relation to the hand pose's base space.
340 * The resulting positions are valid until the next 'update()' call.
341 * @param handIndex The index of the hand for which the pose will be returned, with range [0, numberHands_ - 1]
342 * @return The resulting joint locations define in the baseSpace, XR_HAND_JOINT_COUNT_EXT joint positions if succeeded
343 */
344 const Vectors3& jointPositions(const size_t handIndex) const;
345
346 /**
347 * Returns the lock of the hand poses.
348 * @return The hand poses' lock.
349 */
350 inline Lock& lock() const;
351
352 /**
353 * Returns whether this object holds initialized and valid OpenXR hand trackers.
354 * @return True, if so
355 */
356 inline bool isValid() const;
357
358 /**
359 * Move operator.
360 * @param handPoses The object to be moved
361 * @return Reference to this object
362 */
364
365 /**
366 * Returns the names of the necessary OpenXR extensions necessary for hand tracking.
367 * @return The necessary OpenXR extensions
368 */
370
371 /**
372 * Updates the current hand pose of one hand.
373 * @param xrHandTrackersEXT The hand tracker from which the hand pose will be extracted, must be valid
374 * @param xrLocateHandJointsEXT The OpenXR locate hand joint function, must be valid
375 * @param xrBaseSpace The OpenXR space in which relation the hand pose is determined, must be valid
376 * @param xrTime The OpenXR time for which the hand pose is requested, e.g. the predicted display time
377 * @param pose The hand pose receiving the updated information
378 * @return True, if succeeded
379 */
380 static bool updateHandPose(const XrHandTrackerEXT& xrHandTrackersEXT, const PFN_xrLocateHandJointsEXT xrLocateHandJointsEXT, const XrSpace& xrBaseSpace, const XrTime& xrTime, Pose& pose);
381
382 protected:
383
384 /**
385 * Disabled copy constructor.
386 */
387 HandPoses(const HandPoses&) = delete;
388
389 /**
390 * Disabled copy operator.
391 * @return Reference to this object
392 */
393 HandPoses& operator=(const HandPoses&) = delete;
394
395 protected:
396
397 /// The OpenXR instance for which hand tracking is created.
398 XrInstance xrInstance_ = XR_NULL_HANDLE;
399
400 /// The OpenXR function pointer to create a new hand tracker.
401 PFN_xrCreateHandTrackerEXT xrCreateHandTrackerEXT_ = nullptr;
402
403 /// The OpenXR function pointer to destroy a hand tracker.
404 PFN_xrDestroyHandTrackerEXT xrDestroyHandTrackerEXT_ = nullptr;
405
406 /// The OpenXR function to determine the hand joints.
407 PFN_xrLocateHandJointsEXT xrLocateHandJointsEXT_ = nullptr;
408
409 /// The OpenXR function to determine the hand mesh.
410 PFN_xrGetHandMeshFB xrGetHandMeshFB_ = nullptr;
411
412 /// The OpenXR handles to both hand trackers with order [left, right].
413 XrHandTrackerEXT xrHandTrackersEXT_[numberHands_] = {XR_NULL_HANDLE, XR_NULL_HANDLE};
414
415 /// The meshes for both hands.
416 Mesh meshes_[numberHands_];
417
418 /// The poses for both hands.
419 Pose poses_[numberHands_];
420
421 /// The cached positions of the joints of both hands.
422 mutable Vectors3 baseSpaceJointPositions_[numberHands_];
423
424 /// An empty vector with 3D vectors.
426
427 /// The lock of this object.
428 mutable Lock lock_;
429};
430
435
437{
438 return vertexBlendWeights_;
439}
440
442{
443 return indices_;
444}
445
446inline bool HandPoses::Mesh::isValid() const
447{
448 return isValid_;
449}
450
451inline XrSpace HandPoses::Pose::xrBaseSpace() const
452{
453 return xrBaseSpace_;
454}
455
456inline const XrHandJointLocationEXT* HandPoses::Pose::xrHandJointLocationsEXT() const
457{
458 return xrHandJointLocationsEXT_;
459}
460
461inline const XrHandJointVelocityEXT* HandPoses::Pose::xrHandJointVelocitiesEXT() const
462{
463 return xrHandJointVelocitiesEXT_;
464}
465
466inline bool HandPoses::Pose::isValid() const
467{
468 return xrBaseSpace_ != XR_NULL_HANDLE;
469}
470
472{
473 ocean_assert(session.isValid());
474
475 return initialize(session.xrInstance(), session, session.xrSystemId());
476}
477
478inline const HandPoses::Mesh& HandPoses::mesh(const size_t handIndex) const
479{
480 ocean_assert(handIndex < numberHands_);
481
482 const ScopedLock scopedLock(lock_);
483
484 ocean_assert(isValid());
485
486 return meshes_[handIndex];
487}
488
489inline const HandPoses::Pose& HandPoses::pose(const size_t handIndex) const
490{
491 ocean_assert(handIndex < numberHands_);
492
493 const ScopedLock scopedLock(lock_);
494
495 ocean_assert(isValid());
496
497 return poses_[handIndex];
498}
499
500inline Lock& HandPoses::lock() const
501{
502 return lock_;
503}
504
505inline bool HandPoses::isValid() const
506{
507 const ScopedLock scopedLock(lock_);
508
509 return xrInstance_ != XR_NULL_HANDLE;
510}
511
512}
513
514}
515
516}
517
518}
519
520}
521
522#endif // META_OCEAN_PLATFORM_META_QUEST_OPENXR_HAND_POSES_H
This class implements a recursive lock object.
Definition Lock.h:31
This class holds the relevant information for an OpenXR hand mesh.
Definition HandPoses.h:62
Platform::OpenXR::XrVectors3f vertexPositions_
The positions of the individual vertices.
Definition HandPoses.h:153
Mesh()=default
Protected default constructor.
bool initialize(const XrHandTrackerEXT &xrHandTrackerEXT, const PFN_xrGetHandMeshFB &xrGetHandMeshFB)
Initializes this mesh with a given tracker for one hand.
SignedIndices16 indices_
The vertex indices of the hand mesh triangles, must be a multiple of 3.
Definition HandPoses.h:168
std::vector< float > Radii
Definition of a vector holding radii.
Definition HandPoses.h:70
HomogenousMatricesT4< T > wrist_T_bindJoints() const
Returns the transformations between bind joints and wrist.
Vectors3 normals() const
Returns the normals of the hand mesh.
const Platform::OpenXR::XrVectors4f & blendWeights() const
Returns the blend weights of the individual hand joints.
Definition HandPoses.h:436
std::vector< int16_t > SignedIndices16
Definition of a vector holding signed 16-bit indices.
Definition HandPoses.h:75
bool isValid() const
Returns whether this mesh is valid.
Definition HandPoses.h:446
Vectors3 vertices() const
Returns the vertices of the hand mesh.
const SignedIndices16 & indices() const
Returns the vertex indices of the hand mesh triangles.
Definition HandPoses.h:441
Platform::OpenXR::XrVectors2f vertexUVs_
The texture coordinates of the individual vertices.
Definition HandPoses.h:159
Platform::OpenXR::XrVectors3f vertexNormals_
The normals of the individual vertices.
Definition HandPoses.h:156
Platform::OpenXR::XrVectors4f vertexBlendWeights_
The blend weights of the individual vertices.
Definition HandPoses.h:165
Platform::OpenXR::XrPosesf jointBindPoses_
The joint bind poses.
Definition HandPoses.h:144
const Platform::OpenXR::XrVectors4sFB & blendIndices() const
Returns the blend indices of the individual hand joints.
Definition HandPoses.h:431
Platform::OpenXR::XrHandJointsEXT jointParents_
The parents of the individual joints.
Definition HandPoses.h:150
Radii jointRadii_
The radii of the individual hand joints.
Definition HandPoses.h:147
Platform::OpenXR::XrVectors4sFB vertexBlendIndices_
The blend indices of the individual vertices.
Definition HandPoses.h:162
This class holds the relevant information for an OpenXR hand pose.
Definition HandPoses.h:178
bool jointTransformations(const Mesh &mesh, HomogenousMatricesT4< T > &baseSpace_T_joints, const XrSpaceLocationFlags xrSpaceLocationFlags=defaultLocationFlags_) const
Returns the 6DOF transformations of the hand joints in relation to the hand pose's base space.
bool meshVertices(const Mesh &mesh, VectorsT3< T > &baseSpaceMeshVertices, const XrSpaceLocationFlags xrSpaceLocationFlags=defaultLocationFlags_) const
Returns the vertices of the hand mesh in relation to the hand pose's base space.
bool jointTransformations(HomogenousMatricesT4< T > &baseSpace_T_joints, const XrSpaceLocationFlags xrSpaceLocationFlags=defaultLocationFlags_) const
Returns the 6DOF transformations of the hand joints in relation to the hand pose's base space.
bool jointPositions(VectorsT3< T > &baseSpaceJointPositions, const XrSpaceLocationFlags xrSpaceLocationFlags=defaultLocationFlags_) const
Returns the 3D positions of the hand joints in relation to the hand pose's base space.
Pose()=default
Protected default constructor.
This class implements a wrapper for OpenXR-based hand tracking.
Definition HandPoses.h:41
void release()
Explicitly releases the session and all associated resources.
Pose poses_[numberHands_]
The poses for both hands.
Definition HandPoses.h:419
bool initialize(const XrInstance &xrInstance, const XrSession &xrSession, const XrSystemId &xrSystemId)
Initializes the hand tracking object.
static constexpr size_t numberHands_
The number of supported hands.
Definition HandPoses.h:50
static const StringSet & necessaryOpenXRExtensionNames()
Returns the names of the necessary OpenXR extensions necessary for hand tracking.
XrInstance xrInstance_
The OpenXR instance for which hand tracking is created.
Definition HandPoses.h:398
Mesh meshes_[numberHands_]
The meshes for both hands.
Definition HandPoses.h:416
bool isValid() const
Returns whether this object holds initialized and valid OpenXR hand trackers.
Definition HandPoses.h:505
const Mesh & mesh(const size_t handIndex) const
Returns the mesh of one hand.
Definition HandPoses.h:478
Lock & lock() const
Returns the lock of the hand poses.
Definition HandPoses.h:500
const Pose & pose(const size_t handIndex) const
Returns the current pose of one hand.
Definition HandPoses.h:489
static bool updateHandPose(const XrHandTrackerEXT &xrHandTrackersEXT, const PFN_xrLocateHandJointsEXT xrLocateHandJointsEXT, const XrSpace &xrBaseSpace, const XrTime &xrTime, Pose &pose)
Updates the current hand pose of one hand.
HandPoses(HandPoses &&handPoses)
Move constructor.
bool initialize(const Platform::OpenXR::Session &session)
Initializes the hand tracking object.
Definition HandPoses.h:471
const Vectors3 & jointPositions(const size_t handIndex) const
Returns the 3D positions of the joints of one hand in relation to the hand pose's base space.
HandPoses()=default
Default constructor.
const Vectors3 invalidResultVectors_
An empty vector with 3D vectors.
Definition HandPoses.h:425
Lock lock_
The lock of this object.
Definition HandPoses.h:428
std::unordered_set< std::string > StringSet
Definition of an unordered set holding strings.
Definition HandPoses.h:47
HandPoses & operator=(const HandPoses &)=delete
Disabled copy operator.
HandPoses(const HandPoses &)=delete
Disabled copy constructor.
bool update(const XrSpace &xrBaseSpace, const XrTime &predictedDisplayTime)
Updates the pose of the left and right hands.
HandPoses & operator=(HandPoses &&handPoses)
Move operator.
This class wraps an OpenXR session.
Definition Session.h:32
XrInstance xrInstance() const
Returns the OpenXR instance associated with this session.
Definition Session.h:359
XrSystemId xrSystemId() const
Returns the OpenXR runtime's identifier.
Definition Session.h:366
bool isValid() const
Returns whether this object holds a valid OpenXR instance.
This class implements a scoped lock object for recursive lock objects.
Definition Lock.h:135
std::vector< HomogenousMatrixT4< T > > HomogenousMatricesT4
Definition of a typename alias for vectors with HomogenousMatrixT4 objects.
Definition HomogenousMatrix4.h:66
std::vector< VectorT3< T > > VectorsT3
Definition of a typename alias for vectors with VectorT3 objects.
Definition Vector3.h:58
std::vector< Vector3 > Vectors3
Definition of a vector holding Vector3 objects.
Definition Vector3.h:65
std::vector< XrVector4sFB > XrVectors4sFB
Definition of a vector holding OpenXR XrVector4sFB objects.
Definition openxr/OpenXR.h:92
std::vector< XrPosef > XrPosesf
Definition of a vector holding OpenXR XrPosef objects.
Definition openxr/OpenXR.h:99
std::vector< XrVector3f > XrVectors3f
Definition of a vector holding OpenXR XrVector3f objects.
Definition openxr/OpenXR.h:78
std::vector< XrVector4f > XrVectors4f
Definition of a vector holding OpenXR XrVector4f objects.
Definition openxr/OpenXR.h:85
std::vector< XrVector2f > XrVectors2f
Definition of a vector holding OpenXR XrVector2f objects.
Definition openxr/OpenXR.h:71
std::vector< XrHandJointEXT > XrHandJointsEXT
Definition of a vector holding OpenXR XrHandJointEXT objects.
Definition openxr/OpenXR.h:106
The namespace covering the entire Ocean framework.
Definition Accessor.h:15