initial commit, 4.5 stable
Some checks failed
🔗 GHA / 📊 Static checks (push) Has been cancelled
🔗 GHA / 🤖 Android (push) Has been cancelled
🔗 GHA / 🍏 iOS (push) Has been cancelled
🔗 GHA / 🐧 Linux (push) Has been cancelled
🔗 GHA / 🍎 macOS (push) Has been cancelled
🔗 GHA / 🏁 Windows (push) Has been cancelled
🔗 GHA / 🌐 Web (push) Has been cancelled

This commit is contained in:
2025-09-16 20:46:46 -04:00
commit 9d30169a8d
13378 changed files with 7050105 additions and 0 deletions

6
servers/xr/SCsub Normal file
View File

@@ -0,0 +1,6 @@
#!/usr/bin/env python
from misc.utility.scons_hints import *
Import("env")
env.add_source_files(env.servers_sources, "*.cpp")

View File

@@ -0,0 +1,194 @@
/**************************************************************************/
/* xr_body_tracker.cpp */
/**************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
/* https://godotengine.org */
/**************************************************************************/
/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
/* */
/* 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_body_tracker.h"
void XRBodyTracker::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_has_tracking_data", "has_data"), &XRBodyTracker::set_has_tracking_data);
ClassDB::bind_method(D_METHOD("get_has_tracking_data"), &XRBodyTracker::get_has_tracking_data);
ClassDB::bind_method(D_METHOD("set_body_flags", "flags"), &XRBodyTracker::set_body_flags);
ClassDB::bind_method(D_METHOD("get_body_flags"), &XRBodyTracker::get_body_flags);
ClassDB::bind_method(D_METHOD("set_joint_flags", "joint", "flags"), &XRBodyTracker::set_joint_flags);
ClassDB::bind_method(D_METHOD("get_joint_flags", "joint"), &XRBodyTracker::get_joint_flags);
ClassDB::bind_method(D_METHOD("set_joint_transform", "joint", "transform"), &XRBodyTracker::set_joint_transform);
ClassDB::bind_method(D_METHOD("get_joint_transform", "joint"), &XRBodyTracker::get_joint_transform);
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "has_tracking_data", PROPERTY_HINT_NONE), "set_has_tracking_data", "get_has_tracking_data");
ADD_PROPERTY(PropertyInfo(Variant::INT, "body_flags", PROPERTY_HINT_FLAGS, "Upper Body,Lower Body,Hands"), "set_body_flags", "get_body_flags");
BIND_BITFIELD_FLAG(BODY_FLAG_UPPER_BODY_SUPPORTED);
BIND_BITFIELD_FLAG(BODY_FLAG_LOWER_BODY_SUPPORTED);
BIND_BITFIELD_FLAG(BODY_FLAG_HANDS_SUPPORTED);
BIND_ENUM_CONSTANT(JOINT_ROOT);
BIND_ENUM_CONSTANT(JOINT_HIPS);
BIND_ENUM_CONSTANT(JOINT_SPINE);
BIND_ENUM_CONSTANT(JOINT_CHEST);
BIND_ENUM_CONSTANT(JOINT_UPPER_CHEST);
BIND_ENUM_CONSTANT(JOINT_NECK);
BIND_ENUM_CONSTANT(JOINT_HEAD);
BIND_ENUM_CONSTANT(JOINT_HEAD_TIP);
BIND_ENUM_CONSTANT(JOINT_LEFT_SHOULDER);
BIND_ENUM_CONSTANT(JOINT_LEFT_UPPER_ARM);
BIND_ENUM_CONSTANT(JOINT_LEFT_LOWER_ARM);
BIND_ENUM_CONSTANT(JOINT_RIGHT_SHOULDER);
BIND_ENUM_CONSTANT(JOINT_RIGHT_UPPER_ARM);
BIND_ENUM_CONSTANT(JOINT_RIGHT_LOWER_ARM);
BIND_ENUM_CONSTANT(JOINT_LEFT_UPPER_LEG);
BIND_ENUM_CONSTANT(JOINT_LEFT_LOWER_LEG);
BIND_ENUM_CONSTANT(JOINT_LEFT_FOOT);
BIND_ENUM_CONSTANT(JOINT_LEFT_TOES);
BIND_ENUM_CONSTANT(JOINT_RIGHT_UPPER_LEG);
BIND_ENUM_CONSTANT(JOINT_RIGHT_LOWER_LEG);
BIND_ENUM_CONSTANT(JOINT_RIGHT_FOOT);
BIND_ENUM_CONSTANT(JOINT_RIGHT_TOES);
BIND_ENUM_CONSTANT(JOINT_LEFT_HAND);
BIND_ENUM_CONSTANT(JOINT_LEFT_PALM);
BIND_ENUM_CONSTANT(JOINT_LEFT_WRIST);
BIND_ENUM_CONSTANT(JOINT_LEFT_THUMB_METACARPAL);
BIND_ENUM_CONSTANT(JOINT_LEFT_THUMB_PHALANX_PROXIMAL);
BIND_ENUM_CONSTANT(JOINT_LEFT_THUMB_PHALANX_DISTAL);
BIND_ENUM_CONSTANT(JOINT_LEFT_THUMB_TIP);
BIND_ENUM_CONSTANT(JOINT_LEFT_INDEX_FINGER_METACARPAL);
BIND_ENUM_CONSTANT(JOINT_LEFT_INDEX_FINGER_PHALANX_PROXIMAL);
BIND_ENUM_CONSTANT(JOINT_LEFT_INDEX_FINGER_PHALANX_INTERMEDIATE);
BIND_ENUM_CONSTANT(JOINT_LEFT_INDEX_FINGER_PHALANX_DISTAL);
BIND_ENUM_CONSTANT(JOINT_LEFT_INDEX_FINGER_TIP);
BIND_ENUM_CONSTANT(JOINT_LEFT_MIDDLE_FINGER_METACARPAL);
BIND_ENUM_CONSTANT(JOINT_LEFT_MIDDLE_FINGER_PHALANX_PROXIMAL);
BIND_ENUM_CONSTANT(JOINT_LEFT_MIDDLE_FINGER_PHALANX_INTERMEDIATE);
BIND_ENUM_CONSTANT(JOINT_LEFT_MIDDLE_FINGER_PHALANX_DISTAL);
BIND_ENUM_CONSTANT(JOINT_LEFT_MIDDLE_FINGER_TIP);
BIND_ENUM_CONSTANT(JOINT_LEFT_RING_FINGER_METACARPAL);
BIND_ENUM_CONSTANT(JOINT_LEFT_RING_FINGER_PHALANX_PROXIMAL);
BIND_ENUM_CONSTANT(JOINT_LEFT_RING_FINGER_PHALANX_INTERMEDIATE);
BIND_ENUM_CONSTANT(JOINT_LEFT_RING_FINGER_PHALANX_DISTAL);
BIND_ENUM_CONSTANT(JOINT_LEFT_RING_FINGER_TIP);
BIND_ENUM_CONSTANT(JOINT_LEFT_PINKY_FINGER_METACARPAL);
BIND_ENUM_CONSTANT(JOINT_LEFT_PINKY_FINGER_PHALANX_PROXIMAL);
BIND_ENUM_CONSTANT(JOINT_LEFT_PINKY_FINGER_PHALANX_INTERMEDIATE);
BIND_ENUM_CONSTANT(JOINT_LEFT_PINKY_FINGER_PHALANX_DISTAL);
BIND_ENUM_CONSTANT(JOINT_LEFT_PINKY_FINGER_TIP);
BIND_ENUM_CONSTANT(JOINT_RIGHT_HAND);
BIND_ENUM_CONSTANT(JOINT_RIGHT_PALM);
BIND_ENUM_CONSTANT(JOINT_RIGHT_WRIST);
BIND_ENUM_CONSTANT(JOINT_RIGHT_THUMB_METACARPAL);
BIND_ENUM_CONSTANT(JOINT_RIGHT_THUMB_PHALANX_PROXIMAL);
BIND_ENUM_CONSTANT(JOINT_RIGHT_THUMB_PHALANX_DISTAL);
BIND_ENUM_CONSTANT(JOINT_RIGHT_THUMB_TIP);
BIND_ENUM_CONSTANT(JOINT_RIGHT_INDEX_FINGER_METACARPAL);
BIND_ENUM_CONSTANT(JOINT_RIGHT_INDEX_FINGER_PHALANX_PROXIMAL);
BIND_ENUM_CONSTANT(JOINT_RIGHT_INDEX_FINGER_PHALANX_INTERMEDIATE);
BIND_ENUM_CONSTANT(JOINT_RIGHT_INDEX_FINGER_PHALANX_DISTAL);
BIND_ENUM_CONSTANT(JOINT_RIGHT_INDEX_FINGER_TIP);
BIND_ENUM_CONSTANT(JOINT_RIGHT_MIDDLE_FINGER_METACARPAL);
BIND_ENUM_CONSTANT(JOINT_RIGHT_MIDDLE_FINGER_PHALANX_PROXIMAL);
BIND_ENUM_CONSTANT(JOINT_RIGHT_MIDDLE_FINGER_PHALANX_INTERMEDIATE);
BIND_ENUM_CONSTANT(JOINT_RIGHT_MIDDLE_FINGER_PHALANX_DISTAL);
BIND_ENUM_CONSTANT(JOINT_RIGHT_MIDDLE_FINGER_TIP);
BIND_ENUM_CONSTANT(JOINT_RIGHT_RING_FINGER_METACARPAL);
BIND_ENUM_CONSTANT(JOINT_RIGHT_RING_FINGER_PHALANX_PROXIMAL);
BIND_ENUM_CONSTANT(JOINT_RIGHT_RING_FINGER_PHALANX_INTERMEDIATE);
BIND_ENUM_CONSTANT(JOINT_RIGHT_RING_FINGER_PHALANX_DISTAL);
BIND_ENUM_CONSTANT(JOINT_RIGHT_RING_FINGER_TIP);
BIND_ENUM_CONSTANT(JOINT_RIGHT_PINKY_FINGER_METACARPAL);
BIND_ENUM_CONSTANT(JOINT_RIGHT_PINKY_FINGER_PHALANX_PROXIMAL);
BIND_ENUM_CONSTANT(JOINT_RIGHT_PINKY_FINGER_PHALANX_INTERMEDIATE);
BIND_ENUM_CONSTANT(JOINT_RIGHT_PINKY_FINGER_PHALANX_DISTAL);
BIND_ENUM_CONSTANT(JOINT_RIGHT_PINKY_FINGER_TIP);
BIND_ENUM_CONSTANT(JOINT_LOWER_CHEST);
BIND_ENUM_CONSTANT(JOINT_LEFT_SCAPULA);
BIND_ENUM_CONSTANT(JOINT_LEFT_WRIST_TWIST);
BIND_ENUM_CONSTANT(JOINT_RIGHT_SCAPULA);
BIND_ENUM_CONSTANT(JOINT_RIGHT_WRIST_TWIST);
BIND_ENUM_CONSTANT(JOINT_LEFT_FOOT_TWIST);
BIND_ENUM_CONSTANT(JOINT_LEFT_HEEL);
BIND_ENUM_CONSTANT(JOINT_LEFT_MIDDLE_FOOT);
BIND_ENUM_CONSTANT(JOINT_RIGHT_FOOT_TWIST);
BIND_ENUM_CONSTANT(JOINT_RIGHT_HEEL);
BIND_ENUM_CONSTANT(JOINT_RIGHT_MIDDLE_FOOT);
BIND_ENUM_CONSTANT(JOINT_MAX);
BIND_BITFIELD_FLAG(JOINT_FLAG_ORIENTATION_VALID);
BIND_BITFIELD_FLAG(JOINT_FLAG_ORIENTATION_TRACKED);
BIND_BITFIELD_FLAG(JOINT_FLAG_POSITION_VALID);
BIND_BITFIELD_FLAG(JOINT_FLAG_POSITION_TRACKED);
}
void XRBodyTracker::set_tracker_type(XRServer::TrackerType p_type) {
ERR_FAIL_COND_MSG(p_type != XRServer::TRACKER_BODY, "XRBodyTracker must be of type TRACKER_BODY.");
}
void XRBodyTracker::set_tracker_hand(const XRPositionalTracker::TrackerHand p_hand) {
ERR_FAIL_COND_MSG(p_hand != XRPositionalTracker::TRACKER_HAND_UNKNOWN, "XRBodyTracker cannot specify hand.");
}
void XRBodyTracker::set_has_tracking_data(bool p_has_tracking_data) {
has_tracking_data = p_has_tracking_data;
}
bool XRBodyTracker::get_has_tracking_data() const {
return has_tracking_data;
}
void XRBodyTracker::set_body_flags(BitField<BodyFlags> p_body_flags) {
body_flags = p_body_flags;
}
BitField<XRBodyTracker::BodyFlags> XRBodyTracker::get_body_flags() const {
return body_flags;
}
void XRBodyTracker::set_joint_flags(Joint p_joint, BitField<JointFlags> p_flags) {
ERR_FAIL_INDEX(p_joint, JOINT_MAX);
joint_flags[p_joint] = p_flags;
}
BitField<XRBodyTracker::JointFlags> XRBodyTracker::get_joint_flags(Joint p_joint) const {
ERR_FAIL_INDEX_V(p_joint, JOINT_MAX, BitField<JointFlags>());
return joint_flags[p_joint];
}
void XRBodyTracker::set_joint_transform(Joint p_joint, const Transform3D &p_transform) {
ERR_FAIL_INDEX(p_joint, JOINT_MAX);
joint_transforms[p_joint] = p_transform;
}
Transform3D XRBodyTracker::get_joint_transform(Joint p_joint) const {
ERR_FAIL_INDEX_V(p_joint, JOINT_MAX, Transform3D());
return joint_transforms[p_joint];
}
XRBodyTracker::XRBodyTracker() {
type = XRServer::TRACKER_BODY;
}

View File

@@ -0,0 +1,185 @@
/**************************************************************************/
/* xr_body_tracker.h */
/**************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
/* https://godotengine.org */
/**************************************************************************/
/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
/* */
/* 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. */
/**************************************************************************/
#pragma once
#include "servers/xr/xr_positional_tracker.h"
class XRBodyTracker : public XRPositionalTracker {
GDCLASS(XRBodyTracker, XRPositionalTracker);
_THREAD_SAFE_CLASS_
public:
enum BodyFlags {
BODY_FLAG_UPPER_BODY_SUPPORTED = 1,
BODY_FLAG_LOWER_BODY_SUPPORTED = 2,
BODY_FLAG_HANDS_SUPPORTED = 4,
};
enum Joint {
JOINT_ROOT,
// Upper Body Joints
JOINT_HIPS,
JOINT_SPINE,
JOINT_CHEST,
JOINT_UPPER_CHEST,
JOINT_NECK,
JOINT_HEAD,
JOINT_HEAD_TIP,
JOINT_LEFT_SHOULDER,
JOINT_LEFT_UPPER_ARM,
JOINT_LEFT_LOWER_ARM,
JOINT_RIGHT_SHOULDER,
JOINT_RIGHT_UPPER_ARM,
JOINT_RIGHT_LOWER_ARM,
// Lower Body Joints
JOINT_LEFT_UPPER_LEG,
JOINT_LEFT_LOWER_LEG,
JOINT_LEFT_FOOT,
JOINT_LEFT_TOES,
JOINT_RIGHT_UPPER_LEG,
JOINT_RIGHT_LOWER_LEG,
JOINT_RIGHT_FOOT,
JOINT_RIGHT_TOES,
// Left Hand Joints
JOINT_LEFT_HAND,
JOINT_LEFT_PALM,
JOINT_LEFT_WRIST,
JOINT_LEFT_THUMB_METACARPAL,
JOINT_LEFT_THUMB_PHALANX_PROXIMAL,
JOINT_LEFT_THUMB_PHALANX_DISTAL,
JOINT_LEFT_THUMB_TIP,
JOINT_LEFT_INDEX_FINGER_METACARPAL,
JOINT_LEFT_INDEX_FINGER_PHALANX_PROXIMAL,
JOINT_LEFT_INDEX_FINGER_PHALANX_INTERMEDIATE,
JOINT_LEFT_INDEX_FINGER_PHALANX_DISTAL,
JOINT_LEFT_INDEX_FINGER_TIP,
JOINT_LEFT_MIDDLE_FINGER_METACARPAL,
JOINT_LEFT_MIDDLE_FINGER_PHALANX_PROXIMAL,
JOINT_LEFT_MIDDLE_FINGER_PHALANX_INTERMEDIATE,
JOINT_LEFT_MIDDLE_FINGER_PHALANX_DISTAL,
JOINT_LEFT_MIDDLE_FINGER_TIP,
JOINT_LEFT_RING_FINGER_METACARPAL,
JOINT_LEFT_RING_FINGER_PHALANX_PROXIMAL,
JOINT_LEFT_RING_FINGER_PHALANX_INTERMEDIATE,
JOINT_LEFT_RING_FINGER_PHALANX_DISTAL,
JOINT_LEFT_RING_FINGER_TIP,
JOINT_LEFT_PINKY_FINGER_METACARPAL,
JOINT_LEFT_PINKY_FINGER_PHALANX_PROXIMAL,
JOINT_LEFT_PINKY_FINGER_PHALANX_INTERMEDIATE,
JOINT_LEFT_PINKY_FINGER_PHALANX_DISTAL,
JOINT_LEFT_PINKY_FINGER_TIP,
// Right Hand Joints
JOINT_RIGHT_HAND,
JOINT_RIGHT_PALM,
JOINT_RIGHT_WRIST,
JOINT_RIGHT_THUMB_METACARPAL,
JOINT_RIGHT_THUMB_PHALANX_PROXIMAL,
JOINT_RIGHT_THUMB_PHALANX_DISTAL,
JOINT_RIGHT_THUMB_TIP,
JOINT_RIGHT_INDEX_FINGER_METACARPAL,
JOINT_RIGHT_INDEX_FINGER_PHALANX_PROXIMAL,
JOINT_RIGHT_INDEX_FINGER_PHALANX_INTERMEDIATE,
JOINT_RIGHT_INDEX_FINGER_PHALANX_DISTAL,
JOINT_RIGHT_INDEX_FINGER_TIP,
JOINT_RIGHT_MIDDLE_FINGER_METACARPAL,
JOINT_RIGHT_MIDDLE_FINGER_PHALANX_PROXIMAL,
JOINT_RIGHT_MIDDLE_FINGER_PHALANX_INTERMEDIATE,
JOINT_RIGHT_MIDDLE_FINGER_PHALANX_DISTAL,
JOINT_RIGHT_MIDDLE_FINGER_TIP,
JOINT_RIGHT_RING_FINGER_METACARPAL,
JOINT_RIGHT_RING_FINGER_PHALANX_PROXIMAL,
JOINT_RIGHT_RING_FINGER_PHALANX_INTERMEDIATE,
JOINT_RIGHT_RING_FINGER_PHALANX_DISTAL,
JOINT_RIGHT_RING_FINGER_TIP,
JOINT_RIGHT_PINKY_FINGER_METACARPAL,
JOINT_RIGHT_PINKY_FINGER_PHALANX_PROXIMAL,
JOINT_RIGHT_PINKY_FINGER_PHALANX_INTERMEDIATE,
JOINT_RIGHT_PINKY_FINGER_PHALANX_DISTAL,
JOINT_RIGHT_PINKY_FINGER_TIP,
// Extra joints that aren't part of the Godot humanoid skeleton, but are commonly used in some VR avatars.
JOINT_LOWER_CHEST,
JOINT_LEFT_SCAPULA,
JOINT_LEFT_WRIST_TWIST,
JOINT_RIGHT_SCAPULA,
JOINT_RIGHT_WRIST_TWIST,
JOINT_LEFT_FOOT_TWIST,
JOINT_LEFT_HEEL,
JOINT_LEFT_MIDDLE_FOOT,
JOINT_RIGHT_FOOT_TWIST,
JOINT_RIGHT_HEEL,
JOINT_RIGHT_MIDDLE_FOOT,
JOINT_MAX,
};
enum JointFlags {
JOINT_FLAG_ORIENTATION_VALID = 1,
JOINT_FLAG_ORIENTATION_TRACKED = 2,
JOINT_FLAG_POSITION_VALID = 4,
JOINT_FLAG_POSITION_TRACKED = 8,
};
void set_tracker_type(XRServer::TrackerType p_type) override;
void set_tracker_hand(const XRPositionalTracker::TrackerHand p_hand) override;
void set_has_tracking_data(bool p_has_tracking_data);
bool get_has_tracking_data() const;
void set_body_flags(BitField<BodyFlags> p_body_flags);
BitField<BodyFlags> get_body_flags() const;
void set_joint_flags(Joint p_joint, BitField<JointFlags> p_flags);
BitField<JointFlags> get_joint_flags(Joint p_joint) const;
void set_joint_transform(Joint p_joint, const Transform3D &p_transform);
Transform3D get_joint_transform(Joint p_joint) const;
XRBodyTracker();
protected:
static void _bind_methods();
private:
bool has_tracking_data = false;
BitField<BodyFlags> body_flags = {};
BitField<JointFlags> joint_flags[JOINT_MAX];
Transform3D joint_transforms[JOINT_MAX];
};
VARIANT_BITFIELD_CAST(XRBodyTracker::BodyFlags)
VARIANT_ENUM_CAST(XRBodyTracker::Joint)
VARIANT_BITFIELD_CAST(XRBodyTracker::JointFlags)

