summaryrefslogtreecommitdiff
path: root/examples/julia_set.c
blob: 81aa02c84678dbc4ab38812ab5057ebe736a4b9b (plain)
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
#include "../graphics.c"

#define SCALE_LIMIT (0.9)

f64 view_x = 0.;
f64 view_y = 0.;
f64 view_s = 1.;
f64 cx     = -.771;
f64 cy     = .1005;
f64 radius = 2.;
i64 limit  = 1024;
i64 time_0;

void inc_f64(f64 *x, i8 s) {
  u64 *u = (u64 *) x;
  if (((*u >> 52) & 2047) == 2047)
    return;
  *u += *x > 0 ? s : -s;
}

void apply_scale(f64 delta) {
  while (delta > SCALE_LIMIT) {
    apply_scale(SCALE_LIMIT);
    delta -= SCALE_LIMIT;
  }
  while (delta < -SCALE_LIMIT) {
    apply_scale(-SCALE_LIMIT);
    delta += SCALE_LIMIT;
  }

  f64 ds = view_s * delta * .1;
  if (view_s + ds <= 0.0)
    return;
  f64 dx  = (g_platform.cursor_x * 1. - g_platform.real_width  * .5);
  f64 dy  = (g_platform.cursor_y * 1. - g_platform.real_height * .5);
  view_x -= view_s * dx;
  view_y -= view_s * dy;
  if (view_s == view_s + ds)
    inc_f64(&view_s, ds > 0 ? 1 : -1);
  else
    view_s += ds;
  view_x += view_s * dx;
  view_y += view_s * dy;
}

void update_and_render_frame(void) {
  i32 num_events = handle_main_window_events();

  i64 time_elapsed = current_utc_time_in_milliseconds() - time_0;
  time_0 += time_elapsed;

  b8 left  = g_platform.key_down[KEY_LEFT];
  b8 right = g_platform.key_down[KEY_RIGHT];
  b8 up    = g_platform.key_down[KEY_UP];
  b8 down  = g_platform.key_down[KEY_DOWN];

  if (!left && !right && !up && !down && num_events == 0) {
    suspend_thread_for_milliseconds(1);
    return;
  }

  if (g_platform.key_pressed[KEY_ESCAPE]) {
    view_x = 0.;
    view_y = 0.;
    view_s = 1.;
  }

  f64 d = (g_platform.key_down[MOD_CTRL] ? .00005 : .001) * view_s * time_elapsed;

  if (left)  { cx -= d; cy -= d; }
  if (right) { cx += d; cy += d; }
  if (up)    { cx += d; cy -= d; }
  if (down)  { cx -= d; cy += d; }

  if (g_platform.key_down[BUTTON_LEFT]) {
    view_x += g_platform.cursor_dx * view_s;
    view_y += g_platform.cursor_dy * view_s;
  }

  if (g_platform.wheel_dy != 0.) {
    apply_scale(g_platform.wheel_dy / 2.0);
    apply_scale(g_platform.wheel_dy / 2.0);
  }

  for (i32 j = 0; j < g_platform.frame_height; ++j)
    for (i32 i = 0; i < g_platform.frame_width; ++i) {
      f64 kx = ((f64) g_platform.real_width)  / g_platform.frame_width;
      f64 ky = ((f64) g_platform.real_height) / g_platform.frame_height;

      f64 x = .003 * ((i - (g_platform.frame_width - 1)  * .5) * kx * view_s - view_x);
      f64 y = .003 * ((j - (g_platform.frame_height - 1) * .5) * ky * view_s - view_y);

      i64 n = 0;

      for (; x * x + y * y < radius * radius && n < limit; ++n) {
        f64 z = x * x - y * y;
        y     = 2. * x * y  + cy;
        x     = z + cx;
      }

      u32 c;

      if (n == limit)
        c = 0;
      else
        c = 0xffffff - n * 8 - n * 256 * 4;

      g_platform.pixels[j * g_platform.frame_width + i] = vec4_from_vec3_f32(rgb_f32_from_u32(c), 1.f);
    }

  render_main_window_frame();
}

i32 main(i32 argc, c8 **argv) {
  (void) argc;
  (void) argv;

  g_platform = (Platform) {
    .title = "Julia Set",
  };

  time_0 = current_utc_time_in_milliseconds();

  run_main_window_event_loop();

  return 0;
}