85#define DT_DEFAULT 0.1f
88#define PHI_MAX 9999.0f
103# define ADD_IF_LOWER_POS(a, b) min_ff((a) + (b), max_ff((a), (b)))
104# define ADD_IF_LOWER_NEG(a, b) max_ff((a) + (b), min_ff((a), (b)))
105# define ADD_IF_LOWER(a, b) (((b) > 0) ? ADD_IF_LOWER_POS((a), (b)) : ADD_IF_LOWER_NEG((a), (b)))
109 if (free_old && fds->
fluid) {
112 if (!
min_iii(res[0], res[1], res[2])) {
113 fds->
fluid =
nullptr;
123 return (fds->
fluid !=
nullptr);
137 int new_shift[3] = {0};
143 int o_total_cells = o_res[0] * o_res[1] * o_res[2];
144 int n_total_cells = n_res[0] * n_res[1] * n_res[2];
147 if (o_total_cells > 1 && n_total_cells > 1) {
204 for (
int z = o_min[2];
z < o_max[2];
z++) {
205 for (
int y = o_min[1];
y < o_max[1];
y++) {
206 for (
int x = o_min[0];
x < o_max[0];
x++) {
208 int xo =
x - o_min[0];
209 int yo =
y - o_min[1];
210 int zo =
z - o_min[2];
213 int xn =
x - n_min[0] - new_shift[0];
214 int yn =
y - n_min[1] - new_shift[1];
215 int zn =
z - n_min[2] - new_shift[2];
219 if (xn < 0 || xn >= n_res[0] || yn < 0 || yn >= n_res[1] || zn < 0 || zn >= n_res[2]) {
233 if (xo < bwidth || yo < bwidth || zo < bwidth || xo >= o_res[0] - bwidth ||
234 yo >= o_res[1] - bwidth || zo >= o_res[2] - bwidth)
239 if (xn < bwidth || yn < bwidth || zn < bwidth || xn >= n_res[0] - bwidth ||
240 yn >= n_res[1] - bwidth || zn >= n_res[2] - bwidth)
250 int xx_o = xo * block_size;
251 int yy_o = yo * block_size;
252 int zz_o = zo * block_size;
254 int xx_n = xn * block_size;
255 int yy_n = yn * block_size;
256 int zz_n = zn * block_size;
259 n_wt_tcu[index_new] = o_wt_tcu[index_old];
260 n_wt_tcv[index_new] = o_wt_tcv[index_old];
261 n_wt_tcw[index_new] = o_wt_tcw[index_old];
263 n_wt_tcu2[index_new] = o_wt_tcu2[index_old];
264 n_wt_tcv2[index_new] = o_wt_tcv2[index_old];
265 n_wt_tcw2[index_new] = o_wt_tcw2[index_old];
267 for (
i = 0;
i < block_size;
i++) {
268 for (j = 0; j < block_size; j++) {
269 for (k = 0; k < block_size; k++) {
271 xx_o +
i, wt_res_old[0], yy_o + j, wt_res_old[1], zz_o + k);
275 n_wt_dens[big_index_new] = o_wt_dens[big_index_old];
276 if (n_wt_flame && o_wt_flame) {
277 n_wt_flame[big_index_new] = o_wt_flame[big_index_old];
278 n_wt_fuel[big_index_new] = o_wt_fuel[big_index_old];
279 n_wt_react[big_index_new] = o_wt_react[big_index_old];
281 if (n_wt_r && o_wt_r) {
282 n_wt_r[big_index_new] = o_wt_r[big_index_old];
283 n_wt_g[big_index_new] = o_wt_g[big_index_old];
284 n_wt_b[big_index_new] = o_wt_b[big_index_old];
291 n_dens[index_new] = o_dens[index_old];
293 if (n_heat && o_heat) {
294 n_heat[index_new] = o_heat[index_old];
297 if (n_fuel && o_fuel) {
298 n_flame[index_new] = o_flame[index_old];
299 n_fuel[index_new] = o_fuel[index_old];
300 n_react[index_new] = o_react[index_old];
304 n_r[index_new] = o_r[index_old];
305 n_g[index_new] = o_g[index_old];
306 n_b[index_new] = o_b[index_old];
308 n_vx[index_new] = o_vx[index_old];
309 n_vy[index_new] = o_vy[index_old];
310 n_vz[index_new] = o_vz[index_old];
405 bool init_resolution)
425 fds->
dx = 1.0f / res;
429 if (init_resolution) {
434 for (
i = 0;
i < 3;
i++) {
443 if (!init_resolution || (
size[0] < FLT_EPSILON) || (
size[1] < FLT_EPSILON) ||
444 (
size[2] < FLT_EPSILON))
489static bool fluid_modifier_init(
498 manta_set_domain_from_mesh(fds, ob, mesh,
true);
500 update_final_gravity(fds, scene);
513 res[0] = res[1] = res[2] = 1;
529 fmd->
time = scene_framenr;
538 fmd->
time = scene_framenr;
545 fmd->
time = scene_framenr;
555static float calc_voxel_transp(
556 float *
result,
const float *
input,
int res[3],
int *pixel,
float *t_ray,
float correct);
557static void update_distances(
int index,
560 const float ray_start[3],
561 float surface_thickness,
562 bool use_plane_init);
564static int get_light(
Scene *scene,
ViewLayer *view_layer,
float *light)
571 if (base_tmp->object->type ==
OB_LAMP) {
572 Light *la =
static_cast<Light *
>(base_tmp->object->data);
575 copy_v3_v3(light, base_tmp->object->object_to_world().location());
579 copy_v3_v3(light, base_tmp->object->object_to_world().location());
591 const float *min_vel,
592 const float *max_vel,
596 for (
int i = 0;
i < 3;
i++) {
603 if (min_vel && min_vel[
i] < 0.0f) {
606 if (max_vel && max_vel[
i] > 0.0f) {
616static bool is_static_object(
Object *ob)
621 for (; md; md = md->
next) {
650struct FluidObjectBB {
655 int min[3],
max[3], res[3];
656 int hmin[3], hmax[3], hres[3];
657 int total_cells, valid;
660static void bb_boundInsert(FluidObjectBB *bb,
const float point[3])
665 bb->min[
i] = int(
floor(point[
i]));
666 bb->max[
i] = int(
ceil(point[
i]));
672 if (point[
i] < bb->min[
i]) {
673 bb->min[
i] = int(
floor(point[
i]));
675 if (point[
i] > bb->max[
i]) {
676 bb->max[
i] = int(
ceil(point[
i]));
682static void bb_allocateData(FluidObjectBB *bb,
bool use_velocity,
bool use_influence)
686 for (
i = 0;
i < 3;
i++) {
687 res[
i] = bb->max[
i] - bb->min[
i];
692 bb->total_cells = res[0] * res[1] * res[2];
709static void bb_freeData(FluidObjectBB *bb)
725static void bb_combineMaps(FluidObjectBB *
output,
734 memcpy(&bb1,
output,
sizeof(FluidObjectBB));
735 memset(
output, 0,
sizeof(FluidObjectBB));
737 for (
i = 0;
i < 3;
i++) {
739 output->min[
i] = std::min(bb1.min[
i], bb2->min[
i]);
740 output->max[
i] = std::max(bb1.max[
i], bb2->max[
i]);
748 bb_allocateData(
output, (bb1.velocity || bb2->velocity), (bb1.influence || bb2->influence));
761 if (
x >= bb1.min[0] &&
x < bb1.max[0] &&
y >= bb1.min[1] &&
y < bb1.max[1] &&
762 z >= bb1.min[2] &&
z < bb1.max[2])
765 x - bb1.min[0], bb1.res[0],
y - bb1.min[1], bb1.res[1],
z - bb1.min[2]);
768 output->numobjs[index_out] = bb1.numobjs[index_in];
769 if (
output->influence && bb1.influence) {
770 output->influence[index_out] = bb1.influence[index_in];
772 output->distances[index_out] = bb1.distances[index_in];
773 if (
output->velocity && bb1.velocity) {
783 x - bb2->min[0], bb2->res[0],
y - bb2->min[1], bb2->res[1],
z - bb2->min[2]);
786 output->numobjs[index_out] = std::max(bb2->numobjs[index_in],
787 output->numobjs[index_out]);
788 if (
output->influence && bb2->influence) {
790 output->influence[index_out] += bb2->influence[index_in] * sample_size;
793 output->influence[index_out] = std::max(bb2->influence[index_in],
794 output->influence[index_out]);
797 output->distances[index_out] = std::min(bb2->distances[index_in],
798 output->distances[index_out]);
799 if (
output->velocity && bb2->velocity) {
801 output->velocity[index_out * 3] = ADD_IF_LOWER(
output->velocity[index_out * 3],
802 bb2->velocity[index_in * 3]);
803 output->velocity[index_out * 3 + 1] = ADD_IF_LOWER(
output->velocity[index_out * 3 + 1],
804 bb2->velocity[index_in * 3 + 1]);
805 output->velocity[index_out * 3 + 2] = ADD_IF_LOWER(
output->velocity[index_out * 3 + 2],
806 bb2->velocity[index_in * 3 + 2]);
825 float src_distance_value,
827 float src_numobjs_value,
829 float const src_vel_value[3],
836 dest_phi_in[index] = std::min(src_distance_value, dest_phi_in[index]);
840 if (dest_numobjs && src_numobjs_value > 0) {
841 dest_numobjs[index] += 1;
845 if (dest_vel_x && src_numobjs_value > 0) {
846 dest_vel_x[index] += src_vel_value[0];
847 dest_vel_y[index] += src_vel_value[1];
848 dest_vel_z[index] += src_vel_value[2];
854 const int *corner_verts,
859 const float ray_start[3],
860 const float *vert_vel,
869 const float surface_distance = 1.732;
871 nearest.
dist_sq = surface_distance * surface_distance;
879 int v1,
v2, v3, tri_i = nearest.
index;
882 v1 = corner_verts[corner_tris[tri_i][0]];
883 v2 = corner_verts[corner_tris[tri_i][1]];
884 v3 = corner_verts[corner_tris[tri_i][2]];
886 weights, vert_positions[v1], vert_positions[
v2], vert_positions[v3], nearest.
co);
890 interp_v3_v3v3v3(hit_vel, &vert_vel[v1 * 3], &vert_vel[
v2 * 3], &vert_vel[v3 * 3], weights);
904 velocity_map[index * 3] = (velocity_map[index * 3] + hit_vel[0]) * 0.5f;
905 velocity_map[index * 3 + 1] = (velocity_map[index * 3 + 1] + hit_vel[1]) * 0.5f;
906 velocity_map[index * 3 + 2] = (velocity_map[index * 3 + 2] + hit_vel[2]) * 0.5f;
909 velocity_map[index * 3] = hit_vel[0];
910 velocity_map[index * 3 + 1] = hit_vel[1];
911 velocity_map[index * 3 + 2] = hit_vel[2];
914 velocity_map[index * 3] = std::min(abs_hit_vel[0], abs_vel[0]);
915 velocity_map[index * 3 + 1] = std::min(abs_hit_vel[1], abs_vel[1]);
916 velocity_map[index * 3 + 2] = std::min(abs_hit_vel[2], abs_vel[2]);
920 velocity_map[index * 3] = std::max(abs_hit_vel[0], abs_vel[0]);
921 velocity_map[index * 3 + 1] = std::max(abs_hit_vel[1], abs_vel[1]);
922 velocity_map[index * 3 + 2] = std::max(abs_hit_vel[2], abs_vel[2]);
927 velocity_map[index * 3] = hit_vel[0];
928 velocity_map[index * 3 + 1] = hit_vel[1];
929 velocity_map[index * 3 + 2] = hit_vel[2];
932 printf(
"setting effector object vel: [%f, %f, %f]\n", hit_vel[0], hit_vel[1], hit_vel[2]);
946struct ObstaclesFromDMData {
949 blender::Span<blender::float3> vert_positions;
950 blender::Span<int> corner_verts;
951 blender::Span<blender::int3> corner_tris;
953 blender::bke::BVHTreeFromMesh *
tree;
961static void obstacles_from_mesh_task_cb(
void *__restrict userdata,
965 ObstaclesFromDMData *
data =
static_cast<ObstaclesFromDMData *
>(userdata);
966 FluidObjectBB *bb =
data->bb;
971 x - bb->min[0], bb->res[0],
y - bb->min[1], bb->res[1],
z - bb->min[2]);
975 update_distances(index,
979 data->fes->surface_distance,
984 data->vert_positions,
985 data->corner_verts.data(),
986 data->corner_tris.data(),
995 if (bb->distances[index] < 0) {
996 bb->numobjs[index]++;
1002static void obstacles_from_mesh(
Object *coll_ob,
1011 float *vert_vel =
nullptr;
1012 bool has_velocity =
false;
1017 int min[3],
max[3], res[3];
1036 has_velocity =
true;
1042 for (
i = 0;
i < numverts;
i++) {
1046 mul_m4_v3(coll_ob->object_to_world().ptr(), positions[
i]);
1047 manta_pos_to_cell(fds, positions[
i]);
1058 bb_boundInsert(bb, positions[
i]);
1061 mesh->tag_positions_changed();
1065 int bounds_margin = int(
ceil(5.196));
1066 clamp_bounds_in_domain(fds, bb->min, bb->max,
nullptr,
nullptr, bounds_margin, dt);
1067 bb_allocateData(bb,
true,
false);
1070 for (
i = 0;
i < 3;
i++) {
1071 min[
i] = bb->min[
i];
1072 max[
i] = bb->max[
i];
1073 res[
i] = bb->res[
i];
1079 if (use_effector && tree_data.
tree !=
nullptr) {
1080 ObstaclesFromDMData
data{};
1082 data.vert_positions = positions;
1083 data.corner_verts = corner_verts;
1084 data.corner_tris = corner_tris;
1085 data.tree = &tree_data;
1087 data.has_velocity = has_velocity;
1088 data.vert_vel = vert_vel;
1119 int coll_ob_array_len)
1126 active_fields &= ~prev_flags;
1129 for (coll_index = 0; coll_index < coll_ob_array_len; coll_index++) {
1130 Object *coll_ob = coll_ob_array[coll_index];
1159static bool escape_effectorobject(
Object *flowobj,
1164 bool is_static = is_static_object(flowobj);
1176 if (is_static && !is_first_frame && !is_resume) {
1182static void compute_obstaclesemission(
Scene *scene,
1183 FluidObjectBB *bb_maps,
1191 float time_per_frame)
1196 for (
int effec_index = 0; effec_index < numeffecobjs; effec_index++) {
1197 Object *effecobj = effecobjs[effec_index];
1210 FluidObjectBB *bb = &bb_maps[effec_index];
1213 if (escape_effectorobject(effecobj, fds, fes, frame)) {
1219 if (is_first_frame) {
1224 float sample_size = 1.0f /
float(subframes + 1);
1225 float subframe_dt = dt * sample_size;
1228 for (
int subframe = 0; subframe <= subframes; subframe++) {
1231 FluidObjectBB bb_temp = {
nullptr};
1235 if ((subframe < subframes || time_per_frame + dt + FLT_EPSILON < frame_length) &&
1238 scene->
r.
subframe = (time_per_frame + (subframe + 1.0f) * subframe_dt) / frame_length;
1239 scene->
r.
cfra = frame - 1;
1243 scene->
r.
cfra = frame;
1250 "effector: frame (is first: %d): %d // scene current frame: %d // scene current "
1271 obstacles_from_mesh(effecobj, fds, fes, &bb_temp, subframe_dt);
1274 obstacles_from_mesh(effecobj, fds, fes, bb, subframe_dt);
1281 bb_combineMaps(bb, &bb_temp, 0, 0.0f);
1282 bb_freeData(&bb_temp);
1289static void update_obstacles(Depsgraph *
depsgraph,
1293 float time_per_frame,
1298 FluidObjectBB *bb_maps =
nullptr;
1299 Object **effecobjs =
nullptr;
1300 uint numeffecobjs = 0;
1308 update_obstacleflags(fds, effecobjs, numeffecobjs);
1309 ensure_obstaclefields(fds);
1315 compute_obstaclesemission(scene,
1342 for (
z = 0;
z < fds->
res[0] * fds->
res[1] * fds->
res[2];
z++) {
1350 if (phi_obsstatic_in && (is_first_frame || use_adaptivedomain)) {
1356 if (num_obstacles) {
1357 num_obstacles[
z] = 0;
1362 if (vel_x && vel_y && vel_z) {
1367 if (vel_x_guide && vel_y_guide && vel_z_guide) {
1368 vel_x_guide[
z] = 0.0f;
1369 vel_y_guide[
z] = 0.0f;
1370 vel_z_guide[
z] = 0.0f;
1375 for (
int effec_index = 0; effec_index < numeffecobjs; effec_index++) {
1376 Object *effecobj = effecobjs[effec_index];
1388 bool is_static = is_static_object(effecobj) && !use_adaptivedomain;
1399 FluidObjectBB *bb = &bb_maps[effec_index];
1400 float *velocity_map = bb->velocity;
1401 float *numobjs_map = bb->numobjs;
1402 float *distance_map = bb->distances;
1404 int gx, gy, gz, ex, ey, ez, dx, dy, dz;
1405 size_t e_index, d_index;
1408 for (gx = bb->min[0]; gx < bb->
max[0]; gx++) {
1409 for (gy = bb->min[1]; gy < bb->
max[1]; gy++) {
1410 for (gz = bb->min[2]; gz < bb->
max[2]; gz++) {
1412 ex = gx - bb->min[0];
1413 ey = gy - bb->min[1];
1414 ez = gz - bb->min[2];
1423 if (dx < 0 || dy < 0 || dz < 0 || dx >= fds->
res[0] || dy >= fds->
res[1] ||
1430 float *levelset = ((is_first_frame || is_resume) && is_static) ? phi_obsstatic_in :
1432 apply_effector_fields(fes,
1434 distance_map[e_index],
1436 numobjs_map[e_index],
1438 &velocity_map[e_index * 3],
1444 apply_effector_fields(fes,
1446 distance_map[e_index],
1448 numobjs_map[e_index],
1450 &velocity_map[e_index * 3],
1474struct EmitFromParticlesData {
1479 float *particle_vel;
1486static void emit_from_particles_task_cb(
void *__restrict userdata,
1490 EmitFromParticlesData *
data =
static_cast<EmitFromParticlesData *
>(userdata);
1492 FluidObjectBB *bb =
data->bb;
1497 x - bb->min[0], bb->res[0],
y - bb->min[1], bb->res[1],
z - bb->min[2]);
1501 KDTreeNearest_3d nearest;
1502 const float range =
data->solid +
data->smooth;
1503 BLI_kdtree_3d_find_nearest(
data->tree, ray_start, &nearest);
1505 if (nearest.dist < range) {
1506 bb->influence[index] = (nearest.dist <
data->solid) ?
1508 (1.0f - (nearest.dist -
data->solid) /
data->smooth);
1512 &bb->velocity[index * 3], &data->particle_vel[nearest.index * 3], ffs->vel_multi);
1519static void emit_from_particles(
Object *flow_ob,
1532 float *particle_pos;
1533 float *particle_vel;
1534 int totpart = psys->
totpart, totchild;
1536 int valid_particles = 0;
1537 int bounds_margin = 1;
1541 const float smooth = 0.5f;
1542 KDTree_3d *
tree =
nullptr;
1561 "manta_flow_particles_pos");
1563 "manta_flow_particles_vel");
1568 bounds_margin = int(
ceil(solid + smooth));
1572 for (p = 0; p < totpart + totchild; p++) {
1596 pos = &particle_pos[valid_particles * 3];
1598 manta_pos_to_cell(fds,
pos);
1601 vel = &particle_vel[valid_particles * 3];
1606 BLI_kdtree_3d_insert(
tree, valid_particles,
pos);
1610 bb_boundInsert(bb,
pos);
1615 clamp_bounds_in_domain(fds, bb->min, bb->max,
nullptr,
nullptr, bounds_margin, dt);
1619 for (p = 0; p < valid_particles; p++) {
1626 cell[0] =
floor(particle_pos[p * 3]) - bb->min[0];
1627 cell[1] =
floor(particle_pos[p * 3 + 1]) - bb->min[1];
1628 cell[2] =
floor(particle_pos[p * 3 + 2]) - bb->min[2];
1630 for (
i = 0;
i < 3;
i++) {
1631 if ((cell[
i] > bb->res[
i] - 1) || (cell[
i] < 0)) {
1640 index =
manta_get_index(cell[0], bb->res[0], cell[1], bb->res[1], cell[2]);
1642 bb->influence[index] = 1.0f;
1649 else if (valid_particles > 0) {
1650 int min[3],
max[3], res[3];
1653 for (
int i = 0;
i < 3;
i++) {
1654 min[
i] = bb->min[
i];
1655 max[
i] = bb->max[
i];
1656 res[
i] = bb->res[
i];
1659 BLI_kdtree_3d_balance(
tree);
1661 EmitFromParticlesData
data{};
1665 data.particle_vel = particle_vel;
1670 data.smooth = smooth;
1679 BLI_kdtree_3d_free(
tree);
1696static void update_distances(
int index,
1697 float *distance_map,
1699 const float ray_start[3],
1700 float surface_thickness,
1701 bool use_plane_init)
1706 if (use_plane_init) {
1712 const float surface_distance = 1.732;
1714 nearest.
dist_sq = surface_distance * surface_distance;
1717 if (surface_thickness) {
1718 nearest.
dist_sq += surface_thickness;
1727 min_dist = (-1.0f) *
fabsf(min_dist);
1734 float ray_dirs[26][3] = {
1735 {1.0f, 0.0f, 0.0f}, {0.0f, 1.0f, 0.0f}, {0.0f, 0.0f, 1.0f}, {-1.0f, 0.0f, 0.0f},
1736 {0.0f, -1.0f, 0.0f}, {0.0f, 0.0f, -1.0f}, {1.0f, 1.0f, 0.0f}, {1.0f, -1.0f, 0.0f},
1737 {-1.0f, 1.0f, 0.0f}, {-1.0f, -1.0f, 0.0f}, {1.0f, 0.0f, 1.0f}, {1.0f, 0.0f, -1.0f},
1738 {-1.0f, 0.0f, 1.0f}, {-1.0f, 0.0f, -1.0f}, {0.0f, 1.0f, 1.0f}, {0.0f, 1.0f, -1.0f},
1739 {0.0f, -1.0f, 1.0f}, {0.0f, -1.0f, -1.0f}, {1.0f, 1.0f, 1.0f}, {1.0f, -1.0f, 1.0f},
1740 {-1.0f, 1.0f, 1.0f}, {-1.0f, -1.0f, 1.0f}, {1.0f, 1.0f, -1.0f}, {1.0f, -1.0f, -1.0f},
1741 {-1.0f, 1.0f, -1.0f}, {-1.0f, -1.0f, -1.0f}};
1746 int miss_count = 0, dir_count = 0;
1750 hit_tree.
index = -1;
1764 if (hit_tree.
index == -1) {
1775 min_dist = std::min(hit_tree.
dist, min_dist);
1780 if (!(miss_count > 0 || dir_count ==
ARRAY_SIZE(ray_dirs))) {
1781 min_dist = (-1.0f) *
fabsf(min_dist);
1785 if (surface_thickness) {
1786 min_dist -= surface_thickness;
1791 distance_map[index] = std::min(distance_map[index], min_dist);
1800 const int *corner_verts,
1803 float *influence_map,
1804 float *velocity_map,
1806 const int base_res[3],
1807 const float global_size[3],
1808 const float flow_center[3],
1810 const float ray_start[3],
1811 const float *vert_vel,
1819 float ray_dir[3] = {1.0f, 0.0f, 0.0f};
1823 float volume_factor = 0.0f;
1832 const float surface_distance = 1.732;
1834 nearest.
dist_sq = surface_distance * surface_distance;
1836 bool is_gas_flow =
ELEM(
1842 float emission_strength = (is_gas_flow) ? 0.0f : 1.0f;
1854 float dot = ray_dir[0] * hit.
no[0] + ray_dir[1] * hit.
no[1] + ray_dir[2] * hit.
no[2];
1870 if (hit.
index != -1) {
1882 int v1,
v2, v3, tri_i = nearest.
index;
1883 float hit_normal[3];
1886 v1 = corner_verts[corner_tris[tri_i][0]];
1887 v2 = corner_verts[corner_tris[tri_i][1]];
1888 v3 = corner_verts[corner_tris[tri_i][2]];
1890 weights, vert_positions[v1], vert_positions[
v2], vert_positions[v3], nearest.
co);
1897 CLAMP(emission_strength, 0.0f, 1.0f);
1898 emission_strength =
pow(1.0f - emission_strength, 0.5f);
1901 emission_strength = 0.0f;
1905 if (defgrp_index != -1 && dvert) {
1909 emission_strength *= weight_mask;
1914 float tex_co[3] = {0};
1918 tex_co[0] = ((
x - flow_center[0]) / base_res[0]) / ffs->
texture_size;
1919 tex_co[1] = ((
y - flow_center[1]) / base_res[1]) / ffs->
texture_size;
1920 tex_co[2] = ((
z - flow_center[2]) / base_res[2] - ffs->
texture_offset) /
1925 uv[0] = uv_map[corner_tris[tri_i][0]];
1926 uv[1] = uv_map[corner_tris[tri_i][1]];
1927 uv[2] = uv_map[corner_tris[tri_i][2]];
1932 tex_co[0] = tex_co[0] * 2.0f - 1.0f;
1933 tex_co[1] = tex_co[1] * 2.0f - 1.0f;
1937 emission_strength *= texres.tin;
1947 hit_normal, vert_normals[v1], vert_normals[
v2], vert_normals[v3], weights);
1951 velocity_map[index * 3] += hit_normal[0] * ffs->
vel_normal;
1952 velocity_map[index * 3 + 1] += hit_normal[1] * ffs->
vel_normal;
1953 velocity_map[index * 3 + 2] += hit_normal[2] * ffs->
vel_normal;
1959 hit_vel, &vert_vel[v1 * 3], &vert_vel[
v2 * 3], &vert_vel[v3 * 3], weights);
1960 velocity_map[index * 3] += hit_vel[0] * ffs->
vel_multi;
1961 velocity_map[index * 3 + 1] += hit_vel[1] * ffs->
vel_multi;
1962 velocity_map[index * 3 + 2] += hit_vel[2] * ffs->
vel_multi;
1965 printf(
"adding flow object vel: [%f, %f, %f]\n", hit_vel[0], hit_vel[1], hit_vel[2]);
1969 float convert_vel[3];
1971 float time_mult = 1.0 / (25.0f *
DT_DEFAULT);
1972 float size_mult = std::max({base_res[0], base_res[1], base_res[2]}) /
1973 std::max({global_size[0], global_size[1], global_size[2]});
1976 velocity_map[index * 3] += convert_vel[0];
1977 velocity_map[index * 3 + 1] += convert_vel[1];
1978 velocity_map[index * 3 + 2] += convert_vel[2];
1980 printf(
"initial vel: [%f, %f, %f]\n",
1981 velocity_map[index * 3],
1982 velocity_map[index * 3 + 1],
1983 velocity_map[index * 3 + 2]);
1989 influence_map[index] = std::max(volume_factor, emission_strength);
1992struct EmitFromDMData {
1996 blender::Span<blender::float3> vert_positions;
1997 blender::Span<blender::float3> vert_normals;
1998 blender::Span<int> corner_verts;
1999 blender::Span<blender::int3> corner_tris;
2000 blender::Span<blender::float2> uv_map;
2004 blender::bke::BVHTreeFromMesh *
tree;
2013static void emit_from_mesh_task_cb(
void *__restrict userdata,
2017 EmitFromDMData *
data =
static_cast<EmitFromDMData *
>(userdata);
2018 FluidObjectBB *bb =
data->bb;
2023 x - bb->min[0], bb->res[0],
y - bb->min[1], bb->res[1],
z - bb->min[2]);
2029 sample_mesh(
data->ffs,
2030 data->vert_positions,
2032 data->corner_verts.data(),
2033 data->corner_tris.data(),
2038 data->fds->base_res,
2039 data->fds->global_size,
2053 update_distances(index,
2057 data->ffs->surface_distance,
2063static void emit_from_mesh(
2069 float *vert_vel =
nullptr;
2070 bool has_velocity =
false;
2073 float flow_center[3] = {0};
2074 int min[3],
max[3], res[3];
2084 const MDeformVert *dvert = mesh->deform_verts().data();
2100 has_velocity =
true;
2106 for (
i = 0;
i < numverts;
i++) {
2108 mul_m4_v3(flow_ob->object_to_world().ptr(), positions[
i]);
2109 manta_pos_to_cell(fds, positions[
i]);
2123 bb_boundInsert(bb, positions[
i]);
2125 mesh->tag_positions_changed();
2126 mul_m4_v3(flow_ob->object_to_world().ptr(), flow_center);
2127 manta_pos_to_cell(fds, flow_center);
2131 int bounds_margin = int(
ceil(5.196));
2132 clamp_bounds_in_domain(fds, bb->min, bb->max,
nullptr,
nullptr, bounds_margin, dt);
2136 for (
i = 0;
i < 3;
i++) {
2137 min[
i] = bb->min[
i];
2138 max[
i] = bb->max[
i];
2139 res[
i] = bb->res[
i];
2145 if (use_flow && tree_data.
tree !=
nullptr) {
2147 EmitFromDMData
data{};
2150 data.vert_positions = positions;
2151 data.vert_normals = mesh->vert_normals();
2152 data.corner_verts = corner_verts;
2153 data.corner_tris = corner_tris;
2154 data.uv_map = uv_map;
2156 data.defgrp_index = defgrp_index;
2157 data.tree = &tree_data;
2159 data.has_velocity = has_velocity;
2160 data.vert_vel = vert_vel;
2161 data.flow_center = flow_center;
2185static void adaptive_domain_adjust(
2189 int new_shift[3] = {0};
2191 float frame_shift_f[3];
2192 float ob_loc[3] = {0};
2194 mul_m4_v3(ob->object_to_world().ptr(), ob_loc);
2200 frame_shift_f[0] = frame_shift_f[0] / fds->
cell_size[0];
2201 frame_shift_f[1] = frame_shift_f[1] / fds->
cell_size[1];
2202 frame_shift_f[2] = frame_shift_f[2] / fds->
cell_size[2];
2224 int min[3] = {32767, 32767, 32767},
max[3] = {-32767, -32767, -32767}, res[3];
2225 int total_cells = 1, res_changed = 0, shift_changed = 0;
2226 float min_vel[3], max_vel[3];
2248 int xn =
x - new_shift[0];
2249 int yn =
y - new_shift[1];
2250 int zn =
z - new_shift[2];
2255 if (xn >=
min[0] && xn <=
max[0] && yn >=
min[1] && yn <=
max[1] && zn >=
min[2] &&
2266 max_den = (fuel) ? std::max(density[index], fuel[index]) : density[index];
2267 max_den = (heat) ? std::max(max_den, heat[index]) : max_den;
2273 int xx = (
x - fds->
res_min[0]) * block_size;
2274 int yy = (
y - fds->
res_min[1]) * block_size;
2275 int zz = (
z - fds->
res_min[2]) * block_size;
2277 for (
i = 0;
i < block_size;
i++) {
2278 for (j = 0; j < block_size; j++) {
2279 for (k = 0; k < block_size; k++) {
2280 int big_index =
manta_get_index(xx +
i, wt_res[0], yy + j, wt_res[1], zz + k);
2281 float den = (bigfuel) ? std::max(bigdensity[big_index], bigfuel[big_index]) :
2282 bigdensity[big_index];
2283 max_den = std::max(den, max_den);
2291 min[0] = std::min(
min[0], xn);
2292 min[1] = std::min(
min[1], yn);
2293 min[2] = std::min(
min[2], zn);
2294 max[0] = std::max(
max[0], xn);
2295 max[1] = std::max(
max[1], yn);
2296 max[2] = std::max(
max[2], zn);
2300 min_vel[0] = std::min(min_vel[0], vx[index]);
2301 min_vel[1] = std::min(min_vel[1], vy[index]);
2302 min_vel[2] = std::min(min_vel[2], vz[index]);
2303 max_vel[0] = std::max(max_vel[0], vx[index]);
2304 max_vel[1] = std::max(max_vel[1], vy[index]);
2305 max_vel[2] = std::max(max_vel[2], vz[index]);
2311 for (
int i = 0;
i < numflowobj;
i++) {
2312 FluidObjectBB *bb = &bb_maps[
i];
2318 x - bb->min[0], bb->res[0],
y - bb->min[1], bb->res[1],
z - bb->min[2]);
2319 float max_den = bb->influence[index];
2338 for (
int i = 0;
i < 3;
i++) {
2341 total_cells *= res[
i];
2350 for (j = 0; j < 3; j++) {
2364 if (res_changed || shift_changed) {
2379BLI_INLINE void apply_outflow_fields(
int index,
2380 float distance_value,
2393 phiout[index] = std::min(distance_value, phiout[index]);
2398 density[index] = 0.0f;
2405 react[index] = 0.0f;
2408 color_r[index] = 0.0f;
2409 color_g[index] = 0.0f;
2410 color_b[index] = 0.0f;
2415 float emission_value,
2416 float distance_value,
2419 const float *density,
2427 const float *color_r,
2429 const float *color_g,
2431 const float *color_b,
2438 phi_in[index] = std::min(distance_value, phi_in[index]);
2444 emission_in[index] = std::max(emission_value, emission_in[index]);
2449 float dens_old = (density) ? density[index] : 0.0;
2452 float fuel_flow = (fuel) ? emission_value * ffs->
fuel_amount : 0.0f;
2454 if (heat && heat_in) {
2455 if (emission_value > 0.0f) {
2456 heat_in[index] = ADD_IF_LOWER(heat[index], ffs->
temperature);
2461 if (absolute_flow) {
2462 if (density && density_in) {
2465 density_in[index] = std::max(dens_flow, density_in[index]);
2468 if (fuel && fuel_in) {
2471 fuel_in[index] = std::max(fuel_flow, fuel_in[index]);
2477 if (density && density_in) {
2479 density_in[index] += dens_flow;
2480 CLAMP(density_in[index], 0.0f, 1.0f);
2483 if (fuel && fuel_in) {
2485 fuel_in[index] += fuel_flow;
2486 CLAMP(fuel_in[index], 0.0f, 10.0f);
2492 if (color_r && color_r_in) {
2494 float total_dens = density[index] / (dens_old + dens_flow);
2495 color_r_in[index] = (color_r[index] + ffs->
color[0] * dens_flow) * total_dens;
2496 color_g_in[index] = (color_g[index] + ffs->
color[1] * dens_flow) * total_dens;
2497 color_b_in[index] = (color_b[index] + ffs->
color[2] * dens_flow) * total_dens;
2502 if (fuel && fuel_in) {
2504 float value = 1.0f -
pow2f(1.0f - emission_value);
2506 if (fuel_in[index] > FLT_EPSILON && value > react[index]) {
2507 float f = fuel_flow / fuel_in[index];
2508 react_in[index] = value * f + (1.0f - f) * react[index];
2509 CLAMP(react_in[index], 0.0f, value);
2549 active_fields &= ~prev_flags;
2552 for (flow_index = 0; flow_index < numflowobj; flow_index++) {
2553 Object *flow_ob = flowobjs[flow_index];
2624static bool escape_flowsobject(
Object *flowobj,
2630 bool is_static = is_static_object(flowobj);
2633 bool gas_flow =
ELEM(
2649 if (liquid_flow && is_geometry && !is_first_frame) {
2653 if ((liquid_flow && gas_domain) || (gas_flow && liquid_domain)) {
2658 if (liquid_flow && is_static && !is_first_frame && !is_resume && !use_velocity) {
2664static void compute_flowsemission(
Scene *scene,
2665 FluidObjectBB *bb_maps,
2673 float time_per_frame)
2678 for (
int flow_index = 0; flow_index < numflowobjs; flow_index++) {
2679 Object *flowobj = flowobjs[flow_index];
2692 FluidObjectBB *bb = &bb_maps[flow_index];
2695 if (escape_flowsobject(flowobj, fds, ffs, frame)) {
2701 if (is_first_frame) {
2706 float sample_size = 1.0f /
float(subframes + 1);
2707 float subframe_dt = dt * sample_size;
2710 for (
int subframe = 0; subframe <= subframes; subframe++) {
2712 FluidObjectBB bb_temp = {
nullptr};
2715 if ((subframe < subframes || time_per_frame + dt + FLT_EPSILON < frame_length) &&
2718 scene->
r.
subframe = (time_per_frame + (subframe + 1.0f) * subframe_dt) / frame_length;
2719 scene->
r.
cfra = frame - 1;
2723 scene->
r.
cfra = frame;
2731 "flow: frame (is first: %d): %d // scene current frame: %d // scene current subframe: "
2753 emit_from_particles(flowobj, fds, ffs, &bb_temp,
depsgraph, scene, subframe_dt);
2756 emit_from_particles(flowobj, fds, ffs, bb,
depsgraph, scene, subframe_dt);
2762 emit_from_mesh(flowobj, fds, ffs, &bb_temp, subframe_dt);
2765 emit_from_mesh(flowobj, fds, ffs, bb, subframe_dt);
2769 printf(
"Error: unknown flow emission source\n");
2777 bb_freeData(&bb_temp);
2784 printf(
"flow: frame: %d // time per frame: %f // frame length: %f // dt: %f\n",
2792static void update_flowsfluids(Depsgraph *
depsgraph,
2796 float time_per_frame,
2801 FluidObjectBB *bb_maps =
nullptr;
2802 Object **flowobjs =
nullptr;
2803 uint numflowobjs = 0;
2811 update_flowsflags(fds, flowobjs, numflowobjs);
2812 ensure_flowsfields(fds);
2818 compute_flowsemission(scene,
2831 adaptive_domain_adjust(fds, ob, bb_maps, numflowobjs, dt);
2867 BLI_assert((color_r && color_g && color_b) || (!color_r && !color_g && !color_b));
2868 BLI_assert((color_r_in && color_g_in && color_b_in) ||
2869 (!color_r_in && !color_g_in && !color_b_in));
2870 BLI_assert((velx_initial && vely_initial && velz_initial) ||
2871 (!velx_initial && !vely_initial && !velz_initial));
2875 for (
z = 0;
z < fds->
res[0] * fds->
res[1] * fds->
res[2];
z++) {
2877 if (phistatic_in && is_first_frame) {
2884 if (phioutstatic_in && is_first_frame) {
2892 density_in[
z] = density[
z];
2895 heat_in[
z] = heat[
z];
2897 if (color_r_in && color_g_in && color_b_in) {
2898 color_r_in[
z] = color_r[
z];
2899 color_g_in[
z] = color_b[
z];
2900 color_b_in[
z] = color_g[
z];
2903 fuel_in[
z] = fuel[
z];
2904 react_in[
z] = react[
z];
2907 emission_in[
z] = 0.0f;
2909 if (velx_initial && vely_initial && velz_initial) {
2910 velx_initial[
z] = 0.0f;
2911 vely_initial[
z] = 0.0f;
2912 velz_initial[
z] = 0.0f;
2921 for (
int flow_index = 0; flow_index < numflowobjs; flow_index++) {
2922 Object *flowobj = flowobjs[flow_index];
2938 bool is_static = is_static_object(flowobj) &&
2941 FluidObjectBB *bb = &bb_maps[flow_index];
2942 float *velocity_map = bb->velocity;
2943 float *emission_map = bb->influence;
2944 float *distance_map = bb->distances;
2946 int gx, gy, gz, ex, ey, ez, dx, dy, dz;
2947 size_t e_index, d_index;
2950 for (gx = bb->min[0]; gx < bb->
max[0]; gx++) {
2951 for (gy = bb->min[1]; gy < bb->
max[1]; gy++) {
2952 for (gz = bb->min[2]; gz < bb->
max[2]; gz++) {
2954 ex = gx - bb->min[0];
2955 ey = gy - bb->min[1];
2956 ez = gz - bb->min[2];
2965 if (dx < 0 || dy < 0 || dz < 0 || dx >= fds->
res[0] || dy >= fds->
res[1] ||
2973 float *levelset = ((is_first_frame || is_resume) && is_static) ? phioutstatic_in :
2975 apply_outflow_fields(d_index,
2976 distance_map[e_index],
2987 else if (is_geometry && !is_first_frame) {
2988 apply_inflow_fields(ffs,
3010 else if (is_geometry || is_inflow) {
3011 float *levelset = ((is_first_frame || is_resume) && is_static && !is_geometry) ?
3014 apply_inflow_fields(ffs,
3015 emission_map[e_index],
3016 distance_map[e_index],
3037 float vel_initial[3];
3038 vel_initial[0] = velx_initial[d_index];
3039 vel_initial[1] = vely_initial[d_index];
3040 vel_initial[2] = velz_initial[d_index];
3042 float vel_map_strength =
len_squared_v3(velocity_map + 3 * e_index);
3043 if (vel_map_strength > vel_initial_strength) {
3044 velx_initial[d_index] = velocity_map[e_index * 3];
3045 vely_initial[d_index] = velocity_map[e_index * 3 + 1];
3046 velz_initial[d_index] = velocity_map[e_index * 3 + 2];
3063struct UpdateEffectorsData {
3080static void update_effectors_task_cb(
void *__restrict userdata,
3084 UpdateEffectorsData *
data =
static_cast<UpdateEffectorsData *
>(userdata);
3087 for (
int y = 0;
y < fds->
res[1];
y++) {
3088 for (
int z = 0;
z < fds->
res[2];
z++) {
3091 float voxel_center[3] = {0, 0, 0}, vel[3] = {0, 0, 0}, retvel[3] = {0, 0, 0};
3094 if ((
data->fuel && std::max(
data->density[index],
data->fuel[index]) < FLT_EPSILON) ||
3095 (!
data->fuel &&
data->density &&
data->density[index] < FLT_EPSILON) ||
3096 (
data->phi_obs_in &&
data->phi_obs_in[index] < 0.0f) ||
3097 data->flags[index] & 2)
3103 vel[0] =
data->velocity_x[index];
3104 vel[1] =
data->velocity_y[index];
3105 vel[2] =
data->velocity_z[index];
3133 data->force_x[index] = retvel[0];
3134 data->force_y[index] = retvel[1];
3135 data->force_z[index] = retvel[2];
3139 printf(
"setting force: [%f, %f, %f]\n",
3140 data->force_x[index],
3141 data->force_y[index],
3142 data->force_z[index]);
3148static void update_effectors(
3158 UpdateEffectorsData
data;
3161 data.effectors = effectors;
3193 float cell_size_scaled[3];
3196 const VArraySpan orig_material_indices = *orig_attributes.
lookup<
int>(
"material_index",
3198 const short mp_mat_nr = orig_material_indices.
is_empty() ? 0 : orig_material_indices[0];
3201 int num_verts, num_faces;
3212 printf(
"num_verts: %d, num_faces: %d\n", num_verts, num_faces);
3215 if (!num_verts || !num_faces) {
3242 float max_size = std::max({
size[0],
size[1],
size[2]});
3245 co_scale[0] = max_size / ob->
scale[0];
3246 co_scale[1] = max_size / ob->
scale[1];
3247 co_scale[2] = max_size / ob->
scale[2];
3250 co_offset[0] = (fds->
p0[0] + fds->
p1[0]) / 2.0f;
3251 co_offset[1] = (fds->
p0[1] + fds->
p1[1]) / 2.0f;
3252 co_offset[2] = (fds->
p0[2] + fds->
p1[2]) / 2.0f;
3259 float time_mult = fds->
dx / (
DT_DEFAULT * (25.0f / scene->frames_per_second()));
3261 if (use_speedvectors) {
3267 for (
i = 0;
i < num_verts;
i++) {
3287 printf(
"positions[i][0]: %f, positions[i][1]: %f, positions[i][2]: %f\n",
3295 printf(
"no_s[0]: %d, no_s[1]: %d, no_s[2]: %d\n", no_s[0], no_s[1], no_s[2]);
3298 if (use_speedvectors) {
3304 printf(
"velocities[%d].x: %f, velocities[%d].y: %f, velocities[%d].z: %f\n",
3306 velocities.
span[
i].x,
3308 velocities.
span[
i].y,
3310 velocities.
span[
i].z);
3321 material_indices.
span[
i] = mp_mat_nr;
3323 face_offsets[
i] =
i * 3;
3330 printf(
"mloops[0].v: %d, mloops[1].v: %d, mloops[2].v: %d\n",
3338 material_indices.
finish();
3357 float ob_loc[3] = {0};
3358 float ob_cache_loc[3] = {0};
3411 face_offsets.
fill(4);
3416 corner_vert = &corner_verts[0 * 4];
3422 corner_vert = &corner_verts[1 * 4];
3428 corner_vert = &corner_verts[2 * 4];
3434 corner_vert = &corner_verts[3 * 4];
3440 corner_vert = &corner_verts[4 * 4];
3446 corner_vert = &corner_verts[5 * 4];
3455 mul_m4_v3(ob->object_to_world().ptr(), ob_loc);
3461 for (
int i = 0;
i < num_verts;
i++) {
3470static int manta_step(
3474 float dt, frame_length, time_total, time_total_old;
3475 float time_per_frame;
3476 bool init_resolution =
true;
3491 manta_set_domain_from_mesh(fds, ob,
mesh, init_resolution);
3501 std::scoped_lock
lock(object_update_lock);
3504 while (time_per_frame + FLT_EPSILON < frame_length) {
3513 update_flowsfluids(
depsgraph, scene, ob, fds, time_per_frame, frame_length, frame, dt);
3516 if (
G.is_break && !mode_replay) {
3524 update_obstacles(
depsgraph, scene, ob, fds, time_per_frame, frame_length, frame, dt);
3527 if (
G.is_break && !mode_replay) {
3534 update_effectors(
depsgraph, scene, ob, fds, dt);
3539 time_per_frame += dt;
3551 manta_smoke_calc_transparency(
3558static void manta_guiding(
3564 std::scoped_lock
lock(object_update_lock);
3566 update_obstacles(
depsgraph, scene, ob, fds, dt, dt, frame, dt);
3575 const int scene_framenr)
3577 if (scene_framenr >= fmd->
time) {
3588 if (scene_framenr > fmd->
time) {
3589 fmd->
time = scene_framenr;
3591 else if (scene_framenr < fmd->time) {
3592 fmd->
time = scene_framenr;
3602 const int scene_framenr)
3604 if (scene_framenr >= fmd->
time) {
3615 if (scene_framenr > fmd->
time) {
3616 fmd->
time = scene_framenr;
3618 else if (scene_framenr < fmd->time) {
3619 fmd->
time = scene_framenr;
3629 const int scene_framenr)
3632 Object *guide_parent =
nullptr;
3637 bool is_startframe, has_advanced;
3639 has_advanced = (scene_framenr == fmd->
time + 1);
3643 bool escape =
false;
3648 if (scene_framenr < fds->cache_frame_start ||
3664 if (scene_framenr < fds->cache_frame_start || scene_framenr > fds->
cache_frame_end) {
3670 if (escape && fds->
fluid) {
3698 update_flowsflags(fds, objs, numobj);
3704 update_obstacleflags(fds, objs, numobj);
3711 CLOG_ERROR(&
LOG,
"Fluid initialization failed. Should not happen!");
3720 if (fmd_parent && fmd_parent->
domain) {
3726 int o_res[3], o_min[3], o_max[3], o_shift[3];
3738 update_final_gravity(fds, scene);
3740 int next_frame = scene_framenr + 1;
3741 int prev_frame = scene_framenr - 1;
3745 int data_frame = scene_framenr, noise_frame = scene_framenr;
3746 int mesh_frame = scene_framenr, particles_frame = scene_framenr, guide_frame = scene_framenr;
3748 bool with_smoke, with_liquid;
3752 bool drops, bubble, floater;
3758 bool with_script, with_noise, with_mesh, with_particles, with_guide;
3763 with_particles = drops || bubble || floater;
3765 bool has_data, has_noise, has_mesh, has_particles, has_guide, has_config;
3777 ensure_flowsfields(fds);
3778 ensure_obstaclefields(fds);
3781 bool baking_data, baking_noise, baking_mesh, baking_particles, baking_guide;
3788 bool resume_data, resume_noise, resume_mesh, resume_particles, resume_guide;
3795 bool read_cache, bake_cache;
3797 bake_cache = baking_data || baking_noise || baking_mesh || baking_particles || baking_guide;
3799 bool next_data, next_noise, next_mesh, next_particles, next_guide;
3806 bool prev_data, prev_noise, prev_mesh, prev_particles, prev_guide;
3824 if (!baking_data && !baking_noise && !baking_mesh && !baking_particles && !baking_guide) {
3838 if (baking_data && resume_data) {
3839 data_frame = prev_frame;
3841 if (baking_noise && resume_noise) {
3842 noise_frame = prev_frame;
3844 if (baking_mesh && resume_mesh) {
3845 mesh_frame = prev_frame;
3847 if (baking_particles && resume_particles) {
3848 particles_frame = prev_frame;
3850 if (baking_guide && resume_guide) {
3851 guide_frame = prev_frame;
3865 baking_data = !has_data && (is_startframe || prev_data);
3866 if (with_smoke && with_noise) {
3867 baking_noise = !has_noise && (is_startframe || prev_noise);
3869 if (with_liquid && with_mesh) {
3870 baking_mesh = !has_mesh && (is_startframe || prev_mesh);
3872 if (with_liquid && with_particles) {
3873 baking_particles = !has_particles && (is_startframe || prev_particles);
3882 bool read_partial =
false, read_all =
false;
3889 if (with_liquid && with_mesh) {
3890 if (mesh_frame != scene_framenr) {
3902 if (with_liquid && with_particles) {
3903 if (particles_frame != scene_framenr) {
3907 read_partial = !baking_data && !baking_particles && next_particles;
3908 read_all = !read_partial && with_resumable_cache;
3919 if (with_smoke && with_noise) {
3920 if (noise_frame != scene_framenr) {
3927 fds, o_res, fds->
res, o_min, fds->
res_min, o_max, o_shift, fds->
shift);
3930 read_partial = !baking_data && !baking_noise && next_noise;
3931 read_all = !read_partial && with_resumable_cache;
3934 read_partial = !baking_data && !baking_noise && next_data && next_noise;
3935 read_all = !read_partial && with_resumable_cache;
3940 if (data_frame != scene_framenr) {
3944 if (with_smoke || with_liquid) {
3951 read_partial = !baking_data && !baking_particles && !baking_mesh && next_data &&
3953 read_all = !read_partial && with_resumable_cache;
3962 if (!baking_data && !baking_noise && !baking_mesh && !baking_particles && !baking_guide) {
3969 baking_guide = !has_guide && (is_startframe || prev_guide);
3971 baking_data = !has_data && (is_startframe || prev_data);
3972 if (with_smoke && with_noise) {
3973 baking_noise = !has_noise && (is_startframe || prev_noise);
3975 if (with_liquid && with_mesh) {
3976 baking_mesh = !has_mesh && (is_startframe || prev_mesh);
3978 if (with_liquid && with_particles) {
3979 baking_particles = !has_particles && (is_startframe || prev_particles);
3983 if (is_startframe || has_advanced) {
3984 bake_cache = baking_data || baking_noise || baking_mesh || baking_particles;
3995 if (with_script && is_startframe) {
4004 if (baking_guide && with_guide) {
4005 manta_guiding(
depsgraph, scene, ob, fmd, scene_framenr);
4009 if (manta_step(
depsgraph, scene, ob,
mesh, fmd, scene_framenr)) {
4014 if (has_data || baking_data) {
4015 if (baking_noise && with_smoke && with_noise) {
4022 if (baking_mesh && with_liquid && with_mesh) {
4025 if (baking_particles && with_liquid && with_particles) {
4035 fmd->
time = scene_framenr;
4038static void fluid_modifier_process(
4044 fluid_modifier_processFlow(fmd,
depsgraph, scene, ob,
mesh, scene_framenr);
4047 fluid_modifier_processEffector(fmd,
depsgraph, scene, ob,
mesh, scene_framenr);
4050 fluid_modifier_processDomain(fmd,
depsgraph, scene, ob,
mesh, scene_framenr);
4059 bool needs_viewport_update =
false;
4081 needs_viewport_update =
true;
4087 bool baking_data, baking_noise, baking_mesh, baking_particles, baking_guide;
4094 if (with_mesh && !baking_data && !baking_noise && !baking_mesh && !baking_particles &&
4097 needs_viewport_update =
true;
4105 if (needs_viewport_update) {
4140static float calc_voxel_transp(
4141 float *
result,
const float *
input,
int res[3],
int *pixel,
float *t_ray,
float correct)
4143 const size_t index =
manta_get_index(pixel[0], res[0], pixel[1], res[1], pixel[2]);
4148 if (
result[index] < 0.0f) {
4155static void bresenham_linie_3D(
int x1,
4168 int dx, dy, dz,
i,
l, m, n, x_inc, y_inc, z_inc, err_1, err_2, dx2, dy2, dz2;
4179 x_inc = (dx < 0) ? -1 : 1;
4181 y_inc = (dy < 0) ? -1 : 1;
4183 z_inc = (dz < 0) ? -1 : 1;
4189 if ((
l >= m) && (
l >= n)) {
4192 for (
i = 0;
i <
l;
i++) {
4193 if (cb(
result,
input, res, pixel, t_ray, correct) <= FLT_EPSILON) {
4209 else if ((m >=
l) && (m >= n)) {
4212 for (
i = 0;
i < m;
i++) {
4213 if (cb(
result,
input, res, pixel, t_ray, correct) <= FLT_EPSILON) {
4232 for (
i = 0;
i < n;
i++) {
4233 if (cb(
result,
input, res, pixel, t_ray, correct) <= FLT_EPSILON) {
4258 int slabsize = fds->
res[0] * fds->
res[1];
4261 float correct = -7.0f * fds->
dx;
4263 if (!get_light(scene, view_layer, light)) {
4269 light[0] = (light[0] - fds->
p0[0]) / fds->
cell_size[0] - 0.5f -
float(fds->
res_min[0]);
4270 light[1] = (light[1] - fds->
p0[1]) / fds->
cell_size[1] - 0.5f -
float(fds->
res_min[1]);
4271 light[2] = (light[2] - fds->
p0[2]) / fds->
cell_size[2] - 0.5f -
float(fds->
res_min[2]);
4279 for (
int z = 0;
z < fds->
res[2];
z++) {
4280 size_t index =
z * slabsize;
4282 for (
int y = 0;
y < fds->
res[1];
y++) {
4283 for (
int x = 0;
x < fds->
res[0];
x++, index++) {
4284 float voxel_center[3];
4290 shadow[index] = -1.0f;
4292 voxel_center[0] =
float(
x);
4293 voxel_center[1] =
float(
y);
4294 voxel_center[2] =
float(
z);
4305 cell[0] = int(
floor(light[0]));
4306 cell[1] = int(
floor(light[1]));
4307 cell[2] = int(
floor(light[2]));
4310 CLAMP(cell[0], 0, fds->
res[0] - 1);
4311 CLAMP(cell[1], 0, fds->
res[1] - 1);
4312 CLAMP(cell[2], 0, fds->
res[2] - 1);
4314 bresenham_linie_3D(cell[0],
4328 shadow[index] = t_ray;
4345 float density = 0.0f, fuel = 0.0f;
4348 manta_pos_to_cell(fds,
pos);
4365 if (
pos[0] < 0.0f ||
pos[1] < 0.0f ||
pos[2] < 0.0f) {
4368 if (
pos[0] > 1.0f ||
pos[1] > 1.0f ||
pos[2] > 1.0f) {
4383 vel_mag =
len_v3(velocity);
4393 return std::max(density, fuel);
4419 const char *pset_name,
4420 const char *parts_name,
4421 const char *psys_name,
4422 const int psys_type)
4432 part->
type = psys_type;
4466 next_psys = psys->
next;
4467 if (psys->
part->
type == particle_type) {
4582 settings->
type = type;
4602 settings->
type = type;
4607 settings->
type = type;
4614 const char coba_field = settings->
coba_field;
4618 if (
ELEM(coba_field,
4634 if (
ELEM(coba_field,
4699 fmd->
flow =
nullptr;
4747 else if (fmd->
flow) {
4795#ifndef WITH_OPENVDB_BLOSC
4802 char cache_name[64];
5019 else if (tfmd->
flow) {
5076 static int counter = 1;
void BKE_collision_objects_free(struct Object **objects)
struct Object ** BKE_collision_objects_create(struct Depsgraph *depsgraph, struct Object *self, struct Collection *collection, unsigned int *numcollobj, unsigned int modifier_type)
CustomData interface, see also DNA_customdata_types.h.
struct EffectorWeights * BKE_effector_add_weights(struct Collection *collection)
void BKE_effectors_free(struct ListBase *lb)
void BKE_effectors_apply(struct ListBase *effectors, struct ListBase *colliders, struct EffectorWeights *weights, struct EffectedPoint *point, float *force, float *wind_force, float *impulse)
struct ListBase * BKE_effectors_create(struct Depsgraph *depsgraph, struct Object *ob_src, struct ParticleSystem *psys_src, struct EffectorWeights *weights, bool use_rotation)
void pd_point_from_loc(struct Scene *scene, float *loc, float *vel, int index, struct EffectedPoint *point)
void BKE_fluid_cache_free_all(struct FluidDomainSettings *fds, struct Object *ob)
int BKE_fluid_get_data_flags(struct FluidDomainSettings *fds)
bool BKE_fluid_reallocate_fluid(struct FluidDomainSettings *fds, int res[3], int free_old)
void BKE_fluid_particle_system_destroy(struct Object *ob, int particle_type)
struct Mesh * BKE_fluid_modifier_do(struct FluidModifierData *fmd, struct Depsgraph *depsgraph, struct Scene *scene, struct Object *ob, struct Mesh *mesh)
void BKE_fluid_particle_system_create(struct Main *bmain, struct Object *ob, const char *pset_name, const char *parts_name, const char *psys_name, int psys_type)
float(* BKE_Fluid_BresenhamFn)(float *result, const float *input, int res[3], int *pixel, float *tRay, float correct)
void BKE_fluid_reallocate_copy_fluid(struct 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])
float BKE_fluid_get_velocity_at(struct Object *ob, float position[3], float velocity[3])
void BKE_fluid_cache_free(struct FluidDomainSettings *fds, struct Object *ob, int cache_map)
void BKE_view_layer_synced_ensure(const Scene *scene, ViewLayer *view_layer)
ListBase * BKE_view_layer_object_bases_get(ViewLayer *view_layer)
void BKE_id_free(Main *bmain, void *idv)
@ LIB_ID_COPY_SET_COPIED_ON_WRITE
void BKE_mesh_copy_parameters_for_eval(Mesh *me_dst, const Mesh *me_src)
Mesh * BKE_mesh_new_nomain(int verts_num, int edges_num, int faces_num, int corners_num)
Mesh * BKE_mesh_copy_for_eval(const Mesh &source)
void BKE_mesh_texspace_calc(Mesh *mesh)
void BKE_modifier_path_init(char *path, int path_maxncpy, const char *name)
ModifierData * BKE_modifiers_findby_type(const Object *ob, ModifierType type)
void BKE_modifiers_persistent_uid_init(const Object &object, ModifierData &md)
const char * BKE_modifier_path_relbase_from_global(Object *ob)
void BKE_modifier_unique_name(ListBase *modifiers, ModifierData *md)
void BKE_modifier_free(ModifierData *md)
void BKE_modifier_remove_from_list(Object *ob, ModifierData *md)
ModifierData * BKE_modifiers_get_virtual_modifierlist(const Object *ob, VirtualModifierData *data)
ModifierData * BKE_modifier_new(int type)
General operations, lookup, etc. for blender objects.
#define OBJECT_MODIFIER_UPDATE_SUBFRAME_RECURSION_DEFAULT
bool BKE_object_moves_in_time(const Object *object, bool recurse_parent)
void BKE_object_modifier_update_subframe(Depsgraph *depsgraph, Scene *scene, Object *ob, bool update_mesh, int parent_recursion_limit, float frame, int modifier_type)
struct ParticleSystemModifierData * psys_get_modifier(struct Object *ob, struct ParticleSystem *psys)
void psys_sim_data_free(struct ParticleSimulationData *sim)
void psys_free(struct Object *ob, struct ParticleSystem *psys)
struct ParticleSettings * BKE_particlesettings_add(struct Main *bmain, const char *name)
void psys_sim_data_init(struct ParticleSimulationData *sim)
bool psys_get_particle_state(struct ParticleSimulationData *sim, int p, struct ParticleKey *state, bool always)
struct PointCache * BKE_ptcache_copy_list(struct ListBase *ptcaches_new, const struct ListBase *ptcaches_old, int flag)
struct PointCache * BKE_ptcache_add(struct ListBase *ptcaches)
void BKE_ptcache_free_list(struct ListBase *ptcaches)
#define PTCACHE_RESET_OUTDATED
int BKE_ptcache_id_reset(struct Scene *scene, PTCacheID *pid, int mode)
void BKE_ptcache_id_from_smoke(PTCacheID *pid, struct Object *ob, struct FluidModifierData *fmd)
float BKE_scene_ctime_get(const Scene *scene)
void BKE_texture_get_value(struct Tex *texture, const float *tex_co, struct TexResult *texres, bool use_color_management)
#define BLI_assert_unreachable()
File and directory operations.
int BLI_exists(const char *path) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL()
int BLI_delete(const char *path, bool dir, bool recursive) ATTR_NONNULL()
BLI_INLINE unsigned int BLI_hash_int(unsigned int k)
float BLI_bvhtree_bb_raycast(const float bv[6], const float light_start[3], const float light_end[3], float pos[3])
int BLI_bvhtree_find_nearest(const BVHTree *tree, const float co[3], BVHTreeNearest *nearest, BVHTree_NearestPointCallback callback, void *userdata)
int BLI_bvhtree_ray_cast(const BVHTree *tree, const float co[3], const float dir[3], float radius, BVHTreeRayHit *hit, BVHTree_RayCastCallback callback, void *userdata)
A KD-tree for nearest neighbor search.
#define LISTBASE_FOREACH(type, var, list)
void BLI_addtail(ListBase *listbase, void *vlink) ATTR_NONNULL(1)
void BLI_remlink(ListBase *listbase, void *vlink) ATTR_NONNULL(1)
MINLINE float pow2f(float x)
MINLINE int max_ii(int a, int b)
MINLINE int min_iii(int a, int b, int c)
void interp_weights_tri_v3(float w[3], const float v1[3], const float v2[3], const float v3[3], const float co[3])
void mul_m4_v3(const float M[4][4], float r[3])
void copy_m4_m4(float m1[4][4], const float m2[4][4])
bool invert_m4_m4(float inverse[4][4], const float mat[4][4])
void mul_mat3_m4_v3(const float mat[4][4], float r[3])
MINLINE void copy_v4_v4(float r[4], const float a[4])
MINLINE float len_squared_v3(const float v[3]) ATTR_WARN_UNUSED_RESULT
void minmax_v3v3_v3(float min[3], float max[3], const float vec[3])
MINLINE void add_v3fl_v3fl_v3i(float r[3], const float a[3], const int b[3])
MINLINE void madd_v3_v3fl(float r[3], const float a[3], float f)
MINLINE void add_v3_fl(float r[3], float f)
MINLINE void madd_v3fl_v3fl_v3fl_v3i(float r[3], const float a[3], const float b[3], const int c[3])
MINLINE void clamp_v3(float vec[3], float min, float max)
MINLINE void mul_v3_v3(float r[3], const float a[3])
MINLINE void sub_v3_v3(float r[3], const float a[3])
MINLINE bool equals_v3v3(const float v1[3], const float v2[3]) ATTR_WARN_UNUSED_RESULT
void interp_v3_v3v3v3(float p[3], const float v1[3], const float v2[3], const float v3[3], const float w[3])
MINLINE void sub_v3_v3v3(float r[3], const float a[3], const float b[3])
MINLINE void mul_v3_fl(float r[3], float f)
MINLINE void copy_v3_v3(float r[3], const float a[3])
void interp_v2_v2v2v2(float r[2], const float a[2], const float b[2], const float c[2], const float t[3])
MINLINE void copy_v3_v3_int(int r[3], const int a[3])
void copy_vn_fl(float *array_tar, int size, float val)
MINLINE float dot_v3v3(const float a[3], const float b[3]) ATTR_WARN_UNUSED_RESULT
MINLINE void zero_v3_int(int r[3])
MINLINE void negate_v3(float r[3])
MINLINE void sub_v3_v3v3_int(int r[3], const int a[3], const int b[3])
MINLINE void copy_v3_fl(float r[3], float f)
MINLINE void zero_v3(float r[3])
MINLINE void mul_v3_v3fl(float r[3], const float a[3], float f)
MINLINE void add_v3_v3(float r[3], const float a[3])
MINLINE float normalize_v3(float n[3])
MINLINE float len_v3(const float a[3]) ATTR_WARN_UNUSED_RESULT
bool BLI_path_abs(char path[FILE_MAX], const char *basepath) ATTR_NONNULL(1
#define BLI_path_join(...)
char * STRNCPY(char(&dst)[N], const char *src)
size_t BLI_snprintf(char *__restrict dst, size_t dst_maxncpy, const char *__restrict format,...) ATTR_NONNULL(1
void BLI_task_parallel_range(int start, int stop, void *userdata, TaskParallelRangeFunc func, const TaskParallelSettings *settings)
BLI_INLINE void BLI_parallel_range_settings_defaults(TaskParallelSettings *settings)
ThreadRWMutex * BLI_rw_mutex_alloc(void)
pthread_rwlock_t ThreadRWMutex
#define THREAD_LOCK_WRITE
void BLI_rw_mutex_lock(ThreadRWMutex *mutex, int mode)
void BLI_rw_mutex_free(ThreadRWMutex *mutex)
void BLI_rw_mutex_unlock(ThreadRWMutex *mutex)
#define INIT_MINMAX(min, max)
float BLI_voxel_sample_trilinear(const float *data, const int res[3], const float co[3])
#define CLOG_ERROR(clg_ref,...)
float DEG_get_ctime(const Depsgraph *graph)
Scene * DEG_get_evaluated_scene(const Depsgraph *graph)
ViewLayer * DEG_get_evaluated_view_layer(const Depsgraph *graph)
#define DNA_struct_default_alloc(struct_name)
@ FLUID_DOMAIN_GUIDE_SRC_DOMAIN
#define FLUID_DOMAIN_DIR_DATA
@ FLUID_FLOW_USE_PART_SIZE
@ FLUID_FLOW_NEEDS_UPDATE
@ FLUID_FLOW_USE_PLANE_INIT
@ FLUID_FLOW_INITVELOCITY
#define FLUID_DOMAIN_DIR_PARTICLES
@ FLUID_DOMAIN_BORDER_BOTTOM
@ FLUID_DOMAIN_BORDER_LEFT
@ FLUID_DOMAIN_BORDER_RIGHT
@ FLUID_DOMAIN_BORDER_FRONT
@ FLUID_DOMAIN_BORDER_TOP
@ FLUID_DOMAIN_BORDER_BACK
struct FluidFlowSettings FluidFlowSettings
#define FLUID_DOMAIN_DIR_DEFAULT
@ FLUID_DOMAIN_FIELD_COLOR_B
@ FLUID_DOMAIN_FIELD_FLAME
@ FLUID_DOMAIN_FIELD_PHI_OUT
@ FLUID_DOMAIN_FIELD_PHI_OBSTACLE
@ FLUID_DOMAIN_FIELD_DENSITY
@ FLUID_DOMAIN_FIELD_PHI_IN
@ FLUID_DOMAIN_FIELD_HEAT
@ FLUID_DOMAIN_FIELD_COLOR_G
@ FLUID_DOMAIN_FIELD_FUEL
@ FLUID_DOMAIN_FIELD_COLOR_R
#define FLUID_DOMAIN_DIR_MESH
#define FLUID_DOMAIN_DIR_GUIDE
#define FLUID_DOMAIN_DIR_SCRIPT
@ FLUID_FLOW_TYPE_SMOKEFIRE
@ FLUID_DOMAIN_TYPE_LIQUID
@ VDB_PRECISION_MINI_FLOAT
@ VDB_PRECISION_HALF_FLOAT
@ FLUID_EFFECTOR_NEEDS_UPDATE
@ FLUID_EFFECTOR_USE_EFFEC
@ FLUID_EFFECTOR_USE_PLANE_INIT
struct FluidEffectorSettings FluidEffectorSettings
@ FLUID_DOMAIN_BAKED_DATA
@ FLUID_DOMAIN_OUTDATED_GUIDE
@ FLUID_DOMAIN_OUTDATED_PARTICLES
@ FLUID_DOMAIN_BAKING_MESH
@ FLUID_DOMAIN_BAKING_NOISE
@ FLUID_DOMAIN_BAKING_GUIDE
@ FLUID_DOMAIN_OUTDATED_NOISE
@ FLUID_DOMAIN_BAKED_NOISE
@ FLUID_DOMAIN_BAKED_MESH
@ FLUID_DOMAIN_OUTDATED_MESH
@ FLUID_DOMAIN_BAKING_DATA
@ FLUID_DOMAIN_BAKED_GUIDE
@ FLUID_DOMAIN_BAKED_PARTICLES
@ FLUID_DOMAIN_OUTDATED_DATA
@ FLUID_DOMAIN_BAKING_PARTICLES
#define FLUID_DOMAIN_DIR_CONFIG
struct FluidDomainSettings FluidDomainSettings
@ FLUID_EFFECTOR_GUIDE_MAX
@ FLUID_EFFECTOR_GUIDE_OVERRIDE
@ FLUID_EFFECTOR_GUIDE_AVERAGED
@ FLUID_EFFECTOR_GUIDE_MIN
@ FLUID_DOMAIN_ACTIVE_COLORS
@ FLUID_DOMAIN_ACTIVE_FIRE
@ FLUID_DOMAIN_ACTIVE_INVEL
@ FLUID_DOMAIN_ACTIVE_GUIDE
@ FLUID_DOMAIN_ACTIVE_OUTFLOW
@ FLUID_DOMAIN_ACTIVE_COLOR_SET
@ FLUID_DOMAIN_ACTIVE_HEAT
@ FLUID_DOMAIN_ACTIVE_OBSTACLE
#define FLUID_DOMAIN_DIR_NOISE
@ FLUID_DOMAIN_USE_ADAPTIVE_DOMAIN
@ FLUID_DOMAIN_USE_RESUMABLE_CACHE
@ FLUID_DOMAIN_EXPORT_MANTA_SCRIPT
@ FLUID_DOMAIN_USE_SPEED_VECTORS
@ FLUID_DOMAIN_CACHE_REPLAY
@ FLUID_DOMAIN_CACHE_MODULAR
@ FLUID_FLOW_BEHAVIOR_GEOMETRY
@ FLUID_FLOW_BEHAVIOR_OUTFLOW
@ FLUID_FLOW_BEHAVIOR_INFLOW
@ FLUID_FLOW_TEXTURE_MAP_AUTO
@ FLUID_FLOW_SOURCE_PARTICLES
@ FLUID_DOMAIN_PARTICLE_SPRAY
@ FLUID_DOMAIN_PARTICLE_FOAM
@ FLUID_DOMAIN_PARTICLE_TRACER
@ FLUID_DOMAIN_PARTICLE_BUBBLE
@ FLUID_EFFECTOR_TYPE_GUIDE
@ FLUID_EFFECTOR_TYPE_COLLISION
struct MDeformVert MDeformVert
@ eModifierFlag_SharedCaches
@ eModifierType_ParticleSystem
@ eModifierType_DynamicPaint
Object is a sort of wrapper for general info.
Types and defines for representing Rigid Body entities.
Read Guarded memory(de)allocation.
BMesh const char void * data
ATTR_WARN_UNUSED_RESULT const BMVert * v2
ATTR_WARN_UNUSED_RESULT const BMLoop * l
ATTR_WARN_UNUSED_RESULT const BMVert * v
BPy_StructRNA * depsgraph
static DBVT_INLINE btScalar size(const btDbvtVolume &a)
SIMD_FORCE_INLINE const btScalar & z() const
Return the z value.
constexpr IndexRange drop_back(int64_t n) const
constexpr void fill(const T &value) const
constexpr IndexRange index_range() const
constexpr bool is_empty() const
GAttributeReader lookup(const StringRef attribute_id) const
GSpanAttributeWriter lookup_or_add_for_write_span(StringRef attribute_id, AttrDomain domain, AttrType data_type, const AttributeInit &initializer=AttributeInitDefaultValue())
GSpanAttributeWriter lookup_or_add_for_write_only_span(StringRef attribute_id, AttrDomain domain, AttrType data_type)
dot(value.rgb, luminance_coefficients)") DEFINE_VALUE("REDUCE(lhs
void BKE_fluid_cachetype_noise_set(FluidDomainSettings *settings, int cache_noise_format)
void BKE_fluid_flow_behavior_set(Object *, FluidFlowSettings *settings, int behavior)
static void fluid_modifier_reset_ex(FluidModifierData *fmd, bool need_lock)
void BKE_fluid_cachetype_particle_set(FluidDomainSettings *settings, int cache_particle_format)
static void fluid_modifier_freeDomain(FluidModifierData *fmd)
static void fluid_modifier_freeFlow(FluidModifierData *fmd)
void BKE_fluid_domain_type_set(Object *object, FluidDomainSettings *settings, int type)
void BKE_fluid_particles_set(FluidDomainSettings *settings, int value, bool clear)
void BKE_fluid_cachetype_data_set(FluidDomainSettings *settings, int cache_data_format)
static void fluid_modifier_freeEffector(FluidModifierData *fmd)
void BKE_fluid_collisionextents_set(FluidDomainSettings *settings, int value, bool clear)
void BKE_fluid_modifier_copy(const FluidModifierData *fmd, FluidModifierData *tfmd, const int flag)
void BKE_fluid_modifier_create_type_data(FluidModifierData *fmd)
void BKE_fluid_cache_new_name_for_current_session(int maxlen, char *r_name)
void BKE_fluid_cache_endframe_set(FluidDomainSettings *settings, int value)
void BKE_fluid_fields_sanitize(FluidDomainSettings *settings)
void BKE_fluid_cache_startframe_set(FluidDomainSettings *settings, int value)
void BKE_fluid_modifier_reset(FluidModifierData *fmd)
void BKE_fluid_flow_type_set(Object *object, FluidFlowSettings *settings, int type)
void BKE_fluid_cachetype_mesh_set(FluidDomainSettings *settings, int cache_mesh_format)
void BKE_fluid_effector_type_set(Object *, FluidEffectorSettings *settings, int type)
void BKE_fluid_modifier_free(FluidModifierData *fmd)
void * MEM_calloc_arrayN(size_t len, size_t size, const char *str)
void * MEM_callocN(size_t len, const char *str)
void * MEM_malloc_arrayN(size_t len, size_t size, const char *str)
void * MEM_dupallocN(const void *vmemh)
void MEM_freeN(void *vmemh)
float * manta_noise_get_density(struct MANTA *smoke)
bool manta_has_particles(struct MANTA *fluid, struct FluidModifierData *fmd, int framenr)
float * manta_smoke_get_color_r(struct MANTA *smoke)
float * manta_noise_get_texture_v(struct MANTA *smoke)
float * manta_smoke_get_shadow(struct MANTA *smoke)
float * manta_smoke_get_heat_in(struct MANTA *smoke)
bool manta_has_mesh(struct MANTA *fluid, struct FluidModifierData *fmd, int framenr)
float manta_liquid_get_vertex_y_at(struct MANTA *liquid, int i)
float * manta_noise_get_react(struct MANTA *smoke)
float * manta_get_force_z(struct MANTA *fluid)
bool manta_ensure_invelocity(struct MANTA *fluid, struct FluidModifierData *fmd)
bool manta_read_guiding(struct MANTA *fluid, struct FluidModifierData *fmd, int framenr, bool sourceDomain)
bool manta_has_data(struct MANTA *fluid, struct FluidModifierData *fmd, int framenr)
bool manta_bake_particles(struct MANTA *fluid, struct FluidModifierData *fmd, int framenr)
bool manta_smoke_ensure_colors(struct MANTA *smoke, struct FluidModifierData *fmd)
float * manta_smoke_get_fuel_in(struct MANTA *smoke)
float * manta_noise_get_texture_u(struct MANTA *smoke)
void manta_free(struct MANTA *fluid)
float * manta_get_num_guide(struct MANTA *fluid)
bool manta_smoke_has_heat(struct MANTA *smoke)
int manta_liquid_get_num_triangles(struct MANTA *liquid)
float * manta_get_force_y(struct MANTA *fluid)
bool manta_bake_mesh(struct MANTA *fluid, struct FluidModifierData *fmd, int framenr)
float manta_get_timestep(struct MANTA *fluid)
float * manta_get_guide_velocity_y(struct MANTA *fluid)
float * manta_smoke_get_react(struct MANTA *smoke)
float * manta_get_in_velocity_y(struct MANTA *fluid)
bool manta_bake_noise(struct MANTA *fluid, struct FluidModifierData *fmd, int framenr)
float * manta_get_ob_velocity_x(struct MANTA *fluid)
float * manta_get_ob_velocity_z(struct MANTA *fluid)
float * manta_noise_get_texture_w(struct MANTA *smoke)
bool manta_read_mesh(struct MANTA *fluid, struct FluidModifierData *fmd, int framenr)
float * manta_get_guide_velocity_z(struct MANTA *fluid)
float * manta_get_in_velocity_x(struct MANTA *fluid)
struct MANTA * manta_init(int *res, struct FluidModifierData *fmd)
float * manta_get_guide_velocity_x(struct MANTA *fluid)
bool manta_liquid_ensure_sndparts(struct MANTA *liquid, struct FluidModifierData *fmd)
float * manta_smoke_get_color_g_in(struct MANTA *smoke)
float * manta_noise_get_fuel(struct MANTA *smoke)
bool manta_write_data(struct MANTA *fluid, struct FluidModifierData *fmd, int framenr)
float * manta_noise_get_texture_v2(struct MANTA *smoke)
float * manta_get_phioutstatic_in(struct MANTA *fluid)
bool manta_smoke_ensure_fire(struct MANTA *smoke, struct FluidModifierData *fmd)
void manta_noise_get_res(struct MANTA *smoke, int *res)
float * manta_get_velocity_y(struct MANTA *fluid)
float manta_liquid_get_vertvel_y_at(struct MANTA *liquid, int i)
float * manta_noise_get_color_b(struct MANTA *smoke)
int manta_liquid_get_num_verts(struct MANTA *liquid)
float * manta_smoke_get_color_b_in(struct MANTA *smoke)
bool manta_ensure_obstacle(struct MANTA *fluid, struct FluidModifierData *fmd)
bool manta_write_config(struct MANTA *fluid, struct FluidModifierData *fmd, int framenr)
bool manta_needs_realloc(struct MANTA *fluid, struct FluidModifierData *fmd)
float * manta_noise_get_texture_w2(struct MANTA *smoke)
float * manta_get_force_x(struct MANTA *fluid)
bool manta_has_noise(struct MANTA *fluid, struct FluidModifierData *fmd, int framenr)
float * manta_get_phiguide_in(struct MANTA *fluid)
float manta_liquid_get_vertvel_z_at(struct MANTA *liquid, int i)
bool manta_read_noise(struct MANTA *fluid, struct FluidModifierData *fmd, int framenr, bool resumable)
size_t manta_get_index(int x, int max_x, int y, int max_y, int z)
float * manta_get_ob_velocity_y(struct MANTA *fluid)
bool manta_read_particles(struct MANTA *fluid, struct FluidModifierData *fmd, int framenr, bool resumable)
bool manta_write_noise(struct MANTA *fluid, struct FluidModifierData *fmd, int framenr)
float * manta_smoke_get_density(struct MANTA *smoke)
float * manta_get_phiobsstatic_in(struct MANTA *fluid)
float manta_liquid_get_vertvel_x_at(struct MANTA *liquid, int i)
float * manta_get_in_velocity_z(struct MANTA *fluid)
float * manta_noise_get_color_g(struct MANTA *smoke)
float * manta_smoke_get_color_r_in(struct MANTA *smoke)
bool manta_smoke_ensure_heat(struct MANTA *smoke, struct FluidModifierData *fmd)
float * manta_get_num_obstacle(struct MANTA *fluid)
void manta_update_pointers(struct MANTA *fluid, struct FluidModifierData *fmd, bool flush)
bool manta_ensure_guiding(struct MANTA *fluid, struct FluidModifierData *fmd)
float * manta_get_phi_in(struct MANTA *fluid)
bool manta_read_data(struct MANTA *fluid, struct FluidModifierData *fmd, int framenr, bool resumable)
float * manta_smoke_get_react_in(struct MANTA *smoke)
float * manta_get_velocity_z(struct MANTA *fluid)
bool manta_has_guiding(struct MANTA *fluid, struct FluidModifierData *fmd, int framenr, bool domain)
bool manta_liquid_export_script(struct MANTA *liquid, struct FluidModifierData *fmd)
bool manta_smoke_has_colors(struct MANTA *smoke)
bool manta_read_config(struct MANTA *fluid, struct FluidModifierData *fmd, int framenr)
float * manta_smoke_get_density_in(struct MANTA *smoke)
float manta_liquid_get_vertex_z_at(struct MANTA *liquid, int i)
float * manta_noise_get_texture_u2(struct MANTA *smoke)
float * manta_get_phiout_in(struct MANTA *fluid)
float * manta_get_phiobs_in(struct MANTA *fluid)
int * manta_smoke_get_flags(struct MANTA *smoke)
float * manta_get_velocity_x(struct MANTA *fluid)
int manta_liquid_get_triangle_z_at(struct MANTA *liquid, int i)
bool manta_smoke_has_fuel(struct MANTA *smoke)
float * manta_smoke_get_emission_in(struct MANTA *smoke)
float manta_liquid_get_vertex_x_at(struct MANTA *liquid, int i)
float * manta_smoke_get_color_g(struct MANTA *smoke)
bool manta_ensure_outflow(struct MANTA *fluid, struct FluidModifierData *fmd)
void manta_update_variables(struct MANTA *fluid, struct FluidModifierData *fmd)
float * manta_smoke_get_heat(struct MANTA *smoke)
int manta_liquid_get_triangle_x_at(struct MANTA *liquid, int i)
float * manta_get_phistatic_in(struct MANTA *fluid)
float * manta_smoke_get_color_b(struct MANTA *smoke)
void manta_adapt_timestep(struct MANTA *fluid)
int manta_liquid_get_triangle_y_at(struct MANTA *liquid, int i)
bool manta_bake_data(struct MANTA *fluid, struct FluidModifierData *fmd, int framenr)
float * manta_smoke_get_fuel(struct MANTA *smoke)
bool manta_smoke_export_script(struct MANTA *smoke, struct FluidModifierData *fmd)
float * manta_smoke_get_flame(struct MANTA *smoke)
float * manta_noise_get_flame(struct MANTA *smoke)
float * manta_noise_get_color_r(struct MANTA *smoke)
bool manta_bake_guiding(struct MANTA *fluid, struct FluidModifierData *fmd, int framenr)
static void clear(Message &msg)
void mesh_smooth_set(Mesh &mesh, bool use_smooth, bool keep_sharp_edges=false)
void mesh_calc_edges(Mesh &mesh, bool keep_existing_edges, bool select_new_edges)
MatBase< T, NumCol, NumRow > scale(const MatBase< T, NumCol, NumRow > &mat, const VectorT &scale)
OffsetIndices< int > accumulate_counts_to_offsets(MutableSpan< int > counts_to_offsets, int start_offset=0)
bool is_adaptive(const CpuPatchTable *patch_table)
VecBase< float, 2 > float2
VecBase< int32_t, 3 > int3
VecBase< float, 3 > float3
static void update_velocities(PTCacheEdit *edit)
float gridlines_upper_bound
float gridlines_lower_bound
float sndparticle_tau_min_wc
struct ListBase ptcaches[2]
int sndparticle_update_radius
struct FluidModifierData * fmd
char sndparticle_boundary
float fractions_threshold
char cache_particle_format
float particle_randomness
int sndparticle_potential_radius
int cache_frame_pause_mesh
struct Collection * force_group
float mesh_particle_radius
int cache_frame_pause_data
float flame_smoke_color[3]
float sndparticle_tau_max_wc
float sndparticle_tau_max_ta
struct Collection * effector_group
int cache_frame_pause_particles
int cache_frame_pause_guide
float sndparticle_tau_min_ta
char gridlines_cell_filter
struct PointCache * point_cache[2]
char sndparticle_combined_export
float particle_band_width
float sndparticle_tau_min_k
char cache_directory[1024]
float gridlines_range_color[4]
char vector_scale_with_magnitude
char vector_draw_mac_components
int cache_frame_pause_noise
struct Object * guide_parent
float sndparticle_tau_max_k
struct Collection * fluid_group
struct EffectorWeights * effector_weights
char gridlines_color_field
struct FluidModifierData * fmd
struct FluidModifierData * fmd
struct ParticleSystem * psys
struct Tex * noise_texture
struct FluidDomainSettings * domain
struct FluidEffectorSettings * effector
struct FluidFlowSettings * flow
struct ModifierData * next
ObjectRuntimeHandle * runtime
struct RigidBodyOb * rigidbody_object
struct PointCache * cache
struct Depsgraph * depsgraph
struct ParticleSystem * psys
struct ParticleSystem * psys
struct ParticleSystem * next
struct PointCache * pointcache
struct PhysicsSettings physics_settings
BVHTree_NearestPointCallback nearest_callback
BVHTree_RayCastCallback raycast_callback
MutableVArraySpan< T > span