Merge pull request #119 from Nitwel/fixes

Implement new hand collision system
This commit is contained in:
Nitwel 2024-03-21 16:20:06 +01:00 committed by GitHub
commit 35efe28c19
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
13 changed files with 145 additions and 131 deletions

View File

@ -32,7 +32,7 @@ func _ready():
}
touch = Touch.new(fingers)
collide = Collide.new(hand_left, hand_right, fingers)
collide = Collide.new(hand_left, hand_right, $XRHandLeft/IndexTip/TouchArea, $XRHandRight/IndexTip/TouchArea)
add_child(touch)
add_child(collide)

View File

@ -53,7 +53,7 @@ transform = Transform3D(1, -7.45058e-09, -2.22045e-16, 7.45058e-09, 1, 0, 0, 0,
shape = SubResource("CapsuleShape3D_dopke")
[node name="ThumbTip" type="BoneAttachment3D" parent="XRHandLeft"]
transform = Transform3D(0.937246, 0.0284254, -0.347508, 0.0184905, 0.991216, 0.130949, 0.348178, -0.129157, 0.928487, 0.0498668, 0.0560917, -0.112777)
transform = Transform3D(0.937246, 0.0284254, -0.347508, 0.0184905, 0.991216, 0.130949, 0.348178, -0.129157, 0.928488, 0.0498668, 0.0560917, -0.112777)
bone_name = "Thumb_Tip_L"
bone_idx = 4
use_external_skeleton = true
@ -63,7 +63,7 @@ external_skeleton = NodePath("../left_hand/Armature_001/Skeleton3D")
gizmo_extents = 0.02
[node name="MiddleTip" type="BoneAttachment3D" parent="XRHandLeft"]
transform = Transform3D(0.0812012, -0.650531, -0.755125, 0.996576, 0.064817, 0.051326, 0.0155558, -0.756708, 0.653567, 0.032112, 0.00654224, -0.171612)
transform = Transform3D(0.0812012, -0.650531, -0.755125, 0.996577, 0.064817, 0.051326, 0.0155558, -0.756708, 0.653568, 0.032112, 0.00654224, -0.171612)
bone_name = "Middle_Tip_L"
bone_idx = 14
use_external_skeleton = true
@ -90,6 +90,7 @@ collision_mask = 8
[node name="CollisionShape3D" type="CollisionShape3D" parent="XRHandLeft/AnimatableBody3D"]
transform = Transform3D(1, 1.05818e-16, 4.75779e-13, -2.32831e-10, 1, -1.77636e-14, -4.97946e-12, 1.77636e-15, 1, -7.7486e-07, 1.33878e-09, -0.030436)
shape = SubResource("BoxShape3D_1pxrt")
disabled = true
[node name="RemoteTransform3D" type="RemoteTransform3D" parent="XRHandLeft"]
remote_path = NodePath("../AnimatableBody3D")
@ -106,7 +107,7 @@ transform = Transform3D(1, 0, 4.7579e-13, 0, 1, 0, -1.34149e-12, 1.77636e-15, 1,
material_override = SubResource("StandardMaterial3D_n27ki")
[node name="IndexTip" type="BoneAttachment3D" parent="XRHandRight"]
transform = Transform3D(0.19221, 0.669966, 0.717078, -0.091543, -0.715277, 0.69282, 0.977075, -0.19881, -0.0761527, -0.0345978, -0.164767, -0.0355401)
transform = Transform3D(0.19221, 0.669966, 0.717079, -0.091543, -0.715277, 0.69282, 0.977075, -0.19881, -0.0761527, -0.0345977, -0.164767, -0.0355401)
bone_name = "Index_Tip_R"
bone_idx = 9
use_external_skeleton = true
@ -136,7 +137,7 @@ external_skeleton = NodePath("../right_hand/Armature/Skeleton3D")
gizmo_extents = 0.02
[node name="MiddleTip" type="BoneAttachment3D" parent="XRHandRight"]
transform = Transform3D(0.0812011, 0.650531, 0.755126, -0.0155557, -0.756708, 0.653568, 0.996576, -0.0648169, -0.0513262, -0.032112, -0.171612, -0.00654216)
transform = Transform3D(0.0812011, 0.650531, 0.755126, -0.0155557, -0.756709, 0.653568, 0.996576, -0.0648169, -0.0513262, -0.032112, -0.171612, -0.00654216)
bone_name = "Middle_Tip_R"
bone_idx = 14
use_external_skeleton = true
@ -163,6 +164,7 @@ collision_mask = 8
[node name="CollisionShape3D" type="CollisionShape3D" parent="XRHandRight/AnimatableBody3D"]
transform = Transform3D(1, 0, 4.75779e-13, -2.32831e-10, 1, -1.77636e-14, -4.97946e-12, 1.77636e-15, 1, -7.7486e-07, 1.33878e-09, -0.030436)
shape = SubResource("BoxShape3D_1pxrt")
disabled = true
[node name="RemoteTransform3D" type="RemoteTransform3D" parent="XRHandRight"]
remote_path = NodePath("../AnimatableBody3D")

View File

@ -0,0 +1,18 @@
[gd_scene load_steps=2 format=3 uid="uid://cu33x58yh0mhy"]
[sub_resource type="SphereShape3D" id="SphereShape3D_65tyn"]
radius = 0.01
[node name="TipCollider" type="RigidBody3D"]
collision_layer = 4
collision_mask = 4
axis_lock_angular_x = true
axis_lock_angular_y = true
axis_lock_angular_z = true
mass = 0.01
gravity_scale = 0.0
linear_damp = 50.0
angular_damp = 50.0
[node name="CollisionShape3D" type="CollisionShape3D" parent="."]
shape = SubResource("SphereShape3D_65tyn")

View File

@ -1,18 +0,0 @@
extends Area3D
class_name TouchBody3D
@export var plane = Plane.PLANE_XZ
func _ready():
set_collision_layer_value(1, false)
set_collision_layer_value(3, true)
var collisionShape = null
for child in get_children():
if child is CollisionShape3D:
collisionShape = child
break
if collisionShape != null:
plane.d = collisionShape.shape.size.y / 2 + collisionShape.position.y

View File

@ -129,26 +129,50 @@ func _on_press_up(event):
func _on_touch_enter(event: EventTouch):
if event.target != finger_area:
return
AudioPlayer.play_effect("click")
_touch_change(event)
func _on_touch_move(event: EventTouch):
_touch_change(event)
func _on_touch_leave(_event: EventTouch):
if toggleable:
active = !active
if active:
on_button_up.emit()
else:
on_button_down.emit()
func _touch_change(event: EventTouch):
if disabled:
event.bubbling = false
return
AudioPlayer.play_effect("click")
if toggleable:
active = !active
if active:
on_button_down.emit()
else:
on_button_up.emit()
return
active = true
on_button_down.emit()
_touch_change(event)
func _on_touch_move(event: EventTouch):
if disabled:
event.bubbling = false
return
if toggleable:
return
_touch_change(event)
func _on_touch_leave(event: EventTouch):
if disabled:
event.bubbling = false
return
if toggleable:
return
active = false
on_button_up.emit()
func _touch_change(event: EventTouch):
var pos = Vector3(0, 1, 0)
for finger in event.fingers:
var finger_pos = to_local(finger.area.global_position)
@ -159,15 +183,5 @@ func _touch_change(event: EventTouch):
var button_center = 0.1
var percent = clamp((button_center + button_height / 2 - pos.y) / (button_height / 2), 0, 1)
if !active&&percent < 1:
on_button_down.emit()
elif active&&percent >= 1:
on_button_up.emit()
update_animation(percent)
if toggleable:
return
active = percent < 1

View File

@ -1,9 +1,8 @@
[gd_scene load_steps=8 format=3 uid="uid://bsjqdvkt0u87c"]
[gd_scene load_steps=7 format=3 uid="uid://bsjqdvkt0u87c"]
[ext_resource type="Script" path="res://content/ui/components/button/button.gd" id="1_74x7g"]
[ext_resource type="ArrayMesh" uid="uid://iv4lk77axlk4" path="res://assets/immersive_home/button.obj" id="2_cve3l"]
[ext_resource type="Material" uid="uid://bujy3egn1oqac" path="res://assets/materials/pri-500.material" id="2_wx7av"]
[ext_resource type="Script" path="res://content/system/hands/touch_area.gd" id="4_b27lx"]
[sub_resource type="BoxShape3D" id="BoxShape3D_xwopm"]
size = Vector3(0.05, 0.02, 0.05)
@ -11,8 +10,8 @@ size = Vector3(0.05, 0.02, 0.05)
[sub_resource type="BoxShape3D" id="BoxShape3D_bqjii"]
size = Vector3(0.0501598, 0.0390937, 0.0501598)
[sub_resource type="BoxShape3D" id="BoxShape3D_dfbn3"]
size = Vector3(0.05, 0.029126, 0.05)
[sub_resource type="BoxShape3D" id="BoxShape3D_vkbuh"]
size = Vector3(0.05, 0.03, 0.05)
[node name="Button" type="Node3D" groups=["ui_focus"]]
script = ExtResource("1_74x7g")
@ -51,9 +50,10 @@ monitoring = false
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, -0.00975001, 0)
shape = SubResource("BoxShape3D_bqjii")
[node name="TouchBody3D" type="Area3D" parent="."]
script = ExtResource("4_b27lx")
[node name="TouchBody" type="StaticBody3D" parent="."]
collision_layer = 4
collision_mask = 0
[node name="CollisionShape3D" type="CollisionShape3D" parent="TouchBody3D"]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, -0.00453955, 0)
shape = SubResource("BoxShape3D_dfbn3")
[node name="CollisionShape3D" type="CollisionShape3D" parent="TouchBody"]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, -0.005, 0)
shape = SubResource("BoxShape3D_vkbuh")

