80#define DT_DEFAULT 0.1f
83#define PHI_MAX 9999.0f
98# define ADD_IF_LOWER_POS(a, b) min_ff((a) + (b), max_ff((a), (b)))
99# define ADD_IF_LOWER_NEG(a, b) max_ff((a) + (b), min_ff((a), (b)))
100# define ADD_IF_LOWER(a, b) (((b) > 0) ? ADD_IF_LOWER_POS((a), (b)) : ADD_IF_LOWER_NEG((a), (b)))
104 if (free_old && fds->
fluid) {
107 if (!
min_iii(res[0], res[1], res[2])) {
108 fds->
fluid =
nullptr;
118 return (fds->
fluid !=
nullptr);
132 int new_shift[3] = {0};
138 int o_total_cells = o_res[0] * o_res[1] * o_res[2];
139 int n_total_cells = n_res[0] * n_res[1] * n_res[2];
142 if (o_total_cells > 1 && n_total_cells > 1) {
199 for (
int z = o_min[2];
z < o_max[2];
z++) {
200 for (
int y = o_min[1]; y < o_max[1]; y++) {
201 for (
int x = o_min[0]; x < o_max[0]; x++) {
203 int xo = x - o_min[0];
204 int yo = y - o_min[1];
205 int zo =
z - o_min[2];
208 int xn = x - n_min[0] - new_shift[0];
209 int yn = y - n_min[1] - new_shift[1];
210 int zn =
z - n_min[2] - new_shift[2];
214 if (xn < 0 || xn >= n_res[0] || yn < 0 || yn >= n_res[1] || zn < 0 || zn >= n_res[2]) {
228 if (xo < bwidth || yo < bwidth || zo < bwidth || xo >= o_res[0] - bwidth ||
229 yo >= o_res[1] - bwidth || zo >= o_res[2] - bwidth)
234 if (xn < bwidth || yn < bwidth || zn < bwidth || xn >= n_res[0] - bwidth ||
235 yn >= n_res[1] - bwidth || zn >= n_res[2] - bwidth)
245 int xx_o = xo * block_size;
246 int yy_o = yo * block_size;
247 int zz_o = zo * block_size;
249 int xx_n = xn * block_size;
250 int yy_n = yn * block_size;
251 int zz_n = zn * block_size;
254 n_wt_tcu[index_new] = o_wt_tcu[index_old];
255 n_wt_tcv[index_new] = o_wt_tcv[index_old];
256 n_wt_tcw[index_new] = o_wt_tcw[index_old];
258 n_wt_tcu2[index_new] = o_wt_tcu2[index_old];
259 n_wt_tcv2[index_new] = o_wt_tcv2[index_old];
260 n_wt_tcw2[index_new] = o_wt_tcw2[index_old];
262 for (i = 0; i < block_size; i++) {
263 for (j = 0; j < block_size; j++) {
264 for (k = 0; k < block_size; k++) {
266 xx_o + i, wt_res_old[0], yy_o + j, wt_res_old[1], zz_o + k);
270 n_wt_dens[big_index_new] = o_wt_dens[big_index_old];
271 if (n_wt_flame && o_wt_flame) {
272 n_wt_flame[big_index_new] = o_wt_flame[big_index_old];
273 n_wt_fuel[big_index_new] = o_wt_fuel[big_index_old];
274 n_wt_react[big_index_new] = o_wt_react[big_index_old];
276 if (n_wt_r && o_wt_r) {
277 n_wt_r[big_index_new] = o_wt_r[big_index_old];
278 n_wt_g[big_index_new] = o_wt_g[big_index_old];
279 n_wt_b[big_index_new] = o_wt_b[big_index_old];
286 n_dens[index_new] = o_dens[index_old];
288 if (n_heat && o_heat) {
289 n_heat[index_new] = o_heat[index_old];
292 if (n_fuel && o_fuel) {
293 n_flame[index_new] = o_flame[index_old];
294 n_fuel[index_new] = o_fuel[index_old];
295 n_react[index_new] = o_react[index_old];
299 n_r[index_new] = o_r[index_old];
300 n_g[index_new] = o_g[index_old];
301 n_b[index_new] = o_b[index_old];
303 n_vx[index_new] = o_vx[index_old];
304 n_vy[index_new] = o_vy[index_old];
305 n_vz[index_new] = o_vz[index_old];
400 bool init_resolution)
413 for (i = 0; i < mesh->verts_num; i++) {
420 fds->
dx = 1.0f / res;
424 if (init_resolution) {
429 for (i = 0; i < 3; i++) {
438 if (!init_resolution || (size[0] < FLT_EPSILON) || (size[1] < FLT_EPSILON) ||
439 (size[2] < FLT_EPSILON))
445 if (size[0] >= std::max(size[1], size[2])) {
446 scale = res / size[0];
452 else if (size[1] >= std::max(size[0], size[2])) {
453 scale = res / size[1];
460 scale = res / size[2];
484static bool fluid_modifier_init(
493 manta_set_domain_from_mesh(fds, ob, mesh,
true);
495 update_final_gravity(fds, scene);
508 res[0] = res[1] = res[2] = 1;
524 fmd->
time = scene_framenr;
533 fmd->
time = scene_framenr;
540 fmd->
time = scene_framenr;
550static float calc_voxel_transp(
551 float *result,
const float *input,
int res[3],
int *pixel,
float *t_ray,
float correct);
552static void update_distances(
int index,
555 const float ray_start[3],
556 float surface_thickness,
557 bool use_plane_init);
559static int get_light(
Scene *scene,
ViewLayer *view_layer,
float *light)
566 if (base_tmp->object->type ==
OB_LAMP) {
567 Light *la =
static_cast<Light *
>(base_tmp->object->data);
570 copy_v3_v3(light, base_tmp->object->object_to_world().location());
574 copy_v3_v3(light, base_tmp->object->object_to_world().location());
586 const float *min_vel,
587 const float *max_vel,
591 for (
int i = 0; i < 3; i++) {
598 if (min_vel && min_vel[i] < 0.0f) {
601 if (max_vel && max_vel[i] > 0.0f) {
602 max[i] +=
int(
ceil(max_vel[i] * dt));
611static bool is_static_object(
Object *ob)
616 for (; md; md = md->
next) {
645struct FluidObjectBB {
650 int min[3], max[3], res[3];
651 int hmin[3], hmax[3], hres[3];
652 int total_cells, valid;
655static void bb_boundInsert(FluidObjectBB *bb,
const float point[3])
661 bb->max[i] =
int(
ceil(point[i]));
667 if (point[i] < bb->min[i]) {
670 if (point[i] > bb->max[i]) {
671 bb->max[i] =
int(
ceil(point[i]));
677static void bb_allocateData(FluidObjectBB *bb,
bool use_velocity,
bool use_influence)
681 for (i = 0; i < 3; i++) {
682 res[i] = bb->max[i] - bb->min[i];
687 bb->total_cells = res[0] * res[1] * res[2];
690 bb->numobjs =
static_cast<float *
>(
693 bb->influence =
static_cast<float *
>(
697 bb->velocity =
static_cast<float *
>(
701 bb->distances =
static_cast<float *
>(
708static void bb_freeData(FluidObjectBB *bb)
724static void bb_combineMaps(FluidObjectBB *output,
733 memcpy(&bb1, output,
sizeof(FluidObjectBB));
734 memset(output, 0,
sizeof(FluidObjectBB));
736 for (i = 0; i < 3; i++) {
738 output->min[i] = std::min(bb1.min[i], bb2->min[i]);
739 output->max[i] = std::max(bb1.max[i], bb2->max[i]);
742 output->min[i] = bb2->min[i];
743 output->max[i] = bb2->max[i];
747 bb_allocateData(output, (bb1.velocity || bb2->velocity), (bb1.influence || bb2->influence));
750 for (x = output->min[0]; x < output->max[0]; x++) {
751 for (y = output->min[1]; y < output->max[1]; y++) {
752 for (
z = output->min[2];
z < output->max[2];
z++) {
760 if (x >= bb1.min[0] && x < bb1.max[0] && y >= bb1.min[1] && y < bb1.max[1] &&
761 z >= bb1.min[2] &&
z < bb1.max[2])
764 x - bb1.min[0], bb1.res[0], y - bb1.min[1], bb1.res[1],
z - bb1.min[2]);
767 output->numobjs[index_out] = bb1.numobjs[index_in];
768 if (output->influence && bb1.influence) {
769 output->influence[index_out] = bb1.influence[index_in];
771 output->distances[index_out] = bb1.distances[index_in];
772 if (output->velocity && bb1.velocity) {
773 copy_v3_v3(&output->velocity[index_out * 3], &bb1.velocity[index_in * 3]);
782 x - bb2->min[0], bb2->res[0], y - bb2->min[1], bb2->res[1],
z - bb2->min[2]);
785 output->numobjs[index_out] = std::max(bb2->numobjs[index_in],
786 output->numobjs[index_out]);
787 if (output->influence && bb2->influence) {
789 output->influence[index_out] += bb2->influence[index_in] * sample_size;
792 output->influence[index_out] = std::max(bb2->influence[index_in],
793 output->influence[index_out]);
796 output->distances[index_out] = std::min(bb2->distances[index_in],
797 output->distances[index_out]);
798 if (output->velocity && bb2->velocity) {
800 output->velocity[index_out * 3] = ADD_IF_LOWER(output->velocity[index_out * 3],
801 bb2->velocity[index_in * 3]);
802 output->velocity[index_out * 3 + 1] = ADD_IF_LOWER(output->velocity[index_out * 3 + 1],
803 bb2->velocity[index_in * 3 + 1]);
804 output->velocity[index_out * 3 + 2] = ADD_IF_LOWER(output->velocity[index_out * 3 + 2],
805 bb2->velocity[index_in * 3 + 2]);
824 float src_distance_value,
826 float src_numobjs_value,
828 float const src_vel_value[3],
835 dest_phi_in[index] = std::min(src_distance_value, dest_phi_in[index]);
839 if (dest_numobjs && src_numobjs_value > 0) {
840 dest_numobjs[index] += 1;
844 if (dest_vel_x && src_numobjs_value > 0) {
845 dest_vel_x[index] += src_vel_value[0];
846 dest_vel_y[index] += src_vel_value[1];
847 dest_vel_z[index] += src_vel_value[2];
853 const int *corner_verts,
858 const float ray_start[3],
859 const float *vert_vel,
868 const float surface_distance = 1.732;
870 nearest.dist_sq = surface_distance * surface_distance;
878 int v1,
v2, v3, tri_i = nearest.index;
881 v1 = corner_verts[corner_tris[tri_i][0]];
882 v2 = corner_verts[corner_tris[tri_i][1]];
883 v3 = corner_verts[corner_tris[tri_i][2]];
885 weights, vert_positions[v1], vert_positions[
v2], vert_positions[v3], nearest.co);
889 interp_v3_v3v3v3(hit_vel, &vert_vel[v1 * 3], &vert_vel[
v2 * 3], &vert_vel[v3 * 3], weights);
896 float abs_hit_vel[3];
902 copy_v3_v3(abs_vel, &velocity_map[index * 3]);
907 velocity_map[index * 3] = (velocity_map[index * 3] + hit_vel[0]) * 0.5f;
908 velocity_map[index * 3 + 1] = (velocity_map[index * 3 + 1] + hit_vel[1]) * 0.5f;
909 velocity_map[index * 3 + 2] = (velocity_map[index * 3 + 2] + hit_vel[2]) * 0.5f;
912 velocity_map[index * 3] = hit_vel[0];
913 velocity_map[index * 3 + 1] = hit_vel[1];
914 velocity_map[index * 3 + 2] = hit_vel[2];
917 velocity_map[index * 3] = std::min(abs_hit_vel[0], abs_vel[0]);
918 velocity_map[index * 3 + 1] = std::min(abs_hit_vel[1], abs_vel[1]);
919 velocity_map[index * 3 + 2] = std::min(abs_hit_vel[2], abs_vel[2]);
923 velocity_map[index * 3] = std::max(abs_hit_vel[0], abs_vel[0]);
924 velocity_map[index * 3 + 1] = std::max(abs_hit_vel[1], abs_vel[1]);
925 velocity_map[index * 3 + 2] = std::max(abs_hit_vel[2], abs_vel[2]);
930 velocity_map[index * 3] = hit_vel[0];
931 velocity_map[index * 3 + 1] = hit_vel[1];
932 velocity_map[index * 3 + 2] = hit_vel[2];
935 printf(
"setting effector object vel: [%f, %f, %f]\n", hit_vel[0], hit_vel[1], hit_vel[2]);
949struct ObstaclesFromDMData {
964static void obstacles_from_mesh_task_cb(
void *__restrict userdata,
968 ObstaclesFromDMData *data =
static_cast<ObstaclesFromDMData *
>(userdata);
969 FluidObjectBB *bb = data->bb;
971 for (
int x = data->min[0]; x < data->max[0]; x++) {
972 for (
int y = data->min[1]; y < data->max[1]; y++) {
974 x - bb->min[0], bb->res[0], y - bb->min[1], bb->res[1],
z - bb->min[2]);
975 const float ray_start[3] = {
float(x) + 0.5f,
float(y) + 0.5f,
float(
z) + 0.5f};
978 update_distances(index,
982 data->fes->surface_distance,
987 data->vert_positions,
988 data->corner_verts.data(),
989 data->corner_tris.data(),
998 if (bb->distances[index] < 0) {
999 bb->numobjs[index]++;
1005static void obstacles_from_mesh(
Object *coll_ob,
1015 float *vert_vel =
nullptr;
1016 bool has_velocity =
false;
1021 int min[3], max[3], res[3];
1025 numverts = mesh->verts_num;
1029 vert_vel =
static_cast<float *
>(
1030 MEM_callocN(
sizeof(
float[3]) * numverts,
"manta_obs_velocity"));
1038 MEM_callocN(
sizeof(
float[3]) * numverts,
"manta_obs_verts_old"));
1042 has_velocity =
true;
1048 for (i = 0; i < numverts; i++) {
1052 mul_m4_v3(coll_ob->object_to_world().ptr(), positions[i]);
1053 manta_pos_to_cell(fds, positions[i]);
1064 bb_boundInsert(bb, positions[i]);
1069 int bounds_margin =
int(
ceil(5.196));
1070 clamp_bounds_in_domain(fds, bb->min, bb->max,
nullptr,
nullptr, bounds_margin, dt);
1071 bb_allocateData(bb,
true,
false);
1074 for (i = 0; i < 3; i++) {
1075 min[i] = bb->min[i];
1076 max[i] = bb->max[i];
1077 res[i] = bb->res[i];
1084 ObstaclesFromDMData data{};
1086 data.vert_positions = positions;
1087 data.corner_verts = corner_verts;
1088 data.corner_tris = corner_tris;
1089 data.tree = &tree_data;
1091 data.has_velocity = has_velocity;
1092 data.vert_vel = vert_vel;
1099 settings.min_iter_per_thread = 2;
1125 int coll_ob_array_len)
1132 active_fields &= ~prev_flags;
1135 for (coll_index = 0; coll_index < coll_ob_array_len; coll_index++) {
1136 Object *coll_ob = coll_ob_array[coll_index];
1151 fes->
flags &= ~FLUID_EFFECTOR_NEEDS_UPDATE;
1165static bool escape_effectorobject(
Object *flowobj,
1170 bool is_static = is_static_object(flowobj);
1182 if (is_static && !is_first_frame && !is_resume) {
1188static void compute_obstaclesemission(
Scene *scene,
1189 FluidObjectBB *bb_maps,
1197 float time_per_frame)
1202 for (
int effec_index = 0; effec_index < numeffecobjs; effec_index++) {
1203 Object *effecobj = effecobjs[effec_index];
1216 FluidObjectBB *bb = &bb_maps[effec_index];
1219 if (escape_effectorobject(effecobj, fds, fes, frame)) {
1225 if (is_first_frame) {
1230 float sample_size = 1.0f /
float(subframes + 1);
1231 float subframe_dt = dt * sample_size;
1234 for (
int subframe = 0; subframe <= subframes; subframe++) {
1237 FluidObjectBB bb_temp = {
nullptr};
1241 if ((subframe < subframes || time_per_frame + dt + FLT_EPSILON < frame_length) &&
1244 scene->r.subframe = (time_per_frame + (subframe + 1.0f) * subframe_dt) / frame_length;
1245 scene->r.cfra = frame - 1;
1248 scene->r.subframe = 0.0f;
1249 scene->r.cfra = frame;
1252 CLAMP(scene->r.subframe, 0.0f, 1.0f);
1256 "effector: frame (is first: %d): %d // scene current frame: %d // scene current "
1272 obstacles_from_mesh(effecobj, fds, fes, &bb_temp, subframe_dt);
1275 obstacles_from_mesh(effecobj, fds, fes, bb, subframe_dt);
1282 bb_combineMaps(bb, &bb_temp, 0, 0.0f);
1283 bb_freeData(&bb_temp);
1290static void update_obstacles(Depsgraph *
depsgraph,
1294 float time_per_frame,
1299 FluidObjectBB *bb_maps =
nullptr;
1300 Object **effecobjs =
nullptr;
1301 uint numeffecobjs = 0;
1309 update_obstacleflags(fds, effecobjs, numeffecobjs);
1310 ensure_obstaclefields(fds);
1313 bb_maps =
static_cast<FluidObjectBB *
>(
1314 MEM_callocN(
sizeof(FluidObjectBB) * numeffecobjs,
"fluid_effector_bb_maps"));
1317 compute_obstaclesemission(scene,
1344 for (
z = 0;
z < fds->
res[0] * fds->
res[1] * fds->
res[2];
z++) {
1352 if (phi_obsstatic_in && (is_first_frame || use_adaptivedomain)) {
1358 if (num_obstacles) {
1359 num_obstacles[
z] = 0;
1364 if (vel_x && vel_y && vel_z) {
1369 if (vel_x_guide && vel_y_guide && vel_z_guide) {
1370 vel_x_guide[
z] = 0.0f;
1371 vel_y_guide[
z] = 0.0f;
1372 vel_z_guide[
z] = 0.0f;
1377 for (
int effec_index = 0; effec_index < numeffecobjs; effec_index++) {
1378 Object *effecobj = effecobjs[effec_index];
1390 bool is_static = is_static_object(effecobj) && !use_adaptivedomain;
1401 FluidObjectBB *bb = &bb_maps[effec_index];
1402 float *velocity_map = bb->velocity;
1403 float *numobjs_map = bb->numobjs;
1404 float *distance_map = bb->distances;
1406 int gx, gy, gz, ex, ey, ez, dx, dy, dz;
1407 size_t e_index, d_index;
1410 for (gx = bb->min[0]; gx < bb->max[0]; gx++) {
1411 for (gy = bb->min[1]; gy < bb->max[1]; gy++) {
1412 for (gz = bb->min[2]; gz < bb->max[2]; gz++) {
1414 ex = gx - bb->min[0];
1415 ey = gy - bb->min[1];
1416 ez = gz - bb->min[2];
1425 if (dx < 0 || dy < 0 || dz < 0 || dx >= fds->
res[0] || dy >= fds->
res[1] ||
1432 float *levelset = ((is_first_frame || is_resume) && is_static) ? phi_obsstatic_in :
1434 apply_effector_fields(fes,
1436 distance_map[e_index],
1438 numobjs_map[e_index],
1440 &velocity_map[e_index * 3],
1446 apply_effector_fields(fes,
1448 distance_map[e_index],
1450 numobjs_map[e_index],
1452 &velocity_map[e_index * 3],
1476struct EmitFromParticlesData {
1481 float *particle_vel;
1488static void emit_from_particles_task_cb(
void *__restrict userdata,
1492 EmitFromParticlesData *data =
static_cast<EmitFromParticlesData *
>(userdata);
1494 FluidObjectBB *bb = data->bb;
1496 for (
int x = data->min[0]; x < data->max[0]; x++) {
1497 for (
int y = data->min[1]; y < data->max[1]; y++) {
1499 x - bb->min[0], bb->res[0], y - bb->min[1], bb->res[1],
z - bb->min[2]);
1500 const float ray_start[3] = {
float(x) + 0.5f,
float(y) + 0.5f,
float(
z) + 0.5f};
1503 KDTreeNearest_3d nearest;
1504 const float range = data->solid + data->smooth;
1505 BLI_kdtree_3d_find_nearest(data->tree, ray_start, &nearest);
1507 if (nearest.dist < range) {
1508 bb->influence[index] = (nearest.dist < data->solid) ?
1510 (1.0f - (nearest.dist - data->solid) / data->smooth);
1514 &bb->velocity[index * 3], &data->particle_vel[nearest.index * 3], ffs->
vel_multi);
1521static void emit_from_particles(
Object *flow_ob,
1534 float *particle_pos;
1535 float *particle_vel;
1536 int totpart = psys->
totpart, totchild;
1538 int valid_particles = 0;
1539 int bounds_margin = 1;
1543 const float smooth = 0.5f;
1544 KDTree_3d *
tree =
nullptr;
1562 particle_pos =
static_cast<float *
>(
1563 MEM_callocN(
sizeof(
float[3]) * (totpart + totchild),
"manta_flow_particles_pos"));
1564 particle_vel =
static_cast<float *
>(
1565 MEM_callocN(
sizeof(
float[3]) * (totpart + totchild),
"manta_flow_particles_vel"));
1570 bounds_margin =
int(
ceil(solid + smooth));
1574 for (p = 0; p < totpart + totchild; p++) {
1598 pos = &particle_pos[valid_particles * 3];
1600 manta_pos_to_cell(fds,
pos);
1603 vel = &particle_vel[valid_particles * 3];
1608 BLI_kdtree_3d_insert(
tree, valid_particles,
pos);
1612 bb_boundInsert(bb,
pos);
1617 clamp_bounds_in_domain(fds, bb->min, bb->max,
nullptr,
nullptr, bounds_margin, dt);
1621 for (p = 0; p < valid_particles; p++) {
1628 cell[0] =
floor(particle_pos[p * 3]) - bb->min[0];
1629 cell[1] =
floor(particle_pos[p * 3 + 1]) - bb->min[1];
1630 cell[2] =
floor(particle_pos[p * 3 + 2]) - bb->min[2];
1632 for (i = 0; i < 3; i++) {
1633 if ((cell[i] > bb->res[i] - 1) || (cell[i] < 0)) {
1642 index =
manta_get_index(cell[0], bb->res[0], cell[1], bb->res[1], cell[2]);
1644 bb->influence[index] = 1.0f;
1651 else if (valid_particles > 0) {
1652 int min[3], max[3], res[3];
1655 for (
int i = 0; i < 3; i++) {
1656 min[i] = bb->min[i];
1657 max[i] = bb->max[i];
1658 res[i] = bb->res[i];
1661 BLI_kdtree_3d_balance(
tree);
1663 EmitFromParticlesData data{};
1667 data.particle_vel = particle_vel;
1676 settings.min_iter_per_thread = 2;
1681 BLI_kdtree_3d_free(
tree);
1698static void update_distances(
int index,
1699 float *distance_map,
1701 const float ray_start[3],
1702 float surface_thickness,
1703 bool use_plane_init)
1708 if (use_plane_init) {
1714 const float surface_distance = 1.732;
1716 nearest.dist_sq = surface_distance * surface_distance;
1719 if (surface_thickness) {
1720 nearest.dist_sq += surface_thickness;
1729 min_dist = (-1.0f) *
fabsf(min_dist);
1736 float ray_dirs[26][3] = {
1737 {1.0f, 0.0f, 0.0f}, {0.0f, 1.0f, 0.0f}, {0.0f, 0.0f, 1.0f}, {-1.0f, 0.0f, 0.0f},
1738 {0.0f, -1.0f, 0.0f}, {0.0f, 0.0f, -1.0f}, {1.0f, 1.0f, 0.0f}, {1.0f, -1.0f, 0.0f},
1739 {-1.0f, 1.0f, 0.0f}, {-1.0f, -1.0f, 0.0f}, {1.0f, 0.0f, 1.0f}, {1.0f, 0.0f, -1.0f},
1740 {-1.0f, 0.0f, 1.0f}, {-1.0f, 0.0f, -1.0f}, {0.0f, 1.0f, 1.0f}, {0.0f, 1.0f, -1.0f},
1741 {0.0f, -1.0f, 1.0f}, {0.0f, -1.0f, -1.0f}, {1.0f, 1.0f, 1.0f}, {1.0f, -1.0f, 1.0f},
1742 {-1.0f, 1.0f, 1.0f}, {-1.0f, -1.0f, 1.0f}, {1.0f, 1.0f, -1.0f}, {1.0f, -1.0f, -1.0f},
1743 {-1.0f, 1.0f, -1.0f}, {-1.0f, -1.0f, -1.0f}};
1748 int miss_count = 0, dir_count = 0;
1750 for (
int i = 0; i <
ARRAY_SIZE(ray_dirs); i++) {
1752 hit_tree.
index = -1;
1766 if (hit_tree.
index == -1) {
1773 if (
dot_v3v3(ray_dirs[i], hit_tree.
no) <= 0) {
1777 if (hit_tree.
dist < min_dist) {
1778 min_dist = hit_tree.
dist;
1784 if (!(miss_count > 0 || dir_count ==
ARRAY_SIZE(ray_dirs))) {
1785 min_dist = (-1.0f) *
fabsf(min_dist);
1789 if (surface_thickness) {
1790 min_dist -= surface_thickness;
1795 distance_map[index] = std::min(distance_map[index], min_dist);
1804 const int *corner_verts,
1806 const float (*mloopuv)[2],
1807 float *influence_map,
1808 float *velocity_map,
1810 const int base_res[3],
1811 const float global_size[3],
1812 const float flow_center[3],
1814 const float ray_start[3],
1815 const float *vert_vel,
1823 float ray_dir[3] = {1.0f, 0.0f, 0.0f};
1827 float volume_factor = 0.0f;
1836 const float surface_distance = 1.732;
1838 nearest.dist_sq = surface_distance * surface_distance;
1840 bool is_gas_flow =
ELEM(
1846 float emission_strength = (is_gas_flow) ? 0.0f : 1.0f;
1858 float dot = ray_dir[0] * hit.no[0] + ray_dir[1] * hit.no[1] + ray_dir[2] * hit.no[2];
1874 if (hit.index != -1) {
1886 int v1,
v2, v3, tri_i = nearest.index;
1887 float hit_normal[3];
1890 v1 = corner_verts[corner_tris[tri_i][0]];
1891 v2 = corner_verts[corner_tris[tri_i][1]];
1892 v3 = corner_verts[corner_tris[tri_i][2]];
1894 weights, vert_positions[v1], vert_positions[
v2], vert_positions[v3], nearest.co);
1901 CLAMP(emission_strength, 0.0f, 1.0f);
1902 emission_strength =
pow(1.0f - emission_strength, 0.5f);
1905 emission_strength = 0.0f;
1909 if (defgrp_index != -1 && dvert) {
1913 emission_strength *= weight_mask;
1918 float tex_co[3] = {0};
1922 tex_co[0] = ((x - flow_center[0]) / base_res[0]) / ffs->
texture_size;
1923 tex_co[1] = ((y - flow_center[1]) / base_res[1]) / ffs->
texture_size;
1924 tex_co[2] = ((
z - flow_center[2]) / base_res[2] - ffs->
texture_offset) /
1929 uv[0] = mloopuv[corner_tris[tri_i][0]];
1930 uv[1] = mloopuv[corner_tris[tri_i][1]];
1931 uv[2] = mloopuv[corner_tris[tri_i][2]];
1936 tex_co[0] = tex_co[0] * 2.0f - 1.0f;
1937 tex_co[1] = tex_co[1] * 2.0f - 1.0f;
1941 emission_strength *= texres.
tin;
1951 hit_normal, vert_normals[v1], vert_normals[
v2], vert_normals[v3], weights);
1955 velocity_map[index * 3] += hit_normal[0] * ffs->
vel_normal;
1956 velocity_map[index * 3 + 1] += hit_normal[1] * ffs->
vel_normal;
1957 velocity_map[index * 3 + 2] += hit_normal[2] * ffs->
vel_normal;
1963 hit_vel, &vert_vel[v1 * 3], &vert_vel[
v2 * 3], &vert_vel[v3 * 3], weights);
1964 velocity_map[index * 3] += hit_vel[0] * ffs->
vel_multi;
1965 velocity_map[index * 3 + 1] += hit_vel[1] * ffs->
vel_multi;
1966 velocity_map[index * 3 + 2] += hit_vel[2] * ffs->
vel_multi;
1969 printf(
"adding flow object vel: [%f, %f, %f]\n", hit_vel[0], hit_vel[1], hit_vel[2]);
1973 float convert_vel[3];
1975 float time_mult = 1.0 / (25.0f *
DT_DEFAULT);
1976 float size_mult = std::max({base_res[0], base_res[1], base_res[2]}) /
1977 std::max({global_size[0], global_size[1], global_size[2]});
1980 velocity_map[index * 3] += convert_vel[0];
1981 velocity_map[index * 3 + 1] += convert_vel[1];
1982 velocity_map[index * 3 + 2] += convert_vel[2];
1984 printf(
"initial vel: [%f, %f, %f]\n",
1985 velocity_map[index * 3],
1986 velocity_map[index * 3 + 1],
1987 velocity_map[index * 3 + 2]);
1993 influence_map[index] = std::max(volume_factor, emission_strength);
1996struct EmitFromDMData {
2004 const float (*mloopuv)[2];
2017static void emit_from_mesh_task_cb(
void *__restrict userdata,
2021 EmitFromDMData *data =
static_cast<EmitFromDMData *
>(userdata);
2022 FluidObjectBB *bb = data->bb;
2024 for (
int x = data->min[0]; x < data->max[0]; x++) {
2025 for (
int y = data->min[1]; y < data->max[1]; y++) {
2027 x - bb->min[0], bb->res[0], y - bb->min[1], bb->res[1],
z - bb->min[2]);
2028 const float ray_start[3] = {
float(x) + 0.5f,
float(y) + 0.5f,
float(
z) + 0.5f};
2033 sample_mesh(data->ffs,
2034 data->vert_positions,
2036 data->corner_verts.data(),
2037 data->corner_tris.data(),
2042 data->fds->base_res,
2043 data->fds->global_size,
2057 update_distances(index,
2061 data->ffs->surface_distance,
2067static void emit_from_mesh(
2074 float *vert_vel =
nullptr;
2075 bool has_velocity =
false;
2078 float flow_center[3] = {0};
2079 int min[3], max[3], res[3];
2088 const int numverts = mesh->verts_num;
2089 const MDeformVert *dvert = mesh->deform_verts().data();
2090 const float(*mloopuv)[2] =
static_cast<const float(*)[2]
>(
2094 vert_vel =
static_cast<float *
>(
2095 MEM_callocN(
sizeof(
float[3]) * numverts,
"manta_flow_velocity"));
2102 MEM_callocN(
sizeof(
float[3]) * numverts,
"manta_flow_verts_old"));
2106 has_velocity =
true;
2112 for (i = 0; i < numverts; i++) {
2114 mul_m4_v3(flow_ob->object_to_world().ptr(), positions[i]);
2115 manta_pos_to_cell(fds, positions[i]);
2129 bb_boundInsert(bb, positions[i]);
2131 mesh->tag_positions_changed();
2132 mul_m4_v3(flow_ob->object_to_world().ptr(), flow_center);
2133 manta_pos_to_cell(fds, flow_center);
2137 int bounds_margin =
int(
ceil(5.196));
2138 clamp_bounds_in_domain(fds, bb->min, bb->max,
nullptr,
nullptr, bounds_margin, dt);
2142 for (i = 0; i < 3; i++) {
2143 min[i] = bb->min[i];
2144 max[i] = bb->max[i];
2145 res[i] = bb->res[i];
2152 EmitFromDMData data{};
2155 data.vert_positions = positions;
2156 data.vert_normals = mesh->vert_normals();
2157 data.corner_verts = corner_verts;
2158 data.corner_tris = corner_tris;
2159 data.mloopuv = mloopuv;
2161 data.defgrp_index = defgrp_index;
2162 data.tree = &tree_data;
2164 data.has_velocity = has_velocity;
2165 data.vert_vel = vert_vel;
2166 data.flow_center = flow_center;
2173 settings.min_iter_per_thread = 2;
2192static void adaptive_domain_adjust(
2196 int new_shift[3] = {0};
2198 float frame_shift_f[3];
2199 float ob_loc[3] = {0};
2201 mul_m4_v3(ob->object_to_world().ptr(), ob_loc);
2207 frame_shift_f[0] = frame_shift_f[0] / fds->
cell_size[0];
2208 frame_shift_f[1] = frame_shift_f[1] / fds->
cell_size[1];
2209 frame_shift_f[2] = frame_shift_f[2] / fds->
cell_size[2];
2231 int min[3] = {32767, 32767, 32767}, max[3] = {-32767, -32767, -32767}, res[3];
2232 int total_cells = 1, res_changed = 0, shift_changed = 0;
2233 float min_vel[3], max_vel[3];
2254 int xn = x - new_shift[0];
2255 int yn = y - new_shift[1];
2256 int zn =
z - new_shift[2];
2261 if (xn >=
min[0] && xn <= max[0] && yn >=
min[1] && yn <= max[1] && zn >=
min[2] &&
2272 max_den = (fuel) ? std::max(density[index], fuel[index]) : density[index];
2278 int xx = (x - fds->
res_min[0]) * block_size;
2279 int yy = (y - fds->
res_min[1]) * block_size;
2280 int zz = (
z - fds->
res_min[2]) * block_size;
2282 for (i = 0; i < block_size; i++) {
2283 for (j = 0; j < block_size; j++) {
2284 for (k = 0; k < block_size; k++) {
2285 int big_index =
manta_get_index(xx + i, wt_res[0], yy + j, wt_res[1], zz + k);
2286 float den = (bigfuel) ? std::max(bigdensity[big_index], bigfuel[big_index]) :
2287 bigdensity[big_index];
2288 if (den > max_den) {
2319 if (min_vel[0] > vx[index]) {
2320 min_vel[0] = vx[index];
2322 if (min_vel[1] > vy[index]) {
2323 min_vel[1] = vy[index];
2325 if (min_vel[2] > vz[index]) {
2326 min_vel[2] = vz[index];
2328 if (max_vel[0] < vx[index]) {
2329 max_vel[0] = vx[index];
2331 if (max_vel[1] < vy[index]) {
2332 max_vel[1] = vy[index];
2334 if (max_vel[2] < vz[index]) {
2335 max_vel[2] = vz[index];
2342 for (
int i = 0; i < numflowobj; i++) {
2343 FluidObjectBB *bb = &bb_maps[i];
2345 for (x = bb->min[0]; x < bb->max[0]; x++) {
2346 for (y = bb->min[1]; y < bb->max[1]; y++) {
2347 for (
z = bb->min[2];
z < bb->max[2];
z++) {
2349 x - bb->min[0], bb->res[0], y - bb->min[1], bb->res[1],
z - bb->min[2]);
2350 float max_den = bb->influence[index];
2379 clamp_bounds_in_domain(fds,
min, max, min_vel, max_vel, fds->
adapt_margin + 1, dt);
2381 for (
int i = 0; i < 3; i++) {
2383 res[i] = max[i] -
min[i];
2384 total_cells *= res[i];
2393 for (j = 0; j < 3; j++) {
2407 if (res_changed || shift_changed) {
2422BLI_INLINE void apply_outflow_fields(
int index,
2423 float distance_value,
2436 phiout[index] = std::min(distance_value, phiout[index]);
2441 density[index] = 0.0f;
2448 react[index] = 0.0f;
2451 color_r[index] = 0.0f;
2452 color_g[index] = 0.0f;
2453 color_b[index] = 0.0f;
2458 float emission_value,
2459 float distance_value,
2462 const float *density,
2470 const float *color_r,
2472 const float *color_g,
2474 const float *color_b,
2481 phi_in[index] = std::min(distance_value, phi_in[index]);
2487 emission_in[index] = std::max(emission_value, emission_in[index]);
2492 float dens_old = (density) ? density[index] : 0.0;
2495 float fuel_flow = (fuel) ? emission_value * ffs->
fuel_amount : 0.0f;
2497 if (heat && heat_in) {
2498 if (emission_value > 0.0f) {
2499 heat_in[index] = ADD_IF_LOWER(heat[index], ffs->
temperature);
2504 if (absolute_flow) {
2505 if (density && density_in) {
2508 density_in[index] = std::max(dens_flow, density_in[index]);
2511 if (fuel && fuel_in) {
2514 fuel_in[index] = std::max(fuel_flow, fuel_in[index]);
2520 if (density && density_in) {
2522 density_in[index] += dens_flow;
2523 CLAMP(density_in[index], 0.0f, 1.0f);
2526 if (fuel && fuel_in) {
2528 fuel_in[index] += fuel_flow;
2529 CLAMP(fuel_in[index], 0.0f, 10.0f);
2535 if (color_r && color_r_in) {
2537 float total_dens = density[index] / (dens_old + dens_flow);
2538 color_r_in[index] = (color_r[index] + ffs->
color[0] * dens_flow) * total_dens;
2539 color_g_in[index] = (color_g[index] + ffs->
color[1] * dens_flow) * total_dens;
2540 color_b_in[index] = (color_b[index] + ffs->
color[2] * dens_flow) * total_dens;
2545 if (fuel && fuel_in) {
2547 float value = 1.0f -
pow2f(1.0f - emission_value);
2549 if (fuel_in[index] > FLT_EPSILON && value > react[index]) {
2550 float f = fuel_flow / fuel_in[index];
2551 react_in[index] = value * f + (1.0f - f) * react[index];
2552 CLAMP(react_in[index], 0.0f, value);
2592 active_fields &= ~prev_flags;
2595 for (flow_index = 0; flow_index < numflowobj; flow_index++) {
2596 Object *flow_ob = flowobjs[flow_index];
2612 ffs->
flags &= ~FLUID_FLOW_NEEDS_UPDATE;
2667static bool escape_flowsobject(
Object *flowobj,
2673 bool is_static = is_static_object(flowobj);
2676 bool gas_flow =
ELEM(
2692 if (liquid_flow && is_geometry && !is_first_frame) {
2696 if ((liquid_flow && gas_domain) || (gas_flow && liquid_domain)) {
2701 if (liquid_flow && is_static && !is_first_frame && !is_resume && !use_velocity) {
2707static void compute_flowsemission(
Scene *scene,
2708 FluidObjectBB *bb_maps,
2716 float time_per_frame)
2721 for (
int flow_index = 0; flow_index < numflowobjs; flow_index++) {
2722 Object *flowobj = flowobjs[flow_index];
2735 FluidObjectBB *bb = &bb_maps[flow_index];
2738 if (escape_flowsobject(flowobj, fds, ffs, frame)) {
2744 if (is_first_frame) {
2749 float sample_size = 1.0f /
float(subframes + 1);
2750 float subframe_dt = dt * sample_size;
2753 for (
int subframe = 0; subframe <= subframes; subframe++) {
2755 FluidObjectBB bb_temp = {
nullptr};
2758 if ((subframe < subframes || time_per_frame + dt + FLT_EPSILON < frame_length) &&
2761 scene->r.subframe = (time_per_frame + (subframe + 1.0f) * subframe_dt) / frame_length;
2762 scene->r.cfra = frame - 1;
2765 scene->r.subframe = 0.0f;
2766 scene->r.cfra = frame;
2770 CLAMP(scene->r.subframe, 0.0f, 1.0f);
2774 "flow: frame (is first: %d): %d // scene current frame: %d // scene current subframe: "
2791 emit_from_particles(flowobj, fds, ffs, &bb_temp,
depsgraph, scene, subframe_dt);
2794 emit_from_particles(flowobj, fds, ffs, bb,
depsgraph, scene, subframe_dt);
2800 emit_from_mesh(flowobj, fds, ffs, &bb_temp, subframe_dt);
2803 emit_from_mesh(flowobj, fds, ffs, bb, subframe_dt);
2807 printf(
"Error: unknown flow emission source\n");
2815 bb_freeData(&bb_temp);
2822 printf(
"flow: frame: %d // time per frame: %f // frame length: %f // dt: %f\n",
2830static void update_flowsfluids(Depsgraph *
depsgraph,
2834 float time_per_frame,
2839 FluidObjectBB *bb_maps =
nullptr;
2840 Object **flowobjs =
nullptr;
2841 uint numflowobjs = 0;
2849 update_flowsflags(fds, flowobjs, numflowobjs);
2850 ensure_flowsfields(fds);
2853 bb_maps =
static_cast<FluidObjectBB *
>(
2854 MEM_callocN(
sizeof(FluidObjectBB) * numflowobjs,
"fluid_flow_bb_maps"));
2857 compute_flowsemission(scene,
2870 adaptive_domain_adjust(fds, ob, bb_maps, numflowobjs, dt);
2906 BLI_assert((color_r && color_g && color_b) || (!color_r && !color_g && !color_b));
2907 BLI_assert((color_r_in && color_g_in && color_b_in) ||
2908 (!color_r_in && !color_g_in && !color_b_in));
2909 BLI_assert((velx_initial && vely_initial && velz_initial) ||
2910 (!velx_initial && !vely_initial && !velz_initial));
2914 for (
z = 0;
z < fds->
res[0] * fds->
res[1] * fds->
res[2];
z++) {
2916 if (phistatic_in && is_first_frame) {
2923 if (phioutstatic_in && is_first_frame) {
2931 density_in[
z] = density[
z];
2934 heat_in[
z] = heat[
z];
2936 if (color_r_in && color_g_in && color_b_in) {
2937 color_r_in[
z] = color_r[
z];
2938 color_g_in[
z] = color_b[
z];
2939 color_b_in[
z] = color_g[
z];
2942 fuel_in[
z] = fuel[
z];
2943 react_in[
z] = react[
z];
2946 emission_in[
z] = 0.0f;
2948 if (velx_initial && vely_initial && velz_initial) {
2949 velx_initial[
z] = 0.0f;
2950 vely_initial[
z] = 0.0f;
2951 velz_initial[
z] = 0.0f;
2960 for (
int flow_index = 0; flow_index < numflowobjs; flow_index++) {
2961 Object *flowobj = flowobjs[flow_index];
2977 bool is_static = is_static_object(flowobj) &&
2980 FluidObjectBB *bb = &bb_maps[flow_index];
2981 float *velocity_map = bb->velocity;
2982 float *emission_map = bb->influence;
2983 float *distance_map = bb->distances;
2985 int gx, gy, gz, ex, ey, ez, dx, dy, dz;
2986 size_t e_index, d_index;
2989 for (gx = bb->min[0]; gx < bb->max[0]; gx++) {
2990 for (gy = bb->min[1]; gy < bb->max[1]; gy++) {
2991 for (gz = bb->min[2]; gz < bb->max[2]; gz++) {
2993 ex = gx - bb->min[0];
2994 ey = gy - bb->min[1];
2995 ez = gz - bb->min[2];
3004 if (dx < 0 || dy < 0 || dz < 0 || dx >= fds->
res[0] || dy >= fds->
res[1] ||
3012 float *levelset = ((is_first_frame || is_resume) && is_static) ? phioutstatic_in :
3014 apply_outflow_fields(d_index,
3015 distance_map[e_index],
3026 else if (is_geometry && !is_first_frame) {
3027 apply_inflow_fields(ffs,
3049 else if (is_geometry || is_inflow) {
3050 float *levelset = ((is_first_frame || is_resume) && is_static && !is_geometry) ?
3053 apply_inflow_fields(ffs,
3054 emission_map[e_index],
3055 distance_map[e_index],
3076 float vel_initial[3];
3077 vel_initial[0] = velx_initial[d_index];
3078 vel_initial[1] = vely_initial[d_index];
3079 vel_initial[2] = velz_initial[d_index];
3081 float vel_map_strength =
len_squared_v3(velocity_map + 3 * e_index);
3082 if (vel_map_strength > vel_initial_strength) {
3083 velx_initial[d_index] = velocity_map[e_index * 3];
3084 vely_initial[d_index] = velocity_map[e_index * 3 + 1];
3085 velz_initial[d_index] = velocity_map[e_index * 3 + 2];
3102struct UpdateEffectorsData {
3119static void update_effectors_task_cb(
void *__restrict userdata,
3123 UpdateEffectorsData *data =
static_cast<UpdateEffectorsData *
>(userdata);
3126 for (
int y = 0; y < fds->
res[1]; y++) {
3127 for (
int z = 0;
z < fds->
res[2];
z++) {
3130 float voxel_center[3] = {0, 0, 0}, vel[3] = {0, 0, 0}, retvel[3] = {0, 0, 0};
3133 if ((data->fuel && std::max(data->density[index], data->fuel[index]) < FLT_EPSILON) ||
3134 (data->density && data->density[index] < FLT_EPSILON) ||
3135 (data->phi_obs_in && data->phi_obs_in[index] < 0.0f) ||
3136 data->flags[index] & 2)
3142 vel[0] = data->velocity_x[index];
3143 vel[1] = data->velocity_y[index];
3144 vel[2] = data->velocity_z[index];
3161 data->effectors,
nullptr, fds->
effector_weights, &epoint, retvel,
nullptr,
nullptr);
3171 CLAMP3(retvel, -1.0f, 1.0f);
3172 data->force_x[index] = retvel[0];
3173 data->force_y[index] = retvel[1];
3174 data->force_z[index] = retvel[2];
3178 printf(
"setting force: [%f, %f, %f]\n",
3179 data->force_x[index],
3180 data->force_y[index],
3181 data->force_z[index]);
3187static void update_effectors(
3197 UpdateEffectorsData
data;
3200 data.effectors = effectors;
3214 settings.min_iter_per_thread = 2;
3232 float cell_size_scaled[3];
3235 const VArraySpan orig_material_indices = *orig_attributes.
lookup<
int>(
"material_index",
3237 const short mp_mat_nr = orig_material_indices.
is_empty() ? 0 : orig_material_indices[0];
3240 int num_verts, num_faces;
3251 printf(
"num_verts: %d, num_faces: %d\n", num_verts, num_faces);
3254 if (!num_verts || !num_faces) {
3267 .lookup_or_default<
bool>(
"sharp_face", AttrDomain::Face,
false)
3279 float max_size = std::max({size[0], size[1], size[2]});
3282 co_scale[0] = max_size / ob->
scale[0];
3283 co_scale[1] = max_size / ob->
scale[1];
3284 co_scale[2] = max_size / ob->
scale[2];
3287 co_offset[0] = (fds->
p0[0] + fds->
p1[0]) / 2.0f;
3288 co_offset[1] = (fds->
p0[1] + fds->
p1[1]) / 2.0f;
3289 co_offset[2] = (fds->
p0[2] + fds->
p1[2]) / 2.0f;
3298 if (use_speedvectors) {
3299 velocities = attributes.lookup_or_add_for_write_only_span<
float3>(
"velocity",
3304 for (i = 0; i < num_verts; i++) {
3324 printf(
"positions[i][0]: %f, positions[i][1]: %f, positions[i][2]: %f\n",
3332 printf(
"no_s[0]: %d, no_s[1]: %d, no_s[2]: %d\n", no_s[0], no_s[1], no_s[2]);
3335 if (use_speedvectors) {
3341 printf(
"velocities[%d].x: %f, velocities[%d].y: %f, velocities[%d].z: %f\n",
3343 velocities.
span[i].x,
3345 velocities.
span[i].y,
3347 velocities.
span[i].z);
3353 "material_index", AttrDomain::Face);
3356 for (
const int i : face_offsets.index_range().drop_back(1)) {
3358 material_indices.
span[i] = mp_mat_nr;
3360 face_offsets[i] = i * 3;
3367 printf(
"mloops[0].v: %d, mloops[1].v: %d, mloops[2].v: %d\n",
3375 material_indices.
finish();
3394 float ob_loc[3] = {0};
3395 float ob_cache_loc[3] = {0};
3448 face_offsets.
fill(4);
3453 corner_vert = &corner_verts[0 * 4];
3459 corner_vert = &corner_verts[1 * 4];
3465 corner_vert = &corner_verts[2 * 4];
3471 corner_vert = &corner_verts[3 * 4];
3477 corner_vert = &corner_verts[4 * 4];
3483 corner_vert = &corner_verts[5 * 4];
3492 mul_m4_v3(ob->object_to_world().ptr(), ob_loc);
3498 for (
int i = 0; i < num_verts; i++) {
3507static int manta_step(
3511 float dt, frame_length, time_total, time_total_old;
3512 float time_per_frame;
3513 bool init_resolution =
true;
3528 manta_set_domain_from_mesh(fds, ob, mesh, init_resolution);
3541 while (time_per_frame + FLT_EPSILON < frame_length) {
3550 update_flowsfluids(
depsgraph, scene, ob, fds, time_per_frame, frame_length, frame, dt);
3553 if (
G.is_break && !mode_replay) {
3561 update_obstacles(
depsgraph, scene, ob, fds, time_per_frame, frame_length, frame, dt);
3564 if (
G.is_break && !mode_replay) {
3571 update_effectors(
depsgraph, scene, ob, fds, dt);
3576 time_per_frame += dt;
3588 manta_smoke_calc_transparency(
3596static void manta_guiding(
3604 update_obstacles(
depsgraph, scene, ob, fds, dt, dt, frame, dt);
3615 const int scene_framenr)
3617 if (scene_framenr >= fmd->
time) {
3618 fluid_modifier_init(fmd,
depsgraph, ob, scene, mesh);
3628 if (scene_framenr > fmd->
time) {
3629 fmd->
time = scene_framenr;
3631 else if (scene_framenr < fmd->time) {
3632 fmd->
time = scene_framenr;
3642 const int scene_framenr)
3644 if (scene_framenr >= fmd->
time) {
3645 fluid_modifier_init(fmd,
depsgraph, ob, scene, mesh);
3655 if (scene_framenr > fmd->
time) {
3656 fmd->
time = scene_framenr;
3658 else if (scene_framenr < fmd->time) {
3659 fmd->
time = scene_framenr;
3669 const int scene_framenr)
3672 Object *guide_parent =
nullptr;
3677 bool is_startframe, has_advanced;
3679 has_advanced = (scene_framenr == fmd->
time + 1);
3683 bool escape =
false;
3688 if (scene_framenr < fds->cache_frame_start ||
3704 if (scene_framenr < fds->cache_frame_start || scene_framenr > fds->
cache_frame_end) {
3710 if (escape && fds->
fluid) {
3738 update_flowsflags(fds, objs, numobj);
3744 update_obstacleflags(fds, objs, numobj);
3750 if (!fds->
fluid && !fluid_modifier_init(fmd,
depsgraph, ob, scene, mesh)) {
3751 CLOG_ERROR(&
LOG,
"Fluid initialization failed. Should not happen!");
3760 if (fmd_parent && fmd_parent->
domain) {
3766 int o_res[3], o_min[3], o_max[3], o_shift[3];
3778 update_final_gravity(fds, scene);
3780 int next_frame = scene_framenr + 1;
3781 int prev_frame = scene_framenr - 1;
3785 int data_frame = scene_framenr, noise_frame = scene_framenr;
3786 int mesh_frame = scene_framenr, particles_frame = scene_framenr, guide_frame = scene_framenr;
3788 bool with_smoke, with_liquid;
3792 bool drops, bubble, floater;
3798 bool with_script, with_noise, with_mesh, with_particles, with_guide;
3803 with_particles = drops || bubble || floater;
3805 bool has_data, has_noise, has_mesh, has_particles, has_guide, has_config;
3817 ensure_flowsfields(fds);
3818 ensure_obstaclefields(fds);
3821 bool baking_data, baking_noise, baking_mesh, baking_particles, baking_guide;
3828 bool resume_data, resume_noise, resume_mesh, resume_particles, resume_guide;
3835 bool read_cache, bake_cache;
3837 bake_cache = baking_data || baking_noise || baking_mesh || baking_particles || baking_guide;
3839 bool next_data, next_noise, next_mesh, next_particles, next_guide;
3846 bool prev_data, prev_noise, prev_mesh, prev_particles, prev_guide;
3864 if (!baking_data && !baking_noise && !baking_mesh && !baking_particles && !baking_guide) {
3878 if (baking_data && resume_data) {
3879 data_frame = prev_frame;
3881 if (baking_noise && resume_noise) {
3882 noise_frame = prev_frame;
3884 if (baking_mesh && resume_mesh) {
3885 mesh_frame = prev_frame;
3887 if (baking_particles && resume_particles) {
3888 particles_frame = prev_frame;
3890 if (baking_guide && resume_guide) {
3891 guide_frame = prev_frame;
3905 baking_data = !has_data && (is_startframe || prev_data);
3906 if (with_smoke && with_noise) {
3907 baking_noise = !has_noise && (is_startframe || prev_noise);
3909 if (with_liquid && with_mesh) {
3910 baking_mesh = !has_mesh && (is_startframe || prev_mesh);
3912 if (with_liquid && with_particles) {
3913 baking_particles = !has_particles && (is_startframe || prev_particles);
3922 bool read_partial =
false, read_all =
false;
3929 if (with_liquid && with_mesh) {
3930 if (mesh_frame != scene_framenr) {
3942 if (with_liquid && with_particles) {
3943 if (particles_frame != scene_framenr) {
3947 read_partial = !baking_data && !baking_particles && next_particles;
3948 read_all = !read_partial && with_resumable_cache;
3959 if (with_smoke && with_noise) {
3960 if (noise_frame != scene_framenr) {
3967 fds, o_res, fds->
res, o_min, fds->
res_min, o_max, o_shift, fds->
shift);
3970 read_partial = !baking_data && !baking_noise && next_noise;
3971 read_all = !read_partial && with_resumable_cache;
3974 read_partial = !baking_data && !baking_noise && next_data && next_noise;
3975 read_all = !read_partial && with_resumable_cache;
3980 if (data_frame != scene_framenr) {
3991 read_partial = !baking_data && !baking_particles && !baking_mesh && next_data &&
3993 read_all = !read_partial && with_resumable_cache;
4002 if (!baking_data && !baking_noise && !baking_mesh && !baking_particles && !baking_guide) {
4009 baking_guide = !has_guide && (is_startframe || prev_guide);
4011 baking_data = !has_data && (is_startframe || prev_data);
4012 if (with_smoke && with_noise) {
4013 baking_noise = !has_noise && (is_startframe || prev_noise);
4015 if (with_liquid && with_mesh) {
4016 baking_mesh = !has_mesh && (is_startframe || prev_mesh);
4018 if (with_liquid && with_particles) {
4019 baking_particles = !has_particles && (is_startframe || prev_particles);
4023 if (is_startframe || has_advanced) {
4024 bake_cache = baking_data || baking_noise || baking_mesh || baking_particles;
4035 if (with_script && is_startframe) {
4044 if (baking_guide && with_guide) {
4045 manta_guiding(
depsgraph, scene, ob, fmd, scene_framenr);
4049 if (manta_step(
depsgraph, scene, ob, mesh, fmd, scene_framenr)) {
4054 if (has_data || baking_data) {
4055 if (baking_noise && with_smoke && with_noise) {
4062 if (baking_mesh && with_liquid && with_mesh) {
4065 if (baking_particles && with_liquid && with_particles) {
4074 fds->
flags &= ~FLUID_DOMAIN_FILE_LOAD;
4075 fmd->
time = scene_framenr;
4078static void fluid_modifier_process(
4084 fluid_modifier_processFlow(fmd,
depsgraph, scene, ob, mesh, scene_framenr);
4087 fluid_modifier_processEffector(fmd,
depsgraph, scene, ob, mesh, scene_framenr);
4090 fluid_modifier_processDomain(fmd,
depsgraph, scene, ob, mesh, scene_framenr);
4099 bool needs_viewport_update =
false;
4108 fluid_modifier_process(fmd,
depsgraph, scene, ob, mesh);
4121 needs_viewport_update =
true;
4127 bool baking_data, baking_noise, baking_mesh, baking_particles, baking_guide;
4134 if (with_mesh && !baking_data && !baking_noise && !baking_mesh && !baking_particles &&
4137 needs_viewport_update =
true;
4143 Mesh *result =
nullptr;
4145 if (needs_viewport_update) {
4148 result = create_liquid_geometry(fmd->
domain, scene, mesh, ob);
4151 result = create_smoke_geometry(fmd->
domain, mesh, ob);
4180static float calc_voxel_transp(
4181 float *result,
const float *input,
int res[3],
int *pixel,
float *t_ray,
float correct)
4183 const size_t index =
manta_get_index(pixel[0], res[0], pixel[1], res[1], pixel[2]);
4186 *t_ray *=
expf(input[index] * correct);
4188 if (result[index] < 0.0f) {
4189 result[index] = *t_ray;
4195static void bresenham_linie_3D(
int x1,
4208 int dx, dy, dz, i,
l, m, n, x_inc, y_inc, z_inc, err_1, err_2, dx2, dy2, dz2;
4219 x_inc = (dx < 0) ? -1 : 1;
4221 y_inc = (dy < 0) ? -1 : 1;
4223 z_inc = (dz < 0) ? -1 : 1;
4229 if ((
l >= m) && (
l >= n)) {
4232 for (i = 0; i <
l; i++) {
4233 if (cb(result, input, res, pixel, t_ray, correct) <= FLT_EPSILON) {
4249 else if ((m >=
l) && (m >= n)) {
4252 for (i = 0; i < m; i++) {
4253 if (cb(result, input, res, pixel, t_ray, correct) <= FLT_EPSILON) {
4272 for (i = 0; i < n; i++) {
4273 if (cb(result, input, res, pixel, t_ray, correct) <= FLT_EPSILON) {
4289 cb(result, input, res, pixel, t_ray, correct);
4298 int slabsize = fds->
res[0] * fds->
res[1];
4301 float correct = -7.0f * fds->
dx;
4303 if (!get_light(scene, view_layer, light)) {
4309 light[0] = (light[0] - fds->
p0[0]) / fds->
cell_size[0] - 0.5f -
float(fds->
res_min[0]);
4310 light[1] = (light[1] - fds->
p0[1]) / fds->
cell_size[1] - 0.5f -
float(fds->
res_min[1]);
4311 light[2] = (light[2] - fds->
p0[2]) / fds->
cell_size[2] - 0.5f -
float(fds->
res_min[2]);
4319 for (
int z = 0;
z < fds->
res[2];
z++) {
4320 size_t index =
z * slabsize;
4322 for (
int y = 0; y < fds->
res[1]; y++) {
4323 for (
int x = 0; x < fds->
res[0]; x++, index++) {
4324 float voxel_center[3];
4330 shadow[index] = -1.0f;
4332 voxel_center[0] =
float(x);
4333 voxel_center[1] =
float(y);
4334 voxel_center[2] =
float(
z);
4350 CLAMP(cell[0], 0, fds->
res[0] - 1);
4351 CLAMP(cell[1], 0, fds->
res[1] - 1);
4352 CLAMP(cell[2], 0, fds->
res[2] - 1);
4354 bresenham_linie_3D(cell[0],
4368 shadow[index] = t_ray;
4385 float density = 0.0f, fuel = 0.0f;
4388 manta_pos_to_cell(fds,
pos);
4405 if (
pos[0] < 0.0f ||
pos[1] < 0.0f ||
pos[2] < 0.0f) {
4408 if (
pos[0] > 1.0f ||
pos[1] > 1.0f ||
pos[2] > 1.0f) {
4423 vel_mag =
len_v3(velocity);
4433 return std::max(density, fuel);
4459 const char *pset_name,
4460 const char *parts_name,
4461 const char *psys_name,
4462 const int psys_type)
4470 psys = MEM_cnew<ParticleSystem>(__func__);
4472 part->type = psys_type;
4474 part->draw_size = 0.01f;
4497 next_psys = psys->
next;
4498 if (psys->
part->
type == particle_type) {
4523 settings->cache_frame_start = (value > settings->cache_frame_end) ? settings->cache_frame_end :
4529 settings->cache_frame_end = (value < settings->cache_frame_start) ? settings->cache_frame_start :
4535 if (cache_mesh_format == settings->cache_mesh_format) {
4539 settings->cache_mesh_format = cache_mesh_format;
4544 if (cache_data_format == settings->cache_data_format) {
4548 settings->cache_data_format = cache_data_format;
4553 if (cache_particle_format == settings->cache_particle_format) {
4557 settings->cache_particle_format = cache_particle_format;
4562 if (cache_noise_format == settings->cache_noise_format) {
4566 settings->cache_noise_format = cache_noise_format;
4572 settings->border_collisions &= value;
4575 settings->border_collisions |= value;
4582 settings->particle_type &= ~value;
4585 settings->particle_type |= value;
4613 settings->type = type;
4618 settings->behavior = behavior;
4633 settings->type = type;
4638 settings->type = type;
4645 const char coba_field = settings->coba_field;
4646 const char data_depth = settings->openvdb_data_depth;
4649 if (
ELEM(coba_field,
4665 if (
ELEM(coba_field,
4727 fmd->
flow->
flags &= ~FLUID_FLOW_NEEDS_UPDATE;
4730 fmd->
flow =
nullptr;
4778 else if (fmd->
flow) {
4781 fmd->
flow->
flags &= ~FLUID_FLOW_NEEDS_UPDATE;
4826#ifndef WITH_OPENVDB_BLOSC
4833 char cache_name[64];
5050 else if (tfmd->
flow) {
5107 static int counter = 1;
void free_bvhtree_from_mesh(BVHTreeFromMesh *data)
BVHTree * BKE_bvhtree_from_mesh_get(BVHTreeFromMesh *data, const Mesh *mesh, BVHCacheType bvh_cache_type, int tree_type)
@ BVHTREE_FROM_CORNER_TRIS
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.
const void * CustomData_get_layer_named(const CustomData *data, eCustomDataType type, blender::StringRef name)
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)
@ LIB_ID_COPY_SET_COPIED_ON_WRITE
void BKE_id_free(Main *bmain, void *idv)
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.
bool BKE_object_modifier_update_subframe(Depsgraph *depsgraph, Scene *scene, Object *ob, bool update_mesh, int parent_recursion, float frame, int type)
bool BKE_object_moves_in_time(const Object *object, bool recurse_parent)
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(struct ListBase *listbase, void *vlink) ATTR_NONNULL(1)
void BLI_remlink(struct 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 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 abs_v3(float 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(...)
#define STRNCPY(dst, 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
#define BLI_MUTEX_INITIALIZER
void BLI_rw_mutex_lock(ThreadRWMutex *mutex, int mode)
void BLI_mutex_lock(ThreadMutex *mutex)
void BLI_mutex_unlock(ThreadMutex *mutex)
void BLI_rw_mutex_free(ThreadRWMutex *mutex)
void BLI_rw_mutex_unlock(ThreadRWMutex *mutex)
pthread_mutex_t ThreadMutex
#define INIT_MINMAX(min, max)
#define CLAMP3(vec, b, c)
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_PARTICLE_SPRAY
@ FLUID_DOMAIN_PARTICLE_FOAM
@ FLUID_DOMAIN_PARTICLE_TRACER
@ FLUID_DOMAIN_PARTICLE_BUBBLE
#define FLUID_DOMAIN_DIR_DATA
#define FLUID_DOMAIN_DIR_PARTICLES
@ 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
@ FLUID_DOMAIN_TYPE_LIQUID
#define FLUID_DOMAIN_DIR_DEFAULT
#define FLUID_DOMAIN_DIR_MESH
@ FLUID_EFFECTOR_NEEDS_UPDATE
@ FLUID_EFFECTOR_USE_EFFEC
@ FLUID_EFFECTOR_USE_PLANE_INIT
#define FLUID_DOMAIN_DIR_GUIDE
#define FLUID_DOMAIN_DIR_SCRIPT
@ FLUID_DOMAIN_GUIDE_SRC_DOMAIN
@ 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
@ VDB_PRECISION_MINI_FLOAT
@ VDB_PRECISION_HALF_FLOAT
@ 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
@ FLUID_DOMAIN_CACHE_REPLAY
@ FLUID_DOMAIN_CACHE_MODULAR
#define FLUID_DOMAIN_DIR_CONFIG
@ FLUID_FLOW_USE_PART_SIZE
@ FLUID_FLOW_NEEDS_UPDATE
@ FLUID_FLOW_USE_PLANE_INIT
@ FLUID_FLOW_INITVELOCITY
@ FLUID_FLOW_SOURCE_PARTICLES
@ FLUID_DOMAIN_USE_ADAPTIVE_DOMAIN
@ FLUID_DOMAIN_USE_RESUMABLE_CACHE
@ FLUID_DOMAIN_EXPORT_MANTA_SCRIPT
@ FLUID_DOMAIN_USE_SPEED_VECTORS
@ FLUID_FLOW_TEXTURE_MAP_AUTO
@ FLUID_FLOW_TYPE_SMOKEFIRE
#define FLUID_DOMAIN_DIR_NOISE
@ FLUID_EFFECTOR_TYPE_GUIDE
@ FLUID_EFFECTOR_TYPE_COLLISION
@ FLUID_DOMAIN_BORDER_BOTTOM
@ FLUID_DOMAIN_BORDER_LEFT
@ FLUID_DOMAIN_BORDER_RIGHT
@ FLUID_DOMAIN_BORDER_FRONT
@ FLUID_DOMAIN_BORDER_TOP
@ FLUID_DOMAIN_BORDER_BACK
@ FLUID_FLOW_BEHAVIOR_GEOMETRY
@ FLUID_FLOW_BEHAVIOR_OUTFLOW
@ FLUID_FLOW_BEHAVIOR_INFLOW
@ 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.
ATTR_WARN_UNUSED_RESULT const BMVert * v2
ATTR_WARN_UNUSED_RESULT const BMLoop * l
ATTR_WARN_UNUSED_RESULT const BMVert * v
SIMD_FORCE_INLINE const btScalar & z() const
Return the z value.
constexpr void fill(const T &value) const
constexpr bool is_empty() const
GAttributeReader lookup(const StringRef attribute_id) const
pow(value.r - subtrahend, 2.0)") .do_static_compilation(true)
const Depsgraph * depsgraph
draw_view in_light_buf[] float
draw_view push_constant(Type::INT, "radiance_src") .push_constant(Type capture_info_buf storage_buf(1, Qualifier::READ, "ObjectBounds", "bounds_buf[]") .push_constant(Type draw_view int
smooth(Type::VEC3, "P") .flat(Type out_color storage_buf(0, Qualifier::READ, "Surfel", "surfels_buf[]") .push_constant(Type smooth(Type::VEC4, "interp_color")
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_malloc_arrayN)(size_t len, size_t size, const char *str)
void *(* MEM_calloc_arrayN)(size_t len, size_t size, const char *str)
void MEM_freeN(void *vmemh)
void *(* MEM_callocN)(size_t len, const char *str)
void *(* MEM_dupallocN)(const 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_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_smoke_get_shadow(struct MANTA *fluid)
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)
bool manta_liquid_ensure_sndparts(struct MANTA *fluid, struct FluidModifierData *fmd)
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)
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_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_liquid_export_script(struct MANTA *smoke, struct FluidModifierData *fmd)
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)
ccl_device_inline float2 floor(const float2 a)
ccl_device_inline float3 ceil(const float3 a)
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)
OffsetIndices< int > accumulate_counts_to_offsets(MutableSpan< int > counts_to_offsets, int start_offset=0)
bool is_adaptive(const CpuPatchTable *patch_table)
static void update_velocities(PTCacheEdit *edit)
BVHTree_RayCastCallback raycast_callback
BVHTree_NearestPointCallback nearest_callback
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
MutableVArraySpan< T > span
ccl_device_inline int abs(int x)