ゲーム開発
Unity
UnrealEngine
C++
ゲーム数学
ゲームAI
サウンド
アニメーション
GBDK
制作日記
3DCG
Houdini
Blender
USD
グラフィックス
テクノロジ
ツール開発
フロントエンド関連
サーバサイド関連
ソフトウェア設計
ハードウェア関連
おすすめ技術書
音楽
DTM
楽器・機材
ピアノ
その他
都会のエレキベア
ラーメン日記
四コマ漫画
おすすめアイテム
おもしろコラム
  • ゲーム開発
    • Unity
    • UnrealEngine
    • C++
    • ゲーム数学
    • ゲームAI
    • サウンド
    • アニメーション
    • GBDK
    • 制作日記
  • 3DCG
    • Houdini
    • Blender
    • USD
    • グラフィックス
  • テクノロジ
    • ツール開発
    • フロントエンド関連
    • サーバサイド関連
    • ソフトウェア設計
    • ハードウェア関連
    • おすすめ技術書
  • 音楽
    • DTM
    • 楽器・機材
    • ピアノ
  • その他
    • 都会のエレキベア
    • ラーメン日記
    • 四コマ漫画
    • おすすめアイテム
    • おもしろコラム
  1. ホーム
  2. 20210227_01

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

ゲーム数学JavaScriptフロントエンド関連p5.js
2021-02-27

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

参考書籍と開発言語

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

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

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

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

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

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

三次元ベクトル

座標とベクトル

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

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

で表すことができます!

↑三次元上の座標とベクトル
エレキベア
エレキベア
二次元ベクトルに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つのベクトルを掛け合わせることで 外積 を求めることができます!

↑外積を求める公式
エレキベア
エレキベア
外積って何クマ??
マイケル
マイケル
外積は、掛け合わせた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つのベクトルに対して垂直なベクトルが求められるということクマね
マイケル
マイケル
うん!
そして向きについては右ねじの法則を使ったら分かるよ!

↑法線の向き
マイケル
マイケル
回転方向に合わせて右手を d(-_-) として、親指の方向が法線の向きになるよ!
エレキベア
エレキベア
理科の時間に習ったやつクマね
マイケル
マイケル
そして一点注意しないといけないのは、右ねじの法則が当てはまるのは右手座標系のみだということ!
下記のようにx、yの方向が逆の左手座標系の場合は向きも逆になるから気をつけてね!

↑右手座標系と左手座標系
マイケル
マイケル
今回実装したプログラムは左手座標系になるから、右ねじの法則とは逆方向になるよ!

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

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

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

座標の表裏判定

マイケル
マイケル
それじゃ法線の概念も使いながら、平面に対する座標の表裏判定を行ってみましょう!
ここでは、平面の方程式を使って判定してみます!

↑平面の方程式
マイケル
マイケル
平面は上記のように、法線と平面上の座標一点さえ分かれば式で表すことができる!
この式に表裏判定したい座標を代入して正負を見ることで表か裏かを判断できるんだ!
エレキベア
エレキベア
なんか少し難しいクマね
/**
 * 平面に対する座標の表裏判定
 * 平面の方程式に当てはめて判定を行う
 * @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.

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

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

おわりに

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

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


ゲーム数学JavaScriptフロントエンド関連p5.js
2021-02-27
記事をSNSで共有する
X
Facebook
LINE
はてなブックマーク
Pocket
LinkedIn
Reddit

著者の各種アカウント
フォローいただけると大変励みになります!

関連記事
【Three.js】カスタムシェーダーでトゥーン+背面法アウトラインを実装する
2026-02-15
【Three.js】Three.js入門 - シーン構築・モデル読み込み・ポストプロセスまで
2026-02-15
【Astro】Astroの使い方と複数UIフレームワーク(React、Vue、Svelte)を組み合わせるサンプル
2026-02-01
【Houdini21.0】3Dビル群っぽいブログヘッダー画像を作成する
2026-01-10
【VSCode】ドラッグ&ドロップで画像ファイルをリサイズ・保存する拡張機能を作る
2025-11-22
【ゲーム数学】第十回 p5.js(+α)で学ぶゲーム数学「複素数とフラクタル」
2025-11-02
【ゲーム数学】第九回 p5.jsで学ぶゲーム数学「フーリエ解析」
2024-05-12
【Node.js】廃止されたAmazonアソシエイト画像リンクをAmazon Product Advertising API経由で復活させる
2024-01-08