Created
September 22, 2013 17:52
-
-
Save reuk/6662224 to your computer and use it in GitHub Desktop.
hypercube, implementation inspired by http://steve.hollasch.net/thesis/chapter4.html
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
class Vec4 { | |
float x, y, z, w; | |
Vec4(float a, float b, float c, float d) { | |
x = a; | |
y = b; | |
z = c; | |
w = d; | |
} | |
void mul(float a) { | |
x *= a; | |
y *= a; | |
z *= a; | |
w *= a; | |
} | |
void div(float a) { | |
x /= a; | |
y /= a; | |
z /= a; | |
w /= a; | |
} | |
float lengthSquared() { | |
return x * x + y * y + z * z + w * w; | |
} | |
float length() { | |
return sqrt(lengthSquared()); | |
} | |
void normalize() { | |
div(length()); | |
} | |
} | |
class Matrix4 { | |
Vec4 a, b, c, d; | |
Matrix4(Vec4 wa, Vec4 wb, Vec4 wc, Vec4 wd) { | |
a = wa; | |
b = wb; | |
c = wc; | |
d = wd; | |
} | |
} | |
float dot(Vec4 a, Vec4 b) { | |
return a.x * b.x + a.y * b.y + a.z * b.z + a.w * b.w; | |
} | |
Vec4 cross(Vec4 a, Vec4 b, Vec4 c) { | |
return new Vec4( | |
a.y * (b.z * c.w - c.z * b.w) - a.z * (b.y * c.w - c.y * b.w) + a.w * (b.y * c.z - c.y * b.z), | |
-a.x * (b.z * c.w - c.z * b.w) + a.z * (b.x * c.w - c.x * b.w) - a.w * (b.x * c.z - c.x * b.z), | |
a.x * (b.y * c.w - c.y * b.w) - a.y * (b.x * c.w - c.x * b.w) + a.w * (b.x * c.y - c.x * b.y), | |
-a.x * (b.y * c.z - c.y * b.z) + a.y * (b.x * c.z - c.x * b.z) - a.z * (b.x * c.y - c.x * b.y) | |
); | |
} | |
Vec4 sub(Vec4 a, Vec4 b) { | |
return new Vec4( | |
a.x - b.x, | |
a.y - b.y, | |
a.z - b.z, | |
a.w - b.w | |
); | |
} | |
PVector fourToThree(Vec4 pt, Vec4 from, float vAngle, Matrix4 mat) { | |
final float T = 1 / tan(vAngle / 2); | |
final Vec4 V = sub(pt, from); | |
final float S = T / dot(V, mat.d); | |
return new PVector( | |
S * dot(V, mat.a), | |
S * dot(V, mat.b), | |
S * dot(V, mat.c) | |
); | |
} | |
Matrix4 calcMatrix4(Vec4 from, Vec4 to, Vec4 up, Vec4 over) { | |
Vec4 wd = sub(to, from); | |
wd.normalize(); | |
Vec4 wa = cross(up, over, wd); | |
wa.normalize(); | |
Vec4 wb = cross(over, wd, wa); | |
wb.normalize(); | |
final Vec4 WC = cross(wd, wa, wb); | |
return new Matrix4(wa, wb, WC, wd); | |
} | |
Vec4 FROM4 = new Vec4(4, 0, 0, 0); | |
Vec4 TO4 = new Vec4(0, 0, 0, 0); | |
Vec4 UP4 = new Vec4(0, 1, 0, 0); | |
Vec4 OVER4 = new Vec4(0, 0, 1, 0); | |
float THETA4 = PI / 4; | |
final PVector TO3 = new PVector(0, 0, 0); | |
final PVector UP3 = new PVector(0, 1, 0); | |
final float THETA3 = PI / 4; | |
Matrix4 MAT; | |
void vertex(PVector a) {vertex(a.x, a.y, a.z);} | |
void vertex(Vec4 a) {vertex(fourToThree(a, FROM4, THETA4, MAT));} | |
void setup() { | |
size(500, 500, P3D); | |
frameRate(25); | |
} | |
void draw() { | |
translate(width / 2, height / 2); | |
background(255); | |
noFill(); | |
stroke(0); | |
strokeWeight(3); | |
noSmooth(); | |
final int LOOPLENGTH = 40; | |
final float RATIO = ((frameCount % LOOPLENGTH) + 1) / float(LOOPLENGTH); | |
FROM4 = new Vec4(4 * sin(RATIO * PI / 2), 0, 4 * cos(RATIO * PI / 2), 0); | |
MAT = calcMatrix4(FROM4, TO4, UP4, OVER4); | |
rotateY(-RATIO * PI / 2); | |
rotateX(RATIO * PI / 2); | |
scale(150); | |
final float RADIUS = 1; | |
for (int j = 0; j != 4; ++j) { | |
final float C = ((j % 4) / 2) == 1 ? RADIUS : -RADIUS; | |
final float D = (((j + 1) % 4) / 2) == 1 ? RADIUS : -RADIUS; | |
beginShape(); | |
for (int i = 0; i != 4; ++i) { | |
final float A = ((i % 4) / 2) == 1 ? RADIUS : -RADIUS; | |
final float B = (((i + 1) % 4) / 2) == 1 ? RADIUS : -RADIUS; | |
vertex(new Vec4(A, B, C, D)); | |
} | |
endShape(CLOSE); | |
beginShape(); | |
for (int i = 0; i != 4; ++i) { | |
final float A = ((i % 4) / 2) == 1 ? RADIUS : -RADIUS; | |
final float B = (((i + 1) % 4) / 2) == 1 ? RADIUS : -RADIUS; | |
vertex(new Vec4(A, C, B, D)); | |
} | |
endShape(CLOSE); | |
beginShape(); | |
for (int i = 0; i != 4; ++i) { | |
final float A = ((i % 4) / 2) == 1 ? RADIUS : -RADIUS; | |
final float B = (((i + 1) % 4) / 2) == 1 ? RADIUS : -RADIUS; | |
vertex(new Vec4(A, C, D, B)); | |
} | |
endShape(CLOSE); | |
} | |
// saveFrame("###-hyper.png"); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment