スポンサーサイト

上記の広告は1ヶ月以上更新のないブログに表示されています。
新しい記事を書く事で広告が消せます。

3D数学のメモ

3Dでよく使う数学の知識をメモってみた
誰かの助けになりますよ~に!

座標系で混乱したら
親指
人差し指が
中指
を思い出す
これも忘れたら
短い指から順にXYZと覚えておけばOK

回転方向は右ねじの法則と同じで
電流=軸
磁界=回転方向
要するに親指を軸の正方向に向けながら軸を掴んで4本の指の方向に回転する
右手系座標のときは右手で握り、左手系の場合は左手で行う

~内積~
ふたつのベクトルの角度を表せる
単位ベクトルを利用することで仕事量や角度を便利に扱える

a・b = |a||b|cosθ
θ = acos( a・b) / |a||b|

a・b>0  ならば 0<=θ<90
a・b==0 ならば θ==90
a・b<0  ならば 90<θ<=180

a|| = (a・b) * b / |b|^2
a⊥ = a - a||



~外積~
二つのベクトルに垂直なベクトルを求められる
a×bの垂直なベクトルの向きを知るには
ベクトルaの矢印の先にベクトルbを繋げてみてどっちに回っているかを確認する
その方向に握った4本指を合わせてみて親指が向いた方向が軸の向きになる
座標系が左手系なら左手で 右手系なら右手で行うこと
よって非可換
a×b = -(b×a)

外積の大きさは二つのベクトルの成す角度に関係する(2つのベクトルで作成した平行四辺形の面積になる)
|a×b| = |a||b|sinθ



~行列式~
3x3を三つのベクトルと考えると行列式はその三重積といえる
三重積=a・b×c(もちろん外積からじゃないと計算できない)
符号が負ならオブジェクトがひっくり返ったことを表し(リフレクション行列を含む)0の場合は投影行列を含んでいることを示す
3Dにおける行列式の値は基底ベクトルを三辺とした平行六面体の体積と等しくなるらしい
使うかボケって感じ


~逆行列の短縮~
直行行列の転置行列(行と列を入れ替えるやつ)は逆行列となる
Mт = M-1
よって計算を短縮できるのだが 直行行列かどうか調べるには逆行列を求めるのと同じくらいのコストがかかる
要するに事前に直行と分かっていない時は上記の特性を使うべきではない
直行ベクトルの定義は自身と自身の転置行列との積が恒等行列(Matrix.Identity)であることだが
MMт = I
わかりにくいので突き詰めると
基底ベクトルが全部「単位ベクトル」であり「すべて直行」していること
である



~おまけ~
浮動少数の罠
行列クリープが累積して直行ベクトルが微妙に崩れることがある
この崩れを再構築するアルゴリズムとしてグラム・シュミットの直行化法というものがある
やり方は数学書かWEBで!

4x4Matrix。4次元?!
3次元まではXYZで想像がつく
3Dプログラムも4次元目を利用することになったのだが4つ目は「時間」などではない
3x3行列では平行移動ができないためにXYZにWを追加して仮想的な平面との関係を築いてつじつまを合わせる
3次元でも可能だった「せん断行列」を応用して「平行移動」を可能にしてやったわけだ




3Dゲーム製作って今更だけど結構数学の知識いるみたい・・・(涙)
ねよっと。
スポンサーサイト

自作インポータの完成

アニメーションのインポータが完成した。
思ったより時間がかかって苦労した。

やられたのは「座標系の違い」である。憎い。憎いぜこのやろう。

苦労の原因は、何を隠そう座標系のことなんて微塵も考えてなかったことに起因する。
読み込んで動かしてみても常にグニャグニャとした得体の知れない生物が画面に映るのだ。

はっと我に返って思い返してみる

DirectX→左手系
Cinema4D→左手系
XNA→右手系


こ、こ、これじゃーん(涙)

分かったのはいいけど手直しも大変だった。

Quaternion.CreateFromRotationMatrixを使って行列をクォータニオンと移動Vectorに分解して扱っていた。
これは「ひけにXNA」様のサイトに載っていた方法なのだけれども、スケール情報があるとこの方法が使えないのである
直行系変換なら大丈夫だと思っていたのだけれど剛体系の変換でないといけないようだ。
Z軸方向を反転させるためにリフレクション行列を使っていたのでクォータニオンの位置が任意のもではなくなっていた。

結局Cinema4Dのエクスポータの方で右手用のデータを作成して吐き出すことにして解決。

左手系と右手系で困った人がこの記事を読んでいるとしたら以下に気をつけてくだされ
・ソフトの扱っている行列が列オーダーなのか行オーダーなのか?
・行列の基底ベクトルのZ軸要素(3行目)と平行移動のZ要素matrix.M43を反転させなければならない
・ポリゴンなどの情報に↑の行列を適用するとなるとポリゴンが反転する
・反転問題にはGraphicsDevice.RenderState.CullModeあたりでカリング順を弄るか頂点順番を123から132にかえる


