CESIUM例子学习(六)——Cardboard

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

一、动画基本设置

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

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

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

动画时长370,正常动画时长 动画时长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,使用目标和旋转矩阵设置相机位置和姿态。但是不能理解为什么在使用矩阵后,还要重置相机位置、姿态。先这样用,后面搞明白了再来补。

你可能感兴趣的:(cesium)