https://blog.csdn.net/zhishiqu/article/details/79077883

这是威尔逊Muktar关于整合Three.js与铯的客人帖子。Three.js是一个轻量级的跨浏览器JavaScript库,用于在浏览器中创建和显示动画3D计算机图形。将Cesium的行星级渲染和GIS功能与Three.js广泛而易用的通用3D API相结合,为新的WebGL体验开启了许多可能性。你可以在这里查看这个演示实时版本代码本身。 - 加里

3D JavaScript库现在已经完全成熟并且广为人知,使得开发人员可以避免在浏览器中使用3D的麻烦。开发人员可以轻松创建相机,对象,灯光,材质和图形,并选择渲染器,使用HTML 5的画布,WebGL或SVG绘制场景。

因为Cesium和Three.js都是用于3D可视化的,并且是从头开始用JavaScript构建的,所以它们有相似之处,可以将这些惊人的库集成在一起。我对这两个框架进行整合的方法比看起来简单:我将这两个框架分离到了不同的视图中,并参考了HTML Canvas元素,并将它们的控制器组合在同一个坐标系中。由于两者都是开源的,我可以分享这个演示,这将涵盖一些基础知识。

左:铯现场。中心:Three.js场景。右:组合的场景。

铯是一个为了创建数字地球而开发的三维图书馆,其渲染对于真实的地球来说是非常精确的。借助3D Tiles,开发人员可以将几乎所有内容都重新渲染到浏览器中的数字画布上。

指导铯的基本渲染原理与Three.js没有太大区别。Three.js是用于渲染3D对象的强大3D库。通过在两个场景中复制铯的球面坐标系和匹配的数字地球,很容易将两个单独的渲染引擎层整合到一个主场景中。我将给出一个关于其整合方法的简单说明,如下所示:

  • 初始化Cesium渲染器,
  • 初始化Three.js渲染器,
  • 初始化这两个库的3D对象,和
  • 循环渲染器。

主功能

该html需要三个容器和铯:

  1. <body>
  2. <div id="cesiumContainer"></div>
  3. <div id="ThreeContainer"></div>
  4. </body>
  5. <script> main(); </script>

这是主要功能:

  1. function main(){
  2. // boundaries in WGS84 to help with syncing the renderers
  3. var minWGS84 = [115.23,39.55];
  4. var maxWGS84 = [116.23,41.55];
  5. var cesiumContainer = document.getElementById("cesiumContainer");
  6. var ThreeContainer = document.getElementById("ThreeContainer");
  7.  
  8. var _3Dobjects = []; //Could be any Three.js object mesh
  9. var three = {
  10. renderer: null,
  11. camera: null,
  12. scene: null
  13. };
  14.  
  15. var cesium = {
  16. viewer: null
  17. };
  18.  
  19. initCesium(); // Initialize Cesium renderer
  20. initThree(); // Initialize Three.js renderer
  21. init3DObject(); // Initialize Three.js object mesh with Cesium Cartesian coordinate system
  22. loop(); // Looping renderer
  23. }

初始化铯渲染器

首先,我们可以通过添加自定义图像或默认提供的其他部分来自定义铯查看器。通过禁用Cesium的默认渲染循环,我们可以将其动画帧与Three.js同步。

  1. function initCesium(){
  2. cesium.viewer = new Cesium.Viewer(cesiumContainer,{
  3. useDefaultRenderLoop: false,
  4. selectionIndicator : false,
  5. homeButton:false,
  6. sceneModePicker:false,
  7. navigationHelpButton:false,
  8. infoBox : false,
  9. navigationHelpButton:false,
  10. navigationInstructionsInitiallyVisible:false,
  11. animation : false,
  12. timeline : false,
  13. fullscreenButton : false,
  14. allowTextureFilterAnisotropic:false,
  15. contextOptions:{
  16. webgl: {
  17. alpha: false,
  18. antialias: true,
  19. preserveDrawingBuffer : true,
  20. failIfMajorPerformanceCaveat: false,
  21. depth:true,
  22. stencil:false,
  23. anialias:false
  24. },
  25. },
  26. targetFrameRate:60,
  27. resolutionScale:0.1,
  28. orderIndependentTranslucency : true,
  29. creditContainer : "hidecredit",
  30. imageryProvider : new Cesium.createTileMapServiceImageryProvider({
  31. url: 'Assets/imagery/NaturalEarthII/',
  32. maximumLevel : 5
  33. }),
  34. baseLayerPicker : false,
  35. geocoder : false,
  36. automaticallyTrackDataSourceClocks: false,
  37. dataSources: null,
  38. clock: null,
  39. terrainShadows: Cesium.ShadowMode.DISABLED
  40. });
  41.  
  42. var center = Cesium.Cartesian3.fromDegrees(
  43. (minWGS84[0] + maxWGS84[0]) / 2,
  44. ((minWGS84[1] + maxWGS84[1]) / 2)-1,
  45. 200000
  46. );
  47. cesium.viewer.camera.flyTo({
  48. destination : center,
  49. orientation : {
  50. heading : Cesium.Math.toRadians(0),
  51. pitch : Cesium.Math.toRadians(-60),
  52. roll : Cesium.Math.toRadians(0)
  53. },
  54. duration: 3
  55. });
  56. }

