setOrientation made simple script by Spike1907 and myself

Hope you find uses for it :smiley:

BTW Spike1907 i fixed it it works on all the local axis :wink:


## Ok, so this script is meant to properly use the setOrientation
## function along all axis.  Just change the angle of rotation on
## any of the three axis (found on lines 17-24)
## It also has a function used to multiply the matrices together, 
## and it could be modified to multiply matrices of different sizes.
## Script by Spike1907
## Revised by Siegel
## Assisted by maxwildcat

import GameLogic as g
from math import cos, sin, radians
c = g.getCurrentController()
o = c.getOwner()

current=o.getOrientation()

##Rotation on the X axis
xa = radians(45)

##Rotation on the y axis
ya = radians(0)

##Rotation on the z axis
za = radians(0)

#The rotational Matrices
#ROTATIONAL X MATRIX
matX = [[1.0, 0.0, 0.0],
		[0.0, cos(xa), sin(xa)],
		[0.0, -sin(xa), cos(xa)]]

#ROTATIONAL Y MATRIX
matY = [[cos(ya),0.0,-sin(ya)],
		[0.0,1.0,0.0],
		[sin(ya),0.0,cos(ya)]]

#ROTATIONAL Z MATRIX
matZ = [[cos(za),sin(za),0.0],
		[-sin(za),cos(za),0.0],
		[0.0,0.0,1.0]]
	
 
##Function used to multiply two matrices together.
##This only works for 3x3 matrices.
def matMult(mat1,mat2): 
    return [[(mat1[0][0]*mat2[0][0])+(mat1[0][1]*mat2[1][0])+(mat1[0][2]*mat2[2][0]),
    			(mat1[0][0]*mat2[0][1])+(mat1[0][1]*mat2[1][1])+(mat1[0][2]*mat2[2][1]),
    			(mat1[0][0]*mat2[0][2])+(mat1[0][1]*mat2[1][2])+(mat1[0][2]*mat2[2][2])],
    		[(mat1[1][0]*mat2[0][0])+(mat1[1][1]*mat2[1][0])+(mat1[1][2]*mat2[2][0]),
    			(mat1[1][0]*mat2[0][1])+(mat1[1][1]*mat2[1][1])+(mat1[1][2]*mat2[2][1]),
    			(mat1[1][0]*mat2[0][2])+(mat1[1][1]*mat2[1][2])+(mat1[1][2]*mat2[2][2])],
    		[(mat1[2][0]*mat2[0][0])+(mat1[2][1]*mat2[1][0])+(mat1[2][2]*mat2[2][0]),
    			(mat1[2][0]*mat2[0][1])+(mat1[2][1]*mat2[1][1])+(mat1[2][2]*mat2[2][1]),
    			(mat1[2][0]*mat2[0][2])+(mat1[2][1]*mat2[1][2])+(mat1[2][2]*mat2[2][2])]]

##Multiply X and Y matrices.
multXY = matMult(matX,matY)

##Multiply product of XY to Z matrix
multXYZ = matMult(multXY,matZ)

##Multiply product of XY and Z to currnet matrix 
newXYZ = matMult(current, multXYZ)

##Ok... so now you can add a setOrientation(multXYZ)
o.setOrientation(newXYZ)

##You might need to reset the x y z degrees 
##depending on how you use the script.
##x,y,z=0,0,0

Hey! Nice! Iā€™ve been rambling with matrices and getOrientation() before yesterday at the irc channel! Very neat, I donā€™t know how I can use it, but I actually understand what youā€™re doing in this script, and that feels so good!
Might as well find a use for it beyond educational purposes!
Now I need to work around it the other way around, from the orientation matrix I want to get x,y and z rotation in degrees (like blender shows it in the ā€œnā€ menu)

Thanks!

I donā€™t know when, but euler rotation has been added to python a while back through attributes, only setting though:

http://www.blender.org/documentation/pydoc_gameengine/PyDoc-Gameengine-2.34/KX_GameObject.KX_GameObject-class.html#orientation

for getting the rotation in euler format, you will need a script (such as this :slight_smile: )

Yes, Iā€™m struggling my way into converting the matrix into eulerā€¦ butā€¦ Iā€™m rusty!!! Iā€™ve checked the docs too, just in caseā€¦

ā€¦ I just need to remember with my trig classes i thinkā€¦
One question though, why in the heavens is there a way to set rotation with euler vectors, but no way to directly retrieve rotation in euler vectors???

One question though, why in the heavens is there a way to set rotation with euler vectors, but no way to directly retrieve rotation in euler vectors???

well to answer thatā€¦
the matrix that is used in setOrientation, and the matrix you see when you print an objectā€™s orientation using getOrientation, is the product of 3 different martices multiplied together. There is one matrix for each axis of rotation, and these three matrices vary slightly but have the same general setup. But because of how the system works, I do not think it is possible to accuratly decompose the final matrix into anything usefull without even knowing the angles on each axis that the object is rotated to start with.

