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
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.
CodePudding user response:
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 Vector3
s 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.
CodePudding user response:
Just a small remark, not the answer (all kudos to @Marquizzo)
Since r133
, there is a method .randomDirection()
of THREE.Vector3()
, which helps us to set points on a sphere in a more convenient way.
Thus, all the code for instantiating of particles is:
const distance = Math.min(200, window.innerWidth / 16);
let vertices = new Array(1600).fill().map((v) => {
return new THREE.Vector3().randomDirection().setLength(distance);
});
const geometry = new THREE.BufferGeometry().setFromPoints(vertices);
const material = new THREE.PointsMaterial({ color: 0xffffff, size: 1 });
const particles = new THREE.Points(geometry, material);