02、mikotoデータを読み込んで影響度を設定する



02章ではmikoto形式のmqoデータを読み込み、頂点にボーンの影響度を設定します。
影響度を使ってボーン変形して表示する部分は03章でやります。

mikotoデータ読み込みでは、従来のRokDeBone2の機能を改良した機能を実装します。
例えば、1つのボーンについて複数のアンカー形状が定義してあっても正しく機能するようにし
また、アンカー形状が凹型であってもちゃんと頂点の内外判定が出来るようにします。


ソースは下のページからダウンロードしてください。
OpenRDBダウンロードページ

02−01、mikoto形式とは

mikoto形式のmqoファイルの作り方の詳細については、他の方のホームページに任せます。
ぼくが知っている中ではUMEMORIさんのサイトが一番まとまっていて分かりやすかったです。
http://umemori69.hp.infoseek.co.jp/umemori69_005.htm

概略を書くと
mikoto形式では1つのボーンは1つの三角形で定義します。
三角の辺の長さの大小で、親の位置と子供の位置と軸の向きを定義します。

そしてそれぞれのボーンの影響範囲を箱型の立体(アンカーと呼びます)で定義します。

どのアンカーがどのボーンに対応するものであるかは
ボーンとアンカーに同じ材質を割り当てることで設定します。

キャラクターのすべての頂点は、少なくとも1つのアンカーの中に入っているように作ります。

1つだけのアンカーの中に入っている頂点はそのアンカーに対応するボーン1個だけの影響を100%受けます。
複数のアンカーの中に入っている頂点は、複数のボーンの影響がブレンドされて
曲がったときに滑らかに変形します。


02−02、オブジェクトとマテリアルを分類する

ボーンやアンカーの作成命令はCMQOFile::LoadMQOFileから呼び出されるLoadMQOFile_aftから呼び出されます。
まずボーンやアンカーを区別せずに全部読み込みます。
そしてPickUpAnchor()で表示オブジェクトとボーンオブジェクトとアンカーオブジェクトを分類します。
材質についても表示オブジェクト用の材質とボーン用の材質を分類します。

次に m_modelptr->MakeBoneTri() でボーンを作成します。
そして m_modelptr->MakeInfScope() でInfScope(アンカーのOpenRDBでの呼び方)を作成し
InfScopeとボーンを対応つけます。

それではまずオブジェクトとマテリアルの分類から見てみましょう。
分類はCMQOFile::PickUpAnchor()で行います。
これが呼ばれた時点ではCModel::m_objectにメタセコイアのオブジェクトが読み込まれ
CModel::m_materialにメタセコイアの材質が読み込まれています。

このm_objectからアンカーオブジェクトをm_ancobjectに分類し、ボーンオブジェクトをm_boneobjectに分類します。
またm_materialの中のボーン関係の材質をm_ancmaterialに分類します。

やり方は簡単です。
アンカーオブジェクトにはオブジェクトの名前の先頭に「anchor」と付いています。
ボーンオブジェクトにはオブジェクトの名前の先頭に「bone」と付いています。
これらを探して拾い出していけばいいのです。

ちょっと面倒なのは
m_object, m_materialからボーンとアンカー関係の要素を削除する処理です。

例えばm_objectからアンカーの要素を削除する場合、気をつけないといけないのは
for( itrobj = m_modelptr->m_object.begin(); itrobj != m_modelptr->m_object.end(); itrobj++ ){
のループ中でitrobjを削除することは出来ないことです。
これをやるとメモリアクセス違反が発生します。

OpenRDBでは一度アンカーオブジェクトをm_ancobjectに登録し
m_ancobjectにセットされているオブジェクトを持つ要素をm_objectから検索してそれを削除するようにしています。

気をつけるのはこの部分だけです。

あとはただ拾い出して分類するだけです。



02−03、ボーンを作る

ボーンの作成はCModel::MakeBoneTri()で行います。
まずボーンの三角形を解析します。
ボーンは三角(通常のボーン)または線分(浮動ボーン)で定義されるのですが、どの頂点が親でどの頂点が子供かを確定します。
これには三角の辺の長さを判断基準にします。

三角で定義されているボーンの解析はCMQOObject::SetMikoBoneIndex3()でします。
線分で定義されているボーンの解析はCMQOObject::SetMikoBoneIndex2()でします。

三角の内、どれが親でどこが子供化が分かったら
まず親の無いトップジョイントを探します。

そしてトップジョイントから子供方向に向かって1こずつ親子関係を見つけて設定していきます。



02−04、アンカーを作り、ボーンと対応つける

CModel::MakeInfScope() でInfScope(アンカーのOpenRDBでの呼び方)を作ります。
CInfScopeはアンカーの立体1個に付き1個作ります。

まずはアンカーオブジェクトの中から同じ材質のものを探します。
その中でさらにつながっている面を探して抜き出し、立体ごとにCInfScopeに定義します。

全部のCInfScopeを作り終わったら
InfScopeとBoneの関連付けを行います。

CBone::m_isarrayにボーンごとに対応するInfScopeのポインタを格納します(1つのボーンに10個まで)。

この際、まずはアンカーとボーンの材質が一致するものを探します。
そして同じものが複数ある場合は、位置が一番近いものを選びます。

関連付けたら
それぞれのアンカーの中心位置を計算します。
(CInfScope::m_center)

次に、CBoneの同じターゲットを持つInfScopeごとにアンカーの中心と
アンカーの頂点と中心の最大距離を計算します。
(CInfScope::m_tcenter, CInfScope::m_tmaxdist)


02−05、影響度を計算する

影響度の計算は、CModel::CalcInf()で行います。

影響度の計算には現バージョンでは2種類方法があります。
1つめは
表示オブジェクト名が「表示名-影響ボーン名」のように「-」で影響ボーンが指定されている場合です。
この場合は指定されたボーンの影響を100%受けるように設定します。
この処理が
CPolyMesh3::CalcInfNoSkin()です。

もう1つの方法は
アンカーによる影響度の設定です。
この影響度の数値の設定の仕方には、こうしなさいという決まった方法はありません。
今回はナゾビーフさんと考えたオリジナルの方法を採用します。

まず頂点ごとに4つの影響度を格納できるCInfBoneというデータを作ります。
CInfBoneには最大4つのボーンの影響度が格納できるように要素数4のINFELEM構造体を持たせます。

頂点ごとにどのアンカーに入っているかを調べます。
アンカーに入っている事が分かったら、INFELEMのorginfメンバに
m_tmaxdist - 頂点とm_tcenterの距離
を格納します。
(m_tmaxdist, m_tcenterについては02−04章を参照)

そして全てのアンカーを調べ終わったら
orginfを正規化して全部の影響度の和が1.0になるようにします。
正規化後の影響度がINFELEMのdispinfで、これがボーン変形の際に使う影響度になります。


最後にアンカー立体の中に頂点が入っているかを判定する部分の説明を簡単にします。
この判定は
CPolyMesh3::CalcInfの中で行っています。

判定方法は、アンカー立体と頂点から無限遠に伸ばした半直線との交差回数が
奇数回のときは立体内部、偶数回の時は立体外部という判定をします。

CInfScope::ChkRayで半直線とアンカー面が交差しているかを調べます。
これをCInfScope::CheckInCntでアンカー全ての面に対して行い
交差回数を求めます。
そして奇数回の場合に影響度の設定をします。



オープンソースのトップに戻る

トップページに戻る