commit 8319d127a552e4d67bd708fdf85ff3ea00f1d985 Author: Rokas Puzonas Date: Thu May 11 21:23:10 2023 +0300 initial commit diff --git a/README.md b/README.md new file mode 100644 index 0000000..77ab433 --- /dev/null +++ b/README.md @@ -0,0 +1,3 @@ +# Spinning donut + +Source: https://www.a1k0n.net/2011/07/20/donut-math.html diff --git a/donut b/donut new file mode 100755 index 0000000..2d27b1d Binary files /dev/null and b/donut differ diff --git a/donut.c b/donut.c new file mode 100644 index 0000000..ab6acf8 --- /dev/null +++ b/donut.c @@ -0,0 +1,77 @@ +#include "math.h" +#include "stdio.h" + +const float theta_spacing = 0.07; +const float phi_spacing = 0.02; + +const int screen_width = 50; +const int screen_height = 50; + +const float R1 = 1; +const float R2 = 2; +const float K2 = 5; +const float K1 = screen_width*K2*3/(8*(R1+R2)); + +void render_frame(float A, float B) { + // Pre compute values that are used a lot + float cosA = cosf(A), sinA = sinf(A); + float cosB = cosf(B), sinB = sinf(B); + + // Create output and depth buffers + char output[screen_width][screen_height]; + float zbuffer[screen_width][screen_height]; + + // Initialize output and depth buffers to zero + for (int i = 0; i < screen_width; i++) { + for (int j = 0; j < screen_height; j++) { + output[i][j] = ' '; + zbuffer[i][j] = 0; + } + } + + for (float theta=0; theta < 2*M_PI; theta += theta_spacing) { + float costheta = cosf(theta), sintheta = sinf(theta); + + for (float phi = 0; phi < 2*M_PI; phi += phi_spacing) { + float cosphi = cosf(phi), sinphi = sinf(phi); + + float circlex = R2 + R1*costheta; + float circley = R1*sintheta; + + float x = circlex*(cosB*cosphi + sinA*sinB*sinphi) - circley*cosA*cosB; + float y = circlex*(sinB*cosphi - sinA*cosB*sinphi) + circley*cosA*cosB; + float z = K2 + cosA*circlex*sinphi + circley*sinA; + float ooz = 1/z; // "one over z" + + int xp = (int) ((float)screen_width/2 + K1*ooz*x); + int yp = (int) ((float)screen_height/2 - K1*ooz*y); + + float L = cosphi*costheta*sinB - cosA*costheta*sinA*sinphi - sinA*sintheta + cosB*(cosA*sintheta - costheta*sinA*sinphi); + if (L > 0) { + if (ooz > zbuffer[yp][xp]) { + zbuffer[yp][xp] = ooz; + int luminance_index = L*8; + output[yp][xp] = ".,-~:;=!*#$@"[luminance_index]; + } + } + } + } + + printf("\x1b[H"); + for (int j = 0; j < screen_height; j++) { + for (int i = 0; i < screen_width; i++) { + putchar(output[i][j]); + } + putchar('\n'); + } +} + +int main() { + float A = 0; + float B = 0; + while (1) { + render_frame(A, B); + A += 0.04/20; + B += 0.02/20; + } +}