public class ModelAsset { public Model CrosswalkModel; public int AnimationIndex = 0; // 現在のモーション番号 public int OldAnimationIndex = 0; // 直前のモーション番号 public List Animations; // モーション関連データ public String FilePath; public ModelAsset(String AssetPath, ContentManager content) { LoadContent(AssetPath, content); FilePath = AssetPath; } public void LoadContent(String AssetPath, ContentManager content) { CrosswalkModel = content.Load(AssetPath); // CrosswalkModel.Tagには、このモデルを識別するオブジェクト(CrosswalkModel自身の参照値(ポインタ))が格納される。       // 同一モデルを複数回読み込んだ場合、各インスタンスのCrosswalkModel.Tagには同じオブジェクトインスタンス       // (最初に読み込んだCrosswalkModelの参照値)が格納される。 Animations = new List(); // モーション関連データ格納用領域確保 // 同一モデルを複数回読み込んだ場合でも、モーション関連データはインスタンス毎に生成される // post process animation XSIAnimationData l_Animations = CrosswalkModel.Tag as XSIAnimationData;       // CrosswalkModel.Tag(オブジェクト参照型)を、XSIAnimationDataクラス参照型に型変換し、l_Animationsに代入している。       // asはcastに似ているが、変換できないときはエラーにならずnullを返す。       // asの詳細については下記参照。       // http://www.atmarkit.co.jp/fdotnet/dotnettips/005castandas/castandas.html if (l_Animations != null) { foreach (KeyValuePair AnimationClip in l_Animations.RuntimeAnimationContentDictionary) { AnimationClip.Value.BindModelBones(CrosswalkModel);       // 実際に呼び出されるのはXSIAnimationContentクラスのBindModelBones()メソッド。 // その中で、l_Animationsのアニメーションチャンネル(=キーフレームのコレクション)のボーンターゲット(ボーン情報の参照元)を、 // CrosswalkModelのボーンとしている(バインドしている)。 // // ちなみに、XSIAnimationChannelクラスのメンバーにはTargetが存在するが(初期値null)、 // XNA標準のAnimationChannelクラスのメンバーにはTargetは存在しない。 // XSIAnimationContentクラスを使用する前に必須の初期設定と推測する。 //       // 尚、CrosswalkModelとl_Animationsの参照値は(異モデル読込時においても)同じインスタンスを指している。 Animations.Add(AnimationClip.Value);       // 上記バインドが完了したデータを、モーション関連データに追加している。 } l_Animations.ResolveBones(CrosswalkModel);       // ボーン確定処理。       // 実際に呼び出されるのはXSIAnimationDataクラスのResolveBones()メソッド。       // その中で、l_Animationsのボーンリストに引数CrosswalkModelのボーンを追加している。       // XSIAnimationDataクラスを使用する前に必須の初期設定と推測する。 } } }