JMEにおけるBlenderの制限#3.1

前回の補足。JME(jMonkeyEngine)のAPIドキュメントを読んでいたら、Bone#addChildはユーザコードで使っていけないと書いてあった。代案を探したら、以下のトピックにまんま、おいしいコードがのっかっていた。

Topic : Giving the player a weapon

どうも、読み込んだオブジェクトからSkeletonControlというコントロールにアクセスしてそれで設定できるらしい。これを利用して前回のコードを修正した。(全体はこちら)

52: node_ = assetManager.loadModel(“dist/Models/D08_20130527.mesh.j3o”);
53: AnimControl ctrl_ = node_.getControl(AnimControl.class);
54: AnimChannel ch_ = ctrl_.createChannel();
55: rootNode.attachChild(node_);
56:
57: SkeletonControl sc_ = node_.getControl( SkeletonControl.class );
58: Node node1_ = (Node)assetManager.loadModel(“dist/Models/D08_Excalibur20130527.mesh.j3o”);
59: Node node2_ = sc_.getAttachmentsNode( “hand.equip.R” );
60: node2_.attachChild( node1_ );

これで一応、上手く動く。前回と少し違って、エクスカリバーの”main”というボーンにアクセスしていない。ためしにエクスカリバーのほうもSkeletonControlコントロールを介して”main”のボーンノードを抽出し、D君の”hand.equip.R”というボーンノードにattachChildしてみたが、エクスカリバーがD君の中心位置に表示されてしまい、上手く動かなかった。

上手く動く今回のコードがたぶん正解なのだろう。まだ理屈がよく呑み込めてないけど。

JMEにおけるBlenderの制限#3

ということで、ヨガファイアさん問題が落着したところで残りの懸案を片付ける。

まずは、Blenderで作ったShapeKey/DriversのアニメーションがJME(jMonkeyEngine)で動くかという確認。
けつろん。。。できませんでした!!!

いや、、おそらく出来ないだろうなーと思ってましたのよ。JMEのドキュメントを読んでもメッシュのアニメーションは不可で、ボーンのアニメーションのみサポートって書いてあったし。でもShapeKeyとは直接書いてなかったし、ShapeKeyのアニメーションでもボーンを使うといえば使うし、すこしは望みを残していたのですが、、。やっぱりだめでした!!!

ShapeKeyのアニメーションって便利で、Blenderでも最後の手段だと思ってたので、ぜひサポートして欲しい。どっかのトピックで開発者が熱意を持ってサポートしたいみたいに書いてたのをどこかで読んだ覚えがあるけど。

ShapeKeyはあきらめて次はBlenderのChildOf拘束をJMEでどう実現するかの検討。簡単に言えばChildOf拘束とは2つのボーン同士を親子関係に設定するというもの。前にBlenderで剣士を作ったとき、キャラクターに剣オブジェクトを持たせるのにこのChildOf拘束を利用した。(ここの動画が参考になった。)

JMEではBoneというクラスにaddChildというメソッドがあるので、Blenderで手のボーンに装備スロット的なボーンを追加し、そこに剣のボーンをJMEでaddChildすればよい。実際のコードはこんなかんじになった。

126: Spatial node_ = assetManager.loadModel(“dist/Models/D08_20130527.mesh.j3o”);
127: rootNode.attachChild(node_);
128: AnimControl ctrl_ = node_.getControl(AnimControl.class);
129: AnimChannel ch_ = ctrl_.createChannel();
130: Bone bone_ = ctrl_.getSkeleton().getBone( “hand.equip.R” );
131:
132: Spatial node1_ = assetManager.loadModel(“dist/Models/D08_Excalibur20130527.mesh.j3o”);
133: rootNode.attachChild(node1_);
134: AnimControl ctrl1_ = node1_.getControl(AnimControl.class);
135: Bone bone1_ = ctrl1_.getSkeleton().getBone( “main” );
136:
137: bone_.addChild( bone1_ );

