Three.js中加载和渲染3D Tiles

1. 引言

3D Tiles 是 3D GIS 中常见的三维数据格式,能否用Three.js来加载渲染呢?肯定是可以,Three.js只是一个WebGL框架,渲染数据肯定可以,但是加载、解析数据得手动解决

有没有一个第三方库解决这个问题呢?有,比如这个:NASA-AMMOS/3DTilesRendererJS: Renderer for 3D Tiles in Javascript using three.js (github.com)

这里就简要记录如何在Three.js中加载 3D Tiles

2. 加载3D Tiles

首先,搭建一个简单的三维场景

<!DOCTYPE html> <html lang="en">   <head> 	<meta charset="UTF-8"> 	<meta http-equiv="X-UA-Compatible" content="IE=edge"> 	<meta name="viewport" content="width=device-width, initial-scale=1.0"> 	<title>Document</title> 	<style> 		html, 		body, 		canvas { 			height: 100%; 			width: 100%; 			margin: 0; 		} 	</style> 	 </head>   <body> 	<canvas id="canvas"></canvas>   	<script type="importmap"> 		{ 			"imports": { 				"three": "https://unpkg.com/three/build/three.module.js", 				"three/addons/": "https://unpkg.com/three/examples/jsm/" 			} 		} 	</script> 	 	<script type="module"> 		import * as THREE from 'three'; 		import { OrbitControls } from 'three/addons/controls/OrbitControls.js';   		const scene = new THREE.Scene();   		const canvas = document.querySelector('#canvas'); 		const camera = new THREE.PerspectiveCamera(75,  canvas.clientWidth / canvas.clientHeight , 0.1, 1000); 		camera.position.z = 5;   		const renderer = new THREE.WebGLRenderer({ 			canvas: document.querySelector('#canvas') 		}); 		renderer.setSize(window.innerWidth, window.innerHeight, false) 		 		const geometry = new THREE.BoxGeometry(1, 1, 1); 		const material = new THREE.MeshPhongMaterial({ 			color: 0x00ff00 		}); 		const cube = new THREE.Mesh(geometry, material); 		scene.add(cube);   		const light = new THREE.DirectionalLight(0xffffff, 1); 		light.position.set(0, 0, 5); 		scene.add(light);   		const controls = new OrbitControls( camera, renderer.domElement ); 		 		function animate() { 			requestAnimationFrame(animate); 			cube.rotation.x += 0.01; 			cube.rotation.y += 0.01; 			renderer.render(scene, camera); 		} 		animate(); 	</script> </body>   </html> 

Three.js中加载和渲染3D Tiles

然后是引入3DTilesRendererJS,这里引入的是GoogleTilesRenderer来加载Google的在线地图,另外还需要使用GLTFLoaderDRACOLoader以进行数据解析

<script type="importmap"> 		{ 			"imports": { 				"three": "https://unpkg.com/three/build/three.module.js", 				"three/addons/": "https://unpkg.com/three/examples/jsm/",                 "3DTilesRendererJS": "https://cdn.jsdelivr.net/npm/3d-tiles-renderer@0.3.30/+esm" 			} 		} </script>  <script type="module">     import * as THREE from 'three';     import { OrbitControls } from 'three/addons/controls/OrbitControls.js';     import { GLTFLoader } from 'three/addons/loaders/GLTFLoader.js';     import { TilesRenderer, GoogleTilesRenderer } from '3DTilesRendererJS'     import { DRACOLoader } from 'three/addons/loaders/DRACOLoader.js';     // ... </script> 

下一步是加载谷歌在线3D Tiles并加入场景中

const tilesRenderer = new GoogleTilesRenderer( 'AIzaSyBQ7Wj99aTxRqET-22qYWGFcDCWgVDt89A' ); // 传入的是谷歌倾斜摄影的API key tilesRenderer.setLatLonToYUp( 36.266494 * THREE.MathUtils.DEG2RAD, 120.460205 * THREE.MathUtils.DEG2RAD ); // Tokyo Tower  tilesRenderer.setCamera( camera ); tilesRenderer.setResolutionFromRenderer( camera, renderer );  const dracoLoader = new DRACOLoader(); dracoLoader.setDecoderPath( 'https://unpkg.com/three@0.153.0/examples/jsm/libs/draco/gltf/' );  const loader = new GLTFLoader( tilesRenderer.manager ); loader.setDRACOLoader( dracoLoader );  tilesRenderer.manager.addHandler( /.gltf$/, loader );  scene.add( tilesRenderer.group ); 

