Skip to content

Commit

Permalink
WebXR: Add support for hand tracking
Browse files Browse the repository at this point in the history
  • Loading branch information
dsnopek committed Feb 23, 2024
1 parent 2fe8f07 commit 7fa8ccd
Show file tree
Hide file tree
Showing 8 changed files with 182 additions and 26 deletions.
4 changes: 4 additions & 0 deletions modules/webxr/doc_classes/WebXRInterface.xml
Original file line number Diff line number Diff line change
Expand Up @@ -153,6 +153,10 @@
</method>
</methods>
<members>
<member name="enabled_features" type="String" setter="" getter="get_enabled_features">
A comma-separated list of features that were successfully enabled by [method XRInterface.initialize] when setting up the WebXR session.
This may include features requested by setting [member required_features] and [member optional_features].
</member>
<member name="optional_features" type="String" setter="set_optional_features" getter="get_optional_features">
A comma-seperated list of optional features used by [method XRInterface.initialize] when setting up the WebXR session.
If a user's browser or device doesn't support one of the given features, initialization will continue, but you won't be able to use the requested feature.
Expand Down
7 changes: 5 additions & 2 deletions modules/webxr/godot_webxr.h
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ enum WebXRInputEvent {
};

typedef void (*GodotWebXRSupportedCallback)(char *p_session_mode, int p_supported);
typedef void (*GodotWebXRStartedCallback)(char *p_reference_space_type);
typedef void (*GodotWebXRStartedCallback)(char *p_reference_space_type, char *p_enabled_features);
typedef void (*GodotWebXREndedCallback)();
typedef void (*GodotWebXRFailedCallback)(char *p_message);
typedef void (*GodotWebXRInputEventCallback)(int p_event_type, int p_input_source_id);
Expand Down Expand Up @@ -85,7 +85,10 @@ extern bool godot_webxr_update_input_source(
int *r_button_count,
float *r_buttons,
int *r_axes_count,
float *r_axes);
float *r_axes,
int *r_has_hand_data,
float *r_hand_joints,
float *r_hand_radii);

extern char *godot_webxr_get_visibility_state();
extern int godot_webxr_get_bounds_geometry(float **r_points);
Expand Down
25 changes: 20 additions & 5 deletions modules/webxr/native/library_godot_webxr.js
Original file line number Diff line number Diff line change
Expand Up @@ -318,9 +318,11 @@ const GodotWebXR = {
// callback don't bubble up here and cause Godot to try the
// next reference space.
window.setTimeout(function () {
const c_str = GodotRuntime.allocString(reference_space_type);
onstarted(c_str);
GodotRuntime.free(c_str);
const reference_space_c_str = GodotRuntime.allocString(reference_space_type);
const enabled_features_c_str = GodotRuntime.allocString(Array.from(session.enabledFeatures).join(","));
onstarted(reference_space_c_str, enabled_features_c_str);
GodotRuntime.free(reference_space_c_str);
GodotRuntime.free(enabled_features_c_str);
}, 0);
}

Expand Down Expand Up @@ -479,8 +481,8 @@ const GodotWebXR = {
},

