fsabre
July 20, 2024, 5:33pm
1
Godot Version
V4.2.2

Question
Why doesn’t my Basis.slerp() take the closest path ?

To demonstrate, I made a example scene with a node that rotates from the back to the top. A rod is there to show the precise movement.

The code of the Sphere node is :

```
extends MeshInstance3D
var timer = 0
var top = true
var goal_basis: Basis
@onready var rot: Node3D = $RotatingNode
func _process(delta: float) -> void:
timer -= delta
if timer <= 0:
timer = 3
if top:
top = false
print("Facing back")
goal_basis = Basis.looking_at(Vector3.BACK)
else:
top = true
print("Facing top")
goal_basis = Basis.looking_at(Vector3.UP, Vector3.LEFT) # Specify an "up" vector different than the direction
print(goal_basis)
rot.basis = Basis(rot.basis.slerp(goal_basis, 0.02))
```

I can’t upload videos, so here’s some screenshots.

For the record, I also tried to use Quaternions, as by the doc :

For practical use, it’s enough to understand that pretty much their main use is doing a closest path interpolation.

To no avail : it behaved the same as the current scene. I used `get_rotation_quaternion()`

on every basis to get those.

What happens if you use your timer as the weight?

```
var top_basis := Basis.looking_at(Vector3.UP, Vector3.LEFT)
var back_basis := Basis.looking_at(Vector3.BACK)
var clamped_timer := clampf(timer, 0, 1)
rot.basis = back_basis.slerp(top_basis, clamped_timer)
```

fsabre
July 20, 2024, 6:45pm
3
I edited my function to try that.

```
func _process(delta: float) -> void:
timer -= delta
if timer <= 0:
timer = 1
if top:
top = false
print("Facing back")
goal_basis = Basis.looking_at(Vector3.BACK)
else:
top = true
print("Facing top")
goal_basis = Basis.looking_at(Vector3.UP, Vector3.LEFT) # Specify an "up" vector different than the direction
print(goal_basis)
#rot.basis = Basis(rot.basis.slerp(goal_basis, 0.02))
var clamped_timer: float = 1 - clampf(timer, 0, 1)
rot.basis = rot.basis.slerp(goal_basis, clamped_timer)
```

But as expected, it only changes the timing of the movement : it becomes linear.

one key difference I should’ve pointed out is not using `rot.basis.slerp`

I used `back_basis.slerp`

.

Using lerp/slerp on a shifting starting point might cause issues.

fsabre
July 20, 2024, 7:28pm
5
Ohh, nice point. But I get the same result with :

```
@onready var rot: Node3D = $RotatingNode
var previous_basis: Basis
var goal_basis: Basis
func _process(delta: float) -> void:
timer -= delta
if timer <= 0:
timer = 1
if top:
top = false
print("Facing back")
previous_basis = rot.basis
goal_basis = Basis.looking_at(Vector3.BACK)
else:
top = true
print("Facing top")
previous_basis = rot.basis
goal_basis = Basis.looking_at(Vector3.UP, Vector3.LEFT) # Specify an "up" vector different than the direction
print(goal_basis)
#rot.basis = Basis(rot.basis.slerp(goal_basis, 0.02))
var clamped_timer: float = 1 - clampf(timer, 0, 1)
rot.basis = previous_basis.slerp(goal_basis, clamped_timer)
```

Huh, maybe it has to do with the `look_at`

possibly rotating to face a different way that we can’t tell with the cylinders.

See if changing this line from `Vector3.LEFT`

to `RIGHT`

, `FORWARD`

, or `BACK`

results in a different rotation

`var top_basis := Basis.looking_at(Vector3.UP, Vector3.LEFT)`

1 Like

fsabre
July 20, 2024, 7:57pm
7
```
goal_basis = Basis.looking_at(Vector3.UP, Vector3.RIGHT)
```

This makes the curve at the left side of the ball, while it was at the right side before.

```
goal_basis = Basis.looking_at(Vector3.UP, Vector3.FORWARD)
```

This makes the movement perfect, exactly as wanted.

```
goal_basis = Basis.looking_at(Vector3.UP, Vector3.BACK)
```

This makes an even more exaggerated curve on the left.

How can I interpret that ?
Later, those target basis will be completely dynamic, so I have to find an explanation to have a consistant behavior.

Remember you are also rotating the UP vector. Add another cylinder to represent that up axis, it should be more clear with that visual aid

1 Like

fsabre
July 20, 2024, 8:35pm
9
Thank you for your help ! It’s more clear now.

I still want to choose the direction of my `up`

vector, without it affecting the main rotation.
But I think I can manage it with several layers of rotation in children.