ARgil(あーじる) version 0.1.3

ARgil(あーじる)ってなに?

(注意!) 公開したてのため、ドキュメントは作り途中の部分が多いです。ご了承ください

ARgilとは、ARToolkitを利用したAR(Augmented Reality: 拡張現実)実行プラットフォームです。

もともと、ARであずにゃんペロペロ(^ω^)したい!と思ってARToolkitやらMMDやら手を出したのがきっかけで作りはじめたものですが。
なんだか他のものもペロペロできそうな気がしてきたので公開してみました。


ARを使ったアプリケーションは、ARToolkitなどのライブラリによって、プログラミングの知識さえあれば簡単に作成できるようになりつつあります。そのため、これらを利用したアプリケーションが登場してきており、プログラミングの知識がまったくなくても、とりあえずARを体感してみることはできるようになっています。
しかしながら、少し複雑なARコンテンツ、例えば、マーカーを複数使ってそれらを連携させるようなものを作成しようとした場合には、ARToolkitのようなライブラリや3Dモデルの取り扱いに関するプログラミングの知識が必要となってしまっています。


ARgilは、ARコンテンツの記述にJavaScriptを利用し、スクリプトの(比較的)簡単な知識のみで、気軽にARで遊べるプラットフォームを実現しようと考えています。直接ARToolkitのようなものを触りたくはないのだけど、でも簡単な動きなどは記述して試してみたい、という微妙なところを狙ったプラットフォームです。

特に以下の点を意識しています。

  • ARの基本機能を備える - ARToolkitによるマーカー検出機能
  • 世の中の3Dモデルが簡単に利用できる - MMD,MQO表示機能
  • 映像を超えた展開もできる - iTunes連携機能

もともと自分が遊ぶ&3Dのお勉強用に作りはじめたプラットフォームですが、なにか、このプラットフォームで遊べることがみつけられたらすごくうれしいです。

サンプル

ARgilでは、パターンを読み込み、そのパターンに対するイベントハンドラを
記述するという形式を採用しています。
こんな風に:

// demo.js: デモスクリプト

printLine("初期化開始");

// カメラの関連付け
window.initVideo("WDM_camera_flipV.xml");
// カメラパラメータに基づいてウィンドウ初期化
window.initWindow("camera_para.dat");

// dllはexeとの相対パスで指定
plugins.load("argmmd.dll", "MMD");
plugins.load("argitunes.dll", "iTunes");

printLine("初期化完了");

var itunes = iTunes;

// 再生対象のトラック名
var trackName = "「超時空飯店 娘々」CM";


var pattern = null;

var worldA = window.addWorld();
var currentMMDA = null;
// 倍率x5でMMDモデルをロード
var mmdObj = worldA.loadMMD("mmd/中野梓.pmd", "mmd/azunyan207.vmd", 4.0, function(source, result){
    if(result == 0) {
        // 成功
        printLine("Loaded");
        currentMMDA = source.params;
        if(currentMMDA != null) {
            // あずにゃんモデルの場合は腕IKを無効化
            for(var i = 0; i < currentMMDA.ikCount; i ++) {
                var name = currentMMDA.ikTarget(i);
                if(name.indexOf("腕") > 0) {
                    currentMMDA.setIKEnabled(i, false);
                }
            }
            currentMMDA.fps = 25.0;
            source.clock = iTunesClock;
        }
    }else{
        // 失敗
        alert("Failed");
    }
    });
mmdObj.rotate = {angle: 90.0, x: 1.0, y: 0.0, z: 0.0};

// "A"パターンの読み込み
// data/patt/pattMulti.pdfを印刷してください
pattern = window.loadPattern("patt/patt.a");
// Aパターンの1辺は40mm
pattern.width = 40.0;

// パターンを発見した時の処理
pattern.onfound = function(ev)
{
    printLine("onfound: A");
    refreshMMD(currentMMDA);
    
    worldA.translate = ev.translate;
    worldA.visible = true;
};

// パターンを見失った時の処理
pattern.onlost = function(ev)
{
    printLine("onlost: A");
    
    worldA.visible = false;
};

