通过 FrustumGeometry
绘制视锥体时,如果直接使用 HeadingPitchRoll
设置方向,可能会导致绘制的视锥体与实际相机的视锥体不一致。主要因为 HeadingPitchRoll 是基于局部坐标系的方向描述,而相机的视锥体方向是基于全局坐标系(通常是 ENU 坐标系)的。
为了确保绘制的视锥体与实际相机的视锥体一致,需要将相机的方向矩阵(Camera.direction
)与 FrustumGeometry
的方向对齐。
1. 获取相机的视锥体参数
首先,获取相机的视锥体参数,包括:
相机的位置(Camera.position)。
相机的方向矩阵(Camera.direction)。
相机的视锥体角度(fov、aspectRatio 等)。
javascript
let viewer = new Cesium.Viewer('cesiumContainer');
let camera = viewer.camera;
// 获取相机的位置
let cameraPosition = camera.position;
// 获取相机的方向矩阵
let cameraDirection = camera.direction;
let cameraUp = camera.up;
let cameraRight = camera.right;
// 获取相机的视锥体参数
let fov = Cesium.Math.toRadians(camera.frustum.fov); // 垂直视场角
let aspectRatio = camera.frustum.aspectRatio; // 宽高比
let near = camera.frustum.near; // 近裁剪面
let far = camera.frustum.far; // 远裁剪面
2. 创建视锥几何体
使用 FrustumGeometry
创建视锥几何体,并设置其方向与相机方向一致。
javascript
// 创建视锥几何体
let frustumGeometry = new Cesium.FrustumGeometry({
position: cameraPosition,
orientation: Cesium.Transforms.rotationMatrixFromPositionVelocity(
cameraPosition,
cameraDirection,
cameraUp
),
frustum: new Cesium.PerspectiveFrustum({
fov: fov,
aspectRatio: aspectRatio,
near: near,
far: far
})
});
// 创建几何体实例
let frustumInstance = new Cesium.GeometryInstance({
geometry: frustumGeometry,
attributes: {
color: Cesium.ColorGeometryInstanceAttribute.fromColor(Cesium.Color.RED.withAlpha(0.5))
}
});
// 添加到图元集合
let primitive = viewer.scene.primitives.add(
new Cesium.Primitive({
geometryInstances: frustumInstance,
appearance: new Cesium.PerInstanceColorAppearance({
translucent: true,
flat: true
})
})
);
3. 动态更新视锥体
如果相机的位置或方向发生变化,需要动态更新视锥几何体的位置和方向。
javascript
viewer.scene.preUpdate.addEventListener(function () {
// 更新相机参数
cameraPosition = camera.position;
cameraDirection = camera.direction;
cameraUp = camera.up;
// 更新视锥几何体的位置和方向
frustumGeometry = new Cesium.FrustumGeometry({
position: cameraPosition,
orientation: Cesium.Transforms.rotationMatrixFromPositionVelocity(
cameraPosition,
cameraDirection,
cameraUp
),
frustum: new Cesium.PerspectiveFrustum({
fov: fov,
aspectRatio: aspectRatio,
near: near,
far: far
})
});
// 更新几何体实例
frustumInstance.geometry = frustumGeometry;
});
4. 解决差异问题
坐标系对齐:确保使用 Cesium.Transforms.rotationMatrixFromPositionVelocity
将方向矩阵与相机方向对齐。
视锥体参数:确保 fov、aspectRatio、near 和 far 参数与相机的视锥体参数一致。
几何体更新:如果相机位置或方向发生变化,必须动态更新视锥几何体的位置和方向。
5. 完整代码示例
以下是一个完整的代码示例:
javascript
let viewer = new Cesium.Viewer('cesiumContainer');
let camera = viewer.camera;
// 获取相机参数
let cameraPosition = camera.position;
let cameraDirection = camera.direction;
let cameraUp = camera.up;
let fov = Cesium.Math.toRadians(camera.frustum.fov);
let aspectRatio = camera.frustum.aspectRatio;
let near = camera.frustum.near;
let far = camera.frustum.far;
// 创建视锥几何体
let frustumGeometry = new Cesium.FrustumGeometry({
position: cameraPosition,
orientation: Cesium.Transforms.rotationMatrixFromPositionVelocity(
cameraPosition,
cameraDirection,
cameraUp
),
frustum: new Cesium.PerspectiveFrustum({
fov: fov,
aspectRatio: aspectRatio,
near: near,
far: far
})
});
// 创建几何体实例
let frustumInstance = new Cesium.GeometryInstance({
geometry: frustumGeometry,
attributes: {
color: Cesium.ColorGeometryInstanceAttribute.fromColor(Cesium.Color.RED.withAlpha(0.5))
}
});
// 添加到图元集合
let primitive = viewer.scene.primitives.add(
new Cesium.Primitive({
geometryInstances: frustumInstance,
appearance: new Cesium.PerInstanceColorAppearance({
translucent: true,
flat: true
})
})
);
// 动态更新视锥体
viewer.scene.preUpdate.addEventListener(function () {
cameraPosition = camera.position;
cameraDirection = camera.direction;
cameraUp = camera.up;
frustumGeometry = new Cesium.FrustumGeometry({
position: cameraPosition,
orientation: Cesium.Transforms.rotationMatrixFromPositionVelocity(
cameraPosition,
cameraDirection,
cameraUp
),
frustum: new Cesium.PerspectiveFrustum({
fov: fov,
aspectRatio: aspectRatio,
near: near,
far: far
})
});
frustumInstance.geometry = frustumGeometry;
});