百科

burst out和burst into,burst the gravity

  

  在3D GIS系统中,我们经常会看到一些常见的特效,如雨、雪、雾、烟花、爆炸、喷泉等。这些都可以通过粒子系统来实现。今天,我将带领大家了解铯中的粒子系统。   

  

  1.什么是粒子系统?粒子系统是一种可以模拟复杂物理效果的图形技术。粒子系统是小图像的集合,也就是一堆非常小的图片。当它们聚集在一起观看时,会形成一个复杂的“模糊”物体,如火、烟、天气或烟火。这些复杂的效果实际上是通过控制每个粒子对象的初始位置、速度、生命周期等行为来完成的。可以说,粒子系统控制着每个粒子对象随时间的显示和变化。   

  

  2.粒子系统创建和参数描述的例子。首先,我们从一个简单的例子开始。实现代码如下:   

  

  //初始化并设置ParticleSystem的参数,因为这是一个动态粒子,因此,有start,end,min,max等参数设置const particle system=scene . primitives . add(new particle system({//image image of each particle 3360 '././sampledata/smoke.png ',//设置发射图像的大小,imagesize :New新铯。笛卡尔2(视图模型。粒子大小,视图模型。粒子大小),//开始颜色结束颜色,而不是颜色,使粒子的颜色在粒子的生命周期内平滑地混合在这两种颜色之间。Startcolor:cesium铯。颜色。光明绿色。含(0.7),endcolor3360cesium铯。颜色。白色。使用Alpha (0.0),//设置粒子贴图启动后的最小/最大速度(米/秒)。值越大,尾部浮动越高,最小速度: viewmodel。最小速度,最大速度3360视图模式。最大速度,//开始缩放结束缩放,而不是缩放,设置生命周期中显示的粒子的初始和结束大小。//也是动态混合的功能。该值越大,初始粒子大小越大。start scale : viewmodel . start scale,end scale : viewmodel . end scale,//particleLife:设置该值将覆盖minimumParticleLife和maximum particle life//minimum particle life:设置粒子寿命可能持续时间的最小限制(以秒为单位),粒子的实际寿命将由//machine生成。//maximumParticleLife:设置粒子生命可能持续时间的最大限制(秒)。粒子的实际寿命将由//机器生成。值越大,尾巴越长。MinimumArticleLife 3360视图模型。MinimumArticleLife,maximum article life : view model。MaximumParticleLife,//每秒发射的粒子数。值越大,发射率越密集: viewmodel.emission rate,//在粒子系统的生命周期中,一定数量的粒子会按照指定的周期爆炸。三参数(时间,最小值,最大值)爆发: //爆发粒子的密度是新的。粒子爆发({时间:5.0,最小值336010,最大值3360100,nbsp   

; }), new Cesium.ParticleBurst({ time: 10.0, minimum: 50, maximum: 100, }), new Cesium.ParticleBurst({ time: 15.0, minimum: 200, maximum: 300, }), >, //粒子系统会发射多久粒子,以秒为单位。默认为最大值 lifetime: 16.0, // 粒子系统的粒子发射器;包括四种发射器:圆形、锥体、球体、长方体 emitter: new Cesium.CircleEmitter(2.0), //modelMatrix: 4x4变换矩阵,将粒子系统从模型转换为世界坐标。 //4x4变换矩阵,用于在粒子系统内部坐标系中转换粒子系统发射器。 emitterModelMatrix: computeEmitterModelMatrix(), //一组强制回调。回调被传递一个粒子和上次的差值 //每帧都要调用的回调函数来更新粒子。此updateCallback作用是用来改变粒子系统在每一个时间步长的属 //性,可以强制改变粒子系统的颜色、大小等值。在updateCallback更改gravity重力参数,值越大,烟雾 //离模型越近的地方飘的越高,可能出现负值,此时烟雾会向下方飘。 updateCallback: applyGravity, }));上述通过实例化ParticleSystem,创建了一个卡车后部烟雾效果的粒子系统,实例化参数(如粒子发射速率,粒子生命周期,粒子颜色、大小、运行速度等)对象控制了单个粒子对象随时间变化的外观和行为。如果要想实现不同的粒子效果,还需要对上述参数进行调整。上述示例的结果如下图所示:

     

如果在运行过程中要更改粒子系统的属性, 则需要在ParticleSystem中调用UpdateCallback更新函数,粒子系统使用modelMatrix和emitterModelMatrix两个转换矩阵来定位。粒子系统中的每个粒子是如何生成的呢,这就靠下面要讲的粒子发射器了。

  

3.粒子发射器粒子发射器产生的粒子都有一个位置和类型,存活一段时间后然后消亡。粒子发射器则控制了粒子产生时的初始位置、速度和方向,并依据粒子发射频率(emissionRate)来决定每秒产生多少粒子,并通过发射器类型决定粒子的发射速度和方向。无论是哪种粒子发射器都继承了基类ParticleEmitter,Cesium内置了如下四种粒子发射器:
(1)BoxEmitter 盒形发射器
定义了个盒型,将粒子随机地放置在盒子里的随机一个位置,并且具有从盒子中心发出的初始速度,然后沿着盒子的6个面的法向量向外运动,通过传递Cartesian3类型的参数,来定了盒子的长宽高。

     

(2)CircleEmitter 圆形发射器
定义了一个圆形,在圆形面中的随意一个位置发射具有沿着z矢量的初始速度的粒子,可通过Number类型的参数控制圆的半径。Cesium默认的发射器为圆形发射器。

     

(3)ConeEmitter 锥形发射器
定义了一个的锥体,在锥体顶点产生粒子,并向锥体内随机一个方向运动,参数可控制圆锥体的角度。

     

(4)SphereEmitter 球形发射器
定义了一个球体,在球体内随机产生粒子,并沿着球心向外运动,可通过参数指定球体的半径。

     

4.粒子系统更新回调函数UpdateCallback回调函数充当了每个粒子的手动更新程序,它接受两个参数,一个是粒子本身,另一个是仿真时间步长。每个粒子系统在仿真过程中都会调用更新回调函数来修改粒子的属性,从而进一步自定义粒子系统。比如对于重力、风或颜色更改等效果的模拟,下面是一个粒子相应重力的示例代码:

  

const gravityScratch = new Cesium.Cartesian3(); function applyGravity(p, dt) { // 计算每个粒子的向上向量(相对地心) const position = p.position; Cesium.Cartesian3.normalize(position, gravityScratch); Cesium.Cartesian3.multiplyByScalar( gravityScratch, viewModel.gravity * dt, gravityScratch ); p.velocity = Cesium.Cartesian3.add( p.velocity, gravityScratch, p.velocity ); }该函数计算了一个重力方向,并使用重力加速度(-9.8米每秒平方)来改变粒子的速度,然后设置成粒子的更新回调函数。

  

5.粒子系统位置有了粒子系统的创建、相关参数的位置之后,我们要把显示的粒子效果具体放在什么位置进行展示呢,这就涉及到粒子系统的定位了。Cesium为我们提供了两个Matrix4变换矩阵来定位粒子系统以方便开发,当然你也可以设置一个,而把另一个设置为单位矩阵。
1)modelMatrix:模型矩阵,将粒子系统从模型转换为世界坐标;
2)emitterModelMatrix:粒子发射器模型矩阵,在粒子系统的局部坐标系内变换粒子发射器。
我们在创建粒子的时候,粒子发射器一般都会都会相对于某一个entity或primitive进行定位,用到的就是modelMatrix。如下示例给粒子系统创建了一个模型矩阵,将粒子定位在行驶中的卡车位置中心:

  

const entity = viewer.entities.add({ availability: new Cesium.TimeIntervalCollection(), model: { uri: "../../SampleData/models/CesiumMilkTruck/CesiumMilkTruck.glb", minimumPixelSize: 64, }, viewFrom: new Cesium.Cartesian3(-100.0, 0.0, 100.0), position: position, orientation: new Cesium.VelocityOrientationProperty(position), }); viewer.trackedEntity = entity; viewer.scene.preUpdate.addEventListener(function (scene, time) { particleSystem.modelMatrix = computeModelMatrix(entity, time); // Account for any changes to the emitter model matrix. particleSystem.emitterModelMatrix=computeEmitterModelMatrix(); }); function computeModelMatrix(entity, time) { return entity.computeModelMatrix(time, new Cesium .Matrix4()); }而为了使粒子系统定位在卡车的后面,我们需要创建一个在模型坐标系中的平移矩阵,也就是上述示例中的效果,模型矩阵的计算代码如下:

  

const emitterModelMatrix = new Cesium.Matrix4(); const translation = new Cesium.Cartesian3(); const rotation = new Cesium.Quaternion(); let hpr = new Cesium.HeadingPitchRoll(); const trs = new Cesium.TranslationRotationScale(); function computeEmitterModelMatrix() { hpr = Cesium.HeadingPitchRoll.fromDegrees(0.0, 0.0, 0.0, hpr); trs.translation = Cesium.Cartesian3.fromElements( -4.0, 0.0, 1.4, translation ); trs.rotation = Cesium.Quaternion.fromHeadingPitchRoll(hpr, rotation); return Cesium.Matrix4.fromTranslationRotationScale( trs, emitterModelMatrix ); }