cpu.c 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217
  1. #include "./common.h"
  2. void render_line(SDL_Renderer *renderer,
  3. Vec2 begin, Vec2 end,
  4. uint32_t color)
  5. {
  6. check_sdl_code(
  7. SDL_SetRenderDrawColor(renderer, HEX_COLOR(color)));
  8. check_sdl_code(
  9. SDL_RenderDrawLine(
  10. renderer,
  11. (int) floorf(begin.x),
  12. (int) floorf(begin.y),
  13. (int) floorf(end.x),
  14. (int) floorf(end.y)));
  15. }
  16. void fill_rect(SDL_Renderer *renderer, Vec2 pos, Vec2 size, uint32_t color)
  17. {
  18. check_sdl_code(
  19. SDL_SetRenderDrawColor(renderer, HEX_COLOR(color)));
  20. const SDL_Rect rect = {
  21. (int) floorf(pos.x),
  22. (int) floorf(pos.y),
  23. (int) floorf(size.x),
  24. (int) floorf(size.y),
  25. };
  26. check_sdl_code(SDL_RenderFillRect(renderer, &rect));
  27. }
  28. void render_marker(SDL_Renderer *renderer, Vec2 pos, uint32_t color)
  29. {
  30. const Vec2 size = vec2(MARKER_SIZE, MARKER_SIZE);
  31. fill_rect(
  32. renderer,
  33. vec2_sub(pos, vec2_scale(size, 0.5f)),
  34. size,
  35. color);
  36. }
  37. Vec2 beziern_sample(Vec2 *ps, Vec2 *xs, size_t n, float p)
  38. {
  39. memcpy(xs, ps, sizeof(Vec2) * n);
  40. while (n > 1) {
  41. for (size_t i = 0; i < n - 1; ++i) {
  42. xs[i] = lerpv2(xs[i], xs[i + 1], p);
  43. }
  44. n -= 1;
  45. }
  46. return xs[0];
  47. }
  48. void render_bezier_markers(SDL_Renderer *renderer,
  49. Vec2 *ps, Vec2 *xs, size_t n,
  50. float s, uint32_t color)
  51. {
  52. for (float p = 0.0f; p <= 1.0f; p += s) {
  53. render_marker(renderer, beziern_sample(ps, xs, n, p), color);
  54. }
  55. }
  56. void render_bezier_curve(SDL_Renderer *renderer,
  57. Vec2 *ps, Vec2 *xs, size_t n,
  58. float s, uint32_t color)
  59. {
  60. for (float p = 0.0f; p <= 1.0f; p += s) {
  61. Vec2 begin = beziern_sample(ps, xs, n, p);
  62. Vec2 end = beziern_sample(ps, xs, n, p + s);
  63. render_line(renderer, begin, end, color);
  64. }
  65. }
  66. #define PS_CAPACITY 256
  67. Vec2 ps[PS_CAPACITY];
  68. Vec2 xs[PS_CAPACITY];
  69. size_t ps_count = 0;
  70. int ps_selected = -1;
  71. int ps_at(Vec2 pos)
  72. {
  73. const Vec2 ps_size = vec2(MARKER_SIZE, MARKER_SIZE);
  74. for (size_t i = 0; i < ps_count; ++i) {
  75. const Vec2 ps_begin = vec2_sub(ps[i], vec2_scale(ps_size, 0.5f));
  76. const Vec2 ps_end = vec2_add(ps_begin, ps_size);
  77. if (ps_begin.x <= pos.x && pos.x <= ps_end.x &&
  78. ps_begin.y <= pos.y && pos.y <= ps_end.y) {
  79. return (int) i;
  80. }
  81. }
  82. return -1;
  83. }
  84. int main(void)
  85. {
  86. check_sdl_code(
  87. SDL_Init(SDL_INIT_VIDEO));
  88. SDL_Window * const window =
  89. check_sdl_ptr(
  90. SDL_CreateWindow(
  91. "Bezier Curves",
  92. 0, 0,
  93. SCREEN_WIDTH,
  94. SCREEN_HEIGHT,
  95. SDL_WINDOW_RESIZABLE));
  96. SDL_Renderer * const renderer =
  97. check_sdl_ptr(
  98. SDL_CreateRenderer(
  99. window, -1, SDL_RENDERER_ACCELERATED));
  100. check_sdl_code(
  101. SDL_RenderSetLogicalSize(renderer, SCREEN_WIDTH, SCREEN_HEIGHT));
  102. int quit = 0;
  103. int markers = 1;
  104. float t = 0.0f;
  105. float bezier_sample_step = 0.05f;
  106. while (!quit) {
  107. SDL_Event event;
  108. while (SDL_PollEvent(&event)) {
  109. switch (event.type) {
  110. case SDL_QUIT:
  111. quit = 1;
  112. break;
  113. case SDL_KEYDOWN: {
  114. switch (event.key.keysym.sym) {
  115. case SDLK_F1: {
  116. markers = !markers;
  117. } break;
  118. }
  119. } break;
  120. case SDL_MOUSEBUTTONDOWN: {
  121. switch (event.button.button) {
  122. case SDL_BUTTON_LEFT: {
  123. const Vec2 mouse_pos = vec2(event.button.x, event.button.y);
  124. ps_selected = ps_at(mouse_pos);
  125. if (ps_selected < 0 && ps_count < PS_CAPACITY) {
  126. ps[ps_count++] = mouse_pos;
  127. }
  128. } break;
  129. }
  130. } break;
  131. case SDL_MOUSEBUTTONUP: {
  132. if (event.button.button == SDL_BUTTON_LEFT) {
  133. ps_selected = -1;
  134. }
  135. } break;
  136. case SDL_MOUSEMOTION: {
  137. Vec2 mouse_pos = vec2(event.motion.x, event.motion.y);
  138. if (ps_selected >= 0) {
  139. ps[ps_selected] = mouse_pos;
  140. }
  141. } break;
  142. case SDL_MOUSEWHEEL: {
  143. if (event.wheel.y > 0) {
  144. bezier_sample_step = fminf(bezier_sample_step + 0.001f, 0.999f);
  145. } else if (event.wheel.y < 0) {
  146. bezier_sample_step = fmaxf(bezier_sample_step - 0.001f, 0.001f);
  147. }
  148. } break;
  149. }
  150. }
  151. check_sdl_code(
  152. SDL_SetRenderDrawColor(
  153. renderer,
  154. HEX_COLOR(BACKGROUND_COLOR)));
  155. check_sdl_code(
  156. SDL_RenderClear(renderer));
  157. if (ps_count >= 1) {
  158. if (markers) {
  159. render_bezier_markers(
  160. renderer,
  161. ps, xs, ps_count,
  162. bezier_sample_step,
  163. GREEN_COLOR);
  164. } else {
  165. render_bezier_curve(
  166. renderer,
  167. ps, xs, ps_count,
  168. bezier_sample_step,
  169. GREEN_COLOR);
  170. }
  171. }
  172. for (size_t i = 0; i < ps_count; ++i) {
  173. render_marker(renderer, ps[i], RED_COLOR);
  174. if (i < ps_count - 1) {
  175. render_line(renderer, ps[i], ps[i + 1], RED_COLOR);
  176. }
  177. }
  178. SDL_RenderPresent(renderer);
  179. SDL_Delay(DELTA_TIME_MS);
  180. t += DELTA_TIME_SEC;
  181. }
  182. SDL_Quit();
  183. return 0;
  184. }