「ボーンを指定して動かす」というのをやってみようと思ったのですが、いくら探してもボーンを指定するクラスというのが見つかりませんでした。

その代わりと言っては何ですが、「フレームを指定してアニメーション再生する」という方法がみつかりました。

参考ページ
http://www.kyucon.com/blog/archives/000440.html

で、作ってみたのが以下です。(画像をクリックしてみてください)

$Flash 3D 試行錯誤-アザラシ?


このキャラは、「ゆるキャラ」もしくは「アザラシになるはずだった何か」ということにしておいてください。

左のボタンを押すと、キャラが動作を変えます。

これは、
0-15 宙返り
30-60 お辞儀
60-90 困った顔
120-150 歩く
というようにフレーム設定をしたものを、

var anim1:AnimationClip3D = new AnimationClip3D("somersault", 0, 0.5);
var anim2:AnimationClip3D = new AnimationClip3D("bow", 1, 2);
var anim3:AnimationClip3D = new AnimationClip3D("komatta", 2, 3);
var anim4:AnimationClip3D = new AnimationClip3D("dash", 4, 5);

というようにクリップ設定し、そのクリップを、

dae.animation.addClip(anim1);
dae.animation.addClip(anim2);
dae.animation.addClip(anim3);
dae.animation.addClip(anim4);

というようにDAEインスタンスに追加しています。

あとは、それぞれのボタンに

switch(e.currentTarget) {
case btn_1:
dae.play("somersault", true); //アニメ名, ループの有無
break;


}

という感じでスタート設定しています。

DAEにクリップ追加する場合は変数で追加し、dae.playで呼び出すときはアニメーション名で呼び出す形いなるわけですね。

あと、開始と終了は秒単位で時間設定します。今回は30fpsで作っているので、それぞれのフレームを30で割った数値で開始・終了を記述します。

なので、小数になるにしても、30できれいに割れるフレーム数で作れると良いですね。

とりあえずこれができればかなりのアニメ制御ができますね。
COLLADAオブジェクトで、ある場所をクリックするとそこが動き、別な場所をクリックでそこが動く、というような挙動をテストしてみました。(画像をクリックしてください)

テスト用オブジェクトはイスに変えました。
イスの、シートから上をクリックすると、そこだけが一回転し、足の部分をクリックでそこだけ一回転します。

テクスチャがうまく出ないときもたまにありますので、リロードしてください。

$Flash 3D 試行錯誤-イス


で、やり方なのですが、本当は、一つのオブジェクトでメッシュノードの名称でクリックできるようにしたかったのですが、LightWaveでノードをどうやって設定するかが分かりませんでした。

別オブジェクトにして.x→UnwrapでDAEに、という方法も試したのですが、Unwrapnに読み込んだ時点で一つのメッシュノードになっちゃってるみたいです。

てことで、試行錯誤の後にあきらめました。

で、上のサンプルは、シートから上の部分と足の部分で別なDAEにしてそれぞれ読み込んでいます。
クリックやアニメーションもそれぞれに設定してあります。

まあ、仕方ないですが、これでもほとんどのことには対応できそうです。

ソースは、ほんとにベタに2つ分書き足しただけなので、ここにコピーするほどでもありません。

で、次回は、「ボーン名を指定して動きかしてみる」てのを調べようかと思っています。
例えば、あるボタンをクリックすると、オブジェクトのある場所が動き、しかも押すボタンによって動き方が変わる、みたいなイメージです。

でも、あんまりボーンばっかりにこだわっているのも何なので、うまくいかないようならそろそろ別なことを調べてみようと思います。

物理シミュレーションとか。。。まだ面白いものがたくさんありそうですし。



前回の予告通り、オブジェクトをクリックしてのアニメーション制御をテストしました。

やってみたらけっこう大変でした;

まずは完成したものを見てください。(画像をクリックしてください)

$Flash 3D 試行錯誤-クリックで制御


さて、何が大変だったかといいますと、オブジェクトのマウスイベントを設定するのがえらく面倒でした。いや、正確には「COLLADAオブジェクトの」ですね。

といいますのも、スクリプトで作成したプリムなどのオブジェクトのマウスイベント設定はそれほど大変じゃないんです。

【スクリプトで作成したオブジェクトのマウスイベント設定】

1, BasicViewのインタラクティブ設定をtrueにする。

 //superメソッドのBasicViewのインタラクティブ(4番目)をtrueに
  super(0, 0, true, true);

2,マテリアルのインタラクティブ設定をtrueにする。

  mat1.interactive = true;

3, オブジェクトにマウスイベントを登録

オブジェクト名.addEventListener(InteractiveScene3DEvent.OBJECT_OVER, オンマウス時の指示(関数));
オブジェクト名.addEventListener(InteractiveScene3DEvent.OBJECT_OUT, マウスが離れた際指示(関数));
オブジェクト名.addEventListener(InteractiveScene3DEvent.OBJECT_CLICK, クリック時の指示(関数));
 
4, viewportのボタンモードをtrueにする。

viewport.buttonMode = true;

くらいで大丈夫と思います。

