ゲーム開発
Unity
UnrealEngine
C++
Blender
ゲーム数学
ゲームAI
グラフィックス
サウンド
アニメーション
GBDK
制作日記
IT関連
ツール開発
フロントエンド関連
サーバサイド関連
WordPress関連
ソフトウェア設計
おすすめ技術書
音楽
DTM
楽器・機材
ピアノ
ラーメン日記
四コマ漫画
その他
おすすめアイテム
おもしろコラム
  • ゲーム開発
    • Unity
    • UnrealEngine
    • C++
    • Blender
    • ゲーム数学
    • ゲームAI
    • グラフィックス
    • サウンド
    • アニメーション
    • GBDK
    • 制作日記
  • IT関連
    • ツール開発
    • フロントエンド関連
    • サーバサイド関連
    • WordPress関連
    • ソフトウェア設計
    • おすすめ技術書
  • 音楽
    • 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要素が加わっただけだね
      下記に三次元ベクトルの計算結果を表すシミュレータを用意したから触ってみてね!

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

      外積の計算

      マイケル
      マイケル
      そしてここからが三次元特有!
      三次元では、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の方向が逆の左手座標系の場合は向きも逆になるから気をつけてね!

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

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

      マイケル
      マイケル
      このように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点分かれば求めることができる!
      下記にシミュレータを作ってみたから、触ってみてね!

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

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

      おわりに

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

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


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

      関連記事
      【ゲーム数学】第九回 p5.jsで学ぶゲーム数学「フーリエ解析」
      2024-05-12
      【Node.js】廃止されたAmazonアソシエイト画像リンクをAmazon Product Advertising API経由で復活させる
      2024-01-08
      【都会のエレキベア】ブログを大幅リニューアル!WordPressからNext.jsに移行するまでの流れをまとめる
      2024-01-01
      【Next.js】第四回 WordPressブログをNext.jsに移行する 〜サーバ移行・SEO・広告設定編〜
      2023-12-31
      【Next.js】第三回 WordPressブログをNext.jsに移行する 〜Markdown執筆環境構築編〜
      2023-12-31
      【Next.js】第二回 WordPressブログをNext.jsに移行する 〜WordPressデータの移行・表示編〜
      2023-12-31
      【Next.js】第一回 WordPressブログをNext.jsに移行する 〜全体設計、環境構築編〜
      2023-12-31
      【Electron × Vue3】カテゴリ情報のCSVデータを操作するツールを作る
      2023-12-31