cesium加载gltf模型运动-entity和primitive两种方式实现位移飞行

entity和primitive的相同代码

模型运动离不了两个点,时间和当前时间对应的位置,也就是要设置一个差值集合 

const position = new Cesium.SampledPositionProperty()

这个api 是用于存储类似可以这样理解存储时间对应位置的集合

[   { time:2025.15.02.04,position:{xyz}},

    { time:2025.15.02.05,position:{xyz}}

]

Cesium.Cartesian3.lerp(startPosition,endPosition, locationFactor,  new Cesium.Cartesian3())

1,起始位置2,结束位置3,计算差值比率,4,返回的格式

这个api是计算两点中间的一个差值点,类似这样的

设置飞行的开始的、结束的,以及需要的总时间
 const start = Cesium.JulianDate.fromDate(new Date())
  const totalSeconds = 10
  const stop = Cesium.JulianDate.addSeconds(
    start,
    totalSeconds,
    new Cesium.JulianDate()
  ) //这个api类似一个求加   起始时间一直是最新的间隔一直是10s 结束时间一直是当下时间的后10s


//关于cesium的cesium的一些配置 类似绑定时间
 viewer.clock.startTime = start.clone() // 开始时间
  viewer.clock.stopTime = stop.clone()
  viewer.clock.currentTime = start.clone() //将当前时间设置为开始时间
  viewer.clock.clockRange = Cesium.ClockRange.LOOP_STOP
  viewer.clock.shouldAnimate = true // 开始动画  为false时,根据设定的时间
  viewer.timeline.zoomTo(start, stop)
  viewer.timeline.container.style.display = 'none' //隐藏时间线
定义起始位置和结束位置
 const startPosition = new Cesium.Cartesian3(
    -2379556.799372864,
    -4665528.205030263,
    3628013.106599678
  )
  const endPosition = new Cesium.Cartesian3(
    -2379603.7074103747,
    -4665623.48990283,
    3627860.82704567
  )
效果优化

这里要有个计算方法,这个计算是为了效果,位移一开始的速度为0实现一个加速度的过程

100等分的目的是为了求0-1直接的数

const numberOfSamples = 100    
for (let i = 0; i <= numberOfSamples; ++i) {
    const factor = i / numberOfSamples
    const time = Cesium.JulianDate.addSeconds(
      start,
      factor * totalSeconds,
      new Cesium.JulianDate()
    )
 //这里也是一个累加的函数,输入一个时间,加上一个factor * totalSeconds,计算时间,返回一个新时间
    // time=0.1时
    const locationFactor = Math.pow(factor, 2) 
    //0.0001
    const location = Cesium.Cartesian3.lerp(
      startPosition,
      endPosition,
      locationFactor, //t
      new Cesium.Cartesian3()
    ) //计算差值,返回介于两个点之间的位置。第三个是差值的倍率
    // Lerp(S,E,t)=S+t∗(E−S)
    // 计算结果
    //location = new Cesium.Cartesian3(
    //   -2379556.804063668,  // x
    //   -4665528.21455875,   // y
    //   3628013.091371722    // z
    // );
    position.addSample(time, location) //添加样本
  }

entity加载

 const vehicleEntity = await viewer.entities.add({
    position: position,
    orientation: new Cesium.VelocityOrientationProperty(position),
    model: {
      uri: '/knowledge/model/modelNew.gltf',
      runAnimations: false, //是否开启模型的自带动画。
      scale: 0.1,
      maximumScale: 20,
    },
  })
  console.log(vehicleEntity, 'vehicleEntity')
  viewer.trackedEntity = vehicleEntity
  vehicleEntity.viewFrom = new Cesium.Cartesian3(-10.0, 7.0, 4.0)

补充下,这里官网加载gltf的方式是Cesium.Model.fromGltfAsync()是用primitives添加的,这里用entity的话用的model添加,Cesium.Model.fromGltfAsync()用在entity上不报错也不显示模型。

这个方式加载的无法获取模型节点,但是容易获取模型动画。模型的动画会在''出厂''的时候设置,你要是找不到就找建模师添加,存在一个集合里调api获取,model.activeAnimations 获取集合。

稍微多说两嘴 orientation: new Cesium.VelocityOrientationProperty(position),

这里是会自己计算位置朝向

这是我定义的行进路线,如果是空间的路线不设置自动计算朝向的话,会机身水平但是整体斜向上飞。

entity的完整代码

