Skip to content

Commit 4b818e3

Browse files
committed
OpenXR: Adding support for the render model extension
1 parent 46c495c commit 4b818e3

19 files changed

+1856
-1
lines changed

doc/classes/ProjectSettings.xml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3451,6 +3451,10 @@
34513451
If [code]true[/code], support for the unobstructed data source is requested. If supported, you will receive hand tracking data based on the actual finger positions of the user often determined by optical tracking.
34523452
[b]Note:[/b] This requires the OpenXR data source extension and unobstructed handtracking to be supported by the XR runtime. If not supported this setting will be ignored. [member xr/openxr/extensions/hand_tracking] must be enabled for this setting to be used.
34533453
</member>
3454+
<member name="xr/openxr/extensions/render_model" type="bool" setter="" getter="" default="false">
3455+
If [code]true[/code] we enable the render model extension if available.
3456+
[b]Note:[/b] This relates to the core OpenXR render model extension and has no relation to any vendor render model extensions.
3457+
</member>
34543458
<member name="xr/openxr/form_factor" type="int" setter="" getter="" default="&quot;0&quot;">
34553459
Specify whether OpenXR should be configured for an HMD or a hand held device.
34563460
</member>

main/main.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2771,6 +2771,7 @@ Error Main::setup(const char *execpath, int argc, char *argv[], bool p_second_ph
27712771
GLOBAL_DEF_BASIC("xr/openxr/extensions/hand_tracking_controller_data_source", false); // XR_HAND_TRACKING_DATA_SOURCE_CONTROLLER_EXT
27722772
GLOBAL_DEF_RST_BASIC("xr/openxr/extensions/hand_interaction_profile", false);
27732773
GLOBAL_DEF_RST_BASIC("xr/openxr/extensions/eye_gaze_interaction", false);
2774+
GLOBAL_DEF_BASIC("xr/openxr/extensions/render_model", false);
27742775

27752776
// OpenXR Binding modifier settings
27762777
GLOBAL_DEF_BASIC("xr/openxr/binding_modifiers/analog_threshold", false);

modules/openxr/config.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,9 @@ def get_doc_classes():
4040
"OpenXRBindingModifierEditor",
4141
"OpenXRHapticBase",
4242
"OpenXRHapticVibration",
43+
"OpenXRRenderModelExtension",
44+
"OpenXRRenderModel",
45+
"OpenXRRenderModelManager",
4346
]
4447

4548