最后在每一帧中更新3D Tiles渲染器

function animate() {     requestAnimationFrame(animate);     tilesRenderer.update();     // ...     renderer.render(scene, camera); } 

加载的结果如下:

Three.js中加载和渲染3D Tiles

完整代码如下:

<!DOCTYPE html> <html lang="en">   <head> 	<meta charset="UTF-8"> 	<meta http-equiv="X-UA-Compatible" content="IE=edge"> 	<meta name="viewport" content="width=device-width, initial-scale=1.0"> 	<title>Document</title> 	<style> 		html, 		body, 		canvas { 			height: 100%; 			width: 100%; 			margin: 0; 		} 	</style> 	 </head>   <body> 	<canvas id="canvas"></canvas>   	<script type="importmap"> 		{ 			"imports": { 				"three": "https://unpkg.com/three/build/three.module.js", 				"three/addons/": "https://unpkg.com/three/examples/jsm/" 			} 		} 	</script> 	 	<script type="module"> 		import * as THREE from 'three'; 		import { OrbitControls } from 'three/addons/controls/OrbitControls.js'; 		import { GLTFLoader } from 'three/addons/loaders/GLTFLoader.js';         import { TilesRenderer, GoogleTilesRenderer } from 'https://cdn.jsdelivr.net/npm/3d-tiles-renderer@0.3.30/+esm'         import { DRACOLoader } from 'three/addons/loaders/DRACOLoader.js';   		const scene = new THREE.Scene();   		const canvas = document.querySelector('#canvas'); 		const camera = new THREE.PerspectiveCamera(75,  canvas.clientWidth / canvas.clientHeight , 0.1, 100000); 		camera.position.y = 500; 		camera.position.z = 500;   		const renderer = new THREE.WebGLRenderer({ 			canvas: document.querySelector('#canvas') 		}); 		renderer.setSize(window.innerWidth, window.innerHeight, false)   		const controls = new OrbitControls( camera, renderer.domElement );          const tilesRenderer = new GoogleTilesRenderer( 'AIzaSyBQ7Wj99aTxRqET-22qYWGFcDCWgVDt89A' );         tilesRenderer.setLatLonToYUp( 35.6586 * THREE.MathUtils.DEG2RAD, 139.7454 * THREE.MathUtils.DEG2RAD ); // Tokyo Tower          tilesRenderer.setCamera( camera );         tilesRenderer.setResolutionFromRenderer( camera, renderer );          const dracoLoader = new DRACOLoader();         dracoLoader.setDecoderPath( 'https://unpkg.com/three@0.153.0/examples/jsm/libs/draco/gltf/' );          const loader = new GLTFLoader( tilesRenderer.manager );         loader.setDRACOLoader( dracoLoader );          tilesRenderer.manager.addHandler( /.gltf$/, loader );          scene.add( tilesRenderer.group ); 		 		function animate() { 			requestAnimationFrame(animate);             tilesRenderer.update(); 			renderer.render(scene, camera); 		} 		animate(); 	</script> </body>   </html> 

上面加载的是日本东京的倾斜摄影数据,那在没有倾斜摄影数据的地方呢,比如中国的某些城市,答案是会加载类似于高程与遥感影像的合成数据,如下图:

Three.js中加载和渲染3D Tiles

此时只是把经纬度做以下修改:

tilesRenderer.setLatLonToYUp( 36.266494 * THREE.MathUtils.DEG2RAD, 120.460205 * THREE.MathUtils.DEG2RAD ); // 山东青岛 

总的来说,有时可以在Three.js中加载这样的3D Tiles作为底图来使用,更多的使用方法可参考官方文档:NASA-AMMOS/3DTilesRendererJS: Renderer for 3D Tiles in Javascript using three.js (github.com)

3. 参考资料

[1] NASA-AMMOS/3DTilesRendererJS: Renderer for 3D Tiles in Javascript using three.js (github.com)

[2] 3D Tiles Renderer Options Example (nasa-ammos.github.io)

[3] threejs加载3dtiles(倾斜摄影)数据_threejs 3dtiles-CSDN博客

发表评论

评论已关闭。

相关文章

当前内容话题