cesium-examples/map/3d/static/Cesium/Apps/Sandcastle/gallery/Particle System.html

354 lines
11 KiB
HTML

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, minimum-scale=1, user-scalable=no">
<meta name="description" content="Particle systems.">
<meta name="cesium-sandcastle-labels" content="Beginner, Showcases">
<title>Cesium Demo</title>
<script type="text/javascript" src="../Sandcastle-header.js"></script>
<script type="text/javascript" src="../../../ThirdParty/requirejs-2.1.20/require.js"></script>
<script type="text/javascript">
if(typeof require === 'function') {
require.config({
baseUrl : '../../../Source',
waitSeconds : 120
});
}
</script>
</head>
<body class="sandcastle-loading" data-sandcastle-bucket="bucket-requirejs.html">
<style>
@import url(../templates/bucket.css);
#toolbar {
background: rgba(42, 42, 42, 0.8);
padding: 4px;
border-radius: 4px;
}
#toolbar input {
vertical-align: middle;
padding-top: 2px;
padding-bottom: 2px;
}
#toolbar .header {
font-weight: bold;
}
</style>
<div id="cesiumContainer" class="fullSize"></div>
<div id="loadingOverlay"><h1>Loading...</h1></div>
<div id="toolbar">
<table>
<tbody>
<tr>
<td>Rate</td>
<td>
<input type="range" min="0.0" max="100.0" step="1" data-bind="value: emissionRate, valueUpdate: 'input'">
<input type="text" size="5" data-bind="value: emissionRate">
</td>
</tr>
<tr>
<td>Size</td>
<td>
<input type="range" min="2" max="60.0" step="1" data-bind="value: particleSize, valueUpdate: 'input'">
<input type="text" size="5" data-bind="value: particleSize">
</td>
</tr>
<tr>
<td>Min Life</td>
<td>
<input type="range" min="0.1" max="30.0" step="1" data-bind="value: minimumParticleLife, valueUpdate: 'input'">
<input type="text" size="5" data-bind="value: minimumParticleLife">
</td>
</tr>
<tr>
<td>Max Life</td>
<td>
<input type="range" min="0.1" max="30.0" step="1" data-bind="value: maximumParticleLife, valueUpdate: 'input'">
<input type="text" size="5" data-bind="value: maximumParticleLife">
</td>
</tr>
<tr>
<td>Min Speed</td>
<td>
<input type="range" min="0.0" max="30.0" step="1" data-bind="value: minimumSpeed, valueUpdate: 'input'">
<input type="text" size="5" data-bind="value: minimumSpeed">
</td>
</tr>
<tr>
<td>Max Speed</td>
<td>
<input type="range" min="0.0" max="30.0" step="1" data-bind="value: maximumSpeed, valueUpdate: 'input'">
<input type="text" size="5" data-bind="value: maximumSpeed">
</td>
</tr>
<tr>
<td>Start Scale</td>
<td>
<input type="range" min="0.0" max="10.0" step="1" data-bind="value: startScale, valueUpdate: 'input'">
<input type="text" size="5" data-bind="value: startScale">
</td>
</tr>
<tr>
<td>End Scale</td>
<td>
<input type="range" min="0.0" max="10.0" step="1" data-bind="value: endScale, valueUpdate: 'input'">
<input type="text" size="5" data-bind="value: endScale">
</td>
</tr>
<tr>
<td>Gravity</td>
<td>
<input type="range" min="-20.0" max="20.0" step="1" data-bind="value: gravity, valueUpdate: 'input'">
<input type="text" size="5" data-bind="value: gravity">
</td>
</tr>
</tbody>
</table>
</div>
<script id="cesium_sandcastle_script">
function startup(Cesium) {
'use strict';
//Sandcastle_Begin
var viewer = new Cesium.Viewer('cesiumContainer');
//Set the random number seed for consistent results.
Cesium.Math.setRandomNumberSeed(3);
//Set bounds of our simulation time
var start = Cesium.JulianDate.fromDate(new Date(2015, 2, 25, 16));
var stop = Cesium.JulianDate.addSeconds(start, 120, new Cesium.JulianDate());
//Make sure viewer is at the desired time.
viewer.clock.startTime = start.clone();
viewer.clock.stopTime = stop.clone();
viewer.clock.currentTime = start.clone();
viewer.clock.clockRange = Cesium.ClockRange.LOOP_STOP; //Loop at the end
viewer.clock.multiplier = 1;
viewer.clock.shouldAnimate = true;
//Set timeline to simulation bounds
viewer.timeline.zoomTo(start, stop);
var viewModel = {
emissionRate : 5.0,
gravity : 0.0,
minimumParticleLife : 1.2,
maximumParticleLife : 1.2,
minimumSpeed : 1.0,
maximumSpeed : 4.0,
startScale : 1.0,
endScale : 5.0,
particleSize : 25.0
};
Cesium.knockout.track(viewModel);
var toolbar = document.getElementById('toolbar');
Cesium.knockout.applyBindings(viewModel, toolbar);
var entityPosition = new Cesium.Cartesian3();
var entityOrientation = new Cesium.Quaternion();
var rotationMatrix = new Cesium.Matrix3();
var modelMatrix = new Cesium.Matrix4();
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.0, 0.0, hpr);
trs.translation = Cesium.Cartesian3.fromElements(-4.0, 0.0, 1.4, translation);
trs.rotation = Cesium.Quaternion.fromHeadingPitchRoll(hpr, rotation);
return Cesium.Matrix4.fromTranslationRotationScale(trs, emitterModelMatrix);
}
var pos1 = Cesium.Cartesian3.fromDegrees(-75.15787310614596, 39.97862668312678);
var pos2 = Cesium.Cartesian3.fromDegrees(-75.1633691390455, 39.95355089912078);
var position = new Cesium.SampledPositionProperty();
position.addSample(start, pos1);
position.addSample(stop, pos2);
var entity = viewer.entities.add({
availability : new Cesium.TimeIntervalCollection([new Cesium.TimeInterval({
start : start,
stop : stop
})]),
model : {
uri : '../../SampleData/models/CesiumMilkTruck/CesiumMilkTruck-kmc.glb',
minimumPixelSize : 64
},
viewFrom: new Cesium.Cartesian3(-100.0, 0.0, 100.0),
position : position,
orientation : new Cesium.VelocityOrientationProperty(position)
});
viewer.trackedEntity = entity;
var scene = viewer.scene;
var particleSystem = scene.primitives.add(new Cesium.ParticleSystem({
image : '../../SampleData/smoke.png',
startColor : Cesium.Color.LIGHTSEAGREEN.withAlpha(0.7),
endColor : Cesium.Color.WHITE.withAlpha(0.0),
startScale : viewModel.startScale,
endScale : viewModel.endScale,
minimumParticleLife : viewModel.minimumParticleLife,
maximumParticleLife : viewModel.maximumParticleLife,
minimumSpeed : viewModel.minimumSpeed,
maximumSpeed : viewModel.maximumSpeed,
imageSize : new Cesium.Cartesian2(viewModel.particleSize, viewModel.particleSize),
emissionRate : viewModel.emissionRate,
bursts : [
// these burst will occasionally sync to create a multicolored effect
new Cesium.ParticleBurst({time : 5.0, minimum : 10, maximum : 100}),
new Cesium.ParticleBurst({time : 10.0, minimum : 50, maximum : 100}),
new Cesium.ParticleBurst({time : 15.0, minimum : 200, maximum : 300})
],
lifetime : 16.0,
emitter : new Cesium.CircleEmitter(2.0),
emitterModelMatrix : computeEmitterModelMatrix(),
updateCallback : applyGravity
}));
var gravityScratch = new Cesium.Cartesian3();
function applyGravity(p, dt) {
// We need to compute a local up vector for each particle in geocentric space.
var position = p.position;
Cesium.Cartesian3.normalize(position, gravityScratch);
Cesium.Cartesian3.multiplyByScalar(gravityScratch, viewModel.gravity * dt, gravityScratch);
p.velocity = Cesium.Cartesian3.add(p.velocity, gravityScratch, p.velocity);
}
viewer.scene.preUpdate.addEventListener(function(scene, time) {
particleSystem.modelMatrix = computeModelMatrix(entity, time);
// Account for any changes to the emitter model matrix.
particleSystem.emitterModelMatrix = computeEmitterModelMatrix();
// Spin the emitter if enabled.
if (viewModel.spin) {
viewModel.heading += 1.0;
viewModel.pitch += 1.0;
viewModel.roll += 1.0;
}
});
Cesium.knockout.getObservable(viewModel, 'emissionRate').subscribe(
function(newValue) {
particleSystem.emissionRate = parseFloat(newValue);
}
);
Cesium.knockout.getObservable(viewModel, 'particleSize').subscribe(
function(newValue) {
var particleSize = parseFloat(newValue);
particleSystem.minimumImageSize.x = particleSize;
particleSystem.minimumImageSize.y = particleSize;
particleSystem.maximumImageSize.x = particleSize;
particleSystem.maximumImageSize.y = particleSize;
}
);
Cesium.knockout.getObservable(viewModel, 'minimumParticleLife').subscribe(
function(newValue) {
particleSystem.minimumParticleLife = parseFloat(newValue);
}
);
Cesium.knockout.getObservable(viewModel, 'maximumParticleLife').subscribe(
function(newValue) {
particleSystem.maximumParticleLife = parseFloat(newValue);
}
);
Cesium.knockout.getObservable(viewModel, 'minimumSpeed').subscribe(
function(newValue) {
particleSystem.minimumSpeed = parseFloat(newValue);
}
);
Cesium.knockout.getObservable(viewModel, 'maximumSpeed').subscribe(
function(newValue) {
particleSystem.maximumSpeed = parseFloat(newValue);
}
);
Cesium.knockout.getObservable(viewModel, 'startScale').subscribe(
function(newValue) {
particleSystem.startScale = parseFloat(newValue);
}
);
Cesium.knockout.getObservable(viewModel, 'endScale').subscribe(
function(newValue) {
particleSystem.endScale = parseFloat(newValue);
}
);
var options = [{
text : 'Circle Emitter',
onselect : function() {
particleSystem.emitter = new Cesium.CircleEmitter(2.0);
}
}, {
text : 'Sphere Emitter',
onselect : function() {
particleSystem.emitter = new Cesium.SphereEmitter(2.5);
}
}, {
text : 'Cone Emitter',
onselect : function() {
particleSystem.emitter = new Cesium.ConeEmitter(Cesium.Math.toRadians(45.0));
}
}, {
text : 'Box Emitter',
onselect : function() {
particleSystem.emitter = new Cesium.BoxEmitter(new Cesium.Cartesian3(10.0, 10.0, 10.0));
}
}];
Sandcastle.addToolbarMenu(options);
//Sandcastle_End
Sandcastle.finishedLoading();
}
if (typeof Cesium !== 'undefined') {
startup(Cesium);
} else if (typeof require === 'function') {
require(['Cesium'], startup);
}
</script>
</body>
</html>