How to get global scale of a Spatial Node

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

On a spatial node calling get_global_transform().basis.get_scale() and scale both return the same values regardless of the global rotation of the node. I want to be able to scale a node by a specific amount along a global axis even if it has been rotated. How do I find a Spatial’s scale values in global XYZ so I can do this?

Thank you!!

:bust_in_silhouette: Reply From: magicalogic

You can just use your_node.global_scale(scaling_vector) on a spatial node to scale it in world coordinates. Replace your_node with the actual node and scaling_vector with a vector with the scaling amount for each axis.

The problem is that I need to know the starting global scale value to know how much to scale by. Say I have a Spatial Node that has already been scaled and rotated some amount. I want to scale it to be 5 units long on the global X axis. I need to know the starting scale on the global X axis to know how much to scale it by to get it to 5 units long.

Thanks for the help!

path9263 | 2021-06-16 05:32

:bust_in_silhouette: Reply From: path9263

Here is how I solved this for anyone who may find this in the future.

# scales the Spatial by the amount in the given global direction
func scaleDirection(amount: Vector3, camRot: Vector3):
	
	var selfQuat = transform.basis.get_rotation_quat()  # get the global rotation
	var sclXform = Transform(selfQuat) # make it a transform so we can apply it to a vector
	
	var globalScale = sclXform.xform(scale) # convert local scale to scale on global axis'
	globalScale = globalScale.abs() # scale should always be positive but rotation can make it negative when converted to global
	
	# when camera is behind the object axis direction must be inverted:
	if(camRot.y < 0):  
		amount.x = -amount.x 
		pass
	if(camRot.y > 90 or camRot.y < -90):
		amount.z = -amount.z 
		pass
	
	# calculate new scale amount because we are not setting the scale directly
	var newScale = -amount + globalScale  #  invert amount  here to change side which moves
	
	# actually apply changes
	global_scale(newScale)

With this function applied to a Spatial you can set the input value amount to how many units you would like to scale the Spatial in global coordinates. It is not a ratio, for example if your Spatial was already 5 units long on the global X axis and you set amount to (2,0,0) it would scale your Spatial so it was now 7 units long on the global X axis. It should work no matter the Spatials starting rotation or scale. The camera stuff is optional depending on your use case.

Please let me know if there is a simpler way to do this, I have a feeling I have over thought it, but hey, it works!

:bust_in_silhouette: Reply From: SteveSmith

I get the global scale as follows (edit: note that this only works for unrotated spatials):-

# 'mesh' is the name of the spatial
var scale: Vector3 = Vector3(mesh.global_transform[0][0], mesh.global_transform[1][1], mesh.global_transform[2][2])

From what I can tell unfortunately this breaks if the object is rotated.

path9263 | 2022-07-09 18:12

Yes, you’re right. I never noticed that.

SteveSmith | 2022-07-10 10:05