Changeset View
Changeset View
Standalone View
Standalone View
source/blender/editors/sculpt_paint/sculpt.c
- This file is larger than 256 KB, so syntax highlighting is disabled by default.
| Show First 20 Lines • Show All 417 Lines • ▼ Show 20 Lines | if (distance_squared < nvtd->nearest_vertex_distance_squared && | ||||
| distance_squared < data->max_distance_squared) { | distance_squared < data->max_distance_squared) { | ||||
| nvtd->nearest_vertex_index = vd.index; | nvtd->nearest_vertex_index = vd.index; | ||||
| nvtd->nearest_vertex_distance_squared = distance_squared; | nvtd->nearest_vertex_distance_squared = distance_squared; | ||||
| } | } | ||||
| } | } | ||||
| BKE_pbvh_vertex_iter_end; | BKE_pbvh_vertex_iter_end; | ||||
| } | } | ||||
| static void nearest_vertex_get_finalize(void *__restrict userdata, void *__restrict tls) | static void nearest_vertex_get_reduce(const void *__restrict UNUSED(userdata), | ||||
| { | void *__restrict chunk_join, | ||||
| SculptThreadedTaskData *data = userdata; | void *__restrict chunk) | ||||
| NearestVertexTLSData *nvtd = tls; | { | ||||
| if (data->nearest_vertex_index == -1) { | NearestVertexTLSData *join = chunk_join; | ||||
| data->nearest_vertex_index = nvtd->nearest_vertex_index; | NearestVertexTLSData *nvtd = chunk; | ||||
| data->nearest_vertex_distance_squared = nvtd->nearest_vertex_distance_squared; | if (join->nearest_vertex_index == -1) { | ||||
| } | join->nearest_vertex_index = nvtd->nearest_vertex_index; | ||||
| else if (nvtd->nearest_vertex_distance_squared < data->nearest_vertex_distance_squared) { | join->nearest_vertex_distance_squared = nvtd->nearest_vertex_distance_squared; | ||||
| data->nearest_vertex_index = nvtd->nearest_vertex_index; | } | ||||
| data->nearest_vertex_distance_squared = nvtd->nearest_vertex_distance_squared; | else if (nvtd->nearest_vertex_distance_squared < join->nearest_vertex_distance_squared) { | ||||
| join->nearest_vertex_index = nvtd->nearest_vertex_index; | |||||
| join->nearest_vertex_distance_squared = nvtd->nearest_vertex_distance_squared; | |||||
| } | } | ||||
| } | } | ||||
| static int sculpt_nearest_vertex_get( | static int sculpt_nearest_vertex_get( | ||||
| Sculpt *sd, Object *ob, float co[3], float max_distance, bool use_original) | Sculpt *sd, Object *ob, float co[3], float max_distance, bool use_original) | ||||
| { | { | ||||
| SculptSession *ss = ob->sculpt; | SculptSession *ss = ob->sculpt; | ||||
| PBVHNode **nodes = NULL; | PBVHNode **nodes = NULL; | ||||
| Show All 10 Lines | if (totnode == 0) { | ||||
| return -1; | return -1; | ||||
| } | } | ||||
| SculptThreadedTaskData task_data = { | SculptThreadedTaskData task_data = { | ||||
| .sd = sd, | .sd = sd, | ||||
| .ob = ob, | .ob = ob, | ||||
| .nodes = nodes, | .nodes = nodes, | ||||
| .max_distance_squared = max_distance * max_distance, | .max_distance_squared = max_distance * max_distance, | ||||
| .nearest_vertex_index = -1, | |||||
| }; | }; | ||||
| copy_v3_v3(task_data.nearest_vertex_search_co, co); | copy_v3_v3(task_data.nearest_vertex_search_co, co); | ||||
| task_data.nearest_vertex_distance_squared = FLT_MAX; | |||||
| NearestVertexTLSData nvtd; | NearestVertexTLSData nvtd; | ||||
| nvtd.nearest_vertex_index = -1; | nvtd.nearest_vertex_index = -1; | ||||
| nvtd.nearest_vertex_distance_squared = FLT_MAX; | nvtd.nearest_vertex_distance_squared = FLT_MAX; | ||||
| TaskParallelSettings settings; | PBVHParallelSettings settings; | ||||
| BKE_pbvh_parallel_range_settings(&settings, (sd->flags & SCULPT_USE_OPENMP), totnode); | BKE_pbvh_parallel_range_settings(&settings, (sd->flags & SCULPT_USE_OPENMP), totnode); | ||||
| settings.func_finalize = nearest_vertex_get_finalize; | settings.func_reduce = nearest_vertex_get_reduce; | ||||
| settings.userdata_chunk = &nvtd; | settings.userdata_chunk = &nvtd; | ||||
| settings.userdata_chunk_size = sizeof(NearestVertexTLSData); | settings.userdata_chunk_size = sizeof(NearestVertexTLSData); | ||||
| BLI_task_parallel_range(0, totnode, &task_data, do_nearest_vertex_get_task_cb, &settings); | BKE_pbvh_parallel_range(0, totnode, &task_data, do_nearest_vertex_get_task_cb, &settings); | ||||
| MEM_SAFE_FREE(nodes); | MEM_SAFE_FREE(nodes); | ||||
| return task_data.nearest_vertex_index; | return nvtd.nearest_vertex_index; | ||||
| } | } | ||||
| static bool is_symmetry_iteration_valid(char i, char symm) | static bool is_symmetry_iteration_valid(char i, char symm) | ||||
| { | { | ||||
| return i == 0 || (symm & i && (symm != 5 || i != 3) && (symm != 6 || (i != 3 && i != 5))); | return i == 0 || (symm & i && (symm != 5 || i != 3) && (symm != 6 || (i != 3 && i != 5))); | ||||
| } | } | ||||
| /* Checks if a vertex is inside the brush radius from any of its mirrored axis */ | /* Checks if a vertex is inside the brush radius from any of its mirrored axis */ | ||||
| ▲ Show 20 Lines • Show All 442 Lines • ▼ Show 20 Lines | static void paint_mesh_restore_co(Sculpt *sd, Object *ob) | ||||
| * by a different thread. See T33787. */ | * by a different thread. See T33787. */ | ||||
| SculptThreadedTaskData data = { | SculptThreadedTaskData data = { | ||||
| .sd = sd, | .sd = sd, | ||||
| .ob = ob, | .ob = ob, | ||||
| .brush = brush, | .brush = brush, | ||||
| .nodes = nodes, | .nodes = nodes, | ||||
| }; | }; | ||||
| TaskParallelSettings settings; | PBVHParallelSettings settings; | ||||
| BKE_pbvh_parallel_range_settings(&settings, (sd->flags & SCULPT_USE_OPENMP) && !ss->bm, totnode); | BKE_pbvh_parallel_range_settings(&settings, (sd->flags & SCULPT_USE_OPENMP) && !ss->bm, totnode); | ||||
| BLI_task_parallel_range(0, totnode, &data, paint_mesh_restore_co_task_cb, &settings); | BKE_pbvh_parallel_range(0, totnode, &data, paint_mesh_restore_co_task_cb, &settings); | ||||
| MEM_SAFE_FREE(nodes); | MEM_SAFE_FREE(nodes); | ||||
| } | } | ||||
| /*** BVH Tree ***/ | /*** BVH Tree ***/ | ||||
| static void sculpt_extend_redraw_rect_previous(Object *ob, rcti *rect) | static void sculpt_extend_redraw_rect_previous(Object *ob, rcti *rect) | ||||
| { | { | ||||
| ▲ Show 20 Lines • Show All 457 Lines • ▼ Show 20 Lines | |||||
| * - #calc_area_center | * - #calc_area_center | ||||
| * - #calc_area_normal | * - #calc_area_normal | ||||
| * - #calc_area_normal_and_center | * - #calc_area_normal_and_center | ||||
| * | * | ||||
| * \note These are all _very_ similar, when changing one, check others. | * \note These are all _very_ similar, when changing one, check others. | ||||
| * \{ */ | * \{ */ | ||||
| typedef struct AreaNormalCenterTLSData { | typedef struct AreaNormalCenterTLSData { | ||||
| float private_co[2][3]; | /* 0=towards view, 1=flipped */ | ||||
| float private_no[2][3]; | float area_cos[2][3]; | ||||
| int private_count[2]; | float area_nos[2][3]; | ||||
| int area_count[2]; | |||||
| } AreaNormalCenterTLSData; | } AreaNormalCenterTLSData; | ||||
| static void calc_area_normal_and_center_task_cb(void *__restrict userdata, | static void calc_area_normal_and_center_task_cb(void *__restrict userdata, | ||||
| const int n, | const int n, | ||||
| const TaskParallelTLS *__restrict tls) | const TaskParallelTLS *__restrict tls) | ||||
| { | { | ||||
| SculptThreadedTaskData *data = userdata; | SculptThreadedTaskData *data = userdata; | ||||
| SculptSession *ss = data->ob->sculpt; | SculptSession *ss = data->ob->sculpt; | ||||
| AreaNormalCenterTLSData *anctd = tls->userdata_chunk; | AreaNormalCenterTLSData *anctd = tls->userdata_chunk; | ||||
| float(*area_nos)[3] = data->area_nos; | const bool use_area_nos = data->use_area_nos; | ||||
| float(*area_cos)[3] = data->area_cos; | const bool use_area_cos = data->use_area_cos; | ||||
| PBVHVertexIter vd; | PBVHVertexIter vd; | ||||
| SculptUndoNode *unode = NULL; | SculptUndoNode *unode = NULL; | ||||
| bool use_original = false; | bool use_original = false; | ||||
| if (ss->cache && ss->cache->original) { | if (ss->cache && ss->cache->original) { | ||||
| unode = sculpt_undo_push_node(data->ob, data->nodes[n], SCULPT_UNDO_COORDS); | unode = sculpt_undo_push_node(data->ob, data->nodes[n], SCULPT_UNDO_COORDS); | ||||
| Show All 36 Lines | for (i = 0; i < orco_tris_num; i++) { | ||||
| if (sculpt_brush_test_sq_fn(&test, co)) { | if (sculpt_brush_test_sq_fn(&test, co)) { | ||||
| float no[3]; | float no[3]; | ||||
| int flip_index; | int flip_index; | ||||
| normal_tri_v3(no, UNPACK3(co_tri)); | normal_tri_v3(no, UNPACK3(co_tri)); | ||||
| flip_index = (dot_v3v3(ss->cache->view_normal, no) <= 0.0f); | flip_index = (dot_v3v3(ss->cache->view_normal, no) <= 0.0f); | ||||
| if (area_cos) { | if (use_area_cos) { | ||||
| add_v3_v3(anctd->private_co[flip_index], co); | add_v3_v3(anctd->area_cos[flip_index], co); | ||||
| } | } | ||||
| if (area_nos) { | if (use_area_nos) { | ||||
| add_v3_v3(anctd->private_no[flip_index], no); | add_v3_v3(anctd->area_nos[flip_index], no); | ||||
| } | } | ||||
| anctd->private_count[flip_index] += 1; | anctd->area_count[flip_index] += 1; | ||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| else { | else { | ||||
| BKE_pbvh_vertex_iter_begin(ss->pbvh, data->nodes[n], vd, PBVH_ITER_UNIQUE) | BKE_pbvh_vertex_iter_begin(ss->pbvh, data->nodes[n], vd, PBVH_ITER_UNIQUE) | ||||
| { | { | ||||
| const float *co; | const float *co; | ||||
| const short *no_s; /* bm_vert only */ | const short *no_s; /* bm_vert only */ | ||||
| Show All 29 Lines | BKE_pbvh_vertex_iter_begin(ss->pbvh, data->nodes[n], vd, PBVH_ITER_UNIQUE) | ||||
| } | } | ||||
| else { | else { | ||||
| no = vd.fno; | no = vd.fno; | ||||
| } | } | ||||
| } | } | ||||
| flip_index = (dot_v3v3(ss->cache ? ss->cache->view_normal : ss->cursor_view_normal, no) <= | flip_index = (dot_v3v3(ss->cache ? ss->cache->view_normal : ss->cursor_view_normal, no) <= | ||||
| 0.0f); | 0.0f); | ||||
| if (area_cos) { | if (use_area_cos) { | ||||
| add_v3_v3(anctd->private_co[flip_index], co); | add_v3_v3(anctd->area_cos[flip_index], co); | ||||
| } | } | ||||
| if (area_nos) { | if (use_area_nos) { | ||||
| add_v3_v3(anctd->private_no[flip_index], no); | add_v3_v3(anctd->area_nos[flip_index], no); | ||||
| } | } | ||||
| anctd->private_count[flip_index] += 1; | anctd->area_count[flip_index] += 1; | ||||
| } | } | ||||
| } | } | ||||
| BKE_pbvh_vertex_iter_end; | BKE_pbvh_vertex_iter_end; | ||||
| } | } | ||||
| } | } | ||||
| static void calc_area_normal_and_center_finalize(void *__restrict userdata, void *__restrict tls) | static void calc_area_normal_and_center_reduce(const void *__restrict UNUSED(userdata), | ||||
| void *__restrict chunk_join, | |||||
| void *__restrict chunk) | |||||
| { | { | ||||
| SculptThreadedTaskData *data = userdata; | AreaNormalCenterTLSData *join = chunk_join; | ||||
| AreaNormalCenterTLSData *anctd = tls; | AreaNormalCenterTLSData *anctd = chunk; | ||||
| float(*area_nos)[3] = data->area_nos; | |||||
| float(*area_cos)[3] = data->area_cos; | |||||
| /* for flatten center */ | /* for flatten center */ | ||||
| if (area_cos) { | add_v3_v3(join->area_cos[0], anctd->area_cos[0]); | ||||
| add_v3_v3(area_cos[0], anctd->private_co[0]); | add_v3_v3(join->area_cos[1], anctd->area_cos[1]); | ||||
| add_v3_v3(area_cos[1], anctd->private_co[1]); | |||||
| } | |||||
| /* for area normal */ | /* for area normal */ | ||||
| if (area_nos) { | add_v3_v3(join->area_nos[0], anctd->area_nos[0]); | ||||
| add_v3_v3(area_nos[0], anctd->private_no[0]); | add_v3_v3(join->area_nos[1], anctd->area_nos[1]); | ||||
| add_v3_v3(area_nos[1], anctd->private_no[1]); | |||||
| } | |||||
| /* weights */ | /* weights */ | ||||
| data->count[0] += anctd->private_count[0]; | join->area_count[0] += anctd->area_count[0]; | ||||
| data->count[1] += anctd->private_count[1]; | join->area_count[1] += anctd->area_count[1]; | ||||
| } | } | ||||
| static void calc_area_center( | static void calc_area_center( | ||||
| Sculpt *sd, Object *ob, PBVHNode **nodes, int totnode, float r_area_co[3]) | Sculpt *sd, Object *ob, PBVHNode **nodes, int totnode, float r_area_co[3]) | ||||
| { | { | ||||
| const Brush *brush = BKE_paint_brush(&sd->paint); | const Brush *brush = BKE_paint_brush(&sd->paint); | ||||
| SculptSession *ss = ob->sculpt; | SculptSession *ss = ob->sculpt; | ||||
| const bool has_bm_orco = ss->bm && sculpt_stroke_is_dynamic_topology(ss, brush); | const bool has_bm_orco = ss->bm && sculpt_stroke_is_dynamic_topology(ss, brush); | ||||
| int n; | int n; | ||||
| /* 0=towards view, 1=flipped */ | |||||
| float area_cos[2][3] = {{0.0f}}; | |||||
| int count[2] = {0}; | |||||
| /* Intentionally set 'sd' to NULL since we share logic with vertex paint. */ | /* Intentionally set 'sd' to NULL since we share logic with vertex paint. */ | ||||
| SculptThreadedTaskData data = { | SculptThreadedTaskData data = { | ||||
| .sd = NULL, | .sd = NULL, | ||||
| .ob = ob, | .ob = ob, | ||||
| .brush = brush, | .brush = brush, | ||||
| .nodes = nodes, | .nodes = nodes, | ||||
| .totnode = totnode, | .totnode = totnode, | ||||
| .has_bm_orco = has_bm_orco, | .has_bm_orco = has_bm_orco, | ||||
| .area_cos = area_cos, | .use_area_cos = true, | ||||
| .area_nos = NULL, | |||||
| .count = count, | |||||
| }; | }; | ||||
| AreaNormalCenterTLSData anctd = {{{0}}}; | AreaNormalCenterTLSData anctd = {{{0}}}; | ||||
| TaskParallelSettings settings; | PBVHParallelSettings settings; | ||||
| BKE_pbvh_parallel_range_settings(&settings, (sd->flags & SCULPT_USE_OPENMP), totnode); | BKE_pbvh_parallel_range_settings(&settings, (sd->flags & SCULPT_USE_OPENMP), totnode); | ||||
| settings.func_finalize = calc_area_normal_and_center_finalize; | settings.func_reduce = calc_area_normal_and_center_reduce; | ||||
| settings.userdata_chunk = &anctd; | settings.userdata_chunk = &anctd; | ||||
| settings.userdata_chunk_size = sizeof(AreaNormalCenterTLSData); | settings.userdata_chunk_size = sizeof(AreaNormalCenterTLSData); | ||||
| BLI_task_parallel_range(0, totnode, &data, calc_area_normal_and_center_task_cb, &settings); | BKE_pbvh_parallel_range(0, totnode, &data, calc_area_normal_and_center_task_cb, &settings); | ||||
| /* for flatten center */ | /* for flatten center */ | ||||
| for (n = 0; n < ARRAY_SIZE(area_cos); n++) { | for (n = 0; n < ARRAY_SIZE(anctd.area_cos); n++) { | ||||
| if (count[n] != 0) { | if (anctd.area_count[n] != 0) { | ||||
| mul_v3_v3fl(r_area_co, area_cos[n], 1.0f / count[n]); | mul_v3_v3fl(r_area_co, anctd.area_cos[n], 1.0f / anctd.area_count[n]); | ||||
| break; | break; | ||||
| } | } | ||||
| } | } | ||||
| if (n == 2) { | if (n == 2) { | ||||
| zero_v3(r_area_co); | zero_v3(r_area_co); | ||||
| } | } | ||||
| } | } | ||||
| Show All 11 Lines | bool sculpt_pbvh_calc_area_normal(const Brush *brush, | ||||
| PBVHNode **nodes, | PBVHNode **nodes, | ||||
| int totnode, | int totnode, | ||||
| bool use_threading, | bool use_threading, | ||||
| float r_area_no[3]) | float r_area_no[3]) | ||||
| { | { | ||||
| SculptSession *ss = ob->sculpt; | SculptSession *ss = ob->sculpt; | ||||
| const bool has_bm_orco = ss->bm && sculpt_stroke_is_dynamic_topology(ss, brush); | const bool has_bm_orco = ss->bm && sculpt_stroke_is_dynamic_topology(ss, brush); | ||||
| /* 0=towards view, 1=flipped */ | |||||
| float area_nos[2][3] = {{0.0f}}; | |||||
| int count[2] = {0}; | |||||
| /* Intentionally set 'sd' to NULL since this is used for vertex paint too. */ | /* Intentionally set 'sd' to NULL since this is used for vertex paint too. */ | ||||
| SculptThreadedTaskData data = { | SculptThreadedTaskData data = { | ||||
| .sd = NULL, | .sd = NULL, | ||||
| .ob = ob, | .ob = ob, | ||||
| .brush = brush, | .brush = brush, | ||||
| .nodes = nodes, | .nodes = nodes, | ||||
| .totnode = totnode, | .totnode = totnode, | ||||
| .has_bm_orco = has_bm_orco, | .has_bm_orco = has_bm_orco, | ||||
| .area_cos = NULL, | .use_area_nos = true, | ||||
| .area_nos = area_nos, | |||||
| .count = count, | |||||
| .any_vertex_sampled = false, | .any_vertex_sampled = false, | ||||
| }; | }; | ||||
| AreaNormalCenterTLSData anctd = {{{0}}}; | AreaNormalCenterTLSData anctd = {{{0}}}; | ||||
| TaskParallelSettings settings; | PBVHParallelSettings settings; | ||||
| BKE_pbvh_parallel_range_settings(&settings, use_threading, totnode); | BKE_pbvh_parallel_range_settings(&settings, use_threading, totnode); | ||||
| settings.func_finalize = calc_area_normal_and_center_finalize; | settings.func_reduce = calc_area_normal_and_center_reduce; | ||||
| settings.userdata_chunk = &anctd; | settings.userdata_chunk = &anctd; | ||||
| settings.userdata_chunk_size = sizeof(AreaNormalCenterTLSData); | settings.userdata_chunk_size = sizeof(AreaNormalCenterTLSData); | ||||
| BLI_task_parallel_range(0, totnode, &data, calc_area_normal_and_center_task_cb, &settings); | BKE_pbvh_parallel_range(0, totnode, &data, calc_area_normal_and_center_task_cb, &settings); | ||||
| /* for area normal */ | /* for area normal */ | ||||
| for (int i = 0; i < ARRAY_SIZE(area_nos); i++) { | for (int i = 0; i < ARRAY_SIZE(anctd.area_nos); i++) { | ||||
| if (normalize_v3_v3(r_area_no, area_nos[i]) != 0.0f) { | if (normalize_v3_v3(r_area_no, anctd.area_nos[i]) != 0.0f) { | ||||
| break; | break; | ||||
| } | } | ||||
| } | } | ||||
| return data.any_vertex_sampled; | return data.any_vertex_sampled; | ||||
| } | } | ||||
| /* this calculates flatten center and area normal together, | /* this calculates flatten center and area normal together, | ||||
| * amortizing the memory bandwidth and loop overhead to calculate both at the same time */ | * amortizing the memory bandwidth and loop overhead to calculate both at the same time */ | ||||
| static void calc_area_normal_and_center( | 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]) | Sculpt *sd, Object *ob, PBVHNode **nodes, int totnode, float r_area_no[3], float r_area_co[3]) | ||||
| { | { | ||||
| const Brush *brush = BKE_paint_brush(&sd->paint); | const Brush *brush = BKE_paint_brush(&sd->paint); | ||||
| SculptSession *ss = ob->sculpt; | SculptSession *ss = ob->sculpt; | ||||
| const bool has_bm_orco = ss->bm && sculpt_stroke_is_dynamic_topology(ss, brush); | const bool has_bm_orco = ss->bm && sculpt_stroke_is_dynamic_topology(ss, brush); | ||||
| int n; | int n; | ||||
| /* 0=towards view, 1=flipped */ | |||||
| float area_cos[2][3] = {{0.0f}}; | |||||
| float area_nos[2][3] = {{0.0f}}; | |||||
| int count[2] = {0}; | |||||
| /* Intentionally set 'sd' to NULL since this is used for vertex paint too. */ | /* Intentionally set 'sd' to NULL since this is used for vertex paint too. */ | ||||
| SculptThreadedTaskData data = { | SculptThreadedTaskData data = { | ||||
| .sd = NULL, | .sd = NULL, | ||||
| .ob = ob, | .ob = ob, | ||||
| .brush = brush, | .brush = brush, | ||||
| .nodes = nodes, | .nodes = nodes, | ||||
| .totnode = totnode, | .totnode = totnode, | ||||
| .has_bm_orco = has_bm_orco, | .has_bm_orco = has_bm_orco, | ||||
| .area_cos = area_cos, | .use_area_cos = true, | ||||
| .area_nos = area_nos, | .use_area_nos = true, | ||||
| .count = count, | |||||
| }; | }; | ||||
| AreaNormalCenterTLSData anctd = {{{0}}}; | AreaNormalCenterTLSData anctd = {{{0}}}; | ||||
| TaskParallelSettings settings; | PBVHParallelSettings settings; | ||||
| BKE_pbvh_parallel_range_settings(&settings, (sd->flags & SCULPT_USE_OPENMP), totnode); | BKE_pbvh_parallel_range_settings(&settings, (sd->flags & SCULPT_USE_OPENMP), totnode); | ||||
| settings.func_finalize = calc_area_normal_and_center_finalize; | settings.func_reduce = calc_area_normal_and_center_reduce; | ||||
| settings.userdata_chunk = &anctd; | settings.userdata_chunk = &anctd; | ||||
| settings.userdata_chunk_size = sizeof(AreaNormalCenterTLSData); | settings.userdata_chunk_size = sizeof(AreaNormalCenterTLSData); | ||||
| BLI_task_parallel_range(0, totnode, &data, calc_area_normal_and_center_task_cb, &settings); | BKE_pbvh_parallel_range(0, totnode, &data, calc_area_normal_and_center_task_cb, &settings); | ||||
| /* for flatten center */ | /* for flatten center */ | ||||
| for (n = 0; n < ARRAY_SIZE(area_cos); n++) { | for (n = 0; n < ARRAY_SIZE(anctd.area_cos); n++) { | ||||
| if (count[n] != 0) { | if (anctd.area_count[n] != 0) { | ||||
| mul_v3_v3fl(r_area_co, area_cos[n], 1.0f / count[n]); | mul_v3_v3fl(r_area_co, anctd.area_cos[n], 1.0f / anctd.area_count[n]); | ||||
| break; | break; | ||||
| } | } | ||||
| } | } | ||||
| if (n == 2) { | if (n == 2) { | ||||
| zero_v3(r_area_co); | zero_v3(r_area_co); | ||||
| } | } | ||||
| /* for area normal */ | /* for area normal */ | ||||
| for (n = 0; n < ARRAY_SIZE(area_nos); n++) { | for (n = 0; n < ARRAY_SIZE(anctd.area_nos); n++) { | ||||
| if (normalize_v3_v3(r_area_no, area_nos[n]) != 0.0f) { | if (normalize_v3_v3(r_area_no, anctd.area_nos[n]) != 0.0f) { | ||||
| break; | break; | ||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| /** \} */ | /** \} */ | ||||
| /* Return modified brush strength. Includes the direction of the brush, positive | /* Return modified brush strength. Includes the direction of the brush, positive | ||||
| ▲ Show 20 Lines • Show All 1,085 Lines • ▼ Show 20 Lines | SculptThreadedTaskData data = { | ||||
| .sd = sd, | .sd = sd, | ||||
| .ob = ob, | .ob = ob, | ||||
| .brush = brush, | .brush = brush, | ||||
| .nodes = nodes, | .nodes = nodes, | ||||
| .smooth_mask = smooth_mask, | .smooth_mask = smooth_mask, | ||||
| .strength = strength, | .strength = strength, | ||||
| }; | }; | ||||
| TaskParallelSettings settings; | PBVHParallelSettings settings; | ||||
| BKE_pbvh_parallel_range_settings(&settings, (sd->flags & SCULPT_USE_OPENMP), totnode); | BKE_pbvh_parallel_range_settings(&settings, (sd->flags & SCULPT_USE_OPENMP), totnode); | ||||
| switch (type) { | switch (type) { | ||||
| case PBVH_GRIDS: { | case PBVH_GRIDS: { | ||||
| int gridsize; | int gridsize; | ||||
| size_t size; | size_t size; | ||||
| SculptDoBrushSmoothGridDataChunk *data_chunk; | SculptDoBrushSmoothGridDataChunk *data_chunk; | ||||
| BKE_pbvh_node_get_grids(ss->pbvh, NULL, NULL, NULL, NULL, &gridsize, NULL); | BKE_pbvh_node_get_grids(ss->pbvh, NULL, NULL, NULL, NULL, &gridsize, NULL); | ||||
| size = (size_t)gridsize; | size = (size_t)gridsize; | ||||
| size = sizeof(float) * size * size * (smooth_mask ? 1 : 3); | size = sizeof(float) * size * size * (smooth_mask ? 1 : 3); | ||||
| data_chunk = MEM_mallocN(sizeof(*data_chunk) + size, __func__); | data_chunk = MEM_mallocN(sizeof(*data_chunk) + size, __func__); | ||||
| data_chunk->tmpgrid_size = size; | data_chunk->tmpgrid_size = size; | ||||
| size += sizeof(*data_chunk); | size += sizeof(*data_chunk); | ||||
| settings.userdata_chunk = data_chunk; | settings.userdata_chunk = data_chunk; | ||||
| settings.userdata_chunk_size = size; | settings.userdata_chunk_size = size; | ||||
| BLI_task_parallel_range(0, totnode, &data, do_smooth_brush_multires_task_cb_ex, &settings); | BKE_pbvh_parallel_range(0, totnode, &data, do_smooth_brush_multires_task_cb_ex, &settings); | ||||
| MEM_freeN(data_chunk); | MEM_freeN(data_chunk); | ||||
| break; | break; | ||||
| } | } | ||||
| case PBVH_FACES: | case PBVH_FACES: | ||||
| BLI_task_parallel_range(0, totnode, &data, do_smooth_brush_mesh_task_cb_ex, &settings); | BKE_pbvh_parallel_range(0, totnode, &data, do_smooth_brush_mesh_task_cb_ex, &settings); | ||||
| break; | break; | ||||
| case PBVH_BMESH: | case PBVH_BMESH: | ||||
| BLI_task_parallel_range(0, totnode, &data, do_smooth_brush_bmesh_task_cb_ex, &settings); | BKE_pbvh_parallel_range(0, totnode, &data, do_smooth_brush_bmesh_task_cb_ex, &settings); | ||||
| break; | break; | ||||
| } | } | ||||
| if (ss->multires) { | if (ss->multires) { | ||||
| multires_stitch_grids(ob); | multires_stitch_grids(ob); | ||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| Show All 15 Lines | for (iteration = 0; iteration <= count; iteration++) { | ||||
| SculptThreadedTaskData data = { | SculptThreadedTaskData data = { | ||||
| .sd = sd, | .sd = sd, | ||||
| .ob = ob, | .ob = ob, | ||||
| .brush = brush, | .brush = brush, | ||||
| .nodes = nodes, | .nodes = nodes, | ||||
| .strength = factor, | .strength = factor, | ||||
| }; | }; | ||||
| TaskParallelSettings settings; | PBVHParallelSettings settings; | ||||
| BKE_pbvh_parallel_range_settings(&settings, (sd->flags & SCULPT_USE_OPENMP), totnode); | BKE_pbvh_parallel_range_settings(&settings, (sd->flags & SCULPT_USE_OPENMP), totnode); | ||||
| BLI_task_parallel_range(0, totnode, &data, do_topology_rake_bmesh_task_cb_ex, &settings); | BKE_pbvh_parallel_range(0, totnode, &data, do_topology_rake_bmesh_task_cb_ex, &settings); | ||||
| } | } | ||||
| } | } | ||||
| static void do_smooth_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnode) | static void do_smooth_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnode) | ||||
| { | { | ||||
| SculptSession *ss = ob->sculpt; | SculptSession *ss = ob->sculpt; | ||||
| smooth(sd, ob, nodes, totnode, ss->cache->bstrength, false); | smooth(sd, ob, nodes, totnode, ss->cache->bstrength, false); | ||||
| } | } | ||||
| Show All 37 Lines | static void do_mask_brush_draw(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnode) | ||||
| /* threaded loop over nodes */ | /* threaded loop over nodes */ | ||||
| SculptThreadedTaskData data = { | SculptThreadedTaskData data = { | ||||
| .sd = sd, | .sd = sd, | ||||
| .ob = ob, | .ob = ob, | ||||
| .brush = brush, | .brush = brush, | ||||
| .nodes = nodes, | .nodes = nodes, | ||||
| }; | }; | ||||
| TaskParallelSettings settings; | PBVHParallelSettings settings; | ||||
| BKE_pbvh_parallel_range_settings(&settings, (sd->flags & SCULPT_USE_OPENMP), totnode); | BKE_pbvh_parallel_range_settings(&settings, (sd->flags & SCULPT_USE_OPENMP), totnode); | ||||
| BLI_task_parallel_range(0, totnode, &data, do_mask_brush_draw_task_cb_ex, &settings); | BKE_pbvh_parallel_range(0, totnode, &data, do_mask_brush_draw_task_cb_ex, &settings); | ||||
| } | } | ||||
| static void do_mask_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnode) | static void do_mask_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnode) | ||||
| { | { | ||||
| SculptSession *ss = ob->sculpt; | SculptSession *ss = ob->sculpt; | ||||
| Brush *brush = BKE_paint_brush(&sd->paint); | Brush *brush = BKE_paint_brush(&sd->paint); | ||||
| switch ((BrushMaskTool)brush->mask_tool) { | switch ((BrushMaskTool)brush->mask_tool) { | ||||
| ▲ Show 20 Lines • Show All 68 Lines • ▼ Show 20 Lines | static void do_draw_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnode) | ||||
| SculptThreadedTaskData data = { | SculptThreadedTaskData data = { | ||||
| .sd = sd, | .sd = sd, | ||||
| .ob = ob, | .ob = ob, | ||||
| .brush = brush, | .brush = brush, | ||||
| .nodes = nodes, | .nodes = nodes, | ||||
| .offset = offset, | .offset = offset, | ||||
| }; | }; | ||||
| TaskParallelSettings settings; | PBVHParallelSettings settings; | ||||
| BKE_pbvh_parallel_range_settings(&settings, (sd->flags & SCULPT_USE_OPENMP), totnode); | BKE_pbvh_parallel_range_settings(&settings, (sd->flags & SCULPT_USE_OPENMP), totnode); | ||||
| BLI_task_parallel_range(0, totnode, &data, do_draw_brush_task_cb_ex, &settings); | BKE_pbvh_parallel_range(0, totnode, &data, do_draw_brush_task_cb_ex, &settings); | ||||
| } | } | ||||
| static void do_draw_sharp_brush_task_cb_ex(void *__restrict userdata, | static void do_draw_sharp_brush_task_cb_ex(void *__restrict userdata, | ||||
| const int n, | const int n, | ||||
| const TaskParallelTLS *__restrict tls) | const TaskParallelTLS *__restrict tls) | ||||
| { | { | ||||
| SculptThreadedTaskData *data = userdata; | SculptThreadedTaskData *data = userdata; | ||||
| SculptSession *ss = data->ob->sculpt; | SculptSession *ss = data->ob->sculpt; | ||||
| ▲ Show 20 Lines • Show All 57 Lines • ▼ Show 20 Lines | static void do_draw_sharp_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnode) | ||||
| SculptThreadedTaskData data = { | SculptThreadedTaskData data = { | ||||
| .sd = sd, | .sd = sd, | ||||
| .ob = ob, | .ob = ob, | ||||
| .brush = brush, | .brush = brush, | ||||
| .nodes = nodes, | .nodes = nodes, | ||||
| .offset = offset, | .offset = offset, | ||||
| }; | }; | ||||
| TaskParallelSettings settings; | PBVHParallelSettings settings; | ||||
| BKE_pbvh_parallel_range_settings(&settings, (sd->flags & SCULPT_USE_OPENMP), totnode); | BKE_pbvh_parallel_range_settings(&settings, (sd->flags & SCULPT_USE_OPENMP), totnode); | ||||
| BLI_task_parallel_range(0, totnode, &data, do_draw_sharp_brush_task_cb_ex, &settings); | BKE_pbvh_parallel_range(0, totnode, &data, do_draw_sharp_brush_task_cb_ex, &settings); | ||||
| } | } | ||||
| /** | /** | ||||
| * Used for 'SCULPT_TOOL_CREASE' and 'SCULPT_TOOL_BLOB' | * Used for 'SCULPT_TOOL_CREASE' and 'SCULPT_TOOL_BLOB' | ||||
| */ | */ | ||||
| static void do_crease_brush_task_cb_ex(void *__restrict userdata, | static void do_crease_brush_task_cb_ex(void *__restrict userdata, | ||||
| const int n, | const int n, | ||||
| const TaskParallelTLS *__restrict tls) | const TaskParallelTLS *__restrict tls) | ||||
| ▲ Show 20 Lines • Show All 97 Lines • ▼ Show 20 Lines | SculptThreadedTaskData data = { | ||||
| .ob = ob, | .ob = ob, | ||||
| .brush = brush, | .brush = brush, | ||||
| .nodes = nodes, | .nodes = nodes, | ||||
| .spvc = &spvc, | .spvc = &spvc, | ||||
| .offset = offset, | .offset = offset, | ||||
| .flippedbstrength = flippedbstrength, | .flippedbstrength = flippedbstrength, | ||||
| }; | }; | ||||
| TaskParallelSettings settings; | PBVHParallelSettings settings; | ||||
| BKE_pbvh_parallel_range_settings(&settings, (sd->flags & SCULPT_USE_OPENMP), totnode); | BKE_pbvh_parallel_range_settings(&settings, (sd->flags & SCULPT_USE_OPENMP), totnode); | ||||
| BLI_task_parallel_range(0, totnode, &data, do_crease_brush_task_cb_ex, &settings); | BKE_pbvh_parallel_range(0, totnode, &data, do_crease_brush_task_cb_ex, &settings); | ||||
| } | } | ||||
| static void do_pinch_brush_task_cb_ex(void *__restrict userdata, | static void do_pinch_brush_task_cb_ex(void *__restrict userdata, | ||||
| const int n, | const int n, | ||||
| const TaskParallelTLS *__restrict tls) | const TaskParallelTLS *__restrict tls) | ||||
| { | { | ||||
| SculptThreadedTaskData *data = userdata; | SculptThreadedTaskData *data = userdata; | ||||
| SculptSession *ss = data->ob->sculpt; | SculptSession *ss = data->ob->sculpt; | ||||
| ▲ Show 20 Lines • Show All 43 Lines • ▼ Show 20 Lines | static void do_pinch_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnode) | ||||
| SculptThreadedTaskData data = { | SculptThreadedTaskData data = { | ||||
| .sd = sd, | .sd = sd, | ||||
| .ob = ob, | .ob = ob, | ||||
| .brush = brush, | .brush = brush, | ||||
| .nodes = nodes, | .nodes = nodes, | ||||
| }; | }; | ||||
| TaskParallelSettings settings; | PBVHParallelSettings settings; | ||||
| BKE_pbvh_parallel_range_settings(&settings, (sd->flags & SCULPT_USE_OPENMP), totnode); | BKE_pbvh_parallel_range_settings(&settings, (sd->flags & SCULPT_USE_OPENMP), totnode); | ||||
| BLI_task_parallel_range(0, totnode, &data, do_pinch_brush_task_cb_ex, &settings); | BKE_pbvh_parallel_range(0, totnode, &data, do_pinch_brush_task_cb_ex, &settings); | ||||
| } | } | ||||
| static void do_grab_brush_task_cb_ex(void *__restrict userdata, | static void do_grab_brush_task_cb_ex(void *__restrict userdata, | ||||
| const int n, | const int n, | ||||
| const TaskParallelTLS *__restrict tls) | const TaskParallelTLS *__restrict tls) | ||||
| { | { | ||||
| SculptThreadedTaskData *data = userdata; | SculptThreadedTaskData *data = userdata; | ||||
| SculptSession *ss = data->ob->sculpt; | SculptSession *ss = data->ob->sculpt; | ||||
| ▲ Show 20 Lines • Show All 53 Lines • ▼ Show 20 Lines | static void do_grab_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnode) | ||||
| SculptThreadedTaskData data = { | SculptThreadedTaskData data = { | ||||
| .sd = sd, | .sd = sd, | ||||
| .ob = ob, | .ob = ob, | ||||
| .brush = brush, | .brush = brush, | ||||
| .nodes = nodes, | .nodes = nodes, | ||||
| .grab_delta = grab_delta, | .grab_delta = grab_delta, | ||||
| }; | }; | ||||
| TaskParallelSettings settings; | PBVHParallelSettings settings; | ||||
| BKE_pbvh_parallel_range_settings(&settings, (sd->flags & SCULPT_USE_OPENMP), totnode); | BKE_pbvh_parallel_range_settings(&settings, (sd->flags & SCULPT_USE_OPENMP), totnode); | ||||
| BLI_task_parallel_range(0, totnode, &data, do_grab_brush_task_cb_ex, &settings); | BKE_pbvh_parallel_range(0, totnode, &data, do_grab_brush_task_cb_ex, &settings); | ||||
| } | } | ||||
| /* Regularized Kelvinlets: Sculpting Brushes based on Fundamental Solutions of Elasticity | /* Regularized Kelvinlets: Sculpting Brushes based on Fundamental Solutions of Elasticity | ||||
| * Pixar Technical Memo #17-03 */ | * Pixar Technical Memo #17-03 */ | ||||
| typedef struct KelvinletParams { | typedef struct KelvinletParams { | ||||
| float f; | float f; | ||||
| float a; | float a; | ||||
| ▲ Show 20 Lines • Show All 234 Lines • ▼ Show 20 Lines | static void do_elastic_deform_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnode) | ||||
| SculptThreadedTaskData data = { | SculptThreadedTaskData data = { | ||||
| .sd = sd, | .sd = sd, | ||||
| .ob = ob, | .ob = ob, | ||||
| .brush = brush, | .brush = brush, | ||||
| .nodes = nodes, | .nodes = nodes, | ||||
| .grab_delta = grab_delta, | .grab_delta = grab_delta, | ||||
| }; | }; | ||||
| TaskParallelSettings settings; | PBVHParallelSettings settings; | ||||
| BKE_pbvh_parallel_range_settings(&settings, (sd->flags & SCULPT_USE_OPENMP), totnode); | BKE_pbvh_parallel_range_settings(&settings, (sd->flags & SCULPT_USE_OPENMP), totnode); | ||||
| BLI_task_parallel_range(0, totnode, &data, do_elastic_deform_brush_task_cb_ex, &settings); | BKE_pbvh_parallel_range(0, totnode, &data, do_elastic_deform_brush_task_cb_ex, &settings); | ||||
| } | } | ||||
| static void do_pose_brush_task_cb_ex(void *__restrict userdata, | static void do_pose_brush_task_cb_ex(void *__restrict userdata, | ||||
| const int n, | const int n, | ||||
| const TaskParallelTLS *__restrict UNUSED(tls)) | const TaskParallelTLS *__restrict UNUSED(tls)) | ||||
| { | { | ||||
| SculptThreadedTaskData *data = userdata; | SculptThreadedTaskData *data = userdata; | ||||
| SculptSession *ss = data->ob->sculpt; | SculptSession *ss = data->ob->sculpt; | ||||
| ▲ Show 20 Lines • Show All 70 Lines • ▼ Show 20 Lines | SculptThreadedTaskData data = { | ||||
| .grab_delta = grab_delta, | .grab_delta = grab_delta, | ||||
| .pose_origin = pose_origin, | .pose_origin = pose_origin, | ||||
| .pose_initial_co = pose_initial_co, | .pose_initial_co = pose_initial_co, | ||||
| .transform_rot = transform_rot, | .transform_rot = transform_rot, | ||||
| .transform_trans = transform_trans, | .transform_trans = transform_trans, | ||||
| .transform_trans_inv = transform_trans_inv, | .transform_trans_inv = transform_trans_inv, | ||||
| }; | }; | ||||
| TaskParallelSettings settings; | PBVHParallelSettings settings; | ||||
| BKE_pbvh_parallel_range_settings(&settings, (sd->flags & SCULPT_USE_OPENMP), totnode); | BKE_pbvh_parallel_range_settings(&settings, (sd->flags & SCULPT_USE_OPENMP), totnode); | ||||
| BLI_task_parallel_range(0, totnode, &data, do_pose_brush_task_cb_ex, &settings); | BKE_pbvh_parallel_range(0, totnode, &data, do_pose_brush_task_cb_ex, &settings); | ||||
| } | } | ||||
| typedef struct PoseGrowFactorTLSData { | typedef struct PoseGrowFactorTLSData { | ||||
| float pos_avg[3]; | float pos_avg[3]; | ||||
| int tot_pos_avg; | int pos_count; | ||||
| } PoseGrowFactorTLSData; | } PoseGrowFactorTLSData; | ||||
| static void pose_brush_grow_factor_task_cb_ex(void *__restrict userdata, | static void pose_brush_grow_factor_task_cb_ex(void *__restrict userdata, | ||||
| const int n, | const int n, | ||||
| const TaskParallelTLS *__restrict tls) | const TaskParallelTLS *__restrict tls) | ||||
| { | { | ||||
| SculptThreadedTaskData *data = userdata; | SculptThreadedTaskData *data = userdata; | ||||
| PoseGrowFactorTLSData *gftd = tls->userdata_chunk; | PoseGrowFactorTLSData *gftd = tls->userdata_chunk; | ||||
| Show All 12 Lines | sculpt_vertex_neighbors_iter_begin(ss, vd.index, ni) | ||||
| max = vmask_f; | max = vmask_f; | ||||
| } | } | ||||
| } | } | ||||
| sculpt_vertex_neighbors_iter_end(ni); | sculpt_vertex_neighbors_iter_end(ni); | ||||
| if (max != data->prev_mask[vd.index]) { | if (max != data->prev_mask[vd.index]) { | ||||
| data->pose_factor[vd.index] = max; | data->pose_factor[vd.index] = max; | ||||
| if (check_vertex_pivot_symmetry(vd.co, active_co, symm)) { | if (check_vertex_pivot_symmetry(vd.co, active_co, symm)) { | ||||
| add_v3_v3(gftd->pos_avg, vd.co); | add_v3_v3(gftd->pos_avg, vd.co); | ||||
| gftd->tot_pos_avg++; | gftd->pos_count++; | ||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| BKE_pbvh_vertex_iter_end; | BKE_pbvh_vertex_iter_end; | ||||
| } | } | ||||
| static void pose_brush_grow_factor_finalize(void *__restrict userdata, void *__restrict tls) | static void pose_brush_grow_factor_reduce(const void *__restrict UNUSED(userdata), | ||||
| { | void *__restrict chunk_join, | ||||
| SculptThreadedTaskData *data = userdata; | void *__restrict chunk) | ||||
| PoseGrowFactorTLSData *gftd = tls; | { | ||||
| add_v3_v3(data->tot_pos_avg, gftd->pos_avg); | PoseGrowFactorTLSData *join = chunk_join; | ||||
| data->tot_pos_count += gftd->tot_pos_avg; | PoseGrowFactorTLSData *gftd = chunk; | ||||
| add_v3_v3(join->pos_avg, gftd->pos_avg); | |||||
| join->pos_count += gftd->pos_count; | |||||
| } | } | ||||
| /* Grow the factor until its boundary is near to the offset pose origin */ | /* Grow the factor until its boundary is near to the offset pose origin */ | ||||
| static void sculpt_pose_grow_pose_factor( | static void sculpt_pose_grow_pose_factor( | ||||
| Sculpt *sd, Object *ob, SculptSession *ss, float pose_origin[3], float *pose_factor) | Sculpt *sd, Object *ob, SculptSession *ss, float pose_origin[3], float *pose_factor) | ||||
| { | { | ||||
| PBVHNode **nodes; | PBVHNode **nodes; | ||||
| PBVH *pbvh = ob->sculpt->pbvh; | PBVH *pbvh = ob->sculpt->pbvh; | ||||
| int totnode; | int totnode; | ||||
| BKE_pbvh_search_gather(pbvh, NULL, NULL, &nodes, &totnode); | BKE_pbvh_search_gather(pbvh, NULL, NULL, &nodes, &totnode); | ||||
| SculptThreadedTaskData data = { | SculptThreadedTaskData data = { | ||||
| .sd = sd, | .sd = sd, | ||||
| .ob = ob, | .ob = ob, | ||||
| .nodes = nodes, | .nodes = nodes, | ||||
| .totnode = totnode, | .totnode = totnode, | ||||
| .pose_factor = pose_factor, | .pose_factor = pose_factor, | ||||
| }; | }; | ||||
| TaskParallelSettings settings; | PBVHParallelSettings settings; | ||||
| PoseGrowFactorTLSData gftd; | PoseGrowFactorTLSData gftd; | ||||
| gftd.tot_pos_avg = 0; | gftd.pos_count = 0; | ||||
| zero_v3(gftd.pos_avg); | zero_v3(gftd.pos_avg); | ||||
| BKE_pbvh_parallel_range_settings(&settings, (sd->flags & SCULPT_USE_OPENMP), totnode); | BKE_pbvh_parallel_range_settings(&settings, (sd->flags & SCULPT_USE_OPENMP), totnode); | ||||
| settings.func_finalize = pose_brush_grow_factor_finalize; | settings.func_reduce = pose_brush_grow_factor_reduce; | ||||
| settings.userdata_chunk = &gftd; | settings.userdata_chunk = &gftd; | ||||
| settings.userdata_chunk_size = sizeof(PoseGrowFactorTLSData); | settings.userdata_chunk_size = sizeof(PoseGrowFactorTLSData); | ||||
| bool grow_next_iteration = true; | bool grow_next_iteration = true; | ||||
| float prev_len = FLT_MAX; | float prev_len = FLT_MAX; | ||||
| data.prev_mask = MEM_mallocN(sculpt_vertex_count_get(ss) * sizeof(float), "prev mask"); | data.prev_mask = MEM_mallocN(sculpt_vertex_count_get(ss) * sizeof(float), "prev mask"); | ||||
| while (grow_next_iteration) { | while (grow_next_iteration) { | ||||
| zero_v3(data.tot_pos_avg); | |||||
| data.tot_pos_count = 0; | |||||
| zero_v3(gftd.pos_avg); | zero_v3(gftd.pos_avg); | ||||
| gftd.tot_pos_avg = 0; | gftd.pos_count = 0; | ||||
| memcpy(data.prev_mask, pose_factor, sculpt_vertex_count_get(ss) * sizeof(float)); | memcpy(data.prev_mask, pose_factor, sculpt_vertex_count_get(ss) * sizeof(float)); | ||||
| BLI_task_parallel_range(0, totnode, &data, pose_brush_grow_factor_task_cb_ex, &settings); | BKE_pbvh_parallel_range(0, totnode, &data, pose_brush_grow_factor_task_cb_ex, &settings); | ||||
| if (data.tot_pos_count != 0) { | if (gftd.pos_count != 0) { | ||||
| mul_v3_fl(data.tot_pos_avg, 1.0f / (float)data.tot_pos_count); | mul_v3_fl(gftd.pos_avg, 1.0f / (float)gftd.pos_count); | ||||
| float len = len_v3v3(data.tot_pos_avg, pose_origin); | float len = len_v3v3(gftd.pos_avg, pose_origin); | ||||
| if (len < prev_len) { | if (len < prev_len) { | ||||
| prev_len = len; | prev_len = len; | ||||
| grow_next_iteration = true; | grow_next_iteration = true; | ||||
| } | } | ||||
| else { | else { | ||||
| grow_next_iteration = false; | grow_next_iteration = false; | ||||
| memcpy(pose_factor, data.prev_mask, sculpt_vertex_count_get(ss) * sizeof(float)); | memcpy(pose_factor, data.prev_mask, sculpt_vertex_count_get(ss) * sizeof(float)); | ||||
| } | } | ||||
| ▲ Show 20 Lines • Show All 152 Lines • ▼ Show 20 Lines | SculptThreadedTaskData data = { | ||||
| .sd = sd, | .sd = sd, | ||||
| .ob = ob, | .ob = ob, | ||||
| .brush = br, | .brush = br, | ||||
| .nodes = nodes, | .nodes = nodes, | ||||
| }; | }; | ||||
| /* Smooth the pose brush factor for cleaner deformation */ | /* Smooth the pose brush factor for cleaner deformation */ | ||||
| for (int i = 0; i < 4; i++) { | for (int i = 0; i < 4; i++) { | ||||
| TaskParallelSettings settings; | PBVHParallelSettings settings; | ||||
| BKE_pbvh_parallel_range_settings(&settings, (sd->flags & SCULPT_USE_OPENMP), totnode); | BKE_pbvh_parallel_range_settings(&settings, (sd->flags & SCULPT_USE_OPENMP), totnode); | ||||
| BLI_task_parallel_range(0, totnode, &data, pose_brush_init_task_cb_ex, &settings); | BKE_pbvh_parallel_range(0, totnode, &data, pose_brush_init_task_cb_ex, &settings); | ||||
| } | } | ||||
| MEM_SAFE_FREE(nodes); | MEM_SAFE_FREE(nodes); | ||||
| } | } | ||||
| static void do_nudge_brush_task_cb_ex(void *__restrict userdata, | static void do_nudge_brush_task_cb_ex(void *__restrict userdata, | ||||
| const int n, | const int n, | ||||
| const TaskParallelTLS *__restrict tls) | const TaskParallelTLS *__restrict tls) | ||||
| ▲ Show 20 Lines • Show All 51 Lines • ▼ Show 20 Lines | static void do_nudge_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnode) | ||||
| SculptThreadedTaskData data = { | SculptThreadedTaskData data = { | ||||
| .sd = sd, | .sd = sd, | ||||
| .ob = ob, | .ob = ob, | ||||
| .brush = brush, | .brush = brush, | ||||
| .nodes = nodes, | .nodes = nodes, | ||||
| .cono = cono, | .cono = cono, | ||||
| }; | }; | ||||
| TaskParallelSettings settings; | PBVHParallelSettings settings; | ||||
| BKE_pbvh_parallel_range_settings(&settings, (sd->flags & SCULPT_USE_OPENMP), totnode); | BKE_pbvh_parallel_range_settings(&settings, (sd->flags & SCULPT_USE_OPENMP), totnode); | ||||
| BLI_task_parallel_range(0, totnode, &data, do_nudge_brush_task_cb_ex, &settings); | BKE_pbvh_parallel_range(0, totnode, &data, do_nudge_brush_task_cb_ex, &settings); | ||||
| } | } | ||||
| static void do_snake_hook_brush_task_cb_ex(void *__restrict userdata, | static void do_snake_hook_brush_task_cb_ex(void *__restrict userdata, | ||||
| const int n, | const int n, | ||||
| const TaskParallelTLS *__restrict tls) | const TaskParallelTLS *__restrict tls) | ||||
| { | { | ||||
| SculptThreadedTaskData *data = userdata; | SculptThreadedTaskData *data = userdata; | ||||
| SculptSession *ss = data->ob->sculpt; | SculptSession *ss = data->ob->sculpt; | ||||
| ▲ Show 20 Lines • Show All 102 Lines • ▼ Show 20 Lines | SculptThreadedTaskData data = { | ||||
| .sd = sd, | .sd = sd, | ||||
| .ob = ob, | .ob = ob, | ||||
| .brush = brush, | .brush = brush, | ||||
| .nodes = nodes, | .nodes = nodes, | ||||
| .spvc = &spvc, | .spvc = &spvc, | ||||
| .grab_delta = grab_delta, | .grab_delta = grab_delta, | ||||
| }; | }; | ||||
| TaskParallelSettings settings; | PBVHParallelSettings settings; | ||||
| BKE_pbvh_parallel_range_settings(&settings, (sd->flags & SCULPT_USE_OPENMP), totnode); | BKE_pbvh_parallel_range_settings(&settings, (sd->flags & SCULPT_USE_OPENMP), totnode); | ||||
| BLI_task_parallel_range(0, totnode, &data, do_snake_hook_brush_task_cb_ex, &settings); | BKE_pbvh_parallel_range(0, totnode, &data, do_snake_hook_brush_task_cb_ex, &settings); | ||||
| } | } | ||||
| static void do_thumb_brush_task_cb_ex(void *__restrict userdata, | static void do_thumb_brush_task_cb_ex(void *__restrict userdata, | ||||
| const int n, | const int n, | ||||
| const TaskParallelTLS *__restrict tls) | const TaskParallelTLS *__restrict tls) | ||||
| { | { | ||||
| SculptThreadedTaskData *data = userdata; | SculptThreadedTaskData *data = userdata; | ||||
| SculptSession *ss = data->ob->sculpt; | SculptSession *ss = data->ob->sculpt; | ||||
| ▲ Show 20 Lines • Show All 53 Lines • ▼ Show 20 Lines | static void do_thumb_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnode) | ||||
| SculptThreadedTaskData data = { | SculptThreadedTaskData data = { | ||||
| .sd = sd, | .sd = sd, | ||||
| .ob = ob, | .ob = ob, | ||||
| .brush = brush, | .brush = brush, | ||||
| .nodes = nodes, | .nodes = nodes, | ||||
| .cono = cono, | .cono = cono, | ||||
| }; | }; | ||||
| TaskParallelSettings settings; | PBVHParallelSettings settings; | ||||
| BKE_pbvh_parallel_range_settings(&settings, (sd->flags & SCULPT_USE_OPENMP), totnode); | BKE_pbvh_parallel_range_settings(&settings, (sd->flags & SCULPT_USE_OPENMP), totnode); | ||||
| BLI_task_parallel_range(0, totnode, &data, do_thumb_brush_task_cb_ex, &settings); | BKE_pbvh_parallel_range(0, totnode, &data, do_thumb_brush_task_cb_ex, &settings); | ||||
| } | } | ||||
| static void do_rotate_brush_task_cb_ex(void *__restrict userdata, | static void do_rotate_brush_task_cb_ex(void *__restrict userdata, | ||||
| const int n, | const int n, | ||||
| const TaskParallelTLS *__restrict tls) | const TaskParallelTLS *__restrict tls) | ||||
| { | { | ||||
| SculptThreadedTaskData *data = userdata; | SculptThreadedTaskData *data = userdata; | ||||
| SculptSession *ss = data->ob->sculpt; | SculptSession *ss = data->ob->sculpt; | ||||
| ▲ Show 20 Lines • Show All 54 Lines • ▼ Show 20 Lines | static void do_rotate_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnode) | ||||
| SculptThreadedTaskData data = { | SculptThreadedTaskData data = { | ||||
| .sd = sd, | .sd = sd, | ||||
| .ob = ob, | .ob = ob, | ||||
| .brush = brush, | .brush = brush, | ||||
| .nodes = nodes, | .nodes = nodes, | ||||
| .angle = angle, | .angle = angle, | ||||
| }; | }; | ||||
| TaskParallelSettings settings; | PBVHParallelSettings settings; | ||||
| BKE_pbvh_parallel_range_settings(&settings, (sd->flags & SCULPT_USE_OPENMP), totnode); | BKE_pbvh_parallel_range_settings(&settings, (sd->flags & SCULPT_USE_OPENMP), totnode); | ||||
| BLI_task_parallel_range(0, totnode, &data, do_rotate_brush_task_cb_ex, &settings); | BKE_pbvh_parallel_range(0, totnode, &data, do_rotate_brush_task_cb_ex, &settings); | ||||
| } | } | ||||
| static void do_layer_brush_task_cb_ex(void *__restrict userdata, | static void do_layer_brush_task_cb_ex(void *__restrict userdata, | ||||
| const int n, | const int n, | ||||
| const TaskParallelTLS *__restrict tls) | const TaskParallelTLS *__restrict tls) | ||||
| { | { | ||||
| SculptThreadedTaskData *data = userdata; | SculptThreadedTaskData *data = userdata; | ||||
| SculptSession *ss = data->ob->sculpt; | SculptSession *ss = data->ob->sculpt; | ||||
| ▲ Show 20 Lines • Show All 78 Lines • ▼ Show 20 Lines | SculptThreadedTaskData data = { | ||||
| .sd = sd, | .sd = sd, | ||||
| .ob = ob, | .ob = ob, | ||||
| .brush = brush, | .brush = brush, | ||||
| .nodes = nodes, | .nodes = nodes, | ||||
| .offset = offset, | .offset = offset, | ||||
| }; | }; | ||||
| BLI_mutex_init(&data.mutex); | BLI_mutex_init(&data.mutex); | ||||
| TaskParallelSettings settings; | PBVHParallelSettings settings; | ||||
| BKE_pbvh_parallel_range_settings(&settings, (sd->flags & SCULPT_USE_OPENMP), totnode); | BKE_pbvh_parallel_range_settings(&settings, (sd->flags & SCULPT_USE_OPENMP), totnode); | ||||
| BLI_task_parallel_range(0, totnode, &data, do_layer_brush_task_cb_ex, &settings); | BKE_pbvh_parallel_range(0, totnode, &data, do_layer_brush_task_cb_ex, &settings); | ||||
| BLI_mutex_end(&data.mutex); | BLI_mutex_end(&data.mutex); | ||||
| } | } | ||||
| static void do_inflate_brush_task_cb_ex(void *__restrict userdata, | static void do_inflate_brush_task_cb_ex(void *__restrict userdata, | ||||
| const int n, | const int n, | ||||
| const TaskParallelTLS *__restrict tls) | const TaskParallelTLS *__restrict tls) | ||||
| { | { | ||||
| ▲ Show 20 Lines • Show All 49 Lines • ▼ Show 20 Lines | static void do_inflate_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnode) | ||||
| SculptThreadedTaskData data = { | SculptThreadedTaskData data = { | ||||
| .sd = sd, | .sd = sd, | ||||
| .ob = ob, | .ob = ob, | ||||
| .brush = brush, | .brush = brush, | ||||
| .nodes = nodes, | .nodes = nodes, | ||||
| }; | }; | ||||
| TaskParallelSettings settings; | PBVHParallelSettings settings; | ||||
| BKE_pbvh_parallel_range_settings(&settings, (sd->flags & SCULPT_USE_OPENMP), totnode); | BKE_pbvh_parallel_range_settings(&settings, (sd->flags & SCULPT_USE_OPENMP), totnode); | ||||
| BLI_task_parallel_range(0, totnode, &data, do_inflate_brush_task_cb_ex, &settings); | BKE_pbvh_parallel_range(0, totnode, &data, do_inflate_brush_task_cb_ex, &settings); | ||||
| } | } | ||||
| static void calc_sculpt_plane( | static void calc_sculpt_plane( | ||||
| Sculpt *sd, Object *ob, PBVHNode **nodes, int totnode, float r_area_no[3], float r_area_co[3]) | Sculpt *sd, Object *ob, PBVHNode **nodes, int totnode, float r_area_no[3], float r_area_co[3]) | ||||
| { | { | ||||
| SculptSession *ss = ob->sculpt; | SculptSession *ss = ob->sculpt; | ||||
| Brush *brush = BKE_paint_brush(&sd->paint); | Brush *brush = BKE_paint_brush(&sd->paint); | ||||
| ▲ Show 20 Lines • Show All 190 Lines • ▼ Show 20 Lines | SculptThreadedTaskData data = { | ||||
| .sd = sd, | .sd = sd, | ||||
| .ob = ob, | .ob = ob, | ||||
| .brush = brush, | .brush = brush, | ||||
| .nodes = nodes, | .nodes = nodes, | ||||
| .area_no = area_no, | .area_no = area_no, | ||||
| .area_co = area_co, | .area_co = area_co, | ||||
| }; | }; | ||||
| TaskParallelSettings settings; | PBVHParallelSettings settings; | ||||
| BKE_pbvh_parallel_range_settings(&settings, (sd->flags & SCULPT_USE_OPENMP), totnode); | BKE_pbvh_parallel_range_settings(&settings, (sd->flags & SCULPT_USE_OPENMP), totnode); | ||||
| BLI_task_parallel_range(0, totnode, &data, do_flatten_brush_task_cb_ex, &settings); | BKE_pbvh_parallel_range(0, totnode, &data, do_flatten_brush_task_cb_ex, &settings); | ||||
| } | } | ||||
| static void do_clay_brush_task_cb_ex(void *__restrict userdata, | static void do_clay_brush_task_cb_ex(void *__restrict userdata, | ||||
| const int n, | const int n, | ||||
| const TaskParallelTLS *__restrict tls) | const TaskParallelTLS *__restrict tls) | ||||
| { | { | ||||
| SculptThreadedTaskData *data = userdata; | SculptThreadedTaskData *data = userdata; | ||||
| SculptSession *ss = data->ob->sculpt; | SculptSession *ss = data->ob->sculpt; | ||||
| ▲ Show 20 Lines • Show All 79 Lines • ▼ Show 20 Lines | SculptThreadedTaskData data = { | ||||
| .sd = sd, | .sd = sd, | ||||
| .ob = ob, | .ob = ob, | ||||
| .brush = brush, | .brush = brush, | ||||
| .nodes = nodes, | .nodes = nodes, | ||||
| .area_no = area_no, | .area_no = area_no, | ||||
| .area_co = area_co, | .area_co = area_co, | ||||
| }; | }; | ||||
| TaskParallelSettings settings; | PBVHParallelSettings settings; | ||||
| BKE_pbvh_parallel_range_settings(&settings, (sd->flags & SCULPT_USE_OPENMP), totnode); | BKE_pbvh_parallel_range_settings(&settings, (sd->flags & SCULPT_USE_OPENMP), totnode); | ||||
| BLI_task_parallel_range(0, totnode, &data, do_clay_brush_task_cb_ex, &settings); | BKE_pbvh_parallel_range(0, totnode, &data, do_clay_brush_task_cb_ex, &settings); | ||||
| } | } | ||||
| static void do_clay_strips_brush_task_cb_ex(void *__restrict userdata, | static void do_clay_strips_brush_task_cb_ex(void *__restrict userdata, | ||||
| const int n, | const int n, | ||||
| const TaskParallelTLS *__restrict tls) | const TaskParallelTLS *__restrict tls) | ||||
| { | { | ||||
| SculptThreadedTaskData *data = userdata; | SculptThreadedTaskData *data = userdata; | ||||
| SculptSession *ss = data->ob->sculpt; | SculptSession *ss = data->ob->sculpt; | ||||
| ▲ Show 20 Lines • Show All 111 Lines • ▼ Show 20 Lines | SculptThreadedTaskData data = { | ||||
| .ob = ob, | .ob = ob, | ||||
| .brush = brush, | .brush = brush, | ||||
| .nodes = nodes, | .nodes = nodes, | ||||
| .area_no_sp = area_no_sp, | .area_no_sp = area_no_sp, | ||||
| .area_co = area_co, | .area_co = area_co, | ||||
| .mat = mat, | .mat = mat, | ||||
| }; | }; | ||||
| TaskParallelSettings settings; | PBVHParallelSettings settings; | ||||
| BKE_pbvh_parallel_range_settings(&settings, (sd->flags & SCULPT_USE_OPENMP), totnode); | BKE_pbvh_parallel_range_settings(&settings, (sd->flags & SCULPT_USE_OPENMP), totnode); | ||||
| BLI_task_parallel_range(0, totnode, &data, do_clay_strips_brush_task_cb_ex, &settings); | BKE_pbvh_parallel_range(0, totnode, &data, do_clay_strips_brush_task_cb_ex, &settings); | ||||
| } | } | ||||
| static void do_fill_brush_task_cb_ex(void *__restrict userdata, | static void do_fill_brush_task_cb_ex(void *__restrict userdata, | ||||
| const int n, | const int n, | ||||
| const TaskParallelTLS *__restrict tls) | const TaskParallelTLS *__restrict tls) | ||||
| { | { | ||||
| SculptThreadedTaskData *data = userdata; | SculptThreadedTaskData *data = userdata; | ||||
| SculptSession *ss = data->ob->sculpt; | SculptSession *ss = data->ob->sculpt; | ||||
| ▲ Show 20 Lines • Show All 74 Lines • ▼ Show 20 Lines | SculptThreadedTaskData data = { | ||||
| .sd = sd, | .sd = sd, | ||||
| .ob = ob, | .ob = ob, | ||||
| .brush = brush, | .brush = brush, | ||||
| .nodes = nodes, | .nodes = nodes, | ||||
| .area_no = area_no, | .area_no = area_no, | ||||
| .area_co = area_co, | .area_co = area_co, | ||||
| }; | }; | ||||
| TaskParallelSettings settings; | PBVHParallelSettings settings; | ||||
| BKE_pbvh_parallel_range_settings(&settings, (sd->flags & SCULPT_USE_OPENMP), totnode); | BKE_pbvh_parallel_range_settings(&settings, (sd->flags & SCULPT_USE_OPENMP), totnode); | ||||
| BLI_task_parallel_range(0, totnode, &data, do_fill_brush_task_cb_ex, &settings); | BKE_pbvh_parallel_range(0, totnode, &data, do_fill_brush_task_cb_ex, &settings); | ||||
| } | } | ||||
| static void do_scrape_brush_task_cb_ex(void *__restrict userdata, | static void do_scrape_brush_task_cb_ex(void *__restrict userdata, | ||||
| const int n, | const int n, | ||||
| const TaskParallelTLS *__restrict tls) | const TaskParallelTLS *__restrict tls) | ||||
| { | { | ||||
| SculptThreadedTaskData *data = userdata; | SculptThreadedTaskData *data = userdata; | ||||
| SculptSession *ss = data->ob->sculpt; | SculptSession *ss = data->ob->sculpt; | ||||
| ▲ Show 20 Lines • Show All 73 Lines • ▼ Show 20 Lines | SculptThreadedTaskData data = { | ||||
| .sd = sd, | .sd = sd, | ||||
| .ob = ob, | .ob = ob, | ||||
| .brush = brush, | .brush = brush, | ||||
| .nodes = nodes, | .nodes = nodes, | ||||
| .area_no = area_no, | .area_no = area_no, | ||||
| .area_co = area_co, | .area_co = area_co, | ||||
| }; | }; | ||||
| TaskParallelSettings settings; | PBVHParallelSettings settings; | ||||
| BKE_pbvh_parallel_range_settings(&settings, (sd->flags & SCULPT_USE_OPENMP), totnode); | BKE_pbvh_parallel_range_settings(&settings, (sd->flags & SCULPT_USE_OPENMP), totnode); | ||||
| BLI_task_parallel_range(0, totnode, &data, do_scrape_brush_task_cb_ex, &settings); | BKE_pbvh_parallel_range(0, totnode, &data, do_scrape_brush_task_cb_ex, &settings); | ||||
| } | } | ||||
| static void do_gravity_task_cb_ex(void *__restrict userdata, | static void do_gravity_task_cb_ex(void *__restrict userdata, | ||||
| const int n, | const int n, | ||||
| const TaskParallelTLS *__restrict tls) | const TaskParallelTLS *__restrict tls) | ||||
| { | { | ||||
| SculptThreadedTaskData *data = userdata; | SculptThreadedTaskData *data = userdata; | ||||
| SculptSession *ss = data->ob->sculpt; | SculptSession *ss = data->ob->sculpt; | ||||
| ▲ Show 20 Lines • Show All 50 Lines • ▼ Show 20 Lines | static void do_gravity(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnode, float bstrength) | ||||
| SculptThreadedTaskData data = { | SculptThreadedTaskData data = { | ||||
| .sd = sd, | .sd = sd, | ||||
| .ob = ob, | .ob = ob, | ||||
| .brush = brush, | .brush = brush, | ||||
| .nodes = nodes, | .nodes = nodes, | ||||
| .offset = offset, | .offset = offset, | ||||
| }; | }; | ||||
| TaskParallelSettings settings; | PBVHParallelSettings settings; | ||||
| BKE_pbvh_parallel_range_settings(&settings, (sd->flags & SCULPT_USE_OPENMP), totnode); | BKE_pbvh_parallel_range_settings(&settings, (sd->flags & SCULPT_USE_OPENMP), totnode); | ||||
| BLI_task_parallel_range(0, totnode, &data, do_gravity_task_cb_ex, &settings); | BKE_pbvh_parallel_range(0, totnode, &data, do_gravity_task_cb_ex, &settings); | ||||
| } | } | ||||
| void sculpt_vertcos_to_key(Object *ob, KeyBlock *kb, const float (*vertCos)[3]) | void sculpt_vertcos_to_key(Object *ob, KeyBlock *kb, const float (*vertCos)[3]) | ||||
| { | { | ||||
| Mesh *me = (Mesh *)ob->data; | Mesh *me = (Mesh *)ob->data; | ||||
| float(*ofs)[3] = NULL; | float(*ofs)[3] = NULL; | ||||
| int a; | int a; | ||||
| const int kb_act_idx = ob->shapenr - 1; | const int kb_act_idx = ob->shapenr - 1; | ||||
| ▲ Show 20 Lines • Show All 155 Lines • ▼ Show 20 Lines | if (totnode) { | ||||
| SculptThreadedTaskData task_data = { | SculptThreadedTaskData task_data = { | ||||
| .sd = sd, | .sd = sd, | ||||
| .ob = ob, | .ob = ob, | ||||
| .brush = brush, | .brush = brush, | ||||
| .nodes = nodes, | .nodes = nodes, | ||||
| }; | }; | ||||
| TaskParallelSettings settings; | PBVHParallelSettings settings; | ||||
| BKE_pbvh_parallel_range_settings(&settings, (sd->flags & SCULPT_USE_OPENMP), totnode); | BKE_pbvh_parallel_range_settings(&settings, (sd->flags & SCULPT_USE_OPENMP), totnode); | ||||
| BLI_task_parallel_range(0, totnode, &task_data, do_brush_action_task_cb, &settings); | BKE_pbvh_parallel_range(0, totnode, &task_data, do_brush_action_task_cb, &settings); | ||||
| if (sculpt_brush_needs_normal(ss, brush)) { | if (sculpt_brush_needs_normal(ss, brush)) { | ||||
| update_sculpt_normal(sd, ob, nodes, totnode); | update_sculpt_normal(sd, ob, nodes, totnode); | ||||
| } | } | ||||
| if (brush->mtex.brush_map_mode == MTEX_MAP_MODE_AREA) { | if (brush->mtex.brush_map_mode == MTEX_MAP_MODE_AREA) { | ||||
| update_brush_local_mat(sd, ob); | update_brush_local_mat(sd, ob); | ||||
| } | } | ||||
| ▲ Show 20 Lines • Show All 201 Lines • ▼ Show 20 Lines | static void sculpt_combine_proxies(Sculpt *sd, Object *ob) | ||||
| if (ss->cache->supports_gravity || (sculpt_tool_is_proxy_used(brush->sculpt_tool) == false)) { | if (ss->cache->supports_gravity || (sculpt_tool_is_proxy_used(brush->sculpt_tool) == false)) { | ||||
| SculptThreadedTaskData data = { | SculptThreadedTaskData data = { | ||||
| .sd = sd, | .sd = sd, | ||||
| .ob = ob, | .ob = ob, | ||||
| .brush = brush, | .brush = brush, | ||||
| .nodes = nodes, | .nodes = nodes, | ||||
| }; | }; | ||||
| TaskParallelSettings settings; | PBVHParallelSettings settings; | ||||
| BKE_pbvh_parallel_range_settings(&settings, (sd->flags & SCULPT_USE_OPENMP), totnode); | BKE_pbvh_parallel_range_settings(&settings, (sd->flags & SCULPT_USE_OPENMP), totnode); | ||||
| BLI_task_parallel_range(0, totnode, &data, sculpt_combine_proxies_task_cb, &settings); | BKE_pbvh_parallel_range(0, totnode, &data, sculpt_combine_proxies_task_cb, &settings); | ||||
| } | } | ||||
| MEM_SAFE_FREE(nodes); | MEM_SAFE_FREE(nodes); | ||||
| } | } | ||||
| /* copy the modified vertices from bvh to the active key */ | /* copy the modified vertices from bvh to the active key */ | ||||
| static void sculpt_update_keyblock(Object *ob) | static void sculpt_update_keyblock(Object *ob) | ||||
| { | { | ||||
| ▲ Show 20 Lines • Show All 71 Lines • ▼ Show 20 Lines | if (is_proxy_used) { | ||||
| SculptThreadedTaskData data = { | SculptThreadedTaskData data = { | ||||
| .sd = sd, | .sd = sd, | ||||
| .ob = ob, | .ob = ob, | ||||
| .brush = brush, | .brush = brush, | ||||
| .nodes = nodes, | .nodes = nodes, | ||||
| .vertCos = vertCos, | .vertCos = vertCos, | ||||
| }; | }; | ||||
| TaskParallelSettings settings; | PBVHParallelSettings settings; | ||||
| BKE_pbvh_parallel_range_settings(&settings, (sd->flags & SCULPT_USE_OPENMP), totnode); | BKE_pbvh_parallel_range_settings(&settings, (sd->flags & SCULPT_USE_OPENMP), totnode); | ||||
| BLI_task_parallel_range(0, totnode, &data, sculpt_flush_stroke_deform_task_cb, &settings); | BKE_pbvh_parallel_range(0, totnode, &data, sculpt_flush_stroke_deform_task_cb, &settings); | ||||
| if (vertCos) { | if (vertCos) { | ||||
| sculpt_vertcos_to_key(ob, ss->shapekey_active, vertCos); | sculpt_vertcos_to_key(ob, ss->shapekey_active, vertCos); | ||||
| MEM_freeN(vertCos); | MEM_freeN(vertCos); | ||||
| } | } | ||||
| MEM_SAFE_FREE(nodes); | MEM_SAFE_FREE(nodes); | ||||
| ▲ Show 20 Lines • Show All 2,568 Lines • ▼ Show 20 Lines | static void sculpt_filter_cache_init(Object *ob, Sculpt *sd) | ||||
| } | } | ||||
| SculptThreadedTaskData data = { | SculptThreadedTaskData data = { | ||||
| .sd = sd, | .sd = sd, | ||||
| .ob = ob, | .ob = ob, | ||||
| .nodes = ss->filter_cache->nodes, | .nodes = ss->filter_cache->nodes, | ||||
| }; | }; | ||||
| TaskParallelSettings settings; | PBVHParallelSettings settings; | ||||
| BKE_pbvh_parallel_range_settings( | BKE_pbvh_parallel_range_settings( | ||||
| &settings, (sd->flags & SCULPT_USE_OPENMP), ss->filter_cache->totnode); | &settings, (sd->flags & SCULPT_USE_OPENMP), ss->filter_cache->totnode); | ||||
| BLI_task_parallel_range( | BKE_pbvh_parallel_range( | ||||
| 0, ss->filter_cache->totnode, &data, filter_cache_init_task_cb, &settings); | 0, ss->filter_cache->totnode, &data, filter_cache_init_task_cb, &settings); | ||||
| } | } | ||||
| static void sculpt_filter_cache_free(SculptSession *ss) | static void sculpt_filter_cache_free(SculptSession *ss) | ||||
| { | { | ||||
| if (ss->filter_cache->nodes) { | if (ss->filter_cache->nodes) { | ||||
| MEM_freeN(ss->filter_cache->nodes); | MEM_freeN(ss->filter_cache->nodes); | ||||
| } | } | ||||
| ▲ Show 20 Lines • Show All 179 Lines • ▼ Show 20 Lines | static int sculpt_mesh_filter_modal(bContext *C, wmOperator *op, const wmEvent *event) | ||||
| SculptThreadedTaskData data = { | SculptThreadedTaskData data = { | ||||
| .sd = sd, | .sd = sd, | ||||
| .ob = ob, | .ob = ob, | ||||
| .nodes = ss->filter_cache->nodes, | .nodes = ss->filter_cache->nodes, | ||||
| .filter_type = filter_type, | .filter_type = filter_type, | ||||
| .filter_strength = filter_strength, | .filter_strength = filter_strength, | ||||
| }; | }; | ||||
| TaskParallelSettings settings; | PBVHParallelSettings settings; | ||||
| BKE_pbvh_parallel_range_settings( | BKE_pbvh_parallel_range_settings( | ||||
| &settings, (sd->flags & SCULPT_USE_OPENMP), ss->filter_cache->totnode); | &settings, (sd->flags & SCULPT_USE_OPENMP), ss->filter_cache->totnode); | ||||
| BLI_task_parallel_range(0, ss->filter_cache->totnode, &data, mesh_filter_task_cb, &settings); | BKE_pbvh_parallel_range(0, ss->filter_cache->totnode, &data, mesh_filter_task_cb, &settings); | ||||
| if (ss->deform_modifiers_active || ss->shapekey_active) { | if (ss->deform_modifiers_active || ss->shapekey_active) { | ||||
| sculpt_flush_stroke_deform(sd, ob, true); | sculpt_flush_stroke_deform(sd, ob, true); | ||||
| } | } | ||||
| sculpt_flush_update_step(C, SCULPT_UPDATE_COORDS); | sculpt_flush_update_step(C, SCULPT_UPDATE_COORDS); | ||||
| return OPERATOR_RUNNING_MODAL; | return OPERATOR_RUNNING_MODAL; | ||||
| ▲ Show 20 Lines • Show All 257 Lines • ▼ Show 20 Lines | for (int i = 0; i < iterations; i++) { | ||||
| SculptThreadedTaskData data = { | SculptThreadedTaskData data = { | ||||
| .sd = sd, | .sd = sd, | ||||
| .ob = ob, | .ob = ob, | ||||
| .nodes = nodes, | .nodes = nodes, | ||||
| .filter_type = filter_type, | .filter_type = filter_type, | ||||
| .prev_mask = prev_mask, | .prev_mask = prev_mask, | ||||
| }; | }; | ||||
| TaskParallelSettings settings; | PBVHParallelSettings settings; | ||||
| BKE_pbvh_parallel_range_settings(&settings, (sd->flags & SCULPT_USE_OPENMP), totnode); | BKE_pbvh_parallel_range_settings(&settings, (sd->flags & SCULPT_USE_OPENMP), totnode); | ||||
| BLI_task_parallel_range(0, totnode, &data, mask_filter_task_cb, &settings); | BKE_pbvh_parallel_range(0, totnode, &data, mask_filter_task_cb, &settings); | ||||
| if (ELEM(filter_type, MASK_FILTER_GROW, MASK_FILTER_SHRINK)) { | if (ELEM(filter_type, MASK_FILTER_GROW, MASK_FILTER_SHRINK)) { | ||||
| MEM_freeN(prev_mask); | MEM_freeN(prev_mask); | ||||
| } | } | ||||
| } | } | ||||
| MEM_SAFE_FREE(nodes); | MEM_SAFE_FREE(nodes); | ||||
| ▲ Show 20 Lines • Show All 92 Lines • ▼ Show 20 Lines | static void dirty_mask_compute_range_task_cb(void *__restrict userdata, | ||||
| { | { | ||||
| float dirty_mask = neighbor_dirty_mask(ss, &vd); | float dirty_mask = neighbor_dirty_mask(ss, &vd); | ||||
| range->min = min_ff(dirty_mask, range->min); | range->min = min_ff(dirty_mask, range->min); | ||||
| range->max = max_ff(dirty_mask, range->max); | range->max = max_ff(dirty_mask, range->max); | ||||
| } | } | ||||
| BKE_pbvh_vertex_iter_end; | BKE_pbvh_vertex_iter_end; | ||||
| } | } | ||||
| static void dirty_mask_compute_range_finalize(void *__restrict userdata, void *__restrict tls) | static void dirty_mask_compute_range_reduce(const void *__restrict UNUSED(userdata), | ||||
| { | void *__restrict chunk_join, | ||||
| SculptThreadedTaskData *data = userdata; | void *__restrict chunk) | ||||
| DirtyMaskRangeData *range = tls; | { | ||||
| DirtyMaskRangeData *join = chunk_join; | |||||
| data->dirty_mask_min = min_ff(range->min, data->dirty_mask_min); | DirtyMaskRangeData *range = chunk; | ||||
| data->dirty_mask_max = max_ff(range->max, data->dirty_mask_max); | join->min = min_ff(range->min, join->min); | ||||
| join->max = max_ff(range->max, join->max); | |||||
| } | } | ||||
| static void dirty_mask_apply_task_cb(void *__restrict userdata, | static void dirty_mask_apply_task_cb(void *__restrict userdata, | ||||
| const int i, | const int i, | ||||
| const TaskParallelTLS *__restrict UNUSED(tls)) | const TaskParallelTLS *__restrict UNUSED(tls)) | ||||
| { | { | ||||
| SculptThreadedTaskData *data = userdata; | SculptThreadedTaskData *data = userdata; | ||||
| SculptSession *ss = data->ob->sculpt; | SculptSession *ss = data->ob->sculpt; | ||||
| ▲ Show 20 Lines • Show All 54 Lines • ▼ Show 20 Lines | static int sculpt_dirty_mask_exec(bContext *C, wmOperator *op) | ||||
| for (int i = 0; i < totnode; i++) { | for (int i = 0; i < totnode; i++) { | ||||
| sculpt_undo_push_node(ob, nodes[i], SCULPT_UNDO_MASK); | sculpt_undo_push_node(ob, nodes[i], SCULPT_UNDO_MASK); | ||||
| } | } | ||||
| SculptThreadedTaskData data = { | SculptThreadedTaskData data = { | ||||
| .sd = sd, | .sd = sd, | ||||
| .ob = ob, | .ob = ob, | ||||
| .nodes = nodes, | .nodes = nodes, | ||||
| .dirty_mask_min = FLT_MAX, | |||||
| .dirty_mask_max = -FLT_MAX, | |||||
| .dirty_mask_dirty_only = RNA_boolean_get(op->ptr, "dirty_only"), | .dirty_mask_dirty_only = RNA_boolean_get(op->ptr, "dirty_only"), | ||||
| }; | }; | ||||
| DirtyMaskRangeData range = { | DirtyMaskRangeData range = { | ||||
| .min = FLT_MAX, | .min = FLT_MAX, | ||||
| .max = -FLT_MAX, | .max = -FLT_MAX, | ||||
| }; | }; | ||||
| TaskParallelSettings settings; | PBVHParallelSettings settings; | ||||
| BKE_pbvh_parallel_range_settings(&settings, (sd->flags & SCULPT_USE_OPENMP), totnode); | BKE_pbvh_parallel_range_settings(&settings, (sd->flags & SCULPT_USE_OPENMP), totnode); | ||||
| settings.func_finalize = dirty_mask_compute_range_finalize; | settings.func_reduce = dirty_mask_compute_range_reduce; | ||||
| settings.userdata_chunk = ⦥ | settings.userdata_chunk = ⦥ | ||||
| settings.userdata_chunk_size = sizeof(DirtyMaskRangeData); | settings.userdata_chunk_size = sizeof(DirtyMaskRangeData); | ||||
| BLI_task_parallel_range(0, totnode, &data, dirty_mask_compute_range_task_cb, &settings); | BKE_pbvh_parallel_range(0, totnode, &data, dirty_mask_compute_range_task_cb, &settings); | ||||
| BLI_task_parallel_range(0, totnode, &data, dirty_mask_apply_task_cb, &settings); | data.dirty_mask_min = range.min; | ||||
| data.dirty_mask_max = range.max; | |||||
| BKE_pbvh_parallel_range(0, totnode, &data, dirty_mask_apply_task_cb, &settings); | |||||
| MEM_SAFE_FREE(nodes); | MEM_SAFE_FREE(nodes); | ||||
| BKE_pbvh_update_vertex_data(pbvh, SCULPT_UPDATE_MASK); | BKE_pbvh_update_vertex_data(pbvh, SCULPT_UPDATE_MASK); | ||||
| sculpt_undo_push_end(); | sculpt_undo_push_end(); | ||||
| ED_region_tag_redraw(ar); | ED_region_tag_redraw(ar); | ||||
| ▲ Show 20 Lines • Show All 142 Lines • ▼ Show 20 Lines | SculptThreadedTaskData data = { | ||||
| .ob = ob, | .ob = ob, | ||||
| .nodes = ss->filter_cache->nodes, | .nodes = ss->filter_cache->nodes, | ||||
| .filter_type = MASK_FILTER_SMOOTH, | .filter_type = MASK_FILTER_SMOOTH, | ||||
| }; | }; | ||||
| int smooth_iterations = RNA_int_get(op->ptr, "smooth_iterations"); | int smooth_iterations = RNA_int_get(op->ptr, "smooth_iterations"); | ||||
| BKE_sculpt_update_object_for_edit(depsgraph, ob, true, false); | BKE_sculpt_update_object_for_edit(depsgraph, ob, true, false); | ||||
| for (int i = 0; i < smooth_iterations; i++) { | for (int i = 0; i < smooth_iterations; i++) { | ||||
| TaskParallelSettings settings; | PBVHParallelSettings settings; | ||||
| BKE_pbvh_parallel_range_settings( | BKE_pbvh_parallel_range_settings( | ||||
| &settings, (sd->flags & SCULPT_USE_OPENMP), ss->filter_cache->totnode); | &settings, (sd->flags & SCULPT_USE_OPENMP), ss->filter_cache->totnode); | ||||
| BLI_task_parallel_range(0, ss->filter_cache->totnode, &data, mask_filter_task_cb, &settings); | BKE_pbvh_parallel_range(0, ss->filter_cache->totnode, &data, mask_filter_task_cb, &settings); | ||||
| } | } | ||||
| /* Pivot position */ | /* Pivot position */ | ||||
| if (RNA_boolean_get(op->ptr, "update_pivot")) { | if (RNA_boolean_get(op->ptr, "update_pivot")) { | ||||
| const char symm = sd->paint.symmetry_flags & PAINT_SYMM_AXIS_ALL; | const char symm = sd->paint.symmetry_flags & PAINT_SYMM_AXIS_ALL; | ||||
| const float threshold = 0.2f; | const float threshold = 0.2f; | ||||
| float avg[3]; | float avg[3]; | ||||
| int total = 0; | int total = 0; | ||||
| ▲ Show 20 Lines • Show All 49 Lines • ▼ Show 20 Lines | SculptThreadedTaskData data = { | ||||
| .sd = sd, | .sd = sd, | ||||
| .ob = ob, | .ob = ob, | ||||
| .nodes = ss->filter_cache->nodes, | .nodes = ss->filter_cache->nodes, | ||||
| .mask_expand_update_it = mask_expand_update_it, | .mask_expand_update_it = mask_expand_update_it, | ||||
| .mask_expand_use_normals = RNA_boolean_get(op->ptr, "use_normals"), | .mask_expand_use_normals = RNA_boolean_get(op->ptr, "use_normals"), | ||||
| .mask_expand_invert_mask = RNA_boolean_get(op->ptr, "invert"), | .mask_expand_invert_mask = RNA_boolean_get(op->ptr, "invert"), | ||||
| .mask_expand_keep_prev_mask = RNA_boolean_get(op->ptr, "keep_previous_mask"), | .mask_expand_keep_prev_mask = RNA_boolean_get(op->ptr, "keep_previous_mask"), | ||||
| }; | }; | ||||
| TaskParallelSettings settings; | PBVHParallelSettings settings; | ||||
| BKE_pbvh_parallel_range_settings( | BKE_pbvh_parallel_range_settings( | ||||
| &settings, (sd->flags & SCULPT_USE_OPENMP), ss->filter_cache->totnode); | &settings, (sd->flags & SCULPT_USE_OPENMP), ss->filter_cache->totnode); | ||||
| BLI_task_parallel_range(0, ss->filter_cache->totnode, &data, sculpt_expand_task_cb, &settings); | BKE_pbvh_parallel_range(0, ss->filter_cache->totnode, &data, sculpt_expand_task_cb, &settings); | ||||
| ss->filter_cache->mask_update_current_it = mask_expand_update_it; | ss->filter_cache->mask_update_current_it = mask_expand_update_it; | ||||
| } | } | ||||
| sculpt_flush_update_step(C, SCULPT_UPDATE_MASK); | sculpt_flush_update_step(C, SCULPT_UPDATE_MASK); | ||||
| return OPERATOR_RUNNING_MODAL; | return OPERATOR_RUNNING_MODAL; | ||||
| } | } | ||||
| ▲ Show 20 Lines • Show All 132 Lines • ▼ Show 20 Lines | SculptThreadedTaskData data = { | ||||
| .sd = sd, | .sd = sd, | ||||
| .ob = ob, | .ob = ob, | ||||
| .nodes = ss->filter_cache->nodes, | .nodes = ss->filter_cache->nodes, | ||||
| .mask_expand_update_it = 0, | .mask_expand_update_it = 0, | ||||
| .mask_expand_use_normals = RNA_boolean_get(op->ptr, "use_normals"), | .mask_expand_use_normals = RNA_boolean_get(op->ptr, "use_normals"), | ||||
| .mask_expand_invert_mask = RNA_boolean_get(op->ptr, "invert"), | .mask_expand_invert_mask = RNA_boolean_get(op->ptr, "invert"), | ||||
| .mask_expand_keep_prev_mask = RNA_boolean_get(op->ptr, "keep_previous_mask"), | .mask_expand_keep_prev_mask = RNA_boolean_get(op->ptr, "keep_previous_mask"), | ||||
| }; | }; | ||||
| TaskParallelSettings settings; | PBVHParallelSettings settings; | ||||
| BKE_pbvh_parallel_range_settings( | BKE_pbvh_parallel_range_settings( | ||||
| &settings, (sd->flags & SCULPT_USE_OPENMP), ss->filter_cache->totnode); | &settings, (sd->flags & SCULPT_USE_OPENMP), ss->filter_cache->totnode); | ||||
| BLI_task_parallel_range(0, ss->filter_cache->totnode, &data, sculpt_expand_task_cb, &settings); | BKE_pbvh_parallel_range(0, ss->filter_cache->totnode, &data, sculpt_expand_task_cb, &settings); | ||||
| const char *status_str = TIP_( | const char *status_str = TIP_( | ||||
| "Move the mouse to expand the mask from the active vertex. LBM: confirm mask, ESC/RMB: " | "Move the mouse to expand the mask from the active vertex. LBM: confirm mask, ESC/RMB: " | ||||
| "cancel"); | "cancel"); | ||||
| ED_workspace_status_text(C, status_str); | ED_workspace_status_text(C, status_str); | ||||
| sculpt_flush_update_step(C, SCULPT_UPDATE_MASK); | sculpt_flush_update_step(C, SCULPT_UPDATE_MASK); | ||||
| WM_event_add_modal_handler(C, op); | WM_event_add_modal_handler(C, op); | ||||
| ▲ Show 20 Lines • Show All 297 Lines • ▼ Show 20 Lines | for (int i = 0; i < 8; i++) { | ||||
| /* Final transform matrix */ | /* Final transform matrix */ | ||||
| mul_m4_m4m4(transform_mat, r_mat, t_mat); | mul_m4_m4m4(transform_mat, r_mat, t_mat); | ||||
| mul_m4_m4m4(transform_mat, transform_mat, s_mat); | mul_m4_m4m4(transform_mat, transform_mat, s_mat); | ||||
| mul_m4_m4m4(data.transform_mats[i], transform_mat, pivot_imat); | mul_m4_m4m4(data.transform_mats[i], transform_mat, pivot_imat); | ||||
| mul_m4_m4m4(data.transform_mats[i], pivot_mat, data.transform_mats[i]); | mul_m4_m4m4(data.transform_mats[i], pivot_mat, data.transform_mats[i]); | ||||
| } | } | ||||
| TaskParallelSettings settings; | PBVHParallelSettings settings; | ||||
| BKE_pbvh_parallel_range_settings( | BKE_pbvh_parallel_range_settings( | ||||
| &settings, (sd->flags & SCULPT_USE_OPENMP), ss->filter_cache->totnode); | &settings, (sd->flags & SCULPT_USE_OPENMP), ss->filter_cache->totnode); | ||||
| BLI_task_parallel_range( | BKE_pbvh_parallel_range( | ||||
| 0, ss->filter_cache->totnode, &data, sculpt_transform_task_cb, &settings); | 0, ss->filter_cache->totnode, &data, sculpt_transform_task_cb, &settings); | ||||
| if (ss->deform_modifiers_active || ss->shapekey_active) { | if (ss->deform_modifiers_active || ss->shapekey_active) { | ||||
| sculpt_flush_stroke_deform(sd, ob, true); | sculpt_flush_stroke_deform(sd, ob, true); | ||||
| } | } | ||||
| sculpt_flush_update_step(C, SCULPT_UPDATE_COORDS); | sculpt_flush_update_step(C, SCULPT_UPDATE_COORDS); | ||||
| } | } | ||||
| ▲ Show 20 Lines • Show All 177 Lines • Show Last 20 Lines | |||||