Cesium intermediate tutorial 9 - Advanced Particle System Effects Advanced particle system effects

Cesium Chinese network: http://cesiumcn.org/ | domestic fast access: http://cesium.coinidea.com/

To understand the basics of particle systems, see the Particle System Getting Started tutorial.

Weather Weather

13720662-cbae9657edec6aec.png
image.png
13720662-e79582f905fd5282.png
image.png

Setup settings

To generate snow effect, first add snowflakes image for each particle, then updateParticle defined movement behavior of particles and other dynamic elements function.

The images image

The following three are used in the tutorial images. The left is the rain of particles; in the middle of snow particle image; image to the right for the fire effect.

13720662-ebb5c5084f3916ad.png
image.png

The update function update function

The update function is used to define movement of the particles, and the arrangement visualization. Modify the particle color color, imageSize image size and particleLife particle lifecycle. We may even be defined based on distances from the camera to the particle (as described below), or introduced into the model from the Earth itself to modify them.

Here's our update function for snow:

// snow
var snowGravityVector = new Cesium.Cartesian3();
var snowUpdate = function(particle, dt) {
    Cesium.Cartesian3.normalize(particle.position, snowGravityVector);
    Cesium.Cartesian3.multiplyByScalar(snowGravityVector,
                                                            Cesium.Math.randomBetween(-30.0, -300.0),
                                                            snowGravityVector);
    particle.velocity = Cesium.Cartesian3.add(particle.velocity, snowGravityVector, particle.velocity);

    var distance = Cesium.Cartesian3.distance(scene.camera.position, particle.position);
    if (distance > (snowRadius)) {
        particle.endColor.alpha = 0.0;
    } else {
        particle.endColor.alpha = snowSystem.endColor.alpha / (distance / snowRadius + 0.1);
    }
};

A first portion of the particles as a function of the same gravity fall. Update function also includes a distance check for particles disappear when away from the camera.

13720662-b67d44ec052501c5.png
image.png

Additional weather effects

Use fog and atmospheric effects to enhance the visual effect, we are trying to copy and match type of weather.

hueshift沿着颜色光谱改变颜色,saturationShift改变了视觉实际需要的颜色与黑白的对比程度,brightnessShift改变了颜色的生动程度。

雾密度改变了地球上覆盖物与雾的颜色之间的不透明程度。雾的minimumBrightness用来使雾变暗。

// snow
scene.skyAtmosphere.hueShift = -0.8;
scene.skyAtmosphere.saturationShift = -0.7;
scene.skyAtmosphere.brightnessShift = -0.33;

scene.fog.density = 0.001;
scene.fog.minimumBrightness = 0.8;

The systems 系统

13720662-f8feb31dcc807a3f.png
image.png

Snow 雪

雪花系统使用snowflake_particle图像,并使用minimumImageSizemaximumImageSize,在该范围内随机创建雪花。

var snowParticleSize = scene.drawingBufferWidth / 100.0;
var snowRadius = 100000.0;

var snowSystem = new Cesium.ParticleSystem({
    modelMatrix : new Cesium.Matrix4.fromTranslation(scene.camera.position),
    minimumSpeed : -1.0,
    maximumSpeed : 0.0,
    lifetime : 15.0,
    emitter : new Cesium.SphereEmitter(snowRadius),
    startScale : 0.5,
    endScale : 1.0,
    image : "../../SampleData/snowflake_particle.png",
    emissionRate : 7000.0,
    startColor : Cesium.Color.WHITE.withAlpha(0.0),
    endColor : Cesium.Color.WHITE.withAlpha(1.0),
    minimumImageSize : new Cartesian2(snowParticleSize, snowParticleSize),
    maximumImageSize : new Cartesian2(snowParticleSize * 2.0, snowParticleSize * 2.0),
    updateCallback : snowUpdate
});
scene.primitives.add(snowSystem);

Rain 雨

雨滴系统使用circular_particle.png用于雨滴。imageSize用于垂直拉伸图像,使雨水呈现细长的外观。

rainSystem = new Cesium.ParticleSystem({
    modelMatrix : new Cesium.Matrix4.fromTranslation(scene.camera.position),
    speed : -1.0,
    lifetime : 15.0,
    emitter : new Cesium.SphereEmitter(rainRadius),
    startScale : 1.0,
    endScale : 0.0,
    image : "../../SampleData/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 : new Cesium.Cartesian2(rainParticleSize, rainParticleSize * 2),
    updateCallback : rainUpdate
});
scene.primitives.add(rainSystem);

