Skip to content

Commit

Permalink
Added logic to properly handle movement and teleport impact on collis…
Browse files Browse the repository at this point in the history
…ion hands
  • Loading branch information
BastiaanOlij committed Dec 5, 2024
1 parent 4b40a7b commit b5f2fb8
Show file tree
Hide file tree
Showing 12 changed files with 159 additions and 40 deletions.
40 changes: 39 additions & 1 deletion addons/godot-xr-tools/hands/collision_hand.gd
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ const TELEPORT_DISTANCE := 1.0

## Force we exert on a picked up object when hand is at maximum distance
## before letting go.
@export_range(1.0, 1000.0, 0.1, "suffix:N") var max_pickup_force : float = 400.0
@export_range(1.0, 1000.0, 0.1, "suffix:N") var max_pickup_force : float = 300.0


# Controller to target (if no target overrides)
Expand Down Expand Up @@ -168,6 +168,12 @@ func _ready():
process_physics_priority = -90
sync_to_physics = false

# Connect to player body signals (if applicable)
var player_body = XRToolsPlayerBody.find_instance(self)
if player_body:
player_body.player_moved.connect(_on_player_moved)
player_body.player_teleported.connect(_on_player_teleported)

# Populate nodes
_controller = XRTools.find_xr_ancestor(self, "*", "XRController3D")

Expand Down Expand Up @@ -262,12 +268,14 @@ func _move_to_target(delta):

# Handle too far from target
if global_position.distance_to(_target.global_position) > TELEPORT_DISTANCE:
print("max distance reached")
max_distance_reached.emit()

global_transform = _target.global_transform
return

# Orient the hand
# TODO: should check for collisions along this rotation
global_transform.basis = _target.global_transform.basis

# Adjust target position if we're holding something
Expand Down Expand Up @@ -307,6 +315,36 @@ func _move_to_target(delta):
force_update_transform()


# If our player moved, attempt to move our hand but ignoring weight.
func _on_player_moved(delta_transform : Transform3D):
if mode == CollisionHandMode.DISABLED:
return

if mode == CollisionHandMode.TELEPORT:
_on_player_teleported(delta_transform)
return

var target : Transform3D = delta_transform * global_transform

# Rotate
# TODO: should check for collisions along this rotation
global_basis = target.basis

# And attempt to move
move_and_slide(target.origin - global_position)

force_update_transform()


# If our player teleported, just move.
func _on_player_teleported(delta_transform : Transform3D):
if mode == CollisionHandMode.DISABLED:
return

global_transform = delta_transform * global_transform
force_update_transform()


# This function inserts a target override into the overrides list by priority
# order.
func _insert_target_override(target : Node3D, priority : int) -> void:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

[node name="XRToolsCollisionHand" type="AnimatableBody3D"]
collision_layer = 131072
collision_mask = 327711
collision_mask = 262175
sync_to_physics = false
script = ExtResource("1_vdcct")
max_pickup_force = 400.0
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@

[node name="CollisionHandLeft" type="AnimatableBody3D"]
collision_layer = 131072
collision_mask = 327711
collision_mask = 262175
sync_to_physics = false
script = ExtResource("1_t5acd")

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@

[node name="CollisionHandRight" type="AnimatableBody3D"]
collision_layer = 131072
collision_mask = 327711
collision_mask = 262175
sync_to_physics = false
script = ExtResource("1_so3hf")

Expand Down
25 changes: 21 additions & 4 deletions addons/godot-xr-tools/player/player_body.gd
Original file line number Diff line number Diff line change
Expand Up @@ -24,11 +24,14 @@ extends CharacterBody3D
signal player_jumped()

## Signal emitted when the player teleports
signal player_teleported()
signal player_teleported(delta_transform)

## Signal emitted when the player bounces
signal player_bounced(collider, magnitude)

## Signal emitted when the player has moved (excluding teleport)
## This only captures movement handled by the player body logic.
signal player_moved(delta_transform)

