Mercurial > public > algo-animator
comparison main.c @ 21:8a5a7aee69ce
add description
author | Dennis C. M. <dennis@denniscm.com> |
---|---|
date | Tue, 27 Jun 2023 20:04:25 +0100 |
parents | fc44102980fb |
children |
comparison
equal
deleted
inserted
replaced
20:fc44102980fb | 21:8a5a7aee69ce |
---|---|
6 #include <stdbool.h> | 6 #include <stdbool.h> |
7 #include <ft2build.h> | 7 #include <ft2build.h> |
8 #include FT_FREETYPE_H | 8 #include FT_FREETYPE_H |
9 | 9 |
10 | 10 |
11 #define WINDOW_WIDTH 1920 | |
11 #define WINDOW_HEIGHT 1080 | 12 #define WINDOW_HEIGHT 1080 |
12 #define WINDOW_WIDTH 1920 | |
13 #define VPADDING 150 | 13 #define VPADDING 150 |
14 #define RECT_WIDTH 5 | 14 #define RECT_WIDTH 5 |
15 #define SPACE 1 | 15 #define SPACE 1 |
16 | 16 |
17 | 17 |
18 /* Global variables */ | 18 /* Helper functions */ |
19 | 19 |
20 FT_Library ft_library; | 20 struct Element { |
21 FT_Face ft_face; | 21 float value; |
22 bool current; | |
23 }; | |
24 | |
25 struct Element *arr; | |
26 int arr_size; | |
27 | |
28 void create_array() { | |
29 arr_size = WINDOW_WIDTH / (RECT_WIDTH + SPACE); | |
30 arr = malloc(arr_size * sizeof(struct Element)); | |
31 | |
32 float rect_increase = (WINDOW_HEIGHT - VPADDING * 2) / (float)(arr_size - 1); | |
33 | |
34 for (int i = 1; i <= arr_size; i++) { | |
35 arr[i - 1].value = i * rect_increase; | |
36 arr[i - 1].current = false; | |
37 } | |
38 } | |
39 | |
40 | |
41 void swap_elements(int x, int y) { | |
42 struct Element temp = arr[x]; | |
43 arr[x] = arr[y]; | |
44 arr[y] = temp; | |
45 } | |
46 | |
47 | |
48 void randomize_array() { | |
49 srand(time(NULL)); | |
50 | |
51 // Fisher-Yates shuffle | |
52 for (int i = arr_size - 1; i > 0; i--) { | |
53 int j = rand() % (i + 1); | |
54 | |
55 // Swap | |
56 swap_elements(i, j); | |
57 } | |
58 } | |
59 | |
60 | |
61 bool array_sorted() { | |
62 for (int i = 0; i < arr_size - 1; i++) { | |
63 if (arr[i].value > arr[i + 1].value) { | |
64 return false; | |
65 } | |
66 } | |
67 | |
68 return true; | |
69 } | |
70 | |
22 | 71 |
23 struct Algo { | 72 struct Algo { |
24 char name[50]; | 73 char name[50]; |
25 void (*function)(); | 74 void (*function)(); |
26 }; | 75 }; |
27 | 76 |
28 struct Algo algos[2]; | 77 struct Algo algos[2]; |
29 | |
30 int selected_algo = 0; | 78 int selected_algo = 0; |
31 int speed = 1; | 79 |
32 int refresh_counter = 0; | 80 void algo_selector(int direction) { |
33 int iter_counter = 0; | 81 int selection = selected_algo + direction; |
34 int arr_size; | 82 int lower = 0; |
35 | 83 int upper = (sizeof(algos) / sizeof(algos[0])) - 1; |
36 | 84 |
37 struct Element { | 85 if (selection >= lower && selection <= upper) { |
38 float value; | 86 selected_algo = selection; |
39 bool current; | 87 } |
40 }; | 88 } |
41 | |
42 struct Element *arr; | |
43 | |
44 bool run; | |
45 | 89 |
46 | 90 |
47 /* Algorithms */ | 91 /* Algorithms */ |
48 | 92 |
49 // Just some variables to store the state of the running algorithm | 93 // Just some variables to store the state of the running algorithm |
51 int a; | 95 int a; |
52 int b; | 96 int b; |
53 int c; | 97 int c; |
54 }; | 98 }; |
55 | 99 |
56 struct AlgoState as = {0, 0, 0}; | 100 struct AlgoState as; |
57 | 101 |
58 | 102 void reset_state() { |
59 void swap_elements(int x, int y) { | 103 as.a = 0; |
60 struct Element temp = arr[x]; | 104 as.b = 0; |
61 arr[x] = arr[y]; | 105 as.c = 0; |
62 arr[y] = temp; | |
63 } | 106 } |
64 | 107 |
65 | 108 |
66 void bubble_sort() { | 109 void bubble_sort() { |
67 | 110 |
90 /* | 133 /* |
91 * a: Index of current selection | 134 * a: Index of current selection |
92 * b: Index of boundary of sorted array | 135 * b: Index of boundary of sorted array |
93 * c: Index of the minimum element | 136 * c: Index of the minimum element |
94 */ | 137 */ |
95 | 138 |
96 | 139 |
97 if (as.a < arr_size) { | 140 if (as.a < arr_size) { |
98 arr[as.a].current = true; | 141 arr[as.a].current = true; |
99 | 142 |
100 if (arr[as.a].value < arr[as.c].value) { | 143 if (arr[as.a].value < arr[as.c].value) { |
101 | 144 |
102 // Save new minimum | 145 // Save new minimum |
103 as.c = as.a; | 146 as.c = as.a; |
104 } | 147 } |
105 | 148 |
106 as.a++; | 149 as.a++; |
112 as.c = as.a; | 155 as.c = as.a; |
113 } | 156 } |
114 } | 157 } |
115 | 158 |
116 | 159 |
117 /* Helper functions */ | 160 void quick_sort() { |
118 | 161 |
119 void create_array() { | 162 } |
120 arr_size = WINDOW_WIDTH / (RECT_WIDTH + SPACE); | 163 |
121 arr = malloc(arr_size * sizeof(struct Element)); | 164 |
122 | 165 void insertion_sort() { |
123 float rect_increase = (WINDOW_HEIGHT - VPADDING * 2) / (float)(arr_size - 1); | 166 |
124 | 167 } |
125 for (int i = 1; i <= arr_size; i++) { | 168 |
126 arr[i - 1].value = i * rect_increase; | 169 |
127 arr[i - 1].current = false; | 170 void merge_sort() { |
128 } | 171 |
129 } | 172 } |
130 | |
131 | |
132 void randomize_array() { | |
133 srand(time(NULL)); | |
134 | |
135 // Fisher-Yates shuffle | |
136 for (int i = arr_size - 1; i > 0; i--) { | |
137 int j = rand() % (i + 1); | |
138 | |
139 // Swap | |
140 swap_elements(i, j); | |
141 } | |
142 } | |
143 | |
144 | |
145 bool array_sorted() { | |
146 for (int i = 0; i < arr_size - 1; i++) { | |
147 if (arr[i].value > arr[i + 1].value) { | |
148 return false; | |
149 } | |
150 } | |
151 | |
152 return true; | |
153 } | |
154 | |
155 | |
156 void algo_selector(int direction) { | |
157 int selection = selected_algo + direction; | |
158 int lower = 0; | |
159 int upper = (sizeof(algos) / sizeof(algos[0])) - 1; | |
160 | |
161 if (selection >= lower && selection <= upper) { | |
162 selected_algo = selection; | |
163 } | |
164 } | |
165 | |
166 | |
167 | 173 |
168 | 174 |
169 /* Render functions */ | 175 /* Render functions */ |
176 | |
177 FT_Library ft_library; | |
178 FT_Face ft_face; | |
170 | 179 |
171 void render_text(int x, int y, char* text) { | 180 void render_text(int x, int y, char* text) { |
172 for (const char *c = text; *c; c++) { | 181 for (const char *c = text; *c; c++) { |
173 | 182 |
174 // Get glyph index from character code | 183 // Get glyph index from character code |
175 FT_UInt glyph_index = FT_Get_Char_Index(ft_face, *c); | 184 FT_UInt glyph_index = FT_Get_Char_Index(ft_face, *c); |
176 | 185 |
177 if (glyph_index == 0) { | 186 if (glyph_index == 0) { |
178 fprintf(stderr, "Given character code has no glyph image in the face\n"); | 187 fprintf(stderr, "Given character code has no glyph image in the face\n"); |
201 unsigned char* src_row = glyph_bitmap->buffer + (row * glyph_bitmap->width); | 210 unsigned char* src_row = glyph_bitmap->buffer + (row * glyph_bitmap->width); |
202 unsigned char* dest_row = flipped_bitmap + ((glyph_bitmap->rows - row - 1) * glyph_bitmap->width); | 211 unsigned char* dest_row = flipped_bitmap + ((glyph_bitmap->rows - row - 1) * glyph_bitmap->width); |
203 memcpy(dest_row, src_row, glyph_bitmap->width); | 212 memcpy(dest_row, src_row, glyph_bitmap->width); |
204 } | 213 } |
205 | 214 |
206 glyph_bitmap->buffer = flipped_bitmap; | 215 glyph_bitmap->buffer = flipped_bitmap; |
207 | 216 |
208 // Calculate the adjusted y position based on the glyph's bearing | 217 // Calculate the adjusted y position based on the glyph's bearing |
209 int adjusted_y = y + (slot->bitmap_top - glyph_bitmap->rows); | 218 int adjusted_y = y + (slot->bitmap_top - glyph_bitmap->rows); |
210 | 219 |
211 glRasterPos2f(x, adjusted_y); | 220 glRasterPos2f(x, adjusted_y); |
212 glDrawPixels(glyph_bitmap->width, glyph_bitmap->rows, GL_LUMINANCE, GL_UNSIGNED_BYTE, glyph_bitmap->buffer); | 221 glDrawPixels(glyph_bitmap->width, glyph_bitmap->rows, GL_LUMINANCE, GL_UNSIGNED_BYTE, glyph_bitmap->buffer); |
213 | 222 |
214 x += slot->advance.x / 64; | 223 x += slot->advance.x / 64; |
215 } | 224 } |
216 } | 225 } |
217 | 226 |
218 | 227 |
228 int speed = 50; | |
229 int iter_counter = 0; | |
230 | |
219 void display() { | 231 void display() { |
220 glClear(GL_COLOR_BUFFER_BIT); | 232 glClear(GL_COLOR_BUFFER_BIT); |
221 | 233 |
222 glBegin(GL_QUADS); | 234 glBegin(GL_QUADS); |
223 | 235 |
224 int x = 0; | 236 int x = 0; |
225 for (int i = 0; i < arr_size; i++) { | 237 for (int i = 0; i < arr_size; i++) { |
226 | 238 |
227 if (arr[i].current) { | 239 if (arr[i].current) { |
228 glColor3f(1.0, 1.0, 1.0); | 240 glColor3f(1.0, 1.0, 1.0); |
229 } else { | 241 } else { |
230 glColor3f(1.0, 0.7569, 0.0); | 242 glColor3f(1.0, 0.7569, 0.0); |
231 } | 243 } |
253 char text[256]; | 265 char text[256]; |
254 | 266 |
255 // Top: Column 1 | 267 // Top: Column 1 |
256 sprintf(text, "Algorithm: %s", algos[selected_algo].name); | 268 sprintf(text, "Algorithm: %s", algos[selected_algo].name); |
257 render_text(20, WINDOW_HEIGHT - 50, text); | 269 render_text(20, WINDOW_HEIGHT - 50, text); |
258 | 270 |
259 sprintf(text, "Speed: %i", speed); | 271 sprintf(text, "Speed: %i", speed); |
260 render_text(20, WINDOW_HEIGHT - 80, text); | 272 render_text(20, WINDOW_HEIGHT - 80, text); |
261 | 273 |
262 // Top: Column 2 | 274 // Top: Column 2 |
263 sprintf(text, "Number of elements: %i", arr_size); | 275 sprintf(text, "Number of elements: %i", arr_size); |
264 render_text(500, WINDOW_HEIGHT - 50, text); | 276 render_text(500, WINDOW_HEIGHT - 50, text); |
265 | 277 |
266 sprintf(text, "Iterations: %i", iter_counter); | 278 sprintf(text, "Iterations: %i", iter_counter); |
272 render_text(20, VPADDING - 80, "Press u or d to modify speed."); | 284 render_text(20, VPADDING - 80, "Press u or d to modify speed."); |
273 render_text(20, VPADDING - 110, "Press r to randomize the array."); | 285 render_text(20, VPADDING - 110, "Press r to randomize the array."); |
274 | 286 |
275 // Bottom: Column 2 | 287 // Bottom: Column 2 |
276 render_text(800, VPADDING - 50, "Press enter to run the algorithm."); | 288 render_text(800, VPADDING - 50, "Press enter to run the algorithm."); |
289 render_text(800, VPADDING - 80, "Press p to pause the algorithm."); | |
277 | 290 |
278 glutSwapBuffers(); | 291 glutSwapBuffers(); |
279 } | 292 } |
280 | 293 |
281 | 294 |
282 /* Refresh function */ | 295 /* Refresh function */ |
296 | |
297 | |
298 bool run; | |
299 int refresh_counter = 0; | |
283 | 300 |
284 void idle() { | 301 void idle() { |
285 if (run) { | 302 if (run) { |
286 algos[selected_algo].function(); | 303 algos[selected_algo].function(); |
287 refresh_counter++; | 304 refresh_counter++; |
324 iter_counter = 0; | 341 iter_counter = 0; |
325 refresh_counter = 0; | 342 refresh_counter = 0; |
326 run = false; | 343 run = false; |
327 | 344 |
328 // Reset algo steps | 345 // Reset algo steps |
329 as = (struct AlgoState){0, 0}; | 346 reset_state(); |
330 } | 347 } |
331 | 348 |
332 // u: Increase speed | 349 // u: Increase speed |
333 if (key == 117) { | 350 if (key == 117) { |
334 speed++; | 351 speed++; |
335 } | 352 } |
336 | 353 |
338 if (key == 100) { | 355 if (key == 100) { |
339 if (speed > 1) { | 356 if (speed > 1) { |
340 speed--; | 357 speed--; |
341 } | 358 } |
342 } | 359 } |
343 | 360 |
344 // enter: Run program | 361 // enter: Run program |
345 if (key == 13) { | 362 if (key == 13) { |
346 run = true; | 363 run = true; |
347 } | 364 } |
348 | 365 |
349 // p: Pause program | 366 // p: Pause program |
350 if (key == 112) { | 367 if (key == 112) { |
351 run = false; | 368 run = false; |
352 } | 369 } |
353 | |
354 | |
355 } | 370 } |
356 | 371 |
357 | 372 |
358 /* Set up functions */ | 373 /* Set up functions */ |
359 | 374 |
417 strcpy(algos[0].name, "Bubble sort"); | 432 strcpy(algos[0].name, "Bubble sort"); |
418 algos[0].function = &bubble_sort; | 433 algos[0].function = &bubble_sort; |
419 | 434 |
420 strcpy(algos[1].name, "Selection sort"); | 435 strcpy(algos[1].name, "Selection sort"); |
421 algos[1].function = &selection_sort; | 436 algos[1].function = &selection_sort; |
422 | 437 |
423 create_array(); | 438 create_array(); |
424 | 439 |
425 glutInit(&argc, argv); | 440 glutInit(&argc, argv); |
426 glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB); | 441 glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB); |
427 glutInitWindowSize(WINDOW_WIDTH, WINDOW_HEIGHT); | 442 glutInitWindowSize(WINDOW_WIDTH, WINDOW_HEIGHT); |
436 glutMainLoop(); | 451 glutMainLoop(); |
437 | 452 |
438 free(arr); | 453 free(arr); |
439 | 454 |
440 FT_Done_Face(ft_face); | 455 FT_Done_Face(ft_face); |
441 FT_Done_FreeType(ft_library); | 456 FT_Done_FreeType(ft_library); |
442 | 457 |
443 return 0; | 458 return 0; |
444 } | 459 } |