sry :frowning:

the script is very interestingā€¦ but Iā€™d like also to understand it.
Letā€™s say that I do know nothing about matrices, can somebody point me to a good tutorial/explanation of rotation and translation matrices?

that would be really nice. Iā€™ve been looking on the web but i find only hardcore technical info that are fine only if one is already skilled with this kind of stuffā€¦

ciao

This is exactly what I needed. And it explains the math too. Finally! Thanks a lot!

yea No problem

If not, would it be possible to rewrite the code to use mathutils to speed things up a bit? Just wonderinā€¦

EDIT: I would like to apologize for in my stupididy just assisted this newb bring this post back. F$*&K!

no not really.
There are no math operations that can perform matrix multiplication in less steps. and its not like its slow or anything. there is no faster way, cus it still requires the same number of calculations.

You could get a slight speed increase if you integrate that code into the blender GE source code as a new method i.e. setEulerOrientation(angle x, y, z)

I could get that done in the GE source in like 15 mins. But I have alot of bigger stuff im doing with the GE now. But I might consider implementing something like that just cus the need to use quaternions for setting rotations seems to be difficult for many users.

also It may only take me 15 mins to get somthing like this working in the GE, but Its somthing so small that I wouldnt find it worth making a patch to submit to the CVS. I prefer to work on much larger packages and release new features all at once.

Since youā€™re already down the road of helping n00bs, how about answering another stupid question? (BTW, all questions I ask are bound to be stupid on some level so youā€™re just going to have to bear with me. :stuck_out_tongue: )

Okay! So I just bound the script to the space key with a keyboard sensor blah blah blah. I press the space key and my test cube rotates 45 in x. Fine, thatā€™s as expected.

Then I let go of the space key and the cube reverts back to x rotation equals zero. Huh?

Shouldnā€™t the effects of setOrientation() be permanent? There is literally nothing else in the scene other then the default light/cube/cam and the script.
What gives?

one thing I should point out is that this script is very old, from when i was just starting with 3d math like this. Im actualy a fairly good graphics programer now and stuff like this i deal with on a daily basis.

so lets just say that that script is garbage, So im going to write a new one right now.
Its going to have multiple functions. One is to convert the orientation matrix to euler angles. another is to set the matrix using euler angles.

Well here it isā€¦ as you can see it is much much shorter. Have fun.

################################################
##	Simple use of setOrientation()
##  by Spike1907
##  March 11th, 2006
################################################

from GameLogic import getCurrentController as GCC
from math import atan2, asin, sin, cos, radians, degrees

o = GCC().getOwner()

def matToEuler():
    ori = GCC().getOwner().getOrientation()
    J = -asin(ori[0][2])
    cJ = cos(J)
    if cJ!=0.0:
        cJ = 1.0/cJ
        I = atan2(ori[1][2] * cJ , ori[2][2] * cJ)
        K = atan2(ori[0][1] * cJ , ori[0][0] * cJ)
        return (degrees(I) , degrees(J) , degrees(K))

def eulerToMat(I, J, K):
    A , B = sin(I), cos(I) 
    C , D = sin(J), cos(J) 
    E , F = sin(K), cos(K) 
    AC, BC = A*C, B*C 
    return [[D*F     , D*E	    , -C],
		    [AC*F-B*E, AC*E+B*F, A*D],
		    [BC*F+A*E, BC*E-A*F, B*D]]
		
o.setOrientation( eulerToMat(45,0,0) )

Man look at you and your post times! You werenā€™t kidding when you said you can do this in 15 minutes! haha~! And the ā€œorientation not stickingā€ problem is gone too! Simply amazing.

Thanks man. Iā€™m sure more then just myself will find this code very useful for a long long time. :smiley:

Hey thx alot man and no problem. lol yea I do a crap load of matrix math and quaternion stuff every day, so im quite good at it.

Ok added these lines to the bottom :

print 'geto ',matToEuler()
o.setOrientation( eulerToMat(45,10,20) )
print 'geto ',matToEuler()

and I get this output :

geto (0.0, 0.0, 0.0)

geto (-121.68992132700197, -32.95779636186213, -114.08440864537208)

:confused: :confused: :confused: :confused:

Mike

Try the longer script at the top, see if that works.

These functions are great time-savers! Thanks!:smiley: One question, though, how do I access the output from the matToEuler function. Is it just a string output? Is there any way to make it a list output?

Itā€™s returning a tuple with 3 values. Try something like:
orientation = matToEuler(object.getOrientation())
xDegree = orientation[0]
yDegree = orientation[1]
zDegree = orientation[2]

Hope thatā€™s what your asking. Otherwise, you can change the return statement if there is something else in the you would want to use. You can just change the outside round brackets to square brackets to make it a list. Or define a list and make it equal using a variable:
degrees = []
degrees = matToEuler(object.getOrientation()), then again it might change the list to a tuple. Iā€™m not sure now. Probably changing the return statement is better.