「 2008年02月 」一覧

XSI ModToolからスキニングメッシュ出力


スキニングメッシュとして、円柱にボーンを仕込んだものを作ってみました。

適当に曲げてみて、それを独自形式変換して表示できるかやってみたのですが、失敗してしまい、 tiny.xからの作った場合には正常に表示できているのですが。

うまく出す方法判明

いくつか試してようやく解法がわかりました。
DirectXのエクスポーターの設定で CompressMeshにチェックが入っているとダメのようです。

また、Trianglateにチェックを入れても豪快に崩れました。
このことから、素直に .xを作り、やるならその後最適化をするという流れをとった方が良さそうです。

 


スキニングメッシュ


ようやくtiny.xを自前フォーマットに変換して描画まで確認。
苦労したけど、サンプルのSkinnedMeshのデータと比較できたのでまだ楽だった。

スキニングの一番の問題点は、行列のデータを見ても全く正しいことがわからないこと。オフセット行列も正しいか謎だし。簡単なサンプル作るにしても、スキニングメッシュを作るには、一般的にはモデラーが必要になるし。

今回の一番のポイントは、DrawSubsetらから抜け出せたこと。

drawSubsetの中身は結局は描画バッチを実行しているだけに過ぎない。
内部では、DrawPrimitive呼び出しを実行しているだけだろうし、その部分を自分で何とかやろうとしてみた。

ConvertToIndexedBlendedMesh を実行すると、属性グループ、ボーンコンビネーションバッファが取得できるのでこれから何とでもなる。

pBoneComb[ AttibId ]で、1回のDrawPrimitive呼び出しに必要な頂点数、インデックスなどは入っているし、

必要とするボーン(フレーム)へのIDも取得できる

pBoneComb[ AttribId ].BoneId[ n ]

ここで、必要とするボーン数はパレットの数としてメッシュコンテナが取得しているので、そのループで回せば必要とするボーンIdが取れる。

このボーンIdから、さらにGetBoneName( BoneId )すれば対象とするフレームの名前が取れる。

注意点としては、パレット数(nNumPaletteEntries)はシェーダーのマトリックスパレット数で制限される。で、複数回に分けられた後、最後の描画グループでは、パレットが全て埋まるわけではない。

tinyでやったところ、13という中途半端なものになった。
このとき、BoneIdが UINT_MAXになるのでその場合は取得しないなどの条件が必要となる。

この辺はSkinnedMeshのサンプルで実装されていて、あぁ、なるほどと思ったポイント。


(no title)


_ ! [プログラミング] リフレクションlib

どうやらさらにバグがある模様。ツリー構造のモデルでたまにデシリアライズに失敗…

_ ! [プログラミング] 描画

ツリーの問題が解決しないけど、単に表示部分をテストしてみた。

_ 色々と苦労したけど、ワイヤー上でVB/IBの状態確認…


スキンメッシュ行列


リフレクションlibにバグが潜んでいた

抽象クラスはNG. templateのインスタンス化後、メンバ取得のために抽象クラスのインスタンス作ろうとするのでNG
ユーザーのオブジェクト型をさらに派生したクラスでのエラー

どうやら、class Aを継承したclass B, class Cが居て、それぞれの初期化と、A自身の初期化で、おかしな状況になっていた。こちらは修正済み。

しかし、最初の項目はシステム上どうしても無理だ…。
抽象クラスのメンバのシリアライズは派生先で再定義してもらうしかないのか…。システム的に破綻っぽい orz

スキンメッシュ

とある場所で、ボーンの部分で、ローカルのワールドの逆行列という記述をみた。
さっぱりなので、色々と調べてみた結果このような表記はXSIの部分で使われているようだ。この行列Inverted_matBasePoseとかOffset行列とかいろいろな呼び方をされている模様。

モデルが初期ポーズをとっている状態でボーン空間をきちんと合わせるのに必要な行列ということらしい。

各ノードのワールドマトリックスを作るには、


ここで逆変換を作用させて、ボーンのローカル空間へ. 骨のポーズ状態が原点としているらしい…

“日々精進時々堕落”というWebが参考になりました。
各状態が算出された後の実装方法は、DirectXのSkinnedMeshサンプルで何とかなるんですが、それに必要なデータの情報ってなかなかないですよね。

 


(no title)


[プログラミング] スキンメッシュ注意点

スキニングメッシュを読み込むときには、

  • D3DXMESHCONTAINER
  • D3DXFRAME
  • ID3DXAllocateHierarchy

らを派生し、ロード&生成コードを自前でかかなくてはいけない。

ここで、派生の決まり事である、デストラクタはvirtualを付けよ。
という点を無意識のうちに書いていて、ミスを犯した。

ルートとなるD3DXLoadMeshHierarchyFromXでの結果格納のpFrameで、
ウォッチで値を見てみると数バイトずれて結果が表示されていた。
そこで疑いを持った。

  • 呼び出し規約でも間違えた?
  • virtualが悪い?

のどちらかがまず怪しい感じがしたので見てみた結果比較的短時間でわかった。

あと気になったのは、ボーンのオフセット行列。
メッシュコンテナに入っていて描画時はそこまで違和感を感じないのだが、
なぜボーン(Frame)の個々の要素として持たないんだろうと。

モデラーから出力されたデータを想定すると、各ボーン毎にオフセット行列があっても良い気がする。


スレッドプログラミング


Java互換スレッド操作ができるライブラリ作成中。

あちらこちらでバグにはまり、時間だけ浪費している感じですがようやく動くようになってきました。

待ち行列とsynchronizedクラスのペアで操作
この部分で、1日ほぼ費やしました。

[code lang=”cpp”]synchronized lock( waitingQueue->getCriticalSection() );
{ // データがないので待つ
waitingQueue->wait();
}[/code]

という操作している部分で、2重ロックしていたという…。

結論、待ち行列管理する部分でのwait時にはロック保持しないことに。

そして、動作チェックということで、マルチスレッドのデザインパターンサンプルを作成してみたり。


リモートデバッグ


DirectXのプログラムを作っているわけですが、開発機が既にVistaのため、デバイスロストを発生させることが出来ないので、WindowsXPのマシンを用意してリモートデバッグを試みてみたのですが、なにやらうまくいかず…。実行体を全く同じパスにおいて実行してみるも、拒否されたとか言われてしまう。

WinXP SP2での変更のため、MSDNヘルプの通りにやっても動かないという話もあるし。

とりあえず試したのは、

ファイアウォールの無効化D
COMのリモートによる起動を許可

あと、XPHOMEではローカルセキュリティポリシーが存在しないため、そもそもリモートデバッグのクライアントを入れることが不可能ぽいです

 

DirectX環境依存

SetRenderStateのカリング指定で、無効な値を入れてしまったときの挙動が環境によって異なっていた。GeForce系は無事に動いていたので発見が遅れました。

ちゃんと設定しないとねーということで。

他にも、デバイスロスト時のリソース復帰について環境依存が。
D3DPOOL_MANAGEDであってもテクスチャが正常に復帰されないバグに見舞われました。

環境は 945GMのチップセット統合。他には915GMでも起こると推測されます。

結局のところ、Managedは当てには出来ないのかもということになり、自前でリストアコードを書いた方がきっと無難だろうなと思います。