8.1 glTFモデルの表示(SceneLoaderを使った表示)
mapray.SceneLoaderを使ってglTFモデルを表示する方法を説明します。
1. サンプルコード
mapray.SceneLoaderを使ってglTFモデルを表示する LoadglTFModel.html 及び、 LoadglTFModel.js のサンプルコードとシーンファイル( glTFLoad.json )です。 このサンプルコードでは、薬師寺の場所に3Dモデルを表示します。
1.1. glTFデータの入手
PARTCommunityへアクセスし、glTFファイルフォーマットのデータをダウンロードする、 もしくはダウンロードリンクをクリックしてダウンロードしてください。 ダウンロードリンクからダウンロードした場合はzipファイルを展開してご利用ください。 展開したデータは解凍した結果できたディレクトリを含めて、mapray-jsのルートディレクトリからの相対パスで以下のディレクトリに保存されているという想定で以下の説明を行います。
./examples/entity/gltf/data/
なお、データは当社の著作物ではありません。著作権は各データの作成者に帰属します。詳細はフォルダ中のLICENSEファイルを参照の上ご利用ください。 ユーザーの皆様がコンテンツの権利を侵害した場合、当社では一切責任を追うものではありませんのでご注意ください。
1.2. LoadglTFModel.html
1: <!DOCTYPE html> 2: <html> 3: <head> 4: <meta charset="UTF-8"> 5: <title>LoadglTFModelSample</title> 6: <script src="https://resource.mapray.com/mapray-js/v0.9.5/mapray.min.js"></script> 7: <link rel="stylesheet" href="https://resource.mapray.com/styles/v1/mapray.css"> 8: <script src="LoadglTFModel.js"></script> 9: <style> 10: html, body { 11: height: 100%; 12: margin: 0; 13: } 14: 15: div#mapray-container { 16: display: flex; 17: position: relative; 18: height: 100%; 19: } 20: </style> 21: </head> 22: 23: <body onload="new LoadModel('mapray-container');"> 24: <div id="mapray-container"></div> 25: </body> 26: </html>
1.3. LoadglTFModel.js
1: class LoadModel { 2: constructor(container) { 3: // Access Tokenを設定 4: var accessToken = "<your access token here>"; 5: 6: // Viewerを作成する 7: this.viewer = new mapray.Viewer( 8: container, { 9: image_provider: this.createImageProvider(), 10: dem_provider: new mapray.CloudDemProvider(accessToken) 11: } 12: ); 13: 14: // glTFモデルのライセンス表示 15: this.viewer.attribution_controller.addAttribution( { 16: display: "Yakushiji Temple by Daily CAD is licensed under: Creative Commons - Attribution - ShareAlike International", 17: link: "https://b2b.partcommunity.com/community/knowledge/ja/detail/435/Yakushi-ji" 18: } ); 19: 20: this.SetCamera(); 21: 22: this.LoadScene(); 23: } 24: 25: // 画像プロバイダを生成 26: createImageProvider() { 27: // 国土地理院提供の汎用的な地図タイルを設定 28: return new mapray.StandardImageProvider( { url: "https://cyberjapandata.gsi.go.jp/xyz/seamlessphoto/", format: "jpg", min_level: 2, max_level: 18 } ); 29: } 30: 31: // カメラ位置の設定 32: SetCamera() { 33: // 球面座標系(経度、緯度、高度)で視点を設定。モデルの座標を設定 34: var home_pos = { longitude: 135.784682, latitude: 34.668107, height: 100.0 }; 35: 36: // 球面座標から地心直交座標へ変換 37: var home_view_geoPoint = new mapray.GeoPoint( home_pos.longitude, home_pos.latitude, home_pos.height ); 38: var home_view_to_gocs = home_view_geoPoint.getMlocsToGocsMatrix( mapray.GeoMath.createMatrix() ); 39: 40: // 視線方向を定義 41: var cam_pos = mapray.GeoMath.createVector3([100, -300, 100]); 42: var cam_end_pos = mapray.GeoMath.createVector3([0, 0, 0]); 43: var cam_up = mapray.GeoMath.createVector3([0, 0, 1]); 44: 45: // ビュー変換行列を作成 46: var view_to_home = mapray.GeoMath.createMatrix(); 47: mapray.GeoMath.lookat_matrix(cam_pos, cam_end_pos, cam_up, view_to_home); 48: 49: // カメラの位置と視線方向からカメラの姿勢を変更 50: var view_to_gocs = this.viewer.camera.view_to_gocs; 51: mapray.GeoMath.mul_AA(home_view_to_gocs, view_to_home, view_to_gocs); 52: 53: // カメラのnear、farの設定 54: this.viewer.camera.near = 30; 55: this.viewer.camera.far = 500000; 56: } 57: 58: // シーンの読み込み 59: LoadScene() { 60: var scene_File_URL = "./data/glTFLoad.json"; 61: 62: // シーンを読み込む 63: var loader = new mapray.SceneLoader(this.viewer.scene, scene_File_URL, { 64: transform: (url, type) => this.onTransform(url, type), 65: callback: (loader, isSuccess) => { 66: this.onLoadScene(loader, isSuccess); 67: } 68: }); 69: 70: loader.load(); 71: } 72: 73: onTransform(url, type) { 74: return { 75: url: url, 76: credentials: mapray.CredentialMode.SAME_ORIGIN, 77: headers: {} 78: }; 79: } 80: 81: onLoadScene(loader, isSuccess) { 82: if (isSuccess) { 83: // sceneのEntityを取得 84: var entity = this.viewer.scene.getEntity(0); 85: 86: // モデルの回転 87: entity.setOrientation(new mapray.Orientation(180, 0, 0)); 88: } 89: } 90: 91: }
1.4. シーンファイル(glTFLoad.json)
1: { 2: "model_register": { "model-0": { "link": "./Yakushiji_Temple/Yakushiji_Temple.gltf" } }, 3: "entity_list": [{ 4: "type": "model", 5: "mode": "basic", 6: "transform": { "position": [135.784682, 34.668107, 57.0] }, 7: "ref_model": "model-0", 8: "altitude_mode": "absolute" 9: } 10: ] 11: }
2. htmlのサンプルコードの詳細
htmlのサンプルコードの詳細を以下で解説します。
2.1. htmlの文字コード設定
4行目でhtmlの文字コードを設定します。このサンプルコードでは、utf-8を設定します。
4: <meta charset="UTF-8">
2.2. タイトルの設定
5行目でタイトルを設定します。このサンプルコードでは、LoadglTFModelSampleを設定します。
5: <title>LoadglTFModelSample</title>
2.3. JavaScriptファイルのパス設定
6~8行目で参照するJavaScript及びスタイルシートのパスを設定します。このサンプルコードでは、maprayのJavaScriptファイル、スタイルシート、モデルのシーンを読み込むJavaScriptファイル( Load3DModel.js )を設定します。
6: <script src="https://resource.mapray.com/mapray-js/v0.9.5/mapray.min.js"></script> 7: <link rel="stylesheet" href="https://resource.mapray.com/styles/v1/mapray.css"> 8: <script src="LoadglTFModel.js"></script>
2.4. スタイルの設定
9~20行目で表示する要素のスタイルを設定します。スタイルの詳細は、ヘルプページ『緯度経度によるカメラ位置の指定』を参照してください。
9: <style> 10: html, body { 11: height: 100%; 12: margin: 0; 13: } 14: 15: div#mapray-container { 16: display: flex; 17: position: relative; 18: height: 100%; 19: } 20: </style>
2.5. loadイベントの処理
画面を表示するときに、モデルシーン読み込みクラスを生成します。そのため、23行目でページの読み込み時に、地図表示部分のブロックのidからモデルシーン読み込みクラスのインスタンスを生成します。 モデルシーン読み込みクラスはJavaScriptのサンプルコードの詳細で説明します。
23: <body onload="new LoadModel('mapray-container');">
2.6. 地図表示部分の指定
24行目で地図表示部分のブロックを記述します。 詳細はヘルプページ『緯度経度によるカメラ位置の指定』を参照してください。
24: <div id="mapray-container"></div>
3. JavaScriptのサンプルコードの詳細
JavaScriptのサンプルコードの詳細を以下で解説します。
3.1. クラスの説明
2~91行目で、モデルシーンを読み込み、表示するクラスを定義します。クラス内の各メソッドの詳細は以降で解説します。
class LoadModel { //中略 }
3.2. コンストラクタ
2~23行目がモデルシーンを読み込み、表示するクラスのコンストラクタです。引数として渡されるブロックのidに対して、mapray.Viewerを作成し、glTFモデルの出典情報を追加します。そして、カメラの位置・向きの設定メソッドを呼び出します。その後、シーンのロードメソッドを呼び出します。viewerを作成する際の画像プロバイダは画像プロバイダの生成メソッドから取得します。 mapray.Viewerの作成の詳細は、ヘルプページ『緯度経度によるカメラ位置の指定』を参照してください。
2: constructor(container) { 3: // Access Tokenを設定 4: var accessToken = "<your access token here>"; 5: 6: // Viewerを作成する 7: this.viewer = new mapray.Viewer( 8: container, { 9: image_provider: this.createImageProvider(), 10: dem_provider: new mapray.CloudDemProvider(accessToken) 11: } 12: ); 13: 14: // glTFモデルのライセンス表示 15: this.viewer.attribution_controller.addAttribution( { 16: display: "Yakushiji Temple by Daily CAD is licensed under: Creative Commons - Attribution - ShareAlike International", 17: link: "https://b2b.partcommunity.com/community/knowledge/ja/detail/435/Yakushi-ji" 18: } ); 19: 20: this.SetCamera(); 21: 22: this.LoadScene(); 23: }
3.3. 画像プロバイダの生成
26~29行目が画像プロバイダの生成メソッドです。生成した画像プロバイダを返します。 画像プロバイダの生成の詳細は、ヘルプページ『緯度経度によるカメラ位置の指定』を参照してください。
25: // 画像プロバイダを生成 26: createImageProvider() { 27: // 国土地理院提供の汎用的な地図タイルを設定 28: return new mapray.StandardImageProvider( { url: "https://cyberjapandata.gsi.go.jp/xyz/seamlessphoto/", format: "jpg", min_level: 2, max_level: 18 } ); 29: }
3.4. カメラの位置・向きの設定
32~56行目がカメラの位置・向きの設定メソッドです。 カメラの位置・向きの設定は、ヘルプページ『緯度経度によるカメラ位置の指定』を参照してください。
31: // カメラ位置の設定 32: SetCamera() { 33: // 球面座標系(経度、緯度、高度)で視点を設定。モデルの座標を設定 34: var home_pos = { longitude: 135.784682, latitude: 34.668107, height: 100.0 }; 35: 36: // 球面座標から地心直交座標へ変換 37: var home_view_geoPoint = new mapray.GeoPoint( home_pos.longitude, home_pos.latitude, home_pos.height ); 38: var home_view_to_gocs = home_view_geoPoint.getMlocsToGocsMatrix( mapray.GeoMath.createMatrix() ); 39: 40: // 視線方向を定義 41: var cam_pos = mapray.GeoMath.createVector3([100, -300, 100]); 42: var cam_end_pos = mapray.GeoMath.createVector3([0, 0, 0]); 43: var cam_up = mapray.GeoMath.createVector3([0, 0, 1]); 44: 45: // ビュー変換行列を作成 46: var view_to_home = mapray.GeoMath.createMatrix(); 47: mapray.GeoMath.lookat_matrix(cam_pos, cam_end_pos, cam_up, view_to_home); 48: 49: // カメラの位置と視線方向からカメラの姿勢を変更 50: var view_to_gocs = this.viewer.camera.view_to_gocs; 51: mapray.GeoMath.mul_AA(home_view_to_gocs, view_to_home, view_to_gocs); 52: 53: // カメラのnear、farの設定 54: this.viewer.camera.near = 30; 55: this.viewer.camera.far = 500000; 56: }
3.5. シーンのロード
59~71行目がシーンのロードメソッドです。mapray.SceneLoaderでシーンを読み込みます。 SceneLoaderクラス生成時の引数には、シーンファイルのエンティティを追加するシーン、読み込むシーンファイルのURL、オプション集合の順に指定します。このサンプルコードでは、viewerクラスのシーン、60行目で設定したURL、リソース要求変換関数、シーンのロードが終了した時のコールバック関数の順に指定します。読み込むシーンのURLはhttpもしくはhttpsでアクセスできるURLを指定します。最後に、70行目のload関数を呼び出すことでシーンの読み込みができます。
58: // シーンの読み込み 59: LoadScene() { 60: var scene_File_URL = "./data/glTFLoad.json"; 61: 62: // シーンを読み込む 63: var loader = new mapray.SceneLoader(this.viewer.scene, scene_File_URL, { 64: transform: (url, type) => this.onTransform(url, type), 65: callback: (loader, isSuccess) => { 66: this.onLoadScene(loader, isSuccess); 67: } 68: }); 69: 70: loader.load(); 71: }
3.6. リソース要求変換
73~79行目はリソース要求変換メソッドです。リソースのリクエスト時にURLなどを変換する内容を定義します。このサンプルコードでは、特に指定はしないので、リファレンスに沿った内容で定義します。
73: onTransform(url, type) { 74: return { 75: url: url, 76: credentials: mapray.CredentialMode.SAME_ORIGIN, 77: headers: {} 78: }; 79: }
3.7. シーンのロード終了イベント
81~89行目がシーンのロード終了イベントメソッドです。引数のisSuccessには、読み込み結果が格納されており、trueの場合のみ読み込んだglTFモデルを表示します。 読み込んだモデルの向きを調整するため、87行目で、適切な向きをエンティティに反映させることで、地図上にglTFモデルを表示します。なお、読み込んだモデルは1つ目のエンティティとなるため、エンティティ取得時の引数には0を指定します。
81: onLoadScene(loader, isSuccess) { 82: if (isSuccess) { 83: // sceneのEntityを取得 84: var entity = this.viewer.scene.getEntity(0); 85: 86: // モデルの回転 87: entity.setOrientation(new mapray.Orientation(180, 0, 0)); 88: } 89: }
4. シーンファイルの詳細
シーンファイルの詳細を以下で解説します。なお、シーンファイルはJSON形式で記述します。
4.1. エンティティの設定
3行目でentity_listという名称でエンティティを定義し、その中にエンティティの詳細を定義します。4行目のtypeという名称は、エンティティの種類を表し、glTFモデルの場合はmodelを指定します。
{ 中略 "entity_list": [{ "type": "model", 中略 } ] }
4.2. glTFモデルのデータ
2行目でmodel_registerという名称でモデルデータを定義します。このシーンファイルでは、モデルデータのIDをmodel-0とし、モデルファイルをファイルから読み込むために、linkという名称にglTFファイルのURLを指定します。
2: "model_register": { "model-0": { "link": "./Yakushiji_Temple/Yakushiji_Temple.gltf" } },
4.3. 汎用エンティティの設定
4~8行目で汎用エンティティの設定をします。汎用エンティティには以下の内容を定義します。
- モード(mode) ⇒ basic
- 初期姿勢(transform) ⇒ 球面座標系(position)での初期位置
- モデルデータ(ref_model) ⇒ モデルデータのID(model-0)
- 高度モード(altitude_mode) ⇒ 初期位置の高度を絶対値で指定(absolute)
4: "type": "model", 5: "mode": "basic", 6: "transform": { "position": [135.784682, 34.668107, 57.0] }, 7: "ref_model": "model-0", 8: "altitude_mode": "absolute"
6. glTFモデルの表示の改修
このサンプルコードを改修して、下記のglTFモデルを表示できるようにします。
- 対象のglTFモデルを薬師寺から小倉城に変更する
- カメラが見る位置を小倉城周辺に変更する
また、glTFモデル読み込み時の向き及びスケールはロード後に設定し直す以外に、 シーンファイル内に記載する方法もあるため、その方法についても記載します。
サンプルコードの修正部分は2つあり、以下で解説します。
6.1. カメラの見る位置の変更
カメラの位置・向きの設定メソッドを下記のように変更します。 この修正では、視点位置はを小倉城周辺に変更し、視線方向も小倉城が眺められる方向に変更しています。
SetCamera() { // 球面座標系(経度、緯度、高度)で視点を設定。モデルの座標を設定 var home_pos = { longitude: 130.873921, latitude: 33.884291, height: 3.0 }; // 球面座標から地心直交座標へ変換 var home_view_geoPoint = new mapray.GeoPoint( home_pos.longitude, home_pos.latitude, home_pos.height ); var home_view_to_gocs = home_view_geoPoint.getMlocsToGocsMatrix( mapray.GeoMath.createMatrix() ); // 視線方向を定義 var cam_pos = mapray.GeoMath.createVector3([200, 200, 100]); var cam_end_pos = mapray.GeoMath.createVector3([0, 0, 0]); var cam_up = mapray.GeoMath.createVector3([0, 0, 1]); // ビュー変換行列を作成 var view_to_home = mapray.GeoMath.createMatrix(); mapray.GeoMath.lookat_matrix(cam_pos, cam_end_pos, cam_up, view_to_home); // カメラの位置と視線方向からカメラの姿勢を変更 var view_to_gocs = this.viewer.camera.view_to_gocs; mapray.GeoMath.mul_AA(home_view_to_gocs, view_to_home, view_to_gocs); // カメラのnear、farの設定 this.viewer.camera.near = 30; this.viewer.camera.far = 500000; }
6.2. 読み込み対象の変更
シーンのロードメソッドで読み込み対象のシーンファイルを下記のように変更します。 また、シーンファイル上でモデルの向き、スケールを設定するため、ロード後に実行することがなくなるので、今回はコールバック関数を設定しません。
LoadScene() { var scene_File_URL = "./data/glTFLoadVer2.json"; // シーンを読み込む var loader = new mapray.SceneLoader(this.viewer.scene, scene_File_URL, { transform: (url, type) => this.onTransform(url, type) }); loader.load(); }
6.3. 変更したシーンファイルの詳細
変更したシーンファイルの詳細は下記のとおりです。 表示するモデルとして、小倉城のglTFモデルデータを読み込むように作成しています。 また、モデルの初期向きとスケールは、offset_transformという名称で指定することができます。 このシーンファイルでは、下記の内容を定義しています。
- ヘディング(X軸回りの回転角度)(heading) ⇒ 20
- チルト(Y軸回りの回転角度)(tilt) ⇒ -90
- モデルスケール(scale) ⇒ 0.7
1: { 2: "model_register": { "model-0": { 3: "link": "./kokura_castle/scene.gltf", 4: "offset_transform": { "heading": 20, "tilt": -90, "scale": 0.7 } 5: } 6: }, 7: "entity_list": [{ 8: "type": "model", 9: "mode": "basic", 10: "transform": { "position": [130.873721, 33.884881, -25.0] }, 11: "ref_model": "model-0", 12: "altitude_mode": "absolute" 13: } 14: ] 15: }