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

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

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

$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);
}
}