cesium生成视锥体实现视频投射

效果

直接上代码

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
export function addPerspectiveFrustum({
position,
fov = 90,
near = 1,
far = 100,
aspectRatio = 600 / 1080,
heading = 60,
pitch = -70,
roll = 0,
videoUrl


}) {
removePrimitiveById('frustum')
const frustum = new Cesium.PerspectiveFrustum({
fov: Cesium.Math.toRadians(fov),
aspectRatio,
near,
far,
});

const frustumGeometry = new Cesium.FrustumOutlineGeometry({
frustum: frustum,
origin: position,
orientation: Cesium.Quaternion.fromHeadingPitchRoll(new Cesium.HeadingPitchRoll(
Cesium.Math.toRadians(heading),
Cesium.Math.toRadians(pitch),
Cesium.Math.toRadians(roll)
)),
});
// 取出视锥体的顶点坐标
const geometry = Cesium.FrustumOutlineGeometry.createGeometry(frustumGeometry)
const result = []
for (let i = 0; i < geometry.attributes.position.values.length; i+=3) {
result.push(Array.from(geometry.attributes.position.values).slice(i,i+3))
}
removaEntitiesAndPrimitivesByName('frustumPoint')
const videoPolygon = []
result.forEach((e,i)=>{
if (i>3){
//取后四个坐标, 即远面的坐标
const position1 = new Cesium.Cartesian3(...e)
// 生成射线和globe相交,计算交点
const ray = new Cesium.Ray(position,Cesium.Cartesian3.subtract(position1,position,new Cesium.Cartesian3()))
const pickPosition = window.viewer.scene.globe.pick(ray,window.viewer.scene)
if (pickPosition){
videoPolygon.push(pickPosition)
window.viewer.entities.add({
name:'frustumPoint',
position:pickPosition,
point:{
pixelSize: 10,
color: Cesium.Color.fromCssColorString('rgb(255,255,255)'),
outlineColor: Cesium.Color.fromCssColorString('rgb(255,255,255)'),
outlineWidth: 2,
},
polyline:{
positions:[position,pickPosition],
width:2,
material:Cesium.Color.fromCssColorString('rgb(255,255,255)')
}
})
}

}
})
removaEntitiesAndPrimitivesByName('videoFrustumPolygon')
// 获得视锥体和地面的交点,构成平面,并使用video标签做为材质
if (videoPolygon.length === 4){
const videoEle = document.createElement('video')
videoEle.muted = true
videoEle.autoplay = true
videoEle.src = videoUrl || '/busVisulizer/video/chejianVideo.mp4'
videoEle.loop = true
videoEle.id = "videoFrustumPolygon"
document.body.append(videoEle)
window.viewer.entities.add({
name:'videoFrustumPolygon',
polygon:{
hierarchy:videoPolygon,
material:document.getElementById("videoFrustumPolygon"),
}
})
// 需要同步时钟,否则视频不会动
let synchronizer = new Cesium.VideoSynchronizer({
clock : window.viewer.clock,
element : videoEle
});
window.viewer.clock.shouldAnimate = true;
}

const frustumGeometryInstance = new Cesium.GeometryInstance({
geometry: frustumGeometry,
attributes: {
color: Cesium.ColorGeometryInstanceAttribute.fromColor(Cesium.Color.fromCssColorString('rgb(255,255,255)')),
},
id: "frustum",
});


const primitive = new Cesium.Primitive({
geometryInstances: frustumGeometryInstance,
appearance: new Cesium.PerInstanceColorAppearance({
closed: false,
flat: true,
}),
asynchronous:false
})
primitive.id = "frustum"
primitive.position = position
window.viewer.scene.primitives.add(primitive);

}

cesium生成视锥体实现视频投射
http://samkallon.top/blog/2024/04/10/cesium生成视锥体实现视频投射/
作者
samkallon
发布于
2024年4月10日
许可协议