[Papervision3D] モデル (7) ~ねぎ振りミク~

Papervision3Dを使って、モデルを作るよ。 :boy:

pv3dModel7

DAEクラス で Colladaデータ を読み込んでモデルを表示してみるよ。 :bouzu:
BasicRenderEngine の代わりに、QuadrantRenderEngine を使ってみたよ。 :cake:
さらに、HoverController で、ぐるんぐるん動かせるようにしてみたよ。 :sun:

@rect 先生 :hakase: の「note.x | [Papervision3D]ねぎ振り完了」から、Colladaデータとテクスチャをダウンロードさせていただきました。 :doki:

:caution: 要 Flash Player 11.8 以上

This movie requires Flash Player 11.8.0

Main.as
package {

  import flash.display.Sprite;
  import flash.display.StageScaleMode;
  import flash.display.StageAlign;
  import flash.events.Event;
  import flash.events.MouseEvent;

  import org.papervision3d.Papervision3D;
  import org.papervision3d.scenes.Scene3D;
  import org.papervision3d.cameras.Camera3D;
  import org.papervision3d.view.Viewport3D;
  import org.papervision3d.render.QuadrantRenderEngine;
  import org.papervision3d.objects.DisplayObject3D;
  import org.papervision3d.objects.parsers.DAE;
  import org.papervision3d.materials.BitmapMaterial;
  import org.papervision3d.materials.utils.MaterialsList;
  import org.papervision3d.events.FileLoadEvent;

  import org.libspark.betweenas3.BetweenAS3;
  import org.libspark.betweenas3.tweens.ITween;
  import org.libspark.betweenas3.events.TweenEvent;
  import org.libspark.betweenas3.easing.*;

  import papervision3d.controllers.HoverController;

  [SWF(backgroundColor="#333333", width="600", height="600", frameRate="30")]

  public class Main extends Sprite {
    [Embed(source="assets/negimiku/negimiku.dae", mimeType="application/octet-stream")]
    private var ColladaData:Class;
    [Embed(source="assets/negimiku/negimiku.png")]
    private var ImageData:Class;
    // プロパティ
    private var scene:Scene3D;
    private var camera:Camera3D;
    private var viewport:Viewport3D;
    private var renderer:QuadrantRenderEngine;
    private var controller:HoverController;
    private var container:DisplayObject3D;
    private var negimiku:DAE;
    private var hand:DisplayObject3D;
    private var arm:DisplayObject3D;
    private var negi:DisplayObject3D;
    private static var radius:uint = 500;
    private var moving:Boolean = false;
    private var angle:Number = 180;
    private var degree:Number = 0;
    private static var deceleration:Number = 0.3;
    private var point:Object = {x: 0, y: 0};
    private static var radian:Number = Math.PI/180;
    private static var center:DisplayObject3D = DisplayObject3D.ZERO;

    // コンストラクタ
    public function Main() {
      stage.scaleMode = StageScaleMode.NO_SCALE;
      stage.align = StageAlign.TOP_LEFT;
      init();
    }

    // メソッド
    private function init():void {
      scene = new Scene3D();
      camera = new Camera3D();
      viewport = new Viewport3D(600, 600, false, false);

      renderer = new QuadrantRenderEngine();
      controller = new HoverController(camera, angle, degree);
      setup();
      initialize();
      addChild(viewport);
      stage.addEventListener(MouseEvent.MOUSE_DOWN, press, false, 0, true);
      stage.addEventListener(MouseEvent.MOUSE_UP, release, false, 0, true);

    }
    private function setup():void {
      camera.x = 0;
      camera.y = 0;
      camera.z = - radius;
      camera.focus = radius;
      camera.zoom = 1;
      camera.target = center;
      controller.distance = radius;
    }
    private function initialize():void {
      container = new DisplayObject3D();
      scene.addChild(container);

      var material:BitmapMaterial = new BitmapMaterial(new ImageData().bitmapData);
      material.smooth = true;
      var materials:MaterialsList = new MaterialsList({all: material});

      negimiku = new DAE();
      negimiku.addEventListener(FileLoadEvent.LOAD_COMPLETE, loaded, false, 0, true);
      negimiku.load(XML(new ColladaData()), materials);
    }
    private function loaded(evt:FileLoadEvent):void {
      negimiku.removeEventListener(FileLoadEvent.LOAD_COMPLETE, loaded);
      container.addChild(negimiku);
      negimiku.scale = 16.8;
      var body:DisplayObject3D = negimiku.getChildByName("COLLADA_Scene");
      hand = new DisplayObject3D();
      body.addChild(hand);

      arm = body.getChildByName("R_arm");
      negi = body.getChildByName("negi");

      body.removeChild(arm);
      body.removeChild(negi);

      hand.addChild(arm);
      hand.addChild(negi);

      addEventListener(Event.ENTER_FRAME, render, false, 0, true);
      jump();
      swingHand();
    }
    private function jump():void {
      var itween:ITween = BetweenAS3.serial(
        BetweenAS3.tween(negimiku, {y: 50}, {y: -50}, 0.5, Cubic.easeOut),
        BetweenAS3.tween(negimiku, {y: -50}, {y: 50}, 0.5, Cubic.easeIn)
      );
      itween.addEventListener(TweenEvent.COMPLETE, jumped, false, 0, true);
      itween.play();

    }
    private function jumped(evt:TweenEvent):void {
      evt.target.removeEventListener(TweenEvent.COMPLETE, jumped);
      jump();
    }
    private function swingHand():void {
      var itween:ITween = BetweenAS3.serial(
        BetweenAS3.tween(hand, {rotationX: -40}, {rotationX: 0}, 0.15, Quad.easeOut),
        BetweenAS3.tween(hand, {rotationX: 0}, {rotationX: -40}, 0.15, Quad.easeIn),
        BetweenAS3.tween(hand, {rotationX: 20}, {rotationX: 0}, 0.1, Quad.easeOut),
        BetweenAS3.tween(hand, {rotationX: 0}, {rotationX: 20}, 0.1, Quad.easeIn)
      );
      itween.addEventListener(TweenEvent.COMPLETE, swingedHand, false, 0, true);
      itween.play();

    }
    private function swingedHand(evt:TweenEvent):void {
      evt.target.removeEventListener(TweenEvent.COMPLETE, swingedHand);
      swingHand();
    }
    private function render(evt:Event):void {
      if (moving) {
        controller.panAngle = angle + (stage.mouseX - point.x)*deceleration;
        controller.tiltAngle = degree + (stage.mouseY - point.y)*deceleration;

      }
      controller.update();
      renderer.renderScene(scene, camera, viewport);
    }
    private function press(evt:MouseEvent):void {
      moving = true;
      angle = controller.panAngle;
      degree = controller.tiltAngle;
      point.x = stage.mouseX;
      point.y = stage.mouseY;

      stage.addEventListener(Event.MOUSE_LEAVE, leave, false, 0, true);
    }
    private function release(evt:MouseEvent):void {
      moving = false;
      stage.removeEventListener(Event.MOUSE_LEAVE, leave);
    }
    private function leave(evt:Event):void {
      moving = false;
      stage.removeEventListener(Event.MOUSE_LEAVE, leave);
    }

  }

}