## Enumeration indicating when ground control can be used
enum GroundControl {
Expand Down Expand Up @@ -262,6 +265,9 @@ func _physics_process(delta: float):
set_physics_process(false)
return

# Remember where we are now
var current_transform : Transform3D = global_transform

# Calculate the players "up" direction and plane
up_player = origin_node.global_transform.basis.y

Expand Down Expand Up @@ -325,11 +331,18 @@ func _physics_process(delta: float):
# Orient the player towards (potentially modified) gravity
slew_up(-gravity.normalized(), 5.0 * delta)

# If we moved our player, emit signal
var delta_transform : Transform3D = global_transform * current_transform.inverse()
if delta_transform.origin.length() > 0.001:
player_moved.emit(delta_transform)

## Teleport the player body
## Teleport the player body.
## This moves the player without checking for collisions.
func teleport(target : Transform3D) -> void:
var inv_global_transform : Transform3D = global_transform.inverse()

# Get the player-to-origin transform
var player_to_origin = global_transform.inverse() * origin_node.global_transform
var player_to_origin : Transform3D = inv_global_transform * origin_node.global_transform

# Set the player
global_transform = target
Expand All @@ -338,7 +351,7 @@ func teleport(target : Transform3D) -> void:
origin_node.global_transform = target * player_to_origin

# Report the player teleported
player_teleported.emit()
player_teleported.emit(target * inv_global_transform)


## Request a jump
Expand Down Expand Up @@ -410,6 +423,8 @@ func move_body(p_velocity: Vector3) -> Vector3:

## This method rotates the player by rotating the [XROrigin3D] around the camera.
func rotate_player(angle: float):
var inv_global_transform : Transform3D = global_transform.inverse()

var t1 := Transform3D()
var t2 := Transform3D()
var rot := Transform3D()
Expand All @@ -419,6 +434,8 @@ func rotate_player(angle: float):
rot = rot.rotated(Vector3.DOWN, angle)
origin_node.transform = (origin_node.transform * t2 * rot * t1).orthonormalized()

player_moved.emit(global_transform * inv_global_transform)

## This method slews the players up vector by rotating the [ARVROrigin] around
## the players feet.
func slew_up(up: Vector3, slew: float) -> void:
Expand Down
31 changes: 31 additions & 0 deletions addons/godot-xr-tools/player/poke/poke_body.gd
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,18 @@ func is_xr_class(name : String) -> bool:
return name == "XRToolsPokeBody" or super(name)


func _ready():
# Do not initialise if in the editor
if Engine.is_editor_hint():
return

# Connect to player body signals (if applicable)
var player_body = XRToolsPlayerBody.find_instance(self)
if player_body:
player_body.player_moved.connect(_on_player_moved)
player_body.player_teleported.connect(_on_player_teleported)


# Try moving to the parent Poke node
func _physics_process(_delta):
# Do not process if in the editor
Expand Down Expand Up @@ -52,3 +64,22 @@ func _physics_process(_delta):
# Report when we start touching a new object
if _contact and _contact != old_contact:
body_contact_start.emit(_contact)


# If our player moved, attempt to move our hand but ignoring weight.
func _on_player_moved(delta_transform : Transform3D):
var target : Transform3D = delta_transform * global_transform

# Rotate
global_basis = target.basis

# And attempt to move (we'll detect contact change in physics process.
move_and_slide(target.origin - global_position)

force_update_transform()


# If our player teleported, just move.
func _on_player_teleported(delta_transform : Transform3D):
global_transform = delta_transform * global_transform
force_update_transform()
5 changes: 1 addition & 4 deletions assets/3dmodelscc0/models/scenes/sniper_rifle.tscn
Original file line number Diff line number Diff line change
Expand Up @@ -112,7 +112,7 @@ radius = 0.001

[node name="SniperRifle" instance=ExtResource("1_lpv7q")]
collision_mask = 7
mass = 4.0
mass = 10.0
script = ExtResource("2_bdnea")
second_hand_grab = 2

Expand Down Expand Up @@ -176,12 +176,10 @@ value = Vector3(0, 0, 75)

[node name="GrabPointHandleLeft" parent="sniper_rifle/FirearmSlide/SliderBody/Bolt" index="0" instance=ExtResource("2_x4cgt")]
transform = Transform3D(-4.37114e-08, -1, 0, 1, -4.37114e-08, 0, 0, 0, 1, 0, -0.0359677, -0.0150545)
visible = true
hand_pose = SubResource("Resource_aoud0")

[node name="GrabPointHandleRight" parent="sniper_rifle/FirearmSlide/SliderBody/Bolt" index="1" instance=ExtResource("5_sjb82")]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, -0.0149273)
visible = true
hand_pose = SubResource("Resource_gyywm")

