## In circles and spheres

Looping over circles, sines, cosines, and spheres.

Although not every effect or demo in the wilderness is circular, it's common to see a lot of them using circular functions in one way or another.

Math.sin and Math.cos are handy because they loop, like a wave that goes up and down. When the given value goes over *Math.PI 2, the value they give you it's going to repeat. Both sin and cos are actually both the same function but offset by HALF_PI.

Their circular nature makes it super useful for repeating things. Want a repeating scale animation? Slap a cosine to it.

let scale = Math.cos(time)

Want something to go in circles? Slap both of them with the same angle.

position.x = Math.sin(time);

position.y = Math.cos(time);

### Daydream sphere

In daydream, Keita creates 3 spheres. In their fragment shader, he samples simplex-noise using the normals of the spheres. Then, discards any pixel where the noise is lower than `0.3` . This create the gaps that allow us to see the most inner spheres

float n = snoise(vec3(normal.x + time , normal.y, normal.z));

float visibility = step(0.3, n);

if (visibility < 1.0) discard;

### Stripes around orb

This animation is similar to the daydream sphere. However, the effect is limited to a single stripe, and it has a lot more spheres. Here's a basic version of what it would look like in the fragment shader:

float stripeSize = 0.2;

float stripe = step(0.5 -stripeSize, uv.y) * step(uv.y, 0.5 + stripeSize);

float n = snoise(vec3(normal.x + time , normal.y, normal.z)) * stripe;

Using the sphere UVs I calculate a white-centered stripe. Then, multiply that by the noise to get the noise only happening in the center of the sphere.

### Rectangle around circle

To position a lot of rectangles like in mrDoob's demo, we first divide 2PI by the number of rectangles:

let anglePerSquare = (Math.PI * 2.) / count

Then we loop over all our meshes and calculate their x and y position:

// in some loop
let angle = index * anglePerSquare
mesh.position.x = Math.cos(angle) * radius
mesh.position.y = Math.sin(angle) * radius

### Circle particle torus

While this looks way more complicated than the last demo. A torus is a set of circles around another circle. It's not even an extra step from the last demo, It's the same step repeated twice!

// 1s loop

let pivot = new Object3d()
let torusAngle= index * anglePerPivot
pivot.position.x = Math.cos(torusAngle) * torusRadius
pivot.position.y = Math.sin(torusAngle) * torusRadius

Then, for every pivot (an inner loop), we repeat the process above but add each mesh to the pivot.

### Dave circular motion

This kind of circular motion also worsk with cosine and sine. However, they are applied to the scale and y positoning of the rings:

// loop over all rings.

let offset = ringIndex * Math.PI + time * Math.PI

let minScale = 0.2;

let maxScale = 1.;

ring.scale.setScalar( (Math.sin(offset) * 0.5 + 0.5) * (maxScale - minScale) + minScale )

ring.position.z = Math.cos(offset) *0.8

For the circular motion to work correctly, you need to use both cos and sin.