From 4ddccdaf62e73ca35ae4d00aa3000f6f0d94833e Mon Sep 17 00:00:00 2001 From: attila-vr Date: Tue, 18 Feb 2025 11:34:59 +0100 Subject: [PATCH] Redo main scene Much simpler XR setup based on Bastiaan Olij's Dev stream 58 Correctly applied bone deformation in Mi-2 model --- project/addons/godot-xr-tools/plugin.gd.uid | 1 - project/addons/godot-xr-tools/xr_tools.gd.uid | 1 - project/aircraft.gd | 6 - project/aircraft/aircraft.gd | 19 +++ project/{ => aircraft}/aircraft.gd.uid | 0 project/aircraft/aircraft.tscn | 26 ++++ project/assets/mi2/Mi-2.glb | 4 +- project/main-xr.tscn | 38 ------ project/main.tscn | 42 +++---- project/openxr_action_map.tres | 2 +- project/project.godot | 11 +- project/start-xr.tscn | 11 -- project/start_vr.gd | 112 ++++++++++++++++++ project/start_vr.gd.uid | 1 + update_addons.py | 11 -- 15 files changed, 181 insertions(+), 104 deletions(-) delete mode 100644 project/addons/godot-xr-tools/plugin.gd.uid delete mode 100644 project/addons/godot-xr-tools/xr_tools.gd.uid delete mode 100644 project/aircraft.gd create mode 100644 project/aircraft/aircraft.gd rename project/{ => aircraft}/aircraft.gd.uid (100%) create mode 100644 project/aircraft/aircraft.tscn delete mode 100644 project/main-xr.tscn delete mode 100644 project/start-xr.tscn create mode 100644 project/start_vr.gd create mode 100644 project/start_vr.gd.uid delete mode 100644 update_addons.py diff --git a/project/addons/godot-xr-tools/plugin.gd.uid b/project/addons/godot-xr-tools/plugin.gd.uid deleted file mode 100644 index 6116563..0000000 --- a/project/addons/godot-xr-tools/plugin.gd.uid +++ /dev/null @@ -1 +0,0 @@ -uid://46i64f2dmonl diff --git a/project/addons/godot-xr-tools/xr_tools.gd.uid b/project/addons/godot-xr-tools/xr_tools.gd.uid deleted file mode 100644 index ee86026..0000000 --- a/project/addons/godot-xr-tools/xr_tools.gd.uid +++ /dev/null @@ -1 +0,0 @@ -uid://c086s0jrgaiwi diff --git a/project/aircraft.gd b/project/aircraft.gd deleted file mode 100644 index ce15b7a..0000000 --- a/project/aircraft.gd +++ /dev/null @@ -1,6 +0,0 @@ -extends Node3D - -@export var connector: MarshConnector - -func _process(_delta: float) -> void: - transform = connector.get_aircraft() diff --git a/project/aircraft/aircraft.gd b/project/aircraft/aircraft.gd new file mode 100644 index 0000000..f8c9918 --- /dev/null +++ b/project/aircraft/aircraft.gd @@ -0,0 +1,19 @@ +extends Node3D + +@onready var connector = $MarshConnector +@onready var skeleton = $"Mi-2/Armature/Skeleton3D" +@onready var attitude_root = $AttitudeRoot + +@onready var bone_cg: int = skeleton.find_bone("BodyCG") + +func _process(_delta: float) -> void: + var target: Transform3D = connector.get_aircraft() + position = target.origin + + # Add the rotation to the bone + var rest = skeleton.get_bone_rest(bone_cg).basis.get_rotation_quaternion() + var attitude = target.basis.get_rotation_quaternion() + skeleton.set_bone_pose_rotation(bone_cg, attitude * rest) + + # Rotate other children (not using BoneAttachment3D due to jitter) + attitude_root.rotation = target.basis.get_euler() diff --git a/project/aircraft.gd.uid b/project/aircraft/aircraft.gd.uid similarity index 100% rename from project/aircraft.gd.uid rename to project/aircraft/aircraft.gd.uid diff --git a/project/aircraft/aircraft.tscn b/project/aircraft/aircraft.tscn new file mode 100644 index 0000000..867edc0 --- /dev/null +++ b/project/aircraft/aircraft.tscn @@ -0,0 +1,26 @@ +[gd_scene load_steps=4 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"] + +[sub_resource type="StandardMaterial3D" id="StandardMaterial3D_mrxe8"] + +[node name="Aircraft" type="Node3D"] +script = ExtResource("1_l4uib") + +[node name="Mi-2" parent="." instance=ExtResource("1_mrxe8")] + +[node name="Łopata" parent="Mi-2/Armature/Skeleton3D" index="16"] +material_override = SubResource("StandardMaterial3D_mrxe8") + +[node name="AttitudeRoot" type="Node3D" parent="."] +transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 2.4, 0) + +[node name="XROrigin3D" type="XROrigin3D" parent="AttitudeRoot"] +transform = Transform3D(-1, 0, -8.74227e-08, 0, 0.999999, 0, 8.74228e-08, 0, -0.999999, 0.214, -0.721897, 1.53478) + +[node name="XRCamera3D" type="XRCamera3D" parent="AttitudeRoot/XROrigin3D"] + +[node name="MarshConnector" type="MarshConnector" parent="."] + +[editable path="Mi-2"] diff --git a/project/assets/mi2/Mi-2.glb b/project/assets/mi2/Mi-2.glb index 7d7de03..9c72d04 100644 --- a/project/assets/mi2/Mi-2.glb +++ b/project/assets/mi2/Mi-2.glb @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:2f50f5845353f88ca781a5605fa3aa57cbdbf688280e3b8cbd6fdcf094318145 -size 339648 +oid sha256:12565394be73ddc6c5150deaa400bbfc29ca3911dd36315fec59cd96eb3b838b +size 524076 diff --git a/project/main-xr.tscn b/project/main-xr.tscn deleted file mode 100644 index 18c3f25..0000000 --- a/project/main-xr.tscn +++ /dev/null @@ -1,38 +0,0 @@ -[gd_scene load_steps=8 format=3 uid="uid://cx82op4eecbwr"] - -[ext_resource type="Script" uid="uid://cx30pr7kn4c74" path="res://aircraft.gd" id="1_hips3"] -[ext_resource type="PackedScene" uid="uid://qbmx03iibuuu" path="res://addons/godot-xr-tools/staging/scene_base.tscn" id="1_k0lu6"] - -[sub_resource type="BoxMesh" id="BoxMesh_2w36v"] - -[sub_resource type="ProceduralSkyMaterial" id="ProceduralSkyMaterial_4tcqf"] - -[sub_resource type="Sky" id="Sky_0xm2m"] -sky_material = SubResource("ProceduralSkyMaterial_4tcqf") - -[sub_resource type="Environment" id="Environment_jdgxj"] -background_mode = 2 -sky = SubResource("Sky_0xm2m") - -[sub_resource type="CameraAttributesPractical" id="CameraAttributesPractical_fpvso"] - -[node name="SceneBase" instance=ExtResource("1_k0lu6")] - -[node name="XROrigin3D" parent="." index="0"] -transform = Transform3D(-1, 0, -8.74228e-08, 0, 1, 0, 8.74228e-08, 0, -1, 0, 0, -3) - -[node name="MarshConnector" type="MarshConnector" parent="." index="1"] - -[node name="Aircraft" type="Node3D" parent="." index="2" node_paths=PackedStringArray("connector")] -script = ExtResource("1_hips3") -connector = NodePath("../MarshConnector") - -[node name="MeshInstance3D" type="MeshInstance3D" parent="Aircraft" index="0"] -mesh = SubResource("BoxMesh_2w36v") - -[node name="DirectionalLight3D" type="DirectionalLight3D" parent="." index="3"] -transform = Transform3D(-0.707107, -0.683013, 0.183013, 0, 0.258819, 0.965926, -0.707107, 0.683013, -0.183013, 3, 3, 3) - -[node name="WorldEnvironment" type="WorldEnvironment" parent="." index="4"] -environment = SubResource("Environment_jdgxj") -camera_attributes = SubResource("CameraAttributesPractical_fpvso") diff --git a/project/main.tscn b/project/main.tscn index 2cb87ad..9b40194 100644 --- a/project/main.tscn +++ b/project/main.tscn @@ -1,37 +1,27 @@ -[gd_scene load_steps=7 format=3 uid="uid://cjrkxv8ix1h8s"] +[gd_scene load_steps=6 format=3 uid="uid://crq3o0eu4y8ya"] -[ext_resource type="Script" uid="uid://cx30pr7kn4c74" path="res://aircraft.gd" id="1_ig7tw"] +[ext_resource type="Script" 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="BoxMesh" id="BoxMesh_0xm2m"] +[sub_resource type="ProceduralSkyMaterial" id="ProceduralSkyMaterial_7dm0k"] -[sub_resource type="ProceduralSkyMaterial" id="ProceduralSkyMaterial_ig7tw"] +[sub_resource type="Sky" id="Sky_ig7tw"] +sky_material = SubResource("ProceduralSkyMaterial_7dm0k") -[sub_resource type="Sky" id="Sky_0xm2m"] -sky_material = SubResource("ProceduralSkyMaterial_ig7tw") - -[sub_resource type="Environment" id="Environment_ig7tw"] +[sub_resource type="Environment" id="Environment_0xm2m"] background_mode = 2 -sky = SubResource("Sky_0xm2m") - -[sub_resource type="CameraAttributesPractical" id="CameraAttributesPractical_0xm2m"] +sky = SubResource("Sky_ig7tw") [node name="Main" type="Node3D"] -[node name="MarshConnector" type="MarshConnector" parent="."] - -[node name="Aircraft" type="Node3D" parent="." node_paths=PackedStringArray("connector")] -script = ExtResource("1_ig7tw") -connector = NodePath("../MarshConnector") - -[node name="MeshInstance3D" type="MeshInstance3D" parent="Aircraft"] -mesh = SubResource("BoxMesh_0xm2m") - -[node name="Camera3D" type="Camera3D" parent="."] -transform = Transform3D(-1, -2.26267e-08, 8.44439e-08, 0, 0.965926, 0.258819, -8.74228e-08, 0.258819, -0.965926, 0, 1, -3) +[node name="WorldEnvironment" type="WorldEnvironment" parent="."] +environment = SubResource("Environment_0xm2m") [node name="DirectionalLight3D" type="DirectionalLight3D" parent="."] -transform = Transform3D(-0.707107, -0.683013, 0.183013, 0, 0.258819, 0.965926, -0.707107, 0.683013, -0.183013, 3, 3, 3) +transform = Transform3D(0.707107, 0.683013, -0.183013, 0, 0.258819, 0.965926, 0.707107, -0.683013, 0.183013, -3, 3, -3) -[node name="WorldEnvironment" type="WorldEnvironment" parent="."] -environment = SubResource("Environment_ig7tw") -camera_attributes = SubResource("CameraAttributesPractical_0xm2m") +[node name="StartVR" type="Node3D" parent="."] +script = ExtResource("1_ig7tw") +maximum_refresh_rate = 144 + +[node name="Aircraft" parent="." instance=ExtResource("2_0xm2m")] diff --git a/project/openxr_action_map.tres b/project/openxr_action_map.tres index 035ca38..1adcca3 100644 --- a/project/openxr_action_map.tres +++ b/project/openxr_action_map.tres @@ -1,4 +1,4 @@ -[gd_resource type="OpenXRActionMap" load_steps=417 format=3 uid="uid://c52lwapbt6wt2"] +[gd_resource type="OpenXRActionMap" load_steps=417 format=3 uid="uid://5a62ftnefy7o"] [sub_resource type="OpenXRAction" id="OpenXRAction_6ivru"] resource_name = "trigger" diff --git a/project/project.godot b/project/project.godot index 7d875dc..561ce7d 100644 --- a/project/project.godot +++ b/project/project.godot @@ -11,18 +11,13 @@ config_version=5 [application] config/name="Visualisation for MARSH" -run/main_scene="uid://ba764fx7hx8ei" +run/main_scene="uid://crq3o0eu4y8ya" config/features=PackedStringArray("4.4", "GL Compatibility") config/icon="res://icon.svg" -[autoload] - -XRToolsUserSettings="*res://addons/godot-xr-tools/user_settings/user_settings.gd" -XRToolsRumbleManager="*res://addons/godot-xr-tools/rumble/rumble_manager.gd" - [editor_plugins] -enabled=PackedStringArray("res://addons/godot-xr-tools/plugin.cfg") +enabled=PackedStringArray() [physics] @@ -36,4 +31,6 @@ renderer/rendering_method.mobile="gl_compatibility" [xr] openxr/enabled=true +openxr/reference_space=0 +openxr/foveation_level=3 shaders/enabled=true diff --git a/project/start-xr.tscn b/project/start-xr.tscn deleted file mode 100644 index adc9b83..0000000 --- a/project/start-xr.tscn +++ /dev/null @@ -1,11 +0,0 @@ -[gd_scene load_steps=3 format=3 uid="uid://ba764fx7hx8ei"] - -[ext_resource type="PackedScene" uid="uid://bnqnnnet4dw12" path="res://addons/godot-xr-tools/staging/staging.tscn" id="1_hips3"] -[ext_resource type="Texture2D" uid="uid://ftrrxm7sxndi" path="res://assets/splash/splash.png" id="2_k0lu6"] - -[node name="Staging" instance=ExtResource("1_hips3")] -main_scene = "uid://cx82op4eecbwr" -prompt_for_continue = false - -[node name="LoadingScreen" parent="." index="2"] -splash_screen = ExtResource("2_k0lu6") diff --git a/project/start_vr.gd b/project/start_vr.gd new file mode 100644 index 0000000..c610b4c --- /dev/null +++ b/project/start_vr.gd @@ -0,0 +1,112 @@ +extends Node3D + +signal focus_lost +signal focus_gained +signal pose_recentered + +@export var maximum_refresh_rate : int = 90 + +var xr_interface : OpenXRInterface +var xr_is_focused := false + + +func _ready() -> void: + xr_interface = XRServer.find_interface("OpenXR") + if xr_interface and xr_interface.is_initialized(): + print("OpenXR instantiated successfully.") + var vp : Viewport = get_viewport() + + # Enable XR on our viewport. + vp.use_xr = true + + # Make sure V-Sync is off, as V-Sync is handled by OpenXR. + DisplayServer.window_set_vsync_mode(DisplayServer.VSYNC_DISABLED) + + # Enable variable rate shading. + if RenderingServer.get_rendering_device(): + vp.vrs_mode = Viewport.VRS_XR + elif int(ProjectSettings.get_setting("xr/openxr/foveation_level")) == 0: + push_warning("OpenXR: Recommend setting Foveation level to High in Project Settings") + + # Connect the OpenXR events. + xr_interface.session_begun.connect(_on_openxr_session_begun) + xr_interface.session_visible.connect(_on_openxr_visible_state) + 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) + else: + # We couldn't start OpenXR. + print("OpenXR not instantiated!") + get_tree().quit() + + +# Handle OpenXR session ready. +func _on_openxr_session_begun() -> void: + # Get the reported refresh rate. + var current_refresh_rate := xr_interface.get_display_refresh_rate() + if current_refresh_rate > 0: + print("OpenXR: Refresh rate reported as ", str(current_refresh_rate)) + else: + print("OpenXR: No refresh rate given by XR runtime") + + # See if we have a better refresh rate available. + var new_rate := current_refresh_rate + var available_rates: Array = xr_interface.get_available_display_refresh_rates() + if available_rates.is_empty(): + print("OpenXR: Target does not support refresh rate extension") + elif available_rates.size() == 1: + # Only one available, so use it. + new_rate = available_rates[0] + else: + for rate in available_rates: + if rate > new_rate and rate <= maximum_refresh_rate: + new_rate = rate + + # Did we find a better rate? + if current_refresh_rate != new_rate: + print("OpenXR: Setting refresh rate to ", str(new_rate)) + xr_interface.set_display_refresh_rate(new_rate) + current_refresh_rate = new_rate + + # Now match our physics rate. This is currently needed to avoid jittering, + # due to physics interpolation not being used. + Engine.physics_ticks_per_second = roundi(current_refresh_rate) + + +# Handle OpenXR visible state. +func _on_openxr_visible_state() -> void: + # We always pass this state at startup, + # but the second time we get this, it means our player took off their headset. + if xr_is_focused: + print("OpenXR lost focus") + + xr_is_focused = false + + # Pause our game. + process_mode = Node.PROCESS_MODE_DISABLED + + focus_lost.emit() + + +# Handle OpenXR focused state +func _on_openxr_focused_state() -> void: + print("OpenXR gained focus") + xr_is_focused = true + + # Unpause our game. + process_mode = Node.PROCESS_MODE_INHERIT + + focus_gained.emit() + + +# Handle OpenXR stopping state. +func _on_openxr_stopping() -> void: + # Our session is being stopped. + print("OpenXR is stopping") + + +# Handle OpenXR pose recentered signal. +func _on_openxr_pose_recentered() -> void: + # User recentered view, we have to react to this by recentering the view. + # This is game implementation dependent. + pose_recentered.emit() diff --git a/project/start_vr.gd.uid b/project/start_vr.gd.uid new file mode 100644 index 0000000..036f8dc --- /dev/null +++ b/project/start_vr.gd.uid @@ -0,0 +1 @@ +uid://dfcjdxesyn3l0 diff --git a/update_addons.py b/update_addons.py deleted file mode 100644 index 151aea3..0000000 --- a/update_addons.py +++ /dev/null @@ -1,11 +0,0 @@ -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, -)