【ゲーム数学】第三回 p5.jsで学ぶゲーム数学「三次元ベクトル」

JavaScript
マイケル
マイケル
みなさんこんばんは!
マイケルです!
エレキベア
エレキベア
クマ〜〜〜〜
マイケル
マイケル
今日も前回に引き続いてゲーム数学シリーズを進めるよ!
マイケル
マイケル
第三回は「三次元ベクトル」!!
難しそうですが計算自体は簡単です!張り切っていきましょう!
エレキベア
エレキベア
簡単ならやってやるクマ
スポンサーリンク

参考書籍と開発言語

マイケル
マイケル
勉強にするにあたっては前回同様、下記参考書を参考にしました!

ゲームを動かす数学・物理 R

グラフィックスプログラミング入門

マイケル
マイケル
どちらも高校数学の基礎から解説しているため、しばらく数学から離れている方でも読みやすいと思います!
エレキベア
エレキベア
一読してみるクマ
マイケル
マイケル
そしてサンプルプログラムの実装としては p5.js を使用しています!
気になった方はこちらも使用してみてくださいね!
Screenshot 2021 01 16 23 15 46

p5.js ダウンロードページ

エレキベア
エレキベア
グラフィックス特化のJavaScriptライブラリクマね

三次元ベクトル

座標とベクトル

マイケル
マイケル
座標とベクトルに関しては、二次元ベクトルとほぼ同じで

 座標 → (x, y, z)で表す位置
 ベクトル → (x, y, z)で表す方向

で表すことができます!
Screenshot 2021 02 26 1 09 51
↑三次元上の座標とベクトル
エレキベア
エレキベア
二次元ベクトルにZ要素が加わっただけクマね
// ベクトルクラス
class Vec3 {
  constructor(x, y, z) {
    this.x = x;
    this.y = y;
    this.z = z;
  };
}

// 座標クラス
class Point {
  constructor(x, y, z) {
    this.x = x;
    this.y = y;
    this.z = z;
  };
}
マイケル
マイケル
コードも変数定義を一つ増やすだけだね

ベクトルの計算

マイケル
マイケル
そしてベクトルの計算も基本的に二次元ベクトルと同じで、
それぞれZ要素を増やすことで計算できます!


・加算
 v1 + v2 = (v1.x + v2.x, v1.y + v2.y, v1.z + v2.z)
・減算
 v1 – v2 = (v1.x – v2.x, v1.y – v2.y, v1.z – v2.z)
・乗算
 v1 * s = (v1.x * s, v1.y * s, v1.z * s)
・除算
 v1 / s = (v1.x / s, v1.y / s, v1.z / s)
・ベクトルの大きさ
 sqrt(v1.x**2 + v1.y**2 + v1.z**2)
・正規化
 v1 / sqrt(v1.x**2 + v1.y**2 + v1.z**2)

// *** 座標ベクトル計算 ***
// ベクトル+ベクトル
function addVec(v1, v2) {
  return new Vec3(v1.x + v2.x, v1.y + v2.y, v1.z + v2.z);
}

// ベクトル-ベクトル
function subVec(v1, v2) {
  return new Vec3(v1.x - v2.x, v1.y - v2.y, v1.z - v2.z);
}

// ベクトル*スカラー
function mulVec(v, s) {
  return new Vec3(v.x * s, v.y * s, v.z *s);
}

// ベクトルの正規化
function normalize(v) {
  let l = sqrt(v.x**2 + v.y**2 + v.z**2);
  return new Vec3(v.x/l, v.y/l, v.z/l);
}
エレキベア
エレキベア
これも2次元ベクトルと概念は同じクマね
マイケル
マイケル
Z要素が加わっただけだね
下記に三次元ベクトルの計算結果を表すシミュレータを用意したから触ってみてね!

See the Pen
0227_01
by masarito617 (@masarito617)
on CodePen.

↑三次元ベクトルの計算結果(マウスドラッグで視点変更可)

外積の計算

