プロフィール

Na-7

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


アクセスカウンター


最新記事


最新コメント


最新トラックバック


月別アーカイブ


カテゴリ


DATE: CATEGORY:スポンサー広告
上記の広告は1ヶ月以上更新のないブログに表示されています。
新しい記事を書く事で広告が消せます。
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

スポンサーサイト

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

コメント

あれっ?

ContentManager.Load()は同じアセットファイルを読み込むんでも同じインスタンスを返すって、以前書きませんでしたっけ……思い違いかな(汗)。あの時はEffectの話だったかも知れませんが。

CopyAbsoluteBoneTransformsTo()で得られるのは各ボーンのルートからの変換行列群だと思います。ただし、XNAは現状ろくにアニメーションをサポートしていないため、“何もアニメしていないデフォルトのポーズにおいての”変換行列群が取れるだけです。「基本のポーズだけ取れるようにしとくから、実際のアニメは勝手に設定してね」という程度でしょう。既存のアニメーションライブラリを使うなら必要ないかも知れません。


あと大変僭越なのですが、ブログ主さんはどんなゲームを作ろうとされているんでしたっけ? 対戦格闘ゲームとかで人間の肌がはっきり露出するならともかく、小さめのキャラがわらわら出て来るようなゲームなら、スキンなしで昔ながらのジョイント関節でもいいような気がしましたので。

>あの時は
あの時はエフェクトの話題だったので、Load<Effect>()限定の話として記憶してました(^^;

>CopyAbsoluteBoneTransformsTo()で得られるのは
解説ありがとうございます。若干予想はしたものの、確信が持てなかったのですが、お陰でスッキリしました!

>どんなゲームを
戦術級シミュレーションゲームです(^^)
A:演出シーンや一騎打ちシーンはアップで表示したい
B:メインマップはFPSのような一人称視点に切替可能としたい
上記の理由でスキンアニメを必要としています。但し、どうしてもパフォーマンス(描画速度)が上がらない場合は、Bを諦めて
>昔ながらのジョイント関節
とすることも検討します。

ウチでも複数モデルのアニメーションを試して見ましたが当然ながら同じ現象。
記事参考にさせていただきつついろいろ調べて
問題の理解に至りましたがクレバーな解法は分からなかったので
Update()内でPlayBackを呼ぶ前後のModel.Bones[*].Transform をインスタンス毎に
自力コピー&復元することで何とか動きました・・たぶん。
これでいいんだろうかという疑問はありますが動けば正義ということで。
クリエイターズクラブのフォーラムにも同じ問題についてトピックがありましたが
解決してないみたいでしたが・・みんなどうしてるんだろう・・。

動けば正義!

HOSSIEさんこんにちは~

>Model.Bones[*].Transform をインスタンス毎に自力コピー&復元
私も出来ればそうしたいのですが、私のスキルではちょっと難しそうなので、別の方法を模索してました。

>何とか動きました
おめでとうございます!
私も今やっと動きましたよ~

>動けば正義ということで。
動けば正義!w

>みんなどうしてるんだろう・・。
私も凄く知りたいです。でも結論めいた情報は殆ど見当たらないんですよね~

コメントの投稿


管理者にだけ表示を許可する

トラックバック


この記事にトラックバックする(FC2ブログユーザー)



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