Math World Lab

直線・平面の方程式とレイキャスティング

「銃弾は壁のどこに着弾したか?」FPSゲームの射撃判定とLiDARセンサーの衝突幾何学

この単元の発見をシェア
3行要約(Key Takeaways / AIOサマリー)
1
直線のベクトル方程式 p = a + t d は、起点 a から方向ベクトル d に沿ってパラメータ t だけ進んだすべての点の軌跡を表す
2
平面の方程式 n · (p - a) = 0 は、平面上の基準点 a と法線ベクトル n に直交するすべての点 p の集合である
3
FPSゲームの即着弾判定(Hitscan)や3DCGのレイトレーシングでは、直線の方程式を平面・球の方程式に連立代入し、未知数 t を解くことで着弾座標をミリ秒未満で算出している

なぜこれを学ぶのか? — 現実社会とテクノロジーでの価値

Purpose & Motivation

なぜ生まれたのか?

空間内を飛ぶ光線や弾丸が「どの障害物のどの地点に、何秒後に衝突するか」を代数方程式で瞬時に解くために生み出された。

身につく武器・思考力

幾何学的な直線をパラメータ t の1次関数として定式化し、平面の方程式と連立させて交点をミリ秒未満で算出するアルゴリズム思考が身につく。

実社会・ITでの活躍現場

  • •『Apex』や『VALORANT』などFPSゲームの即着弾(Hitscan)判定
  • •映画やゲームのリアルタイム・レイトレーシング(光線と物体の交差判定)
  • •自動運転車や掃除ロボットのLiDARセンサーによる障害物検知
  • •3DCG制作ソフトでマウスクリックした3Dオブジェクトの選択判定

Layer 1 — 直感・シミュレーター

銃口(光線の発射起点)と射撃角度、障害物(ターゲット壁)の角度や位置をスライダーで動かしてみよう。光線 p⃗(t)=a⃗+td⃗\vec{p}(t) = \vec{a} + t\vec{d} が壁の平面と交差するパラメータ tt がリアルタイムに解かれ、着弾点に赤いターゲットマークが瞬時に表示されるレイキャスティングの幾何計算を体感できる。

FPSレイキャスティング・ベクトルパラメータ:
射撃角度 θ:15°
壁の距離 (X座標):280 px
壁の傾き角度:0°
レイキャスティング着弾検出ビュー:パラメータ t=238.1t = 238.1
壁(平面)法線 n銃口 a着弾! (t=238.1)
直線の式: p(t) = a + td
方向 d: (0.97, -0.26)
射撃角度 15°
交点距離パラメータ t
238.1 px
(n · (p0 - a)) / (n · d)
着弾判定
着弾座標 (280.0, 78.4)
FPSのHitscan判定完了
直感チェック!ミニクイズ

光線 p(t) = (0, 0, 0) + t(1, 1, 0) が平面 x + y + z = 10 と交差するパラメータ t の値はいくつか?

Layer 2 — 定義・受験・証明

定義

空間内の直線と平面のベクトル方程式: - 直線のベクトル方程式: 通る点 a\mathbf{a}、方向ベクトル d≠0\mathbf{d} \neq \mathbf{0} に対し、媒介変数 tt を用いて

p(t)=a+td(t∈R)\mathbf{p}(t) = \mathbf{a} + t\mathbf{d} \quad (t \in \mathbb{R})

- 平面のベクトル方程式: 通る点 p0\mathbf{p}_0、法線ベクトル n\mathbf{n} に対し、内積を用いて

n⋅(p−p0)=0  ⟺  nxx+nyy+nzz+D=0(D=−n⋅p0)\mathbf{n} \cdot (\mathbf{p} - \mathbf{p}_0) = 0 \iff n_x x + n_y y + n_z z + D = 0 \quad (D = -\mathbf{n} \cdot \mathbf{p}_0)

公式・数理モデル

