alignAxisToVect Rotate Local Z axis rather than Global Z axis? -ANSWERD

I am attempting to “LOCK the Z axis” of a series of instanced objects in the game.

So essentially they all rotate on their local Z axis to face the player.

This is what I have currently, but the Object instances that run this code rotate on the global Z axis rather than their individual local Z axis–

from bge import logic
from mathutils import Vector
import mathutils

cont = logic.getCurrentController()
own = cont.owner

own_x = own.localPosition[0] - own.scene.active_camera.worldPosition[0]
own_y = own.localPosition[1] - own.scene.active_camera.worldPosition[1]
own_z = own.localOrientation.to_euler()[2] - own.scene.active_camera.localOrientation.to_euler()[2]
own_z = own.worldOrientation[2] * own.localOrientation[2]

world_y = own.scene.active_camera.worldPosition

own.alignAxisToVect((own_x, own_y, 0), 0, 1.0)

Here is my sample blend of the scene:2.5_Dimensions_FOR_TREES.blend (731.8 KB)

direction = owner.worldPosition - owner.scene.active_camera.worldPosition
direction.z = 0 # flat out the direction on z
owner.alignAxisToVect(direction, 0, 1.0)

Like this? Although it assumes that objects will rotate around global Z, it seems to do what you are after?

As I know sometimes aligning an axis can rotate other axis, here’s an optional line, if you have issues:

# ...
owner.alignAxisToVect((0, 0, 1), 2, 1.0)

Edit: Inverted the sign when computing the direction, fixed.

1 Like

Hey @Wknight02 that doesn’t correct rotation issue. Each tree needs to rate on their individual local z axis.

Look at this example file and press P-- notice how the trees snap “UP” once you run the scene in the game engine? I need the trees to remain at their current angle as they are in the blend scene.

2.5_Dimensions_FOR_TREES.blend (734.5 KB)

You basically want the “TREE FRONT” text to always be in front of the camera, but to always be aligned with the ground, never tilted, did I understand correctly?

Edit: Oh ok, I did not expect your trees to be that messed up, saw the new blend file.

1 Like

Oh well, same idea, but thinking about local axises…

globalDirection = owner.worldPosition - owner.scene.active_camera.worldPosition
localDirection = owner.worldOrientation.inverted() * globalDirection
localDirection.z = 0
owner.alignAxisToVect(owner.worldOrientation * localDirection, 0, 1.0)
1 Like

Nono I do want the tilt-- I need the tilt to remain

I think you got it! Inverted!!! Of course! @Thatimster mentioned that to me this morning, but I didn’t know entirely how to invert orientation.

1 Like

In this case, I need to use the inverted matrix in order to transform something in global space down to local space, I do the stuff in local, then I use the non-inverted matrix to convert from local space back to global.

orientation_matrix * global_vector = local_vector

orientation_matrix.inverted() * local_vector = global_vector

You are a damn hero and you have solved my problem.

So you are calculating the local space, making the necessary calculations with the local, then bringing back into global space.


Do you think there is a more computationally efficient way to achieve this effect? You have solved my problem for sure either way :))))

Is there any way to set the influence of AxistoVect? So you could use a camera distance, for example, to increase or decrease the effect of AxistoVect?

From what I can see there isn’t a way to do this— or is it possible to do this to the orientation in some way?

You can play with the factor value of the alignAxisToVect function, but it is relative to the current transform of the object. Which means that it will rotate until in the target position, and then not move much because relative - target == 0 kind of…

Depending on the effect you are looking after, there are different ways to go about it.

If you want the orientation to be somewhat proportional to the distance, you need to define some kind of “original orientation” and a set of limits to map the distance to some factor for the align function.

If you just want the trees to align more or less slowly based on the distance, then it is just a matter of doing something of the likes:

.alignAxisToVect(..., ..., map_distance_to_factor(distance_to_camera))

Where map_distance_to_factor is the function applying the formulae you want to use to compute the value between 0 and 1. At this point any mathematical equation you like will work, as long as it is [0, 1]…