- ベストアンサー
3Dゲームの行列計算で困っています
- 3Dゲームを作る際に、行列計算に困っています。
- 特に、地形が回転する場合に主人公の位置の管理が難しいです。
- 床の角度に応じて重力の向きを変えるプログラムを実装しても、主人公の位置が回転してしまいます。この問題を解決するための数学力が必要です。
- みんなの回答 (1)
- 専門家の回答
質問者が選んだベストアンサー
全体が180度回転した場合でも、主人公の足が下で頭が上で、重力は下にしておきたいと いうことなのかな・・・。 数学は強くないのですが、一応経験はあるので、理解に努めました。 最近はちょっと3Dとは遠い世界の仕事をしているのですが、日本の3D技術の未来の底上げをしたいと望んでいるので、意地で答えてみようと思います。 で、文から読み取れる範囲と私の推測では、イメージとしては、 display +-player +-bone(胴体、手、頭とか) +-map(世界) +-map objects(よく分からないけど。浮遊物とか木とか) +-gravity みたいなツリーになっています。 ポイントとしては、計算するときに、それぞれのオブジェクトが同じ世界にいるように振舞うには、親オブジェクトの標準の状態(回転や移動をしてない状態)で行わなければならないとい事です。 >回転後も、現座標の床から離れることなく主人公の向きを下向きにしたい 床というのがよく分からないのですが、画面に対して水平な見えない床があるのでしょうか。 で、地形と一緒に動いて欲しくないのであれば PlayerMatrixにModelRotをかけてはならない気がします。 で、回転の中心がプレイヤーじゃない場合は、回転の中心との差分をプレイヤーの座標に対して地形を回転させる前に D3DXMatrixTranslation でPosMatrixかPlayerMatrixに、平行移動成分も与えてやる必要があると思います。 それが動作として正しいのかどうかはよく分かりませんが。 これをするとプレイヤーの周りを惑星(地形)が回っているような感じになり、しなければ、惑星にプレイヤーがくっついて一緒に回っているような感じになります。 計算が難しくなる・・・というより、オブジェクトがたくさんあって混乱することが予想される場合は、先に述べたようなツリー構造そのままのオブジェクトを作って 親オブジェクトに変化があると、子オブジェクトも一緒に計算してくれるような感じにすれば、計算の面倒からは開放されるでしょう。回転や移動させたい物についてのみ考えればよくなります。 meshやmatrixといったプロパティだけでなくTranslationとか、Orientationとか、Rotationとか、そういうメソッドもメンバに含めてしまって。 実際計算する時に、例えば画面全体なら、display.Rotation(mat);だけで、回転できるような感じに実装します。 同階層にあるオブジェクトは回転させても互いに影響しあわず、親を回転させたときにのみ 一緒に回転するというような感じになります。 ついでに、こういった制限から逃れる等のために matpush(状態の保存)とmatpop(状態の復元)といったようなメソッドもあったほうがよいでしょう。 参考になりますでしょうか。
お礼
お返事ありがとうございます。 >回転後も、現座標の床から離れることなく主人公の向きを下向きにしたい という文章ですが、これは私の説明が下手糞でした。 下向きというのは、プレイヤーの回転の”下向き”ことで、 プレイヤーは戦車や車ではなくマリオのような人間型キャラであるため、 ○ ......\/ ...../ ↑人間キャラにこんな風には立ってほしくない。 ......○ ........|./ ..../ ↑こういう風に立ってほしかったという意味のつもりだったのですが。 これについては、INTLINSIDE様の文章と、 いつも世話になってる某知人の意見を参考に、実際のプログラムの動作をいろいろ試してした結果。 PlayerMatrixにModelRotをかける処理は、かける順序にもよるみたいですが、そうする事によりプレイヤーの表示が、地形についていく形で一緒に軸に対して回転してしまうため、上記に説明した「スマブラのメトロイドのコースみたいな……」という、処理の「回転中も、主人公の座標は地形に基本、ついていかない」という動きはなしえないので、そうしたいのならPlayerMatrixにModelRotをかけてはならないという意見は正しく、 反対に、回転する惑星の上に乗せた主人公を、惑星の表面に張り付いている状態で、惑星と一緒に回転させたい場合は、 PlayerMatrixに、先に主人公を任意の角度に傾けるための”原点中心の回転移動”。 すなわち、回転後も、現座標の床から離れることなく主人公の向きを下向きにしたいと、言って説明したつもりになっていた所……)の行列を、平行移動成分をPlayerMatrixにかける 前に かけてから、 ○ ......\/........× ...../ ......○ ........|./ ..../................○ かけると、○の処理のように主人公が傾くマトリックス。 これを、平行移動マトリックスをかける前に、計算上では軸に対してかけてやり、その後、平行移動マトリックスをかけることにより、解決しました! (ここの所が、頭のいい某知人の意見……) また、matpush(状態の保存)とmatpop(状態の復元)という関数についてですが……。 こんな関数がこの世に存在することを、今の今まで知りませんでした。 大変参考になりました。 私も最終的には人に物を教えられるほどのプログラマーになりたいものです。 ありがとうございました。