ところが、COLLADAオブジェクトの場合はそうはいきません。
上の同じ設定してもなかなかうまくかず、かなり試行錯誤を繰り返しました。

その間、以下のブログを参考にさせていただきました。

Note.x
web3D
osbo.com

引用になってしまいますが、DAEファイルというのは純粋なメッシュファイルではなく、本来はライトやカメラも包含できるシーンファイルのようなものなのだそうです。

てことで、メッシュに対していろいろ設定していくには、ノード(メッシュ)を指定してイベントを登録するための手続きが必要なのでした。

【COLLADAのノード(メッシュ)を指定してイベント登録】

5, コンストラクタ関数内では、DAEにロード完了後のイベントを登録して閉じる。

scene.addChild(dae);
dae.addEventListener(FileLoadEvent.LOAD_COMPLETE, handleLoadComplete);
}(閉じる)

6, 5で登録したイベント(handleLoadComplete)の中で、daeのノードにイベントを登録

private function handleLoadComplete(e:FileLoadEvent):void {
// DAEの子であるノードを指定
var dae_rootNode:DisplayObject3D = dae.getChildByName("COLLADA_Scene");
var targetMesh:DisplayObject3D = dae_rootNode.getChildByName("meshU3D");
//ノードにマウスイベントを登録
targetMesh.addEventListener(InteractiveScene3DEvent.OBJECT_OVER, mouseOverHandler);
targetMesh.addEventListener(InteractiveScene3DEvent.OBJECT_OUT, mouseOutHandler);
targetMesh.addEventListener(InteractiveScene3DEvent.OBJECT_CLICK, clickHandler);

後略

}

DAEのルートである"COLLADA_Scene"の子である"meshU3D"を呼び出したわけです。
"COLLADA_Scene"というのは、どんなDAEでも共通の名称のようです。"meshU3D"というのは、私のオブジェクトのノード名です。

ノードの名称を調べる方法ですが、プレビューをしたら出力画面に

INFO: DisplayObject3D: COLLADA_Scene
INFO: DisplayObject3D: Frame_SCENE_ROOT
INFO: DisplayObject3D: Frame1_PC_bone_Layer1
INFO: DisplayObject3D: Frame2_down
INFO: DisplayObject3D: Frame3_up
INFO: DisplayObject3D: meshU3D

というように、いろいろ出てきました。
ちなみに、私のLWデータでは、特にノード設定につながりそうなことは何もしていません。ポリゴンセットとかも反映されないみたいです。

名前的に、おそらく一番下かな、と思って入れてみただけです。
他は、名称からして違いそうでしたし。

で、うまくいったとさ、というわけでした。

せっかくなので最後にソースコピーしときます。

あと、次回ですが、せっかくここまでやったので、LWからUnwrap経由のCOLLADAで、部分的にメッシュを動かす方法を試してみようと思います。

たとえば、車のドアをクリックしてドアが開く、ボンネットをクリックしてそこが開く、みたいなやつですね。

問題は、ノード(メッシュ)をどうやって分けるか、なんです。

LWで作るときに、単純に別オブジェクト(別レイヤー)に分けて作成する方法もあるかな?と想像していますが。それだと、根本的な解決じゃないですね。

また試行錯誤してみます。


==================================================

public class pc_touch extends BasicView {
private var rot:Number = 0;
private var rot2:Number = 0;
private var dae:DAE; //ここで宣言しておく
public function pc_touch():void {
//BasicViewのインタラクティブ(4番目)をtrueに
super(0, 0, true, true);
var mat1:BitmapAssetMaterial = new BitmapAssetMaterial("pc",true);
mat1.interactive = true;
var materials:MaterialsList = new MaterialsList({
all: mat1
} );
// Colladaファイルの読み込み
dae = new DAE();
dae.load("collada/pc_bone_120_3.dae",materials);
// Colladaのスケールや位置を調整
dae.scale = 500;
dae.y = 0;
dae.rotationY=180;
scene.addChild(dae);
dae.addEventListener(FileLoadEvent.LOAD_COMPLETE, handleLoadComplete);
}
//daeに仕込んだイベントの関数
private function handleLoadComplete(e:FileLoadEvent):void {
// DAEの子であるノードを指定
var dae_rootNode:DisplayObject3D = dae.getChildByName("COLLADA_Scene");
var targetMesh:DisplayObject3D = dae_rootNode.getChildByName("meshU3D");
targetMesh.addEventListener(InteractiveScene3DEvent.OBJECT_OVER, mouseOverHandler);
targetMesh.addEventListener(InteractiveScene3DEvent.OBJECT_OUT, mouseOutHandler);
targetMesh.addEventListener(InteractiveScene3DEvent.OBJECT_CLICK, clickHandler);
// 押すまでアニメを始めない
dae.stop();
// レンダリング
renderer = new QuadrantRenderEngine();
startRendering();
addEventListener(Event.ENTER_FRAME, loop);
}
private function mouseOverHandler(e:InteractiveScene3DEvent):void {
// 指カーソルに変えるにはViewportのbuttonModeをtrueに設定する
viewport.buttonMode = true;
}
private function mouseOutHandler(e:InteractiveScene3DEvent):void {
// 指カーソルの解除
viewport.buttonMode = false;
}
private function clickHandler(e:InteractiveScene3DEvent):void {
//falseで一回だけの再生に
dae.play("",false);
}
private function loop(e:Event):void {
var targetRot:Number = (mouseX / stage.stageWidth)*360;
var targetRotY:Number = (mouseY / stage.stageHeight)*360;
rot += (targetRot-rot)*0.1;
rot2 -= (targetRotY+rot2)*0.1;
camera.x = 200 * Math.sin(rot*Math.PI/180);
camera.z = 200 * Math.cos(rot*Math.PI/180);
camera.y = 200 * Math.sin(rot2*Math.PI/180);
}
}
さて、Unwrapのライセンスコードが届きましたので、さっそくUltimate Unwrap2.0をインストール、さらに、COLLADAで書き出すためのプラグインをインストールしました。

