Nilorea Library
C utilities for networking, threading, graphics
Loading...
Searching...
No Matches
ex_fluid.c
Go to the documentation of this file.
1/*
2 * Nilorea Library
3 * Copyright (C) 2005-2026 Castagnier Mickael
4 *
5 * This program is free software: you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation, either version 3 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program. If not, see <https://www.gnu.org/licenses/>.
17 */
18
27#define ALLEGRO_UNSTABLE 1
28
29#include <locale.h>
30
31#include "nilorea/n_common.h"
32#include "nilorea/n_log.h"
33#include "nilorea/n_list.h"
34#include "nilorea/n_str.h"
35#include "nilorea/n_time.h"
36#include "nilorea/n_fluids.h"
37
38#include <allegro5/allegro.h>
39#include <allegro5/allegro_ttf.h>
40#include "allegro5/allegro_audio.h"
41#include "allegro5/allegro_acodec.h"
42#include <allegro5/allegro_font.h>
43#include <allegro5/allegro_image.h>
44#include <allegro5/allegro_primitives.h>
45
46#include "ex_fluid_config.h"
47
49#define RESERVED_SAMPLES 16
51#define MAX_SAMPLE_DATA 10
52
53ALLEGRO_DISPLAY* display = NULL;
54
55/******************************************************************************
56 * VARIOUS DECLARATIONS *
57 ******************************************************************************/
58
59int DONE = 0, /* Flag to check if we are always running */
60 getoptret = 0, /* launch parameter check */
61 log_level = LOG_ERR; /* default LOG_LEVEL */
62
63double drawFPS = 60.0;
64double logicFPS = 120.0;
65
66ALLEGRO_TIMER* fps_timer = NULL;
67ALLEGRO_TIMER* logic_timer = NULL;
70
72int WIDTH = 800,
73 HEIGHT = 600;
74bool fullscreen = 0;
75char* bgmusic = NULL;
76
78
79int main(int argc, char* argv[]) {
80 /* Set the locale to the POSIX C environment */
81 setlocale(LC_ALL, "POSIX");
82
84
85 N_STR* log_file = NULL;
86 nstrprintf(log_file, "%s.log", argv[0]);
87 /*set_log_file( _nstr( log_file ) );*/
89
90 char ver_str[128] = "";
91
92 while ((getoptret = getopt(argc, argv, "hvV:L:")) != EOF) {
93 switch (getoptret) {
94 case 'h':
95 n_log(LOG_NOTICE, "\n %s -h help -v version -V DEBUGLEVEL (NOLOG,VERBOSE,NOTICE,ERROR,DEBUG)\n", argv[0]);
96 exit(TRUE);
97 case 'v':
98 sprintf(ver_str, "%s %s", __DATE__, __TIME__);
99 exit(TRUE);
100 break;
101 case 'V':
102 if (!strncmp("INFO", optarg, 6)) {
104 } else {
105 if (!strncmp("NOTICE", optarg, 6)) {
107 } else {
108 if (!strncmp("VERBOSE", optarg, 7)) {
110 } else {
111 if (!strncmp("ERROR", optarg, 5)) {
113 } else {
114 if (!strncmp("DEBUG", optarg, 5)) {
116 } else {
117 n_log(LOG_ERR, "%s is not a valid log level", optarg);
118 exit(FALSE);
119 }
120 }
121 }
122 }
123 }
124 n_log(LOG_NOTICE, "LOG LEVEL UP TO: %d", log_level);
126 break;
127 case 'L':
128 n_log(LOG_NOTICE, "LOG FILE: %s", optarg);
129 set_log_file(optarg);
130 break;
131 case '?': {
132 switch (optopt) {
133 case 'V':
134 n_log(LOG_ERR, "\nPlease specify a log level after -V. \nAvailable values: NOLOG,VERBOSE,NOTICE,ERROR,DEBUG");
135 break;
136 case 'L':
137 n_log(LOG_ERR, "\nPlease specify a log file after -L");
138 default:
139 break;
140 }
141 }
142 __attribute__((fallthrough));
143 default:
144 n_log(LOG_ERR, "\n %s -h help -v version -V DEBUGLEVEL (NOLOG,VERBOSE,NOTICE,ERROR,DEBUG) -L logfile", argv[0]);
145 exit(FALSE);
146 }
147 }
148 /*
149 * INITIALISATION
150 */
151 int threadedProcessing = 0;
152 N_FLUID* fluid_data = NULL;
153 Malloc(fluid_data, N_FLUID, 1);
154 if (load_app_state("CONFIGS/ex_fluid.cfg", &WIDTH, &HEIGHT, &fullscreen, &bgmusic, &drawFPS, &logicFPS, fluid_data, &threadedProcessing) != TRUE) {
155 n_log(LOG_ERR, "couldn't load CONFIGS/ex_fluid.cfg !");
156 exit(1);
157 }
158 double fluid_factor = fluid_data->cScale;
159 n_log(LOG_DEBUG, "%s starting with params: %dx%d fullscreen(%d), music: %s", argv[0], WIDTH, HEIGHT, fullscreen, _str(bgmusic));
160
161 /* allegro 5 + addons loading */
162 if (!al_init()) {
163 n_abort("Could not init Allegro.\n");
164 }
165 if (!al_init_acodec_addon()) {
166 n_abort("Could not register addons.\n");
167 }
168 if (!al_install_audio()) {
169 n_log(LOG_ERR, "Unable to initialize audio addon, disabling bgmusic\n");
170 Free(bgmusic);
171 }
172 if (!al_init_acodec_addon()) {
173 n_abort("Unable to initialize acoded addon\n");
174 }
175 if (!al_init_image_addon()) {
176 n_abort("Unable to initialize image addon\n");
177 }
178 if (!al_init_primitives_addon()) {
179 n_abort("Unable to initialize primitives addon\n");
180 }
181 if (!al_init_font_addon()) {
182 n_abort("Unable to initialize font addon\n");
183 }
184 if (!al_init_ttf_addon()) {
185 n_abort("Unable to initialize ttf_font addon\n");
186 }
187 if (!al_install_keyboard()) {
188 n_abort("Unable to initialize keyboard handler\n");
189 }
190 if (!al_install_mouse()) {
191 n_abort("Unable to initialize mouse handler\n");
192 }
193
194 if (bgmusic && !al_reserve_samples(RESERVED_SAMPLES)) {
195 n_abort("Could not set up voice and mixer.\n");
196 }
197
198 ALLEGRO_SAMPLE* sample_data[MAX_SAMPLE_DATA] = {NULL};
199 memset(sample_data, 0, sizeof(sample_data));
200
201 ALLEGRO_EVENT_QUEUE* event_queue = NULL;
202
203 event_queue = al_create_event_queue();
204 if (!event_queue) {
205 fprintf(stderr, "failed to create event_queue!\n");
206 return -1;
207 }
208
209 if (fullscreen) {
210 al_set_new_display_flags(ALLEGRO_OPENGL | ALLEGRO_FULLSCREEN_WINDOW);
211 } else {
212 al_set_new_display_flags(ALLEGRO_OPENGL | ALLEGRO_WINDOWED);
213 }
214
215#ifdef __windows__
216 al_set_new_bitmap_flags(ALLEGRO_VIDEO_BITMAP | ALLEGRO_NO_PRESERVE_TEXTURE);
217#endif
218
219 display = al_create_display(WIDTH, HEIGHT);
220 if (!display) {
221 n_abort("Unable to create display\n");
222 }
223
224 al_set_window_title(display, argv[0]);
225
226 ALLEGRO_FONT* font = al_load_font("DATAS/2Dumb.ttf", 18, 0);
227 if (!font) {
228 n_abort("Unable to load font DATAS/2Dumb.ttf\n");
229 }
230
231 DONE = 0;
232 fps_timer = al_create_timer(1.0 / drawFPS);
233 logic_timer = al_create_timer(1.0 / logicFPS);
234
235 al_register_event_source(event_queue, al_get_display_event_source(display));
236 al_start_timer(fps_timer);
237 al_start_timer(logic_timer);
238 al_register_event_source(event_queue, al_get_timer_event_source(fps_timer));
239 al_register_event_source(event_queue, al_get_timer_event_source(logic_timer));
240
241 al_register_event_source(event_queue, al_get_keyboard_event_source());
242 al_register_event_source(event_queue, al_get_mouse_event_source());
243
244 bool backbuffer = 1;
245 ALLEGRO_BITMAP* scrbuf = NULL;
246 ALLEGRO_BITMAP* bitmap = NULL;
247
248 al_hide_mouse_cursor(display);
249
250 enum APP_KEYS {
251 KEY_UP,
252 KEY_DOWN,
253 KEY_LEFT,
254 KEY_RIGHT,
255 KEY_ESC,
256 KEY_SPACE,
257 KEY_CTRL,
258 KEY_SHIFT,
259 KEY_PAD_MINUS,
260 KEY_PAD_PLUS,
261 KEY_PAD_ENTER,
262 KEY_M,
263 KEY_W,
264 KEY_F1,
265 KEY_F2,
266 KEY_F3,
267 KEY_F4,
268 KEY_F5,
269 KEY_F6
270 };
271 int key[19] = {false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false};
272
273 if (bgmusic) {
274 if (!(sample_data[0] = al_load_sample(bgmusic))) {
275 n_log(LOG_ERR, "Could not load %s", bgmusic);
276 exit(1);
277 }
278 al_play_sample(sample_data[0], 1, 0, 1, ALLEGRO_PLAYMODE_LOOP, NULL);
279 }
280
281 long int nb_cores = get_nb_cpu_cores();
282 if (nb_cores <= 0) {
283 nb_cores = 1;
284 }
285 thread_pool = new_thread_pool((size_t)nb_cores, 0);
286
287 /* set fluid */
288 fluid_sim = new_n_fluid(fluid_data->density, fluid_data->gravity, fluid_data->numIters, fluid_data->fluid_production_percentage, fluid_data->overRelaxation, (size_t)(WIDTH / fluid_factor), (size_t)(HEIGHT / fluid_factor));
289
290 fluid_sim->density = fluid_data->density;
291 fluid_sim->gravity = fluid_data->gravity;
292 fluid_sim->numIters = fluid_data->numIters;
295 fluid_sim->cScale = fluid_data->cScale;
296 Free(fluid_data);
297
298 fluid_sim->dt = 1.0 / logicFPS;
299
300 size_t n = fluid_sim->numY;
301 double inVel = 2.0;
302 for (size_t i = 0; i < fluid_sim->numX; i++) {
303 for (size_t j = 0; j < fluid_sim->numY; j++) {
304 double s = 1.0; // fluid
305 if (i == 0 || j == 0 || j == fluid_sim->numY - 1)
306 s = 0.0; // solid
307 //
308 fluid_sim->s[i * n + j] = s;
309
310 if (i == 1) {
311 fluid_sim->u[i * n + j] = inVel;
312 }
313 }
314 }
315 double pipeH = fluid_sim->fluid_production_percentage * (double)fluid_sim->numY;
316 size_t minJ = (size_t)floor(0.5 * (double)fluid_sim->numY - 0.5 * pipeH);
317 size_t maxJ = (size_t)floor(0.5 * (double)fluid_sim->numY + 0.5 * pipeH);
318 for (size_t j = 0; j < minJ; j++)
319 fluid_sim->m[j] = 1.0;
320 for (size_t j = minJ; j < maxJ; j++)
321 fluid_sim->m[j] = 0.0;
322 for (size_t j = maxJ; j < fluid_sim->numY; j++)
323 fluid_sim->m[j] = 1.0;
324
325 bool do_draw = 1, do_logic = 1;
326 int mx = WIDTH / 3, my = HEIGHT / 2, mouse_button = 0, mouse_b1 = 0, mouse_b2 = 0;
327
329
330 al_flush_event_queue(event_queue);
331 al_set_mouse_xy(display, WIDTH / 3, HEIGHT / 2);
332
333 int w = al_get_display_width(display);
334 int h = al_get_display_height(display);
335
336 bitmap = al_create_bitmap(WIDTH, HEIGHT);
337
338 size_t logic_duration = 0;
339 size_t drawing_duration = 0;
340 do {
341 do {
342 ALLEGRO_EVENT ev;
343
344 al_wait_for_event(event_queue, &ev);
345
346 if (ev.type == ALLEGRO_EVENT_KEY_DOWN) {
347 switch (ev.keyboard.keycode) {
348 case ALLEGRO_KEY_UP:
349 key[KEY_UP] = 1;
350 break;
351 case ALLEGRO_KEY_DOWN:
352 key[KEY_DOWN] = 1;
353 break;
354 case ALLEGRO_KEY_LEFT:
355 key[KEY_LEFT] = 1;
356 break;
357 case ALLEGRO_KEY_RIGHT:
358 key[KEY_RIGHT] = 1;
359 break;
360 case ALLEGRO_KEY_ESCAPE:
361 key[KEY_ESC] = 1;
362 break;
363 case ALLEGRO_KEY_SPACE:
364 key[KEY_SPACE] = 1;
365 break;
366 case ALLEGRO_KEY_LSHIFT:
367 case ALLEGRO_KEY_RSHIFT:
368 key[KEY_SHIFT] = 1;
369 break;
370 case ALLEGRO_KEY_PAD_MINUS:
371 key[KEY_PAD_MINUS] = 1;
372 break;
373 case ALLEGRO_KEY_PAD_PLUS:
374 key[KEY_PAD_PLUS] = 1;
375 break;
376 case ALLEGRO_KEY_PAD_ENTER:
377 key[KEY_PAD_ENTER] = 1;
378 break;
379 case ALLEGRO_KEY_M:
380 key[KEY_M] = 1;
381 break;
382 case ALLEGRO_KEY_W:
383 key[KEY_W] = 1;
384 break;
385 case ALLEGRO_KEY_LCTRL:
386 case ALLEGRO_KEY_RCTRL:
387 key[KEY_CTRL] = 1;
388 break;
389 case ALLEGRO_KEY_F1:
390 key[KEY_F1] = 1;
391 break;
392 case ALLEGRO_KEY_F2:
393 key[KEY_F2] = 1;
394 break;
395 case ALLEGRO_KEY_F3:
396 key[KEY_F3] = 1;
397 break;
398 case ALLEGRO_KEY_F4:
399 key[KEY_F4] = 1;
400 break;
401 case ALLEGRO_KEY_F5:
402 key[KEY_F5] = 1;
403 break;
404 case ALLEGRO_KEY_F6:
405 key[KEY_F6] = 1;
406 break;
407 default:
408 break;
409 }
410 } else if (ev.type == ALLEGRO_EVENT_KEY_UP) {
411 switch (ev.keyboard.keycode) {
412 case ALLEGRO_KEY_UP:
413 key[KEY_UP] = 0;
414 break;
415 case ALLEGRO_KEY_DOWN:
416 key[KEY_DOWN] = 0;
417 break;
418 case ALLEGRO_KEY_LEFT:
419 key[KEY_LEFT] = 0;
420 break;
421 case ALLEGRO_KEY_RIGHT:
422 key[KEY_RIGHT] = 0;
423 break;
424 case ALLEGRO_KEY_ESCAPE:
425 key[KEY_ESC] = 0;
426 break;
427 case ALLEGRO_KEY_SPACE:
428 key[KEY_SPACE] = 0;
429 break;
430 case ALLEGRO_KEY_LSHIFT:
431 case ALLEGRO_KEY_RSHIFT:
432 key[KEY_SHIFT] = 0;
433 break;
434 case ALLEGRO_KEY_PAD_MINUS:
435 key[KEY_PAD_MINUS] = 0;
436 break;
437 case ALLEGRO_KEY_PAD_PLUS:
438 key[KEY_PAD_PLUS] = 0;
439 break;
440 case ALLEGRO_KEY_PAD_ENTER:
441 key[KEY_PAD_ENTER] = 0;
442 break;
443 case ALLEGRO_KEY_M:
444 key[KEY_M] = 0;
445 break;
446 case ALLEGRO_KEY_W:
447 key[KEY_W] = 0;
448 break;
449 case ALLEGRO_KEY_LCTRL:
450 case ALLEGRO_KEY_RCTRL:
451 key[KEY_CTRL] = 0;
452 break;
453 case ALLEGRO_KEY_F1:
454 key[KEY_F1] = 0;
455 break;
456 case ALLEGRO_KEY_F2:
457 key[KEY_F2] = 0;
458 break;
459 case ALLEGRO_KEY_F3:
460 key[KEY_F3] = 0;
461 break;
462 case ALLEGRO_KEY_F4:
463 key[KEY_F4] = 0;
464 break;
465 case ALLEGRO_KEY_F5:
466 key[KEY_F5] = 0;
467 break;
468 case ALLEGRO_KEY_F6:
469 key[KEY_F6] = 0;
470 break;
471
472 default:
473 break;
474 }
475 } else if (ev.type == ALLEGRO_EVENT_TIMER) {
476 if (al_get_timer_event_source(fps_timer) == ev.any.source) {
477 do_draw = 1;
478 } else if (al_get_timer_event_source(logic_timer) == ev.any.source) {
479 do_logic = 1;
480 }
481 } else if (ev.type == ALLEGRO_EVENT_MOUSE_AXES) {
482 mx = ev.mouse.x;
483 my = ev.mouse.y;
484 } else if (ev.type == ALLEGRO_EVENT_MOUSE_BUTTON_DOWN) {
485 if (ev.mouse.button == 1)
486 mouse_b1 = 1;
487 if (ev.mouse.button == 2)
488 mouse_b2 = 1;
489 } else if (ev.type == ALLEGRO_EVENT_MOUSE_BUTTON_UP) {
490 if (ev.mouse.button == 1)
491 mouse_b1 = 0;
492 if (ev.mouse.button == 2)
493 mouse_b2 = 0;
494 }
495
496 /* Processing inputs */
497 mouse_button = -1;
498 if (mouse_b1 == 1)
499 mouse_button = 1;
500 if (mouse_b2 == 1)
501 mouse_button = 2;
502 else if (ev.type == ALLEGRO_EVENT_DISPLAY_SWITCH_IN || ev.type == ALLEGRO_EVENT_DISPLAY_SWITCH_OUT) {
503 al_clear_keyboard_state(display);
504 al_flush_event_queue(event_queue);
505 } else {
506 // Processing inputs
507 // get_keyboard( chat_line , ev );
508 if (key[KEY_F1]) {
509 fluid_sim->showSmoke = 1;
510 }
511 if (key[KEY_F2]) {
512 fluid_sim->showSmoke = 0;
513 }
514 if (key[KEY_F3]) {
516 }
517 if (key[KEY_F4]) {
519 }
520 if (key[KEY_F5]) {
521 fluid_sim->showPaint = 1;
522 }
523 if (key[KEY_F6]) {
524 fluid_sim->showPaint = 0;
525 }
526 if (key[KEY_UP]) {
527 fluid_sim->density += 100.0;
528 }
529 if (key[KEY_DOWN]) {
530 fluid_sim->density -= 100.0;
531 if (fluid_sim->density < 1.0) fluid_sim->density = 1.0;
532 }
533 if (key[KEY_LEFT]) {
535 }
536 if (key[KEY_RIGHT]) {
538 if (fluid_sim->numIters < 1.0) fluid_sim->numIters = 1.0;
539 }
540 if (key[KEY_PAD_PLUS]) {
543 }
544 if (key[KEY_PAD_MINUS]) {
547 }
548 if (mouse_button != -1) {
549 n_log(LOG_DEBUG, "mouse button: %d", mouse_button);
550 }
551 }
552 } while (!al_is_event_queue_empty(event_queue));
553
554 if (do_logic == 1) {
556 static int old_mx = -1, old_my = -1;
557 double vx = 0.0, vy = 0.0;
558 if (old_mx != mx || old_my != my) {
559 if (old_mx != -1 && old_my != -1) {
560 vx = (old_mx - mx) / logicFPS;
561 vy = (old_my - my) / logicFPS;
562 }
563 old_mx = mx;
564 old_my = my;
566 n_fluid_setObstacle(fluid_sim, mx / fluid_factor, (my / fluid_factor) - 20.0, vx, vy, fluid_factor / 2);
567 n_fluid_setObstacle(fluid_sim, (mx / fluid_factor) - 15, my / fluid_factor, vx, vy, fluid_factor / 2 + fluid_factor / 3);
568 n_fluid_setObstacle(fluid_sim, (mx / fluid_factor) + 15, my / fluid_factor - 10.0, vx, vy, fluid_factor / 2 + fluid_factor / 2);
569 n_fluid_setObstacle(fluid_sim, (mx / fluid_factor) + 15, my / fluid_factor + 10.0, vx, vy, fluid_factor / 2 + fluid_factor / 2);
570 n_fluid_setObstacle(fluid_sim, mx / fluid_factor, (my / fluid_factor) + 20.0, vx, vy, fluid_factor / 2);
571 }
572
574 minJ = (size_t)floor(0.5 * (double)fluid_sim->numY - 0.5 * pipeH);
575 maxJ = (size_t)floor(0.5 * (double)fluid_sim->numY + 0.5 * pipeH);
576 for (size_t j = 0; j < minJ; j++)
577 fluid_sim->m[j] = 1.0;
578 for (size_t j = minJ; j < maxJ; j++)
579 fluid_sim->m[j] = 0.0;
580 for (size_t j = maxJ; j < fluid_sim->numY; j++)
581 fluid_sim->m[j] = 1.0;
582 for (size_t j = minJ; j < maxJ; j++)
583 fluid_sim->m[j] = 0.0;
584
585 if (threadedProcessing == 1)
587 else
589
590 logic_duration = (logic_duration + (size_t)get_usec(&logic_chrono)) / 2;
591 do_logic = 0;
592 }
593 if (do_draw == 1) {
595
596 if (backbuffer)
597 scrbuf = al_get_backbuffer(display);
598 else
599 scrbuf = bitmap;
600
601 al_set_target_bitmap(scrbuf);
602
603 if (!backbuffer)
604 al_lock_bitmap(scrbuf, al_get_bitmap_format(scrbuf), ALLEGRO_LOCK_READWRITE);
605
607
608 al_draw_circle((float)mx, (float)(my - 20 * fluid_factor), (float)(fluid_factor * fluid_factor / 2), al_map_rgb(255, 0, 0), 2.0);
609 al_draw_circle((float)(mx - 15 * fluid_factor), (float)my, (float)(fluid_factor * fluid_factor / 2 + (fluid_factor * fluid_factor) / 3), al_map_rgb(255, 0, 0), 2.0);
610 al_draw_circle((float)(mx + 15 * fluid_factor), (float)(my + 10.0 * fluid_factor), (float)(fluid_factor * fluid_factor / 2 + (fluid_factor * fluid_factor) / 2), al_map_rgb(255, 0, 0), 2.0);
611 al_draw_circle((float)(mx + 15 * fluid_factor), (float)(my - 10.0 * fluid_factor), (float)(fluid_factor * fluid_factor / 2 + (fluid_factor * fluid_factor) / 2), al_map_rgb(255, 0, 0), 2.0);
612 al_draw_circle((float)mx, (float)(my + 20 * fluid_factor), (float)(fluid_factor * fluid_factor / 2), al_map_rgb(255, 0, 0), 2.0);
613
614 static N_STR* textout = NULL;
615 nstrprintf(textout, "[F1/F2]:showSmoke:%d [F3/F4]:showPressure:%d [F5/F6]:showPaint:%d", fluid_sim->showSmoke, fluid_sim->showPressure, fluid_sim->showPaint);
616 al_draw_text(font, al_map_rgb(0, 0, 255), (float)WIDTH, 10, ALLEGRO_ALIGN_RIGHT, _nstr(textout));
617
618 nstrprintf(textout, "numIters: %zd production: %3.3g density: %3.3g", fluid_sim->numIters, fluid_sim->fluid_production_percentage, fluid_sim->density);
619 al_draw_text(font, al_map_rgb(0, 0, 255), (float)WIDTH, 25, ALLEGRO_ALIGN_RIGHT, _nstr(textout));
620
621 nstrprintf(textout, "logic(max %zd): %zd usecs", (size_t)(1000000.0 / logicFPS), logic_duration);
622 al_draw_text(font, al_map_rgb(0, 0, 255), 5, 10, ALLEGRO_ALIGN_LEFT, _nstr(textout));
623
624 nstrprintf(textout, "drawing(max %zd): %zd usecs", (size_t)(1000000.0 / drawFPS), drawing_duration);
625 al_draw_text(font, al_map_rgb(0, 0, 255), 5, 30, ALLEGRO_ALIGN_LEFT, _nstr(textout));
626
627 if (!backbuffer) {
628 al_unlock_bitmap(scrbuf);
629 al_set_target_bitmap(al_get_backbuffer(display));
630 al_draw_bitmap(scrbuf, (float)(w / 2 - al_get_bitmap_width(scrbuf) / 2), (float)(h / 2 - al_get_bitmap_height(scrbuf) / 2), 0);
631 }
632
633 drawing_duration = (drawing_duration + (size_t)get_usec(&drawing_chrono)) / 2;
634
635 al_flip_display();
636
637 do_draw = 0;
638 }
639
640 } while (!key[KEY_ESC] && !DONE);
641
642 al_uninstall_system();
643
644 return 0;
645}
int main(void)
ALLEGRO_TIMER * fps_timer
Definition ex_fluid.c:66
THREAD_POOL * thread_pool
Definition ex_fluid.c:77
#define MAX_SAMPLE_DATA
audio MAX_SAMPLE_DATA for bgmusic
Definition ex_fluid.c:51
int getoptret
Definition ex_fluid.c:60
double drawFPS
Definition ex_fluid.c:63
int DONE
Definition ex_fluid.c:59
bool fullscreen
Definition ex_fluid.c:74
N_TIME drawing_chrono
Definition ex_fluid.c:69
N_FLUID * fluid_sim
Definition ex_fluid.c:71
N_TIME logic_chrono
Definition ex_fluid.c:68
int log_level
Definition ex_fluid.c:61
char * bgmusic
Definition ex_fluid.c:75
#define RESERVED_SAMPLES
audio RESERVED_SAMPLES for bgmusic
Definition ex_fluid.c:49
ALLEGRO_TIMER * logic_timer
Definition ex_fluid.c:67
double logicFPS
Definition ex_fluid.c:64
ALLEGRO_DISPLAY * display
Definition ex_fluid.c:53
int load_app_state(char *state_filename, int *WIDTH, int *HEIGHT, bool *fullscreen, char **bgmusic, double *drawFPS, double *logicFPS, N_FLUID *fluid, int *threaded)
Load application state from a config file.
#define WIDTH
Definition ex_gui.c:36
#define HEIGHT
Definition ex_gui.c:37
char * key
#define Malloc(__ptr, __struct, __size)
Malloc Handler to get errors and set to 0.
Definition n_common.h:203
#define _str(__PTR)
define true
Definition n_common.h:192
void n_abort(char const *format,...)
abort program with a text
Definition n_common.c:52
#define Free(__ptr)
Free Handler to get errors.
Definition n_common.h:262
#define _nstr(__PTR)
N_STR or "NULL" string for logging purposes.
Definition n_common.h:198
#define n_log(__LEVEL__,...)
Logging function wrapper to get line and func.
Definition n_log.h:88
#define LOG_DEBUG
debug-level messages
Definition n_log.h:83
#define LOG_ERR
error conditions
Definition n_log.h:75
int set_log_file(char *file)
Set the logging to a file instead of stderr.
Definition n_log.c:167
void set_log_level(const int log_level)
Set the global log level value ( static int LOG_LEVEL )
Definition n_log.c:120
#define LOG_NOTICE
normal but significant condition
Definition n_log.h:79
#define LOG_INFO
informational
Definition n_log.h:81
size_t numY
number of cells in Y
Definition n_fluids.h:73
double fluid_production_percentage
size of the produced fluid
Definition n_fluids.h:103
bool showSmoke
display fluid as a colored cloud instead of black and white, can be combined with showPressure
Definition n_fluids.h:91
size_t numX
number of cells in X
Definition n_fluids.h:71
double overRelaxation
over relaxation
Definition n_fluids.h:89
bool showPressure
display fluids pressures as color variations, can be combined with showSmoke
Definition n_fluids.h:95
bool showPaint
activate a fonky palette, override smoke and pressure display
Definition n_fluids.h:93
double * u
holder for u arrays
Definition n_fluids.h:108
double dt
time between frames
Definition n_fluids.h:83
double * s
holder for s arrays
Definition n_fluids.h:120
size_t numIters
number of fluid processing iterations for each frame
Definition n_fluids.h:79
double density
density of the fluid (not working ?)
Definition n_fluids.h:81
double * m
holder for m arrays
Definition n_fluids.h:123
double cScale
scale used to deduce cellX and cellY from screen/window width and height
Definition n_fluids.h:105
double gravity
gravity on Y
Definition n_fluids.h:87
int n_fluid_draw(N_FLUID *fluid)
draw a N_FLUID on screen / targert bitmap
Definition n_fluids.c:842
int n_fluid_simulate_threaded(N_FLUID *fluid, THREAD_POOL *thread_pool)
a threaded version of N_FLUID global processing function
Definition n_fluids.c:640
int n_fluid_simulate(N_FLUID *fluid)
non threaded version of N_FLUID global processing function
Definition n_fluids.c:623
int n_fluid_resetObstacles(N_FLUID *fluid)
reset the obstacles set in a N_FLUID
Definition n_fluids.c:739
int n_fluid_setObstacle(N_FLUID *fluid, double x, double y, double vx, double vy, double r)
set an obstacle in the fluid grid
Definition n_fluids.c:712
N_FLUID * new_n_fluid(double density, double gravity, size_t numIters, double dt, double overRelaxation, size_t sx, size_t sy)
return a newly allocated fluid
Definition n_fluids.c:95
structure of a fluid
Definition n_fluids.h:69
#define free_nstr(__ptr)
free a N_STR structure and set the pointer to NULL
Definition n_str.h:201
#define nstrprintf(__nstr_var, __format,...)
Macro to quickly allocate and sprintf to N_STR.
Definition n_str.h:115
A box including a string and his lenght.
Definition n_str.h:60
int start_HiTimer(N_TIME *timer)
Initialize or restart from zero any N_TIME HiTimer.
Definition n_time.c:84
time_t get_usec(N_TIME *timer)
Poll any N_TIME HiTimer, returning usec, and moving currentTime to startTime.
Definition n_time.c:106
Timing Structure.
Definition n_time.h:48
THREAD_POOL * new_thread_pool(size_t nbmaxthr, size_t nb_max_waiting)
Create a new pool of nbmaxthr threads.
long int get_nb_cpu_cores()
get number of core of current system
Structure of a thread pool.
Common headers and low-level functions & define.
Fluid management port from "How to write an Eulerian fluid simulator with 200 lines of code",...
List structures and definitions.
static FILE * log_file
static FILE handling if logging to file is enabled
Definition n_log.c:83
Generic log system.
__attribute__((unused))
Definition n_network.c:1233
N_STR and string function declaration.
Timing utilities.