Cesium學習筆記(十):粒子系統(Particle System)

粒子系統是Cesium1.35最新的更新,讓我們一起來看看吧

1. 例子

首先先來一架飛機

var entity = viewer.entities.add({
    model : {
        uri : '../Apps/SampleData/models/CesiumAir/Cesium_Air.gltf',
        minimumPixelSize : 64
    },
    position : Cesium.Cartesian3.fromDegrees(-112.110693, 36.0994841, 1000.0)
});
viewer.trackedEntity = entity;

然後我們需要拿到飛機模型的位置

// 計算當前時間點飛機模型的位置矩陣
function computeModelMatrix(entity, time) {
    //獲取位置
    var position = Cesium.Property.getValueOrUndefined(entity.position, time, new Cesium.Cartesian3());
    if (!Cesium.defined(position)) {
        return undefined;
    }
    //獲取方向
    var modelMatrix;
    var orientation = Cesium.Property.getValueOrUndefined(entity.orientation, time, new  Cesium.Quaternion());
    if (!Cesium.defined(orientation)) {
        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;
}

接着設置好粒子發射器的位置

// 計算引擎(粒子發射器)位置矩陣
function computeEmitterModelMatrix() {
    //方向
    hpr = Cesium.HeadingPitchRoll.fromDegrees(0.0, 0.0, 0.0, new Cesium.HeadingPitchRoll());
    var trs = new Cesium.TranslationRotationScale();

    //以modelMatrix(飛機)中心爲原點的座標系的xyz軸位置偏移
    trs.translation = Cesium.Cartesian3.fromElements(2.5, 3.5, 1.0, new Cesium.Cartesian3());
    trs.rotation = Cesium.Quaternion.fromHeadingPitchRoll(hpr, new Cesium.Quaternion());
    return Cesium.Matrix4.fromTranslationRotationScale(trs, new Cesium.Matrix4());
}

最後就可以加載我們的粒子系統看看效果了

var particleSystem = viewer.scene.primitives.add(new Cesium.ParticleSystem({
    image : '../Apps/SampleData/fire.png',
    startScale : 1.0,
    endScale : 4.0,
    minimumLife : 1.0,
    maximumLife : 1.5,
    speed : 5.0,
    width : 20,
    height : 20,
    lifeTime : 16.0,
    //主模型參數(位置)
    modelMatrix : computeModelMatrix(entity, Cesium.JulianDate.now()),
    // 發射器參數
    emitter : new Cesium.CircleEmitter(0.5),
    rate : 5.0,
    emitterModelMatrix : computeEmitterModelMatrix(),
    //顏色
    startColor: Cesium.Color.RED.withAlpha(0.7),
    endColor: Cesium.Color.YELLOW.withAlpha(0.3),
    forces: [applyGravity]
}));

這裏寫圖片描述

2. 粒子發射器

Cesium內置了4種發射器,可以看到我這裏用的是CircleEmitter,下面一起看看幾種發射器發出來的粒子是啥樣的

CircleEmitter

emitter : new Cesium.CircleEmitter(0.5)

這種發射器發射的粒子是一個圓形,所以需要一個半徑,這樣看可能看不出來,我們可以一瞬間把粒子量加大就能看出來了

這裏寫圖片描述

ConeEmitter

emitter : new Cesium.ConeEmitter(Cesium.Math.toRadians(45.0))

這種發出來的稍微有點散,沒有CircleEmitter那麼聚集,因爲它是以一個錐形進行發散的,這樣就需要傳一個角度了

這裏寫圖片描述

嘖嘖,很適合做核彈效果,蘑菇雲哎

BoxEmitter和SphereEmitter

剩下兩種感覺差不多,我就一起說了,順帶對比下

BoxEmitter這種是從一個長方體中將粒子散發出來,需要傳一個Cartesian3,存放長寬高

emitter : new Cesium.BoxEmitter(new Cesium.Cartesian3(1.0, 1.0, 1.0))

SphereEmitter是從一個球中將粒子散發出來,需要一個半徑

emitter : new Cesium.SphereEmitter(0.5)

來看一下效果,感覺差不多,我們需要從高空才能看出區別

這裏寫圖片描述

BoxEmitter

這裏寫圖片描述

SphereEmitter

3. bursts

之前我們看見的效果其實都是用bursts做出來的,bursts就是讓粒子系統週期性的做出一些額外的爆發效果,用法很簡單

var particleSystem = viewer.scene.primitives.add(new Cesium.ParticleSystem({
    ...
    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})
    ],
    ...
}));

