From 322c1a49f59d3fc6441804bbbb29da22567e4bcb Mon Sep 17 00:00:00 2001 From: Charles Date: Wed, 20 May 2020 16:53:25 +0200 Subject: Correct resize, linear iterpolation draft --- inc/config.h | 15 ++++++++-- inc/mandel.h | 6 ++++ src/color.c | 93 ++++++++++++++++++++++++++++++++++++++++++++++++++++-------- src/event.c | 36 ++++++++++++++++------- src/state.c | 1 + 5 files changed, 127 insertions(+), 24 deletions(-) diff --git a/inc/config.h b/inc/config.h index c336c51..680d893 100644 --- a/inc/config.h +++ b/inc/config.h @@ -1,9 +1,20 @@ #ifndef CONFIG_H # define CONFIG_H -# define MANDEL_WINDOW_WIDTH 640 -# define MANDEL_WINDOW_HEIGHT 480 +# include "mandel.h" + +# define MANDEL_WINDOW_WIDTH 400 +# define MANDEL_WINDOW_HEIGHT 400 # define MANDEL_WINDOW_TITLE "Mandelbrot" # define MANDEL_ITERATIONS 50 +static ControlPoint g_theme[] = { + {0.0, {0x00, 0x0F, 0x64} }, + {0.16, {0x20, 0x6B, 0xCB} }, + {0.42, {0xED, 0xFF, 0xFF} }, + {0.6425, {0xFF, 0xAA, 0x00} }, + {1.0, {0x00, 0x02, 0x00} }, + // {0.8575, {0x00, 0x02, 0x00} }, +}; + #endif diff --git a/inc/mandel.h b/inc/mandel.h index 0383a39..a2af137 100644 --- a/inc/mandel.h +++ b/inc/mandel.h @@ -56,6 +56,12 @@ typedef struct double y; } Point; +typedef struct +{ + float position; + Color color; +} ControlPoint; + typedef struct { unsigned int id; diff --git a/src/color.c b/src/color.c index 24ca2f2..40d43d5 100644 --- a/src/color.c +++ b/src/color.c @@ -1,19 +1,95 @@ #include "mandel.h" +#include "config.h" #define MAX(x, y) (x > y ? x : y) #define MIN(x, y) (x < y ? x : y) static Color color_hsl_to_rgb(ColorHSL color_hsl); +static Color *st_hsl_rainbow(int count); +static int st_compar_control_points(const void *ptr1, const void *ptr2); +static Color *st_linear_iterpolation(int count, ControlPoint *points, size_t points_count); unsigned int color_texture_new(int count) { - ColorHSL hsl; - Color *palette; unsigned int texture; + Color *palette; - palette = malloc(sizeof(Color) * count); - if (palette == NULL) + if ((palette = st_hsl_rainbow(count)) == NULL) return 0; + /* if ((palette = st_linear_iterpolation(count, g_theme, sizeof(g_theme) / sizeof(ControlPoint))) == NULL) */ + /* return 0; */ + GL_CALL(glGenTextures(1, &texture)); + GL_CALL(glBindTexture(GL_TEXTURE_1D, texture)); + GL_CALL(glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MIN_FILTER, GL_NEAREST)); + GL_CALL(glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MAG_FILTER, GL_NEAREST)); + GL_CALL(glTexImage1D(GL_TEXTURE_1D, 0, GL_RGB, count + 1, 0, GL_RGB, GL_UNSIGNED_BYTE, palette)); + free(palette); + return texture; +} + +static Color *st_linear_iterpolation(int count, ControlPoint *points, size_t points_count) +{ + Color *palette; + + if (points_count < 2) + return NULL; + if ((palette = malloc(sizeof(Color) * count)) == NULL) + return NULL; + qsort(points, points_count, sizeof(ControlPoint), st_compar_control_points); + + size_t point_i = 0; + + double x0 = points[point_i].position; + double x1 = points[point_i + 1].position; + + double y0 = points[point_i].color.r; + double y1 = points[point_i + 1].color.r; + + double delta_x = x1 - x0; + double delta_y = y1 - y0; + + double m = delta_x / delta_y; + double b = y0 - x0; + + double red = 0; + for (int i = 0; i < count; i++) + { + palette[i].r = (uint8_t)(255.0 * (m * red + b)); + red += 1.0 / (double)count; + if (red >= x1) + { + if (point_i >= points_count) + break; + x0 = x1; + point_i++; + x1 = points[point_i + 1].position; + } + palette[i].g = 0; + palette[i].b = 0; + printf("%d\n", i); + } + return palette; +} + +static int st_compar_control_points(const void *ptr1, const void *ptr2) +{ + const ControlPoint *point1 = ptr1; + const ControlPoint *point2 = ptr2; + + if (point1->position < point2->position) + return -1; + if (point1->position > point2->position) + return 1; + return 0; +} + +static Color *st_hsl_rainbow(int count) +{ + ColorHSL hsl; + Color *palette; + + if ((palette = malloc(sizeof(Color) * count)) == NULL) + return NULL; for (int i = 0; i < count; i++) { hsl.h = (uint8_t)(255.0 * ((double)i / (double)count)); @@ -27,14 +103,7 @@ unsigned int color_texture_new(int count) palette[i] = palette[j]; palette[j] = tmp; } - - GL_CALL(glGenTextures(1, &texture)); - GL_CALL(glBindTexture(GL_TEXTURE_1D, texture)); - GL_CALL(glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MIN_FILTER, GL_NEAREST)); - GL_CALL(glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MAG_FILTER, GL_NEAREST)); - GL_CALL(glTexImage1D(GL_TEXTURE_1D, 0, GL_RGB, count + 1, 0, GL_RGB, GL_UNSIGNED_BYTE, palette)); - free(palette); - return texture; + return palette; } static Color color_hsl_to_rgb(ColorHSL color_hsl) diff --git a/src/event.c b/src/event.c index 9d384fc..d5f1180 100644 --- a/src/event.c +++ b/src/event.c @@ -6,6 +6,7 @@ static void st_move_horizontal(State *state, bool move_right); static void st_move_vertical(State *state, bool move_down); static void st_set_key(SDL_Keycode sym, bool value); static void st_apply_keys(State *state); +static void st_resize(State *state, int new_width, int new_height); static bool g_key_states[] = { [KEY_UP] = false, @@ -60,22 +61,37 @@ void event_handle(State *state) case SDL_WINDOWEVENT: if (e.window.event == SDL_WINDOWEVENT_RESIZED) - { - double w_ratio = (double)state->width / (double)e.window.data1; - double h_ratio = (double)state->height / (double)e.window.data2; - SDL_GL_GetDrawableSize(state->window, &state->width, &state->height); - GL_CALL(glViewport(0, 0, state->width, state->height)); - state->real_start /= w_ratio; - state->real_end /= w_ratio; - state->imag_start /= h_ratio; - state->imag_end /= h_ratio; - } + st_resize(state, e.window.data1, e.window.data2); break; } } st_apply_keys(state); } +void st_resize(State *state, int new_width, int new_height) +{ + double w_delta = ((double)new_width - (double)state->width) / 2.0; + double h_delta = ((double)new_height - (double)state->height) / 2.0; + + double real_dist = state->real_end - state->real_start; + double imag_dist = state->imag_end - state->imag_start; + + double width_real_ratio = (double)state->width / real_dist; + double height_imag_ratio = (double)state->height / imag_dist; + + w_delta /= width_real_ratio; + h_delta /= height_imag_ratio; + + state->real_start -= w_delta; + state->real_end += w_delta; + + state->imag_start -= h_delta; + state->imag_end += h_delta; + + SDL_GL_GetDrawableSize(state->window, &state->width, &state->height); + GL_CALL(glViewport(0, 0, state->width, state->height)); +} + static void st_set_key(SDL_Keycode sym, bool value) { switch (sym) diff --git a/src/state.c b/src/state.c index f661de6..5df4f02 100644 --- a/src/state.c +++ b/src/state.c @@ -54,6 +54,7 @@ bool state_init(State *state) state->real_end = 2.0; state->imag_start = -2.0; state->imag_end = 2.0; + state->running = true; state->smooth = false; state->samples = 1.0; -- cgit