View File

@@ -0,0 +1,39 @@
/**************************************************************************/
/* xr_controller_tracker.cpp */
/**************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
/* https://godotengine.org */
/**************************************************************************/
/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
/* */
/* 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_controller_tracker.h"
#include "core/input/input.h"
void XRControllerTracker::_bind_methods() {}
XRControllerTracker::XRControllerTracker() {
type = XRServer::TRACKER_CONTROLLER;
}

View File

@@ -0,0 +1,49 @@
/**************************************************************************/
/* xr_controller_tracker.h */
/**************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
/* https://godotengine.org */
/**************************************************************************/
/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
/* */
/* 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. */
/**************************************************************************/
#pragma once
#include "core/os/thread_safe.h"
#include "servers/xr/xr_positional_tracker.h"
/**
The controller tracker object as an object that represents the position and orientation of a controller.
*/
class XRControllerTracker : public XRPositionalTracker {
GDCLASS(XRControllerTracker, XRPositionalTracker);
_THREAD_SAFE_CLASS_
protected:
static void _bind_methods();
public:
XRControllerTracker();
};

View File

@@ -0,0 +1,230 @@
/**************************************************************************/
/* xr_face_tracker.cpp */
/**************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
/* https://godotengine.org */
/**************************************************************************/
/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
/* */
/* 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_face_tracker.h"
void XRFaceTracker::_bind_methods() {
// Base Shapes
BIND_ENUM_CONSTANT(FT_EYE_LOOK_OUT_RIGHT);
BIND_ENUM_CONSTANT(FT_EYE_LOOK_IN_RIGHT);
BIND_ENUM_CONSTANT(FT_EYE_LOOK_UP_RIGHT);
BIND_ENUM_CONSTANT(FT_EYE_LOOK_DOWN_RIGHT);
BIND_ENUM_CONSTANT(FT_EYE_LOOK_OUT_LEFT);
BIND_ENUM_CONSTANT(FT_EYE_LOOK_IN_LEFT);
BIND_ENUM_CONSTANT(FT_EYE_LOOK_UP_LEFT);
BIND_ENUM_CONSTANT(FT_EYE_LOOK_DOWN_LEFT);
BIND_ENUM_CONSTANT(FT_EYE_CLOSED_RIGHT);
BIND_ENUM_CONSTANT(FT_EYE_CLOSED_LEFT);
BIND_ENUM_CONSTANT(FT_EYE_SQUINT_RIGHT);
BIND_ENUM_CONSTANT(FT_EYE_SQUINT_LEFT);
BIND_ENUM_CONSTANT(FT_EYE_WIDE_RIGHT);
BIND_ENUM_CONSTANT(FT_EYE_WIDE_LEFT);
BIND_ENUM_CONSTANT(FT_EYE_DILATION_RIGHT);
BIND_ENUM_CONSTANT(FT_EYE_DILATION_LEFT);
BIND_ENUM_CONSTANT(FT_EYE_CONSTRICT_RIGHT);
BIND_ENUM_CONSTANT(FT_EYE_CONSTRICT_LEFT);
BIND_ENUM_CONSTANT(FT_BROW_PINCH_RIGHT);
BIND_ENUM_CONSTANT(FT_BROW_PINCH_LEFT);
BIND_ENUM_CONSTANT(FT_BROW_LOWERER_RIGHT);
BIND_ENUM_CONSTANT(FT_BROW_LOWERER_LEFT);
BIND_ENUM_CONSTANT(FT_BROW_INNER_UP_RIGHT);
BIND_ENUM_CONSTANT(FT_BROW_INNER_UP_LEFT);
BIND_ENUM_CONSTANT(FT_BROW_OUTER_UP_RIGHT);
BIND_ENUM_CONSTANT(FT_BROW_OUTER_UP_LEFT);
BIND_ENUM_CONSTANT(FT_NOSE_SNEER_RIGHT);
BIND_ENUM_CONSTANT(FT_NOSE_SNEER_LEFT);
BIND_ENUM_CONSTANT(FT_NASAL_DILATION_RIGHT);
BIND_ENUM_CONSTANT(FT_NASAL_DILATION_LEFT);
BIND_ENUM_CONSTANT(FT_NASAL_CONSTRICT_RIGHT);
BIND_ENUM_CONSTANT(FT_NASAL_CONSTRICT_LEFT);
BIND_ENUM_CONSTANT(FT_CHEEK_SQUINT_RIGHT);
BIND_ENUM_CONSTANT(FT_CHEEK_SQUINT_LEFT);
BIND_ENUM_CONSTANT(FT_CHEEK_PUFF_RIGHT);
BIND_ENUM_CONSTANT(FT_CHEEK_PUFF_LEFT);
BIND_ENUM_CONSTANT(FT_CHEEK_SUCK_RIGHT);
BIND_ENUM_CONSTANT(FT_CHEEK_SUCK_LEFT);
BIND_ENUM_CONSTANT(FT_JAW_OPEN);
BIND_ENUM_CONSTANT(FT_MOUTH_CLOSED);
BIND_ENUM_CONSTANT(FT_JAW_RIGHT);
BIND_ENUM_CONSTANT(FT_JAW_LEFT);
BIND_ENUM_CONSTANT(FT_JAW_FORWARD);
BIND_ENUM_CONSTANT(FT_JAW_BACKWARD);
BIND_ENUM_CONSTANT(FT_JAW_CLENCH);
BIND_ENUM_CONSTANT(FT_JAW_MANDIBLE_RAISE);
BIND_ENUM_CONSTANT(FT_LIP_SUCK_UPPER_RIGHT);
BIND_ENUM_CONSTANT(FT_LIP_SUCK_UPPER_LEFT);
BIND_ENUM_CONSTANT(FT_LIP_SUCK_LOWER_RIGHT);
BIND_ENUM_CONSTANT(FT_LIP_SUCK_LOWER_LEFT);
BIND_ENUM_CONSTANT(FT_LIP_SUCK_CORNER_RIGHT);
BIND_ENUM_CONSTANT(FT_LIP_SUCK_CORNER_LEFT);
BIND_ENUM_CONSTANT(FT_LIP_FUNNEL_UPPER_RIGHT);
BIND_ENUM_CONSTANT(FT_LIP_FUNNEL_UPPER_LEFT);
BIND_ENUM_CONSTANT(FT_LIP_FUNNEL_LOWER_RIGHT);
BIND_ENUM_CONSTANT(FT_LIP_FUNNEL_LOWER_LEFT);
BIND_ENUM_CONSTANT(FT_LIP_PUCKER_UPPER_RIGHT);
BIND_ENUM_CONSTANT(FT_LIP_PUCKER_UPPER_LEFT);
BIND_ENUM_CONSTANT(FT_LIP_PUCKER_LOWER_RIGHT);
BIND_ENUM_CONSTANT(FT_LIP_PUCKER_LOWER_LEFT);
BIND_ENUM_CONSTANT(FT_MOUTH_UPPER_UP_RIGHT);
BIND_ENUM_CONSTANT(FT_MOUTH_UPPER_UP_LEFT);
BIND_ENUM_CONSTANT(FT_MOUTH_LOWER_DOWN_RIGHT);
BIND_ENUM_CONSTANT(FT_MOUTH_LOWER_DOWN_LEFT);
BIND_ENUM_CONSTANT(FT_MOUTH_UPPER_DEEPEN_RIGHT);
BIND_ENUM_CONSTANT(FT_MOUTH_UPPER_DEEPEN_LEFT);
BIND_ENUM_CONSTANT(FT_MOUTH_UPPER_RIGHT);
BIND_ENUM_CONSTANT(FT_MOUTH_UPPER_LEFT);
BIND_ENUM_CONSTANT(FT_MOUTH_LOWER_RIGHT);
BIND_ENUM_CONSTANT(FT_MOUTH_LOWER_LEFT);
BIND_ENUM_CONSTANT(FT_MOUTH_CORNER_PULL_RIGHT);
BIND_ENUM_CONSTANT(FT_MOUTH_CORNER_PULL_LEFT);
BIND_ENUM_CONSTANT(FT_MOUTH_CORNER_SLANT_RIGHT);
BIND_ENUM_CONSTANT(FT_MOUTH_CORNER_SLANT_LEFT);
BIND_ENUM_CONSTANT(FT_MOUTH_FROWN_RIGHT);
BIND_ENUM_CONSTANT(FT_MOUTH_FROWN_LEFT);
BIND_ENUM_CONSTANT(FT_MOUTH_STRETCH_RIGHT);
BIND_ENUM_CONSTANT(FT_MOUTH_STRETCH_LEFT);
BIND_ENUM_CONSTANT(FT_MOUTH_DIMPLE_RIGHT);
BIND_ENUM_CONSTANT(FT_MOUTH_DIMPLE_LEFT);
BIND_ENUM_CONSTANT(FT_MOUTH_RAISER_UPPER);
BIND_ENUM_CONSTANT(FT_MOUTH_RAISER_LOWER);
BIND_ENUM_CONSTANT(FT_MOUTH_PRESS_RIGHT);
BIND_ENUM_CONSTANT(FT_MOUTH_PRESS_LEFT);
BIND_ENUM_CONSTANT(FT_MOUTH_TIGHTENER_RIGHT);
BIND_ENUM_CONSTANT(FT_MOUTH_TIGHTENER_LEFT);
BIND_ENUM_CONSTANT(FT_TONGUE_OUT);
BIND_ENUM_CONSTANT(FT_TONGUE_UP);
BIND_ENUM_CONSTANT(FT_TONGUE_DOWN);
BIND_ENUM_CONSTANT(FT_TONGUE_RIGHT);
BIND_ENUM_CONSTANT(FT_TONGUE_LEFT);
BIND_ENUM_CONSTANT(FT_TONGUE_ROLL);
BIND_ENUM_CONSTANT(FT_TONGUE_BLEND_DOWN);
BIND_ENUM_CONSTANT(FT_TONGUE_CURL_UP);
BIND_ENUM_CONSTANT(FT_TONGUE_SQUISH);
BIND_ENUM_CONSTANT(FT_TONGUE_FLAT);
BIND_ENUM_CONSTANT(FT_TONGUE_TWIST_RIGHT);
BIND_ENUM_CONSTANT(FT_TONGUE_TWIST_LEFT);
BIND_ENUM_CONSTANT(FT_SOFT_PALATE_CLOSE);
BIND_ENUM_CONSTANT(FT_THROAT_SWALLOW);
BIND_ENUM_CONSTANT(FT_NECK_FLEX_RIGHT);
BIND_ENUM_CONSTANT(FT_NECK_FLEX_LEFT);
// Blended Shapes
BIND_ENUM_CONSTANT(FT_EYE_CLOSED);
BIND_ENUM_CONSTANT(FT_EYE_WIDE);
BIND_ENUM_CONSTANT(FT_EYE_SQUINT);
BIND_ENUM_CONSTANT(FT_EYE_DILATION);
BIND_ENUM_CONSTANT(FT_EYE_CONSTRICT);
BIND_ENUM_CONSTANT(FT_BROW_DOWN_RIGHT);
BIND_ENUM_CONSTANT(FT_BROW_DOWN_LEFT);
BIND_ENUM_CONSTANT(FT_BROW_DOWN);
BIND_ENUM_CONSTANT(FT_BROW_UP_RIGHT);
BIND_ENUM_CONSTANT(FT_BROW_UP_LEFT);
BIND_ENUM_CONSTANT(FT_BROW_UP);
BIND_ENUM_CONSTANT(FT_NOSE_SNEER);
BIND_ENUM_CONSTANT(FT_NASAL_DILATION);
BIND_ENUM_CONSTANT(FT_NASAL_CONSTRICT);
BIND_ENUM_CONSTANT(FT_CHEEK_PUFF);
BIND_ENUM_CONSTANT(FT_CHEEK_SUCK);
BIND_ENUM_CONSTANT(FT_CHEEK_SQUINT);
BIND_ENUM_CONSTANT(FT_LIP_SUCK_UPPER);
BIND_ENUM_CONSTANT(FT_LIP_SUCK_LOWER);
BIND_ENUM_CONSTANT(FT_LIP_SUCK);
BIND_ENUM_CONSTANT(FT_LIP_FUNNEL_UPPER);
BIND_ENUM_CONSTANT(FT_LIP_FUNNEL_LOWER);
BIND_ENUM_CONSTANT(FT_LIP_FUNNEL);
BIND_ENUM_CONSTANT(FT_LIP_PUCKER_UPPER);
BIND_ENUM_CONSTANT(FT_LIP_PUCKER_LOWER);
BIND_ENUM_CONSTANT(FT_LIP_PUCKER);
BIND_ENUM_CONSTANT(FT_MOUTH_UPPER_UP);
BIND_ENUM_CONSTANT(FT_MOUTH_LOWER_DOWN);
BIND_ENUM_CONSTANT(FT_MOUTH_OPEN);
BIND_ENUM_CONSTANT(FT_MOUTH_RIGHT);
BIND_ENUM_CONSTANT(FT_MOUTH_LEFT);
BIND_ENUM_CONSTANT(FT_MOUTH_SMILE_RIGHT);
BIND_ENUM_CONSTANT(FT_MOUTH_SMILE_LEFT);
BIND_ENUM_CONSTANT(FT_MOUTH_SMILE);
BIND_ENUM_CONSTANT(FT_MOUTH_SAD_RIGHT);
BIND_ENUM_CONSTANT(FT_MOUTH_SAD_LEFT);
BIND_ENUM_CONSTANT(FT_MOUTH_SAD);
BIND_ENUM_CONSTANT(FT_MOUTH_STRETCH);
BIND_ENUM_CONSTANT(FT_MOUTH_DIMPLE);
BIND_ENUM_CONSTANT(FT_MOUTH_TIGHTENER);
BIND_ENUM_CONSTANT(FT_MOUTH_PRESS);
BIND_ENUM_CONSTANT(FT_MAX);
ClassDB::bind_method(D_METHOD("get_blend_shape", "blend_shape"), &XRFaceTracker::get_blend_shape);
ClassDB::bind_method(D_METHOD("set_blend_shape", "blend_shape", "weight"), &XRFaceTracker::set_blend_shape);
ClassDB::bind_method(D_METHOD("get_blend_shapes"), &XRFaceTracker::get_blend_shapes);
ClassDB::bind_method(D_METHOD("set_blend_shapes", "weights"), &XRFaceTracker::set_blend_shapes);
ADD_PROPERTY(PropertyInfo(Variant::PACKED_FLOAT32_ARRAY, "blend_shapes"), "set_blend_shapes", "get_blend_shapes");
ADD_PROPERTY_DEFAULT("blend_shapes", PackedFloat32Array()); // To prevent ludicrously large default values.
}
void XRFaceTracker::set_tracker_type(XRServer::TrackerType p_type) {
ERR_FAIL_COND_MSG(p_type != XRServer::TRACKER_FACE, "XRFaceTracker must be of type TRACKER_FACE.");
}
float XRFaceTracker::get_blend_shape(BlendShapeEntry p_blend_shape) const {
// Fail if the blend shape index is out of range.
ERR_FAIL_INDEX_V(p_blend_shape, FT_MAX, 0.0f);
// Return the blend shape value.
return blend_shape_values[p_blend_shape];
}
void XRFaceTracker::set_blend_shape(BlendShapeEntry p_blend_shape, float p_value) {
// Fail if the blend shape index is out of range.
ERR_FAIL_INDEX(p_blend_shape, FT_MAX);
// Save the new blend shape value.
blend_shape_values[p_blend_shape] = p_value;
}
PackedFloat32Array XRFaceTracker::get_blend_shapes() const {
// Create a packed float32 array and copy the blend shape values into it.
PackedFloat32Array data;
data.resize(FT_MAX);
memcpy(data.ptrw(), blend_shape_values, sizeof(blend_shape_values));
// Return the blend shape array.
return data;
}
void XRFaceTracker::set_blend_shapes(const PackedFloat32Array &p_blend_shapes) {
// Fail if the blend shape array is not the correct size.
ERR_FAIL_COND(p_blend_shapes.size() != FT_MAX);
// Copy the blend shape values into the blend shape array.
memcpy(blend_shape_values, p_blend_shapes.ptr(), sizeof(blend_shape_values));
}
XRFaceTracker::XRFaceTracker() {
type = XRServer::TRACKER_FACE;
}

View File

@@ -0,0 +1,214 @@
/**************************************************************************/
/* xr_face_tracker.h */
/**************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
/* https://godotengine.org */
/**************************************************************************/
/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
/* */
/* 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. */
/**************************************************************************/
#pragma once
#include "servers/xr/xr_tracker.h"
/**
The XRFaceTracker class provides face blend shape weights.
The supported blend shapes are based on the Unified Expressions
standard, and as such have a well defined mapping to ARKit, SRanipal,
and Meta Movement standards.
*/
class XRFaceTracker : public XRTracker {
GDCLASS(XRFaceTracker, XRTracker);
_THREAD_SAFE_CLASS_
public:
enum BlendShapeEntry {
// Base Shapes
FT_EYE_LOOK_OUT_RIGHT, // Right eye looks outwards.
FT_EYE_LOOK_IN_RIGHT, // Right eye looks inwards.
FT_EYE_LOOK_UP_RIGHT, // Right eye looks upwards.
FT_EYE_LOOK_DOWN_RIGHT, // Right eye looks downwards.
FT_EYE_LOOK_OUT_LEFT, // Left eye looks outwards.
FT_EYE_LOOK_IN_LEFT, // Left eye looks inwards.
FT_EYE_LOOK_UP_LEFT, // Left eye looks upwards.
FT_EYE_LOOK_DOWN_LEFT, // Left eye looks downwards.
FT_EYE_CLOSED_RIGHT, // Closes the right eyelid.
FT_EYE_CLOSED_LEFT, // Closes the left eyelid.
FT_EYE_SQUINT_RIGHT, // Squeezes the right eye socket muscles.
FT_EYE_SQUINT_LEFT, // Squeezes the left eye socket muscles.
FT_EYE_WIDE_RIGHT, // Right eyelid widens beyond relaxed.
FT_EYE_WIDE_LEFT, // Left eyelid widens beyond relaxed.
FT_EYE_DILATION_RIGHT, // Dilates the right eye pupil.
FT_EYE_DILATION_LEFT, // Dilates the left eye pupil.
FT_EYE_CONSTRICT_RIGHT, // Constricts the right eye pupil.
FT_EYE_CONSTRICT_LEFT, // Constricts the left eye pupil.
FT_BROW_PINCH_RIGHT, // Right eyebrow pinches in.
FT_BROW_PINCH_LEFT, // Left eyebrow pinches in.
FT_BROW_LOWERER_RIGHT, // Outer right eyebrow pulls down.
FT_BROW_LOWERER_LEFT, // Outer left eyebrow pulls down.
FT_BROW_INNER_UP_RIGHT, // Inner right eyebrow pulls up.
FT_BROW_INNER_UP_LEFT, // Inner left eyebrow pulls up.
FT_BROW_OUTER_UP_RIGHT, // Outer right eyebrow pulls up.
FT_BROW_OUTER_UP_LEFT, // Outer left eyebrow pulls up.
FT_NOSE_SNEER_RIGHT, // Right side face sneers.
FT_NOSE_SNEER_LEFT, // Left side face sneers.
FT_NASAL_DILATION_RIGHT, // Right side nose canal dilates.
FT_NASAL_DILATION_LEFT, // Left side nose canal dilates.
FT_NASAL_CONSTRICT_RIGHT, // Right side nose canal constricts.
FT_NASAL_CONSTRICT_LEFT, // Left side nose canal constricts.
FT_CHEEK_SQUINT_RIGHT, // Raises the right side cheek.
FT_CHEEK_SQUINT_LEFT, // Raises the left side cheek.
FT_CHEEK_PUFF_RIGHT, // Puffs the right side cheek.
FT_CHEEK_PUFF_LEFT, // Puffs the left side cheek.
FT_CHEEK_SUCK_RIGHT, // Sucks in the right side cheek.
FT_CHEEK_SUCK_LEFT, // Sucks in the left side cheek.
FT_JAW_OPEN, // Opens jawbone.
FT_MOUTH_CLOSED, // Closes the mouth.
FT_JAW_RIGHT, // Pushes jawbone right.
FT_JAW_LEFT, // Pushes jawbone left.
FT_JAW_FORWARD, // Pushes jawbone forward.
FT_JAW_BACKWARD, // Pushes jawbone backward.
FT_JAW_CLENCH, // Flexes jaw muscles.
FT_JAW_MANDIBLE_RAISE, // Raises the jawbone.
FT_LIP_SUCK_UPPER_RIGHT, // Upper right lip part tucks in the mouth.
FT_LIP_SUCK_UPPER_LEFT, // Upper left lip part tucks in the mouth.
FT_LIP_SUCK_LOWER_RIGHT, // Lower right lip part tucks in the mouth.
FT_LIP_SUCK_LOWER_LEFT, // Lower left lip part tucks in the mouth.
FT_LIP_SUCK_CORNER_RIGHT, // Right lip corner folds into the mouth.
FT_LIP_SUCK_CORNER_LEFT, // Left lip corner folds into the mouth.
FT_LIP_FUNNEL_UPPER_RIGHT, // Upper right lip part pushes into a funnel.
FT_LIP_FUNNEL_UPPER_LEFT, // Upper left lip part pushes into a funnel.
FT_LIP_FUNNEL_LOWER_RIGHT, // Lower right lip part pushes into a funnel.
FT_LIP_FUNNEL_LOWER_LEFT, // Lower left lip part pushes into a funnel.
FT_LIP_PUCKER_UPPER_RIGHT, // Upper right lip part pushes outwards.
FT_LIP_PUCKER_UPPER_LEFT, // Upper left lip part pushes outwards.
FT_LIP_PUCKER_LOWER_RIGHT, // Lower right lip part pushes outwards.
FT_LIP_PUCKER_LOWER_LEFT, // Lower left lip part pushes outwards.
FT_MOUTH_UPPER_UP_RIGHT, // Upper right part of the lip pulls up.
FT_MOUTH_UPPER_UP_LEFT, // Upper left part of the lip pulls up.
FT_MOUTH_LOWER_DOWN_RIGHT, // Lower right part of the lip pulls up.
FT_MOUTH_LOWER_DOWN_LEFT, // Lower left part of the lip pulls up.
FT_MOUTH_UPPER_DEEPEN_RIGHT, // Upper right lip part pushes in the cheek.
FT_MOUTH_UPPER_DEEPEN_LEFT, // Upper left lip part pushes in the cheek.
FT_MOUTH_UPPER_RIGHT, // Moves upper lip right.
FT_MOUTH_UPPER_LEFT, // Moves upper lip left.
FT_MOUTH_LOWER_RIGHT, // Moves lower lip right.
FT_MOUTH_LOWER_LEFT, // Moves lower lip left.
FT_MOUTH_CORNER_PULL_RIGHT, // Right lip corner pulls diagonally up and out.
FT_MOUTH_CORNER_PULL_LEFT, // Left lip corner pulls diagonally up and out.
FT_MOUTH_CORNER_SLANT_RIGHT, // Right corner lip slants up.
FT_MOUTH_CORNER_SLANT_LEFT, // Left corner lip slants up.
FT_MOUTH_FROWN_RIGHT, // Right corner lip pulls down.
FT_MOUTH_FROWN_LEFT, // Left corner lip pulls down.
FT_MOUTH_STRETCH_RIGHT, // Mouth corner lip pulls out and down.
FT_MOUTH_STRETCH_LEFT, // Mouth corner lip pulls out and down.
FT_MOUTH_DIMPLE_RIGHT, // Right lip corner is pushed backwards.
FT_MOUTH_DIMPLE_LEFT, // Left lip corner is pushed backwards.
FT_MOUTH_RAISER_UPPER, // Raises and slightly pushes out the upper mouth.
FT_MOUTH_RAISER_LOWER, // Raises and slightly pushes out the lower mouth.
FT_MOUTH_PRESS_RIGHT, // Right side lips press and flatten together vertically.
FT_MOUTH_PRESS_LEFT, // Left side lips press and flatten together vertically.
FT_MOUTH_TIGHTENER_RIGHT, // Right side lips squeeze together horizontally.
FT_MOUTH_TIGHTENER_LEFT, // Left side lips squeeze together horizontally.
FT_TONGUE_OUT, // Tongue visibly sticks out of the mouth.
FT_TONGUE_UP, // Tongue points upwards.
FT_TONGUE_DOWN, // Tongue points downwards.
FT_TONGUE_RIGHT, // Tongue points right.
FT_TONGUE_LEFT, // Tongue points left.
FT_TONGUE_ROLL, // Sides of the tongue funnel, creating a roll.
FT_TONGUE_BLEND_DOWN, // Tongue arches up then down inside the mouth.
FT_TONGUE_CURL_UP, // Tongue arches down then up inside the mouth.
FT_TONGUE_SQUISH, // Tongue squishes together and thickens.
FT_TONGUE_FLAT, // Tongue flattens and thins out.
FT_TONGUE_TWIST_RIGHT, // Tongue tip rotates clockwise, with the rest following gradually.
FT_TONGUE_TWIST_LEFT, // Tongue tip rotates counter-clockwise, with the rest following gradually.
FT_SOFT_PALATE_CLOSE, // Inner mouth throat closes.
FT_THROAT_SWALLOW, // The Adam's apple visibly swallows.
FT_NECK_FLEX_RIGHT, // Right side neck visibly flexes.
FT_NECK_FLEX_LEFT, // Left side neck visibly flexes.
// Blended Shapes
FT_EYE_CLOSED, // Closes both eye lids.
FT_EYE_WIDE, // Widens both eye lids.
FT_EYE_SQUINT, // Squints both eye lids.
FT_EYE_DILATION, // Dilates both pupils.
FT_EYE_CONSTRICT, // Constricts both pupils.
FT_BROW_DOWN_RIGHT, // Pulls the right eyebrow down and in.
FT_BROW_DOWN_LEFT, // Pulls the left eyebrow down and in.
FT_BROW_DOWN, // Pulls both eyebrows down and in.
FT_BROW_UP_RIGHT, // Right brow appears worried.
FT_BROW_UP_LEFT, // Left brow appears worried.
FT_BROW_UP, // Both brows appear worried.
FT_NOSE_SNEER, // Entire face sneers.
FT_NASAL_DILATION, // Both nose canals dilate.
FT_NASAL_CONSTRICT, // Both nose canals constrict.
FT_CHEEK_PUFF, // Puffs both cheeks.
FT_CHEEK_SUCK, // Sucks in both cheeks.
FT_CHEEK_SQUINT, // Raises both cheeks.
FT_LIP_SUCK_UPPER, // Tucks in the upper lips.
FT_LIP_SUCK_LOWER, // Tucks in the lower lips.
FT_LIP_SUCK, // Tucks in both lips.
FT_LIP_FUNNEL_UPPER, // Funnels in the upper lips.
FT_LIP_FUNNEL_LOWER, // Funnels in the lower lips.
FT_LIP_FUNNEL, // Funnels in both lips.
FT_LIP_PUCKER_UPPER, // Upper lip part pushes outwards.
FT_LIP_PUCKER_LOWER, // Lower lip part pushes outwards.
FT_LIP_PUCKER, // Lips push outwards.
FT_MOUTH_UPPER_UP, // Raises the upper lips.
FT_MOUTH_LOWER_DOWN, // Lowers the lower lips.
FT_MOUTH_OPEN, // Mouth opens, revealing teeth.
FT_MOUTH_RIGHT, // Moves mouth right.
FT_MOUTH_LEFT, // Moves mouth left.
FT_MOUTH_SMILE_RIGHT, // Right side of the mouth smiles.
FT_MOUTH_SMILE_LEFT, // Left side of the mouth smiles.
FT_MOUTH_SMILE, // Mouth expresses a smile.
FT_MOUTH_SAD_RIGHT, // Right side of the mouth expresses sadness.
FT_MOUTH_SAD_LEFT, // Left side of the mouth expresses sadness.
FT_MOUTH_SAD, // Mouth expresses sadness.
FT_MOUTH_STRETCH, // Mouth stretches.
FT_MOUTH_DIMPLE, // Lip corners dimple.
FT_MOUTH_TIGHTENER, // Mouth tightens.
FT_MOUTH_PRESS, // Mouth presses together.
FT_MAX // Maximum blend shape.
};
void set_tracker_type(XRServer::TrackerType p_type) override;
float get_blend_shape(BlendShapeEntry p_blend_shape) const;
void set_blend_shape(BlendShapeEntry p_blend_shape, float p_value);
PackedFloat32Array get_blend_shapes() const;
void set_blend_shapes(const PackedFloat32Array &p_blend_shapes);
XRFaceTracker();
protected:
static void _bind_methods();
private:
float blend_shape_values[FT_MAX] = {};
};
VARIANT_ENUM_CAST(XRFaceTracker::BlendShapeEntry);