アニメーションや数学のことも結構調べたので近いうちに記事にしたいと思う。

ねよっと。

Cinema4Dでエクスポータを作成してみた

XNAでゲームを作成していて、モーションデータはFBXで扱っていたのだが、FBXのバージョンの違いや、SDKのバグの噂を聞いたりと精神衛生上好ましくなかった。

そこでC++の復習も兼ねてついに自作の拡張子のエクスポータを書いてみた。
ドキュメントが少ないのが難点だけど慣れると超強力な味方になってくれそうだ。

とりあえず、VC++Express(無料のやつ)の使い勝手は悪すぎる。
別の環境で作成したいのにもともとのsdkサンプルと雛形がVCで組み込んであるため仕方なしに使っている。

拡張子を書き出すのに苦労したのは・・・
とにかくどこに情報がうまっているのか?を見つけるのが大変だった。
Coffeeの情報は結構あるのでそっちでクラスの検討をつけてからドキュメントを漁るのがいいと思う。

んでんで
情報が出てこなそうなのが以下。

//フレームを進める
BaseTime bt = BaseTime(i,doc->GetFps());
doc->AnimateDocumentExEx(NULL,TRUE,TRUE);
doc->SetTime(bt);


1フレームづず情報を書き出したい時にAnimateDocumentExExをしてやらないとフレーム移動を内部で実行してくれないため、常に同じフレームを書き出して最後に指定したフレームに移動して動作終了、なんてことになります。

引数は1番目は恐らくスレッド関係だけど良く分からないのでNULLにして逃げた
2番目=内部フレーム移動時にエクスプレッションも適用させるかどうかのフラグ
3番目=内部フレーム移動時にアニメーションを適用させるかどうかのフラグ

拡張子の細かい仕様が気になる方は私も散々お世話になったすばらしいサイトに大変詳しく書いてございます。
サイトの主様は 1:多数 の質問回答形式のBBSを設立されており感服します。

サイト自体がC++がメインなので一度も書き込んだことが無いのですが、もしC#だったら毎日書き込んでいたことでしょう。危うかったな!


エクスポータはできたんだけど・・




インポータをまだ作ってない。
ねよっと。

Cinema4Dで書き出したFBXをXNAに持っていく

C4DでFBXを書き出すときにBindPose(初期姿勢)はどのように扱っているのか調べてみた。

結論から言うと書き出す時に表示しているフレームの姿勢がBindPoseになるようだ。

よって書き出し時にポーズリセットを押してその姿勢のまま書き出せばよいと思ったのだが、これではリグにXpressoを含めている場合OFFにしなければならない。
モーションはジョイントにベイクしなくてもFBXにそのまま書き出せるのでXpressoやCoffeeを切り替えるのは面倒。

よってXNAの方の仕様を変えることにした。
具体的には0フレーム目をBinePoseとして扱うことにした。

リグのコントローラにBindPoseを取らせたものをモーションクリップに書き換えてモーションソースを1フレーム目においておけば、モーション作成時も邪魔にならないで済む。


FBX拡張子に左右されるのは面倒になってきたので自前で拡張子を書き出すエクスポータを作成しようとしたのだが、サポートにC++PLUGINの質問をしたら

プラグインの質問はこちらでお願いします>英語のコミュニティらしきURL

といったような返信が来た。
以前から数回カスタマーサポートにはお世話になっている。
対応も早かったし私の中ではAppleの次点といっていいほどサポートがよかっただけに残念だ。
プラグインが活性化すればユーザー目線のカスタマイズが進み差別化の一旦と成りえるだろうに・・・

やろうとしたのは 自分しか使わない拡張子の作成 なので程遠いが、つっこまないっと!

もう少ししたら仮想空間を飛びまわれそうだ。
楽しみで製作意欲も復活気味。

ねよっと。

Dictionaryをforeachで回したい時

なにかと便利なDictionary。
でもコレクションの中ではforやforeachと相性が悪い部類だと思う。

foreachでまわす例
Dictionary<int,int> test
foreach (KeyValuePair<int,int> node in test)
{
node.Key
node.Value
}

var使ってもいいけどC#って感じがしないのでこっちを使ってる。
ねよっと。
プロフィール

あしゅ

Author:あしゅ
ぷぃぷぃ日常。
いつのまにか雑記ブログに。

カテゴリ
最新記事
検索フォーム
最新コメント
リンク
このブログをリンクに追加する
ブロとも申請フォーム

この人とブロともになる

カウンター
上記広告は1ヶ月以上更新のないブログに表示されています。新しい記事を書くことで広告を消せます。