Project PLATEAU WebXR

AR

国土交通省 都市局が公開している3DデータをWebXRで表示してみたいと思います。

こちらに目次がまとめられています。
https://www.geospatial.jp/ckan/dataset/plateau-tokyo23ku

3次メッシュ、4次メッシュとは

これはグローバルに一般的なハナシではなく、JIS規格として定められているスケールです。

“JIS X0410そのままでは, 日本から遠く離れたの海外の空間を表現するために利用することができない.”

“統計利用には面積一定とするMGRS, Ordnance Survey National Grid reference system, European gridの方が優れているよう思われる. 一方で, 日本のJIS X0410で規程されているメッシュコードは緯度経度に基づくもので全てのグリッドの面積は正確に一致しているものとなっていないが, 近似的におおよそ等しく, また緯度と経度と対応するため理解が容易であるという利点がある.”

https://www.fttsus.org/worldgrids/ja/document-ja/

x次メッシュという規格以外に米国主導、イギリス主導、EU主導の規格があるようです。まだガラパゴスとは言い切れない状況なのでしょうか。

LODとは

Level of Development Specificationのことで、数字が大きいほど詳細なデータとなります。LOD4まで行くと、建造物の中に入ることが出来るレベルだそうです。2021年現在、以下のデータをダウンロードすることが出来ます。

提供エリア:
LOD1作成範囲 東京23区全域(627.57k㎡)。
LOD2作成範囲 池袋地区(1.5k㎡)、新宿地区(2.57k㎡)、渋谷地区(1.39k㎡)、国立競技場地区(0.73k㎡)、品川地区(1.79k㎡)、大丸有地区(1.22k㎡)、竹芝地区(0.27k㎡)、東京都心地区(12.55k㎡)、豊洲地区(2.11k㎡)、臨海地区(4.34k㎡)、羽田空港地区(3.56k㎡)、合計(32.02k㎡)

https://www.geospatial.jp/ckan/dataset/plateau-tokyo23ku-fbx4-2020

単にハコっぽい建造物を見る/見せるのであれば、Open Street Mapのデータを使ったOSM Buildingというものがあります。
https://github.com/OSMBuildings/OSMBuildings

東京のデータもあります。

データをダウンロードする

データをダウンロードできるページにはコメント投稿機能があるのですが、いくつかデータに誤りがあるようです。今回は「浅草」を表示しようと思ったのですが、どうやら3次メッシュFBXの浅草データは迷子になっている模様です。。そして4次メッシュであれば細かい(細かく)データをダウンロードできるかと思ったのですが、そうでもないようです。

もし単純に雰囲気を掴みたいのであれば、他の方がやっているように間違いがなさそうな「新宿」あたりを触ると良いのかも知れません。ただしLOD2が多く含まれる地域はダウンロード容量も大きくなるので注意が必要です。

試しに浅草近辺データのOBJ形式のファイルをダウンロードしてみます。Windows標準の機能としてプレビューで確認することも出来ます。

左下が隅田川、左上が浅草寺でしょうか。縦になってますね。上の画像は、地図を裏側から見たような感じです。次に4次メッシュFBXの浅草データをダウンロードして、Windows標準の3Dビューアーで確認してみました。

FBX形式のデータをglb形式に変換する

FBX形式を使うことにしたのですが、Babylon.jsではFBXをサポートしていません。そこでBlenderを使ってglb形式に変換してみます。
インポートしてみると、はるか遠くに表示されました。どうやらこの位置関係は日本のどこかを中心として位置取りされているようで、他のデータを読み込むとパズルのように当てはまっていきます。

もしかして道路元標がある日本橋あたりを原点にしてるのか?と思い、日本橋あたりを読み込んでみます。

そんなことは無かった…。
日本経緯度原点は港区麻布台にあるのですが、この東京データのBlender上の基点(原点?)は埼玉県あたりにありそうな気がするのですがどうでしょうか。。
試しに足立区の北端を読み込んでみます。これより北側は埼玉県です。

位置的に手前が台東区(南側)、オレンジ色のオブジェクトが足立区(北側)です。東京より遥か北ですね。

改めて浅草近辺のみ選択してglbでエクスポートすればglbファイルが手に入ります。それを最適化すると336KBになりました。

このぐらいの容量であれば、Webサイトでも扱いやすそうです。

Babylon.jsで表示する


Loaderが必要なので読み込みます。
https://doc.babylonjs.com/divingDeeper/importers/loadingFileTypes

<!DOCTYPE html>

<head>
    <title>babylonjs sample</title>
    <style>
        html,
        body {
            overflow: hidden;
            width: 100%;
            height: 100%;
            margin: 0;
            padding: 0;
        }

        #renderCanvas {
            width: 100%;
            height: 100%;
            touch-action: none;
        }
    </style>
    <script src="https://cdn.babylonjs.com/babylon.js"></script>
    <script src="./babylon.glTFFileLoader.js"></script>

    <script src="https://code.jquery.com/pep/0.4.3/pep.js"></script>
</head>

<body>
    <canvas id="renderCanvas" touch-action="none"></canvas> 

    <script>
        const canvas = document.getElementById("renderCanvas");
        const engine = new BABYLON.Engine(canvas); 
        var sceneToRender = null;

        const createScene = async function () {
            var scene = new BABYLON.Scene(engine);
            var camera = new BABYLON.FreeCamera("camera1", new BABYLON.Vector3(0, 5, -10), scene);
            camera.setTarget(BABYLON.Vector3.Zero());
            camera.attachControl(canvas, true);
            var light = new BABYLON.HemisphericLight("light", new BABYLON.Vector3(0, 1, 0), scene);
            light.intensity = 0.7;

            BABYLON.SceneLoader.Append("./", "asakusa-cc.glb", scene, function (scene) {
                scene.createDefaultCameraOrLight(true, true, true);
                scene.activeCamera.alpha += Math.PI;
            });

            scene.createDefaultEnvironment();
            try {
                const xrHelper = await WebXRExperienceHelper.CreateAsync(scene);
            } catch (e) {
                // no XR support
            }
            return scene;
        };


        var scene = createScene();

        scene.then(returnedScene => { sceneToRender = returnedScene; });

        engine.runRenderLoop(async function () {
            if (sceneToRender && sceneToRender.activeCamera) {
                await sceneToRender.render();
            }
        });

        window.addEventListener("resize", function () {
            engine.resize();
        });
    </script>
</body>

</html>

結果

何というか、消しゴムで作った町のような感じです。
オブジェクトとして当たり判定など付ければ街歩きなどできるかなと思ったのですが、消しゴムの町を歩いてもなぁというところもあります。

Three.jsで新宿を表示する

少し味気ないので、弊社の会社所在地でもある新宿を表示することにしました。
【つづく】

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