View File

@@ -0,0 +1,178 @@
/**************************************************************************/
/* xr_hand_tracker.cpp */
/**************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
/* https://godotengine.org */
/**************************************************************************/
/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
/* */
/* 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_hand_tracker.h"
void XRHandTracker::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_has_tracking_data", "has_data"), &XRHandTracker::set_has_tracking_data);
ClassDB::bind_method(D_METHOD("get_has_tracking_data"), &XRHandTracker::get_has_tracking_data);
ClassDB::bind_method(D_METHOD("set_hand_tracking_source", "source"), &XRHandTracker::set_hand_tracking_source);
ClassDB::bind_method(D_METHOD("get_hand_tracking_source"), &XRHandTracker::get_hand_tracking_source);
ClassDB::bind_method(D_METHOD("set_hand_joint_flags", "joint", "flags"), &XRHandTracker::set_hand_joint_flags);
ClassDB::bind_method(D_METHOD("get_hand_joint_flags", "joint"), &XRHandTracker::get_hand_joint_flags);
ClassDB::bind_method(D_METHOD("set_hand_joint_transform", "joint", "transform"), &XRHandTracker::set_hand_joint_transform);
ClassDB::bind_method(D_METHOD("get_hand_joint_transform", "joint"), &XRHandTracker::get_hand_joint_transform);
ClassDB::bind_method(D_METHOD("set_hand_joint_radius", "joint", "radius"), &XRHandTracker::set_hand_joint_radius);
ClassDB::bind_method(D_METHOD("get_hand_joint_radius", "joint"), &XRHandTracker::get_hand_joint_radius);
ClassDB::bind_method(D_METHOD("set_hand_joint_linear_velocity", "joint", "linear_velocity"), &XRHandTracker::set_hand_joint_linear_velocity);
ClassDB::bind_method(D_METHOD("get_hand_joint_linear_velocity", "joint"), &XRHandTracker::get_hand_joint_linear_velocity);
ClassDB::bind_method(D_METHOD("set_hand_joint_angular_velocity", "joint", "angular_velocity"), &XRHandTracker::set_hand_joint_angular_velocity);
ClassDB::bind_method(D_METHOD("get_hand_joint_angular_velocity", "joint"), &XRHandTracker::get_hand_joint_angular_velocity);
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "has_tracking_data", PROPERTY_HINT_NONE), "set_has_tracking_data", "get_has_tracking_data");
ADD_PROPERTY(PropertyInfo(Variant::INT, "hand_tracking_source", PROPERTY_HINT_ENUM, "Unknown,Unobstructed,Controller"), "set_hand_tracking_source", "get_hand_tracking_source");
BIND_ENUM_CONSTANT(HAND_TRACKING_SOURCE_UNKNOWN);
BIND_ENUM_CONSTANT(HAND_TRACKING_SOURCE_UNOBSTRUCTED);
BIND_ENUM_CONSTANT(HAND_TRACKING_SOURCE_CONTROLLER);
BIND_ENUM_CONSTANT(HAND_TRACKING_SOURCE_NOT_TRACKED);
BIND_ENUM_CONSTANT(HAND_TRACKING_SOURCE_MAX);
BIND_ENUM_CONSTANT(HAND_JOINT_PALM);
BIND_ENUM_CONSTANT(HAND_JOINT_WRIST);
BIND_ENUM_CONSTANT(HAND_JOINT_THUMB_METACARPAL);
BIND_ENUM_CONSTANT(HAND_JOINT_THUMB_PHALANX_PROXIMAL);
BIND_ENUM_CONSTANT(HAND_JOINT_THUMB_PHALANX_DISTAL);
BIND_ENUM_CONSTANT(HAND_JOINT_THUMB_TIP);
BIND_ENUM_CONSTANT(HAND_JOINT_INDEX_FINGER_METACARPAL);
BIND_ENUM_CONSTANT(HAND_JOINT_INDEX_FINGER_PHALANX_PROXIMAL);
BIND_ENUM_CONSTANT(HAND_JOINT_INDEX_FINGER_PHALANX_INTERMEDIATE);
BIND_ENUM_CONSTANT(HAND_JOINT_INDEX_FINGER_PHALANX_DISTAL);
BIND_ENUM_CONSTANT(HAND_JOINT_INDEX_FINGER_TIP);
BIND_ENUM_CONSTANT(HAND_JOINT_MIDDLE_FINGER_METACARPAL);
BIND_ENUM_CONSTANT(HAND_JOINT_MIDDLE_FINGER_PHALANX_PROXIMAL);
BIND_ENUM_CONSTANT(HAND_JOINT_MIDDLE_FINGER_PHALANX_INTERMEDIATE);
BIND_ENUM_CONSTANT(HAND_JOINT_MIDDLE_FINGER_PHALANX_DISTAL);
BIND_ENUM_CONSTANT(HAND_JOINT_MIDDLE_FINGER_TIP);
BIND_ENUM_CONSTANT(HAND_JOINT_RING_FINGER_METACARPAL);
BIND_ENUM_CONSTANT(HAND_JOINT_RING_FINGER_PHALANX_PROXIMAL);
BIND_ENUM_CONSTANT(HAND_JOINT_RING_FINGER_PHALANX_INTERMEDIATE);
BIND_ENUM_CONSTANT(HAND_JOINT_RING_FINGER_PHALANX_DISTAL);
BIND_ENUM_CONSTANT(HAND_JOINT_RING_FINGER_TIP);
BIND_ENUM_CONSTANT(HAND_JOINT_PINKY_FINGER_METACARPAL);
BIND_ENUM_CONSTANT(HAND_JOINT_PINKY_FINGER_PHALANX_PROXIMAL);
BIND_ENUM_CONSTANT(HAND_JOINT_PINKY_FINGER_PHALANX_INTERMEDIATE);
BIND_ENUM_CONSTANT(HAND_JOINT_PINKY_FINGER_PHALANX_DISTAL);
BIND_ENUM_CONSTANT(HAND_JOINT_PINKY_FINGER_TIP);
BIND_ENUM_CONSTANT(HAND_JOINT_MAX);
BIND_BITFIELD_FLAG(HAND_JOINT_FLAG_ORIENTATION_VALID);
BIND_BITFIELD_FLAG(HAND_JOINT_FLAG_ORIENTATION_TRACKED);
BIND_BITFIELD_FLAG(HAND_JOINT_FLAG_POSITION_VALID);
BIND_BITFIELD_FLAG(HAND_JOINT_FLAG_POSITION_TRACKED);
BIND_BITFIELD_FLAG(HAND_JOINT_FLAG_LINEAR_VELOCITY_VALID);
BIND_BITFIELD_FLAG(HAND_JOINT_FLAG_ANGULAR_VELOCITY_VALID);
}
void XRHandTracker::set_tracker_type(XRServer::TrackerType p_type) {
ERR_FAIL_COND_MSG(p_type != XRServer::TRACKER_HAND, "XRHandTracker must be of type TRACKER_HAND.");
}
void XRHandTracker::set_tracker_hand(const XRPositionalTracker::TrackerHand p_hand) {
ERR_FAIL_COND_MSG(p_hand != TRACKER_HAND_LEFT && p_hand != TRACKER_HAND_RIGHT, "XRHandTracker must specify hand.");
tracker_hand = p_hand;
}
void XRHandTracker::set_has_tracking_data(bool p_has_tracking_data) {
has_tracking_data = p_has_tracking_data;
}
bool XRHandTracker::get_has_tracking_data() const {
return has_tracking_data;
}
void XRHandTracker::set_hand_tracking_source(XRHandTracker::HandTrackingSource p_source) {
hand_tracking_source = p_source;
}
XRHandTracker::HandTrackingSource XRHandTracker::get_hand_tracking_source() const {
return hand_tracking_source;
}
void XRHandTracker::set_hand_joint_flags(XRHandTracker::HandJoint p_joint, BitField<XRHandTracker::HandJointFlags> p_flags) {
ERR_FAIL_INDEX(p_joint, HAND_JOINT_MAX);
hand_joint_flags[p_joint] = p_flags;
}
BitField<XRHandTracker::HandJointFlags> XRHandTracker::get_hand_joint_flags(XRHandTracker::HandJoint p_joint) const {
ERR_FAIL_INDEX_V(p_joint, HAND_JOINT_MAX, BitField<HandJointFlags>());
return hand_joint_flags[p_joint];
}
void XRHandTracker::set_hand_joint_transform(XRHandTracker::HandJoint p_joint, const Transform3D &p_transform) {
ERR_FAIL_INDEX(p_joint, HAND_JOINT_MAX);
hand_joint_transforms[p_joint] = p_transform;
}
Transform3D XRHandTracker::get_hand_joint_transform(XRHandTracker::HandJoint p_joint) const {
ERR_FAIL_INDEX_V(p_joint, HAND_JOINT_MAX, Transform3D());
return hand_joint_transforms[p_joint];
}
void XRHandTracker::set_hand_joint_radius(XRHandTracker::HandJoint p_joint, float p_radius) {
ERR_FAIL_INDEX(p_joint, HAND_JOINT_MAX);
hand_joint_radii[p_joint] = p_radius;
}
float XRHandTracker::get_hand_joint_radius(XRHandTracker::HandJoint p_joint) const {
ERR_FAIL_INDEX_V(p_joint, HAND_JOINT_MAX, 0.0);
return hand_joint_radii[p_joint];
}
void XRHandTracker::set_hand_joint_linear_velocity(XRHandTracker::HandJoint p_joint, const Vector3 &p_velocity) {
ERR_FAIL_INDEX(p_joint, HAND_JOINT_MAX);
hand_joint_linear_velocities[p_joint] = p_velocity;
}
Vector3 XRHandTracker::get_hand_joint_linear_velocity(XRHandTracker::HandJoint p_joint) const {
ERR_FAIL_INDEX_V(p_joint, HAND_JOINT_MAX, Vector3());
return hand_joint_linear_velocities[p_joint];
}
void XRHandTracker::set_hand_joint_angular_velocity(XRHandTracker::HandJoint p_joint, const Vector3 &p_velocity) {
ERR_FAIL_INDEX(p_joint, HAND_JOINT_MAX);
hand_joint_angular_velocities[p_joint] = p_velocity;
}
Vector3 XRHandTracker::get_hand_joint_angular_velocity(XRHandTracker::HandJoint p_joint) const {
ERR_FAIL_INDEX_V(p_joint, HAND_JOINT_MAX, Vector3());
return hand_joint_angular_velocities[p_joint];
}
XRHandTracker::XRHandTracker() {
type = XRServer::TRACKER_HAND;
tracker_hand = TRACKER_HAND_LEFT;
}

View File

@@ -0,0 +1,129 @@
/**************************************************************************/
/* xr_hand_tracker.h */
/**************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
/* https://godotengine.org */
/**************************************************************************/
/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
/* */
/* 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. */
/**************************************************************************/
#pragma once
#include "servers/xr/xr_positional_tracker.h"
class XRHandTracker : public XRPositionalTracker {
GDCLASS(XRHandTracker, XRPositionalTracker);
_THREAD_SAFE_CLASS_
public:
enum HandTrackingSource {
HAND_TRACKING_SOURCE_UNKNOWN,
HAND_TRACKING_SOURCE_UNOBSTRUCTED,
HAND_TRACKING_SOURCE_CONTROLLER,
HAND_TRACKING_SOURCE_NOT_TRACKED,
HAND_TRACKING_SOURCE_MAX
};
enum HandJoint {
HAND_JOINT_PALM,
HAND_JOINT_WRIST,
HAND_JOINT_THUMB_METACARPAL,
HAND_JOINT_THUMB_PHALANX_PROXIMAL,
HAND_JOINT_THUMB_PHALANX_DISTAL,
HAND_JOINT_THUMB_TIP,
HAND_JOINT_INDEX_FINGER_METACARPAL,
HAND_JOINT_INDEX_FINGER_PHALANX_PROXIMAL,
HAND_JOINT_INDEX_FINGER_PHALANX_INTERMEDIATE,
HAND_JOINT_INDEX_FINGER_PHALANX_DISTAL,
HAND_JOINT_INDEX_FINGER_TIP,
HAND_JOINT_MIDDLE_FINGER_METACARPAL,
HAND_JOINT_MIDDLE_FINGER_PHALANX_PROXIMAL,
HAND_JOINT_MIDDLE_FINGER_PHALANX_INTERMEDIATE,
HAND_JOINT_MIDDLE_FINGER_PHALANX_DISTAL,
HAND_JOINT_MIDDLE_FINGER_TIP,
HAND_JOINT_RING_FINGER_METACARPAL,
HAND_JOINT_RING_FINGER_PHALANX_PROXIMAL,
HAND_JOINT_RING_FINGER_PHALANX_INTERMEDIATE,
HAND_JOINT_RING_FINGER_PHALANX_DISTAL,
HAND_JOINT_RING_FINGER_TIP,
HAND_JOINT_PINKY_FINGER_METACARPAL,
HAND_JOINT_PINKY_FINGER_PHALANX_PROXIMAL,
HAND_JOINT_PINKY_FINGER_PHALANX_INTERMEDIATE,
HAND_JOINT_PINKY_FINGER_PHALANX_DISTAL,
HAND_JOINT_PINKY_FINGER_TIP,
HAND_JOINT_MAX,
};
enum HandJointFlags {
HAND_JOINT_FLAG_ORIENTATION_VALID = 1,
HAND_JOINT_FLAG_ORIENTATION_TRACKED = 2,
HAND_JOINT_FLAG_POSITION_VALID = 4,
HAND_JOINT_FLAG_POSITION_TRACKED = 8,
HAND_JOINT_FLAG_LINEAR_VELOCITY_VALID = 16,
HAND_JOINT_FLAG_ANGULAR_VELOCITY_VALID = 32,
};
void set_tracker_type(XRServer::TrackerType p_type) override;
void set_tracker_hand(const XRPositionalTracker::TrackerHand p_hand) override;
void set_has_tracking_data(bool p_has_tracking_data);
bool get_has_tracking_data() const;
void set_hand_tracking_source(HandTrackingSource p_source);
HandTrackingSource get_hand_tracking_source() const;
void set_hand_joint_flags(HandJoint p_joint, BitField<HandJointFlags> p_flags);
BitField<HandJointFlags> get_hand_joint_flags(HandJoint p_joint) const;
void set_hand_joint_transform(HandJoint p_joint, const Transform3D &p_transform);
Transform3D get_hand_joint_transform(HandJoint p_joint) const;
void set_hand_joint_radius(HandJoint p_joint, float p_radius);
float get_hand_joint_radius(HandJoint p_joint) const;
void set_hand_joint_linear_velocity(HandJoint p_joint, const Vector3 &p_velocity);
Vector3 get_hand_joint_linear_velocity(HandJoint p_joint) const;
void set_hand_joint_angular_velocity(HandJoint p_joint, const Vector3 &p_velocity);
Vector3 get_hand_joint_angular_velocity(HandJoint p_joint) const;
XRHandTracker();
protected:
static void _bind_methods();
private:
bool has_tracking_data = false;
HandTrackingSource hand_tracking_source = HAND_TRACKING_SOURCE_UNKNOWN;
BitField<HandJointFlags> hand_joint_flags[HAND_JOINT_MAX];
Transform3D hand_joint_transforms[HAND_JOINT_MAX];
float hand_joint_radii[HAND_JOINT_MAX] = {};
Vector3 hand_joint_linear_velocities[HAND_JOINT_MAX];
Vector3 hand_joint_angular_velocities[HAND_JOINT_MAX];
};
VARIANT_ENUM_CAST(XRHandTracker::HandTrackingSource)
VARIANT_ENUM_CAST(XRHandTracker::HandJoint)
VARIANT_BITFIELD_CAST(XRHandTracker::HandJointFlags)