modules/openxr/doc_classes/OpenXRExtensionWrapper.xml

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -185,6 +185,12 @@
185185
Called when the OpenXR session state is changed to visible. This means OpenXR is now ready to receive frames.
186186
</description>
187187
</method>
188+
<method name="_on_sync_actions" qualifiers="virtual">
189+
<return type="void" />
190+
<description>
191+
Called when OpenXR has performed its action sync.
192+
</description>
193+
</method>
188194
<method name="_on_viewport_composition_layer_destroyed" qualifiers="virtual">
189195
<return type="void" />
190196
<param index="0" name="layer" type="const void*" />
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
<?xml version="1.0" encoding="UTF-8" ?>
2+
<class name="OpenXRRenderModel" inherits="Node3D" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../doc/class.xsd">
3+
<brief_description>
4+
This node will display an OpenXR render model.
5+
</brief_description>
6+
<description>
7+
This node will display an OpenXR render model by accessing the associated GLTF and processes all animation data (if supported by the XR runtime).
8+
Render models were introduced to allow showing the correct model for the controller (or other device) the user has in hand, since the OpenXR action map does not provide information about the hardware used by the user. Note that while the controller (or device) can be somewhat inferred by the bound action map profile, this is a dangerous approach as the user may be using hardware not known at time of development and OpenXR will simply simulate an available interaction profile.
9+
</description>
10+
<tutorials>
11+
</tutorials>
12+
<methods>
13+
<method name="get_top_level_path" qualifiers="const">
14+
<return type="String" />
15+
<description>
16+
Returns the top level path related to this render model.
17+
</description>
18+
</method>
19+
</methods>
20+
<members>
21+
<member name="render_model" type="RID" setter="set_render_model" getter="get_render_model" default="RID()">
22+
The render model RID for the render model to load, as returned by [method OpenXRRenderModelExtension.render_model_create] or [method OpenXRRenderModelExtension.render_model_get_all].
23+
</member>
24+
</members>
25+
<signals>
26+
<signal name="render_model_top_level_path_changed">
27+
<description>
28+
Emitted when the top level path of this render model has changed.
29+
</description>
30+
</signal>
31+
</signals>
32+
</class>
Lines changed: 129 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,129 @@
1+
<?xml version="1.0" encoding="UTF-8" ?>
2+
<class name="OpenXRRenderModelExtension" inherits="OpenXRExtensionWrapper" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../doc/class.xsd">
3+
<brief_description>
4+
This class implements the OpenXR Render Model Extension.
5+
</brief_description>
6+
<description>
7+
This class implements the OpenXR Render Model Extension, if enabled it will maintain a list of active render models and provides an interface to the render model data.
8+
</description>
9+
<tutorials>
10+
</tutorials>
11+
<methods>
12+
<method name="is_active" qualifiers="const">
13+
<return type="bool" />
14+
<description>
15+
Returns [code]true[/code] if OpenXR's render model extension is supported and enabled.
16+
[b]Note:[/b] This only returns a valid value after OpenXR has been initialized.
17+
</description>
18+
</method>
19+
<method name="render_model_create">
20+
<return type="RID" />
21+
<param index="0" name="render_model_id" type="int" />
22+
<description>
23+
Creates a render model object within OpenXR using a render model id.
24+
[b]Note:[/b] This function is exposed for dependent OpenXR extensions that provide render model ids to be used with the render model extension.
25+
</description>
26+
</method>
27+
<method name="render_model_destroy">
28+
<return type="void" />
29+
<param index="0" name="render_model" type="RID" />
30+
<description>
31+
Destroys a render model object within OpenXR that was previously created with [method render_model_create].
32+
[b]Note:[/b] This function is exposed for dependent OpenXR extensions that provide render model ids to be used with the render model extension.
33+
</description>
34+
</method>
35+
<method name="render_model_get_all">
36+
<return type="RID[]" />
37+
<description>
38+
Returns an array of all currently active render models registered with this extension.
39+
</description>
40+
</method>
41+
<method name="render_model_get_animatable_node_count" qualifiers="const">
42+
<return type="int" />
43+
<param index="0" name="render_model" type="RID" />
44+
<description>
45+
Returns the number of animatable nodes this render model has.
46+
</description>
47+
</method>
48+
<method name="render_model_get_animatable_node_name" qualifiers="const">
49+
<return type="String" />
50+
<param index="0" name="render_model" type="RID" />
51+
<param index="1" name="index" type="int" />
52+
<description>
53+
Returns the name of the given animatable node.
54+
</description>
55+
</method>
56+
<method name="render_model_get_animatable_node_transform" qualifiers="const">
57+
<return type="Transform3D" />
58+
<param index="0" name="render_model" type="RID" />
59+
<param index="1" name="index" type="int" />
60+
<description>
61+
Returns the current local transform for an animatable node. This is updated every frame.
62+
</description>
63+
</method>
64+
<method name="render_model_get_confidence" qualifiers="const">
65+
<return type="int" enum="XRPose.TrackingConfidence" />
66+
<param index="0" name="render_model" type="RID" />
67+
<description>
68+
Returns the tracking confidence of the tracking data for the render model.
69+
</description>
70+
</method>
71+
<method name="render_model_get_root_transform" qualifiers="const">
72+
<return type="Transform3D" />
73+
<param index="0" name="render_model" type="RID" />
74+
<description>
75+
Returns the root transform of a render model. This is the tracked position relative to our [XROrigin3D] node.
76+
</description>
77+
</method>
78+
<method name="render_model_get_subaction_paths">
79+
<return type="PackedStringArray" />
80+
<param index="0" name="render_model" type="RID" />
81+
<description>
82+
Returns a list of active subaction paths for this [param render_model].
83+
[b]Note:[/b] If different devices are bound to your actions than available in suggested interaction bindings, this information shows paths related to the interaction bindings being mimicked by that device.
84+
</description>
85+
</method>
86+
<method name="render_model_get_top_level_path" qualifiers="const">
87+
<return type="String" />
88+
<param index="0" name="render_model" type="RID" />
89+
<description>
90+
Returns the top level path associated with this [param render_model]. If provided this identifies whether the render model is associated with the players hands or other body part.
91+
</description>
92+
</method>
93+
<method name="render_model_is_animatable_node_visible" qualifiers="const">
94+
<return type="bool" />
95+
<param index="0" name="render_model" type="RID" />
96+
<param index="1" name="index" type="int" />
97+
<description>
98+
Returns [code]true[/code] if this animatable node should be visible.
99+
</description>
100+
</method>
101+
<method name="render_model_new_scene_instance" qualifiers="const">
102+
<return type="Node3D" />
103+
<param index="0" name="render_model" type="RID" />
104+
<description>
105+
Returns an instance of a subscene that contains all [MeshInstance3D] nodes that allow you to visualize the render model.
106+
</description>
107+
</method>
108+
</methods>
109+
<signals>
110+
<signal name="render_model_added">
111+
<param index="0" name="render_model" type="RID" />
112+
<description>
113+
Emitted when a new render model is added.
114+
</description>
115+
</signal>
116+
<signal name="render_model_removed">
117+
<param index="0" name="render_model" type="RID" />
118+
<description>
119+
Emitted when a render model is removed.
120+
</description>
121+
</signal>
122+
<signal name="render_model_top_level_path_changed">
123+
<param index="0" name="render_model" type="RID" />
124+
<description>
125+
Emitted when the top level path associated with a render model changed.
126+
</description>
127+
</signal>
128+
</signals>
129+
</class>
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
<?xml version="1.0" encoding="UTF-8" ?>
2+
<class name="OpenXRRenderModelManager" inherits="Node3D" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../doc/class.xsd">
3+
<brief_description>
4+
Helper node that will automatically manage displaying render models.
5+
</brief_description>
6+
<description>
7+
This helper node will automatically manage displaying render models. It will create new [OpenXRRenderModel] nodes as controllers and other hand held devices are detected, and remove those nodes when they are deactivated.
8+
[b]Note:[/b] If you want more control over this logic you can alternatively call [method OpenXRRenderModelExtension.render_model_get_all] to obtain a list of active render model ids and create [OpenXRRenderModel] instances for each render model id provided.
9+
</description>
10+
<tutorials>
11+
</tutorials>
12+
<members>
13+
<member name="make_local_to_pose" type="String" setter="set_make_local_to_pose" getter="get_make_local_to_pose" default="&quot;&quot;">
14+
Position render models local to this pose (this will adjust the position of the render models container node).
15+
</member>
16+
<member name="tracker" type="int" setter="set_tracker" getter="get_tracker" enum="OpenXRRenderModelManager.RenderModelTracker" default="0">
17+
Limits render models to the specified tracker. Include: 0 = All render models, 1 = Render models not related to a tracker, 2 = Render models related to the left hand tracker, 3 = Render models related to the right hand tracker.
18+
</member>
19+
</members>
20+
<signals>
21+
<signal name="render_model_added">
22+
<param index="0" name="render_model" type="OpenXRRenderModel" />
23+
<description>
24+
Emitted when a render model node is added as a child to this node.
25+
</description>
26+
</signal>
27+
<signal name="render_model_removed">
28+
<param index="0" name="render_model" type="OpenXRRenderModel" />
29+
<description>
30+
Emitted when a render model child node is about to be removed from this node.
31+
</description>
32+
</signal>
33+
</signals>
34+
<constants>
35+
<constant name="RENDER_MODEL_TRACKER_ANY" value="0" enum="RenderModelTracker">
36+
All active render models are shown regardless of what tracker they relate to.
37+
</constant>
38+
<constant name="RENDER_MODEL_TRACKER_NONE_SET" value="1" enum="RenderModelTracker">
39+
Only active render models are shown that are not related to any tracker we manage.
40+
</constant>
41+
<constant name="RENDER_MODEL_TRACKER_LEFT_HAND" value="2" enum="RenderModelTracker">
42+
Only active render models are shown that are related to the left hand tracker.
43+
</constant>
44+
<constant name="RENDER_MODEL_TRACKER_RIGHT_HAND" value="3" enum="RenderModelTracker">
45+
Only active render models are shown that are related to the right hand tracker.
46+
</constant>
47+
</constants>
48+
</class>

