Cesium 中兩種添加 model 方法的區別

概述

Cesium 中包含兩種添加 model 的方法,分別爲:javascript

  1. 經過 viewer.entities.add() 函數添加
  2. 經過 viewer.scene.primitives.add() 函數添加

兩種方法本質上是相通的,方法 1方法 2在某種程度上進行了封裝。java

兩種方法的區別

表面區別

  1. 方法 1經過指定 model 的 position 和 orientation 來控制模型的位置,對模型進行精確變換的難度較大;方法 2經過 modelMatrix 控制模型的位置和方向,可進行較爲精確的模型變換。
  2. 對相機操做時方法 1提供了較爲方便的 viewer.trackedEntity 函數;方法 2追蹤 model 較爲複雜,須要手動操做相機變換。
  3. 對模型進行縮放、變換等操做,方法 1 須要修改 object.id(Entity 類型) 中 model(ModelGraphics 類型) 的 scale 和 nodeTransformations;方法 2 能夠直接修改 object.primitive(model 類型) 中的 scale 和 modelMatrix。

深層探究

分別使用方法 1方法 2創建兩個模型,而後對其進行點擊操做,查看點擊獲得的物體,方法 1方法 2返回的都爲一樣的 object 對象,其結構以下所示。node

{
    id: object
    mesh: ModelMesh
    node: ModeNode
    primitive: Model
}

其不一樣的是,方法 2 中的 id 對象爲用戶自定義對象,方法 1 中的 Entity 對象。所以方法 1至關於首先經過 方法 2 中的 Cesium.Model.fromGltf() 函數創建 Model,經過該 Model 創建對應的 Entity(方法暫何嘗試,由於 Entity 構造函數中的 options.model 接收的是 ModelGraphics 類型,而不是 Model 類型),將 Entity 賦予對象的 id 屬性,實現雙向綁定,具體的實現可能要參考 viewer.entities.add() 的源碼實現。函數

從 Entity 得到 Model 的方法

function getModelForEntity(entity) {
    var primitives = viewer.scene.primitives;
    for (var i = 0; i < primitives.length; i++) {
        var primitive = primitives.get(i);
        if (primitive instanceof Cesium.Model && primitive.id === entity) {
            return primitive;
        }
    }
};

其它知識點

構建的對象中還包含 ModelMesh 和 ModeNode,ModelMesh 中包含了模型的網格和材質,ModeNode 中包含了一個 transform,能夠在運行時對模型進行動態變換,以實現自定義模型動畫。oop

示例代碼

  1. 方法1
function createModel(url, height) {
    viewer.entities.removeAll();

    var position = Cesium.Cartesian3.fromDegrees(-123.0744619, 44.0503706, height);
    var heading = Cesium.Math.toRadians(135);
    var pitch = 0;
    var roll = 0;
    var hpr = new Cesium.HeadingPitchRoll(heading, pitch, roll);
    var orientation = Cesium.Transforms.headingPitchRollQuaternion(position, hpr);

    var entity = viewer.entities.add({
        name : url,
        position : position,
        orientation : orientation,
        model : {
            uri : url,
            minimumPixelSize : 128,
            maximumScale : 20000
        }
    });
    viewer.trackedEntity = entity;
}
  1. 方法2
function createModel(url, height, heading, pitch, roll) {
    height = Cesium.defaultValue(height, 0.0);
    heading = Cesium.defaultValue(heading, 0.0);
    pitch = Cesium.defaultValue(pitch, 0.0);
    roll = Cesium.defaultValue(roll, 0.0);
    var hpr = new Cesium.HeadingPitchRoll(heading, pitch, roll);

    var origin = Cesium.Cartesian3.fromDegrees(-123.0744619, 44.0503706, height);
    var modelMatrix = Cesium.Transforms.headingPitchRollToFixedFrame(origin, hpr);

    scene.primitives.removeAll(); // Remove previous model
    model = scene.primitives.add(Cesium.Model.fromGltf({
        url : url,
        modelMatrix : modelMatrix,
        minimumPixelSize : 128
    }));

    model.readyPromise.then(function(model) {
        model.color = Cesium.Color.fromAlpha(getColor(viewModel.color), Number(viewModel.alpha));
        model.colorBlendMode = getColorBlendMode(viewModel.colorBlendMode);
        model.colorBlendAmount = viewModel.colorBlendAmount;
        // Play and loop all animations at half-speed
        model.activeAnimations.addAll({
            speedup : 0.5,
            loop : Cesium.ModelAnimationLoop.REPEAT
        });

        var camera = viewer.camera;

        // Zoom to model
        var controller = scene.screenSpaceCameraController;
        var r = 2.0 * Math.max(model.boundingSphere.radius, camera.frustum.near);
        controller.minimumZoomDistance = r * 0.5;

        var center = Cesium.Matrix4.multiplyByPoint(model.modelMatrix, model.boundingSphere.center, new Cesium.Cartesian3());
        var heading = Cesium.Math.toRadians(230.0);
        var pitch = Cesium.Math.toRadians(-20.0);
        camera.lookAt(center, new Cesium.HeadingPitchRange(heading, pitch, r * 2.0));
    }).otherwise(function(error){
        window.alert(error);
    });
}
相關文章
相關標籤/搜索