FLARToolKitを使ったAR系Flashの作り方

第1回FLARToolKitことはじめ

ARとは?

最近よく目にするARとはAugmented Realityの略で、日本語にすると「拡張現実」と言います。昔はやったVR(Virtual Reality)とよく間違われるのですが、こちらは「仮想現実⁠⁠。ARとは違います。

Wikipediaによると、ARは次のように定義されています。

拡張現実とは現実環境にコンピュータを用いて情報を付加提示する技術、および情報を付加提示された環境そのものを示す。

難解な文章でよくわからないですよね。具体的なモノでいうと、アレです、ドラゴンボールに出てくる「スカウター」です。スカウターを通して見ると現実環境に相手の戦闘能力が付加提示されて見える、と。実写に完全にシンクロさせてリアルタイムにCGなどを合成するという技術なのです。

FLARToolKitとは?

さて、本稿で解説するFLARToolKit(えふえるえーあーるつーるきっと)とは、このARという技術を容易に実現するために開発されたARToolKitというものをFlash(ActionScript3.0)に移植したものです[1]⁠。

実際にFLARToolKitがやってくれるのは実写画像から3次元空間の位置を計算するところまでで、その計算結果を使って3Dオブジェクトを表示するためには別途Papervision3Dなどの3Dライブラリが必要になります。現在FLARToolKitが対応しているのはPapervision3D(rev.815以降)だけですが、近日中にAway3D 2.3への対応も予定しています。

FLARToolKitは日本最大のFlash/ActionScriptオープンソースコミュニティ、Spark projectに参加しています。最新版のソースコードはリポジトリからダウンロード可能ですFLARToolKitのページはこちら⁠。

ライセンス

ライセンスは移植元のARToolKitがGPLで公開されているため、必然的にFLARToolKitもGPLでの配布となります。

また、GPLではソースコードの公開が必要であったため、企業サイト等には導入しづらかったのですが、2月16日にARToolKitの開発元のARToolworks,Inc.からFLARToolKitとNyARToolkit向けの商用ライセンスが発表されました。この商用ライセンスを利用すればソースコードの公開は必要ないため、企業のキャンペーンサイトなどにも導入しやすくなったと思います。

FLARToolKitの仕組み

FLARToolKitを使うまえに、FLARToolKitの仕組みを解説しておきましょう。

FLARToolKitはどのようにして実写内の空間を認識するのでしょうか。ヒントはマーカーと呼ばれる特徴のある画像です図1⁠。

図1 FLARToolKitで利用するマーカー
図1 FLARToolKitで利用するマーカー

マーカーでは、黒い四角い枠のなかに任意の絵柄を描きます[2]⁠。FLARToolKitは実写内に写ったマーカーを見つけて、そのマーカーが3次元的にどの方向を向いているのかを計算する、という仕組みになっています。そのため、まったく何もない空間だけでは認識できません。必ずマーカーが必要になります。

FLARToolKitをさわってみよう

FLARToolKitを使用するうえで、準備するものは以下ものです。