modules/openxr/extensions/openxr_extension_wrapper.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,7 @@ void OpenXRExtensionWrapper::_bind_methods() {
5555
GDVIRTUAL_BIND(_on_instance_destroyed);
5656
GDVIRTUAL_BIND(_on_session_created, "session");
5757
GDVIRTUAL_BIND(_on_process);
58+
GDVIRTUAL_BIND(_on_sync_actions);
5859
GDVIRTUAL_BIND(_on_pre_render);
5960
GDVIRTUAL_BIND(_on_main_swapchains_created);
6061
GDVIRTUAL_BIND(_on_pre_draw_viewport, "viewport");
@@ -252,6 +253,10 @@ void OpenXRExtensionWrapper::on_process() {
252253
GDVIRTUAL_CALL(_on_process);
253254
}
254255

256+
void OpenXRExtensionWrapper::on_sync_actions() {
257+
GDVIRTUAL_CALL(_on_sync_actions);
258+
}
259+
255260
void OpenXRExtensionWrapper::on_pre_render() {
256261
GDVIRTUAL_CALL(_on_pre_render);
257262
}

modules/openxr/extensions/openxr_extension_wrapper.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -120,6 +120,7 @@ class OpenXRExtensionWrapper : public Object {
120120
// this happens right before physics process and normal processing is run.
121121
// This is when controller data is queried and made available to game logic.
122122
virtual void on_process();
123+
virtual void on_sync_actions(); // `on_sync_actions` is called right after we sync our action sets.
123124
virtual void on_pre_render(); // `on_pre_render` is called right before we start rendering our XR viewports.
124125
virtual void on_main_swapchains_created(); // `on_main_swapchains_created` is called right after our main swapchains are (re)created.
125126
virtual void on_pre_draw_viewport(RID p_render_target); // `on_pre_draw_viewport` is called right before we start rendering this viewport
@@ -131,6 +132,7 @@ class OpenXRExtensionWrapper : public Object {
131132
GDVIRTUAL0(_on_instance_destroyed);
132133
GDVIRTUAL1(_on_session_created, uint64_t);
133134
GDVIRTUAL0(_on_process);
135+
GDVIRTUAL0(_on_sync_actions);
134136
GDVIRTUAL0(_on_pre_render);
135137
GDVIRTUAL0(_on_main_swapchains_created);
136138
GDVIRTUAL0(_on_session_destroyed);

0 commit comments

Comments
 (0)