当前位置:   article > 正文

cesium+threejs结合实现GIS+BIM大场景-2_three gis

three gis

最终效果

示例的demo我没做,但是可以放一个最终调试完的QModel产品的效果。大概是这个样子:

自研引擎产品试用,demo下载:

QModel-BIM模型浏览器

常见问题

1、原理是什么?

原理是利用threejs在Canvas上渲染支持背景透明的特性。把两个Canvas叠加在一起,然后在render时,使threejs的camera随Cesium的相机联动。

2、如何屏蔽掉表层threejs这个div的鼠标操作,只让底下的cesium响应操作?

一句话实现,让某个div忽略所有的鼠标事件:ThreeContainer.style.pointerEvents = "none";当它不存在。

3、如果是threejs高版本,按照网友以及cesium博客的过时代码,在新版本下,有一行代码都调整顺序。

4、物体看不到。怎样找到物体呢?

看到上面的红蓝绿坐标系了吗?你在模型的group里面加个helper射向外太空,只要不瞎都能找到。

搬砖内容

这篇文章到处都是。源自于Cesium的官方指导。Integrating Cesium with Three.js – Cesium

在引用条件齐全的条件下,开始以下工作

初始化三个div

  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. var _3Dobjects = []; //Could be any Three.js object mesh
  8. var three = {
  9. renderer: null,
  10. camera: null,
  11. scene: null
  12. };
  13. var cesium = {
  14. viewer: null
  15. };
  16. initCesium(); // Initialize Cesium renderer
  17. initThree(); // Initialize Three.js renderer
  18. init3DObject(); // Initialize Three.js object mesh with Cesium Cartesian coordinate system
  19. loop(); // Looping renderer
  20. }

初始化Cesium

  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.TileMapServiceImageryProvider({
  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. var center = Cesium.Cartesian3.fromDegrees(
  42. (minWGS84[0] + maxWGS84[0]) / 2,
  43. ((minWGS84[1] + maxWGS84[1]) / 2)-1,
  44. 200000
  45. );
  46. cesium.viewer.camera.flyTo({
  47. destination : center,
  48. orientation : {
  49. heading : Cesium.Math.toRadians(0),
  50. pitch : Cesium.Math.toRadians(-60),
  51. roll : Cesium.Math.toRadians(0)
  52. },
  53. duration: 3
  54. });
  55. }

初始化threejs

  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. three.scene = new THREE.Scene();
  9. three.camera = new THREE.PerspectiveCamera(fov, aspect, near, far);
  10. three.renderer = new THREE.WebGLRenderer({alpha: true});
  11. ThreeContainer.appendChild(three.renderer.domElement);
  12. }

初始化threejs的对象及其所在的WGS84坐标位置(在地图上的位置)

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

开始循环渲染

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

其中threejs的渲染是需要特殊处理的。官方这个版本,应该是threejs r80之前的写法。

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

本文内容由网友自发贡献,转载请注明出处:https://www.wpsshop.cn/w/weixin_40725706/article/detail/861608
推荐阅读
相关标签
  

闽ICP备14008679号