hide sphere; euler's forumla trick; cache faces
This commit is contained in:
parent
cec27160f4
commit
34e1de68f1
1 changed files with 45 additions and 23 deletions
68
sketch.js
68
sketch.js
|
@ -2,13 +2,18 @@ let camera;
|
||||||
let red;
|
let red;
|
||||||
|
|
||||||
let charges = [];
|
let charges = [];
|
||||||
|
let faces = [];
|
||||||
|
|
||||||
let sphere_radius = 200;
|
let sphere_radius = 200;
|
||||||
|
|
||||||
|
const SURFACE_NONE = 0;
|
||||||
|
const SURFACE_CIRCLES = 1;
|
||||||
|
const SURFACE_EARTH = 2;
|
||||||
|
|
||||||
|
let surface = SURFACE_CIRCLES;
|
||||||
let physics = false;
|
let physics = false;
|
||||||
let earth = false;
|
|
||||||
let skeleton = false;
|
let skeleton = false;
|
||||||
let planes = false;
|
let polyhedron = false;
|
||||||
|
|
||||||
|
|
||||||
function preload() {
|
function preload() {
|
||||||
|
@ -16,11 +21,15 @@ function preload() {
|
||||||
}
|
}
|
||||||
|
|
||||||
function setup() {
|
function setup() {
|
||||||
createCanvas(600, 600, WEBGL);
|
createCanvas(windowWidth, windowHeight, WEBGL);
|
||||||
camera = createCamera();
|
camera = createCamera();
|
||||||
red = color(0xbf, 0x00, 0x00);
|
red = color(0xbf, 0x00, 0x00);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function windowResized() {
|
||||||
|
resizeCanvas(windowWidth, windowHeight);
|
||||||
|
}
|
||||||
|
|
||||||
function draw() {
|
function draw() {
|
||||||
orbitControl();
|
orbitControl();
|
||||||
background(50);
|
background(50);
|
||||||
|
@ -29,9 +38,12 @@ function draw() {
|
||||||
if (physics) move_charges(charges);
|
if (physics) move_charges(charges);
|
||||||
|
|
||||||
draw_charges(sphere_radius);
|
draw_charges(sphere_radius);
|
||||||
draw_sphere(sphere_radius, 25);
|
|
||||||
if (skeleton) draw_skeleton(sphere_radius);
|
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]) {
|
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();
|
return createVector(camera.eyeX, camera.eyeY, camera.eyeZ).sub(center).magSq();
|
||||||
};
|
};
|
||||||
|
|
||||||
function draw_planes(radius) {
|
function find_faces() {
|
||||||
let faces = [];
|
faces = [];
|
||||||
for (let i = 2; i < charges.length; i += 1) {
|
for (let i = 2; i < charges.length; i += 1) {
|
||||||
for (let j = 1; j < i; j += 1) {
|
for (let j = 1; j < i; j += 1) {
|
||||||
for (let k = 0; k < j; k += 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
|
// ... by checking if the other vertices are on the same
|
||||||
// side of the plane generated by p1 p2 p3
|
// side of the plane generated by p1 p2 p3
|
||||||
let plane_separates_vertices = false;
|
let plane_separates_vertices = false;
|
||||||
|
let euler_formula = false;
|
||||||
for (let r = 1; r < charges.length; r += 1) {
|
for (let r = 1; r < charges.length; r += 1) {
|
||||||
for (let s = 0; s < r; s += 1) {
|
for (let s = 0; s < r; s += 1) {
|
||||||
if (
|
if (
|
||||||
|
@ -85,30 +98,32 @@ function draw_planes(radius) {
|
||||||
);
|
);
|
||||||
plane_separates_vertices ||= t >= 0 && t <= 1;
|
plane_separates_vertices ||= t >= 0 && t <= 1;
|
||||||
if (plane_separates_vertices) break;
|
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) {
|
if (!plane_separates_vertices) {
|
||||||
faces.push([
|
faces.push([p1, p2, p3]);
|
||||||
p5.Vector.mult(p1, radius),
|
|
||||||
p5.Vector.mult(p2, radius),
|
|
||||||
p5.Vector.mult(p3, radius),
|
|
||||||
]);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function draw_faces(radius) {
|
||||||
// fix OpenGL stacking alpha behaviour
|
// fix OpenGL stacking alpha behaviour
|
||||||
faces.sort((a, b) => face_dist_sq(b) - face_dist_sq(a));
|
faces.sort((a, b) => face_dist_sq(b) - face_dist_sq(a));
|
||||||
push();
|
push();
|
||||||
strokeWeight(2);
|
strokeWeight(2);
|
||||||
stroke(0x00);
|
stroke(0x00);
|
||||||
for ([v1, v2, v3] of faces) {
|
for ([p1, p2, p3] of faces) {
|
||||||
fill(0xbf, 0x7f);
|
fill(0xbf, 0x7f);
|
||||||
beginShape(TRIANGLES);
|
beginShape(TRIANGLES);
|
||||||
vertex(v1.x, v1.y, v1.z);
|
vertex(p1.x * radius, p1.y * radius, p1.z * radius);
|
||||||
vertex(v2.x, v2.y, v2.z);
|
vertex(p2.x * radius, p2.y * radius, p2.z * radius);
|
||||||
vertex(v3.x, v3.y, v3.z);
|
vertex(p3.x * radius, p3.y * radius, p3.z * radius);
|
||||||
endShape();
|
endShape();
|
||||||
}
|
}
|
||||||
pop();
|
pop();
|
||||||
|
@ -176,11 +191,14 @@ function draw_sphere(radius, n_axis_circles) {
|
||||||
stroke(0x3f);
|
stroke(0x3f);
|
||||||
noFill();
|
noFill();
|
||||||
|
|
||||||
|
if (surface === SURFACE_NONE) n_axis_circles = 0;
|
||||||
|
else if (surface === SURFACE_EARTH) n_axis_circles = 2;
|
||||||
|
|
||||||
push();
|
push();
|
||||||
rotateX(TAU / 4);
|
rotateX(TAU / 4);
|
||||||
draw_circles(
|
draw_circles(
|
||||||
radius,
|
radius,
|
||||||
earth ? 2 : n_axis_circles,
|
n_axis_circles,
|
||||||
color(0x00, 0x9f, 0xff),
|
color(0x00, 0x9f, 0xff),
|
||||||
color(0xff, 0x9f, 0x00),
|
color(0xff, 0x9f, 0x00),
|
||||||
);
|
);
|
||||||
|
@ -189,13 +207,13 @@ function draw_sphere(radius, n_axis_circles) {
|
||||||
rotateY(TAU / 4);
|
rotateY(TAU / 4);
|
||||||
draw_circles(
|
draw_circles(
|
||||||
radius,
|
radius,
|
||||||
earth ? 2 : n_axis_circles,
|
n_axis_circles,
|
||||||
color(0xff, 0x00, 0xff),
|
color(0xff, 0x00, 0xff),
|
||||||
color(0x00, 0xff, 0x00),
|
color(0x00, 0xff, 0x00),
|
||||||
);
|
);
|
||||||
pop();
|
pop();
|
||||||
|
|
||||||
if (earth) {
|
if (surface === SURFACE_EARTH) {
|
||||||
noStroke();
|
noStroke();
|
||||||
noFill();
|
noFill();
|
||||||
tint(0xff, 0x9f);
|
tint(0xff, 0x9f);
|
||||||
|
@ -239,16 +257,20 @@ function keyPressed() {
|
||||||
if (key == ' ') {
|
if (key == ' ') {
|
||||||
physics = !physics;
|
physics = !physics;
|
||||||
} else if (key == 'd') {
|
} else if (key == 'd') {
|
||||||
earth = !earth;
|
surface = (surface + 1) % 3;
|
||||||
} else if (key == 'f') {
|
} else if (key == 'f') {
|
||||||
skeleton = !skeleton;
|
skeleton = !skeleton;
|
||||||
} else if (key == 'g') {
|
} else if (key == 'g') {
|
||||||
planes = !planes;
|
polyhedron = !polyhedron;
|
||||||
} else if (key >= '0' && key <= '9') {
|
} else if (key >= '0' && key <= '9') {
|
||||||
make_charges(int(key));
|
make_charges(Math.pow(int(key), 2));
|
||||||
|
faces = [];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO draw faces
|
// TODO draw faces
|
||||||
// algorithm: choose 3 vertices until 2-partition of other vertices has one empty set
|
// 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
|
// 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
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue