Is it possible to apply wind speed to cesium weather effects (rain, snow) to change direction?
Hi @11167, thanks for the question,
I believe you would have to implement something like that yourself. I’d suggest looking into the ParticleSystem
class which is used in our weather sandcastle. The positions of particles can be changed so you would probably need to calculate the effects of the wind yourself and apply them.
Hi @11167
I hope this code is helpful to you.
It’s a part of a previous project I worked on, where I implemented a wind effect for a smoke particle system.
const viewer = new Cesium.Viewer("cesiumContainer", {
shouldAnimate: true,
terrain: Cesium.Terrain.fromWorldTerrain(),
});
const scene = viewer.scene;
scene.globe.depthTestAgainstTerrain = true;
// Particle parameters
let particleSystem;
let windSpeed = 0.0;
let windDirection = 0.0;
function addParticleCloud(longitude, latitude, height) {
const position = Cesium.Cartesian3.fromDegrees(longitude, latitude, height);
const modelMatrix = Cesium.Transforms.headingPitchRollToFixedFrame(
position,
new Cesium.HeadingPitchRoll(Cesium.Math.toRadians(0))
);
const particleImageURL = "../SampleData/circular_particle.png";
const particleSystemParameters = {
emissionRate: 10.0,
gravity: 1,
minimumParticleLife: 1.2,
maximumParticleLife: 1.2,
minimumSpeed: 1.0,
maximumSpeed: 4.0,
startScale: 1.0,
endScale: 5.0,
particleSize: 10.0,
speed: 0.0,
particleLife: 5.0,
length: 30,
};
const applyGravityAndWind = (particle, windSpeed, windDirection, dt) => {
const length = particleSystemParameters.length * dt;
const ellipsoid = Cesium.Ellipsoid.WGS84;
const ENU = new Cesium.Matrix4();
Cesium.Transforms.eastNorthUpToFixedFrame(particle.position, ellipsoid, ENU);
const windDirectionRad = Cesium.Math.toRadians(windDirection);
const displacement = new Cesium.Cartesian3();
const phi = Math.atan(windSpeed / length);
displacement.x = length * Math.sin(phi) * Math.sin(windDirectionRad);
displacement.y = length * Math.sin(phi) * Math.cos(windDirectionRad);
displacement.z = length * Math.cos(phi);
particle.position = Cesium.Matrix4.multiplyByPoint(ENU, displacement, new Cesium.Cartesian3());
};
particleSystem = new Cesium.ParticleSystem({
image: particleImageURL,
startColor: Cesium.Color.WHITE.withAlpha(0.7),
endColor: Cesium.Color.WHITE.withAlpha(0.1),
startScale: 1.0,
endScale: 5.0,
particleLife: particleSystemParameters.particleLife,
speed: particleSystemParameters.speed,
lifetime: particleSystemParameters.particleLife,
sizeInMeters: true,
imageSize: new Cesium.Cartesian2(particleSystemParameters.particleSize, particleSystemParameters.particleSize),
updateCallback: (particle, dt) => {
applyGravityAndWind(particle, windSpeed, windDirection, dt);
},
});
particleSystem.modelMatrix = modelMatrix;
scene.primitives.add(particleSystem);
viewer.camera.flyTo({
destination: position,
orientation: {
heading: Cesium.Math.toRadians(0),
pitch: Cesium.Math.toRadians(-30),
roll: 0.0,
},
});
}
addParticleCloud(-75.59777, 40.03883, 100);
const windSpeedLabel = document.createElement("div");
windSpeedLabel.innerText = "Wind Speed: 0";
windSpeedLabel.style.position = "absolute";
windSpeedLabel.style.top = "10px";
windSpeedLabel.style.left = "10px";
windSpeedLabel.style.color = "white";
windSpeedLabel.style.zIndex = "100";
document.body.appendChild(windSpeedLabel);
const windSpeedInput = document.createElement("input");
windSpeedInput.type = "range";
windSpeedInput.min = "0";
windSpeedInput.max = "100";
windSpeedInput.value = "0";
windSpeedInput.style.position = "absolute";
windSpeedInput.style.top = "30px";
windSpeedInput.style.left = "10px";
windSpeedInput.style.zIndex = "100";
document.body.appendChild(windSpeedInput);
const windDirectionLabel = document.createElement("div");
windDirectionLabel.innerText = "Wind Direction: 0°";
windDirectionLabel.style.position = "absolute";
windDirectionLabel.style.top = "60px";
windDirectionLabel.style.left = "10px";
windDirectionLabel.style.color = "white";
windDirectionLabel.style.zIndex = "100";
document.body.appendChild(windDirectionLabel);
const windDirectionInput = document.createElement("input");
windDirectionInput.type = "range";
windDirectionInput.min = "0";
windDirectionInput.max = "360";
windDirectionInput.value = "0";
windDirectionInput.style.position = "absolute";
windDirectionInput.style.top = "80px";
windDirectionInput.style.left = "10px";
windDirectionInput.style.zIndex = "100";
document.body.appendChild(windDirectionInput);
windSpeedInput.addEventListener("input", function () {
windSpeed = parseFloat(windSpeedInput.value);
windSpeedLabel.innerText = `Wind Speed: ${windSpeed}`;
});
windDirectionInput.addEventListener("input", function () {
windDirection = parseFloat(windDirectionInput.value);
windDirectionLabel.innerText = `Wind Direction: ${windDirection}°`;
});