GIS融合之路(三)CesiumJS和ThreeJS相机同步
同样在这篇文章开始前重申一下,山海鲸并没有使用ThreeJS引擎。但由于ThreeJS引擎使用广泛,下文中直接用ThreeJS同CesiumJS的整合方案代替山海鲸中3D引擎和CesiumJS整合。
系列传送门:
山海鲸可视化:GIS融合之路(一)技术选型CesiumJS/loaders.gl/iTowns?
山海鲸可视化:GIS融合之路(二)CesiumJS和ThreeJS深度缓冲区整合
按照惯例,文章开始前先自夸,大家可以参考一下山海鲸中相机整合的效果。
详细的内容可以前往这篇视频教程:
感兴趣朋友也欢迎下载软件试一试:山海鲸可视化-一站式数字孪生开发平台-海量数据可视化大屏模板
相机的整合分为三个部分,分别是:1.同步相机fov 2.同步相机位置 3.同步相机方向
一、同步相机fov
我们先来处理最简单的相机fov,我们先看下相机的fov是什么:

可以看出,相机的fov就是相机的视角宽度和高度,我们日常所说的广角相机,鱼眼相机就是fov很大的相机,而相机主要有两个fov参数,一个是横向的vfov,一个是纵向的hfov,因此我们只需要把两个相机自己的fov对应设置上即可,我们先看一下两边的文档中分别怎么描述自己的fov的:


此处一定要敲黑板,fov本身是一个很简单的概念,理论上直接同步两边相机的fov就可以完成。但这里面起码有两个坑,一个是Cesium用的是radians,而threejs用的是degrees,需要做一次转换。另外 CesiumJS有两个fov,和threejs对应的是fovy。这两个问题处理好了就简单了,代码也很简单。
THREE.camera.fov = Cesium.Math.toDegrees(CESIUM.viewer.camera.frustum.fovy)
当然山海鲸采用的是双向同步,反过来的话只需要根据文档内容将山海鲸引擎的fov赋值给CESIUM即可。
二、同步相机位置
搞定了相机fov,下一步就是同步相机的位置,同步相机位置就得先了解一下Cesium的坐标系,我们主要要用到Cesium的两套坐标系,一个是地心坐标,一个是经纬度坐标系。这两个坐标系间Cesium提供了标准的转换方法。
而Cesium同Threejs的坐标转换时,Threejs使用的坐标系对应在Cesium中实际上是东北上坐标系,这两个坐标系的关系如图所示:

Cesium也提供的标准的函数来获得东北上坐标系和地心坐标系的转换矩阵,因此我们可以通过如下代码将Threejs中的坐标转换为Cesium中的地心坐标系,同理也可以反过来将Cesium中的地心坐标系转换为东北天坐标系,也就是threejs中的坐标系,实现坐标系的双向转换。
let origin = Cesium.Cartographic.toCartesian(originCartographic)
let transform = Cesium.Transforms.eastNorthUpToFixedFrame(origin);
let result1 = Cesium.Matrix4.multiplyByPoint(transform, cameraPosition);
山海鲸中需要提供了两种控制方式,一种是控制Threejs相机同步到Cesium相机中,一种是控制Cesium相机同步到Threejs中。所以最后值得注意的就是在第一种方式中需要将Cesium相机自己的控制个关闭掉,这个也很简单,只需要调用以下代码即可:
scene.screenSpaceCameraController.enableInputs = false;
最后,值得注意的是Cesium除了提供3d球面绘制模式( Cesium.SceneMode.SCENE3D)以外,还提供了2.5d的绘制模式(Cesium.SceneMode.COLUMBUS_VIEW),在COLUMBUS_VIEW的模式下,则需要做一步web墨卡托坐标的投影才能够完成坐标转换。
至此,我们终于实现了双向的相机同步。完成了这些,GIS系统算是正式可以在山海鲸中使用了。而且后面的章节我们会提到,山海鲸开放了整合CesiumJS的接口,因此只需要开启反向相机同步,即可无缝的将之前的CesiumJS代码迁移过来了。虽然整合成功了,但是CesiumJS依然是CesiumJS的样子,并没有任何变化,如果是这样,为什么不直接用CesiumJS,干嘛还有整合呢?

我们当然不能就此止步,作为一个对客户负责的技术负责人,客户不仅要求山海鲸可以加载所有的GIS数据,还拿效果和UE对比,觉得Cesium For Unreal的视觉效果更好看。要求我们把Unreal的效果搬到Web上来,什么,你说不可能?没有条件,创造条件也要上。只能再苦一苦开发团队了。
GIS融合之路(三)CesiumJS和ThreeJS相机同步的更多相关文章
- BIM与GIS融合的意义——从智慧工地到智慧城市
随着智慧城市概念的发展,BIM与GIS融合的概念深入人心,通过整合BIM的参数化描述建筑组件性质的特性与GIS宏观的几何空间概念,将 BIM 描述单体建筑物的特性通过 GIS 拓展至三维城市. BIM ...
- 学习之路三十九:新手学习 - Windows API
来到了新公司,一开始就要做个程序去获取另外一个程序里的数据,哇,挑战性很大. 经过两周的学习,终于搞定,主要还是对Windows API有了更多的了解. 文中所有的消息常量,API,结构体都整理出来了 ...
- 我的VSTO之路(三):Word基本知识
原文:我的VSTO之路(三):Word基本知识 在前一篇文章中,我初步介绍了如何如何开发一个VSTO程序,在本文中,我将进一步深入介绍Word的插件开发.Word是一个大家在日常工作中一直接触的文档工 ...
- 相机IMU融合四部曲(三):MSF详细解读与使用
相机IMU融合四部曲(三):MSF详细解读与使用 极品巧克力 前言 通过前两篇文章,<D-LG-EKF详细解读>和<误差状态四元数详细解读>,已经把相机和IMU融合的理论全部都 ...
- Servlet基础(三) Servlet的多线程同步问题
Servlet基础(三) Servlet的多线程同步问题 Servlet/JSP技术和ASP.PHP等相比,由于其多线程运行而具有很高的执行效率. 由于Servlet/JSP默认是以多线程模式执行的, ...
- 转载 三、并行编程 - Task同步机制。TreadLocal类、Lock、Interlocked、Synchronization、ConcurrentQueue以及Barrier等
随笔 - 353, 文章 - 1, 评论 - 5, 引用 - 0 三.并行编程 - Task同步机制.TreadLocal类.Lock.Interlocked.Synchronization.Conc ...
- 三、并行编程 - Task同步机制。TreadLocal类、Lock、Interlocked、Synchronization、ConcurrentQueue以及Barrier等
在并行计算中,不可避免的会碰到多个任务共享变量,实例,集合.虽然task自带了两个方法:task.ContinueWith()和Task.Factory.ContinueWhenAll()来实现任务串 ...
- Socket-IO 系列(三)基于 NIO 的同步非阻塞式编程
Socket-IO 系列(三)基于 NIO 的同步非阻塞式编程 缓冲区(Buffer) 用于存储数据 通道(Channel) 用于传输数据 多路复用器(Selector) 用于轮询 Channel 状 ...
- Windows提高_2.3第三部分:内核区同步
第三部分:内核区同步 等待函数(WaitForObject) 等待函数的形式 单个:WaitForSingleObject 多个:WaitForMultipleObjects 一个可以被等待的对象通常 ...
- [书籍翻译] 《JavaScript并发编程》第三章 使用Promises实现同步
本文是我翻译<JavaScript Concurrency>书籍的第三章 使用Promises实现同步,该书主要以Promises.Generator.Web workers等技术来讲解J ...
随机推荐
- do { } while(){ }
1 var j=10; 2 do{ 3 console.log("十八岁以下禁止观看") 4 console.log(j); 5 j++; //j为18之前都不执行while 6 ...
- Github美化日记 - 又菜又爱玩
Github美化日记 - 又菜又爱玩 一.咱就说 无论是技术大牛, 或者是技术小菜, 都希望有一个好看的Github首页吧!(快说你想要! ![iShot_2023-04-05_18.58.32.mi ...
- CentOS 9 开局配置
CentOS 9 开局配置 CentOS 9 发布有几年了,一直没有尝试使用,CentOS 9 有一些变动. 查看系统基础信息 # 查看系统基础信息 [root@chenby ~]# neofetch ...
- 安装Minikube并启动一个Kubernetes环境
安装Minikube并启动一个Kubernetes环境 Minikube 是一种轻量级的Kubernetes 实现,可在本地计算机上创建VM 并部署仅包含一个节点的简单集群.Minikube 可用于L ...
- python入门教程之六运算符
什么是运算符? 本章节主要说明Python的运算符.举个简单的例子 4 +5 = 9 . 例子中,4 和 5 被称为操作数,"+" 称为运算符. Python语言支持以下类型的运算 ...
- 四月十七日Java基础知识点
1.默认构造方法:如果class前面有public修饰符,则默认的构造方法也会是public的.由于系统提供的默认构造方法往往不能满足需求,所以用户可以自己定义类的构造方法来满足需要,一旦用户为该类定 ...
- 快速重拾 Tmux
Tmux 是一个 Linux (Mac OS也支持)下的终端复用器,相较于 Screen 更为强大,但快捷键和操作逻辑也更复杂,一段时间不用,就很容易忘记相关的命令和快捷键.本文旨在通过一个简单的场景 ...
- 实时分布式低延迟OLAP数据库Apache Pinot探索实操
@ 目录 概述 定义 特性 何时使用 部署 Local安装 快速启动 手动设置集群 Docker安装 快速启动 手动启动集群 Docker Compose 实操 批导入数据 流式导入数据 概述 定义 ...
- if elseif else 怎么用?
问题:求三个数中的最大值 上代码-- 第一种 两两比较 每次取较大值 和第三个值比较 最终得到最大值 private static void maxIf2() { int a = (int) ( ...
- win11 计算器的进制转换