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的在线地图,另外还需要使用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);
}

加载的结果如下:

完整代码如下:

<!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)

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

Three.js中加载和渲染3D Tiles的更多相关文章

  1. java使用htmlunit工具抓取js中加载的数据

    htmlunit 是一款开源的java 页面分析工具,读取页面后,可以有效的使用htmlunit分析页面上的内容.项目可以模拟浏览器运行,被誉为java浏览器的开源实现.这个没有界面的浏览器,运行速度 ...

  2. Three.js中加载外部fbx格式的模型素材

    index.html部分: index.js部分: Scene.js部分:

  3. (转载)arcgis for js - 解决加载天地图和WMTS服务,WMTS服务不显示的问题,以及wmts服务密钥。

    1 arcgis加载天地图和wmts服务 arcgis for js加载天地图的例子网上有很多,这里先不写了,后期有空再贴代码,这里主要分析下WMTS服务为什么不显示,怎么解决. 条件:这里的WMTS ...

  4. JS 动态加载脚本 执行回调_转

    关于在javascript里面加载其它的js文件的问题可能很多人都遇到过,但很多朋友可能并不知道怎么判断我们要加载的js文件是否加载完成,如果没有加载完成我们就调用文件里面的函数是不会成功的.本文讲解 ...

  5. JS 动态加载脚本 执行回调

    JS 动态加载脚本  执行回调 关于在javascript里面加载其它的js文件的问题可能很多人都遇到过,但很多朋友可能并不知道怎么判断我们要加载的js文件是否加载完成,如果没有加载完成我们就调用文件 ...

  6. JS和CSS加载(渲染)机制不同

    一.结论 CSS可以在页面加载完成后随时渲染.举个例子:通过js给某个元素加一个id或者css,只要这个id或者css有对应的样式,此元素的样式就会自动生效. JS不可以在页面加载完成后生效.最明显的 ...

  7. 浏览器加载和渲染html的顺序(html/css/js)

    最近在学习前端的技术,把html.js.css的基础知识看了看.感觉越看越觉得前端并不比后端容易,技术含量还是相当大的.今天突然想弄明白浏览器到底是怎么加载和渲染html的?html中的DOM.js文 ...

  8. CSS样式表、JS脚本加载顺序与SpringMVC在URL路径中传参数与SpringMVC 拦截器

    CSS样式表和JS脚本加载顺序 Css样式表文件要在<head>中先加载,这样网页显示时可以第一次就渲染出正确的布局和样式,网页就不会闪烁,或跳变 JS脚本尽可能放在<body> ...

  9. vue中加载three.js的gltf模型

    vue中加载three.js的gltf模型 一.开始引入three.js相关插件.首先利用淘宝镜像,操作命令为: cnpm install three //npm install three也行 二. ...

  10. 在HTML中使用JavaScript(浏览器对js的加载机制分析)

    前言: 向HTML页面中插入JavaScrip的主要方法,就是使用<script>标签.主要探讨<script>标签的在HTML页面的渲染机制.对应的业务场景:从js的加载机制 ...

随机推荐

  1. P4414题解

    原题 题意简述: 有 $3$ 个整数,将他们排序,将它们存到 $a,b,c$ 三个变量中,满足 $a<b<c$,再按照规则输出. 不难发现,我们可以用到 sort 函数,这个函数的作用是将 ...

  2. ffmpeg之avformat_alloc_output_context2

    函数原型: int avformat_alloc_output_context2(AVFormatContext **ctx, const AVOutputFormat *oformat, const ...

  3. 李宏毅2022机器学习HW3 Image Classification

    Homework3 数据集下载 在本地环境下进行实验总是令人安心,但是又苦于网上找不到数据集,虽然kaggle上有数据集但是下载存在问题 于是有了一个天才的想法,间接从kaggle上下载(利用outp ...

  4. RunnerGo低代码测试体验

    RunnerGo是基于go语言自研的一款企业级全栈式测试平台,采用Apache-2.0 license开源协议,涵盖接口测试.性能测试.UI测试和项目管理等功能,并独创"拖拉拽"的 ...

  5. Direct2D 旋转篇

    微软文档:Transforms 本篇通过官方文档学习,整理出来的demo,初始样本请先创建一个普通的desktop app. ID2D1SolidColorBrush* m_pOriginalShap ...

  6. Flutter学习

    常用网址 免费下载 !<AliFlutter 体系化建设和实践> Flutter 开发文档 Flutter实战 Dart 编程语言概览 pub仓库 main函数使用了(=>)符号, ...

  7. Avalonia 跨平台框架中如何以正确的姿势使用 OpenGL ES 渲染。

    前言 这是一篇很水的文章,没有任何技术含量,在 Github 已经有很多人对 Avalonia 的 OpenGL ES 支持进行了讨论,但是我还是想写一篇文章来记录一下我是如何在 Avalonia 中 ...

  8. 【Azure 存储服务】.NET7.0 示例代码之上传大文件到Azure Storage Blob (二)

    问题描述 在上一篇博文([Azure 存储服务].NET7.0 示例代码之上传大文件到Azure Storage Blob (一):https://www.cnblogs.com/lulight/p/ ...

  9. 【Azure 事件中心】如何查看事件中心的消息中具体报文内容呢?

    问题描述 如何查看事件中心的消息中具体报文内容呢? 问题解答 正常情况是通过 Event Hub 的消费端获取消息进行处理查看,但是没有客户端代码的情况下,也可以通过微软的默认客户端Service B ...

  10. 非正式全面解析 NebulaGraph 中 Session 管理

    NebulaGraph 论坛最近有些讨论帖,各种姿势来问 NebulaGraph Session 管理相关的事情,我寻思这也不是一个法子,还是来写一篇文章来讲述下 NebulaGraph 中的 Ses ...