From 7b6b037f0d633502bae9e95f36e80d3abba64ccf Mon Sep 17 00:00:00 2001 From: "Marek S. Lukasiewicz" Date: Thu, 20 Feb 2025 09:54:39 +0100 Subject: [PATCH 1/4] Add gdcef submodule --- .gitmodules | 3 +++ modules/gdcef | 1 + 2 files changed, 4 insertions(+) create mode 160000 modules/gdcef diff --git a/.gitmodules b/.gitmodules index 3449673..2c9eb07 100644 --- a/.gitmodules +++ b/.gitmodules @@ -7,3 +7,6 @@ [submodule "modules/godot-xr-tools"] path = modules/godot-xr-tools url = https://github.com/GodotVR/godot-xr-tools.git +[submodule "modules/gdcef"] + path = modules/gdcef + url = https://github.com/Lecrapouille/gdcef.git diff --git a/modules/gdcef b/modules/gdcef new file mode 160000 index 0000000..76957e9 --- /dev/null +++ b/modules/gdcef @@ -0,0 +1 @@ +Subproject commit 76957e99ba87af9aecbde4dddc861e98f87ec43f From e21e7aadbc459e7cc72fa83e2b7c926c59bdb6fd Mon Sep 17 00:00:00 2001 From: "Marek S. Lukasiewicz" Date: Thu, 20 Feb 2025 09:59:28 +0100 Subject: [PATCH 2/4] Revert deleting update_addons.py Refs: 4ddccdaf --- update_addons.py | 11 +++++++++++ 1 file changed, 11 insertions(+) create mode 100644 update_addons.py diff --git a/update_addons.py b/update_addons.py new file mode 100644 index 0000000..151aea3 --- /dev/null +++ b/update_addons.py @@ -0,0 +1,11 @@ +from os import path +from shutil import copytree + +# add repository root path +root_path = path.abspath(path.dirname(__file__)) + +copytree( + path.join(root_path, 'modules', 'godot-xr-tools', 'addons'), + path.join(root_path, 'project', 'addons'), + dirs_exist_ok=True, +) From 6d93630e50335a46cda2838fe8c0336e16d6f7aa Mon Sep 17 00:00:00 2001 From: "Marek S. Lukasiewicz" Date: Thu, 20 Feb 2025 10:54:05 +0100 Subject: [PATCH 3/4] Setup gdcef addon --- .gitignore | 5 +++++ README.md | 1 + update_addons.py | 22 ++++++++++++++++++++-- 3 files changed, 26 insertions(+), 2 deletions(-) diff --git a/.gitignore b/.gitignore index 4d1dfd1..6530f70 100644 --- a/.gitignore +++ b/.gitignore @@ -14,6 +14,11 @@ compile_commands.json # Ignore addons files (copied from submodules), except uid created on import /project/addons/godot-xr-tools/** !/project/addons/godot-xr-tools/**/*.uid +/project/addons/gdcef/** +!/project/addons/gdcef/**/*.uid + +# Chrome Embedded Framework binaries +/project/cef_artifacts # Created by https://www.toptal.com/developers/gitignore/api/c++,godot,scons,python # Edit at https://www.toptal.com/developers/gitignore?templates=c++,godot,scons,python diff --git a/README.md b/README.md index c9831c4..1b4c3ad 100644 --- a/README.md +++ b/README.md @@ -32,6 +32,7 @@ godot --dump-extension-api # after updating Godot python update_mavlink.py # after updating MAVLink dialect python update_addons.py # after changing any addon submodules scons compile_commands # after modifying SConstruct +cd project/addons/gdcef; python build.py ``` ### Windows setup diff --git a/update_addons.py b/update_addons.py index 151aea3..c7d17aa 100644 --- a/update_addons.py +++ b/update_addons.py @@ -1,11 +1,29 @@ from os import path from shutil import copytree -# add repository root path +# Add repository root path root_path = path.abspath(path.dirname(__file__)) +# Copy the addon folder from each module copytree( - path.join(root_path, 'modules', 'godot-xr-tools', 'addons'), + path.join(root_path, 'modules', 'gdcef', 'addons'), path.join(root_path, 'project', 'addons'), dirs_exist_ok=True, ) + +# Configure gdcef version for precompiled binaries +gdcef_build = path.join(root_path, 'project', 'addons', 'gdcef', 'build.py') +gdcef_lines = [] + +with open(gdcef_build, 'r', encoding='utf-8') as file: + gdcef_lines = file.readlines() + +for i, line in enumerate(gdcef_lines): + if not line.startswith('GITHUB_GDCEF_RELEASE'): + continue + gdcef_lines[i] = 'GITHUB_GDCEF_RELEASE = "0.16.1"\n' + break + +with open(gdcef_build, 'w', encoding='utf-8') as file: + file.writelines(gdcef_lines) + From 55004f3e60e79f48a3ee5de1f834aa427c741cde Mon Sep 17 00:00:00 2001 From: "Marek S. Lukasiewicz" Date: Thu, 20 Feb 2025 17:18:02 +0100 Subject: [PATCH 4/4] Working with Varjo and Vive Tracker --- project/aircraft/aircraft.gd | 14 +++++++++++--- project/aircraft/aircraft.tscn | 32 +++++++++++++++++++++++++++----- project/main.tscn | 2 +- project/project.godot | 2 +- project/start_vr.gd | 4 ++++ 5 files changed, 44 insertions(+), 10 deletions(-) diff --git a/project/aircraft/aircraft.gd b/project/aircraft/aircraft.gd index 3ab651d..86702a4 100644 --- a/project/aircraft/aircraft.gd +++ b/project/aircraft/aircraft.gd @@ -12,6 +12,9 @@ var _rotor_azimuth: float = 0 @onready var connector: MarshConnector = $MarshConnector @onready var skeleton: Skeleton3D = $"Mi-2/Armature/Skeleton3D" @onready var attitude_root: Node3D = $AttitudeRoot +@onready var tracker_mount: Node3D = $AttitudeRoot/PilotEyes/PilotFloor/TrackerMountChair +@onready var xr_origin: XROrigin3D = $AttitudeRoot/PilotEyes/PilotFloor/XROrigin3D +@onready var tracker: XRController3D = $AttitudeRoot/PilotEyes/PilotFloor/XROrigin3D/ViveTracker @onready var bone_cg: int = skeleton.find_bone("BodyCG") @onready var bone_cyclic: int = skeleton.find_bone("Cyclic") @@ -20,7 +23,7 @@ var _rotor_azimuth: float = 0 func _process(delta: float) -> void: var target := connector.get_aircraft() position = target.origin - + # Add the rotation to the correct bone for rotation around CG var rest := skeleton.get_bone_rest(bone_cg).basis.get_rotation_quaternion() var attitude := target.basis.get_rotation_quaternion() @@ -28,14 +31,14 @@ func _process(delta: float) -> void: # Rotate other children (not using BoneAttachment3D due to jitter) attitude_root.rotation = target.basis.get_euler() - + # Rotate the cyclic stick bone var cyclic := connector.get_cyclic() var cyc_rest := skeleton.get_bone_rest(bone_cyclic).basis.get_rotation_quaternion() var cyc_angles_rad := cyclic * deg_to_rad(range_cyclic) var cyc_att := Quaternion.from_euler(Vector3(cyc_angles_rad.y, cyc_angles_rad.x, 0)) skeleton.set_bone_pose_rotation(bone_cyclic, cyc_att * cyc_rest) - + # Spin the rotor only when receiving flight data if connector.get_model_connected(): _rotor_azimuth += rotor_rpm * 2 * PI / 60 * delta @@ -43,3 +46,8 @@ func _process(delta: float) -> void: var rotor_att := Quaternion.from_euler(Vector3(0, _rotor_azimuth, 0)) # Note that this is reverse order, to rotate in local bone axes skeleton.set_bone_pose_rotation(bone_rotor, rotor_rest * rotor_att) + + if tracker.get_has_tracking_data(): + xr_origin.transform = tracker_mount.transform * tracker.transform.affine_inverse() + else: + xr_origin.transform = Transform3D.IDENTITY diff --git a/project/aircraft/aircraft.tscn b/project/aircraft/aircraft.tscn index bc78d00..4103f4c 100644 --- a/project/aircraft/aircraft.tscn +++ b/project/aircraft/aircraft.tscn @@ -1,7 +1,9 @@ -[gd_scene load_steps=4 format=3 uid="uid://bj1s0g7ixjw71"] +[gd_scene load_steps=6 format=3 uid="uid://bj1s0g7ixjw71"] [ext_resource type="Script" uid="uid://cx30pr7kn4c74" path="res://aircraft/aircraft.gd" id="1_l4uib"] [ext_resource type="PackedScene" uid="uid://cux4tju0ovvly" path="res://assets/mi2/Mi-2.glb" id="1_mrxe8"] +[ext_resource type="PackedScene" uid="uid://fmygcraoturj" path="res://reference_axes.tscn" id="3_2bi7g"] +[ext_resource type="PackedScene" uid="uid://cis4s43ubuynp" path="res://instruments.tscn" id="3_5w717"] [sub_resource type="StandardMaterial3D" id="StandardMaterial3D_mrxe8"] @@ -17,12 +19,32 @@ material_override = SubResource("StandardMaterial3D_mrxe8") transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 2.4, 0) [node name="PilotEyes" type="Node3D" parent="AttitudeRoot"] -editor_description = "Added only to provide a convenient point to reset XROrigin3D to" -transform = Transform3D(-1, 0, -8.74228e-08, 0, 1, 0, 8.74228e-08, 0, -1, 0.214, -0.721897, 1.53478) +editor_description = "Target position for Local XR tracking" +transform = Transform3D(-1, 0, -8.74228e-08, 0, 1, 0, 8.74228e-08, 0, -1, 0.214, -0.7, 1.594) -[node name="XROrigin3D" type="XROrigin3D" parent="AttitudeRoot/PilotEyes"] +[node name="PilotFloor" type="Node3D" parent="AttitudeRoot/PilotEyes"] +editor_description = "Required for floor tracking +(Varjo can only do that)" +transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, -0.8, 0) -[node name="XRCamera3D" type="XRCamera3D" parent="AttitudeRoot/PilotEyes/XROrigin3D"] +[node name="TrackerMountChair" type="Node3D" parent="AttitudeRoot/PilotEyes/PilotFloor"] +transform = Transform3D(-1, 8.74228e-08, -3.82137e-15, 0, -4.37114e-08, -1, -8.74228e-08, -1, 4.37114e-08, 0.27, 0.4, 0) + +[node name="ReferenceAxes" parent="AttitudeRoot/PilotEyes/PilotFloor/TrackerMountChair" instance=ExtResource("3_2bi7g")] +transform = Transform3D(0.25, 0, 0, 0, 0.25, 0, 0, 0, 0.25, 0, 0, 0) + +[node name="XROrigin3D" type="XROrigin3D" parent="AttitudeRoot/PilotEyes/PilotFloor"] + +[node name="XRCamera3D" type="XRCamera3D" parent="AttitudeRoot/PilotEyes/PilotFloor/XROrigin3D"] + +[node name="ViveTracker" type="XRController3D" parent="AttitudeRoot/PilotEyes/PilotFloor/XROrigin3D"] +tracker = &"/user/vive_tracker_htcx/role/camera" + +[node name="ReferenceAxes" parent="AttitudeRoot/PilotEyes/PilotFloor/XROrigin3D/ViveTracker" instance=ExtResource("3_2bi7g")] +transform = Transform3D(0.25, 0, 0, 0, 0.25, 0, 0, 0, 0.25, 0, 0, 0) + +[node name="Instruments" parent="AttitudeRoot" instance=ExtResource("3_5w717")] +transform = Transform3D(-0.5, -1.27582e-08, 7.43353e-08, 4.33325e-10, 0.4923, 0.0874084, -7.5421e-08, 0.0874084, -0.4923, 0.00724897, -1.1581, 2.40391) [node name="MarshConnector" type="MarshConnector" parent="."] diff --git a/project/main.tscn b/project/main.tscn index 60db560..795588e 100644 --- a/project/main.tscn +++ b/project/main.tscn @@ -1,6 +1,6 @@ [gd_scene load_steps=6 format=3 uid="uid://crq3o0eu4y8ya"] -[ext_resource type="Script" path="res://start_vr.gd" id="1_ig7tw"] +[ext_resource type="Script" uid="uid://dfcjdxesyn3l0" path="res://start_vr.gd" id="1_ig7tw"] [ext_resource type="PackedScene" uid="uid://bj1s0g7ixjw71" path="res://aircraft/aircraft.tscn" id="2_0xm2m"] [sub_resource type="ProceduralSkyMaterial" id="ProceduralSkyMaterial_7dm0k"] diff --git a/project/project.godot b/project/project.godot index 561ce7d..1e0fa8b 100644 --- a/project/project.godot +++ b/project/project.godot @@ -31,6 +31,6 @@ renderer/rendering_method.mobile="gl_compatibility" [xr] openxr/enabled=true -openxr/reference_space=0 +openxr/reference_space=2 openxr/foveation_level=3 shaders/enabled=true diff --git a/project/start_vr.gd b/project/start_vr.gd index c610b4c..ae40bb4 100644 --- a/project/start_vr.gd +++ b/project/start_vr.gd @@ -34,12 +34,16 @@ func _ready() -> void: xr_interface.session_focussed.connect(_on_openxr_focused_state) xr_interface.session_stopping.connect(_on_openxr_stopping) xr_interface.pose_recentered.connect(_on_openxr_pose_recentered) + XRServer.tracker_added.connect(_on_tracker_added) else: # We couldn't start OpenXR. print("OpenXR not instantiated!") get_tree().quit() +func _on_tracker_added(tracker_name: StringName, type: int) -> void: + print("added tracker", tracker_name, "type", type) + # Handle OpenXR session ready. func _on_openxr_session_begun() -> void: # Get the reported refresh rate.