Nilorea Library
C utilities for networking, threading, graphics
Loading...
Searching...
No Matches
n_fluids.c
Go to the documentation of this file.
1
7#include <math.h>
8#include <stdio.h>
9#include <stdlib.h>
10#include <stdint.h>
11#include <stdbool.h>
12#include <strings.h>
13#include "nilorea/n_fluids.h"
14#include "nilorea/n_common.h"
16
18#define N_FLUID_U_FIELD 0
20#define N_FLUID_V_FIELD 1
22#define N_FLUID_S_FIELD 2
23
31void n_memset(void* dst, void* val, size_t size, size_t count) {
32 void* ptr = dst;
33 while (count-- > 0) {
34 memcpy(ptr, val, size);
35 ptr += size;
36 }
37}
38
45 __n_assert((*fluid), return FALSE);
46
47 FreeNoLog((*fluid)->u);
48 FreeNoLog((*fluid)->newU);
49 FreeNoLog((*fluid)->v);
50 FreeNoLog((*fluid)->newV);
51 FreeNoLog((*fluid)->p);
52 FreeNoLog((*fluid)->s);
53 FreeNoLog((*fluid)->m);
54 FreeNoLog((*fluid)->newM);
55 FreeNoLog((*fluid));
56
57 return TRUE;
58}
59
71N_FLUID* new_n_fluid(double density, double gravity, size_t numIters, double dt, double overRelaxation, size_t sx, size_t sy) {
72 N_FLUID* fluid = NULL;
73
74 Malloc(fluid, N_FLUID, 1);
75 __n_assert(fluid, return NULL);
76
77 fluid->density = density;
78 fluid->gravity = gravity;
79 fluid->numIters = numIters;
80 fluid->dt = dt;
81 fluid->h = 1.0 / 100.0;
82 fluid->overRelaxation = overRelaxation;
83 fluid->numX = sx + 2;
84 fluid->numY = sy + 2;
85 fluid->numZ = 1; // TODO: expand Z
86 fluid->numCells = fluid->numX * fluid->numY * fluid->numZ;
87
88 Malloc(fluid->u, double, fluid->numCells);
89 Malloc(fluid->newU, double, fluid->numCells);
90 Malloc(fluid->v, double, fluid->numCells);
91 Malloc(fluid->newV, double, fluid->numCells);
92 Malloc(fluid->p, double, fluid->numCells);
93 Malloc(fluid->s, double, fluid->numCells);
94 Malloc(fluid->m, double, fluid->numCells);
95 Malloc(fluid->newM, double, fluid->numCells);
96
97 fluid->showSmoke = 1;
98 fluid->showPressure = 0;
99 fluid->showPaint = 0;
100 fluid->fluid_production_percentage = 0.1;
101 fluid->cScale = 16.0;
102 // double precision. Taking 'value', if( fabs( value ) < float_tolerance ) value is considered as zero
103 fluid->negative_float_tolerance = -0.00001;
104 fluid->positive_float_tolerance = 0.00001;
105
106 double d_val = 1.0;
107 n_memset(fluid->m, &d_val, sizeof(d_val), fluid->numCells);
108
109 // precalculate and allocated N_PROC_PARAMS lists for threaded computing
110 fluid->integrate_chunk_list = new_generic_list(MAX_LIST_ITEMS);
111 fluid->solveIncompressibility_chunk_list = new_generic_list(MAX_LIST_ITEMS);
112 fluid->advectVel_chunk_list = new_generic_list(MAX_LIST_ITEMS);
113 fluid->advectSmoke_chunk_list = new_generic_list(MAX_LIST_ITEMS);
114
115 int nb_cores = get_nb_cpu_cores();
116 if (nb_cores == -1) {
117 nb_cores = 1;
118 }
119 size_t steps = fluid->numX / nb_cores;
120
121 N_FLUID_THREAD_PARAMS* params = NULL;
122 // integrate
123 for (size_t i = 1; i < fluid->numX; i += steps) {
124 Malloc(params, N_FLUID_THREAD_PARAMS, 1);
125 params->ptr = fluid;
126 params->x_start = i;
127 params->x_end = i + steps;
128 params->y_start = 1;
129 params->y_end = fluid->numY - 1;
130 list_push(fluid->integrate_chunk_list, params, &free);
131 }
132 // set the last batch at the end of the range
134 params->x_end = fluid->numX;
135
136 // solveIncompressibility
137 for (size_t i = 1; i < fluid->numX - 1; i += steps) {
138 Malloc(params, N_FLUID_THREAD_PARAMS, 1);
139 params->ptr = fluid;
140 params->x_start = i;
141 params->x_end = i + steps;
142 params->y_start = 1;
143 params->y_end = fluid->numY - 1;
144 list_push(fluid->solveIncompressibility_chunk_list, params, &free);
145 }
146 // set the last batch at the end of the range
148 params->x_end = fluid->numX - 1;
149
150 // advectVel
151 for (size_t i = 1; i < fluid->numX; i += steps) {
152 Malloc(params, N_FLUID_THREAD_PARAMS, 1);
153 params->ptr = fluid;
154 params->x_start = i;
155 params->x_end = i + steps;
156 params->y_start = 1;
157 params->y_end = fluid->numY;
158 list_push(fluid->advectVel_chunk_list, params, &free);
159 }
160 // set the last batch at the end of the range
162 params->x_end = fluid->numX;
163
164 // adVectSmoke
165 for (size_t i = 1; i < fluid->numX - 1; i += steps) {
166 Malloc(params, N_FLUID_THREAD_PARAMS, 1);
167 params->ptr = fluid;
168 params->x_start = i;
169 params->x_end = i + steps;
170 params->y_start = 1;
171 params->y_end = fluid->numY - 1;
172 list_push(fluid->advectSmoke_chunk_list, params, &free);
173 }
174 // set the last batch at the end of the range
176 params->x_end = fluid->numX - 1;
177
178 return fluid;
179} /* new_n_fluid */
180
186void* n_fluid_integrate_proc(void* ptr) {
188 N_FLUID* fluid = (N_FLUID*)params->ptr;
189
190 size_t n = fluid->numY;
191 for (size_t i = params->x_start; i < params->x_end; i++) {
192 for (size_t j = params->y_start; j < params->y_end; j++) {
193 if (!_z(fluid, s[i * n + j]) && !_z(fluid, s[i * n + j - 1]))
194 fluid->v[i * n + j] += fluid->gravity * fluid->dt;
195 }
196 }
197 return NULL;
198}
199
206 __n_assert(fluid, return FALSE);
207
208 size_t n = fluid->numY;
209 for (size_t i = 1; i < fluid->numX; i++) {
210 for (size_t j = 1; j < fluid->numY - 1; j++) {
211 if (!_z(fluid, s[i * n + j]) && !_z(fluid, s[i * n + j - 1]))
212 fluid->v[i * n + j] += fluid->gravity * fluid->dt;
213 }
214 }
215 return TRUE;
216}
217
225 N_FLUID* fluid = (N_FLUID*)params->ptr;
226
227 double cp = (fluid->density * fluid->h) / fluid->dt;
228
229 size_t n = fluid->numY;
230 for (size_t i = params->x_start; i < params->x_end; i++) {
231 for (size_t j = params->y_start; j < params->y_end; j++) {
232 if (_z(fluid, s[i * n + j]))
233 continue;
234
235 double sx0 = fluid->s[(i - 1) * n + j];
236 double sx1 = fluid->s[(i + 1) * n + j];
237 double sy0 = fluid->s[i * n + j - 1];
238 double sy1 = fluid->s[i * n + j + 1];
239 double s = sx0 + sx1 + sy0 + sy1;
240 if (_zd(fluid, s))
241 continue;
242
243 double div = fluid->u[(i + 1) * n + j] - fluid->u[i * n + j] + fluid->v[i * n + j + 1] - fluid->v[i * n + j];
244 double p = (-div * fluid->overRelaxation) / s;
245 fluid->p[i * n + j] += cp * p;
246 fluid->u[i * n + j] -= sx0 * p;
247 fluid->u[(i + 1) * n + j] += sx1 * p;
248 fluid->v[i * n + j] -= sy0 * p;
249 fluid->v[i * n + j + 1] += sy1 * p;
250 }
251 }
252 return NULL;
253}
254
261 __n_assert(fluid, return FALSE);
262 size_t n = fluid->numY;
263
264 double cp = (fluid->density * fluid->h) / fluid->dt;
265
266 for (size_t iter = 0; iter < fluid->numIters; iter++) {
267 for (size_t i = 1; i < fluid->numX - 1; i++) {
268 for (size_t j = 1; j < fluid->numY - 1; j++) {
269 if (_z(fluid, s[i * n + j]))
270 continue;
271
272 double sx0 = fluid->s[(i - 1) * n + j];
273 double sx1 = fluid->s[(i + 1) * n + j];
274 double sy0 = fluid->s[i * n + j - 1];
275 double sy1 = fluid->s[i * n + j + 1];
276 double s = sx0 + sx1 + sy0 + sy1;
277 if (_zd(fluid, s))
278 continue;
279
280 double div = fluid->u[(i + 1) * n + j] - fluid->u[i * n + j] + fluid->v[i * n + j + 1] - fluid->v[i * n + j];
281 double p = (-div * fluid->overRelaxation) / s;
282 fluid->p[i * n + j] += cp * p;
283 fluid->u[i * n + j] -= sx0 * p;
284 fluid->u[(i + 1) * n + j] += sx1 * p;
285 fluid->v[i * n + j] -= sy0 * p;
286 fluid->v[i * n + j + 1] += sy1 * p;
287 }
288 }
289 }
290 return TRUE;
291}
292
299 __n_assert(fluid, return FALSE);
300 size_t n = fluid->numY;
301 for (size_t i = 0; i < fluid->numX; i++) {
302 fluid->u[i * n + 0] = fluid->u[i * n + 1];
303 fluid->u[i * n + fluid->numY - 1] = fluid->u[i * n + fluid->numY - 2];
304 }
305 for (size_t j = 0; j < fluid->numY; j++) {
306 fluid->v[0 * n + j] = fluid->v[1 * n + j];
307 fluid->v[(fluid->numX - 1) * n + j] = fluid->v[(fluid->numX - 2) * n + j];
308 }
309 return TRUE;
310}
311
320double n_fluid_sampleField(N_FLUID* fluid, double x, double y, uint32_t field) {
321 __n_assert(fluid, return FALSE);
322 size_t n = fluid->numY;
323 double h1 = 1.0 / fluid->h;
324 double h2 = 0.5 * fluid->h;
325
326 x = MAX(MIN(x, fluid->numX * fluid->h), fluid->h);
327 y = MAX(MIN(y, fluid->numY * fluid->h), fluid->h);
328
329 double dx = 0.0;
330 double dy = 0.0;
331
332 double* f = NULL;
333 switch (field) {
334 case N_FLUID_U_FIELD:
335 f = fluid->u;
336 dy = h2;
337 break;
338 case N_FLUID_V_FIELD:
339 f = fluid->v;
340 dx = h2;
341 break;
342 case N_FLUID_S_FIELD:
343 f = fluid->m;
344 dx = h2;
345 dy = h2;
346 break;
347 }
348
349 double x0 = MIN(floor((x - dx) * h1), fluid->numX - 1);
350 double tx = ((x - dx) - x0 * fluid->h) * h1;
351 double x1 = MIN(x0 + 1, fluid->numX - 1);
352
353 double y0 = MIN(floor((y - dy) * h1), fluid->numY - 1);
354 double ty = ((y - dy) - y0 * fluid->h) * h1;
355 double y1 = MIN(y0 + 1, fluid->numY - 1);
356
357 double sx = 1.0 - tx;
358 double sy = 1.0 - ty;
359
360 double val = sx * sy * f[(size_t)(x0 * n + y0)] +
361 tx * sy * f[(size_t)(x1 * n + y0)] +
362 tx * ty * f[(size_t)(x1 * n + y1)] +
363 sx * ty * f[(size_t)(x0 * n + y1)];
364
365 return val;
366}
367
375double n_fluid_avgU(N_FLUID* fluid, size_t i, size_t j) {
376 __n_assert(fluid, return FALSE);
377 size_t n = fluid->numY;
378 double u = (fluid->u[i * n + j - 1] + fluid->u[i * n + j] +
379 fluid->u[(i + 1) * n + j - 1] + fluid->u[(i + 1) * n + j]) *
380 0.25;
381
382 return u;
383}
384
392double n_fluid_avgV(N_FLUID* fluid, size_t i, size_t j) {
393 __n_assert(fluid, return FALSE);
394 size_t n = fluid->numY;
395 double v = (fluid->v[(i - 1) * n + j] + fluid->v[i * n + j] +
396 fluid->v[(i - 1) * n + j + 1] + fluid->v[i * n + j + 1]) *
397 0.25;
398 return v;
399}
400
406void* n_fluid_advectVel_proc(void* ptr) {
408 N_FLUID* fluid = (N_FLUID*)params->ptr;
409
410 size_t n = fluid->numY;
411 double h2 = 0.5 * fluid->h;
412 for (size_t i = params->x_start; i < params->x_end; i++) {
413 for (size_t j = params->y_start; j < params->y_end; j++) {
414 size_t index = i * n + j;
415 // u component
416 if (!_z(fluid, s[index]) && !_z(fluid, s[(i - 1) * n + j]) && j < fluid->numY - 1) {
417 double x = i * fluid->h;
418 double y = j * fluid->h + h2;
419 double u = fluid->u[index];
420 double v = n_fluid_avgV(fluid, i, j);
421 // double v = n_fluid_sampleField( fluid , x , y , N_FLUID_V_FIELD );
422 x = x - fluid->dt * u;
423 y = y - fluid->dt * v;
424 u = n_fluid_sampleField(fluid, x, y, N_FLUID_U_FIELD);
425 fluid->newU[index] = u;
426 }
427 // v component
428 if (!_z(fluid, s[index]) && !_z(fluid, s[index - 1]) && i < fluid->numX - 1) {
429 double x = i * fluid->h + h2;
430 double y = j * fluid->h;
431 double u = n_fluid_avgU(fluid, i, j);
432 // double u = n_fluid_sampleField( fluid , x , y , N_FLUID_U_FIELD );
433 double v = fluid->v[index];
434 x = x - fluid->dt * u;
435 y = y - fluid->dt * v;
436 v = n_fluid_sampleField(fluid, x, y, N_FLUID_V_FIELD);
437 fluid->newV[index] = v;
438 }
439 }
440 }
441 return NULL;
442}
443
450 __n_assert(fluid, return FALSE);
451
452 memcpy(fluid->newU, fluid->u, fluid->numCells * sizeof(double));
453 memcpy(fluid->newV, fluid->v, fluid->numCells * sizeof(double));
454
455 size_t n = fluid->numY;
456 double h2 = 0.5 * fluid->h;
457 for (size_t i = 1; i < fluid->numX; i++) {
458 for (size_t j = 1; j < fluid->numY; j++) {
459 size_t index = i * n + j;
460 // u component
461 if (!_z(fluid, s[index]) && !_z(fluid, s[(i - 1) * n + j]) && j < fluid->numY - 1) {
462 double x = i * fluid->h;
463 double y = j * fluid->h + h2;
464 double u = fluid->u[index];
465 double v = n_fluid_avgV(fluid, i, j);
466 // double v = n_fluid_sampleField( fluid , x , y , N_FLUID_V_FIELD );
467 x = x - fluid->dt * u;
468 y = y - fluid->dt * v;
469 u = n_fluid_sampleField(fluid, x, y, N_FLUID_U_FIELD);
470 fluid->newU[index] = u;
471 }
472 // v component
473 if (!_z(fluid, s[index]) && !_z(fluid, s[index - 1]) && i < fluid->numX - 1) {
474 double x = i * fluid->h + h2;
475 double y = j * fluid->h;
476 double u = n_fluid_avgU(fluid, i, j);
477 // double u = n_fluid_sampleField( fluid , x , y , N_FLUID_U_FIELD );
478 double v = fluid->v[index];
479 x = x - fluid->dt * u;
480 y = y - fluid->dt * v;
481 v = n_fluid_sampleField(fluid, x, y, N_FLUID_V_FIELD);
482 fluid->newV[index] = v;
483 }
484 }
485 }
486 double* ptr = fluid->u;
487 fluid->u = fluid->newU;
488 fluid->newU = ptr;
489
490 ptr = fluid->v;
491 fluid->v = fluid->newV;
492 fluid->newV = ptr;
493
494 return TRUE;
495}
496
502void* n_fluid_advectSmoke_proc(void* ptr) {
504 N_FLUID* fluid = (N_FLUID*)params->ptr;
505
506 size_t n = fluid->numY;
507 double h2 = 0.5 * fluid->h;
508 for (size_t i = params->x_start; i < params->x_end; i++) {
509 for (size_t j = params->y_start; j < params->y_end; j++) {
510 size_t index = i * n + j;
511 if (!_z(fluid, s[index])) {
512 double u = (fluid->u[index] + fluid->u[(i + 1) * n + j]) * 0.5;
513 double v = (fluid->v[index] + fluid->v[index + 1]) * 0.5;
514 double x = i * fluid->h + h2 - fluid->dt * u;
515 double y = j * fluid->h + h2 - fluid->dt * v;
516
517 fluid->newM[index] = n_fluid_sampleField(fluid, x, y, N_FLUID_S_FIELD);
518 }
519 }
520 }
521 return NULL;
522}
523
530 __n_assert(fluid, return FALSE);
531
532 size_t n = fluid->numY;
533 double h2 = 0.5 * fluid->h;
534
535 memcpy(fluid->newM, fluid->m, fluid->numCells * sizeof(double));
536
537 for (size_t i = 1; i < fluid->numX - 1; i++) {
538 for (size_t j = 1; j < fluid->numY - 1; j++) {
539 size_t index = i * n + j;
540 if (!_z(fluid, s[index])) {
541 double u = (fluid->u[index] + fluid->u[(i + 1) * n + j]) * 0.5;
542 double v = (fluid->v[index] + fluid->v[index + 1]) * 0.5;
543 double x = i * fluid->h + h2 - fluid->dt * u;
544 double y = j * fluid->h + h2 - fluid->dt * v;
545
546 fluid->newM[index] = n_fluid_sampleField(fluid, x, y, N_FLUID_S_FIELD);
547 }
548 }
549 }
550 double* ptr = fluid->m;
551 fluid->m = fluid->newM;
552 fluid->newM = ptr;
553
554 return TRUE;
555}
556
563 __n_assert(fluid, return FALSE);
564 n_fluid_integrate(fluid);
565 memset(fluid->p, 0, fluid->numCells * sizeof(double));
567 n_fluid_extrapolate(fluid);
568 n_fluid_advectVel(fluid);
569 n_fluid_advectSmoke(fluid);
570 return TRUE;
571}
572
580 __n_assert(fluid, return FALSE);
581
582 // n_fluid_integrate( fluid );
583 list_foreach(node, fluid->integrate_chunk_list) {
584 add_threaded_process(thread_pool, &n_fluid_integrate_proc, (void*)node->ptr, SYNCED_PROC);
585 }
586 start_threaded_pool(thread_pool);
588 refresh_thread_pool(thread_pool);
589
590 // set pressure to 0
591 memset(fluid->p, 0, fluid->numCells * sizeof(double));
592
593 // n_fluid_solveIncompressibility( fluid );
594 for (size_t iter = 0; iter < fluid->numIters; iter++) {
597 }
598 start_threaded_pool(thread_pool);
600 refresh_thread_pool(thread_pool);
601 }
602
603 // extrapolate
604 n_fluid_extrapolate(fluid);
605
606 // n_fluid_advectVel( fluid );
607 memcpy(fluid->newU, fluid->u, fluid->numCells * sizeof(double));
608 memcpy(fluid->newV, fluid->v, fluid->numCells * sizeof(double));
609
610 list_foreach(node, fluid->advectVel_chunk_list) {
611 add_threaded_process(thread_pool, &n_fluid_advectVel_proc, (void*)node->ptr, SYNCED_PROC);
612 }
613 start_threaded_pool(thread_pool);
615 refresh_thread_pool(thread_pool);
616
617 double* ptr = fluid->u;
618 fluid->u = fluid->newU;
619 fluid->newU = ptr;
620
621 ptr = fluid->v;
622 fluid->v = fluid->newV;
623 fluid->newV = ptr;
624
625 // n_fluid_advectSmoke( fluid );
626 memcpy(fluid->newM, fluid->m, fluid->numCells * sizeof(double));
628 add_threaded_process(thread_pool, &n_fluid_advectSmoke_proc, (void*)node->ptr, SYNCED_PROC);
629 }
630 start_threaded_pool(thread_pool);
632 refresh_thread_pool(thread_pool);
633
634 ptr = fluid->m;
635 fluid->m = fluid->newM;
636 fluid->newM = ptr;
637
638 return TRUE;
639}
640
651int n_fluid_setObstacle(N_FLUID* fluid, double x, double y, double vx, double vy, double r) {
652 __n_assert(fluid, return FALSE);
653
654 size_t n = fluid->numY;
655 for (size_t i = 1; i < fluid->numX - 2; i++) {
656 for (size_t j = 1; j < fluid->numY - 2; j++) {
657 double dx = (i + 0.5) - x;
658 double dy = (j + 0.5) - y;
659
660 if (i > 7 && (dx * dx + dy * dy < r * r)) {
661 fluid->s[i * n + j] = 0.0;
662 fluid->m[i * n + j] = 1.0;
663 fluid->u[i * n + j] = vx;
664 fluid->u[(i + 1) * n + j] = vx;
665 fluid->v[i * n + j] = vy;
666 fluid->v[i * n + j + 1] = vy;
667 }
668 }
669 }
670 return TRUE;
671}
672
679 __n_assert(fluid, return FALSE);
680
681 size_t n = fluid->numY;
682 for (size_t i = 1; i < fluid->numX - 2; i++) {
683 for (size_t j = 1; j < fluid->numY - 2; j++) {
684 fluid->s[i * n + j] = 1.0;
685 }
686 }
687
688 return TRUE;
689}
690
702int n_fluid_setObstacleFromBitmap(N_FLUID* fluid, ALLEGRO_BITMAP* bitmap, double x, double y, double vx, double vy, double r) {
703 __n_assert(fluid, return FALSE);
704
705 al_lock_bitmap(bitmap, al_get_bitmap_format(bitmap), ALLEGRO_LOCK_READONLY);
706
707 size_t n = fluid->numY;
708 for (size_t i = 1; i < fluid->numX - 2; i++) {
709 for (size_t j = 1; j < fluid->numY - 2; j++) {
710 double dx = (i + 0.5) - x;
711 double dy = (j + 0.5) - y;
712
713 if (i > 7 && (dx * dx + dy * dy < r * r)) {
714 fluid->s[i * n + j] = 0.0;
715 fluid->m[i * n + j] = 1.0;
716 fluid->u[i * n + j] = vx;
717 fluid->v[i * n + j] = vy;
718
719 fluid->u[(i + 1) * n + j] = vx;
720 fluid->v[i * n + j + 1] = vy;
721 }
722 }
723 }
724
725 al_unlock_bitmap(bitmap);
726
727 return TRUE;
728}
729
738ALLEGRO_COLOR n_fluid_getSciColor(N_FLUID* fluid, double val, double minVal, double maxVal) {
739 val = MIN(MAX(val, minVal), maxVal - 0.0001);
740 double d = maxVal - minVal;
741 if (_zd(fluid, d)) {
742 val = 0.5;
743 } else {
744 val = (val - minVal) / d;
745 }
746 double m = 0.25;
747 size_t num = floor(val / m);
748 double s = (val - num * m) / m;
749 double r = 0.0, g = 0.0, b = 0.0;
750 switch (num) {
751 case 0:
752 r = 0.0;
753 g = s;
754 b = 1.0;
755 break;
756 case 1:
757 r = 0.0;
758 g = 1.0;
759 b = 1.0 - s;
760 break;
761 case 2:
762 r = s;
763 g = 1.0;
764 b = 0.0;
765 break;
766 case 3:
767 r = 1.0;
768 g = 1.0 - s;
769 b = 0.0;
770 break;
771 }
772 // return[255*r,255*g,255*b, 255]
773 return al_map_rgb_f(r, g, b);
774}
775
782 __n_assert(fluid, return FALSE);
783
784 size_t n = fluid->numY;
785
786 double minP = fluid->p[0];
787 double maxP = fluid->p[0];
788
789 if (fluid->showPressure) {
790 for (size_t i = 0; i < fluid->numCells; i++) {
791 minP = MIN(minP, fluid->p[i]);
792 maxP = MAX(maxP, fluid->p[i]);
793 }
794 }
795
796 ALLEGRO_COLOR color;
797 double cScale = fluid->cScale;
798
799 for (size_t i = 0; i < fluid->numX; i++) {
800 for (size_t j = 0; j < fluid->numY; j++) {
801 int64_t x = i * cScale;
802 int64_t y = j * cScale;
803 int64_t cx = x + cScale;
804 int64_t cy = y + cScale;
805
806 double s = fluid->m[i * n + j];
807
808 if (fluid->showPaint) {
809 color = n_fluid_getSciColor(fluid, s, 0.0, 1.0);
810 } else if (fluid->showPressure) {
811 float color_vec_f[3] = {0.0, 0.0, 0.0};
812 double p = fluid->p[i * n + j];
813 color = n_fluid_getSciColor(fluid, p, minP, maxP);
814 if (fluid->showSmoke) {
815 al_unmap_rgb_f(color, color_vec_f, color_vec_f + 1, color_vec_f + 2);
816 color = al_map_rgb_f(MAX(0.0, color_vec_f[0] - s), MAX(0.0, color_vec_f[1] - s), MAX(0.0, color_vec_f[2] - s));
817 }
818 } else if (fluid->showSmoke) {
819 color = al_map_rgb_f(1.0 - s, 0.0, 0.0);
820 } else {
821 color = al_map_rgb_f(s, s, s);
822 }
823 al_draw_filled_rectangle(x, y, cx, cy, color);
824 }
825 }
826 return TRUE;
827}
#define FreeNoLog(__ptr)
Free Handler without log.
Definition n_common.h:251
#define Malloc(__ptr, __struct, __size)
Malloc Handler to get errors and set to 0.
Definition n_common.h:187
#define __n_assert(__ptr, __ret)
macro to assert things
Definition n_common.h:258
LIST_NODE * end
pointer to the end of the list
Definition n_list.h:48
void * ptr
void pointer to store
Definition n_list.h:26
int list_push(LIST *list, void *ptr, void(*destructor)(void *ptr))
Add a pointer to the end of the list.
Definition n_list.c:199
#define list_foreach(__ITEM_, __LIST_)
ForEach macro helper.
Definition n_list.h:65
#define MAX_LIST_ITEMS
flag to pass to new_generic_list for the maximum possible number of item in a list
Definition n_list.h:55
double * newU
holder for newU arrays
Definition n_fluids.h:93
size_t numY
number of cells in Y
Definition n_fluids.h:56
size_t y_start
y start point
Definition n_fluids.h:46
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
LIST * advectSmoke_chunk_list
preprocessed list of threaded procs parameters, for n_fluid_advectSmoke
Definition n_fluids.h:117
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
void * ptr
pointer to data which will be used in the proc
Definition n_fluids.h:40
double positive_float_tolerance
fluid double positive precision setting
Definition n_fluids.h:83
LIST * solveIncompressibility_chunk_list
preprocessed list of threaded procs parameters, for n_fluid_solveIncompressibility
Definition n_fluids.h:113
size_t x_end
x end point
Definition n_fluids.h:44
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
LIST * integrate_chunk_list
preprocessed list of threaded procs parameters, for n_fluid_integrate
Definition n_fluids.h:111
double * newV
holder for newV arrays
Definition n_fluids.h:98
double dt
time between frames
Definition n_fluids.h:66
double * s
holder for s arrays
Definition n_fluids.h:103
double * v
holder for v arrays
Definition n_fluids.h:96
size_t numCells
total number of cells
Definition n_fluids.h:60
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
LIST * advectVel_chunk_list
preprocessed list of threaded procs parameters, for n_fluid_advectVel
Definition n_fluids.h:115
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 * newM
holder for newM arrays
Definition n_fluids.h:108
size_t numZ
number of cells in Z
Definition n_fluids.h:58
double * p
holder for p arrays
Definition n_fluids.h:101
size_t x_start
x start point
Definition n_fluids.h:42
double gravity
gravity on Y
Definition n_fluids.h:70
size_t y_end
y end point
Definition n_fluids.h:48
double negative_float_tolerance
fluid double negative precision setting
Definition n_fluids.h:81
double n_fluid_avgV(N_FLUID *fluid, size_t i, size_t j)
compute the average V value at a fluid position using it's surrounding
Definition n_fluids.c:392
int n_fluid_draw(N_FLUID *fluid)
draw a N_FLUID on screen / targert bitmap
Definition n_fluids.c:781
#define _z(__fluid, __component)
test if component is near zero, according to fluid's precision
Definition n_fluids.h:29
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
double n_fluid_avgU(N_FLUID *fluid, size_t i, size_t j)
compute the average U value at a fluid position using it's surrounding
Definition n_fluids.c:375
double n_fluid_sampleField(N_FLUID *fluid, double x, double y, uint32_t field)
compute a sample value at a field position
Definition n_fluids.c:320
ALLEGRO_COLOR n_fluid_getSciColor(N_FLUID *fluid, double val, double minVal, double maxVal)
get fonky colors for the fluid
Definition n_fluids.c:738
int n_fluid_extrapolate(N_FLUID *fluid)
non threaded extrapolation function
Definition n_fluids.c:298
int n_fluid_advectSmoke(N_FLUID *fluid)
non threaded version of add smoke function
Definition n_fluids.c:529
int n_fluid_solveIncompressibility(N_FLUID *fluid)
non threaded version of incompressibility solving function
Definition n_fluids.c:260
int n_fluid_resetObstacles(N_FLUID *fluid)
reset the obstacles set in a N_FLUID
Definition n_fluids.c:678
#define _zd(__fluid, __value)
test if value is near zero, according to fluid's precision
Definition n_fluids.h:34
int n_fluid_integrate(N_FLUID *fluid)
non threaded version of integration function
Definition n_fluids.c:205
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
int destroy_n_fluid(N_FLUID **fluid)
ddestroy a fluid structure
Definition n_fluids.c:44
int n_fluid_advectVel(N_FLUID *fluid)
non threaded version of add velocities function
Definition n_fluids.c:449
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
structure passed to a threaded fluid process
Definition n_fluids.h:38
int start_threaded_pool(THREAD_POOL *thread_pool)
Launch the process waiting for execution in the thread pool.
#define SYNCED_PROC
processing mode for added func, synced start
int add_threaded_process(THREAD_POOL *thread_pool, void *(*func_ptr)(void *param), void *param, int mode)
add a function and params to a thread pool
int refresh_thread_pool(THREAD_POOL *thread_pool)
try to add some waiting DIRECT_PROCs on some free thread slots, else do nothing
int wait_for_synced_threaded_pool(THREAD_POOL *thread_pool)
wait for all the launched process, blocking but light on the CPU as there is no polling
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.
void n_memset(void *dst, void *val, size_t size, size_t count)
memset bytes to a custom value
Definition n_fluids.c:31
#define N_FLUID_S_FIELD
array number for s
Definition n_fluids.c:22
#define N_FLUID_U_FIELD
array number for u
Definition n_fluids.c:18
void * n_fluid_integrate_proc(void *ptr)
ready to be threaded integration function
Definition n_fluids.c:186
void * n_fluid_advectVel_proc(void *ptr)
ready to be threaded add velocities function
Definition n_fluids.c:406
void * n_fluid_advectSmoke_proc(void *ptr)
ready to be threaded add smoke function
Definition n_fluids.c:502
int n_fluid_setObstacleFromBitmap(N_FLUID *fluid, ALLEGRO_BITMAP *bitmap, double x, double y, double vx, double vy, double r)
set an obstacle in the fluid grid from a bitmap mask
Definition n_fluids.c:702
#define N_FLUID_V_FIELD
array number for v
Definition n_fluids.c:20
void * n_fluid_solveIncompressibility_proc(void *ptr)
ready to be threaded incompressibility solving function
Definition n_fluids.c:223
fluid management port from "How to write an Eulerian fluid simulator with 200 lines of code",...
Thread pool declaration.