サイトトップ

Director Flash 書籍 業務内容 プロフィール

ActionScript 3.0 for 3D

Column Math02 四元数(クォータニオン)
「四元数(しげんすう)」とは「クォータニオン(quaternion)」とも呼ばれ、ひとつの実数(スカラー)とひと組の3次元べクトルで表される数です。3次元べクトルは3つの要素で成立ちますので、ひとつのスカラーと計4つの数(元)で構成されるため、この名がついたのでしょう。

四元数は、4次元べクトルとしての性質をもちます。しかし、それに加えて、ベクトルにはない乗法が定義されています。とくに、四元数の乗算で、3次元座標空間における回転を表せることが特長です。このコラムでは、抽象的で捉えにくい四元数の概略を知っていただくことが主眼です。そのため、細かな計算や証明は省きます。


複素数
四元数は、複素数を拡張した数と捉えることができます。そこで、四元数を説明する前に、複素数について簡単におさらいしておきましょう。複素数は、実数にないiという虚数単位を用いて表します。iは2乗すると-1になります。

i2 = -1

任意のふたつの実数x、yに対して、複素数zはつぎの式で示されます。このときxとyを、それぞれ複素数zの「実部」ならびに「虚部」といいます。

z = x + iy

任意の実数は、数直線上の点で示せます。これに対して、複素数は、実部を横軸(実軸)、虚部を縦軸(虚軸)とする平面で表されます。この平面は「ガウス平面」あるいは「複素平面」と呼ばれます(図MathC2-001)。また逆に、平面上の任意の点は、複素数に対応させることができます。

図MathC2-001■ガウス平面で複素数を示す
図MathC2-001
任意の複素数z = x + iyは、実軸と虚軸との直交座標からなるガウス平面で表せる。

平面上の座標が表せるという点では、複素数は2次元のベクトルと似ています。しかし、ベクトルとは異なり、複素数は四則演算ができます。とくに、その乗算は座標の回転を表せます。任意の複素数zをガウス平面上で、原点から反時計回りにθ回転させるには、つぎの複素数を掛合わせます(図MathC2-002)。この結果は、三角関数の加法定理を使って確かめられます(Tips MathC2-001「複素数のガウス平面における回転」参照)。

cosθ + i sinθ
図MathC2-002■cosθ + i sinθの乗算は座標をθ回転させる
図MathC2-002
任意の複素数zをガウス平面上で、原点から反時計回りにθ回転させるには、複素数cosθ + i sinθを掛合わせる。

Tips MathC2-001■複素数のガウス平面における回転
ガウス平面上において、任意の複素数zの原点からの距離がrで実軸となす角がθのとき、zは三角関数を使ってつぎのように表せます(図MathC2-003。なお、Math01-01「角度を座標にする三角関数sinとcos」参照)。

z = r(cosθ + i sinθ)
図MathC2-003■ガウス平面上の複素数を距離rと角度θで表す
図MathC2-003
任意の複素数zの原点からの距離がrで実軸となす角がθのとき、z = r(cosθ + i sinθ)と表せる。

そこで、この複素数zに複素数cosφ + i sinφを掛合わせると、zの座標が原点から反時計回りにさらにφ回転することを示します。

z(cosφ + i sinφ)
= r(cosθ + i sinθ)(cosφ + i sinφ)
= r((cosθ cosφ - sinθ sinφ) + i(sinθ cosφ + cosθ sinφ))

ここで、三角関数の加法定理より以下の等式が成立ちました(シンタックスMath01-011)。

cos(θ+φ) = cosθ cosφ - sinθ sinφ
sin(θ+φ) = sinθ cosφ + cosθ sinφ

これを前述の式に代入すると、つぎの関係が導かれます。

z(cosφ + i sinφ) = r(cos(θ+φ) + i sin(θ+φ))

これは、原点からの距離がrで実軸となす角がθの任意の複素数zに複素数cosθ + i sinθを乗じると、原点からの距離がr、実軸となす角がθ+φの座標に変換されたことを示します。つまり、原点からの距離はそのまま、角度が反時計回りにさらにφ回転されたということです。

[*筆者用参考] Wikipedia「複素数」、複素数の基礎「複素平面」、高校の数学「複素数」。


四元数の定義
四元数には、虚数iと似たjとkという単位が加わります。これらはすべてiと同じく、2乗すると-1になります。

i2 = j2 = k2 = -1

四元数も複素数と同じように、四則演算ができます。ただし、乗法の交換法則は成立ちません。3つの単位の乗算結果は、つぎのように定義されています。