228
servers/xr/xr_interface.cpp Normal file
View File

@@ -0,0 +1,228 @@
/**************************************************************************/
/* xr_interface.cpp */
/**************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
/* https://godotengine.org */
/**************************************************************************/
/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
/* */
/* 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_interface.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);
ClassDB::bind_method(D_METHOD("is_primary"), &XRInterface::is_primary);
ClassDB::bind_method(D_METHOD("set_primary", "primary"), &XRInterface::set_primary);
ClassDB::bind_method(D_METHOD("is_initialized"), &XRInterface::is_initialized);
ClassDB::bind_method(D_METHOD("initialize"), &XRInterface::initialize);
ClassDB::bind_method(D_METHOD("uninitialize"), &XRInterface::uninitialize);
ClassDB::bind_method(D_METHOD("get_system_info"), &XRInterface::get_system_info);
ClassDB::bind_method(D_METHOD("get_tracking_status"), &XRInterface::get_tracking_status);
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");
// 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");
// 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);
ClassDB::bind_method(D_METHOD("is_passthrough_supported"), &XRInterface::is_passthrough_supported);
ClassDB::bind_method(D_METHOD("is_passthrough_enabled"), &XRInterface::is_passthrough_enabled);
ClassDB::bind_method(D_METHOD("start_passthrough"), &XRInterface::start_passthrough);
ClassDB::bind_method(D_METHOD("stop_passthrough"), &XRInterface::stop_passthrough);
ClassDB::bind_method(D_METHOD("get_transform_for_view", "view", "cam_transform"), &XRInterface::get_transform_for_view);
ClassDB::bind_method(D_METHOD("get_projection_for_view", "view", "aspect", "near", "far"), &XRInterface::get_projection_for_view);
/** environment blend mode. */
ClassDB::bind_method(D_METHOD("get_supported_environment_blend_modes"), &XRInterface::get_supported_environment_blend_modes);
ClassDB::bind_method(D_METHOD("set_environment_blend_mode", "mode"), &XRInterface::set_environment_blend_mode);
ClassDB::bind_method(D_METHOD("get_environment_blend_mode"), &XRInterface::get_environment_blend_mode);
ADD_PROPERTY(PropertyInfo(Variant::INT, "environment_blend_mode"), "set_environment_blend_mode", "get_environment_blend_mode");
ADD_GROUP("AR", "ar_");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "ar_is_anchor_detection_enabled"), "set_anchor_detection_is_enabled", "get_anchor_detection_is_enabled");
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(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);
BIND_ENUM_CONSTANT(XR_PLAY_AREA_CUSTOM);
BIND_ENUM_CONSTANT(XR_ENV_BLEND_MODE_OPAQUE);
BIND_ENUM_CONSTANT(XR_ENV_BLEND_MODE_ADDITIVE);
BIND_ENUM_CONSTANT(XR_ENV_BLEND_MODE_ALPHA_BLEND);
BIND_ENUM_CONSTANT(XR_VRS_TEXTURE_FORMAT_UNIFIED);
BIND_ENUM_CONSTANT(XR_VRS_TEXTURE_FORMAT_FRAGMENT_SHADING_RATE);
BIND_ENUM_CONSTANT(XR_VRS_TEXTURE_FORMAT_FRAGMENT_DENSITY_MAP);
}
bool XRInterface::is_primary() {
XRServer *xr_server = XRServer::get_singleton();
ERR_FAIL_NULL_V(xr_server, false);
return xr_server->get_primary_interface() == this;
}
void XRInterface::set_primary(bool p_primary) {
XRServer *xr_server = XRServer::get_singleton();
ERR_FAIL_NULL(xr_server);
if (p_primary) {
ERR_FAIL_COND(!is_initialized());
xr_server->set_primary_interface(this);
} else if (xr_server->get_primary_interface() == this) {
xr_server->set_primary_interface(nullptr);
}
}
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;
}
void XRInterface::set_anchor_detection_is_enabled(bool p_enable) {
}
int XRInterface::get_camera_feed_id() {
return 0;
}
RID XRInterface::get_vrs_texture() {
return RID();
}
/** these are optional, so we want dummies **/
RID XRInterface::get_color_texture() {
return RID();
}
RID XRInterface::get_depth_texture() {
return RID();
}
RID XRInterface::get_velocity_texture() {
return RID();
}
RID XRInterface::get_velocity_depth_texture() {
return RID();
}
Size2i XRInterface::get_velocity_target_size() {
return Size2i();
}
Rect2i XRInterface::get_render_region() {
return Rect2i();
}
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::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) {
}
Array XRInterface::get_supported_environment_blend_modes() {
Array default_blend_modes = { XR_ENV_BLEND_MODE_OPAQUE };
return default_blend_modes;
}

