let charges = []; let sphere_radius = 200; let physics = false; let earth = false; let skeleton = false; function preload() { earth_image = loadImage("atlas1.jpg"); } function setup() { createCanvas(600, 600, WEBGL); } function draw() { orbitControl(); background(50); make_lights(); if (physics) { move_charges(charges); } if (skeleton) { draw_skeleton(sphere_radius); } draw_charges(sphere_radius); draw_sphere(sphere_radius, 25); } function draw_skeleton(radius) { push(); noStroke(); fill(0xff); sphere(4); stroke(0xbf); for (let charge of charges) { line( 0, 0, 0, charge.position.x * radius, charge.position.y * radius, charge.position.z * radius, ); } pop(); } function make_charges(n) { charges = []; for (let i = 0; i < n; i += 1) { let position; if (i === 0) { position = createVector(0, -1, 0); } else { const lat = random(-TAU / 4, TAU / 4); const lon = random(0, TAU); position = createVector( cos(lat) * cos(lon), sin(lat), cos(lat) * sin(lon), ); } charges.push({ position: position, velocity: createVector(), acceleration: createVector(), }); } } function draw_charges(radius) { push(); noStroke(); ambientMaterial(0xbf, 0x00, 0x00); for (let charge of charges.values()) { let position = charge.position.copy(); position.mult(radius); push(); translate(position.x, position.y, position.z); sphere(15); pop(); } pop(); } function draw_sphere(radius, n_axis_circles) { stroke(0x3f); noFill(); push(); rotateX(TAU / 4); draw_circles( radius, earth ? 2 : n_axis_circles, color(0x00, 0x9f, 0xff), color(0xff, 0x9f, 0x00), ); pop(); push(); rotateY(TAU / 4); draw_circles( radius, earth ? 2 : n_axis_circles, color(0xff, 0x00, 0xff), color(0x00, 0xff, 0x00), ); pop(); if (earth) { noStroke(); noFill(); tint(0xff, 0x9f); texture(earth_image); push(); rotateY(TAU / 4); sphere(radius); pop(); } } function draw_circles(radius, n_circles, pole_1_color, pole_2_color) { push(); stroke(pole_1_color); translate(0, 0, -radius); point(0, 0); pop(); for (let i = 1; i < n_circles; i += 1) { const angle = map(i, 0, n_circles - 1, -TAU / 4, TAU / 4); const circle_radius = radius * cos(angle); push(); translate(0, 0, radius * sin(angle)); circle(0, 0, circle_radius * 2); pop(); } push(); stroke(pole_2_color); translate(0, 0, radius); point(0, 0); pop(); } function make_lights() { let light = createVector(0, 1, -1); light.normalize(); directionalLight(0x1f, 0x1f, 0x1f, light); ambientLight(0xbf); } function keyPressed() { if (key == ' ') { physics = !physics; } else if (key == 'd') { earth = !earth; } else if (key == 'f') { skeleton = !skeleton; } else if (key >= '0' && key <= '9') { make_charges(int(key)); } }