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