Page Menu
Home
Search
Configure Global Search
Log In
Paste
P1939
Masterwork From Distant Lands
Active
Public
Actions
Authored by
Dalai Felinto (dfelinto)
on Feb 2 2021, 6:08 PM.
Edit Paste
Archive Paste
View Raw File
Subscribe
Mute Notifications
Award Token
Tags
None
Subscribers
None
commit f68493f5bee352d4a7feb90c2488a264607c84ac
Author: Joseph Eagar <joeedh@gmail.com>
Date: Mon Oct 19 04:10:34 2020 -0700
Little design study for new API to replace various pbvh/sculpt
iterators (uncomment PROXY_ADVANCED in BKE_pbvh to enable):
+ Same idea as existing pbvh proxies.
+ Based on "struct of arrays" approach.
+ New ProxyVeryArray structure holds all the coordinates,
normals, indices, neighbor references, color, mask, etc
data--basically everything in PBVHVertIter and SculptNeightborIter.
+ Only the desired data is stored. Client code can pass a mask
stating which data layers it wants; e.g. normals, coordiantes, etc.
There's a lot of advantages to this approach: simpler and more
maintainable code, possibility of SSE/opencl/cuda vectorization down
the line, etc.
More importantly for this branch, it should be a great profiling tool.
No more trying to figure out which bit of API cruft is causing the CPU
cache to go haywire. I can eliminate a lot of performance bugs and
concentrate on the ones related to DynTopo.
diff --git a/source/blender/blenkernel/BKE_pbvh.h b/source/blender/blenkernel/BKE_pbvh.h
index 73718ba33bf..3cdbad8885e 100644
--- a/source/blender/blenkernel/BKE_pbvh.h
+++ b/source/blender/blenkernel/BKE_pbvh.h
@@ -58,6 +58,77 @@ struct TaskParallelTLS;
typedef struct PBVH PBVH;
typedef struct PBVHNode PBVHNode;
+#define PROXY_ADVANCED
+
+// experimental performance test of "data-based programming" approach
+#ifdef PROXY_ADVANCED
+typedef struct ProxyKey {
+ int node;
+ int pindex;
+} ProxyKey;
+
+# define MAX_PROXY_NEIGHBORS 12
+
+typedef struct ProxyVertArray {
+ float **ownerco;
+ short **ownerno;
+ float (*co)[3];
+ float (*fno)[3];
+ short (*no)[3];
+ float *mask, **ownermask;
+ int *index;
+ float **ownercolor, (*color)[4];
+
+ ProxyKey (*neighbors)[MAX_PROXY_NEIGHBORS];
+
+ int size;
+ int datamask;
+
+ GHash *indexmap;
+} ProxyVertArray;
+
+typedef enum {
+ PV_OWNERCO = 1,
+ PV_OWNERNO = 2,
+ PV_CO = 4,
+ PV_NO = 8,
+ PV_MASK = 16,
+ PV_OWNERMASK = 32,
+ PV_INDEX = 64,
+ PV_OWNERCOLOR = 128,
+ PV_COLOR = 256,
+ PV_NEIGHBORS = 512
+} ProxyVertField;
+
+typedef struct ProxyVertUpdateRec {
+ float *co, *no, *mask, *color;
+ int index, newindex;
+} ProxyVertUpdateRec;
+
+# define PBVH_PROXY_DEFAULT CO | INDEX | MASK
+
+struct SculptSession;
+
+void BKE_pbvh_ensure_proxyarrays(struct SculptSession *ss, PBVH *pbvh, int mask);
+void BKE_pbvh_load_proxyarrays(PBVH *pbvh, PBVHNode **nodes, int totnode, int mask);
+
+void BKE_pbvh_ensure_proxyarray(
+ struct SculptSession *ss,
+ struct PBVH *pbvh,
+ struct PBVHNode *node,
+ int mask,
+ struct GHash
+ *vert_node_map, // vert_node_map maps vertex SculptIdxs to PBVHNode indices; optional
+ bool check_indexmap,
+ bool force_update);
+void BKE_pbvh_gather_proxyarray(PBVH *pbvh, PBVHNode **nodes, int totnode);
+
+void BKE_pbvh_free_proxyarray(struct PBVH *pbvh, struct PBVHNode *node);
+void BKE_pbvh_update_proxyvert(struct PBVH *pbvh, struct PBVHNode *node, ProxyVertUpdateRec *rec);
+ProxyVertArray *BKE_pbvh_get_proxyarrays(struct PBVH *pbvh, struct PBVHNode *node);
+
+#endif
+
typedef struct {
float (*co)[3];
} PBVHProxyNode;
@@ -107,12 +178,16 @@ void TMElemSet_remove(TMElemSet *ts, void *elem, bool ignoreExist);
bool TMElemSet_has(TMElemSet *ts, void *elem);
#define TMS_ITER(v, ts) \
-{int _i1; for (_i1=0; _i1<ts->cur; _i1++) {\
- if (!ts->elems[_i1])\
- continue;\
- v = ts->elems[_i1];
-
-#define TMS_ITER_END }}
+ { \
+ int _i1; \
+ for (_i1 = 0; _i1 < ts->cur; _i1++) { \
+ if (!ts->elems[_i1]) \
+ continue; \
+ v = ts->elems[_i1];
+
+#define TMS_ITER_END \
+ } \
+ }
void BKE_pbvh_set_frustum_planes(PBVH *pbvh, PBVHFrustumPlanes *planes);
void BKE_pbvh_get_frustum_planes(PBVH *pbvh, PBVHFrustumPlanes *planes);
@@ -155,14 +230,14 @@ void BKE_pbvh_build_bmesh(PBVH *pbvh,
const int cd_vert_node_offset,
const int cd_face_node_offset);
void BKE_pbvh_build_trimesh(PBVH *bvh,
- struct TM_TriMesh *bm,
- bool smooth_shading,
- struct TriMeshLog *log,
- const int cd_vert_node_offset,
- const int cd_face_node_offset);
+ struct TM_TriMesh *bm,
+ bool smooth_shading,
+ struct TriMeshLog *log,
+ const int cd_vert_node_offset,
+ const int cd_face_node_offset);
void BKE_pbvh_free(PBVH *bvh);
-//void BKE_pbvh_free_layer_disp(PBVH *bvh);
+// void BKE_pbvh_free_layer_disp(PBVH *bvh);
/* Hierarchical Search in the BVH, two methods:
* - for each hit calling a callback
@@ -207,10 +282,10 @@ bool BKE_pbvh_bmesh_node_raycast_detail(PBVHNode *node,
float *depth,
float *r_edge_length);
bool BKE_pbvh_trimesh_node_raycast_detail(PBVHNode *node,
- const float ray_start[3],
- struct IsectRayPrecalc *isect_precalc,
- float *depth,
- float *r_edge_length);
+ const float ray_start[3],
+ struct IsectRayPrecalc *isect_precalc,
+ float *depth,
+ float *r_edge_length);
/* for orthographic cameras, project the far away ray segment points to the root node so
* we can have better precision. */
@@ -248,12 +323,7 @@ void BKE_pbvh_draw_debug_cb(
void *user_data);
/* PBVH Access */
-typedef enum {
- PBVH_FACES,
- PBVH_GRIDS,
- PBVH_BMESH,
- PBVH_TRIMESH
-} PBVHType;
+typedef enum { PBVH_FACES, PBVH_GRIDS, PBVH_BMESH, PBVH_TRIMESH } PBVHType;
PBVHType BKE_pbvh_type(const PBVH *pbvh);
bool BKE_pbvh_has_faces(const PBVH *pbvh);
@@ -297,12 +367,13 @@ bool BKE_pbvh_bmesh_update_topology(PBVH *pbvh,
const bool use_projected);
bool BKE_pbvh_trimesh_update_topology(PBVH *bvh,
- PBVHTopologyUpdateMode mode,
- const float center[3],
- const float view_normal[3],
- float radius,
- const bool use_frontface,
- const bool use_projected, int sym_axis);
+ PBVHTopologyUpdateMode mode,
+ const float center[3],
+ const float view_normal[3],
+ float radius,
+ const bool use_frontface,
+ const bool use_projected,
+ int sym_axis);
/* Node Access */
void BKE_pbvh_node_mark_update(PBVHNode *node);
@@ -503,30 +574,32 @@ void pbvh_vertex_iter_init(PBVH *pbvh, PBVHNode *node, PBVHVertexIter *vi, int m
} \
} \
else if (vi.tm_vdata) { \
- TMVert *tv = NULL;\
- while (!tv) {\
- if (!vi.tm_cur_set->elems || vi.ti >= vi.tm_cur_set->cur) {\
- if (vi.tm_cur_set != vi.tm_other_verts) {\
- vi.tm_cur_set = vi.tm_other_verts;\
- vi.ti = 0;\
- if (!vi.tm_cur_set->elems || vi.ti >= vi.tm_other_verts->cur) {\
- break;\
- }\
- } else {\
- break;\
- }\
- } else {\
- tv = vi.tm_cur_set->elems[vi.ti++];\
- if (tv && BLI_safepool_elem_is_dead(tv)) {\
- printf("dead vert: %p\n", tv);\
- tv = NULL;\
- }\
- }\
- }\
- if (!tv) {\
- continue;\
- }\
- vi.tm_vert = tv;\
+ TMVert *tv = NULL; \
+ while (!tv) { \
+ if (!vi.tm_cur_set->elems || vi.ti >= vi.tm_cur_set->cur) { \
+ if (vi.tm_cur_set != vi.tm_other_verts) { \
+ vi.tm_cur_set = vi.tm_other_verts; \
+ vi.ti = 0; \
+ if (!vi.tm_cur_set->elems || vi.ti >= vi.tm_other_verts->cur) { \
+ break; \
+ } \
+ } \
+ else { \
+ break; \
+ } \
+ } \
+ else { \
+ tv = vi.tm_cur_set->elems[vi.ti++]; \
+ if (tv && BLI_safepool_elem_is_dead(tv)) { \
+ printf("dead vert: %p\n", tv); \
+ tv = NULL; \
+ } \
+ } \
+ } \
+ if (!tv) { \
+ continue; \
+ } \
+ vi.tm_vert = tv; \
vi.visible = !TM_elem_flag_test_bool(vi.tm_vert, TM_ELEM_HIDDEN); \
if (mode == PBVH_ITER_UNIQUE && !vi.visible) { \
continue; \
@@ -535,7 +608,7 @@ void pbvh_vertex_iter_init(PBVH *pbvh, PBVHNode *node, PBVHVertexIter *vi, int m
vi.fno = vi.tm_vert->no; \
vi.index = (SculptIdx)vi.tm_vert; \
vi.mask = TM_ELEM_CD_GET_VOID_P(vi.tm_vert, vi.cd_vert_mask_offset); \
- }\
+ } \
else { \
if (!BLI_gsetIterator_done(&vi.bm_unique_verts)) { \
vi.bm_vert = BLI_gsetIterator_getKey(&vi.bm_unique_verts); \
diff --git a/source/blender/blenkernel/intern/pbvh.c b/source/blender/blenkernel/intern/pbvh.c
index 59320ca0d49..773565b4b24 100644
--- a/source/blender/blenkernel/intern/pbvh.c
+++ b/source/blender/blenkernel/intern/pbvh.c
@@ -2451,7 +2451,7 @@ bool BKE_pbvh_node_raycast(PBVH *pbvh,
face_normal);
break;
case PBVH_TRIMESH:
- //TM_mesh_elem_index_ensure(pbvh->tm, TM_VERTEX);
+ // TM_mesh_elem_index_ensure(pbvh->tm, TM_VERTEX);
hit = pbvh_trimesh_node_raycast(node,
ray_start,
ray_normal,
@@ -3003,16 +3003,18 @@ PBVHProxyNode *BKE_pbvh_node_add_proxy(PBVH *pbvh, PBVHNode *node)
return node->proxies + index;
}
-void BKE_pbvh_node_free_proxies(PBVHNode *node)
+void BKE_pbvh_node_free_proxies(PBVH *pbvh, PBVHNode *node)
{
for (int p = 0; p < node->proxy_count; p++) {
MEM_freeN(node->proxies[p].co);
node->proxies[p].co = NULL;
}
- MEM_freeN(node->proxies);
- node->proxies = NULL;
+ if (node->proxies) {
+ MEM_freeN(node->proxies);
+ }
+ node->proxies = NULL;
node->proxy_count = 0;
}
@@ -3218,3 +3220,378 @@ void BKE_pbvh_respect_hide_set(PBVH *pbvh, bool respect_hide)
{
pbvh->respect_hide = respect_hide;
}
+
+#ifdef PROXY_ADVANCED
+// TODO: if this really works, make sure to pull the neighbor iterator out of sculpt.c and put it
+// here
+/* clang-format off */
+# include "BKE_context.h"
+# include "DNA_object_types.h"
+# include "DNA_scene_types.h"
+# include "../../editors/sculpt_paint/sculpt_intern.h"
+/* clang-format on */
+
+int checkalloc(void **data, int esize, int oldsize, int newsize, int emask, int umask)
+{
+ if (!*data && (emask & umask)) {
+ *data = MEM_callocN(newsize * esize, "pbvh proxy vert arrays");
+ return emask;
+ }
+ // update channel if it already was allocated once, or is requested by umask
+ else if (newsize != oldsize && (*data || (emask & umask))) {
+ *data = MEM_reallocN(data, newsize * esize);
+ return emask;
+ }
+
+ return 0;
+}
+
+void BKE_pbvh_ensure_proxyarray_indexmap(PBVH *pbvh, PBVHNode *node, GHash *vert_node_map)
+{
+ ProxyVertArray *p = &node->proxyverts;
+
+ int totvert = 0;
+ BKE_pbvh_node_num_verts(pbvh, node, &totvert, NULL);
+
+ bool update = !p->indexmap || p->size != totvert;
+
+ if (!update) {
+ return;
+ }
+
+ if (p->indexmap) {
+ BLI_ghash_free(p->indexmap, NULL, NULL);
+ }
+
+ GHash *gs = p->indexmap = BLI_ghash_ptr_new("BKE_pbvh_ensure_proxyarray_indexmap");
+
+ PBVHVertexIter vd;
+
+ int i = 0;
+ BKE_pbvh_vertex_iter_begin(pbvh, node, vd, PBVH_ITER_UNIQUE)
+ {
+ BLI_ghash_insert(gs, (void *)vd.index, (void *)i);
+ i++;
+ }
+ BKE_pbvh_vertex_iter_end;
+}
+
+bool pbvh_proxyarray_needs_update(PBVH *pbvh, PBVHNode *node, int mask)
+{
+ ProxyVertArray *p = &node->proxyverts;
+ int totvert = 0;
+
+ BKE_pbvh_node_num_verts(pbvh, node, &totvert, NULL);
+
+ bool bad = p->size != totvert || !p->neighbors;
+ bad = bad || (p->datamask & mask) != mask;
+
+ bad = bad && totvert > 0;
+
+ return bad;
+}
+
+GHash *pbvh_build_vert_node_map(PBVH *pbvh, int mask)
+{
+ GHash *vert_node_map = BLI_ghash_ptr_new("BKE_pbvh_ensure_proxyarrays");
+
+ for (int i = 0; i < pbvh->totnode; i++) {
+ PBVHVertexIter vd;
+ PBVHNode *node = pbvh->nodes + i;
+
+ BKE_pbvh_vertex_iter_begin(pbvh, node, vd, PBVH_ITER_UNIQUE)
+ {
+ BLI_ghash_insert(vert_node_map, (void *)vd.index, (void *)i);
+ }
+ BKE_pbvh_vertex_iter_end;
+ }
+
+ return vert_node_map;
+}
+
+void BKE_pbvh_ensure_proxyarrays(SculptSession *ss, PBVH *pbvh, int mask)
+{
+
+ bool update = false;
+
+ for (int i = 0; i < pbvh->totnode; i++) {
+ if (pbvh_proxyarray_needs_update(pbvh, pbvh->nodes + i, mask)) {
+ update = true;
+ break;
+ }
+ }
+
+ if (!update) {
+ return;
+ }
+
+ GHash *vert_node_map = pbvh_build_vert_node_map(pbvh, mask);
+
+ for (int i = 0; i < pbvh->totnode; i++) {
+ BKE_pbvh_ensure_proxyarray_indexmap(pbvh, pbvh->nodes + i, vert_node_map);
+ }
+
+ for (int i = 0; i < pbvh->totnode; i++) {
+ BKE_pbvh_ensure_proxyarray(ss, pbvh, pbvh->nodes + i, mask, vert_node_map, false, false);
+ }
+
+ if (vert_node_map) {
+ BLI_ghash_free(vert_node_map, NULL, NULL);
+ }
+}
+
+void BKE_pbvh_ensure_proxyarray(SculptSession *ss,
+ PBVH *pbvh,
+ PBVHNode *node,
+ int mask,
+ GHash *vert_node_map,
+ bool check_indexmap,
+ bool force_update)
+{
+ ProxyVertArray *p = &node->proxyverts;
+
+ if (check_indexmap) {
+ BKE_pbvh_ensure_proxyarray_indexmap(pbvh, node, vert_node_map);
+ }
+
+ GHash *gs = p->indexmap;
+
+ int totvert = 0;
+ BKE_pbvh_node_num_verts(pbvh, node, &totvert, NULL);
+
+ if (!totvert) {
+ return;
+ }
+
+ int updatemask = 0;
+
+# define UPDATETEST(name, emask, esize) \
+ if (mask & emask) { \
+ updatemask |= checkalloc((void **)&p->name, esize, p->size, totvert, emask, mask); \
+ }
+
+ UPDATETEST(ownerco, PV_OWNERCO, sizeof(void *))
+ UPDATETEST(ownerno, PV_OWNERNO, sizeof(void *))
+ UPDATETEST(ownermask, PV_OWNERMASK, sizeof(void *))
+ UPDATETEST(ownercolor, PV_OWNERCOLOR, sizeof(void *))
+ UPDATETEST(co, PV_CO, sizeof(float) * 3)
+ UPDATETEST(no, PV_NO, sizeof(short) * 3)
+ UPDATETEST(fno, PV_NO, sizeof(float) * 3)
+ UPDATETEST(mask, PV_MASK, sizeof(float))
+ UPDATETEST(color, PV_COLOR, sizeof(float) * 4)
+ UPDATETEST(index, PV_INDEX, sizeof(int))
+ UPDATETEST(neighbors, PV_NEIGHBORS, sizeof(ProxyKey) * MAX_PROXY_NEIGHBORS)
+
+ p->size = totvert;
+
+ if (force_update) {
+ updatemask |= mask;
+ }
+
+ if (!updatemask) {
+ return;
+ }
+
+ p->datamask |= mask;
+
+ PBVHVertexIter vd;
+
+ int i = 0;
+ BKE_pbvh_vertex_iter_begin(pbvh, node, vd, PBVH_ITER_UNIQUE)
+ {
+ BLI_ghash_insert(gs, (void *)vd.index, (void *)i);
+ i++;
+ }
+ BKE_pbvh_vertex_iter_end;
+
+ i = 0;
+ BKE_pbvh_vertex_iter_begin(pbvh, node, vd, PBVH_ITER_UNIQUE)
+ {
+ if (updatemask & PV_OWNERCO) {
+ p->ownerco[i] = vd.co;
+ }
+ if (updatemask & PV_INDEX) {
+ p->index[i] = vd.index;
+ }
+ if (updatemask & PV_OWNERNO) {
+ p->ownerno[i] = vd.no;
+ }
+ if (updatemask & PV_NO) {
+ copy_v3_v3_short(p->no[i], vd.no);
+ normal_short_to_float_v3(p->fno[i], vd.no);
+ }
+ if (updatemask & PV_CO) {
+ copy_v3_v3(p->co[i], vd.co);
+ }
+ if (updatemask & PV_OWNERMASK) {
+ p->ownermask[i] = vd.mask;
+ }
+ if (updatemask & PV_MASK) {
+ p->mask[i] = vd.mask ? *vd.mask : 0.0f;
+ }
+ if (updatemask & PV_COLOR) {
+ if (vd.vcol) {
+ copy_v4_v4(p->color[i], vd.vcol->color);
+ }
+ }
+
+ if (updatemask & PV_NEIGHBORS) {
+ int j = 0;
+ SculptVertexNeighborIter ni;
+
+ SCULPT_VERTEX_NEIGHBORS_ITER_BEGIN (ss, vd.index, ni) {
+ if (j >= MAX_PROXY_NEIGHBORS - 1) {
+ break;
+ }
+
+ ProxyKey key;
+
+ int *pindex = (int *)BLI_ghash_lookup_p(gs, (void *)ni.index);
+
+ if (!pindex) {
+ if (vert_node_map) {
+ int *nindex = BLI_ghash_lookup_p(vert_node_map, (void *)ni.index);
+
+ if (!nindex) {
+ continue;
+ }
+
+ PBVHNode *node2 = pbvh->nodes + *nindex;
+ if (node2->proxyverts.indexmap) {
+ pindex = (int *)BLI_ghash_lookup_p(node2->proxyverts.indexmap, (void *)ni.index);
+ }
+
+ if (!pindex) {
+ continue;
+ }
+
+ key.node = (int)(node2 - pbvh->nodes);
+ key.pindex = *pindex;
+ }
+ else {
+ continue;
+ }
+ }
+ else {
+ key.node = (int)(node - pbvh->nodes);
+ key.pindex = *pindex;
+ }
+
+ p->neighbors[i][j++] = key;
+ }
+ SCULPT_VERTEX_NEIGHBORS_ITER_END(ni);
+
+ p->neighbors[i][j].node = -1;
+ }
+
+ i++;
+ }
+ BKE_pbvh_vertex_iter_end;
+}
+
+typedef struct GatherProxyThread {
+ PBVHNode **nodes;
+ PBVH *pbvh;
+ int mask;
+} GatherProxyThread;
+
+static void pbvh_load_proxyarray_exec(void *__restrict userdata,
+ const int n,
+ const TaskParallelTLS *__restrict tls)
+{
+ GatherProxyThread *data = (GatherProxyThread *)userdata;
+ PBVHNode *node = data->nodes[n];
+ PBVHVertexIter vd;
+ ProxyVertArray *p = &node->proxyverts;
+ int i = 0;
+
+ int mask = p->datamask;
+
+ BKE_pbvh_ensure_proxyarray(NULL, data->pbvh, node, data->mask, NULL, false, true);
+}
+
+void BKE_pbvh_load_proxyarrays(PBVH *pbvh, PBVHNode **nodes, int totnode, int mask)
+{
+ GatherProxyThread data = {.nodes = nodes, .pbvh = pbvh, .mask = mask};
+
+ mask = mask & ~PV_NEIGHBORS; // don't update neighbors in threaded code?
+
+ TaskParallelSettings settings;
+ BKE_pbvh_parallel_range_settings(&settings, true, totnode);
+ BLI_task_parallel_range(0, totnode, &data, pbvh_load_proxyarray_exec, &settings);
+}
+
+static void pbvh_gather_proxyarray_exec(void *__restrict userdata,
+ const int n,
+ const TaskParallelTLS *__restrict tls)
+{
+ GatherProxyThread *data = (GatherProxyThread *)userdata;
+ PBVHNode *node = data->nodes[n];
+ PBVHVertexIter vd;
+ ProxyVertArray *p = &node->proxyverts;
+ int i = 0;
+
+ int mask = p->datamask;
+
+ BKE_pbvh_vertex_iter_begin(data->pbvh, node, vd, PBVH_ITER_UNIQUE)
+ {
+ if (mask & PV_CO) {
+ copy_v3_v3(vd.co, p->co[i]);
+ }
+
+ if (vd.mask && (mask & PV_MASK)) {
+ *vd.mask = p->mask[i];
+ }
+
+ i++;
+ }
+ BKE_pbvh_vertex_iter_end;
+}
+
+void BKE_pbvh_gather_proxyarray(PBVH *pbvh, PBVHNode **nodes, int totnode)
+{
+ GatherProxyThread data = {.nodes = nodes, .pbvh = pbvh};
+
+ TaskParallelSettings settings;
+ BKE_pbvh_parallel_range_settings(&settings, true, totnode);
+ BLI_task_parallel_range(0, totnode, &data, pbvh_gather_proxyarray_exec, &settings);
+}
+
+void BKE_pbvh_free_proxyarray(PBVH *pbvh, PBVHNode *node)
+{
+ ProxyVertArray *p = &node->proxyverts;
+
+ if (p->co)
+ MEM_freeN(p->co);
+ if (p->no)
+ MEM_freeN(p->no);
+ if (p->index)
+ MEM_freeN(p->index);
+ if (p->mask)
+ MEM_freeN(p->mask);
+ if (p->ownerco)
+ MEM_freeN(p->ownerco);
+ if (p->ownerno)
+ MEM_freeN(p->ownerno);
+ if (p->ownermask)
+ MEM_freeN(p->ownermask);
+ if (p->ownercolor)
+ MEM_freeN(p->ownercolor);
+ if (p->color)
+ MEM_freeN(p->color);
+ if (p->neighbors)
+ MEM_freeN(p->neighbors);
+
+ memset(p, 0, sizeof(*p));
+}
+
+void BKE_pbvh_update_proxyvert(PBVH *pbvh, PBVHNode *node, ProxyVertUpdateRec *rec)
+{
+}
+
+ProxyVertArray *BKE_pbvh_get_proxyarrays(PBVH *pbvh, PBVHNode *node)
+{
+ return &node->proxyverts;
+}
+
+#endif
diff --git a/source/blender/blenkernel/intern/pbvh_intern.h b/source/blender/blenkernel/intern/pbvh_intern.h
index d78453b09f9..bc11a8d19d6 100644
--- a/source/blender/blenkernel/intern/pbvh_intern.h
+++ b/source/blender/blenkernel/intern/pbvh_intern.h
@@ -111,6 +111,7 @@ struct PBVHNode {
/* trimesh */
GSet *tm_faces;
+
TMElemSet *tm_unique_verts;
TMElemSet *tm_other_verts;
float (*tm_orco)[3];
@@ -119,9 +120,11 @@ struct PBVHNode {
int tm_tot_orco;
int tm_subtree_tottri;
-
+
/* Used to store the brush color during a stroke and composite it over the original color */
PBVHColorBufferNode color_buffer;
+
+ ProxyVertArray proxyverts;
};
typedef enum {
diff --git a/source/blender/editors/sculpt_paint/sculpt.c b/source/blender/editors/sculpt_paint/sculpt.c
index 49a3f04f71c..62e327d97ae 100644
--- a/source/blender/editors/sculpt_paint/sculpt.c
+++ b/source/blender/editors/sculpt_paint/sculpt.c
@@ -8679,6 +8679,7 @@ void SCULPT_geometry_preview_lines_update(bContext *C, SculptSession *ss, float
ss->preview_vert_index_count = totpoints;
}
+
static int vertex_to_loop_colors_exec(bContext *C, wmOperator *UNUSED(op))
{
Object *ob = CTX_data_active_object(C);
diff --git a/source/blender/editors/sculpt_paint/sculpt_intern.h b/source/blender/editors/sculpt_paint/sculpt_intern.h
index 31e7d82d429..3da89eadd75 100644
--- a/source/blender/editors/sculpt_paint/sculpt_intern.h
+++ b/source/blender/editors/sculpt_paint/sculpt_intern.h
@@ -124,6 +124,7 @@ typedef struct SculptVertexNeighborIter {
int size;
int capacity;
SculptIdx neighbors_fixed[SCULPT_VERTEX_NEIGHBOR_FIXED_CAPACITY];
+ int neighbors_nindex[SCULPT_VERTEX_NEIGHBOR_FIXED_CAPACITY];
/* Internal iterator. */
int num_duplicates;
diff --git a/source/blender/editors/sculpt_paint/sculpt_smooth.c b/source/blender/editors/sculpt_paint/sculpt_smooth.c
index 26f62aa917d..afa4507945a 100644
--- a/source/blender/editors/sculpt_paint/sculpt_smooth.c
+++ b/source/blender/editors/sculpt_paint/sculpt_smooth.c
@@ -60,6 +60,11 @@
#include "bmesh.h"
#include "trimesh.h"
+#ifdef PROXY_ADVANCED
+#include "BKE_DerivedMesh.h"
+#include "../../blenkernel/intern/pbvh_intern.h"
+#endif
+
#include <math.h>
#include <stdlib.h>
@@ -337,6 +342,80 @@ static void SCULPT_enhance_details_brush(Sculpt *sd,
BLI_task_parallel_range(0, totnode, &data, do_enhance_details_brush_task_cb_ex, &settings);
}
+
+#ifdef PROXY_ADVANCED
+static void do_smooth_brush_task_cb_ex(void *__restrict userdata,
+ const int n,
+ const TaskParallelTLS *__restrict tls)
+{
+ SculptThreadedTaskData *data = userdata;
+ SculptSession *ss = data->ob->sculpt;
+ Sculpt *sd = data->sd;
+ const Brush *brush = data->brush;
+ const bool smooth_mask = data->smooth_mask;
+ float bstrength = data->strength;
+
+ PBVHVertexIter vd;
+
+ CLAMP(bstrength, 0.0f, 1.0f);
+
+ SculptBrushTest test;
+ SculptBrushTestFn sculpt_brush_test_sq_fn = SCULPT_brush_test_init_with_falloff_shape(
+ ss, &test, data->brush->falloff_shape);
+
+ const int thread_id = BLI_task_parallel_thread_id(tls);
+
+ PBVHNode **nodes = data->nodes;
+ ProxyVertArray *p = &nodes[n]->proxyverts;
+
+ for (int i = 0; i < p->size; i++) {
+ float co[3] = {0.0f, 0.0f, 0.0f};
+ int ni = 0;
+
+# if 1
+ if (sculpt_brush_test_sq_fn(&test, p->co[i])) {
+ const float fade = bstrength * SCULPT_brush_strength_factor(
+ ss,
+ brush,
+ p->co[i],
+ sqrtf(test.dist),
+ p->no[i],
+ p->fno[i],
+ smooth_mask ? 0.0f : (p->mask ? p->mask[i] : 0.0f),
+ p->index[i],
+ thread_id);
+# else
+ if (1) {
+ const float fade = 1.0;
+# endif
+
+ while (ni < MAX_PROXY_NEIGHBORS && p->neighbors[i][ni].node >= 0) {
+ ProxyKey *key = p->neighbors[i] + ni;
+ PBVHNode *n2 = ss->pbvh->nodes + key->node;
+
+ // printf("%d %d %d %p\n", key->node, key->pindex, ss->pbvh->totnode, n2);
+
+ add_v3_v3(co, n2->proxyverts.co[key->pindex]);
+ ni++;
+ }
+
+ // printf("ni %d\n", ni);
+
+ if (ni > 2) {
+ mul_v3_fl(co, 1.0f / (float)ni);
+ }
+ else {
+ copy_v3_v3(co, p->co[i]);
+ }
+
+ // printf("%f %f %f ", co[0], co[1], co[2]);
+
+ interp_v3_v3v3(p->co[i], p->co[i], co, fade);
+ }
+ }
+}
+
+#else
static void do_smooth_brush_task_cb_ex(void *__restrict userdata,
const int n,
const TaskParallelTLS *__restrict tls)
@@ -391,6 +470,8 @@ static void do_smooth_brush_task_cb_ex(void *__restrict userdata,
}
BKE_pbvh_vertex_iter_end;
}
+#endif
+
void SCULPT_smooth(Sculpt *sd,
Object *ob,
@@ -421,8 +502,15 @@ void SCULPT_smooth(Sculpt *sd,
if (type != PBVH_TRIMESH) {
SCULPT_vertex_random_access_ensure(ss);
}
+
SCULPT_boundary_info_ensure(ob);
+#ifdef PROXY_ADVANCED
+ int datamask = PV_CO | PV_NEIGHBORS | PV_NO | PV_INDEX | PV_MASK;
+ BKE_pbvh_ensure_proxyarrays(ss, ss->pbvh, datamask);
+
+ BKE_pbvh_load_proxyarrays(ss->pbvh, nodes, totnode, PV_CO | PV_NO | PV_MASK);
+#endif
for (iteration = 0; iteration <= count; iteration++) {
const float strength = (iteration != count) ? 1.0f : last;
@@ -438,6 +526,10 @@ void SCULPT_smooth(Sculpt *sd,
TaskParallelSettings settings;
BKE_pbvh_parallel_range_settings(&settings, true, totnode);
BLI_task_parallel_range(0, totnode, &data, do_smooth_brush_task_cb_ex, &settings);
+
+#ifdef PROXY_ADVANCED
+ BKE_pbvh_gather_proxyarray(ss->pbvh, nodes, totnode);
+#endif
}
}
Event Timeline
Dalai Felinto (dfelinto)
edited the content of this paste.
(Show Details)
Feb 2 2021, 6:08 PM
Dalai Felinto (dfelinto)
changed the title of this paste from untitled to
Masterwork From Distant Lands
.
Dalai Felinto (dfelinto)
mentioned this in
T84864: Multires design validation
.
Feb 2 2021, 6:08 PM
Log In to Comment