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:
Diffstat (limited to 'source/blender/editors')
-rw-r--r--source/blender/editors/datafiles/CMakeLists.txt2
-rw-r--r--source/blender/editors/include/UI_icons.h2
-rw-r--r--source/blender/editors/mesh/editmesh_mask_extract.c6
-rw-r--r--source/blender/editors/mesh/editmesh_tools.c126
-rw-r--r--source/blender/editors/mesh/editmesh_undo.c4
-rw-r--r--source/blender/editors/mesh/editmesh_utils.c1
-rw-r--r--source/blender/editors/mesh/mesh_intern.h2
-rw-r--r--source/blender/editors/mesh/mesh_ops.c3
-rw-r--r--source/blender/editors/object/object_remesh.c6
-rw-r--r--source/blender/editors/sculpt_paint/paint_cursor.c6
-rw-r--r--source/blender/editors/sculpt_paint/paint_hide.c20
-rw-r--r--source/blender/editors/sculpt_paint/paint_mask.c14
-rw-r--r--source/blender/editors/sculpt_paint/sculpt.c1144
-rw-r--r--source/blender/editors/sculpt_paint/sculpt_automasking.c33
-rw-r--r--source/blender/editors/sculpt_paint/sculpt_boundary.c236
-rw-r--r--source/blender/editors/sculpt_paint/sculpt_cloth.c64
-rw-r--r--source/blender/editors/sculpt_paint/sculpt_detail.c6
-rw-r--r--source/blender/editors/sculpt_paint/sculpt_dyntopo.c246
-rw-r--r--source/blender/editors/sculpt_paint/sculpt_face_set.c144
-rw-r--r--source/blender/editors/sculpt_paint/sculpt_filter_color.c6
-rw-r--r--source/blender/editors/sculpt_paint/sculpt_filter_mask.c14
-rw-r--r--source/blender/editors/sculpt_paint/sculpt_filter_mesh.c39
-rw-r--r--source/blender/editors/sculpt_paint/sculpt_intern.h144
-rw-r--r--source/blender/editors/sculpt_paint/sculpt_mask_expand.c26
-rw-r--r--source/blender/editors/sculpt_paint/sculpt_multiplane_scrape.c4
-rw-r--r--source/blender/editors/sculpt_paint/sculpt_paint_color.c27
-rw-r--r--source/blender/editors/sculpt_paint/sculpt_pose.c93
-rw-r--r--source/blender/editors/sculpt_paint/sculpt_smooth.c393
-rw-r--r--source/blender/editors/sculpt_paint/sculpt_transform.c2
-rw-r--r--source/blender/editors/sculpt_paint/sculpt_undo.c276
-rw-r--r--source/blender/editors/uvedit/uvedit_unwrap_ops.c5
31 files changed, 2374 insertions, 720 deletions
diff --git a/source/blender/editors/datafiles/CMakeLists.txt b/source/blender/editors/datafiles/CMakeLists.txt
index 337fb18f835..6ec7fbe80b6 100644
--- a/source/blender/editors/datafiles/CMakeLists.txt
+++ b/source/blender/editors/datafiles/CMakeLists.txt
@@ -657,6 +657,7 @@ set_property(GLOBAL PROPERTY ICON_GEOM_NAMES
brush.sculpt.mask
brush.sculpt.multiplane_scrape
brush.sculpt.nudge
+ brush.sculpt.paint
brush.sculpt.pinch
brush.sculpt.pose
brush.sculpt.rotate
@@ -666,6 +667,7 @@ set_property(GLOBAL PROPERTY ICON_GEOM_NAMES
brush.sculpt.snake_hook
brush.sculpt.thumb
brush.sculpt.topology
+ brush.sculpt.vcol_boundary
brush.uv_sculpt.grab
brush.uv_sculpt.pinch
brush.uv_sculpt.relax
diff --git a/source/blender/editors/include/UI_icons.h b/source/blender/editors/include/UI_icons.h
index b7eb5cab7f9..79311042274 100644
--- a/source/blender/editors/include/UI_icons.h
+++ b/source/blender/editors/include/UI_icons.h
@@ -919,6 +919,8 @@ DEF_ICON_COLOR(BRUSH_TEXFILL)
DEF_ICON_COLOR(BRUSH_TEXMASK)
DEF_ICON_COLOR(BRUSH_THUMB)
DEF_ICON_COLOR(BRUSH_ROTATE)
+DEF_ICON_COLOR(BRUSH_VCOL_BOUNDARY)
+DEF_ICON_COLOR(BRUSH_PAINT)
/* grease pencil sculpt */
DEF_ICON_COLOR(GPBRUSH_SMOOTH)
diff --git a/source/blender/editors/mesh/editmesh_mask_extract.c b/source/blender/editors/mesh/editmesh_mask_extract.c
index be9314ad2fd..714adb96604 100644
--- a/source/blender/editors/mesh/editmesh_mask_extract.c
+++ b/source/blender/editors/mesh/editmesh_mask_extract.c
@@ -116,7 +116,7 @@ static int geometry_extract_apply(bContext *C,
.use_toolflags = true,
}));
- BM_mesh_bm_from_me(bm,
+ BM_mesh_bm_from_me(NULL, bm,
new_mesh,
(&(struct BMeshFromMeshParams){
.calc_face_normal = true,
@@ -509,7 +509,7 @@ static int paint_mask_slice_exec(bContext *C, wmOperator *op)
.use_toolflags = true,
}));
- BM_mesh_bm_from_me(bm,
+ BM_mesh_bm_from_me(NULL, bm,
new_mesh,
(&(struct BMeshFromMeshParams){
.calc_face_normal = true,
@@ -540,7 +540,7 @@ static int paint_mask_slice_exec(bContext *C, wmOperator *op)
.use_toolflags = true,
}));
- BM_mesh_bm_from_me(bm,
+ BM_mesh_bm_from_me(NULL, bm,
new_ob_mesh,
(&(struct BMeshFromMeshParams){
.calc_face_normal = true,
diff --git a/source/blender/editors/mesh/editmesh_tools.c b/source/blender/editors/mesh/editmesh_tools.c
index cf01170dd8a..59ce9140ab8 100644
--- a/source/blender/editors/mesh/editmesh_tools.c
+++ b/source/blender/editors/mesh/editmesh_tools.c
@@ -4222,7 +4222,7 @@ static Base *mesh_separate_tagged(
BM_mesh_normals_update(bm_new);
- BM_mesh_bm_to_me(bmain, bm_new, base_new->object->data, (&(struct BMeshToMeshParams){0}));
+ BM_mesh_bm_to_me(bmain, base_new->object, bm_new, base_new->object->data, (&(struct BMeshToMeshParams){0}));
BM_mesh_free(bm_new);
((Mesh *)base_new->object->data)->edit_mesh = NULL;
@@ -4289,7 +4289,7 @@ static Base *mesh_separate_arrays(Main *bmain,
BM_vert_kill(bm_old, verts[i]);
}
- BM_mesh_bm_to_me(bmain, bm_new, base_new->object->data, (&(struct BMeshToMeshParams){0}));
+ BM_mesh_bm_to_me(bmain, base_new->object, bm_new, base_new->object->data, (&(struct BMeshToMeshParams){0}));
BM_mesh_free(bm_new);
((Mesh *)base_new->object->data)->edit_mesh = NULL;
@@ -4474,7 +4474,7 @@ static bool mesh_separate_loose(
BM_mesh_elem_hflag_disable_all(bm_old, BM_VERT | BM_EDGE | BM_FACE, BM_ELEM_SELECT, false);
if (clear_object_data) {
- BM_mesh_bm_to_me(NULL,
+ BM_mesh_bm_to_me(NULL, base_old->object,
bm_old,
me_old,
(&(struct BMeshToMeshParams){
@@ -4561,7 +4561,7 @@ static int edbm_separate_exec(bContext *C, wmOperator *op)
.use_toolflags = true,
}));
- BM_mesh_bm_from_me(bm_old, me, (&(struct BMeshFromMeshParams){0}));
+ BM_mesh_bm_from_me(NULL, bm_old, me, (&(struct BMeshFromMeshParams){0}));
switch (type) {
case MESH_SEPARATE_MATERIAL:
@@ -4577,6 +4577,7 @@ static int edbm_separate_exec(bContext *C, wmOperator *op)
if (retval_iter) {
BM_mesh_bm_to_me(bmain,
+ ob,
bm_old,
me,
(&(struct BMeshToMeshParams){
@@ -5728,7 +5729,7 @@ static void edbm_dissolve_prop__use_boundary_tear(wmOperatorType *ot)
"Split off face corners instead of merging faces");
}
-static int edbm_dissolve_verts_exec(bContext *C, wmOperator *op)
+static int edbm_mres_test_exec(bContext *C, wmOperator *op)
{
const bool use_face_split = RNA_boolean_get(op->ptr, "use_face_split");
const bool use_boundary_tear = RNA_boolean_get(op->ptr, "use_boundary_tear");
@@ -5750,10 +5751,116 @@ static int edbm_dissolve_verts_exec(bContext *C, wmOperator *op)
if (!EDBM_op_callf(em,
op,
- "dissolve_verts verts=%hv use_face_split=%b use_boundary_tear=%b",
- BM_ELEM_SELECT,
- use_face_split,
- use_boundary_tear)) {
+ "test_mres_smooth")) {
+ continue;
+ }
+
+ BM_custom_loop_normals_from_vector_layer(em->bm, false);
+ EDBM_update_generic(obedit->data, true, true);
+ }
+
+ MEM_freeN(objects);
+ return OPERATOR_FINISHED;
+}
+
+
+extern Object *multires_dump_grids_bmesh(Object *bmob, BMesh *bm);
+
+static int edbm_dump_mres_grids_exec(bContext *C, wmOperator *op)
+{
+ const bool use_face_split = RNA_boolean_get(op->ptr, "use_face_split");
+ const bool use_boundary_tear = RNA_boolean_get(op->ptr, "use_boundary_tear");
+
+ ViewLayer *view_layer = CTX_data_view_layer(C);
+ uint objects_len = 0;
+ Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data(
+ view_layer, CTX_wm_view3d(C), &objects_len);
+
+ for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
+ Object *obedit = objects[ob_index];
+ BMEditMesh *em = BKE_editmesh_from_object(obedit);
+
+ multires_dump_grids_bmesh(obedit, em->bm);
+ }
+
+ WM_event_add_notifier(C, NC_SCENE | ND_LAYER_CONTENT, CTX_data_scene(C));
+
+ MEM_freeN(objects);
+ return OPERATOR_FINISHED;
+}
+
+static bool mres_test_poll(bContext *C)
+{
+ Object *obedit = CTX_data_edit_object(C);
+ if (obedit && obedit->type == OB_MESH) {
+ BMEditMesh *em = BKE_editmesh_from_object(obedit);
+
+ if (!em || !CustomData_has_layer(&em->bm->ldata, CD_MDISPS)) {
+ return false;
+ }
+
+ return true;
+ }
+
+ return false;
+}
+
+void MESH_OT_dump_mres_grids(wmOperatorType *ot) {
+ /* identifiers */
+ ot->name = "Dump Multires Grids";
+ ot->description = "Dump Multires Grids";
+ ot->idname = "MESH_OT_dump_mres_grids";
+
+ /* api callbacks */
+ ot->exec = edbm_dump_mres_grids_exec;
+ ot->poll = mres_test_poll;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+}
+
+void MESH_OT_mres_test(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name = "Test Multires Boundary Smooth";
+ ot->description = "Test multires boundary smooth";
+ ot->idname = "MESH_OT_mres_test";
+
+ /* api callbacks */
+ ot->exec = edbm_mres_test_exec;
+ ot->poll = mres_test_poll;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+}
+
+
+static int edbm_dissolve_verts_exec(bContext *C, wmOperator *op)
+{
+ const bool use_face_split = RNA_boolean_get(op->ptr, "use_face_split");
+ const bool use_boundary_tear = RNA_boolean_get(op->ptr, "use_boundary_tear");
+
+ ViewLayer *view_layer = CTX_data_view_layer(C);
+ uint objects_len = 0;
+ Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data(
+ view_layer, CTX_wm_view3d(C), &objects_len);
+
+ for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
+ Object *obedit = objects[ob_index];
+ BMEditMesh *em = BKE_editmesh_from_object(obedit);
+
+ if (em->bm->totvertsel == 0) {
+ continue;
+ }
+
+ BM_custom_loop_normals_to_vector_layer(em->bm);
+
+ if (!EDBM_op_callf(em,
+ op,
+ "dissolve_verts verts=%hv use_face_split=%b use_boundary_tear=%b",
+ BM_ELEM_SELECT,
+ use_face_split,
+ use_boundary_tear)) {
continue;
}
@@ -5766,6 +5873,7 @@ static int edbm_dissolve_verts_exec(bContext *C, wmOperator *op)
return OPERATOR_FINISHED;
}
+
void MESH_OT_dissolve_verts(wmOperatorType *ot)
{
/* identifiers */
diff --git a/source/blender/editors/mesh/editmesh_undo.c b/source/blender/editors/mesh/editmesh_undo.c
index cff5414da75..b16b2809e51 100644
--- a/source/blender/editors/mesh/editmesh_undo.c
+++ b/source/blender/editors/mesh/editmesh_undo.c
@@ -522,7 +522,7 @@ static void *undomesh_from_editmesh(UndoMesh *um, BMEditMesh *em, Key *key)
/* BM_mesh_validate(em->bm); */ /* for troubleshooting */
BM_mesh_bm_to_me(
- NULL,
+ NULL, NULL,
em->bm,
&um->me,
(&(struct BMeshToMeshParams){
@@ -598,7 +598,7 @@ static void undomesh_to_editmesh(UndoMesh *um, Object *ob, BMEditMesh *em, Key *
.use_toolflags = true,
}));
- BM_mesh_bm_from_me(bm,
+ BM_mesh_bm_from_me(NULL, bm,
&um->me,
(&(struct BMeshFromMeshParams){
.calc_face_normal = true,
diff --git a/source/blender/editors/mesh/editmesh_utils.c b/source/blender/editors/mesh/editmesh_utils.c
index 94f386e08d5..ce77f90c5fe 100644
--- a/source/blender/editors/mesh/editmesh_utils.c
+++ b/source/blender/editors/mesh/editmesh_utils.c
@@ -352,6 +352,7 @@ void EDBM_mesh_load_ex(Main *bmain, Object *ob, bool free_data)
}
BM_mesh_bm_to_me(bmain,
+ ob,
bm,
me,
(&(struct BMeshToMeshParams){
diff --git a/source/blender/editors/mesh/mesh_intern.h b/source/blender/editors/mesh/mesh_intern.h
index 21feddfb886..fcef1866e3a 100644
--- a/source/blender/editors/mesh/mesh_intern.h
+++ b/source/blender/editors/mesh/mesh_intern.h
@@ -259,6 +259,7 @@ void MESH_OT_set_normals_from_faces(struct wmOperatorType *ot);
void MESH_OT_average_normals(struct wmOperatorType *ot);
void MESH_OT_smooth_normals(struct wmOperatorType *ot);
void MESH_OT_mod_weighted_strength(struct wmOperatorType *ot);
+void MESH_OT_mres_test(struct wmOperatorType *ot);
/* *** editmesh_mask_extract.c *** */
void MESH_OT_paint_mask_extract(struct wmOperatorType *ot);
@@ -285,3 +286,4 @@ void MESH_OT_customdata_skin_add(struct wmOperatorType *ot);
void MESH_OT_customdata_skin_clear(struct wmOperatorType *ot);
void MESH_OT_customdata_custom_splitnormals_add(struct wmOperatorType *ot);
void MESH_OT_customdata_custom_splitnormals_clear(struct wmOperatorType *ot);
+void MESH_OT_dump_mres_grids(struct wmOperatorType *ot);
diff --git a/source/blender/editors/mesh/mesh_ops.c b/source/blender/editors/mesh/mesh_ops.c
index 2cf97b7235f..54d540845cf 100644
--- a/source/blender/editors/mesh/mesh_ops.c
+++ b/source/blender/editors/mesh/mesh_ops.c
@@ -208,6 +208,9 @@ void ED_operatortypes_mesh(void)
WM_operatortype_append(MESH_OT_average_normals);
WM_operatortype_append(MESH_OT_smooth_normals);
WM_operatortype_append(MESH_OT_mod_weighted_strength);
+ WM_operatortype_append(MESH_OT_mres_test);
+ WM_operatortype_append(MESH_OT_dump_mres_grids);
+
}
#if 0 /* UNUSED, remove? */
diff --git a/source/blender/editors/object/object_remesh.c b/source/blender/editors/object/object_remesh.c
index 11be71623d8..5d1f634d1b2 100644
--- a/source/blender/editors/object/object_remesh.c
+++ b/source/blender/editors/object/object_remesh.c
@@ -752,7 +752,7 @@ static void quadriflow_update_job(void *customdata, float progress, int *cancel)
*(qj->progress) = progress;
}
-static Mesh *remesh_symmetry_bisect(Mesh *mesh, eSymmetryAxes symmetry_axes)
+static Mesh *remesh_symmetry_bisect(Object *ob, Mesh *mesh, eSymmetryAxes symmetry_axes)
{
MirrorModifierData mmd = {{0}};
mmd.tolerance = QUADRIFLOW_MIRROR_BISECT_TOLERANCE;
@@ -774,7 +774,7 @@ static Mesh *remesh_symmetry_bisect(Mesh *mesh, eSymmetryAxes symmetry_axes)
plane_no[axis] = -1.0f;
mesh_bisect_temp = mesh_bisect;
mesh_bisect = BKE_mesh_mirror_bisect_on_mirror_plane(
- &mmd, mesh_bisect, axis, plane_co, plane_no);
+ ob, &mmd, mesh_bisect, axis, plane_co, plane_no);
if (mesh_bisect_temp != mesh_bisect) {
BKE_id_free(NULL, mesh_bisect_temp);
}
@@ -842,7 +842,7 @@ static void quadriflow_start_job(void *customdata, short *stop, short *do_update
bisect_mesh = BKE_mesh_copy_for_eval(mesh, false);
/* Bisect the input mesh using the paint symmetry settings */
- bisect_mesh = remesh_symmetry_bisect(bisect_mesh, qj->symmetry_axes);
+ bisect_mesh = remesh_symmetry_bisect(ob, bisect_mesh, qj->symmetry_axes);
new_mesh = BKE_mesh_remesh_quadriflow_to_mesh_nomain(
bisect_mesh,
diff --git a/source/blender/editors/sculpt_paint/paint_cursor.c b/source/blender/editors/sculpt_paint/paint_cursor.c
index 550913fc8af..733116536fc 100644
--- a/source/blender/editors/sculpt_paint/paint_cursor.c
+++ b/source/blender/editors/sculpt_paint/paint_cursor.c
@@ -1214,7 +1214,7 @@ typedef struct PaintCursorContext {
/* Sculpt related data. */
Sculpt *sd;
SculptSession *ss;
- int prev_active_vertex_index;
+ SculptVertRef prev_active_vertex_index;
bool is_stroke_active;
bool is_cursor_over_mesh;
bool is_multires;
@@ -1573,8 +1573,8 @@ static void paint_cursor_draw_3d_view_brush_cursor_inactive(PaintCursorContext *
paint_cursor_update_object_space_radius(pcontext);
- const bool update_previews = pcontext->prev_active_vertex_index !=
- SCULPT_active_vertex_get(pcontext->ss);
+ const bool update_previews = pcontext->prev_active_vertex_index.i !=
+ SCULPT_active_vertex_get(pcontext->ss).i;
/* Setup drawing. */
wmViewport(&pcontext->region->winrct);
diff --git a/source/blender/editors/sculpt_paint/paint_hide.c b/source/blender/editors/sculpt_paint/paint_hide.c
index da627c6b7db..4e3e074c9bf 100644
--- a/source/blender/editors/sculpt_paint/paint_hide.c
+++ b/source/blender/editors/sculpt_paint/paint_hide.c
@@ -209,17 +209,15 @@ static void partialvis_update_grids(Depsgraph *depsgraph,
}
static void partialvis_update_bmesh_verts(BMesh *bm,
- GSet *verts,
+ TableGSet *verts,
PartialVisAction action,
PartialVisArea area,
float planes[4][4],
bool *any_changed,
bool *any_visible)
{
- GSetIterator gs_iter;
-
- GSET_ITER (gs_iter, verts) {
- BMVert *v = BLI_gsetIterator_getKey(&gs_iter);
+ BMVert *v;
+ TGSET_ITER (v, verts) {
float *vmask = CustomData_bmesh_get(&bm->vdata, v->head.data, CD_PAINT_MASK);
/* Hide vertex if in the hide volume. */
@@ -237,15 +235,14 @@ static void partialvis_update_bmesh_verts(BMesh *bm,
(*any_visible) = true;
}
}
+ TGSET_ITER_END
}
-static void partialvis_update_bmesh_faces(GSet *faces)
+static void partialvis_update_bmesh_faces(TableGSet *faces)
{
- GSetIterator gs_iter;
-
- GSET_ITER (gs_iter, faces) {
- BMFace *f = BLI_gsetIterator_getKey(&gs_iter);
+ BMFace *f;
+ TGSET_ITER (f, faces) {
if (paint_is_bmesh_face_hidden(f)) {
BM_elem_flag_enable(f, BM_ELEM_HIDDEN);
}
@@ -253,6 +250,7 @@ static void partialvis_update_bmesh_faces(GSet *faces)
BM_elem_flag_disable(f, BM_ELEM_HIDDEN);
}
}
+ TGSET_ITER_END
}
static void partialvis_update_bmesh(Object *ob,
@@ -263,7 +261,7 @@ static void partialvis_update_bmesh(Object *ob,
float planes[4][4])
{
BMesh *bm;
- GSet *unique, *other, *faces;
+ TableGSet *unique, *other, *faces;
bool any_changed = false, any_visible = false;
bm = BKE_pbvh_get_bmesh(pbvh);
diff --git a/source/blender/editors/sculpt_paint/paint_mask.c b/source/blender/editors/sculpt_paint/paint_mask.c
index 92c78a674f0..713049137ce 100644
--- a/source/blender/editors/sculpt_paint/paint_mask.c
+++ b/source/blender/editors/sculpt_paint/paint_mask.c
@@ -680,7 +680,7 @@ static bool sculpt_gesture_is_effected_lasso(SculptGestureContext *sgcontext, co
static bool sculpt_gesture_is_vertex_effected(SculptGestureContext *sgcontext, PBVHVertexIter *vd)
{
float vertex_normal[3];
- SCULPT_vertex_normal_get(sgcontext->ss, vd->index, vertex_normal);
+ SCULPT_vertex_normal_get(sgcontext->ss, vd->vertex, vertex_normal);
float dot = dot_v3v3(sgcontext->view_normal, vertex_normal);
const bool is_effected_front_face = !(sgcontext->front_faces_only && dot < 0.0f);
@@ -760,7 +760,7 @@ static void face_set_gesture_apply_task_cb(void *__restrict userdata,
BKE_pbvh_vertex_iter_begin(sgcontext->ss->pbvh, node, vd, PBVH_ITER_UNIQUE)
{
if (sculpt_gesture_is_vertex_effected(sgcontext, &vd)) {
- SCULPT_vertex_face_set_set(sgcontext->ss, vd.index, face_set_operation->new_face_set_id);
+ SCULPT_vertex_face_set_set(sgcontext->ss, vd.vertex, face_set_operation->new_face_set_id);
any_updated = true;
}
}
@@ -977,7 +977,7 @@ static void sculpt_gesture_trim_normals_update(SculptGestureContext *sgcontext)
.use_toolflags = true,
}));
- BM_mesh_bm_from_me(bm,
+ BM_mesh_bm_from_me(NULL, bm,
trim_mesh,
(&(struct BMeshFromMeshParams){
.calc_face_normal = true,
@@ -1040,7 +1040,7 @@ static void sculpt_gesture_trim_calculate_depth(bContext *C, SculptGestureContex
trim_operation->depth_back = -FLT_MAX;
for (int i = 0; i < totvert; i++) {
- const float *vco = SCULPT_vertex_co_get(ss, i);
+ const float *vco = SCULPT_vertex_co_get(ss, BKE_pbvh_table_index_to_vertex(ss->pbvh, i));
/* Convert the coordinates to world space to calculate the depth. When generating the trimming
* mesh, coordinates are first calculated in world space, then converted to object space to
* store them. */
@@ -1230,13 +1230,15 @@ static void sculpt_gesture_apply_trim(SculptGestureContext *sgcontext)
.use_toolflags = false,
}));
- BM_mesh_bm_from_me(bm,
+ BM_mesh_bm_from_me(NULL,
+ bm,
trim_mesh,
&((struct BMeshFromMeshParams){
.calc_face_normal = true,
}));
- BM_mesh_bm_from_me(bm,
+ BM_mesh_bm_from_me(NULL,
+ bm,
sculpt_mesh,
&((struct BMeshFromMeshParams){
.calc_face_normal = true,
diff --git a/source/blender/editors/sculpt_paint/sculpt.c b/source/blender/editors/sculpt_paint/sculpt.c
index 38d2bed7d97..bf55d6a323e 100644
--- a/source/blender/editors/sculpt_paint/sculpt.c
+++ b/source/blender/editors/sculpt_paint/sculpt.c
@@ -117,7 +117,7 @@
void SCULPT_vertex_random_access_ensure(SculptSession *ss)
{
- if (BKE_pbvh_type(ss->pbvh) == PBVH_BMESH) {
+ if (ss->bm) {
BM_mesh_elem_index_ensure(ss->bm, BM_VERT);
BM_mesh_elem_table_ensure(ss->bm, BM_VERT);
}
@@ -137,22 +137,24 @@ int SCULPT_vertex_count_get(SculptSession *ss)
return 0;
}
-const float *SCULPT_vertex_co_get(SculptSession *ss, int index)
+const float *SCULPT_vertex_co_get(SculptSession *ss, SculptVertRef index)
{
switch (BKE_pbvh_type(ss->pbvh)) {
case PBVH_FACES: {
if (ss->shapekey_active || ss->deform_modifiers_active) {
const MVert *mverts = BKE_pbvh_get_verts(ss->pbvh);
- return mverts[index].co;
+ return mverts[index.i].co;
}
- return ss->mvert[index].co;
+ return ss->mvert[index.i].co;
+ }
+ case PBVH_BMESH: {
+ BMVert *v = (BMVert *)index.i;
+ return v->co;
}
- case PBVH_BMESH:
- return BM_vert_at_index(BKE_pbvh_get_bmesh(ss->pbvh), index)->co;
case PBVH_GRIDS: {
const CCGKey *key = BKE_pbvh_get_grid_key(ss->pbvh);
- const int grid_index = index / key->grid_area;
- const int vertex_index = index - grid_index * key->grid_area;
+ const int grid_index = index.i / key->grid_area;
+ const int vertex_index = index.i - grid_index * key->grid_area;
CCGElem *elem = BKE_pbvh_get_grids(ss->pbvh)[grid_index];
return CCG_elem_co(key, CCG_elem_offset(key, elem, vertex_index));
}
@@ -160,41 +162,53 @@ const float *SCULPT_vertex_co_get(SculptSession *ss, int index)
return NULL;
}
-const float *SCULPT_vertex_color_get(SculptSession *ss, int index)
+const float *SCULPT_vertex_color_get(SculptSession *ss, SculptVertRef index)
{
switch (BKE_pbvh_type(ss->pbvh)) {
case PBVH_FACES:
if (ss->vcol) {
- return ss->vcol[index].color;
+ return ss->vcol[index.i].color;
}
break;
- case PBVH_BMESH:
+ case PBVH_BMESH: {
+ BMVert *v = (BMVert *)index.i;
+
+ if (ss->cd_vcol_offset >= 0) {
+ MPropCol *col = BM_ELEM_CD_GET_VOID_P(v, ss->cd_vcol_offset);
+ return col->color;
+ }
+
+ break;
+ }
case PBVH_GRIDS:
break;
}
return NULL;
}
-void SCULPT_vertex_normal_get(SculptSession *ss, int index, float no[3])
+void SCULPT_vertex_normal_get(SculptSession *ss, SculptVertRef index, float no[3])
{
switch (BKE_pbvh_type(ss->pbvh)) {
case PBVH_FACES: {
if (ss->shapekey_active || ss->deform_modifiers_active) {
const MVert *mverts = BKE_pbvh_get_verts(ss->pbvh);
- normal_short_to_float_v3(no, mverts[index].no);
+ normal_short_to_float_v3(no, mverts[index.i].no);
}
else {
- normal_short_to_float_v3(no, ss->mvert[index].no);
+ normal_short_to_float_v3(no, ss->mvert[index.i].no);
}
break;
}
- case PBVH_BMESH:
- copy_v3_v3(no, BM_vert_at_index(BKE_pbvh_get_bmesh(ss->pbvh), index)->no);
+ case PBVH_BMESH: {
+ BMVert *v = (BMVert *)index.i;
+
+ copy_v3_v3(no, v->no);
break;
+ }
case PBVH_GRIDS: {
const CCGKey *key = BKE_pbvh_get_grid_key(ss->pbvh);
- const int grid_index = index / key->grid_area;
- const int vertex_index = index - grid_index * key->grid_area;
+ const int grid_index = index.i / key->grid_area;
+ const int vertex_index = index.i - grid_index * key->grid_area;
CCGElem *elem = BKE_pbvh_get_grids(ss->pbvh)[grid_index];
copy_v3_v3(no, CCG_elem_no(key, CCG_elem_offset(key, elem, vertex_index)));
break;
@@ -202,32 +216,35 @@ void SCULPT_vertex_normal_get(SculptSession *ss, int index, float no[3])
}
}
-const float *SCULPT_vertex_persistent_co_get(SculptSession *ss, int index)
+const float *SCULPT_vertex_persistent_co_get(SculptSession *ss, SculptVertRef index)
{
if (ss->persistent_base) {
- return ss->persistent_base[index].co;
+ if (BKE_pbvh_type(ss->pbvh) == PBVH_BMESH) {
+ index.i = BM_elem_index_get((BMVert *)index.i);
+ }
+ return ss->persistent_base[index.i].co;
}
return SCULPT_vertex_co_get(ss, index);
}
-const float *SCULPT_vertex_co_for_grab_active_get(SculptSession *ss, int index)
+const float *SCULPT_vertex_co_for_grab_active_get(SculptSession *ss, SculptVertRef vertex)
{
/* Always grab active shape key if the sculpt happens on shapekey. */
if (ss->shapekey_active) {
const MVert *mverts = BKE_pbvh_get_verts(ss->pbvh);
- return mverts[index].co;
+ return mverts[BKE_pbvh_vertex_index_to_table(ss->pbvh, vertex)].co;
}
/* Sculpting on the base mesh. */
if (ss->mvert) {
- return ss->mvert[index].co;
+ return ss->mvert[BKE_pbvh_vertex_index_to_table(ss->pbvh, vertex)].co;
}
/* Everything else, such as sculpting on multires. */
- return SCULPT_vertex_co_get(ss, index);
+ return SCULPT_vertex_co_get(ss, vertex);
}
-void SCULPT_vertex_limit_surface_get(SculptSession *ss, int index, float r_co[3])
+void SCULPT_vertex_limit_surface_get(SculptSession *ss, SculptVertRef index, float r_co[3])
{
switch (BKE_pbvh_type(ss->pbvh)) {
case PBVH_FACES:
@@ -236,8 +253,8 @@ void SCULPT_vertex_limit_surface_get(SculptSession *ss, int index, float r_co[3]
break;
case PBVH_GRIDS: {
const CCGKey *key = BKE_pbvh_get_grid_key(ss->pbvh);
- const int grid_index = index / key->grid_area;
- const int vertex_index = index - grid_index * key->grid_area;
+ const int grid_index = index.i / key->grid_area;
+ const int vertex_index = index.i - grid_index * key->grid_area;
SubdivCCGCoord coord = {.grid_index = grid_index,
.x = vertex_index % key->grid_size,
@@ -248,30 +265,30 @@ void SCULPT_vertex_limit_surface_get(SculptSession *ss, int index, float r_co[3]
}
}
-void SCULPT_vertex_persistent_normal_get(SculptSession *ss, int index, float no[3])
+void SCULPT_vertex_persistent_normal_get(SculptSession *ss, SculptVertRef index, float no[3])
{
if (ss->persistent_base) {
- copy_v3_v3(no, ss->persistent_base[index].no);
+ copy_v3_v3(no, ss->persistent_base[BKE_pbvh_vertex_index_to_table(ss->pbvh, index)].no);
return;
}
SCULPT_vertex_normal_get(ss, index, no);
}
-float SCULPT_vertex_mask_get(SculptSession *ss, int index)
+float SCULPT_vertex_mask_get(SculptSession *ss, SculptVertRef index)
{
BMVert *v;
float *mask;
switch (BKE_pbvh_type(ss->pbvh)) {
case PBVH_FACES:
- return ss->vmask[index];
+ return ss->vmask[index.i];
case PBVH_BMESH:
- v = BM_vert_at_index(BKE_pbvh_get_bmesh(ss->pbvh), index);
+ v = (BMVert *)index.i;
mask = BM_ELEM_CD_GET_VOID_P(v, CustomData_get_offset(&ss->bm->vdata, CD_PAINT_MASK));
return *mask;
case PBVH_GRIDS: {
const CCGKey *key = BKE_pbvh_get_grid_key(ss->pbvh);
- const int grid_index = index / key->grid_area;
- const int vertex_index = index - grid_index * key->grid_area;
+ const int grid_index = index.i / key->grid_area;
+ const int vertex_index = index.i - grid_index * key->grid_area;
CCGElem *elem = BKE_pbvh_get_grids(ss->pbvh)[grid_index];
return *CCG_elem_mask(key, CCG_elem_offset(key, elem, vertex_index));
}
@@ -280,12 +297,12 @@ float SCULPT_vertex_mask_get(SculptSession *ss, int index)
return 0.0f;
}
-int SCULPT_active_vertex_get(SculptSession *ss)
+SculptVertRef SCULPT_active_vertex_get(SculptSession *ss)
{
if (ELEM(BKE_pbvh_type(ss->pbvh), PBVH_FACES, PBVH_BMESH, PBVH_GRIDS)) {
return ss->active_vertex_index;
}
- return 0;
+ return BKE_pbvh_make_vref(0);
}
const float *SCULPT_active_vertex_co_get(SculptSession *ss)
@@ -338,44 +355,49 @@ int SCULPT_active_face_set_get(SculptSession *ss)
{
switch (BKE_pbvh_type(ss->pbvh)) {
case PBVH_FACES:
- return ss->face_sets[ss->active_face_index];
+ return ss->face_sets[ss->active_face_index.i];
case PBVH_GRIDS: {
const int face_index = BKE_subdiv_ccg_grid_to_face_index(ss->subdiv_ccg,
ss->active_grid_index);
return ss->face_sets[face_index];
}
case PBVH_BMESH:
+ if (ss->cd_faceset_offset && ss->active_face_index.i) {
+ BMFace *f = (BMFace *)ss->active_face_index.i;
+ return BM_ELEM_CD_GET_INT(f, ss->cd_faceset_offset);
+ }
+
return SCULPT_FACE_SET_NONE;
}
return SCULPT_FACE_SET_NONE;
}
-void SCULPT_vertex_visible_set(SculptSession *ss, int index, bool visible)
+void SCULPT_vertex_visible_set(SculptSession *ss, SculptVertRef index, bool visible)
{
switch (BKE_pbvh_type(ss->pbvh)) {
case PBVH_FACES:
- SET_FLAG_FROM_TEST(ss->mvert[index].flag, !visible, ME_HIDE);
- ss->mvert[index].flag |= ME_VERT_PBVH_UPDATE;
+ SET_FLAG_FROM_TEST(ss->mvert[index.i].flag, !visible, ME_HIDE);
+ ss->mvert[index.i].flag |= ME_VERT_PBVH_UPDATE;
break;
case PBVH_BMESH:
- BM_elem_flag_set(BM_vert_at_index(ss->bm, index), BM_ELEM_HIDDEN, !visible);
+ BM_elem_flag_set((BMVert *)index.i, BM_ELEM_HIDDEN, !visible);
break;
case PBVH_GRIDS:
break;
}
}
-bool SCULPT_vertex_visible_get(SculptSession *ss, int index)
+bool SCULPT_vertex_visible_get(SculptSession *ss, SculptVertRef index)
{
switch (BKE_pbvh_type(ss->pbvh)) {
case PBVH_FACES:
- return !(ss->mvert[index].flag & ME_HIDE);
+ return !(ss->mvert[index.i].flag & ME_HIDE);
case PBVH_BMESH:
- return !BM_elem_flag_test(BM_vert_at_index(ss->bm, index), BM_ELEM_HIDDEN);
+ return !BM_elem_flag_test(((BMVert *)index.i), BM_ELEM_HIDDEN);
case PBVH_GRIDS: {
const CCGKey *key = BKE_pbvh_get_grid_key(ss->pbvh);
- const int grid_index = index / key->grid_area;
- const int vertex_index = index - grid_index * key->grid_area;
+ const int grid_index = index.i / key->grid_area;
+ const int vertex_index = index.i - grid_index * key->grid_area;
BLI_bitmap **grid_hidden = BKE_pbvh_get_grid_visibility(ss->pbvh);
if (grid_hidden && grid_hidden[grid_index]) {
return !BLI_BITMAP_TEST(grid_hidden[grid_index], vertex_index);
@@ -401,8 +423,28 @@ void SCULPT_face_set_visibility_set(SculptSession *ss, int face_set, bool visibl
}
}
break;
- case PBVH_BMESH:
+ case PBVH_BMESH: {
+ BMIter iter;
+ BMFace *f;
+
+ BM_ITER_MESH (f, &iter, ss->bm, BM_FACES_OF_MESH) {
+ int fset = BM_ELEM_CD_GET_INT(f, ss->cd_faceset_offset);
+
+ if (abs(fset) != face_set) {
+ continue;
+ }
+
+ if (visible) {
+ fset = abs(fset);
+ }
+ else {
+ fset = -abs(fset);
+ }
+
+ BM_ELEM_CD_SET_INT(f, ss->cd_faceset_offset, fset);
+ }
break;
+ }
}
}
@@ -415,8 +457,19 @@ void SCULPT_face_sets_visibility_invert(SculptSession *ss)
ss->face_sets[i] *= -1;
}
break;
- case PBVH_BMESH:
+ case PBVH_BMESH: {
+ BMIter iter;
+ BMFace *f;
+
+ BM_ITER_MESH (f, &iter, ss->bm, BM_FACES_OF_MESH) {
+ int fset = BM_ELEM_CD_GET_INT(f, ss->cd_faceset_offset);
+
+ fset = -fset;
+
+ BM_ELEM_CD_SET_INT(f, ss->cd_faceset_offset, fset);
+ }
break;
+ }
}
}
@@ -442,48 +495,108 @@ void SCULPT_face_sets_visibility_all_set(SculptSession *ss, bool visible)
}
}
break;
- case PBVH_BMESH:
+ case PBVH_BMESH: {
+ BMIter iter;
+ BMFace *f;
+
+ if (!ss->bm) {
+ return;
+ }
+
+ // paranoia check of cd_faceset_offset
+ if (ss->cd_faceset_offset < 0) {
+ ss->cd_faceset_offset = CustomData_get_offset(&ss->bm->pdata, CD_SCULPT_FACE_SETS);
+ }
+ if (ss->cd_faceset_offset < 0) {
+ return;
+ }
+
+ BM_ITER_MESH (f, &iter, ss->bm, BM_FACES_OF_MESH) {
+ int fset = BM_ELEM_CD_GET_INT(f, ss->cd_faceset_offset);
+
+ /* This can run on geometry without a face set assigned, so its ID sign can't be changed to
+ * modify the visibility. Force that geometry to the ID 1 to enable changing the visibility
+ * here. */
+
+ if (fset == SCULPT_FACE_SET_NONE) {
+ fset = 1;
+ }
+
+ if (visible) {
+ fset = abs(fset);
+ }
+ else {
+ fset = -abs(fset);
+ }
+
+ BM_ELEM_CD_SET_INT(f, ss->cd_faceset_offset, fset);
+ }
break;
+ }
}
}
-bool SCULPT_vertex_any_face_set_visible_get(SculptSession *ss, int index)
+bool SCULPT_vertex_any_face_set_visible_get(SculptSession *ss, SculptVertRef index)
{
switch (BKE_pbvh_type(ss->pbvh)) {
case PBVH_FACES: {
- MeshElemMap *vert_map = &ss->pmap[index];
- for (int j = 0; j < ss->pmap[index].count; j++) {
+ MeshElemMap *vert_map = &ss->pmap[index.i];
+ for (int j = 0; j < ss->pmap[index.i].count; j++) {
if (ss->face_sets[vert_map->indices[j]] > 0) {
return true;
}
}
return false;
}
- case PBVH_BMESH:
- return true;
+ case PBVH_BMESH: {
+ BMIter iter;
+ BMLoop *l;
+ BMVert *v = (BMVert *)index.i;
+
+ BM_ITER_ELEM (l, &iter, v, BM_LOOPS_OF_VERT) {
+ int fset = BM_ELEM_CD_GET_INT(l->f, ss->cd_faceset_offset);
+ if (fset >= 0) {
+ return true;
+ }
+ }
+
+ return false;
+ }
case PBVH_GRIDS:
return true;
}
return true;
}
-bool SCULPT_vertex_all_face_sets_visible_get(const SculptSession *ss, int index)
+bool SCULPT_vertex_all_face_sets_visible_get(const SculptSession *ss, SculptVertRef index)
{
switch (BKE_pbvh_type(ss->pbvh)) {
case PBVH_FACES: {
- MeshElemMap *vert_map = &ss->pmap[index];
- for (int j = 0; j < ss->pmap[index].count; j++) {
+ MeshElemMap *vert_map = &ss->pmap[index.i];
+ for (int j = 0; j < ss->pmap[index.i].count; j++) {
if (ss->face_sets[vert_map->indices[j]] < 0) {
return false;
}
}
return true;
}
- case PBVH_BMESH:
+ case PBVH_BMESH: {
+ BMIter iter;
+ BMLoop *l;
+ BMVert *v = (BMVert *)index.i;
+
+ BM_ITER_ELEM (l, &iter, v, BM_LOOPS_OF_VERT) {
+ int fset = BM_ELEM_CD_GET_INT(l->f, ss->cd_faceset_offset);
+ if (fset < 0) {
+ return false;
+ }
+ }
+
return true;
+ }
case PBVH_GRIDS: {
const CCGKey *key = BKE_pbvh_get_grid_key(ss->pbvh);
- const int grid_index = index / key->grid_area;
+ const int grid_index = index.i / key->grid_area;
const int face_index = BKE_subdiv_ccg_grid_to_face_index(ss->subdiv_ccg, grid_index);
return ss->face_sets[face_index] > 0;
}
@@ -491,22 +604,34 @@ bool SCULPT_vertex_all_face_sets_visible_get(const SculptSession *ss, int index)
return true;
}
-void SCULPT_vertex_face_set_set(SculptSession *ss, int index, int face_set)
+void SCULPT_vertex_face_set_set(SculptSession *ss, SculptVertRef index, int face_set)
{
switch (BKE_pbvh_type(ss->pbvh)) {
case PBVH_FACES: {
- MeshElemMap *vert_map = &ss->pmap[index];
- for (int j = 0; j < ss->pmap[index].count; j++) {
+ MeshElemMap *vert_map = &ss->pmap[index.i];
+ for (int j = 0; j < ss->pmap[index.i].count; j++) {
if (ss->face_sets[vert_map->indices[j]] > 0) {
ss->face_sets[vert_map->indices[j]] = abs(face_set);
}
}
} break;
- case PBVH_BMESH:
+ case PBVH_BMESH: {
+ BMIter iter;
+ BMLoop *l;
+ BMVert *v = (BMVert *)index.i;
+
+ BM_ITER_ELEM (l, &iter, v, BM_LOOPS_OF_VERT) {
+ int fset = BM_ELEM_CD_GET_INT(l->f, ss->cd_faceset_offset);
+ if (fset >= 0) {
+ BM_ELEM_CD_SET_INT(l->f, ss->cd_faceset_offset, abs(face_set));
+ }
+ }
+
break;
+ }
case PBVH_GRIDS: {
const CCGKey *key = BKE_pbvh_get_grid_key(ss->pbvh);
- const int grid_index = index / key->grid_area;
+ const int grid_index = index.i / key->grid_area;
const int face_index = BKE_subdiv_ccg_grid_to_face_index(ss->subdiv_ccg, grid_index);
if (ss->face_sets[face_index] > 0) {
ss->face_sets[face_index] = abs(face_set);
@@ -516,24 +641,39 @@ void SCULPT_vertex_face_set_set(SculptSession *ss, int index, int face_set)
}
}
-int SCULPT_vertex_face_set_get(SculptSession *ss, int index)
+int SCULPT_vertex_face_set_get(SculptSession *ss, SculptVertRef index)
{
switch (BKE_pbvh_type(ss->pbvh)) {
case PBVH_FACES: {
- MeshElemMap *vert_map = &ss->pmap[index];
+ MeshElemMap *vert_map = &ss->pmap[index.i];
int face_set = 0;
- for (int i = 0; i < ss->pmap[index].count; i++) {
+ for (int i = 0; i < ss->pmap[index.i].count; i++) {
if (ss->face_sets[vert_map->indices[i]] > face_set) {
face_set = abs(ss->face_sets[vert_map->indices[i]]);
}
}
return face_set;
}
- case PBVH_BMESH:
- return 0;
+ case PBVH_BMESH: {
+ BMIter iter;
+ BMLoop *l;
+ BMVert *v = (BMVert *)index.i;
+ int ret = -1;
+
+ BM_ITER_ELEM (l, &iter, v, BM_LOOPS_OF_VERT) {
+ int fset = BM_ELEM_CD_GET_INT(l->f, ss->cd_faceset_offset);
+ fset = abs(fset);
+
+ if (fset > ret) {
+ ret = fset;
+ }
+ }
+
+ return ret < 0 ? 0 : ret;
+ }
case PBVH_GRIDS: {
const CCGKey *key = BKE_pbvh_get_grid_key(ss->pbvh);
- const int grid_index = index / key->grid_area;
+ const int grid_index = index.i / key->grid_area;
const int face_index = BKE_subdiv_ccg_grid_to_face_index(ss->subdiv_ccg, grid_index);
return ss->face_sets[face_index];
}
@@ -541,23 +681,40 @@ int SCULPT_vertex_face_set_get(SculptSession *ss, int index)
return 0;
}
-bool SCULPT_vertex_has_face_set(SculptSession *ss, int index, int face_set)
+bool SCULPT_vertex_has_face_set(SculptSession *ss, SculptVertRef index, int face_set)
{
switch (BKE_pbvh_type(ss->pbvh)) {
case PBVH_FACES: {
- MeshElemMap *vert_map = &ss->pmap[index];
- for (int i = 0; i < ss->pmap[index].count; i++) {
+ MeshElemMap *vert_map = &ss->pmap[index.i];
+ for (int i = 0; i < ss->pmap[index.i].count; i++) {
if (ss->face_sets[vert_map->indices[i]] == face_set) {
return true;
}
}
return false;
}
- case PBVH_BMESH:
- return true;
+ case PBVH_BMESH: {
+ BMIter iter;
+ BMLoop *l;
+ BMVert *v = (BMVert *)index.i;
+
+ if (ss->cd_faceset_offset == -1) {
+ return false;
+ }
+
+ BM_ITER_ELEM (l, &iter, v, BM_LOOPS_OF_VERT) {
+ BMFace *f = l->f;
+
+ if (abs(BM_ELEM_CD_GET_INT(f, ss->cd_faceset_offset)) == abs(face_set)) {
+ return true;
+ }
+ }
+
+ return false;
+ }
case PBVH_GRIDS: {
const CCGKey *key = BKE_pbvh_get_grid_key(ss->pbvh);
- const int grid_index = index / key->grid_area;
+ const int grid_index = index.i / key->grid_area;
const int face_index = BKE_subdiv_ccg_grid_to_face_index(ss->subdiv_ccg, grid_index);
return ss->face_sets[face_index] == face_set;
}
@@ -579,16 +736,54 @@ void SCULPT_visibility_sync_all_face_sets_to_vertices(Object *ob)
BKE_sculpt_sync_face_sets_visibility_to_grids(mesh, ss->subdiv_ccg);
break;
}
- case PBVH_BMESH:
+ case PBVH_BMESH: {
+ BMIter iter;
+ BMFace *f;
+ BMVert *v;
+
+ BM_ITER_MESH (f, &iter, ss->bm, BM_FACES_OF_MESH) {
+ int fset = BM_ELEM_CD_GET_INT(f, ss->cd_faceset_offset);
+
+ if (fset < 0) {
+ BM_elem_flag_enable(f, BM_ELEM_HIDDEN);
+ }
+ else {
+ BM_elem_flag_disable(f, BM_ELEM_HIDDEN);
+ }
+ }
+
+ BM_ITER_MESH (v, &iter, ss->bm, BM_VERTS_OF_MESH) {
+ BMIter iter2;
+ BMLoop *l;
+
+ int visible = false;
+
+ BM_ITER_ELEM (l, &iter2, v, BM_LOOPS_OF_VERT) {
+ if (!BM_elem_flag_test(l->f, BM_ELEM_HIDDEN)) {
+ visible = true;
+ break;
+ }
+ }
+
+ if (!visible) {
+ BM_elem_flag_enable(v, BM_ELEM_HIDDEN);
+ }
+ else {
+ BM_elem_flag_disable(v, BM_ELEM_HIDDEN);
+ }
+ }
break;
+ }
}
}
static void UNUSED_FUNCTION(sculpt_visibility_sync_vertex_to_face_sets)(SculptSession *ss,
- int index)
+ SculptVertRef vertex)
{
+ int index = (int)vertex.i;
MeshElemMap *vert_map = &ss->pmap[index];
- const bool visible = SCULPT_vertex_visible_get(ss, index);
+ const bool visible = SCULPT_vertex_visible_get(ss, vertex);
+
for (int i = 0; i < ss->pmap[index].count; i++) {
if (visible) {
ss->face_sets[vert_map->indices[i]] = abs(ss->face_sets[vert_map->indices[i]]);
@@ -602,28 +797,66 @@ static void UNUSED_FUNCTION(sculpt_visibility_sync_vertex_to_face_sets)(SculptSe
void SCULPT_visibility_sync_all_vertex_to_face_sets(SculptSession *ss)
{
- if (BKE_pbvh_type(ss->pbvh) == PBVH_FACES) {
- for (int i = 0; i < ss->totfaces; i++) {
- MPoly *poly = &ss->mpoly[i];
- bool poly_visible = true;
- for (int l = 0; l < poly->totloop; l++) {
- MLoop *loop = &ss->mloop[poly->loopstart + l];
- if (!SCULPT_vertex_visible_get(ss, (int)loop->v)) {
- poly_visible = false;
+ switch (BKE_pbvh_type(ss->pbvh)) {
+ case PBVH_FACES: {
+ for (int i = 0; i < ss->totfaces; i++) {
+ MPoly *poly = &ss->mpoly[i];
+ bool poly_visible = true;
+ for (int l = 0; l < poly->totloop; l++) {
+ MLoop *loop = &ss->mloop[poly->loopstart + l];
+ if (!SCULPT_vertex_visible_get(ss, BKE_pbvh_make_vref(loop->v))) {
+ poly_visible = false;
+ }
+ }
+ if (poly_visible) {
+ ss->face_sets[i] = abs(ss->face_sets[i]);
+ }
+ else {
+ ss->face_sets[i] = -abs(ss->face_sets[i]);
}
}
- if (poly_visible) {
- ss->face_sets[i] = abs(ss->face_sets[i]);
+ break;
+ }
+ case PBVH_BMESH: {
+ BMIter iter;
+ BMFace *f;
+
+ if (!ss->bm) {
+ return;
}
- else {
- ss->face_sets[i] = -abs(ss->face_sets[i]);
+
+ BM_ITER_MESH (f, &iter, ss->bm, BM_FACES_OF_MESH) {
+ BMLoop *l = f->l_first;
+ bool visible = true;
+
+ do {
+ if (BM_elem_flag_test(l->v, BM_ELEM_HIDDEN)) {
+ visible = false;
+ break;
+ }
+ l = l->next;
+ } while (l != f->l_first);
+
+ int fset = BM_ELEM_CD_GET_INT(f, ss->cd_faceset_offset);
+ if (visible) {
+ fset = abs(fset);
+ }
+ else {
+ fset = -abs(fset);
+ }
+
+ BM_ELEM_CD_SET_INT(f, ss->cd_faceset_offset, fset);
}
+
+ break;
}
}
}
-static bool sculpt_check_unique_face_set_in_base_mesh(SculptSession *ss, int index)
+static bool sculpt_check_unique_face_set_in_base_mesh(SculptSession *ss, SculptVertRef vertex)
{
+ int index = BKE_pbvh_vertex_index_to_table(ss->pbvh, vertex);
+
MeshElemMap *vert_map = &ss->pmap[index];
int face_set = -1;
for (int i = 0; i < ss->pmap[index].count; i++) {
@@ -671,18 +904,41 @@ static bool sculpt_check_unique_face_set_for_edge_in_base_mesh(SculptSession *ss
return true;
}
-bool SCULPT_vertex_has_unique_face_set(SculptSession *ss, int index)
+bool SCULPT_vertex_has_unique_face_set(SculptSession *ss, SculptVertRef index)
{
switch (BKE_pbvh_type(ss->pbvh)) {
case PBVH_FACES: {
return sculpt_check_unique_face_set_in_base_mesh(ss, index);
}
- case PBVH_BMESH:
- return false;
+ case PBVH_BMESH: {
+ BMIter iter;
+ BMLoop *l;
+ BMVert *v = (BMVert *)index.i;
+ int face_set = 0;
+ bool first = true;
+
+ if (ss->cd_faceset_offset == -1) {
+ return false;
+ }
+
+ BM_ITER_ELEM (l, &iter, v, BM_LOOPS_OF_VERT) {
+ BMFace *f = l->f;
+ int face_set2 = BM_ELEM_CD_GET_INT(f, ss->cd_faceset_offset);
+
+ if (!first && abs(face_set2) != abs(face_set)) {
+ return false;
+ }
+
+ first = false;
+ face_set = face_set2;
+ }
+
+ return !first;
+ }
case PBVH_GRIDS: {
const CCGKey *key = BKE_pbvh_get_grid_key(ss->pbvh);
- const int grid_index = index / key->grid_area;
- const int vertex_index = index - grid_index * key->grid_area;
+ const int grid_index = index.i / key->grid_area;
+ const int vertex_index = index.i - grid_index * key->grid_area;
const SubdivCCGCoord coord = {.grid_index = grid_index,
.x = vertex_index % key->grid_size,
.y = vertex_index / key->grid_size};
@@ -691,7 +947,7 @@ bool SCULPT_vertex_has_unique_face_set(SculptSession *ss, int index)
ss->subdiv_ccg, &coord, ss->mloop, ss->mpoly, &v1, &v2);
switch (adjacency) {
case SUBDIV_CCG_ADJACENT_VERTEX:
- return sculpt_check_unique_face_set_in_base_mesh(ss, v1);
+ return sculpt_check_unique_face_set_in_base_mesh(ss, BKE_pbvh_make_vref(v1));
case SUBDIV_CCG_ADJACENT_EDGE:
return sculpt_check_unique_face_set_for_edge_in_base_mesh(ss, v1, v2);
case SUBDIV_CCG_ADJACENT_NONE:
@@ -716,8 +972,24 @@ int SCULPT_face_set_next_available_get(SculptSession *ss)
next_face_set++;
return next_face_set;
}
- case PBVH_BMESH:
- return 0;
+ case PBVH_BMESH: {
+ int next_face_set = 0;
+ BMIter iter;
+ BMFace *f;
+ if (!ss->cd_faceset_offset) {
+ return 0;
+ }
+
+ BM_ITER_MESH (f, &iter, ss->bm, BM_FACES_OF_MESH) {
+ int fset = abs(BM_ELEM_CD_GET_INT(f, ss->cd_faceset_offset));
+ if (fset > next_face_set) {
+ next_face_set = fset;
+ }
+ }
+
+ next_face_set++;
+ return next_face_set;
+ }
}
return 0;
}
@@ -726,10 +998,12 @@ int SCULPT_face_set_next_available_get(SculptSession *ss)
#define SCULPT_VERTEX_NEIGHBOR_FIXED_CAPACITY 256
-static void sculpt_vertex_neighbor_add(SculptVertexNeighborIter *iter, int neighbor_index)
+static void sculpt_vertex_neighbor_add(SculptVertexNeighborIter *iter,
+ SculptVertRef neighbor,
+ int neighbor_index)
{
for (int i = 0; i < iter->size; i++) {
- if (iter->neighbors[i] == neighbor_index) {
+ if (iter->neighbors[i].i == neighbor.i) {
return;
}
}
@@ -738,51 +1012,61 @@ static void sculpt_vertex_neighbor_add(SculptVertexNeighborIter *iter, int neigh
iter->capacity += SCULPT_VERTEX_NEIGHBOR_FIXED_CAPACITY;
if (iter->neighbors == iter->neighbors_fixed) {
- iter->neighbors = MEM_mallocN(iter->capacity * sizeof(int), "neighbor array");
+ iter->neighbors = MEM_mallocN(iter->capacity * sizeof(SculptVertRef), "neighbor array");
+ iter->neighbor_indices = MEM_mallocN(iter->capacity * sizeof(int), "neighbor array");
memcpy(iter->neighbors, iter->neighbors_fixed, sizeof(int) * iter->size);
}
else {
iter->neighbors = MEM_reallocN_id(
- iter->neighbors, iter->capacity * sizeof(int), "neighbor array");
+ iter->neighbors, iter->capacity * sizeof(SculptVertRef), "neighbor array");
+ iter->neighbor_indices = MEM_reallocN_id(
+ iter->neighbor_indices, iter->capacity * sizeof(int), "neighbor array");
}
}
- iter->neighbors[iter->size] = neighbor_index;
+ iter->neighbors[iter->size] = neighbor;
+ iter->neighbor_indices[iter->size] = neighbor_index;
iter->size++;
}
static void sculpt_vertex_neighbors_get_bmesh(SculptSession *ss,
- int index,
+ SculptVertRef index,
SculptVertexNeighborIter *iter)
{
- BMVert *v = BM_vert_at_index(ss->bm, index);
+ BMVert *v = (BMVert *)index.i;
BMIter liter;
BMLoop *l;
iter->size = 0;
iter->num_duplicates = 0;
iter->capacity = SCULPT_VERTEX_NEIGHBOR_FIXED_CAPACITY;
iter->neighbors = iter->neighbors_fixed;
+ iter->neighbor_indices = iter->neighbor_indices_fixed;
BM_ITER_ELEM (l, &liter, v, BM_LOOPS_OF_VERT) {
const BMVert *adj_v[2] = {l->prev->v, l->next->v};
for (int i = 0; i < ARRAY_SIZE(adj_v); i++) {
const BMVert *v_other = adj_v[i];
- if (BM_elem_index_get(v_other) != (int)index) {
- sculpt_vertex_neighbor_add(iter, BM_elem_index_get(v_other));
+
+ if (v_other != (BMVert *)index.i) {
+ sculpt_vertex_neighbor_add(
+ iter, BKE_pbvh_make_vref((intptr_t)v_other), BM_elem_index_get(v_other));
}
}
}
}
static void sculpt_vertex_neighbors_get_faces(SculptSession *ss,
- int index,
+ SculptVertRef vertex,
SculptVertexNeighborIter *iter)
{
+ int index = BKE_pbvh_vertex_index_to_table(ss->pbvh, vertex);
+
MeshElemMap *vert_map = &ss->pmap[index];
iter->size = 0;
iter->num_duplicates = 0;
iter->capacity = SCULPT_VERTEX_NEIGHBOR_FIXED_CAPACITY;
iter->neighbors = iter->neighbors_fixed;
+ iter->neighbor_indices = iter->neighbor_indices_fixed;
for (int i = 0; i < ss->pmap[index].count; i++) {
const MPoly *p = &ss->mpoly[vert_map->indices[i]];
@@ -790,7 +1074,7 @@ static void sculpt_vertex_neighbors_get_faces(SculptSession *ss,
if (poly_get_adj_loops_from_vert(p, ss->mloop, index, f_adj_v) != -1) {
for (int j = 0; j < ARRAY_SIZE(f_adj_v); j += 1) {
if (f_adj_v[j] != index) {
- sculpt_vertex_neighbor_add(iter, f_adj_v[j]);
+ sculpt_vertex_neighbor_add(iter, BKE_pbvh_make_vref(f_adj_v[j]), f_adj_v[j]);
}
}
}
@@ -798,17 +1082,21 @@ static void sculpt_vertex_neighbors_get_faces(SculptSession *ss,
if (ss->fake_neighbors.use_fake_neighbors) {
BLI_assert(ss->fake_neighbors.fake_neighbor_index != NULL);
- if (ss->fake_neighbors.fake_neighbor_index[index] != FAKE_NEIGHBOR_NONE) {
- sculpt_vertex_neighbor_add(iter, ss->fake_neighbors.fake_neighbor_index[index]);
+ if (ss->fake_neighbors.fake_neighbor_index[index].i != FAKE_NEIGHBOR_NONE) {
+ sculpt_vertex_neighbor_add(iter,
+ ss->fake_neighbors.fake_neighbor_index[index],
+ ss->fake_neighbors.fake_neighbor_index[index].i);
}
}
}
static void sculpt_vertex_neighbors_get_grids(SculptSession *ss,
- const int index,
+ const SculptVertRef vertex,
const bool include_duplicates,
SculptVertexNeighborIter *iter)
{
+ int index = (int)vertex.i;
+
/* TODO: optimize this. We could fill #SculptVertexNeighborIter directly,
* maybe provide coordinate and mask pointers directly rather than converting
* back and forth between #CCGElem and global index. */
@@ -827,17 +1115,21 @@ static void sculpt_vertex_neighbors_get_grids(SculptSession *ss,
iter->num_duplicates = neighbors.num_duplicates;
iter->capacity = SCULPT_VERTEX_NEIGHBOR_FIXED_CAPACITY;
iter->neighbors = iter->neighbors_fixed;
+ iter->neighbor_indices = iter->neighbor_indices_fixed;
for (int i = 0; i < neighbors.size; i++) {
- sculpt_vertex_neighbor_add(iter,
- neighbors.coords[i].grid_index * key->grid_area +
- neighbors.coords[i].y * key->grid_size + neighbors.coords[i].x);
+ int idx = neighbors.coords[i].grid_index * key->grid_area +
+ neighbors.coords[i].y * key->grid_size + neighbors.coords[i].x;
+
+ sculpt_vertex_neighbor_add(iter, BKE_pbvh_make_vref(idx), idx);
}
if (ss->fake_neighbors.use_fake_neighbors) {
BLI_assert(ss->fake_neighbors.fake_neighbor_index != NULL);
- if (ss->fake_neighbors.fake_neighbor_index[index] != FAKE_NEIGHBOR_NONE) {
- sculpt_vertex_neighbor_add(iter, ss->fake_neighbors.fake_neighbor_index[index]);
+ if (ss->fake_neighbors.fake_neighbor_index[index].i != FAKE_NEIGHBOR_NONE) {
+ sculpt_vertex_neighbor_add(iter,
+ ss->fake_neighbors.fake_neighbor_index[index],
+ ss->fake_neighbors.fake_neighbor_index[index].i);
}
}
@@ -847,44 +1139,47 @@ static void sculpt_vertex_neighbors_get_grids(SculptSession *ss,
}
void SCULPT_vertex_neighbors_get(SculptSession *ss,
- const int index,
+ const SculptVertRef vertex,
const bool include_duplicates,
SculptVertexNeighborIter *iter)
{
switch (BKE_pbvh_type(ss->pbvh)) {
case PBVH_FACES:
- sculpt_vertex_neighbors_get_faces(ss, index, iter);
+ sculpt_vertex_neighbors_get_faces(ss, vertex, iter);
return;
case PBVH_BMESH:
- sculpt_vertex_neighbors_get_bmesh(ss, index, iter);
+ sculpt_vertex_neighbors_get_bmesh(ss, vertex, iter);
return;
case PBVH_GRIDS:
- sculpt_vertex_neighbors_get_grids(ss, index, include_duplicates, iter);
+ sculpt_vertex_neighbors_get_grids(ss, vertex, include_duplicates, iter);
return;
}
}
-static bool sculpt_check_boundary_vertex_in_base_mesh(const SculptSession *ss, const int index)
+static bool sculpt_check_boundary_vertex_in_base_mesh(const SculptSession *ss,
+ const SculptVertRef index)
{
BLI_assert(ss->vertex_info.boundary);
- return BLI_BITMAP_TEST(ss->vertex_info.boundary, index);
+ return BLI_BITMAP_TEST(ss->vertex_info.boundary,
+ BKE_pbvh_vertex_index_to_table(ss->pbvh, index));
}
-bool SCULPT_vertex_is_boundary(const SculptSession *ss, const int index)
+bool SCULPT_vertex_is_boundary(const SculptSession *ss, const SculptVertRef vertex)
{
switch (BKE_pbvh_type(ss->pbvh)) {
case PBVH_FACES: {
- if (!SCULPT_vertex_all_face_sets_visible_get(ss, index)) {
+ if (!SCULPT_vertex_all_face_sets_visible_get(ss, vertex)) {
return true;
}
- return sculpt_check_boundary_vertex_in_base_mesh(ss, index);
+ return sculpt_check_boundary_vertex_in_base_mesh(ss, vertex);
}
case PBVH_BMESH: {
- BMVert *v = BM_vert_at_index(ss->bm, index);
+ BMVert *v = (BMVert *)vertex.i;
return BM_vert_is_boundary(v);
}
case PBVH_GRIDS: {
+ int index = (int)vertex.i;
const CCGKey *key = BKE_pbvh_get_grid_key(ss->pbvh);
const int grid_index = index / key->grid_area;
const int vertex_index = index - grid_index * key->grid_area;
@@ -896,10 +1191,10 @@ bool SCULPT_vertex_is_boundary(const SculptSession *ss, const int index)
ss->subdiv_ccg, &coord, ss->mloop, ss->mpoly, &v1, &v2);
switch (adjacency) {
case SUBDIV_CCG_ADJACENT_VERTEX:
- return sculpt_check_boundary_vertex_in_base_mesh(ss, v1);
+ return sculpt_check_boundary_vertex_in_base_mesh(ss, BKE_pbvh_make_vref(v1));
case SUBDIV_CCG_ADJACENT_EDGE:
- return sculpt_check_boundary_vertex_in_base_mesh(ss, v1) &&
- sculpt_check_boundary_vertex_in_base_mesh(ss, v2);
+ return sculpt_check_boundary_vertex_in_base_mesh(ss, BKE_pbvh_make_vref(v1)) &&
+ sculpt_check_boundary_vertex_in_base_mesh(ss, BKE_pbvh_make_vref(v2));
case SUBDIV_CCG_ADJACENT_NONE:
return false;
}
@@ -963,6 +1258,7 @@ bool SCULPT_check_vertex_pivot_symmetry(const float vco[3], const float pco[3],
typedef struct NearestVertexTLSData {
int nearest_vertex_index;
+ SculptVertRef nearest_vertex;
float nearest_vertex_distance_squared;
} NearestVertexTLSData;
@@ -981,6 +1277,7 @@ static void do_nearest_vertex_get_task_cb(void *__restrict userdata,
if (distance_squared < nvtd->nearest_vertex_distance_squared &&
distance_squared < data->max_distance_squared) {
nvtd->nearest_vertex_index = vd.index;
+ nvtd->nearest_vertex = vd.vertex;
nvtd->nearest_vertex_distance_squared = distance_squared;
}
}
@@ -995,15 +1292,17 @@ static void nearest_vertex_get_reduce(const void *__restrict UNUSED(userdata),
NearestVertexTLSData *nvtd = chunk;
if (join->nearest_vertex_index == -1) {
join->nearest_vertex_index = nvtd->nearest_vertex_index;
+ join->nearest_vertex = nvtd->nearest_vertex;
join->nearest_vertex_distance_squared = nvtd->nearest_vertex_distance_squared;
}
else if (nvtd->nearest_vertex_distance_squared < join->nearest_vertex_distance_squared) {
join->nearest_vertex_index = nvtd->nearest_vertex_index;
+ join->nearest_vertex = nvtd->nearest_vertex;
join->nearest_vertex_distance_squared = nvtd->nearest_vertex_distance_squared;
}
}
-int SCULPT_nearest_vertex_get(
+SculptVertRef SCULPT_nearest_vertex_get(
Sculpt *sd, Object *ob, const float co[3], float max_distance, bool use_original)
{
SculptSession *ss = ob->sculpt;
@@ -1018,7 +1317,7 @@ int SCULPT_nearest_vertex_get(
};
BKE_pbvh_search_gather(ss->pbvh, SCULPT_search_sphere_cb, &data, &nodes, &totnode);
if (totnode == 0) {
- return -1;
+ return BKE_pbvh_make_vref(-1);
}
SculptThreadedTaskData task_data = {
@@ -1031,6 +1330,7 @@ int SCULPT_nearest_vertex_get(
copy_v3_v3(task_data.nearest_vertex_search_co, co);
NearestVertexTLSData nvtd;
nvtd.nearest_vertex_index = -1;
+ nvtd.nearest_vertex.i = -1;
nvtd.nearest_vertex_distance_squared = FLT_MAX;
TaskParallelSettings settings;
@@ -1042,7 +1342,7 @@ int SCULPT_nearest_vertex_get(
MEM_SAFE_FREE(nodes);
- return nvtd.nearest_vertex_index;
+ return nvtd.nearest_vertex;
}
bool SCULPT_is_symmetry_iteration_valid(char i, char symm)
@@ -1092,23 +1392,27 @@ void SCULPT_floodfill_init(SculptSession *ss, SculptFloodFill *flood)
int vertex_count = SCULPT_vertex_count_get(ss);
SCULPT_vertex_random_access_ensure(ss);
- flood->queue = BLI_gsqueue_new(sizeof(int));
+ flood->queue = BLI_gsqueue_new(sizeof(SculptVertRef));
flood->visited_vertices = BLI_BITMAP_NEW(vertex_count, "visited vertices");
}
-void SCULPT_floodfill_add_initial(SculptFloodFill *flood, int index)
+void SCULPT_floodfill_add_initial(SculptFloodFill *flood, SculptVertRef index)
{
BLI_gsqueue_push(flood->queue, &index);
}
-void SCULPT_floodfill_add_initial_with_symmetry(
- Sculpt *sd, Object *ob, SculptSession *ss, SculptFloodFill *flood, int index, float radius)
+void SCULPT_floodfill_add_initial_with_symmetry(Sculpt *sd,
+ Object *ob,
+ SculptSession *ss,
+ SculptFloodFill *flood,
+ SculptVertRef index,
+ float radius)
{
/* Add active vertex and symmetric vertices to the queue. */
const char symm = SCULPT_mesh_symmetry_xyz_get(ob);
for (char i = 0; i <= symm; ++i) {
if (SCULPT_is_symmetry_iteration_valid(i, symm)) {
- int v = -1;
+ SculptVertRef v = BKE_pbvh_make_vref(-1);
if (i == 0) {
v = index;
}
@@ -1118,7 +1422,7 @@ void SCULPT_floodfill_add_initial_with_symmetry(
flip_v3_v3(location, SCULPT_vertex_co_get(ss, index), i);
v = SCULPT_nearest_vertex_get(sd, ob, location, radius_squared, false);
}
- if (v != -1) {
+ if (v.i != -1) {
SCULPT_floodfill_add_initial(flood, v);
}
}
@@ -1132,7 +1436,7 @@ void SCULPT_floodfill_add_active(
const char symm = SCULPT_mesh_symmetry_xyz_get(ob);
for (char i = 0; i <= symm; ++i) {
if (SCULPT_is_symmetry_iteration_valid(i, symm)) {
- int v = -1;
+ SculptVertRef v = BKE_pbvh_make_vref(-1);
if (i == 0) {
v = SCULPT_active_vertex_get(ss);
}
@@ -1142,27 +1446,33 @@ void SCULPT_floodfill_add_active(
flip_v3_v3(location, SCULPT_active_vertex_co_get(ss), i);
v = SCULPT_nearest_vertex_get(sd, ob, location, radius_squared, false);
}
- if (v != -1) {
+ if (v.i != -1) {
SCULPT_floodfill_add_initial(flood, v);
}
}
}
}
-void SCULPT_floodfill_execute(
- SculptSession *ss,
- SculptFloodFill *flood,
- bool (*func)(SculptSession *ss, int from_v, int to_v, bool is_duplicate, void *userdata),
- void *userdata)
+void SCULPT_floodfill_execute(SculptSession *ss,
+ SculptFloodFill *flood,
+ bool (*func)(SculptSession *ss,
+ SculptVertRef from_v,
+ SculptVertRef to_v,
+ bool is_duplicate,
+ void *userdata),
+ void *userdata)
{
while (!BLI_gsqueue_is_empty(flood->queue)) {
- int from_v;
+ SculptVertRef from_v;
BLI_gsqueue_pop(flood->queue, &from_v);
SculptVertexNeighborIter ni;
SCULPT_VERTEX_DUPLICATES_AND_NEIGHBORS_ITER_BEGIN (ss, from_v, ni) {
- const int to_v = ni.index;
- if (!BLI_BITMAP_TEST(flood->visited_vertices, to_v) && SCULPT_vertex_visible_get(ss, to_v)) {
- BLI_BITMAP_ENABLE(flood->visited_vertices, to_v);
+ const SculptVertRef to_v = ni.vertex;
+ const int to_v_i = ni.index;
+
+ if (!BLI_BITMAP_TEST(flood->visited_vertices, to_v_i) &&
+ SCULPT_vertex_visible_get(ss, to_v)) {
+ BLI_BITMAP_ENABLE(flood->visited_vertices, to_v_i);
if (func(ss, from_v, to_v, ni.is_duplicate, userdata)) {
BLI_gsqueue_push(flood->queue, &to_v);
@@ -1217,6 +1527,8 @@ static bool sculpt_tool_needs_original(const char sculpt_tool)
SCULPT_TOOL_DRAW_SHARP,
SCULPT_TOOL_ELASTIC_DEFORM,
SCULPT_TOOL_SMOOTH,
+ SCULPT_TOOL_PAINT,
+ SCULPT_TOOL_VCOL_BOUNDARY,
SCULPT_TOOL_BOUNDARY,
SCULPT_TOOL_POSE);
}
@@ -1289,10 +1601,14 @@ void SCULPT_orig_vert_data_unode_init(SculptOrigVertData *data, Object *ob, Scul
memset(data, 0, sizeof(*data));
data->unode = unode;
+ data->pbvh = ss->pbvh;
+ data->ss = ss;
+
if (bm) {
data->bm_log = ss->bm_log;
}
else {
+ data->datatype = data->unode->type;
data->coords = data->unode->co;
data->normals = data->unode->no;
data->vmasks = data->unode->mask;
@@ -1304,11 +1620,21 @@ void SCULPT_orig_vert_data_unode_init(SculptOrigVertData *data, Object *ob, Scul
* Initialize a #SculptOrigVertData for accessing original vertex data;
* handles #BMesh, #Mesh, and multi-resolution.
*/
-void SCULPT_orig_vert_data_init(SculptOrigVertData *data, Object *ob, PBVHNode *node)
+void SCULPT_orig_vert_data_init(SculptOrigVertData *data,
+ Object *ob,
+ PBVHNode *node,
+ SculptUndoType type)
{
- SculptUndoNode *unode;
- unode = SCULPT_undo_push_node(ob, node, SCULPT_UNDO_COORDS);
+ SculptUndoNode *unode = NULL;
+ data->ss = ob->sculpt;
+
+ /*do not allocate an undo node for bmesh pbvh*/
+ if (!ob->sculpt->bm) {
+ unode = SCULPT_undo_push_node(ob, node, type);
+ }
+
SCULPT_orig_vert_data_unode_init(data, ob, unode);
+ data->datatype = type;
}
/**
@@ -1316,19 +1642,30 @@ void SCULPT_orig_vert_data_init(SculptOrigVertData *data, Object *ob, PBVHNode *
*/
void SCULPT_orig_vert_data_update(SculptOrigVertData *orig_data, PBVHVertexIter *iter)
{
- if (orig_data->unode->type == SCULPT_UNDO_COORDS) {
+ if (orig_data->datatype == SCULPT_UNDO_COORDS) {
if (orig_data->bm_log) {
- BM_log_original_vert_data(orig_data->bm_log, iter->bm_vert, &orig_data->co, &orig_data->no);
+ orig_data->co = BM_ELEM_CD_GET_VOID_P(iter->bm_vert, orig_data->ss->cd_origco_offset);
+
+ float *no = BM_ELEM_CD_GET_VOID_P(iter->bm_vert, orig_data->ss->cd_origno_offset);
+ normal_float_to_short_v3(orig_data->_no, no);
+ orig_data->no = orig_data->_no;
+
+ orig_data->col = BM_ELEM_CD_GET_VOID_P(iter->bm_vert, orig_data->ss->cd_origvcol_offset);
}
else {
orig_data->co = orig_data->coords[iter->i];
orig_data->no = orig_data->normals[iter->i];
}
}
- else if (orig_data->unode->type == SCULPT_UNDO_COLOR) {
- orig_data->col = orig_data->colors[iter->i];
+ else if (orig_data->datatype == SCULPT_UNDO_COLOR) {
+ if (orig_data->bm_log) {
+ orig_data->col = BM_ELEM_CD_GET_VOID_P(iter->bm_vert, orig_data->ss->cd_origvcol_offset);
+ }
+ else {
+ orig_data->col = orig_data->colors[iter->i];
+ }
}
- else if (orig_data->unode->type == SCULPT_UNDO_MASK) {
+ else if (orig_data->datatype == SCULPT_UNDO_MASK) {
if (orig_data->bm_log) {
orig_data->mask = BM_log_original_mask(orig_data->bm_log, iter->bm_vert);
}
@@ -1482,7 +1819,7 @@ static void paint_mesh_restore_co_task_cb(void *__restrict userdata,
unode = SCULPT_undo_push_node(data->ob, data->nodes[n], type);
}
else {
- unode = SCULPT_undo_get_node(data->nodes[n]);
+ unode = SCULPT_undo_get_node(data->nodes[n], type);
}
if (unode) {
@@ -2053,10 +2390,14 @@ static void calc_area_normal_and_center_task_cb(void *__restrict userdata,
if (use_original) {
if (unode->bm_entry) {
const float *temp_co;
- const short *temp_no_s;
- BM_log_original_vert_data(ss->bm_log, vd.bm_vert, &temp_co, &temp_no_s);
+ const float *temp_no;
+ BKE_pbvh_bmesh_update_origvert(ss->pbvh, vd.bm_vert, &temp_co, &temp_no, NULL);
+ if (temp_no) {
+ normal_float_to_short_v3(no_s, temp_no);
+ }
+ // BM_log_original_vert_data(ss->bm, ss->bm_log, vd.bm_vert, &temp_co, &temp_no_s,
+ // false);
copy_v3_v3(co, temp_co);
- copy_v3_v3_short(no_s, temp_no_s);
}
else {
copy_v3_v3(co, unode->co[vd.i]);
@@ -2414,6 +2755,8 @@ static float brush_strength(const Sculpt *sd,
case SCULPT_TOOL_SMOOTH:
return flip * alpha * pressure * feather;
+ case SCULPT_TOOL_VCOL_BOUNDARY:
+ return flip * alpha * pressure * feather;
case SCULPT_TOOL_PINCH:
if (flip > 0.0f) {
@@ -2457,7 +2800,7 @@ float SCULPT_brush_strength_factor(SculptSession *ss,
const short vno[3],
const float fno[3],
const float mask,
- const int vertex_index,
+ const SculptVertRef vertex_index,
const int thread_id)
{
StrokeCache *cache = ss->cache;
@@ -2863,10 +3206,10 @@ typedef struct {
float depth;
bool original;
- int active_vertex_index;
+ SculptVertRef active_vertex_index;
float *face_normal;
- int active_face_grid_index;
+ SculptFaceRef active_face_grid_index;
struct IsectRayPrecalc isect_precalc;
} SculptRaycastData;
@@ -2917,7 +3260,7 @@ static void do_topology_rake_bmesh_task_cb_ex(void *__restrict userdata,
const float fade =
bstrength *
SCULPT_brush_strength_factor(
- ss, brush, vd.co, sqrtf(test.dist), vd.no, vd.fno, *vd.mask, vd.index, thread_id) *
+ ss, brush, vd.co, sqrtf(test.dist), vd.no, vd.fno, *vd.mask, vd.vertex, thread_id) *
ss->cache->pressure;
float avg[3], val[3];
@@ -2987,7 +3330,7 @@ static void do_mask_brush_draw_task_cb_ex(void *__restrict userdata,
{
if (sculpt_brush_test_sq_fn(&test, vd.co)) {
const float fade = SCULPT_brush_strength_factor(
- ss, brush, vd.co, sqrtf(test.dist), vd.no, vd.fno, 0.0f, vd.index, thread_id);
+ ss, brush, vd.co, sqrtf(test.dist), vd.no, vd.fno, 0.0f, vd.vertex, thread_id);
if (bstrength > 0.0f) {
(*vd.mask) += fade * bstrength * (1.0f - *vd.mask);
@@ -3068,12 +3411,12 @@ static void do_displacement_eraser_brush_task_cb_ex(void *__restrict userdata,
vd.no,
vd.fno,
vd.mask ? *vd.mask : 0.0f,
- vd.index,
+ vd.vertex,
thread_id);
float limit_co[3];
float disp[3];
- SCULPT_vertex_limit_surface_get(ss, vd.index, limit_co);
+ SCULPT_vertex_limit_surface_get(ss, vd.vertex, limit_co);
sub_v3_v3v3(disp, limit_co, vd.co);
mul_v3_v3fl(proxy[vd.i], disp, fade);
@@ -3135,7 +3478,7 @@ static void do_displacement_smear_brush_task_cb_ex(void *__restrict userdata,
vd.no,
vd.fno,
vd.mask ? *vd.mask : 0.0f,
- vd.index,
+ vd.vertex,
thread_id);
float current_disp[3];
@@ -3162,11 +3505,11 @@ static void do_displacement_smear_brush_task_cb_ex(void *__restrict userdata,
float weights_accum = 1.0f;
SculptVertexNeighborIter ni;
- SCULPT_VERTEX_NEIGHBORS_ITER_BEGIN (ss, vd.index, ni) {
+ SCULPT_VERTEX_NEIGHBORS_ITER_BEGIN (ss, vd.vertex, ni) {
float vertex_disp[3];
float vertex_disp_norm[3];
float neighbor_limit_co[3];
- SCULPT_vertex_limit_surface_get(ss, ni.index, neighbor_limit_co);
+ SCULPT_vertex_limit_surface_get(ss, ni.vertex, neighbor_limit_co);
sub_v3_v3v3(vertex_disp,
ss->cache->limit_surface_co[ni.index],
ss->cache->limit_surface_co[vd.index]);
@@ -3204,7 +3547,7 @@ static void do_displacement_smear_store_prev_disp_task_cb_ex(
BKE_pbvh_vertex_iter_begin(ss->pbvh, data->nodes[n], vd, PBVH_ITER_UNIQUE)
{
sub_v3_v3v3(ss->cache->prev_displacement[vd.index],
- SCULPT_vertex_co_get(ss, vd.index),
+ SCULPT_vertex_co_get(ss, vd.vertex),
ss->cache->limit_surface_co[vd.index]);
}
BKE_pbvh_vertex_iter_end;
@@ -3216,16 +3559,20 @@ static void do_displacement_smear_brush(Sculpt *sd, Object *ob, PBVHNode **nodes
SculptSession *ss = ob->sculpt;
BKE_curvemapping_init(brush->curve);
+ SCULPT_vertex_random_access_ensure(ss);
const int totvert = SCULPT_vertex_count_get(ss);
if (!ss->cache->prev_displacement) {
ss->cache->prev_displacement = MEM_malloc_arrayN(
totvert, sizeof(float[3]), "prev displacement");
ss->cache->limit_surface_co = MEM_malloc_arrayN(totvert, sizeof(float[3]), "limit surface co");
+
for (int i = 0; i < totvert; i++) {
- SCULPT_vertex_limit_surface_get(ss, i, ss->cache->limit_surface_co[i]);
+ SculptVertRef vref = BKE_pbvh_table_index_to_vertex(ss->pbvh, i);
+
+ SCULPT_vertex_limit_surface_get(ss, vref, ss->cache->limit_surface_co[i]);
sub_v3_v3v3(ss->cache->prev_displacement[i],
- SCULPT_vertex_co_get(ss, i),
+ SCULPT_vertex_co_get(ss, vref),
ss->cache->limit_surface_co[i]);
}
}
@@ -3276,7 +3623,7 @@ static void do_draw_brush_task_cb_ex(void *__restrict userdata,
vd.no,
vd.fno,
vd.mask ? *vd.mask : 0.0f,
- vd.index,
+ vd.vertex,
thread_id);
mul_v3_v3fl(proxy[vd.i], offset, fade);
@@ -3334,7 +3681,7 @@ static void do_draw_sharp_brush_task_cb_ex(void *__restrict userdata,
SculptOrigVertData orig_data;
float(*proxy)[3];
- SCULPT_orig_vert_data_init(&orig_data, data->ob, data->nodes[n]);
+ SCULPT_orig_vert_data_init(&orig_data, data->ob, data->nodes[n], SCULPT_UNDO_COORDS);
proxy = BKE_pbvh_node_add_proxy(ss->pbvh, data->nodes[n])->co;
@@ -3355,7 +3702,7 @@ static void do_draw_sharp_brush_task_cb_ex(void *__restrict userdata,
orig_data.no,
NULL,
vd.mask ? *vd.mask : 0.0f,
- vd.index,
+ vd.vertex,
thread_id);
mul_v3_v3fl(proxy[vd.i], offset, fade);
@@ -3416,7 +3763,7 @@ static void do_topology_slide_task_cb_ex(void *__restrict userdata,
SculptOrigVertData orig_data;
float(*proxy)[3];
- SCULPT_orig_vert_data_init(&orig_data, data->ob, data->nodes[n]);
+ SCULPT_orig_vert_data_init(&orig_data, data->ob, data->nodes[n], SCULPT_UNDO_COORDS);
proxy = BKE_pbvh_node_add_proxy(ss->pbvh, data->nodes[n])->co;
@@ -3436,7 +3783,7 @@ static void do_topology_slide_task_cb_ex(void *__restrict userdata,
orig_data.no,
NULL,
vd.mask ? *vd.mask : 0.0f,
- vd.index,
+ vd.vertex,
thread_id);
float current_disp[3];
float current_disp_norm[3];
@@ -3458,10 +3805,10 @@ static void do_topology_slide_task_cb_ex(void *__restrict userdata,
mul_v3_v3fl(current_disp, current_disp_norm, ss->cache->bstrength);
SculptVertexNeighborIter ni;
- SCULPT_VERTEX_NEIGHBORS_ITER_BEGIN (ss, vd.index, ni) {
+ SCULPT_VERTEX_NEIGHBORS_ITER_BEGIN (ss, vd.vertex, ni) {
float vertex_disp[3];
float vertex_disp_norm[3];
- sub_v3_v3v3(vertex_disp, SCULPT_vertex_co_get(ss, ni.index), vd.co);
+ sub_v3_v3v3(vertex_disp, SCULPT_vertex_co_get(ss, ni.vertex), vd.co);
normalize_v3_v3(vertex_disp_norm, vertex_disp);
if (dot_v3v3(current_disp_norm, vertex_disp_norm) > 0.0f) {
madd_v3_v3fl(final_disp, vertex_disp_norm, dot_v3v3(current_disp, vertex_disp));
@@ -3492,30 +3839,30 @@ void SCULPT_relax_vertex(SculptSession *ss,
int neighbor_count = 0;
zero_v3(smooth_pos);
zero_v3(boundary_normal);
- const bool is_boundary = SCULPT_vertex_is_boundary(ss, vd->index);
+ const bool is_boundary = SCULPT_vertex_is_boundary(ss, vd->vertex);
SculptVertexNeighborIter ni;
- SCULPT_VERTEX_NEIGHBORS_ITER_BEGIN (ss, vd->index, ni) {
+ SCULPT_VERTEX_NEIGHBORS_ITER_BEGIN (ss, vd->vertex, ni) {
neighbor_count++;
if (!filter_boundary_face_sets ||
- (filter_boundary_face_sets && !SCULPT_vertex_has_unique_face_set(ss, ni.index))) {
+ (filter_boundary_face_sets && !SCULPT_vertex_has_unique_face_set(ss, ni.vertex))) {
/* When the vertex to relax is boundary, use only connected boundary vertices for the average
* position. */
if (is_boundary) {
- if (SCULPT_vertex_is_boundary(ss, ni.index)) {
- add_v3_v3(smooth_pos, SCULPT_vertex_co_get(ss, ni.index));
+ if (SCULPT_vertex_is_boundary(ss, ni.vertex)) {
+ add_v3_v3(smooth_pos, SCULPT_vertex_co_get(ss, ni.vertex));
avg_count++;
/* Calculate a normal for the constraint plane using the edges of the boundary. */
float to_neighbor[3];
- sub_v3_v3v3(to_neighbor, SCULPT_vertex_co_get(ss, ni.index), vd->co);
+ sub_v3_v3v3(to_neighbor, SCULPT_vertex_co_get(ss, ni.vertex), vd->co);
normalize_v3(to_neighbor);
add_v3_v3(boundary_normal, to_neighbor);
}
}
else {
- add_v3_v3(smooth_pos, SCULPT_vertex_co_get(ss, ni.index));
+ add_v3_v3(smooth_pos, SCULPT_vertex_co_get(ss, ni.vertex));
avg_count++;
}
}
@@ -3544,7 +3891,7 @@ void SCULPT_relax_vertex(SculptSession *ss,
normalize_v3_v3(vno, boundary_normal);
}
else {
- SCULPT_vertex_normal_get(ss, vd->index, vno);
+ SCULPT_vertex_normal_get(ss, vd->vertex, vno);
}
if (is_zero_v3(vno)) {
@@ -3572,7 +3919,7 @@ static void do_topology_relax_task_cb_ex(void *__restrict userdata,
PBVHVertexIter vd;
SculptOrigVertData orig_data;
- SCULPT_orig_vert_data_init(&orig_data, data->ob, data->nodes[n]);
+ SCULPT_orig_vert_data_init(&orig_data, data->ob, data->nodes[n], SCULPT_UNDO_COORDS);
BKE_pbvh_node_add_proxy(ss->pbvh, data->nodes[n]);
@@ -3592,7 +3939,7 @@ static void do_topology_relax_task_cb_ex(void *__restrict userdata,
orig_data.no,
NULL,
vd.mask ? *vd.mask : 0.0f,
- vd.index,
+ vd.vertex,
thread_id);
SCULPT_relax_vertex(ss, &vd, fade * bstrength, false, vd.co);
@@ -3758,7 +4105,7 @@ static void do_crease_brush_task_cb_ex(void *__restrict userdata,
vd.no,
vd.fno,
vd.mask ? *vd.mask : 0.0f,
- vd.index,
+ vd.vertex,
thread_id);
float val1[3];
float val2[3];
@@ -3874,7 +4221,7 @@ static void do_pinch_brush_task_cb_ex(void *__restrict userdata,
vd.no,
vd.fno,
vd.mask ? *vd.mask : 0.0f,
- vd.index,
+ vd.vertex,
thread_id);
float disp_center[3];
float x_disp[3];
@@ -3967,7 +4314,7 @@ static void do_grab_brush_task_cb_ex(void *__restrict userdata,
float(*proxy)[3];
const float bstrength = ss->cache->bstrength;
- SCULPT_orig_vert_data_init(&orig_data, data->ob, data->nodes[n]);
+ SCULPT_orig_vert_data_init(&orig_data, data->ob, data->nodes[n], SCULPT_UNDO_COORDS);
proxy = BKE_pbvh_node_add_proxy(ss->pbvh, data->nodes[n])->co;
@@ -3990,7 +4337,7 @@ static void do_grab_brush_task_cb_ex(void *__restrict userdata,
orig_data.no,
NULL,
vd.mask ? *vd.mask : 0.0f,
- vd.index,
+ vd.vertex,
thread_id);
if (grab_silhouette) {
@@ -4055,7 +4402,7 @@ static void do_elastic_deform_brush_task_cb_ex(void *__restrict userdata,
const float bstrength = ss->cache->bstrength;
- SCULPT_orig_vert_data_init(&orig_data, data->ob, data->nodes[n]);
+ SCULPT_orig_vert_data_init(&orig_data, data->ob, data->nodes[n], SCULPT_UNDO_COORDS);
proxy = BKE_pbvh_node_add_proxy(ss->pbvh, data->nodes[n])->co;
@@ -4112,7 +4459,7 @@ static void do_elastic_deform_brush_task_cb_ex(void *__restrict userdata,
mul_v3_fl(final_disp, 1.0f - *vd.mask);
}
- mul_v3_fl(final_disp, SCULPT_automasking_factor_get(ss->cache->automasking, ss, vd.index));
+ mul_v3_fl(final_disp, SCULPT_automasking_factor_get(ss->cache->automasking, ss, vd.vertex));
copy_v3_v3(proxy[vd.i], final_disp);
@@ -4144,6 +4491,9 @@ static void do_elastic_deform_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, in
};
TaskParallelSettings settings;
+
+ SCULPT_vertex_random_access_ensure(ss);
+
BKE_pbvh_parallel_range_settings(&settings, true, totnode);
BLI_task_parallel_range(0, totnode, &data, do_elastic_deform_brush_task_cb_ex, &settings);
}
@@ -4318,7 +4668,7 @@ static void do_nudge_brush_task_cb_ex(void *__restrict userdata,
vd.no,
vd.fno,
vd.mask ? *vd.mask : 0.0f,
- vd.index,
+ vd.vertex,
thread_id);
mul_v3_v3fl(proxy[vd.i], cono, fade);
@@ -4403,7 +4753,7 @@ static void do_snake_hook_brush_task_cb_ex(void *__restrict userdata,
vd.no,
vd.fno,
vd.mask ? *vd.mask : 0.0f,
- vd.index,
+ vd.vertex,
thread_id);
}
@@ -4451,7 +4801,7 @@ static void do_snake_hook_brush_task_cb_ex(void *__restrict userdata,
if (vd.mask) {
mul_v3_fl(disp, 1.0f - *vd.mask);
}
- mul_v3_fl(disp, SCULPT_automasking_factor_get(ss->cache->automasking, ss, vd.index));
+ mul_v3_fl(disp, SCULPT_automasking_factor_get(ss->cache->automasking, ss, vd.vertex));
copy_v3_v3(proxy[vd.i], disp);
}
@@ -4515,7 +4865,7 @@ static void do_thumb_brush_task_cb_ex(void *__restrict userdata,
float(*proxy)[3];
const float bstrength = ss->cache->bstrength;
- SCULPT_orig_vert_data_init(&orig_data, data->ob, data->nodes[n]);
+ SCULPT_orig_vert_data_init(&orig_data, data->ob, data->nodes[n], SCULPT_UNDO_COORDS);
proxy = BKE_pbvh_node_add_proxy(ss->pbvh, data->nodes[n])->co;
@@ -4536,7 +4886,7 @@ static void do_thumb_brush_task_cb_ex(void *__restrict userdata,
orig_data.no,
NULL,
vd.mask ? *vd.mask : 0.0f,
- vd.index,
+ vd.vertex,
thread_id);
mul_v3_v3fl(proxy[vd.i], cono, fade);
@@ -4588,7 +4938,7 @@ static void do_rotate_brush_task_cb_ex(void *__restrict userdata,
float(*proxy)[3];
const float bstrength = ss->cache->bstrength;
- SCULPT_orig_vert_data_init(&orig_data, data->ob, data->nodes[n]);
+ SCULPT_orig_vert_data_init(&orig_data, data->ob, data->nodes[n], SCULPT_UNDO_COORDS);
proxy = BKE_pbvh_node_add_proxy(ss->pbvh, data->nodes[n])->co;
@@ -4610,7 +4960,7 @@ static void do_rotate_brush_task_cb_ex(void *__restrict userdata,
orig_data.no,
NULL,
vd.mask ? *vd.mask : 0.0f,
- vd.index,
+ vd.vertex,
thread_id);
sub_v3_v3v3(vec, orig_data.co, ss->cache->location);
@@ -4662,13 +5012,19 @@ static void do_layer_brush_task_cb_ex(void *__restrict userdata,
PBVHVertexIter vd;
SculptOrigVertData orig_data;
const float bstrength = ss->cache->bstrength;
- SCULPT_orig_vert_data_init(&orig_data, data->ob, data->nodes[n]);
+ SCULPT_orig_vert_data_init(&orig_data, data->ob, data->nodes[n], SCULPT_UNDO_COORDS);
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);
+ bool bmeshpbvh = BKE_pbvh_type(ss->pbvh) == PBVH_BMESH;
+ if (bmeshpbvh) {
+ BM_mesh_elem_index_ensure(ss->bm, BM_VERT);
+ // BM_mesh_elem_table_ensure(ss->bm, BM_VERT);
+ }
+
BKE_pbvh_vertex_iter_begin(ss->pbvh, data->nodes[n], vd, PBVH_ITER_UNIQUE)
{
SCULPT_orig_vert_data_update(&orig_data, &vd);
@@ -4681,10 +5037,11 @@ static void do_layer_brush_task_cb_ex(void *__restrict userdata,
vd.no,
vd.fno,
vd.mask ? *vd.mask : 0.0f,
- vd.index,
+ vd.vertex,
thread_id);
const int vi = vd.index;
+
float *disp_factor;
if (use_persistent_base) {
disp_factor = &ss->persistent_base[vi].disp;
@@ -4717,9 +5074,10 @@ static void do_layer_brush_task_cb_ex(void *__restrict userdata,
float normal[3];
if (use_persistent_base) {
- SCULPT_vertex_persistent_normal_get(ss, vi, normal);
+ SCULPT_vertex_persistent_normal_get(ss, vd.vertex, normal);
mul_v3_fl(normal, brush->height);
- madd_v3_v3v3fl(final_co, SCULPT_vertex_persistent_co_get(ss, vi), normal, *disp_factor);
+ madd_v3_v3v3fl(
+ final_co, SCULPT_vertex_persistent_co_get(ss, vd.vertex), normal, *disp_factor);
}
else {
normal_short_to_float_v3(normal, orig_data.no);
@@ -4793,7 +5151,7 @@ static void do_inflate_brush_task_cb_ex(void *__restrict userdata,
vd.no,
vd.fno,
vd.mask ? *vd.mask : 0.0f,
- vd.index,
+ vd.vertex,
thread_id);
float val[3];
@@ -4906,7 +5264,7 @@ static void do_flatten_brush_task_cb_ex(void *__restrict userdata,
vd.no,
vd.fno,
vd.mask ? *vd.mask : 0.0f,
- vd.index,
+ vd.vertex,
thread_id);
mul_v3_v3fl(proxy[vd.i], val, fade);
@@ -5060,7 +5418,7 @@ static void do_clay_brush_task_cb_ex(void *__restrict userdata,
vd.no,
vd.fno,
vd.mask ? *vd.mask : 0.0f,
- vd.index,
+ vd.vertex,
thread_id);
mul_v3_v3fl(proxy[vd.i], val, fade);
@@ -5183,7 +5541,7 @@ static void do_clay_strips_brush_task_cb_ex(void *__restrict userdata,
vd.no,
vd.fno,
vd.mask ? *vd.mask : 0.0f,
- vd.index,
+ vd.vertex,
thread_id);
mul_v3_v3fl(proxy[vd.i], val, fade);
@@ -5333,7 +5691,7 @@ static void do_fill_brush_task_cb_ex(void *__restrict userdata,
vd.no,
vd.fno,
vd.mask ? *vd.mask : 0.0f,
- vd.index,
+ vd.vertex,
thread_id);
mul_v3_v3fl(proxy[vd.i], val, fade);
@@ -5428,7 +5786,7 @@ static void do_scrape_brush_task_cb_ex(void *__restrict userdata,
vd.no,
vd.fno,
vd.mask ? *vd.mask : 0.0f,
- vd.index,
+ vd.vertex,
thread_id);
mul_v3_v3fl(proxy[vd.i], val, fade);
@@ -5546,7 +5904,7 @@ static void do_clay_thumb_brush_task_cb_ex(void *__restrict userdata,
vd.no,
vd.fno,
vd.mask ? *vd.mask : 0.0f,
- vd.index,
+ vd.vertex,
thread_id);
mul_v3_v3fl(proxy[vd.i], val, fade);
@@ -5685,7 +6043,7 @@ static void do_gravity_task_cb_ex(void *__restrict userdata,
vd.no,
vd.fno,
vd.mask ? *vd.mask : 0.0f,
- vd.index,
+ vd.vertex,
thread_id);
mul_v3_v3fl(proxy[vd.i], offset, fade);
@@ -5801,27 +6159,40 @@ static void sculpt_topology_update(Sculpt *sd,
}
}
+ bool undo_push = !use_original ||
+ SCULPT_stroke_is_first_brush_step_of_symmetry_pass(ss->cache);
+
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);
+ if (undo_push) {
+ 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]);
if (BKE_pbvh_type(ss->pbvh) == PBVH_BMESH) {
BKE_pbvh_node_mark_topology_update(nodes[n]);
- BKE_pbvh_bmesh_node_save_orig(ss->bm, nodes[n]);
+ BKE_pbvh_bmesh_node_save_ortri(ss->bm, nodes[n]);
}
}
if (BKE_pbvh_type(ss->pbvh) == PBVH_BMESH) {
+ int symidx = ss->cache->mirror_symmetry_pass + (ss->cache->radial_symmetry_pass * 8);
+ if (symidx > 127) {
+ symidx = 127;
+ }
+
BKE_pbvh_bmesh_update_topology(ss->pbvh,
mode,
ss->cache->location,
ss->cache->view_normal,
ss->cache->radius,
(brush->flag & BRUSH_FRONTFACE) != 0,
- (brush->falloff_shape != PAINT_FALLOFF_SHAPE_SPHERE));
+ (brush->falloff_shape != PAINT_FALLOFF_SHAPE_SPHERE),
+ symidx,
+ brush->sculpt_tool != SCULPT_TOOL_DRAW_SHARP);
}
MEM_SAFE_FREE(nodes);
@@ -5853,11 +6224,20 @@ static void do_brush_action_task_cb(void *__restrict userdata,
BKE_pbvh_node_mark_update_mask(data->nodes[n]);
}
else if (ELEM(data->brush->sculpt_tool, SCULPT_TOOL_PAINT, SCULPT_TOOL_SMEAR)) {
- SCULPT_undo_push_node(data->ob, data->nodes[n], SCULPT_UNDO_COLOR);
+ if (!ss->bm) {
+ if (data->brush->vcol_boundary_factor > 0.0f) {
+ SCULPT_undo_push_node(data->ob, data->nodes[n], SCULPT_UNDO_COORDS);
+ }
+
+ SCULPT_undo_push_node(data->ob, data->nodes[n], SCULPT_UNDO_COLOR);
+ }
+
BKE_pbvh_node_mark_update_color(data->nodes[n]);
}
else {
- SCULPT_undo_push_node(data->ob, data->nodes[n], SCULPT_UNDO_COORDS);
+ if (!ss->bm) {
+ SCULPT_undo_push_node(data->ob, data->nodes[n], SCULPT_UNDO_COORDS);
+ }
BKE_pbvh_node_mark_update(data->nodes[n]);
}
}
@@ -5870,11 +6250,8 @@ static void do_brush_action(Sculpt *sd, Object *ob, Brush *brush, UnifiedPaintSe
/* Check for unsupported features. */
PBVHType type = BKE_pbvh_type(ss->pbvh);
- if (brush->sculpt_tool == SCULPT_TOOL_PAINT && type != PBVH_FACES) {
- return;
- }
-
- if (brush->sculpt_tool == SCULPT_TOOL_SMEAR && type != PBVH_FACES) {
+ if (ELEM(brush->sculpt_tool, SCULPT_TOOL_PAINT, SCULPT_TOOL_SMEAR) &&
+ !ELEM(type, PBVH_BMESH, PBVH_FACES)) {
return;
}
@@ -5906,9 +6283,7 @@ static void do_brush_action(Sculpt *sd, Object *ob, Brush *brush, UnifiedPaintSe
if (brush->sculpt_tool == SCULPT_TOOL_DRAW_FACE_SETS &&
SCULPT_stroke_is_first_brush_step(ss->cache) && !ss->cache->alt_smooth) {
- /* Dynamic-topology does not support Face Sets data, so it can't store/restore it from undo. */
- /* TODO(pablodp606): This check should be done in the undo code and not here, but the rest of
- * the sculpt code is not checking for unsupported undo types that may return a null node. */
+ // faceset undo node is created below for pbvh_bmesh
if (BKE_pbvh_type(ss->pbvh) != PBVH_BMESH) {
SCULPT_undo_push_node(ob, NULL, SCULPT_UNDO_FACE_SETS);
}
@@ -5938,16 +6313,56 @@ static void do_brush_action(Sculpt *sd, Object *ob, Brush *brush, UnifiedPaintSe
if (totnode) {
float location[3];
- SculptThreadedTaskData task_data = {
- .sd = sd,
- .ob = ob,
- .brush = brush,
- .nodes = nodes,
- };
+ // dyntopo can't push undo nodes inside a thread
+ if (ss->bm) {
+ if (ELEM(brush->sculpt_tool, SCULPT_TOOL_PAINT, SCULPT_TOOL_SMEAR)) {
+ for (int i = 0; i < totnode; i++) {
+ int other = brush->vcol_boundary_factor > 0.0f ? SCULPT_UNDO_COORDS : -1;
- TaskParallelSettings settings;
- BKE_pbvh_parallel_range_settings(&settings, true, totnode);
- BLI_task_parallel_range(0, totnode, &task_data, do_brush_action_task_cb, &settings);
+ if (SCULPT_ensure_dyntopo_node_undo(ob, nodes[i], SCULPT_UNDO_COLOR, other)) {
+ BKE_pbvh_update_origcolor_bmesh(ss->pbvh, nodes[i]);
+
+ if (other != -1) {
+ BKE_pbvh_update_origco_bmesh(ss->pbvh, nodes[i]);
+ }
+ }
+
+ BKE_pbvh_node_mark_update_color(nodes[i]);
+ // SCULPT_undo_push_node(ob, nodes[i], SCULPT_UNDO_COLOR);
+ }
+ }
+ else if (brush->sculpt_tool == SCULPT_TOOL_DRAW_FACE_SETS) {
+ for (int i = 0; i < totnode; i++) {
+ if (ss->cache->alt_smooth) {
+ SCULPT_ensure_dyntopo_node_undo(
+ ob, nodes[i], SCULPT_UNDO_FACE_SETS, SCULPT_UNDO_COORDS);
+ }
+ else {
+ SCULPT_ensure_dyntopo_node_undo(ob, nodes[i], SCULPT_UNDO_FACE_SETS, -1);
+ }
+
+ BKE_pbvh_node_mark_update(nodes[i]);
+ }
+ }
+ else {
+ for (int i = 0; i < totnode; i++) {
+ SCULPT_ensure_dyntopo_node_undo(ob, nodes[i], SCULPT_UNDO_COORDS, -1);
+ BKE_pbvh_node_mark_update(nodes[i]);
+ }
+ }
+ }
+ else {
+ SculptThreadedTaskData task_data = {
+ .sd = sd,
+ .ob = ob,
+ .brush = brush,
+ .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);
+ }
if (sculpt_brush_needs_normal(ss, brush)) {
update_sculpt_normal(sd, ob, nodes, totnode);
@@ -6081,6 +6496,9 @@ static void do_brush_action(Sculpt *sd, Object *ob, Brush *brush, UnifiedPaintSe
case SCULPT_TOOL_PAINT:
SCULPT_do_paint_brush(sd, ob, nodes, totnode);
break;
+ case SCULPT_TOOL_VCOL_BOUNDARY:
+ SCULPT_smooth_vcol_boundary(sd, ob, nodes, totnode, ss->cache->bstrength);
+ break;
case SCULPT_TOOL_SMEAR:
SCULPT_do_smear_brush(sd, ob, nodes, totnode);
break;
@@ -6188,7 +6606,9 @@ static void sculpt_combine_proxies_task_cb(void *__restrict userdata,
if (use_orco) {
if (ss->bm) {
- copy_v3_v3(val, BM_log_original_vert_co(ss->bm_log, vd.bm_vert));
+ float *co = BM_ELEM_CD_GET_VOID_P(vd.bm_vert, ss->cd_origco_offset);
+ copy_v3_v3(val, co);
+ // copy_v3_v3(val, BM_log_original_vert_co(ss->bm_log, vd.bm_vert));
}
else {
copy_v3_v3(val, orco[vd.i]);
@@ -6276,13 +6696,16 @@ static void SCULPT_flush_stroke_deform_task_cb(void *__restrict userdata,
PBVHVertexIter vd;
+ if (BKE_pbvh_type(ss->pbvh) == PBVH_BMESH) {
+ BM_mesh_elem_index_ensure(ss->bm, BM_VERT);
+ }
+
BKE_pbvh_vertex_iter_begin(ss->pbvh, data->nodes[n], vd, PBVH_ITER_UNIQUE)
{
sculpt_flush_pbvhvert_deform(ob, &vd);
if (vertCos) {
- int index = vd.vert_indices[vd.i];
- copy_v3_v3(vertCos[index], ss->orig_cos[index]);
+ copy_v3_v3(vertCos[vd.index], ss->orig_cos[vd.index]);
}
}
BKE_pbvh_vertex_iter_end;
@@ -6560,6 +6983,24 @@ bool SCULPT_vertex_colors_poll(bContext *C)
if (!U.experimental.use_sculpt_vertex_colors) {
return false;
}
+
+ Object *ob = CTX_data_active_object(C);
+
+ return SCULPT_mode_poll(C);
+}
+
+bool SCULPT_vertex_colors_poll_no_bmesh(bContext *C)
+{
+ if (!U.experimental.use_sculpt_vertex_colors) {
+ return false;
+ }
+
+ Object *ob = CTX_data_active_object(C);
+
+ if (ob && ob->sculpt && ob->sculpt->bm) {
+ return false;
+ }
+
return SCULPT_mode_poll(C);
}
@@ -6647,6 +7088,8 @@ static const char *sculpt_tool_name(Sculpt *sd)
return "Paint Brush";
case SCULPT_TOOL_SMEAR:
return "Smear Brush";
+ case SCULPT_TOOL_VCOL_BOUNDARY:
+ return "Color Boundary";
}
return "Sculpting";
@@ -7255,6 +7698,8 @@ static bool sculpt_needs_connectivity_info(const Sculpt *sd,
(brush->sculpt_tool == SCULPT_TOOL_SMOOTH) || (brush->autosmooth_factor > 0) ||
((brush->sculpt_tool == SCULPT_TOOL_MASK) && (brush->mask_tool == BRUSH_MASK_SMOOTH)) ||
(brush->sculpt_tool == SCULPT_TOOL_POSE) ||
+ (brush->sculpt_tool == SCULPT_TOOL_VCOL_BOUNDARY) ||
+ (brush->sculpt_tool == SCULPT_TOOL_PAINT && brush->vcol_boundary_factor > 0.0f) ||
(brush->sculpt_tool == SCULPT_TOOL_BOUNDARY) ||
(brush->sculpt_tool == SCULPT_TOOL_SLIDE_RELAX) ||
(brush->sculpt_tool == SCULPT_TOOL_CLOTH) || (brush->sculpt_tool == SCULPT_TOOL_SMEAR) ||
@@ -7288,7 +7733,7 @@ static void sculpt_raycast_cb(PBVHNode *node, void *data_v, float *tmin)
}
else {
/* Intersect with coordinates from before we started stroke. */
- SculptUndoNode *unode = SCULPT_undo_get_node(node);
+ SculptUndoNode *unode = SCULPT_undo_get_node(node, -1);
origco = (unode) ? unode->co : NULL;
use_origco = origco ? true : false;
}
@@ -7324,7 +7769,7 @@ static void sculpt_find_nearest_to_ray_cb(PBVHNode *node, void *data_v, float *t
}
else {
/* Intersect with coordinates from before we started stroke. */
- SculptUndoNode *unode = SCULPT_undo_get_node(node);
+ SculptUndoNode *unode = SCULPT_undo_get_node(node, -1);
origco = (unode) ? unode->co : NULL;
use_origco = origco ? true : false;
}
@@ -7440,7 +7885,10 @@ bool SCULPT_cursor_geometry_info_update(bContext *C,
/* Update the active vertex of the SculptSession. */
ss->active_vertex_index = srd.active_vertex_index;
- SCULPT_vertex_random_access_ensure(ss);
+
+ if (BKE_pbvh_type(ss->pbvh) != PBVH_BMESH) {
+ SCULPT_vertex_random_access_ensure(ss);
+ }
copy_v3_v3(out->active_vertex_co, SCULPT_active_vertex_co_get(ss));
switch (BKE_pbvh_type(ss->pbvh)) {
@@ -7449,11 +7897,11 @@ bool SCULPT_cursor_geometry_info_update(bContext *C,
ss->active_grid_index = 0;
break;
case PBVH_GRIDS:
- ss->active_face_index = 0;
- ss->active_grid_index = srd.active_face_grid_index;
+ ss->active_face_index.i = 0;
+ ss->active_grid_index = srd.active_face_grid_index.i;
break;
case PBVH_BMESH:
- ss->active_face_index = 0;
+ ss->active_face_index = srd.active_face_grid_index;
ss->active_grid_index = 0;
break;
}
@@ -7540,11 +7988,6 @@ bool SCULPT_stroke_get_location(bContext *C, float out[3], const float mouse[2])
depth = SCULPT_raycast_init(&vc, mouse, ray_start, ray_end, ray_normal, original);
- if (BKE_pbvh_type(ss->pbvh) == PBVH_BMESH) {
- BM_mesh_elem_table_ensure(ss->bm, BM_VERT);
- BM_mesh_elem_index_ensure(ss->bm, BM_VERT);
- }
-
bool hit = false;
{
SculptRaycastData srd;
@@ -7747,6 +8190,13 @@ void SCULPT_flush_update_step(bContext *C, SculptUpdateType update_flags)
}
}
+bool all_nodes_callback(PBVHNode *node, void *data)
+{
+ return true;
+}
+
+void sculpt_undo_print_nodes(void *active);
+
void SCULPT_flush_update_done(const bContext *C, Object *ob, SculptUpdateType update_flags)
{
/* After we are done drawing the stroke, check if we need to do a more
@@ -7797,12 +8247,31 @@ void SCULPT_flush_update_done(const bContext *C, Object *ob, SculptUpdateType up
BKE_pbvh_update_vertex_data(ss->pbvh, PBVH_UpdateMask);
}
- if (update_flags & SCULPT_UPDATE_COLOR) {
- BKE_pbvh_update_vertex_data(ss->pbvh, PBVH_UpdateColor);
- }
-
if (BKE_pbvh_type(ss->pbvh) == PBVH_BMESH) {
BKE_pbvh_bmesh_after_stroke(ss->pbvh);
+#if 0
+ if (update_flags & SCULPT_UPDATE_COLOR) {
+ PBVHNode **nodes;
+ int totnode = 0;
+
+ // BKE_pbvh_get_nodes(ss->pbvh, PBVH_UpdateColor, &nodes, &totnode);
+ BKE_pbvh_search_gather(ss->pbvh, all_nodes_callback, NULL, &nodes, &totnode);
+
+ for (int i = 0; i < totnode; i++) {
+ SCULPT_undo_push_node(ob, nodes[i], SCULPT_UNDO_COLOR);
+ }
+
+ if (nodes) {
+ MEM_freeN(nodes);
+ }
+ }
+#endif
+
+ sculpt_undo_print_nodes(NULL);
+ }
+
+ if (update_flags & SCULPT_UPDATE_COLOR) {
+ BKE_pbvh_update_vertex_data(ss->pbvh, PBVH_UpdateColor);
}
/* Optimization: if there is locked key and active modifiers present in */
@@ -7979,7 +8448,10 @@ static void sculpt_stroke_done(const bContext *C, struct PaintStroke *UNUSED(str
SCULPT_undo_push_end();
- if (brush->sculpt_tool == SCULPT_TOOL_MASK) {
+ if (brush->sculpt_tool == SCULPT_TOOL_PAINT || brush->sculpt_tool == SCULPT_TOOL_SMEAR) {
+ SCULPT_flush_update_done(C, ob, SCULPT_UPDATE_COORDS | SCULPT_UPDATE_COLOR);
+ }
+ else if (brush->sculpt_tool == SCULPT_TOOL_MASK) {
SCULPT_flush_update_done(C, ob, SCULPT_UPDATE_MASK);
}
else {
@@ -8121,8 +8593,10 @@ static int sculpt_set_persistent_base_exec(bContext *C, wmOperator *UNUSED(op))
"layer persistent base");
for (int i = 0; i < totvert; i++) {
- copy_v3_v3(ss->persistent_base[i].co, SCULPT_vertex_co_get(ss, i));
- SCULPT_vertex_normal_get(ss, i, ss->persistent_base[i].no);
+ SculptVertRef vertex = BKE_pbvh_table_index_to_vertex(ss->pbvh, i);
+
+ copy_v3_v3(ss->persistent_base[i].co, SCULPT_vertex_co_get(ss, vertex));
+ SCULPT_vertex_normal_get(ss, vertex, ss->persistent_base[i].no);
ss->persistent_base[i].disp = 0.0f;
}
}
@@ -8185,6 +8659,22 @@ static bool sculpt_no_multires_poll(bContext *C)
return false;
}
+/* checks if pbvh needs to sync its flat vcol shading flag with scene tool settings
+ scene and ob are allowd to be NULL (in which case nothing is done).
+*/
+void SCULPT_update_flat_vcol_shading(Object *ob, Scene *scene)
+{
+ if (!scene || !ob || !ob->sculpt || !ob->sculpt->pbvh) {
+ return;
+ }
+
+ if (ob->sculpt->pbvh) {
+ bool flat_vcol_shading = ((scene->toolsettings->sculpt->flags &
+ SCULPT_DYNTOPO_FLAT_VCOL_SHADING) != 0);
+
+ BKE_pbvh_set_flat_vcol_shading(ob->sculpt->pbvh, flat_vcol_shading);
+ }
+}
static int sculpt_symmetrize_exec(bContext *C, wmOperator *op)
{
Object *ob = CTX_data_active_object(C);
@@ -8625,26 +9115,31 @@ void SCULPT_geometry_preview_lines_update(bContext *C, SculptSession *ss, float
const int max_preview_vertices = SCULPT_vertex_count_get(ss) * 3 * 2;
if (ss->preview_vert_index_list == NULL) {
- ss->preview_vert_index_list = MEM_callocN(max_preview_vertices * sizeof(int), "preview lines");
+ ss->preview_vert_index_list = MEM_callocN(max_preview_vertices * sizeof(SculptVertRef),
+ "preview lines");
}
- GSQueue *not_visited_vertices = BLI_gsqueue_new(sizeof(int));
- int active_v = SCULPT_active_vertex_get(ss);
+ GSQueue *not_visited_vertices = BLI_gsqueue_new(sizeof(SculptVertRef));
+ SculptVertRef active_v = SCULPT_active_vertex_get(ss);
BLI_gsqueue_push(not_visited_vertices, &active_v);
while (!BLI_gsqueue_is_empty(not_visited_vertices)) {
- int from_v;
+ SculptVertRef from_v;
+
BLI_gsqueue_pop(not_visited_vertices, &from_v);
+
SculptVertexNeighborIter ni;
SCULPT_VERTEX_NEIGHBORS_ITER_BEGIN (ss, from_v, ni) {
if (totpoints + (ni.size * 2) < max_preview_vertices) {
- int to_v = ni.index;
+ SculptVertRef to_v = ni.vertex;
+ int to_v_i = BKE_pbvh_vertex_index_to_table(ss->pbvh, to_v);
+
ss->preview_vert_index_list[totpoints] = from_v;
totpoints++;
ss->preview_vert_index_list[totpoints] = to_v;
totpoints++;
- if (!BLI_BITMAP_TEST(visited_vertices, to_v)) {
- BLI_BITMAP_ENABLE(visited_vertices, to_v);
+ if (!BLI_BITMAP_TEST(visited_vertices, to_v_i)) {
+ BLI_BITMAP_ENABLE(visited_vertices, to_v_i);
const float *co = SCULPT_vertex_co_for_grab_active_get(ss, to_v);
if (len_squared_v3v3(brush_co, co) < radius * radius) {
BLI_gsqueue_push(not_visited_vertices, &to_v);
@@ -8719,7 +9214,7 @@ static void SCULPT_OT_vertex_to_loop_colors(wmOperatorType *ot)
ot->idname = "SCULPT_OT_vertex_to_loop_colors";
/* api callbacks */
- ot->poll = SCULPT_vertex_colors_poll;
+ ot->poll = SCULPT_vertex_colors_poll_no_bmesh;
ot->exec = vertex_to_loop_colors_exec;
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
@@ -8782,7 +9277,7 @@ static void SCULPT_OT_loop_to_vertex_colors(wmOperatorType *ot)
ot->idname = "SCULPT_OT_loop_to_vertex_colors";
/* api callbacks */
- ot->poll = SCULPT_vertex_colors_poll;
+ ot->poll = SCULPT_vertex_colors_poll_no_bmesh;
ot->exec = loop_to_vertex_colors_exec;
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
@@ -8797,7 +9292,7 @@ static int sculpt_sample_color_invoke(bContext *C,
Object *ob = CTX_data_active_object(C);
Brush *brush = BKE_paint_brush(&sd->paint);
SculptSession *ss = ob->sculpt;
- int active_vertex = SCULPT_active_vertex_get(ss);
+ SculptVertRef active_vertex = SCULPT_active_vertex_get(ss);
const float *active_vertex_color = SCULPT_vertex_color_get(ss, active_vertex);
if (!active_vertex_color) {
return OPERATOR_CANCELLED;
@@ -8854,10 +9349,14 @@ enum {
SCULPT_TOPOLOGY_ID_DEFAULT,
};
-static int SCULPT_vertex_get_connected_component(SculptSession *ss, int index)
+static int SCULPT_vertex_get_connected_component(SculptSession *ss, SculptVertRef vertex)
{
+ if (BKE_pbvh_type(ss->pbvh) == PBVH_BMESH) {
+ vertex.i = BM_elem_index_get((BMVert *)vertex.i);
+ }
+
if (ss->vertex_info.connected_component) {
- return ss->vertex_info.connected_component[index];
+ return ss->vertex_info.connected_component[vertex.i];
}
return SCULPT_TOPOLOGY_ID_DEFAULT;
}
@@ -8866,19 +9365,28 @@ static void SCULPT_fake_neighbor_init(SculptSession *ss, const float max_dist)
{
const int totvert = SCULPT_vertex_count_get(ss);
ss->fake_neighbors.fake_neighbor_index = MEM_malloc_arrayN(
- totvert, sizeof(int), "fake neighbor");
+ totvert, sizeof(SculptVertRef), "fake neighbor");
for (int i = 0; i < totvert; i++) {
- ss->fake_neighbors.fake_neighbor_index[i] = FAKE_NEIGHBOR_NONE;
+ ss->fake_neighbors.fake_neighbor_index[i].i = FAKE_NEIGHBOR_NONE;
}
ss->fake_neighbors.current_max_distance = max_dist;
}
-static void SCULPT_fake_neighbor_add(SculptSession *ss, int v_index_a, int v_index_b)
+static void SCULPT_fake_neighbor_add(SculptSession *ss,
+ SculptVertRef v_index_a,
+ SculptVertRef v_index_b)
{
- if (ss->fake_neighbors.fake_neighbor_index[v_index_a] == FAKE_NEIGHBOR_NONE) {
- ss->fake_neighbors.fake_neighbor_index[v_index_a] = v_index_b;
- ss->fake_neighbors.fake_neighbor_index[v_index_b] = v_index_a;
+ int tablea = (int)v_index_a.i, tableb = (int)v_index_b.i;
+
+ if (BKE_pbvh_type(ss->pbvh) == PBVH_BMESH) {
+ tablea = BM_elem_index_get((BMVert *)v_index_a.i);
+ tableb = BM_elem_index_get((BMVert *)v_index_b.i);
+ }
+
+ if (ss->fake_neighbors.fake_neighbor_index[tablea].i == FAKE_NEIGHBOR_NONE) {
+ ss->fake_neighbors.fake_neighbor_index[tablea] = v_index_b;
+ ss->fake_neighbors.fake_neighbor_index[tableb] = v_index_a;
}
}
@@ -8889,6 +9397,7 @@ static void sculpt_pose_fake_neighbors_free(SculptSession *ss)
typedef struct NearestVertexFakeNeighborTLSData {
int nearest_vertex_index;
+ SculptVertRef nearest_vertex;
float nearest_vertex_distance_squared;
int current_topology_id;
} NearestVertexFakeNeighborTLSData;
@@ -8902,15 +9411,20 @@ static void do_fake_neighbor_search_task_cb(void *__restrict userdata,
NearestVertexFakeNeighborTLSData *nvtd = tls->userdata_chunk;
PBVHVertexIter vd;
+ bool has_bmesh = false;
+
+ SCULPT_vertex_random_access_ensure(ss);
+
BKE_pbvh_vertex_iter_begin(ss->pbvh, data->nodes[n], vd, PBVH_ITER_UNIQUE)
{
- int vd_topology_id = SCULPT_vertex_get_connected_component(ss, vd.index);
+ int vd_topology_id = SCULPT_vertex_get_connected_component(ss, vd.vertex);
if (vd_topology_id != nvtd->current_topology_id &&
- ss->fake_neighbors.fake_neighbor_index[vd.index] == FAKE_NEIGHBOR_NONE) {
+ ss->fake_neighbors.fake_neighbor_index[vd.index].i == FAKE_NEIGHBOR_NONE) {
float distance_squared = len_squared_v3v3(vd.co, data->nearest_vertex_search_co);
if (distance_squared < nvtd->nearest_vertex_distance_squared &&
distance_squared < data->max_distance_squared) {
nvtd->nearest_vertex_index = vd.index;
+ nvtd->nearest_vertex = vd.vertex;
nvtd->nearest_vertex_distance_squared = distance_squared;
}
}
@@ -8924,17 +9438,23 @@ static void fake_neighbor_search_reduce(const void *__restrict UNUSED(userdata),
{
NearestVertexFakeNeighborTLSData *join = chunk_join;
NearestVertexFakeNeighborTLSData *nvtd = chunk;
+
if (join->nearest_vertex_index == -1) {
join->nearest_vertex_index = nvtd->nearest_vertex_index;
+ join->nearest_vertex = nvtd->nearest_vertex;
join->nearest_vertex_distance_squared = nvtd->nearest_vertex_distance_squared;
}
else if (nvtd->nearest_vertex_distance_squared < join->nearest_vertex_distance_squared) {
join->nearest_vertex_index = nvtd->nearest_vertex_index;
+ join->nearest_vertex = nvtd->nearest_vertex;
join->nearest_vertex_distance_squared = nvtd->nearest_vertex_distance_squared;
}
}
-static int SCULPT_fake_neighbor_search(Sculpt *sd, Object *ob, const int index, float max_distance)
+static SculptVertRef SCULPT_fake_neighbor_search(Sculpt *sd,
+ Object *ob,
+ const SculptVertRef index,
+ float max_distance)
{
SculptSession *ss = ob->sculpt;
PBVHNode **nodes = NULL;
@@ -8949,7 +9469,7 @@ static int SCULPT_fake_neighbor_search(Sculpt *sd, Object *ob, const int index,
BKE_pbvh_search_gather(ss->pbvh, SCULPT_search_sphere_cb, &data, &nodes, &totnode);
if (totnode == 0) {
- return -1;
+ return BKE_pbvh_make_vref(-1);
}
SculptThreadedTaskData task_data = {
@@ -8963,6 +9483,7 @@ static int SCULPT_fake_neighbor_search(Sculpt *sd, Object *ob, const int index,
NearestVertexFakeNeighborTLSData nvtd;
nvtd.nearest_vertex_index = -1;
+ nvtd.nearest_vertex.i = -1;
nvtd.nearest_vertex_distance_squared = FLT_MAX;
nvtd.current_topology_id = SCULPT_vertex_get_connected_component(ss, index);
@@ -8975,19 +9496,24 @@ static int SCULPT_fake_neighbor_search(Sculpt *sd, Object *ob, const int index,
MEM_SAFE_FREE(nodes);
- return nvtd.nearest_vertex_index;
+ return nvtd.nearest_vertex;
}
typedef struct SculptTopologyIDFloodFillData {
int next_id;
} SculptTopologyIDFloodFillData;
-static bool SCULPT_connected_components_floodfill_cb(
- SculptSession *ss, int from_v, int to_v, bool UNUSED(is_duplicate), void *userdata)
+static bool SCULPT_connected_components_floodfill_cb(SculptSession *ss,
+ SculptVertRef from_v,
+ SculptVertRef to_v,
+ bool UNUSED(is_duplicate),
+ void *userdata)
{
SculptTopologyIDFloodFillData *data = userdata;
- ss->vertex_info.connected_component[from_v] = data->next_id;
- ss->vertex_info.connected_component[to_v] = data->next_id;
+ ss->vertex_info.connected_component[BKE_pbvh_vertex_index_to_table(ss->pbvh, from_v)] =
+ data->next_id;
+ ss->vertex_info.connected_component[BKE_pbvh_vertex_index_to_table(ss->pbvh, to_v)] =
+ data->next_id;
return true;
}
@@ -8995,6 +9521,8 @@ static void sculpt_connected_components_ensure(Object *ob)
{
SculptSession *ss = ob->sculpt;
+ SCULPT_vertex_random_access_ensure(ss);
+
/* Topology IDs already initialized. They only need to be recalculated when the PBVH is rebuild.
*/
if (ss->vertex_info.connected_component) {
@@ -9010,10 +9538,12 @@ static void sculpt_connected_components_ensure(Object *ob)
int next_id = 0;
for (int i = 0; i < totvert; i++) {
+ SculptVertRef vertex = BKE_pbvh_table_index_to_vertex(ss->pbvh, i);
+
if (ss->vertex_info.connected_component[i] == SCULPT_TOPOLOGY_ID_NONE) {
SculptFloodFill flood;
SCULPT_floodfill_init(ss, &flood);
- SCULPT_floodfill_add_initial(&flood, i);
+ SCULPT_floodfill_add_initial(&flood, vertex);
SculptTopologyIDFloodFillData data;
data.next_id = next_id;
SCULPT_floodfill_execute(ss, &flood, SCULPT_connected_components_floodfill_cb, &data);
@@ -9070,12 +9600,13 @@ void SCULPT_fake_neighbors_ensure(Sculpt *sd, Object *ob, const float max_dist)
SCULPT_fake_neighbor_init(ss, max_dist);
for (int i = 0; i < totvert; i++) {
- const int from_v = i;
+ const SculptVertRef from_v = BKE_pbvh_table_index_to_vertex(ss->pbvh, i);
/* This vertex does not have a fake neighbor yet, seach one for it. */
- if (ss->fake_neighbors.fake_neighbor_index[from_v] == FAKE_NEIGHBOR_NONE) {
- const int to_v = SCULPT_fake_neighbor_search(sd, ob, from_v, max_dist);
- if (to_v != -1) {
+ if (ss->fake_neighbors.fake_neighbor_index[i].i == FAKE_NEIGHBOR_NONE) {
+ const SculptVertRef to_v = SCULPT_fake_neighbor_search(sd, ob, from_v, max_dist);
+
+ if (to_v.i != -1) {
/* Add the fake neighbor if available. */
SCULPT_fake_neighbor_add(ss, from_v, to_v);
}
@@ -9192,16 +9723,19 @@ static void do_mask_by_color_contiguous_update_nodes_cb(
}
static bool sculpt_mask_by_color_contiguous_floodfill_cb(
- SculptSession *ss, int from_v, int to_v, bool is_duplicate, void *userdata)
+ SculptSession *ss, SculptVertRef from_v, SculptVertRef to_v, bool is_duplicate, void *userdata)
{
MaskByColorContiguousFloodFillData *data = userdata;
+ int to_v_i = BKE_pbvh_vertex_index_to_table(ss->pbvh, to_v);
+ int from_v_i = BKE_pbvh_vertex_index_to_table(ss->pbvh, from_v);
+
const float *current_color = SCULPT_vertex_color_get(ss, to_v);
float new_vertex_mask = sculpt_mask_by_color_delta_get(
current_color, data->initial_color, data->threshold, data->invert);
- data->new_mask[to_v] = new_vertex_mask;
+ data->new_mask[to_v_i] = new_vertex_mask;
if (is_duplicate) {
- data->new_mask[to_v] = data->new_mask[from_v];
+ data->new_mask[to_v_i] = data->new_mask[from_v_i];
}
float len = len_v3v3(current_color, data->initial_color);
@@ -9210,7 +9744,7 @@ static bool sculpt_mask_by_color_contiguous_floodfill_cb(
}
static void sculpt_mask_by_color_contiguous(Object *object,
- const int vertex,
+ const SculptVertRef vertex,
const float threshold,
const bool invert,
const bool preserve_mask)
@@ -9299,7 +9833,7 @@ static void do_mask_by_color_task_cb(void *__restrict userdata,
}
static void sculpt_mask_by_color_full_mesh(Object *object,
- const int vertex,
+ const SculptVertRef vertex,
const float threshold,
const bool invert,
const bool preserve_mask)
@@ -9355,7 +9889,7 @@ static int sculpt_mask_by_color_invoke(bContext *C, wmOperator *op, const wmEven
SCULPT_undo_push_begin(ob, "Mask by color");
- const int active_vertex = SCULPT_active_vertex_get(ss);
+ const SculptVertRef active_vertex = SCULPT_active_vertex_get(ss);
const float threshold = RNA_float_get(op->ptr, "threshold");
const bool invert = RNA_boolean_get(op->ptr, "invert");
const bool preserve_mask = RNA_boolean_get(op->ptr, "preserve_previous_mask");
@@ -9550,14 +10084,14 @@ static void dyntopo_detail_size_sample_from_surface(Object *ob,
DyntopoDetailSizeEditCustomData *cd)
{
SculptSession *ss = ob->sculpt;
- const int active_vertex = SCULPT_active_vertex_get(ss);
+ const SculptVertRef active_vertex = SCULPT_active_vertex_get(ss);
float len_accum = 0;
int num_neighbors = 0;
SculptVertexNeighborIter ni;
SCULPT_VERTEX_NEIGHBORS_ITER_BEGIN (ss, active_vertex, ni) {
len_accum += len_v3v3(SCULPT_vertex_co_get(ss, active_vertex),
- SCULPT_vertex_co_get(ss, ni.index));
+ SCULPT_vertex_co_get(ss, ni.vertex));
num_neighbors++;
}
SCULPT_VERTEX_NEIGHBORS_ITER_END(ni);
diff --git a/source/blender/editors/sculpt_paint/sculpt_automasking.c b/source/blender/editors/sculpt_paint/sculpt_automasking.c
index bb68ec56b25..a904313c127 100644
--- a/source/blender/editors/sculpt_paint/sculpt_automasking.c
+++ b/source/blender/editors/sculpt_paint/sculpt_automasking.c
@@ -127,7 +127,9 @@ static bool SCULPT_automasking_needs_factors_cache(const Sculpt *sd, const Brush
return false;
}
-float SCULPT_automasking_factor_get(AutomaskingCache *automasking, SculptSession *ss, int vert)
+float SCULPT_automasking_factor_get(AutomaskingCache *automasking,
+ SculptSession *ss,
+ SculptVertRef vert)
{
if (!automasking) {
return 1.0f;
@@ -136,7 +138,7 @@ float SCULPT_automasking_factor_get(AutomaskingCache *automasking, SculptSession
* automasking information can't be computed in real time per vertex and needs to be
* initialized for the whole mesh when the stroke starts. */
if (automasking->factor) {
- return automasking->factor[vert];
+ return automasking->factor[BKE_pbvh_vertex_index_to_table(ss->pbvh, vert)];
}
if (automasking->settings.flags & BRUSH_AUTOMASKING_FACE_SETS) {
@@ -191,16 +193,19 @@ typedef struct AutomaskFloodFillData {
char symm;
} AutomaskFloodFillData;
-static bool automask_floodfill_cb(
- SculptSession *ss, int from_v, int to_v, bool UNUSED(is_duplicate), void *userdata)
+static bool automask_floodfill_cb(SculptSession *ss,
+ SculptVertRef from_vref,
+ SculptVertRef to_vref,
+ bool UNUSED(is_duplicate),
+ void *userdata)
{
AutomaskFloodFillData *data = userdata;
- data->automask_factor[to_v] = 1.0f;
- data->automask_factor[from_v] = 1.0f;
+ data->automask_factor[BKE_pbvh_vertex_index_to_table(ss->pbvh, to_vref)] = 1.0f;
+ data->automask_factor[BKE_pbvh_vertex_index_to_table(ss->pbvh, from_vref)] = 1.0f;
return (!data->use_radius ||
SCULPT_is_vertex_inside_brush_radius_symm(
- SCULPT_vertex_co_get(ss, to_v), data->location, data->radius, data->symm));
+ SCULPT_vertex_co_get(ss, to_vref), data->location, data->radius, data->symm));
}
static float *SCULPT_topology_automasking_init(Sculpt *sd, Object *ob, float *automask_factor)
@@ -255,7 +260,9 @@ static float *sculpt_face_sets_automasking_init(Sculpt *sd, Object *ob, float *a
int tot_vert = SCULPT_vertex_count_get(ss);
int active_face_set = SCULPT_active_face_set_get(ss);
for (int i = 0; i < tot_vert; i++) {
- if (!SCULPT_vertex_has_face_set(ss, i, active_face_set)) {
+ SculptVertRef vertex = BKE_pbvh_table_index_to_vertex(ss->pbvh, i);
+
+ if (!SCULPT_vertex_has_face_set(ss, vertex, active_face_set)) {
automask_factor[i] *= 0.0f;
}
}
@@ -281,15 +288,17 @@ float *SCULPT_boundary_automasking_init(Object *ob,
int *edge_distance = MEM_callocN(sizeof(int) * totvert, "automask_factor");
for (int i = 0; i < totvert; i++) {
+ SculptVertRef vertex = BKE_pbvh_table_index_to_vertex(ss->pbvh, i);
+
edge_distance[i] = EDGE_DISTANCE_INF;
switch (mode) {
case AUTOMASK_INIT_BOUNDARY_EDGES:
- if (SCULPT_vertex_is_boundary(ss, i)) {
+ if (SCULPT_vertex_is_boundary(ss, vertex)) {
edge_distance[i] = 0;
}
break;
case AUTOMASK_INIT_BOUNDARY_FACE_SETS:
- if (!SCULPT_vertex_has_unique_face_set(ss, i)) {
+ if (!SCULPT_vertex_has_unique_face_set(ss, vertex)) {
edge_distance[i] = 0;
}
break;
@@ -298,9 +307,11 @@ float *SCULPT_boundary_automasking_init(Object *ob,
for (int propagation_it = 0; propagation_it < propagation_steps; propagation_it++) {
for (int i = 0; i < totvert; i++) {
+ SculptVertRef vertex = BKE_pbvh_table_index_to_vertex(ss->pbvh, i);
+
if (edge_distance[i] == EDGE_DISTANCE_INF) {
SculptVertexNeighborIter ni;
- SCULPT_VERTEX_NEIGHBORS_ITER_BEGIN (ss, i, ni) {
+ SCULPT_VERTEX_NEIGHBORS_ITER_BEGIN (ss, vertex, ni) {
if (edge_distance[ni.index] == propagation_it) {
edge_distance[i] = propagation_it + 1;
}
diff --git a/source/blender/editors/sculpt_paint/sculpt_boundary.c b/source/blender/editors/sculpt_paint/sculpt_boundary.c
index 5dcaf7d9468..67b7a7daa36 100644
--- a/source/blender/editors/sculpt_paint/sculpt_boundary.c
+++ b/source/blender/editors/sculpt_paint/sculpt_boundary.c
@@ -62,19 +62,28 @@
#define BOUNDARY_STEPS_NONE -1
typedef struct BoundaryInitialVertexFloodFillData {
- int initial_vertex;
+ SculptVertRef initial_vertex;
+ int initial_vertex_index;
int boundary_initial_vertex_steps;
- int boundary_initial_vertex;
+
+ SculptVertRef boundary_initial_vertex;
+
int *floodfill_steps;
float radius_sq;
} BoundaryInitialVertexFloodFillData;
-static bool boundary_initial_vertex_floodfill_cb(
- SculptSession *ss, int from_v, int to_v, bool is_duplicate, void *userdata)
+static bool boundary_initial_vertex_floodfill_cb(SculptSession *ss,
+ SculptVertRef from_vref,
+ SculptVertRef to_vref,
+ bool is_duplicate,
+ void *userdata)
{
BoundaryInitialVertexFloodFillData *data = userdata;
- if (!SCULPT_vertex_visible_get(ss, to_v)) {
+ int to_v = BKE_pbvh_vertex_index_to_table(ss->pbvh, to_vref);
+ int from_v = BKE_pbvh_vertex_index_to_table(ss->pbvh, from_vref);
+
+ if (!SCULPT_vertex_visible_get(ss, to_vref)) {
return false;
}
@@ -85,23 +94,25 @@ static bool boundary_initial_vertex_floodfill_cb(
data->floodfill_steps[to_v] = data->floodfill_steps[from_v];
}
- if (SCULPT_vertex_is_boundary(ss, to_v)) {
+ if (SCULPT_vertex_is_boundary(ss, to_vref)) {
if (data->floodfill_steps[to_v] < data->boundary_initial_vertex_steps) {
data->boundary_initial_vertex_steps = data->floodfill_steps[to_v];
- data->boundary_initial_vertex = to_v;
+ data->boundary_initial_vertex = to_vref;
}
}
const float len_sq = len_squared_v3v3(SCULPT_vertex_co_get(ss, data->initial_vertex),
- SCULPT_vertex_co_get(ss, to_v));
+ SCULPT_vertex_co_get(ss, to_vref));
return len_sq < data->radius_sq;
}
/* From a vertex index anywhere in the mesh, returns the closest vertex in a mesh boundary inside
* the given radius, if it exists. */
-static int sculpt_boundary_get_closest_boundary_vertex(SculptSession *ss,
- const int initial_vertex,
- const float radius)
+static SculptVertRef sculpt_boundary_get_closest_boundary_vertex(
+ SculptSession *ss,
+ const SculptVertRef initial_vertex,
+ const int initial_vertex_index,
+ const float radius)
{
if (SCULPT_vertex_is_boundary(ss, initial_vertex)) {
@@ -114,6 +125,7 @@ static int sculpt_boundary_get_closest_boundary_vertex(SculptSession *ss,
BoundaryInitialVertexFloodFillData fdata = {
.initial_vertex = initial_vertex,
+ .initial_vertex_index = initial_vertex_index,
.boundary_initial_vertex = BOUNDARY_VERTEX_NONE,
.boundary_initial_vertex_steps = INT_MAX,
.radius_sq = radius * radius,
@@ -134,28 +146,36 @@ static int sculpt_boundary_get_closest_boundary_vertex(SculptSession *ss,
* deformations usually need in the boundary. */
static int BOUNDARY_INDICES_BLOCK_SIZE = 300;
-static void sculpt_boundary_index_add(SculptBoundary *boundary,
- const int new_index,
+static void sculpt_boundary_index_add(SculptSession *ss,
+ SculptBoundary *boundary,
+ const SculptVertRef new_index,
const float distance,
GSet *included_vertices)
{
boundary->vertices[boundary->num_vertices] = new_index;
+ boundary->vertex_indices[boundary->num_vertices] = BKE_pbvh_vertex_index_to_table(ss->pbvh, new_index);
+
if (boundary->distance) {
- boundary->distance[new_index] = distance;
+ boundary->distance[BKE_pbvh_vertex_index_to_table(ss->pbvh, new_index)] = distance;
}
if (included_vertices) {
- BLI_gset_add(included_vertices, POINTER_FROM_INT(new_index));
+ BLI_gset_add(included_vertices, POINTER_FROM_INT(new_index.i));
}
boundary->num_vertices++;
if (boundary->num_vertices >= boundary->vertices_capacity) {
boundary->vertices_capacity += BOUNDARY_INDICES_BLOCK_SIZE;
- boundary->vertices = MEM_reallocN_id(
- boundary->vertices, boundary->vertices_capacity * sizeof(int), "boundary indices");
+ boundary->vertices = MEM_reallocN_id(boundary->vertices,
+ boundary->vertices_capacity * sizeof(SculptVertRef),
+ "boundary vertrefs");
+ boundary->vertex_indices = MEM_reallocN_id(
+ boundary->vertex_indices, boundary->vertices_capacity * sizeof(int), "boundary indices");
}
};
-static void sculpt_boundary_preview_edge_add(SculptBoundary *boundary, const int v1, const int v2)
+static void sculpt_boundary_preview_edge_add(SculptBoundary *boundary,
+ const SculptVertRef v1,
+ const SculptVertRef v2)
{
boundary->edges[boundary->num_edges].v1 = v1;
@@ -175,7 +195,7 @@ static void sculpt_boundary_preview_edge_add(SculptBoundary *boundary, const int
* as well as to check if the initial vertex is valid.
*/
static bool sculpt_boundary_is_vertex_in_editable_boundary(SculptSession *ss,
- const int initial_vertex)
+ const SculptVertRef initial_vertex)
{
if (!SCULPT_vertex_visible_get(ss, initial_vertex)) {
@@ -186,9 +206,9 @@ static bool sculpt_boundary_is_vertex_in_editable_boundary(SculptSession *ss,
int boundary_vertex_count = 0;
SculptVertexNeighborIter ni;
SCULPT_VERTEX_NEIGHBORS_ITER_BEGIN (ss, initial_vertex, ni) {
- if (SCULPT_vertex_visible_get(ss, ni.index)) {
+ if (SCULPT_vertex_visible_get(ss, ni.vertex)) {
neighbor_count++;
- if (SCULPT_vertex_is_boundary(ss, ni.index)) {
+ if (SCULPT_vertex_is_boundary(ss, ni.vertex)) {
boundary_vertex_count++;
}
}
@@ -218,22 +238,25 @@ typedef struct BoundaryFloodFillData {
GSet *included_vertices;
EdgeSet *preview_edges;
- int last_visited_vertex;
+ SculptVertRef last_visited_vertex;
} BoundaryFloodFillData;
static bool boundary_floodfill_cb(
- SculptSession *ss, int from_v, int to_v, bool is_duplicate, void *userdata)
+ SculptSession *ss, SculptVertRef from_v, SculptVertRef to_v, bool is_duplicate, void *userdata)
{
BoundaryFloodFillData *data = userdata;
SculptBoundary *boundary = data->boundary;
+ const int from_v_i = BKE_pbvh_vertex_index_to_table(ss->pbvh, from_v);
+
if (SCULPT_vertex_is_boundary(ss, to_v)) {
const float edge_len = len_v3v3(SCULPT_vertex_co_get(ss, from_v),
SCULPT_vertex_co_get(ss, to_v));
const float distance_boundary_to_dst = boundary->distance ?
- boundary->distance[from_v] + edge_len :
+ boundary->distance[from_v_i] + edge_len :
0.0f;
- sculpt_boundary_index_add(boundary, to_v, distance_boundary_to_dst, data->included_vertices);
+ sculpt_boundary_index_add(
+ ss, boundary, to_v, distance_boundary_to_dst, data->included_vertices);
if (!is_duplicate) {
sculpt_boundary_preview_edge_add(boundary, from_v, to_v);
}
@@ -245,12 +268,15 @@ static bool boundary_floodfill_cb(
static void sculpt_boundary_indices_init(SculptSession *ss,
SculptBoundary *boundary,
const bool init_boundary_distances,
- const int initial_boundary_index)
+ const SculptVertRef initial_boundary_index)
{
const int totvert = SCULPT_vertex_count_get(ss);
boundary->vertices = MEM_malloc_arrayN(
+ BOUNDARY_INDICES_BLOCK_SIZE, sizeof(SculptVertRef), "boundary vrefs");
+ boundary->vertex_indices = MEM_malloc_arrayN(
BOUNDARY_INDICES_BLOCK_SIZE, sizeof(int), "boundary indices");
+
if (init_boundary_distances) {
boundary->distance = MEM_calloc_arrayN(totvert, sizeof(float), "boundary distances");
}
@@ -264,7 +290,7 @@ static void sculpt_boundary_indices_init(SculptSession *ss,
boundary->initial_vertex = initial_boundary_index;
copy_v3_v3(boundary->initial_vertex_position,
SCULPT_vertex_co_get(ss, boundary->initial_vertex));
- sculpt_boundary_index_add(boundary, initial_boundary_index, 0.0f, included_vertices);
+ sculpt_boundary_index_add(ss, boundary, initial_boundary_index, 0.0f, included_vertices);
SCULPT_floodfill_add_initial(&flood, initial_boundary_index);
BoundaryFloodFillData fdata = {
@@ -278,13 +304,13 @@ static void sculpt_boundary_indices_init(SculptSession *ss,
SCULPT_floodfill_free(&flood);
/* Check if the boundary loops into itself and add the extra preview edge to close the loop. */
- if (fdata.last_visited_vertex != BOUNDARY_VERTEX_NONE &&
+ if (fdata.last_visited_vertex.i != BOUNDARY_VERTEX_NONE &&
sculpt_boundary_is_vertex_in_editable_boundary(ss, fdata.last_visited_vertex)) {
SculptVertexNeighborIter ni;
SCULPT_VERTEX_NEIGHBORS_ITER_BEGIN (ss, fdata.last_visited_vertex, ni) {
- if (BLI_gset_haskey(included_vertices, POINTER_FROM_INT(ni.index)) &&
- sculpt_boundary_is_vertex_in_editable_boundary(ss, ni.index)) {
- sculpt_boundary_preview_edge_add(boundary, fdata.last_visited_vertex, ni.index);
+ if (BLI_gset_haskey(included_vertices, POINTER_FROM_INT(ni.vertex.i)) &&
+ sculpt_boundary_is_vertex_in_editable_boundary(ss, ni.vertex)) {
+ sculpt_boundary_preview_edge_add(boundary, fdata.last_visited_vertex, ni.vertex);
boundary->forms_loop = true;
}
}
@@ -302,7 +328,7 @@ static void sculpt_boundary_indices_init(SculptSession *ss,
*/
static void sculpt_boundary_edit_data_init(SculptSession *ss,
SculptBoundary *boundary,
- const int initial_vertex,
+ const SculptVertRef initial_vertex,
const float radius)
{
const int totvert = SCULPT_vertex_count_get(ss);
@@ -313,19 +339,22 @@ static void sculpt_boundary_edit_data_init(SculptSession *ss,
totvert, sizeof(SculptBoundaryEditInfo), "Boundary edit info");
for (int i = 0; i < totvert; i++) {
- boundary->edit_info[i].original_vertex = BOUNDARY_VERTEX_NONE;
+ boundary->edit_info[i].original_vertex.i = BOUNDARY_VERTEX_NONE;
+ boundary->edit_info[i].original_vertex_i = BOUNDARY_VERTEX_NONE;
boundary->edit_info[i].num_propagation_steps = BOUNDARY_STEPS_NONE;
}
- GSQueue *current_iteration = BLI_gsqueue_new(sizeof(int));
- GSQueue *next_iteration = BLI_gsqueue_new(sizeof(int));
+ GSQueue *current_iteration = BLI_gsqueue_new(sizeof(SculptVertRef));
+ GSQueue *next_iteration = BLI_gsqueue_new(sizeof(SculptVertRef));
/* Initialized the first iteration with the vertices already in the boundary. This is propagation
* step 0. */
BLI_bitmap *visited_vertices = BLI_BITMAP_NEW(SCULPT_vertex_count_get(ss), "visited_vertices");
for (int i = 0; i < boundary->num_vertices; i++) {
- boundary->edit_info[boundary->vertices[i]].original_vertex = boundary->vertices[i];
- boundary->edit_info[boundary->vertices[i]].num_propagation_steps = 0;
+ boundary->edit_info[boundary->vertex_indices[i]].original_vertex = boundary->vertices[i];
+ boundary->edit_info[boundary->vertex_indices[i]].original_vertex_i =
+ boundary->vertex_indices[i];
+ boundary->edit_info[boundary->vertex_indices[i]].num_propagation_steps = 0;
/* This ensures that all duplicate vertices in the boundary have the same original_vertex
* index, so the deformation for them will be the same. */
@@ -333,7 +362,11 @@ static void sculpt_boundary_edit_data_init(SculptSession *ss,
SculptVertexNeighborIter ni_duplis;
SCULPT_VERTEX_DUPLICATES_AND_NEIGHBORS_ITER_BEGIN (ss, boundary->vertices[i], ni_duplis) {
if (ni_duplis.is_duplicate) {
- boundary->edit_info[ni_duplis.index].original_vertex = boundary->vertices[i];
+ int index = ni_duplis.index;
+
+ boundary->edit_info[index].original_vertex = boundary->vertices[i];
+ boundary->edit_info[index].original_vertex_i = BKE_pbvh_vertex_index_to_table(
+ ss->pbvh, boundary->vertices[i]);
}
}
SCULPT_VERTEX_NEIGHBORS_ITER_END(ni_duplis);
@@ -354,29 +387,35 @@ static void sculpt_boundary_edit_data_init(SculptSession *ss,
}
while (!BLI_gsqueue_is_empty(current_iteration)) {
- int from_v;
+ SculptVertRef from_v;
BLI_gsqueue_pop(current_iteration, &from_v);
+ const int from_v_i = BKE_pbvh_vertex_index_to_table(ss->pbvh, from_v);
SculptVertexNeighborIter ni;
SCULPT_VERTEX_DUPLICATES_AND_NEIGHBORS_ITER_BEGIN (ss, from_v, ni) {
- const bool is_visible = SCULPT_vertex_visible_get(ss, ni.index);
+ const int index = ni.index;
+
+ const bool is_visible = SCULPT_vertex_visible_get(ss, ni.vertex);
if (is_visible &&
- boundary->edit_info[ni.index].num_propagation_steps == BOUNDARY_STEPS_NONE) {
- boundary->edit_info[ni.index].original_vertex =
- boundary->edit_info[from_v].original_vertex;
+ boundary->edit_info[index].num_propagation_steps == BOUNDARY_STEPS_NONE) {
- BLI_BITMAP_ENABLE(visited_vertices, ni.index);
+ boundary->edit_info[index].original_vertex =
+ boundary->edit_info[from_v_i].original_vertex;
+ boundary->edit_info[index].original_vertex_i =
+ boundary->edit_info[from_v_i].original_vertex_i;
+
+ BLI_BITMAP_ENABLE(visited_vertices, index);
if (ni.is_duplicate) {
/* Grids duplicates handling. */
- boundary->edit_info[ni.index].num_propagation_steps =
- boundary->edit_info[from_v].num_propagation_steps;
+ boundary->edit_info[index].num_propagation_steps =
+ boundary->edit_info[from_v_i].num_propagation_steps;
}
else {
- boundary->edit_info[ni.index].num_propagation_steps =
- boundary->edit_info[from_v].num_propagation_steps + 1;
+ boundary->edit_info[index].num_propagation_steps =
+ boundary->edit_info[from_v_i].num_propagation_steps + 1;
- BLI_gsqueue_push(next_iteration, &ni.index);
+ BLI_gsqueue_push(next_iteration, &ni.vertex);
/* When copying the data to the neighbor for the next iteration, it has to be copied to
* all its duplicates too. This is because it is not possible to know if the updated
@@ -384,12 +423,15 @@ static void sculpt_boundary_edit_data_init(SculptSession *ss,
* copy the data in the from_v neighbor iterator. */
if (has_duplicates) {
SculptVertexNeighborIter ni_duplis;
- SCULPT_VERTEX_DUPLICATES_AND_NEIGHBORS_ITER_BEGIN (ss, ni.index, ni_duplis) {
+ SCULPT_VERTEX_DUPLICATES_AND_NEIGHBORS_ITER_BEGIN (ss, ni.vertex, ni_duplis) {
if (ni_duplis.is_duplicate) {
- boundary->edit_info[ni_duplis.index].original_vertex =
- boundary->edit_info[from_v].original_vertex;
- boundary->edit_info[ni_duplis.index].num_propagation_steps =
- boundary->edit_info[from_v].num_propagation_steps + 1;
+ const int index = ni_duplis.index;
+ boundary->edit_info[index].original_vertex =
+ boundary->edit_info[from_v_i].original_vertex;
+ boundary->edit_info[index].original_vertex_i =
+ boundary->edit_info[from_v_i].original_vertex_i;
+ boundary->edit_info[index].num_propagation_steps =
+ boundary->edit_info[from_v_i].num_propagation_steps + 1;
}
}
SCULPT_VERTEX_NEIGHBORS_ITER_END(ni_duplis);
@@ -397,11 +439,11 @@ static void sculpt_boundary_edit_data_init(SculptSession *ss,
/* Check the distance using the vertex that was propagated from the initial vertex that
* was used to initialize the boundary. */
- if (boundary->edit_info[from_v].original_vertex == initial_vertex) {
- boundary->pivot_vertex = ni.index;
- copy_v3_v3(boundary->initial_pivot_position, SCULPT_vertex_co_get(ss, ni.index));
+ if (boundary->edit_info[from_v_i].original_vertex.i == initial_vertex.i) {
+ boundary->pivot_vertex = ni.vertex;
+ copy_v3_v3(boundary->initial_pivot_position, SCULPT_vertex_co_get(ss, ni.vertex));
accum_distance += len_v3v3(SCULPT_vertex_co_get(ss, from_v),
- SCULPT_vertex_co_get(ss, ni.index));
+ SCULPT_vertex_co_get(ss, ni.vertex));
}
}
}
@@ -411,7 +453,7 @@ static void sculpt_boundary_edit_data_init(SculptSession *ss,
/* Copy the new vertices to the queue to be processed in the next iteration. */
while (!BLI_gsqueue_is_empty(next_iteration)) {
- int next_v;
+ SculptVertRef next_v;
BLI_gsqueue_pop(next_iteration, &next_v);
BLI_gsqueue_push(current_iteration, &next_v);
}
@@ -442,7 +484,7 @@ static void sculpt_boundary_falloff_factor_init(SculptSession *ss,
brush, boundary->edit_info[i].num_propagation_steps, boundary->max_propagation_steps);
}
- if (boundary->edit_info[i].original_vertex == boundary->initial_vertex) {
+ if (boundary->edit_info[i].original_vertex.i == boundary->initial_vertex.i) {
/* All vertices that are propagated from the original vertex won't be affected by the
* boundary falloff, so there is no need to calculate anything else. */
continue;
@@ -454,7 +496,8 @@ static void sculpt_boundary_falloff_factor_init(SculptSession *ss,
continue;
}
- const float boundary_distance = boundary->distance[boundary->edit_info[i].original_vertex];
+ const float boundary_distance = boundary->distance[BKE_pbvh_vertex_index_to_table(
+ ss->pbvh, boundary->edit_info[i].original_vertex)];
float falloff_distance = 0.0f;
float direction = 1.0f;
@@ -490,22 +533,22 @@ static void sculpt_boundary_falloff_factor_init(SculptSession *ss,
* return NULL if there is no boundary from the given vertex using the given radius. */
SculptBoundary *SCULPT_boundary_data_init(Object *object,
Brush *brush,
- const int initial_vertex,
+ const SculptVertRef initial_vertex,
const float radius)
{
SculptSession *ss = object->sculpt;
- if (initial_vertex == BOUNDARY_VERTEX_NONE) {
+ if (initial_vertex.i == BOUNDARY_VERTEX_NONE) {
return NULL;
}
SCULPT_vertex_random_access_ensure(ss);
SCULPT_boundary_info_ensure(object);
- const int boundary_initial_vertex = sculpt_boundary_get_closest_boundary_vertex(
- ss, initial_vertex, radius);
+ const SculptVertRef boundary_initial_vertex = sculpt_boundary_get_closest_boundary_vertex(
+ ss, initial_vertex, BKE_pbvh_vertex_index_to_table(ss->pbvh, initial_vertex), radius);
- if (boundary_initial_vertex == BOUNDARY_VERTEX_NONE) {
+ if (boundary_initial_vertex.i == BOUNDARY_VERTEX_NONE) {
return NULL;
}
@@ -554,24 +597,27 @@ static void sculpt_boundary_bend_data_init(SculptSession *ss, SculptBoundary *bo
if (boundary->edit_info[i].num_propagation_steps == boundary->max_propagation_steps) {
float dir[3];
float normal[3];
- SCULPT_vertex_normal_get(ss, i, normal);
+ SculptVertRef vertex = BKE_pbvh_table_index_to_vertex(ss->pbvh, i);
+
+ SCULPT_vertex_normal_get(ss, vertex, normal);
sub_v3_v3v3(dir,
SCULPT_vertex_co_get(ss, boundary->edit_info[i].original_vertex),
- SCULPT_vertex_co_get(ss, i));
- cross_v3_v3v3(
- boundary->bend.pivot_rotation_axis[boundary->edit_info[i].original_vertex], dir, normal);
- normalize_v3(boundary->bend.pivot_rotation_axis[boundary->edit_info[i].original_vertex]);
- copy_v3_v3(boundary->bend.pivot_positions[boundary->edit_info[i].original_vertex],
- SCULPT_vertex_co_get(ss, i));
+ SCULPT_vertex_co_get(ss, vertex));
+ cross_v3_v3v3(boundary->bend.pivot_rotation_axis[boundary->edit_info[i].original_vertex_i],
+ dir,
+ normal);
+ normalize_v3(boundary->bend.pivot_rotation_axis[boundary->edit_info[i].original_vertex_i]);
+ copy_v3_v3(boundary->bend.pivot_positions[boundary->edit_info[i].original_vertex_i],
+ SCULPT_vertex_co_get(ss, vertex));
}
}
for (int i = 0; i < totvert; i++) {
if (boundary->edit_info[i].num_propagation_steps != BOUNDARY_STEPS_NONE) {
copy_v3_v3(boundary->bend.pivot_positions[i],
- boundary->bend.pivot_positions[boundary->edit_info[i].original_vertex]);
+ boundary->bend.pivot_positions[boundary->edit_info[i].original_vertex_i]);
copy_v3_v3(boundary->bend.pivot_rotation_axis[i],
- boundary->bend.pivot_rotation_axis[boundary->edit_info[i].original_vertex]);
+ boundary->bend.pivot_rotation_axis[boundary->edit_info[i].original_vertex_i]);
}
}
}
@@ -583,17 +629,20 @@ static void sculpt_boundary_slide_data_init(SculptSession *ss, SculptBoundary *b
for (int i = 0; i < totvert; i++) {
if (boundary->edit_info[i].num_propagation_steps == boundary->max_propagation_steps) {
- sub_v3_v3v3(boundary->slide.directions[boundary->edit_info[i].original_vertex],
+ const int index = boundary->edit_info[i].original_vertex_i;
+
+ sub_v3_v3v3(boundary->slide.directions[index],
SCULPT_vertex_co_get(ss, boundary->edit_info[i].original_vertex),
- SCULPT_vertex_co_get(ss, i));
- normalize_v3(boundary->slide.directions[boundary->edit_info[i].original_vertex]);
+ SCULPT_vertex_co_get(ss, BKE_pbvh_table_index_to_vertex(ss->pbvh, i)));
+ normalize_v3(boundary->slide.directions[index]);
}
}
for (int i = 0; i < totvert; i++) {
if (boundary->edit_info[i].num_propagation_steps != BOUNDARY_STEPS_NONE) {
copy_v3_v3(boundary->slide.directions[i],
- boundary->slide.directions[boundary->edit_info[i].original_vertex]);
+ boundary->slide.directions[BKE_pbvh_vertex_index_to_table(
+ ss->pbvh, boundary->edit_info[i].original_vertex)]);
}
}
}
@@ -649,7 +698,7 @@ static void do_boundary_brush_bend_task_cb_ex(void *__restrict userdata,
PBVHVertexIter vd;
SculptOrigVertData orig_data;
- SCULPT_orig_vert_data_init(&orig_data, data->ob, data->nodes[n]);
+ SCULPT_orig_vert_data_init(&orig_data, data->ob, data->nodes[n], SCULPT_UNDO_COORDS);
const float disp = strength * sculpt_boundary_displacement_from_grab_delta_get(ss, boundary);
float angle_factor = disp / ss->cache->radius;
@@ -668,13 +717,15 @@ static void do_boundary_brush_bend_task_cb_ex(void *__restrict userdata,
orig_data.co, boundary->initial_vertex_position, symm)) {
const float mask = vd.mask ? 1.0f - *vd.mask : 1.0f;
float t_orig_co[3];
+ const int index = vd.index;
+
float *target_co = SCULPT_brush_deform_target_vertex_co_get(ss, brush->deform_target, &vd);
- sub_v3_v3v3(t_orig_co, orig_data.co, boundary->bend.pivot_positions[vd.index]);
+ sub_v3_v3v3(t_orig_co, orig_data.co, boundary->bend.pivot_positions[index]);
rotate_v3_v3v3fl(target_co,
t_orig_co,
- boundary->bend.pivot_rotation_axis[vd.index],
- angle * boundary->edit_info[vd.index].strength_factor * mask);
- add_v3_v3(target_co, boundary->bend.pivot_positions[vd.index]);
+ boundary->bend.pivot_rotation_axis[index],
+ angle * boundary->edit_info[index].strength_factor * mask);
+ add_v3_v3(target_co, boundary->bend.pivot_positions[index]);
}
}
@@ -700,7 +751,7 @@ static void do_boundary_brush_slide_task_cb_ex(void *__restrict userdata,
PBVHVertexIter vd;
SculptOrigVertData orig_data;
- SCULPT_orig_vert_data_init(&orig_data, data->ob, data->nodes[n]);
+ SCULPT_orig_vert_data_init(&orig_data, data->ob, data->nodes[n], SCULPT_UNDO_COORDS);
const float disp = sculpt_boundary_displacement_from_grab_delta_get(ss, boundary);
@@ -742,7 +793,7 @@ static void do_boundary_brush_inflate_task_cb_ex(void *__restrict userdata,
PBVHVertexIter vd;
SculptOrigVertData orig_data;
- SCULPT_orig_vert_data_init(&orig_data, data->ob, data->nodes[n]);
+ SCULPT_orig_vert_data_init(&orig_data, data->ob, data->nodes[n], SCULPT_UNDO_COORDS);
const float disp = sculpt_boundary_displacement_from_grab_delta_get(ss, boundary);
@@ -786,7 +837,7 @@ static void do_boundary_brush_grab_task_cb_ex(void *__restrict userdata,
PBVHVertexIter vd;
SculptOrigVertData orig_data;
- SCULPT_orig_vert_data_init(&orig_data, data->ob, data->nodes[n]);
+ SCULPT_orig_vert_data_init(&orig_data, data->ob, data->nodes[n], SCULPT_UNDO_COORDS);
BKE_pbvh_vertex_iter_begin(ss->pbvh, data->nodes[n], vd, PBVH_ITER_UNIQUE)
{
@@ -826,7 +877,7 @@ static void do_boundary_brush_twist_task_cb_ex(void *__restrict userdata,
PBVHVertexIter vd;
SculptOrigVertData orig_data;
- SCULPT_orig_vert_data_init(&orig_data, data->ob, data->nodes[n]);
+ SCULPT_orig_vert_data_init(&orig_data, data->ob, data->nodes[n], SCULPT_UNDO_COORDS);
const float disp = strength * sculpt_boundary_displacement_from_grab_delta_get(ss, boundary);
float angle_factor = disp / ss->cache->radius;
@@ -877,7 +928,7 @@ static void do_boundary_brush_smooth_task_cb_ex(void *__restrict userdata,
PBVHVertexIter vd;
SculptOrigVertData orig_data;
- SCULPT_orig_vert_data_init(&orig_data, data->ob, data->nodes[n]);
+ SCULPT_orig_vert_data_init(&orig_data, data->ob, data->nodes[n], SCULPT_UNDO_COORDS);
BKE_pbvh_vertex_iter_begin(ss->pbvh, data->nodes[n], vd, PBVH_ITER_UNIQUE)
{
@@ -895,9 +946,9 @@ static void do_boundary_brush_smooth_task_cb_ex(void *__restrict userdata,
int total_neighbors = 0;
const int current_propagation_steps = boundary->edit_info[vd.index].num_propagation_steps;
SculptVertexNeighborIter ni;
- SCULPT_VERTEX_NEIGHBORS_ITER_BEGIN (ss, vd.index, ni) {
+ SCULPT_VERTEX_NEIGHBORS_ITER_BEGIN (ss, vd.vertex, ni) {
if (current_propagation_steps == boundary->edit_info[ni.index].num_propagation_steps) {
- add_v3_v3(coord_accum, SCULPT_vertex_co_get(ss, ni.index));
+ add_v3_v3(coord_accum, SCULPT_vertex_co_get(ss, ni.vertex));
total_neighbors++;
}
}
@@ -931,7 +982,8 @@ void SCULPT_do_boundary_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totn
const int symm_area = ss->cache->mirror_symmetry_pass;
if (SCULPT_stroke_is_first_brush_step_of_symmetry_pass(ss->cache)) {
- int initial_vertex;
+ SculptVertRef initial_vertex;
+
if (ss->cache->mirror_symmetry_pass == 0) {
initial_vertex = SCULPT_active_vertex_get(ss);
}
diff --git a/source/blender/editors/sculpt_paint/sculpt_cloth.c b/source/blender/editors/sculpt_paint/sculpt_cloth.c
index 0ac0d796ca4..1eab35ae0e5 100644
--- a/source/blender/editors/sculpt_paint/sculpt_cloth.c
+++ b/source/blender/editors/sculpt_paint/sculpt_cloth.c
@@ -219,20 +219,25 @@ static void cloth_brush_reallocate_constraints(SculptClothSimulation *cloth_sim)
static void cloth_brush_add_length_constraint(SculptSession *ss,
SculptClothSimulation *cloth_sim,
const int node_index,
- const int v1,
- const int v2,
+ const int v1i,
+ const int v2i,
const bool use_persistent)
{
SculptClothLengthConstraint *length_constraint =
&cloth_sim->length_constraints[cloth_sim->tot_length_constraints];
- length_constraint->elem_index_a = v1;
- length_constraint->elem_index_b = v2;
+ SculptVertRef v1, v2;
+
+ v1 = BKE_pbvh_table_index_to_vertex(ss->pbvh, v1i);
+ v2 = BKE_pbvh_table_index_to_vertex(ss->pbvh, v2i);
+
+ length_constraint->elem_index_a = v1i;
+ length_constraint->elem_index_b = v2i;
length_constraint->node = node_index;
- length_constraint->elem_position_a = cloth_sim->pos[v1];
- length_constraint->elem_position_b = cloth_sim->pos[v2];
+ length_constraint->elem_position_a = cloth_sim->pos[v1i];
+ length_constraint->elem_position_b = cloth_sim->pos[v2i];
length_constraint->type = SCULPT_CLOTH_CONSTRAINT_STRUCTURAL;
@@ -252,7 +257,7 @@ static void cloth_brush_add_length_constraint(SculptSession *ss,
cloth_brush_reallocate_constraints(cloth_sim);
/* Add the constraint to the #GSet to avoid creating it again. */
- BLI_edgeset_add(cloth_sim->created_length_constraints, v1, v2);
+ BLI_edgeset_add(cloth_sim->created_length_constraints, v1i, v2i);
}
static void cloth_brush_add_softbody_constraint(SculptClothSimulation *cloth_sim,
@@ -387,7 +392,7 @@ static void do_cloth_brush_build_constraints_task_cb_ex(
int tot_indices = 0;
build_indices[tot_indices] = vd.index;
tot_indices++;
- SCULPT_VERTEX_NEIGHBORS_ITER_BEGIN (ss, vd.index, ni) {
+ SCULPT_VERTEX_NEIGHBORS_ITER_BEGIN (ss, vd.vertex, ni) {
build_indices[tot_indices] = ni.index;
tot_indices++;
}
@@ -556,7 +561,7 @@ static void do_cloth_brush_apply_forces_task_cb_ex(void *__restrict userdata,
vd.no,
vd.fno,
vd.mask ? *vd.mask : 0.0f,
- vd.index,
+ vd.vertex,
thread_id);
float brush_disp[3];
@@ -796,7 +801,7 @@ static void do_cloth_brush_solve_simulation_task_cb_ex(
mul_v3_fl(pos_diff, (1.0f - cloth_sim->damping) * sim_factor);
const float mask_v = (1.0f - (vd.mask ? *vd.mask : 0.0f)) *
- SCULPT_automasking_factor_get(automasking, ss, vd.index);
+ SCULPT_automasking_factor_get(automasking, ss, vd.vertex);
madd_v3_v3fl(cloth_sim->pos[i], pos_diff, mask_v);
madd_v3_v3fl(cloth_sim->pos[i], cloth_sim->acceleration[i], mask_v);
@@ -843,6 +848,9 @@ static void cloth_brush_satisfy_constraints(SculptSession *ss,
const int v1 = constraint->elem_index_a;
const int v2 = constraint->elem_index_b;
+ const SculptVertRef v1ref = BKE_pbvh_table_index_to_vertex(ss->pbvh, v1);
+ const SculptVertRef v2ref = BKE_pbvh_table_index_to_vertex(ss->pbvh, v2);
+
float v1_to_v2[3];
sub_v3_v3v3(v1_to_v2, constraint->elem_position_b, constraint->elem_position_a);
const float current_distance = len_v3(v1_to_v2);
@@ -865,10 +873,10 @@ static void cloth_brush_satisfy_constraints(SculptSession *ss,
mul_v3_v3fl(correction_vector_half, correction_vector, 0.5f);
- const float mask_v1 = (1.0f - SCULPT_vertex_mask_get(ss, v1)) *
- SCULPT_automasking_factor_get(automasking, ss, v1);
- const float mask_v2 = (1.0f - SCULPT_vertex_mask_get(ss, v2)) *
- SCULPT_automasking_factor_get(automasking, ss, v2);
+ const float mask_v1 = (1.0f - SCULPT_vertex_mask_get(ss, v1ref)) *
+ SCULPT_automasking_factor_get(automasking, ss, v1ref);
+ const float mask_v2 = (1.0f - SCULPT_vertex_mask_get(ss, v2ref)) *
+ SCULPT_automasking_factor_get(automasking, ss, v2ref);
float sim_location[3];
cloth_brush_simulation_location_get(ss, brush, sim_location);
@@ -1141,16 +1149,20 @@ void SCULPT_cloth_brush_simulation_init(SculptSession *ss, SculptClothSimulation
const int totverts = SCULPT_vertex_count_get(ss);
const bool has_deformation_pos = cloth_sim->deformation_pos != NULL;
const bool has_softbody_pos = cloth_sim->softbody_pos != NULL;
+ SCULPT_vertex_random_access_ensure(ss);
+
for (int i = 0; i < totverts; i++) {
- copy_v3_v3(cloth_sim->last_iteration_pos[i], SCULPT_vertex_co_get(ss, i));
- copy_v3_v3(cloth_sim->init_pos[i], SCULPT_vertex_co_get(ss, i));
- copy_v3_v3(cloth_sim->prev_pos[i], SCULPT_vertex_co_get(ss, i));
+ SculptVertRef vertex = BKE_pbvh_table_index_to_vertex(ss->pbvh, i);
+
+ copy_v3_v3(cloth_sim->last_iteration_pos[i], SCULPT_vertex_co_get(ss, vertex));
+ copy_v3_v3(cloth_sim->init_pos[i], SCULPT_vertex_co_get(ss, vertex));
+ copy_v3_v3(cloth_sim->prev_pos[i], SCULPT_vertex_co_get(ss, vertex));
if (has_deformation_pos) {
- copy_v3_v3(cloth_sim->deformation_pos[i], SCULPT_vertex_co_get(ss, i));
+ copy_v3_v3(cloth_sim->deformation_pos[i], SCULPT_vertex_co_get(ss, vertex));
cloth_sim->deformation_strength[i] = 1.0f;
}
if (has_softbody_pos) {
- copy_v3_v3(cloth_sim->softbody_pos[i], SCULPT_vertex_co_get(ss, i));
+ copy_v3_v3(cloth_sim->softbody_pos[i], SCULPT_vertex_co_get(ss, vertex));
}
}
}
@@ -1159,7 +1171,9 @@ void SCULPT_cloth_brush_store_simulation_state(SculptSession *ss, SculptClothSim
{
const int totverts = SCULPT_vertex_count_get(ss);
for (int i = 0; i < totverts; i++) {
- copy_v3_v3(cloth_sim->pos[i], SCULPT_vertex_co_get(ss, i));
+ SculptVertRef vertex = BKE_pbvh_table_index_to_vertex(ss->pbvh, i);
+
+ copy_v3_v3(cloth_sim->pos[i], SCULPT_vertex_co_get(ss, vertex));
}
}
@@ -1443,13 +1457,13 @@ static void cloth_filter_apply_forces_task_cb(void *__restrict userdata,
BKE_pbvh_vertex_iter_begin(ss->pbvh, node, vd, PBVH_ITER_UNIQUE)
{
float fade = vd.mask ? *vd.mask : 0.0f;
- fade *= SCULPT_automasking_factor_get(ss->filter_cache->automasking, ss, vd.index);
+ fade *= SCULPT_automasking_factor_get(ss->filter_cache->automasking, ss, vd.vertex);
fade = 1.0f - fade;
float force[3] = {0.0f, 0.0f, 0.0f};
float disp[3], temp[3], transform[3][3];
if (ss->filter_cache->active_face_set != SCULPT_FACE_SET_NONE) {
- if (!SCULPT_vertex_has_face_set(ss, vd.index, ss->filter_cache->active_face_set)) {
+ if (!SCULPT_vertex_has_face_set(ss, vd.vertex, ss->filter_cache->active_face_set)) {
continue;
}
}
@@ -1468,7 +1482,7 @@ static void cloth_filter_apply_forces_task_cb(void *__restrict userdata,
break;
case CLOTH_FILTER_INFLATE: {
float normal[3];
- SCULPT_vertex_normal_get(ss, vd.index, normal);
+ SCULPT_vertex_normal_get(ss, vd.vertex, normal);
mul_v3_v3fl(force, normal, fade * data->filter_strength);
} break;
case CLOTH_FILTER_EXPAND:
@@ -1533,7 +1547,9 @@ static int sculpt_cloth_filter_modal(bContext *C, wmOperator *op, const wmEvent
const int totverts = SCULPT_vertex_count_get(ss);
for (int i = 0; i < totverts; i++) {
- copy_v3_v3(ss->filter_cache->cloth_sim->pos[i], SCULPT_vertex_co_get(ss, i));
+ SculptVertRef vertex = BKE_pbvh_table_index_to_vertex(ss->pbvh, i);
+
+ copy_v3_v3(ss->filter_cache->cloth_sim->pos[i], SCULPT_vertex_co_get(ss, vertex));
}
SculptThreadedTaskData data = {
diff --git a/source/blender/editors/sculpt_paint/sculpt_detail.c b/source/blender/editors/sculpt_paint/sculpt_detail.c
index aa1d407dc24..0ee8114aba2 100644
--- a/source/blender/editors/sculpt_paint/sculpt_detail.c
+++ b/source/blender/editors/sculpt_paint/sculpt_detail.c
@@ -126,7 +126,7 @@ static int sculpt_detail_flood_fill_exec(bContext *C, wmOperator *UNUSED(op))
SCULPT_undo_push_node(ob, NULL, SCULPT_UNDO_COORDS);
while (BKE_pbvh_bmesh_update_topology(
- ss->pbvh, PBVH_Collapse | PBVH_Subdivide, center, NULL, size, false, false)) {
+ ss->pbvh, PBVH_Collapse | PBVH_Subdivide, center, NULL, size, false, false, -1, false)) {
for (int i = 0; i < totnodes; i++) {
BKE_pbvh_node_mark_topology_update(nodes[i]);
}
@@ -184,13 +184,13 @@ static void sample_detail_voxel(bContext *C, ViewContext *vc, int mx, int my)
BKE_sculpt_update_object_for_edit(depsgraph, ob, true, false, false);
/* Average the edge length of the connected edges to the active vertex. */
- int active_vertex = SCULPT_active_vertex_get(ss);
+ SculptVertRef active_vertex = SCULPT_active_vertex_get(ss);
const float *active_vertex_co = SCULPT_active_vertex_co_get(ss);
float edge_length = 0.0f;
int tot = 0;
SculptVertexNeighborIter ni;
SCULPT_VERTEX_NEIGHBORS_ITER_BEGIN (ss, active_vertex, ni) {
- edge_length += len_v3v3(active_vertex_co, SCULPT_vertex_co_get(ss, ni.index));
+ edge_length += len_v3v3(active_vertex_co, SCULPT_vertex_co_get(ss, ni.vertex));
tot += 1;
}
SCULPT_VERTEX_NEIGHBORS_ITER_END(ni);
diff --git a/source/blender/editors/sculpt_paint/sculpt_dyntopo.c b/source/blender/editors/sculpt_paint/sculpt_dyntopo.c
index 87e0ea7f6a9..bfd7f843a7e 100644
--- a/source/blender/editors/sculpt_paint/sculpt_dyntopo.c
+++ b/source/blender/editors/sculpt_paint/sculpt_dyntopo.c
@@ -23,6 +23,7 @@
#include "MEM_guardedalloc.h"
+#include "BLI_array.h"
#include "BLI_blenlib.h"
#include "BLI_hash.h"
#include "BLI_math.h"
@@ -110,19 +111,102 @@ void SCULPT_pbvh_clear(Object *ob)
DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
}
+void SCULPT_dyntopo_save_origverts(SculptSession *ss)
+{
+ BMIter iter;
+ BMVert *v;
+
+ BM_ITER_MESH (v, &iter, ss->bm, BM_VERTS_OF_MESH) {
+ float *co = BM_ELEM_CD_GET_VOID_P(v, ss->cd_origco_offset);
+ float *no = BM_ELEM_CD_GET_VOID_P(v, ss->cd_origno_offset);
+
+ copy_v3_v3(co, v->co);
+ copy_v3_v3(no, v->no);
+ }
+}
+
+static char layer_id[] = "_dyntopo_node_id";
+static char origco_id[] = "_dyntopop_orig_co";
+static char origno_id[] = "_dyntopop_orig_no";
+static char origcolor_id[] = "_dyntopo_orig_vcol";
+
+void SCULPT_dyntopo_node_layers_update_offsets(SculptSession *ss)
+{
+ SCULPT_dyntopo_node_layers_add(ss);
+}
+
void SCULPT_dyntopo_node_layers_add(SculptSession *ss)
{
- int cd_node_layer_index;
+ int cd_node_layer_index, cd_face_node_layer_index;
+
+ int cd_origco_index, cd_origno_index, cd_origvcol_index = -1;
+ bool have_vcol = CustomData_has_layer(&ss->bm->vdata, CD_PROP_COLOR);
- char layer_id[] = "_dyntopo_node_id";
+ if (have_vcol) {
+ cd_origvcol_index = CustomData_get_named_layer_index(
+ &ss->bm->vdata, CD_PROP_COLOR, origcolor_id);
+
+ if (cd_origvcol_index == -1) {
+ BM_data_layer_add_named(ss->bm, &ss->bm->vdata, CD_PROP_COLOR, origcolor_id);
+ }
+ }
+
+ cd_origco_index = CustomData_get_named_layer_index(&ss->bm->vdata, CD_PROP_FLOAT3, origco_id);
+ if (cd_origco_index == -1) {
+ BM_data_layer_add_named(ss->bm, &ss->bm->vdata, CD_PROP_FLOAT3, origco_id);
+ }
+
+ cd_origno_index = CustomData_get_named_layer_index(&ss->bm->vdata, CD_PROP_FLOAT3, origno_id);
+ if (cd_origno_index == -1) {
+ BM_data_layer_add_named(ss->bm, &ss->bm->vdata, CD_PROP_FLOAT3, origno_id);
+ }
cd_node_layer_index = CustomData_get_named_layer_index(&ss->bm->vdata, CD_PROP_INT32, layer_id);
if (cd_node_layer_index == -1) {
BM_data_layer_add_named(ss->bm, &ss->bm->vdata, CD_PROP_INT32, layer_id);
- cd_node_layer_index = CustomData_get_named_layer_index(
- &ss->bm->vdata, CD_PROP_INT32, layer_id);
}
+ cd_face_node_layer_index = CustomData_get_named_layer_index(
+ &ss->bm->pdata, CD_PROP_INT32, layer_id);
+ if (cd_face_node_layer_index == -1) {
+ BM_data_layer_add_named(ss->bm, &ss->bm->pdata, CD_PROP_INT32, layer_id);
+ }
+
+ // get indices again, as they might have changed after adding new layers
+ cd_origco_index = CustomData_get_named_layer_index(&ss->bm->vdata, CD_PROP_FLOAT3, origco_id);
+ cd_origno_index = CustomData_get_named_layer_index(&ss->bm->vdata, CD_PROP_FLOAT3, origno_id);
+ cd_node_layer_index = CustomData_get_named_layer_index(&ss->bm->vdata, CD_PROP_INT32, layer_id);
+ cd_face_node_layer_index = CustomData_get_named_layer_index(
+ &ss->bm->pdata, CD_PROP_INT32, layer_id);
+
+ if (have_vcol) {
+ cd_origvcol_index = CustomData_get_named_layer_index(
+ &ss->bm->vdata, CD_PROP_COLOR, origcolor_id);
+
+ ss->cd_origvcol_offset = CustomData_get_n_offset(
+ &ss->bm->vdata,
+ CD_PROP_COLOR,
+ cd_origvcol_index - CustomData_get_layer_index(&ss->bm->vdata, CD_PROP_COLOR));
+ ss->bm->vdata.layers[cd_origvcol_index].flag |= CD_FLAG_TEMPORARY;
+ }
+ else {
+ ss->cd_origvcol_offset = -1;
+ }
+
+ ss->cd_origco_offset = CustomData_get_n_offset(
+ &ss->bm->vdata,
+ CD_PROP_FLOAT3,
+ cd_origco_index - CustomData_get_layer_index(&ss->bm->vdata, CD_PROP_FLOAT3));
+ ss->bm->vdata.layers[cd_origco_index].flag |= CD_FLAG_TEMPORARY;
+
+ ss->cd_vcol_offset = CustomData_get_offset(&ss->bm->vdata, CD_PROP_COLOR);
+
+ ss->cd_origno_offset = CustomData_get_n_offset(
+ &ss->bm->vdata,
+ CD_PROP_FLOAT3,
+ cd_origno_index - CustomData_get_layer_index(&ss->bm->vdata, CD_PROP_FLOAT3));
+ ss->bm->vdata.layers[cd_origno_index].flag |= CD_FLAG_TEMPORARY;
+
ss->cd_vert_node_offset = CustomData_get_n_offset(
&ss->bm->vdata,
CD_PROP_INT32,
@@ -130,19 +214,113 @@ void SCULPT_dyntopo_node_layers_add(SculptSession *ss)
ss->bm->vdata.layers[cd_node_layer_index].flag |= CD_FLAG_TEMPORARY;
- cd_node_layer_index = CustomData_get_named_layer_index(&ss->bm->pdata, CD_PROP_INT32, layer_id);
- if (cd_node_layer_index == -1) {
- BM_data_layer_add_named(ss->bm, &ss->bm->pdata, CD_PROP_INT32, layer_id);
- cd_node_layer_index = CustomData_get_named_layer_index(
- &ss->bm->pdata, CD_PROP_INT32, layer_id);
- }
-
ss->cd_face_node_offset = CustomData_get_n_offset(
&ss->bm->pdata,
CD_PROP_INT32,
- cd_node_layer_index - CustomData_get_layer_index(&ss->bm->pdata, CD_PROP_INT32));
+ cd_face_node_layer_index - CustomData_get_layer_index(&ss->bm->pdata, CD_PROP_INT32));
+
+ ss->bm->pdata.layers[cd_face_node_layer_index].flag |= CD_FLAG_TEMPORARY;
+ ss->cd_faceset_offset = CustomData_get_offset(&ss->bm->pdata, CD_SCULPT_FACE_SETS);
- ss->bm->pdata.layers[cd_node_layer_index].flag |= CD_FLAG_TEMPORARY;
+ SCULPT_dyntopo_save_origverts(ss);
+}
+
+/**
+ Syncs customdata layers with internal bmesh, but ignores deleted layers.
+*/
+void SCULPT_dynamic_topology_sync_layers(Object *ob, Mesh *me)
+{
+ SculptSession *ss = ob->sculpt;
+
+ if (!ss || !ss->bm) {
+ return;
+ }
+
+ bool modified = false;
+ BMesh *bm = ss->bm;
+
+ CustomData *cd1[4] = {&me->vdata, &me->edata, &me->ldata, &me->pdata};
+ CustomData *cd2[4] = {&bm->vdata, &bm->edata, &bm->ldata, &bm->pdata};
+ int types[4] = {BM_VERT, BM_EDGE, BM_LOOP, BM_FACE};
+ int badmask = CD_MASK_MLOOP | CD_MASK_MVERT | CD_MASK_MEDGE | CD_MASK_MPOLY | CD_MASK_ORIGINDEX |
+ CD_MASK_ORIGSPACE | CD_MASK_MFACE;
+
+ for (int i = 0; i < 4; i++) {
+ CustomDataLayer **newlayers = NULL;
+ BLI_array_declare(newlayers);
+
+ CustomData *data1 = cd1[i];
+ CustomData *data2 = cd2[i];
+
+ if (!data1->layers) {
+ continue;
+ }
+
+ for (int j = 0; j < data1->totlayer; j++) {
+ CustomDataLayer *cl1 = data1->layers + j;
+
+ if ((1 << cl1->type) & badmask) {
+ continue;
+ }
+
+ int idx = CustomData_get_named_layer_index(data2, cl1->type, cl1->name);
+ if (idx < 0) {
+ BLI_array_append(newlayers, cl1);
+ }
+ }
+
+ for (int j = 0; j < BLI_array_len(newlayers); j++) {
+ BM_data_layer_add_named(bm, data2, newlayers[j]->type, newlayers[j]->name);
+ modified |= true;
+ }
+
+ char typemap[CD_NUMTYPES] = {
+ 0,
+ };
+
+ for (int j = 0; j < data1->totlayer; j++) {
+ CustomDataLayer *cl = data1->layers + j;
+ CustomDataLayer *cl1 = cl;
+
+ if ((1 << cl1->type) & badmask) {
+ continue;
+ }
+
+ if (typemap[cl1->type]) {
+ continue;
+ }
+
+ typemap[cl1->type] = 1;
+ cl1 = cl + CustomData_get_active_layer(data1, cl1->type);
+
+ int idx = CustomData_get_named_layer_index(data2, cl1->type, cl1->name);
+ CustomData_set_layer_active_index(data2, cl1->type, idx);
+
+ cl1 = cl + CustomData_get_render_layer(data1, cl1->type);
+ idx = CustomData_get_named_layer_index(data2, cl1->type, cl1->name);
+ CustomData_set_layer_render_index(data2, cl1->type, idx);
+
+ cl1 = cl + CustomData_get_stencil_layer(data1, cl1->type);
+ idx = CustomData_get_named_layer_index(data2, cl1->type, cl1->name);
+ CustomData_set_layer_stencil_index(data2, cl1->type, idx);
+
+ cl1 = cl + CustomData_get_clone_layer(data1, cl1->type);
+ idx = CustomData_get_named_layer_index(data2, cl1->type, cl1->name);
+ CustomData_set_layer_clone_index(data2, cl1->type, idx);
+ }
+
+ BLI_array_free(newlayers);
+ }
+
+ if (modified) {
+ SCULPT_dyntopo_node_layers_update_offsets(ss);
+ BKE_pbvh_update_offsets(ss->pbvh,
+ ss->cd_vert_node_offset,
+ ss->cd_face_node_offset,
+ ss->cd_origco_offset,
+ ss->cd_origno_offset,
+ ss->cd_origvcol_offset);
+ }
}
void SCULPT_dynamic_topology_enable_ex(Main *bmain, Depsgraph *depsgraph, Scene *scene, Object *ob)
@@ -165,7 +343,8 @@ void SCULPT_dynamic_topology_enable_ex(Main *bmain, Depsgraph *depsgraph, Scene
.use_toolflags = false,
}));
- BM_mesh_bm_from_me(ss->bm,
+ BM_mesh_bm_from_me(NULL,
+ ss->bm,
me,
(&(struct BMeshFromMeshParams){
.calc_face_normal = true,
@@ -175,6 +354,30 @@ void SCULPT_dynamic_topology_enable_ex(Main *bmain, Depsgraph *depsgraph, Scene
SCULPT_dynamic_topology_triangulate(ss->bm);
BM_data_layer_add(ss->bm, &ss->bm->vdata, CD_PAINT_MASK);
SCULPT_dyntopo_node_layers_add(ss);
+
+ BMIter iter;
+ BMVert *v;
+ int cd_vcol_offset = CustomData_get_offset(&ss->bm->vdata, CD_PROP_COLOR);
+
+ BM_ITER_MESH (v, &iter, ss->bm, BM_VERTS_OF_MESH) {
+ if (ss->cd_origco_offset >= 0) {
+ float *co = BM_ELEM_CD_GET_VOID_P(v, ss->cd_origco_offset);
+ copy_v3_v3(co, v->co);
+ }
+ if (ss->cd_origno_offset >= 0) {
+ float *no = BM_ELEM_CD_GET_VOID_P(v, ss->cd_origno_offset);
+ copy_v3_v3(no, v->no);
+ }
+
+ if (ss->cd_origvcol_offset >= 0) {
+
+ float *ocolor = BM_ELEM_CD_GET_VOID_P(v, ss->cd_origvcol_offset);
+ float *color = BM_ELEM_CD_GET_VOID_P(v, cd_vcol_offset);
+
+ copy_v4_v4(ocolor, color);
+ }
+ }
+
/* Make sure the data for existing faces are initialized. */
if (me->totpoly != ss->bm->totface) {
BM_mesh_normals_update(ss->bm);
@@ -184,7 +387,8 @@ void SCULPT_dynamic_topology_enable_ex(Main *bmain, Depsgraph *depsgraph, Scene
me->flag |= ME_SCULPT_DYNAMIC_TOPOLOGY;
/* Enable logging for undo/redo. */
- ss->bm_log = BM_log_create(ss->bm);
+ ss->bm_log = BM_log_create(
+ ss->bm, ss->cd_origco_offset, ss->cd_origno_offset, ss->cd_origvcol_offset);
/* Update dependency graph, so modifiers that depend on dyntopo being enabled
* are re-evaluated and the PBVH is re-created. */
@@ -233,16 +437,6 @@ static void SCULPT_dynamic_topology_disable_ex(
else {
BKE_sculptsession_bm_to_me(ob, true);
- /* Reset Face Sets as they are no longer valid. */
- if (!CustomData_has_layer(&me->pdata, CD_SCULPT_FACE_SETS)) {
- CustomData_add_layer(&me->pdata, CD_SCULPT_FACE_SETS, CD_CALLOC, NULL, me->totpoly);
- }
- ss->face_sets = CustomData_get_layer(&me->pdata, CD_SCULPT_FACE_SETS);
- for (int i = 0; i < me->totpoly; i++) {
- ss->face_sets[i] = 1;
- }
- me->face_sets_color_default = 1;
-
/* Sync the visibility to vertices manually as the pmap is still not initialized. */
for (int i = 0; i < me->totvert; i++) {
me->mvert[i].flag &= ~ME_HIDE;
@@ -384,6 +578,7 @@ enum eDynTopoWarnFlag SCULPT_dynamic_topology_check(Scene *scene, Object *ob)
BLI_assert(ss->bm == NULL);
UNUSED_VARS_NDEBUG(ss);
+#ifndef DYNTOPO_CD_INTERP
for (int i = 0; i < CD_NUMTYPES; i++) {
if (!ELEM(i, CD_MVERT, CD_MEDGE, CD_MFACE, CD_MLOOP, CD_MPOLY, CD_PAINT_MASK, CD_ORIGINDEX)) {
if (CustomData_has_layer(&me->vdata, i)) {
@@ -397,6 +592,7 @@ enum eDynTopoWarnFlag SCULPT_dynamic_topology_check(Scene *scene, Object *ob)
}
}
}
+#endif
{
VirtualModifierData virtualModifierData;
diff --git a/source/blender/editors/sculpt_paint/sculpt_face_set.c b/source/blender/editors/sculpt_paint/sculpt_face_set.c
index 1fba958d695..0a02f8b543b 100644
--- a/source/blender/editors/sculpt_paint/sculpt_face_set.c
+++ b/source/blender/editors/sculpt_paint/sculpt_face_set.c
@@ -23,6 +23,7 @@
#include "MEM_guardedalloc.h"
+#include "BLI_array.h"
#include "BLI_blenlib.h"
#include "BLI_hash.h"
#include "BLI_math.h"
@@ -135,6 +136,7 @@ static void do_draw_face_sets_brush_task_cb_ex(void *__restrict userdata,
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);
+ const int active_fset = abs(ss->cache->paint_face_set);
MVert *mvert = SCULPT_mesh_deformed_mverts_get(ss);
@@ -156,7 +158,7 @@ static void do_draw_face_sets_brush_task_cb_ex(void *__restrict userdata,
vd.no,
vd.fno,
vd.mask ? *vd.mask : 0.0f,
- vd.index,
+ vd.vertex,
thread_id);
if (fade > 0.05f && ss->face_sets[vert_map->indices[j]] > 0) {
@@ -165,7 +167,34 @@ static void do_draw_face_sets_brush_task_cb_ex(void *__restrict userdata,
}
}
}
+ else if (BKE_pbvh_type(ss->pbvh) == PBVH_BMESH) {
+ BMVert *v = vd.bm_vert;
+ BMIter iter;
+ BMFace *f;
+ BM_ITER_ELEM (f, &iter, v, BM_FACES_OF_VERT) {
+ float poly_center[3];
+ BM_face_calc_center_median(f, poly_center);
+
+ if (sculpt_brush_test_sq_fn(&test, poly_center)) {
+ const float fade = bstrength * SCULPT_brush_strength_factor(ss,
+ brush,
+ vd.co,
+ sqrtf(test.dist),
+ vd.no,
+ vd.fno,
+ vd.mask ? *vd.mask : 0.0f,
+ vd.vertex,
+ thread_id);
+
+ int fset = BM_ELEM_CD_GET_INT(f, ss->cd_faceset_offset);
+
+ if (fade > 0.05f && fset > 0) {
+ BM_ELEM_CD_SET_INT(f, ss->cd_faceset_offset, active_fset);
+ }
+ }
+ }
+ }
else if (BKE_pbvh_type(ss->pbvh) == PBVH_GRIDS) {
{
if (sculpt_brush_test_sq_fn(&test, vd.co)) {
@@ -176,11 +205,11 @@ static void do_draw_face_sets_brush_task_cb_ex(void *__restrict userdata,
vd.no,
vd.fno,
vd.mask ? *vd.mask : 0.0f,
- vd.index,
+ vd.vertex,
thread_id);
if (fade > 0.05f) {
- SCULPT_vertex_face_set_set(ss, vd.index, ss->cache->paint_face_set);
+ SCULPT_vertex_face_set_set(ss, vd.vertex, ss->cache->paint_face_set);
}
}
}
@@ -215,7 +244,7 @@ static void do_relax_face_sets_brush_task_cb_ex(void *__restrict userdata,
BKE_pbvh_vertex_iter_begin(ss->pbvh, data->nodes[n], vd, PBVH_ITER_UNIQUE)
{
if (sculpt_brush_test_sq_fn(&test, vd.co)) {
- if (relax_face_sets != SCULPT_vertex_has_unique_face_set(ss, vd.index)) {
+ if (relax_face_sets != SCULPT_vertex_has_unique_face_set(ss, vd.vertex)) {
const float fade = bstrength * SCULPT_brush_strength_factor(ss,
brush,
vd.co,
@@ -223,7 +252,7 @@ static void do_relax_face_sets_brush_task_cb_ex(void *__restrict userdata,
vd.no,
vd.fno,
vd.mask ? *vd.mask : 0.0f,
- vd.index,
+ vd.vertex,
thread_id);
SCULPT_relax_vertex(ss, &vd, fade * bstrength, relax_face_sets, vd.co);
@@ -339,8 +368,11 @@ static int sculpt_face_set_create_exec(bContext *C, wmOperator *op)
if (mode == SCULPT_FACE_SET_MASKED) {
for (int i = 0; i < tot_vert; i++) {
- if (SCULPT_vertex_mask_get(ss, i) >= threshold && SCULPT_vertex_visible_get(ss, i)) {
- SCULPT_vertex_face_set_set(ss, i, next_face_set);
+ SculptVertRef vertex = BKE_pbvh_table_index_to_vertex(ss->pbvh, i);
+
+ if (SCULPT_vertex_mask_get(ss, vertex) >= threshold &&
+ SCULPT_vertex_visible_get(ss, vertex)) {
+ SCULPT_vertex_face_set_set(ss, vertex, next_face_set);
}
}
}
@@ -352,7 +384,9 @@ static int sculpt_face_set_create_exec(bContext *C, wmOperator *op)
* sets and the performance hit of rendering the overlay. */
bool all_visible = true;
for (int i = 0; i < tot_vert; i++) {
- if (!SCULPT_vertex_visible_get(ss, i)) {
+ SculptVertRef vertex = BKE_pbvh_table_index_to_vertex(ss->pbvh, i);
+
+ if (!SCULPT_vertex_visible_get(ss, vertex)) {
all_visible = false;
break;
}
@@ -366,15 +400,19 @@ static int sculpt_face_set_create_exec(bContext *C, wmOperator *op)
}
for (int i = 0; i < tot_vert; i++) {
- if (SCULPT_vertex_visible_get(ss, i)) {
- SCULPT_vertex_face_set_set(ss, i, next_face_set);
+ SculptVertRef vertex = BKE_pbvh_table_index_to_vertex(ss->pbvh, i);
+
+ if (SCULPT_vertex_visible_get(ss, vertex)) {
+ SCULPT_vertex_face_set_set(ss, vertex, next_face_set);
}
}
}
if (mode == SCULPT_FACE_SET_ALL) {
for (int i = 0; i < tot_vert; i++) {
- SCULPT_vertex_face_set_set(ss, i, next_face_set);
+ SculptVertRef vertex = BKE_pbvh_table_index_to_vertex(ss->pbvh, i);
+
+ SCULPT_vertex_face_set_set(ss, vertex, next_face_set);
}
}
@@ -387,7 +425,8 @@ static int sculpt_face_set_create_exec(bContext *C, wmOperator *op)
.use_toolflags = true,
}));
- BM_mesh_bm_from_me(bm,
+ BM_mesh_bm_from_me(NULL,
+ bm,
mesh,
(&(struct BMeshFromMeshParams){
.calc_face_normal = true,
@@ -565,7 +604,8 @@ static void sculpt_face_sets_init_flood_fill(Object *ob,
.use_toolflags = true,
}));
- BM_mesh_bm_from_me(bm,
+ BM_mesh_bm_from_me(NULL,
+ bm,
mesh,
(&(struct BMeshFromMeshParams){
.calc_face_normal = true,
@@ -638,7 +678,8 @@ static void sculpt_face_sets_init_loop(Object *ob, const int mode)
.use_toolflags = true,
}));
- BM_mesh_bm_from_me(bm,
+ BM_mesh_bm_from_me(NULL,
+ bm,
mesh,
(&(struct BMeshFromMeshParams){
.calc_face_normal = true,
@@ -855,7 +896,9 @@ static int sculpt_face_sets_change_visibility_exec(bContext *C, wmOperator *op)
* be synced from face sets to non-manifold vertices. */
if (BKE_pbvh_type(ss->pbvh) == PBVH_GRIDS) {
for (int i = 0; i < tot_vert; i++) {
- if (!SCULPT_vertex_visible_get(ss, i)) {
+ SculptVertRef vertex = BKE_pbvh_table_index_to_vertex(ss->pbvh, i);
+
+ if (!SCULPT_vertex_visible_get(ss, vertex)) {
hidden_vertex = true;
break;
}
@@ -1070,12 +1113,60 @@ static EnumPropertyItem prop_sculpt_face_sets_edit_types[] = {
{0, NULL, 0, NULL, NULL},
};
+static void sculpt_face_set_grow_bmesh(Object *ob,
+ SculptSession *ss,
+ const int *prev_face_sets,
+ const int active_face_set_id,
+ const bool modify_hidden)
+{
+ BMesh *bm = ss->bm;
+ BMIter iter;
+ BMFace *f;
+ BMFace **faces = NULL;
+ BLI_array_declare(faces);
+
+ if (ss->cd_faceset_offset < 0) {
+ return;
+ }
+
+ BM_ITER_MESH (f, &iter, bm, BM_FACES_OF_MESH) {
+ if (BM_elem_flag_test(f, BM_ELEM_HIDDEN) && !modify_hidden) {
+ continue;
+ }
+
+ int fset = abs(BM_ELEM_CD_GET_INT(f, ss->cd_faceset_offset));
+
+ if (fset == active_face_set_id) {
+ BLI_array_append(faces, f);
+ }
+ }
+
+ for (int i = 0; i < BLI_array_len(faces); i++) {
+ BMFace *f = faces[i];
+ BMLoop *l = f->l_first;
+
+ do {
+ if (l->radial_next != l) {
+ BM_ELEM_CD_GET_INT(l->radial_next->f, active_face_set_id);
+ }
+ l = l->next;
+ } while (l != f->l_first);
+ }
+
+ BLI_array_free(faces);
+}
+
static void sculpt_face_set_grow(Object *ob,
SculptSession *ss,
const int *prev_face_sets,
const int active_face_set_id,
const bool modify_hidden)
{
+ if (ss && ss->bm) {
+ sculpt_face_set_grow_bmesh(ob, ss, prev_face_sets, active_face_set_id, modify_hidden);
+ return;
+ }
+
Mesh *mesh = BKE_mesh_from_object(ob);
for (int p = 0; p < mesh->totpoly; p++) {
if (!modify_hidden && prev_face_sets[p] <= 0) {
@@ -1104,6 +1195,11 @@ static void sculpt_face_set_shrink(Object *ob,
const int active_face_set_id,
const bool modify_hidden)
{
+ if (ss && ss->bm) {
+ // XXX implement me
+ return;
+ }
+
Mesh *mesh = BKE_mesh_from_object(ob);
for (int p = 0; p < mesh->totpoly; p++) {
if (!modify_hidden && prev_face_sets[p] <= 0) {
@@ -1170,7 +1266,8 @@ static void sculpt_face_set_delete_geometry(Object *ob,
.use_toolflags = true,
}));
- BM_mesh_bm_from_me(bm,
+ BM_mesh_bm_from_me(ob,
+ bm,
mesh,
(&(struct BMeshFromMeshParams){
.calc_face_normal = true,
@@ -1191,6 +1288,7 @@ static void sculpt_face_set_delete_geometry(Object *ob,
BM_mesh_elem_hflag_disable_all(bm, BM_VERT | BM_EDGE | BM_FACE, BM_ELEM_TAG, false);
BM_mesh_bm_to_me(NULL,
+ ob,
bm,
ob->data,
(&(struct BMeshToMeshParams){
@@ -1205,17 +1303,21 @@ static void sculpt_face_set_edit_fair_face_set(Object *ob,
const int fair_order)
{
SculptSession *ss = ob->sculpt;
+
const int totvert = SCULPT_vertex_count_get(ss);
Mesh *mesh = ob->data;
bool *fair_vertices = MEM_malloc_arrayN(sizeof(bool), totvert, "fair vertices");
+ SCULPT_vertex_random_access_ensure(ss);
SCULPT_boundary_info_ensure(ob);
for (int i = 0; i < totvert; i++) {
- fair_vertices[i] = !SCULPT_vertex_is_boundary(ss, i) &&
- SCULPT_vertex_has_face_set(ss, i, active_face_set_id) &&
- SCULPT_vertex_has_unique_face_set(ss, i);
+ SculptVertRef vref = BKE_pbvh_table_index_to_vertex(ss->pbvh, i);
+
+ fair_vertices[i] = !SCULPT_vertex_is_boundary(ss, vref) &&
+ SCULPT_vertex_has_face_set(ss, vref, active_face_set_id) &&
+ SCULPT_vertex_has_unique_face_set(ss, vref);
}
MVert *mvert = SCULPT_mesh_deformed_mverts_get(ss);
@@ -1232,13 +1334,13 @@ static void sculpt_face_set_apply_edit(Object *ob,
switch (mode) {
case SCULPT_FACE_SET_EDIT_GROW: {
- int *prev_face_sets = MEM_dupallocN(ss->face_sets);
+ int *prev_face_sets = ss->face_sets ? MEM_dupallocN(ss->face_sets) : NULL;
sculpt_face_set_grow(ob, ss, prev_face_sets, active_face_set_id, modify_hidden);
MEM_SAFE_FREE(prev_face_sets);
break;
}
case SCULPT_FACE_SET_EDIT_SHRINK: {
- int *prev_face_sets = MEM_dupallocN(ss->face_sets);
+ int *prev_face_sets = ss->face_sets ? MEM_dupallocN(ss->face_sets) : NULL;
sculpt_face_set_shrink(ob, ss, prev_face_sets, active_face_set_id, modify_hidden);
MEM_SAFE_FREE(prev_face_sets);
break;
diff --git a/source/blender/editors/sculpt_paint/sculpt_filter_color.c b/source/blender/editors/sculpt_paint/sculpt_filter_color.c
index 76a6b05cdff..38d2904e98a 100644
--- a/source/blender/editors/sculpt_paint/sculpt_filter_color.c
+++ b/source/blender/editors/sculpt_paint/sculpt_filter_color.c
@@ -107,7 +107,7 @@ static void color_filter_task_cb(void *__restrict userdata,
const int mode = data->filter_type;
SculptOrigVertData orig_data;
- SCULPT_orig_vert_data_init(&orig_data, data->ob, data->nodes[n]);
+ SCULPT_orig_vert_data_init(&orig_data, data->ob, data->nodes[n], SCULPT_UNDO_COLOR);
PBVHVertexIter vd;
BKE_pbvh_vertex_iter_begin(ss->pbvh, data->nodes[n], vd, PBVH_ITER_UNIQUE)
@@ -119,7 +119,7 @@ static void color_filter_task_cb(void *__restrict userdata,
float fade = vd.mask ? *vd.mask : 0.0f;
fade = 1.0f - fade;
fade *= data->filter_strength;
- fade *= SCULPT_automasking_factor_get(ss->filter_cache->automasking, ss, vd.index);
+ fade *= SCULPT_automasking_factor_get(ss->filter_cache->automasking, ss, vd.vertex);
if (fade == 0.0f) {
continue;
}
@@ -197,7 +197,7 @@ static void color_filter_task_cb(void *__restrict userdata,
case COLOR_FILTER_SMOOTH: {
fade = clamp_f(fade, -1.0f, 1.0f);
float smooth_color[4];
- SCULPT_neighbor_color_average(ss, smooth_color, vd.index);
+ SCULPT_neighbor_color_average(ss, smooth_color, vd.vertex);
blend_color_interpolate_float(final_color, vd.col, smooth_color, fade);
break;
}
diff --git a/source/blender/editors/sculpt_paint/sculpt_filter_mask.c b/source/blender/editors/sculpt_paint/sculpt_filter_mask.c
index 0297ed73dd4..5ce5a862cbe 100644
--- a/source/blender/editors/sculpt_paint/sculpt_filter_mask.c
+++ b/source/blender/editors/sculpt_paint/sculpt_filter_mask.c
@@ -120,7 +120,7 @@ static void mask_filter_task_cb(void *__restrict userdata,
switch (mode) {
case MASK_FILTER_SMOOTH:
case MASK_FILTER_SHARPEN: {
- float val = SCULPT_neighbor_mask_average(ss, vd.index);
+ float val = SCULPT_neighbor_mask_average(ss, vd.vertex);
val -= *vd.mask;
@@ -140,7 +140,7 @@ static void mask_filter_task_cb(void *__restrict userdata,
}
case MASK_FILTER_GROW:
max = 0.0f;
- SCULPT_VERTEX_NEIGHBORS_ITER_BEGIN (ss, vd.index, ni) {
+ SCULPT_VERTEX_NEIGHBORS_ITER_BEGIN (ss, vd.vertex, ni) {
float vmask_f = data->prev_mask[ni.index];
if (vmask_f > max) {
max = vmask_f;
@@ -151,7 +151,7 @@ static void mask_filter_task_cb(void *__restrict userdata,
break;
case MASK_FILTER_SHRINK:
min = 1.0f;
- SCULPT_VERTEX_NEIGHBORS_ITER_BEGIN (ss, vd.index, ni) {
+ SCULPT_VERTEX_NEIGHBORS_ITER_BEGIN (ss, vd.vertex, ni) {
float vmask_f = data->prev_mask[ni.index];
if (vmask_f < min) {
min = vmask_f;
@@ -233,7 +233,9 @@ static int sculpt_mask_filter_exec(bContext *C, wmOperator *op)
if (ELEM(filter_type, MASK_FILTER_GROW, MASK_FILTER_SHRINK)) {
prev_mask = MEM_mallocN(num_verts * sizeof(float), "prevmask");
for (int j = 0; j < num_verts; j++) {
- prev_mask[j] = SCULPT_vertex_mask_get(ss, j);
+ SculptVertRef vertex = BKE_pbvh_table_index_to_vertex(ss->pbvh, j);
+
+ prev_mask[j] = SCULPT_vertex_mask_get(ss, vertex);
}
}
@@ -324,9 +326,9 @@ static float neighbor_dirty_mask(SculptSession *ss, PBVHVertexIter *vd)
zero_v3(avg);
SculptVertexNeighborIter ni;
- SCULPT_VERTEX_NEIGHBORS_ITER_BEGIN (ss, vd->index, ni) {
+ SCULPT_VERTEX_NEIGHBORS_ITER_BEGIN (ss, vd->vertex, ni) {
float normalized[3];
- sub_v3_v3v3(normalized, SCULPT_vertex_co_get(ss, ni.index), vd->co);
+ sub_v3_v3v3(normalized, SCULPT_vertex_co_get(ss, ni.vertex), vd->co);
normalize_v3(normalized);
add_v3_v3(avg, normalized);
total++;
diff --git a/source/blender/editors/sculpt_paint/sculpt_filter_mesh.c b/source/blender/editors/sculpt_paint/sculpt_filter_mesh.c
index e11894a8c01..b8b6ebae25f 100644
--- a/source/blender/editors/sculpt_paint/sculpt_filter_mesh.c
+++ b/source/blender/editors/sculpt_paint/sculpt_filter_mesh.c
@@ -293,7 +293,7 @@ static void mesh_filter_task_cb(void *__restrict userdata,
const eSculptMeshFilterType filter_type = data->filter_type;
SculptOrigVertData orig_data;
- SCULPT_orig_vert_data_init(&orig_data, data->ob, data->nodes[i]);
+ SCULPT_orig_vert_data_init(&orig_data, data->ob, data->nodes[i], SCULPT_UNDO_COORDS);
/* When using the relax face sets meshes filter,
* each 3 iterations, do a whole mesh relax to smooth the contents of the Face Set. */
@@ -309,7 +309,7 @@ static void mesh_filter_task_cb(void *__restrict userdata,
float fade = vd.mask ? *vd.mask : 0.0f;
fade = 1.0f - fade;
fade *= data->filter_strength;
- fade *= SCULPT_automasking_factor_get(ss->filter_cache->automasking, ss, vd.index);
+ fade *= SCULPT_automasking_factor_get(ss->filter_cache->automasking, ss, vd.vertex);
if (fade == 0.0f && filter_type != MESH_FILTER_SURFACE_SMOOTH) {
/* Surface Smooth can't skip the loop for this vertex as it needs to calculate its
@@ -327,7 +327,7 @@ static void mesh_filter_task_cb(void *__restrict userdata,
}
if (filter_type == MESH_FILTER_RELAX_FACE_SETS) {
- if (relax_face_sets == SCULPT_vertex_has_unique_face_set(ss, vd.index)) {
+ if (relax_face_sets == SCULPT_vertex_has_unique_face_set(ss, vd.vertex)) {
continue;
}
}
@@ -335,7 +335,7 @@ static void mesh_filter_task_cb(void *__restrict userdata,
switch (filter_type) {
case MESH_FILTER_SMOOTH:
fade = clamp_f(fade, -1.0f, 1.0f);
- SCULPT_neighbor_coords_average_interior(ss, avg, vd.index);
+ SCULPT_neighbor_coords_average_interior(ss, avg, vd.vertex);
sub_v3_v3v3(val, avg, orig_co);
madd_v3_v3v3fl(val, orig_co, val, fade);
sub_v3_v3v3(disp, val, orig_co);
@@ -398,7 +398,7 @@ static void mesh_filter_task_cb(void *__restrict userdata,
disp,
vd.co,
ss->filter_cache->surface_smooth_laplacian_disp,
- vd.index,
+ vd.vertex,
orig_data.co,
ss->filter_cache->surface_smooth_shape_preservation);
break;
@@ -412,10 +412,10 @@ static void mesh_filter_task_cb(void *__restrict userdata,
float disp_sharpen[3] = {0.0f, 0.0f, 0.0f};
SculptVertexNeighborIter ni;
- SCULPT_VERTEX_NEIGHBORS_ITER_BEGIN (ss, vd.index, ni) {
+ SCULPT_VERTEX_NEIGHBORS_ITER_BEGIN (ss, vd.vertex, ni) {
float disp_n[3];
sub_v3_v3v3(
- disp_n, SCULPT_vertex_co_get(ss, ni.index), SCULPT_vertex_co_get(ss, vd.index));
+ disp_n, SCULPT_vertex_co_get(ss, ni.vertex), SCULPT_vertex_co_get(ss, vd.vertex));
mul_v3_fl(disp_n, ss->filter_cache->sharpen_factor[ni.index]);
add_v3_v3(disp_sharpen, disp_n);
}
@@ -425,7 +425,7 @@ static void mesh_filter_task_cb(void *__restrict userdata,
float disp_avg[3];
float avg_co[3];
- SCULPT_neighbor_coords_average(ss, avg_co, vd.index);
+ SCULPT_neighbor_coords_average(ss, avg_co, vd.vertex);
sub_v3_v3v3(disp_avg, avg_co, vd.co);
mul_v3_v3fl(
disp_avg, disp_avg, smooth_ratio * pow2f(ss->filter_cache->sharpen_factor[vd.index]));
@@ -487,9 +487,11 @@ static void mesh_filter_enhance_details_init_directions(SculptSession *ss)
filter_cache->detail_directions = MEM_malloc_arrayN(
totvert, sizeof(float[3]), "detail directions");
for (int i = 0; i < totvert; i++) {
+ SculptVertRef vertex = BKE_pbvh_table_index_to_vertex(ss->pbvh, i);
+
float avg[3];
- SCULPT_neighbor_coords_average(ss, avg, i);
- sub_v3_v3v3(filter_cache->detail_directions[i], avg, SCULPT_vertex_co_get(ss, i));
+ SCULPT_neighbor_coords_average(ss, avg, vertex);
+ sub_v3_v3v3(filter_cache->detail_directions[i], avg, SCULPT_vertex_co_get(ss, vertex));
}
}
@@ -513,8 +515,10 @@ static void mesh_filter_init_limit_surface_co(SculptSession *ss)
filter_cache->limit_surface_co = MEM_malloc_arrayN(
sizeof(float[3]), totvert, "limit surface co");
+
for (int i = 0; i < totvert; i++) {
- SCULPT_vertex_limit_surface_get(ss, i, filter_cache->limit_surface_co[i]);
+ SculptVertRef vertex = BKE_pbvh_table_index_to_vertex(ss->pbvh, i);
+ SCULPT_vertex_limit_surface_get(ss, vertex, filter_cache->limit_surface_co[i]);
}
}
@@ -535,8 +539,10 @@ static void mesh_filter_sharpen_init(SculptSession *ss,
for (int i = 0; i < totvert; i++) {
float avg[3];
- SCULPT_neighbor_coords_average(ss, avg, i);
- sub_v3_v3v3(filter_cache->detail_directions[i], avg, SCULPT_vertex_co_get(ss, i));
+ SculptVertRef vertex = BKE_pbvh_table_index_to_vertex(ss->pbvh, i);
+
+ SCULPT_neighbor_coords_average(ss, avg, vertex);
+ sub_v3_v3v3(filter_cache->detail_directions[i], avg, SCULPT_vertex_co_get(ss, vertex));
filter_cache->sharpen_factor[i] = len_v3(filter_cache->detail_directions[i]);
}
@@ -559,11 +565,12 @@ static void mesh_filter_sharpen_init(SculptSession *ss,
smooth_iterations++) {
for (int i = 0; i < totvert; i++) {
float direction_avg[3] = {0.0f, 0.0f, 0.0f};
+ SculptVertRef vertex = BKE_pbvh_table_index_to_vertex(ss->pbvh, i);
float sharpen_avg = 0;
int total = 0;
SculptVertexNeighborIter ni;
- SCULPT_VERTEX_NEIGHBORS_ITER_BEGIN (ss, i, ni) {
+ SCULPT_VERTEX_NEIGHBORS_ITER_BEGIN (ss, vertex, ni) {
add_v3_v3(direction_avg, filter_cache->detail_directions[ni.index]);
sharpen_avg += filter_cache->sharpen_factor[ni.index];
total++;
@@ -591,7 +598,7 @@ static void mesh_filter_surface_smooth_displace_task_cb(
float fade = vd.mask ? *vd.mask : 0.0f;
fade = 1.0f - fade;
fade *= data->filter_strength;
- fade *= SCULPT_automasking_factor_get(ss->filter_cache->automasking, ss, vd.index);
+ fade *= SCULPT_automasking_factor_get(ss->filter_cache->automasking, ss, vd.vertex);
if (fade == 0.0f) {
continue;
}
@@ -599,7 +606,7 @@ static void mesh_filter_surface_smooth_displace_task_cb(
SCULPT_surface_smooth_displace_step(ss,
vd.co,
ss->filter_cache->surface_smooth_laplacian_disp,
- vd.index,
+ vd.vertex,
ss->filter_cache->surface_smooth_current_vertex,
clamp_f(fade, 0.0f, 1.0f));
}
diff --git a/source/blender/editors/sculpt_paint/sculpt_intern.h b/source/blender/editors/sculpt_paint/sculpt_intern.h
index d1e17c7e59b..7aef6f71154 100644
--- a/source/blender/editors/sculpt_paint/sculpt_intern.h
+++ b/source/blender/editors/sculpt_paint/sculpt_intern.h
@@ -51,6 +51,7 @@ bool SCULPT_poll(struct bContext *C);
bool SCULPT_poll_view3d(struct bContext *C);
bool SCULPT_vertex_colors_poll(struct bContext *C);
+bool SCULPT_vertex_colors_poll_no_bmesh(struct bContext *C);
/* Updates */
@@ -98,20 +99,20 @@ char SCULPT_mesh_symmetry_xyz_get(Object *object);
void SCULPT_vertex_random_access_ensure(struct SculptSession *ss);
int SCULPT_vertex_count_get(struct SculptSession *ss);
-const float *SCULPT_vertex_co_get(struct SculptSession *ss, int index);
-void SCULPT_vertex_normal_get(SculptSession *ss, int index, float no[3]);
-float SCULPT_vertex_mask_get(struct SculptSession *ss, int index);
-const float *SCULPT_vertex_color_get(SculptSession *ss, int index);
+const float *SCULPT_vertex_co_get(struct SculptSession *ss, SculptVertRef index);
+void SCULPT_vertex_normal_get(SculptSession *ss, SculptVertRef index, float no[3]);
+float SCULPT_vertex_mask_get(struct SculptSession *ss, SculptVertRef index);
+const float *SCULPT_vertex_color_get(SculptSession *ss, SculptVertRef index);
-const float *SCULPT_vertex_persistent_co_get(SculptSession *ss, int index);
-void SCULPT_vertex_persistent_normal_get(SculptSession *ss, int index, float no[3]);
+const float *SCULPT_vertex_persistent_co_get(SculptSession *ss, SculptVertRef index);
+void SCULPT_vertex_persistent_normal_get(SculptSession *ss, SculptVertRef index, float no[3]);
/* Coordinates used for manipulating the base mesh when Grab Active Vertex is enabled. */
-const float *SCULPT_vertex_co_for_grab_active_get(SculptSession *ss, int index);
+const float *SCULPT_vertex_co_for_grab_active_get(SculptSession *ss, SculptVertRef index);
/* Returns the info of the limit surface when Multires is available, otherwise it returns the
* current coordinate of the vertex. */
-void SCULPT_vertex_limit_surface_get(SculptSession *ss, int index, float r_co[3]);
+void SCULPT_vertex_limit_surface_get(SculptSession *ss, SculptVertRef index, float r_co[3]);
/* Returns the pointer to the coordinates that should be edited from a brush tool iterator
* depending on the given deformation target. */
@@ -122,22 +123,26 @@ float *SCULPT_brush_deform_target_vertex_co_get(SculptSession *ss,
#define SCULPT_VERTEX_NEIGHBOR_FIXED_CAPACITY 256
typedef struct SculptVertexNeighborIter {
/* Storage */
- int *neighbors;
+ SculptVertRef *neighbors;
+ int *neighbor_indices;
+
int size;
int capacity;
- int neighbors_fixed[SCULPT_VERTEX_NEIGHBOR_FIXED_CAPACITY];
+ SculptVertRef neighbors_fixed[SCULPT_VERTEX_NEIGHBOR_FIXED_CAPACITY];
+ int neighbor_indices_fixed[SCULPT_VERTEX_NEIGHBOR_FIXED_CAPACITY];
/* Internal iterator. */
int num_duplicates;
int i;
/* Public */
+ SculptVertRef vertex;
int index;
bool is_duplicate;
} SculptVertexNeighborIter;
void SCULPT_vertex_neighbors_get(struct SculptSession *ss,
- const int index,
+ const SculptVertRef vref,
const bool include_duplicates,
SculptVertexNeighborIter *iter);
@@ -146,7 +151,8 @@ void SCULPT_vertex_neighbors_get(struct SculptSession *ss,
SCULPT_vertex_neighbors_get(ss, v_index, false, &neighbor_iterator); \
for (neighbor_iterator.i = 0; neighbor_iterator.i < neighbor_iterator.size; \
neighbor_iterator.i++) { \
- neighbor_iterator.index = neighbor_iterator.neighbors[neighbor_iterator.i];
+ neighbor_iterator.vertex = neighbor_iterator.neighbors[neighbor_iterator.i]; \
+ neighbor_iterator.index = neighbor_iterator.neighbor_indices[neighbor_iterator.i];
/* Iterate over neighboring and duplicate vertices (for PBVH_GRIDS). Duplicates come
* first since they are nearest for floodfill. */
@@ -154,7 +160,8 @@ void SCULPT_vertex_neighbors_get(struct SculptSession *ss,
SCULPT_vertex_neighbors_get(ss, v_index, true, &neighbor_iterator); \
for (neighbor_iterator.i = neighbor_iterator.size - 1; neighbor_iterator.i >= 0; \
neighbor_iterator.i--) { \
- neighbor_iterator.index = neighbor_iterator.neighbors[neighbor_iterator.i]; \
+ neighbor_iterator.vertex = neighbor_iterator.neighbors[neighbor_iterator.i]; \
+ neighbor_iterator.index = neighbor_iterator.neighbor_indices[neighbor_iterator.i]; \
neighbor_iterator.is_duplicate = (neighbor_iterator.i >= \
neighbor_iterator.size - neighbor_iterator.num_duplicates);
@@ -165,7 +172,7 @@ void SCULPT_vertex_neighbors_get(struct SculptSession *ss,
} \
((void)0)
-int SCULPT_active_vertex_get(SculptSession *ss);
+SculptVertRef SCULPT_active_vertex_get(SculptSession *ss);
const float *SCULPT_active_vertex_co_get(SculptSession *ss);
void SCULPT_active_vertex_normal_get(SculptSession *ss, float normal[3]);
@@ -185,12 +192,12 @@ void SCULPT_fake_neighbors_free(struct Object *ob);
/* Vertex Info. */
void SCULPT_boundary_info_ensure(Object *object);
/* Boundary Info needs to be initialized in order to use this function. */
-bool SCULPT_vertex_is_boundary(const SculptSession *ss, const int index);
+bool SCULPT_vertex_is_boundary(const SculptSession *ss, const SculptVertRef index);
/* Sculpt Visibility API */
-void SCULPT_vertex_visible_set(SculptSession *ss, int index, bool visible);
-bool SCULPT_vertex_visible_get(SculptSession *ss, int index);
+void SCULPT_vertex_visible_set(SculptSession *ss, SculptVertRef index, bool visible);
+bool SCULPT_vertex_visible_get(SculptSession *ss, SculptVertRef index);
void SCULPT_visibility_sync_all_face_sets_to_vertices(struct Object *ob);
void SCULPT_visibility_sync_all_vertex_to_face_sets(struct SculptSession *ss);
@@ -198,17 +205,17 @@ void SCULPT_visibility_sync_all_vertex_to_face_sets(struct SculptSession *ss);
/* Face Sets API */
int SCULPT_active_face_set_get(SculptSession *ss);
-int SCULPT_vertex_face_set_get(SculptSession *ss, int index);
-void SCULPT_vertex_face_set_set(SculptSession *ss, int index, int face_set);
+int SCULPT_vertex_face_set_get(SculptSession *ss, SculptVertRef index);
+void SCULPT_vertex_face_set_set(SculptSession *ss, SculptVertRef index, int face_set);
-bool SCULPT_vertex_has_face_set(SculptSession *ss, int index, int face_set);
-bool SCULPT_vertex_has_unique_face_set(SculptSession *ss, int index);
+bool SCULPT_vertex_has_face_set(SculptSession *ss, SculptVertRef index, int face_set);
+bool SCULPT_vertex_has_unique_face_set(SculptSession *ss, SculptVertRef index);
int SCULPT_face_set_next_available_get(SculptSession *ss);
void SCULPT_face_set_visibility_set(SculptSession *ss, int face_set, bool visible);
-bool SCULPT_vertex_all_face_sets_visible_get(const SculptSession *ss, int index);
-bool SCULPT_vertex_any_face_set_visible_get(SculptSession *ss, int index);
+bool SCULPT_vertex_all_face_sets_visible_get(const SculptSession *ss, SculptVertRef index);
+bool SCULPT_vertex_any_face_set_visible_get(SculptSession *ss, SculptVertRef index);
void SCULPT_face_sets_visibility_invert(SculptSession *ss);
void SCULPT_face_sets_visibility_all_set(SculptSession *ss, bool visible);
@@ -222,24 +229,22 @@ typedef struct {
struct BMLog *bm_log;
struct SculptUndoNode *unode;
+ int datatype;
float (*coords)[3];
short (*normals)[3];
const float *vmasks;
float (*colors)[4];
+ short _no[3];
/* Original coordinate, normal, and mask. */
const float *co;
const short *no;
float mask;
const float *col;
+ struct PBVH *pbvh;
+ struct SculptSession *ss;
} SculptOrigVertData;
-void SCULPT_orig_vert_data_init(SculptOrigVertData *data, Object *ob, PBVHNode *node);
-void SCULPT_orig_vert_data_update(SculptOrigVertData *orig_data, PBVHVertexIter *iter);
-void SCULPT_orig_vert_data_unode_init(SculptOrigVertData *data,
- Object *ob,
- struct SculptUndoNode *unode);
-
/* Utils. */
void SCULPT_calc_brush_plane(struct Sculpt *sd,
struct Object *ob,
@@ -251,11 +256,11 @@ void SCULPT_calc_brush_plane(struct Sculpt *sd,
void SCULPT_calc_area_normal(
Sculpt *sd, Object *ob, PBVHNode **nodes, int totnode, float r_area_no[3]);
-int SCULPT_nearest_vertex_get(struct Sculpt *sd,
- struct Object *ob,
- const float co[3],
- float max_distance,
- bool use_original);
+SculptVertRef SCULPT_nearest_vertex_get(struct Sculpt *sd,
+ struct Object *ob,
+ const float co[3],
+ float max_distance,
+ bool use_original);
int SCULPT_plane_point_side(const float co[3], const float plane[4]);
int SCULPT_plane_trim(const struct StrokeCache *cache,
@@ -297,14 +302,17 @@ void SCULPT_floodfill_add_initial_with_symmetry(struct Sculpt *sd,
struct Object *ob,
struct SculptSession *ss,
SculptFloodFill *flood,
- int index,
+ SculptVertRef index,
float radius);
-void SCULPT_floodfill_add_initial(SculptFloodFill *flood, int index);
-void SCULPT_floodfill_execute(
- struct SculptSession *ss,
- SculptFloodFill *flood,
- bool (*func)(SculptSession *ss, int from_v, int to_v, bool is_duplicate, void *userdata),
- void *userdata);
+void SCULPT_floodfill_add_initial(SculptFloodFill *flood, SculptVertRef index);
+void SCULPT_floodfill_execute(struct SculptSession *ss,
+ SculptFloodFill *flood,
+ bool (*func)(SculptSession *ss,
+ SculptVertRef from_v,
+ SculptVertRef to_v,
+ bool is_duplicate,
+ void *userdata),
+ void *userdata);
void SCULPT_floodfill_free(SculptFloodFill *flood);
/* Dynamic topology */
@@ -316,6 +324,11 @@ enum eDynTopoWarnFlag {
DYNTOPO_WARN_MODIFIER = (1 << 3),
};
+struct Mesh;
+
+void SCULPT_dyntopo_node_layers_update_offsets(SculptSession *ss);
+void SCULPT_dynamic_topology_sync_layers(Object *ob, struct Mesh *me);
+
void SCULPT_dynamic_topology_enable_ex(struct Main *bmain,
struct Depsgraph *depsgraph,
Scene *scene,
@@ -338,7 +351,7 @@ void SCULPT_pbvh_clear(Object *ob);
/* Auto-masking. */
float SCULPT_automasking_factor_get(struct AutomaskingCache *automasking,
SculptSession *ss,
- int vert);
+ SculptVertRef vert);
/* Returns the automasking cache depending on the active tool. Used for code that can run both for
* brushes and filter. */
@@ -497,7 +510,7 @@ void SCULPT_pose_ik_chain_free(struct SculptPoseIKChain *ik_chain);
/* Boundary Brush. */
struct SculptBoundary *SCULPT_boundary_data_init(Object *object,
Brush *brush,
- const int initial_vertex,
+ const SculptVertRef initial_vertex,
const float radius);
void SCULPT_boundary_data_free(struct SculptBoundary *boundary);
void SCULPT_do_boundary_brush(struct Sculpt *sd,
@@ -530,12 +543,17 @@ void SCULPT_do_smear_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnode
/* Smooth Brush. */
void SCULPT_bmesh_four_neighbor_average(float avg[3], float direction[3], struct BMVert *v);
-void SCULPT_neighbor_coords_average(SculptSession *ss, float result[3], int index);
-float SCULPT_neighbor_mask_average(SculptSession *ss, int index);
-void SCULPT_neighbor_color_average(SculptSession *ss, float result[4], int index);
+void SCULPT_neighbor_coords_average(SculptSession *ss, float result[3], SculptVertRef index);
+float SCULPT_neighbor_mask_average(SculptSession *ss, SculptVertRef index);
+void SCULPT_neighbor_color_average(SculptSession *ss, float result[4], SculptVertRef index);
/* Mask the mesh boundaries smoothing only the mesh surface without using automasking. */
-void SCULPT_neighbor_coords_average_interior(SculptSession *ss, float result[3], int index);
+void SCULPT_neighbor_coords_average_interior(SculptSession *ss,
+ float result[3],
+ SculptVertRef index);
+
+void SCULPT_smooth_vcol_boundary(
+ Sculpt *sd, Object *ob, PBVHNode **nodes, const int totnode, float bstrength);
void SCULPT_smooth(Sculpt *sd,
Object *ob,
@@ -551,13 +569,13 @@ void SCULPT_surface_smooth_laplacian_step(SculptSession *ss,
float *disp,
const float co[3],
float (*laplacian_disp)[3],
- const int v_index,
+ const SculptVertRef v_index,
const float origco[3],
const float alpha);
void SCULPT_surface_smooth_displace_step(SculptSession *ss,
float *co,
float (*laplacian_disp)[3],
- const int v_index,
+ const SculptVertRef v_index,
const float beta,
const float fade);
void SCULPT_do_surface_smooth_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnode);
@@ -616,8 +634,8 @@ typedef struct SculptUndoNode {
int totvert;
/* non-multires */
- int maxvert; /* to verify if totvert it still the same */
- int *index; /* to restore into right location */
+ int maxvert; /* to verify if totvert it still the same */
+ SculptVertRef *index; /* to restore into right location */
BLI_bitmap *vert_hidden;
/* multires */
@@ -654,6 +672,9 @@ typedef struct SculptUndoNode {
/* Sculpt Face Sets */
int *face_sets;
+ bool *nodemap;
+ int nodemap_size;
+
size_t undo_size;
} SculptUndoNode;
@@ -768,7 +789,7 @@ typedef struct SculptThreadedTaskData {
bool mask_by_color_preserve_mask;
/* Index of the vertex that is going to be used as a reference for the colors. */
- int mask_by_color_vertex;
+ SculptVertRef mask_by_color_vertex;
float *mask_by_color_floodfill;
int face_set;
@@ -845,7 +866,7 @@ float SCULPT_brush_strength_factor(struct SculptSession *ss,
const short vno[3],
const float fno[3],
const float mask,
- const int vertex_index,
+ const SculptVertRef vertex_index,
const int thread_id);
/* Tilts a normal by the x and y tilt values using the view axis. */
@@ -1132,8 +1153,17 @@ void SCULPT_cache_calc_brushdata_symm(StrokeCache *cache,
const float angle);
void SCULPT_cache_free(StrokeCache *cache);
+void SCULPT_orig_vert_data_init(SculptOrigVertData *data,
+ Object *ob,
+ PBVHNode *node,
+ SculptUndoType type);
+void SCULPT_orig_vert_data_update(SculptOrigVertData *orig_data, PBVHVertexIter *iter);
+void SCULPT_orig_vert_data_unode_init(SculptOrigVertData *data,
+ Object *ob,
+ struct SculptUndoNode *unode);
+
SculptUndoNode *SCULPT_undo_push_node(Object *ob, PBVHNode *node, SculptUndoType type);
-SculptUndoNode *SCULPT_undo_get_node(PBVHNode *node);
+SculptUndoNode *SCULPT_undo_get_node(PBVHNode *node, SculptUndoType type);
SculptUndoNode *SCULPT_undo_get_first_node(void);
void SCULPT_undo_push_begin(struct Object *ob, const char *name);
void SCULPT_undo_push_end(void);
@@ -1192,3 +1222,9 @@ void SCULPT_OT_set_detail_size(struct wmOperatorType *ot);
/* Dyntopo. */
void SCULPT_OT_dynamic_topology_toggle(struct wmOperatorType *ot);
+bool SCULPT_ensure_dyntopo_node_undo(struct Object *ob,
+ struct PBVHNode *node,
+ SculptUndoType type,
+ int extraType);
+
+void SCULPT_update_flat_vcol_shading(struct Object *ob, struct Scene *scene);
diff --git a/source/blender/editors/sculpt_paint/sculpt_mask_expand.c b/source/blender/editors/sculpt_paint/sculpt_mask_expand.c
index 39432dbbca4..ec215ddde41 100644
--- a/source/blender/editors/sculpt_paint/sculpt_mask_expand.c
+++ b/source/blender/editors/sculpt_paint/sculpt_mask_expand.c
@@ -119,7 +119,7 @@ static void sculpt_expand_task_cb(void *__restrict userdata,
int vi = vd.index;
float final_mask = *vd.mask;
if (data->mask_expand_use_normals) {
- if (ss->filter_cache->normal_factor[SCULPT_active_vertex_get(ss)] <
+ if (ss->filter_cache->normal_factor[BKE_pbvh_vertex_index_to_table(ss->pbvh, SCULPT_active_vertex_get(ss))] <
ss->filter_cache->normal_factor[vd.index]) {
final_mask = 1.0f;
}
@@ -139,7 +139,7 @@ static void sculpt_expand_task_cb(void *__restrict userdata,
if (data->mask_expand_create_face_set) {
if (final_mask == 1.0f) {
- SCULPT_vertex_face_set_set(ss, vd.index, ss->filter_cache->new_face_set);
+ SCULPT_vertex_face_set_set(ss, vd.vertex, ss->filter_cache->new_face_set);
}
BKE_pbvh_node_mark_redraw(node);
}
@@ -190,7 +190,8 @@ static int sculpt_mask_expand_modal(bContext *C, wmOperator *op, const wmEvent *
mouse[1] = event->mval[1];
if (SCULPT_cursor_geometry_info_update(C, &sgi, mouse, false)) {
/* The cursor is over the mesh, get the update iteration from the updated active vertex. */
- mask_expand_update_it = ss->filter_cache->mask_update_it[(int)SCULPT_active_vertex_get(ss)];
+ int vi = BKE_pbvh_vertex_index_to_table(ss->pbvh, SCULPT_active_vertex_get(ss));
+ mask_expand_update_it = ss->filter_cache->mask_update_it[vi];
}
else {
/* When the cursor is outside the mesh, affect the entire connected component. */
@@ -312,10 +313,13 @@ typedef struct MaskExpandFloodFillData {
} MaskExpandFloodFillData;
static bool mask_expand_floodfill_cb(
- SculptSession *ss, int from_v, int to_v, bool is_duplicate, void *userdata)
+ SculptSession *ss, SculptVertRef from_vref, SculptVertRef to_vref, bool is_duplicate, void *userdata)
{
MaskExpandFloodFillData *data = userdata;
+ int to_v = BKE_pbvh_vertex_index_to_table(ss->pbvh, to_vref);
+ int from_v = BKE_pbvh_vertex_index_to_table(ss->pbvh, from_vref);
+
if (!is_duplicate) {
int to_it = ss->filter_cache->mask_update_it[from_v] + 1;
ss->filter_cache->mask_update_it[to_v] = to_it;
@@ -325,8 +329,8 @@ static bool mask_expand_floodfill_cb(
if (data->use_normals) {
float current_normal[3], prev_normal[3];
- SCULPT_vertex_normal_get(ss, to_v, current_normal);
- SCULPT_vertex_normal_get(ss, from_v, prev_normal);
+ SCULPT_vertex_normal_get(ss, to_vref, current_normal);
+ SCULPT_vertex_normal_get(ss, from_vref, prev_normal);
const float from_edge_factor = ss->filter_cache->edge_factor[from_v];
ss->filter_cache->edge_factor[to_v] = dot_v3v3(current_normal, prev_normal) *
from_edge_factor;
@@ -415,13 +419,15 @@ static int sculpt_mask_expand_invoke(bContext *C, wmOperator *op, const wmEvent
else {
ss->filter_cache->prev_mask = MEM_callocN(sizeof(float) * vertex_count, "prev mask");
for (int i = 0; i < vertex_count; i++) {
- ss->filter_cache->prev_mask[i] = SCULPT_vertex_mask_get(ss, i);
+ SculptVertRef vertex = BKE_pbvh_table_index_to_vertex(ss->pbvh, i);
+
+ ss->filter_cache->prev_mask[i] = SCULPT_vertex_mask_get(ss, vertex);
}
}
ss->filter_cache->mask_update_last_it = 1;
ss->filter_cache->mask_update_current_it = 1;
- ss->filter_cache->mask_update_it[SCULPT_active_vertex_get(ss)] = 0;
+ ss->filter_cache->mask_update_it[BKE_pbvh_vertex_index_to_table(ss->pbvh, SCULPT_active_vertex_get(ss))] = 0;
copy_v3_v3(ss->filter_cache->mask_expand_initial_co, SCULPT_active_vertex_co_get(ss));
@@ -440,9 +446,11 @@ static int sculpt_mask_expand_invoke(bContext *C, wmOperator *op, const wmEvent
if (use_normals) {
for (int repeat = 0; repeat < 2; repeat++) {
for (int i = 0; i < vertex_count; i++) {
+ SculptVertRef vertex = BKE_pbvh_table_index_to_vertex(ss->pbvh, i);
+
float avg = 0.0f;
SculptVertexNeighborIter ni;
- SCULPT_VERTEX_NEIGHBORS_ITER_BEGIN (ss, i, ni) {
+ SCULPT_VERTEX_NEIGHBORS_ITER_BEGIN (ss, vertex, ni) {
avg += ss->filter_cache->normal_factor[ni.index];
}
SCULPT_VERTEX_NEIGHBORS_ITER_END(ni);
diff --git a/source/blender/editors/sculpt_paint/sculpt_multiplane_scrape.c b/source/blender/editors/sculpt_paint/sculpt_multiplane_scrape.c
index e47a94dff90..b217223c57c 100644
--- a/source/blender/editors/sculpt_paint/sculpt_multiplane_scrape.c
+++ b/source/blender/editors/sculpt_paint/sculpt_multiplane_scrape.c
@@ -106,7 +106,7 @@ static void calc_multiplane_scrape_surface_task_cb(void *__restrict userdata,
vd.no,
vd.fno,
vd.mask ? *vd.mask : 0.0f,
- vd.index,
+ vd.vertex,
thread_id);
/* Sample the normal and area of the +X and -X axis individually. */
@@ -208,7 +208,7 @@ static void do_multiplane_scrape_brush_task_cb_ex(void *__restrict userdata,
vd.no,
vd.fno,
vd.mask ? *vd.mask : 0.0f,
- vd.index,
+ vd.vertex,
thread_id);
mul_v3_v3fl(proxy[vd.i], val, fade);
diff --git a/source/blender/editors/sculpt_paint/sculpt_paint_color.c b/source/blender/editors/sculpt_paint/sculpt_paint_color.c
index 39320f3f558..bb8acd92b11 100644
--- a/source/blender/editors/sculpt_paint/sculpt_paint_color.c
+++ b/source/blender/editors/sculpt_paint/sculpt_paint_color.c
@@ -95,11 +95,11 @@ static void do_color_smooth_task_cb_exec(void *__restrict userdata,
vd.no,
vd.fno,
vd.mask ? *vd.mask : 0.0f,
- vd.index,
+ vd.vertex,
thread_id);
float smooth_color[4];
- SCULPT_neighbor_color_average(ss, smooth_color, vd.index);
+ SCULPT_neighbor_color_average(ss, smooth_color, vd.vertex);
blend_color_interpolate_float(vd.col, vd.col, smooth_color, fade);
if (vd.mvert) {
@@ -123,7 +123,8 @@ static void do_paint_brush_task_cb_ex(void *__restrict userdata,
PBVHColorBufferNode *color_buffer;
SculptOrigVertData orig_data;
- SCULPT_orig_vert_data_init(&orig_data, data->ob, data->nodes[n]);
+ SCULPT_orig_vert_data_init(&orig_data, data->ob, data->nodes[n], SCULPT_UNDO_COLOR);
+ orig_data.datatype = SCULPT_UNDO_COLOR;
color_buffer = BKE_pbvh_node_color_buffer_get(data->nodes[n]);
@@ -161,7 +162,7 @@ static void do_paint_brush_task_cb_ex(void *__restrict userdata,
vd.no,
vd.fno,
vd.mask ? *vd.mask : 0.0f,
- vd.index,
+ vd.vertex,
thread_id);
/* Density. */
@@ -360,6 +361,10 @@ void SCULPT_do_paint_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnode
TaskParallelSettings settings;
BKE_pbvh_parallel_range_settings(&settings, true, totnode);
BLI_task_parallel_range(0, totnode, &data, do_paint_brush_task_cb_ex, &settings);
+
+ if (brush->vcol_boundary_factor > 0.0f) {
+ SCULPT_smooth_vcol_boundary(sd, ob, nodes, totnode, brush->vcol_boundary_factor);
+ }
}
static void do_smear_brush_task_cb_exec(void *__restrict userdata,
@@ -388,7 +393,7 @@ static void do_smear_brush_task_cb_exec(void *__restrict userdata,
vd.no,
vd.fno,
vd.mask ? *vd.mask : 0.0f,
- vd.index,
+ vd.vertex,
thread_id);
float current_disp[3];
@@ -411,10 +416,10 @@ static void do_smear_brush_task_cb_exec(void *__restrict userdata,
mul_v3_v3fl(current_disp, current_disp_norm, ss->cache->bstrength);
SculptVertexNeighborIter ni;
- SCULPT_VERTEX_NEIGHBORS_ITER_BEGIN (ss, vd.index, ni) {
+ SCULPT_VERTEX_NEIGHBORS_ITER_BEGIN (ss, vd.vertex, ni) {
float vertex_disp[3];
float vertex_disp_norm[3];
- sub_v3_v3v3(vertex_disp, SCULPT_vertex_co_get(ss, ni.index), vd.co);
+ sub_v3_v3v3(vertex_disp, SCULPT_vertex_co_get(ss, ni.vertex), vd.co);
const float *neighbor_color = ss->cache->prev_colors[ni.index];
normalize_v3_v3(vertex_disp_norm, vertex_disp);
if (dot_v3v3(current_disp_norm, vertex_disp_norm) < 0.0f) {
@@ -448,7 +453,7 @@ static void do_smear_store_prev_colors_task_cb_exec(void *__restrict userdata,
PBVHVertexIter vd;
BKE_pbvh_vertex_iter_begin(ss->pbvh, data->nodes[n], vd, PBVH_ITER_UNIQUE)
{
- copy_v4_v4(ss->cache->prev_colors[vd.index], SCULPT_vertex_color_get(ss, vd.index));
+ copy_v4_v4(ss->cache->prev_colors[vd.index], SCULPT_vertex_color_get(ss, vd.vertex));
}
BKE_pbvh_vertex_iter_end;
}
@@ -462,13 +467,17 @@ void SCULPT_do_smear_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnode
return;
}
+ SCULPT_vertex_random_access_ensure(ss);
+
const int totvert = SCULPT_vertex_count_get(ss);
if (SCULPT_stroke_is_first_brush_step(ss->cache)) {
if (!ss->cache->prev_colors) {
ss->cache->prev_colors = MEM_callocN(sizeof(float[4]) * totvert, "prev colors");
for (int i = 0; i < totvert; i++) {
- copy_v4_v4(ss->cache->prev_colors[i], SCULPT_vertex_color_get(ss, i));
+ SculptVertRef vertex = BKE_pbvh_table_index_to_vertex(ss->pbvh, i);
+
+ copy_v4_v4(ss->cache->prev_colors[i], SCULPT_vertex_color_get(ss, vertex));
}
}
}
diff --git a/source/blender/editors/sculpt_paint/sculpt_pose.c b/source/blender/editors/sculpt_paint/sculpt_pose.c
index 1bf9ba60073..30d6c3a263d 100644
--- a/source/blender/editors/sculpt_paint/sculpt_pose.c
+++ b/source/blender/editors/sculpt_paint/sculpt_pose.c
@@ -172,7 +172,7 @@ static void do_pose_brush_task_cb_ex(void *__restrict userdata,
float final_pos[3];
SculptOrigVertData orig_data;
- SCULPT_orig_vert_data_init(&orig_data, data->ob, data->nodes[n]);
+ SCULPT_orig_vert_data_init(&orig_data, data->ob, data->nodes[n], SCULPT_UNDO_COORDS);
BKE_pbvh_vertex_iter_begin(ss->pbvh, data->nodes[n], vd, PBVH_ITER_UNIQUE)
{
@@ -238,7 +238,7 @@ static void pose_brush_grow_factor_task_cb_ex(void *__restrict userdata,
float max = 0.0f;
/* Grow the factor. */
- SCULPT_VERTEX_NEIGHBORS_ITER_BEGIN (ss, vd.index, ni) {
+ SCULPT_VERTEX_NEIGHBORS_ITER_BEGIN (ss, vd.vertex, ni) {
float vmask_f = data->prev_mask[ni.index];
max = MAX2(vmask_f, max);
}
@@ -384,7 +384,8 @@ typedef struct PoseFloodFillData {
int current_face_set;
int next_face_set;
int prev_face_set;
- int next_vertex;
+ SculptVertRef next_vertex;
+ int next_vertex_index;
bool next_face_set_found;
@@ -415,10 +416,12 @@ typedef struct PoseFloodFillData {
} PoseFloodFillData;
static bool pose_topology_floodfill_cb(
- SculptSession *ss, int UNUSED(from_v), int to_v, bool is_duplicate, void *userdata)
+ SculptSession *ss, SculptVertRef UNUSED(from_v), SculptVertRef to_vref, bool is_duplicate, void *userdata)
{
PoseFloodFillData *data = userdata;
- const float *co = SCULPT_vertex_co_get(ss, to_v);
+ int to_v = BKE_pbvh_vertex_index_to_table(ss->pbvh, to_vref);
+
+ const float *co = SCULPT_vertex_co_get(ss, to_vref);
if (data->pose_factor) {
data->pose_factor[to_v] = 1.0f;
@@ -444,14 +447,14 @@ static bool pose_topology_floodfill_cb(
}
static bool pose_face_sets_floodfill_cb(
- SculptSession *ss, int UNUSED(from_v), int to_v, bool is_duplicate, void *userdata)
+ SculptSession *ss, SculptVertRef UNUSED(from_v), SculptVertRef to_v, bool is_duplicate, void *userdata)
{
PoseFloodFillData *data = userdata;
- const int index = to_v;
+ const int index = BKE_pbvh_vertex_index_to_table(ss->pbvh, to_v);
bool visit_next = false;
- const float *co = SCULPT_vertex_co_get(ss, index);
+ const float *co = SCULPT_vertex_co_get(ss, to_v);
const bool symmetry_check = SCULPT_check_vertex_pivot_symmetry(
co, data->pose_initial_co, data->symm) &&
!is_duplicate;
@@ -465,11 +468,11 @@ static bool pose_face_sets_floodfill_cb(
if (sculpt_pose_brush_is_vertex_inside_brush_radius(
co, data->pose_initial_co, data->radius, data->symm)) {
- const int visited_face_set = SCULPT_vertex_face_set_get(ss, index);
+ const int visited_face_set = SCULPT_vertex_face_set_get(ss, to_v);
BLI_gset_add(data->visited_face_sets, POINTER_FROM_INT(visited_face_set));
}
else if (symmetry_check) {
- data->current_face_set = SCULPT_vertex_face_set_get(ss, index);
+ data->current_face_set = SCULPT_vertex_face_set_get(ss, to_v);
BLI_gset_add(data->visited_face_sets, POINTER_FROM_INT(data->current_face_set));
}
return true;
@@ -483,11 +486,11 @@ static bool pose_face_sets_floodfill_cb(
GSetIterator gs_iter;
GSET_ITER (gs_iter, data->visited_face_sets) {
const int visited_face_set = POINTER_AS_INT(BLI_gsetIterator_getKey(&gs_iter));
- is_vertex_valid |= SCULPT_vertex_has_face_set(ss, index, visited_face_set);
+ is_vertex_valid |= SCULPT_vertex_has_face_set(ss, to_v, visited_face_set);
}
}
else {
- is_vertex_valid = SCULPT_vertex_has_face_set(ss, index, data->current_face_set);
+ is_vertex_valid = SCULPT_vertex_has_face_set(ss, to_v, data->current_face_set);
}
if (is_vertex_valid) {
@@ -500,26 +503,27 @@ static bool pose_face_sets_floodfill_cb(
/* Fallback origin accumulation. */
if (symmetry_check) {
- add_v3_v3(data->fallback_origin, SCULPT_vertex_co_get(ss, index));
+ add_v3_v3(data->fallback_origin, SCULPT_vertex_co_get(ss, to_v));
data->fallback_count++;
}
- if (symmetry_check && !SCULPT_vertex_has_unique_face_set(ss, index)) {
+ if (symmetry_check && !SCULPT_vertex_has_unique_face_set(ss, to_v)) {
/* We only add coordinates for calculating the origin when it is possible to go from this
* vertex to another vertex in a valid face set for the next iteration. */
bool count_as_boundary = false;
SculptVertexNeighborIter ni;
- SCULPT_VERTEX_NEIGHBORS_ITER_BEGIN (ss, index, ni) {
- int next_face_set_candidate = SCULPT_vertex_face_set_get(ss, ni.index);
+ SCULPT_VERTEX_NEIGHBORS_ITER_BEGIN (ss, to_v, ni) {
+ int next_face_set_candidate = SCULPT_vertex_face_set_get(ss, ni.vertex);
/* Check if we can get a valid face set for the next iteration from this neighbor. */
- if (SCULPT_vertex_has_unique_face_set(ss, ni.index) &&
+ if (SCULPT_vertex_has_unique_face_set(ss, ni.vertex) &&
!BLI_gset_haskey(data->visited_face_sets, POINTER_FROM_INT(next_face_set_candidate))) {
if (!data->next_face_set_found) {
data->next_face_set = next_face_set_candidate;
- data->next_vertex = ni.index;
+ data->next_vertex_index = ni.index;
+ data->next_vertex = ni.vertex;
data->next_face_set_found = true;
}
count_as_boundary = true;
@@ -529,7 +533,7 @@ static bool pose_face_sets_floodfill_cb(
/* Origin accumulation. */
if (count_as_boundary) {
- add_v3_v3(data->pose_origin, SCULPT_vertex_co_get(ss, index));
+ add_v3_v3(data->pose_origin, SCULPT_vertex_co_get(ss, to_v));
data->tot_co++;
}
}
@@ -555,8 +559,6 @@ void SCULPT_pose_calc_pose_data(Sculpt *sd,
float *r_pose_origin,
float *r_pose_factor)
{
- SCULPT_vertex_random_access_ensure(ss);
-
/* Calculate the pose rotation point based on the boundaries of the brush factor. */
SculptFloodFill flood;
SCULPT_floodfill_init(ss, &flood);
@@ -608,7 +610,7 @@ static void pose_brush_init_task_cb_ex(void *__restrict userdata,
SculptVertexNeighborIter ni;
float avg = 0.0f;
int total = 0;
- SCULPT_VERTEX_NEIGHBORS_ITER_BEGIN (ss, vd.index, ni) {
+ SCULPT_VERTEX_NEIGHBORS_ITER_BEGIN (ss, vd.vertex, ni) {
avg += data->pose_factor[ni.index];
total++;
}
@@ -678,12 +680,14 @@ static SculptPoseIKChain *pose_ik_chain_init_topology(Sculpt *sd,
const float initial_location[3],
const float radius)
{
+ SCULPT_vertex_random_access_ensure(ss);
const float chain_segment_len = radius * (1.0f + br->pose_offset);
float next_chain_segment_target[3];
int totvert = SCULPT_vertex_count_get(ss);
- int nearest_vertex_index = SCULPT_nearest_vertex_get(sd, ob, initial_location, FLT_MAX, true);
+ SculptVertRef nearest_vertex = SCULPT_nearest_vertex_get(sd, ob, initial_location, FLT_MAX, true);
+ int nearest_vertex_index = BKE_pbvh_vertex_index_to_table(ss->pbvh, nearest_vertex);
/* Init the buffers used to keep track of the changes in the pose factors as more segments are
* added to the IK chain. */
@@ -768,7 +772,8 @@ static SculptPoseIKChain *pose_ik_chain_init_face_sets(
int current_face_set = SCULPT_FACE_SET_NONE;
int prev_face_set = SCULPT_FACE_SET_NONE;
- int current_vertex = SCULPT_active_vertex_get(ss);
+ SculptVertRef current_vertex = SCULPT_active_vertex_get(ss);
+ int current_vertex_i = BKE_pbvh_vertex_index_to_table(ss->pbvh, current_vertex);
for (int s = 0; s < ik_chain->tot_segments; s++) {
@@ -824,9 +829,11 @@ static SculptPoseIKChain *pose_ik_chain_init_face_sets(
}
static bool pose_face_sets_fk_find_masked_floodfill_cb(
- SculptSession *ss, int from_v, int to_v, bool is_duplicate, void *userdata)
+ SculptSession *ss, SculptVertRef from_vr, SculptVertRef to_vr, bool is_duplicate, void *userdata)
{
PoseFloodFillData *data = userdata;
+ int from_v = BKE_pbvh_vertex_index_to_table(ss->pbvh, from_vr);
+ int to_v = BKE_pbvh_vertex_index_to_table(ss->pbvh, to_vr);
if (!is_duplicate) {
data->floodfill_it[to_v] = data->floodfill_it[from_v] + 1;
@@ -835,11 +842,11 @@ static bool pose_face_sets_fk_find_masked_floodfill_cb(
data->floodfill_it[to_v] = data->floodfill_it[from_v];
}
- const int to_face_set = SCULPT_vertex_face_set_get(ss, to_v);
+ const int to_face_set = SCULPT_vertex_face_set_get(ss, to_vr);
if (!BLI_gset_haskey(data->visited_face_sets, POINTER_FROM_INT(to_face_set))) {
- if (SCULPT_vertex_has_unique_face_set(ss, to_v) &&
- !SCULPT_vertex_has_unique_face_set(ss, from_v) &&
- SCULPT_vertex_has_face_set(ss, from_v, to_face_set)) {
+ if (SCULPT_vertex_has_unique_face_set(ss, to_vr) &&
+ !SCULPT_vertex_has_unique_face_set(ss, from_vr) &&
+ SCULPT_vertex_has_face_set(ss, from_vr, to_face_set)) {
BLI_gset_add(data->visited_face_sets, POINTER_FROM_INT(to_face_set));
@@ -854,14 +861,14 @@ static bool pose_face_sets_fk_find_masked_floodfill_cb(
}
}
- return SCULPT_vertex_has_face_set(ss, to_v, data->initial_face_set);
+ return SCULPT_vertex_has_face_set(ss, to_vr, data->initial_face_set);
}
static bool pose_face_sets_fk_set_weights_floodfill_cb(
- SculptSession *ss, int UNUSED(from_v), int to_v, bool UNUSED(is_duplicate), void *userdata)
+ SculptSession *ss, SculptVertRef UNUSED(from_v), SculptVertRef to_v, bool UNUSED(is_duplicate), void *userdata)
{
PoseFloodFillData *data = userdata;
- data->fk_weights[to_v] = 1.0f;
+ data->fk_weights[BKE_pbvh_vertex_index_to_table(ss->pbvh, to_v)] = 1.0f;
return !SCULPT_vertex_has_face_set(ss, to_v, data->masked_face_set);
}
@@ -872,7 +879,9 @@ static SculptPoseIKChain *pose_ik_chain_init_face_sets_fk(
SculptPoseIKChain *ik_chain = pose_ik_chain_new(1, totvert);
- const int active_vertex = SCULPT_active_vertex_get(ss);
+ const SculptVertRef active_vertex = SCULPT_active_vertex_get(ss);
+ const int active_vertex_i = BKE_pbvh_vertex_index_to_table(ss->pbvh, active_vertex);
+
const int active_face_set = SCULPT_active_face_set_get(ss);
SculptFloodFill flood;
@@ -880,7 +889,7 @@ static SculptPoseIKChain *pose_ik_chain_init_face_sets_fk(
SCULPT_floodfill_add_initial(&flood, active_vertex);
PoseFloodFillData fdata;
fdata.floodfill_it = MEM_calloc_arrayN(totvert, sizeof(int), "floodfill iteration");
- fdata.floodfill_it[active_vertex] = 1;
+ fdata.floodfill_it[active_vertex_i] = 1;
fdata.initial_face_set = active_face_set;
fdata.masked_face_set = SCULPT_FACE_SET_NONE;
fdata.target_face_set = SCULPT_FACE_SET_NONE;
@@ -893,9 +902,11 @@ static SculptPoseIKChain *pose_ik_chain_init_face_sets_fk(
int origin_count = 0;
float origin_acc[3] = {0.0f};
for (int i = 0; i < totvert; i++) {
- if (fdata.floodfill_it[i] != 0 && SCULPT_vertex_has_face_set(ss, i, fdata.initial_face_set) &&
- SCULPT_vertex_has_face_set(ss, i, fdata.masked_face_set)) {
- add_v3_v3(origin_acc, SCULPT_vertex_co_get(ss, i));
+ SculptVertRef vref = BKE_pbvh_table_index_to_vertex(ss->pbvh, i);
+
+ if (fdata.floodfill_it[i] != 0 && SCULPT_vertex_has_face_set(ss, vref, fdata.initial_face_set) &&
+ SCULPT_vertex_has_face_set(ss, vref, fdata.masked_face_set)) {
+ add_v3_v3(origin_acc, SCULPT_vertex_co_get(ss, vref));
origin_count++;
}
}
@@ -904,10 +915,12 @@ static SculptPoseIKChain *pose_ik_chain_init_face_sets_fk(
float target_acc[3] = {0.0f};
if (fdata.target_face_set != fdata.masked_face_set) {
for (int i = 0; i < totvert; i++) {
+ SculptVertRef vref = BKE_pbvh_table_index_to_vertex(ss->pbvh, i);
+
if (fdata.floodfill_it[i] != 0 &&
- SCULPT_vertex_has_face_set(ss, i, fdata.initial_face_set) &&
- SCULPT_vertex_has_face_set(ss, i, fdata.target_face_set)) {
- add_v3_v3(target_acc, SCULPT_vertex_co_get(ss, i));
+ SCULPT_vertex_has_face_set(ss, vref, fdata.initial_face_set) &&
+ SCULPT_vertex_has_face_set(ss, vref, fdata.target_face_set)) {
+ add_v3_v3(target_acc, SCULPT_vertex_co_get(ss, vref));
target_count++;
}
}
diff --git a/source/blender/editors/sculpt_paint/sculpt_smooth.c b/source/blender/editors/sculpt_paint/sculpt_smooth.c
index 87ee7480c92..894efa3c30a 100644
--- a/source/blender/editors/sculpt_paint/sculpt_smooth.c
+++ b/source/blender/editors/sculpt_paint/sculpt_smooth.c
@@ -58,11 +58,18 @@
#include "RNA_define.h"
#include "bmesh.h"
-
+#ifdef PROXY_ADVANCED
+/* clang-format off */
+#include "BKE_DerivedMesh.h"
+#include "../../blenkernel/intern/pbvh_intern.h"
+/* clang-format on */
+#endif
#include <math.h>
#include <stdlib.h>
-void SCULPT_neighbor_coords_average_interior(SculptSession *ss, float result[3], int index)
+void SCULPT_neighbor_coords_average_interior(SculptSession *ss,
+ float result[3],
+ SculptVertRef index)
{
float avg[3] = {0.0f, 0.0f, 0.0f};
int total = 0;
@@ -74,14 +81,14 @@ void SCULPT_neighbor_coords_average_interior(SculptSession *ss, float result[3],
neighbor_count++;
if (is_boundary) {
/* Boundary vertices use only other boundary vertices. */
- if (SCULPT_vertex_is_boundary(ss, ni.index)) {
- add_v3_v3(avg, SCULPT_vertex_co_get(ss, ni.index));
+ if (SCULPT_vertex_is_boundary(ss, ni.vertex)) {
+ add_v3_v3(avg, SCULPT_vertex_co_get(ss, ni.vertex));
total++;
}
}
else {
/* Interior vertices use all neighbors. */
- add_v3_v3(avg, SCULPT_vertex_co_get(ss, ni.index));
+ add_v3_v3(avg, SCULPT_vertex_co_get(ss, ni.vertex));
total++;
}
}
@@ -152,14 +159,14 @@ void SCULPT_bmesh_four_neighbor_average(float avg[3], float direction[3], BMVert
/* Generic functions for laplacian smoothing. These functions do not take boundary vertices into
* account. */
-void SCULPT_neighbor_coords_average(SculptSession *ss, float result[3], int index)
+void SCULPT_neighbor_coords_average(SculptSession *ss, float result[3], SculptVertRef index)
{
float avg[3] = {0.0f, 0.0f, 0.0f};
int total = 0;
SculptVertexNeighborIter ni;
SCULPT_VERTEX_NEIGHBORS_ITER_BEGIN (ss, index, ni) {
- add_v3_v3(avg, SCULPT_vertex_co_get(ss, ni.index));
+ add_v3_v3(avg, SCULPT_vertex_co_get(ss, ni.vertex));
total++;
}
SCULPT_VERTEX_NEIGHBORS_ITER_END(ni);
@@ -172,14 +179,14 @@ void SCULPT_neighbor_coords_average(SculptSession *ss, float result[3], int inde
}
}
-float SCULPT_neighbor_mask_average(SculptSession *ss, int index)
+float SCULPT_neighbor_mask_average(SculptSession *ss, SculptVertRef index)
{
float avg = 0.0f;
int total = 0;
SculptVertexNeighborIter ni;
SCULPT_VERTEX_NEIGHBORS_ITER_BEGIN (ss, index, ni) {
- avg += SCULPT_vertex_mask_get(ss, ni.index);
+ avg += SCULPT_vertex_mask_get(ss, ni.vertex);
total++;
}
SCULPT_VERTEX_NEIGHBORS_ITER_END(ni);
@@ -190,14 +197,14 @@ float SCULPT_neighbor_mask_average(SculptSession *ss, int index)
return SCULPT_vertex_mask_get(ss, index);
}
-void SCULPT_neighbor_color_average(SculptSession *ss, float result[4], int index)
+void SCULPT_neighbor_color_average(SculptSession *ss, float result[4], SculptVertRef index)
{
float avg[4] = {0.0f, 0.0f, 0.0f, 0.0f};
int total = 0;
SculptVertexNeighborIter ni;
SCULPT_VERTEX_NEIGHBORS_ITER_BEGIN (ss, index, ni) {
- add_v4_v4(avg, SCULPT_vertex_color_get(ss, ni.index));
+ add_v4_v4(avg, SCULPT_vertex_color_get(ss, ni.vertex));
total++;
}
SCULPT_VERTEX_NEIGHBORS_ITER_END(ni);
@@ -239,7 +246,7 @@ static void do_enhance_details_brush_task_cb_ex(void *__restrict userdata,
vd.no,
vd.fno,
vd.mask ? *vd.mask : 0.0f,
- vd.index,
+ vd.vertex,
thread_id);
float disp[3];
@@ -272,8 +279,10 @@ static void SCULPT_enhance_details_brush(Sculpt *sd,
for (int i = 0; i < totvert; i++) {
float avg[3];
- SCULPT_neighbor_coords_average(ss, avg, i);
- sub_v3_v3v3(ss->cache->detail_directions[i], avg, SCULPT_vertex_co_get(ss, i));
+ SculptVertRef vertex = BKE_pbvh_table_index_to_vertex(ss->pbvh, i);
+
+ SCULPT_neighbor_coords_average(ss, avg, vertex);
+ sub_v3_v3v3(ss->cache->detail_directions[i], avg, SCULPT_vertex_co_get(ss, vertex));
}
}
@@ -289,6 +298,88 @@ 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);
+
+ if (key->pindex < 0 || key->pindex >= n2->proxyverts.size) {
+ printf("corruption!\n");
+ fflush(stdout);
+ ni++;
+ continue;
+ }
+
+ if (n2->proxyverts.co) {
+ 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)
@@ -321,17 +412,17 @@ static void do_smooth_brush_task_cb_ex(void *__restrict userdata,
vd.no,
vd.fno,
smooth_mask ? 0.0f : (vd.mask ? *vd.mask : 0.0f),
- vd.index,
+ vd.vertex,
thread_id);
if (smooth_mask) {
- float val = SCULPT_neighbor_mask_average(ss, vd.index) - *vd.mask;
+ float val = SCULPT_neighbor_mask_average(ss, vd.vertex) - *vd.mask;
val *= fade * bstrength;
*vd.mask += val;
CLAMP(*vd.mask, 0.0f, 1.0f);
}
else {
float avg[3], val[3];
- SCULPT_neighbor_coords_average_interior(ss, avg, vd.index);
+ SCULPT_neighbor_coords_average_interior(ss, avg, vd.vertex);
sub_v3_v3v3(val, avg, vd.co);
madd_v3_v3v3fl(val, vd.co, val, fade);
SCULPT_clip(sd, ss, vd.co, val);
@@ -343,6 +434,7 @@ static void do_smooth_brush_task_cb_ex(void *__restrict userdata,
}
BKE_pbvh_vertex_iter_end;
}
+#endif
void SCULPT_smooth(Sculpt *sd,
Object *ob,
@@ -370,9 +462,18 @@ void SCULPT_smooth(Sculpt *sd,
return;
}
- SCULPT_vertex_random_access_ensure(ss);
+ if (type != PBVH_BMESH) {
+ 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, nodes, totnode, 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;
@@ -388,6 +489,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
}
}
@@ -411,7 +516,7 @@ void SCULPT_surface_smooth_laplacian_step(SculptSession *ss,
float *disp,
const float co[3],
float (*laplacian_disp)[3],
- const int v_index,
+ const SculptVertRef v_index,
const float origco[3],
const float alpha)
{
@@ -419,10 +524,12 @@ void SCULPT_surface_smooth_laplacian_step(SculptSession *ss,
float weigthed_o[3], weigthed_q[3], d[3];
SCULPT_neighbor_coords_average(ss, laplacian_smooth_co, v_index);
+ int index = BKE_pbvh_vertex_index_to_table(ss->pbvh, v_index);
+
mul_v3_v3fl(weigthed_o, origco, alpha);
mul_v3_v3fl(weigthed_q, co, 1.0f - alpha);
add_v3_v3v3(d, weigthed_o, weigthed_q);
- sub_v3_v3v3(laplacian_disp[v_index], laplacian_smooth_co, d);
+ sub_v3_v3v3(laplacian_disp[index], laplacian_smooth_co, d);
sub_v3_v3v3(disp, laplacian_smooth_co, co);
}
@@ -430,22 +537,25 @@ void SCULPT_surface_smooth_laplacian_step(SculptSession *ss,
void SCULPT_surface_smooth_displace_step(SculptSession *ss,
float *co,
float (*laplacian_disp)[3],
- const int v_index,
+ const SculptVertRef v_index,
const float beta,
const float fade)
{
float b_avg[3] = {0.0f, 0.0f, 0.0f};
float b_current_vertex[3];
int total = 0;
+ int index = BKE_pbvh_vertex_index_to_table(ss->pbvh, v_index);
+
SculptVertexNeighborIter ni;
SCULPT_VERTEX_NEIGHBORS_ITER_BEGIN (ss, v_index, ni) {
add_v3_v3(b_avg, laplacian_disp[ni.index]);
total++;
}
SCULPT_VERTEX_NEIGHBORS_ITER_END(ni);
+
if (total > 0) {
mul_v3_v3fl(b_current_vertex, b_avg, (1.0f - beta) / total);
- madd_v3_v3fl(b_current_vertex, laplacian_disp[v_index], beta);
+ madd_v3_v3fl(b_current_vertex, laplacian_disp[index], beta);
mul_v3_fl(b_current_vertex, clamp_f(fade, 0.0f, 1.0f));
sub_v3_v3(co, b_current_vertex);
}
@@ -468,7 +578,7 @@ static void SCULPT_do_surface_smooth_brush_laplacian_task_cb_ex(
ss, &test, data->brush->falloff_shape);
const int thread_id = BLI_task_parallel_thread_id(tls);
- SCULPT_orig_vert_data_init(&orig_data, data->ob, data->nodes[n]);
+ SCULPT_orig_vert_data_init(&orig_data, data->ob, data->nodes[n], SCULPT_UNDO_COORDS);
BKE_pbvh_vertex_iter_begin(ss->pbvh, data->nodes[n], vd, PBVH_ITER_UNIQUE)
{
@@ -481,7 +591,7 @@ static void SCULPT_do_surface_smooth_brush_laplacian_task_cb_ex(
vd.no,
vd.fno,
vd.mask ? *vd.mask : 0.0f,
- vd.index,
+ vd.vertex,
thread_id);
float disp[3];
@@ -489,7 +599,7 @@ static void SCULPT_do_surface_smooth_brush_laplacian_task_cb_ex(
disp,
vd.co,
ss->cache->surface_smooth_laplacian_disp,
- vd.index,
+ vd.vertex,
orig_data.co,
alpha);
madd_v3_v3fl(vd.co, disp, clamp_f(fade, 0.0f, 1.0f));
@@ -527,10 +637,10 @@ static void SCULPT_do_surface_smooth_brush_displace_task_cb_ex(
vd.no,
vd.fno,
vd.mask ? *vd.mask : 0.0f,
- vd.index,
+ vd.vertex,
thread_id);
SCULPT_surface_smooth_displace_step(
- ss, vd.co, ss->cache->surface_smooth_laplacian_disp, vd.index, beta, fade);
+ ss, vd.co, ss->cache->surface_smooth_laplacian_disp, vd.vertex, beta, fade);
}
}
BKE_pbvh_vertex_iter_end;
@@ -564,3 +674,232 @@ void SCULPT_do_surface_smooth_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, in
0, totnode, &data, SCULPT_do_surface_smooth_brush_displace_task_cb_ex, &settings);
}
}
+
+static void do_smooth_vcol_boundary_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);
+
+ float avg[4] = {0.0f, 0.0f, 0.0f, 0.0f};
+ float tot = 0.0f;
+ BKE_pbvh_vertex_iter_begin(ss->pbvh, data->nodes[n], vd, PBVH_ITER_UNIQUE)
+ {
+ if (!vd.col) {
+ continue;
+ }
+
+ if (sculpt_brush_test_sq_fn(&test, vd.co)) {
+ const float fade = bstrength * SCULPT_brush_strength_factor(
+ ss,
+ brush,
+ vd.co,
+ sqrtf(test.dist),
+ vd.no,
+ vd.fno,
+ smooth_mask ? 0.0f : (vd.mask ? *vd.mask : 0.0f),
+ vd.vertex,
+ thread_id);
+
+ madd_v3_v3fl(avg, vd.col, fade);
+ tot += fade;
+ }
+ }
+ BKE_pbvh_vertex_iter_end;
+
+ if (tot == 0.0f) {
+ return;
+ }
+ tot = 1.0f / tot;
+
+ mul_v3_fl(avg, tot);
+
+ float exp = brush->vcol_boundary_exponent;
+ //detect bad value
+
+ if (exp == 0.0f) {
+ exp = 1.0f;
+ }
+
+ //#define SHARPEN_VCOL_BOUNDARY
+
+ BKE_pbvh_vertex_iter_begin(ss->pbvh, data->nodes[n], vd, PBVH_ITER_UNIQUE)
+ {
+ if (sculpt_brush_test_sq_fn(&test, vd.co)) {
+ const float fade = bstrength * SCULPT_brush_strength_factor(
+ ss,
+ brush,
+ vd.co,
+ sqrtf(test.dist),
+ vd.no,
+ vd.fno,
+ smooth_mask ? 0.0f : (vd.mask ? *vd.mask : 0.0f),
+ vd.vertex,
+ thread_id);
+ if (!vd.col) {
+ continue;
+ }
+
+ float avg2[3], avg3[3], val[3];
+ float tot2 = 0.0f, tot4 = 0.0f;
+
+ copy_v4_v4(avg, vd.col);
+
+ zero_v3(avg2);
+ zero_v3(avg3);
+
+ madd_v3_v3fl(avg2, vd.co, 0.5f);
+ tot2 += 0.5f;
+
+#ifdef SHARPEN_VCOL_BOUNDARY
+ float ntot = 0.0f;
+ float colavg[4], tot3 = 0.0f;
+ zero_v4(colavg);
+#endif
+
+ SculptVertexNeighborIter ni;
+ SCULPT_VERTEX_NEIGHBORS_ITER_BEGIN (ss, vd.vertex, ni) {
+ const float *col = SCULPT_vertex_color_get(ss, ni.vertex);
+ const float *co = SCULPT_vertex_co_get(ss, ni.vertex);
+
+ // simple color metric. TODO: plug in appropriate color space code?
+ float dv[4];
+ sub_v4_v4v4(dv, col, avg);
+ float w = (fabs(dv[0]) + fabs(dv[1]) + fabs(dv[2]) + fabs(dv[3])) / 4.0;
+
+ w = powf(w, exp);
+
+ //w *= w;
+
+#ifdef SHARPEN_VCOL_BOUNDARY
+ float w2 = -1.0f;
+ madd_v4_v4fl(colavg, col, w2);
+ tot3 += w2;
+ ntot += 1.0f;
+#endif
+
+ madd_v3_v3fl(avg3, co, 1.0f);
+ tot4 += 1.0f;
+
+ madd_v3_v3fl(avg2, co, w);
+ tot2 += w;
+ }
+ SCULPT_VERTEX_NEIGHBORS_ITER_END(ni);
+
+ if (tot2 == 0.0f) {
+ continue;
+ }
+
+ if (tot4 > 0.0f) {
+ mul_v3_fl(avg3, 1.0f / tot4);
+ }
+
+#ifdef SHARPEN_VCOL_BOUNDARY
+ float w2 = ntot*40.0f;
+ madd_v4_v4fl(colavg, vd.col, w2);
+ tot3 += w2;
+
+ if (tot3 > 0.0f) {
+ mul_v4_fl(colavg, 1.0f / tot3);
+ }
+
+ //clamp_v4(colavg, 0.0f, 1.0f);
+ //negative numbers are undesirable, but dunno if I should clip above 1.0 or not except for alpha
+ for (int i=0; i<4; i++) {
+ colavg[i] = MAX2(colavg[i], 0.0f);
+ colavg[i] = MIN2(colavg[i], 1.0f);
+ }
+ //colavg[3] = MIN2(colavg[3], 1.0f);
+
+ interp_v4_v4v4(vd.col, vd.col, colavg, fade*0.25);
+#endif
+
+ //try to avoid perfectly colinear triangles, and the normal discontinuities they create,
+ //by blending slightly with unweighted smoothed position
+ mul_v3_fl(avg2, 1.0f / tot2);
+ interp_v3_v3v3(avg2, avg2, avg3, 0.025);
+
+ sub_v3_v3v3(val, avg2, vd.co);
+ madd_v3_v3v3fl(val, vd.co, val, fade);
+ SCULPT_clip(sd, ss, vd.co, val);
+
+ if (vd.mvert) {
+ vd.mvert->flag |= ME_VERT_PBVH_UPDATE;
+ }
+ }
+ }
+ BKE_pbvh_vertex_iter_end;
+}
+
+void SCULPT_smooth_vcol_boundary(
+ Sculpt *sd, Object *ob, PBVHNode **nodes, const int totnode, float bstrength)
+{
+ SculptSession *ss = ob->sculpt;
+
+ Brush *brush = BKE_paint_brush(&sd->paint);
+
+ const int max_iterations = 4;
+ const float fract = 1.0f / max_iterations;
+ PBVHType type = BKE_pbvh_type(ss->pbvh);
+ int iteration, count;
+ float last;
+
+ CLAMP(bstrength, 0.0f, 1.0f);
+
+ count = (int)(bstrength * max_iterations);
+ last = max_iterations * (bstrength - count * fract);
+
+ if (type == PBVH_FACES && !ss->pmap) {
+ BLI_assert(!"sculpt smooth: pmap missing");
+ return;
+ }
+
+ if (type != PBVH_BMESH) {
+ 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, nodes, totnode, 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;
+
+ SculptThreadedTaskData data = {
+ .sd = sd,
+ .ob = ob,
+ .brush = brush,
+ .nodes = nodes,
+ .smooth_mask = false,
+ .strength = strength,
+ };
+
+ TaskParallelSettings settings;
+ BKE_pbvh_parallel_range_settings(&settings, true, totnode);
+ BLI_task_parallel_range(
+ 0, totnode, &data, do_smooth_vcol_boundary_brush_task_cb_ex, &settings);
+
+#ifdef PROXY_ADVANCED
+ BKE_pbvh_gather_proxyarray(ss->pbvh, nodes, totnode);
+#endif
+ }
+}
diff --git a/source/blender/editors/sculpt_paint/sculpt_transform.c b/source/blender/editors/sculpt_paint/sculpt_transform.c
index f74d59e1987..29db601e590 100644
--- a/source/blender/editors/sculpt_paint/sculpt_transform.c
+++ b/source/blender/editors/sculpt_paint/sculpt_transform.c
@@ -160,7 +160,7 @@ static void sculpt_transform_task_cb(void *__restrict userdata,
PBVHNode *node = data->nodes[i];
SculptOrigVertData orig_data;
- SCULPT_orig_vert_data_init(&orig_data, data->ob, data->nodes[i]);
+ SCULPT_orig_vert_data_init(&orig_data, data->ob, data->nodes[i], SCULPT_UNDO_COORDS);
PBVHVertexIter vd;
diff --git a/source/blender/editors/sculpt_paint/sculpt_undo.c b/source/blender/editors/sculpt_paint/sculpt_undo.c
index af2aad14008..4b29b95763f 100644
--- a/source/blender/editors/sculpt_paint/sculpt_undo.c
+++ b/source/blender/editors/sculpt_paint/sculpt_undo.c
@@ -116,6 +116,7 @@ typedef struct UndoSculpt {
} UndoSculpt;
static UndoSculpt *sculpt_undo_get_nodes(void);
+void sculpt_undo_print_nodes(void *active);
static void update_cb(PBVHNode *node, void *rebuild)
{
@@ -133,6 +134,8 @@ struct PartialUpdateData {
char *modified_grids;
};
+static UndoSculpt *sculpt_undosys_step_get_nodes(UndoStep *us_p);
+
/**
* A version of #update_cb that tests for 'ME_VERT_PBVH_UPDATE'
*/
@@ -180,14 +183,14 @@ static bool sculpt_undo_restore_deformed(
return false;
}
-static bool sculpt_undo_restore_coords(bContext *C, Depsgraph *depsgraph, SculptUndoNode *unode)
+__attribute__((optnone)) static bool sculpt_undo_restore_coords(bContext *C, Depsgraph *depsgraph, SculptUndoNode *unode)
{
ViewLayer *view_layer = CTX_data_view_layer(C);
Object *ob = OBACT(view_layer);
SculptSession *ss = ob->sculpt;
SubdivCCG *subdiv_ccg = ss->subdiv_ccg;
MVert *mvert;
- int *index;
+ SculptVertRef *index;
if (unode->maxvert) {
/* Regular mesh restore. */
@@ -221,18 +224,18 @@ static bool sculpt_undo_restore_coords(bContext *C, Depsgraph *depsgraph, Sculpt
if (unode->orig_co) {
if (ss->deform_modifiers_active) {
for (int i = 0; i < unode->totvert; i++) {
- sculpt_undo_restore_deformed(ss, unode, i, index[i], vertCos[index[i]]);
+ sculpt_undo_restore_deformed(ss, unode, i, index[i].i, vertCos[index[i].i]);
}
}
else {
for (int i = 0; i < unode->totvert; i++) {
- swap_v3_v3(vertCos[index[i]], unode->orig_co[i]);
+ swap_v3_v3(vertCos[index[i].i], unode->orig_co[i]);
}
}
}
else {
for (int i = 0; i < unode->totvert; i++) {
- swap_v3_v3(vertCos[index[i]], unode->co[i]);
+ swap_v3_v3(vertCos[index[i].i], unode->co[i]);
}
}
@@ -249,21 +252,21 @@ static bool sculpt_undo_restore_coords(bContext *C, Depsgraph *depsgraph, Sculpt
if (unode->orig_co) {
if (ss->deform_modifiers_active) {
for (int i = 0; i < unode->totvert; i++) {
- sculpt_undo_restore_deformed(ss, unode, i, index[i], mvert[index[i]].co);
- mvert[index[i]].flag |= ME_VERT_PBVH_UPDATE;
+ sculpt_undo_restore_deformed(ss, unode, i, index[i].i, mvert[index[i].i].co);
+ mvert[index[i].i].flag |= ME_VERT_PBVH_UPDATE;
}
}
else {
for (int i = 0; i < unode->totvert; i++) {
- swap_v3_v3(mvert[index[i]].co, unode->orig_co[i]);
- mvert[index[i]].flag |= ME_VERT_PBVH_UPDATE;
+ swap_v3_v3(mvert[index[i].i].co, unode->orig_co[i]);
+ mvert[index[i].i].flag |= ME_VERT_PBVH_UPDATE;
}
}
}
else {
for (int i = 0; i < unode->totvert; i++) {
- swap_v3_v3(mvert[index[i]].co, unode->co[i]);
- mvert[index[i]].flag |= ME_VERT_PBVH_UPDATE;
+ swap_v3_v3(mvert[index[i].i].co, unode->co[i]);
+ mvert[index[i].i].flag |= ME_VERT_PBVH_UPDATE;
}
}
}
@@ -303,7 +306,7 @@ static bool sculpt_undo_restore_hidden(bContext *C, SculptUndoNode *unode)
MVert *mvert = ss->mvert;
for (int i = 0; i < unode->totvert; i++) {
- MVert *v = &mvert[unode->index[i]];
+ MVert *v = &mvert[unode->index[i].i];
if ((BLI_BITMAP_TEST(unode->vert_hidden, i) != 0) != ((v->flag & ME_HIDE) != 0)) {
BLI_BITMAP_FLIP(unode->vert_hidden, i);
v->flag ^= ME_HIDE;
@@ -335,7 +338,7 @@ static bool sculpt_undo_restore_color(bContext *C, SculptUndoNode *unode)
MPropCol *vcol = ss->vcol;
for (int i = 0; i < unode->totvert; i++) {
- copy_v4_v4(vcol[index[i]].color, unode->col[i]);
+ swap_v4_v4(vcol[index[i]].color, unode->col[i]);
mvert[index[i]].flag |= ME_VERT_PBVH_UPDATE;
}
}
@@ -421,7 +424,7 @@ static void sculpt_undo_bmesh_restore_generic(SculptUndoNode *unode, Object *ob,
unode->applied = true;
}
- if (unode->type == SCULPT_UNDO_MASK) {
+ if (unode->type == SCULPT_UNDO_MASK || unode->type == SCULPT_UNDO_COLOR) {
int totnode;
PBVHNode **nodes;
@@ -460,6 +463,8 @@ static void sculpt_undo_bmesh_enable(Object *ob, SculptUndoNode *unode)
/* Restore the BMLog using saved entries. */
ss->bm_log = BM_log_from_existing_entries_create(ss->bm, unode->bm_entry);
+ BM_log_set_cd_offsets(
+ ss->bm_log, ss->cd_origco_offset, ss->cd_origno_offset, ss->cd_origvcol_offset);
}
static void sculpt_undo_bmesh_restore_begin(bContext *C,
@@ -499,6 +504,8 @@ static void sculpt_undo_bmesh_restore_end(bContext *C,
SCULPT_dynamic_topology_disable(C, NULL);
unode->applied = true;
}
+
+ BM_mesh_elem_index_ensure(ss->bm, BM_VERT);
}
static void sculpt_undo_geometry_store_data(SculptUndoNodeGeometry *geometry, Object *object)
@@ -590,17 +597,25 @@ static int sculpt_undo_bmesh_restore(bContext *C,
Object *ob,
SculptSession *ss)
{
+ if (ss->bm_log) {
+ BM_log_set_cd_offsets(
+ ss->bm_log, ss->cd_origco_offset, ss->cd_origno_offset, ss->cd_origvcol_offset);
+ }
+
switch (unode->type) {
case SCULPT_UNDO_DYNTOPO_BEGIN:
sculpt_undo_bmesh_restore_begin(C, unode, ob, ss);
+ SCULPT_vertex_random_access_ensure(ss);
return true;
case SCULPT_UNDO_DYNTOPO_END:
sculpt_undo_bmesh_restore_end(C, unode, ob, ss);
+ SCULPT_vertex_random_access_ensure(ss);
return true;
default:
if (ss->bm_log) {
sculpt_undo_bmesh_restore_generic(unode, ob, ss);
+ SCULPT_vertex_random_access_ensure(ss);
return true;
}
break;
@@ -609,7 +624,9 @@ static int sculpt_undo_bmesh_restore(bContext *C,
return false;
}
-static void sculpt_undo_restore_list(bContext *C, Depsgraph *depsgraph, ListBase *lb)
+static void sculpt_undo_restore_list(bContext *C,
+ Depsgraph *depsgraph,
+ ListBase *lb)
{
Scene *scene = CTX_data_scene(C);
ViewLayer *view_layer = CTX_data_view_layer(C);
@@ -637,7 +654,7 @@ static void sculpt_undo_restore_list(bContext *C, Depsgraph *depsgraph, ListBase
DEG_id_tag_update(&ob->id, ID_RECALC_SHADING);
- if (lb->first) {
+ if (!ss->bm && lb->first) {
unode = lb->first;
if (unode->type == SCULPT_UNDO_FACE_SETS) {
sculpt_undo_restore_face_sets(C, unode);
@@ -692,6 +709,7 @@ static void sculpt_undo_restore_list(bContext *C, Depsgraph *depsgraph, ListBase
* continue. */
if (unode->maxvert) {
if (ss->totvert != unode->maxvert) {
+ printf("error! %s\n", __func__);
continue;
}
}
@@ -831,6 +849,9 @@ static void sculpt_undo_free_list(ListBase *lb)
if (unode->co) {
MEM_freeN(unode->co);
}
+ if (unode->nodemap) {
+ MEM_freeN(unode->nodemap);
+ }
if (unode->no) {
MEM_freeN(unode->no);
}
@@ -860,6 +881,7 @@ static void sculpt_undo_free_list(ListBase *lb)
if (unode->bm_entry) {
BM_log_entry_drop(unode->bm_entry);
+ unode->bm_entry = NULL;
}
sculpt_undo_geometry_free_data(&unode->geometry_original);
@@ -899,7 +921,7 @@ static bool sculpt_undo_cleanup(bContext *C, ListBase *lb)
}
#endif
-SculptUndoNode *SCULPT_undo_get_node(PBVHNode *node)
+SculptUndoNode *SCULPT_undo_get_node(PBVHNode *node, SculptUndoType type)
{
UndoSculpt *usculpt = sculpt_undo_get_nodes();
@@ -907,7 +929,19 @@ SculptUndoNode *SCULPT_undo_get_node(PBVHNode *node)
return NULL;
}
- return BLI_findptr(&usculpt->nodes, node, offsetof(SculptUndoNode, node));
+ if (type < 0) {
+ return BLI_findptr(&usculpt->nodes, node, offsetof(SculptUndoNode, node));
+ }
+
+ SculptUndoNode *unode;
+
+ for (unode = usculpt->nodes.first; unode; unode = unode->next) {
+ if (unode->node == node && type == unode->type) {
+ return unode;
+ }
+ }
+
+ return NULL;
}
SculptUndoNode *SCULPT_undo_get_first_node()
@@ -1038,7 +1072,7 @@ static SculptUndoNode *sculpt_undo_alloc_node(Object *ob, PBVHNode *node, Sculpt
else {
/* Regular mesh. */
unode->maxvert = ss->totvert;
- unode->index = MEM_callocN(sizeof(int) * allvert, "SculptUndoNode.index");
+ unode->index = MEM_callocN(sizeof(SculptVertRef) * allvert, "SculptUndoNode.index");
}
if (ss->deform_modifiers_active) {
@@ -1053,6 +1087,9 @@ static void sculpt_undo_store_coords(Object *ob, SculptUndoNode *unode)
SculptSession *ss = ob->sculpt;
PBVHVertexIter vd;
+ SculptOrigVertData orig_data;
+ SCULPT_orig_vert_data_unode_init(&orig_data, ob, unode);
+
BKE_pbvh_vertex_iter_begin(ss->pbvh, unode->node, vd, PBVH_ITER_ALL)
{
copy_v3_v3(unode->co[vd.i], vd.co);
@@ -1064,7 +1101,11 @@ static void sculpt_undo_store_coords(Object *ob, SculptUndoNode *unode)
}
if (ss->deform_modifiers_active) {
- copy_v3_v3(unode->orig_co[vd.i], ss->orig_cos[unode->index[vd.i]]);
+ SCULPT_orig_vert_data_update(&orig_data, &vd);
+
+ int index = BKE_pbvh_vertex_index_to_table(ss->pbvh, unode->index[vd.i]);
+
+ copy_v3_v3(unode->orig_co[vd.i], orig_data.co);
}
}
BKE_pbvh_vertex_iter_end;
@@ -1171,7 +1212,10 @@ static SculptUndoNode *sculpt_undo_bmesh_push(Object *ob, PBVHNode *node, Sculpt
SculptUndoNode *unode = usculpt->nodes.first;
+ bool new_node = false;
+
if (unode == NULL) {
+ new_node = true;
unode = MEM_callocN(sizeof(*unode), __func__);
BLI_strncpy(unode->idname, ob->id.name, sizeof(unode->idname));
@@ -1179,7 +1223,7 @@ static SculptUndoNode *sculpt_undo_bmesh_push(Object *ob, PBVHNode *node, Sculpt
unode->applied = true;
if (type == SCULPT_UNDO_DYNTOPO_END) {
- unode->bm_entry = BM_log_entry_add(ss->bm_log);
+ unode->bm_entry = BM_log_entry_add(ss->bm, ss->bm_log);
BM_log_before_all_removed(ss->bm, ss->bm_log);
}
else if (type == SCULPT_UNDO_DYNTOPO_BEGIN) {
@@ -1191,17 +1235,21 @@ static SculptUndoNode *sculpt_undo_bmesh_push(Object *ob, PBVHNode *node, Sculpt
SculptUndoNodeGeometry *geometry = &unode->geometry_bmesh_enter;
sculpt_undo_geometry_store_data(geometry, ob);
- unode->bm_entry = BM_log_entry_add(ss->bm_log);
+ unode->bm_entry = BM_log_entry_add(ss->bm, ss->bm_log);
BM_log_all_added(ss->bm, ss->bm_log);
}
else {
- unode->bm_entry = BM_log_entry_add(ss->bm_log);
+ unode->bm_entry = BM_log_entry_add(ss->bm, ss->bm_log);
}
BLI_addtail(&usculpt->nodes, unode);
}
if (node) {
+ if (BKE_pbvh_type(ss->pbvh) == PBVH_BMESH) {
+ unode->bm_entry = BM_log_entry_check_customdata(ss->bm, ss->bm_log);
+ }
+
switch (type) {
case SCULPT_UNDO_COORDS:
case SCULPT_UNDO_MASK:
@@ -1209,40 +1257,118 @@ static SculptUndoNode *sculpt_undo_bmesh_push(Object *ob, PBVHNode *node, Sculpt
* original positions are logged. */
BKE_pbvh_vertex_iter_begin(ss->pbvh, node, vd, PBVH_ITER_ALL)
{
- BM_log_vert_before_modified(ss->bm_log, vd.bm_vert, vd.cd_vert_mask_offset);
+ void *dummy;
+ BKE_pbvh_bmesh_update_origvert(ss->pbvh, vd.bm_vert, &dummy, &dummy, &dummy);
+ // BM_log_vert_before_modified(ss->bm_log, vd.bm_vert, vd.cd_vert_mask_offset, false);
}
BKE_pbvh_vertex_iter_end;
break;
case SCULPT_UNDO_HIDDEN: {
- GSetIterator gs_iter;
- GSet *faces = BKE_pbvh_bmesh_node_faces(node);
+ TableGSet *faces = BKE_pbvh_bmesh_node_faces(node);
+ BMFace *f;
+
BKE_pbvh_vertex_iter_begin(ss->pbvh, node, vd, PBVH_ITER_ALL)
{
- BM_log_vert_before_modified(ss->bm_log, vd.bm_vert, vd.cd_vert_mask_offset);
+ BM_log_vert_before_modified(ss->bm_log, vd.bm_vert, vd.cd_vert_mask_offset, true);
+ // BKE_pbvh_bmesh_update_origvert(ss->pbvh, vd.bm_vert, &dummy, &dummy, &dummy);
}
BKE_pbvh_vertex_iter_end;
- GSET_ITER (gs_iter, faces) {
- BMFace *f = BLI_gsetIterator_getKey(&gs_iter);
+ TGSET_ITER (f, faces) {
BM_log_face_modified(ss->bm_log, f);
}
+ TGSET_ITER_END
+ break;
+ }
+
+ case SCULPT_UNDO_COLOR: {
+#if 1
+ BKE_pbvh_vertex_iter_begin(ss->pbvh, node, vd, PBVH_ITER_ALL)
+ {
+ void *dummy;
+ BKE_pbvh_bmesh_update_origvert(ss->pbvh, vd.bm_vert, NULL, NULL, &dummy);
+ }
+ BKE_pbvh_vertex_iter_end;
+#endif
break;
}
+ case SCULPT_UNDO_FACE_SETS: {
+ TableGSet *faces = BKE_pbvh_bmesh_node_faces(node);
+ BMFace *f;
+
+ TGSET_ITER (f, faces) {
+ BM_log_face_modified(ss->bm_log, f);
+ }
+ TGSET_ITER_END
+ break;
+ }
case SCULPT_UNDO_DYNTOPO_BEGIN:
case SCULPT_UNDO_DYNTOPO_END:
case SCULPT_UNDO_DYNTOPO_SYMMETRIZE:
case SCULPT_UNDO_GEOMETRY:
- case SCULPT_UNDO_FACE_SETS:
- case SCULPT_UNDO_COLOR:
break;
}
}
+ if (new_node) {
+ sculpt_undo_print_nodes(NULL);
+ }
+
return unode;
}
+bool SCULPT_ensure_dyntopo_node_undo(Object *ob,
+ PBVHNode *node,
+ SculptUndoType type,
+ int extraType)
+{
+ SculptSession *ss = ob->sculpt;
+ UndoSculpt *usculpt = sculpt_undo_get_nodes();
+ SculptUndoNode *unode = usculpt->nodes.first;
+
+ if (!unode || unode->type != type) {
+ unode = sculpt_undo_alloc_node_type(ob, type);
+
+ BLI_strncpy(unode->idname, ob->id.name, sizeof(unode->idname));
+
+ unode->type = type;
+ unode->applied = true;
+ unode->bm_entry = BM_log_entry_add(ss->bm, ss->bm_log);
+
+ return SCULPT_ensure_dyntopo_node_undo(ob, node, type, extraType);
+ }
+
+ int n = BKE_pbvh_get_node_index(ss->pbvh, node);
+
+ if (unode->nodemap_size <= n) {
+ int newsize = (n + 1) * 2;
+
+ if (!unode->nodemap) {
+ unode->nodemap = MEM_callocN(sizeof(*unode->nodemap) * newsize, "unode->nodemap");
+ }
+ else {
+ unode->nodemap = MEM_recallocN(unode->nodemap, sizeof(*unode->nodemap) * newsize);
+ }
+
+ unode->nodemap_size = newsize;
+ }
+
+ if (unode->nodemap[n]) {
+ return false;
+ }
+
+ unode->nodemap[n] = 1;
+ sculpt_undo_bmesh_push(ob, node, type);
+
+ if (extraType >= 0) {
+ sculpt_undo_bmesh_push(ob, node, extraType);
+ }
+
+ return true;
+}
+
SculptUndoNode *SCULPT_undo_push_node(Object *ob, PBVHNode *node, SculptUndoType type)
{
SculptSession *ss = ob->sculpt;
@@ -1270,7 +1396,7 @@ SculptUndoNode *SCULPT_undo_push_node(Object *ob, PBVHNode *node, SculptUndoType
BLI_thread_unlock(LOCK_CUSTOM1);
return unode;
}
- if ((unode = SCULPT_undo_get_node(node))) {
+ if ((unode = SCULPT_undo_get_node(node, type))) {
BLI_thread_unlock(LOCK_CUSTOM1);
return unode;
}
@@ -1292,7 +1418,11 @@ SculptUndoNode *SCULPT_undo_push_node(Object *ob, PBVHNode *node, SculptUndoType
int allvert;
BKE_pbvh_node_num_verts(ss->pbvh, node, NULL, &allvert);
BKE_pbvh_node_get_verts(ss->pbvh, node, &vert_indices, NULL);
- memcpy(unode->index, vert_indices, sizeof(int) * unode->totvert);
+
+ for (int i=0; i<unode->totvert; i++) {
+ unode->index[i].i = vert_indices[i];
+ }
+ //memcpy(unode->index, vert_indices, sizeof(int) * unode->totvert);
}
switch (type) {
@@ -1329,6 +1459,8 @@ SculptUndoNode *SCULPT_undo_push_node(Object *ob, PBVHNode *node, SculptUndoType
unode->shapeName[0] = '\0';
}
+ sculpt_undo_print_nodes(NULL);
+
BLI_thread_unlock(LOCK_CUSTOM1);
return unode;
@@ -1389,6 +1521,7 @@ typedef struct SculptUndoStep {
UndoStep step;
/* Note: will split out into list for multi-object-sculpt-mode. */
UndoSculpt data;
+ int id;
} SculptUndoStep;
static void sculpt_undosys_step_encode_init(struct bContext *UNUSED(C), UndoStep *us_p)
@@ -1427,6 +1560,8 @@ static void sculpt_undosys_step_decode_undo_impl(struct bContext *C,
BLI_assert(us->step.is_applied == true);
sculpt_undo_restore_list(C, depsgraph, &us->data.nodes);
us->step.is_applied = false;
+
+ sculpt_undo_print_nodes(us);
}
static void sculpt_undosys_step_decode_redo_impl(struct bContext *C,
@@ -1436,6 +1571,8 @@ static void sculpt_undosys_step_decode_redo_impl(struct bContext *C,
BLI_assert(us->step.is_applied == false);
sculpt_undo_restore_list(C, depsgraph, &us->data.nodes);
us->step.is_applied = true;
+
+ sculpt_undo_print_nodes(us);
}
static void sculpt_undosys_step_decode_undo(struct bContext *C,
@@ -1669,3 +1806,76 @@ void ED_sculpt_undo_push_multires_mesh_end(bContext *C, const char *str)
}
/** \} */
+
+#ifdef _
+# undef _
+#endif
+#define _(type) \
+ case type: \
+ return #type;
+static char *undo_type_to_str(int type)
+{
+ switch (type) {
+ _(SCULPT_UNDO_DYNTOPO_BEGIN)
+ _(SCULPT_UNDO_DYNTOPO_END)
+ _(SCULPT_UNDO_COORDS)
+ _(SCULPT_UNDO_GEOMETRY)
+ _(SCULPT_UNDO_DYNTOPO_SYMMETRIZE)
+ _(SCULPT_UNDO_FACE_SETS)
+ _(SCULPT_UNDO_HIDDEN)
+ _(SCULPT_UNDO_MASK)
+ _(SCULPT_UNDO_COLOR)
+ default:
+ return "unknown node type";
+ }
+}
+#undef _
+
+static int nodeidgen = 1;
+
+void sculpt_undo_print_nodes(void *active)
+{
+#if 0
+ UndoStack *ustack = ED_undo_stack_get();
+ UndoStep *us = ustack->steps.first;
+ if (active == NULL) {
+ active = ustack->step_active;
+ }
+
+ SculptUndoNode *node;
+
+ if (!us) {
+ return;
+ }
+
+ printf("\n");
+ int i = 0;
+ for (; us; us = us->next, i++) {
+ int id = -1;
+
+ if (us->type == BKE_UNDOSYS_TYPE_SCULPT) {
+ SculptUndoStep *su = (SculptUndoStep *)us;
+ if (!su->id) {
+ su->id = nodeidgen++;
+ }
+
+ id = su->id;
+ }
+
+ printf("%d %s %d %s\n", id, us == active ? "->" : " ", i, us->name);
+
+ if (us->type == BKE_UNDOSYS_TYPE_SCULPT) {
+ UndoSculpt *usculpt = sculpt_undosys_step_get_nodes(us);
+
+ for (node = usculpt->nodes.first; node; node = node->next) {
+ printf(" %s:%s {applied=%d bm_entry=%p node=%p}\n",
+ undo_type_to_str(node->type),
+ node->idname,
+ node->applied,
+ node->bm_entry,
+ node->node);
+ }
+ }
+ }
+#endif
+}
diff --git a/source/blender/editors/uvedit/uvedit_unwrap_ops.c b/source/blender/editors/uvedit/uvedit_unwrap_ops.c
index 108eca209b9..59ec8039d55 100644
--- a/source/blender/editors/uvedit/uvedit_unwrap_ops.c
+++ b/source/blender/editors/uvedit/uvedit_unwrap_ops.c
@@ -2859,7 +2859,8 @@ void ED_uvedit_add_simple_uvs(Main *bmain, const Scene *scene, Object *ob)
ED_mesh_uv_texture_ensure(me, NULL);
- BM_mesh_bm_from_me(bm,
+ BM_mesh_bm_from_me(NULL,
+ bm,
me,
(&(struct BMeshFromMeshParams){
.calc_face_normal = true,
@@ -2870,7 +2871,7 @@ void ED_uvedit_add_simple_uvs(Main *bmain, const Scene *scene, Object *ob)
/* set the margin really quickly before the packing operation*/
scene->toolsettings->uvcalc_margin = 0.001f;
uvedit_pack_islands(scene, ob, bm);
- BM_mesh_bm_to_me(bmain, bm, me, (&(struct BMeshToMeshParams){0}));
+ BM_mesh_bm_to_me(bmain, NULL, bm, me, (&(struct BMeshToMeshParams){0}));
BM_mesh_free(bm);
if (sync_selection) {