# How to solve rotation problems when looking up or down 90 degrees?

4.1.1

### Question

When I rotate an object so that it looks straight up or down on the x axis the left right rotation on the y axis becomes a tilt rotation on the z axis. I am unsure if this is a gimbal lock or something else. Switching to use quaternions has also not fixed the issue either. Code below. (\$Inner is a sub node of the parent node)

``````extends Node3D

func _process(delta):

var mouse_speed = _get_mouse_speed()

var current_qat = Quaternion(global_transform.basis)
var a = (mouse_speed.x * 0.01)
var y = sin( a / 2.0 )
var w = cos( a / 2.0 )
var new_ang = Quaternion(0, y, 0, w).normalized()
current_qat = current_qat * new_ang
global_transform.basis = Basis(current_qat)
var current_qat2 = Quaternion(\$Inner.global_transform.basis)
var a2 = (mouse_speed.y * 0.01)
var x2  = sin( a2 / 2.0 )
var w2 = cos( a2 / 2.0 )
var new_ang2 = Quaternion(x2, 0, 0, w2).normalized()
current_qat2 = current_qat2 * new_ang2
\$Inner.global_transform.basis = Basis(current_qat2)

self.orthonormalize()

func _get_mouse_speed() -> Vector2:
var screen_center = get_viewport().size * 0.5
var displacement = screen_center - get_viewport().get_mouse_position()
displacement.x /= screen_center.x
displacement.y /= screen_center.y
return displacement
``````

I was able to fix the problem by changing \$Inner.global_transform.basis to just global_transform.basis. However now I have some unintended rolling around the z axis.

``````#Removing \$Inner from the above code fixes the problem but introduces unintended z roll.
var current_qat = Quaternion(global_transform.basis)
var a = (mouse_speed.x * 0.01)
var y = sin( a / 2.0 )
var w = cos( a / 2.0 )
var new_ang = Quaternion(0, y, 0, w).normalized()
current_qat = current_qat * new_ang
global_transform.basis = Basis(current_qat)
var current_qat2 = Quaternion(global_transform.basis)
var a2 = (mouse_speed.y * 0.01)
var x2  = sin( a2 / 2.0 )
var w2 = cos( a2 / 2.0 )
var new_ang2 = Quaternion(x2, 0, 0, w2).normalized()
current_qat2 = current_qat2 * new_ang2
global_transform.basis = Basis(current_qat2)
``````

Is there something wrong with `Node3D.rotate(axis,angle)`?

Yes. Same problem occurs using the below code for rotation when looking straight up or straight down 90 degrees. I also tried rotate_object_local and rotation_degrees.

``````self.rotate(Vector3(0,1,0),(mouse_speed.x * 70 * 0.0001))
\$Inner.rotate(Vector3(1,0,0),(mouse_speed.y * 70 * 0.0001))
``````

Rotate only the parent. The child will rotate around the parent automatically.

Sorry, I didn’t pick up on what you were trying to accomplish with the second rotation (I’m multitasking). Disregard what I said above.

I was able to get a more readable version of my above code that still suffers from the same problem, incorrect rotation when looking up/down 90 degrees which changes to incorrect z rolling when removing \$Inner.

``````# Calculate rotation for self
var yaw = mouse_speed.x * 0.01
var yaw_quat = Quaternion(Vector3(0, 1, 0), yaw)

var current_qat = Quaternion(global_transform.basis)
current_qat = current_qat * yaw_quat
global_transform.basis = Basis(current_qat)

# Calculate rotation for \$Inner object
var pitch = mouse_speed.y * 0.01
var pitch_quat = Quaternion(Vector3(1, 0, 0), pitch)

var current_qat2 = Quaternion(\$Inner.global_transform.basis)
current_qat2 =  current_qat2 * pitch_quat
\$Inner.global_transform.basis = Basis(current_qat2)
``````