プロフィール

Na-7

Author:Na-7
SE(システムエンジニア)として約15年間システム系ソフト会社を勤めあげ、2008年3月退社。現在、ゲーム制作会社設立を目指して活動中。


アクセスカウンター


最新記事


最新コメント


最新トラックバック


月別アーカイブ


カテゴリ


DATE: CATEGORY:スポンサー広告
上記の広告は1ヶ月以上更新のないブログに表示されています。
新しい記事を書く事で広告が消せます。
| BLOG TOP |
DATE: CATEGORY:Softimage Mod Tool
伊籍
伊籍
元劉表配下の文官。劉表死後、劉備に仕えた。内政や外交に手腕を発揮し、諸葛亮らと共に蜀の法律を制定した。
演義では、劉備の馬が的盧であると教えたり、蔡瑁の劉備暗殺計画を伝えたりした。



◎ACLはインスタンシング対応?

前回のTEAさんからの回答コメントに、content.load遅延バージョン(ここでは以後ReadAsset方式と呼びます)のプログラムを添付しました。これは2回目以降もモデルの新しいコピーを行うもので、content.loadの読み込みは遅くなります。

しかし描画部分のプログラムは一切変更していないので、描画速度は元のバージョンと同じはずです。ところが、実際に試してみると差が出ました。

ACL:ReadAsset方式
10体 60fps
50体 10fps
100体 2fps

ACL:非ReadAsset方式
10体 60fps
50体 15fps
100体 6fps

モデルデータをコピーしたReadAsset方式が遅いということは、「ACLは同一モデル複数表示を想定し、インスタンシング技術(マテリアルバッチなど)を内部実装している可能性がある。(HPの推測より)」の可能性が高まったのではないでしょうか?



◎インポータの変更

ランタイムライブラリに性能差があるかどうかを簡単に確認する方法は無いでしょうか?…そうだ!インポータとライブラリの組み合わせを変えてみるのはどうでしょう?

槍兵モデル(.xsi)
コンテントインポータ:Crosswalk Importer
コンテントプロセッサ:Model-Animation Library

と設定してビルドすると…ビルドエラーになりました。

Building content threw NullReferenceException: オブジェクト参照がオブジェクト インスタンスに設定されていません。

(ちなみに、プロセッサにModel-XNA Frameworkを設定すると、ビルドは通りました。当然動きませんがw)
念のため、.xsiファイルを槍兵モデルからロボットモデルに変えてみましたが、現象は変わりませんでした。
こりゃダメだなぁ…。


仕方がないので、逆の組み合わせを試してみました。

槍兵モデル(.x)
コンテントインポータ:X File - XNA Framework
コンテントプロセッサ:Crosswalk Model Processor

と設定してビルドすると…ビルドは通りました。

インポータの変更

えーと、足の部分が拡大されているようですね。シェーダーが変わってしまったので、ワールド座標を変更してもサイズが変わりません。

頑張れば正常に表示できるかもしれませんが、どうせ頑張るなら.FBX渡しを模索しましょう。



◎FBX渡しに再チャレンジ

まずロボットモデルをFBX書き出し機能で出力します。オプション設定はとりあえず以下のようにしました。

FBX出力オプション設定

すると、こんな警告画面が出ました。

FBX出力時の警告とエラー

テクスチャのUVマッピングとかで警告が出たようですが、ログファイルが指定の位置に存在しません。
警告内容は以前試した時よりマシになりましたが、ログファイルが存在しないのは相変わらず謎です(笑)

これをXNAに追加し、

コンテントインポータ:Autodesk FBX - XNA Framework
コンテントプロセッサ:Model-Animation Library

と設定してビルドすると…ビルドは通りました。
(ちなみに、インポータにCrosswalk Importerを指定するとビルドエラーになります)

以前はビルドエラーになりましたが、今回はサンプルモデルを使用したお陰で、ここまでは順調…と思いきや、Content.Loadでエラーになりました。

An unexpected error has occurred.

直訳すると「予期しないエラーが発生しました。」とのことですが、こちらのItoさんの回答を見ると、ドライバ側が正しくエラーハンドリングできなかった場合に発生するとのこと。
こちらにも別の事例がありましたが、要するにハードの問題である可能性が高いようです。

