diff options
Diffstat (limited to 'src/main.c')
| -rw-r--r-- | src/main.c | 128 |
1 files changed, 128 insertions, 0 deletions
diff --git a/src/main.c b/src/main.c new file mode 100644 index 0000000..9014f22 --- /dev/null +++ b/src/main.c @@ -0,0 +1,128 @@ +#include <SDL3/SDL.h> +#include <math.h> +#include <stdio.h> + +#define LOG(...) \ + do { \ + fprintf(stderr, __VA_ARGS__); \ + fprintf(stderr, "\n"); \ + } while (0) + +#define QUADRATIC_BEZIER_CURVE_CONTROL_POINT_COUNT 4 +#define CONTROL_POINT_RECTANGLE_SIZE 20.f + +struct vec2 { + float x; + float y; +}; +struct vec2 vec2_add(struct vec2 lhs, struct vec2 rhs) { + return (struct vec2){.x = lhs.x + rhs.x, .y = lhs.y + rhs.y}; +} + +struct vec2 vec2_mul_scalar(struct vec2 lhs, float rhs) { + return (struct vec2){.x = lhs.x * rhs, .y = lhs.y * rhs}; +} + +struct vec2 bezier_quadratic( + float t, const struct vec2 + control_points[QUADRATIC_BEZIER_CURVE_CONTROL_POINT_COUNT]) { + + struct vec2 a = vec2_mul_scalar(control_points[0], powf(1.f - t, 3.f)); + struct vec2 b = + vec2_mul_scalar(control_points[1], 3 * powf(1.f - t, 2.f) * t); + struct vec2 c = vec2_mul_scalar(control_points[2], 3 * (1.f - t) * t * t); + struct vec2 d = vec2_mul_scalar(control_points[3], t * t * t); + return vec2_add(a, vec2_add(b, vec2_add(c, d))); +} + +struct state { + struct vec2 control_points[QUADRATIC_BEZIER_CURVE_CONTROL_POINT_COUNT]; + int set_control_point_count; +}; +void state_render(const struct state *state, SDL_Renderer *renderer) { + for (int set_control_point_index = 0; + set_control_point_index < state->set_control_point_count; + set_control_point_index++) { + const struct vec2 *set_control_point = + &state->control_points[set_control_point_index]; + SDL_SetRenderDrawColor(renderer, 0xFF, 0x00, 0x00, 0xFF); + SDL_RenderFillRect( + renderer, + &(const SDL_FRect){ + set_control_point->x - CONTROL_POINT_RECTANGLE_SIZE / 2.f, + set_control_point->y - CONTROL_POINT_RECTANGLE_SIZE / 2.f, + CONTROL_POINT_RECTANGLE_SIZE, CONTROL_POINT_RECTANGLE_SIZE}); + } + + if (state->set_control_point_count == + QUADRATIC_BEZIER_CURVE_CONTROL_POINT_COUNT) { + float prev_t = 0.f; + for (int ti = 0; ti < 100; ti += 1) { + float t = ti / 100.f; + struct vec2 first_point = bezier_quadratic(prev_t, state->control_points); + struct vec2 second_point = bezier_quadratic(t, state->control_points); + SDL_SetRenderDrawColor(renderer, 0xFF, 0x00, 0x00, 0xFF); + SDL_RenderLine(renderer, first_point.x, first_point.y, second_point.x, + second_point.y); + prev_t = t; + } + } +} +void state_on_click(struct state *state, struct vec2 position) { + if (state->set_control_point_count < + QUADRATIC_BEZIER_CURVE_CONTROL_POINT_COUNT) { + state->control_points[state->set_control_point_count++] = position; + } +} + +int main(void) { + bool sdl_initialized = SDL_Init(SDL_INIT_VIDEO); + SDL_Window *window = NULL; + if (sdl_initialized) { + window = SDL_CreateWindow("bezier", 1280, 720, 0); + } + + SDL_Renderer *renderer = NULL; + if (window) { + renderer = SDL_CreateRenderer(window, NULL); + } + + struct state state = {0}; + + if (renderer) { + bool running = true; + while (running) { + SDL_Event event; + while (SDL_PollEvent(&event)) { + bool quit = event.type == SDL_EVENT_QUIT; + bool escape_pressed = + event.type == SDL_EVENT_KEY_DOWN && event.key.key == SDLK_ESCAPE; + + if (quit || escape_pressed) { + running = false; + } else if (event.type == SDL_EVENT_MOUSE_BUTTON_DOWN && + event.button.button == SDL_BUTTON_LEFT) { + state_on_click( + &state, (struct vec2){.x = event.button.x, .y = event.button.y}); + } + } + + SDL_SetRenderDrawColor(renderer, 0x00, 0x00, 0x00, 0xFF); + SDL_RenderClear(renderer); + state_render(&state, renderer); + SDL_RenderPresent(renderer); + } + } + + if (renderer) { + SDL_DestroyRenderer(renderer); + } + if (window) { + SDL_DestroyWindow(window); + } + if (sdl_initialized) { + SDL_Quit(); + } + + return 0; +} |
