Fix grab rotaiton issues

This commit is contained in:
2025-11-01 18:30:17 +01:00
parent 14b24beb23
commit 820da83397
2 changed files with 22 additions and 9 deletions

View File

@ -144,7 +144,7 @@ func _orient_pawn(delta: float):
# 2. Smoothly Interpolate Towards Target Basis
var current_basis = pawn.global_basis
var new_basis = current_basis.slerp(target_basis, delta * orientation_speed)
var new_basis = current_basis.slerp(target_basis, delta * orientation_speed).orthonormalized()
# Store the body's yaw *before* applying the new basis
var _old_body_yaw = current_basis.get_euler().y

View File

@ -299,15 +299,23 @@ func _attempt_grip(target_grip: GripArea3D) -> bool:
# --- Grip Orientation Helper ---
func _choose_grip_orientation(grip_basis: Basis) -> Basis:
var grip_up_vector = grip_basis.y.normalized()
var grip_down_vector = -grip_basis.y.normalized()
var pawn_up_vector = pawn.global_transform.basis.y
# 1. Define the two possible target orientations based on the grip.
# Both will look away from the grip's surface (-Z).
var look_at_dir = -grip_basis.z.normalized()
var target_basis_up = Basis.looking_at(look_at_dir, grip_basis.y.normalized()).orthonormalized()
var target_basis_down = Basis.looking_at(look_at_dir, -grip_basis.y.normalized()).orthonormalized()
var dot_up = pawn_up_vector.dot(grip_up_vector)
var dot_down = pawn_up_vector.dot(grip_down_vector)
var chosen_orientation_up_vector = grip_up_vector if dot_up >= dot_down else grip_down_vector
return Basis.looking_at(-grip_basis.z.normalized(), chosen_orientation_up_vector).orthonormalized()
# 2. Get the pawn's current orientation.
var current_basis = pawn.global_basis
# 3. Compare which target orientation is "closer" to the current one.
# We can do this by finding the angle of rotation needed to get from current to each target.
# The quaternion dot product is related to the angle between orientations. A larger absolute dot product means a smaller angle.
var dot_up = current_basis.get_rotation_quaternion().dot(target_basis_up.get_rotation_quaternion())
var dot_down = current_basis.get_rotation_quaternion().dot(target_basis_down.get_rotation_quaternion())
# We choose the basis that results in a larger absolute dot product (smaller rotational distance).
return target_basis_up if abs(dot_up) >= abs(dot_down) else target_basis_down
# --- Grip Selection Logic ---
# Finds the best grip based on direction, distance, and angle constraints
@ -413,6 +421,11 @@ func _apply_orientation_torque(target_basis: Basis, delta: float):
var current_quat = pawn.global_transform.basis.get_rotation_quaternion()
var target_quat = target_basis.get_rotation_quaternion()
var error_quat = target_quat * current_quat.inverse()
# Ensure we take the shortest path for rotation. If W is negative, the
# quaternion represents the "long way around". Negating it gives the same
# orientation but via the shorter rotational path.
if error_quat.w < 0: error_quat = -error_quat
var error_angle = error_quat.get_angle()
var error_axis = error_quat.get_axis()