diff options
author | Jacques Lucke <jacques@blender.org> | 2022-03-17 14:48:41 +0300 |
---|---|---|
committer | Jacques Lucke <jacques@blender.org> | 2022-03-17 14:48:41 +0300 |
commit | d0968a9c52019b817c001562adbb875780d94786 (patch) | |
tree | 4f5548adcd757cb75443bde77b082487fbf81839 | |
parent | 8f68cff01b85bfde18c9442e6a638eda181ee159 (diff) |
BLI: add probabilistic rounding utility
4 files changed, 19 insertions, 13 deletions
diff --git a/source/blender/blenlib/BLI_rand.hh b/source/blender/blenlib/BLI_rand.hh index 069a81bb84b..2c4484bd63f 100644 --- a/source/blender/blenlib/BLI_rand.hh +++ b/source/blender/blenlib/BLI_rand.hh @@ -103,6 +103,12 @@ class RandomNumberGenerator { return float3(rand1, rand2, 1.0f - rand1 - rand2); } + /** + * Round value to the next integer randomly. + * 4.9f is more likely to round to 5 than 4.6f. + */ + int round_probabilistic(float x); + float2 get_unit_float2(); float3 get_unit_float3(); /** diff --git a/source/blender/blenlib/intern/rand.cc b/source/blender/blenlib/intern/rand.cc index 27774cad31b..17bf5585f3f 100644 --- a/source/blender/blenlib/intern/rand.cc +++ b/source/blender/blenlib/intern/rand.cc @@ -374,6 +374,15 @@ void RandomNumberGenerator::seed_random(uint32_t seed) this->seed(seed + hash[seed & 255]); } +int RandomNumberGenerator::round_probabilistic(float x) +{ + /* Support for negative values can be added when necessary. */ + BLI_assert(x >= 0.0f); + const float round_up_probability = fractf(x); + const bool round_up = round_up_probability > this->get_float(); + return (int)x + (int)round_up; +} + float2 RandomNumberGenerator::get_unit_float2() { float a = (float)(M_PI * 2.0) * this->get_float(); diff --git a/source/blender/editors/sculpt_paint/curves_sculpt_ops.cc b/source/blender/editors/sculpt_paint/curves_sculpt_ops.cc index 178505e2276..ae57a462242 100644 --- a/source/blender/editors/sculpt_paint/curves_sculpt_ops.cc +++ b/source/blender/editors/sculpt_paint/curves_sculpt_ops.cc @@ -378,13 +378,6 @@ class AddOperation : public CurvesSculptStrokeOperation { return kdtree; } - int float_to_int_amount(float amount_f, RandomNumberGenerator &rng) - { - const float add_probability = fractf(amount_f); - const bool add_point = add_probability > rng.get_float(); - return (int)amount_f + (int)add_point; - } - bool is_too_close_to_existing_point(const float3 position, const float minimum_distance) const { if (old_kdtree_ == nullptr) { @@ -439,7 +432,7 @@ class AddOperation : public CurvesSculptStrokeOperation { * the triangle directly. If the triangle is larger than the brush, distribute new points * in a circle on the triangle plane. */ if (looptri_area < area_threshold) { - const int amount = this->float_to_int_amount(looptri_area * density, looptri_rng); + const int amount = looptri_rng.round_probabilistic(looptri_area * density); threading::parallel_for(IndexRange(amount), 512, [&](const IndexRange amount_range) { RandomNumberGenerator point_rng{rng_base_seed + looptri_index * 1000 + @@ -476,7 +469,7 @@ class AddOperation : public CurvesSculptStrokeOperation { const float radius_proj = std::sqrt(radius_proj_sq); const float circle_area = M_PI * radius_proj_sq; - const int amount = this->float_to_int_amount(circle_area * density, rng); + const int amount = rng.round_probabilistic(circle_area * density); const float3 axis_1 = math::normalize(v1 - v0) * radius_proj; const float3 axis_2 = math::normalize( diff --git a/source/blender/nodes/geometry/nodes/node_geo_distribute_points_on_faces.cc b/source/blender/nodes/geometry/nodes/node_geo_distribute_points_on_faces.cc index bdd4d74fe4b..8e28a4ba9b9 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_distribute_points_on_faces.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_distribute_points_on_faces.cc @@ -114,10 +114,8 @@ static void sample_mesh_surface(const Mesh &mesh, const int looptri_seed = noise::hash(looptri_index, seed); RandomNumberGenerator looptri_rng(looptri_seed); - const float points_amount_fl = area * base_density * looptri_density_factor; - const float add_point_probability = fractf(points_amount_fl); - const bool add_point = add_point_probability > looptri_rng.get_float(); - const int point_amount = (int)points_amount_fl + (int)add_point; + const int point_amount = looptri_rng.round_probabilistic(area * base_density * + looptri_density_factor); for (int i = 0; i < point_amount; i++) { const float3 bary_coord = looptri_rng.get_barycentric_coordinates(); |