• ベストアンサー
※ ChatGPTを利用し、要約された質問です(原文:3Dゲームを作っているのですが、行列計算で気が狂いそうです。 助けてください。 )

3Dゲームの行列計算で困っています

このQ&Aのポイント
  • 3Dゲームを作る際に、行列計算に困っています。
  • 特に、地形が回転する場合に主人公の位置の管理が難しいです。
  • 床の角度に応じて重力の向きを変えるプログラムを実装しても、主人公の位置が回転してしまいます。この問題を解決するための数学力が必要です。

質問者が選んだベストアンサー

  • ベストアンサー
回答No.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(状態の復元)といったようなメソッドもあったほうがよいでしょう。 参考になりますでしょうか。

NTD_Kyoto
質問者

お礼

お返事ありがとうございます。 >回転後も、現座標の床から離れることなく主人公の向きを下向きにしたい という文章ですが、これは私の説明が下手糞でした。 下向きというのは、プレイヤーの回転の”下向き”ことで、 プレイヤーは戦車や車ではなくマリオのような人間型キャラであるため、 ○ ......\/ ...../ ↑人間キャラにこんな風には立ってほしくない。 ......○ ........|./ ..../ ↑こういう風に立ってほしかったという意味のつもりだったのですが。 これについては、INTLINSIDE様の文章と、 いつも世話になってる某知人の意見を参考に、実際のプログラムの動作をいろいろ試してした結果。 PlayerMatrixにModelRotをかける処理は、かける順序にもよるみたいですが、そうする事によりプレイヤーの表示が、地形についていく形で一緒に軸に対して回転してしまうため、上記に説明した「スマブラのメトロイドのコースみたいな……」という、処理の「回転中も、主人公の座標は地形に基本、ついていかない」という動きはなしえないので、そうしたいのならPlayerMatrixにModelRotをかけてはならないという意見は正しく、 反対に、回転する惑星の上に乗せた主人公を、惑星の表面に張り付いている状態で、惑星と一緒に回転させたい場合は、 PlayerMatrixに、先に主人公を任意の角度に傾けるための”原点中心の回転移動”。 すなわち、回転後も、現座標の床から離れることなく主人公の向きを下向きにしたいと、言って説明したつもりになっていた所……)の行列を、平行移動成分をPlayerMatrixにかける 前に かけてから、 ○ ......\/........× ...../ ......○ ........|./ ..../................○ かけると、○の処理のように主人公が傾くマトリックス。 これを、平行移動マトリックスをかける前に、計算上では軸に対してかけてやり、その後、平行移動マトリックスをかけることにより、解決しました! (ここの所が、頭のいい某知人の意見……) また、matpush(状態の保存)とmatpop(状態の復元)という関数についてですが……。 こんな関数がこの世に存在することを、今の今まで知りませんでした。 大変参考になりました。 私も最終的には人に物を教えられるほどのプログラマーになりたいものです。 ありがとうございました。

全文を見る
すると、全ての回答が全文表示されます。