178
servers/xr/xr_interface.h Normal file
View File

@@ -0,0 +1,178 @@
/**************************************************************************/
/* xr_interface.h */
/**************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
/* https://godotengine.org */
/**************************************************************************/
/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
/* */
/* 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. */
/**************************************************************************/
#pragma once
#include "core/math/projection.h"
#include "core/os/thread_safe.h"
#include "servers/xr_server.h"
#include "xr_vrs.h"
// forward declaration
struct BlitToScreen;
/**
The XR interface is a template class on top of which we build interface to different AR, VR and tracking SDKs.
The idea is that we subclass this class, implement the logic, and then instantiate a singleton of each interface
when Godot starts. These instances do not initialize themselves but register themselves with the AR/VR server.
If the user wants to enable AR/VR, they can choose the interface they want to use and initialize it.
Note that we may make this into a fully instantiable class for GDExtension support.
*/
class XRInterface : public RefCounted {
GDCLASS(XRInterface, RefCounted);
public:
enum Capabilities { /* purely metadata, provides some info about what this interface supports */
XR_NONE = 0, /* no capabilities */
XR_MONO = 1, /* can be used with mono output */
XR_STEREO = 2, /* can be used with stereo output */
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 */
XR_NORMAL_TRACKING,
XR_EXCESSIVE_MOTION,
XR_INSUFFICIENT_FEATURES,
XR_UNKNOWN_TRACKING,
XR_NOT_TRACKING
};
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 */
XR_PLAY_AREA_CUSTOM = 0x7FFFFFFF, /* Used to denote that a custom, possibly non-standard, play area is being used */
};
enum EnvironmentBlendMode {
XR_ENV_BLEND_MODE_OPAQUE, /* You cannot see the real world, VR like */
XR_ENV_BLEND_MODE_ADDITIVE, /* You can see the real world, AR like */
XR_ENV_BLEND_MODE_ALPHA_BLEND, /* Real world is passed through where alpha channel is 0.0 and gradually blends to opaque for value 1.0. */
};
enum VRSTextureFormat {
XR_VRS_TEXTURE_FORMAT_UNIFIED,
XR_VRS_TEXTURE_FORMAT_FRAGMENT_SHADING_RATE,
XR_VRS_TEXTURE_FORMAT_FRAGMENT_DENSITY_MAP,
};
protected:
_THREAD_SAFE_CLASS_
static void _bind_methods();
public:
/** general interface information **/
virtual StringName get_name() const = 0;
virtual uint32_t get_capabilities() const = 0;
bool is_primary();
void set_primary(bool p_is_primary);
virtual bool is_initialized() const = 0; /* returns true if we've initialized this interface */
virtual bool initialize() = 0; /* initialize this interface, if this has an HMD it becomes the primary interface */
virtual void uninitialize() = 0; /* deinitialize this interface */
virtual Dictionary get_system_info() = 0; /* return a dictionary with info about our system */
/** 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 **/
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;
virtual void set_anchor_detection_is_enabled(bool p_enable);
virtual int get_camera_feed_id();
/** rendering and internal **/
// These methods are called from the main thread.
virtual Transform3D get_camera_transform() = 0; /* returns the position of our camera, only used for updating reference frame. For monoscopic this is equal to the views transform, for stereoscopic this should be an average */
virtual void process() = 0;
// These methods can be called from both main and render thread.
virtual Size2 get_render_target_size() = 0; /* returns the recommended render target size per eye for this device */
virtual uint32_t get_view_count() = 0; /* returns the view count we need (1 is monoscopic, 2 is stereoscopic but can be more) */
// These methods are called from the rendering thread.
virtual Transform3D get_transform_for_view(uint32_t p_view, const Transform3D &p_cam_transform) = 0; /* get each views transform */
virtual Projection get_projection_for_view(uint32_t p_view, double p_aspect, double p_z_near, double p_z_far) = 0; /* get each view projection matrix */
virtual RID get_color_texture(); /* obtain color output texture (if applicable) */
virtual RID get_depth_texture(); /* obtain depth output texture (if applicable, used for reprojection) */
virtual RID get_velocity_texture(); /* obtain velocity output texture (if applicable, used for spacewarp) */
virtual RID get_velocity_depth_texture();
virtual Size2i get_velocity_target_size();
virtual Rect2i get_render_region();
virtual void pre_render() {}
virtual bool pre_draw_viewport(RID p_render_target) { return true; } /* inform XR interface we are about to start our viewport draw process */
virtual Vector<BlitToScreen> post_draw_viewport(RID p_render_target, const Rect2 &p_screen_rect) = 0; /* inform XR interface we finished our viewport draw process */
virtual void end_frame() {}
/** passthrough **/
virtual bool is_passthrough_supported() { return false; }
virtual bool is_passthrough_enabled() { return false; }
virtual bool start_passthrough() { return false; }
virtual void stop_passthrough() {}
/** environment blend mode **/
virtual Array get_supported_environment_blend_modes();
virtual XRInterface::EnvironmentBlendMode get_environment_blend_mode() const { return XR_ENV_BLEND_MODE_OPAQUE; }
virtual bool set_environment_blend_mode(EnvironmentBlendMode mode) { return false; }
/** VRS **/
virtual RID get_vrs_texture(); /* obtain VRS texture */
virtual VRSTextureFormat get_vrs_texture_format() { return XR_VRS_TEXTURE_FORMAT_UNIFIED; }
XRInterface();
~XRInterface();
};
VARIANT_ENUM_CAST(XRInterface::Capabilities);
VARIANT_ENUM_CAST(XRInterface::TrackingStatus);
VARIANT_ENUM_CAST(XRInterface::PlayAreaMode);
VARIANT_ENUM_CAST(XRInterface::EnvironmentBlendMode);
VARIANT_ENUM_CAST(XRInterface::VRSTextureFormat);