ij = k、ki = j、jk = i
ji = -k、ik = -j、kj = -i

これら3つの単位を用いて、任意の四元数Qは実数t、x、y、zに対してつぎのように表されます。このとき、tを実部、x、y、zの項を合わせて虚部といいます。

Q = t + ix + jy + kz

四元数Qは、虚部と実部を分けて、つぎのように表すことがあります。

Q = (t; x, y, z)

虚部は3つの値から成立つので、3次元ベクトルV = (x, y, z)と捉えられます。すると、四元数Qは、つぎのようベクトルを用いて示すこともできます。なお、実部をスカラー部、虚部はベクトル部と呼ぶこともあります。

Q = (t; V)

四元数Q = t + ix + jy + kzの絶対値|Q|は、以下のように定義されます。よって、|Q| = 0となるのは、t = x = y = z = 0のときだけです。

____________
|Q| = √ t2 + x2 + y2 + z2

また、「共役四元数」Q*というものが、つぎのように定義されています。

Q* = t - ix - jy - kz

四元数Qとその共役四元数Q*との積は、計算すると絶対値|Q|の2乗になります(Tips MathC2-002「四元数と共役四元数との積」参照)。

QQ* = Q*Q = t2 + x2 + y2 + z2
シンタックスMathC2-001■四元数の定義と絶対値および共役四元数
四元数の定義

四元数Qは、以下に示す単位i、k、jを用いて、実数t、x、y、zに対してつぎの式で定められる。

Q = t + ix + jy + kz

3つの単位i、j、kは、つぎのような演算規則を満たす。乗法の交換法則は成立たない。

i2 = j2 = k2 = -1
ij = k、ki = j、jk = i
ji = -k、ik = -j、kj = -i

四元数Qは、実部(スカラー部)tと虚部(ベクトル部)V = (x, y, z)とを分けて、つぎのようも表される。

Q = (t; x, y, z) = (t; V)
四元数の絶対値

四元数Q = t + ix + jy + kzの絶対値|Q|は、以下のように定められる。t = x = y = z = 0のときのみ、|Q| = 0となる。

____________
|Q| = √ t2 + x2 + y2 + z2
共役四元数

四元数Qの共役四元数をQ*で表し、つぎのように定められる。

Q* = t - ix - jy - kz

四元数Qとその共役四元数Q*との積は、絶対値|Q|の2乗になる。

QQ* = Q*Q = t2 + x2 + y2 + z2

Tips MathC2-002■四元数と共役四元数との積
次項「四元数の計算」でご紹介するベクトル表現の乗算を行うと、つぎのようにすっきりと計算できます。

QQ* = (t; V) (t; -V)
= (t2 - V・(-V); tV - tV + V×(-V))
= (t2 - |V|2; 0)
= t2 - |V|2

虚部が消えて実部のみ、つまり実数になるため、乗算の順序を入替えてQ*Qとしても同じ値になります。

[*筆者用参考] 物理のかぎしっぽ「四元数」、Wikipedia「四元数」、「70秒で分る、使える、四元数・4元数・クォータニオン・ Quaternionで回転」、「クォータニオンを学んでみよう!」、「四元数の数学的意味」。


四元数の計算
ふたつの四元数P = s + iu + jv + kwとQ = t + ix + jy + kzの計算についてご説明します。まず、加減算P±Qは単純で、実部と虚部を単位ごとにそれぞれ足し引きします。

P + Q = (s + iu + jv + kw)±(t + ix + jy + kz)
= (s±t) + i(u±x) + j(v±y) + k(w±z)

ベクトルを用いてP = (s; U)およびQ = (t; V)とすると、もっと簡潔に表せます。

P + Q = (s; U)±(t; V)
= (s±t; U±V)

つぎに、乗算は項数が多いので、少し手間がかかります。ふたつの四元数の積PQは、以下のとおりです。すでに述べたように、四元数の乗法は交換法則が成立たないことにご注意ください。

PQ = (s + iu + jv + kw)(t + ix + jy + kz)
= (st - ux - vy - wz) + i(sx + ut + vz - wy) + j(sy - uz + vt + wx) + k(sz + uy - vx + wt)

ベクトル表現にすると、ベクトルの演算を用いて、乗算も簡潔に表すことができます。なお、ベクトルUとVとの計算で、U・Vは内積、U×Vは外積を意味します(シンタックスMath02-004およびシンタックスMath02-005)。

PQ = (s; U)(t; V)
= (st - U・V; sV + tU + U×V)
シンタックスMathC2-002■四元数の加減算と乗算
四元数の加減算

