-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathrotating_cube.cpp
130 lines (112 loc) · 3.92 KB
/
rotating_cube.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
#include <iostream>
#include <math.h>
#include <string>
#include <windows.h>
#include<vector>
#include<sstream>
using namespace std;
const int screen_width = 160;
const int screen_height = 44;
const float K2 = 100;
const float K1 =50;
const float cubewidth = 20;
const float resolution = 0.2;
const float pi = 3.14159265359;
const float light[3] = {0,1,-1}; // |light| = sqrt(2)
float A = 1.0, B= 0.5, C= 0.0;
string CHARS_LUMINANCE = ".~!*=#";
vector<string> output(screen_width*screen_height, " ");
vector<float> zbuffer(screen_width*screen_height, 0);
void plotPlane(float x, float y, float z, int nx, int ny, int nz, string c)
{
float cosA = cos(A), sinA = sin(A);
float cosB = cos(B), sinB = sin(B);
float cosC = cos(C), sinC = sin(C);
// rotate the above point
float rotatedX = y * sinA * sinB * cosC - z * cosA * sinB * cosC + y * cosA * sinC + z * sinA * sinC + x * cosB * cosC;
float rotatedY = y * cosA * cosC + z * sinA * cosC - y * sinA * sinB * sinC + z * cosA * sinB * sinC - x * cosB * sinC;
float rotatedZ = z * cosA * cosB - y * sinA * cosB + x * sinB;;
float ooz = 1/(rotatedZ+K2);
// find projection over screen
int xp = (int) (screen_width/2 + K1*ooz*rotatedX*2);
int yp = (int) (screen_height/2 - K1*ooz*rotatedY);
int position = xp + yp * screen_width;
float rotatedNx = ny * sinA * sinB * cosC - nz * cosA * sinB * cosC + ny * cosA * sinC + nz * sinA * sinC + nx * cosB * cosC;;
float rotatedNy = ny * cosA * cosC + nz * sinA * cosC - ny * sinA * sinB * sinC + nz * cosA * sinB * sinC - nx * cosB * sinC;
float rotatedNz = nz * cosA * cosB - ny * sinA * cosB + nx * sinB;;
//find Luminance
float L = rotatedNx*light[0]+rotatedNy*light[1]+rotatedNz*light[2];
//update frame_buffer
if(ooz > zbuffer[position]) {
zbuffer[position] = ooz;
int luminance_index = L*4;
output[position] = c + CHARS_LUMINANCE[luminance_index>0 ? luminance_index: 0];// + "\033[0m";
}
}
int main()
{
bool rotate = true;
ios::sync_with_stdio(false);
while(1)
{
fill(output.begin(), output.end(), " ");
fill(zbuffer.begin(), zbuffer.end(), 0);
for (float a = -cubewidth; a<=cubewidth; a+=resolution)
{
for (float b = -cubewidth; b<= cubewidth; b+=resolution)
{
plotPlane(a,b, cubewidth, 0,0,1, "\033[31m");
plotPlane(a,b, -cubewidth, 0, 0,-1, "\033[33m");
plotPlane(cubewidth, a,b, 1,0,0, "\033[93m");
plotPlane(-cubewidth,a,b,-1,0,0, "\033[97m");
plotPlane(a, cubewidth, b, 0,1,0, "\033[34m");
plotPlane(a, -cubewidth, b, 0,-1,0, "\033[32m");
}
}
cout<<"\x1b[H";
ostringstream buffer;
for (int k = 0; k < screen_width*screen_height; ++k) {
if (k % screen_width == 0) {
buffer << '\n';
} else {
buffer << output[k];
}
}
cout << buffer.str();
// Check if a key is pressed
if(rotate)
{
A+= 0.02;
B+= 0.1;
C+=0.05;
}else{
if (GetAsyncKeyState('W') & 0x8000) {
A-=0.1;
}
if (GetAsyncKeyState('A') & 0x8000) {
B-=0.1;
}
if (GetAsyncKeyState('S') & 0x8000) {
A+=0.1;
}
if (GetAsyncKeyState('D') & 0x8000) {
B+=0.1;
}
if (GetAsyncKeyState('Q') & 0x8000) {
C-=0.1;
}
if (GetAsyncKeyState('E') & 0x8000) {
C+=0.1;
}
}
if (GetAsyncKeyState(VK_SPACE) & 0x8000) {
rotate = !(rotate);
}
// Exit on 'Esc' key press
if (GetAsyncKeyState(VK_ESCAPE) & 0x8000) {
cout << "Exiting...\n";
break;
}
Sleep(20);
}
}