godot_webxr_update_input_source__proxy: 'sync',
godot_webxr_update_input_source__sig: 'iiiiiiiiiiii',
godot_webxr_update_input_source: function (p_input_source_id, r_target_pose, r_target_ray_mode, r_touch_index, r_has_grip_pose, r_grip_pose, r_has_standard_mapping, r_button_count, r_buttons, r_axes_count, r_axes) {
godot_webxr_update_input_source__sig: 'iiiiiiiiiiiiiii',
godot_webxr_update_input_source: function (p_input_source_id, r_target_pose, r_target_ray_mode, r_touch_index, r_has_grip_pose, r_grip_pose, r_has_standard_mapping, r_button_count, r_buttons, r_axes_count, r_axes, r_has_hand_data, r_hand_joints, r_hand_radii) {
if (!GodotWebXR.session || !GodotWebXR.frame) {
return 0;
}
Expand Down Expand Up @@ -563,6 +565,19 @@ const GodotWebXR = {
GodotRuntime.setHeapValue(r_button_count, button_count, 'i32');
GodotRuntime.setHeapValue(r_axes_count, axes_count, 'i32');

// Hand tracking data.
let has_hand_data = false;
if (input_source.hand && r_hand_joints != 0 && r_hand_radii != 0) {
const hand_joint_array = new Float32Array(25 * 16);
const hand_radii_array = new Float32Array(25);
if (frame.fillPoses(input_source.hand.values(), space, hand_joint_array) && frame.fillJointRadii(input_source.hand.values(), hand_radii_array)) {
GodotRuntime.heapCopy(HEAPF32, hand_joint_array, r_hand_joints);
GodotRuntime.heapCopy(HEAPF32, hand_radii_array, r_hand_radii);
has_hand_data = true;
}
}
GodotRuntime.setHeapValue(r_has_hand_data, has_hand_data ? 1 : 0, 'i32');

return true;
},

Expand Down
56 changes: 55 additions & 1 deletion modules/webxr/native/webxr.externs.js
Original file line number Diff line number Diff line change
Expand Up @@ -229,13 +229,27 @@ XRFrame.prototype.session;
XRFrame.prototype.getViewerPose = function (referenceSpace) {};

/**
*
* @param {XRSpace} space
* @param {XRSpace} baseSpace
* @return {XRPose}
*/
XRFrame.prototype.getPose = function (space, baseSpace) {};

/**
* @param {Array<XRSpace>} spaces
* @param {XRSpace} baseSpace
* @param {Float32Array} transforms
* @return {boolean}
*/
XRFrame.prototype.fillPoses = function (spaces, baseSpace, transforms) {};

/**
* @param {Array<XRJointSpace>} jointSpaces
* @param {Float32Array} radii
* @return {boolean}
*/
XRFrame.prototype.fillJointRadii = function (jointSpaces, radii) {};

/**
* @constructor
*/
Expand Down Expand Up @@ -498,11 +512,51 @@ XRInputSource.prototype.targetRayMode;
*/
XRInputSource.prototype.targetRaySpace;

/**
* @type {?XRHand}
*/
XRInputSource.prototype.hand;

/**
* @constructor
*/
function XRHand() {};

/**
* Note: In fact, XRHand acts like a Map<string, XRJointSpace>, but I don't know
* how to represent that here. So, we're just giving the one method we call.
*
* @return {Array<XRJointSpace>}
*/
XRHand.prototype.values = function () {};

/**
* @type {number}
*/
XRHand.prototype.size;

/**
* @param {string} key
* @return {XRJointSpace}
*/
XRHand.prototype.get = function (key) {};

/**
* @constructor
*/
function XRSpace() {};

/**
* @constructor
* @extends {XRSpace}
*/
function XRJointSpace() {};

/**
* @type {string}
*/
XRJointSpace.prototype.jointName;

/**
* @constructor
*/
Expand Down
2 changes: 2 additions & 0 deletions modules/webxr/webxr_interface.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ void WebXRInterface::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_optional_features", "optional_features"), &WebXRInterface::set_optional_features);
ClassDB::bind_method(D_METHOD("get_optional_features"), &WebXRInterface::get_optional_features);
ClassDB::bind_method(D_METHOD("get_reference_space_type"), &WebXRInterface::get_reference_space_type);
ClassDB::bind_method(D_METHOD("get_enabled_features"), &WebXRInterface::get_enabled_features);
ClassDB::bind_method(D_METHOD("set_requested_reference_space_types", "requested_reference_space_types"), &WebXRInterface::set_requested_reference_space_types);
ClassDB::bind_method(D_METHOD("get_requested_reference_space_types"), &WebXRInterface::get_requested_reference_space_types);
ClassDB::bind_method(D_METHOD("is_input_source_active", "input_source_id"), &WebXRInterface::is_input_source_active);
Expand All @@ -56,6 +57,7 @@ void WebXRInterface::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::STRING, "optional_features", PROPERTY_HINT_NONE), "set_optional_features", "get_optional_features");
ADD_PROPERTY(PropertyInfo(Variant::STRING, "requested_reference_space_types", PROPERTY_HINT_NONE), "set_requested_reference_space_types", "get_requested_reference_space_types");
ADD_PROPERTY(PropertyInfo(Variant::STRING, "reference_space_type", PROPERTY_HINT_NONE), "", "get_reference_space_type");
ADD_PROPERTY(PropertyInfo(Variant::STRING, "enabled_features", PROPERTY_HINT_NONE), "", "get_enabled_features");
ADD_PROPERTY(PropertyInfo(Variant::STRING, "visibility_state", PROPERTY_HINT_NONE), "", "get_visibility_state");

ADD_SIGNAL(MethodInfo("session_supported", PropertyInfo(Variant::STRING, "session_mode"), PropertyInfo(Variant::BOOL, "supported")));
Expand Down
1 change: 1 addition & 0 deletions modules/webxr/webxr_interface.h
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,7 @@ class WebXRInterface : public XRInterface {
virtual void set_requested_reference_space_types(String p_requested_reference_space_types) = 0;
virtual String get_requested_reference_space_types() const = 0;
virtual String get_reference_space_type() const = 0;
virtual String get_enabled_features() const = 0;
virtual bool is_input_source_active(int p_input_source_id) const = 0;
virtual Ref<XRPositionalTracker> get_input_source_tracker(int p_input_source_id) const = 0;
virtual TargetRayMode get_input_source_target_ray_mode(int p_input_source_id) const = 0;
Expand Down
Loading

0 comments on commit 7fa8ccd

Please sign in to comment.