- ベストアンサー
リアルタイム3Dについて。
プログラミングを始めて3ヶ月ほどの初心者です。 学校の課題で自由課題が出ました。そこで習ったことを駆使すれば何とか自分でも出来そうな簡単な3D迷路のゲームを作りたいと考えました。 内容はシンプルで迷路自体を傾け、その傾きによってボールが転がりゴールを目指すというものです。 できると思ったですが、分からないことがいくつかりまして(自分で考えたくせに出来ないとは情けない話です)… 1.ある角度まで迷路が傾いたら、それ以上傾かないようにする。 2.壁とボールの衝突判定をする。 3.ボールが壁に当たったらそれ以上進まないようにする。 4.迷路の傾きによりボールが転がるようにする。 以上の4つが分かりません。もちろんかなり質問したのですが、なかなか思うように動いてくれず… で、今回知りたいのは2と3について(特に2)です。1についてはなんとか自力でやってみようと思います。 また3については1と2ができないと、どうしようもないと思うので、今の所手をつけていません。 それに今週、発表前最後の講義があるのでそのときに質問するつもりです。 で、衝突判定ですが、球体と立方体の判定はどのようにすればいいのでしょうか? 質問し、説明を受けた時は理解したつもりだったのですが、よくよく考えてみると球体同士の衝突判定の説明だったようで(私が間違っているだけかもしれませんが)… 一応、課題なので直接答えを教えてもらうのはどうかと思う(もちろん本音はそうしてもらった方が助かりますが)ので、考え方などを教えてもらえないでしょうか? また衝突判定以外も教えてもらえれば助かります。1から10まで質問するよりも、多少なり理解した上で質問しやすいと思うので。 分かる方、教えてもらえないでしょうか? こんな長文、複数の質問をするなど偉そうな内容で申し訳ありません。よろしくお願いします。
- みんなの回答 (5)
- 専門家の回答
質問者が選んだベストアンサー
>球体と立方体の判定はどのようにすればいいのでしょうか? 難しく考えないでも、ボールが跳ねたりしないのであれば 球の中心の(迷路状のx-y)座標(壁が垂直なら高さも考えなくてもよい)と壁の座標の距離が球の半径Rになった時が衝突したということでいいと思います。
その他の回答 (4)
- Interest
- ベストアンサー率31% (207/659)
ANo.4 です。その昔作った自作数学ライブラリをあさってみたら、「点と平面との距離を求める方法」をちょっと違ったやり方で実現していましたので紹介します。 /******************************************************************** 関数 myCalcDistanceOfPlaneAndPoint 説明 : 平面と点との距離を求める。 引数 : normal (in) 面の法線ベクトル p0 (in) 面上の点 p (in) (面上に無い)点 戻値 : 面と点p との距離 参考 : 法線ベクトル n とベクトル p - p0 とのなす角をθと すると、n と p - p0 との内積は n・(p - p0) = |n||p-p0|cosθ と表すことができる。ここで、平面と点との距離 h は このθを用いて h = |p-p0| cosθと表すことができる から、これらの式を整理すると、 h = n・(p - p0) / |n| となり、この式から平面と点との距離が求まる。 *******************************************************************/ float myCalcDistanceOfPlaneAndPoint(float normal[], float p0[], float p[]) { int i; float p0_p[3]; for(i=0; i<3; i++) p0_p[i] = p[i] - p0[i]; return myCalcDotProduct(normal, p0_p) / myCalcNorm(normal); } ここで、 myCalcDotProductは2つのベクトルの内積を求める関数、myCalcNormはベクトルの大きさ(ノルム)を求める関数です。
お礼
実例を提示していただきありがとうございます。 ただ、いきなり基礎をすっ飛ばして3Dのプログラミングをしているもので、この内容をまだ確実に理解できてません…申し訳ありません。 プログラム自体は楽しく感じているので、課題終了後に色々と調べて理解しようと思います。 ありがとうございました。
- Interest
- ベストアンサー率31% (207/659)
2の「壁とボールの衝突判定」について、その仕組みを提案します。 話を簡単にするために、「壁」は直方体かもしれませんが、衝突判定をする「面」を取り出して、問題を「面と球との衝突判定」と定義しなおします。 前提条件として、 ○ 「頂点」は3次元の座標を有する ○ 「面」は3つの頂点を有する ○ 「球」は中心座標と半径を有する ものとします。 考え方ですが、「点(球の中心座標)と平面の距離を求めて、その距離が球の半径以下になったら衝突したものと判定する」という方針でいきます。ただし、「点から平面に下ろした垂線の足が、3つの頂点が構成する面(三角形)の外部にある場合は衝突としない」ことも付け加えておきます。 まず、点p から点a, b, c が構成する三角形に下ろした垂線の足 f の座標を求めます。点a, b, c を含む面の法線ベクトルは、(a-c)×(a-b)で求まりますね。ここで×は、掛け算ではなく外積です。点pから垂線の足fに向かうベクトルは点a,b,cを含む面と垂直ですから、先ほど求めた法線ベクトルと同じ向き(または反対向き)です(条件1)。さらに、垂線の足fは点a,b,cを含む面と同じ面上にあります(条件2)。これらの条件1、条件2から垂線の足fの座標を未知として方程式を立てて、方程式を(手計算で)解けば、点a,b,cと点pを与えると垂線の足fを求めることができます。 つづいて、垂線の足fが点a,b,cが構成する三角形の内部にあるかどうかを判定します。これは、垂線の足fから無限遠方(というなの十分遠いところ)に点qを置いて、線分fqと線分abとが交差するか、線分fqと線分bcが交差するか、線分fqと線分caが交差するかを判定して、いずれか一つでも交差すれば垂線の足fは三角形の内部、一つも交差しなければ三角形の外部であると判定します。(この種の判定は良く使われるので、関数にしておきたいですね。) ここまでですべての下準備が終わり、いよいよ本丸です。 すでに点p から点a, b, c が構成する三角形に下ろした垂線の足 f の座標を求めましたから、点pから垂線の足fまでの距離を求めれば、点と面との距離が求まります。点pを半径rの球の中心としたとき、「垂線の足fが三角形の内部にあり、かつ、点pと垂線の足fとの距離が半径r以下」なら球と面とが衝突したと判定できます。 ------------------------------------------------ 話を簡単にするために面を3点で定義しましたが、四角形は二つの三角形でできていますし、n角形はn-1この三角形でできていますから、この話は凸多角形であれば何角形でも適応可能です。今回は迷路の壁とボールの衝突判定ですから、迷路の壁を直方体で表現する場合は6面の長方形(12面の三角形)と球との衝突判定でこれを実現することが可能です。
お礼
お礼が遅れてしまい、申し訳ありません。 何度も読み見直し、多分理解できたと思います。 非常に勉強になりました。ありがとうございました。
- Qwerty-36
- ベストアンサー率25% (58/226)
壁のデータ構造が判らないと答えようがありませぬ。
お礼
非常に申し訳ないのですが、データ構造なるものが正直全く分かっていないので、説明できません… せっかく答えていただいたのに本当に申し訳ありません。ありがとうございました。
- activedolphin
- ベストアンサー率14% (9/61)
DirectXやOpenGLのような3Dライブラリは使用してないのでしょうか? DirectXには当たり判定用の関数が用意されていたと思いますが、既成のライブラリを使用していないのであれば数学的に解釈して実装するしかないのではないかと思います。
お礼
お答えありがとうございます。 3Dライブラリと言えるのかは分かりませんが、FK Toolkit System & TinyFK Toolkit Systemなるものを使っています。 http://www.teu.ac.jp/aqua/~earth/FK/ ただ、これはどうも学校が作り、使用しているようで、一般的には全く有名ではない(検索してみたのですが全くヒットしなかったので)ようなので、書かないほうがいいのかなと思ってしまいまして。 申し訳ありませんでした。
お礼
お返事が遅れてしまい、申し訳ありません。 多少動作が怪しい気もしますが、何とかできたようです。 本当に助かりました。ありがとうございました。
補足
壁も垂直ですし、壁に衝突してもバウンドはしません。 同じ様な内容を講師の方にも説明されたような気がします(笑)。その説明の理解を私が間違っていただけのようですね… ただその時は口頭での説明だったので、文章として残っている今回のような説明は非常にありがたいです。 よく考え、これから試してみようと思います。まだ試していないので、今回は補足の方にコメントさせていただきました。 お答えありがとうございます。