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

      【ゲーム数学】第五回 p5.jsで学ぶゲーム数学「球と線分の衝突判定」

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

      マイケル
      マイケル
      みなさんこんにちは!
      マイケルです!
      エレキベア
      エレキベア
      クマ〜〜〜〜〜〜
      マイケル
      マイケル
      今日も引き続き、ゲーム数学を進めていくよ!
      今回は「球と線分の衝突判定」についてだ!
      エレキベア
      エレキベア
      また衝突判定クマか〜〜
      マイケル
      マイケル
      前回は円と線分の衝突判定だったけど、
      少しレベルアップして三次元での衝突判定処理だ!
      マイケル
      マイケル
      数学の知識が必要になってくるけど
      がんばっていこう!!
      エレキベア
      エレキベア
      次元が変わるくらいどうってことないクマ〜〜〜

      参考書籍と開発言語

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

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

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

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

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

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

      球と線分の衝突判定

      マイケル
      マイケル
      それじゃ早速やっていこう!

      考え方

      マイケル
      マイケル
      考え方としては、球の方程式と直線の方程式を使います!
      エレキベア
      エレキベア
      懐かしい式が出てきたクマね〜〜〜〜
      マイケル
      マイケル
      問題はどうやって衝突の判定を行うか!
      線分の始点と終点は、下記のようになります。
      つまり球と線分の交点のtの値が0〜1の時に線分の範囲であるといえます!
      エレキベア
      エレキベア
      なるほどクマ!
      でも球と線分の交点はどうやって求めるクマ?
      マイケル
      マイケル
      球の方程式と直線の方程式を使って求めることができるんだ!
      下記のように、球の方程式に直線の方程式を代入してみよう!
      マイケル
      マイケル
      そして、下記のようにまとめながら展開します!
      エレキベア
      エレキベア
      これはどこかで見たことがあるような形クマ
      マイケル
      マイケル
      そう、二次方程式だ!
      a、b、cをそれぞれまとめると、下記のように解の公式で解くことができる!
      エレキベア
      エレキベア
      解の公式なつかしクマ〜〜
      マイケル
      マイケル
      解の公式は±で2種類あるから、最小値(最寄り)のtを求めて0〜1の間にあるかどうかを判定すれば衝突しているかどうかが分かるんだ!
      エレキベア
      エレキベア
      最初に衝突した最寄りのtの値を求めるクマね

      実装

      マイケル
      マイケル
      これまでの考え方を実装したものが以下になります!
      /**
       * 球と線分の衝突判定
       * 球の方程式と直線の方程式から求める
       * @param {Point}  ball_p 球の位置
       * @param {number} ball_r 球の半径
       * @param {Point}  line_p 線分の開始位置
       * @param {Vec3}   line_v 線分のベクトル
       * @returns true:衝突している false:衝突していない
       */
       function checkBallColLine(ball_p, ball_r, line_p, line_v) {
        // 直線の方程式と球の方程式より、
        // ax^2 + bx + c の形に変形し、a, b, cそれぞれの要素を求める
        let r = ball_r;
        let xa = line_p.x - ball_p.x;
        let ya = line_p.y - ball_p.y;
        let za = line_p.z - ball_p.z;
        let a = line_v.x*line_v.x + line_v.y*line_v.y + line_v.z*line_v.z;
        let b = 2.0 * (line_v.x*xa + line_v.y*ya + line_v.z*za);
        let c = xa*xa + ya*ya + za*za - r*r;
        // 解の公式よりtの値を求める
        // 「b^2-4ac」の値が0以下の場合、衝突無し
        let d = b*b - 4.0*a*c;
        if (d < 0) {
          return false;
        }
        // tの値(2種類)を求める
        d = Math.sqrt(d);
        let t1 = (-b + d) / (2.0 * a);
        let t2 = (-b - d) / (2.0 * a);
        // 線分の最寄り(最小値)のtを設定
        let t = 2.0;
        if (t1 >= 0.0 && t1 <= 1.0 && t1 < t) {
          t = t1;
        }
        if (t2 >= 0.0 && t2 <= 1.0 && t2 < t) {
          t = t2;
        }
        // tが1より大きい場合、衝突無し
        if (t > 1.0) {
          return false;
        }
        return true;
      }
      エレキベア
      エレキベア
      ややこしそうクマが、さっきの話を思い出すとなんとなく分かるクマね
      マイケル
      マイケル
      こちらのコードを使ってシミュレータを作ってみたので、
      よければ触ってみてください!

      See the Pen
      0319_01_COLISION
      by masarito617 (@masarito617)
      on CodePen.

      ↑球と線分の衝突判定

      マイケル
      マイケル
      下記のように、正常に衝突判定が行えていることが確認できます!
      エレキベア
      エレキベア
      やったクマ〜〜〜〜〜

      球と直線の衝突判定

      マイケル
      マイケル
      ここからはおまけですが、球と直線の衝突処理についても紹介します!

      実装

      マイケル
      マイケル
      処理内容はほぼ同じですが、直線のためtの範囲を判定する必要がありません!
      「b^2-4ac」の値が0以上かどうかのみ判定することで、衝突有無が分かります!
      /**
       * 球と直線の衝突判定
       * 球の方程式と直線の方程式から求める
       * @param {Point}  ball_p 球の位置
       * @param {number} ball_r 球の半径
       * @param {Point}  line_p 直線の任意位置
       * @param {Vec3}   line_v 直線のベクトル
       * @returns true:衝突している false:衝突していない
       */
      function checkBallColStraightLine(ball_p, ball_r, line_p, line_v) {
        // 直線の方程式と球の方程式より、
        // ax^2 + bx + c の形に変形し、a, b, cそれぞれの要素を求める
        let r = ball_r;
        let xa = line_p.x - ball_p.x;
        let ya = line_p.y - ball_p.y;
        let za = line_p.z - ball_p.z;
        let a = line_v.x*line_v.x + line_v.y*line_v.y + line_v.z*line_v.z;
        let b = 2 * (line_v.x*xa + line_v.y*ya + line_v.z*za);
        let c = xa*xa + ya*ya + za*za -r*r;
        // 「b^2-4ac」の値が0以上の時、衝突しているとみなす
        let d = b*b - 4.0*a*c;
        return d >= 0;
      }
      エレキベア
      エレキベア
      平方根を求める部分が負の値の場合は解が見つけられないクマね
      マイケル
      マイケル
      こちらのコードを使ったシミュレータは以下になります!

      See the Pen
      0319_02_COLISION
      by masarito617 (@masarito617)
      on CodePen.

      ↑球と直線の衝突判定

      マイケル
      マイケル
      こちらも下記のように衝突判定を行えていることが分かります!
      エレキベア
      エレキベア
      ちょろいクマ〜〜〜〜

      おわりに

      マイケル
      マイケル
      というわけで今回は球と直線の衝突判定でした!
      どうだったかな?
      エレキベア
      エレキベア
      計算が少し複雑だったクマが、少しずつ解くと分かったクマ
      マイケル
      マイケル
      衝突処理は引き出しとして覚えて損はないからどんどん覚えていこう!
      マイケル
      マイケル
      それでは今日はこの辺で!
      アデュー!!
      エレキベア
      エレキベア
      クマ〜〜〜〜〜〜〜〜〜

      【ゲーム数学】第五回 p5.jsで学ぶゲーム数学「球と線分の衝突判定」 〜完〜


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

      関連記事
      【ゲーム数学】第九回 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