関連するQ&A

  • 任意軸回転を、XYZ軸回転の組み合わせに分解する?

    こんにちは、私は今DirectXを使って物理シミュレーションを行おうとしております。 そこで物体を任意軸回転させて表示したいのですが、どういった方法を用いれば実現できますか? http://marupeke296.com/DXGSmp_No10_Quaternion.html このサイトで解説されているようにクォータニオンを使うのでしょうか? ただこのサイトで示されているサンプルでは、玉ひとつひとつが回転しているわけではなく、位置がある軸に関して回転させた位置へ「並進させる」ということを行っています。 私は物体を回転させるときに、任意軸回転を使いたいなと思っています。 -- D3DXMatrixRotationX(&Rot_X, angle); D3DXMatrixMultiply(&World, &World, &Rot_X); -- 以上はX軸回転を行う行列をワールド座標変換行列に掛けるコマンドですが、この勢いで任意軸回転行列を作成・掛けるといったことはできますか? 知識が足りなく稚拙な表現で申し訳ありませんが・・・ 任意軸回転をXYZ軸回転の組み合わせに分解できれば D3DXMatrixRotationX(YやZ)とD3DXMatrixMultiply関数のみを使って簡単にできちゃうのですがそのような数学的手法は存在しますか? それとも、任意軸回転関数を自前で既に作ってあるので D3DXMATRIX型の変数にその値を手動で注入(構造体の中身を知る必要あり)、D3DXMatrixMultiply関数で掛けるといった操作でいけちゃうでしょうか? あとでちょっとやってみます。すみません。しかしD3DX~系の用意された関数の域を出て気持ちよくはないですが。

  • VBを使って行列による3Dの図形やグラフを描画するのですが・・

    本をよんでいるのですが自分の創造した図形の3D座標を2Dの座標に変換する仕方やその点の座標をどのように行列に当てはめるのかがわかりません。行列での回転・縮小拡大の仕方などが・・。 3Dの描画や行列に詳しい方教えてほしいです。 もし詳しくなくても関係のあるVBサイトがあれば教えてほしいです。 お願いします。

  • 回転行列について問題

    行列 A ~ F は同時座標系で点の座標を表現する場合の、原点周りの各種の回転 行列である。 √2/ 2, -√2/ 2, 0 (A) √2/ 2 , √2/ 2, 0 0 , 0 , 1 √3 / 2 , 1/2 , 0 (B) -1/2 , √3/ 2 , 0 0 , 0 , 1 1.それぞれどのような回転角度に対応するか、下の値から選んで記載せよ。(イ~ ヘ) 答えは A :イ B: ロ 等と答えればよい。もし該当するものがなければ、そ の効果内容を記載すること。 イ ―90° ロ -30° ハ 30° ニ 45° ホ 60° ヘ 90° 2.上記の行列に対して、次の各演算を行った行列を作用するとどのようなことになる か(点はどのような変換を受けるか)を1~5の各ケースについて記載せよ。 1.A ・A 2.D・D 3.B・D 4.C ・D 5.D・D・D 3. 問題 1 のいくつかの行列を用いると、15°回転する行列を作ることができる。そ れはどのような行列になるか? (ヒント:問題 2 と同様に問題 1 の行列のかけ算で 求めることができる)。

  • ワールド座標系で回転

    こんにちは。3Dプログラムの仕事の指示を受けました。 3Dプログラムは無知でして見よう見まねで行っています。 現在回転行列について困っています。 正方形のモデルをY軸に45度、X軸に45度回転させようとしています。 現在はモデルのローカル座標系で回転するのでY軸の回転でローカル座標系が変わった後にX軸で回転します。これを相対変換と言えばよろしいのでしょうか。 WorldMatrix = RotationX(AngleX) ; WorldMatrix *= RotationY(AngleY) ; WorldMatrix *= RotationZ(AngleZ) ; 上記の回転ではなく、ワールド座標系で回転させたいのですが、このときの回転行列はどのようにして求めればよろしいのでしょうか? Y軸に45度回転させても座標系はそのまま。そしてX軸で45度させるためにはどのようにすればよろしいのでしょうか? わかりづらいですが添付した図のようになればと思っています。

  • DirectXにおける2Dと3Dの座標の違い

    DirectXを使ったプログラミングの初心者で、Softbank Creativeの「シューティングゲームプログラミング」を使って勉強しています。 ライブラリの内容も関わってくるので少し分かりづらい質問ですが、2Dと3Dとで座標の指定の仕方が違うのがよく分かりません。 3Dでは、 D3DXMATRIX mat_view; D3DXVECTOR3 vec_from=D3DXVECTOR3(0, 100, 0); D3DXVECTOR3 vec_lookat=D3DXVECTOR3(0, 0, 0); D3DXVECTOR3 vec_up=D3DXVECTOR3(0, 0, 1); D3DXMatrixLookAtLH(&mat_view, &vec_from, &vec_lookat, &vec_up); device->SetTransform(D3DTS_VIEW, &mat_view); D3DXMatrixOrthoLH(&mat_proj, 120, 90, 1, 1000); device->SetTransform(D3DTS_PROJECTION, &mat_proj); Graphics->SetLight(0, D3DLIGHT_DIRECTIONAL, -1.0f, -1.0f, -1.0f, 1000); このあたりでカメラを設定し、画面端のx座標が±0.6になる……といったことを決めていましたが、 2Dでは VERTEX vertex[4]={ {x, y, z, 1, diffuse, u, v}, {x, y+dy, z, 1, diffuse, u, v+dv}, {x+dx, y, z, 1, diffuse, u+du, v}, {x+dx, y+dy, z, 1, diffuse, u+du, v+dv} }; device->SetFVF(D3DFVF_VERTEX); device->DrawPrimitiveUP(D3DPT_TRIANGLESTRIP, 2, vertex, sizeof(VERTEX)); 例えば四角形ポリゴンを描くときにこんな風に記述して、 このx,yにはウィンドウの座標が入っています。 SETFVFでD3DFVF_XYZRHWを設定することで直接2Dに持ってこれる、というようなことが調べて分かったのですが、 三角形ポリゴンにテクスチャを貼り付けて2Dのような表現をする場合、必ずこのようにウィンドウに合わせた座標になる(する?)のでしょうか? つまり、3Dの時のように左端がx=-0.6……というような座標系で表現できないのでしょうか? 書籍には3Dから2Dに変換する式などがありましたが、このような変換をいちいち行わなくても最初から3Dの座標に2Dのものを表示できないのでしょうか? なにぶん初心者で見当外れのことを言っているかも知れませんが、ご教授をお願いいたします。

  • 誤差を最小化する相似変換行列の求め方

    三次元の変換行列について質問です。 空間上のある3点について、座標変換前と変換後の座標が与えられているとします。 その座標を元に、行った変換の表す行列を知りたいと考えております。 ただし変換は並進と回転のみとし、剪断変形等は行わないという条件です。 (行列は同次変換の形などで得られれば良いです) ただし、変換前と変換後では三点の相対的な位置関係は完璧には一致しておりません。 そのため得られた変換を元の3点に行った際に、変換後の3点の座標(既知)との 誤差を最小化したいという問題です。 変換が相似変換でなければ疑似逆行列により計算が可能と思いますが、 並進・回転のみなのでどうしようか聞きたいと思い質問をしました。 パラメータは「x, y, z 軸方向の並進移動量 + x, y, z 軸周りの回転量」の6つなので、 プログラムを組んで6パラメータを少しずつ変化させ、 誤差の二乗和が最小となる箇所を探すという方法は思いついております。 ですが、その他に行列計算により解析的に答えを得る方法はないでしょうか。 また、変換前後の3点を元に誤差を最小化する変換行列を得ることが可能であるなら、 座標の情報が3点でなくそれ以上の場合でも計算は可能でしょうか。 質問は数学のようですが、この手の計算はCGや画像処理等で多く行われていると 感じたことから、情報工学カテゴリーで質問をさせて頂きました。 よろしくお願いいたします。

  • 誤差を最小化する相似変換行列の求め方

    三次元の変換行列について質問です。 空間上のある3点について、座標変換前と変換後の座標が与えられているとします。 その座標を元に、行った変換の表す行列を知りたいと考えております。 ただし変換は並進と回転のみとし、剪断変形等は行わないという条件です。 (行列は同次変換の形などで得られれば良いです) ただし、変換前と変換後では三点の相対的な位置関係は完璧には一致しておりません。 そのため得られた変換を元の3点に行った際に、変換後の3点の座標(既知)との 誤差を最小化したいという問題です。 変換が相似変換でなければ疑似逆行列により計算が可能と思いますが、 並進・回転のみなのでどうしようか聞きたいと思い質問をしました。 パラメータは「x, y, z 軸方向の並進移動量 + x, y, z 軸周りの回転量」の6つなので、 プログラムを組んで6パラメータを少しずつ変化させ、 誤差の二乗和が最小となる箇所を探すという方法は思いついております。 ですが、その他に行列計算により解析的に答えを得る方法はないでしょうか。 また、変換前後の3点を元に誤差を最小化する変換行列を得ることが可能であるなら、 座標の情報が3点でなくそれ以上の場合でも計算は可能でしょうか。 よろしくお願いいたします。

  • 土木、設計、3D表示に詳しい方教えて下さい。

    国土地理院の基盤地図にも地形図が載っていない、約100m四方のマイナーな湿地帯を3次元モデル(メッシュデータ、鳥瞰図のような)で表示させたいのですが、どうすればいいのでしょうか? GPSと測量により100箇所の平面直角座標(x ,y)とその地点の高さ(DL)が分かっています。 座標はエクセルに入っており、ArcGIS 、PCmapping、カシミール、フリーソフトを使ってなんとか3D表示をさせたいです。 すみませんが、出来るだけ詳しく3D表示の方法を教えて下さい。 よろしくお願いします。

  • OpenGLのD3DTS_WORLDはどれですか?

    こんにちは。 OpenGLでプログラムを書いているものです。 もともとはずっとDirectXでプログラムを書いていたものですが、行列の扱い方で質問させてください。 DirectXでは変換行列はD3DTS_PROJECTION,D3DTS_VIEW,D3DTS_WORLDと3つあったと思うのですが(他にもテクスチャ変換行列などがありますが今回は除外)OpenGLでD3DTS_WORLDに当たるのはどれでしょうか? 現在私は以下のように考えています。 // 射影行列 glMatrixMode( GL_PROJECTION ); glLoadMatrixf( proj ); // ビューイング行列 glMatrixMode( GL_MODELVIEW ); glLoadMatrixf( view ); モデルの頂点を変換するワールド行列はどこにセットすればよいでしょうか? よろしくお願いします。

  • 行列の入れ替え

    次の処理を行うプログラムを書きたいのですが教えていただけないでしょうか? (処理) B列のあるセルの値が2000または2001の場合、当該行のc列からn列までのセルをコピーし、11行を挿入し、行列を入れ替えて貼り付ける。 この処理を繰り返したいです。             (処理前) A  B  C  D  E  F  G   H  I  J  L  M  N  O 1 2000  1  2  3  4  5  6  7  8  9  10  11  12 2 3 4 5 6 7 8 9 10 11 (処理後) A  B  C  D  E  F  G  H  I  J  L  M  N  O 1  2000  1 2      2 3      3 4      4 5      5 6      6 7      7 8      8 9      9 10     10 11     11 12     12 13     13 よろしくお願いします。