[node name="HandleOrigin" type="Node3D" parent="sniper_rifle/FirearmSlide" index="1"]
Expand Down Expand Up @@ -224,7 +222,6 @@ hand_pose = SubResource("Resource_kscym")

[node name="GrabPointForestockLeft" parent="." index="6" instance=ExtResource("2_x4cgt")]
transform = Transform3D(-2.50718e-08, -0.573576, -0.819152, 0.965926, 0.212012, -0.148453, 0.258819, -0.79124, 0.554032, 0.0292044, 0.0294211, -0.107)
visible = true
hand_pose = SubResource("Resource_tbrsh")
drive_position = 0.0
drive_angle = 0.0
Expand Down
2 changes: 1 addition & 1 deletion scenes/climbing_gliding_demo/materials/ghost_hand.tres
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[gd_resource type="StandardMaterial3D" load_steps=2 format=3 uid="uid://cf6y1af3ouutt"]

[ext_resource type="Material" path="res://addons/godot-xr-tools/hands/materials/glove_caucasian_green_camo.tres" id="1_3o4sh"]
[ext_resource type="Material" uid="uid://f2uhcqq8s2jx" path="res://addons/godot-xr-tools/hands/materials/glove_caucasian_green_camo.tres" id="1_3o4sh"]

[resource]
render_priority = -1
Expand Down
15 changes: 15 additions & 0 deletions scenes/demo_scene_base.gd
Original file line number Diff line number Diff line change
@@ -1,6 +1,11 @@
class_name DemoSceneBase
extends XRToolsSceneBase

@onready var left_collision_hand : XRToolsCollisionHand = $XROrigin3D/LeftHand/XRToolsCollisionHand
@onready var left_ghost_hand : XRToolsHand = $XROrigin3D/LeftHand/GhostHand
@onready var right_collision_hand : XRToolsCollisionHand = $XROrigin3D/RightHand/XRToolsCollisionHand
@onready var right_ghost_hand : XRToolsHand = $XROrigin3D/RightHand/GhostHand

func _ready():
super()

Expand All @@ -25,3 +30,13 @@ func _on_webxr_primary_changed(webxr_primary: int) -> void:
f.input_action = action_name
if "rotation_action" in f:
f.rotation_action = action_name

func _process(_delta):
# Show our ghost hands when when our collision hands aren't where our hands are...
if left_collision_hand and left_ghost_hand:
var offset = left_collision_hand.global_position - left_ghost_hand.global_position
left_ghost_hand.visible = offset.length() > 0.01

if right_collision_hand and right_ghost_hand:
var offset = right_collision_hand.global_position - right_ghost_hand.global_position
right_ghost_hand.visible = offset.length() > 0.01
7 changes: 7 additions & 0 deletions scenes/pickable_demo/materials/ghost_hands.tres
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
[gd_resource type="StandardMaterial3D" format=3 uid="uid://c5jkrtp4eipf4"]

[resource]
transparency = 1
no_depth_test = true
shading_mode = 0
albedo_color = Color(0, 1, 1, 0.25098)
1 change: 1 addition & 0 deletions scenes/pickable_demo/objects/grab_ball.tscn
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ albedo_color = Color(1, 1, 0, 1)

[node name="GrabBall" instance=ExtResource("1")]
collision_mask = 720903
mass = 10.0
physics_material_override = SubResource("PhysicsMaterial_bv5s3")
ranged_grab_method = 2
second_hand_grab = 2
Expand Down
Loading

0 comments on commit b5f2fb8

Please sign in to comment.