[Bf-blender-cvs] [47645a8db62] master: Sculpt: Sample Voxel Size

Pablo Dobarro noreply at git.blender.org
Wed Nov 27 17:21:13 CET 2019


Commit: 47645a8db6223ba31b8128db7502f27876a2586b
Author: Pablo Dobarro
Date:   Tue Nov 26 18:53:38 2019 +0100
Branches: master
https://developer.blender.org/rB47645a8db6223ba31b8128db7502f27876a2586b

Sculpt: Sample Voxel Size

This adds support to the current sculpt sample detail operator to sample
a voxel size for the voxel remesher when sculpting on regular meshes.

It provides an approximation of a voxel size that is going to preserve
the sampled sculpt details after remeshing. It is not going to be 100%
accurate in all cases as it relies on having consistent edge length in
the whole sculpt, but it saves a lot of time and avoids guessing the
voxel size by trying different values.

Reviewed By: jbakker

Differential Revision: https://developer.blender.org/D6251

===================================================================

M	release/scripts/startup/bl_ui/space_view3d_toolbar.py
M	source/blender/editors/sculpt_paint/sculpt.c

===================================================================

diff --git a/release/scripts/startup/bl_ui/space_view3d_toolbar.py b/release/scripts/startup/bl_ui/space_view3d_toolbar.py
index 724264fe494..718365ec99d 100644
--- a/release/scripts/startup/bl_ui/space_view3d_toolbar.py
+++ b/release/scripts/startup/bl_ui/space_view3d_toolbar.py
@@ -1193,7 +1193,8 @@ class VIEW3D_PT_sculpt_dyntopo(Panel, View3DPaintPanel):
         if sculpt.detail_type_method in {'CONSTANT', 'MANUAL'}:
             row = sub.row(align=True)
             row.prop(sculpt, "constant_detail_resolution")
-            row.operator("sculpt.sample_detail_size", text="", icon='EYEDROPPER')
+            props = row.operator("sculpt.sample_detail_size", text="", icon='EYEDROPPER')
+            props.mode = 'DYNTOPO'
         elif (sculpt.detail_type_method == 'BRUSH'):
             sub.prop(sculpt, "detail_percent")
         else:
@@ -1252,7 +1253,10 @@ class VIEW3D_PT_sculpt_voxel_remesh(Panel, View3DPaintPanel):
 
         col = layout.column()
         mesh = context.active_object.data
-        col.prop(mesh, "remesh_voxel_size")
+        row = col.row(align=True)
+        row.prop(mesh, "remesh_voxel_size")
+        props = row.operator("sculpt.sample_detail_size", text="", icon='EYEDROPPER')
+        props.mode = 'VOXEL'
         col.prop(mesh, "remesh_voxel_adaptivity")
         col.prop(mesh, "use_remesh_fix_poles")
         col.prop(mesh, "use_remesh_smooth_normals")
diff --git a/source/blender/editors/sculpt_paint/sculpt.c b/source/blender/editors/sculpt_paint/sculpt.c
index 38e4d119aa5..63b9949e0ef 100644
--- a/source/blender/editors/sculpt_paint/sculpt.c
+++ b/source/blender/editors/sculpt_paint/sculpt.c
@@ -8445,36 +8445,60 @@ static void SCULPT_OT_detail_flood_fill(wmOperatorType *ot)
   ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
 }
 
-static void sample_detail(bContext *C, int mx, int my)
+typedef enum eSculptSampleDetailModeTypes {
+  SAMPLE_DETAIL_DYNTOPO = 0,
+  SAMPLE_DETAIL_VOXEL = 1,
+} eSculptSampleDetailModeTypes;
+
+static EnumPropertyItem prop_sculpt_sample_detail_mode_types[] = {
+    {SAMPLE_DETAIL_DYNTOPO, "DYNTOPO", 0, "Dyntopo", "Sample dyntopo detail"},
+    {SAMPLE_DETAIL_VOXEL, "VOXEL", 0, "Voxel", "Sample mesh voxel size"},
+    {0, NULL, 0, NULL, NULL},
+};
+
+static void sample_detail_voxel(bContext *C, ViewContext *vc, int mx, int my)
 {
-  /* Find 3D view to pick from. */
-  bScreen *screen = CTX_wm_screen(C);
-  ScrArea *sa = BKE_screen_find_area_xy(screen, SPACE_VIEW3D, mx, my);
-  ARegion *ar = (sa) ? BKE_area_find_region_xy(sa, RGN_TYPE_WINDOW, mx, my) : NULL;
-  if (ar == NULL) {
-    return;
-  }
+  Depsgraph *depsgraph = CTX_data_depsgraph_pointer(C);
+  Object *ob = vc->obact;
+  Mesh *mesh = ob->data;
 
-  /* Set context to 3D view. */
-  ScrArea *prev_sa = CTX_wm_area(C);
-  ARegion *prev_ar = CTX_wm_region(C);
-  CTX_wm_area_set(C, sa);
-  CTX_wm_region_set(C, ar);
+  SculptSession *ss = ob->sculpt;
+  SculptCursorGeometryInfo sgi;
+  sculpt_vertex_random_access_init(ss);
 
-  Depsgraph *depsgraph = CTX_data_ensure_evaluated_depsgraph(C);
-  ViewContext vc;
-  ED_view3d_viewcontext_init(C, &vc, depsgraph);
+  /* Update the active vertex */
+  float mouse[2] = {mx, my};
+  sculpt_cursor_geometry_info_update(C, &sgi, mouse, false);
+  BKE_sculpt_update_object_for_edit(depsgraph, ob, true, false);
 
-  /* Pick sample detail. */
+  /* Average the edge length of the connected edges to the active vertex */
+  int active_vertex = sculpt_active_vertex_get(ss);
+  const float *active_vertex_co = sculpt_active_vertex_co_get(ss);
+  float edge_length = 0.0f;
+  int tot = 0;
+  SculptVertexNeighborIter ni;
+  sculpt_vertex_neighbors_iter_begin(ss, active_vertex, ni)
+  {
+    edge_length += len_v3v3(active_vertex_co, sculpt_vertex_co_get(ss, ni.index));
+    tot += 1;
+  }
+  sculpt_vertex_neighbors_iter_end(ni);
+  if (tot > 0) {
+    mesh->remesh_voxel_size = edge_length / (float)tot;
+  }
+}
+
+static void sample_detail_dyntopo(bContext *C, ViewContext *vc, ARegion *ar, int mx, int my)
+{
   Sculpt *sd = CTX_data_tool_settings(C)->sculpt;
-  Object *ob = vc.obact;
+  Object *ob = vc->obact;
   Brush *brush = BKE_paint_brush(&sd->paint);
 
   sculpt_stroke_modifiers_check(C, ob, brush);
 
   float mouse[2] = {mx - ar->winrct.xmin, my - ar->winrct.ymin};
   float ray_start[3], ray_end[3], ray_normal[3];
-  float depth = sculpt_raycast_init(&vc, mouse, ray_start, ray_end, ray_normal, false);
+  float depth = sculpt_raycast_init(vc, mouse, ray_start, ray_end, ray_normal, false);
 
   SculptDetailRaycastData srd;
   srd.hit = 0;
@@ -8489,6 +8513,37 @@ static void sample_detail(bContext *C, int mx, int my)
     /* Convert edge length to world space detail resolution. */
     sd->constant_detail = 1 / (srd.edge_length * mat4_to_scale(ob->obmat));
   }
