Copy and paste it into sketchpad.
- Code: Select all
/*
RT : change type of new polygon
F : create new polygon
QWEASD : move selected polygons
XC : move selector box
Z : select a polygon
VB : move selector circle
G : select a vertex, create new link
*/
float face = [], link = [], stiffness = 0.2, metric = [1, 1, 1];
// face[i] = [numberOfEdges, positionVector, orientationVector1,Vector2,Vector3, isSelected]
// link[i] = [indexOfFace1,VertexInFace1, indexOfFace2,VertexInFace2]
int nNew = 3, fIndex = 0, fIndex2 = 0, vIndex1 = 0, vIndex2 = 0;
bool vSelected = false;
float sum = function(a, b) {
return [a[0]+b[0], a[1]+b[1], a[2]+b[2]];
},
dif = function(a, b) {
return [a[0]-b[0], a[1]-b[1], a[2]-b[2]];
},
scal = function(a, b) {
return [a[0]*b, a[1]*b, a[2]*b];
},
dot = function(a, b) { // vector dot vector = scalar
return metric[0]*a[0]*b[0] + metric[1]*a[1]*b[1] + metric[2]*a[2]*b[2];
},
wedge = function(a, b) { // vector wedge vector = bivector
return [a[1]*b[2]-a[2]*b[1],
a[2]*b[0]-a[0]*b[2],
a[0]*b[1]-a[1]*b[0]];
},
dotB = function(a, b) { // vector dot bivector = vector
return [metric[2]*a[2]*b[1] - metric[1]*a[1]*b[2],
metric[0]*a[0]*b[2] - metric[2]*a[2]*b[0],
metric[1]*a[1]*b[0] - metric[0]*a[0]*b[1]];
};
//append(face, [5, [0,0,0], [1,0,0],[0,1,0],[0,0,1], true]);
//append(face, [4, [0,0,2], [1,0,0],[0,0,1],[0,-1,0], false]);
//append(link, [0,1, 1,3]);
float ref = []; // reference polygon
for(int i = 2; i <= 12; i++) {
float radius = 1/(2*sin(PI/i)), angle = 2*PI/i;
ref[i] = [];
for(int j = 0; j < i; j++) {
ref[i][j] = [radius*cos(j*angle), radius*sin(j*angle), 0];
}
}
bool keys = []; int turn = [];
void force = function() {
float velocity = []; // linear and angular
for(int i = 0; i < face.length; i++) {
velocity[i] = [[0,0,0], [0,0,0]];
if(face[i][5]){
if(keys[68]) {
int t = turn[68];
if(t == 87) {
velocity[i][1] = sum(velocity[i][1], [0,0,-0.1]);
} else if(t == 83) {
velocity[i][1] = sum(velocity[i][1], [0,0,0.1]);
} else if(t == 69) {
velocity[i][1] = sum(velocity[i][1], [0,0.1,0]);
} else if(t == 81) {
velocity[i][1] = sum(velocity[i][1], [0,-0.1,0]);
} else {
velocity[i][0] = sum(velocity[i][0], [0.1,0,0]);
}
}
if(keys[65]) {
int t = turn[65];
if(t == 87) {
velocity[i][1] = sum(velocity[i][1], [0,0,0.1]);
} else if(t == 83) {
velocity[i][1] = sum(velocity[i][1], [0,0,-0.1]);
} else if(t == 69) {
velocity[i][1] = sum(velocity[i][1], [0,-0.1,0]);
} else if(t == 81) {
velocity[i][1] = sum(velocity[i][1], [0,0.1,0]);
} else {
velocity[i][0] = sum(velocity[i][0], [-0.1,0,0]);
}
}
if(keys[87]) {
int t = turn[87];
if(t == 68) {
velocity[i][1] = sum(velocity[i][1], [0,0,0.1]);
} else if(t == 65) {
velocity[i][1] = sum(velocity[i][1], [0,0,-0.1]);
} else if(t == 69) {
velocity[i][1] = sum(velocity[i][1], [-0.1,0,0]);
} else if(t == 81) {
velocity[i][1] = sum(velocity[i][1], [0.1,0,0]);
} else {
velocity[i][0] = sum(velocity[i][0], [0,0.1,0]);
}
}
if(keys[83]) {
int t = turn[83];
if(t == 68) {
velocity[i][1] = sum(velocity[i][1], [0,0,-0.1]);
} else if(t == 65) {
velocity[i][1] = sum(velocity[i][1], [0,0,0.1]);
} else if(t == 69) {
velocity[i][1] = sum(velocity[i][1], [0.1,0,0]);
} else if(t == 81) {
velocity[i][1] = sum(velocity[i][1], [-0.1,0,0]);
} else {
velocity[i][0] = sum(velocity[i][0], [0,-0.1,0]);
}
}
if(keys[69]) {
int t = turn[69];
if(t == 68) {
velocity[i][1] = sum(velocity[i][1], [0,-0.1,0]);
} else if(t == 65) {
velocity[i][1] = sum(velocity[i][1], [0,0.1,0]);
} else if(t == 87) {
velocity[i][1] = sum(velocity[i][1], [0.1,0,0]);
} else if(t == 83) {
velocity[i][1] = sum(velocity[i][1], [-0.1,0,0]);
} else {
velocity[i][0] = sum(velocity[i][0], [0,0,0.1]);
}
}
if(keys[81]) {
int t = turn[81];
if(t == 68) {
velocity[i][1] = sum(velocity[i][1], [0,0.1,0]);
} else if(t == 65) {
velocity[i][1] = sum(velocity[i][1], [0,-0.1,0]);
} else if(t == 87) {
velocity[i][1] = sum(velocity[i][1], [-0.1,0,0]);
} else if(t == 83) {
velocity[i][1] = sum(velocity[i][1], [0.1,0,0]);
} else {
velocity[i][0] = sum(velocity[i][0], [0,0,-0.1]);
}
}
}
}
for(int i = 0; i < link.length; i++) {
int f1 = link[i][0], v1 = link[i][1],
f2 = link[i][2], v2 = link[i][3];
float refRadius1 = ref[face[f1][0]][v1],
refRadius2 = ref[face[f2][0]][v2],
radius1 = sum(scal(face[f1][2],refRadius1[0]), scal(face[f1][3],refRadius1[1])),
radius2 = sum(scal(face[f2][2],refRadius2[0]), scal(face[f2][3],refRadius2[1])),
pos1 = sum(face[f1][1], radius1),
pos2 = sum(face[f2][1], radius2),
posRel = dif(pos2, pos1),
F = scal(posRel, stiffness),
T1 = wedge(radius1, F),
T2 = wedge(F, radius2);
velocity[f1][0] = sum(velocity[f1][0], F);
velocity[f2][0] = dif(velocity[f2][0], F);
velocity[f1][1] = sum(velocity[f1][1], T1);
velocity[f2][1] = sum(velocity[f2][1], T2);
}
for(int i = 0; i < face.length; i++) {
face[i][1] = sum(face[i][1], velocity[i][0]);
face[i][2] = sum(face[i][2], dotB(face[i][2], velocity[i][1]));
face[i][3] = sum(face[i][3], dotB(face[i][3], velocity[i][1]));
face[i][4] = sum(face[i][4], dotB(face[i][4], velocity[i][1]));
float sq1 = dot(face[i][2],face[i][2]); // Gram-Schmidt
face[i][3] = dotB(scal(face[i][2],sq1), wedge(face[i][2],face[i][3]));
float sq2 = dot(face[i][3],face[i][3]);
face[i][4] = dotB(scal(face[i][2],sq1), wedge(face[i][2],face[i][4]));
face[i][4] = dotB(scal(face[i][3],sq2), wedge(face[i][3],face[i][4]));
float sq3 = dot(face[i][4],face[i][4]);
face[i][2] = scal(face[i][2], 1/sqrt(abs(sq1)));
face[i][3] = scal(face[i][3], 1/sqrt(abs(sq2)));
face[i][4] = scal(face[i][4], 1/sqrt(abs(sq3)));
}
};
void display = function() {
strokeWeight(1);
stroke(0,255,255);
for(var i = 0; i < link.length; i++) {
int f1 = link[i][0], v1 = link[i][1],
f2 = link[i][2], v2 = link[i][3];
float refRadius1 = ref[face[f1][0]][v1],
refRadius2 = ref[face[f2][0]][v2],
radius1 = sum(scal(face[f1][2],refRadius1[0]), scal(face[f1][3],refRadius1[1])),
radius2 = sum(scal(face[f2][2],refRadius2[0]), scal(face[f2][3],refRadius2[1])),
pos1 = sum(face[f1][1], radius1),
pos2 = sum(face[f2][1], radius2);
if(pos1[0] < 4 && pos2[0] < 4) {
line(200+50*pos1[0], 200-50*pos1[2], 200+50*pos2[0], 200-50*pos2[2]);
}
if(pos1[0] > -4 && pos1[1] > -4 && pos2[0] > -4 && pos2[1] > -4) {
line(500+25*pos1[0], 100-25*pos1[1], 500+25*pos2[0], 100-25*pos2[1]);
line(500+25*pos1[0], 300+25*pos1[1], 500+25*pos2[0], 300+25*pos2[1]);
}
}
if(vSelected && face.length > 0) {
float refRadius = ref[face[fIndex2][0]][vIndex2],
radius = sum(scal(face[fIndex2][2],refRadius[0]), scal(face[fIndex2][3],refRadius[1])),
pos = sum(face[fIndex2][1], radius);
noStroke();
fill(0,255,255,128);
if(pos[0] < 4) {
ellipse(200+50*pos[0], 200-50*pos[2], 20, 20);
}
if(pos[0] > -4 && pos[1] > -4) {
ellipse(500+25*pos[0], 100-25*pos[1], 10, 10);
ellipse(500+25*pos[0], 300+25*pos[1], 10, 10);
}
}
for(var i = 0; i < face.length; i++) {
float pos = [], normal = face[i][4];
for(int j = 0; j < face[i][0]; j++) {
float refRadius = ref[face[i][0]][j],
radius = sum(scal(face[i][2],refRadius[0]), scal(face[i][3],refRadius[1]));
pos[j] = sum(face[i][1], radius);
}
bool inBox = true;
for(int j = 0; j < face[i][0]; j++) {
inBox = inBox && pos[j][0] < 4;
}
if(normal[1] < 0 && inBox) {
if(face[i][5]) {
strokeWeight(1);
stroke(0);
} else {
noStroke();
}
fill(0,255,0,128);
beginShape();
for(int j = 0; j < face[i][0]; j++) {
vertex(200+50*pos[j][0], 200-50*pos[j][2]);
}
endShape(CLOSE);
strokeWeight(3);
stroke(0,0,255);
for(int j = 0; j < face[i][0]; j++) {
point(200+50*pos[j][0], 200-50*pos[j][2]);
}
}
inBox = true;
for(int j = 0; j < face[i][0]; j++) {
inBox = inBox && pos[j][0] > -4 && pos[j][1] > -4;
}
if(normal[2] > 0 && inBox) {
if(face[i][5]) {
strokeWeight(1);
stroke(0);
} else {
noStroke();
}
fill(0,255,0,128);
beginShape();
for(int j = 0; j < face[i][0]; j++) {
vertex(500+25*pos[j][0], 100-25*pos[j][1]);
}
endShape(CLOSE);
strokeWeight(3);
stroke(0,0,255);
for(int j = 0; j < face[i][0]; j++) {
point(500+25*pos[j][0], 100-25*pos[j][1]);
}
}
if(normal[2] < 0 && inBox) {
if(face[i][5]) {
strokeWeight(1);
stroke(0);
} else {
noStroke();
}
fill(0,255,0,128);
beginShape();
for(int j = 0; j < face[i][0]; j++) {
vertex(500+25*pos[j][0], 300+25*pos[j][1]);
}
endShape(CLOSE);
strokeWeight(3);
stroke(0,0,255);
for(int j = 0; j < face[i][0]; j++) {
point(500+25*pos[j][0], 300+25*pos[j][1]);
}
}
}
if(face.length > 0) {
float pos = [];
for(int j = 0; j < face[fIndex][0]; j++) {
float refRadius = ref[face[fIndex][0]][j],
radius = sum(scal(face[fIndex][2],refRadius[0]), scal(face[fIndex][3],refRadius[1]));
pos[j] = sum(face[fIndex][1], radius);
}
strokeWeight(1);
stroke(0);
noFill();
if(pos[vIndex1][0] < 4) {
ellipse(200+50*pos[vIndex1][0], 200-50*pos[vIndex1][2], 10, 10);
}
if(pos[vIndex1][0] > -4 && pos[vIndex1][1] > -4) {
ellipse(500+25*pos[vIndex1][0], 100-25*pos[vIndex1][1], 5, 5);
ellipse(500+25*pos[vIndex1][0], 300+25*pos[vIndex1][1], 5, 5);
}
float selectBox = [400,400, 0,0];
for(int j = 0; j < face[fIndex][0]; j++) {
selectBox[0] = min(selectBox[0], 200+50*pos[j][0]);
selectBox[1] = min(selectBox[1], 200-50*pos[j][2]);
selectBox[2] = max(selectBox[2], 200+50*pos[j][0]);
selectBox[3] = max(selectBox[3], 200-50*pos[j][2]);
}
rect(selectBox[0]-10,selectBox[1]-10, selectBox[2]-selectBox[0]+20,selectBox[3]-selectBox[1]+20);
selectBox = [600,200, 400,0];
for(int j = 0; j < face[fIndex][0]; j++) {
selectBox[0] = min(selectBox[0], 500+25*pos[j][0]);
selectBox[1] = min(selectBox[1], 100-25*pos[j][1]);
selectBox[2] = max(selectBox[2], 500+25*pos[j][0]);
selectBox[3] = max(selectBox[3], 100-25*pos[j][1]);
}
strokeWeight(1);
stroke(0);
noFill();
rect(selectBox[0]-5,selectBox[1]-5, selectBox[2]-selectBox[0]+10,selectBox[3]-selectBox[1]+10);
selectBox = [600,400, 400,200];
for(int j = 0; j < face[fIndex][0]; j++) {
selectBox[0] = min(selectBox[0], 500+25*pos[j][0]);
selectBox[1] = min(selectBox[1], 300+25*pos[j][1]);
selectBox[2] = max(selectBox[2], 500+25*pos[j][0]);
selectBox[3] = max(selectBox[3], 300+25*pos[j][1]);
}
strokeWeight(1);
stroke(0);
noFill();
rect(selectBox[0]-5,selectBox[1]-5, selectBox[2]-selectBox[0]+10,selectBox[3]-selectBox[1]+10);
}
noStroke();
fill(192);
rect(380,0, 40,400);
rect(380,180, 220,40);
fill(0);
text("side view", 0,12);
text("top view", 420,12);
text("bottom view", 420,232);
text(nNew +"-gon", 380,212);
};
void setup() {
background(255);
size(600, 400);
smooth();
frameRate(10);
}
void keyPressed() {
keys[keyCode] = true;
for(int i = 65; i <= 90; i++) {
if(i != keyCode && keys[i] && !turn[i]) {
turn[keyCode] = i;
}
}
if(keyCode == 84) {
nNew++;
if(nNew > 12) {
nNew = 2;
}
} else if(keyCode == 82) {
nNew--;
if(nNew < 2) {
nNew = 12;
}
} else if(keyCode == 70) {
append(face, [nNew, [0,0,0], [1,0,0],[0,1,0],[0,0,1], true]);
} else if(keyCode == 67 && face.length > 0) {
fIndex++;
if(fIndex >= face.length) {
fIndex-= face.length;
}
if(vIndex1 >= face[fIndex][0]) {
vIndex1-= face[fIndex][0];
}
} else if(keyCode == 88 && face.length > 0) {
fIndex--;
if(fIndex < 0) {
fIndex+= face.length;
}
if(vIndex1 >= face[fIndex][0]) {
vIndex1-= face[fIndex][0];
}
} else if(keyCode == 90 && face.length > 0) {
face[fIndex][5] = !face[fIndex][5];
} else if(keyCode == 66 && face.length > 0) {
vIndex1++;
if(vIndex1 >= face[fIndex][0]) {
vIndex1-= face[fIndex][0];
}
} else if(keyCode == 86 && face.length > 0) {
vIndex1--;
if(vIndex1 < 0) {
vIndex1+= face[fIndex][0];
}
} else if(keyCode == 71 && face.length > 0) {
if(vSelected) {
append(link, [fIndex,vIndex1, fIndex2,vIndex2]);
vSelected = false;
} else {
fIndex2 = fIndex;
vIndex2 = vIndex1;
vSelected = true;
}
}
}
void keyReleased() {
keys[keyCode] = false;
turn[keyCode] = 0;
}
void draw() {
force();
background(255);
display();
}