Cesium中文网:http://cesiumcn.org/ | 国内快速访问:http://cesium.coinidea.com/

要了解粒子系统的基础知识,请参见粒子系统入门教程。

Weather 天气

Setup 设置

若要生成雪效果,请首先为每个粒子添加雪花图像,然后在updateParticle函数中定义粒子的移动行为和其他动态元素。

The images 图像

本教程中使用了以下三个图像。左边是雨粒子;中间的图像是雪粒子;右边的图像用于火效果。

The update function 更新函数

更新函数用于定义粒子的移动、排列和可视化。修改粒子的color颜色、imageSize图像大小和particleLife粒子生命周期。我们甚至可以基于到相机距离定义粒子(如下所述)、导入模型或到地球本身的距离来修改它们。

下面是我们针对雪的更新函数:

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

函数的第一部分使粒子像重力一样下落。更新函数还包含一个距离检查,以便粒子在远离相机时消失。

额外的天气效应

使用雾和大气效果来增强可视化效果,并匹配我们试图复制的天气类型。

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 系统

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 彗星和火箭尾部

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

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

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

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 相对位置

使用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 资源

额外的帮助请访问Sandcastle example for both tails examples

更多示例代码:

Cesium中文网交流QQ群:807482793

Cesium中文网:http://cesiumcn.org/ | 国内快速访问:http://cesium.coinidea.com/

Cesium中级教程9 - Advanced Particle System Effects 高级粒子系统效应的更多相关文章

  1. Cesium中级教程8 - Introduction to Particle Systems 粒子系统入门

    Cesium中文网:http://cesiumcn.org/ | 国内快速访问:http://cesium.coinidea.com/ What is a particle system? 什么是粒子 ...

  2. Cesium中级教程10 - CesiumJS and webpack

    Cesium中文网:http://cesiumcn.org/ | 国内快速访问:http://cesium.coinidea.com/ webpack是打包JavaScript模块流行且强大的工具.它 ...

  3. Cesium中级教程4 - 空间数据可视化(二)

    Cesium中文网:http://cesiumcn.org/ | 国内快速访问:http://cesium.coinidea.com/ Viewer中的Entity功能 让我们看看Viewer为操作e ...

  4. Cesium中级教程6 - 3D Models 三维模型

    3D Models 三维模型 本教程将教您如何通过Primitive API转换.加载和使用Cesium中的三维模型.如果你是Cesium的新用户,可能需要阅读三维模型部分的(空间数据可视化教程)[h ...

  5. Cesium中级教程7 - Geometry and Appearances 几何图形和外观

    Cesium中文网:http://cesiumcn.org/ | 国内快速访问:http://cesium.coinidea.com/ 本教程将向您介绍提供使用Primitive API的几何图形和外 ...

  6. Cesium中级教程5 - Terrain 地形

    Cesium中文网:http://cesiumcn.org/ | 国内快速访问:http://cesium.coinidea.com/ CesiumJS支持对与水流相关的海洋.湖泊和河流以及全球高分辨 ...

  7. Cesium中级教程2 - 图层

    Cesium中文网:http://cesiumcn.org/ | 国内快速访问:http://cesium.coinidea.com/ Cesium支持从几个标准服务绘制和添加高分辨率图像(地图)图层 ...

  8. Cesium中级教程1 - 空间数据可视化(一)

    Cesium中文网:http://cesiumcn.org/ | 国内快速访问:http://cesium.coinidea.com/ 本教程将教读者如何使用Cesium的实体(Entity)API绘 ...

  9. Cesium中级教程3 - Camera - 相机(摄像机)

    Cesium中文网:http://cesiumcn.org/ | 国内快速访问:http://cesium.coinidea.com/ Camera CesiumJS中的Camera控制场景的视图.有 ...

随机推荐

  1. java 数据类型:集合接口Collection之List~ArrayList:remove移除;replaceAll改变原有值;sort排序;迭代器listIterator();

    什么是List集合: 特点: 元素有序可重复的集合. 集合中每个元素都有其对应的顺序索引. List集合默认按元素的添加顺序设置元素的索引,索引从0开始.   List接口的常用方法: List可以使 ...

  2. MySQLs数据库建外键时自动跑到缩影处,真奇怪

    MySQLs数据库建外键时自动跑到缩影处,真奇怪MyISAM引擎不支持外键:InnoDB存储引擎支持外键.如何解决的,把表修改成innodb类型吧用的工具是SQLyog Ultimate如图所示:

  3. JAVA判断指定url地址是否匹配指定url集合中的任意一个

    判断字符串为空和判断集合是否为空用到依赖,也可以改成自己的方式 <!-- Spring Web --> <dependency> <groupId>org.spri ...

  4. Linux(centos)安装es(elasticsearch)

    前提条件--需要安装jdk环境,不同版本的es所对应的jdk版本要求不同,es6的使用jdk1.8可以 1.下载elasticsearch压缩包 下载地址:https://www.elastic.co ...

  5. JAVA发送POST请求携带JSON格式字符串参数

    import org.apache.commons.lang.StringUtils; import org.apache.http.HttpEntity; import org.apache.htt ...

  6. 海康威视Java SDK拉流(一)初始化SDK

    19年的时候做了一个视频分析的产品,用户使用的安防摄像机基本的都是海康大华宇视,今天写一下关于Java调用海康威视摄像机的demo,当时也踩了很多坑.写个博客记录一下 测试环境: 系统:Centos ...

  7. 【LeetCode】633. Sum of Square Numbers 解题报告(python & Java & C++)

    作者: 负雪明烛 id: fuxuemingzhu 个人博客: http://fuxuemingzhu.cn/ 目录 题目描述 题目大意 解题方法 双指针 列表生成式 循环 日期 题目地址:https ...

  8. python极简教程01:基础变量

    测试奇谭,BUG不见. 其实很久之前,就有身边的同事或者网友让我分享一些关于python编程语言的教程,他们同大多数自学编程语言的人一样,无外乎遇到以下这些问题: 网络上的资料过多且良莠不全,不知道如 ...

  9. [opencv]GeneralProcessing_Template_Function

    // // Created by leoxae on 2019-05-08. // #ifndef OPENCVDEMO_UTILS_H #define OPENCVDEMO_UTILS_H #inc ...

  10. MySQL高级查询与编程笔记 • 【第2章 数据定义和操作】

    全部章节   >>>> 本章目录 2.1 数据定义语言和数据操作语言 2.1.1 设计"优乐网"数据库 2.1.2 数据定义语言 2.1.3 数据操作语言 ...