オブジェクトの向きの取得
2010/3/31
Blender2.49
オブジェクトの向きはObj.orientationで取得するんだけど、それは3次行列を返してくる。この行列はx軸、y軸、z軸それぞれの基底ベクトルを云々かんぬんで、3Dにおいてよく使われる表現らしい。これの方が便利なそうだ。さっぱりわからん。
obj = GameLogic.getCurrentScene().objects["OBCube"]]
#ローカル
local = obj.localOrientation
#グローバル
world = obj.worldOrientation
obj.orientationは書き込み時にはworldの方で、読み込み時にはlocalらしい。非推奨。わかりずらいので使わないほうがよさそうだ。
Orientation Matrix - Basics
http://sites.google.com/site/socialstorage/orientationmatrix-basics
Orientation に関係するスレッド
http://blenderartists.org/forum/showthread.php?t=113172
http://blenderartists.org/forum/showthread.php?t=70111
使い方がわからんので、x,y,zをそれぞれ角度で受け取る方法はないもんかと。あった。
import Blender.Mathutils as Mathutils
~~~
o = obj.localOrientation
matrix = Mathutils.Matrix(o[0],o[1],o[2])
euler = matrix.transpose().toEuler()
rx,ry,rz = euler.x,euler.y,euler.z
transposeは転置?eulerはオイラー。オイラー角というのが普段いう角度のことらしい。
参考
http://blenderartists.org/forum/showthread.php?t=76936
角度から行列にするには
import Blender.Mathutils as`athutilss
~~~
euler = Mathutils.Euler(45, 0, 0)
orientation = euler.toMatrix().transpose()
参考
http://wiki.gameblender.org/index.php?title=Orientation
ちなみに、orientationの行列を角度x,y,zで表すと
| cos(y)cos(z) sin(x)sin(y)cos(z)-cos(x)sin(z) cos(x)sin(y)cos(z)+sin(x)sin(z) | | cos(y)sin(z) sin(x)sin(y)sin(z)+cos(x)cos(z) cos(x)sin(y)sin(z)-sin(x)cos(z) | | -sin(y) sin(x)cos(y) cos(x)cos(y) |こうなる。
これはx軸、y軸、z軸それぞれ回りに回転する変換行列の積を転置したものなんだけども、自分であの行列の正体はなんぞや?っと逆算的に考えた結果導き出されたものなので、根拠は説明できない。
つまるとこ、これによって何ができるかというと、所定の角度にしたい時には
import math
def setRotation(obj,rx,ry,rz,local=False):
x = math.radians(rx)
y = math.radians(ry)
z = math.radians(rz)
mat = [[0,0,0],[0,0,0],[0,0,0]]
mat[0][0] = math.cos(y)*math.cos(z)
mat[1][0] = math.cos(y)*math.sin(z)
mat[2][0] = -math.sin(y)
mat[0][1] = math.sin(x)*math.sin(y)*math.cos(z)-math.cos(x)*math.sin(z)
mat[1][1] = math.sin(x)*math.sin(y)*math.sin(z)+math.cos(x)*math.cos(z)
mat[2][1] = math.sin(x)*math.cos(y)
mat[0][2] = math.cos(x)*math.sin(y)*math.cos(z)+math.sin(x)*math.sin(z)
mat[1][2] = math.cos(x)*math.sin(y)*math.sin(z)-math.sin(x)*math.cos(z)
mat[2][2] = math.cos(x)*math.cos(y)
if local:
obj.localOrientation = mat
else:
obj.worldOrientation = mat
こうできる。こう使うものじゃないと思うけど。
Class KX_GameObject localOrientation
http://www.blender.org/documentation/249PythonDoc/GE/GameTypes.KX_GameObject-class.html#localOrientation
The Matrix Object
http://www.blender.org/documentation/249PythonDoc/GE/Mathutils.Matrix-class.html
The Euler object
http://www.blender.org/documentation/249PythonDoc/GE/Mathutils.Euler-class.html
以下、向き用に書いた関数色々。
y軸周りにdegだけ回転したorientationを返す
def rotY(deg,orientation):
# rotate y
# | cos(y) 0 sin(y) |
# | 0 1 0 |
# | -sin(y) 0 cos(y) |
l = orientation
y = math.radians(deg)
n = [[0,0,0],[0,0,0],[0,0,0]]
n[0][0] = math.cos(y)*l[0][0] + math.sin(y)*l[2][0]
n[0][1] = math.cos(y)*l[0][1] + math.sin(y)*l[2][1]
n[0][2] = math.cos(y)*l[0][2] + math.sin(y)*l[2][2]
n[1][0] = l[1][0]
n[1][1] = l[1][1]
n[1][2] = l[1][2]
n[2][0] = -math.sin(y)*l[0][0] + math.cos(y)*l[2][0]
n[2][1] = -math.sin(y)*l[0][1] + math.cos(y)*l[2][1]
n[2][2] = -math.sin(y)*l[0][2] + math.cos(y)*l[2][2]
return n