Homemade python object orientation constraint : is it ugly or what ?

Hi there,

I’ve been playing with the BGE and python, mainly to try to learn some python-fu.

I’ve wrote a simple script that kind of replicates the “track to” behaviour in the “Edit object” actuator.

Here is the code :



import bge
import math

#    B_____________A
#     \            |
#      \           |
#       \          |
#        \         |
#         \        |
#          \       |
#           \      |
#            \     |
#             \____|
#              \   |
#               \  |
#                \ |
#                 \|
#                  C
              
def main():
    
    # we have two cubes, a red one at C and a green one at B. When moving the green cube, the red cube's orientation is modified so that the same side of the red cube always faces the green one.

    # get the two cubes
    scn = bge.logic.getCurrentScene()
    # redcube is at C
    redCube = scn.objects['Cube']
    # greencube is at B
    greenCube = scn.objects['Cube.001']
    
    # get the two cubes coordinates
    redCubePos = redCube.position.xyz
    greenCubePos = greenCube.position.xyz
    
    # infer AC and AB from coordinates
    AC  = (redCubePos.y - greenCubePos.y)
    AB  = (redCubePos.x - greenCubePos.x)
    
    # angle C is equal to inv tan of ^B          
    tanB = AC/AB
    atanB = math.atan(tanB)
    
    # ugly hack ?
    if redCubePos.x < greenCubePos.x:
        angleC = abs(math.degrees(atanB)) - 90
    else: 
        # in a triangle, angles sum equals 180
        # we know ^A is square, that's 90°
        # therefore, ^C = ^A - ^B
        angleC = 90 - abs(math.degrees(atanB))

    # get redCube orientation and convert matrix to euler
    xyz = redCube.localOrientation.to_euler()
    # apply ^C
    xyz[2] = math.radians(angleC)
    # convert eulers back to matrix and apply
    redCube.localOrientation = xyz.to_matrix()

main()



and I attach the corresponding blend file.

Though it works, I’m 98% sure I’m not doing it right, but I must say my brain is almost allergic to maths. I found the “ugly hack” to work after fiddling with the values.

My question is, what is the correct way to do this ?

And WHY does this ugly hack do the trick ?

Thanks for your time,

Cheers,

Attachments

orientation.blend (481 KB)

In the BGE API, there is an alignAxisToVect method of KX_GameObject that does this for you. You can also use Vector.to_track_quat to create an alignment quaternion from a vector.

Anyway, I see that you’ve done this primarily to learn Python;

I recommend using module mode, rather than a global main (in this example why would you use main() at all, just remove the function entirely).

The nicest non-bge-api method of doing this (still using the Vector class) is to take the direction vector to the other object, cross that with some constant vector (e.g up) to produce the final vector (e.g x in this case).
Those form the columns of a matrix, which can be set as indices of the Matrix.col attribute (creating a matrix from identity first (mat = Matrix.Identity(3)))