code / nuke

Lines646 C608 make30 Markdown8
(186 lines)
1 /**
2 * ASCII spinning glboe
3 */
5 #include "colors.h"
6 #include <curses.h>
7 #include <stdlib.h>
8 #include <unistd.h>
9 #include <signal.h>
10 #include <string.h>
11 #include <math.h>
12 #include <poll.h>
14 static const double GOLDEN_RATIO = 1.6180339887498948482045868343656381;
16 #define NUM_WAVES 7
18 // Randomly generated x/y offsets:
19 static const double OFFSETS[2*NUM_WAVES] = {
20 0.5459919526, 0.6072439135, 0.6217563193, 0.5444045324, 0.8923452588,
21 0.4626828607, 0.9422234679,
23 0.7870886548, 0.7425605127, 0.1510923405, 0.3889282293, 0.3730024274,
24 0.1450487012, 0.9051931355,
25 };
26 // 0.83^n amplitudes
27 static const double AMPLITUDES[NUM_WAVES] = {
28 0.83, 0.6889, 0.571787, 0.47458321, 0.3939040643, 0.326940373369, 0.27136050989627
29 };
31 // See: https://blog.bruce-hill.com/hill-noise/
32 static double hillnoise(double x, double y)
34 double noise = 0;
35 double sigma = 0;
36 for (int i = 0; i < NUM_WAVES; i++) {
37 // Rotate coordinates
38 double rotation = fmod(((float)i)*GOLDEN_RATIO, 1.0)*2.0*M_PI;
39 double u = x*cos(rotation) - y*sin(rotation);
40 double v = -x*sin(rotation) - y*cos(rotation);
41 double size = AMPLITUDES[i];
42 double offsetx = OFFSETS[2*i];
43 double offsety = OFFSETS[2*i+1];
44 noise += (size/2.)*(sin(u/size + offsetx) + sin(v/size + offsety));
45 sigma += size*size;
47 sigma = sqrt(sigma)/2.;
48 noise /= 2.*sigma;
49 return (0.5*(noise < 0 ? -1. : 1.)*sqrt(1 - exp(-2./M_PI * noise*noise)) + 0.5);
52 static double mix(double a, double b, double amount)
54 return (1.-amount)*a + amount*b;
57 void draw_stars(double t)
59 int rows,cols;
60 getmaxyx(stdscr,rows,cols);
61 attron(COLOR_PAIR(WHITE));
62 for (int r = 0; r < rows; r++) {
63 for (int c = 0; c < cols; c++) {
64 double n = hillnoise(r*1,c*2+(t*.04));
65 if (n > .8) {
66 mvaddch(r,c,n > .9 ? '*' : '.');
70 attroff(COLOR_PAIR(WHITE));
73 static double get_rotation(double t)
75 return t * (2*M_PI)/60. + M_PI;
78 void draw_globe(double t, double zoom)
80 int rows,cols;
81 getmaxyx(stdscr,rows,cols);
82 double rotation = get_rotation(t);
83 const double rho = rows/2.;
84 for (int r = 0; r < rows; r++) {
85 for (int c = 0; c < cols; c++) {
86 double y = (c - cols/2) * 0.5 / zoom;
87 double z = (r - rows/2) * 1.0 / zoom;
88 double x = sqrt(rho*rho - z*z - y*y);
90 if (z*z + y*y > rho*rho) {
91 continue;
94 double theta = atan2(z, sqrt(x*x + y*y));
95 double phi = fmod(atan2(y, x) + rotation, 2.*M_PI);
96 double elevation = hillnoise(theta*4., phi*4.);
97 double clouds = hillnoise(theta*12., phi*6. - 1.*rotation - 140.);
98 int color;
99 int ch;
100 if ((fabs(z)/rho) > .9) {
101 elevation = elevation + mix(.0, 1., 10.*(fabs(z)/rho - .9)) > .6 ? 1. : 0.;
103 if (clouds < .4) {
104 continue;
105 } else if (elevation < .55) {
106 // Water
107 ch = '~';
108 color = COLOR_PAIR(BLUE);
109 } else if (elevation < .65) {
110 // Sand
111 ch = ':';
112 color = COLOR_PAIR(YELLOW);
113 } else if (elevation < .75) {
114 // Grass
115 ch = ',' | A_BOLD;
116 color = COLOR_PAIR(GREEN);
117 } else if (elevation < .85) {
118 // Forest
119 ch = '&';
120 color = COLOR_PAIR(GREEN);
121 } else {
122 // Mountain
123 ch = '#';
124 color = COLOR_PAIR(WHITE);
126 attron(color);
127 mvaddch(r,c,ch);
128 attroff(color);
133 void draw_clouds(double t, double zoom)
135 int rows,cols;
136 getmaxyx(stdscr,rows,cols);
137 double rotation = get_rotation(t);
138 const double rho = rows/2.;
139 for (int r = 0; r < rows; r++) {
140 for (int c = 0; c < cols; c++) {
141 double y = (c - cols/2) * 0.5 / zoom;
142 double z = (r - rows/2) * 1.0 / zoom;
143 double x = sqrt(rho*rho - z*z - y*y);
145 if (z*z + y*y > rho*rho) {
146 continue;
149 double theta = atan2(z, sqrt(x*x + y*y));
150 double phi = fmod(atan2(y, x) + rotation, 2.*M_PI);
151 double clouds = hillnoise(theta*12., phi*6. - 1.*rotation - 140.);
152 int color;
153 int ch;
154 if (clouds < .4) {
155 ch = (clouds < .3 ? '0' : '%') | A_BOLD;
156 color = COLOR_PAIR(WHITE);
157 attron(color);
158 mvaddch(r,c,ch);
159 attroff(color);
165 int latlon_to_rc(double t, double zoom, double lat, double lon, int *r, int *c)
167 int rows,cols;
168 getmaxyx(stdscr,rows,cols);
169 const double rho = rows/2.;
170 double theta = lat;
171 double phi = lon + get_rotation(t);
172 double x = rho*sin(theta)*cos(phi);
173 double y = rho*sin(theta)*sin(phi);
174 double z = rho*cos(theta);
175 *r = z / (1.0/zoom) + rows/2;
176 *c = y / (.5/zoom) + cols/2;
177 return x < 0;
180 const double target_lat = M_PI/2*1.01;
181 const double target_lon = M_PI + 2.6;
182 // return 1 if visible, else 0
183 int get_target_pos(double t, double zoom, int *targetr, int *targetc)
185 return latlon_to_rc(t, zoom, target_lat, target_lon, targetr, targetc);