1 /*
2  * This program is free software; you can redistribute it and/or
3  * modify it under the terms of the GNU General Public License
4  * as published by the Free Software Foundation; either version 2
5  * of the License, or (at your option) any later version.
6  *
7  * This program is distributed in the hope that it will be useful,
8  * but WITHOUT ANY WARRANTY; without even the implied warranty of
9  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
10  * GNU General Public License for more details.
11  *
12  * You should have received a copy of the GNU General Public License
13  * along with this program; if not, write to the Free Software Foundation,
14  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
15  *
16  * The Original Code is Copyright (C) Blender Foundation.
17  * All rights reserved.
18  */
19 
20 /** \file
21  * \ingroup bke
22  */
23 
24 #include "MEM_guardedalloc.h"
25 
26 #include "BLI_listbase.h"
27 
28 #include "BLI_fileops.h"
29 #include "BLI_hash.h"
30 #include "BLI_math.h"
31 #include "BLI_path_util.h"
32 #include "BLI_string.h"
33 #include "BLI_task.h"
34 #include "BLI_utildefines.h"
35 
36 #include "DNA_defaults.h"
37 #include "DNA_fluid_types.h"
38 #include "DNA_modifier_types.h"
39 #include "DNA_object_types.h"
40 #include "DNA_rigidbody_types.h"
41 
42 #include "BKE_effect.h"
43 #include "BKE_fluid.h"
44 #include "BKE_global.h"
45 #include "BKE_lib_id.h"
46 #include "BKE_modifier.h"
47 #include "BKE_pointcache.h"
48 
49 #ifdef WITH_FLUID
50 
51 #  include <float.h>
52 #  include <math.h>
53 #  include <stdio.h>
54 #  include <string.h> /* memset */
55 
56 #  include "DNA_customdata_types.h"
57 #  include "DNA_light_types.h"
58 #  include "DNA_mesh_types.h"
59 #  include "DNA_meshdata_types.h"
60 #  include "DNA_particle_types.h"
61 #  include "DNA_scene_types.h"
62 
63 #  include "BLI_kdopbvh.h"
64 #  include "BLI_kdtree.h"
65 #  include "BLI_threads.h"
66 #  include "BLI_voxel.h"
67 
68 #  include "BKE_bvhutils.h"
69 #  include "BKE_collision.h"
70 #  include "BKE_colortools.h"
71 #  include "BKE_customdata.h"
72 #  include "BKE_deform.h"
73 #  include "BKE_mesh.h"
74 #  include "BKE_mesh_runtime.h"
75 #  include "BKE_object.h"
76 #  include "BKE_particle.h"
77 #  include "BKE_scene.h"
78 #  include "BKE_texture.h"
79 
80 #  include "DEG_depsgraph.h"
81 #  include "DEG_depsgraph_query.h"
82 
83 #  include "RE_shader_ext.h"
84 
85 #  include "CLG_log.h"
86 
87 #  include "manta_fluid_API.h"
88 
89 #endif /* WITH_FLUID */
90 
91 /** Time step default value for nice appearance. */
92 #define DT_DEFAULT 0.1f
93 
94 /** Max value for phi initialization */
95 #define PHI_MAX 9999.0f
96 
97 static void BKE_fluid_modifier_reset_ex(struct FluidModifierData *fmd, bool need_lock);
98 
99 #ifdef WITH_FLUID
100 // #define DEBUG_PRINT
101 
102 static CLG_LogRef LOG = {"bke.fluid"};
103 
104 /* -------------------------------------------------------------------- */
105 /** \name Fluid API
106  * \{ */
107 
108 static ThreadMutex object_update_lock = BLI_MUTEX_INITIALIZER;
109 
110 struct FluidModifierData;
111 struct Mesh;
112 struct Object;
113 struct Scene;
114 
115 #  define ADD_IF_LOWER_POS(a, b) (min_ff((a) + (b), max_ff((a), (b))))
116 #  define ADD_IF_LOWER_NEG(a, b) (max_ff((a) + (b), min_ff((a), (b))))
117 #  define ADD_IF_LOWER(a, b) (((b) > 0) ? ADD_IF_LOWER_POS((a), (b)) : ADD_IF_LOWER_NEG((a), (b)))
118 
BKE_fluid_reallocate_fluid(FluidDomainSettings * fds,int res[3],int free_old)119 bool BKE_fluid_reallocate_fluid(FluidDomainSettings *fds, int res[3], int free_old)
120 {
121   if (free_old && fds->fluid) {
122     manta_free(fds->fluid);
123   }
124   if (!min_iii(res[0], res[1], res[2])) {
125     fds->fluid = NULL;
126   }
127   else {
128     fds->fluid = manta_init(res, fds->fmd);
129 
130     fds->res_noise[0] = res[0] * fds->noise_scale;
131     fds->res_noise[1] = res[1] * fds->noise_scale;
132     fds->res_noise[2] = res[2] * fds->noise_scale;
133   }
134 
135   return (fds->fluid != NULL);
136 }
137 
BKE_fluid_reallocate_copy_fluid(FluidDomainSettings * fds,int o_res[3],int n_res[3],const int o_min[3],const int n_min[3],const int o_max[3],int o_shift[3],int n_shift[3])138 void BKE_fluid_reallocate_copy_fluid(FluidDomainSettings *fds,
139                                      int o_res[3],
140                                      int n_res[3],
141                                      const int o_min[3],
142                                      const int n_min[3],
143                                      const int o_max[3],
144                                      int o_shift[3],
145                                      int n_shift[3])
146 {
147   struct MANTA *fluid_old = fds->fluid;
148   const int block_size = fds->noise_scale;
149   int new_shift[3] = {0};
150   sub_v3_v3v3_int(new_shift, n_shift, o_shift);
151 
152   /* Allocate new fluid data. */
153   BKE_fluid_reallocate_fluid(fds, n_res, 0);
154 
155   int o_total_cells = o_res[0] * o_res[1] * o_res[2];
156   int n_total_cells = n_res[0] * n_res[1] * n_res[2];
157 
158   /* Copy values from old fluid to new fluid object. */
159   if (o_total_cells > 1 && n_total_cells > 1) {
160     float *o_dens = manta_smoke_get_density(fluid_old);
161     float *o_react = manta_smoke_get_react(fluid_old);
162     float *o_flame = manta_smoke_get_flame(fluid_old);
163     float *o_fuel = manta_smoke_get_fuel(fluid_old);
164     float *o_heat = manta_smoke_get_heat(fluid_old);
165     float *o_vx = manta_get_velocity_x(fluid_old);
166     float *o_vy = manta_get_velocity_y(fluid_old);
167     float *o_vz = manta_get_velocity_z(fluid_old);
168     float *o_r = manta_smoke_get_color_r(fluid_old);
169     float *o_g = manta_smoke_get_color_g(fluid_old);
170     float *o_b = manta_smoke_get_color_b(fluid_old);
171 
172     float *n_dens = manta_smoke_get_density(fds->fluid);
173     float *n_react = manta_smoke_get_react(fds->fluid);
174     float *n_flame = manta_smoke_get_flame(fds->fluid);
175     float *n_fuel = manta_smoke_get_fuel(fds->fluid);
176     float *n_heat = manta_smoke_get_heat(fds->fluid);
177     float *n_vx = manta_get_velocity_x(fds->fluid);
178     float *n_vy = manta_get_velocity_y(fds->fluid);
179     float *n_vz = manta_get_velocity_z(fds->fluid);
180     float *n_r = manta_smoke_get_color_r(fds->fluid);
181     float *n_g = manta_smoke_get_color_g(fds->fluid);
182     float *n_b = manta_smoke_get_color_b(fds->fluid);
183 
184     /* Noise smoke fields. */
185     float *o_wt_dens = manta_noise_get_density(fluid_old);
186     float *o_wt_react = manta_noise_get_react(fluid_old);
187     float *o_wt_flame = manta_noise_get_flame(fluid_old);
188     float *o_wt_fuel = manta_noise_get_fuel(fluid_old);
189     float *o_wt_r = manta_noise_get_color_r(fluid_old);
190     float *o_wt_g = manta_noise_get_color_g(fluid_old);
191     float *o_wt_b = manta_noise_get_color_b(fluid_old);
192     float *o_wt_tcu = manta_noise_get_texture_u(fluid_old);
193     float *o_wt_tcv = manta_noise_get_texture_v(fluid_old);
194     float *o_wt_tcw = manta_noise_get_texture_w(fluid_old);
195     float *o_wt_tcu2 = manta_noise_get_texture_u2(fluid_old);
196     float *o_wt_tcv2 = manta_noise_get_texture_v2(fluid_old);
197     float *o_wt_tcw2 = manta_noise_get_texture_w2(fluid_old);
198 
199     float *n_wt_dens = manta_noise_get_density(fds->fluid);
200     float *n_wt_react = manta_noise_get_react(fds->fluid);
201     float *n_wt_flame = manta_noise_get_flame(fds->fluid);
202     float *n_wt_fuel = manta_noise_get_fuel(fds->fluid);
203     float *n_wt_r = manta_noise_get_color_r(fds->fluid);
204     float *n_wt_g = manta_noise_get_color_g(fds->fluid);
205     float *n_wt_b = manta_noise_get_color_b(fds->fluid);
206     float *n_wt_tcu = manta_noise_get_texture_u(fds->fluid);
207     float *n_wt_tcv = manta_noise_get_texture_v(fds->fluid);
208     float *n_wt_tcw = manta_noise_get_texture_w(fds->fluid);
209     float *n_wt_tcu2 = manta_noise_get_texture_u2(fds->fluid);
210     float *n_wt_tcv2 = manta_noise_get_texture_v2(fds->fluid);
211     float *n_wt_tcw2 = manta_noise_get_texture_w2(fds->fluid);
212 
213     int wt_res_old[3];
214     manta_noise_get_res(fluid_old, wt_res_old);
215 
216     for (int z = o_min[2]; z < o_max[2]; z++) {
217       for (int y = o_min[1]; y < o_max[1]; y++) {
218         for (int x = o_min[0]; x < o_max[0]; x++) {
219           /* old grid index */
220           int xo = x - o_min[0];
221           int yo = y - o_min[1];
222           int zo = z - o_min[2];
223           int index_old = manta_get_index(xo, o_res[0], yo, o_res[1], zo);
224           /* new grid index */
225           int xn = x - n_min[0] - new_shift[0];
226           int yn = y - n_min[1] - new_shift[1];
227           int zn = z - n_min[2] - new_shift[2];
228           int index_new = manta_get_index(xn, n_res[0], yn, n_res[1], zn);
229 
230           /* Skip if outside new domain. */
231           if (xn < 0 || xn >= n_res[0] || yn < 0 || yn >= n_res[1] || zn < 0 || zn >= n_res[2]) {
232             continue;
233           }
234 #  if 0
235           /* Note (sebbas):
236            * Disabling this "skip section" as not copying borders results in weird cut-off effects.
237            * It is possible that this cutting off is the reason for line effects as seen in T74559.
238            * Since domain borders will be handled on the simulation side anyways,
239            * copying border values should not be an issue. */
240 
241           /* boundary cells will be skipped when copying data */
242           int bwidth = fds->boundary_width;
243 
244           /* Skip if trying to copy from old boundary cell. */
245           if (xo < bwidth || yo < bwidth || zo < bwidth || xo >= o_res[0] - bwidth ||
246               yo >= o_res[1] - bwidth || zo >= o_res[2] - bwidth) {
247             continue;
248           }
249           /* Skip if trying to copy into new boundary cell. */
250           if (xn < bwidth || yn < bwidth || zn < bwidth || xn >= n_res[0] - bwidth ||
251               yn >= n_res[1] - bwidth || zn >= n_res[2] - bwidth) {
252             continue;
253           }
254 #  endif
255 
256           /* copy data */
257           if (fds->flags & FLUID_DOMAIN_USE_NOISE) {
258             int i, j, k;
259             /* old grid index */
260             int xx_o = xo * block_size;
261             int yy_o = yo * block_size;
262             int zz_o = zo * block_size;
263             /* new grid index */
264             int xx_n = xn * block_size;
265             int yy_n = yn * block_size;
266             int zz_n = zn * block_size;
267 
268             /* insert old texture values into new texture grids */
269             n_wt_tcu[index_new] = o_wt_tcu[index_old];
270             n_wt_tcv[index_new] = o_wt_tcv[index_old];
271             n_wt_tcw[index_new] = o_wt_tcw[index_old];
272 
273             n_wt_tcu2[index_new] = o_wt_tcu2[index_old];
274             n_wt_tcv2[index_new] = o_wt_tcv2[index_old];
275             n_wt_tcw2[index_new] = o_wt_tcw2[index_old];
276 
277             for (i = 0; i < block_size; i++) {
278               for (j = 0; j < block_size; j++) {
279                 for (k = 0; k < block_size; k++) {
280                   int big_index_old = manta_get_index(
281                       xx_o + i, wt_res_old[0], yy_o + j, wt_res_old[1], zz_o + k);
282                   int big_index_new = manta_get_index(
283                       xx_n + i, fds->res_noise[0], yy_n + j, fds->res_noise[1], zz_n + k);
284                   /* copy data */
285                   n_wt_dens[big_index_new] = o_wt_dens[big_index_old];
286                   if (n_wt_flame && o_wt_flame) {
287                     n_wt_flame[big_index_new] = o_wt_flame[big_index_old];
288                     n_wt_fuel[big_index_new] = o_wt_fuel[big_index_old];
289                     n_wt_react[big_index_new] = o_wt_react[big_index_old];
290                   }
291                   if (n_wt_r && o_wt_r) {
292                     n_wt_r[big_index_new] = o_wt_r[big_index_old];
293                     n_wt_g[big_index_new] = o_wt_g[big_index_old];
294                     n_wt_b[big_index_new] = o_wt_b[big_index_old];
295                   }
296                 }
297               }
298             }
299           }
300 
301           n_dens[index_new] = o_dens[index_old];
302           /* heat */
303           if (n_heat && o_heat) {
304             n_heat[index_new] = o_heat[index_old];
305           }
306           /* fuel */
307           if (n_fuel && o_fuel) {
308             n_flame[index_new] = o_flame[index_old];
309             n_fuel[index_new] = o_fuel[index_old];
310             n_react[index_new] = o_react[index_old];
311           }
312           /* color */
313           if (o_r && n_r) {
314             n_r[index_new] = o_r[index_old];
315             n_g[index_new] = o_g[index_old];
316             n_b[index_new] = o_b[index_old];
317           }
318           n_vx[index_new] = o_vx[index_old];
319           n_vy[index_new] = o_vy[index_old];
320           n_vz[index_new] = o_vz[index_old];
321         }
322       }
323     }
324   }
325   manta_free(fluid_old);
326 }
327 
BKE_fluid_cache_free_all(FluidDomainSettings * fds,Object * ob)328 void BKE_fluid_cache_free_all(FluidDomainSettings *fds, Object *ob)
329 {
330   int cache_map = (FLUID_DOMAIN_OUTDATED_DATA | FLUID_DOMAIN_OUTDATED_NOISE |
331                    FLUID_DOMAIN_OUTDATED_MESH | FLUID_DOMAIN_OUTDATED_PARTICLES |
332                    FLUID_DOMAIN_OUTDATED_GUIDE);
333   BKE_fluid_cache_free(fds, ob, cache_map);
334 }
335 
BKE_fluid_cache_free(FluidDomainSettings * fds,Object * ob,int cache_map)336 void BKE_fluid_cache_free(FluidDomainSettings *fds, Object *ob, int cache_map)
337 {
338   char temp_dir[FILE_MAX];
339   int flags = fds->cache_flag;
340   const char *relbase = BKE_modifier_path_relbase_from_global(ob);
341 
342   if (cache_map & FLUID_DOMAIN_OUTDATED_DATA) {
343     flags &= ~(FLUID_DOMAIN_BAKING_DATA | FLUID_DOMAIN_BAKED_DATA | FLUID_DOMAIN_OUTDATED_DATA);
344     BLI_path_join(temp_dir, sizeof(temp_dir), fds->cache_directory, FLUID_DOMAIN_DIR_CONFIG, NULL);
345     BLI_path_abs(temp_dir, relbase);
346     BLI_delete(temp_dir, true, true); /* BLI_exists(filepath) is implicit */
347 
348     BLI_path_join(temp_dir, sizeof(temp_dir), fds->cache_directory, FLUID_DOMAIN_DIR_DATA, NULL);
349     BLI_path_abs(temp_dir, relbase);
350     BLI_delete(temp_dir, true, true); /* BLI_exists(filepath) is implicit */
351 
352     BLI_path_join(temp_dir, sizeof(temp_dir), fds->cache_directory, FLUID_DOMAIN_DIR_SCRIPT, NULL);
353     BLI_path_abs(temp_dir, relbase);
354     BLI_delete(temp_dir, true, true); /* BLI_exists(filepath) is implicit */
355 
356     fds->cache_frame_pause_data = 0;
357   }
358   if (cache_map & FLUID_DOMAIN_OUTDATED_NOISE) {
359     flags &= ~(FLUID_DOMAIN_BAKING_NOISE | FLUID_DOMAIN_BAKED_NOISE | FLUID_DOMAIN_OUTDATED_NOISE);
360     BLI_path_join(temp_dir, sizeof(temp_dir), fds->cache_directory, FLUID_DOMAIN_DIR_NOISE, NULL);
361     BLI_path_abs(temp_dir, relbase);
362     BLI_delete(temp_dir, true, true); /* BLI_exists(filepath) is implicit */
363 
364     fds->cache_frame_pause_noise = 0;
365   }
366   if (cache_map & FLUID_DOMAIN_OUTDATED_MESH) {
367     flags &= ~(FLUID_DOMAIN_BAKING_MESH | FLUID_DOMAIN_BAKED_MESH | FLUID_DOMAIN_OUTDATED_MESH);
368     BLI_path_join(temp_dir, sizeof(temp_dir), fds->cache_directory, FLUID_DOMAIN_DIR_MESH, NULL);
369     BLI_path_abs(temp_dir, relbase);
370     BLI_delete(temp_dir, true, true); /* BLI_exists(filepath) is implicit */
371 
372     fds->cache_frame_pause_mesh = 0;
373   }
374   if (cache_map & FLUID_DOMAIN_OUTDATED_PARTICLES) {
375     flags &= ~(FLUID_DOMAIN_BAKING_PARTICLES | FLUID_DOMAIN_BAKED_PARTICLES |
376                FLUID_DOMAIN_OUTDATED_PARTICLES);
377     BLI_path_join(
378         temp_dir, sizeof(temp_dir), fds->cache_directory, FLUID_DOMAIN_DIR_PARTICLES, NULL);
379     BLI_path_abs(temp_dir, relbase);
380     BLI_delete(temp_dir, true, true); /* BLI_exists(filepath) is implicit */
381 
382     fds->cache_frame_pause_particles = 0;
383   }
384 
385   if (cache_map & FLUID_DOMAIN_OUTDATED_GUIDE) {
386     flags &= ~(FLUID_DOMAIN_BAKING_GUIDE | FLUID_DOMAIN_BAKED_GUIDE | FLUID_DOMAIN_OUTDATED_GUIDE);
387     BLI_path_join(temp_dir, sizeof(temp_dir), fds->cache_directory, FLUID_DOMAIN_DIR_GUIDE, NULL);
388     BLI_path_abs(temp_dir, relbase);
389     BLI_delete(temp_dir, true, true); /* BLI_exists(filepath) is implicit */
390 
391     fds->cache_frame_pause_guide = 0;
392   }
393   fds->cache_flag = flags;
394 }
395 
396 /* convert global position to domain cell space */
manta_pos_to_cell(FluidDomainSettings * fds,float pos[3])397 static void manta_pos_to_cell(FluidDomainSettings *fds, float pos[3])
398 {
399   mul_m4_v3(fds->imat, pos);
400   sub_v3_v3(pos, fds->p0);
401   pos[0] *= 1.0f / fds->cell_size[0];
402   pos[1] *= 1.0f / fds->cell_size[1];
403   pos[2] *= 1.0f / fds->cell_size[2];
404 }
405 
406 /* Set domain transformations and base resolution from object mesh. */
manta_set_domain_from_mesh(FluidDomainSettings * fds,Object * ob,Mesh * me,bool init_resolution)407 static void manta_set_domain_from_mesh(FluidDomainSettings *fds,
408                                        Object *ob,
409                                        Mesh *me,
410                                        bool init_resolution)
411 {
412   size_t i;
413   float min[3] = {FLT_MAX, FLT_MAX, FLT_MAX}, max[3] = {-FLT_MAX, -FLT_MAX, -FLT_MAX};
414   float size[3];
415   MVert *verts = me->mvert;
416   float scale = 0.0;
417   int res;
418 
419   res = fds->maxres;
420 
421   /* Set minimum and maximum coordinates of BB. */
422   for (i = 0; i < me->totvert; i++) {
423     minmax_v3v3_v3(min, max, verts[i].co);
424   }
425 
426   /* Set domain bounds. */
427   copy_v3_v3(fds->p0, min);
428   copy_v3_v3(fds->p1, max);
429   fds->dx = 1.0f / res;
430 
431   /* Calculate domain dimensions. */
432   sub_v3_v3v3(size, max, min);
433   if (init_resolution) {
434     zero_v3_int(fds->base_res);
435     copy_v3_v3(fds->cell_size, size);
436   }
437   /* Apply object scale. */
438   for (i = 0; i < 3; i++) {
439     size[i] = fabsf(size[i] * ob->scale[i]);
440   }
441   copy_v3_v3(fds->global_size, size);
442   copy_v3_v3(fds->dp0, min);
443 
444   invert_m4_m4(fds->imat, ob->obmat);
445 
446   /* Prevent crash when initializing a plane as domain. */
447   if (!init_resolution || (size[0] < FLT_EPSILON) || (size[1] < FLT_EPSILON) ||
448       (size[2] < FLT_EPSILON)) {
449     return;
450   }
451 
452   /* Define grid resolutions from longest domain side. */
453   if (size[0] >= MAX2(size[1], size[2])) {
454     scale = res / size[0];
455     fds->scale = size[0] / fabsf(ob->scale[0]);
456     fds->base_res[0] = res;
457     fds->base_res[1] = max_ii((int)(size[1] * scale + 0.5f), 4);
458     fds->base_res[2] = max_ii((int)(size[2] * scale + 0.5f), 4);
459   }
460   else if (size[1] >= MAX2(size[0], size[2])) {
461     scale = res / size[1];
462     fds->scale = size[1] / fabsf(ob->scale[1]);
463     fds->base_res[0] = max_ii((int)(size[0] * scale + 0.5f), 4);
464     fds->base_res[1] = res;
465     fds->base_res[2] = max_ii((int)(size[2] * scale + 0.5f), 4);
466   }
467   else {
468     scale = res / size[2];
469     fds->scale = size[2] / fabsf(ob->scale[2]);
470     fds->base_res[0] = max_ii((int)(size[0] * scale + 0.5f), 4);
471     fds->base_res[1] = max_ii((int)(size[1] * scale + 0.5f), 4);
472     fds->base_res[2] = res;
473   }
474 
475   /* Set cell size. */
476   fds->cell_size[0] /= (float)fds->base_res[0];
477   fds->cell_size[1] /= (float)fds->base_res[1];
478   fds->cell_size[2] /= (float)fds->base_res[2];
479 }
480 
update_final_gravity(FluidDomainSettings * fds,Scene * scene)481 static void update_final_gravity(FluidDomainSettings *fds, Scene *scene)
482 {
483   if (scene->physics_settings.flag & PHYS_GLOBAL_GRAVITY) {
484     copy_v3_v3(fds->gravity_final, scene->physics_settings.gravity);
485   }
486   else {
487     copy_v3_v3(fds->gravity_final, fds->gravity);
488   }
489   mul_v3_fl(fds->gravity_final, fds->effector_weights->global_gravity);
490 }
491 
BKE_fluid_modifier_init(FluidModifierData * fmd,Depsgraph * depsgraph,Object * ob,Scene * scene,Mesh * me)492 static bool BKE_fluid_modifier_init(
493     FluidModifierData *fmd, Depsgraph *depsgraph, Object *ob, Scene *scene, Mesh *me)
494 {
495   int scene_framenr = (int)DEG_get_ctime(depsgraph);
496 
497   if ((fmd->type & MOD_FLUID_TYPE_DOMAIN) && fmd->domain && !fmd->domain->fluid) {
498     FluidDomainSettings *fds = fmd->domain;
499     int res[3];
500     /* Set domain dimensions from mesh. */
501     manta_set_domain_from_mesh(fds, ob, me, true);
502     /* Set domain gravity, use global gravity if enabled. */
503     update_final_gravity(fds, scene);
504     /* Reset domain values. */
505     zero_v3_int(fds->shift);
506     zero_v3(fds->shift_f);
507     add_v3_fl(fds->shift_f, 0.5f);
508     zero_v3(fds->prev_loc);
509     mul_m4_v3(ob->obmat, fds->prev_loc);
510     copy_m4_m4(fds->obmat, ob->obmat);
511 
512     /* Set resolutions. */
513     if (fmd->domain->type == FLUID_DOMAIN_TYPE_GAS &&
514         fmd->domain->flags & FLUID_DOMAIN_USE_ADAPTIVE_DOMAIN) {
515       res[0] = res[1] = res[2] = 1; /* Use minimum res for adaptive init. */
516     }
517     else {
518       copy_v3_v3_int(res, fds->base_res);
519     }
520     copy_v3_v3_int(fds->res, res);
521     fds->total_cells = fds->res[0] * fds->res[1] * fds->res[2];
522     fds->res_min[0] = fds->res_min[1] = fds->res_min[2] = 0;
523     copy_v3_v3_int(fds->res_max, res);
524 
525     /* Set time, frame length = 0.1 is at 25fps. */
526     float fps = scene->r.frs_sec / scene->r.frs_sec_base;
527     fds->frame_length = DT_DEFAULT * (25.0f / fps) * fds->time_scale;
528     /* Initially dt is equal to frame length (dt can change with adaptive-time stepping though). */
529     fds->dt = fds->frame_length;
530     fds->time_per_frame = 0;
531 
532     fmd->time = scene_framenr;
533 
534     /* Allocate fluid. */
535     return BKE_fluid_reallocate_fluid(fds, fds->res, 0);
536   }
537   if (fmd->type & MOD_FLUID_TYPE_FLOW) {
538     if (!fmd->flow) {
539       BKE_fluid_modifier_create_type_data(fmd);
540     }
541     fmd->time = scene_framenr;
542     return true;
543   }
544   if (fmd->type & MOD_FLUID_TYPE_EFFEC) {
545     if (!fmd->effector) {
546       BKE_fluid_modifier_create_type_data(fmd);
547     }
548     fmd->time = scene_framenr;
549     return true;
550   }
551   return false;
552 }
553 
554 // forward declaration
555 static void manta_smoke_calc_transparency(FluidDomainSettings *fds, ViewLayer *view_layer);
556 static float calc_voxel_transp(
557     float *result, const float *input, int res[3], int *pixel, float *t_ray, float correct);
558 static void update_distances(int index,
559                              float *distance_map,
560                              BVHTreeFromMesh *tree_data,
561                              const float ray_start[3],
562                              float surface_thickness,
563                              bool use_plane_init);
564 
get_light(ViewLayer * view_layer,float * light)565 static int get_light(ViewLayer *view_layer, float *light)
566 {
567   Base *base_tmp = NULL;
568   int found_light = 0;
569 
570   /* Try to find a lamp, preferably local. */
571   for (base_tmp = FIRSTBASE(view_layer); base_tmp; base_tmp = base_tmp->next) {
572     if (base_tmp->object->type == OB_LAMP) {
573       Light *la = base_tmp->object->data;
574 
575       if (la->type == LA_LOCAL) {
576         copy_v3_v3(light, base_tmp->object->obmat[3]);
577         return 1;
578       }
579       if (!found_light) {
580         copy_v3_v3(light, base_tmp->object->obmat[3]);
581         found_light = 1;
582       }
583     }
584   }
585 
586   return found_light;
587 }
588 
clamp_bounds_in_domain(FluidDomainSettings * fds,int min[3],int max[3],const float * min_vel,const float * max_vel,int margin,float dt)589 static void clamp_bounds_in_domain(FluidDomainSettings *fds,
590                                    int min[3],
591                                    int max[3],
592                                    const float *min_vel,
593                                    const float *max_vel,
594                                    int margin,
595                                    float dt)
596 {
597   for (int i = 0; i < 3; i++) {
598     int adapt = (fds->flags & FLUID_DOMAIN_USE_ADAPTIVE_DOMAIN) ? fds->adapt_res : 0;
599     /* Add some margin. */
600     min[i] -= margin;
601     max[i] += margin;
602 
603     /* Adapt to velocity. */
604     if (min_vel && min_vel[i] < 0.0f) {
605       min[i] += (int)floor(min_vel[i] * dt);
606     }
607     if (max_vel && max_vel[i] > 0.0f) {
608       max[i] += (int)ceil(max_vel[i] * dt);
609     }
610 
611     /* Clamp within domain max size. */
612     CLAMP(min[i], -adapt, fds->base_res[i] + adapt);
613     CLAMP(max[i], -adapt, fds->base_res[i] + adapt);
614   }
615 }
616 
is_static_object(Object * ob)617 static bool is_static_object(Object *ob)
618 {
619   /* Check if the object has modifiers that might make the object "dynamic". */
620   ModifierData *md = ob->modifiers.first;
621   for (; md; md = md->next) {
622     if (ELEM(md->type,
623              eModifierType_Cloth,
624              eModifierType_DynamicPaint,
625              eModifierType_Explode,
626              eModifierType_Ocean,
627              eModifierType_ShapeKey,
628              eModifierType_Softbody)) {
629       return false;
630     }
631   }
632 
633   /* Active rigid body objects considered to be dynamic fluid objects. */
634   if (ob->rigidbody_object && ob->rigidbody_object->type == RBO_TYPE_ACTIVE) {
635     return false;
636   }
637 
638   /* Finally, check if the object has animation data. If so, it is considered dynamic. */
639   return !BKE_object_moves_in_time(ob, true);
640 }
641 
642 /** \} */
643 
644 /* -------------------------------------------------------------------- */
645 /** \name Bounding Box
646  * \{ */
647 
648 typedef struct FluidObjectBB {
649   float *influence;
650   float *velocity;
651   float *distances;
652   float *numobjs;
653   int min[3], max[3], res[3];
654   int hmin[3], hmax[3], hres[3];
655   int total_cells, valid;
656 } FluidObjectBB;
657 
bb_boundInsert(FluidObjectBB * bb,const float point[3])658 static void bb_boundInsert(FluidObjectBB *bb, const float point[3])
659 {
660   int i = 0;
661   if (!bb->valid) {
662     for (; i < 3; i++) {
663       bb->min[i] = (int)floor(point[i]);
664       bb->max[i] = (int)ceil(point[i]);
665     }
666     bb->valid = 1;
667   }
668   else {
669     for (; i < 3; i++) {
670       if (point[i] < bb->min[i]) {
671         bb->min[i] = (int)floor(point[i]);
672       }
673       if (point[i] > bb->max[i]) {
674         bb->max[i] = (int)ceil(point[i]);
675       }
676     }
677   }
678 }
679 
bb_allocateData(FluidObjectBB * bb,bool use_velocity,bool use_influence)680 static void bb_allocateData(FluidObjectBB *bb, bool use_velocity, bool use_influence)
681 {
682   int i, res[3];
683 
684   for (i = 0; i < 3; i++) {
685     res[i] = bb->max[i] - bb->min[i];
686     if (res[i] <= 0) {
687       return;
688     }
689   }
690   bb->total_cells = res[0] * res[1] * res[2];
691   copy_v3_v3_int(bb->res, res);
692 
693   bb->numobjs = MEM_calloc_arrayN(bb->total_cells, sizeof(float), "fluid_bb_numobjs");
694   if (use_influence) {
695     bb->influence = MEM_calloc_arrayN(bb->total_cells, sizeof(float), "fluid_bb_influence");
696   }
697   if (use_velocity) {
698     bb->velocity = MEM_calloc_arrayN(bb->total_cells, sizeof(float[3]), "fluid_bb_velocity");
699   }
700 
701   bb->distances = MEM_malloc_arrayN(bb->total_cells, sizeof(float), "fluid_bb_distances");
702   copy_vn_fl(bb->distances, bb->total_cells, FLT_MAX);
703 
704   bb->valid = true;
705 }
706 
bb_freeData(FluidObjectBB * bb)707 static void bb_freeData(FluidObjectBB *bb)
708 {
709   if (bb->numobjs) {
710     MEM_freeN(bb->numobjs);
711   }
712   if (bb->influence) {
713     MEM_freeN(bb->influence);
714   }
715   if (bb->velocity) {
716     MEM_freeN(bb->velocity);
717   }
718   if (bb->distances) {
719     MEM_freeN(bb->distances);
720   }
721 }
722 
bb_combineMaps(FluidObjectBB * output,FluidObjectBB * bb2,int additive,float sample_size)723 static void bb_combineMaps(FluidObjectBB *output,
724                            FluidObjectBB *bb2,
725                            int additive,
726                            float sample_size)
727 {
728   int i, x, y, z;
729 
730   /* Copyfill input 1 struct and clear output for new allocation. */
731   FluidObjectBB bb1;
732   memcpy(&bb1, output, sizeof(FluidObjectBB));
733   memset(output, 0, sizeof(FluidObjectBB));
734 
735   for (i = 0; i < 3; i++) {
736     if (bb1.valid) {
737       output->min[i] = MIN2(bb1.min[i], bb2->min[i]);
738       output->max[i] = MAX2(bb1.max[i], bb2->max[i]);
739     }
740     else {
741       output->min[i] = bb2->min[i];
742       output->max[i] = bb2->max[i];
743     }
744   }
745   /* Allocate output map. */
746   bb_allocateData(output, (bb1.velocity || bb2->velocity), (bb1.influence || bb2->influence));
747 
748   /* Low through bounding box */
749   for (x = output->min[0]; x < output->max[0]; x++) {
750     for (y = output->min[1]; y < output->max[1]; y++) {
751       for (z = output->min[2]; z < output->max[2]; z++) {
752         int index_out = manta_get_index(x - output->min[0],
753                                         output->res[0],
754                                         y - output->min[1],
755                                         output->res[1],
756                                         z - output->min[2]);
757 
758         /* Initialize with first input if in range. */
759         if (x >= bb1.min[0] && x < bb1.max[0] && y >= bb1.min[1] && y < bb1.max[1] &&
760             z >= bb1.min[2] && z < bb1.max[2]) {
761           int index_in = manta_get_index(
762               x - bb1.min[0], bb1.res[0], y - bb1.min[1], bb1.res[1], z - bb1.min[2]);
763 
764           /* Values. */
765           output->numobjs[index_out] = bb1.numobjs[index_in];
766           if (output->influence && bb1.influence) {
767             output->influence[index_out] = bb1.influence[index_in];
768           }
769           output->distances[index_out] = bb1.distances[index_in];
770           if (output->velocity && bb1.velocity) {
771             copy_v3_v3(&output->velocity[index_out * 3], &bb1.velocity[index_in * 3]);
772           }
773         }
774 
775         /* Apply second input if in range. */
776         if (x >= bb2->min[0] && x < bb2->max[0] && y >= bb2->min[1] && y < bb2->max[1] &&
777             z >= bb2->min[2] && z < bb2->max[2]) {
778           int index_in = manta_get_index(
779               x - bb2->min[0], bb2->res[0], y - bb2->min[1], bb2->res[1], z - bb2->min[2]);
780 
781           /* Values. */
782           output->numobjs[index_out] = MAX2(bb2->numobjs[index_in], output->numobjs[index_out]);
783           if (output->influence && bb2->influence) {
784             if (additive) {
785               output->influence[index_out] += bb2->influence[index_in] * sample_size;
786             }
787             else {
788               output->influence[index_out] = MAX2(bb2->influence[index_in],
789                                                   output->influence[index_out]);
790             }
791           }
792           output->distances[index_out] = MIN2(bb2->distances[index_in],
793                                               output->distances[index_out]);
794           if (output->velocity && bb2->velocity) {
795             /* Last sample replaces the velocity. */
796             output->velocity[index_out * 3] = ADD_IF_LOWER(output->velocity[index_out * 3],
797                                                            bb2->velocity[index_in * 3]);
798             output->velocity[index_out * 3 + 1] = ADD_IF_LOWER(output->velocity[index_out * 3 + 1],
799                                                                bb2->velocity[index_in * 3 + 1]);
800             output->velocity[index_out * 3 + 2] = ADD_IF_LOWER(output->velocity[index_out * 3 + 2],
801                                                                bb2->velocity[index_in * 3 + 2]);
802           }
803         }
804       } /* Low res loop. */
805     }
806   }
807 
808   /* Free original data. */
809   bb_freeData(&bb1);
810 }
811 
812 /** \} */
813 
814 /* -------------------------------------------------------------------- */
815 /** \name Effectors
816  * \{ */
817 
apply_effector_fields(FluidEffectorSettings * UNUSED (fes),int index,float src_distance_value,float * dest_phi_in,float src_numobjs_value,float * dest_numobjs,float const src_vel_value[3],float * dest_vel_x,float * dest_vel_y,float * dest_vel_z)818 BLI_INLINE void apply_effector_fields(FluidEffectorSettings *UNUSED(fes),
819                                       int index,
820                                       float src_distance_value,
821                                       float *dest_phi_in,
822                                       float src_numobjs_value,
823                                       float *dest_numobjs,
824                                       float const src_vel_value[3],
825                                       float *dest_vel_x,
826                                       float *dest_vel_y,
827                                       float *dest_vel_z)
828 {
829   /* Ensure that distance value is "joined" into the levelset. */
830   if (dest_phi_in) {
831     dest_phi_in[index] = MIN2(src_distance_value, dest_phi_in[index]);
832   }
833 
834   /* Accumulate effector object count (important once effector object overlap). */
835   if (dest_numobjs && src_numobjs_value > 0) {
836     dest_numobjs[index] += 1;
837   }
838 
839   /* Accumulate effector velocities for each cell. */
840   if (dest_vel_x && src_numobjs_value > 0) {
841     dest_vel_x[index] += src_vel_value[0];
842     dest_vel_y[index] += src_vel_value[1];
843     dest_vel_z[index] += src_vel_value[2];
844   }
845 }
846 
update_velocities(FluidEffectorSettings * fes,const MVert * mvert,const MLoop * mloop,const MLoopTri * mlooptri,float * velocity_map,int index,BVHTreeFromMesh * tree_data,const float ray_start[3],const float * vert_vel,bool has_velocity)847 static void update_velocities(FluidEffectorSettings *fes,
848                               const MVert *mvert,
849                               const MLoop *mloop,
850                               const MLoopTri *mlooptri,
851                               float *velocity_map,
852                               int index,
853                               BVHTreeFromMesh *tree_data,
854                               const float ray_start[3],
855                               const float *vert_vel,
856                               bool has_velocity)
857 {
858   BVHTreeNearest nearest = {0};
859   nearest.index = -1;
860 
861   /* Distance between two opposing vertices in a unit cube.
862    * I.e. the unit cube diagonal or sqrt(3).
863    * This value is our nearest neighbor search distance. */
864   const float surface_distance = 1.732;
865   nearest.dist_sq = surface_distance * surface_distance; /* find_nearest uses squared distance */
866 
867   /* Find the nearest point on the mesh. */
868   if (has_velocity &&
869       BLI_bvhtree_find_nearest(
870           tree_data->tree, ray_start, &nearest, tree_data->nearest_callback, tree_data) != -1) {
871     float weights[3];
872     int v1, v2, v3, f_index = nearest.index;
873 
874     /* Calculate barycentric weights for nearest point. */
875     v1 = mloop[mlooptri[f_index].tri[0]].v;
876     v2 = mloop[mlooptri[f_index].tri[1]].v;
877     v3 = mloop[mlooptri[f_index].tri[2]].v;
878     interp_weights_tri_v3(weights, mvert[v1].co, mvert[v2].co, mvert[v3].co, nearest.co);
879 
880     /* Apply object velocity. */
881     float hit_vel[3];
882     interp_v3_v3v3v3(hit_vel, &vert_vel[v1 * 3], &vert_vel[v2 * 3], &vert_vel[v3 * 3], weights);
883 
884     /* Guiding has additional velocity multiplier */
885     if (fes->type == FLUID_EFFECTOR_TYPE_GUIDE) {
886       mul_v3_fl(hit_vel, fes->vel_multi);
887 
888       /* Absolute representation of new object velocity. */
889       float abs_hit_vel[3];
890       copy_v3_v3(abs_hit_vel, hit_vel);
891       abs_v3(abs_hit_vel);
892 
893       /* Absolute representation of current object velocity. */
894       float abs_vel[3];
895       copy_v3_v3(abs_vel, &velocity_map[index * 3]);
896       abs_v3(abs_vel);
897 
898       switch (fes->guide_mode) {
899         case FLUID_EFFECTOR_GUIDE_AVERAGED:
900           velocity_map[index * 3] = (velocity_map[index * 3] + hit_vel[0]) * 0.5f;
901           velocity_map[index * 3 + 1] = (velocity_map[index * 3 + 1] + hit_vel[1]) * 0.5f;
902           velocity_map[index * 3 + 2] = (velocity_map[index * 3 + 2] + hit_vel[2]) * 0.5f;
903           break;
904         case FLUID_EFFECTOR_GUIDE_OVERRIDE:
905           velocity_map[index * 3] = hit_vel[0];
906           velocity_map[index * 3 + 1] = hit_vel[1];
907           velocity_map[index * 3 + 2] = hit_vel[2];
908           break;
909         case FLUID_EFFECTOR_GUIDE_MIN:
910           velocity_map[index * 3] = MIN2(abs_hit_vel[0], abs_vel[0]);
911           velocity_map[index * 3 + 1] = MIN2(abs_hit_vel[1], abs_vel[1]);
912           velocity_map[index * 3 + 2] = MIN2(abs_hit_vel[2], abs_vel[2]);
913           break;
914         case FLUID_EFFECTOR_GUIDE_MAX:
915         default:
916           velocity_map[index * 3] = MAX2(abs_hit_vel[0], abs_vel[0]);
917           velocity_map[index * 3 + 1] = MAX2(abs_hit_vel[1], abs_vel[1]);
918           velocity_map[index * 3 + 2] = MAX2(abs_hit_vel[2], abs_vel[2]);
919           break;
920       }
921     }
922     else if (fes->type == FLUID_EFFECTOR_TYPE_COLLISION) {
923       velocity_map[index * 3] = hit_vel[0];
924       velocity_map[index * 3 + 1] = hit_vel[1];
925       velocity_map[index * 3 + 2] = hit_vel[2];
926 #  ifdef DEBUG_PRINT
927       /* Debugging: Print object velocities. */
928       printf("setting effector object vel: [%f, %f, %f]\n", hit_vel[0], hit_vel[1], hit_vel[2]);
929 #  endif
930     }
931     else {
932       /* Should never reach this block. */
933       BLI_assert(false);
934     }
935   }
936   else {
937     /* Clear velocities at cells that are not moving. */
938     copy_v3_fl(velocity_map, 0.0);
939   }
940 }
941 
942 typedef struct ObstaclesFromDMData {
943   FluidEffectorSettings *fes;
944 
945   const MVert *mvert;
946   const MLoop *mloop;
947   const MLoopTri *mlooptri;
948 
949   BVHTreeFromMesh *tree;
950   FluidObjectBB *bb;
951 
952   bool has_velocity;
953   float *vert_vel;
954   int *min, *max, *res;
955 } ObstaclesFromDMData;
956 
obstacles_from_mesh_task_cb(void * __restrict userdata,const int z,const TaskParallelTLS * __restrict UNUSED (tls))957 static void obstacles_from_mesh_task_cb(void *__restrict userdata,
958                                         const int z,
959                                         const TaskParallelTLS *__restrict UNUSED(tls))
960 {
961   ObstaclesFromDMData *data = userdata;
962   FluidObjectBB *bb = data->bb;
963 
964   for (int x = data->min[0]; x < data->max[0]; x++) {
965     for (int y = data->min[1]; y < data->max[1]; y++) {
966       const int index = manta_get_index(
967           x - bb->min[0], bb->res[0], y - bb->min[1], bb->res[1], z - bb->min[2]);
968       const float ray_start[3] = {(float)x + 0.5f, (float)y + 0.5f, (float)z + 0.5f};
969 
970       /* Calculate levelset values from meshes. Result in bb->distances. */
971       update_distances(index,
972                        bb->distances,
973                        data->tree,
974                        ray_start,
975                        data->fes->surface_distance,
976                        data->fes->flags & FLUID_EFFECTOR_USE_PLANE_INIT);
977 
978       /* Calculate object velocities. Result in bb->velocity. */
979       update_velocities(data->fes,
980                         data->mvert,
981                         data->mloop,
982                         data->mlooptri,
983                         bb->velocity,
984                         index,
985                         data->tree,
986                         ray_start,
987                         data->vert_vel,
988                         data->has_velocity);
989 
990       /* Increase obstacle count inside of moving obstacles. */
991       if (bb->distances[index] < 0) {
992         bb->numobjs[index]++;
993       }
994     }
995   }
996 }
997 
obstacles_from_mesh(Object * coll_ob,FluidDomainSettings * fds,FluidEffectorSettings * fes,FluidObjectBB * bb,float dt)998 static void obstacles_from_mesh(Object *coll_ob,
999                                 FluidDomainSettings *fds,
1000                                 FluidEffectorSettings *fes,
1001                                 FluidObjectBB *bb,
1002                                 float dt)
1003 {
1004   if (fes->mesh) {
1005     Mesh *me = NULL;
1006     MVert *mvert = NULL;
1007     const MLoopTri *looptri;
1008     const MLoop *mloop;
1009     BVHTreeFromMesh tree_data = {NULL};
1010     int numverts, i;
1011 
1012     float *vert_vel = NULL;
1013     bool has_velocity = false;
1014 
1015     me = BKE_mesh_copy_for_eval(fes->mesh, true);
1016 
1017     int min[3], max[3], res[3];
1018 
1019     /* Duplicate vertices to modify. */
1020     if (me->mvert) {
1021       me->mvert = MEM_dupallocN(me->mvert);
1022       CustomData_set_layer(&me->vdata, CD_MVERT, me->mvert);
1023     }
1024 
1025     BKE_mesh_ensure_normals(me);
1026     mvert = me->mvert;
1027     mloop = me->mloop;
1028     looptri = BKE_mesh_runtime_looptri_ensure(me);
1029     numverts = me->totvert;
1030 
1031     /* TODO(sebbas): Make initialization of vertex velocities optional? */
1032     {
1033       vert_vel = MEM_callocN(sizeof(float[3]) * numverts, "manta_obs_velocity");
1034 
1035       if (fes->numverts != numverts || !fes->verts_old) {
1036         if (fes->verts_old) {
1037           MEM_freeN(fes->verts_old);
1038         }
1039 
1040         fes->verts_old = MEM_callocN(sizeof(float[3]) * numverts, "manta_obs_verts_old");
1041         fes->numverts = numverts;
1042       }
1043       else {
1044         has_velocity = true;
1045       }
1046     }
1047 
1048     /* Transform mesh vertices to domain grid space for fast lookups */
1049     for (i = 0; i < numverts; i++) {
1050       float n[3];
1051       float co[3];
1052 
1053       /* Vertex position. */
1054       mul_m4_v3(coll_ob->obmat, mvert[i].co);
1055       manta_pos_to_cell(fds, mvert[i].co);
1056 
1057       /* Vertex normal. */
1058       normal_short_to_float_v3(n, mvert[i].no);
1059       mul_mat3_m4_v3(coll_ob->obmat, n);
1060       mul_mat3_m4_v3(fds->imat, n);
1061       normalize_v3(n);
1062       normal_float_to_short_v3(mvert[i].no, n);
1063 
1064       /* Vertex velocity. */
1065       add_v3fl_v3fl_v3i(co, mvert[i].co, fds->shift);
1066       if (has_velocity) {
1067         sub_v3_v3v3(&vert_vel[i * 3], co, &fes->verts_old[i * 3]);
1068         mul_v3_fl(&vert_vel[i * 3], 1.0f / dt);
1069       }
1070       copy_v3_v3(&fes->verts_old[i * 3], co);
1071 
1072       /* Calculate emission map bounds. */
1073       bb_boundInsert(bb, mvert[i].co);
1074     }
1075 
1076     /* Set emission map.
1077      * Use 3 cell diagonals as margin (3 * 1.732 = 5.196). */
1078     int bounds_margin = (int)ceil(5.196);
1079     clamp_bounds_in_domain(fds, bb->min, bb->max, NULL, NULL, bounds_margin, dt);
1080     bb_allocateData(bb, true, false);
1081 
1082     /* Setup loop bounds. */
1083     for (i = 0; i < 3; i++) {
1084       min[i] = bb->min[i];
1085       max[i] = bb->max[i];
1086       res[i] = bb->res[i];
1087     }
1088 
1089     /* Skip effector sampling loop if object has disabled effector. */
1090     bool use_effector = fes->flags & FLUID_EFFECTOR_USE_EFFEC;
1091     if (use_effector && BKE_bvhtree_from_mesh_get(&tree_data, me, BVHTREE_FROM_LOOPTRI, 4)) {
1092 
1093       ObstaclesFromDMData data = {
1094           .fes = fes,
1095           .mvert = mvert,
1096           .mloop = mloop,
1097           .mlooptri = looptri,
1098           .tree = &tree_data,
1099           .bb = bb,
1100           .has_velocity = has_velocity,
1101           .vert_vel = vert_vel,
1102           .min = min,
1103           .max = max,
1104           .res = res,
1105       };
1106 
1107       TaskParallelSettings settings;
1108       BLI_parallel_range_settings_defaults(&settings);
1109       settings.min_iter_per_thread = 2;
1110       BLI_task_parallel_range(min[2], max[2], &data, obstacles_from_mesh_task_cb, &settings);
1111     }
1112     /* Free bvh tree. */
1113     free_bvhtree_from_mesh(&tree_data);
1114 
1115     if (vert_vel) {
1116       MEM_freeN(vert_vel);
1117     }
1118     if (me->mvert) {
1119       MEM_freeN(me->mvert);
1120     }
1121     BKE_id_free(NULL, me);
1122   }
1123 }
1124 
ensure_obstaclefields(FluidDomainSettings * fds)1125 static void ensure_obstaclefields(FluidDomainSettings *fds)
1126 {
1127   if (fds->active_fields & FLUID_DOMAIN_ACTIVE_OBSTACLE) {
1128     manta_ensure_obstacle(fds->fluid, fds->fmd);
1129   }
1130   if (fds->active_fields & FLUID_DOMAIN_ACTIVE_GUIDE) {
1131     manta_ensure_guiding(fds->fluid, fds->fmd);
1132   }
1133   manta_update_pointers(fds->fluid, fds->fmd, false);
1134 }
1135 
update_obstacleflags(FluidDomainSettings * fds,Object ** coll_ob_array,int coll_ob_array_len)1136 static void update_obstacleflags(FluidDomainSettings *fds,
1137                                  Object **coll_ob_array,
1138                                  int coll_ob_array_len)
1139 {
1140   int active_fields = fds->active_fields;
1141   uint coll_index;
1142 
1143   /* First, remove all flags that we want to update. */
1144   int prev_flags = (FLUID_DOMAIN_ACTIVE_OBSTACLE | FLUID_DOMAIN_ACTIVE_GUIDE);
1145   active_fields &= ~prev_flags;
1146 
1147   /* Monitor active fields based on flow settings */
1148   for (coll_index = 0; coll_index < coll_ob_array_len; coll_index++) {
1149     Object *coll_ob = coll_ob_array[coll_index];
1150     FluidModifierData *fmd2 = (FluidModifierData *)BKE_modifiers_findby_type(coll_ob,
1151                                                                              eModifierType_Fluid);
1152 
1153     /* Sanity check. */
1154     if (!fmd2) {
1155       continue;
1156     }
1157 
1158     if ((fmd2->type & MOD_FLUID_TYPE_EFFEC) && fmd2->effector) {
1159       FluidEffectorSettings *fes = fmd2->effector;
1160       if (!fes) {
1161         break;
1162       }
1163       if (fes->flags & FLUID_EFFECTOR_NEEDS_UPDATE) {
1164         fes->flags &= ~FLUID_EFFECTOR_NEEDS_UPDATE;
1165         fds->cache_flag |= FLUID_DOMAIN_OUTDATED_DATA;
1166       }
1167       if (fes->type == FLUID_EFFECTOR_TYPE_COLLISION) {
1168         active_fields |= FLUID_DOMAIN_ACTIVE_OBSTACLE;
1169       }
1170       if (fes->type == FLUID_EFFECTOR_TYPE_GUIDE) {
1171         active_fields |= FLUID_DOMAIN_ACTIVE_GUIDE;
1172       }
1173     }
1174   }
1175   fds->active_fields = active_fields;
1176 }
1177 
escape_effectorobject(Object * flowobj,FluidDomainSettings * fds,FluidEffectorSettings * UNUSED (fes),int frame)1178 static bool escape_effectorobject(Object *flowobj,
1179                                   FluidDomainSettings *fds,
1180                                   FluidEffectorSettings *UNUSED(fes),
1181                                   int frame)
1182 {
1183   bool is_static = is_static_object(flowobj);
1184 
1185   bool is_resume = (fds->cache_frame_pause_data == frame);
1186   bool is_adaptive = (fds->flags & FLUID_DOMAIN_USE_ADAPTIVE_DOMAIN);
1187   bool is_first_frame = (frame == fds->cache_frame_start);
1188 
1189   /* Cannot use static mode with adaptive domain.
1190    * The adaptive domain might expand and only later discover the static object. */
1191   if (is_adaptive) {
1192     is_static = false;
1193   }
1194   /* Skip static effector objects after initial frame. */
1195   if (is_static && !is_first_frame && !is_resume) {
1196     return true;
1197   }
1198   return false;
1199 }
1200 
compute_obstaclesemission(Scene * scene,FluidObjectBB * bb_maps,struct Depsgraph * depsgraph,float dt,Object ** effecobjs,int frame,float frame_length,FluidDomainSettings * fds,uint numeffecobjs,float time_per_frame)1201 static void compute_obstaclesemission(Scene *scene,
1202                                       FluidObjectBB *bb_maps,
1203                                       struct Depsgraph *depsgraph,
1204                                       float dt,
1205                                       Object **effecobjs,
1206                                       int frame,
1207                                       float frame_length,
1208                                       FluidDomainSettings *fds,
1209                                       uint numeffecobjs,
1210                                       float time_per_frame)
1211 {
1212   bool is_first_frame = (frame == fds->cache_frame_start);
1213 
1214   /* Prepare effector maps. */
1215   for (int effec_index = 0; effec_index < numeffecobjs; effec_index++) {
1216     Object *effecobj = effecobjs[effec_index];
1217     FluidModifierData *fmd2 = (FluidModifierData *)BKE_modifiers_findby_type(effecobj,
1218                                                                              eModifierType_Fluid);
1219 
1220     /* Sanity check. */
1221     if (!fmd2) {
1222       continue;
1223     }
1224 
1225     /* Check for initialized effector object. */
1226     if ((fmd2->type & MOD_FLUID_TYPE_EFFEC) && fmd2->effector) {
1227       FluidEffectorSettings *fes = fmd2->effector;
1228       int subframes = fes->subframes;
1229       FluidObjectBB *bb = &bb_maps[effec_index];
1230 
1231       /* Optimization: Skip this object under certain conditions. */
1232       if (escape_effectorobject(effecobj, fds, fes, frame)) {
1233         continue;
1234       }
1235 
1236       /* First frame cannot have any subframes because there is (obviously) no previous frame from
1237        * where subframes could come from. */
1238       if (is_first_frame) {
1239         subframes = 0;
1240       }
1241 
1242       /* More splitting because of emission subframe: If no subframes present, sample_size is 1. */
1243       float sample_size = 1.0f / (float)(subframes + 1);
1244       float subframe_dt = dt * sample_size;
1245 
1246       /* Emission loop. When not using subframes this will loop only once. */
1247       for (int subframe = 0; subframe <= subframes; subframe++) {
1248 
1249         /* Temporary emission map used when subframes are enabled, i.e. at least one subframe. */
1250         FluidObjectBB bb_temp = {NULL};
1251 
1252         /* Set scene time */
1253         /* Handle emission subframe */
1254         if ((subframe < subframes || time_per_frame + dt + FLT_EPSILON < frame_length) &&
1255             !is_first_frame) {
1256           scene->r.subframe = (time_per_frame + (subframe + 1.0f) * subframe_dt) / frame_length;
1257           scene->r.cfra = frame - 1;
1258         }
1259         else {
1260           scene->r.subframe = 0.0f;
1261           scene->r.cfra = frame;
1262         }
1263         /* Sanity check: subframe portion must be between 0 and 1. */
1264         CLAMP(scene->r.subframe, 0.0f, 1.0f);
1265 #  ifdef DEBUG_PRINT
1266         /* Debugging: Print subframe information. */
1267         printf(
1268             "effector: frame (is first: %d): %d // scene current frame: %d // scene current "
1269             "subframe: "
1270             "%f\n",
1271             is_first_frame,
1272             frame,
1273             scene->r.cfra,
1274             scene->r.subframe);
1275 #  endif
1276         /* Update frame time, this is considering current subframe fraction
1277          * BLI_mutex_lock() called in manta_step(), so safe to update subframe here
1278          * TODO(sebbas): Using BKE_scene_frame_get(scene) instead of new DEG_get_ctime(depsgraph)
1279          * as subframes don't work with the latter yet. */
1280         BKE_object_modifier_update_subframe(
1281             depsgraph, scene, effecobj, true, 5, BKE_scene_frame_get(scene), eModifierType_Fluid);
1282 
1283         if (subframes) {
1284           obstacles_from_mesh(effecobj, fds, fes, &bb_temp, subframe_dt);
1285         }
1286         else {
1287           obstacles_from_mesh(effecobj, fds, fes, bb, subframe_dt);
1288         }
1289 
1290         /* If this we emitted with temp emission map in this loop (subframe emission), we combine
1291          * the temp map with the original emission map. */
1292         if (subframes) {
1293           /* Combine emission maps. */
1294           bb_combineMaps(bb, &bb_temp, 0, 0.0f);
1295           bb_freeData(&bb_temp);
1296         }
1297       }
1298     }
1299   }
1300 }
1301 
update_obstacles(Depsgraph * depsgraph,Scene * scene,Object * ob,FluidDomainSettings * fds,float time_per_frame,float frame_length,int frame,float dt)1302 static void update_obstacles(Depsgraph *depsgraph,
1303                              Scene *scene,
1304                              Object *ob,
1305                              FluidDomainSettings *fds,
1306                              float time_per_frame,
1307                              float frame_length,
1308                              int frame,
1309                              float dt)
1310 {
1311   FluidObjectBB *bb_maps = NULL;
1312   Object **effecobjs = NULL;
1313   uint numeffecobjs = 0;
1314   bool is_resume = (fds->cache_frame_pause_data == frame);
1315   bool is_first_frame = (frame == fds->cache_frame_start);
1316 
1317   effecobjs = BKE_collision_objects_create(
1318       depsgraph, ob, fds->effector_group, &numeffecobjs, eModifierType_Fluid);
1319 
1320   /* Update all effector related flags and ensure that corresponding grids get initialized. */
1321   update_obstacleflags(fds, effecobjs, numeffecobjs);
1322   ensure_obstaclefields(fds);
1323 
1324   /* Allocate effector map for each effector object. */
1325   bb_maps = MEM_callocN(sizeof(struct FluidObjectBB) * numeffecobjs, "fluid_effector_bb_maps");
1326 
1327   /* Initialize effector map for each effector object. */
1328   compute_obstaclesemission(scene,
1329                             bb_maps,
1330                             depsgraph,
1331                             dt,
1332                             effecobjs,
1333                             frame,
1334                             frame_length,
1335                             fds,
1336                             numeffecobjs,
1337                             time_per_frame);
1338 
1339   float *vel_x = manta_get_ob_velocity_x(fds->fluid);
1340   float *vel_y = manta_get_ob_velocity_y(fds->fluid);
1341   float *vel_z = manta_get_ob_velocity_z(fds->fluid);
1342   float *vel_x_guide = manta_get_guide_velocity_x(fds->fluid);
1343   float *vel_y_guide = manta_get_guide_velocity_y(fds->fluid);
1344   float *vel_z_guide = manta_get_guide_velocity_z(fds->fluid);
1345   float *phi_obs_in = manta_get_phiobs_in(fds->fluid);
1346   float *phi_obsstatic_in = manta_get_phiobsstatic_in(fds->fluid);
1347   float *phi_guide_in = manta_get_phiguide_in(fds->fluid);
1348   float *num_obstacles = manta_get_num_obstacle(fds->fluid);
1349   float *num_guides = manta_get_num_guide(fds->fluid);
1350   uint z;
1351 
1352   bool use_adaptivedomain = (fds->flags & FLUID_DOMAIN_USE_ADAPTIVE_DOMAIN);
1353 
1354   /* Grid reset before writing again. */
1355   for (z = 0; z < fds->res[0] * fds->res[1] * fds->res[2]; z++) {
1356 
1357     /* Use big value that's not inf to initialize levelset grids. */
1358     if (phi_obs_in) {
1359       phi_obs_in[z] = PHI_MAX;
1360     }
1361     /* Only reset static effectors on first frame. Only use static effectors without adaptive
1362      * domains. */
1363     if (phi_obsstatic_in && (is_first_frame || use_adaptivedomain)) {
1364       phi_obsstatic_in[z] = PHI_MAX;
1365     }
1366     if (phi_guide_in) {
1367       phi_guide_in[z] = PHI_MAX;
1368     }
1369     if (num_obstacles) {
1370       num_obstacles[z] = 0;
1371     }
1372     if (num_guides) {
1373       num_guides[z] = 0;
1374     }
1375     if (vel_x && vel_y && vel_z) {
1376       vel_x[z] = 0.0f;
1377       vel_y[z] = 0.0f;
1378       vel_z[z] = 0.0f;
1379     }
1380     if (vel_x_guide && vel_y_guide && vel_z_guide) {
1381       vel_x_guide[z] = 0.0f;
1382       vel_y_guide[z] = 0.0f;
1383       vel_z_guide[z] = 0.0f;
1384     }
1385   }
1386 
1387   /* Prepare grids from effector objects. */
1388   for (int effec_index = 0; effec_index < numeffecobjs; effec_index++) {
1389     Object *effecobj = effecobjs[effec_index];
1390     FluidModifierData *fmd2 = (FluidModifierData *)BKE_modifiers_findby_type(effecobj,
1391                                                                              eModifierType_Fluid);
1392 
1393     /* Sanity check. */
1394     if (!fmd2) {
1395       continue;
1396     }
1397 
1398     /* Cannot use static mode with adaptive domain.
1399      * The adaptive domain might expand and only later in the simulations discover the static
1400      * object. */
1401     bool is_static = is_static_object(effecobj) && !use_adaptivedomain;
1402 
1403     /* Check for initialized effector object. */
1404     if ((fmd2->type & MOD_FLUID_TYPE_EFFEC) && fmd2->effector) {
1405       FluidEffectorSettings *fes = fmd2->effector;
1406 
1407       /* Optimization: Skip effector objects with disabled effec flag. */
1408       if ((fes->flags & FLUID_EFFECTOR_USE_EFFEC) == 0) {
1409         continue;
1410       }
1411 
1412       FluidObjectBB *bb = &bb_maps[effec_index];
1413       float *velocity_map = bb->velocity;
1414       float *numobjs_map = bb->numobjs;
1415       float *distance_map = bb->distances;
1416 
1417       int gx, gy, gz, ex, ey, ez, dx, dy, dz;
1418       size_t e_index, d_index;
1419 
1420       /* Loop through every emission map cell. */
1421       for (gx = bb->min[0]; gx < bb->max[0]; gx++) {
1422         for (gy = bb->min[1]; gy < bb->max[1]; gy++) {
1423           for (gz = bb->min[2]; gz < bb->max[2]; gz++) {
1424             /* Compute emission map index. */
1425             ex = gx - bb->min[0];
1426             ey = gy - bb->min[1];
1427             ez = gz - bb->min[2];
1428             e_index = manta_get_index(ex, bb->res[0], ey, bb->res[1], ez);
1429 
1430             /* Get domain index. */
1431             dx = gx - fds->res_min[0];
1432             dy = gy - fds->res_min[1];
1433             dz = gz - fds->res_min[2];
1434             d_index = manta_get_index(dx, fds->res[0], dy, fds->res[1], dz);
1435             /* Make sure emission cell is inside the new domain boundary. */
1436             if (dx < 0 || dy < 0 || dz < 0 || dx >= fds->res[0] || dy >= fds->res[1] ||
1437                 dz >= fds->res[2]) {
1438               continue;
1439             }
1440 
1441             if (fes->type == FLUID_EFFECTOR_TYPE_COLLISION) {
1442               float *levelset = ((is_first_frame || is_resume) && is_static) ? phi_obsstatic_in :
1443                                                                                phi_obs_in;
1444               apply_effector_fields(fes,
1445                                     d_index,
1446                                     distance_map[e_index],
1447                                     levelset,
1448                                     numobjs_map[e_index],
1449                                     num_obstacles,
1450                                     &velocity_map[e_index * 3],
1451                                     vel_x,
1452                                     vel_y,
1453                                     vel_z);
1454             }
1455             if (fes->type == FLUID_EFFECTOR_TYPE_GUIDE) {
1456               apply_effector_fields(fes,
1457                                     d_index,
1458                                     distance_map[e_index],
1459                                     phi_guide_in,
1460                                     numobjs_map[e_index],
1461                                     num_guides,
1462                                     &velocity_map[e_index * 3],
1463                                     vel_x_guide,
1464                                     vel_y_guide,
1465                                     vel_z_guide);
1466             }
1467           }
1468         }
1469       } /* End of effector map loop. */
1470       bb_freeData(bb);
1471     } /* End of effector object loop. */
1472   }
1473 
1474   BKE_collision_objects_free(effecobjs);
1475   if (bb_maps) {
1476     MEM_freeN(bb_maps);
1477   }
1478 }
1479 
1480 /** \} */
1481 
1482 /* -------------------------------------------------------------------- */
1483 /** \name Flow
1484  * \{ */
1485 
1486 typedef struct EmitFromParticlesData {
1487   FluidFlowSettings *ffs;
1488   KDTree_3d *tree;
1489 
1490   FluidObjectBB *bb;
1491   float *particle_vel;
1492   int *min, *max, *res;
1493 
1494   float solid;
1495   float smooth;
1496 } EmitFromParticlesData;
1497 
emit_from_particles_task_cb(void * __restrict userdata,const int z,const TaskParallelTLS * __restrict UNUSED (tls))1498 static void emit_from_particles_task_cb(void *__restrict userdata,
1499                                         const int z,
1500                                         const TaskParallelTLS *__restrict UNUSED(tls))
1501 {
1502   EmitFromParticlesData *data = userdata;
1503   FluidFlowSettings *ffs = data->ffs;
1504   FluidObjectBB *bb = data->bb;
1505 
1506   for (int x = data->min[0]; x < data->max[0]; x++) {
1507     for (int y = data->min[1]; y < data->max[1]; y++) {
1508       const int index = manta_get_index(
1509           x - bb->min[0], bb->res[0], y - bb->min[1], bb->res[1], z - bb->min[2]);
1510       const float ray_start[3] = {((float)x) + 0.5f, ((float)y) + 0.5f, ((float)z) + 0.5f};
1511 
1512       /* Find particle distance from the kdtree. */
1513       KDTreeNearest_3d nearest;
1514       const float range = data->solid + data->smooth;
1515       BLI_kdtree_3d_find_nearest(data->tree, ray_start, &nearest);
1516 
1517       if (nearest.dist < range) {
1518         bb->influence[index] = (nearest.dist < data->solid) ?
1519                                    1.0f :
1520                                    (1.0f - (nearest.dist - data->solid) / data->smooth);
1521         /* Uses particle velocity as initial velocity for smoke. */
1522         if (ffs->flags & FLUID_FLOW_INITVELOCITY && (ffs->psys->part->phystype != PART_PHYS_NO)) {
1523           madd_v3_v3fl(
1524               &bb->velocity[index * 3], &data->particle_vel[nearest.index * 3], ffs->vel_multi);
1525         }
1526       }
1527     }
1528   }
1529 }
1530 
emit_from_particles(Object * flow_ob,FluidDomainSettings * fds,FluidFlowSettings * ffs,FluidObjectBB * bb,Depsgraph * depsgraph,Scene * scene,float dt)1531 static void emit_from_particles(Object *flow_ob,
1532                                 FluidDomainSettings *fds,
1533                                 FluidFlowSettings *ffs,
1534                                 FluidObjectBB *bb,
1535                                 Depsgraph *depsgraph,
1536                                 Scene *scene,
1537                                 float dt)
1538 {
1539   if (ffs && ffs->psys && ffs->psys->part &&
1540       ELEM(ffs->psys->part->type, PART_EMITTER, PART_FLUID))  // is particle system selected
1541   {
1542     ParticleSimulationData sim;
1543     ParticleSystem *psys = ffs->psys;
1544     float *particle_pos;
1545     float *particle_vel;
1546     int totpart = psys->totpart, totchild;
1547     int p = 0;
1548     int valid_particles = 0;
1549     int bounds_margin = 1;
1550 
1551     /* radius based flow */
1552     const float solid = ffs->particle_size * 0.5f;
1553     const float smooth = 0.5f; /* add 0.5 cells of linear falloff to reduce aliasing */
1554     KDTree_3d *tree = NULL;
1555 
1556     sim.depsgraph = depsgraph;
1557     sim.scene = scene;
1558     sim.ob = flow_ob;
1559     sim.psys = psys;
1560     sim.psys->lattice_deform_data = psys_create_lattice_deform_data(&sim);
1561 
1562     /* prepare curvemapping tables */
1563     if ((psys->part->child_flag & PART_CHILD_USE_CLUMP_CURVE) && psys->part->clumpcurve) {
1564       BKE_curvemapping_changed_all(psys->part->clumpcurve);
1565     }
1566     if ((psys->part->child_flag & PART_CHILD_USE_ROUGH_CURVE) && psys->part->roughcurve) {
1567       BKE_curvemapping_changed_all(psys->part->roughcurve);
1568     }
1569     if ((psys->part->child_flag & PART_CHILD_USE_TWIST_CURVE) && psys->part->twistcurve) {
1570       BKE_curvemapping_changed_all(psys->part->twistcurve);
1571     }
1572 
1573     /* initialize particle cache */
1574     if (psys->part->type == PART_HAIR) {
1575       // TODO: PART_HAIR not supported whatsoever
1576       totchild = 0;
1577     }
1578     else {
1579       totchild = psys->totchild * psys->part->disp / 100;
1580     }
1581 
1582     particle_pos = MEM_callocN(sizeof(float[3]) * (totpart + totchild),
1583                                "manta_flow_particles_pos");
1584     particle_vel = MEM_callocN(sizeof(float[3]) * (totpart + totchild),
1585                                "manta_flow_particles_vel");
1586 
1587     /* setup particle radius emission if enabled */
1588     if (ffs->flags & FLUID_FLOW_USE_PART_SIZE) {
1589       tree = BLI_kdtree_3d_new(psys->totpart + psys->totchild);
1590       bounds_margin = (int)ceil(solid + smooth);
1591     }
1592 
1593     /* calculate local position for each particle */
1594     for (p = 0; p < totpart + totchild; p++) {
1595       ParticleKey state;
1596       float *pos, *vel;
1597       if (p < totpart) {
1598         if (psys->particles[p].flag & (PARS_NO_DISP | PARS_UNEXIST)) {
1599           continue;
1600         }
1601       }
1602       else {
1603         /* handle child particle */
1604         ChildParticle *cpa = &psys->child[p - totpart];
1605         if (psys->particles[cpa->parent].flag & (PARS_NO_DISP | PARS_UNEXIST)) {
1606           continue;
1607         }
1608       }
1609 
1610       state.time = BKE_scene_frame_get(
1611           scene); /* DEG_get_ctime(depsgraph) does not give subframe time */
1612       if (psys_get_particle_state(&sim, p, &state, 0) == 0) {
1613         continue;
1614       }
1615 
1616       /* location */
1617       pos = &particle_pos[valid_particles * 3];
1618       copy_v3_v3(pos, state.co);
1619       manta_pos_to_cell(fds, pos);
1620 
1621       /* velocity */
1622       vel = &particle_vel[valid_particles * 3];
1623       copy_v3_v3(vel, state.vel);
1624       mul_mat3_m4_v3(fds->imat, &particle_vel[valid_particles * 3]);
1625 
1626       if (ffs->flags & FLUID_FLOW_USE_PART_SIZE) {
1627         BLI_kdtree_3d_insert(tree, valid_particles, pos);
1628       }
1629 
1630       /* calculate emission map bounds */
1631       bb_boundInsert(bb, pos);
1632       valid_particles++;
1633     }
1634 
1635     /* set emission map */
1636     clamp_bounds_in_domain(fds, bb->min, bb->max, NULL, NULL, bounds_margin, dt);
1637     bb_allocateData(bb, ffs->flags & FLUID_FLOW_INITVELOCITY, true);
1638 
1639     if (!(ffs->flags & FLUID_FLOW_USE_PART_SIZE)) {
1640       for (p = 0; p < valid_particles; p++) {
1641         int cell[3];
1642         size_t i = 0;
1643         size_t index = 0;
1644         int badcell = 0;
1645 
1646         /* 1. get corresponding cell */
1647         cell[0] = floor(particle_pos[p * 3]) - bb->min[0];
1648         cell[1] = floor(particle_pos[p * 3 + 1]) - bb->min[1];
1649         cell[2] = floor(particle_pos[p * 3 + 2]) - bb->min[2];
1650         /* check if cell is valid (in the domain boundary) */
1651         for (i = 0; i < 3; i++) {
1652           if ((cell[i] > bb->res[i] - 1) || (cell[i] < 0)) {
1653             badcell = 1;
1654             break;
1655           }
1656         }
1657         if (badcell) {
1658           continue;
1659         }
1660         /* get cell index */
1661         index = manta_get_index(cell[0], bb->res[0], cell[1], bb->res[1], cell[2]);
1662         /* Add influence to emission map */
1663         bb->influence[index] = 1.0f;
1664         /* Uses particle velocity as initial velocity for smoke */
1665         if (ffs->flags & FLUID_FLOW_INITVELOCITY && (psys->part->phystype != PART_PHYS_NO)) {
1666           madd_v3_v3fl(&bb->velocity[index * 3], &particle_vel[p * 3], ffs->vel_multi);
1667         }
1668       }  // particles loop
1669     }
1670     else if (valid_particles > 0) {  // FLUID_FLOW_USE_PART_SIZE
1671       int min[3], max[3], res[3];
1672 
1673       /* setup loop bounds */
1674       for (int i = 0; i < 3; i++) {
1675         min[i] = bb->min[i];
1676         max[i] = bb->max[i];
1677         res[i] = bb->res[i];
1678       }
1679 
1680       BLI_kdtree_3d_balance(tree);
1681 
1682       EmitFromParticlesData data = {
1683           .ffs = ffs,
1684           .tree = tree,
1685           .bb = bb,
1686           .particle_vel = particle_vel,
1687           .min = min,
1688           .max = max,
1689           .res = res,
1690           .solid = solid,
1691           .smooth = smooth,
1692       };
1693 
1694       TaskParallelSettings settings;
1695       BLI_parallel_range_settings_defaults(&settings);
1696       settings.min_iter_per_thread = 2;
1697       BLI_task_parallel_range(min[2], max[2], &data, emit_from_particles_task_cb, &settings);
1698     }
1699 
1700     if (ffs->flags & FLUID_FLOW_USE_PART_SIZE) {
1701       BLI_kdtree_3d_free(tree);
1702     }
1703 
1704     /* free data */
1705     if (particle_pos) {
1706       MEM_freeN(particle_pos);
1707     }
1708     if (particle_vel) {
1709       MEM_freeN(particle_vel);
1710     }
1711   }
1712 }
1713 
1714 /* Calculate map of (minimum) distances to flow/obstacle surface. Distances outside mesh are
1715  * positive, inside negative. */
update_distances(int index,float * distance_map,BVHTreeFromMesh * tree_data,const float ray_start[3],float surface_thickness,bool use_plane_init)1716 static void update_distances(int index,
1717                              float *distance_map,
1718                              BVHTreeFromMesh *tree_data,
1719                              const float ray_start[3],
1720                              float surface_thickness,
1721                              bool use_plane_init)
1722 {
1723   float min_dist = PHI_MAX;
1724 
1725   /* Planar initialization: Find nearest cells around mesh. */
1726   if (use_plane_init) {
1727     BVHTreeNearest nearest = {0};
1728     nearest.index = -1;
1729     /* Distance between two opposing vertices in a unit cube.
1730      * I.e. the unit cube diagonal or sqrt(3).
1731      * This value is our nearest neighbor search distance. */
1732     const float surface_distance = 1.732;
1733     nearest.dist_sq = surface_distance *
1734                       surface_distance; /* find_nearest uses squared distance. */
1735 
1736     /* Subtract optional surface thickness value and virtually increase the object size. */
1737     if (surface_thickness) {
1738       nearest.dist_sq += surface_thickness;
1739     }
1740 
1741     if (BLI_bvhtree_find_nearest(
1742             tree_data->tree, ray_start, &nearest, tree_data->nearest_callback, tree_data) != -1) {
1743       float ray[3] = {0};
1744       sub_v3_v3v3(ray, ray_start, nearest.co);
1745       min_dist = len_v3(ray);
1746       min_dist = (-1.0f) * fabsf(min_dist);
1747     }
1748   }
1749   /* Volumetric initialization: Ray-casts around mesh object. */
1750   else {
1751     /* Ray-casts in 26 directions.
1752      * (6 main axis + 12 quadrant diagonals (2D) + 8 octant diagonals (3D)). */
1753     float ray_dirs[26][3] = {
1754         {1.0f, 0.0f, 0.0f},   {0.0f, 1.0f, 0.0f},   {0.0f, 0.0f, 1.0f},  {-1.0f, 0.0f, 0.0f},
1755         {0.0f, -1.0f, 0.0f},  {0.0f, 0.0f, -1.0f},  {1.0f, 1.0f, 0.0f},  {1.0f, -1.0f, 0.0f},
1756         {-1.0f, 1.0f, 0.0f},  {-1.0f, -1.0f, 0.0f}, {1.0f, 0.0f, 1.0f},  {1.0f, 0.0f, -1.0f},
1757         {-1.0f, 0.0f, 1.0f},  {-1.0f, 0.0f, -1.0f}, {0.0f, 1.0f, 1.0f},  {0.0f, 1.0f, -1.0f},
1758         {0.0f, -1.0f, 1.0f},  {0.0f, -1.0f, -1.0f}, {1.0f, 1.0f, 1.0f},  {1.0f, -1.0f, 1.0f},
1759         {-1.0f, 1.0f, 1.0f},  {-1.0f, -1.0f, 1.0f}, {1.0f, 1.0f, -1.0f}, {1.0f, -1.0f, -1.0f},
1760         {-1.0f, 1.0f, -1.0f}, {-1.0f, -1.0f, -1.0f}};
1761 
1762     /* Count ray mesh misses (i.e. no face hit) and cases where the ray direction matches the face
1763      * normal direction. From this information it can be derived whether a cell is inside or
1764      * outside the mesh. */
1765     int miss_cnt = 0, dir_cnt = 0;
1766 
1767     for (int i = 0; i < ARRAY_SIZE(ray_dirs); i++) {
1768       BVHTreeRayHit hit_tree = {0};
1769       hit_tree.index = -1;
1770       hit_tree.dist = PHI_MAX;
1771 
1772       normalize_v3(ray_dirs[i]);
1773       BLI_bvhtree_ray_cast(tree_data->tree,
1774                            ray_start,
1775                            ray_dirs[i],
1776                            0.0f,
1777                            &hit_tree,
1778                            tree_data->raycast_callback,
1779                            tree_data);
1780 
1781       /* Ray did not hit mesh.
1782        * Current point definitely not inside mesh. Inside mesh as all rays have to hit. */
1783       if (hit_tree.index == -1) {
1784         miss_cnt++;
1785         /* Skip this ray since nothing was hit. */
1786         continue;
1787       }
1788 
1789       /* Ray and normal are pointing in opposite directions. */
1790       if (dot_v3v3(ray_dirs[i], hit_tree.no) <= 0) {
1791         dir_cnt++;
1792       }
1793 
1794       if (hit_tree.dist < min_dist) {
1795         min_dist = hit_tree.dist;
1796       }
1797     }
1798 
1799     /* Point lies inside mesh. Use negative sign for distance value.
1800      * This "if statement" has 2 conditions that can be true for points outside mesh. */
1801     if (!(miss_cnt > 0 || dir_cnt == ARRAY_SIZE(ray_dirs))) {
1802       min_dist = (-1.0f) * fabsf(min_dist);
1803     }
1804 
1805     /* Subtract optional surface thickness value and virtually increase the object size. */
1806     if (surface_thickness) {
1807       min_dist -= surface_thickness;
1808     }
1809   }
1810 
1811   /* Update global distance array but ensure that older entries are not overridden. */
1812   distance_map[index] = MIN2(distance_map[index], min_dist);
1813 
1814   /* Sanity check: Ensure that distances don't explode. */
1815   CLAMP(distance_map[index], -PHI_MAX, PHI_MAX);
1816 }
1817 
sample_mesh(FluidFlowSettings * ffs,const MVert * mvert,const MLoop * mloop,const MLoopTri * mlooptri,const MLoopUV * mloopuv,float * influence_map,float * velocity_map,int index,const int base_res[3],const float global_size[3],const float flow_center[3],BVHTreeFromMesh * tree_data,const float ray_start[3],const float * vert_vel,bool has_velocity,int defgrp_index,MDeformVert * dvert,float x,float y,float z)1818 static void sample_mesh(FluidFlowSettings *ffs,
1819                         const MVert *mvert,
1820                         const MLoop *mloop,
1821                         const MLoopTri *mlooptri,
1822                         const MLoopUV *mloopuv,
1823                         float *influence_map,
1824                         float *velocity_map,
1825                         int index,
1826                         const int base_res[3],
1827                         const float global_size[3],
1828                         const float flow_center[3],
1829                         BVHTreeFromMesh *tree_data,
1830                         const float ray_start[3],
1831                         const float *vert_vel,
1832                         bool has_velocity,
1833                         int defgrp_index,
1834                         MDeformVert *dvert,
1835                         float x,
1836                         float y,
1837                         float z)
1838 {
1839   float ray_dir[3] = {1.0f, 0.0f, 0.0f};
1840   BVHTreeRayHit hit = {0};
1841   BVHTreeNearest nearest = {0};
1842 
1843   float volume_factor = 0.0f;
1844 
1845   hit.index = -1;
1846   hit.dist = PHI_MAX;
1847   nearest.index = -1;
1848 
1849   /* Distance between two opposing vertices in a unit cube.
1850    * I.e. the unit cube diagonal or sqrt(3).
1851    * This value is our nearest neighbor search distance. */
1852   const float surface_distance = 1.732;
1853   nearest.dist_sq = surface_distance * surface_distance; /* find_nearest uses squared distance. */
1854 
1855   bool is_gas_flow = (ffs->type == FLUID_FLOW_TYPE_SMOKE || ffs->type == FLUID_FLOW_TYPE_FIRE ||
1856                       ffs->type == FLUID_FLOW_TYPE_SMOKEFIRE);
1857 
1858   /* Emission strength for gases will be computed below.
1859    * For liquids it's not needed. Just set to non zero value
1860    * to allow initial velocity computation. */
1861   float emission_strength = (is_gas_flow) ? 0.0f : 1.0f;
1862 
1863   /* Emission inside the flow object. */
1864   if (is_gas_flow && ffs->volume_density) {
1865     if (BLI_bvhtree_ray_cast(tree_data->tree,
1866                              ray_start,
1867                              ray_dir,
1868                              0.0f,
1869                              &hit,
1870                              tree_data->raycast_callback,
1871                              tree_data) != -1) {
1872       float dot = ray_dir[0] * hit.no[0] + ray_dir[1] * hit.no[1] + ray_dir[2] * hit.no[2];
1873       /* If ray and hit face normal are facing same direction hit point is inside a closed mesh. */
1874       if (dot >= 0) {
1875         /* Also cast a ray in opposite direction to make sure point is at least surrounded by two
1876          * faces. */
1877         negate_v3(ray_dir);
1878         hit.index = -1;
1879         hit.dist = PHI_MAX;
1880 
1881         BLI_bvhtree_ray_cast(tree_data->tree,
1882                              ray_start,
1883                              ray_dir,
1884                              0.0f,
1885                              &hit,
1886                              tree_data->raycast_callback,
1887                              tree_data);
1888         if (hit.index != -1) {
1889           volume_factor = ffs->volume_density;
1890         }
1891       }
1892     }
1893   }
1894 
1895   /* Find the nearest point on the mesh. */
1896   if (BLI_bvhtree_find_nearest(
1897           tree_data->tree, ray_start, &nearest, tree_data->nearest_callback, tree_data) != -1) {
1898     float weights[3];
1899     int v1, v2, v3, f_index = nearest.index;
1900     float n1[3], n2[3], n3[3], hit_normal[3];
1901 
1902     /* Calculate barycentric weights for nearest point. */
1903     v1 = mloop[mlooptri[f_index].tri[0]].v;
1904     v2 = mloop[mlooptri[f_index].tri[1]].v;
1905     v3 = mloop[mlooptri[f_index].tri[2]].v;
1906     interp_weights_tri_v3(weights, mvert[v1].co, mvert[v2].co, mvert[v3].co, nearest.co);
1907 
1908     /* Compute emission strength for smoke flow. */
1909     if (is_gas_flow) {
1910       /* Emission from surface is based on UI configurable distance value. */
1911       if (ffs->surface_distance) {
1912         emission_strength = sqrtf(nearest.dist_sq) / ffs->surface_distance;
1913         CLAMP(emission_strength, 0.0f, 1.0f);
1914         emission_strength = pow(1.0f - emission_strength, 0.5f);
1915       }
1916       else {
1917         emission_strength = 0.0f;
1918       }
1919 
1920       /* Apply vertex group influence if it is being used. */
1921       if (defgrp_index != -1 && dvert) {
1922         float weight_mask = BKE_defvert_find_weight(&dvert[v1], defgrp_index) * weights[0] +
1923                             BKE_defvert_find_weight(&dvert[v2], defgrp_index) * weights[1] +
1924                             BKE_defvert_find_weight(&dvert[v3], defgrp_index) * weights[2];
1925         emission_strength *= weight_mask;
1926       }
1927 
1928       /* Apply emission texture. */
1929       if ((ffs->flags & FLUID_FLOW_TEXTUREEMIT) && ffs->noise_texture) {
1930         float tex_co[3] = {0};
1931         TexResult texres;
1932 
1933         if (ffs->texture_type == FLUID_FLOW_TEXTURE_MAP_AUTO) {
1934           tex_co[0] = ((x - flow_center[0]) / base_res[0]) / ffs->texture_size;
1935           tex_co[1] = ((y - flow_center[1]) / base_res[1]) / ffs->texture_size;
1936           tex_co[2] = ((z - flow_center[2]) / base_res[2] - ffs->texture_offset) /
1937                       ffs->texture_size;
1938         }
1939         else if (mloopuv) {
1940           const float *uv[3];
1941           uv[0] = mloopuv[mlooptri[f_index].tri[0]].uv;
1942           uv[1] = mloopuv[mlooptri[f_index].tri[1]].uv;
1943           uv[2] = mloopuv[mlooptri[f_index].tri[2]].uv;
1944 
1945           interp_v2_v2v2v2(tex_co, UNPACK3(uv), weights);
1946 
1947           /* Map texure coord between -1.0f and 1.0f. */
1948           tex_co[0] = tex_co[0] * 2.0f - 1.0f;
1949           tex_co[1] = tex_co[1] * 2.0f - 1.0f;
1950           tex_co[2] = ffs->texture_offset;
1951         }
1952         texres.nor = NULL;
1953         BKE_texture_get_value(NULL, ffs->noise_texture, tex_co, &texres, false);
1954         emission_strength *= texres.tin;
1955       }
1956     }
1957 
1958     /* Initial velocity of flow object. Only compute velocity if emission is present. */
1959     if (ffs->flags & FLUID_FLOW_INITVELOCITY && velocity_map && emission_strength != 0.0) {
1960       /* Apply normal directional velocity. */
1961       if (ffs->vel_normal) {
1962         /* Interpolate vertex normal vectors to get nearest point normal. */
1963         normal_short_to_float_v3(n1, mvert[v1].no);
1964         normal_short_to_float_v3(n2, mvert[v2].no);
1965         normal_short_to_float_v3(n3, mvert[v3].no);
1966         interp_v3_v3v3v3(hit_normal, n1, n2, n3, weights);
1967         normalize_v3(hit_normal);
1968 
1969         /* Apply normal directional velocity. */
1970         velocity_map[index * 3] += hit_normal[0] * ffs->vel_normal;
1971         velocity_map[index * 3 + 1] += hit_normal[1] * ffs->vel_normal;
1972         velocity_map[index * 3 + 2] += hit_normal[2] * ffs->vel_normal;
1973       }
1974       /* Apply object velocity. */
1975       if (has_velocity && ffs->vel_multi) {
1976         float hit_vel[3];
1977         interp_v3_v3v3v3(
1978             hit_vel, &vert_vel[v1 * 3], &vert_vel[v2 * 3], &vert_vel[v3 * 3], weights);
1979         velocity_map[index * 3] += hit_vel[0] * ffs->vel_multi;
1980         velocity_map[index * 3 + 1] += hit_vel[1] * ffs->vel_multi;
1981         velocity_map[index * 3 + 2] += hit_vel[2] * ffs->vel_multi;
1982 #  ifdef DEBUG_PRINT
1983         /* Debugging: Print flow object velocities. */
1984         printf("adding flow object vel: [%f, %f, %f]\n", hit_vel[0], hit_vel[1], hit_vel[2]);
1985 #  endif
1986       }
1987       /* Convert xyz velocities flow settings from world to grid space. */
1988       float convert_vel[3];
1989       copy_v3_v3(convert_vel, ffs->vel_coord);
1990       float time_mult = 1.0 / (25.f * DT_DEFAULT);
1991       float size_mult = MAX3(base_res[0], base_res[1], base_res[2]) /
1992                         MAX3(global_size[0], global_size[1], global_size[2]);
1993       mul_v3_v3fl(convert_vel, ffs->vel_coord, size_mult * time_mult);
1994 
1995       velocity_map[index * 3] += convert_vel[0];
1996       velocity_map[index * 3 + 1] += convert_vel[1];
1997       velocity_map[index * 3 + 2] += convert_vel[2];
1998 #  ifdef DEBUG_PRINT
1999       printf("initial vel: [%f, %f, %f]\n",
2000              velocity_map[index * 3],
2001              velocity_map[index * 3 + 1],
2002              velocity_map[index * 3 + 2]);
2003 #  endif
2004     }
2005   }
2006 
2007   /* Apply final influence value but also consider volume initialization factor. */
2008   influence_map[index] = MAX2(volume_factor, emission_strength);
2009 }
2010 
2011 typedef struct EmitFromDMData {
2012   FluidDomainSettings *fds;
2013   FluidFlowSettings *ffs;
2014 
2015   const MVert *mvert;
2016   const MLoop *mloop;
2017   const MLoopTri *mlooptri;
2018   const MLoopUV *mloopuv;
2019   MDeformVert *dvert;
2020   int defgrp_index;
2021 
2022   BVHTreeFromMesh *tree;
2023   FluidObjectBB *bb;
2024 
2025   bool has_velocity;
2026   float *vert_vel;
2027   float *flow_center;
2028   int *min, *max, *res;
2029 } EmitFromDMData;
2030 
emit_from_mesh_task_cb(void * __restrict userdata,const int z,const TaskParallelTLS * __restrict UNUSED (tls))2031 static void emit_from_mesh_task_cb(void *__restrict userdata,
2032                                    const int z,
2033                                    const TaskParallelTLS *__restrict UNUSED(tls))
2034 {
2035   EmitFromDMData *data = userdata;
2036   FluidObjectBB *bb = data->bb;
2037 
2038   for (int x = data->min[0]; x < data->max[0]; x++) {
2039     for (int y = data->min[1]; y < data->max[1]; y++) {
2040       const int index = manta_get_index(
2041           x - bb->min[0], bb->res[0], y - bb->min[1], bb->res[1], z - bb->min[2]);
2042       const float ray_start[3] = {((float)x) + 0.5f, ((float)y) + 0.5f, ((float)z) + 0.5f};
2043 
2044       /* Compute emission only for flow objects that produce fluid (i.e. skip outflow objects).
2045        * Result in bb->influence. Also computes initial velocities. Result in bb->velocity. */
2046       if ((data->ffs->behavior == FLUID_FLOW_BEHAVIOR_GEOMETRY) ||
2047           (data->ffs->behavior == FLUID_FLOW_BEHAVIOR_INFLOW)) {
2048         sample_mesh(data->ffs,
2049                     data->mvert,
2050                     data->mloop,
2051                     data->mlooptri,
2052                     data->mloopuv,
2053                     bb->influence,
2054                     bb->velocity,
2055                     index,
2056                     data->fds->base_res,
2057                     data->fds->global_size,
2058                     data->flow_center,
2059                     data->tree,
2060                     ray_start,
2061                     data->vert_vel,
2062                     data->has_velocity,
2063                     data->defgrp_index,
2064                     data->dvert,
2065                     (float)x,
2066                     (float)y,
2067                     (float)z);
2068       }
2069 
2070       /* Calculate levelset values from meshes. Result in bb->distances. */
2071       update_distances(index,
2072                        bb->distances,
2073                        data->tree,
2074                        ray_start,
2075                        data->ffs->surface_distance,
2076                        data->ffs->flags & FLUID_FLOW_USE_PLANE_INIT);
2077     }
2078   }
2079 }
2080 
emit_from_mesh(Object * flow_ob,FluidDomainSettings * fds,FluidFlowSettings * ffs,FluidObjectBB * bb,float dt)2081 static void emit_from_mesh(
2082     Object *flow_ob, FluidDomainSettings *fds, FluidFlowSettings *ffs, FluidObjectBB *bb, float dt)
2083 {
2084   if (ffs->mesh) {
2085     Mesh *me = NULL;
2086     MVert *mvert = NULL;
2087     const MLoopTri *mlooptri = NULL;
2088     const MLoop *mloop = NULL;
2089     const MLoopUV *mloopuv = NULL;
2090     MDeformVert *dvert = NULL;
2091     BVHTreeFromMesh tree_data = {NULL};
2092     int numverts, i;
2093 
2094     float *vert_vel = NULL;
2095     bool has_velocity = false;
2096 
2097     int defgrp_index = ffs->vgroup_density - 1;
2098     float flow_center[3] = {0};
2099     int min[3], max[3], res[3];
2100 
2101     /* Copy mesh for thread safety as we modify it.
2102      * Main issue is its VertArray being modified, then replaced and freed. */
2103     me = BKE_mesh_copy_for_eval(ffs->mesh, true);
2104 
2105     /* Duplicate vertices to modify. */
2106     if (me->mvert) {
2107       me->mvert = MEM_dupallocN(me->mvert);
2108       CustomData_set_layer(&me->vdata, CD_MVERT, me->mvert);
2109     }
2110 
2111     BKE_mesh_ensure_normals(me);
2112     mvert = me->mvert;
2113     mloop = me->mloop;
2114     mlooptri = BKE_mesh_runtime_looptri_ensure(me);
2115     numverts = me->totvert;
2116     dvert = CustomData_get_layer(&me->vdata, CD_MDEFORMVERT);
2117     mloopuv = CustomData_get_layer_named(&me->ldata, CD_MLOOPUV, ffs->uvlayer_name);
2118 
2119     if (ffs->flags & FLUID_FLOW_INITVELOCITY) {
2120       vert_vel = MEM_callocN(sizeof(float[3]) * numverts, "manta_flow_velocity");
2121 
2122       if (ffs->numverts != numverts || !ffs->verts_old) {
2123         if (ffs->verts_old) {
2124           MEM_freeN(ffs->verts_old);
2125         }
2126         ffs->verts_old = MEM_callocN(sizeof(float[3]) * numverts, "manta_flow_verts_old");
2127         ffs->numverts = numverts;
2128       }
2129       else {
2130         has_velocity = true;
2131       }
2132     }
2133 
2134     /* Transform mesh vertices to domain grid space for fast lookups */
2135     for (i = 0; i < numverts; i++) {
2136       float n[3];
2137 
2138       /* Vertex position. */
2139       mul_m4_v3(flow_ob->obmat, mvert[i].co);
2140       manta_pos_to_cell(fds, mvert[i].co);
2141 
2142       /* Vertex normal. */
2143       normal_short_to_float_v3(n, mvert[i].no);
2144       mul_mat3_m4_v3(flow_ob->obmat, n);
2145       mul_mat3_m4_v3(fds->imat, n);
2146       normalize_v3(n);
2147       normal_float_to_short_v3(mvert[i].no, n);
2148 
2149       /* Vertex velocity. */
2150       if (ffs->flags & FLUID_FLOW_INITVELOCITY) {
2151         float co[3];
2152         add_v3fl_v3fl_v3i(co, mvert[i].co, fds->shift);
2153         if (has_velocity) {
2154           sub_v3_v3v3(&vert_vel[i * 3], co, &ffs->verts_old[i * 3]);
2155           mul_v3_fl(&vert_vel[i * 3], 1.0 / dt);
2156         }
2157         copy_v3_v3(&ffs->verts_old[i * 3], co);
2158       }
2159 
2160       /* Calculate emission map bounds. */
2161       bb_boundInsert(bb, mvert[i].co);
2162     }
2163     mul_m4_v3(flow_ob->obmat, flow_center);
2164     manta_pos_to_cell(fds, flow_center);
2165 
2166     /* Set emission map.
2167      * Use 3 cell diagonals as margin (3 * 1.732 = 5.196). */
2168     int bounds_margin = (int)ceil(5.196);
2169     clamp_bounds_in_domain(fds, bb->min, bb->max, NULL, NULL, bounds_margin, dt);
2170     bb_allocateData(bb, ffs->flags & FLUID_FLOW_INITVELOCITY, true);
2171 
2172     /* Setup loop bounds. */
2173     for (i = 0; i < 3; i++) {
2174       min[i] = bb->min[i];
2175       max[i] = bb->max[i];
2176       res[i] = bb->res[i];
2177     }
2178 
2179     /* Skip flow sampling loop if object has disabled flow. */
2180     bool use_flow = ffs->flags & FLUID_FLOW_USE_INFLOW;
2181     if (use_flow && BKE_bvhtree_from_mesh_get(&tree_data, me, BVHTREE_FROM_LOOPTRI, 4)) {
2182 
2183       EmitFromDMData data = {
2184           .fds = fds,
2185           .ffs = ffs,
2186           .mvert = mvert,
2187           .mloop = mloop,
2188           .mlooptri = mlooptri,
2189           .mloopuv = mloopuv,
2190           .dvert = dvert,
2191           .defgrp_index = defgrp_index,
2192           .tree = &tree_data,
2193           .bb = bb,
2194           .has_velocity = has_velocity,
2195           .vert_vel = vert_vel,
2196           .flow_center = flow_center,
2197           .min = min,
2198           .max = max,
2199           .res = res,
2200       };
2201 
2202       TaskParallelSettings settings;
2203       BLI_parallel_range_settings_defaults(&settings);
2204       settings.min_iter_per_thread = 2;
2205       BLI_task_parallel_range(min[2], max[2], &data, emit_from_mesh_task_cb, &settings);
2206     }
2207     /* Free bvh tree. */
2208     free_bvhtree_from_mesh(&tree_data);
2209 
2210     if (vert_vel) {
2211       MEM_freeN(vert_vel);
2212     }
2213     if (me->mvert) {
2214       MEM_freeN(me->mvert);
2215     }
2216     BKE_id_free(NULL, me);
2217   }
2218 }
2219 
2220 /** \} */
2221 
2222 /* -------------------------------------------------------------------- */
2223 /** \name Fluid Step
2224  * \{ */
2225 
adaptive_domain_adjust(FluidDomainSettings * fds,Object * ob,FluidObjectBB * bb_maps,uint numflowobj,float dt)2226 static void adaptive_domain_adjust(
2227     FluidDomainSettings *fds, Object *ob, FluidObjectBB *bb_maps, uint numflowobj, float dt)
2228 {
2229   /* calculate domain shift for current frame */
2230   int new_shift[3] = {0};
2231   int total_shift[3];
2232   float frame_shift_f[3];
2233   float ob_loc[3] = {0};
2234 
2235   mul_m4_v3(ob->obmat, ob_loc);
2236 
2237   sub_v3_v3v3(frame_shift_f, ob_loc, fds->prev_loc);
2238   copy_v3_v3(fds->prev_loc, ob_loc);
2239   /* convert global space shift to local "cell" space */
2240   mul_mat3_m4_v3(fds->imat, frame_shift_f);
2241   frame_shift_f[0] = frame_shift_f[0] / fds->cell_size[0];
2242   frame_shift_f[1] = frame_shift_f[1] / fds->cell_size[1];
2243   frame_shift_f[2] = frame_shift_f[2] / fds->cell_size[2];
2244   /* add to total shift */
2245   add_v3_v3(fds->shift_f, frame_shift_f);
2246   /* convert to integer */
2247   total_shift[0] = (int)(floorf(fds->shift_f[0]));
2248   total_shift[1] = (int)(floorf(fds->shift_f[1]));
2249   total_shift[2] = (int)(floorf(fds->shift_f[2]));
2250   int temp_shift[3];
2251   copy_v3_v3_int(temp_shift, fds->shift);
2252   sub_v3_v3v3_int(new_shift, total_shift, fds->shift);
2253   copy_v3_v3_int(fds->shift, total_shift);
2254 
2255   /* calculate new domain boundary points so that smoke doesn't slide on sub-cell movement */
2256   fds->p0[0] = fds->dp0[0] - fds->cell_size[0] * (fds->shift_f[0] - total_shift[0] - 0.5f);
2257   fds->p0[1] = fds->dp0[1] - fds->cell_size[1] * (fds->shift_f[1] - total_shift[1] - 0.5f);
2258   fds->p0[2] = fds->dp0[2] - fds->cell_size[2] * (fds->shift_f[2] - total_shift[2] - 0.5f);
2259   fds->p1[0] = fds->p0[0] + fds->cell_size[0] * fds->base_res[0];
2260   fds->p1[1] = fds->p0[1] + fds->cell_size[1] * fds->base_res[1];
2261   fds->p1[2] = fds->p0[2] + fds->cell_size[2] * fds->base_res[2];
2262 
2263   /* adjust domain resolution */
2264   const int block_size = fds->noise_scale;
2265   int min[3] = {32767, 32767, 32767}, max[3] = {-32767, -32767, -32767}, res[3];
2266   int total_cells = 1, res_changed = 0, shift_changed = 0;
2267   float min_vel[3], max_vel[3];
2268   int x, y, z;
2269   float *density = manta_smoke_get_density(fds->fluid);
2270   float *fuel = manta_smoke_get_fuel(fds->fluid);
2271   float *bigdensity = manta_noise_get_density(fds->fluid);
2272   float *bigfuel = manta_noise_get_fuel(fds->fluid);
2273   float *vx = manta_get_velocity_x(fds->fluid);
2274   float *vy = manta_get_velocity_y(fds->fluid);
2275   float *vz = manta_get_velocity_z(fds->fluid);
2276   int wt_res[3];
2277 
2278   if (fds->flags & FLUID_DOMAIN_USE_NOISE && fds->fluid) {
2279     manta_noise_get_res(fds->fluid, wt_res);
2280   }
2281 
2282   INIT_MINMAX(min_vel, max_vel);
2283 
2284   /* Calculate bounds for current domain content */
2285   for (x = fds->res_min[0]; x < fds->res_max[0]; x++) {
2286     for (y = fds->res_min[1]; y < fds->res_max[1]; y++) {
2287       for (z = fds->res_min[2]; z < fds->res_max[2]; z++) {
2288         int xn = x - new_shift[0];
2289         int yn = y - new_shift[1];
2290         int zn = z - new_shift[2];
2291         int index;
2292         float max_den;
2293 
2294         /* skip if cell already belongs to new area */
2295         if (xn >= min[0] && xn <= max[0] && yn >= min[1] && yn <= max[1] && zn >= min[2] &&
2296             zn <= max[2]) {
2297           continue;
2298         }
2299 
2300         index = manta_get_index(x - fds->res_min[0],
2301                                 fds->res[0],
2302                                 y - fds->res_min[1],
2303                                 fds->res[1],
2304                                 z - fds->res_min[2]);
2305         max_den = (fuel) ? MAX2(density[index], fuel[index]) : density[index];
2306 
2307         /* check high resolution bounds if max density isnt already high enough */
2308         if (max_den < fds->adapt_threshold && fds->flags & FLUID_DOMAIN_USE_NOISE && fds->fluid) {
2309           int i, j, k;
2310           /* high res grid index */
2311           int xx = (x - fds->res_min[0]) * block_size;
2312           int yy = (y - fds->res_min[1]) * block_size;
2313           int zz = (z - fds->res_min[2]) * block_size;
2314 
2315           for (i = 0; i < block_size; i++) {
2316             for (j = 0; j < block_size; j++) {
2317               for (k = 0; k < block_size; k++) {
2318                 int big_index = manta_get_index(xx + i, wt_res[0], yy + j, wt_res[1], zz + k);
2319                 float den = (bigfuel) ? MAX2(bigdensity[big_index], bigfuel[big_index]) :
2320                                         bigdensity[big_index];
2321                 if (den > max_den) {
2322                   max_den = den;
2323                 }
2324               }
2325             }
2326           }
2327         }
2328 
2329         /* content bounds (use shifted coordinates) */
2330         if (max_den >= fds->adapt_threshold) {
2331           if (min[0] > xn) {
2332             min[0] = xn;
2333           }
2334           if (min[1] > yn) {
2335             min[1] = yn;
2336           }
2337           if (min[2] > zn) {
2338             min[2] = zn;
2339           }
2340           if (max[0] < xn) {
2341             max[0] = xn;
2342           }
2343           if (max[1] < yn) {
2344             max[1] = yn;
2345           }
2346           if (max[2] < zn) {
2347             max[2] = zn;
2348           }
2349         }
2350 
2351         /* velocity bounds */
2352         if (min_vel[0] > vx[index]) {
2353           min_vel[0] = vx[index];
2354         }
2355         if (min_vel[1] > vy[index]) {
2356           min_vel[1] = vy[index];
2357         }
2358         if (min_vel[2] > vz[index]) {
2359           min_vel[2] = vz[index];
2360         }
2361         if (max_vel[0] < vx[index]) {
2362           max_vel[0] = vx[index];
2363         }
2364         if (max_vel[1] < vy[index]) {
2365           max_vel[1] = vy[index];
2366         }
2367         if (max_vel[2] < vz[index]) {
2368           max_vel[2] = vz[index];
2369         }
2370       }
2371     }
2372   }
2373 
2374   /* also apply emission maps */
2375   for (int i = 0; i < numflowobj; i++) {
2376     FluidObjectBB *bb = &bb_maps[i];
2377 
2378     for (x = bb->min[0]; x < bb->max[0]; x++) {
2379       for (y = bb->min[1]; y < bb->max[1]; y++) {
2380         for (z = bb->min[2]; z < bb->max[2]; z++) {
2381           int index = manta_get_index(
2382               x - bb->min[0], bb->res[0], y - bb->min[1], bb->res[1], z - bb->min[2]);
2383           float max_den = bb->influence[index];
2384 
2385           /* density bounds */
2386           if (max_den >= fds->adapt_threshold) {
2387             if (min[0] > x) {
2388               min[0] = x;
2389             }
2390             if (min[1] > y) {
2391               min[1] = y;
2392             }
2393             if (min[2] > z) {
2394               min[2] = z;
2395             }
2396             if (max[0] < x) {
2397               max[0] = x;
2398             }
2399             if (max[1] < y) {
2400               max[1] = y;
2401             }
2402             if (max[2] < z) {
2403               max[2] = z;
2404             }
2405           }
2406         }
2407       }
2408     }
2409   }
2410 
2411   /* calculate new bounds based on these values */
2412   clamp_bounds_in_domain(fds, min, max, min_vel, max_vel, fds->adapt_margin + 1, dt);
2413 
2414   for (int i = 0; i < 3; i++) {
2415     /* calculate new resolution */
2416     res[i] = max[i] - min[i];
2417     total_cells *= res[i];
2418 
2419     if (new_shift[i]) {
2420       shift_changed = 1;
2421     }
2422 
2423     /* if no content set minimum dimensions */
2424     if (res[i] <= 0) {
2425       int j;
2426       for (j = 0; j < 3; j++) {
2427         min[j] = 0;
2428         max[j] = 1;
2429         res[j] = 1;
2430       }
2431       res_changed = 1;
2432       total_cells = 1;
2433       break;
2434     }
2435     if (min[i] != fds->res_min[i] || max[i] != fds->res_max[i]) {
2436       res_changed = 1;
2437     }
2438   }
2439 
2440   if (res_changed || shift_changed) {
2441     BKE_fluid_reallocate_copy_fluid(
2442         fds, fds->res, res, fds->res_min, min, fds->res_max, temp_shift, total_shift);
2443 
2444     /* set new domain dimensions */
2445     copy_v3_v3_int(fds->res_min, min);
2446     copy_v3_v3_int(fds->res_max, max);
2447     copy_v3_v3_int(fds->res, res);
2448     fds->total_cells = total_cells;
2449 
2450     /* Redo adapt time step in manta to refresh solver state (ie time variables) */
2451     manta_adapt_timestep(fds->fluid);
2452   }
2453 }
2454 
apply_outflow_fields(int index,float distance_value,float * density,float * heat,float * fuel,float * react,float * color_r,float * color_g,float * color_b,float * phiout)2455 BLI_INLINE void apply_outflow_fields(int index,
2456                                      float distance_value,
2457                                      float *density,
2458                                      float *heat,
2459                                      float *fuel,
2460                                      float *react,
2461                                      float *color_r,
2462                                      float *color_g,
2463                                      float *color_b,
2464                                      float *phiout)
2465 {
2466   /* Set levelset value for liquid inflow.
2467    * Ensure that distance value is "joined" into the levelset. */
2468   if (phiout) {
2469     phiout[index] = MIN2(distance_value, phiout[index]);
2470   }
2471 
2472   /* Set smoke outflow, i.e. reset cell to zero. */
2473   if (density) {
2474     density[index] = 0.0f;
2475   }
2476   if (heat) {
2477     heat[index] = 0.0f;
2478   }
2479   if (fuel) {
2480     fuel[index] = 0.0f;
2481     react[index] = 0.0f;
2482   }
2483   if (color_r) {
2484     color_r[index] = 0.0f;
2485     color_g[index] = 0.0f;
2486     color_b[index] = 0.0f;
2487   }
2488 }
2489 
apply_inflow_fields(FluidFlowSettings * ffs,float emission_value,float distance_value,int index,float * density_in,const float * density,float * heat_in,const float * heat,float * fuel_in,const float * fuel,float * react_in,const float * react,float * color_r_in,const float * color_r,float * color_g_in,const float * color_g,float * color_b_in,const float * color_b,float * phi_in,float * emission_in)2490 BLI_INLINE void apply_inflow_fields(FluidFlowSettings *ffs,
2491                                     float emission_value,
2492                                     float distance_value,
2493                                     int index,
2494                                     float *density_in,
2495                                     const float *density,
2496                                     float *heat_in,
2497                                     const float *heat,
2498                                     float *fuel_in,
2499                                     const float *fuel,
2500                                     float *react_in,
2501                                     const float *react,
2502                                     float *color_r_in,
2503                                     const float *color_r,
2504                                     float *color_g_in,
2505                                     const float *color_g,
2506                                     float *color_b_in,
2507                                     const float *color_b,
2508                                     float *phi_in,
2509                                     float *emission_in)
2510 {
2511   /* Set levelset value for liquid inflow.
2512    * Ensure that distance value is "joined" into the levelset. */
2513   if (phi_in) {
2514     phi_in[index] = MIN2(distance_value, phi_in[index]);
2515   }
2516 
2517   /* Set emission value for smoke inflow.
2518    * Ensure that emission value is "maximized". */
2519   if (emission_in) {
2520     emission_in[index] = MAX2(emission_value, emission_in[index]);
2521   }
2522 
2523   /* Set inflow for smoke from here on. */
2524   int absolute_flow = (ffs->flags & FLUID_FLOW_ABSOLUTE);
2525   float dens_old = (density) ? density[index] : 0.0;
2526   // float fuel_old = (fuel) ? fuel[index] : 0.0f;  /* UNUSED */
2527   float dens_flow = (ffs->type == FLUID_FLOW_TYPE_FIRE) ? 0.0f : emission_value * ffs->density;
2528   float fuel_flow = (fuel) ? emission_value * ffs->fuel_amount : 0.0f;
2529   /* Set heat inflow. */
2530   if (heat && heat_in) {
2531     if (emission_value > 0.0f) {
2532       heat_in[index] = ADD_IF_LOWER(heat[index], ffs->temperature);
2533     }
2534   }
2535 
2536   /* Set density and fuel - absolute mode. */
2537   if (absolute_flow) {
2538     if (density && density_in) {
2539       if (ffs->type != FLUID_FLOW_TYPE_FIRE && dens_flow > density[index]) {
2540         /* Use MAX2 to preserve values from other emitters at this cell. */
2541         density_in[index] = MAX2(dens_flow, density_in[index]);
2542       }
2543     }
2544     if (fuel && fuel_in) {
2545       if (ffs->type != FLUID_FLOW_TYPE_SMOKE && fuel_flow && fuel_flow > fuel[index]) {
2546         /* Use MAX2 to preserve values from other emitters at this cell. */
2547         fuel_in[index] = MAX2(fuel_flow, fuel_in[index]);
2548       }
2549     }
2550   }
2551   /* Set density and fuel - additive mode. */
2552   else {
2553     if (density && density_in) {
2554       if (ffs->type != FLUID_FLOW_TYPE_FIRE) {
2555         density_in[index] += dens_flow;
2556         CLAMP(density_in[index], 0.0f, 1.0f);
2557       }
2558     }
2559     if (fuel && fuel_in) {
2560       if (ffs->type != FLUID_FLOW_TYPE_SMOKE && ffs->fuel_amount) {
2561         fuel_in[index] += fuel_flow;
2562         CLAMP(fuel_in[index], 0.0f, 10.0f);
2563       }
2564     }
2565   }
2566 
2567   /* Set color. */
2568   if (color_r && color_r_in) {
2569     if (dens_flow) {
2570       float total_dens = density[index] / (dens_old + dens_flow);
2571       color_r_in[index] = (color_r[index] + ffs->color[0] * dens_flow) * total_dens;
2572       color_g_in[index] = (color_g[index] + ffs->color[1] * dens_flow) * total_dens;
2573       color_b_in[index] = (color_b[index] + ffs->color[2] * dens_flow) * total_dens;
2574     }
2575   }
2576 
2577   /* Set fire reaction coordinate. */
2578   if (fuel && fuel_in) {
2579     /* Instead of using 1.0 for all new fuel add slight falloff to reduce flow blocky-ness. */
2580     float value = 1.0f - pow2f(1.0f - emission_value);
2581 
2582     if (fuel_in[index] > FLT_EPSILON && value > react[index]) {
2583       float f = fuel_flow / fuel_in[index];
2584       react_in[index] = value * f + (1.0f - f) * react[index];
2585       CLAMP(react_in[index], 0.0f, value);
2586     }
2587   }
2588 }
2589 
ensure_flowsfields(FluidDomainSettings * fds)2590 static void ensure_flowsfields(FluidDomainSettings *fds)
2591 {
2592   if (fds->active_fields & FLUID_DOMAIN_ACTIVE_INVEL) {
2593     manta_ensure_invelocity(fds->fluid, fds->fmd);
2594   }
2595   if (fds->active_fields & FLUID_DOMAIN_ACTIVE_OUTFLOW) {
2596     manta_ensure_outflow(fds->fluid, fds->fmd);
2597   }
2598   if (fds->active_fields & FLUID_DOMAIN_ACTIVE_HEAT) {
2599     manta_smoke_ensure_heat(fds->fluid, fds->fmd);
2600   }
2601   if (fds->active_fields & FLUID_DOMAIN_ACTIVE_FIRE) {
2602     manta_smoke_ensure_fire(fds->fluid, fds->fmd);
2603   }
2604   if (fds->active_fields & FLUID_DOMAIN_ACTIVE_COLORS) {
2605     /* Initialize all smoke with "active_color". */
2606     manta_smoke_ensure_colors(fds->fluid, fds->fmd);
2607   }
2608   if (fds->type == FLUID_DOMAIN_TYPE_LIQUID &&
2609       (fds->particle_type & FLUID_DOMAIN_PARTICLE_SPRAY ||
2610        fds->particle_type & FLUID_DOMAIN_PARTICLE_FOAM ||
2611        fds->particle_type & FLUID_DOMAIN_PARTICLE_TRACER)) {
2612     manta_liquid_ensure_sndparts(fds->fluid, fds->fmd);
2613   }
2614   manta_update_pointers(fds->fluid, fds->fmd, false);
2615 }
2616 
update_flowsflags(FluidDomainSettings * fds,Object ** flowobjs,int numflowobj)2617 static void update_flowsflags(FluidDomainSettings *fds, Object **flowobjs, int numflowobj)
2618 {
2619   int active_fields = fds->active_fields;
2620   uint flow_index;
2621 
2622   /* First, remove all flags that we want to update. */
2623   int prev_flags = (FLUID_DOMAIN_ACTIVE_INVEL | FLUID_DOMAIN_ACTIVE_OUTFLOW |
2624                     FLUID_DOMAIN_ACTIVE_HEAT | FLUID_DOMAIN_ACTIVE_FIRE);
2625   active_fields &= ~prev_flags;
2626 
2627   /* Monitor active fields based on flow settings. */
2628   for (flow_index = 0; flow_index < numflowobj; flow_index++) {
2629     Object *flow_ob = flowobjs[flow_index];
2630     FluidModifierData *fmd2 = (FluidModifierData *)BKE_modifiers_findby_type(flow_ob,
2631                                                                              eModifierType_Fluid);
2632 
2633     /* Sanity check. */
2634     if (!fmd2) {
2635       continue;
2636     }
2637 
2638     /* Activate specific grids if at least one flow object requires this grid. */
2639     if ((fmd2->type & MOD_FLUID_TYPE_FLOW) && fmd2->flow) {
2640       FluidFlowSettings *ffs = fmd2->flow;
2641       if (!ffs) {
2642         break;
2643       }
2644       if (ffs->flags & FLUID_FLOW_NEEDS_UPDATE) {
2645         ffs->flags &= ~FLUID_FLOW_NEEDS_UPDATE;
2646         fds->cache_flag |= FLUID_DOMAIN_OUTDATED_DATA;
2647       }
2648       if (ffs->flags & FLUID_FLOW_INITVELOCITY) {
2649         active_fields |= FLUID_DOMAIN_ACTIVE_INVEL;
2650       }
2651       if (ffs->behavior == FLUID_FLOW_BEHAVIOR_OUTFLOW) {
2652         active_fields |= FLUID_DOMAIN_ACTIVE_OUTFLOW;
2653       }
2654       /* liquids done from here */
2655       if (fds->type == FLUID_DOMAIN_TYPE_LIQUID) {
2656         continue;
2657       }
2658 
2659       /* Activate heat field if a flow object produces any heat. */
2660       if (ffs->temperature != 0.0) {
2661         active_fields |= FLUID_DOMAIN_ACTIVE_HEAT;
2662       }
2663       /* Activate fuel field if a flow object is of fire type. */
2664       if (ffs->fuel_amount != 0.0 || ffs->type == FLUID_FLOW_TYPE_FIRE ||
2665           ffs->type == FLUID_FLOW_TYPE_SMOKEFIRE) {
2666         active_fields |= FLUID_DOMAIN_ACTIVE_FIRE;
2667       }
2668       /* Activate color field if flows add smoke with varying colors. */
2669       if (ffs->density != 0.0 &&
2670           (ffs->type == FLUID_FLOW_TYPE_SMOKE || ffs->type == FLUID_FLOW_TYPE_SMOKEFIRE)) {
2671         if (!(active_fields & FLUID_DOMAIN_ACTIVE_COLOR_SET)) {
2672           copy_v3_v3(fds->active_color, ffs->color);
2673           active_fields |= FLUID_DOMAIN_ACTIVE_COLOR_SET;
2674         }
2675         else if (!equals_v3v3(fds->active_color, ffs->color)) {
2676           copy_v3_v3(fds->active_color, ffs->color);
2677           active_fields |= FLUID_DOMAIN_ACTIVE_COLORS;
2678         }
2679       }
2680     }
2681   }
2682   /* Monitor active fields based on domain settings. */
2683   if (fds->type == FLUID_DOMAIN_TYPE_GAS && active_fields & FLUID_DOMAIN_ACTIVE_FIRE) {
2684     /* Heat is always needed for fire. */
2685     active_fields |= FLUID_DOMAIN_ACTIVE_HEAT;
2686     /* Also activate colors if domain smoke color differs from active color. */
2687     if (!(active_fields & FLUID_DOMAIN_ACTIVE_COLOR_SET)) {
2688       copy_v3_v3(fds->active_color, fds->flame_smoke_color);
2689       active_fields |= FLUID_DOMAIN_ACTIVE_COLOR_SET;
2690     }
2691     else if (!equals_v3v3(fds->active_color, fds->flame_smoke_color)) {
2692       copy_v3_v3(fds->active_color, fds->flame_smoke_color);
2693       active_fields |= FLUID_DOMAIN_ACTIVE_COLORS;
2694     }
2695   }
2696   fds->active_fields = active_fields;
2697 }
2698 
escape_flowsobject(Object * flowobj,FluidDomainSettings * fds,FluidFlowSettings * ffs,int frame)2699 static bool escape_flowsobject(Object *flowobj,
2700                                FluidDomainSettings *fds,
2701                                FluidFlowSettings *ffs,
2702                                int frame)
2703 {
2704   bool use_velocity = (ffs->flags & FLUID_FLOW_INITVELOCITY);
2705   bool is_static = is_static_object(flowobj);
2706 
2707   bool liquid_flow = ffs->type == FLUID_FLOW_TYPE_LIQUID;
2708   bool gas_flow = (ffs->type == FLUID_FLOW_TYPE_SMOKE || ffs->type == FLUID_FLOW_TYPE_FIRE ||
2709                    ffs->type == FLUID_FLOW_TYPE_SMOKEFIRE);
2710   bool is_geometry = (ffs->behavior == FLUID_FLOW_BEHAVIOR_GEOMETRY);
2711 
2712   bool liquid_domain = fds->type == FLUID_DOMAIN_TYPE_LIQUID;
2713   bool gas_domain = fds->type == FLUID_DOMAIN_TYPE_GAS;
2714   bool is_adaptive = (fds->flags & FLUID_DOMAIN_USE_ADAPTIVE_DOMAIN);
2715   bool is_resume = (fds->cache_frame_pause_data == frame);
2716   bool is_first_frame = (fds->cache_frame_start == frame);
2717 
2718   /* Cannot use static mode with adaptive domain.
2719    * The adaptive domain might expand and only later discover the static object. */
2720   if (is_adaptive) {
2721     is_static = false;
2722   }
2723   /* No need to compute emission value if it won't be applied. */
2724   if (liquid_flow && is_geometry && !is_first_frame) {
2725     return true;
2726   }
2727   /* Skip flow object if it does not "belong" to this domain type. */
2728   if ((liquid_flow && gas_domain) || (gas_flow && liquid_domain)) {
2729     return true;
2730   }
2731   /* Optimization: Static liquid flow objects don't need emission after first frame.
2732    * TODO(sebbas): Also do not use static mode if initial velocities are enabled. */
2733   if (liquid_flow && is_static && !is_first_frame && !is_resume && !use_velocity) {
2734     return true;
2735   }
2736   return false;
2737 }
2738 
compute_flowsemission(Scene * scene,FluidObjectBB * bb_maps,struct Depsgraph * depsgraph,float dt,Object ** flowobjs,int frame,float frame_length,FluidDomainSettings * fds,uint numflowobjs,float time_per_frame)2739 static void compute_flowsemission(Scene *scene,
2740                                   FluidObjectBB *bb_maps,
2741                                   struct Depsgraph *depsgraph,
2742                                   float dt,
2743                                   Object **flowobjs,
2744                                   int frame,
2745                                   float frame_length,
2746                                   FluidDomainSettings *fds,
2747                                   uint numflowobjs,
2748                                   float time_per_frame)
2749 {
2750   bool is_first_frame = (frame == fds->cache_frame_start);
2751 
2752   /* Prepare flow emission maps. */
2753   for (int flow_index = 0; flow_index < numflowobjs; flow_index++) {
2754     Object *flowobj = flowobjs[flow_index];
2755     FluidModifierData *fmd2 = (FluidModifierData *)BKE_modifiers_findby_type(flowobj,
2756                                                                              eModifierType_Fluid);
2757 
2758     /* Sanity check. */
2759     if (!fmd2) {
2760       continue;
2761     }
2762 
2763     /* Check for initialized flow object. */
2764     if ((fmd2->type & MOD_FLUID_TYPE_FLOW) && fmd2->flow) {
2765       FluidFlowSettings *ffs = fmd2->flow;
2766       int subframes = ffs->subframes;
2767       FluidObjectBB *bb = &bb_maps[flow_index];
2768 
2769       /* Optimization: Skip this object under certain conditions. */
2770       if (escape_flowsobject(flowobj, fds, ffs, frame)) {
2771         continue;
2772       }
2773 
2774       /* First frame cannot have any subframes because there is (obviously) no previous frame from
2775        * where subframes could come from. */
2776       if (is_first_frame) {
2777         subframes = 0;
2778       }
2779 
2780       /* More splitting because of emission subframe: If no subframes present, sample_size is 1. */
2781       float sample_size = 1.0f / (float)(subframes + 1);
2782       float subframe_dt = dt * sample_size;
2783 
2784       /* Emission loop. When not using subframes this will loop only once. */
2785       for (int subframe = 0; subframe <= subframes; subframe++) {
2786         /* Temporary emission map used when subframes are enabled, i.e. at least one subframe. */
2787         FluidObjectBB bb_temp = {NULL};
2788 
2789         /* Set scene time */
2790         if ((subframe < subframes || time_per_frame + dt + FLT_EPSILON < frame_length) &&
2791             !is_first_frame) {
2792           scene->r.subframe = (time_per_frame + (subframe + 1.0f) * subframe_dt) / frame_length;
2793           scene->r.cfra = frame - 1;
2794         }
2795         else {
2796           scene->r.subframe = 0.0f;
2797           scene->r.cfra = frame;
2798         }
2799 
2800         /* Sanity check: subframe portion must be between 0 and 1. */
2801         CLAMP(scene->r.subframe, 0.0f, 1.0f);
2802 #  ifdef DEBUG_PRINT
2803         /* Debugging: Print subframe information. */
2804         printf(
2805             "flow: frame (is first: %d): %d // scene current frame: %d // scene current subframe: "
2806             "%f\n",
2807             is_first_frame,
2808             frame,
2809             scene->r.cfra,
2810             scene->r.subframe);
2811 #  endif
2812         /* Update frame time, this is considering current subframe fraction
2813          * BLI_mutex_lock() called in manta_step(), so safe to update subframe here
2814          * TODO(sebbas): Using BKE_scene_frame_get(scene) instead of new DEG_get_ctime(depsgraph)
2815          * as subframes don't work with the latter yet. */
2816         BKE_object_modifier_update_subframe(
2817             depsgraph, scene, flowobj, true, 5, BKE_scene_frame_get(scene), eModifierType_Fluid);
2818 
2819         /* Emission from particles. */
2820         if (ffs->source == FLUID_FLOW_SOURCE_PARTICLES) {
2821           if (subframes) {
2822             emit_from_particles(flowobj, fds, ffs, &bb_temp, depsgraph, scene, subframe_dt);
2823           }
2824           else {
2825             emit_from_particles(flowobj, fds, ffs, bb, depsgraph, scene, subframe_dt);
2826           }
2827         }
2828         /* Emission from mesh. */
2829         else if (ffs->source == FLUID_FLOW_SOURCE_MESH) {
2830           if (subframes) {
2831             emit_from_mesh(flowobj, fds, ffs, &bb_temp, subframe_dt);
2832           }
2833           else {
2834             emit_from_mesh(flowobj, fds, ffs, bb, subframe_dt);
2835           }
2836         }
2837         else {
2838           printf("Error: unknown flow emission source\n");
2839         }
2840 
2841         /* If this we emitted with temp emission map in this loop (subframe emission), we combine
2842          * the temp map with the original emission map. */
2843         if (subframes) {
2844           /* Combine emission maps. */
2845           bb_combineMaps(bb, &bb_temp, !(ffs->flags & FLUID_FLOW_ABSOLUTE), sample_size);
2846           bb_freeData(&bb_temp);
2847         }
2848       }
2849     }
2850   }
2851 #  ifdef DEBUG_PRINT
2852   /* Debugging: Print time information. */
2853   printf("flow: frame: %d // time per frame: %f // frame length: %f // dt: %f\n",
2854          frame,
2855          time_per_frame,
2856          frame_length,
2857          dt);
2858 #  endif
2859 }
2860 
update_flowsfluids(struct Depsgraph * depsgraph,Scene * scene,Object * ob,FluidDomainSettings * fds,float time_per_frame,float frame_length,int frame,float dt)2861 static void update_flowsfluids(struct Depsgraph *depsgraph,
2862                                Scene *scene,
2863                                Object *ob,
2864                                FluidDomainSettings *fds,
2865                                float time_per_frame,
2866                                float frame_length,
2867                                int frame,
2868                                float dt)
2869 {
2870   FluidObjectBB *bb_maps = NULL;
2871   Object **flowobjs = NULL;
2872   uint numflowobjs = 0;
2873   bool is_resume = (fds->cache_frame_pause_data == frame);
2874   bool is_first_frame = (fds->cache_frame_start == frame);
2875 
2876   flowobjs = BKE_collision_objects_create(
2877       depsgraph, ob, fds->fluid_group, &numflowobjs, eModifierType_Fluid);
2878 
2879   /* Update all flow related flags and ensure that corresponding grids get initialized. */
2880   update_flowsflags(fds, flowobjs, numflowobjs);
2881   ensure_flowsfields(fds);
2882 
2883   /* Allocate emission map for each flow object. */
2884   bb_maps = MEM_callocN(sizeof(struct FluidObjectBB) * numflowobjs, "fluid_flow_bb_maps");
2885 
2886   /* Initialize emission map for each flow object. */
2887   compute_flowsemission(scene,
2888                         bb_maps,
2889                         depsgraph,
2890                         dt,
2891                         flowobjs,
2892                         frame,
2893                         frame_length,
2894                         fds,
2895                         numflowobjs,
2896                         time_per_frame);
2897 
2898   /* Adjust domain size if needed. Only do this once for every frame. */
2899   if (fds->type == FLUID_DOMAIN_TYPE_GAS && fds->flags & FLUID_DOMAIN_USE_ADAPTIVE_DOMAIN) {
2900     adaptive_domain_adjust(fds, ob, bb_maps, numflowobjs, dt);
2901   }
2902 
2903   float *phi_in = manta_get_phi_in(fds->fluid);
2904   float *phistatic_in = manta_get_phistatic_in(fds->fluid);
2905   float *phiout_in = manta_get_phiout_in(fds->fluid);
2906   float *phioutstatic_in = manta_get_phioutstatic_in(fds->fluid);
2907 
2908   float *density = manta_smoke_get_density(fds->fluid);
2909   float *color_r = manta_smoke_get_color_r(fds->fluid);
2910   float *color_g = manta_smoke_get_color_g(fds->fluid);
2911   float *color_b = manta_smoke_get_color_b(fds->fluid);
2912   float *fuel = manta_smoke_get_fuel(fds->fluid);
2913   float *heat = manta_smoke_get_heat(fds->fluid);
2914   float *react = manta_smoke_get_react(fds->fluid);
2915 
2916   float *density_in = manta_smoke_get_density_in(fds->fluid);
2917   float *heat_in = manta_smoke_get_heat_in(fds->fluid);
2918   float *color_r_in = manta_smoke_get_color_r_in(fds->fluid);
2919   float *color_g_in = manta_smoke_get_color_g_in(fds->fluid);
2920   float *color_b_in = manta_smoke_get_color_b_in(fds->fluid);
2921   float *fuel_in = manta_smoke_get_fuel_in(fds->fluid);
2922   float *react_in = manta_smoke_get_react_in(fds->fluid);
2923   float *emission_in = manta_smoke_get_emission_in(fds->fluid);
2924 
2925   float *velx_initial = manta_get_in_velocity_x(fds->fluid);
2926   float *vely_initial = manta_get_in_velocity_y(fds->fluid);
2927   float *velz_initial = manta_get_in_velocity_z(fds->fluid);
2928 
2929   float *forcex = manta_get_force_x(fds->fluid);
2930   float *forcey = manta_get_force_y(fds->fluid);
2931   float *forcez = manta_get_force_z(fds->fluid);
2932 
2933   BLI_assert(forcex && forcey && forcez);
2934 
2935   /* Either all or no components have to exist. */
2936   BLI_assert((color_r && color_g && color_b) || (!color_r && !color_g && !color_b));
2937   BLI_assert((color_r_in && color_g_in && color_b_in) ||
2938              (!color_r_in && !color_g_in && !color_b_in));
2939   BLI_assert((velx_initial && vely_initial && velz_initial) ||
2940              (!velx_initial && !vely_initial && !velz_initial));
2941 
2942   uint z;
2943   /* Grid reset before writing again. */
2944   for (z = 0; z < fds->res[0] * fds->res[1] * fds->res[2]; z++) {
2945     /* Only reset static phi on first frame, dynamic phi gets reset every time. */
2946     if (phistatic_in && is_first_frame) {
2947       phistatic_in[z] = PHI_MAX;
2948     }
2949     if (phi_in) {
2950       phi_in[z] = PHI_MAX;
2951     }
2952     /* Only reset static phi on first frame, dynamic phi gets reset every time. */
2953     if (phioutstatic_in && is_first_frame) {
2954       phioutstatic_in[z] = PHI_MAX;
2955     }
2956     if (phiout_in) {
2957       phiout_in[z] = PHI_MAX;
2958     }
2959     /* Sync smoke inflow grids with their counterparts (simulation grids). */
2960     if (density_in) {
2961       density_in[z] = density[z];
2962     }
2963     if (heat_in) {
2964       heat_in[z] = heat[z];
2965     }
2966     if (color_r_in && color_g_in && color_b_in) {
2967       color_r_in[z] = color_r[z];
2968       color_g_in[z] = color_b[z];
2969       color_b_in[z] = color_g[z];
2970     }
2971     if (fuel_in) {
2972       fuel_in[z] = fuel[z];
2973       react_in[z] = react[z];
2974     }
2975     if (emission_in) {
2976       emission_in[z] = 0.0f;
2977     }
2978     if (velx_initial && vely_initial && velz_initial) {
2979       velx_initial[z] = 0.0f;
2980       vely_initial[z] = 0.0f;
2981       velz_initial[z] = 0.0f;
2982     }
2983     /* Reset forces here as update_effectors() is skipped when no external forces are present. */
2984     forcex[z] = 0.0f;
2985     forcey[z] = 0.0f;
2986     forcez[z] = 0.0f;
2987   }
2988 
2989   /* Apply emission data for every flow object. */
2990   for (int flow_index = 0; flow_index < numflowobjs; flow_index++) {
2991     Object *flowobj = flowobjs[flow_index];
2992     FluidModifierData *fmd2 = (FluidModifierData *)BKE_modifiers_findby_type(flowobj,
2993                                                                              eModifierType_Fluid);
2994 
2995     /* Sanity check. */
2996     if (!fmd2) {
2997       continue;
2998     }
2999 
3000     /* Check for initialized flow object. */
3001     if ((fmd2->type & MOD_FLUID_TYPE_FLOW) && fmd2->flow) {
3002       FluidFlowSettings *ffs = fmd2->flow;
3003 
3004       bool is_inflow = (ffs->behavior == FLUID_FLOW_BEHAVIOR_INFLOW);
3005       bool is_geometry = (ffs->behavior == FLUID_FLOW_BEHAVIOR_GEOMETRY);
3006       bool is_outflow = (ffs->behavior == FLUID_FLOW_BEHAVIOR_OUTFLOW);
3007       bool is_static = is_static_object(flowobj) &&
3008                        ((fds->flags & FLUID_DOMAIN_USE_ADAPTIVE_DOMAIN) == 0);
3009 
3010       FluidObjectBB *bb = &bb_maps[flow_index];
3011       float *velocity_map = bb->velocity;
3012       float *emission_map = bb->influence;
3013       float *distance_map = bb->distances;
3014 
3015       int gx, gy, gz, ex, ey, ez, dx, dy, dz;
3016       size_t e_index, d_index;
3017 
3018       /* Loop through every emission map cell. */
3019       for (gx = bb->min[0]; gx < bb->max[0]; gx++) {
3020         for (gy = bb->min[1]; gy < bb->max[1]; gy++) {
3021           for (gz = bb->min[2]; gz < bb->max[2]; gz++) {
3022             /* Compute emission map index. */
3023             ex = gx - bb->min[0];
3024             ey = gy - bb->min[1];
3025             ez = gz - bb->min[2];
3026             e_index = manta_get_index(ex, bb->res[0], ey, bb->res[1], ez);
3027 
3028             /* Get domain index. */
3029             dx = gx - fds->res_min[0];
3030             dy = gy - fds->res_min[1];
3031             dz = gz - fds->res_min[2];
3032             d_index = manta_get_index(dx, fds->res[0], dy, fds->res[1], dz);
3033             /* Make sure emission cell is inside the new domain boundary. */
3034             if (dx < 0 || dy < 0 || dz < 0 || dx >= fds->res[0] || dy >= fds->res[1] ||
3035                 dz >= fds->res[2]) {
3036               continue;
3037             }
3038 
3039             /* Delete fluid in outflow regions. */
3040             if (is_outflow) {
3041               float *levelset = ((is_first_frame || is_resume) && is_static) ? phioutstatic_in :
3042                                                                                phiout_in;
3043               apply_outflow_fields(d_index,
3044                                    distance_map[e_index],
3045                                    density_in,
3046                                    heat_in,
3047                                    fuel_in,
3048                                    react_in,
3049                                    color_r_in,
3050                                    color_g_in,
3051                                    color_b_in,
3052                                    levelset);
3053             }
3054             /* Do not apply inflow after the first frame when in geometry mode. */
3055             else if (is_geometry && !is_first_frame) {
3056               apply_inflow_fields(ffs,
3057                                   0.0f,
3058                                   PHI_MAX,
3059                                   d_index,
3060                                   density_in,
3061                                   density,
3062                                   heat_in,
3063                                   heat,
3064                                   fuel_in,
3065                                   fuel,
3066                                   react_in,
3067                                   react,
3068                                   color_r_in,
3069                                   color_r,
3070                                   color_g_in,
3071                                   color_g,
3072                                   color_b_in,
3073                                   color_b,
3074                                   phi_in,
3075                                   emission_in);
3076             }
3077             /* Main inflow application. */
3078             else if (is_geometry || is_inflow) {
3079               float *levelset = ((is_first_frame || is_resume) && is_static && !is_geometry) ?
3080                                     phistatic_in :
3081                                     phi_in;
3082               apply_inflow_fields(ffs,
3083                                   emission_map[e_index],
3084                                   distance_map[e_index],
3085                                   d_index,
3086                                   density_in,
3087                                   density,
3088                                   heat_in,
3089                                   heat,
3090                                   fuel_in,
3091                                   fuel,
3092                                   react_in,
3093                                   react,
3094                                   color_r_in,
3095                                   color_r,
3096                                   color_g_in,
3097                                   color_g,
3098                                   color_b_in,
3099                                   color_b,
3100                                   levelset,
3101                                   emission_in);
3102               if (ffs->flags & FLUID_FLOW_INITVELOCITY) {
3103                 /* Use the initial velocity from the inflow object with the highest velocity for
3104                  * now. */
3105                 float vel_initial[3];
3106                 vel_initial[0] = velx_initial[d_index];
3107                 vel_initial[1] = vely_initial[d_index];
3108                 vel_initial[2] = velz_initial[d_index];
3109                 float vel_initial_strength = len_squared_v3(vel_initial);
3110                 float vel_map_strength = len_squared_v3(velocity_map + 3 * e_index);
3111                 if (vel_map_strength > vel_initial_strength) {
3112                   velx_initial[d_index] = velocity_map[e_index * 3];
3113                   vely_initial[d_index] = velocity_map[e_index * 3 + 1];
3114                   velz_initial[d_index] = velocity_map[e_index * 3 + 2];
3115                 }
3116               }
3117             }
3118           }
3119         }
3120       } /* End of flow emission map loop. */
3121       bb_freeData(bb);
3122     } /* End of flow object loop. */
3123   }
3124 
3125   BKE_collision_objects_free(flowobjs);
3126   if (bb_maps) {
3127     MEM_freeN(bb_maps);
3128   }
3129 }
3130 
3131 typedef struct UpdateEffectorsData {
3132   Scene *scene;
3133   FluidDomainSettings *fds;
3134   ListBase *effectors;
3135 
3136   float *density;
3137   float *fuel;
3138   float *force_x;
3139   float *force_y;
3140   float *force_z;
3141   float *velocity_x;
3142   float *velocity_y;
3143   float *velocity_z;
3144   int *flags;
3145   float *phi_obs_in;
3146 } UpdateEffectorsData;
3147 
update_effectors_task_cb(void * __restrict userdata,const int x,const TaskParallelTLS * __restrict UNUSED (tls))3148 static void update_effectors_task_cb(void *__restrict userdata,
3149                                      const int x,
3150                                      const TaskParallelTLS *__restrict UNUSED(tls))
3151 {
3152   UpdateEffectorsData *data = userdata;
3153   FluidDomainSettings *fds = data->fds;
3154 
3155   for (int y = 0; y < fds->res[1]; y++) {
3156     for (int z = 0; z < fds->res[2]; z++) {
3157       EffectedPoint epoint;
3158       float mag;
3159       float voxel_center[3] = {0, 0, 0}, vel[3] = {0, 0, 0}, retvel[3] = {0, 0, 0};
3160       const uint index = manta_get_index(x, fds->res[0], y, fds->res[1], z);
3161 
3162       if ((data->fuel && MAX2(data->density[index], data->fuel[index]) < FLT_EPSILON) ||
3163           (data->density && data->density[index] < FLT_EPSILON) ||
3164           (data->phi_obs_in && data->phi_obs_in[index] < 0.0f) ||
3165           data->flags[index] & 2)  // mantaflow convention: 2 == FlagObstacle
3166       {
3167         continue;
3168       }
3169 
3170       /* Get velocities from manta grid space and convert to blender units. */
3171       vel[0] = data->velocity_x[index];
3172       vel[1] = data->velocity_y[index];
3173       vel[2] = data->velocity_z[index];
3174       mul_v3_fl(vel, fds->dx);
3175 
3176       /* Convert vel to global space. */
3177       mag = len_v3(vel);
3178       mul_mat3_m4_v3(fds->obmat, vel);
3179       normalize_v3(vel);
3180       mul_v3_fl(vel, mag);
3181 
3182       voxel_center[0] = fds->p0[0] + fds->cell_size[0] * ((float)(x + fds->res_min[0]) + 0.5f);
3183       voxel_center[1] = fds->p0[1] + fds->cell_size[1] * ((float)(y + fds->res_min[1]) + 0.5f);
3184       voxel_center[2] = fds->p0[2] + fds->cell_size[2] * ((float)(z + fds->res_min[2]) + 0.5f);
3185       mul_m4_v3(fds->obmat, voxel_center);
3186 
3187       /* Do effectors. */
3188       pd_point_from_loc(data->scene, voxel_center, vel, index, &epoint);
3189       BKE_effectors_apply(
3190           data->effectors, NULL, fds->effector_weights, &epoint, retvel, NULL, NULL);
3191 
3192       /* Convert retvel to local space. */
3193       mag = len_v3(retvel);
3194       mul_mat3_m4_v3(fds->imat, retvel);
3195       normalize_v3(retvel);
3196       mul_v3_fl(retvel, mag);
3197 
3198       /* Copy computed force to fluid solver forces. */
3199       mul_v3_fl(retvel, 0.2f);     /* Factor from 0e6820cc5d62. */
3200       CLAMP3(retvel, -1.0f, 1.0f); /* Restrict forces to +-1 interval. */
3201       data->force_x[index] = retvel[0];
3202       data->force_y[index] = retvel[1];
3203       data->force_z[index] = retvel[2];
3204 
3205 #  ifdef DEBUG_PRINT
3206       /* Debugging: Print forces. */
3207       printf("setting force: [%f, %f, %f]\n",
3208              data->force_x[index],
3209              data->force_y[index],
3210              data->force_z[index]);
3211 #  endif
3212     }
3213   }
3214 }
3215 
update_effectors(Depsgraph * depsgraph,Scene * scene,Object * ob,FluidDomainSettings * fds,float UNUSED (dt))3216 static void update_effectors(
3217     Depsgraph *depsgraph, Scene *scene, Object *ob, FluidDomainSettings *fds, float UNUSED(dt))
3218 {
3219   ListBase *effectors;
3220   /* make sure smoke flow influence is 0.0f */
3221   fds->effector_weights->weight[PFIELD_FLUIDFLOW] = 0.0f;
3222   effectors = BKE_effectors_create(depsgraph, ob, NULL, fds->effector_weights);
3223 
3224   if (effectors) {
3225     /* Precalculate wind forces. */
3226     UpdateEffectorsData data;
3227     data.scene = scene;
3228     data.fds = fds;
3229     data.effectors = effectors;
3230     data.density = manta_smoke_get_density(fds->fluid);
3231     data.fuel = manta_smoke_get_fuel(fds->fluid);
3232     data.force_x = manta_get_force_x(fds->fluid);
3233     data.force_y = manta_get_force_y(fds->fluid);
3234     data.force_z = manta_get_force_z(fds->fluid);
3235     data.velocity_x = manta_get_velocity_x(fds->fluid);
3236     data.velocity_y = manta_get_velocity_y(fds->fluid);
3237     data.velocity_z = manta_get_velocity_z(fds->fluid);
3238     data.flags = manta_smoke_get_flags(fds->fluid);
3239     data.phi_obs_in = manta_get_phiobs_in(fds->fluid);
3240 
3241     TaskParallelSettings settings;
3242     BLI_parallel_range_settings_defaults(&settings);
3243     settings.min_iter_per_thread = 2;
3244     BLI_task_parallel_range(0, fds->res[0], &data, update_effectors_task_cb, &settings);
3245   }
3246 
3247   BKE_effectors_free(effectors);
3248 }
3249 
create_liquid_geometry(FluidDomainSettings * fds,Mesh * orgmesh,Object * ob)3250 static Mesh *create_liquid_geometry(FluidDomainSettings *fds, Mesh *orgmesh, Object *ob)
3251 {
3252   Mesh *me;
3253   MVert *mverts;
3254   MPoly *mpolys;
3255   MLoop *mloops;
3256   short *normals, *no_s;
3257   float no[3];
3258   float min[3];
3259   float max[3];
3260   float size[3];
3261   float cell_size_scaled[3];
3262 
3263   /* Assign material + flags to new mesh.
3264    * If there are no faces in original mesh, keep materials and flags unchanged. */
3265   MPoly *mpoly;
3266   MPoly mp_example = {0};
3267   mpoly = orgmesh->mpoly;
3268   if (mpoly) {
3269     mp_example = *mpoly;
3270   }
3271 
3272   const short mp_mat_nr = mp_example.mat_nr;
3273   const char mp_flag = mp_example.flag;
3274 
3275   int i;
3276   int num_verts, num_normals, num_faces;
3277 
3278   if (!fds->fluid) {
3279     return NULL;
3280   }
3281 
3282   num_verts = manta_liquid_get_num_verts(fds->fluid);
3283   num_normals = manta_liquid_get_num_normals(fds->fluid);
3284   num_faces = manta_liquid_get_num_triangles(fds->fluid);
3285 
3286 #  ifdef DEBUG_PRINT
3287   /* Debugging: Print number of vertices, normals, and faces. */
3288   printf("num_verts: %d, num_normals: %d, num_faces: %d\n", num_verts, num_normals, num_faces);
3289 #  endif
3290 
3291   if (!num_verts || !num_faces) {
3292     return NULL;
3293   }
3294   /* Normals are per vertex, so these must match. */
3295   BLI_assert(num_verts == num_normals);
3296 
3297   /* If needed, vertex velocities will be read too. */
3298   bool use_speedvectors = fds->flags & FLUID_DOMAIN_USE_SPEED_VECTORS;
3299   FluidDomainVertexVelocity *velarray = NULL;
3300   float time_mult = 25.f * DT_DEFAULT;
3301 
3302   if (use_speedvectors) {
3303     if (fds->mesh_velocities) {
3304       MEM_freeN(fds->mesh_velocities);
3305     }
3306 
3307     fds->mesh_velocities = MEM_calloc_arrayN(
3308         num_verts, sizeof(FluidDomainVertexVelocity), "fluid_mesh_vertvelocities");
3309     fds->totvert = num_verts;
3310     velarray = fds->mesh_velocities;
3311   }
3312 
3313   me = BKE_mesh_new_nomain(num_verts, 0, 0, num_faces * 3, num_faces);
3314   if (!me) {
3315     return NULL;
3316   }
3317   mverts = me->mvert;
3318   mpolys = me->mpoly;
3319   mloops = me->mloop;
3320 
3321   /* Get size (dimension) but considering scaling scaling. */
3322   copy_v3_v3(cell_size_scaled, fds->cell_size);
3323   mul_v3_v3(cell_size_scaled, ob->scale);
3324   madd_v3fl_v3fl_v3fl_v3i(min, fds->p0, cell_size_scaled, fds->res_min);
3325   madd_v3fl_v3fl_v3fl_v3i(max, fds->p0, cell_size_scaled, fds->res_max);
3326   sub_v3_v3v3(size, max, min);
3327 
3328   /* Biggest dimension will be used for upscaling. */
3329   float max_size = MAX3(size[0], size[1], size[2]);
3330 
3331   float co_scale[3];
3332   co_scale[0] = max_size / ob->scale[0];
3333   co_scale[1] = max_size / ob->scale[1];
3334   co_scale[2] = max_size / ob->scale[2];
3335 
3336   float co_offset[3];
3337   co_offset[0] = (fds->p0[0] + fds->p1[0]) / 2.0f;
3338   co_offset[1] = (fds->p0[1] + fds->p1[1]) / 2.0f;
3339   co_offset[2] = (fds->p0[2] + fds->p1[2]) / 2.0f;
3340 
3341   /* Normals. */
3342   normals = MEM_callocN(sizeof(short[3]) * num_normals, "Fluidmesh_tmp_normals");
3343 
3344   /* Loop for vertices and normals. */
3345   for (i = 0, no_s = normals; i < num_verts && i < num_normals; i++, mverts++, no_s += 3) {
3346 
3347     /* Vertices (data is normalized cube around domain origin). */
3348     mverts->co[0] = manta_liquid_get_vertex_x_at(fds->fluid, i);
3349     mverts->co[1] = manta_liquid_get_vertex_y_at(fds->fluid, i);
3350     mverts->co[2] = manta_liquid_get_vertex_z_at(fds->fluid, i);
3351 
3352     /* Adjust coordinates from Mantaflow to match viewport scaling. */
3353     float tmp[3] = {(float)fds->res[0], (float)fds->res[1], (float)fds->res[2]};
3354     /* Scale to unit cube around 0. */
3355     mul_v3_fl(tmp, fds->mesh_scale * 0.5f);
3356     sub_v3_v3(mverts->co, tmp);
3357     /* Apply scaling of domain object. */
3358     mul_v3_fl(mverts->co, fds->dx / fds->mesh_scale);
3359 
3360     mul_v3_v3(mverts->co, co_scale);
3361     add_v3_v3(mverts->co, co_offset);
3362 
3363 #  ifdef DEBUG_PRINT
3364     /* Debugging: Print coordinates of vertices. */
3365     printf("mverts->co[0]: %f, mverts->co[1]: %f, mverts->co[2]: %f\n",
3366            mverts->co[0],
3367            mverts->co[1],
3368            mverts->co[2]);
3369 #  endif
3370 
3371     /* Normals (data is normalized cube around domain origin). */
3372     no[0] = manta_liquid_get_normal_x_at(fds->fluid, i);
3373     no[1] = manta_liquid_get_normal_y_at(fds->fluid, i);
3374     no[2] = manta_liquid_get_normal_z_at(fds->fluid, i);
3375 
3376     normal_float_to_short_v3(no_s, no);
3377 #  ifdef DEBUG_PRINT
3378     /* Debugging: Print coordinates of normals. */
3379     printf("no_s[0]: %d, no_s[1]: %d, no_s[2]: %d\n", no_s[0], no_s[1], no_s[2]);
3380 #  endif
3381 
3382     if (use_speedvectors) {
3383       velarray[i].vel[0] = manta_liquid_get_vertvel_x_at(fds->fluid, i) * (fds->dx / time_mult);
3384       velarray[i].vel[1] = manta_liquid_get_vertvel_y_at(fds->fluid, i) * (fds->dx / time_mult);
3385       velarray[i].vel[2] = manta_liquid_get_vertvel_z_at(fds->fluid, i) * (fds->dx / time_mult);
3386 #  ifdef DEBUG_PRINT
3387       /* Debugging: Print velocities of vertices. */
3388       printf("velarray[%d].vel[0]: %f, velarray[%d].vel[1]: %f, velarray[%d].vel[2]: %f\n",
3389              i,
3390              velarray[i].vel[0],
3391              i,
3392              velarray[i].vel[1],
3393              i,
3394              velarray[i].vel[2]);
3395 #  endif
3396     }
3397   }
3398 
3399   /* Loop for triangles. */
3400   for (i = 0; i < num_faces; i++, mpolys++, mloops += 3) {
3401     /* Initialize from existing face. */
3402     mpolys->mat_nr = mp_mat_nr;
3403     mpolys->flag = mp_flag;
3404 
3405     mpolys->loopstart = i * 3;
3406     mpolys->totloop = 3;
3407 
3408     mloops[0].v = manta_liquid_get_triangle_x_at(fds->fluid, i);
3409     mloops[1].v = manta_liquid_get_triangle_y_at(fds->fluid, i);
3410     mloops[2].v = manta_liquid_get_triangle_z_at(fds->fluid, i);
3411 #  ifdef DEBUG_PRINT
3412     /* Debugging: Print mesh faces. */
3413     printf("mloops[0].v: %d, mloops[1].v: %d, mloops[2].v: %d\n",
3414            mloops[0].v,
3415            mloops[1].v,
3416            mloops[2].v);
3417 #  endif
3418   }
3419 
3420   BKE_mesh_ensure_normals(me);
3421   BKE_mesh_calc_edges(me, false, false);
3422   BKE_mesh_vert_normals_apply(me, (short(*)[3])normals);
3423 
3424   MEM_freeN(normals);
3425 
3426   return me;
3427 }
3428 
create_smoke_geometry(FluidDomainSettings * fds,Mesh * orgmesh,Object * ob)3429 static Mesh *create_smoke_geometry(FluidDomainSettings *fds, Mesh *orgmesh, Object *ob)
3430 {
3431   Mesh *result;
3432   MVert *mverts;
3433   MPoly *mpolys;
3434   MLoop *mloops;
3435   float min[3];
3436   float max[3];
3437   float *co;
3438   MPoly *mp;
3439   MLoop *ml;
3440 
3441   int num_verts = 8;
3442   int num_faces = 6;
3443   float ob_loc[3] = {0};
3444   float ob_cache_loc[3] = {0};
3445 
3446   /* Just copy existing mesh if there is no content or if the adaptive domain is not being used. */
3447   if (fds->total_cells <= 1 || (fds->flags & FLUID_DOMAIN_USE_ADAPTIVE_DOMAIN) == 0) {
3448     return BKE_mesh_copy_for_eval(orgmesh, false);
3449   }
3450 
3451   result = BKE_mesh_new_nomain(num_verts, 0, 0, num_faces * 4, num_faces);
3452   mverts = result->mvert;
3453   mpolys = result->mpoly;
3454   mloops = result->mloop;
3455 
3456   if (num_verts) {
3457     /* Volume bounds. */
3458     madd_v3fl_v3fl_v3fl_v3i(min, fds->p0, fds->cell_size, fds->res_min);
3459     madd_v3fl_v3fl_v3fl_v3i(max, fds->p0, fds->cell_size, fds->res_max);
3460 
3461     /* Set vertices of smoke BB. Especially important, when BB changes (adaptive domain). */
3462     /* Top slab */
3463     co = mverts[0].co;
3464     co[0] = min[0];
3465     co[1] = min[1];
3466     co[2] = max[2];
3467     co = mverts[1].co;
3468     co[0] = max[0];
3469     co[1] = min[1];
3470     co[2] = max[2];
3471     co = mverts[2].co;
3472     co[0] = max[0];
3473     co[1] = max[1];
3474     co[2] = max[2];
3475     co = mverts[3].co;
3476     co[0] = min[0];
3477     co[1] = max[1];
3478     co[2] = max[2];
3479     /* Bottom slab. */
3480     co = mverts[4].co;
3481     co[0] = min[0];
3482     co[1] = min[1];
3483     co[2] = min[2];
3484     co = mverts[5].co;
3485     co[0] = max[0];
3486     co[1] = min[1];
3487     co[2] = min[2];
3488     co = mverts[6].co;
3489     co[0] = max[0];
3490     co[1] = max[1];
3491     co[2] = min[2];
3492     co = mverts[7].co;
3493     co[0] = min[0];
3494     co[1] = max[1];
3495     co[2] = min[2];
3496 
3497     /* Create faces. */
3498     /* Top side. */
3499     mp = &mpolys[0];
3500     ml = &mloops[0 * 4];
3501     mp->loopstart = 0 * 4;
3502     mp->totloop = 4;
3503     ml[0].v = 0;
3504     ml[1].v = 1;
3505     ml[2].v = 2;
3506     ml[3].v = 3;
3507     /* Right side. */
3508     mp = &mpolys[1];
3509     ml = &mloops[1 * 4];
3510     mp->loopstart = 1 * 4;
3511     mp->totloop = 4;
3512     ml[0].v = 2;
3513     ml[1].v = 1;
3514     ml[2].v = 5;
3515     ml[3].v = 6;
3516     /* Bottom side. */
3517     mp = &mpolys[2];
3518     ml = &mloops[2 * 4];
3519     mp->loopstart = 2 * 4;
3520     mp->totloop = 4;
3521     ml[0].v = 7;
3522     ml[1].v = 6;
3523     ml[2].v = 5;
3524     ml[3].v = 4;
3525     /* Left side. */
3526     mp = &mpolys[3];
3527     ml = &mloops[3 * 4];
3528     mp->loopstart = 3 * 4;
3529     mp->totloop = 4;
3530     ml[0].v = 0;
3531     ml[1].v = 3;
3532     ml[2].v = 7;
3533     ml[3].v = 4;
3534     /* Front side. */
3535     mp = &mpolys[4];
3536     ml = &mloops[4 * 4];
3537     mp->loopstart = 4 * 4;
3538     mp->totloop = 4;
3539     ml[0].v = 3;
3540     ml[1].v = 2;
3541     ml[2].v = 6;
3542     ml[3].v = 7;
3543     /* Back side. */
3544     mp = &mpolys[5];
3545     ml = &mloops[5 * 4];
3546     mp->loopstart = 5 * 4;
3547     mp->totloop = 4;
3548     ml[0].v = 1;
3549     ml[1].v = 0;
3550     ml[2].v = 4;
3551     ml[3].v = 5;
3552 
3553     /* Calculate required shift to match domain's global position
3554      * it was originally simulated at (if object moves without manta step). */
3555     invert_m4_m4(ob->imat, ob->obmat);
3556     mul_m4_v3(ob->obmat, ob_loc);
3557     mul_m4_v3(fds->obmat, ob_cache_loc);
3558     sub_v3_v3v3(fds->obj_shift_f, ob_cache_loc, ob_loc);
3559     /* Convert shift to local space and apply to vertices. */
3560     mul_mat3_m4_v3(ob->imat, fds->obj_shift_f);
3561     /* Apply shift to vertices. */
3562     for (int i = 0; i < num_verts; i++) {
3563       add_v3_v3(mverts[i].co, fds->obj_shift_f);
3564     }
3565   }
3566 
3567   BKE_mesh_calc_edges(result, false, false);
3568   result->runtime.cd_dirty_vert |= CD_MASK_NORMAL;
3569   return result;
3570 }
3571 
manta_step(Depsgraph * depsgraph,Scene * scene,Object * ob,Mesh * me,FluidModifierData * fmd,int frame)3572 static int manta_step(
3573     Depsgraph *depsgraph, Scene *scene, Object *ob, Mesh *me, FluidModifierData *fmd, int frame)
3574 {
3575   FluidDomainSettings *fds = fmd->domain;
3576   float dt, frame_length, time_total, time_total_old;
3577   float time_per_frame;
3578   bool init_resolution = true;
3579 
3580   /* Store baking success - bake might be aborted anytime by user. */
3581   int result = 1;
3582   int mode = fds->cache_type;
3583   bool mode_replay = (mode == FLUID_DOMAIN_CACHE_REPLAY);
3584 
3585   /* Update object state. */
3586   invert_m4_m4(fds->imat, ob->obmat);
3587   copy_m4_m4(fds->obmat, ob->obmat);
3588 
3589   /* Gas domain might use adaptive domain. */
3590   if (fds->type == FLUID_DOMAIN_TYPE_GAS) {
3591     init_resolution = (fds->flags & FLUID_DOMAIN_USE_ADAPTIVE_DOMAIN) != 0;
3592   }
3593   manta_set_domain_from_mesh(fds, ob, me, init_resolution);
3594 
3595   /* Use local variables for adaptive loop, dt can change. */
3596   frame_length = fds->frame_length;
3597   dt = fds->dt;
3598   time_per_frame = 0;
3599   time_total = fds->time_total;
3600   /* Keep track of original total time to correct small errors at end of step. */
3601   time_total_old = fds->time_total;
3602 
3603   BLI_mutex_lock(&object_update_lock);
3604 
3605   /* Loop as long as time_per_frame (sum of sub dt's) does not exceed actual framelength. */
3606   while (time_per_frame + FLT_EPSILON < frame_length) {
3607     manta_adapt_timestep(fds->fluid);
3608     dt = manta_get_timestep(fds->fluid);
3609 
3610     /* Save adapted dt so that MANTA object can access it (important when adaptive domain creates
3611      * new MANTA object). */
3612     fds->dt = dt;
3613 
3614     /* Calculate inflow geometry. */
3615     update_flowsfluids(depsgraph, scene, ob, fds, time_per_frame, frame_length, frame, dt);
3616 
3617     /* If user requested stop, quit baking */
3618     if (G.is_break && !mode_replay) {
3619       result = 0;
3620       break;
3621     }
3622 
3623     manta_update_variables(fds->fluid, fmd);
3624 
3625     /* Calculate obstacle geometry. */
3626     update_obstacles(depsgraph, scene, ob, fds, time_per_frame, frame_length, frame, dt);
3627 
3628     /* If user requested stop, quit baking */
3629     if (G.is_break && !mode_replay) {
3630       result = 0;
3631       break;
3632     }
3633 
3634     /* Only bake if the domain is bigger than one cell (important for adaptive domain). */
3635     if (fds->total_cells > 1) {
3636       update_effectors(depsgraph, scene, ob, fds, dt);
3637       manta_bake_data(fds->fluid, fmd, frame);
3638     }
3639 
3640     /* Count for how long this while loop is running. */
3641     time_per_frame += dt;
3642     time_total += dt;
3643 
3644     fds->time_per_frame = time_per_frame;
3645     fds->time_total = time_total;
3646   }
3647 
3648   /* Total time must not exceed framecount times framelength. Correct tiny errors here. */
3649   CLAMP(fds->time_total, fds->time_total, time_total_old + fds->frame_length);
3650 
3651   /* Compute shadow grid for gas simulations. Make sure to skip if bake job was canceled early. */
3652   if (fds->type == FLUID_DOMAIN_TYPE_GAS && result) {
3653     manta_smoke_calc_transparency(fds, DEG_get_evaluated_view_layer(depsgraph));
3654   }
3655 
3656   BLI_mutex_unlock(&object_update_lock);
3657   return result;
3658 }
3659 
manta_guiding(Depsgraph * depsgraph,Scene * scene,Object * ob,FluidModifierData * fmd,int frame)3660 static void manta_guiding(
3661     Depsgraph *depsgraph, Scene *scene, Object *ob, FluidModifierData *fmd, int frame)
3662 {
3663   FluidDomainSettings *fds = fmd->domain;
3664   float fps = scene->r.frs_sec / scene->r.frs_sec_base;
3665   float dt = DT_DEFAULT * (25.0f / fps) * fds->time_scale;
3666 
3667   BLI_mutex_lock(&object_update_lock);
3668 
3669   update_obstacles(depsgraph, scene, ob, fds, dt, dt, frame, dt);
3670   manta_bake_guiding(fds->fluid, fmd, frame);
3671 
3672   BLI_mutex_unlock(&object_update_lock);
3673 }
3674 
BKE_fluid_modifier_processFlow(FluidModifierData * fmd,Depsgraph * depsgraph,Scene * scene,Object * ob,Mesh * me,const int scene_framenr)3675 static void BKE_fluid_modifier_processFlow(FluidModifierData *fmd,
3676                                            Depsgraph *depsgraph,
3677                                            Scene *scene,
3678                                            Object *ob,
3679                                            Mesh *me,
3680                                            const int scene_framenr)
3681 {
3682   if (scene_framenr >= fmd->time) {
3683     BKE_fluid_modifier_init(fmd, depsgraph, ob, scene, me);
3684   }
3685 
3686   if (fmd->flow) {
3687     if (fmd->flow->mesh) {
3688       BKE_id_free(NULL, fmd->flow->mesh);
3689     }
3690     fmd->flow->mesh = BKE_mesh_copy_for_eval(me, false);
3691   }
3692 
3693   if (scene_framenr > fmd->time) {
3694     fmd->time = scene_framenr;
3695   }
3696   else if (scene_framenr < fmd->time) {
3697     fmd->time = scene_framenr;
3698     BKE_fluid_modifier_reset_ex(fmd, false);
3699   }
3700 }
3701 
BKE_fluid_modifier_processEffector(FluidModifierData * fmd,Depsgraph * depsgraph,Scene * scene,Object * ob,Mesh * me,const int scene_framenr)3702 static void BKE_fluid_modifier_processEffector(FluidModifierData *fmd,
3703                                                Depsgraph *depsgraph,
3704                                                Scene *scene,
3705                                                Object *ob,
3706                                                Mesh *me,
3707                                                const int scene_framenr)
3708 {
3709   if (scene_framenr >= fmd->time) {
3710     BKE_fluid_modifier_init(fmd, depsgraph, ob, scene, me);
3711   }
3712 
3713   if (fmd->effector) {
3714     if (fmd->effector->mesh) {
3715       BKE_id_free(NULL, fmd->effector->mesh);
3716     }
3717     fmd->effector->mesh = BKE_mesh_copy_for_eval(me, false);
3718   }
3719 
3720   if (scene_framenr > fmd->time) {
3721     fmd->time = scene_framenr;
3722   }
3723   else if (scene_framenr < fmd->time) {
3724     fmd->time = scene_framenr;
3725     BKE_fluid_modifier_reset_ex(fmd, false);
3726   }
3727 }
3728 
BKE_fluid_modifier_processDomain(FluidModifierData * fmd,Depsgraph * depsgraph,Scene * scene,Object * ob,Mesh * me,const int scene_framenr)3729 static void BKE_fluid_modifier_processDomain(FluidModifierData *fmd,
3730                                              Depsgraph *depsgraph,
3731                                              Scene *scene,
3732                                              Object *ob,
3733                                              Mesh *me,
3734                                              const int scene_framenr)
3735 {
3736   FluidDomainSettings *fds = fmd->domain;
3737   Object *guide_parent = NULL;
3738   Object **objs = NULL;
3739   uint numobj = 0;
3740   FluidModifierData *fmd_parent = NULL;
3741 
3742   bool is_startframe, has_advanced;
3743   is_startframe = (scene_framenr == fds->cache_frame_start);
3744   has_advanced = (scene_framenr == fmd->time + 1);
3745   int mode = fds->cache_type;
3746 
3747   /* Do not process modifier if current frame is out of cache range. */
3748   bool escape = false;
3749   switch (mode) {
3750     case FLUID_DOMAIN_CACHE_ALL:
3751     case FLUID_DOMAIN_CACHE_MODULAR:
3752       if (fds->cache_frame_offset > 0) {
3753         if (scene_framenr < fds->cache_frame_start ||
3754             scene_framenr > fds->cache_frame_end + fds->cache_frame_offset) {
3755           escape = true;
3756         }
3757       }
3758       else {
3759         if (scene_framenr < fds->cache_frame_start + fds->cache_frame_offset ||
3760             scene_framenr > fds->cache_frame_end) {
3761           escape = true;
3762         }
3763       }
3764       break;
3765     case FLUID_DOMAIN_CACHE_REPLAY:
3766     default:
3767       if (scene_framenr < fds->cache_frame_start || scene_framenr > fds->cache_frame_end) {
3768         escape = true;
3769       }
3770       break;
3771   }
3772   /* If modifier will not be processed, update/flush pointers from (old) fluid object once more. */
3773   if (escape && fds->fluid) {
3774     manta_update_pointers(fds->fluid, fmd, true);
3775     return;
3776   }
3777 
3778   /* Reset fluid if no fluid present. Also resets active fields. */
3779   if (!fds->fluid) {
3780     BKE_fluid_modifier_reset_ex(fmd, false);
3781   }
3782 
3783   /* Ensure cache directory is not relative. */
3784   const char *relbase = BKE_modifier_path_relbase_from_global(ob);
3785   BLI_path_abs(fds->cache_directory, relbase);
3786 
3787   /* Ensure that all flags are up to date before doing any baking and/or cache reading. */
3788   objs = BKE_collision_objects_create(
3789       depsgraph, ob, fds->fluid_group, &numobj, eModifierType_Fluid);
3790   update_flowsflags(fds, objs, numobj);
3791   if (objs) {
3792     MEM_freeN(objs);
3793   }
3794   objs = BKE_collision_objects_create(
3795       depsgraph, ob, fds->effector_group, &numobj, eModifierType_Fluid);
3796   update_obstacleflags(fds, objs, numobj);
3797   if (objs) {
3798     MEM_freeN(objs);
3799   }
3800 
3801   /* TODO(sebbas): Cache reset for when flow / effector object need update flag is set. */
3802 #  if 0
3803   /* If the just updated flags now carry the 'outdated' flag, reset the cache here!
3804    * Plus sanity check: Do not clear cache on file load. */
3805   if (fds->cache_flag & FLUID_DOMAIN_OUTDATED_DATA &&
3806       ((fds->flags & FLUID_DOMAIN_FILE_LOAD) == 0)) {
3807     BKE_fluid_cache_free_all(fds, ob);
3808     BKE_fluid_modifier_reset_ex(fmd, false);
3809   }
3810 #  endif
3811 
3812   /* Fluid domain init must not fail in order to continue modifier evaluation. */
3813   if (!fds->fluid && !BKE_fluid_modifier_init(fmd, depsgraph, ob, scene, me)) {
3814     CLOG_ERROR(&LOG, "Fluid initialization failed. Should not happen!");
3815     return;
3816   }
3817   BLI_assert(fds->fluid);
3818 
3819   /* Guiding parent res pointer needs initialization. */
3820   guide_parent = fds->guide_parent;
3821   if (guide_parent) {
3822     fmd_parent = (FluidModifierData *)BKE_modifiers_findby_type(guide_parent, eModifierType_Fluid);
3823     if (fmd_parent && fmd_parent->domain) {
3824       copy_v3_v3_int(fds->guide_res, fmd_parent->domain->res);
3825     }
3826   }
3827 
3828   /* Adaptive domain needs to know about current state, so save it here. */
3829   int o_res[3], o_min[3], o_max[3], o_shift[3];
3830   copy_v3_v3_int(o_res, fds->res);
3831   copy_v3_v3_int(o_min, fds->res_min);
3832   copy_v3_v3_int(o_max, fds->res_max);
3833   copy_v3_v3_int(o_shift, fds->shift);
3834 
3835   /* Ensure that time parameters are initialized correctly before every step. */
3836   float fps = scene->r.frs_sec / scene->r.frs_sec_base;
3837   fds->frame_length = DT_DEFAULT * (25.0f / fps) * fds->time_scale;
3838   fds->dt = fds->frame_length;
3839   fds->time_per_frame = 0;
3840 
3841   /* Ensure that gravity is copied over every frame (could be keyframed). */
3842   update_final_gravity(fds, scene);
3843 
3844   int next_frame = scene_framenr + 1;
3845   int prev_frame = scene_framenr - 1;
3846   /* Ensure positive of previous frame. */
3847   CLAMP_MIN(prev_frame, fds->cache_frame_start);
3848 
3849   int data_frame = scene_framenr, noise_frame = scene_framenr;
3850   int mesh_frame = scene_framenr, particles_frame = scene_framenr, guide_frame = scene_framenr;
3851 
3852   bool with_smoke, with_liquid;
3853   with_smoke = fds->type == FLUID_DOMAIN_TYPE_GAS;
3854   with_liquid = fds->type == FLUID_DOMAIN_TYPE_LIQUID;
3855 
3856   bool drops, bubble, floater;
3857   drops = fds->particle_type & FLUID_DOMAIN_PARTICLE_SPRAY;
3858   bubble = fds->particle_type & FLUID_DOMAIN_PARTICLE_BUBBLE;
3859   floater = fds->particle_type & FLUID_DOMAIN_PARTICLE_FOAM;
3860 
3861   bool with_resumable_cache = fds->flags & FLUID_DOMAIN_USE_RESUMABLE_CACHE;
3862   bool with_script, with_noise, with_mesh, with_particles, with_guide;
3863   with_script = fds->flags & FLUID_DOMAIN_EXPORT_MANTA_SCRIPT;
3864   with_noise = fds->flags & FLUID_DOMAIN_USE_NOISE;
3865   with_mesh = fds->flags & FLUID_DOMAIN_USE_MESH;
3866   with_guide = fds->flags & FLUID_DOMAIN_USE_GUIDE;
3867   with_particles = drops || bubble || floater;
3868 
3869   bool has_data, has_noise, has_mesh, has_particles, has_guide, has_config;
3870   has_data = manta_has_data(fds->fluid, fmd, scene_framenr);
3871   has_noise = manta_has_noise(fds->fluid, fmd, scene_framenr);
3872   has_mesh = manta_has_mesh(fds->fluid, fmd, scene_framenr);
3873   has_particles = manta_has_particles(fds->fluid, fmd, scene_framenr);
3874   has_guide = manta_has_guiding(fds->fluid, fmd, scene_framenr, guide_parent);
3875   has_config = manta_read_config(fds->fluid, fmd, scene_framenr);
3876 
3877   /* When reading data from cache (has_config == true) ensure that active fields are allocated.
3878    * update_flowsflags() and update_obstacleflags() will not find flow sources hidden from renders.
3879    * See also: T72192. */
3880   if (has_config) {
3881     ensure_flowsfields(fds);
3882     ensure_obstaclefields(fds);
3883   }
3884 
3885   bool baking_data, baking_noise, baking_mesh, baking_particles, baking_guide;
3886   baking_data = fds->cache_flag & FLUID_DOMAIN_BAKING_DATA;
3887   baking_noise = fds->cache_flag & FLUID_DOMAIN_BAKING_NOISE;
3888   baking_mesh = fds->cache_flag & FLUID_DOMAIN_BAKING_MESH;
3889   baking_particles = fds->cache_flag & FLUID_DOMAIN_BAKING_PARTICLES;
3890   baking_guide = fds->cache_flag & FLUID_DOMAIN_BAKING_GUIDE;
3891 
3892   bool resume_data, resume_noise, resume_mesh, resume_particles, resume_guide;
3893   resume_data = (!is_startframe) && (fds->cache_frame_pause_data == scene_framenr);
3894   resume_noise = (!is_startframe) && (fds->cache_frame_pause_noise == scene_framenr);
3895   resume_mesh = (!is_startframe) && (fds->cache_frame_pause_mesh == scene_framenr);
3896   resume_particles = (!is_startframe) && (fds->cache_frame_pause_particles == scene_framenr);
3897   resume_guide = (!is_startframe) && (fds->cache_frame_pause_guide == scene_framenr);
3898 
3899   bool read_cache, bake_cache;
3900   read_cache = false;
3901   bake_cache = baking_data || baking_noise || baking_mesh || baking_particles || baking_guide;
3902 
3903   bool next_data, next_noise, next_mesh, next_particles, next_guide;
3904   next_data = manta_has_data(fds->fluid, fmd, next_frame);
3905   next_noise = manta_has_noise(fds->fluid, fmd, next_frame);
3906   next_mesh = manta_has_mesh(fds->fluid, fmd, next_frame);
3907   next_particles = manta_has_particles(fds->fluid, fmd, next_frame);
3908   next_guide = manta_has_guiding(fds->fluid, fmd, next_frame, guide_parent);
3909 
3910   bool prev_data, prev_noise, prev_mesh, prev_particles, prev_guide;
3911   prev_data = manta_has_data(fds->fluid, fmd, prev_frame);
3912   prev_noise = manta_has_noise(fds->fluid, fmd, prev_frame);
3913   prev_mesh = manta_has_mesh(fds->fluid, fmd, prev_frame);
3914   prev_particles = manta_has_particles(fds->fluid, fmd, prev_frame);
3915   prev_guide = manta_has_guiding(fds->fluid, fmd, prev_frame, guide_parent);
3916 
3917   /* Unused for now. */
3918   UNUSED_VARS(has_guide, prev_guide, next_mesh, next_guide);
3919 
3920   bool with_gdomain;
3921   with_gdomain = (fds->guide_source == FLUID_DOMAIN_GUIDE_SRC_DOMAIN);
3922 
3923   /* Cache mode specific settings. */
3924   switch (mode) {
3925     case FLUID_DOMAIN_CACHE_ALL:
3926     case FLUID_DOMAIN_CACHE_MODULAR:
3927       /* Just load the data that has already been baked */
3928       if (!baking_data && !baking_noise && !baking_mesh && !baking_particles && !baking_guide) {
3929         read_cache = true;
3930         bake_cache = false;
3931 
3932         /* Apply frame offset. */
3933         data_frame -= fmd->domain->cache_frame_offset;
3934         noise_frame -= fmd->domain->cache_frame_offset;
3935         mesh_frame -= fmd->domain->cache_frame_offset;
3936         particles_frame -= fmd->domain->cache_frame_offset;
3937         break;
3938       }
3939 
3940       /* Set to previous frame if the bake was resumed
3941        * ie don't read all of the already baked frames, just the one before bake resumes */
3942       if (baking_data && resume_data) {
3943         data_frame = prev_frame;
3944       }
3945       if (baking_noise && resume_noise) {
3946         noise_frame = prev_frame;
3947       }
3948       if (baking_mesh && resume_mesh) {
3949         mesh_frame = prev_frame;
3950       }
3951       if (baking_particles && resume_particles) {
3952         particles_frame = prev_frame;
3953       }
3954       if (baking_guide && resume_guide) {
3955         guide_frame = prev_frame;
3956       }
3957 
3958       /* Noise, mesh and particles can never be baked more than data. */
3959       CLAMP_MAX(noise_frame, data_frame);
3960       CLAMP_MAX(mesh_frame, data_frame);
3961       CLAMP_MAX(particles_frame, data_frame);
3962       CLAMP_MAX(guide_frame, fds->cache_frame_end);
3963 
3964       /* Force to read cache as we're resuming the bake */
3965       read_cache = true;
3966       break;
3967     case FLUID_DOMAIN_CACHE_REPLAY:
3968     default:
3969       baking_data = !has_data && (is_startframe || prev_data);
3970       if (with_smoke && with_noise) {
3971         baking_noise = !has_noise && (is_startframe || prev_noise);
3972       }
3973       if (with_liquid && with_mesh) {
3974         baking_mesh = !has_mesh && (is_startframe || prev_mesh);
3975       }
3976       if (with_liquid && with_particles) {
3977         baking_particles = !has_particles && (is_startframe || prev_particles);
3978       }
3979 
3980       /* Always trying to read the cache in replay mode. */
3981       read_cache = true;
3982       bake_cache = false;
3983       break;
3984   }
3985 
3986   bool read_partial = false, read_all = false;
3987   bool grid_display = fds->use_coba;
3988 
3989   /* Try to read from cache and keep track of read success. */
3990   if (read_cache) {
3991 
3992     /* Read mesh cache. */
3993     if (with_liquid && with_mesh) {
3994       if (mesh_frame != scene_framenr) {
3995         has_config = manta_read_config(fds->fluid, fmd, mesh_frame);
3996       }
3997 
3998       /* Update mesh data from file is faster than via Python (manta_read_mesh()). */
3999       has_mesh = manta_read_mesh(fds->fluid, fmd, mesh_frame);
4000     }
4001 
4002     /* Read particles cache. */
4003     if (with_liquid && with_particles) {
4004       if (particles_frame != scene_framenr) {
4005         has_config = manta_read_config(fds->fluid, fmd, particles_frame);
4006       }
4007 
4008       read_partial = !baking_data && !baking_particles && next_particles;
4009       read_all = !read_partial && with_resumable_cache;
4010       has_particles = manta_read_particles(fds->fluid, fmd, particles_frame, read_all);
4011     }
4012 
4013     /* Read guide cache. */
4014     if (with_guide) {
4015       FluidModifierData *fmd2 = (with_gdomain) ? fmd_parent : fmd;
4016       has_guide = manta_read_guiding(fds->fluid, fmd2, scene_framenr, with_gdomain);
4017     }
4018 
4019     /* Read noise and data cache */
4020     if (with_smoke && with_noise) {
4021       if (noise_frame != scene_framenr) {
4022         has_config = manta_read_config(fds->fluid, fmd, noise_frame);
4023       }
4024 
4025       /* Only reallocate when just reading cache or when resuming during bake. */
4026       if (has_data && has_config && manta_needs_realloc(fds->fluid, fmd)) {
4027         BKE_fluid_reallocate_copy_fluid(
4028             fds, o_res, fds->res, o_min, fds->res_min, o_max, o_shift, fds->shift);
4029       }
4030 
4031       read_partial = !baking_data && !baking_noise && next_noise;
4032       read_all = !read_partial && with_resumable_cache;
4033       has_noise = manta_read_noise(fds->fluid, fmd, noise_frame, read_all);
4034 
4035       read_partial = !baking_data && !baking_noise && next_data && next_noise;
4036       read_all = !read_partial && with_resumable_cache;
4037       has_data = manta_read_data(fds->fluid, fmd, data_frame, read_all);
4038     }
4039     /* Read data cache only */
4040     else {
4041       if (data_frame != scene_framenr) {
4042         has_config = manta_read_config(fds->fluid, fmd, data_frame);
4043       }
4044 
4045       if (with_smoke) {
4046         /* Read config and realloc fluid object if needed. */
4047         if (has_config && manta_needs_realloc(fds->fluid, fmd)) {
4048           BKE_fluid_reallocate_fluid(fds, fds->res, 1);
4049         }
4050       }
4051 
4052       read_partial = !baking_data && !baking_particles && !baking_mesh && next_data &&
4053                      !grid_display;
4054       read_all = !read_partial && with_resumable_cache;
4055       has_data = manta_read_data(fds->fluid, fmd, data_frame, read_all);
4056     }
4057   }
4058 
4059   /* Cache mode specific settings */
4060   switch (mode) {
4061     case FLUID_DOMAIN_CACHE_ALL:
4062     case FLUID_DOMAIN_CACHE_MODULAR:
4063       if (!baking_data && !baking_noise && !baking_mesh && !baking_particles && !baking_guide) {
4064         bake_cache = false;
4065       }
4066       break;
4067     case FLUID_DOMAIN_CACHE_REPLAY:
4068     default:
4069       baking_data = !has_data && (is_startframe || prev_data);
4070       if (with_smoke && with_noise) {
4071         baking_noise = !has_noise && (is_startframe || prev_noise);
4072       }
4073       if (with_liquid && with_mesh) {
4074         baking_mesh = !has_mesh && (is_startframe || prev_mesh);
4075       }
4076       if (with_liquid && with_particles) {
4077         baking_particles = !has_particles && (is_startframe || prev_particles);
4078       }
4079 
4080       /* Only bake if time advanced by one frame. */
4081       if (is_startframe || has_advanced) {
4082         bake_cache = baking_data || baking_noise || baking_mesh || baking_particles;
4083       }
4084       break;
4085   }
4086 
4087   /* Trigger bake calls individually */
4088   if (bake_cache) {
4089     /* Ensure fresh variables at every animation step */
4090     manta_update_variables(fds->fluid, fmd);
4091 
4092     /* Export mantaflow python script on first frame (once only) and for any bake type */
4093     if (with_script && is_startframe) {
4094       if (with_smoke) {
4095         manta_smoke_export_script(fmd->domain->fluid, fmd);
4096       }
4097       if (with_liquid) {
4098         manta_liquid_export_script(fmd->domain->fluid, fmd);
4099       }
4100     }
4101 
4102     if (baking_guide && with_guide) {
4103       manta_guiding(depsgraph, scene, ob, fmd, scene_framenr);
4104     }
4105     if (baking_data) {
4106       /* Only save baked data if all of it completed successfully. */
4107       if (manta_step(depsgraph, scene, ob, me, fmd, scene_framenr)) {
4108         manta_write_config(fds->fluid, fmd, scene_framenr);
4109         manta_write_data(fds->fluid, fmd, scene_framenr);
4110       }
4111     }
4112     if (has_data || baking_data) {
4113       if (baking_noise && with_smoke && with_noise) {
4114         /* Ensure that no bake occurs if domain was minimized by adaptive domain. */
4115         if (fds->total_cells > 1) {
4116           manta_bake_noise(fds->fluid, fmd, scene_framenr);
4117         }
4118         manta_write_noise(fds->fluid, fmd, scene_framenr);
4119       }
4120       if (baking_mesh && with_liquid && with_mesh) {
4121         manta_bake_mesh(fds->fluid, fmd, scene_framenr);
4122       }
4123       if (baking_particles && with_liquid && with_particles) {
4124         manta_bake_particles(fds->fluid, fmd, scene_framenr);
4125       }
4126     }
4127   }
4128 
4129   /* Ensure that fluid pointers are always up to date at the end of modifier processing. */
4130   manta_update_pointers(fds->fluid, fmd, false);
4131 
4132   fds->flags &= ~FLUID_DOMAIN_FILE_LOAD;
4133   fmd->time = scene_framenr;
4134 }
4135 
BKE_fluid_modifier_process(FluidModifierData * fmd,Depsgraph * depsgraph,Scene * scene,Object * ob,Mesh * me)4136 static void BKE_fluid_modifier_process(
4137     FluidModifierData *fmd, Depsgraph *depsgraph, Scene *scene, Object *ob, Mesh *me)
4138 {
4139   const int scene_framenr = (int)DEG_get_ctime(depsgraph);
4140 
4141   if ((fmd->type & MOD_FLUID_TYPE_FLOW)) {
4142     BKE_fluid_modifier_processFlow(fmd, depsgraph, scene, ob, me, scene_framenr);
4143   }
4144   else if (fmd->type & MOD_FLUID_TYPE_EFFEC) {
4145     BKE_fluid_modifier_processEffector(fmd, depsgraph, scene, ob, me, scene_framenr);
4146   }
4147   else if (fmd->type & MOD_FLUID_TYPE_DOMAIN) {
4148     BKE_fluid_modifier_processDomain(fmd, depsgraph, scene, ob, me, scene_framenr);
4149   }
4150 }
4151 
BKE_fluid_modifier_do(FluidModifierData * fmd,Depsgraph * depsgraph,Scene * scene,Object * ob,Mesh * me)4152 struct Mesh *BKE_fluid_modifier_do(
4153     FluidModifierData *fmd, Depsgraph *depsgraph, Scene *scene, Object *ob, Mesh *me)
4154 {
4155   /* Optimization: Do not update viewport during bakes (except in replay mode)
4156    * Reason: UI is locked and updated liquid / smoke geometry is not visible anyways. */
4157   bool needs_viewport_update = false;
4158 
4159   /* Optimization: Only process modifier if object is not being altered. */
4160   if (!G.moving) {
4161     /* Lock so preview render does not read smoke data while it gets modified. */
4162     if ((fmd->type & MOD_FLUID_TYPE_DOMAIN) && fmd->domain) {
4163       BLI_rw_mutex_lock(fmd->domain->fluid_mutex, THREAD_LOCK_WRITE);
4164     }
4165 
4166     BKE_fluid_modifier_process(fmd, depsgraph, scene, ob, me);
4167 
4168     if ((fmd->type & MOD_FLUID_TYPE_DOMAIN) && fmd->domain) {
4169       BLI_rw_mutex_unlock(fmd->domain->fluid_mutex);
4170     }
4171 
4172     if (fmd->domain) {
4173       FluidDomainSettings *fds = fmd->domain;
4174 
4175       /* Always update viewport in cache replay mode. */
4176       if (fds->cache_type == FLUID_DOMAIN_CACHE_REPLAY ||
4177           fds->flags & FLUID_DOMAIN_USE_ADAPTIVE_DOMAIN) {
4178         needs_viewport_update = true;
4179       }
4180       /* In other cache modes, only update the viewport when no bake is going on. */
4181       else {
4182         bool with_mesh;
4183         with_mesh = fds->flags & FLUID_DOMAIN_USE_MESH;
4184         bool baking_data, baking_noise, baking_mesh, baking_particles, baking_guide;
4185         baking_data = fds->cache_flag & FLUID_DOMAIN_BAKING_DATA;
4186         baking_noise = fds->cache_flag & FLUID_DOMAIN_BAKING_NOISE;
4187         baking_mesh = fds->cache_flag & FLUID_DOMAIN_BAKING_MESH;
4188         baking_particles = fds->cache_flag & FLUID_DOMAIN_BAKING_PARTICLES;
4189         baking_guide = fds->cache_flag & FLUID_DOMAIN_BAKING_GUIDE;
4190 
4191         if (with_mesh && !baking_data && !baking_noise && !baking_mesh && !baking_particles &&
4192             !baking_guide) {
4193           needs_viewport_update = true;
4194         }
4195       }
4196     }
4197   }
4198 
4199   Mesh *result = NULL;
4200   if (fmd->type & MOD_FLUID_TYPE_DOMAIN && fmd->domain) {
4201     if (needs_viewport_update) {
4202       /* Return generated geometry depending on domain type. */
4203       if (fmd->domain->type == FLUID_DOMAIN_TYPE_LIQUID) {
4204         result = create_liquid_geometry(fmd->domain, me, ob);
4205       }
4206       if (fmd->domain->type == FLUID_DOMAIN_TYPE_GAS) {
4207         result = create_smoke_geometry(fmd->domain, me, ob);
4208       }
4209     }
4210 
4211     /* Clear flag outside of locked block (above). */
4212     fmd->domain->cache_flag &= ~FLUID_DOMAIN_OUTDATED_DATA;
4213     fmd->domain->cache_flag &= ~FLUID_DOMAIN_OUTDATED_NOISE;
4214     fmd->domain->cache_flag &= ~FLUID_DOMAIN_OUTDATED_MESH;
4215     fmd->domain->cache_flag &= ~FLUID_DOMAIN_OUTDATED_PARTICLES;
4216     fmd->domain->cache_flag &= ~FLUID_DOMAIN_OUTDATED_GUIDE;
4217   }
4218 
4219   if (!result) {
4220     result = BKE_mesh_copy_for_eval(me, false);
4221   }
4222   else {
4223     BKE_mesh_copy_settings(result, me);
4224   }
4225 
4226   /* Liquid simulation has a texture space that based on the bounds of the fluid mesh.
4227    * This does not seem particularly useful, but it's backwards compatible.
4228    *
4229    * Smoke simulation needs a texture space relative to the adaptive domain bounds, not the
4230    * original mesh. So recompute it at this point in the modifier stack. See T58492. */
4231   BKE_mesh_texspace_calc(result);
4232 
4233   return result;
4234 }
4235 
calc_voxel_transp(float * result,const float * input,int res[3],int * pixel,float * t_ray,float correct)4236 static float calc_voxel_transp(
4237     float *result, const float *input, int res[3], int *pixel, float *t_ray, float correct)
4238 {
4239   const size_t index = manta_get_index(pixel[0], res[0], pixel[1], res[1], pixel[2]);
4240 
4241   // T_ray *= T_vox
4242   *t_ray *= expf(input[index] * correct);
4243 
4244   if (result[index] < 0.0f) {
4245     result[index] = *t_ray;
4246   }
4247 
4248   return *t_ray;
4249 }
4250 
bresenham_linie_3D(int x1,int y1,int z1,int x2,int y2,int z2,float * t_ray,BKE_Fluid_BresenhamFn cb,float * result,float * input,int res[3],float correct)4251 static void bresenham_linie_3D(int x1,
4252                                int y1,
4253                                int z1,
4254                                int x2,
4255                                int y2,
4256                                int z2,
4257                                float *t_ray,
4258                                BKE_Fluid_BresenhamFn cb,
4259                                float *result,
4260                                float *input,
4261                                int res[3],
4262                                float correct)
4263 {
4264   int dx, dy, dz, i, l, m, n, x_inc, y_inc, z_inc, err_1, err_2, dx2, dy2, dz2;
4265   int pixel[3];
4266 
4267   pixel[0] = x1;
4268   pixel[1] = y1;
4269   pixel[2] = z1;
4270 
4271   dx = x2 - x1;
4272   dy = y2 - y1;
4273   dz = z2 - z1;
4274 
4275   x_inc = (dx < 0) ? -1 : 1;
4276   l = abs(dx);
4277   y_inc = (dy < 0) ? -1 : 1;
4278   m = abs(dy);
4279   z_inc = (dz < 0) ? -1 : 1;
4280   n = abs(dz);
4281   dx2 = l << 1;
4282   dy2 = m << 1;
4283   dz2 = n << 1;
4284 
4285   if ((l >= m) && (l >= n)) {
4286     err_1 = dy2 - l;
4287     err_2 = dz2 - l;
4288     for (i = 0; i < l; i++) {
4289       if (cb(result, input, res, pixel, t_ray, correct) <= FLT_EPSILON) {
4290         break;
4291       }
4292       if (err_1 > 0) {
4293         pixel[1] += y_inc;
4294         err_1 -= dx2;
4295       }
4296       if (err_2 > 0) {
4297         pixel[2] += z_inc;
4298         err_2 -= dx2;
4299       }
4300       err_1 += dy2;
4301       err_2 += dz2;
4302       pixel[0] += x_inc;
4303     }
4304   }
4305   else if ((m >= l) && (m >= n)) {
4306     err_1 = dx2 - m;
4307     err_2 = dz2 - m;
4308     for (i = 0; i < m; i++) {
4309       if (cb(result, input, res, pixel, t_ray, correct) <= FLT_EPSILON) {
4310         break;
4311       }
4312       if (err_1 > 0) {
4313         pixel[0] += x_inc;
4314         err_1 -= dy2;
4315       }
4316       if (err_2 > 0) {
4317         pixel[2] += z_inc;
4318         err_2 -= dy2;
4319       }
4320       err_1 += dx2;
4321       err_2 += dz2;
4322       pixel[1] += y_inc;
4323     }
4324   }
4325   else {
4326     err_1 = dy2 - n;
4327     err_2 = dx2 - n;
4328     for (i = 0; i < n; i++) {
4329       if (cb(result, input, res, pixel, t_ray, correct) <= FLT_EPSILON) {
4330         break;
4331       }
4332       if (err_1 > 0) {
4333         pixel[1] += y_inc;
4334         err_1 -= dz2;
4335       }
4336       if (err_2 > 0) {
4337         pixel[0] += x_inc;
4338         err_2 -= dz2;
4339       }
4340       err_1 += dy2;
4341       err_2 += dx2;
4342       pixel[2] += z_inc;
4343     }
4344   }
4345   cb(result, input, res, pixel, t_ray, correct);
4346 }
4347 
manta_smoke_calc_transparency(FluidDomainSettings * fds,ViewLayer * view_layer)4348 static void manta_smoke_calc_transparency(FluidDomainSettings *fds, ViewLayer *view_layer)
4349 {
4350   float bv[6] = {0};
4351   float light[3];
4352   int slabsize = fds->res[0] * fds->res[1];
4353   float *density = manta_smoke_get_density(fds->fluid);
4354   float *shadow = manta_smoke_get_shadow(fds->fluid);
4355   float correct = -7.0f * fds->dx;
4356 
4357   if (!get_light(view_layer, light)) {
4358     return;
4359   }
4360 
4361   /* Convert light pos to sim cell space. */
4362   mul_m4_v3(fds->imat, light);
4363   light[0] = (light[0] - fds->p0[0]) / fds->cell_size[0] - 0.5f - (float)fds->res_min[0];
4364   light[1] = (light[1] - fds->p0[1]) / fds->cell_size[1] - 0.5f - (float)fds->res_min[1];
4365   light[2] = (light[2] - fds->p0[2]) / fds->cell_size[2] - 0.5f - (float)fds->res_min[2];
4366 
4367   /* Calculate domain bounds in sim cell space. */
4368   // 0,2,4 = 0.0f
4369   bv[1] = (float)fds->res[0];  // x
4370   bv[3] = (float)fds->res[1];  // y
4371   bv[5] = (float)fds->res[2];  // z
4372 
4373   for (int z = 0; z < fds->res[2]; z++) {
4374     size_t index = z * slabsize;
4375 
4376     for (int y = 0; y < fds->res[1]; y++) {
4377       for (int x = 0; x < fds->res[0]; x++, index++) {
4378         float voxel_center[3];
4379         float pos[3];
4380         int cell[3];
4381         float t_ray = 1.0;
4382 
4383         /* Reset shadow value.*/
4384         shadow[index] = -1.0f;
4385 
4386         voxel_center[0] = (float)x;
4387         voxel_center[1] = (float)y;
4388         voxel_center[2] = (float)z;
4389 
4390         /* Get starting cell (light pos). */
4391         if (BLI_bvhtree_bb_raycast(bv, light, voxel_center, pos) > FLT_EPSILON) {
4392           /* We're outside -> use point on side of domain. */
4393           cell[0] = (int)floor(pos[0]);
4394           cell[1] = (int)floor(pos[1]);
4395           cell[2] = (int)floor(pos[2]);
4396         }
4397         else {
4398           /* We're inside -> use light itself. */
4399           cell[0] = (int)floor(light[0]);
4400           cell[1] = (int)floor(light[1]);
4401           cell[2] = (int)floor(light[2]);
4402         }
4403         /* Clamp within grid bounds */
4404         CLAMP(cell[0], 0, fds->res[0] - 1);
4405         CLAMP(cell[1], 0, fds->res[1] - 1);
4406         CLAMP(cell[2], 0, fds->res[2] - 1);
4407 
4408         bresenham_linie_3D(cell[0],
4409                            cell[1],
4410                            cell[2],
4411                            x,
4412                            y,
4413                            z,
4414                            &t_ray,
4415                            calc_voxel_transp,
4416                            shadow,
4417                            density,
4418                            fds->res,
4419                            correct);
4420 
4421         /* Convention -> from a RGBA float array, use G value for t_ray. */
4422         shadow[index] = t_ray;
4423       }
4424     }
4425   }
4426 }
4427 
4428 /* Get fluid velocity and density at given coordinates
4429  * Returns fluid density or -1.0f if outside domain. */
BKE_fluid_get_velocity_at(struct Object * ob,float position[3],float velocity[3])4430 float BKE_fluid_get_velocity_at(struct Object *ob, float position[3], float velocity[3])
4431 {
4432   FluidModifierData *fmd = (FluidModifierData *)BKE_modifiers_findby_type(ob, eModifierType_Fluid);
4433   zero_v3(velocity);
4434 
4435   if (fmd && (fmd->type & MOD_FLUID_TYPE_DOMAIN) && fmd->domain && fmd->domain->fluid) {
4436     FluidDomainSettings *fds = fmd->domain;
4437     float time_mult = 25.f * DT_DEFAULT;
4438     float size_mult = MAX3(fds->global_size[0], fds->global_size[1], fds->global_size[2]) /
4439                       MAX3(fds->base_res[0], fds->base_res[1], fds->base_res[2]);
4440     float vel_mag;
4441     float density = 0.0f, fuel = 0.0f;
4442     float pos[3];
4443     copy_v3_v3(pos, position);
4444     manta_pos_to_cell(fds, pos);
4445 
4446     /* Check if position is outside domain max bounds. */
4447     if (pos[0] < fds->res_min[0] || pos[1] < fds->res_min[1] || pos[2] < fds->res_min[2]) {
4448       return -1.0f;
4449     }
4450     if (pos[0] > fds->res_max[0] || pos[1] > fds->res_max[1] || pos[2] > fds->res_max[2]) {
4451       return -1.0f;
4452     }
4453 
4454     /* map pos between 0.0 - 1.0 */
4455     pos[0] = (pos[0] - fds->res_min[0]) / ((float)fds->res[0]);
4456     pos[1] = (pos[1] - fds->res_min[1]) / ((float)fds->res[1]);
4457     pos[2] = (pos[2] - fds->res_min[2]) / ((float)fds->res[2]);
4458 
4459     /* Check if position is outside active area. */
4460     if (fds->type == FLUID_DOMAIN_TYPE_GAS && fds->flags & FLUID_DOMAIN_USE_ADAPTIVE_DOMAIN) {
4461       if (pos[0] < 0.0f || pos[1] < 0.0f || pos[2] < 0.0f) {
4462         return 0.0f;
4463       }
4464       if (pos[0] > 1.0f || pos[1] > 1.0f || pos[2] > 1.0f) {
4465         return 0.0f;
4466       }
4467     }
4468 
4469     /* Get interpolated velocity at given position. */
4470     velocity[0] = BLI_voxel_sample_trilinear(manta_get_velocity_x(fds->fluid), fds->res, pos);
4471     velocity[1] = BLI_voxel_sample_trilinear(manta_get_velocity_y(fds->fluid), fds->res, pos);
4472     velocity[2] = BLI_voxel_sample_trilinear(manta_get_velocity_z(fds->fluid), fds->res, pos);
4473 
4474     /* Convert simulation units to Blender units. */
4475     mul_v3_fl(velocity, size_mult);
4476     mul_v3_fl(velocity, time_mult);
4477 
4478     /* Convert velocity direction to global space. */
4479     vel_mag = len_v3(velocity);
4480     mul_mat3_m4_v3(fds->obmat, velocity);
4481     normalize_v3(velocity);
4482     mul_v3_fl(velocity, vel_mag);
4483 
4484     /* Use max value of fuel or smoke density. */
4485     density = BLI_voxel_sample_trilinear(manta_smoke_get_density(fds->fluid), fds->res, pos);
4486     if (manta_smoke_has_fuel(fds->fluid)) {
4487       fuel = BLI_voxel_sample_trilinear(manta_smoke_get_fuel(fds->fluid), fds->res, pos);
4488     }
4489     return MAX2(density, fuel);
4490   }
4491   return -1.0f;
4492 }
4493 
BKE_fluid_get_data_flags(FluidDomainSettings * fds)4494 int BKE_fluid_get_data_flags(FluidDomainSettings *fds)
4495 {
4496   int flags = 0;
4497 
4498   if (fds->fluid) {
4499     if (manta_smoke_has_heat(fds->fluid)) {
4500       flags |= FLUID_DOMAIN_ACTIVE_HEAT;
4501     }
4502     if (manta_smoke_has_fuel(fds->fluid)) {
4503       flags |= FLUID_DOMAIN_ACTIVE_FIRE;
4504     }
4505     if (manta_smoke_has_colors(fds->fluid)) {
4506       flags |= FLUID_DOMAIN_ACTIVE_COLORS;
4507     }
4508   }
4509 
4510   return flags;
4511 }
4512 
BKE_fluid_particle_system_create(struct Main * bmain,struct Object * ob,const char * pset_name,const char * parts_name,const char * psys_name,const int psys_type)4513 void BKE_fluid_particle_system_create(struct Main *bmain,
4514                                       struct Object *ob,
4515                                       const char *pset_name,
4516                                       const char *parts_name,
4517                                       const char *psys_name,
4518                                       const int psys_type)
4519 {
4520   ParticleSystem *psys;
4521   ParticleSettings *part;
4522   ParticleSystemModifierData *pfmd;
4523 
4524   /* add particle system */
4525   part = BKE_particlesettings_add(bmain, pset_name);
4526   psys = MEM_callocN(sizeof(ParticleSystem), "particle_system");
4527 
4528   part->type = psys_type;
4529   part->totpart = 0;
4530   part->draw_size = 0.01f; /* Make fluid particles more subtle in viewport. */
4531   part->draw_col = PART_DRAW_COL_VEL;
4532   part->phystype = PART_PHYS_NO; /* No physics needed, part system only used to display data. */
4533   psys->part = part;
4534   psys->pointcache = BKE_ptcache_add(&psys->ptcaches);
4535   BLI_strncpy(psys->name, parts_name, sizeof(psys->name));
4536   BLI_addtail(&ob->particlesystem, psys);
4537 
4538   /* add modifier */
4539   pfmd = (ParticleSystemModifierData *)BKE_modifier_new(eModifierType_ParticleSystem);
4540   BLI_strncpy(pfmd->modifier.name, psys_name, sizeof(pfmd->modifier.name));
4541   pfmd->psys = psys;
4542   BLI_addtail(&ob->modifiers, pfmd);
4543   BKE_modifier_unique_name(&ob->modifiers, (ModifierData *)pfmd);
4544 }
4545 
BKE_fluid_particle_system_destroy(struct Object * ob,const int particle_type)4546 void BKE_fluid_particle_system_destroy(struct Object *ob, const int particle_type)
4547 {
4548   ParticleSystemModifierData *pfmd;
4549   ParticleSystem *psys, *next_psys;
4550 
4551   for (psys = ob->particlesystem.first; psys; psys = next_psys) {
4552     next_psys = psys->next;
4553     if (psys->part->type == particle_type) {
4554       /* clear modifier */
4555       pfmd = psys_get_modifier(ob, psys);
4556       BLI_remlink(&ob->modifiers, pfmd);
4557       BKE_modifier_free((ModifierData *)pfmd);
4558 
4559       /* clear particle system */
4560       BLI_remlink(&ob->particlesystem, psys);
4561       psys_free(ob, psys);
4562     }
4563   }
4564 }
4565 
4566 #endif /* WITH_FLUID */
4567 
4568 /** \} */
4569 
4570 /* -------------------------------------------------------------------- */
4571 /** \name Public Data Access API
4572  *
4573  * Use for versioning, even when fluids are disabled.
4574  * \{ */
4575 
BKE_fluid_cache_startframe_set(FluidDomainSettings * settings,int value)4576 void BKE_fluid_cache_startframe_set(FluidDomainSettings *settings, int value)
4577 {
4578   settings->cache_frame_start = (value > settings->cache_frame_end) ? settings->cache_frame_end :
4579                                                                       value;
4580 }
4581 
BKE_fluid_cache_endframe_set(FluidDomainSettings * settings,int value)4582 void BKE_fluid_cache_endframe_set(FluidDomainSettings *settings, int value)
4583 {
4584   settings->cache_frame_end = (value < settings->cache_frame_start) ? settings->cache_frame_start :
4585                                                                       value;
4586 }
4587 
BKE_fluid_cachetype_mesh_set(FluidDomainSettings * settings,int cache_mesh_format)4588 void BKE_fluid_cachetype_mesh_set(FluidDomainSettings *settings, int cache_mesh_format)
4589 {
4590   if (cache_mesh_format == settings->cache_mesh_format) {
4591     return;
4592   }
4593   /* TODO(sebbas): Clear old caches. */
4594   settings->cache_mesh_format = cache_mesh_format;
4595 }
4596 
BKE_fluid_cachetype_data_set(FluidDomainSettings * settings,int cache_data_format)4597 void BKE_fluid_cachetype_data_set(FluidDomainSettings *settings, int cache_data_format)
4598 {
4599   if (cache_data_format == settings->cache_data_format) {
4600     return;
4601   }
4602   /* TODO(sebbas): Clear old caches. */
4603   settings->cache_data_format = cache_data_format;
4604 }
4605 
BKE_fluid_cachetype_particle_set(FluidDomainSettings * settings,int cache_particle_format)4606 void BKE_fluid_cachetype_particle_set(FluidDomainSettings *settings, int cache_particle_format)
4607 {
4608   if (cache_particle_format == settings->cache_particle_format) {
4609     return;
4610   }
4611   /* TODO(sebbas): Clear old caches. */
4612   settings->cache_particle_format = cache_particle_format;
4613 }
4614 
BKE_fluid_cachetype_noise_set(FluidDomainSettings * settings,int cache_noise_format)4615 void BKE_fluid_cachetype_noise_set(FluidDomainSettings *settings, int cache_noise_format)
4616 {
4617   if (cache_noise_format == settings->cache_noise_format) {
4618     return;
4619   }
4620   /* TODO(sebbas): Clear old caches. */
4621   settings->cache_noise_format = cache_noise_format;
4622 }
4623 
BKE_fluid_collisionextents_set(FluidDomainSettings * settings,int value,bool clear)4624 void BKE_fluid_collisionextents_set(FluidDomainSettings *settings, int value, bool clear)
4625 {
4626   if (clear) {
4627     settings->border_collisions &= value;
4628   }
4629   else {
4630     settings->border_collisions |= value;
4631   }
4632 }
4633 
BKE_fluid_particles_set(FluidDomainSettings * settings,int value,bool clear)4634 void BKE_fluid_particles_set(FluidDomainSettings *settings, int value, bool clear)
4635 {
4636   if (clear) {
4637     settings->particle_type &= ~value;
4638   }
4639   else {
4640     settings->particle_type |= value;
4641   }
4642 }
4643 
BKE_fluid_domain_type_set(Object * object,FluidDomainSettings * settings,int type)4644 void BKE_fluid_domain_type_set(Object *object, FluidDomainSettings *settings, int type)
4645 {
4646   /* Set values for border collision:
4647    * Liquids should have a closed domain, smoke domains should be open. */
4648   if (type == FLUID_DOMAIN_TYPE_GAS) {
4649     BKE_fluid_collisionextents_set(settings, FLUID_DOMAIN_BORDER_FRONT, 1);
4650     BKE_fluid_collisionextents_set(settings, FLUID_DOMAIN_BORDER_BACK, 1);
4651     BKE_fluid_collisionextents_set(settings, FLUID_DOMAIN_BORDER_RIGHT, 1);
4652     BKE_fluid_collisionextents_set(settings, FLUID_DOMAIN_BORDER_LEFT, 1);
4653     BKE_fluid_collisionextents_set(settings, FLUID_DOMAIN_BORDER_TOP, 1);
4654     BKE_fluid_collisionextents_set(settings, FLUID_DOMAIN_BORDER_BOTTOM, 1);
4655     object->dt = OB_WIRE;
4656   }
4657   else if (type == FLUID_DOMAIN_TYPE_LIQUID) {
4658     BKE_fluid_collisionextents_set(settings, FLUID_DOMAIN_BORDER_FRONT, 0);
4659     BKE_fluid_collisionextents_set(settings, FLUID_DOMAIN_BORDER_BACK, 0);
4660     BKE_fluid_collisionextents_set(settings, FLUID_DOMAIN_BORDER_RIGHT, 0);
4661     BKE_fluid_collisionextents_set(settings, FLUID_DOMAIN_BORDER_LEFT, 0);
4662     BKE_fluid_collisionextents_set(settings, FLUID_DOMAIN_BORDER_TOP, 0);
4663     BKE_fluid_collisionextents_set(settings, FLUID_DOMAIN_BORDER_BOTTOM, 0);
4664     object->dt = OB_SOLID;
4665   }
4666 
4667   /* Set actual domain type. */
4668   settings->type = type;
4669 }
4670 
BKE_fluid_flow_behavior_set(Object * UNUSED (object),FluidFlowSettings * settings,int behavior)4671 void BKE_fluid_flow_behavior_set(Object *UNUSED(object), FluidFlowSettings *settings, int behavior)
4672 {
4673   settings->behavior = behavior;
4674 }
4675 
BKE_fluid_flow_type_set(Object * object,FluidFlowSettings * settings,int type)4676 void BKE_fluid_flow_type_set(Object *object, FluidFlowSettings *settings, int type)
4677 {
4678   /* By default, liquid flow objects should behave like their geometry (geometry behavior),
4679    * gas flow objects should continuously produce smoke (inflow behavior). */
4680   if (type == FLUID_FLOW_TYPE_LIQUID) {
4681     BKE_fluid_flow_behavior_set(object, settings, FLUID_FLOW_BEHAVIOR_GEOMETRY);
4682   }
4683   else {
4684     BKE_fluid_flow_behavior_set(object, settings, FLUID_FLOW_BEHAVIOR_INFLOW);
4685   }
4686 
4687   /* Set actual flow type. */
4688   settings->type = type;
4689 }
4690 
BKE_fluid_effector_type_set(Object * UNUSED (object),FluidEffectorSettings * settings,int type)4691 void BKE_fluid_effector_type_set(Object *UNUSED(object), FluidEffectorSettings *settings, int type)
4692 {
4693   settings->type = type;
4694 }
4695 
BKE_fluid_fields_sanitize(FluidDomainSettings * settings)4696 void BKE_fluid_fields_sanitize(FluidDomainSettings *settings)
4697 {
4698   /* Based on the domain type, certain fields are defaulted accordingly if the selected field
4699    * is unsupported. */
4700   const char coba_field = settings->coba_field;
4701   const char data_depth = settings->openvdb_data_depth;
4702 
4703   if (settings->type == FLUID_DOMAIN_TYPE_GAS) {
4704     if (coba_field == FLUID_DOMAIN_FIELD_PHI || coba_field == FLUID_DOMAIN_FIELD_PHI_IN ||
4705         coba_field == FLUID_DOMAIN_FIELD_PHI_OUT ||
4706         coba_field == FLUID_DOMAIN_FIELD_PHI_OBSTACLE) {
4707       /* Defaulted to density for gas domain. */
4708       settings->coba_field = FLUID_DOMAIN_FIELD_DENSITY;
4709     }
4710 
4711     /* Gas domains do not support vdb mini precision. */
4712     if (data_depth == VDB_PRECISION_MINI_FLOAT) {
4713       settings->openvdb_data_depth = VDB_PRECISION_HALF_FLOAT;
4714     }
4715   }
4716   else if (settings->type == FLUID_DOMAIN_TYPE_LIQUID) {
4717     if (coba_field == FLUID_DOMAIN_FIELD_COLOR_R || coba_field == FLUID_DOMAIN_FIELD_COLOR_G ||
4718         coba_field == FLUID_DOMAIN_FIELD_COLOR_B || coba_field == FLUID_DOMAIN_FIELD_DENSITY ||
4719         coba_field == FLUID_DOMAIN_FIELD_FLAME || coba_field == FLUID_DOMAIN_FIELD_FUEL ||
4720         coba_field == FLUID_DOMAIN_FIELD_HEAT) {
4721       /* Defaulted to phi for liquid domain. */
4722       settings->coba_field = FLUID_DOMAIN_FIELD_PHI;
4723     }
4724   }
4725 }
4726 
4727 /** \} */
4728 
4729 /* -------------------------------------------------------------------- */
4730 /** \name Public Modifier API
4731  *
4732  * Use for versioning, even when fluids are disabled.
4733  * \{ */
4734 
BKE_fluid_modifier_freeDomain(FluidModifierData * fmd)4735 static void BKE_fluid_modifier_freeDomain(FluidModifierData *fmd)
4736 {
4737   if (fmd->domain) {
4738     if (fmd->domain->fluid) {
4739 #ifdef WITH_FLUID
4740       manta_free(fmd->domain->fluid);
4741 #endif
4742     }
4743 
4744     if (fmd->domain->fluid_mutex) {
4745       BLI_rw_mutex_free(fmd->domain->fluid_mutex);
4746     }
4747 
4748     if (fmd->domain->effector_weights) {
4749       MEM_freeN(fmd->domain->effector_weights);
4750     }
4751     fmd->domain->effector_weights = NULL;
4752 
4753     if (!(fmd->modifier.flag & eModifierFlag_SharedCaches)) {
4754       BKE_ptcache_free_list(&(fmd->domain->ptcaches[0]));
4755       fmd->domain->point_cache[0] = NULL;
4756     }
4757 
4758     if (fmd->domain->mesh_velocities) {
4759       MEM_freeN(fmd->domain->mesh_velocities);
4760     }
4761     fmd->domain->mesh_velocities = NULL;
4762 
4763     if (fmd->domain->coba) {
4764       MEM_freeN(fmd->domain->coba);
4765     }
4766 
4767     MEM_freeN(fmd->domain);
4768     fmd->domain = NULL;
4769   }
4770 }
4771 
BKE_fluid_modifier_freeFlow(FluidModifierData * fmd)4772 static void BKE_fluid_modifier_freeFlow(FluidModifierData *fmd)
4773 {
4774   if (fmd->flow) {
4775     if (fmd->flow->mesh) {
4776       BKE_id_free(NULL, fmd->flow->mesh);
4777     }
4778     fmd->flow->mesh = NULL;
4779 
4780     if (fmd->flow->verts_old) {
4781       MEM_freeN(fmd->flow->verts_old);
4782     }
4783     fmd->flow->verts_old = NULL;
4784     fmd->flow->numverts = 0;
4785     fmd->flow->flags &= ~FLUID_FLOW_NEEDS_UPDATE;
4786 
4787     MEM_freeN(fmd->flow);
4788     fmd->flow = NULL;
4789   }
4790 }
4791 
BKE_fluid_modifier_freeEffector(FluidModifierData * fmd)4792 static void BKE_fluid_modifier_freeEffector(FluidModifierData *fmd)
4793 {
4794   if (fmd->effector) {
4795     if (fmd->effector->mesh) {
4796       BKE_id_free(NULL, fmd->effector->mesh);
4797     }
4798     fmd->effector->mesh = NULL;
4799 
4800     if (fmd->effector->verts_old) {
4801       MEM_freeN(fmd->effector->verts_old);
4802     }
4803     fmd->effector->verts_old = NULL;
4804     fmd->effector->numverts = 0;
4805     fmd->effector->flags &= ~FLUID_EFFECTOR_NEEDS_UPDATE;
4806 
4807     MEM_freeN(fmd->effector);
4808     fmd->effector = NULL;
4809   }
4810 }
4811 
BKE_fluid_modifier_reset_ex(struct FluidModifierData * fmd,bool need_lock)4812 static void BKE_fluid_modifier_reset_ex(struct FluidModifierData *fmd, bool need_lock)
4813 {
4814   if (!fmd) {
4815     return;
4816   }
4817 
4818   if (fmd->domain) {
4819     if (fmd->domain->fluid) {
4820       if (need_lock) {
4821         BLI_rw_mutex_lock(fmd->domain->fluid_mutex, THREAD_LOCK_WRITE);
4822       }
4823 
4824 #ifdef WITH_FLUID
4825       manta_free(fmd->domain->fluid);
4826 #endif
4827       fmd->domain->fluid = NULL;
4828 
4829       if (need_lock) {
4830         BLI_rw_mutex_unlock(fmd->domain->fluid_mutex);
4831       }
4832     }
4833 
4834     fmd->time = -1;
4835     fmd->domain->total_cells = 0;
4836     fmd->domain->active_fields = 0;
4837   }
4838   else if (fmd->flow) {
4839     if (fmd->flow->verts_old) {
4840       MEM_freeN(fmd->flow->verts_old);
4841     }
4842     fmd->flow->verts_old = NULL;
4843     fmd->flow->numverts = 0;
4844     fmd->flow->flags &= ~FLUID_FLOW_NEEDS_UPDATE;
4845   }
4846   else if (fmd->effector) {
4847     if (fmd->effector->verts_old) {
4848       MEM_freeN(fmd->effector->verts_old);
4849     }
4850     fmd->effector->verts_old = NULL;
4851     fmd->effector->numverts = 0;
4852     fmd->effector->flags &= ~FLUID_EFFECTOR_NEEDS_UPDATE;
4853   }
4854 }
4855 
BKE_fluid_modifier_reset(struct FluidModifierData * fmd)4856 void BKE_fluid_modifier_reset(struct FluidModifierData *fmd)
4857 {
4858   BKE_fluid_modifier_reset_ex(fmd, true);
4859 }
4860 
BKE_fluid_modifier_free(FluidModifierData * fmd)4861 void BKE_fluid_modifier_free(FluidModifierData *fmd)
4862 {
4863   if (!fmd) {
4864     return;
4865   }
4866 
4867   BKE_fluid_modifier_freeDomain(fmd);
4868   BKE_fluid_modifier_freeFlow(fmd);
4869   BKE_fluid_modifier_freeEffector(fmd);
4870 }
4871 
BKE_fluid_modifier_create_type_data(struct FluidModifierData * fmd)4872 void BKE_fluid_modifier_create_type_data(struct FluidModifierData *fmd)
4873 {
4874   if (!fmd) {
4875     return;
4876   }
4877 
4878   if (fmd->type & MOD_FLUID_TYPE_DOMAIN) {
4879     if (fmd->domain) {
4880       BKE_fluid_modifier_freeDomain(fmd);
4881     }
4882 
4883     fmd->domain = DNA_struct_default_alloc(FluidDomainSettings);
4884     fmd->domain->fmd = fmd;
4885 
4886     /* Turn off incompatible options. */
4887 #ifndef WITH_OPENVDB
4888     fmd->domain->cache_data_format = FLUID_DOMAIN_FILE_UNI;
4889     fmd->domain->cache_particle_format = FLUID_DOMAIN_FILE_UNI;
4890     fmd->domain->cache_noise_format = FLUID_DOMAIN_FILE_UNI;
4891 #endif
4892 #ifndef WITH_OPENVDB_BLOSC
4893     fmd->domain->openvdb_compression = VDB_COMPRESSION_ZIP;
4894 #endif
4895 
4896     fmd->domain->effector_weights = BKE_effector_add_weights(NULL);
4897     fmd->domain->fluid_mutex = BLI_rw_mutex_alloc();
4898 
4899     char cache_name[64];
4900     BKE_fluid_cache_new_name_for_current_session(sizeof(cache_name), cache_name);
4901     BKE_modifier_path_init(
4902         fmd->domain->cache_directory, sizeof(fmd->domain->cache_directory), cache_name);
4903 
4904     /* pointcache options */
4905     fmd->domain->point_cache[0] = BKE_ptcache_add(&(fmd->domain->ptcaches[0]));
4906     fmd->domain->point_cache[0]->flag |= PTCACHE_DISK_CACHE;
4907     fmd->domain->point_cache[0]->step = 1;
4908     fmd->domain->point_cache[1] = NULL; /* Deprecated */
4909   }
4910   else if (fmd->type & MOD_FLUID_TYPE_FLOW) {
4911     if (fmd->flow) {
4912       BKE_fluid_modifier_freeFlow(fmd);
4913     }
4914 
4915     fmd->flow = DNA_struct_default_alloc(FluidFlowSettings);
4916     fmd->flow->fmd = fmd;
4917   }
4918   else if (fmd->type & MOD_FLUID_TYPE_EFFEC) {
4919     if (fmd->effector) {
4920       BKE_fluid_modifier_freeEffector(fmd);
4921     }
4922 
4923     fmd->effector = DNA_struct_default_alloc(FluidEffectorSettings);
4924     fmd->effector->fmd = fmd;
4925   }
4926 }
4927 
BKE_fluid_modifier_copy(const struct FluidModifierData * fmd,struct FluidModifierData * tfmd,const int flag)4928 void BKE_fluid_modifier_copy(const struct FluidModifierData *fmd,
4929                              struct FluidModifierData *tfmd,
4930                              const int flag)
4931 {
4932   tfmd->type = fmd->type;
4933   tfmd->time = fmd->time;
4934 
4935   BKE_fluid_modifier_create_type_data(tfmd);
4936 
4937   if (tfmd->domain) {
4938     FluidDomainSettings *tfds = tfmd->domain;
4939     FluidDomainSettings *fds = fmd->domain;
4940 
4941     /* domain object data */
4942     tfds->fluid_group = fds->fluid_group;
4943     tfds->force_group = fds->force_group;
4944     tfds->effector_group = fds->effector_group;
4945     if (tfds->effector_weights) {
4946       MEM_freeN(tfds->effector_weights);
4947     }
4948     tfds->effector_weights = MEM_dupallocN(fds->effector_weights);
4949 
4950     /* adaptive domain options */
4951     tfds->adapt_margin = fds->adapt_margin;
4952     tfds->adapt_res = fds->adapt_res;
4953     tfds->adapt_threshold = fds->adapt_threshold;
4954 
4955     /* fluid domain options */
4956     tfds->maxres = fds->maxres;
4957     tfds->solver_res = fds->solver_res;
4958     tfds->border_collisions = fds->border_collisions;
4959     tfds->flags = fds->flags;
4960     tfds->gravity[0] = fds->gravity[0];
4961     tfds->gravity[1] = fds->gravity[1];
4962     tfds->gravity[2] = fds->gravity[2];
4963     tfds->active_fields = fds->active_fields;
4964     tfds->type = fds->type;
4965     tfds->boundary_width = fds->boundary_width;
4966 
4967     /* smoke domain options */
4968     tfds->alpha = fds->alpha;
4969     tfds->beta = fds->beta;
4970     tfds->diss_speed = fds->diss_speed;
4971     tfds->vorticity = fds->vorticity;
4972     tfds->highres_sampling = fds->highres_sampling;
4973 
4974     /* flame options */
4975     tfds->burning_rate = fds->burning_rate;
4976     tfds->flame_smoke = fds->flame_smoke;
4977     tfds->flame_vorticity = fds->flame_vorticity;
4978     tfds->flame_ignition = fds->flame_ignition;
4979     tfds->flame_max_temp = fds->flame_max_temp;
4980     copy_v3_v3(tfds->flame_smoke_color, fds->flame_smoke_color);
4981 
4982     /* noise options */
4983     tfds->noise_strength = fds->noise_strength;
4984     tfds->noise_pos_scale = fds->noise_pos_scale;
4985     tfds->noise_time_anim = fds->noise_time_anim;
4986     tfds->noise_scale = fds->noise_scale;
4987     tfds->noise_type = fds->noise_type;
4988 
4989     /* liquid domain options */
4990     tfds->flip_ratio = fds->flip_ratio;
4991     tfds->particle_randomness = fds->particle_randomness;
4992     tfds->particle_number = fds->particle_number;
4993     tfds->particle_minimum = fds->particle_minimum;
4994     tfds->particle_maximum = fds->particle_maximum;
4995     tfds->particle_radius = fds->particle_radius;
4996     tfds->particle_band_width = fds->particle_band_width;
4997     tfds->fractions_threshold = fds->fractions_threshold;
4998     tfds->fractions_distance = fds->fractions_distance;
4999     tfds->sys_particle_maximum = fds->sys_particle_maximum;
5000 
5001     /* diffusion options*/
5002     tfds->surface_tension = fds->surface_tension;
5003     tfds->viscosity_base = fds->viscosity_base;
5004     tfds->viscosity_exponent = fds->viscosity_exponent;
5005 
5006     /* mesh options */
5007     if (fds->mesh_velocities) {
5008       tfds->mesh_velocities = MEM_dupallocN(fds->mesh_velocities);
5009     }
5010     tfds->mesh_concave_upper = fds->mesh_concave_upper;
5011     tfds->mesh_concave_lower = fds->mesh_concave_lower;
5012     tfds->mesh_particle_radius = fds->mesh_particle_radius;
5013     tfds->mesh_smoothen_pos = fds->mesh_smoothen_pos;
5014     tfds->mesh_smoothen_neg = fds->mesh_smoothen_neg;
5015     tfds->mesh_scale = fds->mesh_scale;
5016     tfds->totvert = fds->totvert;
5017     tfds->mesh_generator = fds->mesh_generator;
5018 
5019     /* secondary particle options */
5020     tfds->sndparticle_k_b = fds->sndparticle_k_b;
5021     tfds->sndparticle_k_d = fds->sndparticle_k_d;
5022     tfds->sndparticle_k_ta = fds->sndparticle_k_ta;
5023     tfds->sndparticle_k_wc = fds->sndparticle_k_wc;
5024     tfds->sndparticle_l_max = fds->sndparticle_l_max;
5025     tfds->sndparticle_l_min = fds->sndparticle_l_min;
5026     tfds->sndparticle_tau_max_k = fds->sndparticle_tau_max_k;
5027     tfds->sndparticle_tau_max_ta = fds->sndparticle_tau_max_ta;
5028     tfds->sndparticle_tau_max_wc = fds->sndparticle_tau_max_wc;
5029     tfds->sndparticle_tau_min_k = fds->sndparticle_tau_min_k;
5030     tfds->sndparticle_tau_min_ta = fds->sndparticle_tau_min_ta;
5031     tfds->sndparticle_tau_min_wc = fds->sndparticle_tau_min_wc;
5032     tfds->sndparticle_boundary = fds->sndparticle_boundary;
5033     tfds->sndparticle_combined_export = fds->sndparticle_combined_export;
5034     tfds->sndparticle_potential_radius = fds->sndparticle_potential_radius;
5035     tfds->sndparticle_update_radius = fds->sndparticle_update_radius;
5036     tfds->particle_type = fds->particle_type;
5037     tfds->particle_scale = fds->particle_scale;
5038 
5039     /* fluid guide options */
5040     tfds->guide_parent = fds->guide_parent;
5041     tfds->guide_alpha = fds->guide_alpha;
5042     tfds->guide_beta = fds->guide_beta;
5043     tfds->guide_vel_factor = fds->guide_vel_factor;
5044     copy_v3_v3_int(tfds->guide_res, fds->guide_res);
5045     tfds->guide_source = fds->guide_source;
5046 
5047     /* cache options */
5048     tfds->cache_frame_start = fds->cache_frame_start;
5049     tfds->cache_frame_end = fds->cache_frame_end;
5050     tfds->cache_frame_pause_data = fds->cache_frame_pause_data;
5051     tfds->cache_frame_pause_noise = fds->cache_frame_pause_noise;
5052     tfds->cache_frame_pause_mesh = fds->cache_frame_pause_mesh;
5053     tfds->cache_frame_pause_particles = fds->cache_frame_pause_particles;
5054     tfds->cache_frame_pause_guide = fds->cache_frame_pause_guide;
5055     tfds->cache_frame_offset = fds->cache_frame_offset;
5056     tfds->cache_flag = fds->cache_flag;
5057     tfds->cache_type = fds->cache_type;
5058     tfds->cache_mesh_format = fds->cache_mesh_format;
5059     tfds->cache_data_format = fds->cache_data_format;
5060     tfds->cache_particle_format = fds->cache_particle_format;
5061     tfds->cache_noise_format = fds->cache_noise_format;
5062     BLI_strncpy(tfds->cache_directory, fds->cache_directory, sizeof(tfds->cache_directory));
5063 
5064     /* time options */
5065     tfds->time_scale = fds->time_scale;
5066     tfds->cfl_condition = fds->cfl_condition;
5067     tfds->timesteps_minimum = fds->timesteps_minimum;
5068     tfds->timesteps_maximum = fds->timesteps_maximum;
5069 
5070     /* display options */
5071     tfds->axis_slice_method = fds->axis_slice_method;
5072     tfds->slice_axis = fds->slice_axis;
5073     tfds->interp_method = fds->interp_method;
5074     tfds->draw_velocity = fds->draw_velocity;
5075     tfds->slice_per_voxel = fds->slice_per_voxel;
5076     tfds->slice_depth = fds->slice_depth;
5077     tfds->display_thickness = fds->display_thickness;
5078     tfds->show_gridlines = fds->show_gridlines;
5079     if (fds->coba) {
5080       tfds->coba = MEM_dupallocN(fds->coba);
5081     }
5082     tfds->vector_scale = fds->vector_scale;
5083     tfds->vector_draw_type = fds->vector_draw_type;
5084     tfds->vector_field = fds->vector_field;
5085     tfds->vector_scale_with_magnitude = fds->vector_scale_with_magnitude;
5086     tfds->vector_draw_mac_components = fds->vector_draw_mac_components;
5087     tfds->use_coba = fds->use_coba;
5088     tfds->coba_field = fds->coba_field;
5089     tfds->grid_scale = fds->grid_scale;
5090     tfds->gridlines_color_field = fds->gridlines_color_field;
5091     tfds->gridlines_lower_bound = fds->gridlines_lower_bound;
5092     tfds->gridlines_upper_bound = fds->gridlines_upper_bound;
5093     copy_v4_v4(tfds->gridlines_range_color, fds->gridlines_range_color);
5094     tfds->gridlines_cell_filter = fds->gridlines_cell_filter;
5095 
5096     /* -- Deprecated / unsed options (below)-- */
5097 
5098     /* pointcache options */
5099     BKE_ptcache_free_list(&(tfds->ptcaches[0]));
5100     if (flag & LIB_ID_CREATE_NO_MAIN) {
5101       /* Share the cache with the original object's modifier. */
5102       tfmd->modifier.flag |= eModifierFlag_SharedCaches;
5103       tfds->point_cache[0] = fds->point_cache[0];
5104       tfds->ptcaches[0] = fds->ptcaches[0];
5105     }
5106     else {
5107       tfds->point_cache[0] = BKE_ptcache_copy_list(
5108           &(tfds->ptcaches[0]), &(fds->ptcaches[0]), flag);
5109     }
5110 
5111     /* OpenVDB cache options */
5112     tfds->openvdb_compression = fds->openvdb_compression;
5113     tfds->clipping = fds->clipping;
5114     tfds->openvdb_data_depth = fds->openvdb_data_depth;
5115   }
5116   else if (tfmd->flow) {
5117     FluidFlowSettings *tffs = tfmd->flow;
5118     FluidFlowSettings *ffs = fmd->flow;
5119 
5120     tffs->psys = ffs->psys;
5121     tffs->noise_texture = ffs->noise_texture;
5122 
5123     /* initial velocity */
5124     tffs->vel_multi = ffs->vel_multi;
5125     tffs->vel_normal = ffs->vel_normal;
5126     tffs->vel_random = ffs->vel_random;
5127     tffs->vel_coord[0] = ffs->vel_coord[0];
5128     tffs->vel_coord[1] = ffs->vel_coord[1];
5129     tffs->vel_coord[2] = ffs->vel_coord[2];
5130 
5131     /* emission */
5132     tffs->density = ffs->density;
5133     copy_v3_v3(tffs->color, ffs->color);
5134     tffs->fuel_amount = ffs->fuel_amount;
5135     tffs->temperature = ffs->temperature;
5136     tffs->volume_density = ffs->volume_density;
5137     tffs->surface_distance = ffs->surface_distance;
5138     tffs->particle_size = ffs->particle_size;
5139     tffs->subframes = ffs->subframes;
5140 
5141     /* texture control */
5142     tffs->texture_size = ffs->texture_size;
5143     tffs->texture_offset = ffs->texture_offset;
5144     BLI_strncpy(tffs->uvlayer_name, ffs->uvlayer_name, sizeof(tffs->uvlayer_name));
5145     tffs->vgroup_density = ffs->vgroup_density;
5146 
5147     tffs->type = ffs->type;
5148     tffs->behavior = ffs->behavior;
5149     tffs->source = ffs->source;
5150     tffs->texture_type = ffs->texture_type;
5151     tffs->flags = ffs->flags;
5152   }
5153   else if (tfmd->effector) {
5154     FluidEffectorSettings *tfes = tfmd->effector;
5155     FluidEffectorSettings *fes = fmd->effector;
5156 
5157     tfes->surface_distance = fes->surface_distance;
5158     tfes->type = fes->type;
5159     tfes->flags = fes->flags;
5160     tfes->subframes = fes->subframes;
5161 
5162     /* guide options */
5163     tfes->guide_mode = fes->guide_mode;
5164     tfes->vel_multi = fes->vel_multi;
5165   }
5166 }
5167 
BKE_fluid_cache_new_name_for_current_session(int maxlen,char * r_name)5168 void BKE_fluid_cache_new_name_for_current_session(int maxlen, char *r_name)
5169 {
5170   static int counter = 1;
5171   BLI_snprintf(r_name, maxlen, FLUID_DOMAIN_DIR_DEFAULT "_%x", BLI_hash_int(counter));
5172   counter++;
5173 }
5174 
5175 /** \} */
5176