diff options
Diffstat (limited to 'source/blender/editors/sculpt_paint/sculpt.c')
-rw-r--r-- | source/blender/editors/sculpt_paint/sculpt.c | 985 |
1 files changed, 804 insertions, 181 deletions
diff --git a/source/blender/editors/sculpt_paint/sculpt.c b/source/blender/editors/sculpt_paint/sculpt.c index 8325b47beab..54ae2ebf588 100644 --- a/source/blender/editors/sculpt_paint/sculpt.c +++ b/source/blender/editors/sculpt_paint/sculpt.c @@ -65,6 +65,7 @@ #include "BKE_report.h" #include "BKE_lattice.h" /* for armature_deform_verts */ #include "BKE_node.h" +#include "BKE_object.h" #include "BKE_subsurf.h" #include "BIF_glutil.h" @@ -86,6 +87,8 @@ #include "GPU_buffers.h" +#include "bmesh.h" + #include <math.h> #include <stdlib.h> #include <string.h> @@ -98,8 +101,13 @@ void ED_sculpt_force_update(bContext *C) { Object *ob = CTX_data_active_object(C); - if (ob && (ob->mode & OB_MODE_SCULPT)) + if (ob && (ob->mode & OB_MODE_SCULPT)) { multires_force_update(ob); + + /* Set reorder=false so that saving the file doesn't reorder + * the BMesh's elements */ + sculptsession_bm_to_me(ob, FALSE); + } } float *ED_sculpt_get_last_stroke(struct Object *ob) @@ -172,7 +180,8 @@ static int sculpt_modifiers_active(Scene *scene, Sculpt *sd, Object *ob) Mesh *me = (Mesh *)ob->data; MultiresModifierData *mmd = sculpt_multires_active(scene, ob); - if (mmd) return 0; + if (mmd || ob->sculpt->bm) + return 0; /* non-locked shape keys could be handled in the same way as deformed mesh */ if ((ob->shapeflag & OB_SHAPE_LOCK) == 0 && me->key && ob->shapenr) @@ -281,12 +290,130 @@ typedef struct StrokeCache { rcti previous_r; /* previous redraw rectangle */ } StrokeCache; +/************** Access to original unmodified vertex data *************/ + +typedef struct { + BMLog *bm_log; + + SculptUndoNode *unode; + float (*coords)[3]; + short (*normals)[3]; + float *vmasks; + + /* Original coordinate, normal, and mask */ + const float *co; + float mask; + short no[3]; +} SculptOrigVertData; + + +/* Initialize a SculptOrigVertData for accessing original vertex data; + * handles BMesh, mesh, and multires */ +static void sculpt_orig_vert_data_unode_init(SculptOrigVertData *data, + Object *ob, + SculptUndoNode *unode) +{ + SculptSession *ss = ob->sculpt; + BMesh *bm = ss->bm; + + memset(data, 0, sizeof(*data)); + data->unode = unode; + + if (bm) { + data->bm_log = ss->bm_log; + } + else { + data->coords = data->unode->co; + data->normals = data->unode->no; + data->vmasks = data->unode->mask; + } +} + +/* Initialize a SculptOrigVertData for accessing original vertex data; + * handles BMesh, mesh, and multires */ +static void sculpt_orig_vert_data_init(SculptOrigVertData *data, + Object *ob, + PBVHNode *node) +{ + SculptUndoNode *unode; + unode = sculpt_undo_push_node(ob, node, SCULPT_UNDO_COORDS); + sculpt_orig_vert_data_unode_init(data, ob, unode); + +} + +/* Update a SculptOrigVertData for a particular vertex from the PBVH + * iterator */ +static void sculpt_orig_vert_data_update(SculptOrigVertData *orig_data, + PBVHVertexIter *iter) +{ + if (orig_data->unode->type == SCULPT_UNDO_COORDS) { + if (orig_data->coords) { + orig_data->co = orig_data->coords[iter->i]; + } + else { + orig_data->co = BM_log_original_vert_co(orig_data->bm_log, iter->bm_vert); + } + + if (orig_data->normals) { + copy_v3_v3_short(orig_data->no, orig_data->normals[iter->i]); + } + else { + /* TODO: log doesn't store normals yet */ + normal_float_to_short_v3(orig_data->no, iter->bm_vert->no); + } + } + else if (orig_data->unode->type == SCULPT_UNDO_MASK) { + if (orig_data->vmasks) { + orig_data->mask = orig_data->vmasks[iter->i]; + } + else { + orig_data->mask = BM_log_original_mask(orig_data->bm_log, iter->bm_vert); + } + } +} + +/**********************************************************************/ + +/* Returns true if the stroke will use dynamic topology, false + otherwise. + + Factors: some brushes like grab cannot do dynamic topology. + Others, like smooth, are better without. Same goes for alt- + key smoothing. */ +static int sculpt_stroke_dynamic_topology(const SculptSession *ss, + const Brush *brush) +{ + return ((BKE_pbvh_type(ss->pbvh) == PBVH_BMESH) && + + (!ss->cache || (!ss->cache->alt_smooth)) && + + /* Requires mesh restore, which doesn't work with + * dynamic-topology */ + !(brush->flag & BRUSH_ANCHORED) && + !(brush->flag & BRUSH_RESTORE_MESH) && + + (!ELEM6(brush->sculpt_tool, + /* These brushes, as currently coded, cannot + * support dynamic topology */ + SCULPT_TOOL_GRAB, + SCULPT_TOOL_ROTATE, + SCULPT_TOOL_THUMB, + SCULPT_TOOL_LAYER, + + /* These brushes could handle dynamic topology, + * but user feedback indicates it's better not + * to */ + SCULPT_TOOL_SMOOTH, + SCULPT_TOOL_MASK))); +} /*** paint mesh ***/ -static void paint_mesh_restore_co(Sculpt *sd, SculptSession *ss) +static void paint_mesh_restore_co(Sculpt *sd, Object *ob) { + SculptSession *ss = ob->sculpt; StrokeCache *cache = ss->cache; + const Brush *brush = paint_brush(&sd->paint); int i; PBVHNode **nodes; @@ -296,31 +423,38 @@ static void paint_mesh_restore_co(Sculpt *sd, SculptSession *ss) (void)sd; /* quied unused warning */ #endif - BLI_pbvh_search_gather(ss->pbvh, NULL, NULL, &nodes, &totnode); + BKE_pbvh_search_gather(ss->pbvh, NULL, NULL, &nodes, &totnode); #pragma omp parallel for schedule(guided) if (sd->flags & SCULPT_USE_OPENMP) for (n = 0; n < totnode; n++) { SculptUndoNode *unode; - - unode = sculpt_undo_get_node(nodes[n]); + SculptUndoType type = (brush->sculpt_tool == SCULPT_TOOL_MASK ? + SCULPT_UNDO_MASK : SCULPT_UNDO_COORDS); + + unode = sculpt_undo_push_node(ob, nodes[n], type); if (unode) { PBVHVertexIter vd; + SculptOrigVertData orig_data; - BLI_pbvh_vertex_iter_begin(ss->pbvh, nodes[n], vd, PBVH_ITER_UNIQUE) + sculpt_orig_vert_data_unode_init(&orig_data, ob, unode); + + BKE_pbvh_vertex_iter_begin(ss->pbvh, nodes[n], vd, PBVH_ITER_UNIQUE) { - if (unode->type == SCULPT_UNDO_COORDS) { - copy_v3_v3(vd.co, unode->co[vd.i]); - if (vd.no) copy_v3_v3_short(vd.no, unode->no[vd.i]); - else normal_short_to_float_v3(vd.fno, unode->no[vd.i]); + sculpt_orig_vert_data_update(&orig_data, &vd); + + if (orig_data.unode->type == SCULPT_UNDO_COORDS) { + copy_v3_v3(vd.co, orig_data.co); + if (vd.no) copy_v3_v3_short(vd.no, orig_data.no); + else normal_short_to_float_v3(vd.fno, orig_data.no); } - else if (unode->type == SCULPT_UNDO_MASK) { - *vd.mask = unode->mask[vd.i]; + else if (orig_data.unode->type == SCULPT_UNDO_MASK) { + *vd.mask = orig_data.mask; } if (vd.mvert) vd.mvert->flag |= ME_VERT_PBVH_UPDATE; } - BLI_pbvh_vertex_iter_end; + BKE_pbvh_vertex_iter_end; - BLI_pbvh_node_mark_update(nodes[n]); + BKE_pbvh_node_mark_update(nodes[n]); } } @@ -347,7 +481,7 @@ static int sculpt_get_redraw_rect(ARegion *ar, RegionView3D *rv3d, if (!pbvh) return 0; - BLI_pbvh_redraw_BB(pbvh, bb_min, bb_max); + BKE_pbvh_redraw_BB(pbvh, bb_min, bb_max); /* convert 3D bounding box to screen space */ if (!paint_convert_bb_to_rect(rect, @@ -387,7 +521,7 @@ void sculpt_get_redraw_planes(float planes[4][4], ARegion *ar, /* clear redraw flag from nodes */ if (pbvh) - BLI_pbvh_update(pbvh, PBVH_UpdateRedraw, NULL); + BKE_pbvh_update(pbvh, PBVH_UpdateRedraw, NULL); } /************************ Brush Testing *******************/ @@ -405,7 +539,7 @@ static void sculpt_brush_test_init(SculptSession *ss, SculptBrushTest *test) test->dist = 0.0f; /* just for initialize */ } -static int sculpt_brush_test(SculptBrushTest *test, float co[3]) +static int sculpt_brush_test(SculptBrushTest *test, const float co[3]) { float distsq = len_squared_v3v3(co, test->location); @@ -418,7 +552,7 @@ static int sculpt_brush_test(SculptBrushTest *test, float co[3]) } } -static int sculpt_brush_test_sq(SculptBrushTest *test, float co[3]) +static int sculpt_brush_test_sq(SculptBrushTest *test, const float co[3]) { float distsq = len_squared_v3v3(co, test->location); @@ -734,7 +868,8 @@ static float brush_strength(Sculpt *sd, StrokeCache *cache, float feather) } /* Return a multiplier for brush strength on a particular vertex. */ -static float tex_strength(SculptSession *ss, Brush *br, float point[3], +static float tex_strength(SculptSession *ss, Brush *br, + const float point[3], const float len, const float sculpt_normal[3], const short vno[3], @@ -871,9 +1006,9 @@ static int sculpt_search_sphere_cb(PBVHNode *node, void *data_v) int i; if (data->original) - BLI_pbvh_node_get_original_BB(node, bb_min, bb_max); + BKE_pbvh_node_get_original_BB(node, bb_min, bb_max); else - BLI_pbvh_node_get_BB(node, bb_min, bb_max); + BKE_pbvh_node_get_BB(node, bb_min, bb_max); for (i = 0; i < 3; ++i) { if (bb_min[i] > center[i]) @@ -926,6 +1061,11 @@ static void calc_area_normal(Sculpt *sd, Object *ob, float an[3], PBVHNode **nod original = (paint_brush(&sd->paint)->sculpt_tool == SCULPT_TOOL_GRAB ? TRUE : ss->cache->original); + /* In general the original coords are not available with dynamic + * topology */ + if (ss->bm) + original = FALSE; + (void)sd; /* unused w/o openmp */ zero_v3(an); @@ -942,7 +1082,7 @@ static void calc_area_normal(Sculpt *sd, Object *ob, float an[3], PBVHNode **nod sculpt_brush_test_init(ss, &test); if (original) { - BLI_pbvh_vertex_iter_begin(ss->pbvh, nodes[n], vd, PBVH_ITER_UNIQUE) + BKE_pbvh_vertex_iter_begin(ss->pbvh, nodes[n], vd, PBVH_ITER_UNIQUE) { if (sculpt_brush_test_fast(&test, unode->co[vd.i])) { float fno[3]; @@ -951,10 +1091,10 @@ static void calc_area_normal(Sculpt *sd, Object *ob, float an[3], PBVHNode **nod add_norm_if(ss->cache->view_normal, private_an, private_out_flip, fno); } } - BLI_pbvh_vertex_iter_end; + BKE_pbvh_vertex_iter_end; } else { - BLI_pbvh_vertex_iter_begin(ss->pbvh, nodes[n], vd, PBVH_ITER_UNIQUE) + BKE_pbvh_vertex_iter_begin(ss->pbvh, nodes[n], vd, PBVH_ITER_UNIQUE) { if (sculpt_brush_test_fast(&test, vd.co)) { if (vd.no) { @@ -968,7 +1108,7 @@ static void calc_area_normal(Sculpt *sd, Object *ob, float an[3], PBVHNode **nod } } } - BLI_pbvh_vertex_iter_end; + BKE_pbvh_vertex_iter_end; } #pragma omp critical @@ -1210,6 +1350,71 @@ static float neighbor_average_mask(SculptSession *ss, unsigned vert) return vmask[vert]; } +/* Same logic as neighbor_average(), but for bmesh rather than mesh */ +static void bmesh_neighbor_average(float avg[3], BMVert *v) +{ + const int vfcount = BM_vert_face_count(v); + + zero_v3(avg); + + /* Don't modify corner vertices */ + if (vfcount > 1) { + BMIter liter; + BMLoop *l; + int i, total = 0; + + BM_ITER_ELEM (l, &liter, v, BM_LOOPS_OF_VERT) { + BMVert *adj_v[3] = {l->prev->v, v, l->next->v}; + + for (i = 0; i < 3; i++) { + if (vfcount != 2 || BM_vert_face_count(adj_v[i]) <= 2) { + add_v3_v3(avg, adj_v[i]->co); + total++; + } + } + } + + if (total > 0) { + mul_v3_fl(avg, 1.0f / total); + return; + } + } + + copy_v3_v3(avg, v->co); +} + +/* Same logic as neighbor_average_mask(), but for bmesh rather than mesh */ +static float bmesh_neighbor_average_mask(BMesh *bm, BMVert *v) +{ + BMIter liter; + BMLoop *l; + float avg = 0; + int i, total = 0; + + BM_ITER_ELEM (l, &liter, v, BM_LOOPS_OF_VERT) { + BMVert *adj_v[3] = {l->prev->v, v, l->next->v}; + + for (i = 0; i < 3; i++) { + BMVert *v2 = adj_v[i]; + float *vmask = CustomData_bmesh_get(&bm->vdata, + v2->head.data, + CD_PAINT_MASK); + avg += (*vmask); + total++; + } + } + + if (total > 0) { + return avg / (float)total; + } + else { + float *vmask = CustomData_bmesh_get(&bm->vdata, + v->head.data, + CD_PAINT_MASK); + return (*vmask); + } +} + static void do_mesh_smooth_brush(Sculpt *sd, SculptSession *ss, PBVHNode *node, float bstrength, int smooth_mask) { Brush *brush = paint_brush(&sd->paint); @@ -1220,7 +1425,7 @@ static void do_mesh_smooth_brush(Sculpt *sd, SculptSession *ss, PBVHNode *node, sculpt_brush_test_init(ss, &test); - BLI_pbvh_vertex_iter_begin(ss->pbvh, node, vd, PBVH_ITER_UNIQUE) + BKE_pbvh_vertex_iter_begin(ss->pbvh, node, vd, PBVH_ITER_UNIQUE) { if (sculpt_brush_test(&test, vd.co)) { const float fade = bstrength * tex_strength(ss, brush, vd.co, test.dist, @@ -1248,7 +1453,48 @@ static void do_mesh_smooth_brush(Sculpt *sd, SculptSession *ss, PBVHNode *node, vd.mvert->flag |= ME_VERT_PBVH_UPDATE; } } - BLI_pbvh_vertex_iter_end; + BKE_pbvh_vertex_iter_end; +} + +static void do_bmesh_smooth_brush(Sculpt *sd, SculptSession *ss, PBVHNode *node, float bstrength, int smooth_mask) +{ + Brush *brush = paint_brush(&sd->paint); + PBVHVertexIter vd; + SculptBrushTest test; + + CLAMP(bstrength, 0.0f, 1.0f); + + sculpt_brush_test_init(ss, &test); + + BKE_pbvh_vertex_iter_begin(ss->pbvh, node, vd, PBVH_ITER_UNIQUE) + { + if (sculpt_brush_test(&test, vd.co)) { + const float fade = bstrength * tex_strength(ss, brush, vd.co, test.dist, + ss->cache->view_normal, vd.no, vd.fno, + smooth_mask ? 0 : *vd.mask); + if (smooth_mask) { + float val = bmesh_neighbor_average_mask(ss->bm, vd.bm_vert) - *vd.mask; + val *= fade * bstrength; + *vd.mask += val; + CLAMP(*vd.mask, 0, 1); + } + else { + float avg[3], val[3]; + + bmesh_neighbor_average(avg, vd.bm_vert); + sub_v3_v3v3(val, avg, vd.co); + mul_v3_fl(val, fade); + + add_v3_v3(val, vd.co); + + sculpt_clip(sd, ss, vd.co, val); + } + + if (vd.mvert) + vd.mvert->flag |= ME_VERT_PBVH_UPDATE; + } + } + BKE_pbvh_vertex_iter_end; } static void do_multires_smooth_brush(Sculpt *sd, SculptSession *ss, PBVHNode *node, @@ -1269,9 +1515,9 @@ static void do_multires_smooth_brush(Sculpt *sd, SculptSession *ss, PBVHNode *no CLAMP(bstrength, 0.0f, 1.0f); - BLI_pbvh_node_get_grids(ss->pbvh, node, &grid_indices, &totgrid, + BKE_pbvh_node_get_grids(ss->pbvh, node, &grid_indices, &totgrid, NULL, &gridsize, &griddata, &gridadj); - BLI_pbvh_get_grid_key(ss->pbvh, &key); + BKE_pbvh_get_grid_key(ss->pbvh, &key); thread_num = 0; #ifdef _OPENMP @@ -1405,7 +1651,7 @@ static void smooth(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnode, SculptSession *ss = ob->sculpt; const int max_iterations = 4; const float fract = 1.0f / max_iterations; - PBVHType type = BLI_pbvh_type(ss->pbvh); + PBVHType type = BKE_pbvh_type(ss->pbvh); int iteration, n, count; float last; @@ -1433,6 +1679,9 @@ static void smooth(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnode, do_mesh_smooth_brush(sd, ss, nodes[n], strength, smooth_mask); break; + case PBVH_BMESH: + do_bmesh_smooth_brush(sd, ss, nodes[n], strength, smooth_mask); + break; } } @@ -1462,7 +1711,7 @@ static void do_mask_brush_draw(Sculpt *sd, Object *ob, PBVHNode **nodes, int tot sculpt_brush_test_init(ss, &test); - BLI_pbvh_vertex_iter_begin(ss->pbvh, nodes[n], vd, PBVH_ITER_UNIQUE) + BKE_pbvh_vertex_iter_begin(ss->pbvh, nodes[n], vd, PBVH_ITER_UNIQUE) { if (sculpt_brush_test(&test, vd.co)) { float fade = tex_strength(ss, brush, vd.co, test.dist, @@ -1474,7 +1723,7 @@ static void do_mask_brush_draw(Sculpt *sd, Object *ob, PBVHNode **nodes, int tot if (vd.mvert) vd.mvert->flag |= ME_VERT_PBVH_UPDATE; } - BLI_pbvh_vertex_iter_end; + BKE_pbvh_vertex_iter_end; } } } @@ -1514,11 +1763,11 @@ static void do_draw_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnode) SculptBrushTest test; float (*proxy)[3]; - proxy = BLI_pbvh_node_add_proxy(ss->pbvh, nodes[n])->co; + proxy = BKE_pbvh_node_add_proxy(ss->pbvh, nodes[n])->co; sculpt_brush_test_init(ss, &test); - BLI_pbvh_vertex_iter_begin(ss->pbvh, nodes[n], vd, PBVH_ITER_UNIQUE) + BKE_pbvh_vertex_iter_begin(ss->pbvh, nodes[n], vd, PBVH_ITER_UNIQUE) { if (sculpt_brush_test(&test, vd.co)) { /* offset vertex */ @@ -1532,7 +1781,7 @@ static void do_draw_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnode) vd.mvert->flag |= ME_VERT_PBVH_UPDATE; } } - BLI_pbvh_vertex_iter_end; + BKE_pbvh_vertex_iter_end; } } @@ -1570,11 +1819,11 @@ static void do_crease_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnod SculptBrushTest test; float (*proxy)[3]; - proxy = BLI_pbvh_node_add_proxy(ss->pbvh, nodes[n])->co; + proxy = BKE_pbvh_node_add_proxy(ss->pbvh, nodes[n])->co; sculpt_brush_test_init(ss, &test); - BLI_pbvh_vertex_iter_begin(ss->pbvh, nodes[n], vd, PBVH_ITER_UNIQUE) + BKE_pbvh_vertex_iter_begin(ss->pbvh, nodes[n], vd, PBVH_ITER_UNIQUE) { if (sculpt_brush_test(&test, vd.co)) { /* offset vertex */ @@ -1597,7 +1846,7 @@ static void do_crease_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnod vd.mvert->flag |= ME_VERT_PBVH_UPDATE; } } - BLI_pbvh_vertex_iter_end; + BKE_pbvh_vertex_iter_end; } } @@ -1614,11 +1863,11 @@ static void do_pinch_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnode SculptBrushTest test; float (*proxy)[3]; - proxy = BLI_pbvh_node_add_proxy(ss->pbvh, nodes[n])->co; + proxy = BKE_pbvh_node_add_proxy(ss->pbvh, nodes[n])->co; sculpt_brush_test_init(ss, &test); - BLI_pbvh_vertex_iter_begin(ss->pbvh, nodes[n], vd, PBVH_ITER_UNIQUE) + BKE_pbvh_vertex_iter_begin(ss->pbvh, nodes[n], vd, PBVH_ITER_UNIQUE) { if (sculpt_brush_test(&test, vd.co)) { float fade = bstrength * tex_strength(ss, brush, vd.co, test.dist, @@ -1633,7 +1882,7 @@ static void do_pinch_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnode vd.mvert->flag |= ME_VERT_PBVH_UPDATE; } } - BLI_pbvh_vertex_iter_end; + BKE_pbvh_vertex_iter_end; } } @@ -1659,26 +1908,27 @@ static void do_grab_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnode) #pragma omp parallel for schedule(guided) if (sd->flags & SCULPT_USE_OPENMP) for (n = 0; n < totnode; n++) { PBVHVertexIter vd; - SculptUndoNode *unode; SculptBrushTest test; - float (*origco)[3]; - short (*origno)[3]; + SculptOrigVertData orig_data; float (*proxy)[3]; - unode = sculpt_undo_push_node(ob, nodes[n], SCULPT_UNDO_COORDS); - origco = unode->co; - origno = unode->no; + sculpt_orig_vert_data_init(&orig_data, ob, nodes[n]); - proxy = BLI_pbvh_node_add_proxy(ss->pbvh, nodes[n])->co; + proxy = BKE_pbvh_node_add_proxy(ss->pbvh, nodes[n])->co; sculpt_brush_test_init(ss, &test); - BLI_pbvh_vertex_iter_begin(ss->pbvh, nodes[n], vd, PBVH_ITER_UNIQUE) + BKE_pbvh_vertex_iter_begin(ss->pbvh, nodes[n], vd, PBVH_ITER_UNIQUE) { - if (sculpt_brush_test(&test, origco[vd.i])) { - const float fade = bstrength * tex_strength(ss, brush, origco[vd.i], test.dist, - ss->cache->sculpt_normal_symm, origno[vd.i], - NULL, vd.mask ? *vd.mask : 0.0f); + sculpt_orig_vert_data_update(&orig_data, &vd); + + if (sculpt_brush_test(&test, orig_data.co)) { + const float fade = bstrength * tex_strength(ss, brush, + orig_data.co, + test.dist, + ss->cache->sculpt_normal_symm, + orig_data.no, + NULL, vd.mask ? *vd.mask : 0.0f); mul_v3_v3fl(proxy[vd.i], grab_delta, fade); @@ -1686,7 +1936,7 @@ static void do_grab_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnode) vd.mvert->flag |= ME_VERT_PBVH_UPDATE; } } - BLI_pbvh_vertex_iter_end; + BKE_pbvh_vertex_iter_end; } } @@ -1710,11 +1960,11 @@ static void do_nudge_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnode SculptBrushTest test; float (*proxy)[3]; - proxy = BLI_pbvh_node_add_proxy(ss->pbvh, nodes[n])->co; + proxy = BKE_pbvh_node_add_proxy(ss->pbvh, nodes[n])->co; sculpt_brush_test_init(ss, &test); - BLI_pbvh_vertex_iter_begin(ss->pbvh, nodes[n], vd, PBVH_ITER_UNIQUE) + BKE_pbvh_vertex_iter_begin(ss->pbvh, nodes[n], vd, PBVH_ITER_UNIQUE) { if (sculpt_brush_test(&test, vd.co)) { const float fade = bstrength * tex_strength(ss, brush, vd.co, test.dist, @@ -1727,7 +1977,7 @@ static void do_nudge_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnode vd.mvert->flag |= ME_VERT_PBVH_UPDATE; } } - BLI_pbvh_vertex_iter_end; + BKE_pbvh_vertex_iter_end; } } @@ -1759,11 +2009,11 @@ static void do_snake_hook_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int to SculptBrushTest test; float (*proxy)[3]; - proxy = BLI_pbvh_node_add_proxy(ss->pbvh, nodes[n])->co; + proxy = BKE_pbvh_node_add_proxy(ss->pbvh, nodes[n])->co; sculpt_brush_test_init(ss, &test); - BLI_pbvh_vertex_iter_begin(ss->pbvh, nodes[n], vd, PBVH_ITER_UNIQUE) + BKE_pbvh_vertex_iter_begin(ss->pbvh, nodes[n], vd, PBVH_ITER_UNIQUE) { if (sculpt_brush_test(&test, vd.co)) { const float fade = bstrength * tex_strength(ss, brush, vd.co, test.dist, @@ -1776,7 +2026,7 @@ static void do_snake_hook_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int to vd.mvert->flag |= ME_VERT_PBVH_UPDATE; } } - BLI_pbvh_vertex_iter_end; + BKE_pbvh_vertex_iter_end; } } @@ -1797,26 +2047,27 @@ static void do_thumb_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnode #pragma omp parallel for schedule(guided) if (sd->flags & SCULPT_USE_OPENMP) for (n = 0; n < totnode; n++) { PBVHVertexIter vd; - SculptUndoNode *unode; SculptBrushTest test; - float (*origco)[3]; - short (*origno)[3]; + SculptOrigVertData orig_data; float (*proxy)[3]; - unode = sculpt_undo_push_node(ob, nodes[n], SCULPT_UNDO_COORDS); - origco = unode->co; - origno = unode->no; + sculpt_orig_vert_data_init(&orig_data, ob, nodes[n]); - proxy = BLI_pbvh_node_add_proxy(ss->pbvh, nodes[n])->co; + proxy = BKE_pbvh_node_add_proxy(ss->pbvh, nodes[n])->co; sculpt_brush_test_init(ss, &test); - BLI_pbvh_vertex_iter_begin(ss->pbvh, nodes[n], vd, PBVH_ITER_UNIQUE) + BKE_pbvh_vertex_iter_begin(ss->pbvh, nodes[n], vd, PBVH_ITER_UNIQUE) { - if (sculpt_brush_test(&test, origco[vd.i])) { - const float fade = bstrength * tex_strength(ss, brush, origco[vd.i], test.dist, + sculpt_orig_vert_data_update(&orig_data, &vd); + + if (sculpt_brush_test(&test, orig_data.co)) { + const float fade = bstrength * tex_strength(ss, brush, + orig_data.co, + test.dist, ss->cache->sculpt_normal_symm, - origno[vd.i], NULL, vd.mask ? *vd.mask : 0.0f); + orig_data.no, + NULL, vd.mask ? *vd.mask : 0.0f); mul_v3_v3fl(proxy[vd.i], cono, fade); @@ -1824,7 +2075,7 @@ static void do_thumb_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnode vd.mvert->flag |= ME_VERT_PBVH_UPDATE; } } - BLI_pbvh_vertex_iter_end; + BKE_pbvh_vertex_iter_end; } } @@ -1850,36 +2101,37 @@ static void do_rotate_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnod #pragma omp parallel for schedule(guided) if (sd->flags & SCULPT_USE_OPENMP) for (n = 0; n < totnode; n++) { PBVHVertexIter vd; - SculptUndoNode *unode; SculptBrushTest test; - float (*origco)[3]; - short (*origno)[3]; + SculptOrigVertData orig_data; float (*proxy)[3]; - unode = sculpt_undo_push_node(ob, nodes[n], SCULPT_UNDO_COORDS); - origco = unode->co; - origno = unode->no; + sculpt_orig_vert_data_init(&orig_data, ob, nodes[n]); - proxy = BLI_pbvh_node_add_proxy(ss->pbvh, nodes[n])->co; + proxy = BKE_pbvh_node_add_proxy(ss->pbvh, nodes[n])->co; sculpt_brush_test_init(ss, &test); - BLI_pbvh_vertex_iter_begin(ss->pbvh, nodes[n], vd, PBVH_ITER_UNIQUE) + BKE_pbvh_vertex_iter_begin(ss->pbvh, nodes[n], vd, PBVH_ITER_UNIQUE) { - if (sculpt_brush_test(&test, origco[vd.i])) { - const float fade = bstrength * tex_strength(ss, brush, origco[vd.i], test.dist, + sculpt_orig_vert_data_update(&orig_data, &vd); + + if (sculpt_brush_test(&test, orig_data.co)) { + const float fade = bstrength * tex_strength(ss, brush, + orig_data.co, + test.dist, ss->cache->sculpt_normal_symm, - origno[vd.i], NULL, vd.mask ? *vd.mask : 0.0f); + orig_data.no, + NULL, vd.mask ? *vd.mask : 0.0f); - mul_v3_m4v3(proxy[vd.i], m, origco[vd.i]); - sub_v3_v3(proxy[vd.i], origco[vd.i]); + mul_v3_m4v3(proxy[vd.i], m, orig_data.co); + sub_v3_v3(proxy[vd.i], orig_data.co); mul_v3_fl(proxy[vd.i], fade); if (vd.mvert) vd.mvert->flag |= ME_VERT_PBVH_UPDATE; } } - BLI_pbvh_vertex_iter_end; + BKE_pbvh_vertex_iter_end; } } @@ -1901,25 +2153,25 @@ static void do_layer_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnode for (n = 0; n < totnode; n++) { PBVHVertexIter vd; SculptBrushTest test; - SculptUndoNode *unode; - float (*origco)[3], *layer_disp; + SculptOrigVertData orig_data; + float *layer_disp; /* XXX: layer brush needs conversion to proxy but its more complicated */ - /* proxy = BLI_pbvh_node_add_proxy(ss->pbvh, nodes[n])->co; */ + /* proxy = BKE_pbvh_node_add_proxy(ss->pbvh, nodes[n])->co; */ - unode = sculpt_undo_push_node(ob, nodes[n], SCULPT_UNDO_COORDS); - origco = unode->co; - if (!unode->layer_disp) { - #pragma omp critical - unode->layer_disp = MEM_callocN(sizeof(float) * unode->totvert, "layer disp"); - } - - layer_disp = unode->layer_disp; + sculpt_orig_vert_data_init(&orig_data, ob, nodes[n]); + #pragma omp critical + { + layer_disp = BKE_pbvh_node_layer_disp_get(ss->pbvh, nodes[n]); + } + sculpt_brush_test_init(ss, &test); - BLI_pbvh_vertex_iter_begin(ss->pbvh, nodes[n], vd, PBVH_ITER_UNIQUE) + BKE_pbvh_vertex_iter_begin(ss->pbvh, nodes[n], vd, PBVH_ITER_UNIQUE) { - if (sculpt_brush_test(&test, origco[vd.i])) { + sculpt_orig_vert_data_update(&orig_data, &vd); + + if (sculpt_brush_test(&test, orig_data.co)) { const float fade = bstrength * tex_strength(ss, brush, vd.co, test.dist, ss->cache->sculpt_normal_symm, vd.no, vd.fno, vd.mask ? *vd.mask : 0.0f); @@ -1941,7 +2193,7 @@ static void do_layer_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnode add_v3_v3(val, ss->layer_co[index]); } else { - add_v3_v3(val, origco[vd.i]); + add_v3_v3(val, orig_data.co); } sculpt_clip(sd, ss, vd.co, val); @@ -1950,7 +2202,7 @@ static void do_layer_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnode vd.mvert->flag |= ME_VERT_PBVH_UPDATE; } } - BLI_pbvh_vertex_iter_end; + BKE_pbvh_vertex_iter_end; } } @@ -1967,11 +2219,11 @@ static void do_inflate_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totno SculptBrushTest test; float (*proxy)[3]; - proxy = BLI_pbvh_node_add_proxy(ss->pbvh, nodes[n])->co; + proxy = BKE_pbvh_node_add_proxy(ss->pbvh, nodes[n])->co; sculpt_brush_test_init(ss, &test); - BLI_pbvh_vertex_iter_begin(ss->pbvh, nodes[n], vd, PBVH_ITER_UNIQUE) + BKE_pbvh_vertex_iter_begin(ss->pbvh, nodes[n], vd, PBVH_ITER_UNIQUE) { if (sculpt_brush_test(&test, vd.co)) { const float fade = bstrength * tex_strength(ss, brush, vd.co, test.dist, @@ -1989,7 +2241,7 @@ static void do_inflate_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totno vd.mvert->flag |= ME_VERT_PBVH_UPDATE; } } - BLI_pbvh_vertex_iter_end; + BKE_pbvh_vertex_iter_end; } } @@ -2016,24 +2268,24 @@ static void calc_flatten_center(Sculpt *sd, Object *ob, PBVHNode **nodes, int to sculpt_brush_test_init(ss, &test); if (ss->cache->original) { - BLI_pbvh_vertex_iter_begin(ss->pbvh, nodes[n], vd, PBVH_ITER_UNIQUE) + BKE_pbvh_vertex_iter_begin(ss->pbvh, nodes[n], vd, PBVH_ITER_UNIQUE) { if (sculpt_brush_test_fast(&test, unode->co[vd.i])) { add_v3_v3(private_fc, unode->co[vd.i]); private_count++; } } - BLI_pbvh_vertex_iter_end; + BKE_pbvh_vertex_iter_end; } else { - BLI_pbvh_vertex_iter_begin(ss->pbvh, nodes[n], vd, PBVH_ITER_UNIQUE) + BKE_pbvh_vertex_iter_begin(ss->pbvh, nodes[n], vd, PBVH_ITER_UNIQUE) { if (sculpt_brush_test_fast(&test, vd.co)) { add_v3_v3(private_fc, vd.co); private_count++; } } - BLI_pbvh_vertex_iter_end; + BKE_pbvh_vertex_iter_end; } #pragma omp critical @@ -2082,8 +2334,8 @@ static void calc_area_normal_and_flatten_center(Sculpt *sd, Object *ob, unode = sculpt_undo_push_node(ob, nodes[n], SCULPT_UNDO_COORDS); sculpt_brush_test_init(ss, &test); - if (ss->cache->original) { - BLI_pbvh_vertex_iter_begin(ss->pbvh, nodes[n], vd, PBVH_ITER_UNIQUE) + if (ss->cache->original && unode->co) { + BKE_pbvh_vertex_iter_begin(ss->pbvh, nodes[n], vd, PBVH_ITER_UNIQUE) { if (sculpt_brush_test_fast(&test, unode->co[vd.i])) { /* for area normal */ @@ -2097,10 +2349,10 @@ static void calc_area_normal_and_flatten_center(Sculpt *sd, Object *ob, private_count++; } } - BLI_pbvh_vertex_iter_end; + BKE_pbvh_vertex_iter_end; } else { - BLI_pbvh_vertex_iter_begin(ss->pbvh, nodes[n], vd, PBVH_ITER_UNIQUE) + BKE_pbvh_vertex_iter_begin(ss->pbvh, nodes[n], vd, PBVH_ITER_UNIQUE) { if (sculpt_brush_test_fast(&test, vd.co)) { /* for area normal */ @@ -2119,7 +2371,7 @@ static void calc_area_normal_and_flatten_center(Sculpt *sd, Object *ob, private_count++; } } - BLI_pbvh_vertex_iter_end; + BKE_pbvh_vertex_iter_end; } #pragma omp critical @@ -2301,11 +2553,11 @@ static void do_flatten_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totno SculptBrushTest test; float (*proxy)[3]; - proxy = BLI_pbvh_node_add_proxy(ss->pbvh, nodes[n])->co; + proxy = BKE_pbvh_node_add_proxy(ss->pbvh, nodes[n])->co; sculpt_brush_test_init(ss, &test); - BLI_pbvh_vertex_iter_begin(ss->pbvh, nodes[n], vd, PBVH_ITER_UNIQUE) + BKE_pbvh_vertex_iter_begin(ss->pbvh, nodes[n], vd, PBVH_ITER_UNIQUE) { if (sculpt_brush_test_sq(&test, vd.co)) { float intr[3]; @@ -2326,7 +2578,7 @@ static void do_flatten_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totno } } } - BLI_pbvh_vertex_iter_end; + BKE_pbvh_vertex_iter_end; } } @@ -2373,11 +2625,11 @@ static void do_clay_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnode) SculptBrushTest test; float (*proxy)[3]; - proxy = BLI_pbvh_node_add_proxy(ss->pbvh, nodes[n])->co; + proxy = BKE_pbvh_node_add_proxy(ss->pbvh, nodes[n])->co; sculpt_brush_test_init(ss, &test); - BLI_pbvh_vertex_iter_begin(ss->pbvh, nodes[n], vd, PBVH_ITER_UNIQUE) + BKE_pbvh_vertex_iter_begin(ss->pbvh, nodes[n], vd, PBVH_ITER_UNIQUE) { if (sculpt_brush_test_sq(&test, vd.co)) { if (plane_point_side_flip(vd.co, an, fc, flip)) { @@ -2401,7 +2653,7 @@ static void do_clay_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnode) } } } - BLI_pbvh_vertex_iter_end; + BKE_pbvh_vertex_iter_end; } } @@ -2475,11 +2727,11 @@ static void do_clay_strips_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int t SculptBrushTest test; float (*proxy)[3]; - proxy = BLI_pbvh_node_add_proxy(ss->pbvh, nodes[n])->co; + proxy = BKE_pbvh_node_add_proxy(ss->pbvh, nodes[n])->co; sculpt_brush_test_init(ss, &test); - BLI_pbvh_vertex_iter_begin(ss->pbvh, nodes[n], vd, PBVH_ITER_UNIQUE) + BKE_pbvh_vertex_iter_begin(ss->pbvh, nodes[n], vd, PBVH_ITER_UNIQUE) { if (sculpt_brush_test_cube(&test, vd.co, mat)) { if (plane_point_side_flip(vd.co, sn, fc, flip)) { @@ -2503,7 +2755,7 @@ static void do_clay_strips_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int t } } } - BLI_pbvh_vertex_iter_end; + BKE_pbvh_vertex_iter_end; } } @@ -2539,11 +2791,11 @@ static void do_fill_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnode) SculptBrushTest test; float (*proxy)[3]; - proxy = BLI_pbvh_node_add_proxy(ss->pbvh, nodes[n])->co; + proxy = BKE_pbvh_node_add_proxy(ss->pbvh, nodes[n])->co; sculpt_brush_test_init(ss, &test); - BLI_pbvh_vertex_iter_begin(ss->pbvh, nodes[n], vd, PBVH_ITER_UNIQUE) + BKE_pbvh_vertex_iter_begin(ss->pbvh, nodes[n], vd, PBVH_ITER_UNIQUE) { if (sculpt_brush_test_sq(&test, vd.co)) { if (plane_point_side(vd.co, an, fc)) { @@ -2567,7 +2819,7 @@ static void do_fill_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnode) } } } - BLI_pbvh_vertex_iter_end; + BKE_pbvh_vertex_iter_end; } } @@ -2603,11 +2855,11 @@ static void do_scrape_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnod SculptBrushTest test; float (*proxy)[3]; - proxy = BLI_pbvh_node_add_proxy(ss->pbvh, nodes[n])->co; + proxy = BKE_pbvh_node_add_proxy(ss->pbvh, nodes[n])->co; sculpt_brush_test_init(ss, &test); - BLI_pbvh_vertex_iter_begin(ss->pbvh, nodes[n], vd, PBVH_ITER_UNIQUE) + BKE_pbvh_vertex_iter_begin(ss->pbvh, nodes[n], vd, PBVH_ITER_UNIQUE) { if (sculpt_brush_test_sq(&test, vd.co)) { if (!plane_point_side(vd.co, an, fc)) { @@ -2631,7 +2883,7 @@ static void do_scrape_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnod } } } - BLI_pbvh_vertex_iter_end; + BKE_pbvh_vertex_iter_end; } } @@ -2688,6 +2940,65 @@ void sculpt_vertcos_to_key(Object *ob, KeyBlock *kb, float (*vertCos)[3]) BKE_key_convert_from_vertcos(ob, kb, vertCos); } +/* Note: we do the topology update before any brush actions to avoid + * issues with the proxies. The size of the proxy can't change, so + * topology must be updated first. */ +static void sculpt_topology_update(Sculpt *sd, Object *ob, Brush *brush) +{ + SculptSession *ss = ob->sculpt; + SculptSearchSphereData data; + PBVHNode **nodes = NULL; + float radius; + int n, totnode; + + /* Build a list of all nodes that are potentially within the + * brush's area of influence */ + data.ss = ss; + data.sd = sd; + + radius = ss->cache->radius * 1.25f; + + data.radius_squared = radius * radius; + data.original = ELEM4(brush->sculpt_tool, + SCULPT_TOOL_GRAB, + SCULPT_TOOL_ROTATE, + SCULPT_TOOL_THUMB, + SCULPT_TOOL_LAYER); + + BKE_pbvh_search_gather(ss->pbvh, sculpt_search_sphere_cb, &data, &nodes, &totnode); + + /* Only act if some verts are inside the brush area */ + if (totnode) { + PBVHTopologyUpdateMode mode = PBVH_Subdivide; + + if ((sd->flags & SCULPT_DYNTOPO_COLLAPSE) || + (brush->sculpt_tool == SCULPT_TOOL_SIMPLIFY)) + { + mode |= PBVH_Collapse; + } + + for (n = 0; n < totnode; n++) { + sculpt_undo_push_node(ob, nodes[n], + brush->sculpt_tool == SCULPT_TOOL_MASK ? + SCULPT_UNDO_MASK : SCULPT_UNDO_COORDS); + BKE_pbvh_node_mark_update(nodes[n]); + + if (BKE_pbvh_type(ss->pbvh) == PBVH_BMESH) { + BKE_pbvh_node_mark_topology_update(nodes[n]); + BKE_pbvh_bmesh_node_save_orig(nodes[n]); + } + } + + if (BKE_pbvh_type(ss->pbvh) == PBVH_BMESH) { + BKE_pbvh_bmesh_update_topology(ss->pbvh, mode, + ss->cache->location, + ss->cache->radius); + } + + MEM_freeN(nodes); + } +} + static void do_brush_action(Sculpt *sd, Object *ob, Brush *brush) { SculptSession *ss = ob->sculpt; @@ -2704,7 +3015,7 @@ static void do_brush_action(Sculpt *sd, Object *ob, Brush *brush) SCULPT_TOOL_ROTATE, SCULPT_TOOL_THUMB, SCULPT_TOOL_LAYER); - BLI_pbvh_search_gather(ss->pbvh, sculpt_search_sphere_cb, &data, &nodes, &totnode); + BKE_pbvh_search_gather(ss->pbvh, sculpt_search_sphere_cb, &data, &nodes, &totnode); /* Only act if some verts are inside the brush area */ if (totnode) { @@ -2713,7 +3024,7 @@ static void do_brush_action(Sculpt *sd, Object *ob, Brush *brush) sculpt_undo_push_node(ob, nodes[n], brush->sculpt_tool == SCULPT_TOOL_MASK ? SCULPT_UNDO_MASK : SCULPT_UNDO_COORDS); - BLI_pbvh_node_mark_update(nodes[n]); + BKE_pbvh_node_mark_update(nodes[n]); } if (brush_needs_sculpt_normal(brush)) @@ -2821,7 +3132,7 @@ static void sculpt_combine_proxies(Sculpt *sd, Object *ob) PBVHNode **nodes; int totnode, n; - BLI_pbvh_gather_proxies(ss->pbvh, &nodes, &totnode); + BKE_pbvh_gather_proxies(ss->pbvh, &nodes, &totnode); if (!ELEM(brush->sculpt_tool, SCULPT_TOOL_SMOOTH, SCULPT_TOOL_LAYER)) { /* these brushes start from original coordinates */ @@ -2835,18 +3146,25 @@ static void sculpt_combine_proxies(Sculpt *sd, Object *ob) int proxy_count; float (*orco)[3]; - if (use_orco) + if (use_orco && !ss->bm) orco = sculpt_undo_push_node(ob, nodes[n], SCULPT_UNDO_COORDS)->co; - BLI_pbvh_node_get_proxies(nodes[n], &proxies, &proxy_count); + BKE_pbvh_node_get_proxies(nodes[n], &proxies, &proxy_count); - BLI_pbvh_vertex_iter_begin(ss->pbvh, nodes[n], vd, PBVH_ITER_UNIQUE) + BKE_pbvh_vertex_iter_begin(ss->pbvh, nodes[n], vd, PBVH_ITER_UNIQUE) { float val[3]; int p; - if (use_orco) - copy_v3_v3(val, orco[vd.i]); + if (use_orco) { + if (ss->bm) { + copy_v3_v3(val, + BM_log_original_vert_co(ss->bm_log, + vd.bm_vert)); + } + else + copy_v3_v3(val, orco[vd.i]); + } else copy_v3_v3(val, vd.co); @@ -2858,9 +3176,9 @@ static void sculpt_combine_proxies(Sculpt *sd, Object *ob) if (ss->modifiers_active) sculpt_flush_pbvhvert_deform(ob, &vd); } - BLI_pbvh_vertex_iter_end; + BKE_pbvh_vertex_iter_end; - BLI_pbvh_node_free_proxies(nodes[n]); + BKE_pbvh_node_free_proxies(nodes[n]); } } @@ -2877,7 +3195,7 @@ static void sculpt_update_keyblock(Object *ob) /* Keyblock update happens after handling deformation caused by modifiers, * so ss->orig_cos would be updated with new stroke */ if (ss->orig_cos) vertCos = ss->orig_cos; - else vertCos = BLI_pbvh_get_vertCos(ss->pbvh); + else vertCos = BKE_pbvh_get_vertCos(ss->pbvh); if (vertCos) { sculpt_vertcos_to_key(ob, ss->kb, vertCos); @@ -2905,13 +3223,13 @@ static void sculpt_flush_stroke_deform(Sculpt *sd, Object *ob) if (ss->kb) vertCos = MEM_callocN(sizeof(*vertCos) * me->totvert, "flushStrokeDeofrm keyVerts"); - BLI_pbvh_search_gather(ss->pbvh, NULL, NULL, &nodes, &totnode); + BKE_pbvh_search_gather(ss->pbvh, NULL, NULL, &nodes, &totnode); #pragma omp parallel for schedule(guided) if (sd->flags & SCULPT_USE_OPENMP) for (n = 0; n < totnode; n++) { PBVHVertexIter vd; - BLI_pbvh_vertex_iter_begin(ss->pbvh, nodes[n], vd, PBVH_ITER_UNIQUE) + BKE_pbvh_vertex_iter_begin(ss->pbvh, nodes[n], vd, PBVH_ITER_UNIQUE) { sculpt_flush_pbvhvert_deform(ob, &vd); @@ -2920,7 +3238,7 @@ static void sculpt_flush_stroke_deform(Sculpt *sd, Object *ob) copy_v3_v3(vertCos[index], ss->orig_cos[index]); } } - BLI_pbvh_vertex_iter_end; + BKE_pbvh_vertex_iter_end; } if (vertCos) { @@ -2978,7 +3296,10 @@ static void calc_brushdata_symm(Sculpt *sd, StrokeCache *cache, const char symm, mul_m4_v3(cache->symm_rot_mat, cache->grab_delta_symmetry); } +typedef void (*BrushActionFunc)(Sculpt *sd, Object *ob, Brush *brush); + static void do_radial_symmetry(Sculpt *sd, Object *ob, Brush *brush, + BrushActionFunc action, const char symm, const int axis, const float feather) { @@ -2989,7 +3310,7 @@ static void do_radial_symmetry(Sculpt *sd, Object *ob, Brush *brush, const float angle = 2 * M_PI * i / sd->radial_symm[axis - 'X']; ss->cache->radial_symmetry_pass = i; calc_brushdata_symm(sd, ss->cache, symm, axis, angle, feather); - do_brush_action(sd, ob, brush); + action(sd, ob, brush); } } @@ -3006,7 +3327,8 @@ static void sculpt_fix_noise_tear(Sculpt *sd, Object *ob) multires_stitch_grids(ob); } -static void do_symmetrical_brush_actions(Sculpt *sd, Object *ob) +static void do_symmetrical_brush_actions(Sculpt *sd, Object *ob, + BrushActionFunc action) { Brush *brush = paint_brush(&sd->paint); SculptSession *ss = ob->sculpt; @@ -3017,7 +3339,6 @@ static void do_symmetrical_brush_actions(Sculpt *sd, Object *ob) float feather = calc_symmetry_feather(sd, ss->cache); cache->bstrength = brush_strength(sd, cache, feather); - cache->symmetry = symm; /* symm is a bit combination of XYZ - 1 is mirror X; 2 is Y; 3 is XY; 4 is Z; 5 is XZ; 6 is YZ; 7 is XYZ */ @@ -3027,23 +3348,13 @@ static void do_symmetrical_brush_actions(Sculpt *sd, Object *ob) cache->radial_symmetry_pass = 0; calc_brushdata_symm(sd, cache, i, 0, 0, feather); - do_brush_action(sd, ob, brush); + action(sd, ob, brush); - do_radial_symmetry(sd, ob, brush, i, 'X', feather); - do_radial_symmetry(sd, ob, brush, i, 'Y', feather); - do_radial_symmetry(sd, ob, brush, i, 'Z', feather); + do_radial_symmetry(sd, ob, brush, action, i, 'X', feather); + do_radial_symmetry(sd, ob, brush, action, i, 'Y', feather); + do_radial_symmetry(sd, ob, brush, action, i, 'Z', feather); } } - - sculpt_combine_proxies(sd, ob); - - /* hack to fix noise texture tearing mesh */ - sculpt_fix_noise_tear(sd, ob); - - if (ss->modifiers_active) - sculpt_flush_stroke_deform(sd, ob); - - cache->first_time = 0; } static void sculpt_update_tex(const Scene *scene, Sculpt *sd, SculptSession *ss) @@ -3142,7 +3453,7 @@ void sculpt_update_mesh_elements(Scene *scene, Sculpt *sd, Object *ob, ss->orig_cos = (ss->kb) ? BKE_key_convert_to_vertcos(ob, ss->kb) : mesh_getVertexCos(me, NULL); crazyspace_build_sculpt(scene, ob, &ss->deform_imats, &ss->deform_cos); - BLI_pbvh_apply_vertCos(ss->pbvh, ss->deform_cos); + BKE_pbvh_apply_vertCos(ss->pbvh, ss->deform_cos); for (a = 0; a < me->totvert; ++a) { invert_m3(ss->deform_imats[a]); @@ -3152,12 +3463,12 @@ void sculpt_update_mesh_elements(Scene *scene, Sculpt *sd, Object *ob, else free_sculptsession_deformMats(ss); /* if pbvh is deformed, key block is already applied to it */ - if (ss->kb && !BLI_pbvh_isDeformed(ss->pbvh)) { + if (ss->kb && !BKE_pbvh_isDeformed(ss->pbvh)) { float (*vertCos)[3] = BKE_key_convert_to_vertcos(ob, ss->kb); if (vertCos) { /* apply shape keys coordinates to PBVH */ - BLI_pbvh_apply_vertCos(ss->pbvh, vertCos); + BKE_pbvh_apply_vertCos(ss->pbvh, vertCos); MEM_freeN(vertCos); } } @@ -3220,6 +3531,8 @@ static const char *sculpt_tool_name(Sculpt *sd) return "Rotate Brush"; case SCULPT_TOOL_MASK: return "Mask Brush"; + case SCULPT_TOOL_SIMPLIFY: + return "Simplify Brush"; } return "Sculpting"; @@ -3291,7 +3604,7 @@ static void sculpt_omp_start(Sculpt *sd, SculptSession *ss) if (ss->multires) { int i, gridsize, array_mem_size; - BLI_pbvh_node_get_grids(ss->pbvh, NULL, NULL, NULL, NULL, + BKE_pbvh_node_get_grids(ss->pbvh, NULL, NULL, NULL, NULL, &gridsize, NULL, NULL); array_mem_size = cache->num_threads * sizeof(void *); @@ -3406,8 +3719,9 @@ static void sculpt_update_cache_invariants(bContext *C, Sculpt *sd, SculptSessio ED_view3d_global_to_vector(cache->vc->rv3d, cache->vc->rv3d->twmat[3], cache->true_view_normal); /* Initialize layer brush displacements and persistent coords */ if (brush->sculpt_tool == SCULPT_TOOL_LAYER) { - /* not supported yet for multires */ - if (!ss->multires && !ss->layer_co && (brush->flag & BRUSH_PERSISTENT)) { + /* not supported yet for multires or dynamic topology */ + if (!ss->multires && !ss->bm && !ss->layer_co && + (brush->flag & BRUSH_PERSISTENT)) { if (!ss->layer_co) ss->layer_co = MEM_mallocN(sizeof(float) * 3 * ss->totvert, "sculpt mesh vertices copy"); @@ -3721,17 +4035,26 @@ typedef struct { static void sculpt_raycast_cb(PBVHNode *node, void *data_v, float *tmin) { - if (BLI_pbvh_node_get_tmin(node) < *tmin) { + if (BKE_pbvh_node_get_tmin(node) < *tmin) { SculptRaycastData *srd = data_v; float (*origco)[3] = NULL; + int use_origco = FALSE; if (srd->original && srd->ss->cache) { - /* intersect with coordinates from before we started stroke */ - SculptUndoNode *unode = sculpt_undo_get_node(node); - origco = (unode) ? unode->co : NULL; + if (BKE_pbvh_type(srd->ss->pbvh) == PBVH_BMESH) { + use_origco = TRUE; + } + else { + /* intersect with coordinates from before we started stroke */ + SculptUndoNode *unode = sculpt_undo_get_node(node); + origco = (unode) ? unode->co : NULL; + use_origco = origco ? TRUE : FALSE; + } } - if (BLI_pbvh_node_raycast(srd->ss->pbvh, node, origco, srd->ray_start, srd->ray_normal, &srd->dist)) { + if (BKE_pbvh_node_raycast(srd->ss->pbvh, node, origco, use_origco, + srd->ray_start, srd->ray_normal, &srd->dist)) + { srd->hit = 1; *tmin = srd->dist; } @@ -3780,7 +4103,7 @@ int sculpt_stroke_get_location(bContext *C, float out[3], const float mouse[2]) srd.dist = dist; srd.hit = 0; srd.original = (cache) ? cache->original : 0; - BLI_pbvh_raycast(ss->pbvh, sculpt_raycast_cb, &srd, + BKE_pbvh_raycast(ss->pbvh, sculpt_raycast_cb, &srd, ray_start, ray_normal, srd.original); copy_v3_v3(out, ray_normal); @@ -3829,8 +4152,9 @@ static int sculpt_brush_stroke_init(bContext *C, wmOperator *op) return 1; } -static void sculpt_restore_mesh(Sculpt *sd, SculptSession *ss) +static void sculpt_restore_mesh(Sculpt *sd, Object *ob) { + SculptSession *ss = ob->sculpt; Brush *brush = paint_brush(&sd->paint); /* Restore the mesh before continuing with anchored stroke */ @@ -3839,7 +4163,7 @@ static void sculpt_restore_mesh(Sculpt *sd, SculptSession *ss) BKE_brush_use_size_pressure(ss->cache->vc->scene, brush)) || (brush->flag & BRUSH_RESTORE_MESH)) { - paint_mesh_restore_co(sd, ss); + paint_mesh_restore_co(sd, ob); } } @@ -3862,7 +4186,7 @@ static void sculpt_flush_update(bContext *C) else { rcti r; - BLI_pbvh_update(ss->pbvh, PBVH_UpdateBB, NULL); + BKE_pbvh_update(ss->pbvh, PBVH_UpdateBB, NULL); if (sculpt_get_redraw_rect(ar, CTX_wm_region_view3d(C), ob, &r)) { if (ss->cache) ss->cache->previous_r = r; @@ -3917,11 +4241,33 @@ static void sculpt_stroke_update_step(bContext *C, struct PaintStroke *stroke, P Sculpt *sd = CTX_data_tool_settings(C)->sculpt; Object *ob = CTX_data_active_object(C); SculptSession *ss = ob->sculpt; + const Brush *brush = paint_brush(&sd->paint); sculpt_stroke_modifiers_check(C, ob); sculpt_update_cache_variants(C, sd, ob, stroke, itemptr); - sculpt_restore_mesh(sd, ss); - do_symmetrical_brush_actions(sd, ob); + sculpt_restore_mesh(sd, ob); + + BKE_pbvh_bmesh_detail_size_set(ss->pbvh, + (ss->cache->radius / + (float)ss->cache->pixel_radius) * + (float)sd->detail_size); + + if (sculpt_stroke_dynamic_topology(ss, brush)) { + do_symmetrical_brush_actions(sd, ob, sculpt_topology_update); + } + + if (paint_brush(&sd->paint)->sculpt_tool != SCULPT_TOOL_SIMPLIFY) + do_symmetrical_brush_actions(sd, ob, do_brush_action); + + sculpt_combine_proxies(sd, ob); + + /* hack to fix noise texture tearing mesh */ + sculpt_fix_noise_tear(sd, ob); + + if (ss->modifiers_active) + sculpt_flush_stroke_deform(sd, ob); + + ss->cache->first_time = FALSE; /* Cleanup */ sculpt_flush_update(C); @@ -3980,7 +4326,10 @@ static void sculpt_stroke_done(const bContext *C, struct PaintStroke *UNUSED(str sculpt_undo_push_end(); - BLI_pbvh_update(ss->pbvh, PBVH_UpdateOriginalBB, NULL); + BKE_pbvh_update(ss->pbvh, PBVH_UpdateOriginalBB, NULL); + + if (BKE_pbvh_type(ss->pbvh) == PBVH_BMESH) + BKE_pbvh_bmesh_after_stroke(ss->pbvh); /* optimization: if there is locked key and active modifiers present in */ /* the stack, keyblock is updating at each step. otherwise we could update */ @@ -4055,7 +4404,7 @@ static int sculpt_brush_stroke_cancel(bContext *C, wmOperator *op) Sculpt *sd = CTX_data_tool_settings(C)->sculpt; if (ss->cache) { - paint_mesh_restore_co(sd, ss); + paint_mesh_restore_co(sd, ob); } paint_stroke_cancel(C, op); @@ -4137,6 +4486,266 @@ static void SCULPT_OT_set_persistent_base(wmOperatorType *ot) ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; } +/************************** Dynamic Topology **************************/ + +static void sculpt_dynamic_topology_triangulate(BMesh *bm) +{ + BMO_op_callf(bm, BMO_FLAG_DEFAULTS, "triangulate faces=%af"); +} + +void sculpt_pbvh_clear(Object *ob) +{ + SculptSession *ss = ob->sculpt; + DerivedMesh *dm = ob->derivedFinal; + + /* Clear out any existing DM and PBVH */ + if (ss->pbvh) + BKE_pbvh_free(ss->pbvh); + ss->pbvh = NULL; + if (dm) + dm->getPBVH(NULL, dm); + BKE_object_free_display(ob); +} + +void sculpt_update_after_dynamic_topology_toggle(bContext *C) +{ + Scene *scene = CTX_data_scene(C); + Object *ob = CTX_data_active_object(C); + Sculpt *sd = scene->toolsettings->sculpt; + + /* Create the PBVH */ + sculpt_update_mesh_elements(scene, sd, ob, FALSE, FALSE); + WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, ob); +} + +void sculpt_dynamic_topology_enable(bContext *C) +{ + Scene *scene = CTX_data_scene(C); + Object *ob = CTX_data_active_object(C); + SculptSession *ss = ob->sculpt; + Mesh *me = ob->data; + + sculpt_pbvh_clear(ob); + + ss->bm_smooth_shading = (scene->toolsettings->sculpt->flags & + SCULPT_DYNTOPO_SMOOTH_SHADING); + + /* Create triangles-only BMesh */ + ss->bm = BM_mesh_create(&bm_mesh_allocsize_default); + + BM_mesh_bm_from_me(ss->bm, me, TRUE, ob->shapenr); + sculpt_dynamic_topology_triangulate(ss->bm); + BM_data_layer_add(ss->bm, &ss->bm->vdata, CD_PAINT_MASK); + BM_mesh_normals_update(ss->bm, TRUE); + + /* Enable dynamic topology */ + me->flag |= ME_SCULPT_DYNAMIC_TOPOLOGY; + + /* Enable logging for undo/redo */ + ss->bm_log = BM_log_create(ss->bm); + + /* Refresh */ + sculpt_update_after_dynamic_topology_toggle(C); +} + +/* Free the sculpt BMesh and BMLog + * + * If 'unode' is given, the BMesh's data is copied out to the unode + * before the BMesh is deleted so that it can be restored from */ +void sculpt_dynamic_topology_disable(bContext *C, + SculptUndoNode *unode) +{ + Object *ob = CTX_data_active_object(C); + SculptSession *ss = ob->sculpt; + Mesh *me = ob->data; + + sculpt_pbvh_clear(ob); + + if (unode) { + /* Free all existing custom data */ + CustomData_free(&me->vdata, me->totvert); + CustomData_free(&me->edata, me->totedge); + CustomData_free(&me->fdata, me->totface); + CustomData_free(&me->ldata, me->totloop); + CustomData_free(&me->pdata, me->totpoly); + + /* Copy over stored custom data */ + me->totvert = unode->bm_enter_totvert; + me->totloop = unode->bm_enter_totloop; + me->totpoly = unode->bm_enter_totpoly; + me->totedge = unode->bm_enter_totedge; + me->totface = 0; + CustomData_copy(&unode->bm_enter_vdata, &me->vdata, CD_MASK_MESH, + CD_DUPLICATE, unode->bm_enter_totvert); + CustomData_copy(&unode->bm_enter_edata, &me->edata, CD_MASK_MESH, + CD_DUPLICATE, unode->bm_enter_totedge); + CustomData_copy(&unode->bm_enter_ldata, &me->ldata, CD_MASK_MESH, + CD_DUPLICATE, unode->bm_enter_totloop); + CustomData_copy(&unode->bm_enter_pdata, &me->pdata, CD_MASK_MESH, + CD_DUPLICATE, unode->bm_enter_totpoly); + + mesh_update_customdata_pointers(me, FALSE); + } else { + sculptsession_bm_to_me(ob, TRUE); + } + + BM_mesh_free(ss->bm); + + /* Clear data */ + me->flag &= ~ME_SCULPT_DYNAMIC_TOPOLOGY; + ss->bm = NULL; + BM_log_free(ss->bm_log); + ss->bm_log = NULL; + + /* Refresh */ + sculpt_update_after_dynamic_topology_toggle(C); +} + +static int sculpt_dynamic_topology_toggle_exec(bContext *C, wmOperator *UNUSED(op)) +{ + Object *ob = CTX_data_active_object(C); + SculptSession *ss = ob->sculpt; + + if (ss->bm) { + sculpt_undo_push_begin("Dynamic topology disable"); + sculpt_undo_push_node(ob, NULL, SCULPT_UNDO_DYNTOPO_END); + sculpt_dynamic_topology_disable(C, NULL); + } + else { + sculpt_undo_push_begin("Dynamic topology enable"); + sculpt_dynamic_topology_enable(C); + sculpt_undo_push_node(ob, NULL, SCULPT_UNDO_DYNTOPO_BEGIN); + } + sculpt_undo_push_end(); + + return OPERATOR_FINISHED; +} + +static int sculpt_dynamic_topology_toggle_invoke(bContext *C, wmOperator *op, + wmEvent *UNUSED(event)) +{ + Object *ob = CTX_data_active_object(C); + Mesh *me = ob->data; + SculptSession *ss = ob->sculpt; + const char *msg = "Dynamic-topology sculpting will not preserve" + "vertex colors, UVs, or other customdata"; + + if (!ss->bm) { + int i; + + for (i = 0; i < CD_NUMTYPES; i++) { + if (!ELEM7(i, CD_MVERT, CD_MEDGE, CD_MFACE, + CD_MLOOP, CD_MPOLY, CD_PAINT_MASK, + CD_ORIGINDEX) && + (CustomData_has_layer(&me->vdata, i) || + CustomData_has_layer(&me->edata, i) || + CustomData_has_layer(&me->fdata, i))) { + /* The mesh has customdata that will be lost, let the + * user confirm this is OK */ + return WM_operator_confirm_message(C, op, msg); + } + } + } + + return sculpt_dynamic_topology_toggle_exec(C, op); +} + +static void SCULPT_OT_dynamic_topology_toggle(wmOperatorType *ot) +{ + /* identifiers */ + ot->name = "Dynamic Topology Toggle"; + ot->idname = "SCULPT_OT_dynamic_topology_toggle"; + ot->description = "Dynamic topology alters the mesh topology while sculpting"; + + /* api callbacks */ + ot->invoke = sculpt_dynamic_topology_toggle_invoke; + ot->exec = sculpt_dynamic_topology_toggle_exec; + ot->poll = sculpt_mode_poll; + + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; +} + +/************************* SCULPT_OT_optimize *************************/ + +static int sculpt_optimize_exec(bContext *C, wmOperator *UNUSED(op)) +{ + Object *ob = CTX_data_active_object(C); + + sculpt_pbvh_clear(ob); + WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, ob); + + return OPERATOR_FINISHED; +} + +static int sculpt_and_dynamic_topology_poll(bContext *C) +{ + Object *ob = CTX_data_active_object(C); + + return sculpt_mode_poll(C) && ob->sculpt->bm; +} + +/* The BVH gets less optimal more quickly with dynamic topology than + * regular sculpting. There is no doubt more clever stuff we can do to + * optimize it on the fly, but for now this gives the user a nicer way + * to recalculate it than toggling modes. */ +static void SCULPT_OT_optimize(wmOperatorType *ot) +{ + /* identifiers */ + ot->name = "Optimize"; + ot->idname = "SCULPT_OT_optimize"; + ot->description = "Recalculate the sculpt BVH to improve performance"; + + /* api callbacks */ + ot->exec = sculpt_optimize_exec; + ot->poll = sculpt_and_dynamic_topology_poll; + + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; +} + +/********************* Dynamic topology symmetrize ********************/ + +static int sculpt_symmetrize_exec(bContext *C, wmOperator *UNUSED(op)) +{ + Object *ob = CTX_data_active_object(C); + const Sculpt *sd = CTX_data_tool_settings(C)->sculpt; + SculptSession *ss = ob->sculpt; + + /* To simplify undo for symmetrize, all BMesh elements are logged + * as deleted, then after symmetrize operation all BMesh elements + * are logged as added (as opposed to attempting to store just the + * parts that symmetrize modifies) */ + sculpt_undo_push_begin("Dynamic topology symmetrize"); + sculpt_undo_push_node(ob, NULL, SCULPT_UNDO_DYNTOPO_SYMMETRIZE); + BM_log_before_all_removed(ss->bm, ss->bm_log); + + /* Symmetrize and re-triangulate */ + BMO_op_callf(ss->bm, BMO_FLAG_DEFAULTS, + "symmetrize input=%avef direction=%i", + sd->symmetrize_direction); + sculpt_dynamic_topology_triangulate(ss->bm); + + /* Finish undo */ + BM_log_all_added(ss->bm, ss->bm_log); + sculpt_undo_push_end(); + + /* Redraw */ + sculpt_pbvh_clear(ob); + WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, ob); + + return OPERATOR_FINISHED; +} + +static void SCULPT_OT_symmetrize(wmOperatorType *ot) +{ + /* identifiers */ + ot->name = "Symmetrize"; + ot->idname = "SCULPT_OT_symmetrize"; + + /* api callbacks */ + ot->exec = sculpt_symmetrize_exec; + ot->poll = sculpt_and_dynamic_topology_poll; +} + /**** Toggle operator for turning sculpt mode on or off ****/ static void sculpt_init_session(Scene *scene, Object *ob) @@ -4222,6 +4831,7 @@ static int sculpt_toggle_mode(bContext *C, wmOperator *UNUSED(op)) Scene *scene = CTX_data_scene(C); ToolSettings *ts = CTX_data_tool_settings(C); Object *ob = CTX_data_active_object(C); + Mesh *me = ob->data; MultiresModifierData *mmd = sculpt_multires_active(scene, ob); int flush_recalc = 0; @@ -4234,9 +4844,16 @@ static int sculpt_toggle_mode(bContext *C, wmOperator *UNUSED(op)) if (mmd) multires_force_update(ob); - if (flush_recalc) + if (flush_recalc || (ob->sculpt && ob->sculpt->bm)) DAG_id_tag_update(&ob->id, OB_RECALC_DATA); + if (me->flag & ME_SCULPT_DYNAMIC_TOPOLOGY) { + /* Dynamic topology must be disabled before exiting sculpt + * mode to ensure the undo stack stays in a consistent + * state */ + sculpt_dynamic_topology_toggle_exec(C, NULL); + } + /* Leave sculptmode */ ob->mode &= ~OB_MODE_SCULPT; @@ -4257,6 +4874,9 @@ static int sculpt_toggle_mode(bContext *C, wmOperator *UNUSED(op)) ts->sculpt->flags |= SCULPT_SYMM_X; } + if (!ts->sculpt->detail_size) + ts->sculpt->detail_size = 30; + /* Create sculpt mode session data */ if (ob->sculpt) free_sculptsession(ob); @@ -4271,7 +4891,7 @@ static int sculpt_toggle_mode(bContext *C, wmOperator *UNUSED(op)) } BKE_paint_init(&ts->sculpt->paint, PAINT_CURSOR_SCULPT); - + paint_cursor_start(C, sculpt_poll); } @@ -4299,4 +4919,7 @@ void ED_operatortypes_sculpt(void) WM_operatortype_append(SCULPT_OT_brush_stroke); WM_operatortype_append(SCULPT_OT_sculptmode_toggle); WM_operatortype_append(SCULPT_OT_set_persistent_base); + WM_operatortype_append(SCULPT_OT_dynamic_topology_toggle); + WM_operatortype_append(SCULPT_OT_optimize); + WM_operatortype_append(SCULPT_OT_symmetrize); } |