p(t)=a+td,n⋅(p−p0)=0,t=n⋅(p0−a)n⋅d\mathbf{p}(t) = \mathbf{a} + t\mathbf{d}, \quad \mathbf{n} \cdot (\mathbf{p} - \mathbf{p}_0) = 0, \quad t = \frac{\mathbf{n} \cdot (\mathbf{p}_0 - \mathbf{a})}{\mathbf{n} \cdot \mathbf{d}}

証明・導出

直線と平面の交点パラメータ tt の導出: 直線の式 p(t)=a+td\mathbf{p}(t) = \mathbf{a} + t\mathbf{d} を平面の方程式 n⋅(p−p0)=0\mathbf{n} \cdot (\mathbf{p} - \mathbf{p}_0) = 0 に直接代入する。

n⋅(a+td−p0)=0\mathbf{n} \cdot (\mathbf{a} + t\mathbf{d} - \mathbf{p}_0) = 0

内積の分配法則を展開すると、

n⋅(a−p0)+t(n⋅d)=0\mathbf{n} \cdot (\mathbf{a} - \mathbf{p}_0) + t(\mathbf{n} \cdot \mathbf{d}) = 0

t(n⋅d)=n⋅(p0−a)t(\mathbf{n} \cdot \mathbf{d}) = \mathbf{n} \cdot (\mathbf{p}_0 - \mathbf{a})

ここで n⋅d≠0\mathbf{n} \cdot \mathbf{d} \neq 0(光線が平面と平行でない)の場合、両辺を割ることで

t=n⋅(p0−a)n⋅dt = \frac{\mathbf{n} \cdot (\mathbf{p}_0 - \mathbf{a})}{\mathbf{n} \cdot \mathbf{d}}

が一意に求まる。t≥0t \ge 0 であれば前方に交点(着弾点)が存在し、交点座標は a+td\mathbf{a} + t\mathbf{d} としてただちに決定される。

押さえておきたいポイント

  • 直線の方程式における tt は「距離スケーリング係数」。t>0t > 0 なら前方、t<0t < 0 なら銃口の後ろを意味する
  • n⋅d=0\mathbf{n} \cdot \mathbf{d} = 0 のときは光線と壁が平行であり、交差しない(着弾しない)
  • 平面の方程式の係数 (a,b,c)(a, b, c) は、そのまま「平面に直交する法線ベクトル」の成分を表している
  • 点と平面の距離公式: d=∣ax0+by0+cz0+D∣a2+b2+c2d = \dfrac{|ax_0 + by_0 + cz_0 + D|}{\sqrt{a^2 + b^2 + c^2}} も内積の射影から美しく導かれる
参照基準・学習指導要領との対応

本トピックの内容・数理モデルは、文部科学省学習指導要領(算数・数学・情報)および国際標準カリキュラムに準拠し、エンジニアリング現場の実装事例と照らし合わせてMath World Lab編集部により検証・作成されています。

Layer 3 — 工学応用・現場実装

FPSゲームの射撃判定(Hitscan Raycasting)と3D着弾検出アルゴリズム

プレイヤーのカメラ位置 origin\mathbf{origin} と視線方向 dir\mathbf{dir} から放たれる無限光線(Ray)と、マップ内の壁ポリゴン(平面)との交点を計算し、最小の正の tt を持つ最近傍の壁に着弾痕(デカール)を生成するエンジンコード。