雨水更新函数略有不同,因为降雨比降雪快得多。

// rain
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);

要使环境与场景的气氛匹配,请修改大气和雾以匹配雨水。下面的代码使一个深蓝色的天空被薄雾覆盖。

// rain
scene.skyAtmosphere.hueShift = -0.97;
scene.skyAtmosphere.saturationShift = 0.25;
scene.skyAtmosphere.brightnessShift = -0.4;

scene.fog.density = 0.00025;
scene.fog.minimumBrightness = 0.01;

获取额外的帮助,请访问Sandcastle example for both snow and rain

Comet and rocket tails 彗星和火箭尾部

13720662-72e46ce84c55a7af.png
image.png
13720662-53455b2ed9e510b7.png
image.png

Using multiple particle systems 使用多重粒子系统

要创建彗星和火箭尾部,我们需要多个粒子系统。该示例创建的粒子环上的每个位置都是完全独立的粒子系统。这使我们能够更均匀地控制系统的运动方向。可视化此效果的一个简单方法是将cometOptions.numberOfSystems限制为2,且cometOptions.colorOptions仅包括两种颜色,如下图所示。

13720662-32e738e2fcd3f826.png
image.png

为了简化不同的系统集合,创建数组来携带与彗星相关联的独立系统和与火箭例子相关联的独立系统。

var rocketSystems = [];
var cometSystems = [];

为对象创建两个不同的选项:一个用于彗星Comet版本,另一个用于火箭Rocket版本。这使得两个系统的初始系统数、偏移值等不同,看起来也不同。

var cometOptions = {
    numberOfSystems : 100.0,
    iterationOffset : 0.003,
    cartographicStep : 0.0000001,
    baseRadius : 0.0005,

    colorOptions : [{
        red : 0.6,
        green : 0.6,
        blue : 0.6,
        alpha : 1.0
    }, {
        red : 0.6,
        green : 0.6,
        blue : 0.9,
        alpha : 0.9
    }, {
        red : 0.5,
        green : 0.5,
        blue : 0.7,
        alpha : 0.5
    }]
};

var rocketOptions = {
    numberOfSystems : 50.0,
    iterationOffset :  0.1,
    cartographicStep : 0.000001,
    baseRadius : 0.0005,

    colorOptions : [{
        minimumRed : 1.0,
        green : 0.5,
        minimumBlue : 0.05,
        alpha : 1.0
    }, {
        red : 0.9,
        minimumGreen : 0.6,
        minimumBlue : 0.01,
        alpha : 1.0
    }, {
        red : 0.8,
        green : 0.05,
        minimumBlue : 0.09,
        alpha : 1.0
    }, {
        minimumRed : 1,
        minimumGreen : 0.05,
        blue : 0.09,
        alpha : 1.0
    }]
};

colorOptions是用于随机视觉的颜色数组。每个系统从一个特定的颜色开始,而不是有一组颜色几何,这取决于当前正在创建的系统。在下面的示例中,i表示当前迭代轮数。

var color = Cesium.Color.fromRandom(options.colorOptions[i % options.colorOptions.length]);

Setup 设置

使用下面的函数作为每个系统的初始化

function createParticleSystems(options, systemsArray) {
    var length = options.numberOfSystems;
    for (var i = 0; i < length; ++i) {
        scratchAngleForOffset = Math.PI * 2.0 * i / options.numberOfSystems;
        scratchOffset.x += options.baseRadius * Math.cos(scratchAngleForOffset);
        scratchOffset.y += options.baseRadius * Math.sin(scratchAngleForOffset);

        var emitterModelMatrix = Cesium.Matrix4.fromTranslation(scratchOffset, matrix4Scratch);
        var color = Cesium.Color.fromRandom(options.colorOptions[i % options.colorOptions.length]);
        var force = forceFunction(options, i);

        var item = viewer.scene.primitives.add(new Cesium.ParticleSystem({
            image : getImage(),
            startColor : color,
            endColor : color.withAlpha(0.0),
            particleLife : 3.5,
            speed : 0.00005,
            imageSize : new Cesium.Cartesian2(15.0, 15.0),
            emissionRate : 30.0,
            emitter : new Cesium.CircleEmitter(0.1),
            bursts : [ ],
            lifetime : 0.1,
            forces : force,
            modelMatrix : particlesModelMatrix,
            emitterModelMatrix : emitterModelMatrix
        }));
        systemsArray.push(item);
    }
}

