Intel PerC ライブラリが認識した指先位置にオブジェクトをリアルタイムで配置するようにしてみました。
これを初期位置に手の姿勢推定を頑張っていこうと思います。
Bullet Physics のスケールに合わせて何もかも 10 倍しましたから。
対象とする手のモデルも 10 倍してそのデータにフィットするように作らなければなりません。
フィットするように調整してみました。
そのままだと人指と親指が長すぎたので調整、だいたいフィットするような大きさであることを確認しました。
このモデルを大きさの基準として利用します。
本当はここから手のオブジェクトを作成し、Kimberlite2 で関節を作りながら試行錯誤するのですが
Blender の中でオブジェクトを作り、関節のコンストレイントまで設定出来た方が良いなとずっと考えてきました。
調査し始めた時期が今から2年と2ヶ月前の058話のころで、当時モデルデータのファイルフォーマットを考えていました。
結局 Blender 2.69 の現在も Collision モディファイアを適用して RigidBody を設定しても Physics データは Collada に出力されません。
そこで緊急でほしい今現在、名前解決を入れてみようという発想に至ったわけです。
名前解決とは?
IT 用語だとコンピュータやネットワーク機器につけられた名前からアドレスを割り出すこと、なのですが
今回はシーンにおける役割を名前から割り出すことの意味で使ってみようと思います。
つまりあるオブジェクト名に自分はコンストレイントである、コンストレイントタイプは何で
軸はどこを向き、何と何を結びつけるコンストレイントである。
とこんな感じの情報を名前に設定します。
オブジェクト名の限界長は Blender では 63 文字までです。
それなりに名前解決用のルールを短めに設定する必要があります。
オブジェクトの情報も利用できると良いです。
コンストレントならば、姿勢行列から軸の方向を決定するなどですね。
では現在はどのようにして物理オブジェクトを生成しているのか見て行きましょう。
ちょうど2年前になりますが064話にて、メッシュの中心と
バウンディングボックスの形でシェイプを作成、これに付随する形で生成元のメッシュを描画する仕組みを作りました。
ちょっと実装メモを
Collada ファイルは、もちろん Blender から書き出す or FBX からコンバートするで得られます。
それを Kimberlite2 に読み込ませると、まず ColladaToBinary で ColladaBinary に変換します。
もう、この時点で ColladaBinary をファイル出力するんですね。
まず KimberliteScene は ColladaBinary のSceneDataの集合として構成されます。
描画はSceneDataの下にぶら下がるNodeを階層的に見ていき、DrawNodeとノードの描画を行なう。
ノードはSceneDataを特定するSceneIndex, ノードを特定するNodeIndexによって特定される。
Node は Blender でいうところのオブジェクトと等価である。
で、ColladaBinary を Kimberlite2 で読み込んだ時にのみ、このオブジェクトに対して物理オブジェクトを生成します。
Kimberlite ファイルを読み込んだ時は物理オブジェクトの自動生成は行わず、すでに Kimberlite の中に書き込まれている
物理オブジェクトとコンストレイントの情報を復元します。
あの、途中ですみませんが、息抜きでチェスやっていたらポーンだけでキングを裸にできたので…
キング自ら敵のキングに歩み寄る。
相手に拒否権はない。
はい、ほんとすみません話を戻します。
なので、ColladaBinary を読み込んで物理オブジェクトを生成する過程にて名前解決を行なうことになります。
で、物理オブジェクトの自動生成コードを確認していますが、よくこんなの調べたなぁと思う所あり。
一件不具合を確認、オブジェクトのPivotがバウンディングボックスの中心にない場合に
物理オブジェクトに付随するモデルの位置が、その中心からずれた量だけ移動しています。
バウンディングボックスの中心からの差分は OffsetCenter としてファイルに保存しているので
これを描画時のオフセット行列にかけておきます。→これで解決しました。
さて、ColladaToBianry のテクスチャ変換にて不具合発見、どうも今まで PDNBulkUpdaterCmd.exe を使っていたのですが
PDN のバージョンが v4.0.3 に上がってしまったせいで、うまく動かなくなってしまいました。
これを別の画像コンバータに変更し、正しく動作することを確認しました。
では、まずコンストレイントであることを証明する名前規則を決めます。
Constraint-?-ObjectA-ObjectB-NodeNameとして - でセパレートした時に5つに別れることが条件
先頭が Constraint であること ? が有効なコンストレイントタイプであることが条件です。
すると、オブジェクトA, B を結ぶコンストレイントが出来るというものなのですが
実際に出来るか試してみます。
テストデータを用意しました。
さて、今は何もしていないのでこんな事になります。
ここで、ColladaBinary を読み込んだ後に行なう物理オブジェクト構築にて名前解決を行うと…
実装メモ
ちょっと恐る恐る実装している感じですが、単にオブジェクト追加をスキップすると
こうなります。
さて、オブジェクトにはシーンで一意の名前がランダムで割り当てられています。
この情報を使ってオブジェクトを割り出し、コンストレイントは連結情報を復元しています。
連結用のオブジェクト名が名前解決によってわかりますが、ここから一意のランダムなオブジェクト名がわかるのでしょうか?
答えはYES そもそもノードの情報からオブジェクトを作成していますので、この時に関連付けを行っておけばよいのです。
まず関連付けを行います。
そしていざコンストレイントを追加する時に必要な情報は、連結するオブジェクトA, B と、位置関係を示す行列2つです。
かなり難しくなってきたので一回トライさせてください。
Constraitn のタイプを Point2Point にして、適当な位置でコンストレイントを追加します。
よし、位置がズレてはいますがコンストレイントが作れているみたいですね。
正しい位置にコンストレイントが作られるように調整してみます。
調整しました。
今度はコンストレイントのタイプを変えてみます。
Hinge, ConeTwist で試してみます。
今度は問題なく一発で正しい位置にコンストレイントが作成されました。
残りのD6, D6Spring についても調べてみます。
問題ありません。
ついでなので、シェイプの結合も名前規則で解決できるようにして
それなりに複雑な形状を生成出来るようにしたいと思います。
Compound-ParentObject-NodeName
こんな名前規則でどうでしょうか。
規則を見つけたらオブジェクトは作成するが、作成後に親オブジェクトに対して
Compoundの子供にして下さいとお願いするのです。
子供も一つではなく複数可能とします。
親指定ごとにCompoundしますが、孫まで作る場合について困ることが出てきます。
親がすでに祖先に組み込まれてしまった場合、親が見つかりません。
この時は親の名前で祖先が取得できるように動作を考慮します。
結果はどうなるでしょうか?
いや、手を動かす前に調べなくては
過去に CompoundShape 作成のコードを書いていました。
必要なのは親オブジェクトと複数の子オブジェクトのようです。
最初にオブジェクトをワールドに追加している最中に
Compound の子を願うオブジェクトを見つけた場合は、無視し
コンストレイントを追加する時に、親オブジェクトと子オブジェクトリストを構築します。
最後にこれらの情報から、Compoundオブジェクトを作成しようと思います。
いや、Compoundオブジェクトを作成した後にコンストレイントを作成することにしようと思います。
ひとまず Compound オブジェクトが自動生成されることを確認できました。
テスト用に少し複雑なオブジェクトを用意したいと思います。
Blender でこのようなモデルを作成し、名前解決でタイヤ以外の部位をCompoundしてみます。
できました。
では、結合されたオブジェクトに対してコンストレイントを設定できるか試してみます。
できました。
ヒンジで繋いだので、タイヤが軸回転します。
不満点があるのが、コンストレイントの軸方向です。
後から編集して正しい軸方向に直しましたが、最初から指定できるとうれしい。
コンストレイントの元となっているオブジェクトの姿勢からこうしたコンストレイントの姿勢、軸方向を
設定できるようにしたいと思います。
で、どうすれば良いのか?
ヒンジコンストレイントに関しては SetAxis で、オブジェクトの姿勢行列の
X軸に合わせる、という方法で解決しました。
他のコンストレイントについても同じようなことをしたいと思います。
同じようなことしました。
Point2Point, Hinge, ConeTwist, D6, D6Spring について
コンストレイントの元となるオブジェクトの姿勢に依存して、コンストレイントの姿勢が決まるようになることを確認しました。
あとひとつ、シェイプについても名前解決したいと思います。
現在まで、最初のシェイプはすべて BOX にしています。
これをオブジェクトの名前から求めたいと思います。
Blender のメッシュ追加時に勝手にリネームされますのでこれを使ってみたいと思います。
例えば Cube → Box, Cylinder → Cylinder といった具合です。
できました。
Cube, Cone, Capsule, Sphere, Cylinder, Plane, Icosphere がそれぞれのシェイプで置き換わることを確認しました。
Plane だけおかしいのでデバッグします。
なるほど、シェイプパラメータを使って法線とオフセットを決めていたためでした。
こちらをノード姿勢の Up を法線にし、位置の Z をオフセットに…
だめでした、単に Yup, オフセット 0 にすることで解決しました。
Blender で次のように四面を設置して試します。
これを Collada で書き出して、Kimberlite2 で読み込むと
うまく結界が張れたようです。
ちゃんとオブジェクトを結界内にとどめておけるかテストします。
うまくいきました。
名前解決で行いたいことの大部分が片付きました。
まだあるのですが、今回はこの辺で話を切りたいと思います。
かなり Blender 側で調整できるようになってきました。(楽だな)
次回をお楽しみに!
2014/09/05 初記。
2014/09/13 更新。