123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217 |
- #include "./common.h"
- void render_line(SDL_Renderer *renderer,
- Vec2 begin, Vec2 end,
- uint32_t color)
- {
- check_sdl_code(
- SDL_SetRenderDrawColor(renderer, HEX_COLOR(color)));
- check_sdl_code(
- SDL_RenderDrawLine(
- renderer,
- (int) floorf(begin.x),
- (int) floorf(begin.y),
- (int) floorf(end.x),
- (int) floorf(end.y)));
- }
- void fill_rect(SDL_Renderer *renderer, Vec2 pos, Vec2 size, uint32_t color)
- {
- check_sdl_code(
- SDL_SetRenderDrawColor(renderer, HEX_COLOR(color)));
- const SDL_Rect rect = {
- (int) floorf(pos.x),
- (int) floorf(pos.y),
- (int) floorf(size.x),
- (int) floorf(size.y),
- };
- check_sdl_code(SDL_RenderFillRect(renderer, &rect));
- }
- void render_marker(SDL_Renderer *renderer, Vec2 pos, uint32_t color)
- {
- const Vec2 size = vec2(MARKER_SIZE, MARKER_SIZE);
- fill_rect(
- renderer,
- vec2_sub(pos, vec2_scale(size, 0.5f)),
- size,
- color);
- }
- Vec2 beziern_sample(Vec2 *ps, Vec2 *xs, size_t n, float p)
- {
- memcpy(xs, ps, sizeof(Vec2) * n);
- while (n > 1) {
- for (size_t i = 0; i < n - 1; ++i) {
- xs[i] = lerpv2(xs[i], xs[i + 1], p);
- }
- n -= 1;
- }
- return xs[0];
- }
- void render_bezier_markers(SDL_Renderer *renderer,
- Vec2 *ps, Vec2 *xs, size_t n,
- float s, uint32_t color)
- {
- for (float p = 0.0f; p <= 1.0f; p += s) {
- render_marker(renderer, beziern_sample(ps, xs, n, p), color);
- }
- }
- void render_bezier_curve(SDL_Renderer *renderer,
- Vec2 *ps, Vec2 *xs, size_t n,
- float s, uint32_t color)
- {
- for (float p = 0.0f; p <= 1.0f; p += s) {
- Vec2 begin = beziern_sample(ps, xs, n, p);
- Vec2 end = beziern_sample(ps, xs, n, p + s);
- render_line(renderer, begin, end, color);
- }
- }
- #define PS_CAPACITY 256
- Vec2 ps[PS_CAPACITY];
- Vec2 xs[PS_CAPACITY];
- size_t ps_count = 0;
- int ps_selected = -1;
- int ps_at(Vec2 pos)
- {
- const Vec2 ps_size = vec2(MARKER_SIZE, MARKER_SIZE);
- for (size_t i = 0; i < ps_count; ++i) {
- const Vec2 ps_begin = vec2_sub(ps[i], vec2_scale(ps_size, 0.5f));
- const Vec2 ps_end = vec2_add(ps_begin, ps_size);
- if (ps_begin.x <= pos.x && pos.x <= ps_end.x &&
- ps_begin.y <= pos.y && pos.y <= ps_end.y) {
- return (int) i;
- }
- }
- return -1;
- }
- int main(void)
- {
- check_sdl_code(
- SDL_Init(SDL_INIT_VIDEO));
- SDL_Window * const window =
- check_sdl_ptr(
- SDL_CreateWindow(
- "Bezier Curves",
- 0, 0,
- SCREEN_WIDTH,
- SCREEN_HEIGHT,
- SDL_WINDOW_RESIZABLE));
- SDL_Renderer * const renderer =
- check_sdl_ptr(
- SDL_CreateRenderer(
- window, -1, SDL_RENDERER_ACCELERATED));
- check_sdl_code(
- SDL_RenderSetLogicalSize(renderer, SCREEN_WIDTH, SCREEN_HEIGHT));
- int quit = 0;
- int markers = 1;
- float t = 0.0f;
- float bezier_sample_step = 0.05f;
- while (!quit) {
- SDL_Event event;
- while (SDL_PollEvent(&event)) {
- switch (event.type) {
- case SDL_QUIT:
- quit = 1;
- break;
- case SDL_KEYDOWN: {
- switch (event.key.keysym.sym) {
- case SDLK_F1: {
- markers = !markers;
- } break;
- }
- } break;
- case SDL_MOUSEBUTTONDOWN: {
- switch (event.button.button) {
- case SDL_BUTTON_LEFT: {
- const Vec2 mouse_pos = vec2(event.button.x, event.button.y);
- ps_selected = ps_at(mouse_pos);
- if (ps_selected < 0 && ps_count < PS_CAPACITY) {
- ps[ps_count++] = mouse_pos;
- }
- } break;
- }
- } break;
- case SDL_MOUSEBUTTONUP: {
- if (event.button.button == SDL_BUTTON_LEFT) {
- ps_selected = -1;
- }
- } break;
- case SDL_MOUSEMOTION: {
- Vec2 mouse_pos = vec2(event.motion.x, event.motion.y);
- if (ps_selected >= 0) {
- ps[ps_selected] = mouse_pos;
- }
- } break;
- case SDL_MOUSEWHEEL: {
- if (event.wheel.y > 0) {
- bezier_sample_step = fminf(bezier_sample_step + 0.001f, 0.999f);
- } else if (event.wheel.y < 0) {
- bezier_sample_step = fmaxf(bezier_sample_step - 0.001f, 0.001f);
- }
- } break;
- }
- }
- check_sdl_code(
- SDL_SetRenderDrawColor(
- renderer,
- HEX_COLOR(BACKGROUND_COLOR)));
- check_sdl_code(
- SDL_RenderClear(renderer));
- if (ps_count >= 1) {
- if (markers) {
- render_bezier_markers(
- renderer,
- ps, xs, ps_count,
- bezier_sample_step,
- GREEN_COLOR);
- } else {
- render_bezier_curve(
- renderer,
- ps, xs, ps_count,
- bezier_sample_step,
- GREEN_COLOR);
- }
- }
- for (size_t i = 0; i < ps_count; ++i) {
- render_marker(renderer, ps[i], RED_COLOR);
- if (i < ps_count - 1) {
- render_line(renderer, ps[i], ps[i + 1], RED_COLOR);
- }
- }
- SDL_RenderPresent(renderer);
- SDL_Delay(DELTA_TIME_MS);
- t += DELTA_TIME_SEC;
- }
- SDL_Quit();
- return 0;
- }
|