summaryrefslogtreecommitdiff
path: root/servers/xr
diff options
context:
space:
mode:
Diffstat (limited to 'servers/xr')
-rw-r--r--servers/xr/xr_interface.cpp67
-rw-r--r--servers/xr/xr_interface.h33
-rw-r--r--servers/xr/xr_interface_extension.cpp70
-rw-r--r--servers/xr/xr_interface_extension.h19
-rw-r--r--servers/xr/xr_pose.cpp110
-rw-r--r--servers/xr/xr_pose.h68
-rw-r--r--servers/xr/xr_positional_tracker.cpp247
-rw-r--r--servers/xr/xr_positional_tracker.h42
8 files changed, 487 insertions, 169 deletions
diff --git a/servers/xr/xr_interface.cpp b/servers/xr/xr_interface.cpp
index bf54158905..ca11df439c 100644
--- a/servers/xr/xr_interface.cpp
+++ b/servers/xr/xr_interface.cpp
@@ -32,6 +32,8 @@
// #include "servers/rendering/renderer_compositor.h"
void XRInterface::_bind_methods() {
+ ADD_SIGNAL(MethodInfo("play_area_changed", PropertyInfo(Variant::INT, "mode")));
+
ClassDB::bind_method(D_METHOD("get_name"), &XRInterface::get_name);
ClassDB::bind_method(D_METHOD("get_capabilities"), &XRInterface::get_capabilities);
@@ -47,12 +49,21 @@ void XRInterface::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_render_target_size"), &XRInterface::get_render_target_size);
ClassDB::bind_method(D_METHOD("get_view_count"), &XRInterface::get_view_count);
+ ClassDB::bind_method(D_METHOD("trigger_haptic_pulse", "action_name", "tracker_name", "frequency", "amplitude", "duration_sec", "delay_sec"), &XRInterface::trigger_haptic_pulse);
+
ADD_GROUP("Interface", "interface_");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "interface_is_primary"), "set_primary", "is_primary");
- // we don't have any properties specific to VR yet....
+ // methods and properties specific to VR...
+ ClassDB::bind_method(D_METHOD("supports_play_area_mode", "mode"), &XRInterface::supports_play_area_mode);
+ ClassDB::bind_method(D_METHOD("get_play_area_mode"), &XRInterface::get_play_area_mode);
+ ClassDB::bind_method(D_METHOD("set_play_area_mode", "mode"), &XRInterface::set_play_area_mode);
+ ClassDB::bind_method(D_METHOD("get_play_area"), &XRInterface::get_play_area);
+
+ ADD_GROUP("XR", "xr_");
+ ADD_PROPERTY(PropertyInfo(Variant::INT, "xr_play_area_mode", PROPERTY_HINT_ENUM, "Unknown,3DOF,Sitting,Roomscale,Stage"), "set_play_area_mode", "get_play_area_mode");
- // but we do have properties specific to AR....
+ // methods and properties specific to AR....
ClassDB::bind_method(D_METHOD("get_anchor_detection_is_enabled"), &XRInterface::get_anchor_detection_is_enabled);
ClassDB::bind_method(D_METHOD("set_anchor_detection_is_enabled", "enable"), &XRInterface::set_anchor_detection_is_enabled);
ClassDB::bind_method(D_METHOD("get_camera_feed_id"), &XRInterface::get_camera_feed_id);
@@ -63,19 +74,23 @@ void XRInterface::_bind_methods() {
BIND_ENUM_CONSTANT(XR_NONE);
BIND_ENUM_CONSTANT(XR_MONO);
BIND_ENUM_CONSTANT(XR_STEREO);
+ BIND_ENUM_CONSTANT(XR_QUAD);
+ BIND_ENUM_CONSTANT(XR_VR);
BIND_ENUM_CONSTANT(XR_AR);
BIND_ENUM_CONSTANT(XR_EXTERNAL);
- BIND_ENUM_CONSTANT(EYE_MONO);
- BIND_ENUM_CONSTANT(EYE_LEFT);
- BIND_ENUM_CONSTANT(EYE_RIGHT);
-
BIND_ENUM_CONSTANT(XR_NORMAL_TRACKING);
BIND_ENUM_CONSTANT(XR_EXCESSIVE_MOTION);
BIND_ENUM_CONSTANT(XR_INSUFFICIENT_FEATURES);
BIND_ENUM_CONSTANT(XR_UNKNOWN_TRACKING);
BIND_ENUM_CONSTANT(XR_NOT_TRACKING);
-}
+
+ BIND_ENUM_CONSTANT(XR_PLAY_AREA_UNKNOWN);
+ BIND_ENUM_CONSTANT(XR_PLAY_AREA_3DOF);
+ BIND_ENUM_CONSTANT(XR_PLAY_AREA_SITTING);
+ BIND_ENUM_CONSTANT(XR_PLAY_AREA_ROOMSCALE);
+ BIND_ENUM_CONSTANT(XR_PLAY_AREA_STAGE);
+};
bool XRInterface::is_primary() {
XRServer *xr_server = XRServer::get_singleton();
@@ -101,6 +116,29 @@ XRInterface::XRInterface() {}
XRInterface::~XRInterface() {}
+// query if this interface supports this play area mode
+bool XRInterface::supports_play_area_mode(XRInterface::PlayAreaMode p_mode) {
+ return p_mode == XR_PLAY_AREA_UNKNOWN;
+}
+
+// get the current play area mode
+XRInterface::PlayAreaMode XRInterface::get_play_area_mode() const {
+ return XR_PLAY_AREA_UNKNOWN;
+}
+
+// change the play area mode, note that this should return false if the mode is not available
+bool XRInterface::set_play_area_mode(XRInterface::PlayAreaMode p_mode) {
+ return p_mode == XR_PLAY_AREA_UNKNOWN;
+}
+
+// if available, returns an array of vectors denoting the play area the player can move around in
+PackedVector3Array XRInterface::get_play_area() const {
+ // Return an empty array by default.
+ // Note implementation is responsible for applying our reference frame and world scale to the raw data.
+ // `play_area_changed` should be emitted if play area data is available and either the reference frame or world scale changes.
+ return PackedVector3Array();
+};
+
/** these will only be implemented on AR interfaces, so we want dummies for VR **/
bool XRInterface::get_anchor_detection_is_enabled() const {
return false;
@@ -114,9 +152,24 @@ int XRInterface::get_camera_feed_id() {
}
/** these are optional, so we want dummies **/
+PackedStringArray XRInterface::get_suggested_tracker_names() const {
+ PackedStringArray arr;
+
+ return arr;
+}
+
+PackedStringArray XRInterface::get_suggested_pose_names(const StringName &p_tracker_name) const {
+ PackedStringArray arr;
+
+ return arr;
+}
+
XRInterface::TrackingStatus XRInterface::get_tracking_status() const {
return XR_UNKNOWN_TRACKING;
}
void XRInterface::notification(int p_what) {
}
+
+void XRInterface::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) {
+}
diff --git a/servers/xr/xr_interface.h b/servers/xr/xr_interface.h
index 534fa18d8a..b489481f75 100644
--- a/servers/xr/xr_interface.h
+++ b/servers/xr/xr_interface.h
@@ -58,14 +58,10 @@ public:
XR_NONE = 0, /* no capabilities */
XR_MONO = 1, /* can be used with mono output */
XR_STEREO = 2, /* can be used with stereo output */
- XR_AR = 4, /* offers a camera feed for AR */
- XR_EXTERNAL = 8 /* renders to external device */
- };
-
- enum Eyes {
- EYE_MONO, /* my son says we should call this EYE_CYCLOPS */
- EYE_LEFT,
- EYE_RIGHT
+ XR_QUAD = 4, /* can be used with quad output (not currently supported) */
+ XR_VR = 8, /* offers VR support */
+ XR_AR = 16, /* offers AR support */
+ XR_EXTERNAL = 32 /* renders to external device */
};
enum TrackingStatus { /* tracking status currently based on AR but we can start doing more with this for VR as well */
@@ -76,7 +72,14 @@ public:
XR_NOT_TRACKING
};
-private:
+ enum PlayAreaMode { /* defines the mode used by the XR interface for tracking */
+ XR_PLAY_AREA_UNKNOWN, /* Area mode not set or not available */
+ XR_PLAY_AREA_3DOF, /* Only support orientation tracking, no positional tracking, area will center around player */
+ XR_PLAY_AREA_SITTING, /* Player is in seated position, limited positional tracking, fixed guardian around player */
+ XR_PLAY_AREA_ROOMSCALE, /* Player is free to move around, full positional tracking */
+ XR_PLAY_AREA_STAGE, /* Same as roomscale but origin point is fixed to the center of the physical space, XRServer.center_on_hmd disabled */
+ };
+
protected:
_THREAD_SAFE_CLASS_
@@ -94,10 +97,18 @@ public:
virtual bool initialize() = 0; /* initialize this interface, if this has an HMD it becomes the primary interface */
virtual void uninitialize() = 0; /* deinitialize this interface */
+ /** input and output **/
+
+ virtual PackedStringArray get_suggested_tracker_names() const; /* return a list of likely/suggested tracker names */
+ virtual PackedStringArray get_suggested_pose_names(const StringName &p_tracker_name) const; /* return a list of likely/suggested action names for this tracker */
virtual TrackingStatus get_tracking_status() const; /* get the status of our current tracking */
+ 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); /* trigger a haptic pulse */
/** specific to VR **/
- // nothing yet
+ virtual bool supports_play_area_mode(XRInterface::PlayAreaMode p_mode); /* query if this interface supports this play area mode */
+ virtual XRInterface::PlayAreaMode get_play_area_mode() const; /* get the current play area mode */
+ virtual bool set_play_area_mode(XRInterface::PlayAreaMode p_mode); /* change the play area mode, note that this should return false if the mode is not available */
+ virtual PackedVector3Array get_play_area() const; /* if available, returns an array of vectors denoting the play area the player can move around in */
/** specific to AR **/
virtual bool get_anchor_detection_is_enabled() const;
@@ -124,7 +135,7 @@ public:
};
VARIANT_ENUM_CAST(XRInterface::Capabilities);
-VARIANT_ENUM_CAST(XRInterface::Eyes);
VARIANT_ENUM_CAST(XRInterface::TrackingStatus);
+VARIANT_ENUM_CAST(XRInterface::PlayAreaMode);
#endif // !XR_INTERFACE_H
diff --git a/servers/xr/xr_interface_extension.cpp b/servers/xr/xr_interface_extension.cpp
index 7fdf90770d..341ba32245 100644
--- a/servers/xr/xr_interface_extension.cpp
+++ b/servers/xr/xr_interface_extension.cpp
@@ -43,6 +43,11 @@ void XRInterfaceExtension::_bind_methods() {
GDVIRTUAL_BIND(_get_tracking_status);
+ GDVIRTUAL_BIND(_supports_play_area_mode, "mode");
+ GDVIRTUAL_BIND(_get_play_area_mode);
+ GDVIRTUAL_BIND(_set_play_area_mode, "mode");
+ GDVIRTUAL_BIND(_get_play_area);
+
GDVIRTUAL_BIND(_get_render_target_size);
GDVIRTUAL_BIND(_get_view_count);
GDVIRTUAL_BIND(_get_camera_transform);
@@ -54,6 +59,13 @@ void XRInterfaceExtension::_bind_methods() {
GDVIRTUAL_BIND(_process);
GDVIRTUAL_BIND(_notification, "what");
+ /** input and output **/
+
+ GDVIRTUAL_BIND(_get_suggested_tracker_names);
+ GDVIRTUAL_BIND(_get_suggested_pose_names, "tracker_name");
+ GDVIRTUAL_BIND(_get_tracking_status);
+ GDVIRTUAL_BIND(_trigger_haptic_pulse, "action_name", "tracker_name", "frequency", "amplitude", "duration_sec", "delay_sec");
+
// we don't have any properties specific to VR yet....
// but we do have properties specific to AR....
@@ -111,6 +123,22 @@ void XRInterfaceExtension::uninitialize() {
GDVIRTUAL_CALL(_uninitialize);
}
+PackedStringArray XRInterfaceExtension::get_suggested_tracker_names() const {
+ PackedStringArray arr;
+
+ GDVIRTUAL_CALL(_get_suggested_tracker_names, arr);
+
+ return arr;
+}
+
+PackedStringArray XRInterfaceExtension::get_suggested_pose_names(const StringName &p_tracker_name) const {
+ PackedStringArray arr;
+
+ GDVIRTUAL_CALL(_get_suggested_pose_names, p_tracker_name, arr);
+
+ return arr;
+}
+
XRInterface::TrackingStatus XRInterfaceExtension::get_tracking_status() const {
uint32_t status;
@@ -121,6 +149,48 @@ XRInterface::TrackingStatus XRInterfaceExtension::get_tracking_status() const {
return XR_UNKNOWN_TRACKING;
}
+void XRInterfaceExtension::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) {
+ GDVIRTUAL_CALL(_trigger_haptic_pulse, p_action_name, p_tracker_name, p_frequency, p_amplitude, p_duration_sec, p_delay_sec);
+}
+
+bool XRInterfaceExtension::supports_play_area_mode(XRInterface::PlayAreaMode p_mode) {
+ bool is_supported;
+
+ if (GDVIRTUAL_CALL(_supports_play_area_mode, p_mode, is_supported)) {
+ return is_supported;
+ }
+
+ return false;
+}
+
+XRInterface::PlayAreaMode XRInterfaceExtension::get_play_area_mode() const {
+ uint32_t mode;
+
+ if (GDVIRTUAL_CALL(_get_play_area_mode, mode)) {
+ return XRInterface::PlayAreaMode(mode);
+ }
+
+ return XRInterface::XR_PLAY_AREA_UNKNOWN;
+}
+
+bool XRInterfaceExtension::set_play_area_mode(XRInterface::PlayAreaMode p_mode) {
+ bool success;
+
+ if (GDVIRTUAL_CALL(_set_play_area_mode, p_mode, success)) {
+ return success;
+ }
+
+ return false;
+}
+
+PackedVector3Array XRInterfaceExtension::get_play_area() const {
+ PackedVector3Array arr;
+
+ GDVIRTUAL_CALL(_get_play_area, arr);
+
+ return arr;
+}
+
/** these will only be implemented on AR interfaces, so we want dummies for VR **/
bool XRInterfaceExtension::get_anchor_detection_is_enabled() const {
bool enabled;
diff --git a/servers/xr/xr_interface_extension.h b/servers/xr/xr_interface_extension.h
index 3b7af4c0a2..763526de96 100644
--- a/servers/xr/xr_interface_extension.h
+++ b/servers/xr/xr_interface_extension.h
@@ -62,11 +62,28 @@ public:
GDVIRTUAL0R(bool, _initialize);
GDVIRTUAL0(_uninitialize);
+ /** input and output **/
+
+ virtual PackedStringArray get_suggested_tracker_names() const override; /* return a list of likely/suggested tracker names */
+ virtual PackedStringArray get_suggested_pose_names(const StringName &p_tracker_name) const override; /* return a list of likely/suggested action names for this tracker */
virtual TrackingStatus get_tracking_status() const override;
+ 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;
+
+ GDVIRTUAL0RC(PackedStringArray, _get_suggested_tracker_names);
+ GDVIRTUAL1RC(PackedStringArray, _get_suggested_pose_names, const StringName &);
GDVIRTUAL0RC(uint32_t, _get_tracking_status);
+ GDVIRTUAL6(_trigger_haptic_pulse, const String &, const StringName &, double, double, double, double);
/** specific to VR **/
- // nothing yet
+ virtual bool supports_play_area_mode(XRInterface::PlayAreaMode p_mode) override; /* query if this interface supports this play area mode */
+ virtual XRInterface::PlayAreaMode get_play_area_mode() const override; /* get the current play area mode */
+ virtual bool set_play_area_mode(XRInterface::PlayAreaMode p_mode) override; /* change the play area mode, note that this should return false if the mode is not available */
+ virtual PackedVector3Array get_play_area() const override; /* if available, returns an array of vectors denoting the play area the player can move around in */
+
+ GDVIRTUAL1RC(bool, _supports_play_area_mode, XRInterface::PlayAreaMode);
+ GDVIRTUAL0RC(uint32_t, _get_play_area_mode);
+ GDVIRTUAL1RC(bool, _set_play_area_mode, uint32_t);
+ GDVIRTUAL0RC(PackedVector3Array, _get_play_area);
/** specific to AR **/
virtual bool get_anchor_detection_is_enabled() const override;
diff --git a/servers/xr/xr_pose.cpp b/servers/xr/xr_pose.cpp
new file mode 100644
index 0000000000..0d05e62b46
--- /dev/null
+++ b/servers/xr/xr_pose.cpp
@@ -0,0 +1,110 @@
+/*************************************************************************/
+/* xr_pose.cpp */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/*************************************************************************/
+
+#include "xr_pose.h"
+
+#include "servers/xr_server.h"
+
+void XRPose::_bind_methods() {
+ ClassDB::bind_method(D_METHOD("set_has_tracking_data", "has_tracking_data"), &XRPose::set_has_tracking_data);
+ ClassDB::bind_method(D_METHOD("get_has_tracking_data"), &XRPose::get_has_tracking_data);
+ ADD_PROPERTY(PropertyInfo(Variant::STRING, "has_tracking_data"), "set_has_tracking_data", "get_has_tracking_data");
+
+ ClassDB::bind_method(D_METHOD("set_name", "name"), &XRPose::set_name);
+ ClassDB::bind_method(D_METHOD("get_name"), &XRPose::get_name);
+ ADD_PROPERTY(PropertyInfo(Variant::STRING, "name"), "set_name", "get_name");
+
+ ClassDB::bind_method(D_METHOD("set_transform", "transform"), &XRPose::set_transform);
+ ClassDB::bind_method(D_METHOD("get_transform"), &XRPose::get_transform);
+ ADD_PROPERTY(PropertyInfo(Variant::STRING, "transform"), "set_transform", "get_transform");
+ ClassDB::bind_method(D_METHOD("get_adjusted_transform"), &XRPose::get_adjusted_transform);
+
+ ClassDB::bind_method(D_METHOD("set_linear_velocity", "velocity"), &XRPose::set_linear_velocity);
+ ClassDB::bind_method(D_METHOD("get_linear_velocity"), &XRPose::get_linear_velocity);
+ ADD_PROPERTY(PropertyInfo(Variant::STRING, "linear_velocity"), "set_linear_velocity", "get_linear_velocity");
+
+ ClassDB::bind_method(D_METHOD("set_angular_velocity", "velocity"), &XRPose::set_angular_velocity);
+ ClassDB::bind_method(D_METHOD("get_angular_velocity"), &XRPose::get_angular_velocity);
+ ADD_PROPERTY(PropertyInfo(Variant::STRING, "angular_velocity"), "set_angular_velocity", "get_angular_velocity");
+}
+
+void XRPose::set_has_tracking_data(const bool p_has_tracking_data) {
+ has_tracking_data = p_has_tracking_data;
+}
+bool XRPose::get_has_tracking_data() const {
+ return has_tracking_data;
+}
+
+void XRPose::set_name(const StringName &p_name) {
+ name = p_name;
+}
+
+StringName XRPose::get_name() const {
+ return name;
+}
+
+void XRPose::set_transform(const Transform3D p_transform) {
+ transform = p_transform;
+}
+
+Transform3D XRPose::get_transform() const {
+ return transform;
+}
+
+Transform3D XRPose::get_adjusted_transform() const {
+ Transform3D adjusted_transform = transform;
+
+ XRServer *xr_server = XRServer::get_singleton();
+ ERR_FAIL_NULL_V(xr_server, transform);
+
+ // apply world scale
+ adjusted_transform.origin *= xr_server->get_world_scale();
+
+ // apply reference frame
+ adjusted_transform = xr_server->get_reference_frame() * adjusted_transform;
+
+ return adjusted_transform;
+}
+
+void XRPose::set_linear_velocity(const Vector3 p_velocity) {
+ linear_velocity = p_velocity;
+}
+
+Vector3 XRPose::get_linear_velocity() const {
+ return linear_velocity;
+}
+
+void XRPose::set_angular_velocity(const Vector3 p_velocity) {
+ angular_velocity = p_velocity;
+}
+
+Vector3 XRPose::get_angular_velocity() const {
+ return angular_velocity;
+}
diff --git a/servers/xr/xr_pose.h b/servers/xr/xr_pose.h
new file mode 100644
index 0000000000..223e95ddfe
--- /dev/null
+++ b/servers/xr/xr_pose.h
@@ -0,0 +1,68 @@
+/*************************************************************************/
+/* xr_pose.h */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/*************************************************************************/
+
+#ifndef XR_POSE_H
+#define XR_POSE_H
+
+#include "core/object/ref_counted.h"
+
+class XRPose : public RefCounted {
+ GDCLASS(XRPose, RefCounted);
+
+public:
+private:
+ bool has_tracking_data = false;
+ StringName name;
+ Transform3D transform;
+ Vector3 linear_velocity;
+ Vector3 angular_velocity;
+
+protected:
+ static void _bind_methods();
+
+public:
+ void set_has_tracking_data(const bool p_has_tracking_data);
+ bool get_has_tracking_data() const;
+
+ void set_name(const StringName &p_name);
+ StringName get_name() const;
+
+ void set_transform(const Transform3D p_transform);
+ Transform3D get_transform() const;
+ Transform3D get_adjusted_transform() const;
+
+ void set_linear_velocity(const Vector3 p_velocity);
+ Vector3 get_linear_velocity() const;
+
+ void set_angular_velocity(const Vector3 p_velocity);
+ Vector3 get_angular_velocity() const;
+};
+
+#endif
diff --git a/servers/xr/xr_positional_tracker.cpp b/servers/xr/xr_positional_tracker.cpp
index e9383db941..1313a91172 100644
--- a/servers/xr/xr_positional_tracker.cpp
+++ b/servers/xr/xr_positional_tracker.cpp
@@ -37,29 +37,37 @@ void XRPositionalTracker::_bind_methods() {
BIND_ENUM_CONSTANT(TRACKER_HAND_LEFT);
BIND_ENUM_CONSTANT(TRACKER_HAND_RIGHT);
- // this class is read only from GDScript, so we only have access to getters..
ClassDB::bind_method(D_METHOD("get_tracker_type"), &XRPositionalTracker::get_tracker_type);
- ClassDB::bind_method(D_METHOD("get_tracker_id"), &XRPositionalTracker::get_tracker_id);
+ ClassDB::bind_method(D_METHOD("set_tracker_type", "type"), &XRPositionalTracker::set_tracker_type);
+ ADD_PROPERTY(PropertyInfo(Variant::INT, "type"), "set_tracker_type", "get_tracker_type");
+
ClassDB::bind_method(D_METHOD("get_tracker_name"), &XRPositionalTracker::get_tracker_name);
- ClassDB::bind_method(D_METHOD("get_joy_id"), &XRPositionalTracker::get_joy_id);
- ClassDB::bind_method(D_METHOD("is_tracking_orientation"), &XRPositionalTracker::is_tracking_orientation);
- ClassDB::bind_method(D_METHOD("get_orientation"), &XRPositionalTracker::get_orientation);
- ClassDB::bind_method(D_METHOD("is_tracking_position"), &XRPositionalTracker::is_tracking_position);
- ClassDB::bind_method(D_METHOD("get_position"), &XRPositionalTracker::get_position);
+ ClassDB::bind_method(D_METHOD("set_tracker_name", "name"), &XRPositionalTracker::set_tracker_name);
+ ADD_PROPERTY(PropertyInfo(Variant::STRING, "name"), "set_tracker_name", "get_tracker_name");
+
+ ClassDB::bind_method(D_METHOD("get_tracker_desc"), &XRPositionalTracker::get_tracker_desc);
+ ClassDB::bind_method(D_METHOD("set_tracker_desc", "description"), &XRPositionalTracker::set_tracker_desc);
+ ADD_PROPERTY(PropertyInfo(Variant::STRING, "description"), "set_tracker_desc", "get_tracker_desc");
+
ClassDB::bind_method(D_METHOD("get_tracker_hand"), &XRPositionalTracker::get_tracker_hand);
- ClassDB::bind_method(D_METHOD("get_transform", "adjust_by_reference_frame"), &XRPositionalTracker::get_transform);
- ClassDB::bind_method(D_METHOD("get_mesh"), &XRPositionalTracker::get_mesh);
-
- // these functions we don't want to expose to normal users but do need to be callable from GDNative
- ClassDB::bind_method(D_METHOD("_set_tracker_type", "type"), &XRPositionalTracker::set_tracker_type);
- ClassDB::bind_method(D_METHOD("_set_tracker_name", "name"), &XRPositionalTracker::set_tracker_name);
- ClassDB::bind_method(D_METHOD("_set_joy_id", "joy_id"), &XRPositionalTracker::set_joy_id);
- ClassDB::bind_method(D_METHOD("_set_orientation", "orientation"), &XRPositionalTracker::set_orientation);
- ClassDB::bind_method(D_METHOD("_set_rw_position", "rw_position"), &XRPositionalTracker::set_rw_position);
- ClassDB::bind_method(D_METHOD("_set_mesh", "mesh"), &XRPositionalTracker::set_mesh);
+ ClassDB::bind_method(D_METHOD("set_tracker_hand", "hand"), &XRPositionalTracker::set_tracker_hand);
+ ADD_PROPERTY(PropertyInfo(Variant::INT, "hand", PROPERTY_HINT_ENUM, "Unknown,Left,Right"), "set_tracker_hand", "get_tracker_hand");
+
+ ClassDB::bind_method(D_METHOD("has_pose", "name"), &XRPositionalTracker::has_pose);
+ ClassDB::bind_method(D_METHOD("get_pose", "name"), &XRPositionalTracker::get_pose);
+ ClassDB::bind_method(D_METHOD("invalidate_pose", "name"), &XRPositionalTracker::invalidate_pose);
+ ClassDB::bind_method(D_METHOD("set_pose", "name", "transform", "linear_velocity", "angular_velocity"), &XRPositionalTracker::set_pose);
+ ADD_SIGNAL(MethodInfo("pose_changed", PropertyInfo(Variant::OBJECT, "pose", PROPERTY_HINT_RESOURCE_TYPE, "XRPose")));
+
+ ClassDB::bind_method(D_METHOD("get_input", "name"), &XRPositionalTracker::get_input);
+ ClassDB::bind_method(D_METHOD("set_input", "name", "value"), &XRPositionalTracker::set_input);
+ ADD_SIGNAL(MethodInfo("button_pressed", PropertyInfo(Variant::STRING, "name")));
+ ADD_SIGNAL(MethodInfo("button_released", PropertyInfo(Variant::STRING, "name")));
+ ADD_SIGNAL(MethodInfo("input_value_changed", PropertyInfo(Variant::STRING, "name"), PropertyInfo(Variant::FLOAT, "value")));
+ ADD_SIGNAL(MethodInfo("input_axis_changed", PropertyInfo(Variant::STRING, "name"), PropertyInfo(Variant::VECTOR2, "vector")));
+
ClassDB::bind_method(D_METHOD("get_rumble"), &XRPositionalTracker::get_rumble);
ClassDB::bind_method(D_METHOD("set_rumble", "rumble"), &XRPositionalTracker::set_rumble);
-
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "rumble"), "set_rumble", "get_rumble");
};
@@ -67,13 +75,6 @@ void XRPositionalTracker::set_tracker_type(XRServer::TrackerType p_type) {
if (type != p_type) {
type = p_type;
hand = XRPositionalTracker::TRACKER_HAND_UNKNOWN;
-
- XRServer *xr_server = XRServer::get_singleton();
- ERR_FAIL_NULL(xr_server);
-
- // get a tracker id for our type
- // note if this is a controller this will be 3 or higher but we may change it later.
- tracker_id = xr_server->get_free_tracker_id_for_type(p_type);
};
};
@@ -81,7 +82,8 @@ XRServer::TrackerType XRPositionalTracker::get_tracker_type() const {
return type;
};
-void XRPositionalTracker::set_tracker_name(const String &p_name) {
+void XRPositionalTracker::set_tracker_name(const StringName &p_name) {
+ // Note: this should not be changed after the tracker is registered with the XRServer!
name = p_name;
};
@@ -89,85 +91,13 @@ StringName XRPositionalTracker::get_tracker_name() const {
return name;
};
-int XRPositionalTracker::get_tracker_id() const {
- return tracker_id;
-};
-
-void XRPositionalTracker::set_joy_id(int p_joy_id) {
- joy_id = p_joy_id;
-};
-
-int XRPositionalTracker::get_joy_id() const {
- return joy_id;
-};
-
-bool XRPositionalTracker::is_tracking_orientation() const {
- return tracking_orientation;
-};
-
-void XRPositionalTracker::set_orientation(const Basis &p_orientation) {
- _THREAD_SAFE_METHOD_
-
- tracking_orientation = true; // obviously we have this
- orientation = p_orientation;
-};
-
-Basis XRPositionalTracker::get_orientation() const {
- _THREAD_SAFE_METHOD_
-
- return orientation;
-};
-
-bool XRPositionalTracker::is_tracking_position() const {
- return tracking_position;
-};
-
-void XRPositionalTracker::set_position(const Vector3 &p_position) {
- _THREAD_SAFE_METHOD_
-
- XRServer *xr_server = XRServer::get_singleton();
- ERR_FAIL_NULL(xr_server);
- real_t world_scale = xr_server->get_world_scale();
- ERR_FAIL_COND(world_scale == 0);
-
- tracking_position = true; // obviously we have this
- rw_position = p_position / world_scale;
-};
-
-Vector3 XRPositionalTracker::get_position() const {
- _THREAD_SAFE_METHOD_
-
- XRServer *xr_server = XRServer::get_singleton();
- ERR_FAIL_NULL_V(xr_server, rw_position);
- real_t world_scale = xr_server->get_world_scale();
-
- return rw_position * world_scale;
-};
-
-void XRPositionalTracker::set_rw_position(const Vector3 &p_rw_position) {
- _THREAD_SAFE_METHOD_
-
- tracking_position = true; // obviously we have this
- rw_position = p_rw_position;
-};
-
-Vector3 XRPositionalTracker::get_rw_position() const {
- _THREAD_SAFE_METHOD_
-
- return rw_position;
-};
-
-void XRPositionalTracker::set_mesh(const Ref<Mesh> &p_mesh) {
- _THREAD_SAFE_METHOD_
-
- mesh = p_mesh;
-};
-
-Ref<Mesh> XRPositionalTracker::get_mesh() const {
- _THREAD_SAFE_METHOD_
+void XRPositionalTracker::set_tracker_desc(const String &p_desc) {
+ description = p_desc;
+}
- return mesh;
-};
+String XRPositionalTracker::get_tracker_desc() const {
+ return description;
+}
XRPositionalTracker::TrackerHand XRPositionalTracker::get_tracker_hand() const {
return hand;
@@ -182,33 +112,98 @@ void XRPositionalTracker::set_tracker_hand(const XRPositionalTracker::TrackerHan
ERR_FAIL_COND((type != XRServer::TRACKER_CONTROLLER) && (p_hand != XRPositionalTracker::TRACKER_HAND_UNKNOWN));
hand = p_hand;
- if (hand == XRPositionalTracker::TRACKER_HAND_LEFT) {
- if (!xr_server->is_tracker_id_in_use_for_type(type, 1)) {
- tracker_id = 1;
- };
- } else if (hand == XRPositionalTracker::TRACKER_HAND_RIGHT) {
- if (!xr_server->is_tracker_id_in_use_for_type(type, 2)) {
- tracker_id = 2;
- };
- };
};
};
-Transform3D XRPositionalTracker::get_transform(bool p_adjust_by_reference_frame) const {
- Transform3D new_transform;
+bool XRPositionalTracker::has_pose(const StringName &p_action_name) const {
+ return poses.has(p_action_name);
+}
- new_transform.basis = get_orientation();
- new_transform.origin = get_position();
+Ref<XRPose> XRPositionalTracker::get_pose(const StringName &p_action_name) const {
+ Ref<XRPose> pose;
- if (p_adjust_by_reference_frame) {
- XRServer *xr_server = XRServer::get_singleton();
- ERR_FAIL_NULL_V(xr_server, new_transform);
+ if (poses.has(p_action_name)) {
+ pose = poses[p_action_name];
+ }
- new_transform = xr_server->get_reference_frame() * new_transform;
- };
+ return pose;
+}
- return new_transform;
-};
+void XRPositionalTracker::invalidate_pose(const StringName &p_action_name) {
+ // only update this if we were tracking this pose
+ if (poses.has(p_action_name)) {
+ // We just set tracking data as invalid, we leave our current transform and velocity data as is so controllers don't suddenly jump to origin.
+ poses[p_action_name]->set_has_tracking_data(false);
+ }
+}
+
+void XRPositionalTracker::set_pose(const StringName &p_action_name, const Transform3D &p_transform, const Vector3 &p_linear_velocity, const Vector3 &p_angular_velocity) {
+ Ref<XRPose> new_pose;
+
+ new_pose.instantiate();
+ new_pose->set_name(p_action_name);
+ new_pose->set_has_tracking_data(true);
+ new_pose->set_transform(p_transform);
+ new_pose->set_linear_velocity(p_linear_velocity);
+ new_pose->set_angular_velocity(p_angular_velocity);
+
+ poses[p_action_name] = new_pose;
+ emit_signal("pose_changed", new_pose);
+
+ // TODO discuss whether we also want to create and emit an InputEventXRPose event
+}
+
+Variant XRPositionalTracker::get_input(const StringName &p_action_name) const {
+ if (inputs.has(p_action_name)) {
+ return inputs[p_action_name];
+ } else {
+ return Variant();
+ }
+}
+
+void XRPositionalTracker::set_input(const StringName &p_action_name, const Variant &p_value) {
+ bool changed = false;
+
+ // XR inputs
+
+ if (inputs.has(p_action_name)) {
+ changed = inputs[p_action_name] != p_value;
+ } else {
+ changed = true;
+ }
+
+ if (changed) {
+ // store the new value
+ inputs[p_action_name] = p_value;
+
+ // emit signals to let the rest of the world know
+ switch (p_value.get_type()) {
+ case Variant::BOOL: {
+ bool pressed = p_value;
+ if (pressed) {
+ emit_signal("button_pressed", p_action_name);
+ } else {
+ emit_signal("button_released", p_action_name);
+ }
+
+ // TODO discuss whether we also want to create and emit an InputEventXRButton event
+ } break;
+ case Variant::FLOAT: {
+ emit_signal("input_value_changed", p_action_name, p_value);
+
+ // TODO discuss whether we also want to create and emit an InputEventXRValue event
+ } break;
+ case Variant::VECTOR2: {
+ emit_signal("input_axis_changed", p_action_name, p_value);
+
+ // TODO discuss whether we also want to create and emit an InputEventXRAxis event
+ } break;
+ default: {
+ // ???
+ } break;
+ }
+ }
+}
real_t XRPositionalTracker::get_rumble() const {
return rumble;
@@ -225,10 +220,6 @@ void XRPositionalTracker::set_rumble(real_t p_rumble) {
XRPositionalTracker::XRPositionalTracker() {
type = XRServer::TRACKER_UNKNOWN;
name = "Unknown";
- joy_id = -1;
- tracker_id = 0;
- tracking_orientation = false;
- tracking_position = false;
hand = TRACKER_HAND_UNKNOWN;
rumble = 0.0;
};
diff --git a/servers/xr/xr_positional_tracker.h b/servers/xr/xr_positional_tracker.h
index 5577582929..69eb105b5a 100644
--- a/servers/xr/xr_positional_tracker.h
+++ b/servers/xr/xr_positional_tracker.h
@@ -33,6 +33,7 @@
#include "core/os/thread_safe.h"
#include "scene/resources/mesh.h"
+#include "servers/xr/xr_pose.h"
#include "servers/xr_server.h"
/**
@@ -57,14 +58,14 @@ public:
private:
XRServer::TrackerType type; // type of tracker
StringName name; // (unique) name of the tracker
- int tracker_id; // tracker index id that is unique per type
+ String description; // description of the tracker, this is interface dependent, for OpenXR this will be the interaction profile bound for to the tracker
+ TrackerHand hand; // if known, the hand this tracker is held in
+
+ Map<StringName, Ref<XRPose>> poses;
+ Map<StringName, Variant> inputs;
+
int joy_id; // if we also have a related joystick entity, the id of the joystick
- bool tracking_orientation; // do we track orientation?
- Basis orientation; // our orientation
- bool tracking_position; // do we track position?
- Vector3 rw_position; // our position "in the real world, so without world_scale applied"
Ref<Mesh> mesh; // when available, a mesh that can be used to render this tracker
- TrackerHand hand; // if known, the hand this tracker is held in
real_t rumble; // rumble strength, 0.0 is off, 1.0 is maximum, note that we only record here, xr_interface is responsible for execution
protected:
@@ -73,27 +74,24 @@ protected:
public:
void set_tracker_type(XRServer::TrackerType p_type);
XRServer::TrackerType get_tracker_type() const;
- void set_tracker_name(const String &p_name);
+ void set_tracker_name(const StringName &p_name);
StringName get_tracker_name() const;
- int get_tracker_id() const;
- void set_joy_id(int p_joy_id);
- int get_joy_id() const;
- bool is_tracking_orientation() const;
- void set_orientation(const Basis &p_orientation);
- Basis get_orientation() const;
- bool is_tracking_position() const;
- void set_position(const Vector3 &p_position); // set position with world_scale applied
- Vector3 get_position() const; // get position with world_scale applied
- void set_rw_position(const Vector3 &p_rw_position);
- Vector3 get_rw_position() const;
+ void set_tracker_desc(const String &p_desc);
+ String get_tracker_desc() const;
XRPositionalTracker::TrackerHand get_tracker_hand() const;
void set_tracker_hand(const XRPositionalTracker::TrackerHand p_hand);
+
+ bool has_pose(const StringName &p_action_name) const;
+ Ref<XRPose> get_pose(const StringName &p_action_name) const;
+ void invalidate_pose(const StringName &p_action_name);
+ void set_pose(const StringName &p_action_name, const Transform3D &p_transform, const Vector3 &p_linear_velocity, const Vector3 &p_angular_velocity);
+
+ Variant get_input(const StringName &p_action_name) const;
+ void set_input(const StringName &p_action_name, const Variant &p_value);
+
+ // TODO replace by new implementation
real_t get_rumble() const;
void set_rumble(real_t p_rumble);
- void set_mesh(const Ref<Mesh> &p_mesh);
- Ref<Mesh> get_mesh() const;
-
- Transform3D get_transform(bool p_adjust_by_reference_frame) const;
XRPositionalTracker();
~XRPositionalTracker() {}