Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPablo Dobarro <pablodp606@gmail.com>2020-03-05 16:53:23 +0300
committerPablo Dobarro <pablodp606@gmail.com>2020-03-05 23:07:20 +0300
commit38d6533f212bf9001cd5f70ed8757eccb9b39dad (patch)
tree239533648a8f075e2d4697ff3b44ccad5deb766c /source/blender/blenkernel
parente56471bcd3a5f0a9bdc369cc4ca9ceb061e321dd (diff)
Sculpt Face Sets
Face Sets are the new system to control the visibility state of the mesh in sculpt and paint modes. They are designed to work in modes where brushes are the primary way of interaction and they provide much more control when working with meshes with complex shapes and overlapping surfaces. This initial commit includes: - Sculpt Face Sets data structures and PBVH rendering. - Face Set overlay and opacity controls. - Sculpt Undo support. - Remesher reprojection support. The visibility state of the mesh is also preserved when remeshing. - Automasking and Mesh filter support. - Mask expand operator mode to expand Face Sets (Shift + W) and flood fill areas by connectivity (press Ctrl while expanding). - Sculpt Mode Face Sets and Visibility API. - Sculpt Face Sets creation and visibility management operators. - Operator to randomize the Face Sets colors. - Draw Face Sets brush tool to create and edit the Face Sets. Drawing on the mesh creates a new Face Set. Pressing Ctrl before drawing modifies the Face Set under the brush at the beginning of the stroke. - Updated keymap and menu to work with Face Sets from Sculpt Mode (H to toggle visibility, Alt + H to show all, Shit + H to hide). - Pie menu on the W key with Face common Sets operations. Know limitations: - Multires support. The Face Sets and Visibility API needs to be implemented for Multires. Reviewed By: jbakker, #user_interface, Severin Differential Revision: https://developer.blender.org/D6070
Diffstat (limited to 'source/blender/blenkernel')
-rw-r--r--source/blender/blenkernel/BKE_mesh_remesh_voxel.h1
-rw-r--r--source/blender/blenkernel/BKE_paint.h6
-rw-r--r--source/blender/blenkernel/BKE_pbvh.h16
-rw-r--r--source/blender/blenkernel/intern/brush.c7
-rw-r--r--source/blender/blenkernel/intern/customdata.c17
-rw-r--r--source/blender/blenkernel/intern/mesh.c8
-rw-r--r--source/blender/blenkernel/intern/mesh_remesh_voxel.c49
-rw-r--r--source/blender/blenkernel/intern/paint.c16
-rw-r--r--source/blender/blenkernel/intern/pbvh.c106
-rw-r--r--source/blender/blenkernel/intern/pbvh_intern.h4
10 files changed, 208 insertions, 22 deletions
diff --git a/source/blender/blenkernel/BKE_mesh_remesh_voxel.h b/source/blender/blenkernel/BKE_mesh_remesh_voxel.h
index 794b8dca4bc..b63f9a9814b 100644
--- a/source/blender/blenkernel/BKE_mesh_remesh_voxel.h
+++ b/source/blender/blenkernel/BKE_mesh_remesh_voxel.h
@@ -60,6 +60,7 @@ struct Mesh *BKE_mesh_remesh_quadriflow_to_mesh_nomain(struct Mesh *mesh,
/* Data reprojection functions */
void BKE_mesh_remesh_reproject_paint_mask(struct Mesh *target, struct Mesh *source);
+void BKE_remesh_reproject_sculpt_face_sets(struct Mesh *target, struct Mesh *source);
#ifdef __cplusplus
}
diff --git a/source/blender/blenkernel/BKE_paint.h b/source/blender/blenkernel/BKE_paint.h
index 016012d7288..ceb48783e20 100644
--- a/source/blender/blenkernel/BKE_paint.h
+++ b/source/blender/blenkernel/BKE_paint.h
@@ -218,6 +218,8 @@ void BKE_paint_toolslots_brush_update(struct Paint *paint);
void BKE_paint_toolslots_brush_validate(struct Main *bmain, struct Paint *paint);
struct Brush *BKE_paint_toolslots_brush_get(struct Paint *paint, int slot_index);
+#define SCULPT_FACE_SET_NONE 0
+
/* Used for both vertex color and weight paint */
struct SculptVertexPaintGeomMap {
int *vert_map_mem;
@@ -290,6 +292,9 @@ typedef struct SculptSession {
struct MeshElemMap *pmap;
int *pmap_mem;
+ /* Mesh Face Sets */
+ int *face_sets;
+
/* BMesh for dynamic topology sculpting */
struct BMesh *bm;
int cd_vert_node_offset;
@@ -304,6 +309,7 @@ typedef struct SculptSession {
/* PBVH acceleration structure */
struct PBVH *pbvh;
bool show_mask;
+ bool show_face_sets;
/* Painting on deformed mesh */
bool deform_modifiers_active; /* object is deformed with some modifiers */
diff --git a/source/blender/blenkernel/BKE_pbvh.h b/source/blender/blenkernel/BKE_pbvh.h
index 3971b248a2e..6097fab814f 100644
--- a/source/blender/blenkernel/BKE_pbvh.h
+++ b/source/blender/blenkernel/BKE_pbvh.h
@@ -102,6 +102,7 @@ void BKE_pbvh_build_mesh(PBVH *bvh,
int totvert,
struct CustomData *vdata,
struct CustomData *ldata,
+ struct CustomData *pdata,
const struct MLoopTri *looptri,
int looptri_num);
void BKE_pbvh_build_grids(PBVH *bvh,
@@ -244,10 +245,10 @@ bool BKE_pbvh_bmesh_update_topology(PBVH *bvh,
void BKE_pbvh_node_mark_update(PBVHNode *node);
void BKE_pbvh_node_mark_update_mask(PBVHNode *node);
+void BKE_pbvh_node_mark_update_visibility(PBVHNode *node);
void BKE_pbvh_node_mark_rebuild_draw(PBVHNode *node);
void BKE_pbvh_node_mark_redraw(PBVHNode *node);
void BKE_pbvh_node_mark_normals_update(PBVHNode *node);
-void BKE_pbvh_node_mark_visibility_update(PBVHNode *node);
void BKE_pbvh_node_mark_topology_update(PBVHNode *node);
void BKE_pbvh_node_fully_hidden_set(PBVHNode *node, int fully_hidden);
void BKE_pbvh_node_fully_masked_set(PBVHNode *node, int fully_masked);
@@ -298,6 +299,8 @@ void BKE_pbvh_grids_update(PBVH *bvh,
struct DMFlagMat *flagmats,
unsigned int **grid_hidden);
+void BKE_pbvh_face_sets_color_seed_set(PBVH *bvh, int seed);
+
/* Layer displacement */
/* Get the node's displacement layer, creating it if necessary */
@@ -361,6 +364,7 @@ typedef struct PBVHVertexIter {
short *no;
float *fno;
float *mask;
+ bool visible;
} PBVHVertexIter;
void pbvh_vertex_iter_init(PBVH *bvh, PBVHNode *node, PBVHVertexIter *vi, int mode);
@@ -390,6 +394,7 @@ void pbvh_vertex_iter_init(PBVH *bvh, PBVHNode *node, PBVHVertexIter *vi, int mo
vi.mask = vi.key.has_mask ? CCG_elem_mask(&vi.key, vi.grid) : NULL; \
vi.grid = CCG_elem_next(&vi.key, vi.grid); \
vi.index++; \
+ vi.visible = true; \
if (vi.gh) { \
if (BLI_BITMAP_TEST(vi.gh, vi.gy * vi.gridsize + vi.gx)) \
continue; \
@@ -397,7 +402,8 @@ void pbvh_vertex_iter_init(PBVH *bvh, PBVHNode *node, PBVHVertexIter *vi, int mo
} \
else if (vi.mverts) { \
vi.mvert = &vi.mverts[vi.vert_indices[vi.gx]]; \
- if (mode == PBVH_ITER_UNIQUE && vi.mvert->flag & ME_HIDE) \
+ vi.visible = !(vi.mvert->flag & ME_HIDE); \
+ if (mode == PBVH_ITER_UNIQUE && !vi.visible) \
continue; \
vi.co = vi.mvert->co; \
vi.no = vi.mvert->no; \
@@ -414,7 +420,8 @@ void pbvh_vertex_iter_init(PBVH *bvh, PBVHNode *node, PBVHVertexIter *vi, int mo
vi.bm_vert = BLI_gsetIterator_getKey(&vi.bm_other_verts); \
BLI_gsetIterator_step(&vi.bm_other_verts); \
} \
- if (mode == PBVH_ITER_UNIQUE && BM_elem_flag_test(vi.bm_vert, BM_ELEM_HIDDEN)) \
+ vi.visible = !BM_elem_flag_test_bool(vi.bm_vert, BM_ELEM_HIDDEN); \
+ if (mode == PBVH_ITER_UNIQUE && !vi.visible) \
continue; \
vi.co = vi.bm_vert->co; \
vi.fno = vi.bm_vert->no; \
@@ -445,6 +452,9 @@ bool BKE_pbvh_node_vert_update_check_any(PBVH *bvh, PBVHNode *node);
bool pbvh_has_mask(PBVH *bvh);
void pbvh_show_mask_set(PBVH *bvh, bool show_mask);
+bool pbvh_has_face_sets(PBVH *bvh);
+void pbvh_show_face_sets_set(PBVH *bvh, bool show_face_sets);
+
/* Parallelization */
typedef void (*PBVHParallelRangeFunc)(void *__restrict userdata,
const int iter,
diff --git a/source/blender/blenkernel/intern/brush.c b/source/blender/blenkernel/intern/brush.c
index 8abad2d541d..a1725197a36 100644
--- a/source/blender/blenkernel/intern/brush.c
+++ b/source/blender/blenkernel/intern/brush.c
@@ -1010,6 +1010,12 @@ void BKE_brush_sculpt_reset(Brush *br)
br->flag &= ~BRUSH_SPACE;
br->flag &= ~BRUSH_SPACE_ATTEN;
break;
+ case SCULPT_TOOL_DRAW_FACE_SETS:
+ br->alpha = 0.5f;
+ br->flag &= ~BRUSH_ALPHA_PRESSURE;
+ br->flag &= ~BRUSH_SPACE;
+ br->flag &= ~BRUSH_SPACE_ATTEN;
+ break;
case SCULPT_TOOL_GRAB:
br->alpha = 0.4f;
br->size = 75;
@@ -1085,6 +1091,7 @@ void BKE_brush_sculpt_reset(Brush *br)
case SCULPT_TOOL_SIMPLIFY:
case SCULPT_TOOL_MASK:
+ case SCULPT_TOOL_DRAW_FACE_SETS:
br->add_col[0] = 0.750000;
br->add_col[1] = 0.750000;
br->add_col[2] = 0.750000;
diff --git a/source/blender/blenkernel/intern/customdata.c b/source/blender/blenkernel/intern/customdata.c
index 93db44ce60a..33707d3f18d 100644
--- a/source/blender/blenkernel/intern/customdata.c
+++ b/source/blender/blenkernel/intern/customdata.c
@@ -1621,6 +1621,8 @@ static const LayerTypeInfo LAYERTYPEINFO[CD_NUMTYPES] = {
{sizeof(short[4][3]), "", 0, NULL, NULL, NULL, NULL, layerSwap_flnor, NULL},
/* 41: CD_CUSTOMLOOPNORMAL */
{sizeof(short[2]), "vec2s", 1, NULL, NULL, NULL, NULL, NULL, NULL},
+ /* 42: CD_SCULPT_FACE_SETS */
+ {sizeof(int), "", 0, NULL, NULL, NULL, NULL, NULL, NULL},
};
static const char *LAYERTYPENAMES[CD_NUMTYPES] = {
@@ -1668,6 +1670,7 @@ static const char *LAYERTYPENAMES[CD_NUMTYPES] = {
/* 39-41 */ "CDMLoopTangent",
"CDTessLoopNormal",
"CDCustomLoopNormal",
+ "CDSculptFaceGroups",
};
const CustomData_MeshMasks CD_MASK_BAREMESH = {
@@ -1692,7 +1695,7 @@ const CustomData_MeshMasks CD_MASK_MESH = {
.lmask = (CD_MASK_MLOOP | CD_MASK_MDISPS | CD_MASK_MLOOPUV | CD_MASK_MLOOPCOL |
CD_MASK_CUSTOMLOOPNORMAL | CD_MASK_GRID_PAINT_MASK | CD_MASK_GENERIC_DATA),
.pmask = (CD_MASK_MPOLY | CD_MASK_RECAST | CD_MASK_FACEMAP | CD_MASK_FREESTYLE_FACE |
- CD_MASK_GENERIC_DATA),
+ CD_MASK_GENERIC_DATA | CD_MASK_SCULPT_FACE_SETS),
};
const CustomData_MeshMasks CD_MASK_EDITMESH = {
.vmask = (CD_MASK_MDEFORMVERT | CD_MASK_PAINT_MASK | CD_MASK_MVERT_SKIN | CD_MASK_SHAPEKEY |
@@ -1701,7 +1704,7 @@ const CustomData_MeshMasks CD_MASK_EDITMESH = {
.fmask = 0,
.lmask = (CD_MASK_MDISPS | CD_MASK_MLOOPUV | CD_MASK_MLOOPCOL | CD_MASK_CUSTOMLOOPNORMAL |
CD_MASK_GRID_PAINT_MASK | CD_MASK_GENERIC_DATA),
- .pmask = (CD_MASK_RECAST | CD_MASK_FACEMAP | CD_MASK_GENERIC_DATA),
+ .pmask = (CD_MASK_RECAST | CD_MASK_FACEMAP | CD_MASK_GENERIC_DATA | CD_MASK_SCULPT_FACE_SETS),
};
const CustomData_MeshMasks CD_MASK_DERIVEDMESH = {
.vmask = (CD_MASK_ORIGINDEX | CD_MASK_MDEFORMVERT | CD_MASK_SHAPEKEY | CD_MASK_MVERT_SKIN |
@@ -1712,7 +1715,7 @@ const CustomData_MeshMasks CD_MASK_DERIVEDMESH = {
CD_MASK_PREVIEW_MLOOPCOL | CD_MASK_ORIGSPACE_MLOOP |
CD_MASK_GENERIC_DATA), /* XXX MISSING CD_MASK_MLOOPTANGENT ? */
.pmask = (CD_MASK_ORIGINDEX | CD_MASK_RECAST | CD_MASK_FREESTYLE_FACE | CD_MASK_FACEMAP |
- CD_MASK_GENERIC_DATA),
+ CD_MASK_GENERIC_DATA | CD_MASK_SCULPT_FACE_SETS),
};
const CustomData_MeshMasks CD_MASK_BMESH = {
.vmask = (CD_MASK_MDEFORMVERT | CD_MASK_BWEIGHT | CD_MASK_MVERT_SKIN | CD_MASK_SHAPEKEY |
@@ -1721,7 +1724,8 @@ const CustomData_MeshMasks CD_MASK_BMESH = {
.fmask = 0,
.lmask = (CD_MASK_MDISPS | CD_MASK_MLOOPUV | CD_MASK_MLOOPCOL | CD_MASK_CUSTOMLOOPNORMAL |
CD_MASK_GRID_PAINT_MASK | CD_MASK_GENERIC_DATA),
- .pmask = (CD_MASK_RECAST | CD_MASK_FREESTYLE_FACE | CD_MASK_FACEMAP | CD_MASK_GENERIC_DATA),
+ .pmask = (CD_MASK_RECAST | CD_MASK_FREESTYLE_FACE | CD_MASK_FACEMAP | CD_MASK_GENERIC_DATA |
+ CD_MASK_SCULPT_FACE_SETS),
};
/**
* cover values copied by #BKE_mesh_loops_to_tessdata
@@ -1750,7 +1754,8 @@ const CustomData_MeshMasks CD_MASK_EVERYTHING = {
CD_MASK_MLOOPTANGENT | CD_MASK_PREVIEW_MLOOPCOL | CD_MASK_ORIGSPACE_MLOOP |
CD_MASK_GRID_PAINT_MASK | CD_MASK_GENERIC_DATA),
.pmask = (CD_MASK_MPOLY | CD_MASK_BM_ELEM_PYPTR | CD_MASK_ORIGINDEX | CD_MASK_NORMAL |
- CD_MASK_RECAST | CD_MASK_FACEMAP | CD_MASK_FREESTYLE_FACE | CD_MASK_GENERIC_DATA),
+ CD_MASK_RECAST | CD_MASK_FACEMAP | CD_MASK_FREESTYLE_FACE | CD_MASK_GENERIC_DATA |
+ CD_MASK_SCULPT_FACE_SETS),
};
static const LayerTypeInfo *layerType_getInfo(int type)
@@ -4221,7 +4226,7 @@ bool CustomData_verify_versions(struct CustomData *data, int index)
/* 0 structnum is used in writing code to tag layer types that should not be written. */
else if (typeInfo->structnum == 0 &&
/* XXX Not sure why those three are exception, maybe that should be fixed? */
- !ELEM(layer->type, CD_PAINT_MASK, CD_FACEMAP, CD_MTEXPOLY)) {
+ !ELEM(layer->type, CD_PAINT_MASK, CD_FACEMAP, CD_MTEXPOLY, CD_SCULPT_FACE_SETS)) {
keeplayer = false;
CLOG_WARN(&LOG, ".blend file read: removing a data layer that should not have been written");
}
diff --git a/source/blender/blenkernel/intern/mesh.c b/source/blender/blenkernel/intern/mesh.c
index 51f37254d8f..81ba48bd106 100644
--- a/source/blender/blenkernel/intern/mesh.c
+++ b/source/blender/blenkernel/intern/mesh.c
@@ -31,6 +31,8 @@
#include "BLI_utildefines.h"
#include "BLI_bitmap.h"
+#include "BLI_ghash.h"
+#include "BLI_hash.h"
#include "BLI_math.h"
#include "BLI_linklist.h"
#include "BLI_memarena.h"
@@ -51,6 +53,8 @@
#include "BKE_object.h"
#include "BKE_editmesh.h"
+#include "PIL_time.h"
+
#include "DEG_depsgraph.h"
#include "DEG_depsgraph_query.h"
@@ -542,6 +546,8 @@ void BKE_mesh_init(Mesh *me)
CustomData_reset(&me->ldata);
BKE_mesh_runtime_reset(me);
+
+ me->face_sets_color_seed = BLI_hash_int(PIL_check_seconds_timer_i() & UINT_MAX);
}
Mesh *BKE_mesh_add(Main *bmain, const char *name)
@@ -671,6 +677,8 @@ void BKE_mesh_copy_settings(Mesh *me_dst, const Mesh *me_src)
me_dst->remesh_voxel_adaptivity = me_src->remesh_voxel_adaptivity;
me_dst->remesh_mode = me_src->remesh_mode;
+ me_dst->face_sets_color_seed = me_src->face_sets_color_seed;
+
/* Copy texture space. */
me_dst->texflag = me_src->texflag;
copy_v3_v3(me_dst->loc, me_src->loc);
diff --git a/source/blender/blenkernel/intern/mesh_remesh_voxel.c b/source/blender/blenkernel/intern/mesh_remesh_voxel.c
index afc380fd369..983c19857dd 100644
--- a/source/blender/blenkernel/intern/mesh_remesh_voxel.c
+++ b/source/blender/blenkernel/intern/mesh_remesh_voxel.c
@@ -356,6 +356,55 @@ void BKE_mesh_remesh_reproject_paint_mask(Mesh *target, Mesh *source)
free_bvhtree_from_mesh(&bvhtree);
}
+void BKE_remesh_reproject_sculpt_face_sets(Mesh *target, Mesh *source)
+{
+ BVHTreeFromMesh bvhtree = {
+ .nearest_callback = NULL,
+ };
+
+ const MPoly *target_polys = CustomData_get_layer(&target->pdata, CD_MPOLY);
+ const MVert *target_verts = CustomData_get_layer(&target->vdata, CD_MVERT);
+ const MLoop *target_loops = CustomData_get_layer(&target->ldata, CD_MLOOP);
+
+ int *target_face_sets;
+ if (CustomData_has_layer(&target->pdata, CD_SCULPT_FACE_SETS)) {
+ target_face_sets = CustomData_get_layer(&target->pdata, CD_SCULPT_FACE_SETS);
+ }
+ else {
+ target_face_sets = CustomData_add_layer(
+ &target->pdata, CD_SCULPT_FACE_SETS, CD_CALLOC, NULL, target->totpoly);
+ }
+
+ int *source_face_sets;
+ if (CustomData_has_layer(&source->pdata, CD_SCULPT_FACE_SETS)) {
+ source_face_sets = CustomData_get_layer(&source->pdata, CD_SCULPT_FACE_SETS);
+ }
+ else {
+ source_face_sets = CustomData_add_layer(
+ &source->pdata, CD_SCULPT_FACE_SETS, CD_CALLOC, NULL, source->totpoly);
+ }
+
+ const MLoopTri *looptri = BKE_mesh_runtime_looptri_ensure(source);
+ BKE_bvhtree_from_mesh_get(&bvhtree, source, BVHTREE_FROM_LOOPTRI, 2);
+
+ for (int i = 0; i < target->totpoly; i++) {
+ float from_co[3];
+ BVHTreeNearest nearest;
+ nearest.index = -1;
+ nearest.dist_sq = FLT_MAX;
+ const MPoly *mpoly = &target_polys[i];
+ BKE_mesh_calc_poly_center(mpoly, &target_loops[mpoly->loopstart], target_verts, from_co);
+ BLI_bvhtree_find_nearest(bvhtree.tree, from_co, &nearest, bvhtree.nearest_callback, &bvhtree);
+ if (nearest.index != -1) {
+ target_face_sets[i] = source_face_sets[looptri[nearest.index].poly];
+ }
+ else {
+ target_face_sets[i] = 1;
+ }
+ }
+ free_bvhtree_from_mesh(&bvhtree);
+}
+
struct Mesh *BKE_mesh_remesh_voxel_fix_poles(struct Mesh *mesh)
{
const BMAllocTemplate allocsize = BMALLOC_TEMPLATE_FROM_ME(mesh);
diff --git a/source/blender/blenkernel/intern/paint.c b/source/blender/blenkernel/intern/paint.c
index 9f05b1656cd..bd585d56a51 100644
--- a/source/blender/blenkernel/intern/paint.c
+++ b/source/blender/blenkernel/intern/paint.c
@@ -1212,6 +1212,7 @@ static void sculpt_update_object(
ss->deform_modifiers_active = sculpt_modifiers_active(scene, sd, ob);
ss->show_mask = (sd->flags & SCULPT_HIDE_MASK) == 0;
+ ss->show_face_sets = (sd->flags & SCULPT_HIDE_FACE_SETS) == 0;
ss->building_vp_handle = false;
@@ -1251,6 +1252,16 @@ static void sculpt_update_object(
ss->mloop = me->mloop;
ss->multires = NULL;
ss->vmask = CustomData_get_layer(&me->vdata, CD_PAINT_MASK);
+
+ /* Sculpt Face Sets. */
+ if (!CustomData_has_layer(&me->pdata, CD_SCULPT_FACE_SETS)) {
+ ss->face_sets = CustomData_add_layer(
+ &me->pdata, CD_SCULPT_FACE_SETS, CD_CALLOC, NULL, me->totpoly);
+ for (int i = 0; i < me->totpoly; i++) {
+ ss->face_sets[i] = 1;
+ }
+ }
+ ss->face_sets = CustomData_get_layer(&me->pdata, CD_SCULPT_FACE_SETS);
}
ss->subdiv_ccg = me_eval->runtime.subdiv_ccg;
@@ -1265,6 +1276,7 @@ static void sculpt_update_object(
}
pbvh_show_mask_set(ss->pbvh, ss->show_mask);
+ pbvh_show_face_sets_set(ss->pbvh, ss->show_face_sets);
if (ss->deform_modifiers_active) {
if (!ss->orig_cos) {
@@ -1501,6 +1513,7 @@ static PBVH *build_pbvh_for_dynamic_topology(Object *ob)
ob->sculpt->cd_vert_node_offset,
ob->sculpt->cd_face_node_offset);
pbvh_show_mask_set(pbvh, ob->sculpt->show_mask);
+ pbvh_show_face_sets_set(pbvh, false);
return pbvh;
}
@@ -1522,10 +1535,12 @@ static PBVH *build_pbvh_from_regular_mesh(Object *ob, Mesh *me_eval_deform)
me->totvert,
&me->vdata,
&me->ldata,
+ &me->pdata,
looptri,
looptris_num);
pbvh_show_mask_set(pbvh, ob->sculpt->show_mask);
+ pbvh_show_face_sets_set(pbvh, ob->sculpt->show_face_sets);
const bool is_deformed = check_sculpt_object_deformed(ob, true);
if (is_deformed && me_eval_deform != NULL) {
@@ -1551,6 +1566,7 @@ static PBVH *build_pbvh_from_ccg(Object *ob, SubdivCCG *subdiv_ccg)
subdiv_ccg->grid_flag_mats,
subdiv_ccg->grid_hidden);
pbvh_show_mask_set(pbvh, ob->sculpt->show_mask);
+ pbvh_show_face_sets_set(pbvh, false);
return pbvh;
}
diff --git a/source/blender/blenkernel/intern/pbvh.c b/source/blender/blenkernel/intern/pbvh.c
index 95e7218a920..61caccccf90 100644
--- a/source/blender/blenkernel/intern/pbvh.c
+++ b/source/blender/blenkernel/intern/pbvh.c
@@ -26,6 +26,7 @@
#include "BLI_math.h"
#include "BLI_ghash.h"
#include "BLI_task.h"
+#include "BLI_rand.h"
#include "DNA_mesh_types.h"
#include "DNA_meshdata_types.h"
@@ -36,6 +37,8 @@
#include "BKE_mesh.h" /* for BKE_mesh_calc_normals */
#include "BKE_paint.h"
+#include "PIL_time.h"
+
#include "GPU_buffers.h"
#include "bmesh.h"
@@ -541,6 +544,7 @@ void BKE_pbvh_build_mesh(PBVH *bvh,
int totvert,
struct CustomData *vdata,
struct CustomData *ldata,
+ struct CustomData *pdata,
const MLoopTri *looptri,
int looptri_num)
{
@@ -558,6 +562,9 @@ void BKE_pbvh_build_mesh(PBVH *bvh,
bvh->leaf_limit = LEAF_LIMIT;
bvh->vdata = vdata;
bvh->ldata = ldata;
+ bvh->pdata = pdata;
+
+ bvh->face_sets_color_seed = mesh->face_sets_color_seed;
BB_reset(&cb);
@@ -992,6 +999,7 @@ typedef struct PBVHUpdateData {
float (*vnors)[3];
int flag;
bool show_vcol;
+ bool show_sculpt_face_sets;
} PBVHUpdateData;
static void pbvh_update_normals_accum_task_cb(void *__restrict userdata,
@@ -1155,6 +1163,44 @@ static void pbvh_update_mask_redraw(PBVH *bvh, PBVHNode **nodes, int totnode, in
BKE_pbvh_parallel_range(0, totnode, &data, pbvh_update_mask_redraw_task_cb, &settings);
}
+static void pbvh_update_visibility_redraw_task_cb(void *__restrict userdata,
+ const int n,
+ const TaskParallelTLS *__restrict UNUSED(tls))
+{
+
+ PBVHUpdateData *data = userdata;
+ PBVH *bvh = data->bvh;
+ PBVHNode *node = data->nodes[n];
+ if (node->flag & PBVH_UpdateVisibility) {
+ node->flag &= ~PBVH_UpdateVisibility;
+ BKE_pbvh_node_fully_hidden_set(node, true);
+ if (node->flag & PBVH_Leaf) {
+ PBVHVertexIter vd;
+ BKE_pbvh_vertex_iter_begin(bvh, node, vd, PBVH_ITER_ALL)
+ {
+ if (vd.visible) {
+ BKE_pbvh_node_fully_hidden_set(node, false);
+ return;
+ }
+ }
+ BKE_pbvh_vertex_iter_end;
+ }
+ }
+}
+
+static void pbvh_update_visibility_redraw(PBVH *bvh, PBVHNode **nodes, int totnode, int flag)
+{
+ PBVHUpdateData data = {
+ .bvh = bvh,
+ .nodes = nodes,
+ .flag = flag,
+ };
+
+ PBVHParallelSettings settings;
+ BKE_pbvh_parallel_range_settings(&settings, true, totnode);
+ BKE_pbvh_parallel_range(0, totnode, &data, pbvh_update_visibility_redraw_task_cb, &settings);
+}
+
static void pbvh_update_BB_redraw_task_cb(void *__restrict userdata,
const int n,
const TaskParallelTLS *__restrict UNUSED(tls))
@@ -1198,6 +1244,7 @@ static int pbvh_get_buffers_update_flags(PBVH *bvh, bool show_vcol)
int update_flags = 0;
update_flags |= bvh->show_mask ? GPU_PBVH_BUFFERS_SHOW_MASK : 0;
update_flags |= show_vcol ? GPU_PBVH_BUFFERS_SHOW_VCOL : 0;
+ update_flags |= bvh->show_face_sets ? GPU_PBVH_BUFFERS_SHOW_SCULPT_FACE_SETS : 0;
return update_flags;
}
@@ -1218,14 +1265,16 @@ static void pbvh_update_draw_buffer_cb(void *__restrict userdata,
node->draw_buffers = GPU_pbvh_grid_buffers_build(node->totprim, bvh->grid_hidden);
break;
case PBVH_FACES:
- node->draw_buffers = GPU_pbvh_mesh_buffers_build(node->face_vert_indices,
- bvh->mpoly,
- bvh->mloop,
- bvh->looptri,
- bvh->verts,
- node->prim_indices,
- node->totprim,
- bvh->mesh);
+ node->draw_buffers = GPU_pbvh_mesh_buffers_build(
+ node->face_vert_indices,
+ bvh->mpoly,
+ bvh->mloop,
+ bvh->looptri,
+ bvh->verts,
+ node->prim_indices,
+ CustomData_get_layer(bvh->pdata, CD_SCULPT_FACE_SETS),
+ node->totprim,
+ bvh->mesh);
break;
case PBVH_BMESH:
node->draw_buffers = GPU_pbvh_bmesh_buffers_build(bvh->flags &
@@ -1253,6 +1302,8 @@ static void pbvh_update_draw_buffer_cb(void *__restrict userdata,
node->uniq_verts + node->face_verts,
CustomData_get_layer(bvh->vdata, CD_PAINT_MASK),
CustomData_get_layer(bvh->ldata, CD_MLOOPCOL),
+ CustomData_get_layer(bvh->pdata, CD_SCULPT_FACE_SETS),
+ bvh->face_sets_color_seed,
node->face_vert_indices,
update_flags);
break;
@@ -1373,6 +1424,10 @@ void BKE_pbvh_update_vertex_data(PBVH *bvh, int flag)
pbvh_update_mask_redraw(bvh, nodes, totnode, flag);
}
+ if (flag & (PBVH_UpdateVisibility)) {
+ pbvh_update_visibility_redraw(bvh, nodes, totnode, flag);
+ }
+
if (nodes) {
MEM_freeN(nodes);
}
@@ -1650,6 +1705,12 @@ void BKE_pbvh_node_mark_update_mask(PBVHNode *node)
node->flag |= PBVH_UpdateMask | PBVH_UpdateDrawBuffers | PBVH_UpdateRedraw;
}
+void BKE_pbvh_node_mark_update_visibility(PBVHNode *node)
+{
+ node->flag |= PBVH_UpdateVisibility | PBVH_RebuildDrawBuffers | PBVH_UpdateDrawBuffers |
+ PBVH_UpdateRedraw;
+}
+
void BKE_pbvh_node_mark_rebuild_draw(PBVHNode *node)
{
node->flag |= PBVH_RebuildDrawBuffers | PBVH_UpdateDrawBuffers | PBVH_UpdateRedraw;
@@ -1665,11 +1726,6 @@ void BKE_pbvh_node_mark_normals_update(PBVHNode *node)
node->flag |= PBVH_UpdateNormals;
}
-void BKE_pbvh_node_mark_visibility_update(PBVHNode *node)
-{
- node->flag |= PBVH_UpdateVisibility;
-}
-
void BKE_pbvh_node_fully_hidden_set(PBVHNode *node, int fully_hidden)
{
BLI_assert(node->flag & PBVH_Leaf);
@@ -2559,6 +2615,11 @@ void BKE_pbvh_update_normals(PBVH *bvh, struct SubdivCCG *subdiv_ccg)
MEM_SAFE_FREE(nodes);
}
+void BKE_pbvh_face_sets_color_seed_set(PBVH *bvh, int seed)
+{
+ bvh->face_sets_color_seed = seed;
+}
+
/**
* PBVH drawing, updating draw buffers as needed and culling any nodes outside
* the specified frustum.
@@ -2873,11 +2934,30 @@ bool pbvh_has_mask(PBVH *bvh)
return false;
}
+bool pbvh_has_face_sets(PBVH *bvh)
+{
+ switch (bvh->type) {
+ case PBVH_GRIDS:
+ return false;
+ case PBVH_FACES:
+ return (bvh->pdata && CustomData_get_layer(bvh->pdata, CD_SCULPT_FACE_SETS));
+ case PBVH_BMESH:
+ return false;
+ }
+
+ return false;
+}
+
void pbvh_show_mask_set(PBVH *bvh, bool show_mask)
{
bvh->show_mask = show_mask;
}
+void pbvh_show_face_sets_set(PBVH *bvh, bool show_face_sets)
+{
+ bvh->show_face_sets = show_face_sets;
+}
+
void BKE_pbvh_parallel_range_settings(PBVHParallelSettings *settings,
bool use_threading,
int totnode)
diff --git a/source/blender/blenkernel/intern/pbvh_intern.h b/source/blender/blenkernel/intern/pbvh_intern.h
index bdee05f1aab..51342eb1faa 100644
--- a/source/blender/blenkernel/intern/pbvh_intern.h
+++ b/source/blender/blenkernel/intern/pbvh_intern.h
@@ -134,6 +134,9 @@ struct PBVH {
const MLoopTri *looptri;
CustomData *vdata;
CustomData *ldata;
+ CustomData *pdata;
+
+ int face_sets_color_seed;
/* Grid Data */
CCGKey gridkey;
@@ -154,6 +157,7 @@ struct PBVH {
/* flag are verts/faces deformed */
bool deformed;
bool show_mask;
+ bool show_face_sets;
/* Dynamic topology */
BMesh *bm;