1

I want to simulate particles driven by wind on a three.js globe. The data I have is a Vector3 for the position of a particle and a Vector2 indicating wind speed and direction, think North/East. How do I get the new Vector3?

I've consulted numerous examples and read the documentation and believe the solution involves quaternions, but the axis of rotation is not given. Also, there are thousands of particles, it should be fast, however real-time is not required.

The radius of the sphere is 1.

Peter O.
  • 32,158
  • 14
  • 82
  • 96
Torsten Becker
  • 4,330
  • 2
  • 21
  • 22
  • I dont really have time to dive into this, but it sounds similar to something I have answered [here](http://stackoverflow.com/questions/43469555/three-js-particles-orbiting-a-point-in-random-directions-forming-a-sphere/43481278#43481278) before (also check the comments for working examples). You could probably do this with quaternions, but I think Vector3.ApplyAxisAngle(axis, angle) will do just fine. – micnil May 21 '17 at 16:33

2 Answers2

1

I would recommend you have a look at the Spherical class provided by three.js. Instead of cartesian coordinates (x,y,z), a point is represented in terms of a spherical coordinate-system (θ (theta), φ (phi), r).

spherical coordinate system

The value of theta is the longitude and phi is the latitude for your globe (r - sphereRadius would be the height above the surface). Your wind-vectors can then be interpreted as changes to these two values. So what I would try is basically this:

// a) convert particle-location to spherical
const sphericalPosition = new THREE.Spherical()
    .setFromVector3(particle.position);

// b) update theta/phi (note that windSpeed is assumed to 
//    be given in radians/time, but for a sphere of size 1 that 
//    shouldn't make a difference)
sphericalPosition.theta += windSpeed.x; // east-direction
sphericalPosition.phi += windSpeed.y; // north-direction

// c) write back to particle-position
particle.position.setFromSpherical(sphericalPosition);

Performance wise this shouldn't be a problem at all (maybe don't create a new Spherical-instance for every particle like I did above). The conversions involve a bit of trigonometry, but we're talking just thousands of points, not millions.

Hope that helps!

Martin Schuhfuß
  • 6,814
  • 1
  • 36
  • 44
0

If you just want to rotate a vector based on an angle, just perform a simple rotation of values on the specified plane yourself using trig as per this page eg for a rotation on the xz plane:

var x = cos(theta)*vec_to_rotate.x - sin(theta)*vec_to_rotate.z;
var z = sin(theta)*vec_to_rotate.x + cos(theta)*vec_to_rotate.z;
rotated_vector = new THREE.Vector3(x,vec_to_rotate.y,z);

But to move particles with wind, you're not really rotating a vector, you should be adding a velocity vector, and it 'rotates' its own heading based on a combination of initial velocity, inertia, air friction, and additional competing forces a la:

init(){
    position = new THREE.Vector(0,0,0);
    velocity = new THREE.Vector3(1,0,0);
    wind_vector = new THREE.Vector3(0,0,1);
}

update(){
    velocity.add(wind_vector);
    position.add(velocity);
    velocity.multiplyScalar(.95);
}

This model is truer to how wind will influence a particle. This particle will start off heading along the x axis, and then 'turn' eventually to go in the direction of the wind, without any rotation of vectors. It has a mass, and a velocity in a direction, a force is acting on it, it turns.

enter image description here

You can see that because the whole velocity is subject to friction (the multscalar), our initial velocity diminishes as the wind vector accumulates, which causes a turn without performing any rotations. Thought i'd throw this out just in case you're unfamiliar with working with particle systems and maybe were just thinking about it wrong.

OtterFamily
  • 803
  • 4
  • 10