• 3D
  • Global to local rotation

Hi, all! I'm trying to get an object to latch onto another by changing it's parentage in the node tree, the two objects having different orientations. I got the parentage thing worked out in a previous project, and got the vector translation worked out pretty quickly, so that it's position doesn't change at the instant of the node tree change. However, I've spent hours and hours trying to get the rotation right. Either it translates the global rotations over to it's new local axes, or it just assumes a seemingly random rotation. I've been reading about transforms and Eulers til my ears ring, but I just seem to be going around in circles. How do you rotate an object in it's new local space so that it assumes the same global orientation that it had before?

I'm not 100% positive this would work, but you may be able cache the global basis/rotation, reparent and move the node, and the reapply the global basis. Something like this (untested):

var global_basis = node_to_reparent.global_transfrom.basis;
# Reparent the node here. Once done...
node_to_reparent.global_transform.basis = global_basis

Then, I think, that should make it keep the same rotation that it had before, prior to having its parent change.

Nope, still all weird. I'm also getting a lot of "Invalid call. Nonexistent function [FUNCTION_THAT_IS_CLEARLY_IN_THE_DOCUMENTATION] in base 'StaticBody'.", like when I try to use "get_euler" on a basis transform matrix. Do I need to use some kind of "extends Basis" or something? Is basis a data type? Sorry, I've been at this less than a month.

Hmm, strange. No, you shouldn’t need to extend Basis to access it, it should be part of the Transform you get from the get_transform or get_global_transform (or just node.transform or node.global_transform).

If you can, do you mind sharing the code you are using?

Well, the rotation part was a convoluted mess, so I deleted it to start over. This script extends ARVRController, and here is the relevant part:

		Pick-up Function 
if !grabLatch and controllerR.is_button_pressed(2):
	grabLatch = 1
	grabbedLoc = grabbed.get_global_transform().origin
	sceneContainer.remove_child(grabbed)
	controllerR.add_child(grabbed)
	grabbed.set_translation(to_local(grabbedLoc))
	
if grabLatch and !controllerR.is_button_pressed(2):
	grabLatch = 0
	grabbedLoc = grabbed.get_global_transform().origin
	controllerR.remove_child(grabbed)
	sceneContainer.add_child(grabbed)
	grabbed.set_translation(grabbedLoc)

If there was a "to_local" function for rotation, I would be set, but, no.

Hah! I took another look at your post after some sleep, and got it to work!

if !grabLatch and controllerR.is_button_pressed(2):
	grabLatch = 1
	grabbedLoc = grabbed.get_global_transform().origin
	grabbedRot = grabbed.global_transform.basis
	sceneContainer.remove_child(grabbed)
	controllerR.add_child(grabbed)
	grabbed.set_translation(to_local(grabbedLoc))
	grabbed.global_transform.basis = grabbedRot
	
if grabLatch and !controllerR.is_button_pressed(2):
	grabLatch = 0
	grabbedLoc = grabbed.get_global_transform().origin
	grabbedRot = grabbed.global_transform.basis
	controllerR.remove_child(grabbed)
	sceneContainer.add_child(grabbed)
	grabbed.set_translation(grabbedLoc)
	grabbed.global_transform.basis = grabbedRot

Thanks a ton, man!