初始化Three.js渲染器

接下来我们简单地初始化Three.js强制阶段,包括场景,相机,渲染器和DOM元素。

  1. function initThree(){
  2. var fov = 45;
  3. var width = window.innerWidth;
  4. var height = window.innerHeight;
  5. var aspect = width / height;
  6. var near = 1;
  7. var far = 10*1000*1000; // needs to be far to support Cesium's world-scale rendering
  8.  
  9. three.scene = new THREE.Scene();
  10. three.camera = new THREE.PerspectiveCamera(fov, aspect, near, far);
  11. three.renderer = new THREE.WebGLRenderer({alpha: true});
  12. ThreeContainer.appendChild(three.renderer.domElement);
  13. }

在两个库中初始化3D对象

使用实体对象可以简单地将Cesium对象添加到其查看器中; 例如,可以使用3D图形类来渲染在Three.js中创建的3D绘图对象网格,或者使用Three.js创建的任何其他3D对象。所有这些都保存在一个_3DObjects进一步处理,其中包含用于同步相机的额外信息。这里我们将渲染一个[Lathe geometry]和一个[dodecahedron]。请注意,Three.js呈现z-up,而Cesium呈现y-up。

  1. function init3DObject(){
  2. //Cesium entity
  3. var entity = {
  4. name : 'Polygon',
  5. polygon : {
  6. hierarchy : Cesium.Cartesian3.fromDegreesArray([
  7. minWGS84[0], minWGS84[1],
  8. maxWGS84[0], minWGS84[1],
  9. maxWGS84[0], maxWGS84[1],
  10. minWGS84[0], maxWGS84[1],
  11. ]),
  12. material : Cesium.Color.RED.withAlpha(0.2)
  13. }
  14. };
  15. var Polygon = cesium.viewer.entities.add(entity);
  16.  
  17. // Lathe geometry
  18. var doubleSideMaterial = new THREE.MeshNormalMaterial({
  19. side: THREE.DoubleSide
  20. });
  21. var segments = 10;
  22. var points = [];
  23. for ( var i = 0; i < segments; i ++ ) {
  24. points.push( new THREE.Vector2( Math.sin( i * 0.2 ) * segments + 5, ( i - 5 ) * 2 ) );
  25. }
  26. var geometry = new THREE.LatheGeometry( points );
  27. var latheMesh = new THREE.Mesh( geometry, doubleSideMaterial ) ;
  28. latheMesh.scale.set(1500,1500,1500); //scale object to be visible at planet scale
  29. latheMesh.position.z += 15000.0; // translate "up" in Three.js space so the "bottom" of the mesh is the handle
  30. latheMesh.rotation.x = Math.PI / 2; // rotate mesh for Cesium's Y-up system
  31. var latheMeshYup = new THREE.Group();
  32. latheMeshYup.add(latheMesh)
  33. three.scene.add(latheMeshYup); // don’t forget to add it to the Three.js scene manually
  34.  
  35. //Assign Three.js object mesh to our object array
  36. var _3DOB = new _3DObject();
  37. _3DOB.threeMesh = latheMeshYup;
  38. _3DOB.minWGS84 = minWGS84;
  39. _3DOB.maxWGS84 = maxWGS84;
  40. _3Dobjects.push(_3DOB);
  41.  
  42. // dodecahedron
  43. geometry = new THREE.DodecahedronGeometry();
  44. var dodecahedronMesh = new THREE.Mesh(geometry, new THREE.MeshNormalMaterial()) ;
  45. dodecahedronMesh.scale.set(5000,5000,5000); //scale object to be visible at planet scale
  46. dodecahedronMesh.position.z += 15000.0; // translate "up" in Three.js space so the "bottom" of the mesh is the handle
  47. dodecahedronMesh.rotation.x = Math.PI / 2; // rotate mesh for Cesium's Y-up system
  48. var dodecahedronMeshYup = new THREE.Group();
  49. dodecahedronMeshYup.add(dodecahedronMesh)
  50. three.scene.add(dodecahedronMeshYup); // don’t forget to add it to the Three.js scene manually
  51.  
  52. //Assign Three.js object mesh to our object array
  53. _3DOB = new _3DObject();
  54. _3DOB.threeMesh = dodecahedronMeshYup;
  55. _3DOB.minWGS84 = minWGS84;
  56. _3DOB.maxWGS84 = maxWGS84;
  57. _3Dobjects.push(_3DOB);
  58. }
  1. function _3DObject(){
  2. this.graphMesh = null; //Three.js 3DObject.mesh
  3. this.minWGS84 = null; //location bounding box
  4. this.maxWGS84 = null;
  5. }

循环渲染器

  1. function loop(){
  2. requestAnimationFrame(loop);
  3. renderCesium();
  4. renderThreeObj();
  5. }
  1. function renderCesium(){
  2. cesium.viewer.render();
  3. }

我们将克隆Three.js摄像头以匹配Cesium摄像头,因此不需要为Three.js分配鼠标控制器,但是由于Three.js DOM元素在Cesium之上,我们仍然需要将其删除。我们通过向pointer-events:noneThree.js渲染器添加CSS属性来删除它。现在一切都会根据铯的相机投影来渲染。

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

  1. function renderThreeObj(){
  2. // register Three.js scene with Cesium
  3. three.camera.fov = Cesium.Math.toDegrees(cesium.viewer.camera.frustum.fovy) // ThreeJS FOV is vertical
  4. three.camera.updateProjectionMatrix();
  5.  
  6. var cartToVec = function(cart){
  7. return new THREE.Vector3(cart.x, cart.y, cart.z);
  8. };
  9.  
  10. // Configure Three.js meshes to stand against globe center position up direction
  11. for(id in _3Dobjects){
  12. minWGS84 = _3Dobjects[id].minWGS84;
  13. maxWGS84 = _3Dobjects[id].maxWGS84;
  14. // convert lat/long center position to Cartesian3
  15. var center = Cesium.Cartesian3.fromDegrees((minWGS84[0] + maxWGS84[0]) / 2, (minWGS84[1] + maxWGS84[1]) / 2);
  16.  
  17. // get forward direction for orienting model
  18. var centerHigh = Cesium.Cartesian3.fromDegrees((minWGS84[0] + maxWGS84[0]) / 2, (minWGS84[1] + maxWGS84[1]) / 2,1);
  19.  
  20. // use direction from bottom left to top left as up-vector
  21. var bottomLeft = cartToVec(Cesium.Cartesian3.fromDegrees(minWGS84[0], minWGS84[1]));
  22. var topLeft = cartToVec(Cesium.Cartesian3.fromDegrees(minWGS84[0], maxWGS84[1]));
  23. var latDir = new THREE.Vector3().subVectors(bottomLeft,topLeft ).normalize();
  24.  
  25. // configure entity position and orientation
  26. _3Dobjects[id].graphMesh.position.copy(center);
  27. _3Dobjects[id].graphMesh.lookAt(centerHigh);
  28. _3Dobjects[id].graphMesh.up.copy(latDir);
  29. }
  30.  
  31. // Clone Cesium Camera projection position so the
  32. // Three.js Object will appear to be at the same place as above the Cesium Globe
  33. three.camera.matrixAutoUpdate = false;
  34. var cvm = cesium.viewer.camera.viewMatrix;
  35. var civm = cesium.viewer.camera.inverseViewMatrix;
  36. three.camera.matrixWorld.set(
  37. civm[0], civm[4], civm[8 ], civm[12],
  38. civm[1], civm[5], civm[9 ], civm[13],
  39. civm[2], civm[6], civm[10], civm[14],
  40. civm[3], civm[7], civm[11], civm[15]
  41. );
  42. three.camera.matrixWorldInverse.set(
  43. cvm[0], cvm[4], cvm[8 ], cvm[12],
  44. cvm[1], cvm[5], cvm[9 ], cvm[13],
  45. cvm[2], cvm[6], cvm[10], cvm[14],
  46. cvm[3], cvm[7], cvm[11], cvm[15]
  47. );
  48. three.camera.lookAt(new THREE.Vector3(0,0,0));
  49.  
  50. var width = ThreeContainer.clientWidth;
  51. var height = ThreeContainer.clientHeight;
  52. var aspect = width / height;
  53. three.camera.aspect = aspect;
  54. three.camera.updateProjectionMatrix();
  55.  
  56. three.renderer.setSize(width, height);
  57. three.renderer.render(three.scene, three.camera);
  58. }

cesium and three.js【转】的更多相关文章

  1. Cesium应用篇:1快速搭建

    范例中所有范例可以在Github中搜索:ExamplesforCesium Cesium ['siːzɪəm]是一款开源的JavaScript开源库,开发者通过Cesium,实现无插件的创建三维球和二 ...

  2. [转][cesium]1.添加本地服务器

    转自:http://www.cnblogs.com/fuckgiser/p/5633748.html 此系列cesium总教程:  https://www.cnblogs.com/fuckgiser/ ...

  3. Cesium应用篇:1快速搭建 【转】

    范例中所有范例可以在Github中搜索:ExamplesforCesium Cesium ['siːzɪəm]是一款开源的JavaScript开源库,开发者通过Cesium,实现无插件的创建三维球和二 ...

  4. 转:Cesium 和 Webpack

    原文地址:https://www.jianshu.com/p/85917bcc023f 注意:webpack 和 webpack-cli 的安装参考 https://www.cnblogs.com/m ...

  5. Cesium资料大全

    前言 Cesium是一个用于显示三维地球和地图的开源js库.它可以用来显示海量三维模型数据.影像数据.地形高程数据.矢量数据等等.三维模型格式支持gltf.三维瓦片模型格式支持3d tiles.矢量数 ...

  6. Cesium官方教程13--Cesium和Webpack

    原文地址:https://cesiumjs.org/tutorials/cesium-and-webpack/ Cesium 和 Webpack Webpack是非常强大非常流行的JavaScript ...

  7. Cesium参考资源

    Reference resources cesium官网 cesium 下载 cesium官方文档 APIs cesium-workshop github cesium 官方示例 cesium git ...

  8. Cesium中级教程10 - CesiumJS and webpack

    Cesium中文网:http://cesiumcn.org/ | 国内快速访问:http://cesium.coinidea.com/ webpack是打包JavaScript模块流行且强大的工具.它 ...

  9. 20个简化开发任务的 JavaScript库

    所谓JavaScript库就是预先写好的可以简化基于JavaScript的应用程序开发的,尤其是Ajax和其它以web为中心的技术的 JavaScript代码集.JavaScript主要用于写内嵌于H ...

随机推荐

  1. PBR Step by Step(四)Lambertian反射模型

    光照可分为局部光照和全局光照. 局部光照:直接照射到物体表面的光照 全局光照:物体表面受周围环境影响的光照 左图中点x接收到周围环境的光线照射,来自周围表面的反射光照称为全局光照:右图中点x接收来自太 ...

  2. Codeforces.838D.Airplane Arrangements(思路)

    题目链接 \(Description\) 飞机上有n个位置.有m个乘客入座,每个人会从前门(1)或后门(n)先走到其票上写的位置.若该位置没人,则在这坐下:若该位置有人,则按原方向向前走直到找到空座坐 ...

  3. BZOJ.3004.[SDOI2012]吊灯(结论)

    题目链接 BZOJ 洛谷 题意: 将树划分为k个连通块,要求每个连通块大小相同.输出可能的大小. 结论: 满足条件时颜色的连通块数为k,当且仅当有 \(n/k\) 个节点满足它的子树是k的倍数(显然还 ...

  4. curl dns缓存设置

    CURLOPT_DNS_USE_GLOBAL_CACHE 启用时会启用一个全局的DNS缓存,此项为线程安全的,并且默认启用.CURLOPT_DNS_CACHE_TIMEOUT 设置在内存中保存DNS信 ...

  5. Linux与Windows远程互访(使用Rdesktop与SSH)

    工作的时候经常使用Redhat系列系统,而平常娱乐文档都是在windows平台上进行.因此实现linux与windows远程互访也是很有必要的事情. 本文将介绍如何实现Linux与Windows的远程 ...

  6. lua中的pairs和ipairs差别

    pairs Returns three values: the next function, the table t, and nil, so that the construction for k, ...

  7. C# ie通过打印控件点打印,总是弹出另存为xps的对话框

    用的是lodop打印控件,点打印后,总是弹出另存为xps的对话框,后来在网上查到可能是把windows自带的Microsoft XPS Document Writer设为默认打印机的原因. 但现在没有 ...

  8. AngularJS中自定义过滤器

    AngularJS中为我们提供了一些内置的过滤器,这里列举一些自定义过滤器的场景. 自定义过滤器,不带参赛 //过滤 不带参赛 app.filter('ordinal', function () { ...

  9. AngularJS双向绑定,手动实施观察

    实现这样的一个需求:页面中某个地方显示某个文本框的值经过计算得到的结果,而且是文本框值每次变化显示的计算结果也跟着动态变化. 在controller中可以声明一个对象,它的一个字段用来存储初始值: $ ...

  10. 直接将DataTable存入oracle数据库中(转)

    注意 1:传入的DataTable的列必须和数据库中表列必须一致,否则数据会默认往前几列存 2:sql语句只要是对要插入的表的一个查询,目的是为了确定表名 3:取得连接字符串的方法为GetOracle ...