View File

@@ -0,0 +1,339 @@
/**************************************************************************/
/* xr_interface_extension.cpp */
/**************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
/* https://godotengine.org */
/**************************************************************************/
/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
/* */
/* 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_interface_extension.h"
#include "servers/rendering/renderer_rd/storage_rd/texture_storage.h"
void XRInterfaceExtension::_bind_methods() {
GDVIRTUAL_BIND(_get_name);
GDVIRTUAL_BIND(_get_capabilities);
GDVIRTUAL_BIND(_is_initialized);
GDVIRTUAL_BIND(_initialize);
GDVIRTUAL_BIND(_uninitialize);
GDVIRTUAL_BIND(_get_system_info);
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);
GDVIRTUAL_BIND(_get_transform_for_view, "view", "cam_transform");
GDVIRTUAL_BIND(_get_projection_for_view, "view", "aspect", "z_near", "z_far");
GDVIRTUAL_BIND(_get_vrs_texture);
GDVIRTUAL_BIND(_get_vrs_texture_format);
GDVIRTUAL_BIND(_process);
GDVIRTUAL_BIND(_pre_render);
GDVIRTUAL_BIND(_pre_draw_viewport, "render_target");
GDVIRTUAL_BIND(_post_draw_viewport, "render_target", "screen_rect");
GDVIRTUAL_BIND(_end_frame);
/** 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....
GDVIRTUAL_BIND(_get_anchor_detection_is_enabled);
GDVIRTUAL_BIND(_set_anchor_detection_is_enabled, "enabled");
GDVIRTUAL_BIND(_get_camera_feed_id);
// override output methods
GDVIRTUAL_BIND(_get_color_texture);
GDVIRTUAL_BIND(_get_depth_texture);
GDVIRTUAL_BIND(_get_velocity_texture);
ClassDB::bind_method(D_METHOD("get_color_texture"), &XRInterfaceExtension::get_color_texture);
ClassDB::bind_method(D_METHOD("get_depth_texture"), &XRInterfaceExtension::get_depth_texture);
ClassDB::bind_method(D_METHOD("get_velocity_texture"), &XRInterfaceExtension::get_velocity_texture);
// helper methods
ClassDB::bind_method(D_METHOD("add_blit", "render_target", "src_rect", "dst_rect", "use_layer", "layer", "apply_lens_distortion", "eye_center", "k1", "k2", "upscale", "aspect_ratio"), &XRInterfaceExtension::add_blit);
ClassDB::bind_method(D_METHOD("get_render_target_texture", "render_target"), &XRInterfaceExtension::get_render_target_texture);
// ClassDB::bind_method(D_METHOD("get_render_target_depth", "render_target"), &XRInterfaceExtension::get_render_target_depth);
}
StringName XRInterfaceExtension::get_name() const {
StringName name;
if (GDVIRTUAL_CALL(_get_name, name)) {
return name;
}
return "Unknown";
}
uint32_t XRInterfaceExtension::get_capabilities() const {
uint32_t capabilities = 0;
GDVIRTUAL_CALL(_get_capabilities, capabilities);
return capabilities;
}
bool XRInterfaceExtension::is_initialized() const {
bool initialized = false;
GDVIRTUAL_CALL(_is_initialized, initialized);
return initialized;
}
bool XRInterfaceExtension::initialize() {
bool initialized = false;
GDVIRTUAL_CALL(_initialize, initialized);
return initialized;
}
void XRInterfaceExtension::uninitialize() {
GDVIRTUAL_CALL(_uninitialize);
}
Dictionary XRInterfaceExtension::get_system_info() {
Dictionary dict;
GDVIRTUAL_CALL(_get_system_info, dict);
return dict;
}
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 {
XRInterface::TrackingStatus status = XR_UNKNOWN_TRACKING;
GDVIRTUAL_CALL(_get_tracking_status, status);
return status;
}
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 = false;
GDVIRTUAL_CALL(_supports_play_area_mode, p_mode, is_supported);
return is_supported;
}
XRInterface::PlayAreaMode XRInterfaceExtension::get_play_area_mode() const {
XRInterface::PlayAreaMode mode = XR_PLAY_AREA_UNKNOWN;
GDVIRTUAL_CALL(_get_play_area_mode, mode);
return mode;
}
bool XRInterfaceExtension::set_play_area_mode(XRInterface::PlayAreaMode p_mode) {
bool success = false;
GDVIRTUAL_CALL(_set_play_area_mode, p_mode, success);
return success;
}
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 = false;
GDVIRTUAL_CALL(_get_anchor_detection_is_enabled, enabled);
return enabled;
}
void XRInterfaceExtension::set_anchor_detection_is_enabled(bool p_enable) {
// don't do anything here, this needs to be implemented on AR interface to enable/disable things like plane detection etc.
GDVIRTUAL_CALL(_set_anchor_detection_is_enabled, p_enable);
}
int XRInterfaceExtension::get_camera_feed_id() {
int feed_id = 0;
GDVIRTUAL_CALL(_get_camera_feed_id, feed_id);
return feed_id;
}
Size2 XRInterfaceExtension::get_render_target_size() {
Size2 size;
GDVIRTUAL_CALL(_get_render_target_size, size);
return size;
}
uint32_t XRInterfaceExtension::get_view_count() {
uint32_t view_count = 1;
GDVIRTUAL_CALL(_get_view_count, view_count);
return view_count;
}
Transform3D XRInterfaceExtension::get_camera_transform() {
Transform3D transform;
GDVIRTUAL_CALL(_get_camera_transform, transform);
return transform;
}
Transform3D XRInterfaceExtension::get_transform_for_view(uint32_t p_view, const Transform3D &p_cam_transform) {
Transform3D transform;
GDVIRTUAL_CALL(_get_transform_for_view, p_view, p_cam_transform, transform);
return transform;
}
Projection XRInterfaceExtension::get_projection_for_view(uint32_t p_view, double p_aspect, double p_z_near, double p_z_far) {
Projection cm;
PackedFloat64Array arr;
if (GDVIRTUAL_CALL(_get_projection_for_view, p_view, p_aspect, p_z_near, p_z_far, arr)) {
ERR_FAIL_COND_V_MSG(arr.size() != 16, Projection(), "Projection matrix must contain 16 floats");
real_t *m = (real_t *)cm.columns;
for (int i = 0; i < 16; i++) {
m[i] = arr[i];
}
return cm;
}
return Projection();
}
RID XRInterfaceExtension::get_vrs_texture() {
RID vrs_texture;
if (GDVIRTUAL_CALL(_get_vrs_texture, vrs_texture)) {
return vrs_texture;
} else {
return XRInterface::get_vrs_texture();
}
}
XRInterface::VRSTextureFormat XRInterfaceExtension::get_vrs_texture_format() {
VRSTextureFormat vrs_texture_format = XR_VRS_TEXTURE_FORMAT_UNIFIED;
if (GDVIRTUAL_CALL(_get_vrs_texture_format, vrs_texture_format)) {
return vrs_texture_format;
}
return vrs_texture_format;
}
RID XRInterfaceExtension::get_color_texture() {
RID texture;
GDVIRTUAL_CALL(_get_color_texture, texture);
return texture;
}
RID XRInterfaceExtension::get_depth_texture() {
RID texture;
GDVIRTUAL_CALL(_get_depth_texture, texture);
return texture;
}
RID XRInterfaceExtension::get_velocity_texture() {
RID texture;
GDVIRTUAL_CALL(_get_velocity_texture, texture);
return texture;
}
void XRInterfaceExtension::add_blit(RID p_render_target, Rect2 p_src_rect, Rect2i p_dst_rect, bool p_use_layer, uint32_t p_layer, bool p_apply_lens_distortion, Vector2 p_eye_center, double p_k1, double p_k2, double p_upscale, double p_aspect_ratio) {
BlitToScreen blit;
ERR_FAIL_COND_MSG(!can_add_blits, "add_blit can only be called from an XR plugin from within _post_draw_viewport!");
blit.render_target = p_render_target;
blit.src_rect = p_src_rect;
blit.dst_rect = p_dst_rect;
blit.multi_view.use_layer = p_use_layer;
blit.multi_view.layer = p_layer;
blit.lens_distortion.apply = p_apply_lens_distortion;
blit.lens_distortion.eye_center = p_eye_center;
blit.lens_distortion.k1 = p_k1;
blit.lens_distortion.k2 = p_k2;
blit.lens_distortion.upscale = p_upscale;
blit.lens_distortion.aspect_ratio = p_aspect_ratio;
blits.push_back(blit);
}
void XRInterfaceExtension::process() {
GDVIRTUAL_CALL(_process);
}
void XRInterfaceExtension::pre_render() {
GDVIRTUAL_CALL(_pre_render);
}
bool XRInterfaceExtension::pre_draw_viewport(RID p_render_target) {
bool do_render = true;
GDVIRTUAL_CALL(_pre_draw_viewport, p_render_target, do_render);
return do_render; // If not implemented we're returning true.
}
Vector<BlitToScreen> XRInterfaceExtension::post_draw_viewport(RID p_render_target, const Rect2 &p_screen_rect) {
// This is just so our XR plugin can add blits...
blits.clear();
can_add_blits = true;
if (GDVIRTUAL_CALL(_post_draw_viewport, p_render_target, p_screen_rect)) {
return blits;
}
can_add_blits = false;
return blits;
}
void XRInterfaceExtension::end_frame() {
GDVIRTUAL_CALL(_end_frame);
}
RID XRInterfaceExtension::get_render_target_texture(RID p_render_target) {
// In due time this will need to be enhance to return the correct INTERNAL RID for the chosen rendering engine.
// So once a GLES driver is implemented we'll return that and the implemented plugin needs to handle this correctly too.
RendererRD::TextureStorage *texture_storage = RendererRD::TextureStorage::get_singleton();
ERR_FAIL_NULL_V_MSG(texture_storage, RID(), "Texture storage not setup");
return texture_storage->render_target_get_rd_texture(p_render_target);
}
/*
RID XRInterfaceExtension::get_render_target_depth(RID p_render_target) {
// TODO implement this, the problem is that our depth texture isn't part of our render target as it is used for 3D rendering only
// but we don't have access to our render buffers from here....
}
*/

