行列でモデルを動かした時に予想と違う動きをする

フォーラム(掲示板)ルール
フォーラム(掲示板)ルールはこちら  ※コードを貼り付ける場合は [code][/code] で囲って下さい。詳しくはこちら
珈琲

行列でモデルを動かした時に予想と違う動きをする

#1

投稿記事 by 珈琲 » 12年前

立方体モデルを行列で動かしてみたのですが、ことごとく予想とハズレます
コードはMV1GetMatrixで立方体の行列を取得し、それにMGetRotY()やMGetTranslate()で生成した回転行列、移動行列と
MMultで掛けあわせたものです。

コードは色々試して
・回転しない、移動しない
・回転する、移動しない
・回転しない、移動する
・回転する、移動する
の4通りにしました

で、例えば2番めのコードは、MV1GetMatrixで立方体の行列(拡大、回転、座標の要素)にMGetRotY()で取得した行列(回転)をMMult()で合成し、毎フレーム1度づつ回転するものです
しかし、結果として、月みたいな、一面をこっちに0,0,0に向けた状態を維持しながら回転する動きをします(衛星軌道?)

コード:

	int Handle = MV1LoadModel("block.x");
	int PlanetariumHandle = MV1LoadModel("planetarium/planetarium.mqo");
	
	float i=PHI/180;
	float t=5;

	while(Loop()){

		//予想:ちょっと偏った状態で止まっている
		//結果:ちょっと偏った状態で止まっている 予想あたり
		//MV1SetMatrix(Handle,MMult(MGetRotY(i),MGetTranslate(VGet(t,0,0))));

		//予想:移動せずにその場で回転する
		//結果:一点を中心にサテライト旋回 予想ハズレ
		//MV1SetMatrix(Handle,MMult(MMult(MV1GetMatrix(Handle),MGetRotY(i)),MGetTranslate(VGet(t,0,0))));

		//予想:回転せずに等速直線運動
		//結果:一定の回転、一定の速度で移動する 予想ハズレ
		//MV1SetMatrix(Handle,MMult(MGetRotY(i),MMult(MV1GetMatrix(Handle),MGetTranslate(VGet(t,0,0)))));

		//予想:現在のHandleの行列と回転行列、現在のHandleの行列と移動行列が組み合わさり、それが現在のHandleにセットされ、一定の回転、一定の速度で移動する
		//結果:最初ブルブルになってドカーンとどっかいく 予想ハズレ
		//MV1SetMatrix(Handle,MMult(MMult(MV1GetMatrix(Handle),MGetRotY(i)),MMult(MV1GetMatrix(Handle),MGetTranslate(VGet(t,0,0)))));


		MV1DrawModel(Handle);
		MV1DrawModel(PlanetariumHandle);

		SetCameraPositionAndTarget_UpVecY(VGet(5000,5000,5000),VTransform( VGet(0,0,0) , MV1GetMatrix( Handle ) ));
	}
つまりMV1GetMatrix(Handle)とMMultしたMGetRotY(i)が座標にも影響を与えたと思い、(拡大がなぜ影響ないのかはしらない)
MV1GetMatrix(Handle)で取得した行列から拡大、回転、座標を取得する関数をまた個別に使用するのかと考えたのですが、
拡大と行列の関数はあるのですが回転がありません

>MGetScale  拡大行列を取得する
>MGetTranslate  平行移動行列を取得する
http://homepage2.nifty.com/natupaji/DxL ... nc_3d.html

みんなどのようしているのかというのと、
もし出来たら↑の間違ってるプログラムを、予想された正しいプログラムにしてもらえませんか?

ISLe
記事: 2650
登録日時: 15年前
連絡を取る:

Re: 行列でモデルを動かした時に予想と違う動きをする

#2

投稿記事 by ISLe » 12年前

平行移動→回転、と、回転→平行移動、では変換後の座標が異なることはお分かりでしょうか。

モデルから取得した行列に対して演算を行い再び設定するという方法だとどんどん原点からズレていき配置が難しくなります。

モデルから取得した行列を、いったん原点に対して平行移動し、回転を戻し、新たに拡大したい分を計算し、戻した分の逆の回転をし、新たに回転したい分を回転し、原点に対して平行移動した分を逆に平行移動し、新たな分の並行移動することで予想通りになると思われます。

上記の方法だととても面倒くさいので、一般的には、毎回原点からの拡大→回転→平行移動の行列を求め、モデルにセットします。

珈琲

Re: 行列でモデルを動かした時に予想と違う動きをする

#3

投稿記事 by 珈琲 » 12年前

ありがとうございます

>モデルから取得した行列を、いったん原点に対して平行移動し、回転を戻し、新たに拡大したい分を計算し、戻した分の逆の回転をし、新たに回転したい分を回転し、原点に対して平行移動した分を逆に平行移動し、新たな分の並行移動することで予想通りになると思われます。

(わかりやすく自分なりに言い直して)
モデルから行列抽出 → 行列から拡大と回転と座標を抽出 → 計算 → モデルの行列を初期化 → 再適用
という流れでしょうか

原点からというのは、行列からデータを引っ張ってくるのではなく、全てのモデルが1から計算され直される、ということですか?

過去に、
パーツをカスタマイズするロボットゲーを作りたくてロボットのボディの斜辺に腕を別にモデリングしたポリゴンモデルを取り付けたい
と質問した所、”行列でなければ難しい”と返答が帰ってきて、
恐らくMGetRotAxis()という関数?を利用しろ、という事だと思うのですが、
上記の方法で可能でしょうか?(後出しジャンケンみたいで申し訳ありません)

