Page MenuHome

Apply random selection precisely for curves, lattices & objects
ClosedPublic

Authored by Piotr Makal (pmakal) on Jun 23 2021, 8:35 PM.

Details

Summary

This patch is part of: T87228
Support accurate random selection for:

  • CURVE_OT_select_random
  • LATTICE_OT_select_random
  • OBJECT_OT_select_random

Additionally regression was fixed in MESH_OT_select_random regarding changing seed for different objects.

Diff Detail

Repository
rB Blender
Branch
T (branched from master)
Build Status
Buildable 15455
Build 15455: arc lint + arc unit

Event Timeline

Piotr Makal (pmakal) requested review of this revision.Jun 23 2021, 8:35 PM
Piotr Makal (pmakal) created this revision.
Piotr Makal (pmakal) edited the summary of this revision. (Show Details)Jun 23 2021, 9:42 PM
Campbell Barton (campbellbarton) requested changes to this revision.Jun 24 2021, 2:24 AM
Campbell Barton (campbellbarton) added inline comments.
source/blender/editors/curve/editcurve_select.c
1201–1270

Not sure why the function needed to be removed? it seems to be fine with the function left as-is.

/********************** select random *********************/

static void curve_select_random(ListBase *editnurb, float randfac, int seed, bool select)
{
  LISTBASE_FOREACH (Nurb *, nu, editnurb) {
    if (nu->type == CU_BEZIER) {
      int tot = nu->pntsu;
      int elem_map_len = 0;
      BezTriple **elem_map = MEM_mallocN(sizeof(*elem_map) * tot, __func__);
      BezTriple *bezt = nu->bezt;

      while (tot--) {
        if (!bezt->hide) {
          elem_map[elem_map_len++] = bezt;
        }
        bezt++;
      }

      BLI_array_randomize(elem_map, sizeof(*elem_map), elem_map_len, seed);
      const int count_select = elem_map_len * randfac;
      for (int i = 0; i < count_select; i++) {
        select_beztriple(elem_map[i], select, SELECT, VISIBLE);
      }
      MEM_freeN(elem_map);
    }
    else {
      int tot = nu->pntsu * nu->pntsv;
      int elem_map_len = 0;
      BPoint **elem_map = MEM_mallocN(sizeof(*elem_map) * tot, __func__);
      BPoint *bp = nu->bp;

      while (tot--) {
        if (!bp->hide) {
          elem_map[elem_map_len++] = bp;
        }
        bp++;
      }

      BLI_array_randomize(elem_map, sizeof(*elem_map), elem_map_len, seed);
      const int count_select = elem_map_len * randfac;
      for (int i = 0; i < count_select; i++) {
        select_bpoint(elem_map[i], select, SELECT, VISIBLE);
      }
      MEM_freeN(elem_map);
    }
  }
}

static int curve_select_random_exec(bContext *C, wmOperator *op)
{
  const bool select = (RNA_enum_get(op->ptr, "action") == SEL_SELECT);
  const float randfac = RNA_float_get(op->ptr, "ratio");
  const int seed = WM_operator_properties_select_random_seed_increment_get(op);

  ViewLayer *view_layer = CTX_data_view_layer(C);
  uint objects_len = 0;
  Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data(
      view_layer, CTX_wm_view3d(C), &objects_len);

  for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
    Object *obedit = objects[ob_index];
    ListBase *editnurb = object_editcurve_get(obedit);
    int seed_iter = seed;

    /* This gives a consistent result regardless of object order. */
    if (ob_index) {
      seed_iter += BLI_ghashutil_strhash_p(obedit->id.name);
    }

    curve_select_random(editnurb, randfac, seed_iter, select);
    BKE_curve_nurb_vert_active_validate(obedit->data);
    DEG_id_tag_update(obedit->data, ID_RECALC_SELECT);
    WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data);
  }
1226

The looping logic here could be cleaned up (using a for instead of a while loop for example). However as this page isn't doing this kind of cleanup, I'd rather leave the variable names as-is. a instead of tot, since this is an counter and doesn't represent the total number of elements.

1228

Randomness is handled per-spline, this could result in reducing randomness in the case of many 2 or 3 vertex splines.

I think it would be better to operate on the entire curve object vertices.

Since this is complicated by having to separate a kinds of vertices, it might be better to write a utility that randomizes a BLI_bitmap e.g. BLI_bitmap_rand_set_all(bitmap, set, seed, bits). See BLI_bitmap.h & BLI_rand.h (best add this to BLI_rand.h the use of a common prefix here is fairly sloppy).

This revision now requires changes to proceed.Jun 24 2021, 2:24 AM
source/blender/editors/curve/editcurve_select.c
1228

In case the use of a randomized bitmap wasn't clear, the steps would be:

  • count the number of visible vertices.
  • create a bitmap that size, randomly enable elements.
  • loop over the vertices again, using the boolean to change selection.

An alternative could be to generate an ordered array of unique int's which would work fine too, in practice I think the boolean version would be more readable.

Piotr Makal (pmakal) updated this revision to Diff 38788.EditedJun 26 2021, 6:37 PM
  • Improved curve_select_random_exec function - using BLI_bitmap to randomly select spline vertices.
  • Implemented BLI_bitmap_randomize and BLI_rng_shuffle_bitmap functions.
Campbell Barton (campbellbarton) edited the summary of this revision. (Show Details)
  • Remove BLI_bitmap header from BLI_rand.h
  • Replace BLI_BITMAP_TEST_BOOL with BLI_BITMAP_TEST (accessing the bool isn't needed for for the test).
Campbell Barton (campbellbarton) retitled this revision from Apply random selection factor precisely for curves, lattices and objects to Apply random selection precisely for curves, lattices & objects.Jun 28 2021, 11:42 AM
Campbell Barton (campbellbarton) edited the summary of this revision. (Show Details)

Remove edit-mesh fix (apply separately).

This revision was not accepted when it landed; it landed in state Needs Review.Jun 28 2021, 11:54 AM
This revision was automatically updated to reflect the committed changes.