我們需要傳入一個ParticleBurst類型的array,存的就是你想要的效果

4. 其他的一些屬性

粒子系統中很多屬性都有min和max以及其本身,比如life就有minimumLife、maximumLife和life三個,但是如果你設置了life屬性,那麼minimumLife和maximumLife就會失效,其他的屬性也是如此

還有一些比較有趣的屬性,比如顏色,你可以設置startColor和endColor來設置顏色的漸變

其中rate是粒子的發射速率,也就是每秒發射的粒子數

在默認的情況下粒子的loop是爲true的,如果需要的話可以把它關閉,再配合bursts並把粒子的速率rate設爲0,可以做出很不錯的爆炸效果

除了這些還有很多的屬性比如speed、width、height等等,詳細的可以見官方API

5. 重力效果

這可是一個重頭戲,官方給我們提供了一個計算方法(原諒我的數學,一臉懵逼)

//你需要的重力倍數,不過這個重力似乎是反過來的,負的纔是增大重力
var gravity = 0;
var gravityScratch = new Cesium.Cartesian3();
function applyGravity(p, dt) {
    // Compute a local up vector for each particle in geocentric space.
    var position = p.position;

    Cesium.Cartesian3.normalize(position, gravityScratch);
    Cesium.Cartesian3.multiplyByScalar(gravityScratch, gravity * dt, gravityScratch);

    p.velocity = Cesium.Cartesian3.add(p.velocity, gravityScratch, p.velocity);
}

你只需要在粒子系統的初始化裏面加上一句就可以了

particleSystem: {
    ...
    forces: [applyGravity],
    ...
}

讓我們看看100倍重力是什麼效果

這裏寫圖片描述

嘿嘿,挺有意思的,讓我們來點更有意思的,讓飛機飛起來看看效果如何呢

我們不需要改任何代碼,還記得之前那個轉圈的飛機麼(不知道的戳這裏),我們只需要把之前那些代碼加在後面,並加上一個更新位置的方法就可以了(畢竟在動嘛)

viewer.scene.preRender.addEventListener(function(scene, time) {
    //重新計算位置
    particleSystem.modelMatrix = computeModelMatrix(entity, time);
});

總共加了這些

//計算當前時間點飛機模型的位置矩陣
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;
}

//計算引擎(粒子發射器)位置矩陣
function computeEmitterModelMatrix() {
    //方向
    hpr = Cesium.HeadingPitchRoll.fromDegrees(0.0, 0.0, 0.0, new Cesium.HeadingPitchRoll());
    var trs = new Cesium.TranslationRotationScale();
    //以modelMatrix(飛機)中心爲原點的座標系的xyz軸位置偏移
    trs.translation = Cesium.Cartesian3.fromElements(2.5, 3.5, 1.0, new Cesium.Cartesian3());
    trs.rotation = Cesium.Quaternion.fromHeadingPitchRoll(hpr, new Cesium.Quaternion());
    return Cesium.Matrix4.fromTranslationRotationScale(trs, new Cesium.Matrix4());
}

//粒子系統參數
var particleSystem = viewer.scene.primitives.add(new Cesium.ParticleSystem({
    image : '../Apps/SampleData/fire.png',
    startScale : 1.0,
    endScale : 4.0,
    minimumLife : 1.0,
    maximumLife : 1.5,
    speed : 5.0,
    width : 20,
    height : 20,
    lifeTime : 16.0,
    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})
    ],
    //主模型參數(位置)
    modelMatrix : computeModelMatrix(entity, Cesium.JulianDate.now()),
    // 發射器參數
    emitter : new Cesium.CircleEmitter(0.5),
    rate : 5.0,
    emitterModelMatrix : computeEmitterModelMatrix(),
    //顏色
    startColor: Cesium.Color.RED.withAlpha(0.7),
    endColor: Cesium.Color.YELLOW.withAlpha(0.3),
    forces: [applyGravity]
}));

//重力計算
var gravityScratch = new Cesium.Cartesian3();
function applyGravity(p, dt) {

    var position = p.position;

    Cesium.Cartesian3.normalize(position, gravityScratch);
    Cesium.Cartesian3.multiplyByScalar(gravityScratch, 1 * dt, gravityScratch);

    p.velocity = Cesium.Cartesian3.add(p.velocity, gravityScratch, p.velocity);
}

//刷新位置
viewer.scene.preRender.addEventListener(function(scene, time) {
    particleSystem.modelMatrix = computeModelMatrix(entity, time);
});

這裏寫圖片描述

效果還是不錯的

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章