マウスのドラッグで3Dモデルが回転するサンプル。

3頂点による面クラス(Face.as)と頂点クラス(Vertex.as)は Flex SDK で回転する3Dオブジェクト描画のサンプルを作る にあるものを流用。

メインクラスのソースコード(GuruGuru3DModel.as)


package {
 
  import flash.display.*;
  import flash.events.*;
  import flash.text.*;
  import flash.utils.*;
 
  public class GuruGuru3DModel extends Sprite {
 
    // 描画キャンバス
    private var shape:Shape;
 
    // 描画補助情報
    private var m_Scale:Number = 100;
    private var Center_x:Number = 100;
    private var Center_y:Number = 100;
 
    // 3Dモデル情報
    private var face:Array = new Array();
 
    private var controller:Sprite; // マウスイベント取得用
    private var moused:Boolean = false; // マウスボタン押下中
    private var mousex:Number = -1; // マウスX位置
    private var mousey:Number = -1; // マウスY位置
 
    private var angle:Number = 6;
 
    public function GuruGuru3DModel() {
 
      // 3Dモデル描画用
      shape = new Shape();
      addChild(shape);
 
      // マウスイベント取得用。こんなんでいいのかなぁ……
      controller = new Sprite();
      controller.alpha = 0;
      controller.graphics.beginFill(0x00FF00);
      controller.graphics.drawRect(0,0,240,240);
      controller.graphics.endFill();
      addChild(controller);
 
      // 頂点
      var vertex:Array = new Array();
      vertex[0] = new Vertex(-1, 0, 0);
      vertex[1] = new Vertex( 0, 0, 1);
      vertex[2] = new Vertex( 0, 1, 0);
      vertex[3] = new Vertex( 1, 0, 0);
      vertex[4] = new Vertex( 0,-1, 0);
      vertex[5] = new Vertex( 0, 0,-1);
 
      // 辺
      face[0] = new Face(vertex[1], vertex[4], vertex[2]);
      face[1] = new Face(vertex[1], vertex[0], vertex[4]);
      face[2] = new Face(vertex[1], vertex[2], vertex[0]);
      face[3] = new Face(vertex[3], vertex[2], vertex[4]);
      face[4] = new Face(vertex[0], vertex[5], vertex[4]);
      face[5] = new Face(vertex[4], vertex[5], vertex[3]);
      face[6] = new Face(vertex[3], vertex[5], vertex[2]);
      face[7] = new Face(vertex[2], vertex[5], vertex[0]);
 
      // 3Dモデルを描画
      drawModel();
 
      // マウスイベント登録
      controller.addEventListener(MouseEvent.MOUSE_DOWN, mousedown);
      controller.addEventListener(MouseEvent.MOUSE_UP, mouseup);
      controller.addEventListener(MouseEvent.MOUSE_MOVE, mousemove);
    }
 
    private function mousedown(evt:MouseEvent):void {
      if(!moused){
        moused = true;
        mousex = evt.localX;
        mousey = evt.localY;
      }
    }
 
    private function mouseup(evt:MouseEvent):void {
      moused = false;
      mousex = -1;
      mousey = -1;
    }
 
    private function mousemove(evt:MouseEvent):void {
      if(moused){
        var x:Number = evt.localX - mousex;
        var y:Number = evt.localY - mousey;
        mousex = evt.localX;
        mousey = evt.localY;
        rotate(y, x, 0);
        drawModel();
      }
    }
 
    private function drawModel():void {
 
      // 前の描画を消去
      shape.graphics.clear();
 
      // 3Dモデルを描画
      for(var i:int=0; i < face.length; i++) {
        var x0:Number =  face[i].vertex[0].x * m_Scale + Center_x;
        var x1:Number =  face[i].vertex[1].x * m_Scale + Center_x;
        var x2:Number =  face[i].vertex[2].x * m_Scale + Center_x;
        var y0:Number = -face[i].vertex[0].y * m_Scale + Center_y;
        var y1:Number = -face[i].vertex[1].y * m_Scale + Center_y;
        var y2:Number = -face[i].vertex[2].y * m_Scale + Center_y;
 
        // 奥行き(Z軸)
        var depth:Number = 3 - (face[i].vertex[0].z + face[i].vertex[1].z + face[i].vertex[2].z);
        // 描画ペンの太さ
        var penWidth:Number = depth;
        // アルファ値(0~1を指定) しかしこのプログラムでは意味がないような...
        var penAlpha:Number = depth / 3;
 
        shape.graphics.lineStyle(penWidth, 0xff0000, penAlpha);
        shape.graphics.moveTo(x0, y0);
        shape.graphics.lineTo(x1, y1);
        shape.graphics.lineTo(x2, y2);
        shape.graphics.lineTo(x0, y0);
      }
    }
 
    // ActionScript の Math.sin とか Math.cos には
    // 角度(°)ではなくラジアンが必要
    private static function toRadians(degree:Number):Number{
      return degree / 180.0 * Math.PI;
    }
 
    // 3Dモデルを回転
    private function rotate(x:Number,y:Number,z:Number):void{
      for(var i:int=0; i<face.length; i++) {
        face[i].rotate(toRadians(x), toRadians(y), toRadians(z));
      }
    }
 
  }
 
}

MOUSE_UP が確実に呼ばれるわけではないみたい? マウスアップしてもグリグリ回転できるときがある。

tags: zlashdot Flash 3D Flash Flex

Posted by NI-Lab. (@nilab)