合計 昨日 今日

DxlibでのMATRIXがよくわかりません

[このトピックは解決済みです]

フォーラムルール
フォーラムルールはこちら  ※コードを貼り付ける場合は [code][/code] で囲って下さい。詳しくはこちら
Name: LisetteLander
[URL]
上級者(17,063 ポイント)
Date: 2012年2月02日(木) 00:44
No: 1
(OFFLINE)

 DxlibでのMATRIXがよくわかりません

MATRIXについて調べてみたのですがいまいちよくわかりません。

MATRIXとは拡大率・角度・三次元座標
のそれぞれを複合して持てる型
という考えなのですが

そうすると順番によって動作が違う
というのが意味不明です。

xに5移動
yに-3移動
zに4移動
これらの順番をいくら変えようと1フレーム内で完結していれば
人間からはどうみても同じにしかみえないのではないのでしょうか?

それとも理解が浅いのであればわかりやすい解説をお願いします・・

参考にしたサイトです↓
http://i-libro.net/wpmu/blog/archives/618

Name: ISLe
[URL]
ハッカー(266,335 ポイント)
Date: 2012年2月02日(木) 04:16
No: 2
(OFFLINE)

 Re: DxlibでのMATRIXがよくわかりません

平行移動してから回転

回転してから平行移動
では結果が違うことが分かりますか?

リンク先にちゃんと図入りで書いてありますね。

Name: softya(ソフト屋)
(副管理人)
[URL]
ウィザード(1,149,155 ポイント)
Date: 2012年2月02日(木) 09:08
No: 3
(OFFLINE)

 Re: DxlibでのMATRIXがよくわかりません

(0,0,0)座標を中心にして回りますので、回転してから並行移動するとその場で回転してから平行移動します。
逆に平行移動してから回転すると(0,0,0)座標を中心に平行移動した距離分離れた距離で回転します。
ちなみに移動だけの順番を変えても影響はありません。
自分でためしてみるのが一番だと思います。

それと回転自体が順番によって結果が変わります。
「無限小回転1 [物理のかぎしっぽ]」
http://hooktail.sub.jp/mechanics/infinitesimalRot1/
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

Name: LisetteLander
[URL]
上級者(17,063 ポイント)
Date: 2012年2月02日(木) 09:16
No: 4
(OFFLINE)

 Re: DxlibでのMATRIXがよくわかりません

自分の考え方だと両方共「自転しながら平行移動」になるのですが
無題.PNG
無題.PNG (11.98 KiB) 表示数: 2332 回


また、
コピー ~ 無題.PNG
コピー ~ 無題.PNG (12.01 KiB) 表示数: 2332 回

みたいになるのとするとMATRIXではダイレクトに指定した座標にモデルを置くことができないようなきがするのですが・・・
ゲームを作る時初期座標だけ設定してあとは座標移動ですべてこなすのでしょうか?

Name: softya(ソフト屋)
(副管理人)
[URL]
ウィザード(1,149,155 ポイント)
Date: 2012年2月02日(木) 09:19
No: 5
(OFFLINE)

 Re: DxlibでのMATRIXがよくわかりません

何処を回転の中心に回転するかって所がポイントです。
その図では常に物体中心で回っていますが、何を回転軸に廻るのでしょうか?

[補足]数学的な自転というのは座標(0,0,0)を中心に回っています。常に回転は(0,0,0)を中心に行われますので、自転と公転は実は表裏一体です。
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

Name: LisetteLander
[URL]
上級者(17,063 ポイント)
Date: 2012年2月02日(木) 09:38
No: 6
(OFFLINE)

 Re: DxlibでのMATRIXがよくわかりません

softya(ソフト屋) さんが書きました:(0,0,0)座標を中心にして回りますので、回転してから並行移動するとその場で回転してから平行移動します。
逆に平行移動してから回転すると(0,0,0)座標を中心に平行移動した距離分離れた距離で回転します。
ちなみに移動だけの順番を変えても影響はありません。
自分でためしてみるのが一番だと思います。