いろいろと機能はありそうなのですが、とりあえずDirectXからCOLLADAに書き出すためにだけ使うので、細かい使用方法はスルーしちゃいます。

復習しますと、
LWからアニメ付きでDirectX書き出し(.x)→ Ultimate Unwrapで読み込み、COLLADA書き出し(.dae)→ Paperviewで読み込み
という手順ですね。


で、結論からいいますと、以下のようにうまく書き出せました。(画像をクリックしてください)

$Flash 3D 試行錯誤-Unwrapから書き出し


ただ、ここまでには少し紆余曲折がありました。

まず、ちょっと不用意だったのが、PCにボーンを仕込む時に使ったスケルゴンをオブジェクとから削除するのを忘れてしまっていたこと。これを忘れると、DirectXエクスポートでエラーが出てしまいます。

次に、Yellow Soupさんのブログにもあるように、画像のパスがうまくいかない、という症状が出ました。

で、あれこれやったのですが、なかなかうまくいかないため、スクリプトで画像を設定するようにしました。前々回の投稿で書いたように、BitmapAssetMaterialでサーフェイスに割り当てる方法ですね。

ただ、LWから書き出したCOLLADAの場合は、LWのサーフェイス名にマテリアル設定すれば良かったのですが、今回のUnwrapで書き出したCOLLADAの場合はうまくいきませんでした。

で、そのCOLLADAを調べたところ、JPGテクスチャを指定しているらしいソース記述が以下のようになっていました。

<library_materials>
<material id="VisualMaterial1" name="Unassigned">
<instance_effect url="#Effect"/>
</material>
<material id="VisualMaterial2" name="NoNameMat0">
<instance_effect url="#Effect1"/>
</material>
<material id="VisualMaterial" name="pc.jpg">
<instance_effect url="#Effect2"/>
</material>
</library_materials>

で、この行の中のid="VisualMaterial"をマテリアル名と考えればよいのかなと思い、AS内で以下のように設定しましたところ、うまくいきました。

//画像マテリアルを作成
var mat1:BitmapAssetMaterial = new BitmapAssetMaterial("pc",true);
//VisualMaterialというマテリアル名に、上で作った画像マテリアルを割り当て
var materials:MaterialsList = new MaterialsList(
{
VisualMaterial: mat1
} );
// Colladaファイルの読み込み
var dae:DAE = new DAE();
dae.load("collada/pc_bone_120.dae",materials);
scene.addChild(dae);


もしかしたら、ファイル変換のどこかで設定がおかしかったのかもしれません。

まぁ、このように読み込んでおけば、マテリアルに画像以外の設定も加えやすいので、これはこれでとりあえずいいかな。

てことで、Unwrapを使ってのアニメ付き3Dオブジェクト読み込みでした。

次回は、せっかくなので、ククリックしたらアニメーションが始まる、みたいな、マウスでのアニメ制御について調べてみようと思います。
さて、LightWaveからボーンアニメーション付きのデータをCOLLADA書き出しし、Papervisionで動くかどうか、のテストをしてみました。

すでにいろんな方のブログを読んで、これは無理らしいと知っていたのですが、どんな症状になるのか試してみました。

先の投稿の時に使ったPCのオブジェクトにボーンを仕込みました。そして、閉じた状態から開き、さらにまた閉じる、という、ボーン2本のいたってシンプルなアニメーションをつけてみました。

サイズが異様に小さく出る、などの症状が出ましたが、それはサイズで調整しました。

その結果が以下です。(画像をクリックしてください)

$Flash 3D 試行錯誤-ボーンアニメ付きPC

ご覧のように、つぶれちゃってます。テクスチャもなんだか変です。一応、アニメーションらしき動きは出ているのですが、これではどうしようもないですね。

てことで、アニメ付きでCOLLADA書き出しできる(無料の)ツールがないか調べたのですが、良いのが見つかりませんでした。Poserで、てのも考えましたが、LWからPoserにオブジェクトとアニメを移行する方法を覚えるまで結構手間と時間がかかりそうなのでやめました。

で、結局、Yellow Soupさんの方法を参考に、Unwrapを使うことにしました。

Swift3Dも考えましたが、どうもアニメも含めての移行ってのができなさそうなのでパスしました。

Ultimate Unwrap 3Dのライセンスキーが来るまでちょっと待ちです。