Edited at

虚無なXmasをARで彩る


初めに(追記)

今回製作した物の動作デモです。

長い上まとまりのない記事を読む前に、

デモを最初にご覧ください!なんと優しい :sob:

こちらをクリックするとYouTubeに飛びます。


生徒です


挨拶

今年も残り僅か.2019年目前です.皆さん元気にお過ごしでしょうか :thinking: 僕は色々なことにに追われ,ゲッソリ元気ハツラツです :blush: :exclamation: 必死にアドカレ記事を書いて心臓バクバクです :sweat:

今は新年の他にクリスマスも目前という訳でして,今回はクリスマスネタです(それしか思いつきませんでした)また,言い訳蒲しいのですが,個人的な用事や仕事等で時間が足りなかったので,今回はかなり妥協した開発になっています :cry: 不完全燃焼です :fire:

さて,本日の献立です :yum: :fork_and_knife:



  • 序章 : アイデアと技術の紹介


  • 本論 : 実際に作ってみた


  • 終章 : 開発から得られた情報


  • おまけ



開発したものだけを見たい方は,序章は読み飛ばして貰ってOKです :exclamation:

本論は中身を知りたい方だけが読めばいいと思います :smile:


序章 - アイデアと技術の紹介

今回は「クリスマス」というテーマを最初に設けました.

そこで僕は,Webで動作するARコンテンツを考えつきました.


アイデアの話

今回適当に20日を選び,そこから「クリスマス近いじゃん、これしかない」と決めた感じです.その御蔭で,テーマは速攻確定したので,アイデアをゆっくり考えました.


当初の予定

最初のアイデアは出先でスマホにちまちまメモしてました.

当初の予定は以下の通りでした.


・拡張現実イルミネーション

スマホ、PC両方で動作するもの

・フローイメージ

①植物を写す

②葉の部分を認識させる

③ARでイルミネーションを描画する

・技術的な部分

①Webカメラの起動

 ・JavaScriptを用いる

②画像解析、認識

 ・Pythonを使った機械学習

 ・OpenCVとやらを用いる


スマホに入ってたメモをコピペしました.見てわかるのですが,サーバーを用意して,サーバー側で画像解析を行わせる予定でした.しかし,このアイデアは現実的にキツく(とにかく時間が無く)すぐに諦めて路線変更しました :cry:


路線変更

何とかAR技術を(使い|覚え)たい思いがあったので,根本の拡張現実のアイデアは継承することにしました.この段階でARを扱うにあたって2つ問題点がありました.



  • 慣れない言語,慣れない開発形態

  • 未対応の機種が数多く存在する


自分が慣れない新しい環境での開発を成し遂げられるのかという問題と,多くの環境で動作させることが出来ない問題でした.しかし,この問題は「「「僕とAR.jsの,運命的な出会い」」によって解決しました.


AR.js is 何 :thinking:

* JavaScript製のマーカー認識型ARライブラリ


つまり



  • 僕が一番慣れている言語JavaScriptのライブラリ :v:


  • マーカー認識を使うので,殆どの環境で動く :v:


これで2つの問題が解決出来ました :v: :v:


新たなアイデア

僕はこの運命的な出会いを果たしたお陰で,アイデアを練り直す時間が与えられました.そこで考えていた物を紹介します.


その1


マーカー上にプレゼントボックスを表示させ,タップするとランダムでアイテムの出現するガチャ


文章の通りガチャが引けます,クリスマスガチャです.然し時間が足りず断念してしまいました.このアイデアは今すぐにでも実装したいアイデアですので,もしかしたら近日中に追加実装するかも知れません.


その2


マーカー上に冬をイメージした小さな世界を描く


今回採用したアイデアです.

いよいよクリスマス要素が薄れてきましたが気にしてはいけません :exclamation: :exclamation: :exclamation:

少しでもクリスマス要素が欲しかったので,申し訳程度にプレゼントボックスを散りばめましたので,これで何の問題はないと思います(前言撤回)


技術紹介

ここからは今回活用した技術達の大まかな紹介です.



  • ar.js

  • three.js

  • blender


以下ざっくり動作フローの紹介です.



  1. 検出したいマーカーデータ(*.patt)を用意


  2. three.jsを用いてblenderで作成したオブジェクトを読み込む. 

  3. 読み込んだオブジェクトは1.にリンクしたグループに追加

  4. Webカメラ起動しテクスチャとして描画

  5. マーカー上のオブジェクトを描画


今回はカスタムマーカーをillustratorで作成し,マーカーに変換しました.

またオブジェクトはblederで自分でモデリング+UVマップをしました.

あとは云々して描画させるだけです.


本論 - 実際に作ってみた

さて,いよいよ僕が作ったものの紹介です.本当に不完全燃焼で色々ギミックを付け加えたかったのですが,締め切り直前まではこれが限界でした.以下のリンクを開くと実際の動作を確認できます.

マーカーは以下の画像です.

※画像をクリックするとGitHub Repository上の画像に飛びます.

**Marker Image**

こちらを印刷あるいは画面に表示させ,カメラで写します.画面上の場合,光の反射などで認識しずらい場合があります.また紙面に印刷した際も,紙が湾曲し過ぎないように気をつけてください.また,マーカーを複数表示せると正常に動かない(はず)です.

マーカーを正常に認識すると,このようになるはずです.

**Success Render**

冬の世界を小さく圧縮した簡単なアニメーションが再生されるはずです.イメージはスノードームです.(こちらを友人に見せたところスノードームと言う的を射た回答をもらったので使わせてもらってます :blush: )


ここからは技術紹介で書いた簡単なフローやその他仕組みに関してを細かく説明していきます.興味ないと言う方は読み飛ばして終章にを見ても構いません.


読み込んでいるjsファイルについて

まず,こちらがindex.htmlのファイルです.


index.html

<script src="./js/three.min.js"></script>

<script src="./js/GLTFLoader.js"></script>
<script src="./js/ar.min.js"></script>
<script src="./js/main.js"></script>

これは上から順にこの様になっています.



  • three.jsの本体


  • three.jsでgLTFを読み込む為のscript


  • ar.jsの本体

  • 自分で記述したscript

three.jsar.jsは良いかと思いますが,「「GLTFLoader.js is 何 :thinking:」」ですよね.これはBlenderのオブジェクトを読み込むために使っています.

詳しくは次の項目で説明します.

main.js内にある,こちらのコードがオブジェクトの一つを読み込んでいる箇所です.


main.js

let loader = new THREE.GLTFLoader();

loader.load('./ar/model/ground.glb', data => {
let size = 0.2;
let object = data.scene;
object.scale.set(size, size, size);
object.position.set(0, 0, 0);
marker.add(object);
});

loaderに対してTHREE.GLTFLoader()というオブジェクトを生成し使っています.このGLTFLoaderを呼び出すためには先ほどのGLTFLoader.jsを読み込む必要がある訳ですね.

ちなみに当然ですが読み込む順番も大切です.GLTFLoader.jsar.jsは,共にthree.jsの機能に追加して動作するライブラリですので,必ずthree.jsより後に読み込まなければなりません.もしコンテンツを作成する際は些細なことですが気をつけましょう.(自分も少し引っかかったので)


GLTF is 何 :thinking:

さて一つ前でも触れましたがこのGLTFとは何者かについてです.前述の通りオブジェクトを読み込む物なのですが,少しthree.jsを齧ったことのある方ならこう思う方がいるかも知れません.


ちょっと待って!

その拡張子,*.jsonで良くない?


僕も前にthree.jsでblenderから読み込んだ記憶を元に,jsonで出力して読み込ませるんだろうな〜なんて思って,blenderにアドオンを追加しようとディレクトリを見て見ました.するとなんと言うことでしょう…

https://github.com/mrdoob/three.js/tree/dev/utils/exporters/blender より,


README.md

The Blender exporter for the Three.js JSON format has been removed


と記されてます.どうやら前まで使用されていたthree.js用にjsonを書き出すアドオンが廃止されたようです.

しかし,有難いことにthree.jsは多くの3Dオブジェクトの拡張子に対応しています.そこで右往左往した結果gLTFと言う拡張子にたどり着きました(長いので省略)

ここで先程も載せた地面のオブジェクトを読み込むコードをもう一度見てみましょう.


main.js

let loader = new THREE.GLTFLoader();

loader.load('./ar/model/ground.glb', data => {
let size = 0.2;
let object = data.scene;
object.scale.set(size, size, size);
object.position.set(0, 0, 0);
marker.add(object);
});

ここで一つ注意点があります.gLTFではSceneに含まれる全てのオブジェクトが含まれます.また,ローダーで読み込んだデータがSceneのデータではなく,Sceneのデータを含む一つのオブジェクトであることを忘れないようにして下さい.4行目にあるように,


main.js

let object = data.scene;


読み込んだデータからSceneだけを取り出す必要があります.忘れるとエラーで怒られます.気をつけましょう :cry: そしてScene全体が出力されるため,複数のオブジェクトがあると全てが表示されます.例えば試行錯誤したモデルが散らばったblendファイルで書き出すと,その全てが凝縮されthree.jsで描画を行うと全てのオブジェクトが表示されます.

ですので今回僕は,家,木,等のオブジェクトをそれぞれ別々のファイルで制作し,一つのblendファイルには一つのオブジェクトのみが含まれる状態にして書き出しました.

またオブジェクトの大きさに関してですが,地面では


main.js

let size = 0.2;

object.scale.set(size, size, size);

と記しています.この0.2というマジックナンバーは各オブジェクトによって違います.僕の場合はこの値は目利きで調度いい塩梅を調整しながらそれぞれの値を定めた感じです.そのままのサイズだと大きすぎて画面全体に広がったりしてしまうので,少し注意が必要です.


以下はgLTFを扱うにあたって基本的な部分です.導入から色の付け方までを記しておきます.


gLTFアドオンどこ〜 :cry:

https://github.com/KhronosGroup/glTF-Blender-Exporter

こちらのリンク先にあります.

https://github.com/KhronosGroup/glTF-Blender-Exporter/tree/master/scripts

こちらのREADME.md参考に導入すればOKです :wink:


gLTFで色が付けられないよ~ :cry:

Blender側でMaterialをノードで作る必要があるのですが,ただ単にノードエディタで組めばいいというわけじゃないんです.これにはgltf metallic roughnessという特殊なノードが必要になります.

https://github.com/KhronosGroup/glTF-Blender-Exporter/tree/master/pbr_nodeこちらからglTF2.blendをダウンロードします.そして,色を付けたいオブジェクトファイルを開き,ファイルからリンクを選択します.

リンクを押すとファイルを選ぶ画面が表示されるので,先程ダウンロードしたglTF2.blendを開き,NodeTreglTF Metallic Roughnessの順番で選択し,ライブラリからリンクを押します.

そうすると,ノードエディタ上でgltf metallic roughnessが使用できるようになります.このノードの一番上のBaseColorに基本色(その名の通り)を入れると,オブジェクトに反映させることが出来ます.またこの状態でgLTFでエクスポートすると,無事に色付きで出力できます.やったね :exclamation: :exclamation:

因みに,テクスチャの場合は通常通りにUV展開し,テクスチャを作成した後に,画像テクスチャでテクスチャを読み込みBaseColorに接続すればテクスチャを反映させることが出来て,幸せになります :blush:


カスタムマーカーの作成

次はカスタムマーカーを作る方法です.非常に簡単にできます.

まず最初に,任意の画像編集ソフトで任意の図形を描画し,pngjpeg等で保存します.

次にhttps://jeromeetienne.github.io/AR.js/three.js/examples/marker-training/examples/generator.htmlにアクセスし,UPLOADから作成した画像を読み込みます.

最後にDOWNLOAD MARKERでマーカーデータである*.pattファイルをダウンロードし,DOWNLOAD IMAGEでマーカーの画像を保存します.これだけ.


終章 - 開発から得られた情報

今回の開発を通しての感想ですが,とりあえず動いたときの感動が大きかったです.

特にgLTF様様でBlenderから任意にオブジェクトをMaterialと共に出力できるのが大きいと感じました.

また細かな箇所ですが,似たような開発を行う方に向けての(当たり前の)アドバイスを幾つか置いておきます.



  • マーカーは必ずアシンメトリーに


最初に作ったマーカーをシンメトリーにしてしまいました.

当然なのですが方向が一定になってしまうので気をつけましょう.



  • オブジェクトのスケーリングを忘れずに


これは気をつけるというより慌てないでって感じですね.大丈夫だとは思いますがオブジェクトがおかしいのではなくサイズが巨大過ぎて表示がおかしい事があるのでという感じです.



  • メモリクラッシュに気をつけて


これなんですが,当初雪を積もらせるために愚直に球体を削除せずに地面上で停止させたらメモリ落ちしたよっていう話です.オブジェクトを作りすぎると直面するかと思いますので,ぜひ気をつけて下さい.


おまけ

AR.js練習中,MMDモデルを読み込んでみてと友人に頼まれて読み込んだ文香.

モデルはこちらhttps://ch.nicovideo.jp/sibainu/blomaga/ar1151600

Fumika

因みにこれが文香を表示させたら発狂した友人.

Hakkyo

MMD表示できた祝にプロ生ちゃんを表示させてみた.

モデルはこちらhttps://3d.nicovideo.jp/works/td8608

PuronamaChan

木のモデリング中,木にかぶった雪だけを残してみたらエモくなったよって話.

EmoiTree

これはおうちのモデリング中に良い感じになったから撮ったよっていうスクショ.

House

gLTFが読み込めた歴史的瞬間のスクショ.

Rekisiteki


以上です.最後までありがとうございました :blush: