diff options
author | Sebastián Barschkis <sebbas@sebbas.org> | 2020-03-24 01:50:25 +0300 |
---|---|---|
committer | Sebastián Barschkis <sebbas@sebbas.org> | 2020-03-24 01:50:39 +0300 |
commit | cda81d5a4d391a8a7b298eb1b6f2fdf1a0ed838a (patch) | |
tree | a6234c07dbc940af17166111d201e08f890a8cc8 /source/blender | |
parent | e9629e3cfdaf995bd76249595c5c2b7d81432e76 (diff) |
Fluid: Enforce minimum thickness to planar flow / effector objects
Planar object now have a thickness by default. This should make it more intuitive for users as there is no need to specify an object thickness.
Diffstat (limited to 'source/blender')
-rw-r--r-- | source/blender/blenkernel/intern/fluid.c | 136 | ||||
-rw-r--r-- | source/blender/makesrna/intern/rna_fluid.c | 12 |
2 files changed, 77 insertions, 71 deletions
diff --git a/source/blender/blenkernel/intern/fluid.c b/source/blender/blenkernel/intern/fluid.c index 58a1ae28d42..ae51c997a08 100644 --- a/source/blender/blenkernel/intern/fluid.c +++ b/source/blender/blenkernel/intern/fluid.c @@ -571,7 +571,7 @@ static void update_distances(int index, BVHTreeFromMesh *tree_data, const float ray_start[3], float surface_thickness, - int use_plane_init); + bool use_plane_init); static int get_light(ViewLayer *view_layer, float *light) { @@ -1717,16 +1717,25 @@ static void update_distances(int index, BVHTreeFromMesh *tree_data, const float ray_start[3], float surface_thickness, - int use_plane_init) + bool use_plane_init) { float min_dist = PHI_MAX; - /* a) Planar initialization */ + /* Planar initialization: Find nearest cells around mesh. */ if (use_plane_init) { BVHTreeNearest nearest = {0}; nearest.index = -1; - nearest.dist_sq = surface_thickness * - surface_thickness; /* find_nearest uses squared distance */ + /* Distance between two opposing vertices in a unit cube. + * I.e. the unit cube diagonal or sqrt(3). + * This value is our nearest neighbor search distance. */ + const float surface_distance = 1.732; + nearest.dist_sq = surface_distance * + surface_distance; /* find_nearest uses squared distance. */ + + /* Subtract optional surface thickness value and virtually increase the object size. */ + if (surface_thickness) { + nearest.dist_sq += surface_thickness; + } if (BLI_bvhtree_find_nearest( tree_data->tree, ray_start, &nearest, tree_data->nearest_callback, tree_data) != -1) { @@ -1734,77 +1743,74 @@ static void update_distances(int index, sub_v3_v3v3(ray, ray_start, nearest.co); min_dist = len_v3(ray); min_dist = (-1.0f) * fabsf(min_dist); - distance_map[index] = min_dist; } - return; } + /* Volumetric initialization: Ray-casts around mesh object. */ + else { + /* 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}, + {0.0f, -1.0f, 0.0f}, {0.0f, 0.0f, -1.0f}, {1.0f, 1.0f, 0.0f}, {1.0f, -1.0f, 0.0f}, + {-1.0f, 1.0f, 0.0f}, {-1.0f, -1.0f, 0.0f}, {1.0f, 0.0f, 1.0f}, {1.0f, 0.0f, -1.0f}, + {-1.0f, 0.0f, 1.0f}, {-1.0f, 0.0f, -1.0f}, {0.0f, 1.0f, 1.0f}, {0.0f, 1.0f, -1.0f}, + {0.0f, -1.0f, 1.0f}, {0.0f, -1.0f, -1.0f}, {1.0f, 1.0f, 1.0f}, {1.0f, -1.0f, 1.0f}, + {-1.0f, 1.0f, 1.0f}, {-1.0f, -1.0f, 1.0f}, {1.0f, 1.0f, -1.0f}, {1.0f, -1.0f, -1.0f}, + {-1.0f, 1.0f, -1.0f}, {-1.0f, -1.0f, -1.0f}}; + size_t ray_cnt = sizeof ray_dirs / sizeof ray_dirs[0]; + + /* 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; + + for (int i = 0; i < ray_cnt; i++) { + BVHTreeRayHit hit_tree = {0}; + hit_tree.index = -1; + hit_tree.dist = PHI_MAX; + + normalize_v3(ray_dirs[i]); + BLI_bvhtree_ray_cast(tree_data->tree, + ray_start, + ray_dirs[i], + 0.0f, + &hit_tree, + tree_data->raycast_callback, + tree_data); + + /* 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++; + /* Skip this ray since nothing was hit. */ + continue; + } - /* b) Volumetric initialization: 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}, - {0.0f, -1.0f, 0.0f}, {0.0f, 0.0f, -1.0f}, {1.0f, 1.0f, 0.0f}, {1.0f, -1.0f, 0.0f}, - {-1.0f, 1.0f, 0.0f}, {-1.0f, -1.0f, 0.0f}, {1.0f, 0.0f, 1.0f}, {1.0f, 0.0f, -1.0f}, - {-1.0f, 0.0f, 1.0f}, {-1.0f, 0.0f, -1.0f}, {0.0f, 1.0f, 1.0f}, {0.0f, 1.0f, -1.0f}, - {0.0f, -1.0f, 1.0f}, {0.0f, -1.0f, -1.0f}, {1.0f, 1.0f, 1.0f}, {1.0f, -1.0f, 1.0f}, - {-1.0f, 1.0f, 1.0f}, {-1.0f, -1.0f, 1.0f}, {1.0f, 1.0f, -1.0f}, {1.0f, -1.0f, -1.0f}, - {-1.0f, 1.0f, -1.0f}, {-1.0f, -1.0f, -1.0f}}; - size_t ray_cnt = sizeof ray_dirs / sizeof ray_dirs[0]; - - /* 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; - - for (int i = 0; i < ray_cnt; i++) { - BVHTreeRayHit hit_tree = {0}; - hit_tree.index = -1; - hit_tree.dist = PHI_MAX; - - normalize_v3(ray_dirs[i]); - BLI_bvhtree_ray_cast(tree_data->tree, - ray_start, - ray_dirs[i], - 0.0f, - &hit_tree, - tree_data->raycast_callback, - tree_data); - - /* 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++; - /* Skip this ray since nothing was hit. */ - continue; - } + /* Ray and normal are pointing in opposite directions. */ + if (dot_v3v3(ray_dirs[i], hit_tree.no) <= 0) { + dir_cnt++; + } - /* Ray and normal are pointing in opposite directions. */ - if (dot_v3v3(ray_dirs[i], hit_tree.no) <= 0) { - dir_cnt++; + if (hit_tree.dist < min_dist) { + min_dist = hit_tree.dist; + } } - if (hit_tree.dist < min_dist) { - min_dist = hit_tree.dist; + /* 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); } - } - /* 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); + /* Subtract optional surface thickness value and virtually increase the object size. */ + if (surface_thickness) { + min_dist -= surface_thickness; + } } /* Update global distance array but ensure that older entries are not overridden. */ distance_map[index] = MIN2(distance_map[index], min_dist); - /* Subtract optional surface thickness value and virtually increase the object size. */ - if (surface_thickness) { - distance_map[index] -= surface_thickness; - } - /* Sanity check: Ensure that distances don't explode. */ CLAMP(distance_map[index], -PHI_MAX, PHI_MAX); } @@ -5179,8 +5185,8 @@ void BKE_fluid_modifier_copy(const struct FluidModifierData *mmd, tmes->surface_distance = mes->surface_distance; tmes->type = mes->type; - tmes->flags = tmes->flags; - tmes->subframes = tmes->subframes; + tmes->flags = mes->flags; + tmes->subframes = mes->subframes; /* guide options */ tmes->guide_mode = mes->guide_mode; diff --git a/source/blender/makesrna/intern/rna_fluid.c b/source/blender/makesrna/intern/rna_fluid.c index 9b46d0cd4a7..9410906595d 100644 --- a/source/blender/makesrna/intern/rna_fluid.c +++ b/source/blender/makesrna/intern/rna_fluid.c @@ -1332,6 +1332,11 @@ static void rna_def_fluid_domain_settings(BlenderRNA *brna) RNA_def_property_clear_flag(prop, PROP_ANIMATABLE); RNA_def_property_update(prop, NC_OBJECT | ND_DRAW, "rna_Fluid_flip_parts_update"); + prop = RNA_def_property(srna, "delete_in_obstacle", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "flags", FLUID_DOMAIN_DELETE_IN_OBSTACLE); + RNA_def_property_ui_text(prop, "Clear In Obstacle", "Delete fluid inside obstacles"); + RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Fluid_reset"); + /* smoke domain options */ prop = RNA_def_property(srna, "alpha", PROP_FLOAT, PROP_NONE); @@ -2541,7 +2546,7 @@ static void rna_def_fluid_effector_settings(BlenderRNA *brna) RNA_def_property_range(prop, 0.0, 10.0); RNA_def_property_ui_range(prop, 0.0, 10.0, 0.05, 5); RNA_def_property_ui_text( - prop, "Surface", "Distance around mesh surface to consider as effector"); + prop, "Surface", "Additional distance around mesh surface to consider as effector"); RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Fluid_reset"); prop = RNA_def_property(srna, "use_plane_init", PROP_BOOLEAN, PROP_NONE); @@ -2549,11 +2554,6 @@ static void rna_def_fluid_effector_settings(BlenderRNA *brna) RNA_def_property_ui_text(prop, "Is Planar", "Treat this object as a planar, unclosed mesh"); RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Fluid_reset"); - prop = RNA_def_property(srna, "delete_in_obstacle", PROP_BOOLEAN, PROP_NONE); - RNA_def_property_boolean_sdna(prop, NULL, "flags", FLUID_DOMAIN_DELETE_IN_OBSTACLE); - RNA_def_property_ui_text(prop, "Clear In Obstacle", "Delete fluid inside obstacles"); - RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Fluid_reset"); - prop = RNA_def_property(srna, "velocity_factor", PROP_FLOAT, PROP_NONE); RNA_def_property_float_sdna(prop, NULL, "vel_multi"); RNA_def_property_range(prop, -100.0, 100.0); |