View File

@@ -0,0 +1,139 @@
/**************************************************************************/
/* xr_interface_extension.h */
/**************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
/* https://godotengine.org */
/**************************************************************************/
/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
/* */
/* 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. */
/**************************************************************************/
#pragma once
#include "servers/xr/xr_interface.h"
class XRInterfaceExtension : public XRInterface {
GDCLASS(XRInterfaceExtension, XRInterface);
public:
private:
bool can_add_blits = false;
Vector<BlitToScreen> blits;
protected:
_THREAD_SAFE_CLASS_
static void _bind_methods();
public:
/** general interface information **/
virtual StringName get_name() const override;
virtual uint32_t get_capabilities() const override;
GDVIRTUAL0RC(StringName, _get_name);
GDVIRTUAL0RC(uint32_t, _get_capabilities);
virtual bool is_initialized() const override;
virtual bool initialize() override;
virtual void uninitialize() override;
virtual Dictionary get_system_info() override;
GDVIRTUAL0RC(bool, _is_initialized);
GDVIRTUAL0R(bool, _initialize);
GDVIRTUAL0(_uninitialize);
GDVIRTUAL0RC(Dictionary, _get_system_info);
/** 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(XRInterface::TrackingStatus, _get_tracking_status);
GDVIRTUAL6(_trigger_haptic_pulse, const String &, const StringName &, double, double, double, double);
/** specific to VR **/
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(XRInterface::PlayAreaMode, _get_play_area_mode);
GDVIRTUAL1RC(bool, _set_play_area_mode, XRInterface::PlayAreaMode);
GDVIRTUAL0RC(PackedVector3Array, _get_play_area);
/** specific to AR **/
virtual bool get_anchor_detection_is_enabled() const override;
virtual void set_anchor_detection_is_enabled(bool p_enable) override;
virtual int get_camera_feed_id() override;
GDVIRTUAL0RC(bool, _get_anchor_detection_is_enabled);
GDVIRTUAL1(_set_anchor_detection_is_enabled, bool);
GDVIRTUAL0RC(int, _get_camera_feed_id);
/** rendering and internal **/
virtual Size2 get_render_target_size() override;
virtual uint32_t get_view_count() override;
virtual Transform3D get_camera_transform() override;
virtual Transform3D get_transform_for_view(uint32_t p_view, const Transform3D &p_cam_transform) override;
virtual Projection get_projection_for_view(uint32_t p_view, double p_aspect, double p_z_near, double p_z_far) override;
virtual RID get_vrs_texture() override;
virtual VRSTextureFormat get_vrs_texture_format() override;
virtual RID get_color_texture() override;
virtual RID get_depth_texture() override;
virtual RID get_velocity_texture() override;
GDVIRTUAL0R(Size2, _get_render_target_size);
GDVIRTUAL0R(uint32_t, _get_view_count);
GDVIRTUAL0R(Transform3D, _get_camera_transform);
GDVIRTUAL2R(Transform3D, _get_transform_for_view, uint32_t, const Transform3D &);
GDVIRTUAL4R(PackedFloat64Array, _get_projection_for_view, uint32_t, double, double, double);
GDVIRTUAL0R(RID, _get_vrs_texture);
GDVIRTUAL0R(VRSTextureFormat, _get_vrs_texture_format);
GDVIRTUAL0R(RID, _get_color_texture);
GDVIRTUAL0R(RID, _get_depth_texture);
GDVIRTUAL0R(RID, _get_velocity_texture);
void add_blit(RID p_render_target, Rect2 p_src_rect, Rect2i p_dst_rect, bool p_use_layer = false, uint32_t p_layer = 0, bool p_apply_lens_distortion = false, Vector2 p_eye_center = Vector2(), double p_k1 = 0.0, double p_k2 = 0.0, double p_upscale = 1.0, double p_aspect_ratio = 1.0);
virtual void process() override;
virtual void pre_render() override;
virtual bool pre_draw_viewport(RID p_render_target) override;
virtual Vector<BlitToScreen> post_draw_viewport(RID p_render_target, const Rect2 &p_screen_rect) override;
virtual void end_frame() override;
GDVIRTUAL0(_process);
GDVIRTUAL0(_pre_render);
GDVIRTUAL1R(bool, _pre_draw_viewport, RID);
GDVIRTUAL2(_post_draw_viewport, RID, const Rect2 &);
GDVIRTUAL0(_end_frame);
/* access to some internals we need */
RID get_render_target_texture(RID p_render_target);
// RID get_render_target_depth(RID p_render_target);
};

126
servers/xr/xr_pose.cpp Normal file
View File

@@ -0,0 +1,126 @@
/**************************************************************************/
/* xr_pose.cpp */
/**************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
/* https://godotengine.org */
/**************************************************************************/
/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
/* */
/* 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() {
BIND_ENUM_CONSTANT(XR_TRACKING_CONFIDENCE_NONE);
BIND_ENUM_CONSTANT(XR_TRACKING_CONFIDENCE_LOW);
BIND_ENUM_CONSTANT(XR_TRACKING_CONFIDENCE_HIGH);
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::BOOL, "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");
ClassDB::bind_method(D_METHOD("set_tracking_confidence", "tracking_confidence"), &XRPose::set_tracking_confidence);
ClassDB::bind_method(D_METHOD("get_tracking_confidence"), &XRPose::get_tracking_confidence);
ADD_PROPERTY(PropertyInfo(Variant::INT, "tracking_confidence"), "set_tracking_confidence", "get_tracking_confidence");
}
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;
}
void XRPose::set_tracking_confidence(const XRPose::TrackingConfidence p_tracking_confidence) {
tracking_confidence = p_tracking_confidence;
}
XRPose::TrackingConfidence XRPose::get_tracking_confidence() const {
return tracking_confidence;
}

78
servers/xr/xr_pose.h Normal file
View File

@@ -0,0 +1,78 @@
/**************************************************************************/
/* xr_pose.h */
/**************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
/* https://godotengine.org */
/**************************************************************************/
/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
/* */
/* 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. */
/**************************************************************************/
#pragma once
#include "core/object/ref_counted.h"
class XRPose : public RefCounted {
GDCLASS(XRPose, RefCounted);
public:
// TrackingConfidence gives an indication of how reliable our transform data is.
enum TrackingConfidence {
XR_TRACKING_CONFIDENCE_NONE, // No tracking information is available for this pose.
XR_TRACKING_CONFIDENCE_LOW, // Tracking information may be inaccurate or estimated.
XR_TRACKING_CONFIDENCE_HIGH // Tracking information is deemed accurate and up to date.
};
private:
bool has_tracking_data = false;
StringName name;
Transform3D transform;
Vector3 linear_velocity;
Vector3 angular_velocity;
TrackingConfidence tracking_confidence = XR_TRACKING_CONFIDENCE_NONE;
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;
void set_tracking_confidence(const TrackingConfidence p_tracking_confidence);
TrackingConfidence get_tracking_confidence() const;
};
VARIANT_ENUM_CAST(XRPose::TrackingConfidence);

View File

@@ -0,0 +1,191 @@
/**************************************************************************/
/* xr_positional_tracker.cpp */
/**************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
/* https://godotengine.org */
/**************************************************************************/
/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
/* */
/* 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_positional_tracker.h"
#include "xr_controller_tracker.h"
void XRPositionalTracker::_bind_methods() {
BIND_ENUM_CONSTANT(TRACKER_HAND_UNKNOWN);
BIND_ENUM_CONSTANT(TRACKER_HAND_LEFT);
BIND_ENUM_CONSTANT(TRACKER_HAND_RIGHT);
BIND_ENUM_CONSTANT(TRACKER_HAND_MAX);
ClassDB::bind_method(D_METHOD("get_tracker_profile"), &XRPositionalTracker::get_tracker_profile);
ClassDB::bind_method(D_METHOD("set_tracker_profile", "profile"), &XRPositionalTracker::set_tracker_profile);
ADD_PROPERTY(PropertyInfo(Variant::STRING, "profile"), "set_tracker_profile", "get_tracker_profile");
ClassDB::bind_method(D_METHOD("get_tracker_hand"), &XRPositionalTracker::get_tracker_hand);
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", "tracking_confidence"), &XRPositionalTracker::set_pose);
ADD_SIGNAL(MethodInfo("pose_changed", PropertyInfo(Variant::OBJECT, "pose", PROPERTY_HINT_RESOURCE_TYPE, "XRPose")));
ADD_SIGNAL(MethodInfo("pose_lost_tracking", 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_float_changed", PropertyInfo(Variant::STRING, "name"), PropertyInfo(Variant::FLOAT, "value")));
ADD_SIGNAL(MethodInfo("input_vector2_changed", PropertyInfo(Variant::STRING, "name"), PropertyInfo(Variant::VECTOR2, "vector")));
ADD_SIGNAL(MethodInfo("profile_changed", PropertyInfo(Variant::STRING, "role")));
}
void XRPositionalTracker::set_tracker_profile(const String &p_profile) {
if (profile != p_profile) {
profile = p_profile;
emit_signal("profile_changed", profile);
}
}
String XRPositionalTracker::get_tracker_profile() const {
return profile;
}
XRPositionalTracker::TrackerHand XRPositionalTracker::get_tracker_hand() const {
return tracker_hand;
}
void XRPositionalTracker::set_tracker_hand(const XRPositionalTracker::TrackerHand p_hand) {
ERR_FAIL_INDEX(p_hand, TRACKER_HAND_MAX);
tracker_hand = p_hand;
}
bool XRPositionalTracker::has_pose(const StringName &p_action_name) const {
return poses.has(p_action_name);
}
Ref<XRPose> XRPositionalTracker::get_pose(const StringName &p_action_name) const {
Ref<XRPose> pose;
if (poses.has(p_action_name)) {
pose = poses[p_action_name];
}
return pose;
}
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.
Ref<XRPose> pose = poses[p_action_name];
pose->set_has_tracking_data(false);
emit_signal(SNAME("pose_lost_tracking"), pose);
}
}
void XRPositionalTracker::set_pose(const StringName &p_action_name, const Transform3D &p_transform, const Vector3 &p_linear_velocity, const Vector3 &p_angular_velocity, const XRPose::TrackingConfidence p_tracking_confidence) {
Ref<XRPose> new_pose;
if (poses.has(p_action_name)) {
new_pose = poses[p_action_name];
} else {
new_pose.instantiate();
poses[p_action_name] = new_pose;
}
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);
new_pose->set_tracking_confidence(p_tracking_confidence);
emit_signal(SNAME("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 {
// Complain if this method is called on a XRPositionalTracker instance.
if (!dynamic_cast<const XRControllerTracker *>(this)) {
WARN_DEPRECATED_MSG(R"*(The "get_input()" method is deprecated, use "XRControllerTracker" instead.)*");
}
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) {
// Complain if this method is called on a XRPositionalTracker instance.
if (!dynamic_cast<XRControllerTracker *>(this)) {
WARN_DEPRECATED_MSG(R"*(The "set_input()" method is deprecated, use "XRControllerTracker" instead.)*");
}
// XR inputs
bool changed;
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(SNAME("button_pressed"), p_action_name);
} else {
emit_signal(SNAME("button_released"), p_action_name);
}
// TODO discuss whether we also want to create and emit an InputEventXRButton event
} break;
case Variant::FLOAT: {
emit_signal(SNAME("input_float_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(SNAME("input_vector2_changed"), p_action_name, p_value);
// TODO discuss whether we also want to create and emit an InputEventXRAxis event
} break;
default: {
// ???
} break;
}
}
}

View File

@@ -0,0 +1,81 @@
/**************************************************************************/
/* xr_positional_tracker.h */
/**************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
/* https://godotengine.org */
/**************************************************************************/
/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
/* */
/* 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. */
/**************************************************************************/
#pragma once
#include "core/os/thread_safe.h"
#include "servers/xr/xr_pose.h"
#include "servers/xr/xr_tracker.h"
#include "servers/xr_server.h"
/**
The positional tracker object as an object that represents the position and orientation of a tracked object like a controller or headset.
An AR/VR Interface will registered the trackers it manages with our AR/VR server and update its position and orientation.
This is where potentially additional AR/VR interfaces may be active as there are AR/VR SDKs that solely deal with positional tracking.
*/
class XRPositionalTracker : public XRTracker {
GDCLASS(XRPositionalTracker, XRTracker);
_THREAD_SAFE_CLASS_
public:
enum TrackerHand {
TRACKER_HAND_UNKNOWN, /* unknown or not applicable */
TRACKER_HAND_LEFT, /* controller is the left hand controller */
TRACKER_HAND_RIGHT, /* controller is the right hand controller */
TRACKER_HAND_MAX
};
protected:
String profile; // this is interface dependent, for OpenXR this will be the interaction profile bound for to the tracker
TrackerHand tracker_hand = TRACKER_HAND_UNKNOWN; // if known, the hand this tracker is held in
HashMap<StringName, Ref<XRPose>> poses;
HashMap<StringName, Variant> inputs;
static void _bind_methods();
public:
void set_tracker_profile(const String &p_profile);
String get_tracker_profile() const;
XRPositionalTracker::TrackerHand get_tracker_hand() const;
virtual 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, const XRPose::TrackingConfidence p_tracking_confidence = XRPose::XR_TRACKING_CONFIDENCE_HIGH);
Variant get_input(const StringName &p_action_name) const;
void set_input(const StringName &p_action_name, const Variant &p_value);
};
VARIANT_ENUM_CAST(XRPositionalTracker::TrackerHand);