(訂正:APIドキュメントを読み直したら、ユーザコードからBone#addChildは使うなと書いてあった。修正版はこちら)

126行目でD君のオブジェクト、132行目で聖剣エクスカリバーのオブジェクトを読み出し、AnimControlを介してボーンにアクセス、137行目で親子関係を作っている。
ちょっと怪しい動きをしているが、ひとまず期待する実行結果が得られた。

Screenshot from 2013-06-10 00^%35^%03

手抜きレンガ棒(?)じゃないよ!エクスカリバーだよ!

ちなみにBlenderで聖剣エクスカリバーを作っているときに気づいたこと。このエクスカリバーに埋め込んでいるボーンの数は一個のみである。メッシュとボーンを紐付けするときに<Ctrl-P>を押して出てくるメニューに”Armature Deform”と”Bone”という選択肢が出てくるが、”Armature Deform”の方を選択すること。”Bone”を選ぶとBlenderでは問題なく動作するが、JMEではスケルトン情報を取得できず、AnimControlのヌルポが発生する。(Ogreにエクスポートする時点で.skeleton.xmlが出力されない。)

あと、実際に作ったモデルをJMEのみで使う目的ならば、BlenderでChildOf拘束を設定しておく必要はない。でもChildOf拘束を設定しておけばポーズやアニメーションで実際の位置を確認できるので便利である。剣オブジェクトをモデリング時の初期位置に戻したければChildOf拘束のinfluenceを0に設定すればよい。

JMEにおけるBlenderの制限#2

引き続き、キャラクターの腕の太さと長さを設定できるボーン構成をJME(jMonkeyEngine)で実現する課題。(ヨガファイアさん問題と勝手に命名した)

結論から言って、Blenderで設定するStretchTo拘束が犯人だった。この拘束のあるボーンにはメッシュのウェイトを割り振っていなかったので、とくにメッシュに影響が出ると思っていなかったのだが、y軸方向のみのスケール変更をしているせいか、あちこちのボーンに影響が出て、結果、メッシュがおかしな動きをしているようだった。

まとめると、
– 腕の太さの設定はボーンの移動で行うこと。
– IKの影響下にあるボーンのスケール変更は正常に動作する。
– StretchTo拘束は使用しないこと。
となる。

この方針に従い、以下の絵のようにボーンを組んだ。Screenshot from 2013-06-08 23^%09^%51

黄色になっている細長い前腕ボーンにIKが設定されており、細長い無色の上腕ボーンがIKの影響を受ける。IKのアーム操作をしたいときは水色に選択されているボーンを動かす。

この前腕ボーン、上腕ボーンにはそれぞれ十字型に並べられた緑色のボーン4つが付属する。この十字のボーンにメッシュのウェイトが設定されており、これを動かすことで腕の太さを変えることが出来る。

前腕ボーン、上腕ボーン自体にはメッシュのウェイトが設定されていないが、ボーンをスケール変更することで親子関係にある十字ボーンが連動するので、メッシュの腕の長さを変えることが出来る。十字ボーンの数や位置は適当だが、少なくとも肘関節辺りに一つは置いておかないと、ちょっと変な動きになる。

以上、けっこう悩んだ割に、出来上がりはごくシンプルなボーン構成となった。

今回の結論に至る実験で使われたファイルはこちらにアップロードされている。
メモ書き的に各blendファイルの特徴をまとめてみた。

d01_20130527.blend、d02_20130527.blend、d03_20130527.blend
基本的な機能を確認したファイル。これでJMEのスケール変更に関する問題が見つかった。

d04_20130527.blend
ボーンの移動でスケール変更するようにしたもの。上手く動かなかった。

d05_20130527.blend
d04_20130527.blendをベースに、IK拘束とStretchTo拘束を削除したもの。狙った動きになったはなったが、IKを削除したことで、少々操作しにくくなっている。

d06_20130527.blend
d04_20130527.blendをベースに、StretchTo拘束のみを削除したもの。狙った動きになり、IK操作で操作しやすい。

JMEにおけるBlenderの制限

先日、Blenderで作ったモデル、D君でいろいろ実験している。
とりあえず、JME(jMonkeyEngine)でD君を表示できるようになったが、その次がアニメーションだ。
いろいろ試した結果、以下のことが分かった。

(1)組んだモデルをコマンドラインでOgreにエクスポートするとき、Blenderでの編集完了時は必ずObjectModeにして対象のメッシュとボーンを選択して終了すること。それをしないとJMEでテクスチャ読み込みとスケルトン読み込みに失敗する。
(2)BlenderのActionEditorで組んだアニメーションはNLAEditorで登録しておかないと、JMEから参照することが出来ない。
(3)異なるメッシュからテクスチャファイルの共有は出来ない。
(4)IKのボーン拘束は使えるようだ。今のところ違和感はない。
(5)meshのOriginは一番下の位置に設定すること。Armatureは完全な木構造にし、rootのボーン(親を設定しないボーン)は2つ以上あってはならない。rootのボーンはmeshのoriginと同様に一番下の位置に設定すること。(公式ドキュメントより。)
(6)ボーンのスケール変更はx,y,z軸、3方向にすべて等倍変更のみ出来る。StretchToやScaleLimitによるx方向のみ拡大とかそういうのは出来ない。

この中で(6)が特に問題だ。これによって、のヨガファイアさん問題で苦労して組んだボーンがJMEでは動かなくなってしまうからだ。キャラクターの腕の太さと長さを個別に設定できるというボーン構成なのだが。

対策として、ボーンのスケール変更でメッシュを直接スケール変更せず、ボーンの移動によってメッシュのスケール変更できるようにBlenderで組んでみたが、BlenderとJMEで明らかに動きが違う、、。
もうちょっと工夫が必要なのかもしれない。

まだやっていない確認リスト、おぼえがき。
– ShapeKey/Driverによるアニメーションは利用できるか。
– ChildOf拘束を利用するには

blendからOgreをコマンドラインで変換

まさか出来ると思ってなかったので、出来るのを知ったらちょっと感動しちゃったよ。

以下のBlender公式Wikiを参考にして、BlenderのblendファイルからOgre形式のエクスポートをコマンドラインでできるようになりました。
Wavefront OBJ Import/Export

blend2ogre.pyという、こんな感じ(最新版)のpythonファイルを作って、以下のようにタイプすればよい。

blender foobar.blend –background –python blend2ogre.py — foobar.mesh.xml

pythonなんて初めて組んだよ!まあ、ほとんどコピペだけど。
細かいパラメータを指定した方がいいのかもしれないなー。そのへんはoioi。

なお、この操作は、先日のプラグインblender2ogreがBlenderにインストールされていることが前提になる。
http://code.google.com/p/blender2ogre/

これでblendからOgreに変換でき、Ogreからj3oに変換できるようになったので、blendからj3oの変換が完全にコマンドラインで出来るようになった!うれぴ~~。

 

Ogreからj3oをコマンドラインで変換 #2

結局、Javaソースはこんなかんじ(最新版)で落ち着いた。

FileLocatorからClasspathLocatorに置き換えると前に書いたが、なんかよく分からないからやめた。registerLocatorは二重に定義することが出来てびっくり。そしてそれができないと今回の目的は達成できなかった。

Javaプログラムのコマンドライン引数は2つから3つに増え、かなりウザイことになっているが、そこはシェルスクリプトでカバーしている。

で、今回からいろいろシェルスクリプトを追加した。

(シェル1) devutil20130602/mesh2j3o.sh
今回作ったJavaプログラムを呼び出すスクリプト。引数は入力ファイルと出力ファイルの2つが必要。

(シェル2) jme3/setup.sh
jMonkeyEngineの本家からsvnでソースコードをダウンロード、jarとjavadocを生成する。(シェル1)で必要とするリソースもこれで取得する。

(シェル3)devenv.sh
コンパイルや実行時に必要な環境変数をセットしている。開発するときはいつも必ず”source devenv.sh”でこのシェルスクリプトを呼び出しておくこと。(“sh devenv.sh”ではない)

シェルが使えるというのが、OSにLinuxを選んだ大きな理由だ。makefileも好き。antとかもあるけど、makefileが一番手軽でいいね。最近のWindowsでもコマンドライン環境は拡充してきているみたいだが、Linuxにはまだまだ適わないだろう。
ちなみに、一時期Windowsで動くUnix、Cygwinを試したことがあるけど、あれは結局どっちつかずで自分はダメだったなあ。Cygwinで動かすソフト自体がCygwinであることを想定してない場合が多いから、いろいろお手当てが必要で非常にめんどくさい。(Cygwinでandroid開発しようとして挫折した。)
Cygwinを使うんだったら、VMWarePlayerにLinuxをインストールして使ったほうが良い。

Ogreからj3oをコマンドラインで変換

ようやく、先日Blenderで作ったD君にテクスチャをくっつけて、JME(jMonkeyEngine)で表示できるようになったよ!

D君を表示するには、BlenderでエクスポートしたOgreXML形式のファイルをさらにJMEでj3o形式に変換して利用する。これはJMEのIDE上でOgreXMLのファイルをクリックして変換すれば簡単に出来ることなのだが、個人的にはこのクリックして変換する手動的な行為が気に食わない。

OgreXMLからj3oの変換がコマンドライン上で自動的に出来るようにならないか調べた。調べたら、「そんな方法はねえ!でもライブラリで公開してるから自分で作れ!」と公式で言ってた。
Topic: .blend to .j3o via java -jar command???
Asset Handling For Other IDEs: Codeless Projects

ここのリンク先のように BinaryExporter を駆使して作ればいいのだそうな。
Saving and Loading Games (.j3o)

なのでこんな感じで作ってみた。

public class JmeExporter {
public static void main( String[] args_ ) throws Exception{
if( args_.length < 2 ){
return;
}
DesktopAssetManager ass_ = new DesktopAssetManager();
ass_.registerLoader( MeshLoader.class, “mesh.xml” );
ass_.registerLoader( MaterialLoader.class, “material” );
ass_.registerLoader( SkeletonLoader.class, “skeleton.xml” );
ass_.registerLoader( AWTLoader.class, “png” );
ass_.registerLoader( J3MLoader.class, “j3md” );
ass_.registerLocator( “.”, FileLocator.class );
Spatial data_ = ass_.loadModel(args_[0]);
File f_ = new File( args_[1] );
BinaryExporter exp_ = BinaryExporter.getInstance();
exp_.save( data_, f_ );
}
}

AssetManagerのregisterLoader指定が曲者だった。あと、JMEのSDKインストールディレクトリ配下にあるjME-core.jar内のCommonディレクトリ下のリソースも必要になるので、registerLocaterでFileLocatorを指定していると、その位置にリソースのCommonディレクトリを展開してコピーしておかなければならない。
これはさすがに不便なので、ClasspathLocatorあたりに置き換えるつもりである。

他、jME3-plugins.jarとjME3-desktop.jarがコンパイル&実行に必要。

もうちょっとコードを精錬させたらgitの方にアップします。

JMEにおけるマテリアルの制限

ドキュメントを読んでたらそんな気はしてたけど、実際JME(jMonkeyEngine)のIDEを動かして確認してみたらやっぱりそうだった。JMEではオブジェクト一つにつきマテリアルは一個まで!
がーん、いままでBlenderで作ったモデルは思いっきり多種なマテリアルを使って色分けしてたので、直さなきゃいかんなー。

ここを読んでみても、開発者にはその方針を変える気はないようだ。
http://hub.jmonkeyengine.org/forum/topic/different-materials-for-one-object/

OgreXMLでもオブジェクト一つに多種マテリアルは持てるようにしてあるし、出来たらサポートして欲しいけど、仕方ない。JMEではテクスチャ主体でいくことになりそうだ。

 

ミスターOgre

いや、オーガさんですけど。

現在もJME(jMonkeyEngine)のドキュメントを読んでいるところではあるが、その中で一番気になるのは、やはりBlenderのファイルを読み込む機能だ。これが出来なければ、何も始まらない。

ここらへんを読んでいると、予想してはいたけど、JMEで読むためにはBlenderの編集でそれなりの制約があるようだ。
http://jmonkeyengine.org/wiki/doku.php/jme3:external:blender

まず、JMEではBlenderがまんま出力するblendファイルを読むことは出来ない。BlenderでOgreXML形式でエクスポートし、JMEでさらに最適化された専用のファイルに変換しなければならない。

(訂正。どうもblendファイルのまま読み込めるクラスが用意されているようだ。あと、OgreXML形式のまま読み込むこともできる。)

OgreXMLにエクスポートするBlenderのアドオンはとりあえず、blender2ogreというのを入れてみた。
http://code.google.com/p/blender2ogre/

このアドオンを利用するにはogreのコマンドラインツールをインストールしておく必要がある。(Ubuntuではsudo apt-get install ogre-tools で可能)

まだあまり検証してないけど。明日はテスト用に作ったモデルを使っていろいろ検証するぞ。

Screenshot from 2013-05-29 00:05:58
これがテスト用モデル。どーも、ども。

 

 

JME3でアプレット(メモ)

たまたま見つけたJME3(jMonkeyEngine3)でアプレットする方法。後で役に立つかな?
http://www.streamhead.com/tutorial-jmonkeyengine-applet-hardware-3d-in-the-browser/

ついでにAndroid。まだやる気はないけど、いずれか。
http://jmonkeyengine.org/wiki/doku.php/jme3:android

それにしても、JMEの公式チュートリアルは本当に良い。英語だけど、すごい親切。まだHelloWorld系をコピペして動作確認してる程度だけど、なんだかほんとうに作れる気になってきたぞ!