+}
+
+static void sample_detail(bContext *C, int mx, int my, int mode)
+{
+  /* Find 3D view to pick from. */
+  bScreen *screen = CTX_wm_screen(C);
+  ScrArea *sa = BKE_screen_find_area_xy(screen, SPACE_VIEW3D, mx, my);
+  ARegion *ar = (sa) ? BKE_area_find_region_xy(sa, RGN_TYPE_WINDOW, mx, my) : NULL;
+  if (ar == NULL) {
+    return;
+  }
+
+  /* Set context to 3D view. */
+  ScrArea *prev_sa = CTX_wm_area(C);
+  ARegion *prev_ar = CTX_wm_region(C);
+  CTX_wm_area_set(C, sa);
+  CTX_wm_region_set(C, ar);
+
+  Depsgraph *depsgraph = CTX_data_ensure_evaluated_depsgraph(C);
+  ViewContext vc;
+  ED_view3d_viewcontext_init(C, &vc, depsgraph);
+
+  /* Pick sample detail. */
+  switch (mode) {
+    case SAMPLE_DETAIL_DYNTOPO:
+      sample_detail_dyntopo(C, &vc, ar, mx, my);
+      break;
+    case SAMPLE_DETAIL_VOXEL:
+      sample_detail_voxel(C, &vc, mx, my);
+      break;
+  }
 
   /* Restore context. */
   CTX_wm_area_set(C, prev_sa);
@@ -8499,7 +8554,8 @@ static int sculpt_sample_detail_size_exec(bContext *C, wmOperator *op)
 {
   int ss_co[2];
   RNA_int_get_array(op->ptr, "location", ss_co);
-  sample_detail(C, ss_co[0], ss_co[1]);
+  int mode = RNA_enum_get(op->ptr, "mode");
+  sample_detail(C, ss_co[0], ss_co[1], mode);
   return OPERATOR_FINISHED;
 }
 
@@ -8518,7 +8574,8 @@ static int sculpt_sample_detail_size_modal(bContext *C, wmOperator *op, const wm
       if (event->val == KM_PRESS) {
         int ss_co[2] = {event->x, event->y};
 
-        sample_detail(C, ss_co[0], ss_co[1]);
+        int mode = RNA_enum_get(op->ptr, "mode");
+        sample_detail(C, ss_co[0], ss_co[1], mode);
 
         RNA_int_set_array(op->ptr, "location", ss_co);
         WM_cursor_modal_restore(CTX_wm_window(C));
@@ -8551,7 +8608,7 @@ static void SCULPT_OT_sample_detail_size(wmOperatorType *ot)
   ot->invoke = sculpt_sample_detail_size_invoke;
   ot->exec = sculpt_sample_detail_size_exec;
   ot->modal = sculpt_sample_detail_size_modal;
-  ot->poll = sculpt_and_constant_or_manual_detail_poll;
+  ot->poll = sculpt_mode_poll;
 
   ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
 
@@ -8565,6 +8622,12 @@ static void SCULPT_OT_sample_detail_size(wmOperatorType *ot)
                     "Screen Coordinates of sampling",
                     0,
                     SHRT_MAX);
+  RNA_def_enum(ot->srna,
+               "mode",
+               prop_sculpt_sample_detail_mode_types,
+               SAMPLE_DETAIL_DYNTOPO,
+               "Detail Mode",
+               "Target sculpting workflow that is going to use the sampled size");
 }
 
 /* Dynamic-topology detail size



More information about the Bf-blender-cvs mailing list