[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