You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
472 lines
14 KiB
HTML
472 lines
14 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="../../../Build/CesiumUnminified/Cesium.js"
|
|
nomodule
|
|
></script>
|
|
<script type="module" src="../load-cesium-es6.js"></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.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") {
|
|
window.startupCalled = true;
|
|
startup(Cesium);
|
|
}
|
|
</script>
|
|
</body>
|
|
</html>
|