まず、なにはともあれFlash。FLARToolKitはActionScript3.0で書かれているため、Flash CS3以降が必要です(実際には.flaには素材的なものは何も含まれていないので、Flex BuilderやFlashDevelopでも簡単にできます⁠⁠。

次にWebカメラ。Flashから使えるものであれば安いものでも問題ありませんが、露出補正機能がついているもののほうが明るさの変化に対応してくれて認識しやすくなるのでおすすめです。

そしてFLARToolKitスタートキット。これは僕のブログの記事FLARToolKitスタートアップガイドのためにファイル一式をまとめたものですが、必要なファイルがまとまって入っているので今回も手始めにこのデータを使います。

最後にマーカー。スターターキットにflarlogo-marker.pdfというのが入っているので、適当な紙に拡大縮小せずにそのままのサイズ(80mm×80mm)で印刷してください。厚めの紙のほうが曲がったりしなくてよいのでおすすめです。

FLARToolKitスタートキットを利用した手順

それでは、始めます。

  1. SimpleCube.flaを開きます。
  2. Ctrl+Enter(MacならCommand+Enter)でパブリッシュプレビューします。
  3. カメラ画像が表示されるのを確認。表示されてない場合はカメラを選び直す必要があるので、ステージを右クリックしてコンテキストメニューから「設定⁠⁠、カメラアイコンの描いてあるタブを選んで、プルダウンから適当なものを選択してください。MacBookなどの内蔵カメラは「USB Video Class Video」という名前です。また、カメラ設定の詳しい説明はAdobeのサイトを参考にしてください。
  4. カメラからの映像が映ったら、カメラの前に印刷しておいたマーカーをかざします!

すると、図2のような感じでマーカーの上にピンクのCubeが乗って表示されます! 現実が拡張されてます! マーカーを動かしてもピッタリくっついてきますムービーで見てみる⁠。

図2 ピンクのCubeが乗っているように表示される
図2 ピンクのCubeが乗っているように表示される

上手に認識されないときは部屋の照明を明るくしてみてください。光が反射して黒い部分が光ってしまっていてもダメです。白と黒のコントラストがはっきり出るようにしてみましょう。

FLARToolKitの座標系

このサンプルの中身を説明する前に、まずFLARToolKitの座標系の説明をしておきます。Papervision3Dは左手座標系、つまり画面右方向をX軸、上方向をY軸としたときに画面奥へ向かう方向がZ軸になります図3⁠。

図3 Papervision3Dは右方向がX軸
図3 Papervision3Dは右方向がX軸

これに対して、FLARToolKitのマーカー上での座標も左手座標系なのですが、図4のように上方向がX軸、右方向がY軸、そして手前方向がZ軸となっています。

図4 FLARToolKitは上方向がX軸
図4 FLARToolKitは上方向がX軸

これを忘れてしまうと混乱するので、しっかり覚えておいてください。

SimpleCube.flaの中身

さて、実際のActionScriptはどんなふうになっているのか中身をみてみましょう。ActionScriptのコードはSimpleCube.flaのDocument Classに設定されているSimpleCube.asにすべて書かれています。以下がその内容です。

リスト1 SimpleCube.as
package {
 
  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.primitives.Cube;
  import org.papervision3d.objects.primitives.Plane;
 
  public class SimpleCube extends PV3DARApp {
    
    private var _plane:Plane;
    private var _cube:Cube;
    
    public function SimpleCube() {
      // カメラ補正ファイルとパターン定義ファイルのファイル名を渡して初期化。
      this.init('Data/camera_para.dat', 'Data/flarlogo.pat');
    }
    
    protected override function onInit():void {
      super.onInit(); // 必ず呼ぶアル。
      
      // マーカーと同じサイズをPlaneを作ってみる。
      var wmat:WireframeMaterial = new WireframeMaterial(0xff0000, 1, 2); // ワイヤーフレームで。
      this._plane = new Plane(wmat, 80, 80); // 80mm x 80mm。
      this._plane.rotationX = 180; // 裏向いてるのでこっち向ける。
      this._baseNode.addChild(this._plane); // _baseNodeにaddChildするとマーカーに追従する。

      // ライトの設定。手前、上のほう。
      var light:PointLight3D = new PointLight3D();
      light.x = 0;
      light.y = 1000;
      light.z = -1000;
      
      // Cube を作る。
      var fmat:FlatShadeMaterial = new FlatShadeMaterial(light, 0xff22aa, 0x75104e); // ピンク色。
      this._cube = new Cube(new MaterialsList({all: fmat}), 40, 40, 40); // 40mm x 40mm x 40mm。
      this._cube.z = 20; // 立方体の高さの半分、上方向(Z方向)に移動させるとちょうどマーカーにのっかる形になる。
      this._baseNode.addChild(this._cube);
    }
  }
}

FLARToolKitのコードというよりPapervision3Dのコードになっています[1]⁠。FLARToolKitの初期化などはSimpleCubeクラスの親クラスであるPV3DARAppクラス(の親クラスのARAppBaseクラス)がすべて行っているので、PV3DARAppクラスを使った場合はFLARToolKitの存在をほとんど意識せずにコーディングできます。

コードの中身を詳しくみていきましょう。

17行目
this.init('Data/camera_para.dat', 'Data/flarlogo.pat');

17行目で、まずinitを呼び出して初期化します。第1引数はカメラ補正ファイルへのパスを指定します。カメラ補正ファイルにはレンズの歪みなどの情報が入っていて、本当は使用するカメラごとにキャリブレーションしたデータを使うほうが精度が高くなるのですが、ここでは簡易にARToolKitに付属しているデータを使います。Webカメラはどれも似たようなものなのでこれでもほとんど問題ありません。

第2引数はマーカーのパターン定義ファイルを指定します。これは使用するマーカーに対応するパターン定義ファイルを指定する必要があります。ここではflar-marker.pdf用のflarlogo.patを指定しています。

20行目
protected override function onInit():void {

init呼んだ後、初期化が問題なく終わると最終的にこの関数が呼び出されます(20行目⁠⁠。3Dオブジェクトの生成などは、この中ですればよいでしょう。パターンファイルが存在しなかったりWebカメラが接続されてないと、これが呼ばれるまでにエラーが発生します。

24, 25行目
var wmat:WireframeMaterial = new WireframeMaterial(0xff0000, 1, 2);
this._plane = new Plane(wmat, 80, 80);

24、25行目では、マーカーが正常に認識できているか確認しやすいように、マーカーと全く同じサイズのPlaneを作っています。Planeコンストラクタの第2、第3引数で指定している80というのがマーカーと同じサイズの80mmになります。

最初にマーカーを正しいサイズで印刷しておいてくださいと説明したのは、サイズ合わせがしやすいようにという意味だったのでした。

26行目
this._plane.rotationX = 180;

26行目で、Planeはデフォルトで-Z方向を向いているので+Z方向に回転させます。

27行目
this._baseNode.addChild(this._plane);

27行目を見てください。通常、Papervision3DではScene3DにaddChildしますが、FLARToolKitではマーカーに追従して3Dオブジェクトを動かすために特別なノードにaddChildする必要があります。それが_baseNodeです。これにaddChildすることで自動的にマーカーに追従して動くようになります。

36, 37行目
var fmat:FlatShadeMaterial = new FlatShadeMaterial(light, 0xff22aa, 0x75104e);
this._cube = new Cube(new MaterialsList({all: fmat}), 40, 40, 40);

36、37行目で、マーカーの上にピンク色のCubeを乗せています。サイズは40mm×40mm×40mmです。これはちょうどマーカーの半分のサイズですね。

38行目
this._cube.z = 20;

Cubeは原点中心に作られるので、+Z方向に20mm移動させます(38行目⁠⁠。これにより、マーカーにちょうど乗っているようになります。

まとめ

このサンプルが理解できれば、いろいろなオブジェクトをマーカー上に出すことは簡単にできます。次回はこのサンプルをベースに外部のモデリングデータを使って遊んでみたいと思います。

おすすめ記事

記事・ニュース一覧