Cleanup: Use Vector for passing lists of PBVHNodes around

Cleaned up sculpt code to store lists of `PBVHNodes` with
`blender::Vector` instead of simple pointer arrays.  This is much
simpler and eliminates memory leaks caused by forgetting to free
the result of `BKE_pbvh_search_gather`.

Notes:

* `BKE_pbvh_search_gather` is now `blender::pbvh::search_gather`.
* `FilterCache` and `ExpandCache` have ownership over their .nodes
  members; as a result they're no longer pure C structs and
  are allocated with `MEM_new`/`MEM_delete`.
* The word 'totnode' no longer occurs anywhere in
  `source/blender/editors/sculpt_paint`

Todo (not for this PR): create a new properly C++ task API for sculpt
      (with lambdas) and use it for brushes.

Pull Request: https://projects.blender.org/blender/blender/pulls/106884
This commit is contained in:
Joseph Eagar
2023-04-14 21:16:42 +02:00
committed by Joseph Eagar
parent 15683d81be
commit b86fc55d30
30 changed files with 824 additions and 1081 deletions

View File

@@ -12,6 +12,7 @@
#include "BLI_ghash.h"
#ifdef __cplusplus
# include "BLI_offset_indices.hh"
# include "BLI_vector.hh"
#endif
#include "bmesh.h"
@@ -320,7 +321,8 @@ void BKE_pbvh_free(PBVH *pbvh);
/* Hierarchical Search in the BVH, two methods:
* - For each hit calling a callback.
* - Gather nodes in an array (easy to multi-thread). */
* - Gather nodes in an array (easy to multi-thread) see blender::bke::pbvh::search_gather.
*/
void BKE_pbvh_search_callback(PBVH *pbvh,
BKE_pbvh_SearchCallback scb,
@@ -328,14 +330,6 @@ void BKE_pbvh_search_callback(PBVH *pbvh,
BKE_pbvh_HitCallback hcb,
void *hit_data);
void BKE_pbvh_search_gather(
PBVH *pbvh, BKE_pbvh_SearchCallback scb, void *search_data, PBVHNode ***array, int *tot);
void BKE_pbvh_search_gather_ex(PBVH *pbvh,
BKE_pbvh_SearchCallback scb,
void *search_data,
PBVHNode ***r_array,
int *r_tot,
PBVHNodeFlags leaf_flag);
/* Ray-cast
* the hit callback is called for all leaf nodes intersecting the ray;
* it's up to the callback to find the primitive within the leaves that is
@@ -748,7 +742,6 @@ void BKE_pbvh_face_iter_finish(PBVHFaceIter *fd);
void BKE_pbvh_node_get_proxies(PBVHNode *node, PBVHProxyNode **proxies, int *proxy_count);
void BKE_pbvh_node_free_proxies(PBVHNode *node);
PBVHProxyNode *BKE_pbvh_node_add_proxy(PBVH *pbvh, PBVHNode *node);
void BKE_pbvh_gather_proxies(PBVH *pbvh, PBVHNode ***r_array, int *r_tot);
void BKE_pbvh_node_get_bm_orco_data(PBVHNode *node,
int (**r_orco_tris)[3],
int *r_orco_tris_num,
@@ -826,4 +819,13 @@ int BKE_pbvh_debug_draw_gen_get(PBVHNode *node);
#ifdef __cplusplus
}
namespace blender::bke::pbvh {
Vector<PBVHNode *> search_gather(PBVH *pbvh,
BKE_pbvh_SearchCallback scb,
void *search_data,
PBVHNodeFlags leaf_flag = PBVH_Leaf);
Vector<PBVHNode *> gather_proxies(PBVH *pbvh);
} // namespace blender::bke::pbvh
#endif

View File

@@ -27,6 +27,7 @@
#include "BLI_math_vector.h"
#include "BLI_string_utf8.h"
#include "BLI_utildefines.h"
#include "BLI_vector.hh"
#include "BLT_translation.h"
@@ -70,6 +71,7 @@
using blender::float3;
using blender::MutableSpan;
using blender::Span;
using blender::Vector;
static void sculpt_attribute_update_refs(Object *ob);
static SculptAttribute *sculpt_attribute_ensure_ex(Object *ob,
@@ -1891,16 +1893,11 @@ void BKE_sculpt_update_object_before_eval(Object *ob_eval)
BKE_sculptsession_free_vwpaint_data(ob_eval->sculpt);
}
else {
PBVHNode **nodes;
int n, totnode;
Vector<PBVHNode *> nodes = blender::bke::pbvh::search_gather(ss->pbvh, nullptr, nullptr);
BKE_pbvh_search_gather(ss->pbvh, nullptr, nullptr, &nodes, &totnode);
for (n = 0; n < totnode; n++) {
BKE_pbvh_node_mark_update(nodes[n]);
for (PBVHNode *node : nodes) {
BKE_pbvh_node_mark_update(node);
}
MEM_freeN(nodes);
}
}
}

View File

@@ -14,6 +14,7 @@
#include "BLI_rand.h"
#include "BLI_task.h"
#include "BLI_utildefines.h"
#include "BLI_vector.hh"
#include "DNA_mesh_types.h"
#include "DNA_meshdata_types.h"
@@ -39,6 +40,7 @@
using blender::float3;
using blender::MutableSpan;
using blender::Span;
using blender::Vector;
#define LEAF_LIMIT 10000
@@ -1225,70 +1227,6 @@ static PBVHNode *pbvh_iter_next_occluded(PBVHIter *iter)
return nullptr;
}
void BKE_pbvh_search_gather_ex(PBVH *pbvh,
BKE_pbvh_SearchCallback scb,
void *search_data,
PBVHNode ***r_array,
int *r_tot,
PBVHNodeFlags leaf_flag)
{
PBVHIter iter;
PBVHNode **array = nullptr, *node;
int tot = 0, space = 0;
pbvh_iter_begin(&iter, pbvh, scb, search_data);
while ((node = pbvh_iter_next(&iter, leaf_flag))) {
if (node->flag & leaf_flag) {
if (UNLIKELY(tot == space)) {
/* resize array if needed */
space = (tot == 0) ? 32 : space * 2;
array = static_cast<PBVHNode **>(
MEM_recallocN_id(array, sizeof(PBVHNode *) * space, __func__));
}
array[tot] = node;
tot++;
}
}
pbvh_iter_end(&iter);
if (tot == 0 && array) {
MEM_freeN(array);
array = nullptr;
}
*r_array = array;
*r_tot = tot;
}
void BKE_pbvh_search_gather(
PBVH *pbvh, BKE_pbvh_SearchCallback scb, void *search_data, PBVHNode ***r_array, int *r_tot)
{
BKE_pbvh_search_gather_ex(pbvh, scb, search_data, r_array, r_tot, PBVH_Leaf);
}
void BKE_pbvh_search_callback(PBVH *pbvh,
BKE_pbvh_SearchCallback scb,
void *search_data,
BKE_pbvh_HitCallback hcb,
void *hit_data)
{
PBVHIter iter;
PBVHNode *node;
pbvh_iter_begin(&iter, pbvh, scb, search_data);
while ((node = pbvh_iter_next(&iter, PBVH_Leaf))) {
if (node->flag & PBVH_Leaf) {
hcb(node, hit_data);
}
}
pbvh_iter_end(&iter);
}
struct node_tree {
PBVHNode *data;
@@ -1352,6 +1290,26 @@ float BKE_pbvh_node_get_tmin(PBVHNode *node)
return node->tmin;
}
void BKE_pbvh_search_callback(PBVH *pbvh,
BKE_pbvh_SearchCallback scb,
void *search_data,
BKE_pbvh_HitCallback hcb,
void *hit_data)
{
PBVHIter iter;
PBVHNode *node;
pbvh_iter_begin(&iter, pbvh, scb, search_data);
while ((node = pbvh_iter_next(&iter, PBVH_Leaf))) {
if (node->flag & PBVH_Leaf) {
hcb(node, hit_data);
}
}
pbvh_iter_end(&iter);
}
static void BKE_pbvh_search_callback_occluded(PBVH *pbvh,
BKE_pbvh_SearchCallback scb,
void *search_data,
@@ -1404,14 +1362,15 @@ static bool update_search_cb(PBVHNode *node, void *data_v)
struct PBVHUpdateData {
PBVH *pbvh;
PBVHNode **nodes;
int totnode;
Span<PBVHNode *> nodes;
float (*vert_normals)[3];
int flag;
bool show_sculpt_face_sets;
PBVHAttrReq *attrs;
int attrs_num;
float (*vert_normals)[3] = nullptr;
int flag = 0;
bool show_sculpt_face_sets = false;
PBVHAttrReq *attrs = nullptr;
int attrs_num = 0;
PBVHUpdateData(PBVH *pbvh_, Span<PBVHNode *> nodes_) : pbvh(pbvh_), nodes(nodes_) {}
};
static void pbvh_update_normals_clear_task_cb(void *__restrict userdata,
@@ -1515,7 +1474,7 @@ static void pbvh_update_normals_store_task_cb(void *__restrict userdata,
}
}
static void pbvh_faces_update_normals(PBVH *pbvh, PBVHNode **nodes, int totnode)
static void pbvh_faces_update_normals(PBVH *pbvh, Span<PBVHNode *> nodes)
{
/* subtle assumptions:
* - We know that for all edited vertices, the nodes with faces
@@ -1527,18 +1486,18 @@ static void pbvh_faces_update_normals(PBVH *pbvh, PBVHNode **nodes, int totnode)
* can only update vertices marked in the `vert_bitmap`.
*/
PBVHUpdateData data{};
PBVHUpdateData data(pbvh, nodes);
data.pbvh = pbvh;
data.nodes = nodes;
data.vert_normals = pbvh->vert_normals;
TaskParallelSettings settings;
BKE_pbvh_parallel_range_settings(&settings, true, totnode);
BKE_pbvh_parallel_range_settings(&settings, true, nodes.size());
/* Zero normals before accumulation. */
BLI_task_parallel_range(0, totnode, &data, pbvh_update_normals_clear_task_cb, &settings);
BLI_task_parallel_range(0, totnode, &data, pbvh_update_normals_accum_task_cb, &settings);
BLI_task_parallel_range(0, totnode, &data, pbvh_update_normals_store_task_cb, &settings);
BLI_task_parallel_range(0, nodes.size(), &data, pbvh_update_normals_clear_task_cb, &settings);
BLI_task_parallel_range(0, nodes.size(), &data, pbvh_update_normals_accum_task_cb, &settings);
BLI_task_parallel_range(0, nodes.size(), &data, pbvh_update_normals_store_task_cb, &settings);
}
static void pbvh_update_mask_redraw_task_cb(void *__restrict userdata,
@@ -1577,16 +1536,16 @@ static void pbvh_update_mask_redraw_task_cb(void *__restrict userdata,
}
}
static void pbvh_update_mask_redraw(PBVH *pbvh, PBVHNode **nodes, int totnode, int flag)
static void pbvh_update_mask_redraw(PBVH *pbvh, Span<PBVHNode *> nodes, int flag)
{
PBVHUpdateData data{};
PBVHUpdateData data(pbvh, nodes);
data.pbvh = pbvh;
data.nodes = nodes;
data.flag = flag;
TaskParallelSettings settings;
BKE_pbvh_parallel_range_settings(&settings, true, totnode);
BLI_task_parallel_range(0, totnode, &data, pbvh_update_mask_redraw_task_cb, &settings);
BKE_pbvh_parallel_range_settings(&settings, true, nodes.size());
BLI_task_parallel_range(0, nodes.size(), &data, pbvh_update_mask_redraw_task_cb, &settings);
}
static void pbvh_update_visibility_redraw_task_cb(void *__restrict userdata,
@@ -1613,16 +1572,17 @@ static void pbvh_update_visibility_redraw_task_cb(void *__restrict userdata,
}
}
static void pbvh_update_visibility_redraw(PBVH *pbvh, PBVHNode **nodes, int totnode, int flag)
static void pbvh_update_visibility_redraw(PBVH *pbvh, Span<PBVHNode *> nodes, int flag)
{
PBVHUpdateData data{};
PBVHUpdateData data(pbvh, nodes);
data.pbvh = pbvh;
data.nodes = nodes;
data.flag = flag;
TaskParallelSettings settings;
BKE_pbvh_parallel_range_settings(&settings, true, totnode);
BLI_task_parallel_range(0, totnode, &data, pbvh_update_visibility_redraw_task_cb, &settings);
BKE_pbvh_parallel_range_settings(&settings, true, nodes.size());
BLI_task_parallel_range(
0, nodes.size(), &data, pbvh_update_visibility_redraw_task_cb, &settings);
}
static void pbvh_update_BB_redraw_task_cb(void *__restrict userdata,
@@ -1649,17 +1609,15 @@ static void pbvh_update_BB_redraw_task_cb(void *__restrict userdata,
}
}
void pbvh_update_BB_redraw(PBVH *pbvh, PBVHNode **nodes, int totnode, int flag)
static void pbvh_update_BB_redraw(PBVH *pbvh, Span<PBVHNode *> nodes, int flag)
{
/* update BB, redraw flag */
PBVHUpdateData data{};
data.pbvh = pbvh;
data.nodes = nodes;
PBVHUpdateData data(pbvh, nodes);
data.flag = flag;
TaskParallelSettings settings;
BKE_pbvh_parallel_range_settings(&settings, true, totnode);
BLI_task_parallel_range(0, totnode, &data, pbvh_update_BB_redraw_task_cb, &settings);
BKE_pbvh_parallel_range_settings(&settings, true, nodes.size());
BLI_task_parallel_range(0, nodes.size(), &data, pbvh_update_BB_redraw_task_cb, &settings);
}
bool BKE_pbvh_get_color_layer(const Mesh *me, CustomDataLayer **r_layer, eAttrDomain *r_attr)
@@ -1724,7 +1682,7 @@ void pbvh_free_draw_buffers(PBVH * /*pbvh*/, PBVHNode *node)
}
}
static void pbvh_update_draw_buffers(PBVH *pbvh, PBVHNode **nodes, int totnode, int update_flag)
static void pbvh_update_draw_buffers(PBVH *pbvh, Span<PBVHNode *> nodes, int update_flag)
{
const CustomData *vdata;
@@ -1748,8 +1706,7 @@ static void pbvh_update_draw_buffers(PBVH *pbvh, PBVHNode **nodes, int totnode,
if ((update_flag & PBVH_RebuildDrawBuffers) || ELEM(pbvh->header.type, PBVH_GRIDS, PBVH_BMESH)) {
/* Free buffers uses OpenGL, so not in parallel. */
for (int n = 0; n < totnode; n++) {
PBVHNode *node = nodes[n];
for (PBVHNode *node : nodes) {
if (node->flag & PBVH_RebuildDrawBuffers) {
pbvh_free_draw_buffers(pbvh, node);
}
@@ -1763,17 +1720,13 @@ static void pbvh_update_draw_buffers(PBVH *pbvh, PBVHNode **nodes, int totnode,
}
/* Parallel creation and update of draw buffers. */
PBVHUpdateData data{};
data.pbvh = pbvh;
data.nodes = nodes;
PBVHUpdateData data(pbvh, nodes);
TaskParallelSettings settings;
BKE_pbvh_parallel_range_settings(&settings, true, totnode);
BLI_task_parallel_range(0, totnode, &data, pbvh_update_draw_buffer_cb, &settings);
for (int i = 0; i < totnode; i++) {
PBVHNode *node = nodes[i];
BKE_pbvh_parallel_range_settings(&settings, true, nodes.size());
BLI_task_parallel_range(0, nodes.size(), &data, pbvh_update_draw_buffer_cb, &settings);
for (PBVHNode *node : nodes) {
if (node->flag & PBVH_UpdateDrawBuffers) {
/* Flush buffers uses OpenGL, so not in parallel. */
@@ -1824,20 +1777,16 @@ void BKE_pbvh_update_bounds(PBVH *pbvh, int flag)
return;
}
PBVHNode **nodes;
int totnode;
BKE_pbvh_search_gather(pbvh, update_search_cb, POINTER_FROM_INT(flag), &nodes, &totnode);
Vector<PBVHNode *> nodes = blender::bke::pbvh::search_gather(
pbvh, update_search_cb, POINTER_FROM_INT(flag));
if (flag & (PBVH_UpdateBB | PBVH_UpdateOriginalBB | PBVH_UpdateRedraw)) {
pbvh_update_BB_redraw(pbvh, nodes, totnode, flag);
pbvh_update_BB_redraw(pbvh, nodes, flag);
}
if (flag & (PBVH_UpdateBB | PBVH_UpdateOriginalBB)) {
pbvh_flush_bb(pbvh, pbvh->nodes, flag);
}
MEM_SAFE_FREE(nodes);
}
void BKE_pbvh_update_vertex_data(PBVH *pbvh, int flag)
@@ -1846,27 +1795,21 @@ void BKE_pbvh_update_vertex_data(PBVH *pbvh, int flag)
return;
}
PBVHNode **nodes;
int totnode;
BKE_pbvh_search_gather(pbvh, update_search_cb, POINTER_FROM_INT(flag), &nodes, &totnode);
Vector<PBVHNode *> nodes = blender::bke::pbvh::search_gather(
pbvh, update_search_cb, POINTER_FROM_INT(flag));
if (flag & (PBVH_UpdateMask)) {
pbvh_update_mask_redraw(pbvh, nodes, totnode, flag);
pbvh_update_mask_redraw(pbvh, nodes, flag);
}
if (flag & (PBVH_UpdateColor)) {
for (int i = 0; i < totnode; i++) {
nodes[i]->flag |= PBVH_UpdateRedraw | PBVH_UpdateDrawBuffers | PBVH_UpdateColor;
for (PBVHNode *node : nodes) {
node->flag |= PBVH_UpdateRedraw | PBVH_UpdateDrawBuffers | PBVH_UpdateColor;
}
}
if (flag & (PBVH_UpdateVisibility)) {
pbvh_update_visibility_redraw(pbvh, nodes, totnode, flag);
}
if (nodes) {
MEM_freeN(nodes);
pbvh_update_visibility_redraw(pbvh, nodes, flag);
}
}
@@ -1973,15 +1916,14 @@ static void pbvh_update_visibility_task_cb(void *__restrict userdata,
}
}
static void pbvh_update_visibility(PBVH *pbvh, PBVHNode **nodes, int totnode)
static void pbvh_update_visibility(PBVH *pbvh, Span<PBVHNode *> nodes)
{
PBVHUpdateData data{};
PBVHUpdateData data(pbvh, nodes);
data.pbvh = pbvh;
data.nodes = nodes;
TaskParallelSettings settings;
BKE_pbvh_parallel_range_settings(&settings, true, totnode);
BLI_task_parallel_range(0, totnode, &data, pbvh_update_visibility_task_cb, &settings);
BKE_pbvh_parallel_range_settings(&settings, true, nodes.size());
BLI_task_parallel_range(0, nodes.size(), &data, pbvh_update_visibility_task_cb, &settings);
}
void BKE_pbvh_update_visibility(PBVH *pbvh)
@@ -1990,16 +1932,10 @@ void BKE_pbvh_update_visibility(PBVH *pbvh)
return;
}
PBVHNode **nodes;
int totnode;
Vector<PBVHNode *> nodes = blender::bke::pbvh::search_gather(
pbvh, update_search_cb, POINTER_FROM_INT(PBVH_UpdateVisibility));
BKE_pbvh_search_gather(
pbvh, update_search_cb, POINTER_FROM_INT(PBVH_UpdateVisibility), &nodes, &totnode);
pbvh_update_visibility(pbvh, nodes, totnode);
if (nodes) {
MEM_freeN(nodes);
}
pbvh_update_visibility(pbvh, nodes);
}
void BKE_pbvh_redraw_BB(PBVH *pbvh, float bb_min[3], float bb_max[3])
@@ -3095,18 +3031,15 @@ bool BKE_pbvh_node_frustum_exclude_AABB(PBVHNode *node, void *data)
void BKE_pbvh_update_normals(PBVH *pbvh, SubdivCCG *subdiv_ccg)
{
/* Update normals */
PBVHNode **nodes;
int totnode;
Vector<PBVHNode *> nodes = blender::bke::pbvh::search_gather(
pbvh, update_search_cb, POINTER_FROM_INT(PBVH_UpdateNormals));
BKE_pbvh_search_gather(
pbvh, update_search_cb, POINTER_FROM_INT(PBVH_UpdateNormals), &nodes, &totnode);
if (totnode > 0) {
if (!nodes.is_empty()) {
if (pbvh->header.type == PBVH_BMESH) {
pbvh_bmesh_normals_update(nodes, totnode);
pbvh_bmesh_normals_update(nodes);
}
else if (pbvh->header.type == PBVH_FACES) {
pbvh_faces_update_normals(pbvh, nodes, totnode);
pbvh_faces_update_normals(pbvh, nodes);
}
else if (pbvh->header.type == PBVH_GRIDS) {
CCGFace **faces;
@@ -3118,8 +3051,6 @@ void BKE_pbvh_update_normals(PBVH *pbvh, SubdivCCG *subdiv_ccg)
}
}
}
MEM_SAFE_FREE(nodes);
}
void BKE_pbvh_face_sets_color_set(PBVH *pbvh, int seed, int color_default)
@@ -3160,8 +3091,7 @@ void BKE_pbvh_draw_cb(PBVH *pbvh,
PBVHAttrReq *attrs,
int attrs_num)
{
PBVHNode **nodes;
int totnode;
Vector<PBVHNode *> nodes;
int update_flag = 0;
pbvh->draw_cache_invalid = false;
@@ -3174,41 +3104,37 @@ void BKE_pbvh_draw_cb(PBVH *pbvh,
data.accum_update_flag = 0;
data.attrs = attrs;
data.attrs_num = attrs_num;
BKE_pbvh_search_gather(pbvh, pbvh_draw_search_cb, &data, &nodes, &totnode);
nodes = blender::bke::pbvh::search_gather(pbvh, pbvh_draw_search_cb, &data);
update_flag = data.accum_update_flag;
}
else {
/* Get all nodes with draw updates, also those outside the view. */
const int search_flag = PBVH_RebuildDrawBuffers | PBVH_UpdateDrawBuffers;
BKE_pbvh_search_gather(
pbvh, update_search_cb, POINTER_FROM_INT(search_flag), &nodes, &totnode);
nodes = blender::bke::pbvh::search_gather(
pbvh, update_search_cb, POINTER_FROM_INT(search_flag));
update_flag = PBVH_RebuildDrawBuffers | PBVH_UpdateDrawBuffers;
}
/* Update draw buffers. */
if (totnode != 0 && (update_flag & (PBVH_RebuildDrawBuffers | PBVH_UpdateDrawBuffers))) {
pbvh_update_draw_buffers(pbvh, nodes, totnode, update_flag);
if (!nodes.is_empty() && (update_flag & (PBVH_RebuildDrawBuffers | PBVH_UpdateDrawBuffers))) {
pbvh_update_draw_buffers(pbvh, nodes, update_flag);
}
MEM_SAFE_FREE(nodes);
/* Draw visible nodes. */
PBVHDrawSearchData draw_data{};
draw_data.frustum = draw_frustum;
draw_data.accum_update_flag = 0;
BKE_pbvh_search_gather(pbvh, pbvh_draw_search_cb, &draw_data, &nodes, &totnode);
nodes = blender::bke::pbvh::search_gather(pbvh, pbvh_draw_search_cb, &draw_data);
PBVH_GPU_Args args;
for (int i = 0; i < totnode; i++) {
PBVHNode *node = nodes[i];
for (PBVHNode *node : nodes) {
if (!(node->flag & PBVH_FullyHidden)) {
pbvh_draw_args_init(pbvh, &args, node);
draw_fn(user_data, node->draw_batches, &args);
}
}
MEM_SAFE_FREE(nodes);
}
void BKE_pbvh_draw_debug_cb(PBVH *pbvh,
@@ -3357,36 +3283,6 @@ void BKE_pbvh_node_free_proxies(PBVHNode *node)
node->proxy_count = 0;
}
void BKE_pbvh_gather_proxies(PBVH *pbvh, PBVHNode ***r_array, int *r_tot)
{
PBVHNode **array = nullptr;
int tot = 0, space = 0;
for (int n = 0; n < pbvh->totnode; n++) {
PBVHNode *node = pbvh->nodes + n;
if (node->proxy_count > 0) {
if (tot == space) {
/* resize array if needed */
space = (tot == 0) ? 32 : space * 2;
array = static_cast<PBVHNode **>(
MEM_recallocN_id(array, sizeof(PBVHNode *) * space, __func__));
}
array[tot] = node;
tot++;
}
}
if (tot == 0 && array) {
MEM_freeN(array);
array = nullptr;
}
*r_array = array;
*r_tot = tot;
}
PBVHColorBufferNode *BKE_pbvh_node_color_buffer_get(PBVHNode *node)
{
@@ -3399,13 +3295,11 @@ PBVHColorBufferNode *BKE_pbvh_node_color_buffer_get(PBVHNode *node)
void BKE_pbvh_node_color_buffer_free(PBVH *pbvh)
{
PBVHNode **nodes;
int totnode;
BKE_pbvh_search_gather(pbvh, nullptr, nullptr, &nodes, &totnode);
for (int i = 0; i < totnode; i++) {
MEM_SAFE_FREE(nodes[i]->color_buffer.color);
Vector<PBVHNode *> nodes = blender::bke::pbvh::search_gather(pbvh, nullptr, nullptr);
for (PBVHNode *node : nodes) {
MEM_SAFE_FREE(node->color_buffer.color);
}
MEM_SAFE_FREE(nodes);
}
void pbvh_vertex_iter_init(PBVH *pbvh, PBVHNode *node, PBVHVertexIter *vi, int mode)
@@ -3934,3 +3828,41 @@ void BKE_pbvh_sync_visibility_from_verts(PBVH *pbvh, Mesh *mesh)
}
}
}
namespace blender::bke::pbvh {
Vector<PBVHNode *> search_gather(PBVH *pbvh,
BKE_pbvh_SearchCallback scb,
void *search_data,
PBVHNodeFlags leaf_flag)
{
PBVHIter iter;
Vector<PBVHNode *> nodes;
pbvh_iter_begin(&iter, pbvh, scb, search_data);
PBVHNode *node;
while ((node = pbvh_iter_next(&iter, leaf_flag))) {
if (node->flag & leaf_flag) {
nodes.append(node);
}
}
pbvh_iter_end(&iter);
return nodes;
}
Vector<PBVHNode *> gather_proxies(PBVH *pbvh)
{
Vector<PBVHNode *> array;
for (int n = 0; n < pbvh->totnode; n++) {
PBVHNode *node = pbvh->nodes + n;
if (node->proxy_count > 0) {
array.append(node);
}
}
return array;
}
} // namespace blender::bke::pbvh

View File

@@ -11,6 +11,7 @@
#include "BLI_heap_simple.h"
#include "BLI_math.h"
#include "BLI_memarena.h"
#include "BLI_span.hh"
#include "BLI_utildefines.h"
#include "BKE_DerivedMesh.h"
@@ -22,6 +23,8 @@
#include "bmesh.h"
#include "pbvh_intern.hh"
using blender::Span;
/* Avoid skinny faces */
#define USE_EDGEQUEUE_EVEN_SUBDIV
#ifdef USE_EDGEQUEUE_EVEN_SUBDIV
@@ -1659,11 +1662,9 @@ bool pbvh_bmesh_node_nearest_to_ray(PBVHNode *node,
return hit;
}
void pbvh_bmesh_normals_update(PBVHNode **nodes, int totnode)
void pbvh_bmesh_normals_update(Span<PBVHNode *> nodes)
{
for (int n = 0; n < totnode; n++) {
PBVHNode *node = nodes[n];
for (PBVHNode *node : nodes) {
if (node->flag & PBVH_UpdateNormals) {
GSetIterator gs_iter;

View File

@@ -2,6 +2,8 @@
#pragma once
#include "BLI_vector.hh"
/** \file
* \ingroup bke
*/
@@ -281,7 +283,7 @@ bool pbvh_bmesh_node_nearest_to_ray(PBVHNode *node,
float *dist_sq,
bool use_original);
void pbvh_bmesh_normals_update(PBVHNode **nodes, int totnode);
void pbvh_bmesh_normals_update(blender::Span<PBVHNode *> nodes);
/* pbvh_pixels.hh */

View File

@@ -11,6 +11,7 @@
#include "BLI_bitmap.h"
#include "BLI_math_vector.h"
#include "BLI_utildefines.h"
#include "BLI_vector.hh"
#include "DNA_mesh_types.h"
#include "DNA_meshdata_types.h"
@@ -43,6 +44,8 @@
/* For undo push. */
#include "sculpt_intern.hh"
using blender::Vector;
/* Return true if the element should be hidden/shown. */
static bool is_effected(PartialVisArea area,
float planes[4][4],
@@ -296,8 +299,7 @@ static void clip_planes_from_rect(bContext *C,
* inside the clip_planes volume. If mode is outside, get all nodes
* that lie at least partially outside the volume. If showing all, get
* all nodes. */
static void get_pbvh_nodes(
PBVH *pbvh, PBVHNode ***nodes, int *totnode, float clip_planes[4][4], PartialVisArea mode)
static Vector<PBVHNode *> get_pbvh_nodes(PBVH *pbvh, float clip_planes[4][4], PartialVisArea mode)
{
BKE_pbvh_SearchCallback cb = nullptr;
@@ -317,7 +319,7 @@ static void get_pbvh_nodes(
PBVHFrustumPlanes frustum{};
frustum.planes = clip_planes;
frustum.num_planes = 4;
BKE_pbvh_search_gather(pbvh, cb, &frustum, nodes, totnode);
return blender::bke::pbvh::search_gather(pbvh, cb, &frustum);
}
static int hide_show_exec(bContext *C, wmOperator *op)
@@ -329,11 +331,9 @@ static int hide_show_exec(bContext *C, wmOperator *op)
PartialVisAction action;
PartialVisArea area;
PBVH *pbvh;
PBVHNode **nodes;
PBVHType pbvh_type;
float clip_planes[4][4];
rcti rect;
int totnode;
/* Read operator properties. */
action = PartialVisAction(RNA_enum_get(op->ptr, "action"));
@@ -345,7 +345,7 @@ static int hide_show_exec(bContext *C, wmOperator *op)
pbvh = BKE_sculpt_object_pbvh_ensure(depsgraph, ob);
BLI_assert(BKE_object_sculpt_pbvh_get(ob) == pbvh);
get_pbvh_nodes(pbvh, &nodes, &totnode, clip_planes, area);
Vector<PBVHNode *> nodes = get_pbvh_nodes(pbvh, clip_planes, area);
pbvh_type = BKE_pbvh_type(pbvh);
negate_m4(clip_planes);
@@ -360,24 +360,20 @@ static int hide_show_exec(bContext *C, wmOperator *op)
break;
}
for (int i = 0; i < totnode; i++) {
for (PBVHNode *node : nodes) {
switch (pbvh_type) {
case PBVH_FACES:
partialvis_update_mesh(ob, pbvh, nodes[i], action, area, clip_planes);
partialvis_update_mesh(ob, pbvh, node, action, area, clip_planes);
break;
case PBVH_GRIDS:
partialvis_update_grids(depsgraph, ob, pbvh, nodes[i], action, area, clip_planes);
partialvis_update_grids(depsgraph, ob, pbvh, node, action, area, clip_planes);
break;
case PBVH_BMESH:
partialvis_update_bmesh(ob, pbvh, nodes[i], action, area, clip_planes);
partialvis_update_bmesh(ob, pbvh, node, action, area, clip_planes);
break;
}
}
if (nodes) {
MEM_freeN(nodes);
}
/* End undo. */
SCULPT_undo_push_end(ob);

View File

@@ -21,8 +21,10 @@
#include "BLI_math_matrix.h"
#include "BLI_polyfill_2d.h"
#include "BLI_rect.h"
#include "BLI_span.hh"
#include "BLI_task.h"
#include "BLI_utildefines.h"
#include "BLI_vector.hh"
#include "BKE_brush.h"
#include "BKE_ccg.h"
@@ -54,6 +56,9 @@
/* For undo push. */
#include "sculpt_intern.hh"
using blender::Span;
using blender::Vector;
static const EnumPropertyItem mode_items[] = {
{PAINT_MASK_FLOOD_VALUE,
"VALUE",
@@ -86,7 +91,7 @@ static void mask_flood_fill_set_elem(float *elem, PaintMaskFloodMode mode, float
struct MaskTaskData {
Object *ob;
PBVH *pbvh;
PBVHNode **nodes;
Span<PBVHNode *> nodes;
bool multires;
PaintMaskFloodMode mode;
@@ -136,8 +141,7 @@ static int mask_flood_fill_exec(bContext *C, wmOperator *op)
Object *ob = CTX_data_active_object(C);
Depsgraph *depsgraph = CTX_data_ensure_evaluated_depsgraph(C);
PBVH *pbvh;
PBVHNode **nodes;
int totnode;
Vector<PBVHNode *> nodes;
bool multires;
PaintMaskFloodMode mode = PaintMaskFloodMode(RNA_enum_get(op->ptr, "mode"));
@@ -150,7 +154,7 @@ static int mask_flood_fill_exec(bContext *C, wmOperator *op)
pbvh = ob->sculpt->pbvh;
multires = (BKE_pbvh_type(pbvh) == PBVH_GRIDS);
BKE_pbvh_search_gather(pbvh, nullptr, nullptr, &nodes, &totnode);
nodes = blender::bke::pbvh::search_gather(pbvh, nullptr, nullptr);
SCULPT_undo_push_begin(ob, op);
@@ -163,8 +167,8 @@ static int mask_flood_fill_exec(bContext *C, wmOperator *op)
data.value = value;
TaskParallelSettings settings;
BKE_pbvh_parallel_range_settings(&settings, true, totnode);
BLI_task_parallel_range(0, totnode, &data, mask_flood_fill_task_cb, &settings);
BKE_pbvh_parallel_range_settings(&settings, true, nodes.size());
BLI_task_parallel_range(0, nodes.size(), &data, mask_flood_fill_task_cb, &settings);
if (multires) {
multires_mark_as_modified(depsgraph, ob, MULTIRES_COORDS_MODIFIED);
@@ -174,10 +178,6 @@ static int mask_flood_fill_exec(bContext *C, wmOperator *op)
SCULPT_undo_push_end(ob);
if (nodes) {
MEM_freeN(nodes);
}
SCULPT_tag_update_overlays(C);
return OPERATOR_FINISHED;
@@ -288,8 +288,7 @@ struct SculptGestureContext {
LineGestureData line;
/* Task Callback Data. */
PBVHNode **nodes;
int totnode;
Vector<PBVHNode *> nodes;
};
struct SculptGestureOperation {
@@ -366,7 +365,7 @@ static void sculpt_gesture_lasso_px_cb(int x, int x_end, int y, void *user_data)
static SculptGestureContext *sculpt_gesture_init_from_lasso(bContext *C, wmOperator *op)
{
SculptGestureContext *sgcontext = MEM_cnew<SculptGestureContext>(__func__);
SculptGestureContext *sgcontext = MEM_new<SculptGestureContext>(__func__);
sgcontext->shape_type = SCULPT_GESTURE_SHAPE_LASSO;
sculpt_gesture_context_init_common(C, op, sgcontext);
@@ -417,7 +416,7 @@ static SculptGestureContext *sculpt_gesture_init_from_lasso(bContext *C, wmOpera
static SculptGestureContext *sculpt_gesture_init_from_box(bContext *C, wmOperator *op)
{
SculptGestureContext *sgcontext = MEM_cnew<SculptGestureContext>(__func__);
SculptGestureContext *sgcontext = MEM_new<SculptGestureContext>(__func__);
sgcontext->shape_type = SCULPT_GESTURE_SHAPE_BOX;
sculpt_gesture_context_init_common(C, op, sgcontext);
@@ -493,7 +492,7 @@ static void sculpt_gesture_line_calculate_plane_points(SculptGestureContext *sgc
static SculptGestureContext *sculpt_gesture_init_from_line(bContext *C, wmOperator *op)
{
SculptGestureContext *sgcontext = MEM_cnew<SculptGestureContext>(__func__);
SculptGestureContext *sgcontext = MEM_new<SculptGestureContext>(__func__);
sgcontext->shape_type = SCULPT_GESTURE_SHAPE_LINE;
sculpt_gesture_context_init_common(C, op, sgcontext);
@@ -542,8 +541,7 @@ static void sculpt_gesture_context_free(SculptGestureContext *sgcontext)
MEM_SAFE_FREE(sgcontext->lasso.mask_px);
MEM_SAFE_FREE(sgcontext->gesture_points);
MEM_SAFE_FREE(sgcontext->operation);
MEM_SAFE_FREE(sgcontext->nodes);
MEM_SAFE_FREE(sgcontext);
MEM_delete(sgcontext);
}
static void flip_plane(float out[4], const float in[4], const char symm)
@@ -587,7 +585,8 @@ static void sculpt_gesture_flip_for_symmetry_pass(SculptGestureContext *sgcontex
flip_plane(sgcontext->line.side_plane[1], sgcontext->line.true_side_plane[1], symmpass);
}
static void sculpt_gesture_update_effected_nodes_by_line_plane(SculptGestureContext *sgcontext)
static Vector<PBVHNode *> sculpt_gesture_update_effected_nodes_by_line_plane(
SculptGestureContext *sgcontext)
{
SculptSession *ss = sgcontext->ss;
float clip_planes[3][4];
@@ -599,11 +598,8 @@ static void sculpt_gesture_update_effected_nodes_by_line_plane(SculptGestureCont
frustum.planes = clip_planes;
frustum.num_planes = sgcontext->line.use_side_planes ? 3 : 1;
BKE_pbvh_search_gather(ss->pbvh,
BKE_pbvh_node_frustum_contain_AABB,
&frustum,
&sgcontext->nodes,
&sgcontext->totnode);
return sgcontext->nodes = blender::bke::pbvh::search_gather(
ss->pbvh, BKE_pbvh_node_frustum_contain_AABB, &frustum);
}
static void sculpt_gesture_update_effected_nodes_by_clip_planes(SculptGestureContext *sgcontext)
@@ -617,11 +613,8 @@ static void sculpt_gesture_update_effected_nodes_by_clip_planes(SculptGestureCon
frustum.planes = clip_planes;
frustum.num_planes = 4;
BKE_pbvh_search_gather(ss->pbvh,
BKE_pbvh_node_frustum_contain_AABB,
&frustum,
&sgcontext->nodes,
&sgcontext->totnode);
sgcontext->nodes = blender::bke::pbvh::search_gather(
ss->pbvh, BKE_pbvh_node_frustum_contain_AABB, &frustum);
}
static void sculpt_gesture_update_effected_nodes(SculptGestureContext *sgcontext)
@@ -716,8 +709,6 @@ static void sculpt_gesture_apply(bContext *C, SculptGestureContext *sgcontext, w
sculpt_gesture_update_effected_nodes(sgcontext);
operation->sculpt_gesture_apply_for_symmetry_pass(C, sgcontext);
MEM_SAFE_FREE(sgcontext->nodes);
}
}
@@ -773,9 +764,9 @@ static void sculpt_gesture_face_set_apply_for_symmetry_pass(bContext * /*C*/,
SculptGestureContext *sgcontext)
{
TaskParallelSettings settings;
BKE_pbvh_parallel_range_settings(&settings, true, sgcontext->totnode);
BKE_pbvh_parallel_range_settings(&settings, true, sgcontext->nodes.size());
BLI_task_parallel_range(
0, sgcontext->totnode, sgcontext, face_set_gesture_apply_task_cb, &settings);
0, sgcontext->nodes.size(), sgcontext, face_set_gesture_apply_task_cb, &settings);
}
static void sculpt_gesture_face_set_end(bContext * /*C*/, SculptGestureContext *sgcontext)
@@ -862,8 +853,9 @@ static void sculpt_gesture_mask_apply_for_symmetry_pass(bContext * /*C*/,
SculptGestureContext *sgcontext)
{
TaskParallelSettings settings;
BKE_pbvh_parallel_range_settings(&settings, true, sgcontext->totnode);
BLI_task_parallel_range(0, sgcontext->totnode, sgcontext, mask_gesture_apply_task_cb, &settings);
BKE_pbvh_parallel_range_settings(&settings, true, sgcontext->nodes.size());
BLI_task_parallel_range(
0, sgcontext->nodes.size(), sgcontext, mask_gesture_apply_task_cb, &settings);
}
static void sculpt_gesture_mask_end(bContext *C, SculptGestureContext *sgcontext)
@@ -1563,12 +1555,12 @@ static void sculpt_gesture_project_apply_for_symmetry_pass(bContext * /*C*/,
SculptGestureContext *sgcontext)
{
TaskParallelSettings settings;
BKE_pbvh_parallel_range_settings(&settings, true, sgcontext->totnode);
BKE_pbvh_parallel_range_settings(&settings, true, sgcontext->nodes.size());
switch (sgcontext->shape_type) {
case SCULPT_GESTURE_SHAPE_LINE:
BLI_task_parallel_range(
0, sgcontext->totnode, sgcontext, project_line_gesture_apply_task_cb, &settings);
0, sgcontext->nodes.size(), sgcontext, project_line_gesture_apply_task_cb, &settings);
break;
case SCULPT_GESTURE_SHAPE_LASSO:
case SCULPT_GESTURE_SHAPE_BOX:

View File

@@ -21,6 +21,7 @@
#include "BLI_string.h"
#include "BLI_task.h"
#include "BLI_task.hh"
#include "BLI_vector.hh"
#include "DNA_brush_types.h"
#include "DNA_mesh_types.h"
@@ -2254,21 +2255,20 @@ static void do_wpaint_brush_calc_average_weight_cb_ex(void *__restrict userdata,
BKE_pbvh_vertex_iter_end;
}
static void calculate_average_weight(SculptThreadedTaskData *data,
PBVHNode ** /*nodes*/,
int totnode)
static void calculate_average_weight(SculptThreadedTaskData *data, Span<PBVHNode *> nodes)
{
WPaintAverageAccum *accum = (WPaintAverageAccum *)MEM_mallocN(sizeof(*accum) * totnode,
WPaintAverageAccum *accum = (WPaintAverageAccum *)MEM_mallocN(sizeof(*accum) * nodes.size(),
__func__);
data->custom_data = accum;
TaskParallelSettings settings;
BKE_pbvh_parallel_range_settings(&settings, true, totnode);
BLI_task_parallel_range(0, totnode, data, do_wpaint_brush_calc_average_weight_cb_ex, &settings);
BKE_pbvh_parallel_range_settings(&settings, true, nodes.size());
BLI_task_parallel_range(
0, nodes.size(), data, do_wpaint_brush_calc_average_weight_cb_ex, &settings);
uint accum_len = 0;
double accum_weight = 0.0;
for (int i = 0; i < totnode; i++) {
for (int i = 0; i < nodes.size(); i++) {
accum_len += accum[i].len;
accum_weight += accum[i].value;
}
@@ -2287,8 +2287,7 @@ static void wpaint_paint_leaves(bContext *C,
WPaintData *wpd,
WeightPaintInfo *wpi,
Mesh *me,
PBVHNode **nodes,
int totnode)
Span<PBVHNode *> nodes)
{
Scene *scene = CTX_data_scene(C);
const Brush *brush = ob->sculpt->cache->brush;
@@ -2311,31 +2310,33 @@ static void wpaint_paint_leaves(bContext *C,
/* NOTE: current mirroring code cannot be run in parallel */
TaskParallelSettings settings;
const bool use_threading = !ME_USING_MIRROR_X_VERTEX_GROUPS(me);
BKE_pbvh_parallel_range_settings(&settings, use_threading, totnode);
BKE_pbvh_parallel_range_settings(&settings, use_threading, nodes.size());
switch ((eBrushWeightPaintTool)brush->weightpaint_tool) {
case WPAINT_TOOL_AVERAGE:
calculate_average_weight(&data, nodes, totnode);
BLI_task_parallel_range(0, totnode, &data, do_wpaint_brush_draw_task_cb_ex, &settings);
calculate_average_weight(&data, nodes);
BLI_task_parallel_range(0, nodes.size(), &data, do_wpaint_brush_draw_task_cb_ex, &settings);
break;
case WPAINT_TOOL_SMEAR:
BLI_task_parallel_range(0, totnode, &data, do_wpaint_brush_smear_task_cb_ex, &settings);
BLI_task_parallel_range(0, nodes.size(), &data, do_wpaint_brush_smear_task_cb_ex, &settings);
break;
case WPAINT_TOOL_BLUR:
BLI_task_parallel_range(0, totnode, &data, do_wpaint_brush_blur_task_cb_ex, &settings);
BLI_task_parallel_range(0, nodes.size(), &data, do_wpaint_brush_blur_task_cb_ex, &settings);
break;
case WPAINT_TOOL_DRAW:
BLI_task_parallel_range(0, totnode, &data, do_wpaint_brush_draw_task_cb_ex, &settings);
BLI_task_parallel_range(0, nodes.size(), &data, do_wpaint_brush_draw_task_cb_ex, &settings);
break;
}
}
static PBVHNode **vwpaint_pbvh_gather_generic(
Object *ob, VPaint *wp, Sculpt *sd, Brush *brush, int *r_totnode)
static Vector<PBVHNode *> vwpaint_pbvh_gather_generic(Object *ob,
VPaint *wp,
Sculpt *sd,
Brush *brush)
{
SculptSession *ss = ob->sculpt;
const bool use_normal = vwpaint_use_normal(wp);
PBVHNode **nodes = nullptr;
Vector<PBVHNode *> nodes;
/* Build a list of all nodes that are potentially within the brush's area of influence */
if (brush->falloff_shape == PAINT_FALLOFF_SHAPE_SPHERE) {
@@ -2345,10 +2346,10 @@ static PBVHNode **vwpaint_pbvh_gather_generic(
data.radius_squared = ss->cache->radius_squared;
data.original = true;
BKE_pbvh_search_gather(ss->pbvh, SCULPT_search_sphere_cb, &data, &nodes, r_totnode);
nodes = blender::bke::pbvh::search_gather(ss->pbvh, SCULPT_search_sphere_cb, &data);
if (use_normal) {
SCULPT_pbvh_calc_area_normal(
brush, ob, nodes, *r_totnode, true, ss->cache->sculpt_normal_symm);
SCULPT_pbvh_calc_area_normal(brush, ob, nodes, true, ss->cache->sculpt_normal_symm);
}
else {
zero_v3(ss->cache->sculpt_normal_symm);
@@ -2365,7 +2366,8 @@ static PBVHNode **vwpaint_pbvh_gather_generic(
data.original = true;
data.dist_ray_to_aabb_precalc = &dist_ray_to_aabb_precalc;
BKE_pbvh_search_gather(ss->pbvh, SCULPT_search_circle_cb, &data, &nodes, r_totnode);
nodes = blender::bke::pbvh::search_gather(ss->pbvh, SCULPT_search_circle_cb, &data);
if (use_normal) {
copy_v3_v3(ss->cache->sculpt_normal_symm, ss->cache->view_normal);
}
@@ -2393,14 +2395,9 @@ static void wpaint_do_paint(bContext *C,
ss->cache->radial_symmetry_pass = i;
SCULPT_cache_calc_brushdata_symm(ss->cache, symm, axis, angle);
int totnode;
PBVHNode **nodes = vwpaint_pbvh_gather_generic(ob, wp, sd, brush, &totnode);
Vector<PBVHNode *> nodes = vwpaint_pbvh_gather_generic(ob, wp, sd, brush);
wpaint_paint_leaves(C, ob, sd, wp, wpd, wpi, me, nodes, totnode);
if (nodes) {
MEM_freeN(nodes);
}
wpaint_paint_leaves(C, ob, sd, wp, wpd, wpi, me, nodes);
}
static void wpaint_do_radial_symmetry(bContext *C,
@@ -2948,8 +2945,7 @@ static void do_vpaint_brush_blur_loops(bContext *C,
VPaintData<Color, Traits, ATTR_DOMAIN_CORNER> *vpd,
Object *ob,
Mesh *me,
PBVHNode **nodes,
int totnode,
Span<PBVHNode *> nodes,
Color *lcol)
{
using Blend = typename Traits::BlendType;
@@ -2966,7 +2962,7 @@ static void do_vpaint_brush_blur_loops(bContext *C,
const blender::VArray<bool> select_poly = me->attributes().lookup_or_default<bool>(
".select_poly", ATTR_DOMAIN_FACE, false);
blender::threading::parallel_for(IndexRange(totnode), 1LL, [&](IndexRange range) {
blender::threading::parallel_for(nodes.index_range(), 1LL, [&](IndexRange range) {
for (int n : range) {
const PBVHType pbvh_type = BKE_pbvh_type(ss->pbvh);
const bool has_grids = (pbvh_type == PBVH_GRIDS);
@@ -3092,8 +3088,7 @@ static void do_vpaint_brush_blur_verts(bContext *C,
VPaintData<Color, Traits, ATTR_DOMAIN_POINT> *vpd,
Object *ob,
Mesh *me,
PBVHNode **nodes,
int totnode,
Span<PBVHNode *> nodes,
Color *lcol)
{
using Blend = typename Traits::BlendType;
@@ -3110,7 +3105,7 @@ static void do_vpaint_brush_blur_verts(bContext *C,
const blender::VArray<bool> select_poly = me->attributes().lookup_or_default<bool>(
".select_poly", ATTR_DOMAIN_FACE, false);
blender::threading::parallel_for(IndexRange(totnode), 1LL, [&](IndexRange range) {
blender::threading::parallel_for(nodes.index_range(), 1LL, [&](IndexRange range) {
for (int n : range) {
const PBVHType pbvh_type = BKE_pbvh_type(ss->pbvh);
const bool has_grids = (pbvh_type == PBVH_GRIDS);
@@ -3237,8 +3232,7 @@ static void do_vpaint_brush_smear(bContext *C,
VPaintData<Color, Traits, domain> *vpd,
Object *ob,
Mesh *me,
PBVHNode **nodes,
int totnode,
Span<PBVHNode *> nodes,
Color *lcol)
{
SculptSession *ss = ob->sculpt;
@@ -3259,7 +3253,7 @@ static void do_vpaint_brush_smear(bContext *C,
const blender::VArray<bool> select_poly = me->attributes().lookup_or_default<bool>(
".select_poly", ATTR_DOMAIN_FACE, false);
blender::threading::parallel_for(IndexRange(totnode), 1LL, [&](IndexRange range) {
blender::threading::parallel_for(nodes.index_range(), 1LL, [&](IndexRange range) {
for (int n : range) {
float brush_size_pressure, brush_alpha_value, brush_alpha_pressure;
@@ -3417,8 +3411,7 @@ static void calculate_average_color(VPaintData<Color, Traits, domain> *vpd,
Mesh *me,
const Brush *brush,
Color *lcol,
PBVHNode **nodes,
int totnode)
Span<PBVHNode *> nodes)
{
using Blend = typename Traits::BlendType;
@@ -3426,8 +3419,8 @@ static void calculate_average_color(VPaintData<Color, Traits, domain> *vpd,
".select_vert", ATTR_DOMAIN_POINT, false);
VPaintAverageAccum<Blend> *accum = (VPaintAverageAccum<Blend> *)MEM_mallocN(
sizeof(*accum) * totnode, __func__);
blender::threading::parallel_for(IndexRange(totnode), 1LL, [&](IndexRange range) {
sizeof(*accum) * nodes.size(), __func__);
blender::threading::parallel_for(nodes.index_range(), 1LL, [&](IndexRange range) {
for (int n : range) {
SculptSession *ss = ob->sculpt;
const PBVHType pbvh_type = BKE_pbvh_type(ss->pbvh);
@@ -3487,7 +3480,7 @@ static void calculate_average_color(VPaintData<Color, Traits, domain> *vpd,
Blend accum_value[3] = {0};
Color blend(0, 0, 0, 0);
for (int i = 0; i < totnode; i++) {
for (int i = 0; i < nodes.size(); i++) {
accum_len += accum[i].len;
accum_value[0] += accum[i].value[0];
accum_value[1] += accum[i].value[1];
@@ -3528,8 +3521,7 @@ static void vpaint_do_draw(bContext *C,
VPaintData<Color, Traits, domain> *vpd,
Object *ob,
Mesh *me,
PBVHNode **nodes,
int totnode,
Span<PBVHNode *> nodes,
Color *lcol)
{
SculptSession *ss = ob->sculpt;
@@ -3545,7 +3537,7 @@ static void vpaint_do_draw(bContext *C,
const blender::VArray<bool> select_poly = me->attributes().lookup_or_default<bool>(
".select_poly", ATTR_DOMAIN_FACE, false);
blender::threading::parallel_for(IndexRange(totnode), 1LL, [&](IndexRange range) {
blender::threading::parallel_for(nodes.index_range(), 1LL, [&](IndexRange range) {
for (int n : range) {
const bool has_grids = (pbvh_type == PBVH_GRIDS);
const SculptVertexPaintGeomMap *gmap = &ss->mode.vpaint.gmap;
@@ -3671,15 +3663,14 @@ static void vpaint_do_blur(bContext *C,
VPaintData<Color, Traits, domain> *vpd,
Object *ob,
Mesh *me,
PBVHNode **nodes,
int totnode,
Span<PBVHNode *> nodes,
Color *lcol)
{
if constexpr (domain == ATTR_DOMAIN_POINT) {
do_vpaint_brush_blur_verts<Color, Traits>(C, sd, vp, vpd, ob, me, nodes, totnode, lcol);
do_vpaint_brush_blur_verts<Color, Traits>(C, sd, vp, vpd, ob, me, nodes, lcol);
}
else {
do_vpaint_brush_blur_loops<Color, Traits>(C, sd, vp, vpd, ob, me, nodes, totnode, lcol);
do_vpaint_brush_blur_loops<Color, Traits>(C, sd, vp, vpd, ob, me, nodes, lcol);
}
}
@@ -3691,28 +3682,27 @@ static void vpaint_paint_leaves(bContext *C,
Object *ob,
Mesh *me,
Color *lcol,
PBVHNode **nodes,
int totnode)
Span<PBVHNode *> nodes)
{
for (int i : IndexRange(totnode)) {
SCULPT_undo_push_node(ob, nodes[i], SCULPT_UNDO_COLOR);
for (PBVHNode *node : nodes) {
SCULPT_undo_push_node(ob, node, SCULPT_UNDO_COLOR);
}
const Brush *brush = ob->sculpt->cache->brush;
switch ((eBrushVertexPaintTool)brush->vertexpaint_tool) {
case VPAINT_TOOL_AVERAGE:
calculate_average_color<Color, Traits, domain>(vpd, ob, me, brush, lcol, nodes, totnode);
calculate_average_color<Color, Traits, domain>(vpd, ob, me, brush, lcol, nodes);
break;
case VPAINT_TOOL_DRAW:
vpaint_do_draw<Color, Traits, domain>(C, sd, vp, vpd, ob, me, nodes, totnode, lcol);
vpaint_do_draw<Color, Traits, domain>(C, sd, vp, vpd, ob, me, nodes, lcol);
break;
case VPAINT_TOOL_BLUR:
vpaint_do_blur<Color, Traits, domain>(C, sd, vp, vpd, ob, me, nodes, totnode, lcol);
vpaint_do_blur<Color, Traits, domain>(C, sd, vp, vpd, ob, me, nodes, lcol);
break;
case VPAINT_TOOL_SMEAR:
do_vpaint_brush_smear<Color, Traits, domain>(C, sd, vp, vpd, ob, me, nodes, totnode, lcol);
do_vpaint_brush_smear<Color, Traits, domain>(C, sd, vp, vpd, ob, me, nodes, lcol);
break;
default:
break;
@@ -3736,8 +3726,7 @@ static void vpaint_do_paint(bContext *C,
ss->cache->radial_symmetry_pass = i;
SCULPT_cache_calc_brushdata_symm(ss->cache, symm, axis, angle);
int totnode;
PBVHNode **nodes = vwpaint_pbvh_gather_generic(ob, vp, sd, brush, &totnode);
Vector<PBVHNode *> nodes = vwpaint_pbvh_gather_generic(ob, vp, sd, brush);
bke::GSpanAttributeWriter attribute = me->attributes_for_write().lookup_for_write_span(
me->active_color_attribute);
@@ -3746,12 +3735,9 @@ static void vpaint_do_paint(bContext *C,
Color *color_data = static_cast<Color *>(attribute.span.data());
/* Paint those leaves. */
vpaint_paint_leaves<Color, Traits, domain>(C, sd, vp, vpd, ob, me, color_data, nodes, totnode);
vpaint_paint_leaves<Color, Traits, domain>(C, sd, vp, vpd, ob, me, color_data, nodes);
attribute.finish();
if (nodes) {
MEM_freeN(nodes);
}
}
template<typename Color, typename Traits, eAttrDomain domain>

View File

@@ -300,18 +300,17 @@ static void transform_active_color(bContext *C, wmOperator *op, const TransformF
CTX_data_ensure_evaluated_depsgraph(C), obact, true, false, true);
SCULPT_undo_push_begin(obact, op);
PBVHNode **nodes;
int nodes_num;
BKE_pbvh_search_gather(obact->sculpt->pbvh, nullptr, nullptr, &nodes, &nodes_num);
for (int i : IndexRange(nodes_num)) {
SCULPT_undo_push_node(obact, nodes[i], SCULPT_UNDO_COLOR);
Vector<PBVHNode *> nodes = blender::bke::pbvh::search_gather(
obact->sculpt->pbvh, nullptr, nullptr);
for (PBVHNode *node : nodes) {
SCULPT_undo_push_node(obact, node, SCULPT_UNDO_COLOR);
}
transform_active_color_data(*BKE_mesh_from_object(obact), transform_fn);
for (int i : IndexRange(nodes_num)) {
BKE_pbvh_node_mark_update_color(nodes[i]);
for (PBVHNode *node : nodes) {
BKE_pbvh_node_mark_update_color(node);
}
SCULPT_undo_push_end(obact);

View File

@@ -79,6 +79,7 @@
using blender::float3;
using blender::MutableSpan;
using blender::Set;
using blender::Span;
using blender::Vector;
static float sculpt_calc_radius(ViewContext *vc,
@@ -1101,16 +1102,16 @@ PBVHVertRef SCULPT_nearest_vertex_get(
Sculpt *sd, Object *ob, const float co[3], float max_distance, bool use_original)
{
SculptSession *ss = ob->sculpt;
PBVHNode **nodes = nullptr;
int totnode;
Vector<PBVHNode *> nodes;
SculptSearchSphereData data{};
data.sd = sd;
data.radius_squared = max_distance * max_distance;
data.original = use_original;
data.center = co;
BKE_pbvh_search_gather(ss->pbvh, SCULPT_search_sphere_cb, &data, &nodes, &totnode);
if (totnode == 0) {
nodes = blender::bke::pbvh::search_gather(ss->pbvh, SCULPT_search_sphere_cb, &data);
if (nodes.is_empty()) {
return BKE_pbvh_make_vref(PBVH_REF_NONE);
}
@@ -1126,13 +1127,11 @@ PBVHVertRef SCULPT_nearest_vertex_get(
nvtd.nearest_vertex_distance_squared = FLT_MAX;
TaskParallelSettings settings;
BKE_pbvh_parallel_range_settings(&settings, true, totnode);
BKE_pbvh_parallel_range_settings(&settings, true, nodes.size());
settings.func_reduce = nearest_vertex_get_reduce;
settings.userdata_chunk = &nvtd;
settings.userdata_chunk_size = sizeof(NearestVertexTLSData);
BLI_task_parallel_range(0, totnode, &task_data, do_nearest_vertex_get_task_cb, &settings);
MEM_SAFE_FREE(nodes);
BLI_task_parallel_range(0, nodes.size(), &task_data, do_nearest_vertex_get_task_cb, &settings);
return nvtd.nearest_vertex;
}
@@ -1619,10 +1618,7 @@ static void paint_mesh_restore_co(Sculpt *sd, Object *ob)
SculptSession *ss = ob->sculpt;
Brush *brush = BKE_paint_brush(&sd->paint);
PBVHNode **nodes;
int totnode;
BKE_pbvh_search_gather(ss->pbvh, nullptr, nullptr, &nodes, &totnode);
Vector<PBVHNode *> nodes = blender::bke::pbvh::search_gather(ss->pbvh, nullptr, nullptr);
/**
* Disable multi-threading when dynamic-topology is enabled. Otherwise,
@@ -1636,12 +1632,10 @@ static void paint_mesh_restore_co(Sculpt *sd, Object *ob)
data.nodes = nodes;
TaskParallelSettings settings;
BKE_pbvh_parallel_range_settings(&settings, true && !ss->bm, totnode);
BLI_task_parallel_range(0, totnode, &data, paint_mesh_restore_co_task_cb, &settings);
BKE_pbvh_parallel_range_settings(&settings, true && !ss->bm, nodes.size());
BLI_task_parallel_range(0, nodes.size(), &data, paint_mesh_restore_co_task_cb, &settings);
BKE_pbvh_node_color_buffer_free(ss->pbvh);
MEM_SAFE_FREE(nodes);
}
/*** BVH Tree ***/
@@ -2249,8 +2243,7 @@ static void calc_area_normal_and_center_reduce(const void *__restrict /*userdata
add_v2_v2_int(join->count_co, anctd->count_co);
}
void SCULPT_calc_area_center(
Sculpt *sd, Object *ob, PBVHNode **nodes, int totnode, float r_area_co[3])
void SCULPT_calc_area_center(Sculpt *sd, Object *ob, Span<PBVHNode *> nodes, float r_area_co[3])
{
const Brush *brush = BKE_paint_brush(&sd->paint);
SculptSession *ss = ob->sculpt;
@@ -2263,18 +2256,17 @@ void SCULPT_calc_area_center(
data.ob = ob;
data.brush = brush;
data.nodes = nodes;
data.totnode = totnode;
data.has_bm_orco = has_bm_orco;
data.use_area_cos = true;
AreaNormalCenterTLSData anctd = {{{0}}};
TaskParallelSettings settings;
BKE_pbvh_parallel_range_settings(&settings, true, totnode);
BKE_pbvh_parallel_range_settings(&settings, true, nodes.size());
settings.func_reduce = calc_area_normal_and_center_reduce;
settings.userdata_chunk = &anctd;
settings.userdata_chunk_size = sizeof(AreaNormalCenterTLSData);
BLI_task_parallel_range(0, totnode, &data, calc_area_normal_and_center_task_cb, &settings);
BLI_task_parallel_range(0, nodes.size(), &data, calc_area_normal_and_center_task_cb, &settings);
/* For flatten center. */
for (n = 0; n < ARRAY_SIZE(anctd.area_cos); n++) {
@@ -2297,19 +2289,14 @@ void SCULPT_calc_area_center(
}
}
void SCULPT_calc_area_normal(
Sculpt *sd, Object *ob, PBVHNode **nodes, int totnode, float r_area_no[3])
void SCULPT_calc_area_normal(Sculpt *sd, Object *ob, Span<PBVHNode *> nodes, float r_area_no[3])
{
const Brush *brush = BKE_paint_brush(&sd->paint);
SCULPT_pbvh_calc_area_normal(brush, ob, nodes, totnode, true, r_area_no);
SCULPT_pbvh_calc_area_normal(brush, ob, nodes, true, r_area_no);
}
bool SCULPT_pbvh_calc_area_normal(const Brush *brush,
Object *ob,
PBVHNode **nodes,
int totnode,
bool use_threading,
float r_area_no[3])
bool SCULPT_pbvh_calc_area_normal(
const Brush *brush, Object *ob, Span<PBVHNode *> nodes, bool use_threading, float r_area_no[3])
{
SculptSession *ss = ob->sculpt;
const bool has_bm_orco = ss->bm && SCULPT_stroke_is_dynamic_topology(ss, brush);
@@ -2320,7 +2307,6 @@ bool SCULPT_pbvh_calc_area_normal(const Brush *brush,
data.ob = ob;
data.brush = brush;
data.nodes = nodes;
data.totnode = totnode;
data.has_bm_orco = has_bm_orco;
data.use_area_nos = true;
data.any_vertex_sampled = false;
@@ -2328,11 +2314,11 @@ bool SCULPT_pbvh_calc_area_normal(const Brush *brush,
AreaNormalCenterTLSData anctd = {{{0}}};
TaskParallelSettings settings;
BKE_pbvh_parallel_range_settings(&settings, use_threading, totnode);
BKE_pbvh_parallel_range_settings(&settings, use_threading, nodes.size());
settings.func_reduce = calc_area_normal_and_center_reduce;
settings.userdata_chunk = &anctd;
settings.userdata_chunk_size = sizeof(AreaNormalCenterTLSData);
BLI_task_parallel_range(0, totnode, &data, calc_area_normal_and_center_task_cb, &settings);
BLI_task_parallel_range(0, nodes.size(), &data, calc_area_normal_and_center_task_cb, &settings);
/* For area normal. */
for (int i = 0; i < ARRAY_SIZE(anctd.area_nos); i++) {
@@ -2345,7 +2331,7 @@ bool SCULPT_pbvh_calc_area_normal(const Brush *brush,
}
void SCULPT_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, Span<PBVHNode *> nodes, float r_area_no[3], float r_area_co[3])
{
const Brush *brush = BKE_paint_brush(&sd->paint);
SculptSession *ss = ob->sculpt;
@@ -2358,7 +2344,6 @@ void SCULPT_calc_area_normal_and_center(
data.ob = ob;
data.brush = brush;
data.nodes = nodes;
data.totnode = totnode;
data.has_bm_orco = has_bm_orco;
data.use_area_cos = true;
data.use_area_nos = true;
@@ -2366,11 +2351,11 @@ void SCULPT_calc_area_normal_and_center(
AreaNormalCenterTLSData anctd = {{{0}}};
TaskParallelSettings settings;
BKE_pbvh_parallel_range_settings(&settings, true, totnode);
BKE_pbvh_parallel_range_settings(&settings, true, nodes.size());
settings.func_reduce = calc_area_normal_and_center_reduce;
settings.userdata_chunk = &anctd;
settings.userdata_chunk_size = sizeof(AreaNormalCenterTLSData);
BLI_task_parallel_range(0, totnode, &data, calc_area_normal_and_center_task_cb, &settings);
BLI_task_parallel_range(0, nodes.size(), &data, calc_area_normal_and_center_task_cb, &settings);
/* For flatten center. */
for (n = 0; n < ARRAY_SIZE(anctd.area_cos); n++) {
@@ -2850,13 +2835,11 @@ void SCULPT_clip(Sculpt *sd, SculptSession *ss, float co[3], const float val[3])
}
}
static PBVHNode **sculpt_pbvh_gather_cursor_update(Object *ob,
Sculpt *sd,
bool use_original,
int *r_totnode)
static Vector<PBVHNode *> sculpt_pbvh_gather_cursor_update(Object *ob,
Sculpt *sd,
bool use_original)
{
SculptSession *ss = ob->sculpt;
PBVHNode **nodes = nullptr;
SculptSearchSphereData data{};
data.ss = ss;
data.sd = sd;
@@ -2864,20 +2847,19 @@ static PBVHNode **sculpt_pbvh_gather_cursor_update(Object *ob,
data.original = use_original;
data.ignore_fully_ineffective = false;
data.center = nullptr;
BKE_pbvh_search_gather(ss->pbvh, SCULPT_search_sphere_cb, &data, &nodes, r_totnode);
return nodes;
return blender::bke::pbvh::search_gather(ss->pbvh, SCULPT_search_sphere_cb, &data);
}
static PBVHNode **sculpt_pbvh_gather_generic_intern(Object *ob,
Sculpt *sd,
const Brush *brush,
bool use_original,
float radius_scale,
int *r_totnode,
PBVHNodeFlags flag)
static Vector<PBVHNode *> sculpt_pbvh_gather_generic_intern(Object *ob,
Sculpt *sd,
const Brush *brush,
bool use_original,
float radius_scale,
PBVHNodeFlags flag)
{
SculptSession *ss = ob->sculpt;
PBVHNode **nodes = nullptr;
Vector<PBVHNode *> nodes;
PBVHNodeFlags leaf_flag = PBVH_Leaf;
if (flag & PBVH_TexLeaf) {
@@ -2894,8 +2876,7 @@ static PBVHNode **sculpt_pbvh_gather_generic_intern(Object *ob,
data.original = use_original;
data.ignore_fully_ineffective = brush->sculpt_tool != SCULPT_TOOL_MASK;
data.center = nullptr;
BKE_pbvh_search_gather_ex(
ss->pbvh, SCULPT_search_sphere_cb, &data, &nodes, r_totnode, leaf_flag);
nodes = blender::bke::pbvh::search_gather(ss->pbvh, SCULPT_search_sphere_cb, &data, leaf_flag);
}
else {
DistRayAABB_Precalc dist_ray_to_aabb_precalc;
@@ -2909,37 +2890,27 @@ static PBVHNode **sculpt_pbvh_gather_generic_intern(Object *ob,
data.original = use_original;
data.dist_ray_to_aabb_precalc = &dist_ray_to_aabb_precalc;
data.ignore_fully_ineffective = brush->sculpt_tool != SCULPT_TOOL_MASK;
BKE_pbvh_search_gather_ex(
ss->pbvh, SCULPT_search_circle_cb, &data, &nodes, r_totnode, leaf_flag);
nodes = blender::bke::pbvh::search_gather(ss->pbvh, SCULPT_search_circle_cb, &data, leaf_flag);
}
return nodes;
}
static PBVHNode **sculpt_pbvh_gather_generic(Object *ob,
Sculpt *sd,
const Brush *brush,
bool use_original,
float radius_scale,
int *r_totnode)
static Vector<PBVHNode *> sculpt_pbvh_gather_generic(
Object *ob, Sculpt *sd, const Brush *brush, bool use_original, float radius_scale)
{
return sculpt_pbvh_gather_generic_intern(
ob, sd, brush, use_original, radius_scale, r_totnode, PBVH_Leaf);
return sculpt_pbvh_gather_generic_intern(ob, sd, brush, use_original, radius_scale, PBVH_Leaf);
}
static PBVHNode **sculpt_pbvh_gather_texpaint(Object *ob,
Sculpt *sd,
const Brush *brush,
bool use_original,
float radius_scale,
int *r_totnode)
static Vector<PBVHNode *> sculpt_pbvh_gather_texpaint(
Object *ob, Sculpt *sd, const Brush *brush, bool use_original, float radius_scale)
{
return sculpt_pbvh_gather_generic_intern(
ob, sd, brush, use_original, radius_scale, r_totnode, PBVH_TexLeaf);
ob, sd, brush, use_original, radius_scale, PBVH_TexLeaf);
}
/* Calculate primary direction of movement for many brushes. */
static void calc_sculpt_normal(
Sculpt *sd, Object *ob, PBVHNode **nodes, int totnode, float r_area_no[3])
static void calc_sculpt_normal(Sculpt *sd, Object *ob, Span<PBVHNode *> nodes, float r_area_no[3])
{
const Brush *brush = BKE_paint_brush(&sd->paint);
const SculptSession *ss = ob->sculpt;
@@ -2962,7 +2933,7 @@ static void calc_sculpt_normal(
break;
case SCULPT_DISP_DIR_AREA:
SCULPT_calc_area_normal(sd, ob, nodes, totnode, r_area_no);
SCULPT_calc_area_normal(sd, ob, nodes, r_area_no);
break;
default:
@@ -2970,7 +2941,7 @@ static void calc_sculpt_normal(
}
}
static void update_sculpt_normal(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnode)
static void update_sculpt_normal(Sculpt *sd, Object *ob, Span<PBVHNode *> nodes)
{
const Brush *brush = BKE_paint_brush(&sd->paint);
StrokeCache *cache = ob->sculpt->cache;
@@ -2983,7 +2954,7 @@ static void update_sculpt_normal(Sculpt *sd, Object *ob, PBVHNode **nodes, int t
if (cache->mirror_symmetry_pass == 0 && cache->radial_symmetry_pass == 0 &&
(SCULPT_stroke_is_first_brush_step_of_symmetry_pass(cache) || update_normal)) {
calc_sculpt_normal(sd, ob, nodes, totnode, cache->sculpt_normal);
calc_sculpt_normal(sd, ob, nodes, cache->sculpt_normal);
if (brush->falloff_shape == PAINT_FALLOFF_SHAPE_TUBE) {
project_plane_v3_v3v3(cache->sculpt_normal, cache->sculpt_normal, cache->view_normal);
normalize_v3(cache->sculpt_normal);
@@ -3222,7 +3193,7 @@ void SCULPT_flip_quat_by_symm_area(float quat[4],
}
void SCULPT_calc_brush_plane(
Sculpt *sd, Object *ob, PBVHNode **nodes, int totnode, float r_area_no[3], float r_area_co[3])
Sculpt *sd, Object *ob, Span<PBVHNode *> nodes, float r_area_no[3], float r_area_co[3])
{
SculptSession *ss = ob->sculpt;
Brush *brush = BKE_paint_brush(&sd->paint);
@@ -3251,7 +3222,7 @@ void SCULPT_calc_brush_plane(
break;
case SCULPT_DISP_DIR_AREA:
SCULPT_calc_area_normal_and_center(sd, ob, nodes, totnode, r_area_no, r_area_co);
SCULPT_calc_area_normal_and_center(sd, ob, nodes, r_area_no, r_area_co);
if (brush->falloff_shape == PAINT_FALLOFF_SHAPE_TUBE) {
project_plane_v3_v3v3(r_area_no, r_area_no, ss->cache->view_normal);
normalize_v3(r_area_no);
@@ -3265,7 +3236,7 @@ void SCULPT_calc_brush_plane(
/* 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) {
SCULPT_calc_area_center(sd, ob, nodes, totnode, r_area_co);
SCULPT_calc_area_center(sd, ob, nodes, r_area_co);
}
/* For area normal. */
@@ -3384,7 +3355,7 @@ static void do_gravity_task_cb_ex(void *__restrict userdata,
BKE_pbvh_vertex_iter_end;
}
static void do_gravity(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnode, float bstrength)
static void do_gravity(Sculpt *sd, Object *ob, Span<PBVHNode *> nodes, float bstrength)
{
SculptSession *ss = ob->sculpt;
Brush *brush = BKE_paint_brush(&sd->paint);
@@ -3407,8 +3378,8 @@ static void do_gravity(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnode, fl
data.offset = offset;
TaskParallelSettings settings;
BKE_pbvh_parallel_range_settings(&settings, true, totnode);
BLI_task_parallel_range(0, totnode, &data, do_gravity_task_cb_ex, &settings);
BKE_pbvh_parallel_range_settings(&settings, true, nodes.size());
BLI_task_parallel_range(0, nodes.size(), &data, do_gravity_task_cb_ex, &settings);
}
/** \} */
@@ -3463,16 +3434,14 @@ static void sculpt_topology_update(Sculpt *sd,
{
SculptSession *ss = ob->sculpt;
int n, totnode;
/* Build a list of all nodes that are potentially within the brush's area of influence. */
const bool use_original = sculpt_tool_needs_original(brush->sculpt_tool) ? true :
ss->cache->original;
const float radius_scale = 1.25f;
PBVHNode **nodes = sculpt_pbvh_gather_generic(
ob, sd, brush, use_original, radius_scale, &totnode);
Vector<PBVHNode *> nodes = sculpt_pbvh_gather_generic(ob, sd, brush, use_original, radius_scale);
/* Only act if some verts are inside the brush area. */
if (totnode == 0) {
if (nodes.is_empty()) {
return;
}
@@ -3493,16 +3462,14 @@ static void sculpt_topology_update(Sculpt *sd,
}
}
for (n = 0; n < totnode; n++) {
SCULPT_undo_push_node(ob,
nodes[n],
brush->sculpt_tool == SCULPT_TOOL_MASK ? SCULPT_UNDO_MASK :
SCULPT_UNDO_COORDS);
BKE_pbvh_node_mark_update(nodes[n]);
for (PBVHNode *node : nodes) {
SCULPT_undo_push_node(
ob, node, brush->sculpt_tool == SCULPT_TOOL_MASK ? SCULPT_UNDO_MASK : SCULPT_UNDO_COORDS);
BKE_pbvh_node_mark_update(node);
if (BKE_pbvh_type(ss->pbvh) == PBVH_BMESH) {
BKE_pbvh_node_mark_topology_update(nodes[n]);
BKE_pbvh_bmesh_node_save_orig(ss->bm, ss->bm_log, nodes[n], false);
BKE_pbvh_node_mark_topology_update(node);
BKE_pbvh_bmesh_node_save_orig(ss->bm, ss->bm_log, node, false);
}
}
@@ -3516,8 +3483,6 @@ static void sculpt_topology_update(Sculpt *sd,
(brush->falloff_shape != PAINT_FALLOFF_SHAPE_SPHERE));
}
MEM_SAFE_FREE(nodes);
/* Update average stroke position. */
copy_v3_v3(location, ss->cache->true_location);
mul_m4_v3(ob->object_to_world, location);
@@ -3568,8 +3533,7 @@ static void do_brush_action(Sculpt *sd,
PaintModeSettings *paint_mode_settings)
{
SculptSession *ss = ob->sculpt;
int totnode, texnodes_num = 0;
PBVHNode **nodes, **texnodes = nullptr;
Vector<PBVHNode *> nodes, texnodes;
/* Check for unsupported features. */
PBVHType type = BKE_pbvh_type(ss->pbvh);
@@ -3589,9 +3553,9 @@ static void do_brush_action(Sculpt *sd,
if (sculpt_needs_pbvh_pixels(paint_mode_settings, brush, ob)) {
sculpt_pbvh_update_pixels(paint_mode_settings, ss, ob);
texnodes = sculpt_pbvh_gather_texpaint(ob, sd, brush, use_original, 1.0f, &texnodes_num);
texnodes = sculpt_pbvh_gather_texpaint(ob, sd, brush, use_original, 1.0f);
if (!texnodes_num) {
if (texnodes.is_empty()) {
return;
}
}
@@ -3600,10 +3564,10 @@ static void do_brush_action(Sculpt *sd,
if (SCULPT_tool_needs_all_pbvh_nodes(brush)) {
/* These brushes need to update all nodes as they are not constrained by the brush radius */
BKE_pbvh_search_gather(ss->pbvh, nullptr, nullptr, &nodes, &totnode);
nodes = blender::bke::pbvh::search_gather(ss->pbvh, nullptr, nullptr);
}
else if (brush->sculpt_tool == SCULPT_TOOL_CLOTH) {
nodes = SCULPT_cloth_brush_affected_nodes_gather(ss, brush, &totnode);
nodes = SCULPT_cloth_brush_affected_nodes_gather(ss, brush);
}
else {
float radius_scale = 1.0f;
@@ -3618,7 +3582,7 @@ static void do_brush_action(Sculpt *sd,
if (brush->sculpt_tool == SCULPT_TOOL_DRAW && brush->flag & BRUSH_ORIGINAL_NORMAL) {
radius_scale = 2.0f;
}
nodes = sculpt_pbvh_gather_generic(ob, sd, brush, use_original, radius_scale, &totnode);
nodes = sculpt_pbvh_gather_generic(ob, sd, brush, use_original, radius_scale);
}
/* Draw Face Sets in draw mode makes a single undo push, in alt-smooth mode deforms the
@@ -3639,7 +3603,7 @@ static void do_brush_action(Sculpt *sd,
/* For anchored brushes with spherical falloff, we start off with zero radius, thus we have no
* PBVH nodes on the first brush step. */
if (totnode ||
if (!nodes.is_empty() ||
((brush->falloff_shape == PAINT_FALLOFF_SHAPE_SPHERE) && (brush->flag & BRUSH_ANCHORED))) {
if (SCULPT_stroke_is_first_brush_step(ss->cache)) {
/* Initialize auto-masking cache. */
@@ -3659,8 +3623,7 @@ static void do_brush_action(Sculpt *sd,
}
/* Only act if some verts are inside the brush area. */
if (totnode == 0) {
MEM_SAFE_FREE(texnodes);
if (nodes.is_empty()) {
return;
}
float location[3];
@@ -3673,12 +3636,12 @@ static void do_brush_action(Sculpt *sd,
task_data.nodes = nodes;
TaskParallelSettings settings;
BKE_pbvh_parallel_range_settings(&settings, true, totnode);
BLI_task_parallel_range(0, totnode, &task_data, do_brush_action_task_cb, &settings);
BKE_pbvh_parallel_range_settings(&settings, true, nodes.size());
BLI_task_parallel_range(0, nodes.size(), &task_data, do_brush_action_task_cb, &settings);
}
if (sculpt_brush_needs_normal(ss, sd, brush)) {
update_sculpt_normal(sd, ob, nodes, totnode);
update_sculpt_normal(sd, ob, nodes);
}
update_brush_local_mat(sd, ob);
@@ -3695,7 +3658,7 @@ static void do_brush_action(Sculpt *sd,
}
SCULPT_cloth_brush_store_simulation_state(ss, ss->cache->cloth_sim);
SCULPT_cloth_brush_ensure_nodes_constraints(
sd, ob, nodes, totnode, ss->cache->cloth_sim, ss->cache->location, FLT_MAX);
sd, ob, nodes, ss->cache->cloth_sim, ss->cache->location, FLT_MAX);
}
bool invert = ss->cache->pen_flip || ss->cache->invert || brush->flag & BRUSH_DIR_IN;
@@ -3703,128 +3666,127 @@ static void do_brush_action(Sculpt *sd,
/* Apply one type of brush action. */
switch (brush->sculpt_tool) {
case SCULPT_TOOL_DRAW:
SCULPT_do_draw_brush(sd, ob, nodes, totnode);
SCULPT_do_draw_brush(sd, ob, nodes);
break;
case SCULPT_TOOL_SMOOTH:
if (brush->smooth_deform_type == BRUSH_SMOOTH_DEFORM_LAPLACIAN) {
SCULPT_do_smooth_brush(sd, ob, nodes, totnode);
SCULPT_do_smooth_brush(sd, ob, nodes);
}
else if (brush->smooth_deform_type == BRUSH_SMOOTH_DEFORM_SURFACE) {
SCULPT_do_surface_smooth_brush(sd, ob, nodes, totnode);
SCULPT_do_surface_smooth_brush(sd, ob, nodes);
}
break;
case SCULPT_TOOL_CREASE:
SCULPT_do_crease_brush(sd, ob, nodes, totnode);
SCULPT_do_crease_brush(sd, ob, nodes);
break;
case SCULPT_TOOL_BLOB:
SCULPT_do_crease_brush(sd, ob, nodes, totnode);
SCULPT_do_crease_brush(sd, ob, nodes);
break;
case SCULPT_TOOL_PINCH:
SCULPT_do_pinch_brush(sd, ob, nodes, totnode);
SCULPT_do_pinch_brush(sd, ob, nodes);
break;
case SCULPT_TOOL_INFLATE:
SCULPT_do_inflate_brush(sd, ob, nodes, totnode);
SCULPT_do_inflate_brush(sd, ob, nodes);
break;
case SCULPT_TOOL_GRAB:
SCULPT_do_grab_brush(sd, ob, nodes, totnode);
SCULPT_do_grab_brush(sd, ob, nodes);
break;
case SCULPT_TOOL_ROTATE:
SCULPT_do_rotate_brush(sd, ob, nodes, totnode);
SCULPT_do_rotate_brush(sd, ob, nodes);
break;
case SCULPT_TOOL_SNAKE_HOOK:
SCULPT_do_snake_hook_brush(sd, ob, nodes, totnode);
SCULPT_do_snake_hook_brush(sd, ob, nodes);
break;
case SCULPT_TOOL_NUDGE:
SCULPT_do_nudge_brush(sd, ob, nodes, totnode);
SCULPT_do_nudge_brush(sd, ob, nodes);
break;
case SCULPT_TOOL_THUMB:
SCULPT_do_thumb_brush(sd, ob, nodes, totnode);
SCULPT_do_thumb_brush(sd, ob, nodes);
break;
case SCULPT_TOOL_LAYER:
SCULPT_do_layer_brush(sd, ob, nodes, totnode);
SCULPT_do_layer_brush(sd, ob, nodes);
break;
case SCULPT_TOOL_FLATTEN:
SCULPT_do_flatten_brush(sd, ob, nodes, totnode);
SCULPT_do_flatten_brush(sd, ob, nodes);
break;
case SCULPT_TOOL_CLAY:
SCULPT_do_clay_brush(sd, ob, nodes, totnode);
SCULPT_do_clay_brush(sd, ob, nodes);
break;
case SCULPT_TOOL_CLAY_STRIPS:
SCULPT_do_clay_strips_brush(sd, ob, nodes, totnode);
SCULPT_do_clay_strips_brush(sd, ob, nodes);
break;
case SCULPT_TOOL_MULTIPLANE_SCRAPE:
SCULPT_do_multiplane_scrape_brush(sd, ob, nodes, totnode);
SCULPT_do_multiplane_scrape_brush(sd, ob, nodes);
break;
case SCULPT_TOOL_CLAY_THUMB:
SCULPT_do_clay_thumb_brush(sd, ob, nodes, totnode);
SCULPT_do_clay_thumb_brush(sd, ob, nodes);
break;
case SCULPT_TOOL_FILL:
if (invert && brush->flag & BRUSH_INVERT_TO_SCRAPE_FILL) {
SCULPT_do_scrape_brush(sd, ob, nodes, totnode);
SCULPT_do_scrape_brush(sd, ob, nodes);
}
else {
SCULPT_do_fill_brush(sd, ob, nodes, totnode);
SCULPT_do_fill_brush(sd, ob, nodes);
}
break;
case SCULPT_TOOL_SCRAPE:
if (invert && brush->flag & BRUSH_INVERT_TO_SCRAPE_FILL) {
SCULPT_do_fill_brush(sd, ob, nodes, totnode);
SCULPT_do_fill_brush(sd, ob, nodes);
}
else {
SCULPT_do_scrape_brush(sd, ob, nodes, totnode);
SCULPT_do_scrape_brush(sd, ob, nodes);
}
break;
case SCULPT_TOOL_MASK:
SCULPT_do_mask_brush(sd, ob, nodes, totnode);
SCULPT_do_mask_brush(sd, ob, nodes);
break;
case SCULPT_TOOL_POSE:
SCULPT_do_pose_brush(sd, ob, nodes, totnode);
SCULPT_do_pose_brush(sd, ob, nodes);
break;
case SCULPT_TOOL_DRAW_SHARP:
SCULPT_do_draw_sharp_brush(sd, ob, nodes, totnode);
SCULPT_do_draw_sharp_brush(sd, ob, nodes);
break;
case SCULPT_TOOL_ELASTIC_DEFORM:
SCULPT_do_elastic_deform_brush(sd, ob, nodes, totnode);
SCULPT_do_elastic_deform_brush(sd, ob, nodes);
break;
case SCULPT_TOOL_SLIDE_RELAX:
SCULPT_do_slide_relax_brush(sd, ob, nodes, totnode);
SCULPT_do_slide_relax_brush(sd, ob, nodes);
break;
case SCULPT_TOOL_BOUNDARY:
SCULPT_do_boundary_brush(sd, ob, nodes, totnode);
SCULPT_do_boundary_brush(sd, ob, nodes);
break;
case SCULPT_TOOL_CLOTH:
SCULPT_do_cloth_brush(sd, ob, nodes, totnode);
SCULPT_do_cloth_brush(sd, ob, nodes);
break;
case SCULPT_TOOL_DRAW_FACE_SETS:
SCULPT_do_draw_face_sets_brush(sd, ob, nodes, totnode);
SCULPT_do_draw_face_sets_brush(sd, ob, nodes);
break;
case SCULPT_TOOL_DISPLACEMENT_ERASER:
SCULPT_do_displacement_eraser_brush(sd, ob, nodes, totnode);
SCULPT_do_displacement_eraser_brush(sd, ob, nodes);
break;
case SCULPT_TOOL_DISPLACEMENT_SMEAR:
SCULPT_do_displacement_smear_brush(sd, ob, nodes, totnode);
SCULPT_do_displacement_smear_brush(sd, ob, nodes);
break;
case SCULPT_TOOL_PAINT:
SCULPT_do_paint_brush(paint_mode_settings, sd, ob, nodes, totnode, texnodes, texnodes_num);
SCULPT_do_paint_brush(paint_mode_settings, sd, ob, nodes, texnodes);
break;
case SCULPT_TOOL_SMEAR:
SCULPT_do_smear_brush(sd, ob, nodes, totnode);
SCULPT_do_smear_brush(sd, ob, nodes);
break;
}
if (!ELEM(brush->sculpt_tool, SCULPT_TOOL_SMOOTH, SCULPT_TOOL_MASK) &&
brush->autosmooth_factor > 0) {
if (brush->flag & BRUSH_INVERSE_SMOOTH_PRESSURE) {
SCULPT_smooth(
sd, ob, nodes, totnode, brush->autosmooth_factor * (1.0f - ss->cache->pressure), false);
SCULPT_smooth(sd, ob, nodes, brush->autosmooth_factor * (1.0f - ss->cache->pressure), false);
}
else {
SCULPT_smooth(sd, ob, nodes, totnode, brush->autosmooth_factor, false);
SCULPT_smooth(sd, ob, nodes, brush->autosmooth_factor, false);
}
}
if (sculpt_brush_use_topology_rake(ss, brush)) {
SCULPT_bmesh_topology_rake(sd, ob, nodes, totnode, brush->topology_rake_factor);
SCULPT_bmesh_topology_rake(sd, ob, nodes, brush->topology_rake_factor);
}
if (!SCULPT_tool_can_reuse_automask(brush->sculpt_tool) ||
@@ -3838,19 +3800,16 @@ static void do_brush_action(Sculpt *sd,
SCULPT_TOOL_CLOTH,
SCULPT_TOOL_DRAW_FACE_SETS,
SCULPT_TOOL_BOUNDARY)) {
do_gravity(sd, ob, nodes, totnode, sd->gravity_factor);
do_gravity(sd, ob, nodes, sd->gravity_factor);
}
if (brush->deform_target == BRUSH_DEFORM_TARGET_CLOTH_SIM) {
if (SCULPT_stroke_is_main_symmetry_pass(ss->cache)) {
SCULPT_cloth_sim_activate_nodes(ss->cache->cloth_sim, nodes, totnode);
SCULPT_cloth_brush_do_simulation_step(sd, ob, ss->cache->cloth_sim, nodes, totnode);
SCULPT_cloth_sim_activate_nodes(ss->cache->cloth_sim, nodes);
SCULPT_cloth_brush_do_simulation_step(sd, ob, ss->cache->cloth_sim, nodes);
}
}
MEM_SAFE_FREE(nodes);
MEM_SAFE_FREE(texnodes);
/* Update average stroke position. */
copy_v3_v3(location, ss->cache->true_location);
mul_m4_v3(ob->object_to_world, location);
@@ -3951,17 +3910,13 @@ static void sculpt_combine_proxies(Sculpt *sd, Object *ob)
SCULPT_TOOL_BOUNDARY,
SCULPT_TOOL_POSE);
int totnode;
PBVHNode **nodes;
BKE_pbvh_gather_proxies(ss->pbvh, &nodes, &totnode);
Vector<PBVHNode *> nodes = blender::bke::pbvh::gather_proxies(ss->pbvh);
threading::parallel_for(IndexRange(totnode), 1, [&](IndexRange range) {
threading::parallel_for(nodes.index_range(), 1, [&](IndexRange range) {
for (const int i : range) {
sculpt_combine_proxies_node(*ob, *sd, use_orco, *nodes[i]);
}
});
MEM_SAFE_FREE(nodes);
}
void SCULPT_combine_transform_proxies(Sculpt *sd, Object *ob)
@@ -3969,17 +3924,13 @@ void SCULPT_combine_transform_proxies(Sculpt *sd, Object *ob)
using namespace blender;
SculptSession *ss = ob->sculpt;
int totnode;
PBVHNode **nodes;
BKE_pbvh_gather_proxies(ss->pbvh, &nodes, &totnode);
Vector<PBVHNode *> nodes = blender::bke::pbvh::gather_proxies(ss->pbvh);
threading::parallel_for(IndexRange(totnode), 1, [&](IndexRange range) {
threading::parallel_for(nodes.index_range(), 1, [&](IndexRange range) {
for (const int i : range) {
sculpt_combine_proxies_node(*ob, *sd, false, *nodes[i]);
}
});
MEM_SAFE_FREE(nodes);
}
/**
@@ -4019,9 +3970,8 @@ void SCULPT_flush_stroke_deform(Sculpt * /*sd*/, Object *ob, bool is_proxy_used)
/* This brushes aren't using proxies, so sculpt_combine_proxies() wouldn't propagate needed
* deformation to original base. */
int totnode;
Mesh *me = (Mesh *)ob->data;
PBVHNode **nodes;
Vector<PBVHNode *> nodes;
float(*vertCos)[3] = nullptr;
if (ss->shapekey_active) {
@@ -4033,11 +3983,11 @@ void SCULPT_flush_stroke_deform(Sculpt * /*sd*/, Object *ob, bool is_proxy_used)
memcpy(vertCos, ss->orig_cos, sizeof(*vertCos) * me->totvert);
}
BKE_pbvh_search_gather(ss->pbvh, nullptr, nullptr, &nodes, &totnode);
nodes = blender::bke::pbvh::search_gather(ss->pbvh, nullptr, nullptr);
MutableSpan<float3> positions = me->vert_positions_for_write();
threading::parallel_for(IndexRange(totnode), 1, [&](IndexRange range) {
threading::parallel_for(nodes.index_range(), 1, [&](IndexRange range) {
for (const int i : range) {
PBVHVertexIter vd;
BKE_pbvh_vertex_iter_begin (ss->pbvh, nodes[i], vd, PBVH_ITER_UNIQUE) {
@@ -4058,8 +4008,6 @@ void SCULPT_flush_stroke_deform(Sculpt * /*sd*/, Object *ob, bool is_proxy_used)
SCULPT_vertcos_to_key(ob, ss->shapekey_active, vertCos);
MEM_freeN(vertCos);
}
MEM_SAFE_FREE(nodes);
}
else if (ss->shapekey_active) {
sculpt_update_keyblock(ob);
@@ -5162,7 +5110,6 @@ bool SCULPT_cursor_geometry_info_update(bContext *C,
float ray_start[3], ray_end[3], ray_normal[3], depth, face_normal[3], sampled_normal[3],
mat[3][3];
float viewDir[3] = {0.0f, 0.0f, 1.0f};
int totnode;
bool original = false;
ED_view3d_viewcontext_init(C, &vc, depsgraph);
@@ -5254,17 +5201,16 @@ bool SCULPT_cursor_geometry_info_update(bContext *C,
}
ss->cursor_radius = radius;
PBVHNode **nodes = sculpt_pbvh_gather_cursor_update(ob, sd, original, &totnode);
Vector<PBVHNode *> nodes = sculpt_pbvh_gather_cursor_update(ob, sd, original);
/* In case there are no nodes under the cursor, return the face normal. */
if (!totnode) {
MEM_SAFE_FREE(nodes);
if (nodes.is_empty()) {
copy_v3_v3(out->normal, srd.face_normal);
return true;
}
/* Calculate the sampled normal. */
if (SCULPT_pbvh_calc_area_normal(brush, ob, nodes, totnode, true, sampled_normal)) {
if (SCULPT_pbvh_calc_area_normal(brush, ob, nodes, true, sampled_normal)) {
copy_v3_v3(out->normal, sampled_normal);
copy_v3_v3(ss->cursor_sampled_normal, sampled_normal);
}
@@ -5272,7 +5218,6 @@ bool SCULPT_cursor_geometry_info_update(bContext *C,
/* Use face normal when there are no vertices to sample inside the cursor radius. */
copy_v3_v3(out->normal, srd.face_normal);
}
MEM_SAFE_FREE(nodes);
return true;
}
@@ -6138,8 +6083,8 @@ static PBVHVertRef SCULPT_fake_neighbor_search(Sculpt *sd,
float max_distance)
{
SculptSession *ss = ob->sculpt;
PBVHNode **nodes = nullptr;
int totnode;
Vector<PBVHNode *> nodes;
SculptSearchSphereData data{};
data.ss = ss;
data.sd = sd;
@@ -6147,9 +6092,9 @@ static PBVHVertRef SCULPT_fake_neighbor_search(Sculpt *sd,
data.original = false;
data.center = SCULPT_vertex_co_get(ss, vertex);
BKE_pbvh_search_gather(ss->pbvh, SCULPT_search_sphere_cb, &data, &nodes, &totnode);
nodes = blender::bke::pbvh::search_gather(ss->pbvh, SCULPT_search_sphere_cb, &data);
if (totnode == 0) {
if (nodes.is_empty()) {
return BKE_pbvh_make_vref(PBVH_REF_NONE);
}
@@ -6167,13 +6112,11 @@ static PBVHVertRef SCULPT_fake_neighbor_search(Sculpt *sd,
nvtd.current_topology_id = SCULPT_vertex_island_get(ss, vertex);
TaskParallelSettings settings;
BKE_pbvh_parallel_range_settings(&settings, true, totnode);
BKE_pbvh_parallel_range_settings(&settings, true, nodes.size());
settings.func_reduce = fake_neighbor_search_reduce;
settings.userdata_chunk = &nvtd;
settings.userdata_chunk_size = sizeof(NearestVertexFakeNeighborTLSData);
BLI_task_parallel_range(0, totnode, &task_data, do_fake_neighbor_search_task_cb, &settings);
MEM_SAFE_FREE(nodes);
BLI_task_parallel_range(0, nodes.size(), &task_data, do_fake_neighbor_search_task_cb, &settings);
return nvtd.nearest_vertex;
}

View File

@@ -973,7 +973,7 @@ static void do_boundary_brush_smooth_task_cb_ex(void *__restrict userdata,
BKE_pbvh_vertex_iter_end;
}
void SCULPT_do_boundary_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnode)
void SCULPT_do_boundary_brush(Sculpt *sd, Object *ob, Span<PBVHNode *> nodes)
{
SculptSession *ss = ob->sculpt;
Brush *brush = BKE_paint_brush(&sd->paint);
@@ -1031,26 +1031,32 @@ void SCULPT_do_boundary_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totn
data.nodes = nodes;
TaskParallelSettings settings;
BKE_pbvh_parallel_range_settings(&settings, true, totnode);
BKE_pbvh_parallel_range_settings(&settings, true, nodes.size());
switch (brush->boundary_deform_type) {
case BRUSH_BOUNDARY_DEFORM_BEND:
BLI_task_parallel_range(0, totnode, &data, do_boundary_brush_bend_task_cb_ex, &settings);
BLI_task_parallel_range(
0, nodes.size(), &data, do_boundary_brush_bend_task_cb_ex, &settings);
break;
case BRUSH_BOUNDARY_DEFORM_EXPAND:
BLI_task_parallel_range(0, totnode, &data, do_boundary_brush_slide_task_cb_ex, &settings);
BLI_task_parallel_range(
0, nodes.size(), &data, do_boundary_brush_slide_task_cb_ex, &settings);
break;
case BRUSH_BOUNDARY_DEFORM_INFLATE:
BLI_task_parallel_range(0, totnode, &data, do_boundary_brush_inflate_task_cb_ex, &settings);
BLI_task_parallel_range(
0, nodes.size(), &data, do_boundary_brush_inflate_task_cb_ex, &settings);
break;
case BRUSH_BOUNDARY_DEFORM_GRAB:
BLI_task_parallel_range(0, totnode, &data, do_boundary_brush_grab_task_cb_ex, &settings);
BLI_task_parallel_range(
0, nodes.size(), &data, do_boundary_brush_grab_task_cb_ex, &settings);
break;
case BRUSH_BOUNDARY_DEFORM_TWIST:
BLI_task_parallel_range(0, totnode, &data, do_boundary_brush_twist_task_cb_ex, &settings);
BLI_task_parallel_range(
0, nodes.size(), &data, do_boundary_brush_twist_task_cb_ex, &settings);
break;
case BRUSH_BOUNDARY_DEFORM_SMOOTH:
BLI_task_parallel_range(0, totnode, &data, do_boundary_brush_smooth_task_cb_ex, &settings);
BLI_task_parallel_range(
0, nodes.size(), &data, do_boundary_brush_smooth_task_cb_ex, &settings);
break;
}
}

View File

@@ -13,6 +13,7 @@
#include "BLI_math.h"
#include "BLI_task.h"
#include "BLI_utildefines.h"
#include "BLI_span.hh"
#include "DNA_brush_types.h"
#include "DNA_customdata_types.h"
@@ -39,6 +40,8 @@
#include <cstdlib>
#include <cstring>
using blender::Span;
/* -------------------------------------------------------------------- */
/** \name SculptProjectVector
*
@@ -86,7 +89,7 @@ static void sculpt_project_v3(const SculptProjectVector *spvc, const float vec[3
}
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, Span<PBVHNode *> nodes, float r_area_no[3], float r_area_co[3])
{
SculptSession *ss = ob->sculpt;
Brush *brush = BKE_paint_brush(&sd->paint);
@@ -112,7 +115,7 @@ static void calc_sculpt_plane(
break;
case SCULPT_DISP_DIR_AREA:
SCULPT_calc_area_normal_and_center(sd, ob, nodes, totnode, r_area_no, r_area_co);
SCULPT_calc_area_normal_and_center(sd, ob, nodes, r_area_no, r_area_co);
if (brush->falloff_shape == PAINT_FALLOFF_SHAPE_TUBE) {
project_plane_v3_v3v3(r_area_no, r_area_no, ss->cache->view_normal);
normalize_v3(r_area_no);
@@ -126,7 +129,7 @@ static void calc_sculpt_plane(
/* 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) {
SCULPT_calc_area_center(sd, ob, nodes, totnode, r_area_co);
SCULPT_calc_area_center(sd, ob, nodes, r_area_co);
}
/* For area normal. */
@@ -302,7 +305,7 @@ static void do_draw_brush_task_cb_ex(void *__restrict userdata,
BKE_pbvh_vertex_iter_end;
}
void SCULPT_do_draw_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnode)
void SCULPT_do_draw_brush(Sculpt *sd, Object *ob, Span<PBVHNode *> nodes)
{
SculptSession *ss = ob->sculpt;
Brush *brush = BKE_paint_brush(&sd->paint);
@@ -329,8 +332,8 @@ void SCULPT_do_draw_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnode)
data.offset = offset;
TaskParallelSettings settings;
BKE_pbvh_parallel_range_settings(&settings, true, totnode);
BLI_task_parallel_range(0, totnode, &data, do_draw_brush_task_cb_ex, &settings);
BKE_pbvh_parallel_range_settings(&settings, true, nodes.size());
BLI_task_parallel_range(0, nodes.size(), &data, do_draw_brush_task_cb_ex, &settings);
}
/** \} */
@@ -406,7 +409,7 @@ static void do_fill_brush_task_cb_ex(void *__restrict userdata,
BKE_pbvh_vertex_iter_end;
}
void SCULPT_do_fill_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnode)
void SCULPT_do_fill_brush(Sculpt *sd, Object *ob, Span<PBVHNode *> nodes)
{
SculptSession *ss = ob->sculpt;
Brush *brush = BKE_paint_brush(&sd->paint);
@@ -421,7 +424,7 @@ void SCULPT_do_fill_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnode)
float temp[3];
SCULPT_calc_brush_plane(sd, ob, nodes, totnode, area_no, area_co);
SCULPT_calc_brush_plane(sd, ob, nodes, area_no, area_co);
SCULPT_tilt_apply_to_normal(area_no, ss->cache, brush->tilt_strength_factor);
@@ -440,8 +443,8 @@ void SCULPT_do_fill_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnode)
data.area_co = area_co;
TaskParallelSettings settings;
BKE_pbvh_parallel_range_settings(&settings, true, totnode);
BLI_task_parallel_range(0, totnode, &data, do_fill_brush_task_cb_ex, &settings);
BKE_pbvh_parallel_range_settings(&settings, true, nodes.size());
BLI_task_parallel_range(0, nodes.size(), &data, do_fill_brush_task_cb_ex, &settings);
}
static void do_scrape_brush_task_cb_ex(void *__restrict userdata,
@@ -510,7 +513,7 @@ static void do_scrape_brush_task_cb_ex(void *__restrict userdata,
BKE_pbvh_vertex_iter_end;
}
void SCULPT_do_scrape_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnode)
void SCULPT_do_scrape_brush(Sculpt *sd, Object *ob, Span<PBVHNode *> nodes)
{
SculptSession *ss = ob->sculpt;
Brush *brush = BKE_paint_brush(&sd->paint);
@@ -525,7 +528,7 @@ void SCULPT_do_scrape_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnod
float temp[3];
SCULPT_calc_brush_plane(sd, ob, nodes, totnode, area_no, area_co);
SCULPT_calc_brush_plane(sd, ob, nodes, area_no, area_co);
SCULPT_tilt_apply_to_normal(area_no, ss->cache, brush->tilt_strength_factor);
@@ -544,8 +547,8 @@ void SCULPT_do_scrape_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnod
data.area_co = area_co;
TaskParallelSettings settings;
BKE_pbvh_parallel_range_settings(&settings, true, totnode);
BLI_task_parallel_range(0, totnode, &data, do_scrape_brush_task_cb_ex, &settings);
BKE_pbvh_parallel_range_settings(&settings, true, nodes.size());
BLI_task_parallel_range(0, nodes.size(), &data, do_scrape_brush_task_cb_ex, &settings);
}
/** \} */
@@ -643,7 +646,7 @@ float SCULPT_clay_thumb_get_stabilized_pressure(StrokeCache *cache)
return final_pressure / SCULPT_CLAY_STABILIZER_LEN;
}
void SCULPT_do_clay_thumb_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnode)
void SCULPT_do_clay_thumb_brush(Sculpt *sd, Object *ob, Span<PBVHNode *> nodes)
{
SculptSession *ss = ob->sculpt;
Brush *brush = BKE_paint_brush(&sd->paint);
@@ -662,10 +665,10 @@ void SCULPT_do_clay_thumb_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int to
float scale[4][4];
float tmat[4][4];
SCULPT_calc_brush_plane(sd, ob, nodes, totnode, area_no_sp, area_co);
SCULPT_calc_brush_plane(sd, ob, nodes, area_no_sp, area_co);
if (brush->sculpt_plane != SCULPT_DISP_DIR_AREA || (brush->flag & BRUSH_ORIGINAL_NORMAL)) {
SCULPT_calc_area_normal(sd, ob, nodes, totnode, area_no);
SCULPT_calc_area_normal(sd, ob, nodes, area_no);
}
else {
copy_v3_v3(area_no, area_no_sp);
@@ -724,8 +727,8 @@ void SCULPT_do_clay_thumb_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int to
data.clay_strength = clay_strength;
TaskParallelSettings settings;
BKE_pbvh_parallel_range_settings(&settings, true, totnode);
BLI_task_parallel_range(0, totnode, &data, do_clay_thumb_brush_task_cb_ex, &settings);
BKE_pbvh_parallel_range_settings(&settings, true, nodes.size());
BLI_task_parallel_range(0, nodes.size(), &data, do_clay_thumb_brush_task_cb_ex, &settings);
}
/** \} */
@@ -796,7 +799,7 @@ static void do_flatten_brush_task_cb_ex(void *__restrict userdata,
BKE_pbvh_vertex_iter_end;
}
void SCULPT_do_flatten_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnode)
void SCULPT_do_flatten_brush(Sculpt *sd, Object *ob, Span<PBVHNode *> nodes)
{
SculptSession *ss = ob->sculpt;
Brush *brush = BKE_paint_brush(&sd->paint);
@@ -810,7 +813,7 @@ void SCULPT_do_flatten_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totno
float displace;
float temp[3];
SCULPT_calc_brush_plane(sd, ob, nodes, totnode, area_no, area_co);
SCULPT_calc_brush_plane(sd, ob, nodes, area_no, area_co);
SCULPT_tilt_apply_to_normal(area_no, ss->cache, brush->tilt_strength_factor);
@@ -829,8 +832,8 @@ void SCULPT_do_flatten_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totno
data.area_co = area_co;
TaskParallelSettings settings;
BKE_pbvh_parallel_range_settings(&settings, true, totnode);
BLI_task_parallel_range(0, totnode, &data, do_flatten_brush_task_cb_ex, &settings);
BKE_pbvh_parallel_range_settings(&settings, true, nodes.size());
BLI_task_parallel_range(0, nodes.size(), &data, do_flatten_brush_task_cb_ex, &settings);
}
/** \} */
@@ -958,7 +961,7 @@ static void do_clay_brush_task_cb_ex(void *__restrict userdata,
BKE_pbvh_vertex_iter_end;
}
void SCULPT_do_clay_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnode)
void SCULPT_do_clay_brush(Sculpt *sd, Object *ob, Span<PBVHNode *> nodes)
{
SculptSession *ss = ob->sculpt;
Brush *brush = BKE_paint_brush(&sd->paint);
@@ -974,26 +977,26 @@ void SCULPT_do_clay_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnode)
float area_co[3];
float temp[3];
SCULPT_calc_brush_plane(sd, ob, nodes, totnode, area_no, area_co);
SCULPT_calc_brush_plane(sd, ob, nodes, area_no, area_co);
SculptThreadedTaskData sample_data{};
sample_data.sd = nullptr;
sample_data.ob = ob;
sample_data.brush = brush;
sample_data.nodes = nodes;
sample_data.totnode = totnode;
sample_data.area_no = area_no;
sample_data.area_co = ss->cache->location;
ClaySampleData csd = {{0}};
TaskParallelSettings sample_settings;
BKE_pbvh_parallel_range_settings(&sample_settings, true, totnode);
BKE_pbvh_parallel_range_settings(&sample_settings, true, nodes.size());
sample_settings.func_reduce = calc_clay_surface_reduce;
sample_settings.userdata_chunk = &csd;
sample_settings.userdata_chunk_size = sizeof(ClaySampleData);
BLI_task_parallel_range(0, totnode, &sample_data, calc_clay_surface_task_cb, &sample_settings);
BLI_task_parallel_range(
0, nodes.size(), &sample_data, calc_clay_surface_task_cb, &sample_settings);
float d_offset = (csd.plane_dist[0] + csd.plane_dist[1]);
d_offset = min_ff(radius, d_offset);
@@ -1018,8 +1021,8 @@ void SCULPT_do_clay_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnode)
data.area_co = area_co;
TaskParallelSettings settings;
BKE_pbvh_parallel_range_settings(&settings, true, totnode);
BLI_task_parallel_range(0, totnode, &data, do_clay_brush_task_cb_ex, &settings);
BKE_pbvh_parallel_range_settings(&settings, true, nodes.size());
BLI_task_parallel_range(0, nodes.size(), &data, do_clay_brush_task_cb_ex, &settings);
}
static void do_clay_strips_brush_task_cb_ex(void *__restrict userdata,
@@ -1090,7 +1093,7 @@ static void do_clay_strips_brush_task_cb_ex(void *__restrict userdata,
BKE_pbvh_vertex_iter_end;
}
void SCULPT_do_clay_strips_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnode)
void SCULPT_do_clay_strips_brush(Sculpt *sd, Object *ob, Span<PBVHNode *> nodes)
{
SculptSession *ss = ob->sculpt;
Brush *brush = BKE_paint_brush(&sd->paint);
@@ -1112,11 +1115,11 @@ void SCULPT_do_clay_strips_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int t
float scale[4][4];
float tmat[4][4];
SCULPT_calc_brush_plane(sd, ob, nodes, totnode, area_no_sp, area_co);
SCULPT_calc_brush_plane(sd, ob, nodes, area_no_sp, area_co);
SCULPT_tilt_apply_to_normal(area_no_sp, ss->cache, brush->tilt_strength_factor);
if (brush->sculpt_plane != SCULPT_DISP_DIR_AREA || (brush->flag & BRUSH_ORIGINAL_NORMAL)) {
SCULPT_calc_area_normal(sd, ob, nodes, totnode, area_no);
SCULPT_calc_area_normal(sd, ob, nodes, area_no);
}
else {
copy_v3_v3(area_no, area_no_sp);
@@ -1178,8 +1181,8 @@ void SCULPT_do_clay_strips_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int t
data.mat = mat;
TaskParallelSettings settings;
BKE_pbvh_parallel_range_settings(&settings, true, totnode);
BLI_task_parallel_range(0, totnode, &data, do_clay_strips_brush_task_cb_ex, &settings);
BKE_pbvh_parallel_range_settings(&settings, true, nodes.size());
BLI_task_parallel_range(0, nodes.size(), &data, do_clay_strips_brush_task_cb_ex, &settings);
}
static void do_snake_hook_brush_task_cb_ex(void *__restrict userdata,
@@ -1298,7 +1301,7 @@ static void do_snake_hook_brush_task_cb_ex(void *__restrict userdata,
BKE_pbvh_vertex_iter_end;
}
void SCULPT_do_snake_hook_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnode)
void SCULPT_do_snake_hook_brush(Sculpt *sd, Object *ob, Span<PBVHNode *> nodes)
{
SculptSession *ss = ob->sculpt;
Brush *brush = BKE_paint_brush(&sd->paint);
@@ -1331,8 +1334,8 @@ void SCULPT_do_snake_hook_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int to
data.grab_delta = grab_delta;
TaskParallelSettings settings;
BKE_pbvh_parallel_range_settings(&settings, true, totnode);
BLI_task_parallel_range(0, totnode, &data, do_snake_hook_brush_task_cb_ex, &settings);
BKE_pbvh_parallel_range_settings(&settings, true, nodes.size());
BLI_task_parallel_range(0, nodes.size(), &data, do_snake_hook_brush_task_cb_ex, &settings);
}
static void do_thumb_brush_task_cb_ex(void *__restrict userdata,
@@ -1390,7 +1393,7 @@ static void do_thumb_brush_task_cb_ex(void *__restrict userdata,
BKE_pbvh_vertex_iter_end;
}
void SCULPT_do_thumb_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnode)
void SCULPT_do_thumb_brush(Sculpt *sd, Object *ob, Span<PBVHNode *> nodes)
{
SculptSession *ss = ob->sculpt;
Brush *brush = BKE_paint_brush(&sd->paint);
@@ -1410,8 +1413,8 @@ void SCULPT_do_thumb_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnode
data.cono = cono;
TaskParallelSettings settings;
BKE_pbvh_parallel_range_settings(&settings, true, totnode);
BLI_task_parallel_range(0, totnode, &data, do_thumb_brush_task_cb_ex, &settings);
BKE_pbvh_parallel_range_settings(&settings, true, nodes.size());
BLI_task_parallel_range(0, nodes.size(), &data, do_thumb_brush_task_cb_ex, &settings);
}
static void do_rotate_brush_task_cb_ex(void *__restrict userdata,
@@ -1475,7 +1478,7 @@ static void do_rotate_brush_task_cb_ex(void *__restrict userdata,
BKE_pbvh_vertex_iter_end;
}
void SCULPT_do_rotate_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnode)
void SCULPT_do_rotate_brush(Sculpt *sd, Object *ob, Span<PBVHNode *> nodes)
{
SculptSession *ss = ob->sculpt;
Brush *brush = BKE_paint_brush(&sd->paint);
@@ -1491,8 +1494,8 @@ void SCULPT_do_rotate_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnod
data.angle = angle;
TaskParallelSettings settings;
BKE_pbvh_parallel_range_settings(&settings, true, totnode);
BLI_task_parallel_range(0, totnode, &data, do_rotate_brush_task_cb_ex, &settings);
BKE_pbvh_parallel_range_settings(&settings, true, nodes.size());
BLI_task_parallel_range(0, nodes.size(), &data, do_rotate_brush_task_cb_ex, &settings);
}
static void do_layer_brush_task_cb_ex(void *__restrict userdata,
@@ -1598,7 +1601,7 @@ static void do_layer_brush_task_cb_ex(void *__restrict userdata,
BKE_pbvh_vertex_iter_end;
}
void SCULPT_do_layer_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnode)
void SCULPT_do_layer_brush(Sculpt *sd, Object *ob, Span<PBVHNode *> nodes)
{
SculptSession *ss = ob->sculpt;
Brush *brush = BKE_paint_brush(&sd->paint);
@@ -1615,8 +1618,8 @@ void SCULPT_do_layer_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnode
data.nodes = nodes;
TaskParallelSettings settings;
BKE_pbvh_parallel_range_settings(&settings, true, totnode);
BLI_task_parallel_range(0, totnode, &data, do_layer_brush_task_cb_ex, &settings);
BKE_pbvh_parallel_range_settings(&settings, true, nodes.size());
BLI_task_parallel_range(0, nodes.size(), &data, do_layer_brush_task_cb_ex, &settings);
}
static void do_inflate_brush_task_cb_ex(void *__restrict userdata,
@@ -1677,7 +1680,7 @@ static void do_inflate_brush_task_cb_ex(void *__restrict userdata,
BKE_pbvh_vertex_iter_end;
}
void SCULPT_do_inflate_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnode)
void SCULPT_do_inflate_brush(Sculpt *sd, Object *ob, Span<PBVHNode *> nodes)
{
Brush *brush = BKE_paint_brush(&sd->paint);
@@ -1688,8 +1691,8 @@ void SCULPT_do_inflate_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totno
data.nodes = nodes;
TaskParallelSettings settings;
BKE_pbvh_parallel_range_settings(&settings, true, totnode);
BLI_task_parallel_range(0, totnode, &data, do_inflate_brush_task_cb_ex, &settings);
BKE_pbvh_parallel_range_settings(&settings, true, nodes.size());
BLI_task_parallel_range(0, nodes.size(), &data, do_inflate_brush_task_cb_ex, &settings);
}
static void do_nudge_brush_task_cb_ex(void *__restrict userdata,
@@ -1742,7 +1745,7 @@ static void do_nudge_brush_task_cb_ex(void *__restrict userdata,
BKE_pbvh_vertex_iter_end;
}
void SCULPT_do_nudge_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnode)
void SCULPT_do_nudge_brush(Sculpt *sd, Object *ob, Span<PBVHNode *> nodes)
{
SculptSession *ss = ob->sculpt;
Brush *brush = BKE_paint_brush(&sd->paint);
@@ -1762,8 +1765,8 @@ void SCULPT_do_nudge_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnode
data.cono = cono;
TaskParallelSettings settings;
BKE_pbvh_parallel_range_settings(&settings, true, totnode);
BLI_task_parallel_range(0, totnode, &data, do_nudge_brush_task_cb_ex, &settings);
BKE_pbvh_parallel_range_settings(&settings, true, nodes.size());
BLI_task_parallel_range(0, nodes.size(), &data, do_nudge_brush_task_cb_ex, &settings);
}
/** \} */
@@ -1842,7 +1845,7 @@ static void do_crease_brush_task_cb_ex(void *__restrict userdata,
BKE_pbvh_vertex_iter_end;
}
void SCULPT_do_crease_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnode)
void SCULPT_do_crease_brush(Sculpt *sd, Object *ob, Span<PBVHNode *> nodes)
{
SculptSession *ss = ob->sculpt;
const Scene *scene = ss->cache->vc->scene;
@@ -1890,8 +1893,8 @@ void SCULPT_do_crease_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnod
data.flippedbstrength = flippedbstrength;
TaskParallelSettings settings;
BKE_pbvh_parallel_range_settings(&settings, true, totnode);
BLI_task_parallel_range(0, totnode, &data, do_crease_brush_task_cb_ex, &settings);
BKE_pbvh_parallel_range_settings(&settings, true, nodes.size());
BLI_task_parallel_range(0, nodes.size(), &data, do_crease_brush_task_cb_ex, &settings);
}
static void do_pinch_brush_task_cb_ex(void *__restrict userdata,
@@ -1967,7 +1970,7 @@ static void do_pinch_brush_task_cb_ex(void *__restrict userdata,
BKE_pbvh_vertex_iter_end;
}
void SCULPT_do_pinch_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnode)
void SCULPT_do_pinch_brush(Sculpt *sd, Object *ob, Span<PBVHNode *> nodes)
{
SculptSession *ss = ob->sculpt;
Brush *brush = BKE_paint_brush(&sd->paint);
@@ -1976,7 +1979,7 @@ void SCULPT_do_pinch_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnode
float area_co[3];
float mat[4][4];
calc_sculpt_plane(sd, ob, nodes, totnode, area_no, area_co);
calc_sculpt_plane(sd, ob, nodes, area_no, area_co);
/* delay the first daub because grab delta is not setup */
if (SCULPT_stroke_is_first_brush_step_of_symmetry_pass(ss->cache)) {
@@ -2010,8 +2013,8 @@ void SCULPT_do_pinch_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnode
data.stroke_xz = stroke_xz;
TaskParallelSettings settings;
BKE_pbvh_parallel_range_settings(&settings, true, totnode);
BLI_task_parallel_range(0, totnode, &data, do_pinch_brush_task_cb_ex, &settings);
BKE_pbvh_parallel_range_settings(&settings, true, nodes.size());
BLI_task_parallel_range(0, nodes.size(), &data, do_pinch_brush_task_cb_ex, &settings);
}
static void do_grab_brush_task_cb_ex(void *__restrict userdata,
@@ -2082,7 +2085,7 @@ static void do_grab_brush_task_cb_ex(void *__restrict userdata,
BKE_pbvh_vertex_iter_end;
}
void SCULPT_do_grab_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnode)
void SCULPT_do_grab_brush(Sculpt *sd, Object *ob, Span<PBVHNode *> nodes)
{
SculptSession *ss = ob->sculpt;
Brush *brush = BKE_paint_brush(&sd->paint);
@@ -2102,8 +2105,8 @@ void SCULPT_do_grab_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnode)
data.grab_delta = grab_delta;
TaskParallelSettings settings;
BKE_pbvh_parallel_range_settings(&settings, true, totnode);
BLI_task_parallel_range(0, totnode, &data, do_grab_brush_task_cb_ex, &settings);
BKE_pbvh_parallel_range_settings(&settings, true, nodes.size());
BLI_task_parallel_range(0, nodes.size(), &data, do_grab_brush_task_cb_ex, &settings);
}
static void do_elastic_deform_brush_task_cb_ex(void *__restrict userdata,
@@ -2196,7 +2199,7 @@ static void do_elastic_deform_brush_task_cb_ex(void *__restrict userdata,
BKE_pbvh_vertex_iter_end;
}
void SCULPT_do_elastic_deform_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnode)
void SCULPT_do_elastic_deform_brush(Sculpt *sd, Object *ob, Span<PBVHNode *> nodes)
{
SculptSession *ss = ob->sculpt;
Brush *brush = BKE_paint_brush(&sd->paint);
@@ -2216,8 +2219,8 @@ void SCULPT_do_elastic_deform_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, in
data.grab_delta = grab_delta;
TaskParallelSettings settings;
BKE_pbvh_parallel_range_settings(&settings, true, totnode);
BLI_task_parallel_range(0, totnode, &data, do_elastic_deform_brush_task_cb_ex, &settings);
BKE_pbvh_parallel_range_settings(&settings, true, nodes.size());
BLI_task_parallel_range(0, nodes.size(), &data, do_elastic_deform_brush_task_cb_ex, &settings);
}
/** \} */
@@ -2280,7 +2283,7 @@ static void do_draw_sharp_brush_task_cb_ex(void *__restrict userdata,
BKE_pbvh_vertex_iter_end;
}
void SCULPT_do_draw_sharp_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnode)
void SCULPT_do_draw_sharp_brush(Sculpt *sd, Object *ob, Span<PBVHNode *> nodes)
{
SculptSession *ss = ob->sculpt;
Brush *brush = BKE_paint_brush(&sd->paint);
@@ -2307,8 +2310,8 @@ void SCULPT_do_draw_sharp_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int to
data.offset = offset;
TaskParallelSettings settings;
BKE_pbvh_parallel_range_settings(&settings, true, totnode);
BLI_task_parallel_range(0, totnode, &data, do_draw_sharp_brush_task_cb_ex, &settings);
BKE_pbvh_parallel_range_settings(&settings, true, nodes.size());
BLI_task_parallel_range(0, nodes.size(), &data, do_draw_sharp_brush_task_cb_ex, &settings);
}
/** \} */
@@ -2532,7 +2535,7 @@ static void do_topology_relax_task_cb_ex(void *__restrict userdata,
BKE_pbvh_vertex_iter_end;
}
void SCULPT_do_slide_relax_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnode)
void SCULPT_do_slide_relax_brush(Sculpt *sd, Object *ob, Span<PBVHNode *> nodes)
{
SculptSession *ss = ob->sculpt;
Brush *brush = BKE_paint_brush(&sd->paint);
@@ -2550,15 +2553,15 @@ void SCULPT_do_slide_relax_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int t
data.nodes = nodes;
TaskParallelSettings settings;
BKE_pbvh_parallel_range_settings(&settings, true, totnode);
BKE_pbvh_parallel_range_settings(&settings, true, nodes.size());
if (ss->cache->alt_smooth) {
SCULPT_boundary_info_ensure(ob);
for (int i = 0; i < 4; i++) {
BLI_task_parallel_range(0, totnode, &data, do_topology_relax_task_cb_ex, &settings);
BLI_task_parallel_range(0, nodes.size(), &data, do_topology_relax_task_cb_ex, &settings);
}
}
else {
BLI_task_parallel_range(0, totnode, &data, do_topology_slide_task_cb_ex, &settings);
BLI_task_parallel_range(0, nodes.size(), &data, do_topology_slide_task_cb_ex, &settings);
}
}
@@ -2619,7 +2622,7 @@ static void do_displacement_eraser_brush_task_cb_ex(void *__restrict userdata,
BKE_pbvh_vertex_iter_end;
}
void SCULPT_do_displacement_eraser_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnode)
void SCULPT_do_displacement_eraser_brush(Sculpt *sd, Object *ob, Span<PBVHNode *> nodes)
{
Brush *brush = BKE_paint_brush(&sd->paint);
BKE_curvemapping_init(brush->curve);
@@ -2632,8 +2635,9 @@ void SCULPT_do_displacement_eraser_brush(Sculpt *sd, Object *ob, PBVHNode **node
data.nodes = nodes;
TaskParallelSettings settings;
BKE_pbvh_parallel_range_settings(&settings, true, totnode);
BLI_task_parallel_range(0, totnode, &data, do_displacement_eraser_brush_task_cb_ex, &settings);
BKE_pbvh_parallel_range_settings(&settings, true, nodes.size());
BLI_task_parallel_range(
0, nodes.size(), &data, do_displacement_eraser_brush_task_cb_ex, &settings);
}
/** \} */
@@ -2752,7 +2756,7 @@ static void do_displacement_smear_store_prev_disp_task_cb_ex(
BKE_pbvh_vertex_iter_end;
}
void SCULPT_do_displacement_smear_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnode)
void SCULPT_do_displacement_smear_brush(Sculpt *sd, Object *ob, Span<PBVHNode *> nodes)
{
Brush *brush = BKE_paint_brush(&sd->paint);
SculptSession *ss = ob->sculpt;
@@ -2782,10 +2786,11 @@ void SCULPT_do_displacement_smear_brush(Sculpt *sd, Object *ob, PBVHNode **nodes
data.nodes = nodes;
TaskParallelSettings settings;
BKE_pbvh_parallel_range_settings(&settings, true, totnode);
BKE_pbvh_parallel_range_settings(&settings, true, nodes.size());
BLI_task_parallel_range(
0, totnode, &data, do_displacement_smear_store_prev_disp_task_cb_ex, &settings);
BLI_task_parallel_range(0, totnode, &data, do_displacement_smear_brush_task_cb_ex, &settings);
0, nodes.size(), &data, do_displacement_smear_store_prev_disp_task_cb_ex, &settings);
BLI_task_parallel_range(
0, nodes.size(), &data, do_displacement_smear_brush_task_cb_ex, &settings);
}
/** \} */
@@ -2865,8 +2870,7 @@ static void do_topology_rake_bmesh_task_cb_ex(void *__restrict userdata,
BKE_pbvh_vertex_iter_end;
}
void SCULPT_bmesh_topology_rake(
Sculpt *sd, Object *ob, PBVHNode **nodes, const int totnode, float bstrength)
void SCULPT_bmesh_topology_rake(Sculpt *sd, Object *ob, Span<PBVHNode *> nodes, float bstrength)
{
Brush *brush = BKE_paint_brush(&sd->paint);
const float strength = clamp_f(bstrength, 0.0f, 1.0f);
@@ -2888,9 +2892,9 @@ void SCULPT_bmesh_topology_rake(
data.strength = factor;
TaskParallelSettings settings;
BKE_pbvh_parallel_range_settings(&settings, true, totnode);
BKE_pbvh_parallel_range_settings(&settings, true, nodes.size());
BLI_task_parallel_range(0, totnode, &data, do_topology_rake_bmesh_task_cb_ex, &settings);
BLI_task_parallel_range(0, nodes.size(), &data, do_topology_rake_bmesh_task_cb_ex, &settings);
}
}
@@ -2948,7 +2952,7 @@ static void do_mask_brush_draw_task_cb_ex(void *__restrict userdata,
BKE_pbvh_vertex_iter_end;
}
void SCULPT_do_mask_brush_draw(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnode)
void SCULPT_do_mask_brush_draw(Sculpt *sd, Object *ob, Span<PBVHNode *> nodes)
{
Brush *brush = BKE_paint_brush(&sd->paint);
@@ -2960,21 +2964,21 @@ void SCULPT_do_mask_brush_draw(Sculpt *sd, Object *ob, PBVHNode **nodes, int tot
data.nodes = nodes;
TaskParallelSettings settings;
BKE_pbvh_parallel_range_settings(&settings, true, totnode);
BLI_task_parallel_range(0, totnode, &data, do_mask_brush_draw_task_cb_ex, &settings);
BKE_pbvh_parallel_range_settings(&settings, true, nodes.size());
BLI_task_parallel_range(0, nodes.size(), &data, do_mask_brush_draw_task_cb_ex, &settings);
}
void SCULPT_do_mask_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnode)
void SCULPT_do_mask_brush(Sculpt *sd, Object *ob, Span<PBVHNode *> nodes)
{
SculptSession *ss = ob->sculpt;
Brush *brush = BKE_paint_brush(&sd->paint);
switch ((BrushMaskTool)brush->mask_tool) {
case BRUSH_MASK_DRAW:
SCULPT_do_mask_brush_draw(sd, ob, nodes, totnode);
SCULPT_do_mask_brush_draw(sd, ob, nodes);
break;
case BRUSH_MASK_SMOOTH:
SCULPT_smooth(sd, ob, nodes, totnode, ss->cache->bstrength, true);
SCULPT_smooth(sd, ob, nodes, ss->cache->bstrength, true);
break;
}
}

View File

@@ -12,6 +12,7 @@
#include "BLI_math.h"
#include "BLI_task.h"
#include "BLI_utildefines.h"
#include "BLI_vector.hh"
#include "DNA_brush_types.h"
#include "DNA_customdata_types.h"
@@ -53,6 +54,8 @@
#include <cstdlib>
#include <cstring>
using blender::Vector;
static void cloth_brush_simulation_location_get(SculptSession *ss,
const Brush *brush,
float r_location[3])
@@ -69,13 +72,10 @@ static void cloth_brush_simulation_location_get(SculptSession *ss,
copy_v3_v3(r_location, ss->cache->location);
}
PBVHNode **SCULPT_cloth_brush_affected_nodes_gather(SculptSession *ss,
Brush *brush,
int *r_totnode)
Vector<PBVHNode *> SCULPT_cloth_brush_affected_nodes_gather(SculptSession *ss, Brush *brush)
{
BLI_assert(ss->cache);
BLI_assert(brush->sculpt_tool == SCULPT_TOOL_CLOTH);
PBVHNode **nodes = nullptr;
switch (brush->cloth_simulation_area_type) {
case BRUSH_CLOTH_SIMULATION_AREA_LOCAL: {
@@ -85,11 +85,10 @@ PBVHNode **SCULPT_cloth_brush_affected_nodes_gather(SculptSession *ss,
data.original = false;
data.ignore_fully_ineffective = false;
data.center = ss->cache->initial_location;
BKE_pbvh_search_gather(ss->pbvh, SCULPT_search_sphere_cb, &data, &nodes, r_totnode);
} break;
return blender::bke::pbvh::search_gather(ss->pbvh, SCULPT_search_sphere_cb, &data);
}
case BRUSH_CLOTH_SIMULATION_AREA_GLOBAL:
BKE_pbvh_search_gather(ss->pbvh, nullptr, nullptr, &nodes, r_totnode);
break;
return blender::bke::pbvh::search_gather(ss->pbvh, nullptr, nullptr);
case BRUSH_CLOTH_SIMULATION_AREA_DYNAMIC: {
SculptSearchSphereData data{};
data.ss = ss;
@@ -97,11 +96,12 @@ PBVHNode **SCULPT_cloth_brush_affected_nodes_gather(SculptSession *ss,
data.original = false;
data.ignore_fully_ineffective = false;
data.center = ss->cache->location;
BKE_pbvh_search_gather(ss->pbvh, SCULPT_search_sphere_cb, &data, &nodes, r_totnode);
} break;
return blender::bke::pbvh::search_gather(ss->pbvh, SCULPT_search_sphere_cb, &data);
}
}
return nodes;
BLI_assert_unreachable();
return Vector<PBVHNode *>();
}
static float cloth_brush_simulation_falloff_get(const Brush *brush,
@@ -901,8 +901,10 @@ static void cloth_brush_satisfy_constraints(SculptSession *ss,
}
}
void SCULPT_cloth_brush_do_simulation_step(
Sculpt *sd, Object *ob, SculptClothSimulation *cloth_sim, PBVHNode **nodes, int totnode)
void SCULPT_cloth_brush_do_simulation_step(Sculpt *sd,
Object *ob,
SculptClothSimulation *cloth_sim,
Span<PBVHNode *> nodes)
{
SculptSession *ss = ob->sculpt;
Brush *brush = BKE_paint_brush(&sd->paint);
@@ -920,12 +922,15 @@ void SCULPT_cloth_brush_do_simulation_step(
solve_simulation_data.cloth_sim = cloth_sim;
TaskParallelSettings settings;
BKE_pbvh_parallel_range_settings(&settings, true, totnode);
BLI_task_parallel_range(
0, totnode, &solve_simulation_data, do_cloth_brush_solve_simulation_task_cb_ex, &settings);
BKE_pbvh_parallel_range_settings(&settings, true, nodes.size());
BLI_task_parallel_range(0,
nodes.size(),
&solve_simulation_data,
do_cloth_brush_solve_simulation_task_cb_ex,
&settings);
}
static void cloth_brush_apply_brush_foces(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnode)
static void cloth_brush_apply_brush_foces(Sculpt *sd, Object *ob, Span<PBVHNode *> nodes)
{
SculptSession *ss = ob->sculpt;
Brush *brush = BKE_paint_brush(&sd->paint);
@@ -970,7 +975,7 @@ static void cloth_brush_apply_brush_foces(Sculpt *sd, Object *ob, PBVHNode **nod
if (brush->cloth_deform_type == BRUSH_CLOTH_DEFORM_PINCH_PERPENDICULAR ||
brush->cloth_force_falloff_type == BRUSH_CLOTH_FORCE_FALLOFF_PLANE) {
SCULPT_calc_brush_plane(sd, ob, nodes, totnode, area_no, area_co);
SCULPT_calc_brush_plane(sd, ob, nodes, area_no, area_co);
/* Initialize stroke local space matrix. */
cross_v3_v3v3(mat[0], area_no, ss->cache->grab_delta_symmetry);
@@ -1003,9 +1008,9 @@ static void cloth_brush_apply_brush_foces(Sculpt *sd, Object *ob, PBVHNode **nod
}
TaskParallelSettings settings;
BKE_pbvh_parallel_range_settings(&settings, true, totnode);
BKE_pbvh_parallel_range_settings(&settings, true, nodes.size());
BLI_task_parallel_range(
0, totnode, &apply_forces_data, do_cloth_brush_apply_forces_task_cb_ex, &settings);
0, nodes.size(), &apply_forces_data, do_cloth_brush_apply_forces_task_cb_ex, &settings);
}
/* Allocates nodes state and initializes them to Uninitialized, so constraints can be created for
@@ -1013,18 +1018,15 @@ static void cloth_brush_apply_brush_foces(Sculpt *sd, Object *ob, PBVHNode **nod
static void cloth_sim_initialize_default_node_state(SculptSession *ss,
SculptClothSimulation *cloth_sim)
{
PBVHNode **nodes;
int totnode;
BKE_pbvh_search_gather(ss->pbvh, nullptr, nullptr, &nodes, &totnode);
Vector<PBVHNode *> nodes = blender::bke::pbvh::search_gather(ss->pbvh, nullptr, nullptr);
cloth_sim->node_state = static_cast<eSculptClothNodeSimState *>(
MEM_malloc_arrayN(totnode, sizeof(eSculptClothNodeSimState), "node sim state"));
MEM_malloc_arrayN(nodes.size(), sizeof(eSculptClothNodeSimState), "node sim state"));
cloth_sim->node_state_index = BLI_ghash_ptr_new("node sim state indices");
for (int i = 0; i < totnode; i++) {
for (int i = 0; i < nodes.size(); i++) {
cloth_sim->node_state[i] = SCULPT_CLOTH_NODE_UNINITIALIZED;
BLI_ghash_insert(cloth_sim->node_state_index, nodes[i], POINTER_FROM_INT(i));
}
MEM_SAFE_FREE(nodes);
}
SculptClothSimulation *SCULPT_cloth_brush_simulation_create(Object *ob,
@@ -1077,8 +1079,7 @@ SculptClothSimulation *SCULPT_cloth_brush_simulation_create(Object *ob,
void SCULPT_cloth_brush_ensure_nodes_constraints(
Sculpt *sd,
Object *ob,
PBVHNode **nodes,
int totnode,
Span<PBVHNode *> nodes,
SculptClothSimulation *cloth_sim,
/* Cannot be `const`, because it is assigned to a `non-const` variable.
* NOLINTNEXTLINE: readability-non-const-parameter. */
@@ -1092,7 +1093,7 @@ void SCULPT_cloth_brush_ensure_nodes_constraints(
/* Currently all constrains are added to the same global array which can't be accessed from
* different threads. */
TaskParallelSettings settings;
BKE_pbvh_parallel_range_settings(&settings, false, totnode);
BKE_pbvh_parallel_range_settings(&settings, false, nodes.size());
cloth_sim->created_length_constraints = BLI_edgeset_new("created length constraints");
@@ -1105,8 +1106,11 @@ void SCULPT_cloth_brush_ensure_nodes_constraints(
build_constraints_data.cloth_sim_initial_location = initial_location;
build_constraints_data.cloth_sim_radius = radius;
BLI_task_parallel_range(
0, totnode, &build_constraints_data, do_cloth_brush_build_constraints_task_cb_ex, &settings);
BLI_task_parallel_range(0,
nodes.size(),
&build_constraints_data,
do_cloth_brush_build_constraints_task_cb_ex,
&settings);
BLI_edgeset_free(cloth_sim->created_length_constraints);
}
@@ -1143,21 +1147,18 @@ void SCULPT_cloth_brush_store_simulation_state(SculptSession *ss, SculptClothSim
}
}
void SCULPT_cloth_sim_activate_nodes(SculptClothSimulation *cloth_sim,
PBVHNode **nodes,
int totnode)
void SCULPT_cloth_sim_activate_nodes(SculptClothSimulation *cloth_sim, Span<PBVHNode *> nodes)
{
/* Activate the nodes inside the simulation area. */
for (int n = 0; n < totnode; n++) {
const int node_index = POINTER_AS_INT(BLI_ghash_lookup(cloth_sim->node_state_index, nodes[n]));
for (PBVHNode *node : nodes) {
const int node_index = POINTER_AS_INT(BLI_ghash_lookup(cloth_sim->node_state_index, node));
cloth_sim->node_state[node_index] = SCULPT_CLOTH_NODE_ACTIVE;
}
}
static void sculpt_cloth_ensure_constraints_in_simulation_area(Sculpt *sd,
Object *ob,
PBVHNode **nodes,
int totnode)
Span<PBVHNode *> nodes)
{
SculptSession *ss = ob->sculpt;
Brush *brush = BKE_paint_brush(&sd->paint);
@@ -1166,10 +1167,10 @@ static void sculpt_cloth_ensure_constraints_in_simulation_area(Sculpt *sd,
float sim_location[3];
cloth_brush_simulation_location_get(ss, brush, sim_location);
SCULPT_cloth_brush_ensure_nodes_constraints(
sd, ob, nodes, totnode, ss->cache->cloth_sim, sim_location, limit);
sd, ob, nodes, ss->cache->cloth_sim, sim_location, limit);
}
void SCULPT_do_cloth_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnode)
void SCULPT_do_cloth_brush(Sculpt *sd, Object *ob, Span<PBVHNode *> nodes)
{
SculptSession *ss = ob->sculpt;
Brush *brush = BKE_paint_brush(&sd->paint);
@@ -1201,7 +1202,7 @@ void SCULPT_do_cloth_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnode
* as this will cause the ensure constraints function to skip the node in the next symmetry
* passes. It needs to build the constraints here and skip simulating the first step, so all
* passes can add their constraints to all affected nodes. */
sculpt_cloth_ensure_constraints_in_simulation_area(sd, ob, nodes, totnode);
sculpt_cloth_ensure_constraints_in_simulation_area(sd, ob, nodes);
}
/* The first step of a symmetry pass is never simulated as deformation modes need valid delta
* for brush tip alignment. */
@@ -1209,19 +1210,19 @@ void SCULPT_do_cloth_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnode
}
/* Ensure the constraints for the nodes. */
sculpt_cloth_ensure_constraints_in_simulation_area(sd, ob, nodes, totnode);
sculpt_cloth_ensure_constraints_in_simulation_area(sd, ob, nodes);
/* Store the initial state in the simulation. */
SCULPT_cloth_brush_store_simulation_state(ss, ss->cache->cloth_sim);
/* Enable the nodes that should be simulated. */
SCULPT_cloth_sim_activate_nodes(ss->cache->cloth_sim, nodes, totnode);
SCULPT_cloth_sim_activate_nodes(ss->cache->cloth_sim, nodes);
/* Apply forces to the vertices. */
cloth_brush_apply_brush_foces(sd, ob, nodes, totnode);
cloth_brush_apply_brush_foces(sd, ob, nodes);
/* Update and write the simulation to the nodes. */
SCULPT_cloth_brush_do_simulation_step(sd, ob, ss->cache->cloth_sim, nodes, totnode);
SCULPT_cloth_brush_do_simulation_step(sd, ob, ss->cache->cloth_sim, nodes);
}
void SCULPT_cloth_simulation_free(SculptClothSimulation *cloth_sim)
@@ -1530,17 +1531,16 @@ static int sculpt_cloth_filter_modal(bContext *C, wmOperator *op, const wmEvent
data.filter_strength = filter_strength;
TaskParallelSettings settings;
BKE_pbvh_parallel_range_settings(&settings, true, ss->filter_cache->totnode);
BKE_pbvh_parallel_range_settings(&settings, true, ss->filter_cache->nodes.size());
BLI_task_parallel_range(
0, ss->filter_cache->totnode, &data, cloth_filter_apply_forces_task_cb, &settings);
0, ss->filter_cache->nodes.size(), &data, cloth_filter_apply_forces_task_cb, &settings);
/* Activate all nodes. */
SCULPT_cloth_sim_activate_nodes(
ss->filter_cache->cloth_sim, ss->filter_cache->nodes, ss->filter_cache->totnode);
SCULPT_cloth_sim_activate_nodes(ss->filter_cache->cloth_sim, ss->filter_cache->nodes);
/* Update and write the simulation to the nodes. */
SCULPT_cloth_brush_do_simulation_step(
sd, ob, ss->filter_cache->cloth_sim, ss->filter_cache->nodes, ss->filter_cache->totnode);
sd, ob, ss->filter_cache->cloth_sim, ss->filter_cache->nodes);
if (ss->deform_modifiers_active || ss->shapekey_active) {
SCULPT_flush_stroke_deform(sd, ob, true);
@@ -1597,13 +1597,8 @@ static int sculpt_cloth_filter_invoke(bContext *C, wmOperator *op, const wmEvent
SCULPT_cloth_brush_simulation_init(ss, ss->filter_cache->cloth_sim);
float origin[3] = {0.0f, 0.0f, 0.0f};
SCULPT_cloth_brush_ensure_nodes_constraints(sd,
ob,
ss->filter_cache->nodes,
ss->filter_cache->totnode,
ss->filter_cache->cloth_sim,
origin,
FLT_MAX);
SCULPT_cloth_brush_ensure_nodes_constraints(
sd, ob, ss->filter_cache->nodes, ss->filter_cache->cloth_sim, origin, FLT_MAX);
const bool use_face_sets = RNA_boolean_get(op->ptr, "use_face_sets");
if (use_face_sets) {

View File

@@ -82,17 +82,15 @@ static int sculpt_detail_flood_fill_exec(bContext *C, wmOperator *op)
SculptSession *ss = ob->sculpt;
float size;
float bb_min[3], bb_max[3], center[3], dim[3];
int totnodes;
PBVHNode **nodes;
BKE_pbvh_search_gather(ss->pbvh, nullptr, nullptr, &nodes, &totnodes);
Vector<PBVHNode *> nodes = blender::bke::pbvh::search_gather(ss->pbvh, nullptr, nullptr);
if (!totnodes) {
if (nodes.is_empty()) {
return OPERATOR_CANCELLED;
}
for (int i = 0; i < totnodes; i++) {
BKE_pbvh_node_mark_topology_update(nodes[i]);
for (PBVHNode *node : nodes) {
BKE_pbvh_node_mark_topology_update(node);
}
/* Get the bounding box, its center and size. */
BKE_pbvh_bounding_box(ob->sculpt->pbvh, bb_min, bb_max);
@@ -111,12 +109,11 @@ static int sculpt_detail_flood_fill_exec(bContext *C, wmOperator *op)
while (BKE_pbvh_bmesh_update_topology(
ss->pbvh, PBVH_Collapse | PBVH_Subdivide, center, nullptr, size, false, false)) {
for (int i = 0; i < totnodes; i++) {
BKE_pbvh_node_mark_topology_update(nodes[i]);
for (PBVHNode *node : nodes) {
BKE_pbvh_node_mark_topology_update(node);
}
}
MEM_SAFE_FREE(nodes);
SCULPT_undo_push_end(ob);
/* Force rebuild of PBVH for better BB placement. */

View File

@@ -1138,14 +1138,13 @@ static void sculpt_expand_cache_data_free(ExpandCache *expand_cache)
if (expand_cache->snap_enabled_face_sets) {
BLI_gset_free(expand_cache->snap_enabled_face_sets, nullptr);
}
MEM_SAFE_FREE(expand_cache->nodes);
MEM_SAFE_FREE(expand_cache->vert_falloff);
MEM_SAFE_FREE(expand_cache->face_falloff);
MEM_SAFE_FREE(expand_cache->original_mask);
MEM_SAFE_FREE(expand_cache->original_face_sets);
MEM_SAFE_FREE(expand_cache->initial_face_sets);
MEM_SAFE_FREE(expand_cache->original_colors);
MEM_SAFE_FREE(expand_cache);
MEM_delete<ExpandCache>(expand_cache);
}
static void sculpt_expand_cache_free(SculptSession *ss)
@@ -1161,14 +1160,11 @@ static void sculpt_expand_cache_free(SculptSession *ss)
*/
static void sculpt_expand_restore_face_set_data(SculptSession *ss, ExpandCache *expand_cache)
{
PBVHNode **nodes;
int totnode;
BKE_pbvh_search_gather(ss->pbvh, nullptr, nullptr, &nodes, &totnode);
for (int n = 0; n < totnode; n++) {
PBVHNode *node = nodes[n];
Vector<PBVHNode *> nodes = blender::bke::pbvh::search_gather(ss->pbvh, nullptr, nullptr);
for (PBVHNode *node : nodes) {
BKE_pbvh_node_mark_redraw(node);
}
MEM_freeN(nodes);
for (int i = 0; i < ss->totfaces; i++) {
ss->face_sets[i] = expand_cache->original_face_sets[i];
}
@@ -1176,11 +1172,9 @@ static void sculpt_expand_restore_face_set_data(SculptSession *ss, ExpandCache *
static void sculpt_expand_restore_color_data(SculptSession *ss, ExpandCache *expand_cache)
{
PBVHNode **nodes;
int totnode;
BKE_pbvh_search_gather(ss->pbvh, nullptr, nullptr, &nodes, &totnode);
for (int n = 0; n < totnode; n++) {
PBVHNode *node = nodes[n];
Vector<PBVHNode *> nodes = blender::bke::pbvh::search_gather(ss->pbvh, nullptr, nullptr);
for (PBVHNode *node : nodes) {
PBVHVertexIter vd;
BKE_pbvh_vertex_iter_begin (ss->pbvh, node, vd, PBVH_ITER_UNIQUE) {
SCULPT_vertex_color_set(ss, vd.vertex, expand_cache->original_colors[vd.index]);
@@ -1188,16 +1182,12 @@ static void sculpt_expand_restore_color_data(SculptSession *ss, ExpandCache *exp
BKE_pbvh_vertex_iter_end;
BKE_pbvh_node_mark_redraw(node);
}
MEM_freeN(nodes);
}
static void sculpt_expand_restore_mask_data(SculptSession *ss, ExpandCache *expand_cache)
{
PBVHNode **nodes;
int totnode;
BKE_pbvh_search_gather(ss->pbvh, nullptr, nullptr, &nodes, &totnode);
for (int n = 0; n < totnode; n++) {
PBVHNode *node = nodes[n];
Vector<PBVHNode *> nodes = blender::bke::pbvh::search_gather(ss->pbvh, nullptr, nullptr);
for (PBVHNode *node : nodes) {
PBVHVertexIter vd;
BKE_pbvh_vertex_iter_begin (ss->pbvh, node, vd, PBVH_ITER_UNIQUE) {
*vd.mask = expand_cache->original_mask[vd.index];
@@ -1205,7 +1195,6 @@ static void sculpt_expand_restore_mask_data(SculptSession *ss, ExpandCache *expa
BKE_pbvh_vertex_iter_end;
BKE_pbvh_node_mark_redraw(node);
}
MEM_freeN(nodes);
}
/* Main function to restore the original state of the data to how it was before starting the expand
@@ -1327,8 +1316,8 @@ static void sculpt_expand_face_sets_update(SculptSession *ss, ExpandCache *expan
}
}
for (int i = 0; i < expand_cache->totnode; i++) {
BKE_pbvh_node_mark_redraw(ss->expand_cache->nodes[i]);
for (PBVHNode *node : ss->expand_cache->nodes) {
BKE_pbvh_node_mark_redraw(node);
}
}
@@ -1501,19 +1490,19 @@ static void sculpt_expand_update_for_vertex(bContext *C, Object *ob, const PBVHV
data.nodes = expand_cache->nodes;
TaskParallelSettings settings;
BKE_pbvh_parallel_range_settings(&settings, true, expand_cache->totnode);
BKE_pbvh_parallel_range_settings(&settings, true, expand_cache->nodes.size());
switch (expand_cache->target) {
case SCULPT_EXPAND_TARGET_MASK:
BLI_task_parallel_range(
0, expand_cache->totnode, &data, sculpt_expand_mask_update_task_cb, &settings);
0, expand_cache->nodes.size(), &data, sculpt_expand_mask_update_task_cb, &settings);
break;
case SCULPT_EXPAND_TARGET_FACE_SETS:
sculpt_expand_face_sets_update(ss, expand_cache);
break;
case SCULPT_EXPAND_TARGET_COLORS:
BLI_task_parallel_range(
0, expand_cache->totnode, &data, sculpt_expand_colors_update_task_cb, &settings);
0, expand_cache->nodes.size(), &data, sculpt_expand_colors_update_task_cb, &settings);
break;
}
@@ -1606,13 +1595,10 @@ static void sculpt_expand_finish(bContext *C)
SCULPT_undo_push_end(ob);
/* Tag all nodes to redraw to avoid artifacts after the fast partial updates. */
PBVHNode **nodes;
int totnode;
BKE_pbvh_search_gather(ss->pbvh, nullptr, nullptr, &nodes, &totnode);
for (int n = 0; n < totnode; n++) {
BKE_pbvh_node_mark_update_mask(nodes[n]);
Vector<PBVHNode *> nodes = blender::bke::pbvh::search_gather(ss->pbvh, nullptr, nullptr);
for (PBVHNode *node : nodes) {
BKE_pbvh_node_mark_update_mask(node);
}
MEM_freeN(nodes);
switch (ss->expand_cache->target) {
case SCULPT_EXPAND_TARGET_MASK:
@@ -2105,29 +2091,25 @@ static void sculpt_expand_cache_initial_config_set(bContext *C,
static void sculpt_expand_undo_push(Object *ob, ExpandCache *expand_cache)
{
SculptSession *ss = ob->sculpt;
PBVHNode **nodes;
int totnode;
BKE_pbvh_search_gather(ss->pbvh, nullptr, nullptr, &nodes, &totnode);
Vector<PBVHNode *> nodes = blender::bke::pbvh::search_gather(ss->pbvh, nullptr, nullptr);
switch (expand_cache->target) {
case SCULPT_EXPAND_TARGET_MASK:
for (int i = 0; i < totnode; i++) {
SCULPT_undo_push_node(ob, nodes[i], SCULPT_UNDO_MASK);
for (PBVHNode *node : nodes) {
SCULPT_undo_push_node(ob, node, SCULPT_UNDO_MASK);
}
break;
case SCULPT_EXPAND_TARGET_FACE_SETS:
for (int i = 0; i < totnode; i++) {
SCULPT_undo_push_node(ob, nodes[i], SCULPT_UNDO_FACE_SETS);
for (PBVHNode *node : nodes) {
SCULPT_undo_push_node(ob, node, SCULPT_UNDO_FACE_SETS);
}
break;
case SCULPT_EXPAND_TARGET_COLORS:
for (int i = 0; i < totnode; i++) {
SCULPT_undo_push_node(ob, nodes[i], SCULPT_UNDO_COLOR);
for (PBVHNode *node : nodes) {
SCULPT_undo_push_node(ob, node, SCULPT_UNDO_COLOR);
}
break;
}
MEM_freeN(nodes);
}
static int sculpt_expand_invoke(bContext *C, wmOperator *op, const wmEvent *event)
@@ -2140,7 +2122,7 @@ static int sculpt_expand_invoke(bContext *C, wmOperator *op, const wmEvent *even
SCULPT_stroke_id_next(ob);
/* Create and configure the Expand Cache. */
ss->expand_cache = MEM_cnew<ExpandCache>(__func__);
ss->expand_cache = MEM_new<ExpandCache>(__func__);
sculpt_expand_cache_initial_config_set(C, op, ss->expand_cache);
/* Update object. */
@@ -2171,21 +2153,17 @@ static int sculpt_expand_invoke(bContext *C, wmOperator *op, const wmEvent *even
}
if (ok) {
int nodes_num;
PBVHNode **nodes;
/* TODO: implement SCULPT_vertex_mask_set and use it here. */
BKE_pbvh_search_gather(ss->pbvh, nullptr, nullptr, &nodes, &nodes_num);
for (int i = 0; i < nodes_num; i++) {
Vector<PBVHNode *> nodes = blender::bke::pbvh::search_gather(ss->pbvh, nullptr, nullptr);
for (PBVHNode *node : nodes) {
PBVHVertexIter vd;
BKE_pbvh_vertex_iter_begin (ss->pbvh, nodes[i], vd, PBVH_ITER_UNIQUE) {
BKE_pbvh_vertex_iter_begin (ss->pbvh, node, vd, PBVH_ITER_UNIQUE) {
*vd.mask = 1.0f;
}
BKE_pbvh_vertex_iter_end;
BKE_pbvh_node_mark_update_mask(nodes[i]);
BKE_pbvh_node_mark_update_mask(node);
}
}
}
@@ -2223,8 +2201,7 @@ static int sculpt_expand_invoke(bContext *C, wmOperator *op, const wmEvent *even
sculpt_expand_set_initial_components_for_mouse(C, ob, ss->expand_cache, mouse);
/* Cache PBVH nodes. */
BKE_pbvh_search_gather(
ss->pbvh, nullptr, nullptr, &ss->expand_cache->nodes, &ss->expand_cache->totnode);
ss->expand_cache->nodes = blender::bke::pbvh::search_gather(ss->pbvh, nullptr, nullptr);
/* Store initial state. */
sculpt_expand_original_state_store(ob, ss->expand_cache);

View File

@@ -11,6 +11,7 @@
#include "MEM_guardedalloc.h"
#include "BLI_array.hh"
#include "BLI_bit_vector.hh"
#include "BLI_function_ref.hh"
#include "BLI_hash.h"
@@ -55,6 +56,7 @@
#include "bmesh.h"
using blender::Array;
using blender::float3;
using blender::Vector;
@@ -252,7 +254,7 @@ static void do_relax_face_sets_brush_task_cb_ex(void *__restrict userdata,
BKE_pbvh_vertex_iter_end;
}
void SCULPT_do_draw_face_sets_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnode)
void SCULPT_do_draw_face_sets_brush(Sculpt *sd, Object *ob, Span<PBVHNode *> nodes)
{
SculptSession *ss = ob->sculpt;
Brush *brush = BKE_paint_brush(&sd->paint);
@@ -273,16 +275,17 @@ void SCULPT_do_draw_face_sets_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, in
data.nodes = nodes;
TaskParallelSettings settings;
BKE_pbvh_parallel_range_settings(&settings, true, totnode);
BKE_pbvh_parallel_range_settings(&settings, true, nodes.size());
if (ss->cache->alt_smooth) {
SCULPT_boundary_info_ensure(ob);
for (int i = 0; i < 4; i++) {
data.iteration = i;
BLI_task_parallel_range(0, totnode, &data, do_relax_face_sets_brush_task_cb_ex, &settings);
BLI_task_parallel_range(
0, nodes.size(), &data, do_relax_face_sets_brush_task_cb_ex, &settings);
}
}
else {
BLI_task_parallel_range(0, totnode, &data, do_draw_face_sets_brush_task_cb_ex, &settings);
BLI_task_parallel_range(0, nodes.size(), &data, do_draw_face_sets_brush_task_cb_ex, &settings);
}
}
@@ -350,17 +353,15 @@ static int sculpt_face_set_create_exec(bContext *C, wmOperator *op)
float threshold = 0.5f;
PBVH *pbvh = ob->sculpt->pbvh;
PBVHNode **nodes;
int totnode;
BKE_pbvh_search_gather(pbvh, nullptr, nullptr, &nodes, &totnode);
Vector<PBVHNode *> nodes = blender::bke::pbvh::search_gather(pbvh, nullptr, nullptr);
if (!nodes) {
if (nodes.is_empty()) {
return OPERATOR_CANCELLED;
}
SCULPT_undo_push_begin(ob, op);
for (const int i : blender::IndexRange(totnode)) {
SCULPT_undo_push_node(ob, nodes[i], SCULPT_UNDO_FACE_SETS);
for (PBVHNode *node : nodes) {
SCULPT_undo_push_node(ob, node, SCULPT_UNDO_FACE_SETS);
}
const int next_face_set = SCULPT_face_set_next_available_get(ss);
@@ -427,12 +428,10 @@ static int sculpt_face_set_create_exec(bContext *C, wmOperator *op)
});
}
for (int i = 0; i < totnode; i++) {
BKE_pbvh_node_mark_redraw(nodes[i]);
for (PBVHNode *node : nodes) {
BKE_pbvh_node_mark_redraw(node);
}
MEM_SAFE_FREE(nodes);
SCULPT_undo_push_end(ob);
SCULPT_tag_update_overlays(C);
@@ -638,17 +637,15 @@ static int sculpt_face_set_init_exec(bContext *C, wmOperator *op)
}
PBVH *pbvh = ob->sculpt->pbvh;
PBVHNode **nodes;
int totnode;
BKE_pbvh_search_gather(pbvh, nullptr, nullptr, &nodes, &totnode);
Vector<PBVHNode *> nodes = blender::bke::pbvh::search_gather(pbvh, nullptr, nullptr);
if (!nodes) {
if (nodes.is_empty()) {
return OPERATOR_CANCELLED;
}
SCULPT_undo_push_begin(ob, op);
for (const int i : blender::IndexRange(totnode)) {
SCULPT_undo_push_node(ob, nodes[i], SCULPT_UNDO_FACE_SETS);
for (PBVHNode *node : nodes) {
SCULPT_undo_push_node(ob, node, SCULPT_UNDO_FACE_SETS);
}
const float threshold = RNA_float_get(op->ptr, "threshold");
@@ -734,14 +731,12 @@ static int sculpt_face_set_init_exec(bContext *C, wmOperator *op)
/* Sync face sets visibility and vertex visibility as now all Face Sets are visible. */
SCULPT_visibility_sync_all_from_faces(ob);
for (int i = 0; i < totnode; i++) {
BKE_pbvh_node_mark_update_visibility(nodes[i]);
for (PBVHNode *node : nodes) {
BKE_pbvh_node_mark_update_visibility(node);
}
BKE_pbvh_update_vertex_data(ss->pbvh, PBVH_UpdateVisibility);
MEM_SAFE_FREE(nodes);
if (BKE_pbvh_type(pbvh) == PBVH_FACES) {
BKE_mesh_flush_hidden_from_verts(mesh);
}
@@ -836,21 +831,17 @@ static int sculpt_face_sets_change_visibility_exec(bContext *C, wmOperator *op)
const int tot_vert = SCULPT_vertex_count_get(ss);
PBVH *pbvh = ob->sculpt->pbvh;
PBVHNode **nodes;
int totnode;
Vector<PBVHNode *> nodes = blender::bke::pbvh::search_gather(pbvh, nullptr, nullptr);
BKE_pbvh_search_gather(pbvh, nullptr, nullptr, &nodes, &totnode);
if (totnode == 0) {
MEM_SAFE_FREE(nodes);
if (nodes.is_empty()) {
return OPERATOR_CANCELLED;
}
const int active_face_set = SCULPT_active_face_set_get(ss);
SCULPT_undo_push_begin(ob, op);
for (int i = 0; i < totnode; i++) {
SCULPT_undo_push_node(ob, nodes[i], SCULPT_UNDO_HIDDEN);
for (PBVHNode *node : nodes) {
SCULPT_undo_push_node(ob, node, SCULPT_UNDO_HIDDEN);
}
switch (mode) {
@@ -940,14 +931,12 @@ static int sculpt_face_sets_change_visibility_exec(bContext *C, wmOperator *op)
SCULPT_visibility_sync_all_from_faces(ob);
SCULPT_undo_push_end(ob);
for (int i = 0; i < totnode; i++) {
BKE_pbvh_node_mark_update_visibility(nodes[i]);
for (PBVHNode *node : nodes) {
BKE_pbvh_node_mark_update_visibility(node);
}
BKE_pbvh_update_vertex_data(ss->pbvh, PBVH_UpdateVisibility);
MEM_SAFE_FREE(nodes);
SCULPT_tag_update_overlays(C);
return OPERATOR_FINISHED;
@@ -1008,8 +997,6 @@ static int sculpt_face_sets_randomize_colors_exec(bContext *C, wmOperator * /*op
}
PBVH *pbvh = ob->sculpt->pbvh;
PBVHNode **nodes;
int totnode;
Mesh *mesh = static_cast<Mesh *>(ob->data);
mesh->face_sets_color_seed += 1;
@@ -1021,13 +1008,11 @@ static int sculpt_face_sets_randomize_colors_exec(bContext *C, wmOperator * /*op
}
BKE_pbvh_face_sets_color_set(pbvh, mesh->face_sets_color_seed, mesh->face_sets_color_default);
BKE_pbvh_search_gather(pbvh, nullptr, nullptr, &nodes, &totnode);
for (int i = 0; i < totnode; i++) {
BKE_pbvh_node_mark_redraw(nodes[i]);
Vector<PBVHNode *> nodes = blender::bke::pbvh::search_gather(pbvh, nullptr, nullptr);
for (PBVHNode *node : nodes) {
BKE_pbvh_node_mark_redraw(node);
}
MEM_SAFE_FREE(nodes);
SCULPT_tag_update_overlays(C);
return OPERATOR_FINISHED;
@@ -1355,7 +1340,7 @@ static void sculpt_face_set_edit_modify_geometry(bContext *C,
WM_event_add_notifier(C, NC_GEOM | ND_DATA, mesh);
}
static void face_set_edit_do_post_visibility_updates(Object *ob, PBVHNode **nodes, int totnode)
static void face_set_edit_do_post_visibility_updates(Object *ob, Span<PBVHNode *> nodes)
{
SculptSession *ss = ob->sculpt;
PBVH *pbvh = ss->pbvh;
@@ -1364,8 +1349,8 @@ static void face_set_edit_do_post_visibility_updates(Object *ob, PBVHNode **node
/* Sync face sets visibility and vertex visibility as now all Face Sets are visible. */
SCULPT_visibility_sync_all_from_faces(ob);
for (int i = 0; i < totnode; i++) {
BKE_pbvh_node_mark_update_visibility(nodes[i]);
for (PBVHNode *node : nodes) {
BKE_pbvh_node_mark_update_visibility(node);
}
BKE_pbvh_update_vertex_data(ss->pbvh, PBVH_UpdateVisibility);
@@ -1382,21 +1367,18 @@ static void sculpt_face_set_edit_modify_face_sets(Object *ob,
wmOperator *op)
{
PBVH *pbvh = ob->sculpt->pbvh;
PBVHNode **nodes;
int totnode;
BKE_pbvh_search_gather(pbvh, nullptr, nullptr, &nodes, &totnode);
Vector<PBVHNode *> nodes = blender::bke::pbvh::search_gather(pbvh, nullptr, nullptr);
if (!nodes) {
if (nodes.is_empty()) {
return;
}
SCULPT_undo_push_begin(ob, op);
for (const int i : blender::IndexRange(totnode)) {
SCULPT_undo_push_node(ob, nodes[i], SCULPT_UNDO_FACE_SETS);
for (PBVHNode *node : nodes) {
SCULPT_undo_push_node(ob, node, SCULPT_UNDO_FACE_SETS);
}
sculpt_face_set_apply_edit(ob, abs(active_face_set), mode, modify_hidden);
SCULPT_undo_push_end(ob);
face_set_edit_do_post_visibility_updates(ob, nodes, totnode);
MEM_freeN(nodes);
face_set_edit_do_post_visibility_updates(ob, nodes);
}
static void sculpt_face_set_edit_modify_coordinates(bContext *C,
@@ -1408,17 +1390,15 @@ static void sculpt_face_set_edit_modify_coordinates(bContext *C,
Sculpt *sd = CTX_data_tool_settings(C)->sculpt;
SculptSession *ss = ob->sculpt;
PBVH *pbvh = ss->pbvh;
PBVHNode **nodes;
int totnode;
BKE_pbvh_search_gather(pbvh, nullptr, nullptr, &nodes, &totnode);
Vector<PBVHNode *> nodes = blender::bke::pbvh::search_gather(pbvh, nullptr, nullptr);
const float strength = RNA_float_get(op->ptr, "strength");
SCULPT_undo_push_begin(ob, op);
for (int i = 0; i < totnode; i++) {
BKE_pbvh_node_mark_update(nodes[i]);
SCULPT_undo_push_node(ob, nodes[i], SCULPT_UNDO_COORDS);
for (PBVHNode *node : nodes) {
BKE_pbvh_node_mark_update(node);
SCULPT_undo_push_node(ob, node, SCULPT_UNDO_COORDS);
}
sculpt_face_set_apply_edit(ob, abs(active_face_set), mode, false, strength);
@@ -1428,7 +1408,6 @@ static void sculpt_face_set_edit_modify_coordinates(bContext *C,
SCULPT_flush_update_step(C, SCULPT_UPDATE_COORDS);
SCULPT_flush_update_done(C, ob, SCULPT_UPDATE_COORDS);
SCULPT_undo_push_end(ob);
MEM_freeN(nodes);
}
static bool sculpt_face_set_edit_init(bContext *C, wmOperator *op)

View File

@@ -289,8 +289,9 @@ static void sculpt_color_filter_apply(bContext *C, wmOperator *op, Object *ob)
TaskParallelSettings settings;
BLI_parallel_range_settings_defaults(&settings);
BKE_pbvh_parallel_range_settings(&settings, true, ss->filter_cache->totnode);
BLI_task_parallel_range(0, ss->filter_cache->totnode, &data, color_filter_task_cb, &settings);
BKE_pbvh_parallel_range_settings(&settings, true, ss->filter_cache->nodes.size());
BLI_task_parallel_range(
0, ss->filter_cache->nodes.size(), &data, color_filter_task_cb, &settings);
SCULPT_flush_update_step(C, SCULPT_UPDATE_COLOR);
}

View File

@@ -161,9 +161,7 @@ static int sculpt_mask_filter_exec(bContext *C, wmOperator *op)
Object *ob = CTX_data_active_object(C);
Depsgraph *depsgraph = CTX_data_depsgraph_pointer(C);
const Scene *scene = CTX_data_scene(C);
PBVHNode **nodes;
Sculpt *sd = CTX_data_tool_settings(C)->sculpt;
int totnode;
int filter_type = RNA_enum_get(op->ptr, "filter_type");
MultiresModifierData *mmd = BKE_sculpt_multires_active(scene, ob);
@@ -182,11 +180,11 @@ static int sculpt_mask_filter_exec(bContext *C, wmOperator *op)
int num_verts = SCULPT_vertex_count_get(ss);
BKE_pbvh_search_gather(pbvh, nullptr, nullptr, &nodes, &totnode);
Vector<PBVHNode *> nodes = blender::bke::pbvh::search_gather(pbvh, nullptr, nullptr);
SCULPT_undo_push_begin(ob, op);
for (int i = 0; i < totnode; i++) {
SCULPT_undo_push_node(ob, nodes[i], SCULPT_UNDO_MASK);
for (PBVHNode *node : nodes) {
SCULPT_undo_push_node(ob, node, SCULPT_UNDO_MASK);
}
float *prev_mask = nullptr;
@@ -217,16 +215,14 @@ static int sculpt_mask_filter_exec(bContext *C, wmOperator *op)
data.prev_mask = prev_mask;
TaskParallelSettings settings;
BKE_pbvh_parallel_range_settings(&settings, true, totnode);
BLI_task_parallel_range(0, totnode, &data, mask_filter_task_cb, &settings);
BKE_pbvh_parallel_range_settings(&settings, true, nodes.size());
BLI_task_parallel_range(0, nodes.size(), &data, mask_filter_task_cb, &settings);
if (ELEM(filter_type, MASK_FILTER_GROW, MASK_FILTER_SHRINK)) {
MEM_freeN(prev_mask);
}
}
MEM_SAFE_FREE(nodes);
SCULPT_undo_push_end(ob);
SCULPT_tag_update_overlays(C);
@@ -234,8 +230,10 @@ static int sculpt_mask_filter_exec(bContext *C, wmOperator *op)
return OPERATOR_FINISHED;
}
void SCULPT_mask_filter_smooth_apply(
Sculpt *sd, Object *ob, PBVHNode **nodes, const int totnode, const int smooth_iterations)
void SCULPT_mask_filter_smooth_apply(Sculpt *sd,
Object *ob,
Span<PBVHNode *> nodes,
const int smooth_iterations)
{
SculptThreadedTaskData data{};
data.sd = sd;
@@ -245,8 +243,8 @@ void SCULPT_mask_filter_smooth_apply(
for (int i = 0; i < smooth_iterations; i++) {
TaskParallelSettings settings;
BKE_pbvh_parallel_range_settings(&settings, true, totnode);
BLI_task_parallel_range(0, totnode, &data, mask_filter_task_cb, &settings);
BKE_pbvh_parallel_range_settings(&settings, true, nodes.size());
BLI_task_parallel_range(0, nodes.size(), &data, mask_filter_task_cb, &settings);
}
}

View File

@@ -117,7 +117,7 @@ void SCULPT_filter_cache_init(bContext *C,
SculptSession *ss = ob->sculpt;
PBVH *pbvh = ob->sculpt->pbvh;
ss->filter_cache = MEM_cnew<FilterCache>(__func__);
ss->filter_cache = MEM_new<FilterCache>(__func__);
ss->filter_cache->start_filter_strength = start_strength;
ss->filter_cache->random_seed = rand();
@@ -132,14 +132,11 @@ void SCULPT_filter_cache_init(bContext *C,
search_data.radius_squared = FLT_MAX;
search_data.ignore_fully_ineffective = true;
BKE_pbvh_search_gather(pbvh,
SCULPT_search_sphere_cb,
&search_data,
&ss->filter_cache->nodes,
&ss->filter_cache->totnode);
ss->filter_cache->nodes = blender::bke::pbvh::search_gather(
pbvh, SCULPT_search_sphere_cb, &search_data);
for (int i = 0; i < ss->filter_cache->totnode; i++) {
BKE_pbvh_node_mark_normals_update(ss->filter_cache->nodes[i]);
for (PBVHNode *node : ss->filter_cache->nodes) {
BKE_pbvh_node_mark_normals_update(node);
}
/* `mesh->runtime.subdiv_ccg` is not available. Updating of the normals is done during drawing.
@@ -155,9 +152,9 @@ void SCULPT_filter_cache_init(bContext *C,
data.filter_undo_type = undo_type;
TaskParallelSettings settings;
BKE_pbvh_parallel_range_settings(&settings, true, ss->filter_cache->totnode);
BKE_pbvh_parallel_range_settings(&settings, true, ss->filter_cache->nodes.size());
BLI_task_parallel_range(
0, ss->filter_cache->totnode, &data, filter_cache_init_task_cb, &settings);
0, ss->filter_cache->nodes.size(), &data, filter_cache_init_task_cb, &settings);
/* Setup orientation matrices. */
copy_m4_m4(ss->filter_cache->obmat, ob->object_to_world);
@@ -180,8 +177,7 @@ void SCULPT_filter_cache_init(bContext *C,
float mval_fl[2] = {float(mval[0]), float(mval[1])};
if (vc.rv3d && SCULPT_stroke_get_location(C, co, mval_fl, false)) {
PBVHNode **nodes;
int totnode;
Vector<PBVHNode *> nodes;
/* Get radius from brush. */
Brush *brush = BKE_paint_brush(&sd->paint);
@@ -206,19 +202,16 @@ void SCULPT_filter_cache_init(bContext *C,
search_data2.radius_squared = radius * radius;
search_data2.ignore_fully_ineffective = true;
BKE_pbvh_search_gather(pbvh, SCULPT_search_sphere_cb, &search_data2, &nodes, &totnode);
nodes = blender::bke::pbvh::search_gather(pbvh, SCULPT_search_sphere_cb, &search_data2);
if (BKE_paint_brush(&sd->paint) &&
SCULPT_pbvh_calc_area_normal(
brush, ob, nodes, totnode, true, ss->filter_cache->initial_normal)) {
SCULPT_pbvh_calc_area_normal(brush, ob, nodes, true, ss->filter_cache->initial_normal)) {
copy_v3_v3(ss->last_normal, ss->filter_cache->initial_normal);
}
else {
copy_v3_v3(ss->filter_cache->initial_normal, ss->last_normal);
}
MEM_SAFE_FREE(nodes);
/* Update last stroke location */
mul_m4_v3(ob->object_to_world, co);
@@ -257,7 +250,6 @@ void SCULPT_filter_cache_free(SculptSession *ss)
if (ss->filter_cache->automasking) {
SCULPT_automasking_cache_free(ss->filter_cache->automasking);
}
MEM_SAFE_FREE(ss->filter_cache->nodes);
MEM_SAFE_FREE(ss->filter_cache->mask_update_it);
MEM_SAFE_FREE(ss->filter_cache->prev_mask);
MEM_SAFE_FREE(ss->filter_cache->normal_factor);
@@ -267,7 +259,7 @@ void SCULPT_filter_cache_free(SculptSession *ss)
MEM_SAFE_FREE(ss->filter_cache->detail_directions);
MEM_SAFE_FREE(ss->filter_cache->limit_surface_co);
MEM_SAFE_FREE(ss->filter_cache->pre_smoothed_color);
MEM_SAFE_FREE(ss->filter_cache);
MEM_delete<FilterCache>(ss->filter_cache);
}
typedef enum eSculptMeshFilterType {
@@ -778,12 +770,13 @@ static void sculpt_mesh_filter_apply(bContext *C, wmOperator *op)
data.filter_strength = filter_strength;
TaskParallelSettings settings;
BKE_pbvh_parallel_range_settings(&settings, true, ss->filter_cache->totnode);
BLI_task_parallel_range(0, ss->filter_cache->totnode, &data, mesh_filter_task_cb, &settings);
BKE_pbvh_parallel_range_settings(&settings, true, ss->filter_cache->nodes.size());
BLI_task_parallel_range(
0, ss->filter_cache->nodes.size(), &data, mesh_filter_task_cb, &settings);
if (filter_type == MESH_FILTER_SURFACE_SMOOTH) {
BLI_task_parallel_range(0,
ss->filter_cache->totnode,
ss->filter_cache->nodes.size(),
&data,
mesh_filter_surface_smooth_displace_task_cb,
&settings);
@@ -872,22 +865,19 @@ static void sculpt_mesh_filter_cancel(bContext *C, wmOperator * /*op*/)
{
Object *ob = CTX_data_active_object(C);
SculptSession *ss = ob->sculpt;
PBVHNode **nodes;
int nodes_num;
if (!ss || !ss->pbvh) {
return;
}
/* Gather all PBVH leaf nodes. */
BKE_pbvh_search_gather(ss->pbvh, nullptr, nullptr, &nodes, &nodes_num);
Vector<PBVHNode *> nodes = blender::bke::pbvh::search_gather(ss->pbvh, nullptr, nullptr);
for (int i : IndexRange(nodes_num)) {
PBVHNode *node = nodes[i];
for (PBVHNode *node : nodes) {
PBVHVertexIter vd;
SculptOrigVertData orig_data;
SCULPT_orig_vert_data_init(&orig_data, ob, nodes[i], SCULPT_UNDO_COORDS);
SCULPT_orig_vert_data_init(&orig_data, ob, node, SCULPT_UNDO_COORDS);
BKE_pbvh_vertex_iter_begin (ss->pbvh, node, vd, PBVH_ITER_UNIQUE) {
SCULPT_orig_vert_data_update(&orig_data, &vd);
@@ -899,7 +889,6 @@ static void sculpt_mesh_filter_cancel(bContext *C, wmOperator * /*op*/)
BKE_pbvh_node_mark_update(node);
}
MEM_SAFE_FREE(nodes);
BKE_pbvh_update_bounds(ss->pbvh, PBVH_UpdateBB);
}

View File

@@ -22,7 +22,9 @@
#include "BLI_compiler_attrs.h"
#include "BLI_compiler_compat.h"
#include "BLI_gsqueue.h"
#include "BLI_span.hh"
#include "BLI_threads.h"
#include "BLI_vector.hh"
#include "ED_view3d.h"
@@ -46,6 +48,9 @@ struct wmKeyConfig;
struct wmOperator;
struct wmOperatorType;
using blender::Span;
using blender::Vector;
/* Updates */
/* -------------------------------------------------------------------- */
@@ -243,8 +248,7 @@ struct SculptThreadedTaskData {
Sculpt *sd;
Object *ob;
const Brush *brush;
PBVHNode **nodes;
int totnode;
Span<PBVHNode *> nodes;
VPaint *vp;
WPaintData *wpd;
@@ -469,8 +473,7 @@ struct FilterCache {
float (*limit_surface_co)[3];
/* unmasked nodes */
PBVHNode **nodes;
int totnode;
Vector<PBVHNode *> nodes;
/* Cloth filter. */
SculptClothSimulation *cloth_sim;
@@ -781,8 +784,7 @@ struct ExpandCache {
/* Cached PBVH nodes. This allows to skip gathering all nodes from the PBVH each time expand
* needs to update the state of the elements. */
PBVHNode **nodes;
int totnode;
Vector<PBVHNode *> nodes;
/* Expand state options. */
@@ -1171,18 +1173,16 @@ BLI_INLINE bool SCULPT_tool_needs_all_pbvh_nodes(const Brush *brush)
}
void SCULPT_calc_brush_plane(
Sculpt *sd, Object *ob, PBVHNode **nodes, int totnode, float r_area_no[3], float r_area_co[3]);
Sculpt *sd, Object *ob, Span<PBVHNode *> nodes, float r_area_no[3], float r_area_co[3]);
void SCULPT_calc_area_normal(
Sculpt *sd, Object *ob, PBVHNode **nodes, int totnode, float r_area_no[3]);
void SCULPT_calc_area_normal(Sculpt *sd, Object *ob, Span<PBVHNode *> nodes, float r_area_no[3]);
/**
* This calculates flatten center and area normal together,
* amortizing the memory bandwidth and loop overhead to calculate both at the same time.
*/
void SCULPT_calc_area_normal_and_center(
Sculpt *sd, Object *ob, PBVHNode **nodes, int totnode, float r_area_no[3], float r_area_co[3]);
void SCULPT_calc_area_center(
Sculpt *sd, Object *ob, PBVHNode **nodes, int totnode, float r_area_co[3]);
Sculpt *sd, Object *ob, Span<PBVHNode *> nodes, float r_area_no[3], float r_area_co[3]);
void SCULPT_calc_area_center(Sculpt *sd, Object *ob, Span<PBVHNode *> nodes, float r_area_co[3]);
PBVHVertRef SCULPT_nearest_vertex_get(
Sculpt *sd, Object *ob, const float co[3], float max_distance, bool use_original);
@@ -1453,8 +1453,10 @@ void SCULPT_filter_cache_init(bContext *C,
void SCULPT_filter_cache_free(SculptSession *ss);
void SCULPT_mesh_filter_properties(wmOperatorType *ot);
void SCULPT_mask_filter_smooth_apply(
Sculpt *sd, Object *ob, PBVHNode **nodes, int totnode, int smooth_iterations);
void SCULPT_mask_filter_smooth_apply(Sculpt *sd,
Object *ob,
Span<PBVHNode *> nodes,
int smooth_iterations);
/* Filter orientation utils. */
void SCULPT_filter_to_orientation_space(float r_v[3], FilterCache *filter_cache);
@@ -1468,7 +1470,7 @@ void SCULPT_filter_zero_disabled_axis_components(float r_v[3], FilterCache *filt
* \{ */
/* Main cloth brush function */
void SCULPT_do_cloth_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnode);
void SCULPT_do_cloth_brush(Sculpt *sd, Object *ob, Span<PBVHNode *> nodes);
void SCULPT_cloth_simulation_free(SculptClothSimulation *cloth_sim);
@@ -1482,20 +1484,19 @@ SculptClothSimulation *SCULPT_cloth_brush_simulation_create(Object *ob,
bool needs_deform_coords);
void SCULPT_cloth_brush_simulation_init(SculptSession *ss, SculptClothSimulation *cloth_sim);
void SCULPT_cloth_sim_activate_nodes(SculptClothSimulation *cloth_sim,
PBVHNode **nodes,
int totnode);
void SCULPT_cloth_sim_activate_nodes(SculptClothSimulation *cloth_sim, Span<PBVHNode *> nodes);
void SCULPT_cloth_brush_store_simulation_state(SculptSession *ss,
SculptClothSimulation *cloth_sim);
void SCULPT_cloth_brush_do_simulation_step(
Sculpt *sd, Object *ob, SculptClothSimulation *cloth_sim, PBVHNode **nodes, int totnode);
void SCULPT_cloth_brush_do_simulation_step(Sculpt *sd,
Object *ob,
SculptClothSimulation *cloth_sim,
Span<PBVHNode *> nodes);
void SCULPT_cloth_brush_ensure_nodes_constraints(Sculpt *sd,
Object *ob,
PBVHNode **nodes,
int totnode,
Span<PBVHNode *> nodes,
SculptClothSimulation *cloth_sim,
float initial_location[3],
float radius);
@@ -1516,9 +1517,7 @@ void SCULPT_cloth_plane_falloff_preview_draw(uint gpuattr,
const float outline_col[3],
float outline_alpha);
PBVHNode **SCULPT_cloth_brush_affected_nodes_gather(SculptSession *ss,
Brush *brush,
int *r_totnode);
Vector<PBVHNode *> SCULPT_cloth_brush_affected_nodes_gather(SculptSession *ss, Brush *brush);
BLI_INLINE bool SCULPT_is_cloth_deform_brush(const Brush *brush)
{
@@ -1554,8 +1553,8 @@ void SCULPT_neighbor_coords_average_interior(SculptSession *ss,
PBVHVertRef vertex);
void SCULPT_smooth(
Sculpt *sd, Object *ob, PBVHNode **nodes, int totnode, float bstrength, bool smooth_mask);
void SCULPT_do_smooth_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnode);
Sculpt *sd, Object *ob, Span<PBVHNode *> nodes, float bstrength, bool smooth_mask);
void SCULPT_do_smooth_brush(Sculpt *sd, Object *ob, Span<PBVHNode *> nodes);
/* Surface Smooth Brush. */
@@ -1572,7 +1571,7 @@ void SCULPT_surface_smooth_displace_step(SculptSession *ss,
PBVHVertRef vertex,
float beta,
float fade);
void SCULPT_do_surface_smooth_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnode);
void SCULPT_do_surface_smooth_brush(Sculpt *sd, Object *ob, Span<PBVHNode *> nodes);
/* Slide/Relax */
void SCULPT_relax_vertex(SculptSession *ss,
@@ -1588,8 +1587,7 @@ void SCULPT_relax_vertex(SculptSession *ss,
*/
bool SCULPT_pbvh_calc_area_normal(const Brush *brush,
Object *ob,
PBVHNode **nodes,
int totnode,
Span<PBVHNode *> nodes,
bool use_threading,
float r_area_no[3]);
@@ -1745,7 +1743,7 @@ void SCULPT_OT_dynamic_topology_toggle(wmOperatorType *ot);
/**
* Main Brush Function.
*/
void SCULPT_do_pose_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnode);
void SCULPT_do_pose_brush(Sculpt *sd, Object *ob, Span<PBVHNode *> nodes);
/**
* Calculate the pose origin and (Optionally the pose factor)
* that is used when using the pose brush.
@@ -1782,7 +1780,7 @@ SculptBoundary *SCULPT_boundary_data_init(Object *object,
float radius);
void SCULPT_boundary_data_free(SculptBoundary *boundary);
/* Main Brush Function. */
void SCULPT_do_boundary_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnode);
void SCULPT_do_boundary_brush(Sculpt *sd, Object *ob, Span<PBVHNode *> nodes);
void SCULPT_boundary_edges_preview_draw(uint gpuattr,
SculptSession *ss,
@@ -1792,30 +1790,28 @@ void SCULPT_boundary_pivot_line_preview_draw(uint gpuattr, SculptSession *ss);
/* Multi-plane Scrape Brush. */
/* Main Brush Function. */
void SCULPT_do_multiplane_scrape_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnode);
void SCULPT_do_multiplane_scrape_brush(Sculpt *sd, Object *ob, Span<PBVHNode *> nodes);
void SCULPT_multiplane_scrape_preview_draw(uint gpuattr,
Brush *brush,
SculptSession *ss,
const float outline_col[3],
float outline_alpha);
/* Draw Face Sets Brush. */
void SCULPT_do_draw_face_sets_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnode);
void SCULPT_do_draw_face_sets_brush(Sculpt *sd, Object *ob, Span<PBVHNode *> nodes);
/* Paint Brush. */
void SCULPT_do_paint_brush(PaintModeSettings *paint_mode_settings,
Sculpt *sd,
Object *ob,
PBVHNode **nodes,
int totnode,
PBVHNode **texnodes,
int texnodes_num) ATTR_NONNULL();
Span<PBVHNode *> nodes,
Span<PBVHNode *> texnodes);
/**
* \brief Get the image canvas for painting on the given object.
*
* \return #true if an image is found. The #r_image and #r_image_user fields are filled with the
* image and image user. Returns false when the image isn't found. In the later case the r_image
* and r_image_user are set to NULL.
* \return #true if an image is found. The #r_image and #r_image_user fields are filled with
* the image and image user. Returns false when the image isn't found. In the later case the
* r_image and r_image_user are set to NULL.
*/
bool SCULPT_paint_image_canvas_get(PaintModeSettings *paint_mode_settings,
Object *ob,
@@ -1824,44 +1820,42 @@ bool SCULPT_paint_image_canvas_get(PaintModeSettings *paint_mode_settings,
void SCULPT_do_paint_brush_image(PaintModeSettings *paint_mode_settings,
Sculpt *sd,
Object *ob,
PBVHNode **texnodes,
int texnode_num) ATTR_NONNULL();
Span<PBVHNode *> texnodes);
bool SCULPT_use_image_paint_brush(PaintModeSettings *settings, Object *ob) ATTR_NONNULL();
/* Smear Brush. */
void SCULPT_do_smear_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnode);
void SCULPT_do_smear_brush(Sculpt *sd, Object *ob, Span<PBVHNode *> nodes);
float SCULPT_clay_thumb_get_stabilized_pressure(StrokeCache *cache);
void SCULPT_do_draw_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnode);
void SCULPT_do_draw_brush(Sculpt *sd, Object *ob, Span<PBVHNode *> nodes);
void SCULPT_do_fill_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnode);
void SCULPT_do_scrape_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnode);
void SCULPT_do_clay_thumb_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnode);
void SCULPT_do_flatten_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnode);
void SCULPT_do_clay_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnode);
void SCULPT_do_clay_strips_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnode);
void SCULPT_do_snake_hook_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnode);
void SCULPT_do_thumb_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnode);
void SCULPT_do_rotate_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnode);
void SCULPT_do_layer_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnode);
void SCULPT_do_inflate_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnode);
void SCULPT_do_nudge_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnode);
void SCULPT_do_crease_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnode);
void SCULPT_do_pinch_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnode);
void SCULPT_do_grab_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnode);
void SCULPT_do_elastic_deform_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnode);
void SCULPT_do_draw_sharp_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnode);
void SCULPT_do_slide_relax_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnode);
void SCULPT_do_fill_brush(Sculpt *sd, Object *ob, Span<PBVHNode *> nodes);
void SCULPT_do_scrape_brush(Sculpt *sd, Object *ob, Span<PBVHNode *> nodes);
void SCULPT_do_clay_thumb_brush(Sculpt *sd, Object *ob, Span<PBVHNode *> nodes);
void SCULPT_do_flatten_brush(Sculpt *sd, Object *ob, Span<PBVHNode *> nodes);
void SCULPT_do_clay_brush(Sculpt *sd, Object *ob, Span<PBVHNode *> nodes);
void SCULPT_do_clay_strips_brush(Sculpt *sd, Object *ob, Span<PBVHNode *> nodes);
void SCULPT_do_snake_hook_brush(Sculpt *sd, Object *ob, Span<PBVHNode *> nodes);
void SCULPT_do_thumb_brush(Sculpt *sd, Object *ob, Span<PBVHNode *> nodes);
void SCULPT_do_rotate_brush(Sculpt *sd, Object *ob, Span<PBVHNode *> nodes);
void SCULPT_do_layer_brush(Sculpt *sd, Object *ob, Span<PBVHNode *> nodes);
void SCULPT_do_inflate_brush(Sculpt *sd, Object *ob, Span<PBVHNode *> nodes);
void SCULPT_do_nudge_brush(Sculpt *sd, Object *ob, Span<PBVHNode *> nodes);
void SCULPT_do_crease_brush(Sculpt *sd, Object *ob, Span<PBVHNode *> nodes);
void SCULPT_do_pinch_brush(Sculpt *sd, Object *ob, Span<PBVHNode *> nodes);
void SCULPT_do_grab_brush(Sculpt *sd, Object *ob, Span<PBVHNode *> nodes);
void SCULPT_do_elastic_deform_brush(Sculpt *sd, Object *ob, Span<PBVHNode *> nodes);
void SCULPT_do_draw_sharp_brush(Sculpt *sd, Object *ob, Span<PBVHNode *> nodes);
void SCULPT_do_slide_relax_brush(Sculpt *sd, Object *ob, Span<PBVHNode *> nodes);
void SCULPT_do_displacement_smear_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnode);
void SCULPT_do_displacement_eraser_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnode);
void SCULPT_do_mask_brush_draw(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnode);
void SCULPT_do_mask_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnode);
void SCULPT_do_displacement_smear_brush(Sculpt *sd, Object *ob, Span<PBVHNode *> nodes);
void SCULPT_do_displacement_eraser_brush(Sculpt *sd, Object *ob, Span<PBVHNode *> nodes);
void SCULPT_do_mask_brush_draw(Sculpt *sd, Object *ob, Span<PBVHNode *> nodes);
void SCULPT_do_mask_brush(Sculpt *sd, Object *ob, Span<PBVHNode *> nodes);
/** \} */
void SCULPT_bmesh_topology_rake(
Sculpt *sd, Object *ob, PBVHNode **nodes, int totnode, float bstrength);
void SCULPT_bmesh_topology_rake(Sculpt *sd, Object *ob, Span<PBVHNode *> nodes, float bstrength);
/* end sculpt_brush_types.cc */

View File

@@ -46,7 +46,7 @@ static void sculpt_mask_expand_cancel(bContext *C, wmOperator *op)
MEM_freeN(op->customdata);
for (int n = 0; n < ss->filter_cache->totnode; n++) {
for (int n = 0; n < ss->filter_cache->nodes.size(); n++) {
PBVHNode *node = ss->filter_cache->nodes[n];
if (create_face_set) {
for (int i = 0; i < ss->totfaces; i++) {
@@ -190,8 +190,7 @@ static int sculpt_mask_expand_modal(bContext *C, wmOperator *op, const wmEvent *
/* Smooth iterations. */
BKE_sculpt_update_object_for_edit(depsgraph, ob, true, false, false);
const int smooth_iterations = RNA_int_get(op->ptr, "smooth_iterations");
SCULPT_mask_filter_smooth_apply(
sd, ob, ss->filter_cache->nodes, ss->filter_cache->totnode, smooth_iterations);
SCULPT_mask_filter_smooth_apply(sd, ob, ss->filter_cache->nodes, smooth_iterations);
/* Pivot position. */
if (RNA_boolean_get(op->ptr, "update_pivot")) {
@@ -201,9 +200,9 @@ static int sculpt_mask_expand_modal(bContext *C, wmOperator *op, const wmEvent *
int total = 0;
zero_v3(avg);
for (int n = 0; n < ss->filter_cache->totnode; n++) {
for (PBVHNode *node : ss->filter_cache->nodes) {
PBVHVertexIter vd;
BKE_pbvh_vertex_iter_begin (ss->pbvh, ss->filter_cache->nodes[n], vd, PBVH_ITER_UNIQUE) {
BKE_pbvh_vertex_iter_begin (ss->pbvh, node, vd, PBVH_ITER_UNIQUE) {
const float mask = (vd.mask) ? *vd.mask : 0.0f;
if (mask < (0.5f + threshold) && mask > (0.5f - threshold)) {
if (SCULPT_check_vertex_pivot_symmetry(
@@ -225,8 +224,8 @@ static int sculpt_mask_expand_modal(bContext *C, wmOperator *op, const wmEvent *
MEM_freeN(op->customdata);
for (int i = 0; i < ss->filter_cache->totnode; i++) {
BKE_pbvh_node_mark_redraw(ss->filter_cache->nodes[i]);
for (PBVHNode *node : ss->filter_cache->nodes) {
BKE_pbvh_node_mark_redraw(node);
}
SCULPT_filter_cache_free(ss);
@@ -270,8 +269,9 @@ static int sculpt_mask_expand_modal(bContext *C, wmOperator *op, const wmEvent *
data.mask_expand_create_face_set = RNA_boolean_get(op->ptr, "create_face_set");
TaskParallelSettings settings;
BKE_pbvh_parallel_range_settings(&settings, true, ss->filter_cache->totnode);
BLI_task_parallel_range(0, ss->filter_cache->totnode, &data, sculpt_expand_task_cb, &settings);
BKE_pbvh_parallel_range_settings(&settings, true, ss->filter_cache->nodes.size());
BLI_task_parallel_range(
0, ss->filter_cache->nodes.size(), &data, sculpt_expand_task_cb, &settings);
ss->filter_cache->mask_update_current_it = mask_expand_update_it;
}
@@ -353,23 +353,22 @@ static int sculpt_mask_expand_invoke(bContext *C, wmOperator *op, const wmEvent
int vertex_count = SCULPT_vertex_count_get(ss);
ss->filter_cache = MEM_cnew<FilterCache>(__func__);
ss->filter_cache = MEM_new<FilterCache>(__func__);
BKE_pbvh_search_gather(
pbvh, nullptr, nullptr, &ss->filter_cache->nodes, &ss->filter_cache->totnode);
ss->filter_cache->nodes = blender::bke::pbvh::search_gather(pbvh, nullptr, nullptr);
SCULPT_undo_push_begin(ob, op);
if (create_face_set) {
for (int i = 0; i < ss->filter_cache->totnode; i++) {
BKE_pbvh_node_mark_redraw(ss->filter_cache->nodes[i]);
SCULPT_undo_push_node(ob, ss->filter_cache->nodes[i], SCULPT_UNDO_FACE_SETS);
for (PBVHNode *node : ss->filter_cache->nodes) {
BKE_pbvh_node_mark_redraw(node);
SCULPT_undo_push_node(ob, node, SCULPT_UNDO_FACE_SETS);
}
}
else {
for (int i = 0; i < ss->filter_cache->totnode; i++) {
SCULPT_undo_push_node(ob, ss->filter_cache->nodes[i], SCULPT_UNDO_MASK);
BKE_pbvh_node_mark_redraw(ss->filter_cache->nodes[i]);
for (PBVHNode *node : ss->filter_cache->nodes) {
SCULPT_undo_push_node(ob, node, SCULPT_UNDO_MASK);
BKE_pbvh_node_mark_redraw(node);
}
}
@@ -447,8 +446,9 @@ static int sculpt_mask_expand_invoke(bContext *C, wmOperator *op, const wmEvent
data.mask_expand_create_face_set = RNA_boolean_get(op->ptr, "create_face_set");
TaskParallelSettings settings;
BKE_pbvh_parallel_range_settings(&settings, true, ss->filter_cache->totnode);
BLI_task_parallel_range(0, ss->filter_cache->totnode, &data, sculpt_expand_task_cb, &settings);
BKE_pbvh_parallel_range_settings(&settings, true, ss->filter_cache->nodes.size());
BLI_task_parallel_range(
0, ss->filter_cache->nodes.size(), &data, sculpt_expand_task_cb, &settings);
const char *status_str = TIP_(
"Move the mouse to expand the mask from the active vertex. LMB: confirm mask, ESC/RMB: "

View File

@@ -117,11 +117,9 @@ static int sculpt_mask_init_exec(bContext *C, wmOperator *op)
BKE_sculpt_update_object_for_edit(depsgraph, ob, true, true, false);
PBVH *pbvh = ob->sculpt->pbvh;
PBVHNode **nodes;
int totnode;
BKE_pbvh_search_gather(pbvh, nullptr, nullptr, &nodes, &totnode);
Vector<PBVHNode *> nodes = blender::bke::pbvh::search_gather(pbvh, nullptr, nullptr);
if (totnode == 0) {
if (nodes.is_empty()) {
return OPERATOR_CANCELLED;
}
@@ -138,15 +136,14 @@ static int sculpt_mask_init_exec(bContext *C, wmOperator *op)
data.mask_init_seed = PIL_check_seconds_timer();
TaskParallelSettings settings;
BKE_pbvh_parallel_range_settings(&settings, true, totnode);
BLI_task_parallel_range(0, totnode, &data, mask_init_task_cb, &settings);
BKE_pbvh_parallel_range_settings(&settings, true, nodes.size());
BLI_task_parallel_range(0, nodes.size(), &data, mask_init_task_cb, &settings);
multires_stitch_grids(ob);
SCULPT_undo_push_end(ob);
BKE_pbvh_update_vertex_data(ss->pbvh, PBVH_UpdateMask);
MEM_SAFE_FREE(nodes);
SCULPT_tag_update_overlays(C);
return OPERATOR_FINISHED;
}

View File

@@ -211,7 +211,7 @@ static void do_multiplane_scrape_brush_task_cb_ex(void *__restrict userdata,
/* Public functions. */
void SCULPT_do_multiplane_scrape_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnode)
void SCULPT_do_multiplane_scrape_brush(Sculpt *sd, Object *ob, Span<PBVHNode *> nodes)
{
SculptSession *ss = ob->sculpt;
Brush *brush = BKE_paint_brush(&sd->paint);
@@ -231,10 +231,10 @@ void SCULPT_do_multiplane_scrape_brush(Sculpt *sd, Object *ob, PBVHNode **nodes,
float temp[3];
float mat[4][4];
SCULPT_calc_brush_plane(sd, ob, nodes, totnode, area_no_sp, area_co);
SCULPT_calc_brush_plane(sd, ob, nodes, area_no_sp, area_co);
if (brush->sculpt_plane != SCULPT_DISP_DIR_AREA || (brush->flag & BRUSH_ORIGINAL_NORMAL)) {
SCULPT_calc_area_normal(sd, ob, nodes, totnode, area_no);
SCULPT_calc_area_normal(sd, ob, nodes, area_no);
}
else {
copy_v3_v3(area_no, area_no_sp);
@@ -281,19 +281,18 @@ void SCULPT_do_multiplane_scrape_brush(Sculpt *sd, Object *ob, PBVHNode **nodes,
sample_data.ob = ob;
sample_data.brush = brush;
sample_data.nodes = nodes;
sample_data.totnode = totnode;
sample_data.mat = mat;
MultiplaneScrapeSampleData mssd = {{{0}}};
TaskParallelSettings sample_settings;
BKE_pbvh_parallel_range_settings(&sample_settings, true, totnode);
BKE_pbvh_parallel_range_settings(&sample_settings, true, nodes.size());
sample_settings.func_reduce = calc_multiplane_scrape_surface_reduce;
sample_settings.userdata_chunk = &mssd;
sample_settings.userdata_chunk_size = sizeof(MultiplaneScrapeSampleData);
BLI_task_parallel_range(
0, totnode, &sample_data, calc_multiplane_scrape_surface_task_cb, &sample_settings);
0, nodes.size(), &sample_data, calc_multiplane_scrape_surface_task_cb, &sample_settings);
float sampled_plane_normals[2][3];
float sampled_plane_co[2][3];
@@ -377,8 +376,9 @@ void SCULPT_do_multiplane_scrape_brush(Sculpt *sd, Object *ob, PBVHNode **nodes,
plane_from_point_normal_v3(data.multiplane_scrape_planes[0], area_co, plane_no);
TaskParallelSettings settings;
BKE_pbvh_parallel_range_settings(&settings, true, totnode);
BLI_task_parallel_range(0, totnode, &data, do_multiplane_scrape_brush_task_cb_ex, &settings);
BKE_pbvh_parallel_range_settings(&settings, true, nodes.size());
BLI_task_parallel_range(
0, nodes.size(), &data, do_multiplane_scrape_brush_task_cb_ex, &settings);
}
void SCULPT_multiplane_scrape_preview_draw(const uint gpuattr,

View File

@@ -817,9 +817,7 @@ static void sculpt_mask_by_color_contiguous(Object *object,
SCULPT_floodfill_execute(ss, &flood, sculpt_mask_by_color_contiguous_floodfill_cb, &ffd);
SCULPT_floodfill_free(&flood);
int totnode;
PBVHNode **nodes;
BKE_pbvh_search_gather(ss->pbvh, nullptr, nullptr, &nodes, &totnode);
Vector<PBVHNode *> nodes = blender::bke::pbvh::search_gather(ss->pbvh, nullptr, nullptr);
SculptThreadedTaskData data{};
data.ob = object;
@@ -831,11 +829,9 @@ static void sculpt_mask_by_color_contiguous(Object *object,
data.mask_by_color_preserve_mask = preserve_mask;
TaskParallelSettings settings;
BKE_pbvh_parallel_range_settings(&settings, true, totnode);
BKE_pbvh_parallel_range_settings(&settings, true, nodes.size());
BLI_task_parallel_range(
0, totnode, &data, do_mask_by_color_contiguous_update_nodes_cb, &settings);
MEM_SAFE_FREE(nodes);
0, nodes.size(), &data, do_mask_by_color_contiguous_update_nodes_cb, &settings);
MEM_freeN(new_mask);
}
@@ -885,9 +881,7 @@ static void sculpt_mask_by_color_full_mesh(Object *object,
{
SculptSession *ss = object->sculpt;
int totnode;
PBVHNode **nodes;
BKE_pbvh_search_gather(ss->pbvh, nullptr, nullptr, &nodes, &totnode);
Vector<PBVHNode *> nodes = blender::bke::pbvh::search_gather(ss->pbvh, nullptr, nullptr);
SculptThreadedTaskData data{};
data.ob = object;
@@ -898,10 +892,8 @@ static void sculpt_mask_by_color_full_mesh(Object *object,
data.mask_by_color_preserve_mask = preserve_mask;
TaskParallelSettings settings;
BKE_pbvh_parallel_range_settings(&settings, true, totnode);
BLI_task_parallel_range(0, totnode, &data, do_mask_by_color_task_cb, &settings);
MEM_SAFE_FREE(nodes);
BKE_pbvh_parallel_range_settings(&settings, true, nodes.size());
BLI_task_parallel_range(0, nodes.size(), &data, do_mask_by_color_task_cb, &settings);
}
static int sculpt_mask_by_color_invoke(bContext *C, wmOperator *op, const wmEvent *event)
@@ -1011,7 +1003,7 @@ enum CavityBakeSettingsSource {
struct AutomaskBakeTaskData {
SculptSession *ss;
AutomaskingCache *automasking;
PBVHNode **nodes;
Span<PBVHNode *> nodes;
CavityBakeMixMode mode;
float factor;
Object *ob;
@@ -1089,10 +1081,7 @@ static int sculpt_bake_cavity_exec(bContext *C, wmOperator *op)
CavityBakeMixMode mode = CavityBakeMixMode(RNA_enum_get(op->ptr, "mix_mode"));
float factor = RNA_float_get(op->ptr, "mix_factor");
PBVHNode **nodes;
int totnode;
BKE_pbvh_search_gather(ss->pbvh, nullptr, nullptr, &nodes, &totnode);
Vector<PBVHNode *> nodes = blender::bke::pbvh::search_gather(ss->pbvh, nullptr, nullptr);
AutomaskBakeTaskData tdata;
@@ -1165,10 +1154,9 @@ static int sculpt_bake_cavity_exec(bContext *C, wmOperator *op)
tdata.automasking = SCULPT_automasking_cache_init(&sd2, &brush2, ob);
TaskParallelSettings settings;
BKE_pbvh_parallel_range_settings(&settings, true, totnode);
BLI_task_parallel_range(0, totnode, &tdata, sculpt_bake_cavity_exec_task_cb, &settings);
BKE_pbvh_parallel_range_settings(&settings, true, nodes.size());
BLI_task_parallel_range(0, nodes.size(), &tdata, sculpt_bake_cavity_exec_task_cb, &settings);
MEM_SAFE_FREE(nodes);
SCULPT_automasking_cache_free(tdata.automasking);
BKE_pbvh_update_vertex_data(ss->pbvh, PBVH_UpdateMask);
@@ -1304,13 +1292,11 @@ static int sculpt_reveal_all_exec(bContext *C, wmOperator *op)
return OPERATOR_CANCELLED;
}
PBVHNode **nodes;
int totnode;
bool with_bmesh = BKE_pbvh_type(ss->pbvh) == PBVH_BMESH;
BKE_pbvh_search_gather(ss->pbvh, nullptr, nullptr, &nodes, &totnode);
Vector<PBVHNode *> nodes = blender::bke::pbvh::search_gather(ss->pbvh, nullptr, nullptr);
if (!totnode) {
if (nodes.is_empty()) {
return OPERATOR_CANCELLED;
}
@@ -1319,11 +1305,11 @@ static int sculpt_reveal_all_exec(bContext *C, wmOperator *op)
SCULPT_undo_push_begin(ob, op);
for (int i = 0; i < totnode; i++) {
BKE_pbvh_node_mark_update_visibility(nodes[i]);
for (PBVHNode *node : nodes) {
BKE_pbvh_node_mark_update_visibility(node);
if (!with_bmesh) {
SCULPT_undo_push_node(ob, nodes[i], SCULPT_UNDO_HIDDEN);
SCULPT_undo_push_node(ob, node, SCULPT_UNDO_HIDDEN);
}
}
@@ -1367,7 +1353,6 @@ static int sculpt_reveal_all_exec(bContext *C, wmOperator *op)
BKE_pbvh_update_visibility(ss->pbvh);
SCULPT_undo_push_end(ob);
MEM_SAFE_FREE(nodes);
SCULPT_tag_update_overlays(C);
DEG_id_tag_update(&ob->id, ID_RECALC_SHADING);

View File

@@ -11,6 +11,7 @@
#include "BLI_math.h"
#include "BLI_math_color_blend.h"
#include "BLI_task.h"
#include "BLI_vector.hh"
#include "DNA_meshdata_types.h"
@@ -32,6 +33,8 @@
#include <cmath>
#include <cstdlib>
using blender::Vector;
static void do_color_smooth_task_cb_exec(void *__restrict userdata,
const int n,
const TaskParallelTLS *__restrict tls)
@@ -252,13 +255,11 @@ static void sample_wet_paint_reduce(const void *__restrict /*userdata*/,
void SCULPT_do_paint_brush(PaintModeSettings *paint_mode_settings,
Sculpt *sd,
Object *ob,
PBVHNode **nodes,
int totnode,
PBVHNode **texnodes,
int texnodes_num)
Span<PBVHNode *> nodes,
Span<PBVHNode *> texnodes)
{
if (SCULPT_use_image_paint_brush(paint_mode_settings, ob)) {
SCULPT_do_paint_brush_image(paint_mode_settings, sd, ob, texnodes, texnodes_num);
SCULPT_do_paint_brush_image(paint_mode_settings, sd, ob, texnodes);
return;
}
@@ -300,8 +301,8 @@ void SCULPT_do_paint_brush(PaintModeSettings *paint_mode_settings,
data.mat = mat;
TaskParallelSettings settings;
BKE_pbvh_parallel_range_settings(&settings, true, totnode);
BLI_task_parallel_range(0, totnode, &data, do_color_smooth_task_cb_exec, &settings);
BKE_pbvh_parallel_range_settings(&settings, true, nodes.size());
BLI_task_parallel_range(0, nodes.size(), &data, do_color_smooth_task_cb_exec, &settings);
return;
}
@@ -321,11 +322,12 @@ void SCULPT_do_paint_brush(PaintModeSettings *paint_mode_settings,
zero_v4(swptd.color);
TaskParallelSettings settings_sample;
BKE_pbvh_parallel_range_settings(&settings_sample, true, totnode);
BKE_pbvh_parallel_range_settings(&settings_sample, true, nodes.size());
settings_sample.func_reduce = sample_wet_paint_reduce;
settings_sample.userdata_chunk = &swptd;
settings_sample.userdata_chunk_size = sizeof(SampleWetPaintTLSData);
BLI_task_parallel_range(0, totnode, &task_data, do_sample_wet_paint_task_cb, &settings_sample);
BLI_task_parallel_range(
0, nodes.size(), &task_data, do_sample_wet_paint_task_cb, &settings_sample);
if (swptd.tot_samples > 0 && is_finite_v4(swptd.color)) {
copy_v4_v4(wet_color, swptd.color);
@@ -354,8 +356,8 @@ void SCULPT_do_paint_brush(PaintModeSettings *paint_mode_settings,
data.mat = mat;
TaskParallelSettings settings;
BKE_pbvh_parallel_range_settings(&settings, true, totnode);
BLI_task_parallel_range(0, totnode, &data, do_paint_brush_task_cb_ex, &settings);
BKE_pbvh_parallel_range_settings(&settings, true, nodes.size());
BLI_task_parallel_range(0, nodes.size(), &data, do_paint_brush_task_cb_ex, &settings);
}
static void do_smear_brush_task_cb_exec(void *__restrict userdata,
@@ -525,7 +527,7 @@ static void do_smear_store_prev_colors_task_cb_exec(void *__restrict userdata,
BKE_pbvh_vertex_iter_end;
}
void SCULPT_do_smear_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnode)
void SCULPT_do_smear_brush(Sculpt *sd, Object *ob, Span<PBVHNode *> nodes)
{
Brush *brush = BKE_paint_brush(&sd->paint);
SculptSession *ss = ob->sculpt;
@@ -554,15 +556,16 @@ void SCULPT_do_smear_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnode
data.nodes = nodes;
TaskParallelSettings settings;
BKE_pbvh_parallel_range_settings(&settings, true, totnode);
BKE_pbvh_parallel_range_settings(&settings, true, nodes.size());
/* Smooth colors mode. */
if (ss->cache->alt_smooth) {
BLI_task_parallel_range(0, totnode, &data, do_color_smooth_task_cb_exec, &settings);
BLI_task_parallel_range(0, nodes.size(), &data, do_color_smooth_task_cb_exec, &settings);
}
else {
/* Smear mode. */
BLI_task_parallel_range(0, totnode, &data, do_smear_store_prev_colors_task_cb_exec, &settings);
BLI_task_parallel_range(0, totnode, &data, do_smear_brush_task_cb_exec, &settings);
BLI_task_parallel_range(
0, nodes.size(), &data, do_smear_store_prev_colors_task_cb_exec, &settings);
BLI_task_parallel_range(0, nodes.size(), &data, do_smear_brush_task_cb_exec, &settings);
}
}

View File

@@ -51,7 +51,7 @@ struct ImageData {
struct TexturePaintingUserData {
Object *ob;
Brush *brush;
PBVHNode **nodes;
Span<PBVHNode *> nodes;
ImageData image_data;
};
@@ -534,12 +534,9 @@ static void fix_non_manifold_seam_bleeding(PBVH &pbvh,
}
}
static void fix_non_manifold_seam_bleeding(Object &ob,
const int totnode,
TexturePaintingUserData &user_data)
static void fix_non_manifold_seam_bleeding(Object &ob, TexturePaintingUserData &user_data)
{
Vector<image::TileNumber> dirty_tiles = collect_dirty_tiles(
Span<PBVHNode *>(user_data.nodes, totnode));
Vector<image::TileNumber> dirty_tiles = collect_dirty_tiles(user_data.nodes);
fix_non_manifold_seam_bleeding(*ob.sculpt->pbvh, user_data, dirty_tiles);
}
@@ -583,8 +580,7 @@ bool SCULPT_use_image_paint_brush(PaintModeSettings *settings, Object *ob)
void SCULPT_do_paint_brush_image(PaintModeSettings *paint_mode_settings,
Sculpt *sd,
Object *ob,
PBVHNode **texnodes,
int texnodes_num)
Span<PBVHNode *> texnodes)
{
Brush *brush = BKE_paint_brush(&sd->paint);
@@ -598,13 +594,13 @@ void SCULPT_do_paint_brush_image(PaintModeSettings *paint_mode_settings,
}
TaskParallelSettings settings;
BKE_pbvh_parallel_range_settings(&settings, true, texnodes_num);
BLI_task_parallel_range(0, texnodes_num, &data, do_push_undo_tile, &settings);
BLI_task_parallel_range(0, texnodes_num, &data, do_paint_pixels, &settings);
fix_non_manifold_seam_bleeding(*ob, texnodes_num, data);
BKE_pbvh_parallel_range_settings(&settings, true, texnodes.size());
BLI_task_parallel_range(0, texnodes.size(), &data, do_push_undo_tile, &settings);
BLI_task_parallel_range(0, texnodes.size(), &data, do_paint_pixels, &settings);
fix_non_manifold_seam_bleeding(*ob, data);
TaskParallelSettings settings_flush;
BKE_pbvh_parallel_range_settings(&settings_flush, false, texnodes_num);
BLI_task_parallel_range(0, texnodes_num, &data, do_mark_dirty_regions, &settings_flush);
BKE_pbvh_parallel_range_settings(&settings_flush, false, texnodes.size());
BLI_task_parallel_range(0, texnodes.size(), &data, do_mark_dirty_regions, &settings_flush);
}

View File

@@ -259,16 +259,14 @@ static void sculpt_pose_grow_pose_factor(Sculpt *sd,
float *r_pose_origin,
float *pose_factor)
{
PBVHNode **nodes;
PBVH *pbvh = ob->sculpt->pbvh;
int totnode;
BKE_pbvh_search_gather(pbvh, nullptr, nullptr, &nodes, &totnode);
Vector<PBVHNode *> nodes = blender::bke::pbvh::search_gather(pbvh, nullptr, nullptr);
SculptThreadedTaskData data{};
data.sd = sd;
data.ob = ob;
data.nodes = nodes;
data.totnode = totnode;
data.pose_factor = pose_factor;
data.pose_initial_co = pose_target;
@@ -276,7 +274,7 @@ static void sculpt_pose_grow_pose_factor(Sculpt *sd,
PoseGrowFactorTLSData gftd;
gftd.pos_count = 0;
zero_v3(gftd.pos_avg);
BKE_pbvh_parallel_range_settings(&settings, true, totnode);
BKE_pbvh_parallel_range_settings(&settings, true, nodes.size());
settings.func_reduce = pose_brush_grow_factor_reduce;
settings.userdata_chunk = &gftd;
settings.userdata_chunk_size = sizeof(PoseGrowFactorTLSData);
@@ -289,7 +287,7 @@ static void sculpt_pose_grow_pose_factor(Sculpt *sd,
zero_v3(gftd.pos_avg);
gftd.pos_count = 0;
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);
BLI_task_parallel_range(0, nodes.size(), &data, pose_brush_grow_factor_task_cb_ex, &settings);
if (gftd.pos_count != 0) {
mul_v3_fl(gftd.pos_avg, 1.0f / float(gftd.pos_count));
@@ -332,8 +330,6 @@ static void sculpt_pose_grow_pose_factor(Sculpt *sd,
}
}
MEM_freeN(data.prev_mask);
MEM_SAFE_FREE(nodes);
}
static bool sculpt_pose_brush_is_vertex_inside_brush_radius(const float vertex[3],
@@ -972,11 +968,9 @@ SculptPoseIKChain *SCULPT_pose_ik_chain_init(Sculpt *sd,
void SCULPT_pose_brush_init(Sculpt *sd, Object *ob, SculptSession *ss, Brush *br)
{
PBVHNode **nodes;
PBVH *pbvh = ob->sculpt->pbvh;
int totnode;
BKE_pbvh_search_gather(pbvh, nullptr, nullptr, &nodes, &totnode);
Vector<PBVHNode *> nodes = blender::bke::pbvh::search_gather(pbvh, nullptr, nullptr);
SculptThreadedTaskData data{};
data.sd = sd;
@@ -993,12 +987,10 @@ void SCULPT_pose_brush_init(Sculpt *sd, Object *ob, SculptSession *ss, Brush *br
data.pose_factor = ss->cache->pose_ik_chain->segments[ik].weights;
for (int i = 0; i < br->pose_smooth_iterations; i++) {
TaskParallelSettings settings;
BKE_pbvh_parallel_range_settings(&settings, true, totnode);
BLI_task_parallel_range(0, totnode, &data, pose_brush_init_task_cb_ex, &settings);
BKE_pbvh_parallel_range_settings(&settings, true, nodes.size());
BLI_task_parallel_range(0, nodes.size(), &data, pose_brush_init_task_cb_ex, &settings);
}
}
MEM_SAFE_FREE(nodes);
}
static void sculpt_pose_do_translate_deform(SculptSession *ss, Brush *brush)
@@ -1124,7 +1116,7 @@ static void sculpt_pose_align_pivot_local_space(float r_mat[4][4],
ortho_basis_v3v3_v3(r_mat[0], r_mat[1], r_mat[2]);
}
void SCULPT_do_pose_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnode)
void SCULPT_do_pose_brush(Sculpt *sd, Object *ob, Span<PBVHNode *> nodes)
{
SculptSession *ss = ob->sculpt;
Brush *brush = BKE_paint_brush(&sd->paint);
@@ -1216,8 +1208,8 @@ void SCULPT_do_pose_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnode)
data.nodes = nodes;
TaskParallelSettings settings;
BKE_pbvh_parallel_range_settings(&settings, true, totnode);
BLI_task_parallel_range(0, totnode, &data, do_pose_brush_task_cb_ex, &settings);
BKE_pbvh_parallel_range_settings(&settings, true, nodes.size());
BLI_task_parallel_range(0, nodes.size(), &data, do_pose_brush_task_cb_ex, &settings);
}
void SCULPT_pose_ik_chain_free(SculptPoseIKChain *ik_chain)

View File

@@ -228,10 +228,7 @@ static void do_enhance_details_brush_task_cb_ex(void *__restrict userdata,
BKE_pbvh_vertex_iter_end;
}
static void SCULPT_enhance_details_brush(Sculpt *sd,
Object *ob,
PBVHNode **nodes,
const int totnode)
static void SCULPT_enhance_details_brush(Sculpt *sd, Object *ob, Span<PBVHNode *> nodes)
{
SculptSession *ss = ob->sculpt;
Brush *brush = BKE_paint_brush(&sd->paint);
@@ -260,8 +257,8 @@ static void SCULPT_enhance_details_brush(Sculpt *sd,
data.nodes = nodes;
TaskParallelSettings settings;
BKE_pbvh_parallel_range_settings(&settings, true, totnode);
BLI_task_parallel_range(0, totnode, &data, do_enhance_details_brush_task_cb_ex, &settings);
BKE_pbvh_parallel_range_settings(&settings, true, nodes.size());
BLI_task_parallel_range(0, nodes.size(), &data, do_enhance_details_brush_task_cb_ex, &settings);
}
static void do_smooth_brush_task_cb_ex(void *__restrict userdata,
@@ -326,12 +323,8 @@ static void do_smooth_brush_task_cb_ex(void *__restrict userdata,
BKE_pbvh_vertex_iter_end;
}
void SCULPT_smooth(Sculpt *sd,
Object *ob,
PBVHNode **nodes,
const int totnode,
float bstrength,
const bool smooth_mask)
void SCULPT_smooth(
Sculpt *sd, Object *ob, Span<PBVHNode *> nodes, float bstrength, const bool smooth_mask)
{
SculptSession *ss = ob->sculpt;
Brush *brush = BKE_paint_brush(&sd->paint);
@@ -367,12 +360,12 @@ void SCULPT_smooth(Sculpt *sd,
data.strength = strength;
TaskParallelSettings settings;
BKE_pbvh_parallel_range_settings(&settings, true, totnode);
BLI_task_parallel_range(0, totnode, &data, do_smooth_brush_task_cb_ex, &settings);
BKE_pbvh_parallel_range_settings(&settings, true, nodes.size());
BLI_task_parallel_range(0, nodes.size(), &data, do_smooth_brush_task_cb_ex, &settings);
}
}
void SCULPT_do_smooth_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnode)
void SCULPT_do_smooth_brush(Sculpt *sd, Object *ob, Span<PBVHNode *> nodes)
{
SculptSession *ss = ob->sculpt;
@@ -382,11 +375,11 @@ void SCULPT_do_smooth_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnod
* middle of the stroke. */
if (ss->cache->bstrength < 0.0f) {
/* Invert mode, intensify details. */
SCULPT_enhance_details_brush(sd, ob, nodes, totnode);
SCULPT_enhance_details_brush(sd, ob, nodes);
}
else {
/* Regular mode, smooth. */
SCULPT_smooth(sd, ob, nodes, totnode, ss->cache->bstrength, false);
SCULPT_smooth(sd, ob, nodes, ss->cache->bstrength, false);
}
}
@@ -536,7 +529,7 @@ static void SCULPT_do_surface_smooth_brush_displace_task_cb_ex(
BKE_pbvh_vertex_iter_end;
}
void SCULPT_do_surface_smooth_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnode)
void SCULPT_do_surface_smooth_brush(Sculpt *sd, Object *ob, Span<PBVHNode *> nodes)
{
Brush *brush = BKE_paint_brush(&sd->paint);
@@ -548,11 +541,11 @@ void SCULPT_do_surface_smooth_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, in
data.nodes = nodes;
TaskParallelSettings settings;
BKE_pbvh_parallel_range_settings(&settings, true, totnode);
BKE_pbvh_parallel_range_settings(&settings, true, nodes.size());
for (int i = 0; i < brush->surface_smooth_iterations; i++) {
BLI_task_parallel_range(
0, totnode, &data, SCULPT_do_surface_smooth_brush_laplacian_task_cb_ex, &settings);
0, nodes.size(), &data, SCULPT_do_surface_smooth_brush_laplacian_task_cb_ex, &settings);
BLI_task_parallel_range(
0, totnode, &data, SCULPT_do_surface_smooth_brush_displace_task_cb_ex, &settings);
0, nodes.size(), &data, SCULPT_do_surface_smooth_brush_displace_task_cb_ex, &settings);
}
}

View File

@@ -195,9 +195,9 @@ static void sculpt_transform_all_vertices(Sculpt *sd, Object *ob)
/* Regular transform applies all symmetry passes at once as it is split by symmetry areas
* (each vertex can only be transformed once by the transform matrix of its area). */
TaskParallelSettings settings;
BKE_pbvh_parallel_range_settings(&settings, true, ss->filter_cache->totnode);
BKE_pbvh_parallel_range_settings(&settings, true, ss->filter_cache->nodes.size());
BLI_task_parallel_range(
0, ss->filter_cache->totnode, &data, sculpt_transform_task_cb, &settings);
0, ss->filter_cache->nodes.size(), &data, sculpt_transform_task_cb, &settings);
}
static void sculpt_elastic_transform_task_cb(void *__restrict userdata,
@@ -270,7 +270,7 @@ static void sculpt_transform_radius_elastic(Sculpt *sd, Object *ob, const float
ss, symm, ss->filter_cache->transform_displacement_mode, data.transform_mats);
TaskParallelSettings settings;
BKE_pbvh_parallel_range_settings(&settings, true, ss->filter_cache->totnode);
BKE_pbvh_parallel_range_settings(&settings, true, ss->filter_cache->nodes.size());
/* Elastic transform needs to apply all transform matrices to all vertices and then combine the
* displacement proxies as all vertices are modified by all symmetry passes. */
@@ -282,7 +282,7 @@ static void sculpt_transform_radius_elastic(Sculpt *sd, Object *ob, const float
const int symm_area = SCULPT_get_vertex_symm_area(data.elastic_transform_pivot);
copy_m4_m4(data.elastic_transform_mat, data.transform_mats[symm_area]);
BLI_task_parallel_range(
0, ss->filter_cache->totnode, &data, sculpt_elastic_transform_task_cb, &settings);
0, ss->filter_cache->nodes.size(), &data, sculpt_elastic_transform_task_cb, &settings);
}
}
SCULPT_combine_transform_proxies(sd, ob);
@@ -413,9 +413,7 @@ static int sculpt_set_pivot_position_exec(bContext *C, wmOperator *op)
}
}
else {
PBVHNode **nodes;
int totnode;
BKE_pbvh_search_gather(ss->pbvh, nullptr, nullptr, &nodes, &totnode);
Vector<PBVHNode *> nodes = blender::bke::pbvh::search_gather(ss->pbvh, nullptr, nullptr);
float avg[3];
int total = 0;
@@ -423,9 +421,9 @@ static int sculpt_set_pivot_position_exec(bContext *C, wmOperator *op)
/* Pivot to unmasked. */
if (mode == SCULPT_PIVOT_POSITION_UNMASKED) {
for (int n = 0; n < totnode; n++) {
for (PBVHNode *node : nodes) {
PBVHVertexIter vd;
BKE_pbvh_vertex_iter_begin (ss->pbvh, nodes[n], vd, PBVH_ITER_UNIQUE) {
BKE_pbvh_vertex_iter_begin (ss->pbvh, node, vd, PBVH_ITER_UNIQUE) {
const float mask = (vd.mask) ? *vd.mask : 0.0f;
if (mask < 1.0f) {
if (SCULPT_check_vertex_pivot_symmetry(vd.co, ss->pivot_pos, symm)) {
@@ -441,9 +439,9 @@ static int sculpt_set_pivot_position_exec(bContext *C, wmOperator *op)
else if (mode == SCULPT_PIVOT_POSITION_MASK_BORDER) {
const float threshold = 0.2f;
for (int n = 0; n < totnode; n++) {
for (PBVHNode *node : nodes) {
PBVHVertexIter vd;
BKE_pbvh_vertex_iter_begin (ss->pbvh, nodes[n], vd, PBVH_ITER_UNIQUE) {
BKE_pbvh_vertex_iter_begin (ss->pbvh, node, vd, PBVH_ITER_UNIQUE) {
const float mask = (vd.mask) ? *vd.mask : 0.0f;
if (mask < (0.5f + threshold) && mask > (0.5f - threshold)) {
if (SCULPT_check_vertex_pivot_symmetry(vd.co, ss->pivot_pos, symm)) {
@@ -460,8 +458,6 @@ static int sculpt_set_pivot_position_exec(bContext *C, wmOperator *op)
mul_v3_fl(avg, 1.0f / total);
copy_v3_v3(ss->pivot_pos, avg);
}
MEM_SAFE_FREE(nodes);
}
/* Update the viewport navigation rotation origin. */

View File

@@ -659,19 +659,15 @@ static void sculpt_undo_bmesh_restore_generic(SculptUndoNode *unode, Object *ob,
}
if (unode->type == SCULPT_UNDO_MASK) {
int totnode;
PBVHNode **nodes;
BKE_pbvh_search_gather(ss->pbvh, nullptr, nullptr, &nodes, &totnode);
Vector<PBVHNode *> nodes = blender::bke::pbvh::search_gather(ss->pbvh, nullptr, nullptr);
TaskParallelSettings settings;
BKE_pbvh_parallel_range_settings(&settings, true, totnode);
BLI_task_parallel_range(
0, totnode, nodes, sculpt_undo_bmesh_restore_generic_task_cb, &settings);
if (nodes) {
MEM_freeN(nodes);
}
BKE_pbvh_parallel_range_settings(&settings, true, nodes.size());
BLI_task_parallel_range(0,
nodes.size(),
static_cast<void *>(nodes.data()),
sculpt_undo_bmesh_restore_generic_task_cb,
&settings);
}
else {
SCULPT_pbvh_clear(ob);
@@ -2153,16 +2149,11 @@ static void sculpt_undo_push_all_grids(Object *object)
return;
}
PBVHNode **nodes;
int totnodes;
BKE_pbvh_search_gather(ss->pbvh, nullptr, nullptr, &nodes, &totnodes);
for (int i = 0; i < totnodes; i++) {
SculptUndoNode *unode = SCULPT_undo_push_node(object, nodes[i], SCULPT_UNDO_COORDS);
Vector<PBVHNode *> nodes = blender::bke::pbvh::search_gather(ss->pbvh, nullptr, nullptr);
for (PBVHNode *node : nodes) {
SculptUndoNode *unode = SCULPT_undo_push_node(object, node, SCULPT_UNDO_COORDS);
unode->node = nullptr;
}
MEM_SAFE_FREE(nodes);
}
void ED_sculpt_undo_push_multires_mesh_begin(bContext *C, const char *str)