Fix grab rotaiton issues
This commit is contained in:
@ -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
|
||||
|
||||
@ -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()
|
||||
|
||||
|
||||
Reference in New Issue
Block a user