How to rotate a Vector3 v from directon v1_3D to v2_3D?

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

Hi…,

in 3D I want to rotate a Vector3 from direction1(as Vector3) to direction2(as Vector3).

What is the easiest way?

Thanks

Mike

:bust_in_silhouette: Reply From: Yuminous

Heya.

Do you mean how to create a smooth animation transition? Or to instantaneously change your Vector3 rotation value from one to the other?

To instantly change it, simply:

$ThingSpatial.set_rotation(Vector3(A, B, C))

or another way:

var thing = $ThingSpatial
var new_rotation = Vector3(0, 0, 180)

func your_function_or_signal_event_here():
    thing.set_rotation(new_rotation)

But assuming you want to make a smooth transition you have a lot of options and depending on what you want it could get complicated. The most customisable one is probably Tween-ing, which isn’t too complicated but it has a lot of extra wording. To start, you’ll need to add a Tween node to your scene, then:

var tween = $Tween
var thing = $ThingSpatial
var new_rotation = Vector3(0, 0 ,180)

func your_function_or_signal_event_here():
    tween.interpolate_property(thing, "rotation", thing.rotation, new_rotation, 2, Tween.TRANS_EXPO, Tween.EASE_IN)
    tween.start()

It looks complicated, but most of that is just copy + paste stuff and you can easily change around the details to find what suits you best.

Breaking it down:
tween.interpolate_property is just necessary set-up, then:
The node you want to affect (thing,
The property you’re changing (has to be in quotes): “rotation”,
The initial value (in this case we’re using the object’s current rotation): thing.rotation,
The end value (you can also just specify it directly): new_rotation,
The duration (in seconds): 2,
Then here are the tween easing-types, they affect how the transition is animated. See this picture, so in this case: Tween.EXPO,
And: Tween.EASE_IN, but you can do any combination you like.

Finally, after you customise all that you have to follow it up with tween.start() in order to actually make the thing happen.

You can see here for another tutorial on tweens.

There are other alternative options to animating properties if this doesn’t fit what you need. For example, another method would be to change properties directly by a fixed value or percentage in _physics_process. This is a lot harder to get right, but if you have several tweens stepping on each other it’s a lot more definitive.

Good luck!

Hi Yuminous,

wow, thank you very much for your detailed answer.

I just need an instant change of my vector by an angle defined from the difference of two other vectors.

I don’t want to setup a Spatial for this. I thought I can do this by setting up a plane by my vectos v1_3D and v2_3D, and then rotate my Vector3 by the normal of this plane and and the angle phi from v2_3D minus v1_3D.

I have to try this all now, puh.

Thanks

Mike

MikeMikeMike | 2021-07-08 16:38

I’ll be honest: I’m not that great at math so I can’t exactly point you at the solution you’re after, but Godot allows you to use full Vector3s in a calculation as long as it makes sense, so for example:

Vector3A = Vector3B * Vector3C / 2
Vector3A = Vector3A - Vector3B

If you know exactly what you want to calculate you can just directly assign that and your rotation vector is immediately changed. There is also some useful knowledge of Vector3 math that may assist you further: you can break down a Vector3 into floats by specifying “.axis”, for example:

Vector3A = Vector3(Vector3A.x, Vector3A.y - PI, Vector3A.z + Vector3B.z)

…But coming to think of it, what you might be after is a transform function “.rotated()” as in: Vector3A = Vector3A.rotated(Vector3, phi). You can see on this page and this other question about its usage. You could still do the math yourself and the result would be identical, but these various functions just make it a lot more concise. Hope that it helps!

Yuminous | 2021-07-09 01:30

:bust_in_silhouette: Reply From: MikeMikeMike

Dear Yuminous,

I have found my code:

# any vector v
var v := Vector3( 11, -3, 5 )

# given Vector3 directions v1 and v2
var angle : float = v1.angle_to( v2 )
if angle > 0.001 or angle < -0.001:

    # calculate rotation axis and rotate
    v.rotated( v1.cross( v2 ).normalized(), angle )

Thanks for your help

Mike