マイケル
マイケル
そしてここからが三次元特有!
三次元では、2つのベクトルを掛け合わせることで 外積を求めることができます!
Screenshot 2021 02 27 12 13 55
↑外積を求める公式
エレキベア
エレキベア
外積って何クマ??
マイケル
マイケル
外積は、掛け合わせた2つのベクトルに対しての法線になるんだ!
2つのベクトルさえ分かれば求められるから、面に対しての向き、方向を求めることに使われることが多いよ!
/ ベクトルの外積
function crossVec(v1, v2) {
  let cross_v = new Vec3();
  cross_v.x = v1.y * v2.z - v1.z * v2.y;
  cross_v.y = v1.z * v2.x - v1.x * v2.z;
  cross_v.z = v1.x * v2.y - v1.y * v2.x;
  return cross_v;
}
マイケル
マイケル
実装するとこんな感じ!
エレキベア
エレキベア
少しややこしいクマが2つのベクトルに対して垂直なベクトルが求められるということクマね
マイケル
マイケル
うん!
そして向きについては右ねじの法則を使ったら分かるよ!
Screenshot 2021 02 27 3 40 47
↑法線の向き
マイケル
マイケル
回転方向に合わせて右手を d(-_-) として、親指の方向が法線の向きになるよ!
エレキベア
エレキベア
理科の時間に習ったやつクマね
マイケル
マイケル
そして一点注意しないといけないのは、右ねじの法則が当てはまるのは右手座標系のみだということ!
下記のようにx、yの方向が逆の左手座標系の場合は向きも逆になるから気をつけてね!
Screenshot 2021 02 27 3 40 40
↑右手座標系と左手座標系
マイケル
マイケル
今回実装したプログラムは左手座標系になるから、右ねじの法則とは逆方向になるよ!

See the Pen
0227_02
by masarito617 (@masarito617)
on CodePen.

↑法線の計算結果(マウスドラッグで視点変更可)

Screenshot 2021 02 27 12 27 03
マイケル
マイケル
このように2つのベクトルから法線が算出できていることが分かります!
エレキベア
エレキベア
法線めっちゃ長いクマね
マイケル
マイケル
かけ合わせるベクトルがある程度大きいと、とても大きい値になるのが外積の特徴なんだ。
方向だけ求めたい時は、外積を求めた後に正規化する必要があるから気をつけてね!

座標の表裏判定

マイケル
マイケル
それじゃ法線の概念も使いながら、平面に対する座標の表裏判定を行ってみましょう!
ここでは、平面の方程式を使って判定してみます!
Screenshot 2021 02 27 12 19 49
↑平面の方程式
マイケル
マイケル
平面は上記のように、法線と平面上の座標一点さえ分かれば式で表すことができる!
この式に表裏判定したい座標を代入して正負を見ることで表か裏かを判断できるんだ!
エレキベア
エレキベア
なんか少し難しいクマね
/**
 * 平面に対する座標の表裏判定
 * 平面の方程式に当てはめて判定を行う
 * @param {Point} check_p チェックする座標
 * @param {Vec3}  cross_v 平面の法線
 * @param {Point} plane_p 平面座標(任意の一点)
 * @return {boolean} 表裏判定結果 true:表 false:裏
 */
function checkFrontPlane(check_p, cross_v, plane_p) {
  // チェック対象座標 - 平面の座標
  sub_x = check_p.x - plane_p.x;
  sub_y = check_p.y - plane_p.y;
  sub_z = check_p.z - plane_p.z;
  // 上記で求めたベクトルを法線の各要素に掛けて加算
  check_value = cross_v.x * sub_x + cross_v.y * sub_y + cross_v.z * sub_z;
  // 0以上の場合:表(0と同値の場合も表とみなす)
  return check_value >= 0;
}
マイケル
マイケル
実装するとこんな感じ!
エレキベア
エレキベア
とりあえず平面の座標と法線が分かれば、式に当てはめて座標の表裏がチェックできるということクマね
マイケル
マイケル
うん!そして法線も2つのベクトルが分かればいいから、平面の座標が3点分かれば求めることができる!
下記にシミュレータを作ってみたから、触ってみてね!

See the Pen
0227_03
by masarito617 (@masarito617)
on CodePen.

↑座標の表裏判定(マウスドラッグで視点変更可)

Screenshot 2021 02 27 13 05 20
Screenshot 2021 02 27 13 05 48
マイケル
マイケル
このように、正しく表裏の判断ができていることが分かります!
エレキベア
エレキベア
やったクマ〜〜〜〜〜

おわりに

マイケル
マイケル
というわけで今回は三次元ベクトルでした!
どうだったかな?
エレキベア
エレキベア
これまでと比べると少し難しかったクマ〜〜〜
マイケル
マイケル
外積が出てくると少し複雑になるよね・・・。
まあ今後も三次元になれながら少しずつステップアップしていこう!
エレキベア
エレキベア
クマ〜〜〜〜〜〜〜
(勉強はコリゴリクマ・・・)

【ゲーム数学】第三回 p5.jsで学ぶゲーム数学「三次元ベクトル」 〜完〜

コメント