前回に引き続きコード説明です。
今回は、ARToolKitやウェブカメラの初期化の部分を説明します。
初期化部分のコードは下記の部分です。
/** * webカメラや表示、detectorの初期化 * @return void */ private function initialization(e:Event): void { this.removeEventListener(Event.COMPLETE, initialization); // Setup camera this.webCamera = Camera.getCamera(); if (!this.webCamera) { throw new Error('No webcam!!!!'); } this.webCamera.setMode( this.captureWidth, this.captureHeight, 30); this.video = new Video( this.captureWidth, this.captureHeight); this.video.attachCamera(this.webCamera); // setup ARToolkit this.capture = new Bitmap(new BitmapData(this.captureWidth, this.captureHeight, false, 0), PixelSnapping.AUTO, true); // ウェブカメラの解像度と表示サイズが異なる場合は拡大する this.capture.width = this.canvasWidth; this.capture.height = this.canvasHeight; // キャプチャーしている内容からラスタ画像を生成 this.raster = new FLARRgbRaster_BitmapData( this.capture.bitmapData); // キャプチャーしている内容を addChild this.addChild(this.capture); // setup Single marker detector this.detector = new FLARSingleMarkerDetector( this.cameraParam, this.markerPatternCode, this.codeWidth); // 継続認識モード発動 this.detector.setContinueMode(true); // しきい値調整 this._threshold_detect=new FLARRasterThresholdAnalyzer_SlidePTile(15,4); // 初期化完了 dispatchEvent(new Event(Event.INIT)); // 3Dオブジェクト関係の初期化へ this.supportLibsInit(); // スタート this.start(); }
この部分では[メインループ処理]で使用する値の準備がほとんどです。
ARToolKitは[webカメラからの映像]から[フレームごとの画像]を取り出して、[二値化](あるしきい値で決められた値で変換して白黒画像にする事)してから解析してマーカーを検出・位置情報を取得するということを行っています。
このあたりは殆どお作法なので詳しく知りたい方のみ内部の処理を調べることをおすすめします。
基本的にコメントに書かれているままなのですが、一箇所だけ説明します
// setup Single marker detector this.detector = new FLARSingleMarkerDetector( this.cameraParam, this.markerPatternCode, this.codeWidth); // 継続認識モード発動 this.detector.setContinueMode(true); // しきい値調整 this._threshold_detect=new FLARRasterThresholdAnalyzer_SlidePTile(15,4);
ここでFLARToolKitの肝であるDetector(マーカー認識用のクラス)を初期化しています。
基本的にはこのままの形式で使うことになります。
表に見える v1系との違いはFLARRasterThresholdAnalyzer_SlidePTileです。 この設定を行うことで、周辺の明るさに応じてしきい値を変更してくれるという優れものを初期化します。
FLARToolKitでは、このDetectorをどう実装するかはユーザー任せになっています。
この基本クラスでも十分ですが、内部処理を修正又は手を加えることでいろいろと化ける部分でもあります。
普通のマーカー認識だけでは飽きた……という場合は、このクラスを書き直して新たなDetectorを作るというのも一つのポイントになります。
これがあるのと無いのとでは認識に差が出ます。
v1系では、FLARManagerでこの機能がサポートされていましたが標準では含まれていませんでした。
そのため、環境……部屋の明るさによっては全く認識しない現象がでます。
どうしても v1系を使わなければならない場合は、FLARManagerを。v2のみである場合は必ず使ってください。
FLARToolKitでマーカー上に何かを表示する際に使用する3D描画ライブラリの設定部分です。
今回の説明では標準的に使われている Papervision3D(以下PV3D)を使用しています。
他の描画ライブラリを使用する場合はこの部分とオブジェクト生成の部分が主に変更になります。
/** * 3Dオブジェクト関係の初期化 * 使用する3Dライブラリに応じてこの部分を書き換える。 */ protected function supportLibsInit(): void { this.viewport3d = new Viewport3D(this.captureWidth, this.captureHeight); this.addChild(this.viewport3d); this.viewport3d.scaleX = this.canvasWidth / this.captureWidth; this.viewport3d.scaleY = this.canvasHeight / this.captureHeight; this.viewport3d.x = -4; // 4pix ??? // マーカーノードの初期化 this.markerNode = new FLARBaseNode(); // シーンの生成 this.scene3d = new Scene3D(); this.scene3d.addChild(this.markerNode) // 3Dモデル表示時の視点を設定 this.camera3d = new FLARCamera3D(this.cameraParam); // setup renderer this.renderer = new LazyRenderEngine(this.scene3d, this.camera3d, this.viewport3d); }
FLARCamera3DはCamera3D、FLARBaseNodeはDisplayObject3D と読み替えればほとんどPV3Dの内容です。
そのため、この部分についてはPV3Dに関する本やウェブを参照にする方が良いと思います。
表示する3Dモデルを定義している場所と、それを登録してる部分になります。
まずは3Dオブジェクトを生成している部分。
/** * 3Dオブジェクト生成 */ protected function createObject(_container:DisplayObject3D):void { // ワイヤーフレームで,マーカーと同じサイズを Plane を作ってみる。 var wmat:WireframeMaterial = new WireframeMaterial(0x0000ff, 1, 2); var _plane:Plane = new Plane(wmat, 80, 80); // 80mm x 80mm。 _plane.rotationX = 180; // ライトの設定。手前、上のほう。 var light:PointLight3D = new PointLight3D(); light.x = 0; light.y = 1000; light.z = -1000; // Cube var fmat:FlatShadeMaterial = new FlatShadeMaterial(light, 0x0000FF, 0x000066); var _cube:Cube = new Cube(new MaterialsList( { all:fmat } ), 40, 40, 40); _cube.z = 20; // _container に 追加 _container.addChild(_plane); _container.addChild(_cube); }
ほとんどPV3Dでの書き方と一緒ですね……
マーカー面に対して左手座標系を用いているので、それに気をつけながら登録する感じになります。
また、PV3Dの機能であればほとんど使用することができるので、Colladaモデルを読み込んで使用することも可能です。
続いて、メインループに入る前の処理部分。
/** * 3Dオブジェクトの生成と登録 * マーカーイベント方式を採用しているため、markerイベントを登録 * スレッドのスタート */ protected function start():void { // モデル格納用のコンテナ作成 this.container = new DisplayObject3D(); // 3Dオブジェクト生成 this.createObject(this.container); // Marker Node に追加 this.markerNode.addChild(this.container); // マーカー認識・非認識時用のイベントを登録 this.addEventListener(MarkerEvent.MARKER_ADDED, this.onMarkerAdded); this.addEventListener(MarkerEvent.MARKER_UPDATED, this.onMarkerUpdated); this.addEventListener(MarkerEvent.MARKER_REMOVED, this.onMarkerRemoved); // 処理開始 this.addEventListener(Event.ENTER_FRAME, this.run); }
イベント周りについては次回説明するとして、今回の説明では下記の部分のみ。
// モデル格納用のコンテナ作成 this.container = new DisplayObject3D(); // 3Dオブジェクト生成 this.createObject(this.container); // Marker Node に追加 this.markerNode.addChild(this.container);
一つしか表示しないので、表示物を DisplayObject3D に詰め込んでしまい、それを markerNode に登録しています。
markerNode は、DisplayObject3D を継承して、FLARToolKitで検出した3DMatrixで移動できるようにしたものです。
このあたりの説明は、こちら(第3回 マーカーの位置や回転,向きなどを取り出す[gihyo.jp])を確認した方がわかりやすいかもしれません。
複数のインスタンスを生成することで、個別に制御することも可能かもしれません。
では、次回はメインループ部分について説明します。