Papervision3D・WiiFlashの勉強のログ

いろいろ調査

Matrix3D.asの中を見ていたら、クォータニオンの記述を発見。専用クラスがあるわけではなく、Objectとして渡してどうこうするらしい。


WiiFlashのsensorXなどの値を表示してみた。軸の方向が思っていたのとは違ったが、値に関してはほぼ想定どおり(基本状態のベクトルの長さが1。振ったりすると長さが4になったりする)。ただ、値がちょっとおおざっぱすぎる。少しずつ傾きを変えても、そこそこ大き目の値で変化していく(変化するまではずっと同じ値)。値にして0.038ほど、角度にして約2.28度ほどのデジタルな値で増減している。360度/128=2.8125なので、1バイトで管理しているんだろうか。細かい傾きを使ったものは、これではつらいかもしれない。
と思ったけど、箱の動きとリンクさせてみると問題ない感じ。これ以上の細かさはなくて良いのかもしれない。

WiiFlash + PV3Dのテスト

Wiiリモコンの傾きにあわせて動く箱の作成テスト。ついでにテクスチャを張るテストも兼ねる。
とりあえず上手く動いてはいるものの、自分の考えている軸と箱の幅のパラメータが一致していない。そこはあとで調べる。


動かすには、

  1. WiiリモコンをPCに接続
  2. WiiFlashのサーバを動かしておく
  3. 同じフォルダに「hoge.jpg」という画像を用意
  4. mxmlc wiimotedemo.as」でコンパイル
  5. できた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;
    }
  }
}