デジタル・デザイン・ラボラトリーな日々

アラフィフプログラマーが数学と物理を基礎からやり直す。https://qiita.com/yaju

3Dを基礎から勉強する 外積

今度は外積を説明します。内積は高校で習うのに対して、外積は大学で数学または物理で習うようです。

外積とは何か
f:id:Yaju3D:20130526103215j:plain
外積は英語で"outer product"と書きますが、"cross product"(クロス積)とも呼ばれます。これは演算記号の「×」(クロス)に由来します。掛け合わせた数を意味する「積」は英語で"product"です。

外積の結果は複数の値=ベクトル(大きさと方向)となるため、2つの定義があります。
大きさではsinθが求まります。これは\vec{a}\vec{b}が作る平行四辺形の面積に等しいです。
\vec{a} \times \vec{b} = \mid \vec{a} \mid \mid \vec{b} \mid sin\theta
方向は下図のように\vec{a}\vec{b}が作る平面に垂直な方向を向いています。
\vec{a}=(a_1,a_2,a_3) , \vec{b}=(b_1,b_2,b_3) とすると 
\vec{a} \times \vec{b} = \mid (a_2b_3 - a_3b_2),(a_3b_1 - a_1b_3),(a_1b_2 - a_2b_1) \mid
f:id:Yaju3D:20130526152842j:plain

外積内積と違い\vec{a} \times \vec{b}\vec{b} \times \vec{a}と掛ける順番を逆にすると、大きさは同じだが、方向は逆になる。
\vec{a} \times \vec{b}が右手系で、\vec{b} \times \vec{a}が左手系となる。
下図は3次元直行座標系に方向を合わせてみました。Z軸が外積となります。

f:id:Yaju3D:20130526171408j:plain

何故、DirectXは左手系なのか?

左手系と右手系の2つある中でDirectXが左手系を選んだのはなぜなのでしょうか?私たちは小さい時から右方向がX軸、上方向がY軸の2Dのグラフを見てきました。そしてごく普通にアニメや漫画のキャラクタは上方向であるY軸に頭を向けて立ちます。さてこの状態で3Dになった時、キャラクタの目線は画面の奥に向かうのが自然でしょう。そうすれば、キャラクタの目線方向とプレーヤーの目線方向も合います。「前へ進め!」とボタンを押したとき、画面の奥に向かっていくのが自然なのです。Z軸が画面の奥へ進む座標系は『左手系』です。この自然な成り行きでDirectXなどの3Dゲームは左手系座標を採用しています。

http://marupeke296.com/DXG_No15_AttentionCoordinate.html

内積外積の違い
内積がcosθが求まるのに対して、外積はsinθが求まります。
内積の結果がスカラー値(大きさ)に対して、外積の結果はベクトル(向き、大きさ)となります。
内積は順番を逆にしても結果は同じに対して、外積では大きさは同じだが方向が逆になります。
内積は何次元でも同じように定義されますが、外積は3次元ベクトルでしか使えません。
※3次元ベクトルでしか使えない外積ですが、2次元の処理で(x,y,0)と3次元に拡張すれば使うことができます。

外積の使い道
外積の使い道は幾つかあります。
・左右の位置関係を知る
・三角ポリゴンの向き(法線ベクトル)を求める。
・平面上の三角形と点の内外判定
三角形の面積を求める。
・その他 参照:使える数学-外積
など

左右の位置関係について
下図を見てもらうと分かりますが、sinは±180度以上でマイナスの値になります。
外積の結果の符合を見ることで左右が分かります。
f:id:Yaju3D:20130526151945j:plain

ポリゴンの向き(法線ベクトル)について
ポリゴンの向きは、3角形の面の向きは視点に対する手前向きとするとイメージしやすいです。(右手系)
f:id:Yaju3D:20130526190410j:plain

面の法線ベクトル
三角ポリゴンは、3つの頂点の並びにより「面から垂直に出るベクトル」が計算できます。これが「面法線」といわれるものです。(三角形の面の中央から垂直の矢印が出るイメージです。)
f:id:Yaju3D:20140906192636j:plain
面の法線ベクトルは2つのベクトルの外積を計算することで求まります。
右手座標系では頂点の順番が左回りのP1,P3,P2 なので (P3 - P1) \times (P2 - P1)となります。
左手座標系では頂点の順番が右回りのP1,P2,P3 なので (P2 - P1) \times (P3 - P1)となります。
※右手座標系と左手座標系では、掛ける順番が違います。
※法線ベクトルは物体内側から物体外側に出るので、外から表面を見た場合は反転回りとなります。

この面法線ベクトル(n)と光源ベクトル(l)の角度を求めることで、面の明るさが求まります。
フラットシェーディング等に使われます。
f:id:Yaju3D:20130526212554j:plain
ベクトルの間の角度をθとします。面の明るさは、面が光の方向を向いているとき、つまりθが0度のときに最大となり、θが90度になると真っ暗になります。これをcosθで表すのがランベルトの法則(ランバート反射)です。

面の明るさ = cosθ

cosθを使うことで、θが0度のときには明るさが1、90度の時には明るさが0となります。cosθがとりうる値は-1~1です。
f:id:Yaju3D:20130525230936j:plain

■z座標が0のベクトルの外積
V1=(10,20, 0) 、V2=(30,40,0)のようにz成分が0とした場合、ベクトルがxy平面上にあることになり、その外積のベクトルはz軸と平行になるため、z成分に値が求まります。
\vec{a}=(10,20,0) , \vec{b}=(30,40,0) とすると 
\vec{a} \times \vec{b} = \mid (20\times0 - 0\times40),(0\times30 - 10\times0),(10\times40 - 20\times30) \mid
\vec{a} \times \vec{b} = \mid (0),(0),(-200) \mid
これは、2次元ベクトルの外積の結果と3次元ベクトルの外積のz成分の結果が同じとなります。