View File

@ -6,11 +6,11 @@
[sub_resource type="BoxMesh" id="BoxMesh_kjbca"]
resource_local_to_scene = true
size = Vector3(0.2, 0.006, 0.03)
size = Vector3(0.15, 0.006, 0.03)
[sub_resource type="BoxShape3D" id="BoxShape3D_x4yp8"]
resource_local_to_scene = true
size = Vector3(0.2, 0.006, 0.03)
size = Vector3(0.15, 0.006, 0.03)
[sub_resource type="BoxMesh" id="BoxMesh_2736g"]
size = Vector3(0.001, 0.02, 0.001)
@ -53,7 +53,7 @@ _data = {
}
[node name="Input" type="StaticBody3D" groups=["ui_focus"]]
collision_layer = 2
collision_layer = 6
collision_mask = 0
script = ExtResource("1_uml3t")
text = "Example"
@ -68,7 +68,7 @@ transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0.003, 0)
shape = SubResource("BoxShape3D_x4yp8")
[node name="Label" type="Label3D" parent="."]
transform = Transform3D(1, 0, 0, 0, -4.37114e-08, 1, 0, -1, -4.37114e-08, -0.098, 0.00618291, 0)
transform = Transform3D(1, 0, 0, 0, -4.37114e-08, 1, 0, -1, -4.37114e-08, -0.073, 0.00618291, 0)
pixel_size = 0.001
text = "Example"
font = ExtResource("3_ij5fh")

