Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--intern/mantaflow/intern/strings/liquid_script.h3
-rw-r--r--intern/mantaflow/intern/strings/smoke_script.h4
-rw-r--r--source/blender/blenkernel/intern/fluid.c222
-rw-r--r--source/blender/editors/physics/physics_fluid.c3
4 files changed, 117 insertions, 115 deletions
diff --git a/intern/mantaflow/intern/strings/liquid_script.h b/intern/mantaflow/intern/strings/liquid_script.h
index 6cbbf06f0d2..bb42b781c19 100644
--- a/intern/mantaflow/intern/strings/liquid_script.h
+++ b/intern/mantaflow/intern/strings/liquid_script.h
@@ -175,9 +175,6 @@ def liquid_adaptive_step_$ID$(framenr):\n\
extrapolateLsSimple(phi=phiObs_s$ID$, distance=int(res_s$ID$/2), inside=True)\n\
extrapolateLsSimple(phi=phiObs_s$ID$, distance=int(res_s$ID$/2), inside=False)\n\
\n\
- mantaMsg('Initializing fluid levelset')\n\
- extrapolateLsSimple(phi=phiIn_s$ID$, distance=int(res_s$ID$/2), inside=True)\n\
- extrapolateLsSimple(phi=phiIn_s$ID$, distance=int(res_s$ID$/2), inside=False)\n\
phi_s$ID$.join(phiIn_s$ID$)\n\
\n\
if using_obstacle_s$ID$:\n\
diff --git a/intern/mantaflow/intern/strings/smoke_script.h b/intern/mantaflow/intern/strings/smoke_script.h
index 9277923fa7a..ad966503fd1 100644
--- a/intern/mantaflow/intern/strings/smoke_script.h
+++ b/intern/mantaflow/intern/strings/smoke_script.h
@@ -288,10 +288,6 @@ def smoke_adaptive_step_$ID$(framenr):\n\
extrapolateLsSimple(phi=phiObs_s$ID$, distance=int(res_s$ID$/2), inside=True)\n\
extrapolateLsSimple(phi=phiObs_s$ID$, distance=int(res_s$ID$/2), inside=False)\n\
\n\
- mantaMsg('Initializing fluid levelset')\n\
- extrapolateLsSimple(phi=phiIn_s$ID$, distance=int(res_s$ID$/2), inside=True)\n\
- extrapolateLsSimple(phi=phiIn_s$ID$, distance=int(res_s$ID$/2), inside=False)\n\
- \n\
if using_outflow_s$ID$:\n\
phiOut_s$ID$.join(phiOutIn_s$ID$)\n\
\n\
diff --git a/source/blender/blenkernel/intern/fluid.c b/source/blender/blenkernel/intern/fluid.c
index cb94a78e619..12c65027e25 100644
--- a/source/blender/blenkernel/intern/fluid.c
+++ b/source/blender/blenkernel/intern/fluid.c
@@ -630,9 +630,10 @@ static void obstacles_from_mesh_task_cb(void *__restrict userdata,
ObstaclesFromDMData *data = userdata;
FluidDomainSettings *mds = data->mds;
- /* Distance from unit cube center to one of the vertices.
- * I.e. half the cube diagonal or sqrt(3) * 0.5. */
- const float surface_distance = 0.867f;
+ /* Distance between two opposing vertices in a unit cube.
+ * I.e. the unit cube diagonal or sqrt(3).
+ * This value is our nearest neighbour search distance. */
+ const float surface_distance = 1.732;
for (int x = mds->res_min[0]; x < mds->res_max[0]; x++) {
for (int y = mds->res_min[1]; y < mds->res_max[1]; y++) {
@@ -646,7 +647,7 @@ static void obstacles_from_mesh_task_cb(void *__restrict userdata,
surface_distance; /* find_nearest uses squared distance */
bool has_inc_obj = false;
- /* find the nearest point on the mesh */
+ /* Find the nearest point on the mesh. */
if (BLI_bvhtree_find_nearest(
data->tree->tree, ray_start, &nearest, data->tree->nearest_callback, data->tree) !=
-1) {
@@ -1433,11 +1434,12 @@ static void update_mesh_distances(int index,
{
float min_dist = PHI_MAX;
- /* Ensure that planes get initialized correctly. */
+ /* a) Planar initialization */
if (use_plane_init) {
BVHTreeNearest nearest = {0};
nearest.index = -1;
- nearest.dist_sq = surface_thickness;
+ nearest.dist_sq = surface_thickness *
+ surface_thickness; /* find_nearest uses squared distance */
if (BLI_bvhtree_find_nearest(
tree_data->tree, ray_start, &nearest, tree_data->nearest_callback, tree_data) != -1) {
@@ -1445,12 +1447,14 @@ static void update_mesh_distances(int index,
sub_v3_v3v3(ray, ray_start, nearest.co);
min_dist = len_v3(ray);
min_dist = (-1.0f) * fabsf(min_dist);
- mesh_distances[index] = MIN2(mesh_distances[index], min_dist);
+ mesh_distances[index] = min_dist;
}
return;
}
- /* First pass: Ray-casts in 26 directions
+ /* b) Volumetric initialization: 1) Ray-casts around mesh object. */
+
+ /* Ray-casts in 26 directions.
* (6 main axis + 12 quadrant diagonals (2D) + 8 octant diagonals (3D)). */
float ray_dirs[26][3] = {
{1.0f, 0.0f, 0.0f}, {0.0f, 1.0f, 0.0f}, {0.0f, 0.0f, 1.0f}, {-1.0f, 0.0f, 0.0f},
@@ -1462,8 +1466,9 @@ static void update_mesh_distances(int index,
{-1.0f, 1.0f, -1.0f}, {-1.0f, -1.0f, -1.0f}};
size_t ray_cnt = sizeof ray_dirs / sizeof ray_dirs[0];
- /* Count for ray misses (no face hit) and cases where ray direction matches face normal
- * direction. */
+ /* Count ray mesh misses (i.e. no face hit) and cases where the ray direction matches the face
+ * normal direction. From this information it can be derived whether a cell is inside or outside
+ * the mesh. */
int miss_cnt = 0, dir_cnt = 0;
min_dist = PHI_MAX;
@@ -1481,14 +1486,13 @@ static void update_mesh_distances(int index,
tree_data->raycast_callback,
tree_data);
- /* Ray did not hit mesh. Current point definitely not inside mesh. Inside mesh all rays have to
- * hit. */
+ /* Ray did not hit mesh.
+ * Current point definitely not inside mesh. Inside mesh as all rays have to hit. */
if (hit_tree.index == -1) {
miss_cnt++;
- continue;
}
- /* Ray and normal are in pointing opposite directions. */
+ /* Ray and normal are pointing in opposite directions. */
if (dot_v3v3(ray_dirs[i], hit_tree.no) <= 0) {
dir_cnt++;
}
@@ -1498,25 +1502,30 @@ static void update_mesh_distances(int index,
}
}
- /* Point lies inside mesh. Use negative sign for distance value. */
+ /* Point lies inside mesh. Use negative sign for distance value.
+ * This "if statement" has 2 conditions that can be true for points outside mesh. */
if (!(miss_cnt > 0 || dir_cnt == ray_cnt)) {
min_dist = (-1.0f) * fabsf(min_dist);
}
- /* Update global distance array but ensure that older entries are not overridden. */
- mesh_distances[index] = MIN2(mesh_distances[index], min_dist);
+ /* Update global distance array with distance value. */
+ mesh_distances[index] = min_dist;
- /* Second pass: Use nearest neighbor search on mesh surface. */
+ /* b) Volumetric initialization: 2) Use nearest neighbor search on mesh surface. */
+
+ /* Distance between two opposing vertices in a unit cube.
+ * I.e. the unit cube diagonal or sqrt(3).
+ * This value is our nearest neighbour search distance. */
+ const float surface_distance = 1.732;
BVHTreeNearest nearest = {0};
nearest.index = -1;
- nearest.dist_sq = 5;
+ nearest.dist_sq = surface_distance * surface_distance; /* find_nearest uses squared distance. */
if (BLI_bvhtree_find_nearest(
tree_data->tree, ray_start, &nearest, tree_data->nearest_callback, tree_data) != -1) {
float ray[3] = {0};
sub_v3_v3v3(ray, nearest.co, ray_start);
min_dist = len_v3(ray);
- // CLAMP(min_dist, 0.5, min_dist);
BVHTreeRayHit hit_tree = {0};
hit_tree.index = -1;
@@ -1529,22 +1538,23 @@ static void update_mesh_distances(int index,
/* Only proceed if casted ray hit the mesh surface. */
if (hit_tree.index != -1) {
- /* Ray and normal are in pointing same directions: Point must lie inside mesh. */
+ /* Ray and normal are pointing in the same direction: Point must lie inside mesh. */
if (dot_v3v3(ray, hit_tree.no) > 0) {
min_dist = (-1.0f) * fabsf(min_dist);
}
- /* Update distance value with more accurate one from this nearest neighbor search.
- * Skip if new value would be outside and current value has inside value already. */
- if (!(min_dist > 0 && mesh_distances[index] <= 0)) {
- mesh_distances[index] = min_dist;
- }
+ /* Update distance map with more accurate distance from this nearest neighbor search. */
+ mesh_distances[index] = min_dist;
}
}
+ /* Subtract optional surface thickness value and virtually increase the object size. */
if (surface_thickness) {
mesh_distances[index] -= surface_thickness;
}
+
+ /* Sanity check: Ensure that distances don't explode. */
+ CLAMP(mesh_distances[index], -PHI_MAX, PHI_MAX);
}
static void sample_mesh(FluidFlowSettings *mfs,
@@ -1578,9 +1588,10 @@ static void sample_mesh(FluidFlowSettings *mfs,
hit.dist = PHI_MAX;
nearest.index = -1;
- /* Distance from unit cube center to one of the vertices.
- * I.e. half the cube diagonal or sqrt(3) * 0.5. */
- const float surface_distance = 0.867f;
+ /* Distance between two opposing vertices in a unit cube.
+ * I.e. the unit cube diagonal or sqrt(3).
+ * This value is our nearest neighbour search distance. */
+ const float surface_distance = 1.732;
nearest.dist_sq = surface_distance * surface_distance; /* find_nearest uses squared distance. */
bool is_gas_flow = (mfs->type == FLUID_FLOW_TYPE_SMOKE || mfs->type == FLUID_FLOW_TYPE_FIRE ||
@@ -1625,22 +1636,13 @@ static void sample_mesh(FluidFlowSettings *mfs,
int v1, v2, v3, f_index = nearest.index;
float n1[3], n2[3], n3[3], hit_normal[3];
- /* Emission from surface is based on UI configurable distance value. */
- if (mfs->surface_distance) {
- emission_strength = sqrtf(nearest.dist_sq) / mfs->surface_distance;
- CLAMP(emission_strength, 0.0f, 1.0f);
- emission_strength = pow(1.0f - emission_strength, 0.5f);
- }
- else {
- emission_strength = 0.0f;
- }
-
/* Calculate barycentric weights for nearest point. */
v1 = mloop[mlooptri[f_index].tri[0]].v;
v2 = mloop[mlooptri[f_index].tri[1]].v;
v3 = mloop[mlooptri[f_index].tri[2]].v;
interp_weights_tri_v3(weights, mvert[v1].co, mvert[v2].co, mvert[v3].co, nearest.co);
+ /* Initial velocity of flow object. */
if (mfs->flags & FLUID_FLOW_INITVELOCITY && velocity_map) {
/* Apply normal directional velocity. */
if (mfs->vel_normal) {
@@ -1674,40 +1676,54 @@ static void sample_mesh(FluidFlowSettings *mfs,
velocity_map[index * 3 + 2] += mfs->vel_coord[2];
}
- /* Apply vertex group influence if it is being used. */
- if (defgrp_index != -1 && dvert) {
- float weight_mask = defvert_find_weight(&dvert[v1], defgrp_index) * weights[0] +
- defvert_find_weight(&dvert[v2], defgrp_index) * weights[1] +
- defvert_find_weight(&dvert[v3], defgrp_index) * weights[2];
- emission_strength *= weight_mask;
- }
-
- /* Apply emission texture. */
- if (is_gas_flow && (mfs->flags & FLUID_FLOW_TEXTUREEMIT) && mfs->noise_texture) {
- float tex_co[3] = {0};
- TexResult texres;
+ /* Compute emission strength for smoke flow. */
+ if (is_gas_flow) {
+ /* Emission from surface is based on UI configurable distance value. */
+ if (mfs->surface_distance) {
+ emission_strength = sqrtf(nearest.dist_sq) / mfs->surface_distance;
+ CLAMP(emission_strength, 0.0f, 1.0f);
+ emission_strength = pow(1.0f - emission_strength, 0.5f);
+ }
+ else {
+ emission_strength = 0.0f;
+ }
- if (mfs->texture_type == FLUID_FLOW_TEXTURE_MAP_AUTO) {
- tex_co[0] = ((x - flow_center[0]) / base_res[0]) / mfs->texture_size;
- tex_co[1] = ((y - flow_center[1]) / base_res[1]) / mfs->texture_size;
- tex_co[2] = ((z - flow_center[2]) / base_res[2] - mfs->texture_offset) / mfs->texture_size;
+ /* Apply vertex group influence if it is being used. */
+ if (defgrp_index != -1 && dvert) {
+ float weight_mask = defvert_find_weight(&dvert[v1], defgrp_index) * weights[0] +
+ defvert_find_weight(&dvert[v2], defgrp_index) * weights[1] +
+ defvert_find_weight(&dvert[v3], defgrp_index) * weights[2];
+ emission_strength *= weight_mask;
}
- else if (mloopuv) {
- const float *uv[3];
- uv[0] = mloopuv[mlooptri[f_index].tri[0]].uv;
- uv[1] = mloopuv[mlooptri[f_index].tri[1]].uv;
- uv[2] = mloopuv[mlooptri[f_index].tri[2]].uv;
-
- interp_v2_v2v2v2(tex_co, UNPACK3(uv), weights);
-
- /* Map texure coord between -1.0f and 1.0f. */
- tex_co[0] = tex_co[0] * 2.0f - 1.0f;
- tex_co[1] = tex_co[1] * 2.0f - 1.0f;
- tex_co[2] = mfs->texture_offset;
+
+ /* Apply emission texture. */
+ if ((mfs->flags & FLUID_FLOW_TEXTUREEMIT) && mfs->noise_texture) {
+ float tex_co[3] = {0};
+ TexResult texres;
+
+ if (mfs->texture_type == FLUID_FLOW_TEXTURE_MAP_AUTO) {
+ tex_co[0] = ((x - flow_center[0]) / base_res[0]) / mfs->texture_size;
+ tex_co[1] = ((y - flow_center[1]) / base_res[1]) / mfs->texture_size;
+ tex_co[2] = ((z - flow_center[2]) / base_res[2] - mfs->texture_offset) /
+ mfs->texture_size;
+ }
+ else if (mloopuv) {
+ const float *uv[3];
+ uv[0] = mloopuv[mlooptri[f_index].tri[0]].uv;
+ uv[1] = mloopuv[mlooptri[f_index].tri[1]].uv;
+ uv[2] = mloopuv[mlooptri[f_index].tri[2]].uv;
+
+ interp_v2_v2v2v2(tex_co, UNPACK3(uv), weights);
+
+ /* Map texure coord between -1.0f and 1.0f. */
+ tex_co[0] = tex_co[0] * 2.0f - 1.0f;
+ tex_co[1] = tex_co[1] * 2.0f - 1.0f;
+ tex_co[2] = mfs->texture_offset;
+ }
+ texres.nor = NULL;
+ BKE_texture_get_value(NULL, mfs->noise_texture, tex_co, &texres, false);
+ emission_strength *= texres.tin;
}
- texres.nor = NULL;
- BKE_texture_get_value(NULL, mfs->noise_texture, tex_co, &texres, false);
- emission_strength *= texres.tin;
}
}
@@ -1868,9 +1884,10 @@ static void emit_from_mesh(
mul_m4_v3(flow_ob->obmat, flow_center);
manta_pos_to_cell(mds, flow_center);
- /* Set emission map. */
- clamp_bounds_in_domain(
- mds, em->min, em->max, NULL, NULL, (int)ceil(mfs->surface_distance), dt);
+ /* Set emission map.
+ * Use 3 cell diagonals as margin (3 * 1.732 = 5.196). */
+ int bounds_margin = (int)ceil(5.196);
+ clamp_bounds_in_domain(mds, em->min, em->max, NULL, NULL, bounds_margin, dt);
em_allocateData(em, mfs->flags & FLUID_FLOW_INITVELOCITY);
/* Setup loop bounds. */
@@ -2222,60 +2239,55 @@ BLI_INLINE void apply_inflow_fields(FluidFlowSettings *mfs,
float *phi_in,
float *emission_in)
{
- /* add inflow */
+ /* Set levelset value for liquid inflow.
+ * Ensure that distance value is "joined" into the levelset. */
if (phi_in) {
- phi_in[index] = distance_value;
+ phi_in[index] = MIN2(distance_value, phi_in[index]);
}
- /* save emission value for manta inflow */
+ /* Set emission value for smoke inflow.
+ * Ensure that emission value is "maximised". */
if (emission_in) {
- emission_in[index] = emission_value;
+ emission_in[index] = MAX2(emission_value, emission_in[index]);
}
- /* add smoke inflow */
+ /* Set inflow for smoke from here on. */
int absolute_flow = (mfs->flags & FLUID_FLOW_ABSOLUTE);
float dens_old = (density) ? density[index] : 0.0;
// float fuel_old = (fuel) ? fuel[index] : 0.0f; /* UNUSED */
float dens_flow = (mfs->type == FLUID_FLOW_TYPE_FIRE) ? 0.0f : emission_value * mfs->density;
float fuel_flow = (fuel) ? emission_value * mfs->fuel_amount : 0.0f;
- /* add heat */
+ /* Set heat inflow. */
if (heat && heat_in) {
if (emission_value > 0.0f) {
heat_in[index] = ADD_IF_LOWER(heat[index], mfs->temperature);
- /* Scale inflow by dt/frame-length.
- * This is to ensure that adaptive steps don't apply too much emission. */
- }
- else {
- heat_in[index] = heat[index];
}
}
- /* set density and fuel - absolute mode */
+ /* Set density and fuel - absolute mode. */
if (absolute_flow) {
if (density && density_in) {
- density_in[index] = density[index];
if (mfs->type != FLUID_FLOW_TYPE_FIRE && dens_flow > density[index]) {
- density_in[index] = dens_flow;
+ /* Use MAX2 to preserve values from other emitters at this cell. */
+ density_in[index] = MAX2(dens_flow, density_in[index]);
}
}
if (fuel && fuel_in) {
- fuel_in[index] = fuel[index];
if (mfs->type != FLUID_FLOW_TYPE_SMOKE && fuel_flow && fuel_flow > fuel[index]) {
- fuel_in[index] = fuel_flow;
+ /* Use MAX2 to preserve values from other emitters at this cell. */
+ fuel_in[index] = MAX2(fuel_flow, fuel_in[index]);
}
}
}
- /* set density and fuel - additive mode */
+ /* Set density and fuel - additive mode. */
else {
if (density && density_in) {
- density_in[index] = density[index];
if (mfs->type != FLUID_FLOW_TYPE_FIRE) {
density_in[index] += dens_flow;
CLAMP(density_in[index], 0.0f, 1.0f);
}
}
if (fuel && fuel_in) {
- fuel_in[index] = fuel[index];
if (mfs->type != FLUID_FLOW_TYPE_SMOKE && mfs->fuel_amount) {
fuel_in[index] += fuel_flow;
CLAMP(fuel_in[index], 0.0f, 10.0f);
@@ -2283,12 +2295,8 @@ BLI_INLINE void apply_inflow_fields(FluidFlowSettings *mfs,
}
}
- /* set color */
+ /* Set color. */
if (color_r && color_r_in) {
- color_r_in[index] = color_r[index];
- color_g_in[index] = color_g[index];
- color_b_in[index] = color_b[index];
-
if (dens_flow) {
float total_dens = density[index] / (dens_old + dens_flow);
color_r_in[index] = (color_r[index] + mfs->color[0] * dens_flow) * total_dens;
@@ -2297,7 +2305,7 @@ BLI_INLINE void apply_inflow_fields(FluidFlowSettings *mfs,
}
}
- /* set fire reaction coordinate */
+ /* Set fire reaction coordinate. */
if (fuel && fuel_in) {
/* Instead of using 1.0 for all new fuel add slight falloff to reduce flow blocky-ness. */
float value = 1.0f - pow2f(1.0f - emission_value);
@@ -2307,9 +2315,6 @@ BLI_INLINE void apply_inflow_fields(FluidFlowSettings *mfs,
react_in[index] = value * f + (1.0f - f) * react[index];
CLAMP(react_in[index], 0.0f, value);
}
- else {
- react_in[index] = react[index];
- }
}
}
@@ -2607,20 +2612,21 @@ static void update_flowsfluids(struct Depsgraph *depsgraph,
if (phiout_in) {
phiout_in[z] = PHI_MAX;
}
+ /* Sync smoke inflow grids with their counterparts (simulation grids). */
if (density_in) {
- density_in[z] = 0.0f;
+ density_in[z] = density[z];
}
if (heat_in) {
- heat_in[z] = 0.0f;
+ heat_in[z] = heat[z];
}
if (color_r_in) {
- color_r_in[z] = 0.0f;
- color_g_in[z] = 0.0f;
- color_b_in[z] = 0.0f;
+ color_r_in[z] = color_r[z];
+ color_g_in[z] = color_b[z];
+ color_b_in[z] = color_g[z];
}
if (fuel_in) {
- fuel_in[z] = 0.0f;
- react_in[z] = 0.0f;
+ fuel_in[z] = fuel[z];
+ react_in[z] = react[z];
}
if (emission_in) {
emission_in[z] = 0.0f;
diff --git a/source/blender/editors/physics/physics_fluid.c b/source/blender/editors/physics/physics_fluid.c
index 8fa72d554be..63979e247bf 100644
--- a/source/blender/editors/physics/physics_fluid.c
+++ b/source/blender/editors/physics/physics_fluid.c
@@ -454,6 +454,9 @@ static void fluid_free_endjob(void *customdata)
BKE_spacedata_draw_locks(false);
WM_set_locked_interface(G_MAIN->wm.first, false);
+ /* Reflect the now empty cache in the viewport too. */
+ DEG_id_tag_update(&job->ob->id, ID_RECALC_GEOMETRY);
+
/* Free was successful:
* Report for ended free job and how long it took */
if (job->success) {