user1059511
user1059511

Reputation: 267

Setting bounds on particle movement

I am creating particles and positioning them randomly with three.js:

for( var i = 0; i < particleCount; i++ ){
  var pX = Math.random() * 100-50;
  var pY =Math.random() * 100-50;
  var pZ = Math.random() * 100-50;
  particle = new THREE.Vector3(pX,pY,pZ);
  particle.velocity = new THREE.Vector3(Math.random(), Math.random(), pZ);
  particles.vertices.push(particle);
}

Then on my requestAnimationFrame update function I am moving the particles:

for (var i = 0; i < particleCount; i++) {
    var particle = particles.vertices[i];
    particle.y += particle.velocity.y*speed;
    particle.x += particle.velocity.x*speed;
  }

How can I introduce some limits to the movement ? i.e when the particle reaches the edge of the screen I want to "bounce" them back.

Upvotes: 0

Views: 274

Answers (1)

prisoner849
prisoner849

Reputation: 17586

It's better to have direction and velocity for each particle. Direction is always a normalized THREE.Vector3().

Then the code for your particles will be like this:

var particles = [];
var particleCount = 100;
var sizeX = 300;
var sizeY = 200;
var sizeZ = 100;

for (var i = 0; i < particleCount; i++) {
  var pX = Math.random() * sizeX - sizeX / 2;
  var pY = Math.random() * sizeY - sizeY / 2;
  var pZ = Math.random() * sizeZ - sizeZ / 2;
  particle = new THREE.Vector3(pX, pY, pZ);
  particle.direction = new THREE.Vector3(Math.random() - .5, Math.random() - .5, 0).normalize(); // a normalized vector with random values for x,y
  particle.velocity = Math.random() * 50; // speed is 50 units per second
  particles.push(particle);
}

Supposing, you use THREE.Points():

var geometry = new THREE.Geometry();
geometry.vertices = particles;

var points = new THREE.Points(geometry, new THREE.PointsMaterial({
  size: 5,
  color: "red"
}));
scene.add(points);

To set the proper speed (our 50 units per second) we'll need THREE.Clock() and its .getDelta() method:

var clock = new THREE.Clock();
var shift = new THREE.Vector3(); //we will re-use it in the animation loop
var delta = 0; // we will re-use it in the animation loop

And in the animation loop we will do this:

  delta = clock.getDelta(); // get period between frames (in seconds)

  particles.forEach(function(p) {

    if (p.x > sizeX / 2 || p.x < -sizeX / 2) { // it's also can be like if (Math.abs(p.x > sizeX / 2))
      p.direction.x = -p.direction.x;
    }
    if (p.y > sizeY / 2 || p.y < -sizeY / 2) {
      p.direction.y = -p.direction.y;
    }
    if (p.z > sizeZ / 2 || p.z < -sizeZ / 2) {
      p.direction.z = -p.direction.z;
    }

    p.add(shift.copy(p.direction).multiplyScalar(p.velocity * delta)); // here we re-use the `shift` vector 
  })

  points.geometry.verticesNeedUpdate = true; // important, if you won't set it to true you won't get your particles moving

So that's it.

jsfiddle example

PS If you want to use BufferGeometry, then you can refer to this very good SO answer

Upvotes: 1

Related Questions