Does the orientation matrix give three lists of rows or three lists of columns of the 3x3 matrix?
Nevermind, it’s rows. I was doing something wrong. He He.
Maybe there’s some math wizard out there that can help me with this.
Normally, I can set
owner.setOrientation(owner.getOrientation())
and get no movement. However, if the object is parented and the parented object has rotated, the child object will rotate. Apparently it’s returning the orientation in respect to the parented object. So my question is, how do I cancel that out?
Maybe you could get the orientation of the parent and “subtract” it from the orientation of the child…but I don’t have a clue.
I have read that getOrientation() returns the global orientation of an object while setOrientation() sets the local orientation. Why? I don’t know. But I have had problems related to this in the past… The solution I saw recommended was to multiply the orientation by the inverse of the parent’s orientation before setting it. I can’t even begin to tell you how to do that.
The solution I saw recommended was to multiply the orientation by the inverse of the parent’s orientation before setting it.
Well, that’s a clue anyway. Thanks.
ahhh thats why the turrets on my vehcile wouldn’t track to the vertex- parented camera reticule, once the vehicle turned. Grrr.
If blendozo is right, how do access two objects orientation values in one script (I suck at python). Then it would be a case of objectorientation*(1/parentorientation) ?
Not sure, but if anyone figures this out please post a solution.
Well, I found out there’s a blender module called Mathutils that does a matrix inversion. Unfortunately, it doesn’t seem to work. The following code gives the exact same matrix for the regular and the inverted version. The “toEuler” seems to work and might come in handy.
from Blender.Mathutils import *
import GameLogic
cont = GameLogic.getCurrentController()
owner = cont.getOwner()
m = owner.getOrientation()
mat = Matrix(m[0],m[1],m[2])
print "mat"
print mat
print "mat.invert()"
print mat.invert()
print "mat.toEuler()"
print mat.toEuler()
edit: apparently the invert is a known bug that no one has gotten around to fixing:
http://www.blender.org/forum/viewtopic.php?t=9042&sid=bd6fd43fc00e81d97e9a329ac73bfd35
known bug with Python’s mathutils or with Blender’s orientation matrix?
Mathutils, it wouldn’t give the same matrix for both otherwise.
The orientation matrix satisfies a nice property:
R^{-1} = R^{T},
i.e. you can get the inverse by inverting rows and columns. I assume you know how to do the rest?
ht
Really? From what I read, I don’t claim to know anything here, the inverse is the number that the row needs to be multiplied by in order to have it go back to the identity. Do you mean inverting rows and cols as in reversing order or by dividing one by each number in the rows and cols?
Sorry, I hav not been very clear. Say R_i is the inverse of R, in the sense that RR_i = I (ie multiplied with R it gives the identity).
Now you can get R_i as follows:
...
R = obj.getOrientation()
R_i = [[0, 0, 0], [0, 0, 0], [0, 0, 0]]
for i in range(3):
for j in range(3):
R_i[i][j] = R[j][i]
#Now use R_i as the orientation matrix that reverses the action of R
<< Ignore this if you want to:
This can be done only because R is also orthonormal, a special property that means:
- the cross product of any two columns viewed as vectors gives +/- the third row (ortho); and
- the length of any column viewed as a vector is 1 (normal).>>
Beware though - if you use your orientation matrix to perform shearing and scaling, you mess up the orthonormality, and the trick above won’t work. You will be safe with normal scaling and shearing inside the GUI.
If you need code for performing the matrix multiplication, let me know, I have some that I’ve used before.
O.K. I’ll try that out. According to Blendenzo, I get the inverse of the parent and multiply by the child orientation.
Well, it doesn’t work for me. This is the code I tried. The child cube seemed to always rotate a little bit when I activated the script. The multiply script I’ve used before, so it works.
import GameLogic
import Orient
scene = GameLogic.getCurrentScene()
parent = scene.getObjectList()["OBCube.001"]
R = parent.getOrientation()
R_i = [[0, 0, 0], [0, 0, 0], [0, 0, 0]]
for i in range(3):
for j in range(3):
R_i[i][j] = R[j][i]
cont = GameLogic.getCurrentController()
owner = cont.getOwner()
owner.setOrientation(Orient.mult(owner.getOrientation(),R_i))
This works:
import GameLogic
def mmul(m1, m2):
res = [[0, 0, 0], [0, 0, 0], [0, 0, 0]]
for i in range(3):
for j in range(3):
sum = 0
for k in range (3):
sum = sum + (m1[k][j] * m2[i][k])
res[i][j] = sum
return res
cont = GameLogic.getCurrentController()
owner = cont.getOwner()
scene = GameLogic.getCurrentScene()
parent = owner.getParent()
R = parent.getOrientation()
R_i = [[0, 0, 0], [0, 0, 0], [0, 0, 0]]
for i in range(3):
for j in range(3):
R_i[i][j] = R[j][i]
owner.setOrientation(mmul(owner.getOrientation(), R_i))
The problem might either be with your multiplication function, or with the name of your parent.
Yeah, works like a charm. Thanks a lot. I’ll try to figure out which of those things I did wrong. I’ve used the mult quite a bit, so it almost has to be something about the parent. Anyway, this works and is more generic. I like your multiply code, also. Definately a saver. Thanks for all your help.
I’ve just been getting into blender python and i figured out a good way to fix orientation problems with parented objects.
first off don’t parent them. What you can do is make a fake parent:
set an empty where you want the center of your child object to be. Have the empty be parented to your master object. Then…
#a script run by the child object:
first find your empty…don’t forget to import the current scene
scene = GameLogic.getCurrentScene()
empty = scene.getObjectList()[“OBEmpty.001”]
child.setPosition(empty.getPosition())
this should work but i suppose you already solved the problem
Interesting…but the man is maybe dead, now…this is quite old.
You should post a new thread, maybe?!