zoukankan      html  css  js  c++  java
  • Cesium 中两种添加 model 方法的区别

    概述

    Cesium 中包含两种添加 model 的方法,分别为:

    1. 通过 viewer.entities.add() 函数添加
    2. 通过 viewer.scene.primitives.add() 函数添加

    两种方法本质上是相通的,方法 1方法 2在某种程度上进行了封装。

    两种方法的区别

    表面区别

    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 对象,其结构如下所示。

    {
    	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,可以在运行时对模型进行动态变换,以实现自定义模型动画。

    示例代码

    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);
        });
    }
    
  • 相关阅读:
    第十八章所有者权益部分考点知识点
    会计基础模拟练习一(3)
    会计基础模拟练习一(2)
    会计基础模拟练习一(1)
    第三章 复式记账
    第二章 会计科目和账户 笔记
    【Flink系列一】Flink开启Checkpoint,以及从Checkpoint恢复
    【已解决】解决Gradle在使用代理的情况下访问中央仓库返回403 Forbidden的问题
    Surface Laptop 3三个月使用心得
    Spring跨系统转发HTTP请求的简易实现(支持下载文件二进制流)
  • 原文地址:https://www.cnblogs.com/flypopo/p/9796430.html
Copyright © 2011-2022 走看看