diff --git a/sketch.js b/sketch.js index 0a6646c..e08bbe8 100644 --- a/sketch.js +++ b/sketch.js @@ -1,9 +1,10 @@ -let charges = new Map(); -let counter = 0; +let charges = []; let sphere_mode = 'circles'; let sphere_radius = 200; +let physics = false; + function preload() { earth = loadImage("atlas1.jpg"); } @@ -17,15 +18,59 @@ function draw() { background(50); make_lights(); - draw_sphere(sphere_radius, 25); + if (physics) { + move_charges(); + } draw_charges(sphere_radius); + draw_sphere(sphere_radius, 25); +} + +function move_charges() { + for (charge of charges) { + charge.acceleration.setMag(0); + } + for (let i = 0; i < charges.length; i += 1) { + for (let j = 0; j < i; j += 1) { + const displacement = p5.Vector.sub( + charges[i].position, + charges[j].position, + ); + const acceleration_mag = 1 / displacement.mag() * 0.005; + let ai = displacement.copy().normalize().mult(acceleration_mag); + let aj = p5.Vector.mult(ai, -1); + let ai_norm = project_onto_plane(ai, charges[i].position); + + let aj_norm = project_onto_plane(aj, charges[j].position); + + charges[i].acceleration.add(ai_norm); + charges[j].acceleration.add(aj_norm); + } + } + for (let i = 0; i < charges.length; i += 1) { + let charge = charges[i]; + charge.velocity = charge.velocity.add(charge.acceleration); + //charge.velocity = project_onto_plane(charge.velocity, charge.position); + charge.position = charge.position.add(charge.velocity); + charge.position.normalize(); + } +} + +function project_onto_unit_vector(v, unit_vector) { + let size = p5.Vector.dot(v, unit_vector); + return p5.Vector.mult(unit_vector, size); +} + +/// Project `v` onto the plane normal to `unit_vector` +function project_onto_plane(v, unit_vector) { + let v_proj = project_onto_unit_vector(v, unit_vector); + return v.sub(v_proj) } function make_charges(n) { - charges.clear(); + charges = []; for (let i = 0; i < n; i += 1) { let position; - if (i == 0) { + if (i === 0) { position = createVector(0, -1, 0); } else { const lat = random(-TAU / 4, TAU / 4); @@ -36,8 +81,11 @@ function make_charges(n) { cos(lat) * sin(lon), ); } - charges.set(counter, position); - counter += 1; + charges.push({ + position: position, + velocity: createVector(), + acceleration: createVector(), + }); } } @@ -46,7 +94,7 @@ function draw_charges(radius) { noStroke(); ambientMaterial(0xbf, 0x00, 0x00); for (let charge of charges.values()) { - let position = charge.copy(); + let position = charge.position.copy(); position.mult(radius); push(); translate(position.x, position.y, position.z); @@ -122,6 +170,8 @@ function make_lights() { function keyPressed() { if (key == 'd') { sphere_mode = sphere_mode === 'earth' ? 'circles' : 'earth'; + } else if (key == ' ') { + physics = !physics; } else if (key >= '0' && key <= '9') { make_charges(int(key)); }