メニューなどのリソースのヘッダ。あと、モデルと、実行ファイル及び、プロジェクトファイルが入っています。入れているんですが、これっていいですかね。実際には、ライブラリとして使いたい「くれくれ君」が多いでしょうから、関連するファイルを一つ(CSkinModel.cpp)にまとめました。単独のオブジェクトになるように、複数のメッシュが登録できる仕組みは取り除いて簡単にしました。オブジェクトを使用しています。最初にすることですが、ヘッダファイルを読み込んでオブジェクトを生成します。実際に取り扱うクラスです。あれば十分に使えます。次に必要なのが初期化です。内部で時間差をとって表示するフレームを決めるので、開始時間も初期化時に受け渡します。Xファイルをロードします。通さなければ、同じ姿勢で表示されます。それ以外に、ワールド行列(に連動した回転や平行移動)や、ビュー行列を指定できます。指定すれば、位置が動きます。}最後は、お決まりの後片付けです。「Release()」を、呼んでください。}これぐらいなら、どなたでも使えるのではないでしょうか。複雑なことをされたい方やシェーダーを変えたい方は以降で説明する内部構造から、改良を加えていってください。初期化で一番大事なことは、頂点シェーダーの作成です(後は、引数を保存しているだけです)。今回は、なるべくファイル数を減らしたかったので、頂点シェーダーをプログラム中に埋め込んでいます。現在の頂点シェーダーでは、分岐命令が使えないので、混ぜ合わせる行列の数に対応して、頂点シェーダーが4つに分かれます。ここらへんは頂点シェーダー2.0になって、本質的に良くなる一つの点ですね。今回は、「行列パレット」を使います。「行列パレット」とは、変換のためのローカル行列を配列として格納したものです。実際にブレンドに使用する(4つ以下の)行列を「行列パレット」から引っ張ってきます。絵を書くときにパレットから原色を取り出して色を作るように行列を混ぜ合わせて、実際に用いる行列を作ります。行列を引っ張るのに、初登場のアドレスレジスタを使います。動的に参照する番号を変えるためのレジスタです。サポートしていない頂点シェーダー1.0では、ソフトウェア的にしかシェーダーを実行できません。行列パレットでは4x3の正方でない行列をつかいます。今回のパレット数では最大が29個(c9~c95で87個の定数レジスタから3列の行列を生成する)にもなるので、自明な4列目の行列は省略して少しでもレジスタを節約しています。行列1つの(骨が入っていない)モデルの表示をする頂点シェーダーは次のとおりです。サンプルをそのまま引っ張ったので、コメントが多いですが、やっている事は短いです。アドレスレジスタです。命令などで、行列パレットの最初の位置である定数レジスタ9をオフセットにして行列を引っ張ってきます。係数や並び順が頂点情報に入れられて時点のものでは使いづらいので並び替えます。後は、透視変換したり、法線は規格化して光源計算を行ったり、テクスチャー座標をコピーしてテクスチャーを張ります。次に一気に飛ばして行列を4つ混ぜる場合を見ましょう。1つの場合との違いはアドレスレジスタを4回変更して、4つの行列を合成していることです。掛けて、混ぜ合わせます。全ての係数の和が1になるように4つめの係数はそれ以外の3つの係数から求めました。};行列が2つと3つの場合の合成はちょうどその中間のようになします。シャーダープログラムの生成は次のようになりますが、特に見るべき点は無いので、適当に流してください。}■内部プログラム:ロードでは、いよいよXファイルのロードです。ここが一番しんどい部分です。親子関係を構築するなどのいろいろなことをしなくてはなりません。使われている関数やメソッドをまとめると次のようになります。しんどいですが、順次見ていきましょう。呼びだされた関数の内部ですが、大まかに2つの部分に分かれます。本質的なロード関数です。全体の流れを制御します。現在登録されているモデルを削除し。}説明すつ前に、少し構造を示しておきましょうか。彼が基点となり、骨の親子関係を構築する階層構造を作ります。親子関係を保存するための木構造です。(時間の設定を容易にするための)アニメーション構造のツリー構造です。階層構造の情報が入ります。いままで出てきた階層構造は、骨格を考えることになります。下のような骨格を持つモデルが考えられます。橙色の「へそ」の部分から全ての矢印は伸びていますが、ここを「親」とよびます。親から直接伸びている部分が子供です。矢印が複数伸びている場合(「へそ」からは3本伸びていますね。)それぞれの子供の関係は兄弟(sibling)と呼ばれます。骨を表現する行列だけでなく、メッシュやアニメーションデータも格納します。各親および子供から緑色の矢印が出ています。この矢印は骨の回転運動による基底行列の向きの変化を表しています(どこが基準の位置か明示されていませんが、それはアニメーションをしていないときの矢印の向きが自然な向きです)。骨の行列の平行移動の部分は、白い矢印で表されます。ワールド座標から見たときの子供の行列は、親の行列に子供自信の行列を掛けます。掛けた行列をさらに子供(元の親から見て孫ですね)に渡すことによって、親の行列の情報が子孫に伝わっていきます。この変換によって、腰を回したときに、肩も腕も同じように回ることが表現できます。ここでも骨格は、あくまで説明用に適当に作ったものです。皆さんがどのようなワンスキンの骨格を作られているかはわかりません。行列の合成に関しても、ここで見ておきましょう。黄色い子供に注目します。黄色い子供から出ている矢印は、紫色で囲まれた3つです。この3つの行列が「黄色い子供に関連付けられた」メッシュを混ぜ合わせる合成行列になります。黄色い子供の行列自体はワールド行列に設定され、重心移動のような効果として用いられます。等のメモリを確保します。使うためには必ず確保するものですし、特に問題はないでしょう。Xファイルを取り扱うための準備をします。「テンプレート」を読み込みます。「テンプレート」とは、Xファイルを読み込むためのフォーマットが格納されたファイルです。ここでは、いにしえのRMで規定されたフォーマットを読むように宣言します。(が、誰もそんなことしないでしょうね)。{...}で、どんどん読み込んでいきます。読み込むかは後でやっていきましょう。それぞれのメッシュに骨の行列のポインタを確保していきます。操作すればよいでしょう。終了したらロードに成功したもほぼ同じなので、名前を保存したり、メッシュを登録します。射影行列を設定したり、時間やアニメをしていないときの行列を保存するなどの変数の初期化を行います。xファイルの中身のデータを見る部分にいきます。よって得られるさまざまな種類のデータがあります。各骨に関連した行列データ。その中にさらにアニメーションデータが入っている。子のフレームの情報が入っている(再帰的に子供のデータを読み込む)それらを適当な方法で読み込みます。}それでは、それぞれの読み込みを見ましょう。メッシュの読み込みです。質感やテクスチャーの情報があります。あるメッシュデータを読み込みます。メッシュを適当な構造に再構成します。質感情報やテクスチャーのロードなど、スキンでないメッシュでも行った手順を踏みます。メッシュの再構成ですが、描画方法によって処理が異なります。}今回は、頂点シェーダーにしか興味がないので、_GenerateMeshIndexedVs(D3DINDEXEDVS)を見ます。固定レジスタの数に限界があるので、行列パレットの最大値を制限します(あれ、ここで28個ですね。29個までいける気もするのですが...)。次に頂点シェーダーのバージョンをチェックして、ハードウェアで実行できるか確認します。だめならソフトウェアT&Lで実行です。頂点パレットが使えるように変換します。フレキシブル頂点フォーマットを確認して、混ぜ合わせる行列の数、すなわち頂点シェーダーの種類を確認します。最後にフレキシブル頂点フォーマットにあったメッシュに再変換します。}以上で、メッシュの読み込みは完了します。次にアニメーションセットです。登録されたアニメーションを読めるだけ読んでいきます。}最後にアニメーションです。ここも分岐があります。以外にも、子供のフレームデータや「参照」として別のフレームのデータを引っ張ってきたりします。サンプル通りにしておきましょう。キーフレームデータキーフレームデータの中にも種類があります。行列のデータがそのまま入っていますちなみにキーフレーム(法)とは、アニメのデータを全ての時間持っているのでは無く、時間を空けて持ち、その間は適当な方法で補間する方法のことです。同じアニメーションでも、キーフレームが少ないほうがデータが小さく、綺麗なアニメーションになる傾向があります。以下にキーフレームの数を減らすかは、アニメータの腕、ないしはコンバーターを作る人の腕にかかっています。}と、このような長い経過を経て、ロードが終了します。あと説明していないのは、レンダリングステートなどの設定ですね。深度バッファを有効にしたり、ライトの構造体を設定したりします。}ごくろうさまでした。描画部分では、時間を進める部分と設定された時間で描画する部分とに分かれています。時間を進める部分では、全てのアニメーションのフレームにわたって時間を設定します。倍していますが、これはSDKのサンプルからそのまま引っ張ってきた値なのでどうしてか分かっていません。ここを変えればスローモーションになったり動きが速くなったりします。}実際に時間を設定する部分は条件分岐の嵐です。線形補間と、補間の仕方を変えます。データを行列で与えるのはデータが離散的になるので、なるべくやめたほうがよさそうですね。}描画部分はもう少し入り組んでいます。全体の回転や平行移動を決め、ビュー行列も確保した後、行列を決定しその行列で描画します。各骨の行列から親子関係を持ったローカル行列を作成します。方法は親の骨の行列にさらに自分の骨の行列を掛けて親からの相対的な行列に変換します。自分の骨を子供に受け渡して、さらに孫、曾孫のローカル座標を作らせます。作成した行列をワールド座標に設定して描画し、子供も次々に描画していきます。}描画する関数は、さらにレンダリング方法によって分岐します。今回は頂点シェーダーにのみ注目します。選ばれるので、その中身を見ていきます。次に(スキンでない)メッシュを描画するときと同じように頂点バッファ、インデックスバッファ、頂点シェーダーの指定を行います。ここで、混ぜ合わせに使う行列の数に応じて頂点シェーダーの切り替えが行われます。次に骨の行列を固定レジスタに設定します。高速化したいときは、(行列の数を減らして)全ての行列を共通化して一モデルに一回ぐらいの更新に減らすと早くなるかもしれません(未検証)。}■内部プログラム:後片付け後片付けは確保したメモリを開放します。階層構造になっているものはその子供、兄弟も順次開放していきます。}■最後にやっとモーションを終えました。オブジェクト化を進めようと思ったのですが、全然、まとまってなかったりして...モーションは難しいことがない割に、ソースコードばかり長くなるので、説明はしたくないところですよね。サンプルを見ろよ』で片付けられますね。個人的には、その回答で良いと思うのですが、うざいのでやってみました。モーションはフォーマットをどうするのかは考え物ですよね。今回のように、よく知られたXファイルを使うときには、全てのXファイルが表示できないと文句いわれるし。仕事でやらない限りは、広がっているフォーマットを使うほうが(頭の良い人が考えているはずだから)効率もいいだろうし、データも沢山あるしでお勧めする方法だと思いますけどね。いうことで、今後『初心者なのですが、ファイルでアニメーションをするにはどうすればいいですか』という『あきらめろ』といいたくなるような質問が減ってくれればいいと思います。もどるimagire@gmail.com。