-
Notifications
You must be signed in to change notification settings - Fork 6
/
metaballs-fixp.c
97 lines (89 loc) · 3.8 KB
/
metaballs-fixp.c
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
#include <stdio.h>
#include <stdint.h>
#include <unistd.h>
#include <math.h>
#define POW2_24 (1<<24)
#define FPS 50
#define WIDTH 80
#define HEIGHT 50
#define CLAMP(x, low, high) (((x) > (high)) ? (high) : (((x) < (low)) ? (low) : (x)))
#define ABS(a) (((a) < 0) ? -(a) : (a))
int32_t iTime = 0;
// sin(x) = x * (1 + x^2 * (0.00761 * x^2 - 0.16605))
// this formula works pretty well in the range [-pi/2, +pi/2]
// x is fixed-point 24 bit precision
int32_t sin24(int32_t x) {
int32_t sign;
if (x>0) { sign = 1; } else { sign = -1; x = -x; } //
while (x>79060768) { x = x - 105414357; } // reduce the argument to the acceptable range
if (x>26353589) { return sign*sin24(52707179 - x); } //
return sign*(x/4096)*((16777216 + (((x/4096)*(x/4096))/4096)*((((x/4096)*(x/4096))/131 - 2785856)/4096))/4096);
}
// cos(x) = 1 + x^2 * (0.03705 * x^2 - 0.49670))
// this formula works pretty well in the range [-pi/2, +pi/2]
// x is fixed-point 24 bit precision
int32_t cos24(int32_t x) {
if (x<0) { x = -x; } //
while (x>79060768) { x = x - 105414357; } // reduce the argument to the acceptable range
if (x>26353589) { return -sin24(x - 26353589); } //
return 16777216 + (((x/4096)*(x/4096))/4096)*((((x/4096)*(x/4096))/27 - 8333243)/4096);
}
// square root of a fixed-point number
// stored in a 32 bit integer variable, shift is the precision
int32_t sqrtfp(int32_t n, int32_t shift) {
int32_t x;
int32_t x_old;
int32_t n_one;
if (n > 2147483647/shift) { // pay attention to potential overflows
return 2 * sqrtfp(n / 4, shift);
}
x = shift; // initial guess 1.0, can do better, but oh well
n_one = n * shift; // need to compensate for fixp division
for (;;) {
x_old = x;
x = (x + n_one / x) / 2;
if (ABS(x - x_old) <= 1) {
return x;
}
}
}
void mainImage(int32_t fragCoord_x, int32_t fragCoord_y) { // kinda shadertoy naming :)
int32_t u; int32_t v;
int32_t fragColor_r; int32_t fragColor_g; int32_t fragColor_b;
int32_t sdf;
int32_t a; int32_t b; int32_t c; int32_t d; int32_t e;
int32_t d1; int32_t d2; int32_t d3;
u = ((2*fragCoord_x - WIDTH )*POW2_24)/HEIGHT;
v = ((2*fragCoord_y - HEIGHT)*POW2_24)/HEIGHT;
a = sin24(iTime/2)-u;
b = sin24(iTime/2)-v;
c = cos24(iTime/2)-v;
d = sin24(iTime/4)-u;
e = sin24(iTime )-v;
d1 = ((POW2_24*6/10)/CLAMP(sqrtfp((a/4096)*(a/4096) + (b/4096)*(b/4096), POW2_24)/4096,100,10000))*4096; // linear motion
d2 = ((POW2_24*6/10)/CLAMP(sqrtfp((a/4096)*(a/4096) + (c/4096)*(c/4096), POW2_24)/4096,100,10000))*4096; // circular motion
d3 = ((POW2_24*6/10)/CLAMP(sqrtfp((d/4096)*(d/4096) + (e/4096)*(e/4096), POW2_24)/4096,100,10000))*4096; // wave
sdf = d1 + d2 + d3 - (POW2_24*22)/10;
fragColor_r = ((255*17*((sdf+POW2_24)/4096))/10)/4096; // orange halo (red and green channels)
fragColor_g = ((255*8*((sdf+POW2_24)/4096))/10)/4096;
fragColor_b = 255; if (sdf<0) { fragColor_b = 0; }
printf("%d;%d;%d", CLAMP(fragColor_r,0,255), CLAMP(fragColor_g, 0, 255), CLAMP(fragColor_b, 0, 255));
}
int main () {
printf("\033[2j\033[?25l"); // clear screen and hide cursor
for (;;) {
printf("\033[H"); // home
for (int j = 0; j<HEIGHT; j+=2) {
for (int i = 0; i<WIDTH; i++) {
printf("\033[48;2;"); mainImage(i, j+0); printf("m"); // set background color
printf("\033[38;2;"); mainImage(i, j+1); printf("m"); // set foreground color
printf("\xE2\x96\x83"); // half-block Unicode symbol
}
printf("\033[49m\n");
}
usleep(1000000/FPS);
iTime += POW2_24/(FPS/2);
if (iTime>POW2_24*100) iTime = 0; // 100 approx 32 pi :)
}
return 0;
}