Cesium之粒子---简单粒子特效

首先,来个最简单的粒子特效:
雨:

      var rainParticleSize = 15.0;
      var rainRadius = 100000.0;
      var rainImageSize = new Cesium.Cartesian2(rainParticleSize, rainParticleSize * 2.0);
      var rainGravityScratch = new Cesium.Cartesian3();
      var rainUpdate = function (particle, dt) {
        rainGravityScratch = Cesium.Cartesian3.normalize(particle.position, rainGravityScratch);
        rainGravityScratch = Cesium.Cartesian3.multiplyByScalar(rainGravityScratch, -1050.0, rainGravityScratch);
        particle.position = Cesium.Cartesian3.add(particle.position, rainGravityScratch, particle.position);
        var distance = Cesium.Cartesian3.distance(viewer.scene.camera.position, particle.position);
        if (distance > rainRadius) {
          particle.endColor.alpha = 0.0;
        } else {
          particle.endColor.alpha = rainSystem.endColor.alpha / (distance / rainRadius + 0.1);
        }
      };
      rainSystem = new Cesium.ParticleSystem({
        modelMatrix: new Cesium.Matrix4.fromTranslation(viewer.scene.camera.position),
        speed: -1.0,
        lifetime: 15.0,
        emitter: new Cesium.SphereEmitter(rainRadius),
        startScale: 1.0,
        endScale: 0.0,
        image: 'images/circular_particle.png',
        emissionRate: 9000.0,
        startColor: new Cesium.Color(0.27, 0.5, 0.70, 0.0),
        endColor: new Cesium.Color(0.27, 0.5, 0.70, 0.98),
        imageSize: rainImageSize,
        updateCallback: rainUpdate
      });
      viewer.scene.primitives.add(rainSystem);

以此,我们来分析粒子功能的一些方法和属性。
首先,我们需要创立一个粒子特效(针对于每一个粒子)。
下面,是创建粒子特效的第一步。

rainSystem = new Cesium.ParticleSystem({
        modelMatrix: new Cesium.Matrix4.fromTranslation(viewer.scene.camera.position),
        speed: -1.0,
        lifetime: 15.0,
        emitter: new Cesium.SphereEmitter(rainRadius),
        startScale: 1.0,
        endScale: 0.0,
        image: 'images/circular_particle.png',
        emissionRate: 9000.0,
        startColor: new Cesium.Color(0.27, 0.5, 0.70, 0.0),
        endColor: new Cesium.Color(0.27, 0.5, 0.70, 0.98),
        imageSize: rainImageSize,
        updateCallback: rainUpdate
      });

ParticleSystem这个函数是专门的粒子功能类。
startScale:代表了粒子初始化的密集程度;
endScale:代表了粒子消失的密集程度;
Scale:它的优先级高于startScale和endScale,当它存在时,startScale和endScale都失效了。它是一个恒定值。
startColor:代表粒子刚出现时,粒子显示的颜色效果;
endColor:代表粒子结束时,粒子显示的颜色效果;
Color:它的优先级高于startColor和endColor,当它存在时,startColor和endColor都失效了。它是一个恒定值。
image:代表粒子图片的路径存放位置。Cesium中我知道的有两种粒子特效展示,一种是这个用png图片展示粒子特效,一种是用着色器来展示粒子特效。
minimumImageSize:代表粒子图片的最小值;
maximumImageSize:代表粒子图片的最大值;
imageSize:它的优先级高于minimumImageSize和maximumImageSize,当它存在时,minimumImageSize和maximumImageSize都失效了。它是一个恒定值。另外,当minimumImageSize和
maximumImageSize配合使用的时候,粒子图片的大小是在最小值和最大值之间随机选择的。
minimumSpeed:代表粒子速度的最小值;
maximumSpeed:代表粒子速度的最大值;
speed:它的优先级高于minimumSpeed和maximumSpeed,当它存在时,minimumSpeed和maximumSpeed都失效了。它是一个恒定值。并且它也有系统默认的值1.0。
minimumParticleLife:粒子持续时间的最小值;
maximumParticleLife:粒子持续时间的最大值;
particleLife:它的优先级高于minimumParticleLife和maximumParticleLife,当它存在时,minimumParticleLife和maximumParticleLife都失效了。它是一个恒定值。并且它也有系统默认的值5.0。
lifetime:代表粒子发射时间。
minimumMass:代表粒子的最小质量;
maximumMass:代表粒子的最大质量;
mass:它的优先级高于minimumMass和maximumMass,当它存在时,minimumMass和maximumMass都失效了。它是一个恒定值。并且它也有系统默认的值1.0。
sizeInMeters:代表粒子的大小的像素还是米。true:以米为单位调整粒子大小;否则,大小以像素为单位。
bursts:这个是设定某一个时间点具有爆炸效果;比如说做爆炸特效或者烟花特效等;
使用方法:

