欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

CESIUM例子学习(六)——Cardboard

程序员文章站 2022-06-23 21:22:55
在初看到这个例子时,感觉这个例子没有什么可学的。仔细看完之后,至少可以学习到两个方面的内容:(1)基本的相机动画实现;(2)cesium相机绑定,即把相机绑定到模型上,当模型运动时,带着相机一起运动;一、动画基本设置start:开始时间,设置动画开始时间,只是一个与结束时间相对的时间,设置到哪年并不影响动画。stop:结束时间,也就是开始时间加上动画时长,时间最好是等于或略大于动画时长,否则,可能会导致动画不完整。同样的动画数据,设置不同的动画时长,如下对:动画时长370,正常动画时长动...

在初看到这个例子时,感觉这个例子没有什么可学的。仔细看完之后,至少可以学习到两个方面的内容:(1)基本的相机动画实现;(2)cesium相机绑定,即把相机绑定到模型上,当模型运动时,带着相机一起运动;

一、动画基本设置

start:开始时间,设置动画开始时间,只是一个与结束时间相对的时间,设置到哪年并不影响动画。

stop:结束时间,也就是开始时间加上动画时长,时间最好是等于或略大于动画时长,否则,可能会导致动画不完整。

同样的动画数据,设置不同的动画时长,如下对:

CESIUM例子学习(六)——Cardboard
动画时长370,正常动画时长
CESIUM例子学习(六)——Cardboard
动画时长180,不正常动画时长

从上图可以看出设置的结束动画时间提前于第n帧动画时间时,第n帧和后面的帧都会被剪切掉。绘制的路径也是不完整的。

动画基本设置代码如下:

var start = Cesium.JulianDate.fromDate(new Date(2015, 2, 25, 16));
var stop = Cesium.JulianDate.addSeconds(
    start,
    370,
    new Cesium.JulianDate()
);
// 给viewer.clock的开始时间、结束时间、当前时间赋值
 viewer.clock.startTime = start.clone();
    viewer.clock.stopTime = stop.clone();
    viewer.clock.currentTime = start.clone();
// 设置动画模式:结束后再循环
    viewer.clock.clockRange = Cesium.ClockRange.LOOP_STOP;
    viewer.clock.multiplier = 1.0;
    viewer.clock.shouldAnimate = true;

二、动画加载

代码如下:

function addOneBall () {
    var entity = viewer.entities.add({
        availability: new Cesium.TimeIntervalCollection([
            new Cesium.TimeInterval({
                start: start,
                stop: stop,
            }),
        ]),
        position: computeCirclularFlight(longitude, latitude, radius),
        //绘制路径
        path: {
            material: Cesium.Color.RED,    //点位颜色
            width: 4                //像素点大小
        },
        model: {
            uri: modelURI,
            minimumPixelSize: 64,
        },
    });
    entity.position.setInterpolationOptions({
        interpolationDegree: 2,
        interpolationAlgorithm: Cesium.HermitePolynomialApproximation,
    });
    postUpdate(entity)
}
function computeCirclularFlight (lon, lat, radius) {
    var property = new Cesium.SampledPositionProperty();
    var startAngle = Cesium.Math.nextRandomNumber() * 360.0;
    var endAngle = startAngle + 360.0;
    var increment = (Cesium.Math.nextRandomNumber() * 2.0 - 1.0) * 10.0 + 45.0;
    for (var i = startAngle; i < endAngle; i += increment) {
        var radians = Cesium.Math.toRadians(i);
        var timeIncrement = i - startAngle;
        var time = Cesium.JulianDate.addSeconds(
            start,
            timeIncrement,
            new Cesium.JulianDate()
        );
        var position = Cesium.Cartesian3.fromDegrees(
            lon + radius * 1.5 * Math.cos(radians),
            lat + radius * Math.sin(radians),
            Cesium.Math.nextRandomNumber() * 500 + 1800
        );
        property.addSample(time, position);
    }
    return property;
}

其中:availability:定义了动画开始与结束时间;computeCirclularFlight函数获取动画路径,并设置在每一个节点(关键帧)的动画时间。这里的动画时间就与前面的设置动画时间一起作用的,cesium会自动在两个关键帧之间内插相应的节点出,以免出现跳动现象,而通过 var position=entity.position.getValue(time)能够获取到该时刻下的位置;entity.position.setInterpolationOptions是使用动画插值函数,使用动画在节点转拐节点更加平滑。

 

postUpdate(entity)就是下面要讲的机绑定。

三、相机绑定

上面代码中加载完成动画后,有一个postUpdate(entity),是在这个函数中完成相机绑定。也就是在每一帧渲染中都设置相机。代码如下:

function postUpdate (entity) {
    let camera = viewer.camera
    viewer.scene.preUpdate.addEventListener(function (scene, time) {
        // 获取对应时刻下,物体的位置
        var position = entity.position.getValue(time);
        if (!Cesium.defined(position)) {
            return;
        }
        var transform;
        //如果物体没有定义方向
        if (!Cesium.defined(entity.orientation)) {
            // 获取entity坐标position的z轴垂直于地表,entity坐标的y轴指向正北的4x4变换矩阵
            transform = Cesium.Transforms.eastNorthUpToFixedFrame(position);
        } else {//如果物体已经定义方向,则获取该时刻下的方向。
            var orientation = entity.orientation.getValue(time);
            if (!Cesium.defined(orientation)) {
                return;
            }
            transform = Cesium.Matrix4.fromRotationTranslation(
                Cesium.Matrix3.fromQuaternion(orientation),
                position
            );
        }
        ////////////// 保存相机姿态
        var offset = Cesium.Cartesian3.clone(camera.position);
        var direction = Cesium.Cartesian3.clone(camera.direction);
        var up = Cesium.Cartesian3.clone(camera.up);
        /////////// 设置相机为模型参考系
        camera.lookAtTransform(transform);
        Cesium.Cartesian3.clone(offset, camera.position);
        Cesium.Cartesian3.clone(direction, camera.direction);
        Cesium.Cartesian3.clone(up, camera.up);
        Cesium.Cartesian3.cross(direction, up, camera.right);
    });
}

 其中最重要的是:camera.lookAtTransform(transform);官网解释这个函数是,Sets the camera position and orientation using a target and transformation matrix,使用目标和旋转矩阵设置相机位置和姿态。但是不能理解为什么在使用矩阵后,还要重置相机位置、姿态。先这样用,后面搞明白了再来补。

本文地址:https://blog.csdn.net/luoyun620/article/details/107281041