HoverController.as (papervision3d.controllers.HoverController.as)
package papervision3d.controllers {

  import org.papervision3d.cameras.Camera3D;

  public class HoverController {
    // プロパティ
    private var _camera:Camera3D;
    private var _angle:Number = 0;
    private var _degree:Number = 0;
    private var _panAngle:Number = 0;
    private var _tiltAngle:Number = 0;
    private var _currentPanAngle:Number = 0;
    private var _currentTiltAngle:Number = 0;
    private var _radius:Number = 0;
    private var _minPanAngle:Number = Number.NEGATIVE_INFINITY;
    private var _maxPanAngle:Number = Number.POSITIVE_INFINITY;
    private var _minTiltAngle:Number = -90;
    private var _maxTiltAngle:Number = 90;
    private static var radian:Number = Math.PI/180;
    private static var deceleration:Number = 0.2;

    // コンストラクタ
    public function HoverController(camera:Camera3D, angle:Number = 0, degree:Number = 0) {
      _camera = camera;
      _currentPanAngle = _panAngle = _angle = angle;
      _currentTiltAngle = _tiltAngle = _degree = degree;
    }

    // メソッド
    public function update():void {
      _currentPanAngle += (_panAngle - _currentPanAngle)*deceleration;
      _currentTiltAngle += (_tiltAngle - _currentTiltAngle)*deceleration;
      if (Math.abs(_panAngle - _currentPanAngle) < 0.01 && Math.abs(_panAngle - _currentPanAngle) < 0.01) {
        _currentPanAngle = _panAngle;
        _currentTiltAngle = _tiltAngle;
      }
      _camera.x = _radius*Math.sin(_currentPanAngle*radian)*Math.cos(_currentTiltAngle*radian);
      _camera.y = _radius*Math.sin(_currentTiltAngle*radian);
      _camera.z = _radius*Math.cos(_currentPanAngle*radian)*Math.cos(_currentTiltAngle*radian);
    }
    public function get panAngle():Number {
      return _panAngle;
    }
    public function set panAngle(value:Number):void {
      value = Math.max(minPanAngle, Math.min(maxPanAngle, value));
      if (_panAngle == value) return;
      _panAngle = value;
    }
    public function get tiltAngle():Number {
      return _tiltAngle;
    }
    public function set tiltAngle(value:Number):void {
      value = Math.max(_minTiltAngle, Math.min(_maxTiltAngle, value));
      if (_tiltAngle == value) return;
      _tiltAngle = value;
    }
    public function get distance():Number {
      return _radius;
    }
    public function set distance(value:Number):void {
      _radius = value;
    }
    public function get minPanAngle():Number {
      return _minPanAngle;
    }
    public function set minPanAngle(value:Number):void {
      _minPanAngle = value;
    }
    public function get maxPanAngle():Number {
      return _maxPanAngle;
    }
    public function set maxPanAngle(value:Number):void {
      _maxPanAngle = value;
    }
    public function get minTiltAngle():Number {
      return _minTiltAngle;
    }
    public function set minTiltAngle(value:Number):void {
      _minTiltAngle = value;
    }
    public function get maxTiltAngle():Number {
      return _maxTiltAngle;
    }
    public function set maxTiltAngle(value:Number):void {
      _maxTiltAngle = value;
    }

  }

}

Flash CC + Flex 4 SDK でパブリッシュ。