Skip to content

only one particle showing in the scene with three.js

I am trying to create a sphere with particles randomly floating on its surface. It will move depends on the position on mousemove. something like this enter image description here

Strangely, it is only displaying one particle on canvas. I am debugging with console.log(vertices), but it clearly shows all the vertices in the array.

My code in CodeSandBox

Answer

The problem is with your loop. You’re assigning a value to theta and phi only once outside your loop, then you give the same value to all 1600 vertices:

const theta = Math.acos(THREE.Math.randFloatSpread(2));
const phi = THREE.Math.randFloatSpread(360);

for (let i = 0; i < 1600; i++) {
  const vertex = new THREE.Vector3();

  vertex.x = distance * Math.sin(theta) * Math.cos(phi);
  vertex.y = distance * Math.sin(theta) * Math.sin(phi);
  vertex.z = distance * Math.cos(theta);

  vertices.push(vertex.x, vertex.y, vertex.z);
}

When you use console.log(vertices), look at the x, y, z values and you’ll see they all repeat.

What you should do is re-assign a new theta and a new phi inside the loop, so each vertex gets a unique position:

let theta, phi;
let x, y, z;

for (let i = 0; i < 1600; i++) {
  theta = Math.acos(THREE.Math.randFloatSpread(2));
  phi = THREE.Math.randFloatSpread(360);

  x = distance * Math.sin(theta) * Math.cos(phi);
  y = distance * Math.sin(theta) * Math.sin(phi);
  z = distance * Math.cos(theta);

  vertices.push(x, y, z);
}

You also don’t need to create a THREE.Vector3() on each iteration, it’s pretty inefficient to create 1600 Vector3s just to be discarded immediately. Instead you can re-use the same x, y, z variables to avoid all those object construction costs.

See here for a working demo of your example. I also scaled down the point size to 1.