Nilorea Library
C utilities for networking, threading, graphics
ex_fluid.c

ex_fluids Main File

ex_fluids Main File

Author
Castagnier Mickaƫl
Version
1.0
Date
30/12/2021
#include <locale.h>
#include "nilorea/n_log.h"
#include "nilorea/n_list.h"
#include "nilorea/n_str.h"
#include "nilorea/n_time.h"
#include <allegro5/allegro.h>
#include <allegro5/allegro_ttf.h>
#include "allegro5/allegro_audio.h"
#include "allegro5/allegro_acodec.h"
#include <allegro5/allegro_font.h>
#include <allegro5/allegro_image.h>
#include <allegro5/allegro_primitives.h>
#include "ex_fluid_config.h"
#define RESERVED_SAMPLES 16
#define MAX_SAMPLE_DATA 10
ALLEGRO_DISPLAY *display = NULL ;
/******************************************************************************
* VARIOUS DECLARATIONS *
******************************************************************************/
int DONE = 0, /* Flag to check if we are always running */
getoptret = 0, /* launch parameter check */
log_level = LOG_ERR ; /* default LOG_LEVEL */
double drawFPS = 60.0 ;
double logicFPS = 120.0 ;
ALLEGRO_TIMER *fps_timer = NULL ;
ALLEGRO_TIMER *logic_timer = NULL ;
N_TIME logic_chrono ;
N_TIME drawing_chrono ;
N_FLUID *fluid_sim = NULL ;
size_t WIDTH = 320 ,
HEIGHT = 200 ;
bool fullscreen = 0 ;
char *bgmusic = NULL ;
THREAD_POOL *thread_pool = NULL ;
int main( int argc, char *argv[] )
{
/* Set the locale to the POSIX C environment */
setlocale (LC_ALL, "POSIX");
N_STR *log_file = NULL ;
nstrprintf( log_file, "%s.log", argv[ 0 ] ) ;
/*set_log_file( _nstr( log_file ) );*/
char ver_str[ 128 ] = "" ;
while( ( getoptret = getopt( argc, argv, "hvV:L:" ) ) != EOF )
{
switch( getoptret )
{
case 'h':
n_log( LOG_NOTICE, "\n %s -h help -v version -V DEBUGLEVEL (NOLOG,VERBOSE,NOTICE,ERROR,DEBUG)\n", argv[ 0 ] );
exit( TRUE );
case 'v':
sprintf( ver_str, "%s %s", __DATE__, __TIME__ );
exit( TRUE );
break ;
case 'V':
if( !strncmp( "INFO", optarg, 6 ) )
{
log_level = LOG_INFO ;
}
else
{ if( !strncmp( "NOTICE", optarg, 6 ) )
{
log_level = LOG_NOTICE ; }
else
{
if( !strncmp( "VERBOSE", optarg, 7 ) )
{
log_level = LOG_NOTICE ;
}
else
{
if( !strncmp( "ERROR", optarg, 5 ) )
{
log_level = LOG_ERR ;
}
else
{
if( !strncmp( "DEBUG", optarg, 5 ) )
{
log_level = LOG_DEBUG ;
}
else
{
n_log( LOG_ERR, "%s is not a valid log level", optarg );
exit( FALSE );
}
}
}
}
}
n_log( LOG_NOTICE, "LOG LEVEL UP TO: %d", log_level );
set_log_level( log_level );
break;
case 'L' :
n_log( LOG_NOTICE, "LOG FILE: %s", optarg );
set_log_file( optarg );
break ;
case '?' :
{
switch( optopt )
{
case 'V' :
n_log( LOG_ERR, "\nPlease specify a log level after -V. \nAvailable values: NOLOG,VERBOSE,NOTICE,ERROR,DEBUG" );
break;
case 'L' :
n_log( LOG_ERR, "\nPlease specify a log file after -L" );
default:
break;
}
}
__attribute__ ((fallthrough));
default:
n_log( LOG_ERR, "\n %s -h help -v version -V DEBUGLEVEL (NOLOG,VERBOSE,NOTICE,ERROR,DEBUG) -L logfile", argv[ 0 ] );
exit( FALSE );
}
}
/*
* INITIALISATION
*/
int threadedProcessing = 0 ;
N_FLUID *fluid_data = NULL ;
Malloc( fluid_data , N_FLUID , 1 );
if( load_app_state( "CONFIGS/ex_fluid.cfg" , &WIDTH , &HEIGHT , &fullscreen , &bgmusic , &drawFPS , &logicFPS , fluid_data , &threadedProcessing ) != TRUE )
{
n_log( LOG_ERR , "couldn't load CONFIGS/ex_fluid.cfg !");
exit( 1 );
}
double fluid_factor = fluid_data -> cScale ;
n_log( LOG_DEBUG , "%s starting with params: %dx%d fullscreen(%d), music: %s" , argv[ 0 ] , WIDTH , HEIGHT , fullscreen , _str( bgmusic ) );
/* allegro 5 + addons loading */
if (!al_init())
{
n_abort("Could not init Allegro.\n");
}
if( !al_init_acodec_addon() )
{
n_abort("Could not register addons.\n");
}
if (!al_install_audio())
{
n_log( LOG_ERR , "Unable to initialize audio addon, disabling bgmusic\n");
Free( bgmusic );
}
if (!al_init_acodec_addon())
{
n_abort("Unable to initialize acoded addon\n");
}
if (!al_init_image_addon())
{
n_abort("Unable to initialize image addon\n");
}
if (!al_init_primitives_addon() )
{
n_abort("Unable to initialize primitives addon\n");
}
if( !al_init_font_addon() )
{
n_abort("Unable to initialize font addon\n");
}
if( !al_init_ttf_addon() )
{
n_abort("Unable to initialize ttf_font addon\n");
}
if( !al_install_keyboard() )
{
n_abort("Unable to initialize keyboard handler\n");
}
if( !al_install_mouse())
{
n_abort("Unable to initialize mouse handler\n");
}
if( bgmusic && !al_reserve_samples( RESERVED_SAMPLES ) )
{
n_abort("Could not set up voice and mixer.\n");
}
ALLEGRO_SAMPLE *sample_data[MAX_SAMPLE_DATA] = {NULL};
memset(sample_data, 0, sizeof(sample_data));
ALLEGRO_EVENT_QUEUE *event_queue = NULL;
event_queue = al_create_event_queue();
if(!event_queue)
{
fprintf(stderr, "failed to create event_queue!\n");
return -1;
}
if( fullscreen )
{
al_set_new_display_flags( ALLEGRO_OPENGL|ALLEGRO_FULLSCREEN_WINDOW );
}
else
{
al_set_new_display_flags( ALLEGRO_OPENGL|ALLEGRO_WINDOWED );
}
al_set_new_bitmap_flags( ALLEGRO_VIDEO_BITMAP|ALLEGRO_NO_PRESERVE_TEXTURE );
display = al_create_display( WIDTH, HEIGHT );
if( !display )
{
n_abort("Unable to create display\n");
}
al_set_window_title( display, argv[ 0 ] );
ALLEGRO_FONT *font = al_load_font( "DATAS/2Dumb.ttf", 18, 0 );
if( !font )
{
n_abort("Unable to load font DATAS/2Dumb.ttf\n");
}
DONE = 0 ;
fps_timer = al_create_timer( 1.0 / drawFPS );
logic_timer = al_create_timer( 1.0 / logicFPS );
al_register_event_source(event_queue, al_get_display_event_source(display));
al_start_timer( fps_timer );
al_start_timer( logic_timer );
al_register_event_source(event_queue, al_get_timer_event_source(fps_timer));
al_register_event_source(event_queue, al_get_timer_event_source(logic_timer));
al_register_event_source(event_queue, al_get_keyboard_event_source());
al_register_event_source(event_queue, al_get_mouse_event_source());
bool backbuffer = 1 ;
ALLEGRO_BITMAP *scrbuf = NULL ;
ALLEGRO_BITMAP *bitmap = al_create_bitmap( WIDTH , HEIGHT );
al_hide_mouse_cursor(display);
enum APP_KEYS
{
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
};
int key[ 19 ] = {false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false};
if( bgmusic )
{
if( !( sample_data[ 0 ] = al_load_sample( bgmusic ) ) )
{
n_log( LOG_ERR , "Could not load %s" , bgmusic );
exit( 1 );
}
al_play_sample(sample_data[ 0 ] , 1 , 0 , 1 , ALLEGRO_PLAYMODE_LOOP , NULL );
}
thread_pool = new_thread_pool( get_nb_cpu_cores() , 0 );
/* set fluid */
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 );
fluid_sim -> density = fluid_data -> density ;
fluid_sim -> gravity = fluid_data -> gravity ;
fluid_sim -> numIters = fluid_data -> numIters ;
fluid_sim -> fluid_production_percentage = fluid_data -> fluid_production_percentage ;
fluid_sim -> overRelaxation = fluid_data -> overRelaxation ;
fluid_sim -> cScale = fluid_data -> cScale ;
Free( fluid_data );
fluid_sim -> dt = 1.0 / logicFPS ;
size_t n = fluid_sim -> numY;
double inVel = 2.0;
for( size_t i = 0; i < fluid_sim -> numX; i++)
{
for (size_t j = 0; j < fluid_sim -> numY; j++)
{
double s = 1.0; // fluid
if (i == 0 || j == 0 || j == fluid_sim -> numY-1)
s = 0.0; // solid
//
fluid_sim -> s[i*n + j] = s ;
if (i == 1) {
fluid_sim -> u[i*n + j] = inVel;
}
}
}
double pipeH = fluid_sim -> fluid_production_percentage * fluid_sim -> numY;
size_t minJ = floor( 0.5 * fluid_sim -> numY - 0.5 * pipeH );
size_t maxJ = floor( 0.5 * fluid_sim -> numY + 0.5 * pipeH );
for( size_t j = 0 ; j < minJ ; j ++ )
fluid_sim -> m[j] = 1.0;
for (size_t j = minJ; j < maxJ; j++)
fluid_sim -> m[j] = 0.0;
for( size_t j = maxJ ; j < fluid_sim -> numY ; j ++ )
fluid_sim -> m[j] = 1.0;
bool do_draw = 1 , do_logic = 1 ;
int mx = WIDTH/3 , my = HEIGHT/2 , mouse_button = 0 , mouse_b1 = 0 , mouse_b2 = 0 ;
n_fluid_resetObstacles( fluid_sim );
al_flush_event_queue( event_queue );
al_set_mouse_xy( display , WIDTH/3 , HEIGHT/2 );
int w = al_get_display_width( display );
int h = al_get_display_height( display );
bitmap = al_create_bitmap( WIDTH, HEIGHT );
size_t logic_duration = 0 ;
size_t drawing_duration = 0 ;
do
{
do
{
ALLEGRO_EVENT ev ;
al_wait_for_event(event_queue, &ev);
if(ev.type == ALLEGRO_EVENT_KEY_DOWN)
{
switch(ev.keyboard.keycode)
{
case ALLEGRO_KEY_UP:
key[KEY_UP] = 1;
break;
case ALLEGRO_KEY_DOWN:
key[KEY_DOWN] = 1;
break;
case ALLEGRO_KEY_LEFT:
key[KEY_LEFT] = 1;
break;
case ALLEGRO_KEY_RIGHT:
key[KEY_RIGHT] = 1;
break;
case ALLEGRO_KEY_ESCAPE:
key[KEY_ESC] = 1 ;
break;
case ALLEGRO_KEY_SPACE:
key[KEY_SPACE] = 1 ;
break;
case ALLEGRO_KEY_LSHIFT:
case ALLEGRO_KEY_RSHIFT:
key[KEY_SHIFT] = 1 ;
break;
case ALLEGRO_KEY_PAD_MINUS:
key[KEY_PAD_MINUS] = 1 ;
break;
case ALLEGRO_KEY_PAD_PLUS:
key[KEY_PAD_PLUS] = 1 ;
break;
case ALLEGRO_KEY_PAD_ENTER:
key[KEY_PAD_ENTER] = 1 ;
break;
case ALLEGRO_KEY_M:
key[KEY_M] = 1 ;
break;
case ALLEGRO_KEY_W:
key[KEY_W] = 1 ;
break;
case ALLEGRO_KEY_LCTRL:
case ALLEGRO_KEY_RCTRL:
key[KEY_CTRL] = 1 ;
break;
case ALLEGRO_KEY_F1:
key[ KEY_F1 ] = 1 ;
break;
case ALLEGRO_KEY_F2:
key[ KEY_F2 ] = 1 ;
break;
case ALLEGRO_KEY_F3:
key[ KEY_F3 ] = 1 ;
break;
case ALLEGRO_KEY_F4:
key[ KEY_F4 ] = 1 ;
break;
case ALLEGRO_KEY_F5:
key[ KEY_F5 ] = 1 ;
break;
case ALLEGRO_KEY_F6:
key[ KEY_F6 ] = 1 ;
break;
default:
break;
}
}
else if(ev.type == ALLEGRO_EVENT_KEY_UP)
{
switch(ev.keyboard.keycode)
{
case ALLEGRO_KEY_UP:
key[KEY_UP] = 0;
break;
case ALLEGRO_KEY_DOWN:
key[KEY_DOWN] = 0;
break;
case ALLEGRO_KEY_LEFT:
key[KEY_LEFT] = 0;
break;
case ALLEGRO_KEY_RIGHT:
key[KEY_RIGHT] =0;
break;
case ALLEGRO_KEY_ESCAPE:
key[KEY_ESC] = 0 ;
break;
case ALLEGRO_KEY_SPACE:
key[KEY_SPACE] = 0 ;
break;
case ALLEGRO_KEY_LSHIFT:
case ALLEGRO_KEY_RSHIFT:
key[KEY_SHIFT] = 0 ;
break;
case ALLEGRO_KEY_PAD_MINUS:
key[KEY_PAD_MINUS] = 0 ;
break;
case ALLEGRO_KEY_PAD_PLUS:
key[KEY_PAD_PLUS] = 0 ;
break;
case ALLEGRO_KEY_PAD_ENTER:
key[KEY_PAD_ENTER] = 0 ;
break;
case ALLEGRO_KEY_M:
key[KEY_M] = 0 ;
break;
case ALLEGRO_KEY_W:
key[KEY_W] = 0 ;
break;
case ALLEGRO_KEY_LCTRL:
case ALLEGRO_KEY_RCTRL:
key[KEY_CTRL] = 0 ;
break;
case ALLEGRO_KEY_F1:
key[ KEY_F1 ] = 0 ;
break;
case ALLEGRO_KEY_F2:
key[ KEY_F2 ] = 0 ;
break;
case ALLEGRO_KEY_F3:
key[ KEY_F3 ] = 0 ;
break;
case ALLEGRO_KEY_F4:
key[ KEY_F4 ] = 0 ;
break;
case ALLEGRO_KEY_F5:
key[ KEY_F5 ] = 0 ;
break;
case ALLEGRO_KEY_F6:
key[ KEY_F6 ] = 0 ;
break;
default:
break;
}
}
else if( ev.type == ALLEGRO_EVENT_TIMER )
{
if( al_get_timer_event_source( fps_timer ) == ev.any.source )
{
do_draw = 1 ;
}
else if( al_get_timer_event_source( logic_timer ) == ev.any.source )
{
do_logic = 1;
}
}
else if( ev.type == ALLEGRO_EVENT_MOUSE_AXES )
{
mx = ev.mouse.x;
my = ev.mouse.y;
}
else if( ev.type == ALLEGRO_EVENT_MOUSE_BUTTON_DOWN )
{
if( ev.mouse.button == 1 )
mouse_b1 = 1 ;
if( ev.mouse.button == 2 )
mouse_b2 = 1 ;
}
else if( ev.type == ALLEGRO_EVENT_MOUSE_BUTTON_UP )
{
if( ev.mouse.button == 1 )
mouse_b1 = 0 ;
if( ev.mouse.button == 2 )
mouse_b2 = 0 ;
}
/* Processing inputs */
mouse_button = -1 ;
if( mouse_b1==1 )
mouse_button = 1 ;
if( mouse_b2==1 )
mouse_button = 2 ;
else if( ev.type == ALLEGRO_EVENT_DISPLAY_SWITCH_IN || ev.type == ALLEGRO_EVENT_DISPLAY_SWITCH_OUT )
{
al_clear_keyboard_state( display );
al_flush_event_queue( event_queue );
}
else
{
// Processing inputs
// get_keyboard( chat_line , ev );
if( key[KEY_F1 ] )
{
fluid_sim -> showSmoke = 1 ;
}
if( key[KEY_F2 ] )
{
fluid_sim -> showSmoke = 0 ;
}
if( key[KEY_F3 ] )
{
fluid_sim -> showPressure = 1 ;
}
if( key[KEY_F4 ] )
{
fluid_sim -> showPressure = 0 ;
}
if( key[KEY_F5 ] )
{
fluid_sim -> showPaint = 1 ;
}
if( key[KEY_F6 ] )
{
fluid_sim -> showPaint = 0 ;
}
if( key[KEY_UP] )
{
fluid_sim -> density += 100.0 ;
}
if( key[KEY_DOWN] )
{
fluid_sim -> density -= 100.0 ;
if( fluid_sim -> density < 1.0 ) fluid_sim -> density = 1.0 ;
}
if( key[KEY_LEFT] )
{
fluid_sim -> numIters ++ ;
}
if( key[KEY_RIGHT] )
{
fluid_sim -> numIters -- ;
if( fluid_sim -> numIters < 1.0 ) fluid_sim -> numIters = 1.0 ;
}
if( key[KEY_PAD_PLUS] )
{
fluid_sim -> fluid_production_percentage += 0.01 ;
if( fluid_sim -> fluid_production_percentage > 1.0 ) fluid_sim -> fluid_production_percentage = 1.0 ;
}
if( key[KEY_PAD_MINUS] )
{
fluid_sim -> fluid_production_percentage -= 0.01 ;
if( fluid_sim -> fluid_production_percentage < 0.1 ) fluid_sim -> fluid_production_percentage = 0.1 ;
}
if( mouse_button != -1 )
{
n_log( LOG_DEBUG , "mouse button: %d" , mouse_button );
}
}
}while( !al_is_event_queue_empty( event_queue) );
if( do_logic == 1 )
{
start_HiTimer( &logic_chrono );
static int old_mx = -1 , old_my = -1 ;
double vx = 0.0 , vy = 0.0 ;
if( old_mx != mx || old_my != my )
{
if( old_mx != -1 && old_my != -1 )
{
vx = (old_mx - mx ) / logicFPS ;
vy = (old_my - my ) / logicFPS ;
}
old_mx = mx ;
old_my = my ;
n_fluid_resetObstacles( fluid_sim );
n_fluid_setObstacle( fluid_sim , mx / fluid_factor , ( my / fluid_factor ) - 20.0 , vx , vy , fluid_factor/2 );
n_fluid_setObstacle( fluid_sim , (mx / fluid_factor ) - 15 , my / fluid_factor , vx , vy , fluid_factor/2 + fluid_factor/3 );
n_fluid_setObstacle( fluid_sim , (mx / fluid_factor ) + 15 , my / fluid_factor - 10.0 , vx , vy , fluid_factor/2 + fluid_factor/2 );
n_fluid_setObstacle( fluid_sim , (mx / fluid_factor ) + 15 , my / fluid_factor + 10.0 , vx , vy , fluid_factor/2 + fluid_factor/2 );
n_fluid_setObstacle( fluid_sim , mx / fluid_factor , ( my / fluid_factor ) + 20.0 , vx , vy , fluid_factor/2 );
}
double pipeH = fluid_sim -> fluid_production_percentage * fluid_sim -> numY;
size_t minJ = floor( 0.5 * fluid_sim -> numY - 0.5 * pipeH );
size_t maxJ = floor( 0.5 * fluid_sim -> numY + 0.5 * pipeH );
for( size_t j = 0 ; j < minJ ; j ++ )
fluid_sim -> m[j] = 1.0;
for (size_t j = minJ; j < maxJ; j++)
fluid_sim -> m[j] = 0.0;
for( size_t j = maxJ ; j < fluid_sim -> numY ; j ++ )
fluid_sim -> m[j] = 1.0;
for (size_t j = minJ; j < maxJ; j++)
fluid_sim -> m[j] = 0.0;
if( threadedProcessing == 1 )
n_fluid_simulate_threaded( fluid_sim , thread_pool );
else
n_fluid_simulate( fluid_sim );
logic_duration = ( logic_duration + get_usec( &logic_chrono ) ) / 2;
do_logic = 0 ;
}
if( do_draw == 1 )
{
start_HiTimer( &drawing_chrono );
if( backbuffer )
scrbuf = al_get_backbuffer(display);
else
scrbuf = bitmap ;
al_set_target_bitmap( scrbuf );
if( !backbuffer )
al_lock_bitmap( scrbuf , al_get_bitmap_format( scrbuf ) , ALLEGRO_LOCK_READWRITE );
n_fluid_draw( fluid_sim );
al_draw_circle( mx , my - 20 * fluid_factor , fluid_factor * fluid_factor / 2 , al_map_rgb( 255 , 0 , 0 ) , 2.0 );
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 );
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 );
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 );
al_draw_circle( mx , my + 20 * fluid_factor , fluid_factor *fluid_factor / 2 , al_map_rgb( 255 , 0 , 0 ) , 2.0 );
static N_STR *textout = NULL ;
nstrprintf( textout , "[F1/F2]:showSmoke:%d [F3/F4]:showPressure:%d [F5/F6]:showPaint:%d" , fluid_sim -> showSmoke , fluid_sim -> showPressure , fluid_sim -> showPaint );
al_draw_text( font, al_map_rgb( 0 , 0 , 255 ), WIDTH , 10 , ALLEGRO_ALIGN_RIGHT , _nstr( textout ) );
nstrprintf( textout , "numIters: %zd production: %3.3g density: %3.3g" , fluid_sim -> numIters , fluid_sim -> fluid_production_percentage , fluid_sim -> density );
al_draw_text( font, al_map_rgb( 0 , 0 , 255 ), WIDTH , 25 , ALLEGRO_ALIGN_RIGHT , _nstr( textout ) );
nstrprintf( textout , "logic(max %zd): %zd usecs" , (size_t)(1000000.0/logicFPS) , logic_duration );
al_draw_text( font, al_map_rgb( 0 , 0 , 255 ), 5 , 10 , ALLEGRO_ALIGN_LEFT , _nstr( textout ) );
nstrprintf( textout , "drawing(max %zd): %zd usecs" , (size_t)(1000000.0/drawFPS) , drawing_duration );
al_draw_text( font, al_map_rgb( 0 , 0 , 255 ), 5 , 30 , ALLEGRO_ALIGN_LEFT , _nstr( textout ) );
if( !backbuffer )
{
al_unlock_bitmap( scrbuf );
al_set_target_bitmap(al_get_backbuffer(display));
al_draw_bitmap( scrbuf, w/2 - al_get_bitmap_width( scrbuf ) /2, h/2 - al_get_bitmap_height( scrbuf ) / 2, 0 );
}
drawing_duration = ( drawing_duration + get_usec( &drawing_chrono ) ) / 2;
al_flip_display();
do_draw = 0 ;
}
}
while( !key[KEY_ESC] && !DONE );
al_uninstall_system();
return 0;
}
#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.