Sherical coordinates
The basics of spherical coordinates for creative coding
I'm playing around with the idea of creating a music visualiser in the shape of an Orb. I figured if I could generate a mesh of a sphere it would be a great start, and hopefully give me a reusable function which I could add to my library.
Let's build a function that'll generate Cartesian coordinates of a sphere. Our starting point for this is the Spherical Coordinates Wikipedia Article, on which I can find the following formula:
Since we have 2 variables (theta & phi), this will translate in code to a double loop to iterate through all the angle combinations. Similar to polar coordinates but with an extra level to account for the 3rd dimension.
It looks something like this:
/**
* Generates a set of spherical coordinates around a given center point.
*
* @param {number} radius - The radius of the sphere.
* @param {number} [resolution=100] - The number of points per full rotation. Higher values result in more detailed spheres.
* @param {number} [x=0] - The x-coordinate of the sphere's center.
* @param {number} [y=0] - The y-coordinate of the sphere's center.
* @param {number} [z=0] - The z-coordinate of the sphere's center.
* @returns {Array<Object>} data - A nested array of points on the sphere. Each point is an object with x, y, and z properties.
*/
function sphericalCoordinates(
radius,
resolution = 50,
x = 0,
y = 0,
z = 0
) {
const twoPi = Math.PI * 2;
// The angular distance between each point
const angleStep = twoPi / resolution;
// Initialize the array that will store the generated points
const data = [];
for (let theta = 0; theta < twoPi; theta += angleStep) {
const layer = [];
for (let phi = 0; phi < twoPi; phi += angleStep) {
// Convert spherical coordinates (radius, theta, phi) to Cartesian coordinates (x, y, z)
layer.push({
x: x + radius * Math.sin(theta) * Math.cos(phi),
y: y + radius * Math.cos(theta),
z: z + radius * Math.sin(theta) * Math.sin(phi)
});
}
// Add this layer to the overall data array
data.push(layer);
}
return data;
}
Once you have the points to draw, you can simply iterate over them and place them on the screen as such:
beginShape(POINTS);
for (const row of sphereData) {
for (const item of row) {
vertex(item.x, item.y, item.z)
}
}
p5.endShape();
Here's an example of it in action: