プチメタ3.0

刺激を受けた物事に対する感想や考察、自己成長や資産運用、ゲーム作りに関することなど。


3Dゲームではあらゆる判定でコサイン(内積)が役に立つ


サイン・コサインなどの三角関数
ゲーム開発で非常によく使われるが、
3Dゲームの場合は特にコサインが役に立つ。
これはコサインでベクトルの影の長さを求められるからだ。

内積を利用してベクトルの影の長さを求める


コサインを使えば直角三角形の底辺の長さがわかるが、
その計算式は「斜辺の長さ × コサイン値」となる。
この図の場合は「3 × コサイン30度」だ。




これをそのまま先ほどの図に当てはめてみると、
「ベクトルABの長さ × コサインθ」を計算によって
ベクトルABの影となるベクトルACの長さが求まるということだ。


これを数学的に表現すると以下のようになる。


  \displaystyle\ |\vec{AC}|=|\vec{AB}|\cos\theta


この式は以前紹介したベクトルの内積の計算方法、
\displaystyle\ |\vec{AB}||\vec{AC}|cos\theta と非常に似ていることがわかる。
違うのは\displaystyle\ |\vec{AC}| があるかどうかだ。


\displaystyle\ |\vec{AC}| はベクトルACの長さを表すが、もしこれが 1 なら
\displaystyle\ |\vec{AB}|cos\theta\displaystyle\ |\vec{AB}||\vec{AC}|cos\theta は同じ意味になる。
つまり、ベクトルACの長さを1にしたものとの内積を求めれば
それがベクトルACの長さを表すということになる。



  \displaystyle\begin{align}\ |\vec{AC}|&=|\vec{AB}|\cos\theta\\&=|\vec{AB}||\hat{AC}|\cos\theta\\&=\vec{AB}\cdot\hat{AC}\end{align}


数学的に表現するとややこしく見えるが、
要するに内積を求めるときの2本のベクトルのうち、
片方は正規化したものを使うというだけだ。
この場合、ベクトルACはベクトルABの影が落ちる地面と考える。

影の長さで特定方向に対する位置がわかる


「影」といっても実際の地面とは関係がなく、
2本のベクトルがどこを向いていようが
正規化したベクトル方向を基準に
ベクトルの影の長さがわかるということだ。


これが役立つ場面として
たとえばレースゲームを想像してみよう。


自機と敵が順位を競っている場合、
どちらがゴールに近いかを判定して順位表示する必要があるが、
サーキットは曲がりくねっているので
各キャラクターとゴール地点の単純な距離では判断できない。




そこでスタートからゴールまでコース上に少しずつ点を置いていく。
ここではそのうちの2つの点を取り上げ、
P1からP2に向かう方向がゴールだとする。


そして、P2の座標からP1の座標を引き算して求めたベクトル
さらに正規化し、これを基準ベクトル(\vec{V_0})と考える。




さらに自機の座標からP1の座標を引いて求めたベクトルを \vec{\alpha}
敵の座標からP1の座標を引いて求めたベクトルを \vec{\beta} とする。


正規化された \vec{V_0} の長さは1なのだから、 \vec{\alpha}\vec{V_0} の内積を求めれば


  \displaystyle\vec{\alpha}\cdot\vec{V_0}=|\vec{\alpha}||\vec{V_0}|cos\theta=|\vec{\alpha}|\times\ 1\times\cos\theta=|\vec{\alpha}|cos\theta


となり、 \vec{\alpha} の影の長さを求めることができる。
同様に \vec{\beta}\vec{V_0} の内積を使って \vec{\beta} の影の長さも求める。




そしてその影はP1とP2を結んだ軸上に落ちたものなので
自機と敵のうち影の長い方がP2に近いということがわかる。
これで順位を判別するのだ。




同じ考え方でゴールを通過したかどうかも判定できる。
ゴールは1本の直線だが、判定する際は
そのゴールラインの上にある点Gの座標を使う。




さらに点Gから進行方向に伸びる長さ1のベクトル \vec{V_0}
点Gと自機を結ぶベクトル \vec{\alpha} 、点Gと敵を結ぶベクトル \vec{\beta} を用意する。


あとは先ほどと同じように \vec{\alpha}\vec{V_0} の内積、
\vec{\beta}\vec{V_0} の内積を使ってそれぞれの影の長さを求める。


この影の長さは \vec{V_0} 方向に対しての進捗具合を表すが、
点Gより手前を向いている \vec{\beta} の影はマイナス値になるので
キャラクターがゴールラインを通過したかどうかも簡単に判定できる。


直線からの離れ具合も判定できる


別の利用法として、レーザー兵器との当たり判定を考えてみる。
発射口から一直線に伸びていく攻撃では
単純に発射口との距離が近いからといって当たっているとは限らない。
大切なのはレーザーの太さよりも近くにいるかどうかだ。




そこでレーザーの発射方向を基準ベクトル(\vec{V_0})とし、
座標Aと発射口の座標を結ぶベクトル \vec{W} を求める。




そして \vec{W}\vec{V_0} の内積を求めれば
これまで同様の理屈で、\vec{W} の影の長さ a が手に入る。




ベクトルの長さは簡単に調べられるので
\vec{W} の長さを c とすると、ここに直角三角形が見えてくる。


直角三角形なら三平方の定理である「 c^2=a^2+b^2 」を変形すれば
b=\sqrt{c^2-a^2} 」となり、 b の長さを求めることができる。


この b はレーザーの中心線からの距離となるわけだから
それがレーザーの半径以下かどうかを調べれば
座標Aがレーザーの攻撃範囲内かどうかがわかる。
これが点と直線を使った当たり判定だ。

まとめ

「ベクトルの計算」と聞くとややこしく感じるが、
その中身は四則演算と三平方の定理、三角関数など
数学の基本的な理屈ばかりだ。


すべては基本の積み重ねであり、
思い通りの判定を作っていくためにも
このあたりの知識はきちんと理解しておきたい。



mclover.hateblo.jp

mclover.hateblo.jp

mclover.hateblo.jp

mclover.hateblo.jp

総アクセス数