いろいろ調査
Matrix3D.asの中を見ていたら、クォータニオンの記述を発見。専用クラスがあるわけではなく、Objectとして渡してどうこうするらしい。
WiiFlashのsensorXなどの値を表示してみた。軸の方向が思っていたのとは違ったが、値に関してはほぼ想定どおり(基本状態のベクトルの長さが1。振ったりすると長さが4になったりする)。ただ、値がちょっとおおざっぱすぎる。少しずつ傾きを変えても、そこそこ大き目の値で変化していく(変化するまではずっと同じ値)。値にして0.038ほど、角度にして約2.28度ほどのデジタルな値で増減している。360度/128=2.8125なので、1バイトで管理しているんだろうか。細かい傾きを使ったものは、これではつらいかもしれない。
と思ったけど、箱の動きとリンクさせてみると問題ない感じ。これ以上の細かさはなくて良いのかもしれない。
WiiFlash + PV3Dのテスト
Wiiリモコンの傾きにあわせて動く箱の作成テスト。ついでにテクスチャを張るテストも兼ねる。
とりあえず上手く動いてはいるものの、自分の考えている軸と箱の幅のパラメータが一致していない。そこはあとで調べる。
動かすには、
- WiiリモコンをPCに接続
- WiiFlashのサーバを動かしておく
- 同じフォルダに「hoge.jpg」という画像を用意
- 「mxmlc wiimotedemo.as」でコンパイル
- できたswfをブラウザに入れて実行
実験コードがそのままコメントとかに入っているので多少汚い。が、疲れたので今日はここまで。上の件を調べた後に綺麗にしよう。
//wiimotedemo.as package{ //label import flash.display.*; import flash.text.*; import flash.events.*; import flash.ui.*; import flash.utils.*; //PV3D import org.papervision3d.core.*; import org.papervision3d.core.proto.*; import org.papervision3d.scenes.*; import org.papervision3d.objects.*; import org.papervision3d.cameras.*; import org.papervision3d.materials.*; import mx.core.BitmapAsset;//Material //WiiFlash import org.wiiflash.Wiimote; import org.wiiflash.events.ButtonEvent; //Class public class wiimotedemo extends Sprite { //Reources [Embed(source="hoge.jpg")] private var ImageHoge:Class; //WiiFlash private var wiimote:Wiimote = new Wiimote(); //PV3D private var container : Sprite; private var scene : Scene3D; private var camera : Camera3D; private var rootNode : DisplayObject3D; private var obj:Array = new Array(); //Label private var label:TextField; //Constructor public function wiimotedemo():void { //Init Common { //リサイズ対応 stage.addEventListener(Event.RESIZE, onStageResize); //毎フレーム呼ばせる関数の登録 addEventListener(Event.ENTER_FRAME, myLoopEvent); } //Init WiiFlash { //サーバに接続したときのリスナ wiimote.addEventListener(Event.CONNECT, handleConnect); //Aボタンが押されたときのリスナ wiimote.addEventListener(ButtonEvent.A_PRESS, handleAPress); //接続開始 wiimote.connect(); } //Init PV3D { //表示用のSpriteオブジェクトを生成 container = new Sprite(); container.x = 400 / 2; // at center : swf width = 400 container.y = 400 / 2; // at center : swf height = 400 addChild(container); //シーンオブジェクトを作成 scene = new Scene3D(container); //カメラオブジェクトを作成 camera = new Camera3D(); camera.z = -200; camera.focus = 500; camera.zoom = 1; //ルートノードを作成 rootNode = new DisplayObject3D(); scene.addChild(rootNode); //オブジェクトの作成 obj.push(createCube()); //オブジェクトをルートノードに追加 for(var i:int; i<obj.length; i++){ rootNode.addChild(obj[i]); } } //Init Debug Label { //デバッグ表示用のラベルの作成 label = makeLabel(""); addChild(label); } } //=WiiFlash= //WiiFlash Serverに接続したときのリスナ private function handleConnect(e:Event):void { trace("Connect"); } //WiiリモコンのAボタンが押されたときのリスナ private function handleAPress(e:Event):void { trace("A Press"); wiimote.rumbleTimeout = 500; wiimote.rumble = true; //Wiiリモコンを振動させる } //=PV3D= //Create Material private function CreateMaterial():MaterialObject3D { var tex:BitmapAsset = new ImageHoge(); var material:BitmapMaterial = new BitmapMaterial(tex.bitmapData); material.doubleSided = true; return material; } //Create Cube private function createCube():DisplayObject3D { //* var material:MaterialObject3D = CreateMaterial(); /*/ var material:WireframeMaterial = new WireframeMaterial(); material.oneSide = false; material.lineColor = 0xFFFF00; material.lineAlpha = 1; //*/ var width:Number = 40;//本当はこっちを80にしたい var depth:Number = 80;//本当はこっちを40にしたい var height:Number = 30; var cube:Cube = new Cube( material, width, depth, height); // cube.x = 0;//50;//位置はループ内で指定 // cube.y = 0;//-100; // cube.z = 0;//-100 return cube; } //=Common= //Main Loop private function myLoopEvent( event:Event ):void { //Update for(var i:int; i<obj.length; i++){ // obj[i].rotationY = 360 * wiimote.sensorY;//横持ち時のXの値 // obj[i].rotationY = 20 * wiimote.sensorZ;//横持ち時のYの値 // obj[i].rotationY = 20 * wiimote.sensorX;//横持ち時のZの値 var axisY:Number3D = new Number3D(0, 1, 0); var nrm:Number3D = new Number3D(wiimote.sensorY, wiimote.sensorZ, -wiimote.sensorX); // var nrm:Number3D = new Number3D(-wiimote.sensorX, wiimote.sensorZ, -wiimote.sensorY); nrm.normalize(); if(nrm.modulo < 0.01){ nrm = new Number3D(0, 1, 0); } var axis:Number3D = Number3D.cross(axisY, nrm); if(axis.modulo < 0.01){ axis = new Number3D(0, 0, 1); }else{ axis.normalize(); } var angle:Number = Math.acos(Number3D.dot(axisY, nrm)); if(Number3D.dot(Number3D.cross(axis, axisY), nrm) < 0){ angle = -angle; } obj[i].transform = Matrix3D.rotationMatrix( axis.x, axis.y, axis.z, angle ); } //Render scene.renderCamera(camera); //Debug label.text = ""+wiimote.sensorX+"\n"+wiimote.sensorY+"\n"+wiimote.sensorZ+"\n"; } //Resize private function onStageResize(event:Event):void { container.x = stage.stageWidth / 2; container.y = stage.stageHeight / 2; } //=Debug= //Create Label private function makeLabel(text:String):TextField { var label:TextField=new TextField(); label.text =text; label.autoSize =TextFieldAutoSize.LEFT; label.selectable=false; return label; } } }