しおんの部屋

3DCG とか スクリプト とか…

Quaternion の積の展開[Blender 3DCG]

2020年04月17日 | Blender Python
肩のポージングは難しい[Blender 3DCG] で予告したが、方向を変えないで quaternion の Y=0 にするための計算方法方法について数回に分けて説明しようと思う。

まずは最も基本となる quaternion の積から始める。
webを見れば展開後の式が見つかるのだが…
色々と方向性を探る段階で ある程度 自力で展開してみたので、その過程を示す。
とは言っても…詳しい理論に踏み込む気はない ( 本質的には理解できていない^^; )

Quaternion(w,x,y,z)は、ijk=ii=jj=kk=-1 を満たす 基底元i,j,k を用いて w+xi+yj+zk と示せる。
この時 quaternion の積の展開は、一般的な積の展開に近い形で行うことができる。
但し、基底元i,j,k は掛ける順序が重要であるため、展開時 i,j,k を掛ける順序を崩してはいけない。
w,x,y,z は実数なので、掛ける順序を入れ替えても問題ない。

実際に積の展開を行う前に、基底元の積についてマトリクスを作っておく。
マトリクスの全要素は、ijk=ii=jj=kk=-1 から、以下の手順で導き出すことができる。
 ijk=-1
 →(右側からkを掛ける)ijkk=-k   →(kkを-1に置き換える)ij=k 
 →(左側からiを掛ける) iij=ik   →(iiを-1に置き換える)-j=ik
 →(右側からkを掛ける) -jk=ikk  →(kkを-1に置き換える)jk=i 
 →(左側からjを掛ける) jjk=ji   →(jjを-1に置き換える)-k=ji
 →(右側からiを掛ける) -ki=jii  →(iiを-1に置き換える)ki=j 
 →(左側からkを掛ける) kki=kj   →(kkを-1に置き換える)-i=kj
基底元の積のマトリクス としてまとめると…
     i_     j_     k_    
 _i  ii=-1  ji=-k  ki= j 
 _j  ij= k  jj=-1  kj=-i 
 _k  ik=-j  jk= i  kk=-1
このマトリクスを使用して、Quaternion( w,x,y,z ) と Quaternion( o,p,q,r )の積を展開する。
  ( w+xi+yj+zk )( o+pi+qj+rk )
  
  =   wo   + xo i  + yo j  + zo k 
    + wp i + xp ii + yp ji + zp ki
    + wq j + xq ij + yq jj + zq kj
    + wr k + xr ik + yr jk + zr kk
  
  =   wo   + xo i + yo j + zo k
    + wp i - xp   - yp k + zp j
    + wq j + xq k - yq   - zq i
    + wr k - xr j + yr i - zr  
  
  =   wo   - xp   - yq   - zr  
    + wp i + xo i + yr i - zq i
    + wq j - xr j + yo j + zp j
    + wr k + xq k - yp k + zo k
  
  =   ( wo-xp-yq-zr )
    + ( wp+xo+yr-zq )i
    + ( wq-xr+yo+zp )j
    + ( wr+xq-yp+zo )k
以上より Quaternion の積の展開結果は以下となる。
  (w,x,y,z)(o,p,q,r)
  =( wo-xp-yq-zr 
   , wp+xo+yr-zq 
   , wq-xr+yo+zp 
   , wr+xq-yp+zo )
実際に Blender2.8 の Pythonコンソール で試算してみる。
q3 が 今回の展開結果から計算した値だが、 q1 と q2 の積 ( q1 @ q2 )と一致している事がわかる。
--Python--

q1 = bpy.data.objects['Armature'].pose.bones["Bone1"].rotation_quaternion
q2 = bpy.data.objects['Armature'].pose.bones["Bone2"].rotation_quaternion
w,x,y,z = q1
o,p,q,r = q2
q3 = Quaternion((
        w*o-x*p-y*q-z*r,w*p+x*o+y*r-z*q,w*q-x*r+y*o+z*p,w*r+x*q-y*p+z*o))

print( "q1       =" , q1       )
print( "q2       =" , q2       )
print( "q3       =" , q3       )
print( "q1@q2    =" , q1@q2    )
print( "q1@q2-q3 =" , q1@q2-q3 )

--実行結果--

q1       = <Quaternion (w=0.6884, x="0.7204," y="0.0192," z="0.0822)">
q2       = <Quaternion (w=0.6750, x="0.6885," y="-0.1859," z="-0.1893)">
q3       = <Quaternion (w=-0.0122, x="0.9719," y="0.0779," z="-0.2220)">
q1@q2    = <Quaternion (w=-0.0122, x="0.9719," y="0.0779," z="-0.2220)">
q1@q2-q3 = <Quaternion (w=0.0000, x="0.0000," y="0.0000," z="-0.0000)">

コメント    この記事についてブログを書く
  • X
  • Facebookでシェアする
  • はてなブックマークに追加する
  • LINEでシェアする
« 肩のポージングは難しい[Blen... | トップ | Quaternion の回転式の展開[B... »

コメントを投稿

ブログ作成者から承認されるまでコメントは反映されません。

Blender Python」カテゴリの最新記事