1type Vec3 = { x: number; y: number; z: number };
2
3interface HitResult {
4 hit: boolean;
5 distanceT: number;
6 hitPoint: Vec3;
7}
8
9// 内積
10const dot = (a: Vec3, b: Vec3) => a.x * b.x + a.y * b.y + a.z * b.z;
11
12// 光線と平面の交差判定 (Ray-Plane Intersection)
13function intersectRayPlane(
14 rayOrigin: Vec3, // 銃口 a
15 rayDir: Vec3, // 射撃方向 d (正規化済み)
16 planePoint: Vec3, // 平面上の基準点 p0
17 planeNormal: Vec3 // 平面の単位法線 n
18): HitResult {
19 const denom = dot(planeNormal, rayDir);
20
21 // 分母がほぼ 0 の場合、光線と壁は平行(ヒットしない)
22 if (Math.abs(denom) < 1e-6) {
23 return { hit: false, distanceT: 0, hitPoint: { x: 0, y: 0, z: 0 } };
24 }
25
26 // t = (n · (p0 - a)) / (n · d)
27 const diff = { x: planePoint.x - rayOrigin.x, y: planePoint.y - rayOrigin.y, z: planePoint.z - rayOrigin.z };
28 const t = dot(planeNormal, diff) / denom;
29
30 // t < 0 はプレイヤーの後ろ側にあるため除外
31 if (t < 0) {
32 return { hit: false, distanceT: t, hitPoint: { x: 0, y: 0, z: 0 } };
33 }
34
35 // 着弾点: p = a + t * d
36 return {
37 hit: true,
38 distanceT: t,
39 hitPoint: {
40 x: rayOrigin.x + t * rayDir.x,
41 y: rayOrigin.y + t * rayDir.y,
42 z: rayOrigin.z + t * rayDir.z,
43 },
44 };
45}
46
47// 例: 原点から X軸方向に撃ち、X=50 にある壁にヒット
48const origin = { x: 0, y: 1.5, z: 0 }; // 目の高さ 1.5m
49const dir = { x: 1, y: 0, z: 0 }; // 真東に射撃
50const wallPoint = { x: 50, y: 0, z: 0 };
51const wallNormal = { x: -1, y: 0, z: 0 }; // プレイヤー向きの壁法線
52
53const hit = intersectRayPlane(origin, dir, wallPoint, wallNormal);
54console.log(`着弾判定: ${hit.hit}, 距離: ${hit.distanceT.toFixed(1)}m`);
55console.log(`着弾座標: (${hit.hitPoint.x}, ${hit.hitPoint.y}, ${hit.hitPoint.z})`);
56// 着弾判定: true, 距離: 50.0m, 着弾座標: (50, 1.5, 0)

次に学ぶならコレ!おすすめトピック

この単元と深い繋がりを持つ、あわせて学ぶと理解が深まるおすすめ単元

数理モデル・概念が近い関連トピック

関連度高高校数学

ベクトルの内積

2本の矢印の「向きの近さ」を1つの数値にする

関連度高高校数学

3D空間ベクトルと外積(クロス積)

3次元空間におけるポリゴンの表裏・法線ベクトルと3DCGライティングの数理

B(t) 媒介変数CSS cubic-bezier
関連度高高校数学

ベジェ曲線とデザイン幾何学(フォント・UIの数理)

「制御点を引っ張ると曲線が曲がる理由」線分内分が創り出す美しきグラフィックス

同じレベルで次に挑戦したいトピック

同レベル推薦高校数学

三角関数(単位円とサイン・コサイン)

回転する点のx座標・y座標が三角関数の正体

同レベル推薦高校数学

微分の基本(接線と変化率)

平均変化率の極限として現れる「その瞬間の傾き」

同レベル推薦高校数学

積分の基本(面積と区分求積法)

微小な短冊を無限に足し合わせることで現れる「曲線下の面積」

工学・実社会での応用先でつながるトピック

工学・実践連携小学校・算数

円の面積と円周率

半径を変えると、円周と面積はどう変わる?

工学・実践連携小学校・算数

三角形・多角形の面積

頂点を動かして、面積の公式が成り立つ理由を確かめよう

工学・実践連携小学校・算数

単位変換(長さ・面積・体積)

長さが2倍になると、面積・体積は何倍になる?

あなたの数学力をさらに伸ばす

数学の弱点診断や算数パズルに挑戦してみませんか?

簡単な質問に答えてあなたにぴったりの学習ロードマップを発見したり、直感を試すパズルで数の面白さを体験できます。