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>
然后是引入3DTilesRendererJS,这里引入的是GoogleTilesRenderer
来加载Google的在线地图,另外还需要使用GLTFLoader
和DRACOLoader
以进行数据解析
<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); }
加载的结果如下:
完整代码如下:
<!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>
上面加载的是日本东京的倾斜摄影数据,那在没有倾斜摄影数据的地方呢,比如中国的某些城市,答案是会加载类似于高程与遥感影像的合成数据,如下图:
此时只是把经纬度做以下修改:
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)
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 全程不用写代码,我用AI程序员写了一个飞机大战
· DeepSeek 开源周回顾「GitHub 热点速览」
· 记一次.NET内存居高不下排查解决与启示
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!
2022-03-20 webpack的快速使用
2022-03-20 Vue学习笔记之Vue-Router
2022-03-20 Vue学习笔记之Vue-CLI快速使用