Cesium學習筆記(七):Demo學習(自由控制飛行的飛機)

這是官方的教程Demo,名字叫Use HeadingPitchRoll,顧名思義,就是教你用HeadingPitchRoll這個方法的,下面我們就來看一看這個Demo

首先先說一下,這個Demo是沙盒裏面的,所以如果你想在本地運行的話需要改一下html

這裏是html

<!DOCTYPE html>
<html lang="en">
<head> 
    <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport"
          content="width=device-width, initial-scale=1, maximum-scale=1, minimum-scale=1, user-scalable=no">
    <title>Hello World!</title>
    <script src="../Build/Cesium/Cesium.js"></script>
    <!-- 如果要用沙盒裏的東西的話加上這個 -->
    <script src="../Apps/Sandcastle/Sandcastle-header.js"></script>
    <!-- 一定要加上這個css樣式 -->
    <link rel="stylesheet" href="Sandcastle/templates/bucket.css">
    <style>
        @import url(../Build/Cesium/Widgets/widgets.css);
    </style>
</head>
<body>
<div id="cesiumContainer" class="fullSize"></div>
<div id="toolbar">
    <!-- 這是Demo需要的側邊欄 -->
    <table class="infoPanel">
        <tbody>
        <tr>
            <td>Click on the 3D window then use the keyboard to change settings.</td>
        </tr>
        <tr>
            <td>Heading: <span id="heading"></span>°</td>
        </tr>
        <tr>
            <td>← to left/→ to right</td>
        </tr>
        <tr>
            <td>Pitch: <span id="pitch"></span>°</td>
        </tr>
        <tr>
            <td>↑ to up/↓ to down</td>
        </tr>
        <tr>
            <td>roll: <span id="roll"></span>°</td>
        </tr>
        <tr>
            <td>← + ⇧ left/→ + ⇧ right</td>
        </tr>
        <tr>
            <td>Speed: <span id="speed"></span>m/s</td>
        </tr>
        <tr>
            <td>↑ + ⇧ to speed up/↓ + ⇧ to speed down</td>
        </tr>
        <tr>
            <td>following aircraft
                <input id="fromBehind" type="checkbox">
            </td>
        </tr>

        </tbody>
    </table>
</div>

<script src="你的js文件"></script>

</body>
</html>

這是js代碼

//飛機飛行
var canvas = viewer.canvas;
canvas.setAttribute('tabindex', '0'); // 將焦點放在畫布上
//如果點擊就獲取畫布焦點
canvas.addEventListener('click', function() {
    canvas.focus();
});
canvas.focus();

//飛行路徑的位置
var pathPosition = new Cesium.SampledPositionProperty();
//添加飛機飛行路徑
var entityPath = viewer.entities.add({
    position : pathPosition,
    name : 'path',
    path : {
        show : true,
        leadTime : 0,
        trailTime : 60,
        width : 10,
        resolution : 1,
        material : new Cesium.PolylineGlowMaterialProperty({
            glowPower : 0.3,
            color : Cesium.Color.PALEGOLDENROD
        })
    }
});

var camera = viewer.camera;
var controller = scene.screenSpaceCameraController;
var r = 0;
//中心點
var center = new Cesium.Cartesian3();

//機身模型的偏移參數
var hpRoll = new Cesium.HeadingPitchRoll();
//相機模型的偏移參數
var hpRange = new Cesium.HeadingPitchRange();

var speed = 10;
//默認按一下偏移3度
var deltaRadians = Cesium.Math.toRadians(3.0);

//飛機位置
var position = Cesium.Cartesian3.fromDegrees(-123.0744619, 44.0503706, 5000.0);
//速度向量
var speedVector = new Cesium.Cartesian3();
//生成一個由兩個參考系生成的矩陣
var fixedFrameTransform = Cesium.Transforms.localFrameToFixedFrameGenerator('north', 'west');

//添加模型
var planePrimitive = scene.primitives.add(Cesium.Model.fromGltf({
    //這裏需要把模型路徑改下(如果你用的還是HelloWord.html的話就用這個,不是的話請自行修改)
    url : '../Apps/SampleData/models/CesiumAir/Cesium_Air.glb',
    modelMatrix : Cesium.Transforms.headingPitchRollToFixedFrame(position, hpRoll, Cesium.Ellipsoid.WGS84, fixedFrameTransform),
    minimumPixelSize : 128
}));