View File

@ -161,6 +161,8 @@ _data = {
script = ExtResource("1_yw3yb")
[node name="AnimationNode" type="StaticBody3D" parent="."]
collision_layer = 6
collision_mask = 0
[node name="MeshInstance3D" type="MeshInstance3D" parent="AnimationNode"]
material_override = ExtResource("2_5b8oo")
@ -172,7 +174,6 @@ shape = SubResource("BoxShape3D_m4d21")
[node name="Text" type="Label3D" parent="AnimationNode"]
transform = Transform3D(1, 0, 0, 0, -4.37114e-08, 1, 0, -1, -4.37114e-08, -0.08, 0.006, 0)
pixel_size = 0.001
text = "Example Text"
font_size = 10
outline_size = 0
horizontal_alignment = 0
@ -182,7 +183,7 @@ width = 190.0
[node name="Icon" type="Label3D" parent="AnimationNode"]
transform = Transform3D(1, 0, 0, 0, -4.37114e-08, 1, 0, -1, -4.37114e-08, -0.1, 0.006, 0)
pixel_size = 0.001
text = "check_circle"
text = "info"
font = ExtResource("3_1ljpc")
font_size = 24
outline_size = 0

View File

@ -65,6 +65,8 @@ transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, -0.00353538, 0)
mesh = SubResource("CylinderMesh_v34nn")
[node name="CollisionBody" type="StaticBody3D" parent="."]
collision_layer = 6
collision_mask = 6
[node name="CollisionShape3D" type="CollisionShape3D" parent="CollisionBody"]
shape = SubResource("BoxShape3D_h1mn1")
@ -73,7 +75,7 @@ shape = SubResource("BoxShape3D_h1mn1")
transform = Transform3D(1, 0, 0, 0, -4.37114e-08, 1, 0, -1, -4.37114e-08, 0.105, 0, 0)
visible = false
pixel_size = 0.001
text = "0.2"
text = "0.2 "
font_size = 10
outline_size = 4
horizontal_alignment = 0

