# teaching machines

## Sphere

May 25, 2021 by . Filed under public, slai-2021.

This post is part of a course on geometric modeling at the Summer Liberal Arts Institute for Computer Science held at Carleton College in 2021.

Consider the sphere. How are spheres made in nature? There are several ways. Like many celestial bodies, the sphere we live on started as a smaller mass. The gravitational pull of baby Earth collected up more mass. In the absense of other forces, masses formed by gravity tend toward spheres. Rocks erode to spheres when forces erode them on all sides equally.

Nature’s sphere-making processes take eons. We humans don’t have that kind of time, so we use math to speed things. In this exercise, we’ll make a sphere as surface of revolution. (It also possible to express a sphere as a parametric surface. That method is not as intuitive as a surface of revolution.)

### Draw

On your paper, draw a semi-circle that forms the right side of a sphere, starting at the south pole and ending at the north. Label the south pole as -90 degrees. What is that in radians? Label the north pole as 90 degrees. What is that in radians?

Draw five or more points between the poles of the semi-circle, distributed evenly. Do not include the poles for reasons we’ll discuss later. The points you did draw represent a set of seed points, which are the starting points along the first line of longitude. To generate the other lines of longitude, you will rotate this first line around the y-axis.

### Function

Write a function named generateSphere. Have it accept these parameters:

• An integer nlatitudes that specifies the number of lines of latitude that the sphere has. The higher the number, the more spherical it will be.
• An integer nlongitudes that specifies the number of lines of longitude that the sphere has. The higher the number, the more spherical it will be.
• The radius of the sphere.

Create an empty positions and triangle arrays and return them in an object.

### Seed Positions

Before generating the big list of vertex of positions all across the sphere, write code to generate just the single line of longitude that you drew earlier. Follow these steps:

• All told, the semicircle is $pi$ radians, and you want to break it up into nlatitudes slices. Compute the number of radians per slice and store it in radiansPerSlice.
• Create an empty array of seed points. Call it seeds perhaps.
• Loop through all the latitude indices.
• Inside the loop, range-map the latitude index from its interval to the interval of possible radians of the lines of latitude. The bottom-most line of latitude, which sits just above the south pole, sits at $-\frac{\pi}{2} + \mathrm{radiansPerSlice}$. The top-most line of latitude, which sits just below the north pole, sits at $\frac{\pi}{2} – \mathrm{radiansPerSlice}$.
• Convert the radians to a seed point’s xy-coordinates.
• Assume the z-coordinate is 0.
• Turn the coordinates into a vector with this code:
const seed = new THREE.Vector3(x, y, z);

If the points are in vector form, they are easier to rotate.
• Push the seed into the array of seed points.

Test that your seed points appear along a semicircle on the right side of the sphere by rendering as points and changing your return statement to this:

return {positions: seeds.map(seed => seed.toArray()).flat(), triangles: []};


If that worked, great! If not, let’s talk.

### Vertex Positions

The next task is to rotate the line of seed points all around the sphere to form the lines of longitude. Follow these steps to produce the full array of vertex positions:

• Add a loop that visits each longitude index.
• Inside the loop, calculate the longitude’s angle around the sphere in radians by range-mapping the longitude index to $[0, 2\pi]$.
• Create a matrix that rotates a position around the y-axis by the longitude’s angle with code like this:
const matrix = new THREE.Matrix4().makeRotationY(radians);

• Add an inner loop that visits each latitude index.
• Inside the inner loop, use the latitude index to look up the seed.
• Clone and multiply the seed with code like this:
const rotatedPosition = seed.clone().applyMatrix4(matrix);

Adapt the names of variables accordingly. The call to clone makes an independent copy of the seed position. If you don’t make an independent copy, you will rotate the original seed point, which would interfere with subsequent lines of longitude. The applyMatrix4 method performs a matrix-vector multiplication. Such multiplications are to computer graphics as breathing is to living.
• Push the rotated position into your positions array.
• After the loops are all finished, push the coordinates of the south and north poles into the array. What will their indices be?

When you restore the return statement and render as points, you should see the entire sphere covered.

### Triangles

Stitching together the vertices of the sphere is just like stitching together the vertices of the cylinder, though the winding order may need to be adjusted. The poles are treated like the caps of the cylinder.