//動畫播放
planePrimitive.readyPromise.then(function(model) {
    // 以半速循環動畫
    model.activeAnimations.addAll({
        speedup : 0.5,
        loop : Cesium.ModelAnimationLoop.REPEAT
    });

    //r=2*max(模型的半徑,相機的最近距離)
    r = 2.0 * Math.max(model.boundingSphere.radius, camera.frustum.near);
    //鏡頭最近距離
    controller.minimumZoomDistance = r * 0.5;
    //計算center位置(也爲下面的鏡頭跟隨提供了center位置)
    Cesium.Matrix4.multiplyByPoint(model.modelMatrix, model.boundingSphere.center, center);
    //相機偏移角度
    var heading = Cesium.Math.toRadians(230.0);
    var pitch = Cesium.Math.toRadians(-20.0);
    hpRange.heading = heading;
    hpRange.pitch = pitch;
    hpRange.range = r * 50.0;
    //固定相機
    camera.lookAt(center, hpRange);
});

//鍵盤監聽
document.addEventListener('keydown', function(e) {
    switch (e.keyCode) {
        case 40:
            if (e.shiftKey) {
                // 按住shift加下箭頭減速
                speed = Math.max(--speed, 1);
            } else {
                // 直接按下箭頭降低角度
                hpRoll.pitch -= deltaRadians;
                if (hpRoll.pitch < -Cesium.Math.TWO_PI) {
                    hpRoll.pitch += Cesium.Math.TWO_PI;
                }
            }
            break;
        case 38:
            if (e.shiftKey) {
                // 按住shift加上箭頭加速
                speed = Math.min(++speed, 100);
            } else {
                // 直接按上箭頭擡高角度
                hpRoll.pitch += deltaRadians;
                if (hpRoll.pitch > Cesium.Math.TWO_PI) {
                    hpRoll.pitch -= Cesium.Math.TWO_PI;
                }
            }
            break;
        case 39:
            if (e.shiftKey) {
                // 飛機本身向右旋轉
                hpRoll.roll += deltaRadians;
                if (hpRoll.roll > Cesium.Math.TWO_PI) {
                    hpRoll.roll -= Cesium.Math.TWO_PI;
                }
            } else {
                // 向右飛行
                hpRoll.heading += deltaRadians;
                if (hpRoll.heading > Cesium.Math.TWO_PI) {
                    hpRoll.heading -= Cesium.Math.TWO_PI;
                }
            }
            break;
        case 37:
            if (e.shiftKey) {
                // 飛機本身向左旋轉
                hpRoll.roll -= deltaRadians;
                if (hpRoll.roll < 0.0) {
                    hpRoll.roll += Cesium.Math.TWO_PI;
                }
            } else {
                // 向左飛行
                hpRoll.heading -= deltaRadians;
                if (hpRoll.heading < 0.0) {
                    hpRoll.heading += Cesium.Math.TWO_PI;
                }
            }
            break;
        default:
    }
});

var headingSpan = document.getElementById('heading');
var pitchSpan = document.getElementById('pitch');
var rollSpan = document.getElementById('roll');
var speedSpan = document.getElementById('speed');
var fromBehind = document.getElementById('fromBehind');

//給左邊的通知欄更新數據同時刷新飛機位置(這裏也是個1ms一次的回調)
viewer.scene.preRender.addEventListener(function(scene, time) {
    headingSpan.innerHTML = Cesium.Math.toDegrees(hpRoll.heading).toFixed(1);
    pitchSpan.innerHTML = Cesium.Math.toDegrees(hpRoll.pitch).toFixed(1);
    rollSpan.innerHTML = Cesium.Math.toDegrees(hpRoll.roll).toFixed(1);
    speedSpan.innerHTML = speed.toFixed(1);

    //選擇的笛卡爾分量Cartesian3.UNIT_X(x軸單位長度)乘以一個標量speed/10,得到速度向量speedVector
    speedVector = Cesium.Cartesian3.multiplyByScalar(Cesium.Cartesian3.UNIT_X, speed / 10, speedVector);
    //飛機的模型矩陣與速度向量speedVector相乘,得到position
    position = Cesium.Matrix4.multiplyByPoint(planePrimitive.modelMatrix, speedVector, position);
    //添加一個路徑模型(就是白色的尾氣)
    pathPosition.addSample(Cesium.JulianDate.now(), position);
    //飛機位置+旋轉角度+地球+座標矩陣=飛機模型矩陣
    Cesium.Transforms.headingPitchRollToFixedFrame(position, hpRoll, Cesium.Ellipsoid.WGS84, fixedFrameTransform, planePrimitive.modelMatrix);

    if (fromBehind.checked) {
        // 鏡頭跟隨
        Cesium.Matrix4.multiplyByPoint(planePrimitive.modelMatrix, planePrimitive.boundingSphere.center, center);
        hpRange.heading = hpRoll.heading;
        hpRange.pitch = hpRoll.pitch;
        camera.lookAt(center, hpRange);
    }
});

如上就是這個Demo的源碼了,具體運行我就不展示了(csdn上傳不了這麼大的gif),還是很有趣的

我覺得註釋已經很詳細了,就不多說了,不清楚或者發現錯誤的請留言,大家一起學習

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