bursts : [
    new Cesium.ParticleBurst({time : 5.0, minimum : 300, maximum : 500}),
    new Cesium.ParticleBurst({time : 10.0, minimum : 50, maximum : 100}),
    new Cesium.ParticleBurst({time : 15.0, minimum : 200, maximum : 300})
],

emissionRate:代表每秒发射的粒子个数,它有一个默认值5.
emitter:代表粒子发射的形状,总共有四个:BoxEmitter、CircleEmitter、ConeEmitter、SphereEmitter。
使用方法:

BoxEmitter 类在盒子里(box)里随机一个位置,沿着盒子的6个面的法向量向外运动。它接受一个Cartesian3 参数,定义了盒子的长宽高。
emitter: new Cesium.BoxEmitter(new Cesium.Cartesian3(10.0, 10.0, 10.0));
CircleEmitter类在圆形面上随机一个位置,粒子方向是发射器的向上向量。它接受一个float参数指定了圆的半径。
emitter: new Cesium.CircleEmitter(5.0);
ConeEmitter在椎体顶点产生粒子,粒子方向在椎体内随机一个角度向外。它接受一个float参数,制定了锥角。椎的方向沿着向上轴。
emitter: new Cesium.ConeEmitter(Cesium.Math.toRadians(30.0));
SphereEmitter类在球体内随机产生粒子,初始速度是沿着秋心向外。它接受一个float参数指定了球体半径。
emitter: new Cesium.SphereEmitter(5.0);

updateCallback:为了提升仿真效果,粒子系统有一个更新函数。这个是个手动更新器,比如对每个粒子模拟重力或者风力的影响,或者除了线性插值之外的颜色插值方式等等。说白了,这个就是模拟粒子在真实场景下的运动。使粒子具有更加真实的显示效果。
每个粒子系统在仿真过程种,都会调用更新回调函数来修改粒子的属性。回调函数传过两个参数,一个是粒子本身,另一个是仿真时间步长。大部分物理效果都会修改速率向量来改变方向或者速度。下面是一个粒子响应重力的示例代码:

var gravityScratch = new Cesium.Cartesian3();
function applyGravity(p, dt) {
    // 计算每个粒子的向上向量(相对地心) 
    var 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);
}

modelMatrix:把粒子系统从模型坐标系转到世界坐标系。也可以这样说,就相当于把粒子当做一个模型,对它进行任意的旋转变换。
对于复杂的粒子变换,有一个参考代码:

function computeModelMatrix(entity, time) {
    var position = Cesium.Property.getValueOrUndefined(entity.position, time, new Cesium.Cartesian3());
    if (!Cesium.defined(position)) {
        return undefined;
    }
    var orientation = Cesium.Property.getValueOrUndefined(entity.orientation, time, new Cesium.Quaternion());
    if (!Cesium.defined(orientation)) {
        var modelMatrix = Cesium.Transforms.eastNorthUpToFixedFrame(position, undefined, new Cesium.Matrix4());
    } else {
        modelMatrix = Cesium.Matrix4.fromRotationTranslation(Cesium.Matrix3.fromQuaternion(orientation, new Cesium.Matrix3()), position, new Cesium.Matrix4());
    }
    return modelMatrix;
 }

emitterModelMatrix:在粒子系统的局部坐标系内变换粒子发射器。说白了,就是在粒子进行modelMatrix位置转换之后,然后开始在该位置进行粒子的发射。
这里也有一个参考代码:

function computeEmitterModelMatrix() {
    hpr = Cesium.HeadingPitchRoll.fromDegrees(0.0, 0.0, 0.0, new Cesium.HeadingPitchRoll());
    var trs = new Cesium.TranslationRotationScale();
    trs.translation = Cesium.Cartesian3.fromElements(2.5, 4.0, 1.0, new Cesium.Cartesian3());
    trs.rotation = Cesium.Quaternion.fromHeadingPitchRoll(hpr, new Cesium.Quaternion());
    return Cesium.Matrix4.fromTranslationRotationScale(trs, new Cesium.Matrix4());
}

另外,我需要说的是,如果需要展示粒子特效,Cesium的shouldAnimate必须为true。
第二步,就是把该粒子加入到场景中:

viewer.scene.primitives.add(rainSystem);
  • 2
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值