export async function flyModel() {
  const start = Cesium.JulianDate.fromDate(new Date())
  const totalSeconds = 10
  const stop = Cesium.JulianDate.addSeconds(
    start,
    totalSeconds,
    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.shouldAnimate = true // 开始动画  为false时,根据设定的时间
  viewer.timeline.zoomTo(start, stop)
  viewer.timeline.container.style.display = 'none'
  const position = new Cesium.SampledPositionProperty() //差值集合

  const startPosition = new Cesium.Cartesian3(
    -2379556.799372864,
    -4665528.205030263,
    3628013.106599678
  )
  const endPosition = new Cesium.Cartesian3(
    -2379603.7074103747,
    -4665623.48990283,
    3627860.82704567
  )

  const numberOfSamples = 100

  for (let i = 0; i <= numberOfSamples; ++i) {
    const factor = i / numberOfSamples
    const time = Cesium.JulianDate.addSeconds(
      start,
      factor * totalSeconds,
      new Cesium.JulianDate()
    )
    // time=0.1时
    const locationFactor = Math.pow(factor, 2)
    //0.0001
    const location = Cesium.Cartesian3.lerp(
      startPosition,
      endPosition,
      locationFactor,
      new Cesium.Cartesian3()
    ) //计算差值,返回介于两个点之间的位置。
    // Lerp(A,B,t)=A+t∗(B−A)
    // 计算结果
    //location = new Cesium.Cartesian3(
    //   -2379556.804063668,  // x
    //   -4665528.21455875,   // y
    //   3628013.091371722    // z
    // );
    position.addSample(time, location) //添加样本
  }

  const vehicleEntity = await viewer.entities.add({
    position: position,
    orientation: new Cesium.VelocityOrientationProperty(position),
    model: {
      uri: '/knowledge/model/modelNew.gltf',
      runAnimations: false, //是否开启模型的自带动画。
      scale: 0.1,
      maximumScale: 20,
    },
  })
  console.log(vehicleEntity, 'vehicleEntity')
  viewer.trackedEntity = vehicleEntity
  vehicleEntity.viewFrom = new Cesium.Cartesian3(-10.0, 7.0, 4.0)
}

primitive,添加方式设置时间都是一样的只不过在加载的时候设置不一样

const model = await Cesium.Model.fromGltfAsync({
    url: '/knowledge/model/modelNew.gltf',
    scale: 0.1,
  })

  viewer.scene.primitives.add(model)

关键设置

viewer.scene.preRender.addEventListener(function (scene, time) {
    debugger
    // 获取当前位置和方向
    const currentPosition = position.getValue(time)
    // 获取四元数
    const quat = orientation.getValue(time) // 获取四元数(wxyz)
    // 直接使用四元数创建模型矩阵
    const modelMatrix = Cesium.Matrix4.fromTranslationQuaternionRotationScale(
      currentPosition,
      quat,
      new Cesium.Cartesian3(1.0, 1.0, 1.0) 
    )

    // 更新模型的矩阵
    model.modelMatrix = modelMatrix
  })

补充; const orientation = new Cesium.VelocityOrientationProperty(position)这里和上面一样也创建一个方向样本,也是防止飞机屁股当头飞

完整代码

export async function flyModel() {
  const start = Cesium.JulianDate.fromDate(new Date())
  const totalSeconds = 10
  const stop = Cesium.JulianDate.addSeconds(
    start,
    totalSeconds,
    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.shouldAnimate = true // 开始动画  为false时,根据设定的时间
  viewer.timeline.zoomTo(start, stop)
  viewer.timeline.container.style.display = 'none'

  const position = new Cesium.SampledPositionProperty() //差值集合
  const startPosition = new Cesium.Cartesian3(
    -2379556.799372864,
    -4665528.205030263,
    3628013.106599678
  )
  const endPosition = new Cesium.Cartesian3(
    -2379603.7074103747,
    -4665623.48990283,
    3627860.82704567
  )

  const numberOfSamples = 100

  for (let i = 0; i <= numberOfSamples; ++i) {
    const factor = i / numberOfSamples
    const time = Cesium.JulianDate.addSeconds(
      start,
      factor * totalSeconds,
      new Cesium.JulianDate()
    )

    const locationFactor = Math.pow(factor, 2)
    const location = Cesium.Cartesian3.lerp(
      startPosition,
      endPosition,
      locationFactor,
      new Cesium.Cartesian3()
    )
    position.addSample(time, location) //添加样本
  }

  // 创建方向样本
  const orientation = new Cesium.VelocityOrientationProperty(position)
  const model = await Cesium.Model.fromGltfAsync({
    url: '/knowledge/model/modelNew.gltf',
    scale: 0.1, // 可选:缩放模型
  })

  viewer.scene.primitives.add(model)

  viewer.camera.setView({
    destination: new Cesium.Cartesian3(
      -2379556.799372864,
      -4665528.205030263,
      3628013.106599678
    ),
  })

  viewer.scene.preRender.addEventListener(function (scene, time) {
    debugger
    // 获取当前位置和方向
    const currentPosition = position.getValue(time)
    // 获取四元数
    const quat = orientation.getValue(time) // 获取四元数(wxyz)

    // 直接使用四元数创建模型矩阵
    const modelMatrix = Cesium.Matrix4.fromTranslationQuaternionRotationScale(
      currentPosition,
      quat,
      new Cesium.Cartesian3(1.0, 1.0, 1.0) // 缩放因子
    )

    // 更新模型的矩阵
    model.modelMatrix = modelMatrix
  })
}

补充下模型获取节点getNode()entity加载方式获取不到,有大神能获取可以在评论补充说明

 gltfModel.readyEvent.addEventListener(() => {
   
    // 获取关键节点
    node1 = gltfModel.getNode('Bomb01_MQ1CDroneMissilesGlassShader_0') // 导弹舱门控制节点
    node = gltfModel.getNode('Bomb02') // 导弹发射控制节点
    node2 = gltfModel.getNode('Undercarriage_MQ1CDroneShader_0') // 起落架控制节点
    node3 = gltfModel.getNode('Propeller_MQ1CDroneShader_0') // 螺旋桨控制节点

  })

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值