1/**************************************************************************/
2/* openxr_interface.h */
3/**************************************************************************/
4/* This file is part of: */
5/* GODOT ENGINE */
6/* https://godotengine.org */
7/**************************************************************************/
8/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
9/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
10/* */
11/* Permission is hereby granted, free of charge, to any person obtaining */
12/* a copy of this software and associated documentation files (the */
13/* "Software"), to deal in the Software without restriction, including */
14/* without limitation the rights to use, copy, modify, merge, publish, */
15/* distribute, sublicense, and/or sell copies of the Software, and to */
16/* permit persons to whom the Software is furnished to do so, subject to */
17/* the following conditions: */
18/* */
19/* The above copyright notice and this permission notice shall be */
20/* included in all copies or substantial portions of the Software. */
21/* */
22/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
23/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
24/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
25/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
26/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
27/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
28/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
29/**************************************************************************/
30
31#ifndef OPENXR_INTERFACE_H
32#define OPENXR_INTERFACE_H
33
34#include "action_map/openxr_action_map.h"
35#include "extensions/openxr_fb_passthrough_extension_wrapper.h"
36#include "openxr_api.h"
37
38#include "servers/xr/xr_interface.h"
39#include "servers/xr/xr_positional_tracker.h"
40
41// declare some default strings
42#define INTERACTION_PROFILE_NONE "/interaction_profiles/none"
43
44class OpenXRInterface : public XRInterface {
45 GDCLASS(OpenXRInterface, XRInterface);
46
47private:
48 OpenXRAPI *openxr_api = nullptr;
49 bool initialized = false;
50 XRInterface::TrackingStatus tracking_state;
51 OpenXRFbPassthroughExtensionWrapper *passthrough_wrapper = nullptr;
52
53 // At a minimum we need a tracker for our head
54 Ref<XRPositionalTracker> head;
55 Transform3D head_transform;
56 Vector3 head_linear_velocity;
57 Vector3 head_angular_velocity;
58 Transform3D transform_for_view[2]; // We currently assume 2, but could be 4 for VARJO which we do not support yet
59
60 void _load_action_map();
61
62 struct Action { // An action we've registered with OpenXR
63 String action_name; // Name of our action as presented to Godot (can be altered from the action map)
64 OpenXRAction::ActionType action_type; // The action type of this action
65 RID action_rid; // RID of the action registered with our OpenXR API
66 };
67 struct ActionSet { // An action set we've registered with OpenXR
68 String action_set_name; // Name of our action set
69 bool is_active; // If true this action set is active and we will sync it
70 Vector<Action *> actions; // List of actions in this action set
71 RID action_set_rid; // RID of the action registered with our OpenXR API
72 };
73 struct Tracker { // A tracker we've registered with OpenXR
74 String tracker_name; // Name of our tracker (can be altered from the action map)
75 Vector<Action *> actions; // Actions related to this tracker
76 Ref<XRPositionalTracker> positional_tracker; // Our positional tracker object that holds our tracker state
77 RID tracker_rid; // RID of the tracker registered with our OpenXR API
78 RID interaction_profile; // RID of the interaction profile bound to this tracker (can be null)
79 };
80
81 Vector<ActionSet *> action_sets;
82 Vector<RID> interaction_profiles;
83 Vector<Tracker *> trackers;
84
85 ActionSet *create_action_set(const String &p_action_set_name, const String &p_localized_name, const int p_priority);
86 void free_action_sets();
87
88 Action *create_action(ActionSet *p_action_set, const String &p_action_name, const String &p_localized_name, OpenXRAction::ActionType p_action_type, const Vector<Tracker *> p_trackers);
89 Action *find_action(const String &p_action_name);
90 void free_actions(ActionSet *p_action_set);
91
92 Tracker *find_tracker(const String &p_tracker_name, bool p_create = false);
93 void handle_tracker(Tracker *p_tracker);
94 void free_trackers();
95
96 void free_interaction_profiles();
97
98 void _set_default_pos(Transform3D &p_transform, double p_world_scale, uint64_t p_eye);
99
100protected:
101 static void _bind_methods();
102
103public:
104 virtual StringName get_name() const override;
105 virtual uint32_t get_capabilities() const override;
106
107 virtual PackedStringArray get_suggested_tracker_names() const override;
108 virtual TrackingStatus get_tracking_status() const override;
109
110 bool initialize_on_startup() const;
111 virtual bool is_initialized() const override;
112 virtual bool initialize() override;
113 virtual void uninitialize() override;
114 virtual Dictionary get_system_info() override;
115
116 virtual void trigger_haptic_pulse(const String &p_action_name, const StringName &p_tracker_name, double p_frequency, double p_amplitude, double p_duration_sec, double p_delay_sec = 0) override;
117
118 virtual bool supports_play_area_mode(XRInterface::PlayAreaMode p_mode) override;
119 virtual XRInterface::PlayAreaMode get_play_area_mode() const override;
120 virtual bool set_play_area_mode(XRInterface::PlayAreaMode p_mode) override;
121
122 float get_display_refresh_rate() const;
123 void set_display_refresh_rate(float p_refresh_rate);
124 Array get_available_display_refresh_rates() const;
125
126 bool is_action_set_active(const String &p_action_set) const;
127 void set_action_set_active(const String &p_action_set, bool p_active);
128 Array get_action_sets() const;
129
130 double get_render_target_size_multiplier() const;
131 void set_render_target_size_multiplier(double multiplier);
132
133 virtual Size2 get_render_target_size() override;
134 virtual uint32_t get_view_count() override;
135 virtual Transform3D get_camera_transform() override;
136 virtual Transform3D get_transform_for_view(uint32_t p_view, const Transform3D &p_cam_transform) override;
137 virtual Projection get_projection_for_view(uint32_t p_view, double p_aspect, double p_z_near, double p_z_far) override;
138
139 virtual RID get_color_texture() override;
140 virtual RID get_depth_texture() override;
141
142 virtual void process() override;
143 virtual void pre_render() override;
144 bool pre_draw_viewport(RID p_render_target) override;
145 virtual Vector<BlitToScreen> post_draw_viewport(RID p_render_target, const Rect2 &p_screen_rect) override;
146 virtual void end_frame() override;
147
148 virtual bool is_passthrough_supported() override;
149 virtual bool is_passthrough_enabled() override;
150 virtual bool start_passthrough() override;
151 virtual void stop_passthrough() override;
152
153 /** environment blend mode. */
154 virtual Array get_supported_environment_blend_modes() override;
155 virtual XRInterface::EnvironmentBlendMode get_environment_blend_mode() const override;
156 virtual bool set_environment_blend_mode(XRInterface::EnvironmentBlendMode mode) override;
157
158 void on_state_ready();
159 void on_state_visible();
160 void on_state_focused();
161 void on_state_stopping();
162 void on_pose_recentered();
163 void tracker_profile_changed(RID p_tracker, RID p_interaction_profile);
164
165 /** Hand tracking. */
166 enum Hand {
167 HAND_LEFT,
168 HAND_RIGHT,
169 HAND_MAX,
170 };
171
172 enum HandMotionRange {
173 HAND_MOTION_RANGE_UNOBSTRUCTED,
174 HAND_MOTION_RANGE_CONFORM_TO_CONTROLLER,
175 HAND_MOTION_RANGE_MAX
176 };
177
178 void set_motion_range(const Hand p_hand, const HandMotionRange p_motion_range);
179 HandMotionRange get_motion_range(const Hand p_hand) const;
180
181 enum HandJoints {
182 HAND_JOINT_PALM = 0,
183 HAND_JOINT_WRIST = 1,
184 HAND_JOINT_THUMB_METACARPAL = 2,
185 HAND_JOINT_THUMB_PROXIMAL = 3,
186 HAND_JOINT_THUMB_DISTAL = 4,
187 HAND_JOINT_THUMB_TIP = 5,
188 HAND_JOINT_INDEX_METACARPAL = 6,
189 HAND_JOINT_INDEX_PROXIMAL = 7,
190 HAND_JOINT_INDEX_INTERMEDIATE = 8,
191 HAND_JOINT_INDEX_DISTAL = 9,
192 HAND_JOINT_INDEX_TIP = 10,
193 HAND_JOINT_MIDDLE_METACARPAL = 11,
194 HAND_JOINT_MIDDLE_PROXIMAL = 12,
195 HAND_JOINT_MIDDLE_INTERMEDIATE = 13,
196 HAND_JOINT_MIDDLE_DISTAL = 14,
197 HAND_JOINT_MIDDLE_TIP = 15,
198 HAND_JOINT_RING_METACARPAL = 16,
199 HAND_JOINT_RING_PROXIMAL = 17,
200 HAND_JOINT_RING_INTERMEDIATE = 18,
201 HAND_JOINT_RING_DISTAL = 19,
202 HAND_JOINT_RING_TIP = 20,
203 HAND_JOINT_LITTLE_METACARPAL = 21,
204 HAND_JOINT_LITTLE_PROXIMAL = 22,
205 HAND_JOINT_LITTLE_INTERMEDIATE = 23,
206 HAND_JOINT_LITTLE_DISTAL = 24,
207 HAND_JOINT_LITTLE_TIP = 25,
208 HAND_JOINT_MAX = 26,
209 };
210
211 Quaternion get_hand_joint_rotation(Hand p_hand, HandJoints p_joint) const;
212 Vector3 get_hand_joint_position(Hand p_hand, HandJoints p_joint) const;
213 float get_hand_joint_radius(Hand p_hand, HandJoints p_joint) const;
214
215 Vector3 get_hand_joint_linear_velocity(Hand p_hand, HandJoints p_joint) const;
216 Vector3 get_hand_joint_angular_velocity(Hand p_hand, HandJoints p_joint) const;
217
218 OpenXRInterface();
219 ~OpenXRInterface();
220};
221
222VARIANT_ENUM_CAST(OpenXRInterface::Hand)
223VARIANT_ENUM_CAST(OpenXRInterface::HandMotionRange)
224VARIANT_ENUM_CAST(OpenXRInterface::HandJoints)
225
226#endif // OPENXR_INTERFACE_H
227