【Unity道場スペシャル 2017博多】クォータニオン完全マスター
-
Upload
unitytechnologiesjapan -
Category
Technology
-
view
9.190 -
download
1
Transcript of 【Unity道場スペシャル 2017博多】クォータニオン完全マスター
クォータニオン完全マスター
ユニティ・テクノロジーズ・ジャパン合同会社
安原祐二
Unity スクリプトリファレンスより抜粋
座標変換
CG
オイラー角
複素数
クォータニオン本セッションの旅程
座標変換
CGのきほん
たくさんの点を動かす!
© Unity Technologies Japan/UCL
P(1, 2)
x
y
二次元座標
P’(-2, 1)
x
y
P(1, 2)
P(1, 2) P’(-2, 1)
ある変換で点を移動
変換
ある変換=なんらかのルール
同じ変換でたくさんの点を移動
Q(2, 0) Q’(0, 2)変換
P(1, 2) P’(-2, 1)変換
R(1, 1) R’(-1, 1)変換
こういう式にしてみよう
x’ = ax + by
y’ = cx + dy
P’(x’, y’) = [変換]P(x, y)
x’ = ax + by
y’ = cx + dy
x’ = 1x + 0y
y’ = 0x + 1y
a=1 b=0 c=0 d=1 なら
x’ = x
y’ = y変化しない変換
色々できそう!
色々できそう!x’ = ax + by
y’ = cx + dy
x’ = 1x + 0y
y’ = 0x + 1y
a=1 b=0 c=0 d=1 なら
x’ = x
y’ = y変化しない変換
x’ = 0x + 1y
y’ = 1x + 0y
a=0 b=1 c=1 d=0 なら
x’ = y
y’ = xxy入れ替え変換
abcdをまとめてしまおうx’ = ax + by
y’ = cx + dy
a b
c d( )
これを行列と呼ぶ!
変換を行列Mとして
P(1, 2) P’(-2, 1)変換
P’=MP
P’(x’, y’) = [変換]P(x, y)
a b
c d( )P’= P
変換を行列Mとして
P(1, 2) P’(-2, 1)変換
P’=MP
P’(x’, y’) = [変換]P(x, y)
(
行列に点ベクトルを掛ける
a b
c d( )=
a b
c d( ) 1
2)=)(-2
1
x’ = ax + by
y’ = cx + dy
-2 = a1 + b2
1 = c1 + d2
例えば
)(x’
y’ (x
y)
-2 = a1 + b2
1 = c1 + d2
行列に点ベクトルを掛ける
-2 = a1 + b2
1 = c1 + d2
1
2( )a b
c d( ) 1=)(-2
1 2
1
2
+
+
三次元では3x3行列になるx’ = ax + by + cz
y’ = dx + ey + fz
a b c
d e f
g h i( )
z’ = gx + hy + iz
概念は同じなので以降も二次元で続けます
いろいろな行列
2 0
0 2( ) 2倍に拡大スケーリング行列
cosθ -sinθ
sinθ cosθ( ) θ回転する回転行列
デモ
x
y
あれ?移動は?
行列の値をどう工夫しても移動はできない!
x’ = ax + by
y’ = cx + dy
x’ = ax + by + s
y’ = cx + dy + t
移動するために式を変更
これで(s,t)で移動できる
追加!
移動を実現するために行列を拡張
a b s
c d t( )
a b
c d( )
a b s
c d t
0 0 1( )
何かと都合がいいので3x3 にする
x’ = ax + by + s
y’ = cx + dy + t
行と列の数が同じ正方行列と呼ぶ
デモ
三次元でも同様にして移動を実現
つまり三次元では4x4行列を使う
a b c s
d e f t
g h i u
0 0 0 1)(
x’
y’
z’
1( ) =
x
y
z
1( )
a b s
c d t
0 0 1( )
二次元用3x3行列の各部分の役割
回転 移動
a b c s
d e f t
g h i u
0 0 0 1)(
回転 移動
三次元用4x4行列の各部分の役割
回転 移動
三次元用4x4行列の各部分の役割
transform.rotation transform.position
Quaternionクォータニオンで作る
Vector3ベクトル
で作る
a b c s
d e f t
g h i u
0 0 0 1)(
異なる変換をいくつも重ねる
これを点ごとに計算するのはたいへん…
P’=(○(○(○(○P))))
いくつも変換する場合は事前に計算しておける
点ごとにMを掛ければ済む
P’=MP
P’=○○○○P
P’=(○(○(○(○P))))
M=○○○○を事前に計算して…
座標変換
CG
オイラー角
複素数
クォータニオン
CGに応用する行列
3つの変換行列
• モデル行列
• ビュー行列
• プロジェクション行列
すべての変換前モデリングした物体の座標
データにはこの座標が格納されている
この変換がモデル行列
Transformで移動・回転
シーンにはカメラがある
カメラ
Transformで移動・回転
z
カメラが原点・ゼロ回転になるように変換
この変換がビュー行列
空間全体をモニタの位置に合わせる!
z
画角や near, far を処理w に z を格納など…
この変換がプロジェクション行列
Unity組み込みシェーダUnityShaderVariables.cginc より抜粋
M:モデル V:ビュー P:プロジェクション
モニタに映すための透視変換
この変換は行列ではなく奥行きで割る
遠くのものを小さく!
透視変換のようす
座標変換
CG
オイラー角
複素数
クォータニオン
オイラー角方式
二次元の回転はシンプル
回転軸はひとつcosθ -sinθ
sinθ cosθ( ) θ回転の回転行列
三次元では3軸の回転量をそれぞれ記述
あらゆる姿勢を表現可能これがオイラー角方式
x
y
z
直感的!
Unity の Inspector のRotation は…
表示に関してはオイラー角方式
P’=YXZP
X X軸まわりの回転行列
Y Y軸まわりの回転行列
Z Z軸まわりの回転行列
オイラー角方式の回転には順番がある
UnityはZYXの順番
プログラム例:オイラー角で作った回転を代入
transform.rotation = Quaternion.Euler(x, y, z);
①
②
③
変換を3回重ねている
座標変換
CG
オイラー角
複素数
クォータニオン
複素数と複素平面
クォータニオンは複素数の拡張
問題
は虚数単位
虚数の定義
虚数単位
複素数
:実部:虚部
2
1
普通の平面
P(1, 2)
x
y
実軸
虚軸
1+2i
1
2
複素平面
実軸
虚軸
半径1の円周上の点を考える
単位円と呼ぶ
実軸
虚軸
1+0i つまり 1
実軸
虚軸
-1+0i つまり -1
1
実軸
虚軸0+i つまり i
-1 1
実軸
虚軸
0-i つまり -i
-1 1
i
実軸
虚軸
-1 1
i
-i
実軸
虚軸
-1 1
i
-i
45°
実軸
虚軸
cos45°-1 1
i
-i
45°
sin45°
実軸
虚軸
cos45°+isin45°
-1 1
i
-i
45°
cos45°
sin45°
0.7+0.7iぐらい
実軸
虚軸
cosθ+isinθ
-1 1
i
-i
θ
cosθ
sinθ
重大な事実
単位円上の点は回転だった
実軸
虚軸
-1 1
i
-i
ゼロ回転
実軸
虚軸
-1 1
i
-i
180°回転
実軸
虚軸90°回転
-1 1
i
-i
実軸
虚軸
270°回転
-1 1
i
-i
実軸
虚軸
-90°回転
-1 1
i
-i270°と-90°は同じ意味
もしくは
もっと重大な事実
点と点を掛けると回転する
虚数の性質
実軸
虚軸i
-1 1
i
-i
i は90°回転
実軸
虚軸i
-1 1
i
-i
i は i をさらに90°回転
2
つまりi = -12
実軸
虚軸
-1 1
i
-i
-1
-1をさらに180°回転
つまり(-1) = 12
実軸
虚軸
0.7+0.7i
-1 1
i
-i
実軸
虚軸0.98i
-1 1
i
-i
0.7+0.7i
θ実軸
虚軸
cosθ+isinθ
-1 1
i
-i
(cosθ+isinθ)2回転角を足す
と複素数を掛ける
は同じ意味!
cos2θ+isin2θ
=
2θ
ところで…
この方程式を解いてみよう
実軸
虚軸
-1 1
i
-i
実軸
虚軸
-1 1
i
-iから正三角形!
120°
座標変換
CG
オイラー角
複素数
クォータニオン
クォータニオン
考案者はハミルトン(William Rowan Hamilton 1805-1865)
「複素平面の三次元版は作れないものか…」
虚軸を3つにすればうまくいく!
iが虚数単位
クォータニオン複素数
i, j, kが虚数単位
i =-12 i =-12 j =-12 k =-12
ij=k jk=i ki=jji=-k kj=-i ik=-j
驚愕のアイデア!
クォータニオンは複素数の三次元版
a+ib a+ib+jc+kd
クォータニオン複素数
複素数の要素はふたつクォータニオンの要素は4つ
クォータニオン要素をx, y, z, w とする
ix+jy+kz+w
(x, y, z, w)
実部虚部
複素平面の回転軸は固定だった
立体の場合
(x, y, z)
ix+jy+kz+w
(x, y, z, w)
実部虚部
回転軸が虚部のベクトル
複素数の回転とクォータニオンの回転
cosθ+isinθ
複素数
cosー+nsinー2 2
θ θ
n=inx+jny+knz
n(nx, ny, nz)は回転軸のベクトル
クォータニオン
重大な事実
あらゆる回転はひとつの軸回転で表現できる
そしてクォータニオンは軸回転を表現する
クォータニオンなら一発で決まる!
あらゆる回転はひとつの軸回転で表現できる
クォータニオンのテクニック
便利なテクニックSlerp (Spherical Linear Interpolation):球面線形補間
transform.rotation =
Quaternion.Slerp(transform.rotation,
target_rotation,
0.1f);
現在の値
目標の値
適当な率
凝ったテクニックバネトルク
目標との差分に比例したトルクをかける
基本戦略:目標への差分を求めて、トルクに変換する
差分クォータニオンの求めかた
差分=目標の値×現在の値-1
実演バネトルク実装例
4要素の符号を反転しても同じ回転になる
(x, y, z, w)
(-x, -y, -z, -w)
実は回転の方向が異なる
(x, y, z, w)
(-x, -y, -z, -w)
バネトルクを完成させるテクニック
wが負のときに反転すると短い方の回転になる
(x, y, z, w)
(-x, -y, -z, -w)
修正済みコード
追加
var rot = Quaternion.LookRotation(diff);
第二引数に Vector.up が省略されている
var up = transform.TransformVector(Vector3.up);
var rot = Quaternion.LookRotation(diff, up);
自分の姿勢から upベクトルを作る
水平を維持しないテクニック
修正済みコードその2
追加
デモ
このあと学習を続けるなら…
• トルクや物理を詳しく知りたい→Unity道場札幌講演をぜひ!https://www.youtube.com/watch?v=FqjM9oujyNE&feature=youtu.be
• クォータニオンの応用例を知りたい→Unite2017Tokyoをぜひ!https://www.youtube.com/watch?v=6EtTI5xC524 27分あたりから
• なんで と、 になるのか気になる→ ブログ「クォータニオンで回転を表現する定義にθ/2が使用される理由」をぜひ!http://qiita.com/yuji_yasuhara/items/a5b7c489e1d521adbd72
θ
2cosー+nsinー
2
θ
2
θー
参考:Inverse自前実装
虚部を反転するだけで逆クォータニオン
実軸
虚軸
-1 1
i
-i
マメ知識
逆変換は虚部の符号を反転
共役複素数と呼ぶ
おしまい