Cesium粒子系统、火焰效果、喷泉效果
前言
Cesium中可以使用粒子系统来实现现实生活中的一些效果,比如喷泉、火焰等效果。
实现效果
实现思路
通过Cesium自带的粒子系统实现
关键代码
// 火焰粒子标绘类
import ParticlePlotBase from "../PlotBase"
import PlotTypes from "../PlotTypes"
export default class FirePlot extends ParticlePlotBase {
constructor(viewer, geoFeature) {
super(viewer, geoFeature);
this.properties.plotType = PlotTypes.FIRE;
this.properties.plotName = "火焰";
this.style = geoFeature.properties.style || this.getDefaultStyle();
this.properties.style = this.style;
this.init();
}
init() {
//需要一个entity提供位置信息
this.entity = this.viewer.entities.add({
position: this.position,
});
this.particleSystem = this.createParticleSystem();
this.viewer.scene.primitives.add(this.particleSystem);
this.addEvent();
}
//添加事件
addEvent() {
this.emitterModelMatrix = new Cesium.Matrix4();
this.translation = new Cesium.Cartesian3();
this.rotation = new Cesium.Quaternion();
this.hpr = new Cesium.HeadingPitchRoll();
this.trs = new Cesium.TranslationRotationScale();
this.viewer.scene.preUpdate.addEventListener(this.preUpdateEvent, this);
}
removeEvent() {
this.viewer.scene.preUpdate.removeEventListener(this.preUpdateEvent, this);
this.emitterModelMatrix = undefined;
this.translation = undefined;
this.rotation = undefined;
this.hpr = undefined;
this.trs = undefined;
}
//场景渲染事件
preUpdateEvent(scene, time) {
this.particleSystem.modelMatrix = this.entity.computeModelMatrix(time, new Cesium.Matrix4());
this.hpr = Cesium.HeadingPitchRoll.fromDegrees(0.0, 0.0, 0.0, this.hpr);
this.trs.translation = Cesium.Cartesian3.fromElements(0, 0, 0, this.translation);
this.trs.rotation = Cesium.Quaternion.fromHeadingPitchRoll(this.hpr, this.rotation);
this.particleSystem.emitterModelMatrix = Cesium.Matrix4.fromTranslationRotationScale(this.trs, this.emitterModelMatrix);
}
//创建粒子对象
createParticleSystem() {
return new Cesium.ParticleSystem({
image: this.style.fireImage,
startColor: new Cesium.Color(1, 1, 1, 1),
endColor: new Cesium.Color(0.5, 0, 0, 0),
startScale: this.style.startScale,
endScale: this.style.endScale,
minimumParticleLife: this.style.minimumParticleLife,
maximumParticleLife: this.style.maximumParticleLife,
minimumSpeed: this.style.minimumSpeed,
maximumSpeed: this.style.maximumSpeed,
imageSize: new Cesium.Cartesian2(this.style.particleSize, this.style.particleSize),
emissionRate: this.style.emissionRate,
lifetime: 16.0,
loop: true,
emitter: new Cesium.ConeEmitter(Cesium.Math.toRadians(45.0)),
sizeInMeters: true,
});
}
//移除
remove() {
this.removeEvent(); //清除事件
this.viewer.scene.primitives.remove(this.particleSystem); //删除粒子对象
this.viewer.entities.remove(this.entity); //删除entity
}
updateStyle() {
this.particleSystem.startScale = this.style.startScale;
this.particleSystem.endScale = this.style.endScale;
this.particleSystem.minimumParticleLife = this.style.minimumParticleLife;
this.particleSystem.maximumParticleLife = this.style.maximumParticleLife;
this.particleSystem.minimumSpeed = this.style.minimumSpeed;
this.particleSystem.maximumSpeed = this.style.maximumSpeed;
this.particleSystem.imageSize = new Cesium.Cartesian2(this.style.particleSize, this.style.particleSize);
this.particleSystem.emissionRate = this.style.emissionRate;
}
//默认样式信息
getDefaultStyle() {
return {
fireImage: "../../../static/images/effects/fire.png",
startScale: 3,
endScale: 1.5,
minimumParticleLife: 1.5,
maximumParticleLife: 1.8,
minimumSpeed: 7,
maximumSpeed: 9,
particleSize: 2,
emissionRate: 200,
}
}
}
// 喷泉粒子标绘类
import ParticlePlotBase from "../PlotBase"
import PlotTypes from "../PlotTypes"
export default class FountainPlot extends ParticlePlotBase {
constructor(viewer, geoFeature) {
super(viewer, geoFeature);
this.properties.plotType = PlotTypes.FOUNTAIN;
this.properties.plotName = "火焰";
this.style = geoFeature.properties.style || this.getDefaultStyle();
this.properties.style = this.style;
this.init();
}
init() {
//需要一个entity提供位置信息
this.entity = this.viewer.entities.add({
position: this.position,
});
this.particleSystem = this.createParticleSystem();
this.viewer.scene.primitives.add(this.particleSystem);
this.addEvent();
}
//添加事件
addEvent() {
this.emitterModelMatrix = new Cesium.Matrix4();
this.translation = new Cesium.Cartesian3();
this.rotation = new Cesium.Quaternion();
this.hpr = new Cesium.HeadingPitchRoll();
this.trs = new Cesium.TranslationRotationScale();
this.viewer.scene.preUpdate.addEventListener(this.preUpdateEvent, this);
}
removeEvent() {
this.viewer.scene.preUpdate.removeEventListener(this.preUpdateEvent, this);
this.emitterModelMatrix = undefined;
this.translation = undefined;
this.rotation = undefined;
this.hpr = undefined;
this.trs = undefined;
}
//场景渲染事件
preUpdateEvent(scene, time) {
this.particleSystem.modelMatrix = this.entity.computeModelMatrix(time, new Cesium.Matrix4());
this.hpr = Cesium.HeadingPitchRoll.fromDegrees(0.0, 0.0, 0.0, this.hpr);
this.trs.translation = Cesium.Cartesian3.fromElements(0, 0, 0, this.translation);
this.trs.rotation = Cesium.Quaternion.fromHeadingPitchRoll(this.hpr, this.rotation);
this.particleSystem.emitterModelMatrix = Cesium.Matrix4.fromTranslationRotationScale(this.trs, this.emitterModelMatrix);
}
//创建粒子对象
createParticleSystem() {
this.gravityScratch = new Cesium.Cartesian3();
return new Cesium.ParticleSystem({
image: this.style.fountainImage,
startColor: new Cesium.Color(1, 1, 1, 0.6),
endColor: new Cesium.Color(0.80, 0.86, 1, 0.4),
startScale: this.style.startScale,
endScale: this.style.endScale,
minimumParticleLife: this.style.minimumParticleLife,
maximumParticleLife: this.style.maximumParticleLife,
minimumSpeed: this.style.minimumSpeed,
maximumSpeed: this.style.maximumSpeed,
imageSize: new Cesium.Cartesian2(this.style.particleSize, this.style.particleSize),
emissionRate: this.style.emissionRate,
lifetime: 16.0,
//粒子发射器
emitter: new Cesium.CircleEmitter(0.2),
updateCallback: (p, dt) => {
return this.applyGravity(p, dt);
},
sizeInMeters: true,
performance: false,
});
}
applyGravity(p, dt) {
// We need to compute a local up vector for each particle in geocentric space.
Cesium.Cartesian3.normalize(p.position, this.gravityScratch);
Cesium.Cartesian3.multiplyByScalar(this.gravityScratch, this.style.gravity * dt, this.gravityScratch);
p.velocity = Cesium.Cartesian3.add(p.velocity, this.gravityScratch, p.velocity);
}
updateStyle() {
}
//移除
remove() {
this.removeEvent(); //清除事件
this.viewer.scene.primitives.remove(this.particleSystem); //删除粒子对象
this.viewer.entities.remove(this.entity); //删除entity
}
//默认样式信息
getDefaultStyle() {
return {
fountainImage: "../../../static/images/effects/fountain.png",
emissionRate: 40.0,
gravity: -3.5,
minimumParticleLife: 6,
maximumParticleLife: 7,
minimumSpeed: 9,
maximumSpeed: 9.5,
startScale: 1,
endScale: 7,
particleSize: 1,
}
}
}
详情参见 Cesium实战专栏