View File

@ -1,9 +1,8 @@
[gd_scene load_steps=21 format=3 uid="uid://c3kdssrmv84kv"]
[gd_scene load_steps=19 format=3 uid="uid://c3kdssrmv84kv"]
[ext_resource type="Script" path="res://content/ui/menu/menu.gd" id="1_ng4u3"]
[ext_resource type="Material" uid="uid://bnwimm214q67g" path="res://assets/materials/sec-500.material" id="2_0x5at"]
[ext_resource type="Script" path="res://content/functions/movable.gd" id="2_8coxu"]
[ext_resource type="Script" path="res://content/system/hands/touch_area.gd" id="2_fxtnc"]
[ext_resource type="Script" path="res://content/ui/components/tabs/tabs.gd" id="4_eavfx"]
[ext_resource type="PackedScene" uid="uid://crrb0l3ekuotj" path="res://content/ui/menu/edit/edit_menu.tscn" id="4_r2raj"]
[ext_resource type="PackedScene" uid="uid://bsjqdvkt0u87c" path="res://content/ui/components/button/button.tscn" id="5_w4i01"]
@ -13,21 +12,18 @@
[ext_resource type="PackedScene" uid="uid://c01gkeldvjwtr" path="res://content/ui/menu/room/room_menu.tscn" id="10_u4i1x"]
[ext_resource type="PackedScene" uid="uid://c6r4higceibif" path="res://content/ui/menu/settings/settings_menu.tscn" id="11_7wm6b"]
[sub_resource type="BoxShape3D" id="BoxShape3D_fgcdq"]
size = Vector3(0.38, 0.0634595, 0.32)
[sub_resource type="BoxShape3D" id="BoxShape3D_e1esh"]
size = Vector3(0.38, 0.0128076, 0.32)
[sub_resource type="BoxShape3D" id="BoxShape3D_6xn1i"]
size = Vector3(0.3, 0.0264844, 0.3)
[sub_resource type="StandardMaterial3D" id="StandardMaterial3D_ti5t2"]
[sub_resource type="BoxMesh" id="BoxMesh_08du6"]
material = SubResource("StandardMaterial3D_ti5t2")
size = Vector3(0.3, 0.01, 0.3)
[sub_resource type="ConvexPolygonShape3D" id="ConvexPolygonShape3D_mgnm0"]
points = PackedVector3Array(-0.15, -0.005, -0.15, -0.15, 0.005, -0.15, 0.15, -0.005, -0.15, -0.15, -0.005, 0.15, -0.15, 0.005, 0.15, 0.15, 0.005, -0.15, 0.15, -0.005, 0.15, 0.15, 0.005, 0.15)
[sub_resource type="Animation" id="Animation_61md4"]
length = 0.001
tracks/0/type = "bezier"
@ -166,17 +162,10 @@ _data = {
}
[node name="Menu" type="StaticBody3D"]
collision_layer = 2
collision_mask = 2
script = ExtResource("1_ng4u3")
[node name="TouchBody3D" type="Area3D" parent="."]
collision_layer = 4
collision_mask = 0
script = ExtResource("2_fxtnc")
[node name="CollisionShape3D" type="CollisionShape3D" parent="TouchBody3D"]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -0.02, -0.0282703, 2.98023e-08)
shape = SubResource("BoxShape3D_fgcdq")
[node name="CollisionShape3D" type="CollisionShape3D" parent="."]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -0.02, -0.00286309, 1.49012e-08)
shape = SubResource("BoxShape3D_e1esh")
@ -186,6 +175,12 @@ script = ExtResource("2_8coxu")
[node name="AnimationContainer" type="StaticBody3D" parent="."]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -0.2, 0, -0.15)
collision_layer = 6
collision_mask = 6
[node name="CollisionShape3D" type="CollisionShape3D" parent="AnimationContainer"]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0.21, -0.00824219, 0.15)
shape = SubResource("BoxShape3D_6xn1i")
[node name="Background" type="MeshInstance3D" parent="AnimationContainer"]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0.21, 0, 0.15)
@ -193,10 +188,6 @@ material_override = ExtResource("2_0x5at")
mesh = SubResource("BoxMesh_08du6")
skeleton = NodePath("../..")
[node name="CollisionShape3D" type="CollisionShape3D" parent="AnimationContainer"]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0.21, 0, 0.15)
shape = SubResource("ConvexPolygonShape3D_mgnm0")
[node name="Tabs" type="Node3D" parent="AnimationContainer" node_paths=PackedStringArray("initial_selected")]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0.06, 0, 0)
script = ExtResource("4_eavfx")

