Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
godotengine
GitHub Repository: godotengine/godot
Path: blob/master/servers/xr_server.h
9887 views
1
/**************************************************************************/
2
/* xr_server.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
#pragma once
32
33
#include "core/object/ref_counted.h"
34
#include "core/os/thread_safe.h"
35
#include "core/variant/variant.h"
36
#include "rendering_server.h"
37
38
class XRInterface;
39
class XRTracker;
40
class XRPositionalTracker;
41
42
/**
43
The XR server is a singleton object that gives access to the various
44
objects and SDKs that are available on the system.
45
Because there can be multiple SDKs active this is exposed as an array
46
and our XR server object acts as a pass through
47
Also each positioning tracker is accessible from here.
48
49
I've added some additional info into this header file that should move
50
into the documentation, I will do so when we're close to accepting this PR
51
or as a separate PR once this has been merged into the master branch.
52
**/
53
54
class XRServer : public Object {
55
GDCLASS(XRServer, Object);
56
_THREAD_SAFE_CLASS_
57
58
public:
59
enum XRMode {
60
XRMODE_DEFAULT, /* Default behavior, means we check project settings */
61
XRMODE_OFF, /* Ignore project settings, disable OpenXR, disable shaders */
62
XRMODE_ON, /* Ignore project settings, enable OpenXR, enable shaders, run editor in VR (if applicable) */
63
};
64
65
enum TrackerType {
66
TRACKER_HEAD = 0x01, /* tracks the position of the players head (or in case of handheld AR, location of the phone) */
67
TRACKER_CONTROLLER = 0x02, /* tracks a controller */
68
TRACKER_BASESTATION = 0x04, /* tracks location of a base station */
69
TRACKER_ANCHOR = 0x08, /* tracks an anchor point, used in AR to track a real live location */
70
TRACKER_HAND = 0x10, /* tracks a hand */
71
TRACKER_BODY = 0x20, /* tracks a body */
72
TRACKER_FACE = 0x40, /* tracks a face */
73
TRACKER_UNKNOWN = 0x80, /* unknown tracker */
74
75
TRACKER_ANY_KNOWN = 0x7f, /* all except unknown */
76
TRACKER_ANY = 0xff /* used by get_connected_trackers to return all types */
77
};
78
79
enum RotationMode {
80
RESET_FULL_ROTATION = 0, /* we reset the full rotation, regardless of how the HMD is oriented, we're looking dead ahead */
81
RESET_BUT_KEEP_TILT = 1, /* reset rotation but keep tilt. */
82
DONT_RESET_ROTATION = 2, /* don't reset the rotation, we will only center on position */
83
};
84
85
private:
86
static XRMode xr_mode;
87
88
Vector<Ref<XRInterface>> interfaces;
89
Dictionary trackers;
90
91
Ref<XRInterface> primary_interface; /* we'll identify one interface as primary, this will be used by our viewports */
92
93
double world_scale = 1.0; /* scale by which we multiply our tracker positions */
94
Transform3D world_origin; /* our world origin point, maps a location in our virtual world to the origin point in our real world tracking volume */
95
Transform3D reference_frame; /* our reference frame */
96
bool camera_locked_to_origin = false;
97
98
// As we may be updating our main state for our next frame while we're still rendering our previous frame,
99
// we need to keep copies around.
100
struct RenderState {
101
double world_scale = 1.0; /* scale by which we multiply our tracker positions */
102
Transform3D world_origin; /* our world origin point, maps a location in our virtual world to the origin point in our real world tracking volume */
103
Transform3D reference_frame; /* our reference frame */
104
} render_state;
105
106
static void _set_render_world_scale(double p_world_scale);
107
static void _set_render_world_origin(const Transform3D &p_world_origin);
108
static void _set_render_reference_frame(const Transform3D &p_reference_frame);
109
110
_FORCE_INLINE_ void set_render_world_scale(double p_world_scale) {
111
// If we're rendering on a separate thread, we may still be processing the last frame, don't communicate this till we're ready...
112
RenderingServer *rendering_server = RenderingServer::get_singleton();
113
ERR_FAIL_NULL(rendering_server);
114
115
rendering_server->call_on_render_thread(callable_mp_static(&XRServer::_set_render_world_scale).bind(p_world_scale));
116
}
117
118
_FORCE_INLINE_ void set_render_world_origin(const Transform3D &p_world_origin) {
119
// If we're rendering on a separate thread, we may still be processing the last frame, don't communicate this till we're ready...
120
RenderingServer *rendering_server = RenderingServer::get_singleton();
121
ERR_FAIL_NULL(rendering_server);
122
123
rendering_server->call_on_render_thread(callable_mp_static(&XRServer::_set_render_world_origin).bind(p_world_origin));
124
}
125
126
_FORCE_INLINE_ void set_render_reference_frame(const Transform3D &p_reference_frame) {
127
// If we're rendering on a separate thread, we may still be processing the last frame, don't communicate this till we're ready...
128
RenderingServer *rendering_server = RenderingServer::get_singleton();
129
ERR_FAIL_NULL(rendering_server);
130
131
rendering_server->call_on_render_thread(callable_mp_static(&XRServer::_set_render_reference_frame).bind(p_reference_frame));
132
}
133
134
protected:
135
static XRServer *singleton;
136
137
static void _bind_methods();
138
139
#ifndef DISABLE_DEPRECATED
140
static void _bind_compatibility_methods();
141
void _add_tracker_bind_compat_90645(const Ref<XRPositionalTracker> &p_tracker);
142
void _remove_tracker_bind_compat_90645(const Ref<XRPositionalTracker> &p_tracker);
143
Ref<XRPositionalTracker> _get_tracker_bind_compat_90645(const StringName &p_name) const;
144
#endif
145
146
public:
147
static XRMode get_xr_mode();
148
static void set_xr_mode(XRMode p_mode);
149
150
static XRServer *get_singleton();
151
152
/*
153
World scale allows you to specify a scale factor that is applied to all positioning vectors in our VR world in essence scaling up, or scaling down the world.
154
For stereoscopic rendering specifically this is very important to give an accurate sense of scale.
155
Add controllers into the mix and an accurate mapping of real world movement to perceived virtual movement becomes very important.
156
157
Most VR platforms, and our assumption, is that 1 unit in our virtual world equates to 1 meter in the real mode.
158
This scale basically effects the unit size relationship to real world size.
159
160
I may remove access to this property in GDScript in favor of exposing it on the XROrigin3D node
161
*/
162
double get_world_scale() const;
163
void set_world_scale(double p_world_scale);
164
165
/*
166
The world maps the 0,0,0 coordinate of our real world coordinate system for our tracking volume to a location in our
167
virtual world. It is this origin point that should be moved when the player is moved through the world by controller
168
actions be it straffing, teleporting, etc. Movement of the player by moving through the physical space is always tracked
169
in relation to this point.
170
171
Note that the XROrigin3D spatial node in your scene automatically updates this property and it should be used instead of
172
direct access to this property and it therefore is not available in GDScript
173
174
Note: this should not be used in AR and should be ignored by an AR based interface as it would throw what you're looking at in the real world
175
and in the virtual world out of sync
176
*/
177
Transform3D get_world_origin() const;
178
void set_world_origin(const Transform3D &p_world_origin);
179
180
/*
181
center_on_hmd calculates a new reference frame. This ensures the HMD is positioned to 0,0,0 facing 0,0,-1 (need to verify this direction)
182
in the virtual world.
183
184
You can ignore the tilt of the device ensuring you're looking straight forward even if the player is looking down or sideways.
185
You can chose to keep the height the tracking provides which is important for room scale capable tracking.
186
187
Note: this should not be used in AR and should be ignored by an AR based interface as it would throw what you're looking at in the real world
188
and in the virtual world out of sync
189
*/
190
Transform3D get_reference_frame() const;
191
void clear_reference_frame();
192
void center_on_hmd(RotationMode p_rotation_mode, bool p_keep_height);
193
194
/*
195
get_hmd_transform gets our hmd transform (centered between eyes) with most up to date tracking, relative to the origin
196
*/
197
Transform3D get_hmd_transform();
198
199
void set_camera_locked_to_origin(bool p_enable);
200
inline bool is_camera_locked_to_origin() const { return camera_locked_to_origin; }
201
202
/*
203
Interfaces are objects that 'glue' Godot to an AR or VR SDK such as the Oculus SDK, OpenVR, OpenHMD, etc.
204
*/
205
void add_interface(const Ref<XRInterface> &p_interface);
206
void remove_interface(const Ref<XRInterface> &p_interface);
207
int get_interface_count() const;
208
Ref<XRInterface> get_interface(int p_index) const;
209
Ref<XRInterface> find_interface(const String &p_name) const;
210
TypedArray<Dictionary> get_interfaces() const;
211
212
/*
213
note, more then one interface can technically be active, especially on mobile, but only one interface is used for
214
rendering. This interface identifies itself by calling set_primary_interface when it is initialized
215
*/
216
Ref<XRInterface> get_primary_interface() const;
217
void set_primary_interface(const Ref<XRInterface> &p_primary_interface);
218
219
/*
220
Our trackers are objects that expose tracked information about physical objects such as controller, anchor points, faces, hands etc.
221
They are created and managed by our active AR/VR interfaces.
222
*/
223
void add_tracker(const Ref<XRTracker> &p_tracker);
224
void remove_tracker(const Ref<XRTracker> &p_tracker);
225
Dictionary get_trackers(int p_tracker_types);
226
Ref<XRTracker> get_tracker(const StringName &p_name) const;
227
228
/*
229
We don't know which trackers and actions will existing during runtime but we can request suggested names from our interfaces to help our IDE UI.
230
*/
231
PackedStringArray get_suggested_tracker_names() const;
232
PackedStringArray get_suggested_pose_names(const StringName &p_tracker_name) const;
233
// Q: Should we add get_suggested_input_names and get_suggested_haptic_names even though we don't use them for the IDE?
234
235
// Process is called before we handle our physics process and game process. This is where our interfaces will update controller data and such.
236
void _process();
237
238
// Pre-render is called right before we're rendering our viewports.
239
// This is where interfaces such as OpenVR and OpenXR will update positioning data.
240
// Many of these interfaces will also do a predictive sync which ensures we run at a steady framerate.
241
void pre_render();
242
243
// End-frame is called right after Godot has finished its rendering bits.
244
void end_frame();
245
246
XRServer();
247
~XRServer();
248
};
249
250
#define XR XRServer
251
252
VARIANT_ENUM_CAST(XRServer::TrackerType);
253
VARIANT_ENUM_CAST(XRServer::RotationMode);
254
255