原文链接及内容

本文演示了VR 按钮开启VR模式的示例:

示例代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
const viewer = new Cesium.Viewer("cesiumContainer", {
vrButton: true,
terrain: Cesium.Terrain.fromWorldTerrain(),
});
// 点击屏幕右下方的 VR 按钮,即可切换到 VR 模式。

viewer.scene.globe.enableLighting = true;
viewer.scene.globe.depthTestAgainstTerrain = true;

// 沿着飞机的路径前进。
// 参见插值 Sandcastle 示例: https://sandcastle.cesium.com/?src=Interpolation.html&label=All
Cesium.Math.setRandomNumberSeed(3);

const start = Cesium.JulianDate.fromDate(new Date(2015, 2, 25, 16));
const stop = Cesium.JulianDate.addSeconds(start, 360, new Cesium.JulianDate());

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 computeCirclularFlight(lon, lat, radius) {
const property = new Cesium.SampledPositionProperty();
const startAngle = Cesium.Math.nextRandomNumber() * 360.0;
const endAngle = startAngle + 360.0;

const increment = (Cesium.Math.nextRandomNumber() * 2.0 - 1.0) * 10.0 + 45.0;
for (let i = startAngle; i < endAngle; i += increment) {
const radians = Cesium.Math.toRadians(i);
const timeIncrement = i - startAngle;
const time = Cesium.JulianDate.addSeconds(
start,
timeIncrement,
new Cesium.JulianDate(),
);
const 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;
}

const longitude = -112.110693;
const latitude = 36.0994841;
const radius = 0.03;

const modelURI = "../SampleData/models/CesiumBalloon/CesiumBalloon.glb";
const entity = viewer.entities.add({
availability: new Cesium.TimeIntervalCollection([
new Cesium.TimeInterval({
start: start,
stop: stop,
}),
]),
position: computeCirclularFlight(longitude, latitude, radius),
model: {
uri: modelURI,
minimumPixelSize: 64,
},
});

entity.position.setInterpolationOptions({
interpolationDegree: 2,
interpolationAlgorithm: Cesium.HermitePolynomialApproximation,
});

// 将初始相机位置和方向设置为位于模型的参考框架中。
const camera = viewer.camera;
camera.position = new Cesium.Cartesian3(0.25, 0.0, 0.0);
camera.direction = new Cesium.Cartesian3(1.0, 0.0, 0.0);
camera.up = new Cesium.Cartesian3(0.0, 0.0, 1.0);
camera.right = new Cesium.Cartesian3(0.0, -1.0, 0.0);

viewer.scene.postUpdate.addEventListener(function (scene, time) {
const position = entity.position.getValue(time);
if (!Cesium.defined(position)) {
return;
}

let transform;
if (!Cesium.defined(entity.orientation)) {
transform = Cesium.Transforms.eastNorthUpToFixedFrame(position);
} else {
const orientation = entity.orientation.getValue(time);
if (!Cesium.defined(orientation)) {
return;
}

transform = Cesium.Matrix4.fromRotationTranslation(
Cesium.Matrix3.fromQuaternion(orientation),
position,
);
}

// 保存相机状态
const offset = Cesium.Cartesian3.clone(camera.position);
const direction = Cesium.Cartesian3.clone(camera.direction);
const up = Cesium.Cartesian3.clone(camera.up);

// 将 camera 设置为在模型的参考系中。
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);
});

// 再添加几个气球与观众所在的气球一起飞行。
const numBalloons = 12;
for (let i = 0; i < numBalloons; ++i) {
const balloonRadius =
(Cesium.Math.nextRandomNumber() * 2.0 - 1.0) * 0.01 + radius;
const balloon = viewer.entities.add({
availability: new Cesium.TimeIntervalCollection([
new Cesium.TimeInterval({
start: start,
stop: stop,
}),
]),
position: computeCirclularFlight(longitude, latitude, balloonRadius),
model: {
uri: modelURI,
minimumPixelSize: 64,
},
});

balloon.position.setInterpolationOptions({
interpolationDegree: 2,
interpolationAlgorithm: Cesium.HermitePolynomialApproximation,
});
}