daodan修改爆炸修改
This commit is contained in:
parent
2283317c85
commit
1d8f4af93c
BIN
public/images/fire.png
Normal file
BIN
public/images/fire.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 756 KiB |
BIN
public/models/导弹整体.glb
Normal file
BIN
public/models/导弹整体.glb
Normal file
Binary file not shown.
BIN
public/models/第一级.glb
Normal file
BIN
public/models/第一级.glb
Normal file
Binary file not shown.
BIN
public/models/第三级.glb
Normal file
BIN
public/models/第三级.glb
Normal file
Binary file not shown.
BIN
public/models/第二级.glb
Normal file
BIN
public/models/第二级.glb
Normal file
Binary file not shown.
BIN
public/models/美三叉戟2动画.glb
Normal file
BIN
public/models/美三叉戟2动画.glb
Normal file
Binary file not shown.
BIN
public/models/美三叉戟2整体.glb
Normal file
BIN
public/models/美三叉戟2整体.glb
Normal file
Binary file not shown.
BIN
public/models/美三叉戟2第一级.glb
Normal file
BIN
public/models/美三叉戟2第一级.glb
Normal file
Binary file not shown.
BIN
public/models/美三叉戟2第三级.glb
Normal file
BIN
public/models/美三叉戟2第三级.glb
Normal file
Binary file not shown.
BIN
public/models/美三叉戟2第二级.glb
Normal file
BIN
public/models/美三叉戟2第二级.glb
Normal file
Binary file not shown.
@ -2,6 +2,15 @@ export default class ExplosionEffect {
|
||||
constructor(viewer, obj) {
|
||||
this.viewer = viewer
|
||||
this.viewModel = {
|
||||
// emissionRate: 5,
|
||||
// gravity: 0.0, //设置重力参数
|
||||
// minimumParticleLife: 1,
|
||||
// maximumParticleLife: 6,
|
||||
// minimumSpeed: 1.0, //粒子发射的最小速度
|
||||
// maximumSpeed: 4.0, //粒子发射的最大速度
|
||||
// startScale: 0.0,
|
||||
// endScale: 8.0,
|
||||
// particleSize: 25.0,
|
||||
emissionRate: 5,
|
||||
gravity: 0.0, //设置重力参数
|
||||
minimumParticleLife: 1,
|
||||
@ -10,7 +19,7 @@ export default class ExplosionEffect {
|
||||
maximumSpeed: 4.0, //粒子发射的最大速度
|
||||
startScale: 0.0,
|
||||
endScale: 8.0,
|
||||
particleSize: 25.0,
|
||||
particleSize: 10.0,
|
||||
}
|
||||
this.emitterModelMatrix = new Cesium.Matrix4()
|
||||
this.translation = new Cesium.Cartesian3()
|
||||
@ -33,7 +42,8 @@ export default class ExplosionEffect {
|
||||
// this.viewer.trackedEntity = this.entity;
|
||||
let particleSystem = this.scene.primitives.add(
|
||||
new Cesium.ParticleSystem({
|
||||
image: './images/explosion.png', //生成所需粒子的图片路径
|
||||
// image: './images/explosion.png', //生成所需粒子的图片路径
|
||||
image: './images/fire.png', //生成所需粒子的图片路径
|
||||
//粒子在生命周期开始时的颜色
|
||||
startColor: Cesium.Color.RED.withAlpha(0.7),
|
||||
//粒子在生命周期结束时的颜色
|
||||
@ -61,14 +71,33 @@ export default class ExplosionEffect {
|
||||
lifetime: 16.0,
|
||||
//设置粒子的大小是否以米或像素为单位
|
||||
sizeInMeters: false,
|
||||
// sizeInMeters: true,
|
||||
//系统的粒子发射器
|
||||
emitter: new Cesium.CircleEmitter(5.0), //BoxEmitter 盒形发射器,ConeEmitter 锥形发射器,SphereEmitter 球形发射器,CircleEmitter圆形发射器
|
||||
// emitter: new Cesium.CircleEmitter(5.0), //BoxEmitter 盒形发射器,ConeEmitter 锥形发射器,SphereEmitter 球形发射器,CircleEmitter圆形发射器
|
||||
emitter: new Cesium.CircleEmitter(2.0), //BoxEmitter 盒形发射器,ConeEmitter 锥形发射器,SphereEmitter 球形发射器,CircleEmitter圆形发射器
|
||||
//回调函数,实现各种喷泉、烟雾效果
|
||||
updateCallback: (p, dt) => {
|
||||
return this.applyGravity(p, dt)
|
||||
},
|
||||
})
|
||||
)
|
||||
this.particleSystem = particleSystem
|
||||
this.preUpdateEvent()
|
||||
}
|
||||
|
||||
applyGravity(p, dt) {
|
||||
let gravityScratch = new Cesium.Cartesian3()
|
||||
let position = p.position
|
||||
Cesium.Cartesian3.normalize(position, gravityScratch)
|
||||
Cesium.Cartesian3.fromElements(
|
||||
20 * dt,
|
||||
30 * dt,
|
||||
gravityScratch.y * dt,
|
||||
gravityScratch
|
||||
)
|
||||
p.velocity = Cesium.Cartesian3.add(p.velocity, gravityScratch, p.velocity)
|
||||
}
|
||||
|
||||
//场景渲染事件
|
||||
preUpdateEvent() {
|
||||
let _this = this
|
||||
|
101
src/utils/pos.js
101
src/utils/pos.js
@ -32,6 +32,107 @@ export function getPositionFromTime(
|
||||
return points
|
||||
}
|
||||
|
||||
export function getOnePositionFromTime(startTime, i, pos) {
|
||||
const time = Cesium.JulianDate.addSeconds(
|
||||
startTime,
|
||||
i,
|
||||
new Cesium.JulianDate()
|
||||
)
|
||||
const point = pos.getValue(time)
|
||||
return point
|
||||
}
|
||||
|
||||
export function getBezierSpline(points) {
|
||||
return bezierSpline(lineString(points))
|
||||
}
|
||||
|
||||
export async function test() {
|
||||
const points = createTrajectory(
|
||||
[137, 25, 0, 1183135285000],
|
||||
[140, 27, 100000, 1183135295000]
|
||||
).map(point => {
|
||||
// const point = getTrajectoryPoint(i)
|
||||
console.log(point)
|
||||
// console.log(
|
||||
// `t=${point.time}s, lon=${point.longitude.toFixed(
|
||||
// 3
|
||||
// )}, lat=${point.latitude.toFixed(3)}, alt=${point.altitude.toFixed(2)}m`
|
||||
// )
|
||||
return [point.lon, point.lat, point.alt]
|
||||
})
|
||||
// const points = a.map(item => {
|
||||
// return [item.lon, item.lat, item.alt]
|
||||
// })
|
||||
viewer.entities.add({
|
||||
name: 'line',
|
||||
polyline: {
|
||||
positions: Cesium.Cartesian3.fromDegreesArrayHeights(
|
||||
points.flat(Infinity)
|
||||
),
|
||||
width: 10,
|
||||
material: new Cesium.PolylineGlowMaterialProperty({
|
||||
glowPower: 0.1,
|
||||
color: Cesium.Color.RED,
|
||||
}),
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
export function createTrajectory(p1, p2, options = {}) {
|
||||
const {
|
||||
steps = 20,
|
||||
useStartAsPeak = false,
|
||||
useEndAsPeak = false,
|
||||
peakBias = 0.3, // 控制曲率偏向:0.5 表示中点;靠近 0 表示更靠近起点
|
||||
midOffset = 1000,
|
||||
} = options
|
||||
|
||||
const [lon1, lat1, alt1, t1] = p1
|
||||
const [lon2, lat2, alt2, t2] = p2
|
||||
|
||||
const dt = (t2 - t1) / 1000 // 秒
|
||||
const tPeak =
|
||||
dt * (useEndAsPeak ? 1 - peakBias : useStartAsPeak ? peakBias : 0.5)
|
||||
|
||||
// 设置高度
|
||||
let h0 = alt1
|
||||
let h2 = alt2
|
||||
let h1
|
||||
|
||||
if (useStartAsPeak) {
|
||||
h1 = (alt1 + alt2) / 2 - midOffset
|
||||
} else if (useEndAsPeak) {
|
||||
h1 = (alt1 + alt2) / 2 - midOffset
|
||||
} else {
|
||||
h1 = Math.max(alt1, alt2) + midOffset
|
||||
}
|
||||
|
||||
// 三点拟合抛物线
|
||||
const c = h0
|
||||
const A = [
|
||||
[tPeak ** 2, tPeak],
|
||||
[dt ** 2, dt],
|
||||
]
|
||||
const B = [h1 - c, h2 - c]
|
||||
|
||||
const denom = A[0][0] * A[1][1] - A[0][1] * A[1][0]
|
||||
const a = (B[0] * A[1][1] - B[1] * A[0][1]) / denom
|
||||
const b = (A[0][0] * B[1] - A[1][0] * B[0]) / denom
|
||||
|
||||
const result = []
|
||||
|
||||
for (let i = 0; i <= steps; i++) {
|
||||
const t = (dt * i) / steps
|
||||
const fraction = t / dt
|
||||
|
||||
const lon = lon1 + (lon2 - lon1) * fraction
|
||||
const lat = lat1 + (lat2 - lat1) * fraction
|
||||
const alt = a * t * t + b * t + c
|
||||
|
||||
result.push({ t: t1 + t * 1000, lon, lat, alt })
|
||||
}
|
||||
|
||||
return result
|
||||
}
|
||||
|
||||
// 示例:每秒插值
|
||||
|
@ -9,8 +9,14 @@ const panels = ['手动配置', 'STK轨迹文件配置']
|
||||
export default defineComponent({
|
||||
setup() {
|
||||
const { daodanData, showOrHideDdConfig } = useDaodan()
|
||||
const { trajData, interceptData, loadStoreData, addIntercept, initDaodan } =
|
||||
useTestConfig()
|
||||
const {
|
||||
trajData,
|
||||
boosterList,
|
||||
interceptData,
|
||||
loadStoreData,
|
||||
addIntercept,
|
||||
initDaodan,
|
||||
} = useTestConfig()
|
||||
|
||||
watch(daodanData, newval => {
|
||||
loadStoreData()
|
||||
@ -54,8 +60,19 @@ export default defineComponent({
|
||||
<div class="detail-container">
|
||||
{panel === '手动配置' ? (
|
||||
<>
|
||||
<div class="rounded border border-blue-500 p-4">
|
||||
<TrajTable title="轨迹点" data={trajData.value} />
|
||||
<div class="flex flex-col gap-4 rounded border border-blue-500 p-4">
|
||||
<TrajTable
|
||||
title="轨迹点"
|
||||
data={trajData.value}
|
||||
showPosIcon={false}
|
||||
/>
|
||||
{boosterList.value.map((booster, index) => (
|
||||
<TrajTable
|
||||
title={`${['一', '二', '三'][index]}级助推器`}
|
||||
data={booster}
|
||||
showPosIcon={false}
|
||||
/>
|
||||
))}
|
||||
</div>
|
||||
<div class="flex flex-col gap-4 rounded border border-red-500 p-4">
|
||||
{interceptData.value.map(data => (
|
||||
@ -63,6 +80,7 @@ export default defineComponent({
|
||||
title="拦截"
|
||||
data={data}
|
||||
onRemoveIntercept={removeIntercept}
|
||||
showPosIcon={false}
|
||||
/>
|
||||
))}
|
||||
<div>
|
||||
@ -75,6 +93,9 @@ export default defineComponent({
|
||||
) : (
|
||||
<>
|
||||
<TrajUpload title="轨迹点" />
|
||||
<TrajUpload title="一级助推器" />
|
||||
<TrajUpload title="二级助推器" />
|
||||
<TrajUpload title="三级助推器" />
|
||||
<TrajUpload title="拦截" />
|
||||
</>
|
||||
)}
|
||||
|
@ -38,7 +38,7 @@ export default defineComponent({
|
||||
render(row) {
|
||||
return (
|
||||
<div class="flex items-center justify-between gap-2">
|
||||
<div>{row.name} </div>
|
||||
<div>{row.name}</div>
|
||||
{props.showPosIcon && (
|
||||
<NButton
|
||||
// quaternary
|
||||
@ -75,7 +75,7 @@ export default defineComponent({
|
||||
},
|
||||
},
|
||||
{
|
||||
title: '经度',
|
||||
title: getTitle('lon'),
|
||||
key: 'lon',
|
||||
render(row) {
|
||||
return (
|
||||
@ -88,7 +88,7 @@ export default defineComponent({
|
||||
},
|
||||
},
|
||||
{
|
||||
title: '纬度',
|
||||
title: getTitle('lat'),
|
||||
key: 'lat',
|
||||
render(row) {
|
||||
return (
|
||||
@ -109,7 +109,7 @@ export default defineComponent({
|
||||
},
|
||||
},
|
||||
{
|
||||
title: '时间',
|
||||
title: getTitle('time'),
|
||||
key: 'time',
|
||||
render(row) {
|
||||
return (
|
||||
@ -117,52 +117,27 @@ export default defineComponent({
|
||||
)
|
||||
},
|
||||
},
|
||||
{
|
||||
title: '助推器脱落',
|
||||
key: 'detached',
|
||||
render(row, rowIndex) {
|
||||
return rowIndex !== 0 && rowIndex < trajData.value.length - 1 ? (
|
||||
<NSwitch v-model:value={row.detached} type="datetime"></NSwitch>
|
||||
) : (
|
||||
'-'
|
||||
)
|
||||
},
|
||||
},
|
||||
{
|
||||
title: '操作',
|
||||
render(row, rowIndex) {
|
||||
return rowIndex !== 0 && rowIndex < trajData.value.length - 1 ? (
|
||||
<NButton
|
||||
type="error"
|
||||
text
|
||||
v-slots={{
|
||||
icon: () => (
|
||||
<NIcon>
|
||||
<TrashOutline />
|
||||
</NIcon>
|
||||
),
|
||||
}}
|
||||
onClick={() => {
|
||||
trajData.value.splice(rowIndex, 1)
|
||||
}}
|
||||
></NButton>
|
||||
) : (
|
||||
'-'
|
||||
)
|
||||
},
|
||||
},
|
||||
]
|
||||
|
||||
const addFeaturePoint = () => {
|
||||
trajData.value.splice(trajData.value.length - 1, 0, {
|
||||
name: '中间特征点',
|
||||
lon: 0,
|
||||
lat: 0,
|
||||
alt: 0,
|
||||
time: Date.now(),
|
||||
detached: false,
|
||||
})
|
||||
function getTitle(key) {
|
||||
const isIntercept = props.title.indexOf('拦截') > -1
|
||||
const isBooster = props.title.indexOf('助推器') > -1
|
||||
|
||||
const dict = {
|
||||
time: isIntercept ? '命中时间' : isBooster ? '脱离时间' : '时间',
|
||||
lat: isIntercept ? '发射纬度' : isBooster ? '落点纬度' : '纬度',
|
||||
lon: isIntercept ? '发射经度' : isBooster ? '落点经度' : '经度',
|
||||
alt: '高度',
|
||||
}
|
||||
return dict[key] || key
|
||||
}
|
||||
|
||||
if (props.title.indexOf('助推器') > -1) {
|
||||
columns.splice(3, 1)
|
||||
} else if (props.title.indexOf('拦截') > -1) {
|
||||
columns.splice(3, 1)
|
||||
}
|
||||
|
||||
const dialog = useDialog()
|
||||
const remove = () => {
|
||||
dialog.warning({
|
||||
@ -180,9 +155,6 @@ export default defineComponent({
|
||||
<div class="flex justify-between">
|
||||
<div class="detail-item-title">{props.title}</div>
|
||||
<div>
|
||||
<NButton quaternary type="primary" onClick={addFeaturePoint}>
|
||||
添加特征点
|
||||
</NButton>
|
||||
{props.title.indexOf('拦截') > -1 && (
|
||||
<NButton quaternary type="error" onClick={remove}>
|
||||
删除拦截
|
||||
|
@ -1,12 +1,20 @@
|
||||
import { ref, toRaw } from 'vue'
|
||||
import { useDaodan } from '../../ddHooks'
|
||||
import { cartesian32LonLat, getPositionFromTime } from '@/utils/pos'
|
||||
import {
|
||||
cartesian32LonLat,
|
||||
getPositionFromTime,
|
||||
getOnePositionFromTime,
|
||||
test,
|
||||
createTrajectory,
|
||||
} from '@/utils/pos'
|
||||
import ExplosionEffect from '@/js/Explosion'
|
||||
import { generateId } from '@/utils/id'
|
||||
import store from 'store2'
|
||||
// import { getPositionFromTime } from '@/utils/pos'
|
||||
import { lineString, bezierSpline } from '@turf/turf'
|
||||
// import { useDaodan } from '../../ddHooks'
|
||||
|
||||
const ddScale = 30
|
||||
|
||||
const trajData = ref({
|
||||
id: 'dd',
|
||||
data: [
|
||||
@ -18,63 +26,69 @@ const trajData = ref({
|
||||
time: 1183135260000,
|
||||
},
|
||||
{
|
||||
name: '中间特征点',
|
||||
lon: 122,
|
||||
lat: 21,
|
||||
alt: 1000000,
|
||||
time: 1183135265000,
|
||||
detached: true,
|
||||
},
|
||||
{
|
||||
name: '中间特征点',
|
||||
lon: 124,
|
||||
lat: 21,
|
||||
alt: 1500000,
|
||||
time: 1183135270000,
|
||||
detached: true,
|
||||
},
|
||||
{
|
||||
name: '中间特征点',
|
||||
lon: 128,
|
||||
lat: 21,
|
||||
name: '最高点',
|
||||
lon: 125,
|
||||
lat: 25,
|
||||
alt: 2000000,
|
||||
time: 1183135280000,
|
||||
detached: true,
|
||||
},
|
||||
{
|
||||
name: '落点',
|
||||
lon: 135,
|
||||
lat: 21,
|
||||
alt: 1500000,
|
||||
time: 1183135290000,
|
||||
lon: 160,
|
||||
lat: 40,
|
||||
alt: 0,
|
||||
time: 1183135300000,
|
||||
},
|
||||
],
|
||||
})
|
||||
const interceptData = ref([
|
||||
const boosterList = ref([
|
||||
{
|
||||
id: 'dd1',
|
||||
id: 'booster-1',
|
||||
data: [
|
||||
{
|
||||
name: '起始点',
|
||||
lon: 137,
|
||||
lat: 25,
|
||||
// name: '落点',
|
||||
lon: 130,
|
||||
lat: 23,
|
||||
alt: 0,
|
||||
time: 1183135265000,
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
id: 'booster-2',
|
||||
data: [
|
||||
{
|
||||
// name: '落点',
|
||||
lon: 135,
|
||||
lat: 28,
|
||||
alt: 0,
|
||||
time: 1183135270000,
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
id: 'booster-3',
|
||||
data: [
|
||||
{
|
||||
name: '中间特征点',
|
||||
lon: 138,
|
||||
lat: 24,
|
||||
alt: 1000000,
|
||||
time: 1183135280000,
|
||||
detached: true,
|
||||
// name: '落点',
|
||||
lon: 140,
|
||||
lat: 35,
|
||||
alt: 0,
|
||||
time: 1183135275000,
|
||||
},
|
||||
],
|
||||
},
|
||||
])
|
||||
const interceptData = ref([
|
||||
{
|
||||
id: 'intercept-1',
|
||||
data: [
|
||||
{
|
||||
name: '落点',
|
||||
lon: 135,
|
||||
lat: 21,
|
||||
alt: 1500000,
|
||||
time: 1183135290000,
|
||||
// name: '起始点',
|
||||
lon: 137,
|
||||
lat: 25,
|
||||
alt: 0,
|
||||
time: 1183135285000,
|
||||
},
|
||||
],
|
||||
},
|
||||
@ -85,6 +99,7 @@ const { daodanData, showDdConfigCom } = useDaodan()
|
||||
export function useTestConfig() {
|
||||
return {
|
||||
trajData,
|
||||
boosterList,
|
||||
interceptData,
|
||||
loadStoreData,
|
||||
addIntercept,
|
||||
@ -94,13 +109,16 @@ export function useTestConfig() {
|
||||
}
|
||||
|
||||
function saveDataToStore() {
|
||||
// test()
|
||||
const daodanDataRaw = toRaw(daodanData.value)
|
||||
const storeData = store.get('daodanData')
|
||||
|
||||
store.set('daodanData', {
|
||||
...storeData,
|
||||
[daodanDataRaw.id]: {
|
||||
...daodanDataRaw,
|
||||
trajData: trajData.value,
|
||||
boosterList: boosterList.value,
|
||||
interceptData: interceptData.value,
|
||||
},
|
||||
})
|
||||
@ -174,20 +192,23 @@ function addDaodan(trajData, type = 0) {
|
||||
ddTrajData[0].alt
|
||||
)
|
||||
const hpRoll = new Cesium.HeadingPitchRoll()
|
||||
// const fixedFrameTransform = Cesium.Transforms.eastNorthUpToFixedFrame
|
||||
const fixedFrameTransform = Cesium.Transforms.localFrameToFixedFrameGenerator(
|
||||
'north',
|
||||
'west'
|
||||
)
|
||||
hpRoll.pitch = (90 * Math.PI) / 180
|
||||
// hpRoll.pitch = (90 * Math.PI) / 180
|
||||
const modelObj = Cesium.Model.fromGltf({
|
||||
url: './models/launchvehicle.glb',
|
||||
// url: './models/launchvehicle.glb',
|
||||
url: './models/美三叉戟2动画.glb',
|
||||
modelMatrix: Cesium.Transforms.headingPitchRollToFixedFrame(
|
||||
position,
|
||||
hpRoll,
|
||||
Cesium.Ellipsoid.WGS84,
|
||||
fixedFrameTransform
|
||||
),
|
||||
minimumPixelSize: 70,
|
||||
scale: ddScale,
|
||||
minimumPixelSize: ddScale,
|
||||
})
|
||||
|
||||
const ddPrimitive = viewer.scene.primitives.add(modelObj)
|
||||
@ -210,17 +231,16 @@ function addDaodan(trajData, type = 0) {
|
||||
// })
|
||||
|
||||
ddPrimitive.readyPromise.then(model => {
|
||||
console.log('model', model)
|
||||
nodes = model.pickIds.map(item => item.object.detail.node)
|
||||
nodes.forEach(i => {
|
||||
// console.log(i._name, model.getNode(i._name))
|
||||
if (new RegExp(/SRB\d/).test(i._name)) {
|
||||
model.getNode(i._name).show = false
|
||||
}
|
||||
})
|
||||
console.log('nodes', nodes)
|
||||
// nodes.forEach(i => {
|
||||
// // console.log(i._name, model.getNode(i._name))
|
||||
// if (new RegExp(/SRB\d/).test(i._name)) {
|
||||
// model.getNode(i._name).show = false
|
||||
// }
|
||||
// })
|
||||
computePath(ddPrimitive, trajData, type)
|
||||
// setTimeout(() => {
|
||||
// playDaodan(ddPrimitive, nodes)
|
||||
// }, 3000)
|
||||
})
|
||||
}
|
||||
|
||||
@ -229,16 +249,16 @@ function initDaodan() {
|
||||
saveDataToStore()
|
||||
minTime = getMinTime([
|
||||
...toRaw(trajData.value.data),
|
||||
...toRaw(interceptData.value.map(item => toRaw(item.data))).flat(Infinity),
|
||||
// ...toRaw(interceptData.value.map(item => toRaw(item.data))).flat(Infinity),
|
||||
])
|
||||
// console.log(minTime)
|
||||
addDaodan(trajData.value)
|
||||
aniIndexMap.set(trajData.value.id, 0)
|
||||
interceptData.value.forEach(item => {
|
||||
const { id, data } = item
|
||||
addDaodan(item, 1)
|
||||
aniIndexMap.set(id, 0)
|
||||
})
|
||||
// interceptData.value.forEach(item => {
|
||||
// const { id, data } = item
|
||||
// addDaodan(item, 1)
|
||||
// aniIndexMap.set(id, 0)
|
||||
// })
|
||||
}
|
||||
|
||||
function getMinTime(data) {
|
||||
@ -249,14 +269,16 @@ function getMinTime(data) {
|
||||
return minTime
|
||||
}
|
||||
|
||||
const pathLine = new Map()
|
||||
|
||||
function computePath(daodan, trajData, type) {
|
||||
const { data: ddTrajData } = trajData
|
||||
const { id, data: ddTrajData } = trajData
|
||||
const points = ddTrajData.map(item => {
|
||||
const { time, lon, lat, alt, detached } = item
|
||||
const { time, lon, lat, alt } = item
|
||||
|
||||
return {
|
||||
position: Cesium.Cartesian3.fromDegrees(lon, lat, alt),
|
||||
time: time - minTime,
|
||||
detached,
|
||||
}
|
||||
})
|
||||
const totalAnimationTime = points.at(-1).time
|
||||
@ -270,13 +292,13 @@ function computePath(daodan, trajData, type) {
|
||||
point.time / 1000,
|
||||
new Cesium.JulianDate()
|
||||
)
|
||||
viewer.entities.add({
|
||||
position: point.position,
|
||||
point: {
|
||||
color: Cesium.Color.WHITE,
|
||||
pixelSize: 5,
|
||||
},
|
||||
})
|
||||
// const point = viewer.entities.add({
|
||||
// position: point.position,
|
||||
// point: {
|
||||
// color: Cesium.Color.WHITE,
|
||||
// pixelSize: 5,
|
||||
// },
|
||||
// })
|
||||
positionProperty.addSample(time, point.position)
|
||||
})
|
||||
positionProperty.setInterpolationOptions({
|
||||
@ -285,7 +307,28 @@ function computePath(daodan, trajData, type) {
|
||||
// interpolationDegree: 5,
|
||||
// interpolationAlgorithm: Cesium.LagrangePolynomialApproximation,
|
||||
})
|
||||
createLine({ totalAnimationTime, startTime, positionProperty, type })
|
||||
const line = createLine({
|
||||
totalAnimationTime,
|
||||
startTime,
|
||||
positionProperty,
|
||||
type,
|
||||
})
|
||||
|
||||
pathLine.set(id, line)
|
||||
if (type === 0) {
|
||||
computeBoosterOrInterceptPath({
|
||||
dataList: boosterList.value,
|
||||
startTime,
|
||||
positionProperty,
|
||||
type: 'booster',
|
||||
})
|
||||
computeBoosterOrInterceptPath({
|
||||
dataList: interceptData.value,
|
||||
startTime,
|
||||
positionProperty,
|
||||
type: 'intercept',
|
||||
})
|
||||
}
|
||||
daodanAnimation({
|
||||
totalAnimationTime,
|
||||
startTime,
|
||||
@ -295,11 +338,140 @@ function computePath(daodan, trajData, type) {
|
||||
})
|
||||
}
|
||||
|
||||
const boosterMap = new Map()
|
||||
const interceptMap = new Map()
|
||||
const interceptTime = ref()
|
||||
function computeBoosterOrInterceptPath({
|
||||
dataList,
|
||||
startTime,
|
||||
positionProperty,
|
||||
type,
|
||||
}) {
|
||||
dataList.forEach((dataItem, index) => {
|
||||
const { id, data } = dataItem
|
||||
let points = []
|
||||
data.forEach(item => {
|
||||
const { time, lon, lat, alt } = item
|
||||
|
||||
const position = getOnePositionFromTime(
|
||||
startTime,
|
||||
(time - minTime) / 1000,
|
||||
positionProperty
|
||||
)
|
||||
|
||||
// points.push({
|
||||
// position,
|
||||
// time: time - minTime,
|
||||
// })
|
||||
|
||||
const lonlat = cartesian32LonLat(position)
|
||||
|
||||
const pointTime = time - minTime
|
||||
|
||||
const aniPointTime = pointTime + (type === 'booster' ? 10000 : -10000)
|
||||
type === 'intercept' && (interceptTime.value = pointTime / 1000)
|
||||
const pointInline = {
|
||||
position: Cesium.Cartesian3.fromDegrees(lon, lat, alt),
|
||||
time: aniPointTime,
|
||||
}
|
||||
// points.push(pointInline)
|
||||
|
||||
points = createTrajectory(
|
||||
[lon, lat, alt, aniPointTime],
|
||||
[...lonlat, time - minTime],
|
||||
{
|
||||
useEndAsPeak: true,
|
||||
peakBias: 0.65,
|
||||
midOffset: 1000,
|
||||
}
|
||||
).map(item => {
|
||||
return {
|
||||
position: Cesium.Cartesian3.fromDegrees(item.lon, item.lat, item.alt),
|
||||
time: item.t,
|
||||
}
|
||||
})
|
||||
})
|
||||
|
||||
const dataPositionProperty = new Cesium.SampledPositionProperty()
|
||||
points.forEach(point => {
|
||||
const time = Cesium.JulianDate.addSeconds(
|
||||
startTime,
|
||||
point.time / 1000,
|
||||
new Cesium.JulianDate()
|
||||
)
|
||||
|
||||
// viewer.entities.add({
|
||||
// position: point.position,
|
||||
// point: {
|
||||
// color: Cesium.Color.ORANGE,
|
||||
// pixelSize: 5,
|
||||
// },
|
||||
// })
|
||||
dataPositionProperty.addSample(time, point.position)
|
||||
})
|
||||
dataPositionProperty.setInterpolationOptions({
|
||||
interpolationDegree: 2,
|
||||
interpolationAlgorithm: Cesium.HermitePolynomialApproximation,
|
||||
})
|
||||
|
||||
const dataLine = createLine({
|
||||
totalAnimationTime: points.at(-1).time,
|
||||
startTime,
|
||||
positionProperty: dataPositionProperty,
|
||||
type: 2,
|
||||
color: type === 'booster' ? 'ORANGE' : 'RED',
|
||||
})
|
||||
|
||||
const modelUrl =
|
||||
type === 'booster'
|
||||
? `./models/美三叉戟2第${['一', '二', '三'][index]}级.glb`
|
||||
: './models/美三叉戟2动画.glb'
|
||||
|
||||
dataLine.model = {
|
||||
show: true,
|
||||
uri: modelUrl,
|
||||
runAnimations: false,
|
||||
// uri: `./models/第${['一', '二', '三'][index]}级.glb`,
|
||||
scale: type === 'booster' ? ddScale / 4 : ddScale,
|
||||
minimumPixelSize: type === 'booster' ? ddScale / 4 : ddScale,
|
||||
}
|
||||
dataLine.orientation = new Cesium.VelocityOrientationProperty(
|
||||
dataPositionProperty
|
||||
)
|
||||
|
||||
type === 'booster'
|
||||
? boosterMap.set(id, dataLine)
|
||||
: interceptMap.set(id, dataLine)
|
||||
})
|
||||
}
|
||||
|
||||
function daodanAnimation(params) {
|
||||
const { totalAnimationTime, startTime, positionProperty, daodan, trajData } =
|
||||
params
|
||||
// const { data: ddTrajData } = trajData
|
||||
dianhuo(daodan)
|
||||
// dianhuo(daodan)
|
||||
|
||||
// setTimeout(() => {
|
||||
// modelAnimationController({
|
||||
// primitive: daodan,
|
||||
// type: '第一级发动机 MoveZ',
|
||||
// initVal: 0,
|
||||
// minVal: -450,
|
||||
// step: -3,
|
||||
// fn: () => {
|
||||
// console.log(
|
||||
// `一级脱离`,
|
||||
// 'color: red;font-size: 20px;border: 1px solid red'
|
||||
// )
|
||||
// nodes.forEach(i => {
|
||||
// const nodeName = i._name
|
||||
// if (new RegExp(/第一级发动机/).test(nodeName)) {
|
||||
// daodan.getNode(nodeName).show = false
|
||||
// }
|
||||
// })
|
||||
// },
|
||||
// })
|
||||
// }, 3000)
|
||||
|
||||
let lastFrameTime = performance.now()
|
||||
let customElapsedTime = 0
|
||||
@ -317,12 +489,17 @@ function daodanAnimation(params) {
|
||||
if (customElapsedTime >= totalAnimationTime) {
|
||||
customElapsedTime = totalAnimationTime // 限制时间为总时长
|
||||
isAnimationRunning = false // 停止动画
|
||||
|
||||
setTimeout(() => {
|
||||
removeAllEntity()
|
||||
}, 6000)
|
||||
}
|
||||
ddNodesAnimationController({
|
||||
ddPrimitive: daodan,
|
||||
curTime: minTime + customElapsedTime * 1000,
|
||||
trajData,
|
||||
})
|
||||
|
||||
// ddNodesAnimationController({
|
||||
// ddPrimitive: daodan,
|
||||
// curTime: minTime + customElapsedTime * 1000,
|
||||
// trajData,
|
||||
// })
|
||||
|
||||
// 计算自定义时间下的位置
|
||||
const customTime = Cesium.JulianDate.addSeconds(
|
||||
@ -340,17 +517,28 @@ function daodanAnimation(params) {
|
||||
new Cesium.JulianDate()
|
||||
)
|
||||
)
|
||||
if (position && !nextPosition && !explosion) {
|
||||
const [lon, lat, height] = cartesian32LonLat(position)
|
||||
explosion = new ExplosionEffect(viewer, {
|
||||
lng: lon,
|
||||
lat: lat,
|
||||
height,
|
||||
})
|
||||
|
||||
if (interceptTime.value && customElapsedTime >= interceptTime.value) {
|
||||
customElapsedTime = totalAnimationTime
|
||||
isAnimationRunning = false
|
||||
explosion = explosionEffect(position)
|
||||
|
||||
setTimeout(() => {
|
||||
explosion && explosion.remove()
|
||||
removeAllEntity()
|
||||
}, 6000)
|
||||
}
|
||||
if (position && !nextPosition && !explosion) {
|
||||
// const [lon, lat, height] = cartesian32LonLat(position)
|
||||
// explosion = new ExplosionEffect(viewer, {
|
||||
// lng: lon,
|
||||
// lat: lat,
|
||||
// height,
|
||||
// })
|
||||
// setTimeout(() => {
|
||||
// explosion && explosion.remove()
|
||||
// }, 6000)
|
||||
explosion = explosionEffect(position)
|
||||
}
|
||||
if (position && nextPosition) {
|
||||
const fixedFrameTransform =
|
||||
Cesium.Transforms.localFrameToFixedFrameGenerator('north', 'west')
|
||||
@ -363,16 +551,22 @@ function daodanAnimation(params) {
|
||||
fixedFrameTransform,
|
||||
daodan.modelMatrix
|
||||
)
|
||||
|
||||
// Cesium.Matrix4.fromTranslationQuaternionRotationScale(
|
||||
// position,
|
||||
// orientation,
|
||||
// new Cesium.Cartesian3(1.0, 1.0, 1.0), // 缩放比例,
|
||||
// daodan.modelMatrix
|
||||
// )
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
function explosionEffect(position) {
|
||||
const [lon, lat, height] = cartesian32LonLat(position)
|
||||
const explosion = new ExplosionEffect(viewer, {
|
||||
lng: lon,
|
||||
lat: lat,
|
||||
height,
|
||||
})
|
||||
setTimeout(() => {
|
||||
explosion && explosion.remove()
|
||||
}, 6000)
|
||||
return explosion
|
||||
}
|
||||
function dianhuo(ddPrimitive) {
|
||||
modelAnimationController({
|
||||
primitive: ddPrimitive,
|
||||
@ -392,14 +586,6 @@ function ddNodesAnimationController(params) {
|
||||
const { id: ddId, data: ddTrajData } = trajData
|
||||
const nodeAniList = ddTrajData.filter(item => item.detached)
|
||||
|
||||
// console.log(
|
||||
// curTime,
|
||||
// aniIndex,
|
||||
// nodeAniList[aniIndex].time,
|
||||
// curTime >= nodeAniList[aniIndex].time,
|
||||
// 'curTime'
|
||||
// )
|
||||
|
||||
if (!ddPrimitive || !aniIndexMap.has(ddId)) return
|
||||
|
||||
const aniIndex = aniIndexMap.get(ddId)
|
||||
@ -595,38 +781,36 @@ function getHeadingPitchRoll(curPos, nextPos) {
|
||||
return hpr
|
||||
}
|
||||
|
||||
function createLine({ totalAnimationTime, startTime, positionProperty, type }) {
|
||||
function createLine({
|
||||
totalAnimationTime,
|
||||
startTime,
|
||||
positionProperty,
|
||||
type,
|
||||
color,
|
||||
}) {
|
||||
const positionList = getPositionFromTime(
|
||||
startTime,
|
||||
positionProperty,
|
||||
totalAnimationTime
|
||||
)
|
||||
viewer.entities.add({
|
||||
// if (type === 2) {
|
||||
// console.log('positionList', positionList)
|
||||
// }
|
||||
|
||||
return viewer.entities.add({
|
||||
position: positionProperty,
|
||||
polyline: {
|
||||
positions: positionList,
|
||||
width: 2,
|
||||
material: type
|
||||
? Cesium.Color.RED.withAlpha(0.5)
|
||||
: Cesium.Color.BLUE.withAlpha(0.5),
|
||||
width: 8,
|
||||
material: new Cesium.PolylineGlowMaterialProperty({
|
||||
glowPower: 0.1,
|
||||
color: type
|
||||
? type === 2 && Cesium.Color[color].withAlpha(0.5)
|
||||
: Cesium.Color.BLUE.withAlpha(0.5),
|
||||
}),
|
||||
},
|
||||
})
|
||||
}
|
||||
// function getPositionFromTime(startTime, pos, totalAnimationTime) {
|
||||
// const points = []
|
||||
|
||||
// for (let i = 0; i <= totalAnimationTime / 100; i++) {
|
||||
// const time = Cesium.JulianDate.addSeconds(
|
||||
// startTime,
|
||||
// i,
|
||||
// new Cesium.JulianDate()
|
||||
// )
|
||||
// const point = pos.getValue(time)
|
||||
// point && points.push(point)
|
||||
// }
|
||||
|
||||
// return points
|
||||
// }
|
||||
|
||||
function modelAnimationController(controller) {
|
||||
const { type, initVal, maxVal, fn, step, minVal, primitive } = controller
|
||||
@ -648,3 +832,25 @@ function modelAnimationController(controller) {
|
||||
}
|
||||
render()
|
||||
}
|
||||
|
||||
function removeAllEntity() {
|
||||
boosterMap.values().forEach(i => {
|
||||
viewer.entities.remove(i)
|
||||
})
|
||||
boosterMap.clear()
|
||||
|
||||
interceptMap.values().forEach(i => {
|
||||
viewer.entities.remove(i)
|
||||
})
|
||||
interceptMap.clear()
|
||||
|
||||
pathLine.values().forEach(i => {
|
||||
viewer.entities.remove(i)
|
||||
})
|
||||
pathLine.clear()
|
||||
|
||||
ddMap.values().forEach(i => {
|
||||
viewer.scene.primitives.remove(i.primitive)
|
||||
})
|
||||
ddMap.clear()
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user