Topic was automatically imported from the old Question2Answer platform.
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?
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.
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!
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.
If you want to get the scale, accounting for rotation in the matrix,
then you need to extract the vector3’s from the 3x3 matrix and get the length of each one like so:
var scaleX:Vector3 = Vector3(basis.x.x, basis.y.x, basis.z.x)
var scaleY:Vector3 = Vector3(basis.x.y, basis.y.y, basis.z.y)
var scaleZ:Vector3 = Vector3(basis.x.z, basis.y.z, basis.z.z)
var scale_x_len = scaleX.length()
var scale_y_len = scaleY.length()
var scale_z_len = scaleZ.length()