diff --git a/sketch.js b/sketch.js index db98094..1d684e6 100644 --- a/sketch.js +++ b/sketch.js @@ -2,13 +2,18 @@ let camera; let red; let charges = []; +let faces = []; let sphere_radius = 200; +const SURFACE_NONE = 0; +const SURFACE_CIRCLES = 1; +const SURFACE_EARTH = 2; + +let surface = SURFACE_CIRCLES; let physics = false; -let earth = false; let skeleton = false; -let planes = false; +let polyhedron = false; function preload() { @@ -16,11 +21,15 @@ function preload() { } function setup() { - createCanvas(600, 600, WEBGL); + createCanvas(windowWidth, windowHeight, WEBGL); camera = createCamera(); red = color(0xbf, 0x00, 0x00); } +function windowResized() { + resizeCanvas(windowWidth, windowHeight); +} + function draw() { orbitControl(); background(50); @@ -29,9 +38,12 @@ function draw() { if (physics) move_charges(charges); draw_charges(sphere_radius); - draw_sphere(sphere_radius, 25); if (skeleton) draw_skeleton(sphere_radius); - if (planes) draw_planes(sphere_radius); + if (polyhedron) { + if (physics || faces.length === 0) find_faces(); + draw_faces(sphere_radius); + } + draw_sphere(sphere_radius, 25); } function face_dist_sq([v1, v2, v3]) { @@ -39,8 +51,8 @@ function face_dist_sq([v1, v2, v3]) { return createVector(camera.eyeX, camera.eyeY, camera.eyeZ).sub(center).magSq(); }; -function draw_planes(radius) { - let faces = []; +function find_faces() { + faces = []; for (let i = 2; i < charges.length; i += 1) { for (let j = 1; j < i; j += 1) { for (let k = 0; k < j; k += 1) { @@ -53,6 +65,7 @@ function draw_planes(radius) { // ... by checking if the other vertices are on the same // side of the plane generated by p1 p2 p3 let plane_separates_vertices = false; + let euler_formula = false; for (let r = 1; r < charges.length; r += 1) { for (let s = 0; s < r; s += 1) { if ( @@ -85,30 +98,32 @@ function draw_planes(radius) { ); plane_separates_vertices ||= t >= 0 && t <= 1; if (plane_separates_vertices) break; + euler_formula ||= charges.length * 2 - faces.length == 4; + if (euler_formula) break; } - if (plane_separates_vertices) break; + if (plane_separates_vertices || euler_formula) break; } + if (euler_formula) return; if (!plane_separates_vertices) { - faces.push([ - p5.Vector.mult(p1, radius), - p5.Vector.mult(p2, radius), - p5.Vector.mult(p3, radius), - ]); + faces.push([p1, p2, p3]); } } } } +} + +function draw_faces(radius) { // fix OpenGL stacking alpha behaviour faces.sort((a, b) => face_dist_sq(b) - face_dist_sq(a)); push(); strokeWeight(2); stroke(0x00); - for ([v1, v2, v3] of faces) { + for ([p1, p2, p3] of faces) { fill(0xbf, 0x7f); beginShape(TRIANGLES); - vertex(v1.x, v1.y, v1.z); - vertex(v2.x, v2.y, v2.z); - vertex(v3.x, v3.y, v3.z); + vertex(p1.x * radius, p1.y * radius, p1.z * radius); + vertex(p2.x * radius, p2.y * radius, p2.z * radius); + vertex(p3.x * radius, p3.y * radius, p3.z * radius); endShape(); } pop(); @@ -176,11 +191,14 @@ function draw_sphere(radius, n_axis_circles) { stroke(0x3f); noFill(); + if (surface === SURFACE_NONE) n_axis_circles = 0; + else if (surface === SURFACE_EARTH) n_axis_circles = 2; + push(); rotateX(TAU / 4); draw_circles( radius, - earth ? 2 : n_axis_circles, + n_axis_circles, color(0x00, 0x9f, 0xff), color(0xff, 0x9f, 0x00), ); @@ -189,13 +207,13 @@ function draw_sphere(radius, n_axis_circles) { rotateY(TAU / 4); draw_circles( radius, - earth ? 2 : n_axis_circles, + n_axis_circles, color(0xff, 0x00, 0xff), color(0x00, 0xff, 0x00), ); pop(); - if (earth) { + if (surface === SURFACE_EARTH) { noStroke(); noFill(); tint(0xff, 0x9f); @@ -239,16 +257,20 @@ function keyPressed() { if (key == ' ') { physics = !physics; } else if (key == 'd') { - earth = !earth; + surface = (surface + 1) % 3; } else if (key == 'f') { skeleton = !skeleton; } else if (key == 'g') { - planes = !planes; + polyhedron = !polyhedron; } else if (key >= '0' && key <= '9') { - make_charges(int(key)); + make_charges(Math.pow(int(key), 2)); + faces = []; } } // TODO draw faces // algorithm: choose 3 vertices until 2-partition of other vertices has one empty set // done when V - E + F = 2. V is known. count E and F while creating faces +// when the graph is finished: E = F * 3 / 2 +// V - E + F = V - F * 3 / 2 + F = V - F / 2 +// V * 2 - F = 4