Let’s see how to create a Spinning 3D Donut Animation in ASCII Art using only ASCII characters in C++.
The goal is to simulate a 3D donut, rotate it around two axes, and display it using ASCII characters. The donut’s surface is calculated in 3D and then projected into 2D for the terminal display.
The Steps to Build the Animation
1) Setup and Variables
- alpha and beta are the angles that control the rotation of the donut around two axes.
- frame_buffer stores the ASCII characters that represent the donut’s surface.
- depth_buffer keeps track of the depth (distance from the viewer) for each point on the donut.
2) The Animation Loop
a. Clear Buffers
Before each new frame, we reset both the frame_buffer and the depth_buffer (reset to zeros).
memset(frame_buffer, 32, 1760);
memset(depth_buffer, 0, 7040);
b. Donut Points Calculation
The donut’s surface is calculated using trigonometric functions (sin and cos), which generate 3D coordinates. These coordinates are based on two variables, i and j, which define the positions.
x = (R2 + R1 * cos(i)) * cos(j);
y = (R2 + R1 * cos(i)) * sin(j);
z = R1 * sin(i);
c. Apply Rotation
To make the donut spin, we rotate the 3D points around the vertical (alpha) and horizontal (beta) axes.
x = x * cos(alpha) - z * sin(alpha); // Rotate around vertical axis
z = x * sin(alpha) + z * cos(alpha); // Update z-coordinate
d. Projection to 2D
To display in the terminal, we convert the 3D coordinates into 2D using a perspective projection.
x_proj = x / z;
y_proj = y / z;
e. Shading
We calculate the brightness of each point based on its angle to the light source.
brightness = (sin(i) * cos(j) + cos(i) * sin(alpha) + cos(j) * sin(beta));
This formula calculates a brightness value that’s used to pick an appropriate ASCII character, such as @ or
3) Display the Frame
After all points are calculated and shaded, we update the frame_buffer with the corresponding ASCII characters.
The characters are printed in the terminal to create the spinning donut effect. The cursor is moved to the top-left corner before printing each frame to overwrite the previous one.
for (int k = 0; k < 1761; k++) {
putchar(k % 80 ? frame_buffer[k] : 10); // Print line by line
}
4) Rotation and Speed
To make the donut spin smoothly, the angles alpha and beta are slightly incremented after each frame.
alpha += 0.04;
beta += 0.02;
The usleep(30000) function adds a short delay to control the animation speed.
Complete Source Code: Spinning 3D Donut Animation
#include <stdio.h> #include <math.h> #include <string.h> #include <unistd.h> int main() { float alpha = 0, beta = 0; float angle_i, angle_j; int idx; float depth_buffer[1761]; char frame_buffer[1761]; printf("\x1b[2J"); for(;;) { memset(frame_buffer, 32, 1761); memset(depth_buffer, 0, 7040); for(angle_j = 0; angle_j < 6.28; angle_j += 0.07) { for(angle_i = 0; angle_i < 6.28; angle_i += 0.02) { float sine_i = sin(angle_i); float cosine_j = cos(angle_j); float sine_alpha = sin(alpha); float sine_j = sin(angle_j); float cosine_alpha = cos(alpha); float h = cosine_j + 2; float one_over_depth = 1 / (sine_i * h * sine_alpha + sine_j * cosine_alpha + 5); float cosine_i = cos(angle_i); float cosine_beta = cos(beta); float sine_beta = sin(beta); float t = sine_i * h * cosine_alpha - sine_j * sine_alpha; int x_coord = 40 + 30 * one_over_depth * (cosine_i * h * cosine_beta - t * sine_beta); int y_coord = 12 + 15 * one_over_depth * (cosine_i * h * sine_beta + t * cosine_beta); int buffer_index = x_coord + 80 * y_coord; int luminance = 8 * ((sine_j * sine_alpha - sine_i * cosine_j * cosine_alpha) * cosine_beta - sine_i * cosine_j * sine_alpha - sine_j * cosine_alpha - cosine_i * cosine_j * sine_beta); if(22 > y_coord && y_coord > 0 && x_coord > 0 && 80 > x_coord && one_over_depth > depth_buffer[buffer_index]) { depth_buffer[buffer_index] = one_over_depth; frame_buffer[buffer_index] = ".,-~:;=!*#$@"[luminance > 0 ? luminance : 0]; } } } printf("\x1b[H"); for(idx = 0; idx < 1761; idx++) { putchar(idx % 80 ? frame_buffer[idx] : 10); alpha += 0.00004; beta += 0.00002; } usleep(30000); } return 0; }
OutPut:
Conclusion
This Spinning 3D Donut Animation in ASCII Art is an example of how 3D graphics can be rendered using just text. By applying basic trigonometry and perspective projection, you can visualize 3D shapes and create interactive animations in the terminal.
Thanks for visiting codehelping.com and for more such amazing projects visit: Projects Link