FLARToolKitで偽Wiiもどき作ってみた

2008/07/24

こんにちは。フルーチェを久し振りに食べたんですが、おいしいですね。フルーチェもいいんですが、同様に牛乳で作る杏仁豆腐というのも売っていて、これがまたおいしい。いろんな会社から出ていますので、それぞれ味に特徴があるので食べ比べてみるといいですよ。

さて、前回日本文化についてなんて語っちゃったわけですが、後半にいく前にFLARToolKitを使ってみましたので、それのご紹介です。
今までWebカメラというものを持っていなかったのですが、このたび購入しまして早速気になっていたFLARToolKitをためしてみたのです。そしたらすごいですね!やっぱりこういうのは実際に自分の手で動かしてみないとわかりませんね。

とにかく作ったものは→こちら

用意するもの
・webカメラ
・マーカー(紙に印刷する。さくーしゃさんのこのページにあるpattHiro.pdfを印刷してください。)

設定完了で、オレンジ色のボールがマーカーの上にとびはねます。さらに、うまくやるとマーカーから押し出されてボールが飛びだします。マーカーをスライドさせたり、カメラに向かって押し出したりしてみてください。動きはぎこちないのですが、自分の手でボールを押し出す感じが伝われば成功です。成功率はあまり高くないです。すみません。
Wiiは持ってないんで、みたかんじの想像ですが、Webカメラと紙一枚+ブラウザで似たようなことができるのは驚きです。
作っててひとりで興奮してしまった!フンガッフッフッ!

さくーしゃさん、タロタローグさんには心から感謝いたします。
Saqoosha.net| FLARToolKit
タロタローグ ブログ|電脳コイルももう間近!FlashDevelopとFLARToolKitで始める、お手軽簡単Flash拡張現実の世界(1)

電脳コイルは見たことなかったんですが、これを機に見てみようかな。

以下ソースです。サンプルコードを改良しました。

package {

  import caurina.transitions.Tweener;

  import com.libspark.flartoolkit.core.FLARTransMatResult;
  import com.libspark.flartoolkit.scene.FLARCamera3D;

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

  import org.papervision3d.core.math.Matrix3D;
  import org.papervision3d.lights.PointLight3D;
  import org.papervision3d.materials.WireframeMaterial;
  import org.papervision3d.materials.shadematerials.FlatShadeMaterial;
  import org.papervision3d.materials.utils.MaterialsList;
  import org.papervision3d.objects.DisplayObject3D;
  import org.papervision3d.objects.primitives.Cube;
  import org.papervision3d.objects.primitives.Plane;
  import org.papervision3d.objects.primitives.Sphere;
  import org.papervision3d.render.LazyRenderEngine;
  import org.papervision3d.scenes.Scene3D;
  import org.papervision3d.view.Viewport3D;


  [SWF(width=640,height=480,frameRate=60,backgroundColor=0x0)]

  public class FLARToolKitTest2 extends ARAppBase {

    private static const PATTERN_FILE:String = "Data/patt.hiro";
    private static const CAMERA_FILE:String = "Data/camera_para.dat";

    private var _base:Sprite;
    private var _scene:Scene3D;
    private var _camera3d:FLARCamera3D;
    private var _viewport:Viewport3D;
    private var _renderer:LazyRenderEngine;

    private var _transGrp:DisplayObject3D;
    private var _basePlane:Plane;
    private var _cube:Cube;

    private var _resultMat:FLARTransMatResult = new FLARTransMatResult();

    private var _isMirror:Boolean = false;

    private var sphear:BoundsSphere;

    public function FLARToolKitTest2() {
      this.stage.scaleMode = StageScaleMode.SHOW_ALL;
      this.stage.quality = StageQuality.LOW;

      this.addEventListener(Event.INIT, this._onInit);
      this.init(CAMERA_FILE, PATTERN_FILE, 320, 240);
    }

    private function _onInit(e:Event):void {
      this.removeEventListener(Event.INIT, this._onInit);

      this._base = this.addChild(new Sprite()) as Sprite;

      this._capture.width = 640;
      this._capture.height = 480;
      this._base.addChild(this._capture);

      this._viewport = this._base.addChild(new Viewport3D(320, 240, false, false, false, false)) as Viewport3D;
      this._viewport.scaleX = 640 / 320;
      this._viewport.scaleY = 480 / 240;
      this._viewport.x = -4; // 4pix ???

      this._camera3d = new FLARCamera3D(this._viewport, this._param);

      this._scene = new Scene3D();
      this._transGrp = this._scene.addChild(new DisplayObject3D()) as DisplayObject3D;
        var wmat:WireframeMaterial = new WireframeMaterial(0xff0000, 1, 2);
        wmat.doubleSided = true;
        this._basePlane = new Plane(wmat, 80, 80);
      //this._transGrp.addChild(this._basePlane);
        var light:PointLight3D = new PointLight3D();
        light.x = 1000;
        light.y = 1000;
        light.z = -1000;
        var fmat:FlatShadeMaterial = new FlatShadeMaterial(light, 0xff22aa, 0x0);
        this._cube = new Cube(new MaterialsList({ all: fmat }), 40, 40, 40);
        this._cube.z += 20;

      var mt:FlatShadeMaterial = new FlatShadeMaterial(light, 0xff5d25, 0x842e10);
      sphear = new BoundsSphere(mt, 20);
      //this._transGrp.addChild(this._cube);
      this._transGrp.addChild(sphear);
      this.sphear.z = 60;

      this._renderer = new LazyRenderEngine(this._scene, this._camera3d, this._viewport);

      this.addChild(new FPSMeter());

      this.addEventListener(Event.ENTER_FRAME, this._onEnterFrame);
      this.stage.addEventListener(MouseEvent.CLICK, this._onClick);
    }

    private function _onEnterFrame(e:Event = null):void {
      this._capture.bitmapData.draw(this._video);
      if (this._detector.detectMarkerLite(this._raster, 80)) {
        this._detector.getTranslationMatrix(this._resultMat);
        var a:Array = this._resultMat.getArray();
        var mtx:Matrix3D = this._transGrp.transform;

        var pastX:Number = this._transGrp.x;
        var pastY:Number = this._transGrp.y;
        var pastZ:Number = this._transGrp.z;
        mtx.n11 =  a[0][1];  mtx.n12 =  a[0][0];  mtx.n13 =  a[0][2];  mtx.n14 =  a[0][3];
        mtx.n21 = -a[1][1];  mtx.n22 = -a[1][0];  mtx.n23 = -a[1][2];  mtx.n24 = -a[1][3];
        mtx.n31 =  a[2][1];  mtx.n32 =  a[2][0];  mtx.n33 =  a[2][2];  mtx.n34 =  a[2][3];
        this._renderer.render();
        var dx:Number = this._transGrp.x - pastX;
        var dy:Number = this._transGrp.y - pastY;
        var dz:Number = this._transGrp.z - pastZ;
        this.sphear.update(dx, dy, dz);
      }
    }

    private function _onClick(e:MouseEvent):void {

      this._isMirror = !this._isMirror;
      if (this._isMirror) {
        this._base.scaleX = -1;
        this._base.x = 640;
      } else {
        this._base.scaleX = 1;
        this._base.x = 0;
      }
    }

  }

}

import org.papervision3d.objects.primitives.Sphere;
import org.papervision3d.core.proto.MaterialObject3D;

class BoundsSphere extends Sphere
{
  private var gravity:Number = -3;
  private var vx:Number = 0;
  private var vy:Number = 0;
  private var vz:Number = 0;

  public function BoundsSphere(material:MaterialObject3D, radius:Number):void
  {
    super(material, radius);
  }

  public function update(dx:Number, dy:Number, dz:Number):void
  {
    if(Math.abs(dx) > 100){  dx = 0; }
    if(Math.abs(dy) > 100){  dy = 0; }
    if(Math.abs(dz) > 100){  dz = 0; }

    this.vx = -this.x * 0.03 + dx * -2.5;
    this.vy = -this.y * 0.03 + dy * 2.5;
    this.vz += gravity + dz * -0.4;

    this.x += vx;
    this.y += vy;
    this.z += vz;

    if(this.z < 0)
    {
      this.vz *= -0.8;
      this.z = 0;
    }
  }
}

自作iPhoneアプリ 好評発売中!
フォルメモ - シンプルなフォルダつきメモ帳
ジッピー電卓 - 消費税や割引もサクサク計算!

ページトップへ戻る