210 likes | 471 Views
プロジェクト演習 Ⅳ インタラクティブゲーム 制作 プログラミング 4. 2011/11/29 当たり 判定 総復習. 今日の内容. 当たり判定の素材を整理しよう 基礎となる計算の整理 座標系の正規化 球ベース判定 角張系判定 戻し方で苦労 しよう 速度 分解 ゲームの特性に合わせた戻し方. 覚えておいて欲しい計算. 距離を算出できると判定に使える 点と点 まさかこれが出来ないという人はおる まいね ? 点と線 & 線と線 fk_Math クラス参照 点と平面 & 線と平面 「 三次元幾何要素表現と交差交線計算 」参照
E N D
プロジェクト演習Ⅳインタラクティブゲーム制作プログラミング4プロジェクト演習Ⅳインタラクティブゲーム制作プログラミング4 2011/11/29 当たり判定総復習
今日の内容 • 当たり判定の素材を整理しよう • 基礎となる計算の整理 • 座標系の正規化 • 球ベース判定 • 角張系判定 • 戻し方で苦労しよう • 速度分解 • ゲームの特性に合わせた戻し方
覚えておいて欲しい計算 • 距離を算出できると判定に使える • 点と点 • まさかこれが出来ないという人はおるまいね? • 点と線&線と線 • fk_Mathクラス参照 • 点と平面&線と平面 • 「三次元幾何要素表現と交差交線計算」参照 • 線と平面の交差判定は、パラメータu,vを算出することで三角形との衝突判定になるので重要
座標系の正規化とは • こういう計算よりは • こういう計算の方が楽そうだよね
球ベース判定の傾向と対策 • 球 • 球だけで押し通すのは厳しいが、他の判定と併用することも多い • 複雑な判定の前に球ベースで判定しておくなど • 球の中心を「点」から「線分」に拡張することにより、「カプセル」へと進化する • カプセル • 球よりボリュームの広いエリアをカバー • 球の弾丸貫通問題対策としても使用 • ボーンのように組み合わせれば人型キャラの判定は十分作れる
球とカプセル • 中心間の距離が、お互いの半径の合計より小さかったら衝突 • 球がうぞぞぞぞっと動いた軌跡 • 組み合わせて人型にしたり、弾丸貫通問題への対処に使う • 線分と線分(点)の距離で判定ができる
真の衝突判定とは • ある瞬間にぶつかってるかどうか、を調べるだけでは「干渉判定」でしかない • 「これくらい動く予定なんだけど、 どこかでぶつかっちゃう?」を調べる !!!! ! ! ?
角張り系判定 • 球VS球では安定した接地が難しいため、乗っかることを前提とした物体は角張り系の判定が必要 • 直方体 • XYZ軸に平行に配置された直方体はAABB、自由に回転が許されたものはOBBと呼ぶ • 球やカプセルとの判定も可能で、その場合は座標系の正規化を使って処理を行う • 凸包 • 対球に関しては最強レベルの判定素材 • 凸包同士や、その他の判定素材との連携が困難 • 三角形メッシュ集合体 • DirectXやXNAではデフォルトでサポートしている • 点や線との判定は容易だが、閉じた形状は表せないので運用に注意が必要
凸包とは • 凹んだ部位のない立体 • n角柱、n角錐なども凸包に含まれる • 点(球)との内外判定がべらぼうに簡単 • 衝突検出になると難しいが。。。
三角形と線分の判定を駆使 • 理論上はどんなポリゴンモデルでも対応可能 • 破綻無く判定するのが困難だが… • どこでぶつかったのか、を明確に判断できるのは線分系の判定なので、それをひたすら駆使する
用途に応じて使い分け • キャラクターは球 • 見た目はゴージャスに作った形状でもいい • それらを覆うような球を当たり判定用に用意して、親子関係を結べばいい • entry()しなければ表示されない • マップはブロック • 球だとつるつるすべって操作性に難がある
とりあえずおすすめは • キャラ&可動障害物 • 球(カプセル)、OBB • 地形 • 全てをOBB • 地面はポリゴンで、障害物はOBB • 乗っかれる必要があるデカキャラなど • OBB • 視界判定 • ベクトルの内積による角度判定&距離 • 攻撃判定 • 球、カプセル
戻し方 • 動物体の次フレームでの位置を仮定する • その動きを阻害する可能性のある物体全てと衝突判定を行う • 戻しベクトルが発生したら動物体に適用する • 全物体と判定を終えたら終了… ではない
以下のようなシチュを考える • 右図のような状況の場合、Aに衝突して発生した戻しベクトルによって、Bに衝突する危険性がある • A→Bの順に判定できればいいが、そうならなかったらどうする? 真上から見た図 A B
解決案 • 候補の物体と判定して、「戻しベクトルが発生しなかったら」判定終了とする • 色々効率化の余地はあるだろうが、とりあえずはこうしておこう do { 戻しベクトル初期化 for(障害物候補全部) { 当たり判定する 戻しベクトル加算 } 動物体に適用 } while(適用したベクトルがゼロじゃなかったらもう1回ループ);
重力の扱い • 基本的には常時下向きの力を働かせる • そうすると、同じ高さで並べたブロックでつっかかる • 足下のブロックから先に判定できればいいが、そうもいかない • 速度をXZ方向とY方向に分解して2回判定 真横から見た図 A B
どちらが好ましいか? • ぶつかった時点で止まるタイプ • 壁擦れするタイプ
効率的な判定のためテクニック • 距離で刈り込む • OBBの判定より距離の判定の方が軽い • 具体的な距離の値が要らない(距離内かどうかだけが知りたい)場合は、ベクトルの長さの2乗と判定距離の2乗で比較しよう • if(vec.dist2() < d*d) のように判定 • クラスタで刈り込む • 常時全物体と判定するのはナンセンスの極み
クラスタリングって? • モノの分類や、グループ分けのこと • マップを領域ごとに分割する • 領域ごとに「どの物体が存在しているか」のリストを持つ • 判定したくなったら、自分が居る領域のリストに問い合わせて判定 真上から見た図
クラスタリングに必要な部品 • 座標→クラスターIDへの変換 • (x, z)の座標値を、一定間隔ごとの整数値に変換する必要がある • 配列の配列 • クラスターIDで問い合わせると、対応する領域の物体情報が取れるようにしたい • vector< vector<int> >などを使う • 本当はlistなどに出来ればした方がよい
当たり判定クラスの設計方針 • 現状のfkutシリーズではまだまだです • 共通の基底クラスを持たせて、個別の判定クラスはそれを継承して作るようにすべき • チームを超えて設計して、共通のクラスを開発するのもgood! • こうなるよりは… vector<fkut_OBB *> obbArray; vector<fkut_Capsule *> capArray; vector<fkut_... *> otherArray; • この方がいい vector<fkut_Collision*> colArray;