How to rotate points around a "sphere" without weird pole problems?

Let’s say I have 10,000 points arranged in a spherical form like so:

//inside a for loop...
const theta = Math.random() * (Math.PI);
const phi =  Math.random() * (Math.PI * 2);
const x = (radius * Math.sin(phi) * Math.cos(theta));
const y = (radius * Math.sin(phi) * Math.sin(theta));
const z = (radius * Math.cos(phi));

In my animation loop I iterate through each point and update its position like so:

const phiDelta = 0.005;
const thetaDelta = 0.01;
const radius = 1;

particleAnimate: function(i) {
	
    this.particleData[i].phi += phiDelta;
    this.particleData[i].theta += thetaDelta;
    
    if(this.particleData[i].phi > Math.PI * 2)
        this.particleData[i].phi = 0;

    if(this.particleData[i].theta > Math.PI)
        this.particleData[i].theta = 0;

    const {phi, theta} = this.particleData[i];
    
    let x = radius * Math.sin(phi) * Math.cos(theta);
    let y = radius * Math.sin(phi) * Math.sin(theta);
    let z = radius * Math.cos(phi);

    Particles.setPosition(i,x,y,z);
}

The problem is the points all seem to converge into the poles of the sphere which looks really ugly. Instead I just want my particles to sort of randomly drift around the “surface” of my invisible sphere in a smooth and pretty fashion… like random satellites.

It seems like incrementing phi/theta isn’t the right approach here, so what is?

Hi!
As an option, set an individual normal to each point and rotate the point around it:


Demo: https://codepen.io/prisoner849/full/WNaLywN

2 Likes

Thank you so much for this.

I only have one problem: if I want the “origin/center” of the sphere to be (as an example)

const sphereCenter = new Three.Vector3(1.2, 1.8, 1.2);

How would I factor that in? I tried doing this…

p.applyQuaternion(q);
p.add(sphereCenter.position);

Which works for setting the initial position, but it falls apart in the animation loop. It seems like the normal is at 0,0,0 or something? Because the points start to orbit around 0,0,0.

But I also tried this instead:

randNorm.add(sphereCenter.position);
q.setFromUnitVectors(front, randNorm);
p.applyQuaternion(q);

Which didn’t work at all…

change line 62 to

g.attributes.position.setXYZ(idx, p.x + 1.2, p.y + 1.8, p.z + 1.2);
1 Like

or why simply not set object’s position, like so:

let points = new THREE.Points(g, m);
points.position.set(1.2, 1.8, 1.2); // added line
scene.add(points);

because in truth, I have one single large Points object with thousands of points, and I want multiple “spheres” of swarming particles scattered about.

and adding the offset on .setXYZ in the animation loop doesn’t work. I already position the points in the right place before the loop starts. so continuing to apply the offset again instantly hurls the points further away into space.

the problem is that p.applyAxisAngle causes the point to rotate from the world origin of the scene, not relative to sphereCenter. combine that with adding the +1.2, +1.8, +1.2, and the points blow far outside the viewport.

Not sure I understood correctly the desired result.
Something like this?


Demo: https://codepen.io/prisoner849/full/rNqPLPo