0 votes

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?

asked May 6 in Engine by Ole (78 points)

1 Answer

0 votes
Best answer

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

answered May 6 by Magso (791 points)
selected May 6 by Ole

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 :)

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... :D

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 :p

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 :)

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.

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!

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.

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 :)

Welcome to Godot Engine Q&A, where you can ask questions and receive answers from other members of the community.

Please make sure to read How to use this Q&A? before posting your first questions.