본문 바로가기

프로젝트/C, C++ 프로젝트

Spinning Donut

반응형

 회전하는 도넛 코드이다. 행렬에 대한 이해를 바탕으로 도넛을 그리고, 회전을 시킨 후, 화면에 투영되는 것을 코드로 작성해주면 된다. 수학적인 지식과 코딩에 대한 지식 모두 필요하다. 다음 글을 바탕으로 코드를 작성하였다.

 

spinning donut

 

https://www.a1k0n.net/2011/07/20/donut-math.html

 

Donut math: how donut.c works

Donut math: how donut.c works Jul 20, 2011 [Update 1/13/2021: I wrote a follow-up with some optimizations. ] There has been a sudden resurgence of interest in my "donut" code from 2006, and I've had a couple requests to explain this one. It's been five yea

www.a1k0n.net

 

#include <stdio.h>
#include <math.h>
#include <windows.h>

#define PI 3.141592
#define R1 1
#define R2 2
#define EYE -6
#define SCREEN -4
#define BUFFER_SIZE 6561 // 81x81

void GotoXY(int x, int y) {
	COORD Pos;
	Pos.X = x;
	Pos.Y = y;
	SetConsoleCursorPosition(GetStdHandle(STD_OUTPUT_HANDLE), Pos);
}

int main() {

	double A = 0;
	double B = 0;

	printf("\x1b[2J");
	char b[BUFFER_SIZE];

	while (1){

		double sinA = sin(A);
		double cosA = cos(A);
		double sinB = sin(B);
		double cosB = cos(B);

		double rotation_matrix[3][3] = {
			{cosB,              -sinB,     0},
			{cosA * sinB, cosA * cosB, -sinA},
			{sinA * sinB, sinA * cosB,  cosA}
		};

		memset(b, ' ', BUFFER_SIZE);

		for (double pi = 0; pi < 2 * PI; pi += 0.1) {
			for (double theta = 0; theta < 2 * PI; theta += 0.07) {
				double sinTheta = sin(theta);
				double cosTheta = cos(theta);
				double sinPi = sin(pi);
				double cosPi = cos(pi);

				double pos[3] = {cosPi*(R2+R1*cosTheta), R1*sinTheta, -sinPi*(R2 + R1 * cosTheta)};
				double lumi[3] = {cosTheta, sinPi, 0};
				double pos_with_roatation[3] = {
					pos[0]*rotation_matrix[0][0] + pos[1]*rotation_matrix[1][0] + pos[2]*rotation_matrix[2][0],
					pos[0]*rotation_matrix[0][1] + pos[1]*rotation_matrix[1][1] + pos[2]*rotation_matrix[2][1], 
					pos[0]*rotation_matrix[0][2] + pos[1]*rotation_matrix[1][2] + pos[2]*rotation_matrix[2][2] 
				};

				double L = cosTheta * rotation_matrix[0][1] + sinTheta * rotation_matrix[1][1]
					- sinTheta * rotation_matrix[1][2];
				int x = 40 + 30*(SCREEN - EYE)*pos_with_roatation[0] / (pos_with_roatation[2] - EYE);
				int y = 40 + 30*(SCREEN - EYE)*pos_with_roatation[1] / (pos_with_roatation[2] - EYE);

				if (x >= 0 && x <= 80 && y >= 0 && y <= 80) {
					if (L > 0) {
						b[x + 81 * y] = ".,-~:;=!*#$@"[(int)(8*L)];
					}
				}
			}
		}

		printf("\x1b[H");
		for (int i = 0; i < BUFFER_SIZE; i++) {
			putchar(i%81 ? b[i] : '\n');
		}

		A += 0.1;
		B += 0.05;
	}
}

 

 

 

반응형