記事の前提:デジタルツインって何?
現実世界とリンクして、現実世界を再現するバーチャル空間のことです。
デジタルの双子(デジタルツイン)と呼ばれています。
ざっくりとしたジャンルを表す言葉ですので、同じ言葉でもまるで異なる技術のことを指します。
-
シミュレーションツールとしてのデジタルツイン
目的:現実に起こっていないことをバーチャル空間で再現する
例:NVIDIA Omniverse, 災害シミュレータ -
可視化ツールとしてのデジタルツイン
目的:言語化が難しいものに 3D でラベル付けする
例:AWS TwinMaker, Azure Digital Twins - などなど。ほかにもいろいろ
この記事では「デジタルツイン=現実とリンクした3Dの地図コンテンツ」の意味で扱います。
可視化ツールとして、「言語化の難しいものへのラベル付け」を目的とします。
記事の概要
- Wiki や 5ch みたいに、誰もが簡単に編集できる3D地図
の作り方を紹介する記事です。
記事が扱う開発環境とライブラリ
- Draw.io
- three.js
- Cloudflare Workers
技術的なトピックを 3 行で
- コストをかけずにデジタルツインを公開・運用する
- 編集可能な Google Drive 上のファイルを、Web サイトからAjax参照する
- Draw.io から 3D モデル(three.js) に変換するツールを筆者が作ったので紹介
デモサイトで触れる?
以下のサイトで実際に動いているものに触ることができます。
Google Map と同じ操作方法で閲覧できます。
- 飛田の地図(飛田新地をDraw.ioのファイルで3D化したサイトです)
https://tobitamap.pages.dev
- Githubに、編集用のページとプレビュー用のデモページのリンクを置いています。
https://github.com/fuyoneko/dio2town-contents
何が嬉しいの?
デジタルツインは何が嬉しいの?
デジタルツインのメリットに、『言語化できないもの』にラベル付けできることがあります。
デジタルツインはデータを現実世界にひもづけて表現することで、名前がない、言葉で表現しにくい、名前を聞いてもピンとこないものに対して、ラベル付けやトピック付けをすることができます。
それを Draw.io で導入できると何が嬉しいの?
Draw.io で更新できるようになることで、
- ツール不要で修正できるので、誰もがいつでも更新できる
- データストレージも開発環境も不要になるので、安くなる
ようになります。
デジタルツインを Wiki 化できると何が嬉しいの?
オフィスが主体でデジタルツインをやるとしたら、
- 空調のデジタルツイン
- 会議中と人流のデジタルツイン
どうしても堅いプロジェクトになります。席替えやセンサーの入れ替えがあれば更新も手間がかかりますし、「毎回ダッシュボードを立ち上げるほど空調気にする?」があります。
Wiki なら、柔らかい情報をデジタルツインに書き込めます。
- 寒い座席、サーバの音がうるさい座席
- 推しのアニメの食玩が売っているコンビニの場所
- 会社の裏の自販機のラインナップ
- 明日休みますから飲み会の費用は〇〇さんに渡して、みたいなメモ書き
空調も人流に体感が入ることで双方向になりますし、使う人が見たい情報、見せたい情報、知りたい情報、比較的新鮮な情報が集まる場所になります。席替えをしてもすぐに更新できます。
構築してみる
構築の手順は以下の通りです。
- Draw.ioのファイルを共有する
- Draw.io のファイルを作って、 Google Drive に保存する
- ファイル設定の「保存時の圧縮」を無効にする
- 誰でもブラウザ上で編集できるように公開する
- Ajax で Web サイトからDraw.ioの取れるようにするようにする
- Draw.ioのファイルを3D化する
- 読み込んだDraw.ioのファイルを、JavaScriptのライブラリで3D化する
以下のものが必要ですので、あらかじめ用意しておきます。
- Google のアカウント
- Cloudflare のアカウント
手順1:Draw.io のファイル共有する
[1:Draw.io のファイルを作って、 Google Drive に保存する]
Draw.io (https://app.diagrams.net/)をブラウザで開きます。
ファイルの保存先を尋ねられるので、「Google ドライブ」を選択します。
Draw.io(diagrams.net)からGoogle ドライブへのアクセス権限を求められた場合は、3つともにチェックをつけて、Draw.ioからのアクセスを許可します。
[2:ファイル設定の「保存時の圧縮」を無効にする]
初期設定では「属性」→「圧縮」が有効になっているのですが、これを無効にします。
「圧縮」のチェックを外すと保存時の圧縮が無効になります。
[3:誰でもブラウザ上で編集できるようにする]
右上にある「共有」ボタンをクリックします。
ダイアログが出たら、「リンクを知っている全員」に対して「編集者」の権限を設定します。
「リンクをコピー」をクリックして、URLをコピーします。
コピーしたURLは(https)://drive.google.com/file/d/${ファイルID}/view?usp=sharing
のようなフォーマットになっているのですが、末尾が/view
になっています。これを/edit
に置き換えた(https)://drive.google.com/file/d/${ファイルID}/edit?usp=sharing
が編集用のURLになります。
編集用のURLを開くと、誰でもブラウザ上でDraw.ioファイルを編集することができますし、変更した内容はGoogle Driveに即時で反映されます。
この${ファイルID}は後で繰り返し出てくるため、コピーして手元のテキストエディタに置いておきます。
[4:Ajax で Web サイトから取れるようにする]
編集用のURLはあくまでプレビュー画面のURLですので、AjaxでWebアプリから参照するには直接のURLが必要です。直接参照するURL はhttps://drive.google.com/uc?export=download&id=${ファイルID}
になります。
ただ、これをAjaxでウェブサイトから取得しようとするとエラーが出てしまいます。ドメインが違うためです。GoogleはこのURLから別のドメインにリダイレクトをかけているため、CloudfrontやAPI Gatewayの下にGoogle Driveを置くだけでは回避できません。
昔は CORS Anywhere(https://github.com/Rob--W/cors-anywhere )で簡単に解決できたのですが、悪用が多かったらしく、今ではサーバ側から厳しい制限がかけられています。Herokuも有料化したので、別の方法で対応します。
CORS Anywhereと同じものをCloudflare Workersの無料プランで自作します。
Cloudflare Workers(https://www.cloudflare.com/ja-jp/ )の「サービスを作成」で「HTTPハンドラ」のサービスを1つ作ります。
作ったサービスを選んだら、右上の「クイック編集」のボタンを押します。
ソースコードをブラウザ上で編集できます。
ソースコードに以下のソースをコピペして、デプロイします。
addEventListener("fetch", (event) => {
event.respondWith(handleRequest(event.request));
});
async function handleRequest(request) {
const url = new URL(request.url);
const id = url.pathname.replace("/", "");
const corsHeaders = {
"Access-Control-Allow-Origin": "*",
"Access-Control-Allow-Methods": "GET,OPTIONS",
};
const url_response = await fetch(
"https://drive.google.com/uc?export=download&id=" + id
);
const body = await url_response.text();
return new Response(body, {
headers: corsHeaders,
});
}
エディタの右側に検証ツールがあるので、URLの後ろに${ファイルID}をつけてリクエストします。
リクエスト先のURLはこんな感じになるはずです。
https://${workerの関数名}.${プロジェクト名}.workers.dev/${ファイルID}
リクエストに対して、xml形式のDraw.ioデータが返ってきたらOKです
Cloudflare Workers の無料プランには、
- 実行時間(CPU runtime)が 10ms 以内であること
- 1 日あたり 10 万リクエスト以内であること
の制限があります。
ピンとこない表現ですが、CPU runtime はプロセスの待ち時間(例:Google Driveに対してfetchしている間の通信時間など)を除いた時間になります。上記のソースなら 1ms 程度です。
ですので、このために有料プランを導入する必要はありません。
手順2:Draw.io で 3D に必要なデータを設定する
Draw.io は、座標や形、ラベルの文字列のほかに、自由なプロパティを持つことができます
※ショートカットはctrl+Mになります
Rectangle で好きな形を作成したら、プロパティに「type: x-building」を設定します
このデータをあとのライブラリで読み込むと、建物として立体化されます
ライブラリが読み込めるプロパティの例です
プロパティの値 | できるもの |
---|---|
x-building | 建物 |
x-street | 道 |
street-label | 道の上に表示するテキスト |
手順3:取得した Draw.io のファイルを、3D化して表示する
以下のサンプルプロジェクトを参考にしてください。
【githubのプロジェクト】
https://github.com/fuyoneko/dio2town-contents
【index.htmlのソース】
https://github.com/fuyoneko/dio2town-contents/blob/master/docs/tobitamap/index.html
Draw.io を 3D に変換する Javascript のソースは以下の通りです。
ライブラリの読み込みをヘッダに書き込みます。
<script
src="https://cdn.jsdelivr.net/gh/fuyoneko/dio2town@v0.0.1/_bundles/dio-2-town-map.js"
crossorigin="anonymous"
></script>
地図の表示場所にDIVタグを置きます。
<!-- このDIVタグが3D地図に置き換わります。大きさは自由です -->
<div id="main" style="height: 100vh; width: 100vw"></div>
スクリプトで読み込みをします。
<script>
window.onload = function () {
// カメラ、レンダラを作成して、mainタグの場所にマッピングする
const core = new Dio2TownMap.Core(document.getElementById("main"));
// DrawIoからデータを取得する
new Dio2TownMap.DioParser()
.parse({
dioFile:
"${先の手順で作ったCloudflare WorkersへのURL}", // Draw.ioファイルを取得する
polygonFile: "./polygon.json", // 空のJSONファイルへのパス
})
.then((dataList) => {
// Dioデータから3D画面を作成する
new Dio2TownMap.MainField().basement(
core.scene, // シーンオブジェクトを連携する
dataList, // Dioデータを連携する
(started, dataCount) => {} // オブジェクト化の完了通知
);
// 光源を初期化
new Dio2TownMap.Light(core.scene);
});
};
</script>
既存のホームページに埋め込んでもいいですし、S3 や Cloudflare pages で公開してもいいですし、React や Vue に埋め込むのもよいと思います。
サンプルソースにはオブジェクトへのクリック操作を拾うソースも書いています。MainField がオブジェクトを持っているので、JavaScript で参照して操作することもできます。
これまでの展開と今後の展開
ここからは技術的な話を離れて雑記になります。
「Draw.io を 3D にするツール」は、飛田の地図のコア部分を切り出したものですので、「このツールで現状どこまでできるの?」は、飛田の地図を見ていただければと思います。
https://tobitamap.pages.dev
実装済みや一部実装した機能:
- 建物をタップすると詳細を表示する
- カメラ位置が下がると現実に近い表現(GLBデータの表示)になる
- ルートに沿ってカメラが移動して、道案内をする
- QRコードでカメラの状態を共有する
これらについてはドキュメントを整備します。
実装予定の機能:
- 現実の雨に連動して、デジタルツイン空間内でも雨が降る
- 「building」以外のプロパティ(「room」やデータ表示のオブジェクト)を整備する
これらについては引き続き対応をと考えています
まとめとか
コストゼロ、編集もブラウザだけで完結するデジタルツインの紹介でした。
画面をぐりぐりと操作してみて、
- 3D の地図を、予算が用意できない商店街や学園祭でやったら?
- QRコードのカメラ情報共有を、GPSの精度が下がる地下街やドーム球場でやったら?
- iPhoneで3Dスキャンしたモデルをデジタルツイン上に表示したら?
「きっと楽しくなるだろう」「きっと便利になるだろう」と思ってもらえるのなら、色々な会社が出しているデジタルツインのサービスも含めて検討して、ぜひ導入してみてはと思います。