Blender ワンポイント情報?(説明が長くなってしまった…)
Blender には bones , edit_bones , pose.bones があり、それぞれ様々なマトリクスを持つ。
今回は edit_bones のマトリクスについて考える。
edit_bones のマトリクス関連の属性は以下1種類
・matrix:armature空間でのボーンの位置と回転(※)を示すマトリクス
※ head,y軸方向,roll を含み length,sizeは含まない
マトリクス全般に言えることだが、4x4 計16個の値は一定の規則を満たす必要があり、矛盾する値を設定するとblenderが不安定になる。
よって編集モード時は edit_bones の回転や位置を matrix ではなく、以下属性で指定する。
・head:head位置(armature空間)
・tail:tail位置(armature空間)
・roll:Boneのy軸周りの回転角
matrix と head , tail , roll は相互変換が可能だが、matrix には length,size の情報は含まれないので、相互変換する場合は matrix と以下属性をセットで考える必要がある。
・length:boneの長さ(変更するとtail位置が移動)
ところで matrix を使うと何ができるのかというと、edit_boneのlocal空間 と armature空間 の変換を行うことができる。
<変換例>
armature空間 = matrix @ edit_boneのlocal空間
head = matrix @ ( 0 , 0 , 0 ) # 原点 が headのローカル位置
tail = matrix @ ( 0 , b.length , 0 ) # 原点からy方向にlengthの位置 が tailのローカル位置
blenderのpythonコンソール で matrix,length と head,tail,roll の相互変換を確認してみる。
用意した関数は以下2種類。
・matrix_length_2_head_tail_roll
・head_tail_roll_2_matrix_length
( webから得られた情報を組み合わせて作ったが、今のところ正しい結果を得られている )
上記関数内では以下関数を利用しているため、古いBlenderでは利用できない場合がある。
・bpy.types.Bone.AxisRollFromMatrix
・bpy.types.Bone.MatrixFromAxisRoll
最後に roll について触れておく。
roll は y_axis 周りの回転だが、roll=0 の時 z_axis や x_axis がどの方向になるのかが今までわからなかった。が、最近判明したので説明する。
まず boneのy_axis が armature空間のY軸 と一致しているなら、roll = 0 の時 boneのz_axis と armature空間のZ軸方向 も一致している。この状態のboneをhead位置を中心に、x_axis と z_axis の平面上任意の軸( x_axis z_axis そのものとは限らない ) まわりに 0以上180未満の範囲で回転させた場合、y_axis が真反対となる場合を除き、1回の回転でbone を全ての方向に向けることができる。この時の x_axis,y_axis,z_axis の方向が roll=0の時の方向となる。
例外として 回転角度が180度の場合は、回転軸によらず y_axis は正反対を向くが、x_axis と z_axis は 回転軸次第で 一定に定まらない。
よって、回転角度が180度の場合のみ z_axis を回転軸とする。
Blender には bones , edit_bones , pose.bones があり、それぞれ様々なマトリクスを持つ。
今回は edit_bones のマトリクスについて考える。
edit_bones のマトリクス関連の属性は以下1種類
・matrix:armature空間でのボーンの位置と回転(※)を示すマトリクス
※ head,y軸方向,roll を含み length,sizeは含まない
マトリクス全般に言えることだが、4x4 計16個の値は一定の規則を満たす必要があり、矛盾する値を設定するとblenderが不安定になる。
よって編集モード時は edit_bones の回転や位置を matrix ではなく、以下属性で指定する。
・head:head位置(armature空間)
・tail:tail位置(armature空間)
・roll:Boneのy軸周りの回転角
matrix と head , tail , roll は相互変換が可能だが、matrix には length,size の情報は含まれないので、相互変換する場合は matrix と以下属性をセットで考える必要がある。
・length:boneの長さ(変更するとtail位置が移動)
ところで matrix を使うと何ができるのかというと、edit_boneのlocal空間 と armature空間 の変換を行うことができる。
<変換例>
armature空間 = matrix @ edit_boneのlocal空間
head = matrix @ ( 0 , 0 , 0 ) # 原点 が headのローカル位置
tail = matrix @ ( 0 , b.length , 0 ) # 原点からy方向にlengthの位置 が tailのローカル位置
blenderのpythonコンソール で matrix,length と head,tail,roll の相互変換を確認してみる。
用意した関数は以下2種類。
・matrix_length_2_head_tail_roll
・head_tail_roll_2_matrix_length
( webから得られた情報を組み合わせて作ったが、今のところ正しい結果を得られている )
上記関数内では以下関数を利用しているため、古いBlenderでは利用できない場合がある。
・bpy.types.Bone.AxisRollFromMatrix
・bpy.types.Bone.MatrixFromAxisRoll
# # 確認用コード # 表示が全て 0 なら確認OK # 属性によっては 1e-7程度 の演算誤差が発生する # import numpy # # matrix と length を head と tail と roll に変換する関数 def matrix_length_2_head_tail_roll( m , l ): a , r = bpy.types.Bone.AxisRollFromMatrix( m.to_3x3() ) h = m.translation t = a * l + h return h , t , r # # head と tail と roll を matrix と length に変換する関数 def head_tail_roll_2_matrix_length( h , t , r ): a = t - h l = a.length m = Matrix().Translation( h ) @ bpy.types.Bone.MatrixFromAxisRoll( a , r ).to_4x4() return m , l # # 一致確認用関数 ( 各要素の差を取り、最も大きい値を表示 ) def f(p,q):return max([abs(a-b) for a,b in zip(numpy.ravel(p),numpy.ravel(q))]) # # editモードに変更 _ = bpy.ops.object.mode_set( mode = 'EDIT' ) # # 選択されたedit_boneを取得 b = bpy.context.active_bone # # matrix_length_2_head_tail_roll の確認 h1 , t1 , r1 = matrix_length_2_head_tail_roll( b.matrix , b.length ) print( f"name { b.name }" ) print( f"head1 {f( b.head , h1 )}" ) print( f"tail1 {f( b.tail , t1 )}" ) print( f"roll1 {f( b.roll , r1 )}" ) # # head_tail_roll_2_matrix_length の確認 m1 , l1 = head_tail_roll_2_matrix_length( b.head , b.tail , b.roll ) print( f"mat {f( b.matrix , m1 )}" ) print( f"len {f( b.length , l1 )}" ) # # boneの local空間 から armature空間 への変換の確認 h2 = b.matrix @ Vector((0,0,0)) t2 = b.matrix @ Vector((0,b.length,0)) print( f"head2 {f( b.head , h2 )}" ) print( f"tail2 {f( b.tail , t2 )}" )
最後に roll について触れておく。
roll は y_axis 周りの回転だが、roll=0 の時 z_axis や x_axis がどの方向になるのかが今までわからなかった。が、最近判明したので説明する。
まず boneのy_axis が armature空間のY軸 と一致しているなら、roll = 0 の時 boneのz_axis と armature空間のZ軸方向 も一致している。この状態のboneをhead位置を中心に、x_axis と z_axis の平面上任意の軸( x_axis z_axis そのものとは限らない ) まわりに 0以上180未満の範囲で回転させた場合、y_axis が真反対となる場合を除き、1回の回転でbone を全ての方向に向けることができる。この時の x_axis,y_axis,z_axis の方向が roll=0の時の方向となる。
例外として 回転角度が180度の場合は、回転軸によらず y_axis は正反対を向くが、x_axis と z_axis は 回転軸次第で 一定に定まらない。
よって、回転角度が180度の場合のみ z_axis を回転軸とする。