ロボットのボディに行列を適用 → ロボットのパーツの行列を、ボディから計算して取得 → ロボットのパーツに行列を適用
って流れになると思うのですが、行列適用済みのボディ位置からパーツの差分座標や角度を計算して正しいパーツの座標を取得できるか不安です。

ISLe
記事: 2650
登録日時: 15年前
連絡を取る:

Re: 行列でモデルを動かした時に予想と違う動きをする

#4

投稿記事 by ISLe » 12年前

珈琲 さんが書きました:原点からというのは、行列からデータを引っ張ってくるのではなく、全てのモデルが1から計算され直される、ということですか?
行列を元に戻すというのは一に戻すということなのでそういうことになります。
つまるところ元に戻すという処理はまったくの無駄です。
珈琲 さんが書きました:過去に、
パーツをカスタマイズするロボットゲーを作りたくてロボットのボディの斜辺に腕を別にモデリングしたポリゴンモデルを取り付けたい
と質問した所、”行列でなければ難しい”と返答が帰ってきて、
恐らくMGetRotAxis()という関数?を利用しろ、という事だと思うのですが、
MGetRotAxis関数は回転行列を求める方法のひとつでしかありません。
モデルにセットするのは拡大縮小・回転・平行移動のそれぞれに行列を求めて順番に掛け合わせたものです。
#いったん行列を求めてから掛ける必要があるのはDXライブラリにあらかじめ用意されている関数の仕様です。


ロボットのボディにパーツを取り付ける場合…

あらかじめロボットの基本姿勢とパーツの原点を合わせてモデリングしているなら、ロボットのボティにセットする行列をパーツにもセットします。

パーツごとにロボットの基本姿勢と異なる原点であれば、パーツをロボットの基本姿勢に配置する行列を求め、それにロボットのボティにセットした行列を掛けたものをパーツのモデルにセットします。

ボディがアニメーションする場合はアニメーションを適用した行列を取り出して使います。
ロボットのボディをモデリングするときパーツを配置する場所に特定のオブジェクトを埋め込んでおくと処理がしやすいです。

珈琲

Re: 行列でモデルを動かした時に予想と違う動きをする

#5

投稿記事 by 珈琲 » 12年前

>パーツごとにロボットの基本姿勢と異なる原点であれば、パーツをロボットの基本姿勢に配置する行列を求め、それにロボットのボティにセットした行列を掛けたものをパーツのモデルにセットします。
なるほど、ロボットのボディを原点とした行列になるんですね、これならパーツの行列を取得するのが簡単そうです

>ロボットのボディをモデリングするときパーツを配置する場所に特定のオブジェクトを埋め込んでおくと処理がしやすいです。
特定のオブジェクトというのは・・?
ボディとパーツの接続箇所に球を配置するとか・・・??


回答をまとめさせてもらうと、
クラス内のメンバ変数として保持するのはそれぞれの型の拡大率、回転、座標で、
描画直前に行列に変換してモデルハンドルにセットする。
ロボットのパーツの行列はルートであるボディの行列と、パーツの差分行列を掛けあわせて取得する。

アバター
softya(ソフト屋)
副管理人
記事: 11677
登録日時: 15年前
住所: 東海地方
連絡を取る:

Re: 行列でモデルを動かした時に予想と違う動きをする

#6

投稿記事 by softya(ソフト屋) » 12年前

珈琲 さんが書きました: >ロボットのボディをモデリングするときパーツを配置する場所に特定のオブジェクトを埋め込んでおくと処理がしやすいです。
特定のオブジェクトというのは・・?
ボディとパーツの接続箇所に球を配置するとか・・・??
見えないボーンやモデルなどのジョイント専用の部分を作ります。
可動した場合のローカル・マトリクスが最終反映されている部分がないと接続が困難なので。
珈琲 さんが書きました: 回答をまとめさせてもらうと、
クラス内のメンバ変数として保持するのはそれぞれの型の拡大率、回転、座標で、
描画直前に行列に変換してモデルハンドルにセットする。
ロボットのパーツの行列はルートであるボディの行列と、パーツの差分行列を掛けあわせて取得する。
ここら辺は試行錯誤で理解してもらったほうが良いと思います。
関節だけはちょっと複雑で簡単なモデルを作ってアニメーションでの動作を試行錯誤してみてください。
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

珈琲

Re: 行列でモデルを動かした時に予想と違う動きをする

#7

投稿記事 by 珈琲 » 12年前

ソフト屋さん、ありがとうございます

>ここら辺は試行錯誤で理解してもらったほうが良いと思います。
>関節だけはちょっと複雑で簡単なモデルを作ってアニメーションでの動作を試行錯誤してみてください。
わかりました、しばらく色々試してみます。

>見えないボーンやモデルなどのジョイント専用の部分を作ります。
>可動した場合のローカル・マトリクスが最終反映されている部分がないと接続が困難なので。
うーん、ボーンは触ったことないのでピンと来ません
今参考サイトを見てみたのですが、腕のボーンの付け根に”重ねる用”の親ボーンをつける感じ・・・?
とりあえず触ってみないと前に進めなさそうですね。

もしそれでもピンとこなかったらまた質問させて頂きます。

お二方とも回答ありがとうございました。

閉鎖

“C言語何でも質問掲示板” へ戻る