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