心当たりありすぎ(ー_ー;



◎ハードエラー回避テク

ふとコンテントプロセッサ(Model - Animation Library)のプロパティを展開すると、「Resize Textures to Power of Two」などがありました。ひょっとして、これをTrueにすればいちいちテクスチャ解像度を修正しなくても良いのでは?

実際に試したら、

Invalid texture. Face 0 is sized 512x499, but textures using DXT compressed formats must be multiples of four.

Device does not support multi-level texture width and height values that are not powers of 2.

上記の2つのエラーは、Resize Textures to Power of TwoをTrueにすると回避できました。これまでテクスチャ解像度をいちいちペイントツールで修正してましたよ(T_T)

ちなみに、このプロパティはXNA標準のモデルプロセッサやテクスチャプロセッサにも装備されています。



◎サブPCに開発環境構築

本題のFBX渡しに戻ります。
予期しないエラーは不可解で、アテもなく適当にいじってどうにかなるとは思えません。

いい加減新しいPC買おうか悩みましたが、結局サブPC(GeForceFX5200)にXNA開発環境を構築することにしました。
サブPCは実行環境テスト用にしておきたかったのですが、仕方無いですね。

USBメモリによるデータ渡しには限界を感じたので、ネットワークHDDを購入しました。メルコ製ですが、付属ソフトによる自動セッティングが簡単で感心しました。一般向けってお手軽だなぁw


「SoftimageはXNA3.1で動かない」との書き込みをちらっと見かけたことがあるので、XNA3.0を導入したかったのですが、今は英語版しか無かったので、結局XNA3.1日本語版を導入しました。

数時間かけて環境構築し、プログラムを実行すると…メインPCと同じエラーが出ました。ガーン!!

安物の旧式とはいえメーカー製のグラボなんだから、せめてエラーメッセージぐらい返してくれ~!(泣)



◎キャプテンモデルのFBX渡し

ロボットモデルが「予期しないエラー」で行き詰ってしまったので、今度はキャプテンモデルで試してみました。するとコントローラ設定行で

指定されたキーはディレクトリ内に存在しませんでした。

とエラーになりました。アクション名が見付からないと言われたわけですが、アクション名を「bind_pose」や「walk」にしても同じエラーが出ます。

FBXファイルを検索すると、上記アクション名は存在せず、

Pose: "Pose::BIND_POSES", "BindPose" {

こんな記述があったので「BIND_POSES」や「BindPose」を指定してみましたが同じエラーが出ます。FBX出力時にアクションが格納されていないような気がするなぁ…



◎Softimageのサンプルプロジェクト発見!

ネットを探っていたら、こちらの記事を見付けました。

「4. XNA Game Studio での単純なモデルの表示」ではFBX渡しを実装していますが、非アニメーションモデルなのであまり参考にならなさそうです。

しかし「7. ゲームの作成」では、アニメーションモデルを.xsiで渡しており、複数表示の参考になりそうです。

しばらく英語ビデオを見ていましたが、時間が長いし肝心な所がわかりにくいので、プログラムをダウンロードすることにしました。

236MB!デカいな~



◎次回予告

というわけで、サンプルプロジェクトの解析を始めた所ですが…自作コードに問題があったんじゃないかな~?(汗)

解析結果は次回報告しま~す!

スポンサーサイト

テーマ : ゲーム製作 関連 - ジャンル : ゲーム

| BLOG TOP |
DATE: CATEGORY:Softimage Mod Tool
韓当
韓当
呉将。孫堅旗本四天王の一人。孫子三代に渡って仕え、数多の合戦に参加した。長寿を得て晩年まで戦場で活躍し、数々の武功を挙げた。



◎Softimageのサンプルコード

Softimage付属ランタイムの個別制御サンプルコードをHPに追加しました。

余分なコード(思考錯誤中のコードとか)を整理すると、ここまでシンプルになるんですね…頭の中が整理できたのは良いのですが、20行足らずのコードを導き出すのにかかった時間を思うと、ちょっとショックです(笑)



◎ACLの個別制御

Softimage付属ランタイムの個別制御が出来るようになったので、ACLでも同じ手法で個別制御出来るか適用テストを行います。

まず、ACLでモデルを複数登録し、モデルアニメータとアニメーションコントローラを複製して…

ACLの個別制御.JPG

ハテ?!
まだ何も工夫してないのに、個別制御できてますね?
ということは、ACLで個別制御できないと思っていたのは、私の勘違いってことですか?…ガーン!!

当時はまだC言語始めたばかりだったので、複製した時のコントローラ設定とか間違えたかもしれません。Listどころかインスタンスの概念すら把握しきれてなかったし(汗)

というわけで、ACLでは個別制御の問題は発生しませんでした。ACLでもModelクラスのインスタンスは複製されていないはずですが、アニメーションに必要な情報は、モデルアニメータとアニメーションコントローラに全て納まっているのでしょう。どうもお騒がせしました_O_


ACLの参考用に、今回のプログラムをHPに追加しておきました。Update()とDraw()にコードが無いアニメプログラムって、ちょっと珍しいかも?w



◎性能比較テスト

というわけで、ようやく念願のライブラリ性能比較テストを実施しました。

XNAのアニメーションライブラリを比較検証する

HPを見て頂ければわかると思いますが、XSIXNARuntimeとACLのパフォーマンス測定結果は、3倍の差がありました。

まさかここまで差が出るとは思いませんでしたね~!
プロジェクトファイルをUPしておきましたので、興味がある方はご自分の環境で試してみてください。


パフォーマンスに差が出た原因については、HPの「◎測定結果の考察」に記述しました。

項目だけ転記すると

A:モデルの違いによるもの
B:プログラムの違いによるもの
C:ライブラリの違いによるもの

という推測です。現時点ではBに関する検証アイデアが無いのですが、ACに関しては今後検証作業を進めて遅延原因を追及するつもりです。



◎対策の検討

今までのやり方で続行すると、ACLより3倍遅いゲームになってしまうことが判明しました(笑)
さすがにこれはマズいので、対策を考えます。

一番手っ取り早い対策は「昔のやり方(メタセコイア+RokDeBone2+ACL)に戻す」ですが、そうすると3DCG担当者が見付からない問題に戻るので、これは極力避けます。

次に考えられるのは「Softimageをやめて別のソフト(Mayaなど)に乗り換える」ですが、まだロクに使いこなせていないツールを見限るのは、ちょっと早い気がします。一応、XNA公式認定ツールですし。…疑問は多々ありますがw


というわけで、まだしばらくSoftimageとXNAの連携に拘るつもりですが、今後の対策は2つ考えられます。

1つは「現在の手順の見直し」、もう1つは「XNA公式連携手順以外の手法の模索(例:FBX渡しなど)」です。前者は、遅延原因がABだった場合に有効であり、後者は、遅延原因がCだった場合に有効です。

今後しばらくは「検証作業を進めて遅延原因を追及しつつ、2つの対策を並行的に進めていく」つもりです。



◎次回予告

性能比較テストは前々からやりたいと思っていましたが、この差は驚きですね~。「今のやり方を改める必要がある」と認知できたことは大きいと思います。

まずは検証作業の一環として、他のモデルによるパフォーマンス測定を試みます。FBX渡しについても本格的にチャレンジしていきたいですね。

テーマ : ゲーム製作 関連 - ジャンル : ゲーム

| BLOG TOP |
DATE: CATEGORY:Softimage Mod Tool
孫皎
孫皎
呉将。孫権の従弟。若くして曹操の濡須侵攻を防ぎ止め、精鋭と讃えられた。荊州の戦いでは呂蒙に従い参戦し、関羽討伐に貢献したが、直後に病死した。



◎不完全な個別制御

ボーントランスフォームを退避復元する手法により、メモリを浪費しなくてもモデルの個別制御が可能となりましたが、この手法では「増やせば増やすほどアニメーションが速くなる」という問題が再発しました。(現象についてはコチラ

最初は速度だけの問題と認識していたので、PlayBackの引数か、XSIAnimationContentクラスのDurationやCurrentTimeあたりを何とかすれば良いのだろうと考えていました。

しかしいろいろ試していたら、同一モーションのタイミングは必ず同期し、タイミングをずらせないことに気付きました。

不完全な個別制御

つまり、この方式による個別制御は不完全だったのです。
トホホ…。



◎CurrentTimeの退避復元

モーションが同期するということは、モーション関連データのどれかが共通的に参照されている、ということです。

Update()内のModels[*].Animations[Models[*].AnimationIndex].CurrentTimeなんかが怪しいと思って値を確認すると、インスタンス毎に異なる値が格納されてました。

これは問題無さそうなので別のことを調べたりしましたが、なかなか手掛かりが掴めません。振り出しに戻ってもう一度考え直すと、やっぱりCurrentTimeが怪しい気がします。

デバッグコードを確認すると、ループ中に値を出力してました。つまり、異なる値が格納されていたわけではなくて、異なるタイミングの値を出力していたわけです(ー_ー;

その後、CurrentTimeは同じ値であることが確認できたので、これを退避復元するようにしたら、「増やせば増やすほどアニメーションが速くなる」という現象は解消しました。

しかしアニメーションは相変わらず同期します。う~ん、Durationは固定値のはずだけど、他にもまだ何かあるのかなぁ?ブツブツ…。



◎CurrentTimeの初期化

しばらく試していると、ある条件を満たす場合、個別のタイミングで動くことが判明しました。

・最初から表示する6体の腕振り&スクワットモーションは必ず同期する(CurrentTimeのUpdate処理開始タイミングが一緒のため)

・最初から表示する6体の回転モーションは、個別に動くこともある(謎)

・途中から追加する4体は、全てのモーションが個別に動く(CurrentTimeのUpdate処理開始タイミングがバラバラのため)

いずれにしても、個別に動くケースがあるということは、(CurrentTimeを退避復元した段階で)個別制御が出来ている、と言えそうです。

試しに、キーを押すとCurrentTimeを初期化するように改修しました。



最初から表示したモデル6体のモーションは同期します。モデル4体追加後、個別操作により最初のモデル6体をバラバラに動かし、最後(1分15秒)に同期させています。

ちゃんと個別制御できてますよ~!w



◎HPとサンプルプロジェクトについて

Softimage付属ランタイムの使用に関するノウハウをHPにまとめました。

Softimage付属ランタイムをXNAに組み込みスキンアニメする

できればサンプルプロジェクトも作成&掲載したかったのですが、コンテンツのファイルサイズが1MBを超えると巡回削除対象となってしまうので、対策を検討中です。



◎次回予告

今回はちゃんと個別制御できました!
トランスフォームもタイミングも自由自在です!w

HPでのノウハウのまとめも完了したので、今後はサンプルプロジェクトを作成し、ACLへの適用テストと性能比較テストを行う予定です。

テーマ : ゲーム製作 関連 - ジャンル : ゲーム

| BLOG TOP |
DATE: CATEGORY:Softimage Mod Tool
蒋欽
蒋欽
呉将。演義では周泰と共に湖賊の頭目として登場し、孫策帰順後は江東各地を転戦し戦功を重ねた。荊州の戦いでは水軍を率いたが、関羽討伐後の帰還途上で病死した。公の推挙に私怨を交えぬ実直な性格で、人々から称賛された。



◎前回のまとめ

ACLやSoftimage付属ライブラリを使用してスキンアニメを実装すると、同一モデルのインスタンスを複数作成した場合、個別に制御できないという問題があります。

原因は、同一モデルを複数回読み込む場合、モデルインスタンスが複製されないからです(詳細は前々回参照)。

そこで、前回はLoadメソッドをオーバーライドすることによりモデルインスタンスを複製し、個別制御を実現しました。但しこの手法はメモリを無駄に消費するという欠点があり、インスタンスを大量に作成する場合は不向きです。



◎その後の経緯

メモリ消費を抑えるには、モデルインスタンスの複製は行わず、必要な情報だけ複製する必要があります。必要な情報とはボーントランスフォームを指しますが、ボーントランスフォームがModelBoneクラスのメンバーである以上、ModelBoneクラスを複製する必要があると考えていました。

また、私はまだUpdate()の中身を把握しきれておらず、特にXSIAnimationChannelクラスのPlayBackが何をしているのか未だによくわかりません。ボーンだけコピーする手法を実装するには、まずこれを理解する必要があると思っていたのですが、Update()の解析には時間がかかりそうだったので、先に別のことをやるつもりでした。

しかし、yohさんやHOSSIEさんからコメントを頂いて、ボーンだけコピーする手法を手早く実装することができました。
yohさん、HOSSIEさん、どうもありがとうございました!



◎実装

私が今回実装した方法は、インスタンス毎にボーントランスフォームデータ退避領域を作成し、必要に応じて退避復元する、というものです。

1.ModelAssetに、ボーントランスフォーム退避領域を設ける
public Matrix[] BoneTransforms;

2.ModelAssetのLoadContent()の最後の方で、退避領域を初期化する
BoneTransforms = new Matrix[CrosswalkModel.Bones.Count];
CrosswalkModel.CopyBoneTransformsTo(BoneTransforms);


3.Update()の最初の方で、退避領域からデータを復元する
Models[i].CrosswalkModel.CopyBoneTransformsFrom(Models[i].BoneTransforms);

4.Update()の最後の方で、退避領域にデータを退避する
Models[i].CrosswalkModel.CopyBoneTransformsTo(Models[i].BoneTransforms);

5.DrawModel()の最初の方で、退避領域からデータを復元する
m.CopyBoneTransformsFrom(BoneTransforms);

細かいことを言うと、DrawModel()の引数を追加して、5の引数BoneTransformsを参照可能としましたが…まぁその辺はどうでもいいですね。



◎比較

前回のオーバーライド手法と比較すると、

・メモリは浪費しない

・描画速度は落ちる
 (3~5でコピーを3回実施しているため)

と言えそうです。

描画速度が気になるので、今後性能比較テストを実施し、無視できないレベルであれば、コピー回数の低減を図ります。



◎次回予告

実は、今回の手法だと「増やせば増やすほどアニメーションが速くなる」という問題が再発しました(汗)
(前回の手法では発生しません)

まずこの問題をクリアしてから、ライブラリ関連の記事をHPにまとめる予定です。できればサンプルプロジェクトも載せたいですね。

その後ACLへの適用テストと性能比較テストを行い、結果が悪ければ改善を図ります。

…やること沢山あるなぁw

テーマ : ゲーム製作 関連 - ジャンル : ゲーム

| BLOG TOP |
DATE: CATEGORY:Softimage Mod Tool
虞翻
虞翻
呉の文官。易学、儒学、医術に長けていた。荊州の戦いでは傅士仁に降伏勧告を行い説得に成功した。相手が誰であろうと構わず意見する剛直な性格。



◎問題点と対策方針

モデルインスタンスの中のボーンデータは、固定値ではなくモーション関連データでした。しかし同一モデルを複数回読み込む場合、モデルインスタンスは複製されず、参照値のみ返します。このままだと、同一モデルを複数表示することは可能ですが、ばらばらに動かすことはできません。

ここはやはりボーンデータを複製するのが理想的と思いますが、今の私のスキルレベルでは難しそうなので、まずはモデルインスタンスを丸ごと複製する方式を試みます。



◎Modelクラスのメソッド

まずModelクラスを確認すると、ボーン関連のコピーメソッドが3つありますが、CopyAbsoluteBoneTransformsTo()とCopyBoneTransformsTo()は今回の目的に合わなさそうです。

CopyBoneTransformsFromはトランスフォームのコピーに使えるかもしれませんが、トランスフォームの他にもボーンデータは存在するので、単独で使用しても目的は達成できないでしょう。

他にMemberwiseCloneという保護メソッドがあるのですが、「そもそも保護メソッドって何?」と思ってこちら(注:java)を参照すると…なんだ、protectedのことだったんですか(^^;

クラスから呼び出せないのに何でマニュアルに記載されているのか疑問だったのですが、オーバーライドやサブクラスなどのためだったんですね。

Modelクラスにコピーorクローン作成メソッドがあると楽だったのですが、そんな便利なものは無さそうです。



◎案1:Listのコピー

次に考えたのは、Listクラスのオブジェクトをコピーorクローン作成するという方法ですが…どうやるんでしょうか?(爆)

XNAではGCを問題視する記事をよく見かけたので、Listは敬遠してきました。お陰でいまだに使えません(^^;

これを機に勉強するのも良いかと思い、適当な記事を軽く流し読みしたのですが…今回はディープコピーに該当し、値か参照かを気にしつつ各要素を1つ1つコピーしなきゃいけないのかな?ConvertAllが使えるかもわからないし、先にテストプロジェクトを作っていろいろ試さないといけないなぁ…。

…そこまでやるぐらいなら、素直にボーンデータを複製した方が早そうです。他に良い方法は無いでしょうか?



◎案2:アセット名の一時的変更

同一モデルを複数回読み込む場合、モデルインスタンスが複製されないことが問題となっているわけですが、同一モデルか否かの判断基準は「アセット名が同一か否か?」だと思います。ということは、アセット名を変更すればこの問題を回避できるかもしれません。

1.Content.Loadでモデルデータを読み込む(初回読込)

2.メモリ内に作成されたインスタンスのアセット名を一時的に変更する

3.Content.Loadで同一のモデルデータを読み込む(2回目読込)

4.2.で変更したアセット名を元に戻す

これを実現すべく、アセット名の格納場所を調べていたら、ContentManagerにReadAsset保護メソッドがあることに気付きました。



◎案3:Loadメソッドのオーバーライド

ContentManagerのReadAssetは、Load メソッドをオーバーライドして使用することを想定した保護メソッドです。こちらにReadAssetのサンプルコードがありました。

ContentManagerの継承クラスを作成し、Load メソッドを書き変えることで、インスタンスが必ず複製されるようにします。新たに作成したContentManagerをModels.Addの引数に指定すると…



やりました!個別制御成功です!(^^)


この手法は

・手軽に実装できる
・コンテンツのデータ構造が変わっても影響を受けない
・モデルデータ以外のコンテンツデータにも適用可能
・ACLなど他のライブラリにも適用可能(たぶん)

などの長所があるので、場合によってはこれもアリでしょう。(HPにまとめておいた方がいいのかな?)

ただし、

・メッシュデータやエフェクトデータも複製されるため、メモリを無駄に消費する

という欠点があるので、インスタンスを大量に作成する場合は不向きです。



◎おまけ

私のC言語歴は15年間空白だったので、C#においても知らないことや曖昧なことが沢山あります。(ヘルプを読んでもわからないことだらけです(^^;)

これらを一度に全て理解するのは難しいので、調査中に気になったキーワードを少しずつ勉強しています。学習方針は‘行き当たりばったり’(笑)

というわけで、今回勉強したキーワードをメモがわりに記述しておきます。

値型と参照型
スタック領域やヒープ領域の認識がずれていたり、「パフォーマンスの問題」を殆ど無視してたことに気付きました。地形描画プログラムは、殆ど全部値渡しです(爆)

デリゲート
今回の調査中にデリゲートという単語が出てきたのでついでに勉強。



◎次回予告

ACLの頃からずっと懸案だった個別制御がやっとできたので、とりあえず良かったです(^^)

いずれボーンだけコピーする手法も確立したいと思いますが、先にACLへの適用テストと性能比較テストを行います。

テーマ : ゲーム製作 関連 - ジャンル : ゲーム

| BLOG TOP |
DATE: CATEGORY:Softimage Mod Tool
徐商   呂建
徐商(左図)、呂建(右図)
魏将。荊州の戦いで徐晃の援軍として派遣された。合流後、さらなる援軍を待って関羽軍をじりじりと圧迫し、これを破った。



◎推測の裏付け調査

前回のラストで、

「同一モデルのインスタンスのタグに同じ参照値がセットされるのは、Content.Loadの際に重複読込をしないで(最初に読み込んだモデルの)参照値だけ返しているのかもしれません。」

と書きましたが、XNAのヘルプでContentManager.Loadを参照すると

「同じアセットを読み込む呼び出しを繰り返すと、同じオブジェクト インスタンスが返されます。」

との記述がありました。
この推測は正しかったようですね(^^)

まぁ、同じメッシュデータを複数抱えてもメモリのムダですから、ごもっともな仕様でしょうw



◎モーション関連データは複製されているか?

モデルデータ(CrosswalkModel)はメモリ内で複製されていないことがはっきりしましたが、モーション関連データ(現在のモーション番号や時間経過に伴うボーンの位置情報等)はどうでしょうか?
これを確認するためにModelAssetクラスを解析しました。

XNAViewerのModelAssetクラス解析結果

解析中に「同一モデル読み込み時は、ボーンターゲットが全て同一になっている。ボーンのコピーを自前でやらないといけないかも?」と焦ったりしましたが、よく考えると、LoadContentの段階ではボーンもモデル同様1つで問題無いことに気付きました(^^;

で、結論としては、モーション関連データはインスタンス毎に複製されています(たぶん)。この解析だけで丸1日かかってしまいましたが、少しはスキルアップに繋がったと思うので、よしとしましょうw



◎モーション関連データの流れ

モーション関連データがインスタンス毎に存在するのに、全てのインスタンスモデルが同じ動きになってしまうのは、特定インスタンスのモーション関連データを全インスタンスモデルが参照しているからと予想しています。
データの流れをイメージで表すと、こんな感じです。

モーション関連データ参照イメージ(予想図)
モーション関連データ参照イメージ(予想図)

プラグラムと見比べる場合は、インスタンスAをModels[A]、モーション関連データをl_Animationsに置き変えてください。


もし上図の通りであるならば、下図のように改修したいと考えています。

モーション関連データ参照イメージ(理想図)
モーション関連データ参照イメージ(理想図)



◎DrawModel解析

というわけで、予想が正しいか確認するためにDrawModelのコードを解析しました。

XNAViewerのDrawModelメソッド解析結果


ModelクラスのCopyAbsoluteBoneTransformsTo()に関しては、ヘルプを読んでもよくわかりませんでした。ネットを検索すると多数ヒットしましたが、このコードに対する解説やコメントは意外と少なく、未だによくわかりません。

ただ、「(アニメしないプログラムなので)本当は不要なんだけど一応書いときました」というケースが散見されたので、3Dモデル表示時の慣習として(深く考えずに)記述している人もいるようです。この様子だと、今回特に注目すべきコードではなさそうだなぁ…。


そうなると、残る怪しいコードは下記だけです。
l_Animations.ComputeBoneTransforms(transforms);
これ以後のコードは、準備が完了したデータを画面に単純表示するだけなので、今回の問題とは関係ありません。

このコードの呼び出し先はXSIAnimationDataクラスのComputeBoneTransformsであり、その中の
BoneTransforms[index] = BoneInvBindPoses[index] * in_Transforms[Bones[index].Index];
このコードが鍵となりそうですが、BoneInvBindPosesが一体何なのかよくわかりません。

そこで、試しにこの行を
BoneTransforms[index] = BoneInvBindPoses[index];
BoneTransforms[index] = in_Transforms[Bones[index].Index];

などと変えてみたのですが、実行しても何の変化もありませんでした。ホワーイ??



◎予想外の結果

…ここでしばらくハマっていたのですが、結局環境設定の問題でした。以前試行錯誤した時に、SOFTIMAGE_XNAViewerプロジェクトの参照設定XSIXNARuntimeのパスを変更してしまったので、ランタイム側のソースを変更しても反映されなかったのです。これを直したら、画面が変化しました。

BoneInvBindPoses
こちらは試しに
BoneTransforms[index] = BoneInvBindPoses[index];
とした状態です。モデルは全く動かないので、BoneInvBindPosesは固定値ですね。今回は気にしなくても良さそうです。


in_Transforms
こちらは試しに
BoneTransforms[index] = in_Transforms[Bones[index].Index];
とした状態です。見た目はアレですが動きます。
つまり、in_Transformsは時間経過に伴うボーン移動情報が格納されている、ということです。

実は私はModel.Bones.Transformの値は固定値であろうと考えていたので、この結果は予想外でした。



◎Transformの値

確認のため、各インスタンスのTransformの値をログに出力しました。

Models[*].CrosswalkModel.Bones[*].Transformのログ(一部抜粋)

時間経緯と共にTransformの値が変動するボーンがありました。ということは、呼び出し元のm(Modelクラス)の中に、モーション関連データの一部が格納されている、ということです。

また、同一モデル&同一タイミングでは、Transformの値が同じです。ということは、Draw()内のデータ参照元がおかしいのではなくて、Update()内でモーションデータを計算or格納する段階でおかしい、ということです。



◎おや?

私はモーション関連データは全てXSIAnimationContentクラスに格納されていると予想していたのですが、実はモデルデータ(CrosswalkModel)の中にも重要なデータが存在することが判明しました。

…ちょっと待てよ?確か「モデルデータ(CrosswalkModel)はメモリ内で複製されていない」という結論が出たはずでは?

ガガーン!!
ど~すりゃいいんだ~!!



◎次回予告

ボーンのコピーを自前でやらないといけないんですかね~?

「そこまでやるぐらいなら、ランタイムいらないのでは?」と自分に突っ込みつつ、今後どうするか検討します。

…メモリ浪費を覚悟の上で、モデルインスタンスを丸ごと複製しちゃおうかなぁ?w

テーマ : ゲーム製作 関連 - ジャンル : ゲーム

| BLOG TOP |
DATE: CATEGORY:Softimage Mod Tool
趙儼
趙儼(ちょうげん)
魏の軍政家。荊州の戦いでは徐晃と共に援軍として駆けつけ、曹仁の救出を急ぐ軍内の意見を抑えて万全の体制をとるよう主張し、さらなる援軍を迎えて関羽を破った。敗走する関羽を追撃すべしとの意見を抑え、呉と蜀の争いになる展開を予測し、水を差さないよう進言した。



◎モデルの複数表示

モデルを複数表示できるようにXNAViewerを改修しました。
槍兵、ロボット、キャプテンが同時にアニメーションします。

槍兵モデル複数表示

iキーを押す毎に槍兵を1体追加するようにしたら、増やせば増やすほどアニメーションが速くなるという不思議な状態になりました。普通逆でしょ?(^^;

○10秒あたりに突く回数
  1体:2回
  2体:4回
  3体:6回

これはプログラムの問題でしょうか?
モデルの問題でしょうか?



◎試行1:モーションを個別に割り当てる

ロボットが増えるよう改修し、いろいろ試してみました。

ロボットモデル複数表示

ロボットモデルには3種類のモーションがありますが、5体のロボットに別々のモーションを割り当てようとしても、皆同じモーションになってしまいます。

また、モーションの速度は、5体に割り当てたモーション速度の合計値に影響しているようです。これはつまり、モデルじゃなくてプログラムの問題ですね。


XNAViewerは、リスト型のModelsにAddメソッドでインスタンスを追加していますが、同一クラスのインスタンスを追加するやり方だと、実はACLでも同様の現象が発生します。3Dテストプログラムのフロントダンサーが、3人揃って同じ動作をするのはこの応用です。…って当時はわけもわからずやってました(笑)



◎試行2:別名インスタンスによる個別制御

3Dテストプログラムでは、フロントダンサーとメインダンサーで別々の動作をさせるために別々のクラスを作成しましたが、XNAViewerランタイムでもそのようにしないといけないのでしょうか?

試しに別名のインスタンスを作成してみました。
Models = new List();
Models2 = new List();

別名インスタンスによる個別制御テスト

下列3体がModels、上列3体がModels2です。上下で別々のモーションをセットしても、同じ動きになりました。途中で別のモデルを混ぜても関係ありません。

…やっぱりこうなるんですね。昔ACLでも同じ実験をして同じ結果になりました。C言語のインスタンスの概念からすると、別名でも同名でも一緒というのは理解できます。


しかしモデルが異なると個別制御できるのに、同一モデルだと個別制御できない理由はいまいち理解できません。この問題は何とかしないと「メインマップに複数の同一ユニットを表示し、バラバラに動かす」といったことができません。もう少し調べてみましょう。



◎試行3:コンテナを個別に用意する

これまでコンテナ(SASData)は共通的に使用してきましたが、もしやこれが関係してるのかと思い、試しに別名インスタンスのコンテナを作成して個別に割り当ててみました。

…しかし結果は変わりませんでした。
コンテナは関係無さそうです。



◎プログラム調査

仕方が無いので、プログラムを詳しく調査します。

まず、カレントモーション(現在動作中のモーション)番号の格納先を確認すると、ModelAssetクラスのAnimationIndexでした。動作中の値を確認すると、各インスタンス毎に異なる値(正しい値)を保持してました。ということは、この値を参照するよう改修すると、問題が解決できそうです。

…と、ここまでは順当に判明したものの、この先が難解でした。


一番怪しいのは、DrawModel()内の
XSIAnimationData l_Animations = m.Tag as XSIAnimationData;
と記述された部分です。モデルのタグからアニメーション情報を逆引き(?)してるようですが、m.Tagは(同一モデルの場合)同じインスタンスモデルを指すのかもしれません。

試しにCrosswalkModel.Tag.GetHashCode()としてハッシュコードを取得すると、同一モデルには同じ値が入ってました。

Tag = 33736294(ロボット)
Tag = 35191196(キャプテン)
Tag = 33736294(ロボット)
Tag = 33736294(ロボット)
Tag = 33736294(ロボット)

ハッシュコードがどういうものかよく知らないのではっきりとは言えませんが、前述の仮説は正しそうな気がします。



◎試行4:タグの書き換え

ModelAssetのLoadContent()を見ると、タグにはModelsインスタンスの個別参照値がセットされてもおかしくなさそうですが、実際には同じ参照値がセットされるようです。
ではどうするか?

試しに、Content.Load直後にタグを連番や新規生成ハッシュコードで強引に書き変えてみましたが、実行時に例外エラーで落ちました。タグにはモデルのインスタンスを渡しておかないとダメなのかもしれません。

よく考えると、同一モデルのインスタンスのタグに同じ参照値がセットされるのは、Content.Loadの際に重複読込をしないで(最初に読み込んだモデルの)参照値だけ返しているのかもしれません。その方がメモリを節約できますからね。

もしそうだとすると、メモリ内のモデルデータは1つしか存在しないので、タグの書き変えは不可能ということになります。



◎次回予告

というわけで目一杯ハマってますが(汗)、これは何とかしないといけない問題なので、もう少し粘ります。

テーマ : ゲーム製作 関連 - ジャンル : ゲーム

| BLOG TOP |
DATE: CATEGORY:三国志軍記開発
蒋済
蒋済
曹操から3代に渡り魏に仕え、的確な進言を多数行い、太尉にまで昇進した。関羽北上の際は、司馬懿と共に遷都に反対し、孫権に関羽の背後をつかせる策を進言した。権力におもねらない硬骨漢であったが、泥酔して乱暴したり人を追い返すこともあった。



◎7月の目標達成度

・Softimageで槍兵モデル更新(3日)

 実績:14日間で更新完了(達成率100%)


・アニメライブラリ選定(3日)

 実績:4日間でランタイム制御調査まで(達成率10%)


・地形モデル描画(4日)
・マップオブジェクトモデル描画(5日)
・マップデータ調整(1日)
・マップオブジェクト属性データ作成(1日)

 実績:未着手(達成率:0%)


・その他
 →ブログ更新/HP更新(3日)
 →休息/予備(5日)

 実績:2日間で「3D人型モデルをSoftimage Mod Toolで編集しXNAで動かす」を作成(達成率:100%)


・活動時間月140時間以上

 実績:141時間(達成率:100%)



◎作業時間分析

7月から鳳雛さんと相互管理を始めたので、作業時間の記録が残っています。これを集計し自己分析しました。

作業時間集計2009年7月(PDF形式)

○良かった点
・相互管理のおかげで活動時間は目標達成
・やる気が高い時期(前半)に、集中的に進めた
・1日も休まず走った(活動じゃないけど(^^;)

○悪かった点
・作業時間の割に成果や進捗がいまいち
・ブログやHPの比率が4割に達している
・中後半に休みが多い(バテた)

7月は「活動140時間以上」と「毎日休まず走る」の2点を重点目標と考えていたのですが、これを達成できたのは嬉しいです(^^)

しかし作業時間の割に、進捗は伸びませんでした。「スキル不足のため、壁を超えるのに時間がかかった」というのが直接的な要因ですが、今にして思えば、時間を短縮するための工夫が足りなかったかもしれません。

以前のツールと同レベルのことが出来るようになるのに3か月もかかるとは…(>_<)



◎XNA連携修得方針について

前回のランタイム制御で、ようやく必要最小限のことが一通り出来るようになったと思っています。

しかしこれまでの感触からすると、XNA連携スキル全体の半分も修得していないのかもしれません。もし現時点で3D担当者からモデルを受領した場合、XNAで動かせるようになるまでかなり苦戦しそうです。

ではまだXNA連携の勉強を続けるのか?答えはNoです。
ただ漠然と勉強しても身に付かない気がするからです。

今後はゲーム開発を進めて、ある程度形が整った段階で3D担当者を巻き込み、その時に試行錯誤するつもりです。



◎年間目標と開発スケジュール

XNA連携の影響で、4月に立てた開発スケジュールが破綻してしまったので、鳳雛さんと相談して開発スケジュールを見直すことにしました。

A案:完成予定を3~6か月延期してスケジュールを組み直す

B案:年内目標成果物の品質レベルを下げる(α版以前の状態。ゲームとして遊べないので、リリースもしない)

C案:ゲームデザイン確認用として2D版を年内に作成し、来年以降3D版を作成する

D案:大幅な予定変更はせずに、細かい工夫と努力を積み重ねてなるべく早く仕上げるよう最善を尽くす

まずB案D案が却下されました。C案にはちょっと魅かれるものがありましたが、以下の理由により却下されました。

「実際にゲームがプレイできて、このゲームが面白いか否かを判断できるぐらいまで仕上げる場合、別のゲームをもう1つ作るのと同程度のコストがかかる。しかしそれに満たないレベルのプロトタイプ版は、存在意義が薄い。」


というわけで、A案をベースに年間目標とスケジュールを組み直しました。

2009年度 年間目標(8月修正版)(PDF形式)

2009年度 開発スケジュール(8月修正版)(PDF形式)



◎8月の目標

実績集計が時間単位になったので、作業目標も時間単位とします。

・活動時間月150時間以上

・ライブラリ選定(30h)

・地形モデル描画(40h)

・マップオブジェクトモデル描画(30h)

・マップデータ調整(6h)

・シナリオ概要作成(6h)

・その他
 →ブログ更新/HP更新(38h)



◎次回予告

XNAViewerを改修してモデルを多数表示し、ACLとパフォーマンスを比較する予定です。

テーマ : ゲーム製作 関連 - ジャンル : ゲーム

| BLOG TOP |
DATE: CATEGORY:Softimage Mod Tool
司馬懿
司馬懿
魏で功績を重ねて大権を握り、後の晋の礎を築いた。演義では諸葛亮のライバルとして描かれている。荊州の戦いでは、関羽の北上に狼狽し遷都を諮る曹操に反対し、孫権を動かして関羽の後背を突く作成を提案、これを成功させた。



◎情報収集

ヘルプが駄目だったので、ネットを探ってみたのですが、検索範囲を海外まで広げても、ランタイムのコードに関する情報は殆ど見当たりませんでした。

唯一見付けたのがこちらのソースですが、残念ながらBasicEffectなので参考になりません。

いや待てよ?現在のエフェクトをBasicEffectと見なして強引に読み込めないかな?
…ダメでした。「キャストできません」とエラーになりました。



◎チュートリアルビデオ

どうしたものかと悩んだ末、海外の公式チュートリアルビデオをチェックすることにしました。ビデオでコードまで踏み込んでいる可能性は低そうですし、英語で解説されてもさっぱり解らないのですが、こうなったらダメモトです。

こちらが多分公式のチュートリアルビデオです。今回はラスト2つを視聴しました。


特に気になったのは、エラーチェック(XNA Game Studio>Diagnose Models)を実行した時に、警告やらエラーやらが大量に表示されたこと。「自分だけじゃないんだなぁ」と安心していたら、いつの間にかエラーが無くなりました。ちょっとびっくりしましたよ!「お前、今何やった!?」って(笑)

ビデオを見直すと、XNA Game Studio>Publish Models の「Consolidate images and FX files」ボタンを押してました。ヘルプを確認すると、テクスチャ/Effectファイルをコピーする機能のようです。私は予め手動コピーしていたので動作上の問題はありませんでしたが、本来はこうするべきだったのですね。


他に気になったのは、

・ビューポートは「DirectX9」画面で編集している模様

・マテリアル関連を操作しているが、よくわからない

・「Publish」直前に「Transform>すべての変換をフリーズ」を実施している

・モデル出力先フォルダがXNAコンテンツフォルダではない

などです。マテリアル関連は後できちんと確認した方が良さそうだなぁ。



◎要総チェック?

ビデオ2本見ただけ(しかも解説無し)でこれだけ気になる点が出てくるということは、全ビデオを翻訳して見直した方が良いかも…と迷いましたが、結論は保留。

仮にビデオの内容をマスターしたとしても、XNAでモデルを制御できなかったら意味無いですからね。
というわけで、プログラムに戻ります。



◎コントローラ導入

ビデオからは何もヒントが得られなかったので、どうしたものかと思っていたのですが、たまたまヨドバシカメラに行く用事があったので、ついでにXBOX360のコントローラを購入しました。本体は持ってないんですけどね(笑)

これを機にSoftimageの再インストールを実施し、XNAViewerプロジェクトを初期状態に戻しました。これまで(キーボード対応など)プログラムを多少改造していたので、初期状態に戻せば何かヒントが掴めるかも…と期待したからです。

コントローラ操作1   コントローラ操作2

キーボードではアナログコントローラを再現できないので、その辺の機能はこれまで無視してましたが、ようやく操作できるようになりました。

しかしアナログコントローラを操作すると、画面上での位置は移動しますが、ランタイム表示オブジェクトだけでなく非ランタイム表示オブジェクトも移動します。やはり、この操作はワールド座標ではなくビュー座標を変更してました。

合計3個(アナログ2個と十字1個)のレバー入力が可能なのに、ワールド座標変更操作が1つも無いのはサンプルとしてどうかなぁ?



◎FXファイルの書き換え

結局新たなヒントは1つも得られませんでした。残る手段は、FXファイルの書き換え/差し替えぐらいでしょうか?ハードルが高そうなのでなるべく避けたかったのですが、他に思い付きません。

…で、腹をくくってFXファイルを解析すると、意外なことが判明しました。

以前さらっとxsi_defaultvs.hlslを見た時に、Modelパラメータをベースとしたワールド座標変換処理が記述されていることを確認したのですが、実はスキンモデルと非スキンモデルに処理が分かれてて、以前見たのは非スキンモデルの処理でした。

スキンモデル処理内のワールド座標変換処理は、Modelパラメータを無視してるようです。ワールド座標が反映されない理由は、ここにありました。


というわけで、ワールド座標を反映するよう書き変えました。

// transform in screen space
// OUT.position = mul( mul(weightedposition, View), Projection );

float4 position = mul(weightedposition, Model);
OUT.position = mul( mul(position , View), Projection );


FXファイル書換

前回の画像と見比べてもらえばわかると思いますが、今回の槍兵モデルはワールド座標の変更が反映されています。やっと思い通りに動かすことができました!

キャプテンモデルのワールド座標の変更も試みましたが、こちらはさらにXNAコード改修が必要のようです。まぁ、元々1体だけ表示するプログラムですからね。



◎意図不明

XNAViewer及び添付FXファイルは、非スキンモデルはワールド座標パラメータに対応してますが、スキンモデルはワールド座標パラメータ非対応でした。

何故このようにしたのか、私には設計者の意図が理解できません。私のレベルでは気付かない、何か深い意味があるのでしょうか?



◎次回予告

8月になったので、次回は「7月の総括と8月の目標」です。

テーマ : ゲーム製作 関連 - ジャンル : ゲーム

| BLOG TOP |

copyright © ゲーム制作の舞台裏 all rights reserved.Powered by FC2ブログ
上記広告は1ヶ月以上更新のないブログに表示されています。新しい記事を書くことで広告を消せます。