revisited the donut sphere gif to improve the lighting.
| //by Jo | |
| //newer version: https://dribbble.com/shots/6882529-Tori-Spheres | |
| //original version: https://twitter.com/jn3008/status/1145009502426730498 | |
| float t, tt; | |
| void setup() { | |
| size(800, 600, P3D); | |
| smooth(8); | |
| ortho(); | |
| noStroke(); | |
| fill(255); | |
| sphereDetail(40); | |
| } | |
| void draw() { | |
| t = mouseX*1.0/width; | |
| translate(width/2, height/2); | |
| if (2*t<1) { | |
| tt = 2*t; | |
| background(20); | |
| float pct = map(cos(TWO_PI*ease(tt, 0.8)), 1, -1, 1, 0); | |
| lights_(100+150*pct, 150*(1-pct)); | |
| } else { | |
| tt = 2*t-1; | |
| background(250); | |
| float pct = map(cos(TWO_PI*ease(tt, 0.8)), 1, -1, 1, 0); | |
| lights_(20*pct, 40*(1-pct)); | |
| } | |
| torus(); | |
| } | |
| void torus() { | |
| //torus made by revolving a circle of radius r along the circumference of a larger circle of radius R | |
| float R = 155; | |
| float r = R*0.4; | |
| float R_=R*pow((R+r)/(R-r), tt); | |
| float r_=R_*0.4; | |
| float sphere_radius = sq(R_-r_)/(R_+r_); | |
| donut(R_, r_); | |
| if (2*tt > 1) //sphere appears after the donut has completed a 1/4 revolution about the x-axis | |
| sphere(sphere_radius); | |
| noLights(); | |
| } | |
| void donut(float R, float r) { | |
| int nR = 50; //number of slices on the circle R. | |
| int nr = 50; //number of slices on the circle r. Increasing these will improve quality but run slower | |
| for (int i = 0; i < nR; i++) { | |
| //angles on the circle R | |
| float a1_R = i*TWO_PI/nR; | |
| float a2_R = (i+1)*TWO_PI/nR; | |
| for (int j = 0; j < nr; j++) { | |
| //angles on the circle r | |
| float a1_r = j*TWO_PI/nr; | |
| float a2_r = (j+1)*TWO_PI/nr; | |
| float R1 = R-r*cos(a1_r); | |
| float R2 = R-r*cos(a2_r); | |
| //squares on the surface of the torus | |
| //stroke(255, 0, 0); //un-comment this to see the squares | |
| beginShape(); | |
| vert(R1*cos(a1_R), R1*sin(a1_R), r*sin(a1_r)); | |
| vert(R1*cos(a2_R), R1*sin(a2_R), r*sin(a1_r)); | |
| vert(R2*cos(a2_R), R2*sin(a2_R), r*sin(a2_r)); | |
| vert(R2*cos(a1_R), R2*sin(a1_R), r*sin(a2_r)); | |
| endShape(CLOSE); | |
| } | |
| } | |
| } | |
| void vert(float x, float y, float z) { //transforms and colours the vertex | |
| PVector v = new PVector(x, y, z); | |
| v = rotX(v, PI*ease(tt, 2)*(t>0.5?-1:1)); | |
| vertex(v.x, v.y, v.z); | |
| } | |
| void lights_(float C1, float C2) { | |
| ambientLight(C1, C1, C1); | |
| directionalLight(C2, C2, C2, 0, 0, -1); | |
| lightFalloff(1, 0, 0); | |
| lightSpecular(0, 0, 0); | |
| } | |
| float ease(float p, float g) { | |
| if (p < 0.5) | |
| return 0.5 * pow(2*p, g); | |
| else | |
| return 1 - 0.5 * pow(2*(1 - p), g); | |
| } | |
| float softplus(float q, float p) { | |
| float qq = q+p; | |
| if (qq<=0) { | |
| return 0; | |
| } | |
| if (qq>=2*p) { | |
| return qq-p; | |
| } | |
| return 1/(4*p)*qq*qq; | |
| } | |
| PVector rotY(PVector v, float th) { //matrix rotation about y-axis | |
| return new PVector(v.x*cos(th)+v.z*sin(th), v.y, v.z*cos(th)-v.x*sin(th)); | |
| } | |
| PVector rotX(PVector v, float th) { | |
| return new PVector(v.x, v.y*cos(th)-v.z*sin(th), v.y*sin(th)+v.z*cos(th)); | |
| } | |
| void push() { | |
| pushMatrix(); | |
| pushStyle(); | |
| } | |
| void pop() { | |
| popStyle(); | |
| popMatrix(); | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment