Last active
August 21, 2023 09:27
-
-
Save Hachem-H/0b1b6a1ad15dbb85779af9210373e8fb to your computer and use it in GitHub Desktop.
A 3D ASCII-Terminal cube projection.
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
// gcc -o ASCII-Cube -O2 -DNDEBUG -Wall -Wextra -Werror ASCII-Cube.c -lm | |
// ./ASCII-Cube | |
// NOTE: - Resize the terminal to at least 160 columns & 44 rows. | |
// - This does depend on a terminal which supports ASCII escape codes. | |
#include <stdbool.h> | |
#include <string.h> | |
#include <unistd.h> | |
#include <stdio.h> | |
#include <math.h> | |
#define CubeSize 10.f | |
#define BUFFER_WIDTH 160 | |
#define BUFFER_HEIGHT 44 | |
static float ZBuffer[BUFFER_WIDTH*BUFFER_HEIGHT]; | |
static char OutBuffer[BUFFER_WIDTH*BUFFER_HEIGHT]; | |
static float A = 0.00f; | |
static float B = 0.00f; | |
static float C = 0.00f; | |
static float CalculateX(int i, int j, int k) | |
{ | |
return j * sin(A) * sin(B) * cos(C) - | |
k * cos(A) * sin(B) * cos(C) + | |
j * cos(A) * sin(C) + | |
k * sin(A) * sin(C) + | |
i * cos(B) * cos(C); | |
} | |
static float CalculateY(int i, int j, int k) | |
{ | |
return j * cos(A) * cos(C) + | |
k * sin(A) * cos(C) - | |
j * sin(A) * sin(B) * sin(C) + | |
k * cos(A) * sin(B) * sin(C) - | |
i * cos(B) * sin(C); | |
} | |
static float CalculateZ(int i, int j, int k) | |
{ | |
return k * cos(A) * cos(B) - | |
j * sin(A) * cos(B) + | |
i * sin(B); | |
} | |
static void ProjectSurface(float cx, float cy, float cz, char character) | |
{ | |
float x = CalculateX(cx, cy, cz); | |
float y = CalculateY(cx, cy, cz); | |
float z = CalculateZ(cx, cy, cz) + BUFFER_HEIGHT - CubeSize; | |
float zOff = 40; | |
float invZ = 1/z; | |
float xOff = CubeSize*2; | |
int xp = (int)(BUFFER_WIDTH/2 + zOff * invZ * x * 2 - xOff); | |
int yp = (int)(BUFFER_HEIGHT/2 + zOff * invZ * y); | |
unsigned int index = xp + yp * BUFFER_WIDTH; | |
if (index < sizeof(OutBuffer)) | |
if (ZBuffer[index] < invZ) | |
{ | |
ZBuffer[index] = invZ; | |
OutBuffer[index] = character; | |
} | |
} | |
int main() | |
{ | |
printf("\x1b[2J"); | |
while (true) | |
{ | |
memset(OutBuffer, ' ', sizeof(OutBuffer)); | |
memset(ZBuffer, 0x0, sizeof(ZBuffer)); | |
for (float x = -CubeSize; x < CubeSize; x++) | |
for (float y = -CubeSize; y < CubeSize; y++) | |
{ | |
ProjectSurface( x, y, -CubeSize, '.'); | |
ProjectSurface( CubeSize, y, x, '$'); | |
ProjectSurface(-CubeSize, y, -x, '~'); | |
ProjectSurface(-x, y, CubeSize, '@'); | |
ProjectSurface( x, -CubeSize, -y, ';'); | |
} | |
printf("\x1b[H"); | |
for (unsigned int i = 0; i < sizeof(OutBuffer); i++) | |
putchar(i % BUFFER_WIDTH ? OutBuffer[i] : '\n'); | |
A += 0.005f; | |
B += 0.005f; | |
usleep(2000); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment