2009年7月20日月曜日

さらに読み込むべし

次はアクションとキーフレームの読み込みです。


Model::Action* Model::readActionLine(std::istream& in) {
std::string name;
in >> name;
Action *a = new Action(name);
actions.push_back(a);
return a;
}


アクションの行にはアクション名しか出力してなかったので、単純にアクション名を読み込んでアクションクラスのインスタンスを生成し、actionsというベクタに追加しています。

キーフレームの読み込みはちょっと長いです。

void Model::readKeyframeLine(std::istream& in, Action& action) {
unsigned int num;
std::string boneName;
float x, y, z;
float qw, qx, qy, qz;

if (armature == NULL) {
std::cerr << "found keyframe line without previous armature line" << std::endl;
return;
}
in >> num;
Keyframe *f = new Keyframe(num);
do {
in >> boneName >> x >> y >> z >> qw >> qx >> qy >> qz;
if (in.fail()) {
break;
} else {
Bone *bone = armature->findBone(boneName);
if (bone != NULL) {
ActionKey *key = new ActionKey();
key->bone = bone;
key->loc.x = x;
key->loc.y = y;
key->loc.z = z;
key->quat.w = qw;
key->quat.x = qx;
key->quat.y = qy;
key->quat.z = qz;
f->addKey(key);
} else {
std::cerr << "not found bone named " << boneName << std::endl;
}
}
} while (true);
action.addKeyframe(f);
}

引数で渡されるActionは直前に生成したアクションクラスのインスタンスです。読み込んだキーフレームはこのアクションのキーフレームとして追加します。
キーフレームクラスのインスタンスを生成し、それにキー情報(ActionKeyクラスのインスタンス)をボーンの数だけ追加しています。キー情報には、関連するボーンのポインタと平行移動の座標とクォータニオンを保持させています。関連するボーンはアーマチャのfindBone()でボーン名から取得しています。key->locはVector3クラスのインスタンス、key->quatがQuaternionクラスのインスタンスです。それぞれ実例で学ぶゲーム3D数学で使われているソースを利用しています。キーフレームの数だけこの読み込みが行われることになります。

そして、頂点ブレンディング用の重みの読み込みです。

void MyModel::readWeightLine(std::istream& in, Bone& bone) {
unsigned int idx;
float weight;
do {
in >> idx >> weight;
if (in.fail()) {
break;
} else {
if (idx < numVerts) {
Vertex* v = &vertices[idx];
v->addBoneWeight(&bone, weight);
} else {
std::cerr << "vertex idx is out out range for weight. idx=" << idx << std::endl;
}
}
} while (true);
}

引数で対象となるボーンを渡しています。頂点番号と重みのペアの繰り返しを読み込んで、該当する頂点にボーンと重みを追加しています。最終的に頂点に追加されたボーンの数だけ変換行列をブレンドしてやることになります。

と、こんな感じで読み込みが終わったので、次はいよいよ表示、つまりアニメーションの実装です。

0 件のコメント: