CesiumJs+ThreeJs實測

原帖:https://blog.csdn.net/zhishiqu/article/details/79077883
這篇帖子講述瞭如何將cesium和threejs結合,但是如果跟着代碼敲一遍,會發現並不能加載出threejs的模型。仔細跟着寫了編,把遇到的坑做一下說明。
1.要注意threejs的版本。文中所用爲r87版的threejs,嘗試換成r92,r103,都找不到模型,這個問題後續再探究一下是爲什麼。
2.代碼中涉及很多的cesium中js的引用,cesium中的文件儘量要齊全。
3.關於three的模型在cesium中的位置變幻:
文中設置了一個最大座標和最小座標,位置如圖:
根據最大最小座標繪製的polygon

  function _3DObject(){
    //THREEJS 3DObject.mesh
    this.threeMesh = null;
    //location bounding box
    this.minWGS84 = null;
    this.maxWGS84 = null;
  }
   var minWGS84 = [115.23,39.55];
  var maxWGS84 = [116.23,41.55];

//位置變換
 for(var id in _3Dobjects){
      minWGS84 = _3Dobjects[id].minWGS84;
      maxWGS84 = _3Dobjects[id].maxWGS84;
      // convert lat/long center position to Cartesian3
      var center = CesiumCartesian3.fromDegrees(116.39,39.9);    //設置模型的插入點經緯度

      // get forward direction for orienting model
      var centerHigh = CesiumCartesian3.fromDegrees(116.39,39.9,1);   //設置插入點向上的向量

      // use direction from bottom left to top left as up-vector
      var bottomLeft  = cartToVec(CesiumCartesian3.fromDegrees(minWGS84[0], minWGS84[1]));
      var topLeft = cartToVec(CesiumCartesian3.fromDegrees(minWGS84[0], maxWGS84[1]));
      var latDir  = new THREE.Vector3().subVectors(bottomLeft,topLeft ).normalize();   //設置y軸應該的指向

      // configure entity position and orientation
      // _3Dobjects[id].threeMesh.position.copy(center);
      _3Dobjects[id].threeMesh.lookAt(centerHigh);   //模型的朝向
      _3Dobjects[id].threeMesh.up.copy(latDir);   //指定y軸的朝向
    }

位置變換前three的座標系如圖(紅色爲x軸,綠色爲y軸,藍色爲z軸):

在這裏插入圖片描述
在這裏插入圖片描述
進行位置變化後:
在這裏插入圖片描述
4.關於自己的模型變黑:加載帖子中的兩個自建模型,顏色是很明顯的彩色,如圖所示:
在這裏插入圖片描述
加載其他自建模型或其他導入的模型,則是如圖:
在這裏插入圖片描述
原因是threejs渲染器中並沒有加燈光進去,加上燈光就好了。至於爲什麼原貼中是有顏色的,等再看看再做解答。
(與原文中的位置有偏差是因爲重新設置了模型的經緯度,放置在了北京正中心)。
附源碼

var Cesium = {};

define([
        'Cesium/Core/Cartesian3',
        'Cesium/Widgets/Viewer/Viewer',
        'Cesium/Scene/ShadowMode',
        'Cesium/Core/Color',
        'Cesium/Core/Math',
        'Three/three.min',
    ], function(
        CesiumCartesian3,
        CesiumViewer,
        CesiumShadowMode,
        CesiumColor,
        CesiumMath,
        // CesiumUrlTemplateImageryProvider,
        THREE) {
  'use strict';

  var loadingIndicator = document.getElementById('loadingIndicator');
  loadingIndicator.style.display = 'none';

  // boundaries in WGS84 around the object
  var minWGS84 = [115.23,39.55];
  var maxWGS84 = [116.23,41.55];
  var cesiumContainer = document.getElementById("cesiumContainer");
  var ThreeContainer = document.getElementById("ThreeContainer");

  var _3Dobjects = []; //Could be any Three.js object mesh
  var three = {
    renderer: null,
    camera: null,
    scene: null
  };

  var cesium = {
    viewer: null
  };

  function _3DObject(){
    //THREEJS 3DObject.mesh
    this.threeMesh = null;
    //location bounding box
    this.minWGS84 = null;
    this.maxWGS84 = null;
  }

  function initCesium(){
    cesium.viewer = new CesiumViewer(cesiumContainer,{
      useDefaultRenderLoop: false,
      selectionIndicator : false,
      homeButton:false,
      sceneModePicker:false,

      infoBox : false,
      navigationHelpButton:false,
      navigationInstructionsInitiallyVisible:false,
      animation : false,
      timeline : false,
      fullscreenButton : false,
      allowTextureFilterAnisotropic:false,
      contextOptions:{
        webgl: {
          alpha: false,
          antialias: true,
          preserveDrawingBuffer : true,
          failIfMajorPerformanceCaveat: false,
          depth:true,
          stencil:false,
          anialias:false
        },
      },
      targetFrameRate:60,
      resolutionScale:0.1,
      orderIndependentTranslucency : true,
      // imageryProvider : googlemap,
      baseLayerPicker : true,
      geocoder : false,
      automaticallyTrackDataSourceClocks: false,
      dataSources: null,
      clock: null,
      terrainShadows: CesiumShadowMode.DISABLED
    });

    var center = CesiumCartesian3.fromDegrees(
      (minWGS84[0] + maxWGS84[0]) / 2,
      ((minWGS84[1] + maxWGS84[1]) / 2)-1,
      200000
    );
    cesium.viewer.camera.flyTo({
      destination :center,
      orientation : {
        heading : CesiumMath.toRadians(0),
        pitch : CesiumMath.toRadians(-60),
        roll : CesiumMath.toRadians(0)
      },
      duration: 3
    });
  }

  function initThree(){
    var fov = 45;
    var width = window.innerWidth;
    var height = window.innerHeight;
    var aspect = width / height;
    var near = 1;
    var far = 10*1000*1000;

    three.scene = new THREE.Scene();
    three.camera = new THREE.PerspectiveCamera(fov, aspect, near, far);
    three.renderer = new THREE.WebGLRenderer({alpha: true});
    var Amlight=new THREE.AmbientLight(0xffffff,2);
    // three.scene.add(Amlight);
    ThreeContainer.appendChild(three.renderer.domElement);
  }

  function init3DObject(){
    //Cesium entity
    var entity = {
      name : 'Polygon',
      polygon : {
        hierarchy : CesiumCartesian3.fromDegreesArray([
          minWGS84[0], minWGS84[1],
          maxWGS84[0], minWGS84[1],
          maxWGS84[0], maxWGS84[1],
          minWGS84[0], maxWGS84[1],
        ]),
        material : CesiumColor.RED.withAlpha(0.2)
      }
    };
    var Polygon = cesium.viewer.entities.add(entity);


    //Three.js Objects
    // Lathe geometry

    //加載json
       var loader = new THREE.ObjectLoader();
    var mesh = [];
    loader.load('./Model/model-a2-1.json', function (obj) {
      obj.scale.x = obj.scale.y = obj.scale.z =1;
      mesh.push(obj);
      three.scene.add(obj);   //加載外部json
      obj.castShadow = true;
      obj.name="121";
      var position=new CesiumCartesian3.fromDegrees(116.39,39.9,0);
      obj.position.set(position.x,position.y,position.z);
      var _3DOB = new _3DObject();
      _3DOB.threeMesh = obj;
      _3DOB.minWGS84 = minWGS84;
      _3DOB.maxWGS84 = maxWGS84;
      _3Dobjects.push(_3DOB);


      var mat=new THREE.MeshLambertMaterial({color:0xff0000});
      var geo=new THREE.BoxGeometry(200,200,200);
      var objects=new THREE.Group();
      for (var i = 0; i < 10; i++) {
        var object = new THREE.Mesh(geo,mat);
        object.position.x = Math.round(Math.random() * 10000);
        objects.add(object);
      }
      three.scene.add(objects);   //用cube模擬x軸
      var _3DOB = new _3DObject();
      _3DOB.threeMesh = objects;
      _3DOB.minWGS84 = minWGS84;
      _3DOB.maxWGS84 = maxWGS84;
      _3Dobjects.push(_3DOB);
      // objects.position.set(position.x,position.y,position.z);

      var mat2=new THREE.MeshLambertMaterial({color:0x00ff00});
      var geo2=new THREE.BoxGeometry(200,200,200);
      var objects2=new THREE.Group();
      for (var i = 0; i < 20;i++) {
        var object2 = new THREE.Mesh(geo2,mat2);
        object2.position.y = Math.round(Math.random() * 10000);
        objects2.add(object2);
      }
      three.scene.add(objects2);    //模擬y軸
      var _3DOB = new _3DObject();
      _3DOB.threeMesh = objects2;
      _3DOB.minWGS84 = minWGS84;
      _3DOB.maxWGS84 = maxWGS84;
      _3Dobjects.push(_3DOB);
      // objects2.position.set(position.x,position.y,position.z);

      var mat3=new THREE.MeshLambertMaterial({color:0x0000ff});
      var geo3=new THREE.BoxGeometry(200,200,200);
      var objects3=new THREE.Group();
      for (var i = 0; i < 20;i++) {
        var object3 = new THREE.Mesh(geo3,mat3);
        object3.position.z = Math.round(Math.random() * 10000);
        objects3.add(object3);
      }
      three.scene.add(objects3);   //模擬z軸
      var _3DOB = new _3DObject();
      _3DOB.threeMesh = objects3;
      _3DOB.minWGS84 = minWGS84;
      _3DOB.maxWGS84 = maxWGS84;
      _3Dobjects.push(_3DOB);

    });


    //原貼中的模型
    // var doubleSideMaterial = new THREE.MeshNormalMaterial({
    //   side: THREE.DoubleSide
    // });
    // var segments = 10;
    // var points = [];
    // for ( var i = 0; i < segments; i ++ ) {
    // 	points.push( new THREE.Vector2( Math.sin( i * 0.2 ) * segments + 5, ( i - 5 ) * 2 ) );
    // }
    // var geometry = new THREE.LatheGeometry( points );
    // var latheMesh = new THREE.Mesh( geometry, doubleSideMaterial ) ;
    // latheMesh.scale.set(1500,1500,1500); //scale object to be visible at planet scale
    // latheMesh.position.z += 15000.0; // translate "up" in Three.js space so the "bottom" of the mesh is the handle
    // latheMesh.rotation.x = Math.PI / 2; // rotate mesh for Cesium's Y-up system
    // var latheMeshYup = new THREE.Group();
    // latheMeshYup.add(latheMesh)
    // three.scene.add(latheMeshYup); // don’t forget to add it to the Three.js scene manually
    //
    // //Assign Three.js object mesh to our object array
    // var _3DOB = new _3DObject();
    // _3DOB.threeMesh = latheMeshYup;
    // _3DOB.minWGS84 = minWGS84;
    // _3DOB.maxWGS84 = maxWGS84;
    // _3Dobjects.push(_3DOB);
    //
    // // dodecahedron
    // geometry = new THREE.DodecahedronGeometry();
    // var dodecahedronMesh = new THREE.Mesh(geometry, new THREE.MeshNormalMaterial()) ;
    // dodecahedronMesh.scale.set(5000,5000,5000); //scale object to be visible at planet scale
    // dodecahedronMesh.position.z += 15000.0; // translate "up" in Three.js space so the "bottom" of the mesh is the handle
    // dodecahedronMesh.rotation.x = Math.PI / 2; // rotate mesh for Cesium's Y-up system
    // var dodecahedronMeshYup = new THREE.Group();
    // dodecahedronMeshYup.add(dodecahedronMesh)
    // three.scene.add(dodecahedronMesh); // don’t forget to add it to the Three.js scene manually
    //
    // //Assign Three.js object mesh to our object array
    // _3DOB = new _3DObject();
    // _3DOB.threeMesh = dodecahedronMesh;
    // _3DOB.minWGS84 = minWGS84;
    // _3DOB.maxWGS84 = maxWGS84;
    // _3Dobjects.push(_3DOB);

  }

  // Looping Renderer
  function renderCesium(){
    cesium.viewer.render();
  }

  function renderThreeObj(){
    // register Three.js scene with Cesium
    three.camera.fov = CesiumMath.toDegrees(cesium.viewer.camera.frustum.fovy) // ThreeJS FOV is vertical
    three.camera.updateProjectionMatrix();

    var cartToVec = function(cart){
      return new THREE.Vector3(cart.x, cart.y, cart.z);
    };

    // Configure Three.js meshes to stand against globe center position up direction
    for(var id in _3Dobjects){
      minWGS84 = _3Dobjects[id].minWGS84;
      maxWGS84 = _3Dobjects[id].maxWGS84;
      // convert lat/long center position to Cartesian3
      var center = CesiumCartesian3.fromDegrees(116.39,39.9);

      // get forward direction for orienting model
      var centerHigh = CesiumCartesian3.fromDegrees(116.39,39.9,1);

      // use direction from bottom left to top left as up-vector
      var bottomLeft  = cartToVec(CesiumCartesian3.fromDegrees(minWGS84[0], minWGS84[1]));
      var topLeft = cartToVec(CesiumCartesian3.fromDegrees(minWGS84[0], maxWGS84[1]));
      var latDir  = new THREE.Vector3().subVectors(bottomLeft,topLeft ).normalize();

      // configure entity position and orientation
      _3Dobjects[id].threeMesh.position.copy(center);
      _3Dobjects[id].threeMesh.lookAt(centerHigh);
      _3Dobjects[id].threeMesh.up.copy(latDir);   //指定y軸的朝向
    }

    // Clone Cesium Camera projection position so the
    // Three.js Object will appear to be at the same place as above the Cesium Globe
    three.camera.matrixAutoUpdate = false;
    var cvm = cesium.viewer.camera.viewMatrix;
    var civm = cesium.viewer.camera.inverseViewMatrix;
    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]
    );
    three.camera.lookAt(new THREE.Vector3(0,0,0));

    var width = ThreeContainer.clientWidth;
    var height = ThreeContainer.clientHeight;
    var aspect = width / height;
    three.camera.aspect = aspect;
    three.camera.updateProjectionMatrix();

    three.renderer.setSize(width, height);
    three.renderer.render(three.scene, three.camera);

  }

  function loop(){
    renderCesium();
    renderThreeObj();
    requestAnimationFrame(loop);
  }


  initCesium(); // Initialize Cesium renderer
  initThree(); // Initialize Three.js renderer
  init3DObject(); // Initialize Three.js object mesh with Cesium Cartesian coordinate system
  loop(); // Looping renderer

});

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章