{"id":22495257,"url":"https://github.com/chitangchin/rotateadonut","last_synced_at":"2025-03-27T21:16:11.100Z","repository":{"id":263440878,"uuid":"890406249","full_name":"chitangchin/RotateADonut","owner":"chitangchin","description":"Rotating Donut","archived":false,"fork":false,"pushed_at":"2024-11-18T14:55:25.000Z","size":21,"stargazers_count":1,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"master","last_synced_at":"2025-02-01T23:38:52.579Z","etag":null,"topics":["3d","csharp","fun","math","mathematics","torus"],"latest_commit_sha":null,"homepage":"","language":"C#","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/chitangchin.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE.txt","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2024-11-18T14:11:27.000Z","updated_at":"2024-11-18T15:21:07.000Z","dependencies_parsed_at":"2024-11-19T04:57:11.232Z","dependency_job_id":null,"html_url":"https://github.com/chitangchin/RotateADonut","commit_stats":null,"previous_names":["chitangchin/rotateadonut"],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/chitangchin%2FRotateADonut","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/chitangchin%2FRotateADonut/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/chitangchin%2FRotateADonut/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/chitangchin%2FRotateADonut/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/chitangchin","download_url":"https://codeload.github.com/chitangchin/RotateADonut/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":245924507,"owners_count":20694730,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["3d","csharp","fun","math","mathematics","torus"],"created_at":"2024-12-06T19:26:36.229Z","updated_at":"2025-03-27T21:16:11.062Z","avatar_url":"https://github.com/chitangchin.png","language":"C#","funding_links":[],"categories":[],"sub_categories":[],"readme":"# ASCII Donut in C#\n\n[![Test Validation](https://github.com/chitangchin/RotateADonut/actions/workflows/TestValidation.yml/badge.svg)](https://github.com/chitangchin/RotateADonut/actions/workflows/TestValidation.yml)\n\nThis project is a C# console application that renders an animated rotating 3D donut (torus) using ASCII characters. It utilizes mathematical formulas to project 3D points onto a 2D plane and updates the console to animate the donut.\n\n![2024-11-1809-14-39-ezgif com-resize](https://github.com/user-attachments/assets/2a959222-e980-40ba-b534-4f6b2636cdd5)\n\n## Table of Contents\n\n- [Introduction](#introduction)\n- [How It Works](#how-it-works)\n- [Code Explanation](#code-explanation)\n  - [Variables Initialization](#variables-initialization)\n  - [Main Loop](#main-loop)\n  - [Inner Loop Calculations](#inner-loop-calculations)\n  - [Rendering the Frame](#rendering-the-frame)\n  - [Updating Rotation Angles](#updating-rotation-angles)\n- [Running the Program](#running-the-program)\n- [Mathematical Detail](#mathematical-detail)\n\n## Introduction\n\nThis program demonstrates how to create a simple 3D animation in the console by rendering a rotating donut using ASCII characters. It involves 3D math, projections, and an understanding of how to manipulate the console output.\n\n## How It Works\n\nThe program calculates the 3D coordinates of points on a torus (donut shape), applies rotation transformations, projects them onto a 2D plane, calculates luminance for shading, and updates the console buffer to display the animation.\n\n## Code Explanation\n\nHere's the full code:\n\n```csharp\nfloat A = 0, B = 0;\ndouble i, j;\nfloat[] z = new float[1760];\nchar[] b = new char[1760];\n\nConsole.WriteLine(\"\\x1b[2J\");\n\nfor (; ; )\n{\n    Array.Fill(b, ' ');\n    Array.Fill(z, 0);\n\n    for (j = 0; j \u003c 6.28; j += 0.07)\n    {\n        for (i = 0; i \u003c 6.28; i += 0.02)\n        {\n            float c = (float)Math.Sin(i);\n            float d = (float)Math.Cos(j);\n            float e = (float)Math.Sin(A);\n            float f = (float)Math.Sin(j);\n            float g = (float)Math.Cos(A);\n            float h = d + 2;\n            float D = 1f / (c * h * e + f * g + 5);\n            float l = (float)Math.Cos(i);\n            float m = (float)Math.Cos(B);\n            float n = (float)Math.Sin(B);\n            float t = c * h * g - f * e;\n\n            int x = (int)(40 + 30 * D * (l * h * m - t * n));\n            int y = (int)(12 + 15 * D * (l * h * n + t * m));\n            int o = x + 80 * y;\n\n            int N = (int)(8 * ((f * e - c * d * g) * m - c * d * e - f * g - l * d * n));\n\n            if (22 \u003e y \u0026\u0026 y \u003e 0 \u0026\u0026 x \u003e 0 \u0026\u0026 80 \u003e x \u0026\u0026 D \u003e z[o])\n            {\n                z[o] = D;\n                b[o] = \".,-~:;=!*#$@\"[Math.Max(0, Math.Min(11, N))];\n            }\n        }\n    }\n\n    Console.SetCursorPosition(0, 0);\n\n    for (int k = 0; k \u003c 1760; k++)\n    {\n        Console.Write(k % 80 != 0 ? b[k] : '\\n');\n    }\n\n    A += 0.04f;\n    B += 0.02f;\n\n    System.Threading.Thread.Sleep(30);\n}\n```\n\n### Variables Initialization\n\n- `float A = 0, B = 0;`  \n  These variables represent the rotation angles of the donut around the X-axis (`A`) and Z-axis (`B`).\n\n- `double i, j;`  \n  Loop variables used for iterating over the torus surface.\n\n- `float[] z = new float[1760];`  \n  Depth buffer (`z-buffer`) to handle occlusion. Initialized to zero.\n\n- `char[] b = new char[1760];`  \n  Screen buffer to store ASCII characters for each frame.\n\n- `Console.WriteLine(\"\\x1b[2J\");`  \n  Clears the console screen.\n\n### Main Loop\n\nThe infinite loop `for (; ; )` runs the animation continuously.\n\n```csharp\nfor (; ; )\n{\n    // Clear buffers\n    Array.Fill(b, ' ');\n    Array.Fill(z, 0);\n\n    // Rest of the code...\n}\n```\n\n- `Array.Fill(b, ' ');`  \n  Fills the screen buffer with spaces.\n\n- `Array.Fill(z, 0);`  \n  Resets the depth buffer.\n\n### Inner Loop Calculations\n\nThe nested loops iterate over the angles `j` and `i` to calculate points on the torus surface.\n\n```csharp\nfor (j = 0; j \u003c 6.28; j += 0.07)\n{\n    for (i = 0; i \u003c 6.28; i += 0.02)\n    {\n        // Calculations...\n    }\n}\n```\n\n- **Calculating Sines and Cosines:**\n\n  ```csharp\n  float c = (float)Math.Sin(i);\n  float d = (float)Math.Cos(j);\n  float e = (float)Math.Sin(A);\n  float f = (float)Math.Sin(j);\n  float g = (float)Math.Cos(A);\n  float l = (float)Math.Cos(i);\n  float m = (float)Math.Cos(B);\n  float n = (float)Math.Sin(B);\n  ```\n\n- **Intermediate Variables:**\n\n  - `h = d + 2;`  \n    A helper variable used in the calculation of `x`, `y`, and `D`.\n\n  - `D = 1f / (c * h * e + f * g + 5);`  \n    Calculates the depth factor (`ooz`), which is used for scaling and depth buffering.\n\n  - `t = c * h * g - f * e;`  \n    Another helper variable for coordinate transformations.\n\n- **Calculating Screen Coordinates:**\n\n  ```csharp\n  int x = (int)(40 + 30 * D * (l * h * m - t * n));\n  int y = (int)(12 + 15 * D * (l * h * n + t * m));\n  int o = x + 80 * y;\n  ```\n\n  - `x` and `y` are the projected 2D screen coordinates.\n  - `o` is the index in the buffer arrays corresponding to the `(x, y)` position.\n\n- **Calculating Luminance (`N`):**\n\n  ```csharp\n  int N = (int)(8 * ((f * e - c * d * g) * m - c * d * e - f * g - l * d * n));\n  ```\n\n  - `N` determines the luminance of the point, which is used to select an ASCII character for shading.\n\n### Rendering the Frame\n\n- **Updating Buffers:**\n\n  ```csharp\n  if (22 \u003e y \u0026\u0026 y \u003e 0 \u0026\u0026 x \u003e 0 \u0026\u0026 80 \u003e x \u0026\u0026 D \u003e z[o])\n  {\n      z[o] = D;\n      b[o] = \".,-~:;=!*#$@\"[Math.Max(0, Math.Min(11, N))];\n  }\n  ```\n\n  - Checks if the point is within the screen boundaries.\n  - Updates the depth buffer `z[o]` and the screen buffer `b[o]` if the current point is closer to the viewer.\n\n- **Displaying the Frame:**\n\n  ```csharp\n  Console.SetCursorPosition(0, 0);\n\n  for (int k = 0; k \u003c 1760; k++)\n  {\n      Console.Write(k % 80 != 0 ? b[k] : '\\n');\n  }\n  ```\n\n  - Resets the cursor to the top-left corner.\n  - Writes the contents of the screen buffer to the console.\n\n### Updating Rotation Angles\n\n```csharp\nA += 0.04f;\nB += 0.02f;\n```\n\n- Increment the rotation angles to animate the donut's rotation over time.\n\n### Frame Rate Control\n\n```csharp\nSystem.Threading.Thread.Sleep(30);\n```\n\n- Pauses the loop for 30 milliseconds to control the frame rate of the animation.\n\n## Running the Program\n\n1. **Set Up the Environment:**\n   - Ensure you have .NET installed on your system.\n   - Use an IDE like Visual Studio or Visual Studio Code.\n\n2. **Create a Console App:**\n   - Create a new C# Console Application project.\n\n3. **Replace the Code:**\n   - Copy and paste the provided code into your `Program.cs` file.\n\n4. **Run the Application:**\n   - Build and run the project.\n   - You should see the animated ASCII donut in the console window.\n\n## Mathematical Detail\n\nThe program simulates a 3D torus by calculating the coordinates of points on its surface and projecting them onto a 2D plane.\n\n### Torus Parametric Equations\n\nA torus can be represented parametrically with two angles, `i` (theta) and `j` (phi):\n\n- **3D Coordinates:**\n\n  ```plaintext\n  x = (R2 + R1 * cos(i)) * cos(j)\n  y = (R2 + R1 * cos(i)) * sin(j)\n  z = R1 * sin(i)\n  ```\n\n  - `R1` is the radius of the tube.\n  - `R2` is the distance from the center of the tube to the center of the torus.\n\n### Rotation Transformations\n\n- The torus is rotated around the X-axis and Z-axis using rotation matrices.\n- The rotations are controlled by angles `A` and `B`.\n\n### Projection onto 2D Plane\n\n- The 3D coordinates are projected onto a 2D plane using perspective projection.\n- Depth (`D`) is calculated to simulate the effect of perspective and handle occlusion.\n\n### Luminance Calculation\n\n- The luminance `N` is calculated based on the surface normal and a light source direction.\n- Different ASCII characters represent different levels of brightness.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fchitangchin%2Frotateadonut","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fchitangchin%2Frotateadonut","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fchitangchin%2Frotateadonut/lists"}