由于两个尾部版本都相似,因此可以使用相同的createParticleSystems函数来创建其中一个。传入CometOptionsRocketOptions选项参数以创建不同的效果。

Create the particle image from scratch 从头开始创建粒子图像

不是从URL加载图像,getImage函数是使用HTML画布创建图像。这使得图像创建更加灵活。

var particleCanvas;
function getImage() {
    if (!Cesium.defined(particleCanvas)) {
        particleCanvas = document.createElement('canvas');
        particleCanvas.width = 20;
        particleCanvas.height = 20;
        var context2D = particleCanvas.getContext('2d');
        context2D.beginPath();
        context2D.arc(8, 8, 8, 0, Cesium.Math.TWO_PI, true);
        context2D.closePath();
        context2D.fillStyle = 'rgb(255, 255, 255)';
        context2D.fill();
    }
    return particleCanvas;
}

The force function 强制函数

下面使我们的updateCallback函数:

var scratchCartesian3 = new Cesium.Cartesian3();
var scratchCartographic = new Cesium.Cartographic();
var forceFunction = function(options, iteration) {
    var iterationOffset = iteration;
    var func = function(particle) {
        scratchCartesian3 = Cesium.Cartesian3.normalize(particle.position, new Cesium.Cartesian3());
        scratchCartesian3 = Cesium.Cartesian3.multiplyByScalar(scratchCartesian3, -1.0, scratchCartesian3);

        particle.position = Cesium.Cartesian3.add(particle.position, scratchCartesian3, particle.position);

        scratchCartographic = Cesium.Cartographic.fromCartesian(particle.position,
                                                                Cesium.Ellipsoid.WGS84,
                                                                scratchCartographic);

        var angle = Cesium.Math.PI * 2.0 * iterationOffset / options.numberOfSystems;
        iterationOffset += options.iterationOffset;
        scratchCartographic.longitude += Math.cos(angle) * options.cartographicStep;
        scratchCartographic.latitude += Math.sin(angle) * options.cartographicStep;

        particle.position = Cesium.Cartographic.toCartesian(scratchCartographic);
    };
    return func;
};

注意forceFunction正在返回函数。返回的func是实际的updateCallback函数。对于每次迭代,update函数根据angleiterationOffset创建不同的旋转偏移量。较小的迭代偏移只会稍微调整角度,允许半径随着系统的继续稳步增大,如彗星示例所示。较大的迭代偏移将更快地改变角度;这将使更紧密、更不稳定的圆柱形输出,如火箭例子中所示。

本教程使用正弦和余弦函数进行循环效果。对于其他的效果,试着做一些形状,比如Lissajous curveGibbs phenomenon,或者square wave

Relative position 相对位置

13720662-9dbcfbc4bc95d3dc.png
image.png

使用modelMatrix将粒子系统定位在平面后面的适当位置。因为这些系统是垂直的,所以我们需要使用particleOffset值进行轻微的偏移。如createParticleSystems函数所示,根据迭代,计算每个系统的emitterModelMatrix偏移量。

// positioning the plane
var planePosition = Cesium.Cartesian3.fromDegrees(-75.59777, 40.03883, 800.0);
var particlesOffset = new Cesium.Cartesian3(-8.950115473940969, 34.852766731753945, -30.235411095432937);

// creating the particles model matrix
var transl = Cesium.Matrix4.fromTranslation(particlesOffset, new Cesium.Matrix4());
var translPosition = Cesium.Matrix4.fromTranslation(planePosition, new Cesium.Matrix4());
var particlesModelMatrix = Cesium.Matrix4.multiplyTransformation(translPosition, transl, new Cesium.Matrix4());

Resources 资源

Extra help, visit the Sandcastle example for both tails examples
More sample code:

This article from the admin creation, using the Creative Commons Attribution 3.0 China Mainland License Agreement for licensing.
It can be freely reproduced, quoted with named authors and indicate the source of the article.

Cesium Chinese net exchange QQ group: 807 482 793

Cesium Chinese network: http://cesiumcn.org/ | domestic fast access: http://cesium.coinidea.com/

Reproduced in: https: //www.jianshu.com/p/edaac647caf3

Guess you like

Origin blog.csdn.net/weixin_34050427/article/details/91161486