ふたつの四元数P = s + iu + jv + kwとQ = t + ix + jy + kzとすると、加減算P±Qは実部と虚部を単位ごとにそれぞれ足し引きする。

P + Q = (s±t) + i(u±x) + j(v±y) + k(w±z)

ベクトルを用いてP = (s; U)およびQ = (t; V)とすれば、P±Qはつぎの式で表せる。

P + Q = = (s±t; U±V)
四元数の乗算

ふたつの四元数P = s + iu + jv + kwとQ = t + ix + jy + kzの積PQは、以下のとおり。四元数の乗法は交換法則が成立たない。

PQ = (st - ux - vy - wz) + i(sx + ut + vz - wy) + j(sy - uz + vt + wx) + k(sz + uy - vx + wt)

ベクトルを用いてP = (s; U)およびQ = (t; V)とすれば、PQはつぎの式で表せる。

PQ = (st - U・V; sV + tU + U×V)

四元数による3次元座標空間の回転
四元数を用いると3次元座標空間の回転が簡潔に表せ、行列を使うより計算も楽になります。

まず、3次元座標空間における任意の点は、3次元位置ベクトルP = (x, y, z)で示せます。この3次元ベクトルは、以下のようにスカラー部を0とした四元数で表します。

X = (0; P)

つぎに、回転の軸となる任意の単位ベクトルU = (u, v, w)を定めます。単位ベクトルですので|U| = 1です(シンタックスMath02-003)。このとき、位置ベクトルPを回転軸Uで角度θ回した座標P'は、つぎのような四元数Qとその共役四元数Q*を使って、四元数X' = (0; P')のベクトル部P'として求めることができます(図MathC2-004)。

Q = (cos(θ/2); sin(θ/2)U)

X' = QXQ*

図MathC2-004■軸とする任意の単位ベクトルUにより位置ベクトルPをθ回転させる
図004
任意の単位ベクトルUを軸に定めて、その軸で位置ベクトルPを角度θ回転する。

このX'をさらに別の単位ベクトルU'でφ回転させたいときは、同じように四元数Rを使って共役四元数R*と挟み込んで乗算します。

R = (cos(φ/2); sin(φ/2)U')

X'' = RX'R* = RQXQ*R*

このように四元数による3次元座標空間の回転では、直交座標のxyz軸にかぎらず、任意のベクトルを軸に指定できます。また、3次元座標空間の回転などを扱う変換行列が4×4の計16成分で構成されるのに対して、四元数は4つの値だけで回転を表すことができます。そのため、演算の処理効率は高くなります。ただ、四元数を構成する値の意味が、直感的にわかりにくいという難点もあります。

Tips MathC2-003■xyz各軸による回転を表す四元数
xyz各軸の単位ベクトルは、それぞれUx = (1, 0, 0)、Uy = (0, 1, 0)、Uz = (0, 0, 1)です。したがって、各軸による角度θの回転を表す四元数は、つぎのとおりです。

x軸: (cos(θ/2); sin(θ/2)Ux) = (cos(θ/2); sin(θ/2), 0, 0)
y軸: (cos(θ/2); sin(θ/2)Uy) = (cos(θ/2); 0, sin(θ/2), 0)
z軸: (cos(θ/2); sin(θ/2)Uz) = (cos(θ/2); 0, 0, sin(θ/2))

ActionScript 3.0で使われる四元数
ActionScript 3.0には、四元数をつくりその演算を行うというクラスはありません。ただ、Matrix3Dクラスに回転の四元数表現を扱うメソッドとして、Matrix3D.decompose()Matrix3D.recompose()が備わっています(シンタックス04-011)。

Maniac! MathC2-001■Matrix3D.interpolate()とMatrix3D.interpolateTo()メソッドにおける四元数
[ヘルプ]の[Matrix3D]クラスを探すと、Matrix3D.interpolate()Matrix3D.interpolateTo()メソッドも、四元数について触れています。しかし、これらのメソッドでは、四元数が内部的な処理として使われていることを説明しているだけです。

前者は、Matrix3Dインスタンスの変換行列から、平行移動、回転、伸縮の各設定値をVector3Dがベース型のVectorインスタンスとして取出すメソッドです。後者のメソッドは、逆に平行移動、回転、伸縮の各設定値をVectorインスタンスのVector3Dエレメントとして納めて、Matrix3Dインスタンスに設定します(04-04「Matrix3Dクラスのその他のメソッド」の「Matrix3D.decompose()とMatrix3D.recompose()メソッド」参照)。

これらのメソッドを使うとき、方向スタイルの引数として定数Orientation3D.QUATERNIONを指定すると、回転の設定となるVector3Dオブジェクト(Vectorインスタンスのエレメント1)のプロパティ値が四元数として計算されます。

たとえば、y軸による60度(π/3ラジアン)の回転を四元数表現で取出してみましょう。つぎのスクリプトMathC2-001は、Matrix3Dインスタンスに60度回転(Matrix3D.appendRotation()メソッド)の変換を加えたうえで、Matrix3D.decompose()メソッドで回転の設定となるVector3Dインスタンスを取出し、その値を[出力]して確かめます。

スクリプトMathC2-001■回転したMatrix3Dインスタンスから回転の四元数表現の値を調べる
    // フレームアクション
  1. var myMatrix3D:Matrix3D = new Matrix3D();
  2. myMatrix3D.appendRotation(60, Vector3D.Y_AXIS);
  3. var myVector:Vector.<Vector3D> = myMatrix3D.decompose(Orientation3D.QUATERNION);
  4. var myRotation:Vector3D = myVector[1];   // 回転の四元数表現となるVector3D取得
  5. trace(myRotation.w, myRotation);

スクリプト第3〜4行目で、Matrix3D.decompose()メソッドが返す数値ベース型のVectorインスタンスを得て、そのインデックス1に納められた回転を表すVector3Dオブジェクトを取出します。メソッドには定数Orientation3D.QUATERNIONを渡したので、回転のVector3Dオブジェクトのプロパティ値は四元数として計算されています。

そして、スクリプト第5行目は、そのVector3DオブジェクトのVector3D.w プロパティの値とプロパティ(x, y, z)で表される3次元ベクトルを[出力]します。[出力]パネルに表示されるのは、つぎのような値です。

0.8660253882408142 Vector3D(0, 0.4999999701976776, 0)

まず、ひとつ目の数であるVector3D.wプロパティの約0.866という値はcos(π/6) = √3/2に当たります。つぎに、ふたつ目のVector3Dオブジェクトの3次元空間座標のうちy座標値となる約0.5はcos(π/6)と等しくなっています。

前項で述べた四元数の回転を表す式によれば、y軸に平行な単位ベクトルUy = (0, 1, 0)を軸とする角度π/3の回転はつぎのように求められます。

(cos(π/3/2); sin(π/3/2)Uy) = (cos(π/6); sin(π/6)Uy) = (cos(π/6); 0, sin(π/6), 0)

よって、前掲スクリプトMathC2-001で[出力]された値は、y軸による角度π/3の回転を表す四元数と一致します。

Maniac! MathC2-002■[ヘルプ]のVector3D.wプロパティの項における四元数の説明
[ヘルプ]の[Vector3D]クラスで「Vector3D.wプロパティ」の項を読むと、つぎのようなくだりがあります。しかし、これは四元数についての説明ではなさそうです。

四元数表記では、3次元回転の計算の4番目のエレメントとして角度が使用されます。wプロパティを使用すると、Vector3Dオブジェクトの回転角度を定義できます。回転角度と座標(x, y, z)の組み合わせにより、表示オブジェクトの方向が決まります。

本文でご説明したとおり、四元数表現におけるVector3D.wプロパティの値はスカラー部です。角度θの回転を表す四元数Qはベクトル部の単位ベクトルUにも三角関数が乗じられていますので、回転角θによって成分値が変わります。スカラー部だけで角度を定めているとはいいにくいでしょう。

Q = (cos(θ/2); sin(θ/2)U)

上記に引用した[ヘルプ]の説明は、むしろ軸角度による指定に当てはまるように思われます(Column 04「3次元座標空間における回転について」の「軸角度による回転」参照)。試しに、前掲スクリプトMathC2-001の第3行目を、つぎのように軸角度(定数Orientation3D.AXIS_ANGLE)の指定に書替えてみます。

  1. // var myVector:Vector.<Vector3D> = myMatrix3D.decompose(Orientation3D.QUATERNION);
    var myVector:Vector. = myMatrix3D.decompose(Orientation3D.AXIS_ANGLE);

すると、[出力]される値は、以下のように変わります。ひとつ目のVector3D.wプロパティの値である約1.05はπ/3に当たり、まさに回転角度を表します。そして、ふたつ目のVector3Dの3次元座標が示すベクトルは、多少の誤差を含むものの、回転したy軸の単位ベクトルUy = (0, 1, 0)です。

1.0471975803375244 Vector3D(0, 0.9999998807907104, 0)

[Prev/Next]


作成者: 野中文雄
作成日: 2010年4月3日


Copyright © 2001-2010 Fumio Nonaka.  All rights reserved.