作者:kele
前言
在三维场景中,粒子特效(ParticleSystem)能够真实有效地反应自然灾害,如火焰、烟雾、洪水等;在天气系统中,粒子特效也有很好的应用,如降雨、降雪。但在实际生活中,火焰、烟雾、降雨都会受到自然风的影响,风向会影响火势的走向,风力会影响火焰的蔓延速度。在三维场景中,为粒子特效加上这些受力因子,将能够更加准确地表达这些真实地理信息。
一、数据准备
制作粒子特效,需要准备对应粒子的图片,我们以火焰、烟雾特效为例,如图下所示。
二、关键接口
粒子的基础参数设置可以参考官网示例
三、实现代码
1.以火焰特效为例,生成火焰粒子
var viewModelfire= {
emissionRate: 40.0, //粒子数量
gravity: 1.0, //重力
minimumParticleLife: 2,//最小生命周期
maximumParticleLife: 3,//最大生命周期
minimumSpeed: 3.0, //最小速度
maximumSpeed: 5.0, //最大速度
startScale: 5.0, //初始比例
endScale: 6, //终止比例
particleSize: 2, //粒子大小
};
function fire(){
var pos1 = Cesium.Cartesian3.fromDegrees(116.45435918469913,39.90935742145429,146.16445509515142);
var entity = viewer.entities.add({
position: pos1,
});//火焰位置
var particleSystem1 = scene.primitives.add(new Cesium.ParticleSystem({
image : './images/爆炸起火.png',
startColor: new Cesium.Color(1, 1, 1, 1),
endColor: new Cesium.Color(0.5, 0, 0, 0),
startScale: viewModelfire.startScale,
endScale: viewModelfire.endScale,
minimumParticleLife: viewModelfire.minimumParticleLife,
maximumParticleLife: viewModelfire.maximumParticleLife,
minimumSpeed: viewModelfire.minimumSpeed,
maximumSpeed: viewModelfire.maximumSpeed,
imageSize: new Cesium.Cartesian2(viewModelfire.particleSize, viewModelfire.particleSize),
emissionRate: viewModelfire.emissionRate,
lifetime: 6.0,//生命周期
loop: true,//循环是否开启
emitter: new Cesium.ConeEmitter(Cesium.Math.toRadians(45.0)),
sizeInMeters: true,
}));
viewer.scene.preUpdate.addEventListener(function (scene, time) {
particleSystem1.modelMatrix = computeModelMatrix(entity, time);
particleSystem1.emitterModelMatrix = computeEmitterModelMatrix();
});
function computeModelMatrix(entity, time) {
return entity.computeModelMatrix(time, new Cesium.Matrix4());
}
var emitterModelMatrix = new Cesium.Matrix4();
var translation = new Cesium.Cartesian3();
var rotation = new Cesium.Quaternion();
var hpr = new Cesium.HeadingPitchRoll();
var trs = new Cesium.TranslationRotationScale();
//改变粒子系统的位置
function computeEmitterModelMatrix() {
hpr = Cesium.HeadingPitchRoll.fromDegrees(0,0,0, hpr);//旋转控制参数
trs.translation = Cesium.Cartesian3.fromElements(0,0, 0, translation);
trs.rotation = Cesium.Quaternion.fromHeadingPitchRoll(hpr, rotation);
return Cesium.Matrix4.fromTranslationRotationScale(trs, emitterModelMatrix);
}
}
火焰粒子效果如下图所示:
2.设置作用力因子
windSpeed: 10,//风力,对应每秒多少米
windType: "undf",
windDirection: [
//x为正:向西; x为负:向东; y为正:向南向上; y为负:向北向下; z为正:向比向上; z为负:向南向下
{type:"west",canshu:new Cesium.Cartesian3(1 , 0 , 0),x:1.0,y:0,z:0},
{type:"east",canshu:new Cesium.Cartesian3(-1 , 0 , 0),x:-1.0,y:0,z:0},
{type:"south",canshu:new Cesium.Cartesian3(0 , 1 , 0),x:0,y:1.0,z:0},
{type:"north",canshu:new Cesium.Cartesian3(0 , -1 , 0),x:0,y:-1.0,z:0},
{type:"undf",canshu:new Cesium.Cartesian3(0 , 0 , 0),x:0,y:0,z:0}
]
updateCallback : applyForce, //设置作用力
//重力的方向
var gravityScratch = new Cesium.Cartesian3();
//风向
//控制风向的方法???
//x为正:向西; x为负:向东; y为正:向南向上; y为负:向北向下; z为正:向比向上; z为负:向南向下
var windDirectionForFire = new Cesium.Cartesian3(1 , 0.5 , 0);//初始化风向
//风力 对应风级 每秒多少米
var windSpeed = 0;//风力
//风向和重力方向共同作用的结果
var endDirection=new Cesium.Cartesian3();
function applyForce(p, dt) {
var canshu_x,canshu_y,canshu_z;
var windType = viewModelfire.windType;
for(var i=0;i<viewModelfire.windDirection.length;i++){
if(viewModelfire.windDirection[i].type === windType){
windDirectionForFire = viewModelfire.windDirection[i].canshu;
canshu_x = viewModelfire.windDirection[i].x;
canshu_y = viewModelfire.windDirection[i].y;
canshu_z = viewModelfire.windDirection[i].z;
break
}
}
windDirectionForFire.x = canshu_x;
windDirectionForFire.y = canshu_y;
windDirectionForFire.z = canshu_z;
//计算地心空间中每个粒子的局部向上矢量
var position = p.position;
Cesium.Cartesian3.normalize(position, gravityScratch);
//判断windDirectionForFire是否为(0,0,0),以决定是否执行Cesium.Cartesian3.normalize(windDirection, windDirection);函数
if(!Cesium.Cartesian3.equalsEpsilon(windDirectionForFire,new Cesium.Cartesian3(0,0,0),0))
{
Cesium.Cartesian3.normalize(windDirectionForFire, windDirectionForFire);
}
Cesium.Cartesian3.multiplyByScalar(gravityScratch, viewModelfire.gravity * dt, gravityScratch);
Cesium.Cartesian3.multiplyByScalar(windDirectionForFire, viewModelfire.windSpeed * dt, windDirectionForFire);
endDirection = Cesium.Cartesian3.add(gravityScratch, windDirectionForFire, endDirection);
p.velocity = Cesium.Cartesian3.add(p.velocity, endDirection, p.velocity);
}
利用同样的方式,我们可以修改粒子基础参数再构造出一个烟雾粒子。
四、效果图
demo下载地址:https://pan.baidu.com/s/1MSMMSH42jUguBJogIddnrQ
提取码:9qok