Make

Web上でもARでミクさんを踊らせたい

Make
この記事は約12分で読めます。
スポンサーリンク

最近、自分の中でAR(拡張現実)が再ブレイク中です

はじめは三年前ぐらいに流行り、Unituyを使ってARを挑戦しました

AndroidでAR(拡張現実)をする [オブジェクの生成編]
アンドロイド端末でARをする方法を調べると色々出てきますが、自己流のやり方をまとめました 参考にしてもらえると嬉しいです

デバイスごとにアプリを作り直さなければならない点がどうしても開発に煩わしさを感じてしまい、一気にブレイクが去っていきました

しかし、Web上でもARができるようになったよ!というニュースをみて改めて挑戦をしてみました

挑戦をした結果、Web上にてARでミクさんを踊らせることができたので記事にします

デモ

解説云々を入れる前に先にデモを記述します

 

Lat式ミクに”地球最後の告白を“を踊らせています

ARマーカーをカメラに近づけるとミクさんが踊ってくれます

著作権の問題で音楽は流れません

 

手持ちのスマホやパソコンでも下記のサイトにて体験ができます

下のマーカー(Hiro Marker)を認識させてください

参考:https://commons.wikimedia.org/wiki/File:Hiro_marker_ARjs.png

 

体験するときに、スマートフォンの場合は下記のURLをコピーしてからブラウザで起動してください

また、iPhoneの方はsafariにてアクセスをしてください

Miku WebAR

使用したライブラリ

本プログラムはThree.jsとAR.jsを用いて作成をしています

Three.jsとは

Three.jsとは、ウェブブラウザ上にて簡単にCGを描画することができるJavaScirptのライブラリです

これを使うことで簡単に3Dコンテンツを作ることができます

Three.js – JavaScript 3D Library

 

このライブラリの主にMMDを取り扱うための関数を使っていきます

three.js examples

AR.jsとは

AR.jsとは、ウェブブラウザ上で簡単にARをすることができるJavaScirptライブラリです

また、非常に高速に動作することができるだけではなく、AndroidやiOS、windowsといったあらゆるプラットフォームで動作することが可能です

AR.js/README.md at master · jeromeetienne/AR.js
Efficient Augmented Reality for the Web - 60fps on mobile! - AR.js/README.md at master · jeromeetienne/AR.js

プログラム

プログラムはすべてGitHubに掲載しています

GitHub - Momijinn/myWebAR_MMD: WebアプリでもMMDを踊らせたい
WebアプリでもMMDを踊らせたい. Contribute to Momijinn/myWebAR_MMD development by creating an account on GitHub.

 

プログラムにて重要なのはindex.js(staitc/js/index.js)です

コメントアウトにて解説をいれているので、本記事では重要な箇所や開発中に困ったことを記載します

Hiroマーカーの使用

本プログラムはARのサンプルでよく使われているHiroマーカーを使い、このHiroマーカーを認識したらミクさんを召喚しています

サンプルを参考にして記述をしたのですが、マーカーを認識してくれませんでした

ネットで探してみると解決策が見つかり、どうやら”HREEx.ArToolkitContext.baseURL“の場所を変えろよということでした

link THREEx.ArToolkitContext.baseURL to local three.js folder · Issue #50 · jeromeetienne/AR.js
why not to change THREEx.ArToolkitContext.baseURL = ' for local three.js folder in aframe-ar.js? could be better for offline demos.

 

index.htmlにURLを変更する記述をしています

 <script>THREEx.ArToolkitContext.baseURL = 'https://jeromeetienne.github.io/AR.js/three.js/'</script>

 

Hiroマーカーは以下からダウンロードできます

https://commons.wikimedia.org/wiki/File:Hiro_marker_ARjs.png

MMDのスケールの縮小

MMDをインポートしたあとそのままマーカーへ投影するとミクさんがとてつもなく大きく投影されます

そのため、ミクさんの大きさを変換してあげます

 

私はObject3Dを作成し、そのなかにMMDのデータを追加後、追加したObject3Dを縮小するようにしました

new THREE.MMDLoader().loadWithAnimation( modelFile, vmdFiles, function ( mmd ) {
    mesh = mmd.mesh;

    // 3dobject
    var model = new THREE.Object3D();
    // Scaleの変換
    model.scale.x = 0.1;
    model.scale.y = 0.1;
    model.scale.z = 0.1;
    model.add(mesh);

   marker.add(model);

    //以下略
});

 

一応mmd.meshにもスケールを変換するための変数(scale.set)を持っています

一度以下のように追加してプログラムを動かしてみたのですが、初期状態時にミクさんのスカートが飛び跳ねて食い込んでいたのでobject3dを使用しました

new THREE.MMDLoader().loadWithAnimation( modelFile, vmdFiles, function ( mmd ) {
    mesh = mmd.mesh;

    mesh.scale.set(0.1, 0.1, 0.1);
    marker.add(mesh);

    //以下略
});

下記のように初期状態にてスカートが跳ね返り、食い込みます

 

レンダリング

Web上にてレンダリングをするにはrequestAnimationFrame()を呼び出して描画をします

本プログラムにもrequestAnimationFrame()を入れているのですがコメントアウトし、setIntarvalにて描画をしています

理由として、requestAnimationFrame()にするとミクさんが汚く描画されたためです

 

requestAnimationFrame()について詳しく追えてはいないのですが、setIntarvalでやったほうが綺麗にミクさんが描画されたのでこちらを採用しました

