前回の内容を 100% 理解していれば、あとは手を動かすだけです。
そしていきなり躓きます。どうも参照に System.Drawing を追加しないと
上記のコードは通らないらしい。
気を取り直して…と思ったら、また勘違いしていたところを発見。
以前コードからイメージキャンバスを作成して、XAML に配置するとき dpf という不可思議な名前のものがあったけど
あれは WPFHost 名前空間の略だったのだ… WPF を略して dpf そこ wpf じゃダメだったんかい!
ということで、自分はもう少しわかりやすく sandbox を使ってみた。
さて、WPF のサンプルを例に IScene, ISceneHost(IScreen) を継承してそれぞれ、シーンとキャンバスを作成し
MainWindow をコントローラに見立てて、ColladaViewer なるものを作ってみようと思います。
8/5
ひと通りビューア機能を揃えて描画してみました。結果を次に示します。
アレ…何だこりゃ。
調査の結果、2箇所ミスしていました。
・頂点バッファの重複点再利用の圧縮処理が正しくなかった。(←最大の原因)
・エフェクトファイルの内容も一行余分に行列計算していた。(アスペクト比がおかしかった)
これらを修正して、もう一度描画した結果を次に示します。
よしよし、まずこれができないとね。
では機能を追加して行きましょう。
<途中経過>
エフェクト変数の実体はプリミティブ単位で作成して、保持するようにしてみました。
待て、それだとやはりメモリに無駄が多いし、更新処理にて変数を総ナメしないと
いけないことになるはず → やめる。(今は気にならないけど、今後ぜったいネックになるよね。)
シーンの外から変数の位置(データ、プリミティブ、変数の種類)を指定して変数の設定を行うようにしました。
これでシステム側から変数の更新をかけない限り、デバイスへは何の干渉もせずに描画することになります。
特に何もしなければ最大のパフォーマンスが出る仕組みです。
では、現在の状態を次に示します。
見て分かる通り、マテリアルカラーを適当に割り当てています。
まぁシステム側のコードを弄っただけなので見た目は何も変わりません。
ここで、ちょっと悩む所があります。
エフェクト変数の何を更新すれば目的を達成するのか実行コードからわからないということです。
例えば world, worldInverseTranspose, view, projection, viewProjection, worldViewProjection を
全部設定してあげないと、正しい姿勢にならないのではないか、ということ。
解決策を考えると、やはり現在描画しているプリミティブごとの姿勢行列やフレーム行列リスト
ビュー行列やプロジェクション行列がわかるようにしなければならないはず。
ここからはアプリケーション依存なので、別プロジェクトとして切り離して管理するようにしてみようと
思いました。
8/11
プロジェクト名は、まぁ適当で…
結局、事前に調べずにシステム側からすべての予約変数を更新するように修正しました。
ほか、カメラ管理モジュールを作成してビュー、プロジェクション行列の更新を管理するようにし
様々な角度から見ることができるように修正しました。また、ノードの姿勢行列が反映されるようになりました。
余談です、エフェクトを複数のノードで使いまわす場合は、どうしてもノードごとに変数の再設定が必要になります。
修正した Viewer の結果を次に示します。
座標変換をしていないので Blender の Z-up のままになっています。
つまり -Z の位置から DirectX で描画すると Blender の床から見上げた形になるのです。
よく分かるように、テストデータを変更します。
Blender の軸方向を表すボックスx27個のシーンデータを用意しました。
これを Viewer の初期位置から見ると次の通りです。
裏が取れましたね、Blender の床側から見上げているのがわかりますでしょうか。
軸方向は問題ない様子ですね。
さて、座標系を DirectX に変更して出力するよう、今度はコンバータの方に手を加えてみます。
修正した結果を次に示します。
よーし、正しく座標変換できているようですね。
では、姿勢行列についても正しく変換できているか調べてみましょう。
ということで次のテストデータを用意しました。
中央以外のキューブにそれぞれの変換をかけて、配置しています。
この通りに描画されれば、合格としたいと思います。
結果は次の通りです。
ありゃりゃ〜、大失敗です。
見た感じ回転がおかしいです。
Blender での X 軸の回転が逆向き、Z軸の回転は反映されない。
Y軸での回転がよくわからない任意軸回転…という結果になっているようです。
<調査、修正>
原因は…YZ軸の回転角度を交換する際に上書きしてしまっていたためでした。
また、回転角方向がすべて逆向きで指定していたためでした。
角度に-1を掛けて対応し、上書きのところは正しく分岐するよう修正しました。
修正結果を次に示します。
一見して正しい…のですが、複合軸回転の結果が若干異なる気がします。
もう少しわかりやすいモデルを用意してみよう。
回転の詳細がわかるよう、プレートを置いてみました。
<調査>
やはり間違っていました。Blender の時のように X→Y→Z とオイラー角をかけていましたが
DirectX では X→Z→Y の順にかける必要があるようです。(何回かこんなコトしていますが毎回忘れる)
修正した結果を次に示します。
これで姿勢行列が正しく再現できることを確認しました。
続いて、マテリアルカラーを反映させてみましょう。
次のテスト用のデータを用意します。
<コードを修正>
プリミティブごとの描画タイミングでマテリアルからディフューズ色を取り出し
予約エフェクト変数へ転送します。
問題ないようですね。
次はテクスチャマッピングです。
次のようなジオメトリノードを用意します。
<コードを修正>
プリミティブごとの描画タイミングでマテリアルからディフューズテクスチャを取り出し
エフェクト変数へ転送します。(セマンティクスアクセスなので処理は低速、しかし自由度は高い)
げげ!テクスチャ座標が反転している…これはまずいですね。
<コンバータを修正>
Blender → DirectX なので UV 座標は Y = 1 - Y にします。
修正完了!
少し、色々な角度から観測できるように調整します。
次の骸骨さんを描画してみますか
読み込んだ結果を次に示します。
任意の方向から並行光源のライトを照らせるようにし、また
ターゲットを現在のカメラの上下左右にスライドできる機能を追加しました。
問題なく動作しているようです。
描画テストはこんなところでしょうか?
次回はノードツリーの表示をやる予定です。
お楽しみに!
<オマケ>
コンバータとビューアのテストがてら色々表示してテストしてみました。
変換に失敗するファイルや、表示自体が行われないものもありましたが…
必要に応じて対応することにします。
2012/07/29 初記。
2012/08/18 更新。