您当前的位置: 首页 > 

HM-hhxx!

暂无认证

  • 6浏览

    0关注

    123博文

    0收益

  • 0浏览

    0点赞

    0打赏

    0留言

私信
关注
热门博文

VUE3+Cesium+Three项目构建

HM-hhxx! 发布时间:2022-08-27 10:03:07 ,浏览量:6

CesiumJS是一个开源、免费的三维地图开发框架,Three.js是一个也开源、免费的三维渲染框架,两者都是基于WebGL技术、使用JavaScript开发的Web前端三维可视化框架,目前在国内外的三维Web开发中使用极为广泛。但Three.js是一个轻量级的跨浏览器JavaScript库,用于在浏览器中创建和显示动画3D计算机图形;而Cesium的可视化内容以地理空间数据为主,如卫星影像、地形、城市级三维模型等,数据量和空间范围都非常大,对数据精度要求更高,并且还具有一系列GIS相关的空间分析功能,但在模型的渲染及可视化方面略逊于Three。

因此,将Cesium的地理数据渲染和GIS功能与Three.js广泛而易用的通用3D API相结合,不仅可以优化模型的渲染精度,也可以加入许多地理信息相关的应用,为新的WebGL体验开启了许多可能性。

目录

1.Cesium+Three实现原理

2.VUE3+Cesium项目创建

3.导入Three

4.实现VUE3+Cesium+Three

5. 项目模块化源码

1.Cesium+Three实现原理

主要原理:两个框架分成不同的视图层,参考 HTML Canvas 元素,并将它们的控制器组合在同一个坐标系中。

可参考如下官方案例:

Integrating Cesium with Three.js – Cesiumhttps://cesium.com/blog/2017/10/23/integrating-cesium-with-threejs/

实现步骤:

1)在HTML中设置两个容器分别容纳Cesium和Three(或初始化Cesium容器后将Three容器追加到Cesium后)。

2)使Three产生的场景覆盖Cesium之上( Three.js DOM 元素位于 Cesium 之上),并禁用Three容器的鼠标事件,通过Cesium同步控制Three。

3)并分别对Cesium渲染器和Three渲染器进行初始化,通过禁用Cesium的默认渲染循环,我们可以将其动画帧与Three.js同步。并设置Three场景的渲染器背景为透明,以达成叠加效果。

4)初始化物体并分别加入至各自的场景之中(注意 Three.js 渲染 z-up 而 Cesium 渲染 y-up。)。

5)进行坐标转换,使对象在地球上正确显示。这包括将大地纬度/经度位置转换为笛卡儿XYZ,并使用WGS84区域从左下角到左上角的方向作为向上矢量,使物体指向地球中心。这也可以通过使用本地笛卡尔东北向或东北向下来计算。

6)请求关键帧并循环渲染器。

2.VUE3+Cesium项目创建

项目创建可参考往期内容:

VUE3构建Cesium项目_HM-hhxx!的博客-CSDN博客_cesium vue3使用VUE3构建cesium项目https://blog.csdn.net/damadashen/article/details/124896474

3.导入Three

安装Three相关依赖:

npm install three --save
or
yarn add three

Three初始化可参考往期内容:

VUE3_Three项目构建(基础模板)_HM-hhxx!的博客-CSDN博客_three项目VUE3配置Three开发环境(配置glsl语法支持)及项目基础模板。https://blog.csdn.net/damadashen/article/details/126064919

4.实现VUE3+Cesium+Three

  
import { onMounted } from "vue"; import * as Cesium from "cesium"; import "./Widgets/widgets.css"; import * as THREE from "three"; // console.log(flightData); // 设置cesium的token Cesium.Ion.defaultAccessToken = "yourToken"; // cesium默认资源路径 window.CESIUM_BASE_URL = "/"; // 设置默认的视角为中国 Cesium.Camera.DEFAULT_VIEW_RECTANGLE = Cesium.Rectangle.fromDegrees( // 西边经度 89.5, // 南边维度 20.4, // 东边经度 110.4, // 北边维度 61.2 ); onMounted(() => { main(); }); // 初始化cesium渲染器 // 初始化three渲染器 // 初始化2个库的3D物体 // 循环渲染 // three全局对象 let three = { renderer: null, camera: null, scene: null, }; // 设置全局cesium对象 let cesium = { viewer: null, }; function main() { // 设置北京显示模型的渲染范围 var minWGS84 = [115.39, 38.9]; var maxWGS84 = [117.39, 40.9]; // 设置cesium容器 var cesiumContainer = document.getElementById("cesiumContainer"); // three.js物体 let objects3D = []; //封装three物体(使three物体具有经纬度) function Object3D(mesh, minWGS84, maxWGS84) { this.threeMesh = mesh;//物体 this.minWGS84 = minWGS84;//范围 this.maxWGS84 = maxWGS84;//范围 } // 初始化cesium渲染器 function initCesium() { cesium.viewer = new Cesium.Viewer(cesiumContainer, { useDefaultRenderLoop: false, selectionIndicator: false, homeButton: false, infoBox: false, sceneModePicker: false, navigationHelpButton: false, animation: false, timeline: false, fullscreenButton: false, baseLayerPicker: false, clock: false, geocoder: false, // 天地图矢量路径图 imageryProvider: new Cesium.WebMapTileServiceImageryProvider({ url: "http://t0.tianditu.com/vec_w/wmts?service=wmts&request=GetTile&version=1.0.0&LAYER=vec&tileMatrixSet=w&TileMatrix={TileMatrix}&TileRow={TileRow}&TileCol={TileCol}&style=default&format=tiles&tk=30d07720fa76f07732d83c748bb84211", layer: "tdtBasicLayer", style: "default", format: "image/jpeg", tileMatrixSetID: "GoogleMapsCompatible", }), //cesium中webgl选项 contextOptions: { webgl: { //透明度 alpha: false, // 抗锯齿 antialias: true, //深度检测 depth: true, }, }, }); // 地图叠加 var imageryLayers = cesium.viewer.imageryLayers; console.log(imageryLayers); var layer = imageryLayers.addImageryProvider( new Cesium.WebMapTileServiceImageryProvider({ url: "http://t0.tianditu.com/img_w/wmts?service=wmts&request=GetTile&version=1.0.0&LAYER=img&tileMatrixSet=w&TileMatrix={TileMatrix}&TileRow={TileRow}&TileCol={TileCol}&style=default&format=tiles&tk=30d07720fa76f07732d83c748bb84211", layer: "tdtBasicLayer", style: "default", format: "image/jpeg", tileMatrixSetID: "GoogleMapsCompatible", }) ); layer.alpha = 0.5; // 设置前往地点 let center = Cesium.Cartesian3.fromDegrees( (minWGS84[0] + maxWGS84[0]) / 2, (minWGS84[1] + maxWGS84[1]) / 2, 20000 ); // 设置相机飞往该区域 cesium.viewer.camera.flyTo({ destination: center, duration: 2, orientation: { heading: Cesium.Math.toRadians(0), pitch: Cesium.Math.toRadians(-90), roll: 0, }, }); } //初始化Three function initThree() { // 设置相机配置 let fov = 45;//视角 let aspect = window.innerWidth / window.innerHeight;//宽高比例 let near = 0.1; let far = 10 * 1000 * 1000;//视域范围 // 初始化场景 three.scene = new THREE.Scene(); three.camera = new THREE.PerspectiveCamera(fov, aspect, near, far); three.renderer = new THREE.WebGLRenderer({ antialias: true,//抗锯齿 alpha: true, }); // 设置渲染器大小 three.renderer.setSize(window.innerWidth, window.innerHeight); // 添加环境光 let ambientLight = new THREE.AmbientLight(0xffffff, 1); three.scene.add(ambientLight); // 添加three.jscanvas元素到cesium容器 cesiumContainer.appendChild(three.renderer.domElement); } // 创建three.js物体 function createMesh() { let geometry = new THREE.BoxBufferGeometry(1, 1, 1); let material = new THREE.MeshBasicMaterial({ color: 0x00ff00, }); let mesh = new THREE.Mesh(geometry, material); // 放大物体 mesh.scale.set(100, 100, 100); // 放大 mesh.position.set(0, 0, 50); // 平移 let meshGroup = new THREE.Group(); meshGroup.add(mesh); // 添加至场景 three.scene.add(meshGroup); // 创建3d物体 let OB3d = new Object3D( meshGroup, [minWGS84[0], minWGS84[1]], [maxWGS84[0], maxWGS84[1]] ); // 添加到3d物体数组 objects3D.push(OB3d); } function renderThree() { // 设置相机跟cesium保持一致 three.camera.fov = Cesium.Math.toDegrees(cesium.viewer.camera.frustum.fovy); // 声明一个将cesium框架的cartesian3转换为three.js的vector3(笛卡尔坐标转换为三维向量) let cartToVec = function (cart) { return new THREE.Vector3(cart.x, cart.y, cart.z); }; // 将3D的物体通过经纬度转换成对应的位置 objects3D.forEach((item, index) => { // 通过经纬度获取中心点的位置 let center = Cesium.Cartesian3.fromDegrees( (item.minWGS84[0] + item.maxWGS84[0]) / 2, (item.minWGS84[1] + item.maxWGS84[1]) / 2 ); item.threeMesh.position.copy(cartToVec(center)); //计算朝向(切面方向-切线向量) //中心高度点 let centerHeight = Cesium.Cartesian3.fromDegrees( (item.minWGS84[0] + item.maxWGS84[0]) / 2, (item.minWGS84[1] + item.maxWGS84[1]) / 2, 1 ); //左下 let bottomLeft = cartToVec( Cesium.Cartesian3.fromDegrees(item.minWGS84[0], item.minWGS84[1]) ); //左上 let topLeft = cartToVec( Cesium.Cartesian3.fromDegrees(item.minWGS84[0], item.maxWGS84[1]) ); //朝向() let latDir = new THREE.Vector3() .subVectors(bottomLeft, topLeft) .normalize(); // console.log(item); //设置查看方向 item.threeMesh.lookAt(centerHeight.x, centerHeight.y, centerHeight.z); //设置朝向 item.threeMesh.up.copy(latDir); }); //设置摄像机矩阵 // 设置相机跟cesium保持一致 three.camera.matrixAutoUpdate = false;//自动更新 //复制cesium相机矩阵 let cvm = cesium.viewer.camera.viewMatrix; let civm = cesium.viewer.camera.inverseViewMatrix; // three相机默认朝向0,0,0 three.camera.lookAt(0, 0, 0); // 设置threejs相机矩阵 three.camera.matrixWorld.set( civm[0], civm[4], civm[8], civm[12], civm[1], civm[5], civm[9], civm[13], civm[2], civm[6], civm[10], civm[14], civm[3], civm[7], civm[11], civm[15] ); three.camera.matrixWorldInverse.set( cvm[0], cvm[4], cvm[8], cvm[12], cvm[1], cvm[5], cvm[9], cvm[13], cvm[2], cvm[6], cvm[10], cvm[14], cvm[3], cvm[7], cvm[11], cvm[15] ); //设置宽高比例 let width = cesiumContainer.clientWidth; let height = cesiumContainer.clientHeight; three.camera.aspect = width / height; //更新相机矩阵 three.camera.updateProjectionMatrix(); //设置尺寸大小 three.renderer.setSize(width, height); three.renderer.clear(); three.renderer.render(three.scene, three.camera); } function renderCesium() { cesium.viewer.render(); } //循环函数,不断请求动画帧渲染 function loop() { requestAnimationFrame(loop); // cesium渲染 renderCesium(); // three.js渲染 renderThree(); } //初始化调用 initCesium(); initThree(); createMesh(); loop(); } * { margin: 0; padding: 0; } #cesiumContainer { width: 100vw; height: 100vh; position: relative; } #cesiumContainer>canvas { position: absolute; top: 0; left: 0; /* 设置鼠标事件穿透 */ pointer-events: none; }

实现效果:

5. 项目模块化源码

VUE3+Cesium+Three项目源码_HM-hhxx!的博客-CSDN博客Vue+Cesium+Three项目构建的详解及源码。https://blog.csdn.net/damadashen/article/details/126585531?spm=1001.2014.3001.5501

关注
打赏
1663160980
查看更多评论
立即登录/注册

微信扫码登录

0.1138s