(0,0,0)というのはローカル座標ですか?
例で疑問になったのは
「並行移動して回転する」を毎フレーム行うと渦巻状に離れていくと予想したのですが
先のリンク先ではどうも回転を維持するようでした。

→毎フレーム宣言・代入しているだけでした。
→しかし回転軸座標の維持と回転角度がどうも矛盾するような・・・
→自分の考えだと毎フレーム代入しているのならば毎フレーム初期値からその回転する角度の分だけ回転して、傍目からは止まってるように見えるはずでは・・・

だとするとここからは本当に確かめてもない予想ですが
「MATRIXとはローカル座標の(0,0,0)を起点に動くローカル内での操作」とすれば
「ワールド変換するための座標」と「ローカル座標」の
2つが存在するのでしょうか?
無題.PNG
無題.PNG (16.47 KiB) 表示数: 2328 回


softya(ソフト屋) さんが書きました:それと回転自体が順番によって結果が変わります。
「無限小回転1 [物理のかぎしっぽ]」
http://hooktail.sub.jp/mechanics/infinitesimalRot1/

ありがとうございます!
回転だけでもめんどくさそうですね・・・
最後に編集したユーザー LisetteLander [ 2012年2月02日(木) 09:50 ], 累計 1 回

Name: softya(ソフト屋)
(副管理人)
[URL]
ウィザード(1,149,155 ポイント)
Date: 2012年2月02日(木) 09:44
No: 7
(OFFLINE)

 Re: DxlibでのMATRIXがよくわかりません

便宜上ワールド座標とローカル座標がありますが、これは掛け合わせる順番で作り出されるものです。

回転1→移動→回転2

と掛け合わさっている場合、回転1はローカル回転で回転2はワールド回転です。
回転1と回転2は(0,0,0)を中心に回っています。
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

Name: LisetteLander
[URL]
上級者(17,063 ポイント)
Date: 2012年2月02日(木) 09:56
No: 8
(OFFLINE)

 Re: DxlibでのMATRIXがよくわかりません

えーと、じゃあMATRIX変数をゲームのキャラクターのクラスメンバでPositionAngleSizeなんて名前と用途で持ってると・・・

Name: beatle
[URL]
ハッカー(101,578 ポイント)
Date: 2012年2月02日(木) 10:19
No: 9
(OFFLINE)

 Re: DxlibでのMATRIXがよくわかりません

数学的なことを書きます.
行列AとBを考えます.一般に,行列の積について交換則は成り立たず,A×B B×Aです.実数の掛け算では交換則が成り立ちますから,a×b = b×aですが,行列では違います.
(特殊な行列だとA×B = B×Aとなることもあります)

行列Aが回転を表し,Bが移動を表すとすると,点Xを原点まわりに回転させてから移動させる式は,点Xの移動先の点をY1とすると
Y1 = B×A×X
となります.一方,点Xを移動させてから原点まわりに回転させる式は,点Xの移動先の点をY2とすると,
Y2 = A×B×X
です.A×B ≠ B×Aですから,当然B×A×X ≠ A×B×X,すなわちY1 ≠ Y2となり,「回転→移動」と「移動→回転」は違うということが分かります.

Name: LisetteLander
[URL]
上級者(17,063 ポイント)
Date: 2012年2月02日(木) 12:42
No: 10
(OFFLINE)

 Re: DxlibでのMATRIXがよくわかりません

実数と、行列の「適用する順番」での動きの違いは理解できました。
ありがとうございます。
あと、ちょっと脱線するかもしれませんが質問させてください。