View File

@ -11,6 +11,8 @@ size = Vector3(0.5, 0.3, 0.01)
size = Vector3(0.5, 0.3, 0.01)
[node name="Onboarding" type="StaticBody3D"]
collision_layer = 6
collision_mask = 6
script = ExtResource("1_k4yvw")
[node name="Label3D2" type="Label3D" parent="."]

View File

@ -2,64 +2,58 @@ extends Node3D
## Calculates collision for fingers and FingerAreas
const Finger = preload ("res://lib/utils/touch/finger.gd")
const TipCollider = preload ("res://content/system/hands/tip_collider.tscn")
## Record<Finger.Type, Area3D>
var finger_areas: Dictionary
var tip_right: Node3D
var tip_left: Node3D
var tip_left_body: RigidBody3D
var tip_right_body: RigidBody3D
## Record<TouchBody3D, Array<Finger.Type>>
var bodies_entered = {}
var hand_left: Node3D
var hand_right: Node3D
var hand_left_mesh: MeshInstance3D
var hand_right_mesh: MeshInstance3D
func _init(hand_left: OpenXRHand, hand_right: OpenXRHand, finger_areas: Dictionary):
self.finger_areas = finger_areas
self.hand_left = hand_left.get_node("left_hand/Armature_001/Skeleton3D/vr_glove_left_slim")
self.hand_right = hand_right.get_node("right_hand/Armature/Skeleton3D/vr_glove_right_slim")
func _init(hand_left: OpenXRHand, hand_right: OpenXRHand, tip_left: Node3D, tip_right: Node3D):
self.tip_right = tip_right
self.tip_left = tip_left
self.hand_left = hand_left
self.hand_right = hand_right
self.hand_left_mesh = hand_left.get_node("left_hand/Armature_001/Skeleton3D/vr_glove_left_slim")
self.hand_right_mesh = hand_right.get_node("right_hand/Armature/Skeleton3D/vr_glove_right_slim")
func _ready():
for finger_type in finger_areas.keys():
var body_container = Node3D.new()
body_container.name = "HandBodyContainer"
finger_areas[finger_type].area_entered.connect(func(body):
if body is TouchBody3D:
_on_body_entered(finger_type, body)
)
get_node("/root/Main/").add_child.call_deferred(body_container)
finger_areas[finger_type].area_exited.connect(func(body):
if body is TouchBody3D:
_on_body_exited(finger_type, body)
)
tip_right_body = TipCollider.instantiate()
tip_right_body.global_position = tip_right.global_position
body_container.add_child(tip_right_body)
tip_left_body = TipCollider.instantiate()
tip_left_body.global_position = tip_left.global_position
body_container.add_child(tip_left_body)
func _physics_process(_delta):
hand_left.position = Vector3.ZERO
hand_right.position = Vector3.ZERO
_move_tip_rigidbody_to_bone(tip_left_body, tip_left)
_move_tip_rigidbody_to_bone(tip_right_body, tip_right)
for body in bodies_entered.keys():
var fingers = bodies_entered[body]
func _move_tip_rigidbody_to_bone(tip_rigidbody: RigidBody3D, tip_bone: Node3D):
if tip_rigidbody.is_inside_tree() == false:
return
for finger in fingers:
if finger == Finger.Type.INDEX_LEFT:
var start_pos = finger_areas[finger].get_parent().global_position
var end_pos = body.to_global(body.plane.project(body.to_local(start_pos)))
var move_delta: Vector3 = tip_bone.global_position - tip_rigidbody.global_position
hand_left.global_position = end_pos + (hand_left.global_position - start_pos)
hand_right_mesh.global_position = hand_right.global_position - move_delta
elif finger == Finger.Type.INDEX_RIGHT:
var start_pos = finger_areas[finger].get_parent().global_position
var end_pos = body.to_global(body.plane.project(body.to_local(start_pos)))
# Snap back the rigidbody if it's too far away.
if move_delta.length() > 0.1:
tip_rigidbody.global_position = tip_bone.global_position
return
hand_right.global_position = end_pos + (hand_right.global_position - start_pos)
func _on_body_entered(finger_type, body):
if bodies_entered.has(body):
if !bodies_entered[body].has(finger_type):
bodies_entered[body].append(finger_type)
else:
bodies_entered[body] = [finger_type]
func _on_body_exited(finger_type, body):
if bodies_entered.has(body):
if bodies_entered[body].has(finger_type):
bodies_entered[body].erase(finger_type)
if bodies_entered[body].size() == 0:
bodies_entered.erase(body)
var coef_force = 30.0
tip_rigidbody.apply_central_force(move_delta * coef_force)
tip_rigidbody.global_transform.basis = hand_right.global_transform.basis

View File

@ -69,4 +69,12 @@ root
Static code reference can be found in the Reference section of the documentation at the top right. It is exported from Godot and contains all available scripts from the `/lib` folder.
The documentation is written in Markdown and can be found in the `docs` folder of the repository.
The documentation is written in Markdown and can be found in the `docs` folder of the repository.
### Physics layers
1. **Entitites**: Used for interaction with entities in the room.
2. **Interface**: Used for interaction with the UI.
3. **Touch**: Used for touch based interactions.
4. **Physics**: Used for physics interactions.
5. **Room**: Used for interaction with the room.