2
0

openxr_render_models.rst 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275
  1. .. _doc_openxr_render_models:
  2. OpenXR Render Models
  3. ====================
  4. A cornerstone of OpenXR's API design is being as platform agnostic as possible.
  5. A great example of this is OpenXR's action map system where XR runtimes
  6. have to support core interaction profiles to fall back on,
  7. if no interaction profile exists for the hardware being used.
  8. This ensures that OpenXR applications keep functioning even when used on
  9. hardware that didn't exist when the application was released,
  10. or that the developers of the application did not have access too.
  11. A consequence of this is that the application developer doesn't know with any
  12. certainty what hardware is being used, as the XR runtime could be mimicking
  13. other hardware.
  14. The application developer thus can't show anything in relation to the actual
  15. hardware used, the most common use case being showing the controllers the user
  16. is currently holding.
  17. Showing the correct controller models and having these models
  18. correctly positioned is important to a proper sense of immersion.
  19. This is where OpenXR's `render models API <https://registry.khronos.org/OpenXR/specs/1.1/html/xrspec.html#XR_EXT_render_models>`_ comes in.
  20. This API allows us to query the XR runtime for 3D assets that are correct
  21. for the physical hardware being used.
  22. The API also allows us to query the position of this hardware within the
  23. tracking volume and the correct positioning of subcomponents of this hardware.
  24. For instance, we can correctly position and animate the trigger or show buttons
  25. being pressed.
  26. For those runtimes that support the
  27. `controller data source for hand tracking <https://registry.khronos.org/OpenXR/specs/1.1/html/xrspec.html#XR_EXT_hand_tracking_data_source>`_
  28. , we can also correctly position the user's fingers and hand according to the
  29. shape of the controller.
  30. Do note that this works in combination with the
  31. `hand joints motion range extension <https://registry.khronos.org/OpenXR/specs/1.1/html/xrspec.html#XR_EXT_hand_joints_motion_range>`_
  32. to prevent clipping of the fingers.
  33. OpenXR Render models node
  34. -------------------------
  35. The :ref:`OpenXRRenderModelManager<class_OpenXRRenderModelManager>`
  36. node can be used to automate most of the render models functionality.
  37. This node keeps track of the active render models currently made
  38. available by the XR runtime.
  39. It will create child nodes for each active render model resulting in
  40. that render model being displayed.
  41. This node must have an :ref:`XROrigin3D<class_XROrigin3D>` node as an
  42. ancestor.
  43. If ``tracker`` is set to ``Any`` our node will show all render models
  44. currently being tracked. In this scenario this node must be a direct
  45. child of our :ref:`XROrigin3D<class_XROrigin3D>` node.
  46. If ``tracker`` is set to ``None set`` our node will only show render
  47. models for which no tracker has been identified. In this scenario this
  48. node must also be a direct child of our
  49. :ref:`XROrigin3D<class_XROrigin3D>` node.
  50. If ``tracker`` is set to ``Left Hand`` or ``Right Hand`` our node will
  51. only show render models related to our left or right hand respectively.
  52. In this scenario, our node can be placed deeper in the scene tree.
  53. .. warning::
  54. For most XR runtimes this means the render model represents a controller
  55. that is actually being held by the user but this is not a guarantee.
  56. Some XR runtimes will always set the tracker to either the left or right
  57. hand even if the controller is not currently held but is being tracked.
  58. You should always test this as this will lead to unwanted behavior.
  59. In this scenario we can also specify an action for a pose in the action map
  60. by setting the ``make_local_to_pose`` property to the pose action.
  61. Use this in combination with an :ref:`XRController3D<class_XRController3D>`
  62. node that is using the same pose and you can now add a layer that allows
  63. you to deviate from the tracked position of both your controller and the
  64. related render model (see example below).
  65. .. note::
  66. Combining the above with hand tracking does introduce the problem
  67. that hand tracking is completely independent from the action map
  68. system. You will need to combine the hand tracking and controller
  69. tracking poses to properly offset the render models.
  70. This falls beyond the scope of this documentation.
  71. Render model manager example
  72. ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  73. You can download `our render models demo <https://github.com/godotengine/godot-demo-projects/tree/master/xr/openxr_render_models>`_
  74. which implements the setup described below.
  75. .. image:: img/openxr_render_models_setup.webp
  76. In this setup we find an :ref:`OpenXRRenderModelManager<class_OpenXRRenderModelManager>`
  77. node directly underneath our :ref:`XROrigin3D<class_XROrigin3D>` node.
  78. On this node our ``target`` property is set to ``None set`` and will handle
  79. showing all render models that are currently not related to our left or
  80. right hand controllers.
  81. We then see the same setup for our left and right hand so we'll focus on
  82. just the left hand.
  83. We have an :ref:`XRController3D<class_XRController3D>` that will track the
  84. location of our hand.
  85. .. note::
  86. We are using the ``grip`` pose in this example. The ``palm`` pose is
  87. arguably more suitable and predictable however it is not supported
  88. by all XR runtimes. See the hand tracking demo project for a
  89. solution to switching between these poses based on what is supported.
  90. As a child of the node we have an :ref:`AnimatableBody3D<class_AnimatableBody3D>`
  91. node that follows the tracked location of the hand **but** will interact
  92. with physics objects to stop the player's hand from going through walls etc.
  93. This node has a collision shape that encapsulates the hand.
  94. .. note::
  95. It is important to set the physics priority so that this logic runs
  96. after any physics logic that moves the XROrigin3D node or the hand
  97. will lag a frame behind.
  98. The script below shows a basic implementation for this that you can build
  99. upon.
  100. .. code-block:: gdscript
  101. class_name CollisionHands3D
  102. extends AnimatableBody3D
  103. func _ready():
  104. # Make sure these are set correctly.
  105. top_level = true
  106. sync_to_physics = false
  107. process_physics_priority = -90
  108. func _physics_process(_delta):
  109. # Follow our parent node around.
  110. var dest_transform = get_parent().global_transform
  111. # We just apply rotation for this example.
  112. global_basis = dest_transform.basis
  113. # Attempt to move to where our tracked hand is.
  114. move_and_collide(dest_transform.origin - global_position)
  115. Finally we see another :ref:`OpenXRRenderModelManager<class_OpenXRRenderModelManager>`
  116. node, this one with ``target`` set to the appropriate hand and
  117. ``make_local_to_pose`` set to the correct pose.
  118. This will ensure that the render models related to this hand are properly
  119. shown and offset if our collision handler has altered the location.
  120. .. raw:: html
  121. <div style="position: relative; padding-bottom: 56.25%; height: 0; overflow: hidden; max-width: 100%; height: auto;">
  122. <iframe src="https://www.youtube-nocookie.com/embed/_gNOd7wQ62M" frameborder="0" allowfullscreen style="position: absolute; top: 0; left: 0; width: 100%; height: 100%;"></iframe>
  123. </div>
  124. Render model node
  125. -----------------
  126. The :ref:`OpenXRRenderModel<class_OpenXRRenderModel>` node implements
  127. all the logic to display and position a given render model provided by
  128. the render models API.
  129. Instances of this node are added by the render model manager node we used up
  130. above but you can interact with these directly if you wish.
  131. Whenever Godot obtains information about a new render model an RID is
  132. created to reference that render model.
  133. By assigning that RID to the ``render_model`` property on this node,
  134. the node will start displaying the render model and manage both the
  135. transform that places the render model in the correct place and
  136. animates all the sub objects.
  137. The ``get_top_level_path`` function will return the top level path
  138. associated with this render model. This will point to either the
  139. left or right hand. As the top level path can be set or cleared
  140. depending on whether the user picks up, or puts down, the controller
  141. you can connect to the ``render_model_top_level_path_changes`` signal
  142. and react to these changes.
  143. Depending on your setup of the
  144. :ref:`OpenXRRenderModelManager<class_OpenXRRenderModelManager>` nodes,
  145. render models will be removed or added as their top level path changes.
  146. Backend access
  147. --------------
  148. The nodes we've detailed out above handle all the display logic
  149. for us but it is possible to interact with the data that drives
  150. this directly and create your own implementation.
  151. For this you can access the
  152. :ref:`OpenXRRenderModelExtension<class_OpenXRRenderModelExtension>`
  153. singleton.
  154. This object also lets you query whether render models are
  155. supported and enabled on the device currently being used by
  156. calling the ``is_active`` function on this object.
  157. The built-in logic implements the
  158. `interaction render model API <https://registry.khronos.org/OpenXR/specs/1.1/html/xrspec.html#XR_EXT_interaction_render_model>`_
  159. that lists all render models related to controllers and similar
  160. devices that are present in the action map.
  161. It will automatically create and remove render model entities
  162. that are exposed through this API.
  163. As other extensions become available these can be implemented
  164. in a GDExtension plugin. Such a plugin can call
  165. ``render_model_create`` and ``render_model_destroy`` to
  166. create the object that will provide access to that render
  167. model through the core render models API.
  168. You should not destroy a render model outside of this logic.
  169. You can connect to the ``render_model_added`` and
  170. ``render_model_removed`` signals to be informed when new render
  171. models are added or removed.
  172. The core methods for working with this API are listed
  173. below:
  174. .. list-table:: Render modele extension functions
  175. :header-rows: 1
  176. * - Function
  177. - Description
  178. * - render_model_get_all
  179. - Provides an array of RIDs for all render models
  180. that are being tracked.
  181. * - render_model_new_scene_instance
  182. - Provides a new scene that contains all meshes
  183. needed to display the render model.
  184. * - render_model_get_subaction_paths
  185. - Provides a list of subaction paths from your
  186. action map related to this render mode.
  187. * - render_model_get_top_level_path
  188. - Returns the top level path associated with this
  189. render model (if any).
  190. Use the ``render_model_top_level_path_changed``
  191. signal to react to this changing.
  192. * - render_model_get_confidence
  193. - Returns the tracking confidence for the tracking
  194. data for this render model.
  195. * - render_model_get_root_transform
  196. - Returns the root transform for this render model
  197. within our current reference space. This can be
  198. used to place the render model in space.
  199. * - render_model_get_animatable_node_count
  200. - Returns the number of nodes in our render model
  201. scene that can be animated
  202. * - render_model_get_animatable_node_name
  203. - Returns the name of the node that we can animate.
  204. Note that this node can be any number of levels
  205. deep within the scene.
  206. * - render_model_is_animatable_node_visible
  207. - Returns true if this animatable node should be
  208. visible
  209. * - render_model_get_animatable_node_transform
  210. - Returns the transform for this animatable node.
  211. This is a local transform that can be directly
  212. applied.