2017年07月13日

modo11.0v3のスクリプトについて調べてみた その104

引き続き「TD SDK」の「mathutils」の「Quaternion」クラスについて調べてみたい。

「fromMatrix4()」は「Matrix4」の回転変換を「Quaternion」にセットするメソッドだ。下がそのコードで、これも「Matrix3」に変換して、「transpose()」で転置してから「fromMatrix3()」で値を変換している。

 def fromMatrix4(self, input):
     """ This function converts a matrix into a quaternion, containing the same rotation.

     :param Matrix4 input:
     """
     matrix = Matrix3(input)
     matrix.transpose()

     quat = Quaternion()
     quat.fromMatrix3(matrix)
     self.values = quat.values

そして「fromMatrix3()」メソッドのコードは下のようになっている。

def fromMatrix3(self, input):
     """ This function converts a matrix into a quaternion, containing the same rotation.

     :param Matrix3 input:
     :param Quaternion output:
     """

     output = Quaternion()

     nxt = [1, 2, 0]
     i, j, k = 0, 0, 0
     tr, s = 0.0, 0.0

     tr = input[QX][QX] + input[QY][QY] + input[QZ][QZ] + 1.0

     if tr > 0.0:
         s = math.sqrt(tr)

         output[QW] = s * 0.5

         s = 0.5 / s

         output[QX] = (input[QZ][QY] - input[QY][QZ]) * s
         output[QY] = (input[QX][QZ] - input[QZ][QX]) * s
         output[QZ] = (input[QY][QX] - input[QX][QY]) * s
     else:
         i = QX

         if input[QY][QY] > input[QX][QX]:
             i = QY

         if input[QZ][QZ] > input[i][i]:
             i = QZ

         j = nxt[i]
         k = nxt[j]

         s = math.sqrt((input[i][i] - (input[j][j] + input[k][k])) + 1.0)

         output[i] = s * 0.5

         if s > 0:
             s = 0.5 / s

         output[QW] = (input[k][j] - input[j][k]) * s
         output[j]  = (input[j][i] + input[i][j]) * s
         output[k]  = (input[k][i] + input[i][k]) * s

     self.values = output

前回出て来たように、正規化されたクォータニオン(x,y,z,w)を回転行列に変換すると下のようになり、

fig01

これを転置した行列が与えられるから、

fig04

となる。

QX = 0、QY = 1、QZ = 2、QW = 3、x2 + y2 + z2 + w2 = 1で、

tr = input[QX][QX] + input[QY][QY] + input[QZ][QZ] + 1.0
  = 1-2y2-2x2+1-2x2-2z2+1-2x2-2y2+1
  = 4(1-x2-y2-z2)
  = 4w2

よって下のコードで「output[QW]」にはwが入力されるのがわかる。

 tr = input[QX][QX] + input[QY][QY] + input[QZ][QZ] + 1.0
 s = math.sqrt(tr)
 output[QW] = s * 0.5

ここまでで「s」は2wなので、0.5/sは1/4wだ。

s = 0.5 / s -> 1/4w

output[QX]
= (input[QZ][QY] - input[QY][QZ]) * s
= (input[2][1] - input[1][2]) / 4w
= (2(yz+wx) - 2(yz-wx)) / 4w
= 4wx/4w = x

output[QY]
= (input[QX][QZ] - input[QZ][QX]) * s
= (2(xz+wy) - 2(xz-wy)) / 4w
= 4wy/4w = y

output[QZ]
= (input[QY][QX] - input[QX][QY]) * s
= (2(xy+wz) - 2(xy-wz)) / 4w
= 4wz/4w = z

となる。

今回のコードは「Matrix4」から「Matrix3」へは転置して正解のようだな。

ここで前回の「fromMatrix4()」の検証をしてみた。下がそのプログラム。「Mesh」アイテムのX軸に30度の回転を与えてから実行してみた。

from modo import *
import math
q=Quaternion()
mesh = Mesh('Mesh')
m4 = Matrix4(mesh.channel('worldMatrix').get())
q.fromMatrix4(m4)
print q.getAxisAngle()[1]*180/math.pi
print m4
print q.toMatrix4()

これがその結果。「Mesh」アイテムの「worldMatrix」から取得した「Matrix4」を「fromMatrix4()」でクォータニオンに変換させて「getAxisAngle()」で回転角度を取得すると30度と出力されて合ってる。そこで変換される前の「Matrix4」と「toMatrix4()」でこの「Quaternion」を「Matrix4」に変換したものとを比較してみたらやっぱり符号が逆になっていた。やっぱり「toMatrix4()」は転置がひっくりかえっちゃってるみたいだ。

# Result: 
30.0
Matrix4([[1.0, 0.0, 0.0, 0.0], [0.0, 0.8660254037844387, 0.49999999999999994, 0.0], [0.0, -0.49999999999999994, 0.8660254037844387, 0.0], [0.0, 0.0, 0.0, 1.0]])
Matrix4([[1.0, 0.0, 0.0, 0.0], [0.0, 0.8660254037844387, -0.4999999999999999, 0.0], [0.0, 0.4999999999999999, 0.8660254037844387, 0.0], [0.0, 0.0, 0.0, 1.0]])

つづきはまた来週。明日は更新お休みします。

modo10-11ブログ目次



take_z_ultima at 11:30│Comments(0)modo | CG

この記事にコメントする

名前:
URL:
  情報を記憶: 評価: 顔   
 
 
 

Archives