[AIR3.0] LeapMotionを体験するのだ! (4)

そうだ! LeapMotionを体験してみよう! :bouzu:

LeapMotion

LeapMotionAS3 を使ってみるよ。 :boy:
Away3D と組み合わせちゃうんだからね。 :girl:

:caution: 要 Flash Player 9 以上

This movie requires Flash Player 9.0.0

Main.as
package {

  import flash.display.Sprite;
  import flash.system.System;
  import flash.events.Event;
  import flash.geom.Vector3D;
  import flash.display.BlendMode;
  import flash.geom.ColorTransform;

  import com.leapmotion.leap.Controller;
  import com.leapmotion.leap.Frame;
  import com.leapmotion.leap.Hand;
  import com.leapmotion.leap.Finger;
  import com.leapmotion.leap.Vector3;
  import com.leapmotion.leap.events.LeapEvent;

  import away3d.Away3D;
  import away3d.containers.View3D;
  import away3d.containers.Scene3D;
  import away3d.cameras.Camera3D;
  import away3d.animators.ParticleAnimationSet;
  import away3d.animators.ParticleAnimator;
  import away3d.animators.data.ParticlePropertiesMode;
  import away3d.animators.data.ParticleProperties;
  import away3d.animators.nodes.ParticleBillboardNode;
  import away3d.animators.nodes.ParticleVelocityNode;
  import away3d.animators.nodes.ParticleFollowNode;
  import away3d.animators.nodes.ParticleColorNode;
  import away3d.animators.states.ParticleColorState;
  import away3d.entities.Mesh;
  import away3d.core.base.ParticleGeometry;
  import away3d.core.base.Geometry;
  import away3d.primitives.PlaneGeometry;
  import away3d.core.base.Object3D;
  import away3d.tools.helpers.ParticleGeometryHelper;
  import away3d.materials.TextureMaterial;
  import away3d.utils.Cast;

  import controls.Label;

  [SWF(backgroundColor="#000000", width="800", height="600", frameRate="60")]

  public class Main extends Sprite {
    [Embed(source="assets/particle.png")]
    private var ParticleHand:Class;
    [Embed(source="assets/clover.png")]
    private var ParticleFinger:Class;
    // プロパティ
    private var view:View3D;
    private var scene:Scene3D;
    private var camera:Camera3D;
    private var animationHand:ParticleAnimationSet;
    private var animationFinger:ParticleAnimationSet;
    private var animatorsFinger:Array;
    private var leadersHand:Vector.<Object3D>;
    private var leadersFinger:Array;
    private var colorNode:ParticleColorNode;
    private var startColorTransList:Vector.<ColorTransform>;
    private var endColorTransList:Vector.<ColorTransform>;
    private static var radius:uint = 1000;
    private var angle:Number = - 90;
    private var degree:Number = 0;
    private static var depression:uint = 12;
    private static var radian:Number = Math.PI/180;
    private static var center:Vector3D = new Vector3D();
    private var controller:Controller;
    private static var sw:uint = 800;
    private static var sh:uint = 600;
    private var msg:Label;

    // コンストラクタ
    public function Main() {
      System.pauseForGCIfCollectionImminent(1);
      init();
    }

    // メソッド
    private function init():void {
      view = new View3D();
      scene = view.scene;
      camera = view.camera;

      addChild(view);
      setup();
      initialize();
      addEventListener(Event.ENTER_FRAME, render, false, 0, true);
      controller = new Controller();
      controller.addEventListener(LeapEvent.LEAPMOTION_INIT, initialized, false, 0, true);
      controller.addEventListener(LeapEvent.LEAPMOTION_CONNECTED, connected, false, 0, true);
      controller.addEventListener(LeapEvent.LEAPMOTION_DISCONNECTED, disconnected, false, 0, true);
      controller.addEventListener(LeapEvent.LEAPMOTION_EXIT, exit, false, 0, true);
      controller.addEventListener(LeapEvent.LEAPMOTION_FRAME, update, false, 0, true);

      msg = new Label(120, 20, 14, Label.LEFT);
      addChild(msg);
      msg.x = 10;
      msg.y = 580;
      msg.textColor = 0xFFFFFF;
    }
    private function setup():void {
      view.backgroundColor = 0x000000;
      view.antiAlias = 4;
      camera.x = 0;
      camera.y = 0;
      camera.z = - radius;
    }
    private function initialize():void {
      var planeHand:Geometry = new PlaneGeometry(36, 36, 1, 1, false);
      var planesHand:Vector.<Geometry> = new Vector.<Geometry>();
      for (var h:uint = 0; h < 400; h++) {
        planesHand.push(planeHand);
      }

      var geometryHand:ParticleGeometry = ParticleGeometryHelper.generateGeometry(planesHand);
      var materialHand:TextureMaterial = new TextureMaterial(Cast.bitmapTexture(ParticleHand));
      materialHand.blendMode = BlendMode.ADD;
      var startColorTransHand:ColorTransform = new ColorTransform(0.36, 0.54, 1, 1);
      var endColorTransHand:ColorTransform = new ColorTransform(0.36, 0.54, 1, 0);

      animationHand = new ParticleAnimationSet(true, true, true);
      animationHand.addAnimation(new ParticleBillboardNode());
      animationHand.addAnimation(new ParticleVelocityNode(ParticlePropertiesMode.LOCAL_STATIC));
      var followNodeHand:ParticleFollowNode = new ParticleFollowNode(true, false, true);
      animationHand.addAnimation(followNodeHand);
      animationHand.addAnimation(new ParticleColorNode(ParticlePropertiesMode.GLOBAL, true, false, false, false, startColorTransHand, endColorTransHand));
      animationHand.initParticleFunc = initParticleHand;

      leadersHand = new Vector.<Object3D>();
      for (var n:uint = 0; n < 2; n ++) {
        var particleHand:Mesh = new Mesh(geometryHand, materialHand);
        scene.addChild(particleHand);

        particleHand.shareAnimationGeometry = false;
        var leaderHand:Object3D = new Object3D();
        leadersHand.push(leaderHand);
        var animatorHand:ParticleAnimator = new ParticleAnimator(animationHand);
        particleHand.animator = animatorHand;
        animatorHand.start();
        followNodeHand.getAnimationState(animatorHand).followTarget = leaderHand;

      }

      var planeFinger:Geometry = new PlaneGeometry(24, 24, 1, 1, false);
      var planesFinger:Vector.<Geometry> = new Vector.<Geometry>();
      for (var f:uint = 0; f < 100; f++) {
        planesFinger.push(planeFinger);
      }

      var geometryFinger:ParticleGeometry = ParticleGeometryHelper.generateGeometry(planesFinger);
      var materialFinger:TextureMaterial = new TextureMaterial(Cast.bitmapTexture(ParticleFinger));
      materialFinger.blendMode = BlendMode.ADD;
      animationFinger = new ParticleAnimationSet(true, true, true);
      animationFinger.addAnimation(new ParticleBillboardNode());
      animationFinger.addAnimation(new ParticleVelocityNode(ParticlePropertiesMode.LOCAL_STATIC));
      var followNodeFinger:ParticleFollowNode = new ParticleFollowNode(true, false, true);
      animationFinger.addAnimation(followNodeFinger);
      colorNode = new ParticleColorNode(ParticlePropertiesMode.GLOBAL, true, false, false, false);
      animationFinger.addAnimation(colorNode);
      animationFinger.initParticleFunc = initParticleFinger;

      var colors:Array = new Array();
      colors.push({r: 1, g: 0.4, b: 0.4});
      colors.push({r: 1, g: 1, b: 0.5});
      colors.push({r: 1, g: 0.48, b: 0.64});
      colors.push({r: 0.4, g: 1, b: 0.4});
      colors.push({r: 0.6, g: 0.24, b: 0.6});
      animatorsFinger = new Array();
      var animatorsFinger1:Vector.<ParticleAnimator> = new Vector.<ParticleAnimator>();
      var animatorsFinger2:Vector.<ParticleAnimator> = new Vector.<ParticleAnimator>();
      leadersFinger = new Array();
      var leadersFinger1:Vector.<Object3D> = new Vector.<Object3D>();
      var leadersFinger2:Vector.<Object3D> = new Vector.<Object3D>();
      startColorTransList = new Vector.<ColorTransform>();
      endColorTransList = new Vector.<ColorTransform>();
      for (var t:uint = 0; t < 5; t++) {
        var particleFinger1:Mesh = new Mesh(geometryFinger, materialFinger);
        scene.addChild(particleFinger1);

        particleFinger1.shareAnimationGeometry = false;
        var particleFinger2:Mesh = new Mesh(geometryFinger, materialFinger);
        scene.addChild(particleFinger2);

        particleFinger2.shareAnimationGeometry = false;
        var leaderFinger1:Object3D = new Object3D();
        var leaderFinger2:Object3D = new Object3D();
        leadersFinger1.push(leaderFinger1);
        leadersFinger2.push(leaderFinger2);
        var animatorFinger1:ParticleAnimator = new ParticleAnimator(animationFinger);
        particleFinger1.animator = animatorFinger1;
        animatorFinger1.start();
        followNodeFinger.getAnimationState(animatorFinger1).followTarget = leaderFinger1;
        animatorsFinger1.push(animatorFinger1);

        var animatorFinger2:ParticleAnimator = new ParticleAnimator(animationFinger);
        particleFinger2.animator = animatorFinger2;
        animatorFinger2.start();
        followNodeFinger.getAnimationState(animatorFinger2).followTarget = leaderFinger2;
        animatorsFinger2.push(animatorFinger2);

        var color:Object = colors[t];
        var startColorTrans:ColorTransform = new ColorTransform(color.r, color.g, color.b, 1);
        var endColorTrans:ColorTransform = new ColorTransform(color.r, color.g, color.b, 0);

        startColorTransList.push(startColorTrans);
        endColorTransList.push(endColorTrans);
      }
      animatorsFinger[0] = animatorsFinger1;
      animatorsFinger[1] = animatorsFinger2;
      leadersFinger[0] = leadersFinger1;
      leadersFinger[1] = leadersFinger2;
    }
    private function initParticleHand(prop:ParticleProperties):void {
      prop.startTime = - 0.2 + Math.random()*3;
      prop.duration = 3;

      prop[ParticleVelocityNode.VELOCITY_VECTOR3D] = new Vector3D((Math.random() - 0.5)*60, (Math.random() - 0.5)*60, (Math.random() - 0.5)*60);
    }
    private function initParticleFinger(prop:ParticleProperties):void {
      prop.startTime = - 0.2 + Math.random()*3;
      prop.duration = 3;

      prop[ParticleVelocityNode.VELOCITY_VECTOR3D] = new Vector3D((Math.random() - 0.5)*80, (Math.random() - 0.5)*80, (Math.random() - 0.5)*80);
    }
    private function render(evt:Event):void {
      for (var n:uint = 0; n < 2; n++) {
        for (var t:uint = 0; t < 5; t++) {
          var animatorFinger:ParticleAnimator = animatorsFinger[n][t];
          var state:ParticleColorState = ParticleColorState(animatorFinger.getAnimationState(colorNode));
          state.startColor = startColorTransList[t];
          state.endColor = endColorTransList[t];

        }
      }
      angle += 0.5;
      degree += 1;
      var dip:Number = depression*Math.sin(degree*radian);
      camera.x = radius*Math.cos(angle*radian)*Math.cos(dip*radian);
      camera.y = radius*Math.sin(dip*radian);
      camera.z = radius*Math.sin(angle*radian)*Math.cos(dip*radian);
      camera.lookAt(center);
      view.render();
    }
    private function initialized(evt:LeapEvent):void {
      msg.text = "initialized";
    }
    private function connected(evt:LeapEvent):void {
      msg.text = "connected";
      controller.setPolicyFlags(Controller.POLICY_BACKGROUND_FRAMES);
    }
    private function disconnected(evt:LeapEvent):void {
      msg.text = "disconnected";
    }
    private function exit(evt:LeapEvent):void {
      msg.text = "exit";
    }
    private function update(evt:LeapEvent):void {
      var frame:Frame = evt.frame;
      var position:Vector3;
      var nmax:uint = frame.hands.length;
      for (var n:uint = 0; n < 2; n++) {
        var leaderHand:Object3D = leadersHand[n];
        if (n < nmax) {
          var hand:Hand = frame.hands[n];
          position = hand.palmPosition.multiply(2.0);
          leaderHand.x = position.x;
          leaderHand.y = position.y - radius/2;
          leaderHand.z = - position.z;

          var fingers:Vector.<Finger> = hand.fingers;
          var tmax:uint = fingers.length;
          for (var t:uint = 0; t < 5; t ++) {
            var leaderFinger:Object3D = leadersFinger[n][t];
            if (t < tmax) {
              var finger:Finger = fingers[t];
              position = finger.tipPosition.multiply(2.0);
              leaderFinger.x = position.x;
              leaderFinger.y = position.y - radius/2;
              leaderFinger.z = - position.z;

            }
          }
        }
      }
    }

  }

}

libsフォルダに、LeapMotionAS3.swc, LeapMotionAS3.ane を用意。ライブラリパスを通す。

CCなら、パブリッシュするだけ。(AIR 3.9/ASC 2.0)

LeapMotion_away3d_particle


[修正] (13/11/21 Thu 13:20)
ParticleFollowNodeの第3引数(smooth)をtrueに変更。MeshのshareAnimationGeometryプロパティをfalseにして、個別のアニメーションに変更。