mirror of
https://github.com/godotengine/godot-demo-projects.git
synced 2025-12-16 05:20:06 +01:00
Added an OpenXR render models demo
This commit is contained in:
2
xr/openxr_render_models/.gitattributes
vendored
Normal file
2
xr/openxr_render_models/.gitattributes
vendored
Normal file
@@ -0,0 +1,2 @@
|
||||
# Normalize EOL for all files that Git considers text files.
|
||||
* text=auto eol=lf
|
||||
4
xr/openxr_render_models/.gitignore
vendored
Normal file
4
xr/openxr_render_models/.gitignore
vendored
Normal file
@@ -0,0 +1,4 @@
|
||||
# Godot 4+ specific ignores
|
||||
.godot/
|
||||
.editorconfig
|
||||
/android/
|
||||
50
xr/openxr_render_models/README.md
Normal file
50
xr/openxr_render_models/README.md
Normal file
@@ -0,0 +1,50 @@
|
||||
# OpenXR Render models demo
|
||||
|
||||
This is a demo showing OpenXR's render models implementation.
|
||||
|
||||
Language: GDScript
|
||||
|
||||
Renderer: Compatibility
|
||||
|
||||
> [!NOTE]
|
||||
>
|
||||
> This demo requires Godot 4.5 or later
|
||||
|
||||
## Screenshots
|
||||
|
||||

