14 static const double GOLDEN_RATIO = 1.6180339887498948482045868343656381;
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,
27 static const double AMPLITUDES[NUM_WAVES] = {
28 0.83, 0.6889, 0.571787, 0.47458321, 0.3939040643, 0.326940373369, 0.27136050989627
31 // See: https://blog.bruce-hill.com/hill-noise/
32 static double hillnoise(double x, double y)
36 for (int i = 0; i < NUM_WAVES; i++) {
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));
47 sigma = sqrt(sigma)/2.;
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)
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));
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)
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) {
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.);
100 if ((fabs(z)/rho) > .9) {
101 elevation = elevation + mix(.0, 1., 10.*(fabs(z)/rho - .9)) > .6 ? 1. : 0.;
105 } else if (elevation < .55) {
108 color = COLOR_PAIR(BLUE);
109 } else if (elevation < .65) {
112 color = COLOR_PAIR(YELLOW);
113 } else if (elevation < .75) {
116 color = COLOR_PAIR(GREEN);
117 } else if (elevation < .85) {
120 color = COLOR_PAIR(GREEN);
124 color = COLOR_PAIR(WHITE);
133 void draw_clouds(double t, double zoom)
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) {
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.);
155 ch = (clouds < .3 ? '0' : '%') | A_BOLD;
156 color = COLOR_PAIR(WHITE);
165 int latlon_to_rc(double t, double zoom, double lat, double lon, int *r, int *c)
168 getmaxyx(stdscr,rows,cols);
169 const double rho = rows/2.;
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;
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);