CesiumJS整合ThreeJS插件封装

news2024/12/29 9:59:51

最近做项目有一个三维需求使用CesiumJS比较难以实现,发现THREEJS中效果比较合适,于是准备将THREEJS整合到CesiumJS中

为实现效果所需我们找到官方Integrating Cesium with Three.js博客,于是根据该博客提供的思路去实现整合

文章目录

    • 一、创建ThreeJS类
    • 二、插件threeJs 优化
      • 1、创建ThressScene工具
        • 1.1、同步camera
        • 1.2、同步场景中的物体
        • 1.3、同步render
      • 2、插件使用
        • 2.1 引入插件初始化map
        • 2.1 初始化Meshes
        • 2.2 初始化threeScene
        • 2.3 效果预览

一、创建ThreeJS类

为了开发时更好的扩展性把他写到了一个ThreeJS 类里面,功能直接调用即可

function ThreeJs(viewer, cesiumGlobal, defaultStatic, threeConf) {
  if (viewer && threeConf) {
    const { threeGlobal, containerId, threeContainerId } = threeConf;
    Cesium = cesiumGlobal;
    THREE = threeGlobal;
    this._viewer = viewer;
    this._containerId = containerId;
    this._threeContainerId = threeContainerId;
    this._initContainer();
    this._initThree();
  }
}
//部分省略......

项目中使用

import { ThreeJs } from 'cesium_dev_kit'

// 初始化map
 initMap (){
     const ThreeJsObj = new ThreeJs({
        cesiumGlobal: Cesium,
        threeGlobal: THREE,
        containerId: 'cesiumContainer',
        threeContainerId: 'threeContainer',
//部分省略......
      })
      this.c_viewer = ThreeJsObj.viewer;
      this.threeJs = ThreeJsObj.threeJs;
      this.initThree(this.threeJs);
  },
  // 初始化ThreeJs
 initThree (ThreeJs) {
      const threeDObject = this.create3DOject(ThreeJs, this.c_viewer);
      ThreeJs.addThreeObjects(threeDObject)

      this.c_viewer.camera.lookAtTransform(Cesium.Matrix4.IDENTITY)//解除视角锁定
    },
    // 创建三维模型
  create3DOject (threeObj, viewer) {
      let three = threeObj._three;
      let _3Dobjects = [], _3DOB;
      let entity = {
        name: 'Polygon',
        polygon: {
          hierarchy: Cesium.Cartesian3.fromDegreesArray([
            minWGS84[0], minWGS84[1],
            maxWGS84[0], minWGS84[1],
            maxWGS84[0], maxWGS84[1],
            minWGS84[0], maxWGS84[1]
          ]),
          material: Cesium.Color.RED.withAlpha(0.1)
        }
      }
      let Polypon = viewer.entities.add(entity);
      let doubleSideMaterial = new THREE.MeshNormalMaterial({
        side: THREE.DoubleSide
      });
//部分省略......
      return _3Dobjects;
    }   

根据官网的思量整合后最终实现效果如下
实现效果
效果是实现了,但是这个封装耦合性相当高,多个功能都需要使用这个插件时特别蹩脚,于是开始了下一次造…

二、插件threeJs 优化

理解官方案例的思路整合关键主要有三个方面,第一个是同步Camera,第二个是同步Scene中的物体位置,第三个是需要同步CesiumJS和THREEJS 的render重绘程序

1、创建ThressScene工具

为了扩展与管理我们抽离一个Scene 的工具js

class Scene extends THREE.Scene {}

在这个js 里面去实现插件操作的优化

1.1、同步camera

创建一个updateCameraMatrix来同步项目位置,核心代码如下

  updateCameraMatrix() {
      //同步相机
      this.camera.fov = Cesium.Math.toDegrees(
        this.cesiumViewer.camera.frustum.fovy
      ) // ThreeJS FOV is vertical
      this.camera.updateProjectionMatrix()

      this.camera.matrixAutoUpdate = false
      const cvm = this.cesiumViewer.camera.viewMatrix
      const civm = this.cesiumViewer.camera.inverseViewMatrix
      this.camera.lookAt(this.cameraCenter)
//部分省略......
      const width = this.cesiumViewer.scene.canvas.clientWidth
      const height = this.cesiumViewer.scene.canvas.clientHeight
      this.camera.aspect = width / height
      this.camera.updateProjectionMatrix()

      this.renderer.setSize(width, height)

      return this
    }
1.2、同步场景中的物体

创建一个updateGroupMatrixWorld来进行物体位置同步,核心代码如下

	 // 重写add 方法
     add(object) {
      if (arguments.length > 1) {
        for (let i = 0; i < arguments.length; i++) {
          this.childrenGroup.add(arguments[i])
        }

        return this
      }
	//部分省略......
      return this
    }
    updateGroupMatrixWorld() {
      // 得到面向模型的前向方向
      const center = this.cartesian3ToVector(
        Cesium.Cartesian3.fromDegrees(this.lngLat[0], this.lngLat[1], 0)
      )
      // 使用从左下到左上的方向作为上向量
      const topLeft = this.cartesian3ToVector(
        Cesium.Cartesian3.fromDegrees(this.lngLat[0], this.lngLat[1], 2)
      )
      const latDir = new THREE.Vector3().subVectors(center, topLeft).normalize()

      // 配置实体的位置和方向
      // this.syncGroup.position.copy(center)
      this.syncGroup.lookAt(latDir)
      this.syncGroup.up.copy(latDir)
      this.syncGroup.updateMatrix()

      this.cameraOffset.copy(center)

      this.sphere.position.set(0 - center.x, 0 - center.y, 0 - center.z)
      this.syncGroup.up.set(0, 0, -1)
      this.up.set(0, 0, -1)

      return this
    }
1.3、同步render
    renderCesium() {
      this.cesiumViewer.render()
      return this
    }

    renderThree() {
      this.renderer.render(this, this.camera)
      return this
    }
    
   loop(callback) {
    const _loop = function () {
      let time = requestAnimationFrame(_loop)
      callback && callback(time)
    }
    _loop()
  }

2、插件使用

插件改完了心里还是有点鸡冻,马上在项目中引入开始测试

2.1 引入插件初始化map
import { initCesium } from 'cesium_dev_kit'

// 初始化map
 initMap (){
      const { viewer, threeJs, base, graphics, material } = new initCesium({
        cesiumGlobal: Cesium,
        threeGlobal: THREE,
        containerId: 'cesiumContainer',
        threeContainerId: 'threeContainer',
		//部分省略......
      })
      this.c_viewer = viewer;
      this.threeJs = threeJs;
      this.base = base;
      this.graphics = graphics;
      this.material = material
      this.initThree(this.threeJs);
      // this.getClickPosition()
      this.createAEllipsoid();
      this.createAFanShape();
  },
2.1 初始化Meshes

这里我们就使用官方的extrude案例

    initMeshes (scene) {
      // 环形 extrude
      const closedSpline = new THREE.CatmullRomCurve3([
        new THREE.Vector3(-60, 30, 60), // 左下
        new THREE.Vector3(-60, 100, 60), // 左中
        new THREE.Vector3(-60, 220, 60), // 左上
        new THREE.Vector3(60, 80, -60), // 右中
        new THREE.Vector3(60, 30, -60), // 右下
      ]);
      // 2、extrude settings
      closedSpline.curveType = "catmullrom";
      closedSpline.closed = true;
      const extrudeSettings = {
        steps: 100,
        bevelEnabled: false,
        extrudePath: closedSpline,
      };
      // 3、construct shape
      const r = 20; // 截面半径
      const pts1 = [];
      const count = 3; // 截面的棱边数量
      for (let index = 0; index < count; index++) {
        // index/count 几分之几,2π为周长
        const a = (index / count) * Math.PI * 2;
        pts1.push(new THREE.Vector2(r * Math.cos(a), r * Math.sin(a)));
      }
      const shape1 = new THREE.Shape(pts1);
      // create geometry
      const geometry1 = new THREE.ExtrudeGeometry(shape1, extrudeSettings);
      // create material
      const material1 = new THREE.MeshLambertMaterial({
        color: 0xb00000,
      });
      // assembly meshes
      const mesh1 = new THREE.Mesh(geometry1, material1);
      // add mesh to scene
      scene.add(mesh1);
		//部分省略......
    },
2.2 初始化threeScene
    initThree (ThreeJs) {
      const { scene, camera } = ThreeJs.initThree({ center, axesHelper: true, threeHabit: false });
      this.initLight(scene, camera)
      this.initMeshes(scene);
      this.flyto(scene);
      ThreeJs.loop(function () {
        scene.update();
      })
    },
2.3 效果预览

光线投射
光线投射 图形挤压图形挤压烟花效果
烟花效果

奔跑的士兵
奔跑的士兵

嗯嗯测试了几个功能看了基本上问题不大了,ok先告一段落后期继续优化…

感谢您的阅读,最后附上插件下载与源码地址

  • 插件下载安装
npm install cesium_dev_kit
  • 案例源码地址
    https://github.com/dengxiaoning/cesium_dev_kit

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1842937.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

VMware虚拟机三种网络模式设置 - NAT(网络地址转换模式)

一、前言 在前一篇《Bridged&#xff08;桥接模式&#xff09;》中&#xff0c;我详细介绍了虚拟机网络模式设置中的桥接模式。今天详细讲解一下NAT&#xff08;网络地址转换模式&#xff09;。 在虚拟机&#xff08;VM&#xff09;中&#xff0c;NAT&#xff08;Network Addre…

微信小程序navigateTo异常(APP-SERVICE-SDK:Unknown URL)

背景 在开发小程序时&#xff0c;可能会用到banner&#xff0c;通过banner跳转至各种子页面。但是因为小程序自身的因素&#xff0c;有些是不允许的&#xff0c;比如通过banner跳转一个http/https链接。如果使用 wx.navigateTo完成跳转时&#xff0c;就会发生异常。 navigate…

Latex添加参考文献的两种方案

Latex添加参考文献的两种方案 方案1&#xff1a;一般插入法方案2&#xff1a;使用BibTex 方案1&#xff1a;一般插入法 此方案在latex结尾直接插入参考文献&#xff0c;一般从IEEE官网下载的模板好像默认都是这样的&#xff01;下面为参考格式&#xff1a; 这种方案比较容易操…

产品心理学:曝光效应

曝光效应&#xff08;the exposure effect or the mere exposure effect&#xff09;&#xff1a;又谓多看效应、&#xff08;简单、单纯&#xff09;暴露效应、&#xff08;纯粹&#xff09;接触效应等等。 它是一种心理现象&#xff0c;指的是我们会偏好自己熟悉的事物&#…

JVM中的垃圾回收机制

文章目录 什么是垃圾为什么需要垃圾回收早期垃圾回收Java的垃圾回收机制垃圾回收主要关注的区域垃圾判定算法引用计数算法可达性分析算法 垃圾收集算法标记清除算法复制算法标记整理算法分代收集思想增量收集算法分区算法 什么是垃圾 垃圾回收&#xff08;Garbage Collection&…

2024-06月 | 维信金科 | 风控数据岗位推荐,高收入岗位来袭!

今日推荐岗位&#xff1a;策略分析经理/分析专家、贷前、中策略分析、风控模型分析。 风控部门是金融业务的核心部门&#xff0c;而从事风控行业的人即称之为风险管理者。是大脑&#xff0c;是最最最重要的部门之一。今日推荐岗位的核心技能分布如下&#xff1a; 简历发送方式…

磁盘未格式化:深度解析、恢复策略与预防措施

一、磁盘未格式化的定义与现象 在计算机存储领域&#xff0c;磁盘未格式化通常指的是磁盘分区或整个磁盘的文件系统信息出现丢失或损坏的情况&#xff0c;导致操作系统无法正确读取和识别磁盘上的数据。当尝试访问这样的磁盘时&#xff0c;系统往往会弹出一个警告框&#xff0…

001 Spring介绍

文章目录 特点1.方便解耦&#xff0c;简化开发2.AOP编程的支持3.声明式事务的支持4.方便程序的测试5.方便集成各种优秀框架6.降低Java EE API的使用难度7.Java源码是经典学习范例 好处什么是耦合和内聚耦合性&#xff0c;也叫耦合度&#xff0c;是对模块间关联程度的度量内聚标…

蓝鹏测控公司全长直线度算法项目多部门现场组织验收

关键字:全场直线度算法,直线度测量仪,直线度检测,直线度测量设备, 6月18日上午&#xff0c;蓝鹏测控公司全长直线度算法项目顺利通过多部门现场验收。该项目由公司技术部、开发部、生产部等多个部门共同参与&#xff0c;旨在提高直线度测量精度&#xff0c;满足高精度制造领域需…

ppt转换word文档怎么操作?6个软件让你自己轻松转换文件

ppt转换word文档怎么操作&#xff1f;6个软件让你自己轻松转换文件 将PPT文件转换为Word文档是一项常见的任务&#xff0c;可以通过多种软件和在线工具来实现。以下是六款常用的软件和工具&#xff0c;它们可以帮助您轻松地将PPT文件转换为Word文档&#xff1a; 1.迅捷PDF转换…

Windows上PyTorch3D安装踩坑记录

直入正题&#xff0c;打开命令行&#xff0c;直接通过 pip 安装 PyTorch3D : (python11) F:\study\2021-07\python>pip install pytorch3d Looking in indexes: http://mirrors.aliyun.com/pypi/simple/ ERROR: Could not find a version that satisfies the requirement p…

我们是否需要AI服务器?推动人工智能繁荣发展的AI服务器

揭穿人工智能服务器的炒作 人工智能的研究已经有几十年了&#xff0c;早在 1960 年代&#xff0c;生成式人工智能就已应用于聊天机器人。然而&#xff0c;2022 年 11 月 30 日发布的 ChatGPT 聊天机器人和虚拟助手席卷了 IT 界&#xff0c;让 GenAI 成为家喻户晓的术语&#x…

CheckPoint 防火墙 CVE-2024-24919 VPN 漏洞修复说明

1. 漏洞说明 在 2024 年 5 月 27 日进行安全更新后&#xff0c;Check Point 的专门工作组将继续调查未经授权访问我们客户使用的 VPN 产品的企图。 2024 年 5 月 28 日&#xff0c;我们在远程访问 VPN 社区和移动访问软件刀片中使用 IPsec VPN 的安全网关中发现了一个漏洞 (…

海豚调度监控:使用图关系网络解决核心链路告警,减轻任务运维负担!

&#x1f4a1; 本系列文章是 DolphinScheduler 由浅入深的教程&#xff0c;涵盖搭建、二开迭代、核心原理解读、运维和管理等一系列内容。适用于想对 DolphinScheduler了解或想要加深理解的读者。 祝开卷有益。大数据学习指南 大家好&#xff0c;我是小陶&#xff0c;之前分享了…

Python | Leetcode Python题解之第155题最小栈

题目&#xff1a; 题解&#xff1a; class MinStack:def __init__(self):self.stack []self.min_stack [math.inf]def push(self, x: int) -> None:self.stack.append(x)self.min_stack.append(min(x, self.min_stack[-1]))def pop(self) -> None:self.stack.pop()sel…

Java8 --- Gradle安装及测试使用

目录 一、Gradle 1.1、简介 1.2、安装 1.2.1、注意事项 1.2.2、安装流程 1.2.3、配置共享仓库 1.3、构建项目 1.4、常用指令 1.4.1、gradle classes 1.4.2、gradle clean 1.4.3、gradle test 1.4.4、gradle build 1.5、修改Maven下载源 1.6、Wrapper包装器 1.…

蓝牙模块在智能城市构建中的创新应用

随着科技的飞速发展&#xff0c;智能城市的概念已经逐渐从理论走向实践。物联网技术作为智能城市构建的核心驱动力&#xff0c;正在推动着城市基础设施、交通管理、环境监测等领域的深刻变革。蓝牙模块&#xff0c;作为物联网技术的重要组成部分&#xff0c;以其低功耗、低成本…

数据结构与算法-差分数组及应用

差分数组 差分数组&#xff1a; 其实差分数组是创建一个一个辅助数组&#xff0c;用来表示给定数组的变化&#xff0c;一般用来对数组进行区间修改的操作。 频繁操作数组区间的问题 假设我们要对一个数组进行区间操作。数组为 a {10,10, 20,20,50,… 100}。数组数据比较多。 对…

中新赛克两款数据安全产品成功获得“可信数安”评估测试证书

6月19日&#xff0c;2024数据智能大会在北京盛大召开。 会上&#xff0c;中国2024年上半年度“可信数安”评估测试证书正式颁发。中新赛克两款参评产品凭借过硬的技术水准和卓越的应用效果&#xff0c;成功获得专项测试证书。 2024年上半年度“可信数安”评估测试通过名单 中新…

SpringBoot集成logback初始化源码解析(部分)

一.SpringBoot配置扩展点 SpringBoot日志模块使用监听的方式进行初始化&#xff0c;在SpringBoot项目启动后&#xff0c;会通知日志监听器 在日志监听器中ApplicationStartingEvent事件用来确定到底使用哪个日志系统&#xff0c;logback log4j等 在日志监听器中ApplicationEn…