//Render
// function renderScene() {
//   requestAnimationFrame(renderScene);
//   if(source.ready === false){ return; }

//   context.update(source.domElement);
  
//   if(ready){
//     helper.update(clock.getDelta());
//   }

//   // renderer.render( scene, camera );
//   effect.render( scene, camera );
// }

setInterval(function(){
  if(source.ready === false){ return; }

  if(ready){
    helper.update(clock.getDelta());
  }

  renderer.render( scene, camera );
  context.update(source.domElement);
}, 1000 / 60); //60fps

requestAnimationFrame()で動かしたい場合は、function renderScene()のコメントアウトを外し、Index.jsの冒頭付近にあるrenderScene()のコメントアウトも外すします

そのあと、setInterval()内をコメントアウトするとrequestAnimationFrame()で動作します

 

左がsetInterval()での描写で左がrequestAnimationFrame()での描写です

requestAnimationFrame()が髪の毛の影?が強くなっている

音楽再生

冒頭にてデモは音楽を再生することができないと記述しました

しかし、音楽データをいれてコメントアウトされている部分を外すと音楽も再生することができます

 

まず、”static/mmd/music/”に”地球最後の告白を”の音源をmusic.mp3にリネームして配置します

(Amazonにて販売をしています:https://amzn.to/2ODiMzm)

つぎに”staitc/js/index.js”にて,”new THREE.MMDLoader().loadWithAnimation”内に入っている音楽を再生する箇所のコメントアウトを外します

before

helper = new THREE.MMDAnimationHelper( {
    afterglow: 2.0
});
    
new THREE.MMDLoader().loadWithAnimation( modelFile, vmdFiles, function ( mmd ) {
    mesh = mmd.mesh;

    // 3dobject
    var model = new THREE.Object3D();
    // Scaleの変換
    model.scale.x = 0.1;
    model.scale.y = 0.1;
    model.scale.z = 0.1;
    model.add(mesh);

    helper.add( mesh, {
    animation: mmd.animation,
    physics: true,
    });

    //add maker
    marker.add(model);
    
    //Audio
    // new THREE.AudioLoader().load(audioFile, function(buffer){
    //   var listener = new THREE.AudioListener();
    //   var audio = new THREE.Audio( listener ).setBuffer( buffer );

    //   listener.position.z = 1;
    
    //   helper.add( audio, audioParams );
    //   marker.add( listener );

    //   // Music Load Flag
    //   ready = true;
    // });
    ready = true;


}, onProgress, onError );

 

after

helper = new THREE.MMDAnimationHelper( {
    afterglow: 2.0
});
    
new THREE.MMDLoader().loadWithAnimation( modelFile, vmdFiles, function ( mmd ) {
    mesh = mmd.mesh;

    // 3dobject
    var model = new THREE.Object3D();
    // Scaleの変換
    model.scale.x = 0.1;
    model.scale.y = 0.1;
    model.scale.z = 0.1;
    model.add(mesh);

    helper.add( mesh, {
    animation: mmd.animation,
    physics: true,
    });

    //add maker
    marker.add(model);
    
    //Audio
    new THREE.AudioLoader().load(audioFile, function(buffer){
    var listener = new THREE.AudioListener();
    var audio = new THREE.Audio( listener ).setBuffer( buffer );

    listener.position.z = 1;
    
    helper.add( audio, audioParams );
    marker.add( listener );

    // Music Load Flag
    ready = true;
    });
    // ready = true; //ここのFlagをコメントアウトする


}, onProgress, onError );

その後、キャシュを削除後index.htmlを開き直すと音楽が流れます

本プログラムのライセンスについて

本プログラムに使用しているMMDやモーションは再配布が問題ないものを使用しています

製作者のLat様とよぴ様に感謝いたします

MMDのライセンス

製作者 : Lat
yhblat@gmail.com
――innoce――

モーションのライセンス

製作者:よぴ
Twitter:@pyopi
Motion:https://www.nicovideo.jp/watch/sm25418510

いろんな端末でやってみた

いろんな端末で本当に動くのかやってみました

手元にあったWindows 10,iOS(iPad pro), Android(ASUS)でやってみました

Android端末だけ多少もっさり感があります

未解決

Webブラウザ上にてARマーカートラッキングしミクさんを踊らせるという目標は達成しました

しかし、最終的にやりたかった「ARマーカーを認識していなければ一時停止」というプログラムが実装できませんでした

音楽は一時停止するのですが、ミクさんは一時停止したあとに再生をすると一時停止した時間分進んだところから踊り始めます

一時停止したところからもう一度再生を始めてほしいのです

解決策をお待ちしています

まとめ

Webブラウザ上にてARマーカートラッキングしミクさんを踊らせるプログラムを作りました

様々な端末でやってみましたがどれも動作することを確認しました

一時停止機能の実装ができない状況なので解決策をお待ちしています

参考

コメント

  1. requestAnimationFrameでの描画はTHREE.OutlineEffectで描画されているので、見た目は違う結果になると思われます。

    effect.render( scene, camera );

    この部分ですね。

    • >がねぶん様
      返信が遅くなり申し訳ございません。

      requestAnimationFrameはTHREE.OutlineEffectで描画されるのですね。
      THREE.OutlineEffectであるため、輪郭がはっきりと描画されると。

      助言ありがとうございます。

タイトルとURLをコピーしました