|
||||
|
||||
## How does it work?
|
||||
|
||||
OpenXR allows us to run our application without having knowledge of the hardware being used,
|
||||
or that we as developers have access too at the time of developing our application.
|
||||
|
||||
As a result we don't have direct information telling us what hardware is being used,
|
||||
however there are situations where we want to visually show this hardware.
|
||||
|
||||
This specifically applies to the controllers used by the user, as showing the correct hardware
|
||||
improves the user's sense of immersion.
|
||||
|
||||
The render model API allows us to enumerate the devices currently in use and then query
|
||||
information such as its 3D asset, its position and orientation in space, and the position
|
||||
and orientation of individual components of the asset.
|
||||
|
||||
Godot's implementation hides most of the complexity of this through the OpenXRRenderModelManager
|
||||
node as a child of the XROrigin3D node. You can add just this node by itself and let it show
|
||||
all render models that are currently active, or like we do in this demo, you can add nodes
|
||||
in the tree of each controller to show render models related to that controller.
|
||||
|
||||
## Action map
|
||||
|
||||
This demo project has a barebones action map as we're only dealing with positioning.
|
||||
|
||||
## Running on PCVR
|
||||
|
||||
This project can be run as normal for PCVR. Ensure that an OpenXR runtime has been installed.
|
||||
|
||||
## Running on standalone VR
|
||||
|
||||
You must install the Android build templates and OpenXR loader plugin and configure an export template for your device.
|
||||
Please follow [the instructions for deploying on Android in the manual](https://docs.godotengine.org/en/stable/tutorials/xr/deploying_to_android.html).
|
||||
|
||||
|
||||
BIN
xr/openxr_render_models/assets/pattern.png
Normal file
BIN
xr/openxr_render_models/assets/pattern.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 1.8 KiB |
41
xr/openxr_render_models/assets/pattern.png.import
Normal file
41
xr/openxr_render_models/assets/pattern.png.import
Normal file
@@ -0,0 +1,41 @@
|
||||
[remap]
|
||||
|
||||
importer="texture"
|
||||
type="CompressedTexture2D"
|
||||
uid="uid://btobyv4xjhltq"
|
||||
path.s3tc="res://.godot/imported/pattern.png-cf6f03dfd1cdd4bc35da3414e912103d.s3tc.ctex"
|
||||
metadata={
|
||||
"imported_formats": ["s3tc_bptc"],
|
||||
"vram_texture": true
|
||||
}
|
||||
|
||||
[deps]
|
||||
|
||||
source_file="res://assets/pattern.png"
|
||||
dest_files=["res://.godot/imported/pattern.png-cf6f03dfd1cdd4bc35da3414e912103d.s3tc.ctex"]
|
||||
|
||||
[params]
|
||||
|
||||
compress/mode=2
|
||||
compress/high_quality=false
|
||||
compress/lossy_quality=0.7
|
||||
compress/uastc_level=0
|
||||
compress/rdo_quality_loss=0.0
|
||||
compress/hdr_compression=1
|
||||
compress/normal_map=0
|
||||
compress/channel_pack=0
|
||||
mipmaps/generate=true
|
||||
mipmaps/limit=-1
|
||||
roughness/mode=0
|
||||
roughness/src_normal=""
|
||||
process/channel_remap/red=0
|
||||
process/channel_remap/green=1
|
||||
process/channel_remap/blue=2
|
||||
process/channel_remap/alpha=3
|
||||
process/fix_alpha_border=true
|
||||
process/premult_alpha=false
|
||||
process/normal_map_invert_y=false
|
||||
process/hdr_as_srgb=false
|
||||
process/hdr_clamp_exposure=false
|
||||
process/size_limit=0
|
||||
detect_3d/compress_to=0
|
||||
21
xr/openxr_render_models/box.tscn
Normal file
21
xr/openxr_render_models/box.tscn
Normal file
@@ -0,0 +1,21 @@
|
||||
[gd_scene load_steps=5 format=3 uid="uid://cfgfwisj8m2mg"]
|
||||
|
||||
[ext_resource type="Texture2D" uid="uid://btobyv4xjhltq" path="res://assets/pattern.png" id="1_g2tbl"]
|
||||
|
||||
[sub_resource type="BoxShape3D" id="BoxShape3D_oq5cr"]
|
||||
|
||||
[sub_resource type="StandardMaterial3D" id="StandardMaterial3D_bqn3j"]
|
||||
albedo_color = Color(0.16217351, 0.546357, 0.5366536, 1)
|
||||
albedo_texture = ExtResource("1_g2tbl")
|
||||
uv1_scale = Vector3(3, 3, 3)
|
||||
|
||||
[sub_resource type="BoxMesh" id="BoxMesh_3n43a"]
|
||||
material = SubResource("StandardMaterial3D_bqn3j")
|
||||
|
||||
[node name="Box" type="RigidBody3D"]
|
||||
|
||||
[node name="CollisionShape3D" type="CollisionShape3D" parent="."]
|
||||
shape = SubResource("BoxShape3D_oq5cr")
|
||||
|
||||
[node name="MeshInstance3D" type="MeshInstance3D" parent="."]
|
||||
mesh = SubResource("BoxMesh_3n43a")
|
||||
19
xr/openxr_render_models/collision_hands.gd
Normal file
19
xr/openxr_render_models/collision_hands.gd
Normal file
@@ -0,0 +1,19 @@
|
||||
class_name CollisionHands3D
|
||||
extends AnimatableBody3D
|
||||
|
||||
func _ready():
|
||||
# Make sure these are set correctly.
|
||||
top_level = true
|
||||
sync_to_physics = false
|
||||
process_physics_priority = -90
|
||||
|
||||
|
||||
func _physics_process(_delta):
|
||||
# Follow our parent node around.
|
||||
var dest_transform = get_parent().global_transform
|
||||
|
||||
# We just apply rotation for this example.
|
||||
global_basis = dest_transform.basis
|
||||
|
||||
# Attempt to move to where our tracked hand is.
|
||||
move_and_collide(dest_transform.origin - global_position)
|
||||
1
xr/openxr_render_models/collision_hands.gd.uid
Normal file
1
xr/openxr_render_models/collision_hands.gd.uid
Normal file
@@ -0,0 +1 @@
|
||||
uid://c5bnmb8grcumh
|
||||
1
xr/openxr_render_models/icon.svg
Normal file
1
xr/openxr_render_models/icon.svg
Normal file
@@ -0,0 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="128" height="128"><rect width="124" height="124" x="2" y="2" fill="#363d52" stroke="#212532" stroke-width="4" rx="14"/><g fill="#fff" transform="translate(12.322 12.322)scale(.101)"><path d="M105 673v33q407 354 814 0v-33z"/><path fill="#478cbf" d="m105 673 152 14q12 1 15 14l4 67 132 10 8-61q2-11 15-15h162q13 4 15 15l8 61 132-10 4-67q3-13 15-14l152-14V427q30-39 56-81-35-59-83-108-43 20-82 47-40-37-88-64 7-51 8-102-59-28-123-42-26 43-46 89-49-7-98 0-20-46-46-89-64 14-123 42 1 51 8 102-48 27-88 64-39-27-82-47-48 49-83 108 26 42 56 81zm0 33v39c0 276 813 276 814 0v-39l-134 12-5 69q-2 10-14 13l-162 11q-12 0-16-11l-10-65H446l-10 65q-4 11-16 11l-162-11q-12-3-14-13l-5-69z"/><path d="M483 600c0 34 58 34 58 0v-86c0-34-58-34-58 0z"/><circle cx="725" cy="526" r="90"/><circle cx="299" cy="526" r="90"/></g><g fill="#414042" transform="translate(12.322 12.322)scale(.101)"><circle cx="307" cy="532" r="60"/><circle cx="717" cy="532" r="60"/></g></svg>
|
||||
|
After Width: | Height: | Size: 995 B |
43
xr/openxr_render_models/icon.svg.import
Normal file
43
xr/openxr_render_models/icon.svg.import
Normal file
@@ -0,0 +1,43 @@
|
||||
[remap]
|
||||
|
||||
importer="texture"
|
||||
type="CompressedTexture2D"
|
||||
uid="uid://bi6bu4ng584fq"
|
||||
path="res://.godot/imported/icon.svg-218a8f2b3041327d8a5756f3a245f83b.ctex"
|
||||
metadata={
|
||||
"vram_texture": false
|
||||
}
|
||||
|
||||
[deps]
|
||||
|
||||
source_file="res://icon.svg"
|
||||
dest_files=["res://.godot/imported/icon.svg-218a8f2b3041327d8a5756f3a245f83b.ctex"]
|
||||
|
||||
[params]
|
||||
|
||||
compress/mode=0
|
||||
compress/high_quality=false
|
||||
compress/lossy_quality=0.7
|
||||
compress/uastc_level=0
|
||||
compress/rdo_quality_loss=0.0
|
||||
compress/hdr_compression=1
|
||||
compress/normal_map=0
|
||||
compress/channel_pack=0
|
||||
mipmaps/generate=false
|
||||
mipmaps/limit=-1
|
||||
roughness/mode=0
|
||||
roughness/src_normal=""
|
||||
process/channel_remap/red=0
|
||||
process/channel_remap/green=1
|
||||
process/channel_remap/blue=2
|
||||
process/channel_remap/alpha=3
|
||||
process/fix_alpha_border=true
|
||||
process/premult_alpha=false
|
||||
process/normal_map_invert_y=false
|
||||
process/hdr_as_srgb=false
|
||||
process/hdr_clamp_exposure=false
|
||||
process/size_limit=0
|
||||
detect_3d/compress_to=1
|
||||
svg/scale=1.0
|
||||
editor/scale_with_editor_scale=false
|
||||
editor/convert_colors_with_editor_theme=false
|
||||
122
xr/openxr_render_models/main.tscn
Normal file
122
xr/openxr_render_models/main.tscn
Normal file
@@ -0,0 +1,122 @@
|
||||
[gd_scene load_steps=13 format=3 uid="uid://btli1dajen53o"]
|
||||
|
||||
[ext_resource type="Script" uid="uid://bqa4r4n7b6d7s" path="res://start_vr.gd" id="1_1bvp3"]
|
||||
[ext_resource type="Script" uid="uid://c5bnmb8grcumh" path="res://collision_hands.gd" id="1_ig7tw"]
|
||||
[ext_resource type="Texture2D" uid="uid://btobyv4xjhltq" path="res://assets/pattern.png" id="2_h2yge"]
|
||||
[ext_resource type="PackedScene" uid="uid://cfgfwisj8m2mg" path="res://box.tscn" id="3_1bvp3"]
|
||||
[ext_resource type="PackedScene" uid="uid://c7ohc2o1shtu7" path="res://wall.tscn" id="5_lquwl"]
|
||||
|
||||
[sub_resource type="ProceduralSkyMaterial" id="ProceduralSkyMaterial_7dm0k"]
|
||||
sky_horizon_color = Color(0.662243, 0.671743, 0.686743, 1)
|
||||
ground_horizon_color = Color(0.662243, 0.671743, 0.686743, 1)
|
||||
|
||||
[sub_resource type="Sky" id="Sky_ig7tw"]
|
||||
sky_material = SubResource("ProceduralSkyMaterial_7dm0k")
|
||||
|
||||
[sub_resource type="Environment" id="Environment_0xm2m"]
|
||||
background_mode = 2
|
||||
sky = SubResource("Sky_ig7tw")
|
||||
tonemap_mode = 2
|
||||
|
||||
[sub_resource type="SphereShape3D" id="SphereShape3D_0xm2m"]
|
||||
radius = 0.02
|
||||
|
||||
[sub_resource type="WorldBoundaryShape3D" id="WorldBoundaryShape3D_lquwl"]
|
||||
|
||||
[sub_resource type="StandardMaterial3D" id="StandardMaterial3D_7mycd"]
|
||||
albedo_color = Color(0.3241276, 0.50004333, 0.2159737, 1)
|
||||
albedo_texture = ExtResource("2_h2yge")
|
||||
uv1_scale = Vector3(100, 100, 100)
|
||||
|
||||
[sub_resource type="PlaneMesh" id="PlaneMesh_272bh"]
|
||||
material = SubResource("StandardMaterial3D_7mycd")
|
||||
size = Vector2(1000, 1000)
|
||||
|
||||
[node name="Main" type="Node3D"]
|
||||
|
||||
[node name="StartVR" type="Node3D" parent="."]
|
||||
script = ExtResource("1_1bvp3")
|
||||
|
||||
[node name="DirectionalLight3D" type="DirectionalLight3D" parent="."]
|
||||
transform = Transform3D(-0.866025, -0.433013, 0.25, 0, 0.5, 0.866025, -0.5, 0.75, -0.433013, 0, 0, 0)
|
||||
shadow_enabled = true
|
||||
shadow_bias = 0.01
|
||||
directional_shadow_max_distance = 50.0
|
||||
|
||||
[node name="WorldEnvironment" type="WorldEnvironment" parent="."]
|
||||
environment = SubResource("Environment_0xm2m")
|
||||
|
||||
[node name="XROrigin3D" type="XROrigin3D" parent="."]
|
||||
|
||||
[node name="XRCamera3D" type="XRCamera3D" parent="XROrigin3D"]
|
||||
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1.7, 0)
|
||||
|
||||
[node name="OpenXRRenderManager" type="OpenXRRenderModelManager" parent="XROrigin3D"]
|
||||
tracker = 1
|
||||
|
||||
[node name="LeftHand" type="XRController3D" parent="XROrigin3D"]
|
||||
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -0.5, 1, -0.5)
|
||||
tracker = &"left_hand"
|
||||
pose = &"grip"
|
||||
|
||||
[node name="CollisionHands3D" type="AnimatableBody3D" parent="XROrigin3D/LeftHand"]
|
||||
script = ExtResource("1_ig7tw")
|
||||
metadata/_custom_type_script = "uid://c5bnmb8grcumh"
|
||||
|
||||
[node name="OpenXRRenderManager" type="OpenXRRenderModelManager" parent="XROrigin3D/LeftHand/CollisionHands3D"]
|
||||
tracker = 2
|
||||
make_local_to_pose = "grip"
|
||||
|
||||
[node name="CollisionShape3D" type="CollisionShape3D" parent="XROrigin3D/LeftHand/CollisionHands3D"]
|
||||
shape = SubResource("SphereShape3D_0xm2m")
|
||||
|
||||
[node name="RightHand" type="XRController3D" parent="XROrigin3D"]
|
||||
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0.5, 1, -0.5)
|
||||
tracker = &"right_hand"
|
||||
pose = &"grip"
|
||||
|
||||
[node name="CollisionHands3D" type="AnimatableBody3D" parent="XROrigin3D/RightHand"]
|
||||
script = ExtResource("1_ig7tw")
|
||||
metadata/_custom_type_script = "uid://c5bnmb8grcumh"
|
||||
|
||||
[node name="OpenXRRenderManager" type="OpenXRRenderModelManager" parent="XROrigin3D/RightHand/CollisionHands3D"]
|
||||
tracker = 3
|
||||
make_local_to_pose = "grip"
|
||||
|
||||
[node name="CollisionShape3D" type="CollisionShape3D" parent="XROrigin3D/RightHand/CollisionHands3D"]
|
||||
shape = SubResource("SphereShape3D_0xm2m")
|
||||
|
||||
[node name="Floor" type="StaticBody3D" parent="."]
|
||||
|
||||
[node name="CollisionShape3D" type="CollisionShape3D" parent="Floor"]
|
||||
shape = SubResource("WorldBoundaryShape3D_lquwl")
|
||||
|
||||
[node name="MeshInstance3D" type="MeshInstance3D" parent="Floor"]
|
||||
mesh = SubResource("PlaneMesh_272bh")
|
||||
|
||||
[node name="Box" parent="." instance=ExtResource("3_1bvp3")]
|
||||
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0.75, 0.5, -0.75)
|
||||
|
||||
[node name="Wall01" parent="." instance=ExtResource("5_lquwl")]
|
||||
transform = Transform3D(0.5077975, 0.073525466, 0.8583331, -0.14741239, 0.989072, 0.0024858303, -0.8487705, -0.12779121, 0.5130869, -1.3576927, -0.4236443, 0)
|
||||
|
||||
[node name="Wall02" parent="." instance=ExtResource("5_lquwl")]
|
||||
transform = Transform3D(-0.4400646, -0.09660582, 0.89275444, 0, 0.9941961, 0.10758293, -0.89796615, 0.047343437, -0.43751052, 2.5047212, -0.106753826, 0.0325222)
|
||||
|
||||
[node name="Wall03" parent="." instance=ExtResource("5_lquwl")]
|
||||
transform = Transform3D(0.584169, -0.048437964, 0.8101854, -0.1719119, 0.9681845, 0.181838, -0.7932168, -0.24550463, 0.5572562, 2.4887834, -0.7894809, 2.6100364)
|
||||
|
||||
[node name="Wall04" parent="." instance=ExtResource("5_lquwl")]
|
||||
transform = Transform3D(-0.63450754, -0.2243154, 0.7396504, -0.12261418, 0.9740546, 0.19021934, -0.763129, 0.030003972, -0.64554924, -1.2827711, -0.22003722, 2.6100364)
|
||||
|
||||
[node name="Wall05" parent="." instance=ExtResource("5_lquwl")]
|
||||
transform = Transform3D(-0.9373456, 0.2908417, 0.1918185, 0.3214552, 0.93427694, 0.1542501, -0.13434927, 0.20624672, -0.9692331, 0.36298275, -0.48010635, -3.1081657)
|
||||
|
||||
[node name="Wall06" parent="." instance=ExtResource("5_lquwl")]
|
||||
transform = Transform3D(-0.990934, 0, 0.13434926, 0, 1, 0, -0.13434926, 0, -0.990934, 0.75976896, -0.70440745, 4.5405197)
|
||||
|
||||
[node name="Wall07" parent="." instance=ExtResource("5_lquwl")]
|
||||
transform = Transform3D(0.02368374, 0.13314083, -0.99081427, -0.16938388, 0.97729725, 0.12727568, 0.9852657, 0.16481358, 0.045697965, 3.8073082, -0.5026467, 0.84226894)
|
||||
|
||||
[node name="Wall08" parent="." instance=ExtResource("5_lquwl")]
|
||||
transform = Transform3D(0.023540916, 0.2297096, -0.9729746, -0.2009241, 0.95447266, 0.22048022, 0.97932404, 0.19030367, 0.06862336, -3.4319887, -0.45930338, 0.84226894)
|
||||
140
xr/openxr_render_models/openxr_action_map.tres
Normal file
140
xr/openxr_render_models/openxr_action_map.tres
Normal file
@@ -0,0 +1,140 @@
|
||||
[gd_resource type="OpenXRActionMap" load_steps=33 format=3 uid="uid://cqrfv76xcmkca"]
|
||||
|
||||
[sub_resource type="OpenXRAction" id="OpenXRAction_m08eo"]
|
||||
resource_name = "aim_pose"
|
||||
localized_name = "Aim pose"
|
||||
action_type = 3
|
||||
toplevel_paths = PackedStringArray("/user/hand/left", "/user/hand/right")
|
||||
|
||||
[sub_resource type="OpenXRAction" id="OpenXRAction_c4j1d"]
|
||||
resource_name = "grip_pose"
|
||||
localized_name = "Grip pose"
|
||||
action_type = 3
|
||||
toplevel_paths = PackedStringArray("/user/hand/left", "/user/hand/right")
|
||||
|
||||
[sub_resource type="OpenXRAction" id="OpenXRAction_sow2k"]
|
||||
resource_name = "haptic"
|
||||
localized_name = "Haptic"
|
||||
action_type = 4
|
||||
toplevel_paths = PackedStringArray("/user/hand/left", "/user/hand/right", "/user/vive_tracker_htcx/role/left_foot", "/user/vive_tracker_htcx/role/right_foot", "/user/vive_tracker_htcx/role/left_shoulder", "/user/vive_tracker_htcx/role/right_shoulder", "/user/vive_tracker_htcx/role/left_elbow", "/user/vive_tracker_htcx/role/right_elbow", "/user/vive_tracker_htcx/role/left_knee", "/user/vive_tracker_htcx/role/right_knee", "/user/vive_tracker_htcx/role/waist", "/user/vive_tracker_htcx/role/chest", "/user/vive_tracker_htcx/role/camera", "/user/vive_tracker_htcx/role/keyboard")
|
||||
|
||||
[sub_resource type="OpenXRActionSet" id="OpenXRActionSet_ngwcy"]
|
||||
resource_name = "godot"
|
||||
localized_name = "Godot action set"
|
||||
actions = [SubResource("OpenXRAction_m08eo"), SubResource("OpenXRAction_c4j1d"), SubResource("OpenXRAction_sow2k")]
|
||||
|
||||
[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_pjtev"]
|
||||
action = SubResource("OpenXRAction_m08eo")
|
||||
binding_path = "/user/hand/left/input/aim/pose"
|
||||
|
||||
[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_nqyri"]
|
||||
action = SubResource("OpenXRAction_m08eo")
|
||||
binding_path = "/user/hand/right/input/aim/pose"
|
||||
|
||||
[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_86uui"]
|
||||
action = SubResource("OpenXRAction_c4j1d")
|
||||
binding_path = "/user/hand/left/input/grip/pose"
|
||||
|
||||
[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_nrtxc"]
|
||||
action = SubResource("OpenXRAction_c4j1d")
|
||||
binding_path = "/user/hand/right/input/grip/pose"
|
||||
|
||||
[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_rjtq8"]
|
||||
action = SubResource("OpenXRAction_sow2k")
|
||||
binding_path = "/user/hand/left/output/haptic"
|
||||
|
||||
[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_lce2q"]
|
||||
action = SubResource("OpenXRAction_sow2k")
|
||||
binding_path = "/user/hand/right/output/haptic"
|
||||
|
||||
[sub_resource type="OpenXRInteractionProfile" id="OpenXRInteractionProfile_ckeh6"]
|
||||
interaction_profile_path = "/interaction_profiles/khr/simple_controller"
|
||||
bindings = [SubResource("OpenXRIPBinding_pjtev"), SubResource("OpenXRIPBinding_nqyri"), SubResource("OpenXRIPBinding_86uui"), SubResource("OpenXRIPBinding_nrtxc"), SubResource("OpenXRIPBinding_rjtq8"), SubResource("OpenXRIPBinding_lce2q")]
|
||||
|
||||
[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_chplt"]
|
||||
action = SubResource("OpenXRAction_m08eo")
|
||||
binding_path = "/user/hand/left/input/aim/pose"
|
||||
|
||||
[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_obxrh"]
|
||||
action = SubResource("OpenXRAction_m08eo")
|
||||
binding_path = "/user/hand/right/input/aim/pose"
|
||||
|
||||
[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_on7oi"]
|
||||
action = SubResource("OpenXRAction_c4j1d")
|
||||
binding_path = "/user/hand/left/input/grip/pose"
|
||||
|
||||
[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_ege4h"]
|
||||
action = SubResource("OpenXRAction_c4j1d")
|
||||
binding_path = "/user/hand/right/input/grip/pose"
|
||||
|
||||
[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_me87v"]
|
||||
action = SubResource("OpenXRAction_sow2k")
|
||||
binding_path = "/user/hand/left/output/haptic"
|
||||
|
||||
[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_d8myu"]
|
||||
action = SubResource("OpenXRAction_sow2k")
|
||||
binding_path = "/user/hand/right/output/haptic"
|
||||
|
||||
[sub_resource type="OpenXRInteractionProfile" id="OpenXRInteractionProfile_hsh5n"]
|
||||
interaction_profile_path = "/interaction_profiles/oculus/touch_controller"
|
||||
bindings = [SubResource("OpenXRIPBinding_chplt"), SubResource("OpenXRIPBinding_obxrh"), SubResource("OpenXRIPBinding_on7oi"), SubResource("OpenXRIPBinding_ege4h"), SubResource("OpenXRIPBinding_me87v"), SubResource("OpenXRIPBinding_d8myu")]
|
||||
|
||||
[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_gosqu"]
|
||||
action = SubResource("OpenXRAction_m08eo")
|
||||
binding_path = "/user/hand/left/input/aim/pose"
|
||||
|
||||
[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_n52fm"]
|
||||
action = SubResource("OpenXRAction_m08eo")
|
||||
binding_path = "/user/hand/right/input/aim/pose"
|
||||
|
||||
[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_vushy"]
|
||||
action = SubResource("OpenXRAction_c4j1d")
|
||||
binding_path = "/user/hand/left/input/grip/pose"
|
||||
|
||||
[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_lbhgg"]
|
||||
action = SubResource("OpenXRAction_c4j1d")
|
||||
binding_path = "/user/hand/right/input/grip/pose"
|
||||
|
||||
[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_8xxre"]
|
||||
action = SubResource("OpenXRAction_sow2k")
|
||||
binding_path = "/user/hand/left/output/haptic"
|
||||
|
||||
[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_jceb4"]
|
||||
action = SubResource("OpenXRAction_sow2k")
|
||||
binding_path = "/user/hand/right/output/haptic"
|
||||
|
||||
[sub_resource type="OpenXRInteractionProfile" id="OpenXRInteractionProfile_lvl5r"]
|
||||
interaction_profile_path = "/interaction_profiles/bytedance/pico4_controller"
|
||||
bindings = [SubResource("OpenXRIPBinding_gosqu"), SubResource("OpenXRIPBinding_n52fm"), SubResource("OpenXRIPBinding_vushy"), SubResource("OpenXRIPBinding_lbhgg"), SubResource("OpenXRIPBinding_8xxre"), SubResource("OpenXRIPBinding_jceb4")]
|
||||
|
||||
[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_34k6i"]
|
||||
action = SubResource("OpenXRAction_m08eo")
|
||||
binding_path = "/user/hand/left/input/aim/pose"
|
||||
|
||||
[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_biq8g"]
|
||||
action = SubResource("OpenXRAction_m08eo")
|
||||
binding_path = "/user/hand/right/input/aim/pose"
|
||||
|
||||
[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_7rnxc"]
|
||||
action = SubResource("OpenXRAction_c4j1d")
|
||||
binding_path = "/user/hand/left/input/grip/pose"
|
||||
|
||||
[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_go0kb"]
|
||||
action = SubResource("OpenXRAction_c4j1d")
|
||||
binding_path = "/user/hand/right/input/grip/pose"
|
||||
|
||||
[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_nudtj"]
|
||||
action = SubResource("OpenXRAction_sow2k")
|
||||
binding_path = "/user/hand/left/output/haptic"
|
||||
|
||||
[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_2a6v2"]
|
||||
action = SubResource("OpenXRAction_sow2k")
|
||||
binding_path = "/user/hand/right/output/haptic"
|
||||
|
||||
[sub_resource type="OpenXRInteractionProfile" id="OpenXRInteractionProfile_jhul1"]
|
||||
interaction_profile_path = "/interaction_profiles/valve/index_controller"
|
||||
bindings = [SubResource("OpenXRIPBinding_34k6i"), SubResource("OpenXRIPBinding_biq8g"), SubResource("OpenXRIPBinding_7rnxc"), SubResource("OpenXRIPBinding_go0kb"), SubResource("OpenXRIPBinding_nudtj"), SubResource("OpenXRIPBinding_2a6v2")]
|
||||
|
||||
[resource]
|
||||
action_sets = [SubResource("OpenXRActionSet_ngwcy")]
|
||||
interaction_profiles = [SubResource("OpenXRInteractionProfile_ckeh6"), SubResource("OpenXRInteractionProfile_hsh5n"), SubResource("OpenXRInteractionProfile_lvl5r"), SubResource("OpenXRInteractionProfile_jhul1")]
|
||||
34
xr/openxr_render_models/project.godot
Normal file
34
xr/openxr_render_models/project.godot
Normal file
@@ -0,0 +1,34 @@
|
||||
; Engine configuration file.
|
||||
; It's best edited using the editor UI and not directly,
|
||||
; since the parameters that go here are not all obvious.
|
||||
;
|
||||
; Format:
|
||||
; [section] ; section goes between []
|
||||
; param=value ; assign values to parameters
|
||||
|
||||
config_version=5
|
||||
|
||||
[application]
|
||||
|
||||
config/name="openxr render models"
|
||||
run/main_scene="uid://btli1dajen53o"
|
||||
config/features=PackedStringArray("4.5", "GL Compatibility")
|
||||
config/icon="res://icon.svg"
|
||||
|
||||
[physics]
|
||||
|
||||
3d/physics_engine="Jolt Physics"
|
||||
|
||||
[rendering]
|
||||
|
||||
renderer/rendering_method="gl_compatibility"
|
||||
renderer/rendering_method.mobile="gl_compatibility"
|
||||
|
||||
[xr]
|
||||
|
||||
openxr/enabled=true
|
||||
openxr/reference_space=2
|
||||
openxr/foveation_level=3
|
||||
openxr/foveation_dynamic=true
|
||||
shaders/enabled=true
|
||||
openxr/extensions/render_model=true
|
||||
BIN
xr/openxr_render_models/screenshots/render_model_demo.png
Normal file
BIN
xr/openxr_render_models/screenshots/render_model_demo.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 327 KiB |
@@ -0,0 +1,40 @@
|
||||
[remap]
|
||||
|
||||
importer="texture"
|
||||
type="CompressedTexture2D"
|
||||
uid="uid://4eulsha6ncfa"
|
||||
path="res://.godot/imported/render_model_demo.png-3043378ddd018812c86616f385e65c99.ctex"
|
||||
metadata={
|
||||
"vram_texture": false
|
||||
}
|
||||
|
||||
[deps]
|
||||
|
||||
source_file="res://screenshots/render_model_demo.png"
|
||||
dest_files=["res://.godot/imported/render_model_demo.png-3043378ddd018812c86616f385e65c99.ctex"]
|
||||
|
||||
[params]
|
||||
|
||||
compress/mode=0
|
||||
compress/high_quality=false
|
||||
compress/lossy_quality=0.7
|
||||
compress/uastc_level=0
|
||||
compress/rdo_quality_loss=0.0
|
||||
compress/hdr_compression=1
|
||||
compress/normal_map=0
|
||||
compress/channel_pack=0
|
||||
mipmaps/generate=false
|
||||
mipmaps/limit=-1
|
||||
roughness/mode=0
|
||||
roughness/src_normal=""
|
||||
process/channel_remap/red=0
|
||||
process/channel_remap/green=1
|
||||
process/channel_remap/blue=2
|
||||
process/channel_remap/alpha=3
|
||||
process/fix_alpha_border=true
|
||||
process/premult_alpha=false
|
||||
process/normal_map_invert_y=false
|
||||
process/hdr_as_srgb=false
|
||||
process/hdr_clamp_exposure=false
|
||||
process/size_limit=0
|
||||
detect_3d/compress_to=1
|
||||
112
xr/openxr_render_models/start_vr.gd
Normal file
112
xr/openxr_render_models/start_vr.gd
Normal file
@@ -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()
|
||||
1
xr/openxr_render_models/start_vr.gd.uid
Normal file
1
xr/openxr_render_models/start_vr.gd.uid
Normal file
@@ -0,0 +1 @@
|
||||
uid://bqa4r4n7b6d7s
|
||||
25
xr/openxr_render_models/wall.tscn
Normal file
25
xr/openxr_render_models/wall.tscn
Normal file
@@ -0,0 +1,25 @@
|
||||
[gd_scene load_steps=5 format=3 uid="uid://c7ohc2o1shtu7"]
|
||||
|
||||
[ext_resource type="Texture2D" uid="uid://btobyv4xjhltq" path="res://assets/pattern.png" id="1_xxgf6"]
|
||||
|
||||
[sub_resource type="BoxShape3D" id="BoxShape3D_oh6kn"]
|
||||
size = Vector3(2, 2, 0.2)
|
||||
|
||||
[sub_resource type="StandardMaterial3D" id="StandardMaterial3D_y4f30"]
|
||||
albedo_color = Color(0.76257527, 0.49292004, 0.17555861, 1)
|
||||
albedo_texture = ExtResource("1_xxgf6")
|
||||
uv1_scale = Vector3(2, 2, 2)
|
||||
|
||||
[sub_resource type="BoxMesh" id="BoxMesh_xxgf6"]
|
||||
material = SubResource("StandardMaterial3D_y4f30")
|
||||
size = Vector3(2, 2, 0.2)
|
||||
|
||||
[node name="Wall" type="StaticBody3D"]
|
||||
|
||||
[node name="CollisionShape3D" type="CollisionShape3D" parent="."]
|
||||
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1, 0)
|
||||
shape = SubResource("BoxShape3D_oh6kn")
|
||||
|
||||
[node name="MeshInstance3D" type="MeshInstance3D" parent="."]
|
||||
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1, 0)
|
||||
mesh = SubResource("BoxMesh_xxgf6")
|
||||
Reference in New Issue
Block a user