// パターンの位置が変化した時の処理
pattern.onchanged = function(ev)
{
    window.status = "onchanged: A";
    refreshMMD(currentMMDA);
    
    worldA.translate = ev.translate;
};

// モデルを更新します。
function refreshMMD(model)
{
    if(model != null) {
        if(model.playing == false) {
            printLine("Play");
            model.play(model.fps * -6);
        }else if(model.currentFrame >= model.maxFrame) {
            printLine("Replay");
            model.play(model.fps * -6);
        }
    }
}

var worldB = window.addWorld();
// 40mm浮かせる
var containerB1 = worldB.addContainer();
containerB1.translate = {x: 0, y: 0, z: 40.0};
containerB1.visible = true;
// 90°回転
var containerB2 = containerB1.addContainer();
containerB2.rotate = {angle: 90.0, x: 1.0, y: 0.0, z: 0.0};
containerB2.visible = true;
// 90°回転
var containerB3 = containerB2.addContainer();
containerB3.rotate = {angle: 90.0, x: 0.0, y: 1.0, z: 0.0};
containerB3.visible = true;

// 画像の読み込み: 表示幅は40mm
var imageB = containerB3.loadImage("png", "image/nyanfro.png", 40.0, 
    function(source, result){
        var targetPath = "image/nyanfro.png";
        if(result == 0) {
            // 成功
            printLine("Loaded: " + targetPath);
            // 半透明に変更
            source.props.alpha = 0.9;
        }else{
            // 失敗
            alert("Failed: " + targetPath);
        }
    });

var targetTrack = null;
var notFound = false;

// "B"パターンの読み込み
// data/patt/pattMulti.pdfを印刷してください
pattern = window.loadPattern("patt/patt.b");
// Bパターンの1辺は40mm
pattern.width = 40.0;

// パターンを発見した時の処理
pattern.onfound = function(ev)
{
    printLine("onfound: B");
    
    worldB.translate = ev.translate;
    worldB.visible = true;
    
    // 再生開始
    if(notFound) {
        return;
    }
    if(targetTrack == null) {
        targetTrack = findTrackFromSourceCollection(iTunes.Sources, trackName);
        if(targetTrack == null) {
            alert("Not found: " + trackName);
            notFound = true;
            return;
        }
    }
    targetTrack.Play();
};

// パターンを見失った時の処理
pattern.onlost = function(ev)
{
    printLine("onlost: B");
    
    worldB.visible = false;
    
    // 一時停止
    iTunes.Pause();
};

// パターンの位置が変化した時の処理
pattern.onchanged = function(ev)
{
    window.status = "onchanged: B";
    
    worldB.translate = ev.translate;
};

// トラックを検索します。
function findTrackFromSourceCollection(sources, name)
{
    for(var i = 0; i < sources.Count; i ++) {
        var source = sources.Item(i+1);
        
        var result = findTrackFromSource(source, name);
        if(result != undefined) {
            return result;
        }
    }
    return undefined;
};

// トラックを検索します。
function findTrackFromSource(source, name)
{
    var playlists = source.Playlists;
    for(var i = 0; i < playlists.Count; i ++) {
        var playlist = playlists.Item(i+1);
        
        var result = findTrackFromPlaylist(playlist, name);
        if(result != undefined) {
            return result;
        }
    }
    return undefined;
};

// トラックを検索します。
function findTrackFromPlaylist(source, name)
{
    var tracks = source.Tracks;
    return tracks.ItemByName(name);
};



MMDモデルなどはARgilパッケージには含まれていませんので、
実際に動かしてみるためには基本的なスクリプトの作成を参照してください。

こんな感じで動きます。編集が適当ですけど雰囲気が伝われば・・・!

素材は以下のものを使わせていただいてます。

追記

と、真面目に書いてきましたが、なんかこう少しでもこれでARで二次元キャラをぺろぺろできる人が増えることを祈っています(白目)

ダウンロードして動かしてみる

ダウンロードしてとりあえず動かしてみる。

リファレンス

だんだんと充実させていく予定。
リファレンスはとりあえず項目をあげただけです。

TODO

変更履歴



Copyright(C) 2010 やざわラボ
Powered by Carabiner BEITEL