①”他のクラス”でモデルファイルをロードし、ハンドルを保持しておく。(配列に入れて列挙体で定義する
②キャラクタクラスのメンバに、”他のクラス”に保持してあるハンドルをコピーする。
③そのキャラクターのシーケンスに入ったら⑥でMV1GetMatrix()で取得したキャラクタクラスのメンバ「PAS」に保持してMATRIXをメンバのハンドルに適用する。(1フレーム前のキャラクターを再現する)
④MATRIX型の「tmp」を宣言し、1フレーム内で行う動作を適用する。
⑤「tmp」を「PAS」に加算する。
⑥「tmp」を破棄し、MV1GetMatrix()で適用後(⑤の加算)のMATRIXを③のために保持しておく。

というやり方を思いついたのですが、如何でしょうか・・・
「ひとつのモデルを使いまわす」「モデル情報を変更させない(const)」「MATRIX型には座標と角度と大きさが保存できる」
というのが前提条件です。(3つめは理想

これはまずい!というのがあったらよろしくお願いします。

Name: softya(ソフト屋)
(副管理人)
[URL]
ウィザード(1,149,155 ポイント)
Date: 2012年2月02日(木) 12:58
No: 11
(OFFLINE)

 Re: DxlibでのMATRIXがよくわかりません

よく分からないので整理してみます。

①”他のクラス”でモデルファイルをロードし、ハンドルを保持しておく。(配列に入れて列挙体で定義する
クラスBでモデルファイルをロードしてモデル・ハンドル1を保持。

②キャラクタクラスのメンバに、”他のクラス”に保持してあるハンドルをコピーする。
クラスAにクラスBのモデル・ハンドル1をコピー。

③そのキャラクターのシーケンスに入ったら⑥でMV1GetMatrix()で取得したキャラクタクラスのメンバ「PAS」に保持してMATRIXをメンバのハンドルに適用する。(1フレーム前のキャラクターを再現する)
クラスAのMATRIX変数PASをモデル・ハンドル1のMATRIXとしてMV1SetMatrixで適用。

④MATRIX型の「tmp」を宣言し、1フレーム内で行う動作を適用する。
MATRIX変数tmpにこのフレームでの変化を書き込む。

⑤「tmp」を「PAS」に加算する。
クラスAのMATRIX変数PASにMATRIX変数tmpを加算

⑥「tmp」を破棄し、MV1GetMatrix()で適用後(⑤の加算)のMATRIXを③のために保持しておく。
クラスAのMATRIX変数PASをモデル・ハンドル1のMATRIXとしてMV1SetMatrixで適用? じゃあ、③は何のために?

まとめると、これの分からない所は描画のタイミングとモデル・ハンドル1のMATRIXが③から⑥以外で変更されるのか?って事と③と⑥で2回も適用する理由は?
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

Name: LisetteLander
[URL]
上級者(17,063 ポイント)
Date: 2012年2月02日(木) 14:22
No: 12
(OFFLINE)

 Re: DxlibでのMATRIXがよくわかりません

⑥は間違えました。
適用後のMATRIXは③で手に入れるので⑥で手に入れる必要はありません。
「tmpとPASの加算したものをMV1SetMatrixで適用し、それの描画とtmpの破棄」です。

PASは今の情報(前のフレーム)で、tmpはこれから動く(このフレーム)情報です

また、③から⑥以外では同一のモデルを使った他のクラス(ここでは敵、クラスC?)が変更します。
キャラクターと同じモデルを使用したクラスがあれば、その分だけ1フレームで書き換えと描画が行われます。

Name: LisetteLander
[URL]
上級者(17,063 ポイント)
Date: 2012年2月02日(木) 14:29
No: 13
(OFFLINE)

 Re: DxlibでのMATRIXがよくわかりません

あれ、既に存在するMATRIXに変化を加えるにはtmpはいらないのかな・・・
いや、でも直接MATRIXに回転を加えると初期位置を軸に勝手に移動するのでは・・・
試してきます

Name: softya(ソフト屋)
(副管理人)
[URL]
ウィザード(1,149,155 ポイント)
Date: 2012年2月02日(木) 14:44
No: 14
(OFFLINE)

 Re: DxlibでのMATRIXがよくわかりません

そうだとすれば③は不要ですね。
それと加算であれば順番は関係ないです。積は順番があります。
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

Name: beatle
[URL]
ハッカー(101,578 ポイント)
Date: 2012年2月02日(木) 15:19
No: 15
(OFFLINE)

 Re: DxlibでのMATRIXがよくわかりません

行列の加算に何か意味があるのでしょうか.例えば10度回転させる行列2つを加算しても,20度回転させる行列にはなりません.

Name: softya(ソフト屋)
(副管理人)
[URL]
ウィザード(1,149,155 ポイント)
Date: 2012年2月02日(木) 15:42
No: 16
(OFFLINE)

 Re: DxlibでのMATRIXがよくわかりません

beatle さんが書きました:行列の加算に何か意味があるのでしょうか.例えば10度回転させる行列2つを加算しても,20度回転させる行列にはなりません.


スケーリングや回転を含めたらただの加算ではダメですね。
RASとtmpに含まれるのが平行移動だけならOKですが。
[訂正] 平行移動成分の差分だけと言い直しておきます。
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

Name: LisetteLander
[URL]
上級者(17,063 ポイント)
Date: 2012年2月02日(木) 17:40
No: 17
(OFFLINE)

 Re: DxlibでのMATRIXがよくわかりません

そうなんですか
では、回転のメソッドと平行移動のメソッドの2つを用意してそれぞれtmp積・tmp和と自動化したほうがいいですね
で、描画の直前にtmp積(回転)→tmp和(移動)の順でハンドルに適用したほうがよさそうです。
(0,0,0)を中心に回転しているのならば回転による移動は行われないからです。

①クラスBでモデルファイルをロードしてモデル・ハンドル1を保持。

②クラスAにクラスBのモデル・ハンドル1をコピー。

③MATRIX変数tmpPositionにこのフレームでの並行移動量を代入。
③MATRIX変数tmpAngleSizeにこのフレームでの角度量と大きさを代入。
//↑ゲーム内容に依存

④クラスAのMATRIX変数tmpAngleSizeをPASに掛ける(MMult())
⑤クラスAのMATRIX変数tmpPositionをPASに加える(MAdd())

⑥PASをモデルハンドルにMV1SetMatrix()で適用する。

⑦「tmpAngleSize」と「tmpPosition」を破棄・モデルの描画

⑧ゲーム内ループを通じて③に戻る

↑これならばできそうな気がします。

ただ、やはり画像みたいに渦巻状に広がる気がしてなりません・・・
2フレーム目以降の回転軸が(0,0,0)でなかったら(毎回tmpを初期化してるので(0,0,0)を中心とした回転をモデルに適用できたりする?)
まだ理解していないのでわかりません!
コード[C++]: 全て選択
1
2
3
int tmp=0;
int PAS;
while(1){tmp++;PAS=tmp;}

↑こう、渦巻きになりそう
コード[C++]: 全て選択
1
2
3
int tmp;
int PAS;
while(1){tmp=0;tmp++;PAS=tmp;}
添付ファイル
無題.PNG
無題.PNG (14.72 KiB) 表示数: 2230 回

Name: softya(ソフト屋)
(副管理人)
[URL]
ウィザード(1,149,155 ポイント)
Date: 2012年2月02日(木) 18:00
No: 18
(OFFLINE)

 Re: DxlibでのMATRIXがよくわかりません

まず、その回転変換は変な回転になります。
回転1→平行移動→回転2→平行移動→回転3→ →回転n
とやっているのと同じです。
ただし、平行移動は加算しているのでもっとマズイです。単位行列からの平行移動マトリクス(加算用ではなく乗算用)ですので、そのまま加算すると意図しないスケーリングまでかかることになります。

一番単純に済ますのは、現在座標と現在ローカル回転角を保持していて、その差分だけ変更計算して毎回座標とローカル回転角をMV1SetRotationXYZとMV1SetPositionで設定するということです。

[補足]クラスA・Bは抜きで行列部分だけなら難しくないので差分だけで動くMATRIXのプログラムを作ってみると分かります。そのプログラムをベースに議論したほうが良いでしょう。
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

Name: ISLe
[URL]
ハッカー(266,335 ポイント)
Date: 2012年2月02日(木) 18:06
No: 19
(OFFLINE)

 Re: DxlibでのMATRIXがよくわかりません

そもそもどうしてMATRIXを引き継いで更新しないといけないのですか?

座標と向きと拡大率のパラメータで毎フレームMATRIXを求めるほうが速いと思いますけど。

Name: LisetteLander
[URL]
上級者(17,063 ポイント)
Date: 2012年2月02日(木) 18:37
No: 20
(OFFLINE)

 Re: DxlibでのMATRIXがよくわかりません

行列のほうが速い~
ときいたので、何も考えず飛びつきました・・・

X,Y,Z,Xa,Ya,Za,Sizeとパラメータをメンバで持っといて、
毎フレームMATRIX変換、
もしくsoftyaさんのMV1SetRotationXYZとMV1SetPositionでそれぞれ設定したほうがいいんですね
そっちのほうが2Dの延長で行ける気がしなくもない・・・

そこで疑問に思ったのですが
行列を使うのはどういうゲームが対象でしょうか?
今後フライトシミュレーションや結構動き回るゲームを作るつもりなのですが、将来的に行列は必須ですか?
No1のリンク先で「行列の計算をするためにGPUがあるといっても過言ではありません」的なことを言っていたのですが・・・

Name: softya(ソフト屋)
(副管理人)
[URL]
ウィザード(1,149,155 ポイント)
Date: 2012年2月02日(木) 19:12
No: 21
(OFFLINE)

 Re: DxlibでのMATRIXがよくわかりません

sood さんが書きました:行列を使うのはどういうゲームが対象でしょうか?

モデルのボーン(DXライブラリのフレーム操作)のマトリックスを直接いじる場合でしょうか。
アニメーションに頼らない処理には必要です。自動でカメラ目線とか。

sood さんが書きました:今後フライトシミュレーションや結構動き回るゲームを作るつもりなのですが、将来的に行列は必須ですか?

フライトシミュレーションだと単純な回転行列ではジンバル・ロックするのでクォータニオン(4元数)は必須ですね。単純な回転行例より原理自体は複雑です。
まぁ使い方だけ覚えれば良いんですけどね。

sood さんが書きました:No1のリンク先で「行列の計算をするためにGPUがあるといっても過言ではありません」的なことを言っていたのですが・・・

これはモデルの描画用の座標点のマトリックス計算なのでこちらが適用して描画した先で行われるものです。
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

Name: ISLe
[URL]
ハッカー(266,335 ポイント)
Date: 2012年2月02日(木) 23:27
No: 22
(OFFLINE)

 Re: DxlibでのMATRIXがよくわかりません

姿勢に対して物理的な制御(いわゆる物理エンジンの実装など)をする場合は、ベクトルや行列の演算が必要になります。
3D空間にモデルを描画するだけなら特に行列を意識しなくてもゲームプログラムは作れます。

8ビットパソコンの頃からフライトシミュレータはありました。
当時はクォータニオンというのを聞いたことがなかったですけど、どうやってジンバルロックを防いでいたんですかね。
やり方を聞いたような気がするんですが昔のことで忘れてしまいました。

Name: LisetteLander
[URL]
上級者(17,063 ポイント)
Date: 2012年2月04日(土) 14:58
No: 23
(OFFLINE)

 Re: DxlibでのMATRIXがよくわかりません

[解決!]

なるほどー
では行列ではなくX,Y,Zで作ってみます。
ありがとうございました!


Return to C言語何でも質問掲示板

オンラインデータ

このフォーラムを閲覧中のユーザー: なし & ゲスト[19人]