1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

AMCI Develop Note #00 PLATEAUモデルを表示するまで

Last updated at Posted at 2022-03-30

00_01.jpg

はじめに

本解説ではPLATEAUで公開しているCityGML(OBJ)データをWebサイト上で使用する方法を、AMCIでの事例を参考に説明していきます。本解説では3DとHTML、JavaScript(Three.js)の基礎的な知識が必要です。予めご注意ください。

AMCI

本解説における推奨の開発環境は以下の通りです。

  • OS: Windows10、MacOS10
  • CPU: Corei7 相当
  • GPU: GTX1060 相当
  • メモリ: 8GB
  • ブラウザ: 最新のGoogle Chrome、Microsoft Edge など

※上記以上のスペックを推奨しています

データのダウンロード

データは G空間情報センター(https://www.geospatial.jp/gp_front/) のサイトからダウンロードを行います。本解説では東京駅周辺のエリアをサンプルとして利用します。
東京都のOBJデータの公開ページは下記リンクを参照ください。

3D都市モデル(Project PLATEAU)東京都23区(OBJ 4次メッシュ 2020年度)
https://www.geospatial.jp/ckan/dataset/plateau-tokyo23ku-obj4-2020

ページ内の「東京都23区構築範囲拡大図2/4」を選択すると、東京23区の北東エリアを区切ったマップが表示されます。この中の東京駅付近の番号を探します。
大丸有と名前がつけられたエリアの「53394611」のデータを利用したいので、このデータのダウンロードページ(533946)へ移動し、ページ右上のダウンロードボタンをクリックします。

データの解凍

ダウンロードしたzipデータを解凍すると、下記のようなデータが含まれているので、その中からLOD1.zipを解凍しそのフォルダをクリックします。この中にはエリア毎に細かく分かれた建物のデータが含まれます。続いてこのデータをブラウザ上で表示してみます。

Zipデータに含まれるもの

  • brid.zip: 橋や陸橋などのデータ
  • dem.zip: 数値標高モデル(地面データ)
  • LOD1.zip: 簡略化した建物データ
  • LOD2.zip: 形状が細かくテクスチャも付いた建物データ

3Dデータの調整

ダウンロードした3Dデータをブラウザで表示する前に、3Dデータの座標を調整する必要があります。PLATEAUの3Dモデルは細かくエリアやカテゴリ(ビル、地面、橋など)に分かれており、それらは組み合わせることで街の再現などが行なえます。
ここで、1点問題があります。
単純に1つの区画だけをブラウザなどで表示する場合は、3Dモデルの左右と奥行きの座標が中央から離れているため、そのまま表示させようと思っても画面外に表示されてしまいます。
なので、一度3Dソフトなどでデータを開き、中央に座標を移動させたデータをJavaScriptなどで読み込む必要があります。
具体的な手順はここでは割愛しますが、Blenderなどの3Dソフトで調整を行った上で利用をおすすめします。

ブラウザでの表示方法

3Dデータをブラウザで表示するためには、Three.jsという3Dの描画ライブラリを利用します。Three.jsについての説明は下記ページを参照ください。

最新版で学ぶThree.js入門 手軽にWebGLを扱える3Dライブラリ(ics.mediaより)
https://ics.media/entry/14771/

続いて、Three.jsの使い方を説明します。まずはThree.jsライブラリを読み込む必要があるのでこちらのファイル( https://threejs.org/build/three.js )をご自分のPCにダウンロードしてください。次にダウンロードしたthree.jsファイルと同じ階層に、下記のHTMLを作成します。

index.html
<!DOCTYPE html>
<html>
	<head>
		<meta charset="utf-8">
		<title>My first three.js app</title>
		<style>
			body { margin: 0; }
		</style>
	</head>
	<body>
		<script src="three.js"></script>
		<script>
			// ここにコードを記述します
		</script>
	</body>
</html>

このHTMLをGoogle ChromeなどのWebブラウザで開き、エラーなどが出ていなければ準備完了です。

OBJデータを表示する

Three.jsでOBJデータを扱うには、OBJ loaderというクラスを読み込む必要があります。こちらはThree.jsの拡張機能のようなもので、他にもFBX loaderやFont loaderなど様々なものが用意されています。
こちらはGitHubのThree.jsのリポジトリ内からダウンロードができますが、最近のバージョンはWebpackなどでの利用を想定して作られているので、今回のサンプルでは過去バージョンのOBJ loaderを使用します。ファイルはサンプルに含めているので、そちらからご利用ください。

使用例: OBJ loader
https://threejs.org/examples/#webgl_loader_obj

index.html
  <script src="three.js"></script>
  <script src="OBJLoader.js"></script>

上記のようにスクリプトの読み込みに1行加えます。必ずThree.js本体の読み込みの後に行うようにしてください。
そして下記がThree.jsでPLATEAUの3Dモデルを描画するソースコードです。行っている処理についてはコメントを参照してください。

また、最近のGoogle Chromeでは「file:///Users/〜」などではじまるアドレスではデータ(3Dデータなど)の読み込みが行えないので、ローカル環境で動作させたい場合はローカルホストを立てる必要があります。
PythonやPHPから、「python -m SimpleHTTPServer 8000」や「php -S localhost:8000」などのコマンドで簡単にローカルホストを立てる事ができます。ご利用の環境によってコマンドは違う可能性もあるので、ご自身の環境で動作するコマンドをお試しください。

index.html
<script>
// 変数の用意
let container;
let camera, scene, renderer;
let mouseX = 0, mouseY = 0;
let windowHalfX = window.innerWidth / 2;
let windowHalfY = window.innerHeight / 2;
let object;

init();
animate();

function init() {
  // HTMLにCanvasを追加
  container = document.createElement('div');
  document.body.appendChild(container);

  // カメラを追加
  camera = new THREE.PerspectiveCamera(45, window.innerWidth / window.innerHeight, 1, 2000);
  camera.position.z = 250;

  // scene
  scene = new THREE.Scene();
  scene.background = new THREE.Color(0x333333);

  // ライトを追加
  const ambientLight = new THREE.AmbientLight(0xcccccc, 0.4);
  scene.add(ambientLight);
  const pointLight = new THREE.PointLight(0xffffff, 0.8);
  camera.add(pointLight);
  scene.add(camera);

  // 地面を追加
  const geometry = new THREE.PlaneGeometry( 1000, 1000 );
  const material = new THREE.MeshBasicMaterial( {color: 0x666666, side: THREE.DoubleSide} );
  const plane = new THREE.Mesh( geometry, material );
  plane.rotation.x = 90 * Math.PI / 180;
  scene.add( plane );

  // 3Dモデルを読み込み
  const loader = new THREE.OBJLoader();
  loader.load('model/53394610_bldg_6677_center.obj', function(obj) {
    object = obj;
    object.scale.x = 0.3;
    object.scale.y = 0.3;
    object.scale.z = 0.3;
    scene.add(object);
  });

  // レンダラーを追加
  renderer = new THREE.WebGLRenderer();
  renderer.setPixelRatio(window.devicePixelRatio);
  renderer.setSize(window.innerWidth, window.innerHeight);
  container.appendChild(renderer.domElement);

  // イベントを追加
  document.addEventListener('mousemove', onDocumentMouseMove);
  window.addEventListener('resize', onWindowResize);
}

// ブラウザのリサイズ時に実行
function onWindowResize() {
  windowHalfX = window.innerWidth / 2;
  windowHalfY = window.innerHeight / 2;
  camera.aspect = window.innerWidth / window.innerHeight;
  camera.updateProjectionMatrix();
  renderer.setSize(window.innerWidth, window.innerHeight);
}

// マウスムーブ時に実行
function onDocumentMouseMove(event) {
  mouseX = (event.clientX - windowHalfX) / 2;
  mouseY = (event.clientY - windowHalfY) / 2;
}

// 毎フレーム実行
function animate() {
  requestAnimationFrame(animate);
  render();
}

function render() {
  camera.position.x += (mouseX - camera.position.x) * .05;
  camera.position.y += (-mouseY - camera.position.y) * .05;
  camera.lookAt(new THREE.Vector3(0, 10, 0));
  renderer.render(scene, camera);
}
</script>
1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?