From fb6a0d24e1078574135ca1d083c2b933191d9bda Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Sun, 19 Apr 2015 18:22:25 +1000 Subject: Dyntopo: support for original normal access Rename calc_flatten_center to calc_area_center, since theres no 'flatten' spesific logic there. Also refactor calc_area_center, calc_area_normal, calc_area_normal_and_center so they're next to eachother - they're almost the same, having them scattered about isn't helpful. --- source/blender/editors/sculpt_paint/sculpt.c | 1037 ++++++++++++++------------ 1 file changed, 549 insertions(+), 488 deletions(-) (limited to 'source/blender/editors/sculpt_paint/sculpt.c') diff --git a/source/blender/editors/sculpt_paint/sculpt.c b/source/blender/editors/sculpt_paint/sculpt.c index a08ea2ba60e..4e3d03f916f 100644 --- a/source/blender/editors/sculpt_paint/sculpt.c +++ b/source/blender/editors/sculpt_paint/sculpt.c @@ -729,6 +729,429 @@ static float calc_symmetry_feather(Sculpt *sd, StrokeCache *cache) } } +/** \name Calculate Normal and Center + * + * Calculate geometry surrounding the brush center. + * (optionally using original coordinates). + * + * Functions are: + * - #calc_area_center + * - #calc_area_normal + * - #calc_area_normal_and_center + * + * \note These are all _very_ similar, when changing one, check others. + * \{ */ + +static void calc_area_center( + Sculpt *sd, Object *ob, + PBVHNode **nodes, int totnode, + float r_area_co[3]) +{ + SculptSession *ss = ob->sculpt; + int n; + + /* 0=towards view, 1=flipped */ + float area_co[2][3] = {{0.0f}}; + + int count[2] = {0}; + + (void)sd; /* unused w/o openmp */ + +#pragma omp parallel for schedule(guided) if ((sd->flags & SCULPT_USE_OPENMP) && totnode > SCULPT_OMP_LIMIT) + for (n = 0; n < totnode; n++) { + PBVHVertexIter vd; + SculptBrushTest test; + SculptUndoNode *unode; + float private_co[2][3] = {{0.0f}}; + int private_count[2] = {0}; + bool use_original; + + unode = sculpt_undo_push_node(ob, nodes[n], SCULPT_UNDO_COORDS); + sculpt_brush_test_init(ss, &test); + + use_original = (ss->cache->original && (unode->co || unode->bm_entry)); + + /* when the mesh is edited we can't rely on original coords + * (original mesh may not even have verts in brush radius) */ + if (use_original && unode->bm_entry) { + float (*orco_coords)[3]; + int (*orco_tris)[3]; + int orco_tris_num; + int i; + + BKE_pbvh_node_get_bm_orco_data( + nodes[n], + &orco_tris, &orco_tris_num, &orco_coords); + + for (i = 0; i < orco_tris_num; i++) { + const float *co_tri[3] = { + orco_coords[orco_tris[i][0]], + orco_coords[orco_tris[i][1]], + orco_coords[orco_tris[i][2]], + }; + float co[3]; + + closest_on_tri_to_point_v3(co, test.location, UNPACK3(co_tri)); + + if (sculpt_brush_test_fast(&test, co)) { + float no[3]; + int flip_index; + + cross_tri_v3(no, UNPACK3(co_tri)); + + flip_index = (dot_v3v3(ss->cache->view_normal, no) <= 0.0f); + add_v3_v3(private_co[flip_index], co); + private_count[flip_index] += 1; + } + } + } + else { + BKE_pbvh_vertex_iter_begin(ss->pbvh, nodes[n], vd, PBVH_ITER_UNIQUE) + { + const float *co; + + if (use_original) { + co = unode->co[vd.i]; + } + else { + co = vd.co; + } + + if (sculpt_brush_test_fast(&test, co)) { + float no_buf[3]; + const float *no; + int flip_index; + + if (use_original) { + normal_short_to_float_v3(no_buf, unode->no[vd.i]); + no = no_buf; + } + else { + if (vd.no) { + normal_short_to_float_v3(no_buf, vd.no); + no = no_buf; + } + else { + no = vd.fno; + } + } + + flip_index = (dot_v3v3(ss->cache->view_normal, no) <= 0.0f); + add_v3_v3(private_co[flip_index], co); + private_count[flip_index] += 1; + } + } + BKE_pbvh_vertex_iter_end; + } + +#pragma omp critical + { + /* for flatten center */ + add_v3_v3(area_co[0], private_co[0]); + add_v3_v3(area_co[1], private_co[1]); + + /* weights */ + count[0] += private_count[0]; + count[1] += private_count[1]; + } + } + + /* for flatten center */ + for (n = 0; n < ARRAY_SIZE(area_co); n++) { + if (count[n] != 0) { + mul_v3_v3fl(r_area_co, area_co[n], 1.0f / count[n]); + break; + } + } + if (n == 2) { + zero_v3(r_area_co); + } +} + + +static void calc_area_normal( + Sculpt *sd, Object *ob, + PBVHNode **nodes, int totnode, + float r_area_no[3]) +{ + const Brush *brush = BKE_paint_brush(&sd->paint); + SculptSession *ss = ob->sculpt; + int n; + + /* 0=towards view, 1=flipped */ + float area_no[2][3] = {{0.0f}}; + + int count[2] = {0}; + + /* Grab brush requires to test on original data (see T25371) */ + bool original; + + original = (brush->sculpt_tool == SCULPT_TOOL_GRAB) ? true : ss->cache->original; + /* In general the original coords are not available with dynamic + * topology + * + * Mask tool could not use undo nodes to get coordinates from + * since the coordinates are not stored in those nodes. + * And mask tool is not gonna to modify vertex coordinates, + * so we don't actually need to use modified coords. + */ + if (brush->sculpt_tool == SCULPT_TOOL_MASK) { + original = false; + } + +#pragma omp parallel for schedule(guided) if ((sd->flags & SCULPT_USE_OPENMP) && totnode > SCULPT_OMP_LIMIT) + for (n = 0; n < totnode; n++) { + PBVHVertexIter vd; + SculptBrushTest test; + SculptUndoNode *unode; + float private_no[2][3] = {{0.0f}}; + int private_count[2] = {0}; + bool use_original; + + unode = sculpt_undo_push_node(ob, nodes[n], SCULPT_UNDO_COORDS); + sculpt_brush_test_init(ss, &test); + + use_original = (original && (unode->co || unode->bm_entry)); + + /* when the mesh is edited we can't rely on original coords + * (original mesh may not even have verts in brush radius) */ + if (use_original && unode->bm_entry) { + float (*orco_coords)[3]; + int (*orco_tris)[3]; + int orco_tris_num; + int i; + + BKE_pbvh_node_get_bm_orco_data( + nodes[n], + &orco_tris, &orco_tris_num, &orco_coords); + + for (i = 0; i < orco_tris_num; i++) { + const float *co_tri[3] = { + orco_coords[orco_tris[i][0]], + orco_coords[orco_tris[i][1]], + orco_coords[orco_tris[i][2]], + }; + float co[3]; + + closest_on_tri_to_point_v3(co, test.location, UNPACK3(co_tri)); + + if (sculpt_brush_test_fast(&test, co)) { + float no[3]; + int flip_index; + + normal_tri_v3(no, UNPACK3(co_tri)); + + flip_index = (dot_v3v3(ss->cache->view_normal, no) <= 0.0f); + add_v3_v3(private_no[flip_index], no); + private_count[flip_index] += 1; + } + } + } + else { + BKE_pbvh_vertex_iter_begin(ss->pbvh, nodes[n], vd, PBVH_ITER_UNIQUE) + { + const float *co; + + if (use_original) { + co = unode->co[vd.i]; + } + else { + co = vd.co; + } + + if (sculpt_brush_test_fast(&test, co)) { + float no_buf[3]; + const float *no; + int flip_index; + + if (use_original) { + normal_short_to_float_v3(no_buf, unode->no[vd.i]); + no = no_buf; + } + else { + if (vd.no) { + normal_short_to_float_v3(no_buf, vd.no); + no = no_buf; + } + else { + no = vd.fno; + } + } + + flip_index = (dot_v3v3(ss->cache->view_normal, no) <= 0.0f); + add_v3_v3(private_no[flip_index], no); + private_count[flip_index] += 1; + } + } + BKE_pbvh_vertex_iter_end; + } + +#pragma omp critical + { + /* for area normal */ + add_v3_v3(area_no[0], private_no[0]); + add_v3_v3(area_no[1], private_no[1]); + + /* weights */ + count[0] += private_count[0]; + count[1] += private_count[1]; + } + } + + /* for area normal */ + for (n = 0; n < ARRAY_SIZE(area_no); n++) { + if (normalize_v3_v3(r_area_no, area_no[n]) != 0.0f) { + break; + } + } +} + +/* this calculates flatten center and area normal together, + * amortizing the memory bandwidth and loop overhead to calculate both at the same time */ +static void calc_area_normal_and_center( + Sculpt *sd, Object *ob, + PBVHNode **nodes, int totnode, + float r_area_no[3], float r_area_co[3]) +{ + SculptSession *ss = ob->sculpt; + int n; + + /* 0=towards view, 1=flipped */ + float area_co[2][3] = {{0.0f}}; + float area_no[2][3] = {{0.0f}}; + + int count[2] = {0}; + + (void)sd; /* unused w/o openmp */ + +#pragma omp parallel for schedule(guided) if ((sd->flags & SCULPT_USE_OPENMP) && totnode > SCULPT_OMP_LIMIT) + for (n = 0; n < totnode; n++) { + PBVHVertexIter vd; + SculptBrushTest test; + SculptUndoNode *unode; + float private_co[2][3] = {{0.0f}}; + float private_no[2][3] = {{0.0f}}; + int private_count[2] = {0}; + bool use_original; + + unode = sculpt_undo_push_node(ob, nodes[n], SCULPT_UNDO_COORDS); + sculpt_brush_test_init(ss, &test); + + use_original = (ss->cache->original && (unode->co || unode->bm_entry)); + + /* when the mesh is edited we can't rely on original coords + * (original mesh may not even have verts in brush radius) */ + if (use_original && unode->bm_entry) { + float (*orco_coords)[3]; + int (*orco_tris)[3]; + int orco_tris_num; + int i; + + BKE_pbvh_node_get_bm_orco_data( + nodes[n], + &orco_tris, &orco_tris_num, &orco_coords); + + for (i = 0; i < orco_tris_num; i++) { + const float *co_tri[3] = { + orco_coords[orco_tris[i][0]], + orco_coords[orco_tris[i][1]], + orco_coords[orco_tris[i][2]], + }; + float co[3]; + + closest_on_tri_to_point_v3(co, test.location, UNPACK3(co_tri)); + + if (sculpt_brush_test_fast(&test, co)) { + float no[3]; + int flip_index; + + normal_tri_v3(no, UNPACK3(co_tri)); + + flip_index = (dot_v3v3(ss->cache->view_normal, no) <= 0.0f); + add_v3_v3(private_co[flip_index], co); + add_v3_v3(private_no[flip_index], no); + private_count[flip_index] += 1; + } + } + } + else { + BKE_pbvh_vertex_iter_begin(ss->pbvh, nodes[n], vd, PBVH_ITER_UNIQUE) + { + const float *co; + + if (use_original) { + co = unode->co[vd.i]; + } + else { + co = vd.co; + } + + if (sculpt_brush_test_fast(&test, co)) { + float no_buf[3]; + const float *no; + int flip_index; + + if (use_original) { + normal_short_to_float_v3(no_buf, unode->no[vd.i]); + no = no_buf; + } + else { + if (vd.no) { + normal_short_to_float_v3(no_buf, vd.no); + no = no_buf; + } + else { + no = vd.fno; + } + } + + flip_index = (dot_v3v3(ss->cache->view_normal, no) <= 0.0f); + add_v3_v3(private_co[flip_index], co); + add_v3_v3(private_no[flip_index], no); + private_count[flip_index] += 1; + } + } + BKE_pbvh_vertex_iter_end; + } + +#pragma omp critical + { + /* for flatten center */ + add_v3_v3(area_co[0], private_co[0]); + add_v3_v3(area_co[1], private_co[1]); + + /* for area normal */ + add_v3_v3(area_no[0], private_no[0]); + add_v3_v3(area_no[1], private_no[1]); + + /* weights */ + count[0] += private_count[0]; + count[1] += private_count[1]; + } + } + + /* for flatten center */ + for (n = 0; n < ARRAY_SIZE(area_co); n++) { + if (count[n] != 0) { + mul_v3_v3fl(r_area_co, area_co[n], 1.0f / count[n]); + break; + } + } + if (n == 2) { + zero_v3(r_area_co); + } + + /* for area normal */ + for (n = 0; n < ARRAY_SIZE(area_no); n++) { + if (normalize_v3_v3(r_area_no, area_no[n]) != 0.0f) { + break; + } + } +} + +/** \} */ + + /* Return modified brush strength. Includes the direction of the brush, positive * values pull vertices, negative values push. Uses tablet pressure and a * special multiplier found experimentally to scale the strength factor. */ @@ -928,123 +1351,30 @@ static bool sculpt_search_sphere_cb(PBVHNode *node, void *data_v) if (bb_min[i] > center[i]) nearest[i] = bb_min[i]; else if (bb_max[i] < center[i]) - nearest[i] = bb_max[i]; - else - nearest[i] = center[i]; - } - - sub_v3_v3v3(t, center, nearest); - - return len_squared_v3(t) < data->radius_squared; -} - -/* Handles clipping against a mirror modifier and SCULPT_LOCK axis flags */ -static void sculpt_clip(Sculpt *sd, SculptSession *ss, float co[3], const float val[3]) -{ - int i; - - for (i = 0; i < 3; ++i) { - if (sd->flags & (SCULPT_LOCK_X << i)) - continue; - - if ((ss->cache->flag & (CLIP_X << i)) && (fabsf(co[i]) <= ss->cache->clip_tolerance[i])) - co[i] = 0.0f; - else - co[i] = val[i]; - } -} - -static void add_norm_if(float view_vec[3], float out[3], float out_flip[3], float fno[3]) -{ - if ((dot_v3v3(view_vec, fno)) > 0) { - add_v3_v3(out, fno); - } - else { - add_v3_v3(out_flip, fno); /* out_flip is used when out is {0,0,0} */ - } -} - -static void calc_area_normal(Sculpt *sd, Object *ob, float an[3], PBVHNode **nodes, int totnode) -{ - float out_flip[3] = {0.0f, 0.0f, 0.0f}; - - SculptSession *ss = ob->sculpt; - const Brush *brush = BKE_paint_brush(&sd->paint); - int n; - bool original; - - /* Grab brush requires to test on original data (see r33888 and - * bug #25371) */ - original = (BKE_paint_brush(&sd->paint)->sculpt_tool == SCULPT_TOOL_GRAB ? - true : ss->cache->original); - - /* In general the original coords are not available with dynamic - * topology - * - * Mask tool could not use undo nodes to get coordinates from - * since the coordinates are not stored in those odes. - * And mask tool is not gonna to modify vertex coordinates, - * so we don't actually need to use modified coords. - */ - if (ss->bm || brush->sculpt_tool == SCULPT_TOOL_MASK) - original = false; - - (void)sd; /* unused w/o openmp */ - - zero_v3(an); - -#pragma omp parallel for schedule(guided) if ((sd->flags & SCULPT_USE_OPENMP) && totnode > SCULPT_OMP_LIMIT) - for (n = 0; n < totnode; n++) { - PBVHVertexIter vd; - SculptBrushTest test; - SculptUndoNode *unode; - float private_an[3] = {0.0f, 0.0f, 0.0f}; - float private_out_flip[3] = {0.0f, 0.0f, 0.0f}; - - unode = sculpt_undo_push_node(ob, nodes[n], SCULPT_UNDO_COORDS); - sculpt_brush_test_init(ss, &test); + nearest[i] = bb_max[i]; + else + nearest[i] = center[i]; + } + + sub_v3_v3v3(t, center, nearest); - if (original) { - 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]; + return len_squared_v3(t) < data->radius_squared; +} - normal_short_to_float_v3(fno, unode->no[vd.i]); - add_norm_if(ss->cache->view_normal, private_an, private_out_flip, fno); - } - } - BKE_pbvh_vertex_iter_end; - } - else { - BKE_pbvh_vertex_iter_begin(ss->pbvh, nodes[n], vd, PBVH_ITER_UNIQUE) - { - if (sculpt_brush_test_fast(&test, vd.co)) { - if (vd.no) { - float fno[3]; +/* Handles clipping against a mirror modifier and SCULPT_LOCK axis flags */ +static void sculpt_clip(Sculpt *sd, SculptSession *ss, float co[3], const float val[3]) +{ + int i; - normal_short_to_float_v3(fno, vd.no); - add_norm_if(ss->cache->view_normal, private_an, private_out_flip, fno); - } - else { - add_norm_if(ss->cache->view_normal, private_an, private_out_flip, vd.fno); - } - } - } - BKE_pbvh_vertex_iter_end; - } + for (i = 0; i < 3; ++i) { + if (sd->flags & (SCULPT_LOCK_X << i)) + continue; -#pragma omp critical - { - add_v3_v3(an, private_an); - add_v3_v3(out_flip, private_out_flip); - } + if ((ss->cache->flag & (CLIP_X << i)) && (fabsf(co[i]) <= ss->cache->clip_tolerance[i])) + co[i] = 0.0f; + else + co[i] = val[i]; } - - if (is_zero_v3(an)) - copy_v3_v3(an, out_flip); - - normalize_v3(an); } /* Calculate primary direction of movement for many brushes */ @@ -1079,7 +1409,7 @@ static void calc_sculpt_normal(Sculpt *sd, Object *ob, break; case SCULPT_DISP_DIR_AREA: - calc_area_normal(sd, ob, an, nodes, totnode); + calc_area_normal(sd, ob, nodes, totnode, an); break; default: @@ -2014,422 +2344,153 @@ static void do_rotate_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnod Brush *brush = BKE_paint_brush(&sd->paint); float bstrength = ss->cache->bstrength; int n; - static const int flip[8] = { 1, -1, -1, 1, -1, 1, 1, -1 }; - float angle = ss->cache->vertex_rotation * flip[ss->cache->mirror_symmetry_pass]; - -#pragma omp parallel for schedule(guided) if ((sd->flags & SCULPT_USE_OPENMP) && totnode > SCULPT_OMP_LIMIT) - for (n = 0; n < totnode; n++) { - PBVHVertexIter vd; - SculptBrushTest test; - SculptOrigVertData orig_data; - float (*proxy)[3]; - - sculpt_orig_vert_data_init(&orig_data, ob, nodes[n]); - - proxy = BKE_pbvh_node_add_proxy(ss->pbvh, nodes[n])->co; - - sculpt_brush_test_init(ss, &test); - - BKE_pbvh_vertex_iter_begin(ss->pbvh, nodes[n], vd, PBVH_ITER_UNIQUE) - { - sculpt_orig_vert_data_update(&orig_data, &vd); - - if (sculpt_brush_test(&test, orig_data.co)) { - float vec[3], rot[3][3]; - const float fade = bstrength * tex_strength(ss, brush, - orig_data.co, - test.dist, - orig_data.no, - NULL, vd.mask ? *vd.mask : 0.0f); - - sub_v3_v3v3(vec, orig_data.co, ss->cache->location); - axis_angle_normalized_to_mat3(rot, ss->cache->sculpt_normal_symm, angle * fade); - mul_v3_m3v3(proxy[vd.i], rot, vec); - add_v3_v3(proxy[vd.i], ss->cache->location); - sub_v3_v3(proxy[vd.i], orig_data.co); - - if (vd.mvert) - vd.mvert->flag |= ME_VERT_PBVH_UPDATE; - } - } - BKE_pbvh_vertex_iter_end; - } -} - -static void do_layer_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnode) -{ - SculptSession *ss = ob->sculpt; - Brush *brush = BKE_paint_brush(&sd->paint); - float bstrength = ss->cache->bstrength; - float offset[3]; - float lim = brush->height; - int n; - - if (bstrength < 0) - lim = -lim; - - mul_v3_v3v3(offset, ss->cache->scale, ss->cache->sculpt_normal_symm); - -#pragma omp parallel for schedule(guided) if ((sd->flags & SCULPT_USE_OPENMP) && totnode > SCULPT_OMP_LIMIT) - for (n = 0; n < totnode; n++) { - PBVHVertexIter vd; - SculptBrushTest test; - SculptOrigVertData orig_data; - float *layer_disp; - /* XXX: layer brush needs conversion to proxy but its more complicated */ - /* proxy = BKE_pbvh_node_add_proxy(ss->pbvh, nodes[n])->co; */ - - 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); - - BKE_pbvh_vertex_iter_begin(ss->pbvh, nodes[n], vd, PBVH_ITER_UNIQUE) - { - 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, - vd.no, vd.fno, vd.mask ? *vd.mask : 0.0f); - float *disp = &layer_disp[vd.i]; - float val[3]; - - *disp += fade; - - /* Don't let the displacement go past the limit */ - if ((lim < 0 && *disp < lim) || (lim >= 0 && *disp > lim)) - *disp = lim; - - mul_v3_v3fl(val, offset, *disp); - - if (!ss->multires && !ss->bm && ss->layer_co && (brush->flag & BRUSH_PERSISTENT)) { - int index = vd.vert_indices[vd.i]; - - /* persistent base */ - add_v3_v3(val, ss->layer_co[index]); - } - else { - add_v3_v3(val, orig_data.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_inflate_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnode) -{ - SculptSession *ss = ob->sculpt; - Brush *brush = BKE_paint_brush(&sd->paint); - float bstrength = ss->cache->bstrength; - int n; - -#pragma omp parallel for schedule(guided) if ((sd->flags & SCULPT_USE_OPENMP) && totnode > SCULPT_OMP_LIMIT) - for (n = 0; n < totnode; n++) { - PBVHVertexIter vd; - SculptBrushTest test; - float (*proxy)[3]; - - proxy = BKE_pbvh_node_add_proxy(ss->pbvh, nodes[n])->co; - - sculpt_brush_test_init(ss, &test); - - 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, - vd.no, vd.fno, vd.mask ? *vd.mask : 0.0f); - float val[3]; - - if (vd.fno) copy_v3_v3(val, vd.fno); - else normal_short_to_float_v3(val, vd.no); - - mul_v3_fl(val, fade * ss->cache->radius); - mul_v3_v3v3(proxy[vd.i], val, ss->cache->scale); - - if (vd.mvert) - vd.mvert->flag |= ME_VERT_PBVH_UPDATE; - } - } - BKE_pbvh_vertex_iter_end; - } -} - -static void calc_flatten_center( - Sculpt *sd, Object *ob, - PBVHNode **nodes, int totnode, - float r_area_co[3]) -{ - SculptSession *ss = ob->sculpt; - int n; - - /* 0=towards view, 1=flipped */ - float area_co[2][3] = {{0.0f}}; - - int count[2] = {0}; - - (void)sd; /* unused w/o openmp */ - -#pragma omp parallel for schedule(guided) if ((sd->flags & SCULPT_USE_OPENMP) && totnode > SCULPT_OMP_LIMIT) - for (n = 0; n < totnode; n++) { - PBVHVertexIter vd; - SculptBrushTest test; - SculptUndoNode *unode; - float private_co[2][3] = {{0.0f}}; - int private_count[2] = {0}; - bool use_original; - - unode = sculpt_undo_push_node(ob, nodes[n], SCULPT_UNDO_COORDS); - sculpt_brush_test_init(ss, &test); - - use_original = (ss->cache->original && (unode->co || unode->bm_entry)); - - /* when the mesh is edited we can't rely on original coords - * (original mesh may not even have verts in brush radius) */ - if (use_original && unode->bm_entry) { - float (*orco_coords)[3]; - int (*orco_tris)[3]; - int orco_tris_num; - int i; - - BKE_pbvh_node_get_bm_orco_data( - nodes[n], - &orco_tris, &orco_tris_num, &orco_coords); - - for (i = 0; i < orco_tris_num; i++) { - const float *co_tri[3] = { - orco_coords[orco_tris[i][0]], - orco_coords[orco_tris[i][1]], - orco_coords[orco_tris[i][2]], - }; - float co[3]; - - closest_on_tri_to_point_v3(co, test.location, UNPACK3(co_tri)); - - if (sculpt_brush_test_fast(&test, co)) { - float no[3]; - int flip_index; - - cross_tri_v3(no, UNPACK3(co_tri)); - - flip_index = (dot_v3v3(ss->cache->view_normal, no) <= 0.0f); - add_v3_v3(private_co[flip_index], co); - private_count[flip_index] += 1; - } - } - } - else { - BKE_pbvh_vertex_iter_begin(ss->pbvh, nodes[n], vd, PBVH_ITER_UNIQUE) - { - const float *co; + static const int flip[8] = { 1, -1, -1, 1, -1, 1, 1, -1 }; + float angle = ss->cache->vertex_rotation * flip[ss->cache->mirror_symmetry_pass]; - if (use_original) { - co = unode->co[vd.i]; - } - else { - co = vd.co; - } +#pragma omp parallel for schedule(guided) if ((sd->flags & SCULPT_USE_OPENMP) && totnode > SCULPT_OMP_LIMIT) + for (n = 0; n < totnode; n++) { + PBVHVertexIter vd; + SculptBrushTest test; + SculptOrigVertData orig_data; + float (*proxy)[3]; - if (sculpt_brush_test_fast(&test, co)) { - float no_buf[3]; - const float *no; - int flip_index; + sculpt_orig_vert_data_init(&orig_data, ob, nodes[n]); - if (use_original) { - normal_short_to_float_v3(no_buf, unode->no[vd.i]); - no = no_buf; - } - else { - if (vd.no) { - normal_short_to_float_v3(no_buf, vd.no); - no = no_buf; - } - else { - no = vd.fno; - } - } + proxy = BKE_pbvh_node_add_proxy(ss->pbvh, nodes[n])->co; - flip_index = (dot_v3v3(ss->cache->view_normal, no) <= 0.0f); - add_v3_v3(private_co[flip_index], co); - private_count[flip_index] += 1; - } - } - BKE_pbvh_vertex_iter_end; - } + sculpt_brush_test_init(ss, &test); -#pragma omp critical + BKE_pbvh_vertex_iter_begin(ss->pbvh, nodes[n], vd, PBVH_ITER_UNIQUE) { - /* for flatten center */ - add_v3_v3(area_co[0], private_co[0]); - add_v3_v3(area_co[1], private_co[1]); + sculpt_orig_vert_data_update(&orig_data, &vd); - /* weights */ - count[0] += private_count[0]; - count[1] += private_count[1]; - } - } + if (sculpt_brush_test(&test, orig_data.co)) { + float vec[3], rot[3][3]; + const float fade = bstrength * tex_strength(ss, brush, + orig_data.co, + test.dist, + orig_data.no, + NULL, vd.mask ? *vd.mask : 0.0f); - /* for flatten center */ - for (n = 0; n < ARRAY_SIZE(area_co); n++) { - if (count[n] != 0) { - mul_v3_v3fl(r_area_co, area_co[n], 1.0f / count[n]); - break; + sub_v3_v3v3(vec, orig_data.co, ss->cache->location); + axis_angle_normalized_to_mat3(rot, ss->cache->sculpt_normal_symm, angle * fade); + mul_v3_m3v3(proxy[vd.i], rot, vec); + add_v3_v3(proxy[vd.i], ss->cache->location); + sub_v3_v3(proxy[vd.i], orig_data.co); + + if (vd.mvert) + vd.mvert->flag |= ME_VERT_PBVH_UPDATE; + } } - } - if (n == 2) { - zero_v3(r_area_co); + BKE_pbvh_vertex_iter_end; } } -/* this calculates flatten center and area normal together, - * amortizing the memory bandwidth and loop overhead to calculate both at the same time */ -static void calc_area_normal_and_flatten_center( - Sculpt *sd, Object *ob, - PBVHNode **nodes, int totnode, - float r_area_no[3], float r_area_co[3]) +static void do_layer_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnode) { SculptSession *ss = ob->sculpt; + Brush *brush = BKE_paint_brush(&sd->paint); + float bstrength = ss->cache->bstrength; + float offset[3]; + float lim = brush->height; int n; - /* 0=towards view, 1=flipped */ - float area_co[2][3] = {{0.0f}}; - float area_no[2][3] = {{0.0f}}; - - int count[2] = {0}; + if (bstrength < 0) + lim = -lim; - (void)sd; /* unused w/o openmp */ + mul_v3_v3v3(offset, ss->cache->scale, ss->cache->sculpt_normal_symm); #pragma omp parallel for schedule(guided) if ((sd->flags & SCULPT_USE_OPENMP) && totnode > SCULPT_OMP_LIMIT) for (n = 0; n < totnode; n++) { PBVHVertexIter vd; SculptBrushTest test; - SculptUndoNode *unode; - float private_co[2][3] = {{0.0f}}; - float private_no[2][3] = {{0.0f}}; - int private_count[2] = {0}; - bool use_original; + SculptOrigVertData orig_data; + float *layer_disp; + /* XXX: layer brush needs conversion to proxy but its more complicated */ + /* proxy = BKE_pbvh_node_add_proxy(ss->pbvh, nodes[n])->co; */ + + sculpt_orig_vert_data_init(&orig_data, ob, nodes[n]); - unode = sculpt_undo_push_node(ob, nodes[n], SCULPT_UNDO_COORDS); +#pragma omp critical + { + layer_disp = BKE_pbvh_node_layer_disp_get(ss->pbvh, nodes[n]); + } + sculpt_brush_test_init(ss, &test); - use_original = (ss->cache->original && (unode->co || unode->bm_entry)); - - /* when the mesh is edited we can't rely on original coords - * (original mesh may not even have verts in brush radius) */ - if (use_original && unode->bm_entry) { - float (*orco_coords)[3]; - int (*orco_tris)[3]; - int orco_tris_num; - int i; - - BKE_pbvh_node_get_bm_orco_data( - nodes[n], - &orco_tris, &orco_tris_num, &orco_coords); + BKE_pbvh_vertex_iter_begin(ss->pbvh, nodes[n], vd, PBVH_ITER_UNIQUE) + { + sculpt_orig_vert_data_update(&orig_data, &vd); - for (i = 0; i < orco_tris_num; i++) { - const float *co_tri[3] = { - orco_coords[orco_tris[i][0]], - orco_coords[orco_tris[i][1]], - orco_coords[orco_tris[i][2]], - }; - float co[3]; + if (sculpt_brush_test(&test, orig_data.co)) { + const float fade = bstrength * tex_strength(ss, brush, vd.co, test.dist, + vd.no, vd.fno, vd.mask ? *vd.mask : 0.0f); + float *disp = &layer_disp[vd.i]; + float val[3]; - closest_on_tri_to_point_v3(co, test.location, UNPACK3(co_tri)); + *disp += fade; - if (sculpt_brush_test_fast(&test, co)) { - float no[3]; - int flip_index; + /* Don't let the displacement go past the limit */ + if ((lim < 0 && *disp < lim) || (lim >= 0 && *disp > lim)) + *disp = lim; - normal_tri_v3(no, UNPACK3(co_tri)); + mul_v3_v3fl(val, offset, *disp); - flip_index = (dot_v3v3(ss->cache->view_normal, no) <= 0.0f); - add_v3_v3(private_co[flip_index], co); - add_v3_v3(private_no[flip_index], no); - private_count[flip_index] += 1; - } - } - } - else { - BKE_pbvh_vertex_iter_begin(ss->pbvh, nodes[n], vd, PBVH_ITER_UNIQUE) - { - const float *co; + if (!ss->multires && !ss->bm && ss->layer_co && (brush->flag & BRUSH_PERSISTENT)) { + int index = vd.vert_indices[vd.i]; - if (use_original) { - co = unode->co[vd.i]; + /* persistent base */ + add_v3_v3(val, ss->layer_co[index]); } else { - co = vd.co; + add_v3_v3(val, orig_data.co); } - if (sculpt_brush_test_fast(&test, co)) { - float no_buf[3]; - const float *no; - int flip_index; - - if (use_original) { - normal_short_to_float_v3(no_buf, unode->no[vd.i]); - no = no_buf; - } - else { - if (vd.no) { - normal_short_to_float_v3(no_buf, vd.no); - no = no_buf; - } - else { - no = vd.fno; - } - } + sculpt_clip(sd, ss, vd.co, val); - flip_index = (dot_v3v3(ss->cache->view_normal, no) <= 0.0f); - add_v3_v3(private_co[flip_index], co); - add_v3_v3(private_no[flip_index], no); - private_count[flip_index] += 1; - } + if (vd.mvert) + vd.mvert->flag |= ME_VERT_PBVH_UPDATE; } - BKE_pbvh_vertex_iter_end; } + BKE_pbvh_vertex_iter_end; + } +} -#pragma omp critical - { - /* for flatten center */ - add_v3_v3(area_co[0], private_co[0]); - add_v3_v3(area_co[1], private_co[1]); +static void do_inflate_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnode) +{ + SculptSession *ss = ob->sculpt; + Brush *brush = BKE_paint_brush(&sd->paint); + float bstrength = ss->cache->bstrength; + int n; - /* for area normal */ - add_v3_v3(area_no[0], private_no[0]); - add_v3_v3(area_no[1], private_no[1]); +#pragma omp parallel for schedule(guided) if ((sd->flags & SCULPT_USE_OPENMP) && totnode > SCULPT_OMP_LIMIT) + for (n = 0; n < totnode; n++) { + PBVHVertexIter vd; + SculptBrushTest test; + float (*proxy)[3]; - /* weights */ - count[0] += private_count[0]; - count[1] += private_count[1]; - } - } + proxy = BKE_pbvh_node_add_proxy(ss->pbvh, nodes[n])->co; - /* for flatten center */ - for (n = 0; n < ARRAY_SIZE(area_co); n++) { - if (count[n] != 0) { - mul_v3_v3fl(r_area_co, area_co[n], 1.0f / count[n]); - break; - } - } - if (n == 2) { - zero_v3(r_area_co); - } + sculpt_brush_test_init(ss, &test); - /* for area normal */ - for (n = 0; n < ARRAY_SIZE(area_no); n++) { - if (normalize_v3_v3(r_area_no, area_no[n]) != 0.0f) { - break; + 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, + vd.no, vd.fno, vd.mask ? *vd.mask : 0.0f); + float val[3]; + + if (vd.fno) copy_v3_v3(val, vd.fno); + else normal_short_to_float_v3(val, vd.no); + + mul_v3_fl(val, fade * ss->cache->radius); + mul_v3_v3v3(proxy[vd.i], val, ss->cache->scale); + + if (vd.mvert) + vd.mvert->flag |= ME_VERT_PBVH_UPDATE; + } } + BKE_pbvh_vertex_iter_end; } } @@ -2466,7 +2527,7 @@ static void calc_sculpt_plane(Sculpt *sd, Object *ob, PBVHNode **nodes, int totn break; case SCULPT_DISP_DIR_AREA: - calc_area_normal_and_flatten_center(sd, ob, nodes, totnode, an, fc); + calc_area_normal_and_center(sd, ob, nodes, totnode, an, fc); break; default: @@ -2476,7 +2537,7 @@ static void calc_sculpt_plane(Sculpt *sd, Object *ob, PBVHNode **nodes, int totn /* for flatten center */ /* flatten center has not been calculated yet if we are not using the area normal */ if (brush->sculpt_plane != SCULPT_DISP_DIR_AREA) - calc_flatten_center(sd, ob, nodes, totnode, fc); + calc_area_center(sd, ob, nodes, totnode, fc); /* for area normal */ copy_v3_v3(ss->cache->sculpt_normal, an); @@ -2722,7 +2783,7 @@ static void do_clay_strips_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int t calc_sculpt_plane(sd, ob, nodes, totnode, sn, fc); if (brush->sculpt_plane != SCULPT_DISP_DIR_AREA || (brush->flag & BRUSH_ORIGINAL_NORMAL)) - calc_area_normal(sd, ob, an, nodes, totnode); + calc_area_normal(sd, ob, nodes, totnode, an); else copy_v3_v3(an, sn); -- cgit v1.2.3