70
servers/xr/xr_tracker.cpp Normal file
View File

@@ -0,0 +1,70 @@
/**************************************************************************/
/* xr_tracker.cpp */
/**************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
/* https://godotengine.org */
/**************************************************************************/
/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
/* */
/* 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_tracker.h"
void XRTracker::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_tracker_type"), &XRTracker::get_tracker_type);
ClassDB::bind_method(D_METHOD("set_tracker_type", "type"), &XRTracker::set_tracker_type);
ADD_PROPERTY(PropertyInfo(Variant::INT, "type"), "set_tracker_type", "get_tracker_type");
ClassDB::bind_method(D_METHOD("get_tracker_name"), &XRTracker::get_tracker_name);
ClassDB::bind_method(D_METHOD("set_tracker_name", "name"), &XRTracker::set_tracker_name);
ADD_PROPERTY(PropertyInfo(Variant::STRING, "name"), "set_tracker_name", "get_tracker_name");
ClassDB::bind_method(D_METHOD("get_tracker_desc"), &XRTracker::get_tracker_desc);
ClassDB::bind_method(D_METHOD("set_tracker_desc", "description"), &XRTracker::set_tracker_desc);
ADD_PROPERTY(PropertyInfo(Variant::STRING, "description"), "set_tracker_desc", "get_tracker_desc");
}
void XRTracker::set_tracker_type(XRServer::TrackerType p_type) {
type = p_type;
}
XRServer::TrackerType XRTracker::get_tracker_type() const {
return type;
}
void XRTracker::set_tracker_name(const StringName &p_name) {
// Note: this should not be changed after the tracker is registered with the XRServer!
name = p_name;
}
StringName XRTracker::get_tracker_name() const {
return name;
}
void XRTracker::set_tracker_desc(const String &p_desc) {
description = p_desc;
}
String XRTracker::get_tracker_desc() const {
return description;
}

58
servers/xr/xr_tracker.h Normal file
View File

@@ -0,0 +1,58 @@
/**************************************************************************/
/* xr_tracker.h */
/**************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
/* https://godotengine.org */
/**************************************************************************/
/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
/* */
/* 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. */
/**************************************************************************/
#pragma once
#include "core/os/thread_safe.h"
#include "servers/xr_server.h"
/**
The XR tracker object is a common base for all different types of XR trackers.
*/
class XRTracker : public RefCounted {
GDCLASS(XRTracker, RefCounted);
_THREAD_SAFE_CLASS_
protected:
XRServer::TrackerType type = XRServer::TRACKER_UNKNOWN; // type of tracker
StringName name = "Unknown"; // (unique) name of the tracker
String description; // description of the tracker
static void _bind_methods();
public:
virtual void set_tracker_type(XRServer::TrackerType p_type);
XRServer::TrackerType get_tracker_type() const;
void set_tracker_name(const StringName &p_name);
StringName get_tracker_name() const;
void set_tracker_desc(const String &p_desc);
String get_tracker_desc() const;
};

179
servers/xr/xr_vrs.cpp Normal file
View File

@@ -0,0 +1,179 @@
/**************************************************************************/
/* xr_vrs.cpp */
/**************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
/* https://godotengine.org */
/**************************************************************************/
/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
/* */
/* 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_vrs.h"
#include "servers/rendering/renderer_scene_render.h"
#include "servers/rendering_server.h"
void XRVRS::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_vrs_min_radius"), &XRVRS::get_vrs_min_radius);
ClassDB::bind_method(D_METHOD("set_vrs_min_radius", "radius"), &XRVRS::set_vrs_min_radius);
ClassDB::bind_method(D_METHOD("get_vrs_strength"), &XRVRS::get_vrs_strength);
ClassDB::bind_method(D_METHOD("set_vrs_strength", "strength"), &XRVRS::set_vrs_strength);
ClassDB::bind_method(D_METHOD("get_vrs_render_region"), &XRVRS::get_vrs_render_region);
ClassDB::bind_method(D_METHOD("set_vrs_render_region", "render_region"), &XRVRS::set_vrs_render_region);
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "vrs_min_radius", PROPERTY_HINT_RANGE, "1.0,100.0,1.0"), "set_vrs_min_radius", "get_vrs_min_radius");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "vrs_strength", PROPERTY_HINT_RANGE, "0.1,10.0,0.1"), "set_vrs_strength", "get_vrs_strength");
ADD_PROPERTY(PropertyInfo(Variant::RECT2I, "vrs_render_region"), "set_vrs_render_region", "get_vrs_render_region");
ClassDB::bind_method(D_METHOD("make_vrs_texture", "target_size", "eye_foci"), &XRVRS::make_vrs_texture);
}
XRVRS::~XRVRS() {
if (vrs_texture.is_valid()) {
ERR_FAIL_NULL(RS::get_singleton());
RS::get_singleton()->free(vrs_texture);
vrs_texture = RID();
}
}
float XRVRS::get_vrs_min_radius() const {
return vrs_min_radius;
}
void XRVRS::set_vrs_min_radius(float p_vrs_min_radius) {
if (p_vrs_min_radius < 1.0) {
WARN_PRINT_ONCE("VRS minimum radius can not be set below 1.0");
vrs_min_radius = 1.0;
} else if (p_vrs_min_radius > 100.0) {
WARN_PRINT_ONCE("VRS minimum radius can not be set above 100.0");
vrs_min_radius = 100.0;
} else {
vrs_min_radius = p_vrs_min_radius;
vrs_dirty = true;
}
}
float XRVRS::get_vrs_strength() const {
return vrs_strength;
}
void XRVRS::set_vrs_strength(float p_vrs_strength) {
if (p_vrs_strength < 0.1) {
WARN_PRINT_ONCE("VRS strength can not be set below 0.1");
vrs_strength = 0.1;
} else if (p_vrs_strength > 10.0) {
WARN_PRINT_ONCE("VRS strength can not be set above 10.0");
vrs_strength = 10.0;
} else {
vrs_strength = p_vrs_strength;
vrs_dirty = true;
}
}
Rect2i XRVRS::get_vrs_render_region() const {
return vrs_render_region;
}
void XRVRS::set_vrs_render_region(const Rect2i &p_vrs_render_region) {
vrs_render_region = p_vrs_render_region;
vrs_dirty = true;
}
RID XRVRS::make_vrs_texture(const Size2 &p_target_size, const PackedVector2Array &p_eye_foci) {
ERR_FAIL_COND_V(p_eye_foci.is_empty(), RID());
Size2i texel_size = RD::get_singleton()->vrs_get_texel_size();
// Should return sensible data or graphics API does not support VRS.
ERR_FAIL_COND_V(texel_size.x < 1 || texel_size.y < 1, RID());
Size2 vrs_size = Size2(0.5 + p_target_size.x / texel_size.x, 0.5 + p_target_size.y / texel_size.y).floor();
// Make sure we have at least one pixel.
vrs_size = vrs_size.maxf(1.0);
float max_radius = 0.5 * MIN(vrs_size.x, vrs_size.y); // Maximum radius that fits inside of our image
float min_radius = vrs_min_radius * max_radius / 100.0; // Minimum radius as a percentage of our size
real_t outer_radius = MAX(1.0, (max_radius - min_radius) / vrs_strength);
Size2 vrs_sizei = vrs_size;
// Our density map is now unified, with a value of (0.0, 0.0) meaning a 1x1 texel size and (1.0, 1.0) an max texel size.
// For our standard VRS extension on Vulkan this means a maximum of 8x8.
// For the density map extension this scales depending on the max texel size.
if (target_size != vrs_sizei || eye_foci != p_eye_foci || vrs_dirty) {
// Out with the old.
if (vrs_texture.is_valid()) {
RS::get_singleton()->free(vrs_texture);
vrs_texture = RID();
}
// In with the new.
Vector<Ref<Image>> images;
target_size = vrs_sizei;
eye_foci = p_eye_foci;
Size2 region_ratio = Size2(1.0, 1.0);
Point2i region_offset;
if (vrs_render_region != Rect2i()) {
region_ratio = (Size2)vrs_render_region.size / p_target_size;
region_offset = (Point2)vrs_render_region.position / p_target_size * vrs_sizei;
}
for (int i = 0; i < eye_foci.size() && i < RendererSceneRender::MAX_RENDER_VIEWS; i++) {
PackedByteArray data;
data.resize(vrs_sizei.x * vrs_sizei.y * 2);
uint8_t *data_ptr = data.ptrw();
Vector2i view_center;
view_center.x = int(vrs_size.x * (eye_foci[i].x + 1.0) * region_ratio.x * 0.5) + region_offset.x;
view_center.y = int(vrs_size.y * (-eye_foci[i].y + 1.0) * region_ratio.y * 0.5) + region_offset.y;
int d = 0;
for (int y = 0; y < vrs_sizei.y; y++) {
for (int x = 0; x < vrs_sizei.x; x++) {
// Generate a density map that represents the distance to the view focus point. While this leaves the opportunities
// offered by the density map being different in each direction currently unused, it was found to give better tile
// distribution on hardware that supports the feature natively. This area is open to improvements in the future.
Vector2 offset = Vector2(x - view_center.x, y - view_center.y) / region_ratio;
real_t density = MAX(offset.length() - min_radius, 0.0) / outer_radius;
data_ptr[d++] = CLAMP(255.0 * density, 0, 255);
data_ptr[d++] = CLAMP(255.0 * density, 0, 255);
}
}
images.push_back(Image::create_from_data(vrs_sizei.x, vrs_sizei.y, false, Image::FORMAT_RG8, data));
}
if (images.size() == 1) {
vrs_texture = RS::get_singleton()->texture_2d_create(images[0]);
} else {
vrs_texture = RS::get_singleton()->texture_2d_layered_create(images, RS::TEXTURE_LAYERED_2D_ARRAY);
}
vrs_dirty = false;
}
return vrs_texture;
}

67
servers/xr/xr_vrs.h Normal file
View File

@@ -0,0 +1,67 @@
/**************************************************************************/
/* xr_vrs.h */
/**************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
/* https://godotengine.org */
/**************************************************************************/
/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
/* */
/* 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. */
/**************************************************************************/
#pragma once
#include "core/object/class_db.h"
#include "core/object/object.h"
#include "core/templates/rid.h"
#include "core/variant/variant.h"
/* This is a helper class for generating stereoscopic VRS images */
class XRVRS : public Object {
GDCLASS(XRVRS, Object);
private:
float vrs_min_radius = 20.0;
float vrs_strength = 1.0;
Rect2i vrs_render_region;
bool vrs_dirty = true;
RID vrs_texture;
Size2i target_size;
PackedVector2Array eye_foci;
protected:
static void _bind_methods();
public:
~XRVRS();
float get_vrs_min_radius() const;
void set_vrs_min_radius(float p_vrs_min_radius);
float get_vrs_strength() const;
void set_vrs_strength(float p_vrs_strength);
Rect2i get_vrs_render_region() const;
void set_vrs_render_region(const Rect2i &p_vrs_render_region);
RID make_vrs_texture(const Size2 &p_target_size, const PackedVector2Array &p_eye_foci);
};