Manually rotate KinematicBody's local UP-axis toward World's UP-axis ?

:information_source: Attention Topic was automatically imported from the old Question2Answer platform.
:bust_in_silhouette: Asked By Ole

My object can have any(unknown) rotation in the world.

I need to interpolate this object’s local UP-axis, towards the World’s UP-axis, without touching the object’s other local rotations.

Anyway, all I seem to manage, is interpolating every object-axis towards every World-axis at the same time, effectively aligning my object to the World, like a well trained nazi-soldier.

I’m using this code to accomplish my faliure:

var TopQuat:Quat = Quat(0,0,0,1)
transform.basis = Basis(Quat(transform.basis).slerp(TopQuat,delta))

Any hints for isolating this interpolation to my object’s local UP-axis?

:bust_in_silhouette: Reply From: Magso

You could have 2 lerps, one for X and one for Z both going from their initial value to 0.

Mmmm yes … I tried that, but I’m unsure about what property to do the lerping against.

If I lerp over transform.basis.x/z, like this:

transform.basis.x = lerp(transform.basis.x,Vector3(1,0,0),delta)

… I get absolutely crazy psychedelic warping of my object’s dimensions, giving me ideas for a LSD-simulator-game :slight_smile:

Ole | 2019-05-06 17:59

You need to get the transform.basis.x starting value.

var x_start = transform.basis.x

transform.basis.x = lerp(x_start ,0, delta)

Make sure x_start doesn’t change, then again a LSD-simulator-game sounds awesome transform.basis.x = randf... :smiley:

Magso | 2019-05-06 18:14

Yours and my code, does exactly the same job … I don’t need your x_start variable, as I stick the transform.basis.x-start-state directly into the lerp-function, and saves the result as the new (lerp’ed) value of transform.basis.x, resulting in the same functionality, with on less code line :stuck_out_tongue:

Besides, you want to input an integer (0) as the second argument for the lerp, which isn’t allowed. It wants a Vector3, because the transform.basis.x itself is a Vector3.

A long story short … it still gives the LSD-result :slight_smile:

Ole | 2019-05-06 18:29

Ah… I thought transform.basis was a vector3 and transform.basis.x would be a float. I’m too used to rotation_degrees. I myself would do it like this,

var start_rotation = [rotation_degrees.x, rotation_degrees.z]
var time : float

func _process(delta):
    time += delta
    if time <= 1:
        rotation_degrees.x = lerp(start_rotation[0], 0, time)
        rotation_degrees.z = lerp(start_rotation[1], 0, time)

Not very fancy but reliable.

Magso | 2019-05-06 18:51

Wonderful … You solved my problem!

However, I don’t understand all your extra fluff-code … it isn’t necessary, and will bloat your code base.

My implementation is way simpler, and does exactly the same job:

rotation_degrees.x = lerp(rotation_degrees.x, 0, delta)
rotation_degrees.z = lerp(rotation_degrees.z, 0, delta)

But, thanks alot!

Ole | 2019-05-06 19:09

I thought that setting a lerp every frame would have more unnecessary overhead than checking if a float is below 1. It also helps if the lerp needs to be repeated or reversed.

Magso | 2019-05-06 19:33

Fair enough.

Besides, I believe my approach yields a kind of ‘diminishing’ interpolation (reversed exponential), theoretically never reaching 0 (in reality it does), which renders lovely smooth animation, perfect for my use case,

Your approach yields linear interpolation, which is more in-line with the intended use of the function lerp().

Anyway … I’m happy, and owe you a beer, or an LSD-trip … thanks for the help :slight_smile:

Ole | 2019-05-06 20:23