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/sculpt_paint')
-rw-r--r--source/blender/editors/sculpt_paint/CMakeLists.txt2
-rw-r--r--source/blender/editors/sculpt_paint/curves_sculpt_add.cc10
-rw-r--r--source/blender/editors/sculpt_paint/curves_sculpt_brush.cc45
-rw-r--r--source/blender/editors/sculpt_paint/curves_sculpt_density.cc18
-rw-r--r--source/blender/editors/sculpt_paint/curves_sculpt_grow_shrink.cc6
-rw-r--r--source/blender/editors/sculpt_paint/curves_sculpt_intern.hh18
-rw-r--r--source/blender/editors/sculpt_paint/curves_sculpt_ops.cc33
-rw-r--r--source/blender/editors/sculpt_paint/curves_sculpt_puff.cc3
-rw-r--r--source/blender/editors/sculpt_paint/curves_sculpt_slide.cc14
-rw-r--r--source/blender/editors/sculpt_paint/curves_sculpt_snake_hook.cc10
-rw-r--r--source/blender/editors/sculpt_paint/paint_canvas.cc1
-rw-r--r--source/blender/editors/sculpt_paint/paint_cursor.c52
-rw-r--r--source/blender/editors/sculpt_paint/paint_curve.c5
-rw-r--r--source/blender/editors/sculpt_paint/paint_curve_undo.c7
-rw-r--r--source/blender/editors/sculpt_paint/paint_hide.c3
-rw-r--r--source/blender/editors/sculpt_paint/paint_image.cc30
-rw-r--r--source/blender/editors/sculpt_paint/paint_image_2d.c12
-rw-r--r--source/blender/editors/sculpt_paint/paint_image_2d_curve_mask.cc19
-rw-r--r--source/blender/editors/sculpt_paint/paint_image_ops_paint.cc25
-rw-r--r--source/blender/editors/sculpt_paint/paint_image_proj.c56
-rw-r--r--source/blender/editors/sculpt_paint/paint_intern.h2
-rw-r--r--source/blender/editors/sculpt_paint/paint_mask.c42
-rw-r--r--source/blender/editors/sculpt_paint/paint_stroke.c26
-rw-r--r--source/blender/editors/sculpt_paint/paint_utils.c9
-rw-r--r--source/blender/editors/sculpt_paint/paint_vertex.cc171
-rw-r--r--source/blender/editors/sculpt_paint/paint_vertex_color_ops.cc37
-rw-r--r--source/blender/editors/sculpt_paint/paint_vertex_proj.c1
-rw-r--r--source/blender/editors/sculpt_paint/paint_vertex_weight_ops.c11
-rw-r--r--source/blender/editors/sculpt_paint/paint_vertex_weight_utils.c4
-rw-r--r--source/blender/editors/sculpt_paint/sculpt.c636
-rw-r--r--source/blender/editors/sculpt_paint/sculpt_automasking.cc673
-rw-r--r--source/blender/editors/sculpt_paint/sculpt_boundary.c44
-rw-r--r--source/blender/editors/sculpt_paint/sculpt_brush_types.c302
-rw-r--r--source/blender/editors/sculpt_paint/sculpt_cloth.c101
-rw-r--r--source/blender/editors/sculpt_paint/sculpt_detail.c15
-rw-r--r--source/blender/editors/sculpt_paint/sculpt_dyntopo.c68
-rw-r--r--source/blender/editors/sculpt_paint/sculpt_expand.c33
-rw-r--r--source/blender/editors/sculpt_paint/sculpt_face_set.cc (renamed from source/blender/editors/sculpt_paint/sculpt_face_set.c)657
-rw-r--r--source/blender/editors/sculpt_paint/sculpt_filter_color.c37
-rw-r--r--source/blender/editors/sculpt_paint/sculpt_filter_mask.c187
-rw-r--r--source/blender/editors/sculpt_paint/sculpt_filter_mesh.c138
-rw-r--r--source/blender/editors/sculpt_paint/sculpt_geodesic.c30
-rw-r--r--source/blender/editors/sculpt_paint/sculpt_intern.h94
-rw-r--r--source/blender/editors/sculpt_paint/sculpt_mask_expand.c23
-rw-r--r--source/blender/editors/sculpt_paint/sculpt_mask_init.c14
-rw-r--r--source/blender/editors/sculpt_paint/sculpt_multiplane_scrape.c34
-rw-r--r--source/blender/editors/sculpt_paint/sculpt_ops.c439
-rw-r--r--source/blender/editors/sculpt_paint/sculpt_paint_color.c58
-rw-r--r--source/blender/editors/sculpt_paint/sculpt_paint_image.cc29
-rw-r--r--source/blender/editors/sculpt_paint/sculpt_pose.c14
-rw-r--r--source/blender/editors/sculpt_paint/sculpt_smooth.c58
-rw-r--r--source/blender/editors/sculpt_paint/sculpt_transform.c17
-rw-r--r--source/blender/editors/sculpt_paint/sculpt_undo.c171
53 files changed, 2897 insertions, 1647 deletions
diff --git a/source/blender/editors/sculpt_paint/CMakeLists.txt b/source/blender/editors/sculpt_paint/CMakeLists.txt
index f4d3002219d..2709ac3fd91 100644
--- a/source/blender/editors/sculpt_paint/CMakeLists.txt
+++ b/source/blender/editors/sculpt_paint/CMakeLists.txt
@@ -68,7 +68,7 @@ set(SRC
sculpt_detail.c
sculpt_dyntopo.c
sculpt_expand.c
- sculpt_face_set.c
+ sculpt_face_set.cc
sculpt_filter_color.c
sculpt_filter_mask.c
sculpt_filter_mesh.c
diff --git a/source/blender/editors/sculpt_paint/curves_sculpt_add.cc b/source/blender/editors/sculpt_paint/curves_sculpt_add.cc
index b5d739ae08e..0d2c2d3f0c9 100644
--- a/source/blender/editors/sculpt_paint/curves_sculpt_add.cc
+++ b/source/blender/editors/sculpt_paint/curves_sculpt_add.cc
@@ -144,8 +144,7 @@ struct AddOperationExecutor {
}
surface_verts_eval_ = surface_eval_->verts();
surface_loops_eval_ = surface_eval_->loops();
- surface_looptris_eval_ = {BKE_mesh_runtime_looptri_ensure(surface_eval_),
- BKE_mesh_runtime_looptri_len(surface_eval_)};
+ surface_looptris_eval_ = surface_eval_->looptris();
BKE_bvhtree_from_mesh_get(&surface_bvh_eval_, surface_eval_, BVHTREE_FROM_LOOPTRI, 2);
BLI_SCOPED_DEFER([&]() { free_bvhtree_from_mesh(&surface_bvh_eval_); });
@@ -206,8 +205,7 @@ struct AddOperationExecutor {
return;
}
- const Span<MLoopTri> surface_looptris_orig = {BKE_mesh_runtime_looptri_ensure(&surface_orig),
- BKE_mesh_runtime_looptri_len(&surface_orig)};
+ const Span<MLoopTri> surface_looptris_orig = surface_orig.looptris();
/* Find normals. */
if (!CustomData_has_layer(&surface_orig.ldata, CD_NORMAL)) {
@@ -420,7 +418,7 @@ struct AddOperationExecutor {
*surface_bvh_eval_.tree,
brush_pos_su,
brush_radius_su,
- [&](const int index, const float3 &UNUSED(co), const float UNUSED(dist_sq)) {
+ [&](const int index, const float3 & /*co*/, const float /*dist_sq*/) {
const MLoopTri &looptri = surface_looptris_eval_[index];
const float3 v0_su = surface_verts_eval_[surface_loops_eval_[looptri.tri[0]].v].co;
const float3 v1_su = surface_verts_eval_[surface_loops_eval_[looptri.tri[1]].v].co;
@@ -438,7 +436,7 @@ struct AddOperationExecutor {
*surface_bvh_eval_.tree,
brush_pos_su,
brush_radius_su,
- [&](const int index, const float3 &UNUSED(co), const float UNUSED(dist_sq)) {
+ [&](const int index, const float3 & /*co*/, const float /*dist_sq*/) {
selected_looptri_indices.append(index);
});
}
diff --git a/source/blender/editors/sculpt_paint/curves_sculpt_brush.cc b/source/blender/editors/sculpt_paint/curves_sculpt_brush.cc
index 95261f29914..8172eb8a5d7 100644
--- a/source/blender/editors/sculpt_paint/curves_sculpt_brush.cc
+++ b/source/blender/editors/sculpt_paint/curves_sculpt_brush.cc
@@ -8,7 +8,6 @@
#include "BKE_bvhutils.h"
#include "BKE_context.h"
#include "BKE_curves.hh"
-#include "BKE_modifier.h"
#include "BKE_object.h"
#include "BKE_report.h"
@@ -16,10 +15,6 @@
#include "UI_interface.h"
-#include "DNA_mesh_types.h"
-#include "DNA_meshdata_types.h"
-
-#include "BLI_enumerable_thread_specific.hh"
#include "BLI_length_parameterize.hh"
#include "BLI_task.hh"
@@ -59,7 +54,7 @@ static std::optional<float3> find_curves_brush_position(const CurvesGeometry &cu
const Span<float3> positions)
{
/* This value might have to be adjusted based on user feedback. */
- const float brush_inner_radius_re = std::min<float>(brush_radius_re, (float)UI_UNIT_X / 3.0f);
+ const float brush_inner_radius_re = std::min<float>(brush_radius_re, float(UI_UNIT_X) / 3.0f);
const float brush_inner_radius_sq_re = pow2f(brush_inner_radius_re);
float4x4 projection;
@@ -190,7 +185,7 @@ std::optional<CurvesBrush3D> sample_curves_3d_brush(const Depsgraph &depsgraph,
/* Shorten ray when the surface object is hit. */
if (surface_object_eval != nullptr) {
- const float4x4 surface_to_world_mat = surface_object->obmat;
+ const float4x4 surface_to_world_mat = surface_object->object_to_world;
const float4x4 world_to_surface_mat = surface_to_world_mat.inverted();
Mesh *surface_eval = BKE_object_get_evaluated_mesh(surface_object_eval);
@@ -223,7 +218,7 @@ std::optional<CurvesBrush3D> sample_curves_3d_brush(const Depsgraph &depsgraph,
}
}
- const float4x4 curves_to_world_mat = curves_object.obmat;
+ const float4x4 curves_to_world_mat = curves_object.object_to_world;
const float4x4 world_to_curves_mat = curves_to_world_mat.inverted();
const float3 center_ray_start_cu = world_to_curves_mat * center_ray_start_wo;
@@ -352,33 +347,37 @@ float transform_brush_radius(const float4x4 &transform,
return math::distance(new_position, new_offset_position);
}
-void move_last_point_and_resample(MutableSpan<float3> positions, const float3 &new_last_position)
+void move_last_point_and_resample(MoveAndResampleBuffers &buffer,
+ MutableSpan<float3> positions,
+ const float3 &new_last_position)
{
/* Find the accumulated length of each point in the original curve,
* treating it as a poly curve for performance reasons and simplicity. */
- Array<float> orig_lengths(length_parameterize::segments_num(positions.size(), false));
- length_parameterize::accumulate_lengths<float3>(positions, false, orig_lengths);
- const float orig_total_length = orig_lengths.last();
+ buffer.orig_lengths.reinitialize(length_parameterize::segments_num(positions.size(), false));
+ length_parameterize::accumulate_lengths<float3>(positions, false, buffer.orig_lengths);
+ const float orig_total_length = buffer.orig_lengths.last();
/* Find the factor by which the new curve is shorter or longer than the original. */
const float new_last_segment_length = math::distance(positions.last(1), new_last_position);
- const float new_total_length = orig_lengths.last(1) + new_last_segment_length;
+ const float new_total_length = buffer.orig_lengths.last(1) + new_last_segment_length;
const float length_factor = safe_divide(new_total_length, orig_total_length);
/* Calculate the lengths to sample the original curve with by scaling the original lengths. */
- Array<float> new_lengths(positions.size() - 1);
- new_lengths.first() = 0.0f;
- for (const int i : new_lengths.index_range().drop_front(1)) {
- new_lengths[i] = orig_lengths[i - 1] * length_factor;
+ buffer.new_lengths.reinitialize(positions.size() - 1);
+ buffer.new_lengths.first() = 0.0f;
+ for (const int i : buffer.new_lengths.index_range().drop_front(1)) {
+ buffer.new_lengths[i] = buffer.orig_lengths[i - 1] * length_factor;
}
- Array<int> indices(positions.size() - 1);
- Array<float> factors(positions.size() - 1);
- length_parameterize::sample_at_lengths(orig_lengths, new_lengths, indices, factors);
+ buffer.sample_indices.reinitialize(positions.size() - 1);
+ buffer.sample_factors.reinitialize(positions.size() - 1);
+ length_parameterize::sample_at_lengths(
+ buffer.orig_lengths, buffer.new_lengths, buffer.sample_indices, buffer.sample_factors);
- Array<float3> new_positions(positions.size() - 1);
- length_parameterize::interpolate<float3>(positions, indices, factors, new_positions);
- positions.drop_back(1).copy_from(new_positions);
+ buffer.new_positions.reinitialize(positions.size() - 1);
+ length_parameterize::interpolate<float3>(
+ positions, buffer.sample_indices, buffer.sample_factors, buffer.new_positions);
+ positions.drop_back(1).copy_from(buffer.new_positions);
positions.last() = new_last_position;
}
diff --git a/source/blender/editors/sculpt_paint/curves_sculpt_density.cc b/source/blender/editors/sculpt_paint/curves_sculpt_density.cc
index a37eb4bb560..78e2d55e6b9 100644
--- a/source/blender/editors/sculpt_paint/curves_sculpt_density.cc
+++ b/source/blender/editors/sculpt_paint/curves_sculpt_density.cc
@@ -132,8 +132,7 @@ struct DensityAddOperationExecutor {
BKE_bvhtree_from_mesh_get(&surface_bvh_eval_, surface_eval_, BVHTREE_FROM_LOOPTRI, 2);
BLI_SCOPED_DEFER([&]() { free_bvhtree_from_mesh(&surface_bvh_eval_); });
- surface_looptris_eval_ = {BKE_mesh_runtime_looptri_ensure(surface_eval_),
- BKE_mesh_runtime_looptri_len(surface_eval_)};
+ surface_looptris_eval_ = surface_eval_->looptris();
/* Find UV map. */
VArraySpan<float2> surface_uv_map;
if (curves_id_orig_->surface_uv_map != nullptr) {
@@ -235,7 +234,7 @@ struct DensityAddOperationExecutor {
new_roots_kdtree,
root_pos_cu,
brush_settings_->minimum_distance,
- [&](const int other_new_i, const float *UNUSED(co), float UNUSED(dist_sq)) {
+ [&](const int other_new_i, const float * /*co*/, float /*dist_sq*/) {
if (other_new_i == -1) {
new_curve_skipped[new_i] = true;
return false;
@@ -265,8 +264,7 @@ struct DensityAddOperationExecutor {
reinterpret_cast<const float3 *>(CustomData_get_layer(&surface_orig_->ldata, CD_NORMAL)),
surface_orig_->totloop};
- const Span<MLoopTri> surface_looptris_orig = {BKE_mesh_runtime_looptri_ensure(surface_orig_),
- BKE_mesh_runtime_looptri_len(surface_orig_)};
+ const Span<MLoopTri> surface_looptris_orig = surface_orig_->looptris();
const geometry::ReverseUVSampler reverse_uv_sampler{surface_uv_map, surface_looptris_orig};
geometry::AddCurvesOnMeshInputs add_inputs;
@@ -417,7 +415,7 @@ struct DensityAddOperationExecutor {
*surface_bvh_eval_.tree,
brush_pos_su,
brush_radius_su,
- [&](const int index, const float3 &UNUSED(co), const float UNUSED(dist_sq)) {
+ [&](const int index, const float3 & /*co*/, const float /*dist_sq*/) {
selected_looptri_indices.append(index);
});
@@ -644,7 +642,7 @@ struct DensitySubtractOperationExecutor {
* strength. */
Array<bool> allow_remove_curve(curves_->curves_num(), false);
threading::parallel_for(curves_->curves_range(), 512, [&](const IndexRange range) {
- RandomNumberGenerator rng((int)(PIL_check_seconds_timer() * 1000000.0));
+ RandomNumberGenerator rng(int(PIL_check_seconds_timer() * 1000000.0));
for (const int curve_i : range) {
if (curves_to_delete[curve_i]) {
@@ -689,7 +687,7 @@ struct DensitySubtractOperationExecutor {
root_points_kdtree_,
orig_pos_cu,
minimum_distance_,
- [&](const int other_curve_i, const float *UNUSED(co), float UNUSED(dist_sq)) {
+ [&](const int other_curve_i, const float * /*co*/, float /*dist_sq*/) {
if (other_curve_i == curve_i) {
return true;
}
@@ -733,7 +731,7 @@ struct DensitySubtractOperationExecutor {
* strength. */
Array<bool> allow_remove_curve(curves_->curves_num(), false);
threading::parallel_for(curves_->curves_range(), 512, [&](const IndexRange range) {
- RandomNumberGenerator rng((int)(PIL_check_seconds_timer() * 1000000.0));
+ RandomNumberGenerator rng(int(PIL_check_seconds_timer() * 1000000.0));
for (const int curve_i : range) {
if (curves_to_delete[curve_i]) {
@@ -774,7 +772,7 @@ struct DensitySubtractOperationExecutor {
root_points_kdtree_,
pos_cu,
minimum_distance_,
- [&](const int other_curve_i, const float *UNUSED(co), float UNUSED(dist_sq)) {
+ [&](const int other_curve_i, const float * /*co*/, float /*dist_sq*/) {
if (other_curve_i == curve_i) {
return true;
}
diff --git a/source/blender/editors/sculpt_paint/curves_sculpt_grow_shrink.cc b/source/blender/editors/sculpt_paint/curves_sculpt_grow_shrink.cc
index 0ca22004540..2624d70ccf7 100644
--- a/source/blender/editors/sculpt_paint/curves_sculpt_grow_shrink.cc
+++ b/source/blender/editors/sculpt_paint/curves_sculpt_grow_shrink.cc
@@ -7,8 +7,6 @@
#include "BLI_length_parameterize.hh"
#include "BLI_vector.hh"
-#include "PIL_time.h"
-
#include "DEG_depsgraph.h"
#include "BKE_attribute_math.hh"
@@ -141,11 +139,11 @@ class ExtrapolateCurvesEffect : public CurvesEffect {
{
MutableSpan<float3> positions_cu = curves.positions_for_write();
threading::parallel_for(curve_indices.index_range(), 256, [&](const IndexRange range) {
+ MoveAndResampleBuffers resample_buffer;
for (const int influence_i : range) {
const int curve_i = curve_indices[influence_i];
const float move_distance_cu = move_distances_cu[influence_i];
const IndexRange points = curves.points_for_curve(curve_i);
-
if (points.size() <= 1) {
continue;
}
@@ -157,7 +155,7 @@ class ExtrapolateCurvesEffect : public CurvesEffect {
const float3 direction = math::normalize(old_last_pos_cu - direction_reference_point);
const float3 new_last_pos_cu = old_last_pos_cu + direction * move_distance_cu;
- move_last_point_and_resample(positions_cu.slice(points), new_last_pos_cu);
+ move_last_point_and_resample(resample_buffer, positions_cu.slice(points), new_last_pos_cu);
}
});
}
diff --git a/source/blender/editors/sculpt_paint/curves_sculpt_intern.hh b/source/blender/editors/sculpt_paint/curves_sculpt_intern.hh
index 5c8c0cedc6f..61e2559f303 100644
--- a/source/blender/editors/sculpt_paint/curves_sculpt_intern.hh
+++ b/source/blender/editors/sculpt_paint/curves_sculpt_intern.hh
@@ -102,7 +102,23 @@ VArray<float> get_curves_selection(const Curves &curves_id);
*/
VArray<float> get_point_selection(const Curves &curves_id);
-void move_last_point_and_resample(MutableSpan<float3> positions, const float3 &new_last_position);
+/** See #move_last_point_and_resample. */
+struct MoveAndResampleBuffers {
+ Array<float> orig_lengths;
+ Array<float> new_lengths;
+
+ Array<int> sample_indices;
+ Array<float> sample_factors;
+
+ Array<float3> new_positions;
+};
+
+/**
+ * \param buffer: Reused memory to avoid reallocations when the function is called many times.
+ */
+void move_last_point_and_resample(MoveAndResampleBuffers &buffer,
+ MutableSpan<float3> positions,
+ const float3 &new_last_position);
class CurvesSculptCommonContext {
public:
diff --git a/source/blender/editors/sculpt_paint/curves_sculpt_ops.cc b/source/blender/editors/sculpt_paint/curves_sculpt_ops.cc
index 6e1ac24e21b..df7dd871a94 100644
--- a/source/blender/editors/sculpt_paint/curves_sculpt_ops.cc
+++ b/source/blender/editors/sculpt_paint/curves_sculpt_ops.cc
@@ -153,7 +153,7 @@ struct SculptCurvesBrushStrokeData {
static bool stroke_get_location(bContext *C,
float out[3],
const float mouse[2],
- bool UNUSED(force_original))
+ bool /*force_original*/)
{
out[0] = mouse[0];
out[1] = mouse[1];
@@ -170,7 +170,7 @@ static bool stroke_test_start(bContext *C, struct wmOperator *op, const float mo
static void stroke_update_step(bContext *C,
wmOperator *op,
- PaintStroke *UNUSED(stroke),
+ PaintStroke * /*stroke*/,
PointerRNA *stroke_element)
{
SculptCurvesBrushStrokeData *op_data = static_cast<SculptCurvesBrushStrokeData *>(
@@ -220,8 +220,10 @@ static int sculpt_curves_stroke_invoke(bContext *C, wmOperator *op, const wmEven
int return_value = op->type->modal(C, op, event);
if (return_value == OPERATOR_FINISHED) {
- paint_stroke_free(C, op, op_data->stroke);
- MEM_delete(op_data);
+ if (op->customdata != nullptr) {
+ paint_stroke_free(C, op, op_data->stroke);
+ MEM_delete(op_data);
+ }
return OPERATOR_FINISHED;
}
@@ -236,16 +238,19 @@ static int sculpt_curves_stroke_modal(bContext *C, wmOperator *op, const wmEvent
int return_value = paint_stroke_modal(C, op, event, &op_data->stroke);
if (ELEM(return_value, OPERATOR_FINISHED, OPERATOR_CANCELLED)) {
MEM_delete(op_data);
+ op->customdata = nullptr;
}
return return_value;
}
static void sculpt_curves_stroke_cancel(bContext *C, wmOperator *op)
{
- SculptCurvesBrushStrokeData *op_data = static_cast<SculptCurvesBrushStrokeData *>(
- op->customdata);
- paint_stroke_cancel(C, op, op_data->stroke);
- MEM_delete(op_data);
+ if (op->customdata != nullptr) {
+ SculptCurvesBrushStrokeData *op_data = static_cast<SculptCurvesBrushStrokeData *>(
+ op->customdata);
+ paint_stroke_cancel(C, op, op_data->stroke);
+ MEM_delete(op_data);
+ }
}
static void SCULPT_CURVES_OT_brush_stroke(struct wmOperatorType *ot)
@@ -344,7 +349,7 @@ static int select_random_exec(bContext *C, wmOperator *op)
VectorSet<Curves *> unique_curves = curves::get_unique_editable_curves(*C);
const int seed = RNA_int_get(op->ptr, "seed");
- RandomNumberGenerator rng{static_cast<uint32_t>(seed)};
+ RandomNumberGenerator rng{uint32_t(seed)};
const bool partial = RNA_boolean_get(op->ptr, "partial");
const bool constant_per_curve = RNA_boolean_get(op->ptr, "constant_per_curve");
@@ -448,7 +453,7 @@ static int select_random_exec(bContext *C, wmOperator *op)
return OPERATOR_FINISHED;
}
-static void select_random_ui(bContext *UNUSED(C), wmOperator *op)
+static void select_random_ui(bContext * /*C*/, wmOperator *op)
{
uiLayout *layout = op->layout;
@@ -786,7 +791,7 @@ static void select_grow_invoke_per_curve(Curves &curves_id,
});
});
- float4x4 curves_to_world_mat = curves_ob.obmat;
+ float4x4 curves_to_world_mat = curves_ob.object_to_world;
float4x4 world_to_curves_mat = curves_to_world_mat.inverted();
float4x4 projection;
@@ -914,7 +919,7 @@ static void SCULPT_CURVES_OT_select_grow(wmOperatorType *ot)
"Distance",
"By how much to grow the selection",
-10.0f,
- 10.f);
+ 10.0f);
RNA_def_property_subtype(prop, PROP_DISTANCE);
}
@@ -1003,7 +1008,7 @@ static int calculate_points_per_side(bContext *C, MinDistanceEditData &op_data)
return std::min(300, needed_points);
}
-static void min_distance_edit_draw(bContext *C, int UNUSED(x), int UNUSED(y), void *customdata)
+static void min_distance_edit_draw(bContext *C, int /*x*/, int /*y*/, void *customdata)
{
Scene *scene = CTX_data_scene(C);
MinDistanceEditData &op_data = *static_cast<MinDistanceEditData *>(customdata);
@@ -1093,7 +1098,7 @@ static void min_distance_edit_draw(bContext *C, int UNUSED(x), int UNUSED(y), vo
GPU_scissor(scissor[0], scissor[1], scissor[2], scissor[3]);
/* Draw the brush circle. */
- GPU_matrix_translate_2f((float)op_data.initial_mouse.x, (float)op_data.initial_mouse.y);
+ GPU_matrix_translate_2f(float(op_data.initial_mouse.x), float(op_data.initial_mouse.y));
GPUVertFormat *format = immVertexFormat();
uint pos2d = GPU_vertformat_attr_add(format, "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
diff --git a/source/blender/editors/sculpt_paint/curves_sculpt_puff.cc b/source/blender/editors/sculpt_paint/curves_sculpt_puff.cc
index ec69aae372c..b4e949106e7 100644
--- a/source/blender/editors/sculpt_paint/curves_sculpt_puff.cc
+++ b/source/blender/editors/sculpt_paint/curves_sculpt_puff.cc
@@ -121,8 +121,7 @@ struct PuffOperationExecutor {
surface_verts_ = surface_->verts();
surface_loops_ = surface_->loops();
- surface_looptris_ = {BKE_mesh_runtime_looptri_ensure(surface_),
- BKE_mesh_runtime_looptri_len(surface_)};
+ surface_looptris_ = surface_->looptris();
BKE_bvhtree_from_mesh_get(&surface_bvh_, surface_, BVHTREE_FROM_LOOPTRI, 2);
BLI_SCOPED_DEFER([&]() { free_bvhtree_from_mesh(&surface_bvh_); });
diff --git a/source/blender/editors/sculpt_paint/curves_sculpt_slide.cc b/source/blender/editors/sculpt_paint/curves_sculpt_slide.cc
index 1108f5c72a9..ae89bc1c58b 100644
--- a/source/blender/editors/sculpt_paint/curves_sculpt_slide.cc
+++ b/source/blender/editors/sculpt_paint/curves_sculpt_slide.cc
@@ -8,8 +8,6 @@
#include "BLI_float4x4.hh"
#include "BLI_vector.hh"
-#include "PIL_time.h"
-
#include "DEG_depsgraph.h"
#include "BKE_attribute_math.hh"
@@ -17,17 +15,13 @@
#include "BKE_bvhutils.h"
#include "BKE_context.h"
#include "BKE_curves.hh"
-#include "BKE_geometry_set.hh"
#include "BKE_mesh.h"
-#include "BKE_mesh_runtime.h"
#include "BKE_mesh_sample.hh"
-#include "BKE_modifier.h"
#include "BKE_object.h"
#include "BKE_paint.h"
#include "BKE_report.h"
#include "DNA_brush_enums.h"
-#include "DNA_brush_types.h"
#include "DNA_curves_types.h"
#include "DNA_mesh_types.h"
#include "DNA_meshdata_types.h"
@@ -37,8 +31,6 @@
#include "ED_screen.h"
#include "ED_view3d.h"
-#include "UI_interface.h"
-
#include "WM_api.h"
#include "DEG_depsgraph_query.h"
@@ -178,8 +170,7 @@ struct SlideOperationExecutor {
report_empty_original_surface(stroke_extension.reports);
return;
}
- surface_looptris_orig_ = {BKE_mesh_runtime_looptri_ensure(surface_orig_),
- BKE_mesh_runtime_looptri_len(surface_orig_)};
+ surface_looptris_orig_ = surface_orig_->looptris();
surface_uv_map_orig_ = surface_orig_->attributes().lookup<float2>(uv_map_name,
ATTR_DOMAIN_CORNER);
if (surface_uv_map_orig_.is_empty()) {
@@ -205,8 +196,7 @@ struct SlideOperationExecutor {
report_empty_evaluated_surface(stroke_extension.reports);
return;
}
- surface_looptris_eval_ = {BKE_mesh_runtime_looptri_ensure(surface_eval_),
- BKE_mesh_runtime_looptri_len(surface_eval_)};
+ surface_looptris_eval_ = surface_eval_->looptris();
surface_verts_eval_ = surface_eval_->verts();
surface_loops_eval_ = surface_eval_->loops();
surface_uv_map_eval_ = surface_eval_->attributes().lookup<float2>(uv_map_name,
diff --git a/source/blender/editors/sculpt_paint/curves_sculpt_snake_hook.cc b/source/blender/editors/sculpt_paint/curves_sculpt_snake_hook.cc
index 54b81fa221d..67757ce5f4a 100644
--- a/source/blender/editors/sculpt_paint/curves_sculpt_snake_hook.cc
+++ b/source/blender/editors/sculpt_paint/curves_sculpt_snake_hook.cc
@@ -188,6 +188,7 @@ struct SnakeHookOperatorExecutor {
const float brush_radius_sq_re = pow2f(brush_radius_re);
threading::parallel_for(curves_->curves_range(), 256, [&](const IndexRange curves_range) {
+ MoveAndResampleBuffers resample_buffer;
for (const int curve_i : curves_range) {
const IndexRange points = curves_->points_for_curve(curve_i);
const int last_point_i = points.last();
@@ -221,8 +222,8 @@ struct SnakeHookOperatorExecutor {
const float3 translation_orig = deformation.translation_from_deformed_to_original(
last_point_i, translation_eval);
- move_last_point_and_resample(positions_cu.slice(points),
- positions_cu[last_point_i] + translation_orig);
+ const float3 last_point_cu = positions_cu[last_point_i] + translation_orig;
+ move_last_point_and_resample(resample_buffer, positions_cu.slice(points), last_point_cu);
}
});
}
@@ -268,6 +269,7 @@ struct SnakeHookOperatorExecutor {
const float brush_radius_sq_cu = pow2f(brush_radius_cu);
threading::parallel_for(curves_->curves_range(), 256, [&](const IndexRange curves_range) {
+ MoveAndResampleBuffers resample_buffer;
for (const int curve_i : curves_range) {
const IndexRange points = curves_->points_for_curve(curve_i);
const int last_point_i = points.last();
@@ -289,8 +291,8 @@ struct SnakeHookOperatorExecutor {
const float3 translation_orig = deformation.translation_from_deformed_to_original(
last_point_i, translation_eval);
- move_last_point_and_resample(positions_cu.slice(points),
- positions_cu[last_point_i] + translation_orig);
+ const float3 last_point_cu = positions_cu[last_point_i] + translation_orig;
+ move_last_point_and_resample(resample_buffer, positions_cu.slice(points), last_point_cu);
}
});
}
diff --git a/source/blender/editors/sculpt_paint/paint_canvas.cc b/source/blender/editors/sculpt_paint/paint_canvas.cc
index 9262cbebcac..22e1ecbedd7 100644
--- a/source/blender/editors/sculpt_paint/paint_canvas.cc
+++ b/source/blender/editors/sculpt_paint/paint_canvas.cc
@@ -1,4 +1,5 @@
/* SPDX-License-Identifier: GPL-2.0-or-later */
+
#include "BLI_compiler_compat.h"
#include "DNA_material_types.h"
diff --git a/source/blender/editors/sculpt_paint/paint_cursor.c b/source/blender/editors/sculpt_paint/paint_cursor.c
index 164e13ac3c9..b6e83187c86 100644
--- a/source/blender/editors/sculpt_paint/paint_cursor.c
+++ b/source/blender/editors/sculpt_paint/paint_cursor.c
@@ -27,7 +27,6 @@
#include "BKE_context.h"
#include "BKE_curve.h"
#include "BKE_image.h"
-#include "BKE_node.h"
#include "BKE_object.h"
#include "BKE_paint.h"
@@ -563,31 +562,36 @@ static bool paint_draw_tex_overlay(UnifiedPaintSettings *ups,
if (mtex->brush_map_mode == MTEX_MAP_MODE_VIEW) {
GPU_matrix_push();
+ float center[2] = {
+ ups->draw_anchored ? ups->anchored_initial_mouse[0] : x,
+ ups->draw_anchored ? ups->anchored_initial_mouse[1] : y,
+ };
+
/* Brush rotation. */
- GPU_matrix_translate_2f(x, y);
+ GPU_matrix_translate_2fv(center);
GPU_matrix_rotate_2d(-RAD2DEGF(primary ? ups->brush_rotation : ups->brush_rotation_sec));
- GPU_matrix_translate_2f(-x, -y);
+ GPU_matrix_translate_2f(-center[0], -center[1]);
/* Scale based on tablet pressure. */
if (primary && ups->stroke_active && BKE_brush_use_size_pressure(brush)) {
const float scale = ups->size_pressure_value;
- GPU_matrix_translate_2f(x, y);
+ GPU_matrix_translate_2fv(center);
GPU_matrix_scale_2f(scale, scale);
- GPU_matrix_translate_2f(-x, -y);
+ GPU_matrix_translate_2f(-center[0], -center[1]);
}
if (ups->draw_anchored) {
- quad.xmin = ups->anchored_initial_mouse[0] - ups->anchored_size;
- quad.ymin = ups->anchored_initial_mouse[1] - ups->anchored_size;
- quad.xmax = ups->anchored_initial_mouse[0] + ups->anchored_size;
- quad.ymax = ups->anchored_initial_mouse[1] + ups->anchored_size;
+ quad.xmin = center[0] - ups->anchored_size;
+ quad.ymin = center[1] - ups->anchored_size;
+ quad.xmax = center[0] + ups->anchored_size;
+ quad.ymax = center[1] + ups->anchored_size;
}
else {
const int radius = BKE_brush_size_get(vc->scene, brush) * zoom;
- quad.xmin = x - radius;
- quad.ymin = y - radius;
- quad.xmax = x + radius;
- quad.ymax = y + radius;
+ quad.xmin = center[0] - radius;
+ quad.ymin = center[1] - radius;
+ quad.xmax = center[0] + radius;
+ quad.ymax = center[1] + radius;
}
}
else if (mtex->brush_map_mode == MTEX_MAP_MODE_TILED) {
@@ -1072,7 +1076,7 @@ static void cursor_draw_tiling_preview(const uint gpuattr,
for (int dim = 0; dim < 3; dim++) {
location[dim] = cur[dim] * step[dim] + orgLoc[dim];
}
- cursor_draw_point_screen_space(gpuattr, region, location, ob->obmat, 3);
+ cursor_draw_point_screen_space(gpuattr, region, location, ob->object_to_world, 3);
}
}
}
@@ -1089,11 +1093,11 @@ static void cursor_draw_point_with_symmetry(const uint gpuattr,
float location[3], symm_rot_mat[4][4];
for (int i = 0; i <= symm; i++) {
- if (i == 0 || (symm & i && (symm != 5 || i != 3) && (symm != 6 || (!ELEM(i, 3, 5))))) {
+ if (i == 0 || (symm & i && (symm != 5 || i != 3) && (symm != 6 || !ELEM(i, 3, 5)))) {
/* Axis Symmetry. */
flip_v3_v3(location, true_location, (char)i);
- cursor_draw_point_screen_space(gpuattr, region, location, ob->obmat, 3);
+ cursor_draw_point_screen_space(gpuattr, region, location, ob->object_to_world, 3);
/* Tiling. */
cursor_draw_tiling_preview(gpuattr, region, location, sd, ob, radius);
@@ -1108,7 +1112,7 @@ static void cursor_draw_point_with_symmetry(const uint gpuattr,
mul_m4_v3(symm_rot_mat, location);
cursor_draw_tiling_preview(gpuattr, region, location, sd, ob, radius);
- cursor_draw_point_screen_space(gpuattr, region, location, ob->obmat, 3);
+ cursor_draw_point_screen_space(gpuattr, region, location, ob->object_to_world, 3);
}
}
}
@@ -1335,7 +1339,7 @@ static void paint_cursor_update_pixel_radius(PaintCursorContext *pcontext)
}
copy_v3_v3(pcontext->scene_space_location, pcontext->location);
- mul_m4_v3(pcontext->vc.obact->obmat, pcontext->scene_space_location);
+ mul_m4_v3(pcontext->vc.obact->object_to_world, pcontext->scene_space_location);
}
else {
Sculpt *sd = CTX_data_tool_settings(pcontext->C)->sculpt;
@@ -1465,7 +1469,7 @@ static void paint_cursor_drawing_setup_cursor_space(PaintCursorContext *pcontext
float cursor_trans[4][4], cursor_rot[4][4];
const float z_axis[4] = {0.0f, 0.0f, 1.0f, 0.0f};
float quat[4];
- copy_m4_m4(cursor_trans, pcontext->vc.obact->obmat);
+ copy_m4_m4(cursor_trans, pcontext->vc.obact->object_to_world);
translate_m4(cursor_trans, pcontext->location[0], pcontext->location[1], pcontext->location[2]);
rotation_between_vecs_to_quat(quat, z_axis, pcontext->normal);
quat_to_mat4(cursor_rot, quat);
@@ -1509,7 +1513,7 @@ static void paint_cursor_pose_brush_origins_draw(PaintCursorContext *pcontext)
cursor_draw_point_screen_space(pcontext->pos,
pcontext->region,
ss->pose_ik_chain_preview->segments[i].initial_orig,
- pcontext->vc.obact->obmat,
+ pcontext->vc.obact->object_to_world,
3);
}
}
@@ -1527,7 +1531,7 @@ static void paint_cursor_preview_boundary_data_pivot_draw(PaintCursorContext *pc
pcontext->pos,
pcontext->region,
SCULPT_vertex_co_get(pcontext->ss, pcontext->ss->boundary_preview->pivot_vertex),
- pcontext->vc.obact->obmat,
+ pcontext->vc.obact->object_to_world,
3);
}
@@ -1635,7 +1639,7 @@ static void paint_cursor_draw_3d_view_brush_cursor_inactive(PaintCursorContext *
pcontext->pos,
pcontext->region,
SCULPT_vertex_co_get(pcontext->ss, pcontext->ss->expand_cache->initial_active_vertex),
- pcontext->vc.obact->obmat,
+ pcontext->vc.obact->object_to_world,
2);
}
@@ -1657,7 +1661,7 @@ static void paint_cursor_draw_3d_view_brush_cursor_inactive(PaintCursorContext *
NULL);
GPU_matrix_push();
- GPU_matrix_mul(pcontext->vc.obact->obmat);
+ GPU_matrix_mul(pcontext->vc.obact->object_to_world);
/* Drawing Cursor overlays in 3D object space. */
if (is_brush_tool && brush->sculpt_tool == SCULPT_TOOL_GRAB &&
@@ -1748,7 +1752,7 @@ static void paint_cursor_cursor_draw_3d_view_brush_cursor_active(PaintCursorCont
NULL,
NULL);
GPU_matrix_push();
- GPU_matrix_mul(pcontext->vc.obact->obmat);
+ GPU_matrix_mul(pcontext->vc.obact->object_to_world);
/* Draw the special active cursors different tools may have. */
diff --git a/source/blender/editors/sculpt_paint/paint_curve.c b/source/blender/editors/sculpt_paint/paint_curve.c
index 22d6626ab16..26f76d46f85 100644
--- a/source/blender/editors/sculpt_paint/paint_curve.c
+++ b/source/blender/editors/sculpt_paint/paint_curve.c
@@ -44,7 +44,7 @@ bool paint_curve_poll(bContext *C)
RegionView3D *rv3d = CTX_wm_region_view3d(C);
SpaceImage *sima;
- if (rv3d && !(ob && ((ob->mode & OB_MODE_ALL_PAINT) != 0))) {
+ if (rv3d && !(ob && ((ob->mode & (OB_MODE_ALL_PAINT | OB_MODE_SCULPT_CURVES)) != 0))) {
return false;
}
@@ -676,6 +676,9 @@ static int paintcurve_draw_exec(bContext *C, wmOperator *UNUSED(op))
case PAINT_MODE_SCULPT:
name = "SCULPT_OT_brush_stroke";
break;
+ case PAINT_MODE_SCULPT_CURVES:
+ name = "SCULPT_CURVES_OT_brush_stroke";
+ break;
default:
return OPERATOR_PASS_THROUGH;
}
diff --git a/source/blender/editors/sculpt_paint/paint_curve_undo.c b/source/blender/editors/sculpt_paint/paint_curve_undo.c
index 2678ec6e115..a5daa13b762 100644
--- a/source/blender/editors/sculpt_paint/paint_curve_undo.c
+++ b/source/blender/editors/sculpt_paint/paint_curve_undo.c
@@ -9,9 +9,6 @@
#include "MEM_guardedalloc.h"
#include "DNA_brush_types.h"
-#include "DNA_space_types.h"
-
-#include "BLI_array_utils.h"
#include "BKE_context.h"
#include "BKE_paint.h"
@@ -24,6 +21,10 @@
#include "paint_intern.h"
+#ifndef NDEBUG
+# include "BLI_array_utils.h" /* #BLI_array_is_zeroed */
+#endif
+
/* -------------------------------------------------------------------- */
/** \name Undo Conversion
* \{ */
diff --git a/source/blender/editors/sculpt_paint/paint_hide.c b/source/blender/editors/sculpt_paint/paint_hide.c
index c1289364fb2..9e435ee0748 100644
--- a/source/blender/editors/sculpt_paint/paint_hide.c
+++ b/source/blender/editors/sculpt_paint/paint_hide.c
@@ -383,10 +383,9 @@ static int hide_show_exec(bContext *C, wmOperator *op)
* sculpt but it looks wrong when entering editmode otherwise). */
if (pbvh_type == PBVH_FACES) {
BKE_mesh_flush_hidden_from_verts(me);
+ BKE_pbvh_update_hide_attributes_from_mesh(pbvh);
}
- SCULPT_visibility_sync_all_vertex_to_face_sets(ob->sculpt);
-
DEG_id_tag_update(&ob->id, ID_RECALC_SHADING);
ED_region_tag_redraw(region);
diff --git a/source/blender/editors/sculpt_paint/paint_image.cc b/source/blender/editors/sculpt_paint/paint_image.cc
index c852fd25bc4..f334b2eb8f8 100644
--- a/source/blender/editors/sculpt_paint/paint_image.cc
+++ b/source/blender/editors/sculpt_paint/paint_image.cc
@@ -13,7 +13,6 @@
#include "MEM_guardedalloc.h"
-#include "BLI_blenlib.h"
#include "BLI_math.h"
#include "BLI_utildefines.h"
@@ -35,9 +34,7 @@
#include "BKE_main.h"
#include "BKE_material.h"
#include "BKE_mesh.h"
-#include "BKE_node.h"
#include "BKE_paint.h"
-#include "BKE_undo_system.h"
#include "NOD_texture.h"
@@ -50,7 +47,6 @@
#include "ED_object.h"
#include "ED_paint.h"
#include "ED_screen.h"
-#include "ED_view3d.h"
#include "WM_api.h"
#include "WM_message.h"
@@ -60,9 +56,6 @@
#include "RNA_access.h"
#include "RNA_define.h"
-#include "GPU_immediate.h"
-#include "GPU_state.h"
-
#include "IMB_colormanagement.h"
#include "paint_intern.h"
@@ -328,7 +321,7 @@ bool paint_use_opacity_masking(Brush *brush)
{
return ((brush->flag & BRUSH_AIRBRUSH) || (brush->flag & BRUSH_DRAG_DOT) ||
(brush->flag & BRUSH_ANCHORED) ||
- (ELEM(brush->imagepaint_tool, PAINT_TOOL_SMEAR, PAINT_TOOL_SOFTEN)) ||
+ ELEM(brush->imagepaint_tool, PAINT_TOOL_SMEAR, PAINT_TOOL_SOFTEN) ||
(brush->imagepaint_tool == PAINT_TOOL_FILL) ||
(brush->flag & BRUSH_USE_GRADIENT) ||
(brush->mtex.tex && !ELEM(brush->mtex.brush_map_mode,
@@ -546,7 +539,7 @@ static int grab_clone_modal(bContext *C, wmOperator *op, const wmEvent *event)
return OPERATOR_RUNNING_MODAL;
}
-static void grab_clone_cancel(bContext *UNUSED(C), wmOperator *op)
+static void grab_clone_cancel(bContext * /*C*/, wmOperator *op)
{
GrabClone *cmv = static_cast<GrabClone *>(op->customdata);
MEM_delete(cmv);
@@ -787,20 +780,7 @@ void ED_object_texture_paint_mode_enter_ex(Main *bmain, Scene *scene, Object *ob
}
if (ima) {
- wmWindowManager *wm = static_cast<wmWindowManager *>(bmain->wm.first);
- LISTBASE_FOREACH (wmWindow *, win, &wm->windows) {
- const bScreen *screen = WM_window_get_active_screen(win);
- LISTBASE_FOREACH (ScrArea *, area, &screen->areabase) {
- SpaceLink *sl = static_cast<SpaceLink *>(area->spacedata.first);
- if (sl->spacetype == SPACE_IMAGE) {
- SpaceImage *sima = (SpaceImage *)sl;
-
- if (!sima->pin) {
- ED_space_image_set(bmain, sima, ima, true);
- }
- }
- }
- }
+ ED_space_image_sync(bmain, ima, false);
}
ob->mode |= OB_MODE_TEXTURE_PAINT;
@@ -911,7 +891,7 @@ void PAINT_OT_texture_paint_toggle(wmOperatorType *ot)
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
-static int brush_colors_flip_exec(bContext *C, wmOperator *UNUSED(op))
+static int brush_colors_flip_exec(bContext *C, wmOperator * /*op*/)
{
Scene *scene = CTX_data_scene(C);
UnifiedPaintSettings *ups = &scene->toolsettings->unified_paint_settings;
@@ -980,7 +960,7 @@ void ED_imapaint_bucket_fill(struct bContext *C,
ED_image_undo_push_begin(op->type->name, PAINT_MODE_TEXTURE_2D);
- const float mouse_init[2] = {static_cast<float>(mouse[0]), static_cast<float>(mouse[1])};
+ const float mouse_init[2] = {float(mouse[0]), float(mouse[1])};
paint_2d_bucket_fill(C, color, nullptr, mouse_init, nullptr, nullptr);
ED_image_undo_push_end();
diff --git a/source/blender/editors/sculpt_paint/paint_image_2d.c b/source/blender/editors/sculpt_paint/paint_image_2d.c
index 5df65e596b9..b7ce4b2973c 100644
--- a/source/blender/editors/sculpt_paint/paint_image_2d.c
+++ b/source/blender/editors/sculpt_paint/paint_image_2d.c
@@ -150,7 +150,7 @@ static void brush_painter_2d_require_imbuf(
{
BrushPainterCache *cache = &tile->cache;
- if ((cache->use_float != use_float)) {
+ if (cache->use_float != use_float) {
if (cache->ibuf) {
IMB_freeImBuf(cache->ibuf);
}
@@ -402,7 +402,8 @@ static ImBuf *brush_painter_imbuf_new(
if (is_texbrush) {
brush_imbuf_tex_co(&tex_mapping, x, y, texco);
- BKE_brush_sample_tex_3d(scene, brush, texco, rgba, thread, pool);
+ const MTex *mtex = &brush->mtex;
+ BKE_brush_sample_tex_3d(scene, brush, mtex, texco, rgba, thread, pool);
/* TODO(sergey): Support texture paint color space. */
if (!use_float) {
IMB_colormanagement_scene_linear_to_display_v3(rgba, display);
@@ -446,6 +447,7 @@ static void brush_painter_imbuf_update(BrushPainter *painter,
{
Scene *scene = painter->scene;
Brush *brush = painter->brush;
+ const MTex *mtex = &brush->mtex;
BrushPainterCache *cache = &tile->cache;
const char *display_device = scene->display_settings.display_device;
@@ -485,7 +487,7 @@ static void brush_painter_imbuf_update(BrushPainter *painter,
if (!use_texture_old) {
if (is_texbrush) {
brush_imbuf_tex_co(&tex_mapping, x, y, texco);
- BKE_brush_sample_tex_3d(scene, brush, texco, rgba, thread, pool);
+ BKE_brush_sample_tex_3d(scene, brush, mtex, texco, rgba, thread, pool);
/* TODO(sergey): Support texture paint color space. */
if (!use_float) {
IMB_colormanagement_scene_linear_to_display_v3(rgba, display);
@@ -1178,8 +1180,8 @@ static ImBuf *paint_2d_lift_clone(ImBuf *ibuf, ImBuf *ibufb, const int *pos)
static void paint_2d_convert_brushco(ImBuf *ibufb, const float pos[2], int ipos[2])
{
- ipos[0] = (int)floorf((pos[0] - ibufb->x / 2));
- ipos[1] = (int)floorf((pos[1] - ibufb->y / 2));
+ ipos[0] = (int)floorf(pos[0] - ibufb->x / 2);
+ ipos[1] = (int)floorf(pos[1] - ibufb->y / 2);
}
static void paint_2d_do_making_brush(ImagePaintState *s,
diff --git a/source/blender/editors/sculpt_paint/paint_image_2d_curve_mask.cc b/source/blender/editors/sculpt_paint/paint_image_2d_curve_mask.cc
index f5657b004e2..6c7029cccd1 100644
--- a/source/blender/editors/sculpt_paint/paint_image_2d_curve_mask.cc
+++ b/source/blender/editors/sculpt_paint/paint_image_2d_curve_mask.cc
@@ -52,29 +52,29 @@ static void update_curve_mask(CurveMaskCache *curve_mask_cache,
const float cursor_position[2])
{
BLI_assert(curve_mask_cache->curve_mask != nullptr);
- int offset = (int)floorf(diameter / 2.0f);
+ int offset = int(floorf(diameter / 2.0f));
int clamped_radius = max_ff(radius, 1.0);
- unsigned short *m = curve_mask_cache->curve_mask;
+ ushort *m = curve_mask_cache->curve_mask;
const int aa_samples = aa_samples_per_texel_axis(brush, radius);
- const float aa_offset = 1.0f / (2.0f * (float)aa_samples);
- const float aa_step = 1.0f / (float)aa_samples;
+ const float aa_offset = 1.0f / (2.0f * float(aa_samples));
+ const float aa_step = 1.0f / float(aa_samples);
float bpos[2];
bpos[0] = cursor_position[0] - floorf(cursor_position[0]) + offset;
bpos[1] = cursor_position[1] - floorf(cursor_position[1]) + offset;
- float weight_factor = 65535.0f / (float)(aa_samples * aa_samples);
+ float weight_factor = 65535.0f / float(aa_samples * aa_samples);
for (int y = 0; y < diameter; y++) {
for (int x = 0; x < diameter; x++, m++) {
float pixel_xy[2];
- pixel_xy[0] = static_cast<float>(x) + aa_offset;
+ pixel_xy[0] = float(x) + aa_offset;
float total_weight = 0;
for (int i = 0; i < aa_samples; i++) {
- pixel_xy[1] = static_cast<float>(y) + aa_offset;
+ pixel_xy[1] = float(y) + aa_offset;
for (int j = 0; j < aa_samples; j++) {
const float len = len_v2v2(pixel_xy, bpos);
const int sample_index = min_ii((len / clamped_radius) * CurveSamplesBaseLen,
@@ -87,7 +87,7 @@ static void update_curve_mask(CurveMaskCache *curve_mask_cache,
}
pixel_xy[0] += aa_step;
}
- *m = (unsigned short)(total_weight * weight_factor);
+ *m = ushort(total_weight * weight_factor);
}
}
}
@@ -140,8 +140,7 @@ static void curve_mask_free(CurveMaskCache *curve_mask_cache)
static void curve_mask_allocate(CurveMaskCache *curve_mask_cache, const int diameter)
{
const size_t curve_mask_size = diameter_to_curve_mask_size(diameter);
- curve_mask_cache->curve_mask = static_cast<unsigned short *>(
- MEM_mallocN(curve_mask_size, __func__));
+ curve_mask_cache->curve_mask = static_cast<ushort *>(MEM_mallocN(curve_mask_size, __func__));
curve_mask_cache->curve_mask_size = curve_mask_size;
}
diff --git a/source/blender/editors/sculpt_paint/paint_image_ops_paint.cc b/source/blender/editors/sculpt_paint/paint_image_ops_paint.cc
index 928f3e9a496..d5c5aa5cebd 100644
--- a/source/blender/editors/sculpt_paint/paint_image_ops_paint.cc
+++ b/source/blender/editors/sculpt_paint/paint_image_ops_paint.cc
@@ -17,8 +17,6 @@
#include "BKE_paint.h"
#include "BKE_undo_system.h"
-#include "DEG_depsgraph.h"
-
#include "ED_paint.h"
#include "ED_view3d.h"
@@ -28,11 +26,8 @@
#include "MEM_guardedalloc.h"
#include "RNA_access.h"
-#include "RNA_define.h"
#include "WM_api.h"
-#include "WM_message.h"
-#include "WM_toolsystem.h"
#include "WM_types.h"
#include "ED_image.h"
@@ -79,16 +74,13 @@ class AbstractPaintMode {
class ImagePaintMode : public AbstractPaintMode {
public:
- void *paint_new_stroke(bContext *C,
- wmOperator *op,
- Object *UNUSED(ob),
- const float UNUSED(mouse[2]),
- int mode) override
+ void *paint_new_stroke(
+ bContext *C, wmOperator *op, Object * /*ob*/, const float /*mouse*/[2], int mode) override
{
return paint_2d_new_stroke(C, op, mode);
}
- void paint_stroke(bContext *UNUSED(C),
+ void paint_stroke(bContext * /*C*/,
void *stroke_handle,
float prev_mouse[2],
float mouse[2],
@@ -111,9 +103,9 @@ class ImagePaintMode : public AbstractPaintMode {
}
void paint_gradient_fill(const bContext *C,
- const Scene *UNUSED(scene),
+ const Scene * /*scene*/,
Brush *brush,
- struct PaintStroke *UNUSED(stroke),
+ struct PaintStroke * /*stroke*/,
void *stroke_handle,
float mouse_start[2],
float mouse_end[2]) override
@@ -143,7 +135,7 @@ class ImagePaintMode : public AbstractPaintMode {
class ProjectionPaintMode : public AbstractPaintMode {
public:
void *paint_new_stroke(
- bContext *C, wmOperator *UNUSED(op), Object *ob, const float mouse[2], int mode) override
+ bContext *C, wmOperator * /*op*/, Object *ob, const float mouse[2], int mode) override
{
return paint_proj_new_stroke(C, ob, mouse, mode);
}
@@ -240,7 +232,7 @@ struct PaintOperation {
}
};
-static void gradient_draw_line(bContext *UNUSED(C), int x, int y, void *customdata)
+static void gradient_draw_line(bContext * /*C*/, int x, int y, void *customdata)
{
PaintOperation *pop = (PaintOperation *)customdata;
@@ -294,6 +286,7 @@ static PaintOperation *texture_paint_init(bContext *C, wmOperator *op, const flo
copy_v2_v2(pop->startmouse, mouse);
ViewLayer *view_layer = CTX_data_view_layer(C);
+ BKE_view_layer_synced_ensure(scene, view_layer);
Object *ob = BKE_view_layer_active_object_get(view_layer);
/* initialize from context */
@@ -329,7 +322,7 @@ static PaintOperation *texture_paint_init(bContext *C, wmOperator *op, const flo
}
static void paint_stroke_update_step(bContext *C,
- wmOperator *UNUSED(op),
+ wmOperator * /*op*/,
struct PaintStroke *stroke,
PointerRNA *itemptr)
{
diff --git a/source/blender/editors/sculpt_paint/paint_image_proj.c b/source/blender/editors/sculpt_paint/paint_image_proj.c
index 1ca5df47e17..c85044bf915 100644
--- a/source/blender/editors/sculpt_paint/paint_image_proj.c
+++ b/source/blender/editors/sculpt_paint/paint_image_proj.c
@@ -74,6 +74,7 @@
#include "DEG_depsgraph.h"
#include "DEG_depsgraph_query.h"
+#include "ED_image.h"
#include "ED_node.h"
#include "ED_object.h"
#include "ED_paint.h"
@@ -415,6 +416,7 @@ typedef struct ProjPaintState {
const float (*vert_normals)[3];
const MEdge *medge_eval;
const MPoly *mpoly_eval;
+ const bool *select_poly_eval;
const int *material_indices;
const MLoop *mloop_eval;
const MLoopTri *mlooptri_eval;
@@ -591,8 +593,8 @@ static int project_bucket_offset(const ProjPaintState *ps, const float projCoSS[
*
* Second multiplication does similar but for vertical offset
*/
- return ((int)(((projCoSS[0] - ps->screenMin[0]) / ps->screen_width) * ps->buckets_x)) +
- (((int)(((projCoSS[1] - ps->screenMin[1]) / ps->screen_height) * ps->buckets_y)) *
+ return (int)(((projCoSS[0] - ps->screenMin[0]) / ps->screen_width) * ps->buckets_x) +
+ ((int)(((projCoSS[1] - ps->screenMin[1]) / ps->screen_height) * ps->buckets_y) *
ps->buckets_x);
}
@@ -1233,12 +1235,12 @@ static VertSeam *find_adjacent_seam(const ProjPaintState *ps,
LISTBASE_CIRCULAR_BACKWARD_END(VertSeam *, vert_seams, adjacent, seam);
}
else {
- LISTBASE_CIRCULAR_FORWARD_BEGIN (vert_seams, adjacent, seam) {
+ LISTBASE_CIRCULAR_FORWARD_BEGIN (VertSeam *, vert_seams, adjacent, seam) {
if ((adjacent->normal_cw != seam->normal_cw) && cmp_uv(adjacent->uv, seam->uv)) {
break;
}
}
- LISTBASE_CIRCULAR_FORWARD_END(vert_seams, adjacent, seam);
+ LISTBASE_CIRCULAR_FORWARD_END(VertSeam *, vert_seams, adjacent, seam);
}
BLI_assert(adjacent);
@@ -1523,7 +1525,7 @@ static void project_face_seams_init(const ProjPaintState *ps,
static void screen_px_from_ortho(const float uv[2],
const float v1co[3],
const float v2co[3],
- const float v3co[3], /* Screenspace coords */
+ const float v3co[3], /* Screen-space coords */
const float uv1co[2],
const float uv2co[2],
const float uv3co[2],
@@ -1941,8 +1943,8 @@ static ProjPixel *project_paint_uvpixel_init(const ProjPaintState *ps,
}
/* which bounding box cell are we in?, needed for undo */
- projPixel->bb_cell_index = ((int)(((float)x_px / (float)ibuf->x) * PROJ_BOUNDBOX_DIV)) +
- ((int)(((float)y_px / (float)ibuf->y) * PROJ_BOUNDBOX_DIV)) *
+ projPixel->bb_cell_index = (int)(((float)x_px / (float)ibuf->x) * PROJ_BOUNDBOX_DIV) +
+ (int)(((float)y_px / (float)ibuf->y) * PROJ_BOUNDBOX_DIV) *
PROJ_BOUNDBOX_DIV;
/* done with view3d_project_float inline */
@@ -2411,7 +2413,7 @@ static bool IsectPT2Df_limit(
const float pt[2], const float v1[2], const float v2[2], const float v3[2], const float limit)
{
return ((area_tri_v2(pt, v1, v2) + area_tri_v2(pt, v2, v3) + area_tri_v2(pt, v3, v1)) /
- (area_tri_v2(v1, v2, v3))) < limit;
+ area_tri_v2(v1, v2, v3)) < limit;
}
/**
@@ -3683,7 +3685,7 @@ static void proj_paint_state_viewport_init(ProjPaintState *ps, const char symmet
ps->viewDir[1] = 0.0f;
ps->viewDir[2] = 1.0f;
- copy_m4_m4(ps->obmat, ps->ob->obmat);
+ copy_m4_m4(ps->obmat, ps->ob->object_to_world);
if (symmetry_flag) {
int i;
@@ -3741,7 +3743,7 @@ static void proj_paint_state_viewport_init(ProjPaintState *ps, const char symmet
CameraParams params;
/* viewmat & viewinv */
- copy_m4_m4(viewinv, cam_ob_eval->obmat);
+ copy_m4_m4(viewinv, cam_ob_eval->object_to_world);
normalize_m4(viewinv);
invert_m4_m4(viewmat, viewinv);
@@ -4062,6 +4064,8 @@ static bool proj_paint_state_mesh_eval_init(const bContext *C, ProjPaintState *p
}
ps->mloop_eval = BKE_mesh_loops(ps->me_eval);
ps->mpoly_eval = BKE_mesh_polys(ps->me_eval);
+ ps->select_poly_eval = (const bool *)CustomData_get_layer_named(
+ &ps->me_eval->pdata, CD_PROP_BOOL, ".select_poly");
ps->material_indices = (const int *)CustomData_get_layer_named(
&ps->me_eval->pdata, CD_PROP_INT32, "material_index");
@@ -4071,7 +4075,7 @@ static bool proj_paint_state_mesh_eval_init(const bContext *C, ProjPaintState *p
ps->totloop_eval = ps->me_eval->totloop;
ps->mlooptri_eval = BKE_mesh_runtime_looptri_ensure(ps->me_eval);
- ps->totlooptri_eval = ps->me_eval->runtime.looptris.len;
+ ps->totlooptri_eval = BKE_mesh_runtime_looptri_len(ps->me_eval);
ps->poly_to_loop_uv = MEM_mallocN(ps->totpoly_eval * sizeof(MLoopUV *), "proj_paint_mtfaces");
@@ -4145,7 +4149,7 @@ static bool project_paint_clone_face_skip(ProjPaintState *ps,
}
typedef struct {
- const MPoly *mpoly_orig;
+ const bool *select_poly_orig;
const int *index_mp_to_orig;
} ProjPaintFaceLookup;
@@ -4154,8 +4158,10 @@ static void proj_paint_face_lookup_init(const ProjPaintState *ps, ProjPaintFaceL
{
memset(face_lookup, 0, sizeof(*face_lookup));
if (ps->do_face_sel) {
+ Mesh *orig_mesh = (Mesh *)ps->ob->data;
face_lookup->index_mp_to_orig = CustomData_get_layer(&ps->me_eval->pdata, CD_ORIGINDEX);
- face_lookup->mpoly_orig = BKE_mesh_polys((Mesh *)ps->ob->data);
+ face_lookup->select_poly_orig = CustomData_get_layer_named(
+ &orig_mesh->pdata, CD_PROP_BOOL, ".select_poly");
}
}
@@ -4166,17 +4172,12 @@ static bool project_paint_check_face_sel(const ProjPaintState *ps,
{
if (ps->do_face_sel) {
int orig_index;
- const MPoly *mp;
if ((face_lookup->index_mp_to_orig != NULL) &&
- (((orig_index = (face_lookup->index_mp_to_orig[lt->poly]))) != ORIGINDEX_NONE)) {
- mp = &face_lookup->mpoly_orig[orig_index];
+ ((orig_index = (face_lookup->index_mp_to_orig[lt->poly])) != ORIGINDEX_NONE)) {
+ return face_lookup->select_poly_orig && face_lookup->select_poly_orig[orig_index];
}
- else {
- mp = &ps->mpoly_eval[lt->poly];
- }
-
- return ((mp->flag & ME_FACE_SEL) != 0);
+ return ps->select_poly_eval && ps->select_poly_eval[lt->poly];
}
return true;
}
@@ -4462,7 +4463,7 @@ static void project_paint_begin(const bContext *C,
if (ps->source == PROJ_SRC_VIEW) {
/* faster clipping lookups */
- ED_view3d_clipping_local(ps->rv3d, ps->ob->obmat);
+ ED_view3d_clipping_local(ps->rv3d, ps->ob->object_to_world);
}
ps->do_face_sel = ((((Mesh *)ps->ob->data)->editflag & ME_EDIT_PAINT_FACE_SEL) != 0);
@@ -5370,7 +5371,7 @@ static void do_projectpaint_thread(TaskPool *__restrict UNUSED(pool), void *ph_v
/* Color texture (alpha used as mask). */
if (ps->is_texbrush) {
- MTex *mtex = &brush->mtex;
+ const MTex *mtex = BKE_brush_color_texture_get(brush, OB_MODE_TEXTURE_PAINT);
float samplecos[3];
float texrgba[4];
@@ -5386,7 +5387,8 @@ static void do_projectpaint_thread(TaskPool *__restrict UNUSED(pool), void *ph_v
/* NOTE: for clone and smear,
* we only use the alpha, could be a special function */
- BKE_brush_sample_tex_3d(ps->scene, brush, samplecos, texrgba, thread_index, pool);
+ BKE_brush_sample_tex_3d(
+ ps->scene, brush, mtex, samplecos, texrgba, thread_index, pool);
copy_v3_v3(texrgb, texrgba);
custom_mask *= texrgba[3];
@@ -6042,6 +6044,7 @@ static int texture_paint_camera_project_exec(bContext *C, wmOperator *op)
int orig_brush_size;
IDProperty *idgroup;
IDProperty *view_data = NULL;
+ BKE_view_layer_synced_ensure(scene, view_layer);
Object *ob = BKE_view_layer_active_object_get(view_layer);
bool uvs, mat, tex;
@@ -6249,8 +6252,8 @@ static int texture_paint_image_from_view_exec(bContext *C, wmOperator *op)
err_out);
if (!ibuf) {
- /* Mostly happens when OpenGL offscreen buffer was failed to create, */
- /* but could be other reasons. Should be handled in the future. nazgul */
+ /* NOTE(@sergey): Mostly happens when OpenGL off-screen buffer was failed to create, */
+ /* but could be other reasons. Should be handled in the future. */
BKE_reportf(op->reports, RPT_ERROR, "Failed to create OpenGL off-screen buffer: %s", err_out);
return OPERATOR_CANCELLED;
}
@@ -6702,6 +6705,7 @@ static bool proj_paint_add_slot(bContext *C, wmOperator *op)
BKE_texpaint_slot_refresh_cache(scene, ma, ob);
BKE_image_signal(bmain, ima, NULL, IMA_SIGNAL_USER_NEW_IMAGE);
WM_event_add_notifier(C, NC_IMAGE | NA_ADDED, ima);
+ ED_space_image_sync(bmain, ima, false);
}
if (layer) {
BKE_texpaint_slot_refresh_cache(scene, ma, ob);
diff --git a/source/blender/editors/sculpt_paint/paint_intern.h b/source/blender/editors/sculpt_paint/paint_intern.h
index 99c25953d50..c6fe7ed3072 100644
--- a/source/blender/editors/sculpt_paint/paint_intern.h
+++ b/source/blender/editors/sculpt_paint/paint_intern.h
@@ -100,6 +100,8 @@ struct ViewContext *paint_stroke_view_context(struct PaintStroke *stroke);
void *paint_stroke_mode_data(struct PaintStroke *stroke);
float paint_stroke_distance_get(struct PaintStroke *stroke);
void paint_stroke_set_mode_data(struct PaintStroke *stroke, void *mode_data);
+bool paint_stroke_started(struct PaintStroke *stroke);
+
bool PAINT_brush_tool_poll(struct bContext *C);
/**
* Delete overlay cursor textures to preserve memory and invalidate all overlay flags.
diff --git a/source/blender/editors/sculpt_paint/paint_mask.c b/source/blender/editors/sculpt_paint/paint_mask.c
index 437ff7506ba..ce7db91571c 100644
--- a/source/blender/editors/sculpt_paint/paint_mask.c
+++ b/source/blender/editors/sculpt_paint/paint_mask.c
@@ -31,6 +31,7 @@
#include "BKE_multires.h"
#include "BKE_paint.h"
#include "BKE_pbvh.h"
+#include "BKE_scene.h"
#include "BKE_subsurf.h"
#include "DEG_depsgraph.h"
@@ -41,12 +42,10 @@
#include "WM_api.h"
#include "WM_types.h"
-#include "ED_screen.h"
#include "ED_sculpt.h"
#include "ED_view3d.h"
#include "bmesh.h"
-#include "bmesh_tools.h"
#include "tools/bmesh_boolean.h"
#include "paint_intern.h"
@@ -148,7 +147,7 @@ static int mask_flood_fill_exec(bContext *C, wmOperator *op)
value = RNA_float_get(op->ptr, "value");
MultiresModifierData *mmd = BKE_sculpt_multires_active(scene, ob);
- BKE_sculpt_mask_layers_ensure(ob, mmd);
+ BKE_sculpt_mask_layers_ensure(depsgraph, CTX_data_main(C), ob, mmd);
BKE_sculpt_update_object_for_edit(depsgraph, ob, false, true, false);
pbvh = ob->sculpt->pbvh;
@@ -349,7 +348,7 @@ static void sculpt_gesture_context_init_common(bContext *C,
copy_m3_m4(mat, sgcontext->vc.rv3d->viewinv);
mul_m3_v3(mat, view_dir);
normalize_v3_v3(sgcontext->world_space_view_normal, view_dir);
- copy_m3_m4(mat, ob->imat);
+ copy_m3_m4(mat, ob->world_to_object);
mul_m3_v3(mat, view_dir);
normalize_v3_v3(sgcontext->true_view_normal, view_dir);
@@ -461,12 +460,12 @@ static void sculpt_gesture_line_plane_from_tri(float *r_plane,
{
float normal[3];
normal_tri_v3(normal, p1, p2, p3);
- mul_v3_mat3_m4v3(normal, sgcontext->vc.obact->imat, normal);
+ mul_v3_mat3_m4v3(normal, sgcontext->vc.obact->world_to_object, normal);
if (flip) {
mul_v3_fl(normal, -1.0f);
}
float plane_point_object_space[3];
- mul_v3_m4v3(plane_point_object_space, sgcontext->vc.obact->imat, p1);
+ mul_v3_m4v3(plane_point_object_space, sgcontext->vc.obact->world_to_object, p1);
plane_from_point_normal_v3(r_plane, plane_point_object_space, normal);
}
@@ -863,7 +862,9 @@ static void sculpt_gesture_mask_end(bContext *C, SculptGestureContext *sgcontext
BKE_pbvh_update_vertex_data(sgcontext->ss->pbvh, PBVH_UpdateMask);
}
-static void sculpt_gesture_init_mask_properties(SculptGestureContext *sgcontext, wmOperator *op)
+static void sculpt_gesture_init_mask_properties(bContext *C,
+ SculptGestureContext *sgcontext,
+ wmOperator *op)
{
sgcontext->operation = MEM_callocN(sizeof(SculptGestureMaskOperation), "Mask Operation");
@@ -871,7 +872,8 @@ static void sculpt_gesture_init_mask_properties(SculptGestureContext *sgcontext,
Object *object = sgcontext->vc.obact;
MultiresModifierData *mmd = BKE_sculpt_multires_active(sgcontext->vc.scene, object);
- BKE_sculpt_mask_layers_ensure(sgcontext->vc.obact, mmd);
+ BKE_sculpt_mask_layers_ensure(
+ CTX_data_depsgraph_pointer(C), CTX_data_main(C), sgcontext->vc.obact, mmd);
mask_operation->op.sculpt_gesture_begin = sculpt_gesture_mask_begin;
mask_operation->op.sculpt_gesture_apply_for_symmetry_pass =
@@ -1007,11 +1009,12 @@ static void sculpt_gesture_trim_shape_origin_normal_get(SculptGestureContext *sg
copy_v3_v3(r_normal, sgcontext->world_space_view_normal);
break;
case SCULPT_GESTURE_TRIM_ORIENTATION_SURFACE:
- mul_v3_m4v3(r_origin, sgcontext->vc.obact->obmat, sgcontext->ss->gesture_initial_location);
+ mul_v3_m4v3(
+ r_origin, sgcontext->vc.obact->object_to_world, sgcontext->ss->gesture_initial_location);
/* Transforming the normal does not take non uniform scaling into account. Sculpt mode is not
* expected to work on object with non uniform scaling. */
copy_v3_v3(r_normal, sgcontext->ss->gesture_initial_normal);
- mul_mat3_m4_v3(sgcontext->vc.obact->obmat, r_normal);
+ mul_mat3_m4_v3(sgcontext->vc.obact->object_to_world, r_normal);
break;
}
}
@@ -1042,7 +1045,7 @@ static void sculpt_gesture_trim_calculate_depth(SculptGestureContext *sgcontext)
* mesh, coordinates are first calculated in world space, then converted to object space to
* store them. */
float world_space_vco[3];
- mul_v3_m4v3(world_space_vco, vc->obact->obmat, vco);
+ mul_v3_m4v3(world_space_vco, vc->obact->object_to_world, vco);
const float dist = dist_signed_to_plane_v3(world_space_vco, shape_plane);
trim_operation->depth_front = min_ff(dist, trim_operation->depth_front);
trim_operation->depth_back = max_ff(dist, trim_operation->depth_back);
@@ -1050,8 +1053,9 @@ static void sculpt_gesture_trim_calculate_depth(SculptGestureContext *sgcontext)
if (trim_operation->use_cursor_depth) {
float world_space_gesture_initial_location[3];
- mul_v3_m4v3(
- world_space_gesture_initial_location, vc->obact->obmat, ss->gesture_initial_location);
+ mul_v3_m4v3(world_space_gesture_initial_location,
+ vc->obact->object_to_world,
+ ss->gesture_initial_location);
float mid_point_depth;
if (trim_operation->orientation == SCULPT_GESTURE_TRIM_ORIENTATION_VIEW) {
@@ -1130,7 +1134,7 @@ static void sculpt_gesture_trim_geometry_generate(SculptGestureContext *sgcontex
sculpt_gesture_trim_shape_origin_normal_get(sgcontext, shape_origin, shape_normal);
plane_from_point_normal_v3(shape_plane, shape_origin, shape_normal);
- const float(*ob_imat)[4] = vc->obact->imat;
+ const float(*ob_imat)[4] = vc->obact->world_to_object;
/* Write vertices coordinates for the front face. */
MVert *verts = BKE_mesh_verts_for_write(trim_operation->mesh);
@@ -1354,7 +1358,9 @@ static void sculpt_gesture_trim_end(bContext *UNUSED(C), SculptGestureContext *s
{
Object *object = sgcontext->vc.obact;
SculptSession *ss = object->sculpt;
- ss->face_sets = CustomData_get_layer(&((Mesh *)object->data)->pdata, CD_SCULPT_FACE_SETS);
+
+ ss->face_sets = CustomData_get_layer_named(
+ &((Mesh *)object->data)->pdata, CD_PROP_INT32, ".sculpt_face_set");
if (ss->face_sets) {
/* Assign a new Face Set ID to the new faces created by the trim operation. */
const int next_face_set_id = ED_sculpt_face_sets_find_next_available_id(object->data);
@@ -1514,7 +1520,7 @@ static int paint_mask_gesture_box_exec(bContext *C, wmOperator *op)
if (!sgcontext) {
return OPERATOR_CANCELLED;
}
- sculpt_gesture_init_mask_properties(sgcontext, op);
+ sculpt_gesture_init_mask_properties(C, sgcontext, op);
sculpt_gesture_apply(C, sgcontext, op);
sculpt_gesture_context_free(sgcontext);
return OPERATOR_FINISHED;
@@ -1526,7 +1532,7 @@ static int paint_mask_gesture_lasso_exec(bContext *C, wmOperator *op)
if (!sgcontext) {
return OPERATOR_CANCELLED;
}
- sculpt_gesture_init_mask_properties(sgcontext, op);
+ sculpt_gesture_init_mask_properties(C, sgcontext, op);
sculpt_gesture_apply(C, sgcontext, op);
sculpt_gesture_context_free(sgcontext);
return OPERATOR_FINISHED;
@@ -1538,7 +1544,7 @@ static int paint_mask_gesture_line_exec(bContext *C, wmOperator *op)
if (!sgcontext) {
return OPERATOR_CANCELLED;
}
- sculpt_gesture_init_mask_properties(sgcontext, op);
+ sculpt_gesture_init_mask_properties(C, sgcontext, op);
sculpt_gesture_apply(C, sgcontext, op);
sculpt_gesture_context_free(sgcontext);
return OPERATOR_FINISHED;
diff --git a/source/blender/editors/sculpt_paint/paint_stroke.c b/source/blender/editors/sculpt_paint/paint_stroke.c
index 60f4a9d59a5..f1f864fdf82 100644
--- a/source/blender/editors/sculpt_paint/paint_stroke.c
+++ b/source/blender/editors/sculpt_paint/paint_stroke.c
@@ -249,7 +249,7 @@ static bool paint_stroke_use_scene_spacing(Brush *brush, ePaintMode mode)
static bool paint_tool_raycast_original(Brush *brush, ePaintMode UNUSED(mode))
{
- return brush->flag & BRUSH_ANCHORED;
+ return brush->flag & (BRUSH_ANCHORED | BRUSH_DRAG_DOT);
}
static bool paint_tool_require_inbetween_mouse_events(Brush *brush, ePaintMode mode)
@@ -564,7 +564,7 @@ static void paint_brush_stroke_add_step(
if (SCULPT_stroke_get_location(
C, world_space_position, stroke->last_mouse_position, stroke->original)) {
copy_v3_v3(stroke->last_world_space_position, world_space_position);
- mul_m4_v3(stroke->vc.obact->obmat, stroke->last_world_space_position);
+ mul_m4_v3(stroke->vc.obact->object_to_world, stroke->last_world_space_position);
}
else {
add_v3_v3(stroke->last_world_space_position, stroke->last_scene_spacing_delta);
@@ -681,8 +681,9 @@ static float paint_space_stroke_spacing(bContext *C,
if (paint_stroke_use_scene_spacing(brush, mode)) {
if (!BKE_brush_use_locked_size(scene, brush)) {
float last_object_space_position[3];
- mul_v3_m4v3(
- last_object_space_position, stroke->vc.obact->imat, stroke->last_world_space_position);
+ mul_v3_m4v3(last_object_space_position,
+ stroke->vc.obact->world_to_object,
+ stroke->last_world_space_position);
size_clamp = paint_calc_object_space_radius(&stroke->vc, last_object_space_position, size);
}
else {
@@ -825,7 +826,7 @@ static int paint_space_stroke(bContext *C,
if (use_scene_spacing) {
float world_space_position[3];
bool hit = SCULPT_stroke_get_location(C, world_space_position, final_mouse, stroke->original);
- mul_m4_v3(stroke->vc.obact->obmat, world_space_position);
+ mul_m4_v3(stroke->vc.obact->object_to_world, world_space_position);
if (hit && stroke->stroke_over_mesh) {
sub_v3_v3v3(d_world_space_position, world_space_position, stroke->last_world_space_position);
length = len_v3(d_world_space_position);
@@ -1140,7 +1141,7 @@ struct wmKeyMap *paint_stroke_modal_keymap(struct wmKeyConfig *keyconf)
struct wmKeyMap *keymap = WM_modalkeymap_find(keyconf, name);
- /* this function is called for each spacetype, only needs to add map once */
+ /* This function is called for each space-type, only needs to add map once. */
if (!keymap) {
keymap = WM_modalkeymap_ensure(keyconf, name, modal_items);
}
@@ -1216,8 +1217,8 @@ static void paint_line_strokes_spacing(bContext *C,
C, world_space_position_old, old_pos, stroke->original);
bool hit_new = SCULPT_stroke_get_location(
C, world_space_position_new, new_pos, stroke->original);
- mul_m4_v3(stroke->vc.obact->obmat, world_space_position_old);
- mul_m4_v3(stroke->vc.obact->obmat, world_space_position_new);
+ mul_m4_v3(stroke->vc.obact->object_to_world, world_space_position_old);
+ mul_m4_v3(stroke->vc.obact->object_to_world, world_space_position_new);
if (hit_old && hit_new && stroke->stroke_over_mesh) {
sub_v3_v3v3(d_world_space_position, world_space_position_new, world_space_position_old);
length = len_v3(d_world_space_position);
@@ -1360,7 +1361,7 @@ static bool paint_stroke_curve_end(bContext *C, wmOperator *op, PaintStroke *str
if (paint_stroke_use_scene_spacing(br, BKE_paintmode_get_active_from_context(C))) {
stroke->stroke_over_mesh = SCULPT_stroke_get_location(
C, stroke->last_world_space_position, data + 2 * j, stroke->original);
- mul_m4_v3(stroke->vc.obact->obmat, stroke->last_world_space_position);
+ mul_m4_v3(stroke->vc.obact->object_to_world, stroke->last_world_space_position);
}
stroke->stroke_started = stroke->test_start(C, op, stroke->last_mouse_position);
@@ -1492,7 +1493,7 @@ int paint_stroke_modal(bContext *C, wmOperator *op, const wmEvent *event, PaintS
if (paint_stroke_use_scene_spacing(br, mode)) {
stroke->stroke_over_mesh = SCULPT_stroke_get_location(
C, stroke->last_world_space_position, sample_average.mouse, stroke->original);
- mul_m4_v3(stroke->vc.obact->obmat, stroke->last_world_space_position);
+ mul_m4_v3(stroke->vc.obact->object_to_world, stroke->last_world_space_position);
}
stroke->stroke_started = stroke->test_start(C, op, sample_average.mouse);
BLI_assert((stroke->stroke_started & ~1) == 0); /* 0/1 */
@@ -1674,6 +1675,11 @@ void paint_stroke_set_mode_data(PaintStroke *stroke, void *mode_data)
stroke->mode_data = mode_data;
}
+bool paint_stroke_started(PaintStroke *stroke)
+{
+ return stroke->stroke_started;
+}
+
bool PAINT_brush_tool_poll(bContext *C)
{
Paint *p = BKE_paint_get_active_from_context(C);
diff --git a/source/blender/editors/sculpt_paint/paint_utils.c b/source/blender/editors/sculpt_paint/paint_utils.c
index 1cedcde7035..f87ca073c82 100644
--- a/source/blender/editors/sculpt_paint/paint_utils.c
+++ b/source/blender/editors/sculpt_paint/paint_utils.c
@@ -135,12 +135,12 @@ float paint_calc_object_space_radius(ViewContext *vc, const float center[3], flo
float delta[3], scale, loc[3];
const float xy_delta[2] = {pixel_radius, 0.0f};
- mul_v3_m4v3(loc, ob->obmat, center);
+ mul_v3_m4v3(loc, ob->object_to_world, center);
const float zfac = ED_view3d_calc_zfac(vc->rv3d, loc);
ED_view3d_win_to_delta(vc->region, xy_delta, zfac, delta);
- scale = fabsf(mat4_to_scale(ob->obmat));
+ scale = fabsf(mat4_to_scale(ob->object_to_world));
scale = (scale == 0.0f) ? 1.0f : scale;
return len_v3(delta) / scale;
@@ -286,7 +286,7 @@ static void imapaint_pick_uv(
const ePaintCanvasSource mode = scene->toolsettings->imapaint.mode;
const MLoopTri *lt = BKE_mesh_runtime_looptri_ensure(me_eval);
- const int tottri = me_eval->runtime.looptris.len;
+ const int tottri = BKE_mesh_runtime_looptri_len(me_eval);
const MVert *mvert = BKE_mesh_verts(me_eval);
const MLoop *mloop = BKE_mesh_loops(me_eval);
@@ -297,7 +297,7 @@ static void imapaint_pick_uv(
GPU_matrix_model_view_get(matrix);
GPU_matrix_projection_get(proj);
view[0] = view[1] = 0;
- mul_m4_m4m4(matrix, matrix, ob_eval->obmat);
+ mul_m4_m4m4(matrix, matrix, ob_eval->object_to_world);
mul_m4_m4m4(matrix, proj, matrix);
minabsw = 1e10;
@@ -404,6 +404,7 @@ void paint_sample_color(
if (v3d && texpaint_proj) {
/* first try getting a color directly from the mesh faces if possible */
ViewLayer *view_layer = CTX_data_view_layer(C);
+ BKE_view_layer_synced_ensure(scene, view_layer);
Object *ob = BKE_view_layer_active_object_get(view_layer);
Object *ob_eval = DEG_get_evaluated_object(depsgraph, ob);
ImagePaintSettings *imapaint = &scene->toolsettings->imapaint;
diff --git a/source/blender/editors/sculpt_paint/paint_vertex.cc b/source/blender/editors/sculpt_paint/paint_vertex.cc
index c38a79cb6bb..8e790ac435e 100644
--- a/source/blender/editors/sculpt_paint/paint_vertex.cc
+++ b/source/blender/editors/sculpt_paint/paint_vertex.cc
@@ -29,25 +29,21 @@
#include "DNA_scene_types.h"
#include "RNA_access.h"
-#include "RNA_prototypes.h"
#include "BKE_attribute.h"
+#include "BKE_attribute.hh"
#include "BKE_brush.h"
#include "BKE_colortools.h"
#include "BKE_context.h"
#include "BKE_deform.h"
#include "BKE_editmesh.h"
-#include "BKE_layer.h"
#include "BKE_lib_id.h"
-#include "BKE_main.h"
#include "BKE_mesh.h"
#include "BKE_mesh_mapping.h"
-#include "BKE_modifier.h"
#include "BKE_object.h"
#include "BKE_object_deform.h"
#include "BKE_paint.h"
#include "BKE_report.h"
-#include "BKE_subsurf.h"
#include "DEG_depsgraph.h"
@@ -56,7 +52,6 @@
#include "WM_toolsystem.h"
#include "WM_types.h"
-#include "ED_armature.h"
#include "ED_image.h"
#include "ED_mesh.h"
#include "ED_object.h"
@@ -170,8 +165,8 @@ static void view_angle_limits_init(NormalAnglePrecalc *a, float angle, bool do_m
a->angle_inner = a->angle = angle;
}
- a->angle_inner *= (float)(M_PI_2 / 90);
- a->angle *= (float)(M_PI_2 / 90);
+ a->angle_inner *= float(M_PI_2 / 90);
+ a->angle *= float(M_PI_2 / 90);
a->angle_range = a->angle - a->angle_inner;
if (a->angle_range <= 0.0f) {
@@ -397,7 +392,7 @@ static float wpaint_blend(const VPaint *wp,
float weight,
const float alpha,
float paintval,
- const float UNUSED(brush_alpha_value),
+ const float /*brush_alpha_value*/,
const bool do_flip)
{
const Brush *brush = wp->paint.brush;
@@ -438,9 +433,10 @@ static void paint_and_tex_color_alpha_intern(VPaint *vp,
float r_rgba[4])
{
const Brush *brush = BKE_paint_brush(&vp->paint);
- BLI_assert(brush->mtex.tex != nullptr);
- if (brush->mtex.brush_map_mode == MTEX_MAP_MODE_3D) {
- BKE_brush_sample_tex_3d(vc->scene, brush, co, r_rgba, 0, nullptr);
+ const MTex *mtex = BKE_brush_mask_texture_get(brush, OB_MODE_SCULPT);
+ BLI_assert(mtex->tex != nullptr);
+ if (mtex->brush_map_mode == MTEX_MAP_MODE_3D) {
+ BKE_brush_sample_tex_3d(vc->scene, brush, mtex, co, r_rgba, 0, nullptr);
}
else {
float co_ss[2]; /* screenspace */
@@ -450,7 +446,7 @@ static void paint_and_tex_color_alpha_intern(VPaint *vp,
co_ss,
(eV3DProjTest)(V3D_PROJ_TEST_CLIP_BB | V3D_PROJ_TEST_CLIP_NEAR)) == V3D_PROJ_RET_OK) {
const float co_ss_3d[3] = {co_ss[0], co_ss[1], 0.0f}; /* we need a 3rd empty value */
- BKE_brush_sample_tex_3d(vc->scene, brush, co_ss_3d, r_rgba, 0, nullptr);
+ BKE_brush_sample_tex_3d(vc->scene, brush, mtex, co_ss_3d, r_rgba, 0, nullptr);
}
else {
zero_v4(r_rgba);
@@ -893,7 +889,7 @@ static void do_weight_paint_vertex_single(
else {
/* dv and dv_mirr are the same */
int totweight_prev = dv_mirr->totweight;
- int dw_offset = (int)(dw - dv_mirr->dw);
+ int dw_offset = int(dw - dv_mirr->dw);
dw_mirr = BKE_defvert_ensure_index(dv_mirr, vgroup_mirr);
/* if we added another, get our old one back */
@@ -1651,10 +1647,10 @@ static void vwpaint_update_cache_invariants(
/* cache projection matrix */
ED_view3d_ob_project_mat_get(cache->vc->rv3d, ob, cache->projection_mat);
- invert_m4_m4(ob->imat, ob->obmat);
+ invert_m4_m4(ob->world_to_object, ob->object_to_world);
copy_m3_m4(mat, cache->vc->rv3d->viewinv);
mul_m3_v3(mat, view_dir);
- copy_m3_m4(mat, ob->imat);
+ copy_m3_m4(mat, ob->world_to_object);
mul_m3_v3(mat, view_dir);
normalize_v3_v3(cache->true_view_normal, view_dir);
@@ -1901,7 +1897,7 @@ static float wpaint_get_active_weight(const MDeformVert *dv, const WeightPaintIn
static void do_wpaint_precompute_weight_cb_ex(void *__restrict userdata,
const int n,
- const TaskParallelTLS *__restrict UNUSED(tls))
+ const TaskParallelTLS *__restrict /*tls*/)
{
SculptThreadedTaskData *data = (SculptThreadedTaskData *)userdata;
const MDeformVert *dv = &data->wpi->dvert[n];
@@ -1933,7 +1929,7 @@ static void precompute_weight_values(
static void do_wpaint_brush_blur_task_cb_ex(void *__restrict userdata,
const int n,
- const TaskParallelTLS *__restrict UNUSED(tls))
+ const TaskParallelTLS *__restrict /*tls*/)
{
SculptThreadedTaskData *data = (SculptThreadedTaskData *)userdata;
SculptSession *ss = data->ob->sculpt;
@@ -1958,6 +1954,10 @@ static void do_wpaint_brush_blur_task_cb_ex(void *__restrict userdata,
const float *sculpt_normal_frontface = SCULPT_brush_frontface_normal_from_falloff_shape(
ss, data->brush->falloff_shape);
+ const blender::bke::AttributeAccessor attributes = data->me->attributes();
+ const blender::VArray<bool> select_vert = attributes.lookup_or_default<bool>(
+ ".select_vert", ATTR_DOMAIN_POINT, false);
+
/* For each vertex */
PBVHVertexIter vd;
BKE_pbvh_vertex_iter_begin (ss->pbvh, data->nodes[n], vd, PBVH_ITER_UNIQUE) {
@@ -1967,9 +1967,8 @@ static void do_wpaint_brush_blur_task_cb_ex(void *__restrict userdata,
* Otherwise, take the current vert. */
const int v_index = has_grids ? ss->mloop[vd.grid_indices[vd.g]].v : vd.vert_indices[vd.i];
const float grid_alpha = has_grids ? 1.0f / vd.gridsize : 1.0f;
- const char v_flag = ss->mvert[v_index].flag;
/* If the vertex is selected */
- if (!(use_face_sel || use_vert_sel) || v_flag & SELECT) {
+ if (!(use_face_sel || use_vert_sel) || select_vert[v_index]) {
/* Get the average poly weight */
int total_hit_loops = 0;
float weight_final = 0.0f;
@@ -2023,7 +2022,7 @@ static void do_wpaint_brush_blur_task_cb_ex(void *__restrict userdata,
static void do_wpaint_brush_smear_task_cb_ex(void *__restrict userdata,
const int n,
- const TaskParallelTLS *__restrict UNUSED(tls))
+ const TaskParallelTLS *__restrict /*tls*/)
{
SculptThreadedTaskData *data = (SculptThreadedTaskData *)userdata;
SculptSession *ss = data->ob->sculpt;
@@ -2045,6 +2044,10 @@ static void do_wpaint_brush_smear_task_cb_ex(void *__restrict userdata,
sub_v3_v3v3(brush_dir, cache->location, cache->last_location);
project_plane_v3_v3v3(brush_dir, brush_dir, cache->view_normal);
+ const blender::bke::AttributeAccessor attributes = data->me->attributes();
+ const blender::VArray<bool> select_vert = attributes.lookup_or_default<bool>(
+ ".select_vert", ATTR_DOMAIN_POINT, false);
+
if (cache->is_last_valid && (normalize_v3(brush_dir) != 0.0f)) {
SculptBrushTest test;
@@ -2065,7 +2068,7 @@ static void do_wpaint_brush_smear_task_cb_ex(void *__restrict userdata,
const MVert *mv_curr = &ss->mvert[v_index];
/* If the vertex is selected */
- if (!(use_face_sel || use_vert_sel) || mv_curr->flag & SELECT) {
+ if (!(use_face_sel || use_vert_sel) || select_vert[v_index]) {
float brush_strength = cache->bstrength;
const float angle_cos = (use_normal && vd.no) ?
dot_v3v3(sculpt_normal_frontface, vd.no) :
@@ -2120,7 +2123,7 @@ static void do_wpaint_brush_smear_task_cb_ex(void *__restrict userdata,
}
do_weight_paint_vertex(
- data->vp, data->ob, data->wpi, v_index, final_alpha, (float)weight_final);
+ data->vp, data->ob, data->wpi, v_index, final_alpha, float(weight_final));
}
}
}
@@ -2132,7 +2135,7 @@ static void do_wpaint_brush_smear_task_cb_ex(void *__restrict userdata,
static void do_wpaint_brush_draw_task_cb_ex(void *__restrict userdata,
const int n,
- const TaskParallelTLS *__restrict UNUSED(tls))
+ const TaskParallelTLS *__restrict /*tls*/)
{
SculptThreadedTaskData *data = (SculptThreadedTaskData *)userdata;
SculptSession *ss = data->ob->sculpt;
@@ -2158,6 +2161,10 @@ static void do_wpaint_brush_draw_task_cb_ex(void *__restrict userdata,
const float *sculpt_normal_frontface = SCULPT_brush_frontface_normal_from_falloff_shape(
ss, data->brush->falloff_shape);
+ const blender::bke::AttributeAccessor attributes = data->me->attributes();
+ const blender::VArray<bool> select_vert = attributes.lookup_or_default<bool>(
+ ".select_vert", ATTR_DOMAIN_POINT, false);
+
/* For each vertex */
PBVHVertexIter vd;
BKE_pbvh_vertex_iter_begin (ss->pbvh, data->nodes[n], vd, PBVH_ITER_UNIQUE) {
@@ -2169,9 +2176,8 @@ static void do_wpaint_brush_draw_task_cb_ex(void *__restrict userdata,
const int v_index = has_grids ? ss->mloop[vd.grid_indices[vd.g]].v : vd.vert_indices[vd.i];
const float grid_alpha = has_grids ? 1.0f / vd.gridsize : 1.0f;
- const char v_flag = ss->mvert[v_index].flag;
/* If the vertex is selected */
- if (!(use_face_sel || use_vert_sel) || v_flag & SELECT) {
+ if (!(use_face_sel || use_vert_sel) || select_vert[v_index]) {
float brush_strength = cache->bstrength;
const float angle_cos = (use_normal && vd.no) ? dot_v3v3(sculpt_normal_frontface, vd.no) :
1.0f;
@@ -2201,8 +2207,9 @@ static void do_wpaint_brush_draw_task_cb_ex(void *__restrict userdata,
BKE_pbvh_vertex_iter_end;
}
-static void do_wpaint_brush_calc_average_weight_cb_ex(
- void *__restrict userdata, const int n, const TaskParallelTLS *__restrict UNUSED(tls))
+static void do_wpaint_brush_calc_average_weight_cb_ex(void *__restrict userdata,
+ const int n,
+ const TaskParallelTLS *__restrict /*tls*/)
{
SculptThreadedTaskData *data = (SculptThreadedTaskData *)userdata;
SculptSession *ss = data->ob->sculpt;
@@ -2224,6 +2231,10 @@ static void do_wpaint_brush_calc_average_weight_cb_ex(
const float *sculpt_normal_frontface = SCULPT_brush_frontface_normal_from_falloff_shape(
ss, data->brush->falloff_shape);
+ const blender::bke::AttributeAccessor attributes = data->me->attributes();
+ const blender::VArray<bool> select_vert = attributes.lookup_or_default<bool>(
+ ".select_vert", ATTR_DOMAIN_POINT, false);
+
/* For each vertex */
PBVHVertexIter vd;
BKE_pbvh_vertex_iter_begin (ss->pbvh, data->nodes[n], vd, PBVH_ITER_UNIQUE) {
@@ -2234,10 +2245,9 @@ static void do_wpaint_brush_calc_average_weight_cb_ex(
if (angle_cos > 0.0 &&
BKE_brush_curve_strength(data->brush, sqrtf(test.dist), cache->radius) > 0.0) {
const int v_index = has_grids ? ss->mloop[vd.grid_indices[vd.g]].v : vd.vert_indices[vd.i];
- const char v_flag = ss->mvert[v_index].flag;
/* If the vertex is selected. */
- if (!(use_face_sel || use_vert_sel) || v_flag & SELECT) {
+ if (!(use_face_sel || use_vert_sel) || select_vert[v_index]) {
const MDeformVert *dv = &data->wpi->dvert[v_index];
accum->len += 1;
accum->value += wpaint_get_active_weight(dv, data->wpi);
@@ -2249,7 +2259,7 @@ static void do_wpaint_brush_calc_average_weight_cb_ex(
}
static void calculate_average_weight(SculptThreadedTaskData *data,
- PBVHNode **UNUSED(nodes),
+ PBVHNode ** /*nodes*/,
int totnode)
{
WPaintAverageAccum *accum = (WPaintAverageAccum *)MEM_mallocN(sizeof(*accum) * totnode,
@@ -2268,7 +2278,7 @@ static void calculate_average_weight(SculptThreadedTaskData *data,
}
if (accum_len != 0) {
accum_weight /= accum_len;
- data->strength = (float)accum_weight;
+ data->strength = float(accum_weight);
}
MEM_SAFE_FREE(data->custom_data); /* 'accum' */
@@ -2445,7 +2455,7 @@ static void wpaint_do_symmetrical_brush_actions(
/* symm is a bit combination of XYZ - 1 is mirror
* X; 2 is Y; 3 is XY; 4 is Z; 5 is XZ; 6 is YZ; 7 is XYZ */
for (i = 1; i <= symm; i++) {
- if ((symm & i && (symm != 5 || i != 3) && (symm != 6 || (!ELEM(i, 3, 5))))) {
+ if (symm & i && (symm != 5 || i != 3) && (symm != 6 || !ELEM(i, 3, 5))) {
cache->mirror_symmetry_pass = i;
cache->radial_symmetry_pass = 0;
SCULPT_cache_calc_brushdata_symm(cache, i, 0, 0);
@@ -2469,7 +2479,7 @@ static void wpaint_do_symmetrical_brush_actions(
}
static void wpaint_stroke_update_step(bContext *C,
- wmOperator *UNUSED(op),
+ wmOperator * /*op*/,
PaintStroke *stroke,
PointerRNA *itemptr)
{
@@ -2508,7 +2518,7 @@ static void wpaint_stroke_update_step(bContext *C,
ED_view3d_init_mats_rv3d(ob, vc->rv3d);
/* load projection matrix */
- mul_m4_m4m4(mat, vc->rv3d->persmat, ob->obmat);
+ mul_m4_m4m4(mat, vc->rv3d->persmat, ob->object_to_world);
Mesh *mesh = static_cast<Mesh *>(ob->data);
@@ -2546,7 +2556,7 @@ static void wpaint_stroke_update_step(bContext *C,
/* Calculate pivot for rotation around selection if needed.
* also needed for "Frame Selected" on last stroke. */
float loc_world[3];
- mul_v3_m4v3(loc_world, ob->obmat, ss->cache->true_location);
+ mul_v3_m4v3(loc_world, ob->object_to_world, ss->cache->true_location);
paint_last_stroke_update(scene, loc_world);
BKE_mesh_batch_cache_dirty_tag(mesh, BKE_MESH_BATCH_DIRTY_ALL);
@@ -2938,7 +2948,7 @@ static bool vpaint_stroke_test_start(bContext *C, wmOperator *op, const float mo
template<class Color = ColorPaint4b, typename Traits = ByteTraits>
static void do_vpaint_brush_blur_loops(bContext *C,
- Sculpt *UNUSED(sd),
+ Sculpt * /*sd*/,
VPaint *vp,
VPaintData<Color, Traits, ATTR_DOMAIN_CORNER> *vpd,
Object *ob,
@@ -2956,6 +2966,11 @@ static void do_vpaint_brush_blur_loops(bContext *C,
Color *previous_color = static_cast<Color *>(ss->cache->prev_colors_vpaint);
+ const blender::VArray<bool> select_vert = me->attributes().lookup_or_default<bool>(
+ ".select_vert", ATTR_DOMAIN_POINT, false);
+ const blender::VArray<bool> select_poly = me->attributes().lookup_or_default<bool>(
+ ".select_poly", ATTR_DOMAIN_FACE, false);
+
blender::threading::parallel_for(IndexRange(totnode), 1LL, [&](IndexRange range) {
for (int n : range) {
const PBVHType pbvh_type = BKE_pbvh_type(ss->pbvh);
@@ -2987,10 +3002,9 @@ static void do_vpaint_brush_blur_loops(bContext *C,
const int v_index = has_grids ? ss->mloop[vd.grid_indices[vd.g]].v :
vd.vert_indices[vd.i];
const float grid_alpha = has_grids ? 1.0f / vd.gridsize : 1.0f;
- const MVert *mv = &ss->mvert[v_index];
/* If the vertex is selected for painting. */
- if (!use_vert_sel || mv->flag & SELECT) {
+ if (!use_vert_sel || select_vert[v_index]) {
float brush_strength = cache->bstrength;
const float angle_cos = (use_normal && vd.no) ?
dot_v3v3(sculpt_normal_frontface, vd.no) :
@@ -3011,7 +3025,7 @@ static void do_vpaint_brush_blur_loops(bContext *C,
for (int j = 0; j < gmap->vert_to_poly[v_index].count; j++) {
int p_index = gmap->vert_to_poly[v_index].indices[j];
const MPoly *mp = &ss->mpoly[p_index];
- if (!use_face_sel || mp->flag & ME_FACE_SEL) {
+ if (!use_face_sel || select_poly[p_index]) {
total_hit_loops += mp->totloop;
for (int k = 0; k < mp->totloop; k++) {
const uint l_index = mp->loopstart + k;
@@ -3045,8 +3059,7 @@ static void do_vpaint_brush_blur_loops(bContext *C,
const int p_index = gmap->vert_to_poly[v_index].indices[j];
const int l_index = gmap->vert_to_loop[v_index].indices[j];
BLI_assert(ss->mloop[l_index].v == v_index);
- const MPoly *mp = &ss->mpoly[p_index];
- if (!use_face_sel || mp->flag & ME_FACE_SEL) {
+ if (!use_face_sel || select_poly[p_index]) {
Color color_orig(0, 0, 0, 0); /* unused when array is nullptr */
if (previous_color != nullptr) {
@@ -3080,7 +3093,7 @@ static void do_vpaint_brush_blur_loops(bContext *C,
template<class Color = ColorPaint4b, typename Traits = ByteTraits>
static void do_vpaint_brush_blur_verts(bContext *C,
- Sculpt *UNUSED(sd),
+ Sculpt * /*sd*/,
VPaint *vp,
VPaintData<Color, Traits, ATTR_DOMAIN_POINT> *vpd,
Object *ob,
@@ -3098,6 +3111,11 @@ static void do_vpaint_brush_blur_verts(bContext *C,
Color *previous_color = static_cast<Color *>(ss->cache->prev_colors_vpaint);
+ const blender::VArray<bool> select_vert = me->attributes().lookup_or_default<bool>(
+ ".select_vert", ATTR_DOMAIN_POINT, false);
+ const blender::VArray<bool> select_poly = me->attributes().lookup_or_default<bool>(
+ ".select_poly", ATTR_DOMAIN_FACE, false);
+
blender::threading::parallel_for(IndexRange(totnode), 1LL, [&](IndexRange range) {
for (int n : range) {
const PBVHType pbvh_type = BKE_pbvh_type(ss->pbvh);
@@ -3129,10 +3147,9 @@ static void do_vpaint_brush_blur_verts(bContext *C,
const int v_index = has_grids ? ss->mloop[vd.grid_indices[vd.g]].v :
vd.vert_indices[vd.i];
const float grid_alpha = has_grids ? 1.0f / vd.gridsize : 1.0f;
- const MVert *mv = &ss->mvert[v_index];
/* If the vertex is selected for painting. */
- if (!use_vert_sel || mv->flag & SELECT) {
+ if (!use_vert_sel || select_vert[v_index]) {
float brush_strength = cache->bstrength;
const float angle_cos = (use_normal && vd.no) ?
dot_v3v3(sculpt_normal_frontface, vd.no) :
@@ -3153,7 +3170,7 @@ static void do_vpaint_brush_blur_verts(bContext *C,
for (int j = 0; j < gmap->vert_to_poly[v_index].count; j++) {
int p_index = gmap->vert_to_poly[v_index].indices[j];
const MPoly *mp = &ss->mpoly[p_index];
- if (!use_face_sel || mp->flag & ME_FACE_SEL) {
+ if (!use_face_sel || select_poly[p_index]) {
total_hit_loops += mp->totloop;
for (int k = 0; k < mp->totloop; k++) {
const uint l_index = mp->loopstart + k;
@@ -3190,8 +3207,7 @@ static void do_vpaint_brush_blur_verts(bContext *C,
BLI_assert(ss->mloop[gmap->vert_to_loop[v_index].indices[j]].v == v_index);
- const MPoly *mp = &ss->mpoly[p_index];
- if (!use_face_sel || mp->flag & ME_FACE_SEL) {
+ if (!use_face_sel || select_poly[p_index]) {
Color color_orig(0, 0, 0, 0); /* unused when array is nullptr */
if (previous_color != nullptr) {
@@ -3225,7 +3241,7 @@ static void do_vpaint_brush_blur_verts(bContext *C,
template<typename Color = ColorPaint4b, typename Traits, eAttrDomain domain>
static void do_vpaint_brush_smear(bContext *C,
- Sculpt *UNUSED(sd),
+ Sculpt * /*sd*/,
VPaint *vp,
VPaintData<Color, Traits, domain> *vpd,
Object *ob,
@@ -3247,6 +3263,11 @@ static void do_vpaint_brush_smear(bContext *C,
Color *color_prev_smear = static_cast<Color *>(vpd->smear.color_prev);
Color *color_prev = reinterpret_cast<Color *>(ss->cache->prev_colors_vpaint);
+ const blender::VArray<bool> select_vert = me->attributes().lookup_or_default<bool>(
+ ".select_vert", ATTR_DOMAIN_POINT, false);
+ const blender::VArray<bool> select_poly = me->attributes().lookup_or_default<bool>(
+ ".select_poly", ATTR_DOMAIN_FACE, false);
+
blender::threading::parallel_for(IndexRange(totnode), 1LL, [&](IndexRange range) {
for (int n : range) {
float brush_size_pressure, brush_alpha_value, brush_alpha_pressure;
@@ -3283,7 +3304,7 @@ static void do_vpaint_brush_smear(bContext *C,
const MVert *mv_curr = &ss->mvert[v_index];
/* if the vertex is selected for painting. */
- if (!use_vert_sel || mv_curr->flag & SELECT) {
+ if (!use_vert_sel || select_vert[v_index]) {
/* Calc the dot prod. between ray norm on surf and current vert
* (ie splash prevention factor), and only paint front facing verts. */
float brush_strength = cache->bstrength;
@@ -3312,7 +3333,7 @@ static void do_vpaint_brush_smear(bContext *C,
BLI_assert(ss->mloop[l_index].v == v_index);
UNUSED_VARS_NDEBUG(l_index);
const MPoly *mp = &ss->mpoly[p_index];
- if (!use_face_sel || mp->flag & ME_FACE_SEL) {
+ if (!use_face_sel || select_poly[p_index]) {
const MLoop *ml_other = &ss->mloop[mp->loopstart];
for (int k = 0; k < mp->totloop; k++, ml_other++) {
const uint v_other_index = ml_other->v;
@@ -3366,8 +3387,7 @@ static void do_vpaint_brush_smear(bContext *C,
BLI_assert(ss->mloop[l_index].v == v_index);
}
- const MPoly *mp = &ss->mpoly[p_index];
- if (!use_face_sel || mp->flag & ME_FACE_SEL) {
+ if (!use_face_sel || select_poly[p_index]) {
/* Get the previous element color */
Color color_orig(0, 0, 0, 0); /* unused when array is nullptr */
@@ -3413,6 +3433,9 @@ static void calculate_average_color(VPaintData<Color, Traits, domain> *vpd,
{
using Blend = typename Traits::BlendType;
+ const blender::VArray<bool> select_vert = me->attributes().lookup_or_default<bool>(
+ ".select_vert", ATTR_DOMAIN_POINT, false);
+
VPaintAverageAccum<Blend> *accum = (VPaintAverageAccum<Blend> *)MEM_mallocN(
sizeof(*accum) * totnode, __func__);
blender::threading::parallel_for(IndexRange(totnode), 1LL, [&](IndexRange range) {
@@ -3443,8 +3466,7 @@ static void calculate_average_color(VPaintData<Color, Traits, domain> *vpd,
vd.vert_indices[vd.i];
if (BKE_brush_curve_strength(brush, 0.0, cache->radius) > 0.0) {
/* If the vertex is selected for painting. */
- const MVert *mv = &ss->mvert[v_index];
- if (!use_vert_sel || mv->flag & SELECT) {
+ if (!use_vert_sel || select_vert[v_index]) {
accum2->len += gmap->vert_to_loop[v_index].count;
/* if a vertex is within the brush region, then add its color to the blend. */
for (int j = 0; j < gmap->vert_to_loop[v_index].count; j++) {
@@ -3512,7 +3534,7 @@ static float paint_and_tex_color_alpha(VPaint *vp,
template<typename Color, typename Traits, eAttrDomain domain>
static void vpaint_do_draw(bContext *C,
- Sculpt *UNUSED(sd),
+ Sculpt * /*sd*/,
VPaint *vp,
VPaintData<Color, Traits, domain> *vpd,
Object *ob,
@@ -3529,6 +3551,11 @@ static void vpaint_do_draw(bContext *C,
Color *previous_color = static_cast<Color *>(ss->cache->prev_colors_vpaint);
+ const blender::VArray<bool> select_vert = me->attributes().lookup_or_default<bool>(
+ ".select_vert", ATTR_DOMAIN_POINT, false);
+ const blender::VArray<bool> select_poly = me->attributes().lookup_or_default<bool>(
+ ".select_poly", ATTR_DOMAIN_FACE, false);
+
blender::threading::parallel_for(IndexRange(totnode), 1LL, [&](IndexRange range) {
for (int n : range) {
const bool has_grids = (pbvh_type == PBVH_GRIDS);
@@ -3562,10 +3589,9 @@ static void vpaint_do_draw(bContext *C,
const int v_index = has_grids ? ss->mloop[vd.grid_indices[vd.g]].v :
vd.vert_indices[vd.i];
const float grid_alpha = has_grids ? 1.0f / vd.gridsize : 1.0f;
- const MVert *mv = &ss->mvert[v_index];
/* If the vertex is selected for painting. */
- if (!use_vert_sel || mv->flag & SELECT) {
+ if (!use_vert_sel || select_vert[v_index]) {
/* Calc the dot prod. between ray norm on surf and current vert
* (ie splash prevention factor), and only paint front facing verts. */
float brush_strength = cache->bstrength;
@@ -3617,8 +3643,7 @@ static void vpaint_do_draw(bContext *C,
const int p_index = gmap->vert_to_poly[v_index].indices[j];
const int l_index = gmap->vert_to_loop[v_index].indices[j];
BLI_assert(ss->mloop[l_index].v == v_index);
- const MPoly *mp = &ss->mpoly[p_index];
- if (!use_face_sel || mp->flag & ME_FACE_SEL) {
+ if (!use_face_sel || select_poly[p_index]) {
Color color_orig = Color(0, 0, 0, 0); /* unused when array is nullptr */
if (previous_color != nullptr) {
@@ -3778,7 +3803,7 @@ static void vpaint_do_symmetrical_brush_actions(
/* symm is a bit combination of XYZ - 1 is mirror
* X; 2 is Y; 3 is XY; 4 is Z; 5 is XZ; 6 is YZ; 7 is XYZ */
for (i = 1; i <= symm; i++) {
- if (symm & i && (symm != 5 || i != 3) && (symm != 6 || (!ELEM(i, 3, 5)))) {
+ if (symm & i && (symm != 5 || i != 3) && (symm != 6 || !ELEM(i, 3, 5))) {
cache->mirror_symmetry_pass = i;
cache->radial_symmetry_pass = 0;
SCULPT_cache_calc_brushdata_symm(cache, i, 0, 0);
@@ -3822,7 +3847,7 @@ static void vpaint_stroke_update_step_intern(bContext *C, PaintStroke *stroke, P
ED_view3d_init_mats_rv3d(ob, vc->rv3d);
/* load projection matrix */
- mul_m4_m4m4(mat, vc->rv3d->persmat, ob->obmat);
+ mul_m4_m4m4(mat, vc->rv3d->persmat, ob->object_to_world);
swap_m4m4(vc->rv3d->persmat, mat);
@@ -3845,7 +3870,7 @@ static void vpaint_stroke_update_step_intern(bContext *C, PaintStroke *stroke, P
/* Calculate pivot for rotation around selection if needed.
* also needed for "Frame Selected" on last stroke. */
float loc_world[3];
- mul_v3_m4v3(loc_world, ob->obmat, ss->cache->true_location);
+ mul_v3_m4v3(loc_world, ob->object_to_world, ss->cache->true_location);
paint_last_stroke_update(scene, loc_world);
ED_region_tag_redraw(vc->region);
@@ -3854,7 +3879,7 @@ static void vpaint_stroke_update_step_intern(bContext *C, PaintStroke *stroke, P
}
static void vpaint_stroke_update_step(bContext *C,
- wmOperator *UNUSED(op),
+ wmOperator * /*op*/,
PaintStroke *stroke,
PointerRNA *itemptr)
{
@@ -3883,7 +3908,7 @@ static void vpaint_stroke_update_step(bContext *C,
}
template<typename Color, typename Traits, eAttrDomain domain>
-static void vpaint_free_vpaintdata(Object *UNUSED(ob), void *_vpd)
+static void vpaint_free_vpaintdata(Object * /*ob*/, void *_vpd)
{
VPaintData<Color, Traits, domain> *vpd = static_cast<VPaintData<Color, Traits, domain> *>(_vpd);
@@ -4045,6 +4070,11 @@ static bool vertex_color_set(Object *ob, ColorPaint4f paintcol_in, CustomDataLay
return false;
}
+ const blender::VArray<bool> select_vert = me->attributes().lookup_or_default<bool>(
+ ".select_vert", ATTR_DOMAIN_POINT, false);
+ const blender::VArray<bool> select_poly = me->attributes().lookup_or_default<bool>(
+ ".select_poly", ATTR_DOMAIN_FACE, false);
+
Color paintcol = fromFloat<Color>(paintcol_in);
const bool use_face_sel = (me->editflag & ME_EDIT_PAINT_FACE_SEL) != 0;
@@ -4073,7 +4103,7 @@ static bool vertex_color_set(Object *ob, ColorPaint4f paintcol_in, CustomDataLay
BMLoop *l = f->l_first;
do {
- if (!(use_vert_sel && !(BM_elem_flag_test(l->v, BM_ELEM_SELECT)))) {
+ if (!(use_vert_sel && !BM_elem_flag_test(l->v, BM_ELEM_SELECT))) {
if constexpr (domain == ATTR_DOMAIN_CORNER) {
color = static_cast<Color *>(BM_ELEM_CD_GET_VOID_P(l, cd_offset));
}
@@ -4088,21 +4118,20 @@ static bool vertex_color_set(Object *ob, ColorPaint4f paintcol_in, CustomDataLay
}
else {
Color *color_layer = static_cast<Color *>(layer->data);
- const Span<MVert> verts = me->verts();
const Span<MPoly> polys = me->polys();
const Span<MLoop> loops = me->loops();
for (const int i : polys.index_range()) {
- const MPoly &poly = polys[i];
- if (use_face_sel && !(poly.flag & ME_FACE_SEL)) {
+ if (use_face_sel && !select_poly[i]) {
continue;
}
+ const MPoly &poly = polys[i];
int j = 0;
do {
uint vidx = loops[poly.loopstart + j].v;
- if (!(use_vert_sel && !(verts[vidx].flag & SELECT))) {
+ if (!(use_vert_sel && !(select_vert[vidx]))) {
if constexpr (domain == ATTR_DOMAIN_CORNER) {
color_layer[poly.loopstart + j] = paintcol;
}
@@ -4177,7 +4206,7 @@ extern "C" bool BKE_object_attributes_active_color_fill(Object *ob,
return paint_object_attributes_active_color_fill_ex(ob, ColorPaint4f(fill_color), only_selected);
}
-static int vertex_color_set_exec(bContext *C, wmOperator *UNUSED(op))
+static int vertex_color_set_exec(bContext *C, wmOperator * /*op*/)
{
Scene *scene = CTX_data_scene(C);
Object *obact = CTX_data_active_object(C);
diff --git a/source/blender/editors/sculpt_paint/paint_vertex_color_ops.cc b/source/blender/editors/sculpt_paint/paint_vertex_color_ops.cc
index 10ad4c2192f..09374422888 100644
--- a/source/blender/editors/sculpt_paint/paint_vertex_color_ops.cc
+++ b/source/blender/editors/sculpt_paint/paint_vertex_color_ops.cc
@@ -49,7 +49,7 @@ static bool vertex_weight_paint_mode_poll(bContext *C)
{
Object *ob = CTX_data_active_object(C);
Mesh *me = BKE_mesh_from_object(ob);
- return (ob && (ELEM(ob->mode, OB_MODE_VERTEX_PAINT, OB_MODE_WEIGHT_PAINT))) &&
+ return (ob && ELEM(ob->mode, OB_MODE_VERTEX_PAINT, OB_MODE_WEIGHT_PAINT)) &&
(me && me->totpoly && !me->deform_verts().is_empty());
}
@@ -73,8 +73,7 @@ static bool vertex_paint_from_weight(Object *ob)
using namespace blender;
Mesh *me;
- if (((me = BKE_mesh_from_object(ob)) == nullptr ||
- (ED_mesh_color_ensure(me, nullptr)) == false)) {
+ if ((me = BKE_mesh_from_object(ob)) == nullptr || ED_mesh_color_ensure(me, nullptr) == false) {
return false;
}
@@ -121,7 +120,7 @@ static bool vertex_paint_from_weight(Object *ob)
return true;
}
-static int vertex_paint_from_weight_exec(bContext *C, wmOperator *UNUSED(op))
+static int vertex_paint_from_weight_exec(bContext *C, wmOperator * /*op*/)
{
Object *obact = CTX_data_active_object(C);
if (vertex_paint_from_weight(obact)) {
@@ -159,29 +158,19 @@ static IndexMask get_selected_indices(const Mesh &mesh,
Vector<int64_t> &indices)
{
using namespace blender;
- const Span<MVert> verts = mesh.verts();
- const Span<MPoly> polys = mesh.polys();
-
- bke::AttributeAccessor attributes = mesh.attributes();
+ const bke::AttributeAccessor attributes = mesh.attributes();
if (mesh.editflag & ME_EDIT_PAINT_FACE_SEL) {
- const VArray<bool> selection = attributes.adapt_domain(
- VArray<bool>::ForFunc(polys.size(),
- [&](const int i) { return polys[i].flag & ME_FACE_SEL; }),
- ATTR_DOMAIN_FACE,
- domain);
-
+ const VArray<bool> selection = attributes.lookup_or_default<bool>(
+ ".select_poly", ATTR_DOMAIN_FACE, false);
return index_mask_ops::find_indices_from_virtual_array(
- IndexMask(attributes.domain_size(domain)), selection, 4096, indices);
+ selection.index_range(), selection, 4096, indices);
}
if (mesh.editflag & ME_EDIT_PAINT_VERT_SEL) {
- const VArray<bool> selection = attributes.adapt_domain(
- VArray<bool>::ForFunc(verts.size(), [&](const int i) { return verts[i].flag & SELECT; }),
- ATTR_DOMAIN_POINT,
- domain);
-
+ const VArray<bool> selection = attributes.lookup_or_default<bool>(
+ ".select_vert", ATTR_DOMAIN_POINT, false);
return index_mask_ops::find_indices_from_virtual_array(
- IndexMask(attributes.domain_size(domain)), selection, 4096, indices);
+ selection.index_range(), selection, 4096, indices);
}
return IndexMask(attributes.domain_size(domain));
}
@@ -228,7 +217,7 @@ static bool vertex_color_smooth(Object *ob)
return true;
}
-static int vertex_color_smooth_exec(bContext *C, wmOperator *UNUSED(op))
+static int vertex_color_smooth_exec(bContext *C, wmOperator * /*op*/)
{
Object *obact = CTX_data_active_object(C);
if (vertex_color_smooth(obact)) {
@@ -320,7 +309,7 @@ static int vertex_color_brightness_contrast_exec(bContext *C, wmOperator *op)
/*
* The algorithm is by Werner D. Streidt
* (http://visca.com/ffactory/archives/5-99/msg00021.html)
- * Extracted of OpenCV demhist.c
+ * Extracted of OpenCV `demhist.c`.
*/
if (contrast > 0) {
gain = 1.0f - delta * 2.0f;
@@ -430,7 +419,7 @@ void PAINT_OT_vertex_color_hsv(wmOperatorType *ot)
RNA_def_float(ot->srna, "v", 1.0f, 0.0f, 2.0f, "Value", "", 0.0f, 2.0f);
}
-static int vertex_color_invert_exec(bContext *C, wmOperator *UNUSED(op))
+static int vertex_color_invert_exec(bContext *C, wmOperator * /*op*/)
{
Object *obact = CTX_data_active_object(C);
diff --git a/source/blender/editors/sculpt_paint/paint_vertex_proj.c b/source/blender/editors/sculpt_paint/paint_vertex_proj.c
index b4e2d4901c9..bac3e7a9e52 100644
--- a/source/blender/editors/sculpt_paint/paint_vertex_proj.c
+++ b/source/blender/editors/sculpt_paint/paint_vertex_proj.c
@@ -10,7 +10,6 @@
#include "MEM_guardedalloc.h"
-#include "BLI_listbase.h"
#include "BLI_math.h"
#include "DNA_mesh_types.h"
diff --git a/source/blender/editors/sculpt_paint/paint_vertex_weight_ops.c b/source/blender/editors/sculpt_paint/paint_vertex_weight_ops.c
index 0a0d7cff214..fca25ee2e4b 100644
--- a/source/blender/editors/sculpt_paint/paint_vertex_weight_ops.c
+++ b/source/blender/editors/sculpt_paint/paint_vertex_weight_ops.c
@@ -7,7 +7,6 @@
#include "MEM_guardedalloc.h"
#include "BLI_bitmap.h"
-#include "BLI_blenlib.h"
#include "BLI_math.h"
#include "DNA_brush_types.h"
@@ -445,7 +444,6 @@ static bool weight_paint_set(Object *ob, float paintweight)
/* mutually exclusive, could be made into a */
const short paint_selmode = ME_EDIT_PAINT_SEL_MODE(me);
- const MVert *verts = BKE_mesh_verts(me);
const MPoly *polys = BKE_mesh_polys(me);
const MLoop *loops = BKE_mesh_loops(me);
MDeformVert *dvert = BKE_mesh_deform_verts_for_write(me);
@@ -464,10 +462,15 @@ static bool weight_paint_set(Object *ob, float paintweight)
struct WPaintPrev wpp;
wpaint_prev_create(&wpp, dvert, me->totvert);
+ const bool *select_vert = (const bool *)CustomData_get_layer_named(
+ &me->vdata, CD_PROP_BOOL, ".select_vert");
+ const bool *select_poly = (const bool *)CustomData_get_layer_named(
+ &me->pdata, CD_PROP_BOOL, ".select_poly");
+
for (index = 0, mp = polys; index < me->totpoly; index++, mp++) {
uint fidx = mp->totloop - 1;
- if ((paint_selmode == SCE_SELECT_FACE) && !(mp->flag & ME_FACE_SEL)) {
+ if ((paint_selmode == SCE_SELECT_FACE) && !(select_poly && select_poly[index])) {
continue;
}
@@ -475,7 +478,7 @@ static bool weight_paint_set(Object *ob, float paintweight)
uint vidx = loops[mp->loopstart + fidx].v;
if (!dvert[vidx].flag) {
- if ((paint_selmode == SCE_SELECT_VERTEX) && !(verts[vidx].flag & SELECT)) {
+ if ((paint_selmode == SCE_SELECT_VERTEX) && !(select_vert && select_vert[vidx])) {
continue;
}
diff --git a/source/blender/editors/sculpt_paint/paint_vertex_weight_utils.c b/source/blender/editors/sculpt_paint/paint_vertex_weight_utils.c
index ac16631f115..9ab36fe1402 100644
--- a/source/blender/editors/sculpt_paint/paint_vertex_weight_utils.c
+++ b/source/blender/editors/sculpt_paint/paint_vertex_weight_utils.c
@@ -203,7 +203,7 @@ BLI_INLINE float wval_screen(float weight, float paintval, float fac)
return weight;
}
mfac = 1.0f - fac;
- temp = max_ff(1.0f - (((1.0f - weight) * (1.0f - paintval))), 0);
+ temp = max_ff(1.0f - ((1.0f - weight) * (1.0f - paintval)), 0);
return mfac * weight + temp * fac;
}
BLI_INLINE float wval_hardlight(float weight, float paintval, float fac)
@@ -258,7 +258,7 @@ BLI_INLINE float wval_exclusion(float weight, float paintval, float fac)
return weight;
}
mfac = 1.0f - fac;
- temp = 0.5f - ((2.0f * (weight - 0.5f) * (paintval - 0.5f)));
+ temp = 0.5f - (2.0f * (weight - 0.5f) * (paintval - 0.5f));
return temp * fac + weight * mfac;
}
diff --git a/source/blender/editors/sculpt_paint/sculpt.c b/source/blender/editors/sculpt_paint/sculpt.c
index 65e69bd8761..3477285814e 100644
--- a/source/blender/editors/sculpt_paint/sculpt.c
+++ b/source/blender/editors/sculpt_paint/sculpt.c
@@ -12,17 +12,10 @@
#include "BLI_dial_2d.h"
#include "BLI_ghash.h"
#include "BLI_gsqueue.h"
-#include "BLI_hash.h"
#include "BLI_math.h"
-#include "BLI_math_color.h"
-#include "BLI_math_color_blend.h"
#include "BLI_task.h"
#include "BLI_utildefines.h"
-#include "BLT_translation.h"
-
-#include "PIL_time.h"
-
#include "DNA_brush_types.h"
#include "DNA_customdata_types.h"
#include "DNA_mesh_types.h"
@@ -37,24 +30,18 @@
#include "BKE_colortools.h"
#include "BKE_context.h"
#include "BKE_image.h"
-#include "BKE_kelvinlet.h"
#include "BKE_key.h"
#include "BKE_lib_id.h"
#include "BKE_main.h"
#include "BKE_mesh.h"
#include "BKE_mesh_mapping.h"
-#include "BKE_mesh_mirror.h"
#include "BKE_modifier.h"
#include "BKE_multires.h"
-#include "BKE_node.h"
#include "BKE_object.h"
#include "BKE_paint.h"
-#include "BKE_particle.h"
#include "BKE_pbvh.h"
-#include "BKE_pointcache.h"
#include "BKE_report.h"
#include "BKE_scene.h"
-#include "BKE_screen.h"
#include "BKE_subdiv_ccg.h"
#include "BKE_subsurf.h"
@@ -62,29 +49,21 @@
#include "DEG_depsgraph.h"
-#include "IMB_colormanagement.h"
-
#include "WM_api.h"
-#include "WM_message.h"
-#include "WM_toolsystem.h"
#include "WM_types.h"
-#include "ED_object.h"
#include "ED_paint.h"
#include "ED_screen.h"
#include "ED_sculpt.h"
#include "ED_view3d.h"
+
#include "paint_intern.h"
#include "sculpt_intern.h"
#include "RNA_access.h"
#include "RNA_define.h"
-#include "UI_interface.h"
-#include "UI_resources.h"
-
#include "bmesh.h"
-#include "bmesh_tools.h"
#include <math.h>
#include <stdlib.h>
@@ -194,9 +173,10 @@ void SCULPT_vertex_normal_get(SculptSession *ss, PBVHVertRef vertex, float no[3]
const float *SCULPT_vertex_persistent_co_get(SculptSession *ss, PBVHVertRef vertex)
{
- if (ss->persistent_base) {
- return ss->persistent_base[BKE_pbvh_vertex_to_index(ss->pbvh, vertex)].co;
+ if (ss->attrs.persistent_co) {
+ return (const float *)SCULPT_vertex_attr_get(vertex, ss->attrs.persistent_co);
}
+
return SCULPT_vertex_co_get(ss, vertex);
}
@@ -240,8 +220,8 @@ void SCULPT_vertex_limit_surface_get(SculptSession *ss, PBVHVertRef vertex, floa
void SCULPT_vertex_persistent_normal_get(SculptSession *ss, PBVHVertRef vertex, float no[3])
{
- if (ss->persistent_base) {
- copy_v3_v3(no, ss->persistent_base[vertex.i].no);
+ if (ss->attrs.persistent_no) {
+ copy_v3_v3(no, (float *)SCULPT_vertex_attr_get(vertex, ss->attrs.persistent_no));
return;
}
SCULPT_vertex_normal_get(ss, vertex, no);
@@ -249,15 +229,16 @@ void SCULPT_vertex_persistent_normal_get(SculptSession *ss, PBVHVertRef vertex,
float SCULPT_vertex_mask_get(SculptSession *ss, PBVHVertRef vertex)
{
- BMVert *v;
- float *mask;
switch (BKE_pbvh_type(ss->pbvh)) {
case PBVH_FACES:
return ss->vmask ? ss->vmask[vertex.i] : 0.0f;
- case PBVH_BMESH:
+ case PBVH_BMESH: {
+ BMVert *v;
+ int cd_mask = CustomData_get_offset(&ss->bm->vdata, CD_PAINT_MASK);
+
v = (BMVert *)vertex.i;
- mask = BM_ELEM_CD_GET_VOID_P(v, CustomData_get_offset(&ss->bm->vdata, CD_PAINT_MASK));
- return mask ? *mask : 0.0f;
+ return cd_mask != -1 ? BM_ELEM_CD_GET_FLOAT(v, cd_mask) : 0.0f;
+ }
case PBVH_GRIDS: {
const CCGKey *key = BKE_pbvh_get_grid_key(ss->pbvh);
const int grid_index = vertex.i / key->grid_area;
@@ -390,19 +371,15 @@ bool SCULPT_vertex_visible_get(SculptSession *ss, PBVHVertRef vertex)
void SCULPT_face_set_visibility_set(SculptSession *ss, int face_set, bool visible)
{
BLI_assert(ss->face_sets != NULL);
+ BLI_assert(ss->hide_poly != NULL);
switch (BKE_pbvh_type(ss->pbvh)) {
case PBVH_FACES:
case PBVH_GRIDS:
for (int i = 0; i < ss->totfaces; i++) {
- if (abs(ss->face_sets[i]) != face_set) {
+ if (ss->face_sets[i] != face_set) {
continue;
}
- if (visible) {
- ss->face_sets[i] = abs(ss->face_sets[i]);
- }
- else {
- ss->face_sets[i] = -abs(ss->face_sets[i]);
- }
+ ss->hide_poly[i] = !visible;
}
break;
case PBVH_BMESH:
@@ -410,62 +387,59 @@ void SCULPT_face_set_visibility_set(SculptSession *ss, int face_set, bool visibl
}
}
-void SCULPT_face_sets_visibility_invert(SculptSession *ss)
+void SCULPT_face_visibility_all_invert(SculptSession *ss)
{
BLI_assert(ss->face_sets != NULL);
+ BLI_assert(ss->hide_poly != NULL);
switch (BKE_pbvh_type(ss->pbvh)) {
case PBVH_FACES:
case PBVH_GRIDS:
for (int i = 0; i < ss->totfaces; i++) {
- ss->face_sets[i] *= -1;
+ ss->hide_poly[i] = !ss->hide_poly[i];
}
break;
- case PBVH_BMESH:
+ case PBVH_BMESH: {
+ BMIter iter;
+ BMFace *f;
+
+ BM_ITER_MESH (f, &iter, ss->bm, BM_FACES_OF_MESH) {
+ BM_elem_flag_toggle(f, BM_ELEM_HIDDEN);
+ }
break;
+ }
}
}
-void SCULPT_face_sets_visibility_all_set(SculptSession *ss, bool visible)
+void SCULPT_face_visibility_all_set(SculptSession *ss, bool visible)
{
switch (BKE_pbvh_type(ss->pbvh)) {
case PBVH_FACES:
case PBVH_GRIDS:
- if (!ss->face_sets) {
- return;
- }
- for (int i = 0; i < ss->totfaces; i++) {
-
- /* 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 (ss->face_sets[i] == SCULPT_FACE_SET_NONE) {
- ss->face_sets[i] = 1;
- }
+ BLI_assert(ss->hide_poly != NULL);
+ memset(ss->hide_poly, !visible, sizeof(bool) * ss->totfaces);
+ break;
+ case PBVH_BMESH: {
+ BMIter iter;
+ BMFace *f;
- if (visible) {
- ss->face_sets[i] = abs(ss->face_sets[i]);
- }
- else {
- ss->face_sets[i] = -abs(ss->face_sets[i]);
- }
+ BM_ITER_MESH (f, &iter, ss->bm, BM_FACES_OF_MESH) {
+ BM_elem_flag_set(f, BM_ELEM_HIDDEN, !visible);
}
break;
- case PBVH_BMESH:
- break;
+ }
}
}
-bool SCULPT_vertex_any_face_set_visible_get(SculptSession *ss, PBVHVertRef vertex)
+bool SCULPT_vertex_any_face_visible_get(SculptSession *ss, PBVHVertRef vertex)
{
- const bool *hide_poly = BKE_pbvh_get_poly_hide(ss->pbvh);
- if (!hide_poly) {
- return true;
- }
switch (BKE_pbvh_type(ss->pbvh)) {
case PBVH_FACES: {
- MeshElemMap *vert_map = &ss->pmap[vertex.i];
+ if (!ss->hide_poly) {
+ return true;
+ }
+ const MeshElemMap *vert_map = &ss->pmap[vertex.i];
for (int j = 0; j < ss->pmap[vertex.i].count; j++) {
- if (!hide_poly[vert_map->indices[j]]) {
+ if (!ss->hide_poly[vert_map->indices[j]]) {
return true;
}
}
@@ -479,29 +453,53 @@ bool SCULPT_vertex_any_face_set_visible_get(SculptSession *ss, PBVHVertRef verte
return true;
}
-bool SCULPT_vertex_all_face_sets_visible_get(const SculptSession *ss, PBVHVertRef vertex)
+bool SCULPT_vertex_all_faces_visible_get(const SculptSession *ss, PBVHVertRef vertex)
{
- const bool *hide_poly = BKE_pbvh_get_poly_hide(ss->pbvh);
- if (!hide_poly) {
- return true;
- }
switch (BKE_pbvh_type(ss->pbvh)) {
case PBVH_FACES: {
- MeshElemMap *vert_map = &ss->pmap[vertex.i];
- for (int j = 0; j < ss->pmap[vertex.i].count; j++) {
- if (hide_poly[vert_map->indices[j]]) {
+ if (!ss->hide_poly) {
+ return true;
+ }
+ const MeshElemMap *vert_map = &ss->pmap[vertex.i];
+ for (int j = 0; j < vert_map->count; j++) {
+ if (ss->hide_poly[vert_map->indices[j]]) {
return false;
}
}
return true;
}
- case PBVH_BMESH:
+ case PBVH_BMESH: {
+ BMVert *v = (BMVert *)vertex.i;
+ BMEdge *e = v->e;
+
+ if (!e) {
+ return true;
+ }
+
+ do {
+ BMLoop *l = e->l;
+
+ if (!l) {
+ continue;
+ }
+
+ do {
+ if (BM_elem_flag_test(l->f, BM_ELEM_HIDDEN)) {
+ return false;
+ }
+ } while ((l = l->radial_next) != e->l);
+ } while ((e = BM_DISK_EDGE_NEXT(e, v)) != v->e);
+
return true;
+ }
case PBVH_GRIDS: {
+ if (!ss->hide_poly) {
+ return true;
+ }
const CCGKey *key = BKE_pbvh_get_grid_key(ss->pbvh);
const int grid_index = vertex.i / key->grid_area;
const int face_index = BKE_subdiv_ccg_grid_to_face_index(ss->subdiv_ccg, grid_index);
- return !hide_poly[face_index];
+ return !ss->hide_poly[face_index];
}
}
return true;
@@ -512,13 +510,17 @@ void SCULPT_vertex_face_set_set(SculptSession *ss, PBVHVertRef vertex, int face_
switch (BKE_pbvh_type(ss->pbvh)) {
case PBVH_FACES: {
BLI_assert(ss->face_sets != NULL);
- MeshElemMap *vert_map = &ss->pmap[vertex.i];
- for (int j = 0; j < ss->pmap[vertex.i].count; j++) {
- if (ss->face_sets[vert_map->indices[j]] > 0) {
- ss->face_sets[vert_map->indices[j]] = abs(face_set);
+ const MeshElemMap *vert_map = &ss->pmap[vertex.i];
+ for (int j = 0; j < vert_map->count; j++) {
+ const int poly_index = vert_map->indices[j];
+ if (ss->hide_poly && ss->hide_poly[poly_index]) {
+ /* Skip hidden faces connected to the vertex. */
+ continue;
}
+ ss->face_sets[poly_index] = face_set;
}
- } break;
+ break;
+ }
case PBVH_BMESH:
break;
case PBVH_GRIDS: {
@@ -526,11 +528,13 @@ void SCULPT_vertex_face_set_set(SculptSession *ss, PBVHVertRef vertex, int face_
const CCGKey *key = BKE_pbvh_get_grid_key(ss->pbvh);
const int grid_index = vertex.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);
+ if (ss->hide_poly && ss->hide_poly[face_index]) {
+ /* Skip the vertex if it's in a hidden face. */
+ return;
}
-
- } break;
+ ss->face_sets[face_index] = face_set;
+ break;
+ }
}
}
@@ -541,9 +545,9 @@ int SCULPT_vertex_face_set_get(SculptSession *ss, PBVHVertRef vertex)
if (!ss->face_sets) {
return SCULPT_FACE_SET_NONE;
}
- MeshElemMap *vert_map = &ss->pmap[vertex.i];
+ const MeshElemMap *vert_map = &ss->pmap[vertex.i];
int face_set = 0;
- for (int i = 0; i < ss->pmap[vertex.i].count; i++) {
+ for (int i = 0; i < vert_map->count; i++) {
if (ss->face_sets[vert_map->indices[i]] > face_set) {
face_set = abs(ss->face_sets[vert_map->indices[i]]);
}
@@ -572,8 +576,8 @@ bool SCULPT_vertex_has_face_set(SculptSession *ss, PBVHVertRef vertex, int face_
if (!ss->face_sets) {
return face_set == SCULPT_FACE_SET_NONE;
}
- MeshElemMap *vert_map = &ss->pmap[vertex.i];
- for (int i = 0; i < ss->pmap[vertex.i].count; i++) {
+ const MeshElemMap *vert_map = &ss->pmap[vertex.i];
+ for (int i = 0; i < vert_map->count; i++) {
if (ss->face_sets[vert_map->indices[i]] == face_set) {
return true;
}
@@ -595,61 +599,51 @@ bool SCULPT_vertex_has_face_set(SculptSession *ss, PBVHVertRef vertex, int face_
return true;
}
-void SCULPT_visibility_sync_all_face_sets_to_verts(Object *ob)
+void SCULPT_visibility_sync_all_from_faces(Object *ob)
{
SculptSession *ss = ob->sculpt;
Mesh *mesh = BKE_object_get_original_mesh(ob);
switch (BKE_pbvh_type(ss->pbvh)) {
case PBVH_FACES: {
- BKE_sculpt_sync_face_sets_visibility_to_base_mesh(mesh);
+ /* We may have adjusted the ".hide_poly" attribute, now make the hide status attributes for
+ * vertices and edges consistent. */
+ BKE_mesh_flush_hidden_from_polys(mesh);
+ BKE_pbvh_update_hide_attributes_from_mesh(ss->pbvh);
break;
}
case PBVH_GRIDS: {
- BKE_sculpt_sync_face_sets_visibility_to_base_mesh(mesh);
- BKE_sculpt_sync_face_sets_visibility_to_grids(mesh, ss->subdiv_ccg);
- break;
- }
- case PBVH_BMESH:
+ /* In addition to making the hide status of the base mesh consistent, we also have to
+ * propagate the status to the Multires grids. */
+ BKE_mesh_flush_hidden_from_polys(mesh);
+ BKE_sculpt_sync_face_visibility_to_grids(mesh, ss->subdiv_ccg);
break;
- }
-}
-
-static void UNUSED_FUNCTION(sculpt_visibility_sync_vertex_to_face_sets)(SculptSession *ss,
- PBVHVertRef vertex)
-{
- MeshElemMap *vert_map = &ss->pmap[vertex.i];
- const bool visible = SCULPT_vertex_visible_get(ss, vertex);
- for (int i = 0; i < ss->pmap[vertex.i].count; i++) {
- if (visible) {
- ss->face_sets[vert_map->indices[i]] = abs(ss->face_sets[vert_map->indices[i]]);
- }
- else {
- ss->face_sets[vert_map->indices[i]] = -abs(ss->face_sets[vert_map->indices[i]]);
}
- }
-}
+ case PBVH_BMESH: {
+ BMIter iter;
+ BMFace *f;
+
+ /* Hide all verts and edges attached to faces.*/
+ BM_ITER_MESH (f, &iter, ss->bm, BM_FACES_OF_MESH) {
+ BMLoop *l = f->l_first;
+ do {
+ BM_elem_flag_enable(l->v, BM_ELEM_HIDDEN);
+ BM_elem_flag_enable(l->e, BM_ELEM_HIDDEN);
+ } while ((l = l->next) != f->l_first);
+ }
-void SCULPT_visibility_sync_all_vertex_to_face_sets(SculptSession *ss)
-{
- if (BKE_pbvh_type(ss->pbvh) == PBVH_FACES) {
- if (ss->face_sets == NULL) {
- return;
- }
- for (int i = 0; i < ss->totfaces; i++) {
- const MPoly *poly = &ss->mpoly[i];
- bool poly_visible = true;
- for (int l = 0; l < poly->totloop; l++) {
- const MLoop *loop = &ss->mloop[poly->loopstart + l];
- if (!SCULPT_vertex_visible_get(ss, BKE_pbvh_make_vref(loop->v))) {
- poly_visible = false;
+ /* Unhide verts and edges attached to visible faces. */
+ BM_ITER_MESH (f, &iter, ss->bm, BM_FACES_OF_MESH) {
+ if (BM_elem_flag_test(f, BM_ELEM_HIDDEN)) {
+ continue;
}
+
+ BMLoop *l = f->l_first;
+ do {
+ BM_elem_flag_disable(l->v, BM_ELEM_HIDDEN);
+ BM_elem_flag_disable(l->e, BM_ELEM_HIDDEN);
+ } while ((l = l->next) != f->l_first);
}
- if (poly_visible) {
- ss->face_sets[i] = abs(ss->face_sets[i]);
- }
- else {
- ss->face_sets[i] = -abs(ss->face_sets[i]);
- }
+ break;
}
}
}
@@ -659,14 +653,14 @@ static bool sculpt_check_unique_face_set_in_base_mesh(SculptSession *ss, int ind
if (!ss->face_sets) {
return true;
}
- MeshElemMap *vert_map = &ss->pmap[index];
+ const MeshElemMap *vert_map = &ss->pmap[index];
int face_set = -1;
- for (int i = 0; i < ss->pmap[index].count; i++) {
+ for (int i = 0; i < vert_map->count; i++) {
if (face_set == -1) {
- face_set = abs(ss->face_sets[vert_map->indices[i]]);
+ face_set = ss->face_sets[vert_map->indices[i]];
}
else {
- if (abs(ss->face_sets[vert_map->indices[i]]) != face_set) {
+ if (ss->face_sets[vert_map->indices[i]] != face_set) {
return false;
}
}
@@ -680,9 +674,9 @@ static bool sculpt_check_unique_face_set_in_base_mesh(SculptSession *ss, int ind
*/
static bool sculpt_check_unique_face_set_for_edge_in_base_mesh(SculptSession *ss, int v1, int v2)
{
- MeshElemMap *vert_map = &ss->pmap[v1];
+ const MeshElemMap *vert_map = &ss->pmap[v1];
int p1 = -1, p2 = -1;
- for (int i = 0; i < ss->pmap[v1].count; i++) {
+ for (int i = 0; i < vert_map->count; i++) {
const MPoly *p = &ss->mpoly[vert_map->indices[i]];
for (int l = 0; l < p->totloop; l++) {
const MLoop *loop = &ss->mloop[p->loopstart + l];
@@ -750,8 +744,8 @@ int SCULPT_face_set_next_available_get(SculptSession *ss)
}
int next_face_set = 0;
for (int i = 0; i < ss->totfaces; i++) {
- if (abs(ss->face_sets[i]) > next_face_set) {
- next_face_set = abs(ss->face_sets[i]);
+ if (ss->face_sets[i] > next_face_set) {
+ next_face_set = ss->face_sets[i];
}
}
next_face_set++;
@@ -831,21 +825,20 @@ static void sculpt_vertex_neighbors_get_faces(SculptSession *ss,
PBVHVertRef vertex,
SculptVertexNeighborIter *iter)
{
- MeshElemMap *vert_map = &ss->pmap[vertex.i];
+ const MeshElemMap *vert_map = &ss->pmap[vertex.i];
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;
- const bool *hide_poly = BKE_pbvh_get_vert_hide(ss->pbvh);
- for (int i = 0; i < ss->pmap[vertex.i].count; i++) {
- if (hide_poly && hide_poly[vert_map->indices[i]]) {
+ for (int i = 0; i < vert_map->count; i++) {
+ if (ss->hide_poly && ss->hide_poly[vert_map->indices[i]]) {
/* Skip connectivity from hidden faces. */
continue;
}
const MPoly *p = &ss->mpoly[vert_map->indices[i]];
- uint f_adj_v[2];
+ int f_adj_v[2];
if (poly_get_adj_loops_from_vert(p, ss->mloop, vertex.i, f_adj_v) != -1) {
for (int j = 0; j < ARRAY_SIZE(f_adj_v); j += 1) {
if (f_adj_v[j] != vertex.i) {
@@ -939,7 +932,7 @@ bool SCULPT_vertex_is_boundary(const SculptSession *ss, const PBVHVertRef vertex
{
switch (BKE_pbvh_type(ss->pbvh)) {
case PBVH_FACES: {
- if (!SCULPT_vertex_all_face_sets_visible_get(ss, vertex)) {
+ if (!SCULPT_vertex_all_faces_visible_get(ss, vertex)) {
return true;
}
return sculpt_check_boundary_vertex_in_base_mesh(ss, vertex.i);
@@ -1097,7 +1090,7 @@ PBVHVertRef SCULPT_nearest_vertex_get(
bool SCULPT_is_symmetry_iteration_valid(char i, char symm)
{
- return i == 0 || (symm & i && (symm != 5 || i != 3) && (symm != 6 || (!ELEM(i, 3, 5))));
+ return i == 0 || (symm & i && (symm != 5 || i != 3) && (symm != 6 || !ELEM(i, 3, 5)));
}
bool SCULPT_is_vertex_inside_brush_radius_symm(const float vertex[3],
@@ -1128,8 +1121,8 @@ void SCULPT_tag_update_overlays(bContext *C)
DEG_id_tag_update(&ob->id, ID_RECALC_SHADING);
- View3D *v3d = CTX_wm_view3d(C);
- if (!BKE_sculptsession_use_pbvh_draw(ob, v3d)) {
+ RegionView3D *rv3d = CTX_wm_region_view3d(C);
+ if (!BKE_sculptsession_use_pbvh_draw(ob, rv3d)) {
DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
}
}
@@ -1315,11 +1308,11 @@ static bool sculpt_brush_use_topology_rake(const SculptSession *ss, const Brush
/**
* Test whether the #StrokeCache.sculpt_normal needs update in #do_brush_action
*/
-static int sculpt_brush_needs_normal(const SculptSession *ss, const Brush *brush)
+static int sculpt_brush_needs_normal(const SculptSession *ss, Sculpt *sd, const Brush *brush)
{
return ((SCULPT_TOOL_HAS_NORMAL_WEIGHT(brush->sculpt_tool) &&
(ss->cache->normal_weight > 0.0f)) ||
-
+ SCULPT_automasking_needs_normal(ss, sd, brush) ||
ELEM(brush->sculpt_tool,
SCULPT_TOOL_BLOB,
SCULPT_TOOL_CREASE,
@@ -1989,7 +1982,7 @@ static void calc_area_normal_and_center_task_cb(void *__restrict userdata,
int(*orco_tris)[3];
int orco_tris_num;
- BKE_pbvh_node_get_bm_orco_data(data->nodes[n], &orco_tris, &orco_tris_num, &orco_coords);
+ BKE_pbvh_node_get_bm_orco_data(data->nodes[n], &orco_tris, &orco_tris_num, &orco_coords, NULL);
for (int i = 0; i < orco_tris_num; i++) {
const float *co_tri[3] = {
@@ -2460,11 +2453,12 @@ float SCULPT_brush_strength_factor(SculptSession *ss,
const float fno[3],
float mask,
const PBVHVertRef vertex,
- int thread_id)
+ const int thread_id,
+ AutomaskingNodeData *automask_data)
{
StrokeCache *cache = ss->cache;
const Scene *scene = cache->vc->scene;
- const MTex *mtex = &br->mtex;
+ const MTex *mtex = BKE_brush_mask_texture_get(br, OB_MODE_SCULPT);
float avg = 1.0f;
float rgba[4];
float point[3];
@@ -2476,7 +2470,7 @@ float SCULPT_brush_strength_factor(SculptSession *ss,
}
else if (mtex->brush_map_mode == MTEX_MAP_MODE_3D) {
/* Get strength by feeding the vertex location directly into a texture. */
- avg = BKE_brush_sample_tex_3d(scene, br, point, rgba, 0, ss->tex_pool);
+ avg = BKE_brush_sample_tex_3d(scene, br, mtex, point, rgba, 0, ss->tex_pool);
}
else {
float symm_point[3], point_2d[2];
@@ -2505,19 +2499,19 @@ float SCULPT_brush_strength_factor(SculptSession *ss,
x = symm_point[0];
y = symm_point[1];
- x *= br->mtex.size[0];
- y *= br->mtex.size[1];
+ x *= mtex->size[0];
+ y *= mtex->size[1];
- x += br->mtex.ofs[0];
- y += br->mtex.ofs[1];
+ x += mtex->ofs[0];
+ y += mtex->ofs[1];
- avg = paint_get_tex_pixel(&br->mtex, x, y, ss->tex_pool, thread_id);
+ avg = paint_get_tex_pixel(mtex, x, y, ss->tex_pool, thread_id);
avg += br->texture_sample_bias;
}
else {
const float point_3d[3] = {point_2d[0], point_2d[1], 0.0f};
- avg = BKE_brush_sample_tex_3d(scene, br, point_3d, rgba, 0, ss->tex_pool);
+ avg = BKE_brush_sample_tex_3d(scene, br, mtex, point_3d, rgba, 0, ss->tex_pool);
}
}
@@ -2544,7 +2538,7 @@ float SCULPT_brush_strength_factor(SculptSession *ss,
avg *= 1.0f - mask;
/* Auto-masking. */
- avg *= SCULPT_automasking_factor_get(cache->automasking, ss, vertex);
+ avg *= SCULPT_automasking_factor_get(cache->automasking, ss, vertex, automask_data);
return avg;
}
@@ -2779,14 +2773,14 @@ static void calc_local_y(ViewContext *vc, const float center[3], float y[3])
float loc[3];
const float xy_delta[2] = {0.0f, 1.0f};
- mul_v3_m4v3(loc, ob->imat, center);
+ mul_v3_m4v3(loc, ob->world_to_object, center);
const float zfac = ED_view3d_calc_zfac(vc->rv3d, loc);
ED_view3d_win_to_delta(vc->region, xy_delta, zfac, y);
normalize_v3(y);
add_v3_v3(y, ob->loc);
- mul_m4_v3(ob->imat, y);
+ mul_m4_v3(ob->world_to_object, y);
}
static void calc_brush_local_mat(const Brush *brush, Object *ob, float local_mat[4][4])
@@ -2798,8 +2792,8 @@ static void calc_brush_local_mat(const Brush *brush, Object *ob, float local_mat
float angle, v[3];
float up[3];
- /* Ensure `ob->imat` is up to date. */
- invert_m4_m4(ob->imat, ob->obmat);
+ /* Ensure `ob->world_to_object` is up to date. */
+ invert_m4_m4(ob->world_to_object, ob->object_to_world);
/* Initialize last column of matrix. */
mat[0][3] = 0.0f;
@@ -2839,13 +2833,13 @@ void SCULPT_tilt_apply_to_normal(float r_normal[3], StrokeCache *cache, const fl
return;
}
const float rot_max = M_PI_2 * tilt_strength * SCULPT_TILT_SENSITIVITY;
- mul_v3_mat3_m4v3(r_normal, cache->vc->obact->obmat, r_normal);
+ mul_v3_mat3_m4v3(r_normal, cache->vc->obact->object_to_world, r_normal);
float normal_tilt_y[3];
rotate_v3_v3v3fl(normal_tilt_y, r_normal, cache->vc->rv3d->viewinv[0], cache->y_tilt * rot_max);
float normal_tilt_xy[3];
rotate_v3_v3v3fl(
normal_tilt_xy, normal_tilt_y, cache->vc->rv3d->viewinv[1], cache->x_tilt * rot_max);
- mul_v3_mat3_m4v3(r_normal, cache->vc->obact->imat, normal_tilt_xy);
+ mul_v3_mat3_m4v3(r_normal, cache->vc->obact->world_to_object, normal_tilt_xy);
normalize_v3(r_normal);
}
@@ -3031,7 +3025,7 @@ void SCULPT_calc_brush_plane(
}
/* For area normal. */
- if ((!SCULPT_stroke_is_first_brush_step_of_symmetry_pass(ss->cache)) &&
+ if (!SCULPT_stroke_is_first_brush_step_of_symmetry_pass(ss->cache) &&
(brush->flag & BRUSH_ORIGINAL_NORMAL)) {
copy_v3_v3(r_area_no, ss->cache->sculpt_normal);
}
@@ -3040,7 +3034,7 @@ void SCULPT_calc_brush_plane(
}
/* For flatten center. */
- if ((!SCULPT_stroke_is_first_brush_step_of_symmetry_pass(ss->cache)) &&
+ if (!SCULPT_stroke_is_first_brush_step_of_symmetry_pass(ss->cache) &&
(brush->flag & BRUSH_ORIGINAL_PLANE)) {
copy_v3_v3(r_area_co, ss->cache->last_center);
}
@@ -3075,7 +3069,7 @@ void SCULPT_calc_brush_plane(
int SCULPT_plane_trim(const StrokeCache *cache, const Brush *brush, const float val[3])
{
return (!(brush->flag & BRUSH_PLANE_TRIM) ||
- ((dot_v3v3(val, val) <= cache->radius_squared * cache->plane_trim_squared)));
+ (dot_v3v3(val, val) <= cache->radius_squared * cache->plane_trim_squared));
}
int SCULPT_plane_point_side(const float co[3], const float plane[4])
@@ -3134,7 +3128,8 @@ static void do_gravity_task_cb_ex(void *__restrict userdata,
vd.fno,
vd.mask ? *vd.mask : 0.0f,
vd.vertex,
- thread_id);
+ thread_id,
+ NULL);
mul_v3_v3fl(proxy[vd.i], offset, fade);
@@ -3271,7 +3266,7 @@ static void sculpt_topology_update(Sculpt *sd,
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_orig(ss->bm, ss->bm_log, nodes[n], false);
}
}
@@ -3289,7 +3284,7 @@ static void sculpt_topology_update(Sculpt *sd,
/* Update average stroke position. */
copy_v3_v3(location, ss->cache->true_location);
- mul_m4_v3(ob->obmat, location);
+ mul_m4_v3(ob->object_to_world, location);
}
static void do_brush_action_task_cb(void *__restrict userdata,
@@ -3348,15 +3343,6 @@ static void do_brush_action(Sculpt *sd,
BKE_pbvh_ensure_node_loops(ss->pbvh);
}
- if (SCULPT_tool_is_mask(brush->sculpt_tool)) {
- MultiresModifierData *mmd = BKE_sculpt_multires_active(ss->scene, ob);
- BKE_sculpt_mask_layers_ensure(ob, mmd);
- }
- if (SCULPT_tool_is_face_sets(brush->sculpt_tool)) {
- Mesh *mesh = BKE_object_get_original_mesh(ob);
- ss->face_sets = BKE_sculpt_face_sets_ensure(mesh);
- }
-
/* Build a list of all nodes that are potentially within the brush's area of influence */
if (SCULPT_tool_needs_all_pbvh_nodes(brush)) {
@@ -3420,6 +3406,8 @@ static void do_brush_action(Sculpt *sd,
/* Initialize auto-masking cache. */
if (SCULPT_is_automasking_enabled(sd, ss, brush)) {
ss->cache->automasking = SCULPT_automasking_cache_init(sd, brush, ob);
+ ss->last_automasking_settings_hash = SCULPT_automasking_settings_hash(
+ ob, ss->cache->automasking);
}
/* Initialize surface smooth cache. */
if ((brush->sculpt_tool == SCULPT_TOOL_SMOOTH) &&
@@ -3450,7 +3438,7 @@ static void do_brush_action(Sculpt *sd,
BLI_task_parallel_range(0, totnode, &task_data, do_brush_action_task_cb, &settings);
}
- if (sculpt_brush_needs_normal(ss, brush)) {
+ if (sculpt_brush_needs_normal(ss, sd, brush)) {
update_sculpt_normal(sd, ob, nodes, totnode);
}
@@ -3602,6 +3590,12 @@ static void do_brush_action(Sculpt *sd,
SCULPT_bmesh_topology_rake(sd, ob, nodes, totnode, brush->topology_rake_factor);
}
+ if (!SCULPT_tool_can_reuse_automask(brush->sculpt_tool) ||
+ (ss->cache->supports_gravity && sd->gravity_factor > 0.0f)) {
+ /* Clear cavity mask cache. */
+ ss->last_automasking_settings_hash = 0;
+ }
+
/* The cloth brush adds the gravity as a regular force and it is processed in the solver. */
if (ss->cache->supports_gravity && !ELEM(brush->sculpt_tool,
SCULPT_TOOL_CLOTH,
@@ -3621,7 +3615,7 @@ static void do_brush_action(Sculpt *sd,
/* Update average stroke position. */
copy_v3_v3(location, ss->cache->true_location);
- mul_m4_v3(ob->obmat, location);
+ mul_m4_v3(ob->object_to_world, location);
add_v3_v3(ups->average_stroke_accum, location);
ups->average_stroke_counter++;
@@ -4207,8 +4201,8 @@ static void sculpt_init_mirror_clipping(Object *ob, SculptSession *ss)
/* Store matrix for mirror object clipping. */
if (mmd->mirror_ob) {
float imtx_mirror_ob[4][4];
- invert_m4_m4(imtx_mirror_ob, mmd->mirror_ob->obmat);
- mul_m4_m4m4(ss->cache->clip_mirror_mtx, imtx_mirror_ob, ob->obmat);
+ invert_m4_m4(imtx_mirror_ob, mmd->mirror_ob->object_to_world);
+ mul_m4_m4m4(ss->cache->clip_mirror_mtx, imtx_mirror_ob, ob->object_to_world);
}
}
}
@@ -4279,7 +4273,8 @@ static void sculpt_update_cache_invariants(
bContext *C, Sculpt *sd, SculptSession *ss, wmOperator *op, const float mval[2])
{
StrokeCache *cache = MEM_callocN(sizeof(StrokeCache), "stroke cache");
- UnifiedPaintSettings *ups = &CTX_data_tool_settings(C)->unified_paint_settings;
+ ToolSettings *tool_settings = CTX_data_tool_settings(C);
+ UnifiedPaintSettings *ups = &tool_settings->unified_paint_settings;
Brush *brush = BKE_paint_brush(&sd->paint);
ViewContext *vc = paint_stroke_view_context(op->customdata);
Object *ob = CTX_data_active_object(C);
@@ -4359,10 +4354,10 @@ static void sculpt_update_cache_invariants(
/* Cache projection matrix. */
ED_view3d_ob_project_mat_get(cache->vc->rv3d, ob, cache->projection_mat);
- invert_m4_m4(ob->imat, ob->obmat);
+ invert_m4_m4(ob->world_to_object, ob->object_to_world);
copy_m3_m4(mat, cache->vc->rv3d->viewinv);
mul_m3_v3(mat, viewDir);
- copy_m3_m4(mat, ob->imat);
+ copy_m3_m4(mat, ob->world_to_object);
mul_m3_v3(mat, viewDir);
normalize_v3_v3(cache->true_view_normal, viewDir);
@@ -4378,7 +4373,7 @@ static void sculpt_update_cache_invariants(
if (sd->gravity_object) {
Object *gravity_object = sd->gravity_object;
- copy_v3_v3(cache->true_gravity_direction, gravity_object->obmat[2]);
+ copy_v3_v3(cache->true_gravity_direction, gravity_object->object_to_world[2]);
}
else {
cache->true_gravity_direction[0] = cache->true_gravity_direction[1] = 0.0f;
@@ -4395,6 +4390,10 @@ static void sculpt_update_cache_invariants(
cache->original = true;
}
+ if (SCULPT_automasking_needs_original(sd, brush)) {
+ cache->original = true;
+ }
+
/* Draw sharp does not need the original coordinates to produce the accumulate effect, so it
* should work the opposite way. */
if (brush->sculpt_tool == SCULPT_TOOL_DRAW_SHARP) {
@@ -4410,6 +4409,13 @@ static void sculpt_update_cache_invariants(
}
}
+ /* Original coordinates require the sculpt undo system, which isn't used
+ * for image brushes. It's also not necessary, just disable it. */
+ if (brush && brush->sculpt_tool == SCULPT_TOOL_PAINT &&
+ SCULPT_use_image_paint_brush(&tool_settings->paint_mode, ob)) {
+ cache->original = false;
+ }
+
cache->first_time = true;
#define PIXEL_INPUT_THRESHHOLD 5
@@ -4521,27 +4527,27 @@ static void sculpt_update_brush_delta(UnifiedPaintSettings *ups, Object *ob, Bru
}
/* Compute 3d coordinate at same z from original location + mval. */
- mul_v3_m4v3(loc, ob->obmat, cache->orig_grab_location);
+ mul_v3_m4v3(loc, ob->object_to_world, cache->orig_grab_location);
ED_view3d_win_to_3d(cache->vc->v3d, cache->vc->region, loc, mval, grab_location);
/* Compute delta to move verts by. */
if (!SCULPT_stroke_is_first_brush_step_of_symmetry_pass(ss->cache)) {
if (sculpt_needs_delta_from_anchored_origin(brush)) {
sub_v3_v3v3(delta, grab_location, cache->old_grab_location);
- invert_m4_m4(imat, ob->obmat);
+ invert_m4_m4(imat, ob->object_to_world);
mul_mat3_m4_v3(imat, delta);
add_v3_v3(cache->grab_delta, delta);
}
else if (sculpt_needs_delta_for_tip_orientation(brush)) {
if (brush->flag & BRUSH_ANCHORED) {
float orig[3];
- mul_v3_m4v3(orig, ob->obmat, cache->orig_grab_location);
+ mul_v3_m4v3(orig, ob->object_to_world, cache->orig_grab_location);
sub_v3_v3v3(cache->grab_delta, grab_location, orig);
}
else {
sub_v3_v3v3(cache->grab_delta, grab_location, cache->old_grab_location);
}
- invert_m4_m4(imat, ob->obmat);
+ invert_m4_m4(imat, ob->object_to_world);
mul_mat3_m4_v3(imat, cache->grab_delta);
}
else {
@@ -4586,7 +4592,7 @@ static void sculpt_update_brush_delta(UnifiedPaintSettings *ups, Object *ob, Bru
/* Handle 'rake' */
cache->is_rake_rotation_valid = false;
- invert_m4_m4(imat, ob->obmat);
+ invert_m4_m4(imat, ob->object_to_world);
mul_mat3_m4_v3(imat, grab_location);
if (SCULPT_stroke_is_first_brush_step_of_symmetry_pass(ss->cache)) {
@@ -4807,12 +4813,12 @@ static bool sculpt_needs_connectivity_info(const Sculpt *sd,
void SCULPT_stroke_modifiers_check(const bContext *C, Object *ob, const Brush *brush)
{
SculptSession *ss = ob->sculpt;
- View3D *v3d = CTX_wm_view3d(C);
+ RegionView3D *rv3d = CTX_wm_region_view3d(C);
Sculpt *sd = CTX_data_tool_settings(C)->sculpt;
bool need_pmap = sculpt_needs_connectivity_info(sd, brush, ss, 0);
if (ss->shapekey_active || ss->deform_modifiers_active ||
- (!BKE_sculptsession_use_pbvh_draw(ob, v3d) && need_pmap)) {
+ (!BKE_sculptsession_use_pbvh_draw(ob, rv3d) && need_pmap)) {
Depsgraph *depsgraph = CTX_data_depsgraph_pointer(C);
BKE_sculpt_update_object_for_edit(
depsgraph, ob, need_pmap, false, SCULPT_tool_is_paint(brush->sculpt_tool));
@@ -4907,7 +4913,7 @@ float SCULPT_raycast_init(ViewContext *vc,
ED_view3d_win_to_segment_clipped(
vc->depsgraph, vc->region, vc->v3d, mval, ray_start, ray_end, true);
- invert_m4_m4(obimat, ob->obmat);
+ invert_m4_m4(obimat, ob->object_to_world);
mul_m4_v3(obimat, ray_start);
mul_m4_v3(obimat, ray_end);
@@ -5015,10 +5021,10 @@ bool SCULPT_cursor_geometry_info_update(bContext *C,
float radius;
/* Update cursor data in SculptSession. */
- invert_m4_m4(ob->imat, ob->obmat);
+ invert_m4_m4(ob->world_to_object, ob->object_to_world);
copy_m3_m4(mat, vc.rv3d->viewinv);
mul_m3_v3(mat, viewDir);
- copy_m3_m4(mat, ob->imat);
+ copy_m3_m4(mat, ob->world_to_object);
mul_m3_v3(mat, viewDir);
normalize_v3_v3(ss->cursor_view_normal, viewDir);
copy_v3_v3(ss->cursor_normal, srd.face_normal);
@@ -5207,7 +5213,7 @@ static void sculpt_restore_mesh(Sculpt *sd, Object *ob)
/* Restore the mesh before continuing with anchored stroke. */
if ((brush->flag & BRUSH_ANCHORED) ||
- ((ELEM(brush->sculpt_tool, SCULPT_TOOL_GRAB, SCULPT_TOOL_ELASTIC_DEFORM)) &&
+ (ELEM(brush->sculpt_tool, SCULPT_TOOL_GRAB, SCULPT_TOOL_ELASTIC_DEFORM) &&
BKE_brush_use_size_pressure(brush)) ||
(brush->flag & BRUSH_DRAG_DOT)) {
@@ -5243,7 +5249,6 @@ void SCULPT_flush_update_step(bContext *C, SculptUpdateType update_flags)
SculptSession *ss = ob->sculpt;
ARegion *region = CTX_wm_region(C);
MultiresModifierData *mmd = ss->multires.modifier;
- View3D *v3d = CTX_wm_view3d(C);
RegionView3D *rv3d = CTX_wm_region_view3d(C);
if (rv3d) {
@@ -5268,7 +5273,7 @@ void SCULPT_flush_update_step(bContext *C, SculptUpdateType update_flags)
/* Only current viewport matters, slower update for all viewports will
* be done in sculpt_flush_update_done. */
- if (!BKE_sculptsession_use_pbvh_draw(ob, v3d)) {
+ if (!BKE_sculptsession_use_pbvh_draw(ob, rv3d)) {
/* Slow update with full dependency graph update and all that comes with it.
* Needed when there are modifiers or full shading in the 3D viewport. */
DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
@@ -5310,16 +5315,15 @@ void SCULPT_flush_update_done(const bContext *C, Object *ob, SculptUpdateType up
/* After we are done drawing the stroke, check if we need to do a more
* expensive depsgraph tag to update geometry. */
wmWindowManager *wm = CTX_wm_manager(C);
- View3D *current_v3d = CTX_wm_view3d(C);
- RegionView3D *rv3d = CTX_wm_region_view3d(C);
+ RegionView3D *current_rv3d = CTX_wm_region_view3d(C);
SculptSession *ss = ob->sculpt;
Mesh *mesh = ob->data;
/* Always needed for linked duplicates. */
bool need_tag = (ID_REAL_USERS(&mesh->id) > 1);
- if (rv3d) {
- rv3d->rflag &= ~RV3D_PAINTING;
+ if (current_rv3d) {
+ current_rv3d->rflag &= ~RV3D_PAINTING;
}
LISTBASE_FOREACH (wmWindow *, win, &wm->windows) {
@@ -5329,16 +5333,17 @@ void SCULPT_flush_update_done(const bContext *C, Object *ob, SculptUpdateType up
if (sl->spacetype != SPACE_VIEW3D) {
continue;
}
- View3D *v3d = (View3D *)sl;
- if (v3d != current_v3d) {
- need_tag |= !BKE_sculptsession_use_pbvh_draw(ob, v3d);
- }
/* Tag all 3D viewports for redraw now that we are done. Others
* viewports did not get a full redraw, and anti-aliasing for the
* current viewport was deactivated. */
LISTBASE_FOREACH (ARegion *, region, &area->regionbase) {
if (region->regiontype == RGN_TYPE_WINDOW) {
+ RegionView3D *rv3d = region->regiondata;
+ if (rv3d != current_rv3d) {
+ need_tag |= !BKE_sculptsession_use_pbvh_draw(ob, rv3d);
+ }
+
ED_region_tag_redraw(region);
}
}
@@ -5370,15 +5375,19 @@ void SCULPT_flush_update_done(const bContext *C, Object *ob, SculptUpdateType up
BKE_pbvh_update_vertex_data(ss->pbvh, PBVH_UpdateColor);
}
- if (BKE_pbvh_type(ss->pbvh) == PBVH_BMESH) {
- BKE_pbvh_bmesh_after_stroke(ss->pbvh);
- }
+ BKE_sculpt_attributes_destroy_temporary_stroke(ob);
- /* Optimization: if there is locked key and active modifiers present in */
- /* the stack, keyblock is updating at each step. otherwise we could update */
- /* keyblock only when stroke is finished. */
- if (ss->shapekey_active && !ss->deform_modifiers_active) {
- sculpt_update_keyblock(ob);
+ if (update_flags & SCULPT_UPDATE_COORDS) {
+ if (BKE_pbvh_type(ss->pbvh) == PBVH_BMESH) {
+ BKE_pbvh_bmesh_after_stroke(ss->pbvh);
+ }
+
+ /* Optimization: if there is locked key and active modifiers present in */
+ /* the stack, keyblock is updating at each step. otherwise we could update */
+ /* keyblock only when stroke is finished. */
+ if (ss->shapekey_active && !ss->deform_modifiers_active) {
+ sculpt_update_keyblock(ob);
+ }
}
if (need_tag) {
@@ -5394,6 +5403,38 @@ static bool over_mesh(bContext *C, struct wmOperator *UNUSED(op), const float mv
return SCULPT_stroke_get_location(C, co_dummy, mval, false);
}
+static void sculpt_stroke_undo_begin(const bContext *C, wmOperator *op)
+{
+ Object *ob = CTX_data_active_object(C);
+ Sculpt *sd = CTX_data_tool_settings(C)->sculpt;
+ Brush *brush = BKE_paint_brush(&sd->paint);
+ ToolSettings *tool_settings = CTX_data_tool_settings(C);
+
+ /* Setup the correct undo system. Image painting and sculpting are mutual exclusive.
+ * Color attributes are part of the sculpting undo system. */
+ if (brush && brush->sculpt_tool == SCULPT_TOOL_PAINT &&
+ SCULPT_use_image_paint_brush(&tool_settings->paint_mode, ob)) {
+ ED_image_undo_push_begin(op->type->name, PAINT_MODE_SCULPT);
+ }
+ else {
+ SCULPT_undo_push_begin_ex(ob, sculpt_tool_name(sd));
+ }
+}
+
+static void sculpt_stroke_undo_end(const bContext *C, Brush *brush)
+{
+ Object *ob = CTX_data_active_object(C);
+ ToolSettings *tool_settings = CTX_data_tool_settings(C);
+
+ if (brush && brush->sculpt_tool == SCULPT_TOOL_PAINT &&
+ SCULPT_use_image_paint_brush(&tool_settings->paint_mode, ob)) {
+ ED_image_undo_push_end();
+ }
+ else {
+ SCULPT_undo_push_end(ob);
+ }
+}
+
bool SCULPT_handles_colors_report(SculptSession *ss, ReportList *reports)
{
switch (BKE_pbvh_type(ss->pbvh)) {
@@ -5442,15 +5483,10 @@ static bool sculpt_stroke_test_start(bContext *C, struct wmOperator *op, const f
SculptCursorGeometryInfo sgi;
SCULPT_cursor_geometry_info_update(C, &sgi, mval, false);
- /* Setup the correct undo system. Image painting and sculpting are mutual exclusive.
- * Color attributes are part of the sculpting undo system. */
- if (brush && brush->sculpt_tool == SCULPT_TOOL_PAINT &&
- SCULPT_use_image_paint_brush(&tool_settings->paint_mode, ob)) {
- ED_image_undo_push_begin(op->type->name, PAINT_MODE_SCULPT);
- }
- else {
- SCULPT_undo_push_begin_ex(ob, sculpt_tool_name(sd));
- }
+ sculpt_stroke_undo_begin(C, op);
+
+ SCULPT_stroke_id_next(ob);
+ ss->cache->stroke_id = ss->stroke_id;
return true;
}
@@ -5476,7 +5512,8 @@ static void sculpt_stroke_update_step(bContext *C,
sculpt_restore_mesh(sd, ob);
if (sd->flags & (SCULPT_DYNTOPO_DETAIL_CONSTANT | SCULPT_DYNTOPO_DETAIL_MANUAL)) {
- float object_space_constant_detail = 1.0f / (sd->constant_detail * mat4_to_scale(ob->obmat));
+ float object_space_constant_detail = 1.0f / (sd->constant_detail *
+ mat4_to_scale(ob->object_to_world));
BKE_pbvh_bmesh_detail_size_set(ss->pbvh, object_space_constant_detail);
}
else if (sd->flags & SCULPT_DYNTOPO_DETAIL_BRUSH) {
@@ -5579,13 +5616,7 @@ static void sculpt_stroke_done(const bContext *C, struct PaintStroke *UNUSED(str
SCULPT_cache_free(ss->cache);
ss->cache = NULL;
- if (brush && brush->sculpt_tool == SCULPT_TOOL_PAINT &&
- SCULPT_use_image_paint_brush(&tool_settings->paint_mode, ob)) {
- ED_image_undo_push_end();
- }
- else {
- SCULPT_undo_push_end(ob);
- }
+ sculpt_stroke_undo_end(C, brush);
if (brush->sculpt_tool == SCULPT_TOOL_MASK) {
SCULPT_flush_update_done(C, ob, SCULPT_UPDATE_MASK);
@@ -5594,6 +5625,10 @@ static void sculpt_stroke_done(const bContext *C, struct PaintStroke *UNUSED(str
if (SCULPT_use_image_paint_brush(&tool_settings->paint_mode, ob)) {
SCULPT_flush_update_done(C, ob, SCULPT_UPDATE_IMAGE);
}
+ else {
+ BKE_sculpt_attributes_destroy_temporary_stroke(ob);
+ SCULPT_flush_update_done(C, ob, SCULPT_UPDATE_COLOR);
+ }
}
else {
SCULPT_flush_update_done(C, ob, SCULPT_UPDATE_COORDS);
@@ -5627,11 +5662,20 @@ static int sculpt_brush_stroke_invoke(bContext *C, wmOperator *op, const wmEvent
Sculpt *sd = CTX_data_tool_settings(C)->sculpt;
Brush *brush = BKE_paint_brush(&sd->paint);
+ SculptSession *ss = ob->sculpt;
if (SCULPT_tool_is_paint(brush->sculpt_tool) &&
!SCULPT_handles_colors_report(ob->sculpt, op->reports)) {
return OPERATOR_CANCELLED;
}
+ if (SCULPT_tool_is_mask(brush->sculpt_tool)) {
+ MultiresModifierData *mmd = BKE_sculpt_multires_active(ss->scene, ob);
+ BKE_sculpt_mask_layers_ensure(CTX_data_depsgraph_pointer(C), CTX_data_main(C), ob, mmd);
+ }
+ if (SCULPT_tool_is_face_sets(brush->sculpt_tool)) {
+ Mesh *mesh = BKE_object_get_original_mesh(ob);
+ ss->face_sets = BKE_sculpt_face_sets_ensure(mesh);
+ }
stroke = paint_stroke_new(C,
op,
@@ -5652,9 +5696,10 @@ static int sculpt_brush_stroke_invoke(bContext *C, wmOperator *op, const wmEvent
return OPERATOR_PASS_THROUGH;
}
- if ((retval = op->type->modal(C, op, event)) == OPERATOR_FINISHED) {
+ retval = op->type->modal(C, op, event);
+ if (ELEM(retval, OPERATOR_FINISHED, OPERATOR_CANCELLED)) {
paint_stroke_free(C, op, op->customdata);
- return OPERATOR_FINISHED;
+ return retval;
}
/* Add modal handler. */
WM_event_add_modal_handler(C, op);
@@ -5709,7 +5754,29 @@ static void sculpt_brush_stroke_cancel(bContext *C, wmOperator *op)
static int sculpt_brush_stroke_modal(bContext *C, wmOperator *op, const wmEvent *event)
{
- return paint_stroke_modal(C, op, event, (struct PaintStroke **)&op->customdata);
+ bool started = op->customdata && paint_stroke_started((struct PaintStroke *)op->customdata);
+
+ int retval = paint_stroke_modal(C, op, event, (struct PaintStroke **)&op->customdata);
+
+ if (!started && ELEM(retval, OPERATOR_FINISHED, OPERATOR_CANCELLED)) {
+ /* Did the stroke never start? If so push a blank sculpt undo
+ * step to prevent a global undo step (which is triggered by the
+ * #OPTYPE_UNDO flag in #SCULPT_OT_brush_stroke).
+ *
+ * Having blank global undo steps interleaved with sculpt steps
+ * corrupts the DynTopo undo stack.
+ * See T101430.
+ *
+ * NOTE: simply returning #OPERATOR_CANCELLED was not
+ * sufficient to prevent this. */
+ Sculpt *sd = CTX_data_tool_settings(C)->sculpt;
+ Brush *brush = BKE_paint_brush(&sd->paint);
+
+ sculpt_stroke_undo_begin(C, op);
+ sculpt_stroke_undo_end(C, brush);
+ }
+
+ return retval;
}
static void sculpt_redo_empty_ui(bContext *UNUSED(C), wmOperator *UNUSED(op))
@@ -6041,4 +6108,91 @@ void SCULPT_fake_neighbors_free(Object *ob)
sculpt_pose_fake_neighbors_free(ss);
}
+void SCULPT_automasking_node_begin(Object *ob,
+ const SculptSession *UNUSED(ss),
+ AutomaskingCache *automasking,
+ AutomaskingNodeData *automask_data,
+ PBVHNode *node)
+{
+ if (!automasking) {
+ memset(automask_data, 0, sizeof(*automask_data));
+ return;
+ }
+
+ automask_data->node = node;
+ automask_data->have_orig_data = automasking->settings.flags &
+ (BRUSH_AUTOMASKING_BRUSH_NORMAL | BRUSH_AUTOMASKING_VIEW_NORMAL);
+
+ if (automask_data->have_orig_data) {
+ SCULPT_orig_vert_data_init(&automask_data->orig_data, ob, node, SCULPT_UNDO_COORDS);
+ }
+ else {
+ memset(&automask_data->orig_data, 0, sizeof(automask_data->orig_data));
+ }
+}
+
+void SCULPT_automasking_node_update(SculptSession *UNUSED(ss),
+ AutomaskingNodeData *automask_data,
+ PBVHVertexIter *vd)
+{
+ if (automask_data->have_orig_data) {
+ SCULPT_orig_vert_data_update(&automask_data->orig_data, vd);
+ }
+}
+
+bool SCULPT_vertex_is_occluded(SculptSession *ss, PBVHVertRef vertex, bool original)
+{
+ float ray_start[3], ray_end[3], ray_normal[3], face_normal[3];
+ float co[3];
+
+ copy_v3_v3(co, SCULPT_vertex_co_get(ss, vertex));
+ float mouse[2];
+
+ ED_view3d_project_float_v2_m4(ss->cache->vc->region, co, mouse, ss->cache->projection_mat);
+
+ int depth = SCULPT_raycast_init(ss->cache->vc, mouse, ray_end, ray_start, ray_normal, original);
+
+ negate_v3(ray_normal);
+
+ copy_v3_v3(ray_start, SCULPT_vertex_co_get(ss, vertex));
+ madd_v3_v3fl(ray_start, ray_normal, 0.002);
+
+ SculptRaycastData srd = {0};
+ srd.original = original;
+ srd.ss = ss;
+ srd.hit = false;
+ srd.ray_start = ray_start;
+ srd.ray_normal = ray_normal;
+ srd.depth = depth;
+ srd.face_normal = face_normal;
+
+ isect_ray_tri_watertight_v3_precalc(&srd.isect_precalc, ray_normal);
+ BKE_pbvh_raycast(ss->pbvh, sculpt_raycast_cb, &srd, ray_start, ray_normal, srd.original);
+
+ return srd.hit;
+}
+
+void SCULPT_stroke_id_next(Object *ob)
+{
+ /* Manually wrap in int32 space to avoid tripping up undefined behavior
+ * sanitizers.
+ */
+ ob->sculpt->stroke_id = (uchar)(((int)ob->sculpt->stroke_id + 1) & 255);
+}
+
+void SCULPT_stroke_id_ensure(Object *ob)
+{
+ SculptSession *ss = ob->sculpt;
+
+ if (!ss->attrs.automasking_stroke_id) {
+ SculptAttributeParams params = {0};
+ ss->attrs.automasking_stroke_id = BKE_sculpt_attribute_ensure(
+ ob,
+ ATTR_DOMAIN_POINT,
+ CD_PROP_INT8,
+ SCULPT_ATTRIBUTE_NAME(automasking_stroke_id),
+ &params);
+ }
+}
+
/** \} */
diff --git a/source/blender/editors/sculpt_paint/sculpt_automasking.cc b/source/blender/editors/sculpt_paint/sculpt_automasking.cc
index a9fe8cc4b2f..505440c9272 100644
--- a/source/blender/editors/sculpt_paint/sculpt_automasking.cc
+++ b/source/blender/editors/sculpt_paint/sculpt_automasking.cc
@@ -7,17 +7,22 @@
#include "MEM_guardedalloc.h"
+#include "BLI_array.hh"
#include "BLI_blenlib.h"
#include "BLI_hash.h"
#include "BLI_index_range.hh"
#include "BLI_math.h"
+#include "BLI_math_vec_types.hh"
+#include "BLI_set.hh"
#include "BLI_task.h"
+#include "BLI_vector.hh"
#include "DNA_brush_types.h"
#include "DNA_mesh_types.h"
#include "DNA_meshdata_types.h"
#include "BKE_brush.h"
+#include "BKE_colortools.h"
#include "BKE_context.h"
#include "BKE_mesh.h"
#include "BKE_mesh_mapping.h"
@@ -47,7 +52,10 @@
#include <cmath>
#include <cstdlib>
+using blender::float3;
using blender::IndexRange;
+using blender::Set;
+using blender::Vector;
AutomaskingCache *SCULPT_automasking_active_cache_get(SculptSession *ss)
{
@@ -64,10 +72,13 @@ bool SCULPT_is_automasking_mode_enabled(const Sculpt *sd,
const Brush *br,
const eAutomasking_flag mode)
{
+ int automasking = sd->automasking_flags;
+
if (br) {
- return br->automasking_flags & mode || sd->automasking_flags & mode;
+ automasking |= br->automasking_flags;
}
- return sd->automasking_flags & mode;
+
+ return (eAutomasking_flag)automasking & mode;
}
bool SCULPT_is_automasking_enabled(const Sculpt *sd, const SculptSession *ss, const Brush *br)
@@ -87,17 +98,85 @@ bool SCULPT_is_automasking_enabled(const Sculpt *sd, const SculptSession *ss, co
if (SCULPT_is_automasking_mode_enabled(sd, br, BRUSH_AUTOMASKING_BOUNDARY_FACE_SETS)) {
return true;
}
+ if (SCULPT_is_automasking_mode_enabled(sd, br, BRUSH_AUTOMASKING_BRUSH_NORMAL)) {
+ return true;
+ }
+ if (SCULPT_is_automasking_mode_enabled(sd, br, BRUSH_AUTOMASKING_VIEW_NORMAL)) {
+ return true;
+ }
+ if (SCULPT_is_automasking_mode_enabled(sd, br, BRUSH_AUTOMASKING_CAVITY_ALL)) {
+ return true;
+ }
+
return false;
}
static int sculpt_automasking_mode_effective_bits(const Sculpt *sculpt, const Brush *brush)
{
if (brush) {
- return sculpt->automasking_flags | brush->automasking_flags;
+ int flags = sculpt->automasking_flags | brush->automasking_flags;
+
+ /* Check if we are using brush cavity settings. */
+ if (brush->automasking_flags & BRUSH_AUTOMASKING_CAVITY_ALL) {
+ flags &= ~(BRUSH_AUTOMASKING_CAVITY_ALL | BRUSH_AUTOMASKING_CAVITY_USE_CURVE |
+ BRUSH_AUTOMASKING_CAVITY_NORMAL);
+ flags |= brush->automasking_flags;
+ }
+ else if (sculpt->automasking_flags & BRUSH_AUTOMASKING_CAVITY_ALL) {
+ flags &= ~(BRUSH_AUTOMASKING_CAVITY_ALL | BRUSH_AUTOMASKING_CAVITY_USE_CURVE |
+ BRUSH_AUTOMASKING_CAVITY_NORMAL);
+ flags |= sculpt->automasking_flags;
+ }
+
+ return flags;
}
return sculpt->automasking_flags;
}
+bool SCULPT_automasking_needs_normal(const SculptSession * /*ss*/,
+ const Sculpt *sculpt,
+ const Brush *brush)
+{
+ int flags = sculpt_automasking_mode_effective_bits(sculpt, brush);
+
+ return flags & (BRUSH_AUTOMASKING_BRUSH_NORMAL | BRUSH_AUTOMASKING_VIEW_NORMAL);
+}
+
+static float sculpt_automasking_normal_calc(SculptSession *ss,
+ PBVHVertRef vertex,
+ float3 &normal,
+ float limit_lower,
+ float limit_upper,
+ AutomaskingNodeData *automask_data)
+{
+ float3 normal_v;
+
+ if (automask_data->have_orig_data) {
+ normal_v = automask_data->orig_data.no;
+ }
+ else {
+ SCULPT_vertex_normal_get(ss, vertex, normal_v);
+ }
+
+ float angle = saacos(dot_v3v3(normal, normal_v));
+
+ /* note that limit is pre-divided by M_PI */
+
+ if (angle > limit_lower && angle < limit_upper) {
+ float t = 1.0f - (angle - limit_lower) / (limit_upper - limit_lower);
+
+ /* smoothstep */
+ t = t * t * (3.0 - 2.0 * t);
+
+ return t;
+ }
+ if (angle > limit_upper) {
+ return 0.0f;
+ }
+
+ return 1.0f;
+}
+
static bool SCULPT_automasking_needs_factors_cache(const Sculpt *sd, const Brush *brush)
{
@@ -105,30 +184,352 @@ static bool SCULPT_automasking_needs_factors_cache(const Sculpt *sd, const Brush
if (automasking_flags & BRUSH_AUTOMASKING_TOPOLOGY) {
return true;
}
- if (automasking_flags & BRUSH_AUTOMASKING_BOUNDARY_EDGES) {
- return brush && brush->automasking_boundary_edges_propagation_steps != 1;
- }
- if (automasking_flags & BRUSH_AUTOMASKING_BOUNDARY_FACE_SETS) {
+
+ if (automasking_flags &
+ (BRUSH_AUTOMASKING_BOUNDARY_EDGES | BRUSH_AUTOMASKING_BOUNDARY_FACE_SETS |
+ BRUSH_AUTOMASKING_BRUSH_NORMAL | BRUSH_AUTOMASKING_VIEW_NORMAL)) {
return brush && brush->automasking_boundary_edges_propagation_steps != 1;
}
return false;
}
+static float automasking_brush_normal_factor(AutomaskingCache *automasking,
+ SculptSession *ss,
+ PBVHVertRef vertex,
+ AutomaskingNodeData *automask_data)
+{
+ float falloff = automasking->settings.start_normal_falloff * M_PI;
+ float3 initial_normal;
+
+ if (ss->cache) {
+ initial_normal = ss->cache->initial_normal;
+ }
+ else {
+ initial_normal = ss->filter_cache->initial_normal;
+ }
+
+ return sculpt_automasking_normal_calc(ss,
+ vertex,
+ initial_normal,
+ automasking->settings.start_normal_limit - falloff * 0.5f,
+ automasking->settings.start_normal_limit + falloff * 0.5f,
+ automask_data);
+}
+
+static float automasking_view_normal_factor(AutomaskingCache *automasking,
+ SculptSession *ss,
+ PBVHVertRef vertex,
+ AutomaskingNodeData *automask_data)
+{
+ float falloff = automasking->settings.view_normal_falloff * M_PI;
+
+ float3 view_normal;
+
+ if (ss->cache) {
+ view_normal = ss->cache->view_normal;
+ }
+ else {
+ view_normal = ss->filter_cache->view_normal;
+ }
+
+ return sculpt_automasking_normal_calc(ss,
+ vertex,
+ view_normal,
+ automasking->settings.view_normal_limit,
+ automasking->settings.view_normal_limit + falloff,
+ automask_data);
+}
+
+static float automasking_view_occlusion_factor(AutomaskingCache *automasking,
+ SculptSession *ss,
+ PBVHVertRef vertex,
+ uchar stroke_id,
+ AutomaskingNodeData * /*automask_data*/)
+{
+ char f = *(char *)SCULPT_vertex_attr_get(vertex, ss->attrs.automasking_occlusion);
+
+ if (stroke_id != automasking->current_stroke_id) {
+ f = *(char *)SCULPT_vertex_attr_get(
+ vertex,
+ ss->attrs.automasking_occlusion) = SCULPT_vertex_is_occluded(ss, vertex, true) ? 2 : 1;
+ }
+
+ return f == 2;
+}
+
+/* Updates vertex stroke id. */
+static float automasking_factor_end(SculptSession *ss,
+ AutomaskingCache *automasking,
+ PBVHVertRef vertex,
+ float value)
+{
+ if (ss->attrs.automasking_stroke_id) {
+ *(uchar *)SCULPT_vertex_attr_get(
+ vertex, ss->attrs.automasking_stroke_id) = automasking->current_stroke_id;
+ }
+
+ return value;
+}
+
+static float sculpt_cavity_calc_factor(AutomaskingCache *automasking, float factor)
+{
+ float sign = signf(factor);
+
+ factor = fabsf(factor) * automasking->settings.cavity_factor * 50.0f;
+
+ factor = factor * sign * 0.5f + 0.5f;
+ CLAMP(factor, 0.0f, 1.0f);
+
+ return (automasking->settings.flags & BRUSH_AUTOMASKING_CAVITY_INVERTED) ? 1.0f - factor :
+ factor;
+}
+
+struct CavityBlurVert {
+ PBVHVertRef vertex;
+ float dist;
+ int depth;
+
+ CavityBlurVert(PBVHVertRef vertex_, float dist_, int depth_)
+ : vertex(vertex_), dist(dist_), depth(depth_)
+ {
+ }
+
+ CavityBlurVert() = default;
+};
+
+static void sculpt_calc_blurred_cavity(SculptSession *ss,
+ AutomaskingCache *automasking,
+ int steps,
+ PBVHVertRef vertex)
+{
+ float3 sno1(0.0f);
+ float3 sno2(0.0f);
+ float3 sco1(0.0f);
+ float3 sco2(0.0f);
+ float len1_sum = 0.0f;
+ int sco1_len = 0, sco2_len = 0;
+
+ /* Steps starts at 1, but API and user interface
+ * are zero-based.
+ */
+ steps++;
+
+ Vector<CavityBlurVert, 64> queue;
+ Set<int64_t, 64> visit;
+
+ int start = 0, end = 0;
+
+ queue.resize(64);
+
+ CavityBlurVert initial(vertex, 0.0f, 0);
+
+ visit.add_new(vertex.i);
+ queue[0] = initial;
+ end = 1;
+
+ const float *co1 = SCULPT_vertex_co_get(ss, vertex);
+
+ while (start != end) {
+ CavityBlurVert &blurvert = queue[start];
+ PBVHVertRef v = blurvert.vertex;
+ start = (start + 1) % queue.size();
+
+ float3 no;
+
+ const float *co = SCULPT_vertex_co_get(ss, v);
+ SCULPT_vertex_normal_get(ss, v, no);
+
+ float centdist = len_v3v3(co, co1);
+
+ sco1 += co;
+ sno1 += no;
+ len1_sum += centdist;
+ sco1_len++;
+
+ if (blurvert.depth < steps) {
+ sco2 += co;
+ sno2 += no;
+ sco2_len++;
+ }
+
+ if (blurvert.depth >= steps) {
+ continue;
+ }
+
+ SculptVertexNeighborIter ni;
+ SCULPT_VERTEX_NEIGHBORS_ITER_BEGIN (ss, v, ni) {
+ PBVHVertRef v2 = ni.vertex;
+
+ if (visit.contains(v2.i)) {
+ continue;
+ }
+
+ float dist = len_v3v3(SCULPT_vertex_co_get(ss, v2), SCULPT_vertex_co_get(ss, v));
+
+ visit.add_new(v2.i);
+ CavityBlurVert blurvert2(v2, dist, blurvert.depth + 1);
+
+ int nextend = (end + 1) % queue.size();
+
+ if (nextend == start) {
+ int oldsize = queue.size();
+
+ queue.resize(queue.size() << 1);
+
+ if (end < start) {
+ int n = oldsize - start;
+
+ for (int i = 0; i < n; i++) {
+ queue[queue.size() - n + i] = queue[i + start];
+ }
+
+ start = queue.size() - n;
+ }
+ }
+
+ queue[end] = blurvert2;
+ end = (end + 1) % queue.size();
+ }
+ SCULPT_VERTEX_NEIGHBORS_ITER_END(ni);
+ }
+
+ BLI_assert(sco1_len != sco2_len);
+
+ if (!sco1_len) {
+ sco1 = SCULPT_vertex_co_get(ss, vertex);
+ }
+ else {
+ sco1 /= float(sco1_len);
+ len1_sum /= sco1_len;
+ }
+
+ if (!sco2_len) {
+ sco2 = SCULPT_vertex_co_get(ss, vertex);
+ }
+ else {
+ sco2 /= float(sco2_len);
+ }
+
+ normalize_v3(sno1);
+ if (dot_v3v3(sno1, sno1) == 0.0f) {
+ SCULPT_vertex_normal_get(ss, vertex, sno1);
+ }
+
+ normalize_v3(sno2);
+ if (dot_v3v3(sno2, sno2) == 0.0f) {
+ SCULPT_vertex_normal_get(ss, vertex, sno2);
+ }
+
+ float3 vec = sco1 - sco2;
+ float factor_sum = dot_v3v3(vec, sno2) / len1_sum;
+
+ factor_sum = sculpt_cavity_calc_factor(automasking, factor_sum);
+
+ *(float *)SCULPT_vertex_attr_get(vertex, ss->attrs.automasking_cavity) = factor_sum;
+}
+
+int SCULPT_automasking_settings_hash(Object *ob, AutomaskingCache *automasking)
+{
+ SculptSession *ss = ob->sculpt;
+
+ int hash;
+ int totvert = SCULPT_vertex_count_get(ss);
+
+ hash = BLI_hash_int(automasking->settings.flags);
+ hash = BLI_hash_int_2d(hash, totvert);
+
+ if (automasking->settings.flags & BRUSH_AUTOMASKING_CAVITY_ALL) {
+ hash = BLI_hash_int_2d(hash, automasking->settings.cavity_blur_steps);
+ hash = BLI_hash_int_2d(hash, *reinterpret_cast<uint *>(&automasking->settings.cavity_factor));
+
+ if (automasking->settings.cavity_curve) {
+ CurveMap *cm = automasking->settings.cavity_curve->cm;
+
+ for (int i = 0; i < cm->totpoint; i++) {
+ hash = BLI_hash_int_2d(hash, *reinterpret_cast<uint *>(&cm->curve[i].x));
+ hash = BLI_hash_int_2d(hash, *reinterpret_cast<uint *>(&cm->curve[i].y));
+ hash = BLI_hash_int_2d(hash, uint(cm->curve[i].flag));
+ hash = BLI_hash_int_2d(hash, uint(cm->curve[i].shorty));
+ }
+ }
+ }
+
+ if (automasking->settings.flags & BRUSH_AUTOMASKING_FACE_SETS) {
+ hash = BLI_hash_int_2d(hash, automasking->settings.initial_face_set);
+ }
+
+ if (automasking->settings.flags & BRUSH_AUTOMASKING_VIEW_NORMAL) {
+ hash = BLI_hash_int_2d(hash,
+ *reinterpret_cast<uint *>(&automasking->settings.view_normal_falloff));
+ hash = BLI_hash_int_2d(hash,
+ *reinterpret_cast<uint *>(&automasking->settings.view_normal_limit));
+ }
+
+ if (automasking->settings.flags & BRUSH_AUTOMASKING_BRUSH_NORMAL) {
+ hash = BLI_hash_int_2d(hash,
+ *reinterpret_cast<uint *>(&automasking->settings.start_normal_falloff));
+ hash = BLI_hash_int_2d(hash,
+ *reinterpret_cast<uint *>(&automasking->settings.start_normal_limit));
+ }
+
+ return hash;
+}
+
+static float sculpt_automasking_cavity_factor(AutomaskingCache *automasking,
+ SculptSession *ss,
+ PBVHVertRef vertex)
+{
+ uchar stroke_id = *(uchar *)SCULPT_vertex_attr_get(vertex, ss->attrs.automasking_stroke_id);
+
+ if (stroke_id != automasking->current_stroke_id) {
+ sculpt_calc_blurred_cavity(ss, automasking, automasking->settings.cavity_blur_steps, vertex);
+ }
+
+ float factor = *(float *)SCULPT_vertex_attr_get(vertex, ss->attrs.automasking_cavity);
+ bool inverted = automasking->settings.flags & BRUSH_AUTOMASKING_CAVITY_INVERTED;
+
+ if ((automasking->settings.flags & BRUSH_AUTOMASKING_CAVITY_ALL) &&
+ (automasking->settings.flags & BRUSH_AUTOMASKING_CAVITY_USE_CURVE)) {
+ factor = inverted ? 1.0f - factor : factor;
+ factor = BKE_curvemapping_evaluateF(automasking->settings.cavity_curve, 0, factor);
+ factor = inverted ? 1.0f - factor : factor;
+ }
+
+ return factor;
+}
+
float SCULPT_automasking_factor_get(AutomaskingCache *automasking,
SculptSession *ss,
- PBVHVertRef vert)
+ PBVHVertRef vert,
+ AutomaskingNodeData *automask_data)
{
- if (!automasking) {
+ if (!automasking || vert.i == PBVH_REF_NONE) {
return 1.0f;
}
- int index = BKE_pbvh_vertex_to_index(ss->pbvh, vert);
-
/* If the cache is initialized with valid info, use the cache. This is used when the
* 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[index];
+ if (ss->attrs.automasking_factor) {
+ float factor = *(float *)SCULPT_vertex_attr_get(vert, ss->attrs.automasking_factor);
+
+ if (automasking->settings.flags & BRUSH_AUTOMASKING_CAVITY_ALL) {
+ factor *= sculpt_automasking_cavity_factor(automasking, ss, vert);
+ }
+
+ return factor;
+ }
+
+ uchar stroke_id = ss->attrs.automasking_stroke_id ?
+ *(uchar *)SCULPT_vertex_attr_get(vert, ss->attrs.automasking_stroke_id) :
+ -1;
+
+ bool do_occlusion = (automasking->settings.flags &
+ (BRUSH_AUTOMASKING_VIEW_OCCLUSION | BRUSH_AUTOMASKING_VIEW_NORMAL)) ==
+ (BRUSH_AUTOMASKING_VIEW_OCCLUSION | BRUSH_AUTOMASKING_VIEW_NORMAL);
+ if (do_occlusion &&
+ automasking_view_occlusion_factor(automasking, ss, vert, stroke_id, automask_data)) {
+ return automasking_factor_end(ss, automasking, vert, 0.0f);
}
if (automasking->settings.flags & BRUSH_AUTOMASKING_FACE_SETS) {
@@ -149,7 +550,23 @@ float SCULPT_automasking_factor_get(AutomaskingCache *automasking,
}
}
- return 1.0f;
+ float mask = 1.0f;
+
+ if ((ss->cache || ss->filter_cache) &&
+ (automasking->settings.flags & BRUSH_AUTOMASKING_BRUSH_NORMAL)) {
+ mask *= automasking_brush_normal_factor(automasking, ss, vert, automask_data);
+ }
+
+ if ((ss->cache || ss->filter_cache) &&
+ (automasking->settings.flags & BRUSH_AUTOMASKING_VIEW_NORMAL)) {
+ mask *= automasking_view_normal_factor(automasking, ss, vert, automask_data);
+ }
+
+ if (automasking->settings.flags & BRUSH_AUTOMASKING_CAVITY_ALL) {
+ mask *= sculpt_automasking_cavity_factor(automasking, ss, vert);
+ }
+
+ return automasking_factor_end(ss, automasking, vert, mask);
}
void SCULPT_automasking_cache_free(AutomaskingCache *automasking)
@@ -158,7 +575,6 @@ void SCULPT_automasking_cache_free(AutomaskingCache *automasking)
return;
}
- MEM_SAFE_FREE(automasking->factor);
MEM_SAFE_FREE(automasking);
}
@@ -176,43 +592,39 @@ static bool sculpt_automasking_is_constrained_by_radius(Brush *br)
}
struct AutomaskFloodFillData {
- float *automask_factor;
float radius;
bool use_radius;
float location[3];
char symm;
};
-static bool automask_floodfill_cb(SculptSession *ss,
- PBVHVertRef from_v,
- PBVHVertRef to_v,
- bool UNUSED(is_duplicate),
- void *userdata)
+static bool automask_floodfill_cb(
+ SculptSession *ss, PBVHVertRef from_v, PBVHVertRef to_v, bool /*is_duplicate*/, void *userdata)
{
AutomaskFloodFillData *data = (AutomaskFloodFillData *)userdata;
- int from_v_i = BKE_pbvh_vertex_to_index(ss->pbvh, from_v);
- int to_v_i = BKE_pbvh_vertex_to_index(ss->pbvh, to_v);
- data->automask_factor[to_v_i] = 1.0f;
- data->automask_factor[from_v_i] = 1.0f;
+ *(float *)SCULPT_vertex_attr_get(to_v, ss->attrs.automasking_factor) = 1.0f;
+ *(float *)SCULPT_vertex_attr_get(from_v, ss->attrs.automasking_factor) = 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));
}
-static float *SCULPT_topology_automasking_init(Sculpt *sd, Object *ob, float *automask_factor)
+static void SCULPT_topology_automasking_init(Sculpt *sd, Object *ob)
{
SculptSession *ss = ob->sculpt;
Brush *brush = BKE_paint_brush(&sd->paint);
if (BKE_pbvh_type(ss->pbvh) == PBVH_FACES && !ss->pmap) {
- BLI_assert_msg(0, "Topology masking: pmap missing");
- return nullptr;
+ BLI_assert_unreachable();
+ return;
}
const int totvert = SCULPT_vertex_count_get(ss);
for (int i : IndexRange(totvert)) {
- automask_factor[i] = 0.0f;
+ PBVHVertRef vertex = BKE_pbvh_index_to_vertex(ss->pbvh, i);
+
+ (*(float *)SCULPT_vertex_attr_get(vertex, ss->attrs.automasking_factor)) = 0.0f;
}
/* Flood fill automask to connected vertices. Limited to vertices inside
@@ -222,9 +634,8 @@ static float *SCULPT_topology_automasking_init(Sculpt *sd, Object *ob, float *au
const float radius = ss->cache ? ss->cache->radius : FLT_MAX;
SCULPT_floodfill_add_active(sd, ob, ss, &flood, radius);
- AutomaskFloodFillData fdata = {nullptr};
+ AutomaskFloodFillData fdata = {0};
- fdata.automask_factor = automask_factor;
fdata.radius = radius;
fdata.use_radius = ss->cache && sculpt_automasking_is_constrained_by_radius(brush);
fdata.symm = SCULPT_mesh_symmetry_xyz_get(ob);
@@ -232,22 +643,20 @@ static float *SCULPT_topology_automasking_init(Sculpt *sd, Object *ob, float *au
copy_v3_v3(fdata.location, SCULPT_active_vertex_co_get(ss));
SCULPT_floodfill_execute(ss, &flood, automask_floodfill_cb, &fdata);
SCULPT_floodfill_free(&flood);
-
- return automask_factor;
}
-static float *sculpt_face_sets_automasking_init(Sculpt *sd, Object *ob, float *automask_factor)
+static void sculpt_face_sets_automasking_init(Sculpt *sd, Object *ob)
{
SculptSession *ss = ob->sculpt;
Brush *brush = BKE_paint_brush(&sd->paint);
if (!SCULPT_is_automasking_enabled(sd, ss, brush)) {
- return nullptr;
+ return;
}
if (BKE_pbvh_type(ss->pbvh) == PBVH_FACES && !ss->pmap) {
BLI_assert_msg(0, "Face Sets automasking: pmap missing");
- return nullptr;
+ return;
}
int tot_vert = SCULPT_vertex_count_get(ss);
@@ -256,25 +665,22 @@ static float *sculpt_face_sets_automasking_init(Sculpt *sd, Object *ob, float *a
PBVHVertRef vertex = BKE_pbvh_index_to_vertex(ss->pbvh, i);
if (!SCULPT_vertex_has_face_set(ss, vertex, active_face_set)) {
- automask_factor[i] *= 0.0f;
+ *(float *)SCULPT_vertex_attr_get(vertex, ss->attrs.automasking_factor) = 0.0f;
}
}
-
- return automask_factor;
}
#define EDGE_DISTANCE_INF -1
-float *SCULPT_boundary_automasking_init(Object *ob,
- eBoundaryAutomaskMode mode,
- int propagation_steps,
- float *automask_factor)
+static void SCULPT_boundary_automasking_init(Object *ob,
+ eBoundaryAutomaskMode mode,
+ int propagation_steps)
{
SculptSession *ss = ob->sculpt;
if (!ss->pmap) {
BLI_assert_msg(0, "Boundary Edges masking: pmap missing");
- return nullptr;
+ return;
}
const int totvert = SCULPT_vertex_count_get(ss);
@@ -316,16 +722,19 @@ float *SCULPT_boundary_automasking_init(Object *ob,
}
for (int i : IndexRange(totvert)) {
+ PBVHVertRef vertex = BKE_pbvh_index_to_vertex(ss->pbvh, i);
+
if (edge_distance[i] == EDGE_DISTANCE_INF) {
continue;
}
- const float p = 1.0f - ((float)edge_distance[i] / (float)propagation_steps);
+ const float p = 1.0f - (float(edge_distance[i]) / float(propagation_steps));
const float edge_boundary_automask = pow2f(p);
- automask_factor[i] *= (1.0f - edge_boundary_automask);
+
+ *(float *)SCULPT_vertex_attr_get(
+ vertex, ss->attrs.automasking_factor) *= (1.0f - edge_boundary_automask);
}
MEM_SAFE_FREE(edge_distance);
- return automask_factor;
}
static void SCULPT_automasking_cache_settings_update(AutomaskingCache *automasking,
@@ -335,6 +744,66 @@ static void SCULPT_automasking_cache_settings_update(AutomaskingCache *automaski
{
automasking->settings.flags = sculpt_automasking_mode_effective_bits(sd, brush);
automasking->settings.initial_face_set = SCULPT_active_face_set_get(ss);
+
+ automasking->settings.view_normal_limit = sd->automasking_view_normal_limit;
+ automasking->settings.view_normal_falloff = sd->automasking_view_normal_falloff;
+ automasking->settings.start_normal_limit = sd->automasking_start_normal_limit;
+ automasking->settings.start_normal_falloff = sd->automasking_start_normal_falloff;
+
+ if (brush && (brush->automasking_flags & BRUSH_AUTOMASKING_CAVITY_ALL)) {
+ automasking->settings.cavity_curve = brush->automasking_cavity_curve;
+ automasking->settings.cavity_factor = brush->automasking_cavity_factor;
+ automasking->settings.cavity_blur_steps = brush->automasking_cavity_blur_steps;
+ }
+ else {
+ automasking->settings.cavity_curve = sd->automasking_cavity_curve;
+ automasking->settings.cavity_factor = sd->automasking_cavity_factor;
+ automasking->settings.cavity_blur_steps = sd->automasking_cavity_blur_steps;
+ }
+}
+
+static void sculpt_normal_occlusion_automasking_fill(AutomaskingCache *automasking,
+ Object *ob,
+ eAutomasking_flag mode)
+{
+ SculptSession *ss = ob->sculpt;
+ const int totvert = SCULPT_vertex_count_get(ss);
+
+ /* No need to build original data since this is only called at the beginning of strokes.*/
+ AutomaskingNodeData nodedata;
+ nodedata.have_orig_data = false;
+
+ for (int i = 0; i < totvert; i++) {
+ PBVHVertRef vertex = BKE_pbvh_index_to_vertex(ss->pbvh, i);
+
+ float f = *(float *)SCULPT_vertex_attr_get(vertex, ss->attrs.automasking_factor);
+
+ if (int(mode) & BRUSH_AUTOMASKING_BRUSH_NORMAL) {
+ f *= automasking_brush_normal_factor(automasking, ss, vertex, &nodedata);
+ }
+ if (int(mode) & BRUSH_AUTOMASKING_VIEW_NORMAL) {
+ if (int(mode) & BRUSH_AUTOMASKING_VIEW_OCCLUSION) {
+ f *= automasking_view_occlusion_factor(automasking, ss, vertex, -1, &nodedata);
+ }
+
+ f *= automasking_view_normal_factor(automasking, ss, vertex, &nodedata);
+ }
+
+ if (ss->attrs.automasking_stroke_id) {
+ *(uchar *)SCULPT_vertex_attr_get(vertex, ss->attrs.automasking_stroke_id) = ss->stroke_id;
+ }
+
+ *(float *)SCULPT_vertex_attr_get(vertex, ss->attrs.automasking_factor) = f;
+ }
+}
+
+bool SCULPT_tool_can_reuse_automask(int sculpt_tool)
+{
+ return ELEM(sculpt_tool,
+ SCULPT_TOOL_PAINT,
+ SCULPT_TOOL_SMEAR,
+ SCULPT_TOOL_MASK,
+ SCULPT_TOOL_DRAW_FACE_SETS);
}
AutomaskingCache *SCULPT_automasking_cache_init(Sculpt *sd, Brush *brush, Object *ob)
@@ -351,38 +820,134 @@ AutomaskingCache *SCULPT_automasking_cache_init(Sculpt *sd, Brush *brush, Object
SCULPT_automasking_cache_settings_update(automasking, ss, sd, brush);
SCULPT_boundary_info_ensure(ob);
+ automasking->current_stroke_id = ss->stroke_id;
+
+ bool use_stroke_id = false;
+ int mode = sculpt_automasking_mode_effective_bits(sd, brush);
+
+ if ((mode & BRUSH_AUTOMASKING_VIEW_OCCLUSION) && (mode & BRUSH_AUTOMASKING_VIEW_NORMAL)) {
+ use_stroke_id = true;
+
+ if (!ss->attrs.automasking_occlusion) {
+ SculptAttributeParams params = {0};
+ ss->attrs.automasking_occlusion = BKE_sculpt_attribute_ensure(
+ ob,
+ ATTR_DOMAIN_POINT,
+ CD_PROP_INT8,
+ SCULPT_ATTRIBUTE_NAME(automasking_occlusion),
+ &params);
+ }
+ }
+
+ if (mode & BRUSH_AUTOMASKING_CAVITY_ALL) {
+ use_stroke_id = true;
+
+ if (SCULPT_is_automasking_mode_enabled(sd, brush, BRUSH_AUTOMASKING_CAVITY_USE_CURVE)) {
+ BKE_curvemapping_init(brush->automasking_cavity_curve);
+ BKE_curvemapping_init(sd->automasking_cavity_curve);
+ }
+
+ if (!ss->attrs.automasking_cavity) {
+ SculptAttributeParams params = {0};
+ ss->attrs.automasking_cavity = BKE_sculpt_attribute_ensure(
+ ob,
+ ATTR_DOMAIN_POINT,
+ CD_PROP_FLOAT,
+ SCULPT_ATTRIBUTE_NAME(automasking_cavity),
+ &params);
+ }
+ }
+
+ if (use_stroke_id) {
+ SCULPT_stroke_id_ensure(ob);
+
+ bool have_occlusion = (mode & BRUSH_AUTOMASKING_VIEW_OCCLUSION) &&
+ (mode & BRUSH_AUTOMASKING_VIEW_NORMAL);
+
+ if (brush && SCULPT_tool_can_reuse_automask(brush->sculpt_tool) && !have_occlusion) {
+ int hash = SCULPT_automasking_settings_hash(ob, automasking);
+
+ if (hash == ss->last_automasking_settings_hash) {
+ automasking->current_stroke_id = ss->last_automask_stroke_id;
+ automasking->can_reuse_mask = true;
+ }
+ }
+
+ if (!automasking->can_reuse_mask) {
+ ss->last_automask_stroke_id = ss->stroke_id;
+ }
+ }
+
if (!SCULPT_automasking_needs_factors_cache(sd, brush)) {
return automasking;
}
- automasking->factor = (float *)MEM_malloc_arrayN(totvert, sizeof(float), "automask_factor");
+ SculptAttributeParams params = {0};
+ params.stroke_only = true;
+
+ ss->attrs.automasking_factor = BKE_sculpt_attribute_ensure(
+ ob, ATTR_DOMAIN_POINT, CD_PROP_FLOAT, SCULPT_ATTRIBUTE_NAME(automasking_factor), &params);
+
+ float initial_value;
+
+ /* Topology, boundary and boundary face sets build up the mask
+ * from zero which other modes can subtract from. If none of them are
+ * enabled initialize to 1.
+ */
+ if (!(mode & (BRUSH_AUTOMASKING_BOUNDARY_EDGES | BRUSH_AUTOMASKING_TOPOLOGY |
+ BRUSH_AUTOMASKING_BOUNDARY_FACE_SETS))) {
+ initial_value = 1.0f;
+ }
+ else {
+ initial_value = 0.0f;
+ }
+
for (int i : IndexRange(totvert)) {
- automasking->factor[i] = 1.0f;
+ PBVHVertRef vertex = BKE_pbvh_index_to_vertex(ss->pbvh, i);
+
+ (*(float *)SCULPT_vertex_attr_get(vertex, ss->attrs.automasking_factor)) = initial_value;
}
const int boundary_propagation_steps = brush ?
brush->automasking_boundary_edges_propagation_steps :
1;
+ /* Additive modes. */
if (SCULPT_is_automasking_mode_enabled(sd, brush, BRUSH_AUTOMASKING_TOPOLOGY)) {
SCULPT_vertex_random_access_ensure(ss);
- SCULPT_topology_automasking_init(sd, ob, automasking->factor);
+ SCULPT_topology_automasking_init(sd, ob);
}
if (SCULPT_is_automasking_mode_enabled(sd, brush, BRUSH_AUTOMASKING_FACE_SETS)) {
SCULPT_vertex_random_access_ensure(ss);
- sculpt_face_sets_automasking_init(sd, ob, automasking->factor);
+ sculpt_face_sets_automasking_init(sd, ob);
}
if (SCULPT_is_automasking_mode_enabled(sd, brush, BRUSH_AUTOMASKING_BOUNDARY_EDGES)) {
SCULPT_vertex_random_access_ensure(ss);
- SCULPT_boundary_automasking_init(
- ob, AUTOMASK_INIT_BOUNDARY_EDGES, boundary_propagation_steps, automasking->factor);
+ SCULPT_boundary_automasking_init(ob, AUTOMASK_INIT_BOUNDARY_EDGES, boundary_propagation_steps);
}
if (SCULPT_is_automasking_mode_enabled(sd, brush, BRUSH_AUTOMASKING_BOUNDARY_FACE_SETS)) {
SCULPT_vertex_random_access_ensure(ss);
SCULPT_boundary_automasking_init(
- ob, AUTOMASK_INIT_BOUNDARY_FACE_SETS, boundary_propagation_steps, automasking->factor);
+ ob, AUTOMASK_INIT_BOUNDARY_FACE_SETS, boundary_propagation_steps);
+ }
+
+ /* Subtractive modes. */
+ int normal_bits = sculpt_automasking_mode_effective_bits(sd, brush) &
+ (BRUSH_AUTOMASKING_BRUSH_NORMAL | BRUSH_AUTOMASKING_VIEW_NORMAL |
+ BRUSH_AUTOMASKING_VIEW_OCCLUSION);
+
+ if (normal_bits) {
+ sculpt_normal_occlusion_automasking_fill(automasking, ob, (eAutomasking_flag)normal_bits);
}
return automasking;
}
+
+bool SCULPT_automasking_needs_original(const Sculpt *sd, const Brush *brush)
+{
+
+ return sculpt_automasking_mode_effective_bits(sd, brush) &
+ (BRUSH_AUTOMASKING_CAVITY_ALL | BRUSH_AUTOMASKING_BRUSH_NORMAL |
+ BRUSH_AUTOMASKING_VIEW_NORMAL);
+}
diff --git a/source/blender/editors/sculpt_paint/sculpt_boundary.c b/source/blender/editors/sculpt_paint/sculpt_boundary.c
index 005892b88a0..355f260ae11 100644
--- a/source/blender/editors/sculpt_paint/sculpt_boundary.c
+++ b/source/blender/editors/sculpt_paint/sculpt_boundary.c
@@ -7,13 +7,11 @@
#include "MEM_guardedalloc.h"
-#include "BLI_blenlib.h"
#include "BLI_edgehash.h"
#include "BLI_math.h"
#include "BLI_task.h"
#include "DNA_brush_types.h"
-#include "DNA_mesh_types.h"
#include "DNA_meshdata_types.h"
#include "DNA_object_types.h"
@@ -21,20 +19,13 @@
#include "BKE_ccg.h"
#include "BKE_colortools.h"
#include "BKE_context.h"
-#include "BKE_mesh.h"
-#include "BKE_multires.h"
-#include "BKE_node.h"
-#include "BKE_object.h"
#include "BKE_paint.h"
#include "BKE_pbvh.h"
-#include "BKE_scene.h"
#include "paint_intern.h"
#include "sculpt_intern.h"
#include "GPU_immediate.h"
-#include "GPU_immediate_util.h"
-#include "GPU_matrix.h"
#include "GPU_state.h"
#include "bmesh.h"
@@ -681,12 +672,16 @@ static void do_boundary_brush_bend_task_cb_ex(void *__restrict userdata,
angle_factor = floorf(angle_factor * 10) / 10.0f;
}
const float angle = angle_factor * M_PI;
+ AutomaskingNodeData automask_data;
+ SCULPT_automasking_node_begin(
+ data->ob, ss, ss->cache->automasking, &automask_data, data->nodes[n]);
BKE_pbvh_vertex_iter_begin (ss->pbvh, data->nodes[n], vd, PBVH_ITER_UNIQUE) {
if (boundary->edit_info[vd.index].propagation_steps_num == -1) {
continue;
}
+ SCULPT_automasking_node_update(ss, &automask_data, &vd);
SCULPT_orig_vert_data_update(&orig_data, &vd);
if (!SCULPT_check_vertex_pivot_symmetry(
orig_data.co, boundary->initial_vertex_position, symm)) {
@@ -694,7 +689,8 @@ static void do_boundary_brush_bend_task_cb_ex(void *__restrict userdata,
}
const float mask = vd.mask ? 1.0f - *vd.mask : 1.0f;
- const float automask = SCULPT_automasking_factor_get(ss->cache->automasking, ss, vd.vertex);
+ const float automask = SCULPT_automasking_factor_get(
+ ss->cache->automasking, ss, vd.vertex, &automask_data);
float t_orig_co[3];
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]);
@@ -729,12 +725,16 @@ static void do_boundary_brush_slide_task_cb_ex(void *__restrict userdata,
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);
+ AutomaskingNodeData automask_data;
+ SCULPT_automasking_node_begin(
+ data->ob, ss, ss->cache->automasking, &automask_data, data->nodes[n]);
BKE_pbvh_vertex_iter_begin (ss->pbvh, data->nodes[n], vd, PBVH_ITER_UNIQUE) {
if (boundary->edit_info[vd.index].propagation_steps_num == -1) {
continue;
}
+ SCULPT_automasking_node_update(ss, &automask_data, &vd);
SCULPT_orig_vert_data_update(&orig_data, &vd);
if (!SCULPT_check_vertex_pivot_symmetry(
orig_data.co, boundary->initial_vertex_position, symm)) {
@@ -742,7 +742,8 @@ static void do_boundary_brush_slide_task_cb_ex(void *__restrict userdata,
}
const float mask = vd.mask ? 1.0f - *vd.mask : 1.0f;
- const float automask = SCULPT_automasking_factor_get(ss->cache->automasking, ss, vd.vertex);
+ const float automask = SCULPT_automasking_factor_get(
+ ss->cache->automasking, ss, vd.vertex, &automask_data);
float *target_co = SCULPT_brush_deform_target_vertex_co_get(ss, brush->deform_target, &vd);
madd_v3_v3v3fl(target_co,
orig_data.co,
@@ -773,6 +774,9 @@ 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_UNDO_COORDS);
+ AutomaskingNodeData automask_data;
+ SCULPT_automasking_node_begin(
+ data->ob, ss, ss->cache->automasking, &automask_data, data->nodes[n]);
const float disp = sculpt_boundary_displacement_from_grab_delta_get(ss, boundary);
@@ -781,6 +785,7 @@ static void do_boundary_brush_inflate_task_cb_ex(void *__restrict userdata,
continue;
}
+ SCULPT_automasking_node_update(ss, &automask_data, &vd);
SCULPT_orig_vert_data_update(&orig_data, &vd);
if (!SCULPT_check_vertex_pivot_symmetry(
orig_data.co, boundary->initial_vertex_position, symm)) {
@@ -788,7 +793,8 @@ static void do_boundary_brush_inflate_task_cb_ex(void *__restrict userdata,
}
const float mask = vd.mask ? 1.0f - *vd.mask : 1.0f;
- const float automask = SCULPT_automasking_factor_get(ss->cache->automasking, ss, vd.vertex);
+ const float automask = SCULPT_automasking_factor_get(
+ ss->cache->automasking, ss, vd.vertex, &automask_data);
float *target_co = SCULPT_brush_deform_target_vertex_co_get(ss, brush->deform_target, &vd);
madd_v3_v3v3fl(target_co,
orig_data.co,
@@ -819,12 +825,16 @@ 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_UNDO_COORDS);
+ AutomaskingNodeData automask_data;
+ SCULPT_automasking_node_begin(
+ data->ob, ss, ss->cache->automasking, &automask_data, data->nodes[n]);
BKE_pbvh_vertex_iter_begin (ss->pbvh, data->nodes[n], vd, PBVH_ITER_UNIQUE) {
if (boundary->edit_info[vd.index].propagation_steps_num == -1) {
continue;
}
+ SCULPT_automasking_node_update(ss, &automask_data, &vd);
SCULPT_orig_vert_data_update(&orig_data, &vd);
if (!SCULPT_check_vertex_pivot_symmetry(
orig_data.co, boundary->initial_vertex_position, symm)) {
@@ -832,7 +842,8 @@ static void do_boundary_brush_grab_task_cb_ex(void *__restrict userdata,
}
const float mask = vd.mask ? 1.0f - *vd.mask : 1.0f;
- const float automask = SCULPT_automasking_factor_get(ss->cache->automasking, ss, vd.vertex);
+ const float automask = SCULPT_automasking_factor_get(
+ ss->cache->automasking, ss, vd.vertex, &automask_data);
float *target_co = SCULPT_brush_deform_target_vertex_co_get(ss, brush->deform_target, &vd);
madd_v3_v3v3fl(target_co,
orig_data.co,
@@ -862,6 +873,9 @@ 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_UNDO_COORDS);
+ AutomaskingNodeData automask_data;
+ SCULPT_automasking_node_begin(
+ data->ob, ss, ss->cache->automasking, &automask_data, data->nodes[n]);
const float disp = strength * sculpt_boundary_displacement_from_grab_delta_get(ss, boundary);
float angle_factor = disp / ss->cache->radius;
@@ -876,6 +890,7 @@ static void do_boundary_brush_twist_task_cb_ex(void *__restrict userdata,
continue;
}
+ SCULPT_automasking_node_update(ss, &automask_data, &vd);
SCULPT_orig_vert_data_update(&orig_data, &vd);
if (!SCULPT_check_vertex_pivot_symmetry(
orig_data.co, boundary->initial_vertex_position, symm)) {
@@ -883,7 +898,8 @@ static void do_boundary_brush_twist_task_cb_ex(void *__restrict userdata,
}
const float mask = vd.mask ? 1.0f - *vd.mask : 1.0f;
- const float automask = SCULPT_automasking_factor_get(ss->cache->automasking, ss, vd.vertex);
+ const float automask = SCULPT_automasking_factor_get(
+ ss->cache->automasking, ss, vd.vertex, &automask_data);
float t_orig_co[3];
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->twist.pivot_position);
diff --git a/source/blender/editors/sculpt_paint/sculpt_brush_types.c b/source/blender/editors/sculpt_paint/sculpt_brush_types.c
index 245cbe0f54e..666fa884e03 100644
--- a/source/blender/editors/sculpt_paint/sculpt_brush_types.c
+++ b/source/blender/editors/sculpt_paint/sculpt_brush_types.c
@@ -8,26 +8,15 @@
#include "MEM_guardedalloc.h"
-#include "BLI_blenlib.h"
-#include "BLI_dial_2d.h"
#include "BLI_ghash.h"
#include "BLI_gsqueue.h"
-#include "BLI_hash.h"
#include "BLI_math.h"
-#include "BLI_math_color.h"
-#include "BLI_math_color_blend.h"
#include "BLI_task.h"
#include "BLI_utildefines.h"
-#include "BLT_translation.h"
-
-#include "PIL_time.h"
-
#include "DNA_brush_types.h"
#include "DNA_customdata_types.h"
-#include "DNA_mesh_types.h"
#include "DNA_meshdata_types.h"
-#include "DNA_node_types.h"
#include "DNA_object_types.h"
#include "DNA_scene_types.h"
@@ -35,53 +24,16 @@
#include "BKE_ccg.h"
#include "BKE_colortools.h"
#include "BKE_context.h"
-#include "BKE_image.h"
#include "BKE_kelvinlet.h"
-#include "BKE_key.h"
-#include "BKE_lib_id.h"
-#include "BKE_main.h"
-#include "BKE_mesh.h"
-#include "BKE_mesh_mapping.h"
-#include "BKE_mesh_mirror.h"
-#include "BKE_modifier.h"
-#include "BKE_multires.h"
-#include "BKE_node.h"
-#include "BKE_object.h"
#include "BKE_paint.h"
-#include "BKE_particle.h"
#include "BKE_pbvh.h"
-#include "BKE_pointcache.h"
-#include "BKE_report.h"
-#include "BKE_scene.h"
-#include "BKE_screen.h"
-#include "BKE_subdiv_ccg.h"
-#include "BKE_subsurf.h"
-
-#include "DEG_depsgraph.h"
-
-#include "IMB_colormanagement.h"
-
-#include "WM_api.h"
-#include "WM_message.h"
-#include "WM_toolsystem.h"
-#include "WM_types.h"
-#include "ED_object.h"
-#include "ED_screen.h"
-#include "ED_sculpt.h"
#include "ED_view3d.h"
#include "paint_intern.h"
#include "sculpt_intern.h"
-#include "RNA_access.h"
-#include "RNA_define.h"
-
-#include "UI_interface.h"
-#include "UI_resources.h"
-
#include "bmesh.h"
-#include "bmesh_tools.h"
#include <math.h>
#include <stdlib.h>
@@ -179,7 +131,7 @@ static void calc_sculpt_plane(
}
/* For area normal. */
- if ((!SCULPT_stroke_is_first_brush_step_of_symmetry_pass(ss->cache)) &&
+ if (!SCULPT_stroke_is_first_brush_step_of_symmetry_pass(ss->cache) &&
(brush->flag & BRUSH_ORIGINAL_NORMAL)) {
copy_v3_v3(r_area_no, ss->cache->sculpt_normal);
}
@@ -188,7 +140,7 @@ static void calc_sculpt_plane(
}
/* For flatten center. */
- if ((!SCULPT_stroke_is_first_brush_step_of_symmetry_pass(ss->cache)) &&
+ if (!SCULPT_stroke_is_first_brush_step_of_symmetry_pass(ss->cache) &&
(brush->flag & BRUSH_ORIGINAL_PLANE)) {
copy_v3_v3(r_area_co, ss->cache->last_center);
}
@@ -302,10 +254,17 @@ static void do_draw_brush_task_cb_ex(void *__restrict userdata,
ss, &test, data->brush->falloff_shape);
const int thread_id = BLI_task_parallel_thread_id(tls);
+ AutomaskingNodeData automask_data;
+ SCULPT_automasking_node_begin(
+ data->ob, ss, ss->cache->automasking, &automask_data, data->nodes[n]);
+
BKE_pbvh_vertex_iter_begin (ss->pbvh, data->nodes[n], vd, PBVH_ITER_UNIQUE) {
if (!sculpt_brush_test_sq_fn(&test, vd.co)) {
continue;
}
+
+ SCULPT_automasking_node_update(ss, &automask_data, &vd);
+
/* Offset vertex. */
const float fade = SCULPT_brush_strength_factor(ss,
brush,
@@ -315,7 +274,8 @@ static void do_draw_brush_task_cb_ex(void *__restrict userdata,
vd.fno,
vd.mask ? *vd.mask : 0.0f,
vd.vertex,
- thread_id);
+ thread_id,
+ &automask_data);
mul_v3_v3fl(proxy[vd.i], offset, fade);
@@ -387,6 +347,10 @@ static void do_fill_brush_task_cb_ex(void *__restrict userdata,
plane_from_point_normal_v3(test.plane_tool, area_co, area_no);
+ AutomaskingNodeData automask_data;
+ SCULPT_automasking_node_begin(
+ data->ob, ss, ss->cache->automasking, &automask_data, data->nodes[n]);
+
BKE_pbvh_vertex_iter_begin (ss->pbvh, data->nodes[n], vd, PBVH_ITER_UNIQUE) {
if (!sculpt_brush_test_sq_fn(&test, vd.co)) {
continue;
@@ -405,6 +369,8 @@ static void do_fill_brush_task_cb_ex(void *__restrict userdata,
continue;
}
+ SCULPT_automasking_node_update(ss, &automask_data, &vd);
+
const float fade = bstrength * SCULPT_brush_strength_factor(ss,
brush,
vd.co,
@@ -413,7 +379,8 @@ static void do_fill_brush_task_cb_ex(void *__restrict userdata,
vd.fno,
vd.mask ? *vd.mask : 0.0f,
vd.vertex,
- thread_id);
+ thread_id,
+ &automask_data);
mul_v3_v3fl(proxy[vd.i], val, fade);
@@ -485,6 +452,10 @@ static void do_scrape_brush_task_cb_ex(void *__restrict userdata,
const int thread_id = BLI_task_parallel_thread_id(tls);
plane_from_point_normal_v3(test.plane_tool, area_co, area_no);
+ AutomaskingNodeData automask_data;
+ SCULPT_automasking_node_begin(
+ data->ob, ss, ss->cache->automasking, &automask_data, data->nodes[n]);
+
BKE_pbvh_vertex_iter_begin (ss->pbvh, data->nodes[n], vd, PBVH_ITER_UNIQUE) {
if (!sculpt_brush_test_sq_fn(&test, vd.co)) {
continue;
@@ -503,6 +474,8 @@ static void do_scrape_brush_task_cb_ex(void *__restrict userdata,
continue;
}
+ SCULPT_automasking_node_update(ss, &automask_data, &vd);
+
const float fade = bstrength * SCULPT_brush_strength_factor(ss,
brush,
vd.co,
@@ -511,7 +484,8 @@ static void do_scrape_brush_task_cb_ex(void *__restrict userdata,
vd.fno,
vd.mask ? *vd.mask : 0.0f,
vd.vertex,
- thread_id);
+ thread_id,
+ &automask_data);
mul_v3_v3fl(proxy[vd.i], val, fade);
@@ -601,6 +575,10 @@ static void do_clay_thumb_brush_task_cb_ex(void *__restrict userdata,
/* Tilted plane (front part of the brush). */
plane_from_point_normal_v3(plane_tilt, area_co, normal_tilt);
+ AutomaskingNodeData automask_data;
+ SCULPT_automasking_node_begin(
+ data->ob, ss, ss->cache->automasking, &automask_data, data->nodes[n]);
+
BKE_pbvh_vertex_iter_begin (ss->pbvh, data->nodes[n], vd, PBVH_ITER_UNIQUE) {
if (!sculpt_brush_test_sq_fn(&test, vd.co)) {
continue;
@@ -621,6 +599,8 @@ static void do_clay_thumb_brush_task_cb_ex(void *__restrict userdata,
interp_v3_v3v3(intr, intr, intr_tilt, tilt_mix);
sub_v3_v3v3(val, intr_tilt, vd.co);
+ SCULPT_automasking_node_update(ss, &automask_data, &vd);
+
const float fade = bstrength * SCULPT_brush_strength_factor(ss,
brush,
vd.co,
@@ -629,7 +609,8 @@ static void do_clay_thumb_brush_task_cb_ex(void *__restrict userdata,
vd.fno,
vd.mask ? *vd.mask : 0.0f,
vd.vertex,
- thread_id);
+ thread_id,
+ &automask_data);
mul_v3_v3fl(proxy[vd.i], val, fade);
@@ -764,6 +745,10 @@ static void do_flatten_brush_task_cb_ex(void *__restrict userdata,
plane_from_point_normal_v3(test.plane_tool, area_co, area_no);
+ AutomaskingNodeData automask_data;
+ SCULPT_automasking_node_begin(
+ data->ob, ss, ss->cache->automasking, &automask_data, data->nodes[n]);
+
BKE_pbvh_vertex_iter_begin (ss->pbvh, data->nodes[n], vd, PBVH_ITER_UNIQUE) {
if (!sculpt_brush_test_sq_fn(&test, vd.co)) {
continue;
@@ -776,6 +761,8 @@ static void do_flatten_brush_task_cb_ex(void *__restrict userdata,
sub_v3_v3v3(val, intr, vd.co);
if (SCULPT_plane_trim(ss->cache, brush, val)) {
+ SCULPT_automasking_node_update(ss, &automask_data, &vd);
+
const float fade = bstrength * SCULPT_brush_strength_factor(ss,
brush,
vd.co,
@@ -784,7 +771,8 @@ static void do_flatten_brush_task_cb_ex(void *__restrict userdata,
vd.fno,
vd.mask ? *vd.mask : 0.0f,
vd.vertex,
- thread_id);
+ thread_id,
+ &automask_data);
mul_v3_v3fl(proxy[vd.i], val, fade);
@@ -922,6 +910,10 @@ static void do_clay_brush_task_cb_ex(void *__restrict userdata,
plane_from_point_normal_v3(test.plane_tool, area_co, area_no);
+ AutomaskingNodeData automask_data;
+ SCULPT_automasking_node_begin(
+ data->ob, ss, ss->cache->automasking, &automask_data, data->nodes[n]);
+
BKE_pbvh_vertex_iter_begin (ss->pbvh, data->nodes[n], vd, PBVH_ITER_UNIQUE) {
if (!sculpt_brush_test_sq_fn(&test, vd.co)) {
continue;
@@ -933,6 +925,8 @@ static void do_clay_brush_task_cb_ex(void *__restrict userdata,
sub_v3_v3v3(val, intr, vd.co);
+ SCULPT_automasking_node_update(ss, &automask_data, &vd);
+
const float fade = bstrength * SCULPT_brush_strength_factor(ss,
brush,
vd.co,
@@ -941,7 +935,8 @@ static void do_clay_brush_task_cb_ex(void *__restrict userdata,
vd.fno,
vd.mask ? *vd.mask : 0.0f,
vd.vertex,
- thread_id);
+ thread_id,
+ &automask_data);
mul_v3_v3fl(proxy[vd.i], val, fade);
@@ -1041,6 +1036,10 @@ static void do_clay_strips_brush_task_cb_ex(void *__restrict userdata,
plane_from_point_normal_v3(test.plane_tool, area_co, area_no_sp);
const int thread_id = BLI_task_parallel_thread_id(tls);
+ AutomaskingNodeData automask_data;
+ SCULPT_automasking_node_begin(
+ data->ob, ss, ss->cache->automasking, &automask_data, data->nodes[n]);
+
BKE_pbvh_vertex_iter_begin (ss->pbvh, data->nodes[n], vd, PBVH_ITER_UNIQUE) {
if (!SCULPT_brush_test_cube(&test, vd.co, mat, brush->tip_roundness)) {
continue;
@@ -1058,6 +1057,9 @@ static void do_clay_strips_brush_task_cb_ex(void *__restrict userdata,
if (!SCULPT_plane_trim(ss->cache, brush, val)) {
continue;
}
+
+ SCULPT_automasking_node_update(ss, &automask_data, &vd);
+
/* The normal from the vertices is ignored, it causes glitch with planes, see: T44390. */
const float fade = bstrength * SCULPT_brush_strength_factor(ss,
brush,
@@ -1067,7 +1069,8 @@ static void do_clay_strips_brush_task_cb_ex(void *__restrict userdata,
vd.fno,
vd.mask ? *vd.mask : 0.0f,
vd.vertex,
- thread_id);
+ thread_id,
+ &automask_data);
mul_v3_v3fl(proxy[vd.i], val, fade);
@@ -1202,6 +1205,10 @@ static void do_snake_hook_brush_task_cb_ex(void *__restrict userdata,
KelvinletParams params;
BKE_kelvinlet_init_params(&params, ss->cache->radius, bstrength, 1.0f, 0.4f);
+ AutomaskingNodeData automask_data;
+ SCULPT_automasking_node_begin(
+ data->ob, ss, ss->cache->automasking, &automask_data, data->nodes[n]);
+
BKE_pbvh_vertex_iter_begin (ss->pbvh, data->nodes[n], vd, PBVH_ITER_UNIQUE) {
if (!do_elastic && !sculpt_brush_test_sq_fn(&test, vd.co)) {
continue;
@@ -1212,6 +1219,8 @@ static void do_snake_hook_brush_task_cb_ex(void *__restrict userdata,
fade = 1.0f;
}
else {
+ SCULPT_automasking_node_update(ss, &automask_data, &vd);
+
fade = bstrength * SCULPT_brush_strength_factor(ss,
brush,
vd.co,
@@ -1220,7 +1229,8 @@ static void do_snake_hook_brush_task_cb_ex(void *__restrict userdata,
vd.fno,
vd.mask ? *vd.mask : 0.0f,
vd.vertex,
- thread_id);
+ thread_id,
+ &automask_data);
}
mul_v3_v3fl(proxy[vd.i], grab_delta, fade);
@@ -1267,7 +1277,9 @@ 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.vertex));
+ mul_v3_fl(
+ disp,
+ SCULPT_automasking_factor_get(ss->cache->automasking, ss, vd.vertex, &automask_data));
copy_v3_v3(proxy[vd.i], disp);
}
@@ -1339,12 +1351,18 @@ static void do_thumb_brush_task_cb_ex(void *__restrict userdata,
ss, &test, data->brush->falloff_shape);
const int thread_id = BLI_task_parallel_thread_id(tls);
+ AutomaskingNodeData automask_data;
+ SCULPT_automasking_node_begin(
+ data->ob, ss, ss->cache->automasking, &automask_data, data->nodes[n]);
+
BKE_pbvh_vertex_iter_begin (ss->pbvh, data->nodes[n], vd, PBVH_ITER_UNIQUE) {
SCULPT_orig_vert_data_update(&orig_data, &vd);
if (!sculpt_brush_test_sq_fn(&test, orig_data.co)) {
continue;
}
+ SCULPT_automasking_node_update(ss, &automask_data, &vd);
+
const float fade = bstrength * SCULPT_brush_strength_factor(ss,
brush,
orig_data.co,
@@ -1353,7 +1371,8 @@ static void do_thumb_brush_task_cb_ex(void *__restrict userdata,
NULL,
vd.mask ? *vd.mask : 0.0f,
vd.vertex,
- thread_id);
+ thread_id,
+ &automask_data);
mul_v3_v3fl(proxy[vd.i], cono, fade);
@@ -1412,12 +1431,19 @@ static void do_rotate_brush_task_cb_ex(void *__restrict userdata,
ss, &test, data->brush->falloff_shape);
const int thread_id = BLI_task_parallel_thread_id(tls);
+ AutomaskingNodeData automask_data;
+ SCULPT_automasking_node_begin(
+ data->ob, ss, ss->cache->automasking, &automask_data, data->nodes[n]);
+
BKE_pbvh_vertex_iter_begin (ss->pbvh, data->nodes[n], vd, PBVH_ITER_UNIQUE) {
SCULPT_orig_vert_data_update(&orig_data, &vd);
if (!sculpt_brush_test_sq_fn(&test, orig_data.co)) {
continue;
}
+
+ SCULPT_automasking_node_update(ss, &automask_data, &vd);
+
float vec[3], rot[3][3];
const float fade = bstrength * SCULPT_brush_strength_factor(ss,
brush,
@@ -1427,7 +1453,8 @@ static void do_rotate_brush_task_cb_ex(void *__restrict userdata,
NULL,
vd.mask ? *vd.mask : 0.0f,
vd.vertex,
- thread_id);
+ thread_id,
+ &automask_data);
sub_v3_v3v3(vec, orig_data.co, ss->cache->location);
axis_angle_normalized_to_mat3(rot, ss->cache->sculpt_normal_symm, angle * fade);
@@ -1472,7 +1499,8 @@ static void do_layer_brush_task_cb_ex(void *__restrict userdata,
Sculpt *sd = data->sd;
const Brush *brush = data->brush;
- const bool use_persistent_base = ss->persistent_base && brush->flag & BRUSH_PERSISTENT;
+ const bool use_persistent_base = !ss->bm && ss->attrs.persistent_co &&
+ brush->flag & BRUSH_PERSISTENT;
PBVHVertexIter vd;
SculptOrigVertData orig_data;
@@ -1484,12 +1512,18 @@ static void do_layer_brush_task_cb_ex(void *__restrict userdata,
ss, &test, data->brush->falloff_shape);
const int thread_id = BLI_task_parallel_thread_id(tls);
+ AutomaskingNodeData automask_data;
+ SCULPT_automasking_node_begin(
+ data->ob, ss, ss->cache->automasking, &automask_data, data->nodes[n]);
+
BKE_pbvh_vertex_iter_begin (ss->pbvh, data->nodes[n], vd, PBVH_ITER_UNIQUE) {
SCULPT_orig_vert_data_update(&orig_data, &vd);
if (!sculpt_brush_test_sq_fn(&test, orig_data.co)) {
continue;
}
+ SCULPT_automasking_node_update(ss, &automask_data, &vd);
+
const float fade = SCULPT_brush_strength_factor(ss,
brush,
vd.co,
@@ -1498,12 +1532,13 @@ static void do_layer_brush_task_cb_ex(void *__restrict userdata,
vd.fno,
vd.mask ? *vd.mask : 0.0f,
vd.vertex,
- thread_id);
+ thread_id,
+ &automask_data);
const int vi = vd.index;
float *disp_factor;
if (use_persistent_base) {
- disp_factor = &ss->persistent_base[vi].disp;
+ disp_factor = (float *)SCULPT_vertex_attr_get(vd.vertex, ss->attrs.persistent_disp);
}
else {
disp_factor = &ss->cache->layer_displacement_factor[vi];
@@ -1599,10 +1634,16 @@ static void do_inflate_brush_task_cb_ex(void *__restrict userdata,
ss, &test, data->brush->falloff_shape);
const int thread_id = BLI_task_parallel_thread_id(tls);
+ AutomaskingNodeData automask_data;
+ SCULPT_automasking_node_begin(
+ data->ob, ss, ss->cache->automasking, &automask_data, data->nodes[n]);
+
BKE_pbvh_vertex_iter_begin (ss->pbvh, data->nodes[n], vd, PBVH_ITER_UNIQUE) {
if (!sculpt_brush_test_sq_fn(&test, vd.co)) {
continue;
}
+ SCULPT_automasking_node_update(ss, &automask_data, &vd);
+
const float fade = bstrength * SCULPT_brush_strength_factor(ss,
brush,
vd.co,
@@ -1611,7 +1652,8 @@ static void do_inflate_brush_task_cb_ex(void *__restrict userdata,
vd.fno,
vd.mask ? *vd.mask : 0.0f,
vd.vertex,
- thread_id);
+ thread_id,
+ &automask_data);
float val[3];
if (vd.fno) {
@@ -1667,10 +1709,16 @@ static void do_nudge_brush_task_cb_ex(void *__restrict userdata,
ss, &test, data->brush->falloff_shape);
const int thread_id = BLI_task_parallel_thread_id(tls);
+ AutomaskingNodeData automask_data;
+ SCULPT_automasking_node_begin(
+ data->ob, ss, ss->cache->automasking, &automask_data, data->nodes[n]);
+
BKE_pbvh_vertex_iter_begin (ss->pbvh, data->nodes[n], vd, PBVH_ITER_UNIQUE) {
if (!sculpt_brush_test_sq_fn(&test, vd.co)) {
continue;
}
+ SCULPT_automasking_node_update(ss, &automask_data, &vd);
+
const float fade = bstrength * SCULPT_brush_strength_factor(ss,
brush,
vd.co,
@@ -1679,7 +1727,8 @@ static void do_nudge_brush_task_cb_ex(void *__restrict userdata,
vd.fno,
vd.mask ? *vd.mask : 0.0f,
vd.vertex,
- thread_id);
+ thread_id,
+ &automask_data);
mul_v3_v3fl(proxy[vd.i], cono, fade);
@@ -1745,11 +1794,17 @@ static void do_crease_brush_task_cb_ex(void *__restrict userdata,
ss, &test, data->brush->falloff_shape);
const int thread_id = BLI_task_parallel_thread_id(tls);
+ AutomaskingNodeData automask_data;
+ SCULPT_automasking_node_begin(
+ data->ob, ss, ss->cache->automasking, &automask_data, data->nodes[n]);
+
BKE_pbvh_vertex_iter_begin (ss->pbvh, data->nodes[n], vd, PBVH_ITER_UNIQUE) {
if (!sculpt_brush_test_sq_fn(&test, vd.co)) {
continue;
}
/* Offset vertex. */
+ SCULPT_automasking_node_update(ss, &automask_data, &vd);
+
const float fade = SCULPT_brush_strength_factor(ss,
brush,
vd.co,
@@ -1758,7 +1813,8 @@ static void do_crease_brush_task_cb_ex(void *__restrict userdata,
vd.fno,
vd.mask ? *vd.mask : 0.0f,
vd.vertex,
- thread_id);
+ thread_id,
+ &automask_data);
float val1[3];
float val2[3];
@@ -1862,10 +1918,16 @@ static void do_pinch_brush_task_cb_ex(void *__restrict userdata,
copy_v3_v3(x_object_space, stroke_xz[0]);
copy_v3_v3(z_object_space, stroke_xz[1]);
+ AutomaskingNodeData automask_data;
+ SCULPT_automasking_node_begin(
+ data->ob, ss, ss->cache->automasking, &automask_data, data->nodes[n]);
+
BKE_pbvh_vertex_iter_begin (ss->pbvh, data->nodes[n], vd, PBVH_ITER_UNIQUE) {
if (!sculpt_brush_test_sq_fn(&test, vd.co)) {
continue;
}
+ SCULPT_automasking_node_update(ss, &automask_data, &vd);
+
const float fade = bstrength * SCULPT_brush_strength_factor(ss,
brush,
vd.co,
@@ -1874,7 +1936,8 @@ static void do_pinch_brush_task_cb_ex(void *__restrict userdata,
vd.fno,
vd.mask ? *vd.mask : 0.0f,
vd.vertex,
- thread_id);
+ thread_id,
+ &automask_data);
float disp_center[3];
float x_disp[3];
float z_disp[3];
@@ -1976,12 +2039,18 @@ static void do_grab_brush_task_cb_ex(void *__restrict userdata,
const bool grab_silhouette = brush->flag2 & BRUSH_GRAB_SILHOUETTE;
+ AutomaskingNodeData automask_data;
+ SCULPT_automasking_node_begin(
+ data->ob, ss, ss->cache->automasking, &automask_data, data->nodes[n]);
+
BKE_pbvh_vertex_iter_begin (ss->pbvh, data->nodes[n], vd, PBVH_ITER_UNIQUE) {
SCULPT_orig_vert_data_update(&orig_data, &vd);
if (!sculpt_brush_test_sq_fn(&test, orig_data.co)) {
continue;
}
+ SCULPT_automasking_node_update(ss, &automask_data, &vd);
+
float fade = bstrength * SCULPT_brush_strength_factor(ss,
brush,
orig_data.co,
@@ -1990,7 +2059,8 @@ static void do_grab_brush_task_cb_ex(void *__restrict userdata,
NULL,
vd.mask ? *vd.mask : 0.0f,
vd.vertex,
- thread_id);
+ thread_id,
+ &automask_data);
if (grab_silhouette) {
float silhouette_test_dir[3];
@@ -2054,6 +2124,9 @@ 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_UNDO_COORDS);
+ AutomaskingNodeData automask_data;
+ SCULPT_automasking_node_begin(
+ data->ob, ss, ss->cache->automasking, &automask_data, data->nodes[n]);
proxy = BKE_pbvh_node_add_proxy(ss->pbvh, data->nodes[n])->co;
@@ -2079,6 +2152,8 @@ static void do_elastic_deform_brush_task_cb_ex(void *__restrict userdata,
BKE_pbvh_vertex_iter_begin (ss->pbvh, data->nodes[n], vd, PBVH_ITER_UNIQUE) {
SCULPT_orig_vert_data_update(&orig_data, &vd);
+ SCULPT_automasking_node_update(ss, &automask_data, &vd);
+
float final_disp[3];
switch (brush->elastic_deform_type) {
case BRUSH_ELASTIC_DEFORM_GRAB:
@@ -2109,7 +2184,9 @@ 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.vertex));
+ mul_v3_fl(
+ final_disp,
+ SCULPT_automasking_factor_get(ss->cache->automasking, ss, vd.vertex, &automask_data));
copy_v3_v3(proxy[vd.i], final_disp);
@@ -2173,12 +2250,18 @@ static void do_draw_sharp_brush_task_cb_ex(void *__restrict userdata,
ss, &test, data->brush->falloff_shape);
const int thread_id = BLI_task_parallel_thread_id(tls);
+ AutomaskingNodeData automask_data;
+ SCULPT_automasking_node_begin(
+ data->ob, ss, ss->cache->automasking, &automask_data, data->nodes[n]);
+
BKE_pbvh_vertex_iter_begin (ss->pbvh, data->nodes[n], vd, PBVH_ITER_UNIQUE) {
SCULPT_orig_vert_data_update(&orig_data, &vd);
if (!sculpt_brush_test_sq_fn(&test, orig_data.co)) {
continue;
}
/* Offset vertex. */
+ SCULPT_automasking_node_update(ss, &automask_data, &vd);
+
const float fade = SCULPT_brush_strength_factor(ss,
brush,
orig_data.co,
@@ -2187,7 +2270,8 @@ static void do_draw_sharp_brush_task_cb_ex(void *__restrict userdata,
NULL,
vd.mask ? *vd.mask : 0.0f,
vd.vertex,
- thread_id);
+ thread_id,
+ &automask_data);
mul_v3_v3fl(proxy[vd.i], offset, fade);
@@ -2257,11 +2341,17 @@ static void do_topology_slide_task_cb_ex(void *__restrict userdata,
ss, &test, data->brush->falloff_shape);
const int thread_id = BLI_task_parallel_thread_id(tls);
+ AutomaskingNodeData automask_data;
+ SCULPT_automasking_node_begin(
+ data->ob, ss, ss->cache->automasking, &automask_data, data->nodes[n]);
+
BKE_pbvh_vertex_iter_begin (ss->pbvh, data->nodes[n], vd, PBVH_ITER_UNIQUE) {
SCULPT_orig_vert_data_update(&orig_data, &vd);
if (!sculpt_brush_test_sq_fn(&test, orig_data.co)) {
continue;
}
+ SCULPT_automasking_node_update(ss, &automask_data, &vd);
+
const float fade = SCULPT_brush_strength_factor(ss,
brush,
orig_data.co,
@@ -2270,7 +2360,8 @@ static void do_topology_slide_task_cb_ex(void *__restrict userdata,
NULL,
vd.mask ? *vd.mask : 0.0f,
vd.vertex,
- thread_id);
+ thread_id,
+ &automask_data);
float current_disp[3];
float current_disp_norm[3];
float final_disp[3] = {0.0f, 0.0f, 0.0f};
@@ -2414,11 +2505,17 @@ static void do_topology_relax_task_cb_ex(void *__restrict userdata,
ss, &test, data->brush->falloff_shape);
const int thread_id = BLI_task_parallel_thread_id(tls);
+ AutomaskingNodeData automask_data;
+ SCULPT_automasking_node_begin(
+ data->ob, ss, ss->cache->automasking, &automask_data, data->nodes[n]);
+
BKE_pbvh_vertex_iter_begin (ss->pbvh, data->nodes[n], vd, PBVH_ITER_UNIQUE) {
SCULPT_orig_vert_data_update(&orig_data, &vd);
if (!sculpt_brush_test_sq_fn(&test, orig_data.co)) {
continue;
}
+ SCULPT_automasking_node_update(ss, &automask_data, &vd);
+
const float fade = SCULPT_brush_strength_factor(ss,
brush,
orig_data.co,
@@ -2427,7 +2524,8 @@ static void do_topology_relax_task_cb_ex(void *__restrict userdata,
NULL,
vd.mask ? *vd.mask : 0.0f,
vd.vertex,
- thread_id);
+ thread_id,
+ &automask_data);
SCULPT_relax_vertex(ss, &vd, fade * bstrength, false, vd.co);
if (vd.mvert) {
@@ -2490,11 +2588,17 @@ static void do_displacement_eraser_brush_task_cb_ex(void *__restrict userdata,
ss, &test, data->brush->falloff_shape);
const int thread_id = BLI_task_parallel_thread_id(tls);
+ AutomaskingNodeData automask_data;
+ SCULPT_automasking_node_begin(
+ data->ob, ss, ss->cache->automasking, &automask_data, data->nodes[n]);
+
PBVHVertexIter vd;
BKE_pbvh_vertex_iter_begin (ss->pbvh, data->nodes[n], vd, PBVH_ITER_UNIQUE) {
if (!sculpt_brush_test_sq_fn(&test, vd.co)) {
continue;
}
+ SCULPT_automasking_node_update(ss, &automask_data, &vd);
+
const float fade = bstrength * SCULPT_brush_strength_factor(ss,
brush,
vd.co,
@@ -2503,7 +2607,8 @@ static void do_displacement_eraser_brush_task_cb_ex(void *__restrict userdata,
vd.fno,
vd.mask ? *vd.mask : 0.0f,
vd.vertex,
- thread_id);
+ thread_id,
+ &automask_data);
float limit_co[3];
float disp[3];
@@ -2556,11 +2661,17 @@ static void do_displacement_smear_brush_task_cb_ex(void *__restrict userdata,
ss, &test, data->brush->falloff_shape);
const int thread_id = BLI_task_parallel_thread_id(tls);
+ AutomaskingNodeData automask_data;
+ SCULPT_automasking_node_begin(
+ data->ob, ss, ss->cache->automasking, &automask_data, data->nodes[n]);
+
PBVHVertexIter vd;
BKE_pbvh_vertex_iter_begin (ss->pbvh, data->nodes[n], vd, PBVH_ITER_UNIQUE) {
if (!sculpt_brush_test_sq_fn(&test, vd.co)) {
continue;
}
+ SCULPT_automasking_node_update(ss, &automask_data, &vd);
+
const float fade = bstrength * SCULPT_brush_strength_factor(ss,
brush,
vd.co,
@@ -2569,7 +2680,8 @@ static void do_displacement_smear_brush_task_cb_ex(void *__restrict userdata,
vd.fno,
vd.mask ? *vd.mask : 0.0f,
vd.vertex,
- thread_id);
+ thread_id,
+ &automask_data);
float current_disp[3];
float current_disp_norm[3];
@@ -2717,16 +2829,29 @@ static void do_topology_rake_bmesh_task_cb_ex(void *__restrict userdata,
ss, &test, data->brush->falloff_shape);
const int thread_id = BLI_task_parallel_thread_id(tls);
+ AutomaskingNodeData automask_data;
+ SCULPT_automasking_node_begin(
+ data->ob, ss, ss->cache->automasking, &automask_data, data->nodes[n]);
+
PBVHVertexIter vd;
BKE_pbvh_vertex_iter_begin (ss->pbvh, data->nodes[n], vd, PBVH_ITER_UNIQUE) {
if (!sculpt_brush_test_sq_fn(&test, vd.co)) {
continue;
}
- const float fade =
- bstrength *
- SCULPT_brush_strength_factor(
- ss, brush, vd.co, sqrtf(test.dist), vd.no, vd.fno, *vd.mask, vd.vertex, thread_id) *
- ss->cache->pressure;
+ SCULPT_automasking_node_update(ss, &automask_data, &vd);
+
+ const float fade = bstrength *
+ SCULPT_brush_strength_factor(ss,
+ brush,
+ vd.co,
+ sqrtf(test.dist),
+ vd.no,
+ vd.fno,
+ *vd.mask,
+ vd.vertex,
+ thread_id,
+ &automask_data) *
+ ss->cache->pressure;
float avg[3], val[3];
@@ -2796,13 +2921,26 @@ static void do_mask_brush_draw_task_cb_ex(void *__restrict userdata,
ss, &test, data->brush->falloff_shape);
const int thread_id = BLI_task_parallel_thread_id(tls);
+ AutomaskingNodeData automask_data;
+ SCULPT_automasking_node_begin(
+ data->ob, ss, ss->cache->automasking, &automask_data, data->nodes[n]);
+
BKE_pbvh_vertex_iter_begin (ss->pbvh, data->nodes[n], vd, PBVH_ITER_UNIQUE) {
if (!sculpt_brush_test_sq_fn(&test, vd.co)) {
continue;
}
- const float fade = SCULPT_brush_strength_factor(
- ss, brush, vd.co, sqrtf(test.dist), vd.no, vd.fno, 0.0f, vd.vertex, thread_id);
+ SCULPT_automasking_node_update(ss, &automask_data, &vd);
+ const float fade = SCULPT_brush_strength_factor(ss,
+ brush,
+ vd.co,
+ sqrtf(test.dist),
+ vd.no,
+ vd.fno,
+ 0.0f,
+ vd.vertex,
+ thread_id,
+ &automask_data);
if (bstrength > 0.0f) {
(*vd.mask) += fade * bstrength * (1.0f - *vd.mask);
diff --git a/source/blender/editors/sculpt_paint/sculpt_cloth.c b/source/blender/editors/sculpt_paint/sculpt_cloth.c
index 691dfa21851..cf7e1d027f7 100644
--- a/source/blender/editors/sculpt_paint/sculpt_cloth.c
+++ b/source/blender/editors/sculpt_paint/sculpt_cloth.c
@@ -7,22 +7,15 @@
#include "MEM_guardedalloc.h"
-#include "BLI_blenlib.h"
-#include "BLI_dial_2d.h"
#include "BLI_edgehash.h"
#include "BLI_gsqueue.h"
-#include "BLI_hash.h"
#include "BLI_math.h"
#include "BLI_task.h"
#include "BLI_utildefines.h"
-#include "BLT_translation.h"
-
#include "DNA_brush_types.h"
#include "DNA_customdata_types.h"
-#include "DNA_mesh_types.h"
#include "DNA_meshdata_types.h"
-#include "DNA_node_types.h"
#include "DNA_object_types.h"
#include "DNA_scene_types.h"
@@ -32,41 +25,16 @@
#include "BKE_collision.h"
#include "BKE_colortools.h"
#include "BKE_context.h"
-#include "BKE_image.h"
-#include "BKE_kelvinlet.h"
-#include "BKE_key.h"
-#include "BKE_lib_id.h"
-#include "BKE_main.h"
-#include "BKE_mesh.h"
-#include "BKE_mesh_mapping.h"
-#include "BKE_mesh_mirror.h"
#include "BKE_modifier.h"
-#include "BKE_multires.h"
-#include "BKE_node.h"
-#include "BKE_object.h"
#include "BKE_paint.h"
-#include "BKE_particle.h"
#include "BKE_pbvh.h"
-#include "BKE_pointcache.h"
-#include "BKE_report.h"
-#include "BKE_scene.h"
-#include "BKE_screen.h"
-#include "BKE_subdiv_ccg.h"
-#include "BKE_subsurf.h"
#include "DEG_depsgraph.h"
#include "DEG_depsgraph_query.h"
#include "WM_api.h"
-#include "WM_message.h"
-#include "WM_toolsystem.h"
#include "WM_types.h"
-#include "ED_object.h"
-#include "ED_screen.h"
-#include "ED_sculpt.h"
-#include "ED_view3d.h"
-#include "paint_intern.h"
#include "sculpt_intern.h"
#include "RNA_access.h"
@@ -78,10 +46,8 @@
#include "GPU_state.h"
#include "UI_interface.h"
-#include "UI_resources.h"
#include "bmesh.h"
-#include "bmesh_tools.h"
#include <math.h>
#include <stdlib.h>
@@ -504,7 +470,13 @@ static void do_cloth_brush_apply_forces_task_cb_ex(void *__restrict userdata,
madd_v3_v3fl(gravity, ss->cache->gravity_direction, -data->sd->gravity_factor);
}
+ AutomaskingNodeData automask_data;
+ SCULPT_automasking_node_begin(
+ data->ob, ss, SCULPT_automasking_active_cache_get(ss), &automask_data, data->nodes[n]);
+
BKE_pbvh_vertex_iter_begin (ss->pbvh, data->nodes[n], vd, PBVH_ITER_UNIQUE) {
+ SCULPT_automasking_node_update(ss, &automask_data, &vd);
+
float force[3];
float sim_location[3];
cloth_brush_simulation_location_get(ss, brush, sim_location);
@@ -544,7 +516,8 @@ static void do_cloth_brush_apply_forces_task_cb_ex(void *__restrict userdata,
vd.fno,
vd.mask ? *vd.mask : 0.0f,
vd.vertex,
- thread_id);
+ thread_id,
+ &automask_data);
float brush_disp[3];
@@ -617,10 +590,11 @@ static void do_cloth_brush_apply_forces_task_cb_ex(void *__restrict userdata,
static ListBase *cloth_brush_collider_cache_create(Object *object, Depsgraph *depsgraph)
{
ListBase *cache = NULL;
- DEG_OBJECT_ITER_BEGIN (depsgraph,
- ob,
- DEG_ITER_OBJECT_FLAG_LINKED_DIRECTLY | DEG_ITER_OBJECT_FLAG_VISIBLE |
- DEG_ITER_OBJECT_FLAG_DUPLI) {
+ DEGObjectIterSettings deg_iter_settings = {0};
+ deg_iter_settings.depsgraph = depsgraph;
+ deg_iter_settings.flags = DEG_ITER_OBJECT_FLAG_LINKED_DIRECTLY | DEG_ITER_OBJECT_FLAG_VISIBLE |
+ DEG_ITER_OBJECT_FLAG_DUPLI;
+ DEG_OBJECT_ITER_BEGIN (&deg_iter_settings, ob) {
if (STREQ(object->id.name, ob->id.name)) {
continue;
}
@@ -693,15 +667,15 @@ static void cloth_brush_solve_collision(Object *object,
BVHTreeRayHit hit;
float obmat_inv[4][4];
- invert_m4_m4(obmat_inv, object->obmat);
+ invert_m4_m4(obmat_inv, object->object_to_world);
for (collider_cache = cloth_sim->collider_list->first; collider_cache;
collider_cache = collider_cache->next) {
float ray_start[3], ray_normal[3];
float pos_world_space[3], prev_pos_world_space[3];
- mul_v3_m4v3(pos_world_space, object->obmat, cloth_sim->pos[i]);
- mul_v3_m4v3(prev_pos_world_space, object->obmat, cloth_sim->last_iteration_pos[i]);
+ mul_v3_m4v3(pos_world_space, object->object_to_world, cloth_sim->pos[i]);
+ mul_v3_m4v3(prev_pos_world_space, object->object_to_world, cloth_sim->last_iteration_pos[i]);
sub_v3_v3v3(ray_normal, pos_world_space, prev_pos_world_space);
copy_v3_v3(ray_start, prev_pos_world_space);
hit.index = -1;
@@ -764,8 +738,13 @@ static void do_cloth_brush_solve_simulation_task_cb_ex(
}
AutomaskingCache *automasking = SCULPT_automasking_active_cache_get(ss);
+ AutomaskingNodeData automask_data;
+ SCULPT_automasking_node_begin(
+ data->ob, ss, SCULPT_automasking_active_cache_get(ss), &automask_data, data->nodes[n]);
BKE_pbvh_vertex_iter_begin (ss->pbvh, data->nodes[n], vd, PBVH_ITER_UNIQUE) {
+ SCULPT_automasking_node_update(ss, &automask_data, &vd);
+
float sim_location[3];
cloth_brush_simulation_location_get(ss, brush, sim_location);
const float sim_factor =
@@ -787,7 +766,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.vertex);
+ SCULPT_automasking_factor_get(automasking, ss, vd.vertex, &automask_data);
madd_v3_v3fl(cloth_sim->pos[i], pos_diff, mask_v);
madd_v3_v3fl(cloth_sim->pos[i], cloth_sim->acceleration[i], mask_v);
@@ -820,6 +799,9 @@ static void cloth_brush_satisfy_constraints(SculptSession *ss,
{
AutomaskingCache *automasking = SCULPT_automasking_active_cache_get(ss);
+ AutomaskingNodeData automask_data = {0};
+
+ automask_data.have_orig_data = true;
for (int constraint_it = 0; constraint_it < CLOTH_SIMULATION_ITERATIONS; constraint_it++) {
for (int i = 0; i < cloth_sim->tot_length_constraints; i++) {
@@ -858,10 +840,17 @@ static void cloth_brush_satisfy_constraints(SculptSession *ss,
PBVHVertRef vertex1 = BKE_pbvh_index_to_vertex(ss->pbvh, v1);
PBVHVertRef vertex2 = BKE_pbvh_index_to_vertex(ss->pbvh, v2);
+ automask_data.orig_data.co = cloth_sim->init_pos[v1];
+ automask_data.orig_data.no = cloth_sim->init_no[v1];
const float mask_v1 = (1.0f - SCULPT_vertex_mask_get(ss, vertex1)) *
- SCULPT_automasking_factor_get(automasking, ss, vertex1);
+ SCULPT_automasking_factor_get(
+ automasking, ss, vertex1, &automask_data);
+
+ automask_data.orig_data.co = cloth_sim->init_pos[v2];
+ automask_data.orig_data.no = cloth_sim->init_no[v2];
const float mask_v2 = (1.0f - SCULPT_vertex_mask_get(ss, vertex2)) *
- SCULPT_automasking_factor_get(automasking, ss, vertex2);
+ SCULPT_automasking_factor_get(
+ automasking, ss, vertex2, &automask_data);
float sim_location[3];
cloth_brush_simulation_location_get(ss, brush, sim_location);
@@ -1064,6 +1053,7 @@ SculptClothSimulation *SCULPT_cloth_brush_simulation_create(Object *ob,
cloth_sim->last_iteration_pos = MEM_calloc_arrayN(
totverts, sizeof(float[3]), "cloth sim last iteration pos");
cloth_sim->init_pos = MEM_calloc_arrayN(totverts, sizeof(float[3]), "cloth sim init pos");
+ cloth_sim->init_no = MEM_calloc_arrayN(totverts, sizeof(float[3]), "cloth sim init normals");
cloth_sim->length_constraint_tweak = MEM_calloc_arrayN(
totverts, sizeof(float), "cloth sim length tweak");
@@ -1139,6 +1129,7 @@ void SCULPT_cloth_brush_simulation_init(SculptSession *ss, SculptClothSimulation
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));
+ SCULPT_vertex_normal_get(ss, vertex, cloth_sim->init_no[i]);
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, vertex));
@@ -1252,6 +1243,7 @@ void SCULPT_cloth_simulation_free(struct SculptClothSimulation *cloth_sim)
MEM_SAFE_FREE(cloth_sim->deformation_pos);
MEM_SAFE_FREE(cloth_sim->softbody_pos);
MEM_SAFE_FREE(cloth_sim->init_pos);
+ MEM_SAFE_FREE(cloth_sim->init_no);
MEM_SAFE_FREE(cloth_sim->deformation_strength);
MEM_SAFE_FREE(cloth_sim->node_state);
BLI_ghash_free(cloth_sim->node_state_index, NULL, NULL);
@@ -1427,17 +1419,23 @@ static void cloth_filter_apply_forces_task_cb(void *__restrict userdata,
float sculpt_gravity[3] = {0.0f};
if (sd->gravity_object) {
- copy_v3_v3(sculpt_gravity, sd->gravity_object->obmat[2]);
+ copy_v3_v3(sculpt_gravity, sd->gravity_object->object_to_world[2]);
}
else {
sculpt_gravity[2] = -1.0f;
}
mul_v3_fl(sculpt_gravity, sd->gravity_factor * data->filter_strength);
+ AutomaskingNodeData automask_data;
+ SCULPT_automasking_node_begin(
+ data->ob, ss, SCULPT_automasking_active_cache_get(ss), &automask_data, node);
PBVHVertexIter vd;
BKE_pbvh_vertex_iter_begin (ss->pbvh, node, vd, PBVH_ITER_UNIQUE) {
+ SCULPT_automasking_node_update(ss, &automask_data, &vd);
+
float fade = vd.mask ? *vd.mask : 0.0f;
- fade *= SCULPT_automasking_factor_get(ss->filter_cache->automasking, ss, vd.vertex);
+ fade *= SCULPT_automasking_factor_get(
+ ss->filter_cache->automasking, ss, vd.vertex, &automask_data);
fade = 1.0f - fade;
float force[3] = {0.0f, 0.0f, 0.0f};
float disp[3], temp[3], transform[3][3];
@@ -1579,8 +1577,11 @@ static int sculpt_cloth_filter_invoke(bContext *C, wmOperator *op, const wmEvent
/* Needs mask data to be available as it is used when solving the constraints. */
BKE_sculpt_update_object_for_edit(depsgraph, ob, true, true, false);
+ SCULPT_stroke_id_next(ob);
+
SCULPT_undo_push_begin(ob, op);
- SCULPT_filter_cache_init(C, ob, sd, SCULPT_UNDO_COORDS);
+ SCULPT_filter_cache_init(
+ C, ob, sd, SCULPT_UNDO_COORDS, event->mval, RNA_float_get(op->ptr, "area_normal_radius"));
ss->filter_cache->automasking = SCULPT_automasking_cache_init(sd, NULL, ob);
@@ -1643,14 +1644,14 @@ void SCULPT_OT_cloth_filter(struct wmOperatorType *ot)
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
/* RNA. */
+ SCULPT_mesh_filter_properties(ot);
+
RNA_def_enum(ot->srna,
"type",
prop_cloth_filter_type,
CLOTH_FILTER_GRAVITY,
"Filter Type",
"Operation that is going to be applied to the mesh");
- RNA_def_float(
- ot->srna, "strength", 1.0f, -10.0f, 10.0f, "Strength", "Filter strength", -10.0f, 10.0f);
RNA_def_enum_flag(ot->srna,
"force_axis",
prop_cloth_filter_force_axis_items,
diff --git a/source/blender/editors/sculpt_paint/sculpt_detail.c b/source/blender/editors/sculpt_paint/sculpt_detail.c
index 8f87cd1b6ed..0e46fd50f3b 100644
--- a/source/blender/editors/sculpt_paint/sculpt_detail.c
+++ b/source/blender/editors/sculpt_paint/sculpt_detail.c
@@ -30,7 +30,6 @@
#include "WM_types.h"
#include "ED_screen.h"
-#include "ED_sculpt.h"
#include "ED_space_api.h"
#include "ED_view3d.h"
#include "sculpt_intern.h"
@@ -103,7 +102,8 @@ static int sculpt_detail_flood_fill_exec(bContext *C, wmOperator *op)
size = max_fff(dim[0], dim[1], dim[2]);
/* Update topology size. */
- float object_space_constant_detail = 1.0f / (sd->constant_detail * mat4_to_scale(ob->obmat));
+ float object_space_constant_detail = 1.0f /
+ (sd->constant_detail * mat4_to_scale(ob->object_to_world));
BKE_pbvh_bmesh_detail_size_set(ss->pbvh, object_space_constant_detail);
SCULPT_undo_push_begin(ob, op);
@@ -224,7 +224,7 @@ static void sample_detail_dyntopo(bContext *C, ViewContext *vc, const int mval[2
if (srd.hit && srd.edge_length > 0.0f) {
/* Convert edge length to world space detail resolution. */
- sd->constant_detail = 1 / (srd.edge_length * mat4_to_scale(ob->obmat));
+ sd->constant_detail = 1 / (srd.edge_length * mat4_to_scale(ob->object_to_world));
}
}
@@ -474,8 +474,8 @@ static void dyntopo_detail_size_parallel_lines_draw(uint pos3d,
bool flip,
const float angle)
{
- float object_space_constant_detail = 1.0f /
- (cd->detail_size * mat4_to_scale(cd->active_object->obmat));
+ float object_space_constant_detail = 1.0f / (cd->detail_size *
+ mat4_to_scale(cd->active_object->object_to_world));
/* The constant detail represents the maximum edge length allowed before subdividing it. If the
* triangle grid preview is created with this value it will represent an ideal mesh density where
@@ -593,7 +593,8 @@ static void dyntopo_detail_size_sample_from_surface(Object *ob,
if (num_neighbors > 0) {
const float avg_edge_len = len_accum / num_neighbors;
/* Use 0.7 as the average of min and max dyntopo edge length. */
- const float detail_size = 0.7f / (avg_edge_len * mat4_to_scale(cd->active_object->obmat));
+ const float detail_size = 0.7f /
+ (avg_edge_len * mat4_to_scale(cd->active_object->object_to_world));
cd->detail_size = clamp_f(detail_size, 1.0f, 500.0f);
}
}
@@ -717,7 +718,7 @@ static int dyntopo_detail_size_edit_invoke(bContext *C, wmOperator *op, const wm
float cursor_trans[4][4], cursor_rot[4][4];
const float z_axis[4] = {0.0f, 0.0f, 1.0f, 0.0f};
float quat[4];
- copy_m4_m4(cursor_trans, active_object->obmat);
+ copy_m4_m4(cursor_trans, active_object->object_to_world);
translate_m4(
cursor_trans, ss->cursor_location[0], ss->cursor_location[1], ss->cursor_location[2]);
diff --git a/source/blender/editors/sculpt_paint/sculpt_dyntopo.c b/source/blender/editors/sculpt_paint/sculpt_dyntopo.c
index 46674c5d239..388f4111555 100644
--- a/source/blender/editors/sculpt_paint/sculpt_dyntopo.c
+++ b/source/blender/editors/sculpt_paint/sculpt_dyntopo.c
@@ -7,9 +7,6 @@
#include "MEM_guardedalloc.h"
-#include "BLI_blenlib.h"
-#include "BLI_hash.h"
-#include "BLI_math.h"
#include "BLI_task.h"
#include "BLT_translation.h"
@@ -18,12 +15,10 @@
#include "DNA_meshdata_types.h"
#include "DNA_modifier_types.h"
-#include "BKE_brush.h"
#include "BKE_context.h"
#include "BKE_global.h"
#include "BKE_main.h"
#include "BKE_mesh.h"
-#include "BKE_mesh_mapping.h"
#include "BKE_modifier.h"
#include "BKE_object.h"
#include "BKE_paint.h"
@@ -31,26 +26,15 @@
#include "BKE_pbvh.h"
#include "BKE_pointcache.h"
#include "BKE_scene.h"
-#include "BKE_screen.h"
#include "DEG_depsgraph.h"
#include "WM_api.h"
-#include "WM_message.h"
-#include "WM_toolsystem.h"
#include "WM_types.h"
-#include "ED_object.h"
-#include "ED_screen.h"
-#include "ED_sculpt.h"
#include "ED_undo.h"
-#include "ED_view3d.h"
-#include "paint_intern.h"
#include "sculpt_intern.h"
-#include "RNA_access.h"
-#include "RNA_define.h"
-
#include "UI_interface.h"
#include "UI_resources.h"
@@ -88,45 +72,6 @@ void SCULPT_pbvh_clear(Object *ob)
DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
}
-void SCULPT_dyntopo_node_layers_add(SculptSession *ss)
-{
- int cd_node_layer_index;
-
- char node_vertex_id[] = "_dyntopo_vnode_id";
- char node_face_id[] = "_dyntopo_fnode_id";
-
- cd_node_layer_index = CustomData_get_named_layer_index(
- &ss->bm->vdata, CD_PROP_INT32, node_vertex_id);
-
- if (cd_node_layer_index == -1) {
- BM_data_layer_add_named(ss->bm, &ss->bm->vdata, CD_PROP_INT32, node_vertex_id);
- cd_node_layer_index = CustomData_get_named_layer_index(
- &ss->bm->vdata, CD_PROP_INT32, node_vertex_id);
- }
-
- ss->cd_vert_node_offset = CustomData_get_n_offset(
- &ss->bm->vdata,
- CD_PROP_INT32,
- cd_node_layer_index - CustomData_get_layer_index(&ss->bm->vdata, CD_PROP_INT32));
-
- 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, node_face_id);
- if (cd_node_layer_index == -1) {
- BM_data_layer_add_named(ss->bm, &ss->bm->pdata, CD_PROP_INT32, node_face_id);
- cd_node_layer_index = CustomData_get_named_layer_index(
- &ss->bm->pdata, CD_PROP_INT32, node_face_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));
-
- ss->bm->pdata.layers[cd_node_layer_index].flag |= CD_FLAG_TEMPORARY;
-}
-
void SCULPT_dynamic_topology_enable_ex(Main *bmain, Depsgraph *depsgraph, Scene *scene, Object *ob)
{
SculptSession *ss = ob->sculpt;
@@ -156,8 +101,9 @@ void SCULPT_dynamic_topology_enable_ex(Main *bmain, Depsgraph *depsgraph, Scene
.active_shapekey = ob->shapenr,
}));
SCULPT_dynamic_topology_triangulate(ss->bm);
+
BM_data_layer_add(ss->bm, &ss->bm->vdata, CD_PAINT_MASK);
- SCULPT_dyntopo_node_layers_add(ss);
+
/* Make sure the data for existing faces are initialized. */
if (me->totpoly != ss->bm->totface) {
BM_mesh_normals_update(ss->bm);
@@ -185,6 +131,14 @@ static void SCULPT_dynamic_topology_disable_ex(
SculptSession *ss = ob->sculpt;
Mesh *me = ob->data;
+ if (ss->attrs.dyntopo_node_id_vertex) {
+ BKE_sculpt_attribute_destroy(ob, ss->attrs.dyntopo_node_id_vertex);
+ }
+
+ if (ss->attrs.dyntopo_node_id_face) {
+ BKE_sculpt_attribute_destroy(ob, ss->attrs.dyntopo_node_id_face);
+ }
+
SCULPT_pbvh_clear(ob);
if (unode) {
@@ -215,7 +169,7 @@ static void SCULPT_dynamic_topology_disable_ex(
BKE_sculptsession_bm_to_me(ob, true);
/* Reset Face Sets as they are no longer valid. */
- CustomData_free_layers(&me->pdata, CD_SCULPT_FACE_SETS, me->totpoly);
+ CustomData_free_layer_named(&me->pdata, ".sculpt_face_set", me->totpoly);
me->face_sets_color_default = 1;
/* Sync the visibility to vertices manually as the pmap is still not initialized. */
diff --git a/source/blender/editors/sculpt_paint/sculpt_expand.c b/source/blender/editors/sculpt_paint/sculpt_expand.c
index 414a855ab2f..3133bb2007e 100644
--- a/source/blender/editors/sculpt_paint/sculpt_expand.c
+++ b/source/blender/editors/sculpt_paint/sculpt_expand.c
@@ -7,13 +7,10 @@
#include "MEM_guardedalloc.h"
-#include "BLI_blenlib.h"
#include "BLI_linklist_stack.h"
#include "BLI_math.h"
#include "BLI_task.h"
-#include "BLT_translation.h"
-
#include "DNA_brush_types.h"
#include "DNA_mesh_types.h"
#include "DNA_meshdata_types.h"
@@ -27,9 +24,6 @@
#include "BKE_image.h"
#include "BKE_mesh.h"
#include "BKE_mesh_mapping.h"
-#include "BKE_multires.h"
-#include "BKE_node.h"
-#include "BKE_object.h"
#include "BKE_paint.h"
#include "BKE_pbvh.h"
#include "BKE_report.h"
@@ -39,17 +33,13 @@
#include "DEG_depsgraph.h"
#include "WM_api.h"
-#include "WM_message.h"
-#include "WM_toolsystem.h"
#include "WM_types.h"
#include "RNA_access.h"
#include "RNA_define.h"
-#include "ED_object.h"
#include "ED_screen.h"
#include "ED_sculpt.h"
-#include "ED_view3d.h"
#include "paint_intern.h"
#include "sculpt_intern.h"
@@ -177,15 +167,16 @@ static float sculpt_expand_falloff_value_vertex_get(SculptSession *ss,
if (expand_cache->texture_distortion_strength == 0.0f) {
return expand_cache->vert_falloff[v_i];
}
-
- if (!expand_cache->brush->mtex.tex) {
+ const Brush *brush = expand_cache->brush;
+ const MTex *mtex = BKE_brush_mask_texture_get(brush, OB_MODE_SCULPT);
+ if (!mtex->tex) {
return expand_cache->vert_falloff[v_i];
}
float rgba[4];
const float *vertex_co = SCULPT_vertex_co_get(ss, v);
const float avg = BKE_brush_sample_tex_3d(
- expand_cache->scene, expand_cache->brush, vertex_co, rgba, 0, ss->tex_pool);
+ expand_cache->scene, brush, mtex, vertex_co, rgba, 0, ss->tex_pool);
const float distortion = (avg - 0.5f) * expand_cache->texture_distortion_strength *
expand_cache->max_vert_falloff;
@@ -617,7 +608,7 @@ static float *sculpt_expand_boundary_topology_falloff_create(Object *ob, const P
for (int i = 0; i < boundary->verts_num; i++) {
BLI_gsqueue_push(queue, &boundary->verts[i]);
- BLI_BITMAP_ENABLE(visited_verts, boundary->verts_i[i]);
+ BLI_BITMAP_ENABLE(visited_verts, BKE_pbvh_vertex_to_index(ss->pbvh, boundary->verts[i]));
}
SCULPT_boundary_data_free(boundary);
}
@@ -2102,6 +2093,8 @@ static int sculpt_expand_invoke(bContext *C, wmOperator *op, const wmEvent *even
SculptSession *ss = ob->sculpt;
Sculpt *sd = CTX_data_tool_settings(C)->sculpt;
+ SCULPT_stroke_id_next(ob);
+
/* Create and configure the Expand Cache. */
ss->expand_cache = MEM_callocN(sizeof(ExpandCache), "expand cache");
sculpt_expand_cache_initial_config_set(C, op, ss->expand_cache);
@@ -2116,6 +2109,11 @@ static int sculpt_expand_invoke(bContext *C, wmOperator *op, const wmEvent *even
depsgraph = CTX_data_ensure_evaluated_depsgraph(C);
}
+ if (ss->expand_cache->target == SCULPT_EXPAND_TARGET_MASK) {
+ MultiresModifierData *mmd = BKE_sculpt_multires_active(ss->scene, ob);
+ BKE_sculpt_mask_layers_ensure(depsgraph, CTX_data_main(C), ob, mmd);
+ }
+
BKE_sculpt_update_object_for_edit(depsgraph, ob, true, true, needs_colors);
/* Do nothing when the mesh has 0 vertices. */
@@ -2130,11 +2128,6 @@ static int sculpt_expand_invoke(bContext *C, wmOperator *op, const wmEvent *even
ss->face_sets = BKE_sculpt_face_sets_ensure(mesh);
}
- if (ss->expand_cache->target == SCULPT_EXPAND_TARGET_MASK) {
- MultiresModifierData *mmd = BKE_sculpt_multires_active(ss->scene, ob);
- BKE_sculpt_mask_layers_ensure(ob, mmd);
- }
-
/* Face Set operations are not supported in dyntopo. */
if (ss->expand_cache->target == SCULPT_EXPAND_TARGET_FACE_SETS &&
BKE_pbvh_type(ss->pbvh) == PBVH_BMESH) {
@@ -2244,7 +2237,7 @@ void sculpt_expand_modal_keymap(wmKeyConfig *keyconf)
static const char *name = "Sculpt Expand Modal";
wmKeyMap *keymap = WM_modalkeymap_find(keyconf, name);
- /* This function is called for each spacetype, only needs to add map once. */
+ /* This function is called for each space-type, only needs to add map once. */
if (keymap && keymap->modal_items) {
return;
}
diff --git a/source/blender/editors/sculpt_paint/sculpt_face_set.c b/source/blender/editors/sculpt_paint/sculpt_face_set.cc
index 8aa645c6af5..40835172be9 100644
--- a/source/blender/editors/sculpt_paint/sculpt_face_set.c
+++ b/source/blender/editors/sculpt_paint/sculpt_face_set.cc
@@ -5,12 +5,20 @@
* \ingroup edsculpt
*/
+#include <cmath>
+#include <cstdlib>
+#include <queue>
+
#include "MEM_guardedalloc.h"
-#include "BLI_blenlib.h"
+#include "BLI_bit_vector.hh"
+#include "BLI_function_ref.hh"
#include "BLI_hash.h"
#include "BLI_math.h"
+#include "BLI_math_vector.hh"
+#include "BLI_span.hh"
#include "BLI_task.h"
+#include "BLI_task.hh"
#include "DNA_brush_types.h"
#include "DNA_customdata_types.h"
@@ -19,7 +27,7 @@
#include "DNA_object_types.h"
#include "DNA_scene_types.h"
-#include "BKE_brush.h"
+#include "BKE_attribute.hh"
#include "BKE_ccg.h"
#include "BKE_colortools.h"
#include "BKE_context.h"
@@ -27,25 +35,17 @@
#include "BKE_mesh.h"
#include "BKE_mesh_fair.h"
#include "BKE_mesh_mapping.h"
-#include "BKE_multires.h"
-#include "BKE_node.h"
#include "BKE_object.h"
#include "BKE_paint.h"
#include "BKE_pbvh.h"
-#include "BKE_scene.h"
#include "DEG_depsgraph.h"
#include "WM_api.h"
-#include "WM_message.h"
-#include "WM_toolsystem.h"
#include "WM_types.h"
-#include "ED_object.h"
-#include "ED_screen.h"
#include "ED_sculpt.h"
-#include "ED_view3d.h"
-#include "paint_intern.h"
+
#include "sculpt_intern.h"
#include "RNA_access.h"
@@ -53,21 +53,19 @@
#include "bmesh.h"
-#include <math.h>
-#include <stdlib.h>
-
/* Utils. */
int ED_sculpt_face_sets_find_next_available_id(struct Mesh *mesh)
{
- const int *face_sets = CustomData_get_layer(&mesh->pdata, CD_SCULPT_FACE_SETS);
+ const int *face_sets = static_cast<const int *>(
+ CustomData_get_layer_named(&mesh->pdata, CD_PROP_INT32, ".sculpt_face_set"));
if (!face_sets) {
return SCULPT_FACE_SET_NONE;
}
int next_face_set_id = 0;
for (int i = 0; i < mesh->totpoly; i++) {
- next_face_set_id = max_ii(next_face_set_id, abs(face_sets[i]));
+ next_face_set_id = max_ii(next_face_set_id, face_sets[i]);
}
next_face_set_id++;
@@ -76,7 +74,8 @@ int ED_sculpt_face_sets_find_next_available_id(struct Mesh *mesh)
void ED_sculpt_face_sets_initialize_none_to_id(struct Mesh *mesh, const int new_id)
{
- int *face_sets = CustomData_get_layer(&mesh->pdata, CD_SCULPT_FACE_SETS);
+ int *face_sets = static_cast<int *>(
+ CustomData_get_layer_named(&mesh->pdata, CD_PROP_INT32, ".sculpt_face_set"));
if (!face_sets) {
return;
}
@@ -109,7 +108,7 @@ static void do_draw_face_sets_brush_task_cb_ex(void *__restrict userdata,
const int n,
const TaskParallelTLS *__restrict tls)
{
- SculptThreadedTaskData *data = userdata;
+ SculptThreadedTaskData *data = static_cast<SculptThreadedTaskData *>(userdata);
SculptSession *ss = data->ob->sculpt;
const Brush *brush = data->brush;
const float bstrength = ss->cache->bstrength;
@@ -122,8 +121,13 @@ static void do_draw_face_sets_brush_task_cb_ex(void *__restrict userdata,
const int thread_id = BLI_task_parallel_thread_id(tls);
MVert *mvert = SCULPT_mesh_deformed_mverts_get(ss);
+ AutomaskingNodeData automask_data;
+ SCULPT_automasking_node_begin(
+ data->ob, ss, ss->cache->automasking, &automask_data, data->nodes[n]);
BKE_pbvh_vertex_iter_begin (ss->pbvh, data->nodes[n], vd, PBVH_ITER_UNIQUE) {
+ SCULPT_automasking_node_update(ss, &automask_data, &vd);
+
if (BKE_pbvh_type(ss->pbvh) == PBVH_FACES) {
MeshElemMap *vert_map = &ss->pmap[vd.index];
for (int j = 0; j < ss->pmap[vd.index].count; j++) {
@@ -135,6 +139,10 @@ static void do_draw_face_sets_brush_task_cb_ex(void *__restrict userdata,
if (!sculpt_brush_test_sq_fn(&test, poly_center)) {
continue;
}
+ const bool face_hidden = ss->hide_poly && ss->hide_poly[vert_map->indices[j]];
+ if (face_hidden) {
+ continue;
+ }
const float fade = bstrength * SCULPT_brush_strength_factor(ss,
brush,
vd.co,
@@ -143,10 +151,11 @@ static void do_draw_face_sets_brush_task_cb_ex(void *__restrict userdata,
vd.fno,
vd.mask ? *vd.mask : 0.0f,
vd.vertex,
- thread_id);
+ thread_id,
+ &automask_data);
- if (fade > 0.05f && ss->face_sets[vert_map->indices[j]] > 0) {
- ss->face_sets[vert_map->indices[j]] = abs(ss->cache->paint_face_set);
+ if (fade > 0.05f) {
+ ss->face_sets[vert_map->indices[j]] = ss->cache->paint_face_set;
}
}
}
@@ -162,7 +171,8 @@ static void do_draw_face_sets_brush_task_cb_ex(void *__restrict userdata,
vd.fno,
vd.mask ? *vd.mask : 0.0f,
vd.vertex,
- thread_id);
+ thread_id,
+ &automask_data);
if (fade > 0.05f) {
SCULPT_vertex_face_set_set(ss, vd.vertex, ss->cache->paint_face_set);
@@ -176,7 +186,7 @@ static void do_relax_face_sets_brush_task_cb_ex(void *__restrict userdata,
const int n,
const TaskParallelTLS *__restrict tls)
{
- SculptThreadedTaskData *data = userdata;
+ SculptThreadedTaskData *data = static_cast<SculptThreadedTaskData *>(userdata);
SculptSession *ss = data->ob->sculpt;
const Brush *brush = data->brush;
float bstrength = ss->cache->bstrength;
@@ -189,13 +199,18 @@ static void do_relax_face_sets_brush_task_cb_ex(void *__restrict userdata,
const bool relax_face_sets = !(ss->cache->iteration_count % 3 == 0);
/* This operations needs a strength tweak as the relax deformation is too weak by default. */
- if (relax_face_sets) {
- bstrength *= 2.0f;
+ if (relax_face_sets && data->iteration < 2) {
+ bstrength *= 1.5f;
}
const int thread_id = BLI_task_parallel_thread_id(tls);
+ AutomaskingNodeData automask_data;
+ SCULPT_automasking_node_begin(
+ data->ob, ss, ss->cache->automasking, &automask_data, data->nodes[n]);
BKE_pbvh_vertex_iter_begin (ss->pbvh, data->nodes[n], vd, PBVH_ITER_UNIQUE) {
+ SCULPT_automasking_node_update(ss, &automask_data, &vd);
+
if (!sculpt_brush_test_sq_fn(&test, vd.co)) {
continue;
}
@@ -211,7 +226,8 @@ static void do_relax_face_sets_brush_task_cb_ex(void *__restrict userdata,
vd.fno,
vd.mask ? *vd.mask : 0.0f,
vd.vertex,
- thread_id);
+ thread_id,
+ &automask_data);
SCULPT_relax_vertex(ss, &vd, fade * bstrength, relax_face_sets, vd.co);
if (vd.mvert) {
@@ -226,21 +242,27 @@ void SCULPT_do_draw_face_sets_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, in
SculptSession *ss = ob->sculpt;
Brush *brush = BKE_paint_brush(&sd->paint);
+ if (ss->pbvh) {
+ Mesh *mesh = BKE_mesh_from_object(ob);
+ BKE_pbvh_face_sets_color_set(
+ ss->pbvh, mesh->face_sets_color_seed, mesh->face_sets_color_default);
+ }
+
BKE_curvemapping_init(brush->curve);
/* Threaded loop over nodes. */
- SculptThreadedTaskData data = {
- .sd = sd,
- .ob = ob,
- .brush = brush,
- .nodes = nodes,
- };
+ SculptThreadedTaskData data{};
+ data.sd = sd;
+ data.ob = ob;
+ data.brush = brush;
+ data.nodes = nodes;
TaskParallelSettings settings;
BKE_pbvh_parallel_range_settings(&settings, true, totnode);
if (ss->cache->alt_smooth) {
SCULPT_boundary_info_ensure(ob);
for (int i = 0; i < 4; i++) {
+ data.iteration = i;
BLI_task_parallel_range(0, totnode, &data, do_relax_face_sets_brush_task_cb_ex, &settings);
}
}
@@ -251,12 +273,12 @@ void SCULPT_do_draw_face_sets_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, in
/* Face Sets Operators */
-typedef enum eSculptFaceGroupsCreateModes {
+enum eSculptFaceGroupsCreateModes {
SCULPT_FACE_SET_MASKED = 0,
SCULPT_FACE_SET_VISIBLE = 1,
SCULPT_FACE_SET_ALL = 2,
SCULPT_FACE_SET_SELECTION = 3,
-} eSculptFaceGroupsCreateModes;
+};
static EnumPropertyItem prop_sculpt_face_set_create_types[] = {
{
@@ -287,11 +309,12 @@ static EnumPropertyItem prop_sculpt_face_set_create_types[] = {
"Face Set from Edit Mode Selection",
"Create an Face Set corresponding to the Edit Mode face selection",
},
- {0, NULL, 0, NULL, NULL},
+ {0, nullptr, 0, nullptr, nullptr},
};
static int sculpt_face_set_create_exec(bContext *C, wmOperator *op)
{
+ using namespace blender;
Object *ob = CTX_data_active_object(C);
SculptSession *ss = ob->sculpt;
Depsgraph *depsgraph = CTX_data_depsgraph_pointer(C);
@@ -303,7 +326,7 @@ static int sculpt_face_set_create_exec(bContext *C, wmOperator *op)
return OPERATOR_CANCELLED;
}
- Mesh *mesh = ob->data;
+ Mesh *mesh = static_cast<Mesh *>(ob->data);
ss->face_sets = BKE_sculpt_face_sets_ensure(mesh);
BKE_sculpt_update_object_for_edit(depsgraph, ob, true, mode == SCULPT_FACE_SET_MASKED, false);
@@ -314,7 +337,7 @@ static int sculpt_face_set_create_exec(bContext *C, wmOperator *op)
PBVH *pbvh = ob->sculpt->pbvh;
PBVHNode **nodes;
int totnode;
- BKE_pbvh_search_gather(pbvh, NULL, NULL, &nodes, &totnode);
+ BKE_pbvh_search_gather(pbvh, nullptr, nullptr, &nodes, &totnode);
if (!nodes) {
return OPERATOR_CANCELLED;
@@ -375,28 +398,16 @@ static int sculpt_face_set_create_exec(bContext *C, wmOperator *op)
}
if (mode == SCULPT_FACE_SET_SELECTION) {
- BMesh *bm;
- const BMAllocTemplate allocsize = BMALLOC_TEMPLATE_FROM_ME(mesh);
- bm = BM_mesh_create(&allocsize,
- &((struct BMeshCreateParams){
- .use_toolflags = true,
- }));
-
- BM_mesh_bm_from_me(bm,
- mesh,
- (&(struct BMeshFromMeshParams){
- .calc_face_normal = true,
- .calc_vert_normal = true,
- }));
-
- BMIter iter;
- BMFace *f;
- BM_ITER_MESH (f, &iter, bm, BM_FACES_OF_MESH) {
- if (BM_elem_flag_test(f, BM_ELEM_SELECT)) {
- ss->face_sets[BM_elem_index_get(f)] = next_face_set;
+ const bke::AttributeAccessor attributes = mesh->attributes();
+ const VArraySpan<bool> select_poly = attributes.lookup_or_default<bool>(
+ ".select_poly", ATTR_DOMAIN_FACE, false);
+ threading::parallel_for(IndexRange(mesh->totvert), 4096, [&](const IndexRange range) {
+ for (const int i : range) {
+ if (select_poly[i]) {
+ ss->face_sets[i] = next_face_set;
+ }
}
- }
- BM_mesh_free(bm);
+ });
}
for (int i = 0; i < totnode; i++) {
@@ -429,7 +440,7 @@ void SCULPT_OT_face_sets_create(wmOperatorType *ot)
ot->srna, "mode", prop_sculpt_face_set_create_types, SCULPT_FACE_SET_MASKED, "Mode", "");
}
-typedef enum eSculptFaceSetsInitMode {
+enum eSculptFaceSetsInitMode {
SCULPT_FACE_SETS_FROM_LOOSE_PARTS = 0,
SCULPT_FACE_SETS_FROM_MATERIALS = 1,
SCULPT_FACE_SETS_FROM_NORMALS = 2,
@@ -439,7 +450,7 @@ typedef enum eSculptFaceSetsInitMode {
SCULPT_FACE_SETS_FROM_BEVEL_WEIGHT = 6,
SCULPT_FACE_SETS_FROM_FACE_MAPS = 7,
SCULPT_FACE_SETS_FROM_FACE_SET_BOUNDARIES = 8,
-} eSculptFaceSetsInitMode;
+};
static EnumPropertyItem prop_sculpt_face_sets_init_types[] = {
{
@@ -506,203 +517,120 @@ static EnumPropertyItem prop_sculpt_face_sets_init_types[] = {
"Create a Face Set per isolated Face Set",
},
- {0, NULL, 0, NULL, NULL},
+ {0, nullptr, 0, nullptr, nullptr},
};
-typedef bool (*face_sets_flood_fill_test)(
- BMesh *bm, BMFace *from_f, BMEdge *from_e, BMFace *to_f, const float threshold);
-
-static bool sculpt_face_sets_init_loose_parts_test(BMesh *UNUSED(bm),
- BMFace *UNUSED(from_f),
- BMEdge *UNUSED(from_e),
- BMFace *UNUSED(to_f),
- const float UNUSED(threshold))
-{
- return true;
-}
-
-static bool sculpt_face_sets_init_normals_test(
- BMesh *UNUSED(bm), BMFace *from_f, BMEdge *UNUSED(from_e), BMFace *to_f, const float threshold)
-{
- return fabsf(dot_v3v3(from_f->no, to_f->no)) > threshold;
-}
-
-static bool sculpt_face_sets_init_uv_seams_test(BMesh *UNUSED(bm),
- BMFace *UNUSED(from_f),
- BMEdge *from_e,
- BMFace *UNUSED(to_f),
- const float UNUSED(threshold))
-{
- return !BM_elem_flag_test(from_e, BM_ELEM_SEAM);
-}
-
-static bool sculpt_face_sets_init_crease_test(
- BMesh *bm, BMFace *UNUSED(from_f), BMEdge *from_e, BMFace *UNUSED(to_f), const float threshold)
-{
- return BM_elem_float_data_get(&bm->edata, from_e, CD_CREASE) < threshold;
-}
-
-static bool sculpt_face_sets_init_bevel_weight_test(
- BMesh *bm, BMFace *UNUSED(from_f), BMEdge *from_e, BMFace *UNUSED(to_f), const float threshold)
-{
- return BM_elem_float_data_get(&bm->edata, from_e, CD_BWEIGHT) < threshold;
-}
-
-static bool sculpt_face_sets_init_sharp_edges_test(BMesh *UNUSED(bm),
- BMFace *UNUSED(from_f),
- BMEdge *from_e,
- BMFace *UNUSED(to_f),
- const float UNUSED(threshold))
-{
- return BM_elem_flag_test(from_e, BM_ELEM_SMOOTH);
-}
+using FaceSetsFloodFillFn = blender::FunctionRef<bool(int from_face, int edge, int to_face)>;
-static bool sculpt_face_sets_init_face_set_boundary_test(
- BMesh *bm, BMFace *from_f, BMEdge *UNUSED(from_e), BMFace *to_f, const float UNUSED(threshold))
-{
- const int cd_face_sets_offset = CustomData_get_offset(&bm->pdata, CD_SCULPT_FACE_SETS);
- return BM_ELEM_CD_GET_INT(from_f, cd_face_sets_offset) ==
- BM_ELEM_CD_GET_INT(to_f, cd_face_sets_offset);
-}
-
-static void sculpt_face_sets_init_flood_fill(Object *ob,
- face_sets_flood_fill_test test,
- const float threshold)
+static void sculpt_face_sets_init_flood_fill(Object *ob, const FaceSetsFloodFillFn &test_fn)
{
+ using namespace blender;
SculptSession *ss = ob->sculpt;
- Mesh *mesh = ob->data;
- BMesh *bm;
- const BMAllocTemplate allocsize = BMALLOC_TEMPLATE_FROM_ME(mesh);
- bm = BM_mesh_create(&allocsize,
- &((struct BMeshCreateParams){
- .use_toolflags = true,
- }));
+ Mesh *mesh = static_cast<Mesh *>(ob->data);
- BM_mesh_bm_from_me(bm,
- mesh,
- (&(struct BMeshFromMeshParams){
- .calc_face_normal = true,
- .calc_vert_normal = true,
- }));
-
- BLI_bitmap *visited_faces = BLI_BITMAP_NEW(mesh->totpoly, "visited faces");
- const int totfaces = mesh->totpoly;
+ BitVector<> visited_faces(mesh->totpoly, false);
int *face_sets = ss->face_sets;
- BM_mesh_elem_table_init(bm, BM_FACE);
- BM_mesh_elem_table_ensure(bm, BM_FACE);
+ const Span<MEdge> edges = mesh->edges();
+ const Span<MPoly> polys = mesh->polys();
+ const Span<MLoop> loops = mesh->loops();
+
+ if (!ss->epmap) {
+ BKE_mesh_edge_poly_map_create(&ss->epmap,
+ &ss->epmap_mem,
+ edges.data(),
+ edges.size(),
+ polys.data(),
+ polys.size(),
+ loops.data(),
+ loops.size());
+ }
int next_face_set = 1;
- for (int i = 0; i < totfaces; i++) {
- if (BLI_BITMAP_TEST(visited_faces, i)) {
+ for (const int i : polys.index_range()) {
+ if (visited_faces[i]) {
continue;
}
- GSQueue *queue;
- queue = BLI_gsqueue_new(sizeof(int));
+ std::queue<int> queue;
face_sets[i] = next_face_set;
- BLI_BITMAP_ENABLE(visited_faces, i);
- BLI_gsqueue_push(queue, &i);
-
- while (!BLI_gsqueue_is_empty(queue)) {
- int from_f;
- BLI_gsqueue_pop(queue, &from_f);
-
- BMFace *f, *f_neighbor;
- BMEdge *ed;
- BMIter iter_a, iter_b;
-
- f = BM_face_at_index(bm, from_f);
-
- BM_ITER_ELEM (ed, &iter_a, f, BM_EDGES_OF_FACE) {
- BM_ITER_ELEM (f_neighbor, &iter_b, ed, BM_FACES_OF_EDGE) {
- if (f_neighbor == f) {
+ visited_faces[i].set(true);
+ queue.push(i);
+
+ while (!queue.empty()) {
+ const int poly_i = queue.front();
+ const MPoly &poly = polys[poly_i];
+ queue.pop();
+
+ for (const MLoop &loop : loops.slice(poly.loopstart, poly.totloop)) {
+ const int edge_i = loop.e;
+ const Span<int> neighbor_polys(ss->epmap[edge_i].indices, ss->epmap[edge_i].count);
+ for (const int neighbor_i : neighbor_polys) {
+ if (neighbor_i == poly_i) {
continue;
}
- int neighbor_face_index = BM_elem_index_get(f_neighbor);
- if (BLI_BITMAP_TEST(visited_faces, neighbor_face_index)) {
+ if (visited_faces[neighbor_i]) {
continue;
}
- if (!test(bm, f, ed, f_neighbor, threshold)) {
+ if (!test_fn(poly_i, edge_i, neighbor_i)) {
continue;
}
- face_sets[neighbor_face_index] = next_face_set;
- BLI_BITMAP_ENABLE(visited_faces, neighbor_face_index);
- BLI_gsqueue_push(queue, &neighbor_face_index);
+ face_sets[neighbor_i] = next_face_set;
+ visited_faces[neighbor_i].set(true);
+ queue.push(neighbor_i);
}
}
}
next_face_set += 1;
-
- BLI_gsqueue_free(queue);
}
-
- MEM_SAFE_FREE(visited_faces);
-
- BM_mesh_free(bm);
}
static void sculpt_face_sets_init_loop(Object *ob, const int mode)
{
- Mesh *mesh = ob->data;
+ using namespace blender;
+ Mesh *mesh = static_cast<Mesh *>(ob->data);
SculptSession *ss = ob->sculpt;
- BMesh *bm;
- const BMAllocTemplate allocsize = BMALLOC_TEMPLATE_FROM_ME(mesh);
- bm = BM_mesh_create(&allocsize,
- &((struct BMeshCreateParams){
- .use_toolflags = true,
- }));
-
- BM_mesh_bm_from_me(bm,
- mesh,
- (&(struct BMeshFromMeshParams){
- .calc_face_normal = true,
- .calc_vert_normal = true,
- }));
- BMIter iter;
- BMFace *f;
-
- const int cd_fmaps_offset = CustomData_get_offset(&bm->pdata, CD_FACEMAP);
- BM_ITER_MESH (f, &iter, bm, BM_FACES_OF_MESH) {
- if (mode == SCULPT_FACE_SETS_FROM_MATERIALS) {
- ss->face_sets[BM_elem_index_get(f)] = (int)(f->mat_nr + 1);
+ if (mode == SCULPT_FACE_SETS_FROM_MATERIALS) {
+ const bke::AttributeAccessor attributes = mesh->attributes();
+ const VArraySpan<int> material_indices = attributes.lookup_or_default<int>(
+ "material_index", ATTR_DOMAIN_FACE, 0);
+ for (const int i : IndexRange(mesh->totpoly)) {
+ ss->face_sets[i] = material_indices[i] + 1;
}
- else if (mode == SCULPT_FACE_SETS_FROM_FACE_MAPS) {
- if (cd_fmaps_offset != -1) {
- ss->face_sets[BM_elem_index_get(f)] = BM_ELEM_CD_GET_INT(f, cd_fmaps_offset) + 2;
- }
- else {
- ss->face_sets[BM_elem_index_get(f)] = 1;
- }
+ }
+ else if (mode == SCULPT_FACE_SETS_FROM_FACE_MAPS) {
+ const int *face_maps = static_cast<int *>(CustomData_get_layer(&mesh->pdata, CD_FACEMAP));
+ for (const int i : IndexRange(mesh->totpoly)) {
+ ss->face_sets[i] = face_maps ? face_maps[i] : 1;
}
}
- BM_mesh_free(bm);
}
static int sculpt_face_set_init_exec(bContext *C, wmOperator *op)
{
+ using namespace blender;
Object *ob = CTX_data_active_object(C);
SculptSession *ss = ob->sculpt;
Depsgraph *depsgraph = CTX_data_depsgraph_pointer(C);
const int mode = RNA_enum_get(op->ptr, "mode");
+ BKE_sculpt_update_object_for_edit(depsgraph, ob, true, false, false);
+
/* Dyntopo not supported. */
if (BKE_pbvh_type(ss->pbvh) == PBVH_BMESH) {
return OPERATOR_CANCELLED;
}
- BKE_sculpt_update_object_for_edit(depsgraph, ob, true, false, false);
-
PBVH *pbvh = ob->sculpt->pbvh;
PBVHNode **nodes;
int totnode;
- BKE_pbvh_search_gather(pbvh, NULL, NULL, &nodes, &totnode);
+ BKE_pbvh_search_gather(pbvh, nullptr, nullptr, &nodes, &totnode);
if (!nodes) {
return OPERATOR_CANCELLED;
@@ -713,44 +641,85 @@ static int sculpt_face_set_init_exec(bContext *C, wmOperator *op)
const float threshold = RNA_float_get(op->ptr, "threshold");
- Mesh *mesh = ob->data;
+ Mesh *mesh = static_cast<Mesh *>(ob->data);
ss->face_sets = BKE_sculpt_face_sets_ensure(mesh);
+ const bke::AttributeAccessor attributes = mesh->attributes();
switch (mode) {
- case SCULPT_FACE_SETS_FROM_LOOSE_PARTS:
- sculpt_face_sets_init_flood_fill(ob, sculpt_face_sets_init_loose_parts_test, threshold);
+ case SCULPT_FACE_SETS_FROM_LOOSE_PARTS: {
+ const VArray<bool> hide_poly = attributes.lookup_or_default<bool>(
+ ".hide_poly", ATTR_DOMAIN_FACE, false);
+ sculpt_face_sets_init_flood_fill(
+ ob, [&](const int from_face, const int /*edge*/, const int to_face) {
+ return hide_poly[from_face] == hide_poly[to_face];
+ });
break;
- case SCULPT_FACE_SETS_FROM_MATERIALS:
+ }
+ case SCULPT_FACE_SETS_FROM_MATERIALS: {
sculpt_face_sets_init_loop(ob, SCULPT_FACE_SETS_FROM_MATERIALS);
break;
- case SCULPT_FACE_SETS_FROM_NORMALS:
- sculpt_face_sets_init_flood_fill(ob, sculpt_face_sets_init_normals_test, threshold);
+ }
+ case SCULPT_FACE_SETS_FROM_NORMALS: {
+ const Span<float3> poly_normals(
+ reinterpret_cast<const float3 *>(BKE_mesh_poly_normals_ensure(mesh)), mesh->totpoly);
+ sculpt_face_sets_init_flood_fill(
+ ob, [&](const int from_face, const int /*edge*/, const int to_face) -> bool {
+ return std::abs(math::dot(poly_normals[from_face], poly_normals[to_face])) > threshold;
+ });
break;
- case SCULPT_FACE_SETS_FROM_UV_SEAMS:
- sculpt_face_sets_init_flood_fill(ob, sculpt_face_sets_init_uv_seams_test, threshold);
+ }
+ case SCULPT_FACE_SETS_FROM_UV_SEAMS: {
+ const Span<MEdge> edges = mesh->edges();
+ sculpt_face_sets_init_flood_fill(
+ ob, [&](const int /*from_face*/, const int edge, const int /*to_face*/) -> bool {
+ return (edges[edge].flag & ME_SEAM) == 0;
+ });
break;
- case SCULPT_FACE_SETS_FROM_CREASES:
- sculpt_face_sets_init_flood_fill(ob, sculpt_face_sets_init_crease_test, threshold);
+ }
+ case SCULPT_FACE_SETS_FROM_CREASES: {
+ const float *creases = static_cast<const float *>(
+ CustomData_get_layer(&mesh->edata, CD_CREASE));
+ sculpt_face_sets_init_flood_fill(
+ ob, [&](const int /*from_face*/, const int edge, const int /*to_face*/) -> bool {
+ return creases[edge] < threshold;
+ });
break;
- case SCULPT_FACE_SETS_FROM_SHARP_EDGES:
- sculpt_face_sets_init_flood_fill(ob, sculpt_face_sets_init_sharp_edges_test, threshold);
+ }
+ case SCULPT_FACE_SETS_FROM_SHARP_EDGES: {
+ const Span<MEdge> edges = mesh->edges();
+ sculpt_face_sets_init_flood_fill(
+ ob, [&](const int /*from_face*/, const int edge, const int /*to_face*/) -> bool {
+ return (edges[edge].flag & ME_SHARP) == 0;
+ });
break;
- case SCULPT_FACE_SETS_FROM_BEVEL_WEIGHT:
- sculpt_face_sets_init_flood_fill(ob, sculpt_face_sets_init_bevel_weight_test, threshold);
+ }
+ case SCULPT_FACE_SETS_FROM_BEVEL_WEIGHT: {
+ const float *bevel_weights = static_cast<const float *>(
+ CustomData_get_layer(&mesh->edata, CD_BWEIGHT));
+ sculpt_face_sets_init_flood_fill(
+ ob, [&](const int /*from_face*/, const int edge, const int /*to_face*/) -> bool {
+ return bevel_weights ? bevel_weights[edge] / 255.0f < threshold : true;
+ });
break;
- case SCULPT_FACE_SETS_FROM_FACE_SET_BOUNDARIES:
+ }
+ case SCULPT_FACE_SETS_FROM_FACE_SET_BOUNDARIES: {
+ Array<int> face_sets_copy(Span<int>(ss->face_sets, mesh->totpoly));
sculpt_face_sets_init_flood_fill(
- ob, sculpt_face_sets_init_face_set_boundary_test, threshold);
+ ob, [&](const int from_face, const int /*edge*/, const int to_face) -> bool {
+ return face_sets_copy[from_face] == face_sets_copy[to_face];
+ });
break;
- case SCULPT_FACE_SETS_FROM_FACE_MAPS:
+ }
+ case SCULPT_FACE_SETS_FROM_FACE_MAPS: {
sculpt_face_sets_init_loop(ob, SCULPT_FACE_SETS_FROM_FACE_MAPS);
break;
+ }
}
SCULPT_undo_push_end(ob);
/* Sync face sets visibility and vertex visibility as now all Face Sets are visible. */
- SCULPT_visibility_sync_all_face_sets_to_verts(ob);
+ SCULPT_visibility_sync_all_from_faces(ob);
for (int i = 0; i < totnode; i++) {
BKE_pbvh_node_mark_update_visibility(nodes[i]);
@@ -761,7 +730,7 @@ static int sculpt_face_set_init_exec(bContext *C, wmOperator *op)
MEM_SAFE_FREE(nodes);
if (BKE_pbvh_type(pbvh) == PBVH_FACES) {
- BKE_mesh_flush_hidden_from_verts(ob->data);
+ BKE_mesh_flush_hidden_from_verts(mesh);
}
SCULPT_tag_update_overlays(C);
@@ -796,13 +765,12 @@ void SCULPT_OT_face_sets_init(wmOperatorType *ot)
1.0f);
}
-typedef enum eSculptFaceGroupVisibilityModes {
+enum eSculptFaceGroupVisibilityModes {
SCULPT_FACE_SET_VISIBILITY_TOGGLE = 0,
SCULPT_FACE_SET_VISIBILITY_SHOW_ACTIVE = 1,
SCULPT_FACE_SET_VISIBILITY_HIDE_ACTIVE = 2,
SCULPT_FACE_SET_VISIBILITY_INVERT = 3,
- SCULPT_FACE_SET_VISIBILITY_SHOW_ALL = 4,
-} eSculptFaceGroupVisibilityModes;
+};
static EnumPropertyItem prop_sculpt_face_sets_change_visibility_types[] = {
{
@@ -833,14 +801,7 @@ static EnumPropertyItem prop_sculpt_face_sets_change_visibility_types[] = {
"Invert Face Set Visibility",
"Invert Face Set Visibility",
},
- {
- SCULPT_FACE_SET_VISIBILITY_SHOW_ALL,
- "SHOW_ALL",
- 0,
- "Show All Face Sets",
- "Show All Face Sets",
- },
- {0, NULL, 0, NULL, NULL},
+ {0, nullptr, 0, nullptr, nullptr},
};
static int sculpt_face_sets_change_visibility_exec(bContext *C, wmOperator *op)
@@ -849,102 +810,123 @@ static int sculpt_face_sets_change_visibility_exec(bContext *C, wmOperator *op)
SculptSession *ss = ob->sculpt;
Depsgraph *depsgraph = CTX_data_depsgraph_pointer(C);
- /* Dyntopo not supported. */
- if (BKE_pbvh_type(ss->pbvh) == PBVH_BMESH) {
- return OPERATOR_CANCELLED;
- }
+ Mesh *mesh = BKE_object_get_original_mesh(ob);
- if (!pbvh_has_face_sets(ss->pbvh)) {
+ BKE_sculpt_update_object_for_edit(depsgraph, ob, true, true, false);
+
+ /* Not supported for dyntopo. */
+ if (BKE_pbvh_type(ss->pbvh) == PBVH_BMESH) {
return OPERATOR_CANCELLED;
}
- BKE_sculpt_update_object_for_edit(depsgraph, ob, true, true, false);
-
- const int tot_vert = SCULPT_vertex_count_get(ss);
const int mode = RNA_enum_get(op->ptr, "mode");
- const int active_face_set = SCULPT_active_face_set_get(ss);
-
- SCULPT_undo_push_begin(ob, op);
+ const int tot_vert = SCULPT_vertex_count_get(ss);
PBVH *pbvh = ob->sculpt->pbvh;
PBVHNode **nodes;
int totnode;
- BKE_pbvh_search_gather(pbvh, NULL, NULL, &nodes, &totnode);
+ BKE_pbvh_search_gather(pbvh, nullptr, nullptr, &nodes, &totnode);
if (totnode == 0) {
MEM_SAFE_FREE(nodes);
return OPERATOR_CANCELLED;
}
- SCULPT_undo_push_node(ob, nodes[0], SCULPT_UNDO_FACE_SETS);
-
- if (mode == SCULPT_FACE_SET_VISIBILITY_TOGGLE) {
- bool hidden_vertex = false;
+ const int active_face_set = SCULPT_active_face_set_get(ss);
- /* This can fail with regular meshes with non-manifold geometry as the visibility state can't
- * 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++) {
- PBVHVertRef vertex = BKE_pbvh_index_to_vertex(ss->pbvh, i);
+ SCULPT_undo_push_begin(ob, op);
+ for (int i = 0; i < totnode; i++) {
+ SCULPT_undo_push_node(ob, nodes[i], SCULPT_UNDO_HIDDEN);
+ }
- if (!SCULPT_vertex_visible_get(ss, vertex)) {
- hidden_vertex = true;
- break;
+ switch (mode) {
+ case SCULPT_FACE_SET_VISIBILITY_TOGGLE: {
+ bool hidden_vertex = false;
+
+ /* This can fail with regular meshes with non-manifold geometry as the visibility state can't
+ * 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++) {
+ PBVHVertRef vertex = BKE_pbvh_index_to_vertex(ss->pbvh, i);
+
+ if (!SCULPT_vertex_visible_get(ss, vertex)) {
+ hidden_vertex = true;
+ break;
+ }
}
}
- }
- for (int i = 0; i < ss->totfaces; i++) {
- if (ss->face_sets[i] <= 0) {
- hidden_vertex = true;
- break;
+ if (ss->hide_poly) {
+ for (int i = 0; i < ss->totfaces; i++) {
+ if (ss->hide_poly[i]) {
+ hidden_vertex = true;
+ break;
+ }
+ }
}
- }
- if (hidden_vertex) {
- SCULPT_face_sets_visibility_all_set(ss, true);
- }
- else {
- SCULPT_face_sets_visibility_all_set(ss, false);
- SCULPT_face_set_visibility_set(ss, active_face_set, true);
- }
- }
+ ss->hide_poly = BKE_sculpt_hide_poly_ensure(mesh);
- if (mode == SCULPT_FACE_SET_VISIBILITY_SHOW_ALL) {
- SCULPT_face_sets_visibility_all_set(ss, true);
- }
+ if (hidden_vertex) {
+ SCULPT_face_visibility_all_set(ss, true);
+ }
+ else {
+ if (ss->face_sets) {
+ SCULPT_face_visibility_all_set(ss, false);
+ SCULPT_face_set_visibility_set(ss, active_face_set, true);
+ }
+ else {
+ SCULPT_face_visibility_all_set(ss, true);
+ }
+ }
+ break;
+ }
+ case SCULPT_FACE_SET_VISIBILITY_SHOW_ACTIVE:
+ ss->hide_poly = BKE_sculpt_hide_poly_ensure(mesh);
- if (mode == SCULPT_FACE_SET_VISIBILITY_SHOW_ACTIVE) {
- SCULPT_face_sets_visibility_all_set(ss, false);
- SCULPT_face_set_visibility_set(ss, active_face_set, true);
- }
+ if (ss->face_sets) {
+ SCULPT_face_visibility_all_set(ss, false);
+ SCULPT_face_set_visibility_set(ss, active_face_set, true);
+ }
+ else {
+ SCULPT_face_set_visibility_set(ss, active_face_set, true);
+ }
+ break;
+ case SCULPT_FACE_SET_VISIBILITY_HIDE_ACTIVE:
+ ss->hide_poly = BKE_sculpt_hide_poly_ensure(mesh);
- if (mode == SCULPT_FACE_SET_VISIBILITY_HIDE_ACTIVE) {
- SCULPT_face_set_visibility_set(ss, active_face_set, false);
- }
+ if (ss->face_sets) {
+ SCULPT_face_set_visibility_set(ss, active_face_set, false);
+ }
+ else {
+ SCULPT_face_visibility_all_set(ss, false);
+ }
- if (mode == SCULPT_FACE_SET_VISIBILITY_INVERT) {
- SCULPT_face_sets_visibility_invert(ss);
+ break;
+ case SCULPT_FACE_SET_VISIBILITY_INVERT:
+ ss->hide_poly = BKE_sculpt_hide_poly_ensure(mesh);
+ SCULPT_face_visibility_all_invert(ss);
+ break;
}
/* For modes that use the cursor active vertex, update the rotation origin for viewport
- * navigation. */
+ * navigation.
+ */
if (ELEM(mode, SCULPT_FACE_SET_VISIBILITY_TOGGLE, SCULPT_FACE_SET_VISIBILITY_SHOW_ACTIVE)) {
UnifiedPaintSettings *ups = &CTX_data_tool_settings(C)->unified_paint_settings;
float location[3];
copy_v3_v3(location, SCULPT_active_vertex_co_get(ss));
- mul_m4_v3(ob->obmat, location);
+ mul_m4_v3(ob->object_to_world, location);
copy_v3_v3(ups->average_stroke_accum, location);
ups->average_stroke_counter = 1;
ups->last_stroke_valid = true;
}
/* Sync face sets visibility and vertex visibility. */
- SCULPT_visibility_sync_all_face_sets_to_verts(ob);
+ SCULPT_visibility_sync_all_from_faces(ob);
SCULPT_undo_push_end(ob);
-
for (int i = 0; i < totnode; i++) {
BKE_pbvh_node_mark_update_visibility(nodes[i]);
}
@@ -968,7 +950,7 @@ static int sculpt_face_sets_change_visibility_invoke(bContext *C,
/* Update the active vertex and Face Set using the cursor position to avoid relying on the paint
* cursor updates. */
SculptCursorGeometryInfo sgi;
- const float mval_fl[2] = {UNPACK2(event->mval)};
+ const float mval_fl[2] = {float(event->mval[0]), float(event->mval[1])};
SCULPT_vertex_random_access_ensure(ss);
SCULPT_cursor_geometry_info_update(C, &sgi, mval_fl, false);
@@ -997,7 +979,7 @@ void SCULPT_OT_face_sets_change_visibility(wmOperatorType *ot)
"");
}
-static int sculpt_face_sets_randomize_colors_exec(bContext *C, wmOperator *UNUSED(op))
+static int sculpt_face_sets_randomize_colors_exec(bContext *C, wmOperator * /*op*/)
{
Object *ob = CTX_data_active_object(C);
@@ -1008,14 +990,14 @@ static int sculpt_face_sets_randomize_colors_exec(bContext *C, wmOperator *UNUSE
return OPERATOR_CANCELLED;
}
- if (!pbvh_has_face_sets(ss->pbvh)) {
+ if (!ss->face_sets) {
return OPERATOR_CANCELLED;
}
PBVH *pbvh = ob->sculpt->pbvh;
PBVHNode **nodes;
int totnode;
- Mesh *mesh = ob->data;
+ Mesh *mesh = static_cast<Mesh *>(ob->data);
mesh->face_sets_color_seed += 1;
if (ss->face_sets) {
@@ -1026,7 +1008,7 @@ static int sculpt_face_sets_randomize_colors_exec(bContext *C, wmOperator *UNUSE
}
BKE_pbvh_face_sets_color_set(pbvh, mesh->face_sets_color_seed, mesh->face_sets_color_default);
- BKE_pbvh_search_gather(pbvh, NULL, NULL, &nodes, &totnode);
+ BKE_pbvh_search_gather(pbvh, nullptr, nullptr, &nodes, &totnode);
for (int i = 0; i < totnode; i++) {
BKE_pbvh_node_mark_redraw(nodes[i]);
}
@@ -1052,13 +1034,13 @@ void SCULPT_OT_face_sets_randomize_colors(wmOperatorType *ot)
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
-typedef enum eSculptFaceSetEditMode {
+enum eSculptFaceSetEditMode {
SCULPT_FACE_SET_EDIT_GROW = 0,
SCULPT_FACE_SET_EDIT_SHRINK = 1,
SCULPT_FACE_SET_EDIT_DELETE_GEOMETRY = 2,
SCULPT_FACE_SET_EDIT_FAIR_POSITIONS = 3,
SCULPT_FACE_SET_EDIT_FAIR_TANGENCY = 4,
-} eSculptFaceSetEditMode;
+};
static EnumPropertyItem prop_sculpt_face_sets_edit_types[] = {
{
@@ -1098,7 +1080,7 @@ static EnumPropertyItem prop_sculpt_face_sets_edit_types[] = {
"Creates a smooth as possible geometry patch from the Face Set minimizing changes in "
"vertex tangents",
},
- {0, NULL, 0, NULL, NULL},
+ {0, nullptr, 0, nullptr, nullptr},
};
static void sculpt_face_set_grow(Object *ob,
@@ -1164,22 +1146,25 @@ static void sculpt_face_set_shrink(Object *ob,
}
}
-static bool check_single_face_set(SculptSession *ss, int *face_sets, const bool check_visible_only)
+static bool check_single_face_set(SculptSession *ss,
+ const int *face_sets,
+ const bool check_visible_only)
{
- if (face_sets == NULL) {
+ if (face_sets == nullptr) {
return true;
}
int first_face_set = SCULPT_FACE_SET_NONE;
if (check_visible_only) {
for (int f = 0; f < ss->totfaces; f++) {
- if (face_sets[f] > 0) {
- first_face_set = face_sets[f];
- break;
+ if (ss->hide_poly && ss->hide_poly[f]) {
+ continue;
}
+ first_face_set = face_sets[f];
+ break;
}
}
else {
- first_face_set = abs(face_sets[0]);
+ first_face_set = face_sets[0];
}
if (first_face_set == SCULPT_FACE_SET_NONE) {
@@ -1187,8 +1172,10 @@ static bool check_single_face_set(SculptSession *ss, int *face_sets, const bool
}
for (int f = 0; f < ss->totfaces; f++) {
- const int face_set_id = check_visible_only ? face_sets[f] : abs(face_sets[f]);
- if (face_set_id != first_face_set) {
+ if (check_visible_only && ss->hide_poly && ss->hide_poly[f]) {
+ continue;
+ }
+ if (face_sets[f] != first_face_set) {
return false;
}
}
@@ -1201,19 +1188,16 @@ static void sculpt_face_set_delete_geometry(Object *ob,
const bool modify_hidden)
{
- Mesh *mesh = ob->data;
+ Mesh *mesh = static_cast<Mesh *>(ob->data);
const BMAllocTemplate allocsize = BMALLOC_TEMPLATE_FROM_ME(mesh);
- BMesh *bm = BM_mesh_create(&allocsize,
- &((struct BMeshCreateParams){
- .use_toolflags = true,
- }));
-
- BM_mesh_bm_from_me(bm,
- mesh,
- (&(struct BMeshFromMeshParams){
- .calc_face_normal = true,
- .calc_vert_normal = true,
- }));
+ BMeshCreateParams create_params{};
+ create_params.use_toolflags = true;
+ BMesh *bm = BM_mesh_create(&allocsize, &create_params);
+
+ BMeshFromMeshParams convert_params{};
+ convert_params.calc_vert_normal = true;
+ convert_params.calc_face_normal = true;
+ BM_mesh_bm_from_me(bm, mesh, &convert_params);
BM_mesh_elem_table_init(bm, BM_FACE);
BM_mesh_elem_table_ensure(bm, BM_FACE);
@@ -1222,32 +1206,31 @@ static void sculpt_face_set_delete_geometry(Object *ob,
BMFace *f;
BM_ITER_MESH (f, &iter, bm, BM_FACES_OF_MESH) {
const int face_index = BM_elem_index_get(f);
- const int face_set_id = modify_hidden ? abs(ss->face_sets[face_index]) :
- ss->face_sets[face_index];
- BM_elem_flag_set(f, BM_ELEM_TAG, face_set_id == active_face_set_id);
+ if (!modify_hidden && ss->hide_poly && ss->hide_poly[face_index]) {
+ continue;
+ }
+ BM_elem_flag_set(f, BM_ELEM_TAG, ss->face_sets[face_index] == active_face_set_id);
}
BM_mesh_delete_hflag_context(bm, BM_ELEM_TAG, DEL_FACES);
BM_mesh_elem_hflag_disable_all(bm, BM_VERT | BM_EDGE | BM_FACE, BM_ELEM_TAG, false);
- BM_mesh_bm_to_me(NULL,
- bm,
- ob->data,
- (&(struct BMeshToMeshParams){
- .calc_object_remap = false,
- }));
+ BMeshToMeshParams bmesh_to_mesh_params{};
+ bmesh_to_mesh_params.calc_object_remap = false;
+ BM_mesh_bm_to_me(nullptr, bm, mesh, &bmesh_to_mesh_params);
BM_mesh_free(bm);
}
static void sculpt_face_set_edit_fair_face_set(Object *ob,
const int active_face_set_id,
- const int fair_order)
+ const eMeshFairingDepth fair_order)
{
SculptSession *ss = ob->sculpt;
const int totvert = SCULPT_vertex_count_get(ss);
- Mesh *mesh = ob->data;
- bool *fair_verts = MEM_malloc_arrayN(totvert, sizeof(bool), "fair vertices");
+ Mesh *mesh = static_cast<Mesh *>(ob->data);
+ bool *fair_verts = static_cast<bool *>(
+ MEM_malloc_arrayN(totvert, sizeof(bool), "fair vertices"));
SCULPT_boundary_info_ensure(ob);
@@ -1273,13 +1256,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 = static_cast<int *>(MEM_dupallocN(ss->face_sets));
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 = static_cast<int *>(MEM_dupallocN(ss->face_sets));
sculpt_face_set_shrink(ob, ss, prev_face_sets, active_face_set_id, modify_hidden);
MEM_SAFE_FREE(prev_face_sets);
break;
@@ -1339,21 +1322,23 @@ static void sculpt_face_set_edit_modify_geometry(bContext *C,
const bool modify_hidden,
wmOperator *op)
{
+ Mesh *mesh = static_cast<Mesh *>(ob->data);
ED_sculpt_undo_geometry_begin(ob, op);
sculpt_face_set_apply_edit(ob, abs(active_face_set), mode, modify_hidden);
ED_sculpt_undo_geometry_end(ob);
- BKE_mesh_batch_cache_dirty_tag(ob->data, BKE_MESH_BATCH_DIRTY_ALL);
+ BKE_mesh_batch_cache_dirty_tag(mesh, BKE_MESH_BATCH_DIRTY_ALL);
DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
- WM_event_add_notifier(C, NC_GEOM | ND_DATA, ob->data);
+ WM_event_add_notifier(C, NC_GEOM | ND_DATA, mesh);
}
static void face_set_edit_do_post_visibility_updates(Object *ob, PBVHNode **nodes, int totnode)
{
SculptSession *ss = ob->sculpt;
PBVH *pbvh = ss->pbvh;
+ Mesh *mesh = static_cast<Mesh *>(ob->data);
/* Sync face sets visibility and vertex visibility as now all Face Sets are visible. */
- SCULPT_visibility_sync_all_face_sets_to_verts(ob);
+ SCULPT_visibility_sync_all_from_faces(ob);
for (int i = 0; i < totnode; i++) {
BKE_pbvh_node_mark_update_visibility(nodes[i]);
@@ -1362,7 +1347,7 @@ static void face_set_edit_do_post_visibility_updates(Object *ob, PBVHNode **node
BKE_pbvh_update_vertex_data(ss->pbvh, PBVH_UpdateVisibility);
if (BKE_pbvh_type(pbvh) == PBVH_FACES) {
- BKE_mesh_flush_hidden_from_verts(ob->data);
+ BKE_mesh_flush_hidden_from_verts(mesh);
}
}
@@ -1375,7 +1360,7 @@ static void sculpt_face_set_edit_modify_face_sets(Object *ob,
PBVH *pbvh = ob->sculpt->pbvh;
PBVHNode **nodes;
int totnode;
- BKE_pbvh_search_gather(pbvh, NULL, NULL, &nodes, &totnode);
+ BKE_pbvh_search_gather(pbvh, nullptr, nullptr, &nodes, &totnode);
if (!nodes) {
return;
@@ -1399,7 +1384,7 @@ static void sculpt_face_set_edit_modify_coordinates(bContext *C,
PBVH *pbvh = ss->pbvh;
PBVHNode **nodes;
int totnode;
- BKE_pbvh_search_gather(pbvh, NULL, NULL, &nodes, &totnode);
+ BKE_pbvh_search_gather(pbvh, nullptr, nullptr, &nodes, &totnode);
SCULPT_undo_push_begin(ob, op);
for (int i = 0; i < totnode; i++) {
BKE_pbvh_node_mark_update(nodes[i]);
@@ -1422,19 +1407,21 @@ static int sculpt_face_set_edit_invoke(bContext *C, wmOperator *op, const wmEven
SculptSession *ss = ob->sculpt;
Depsgraph *depsgraph = CTX_data_ensure_evaluated_depsgraph(C);
- const int mode = RNA_enum_get(op->ptr, "mode");
+ const eSculptFaceSetEditMode mode = static_cast<eSculptFaceSetEditMode>(
+ RNA_enum_get(op->ptr, "mode"));
const bool modify_hidden = RNA_boolean_get(op->ptr, "modify_hidden");
if (!sculpt_face_set_edit_is_operation_valid(ss, mode, modify_hidden)) {
return OPERATOR_CANCELLED;
}
+ ss->face_sets = BKE_sculpt_face_sets_ensure(BKE_mesh_from_object(ob));
BKE_sculpt_update_object_for_edit(depsgraph, ob, true, false, false);
/* Update the current active Face Set and Vertex as the operator can be used directly from the
* tool without brush cursor. */
SculptCursorGeometryInfo sgi;
- const float mval_fl[2] = {UNPACK2(event->mval)};
+ const float mval_fl[2] = {float(event->mval[0]), float(event->mval[1])};
if (!SCULPT_cursor_geometry_info_update(C, &sgi, mval_fl, false)) {
/* The cursor is not over the mesh. Cancel to avoid editing the last updated Face Set ID. */
return OPERATOR_CANCELLED;
diff --git a/source/blender/editors/sculpt_paint/sculpt_filter_color.c b/source/blender/editors/sculpt_paint/sculpt_filter_color.c
index 161fc563950..89cb67a875f 100644
--- a/source/blender/editors/sculpt_paint/sculpt_filter_color.c
+++ b/source/blender/editors/sculpt_paint/sculpt_filter_color.c
@@ -7,47 +7,29 @@
#include "MEM_guardedalloc.h"
-#include "BLI_blenlib.h"
-#include "BLI_hash.h"
#include "BLI_math.h"
#include "BLI_math_color_blend.h"
#include "BLI_task.h"
-#include "DNA_mesh_types.h"
#include "DNA_meshdata_types.h"
-#include "BKE_brush.h"
-#include "BKE_colortools.h"
#include "BKE_context.h"
-#include "BKE_mesh.h"
-#include "BKE_mesh_mapping.h"
-#include "BKE_object.h"
#include "BKE_paint.h"
#include "BKE_pbvh.h"
-#include "BKE_report.h"
-#include "BKE_scene.h"
#include "IMB_colormanagement.h"
#include "DEG_depsgraph.h"
#include "WM_api.h"
-#include "WM_message.h"
-#include "WM_toolsystem.h"
#include "WM_types.h"
-#include "ED_object.h"
#include "ED_paint.h"
-#include "ED_screen.h"
-#include "ED_sculpt.h"
-#include "paint_intern.h"
#include "sculpt_intern.h"
#include "RNA_access.h"
#include "RNA_define.h"
-#include "UI_interface.h"
-
#include "bmesh.h"
#include <math.h>
@@ -95,16 +77,23 @@ static void color_filter_task_cb(void *__restrict userdata,
SculptOrigVertData orig_data;
SCULPT_orig_vert_data_init(&orig_data, data->ob, data->nodes[n], SCULPT_UNDO_COLOR);
+ AutomaskingNodeData automask_data;
+ SCULPT_automasking_node_begin(
+ data->ob, ss, ss->filter_cache->automasking, &automask_data, data->nodes[n]);
+
PBVHVertexIter vd;
BKE_pbvh_vertex_iter_begin (ss->pbvh, data->nodes[n], vd, PBVH_ITER_UNIQUE) {
SCULPT_orig_vert_data_update(&orig_data, &vd);
+ SCULPT_automasking_node_update(ss, &automask_data, &vd);
+
float orig_color[3], final_color[4], hsv_color[3];
int hue;
float brightness, contrast, gain, delta, offset;
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.vertex);
+ fade *= SCULPT_automasking_factor_get(
+ ss->filter_cache->automasking, ss, vd.vertex, &automask_data);
if (fade == 0.0f) {
continue;
}
@@ -334,6 +323,9 @@ static int sculpt_color_filter_invoke(bContext *C, wmOperator *op, const wmEvent
const bool use_automasking = SCULPT_is_automasking_enabled(sd, ss, NULL);
if (use_automasking) {
+ /* Increment stroke id for automasking system. */
+ SCULPT_stroke_id_next(ob);
+
/* Update the active face set manually as the paint cursor is not enabled when using the Mesh
* Filter Tool. */
float mval_fl[2] = {UNPACK2(event->mval)};
@@ -358,7 +350,8 @@ static int sculpt_color_filter_invoke(bContext *C, wmOperator *op, const wmEvent
return OPERATOR_CANCELLED;
}
- SCULPT_filter_cache_init(C, ob, sd, SCULPT_UNDO_COLOR);
+ SCULPT_filter_cache_init(
+ C, ob, sd, SCULPT_UNDO_COLOR, event->mval, RNA_float_get(op->ptr, "area_normal_radius"));
FilterCache *filter_cache = ss->filter_cache;
filter_cache->active_face_set = SCULPT_FACE_SET_NONE;
filter_cache->automasking = SCULPT_automasking_cache_init(sd, NULL, ob);
@@ -383,9 +376,9 @@ void SCULPT_OT_color_filter(struct wmOperatorType *ot)
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
/* rna */
+ SCULPT_mesh_filter_properties(ot);
+
RNA_def_enum(ot->srna, "type", prop_color_filter_types, COLOR_FILTER_HUE, "Filter Type", "");
- RNA_def_float(
- ot->srna, "strength", 1.0f, -10.0f, 10.0f, "Strength", "Filter strength", -10.0f, 10.0f);
PropertyRNA *prop = RNA_def_float_color(
ot->srna, "fill_color", 3, NULL, 0.0f, FLT_MAX, "Fill Color", "", 0.0f, 1.0f);
diff --git a/source/blender/editors/sculpt_paint/sculpt_filter_mask.c b/source/blender/editors/sculpt_paint/sculpt_filter_mask.c
index bb27e4f1e9e..8e199a72858 100644
--- a/source/blender/editors/sculpt_paint/sculpt_filter_mask.c
+++ b/source/blender/editors/sculpt_paint/sculpt_filter_mask.c
@@ -7,20 +7,13 @@
#include "MEM_guardedalloc.h"
-#include "BLI_blenlib.h"
-#include "BLI_hash.h"
#include "BLI_math.h"
#include "BLI_task.h"
-#include "DNA_mesh_types.h"
#include "DNA_meshdata_types.h"
#include "DNA_modifier_types.h"
-#include "BKE_brush.h"
#include "BKE_context.h"
-#include "BKE_mesh.h"
-#include "BKE_mesh_mapping.h"
-#include "BKE_object.h"
#include "BKE_paint.h"
#include "BKE_pbvh.h"
#include "BKE_scene.h"
@@ -28,21 +21,13 @@
#include "DEG_depsgraph.h"
#include "WM_api.h"
-#include "WM_message.h"
-#include "WM_toolsystem.h"
#include "WM_types.h"
-#include "ED_object.h"
-#include "ED_screen.h"
-#include "ED_sculpt.h"
-#include "paint_intern.h"
#include "sculpt_intern.h"
#include "RNA_access.h"
#include "RNA_define.h"
-#include "UI_interface.h"
-
#include "bmesh.h"
#include <math.h>
@@ -182,7 +167,7 @@ static int sculpt_mask_filter_exec(bContext *C, wmOperator *op)
int filter_type = RNA_enum_get(op->ptr, "filter_type");
MultiresModifierData *mmd = BKE_sculpt_multires_active(scene, ob);
- BKE_sculpt_mask_layers_ensure(ob, mmd);
+ BKE_sculpt_mask_layers_ensure(CTX_data_depsgraph_pointer(C), CTX_data_main(C), ob, mmd);
BKE_sculpt_update_object_for_edit(depsgraph, ob, true, true, false);
@@ -303,173 +288,3 @@ void SCULPT_OT_mask_filter(struct wmOperatorType *ot)
"Auto Iteration Count",
"Use a automatic number of iterations based on the number of vertices of the sculpt");
}
-
-static float neighbor_dirty_mask(SculptSession *ss, PBVHVertexIter *vd)
-{
- int total = 0;
- float avg[3];
- zero_v3(avg);
-
- SculptVertexNeighborIter ni;
- SCULPT_VERTEX_NEIGHBORS_ITER_BEGIN (ss, vd->vertex, ni) {
- float normalized[3];
- sub_v3_v3v3(normalized, SCULPT_vertex_co_get(ss, ni.vertex), vd->co);
- normalize_v3(normalized);
- add_v3_v3(avg, normalized);
- total++;
- }
- SCULPT_VERTEX_NEIGHBORS_ITER_END(ni);
-
- if (total > 0) {
- mul_v3_fl(avg, 1.0f / total);
- float dot = dot_v3v3(avg, vd->no ? vd->no : vd->fno);
- float angle = max_ff(saacosf(dot), 0.0f);
- return angle;
- }
- return 0.0f;
-}
-
-typedef struct DirtyMaskRangeData {
- float min, max;
-} DirtyMaskRangeData;
-
-static void dirty_mask_compute_range_task_cb(void *__restrict userdata,
- const int i,
- const TaskParallelTLS *__restrict tls)
-{
- SculptThreadedTaskData *data = userdata;
- SculptSession *ss = data->ob->sculpt;
- PBVHNode *node = data->nodes[i];
- DirtyMaskRangeData *range = tls->userdata_chunk;
- PBVHVertexIter vd;
-
- BKE_pbvh_vertex_iter_begin (ss->pbvh, node, vd, PBVH_ITER_UNIQUE) {
- float dirty_mask = neighbor_dirty_mask(ss, &vd);
- range->min = min_ff(dirty_mask, range->min);
- range->max = max_ff(dirty_mask, range->max);
- }
- BKE_pbvh_vertex_iter_end;
-}
-
-static void dirty_mask_compute_range_reduce(const void *__restrict UNUSED(userdata),
- void *__restrict chunk_join,
- void *__restrict chunk)
-{
- DirtyMaskRangeData *join = chunk_join;
- DirtyMaskRangeData *range = chunk;
- join->min = min_ff(range->min, join->min);
- join->max = max_ff(range->max, join->max);
-}
-
-static void dirty_mask_apply_task_cb(void *__restrict userdata,
- const int i,
- const TaskParallelTLS *__restrict UNUSED(tls))
-{
- SculptThreadedTaskData *data = userdata;
- SculptSession *ss = data->ob->sculpt;
- PBVHNode *node = data->nodes[i];
- PBVHVertexIter vd;
-
- const bool dirty_only = data->dirty_mask_dirty_only;
- const float min = data->dirty_mask_min;
- const float max = data->dirty_mask_max;
-
- float range = max - min;
- if (range < 0.0001f) {
- range = 0.0f;
- }
- else {
- range = 1.0f / range;
- }
-
- BKE_pbvh_vertex_iter_begin (ss->pbvh, node, vd, PBVH_ITER_UNIQUE) {
- float dirty_mask = neighbor_dirty_mask(ss, &vd);
- float mask = *vd.mask + (1.0f - ((dirty_mask - min) * range));
- if (dirty_only) {
- mask = fminf(mask, 0.5f) * 2.0f;
- }
- *vd.mask = CLAMPIS(mask, 0.0f, 1.0f);
- }
- BKE_pbvh_vertex_iter_end;
- BKE_pbvh_node_mark_update_mask(node);
-}
-
-static int sculpt_dirty_mask_exec(bContext *C, wmOperator *op)
-{
- ARegion *region = CTX_wm_region(C);
- Object *ob = CTX_data_active_object(C);
- SculptSession *ss = ob->sculpt;
- Depsgraph *depsgraph = CTX_data_depsgraph_pointer(C);
- PBVH *pbvh = ob->sculpt->pbvh;
- PBVHNode **nodes;
- Sculpt *sd = CTX_data_tool_settings(C)->sculpt;
- int totnode;
-
- BKE_sculpt_update_object_for_edit(depsgraph, ob, true, true, false);
-
- SCULPT_vertex_random_access_ensure(ss);
-
- if (!ob->sculpt->pmap) {
- return OPERATOR_CANCELLED;
- }
-
- BKE_pbvh_search_gather(pbvh, NULL, NULL, &nodes, &totnode);
- SCULPT_undo_push_begin(ob, op);
-
- for (int i = 0; i < totnode; i++) {
- SCULPT_undo_push_node(ob, nodes[i], SCULPT_UNDO_MASK);
- }
-
- SculptThreadedTaskData data = {
- .sd = sd,
- .ob = ob,
- .nodes = nodes,
- .dirty_mask_dirty_only = RNA_boolean_get(op->ptr, "dirty_only"),
- };
- DirtyMaskRangeData range = {
- .min = FLT_MAX,
- .max = -FLT_MAX,
- };
-
- TaskParallelSettings settings;
- BKE_pbvh_parallel_range_settings(&settings, true, totnode);
-
- settings.func_reduce = dirty_mask_compute_range_reduce;
- settings.userdata_chunk = &range;
- settings.userdata_chunk_size = sizeof(DirtyMaskRangeData);
-
- BLI_task_parallel_range(0, totnode, &data, dirty_mask_compute_range_task_cb, &settings);
- data.dirty_mask_min = range.min;
- data.dirty_mask_max = range.max;
- BLI_task_parallel_range(0, totnode, &data, dirty_mask_apply_task_cb, &settings);
-
- MEM_SAFE_FREE(nodes);
-
- BKE_pbvh_update_vertex_data(pbvh, PBVH_UpdateMask);
-
- SCULPT_undo_push_end(ob);
-
- ED_region_tag_redraw(region);
-
- WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, ob);
-
- return OPERATOR_FINISHED;
-}
-
-void SCULPT_OT_dirty_mask(struct wmOperatorType *ot)
-{
- /* Identifiers. */
- ot->name = "Dirty Mask";
- ot->idname = "SCULPT_OT_dirty_mask";
- ot->description = "Generates a mask based on the geometry cavity and pointiness";
-
- /* API callbacks. */
- ot->exec = sculpt_dirty_mask_exec;
- ot->poll = SCULPT_mode_poll;
-
- ot->flag = OPTYPE_REGISTER;
-
- /* RNA. */
- RNA_def_boolean(
- ot->srna, "dirty_only", false, "Dirty Only", "Don't calculate cleans for convex areas");
-}
diff --git a/source/blender/editors/sculpt_paint/sculpt_filter_mesh.c b/source/blender/editors/sculpt_paint/sculpt_filter_mesh.c
index e576cfda3af..c158cf33f6d 100644
--- a/source/blender/editors/sculpt_paint/sculpt_filter_mesh.c
+++ b/source/blender/editors/sculpt_paint/sculpt_filter_mesh.c
@@ -7,34 +7,24 @@
#include "MEM_guardedalloc.h"
-#include "BLI_blenlib.h"
#include "BLI_hash.h"
#include "BLI_math.h"
#include "BLI_task.h"
-#include "DNA_mesh_types.h"
#include "DNA_meshdata_types.h"
#include "BKE_brush.h"
#include "BKE_context.h"
-#include "BKE_mesh.h"
-#include "BKE_mesh_mapping.h"
-#include "BKE_object.h"
#include "BKE_paint.h"
#include "BKE_pbvh.h"
-#include "BKE_scene.h"
#include "DEG_depsgraph.h"
#include "WM_api.h"
-#include "WM_message.h"
-#include "WM_toolsystem.h"
#include "WM_types.h"
-#include "ED_object.h"
-#include "ED_screen.h"
-#include "ED_sculpt.h"
#include "ED_view3d.h"
+
#include "paint_intern.h"
#include "sculpt_intern.h"
@@ -101,7 +91,12 @@ static void filter_cache_init_task_cb(void *__restrict userdata,
SCULPT_undo_push_node(data->ob, node, data->filter_undo_type);
}
-void SCULPT_filter_cache_init(bContext *C, Object *ob, Sculpt *sd, const int undo_type)
+void SCULPT_filter_cache_init(bContext *C,
+ Object *ob,
+ Sculpt *sd,
+ const int undo_type,
+ const int mval[2],
+ float area_normal_radius)
{
SculptSession *ss = ob->sculpt;
PBVH *pbvh = ob->sculpt->pbvh;
@@ -151,14 +146,87 @@ void SCULPT_filter_cache_init(bContext *C, Object *ob, Sculpt *sd, const int und
0, ss->filter_cache->totnode, &data, filter_cache_init_task_cb, &settings);
/* Setup orientation matrices. */
- copy_m4_m4(ss->filter_cache->obmat, ob->obmat);
- invert_m4_m4(ss->filter_cache->obmat_inv, ob->obmat);
+ copy_m4_m4(ss->filter_cache->obmat, ob->object_to_world);
+ invert_m4_m4(ss->filter_cache->obmat_inv, ob->object_to_world);
Depsgraph *depsgraph = CTX_data_ensure_evaluated_depsgraph(C);
ViewContext vc;
ED_view3d_viewcontext_init(C, &vc, depsgraph);
copy_m4_m4(ss->filter_cache->viewmat, vc.rv3d->viewmat);
copy_m4_m4(ss->filter_cache->viewmat_inv, vc.rv3d->viewinv);
+
+ Scene *scene = CTX_data_scene(C);
+ UnifiedPaintSettings *ups = &scene->toolsettings->unified_paint_settings;
+
+ float co[3];
+ float mval_fl[2] = {(float)mval[0], (float)mval[1]};
+
+ if (SCULPT_stroke_get_location(C, co, mval_fl, false)) {
+ PBVHNode **nodes;
+ int totnode;
+
+ /* Get radius from brush. */
+ Brush *brush = BKE_paint_brush(&sd->paint);
+ float radius;
+
+ if (brush) {
+ if (BKE_brush_use_locked_size(scene, brush)) {
+ radius = paint_calc_object_space_radius(
+ &vc, co, (float)BKE_brush_size_get(scene, brush) * area_normal_radius);
+ }
+ else {
+ radius = BKE_brush_unprojected_radius_get(scene, brush) * area_normal_radius;
+ }
+ }
+ else {
+ radius = paint_calc_object_space_radius(&vc, co, (float)ups->size * area_normal_radius);
+ }
+
+ SculptSearchSphereData search_data2 = {
+ .original = true,
+ .center = co,
+ .radius_squared = radius * radius,
+ .ignore_fully_ineffective = true,
+ };
+
+ BKE_pbvh_search_gather(pbvh, SCULPT_search_sphere_cb, &search_data2, &nodes, &totnode);
+
+ if (SCULPT_pbvh_calc_area_normal(
+ brush, ob, nodes, totnode, true, ss->filter_cache->initial_normal)) {
+ copy_v3_v3(ss->last_normal, ss->filter_cache->initial_normal);
+ }
+ else {
+ copy_v3_v3(ss->filter_cache->initial_normal, ss->last_normal);
+ }
+
+ MEM_SAFE_FREE(nodes);
+
+ /* Update last stroke location */
+
+ mul_m4_v3(ob->object_to_world, co);
+
+ add_v3_v3(ups->average_stroke_accum, co);
+ ups->average_stroke_counter++;
+ ups->last_stroke_valid = true;
+ }
+ else {
+ /* Use last normal. */
+ copy_v3_v3(ss->filter_cache->initial_normal, ss->last_normal);
+ }
+
+ /* Update view normal */
+ float projection_mat[4][4];
+ float mat[3][3];
+ float viewDir[3] = {0.0f, 0.0f, 1.0f};
+
+ ED_view3d_ob_project_mat_get(vc.rv3d, ob, projection_mat);
+
+ invert_m4_m4(ob->world_to_object, ob->object_to_world);
+ copy_m3_m4(mat, vc.rv3d->viewinv);
+ mul_m3_v3(mat, viewDir);
+ copy_m3_m4(mat, ob->world_to_object);
+ mul_m3_v3(mat, viewDir);
+ normalize_v3_v3(ss->filter_cache->view_normal, viewDir);
}
void SCULPT_filter_cache_free(SculptSession *ss)
@@ -288,15 +356,20 @@ static void mesh_filter_task_cb(void *__restrict userdata,
/* This produces better results as the relax operation is no completely focused on the
* boundaries. */
const bool relax_face_sets = !(ss->filter_cache->iteration_count % 3 == 0);
+ AutomaskingNodeData automask_data;
+ SCULPT_automasking_node_begin(data->ob, ss, ss->filter_cache->automasking, &automask_data, node);
PBVHVertexIter vd;
BKE_pbvh_vertex_iter_begin (ss->pbvh, node, vd, PBVH_ITER_UNIQUE) {
SCULPT_orig_vert_data_update(&orig_data, &vd);
+ SCULPT_automasking_node_update(ss, &automask_data, &vd);
+
float orig_co[3], val[3], avg[3], disp[3], disp2[3], transform[3][3], final_pos[3];
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.vertex);
+ fade *= SCULPT_automasking_factor_get(
+ ss->filter_cache->automasking, ss, vd.vertex, &automask_data);
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
@@ -580,11 +653,18 @@ static void mesh_filter_surface_smooth_displace_task_cb(
PBVHNode *node = data->nodes[i];
PBVHVertexIter vd;
+ AutomaskingNodeData automask_data;
+ SCULPT_automasking_node_begin(
+ data->ob, ss, ss->filter_cache->automasking, &automask_data, data->nodes[i]);
+
BKE_pbvh_vertex_iter_begin (ss->pbvh, node, vd, PBVH_ITER_UNIQUE) {
+ SCULPT_automasking_node_update(ss, &automask_data, &vd);
+
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.vertex);
+ fade *= SCULPT_automasking_factor_get(
+ ss->filter_cache->automasking, ss, vd.vertex, &automask_data);
if (fade == 0.0f) {
continue;
}
@@ -681,6 +761,9 @@ static int sculpt_mesh_filter_invoke(bContext *C, wmOperator *op, const wmEvent
}
if (use_automasking) {
+ /* Increment stroke id for automasking system. */
+ SCULPT_stroke_id_next(ob);
+
/* Update the active face set manually as the paint cursor is not enabled when using the Mesh
* Filter Tool. */
float mval_fl[2] = {UNPACK2(event->mval)};
@@ -696,7 +779,8 @@ static int sculpt_mesh_filter_invoke(bContext *C, wmOperator *op, const wmEvent
SCULPT_undo_push_begin(ob, op);
- SCULPT_filter_cache_init(C, ob, sd, SCULPT_UNDO_COORDS);
+ SCULPT_filter_cache_init(
+ C, ob, sd, SCULPT_UNDO_COORDS, event->mval, RNA_float_get(op->ptr, "area_normal_radius"));
FilterCache *filter_cache = ss->filter_cache;
filter_cache->active_face_set = SCULPT_FACE_SET_NONE;
@@ -743,6 +827,22 @@ static int sculpt_mesh_filter_invoke(bContext *C, wmOperator *op, const wmEvent
return OPERATOR_RUNNING_MODAL;
}
+void SCULPT_mesh_filter_properties(struct wmOperatorType *ot)
+{
+ RNA_def_float(
+ ot->srna,
+ "area_normal_radius",
+ 0.25,
+ 0.001,
+ 5.0,
+ "Normal Radius",
+ "Radius used for calculating area normal on initial click,\nin percentage of brush radius",
+ 0.01,
+ 1.0);
+ RNA_def_float(
+ ot->srna, "strength", 1.0f, -10.0f, 10.0f, "Strength", "Filter strength", -10.0f, 10.0f);
+}
+
void SCULPT_OT_mesh_filter(struct wmOperatorType *ot)
{
/* Identifiers. */
@@ -758,14 +858,14 @@ void SCULPT_OT_mesh_filter(struct wmOperatorType *ot)
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
/* RNA. */
+ SCULPT_mesh_filter_properties(ot);
+
RNA_def_enum(ot->srna,
"type",
prop_mesh_filter_types,
MESH_FILTER_INFLATE,
"Filter Type",
"Operation that is going to be applied to the mesh");
- RNA_def_float(
- ot->srna, "strength", 1.0f, -10.0f, 10.0f, "Strength", "Filter strength", -10.0f, 10.0f);
RNA_def_enum_flag(ot->srna,
"deform_axis",
prop_mesh_filter_deform_axis_items,
diff --git a/source/blender/editors/sculpt_paint/sculpt_geodesic.c b/source/blender/editors/sculpt_paint/sculpt_geodesic.c
index c0856ab21d2..5d74853be8c 100644
--- a/source/blender/editors/sculpt_paint/sculpt_geodesic.c
+++ b/source/blender/editors/sculpt_paint/sculpt_geodesic.c
@@ -7,52 +7,26 @@
#include "MEM_guardedalloc.h"
-#include "BLI_blenlib.h"
#include "BLI_linklist_stack.h"
#include "BLI_math.h"
#include "BLI_task.h"
-#include "BLT_translation.h"
-
#include "DNA_brush_types.h"
#include "DNA_mesh_types.h"
#include "DNA_meshdata_types.h"
#include "DNA_object_types.h"
-#include "BKE_brush.h"
#include "BKE_ccg.h"
-#include "BKE_colortools.h"
#include "BKE_context.h"
-#include "BKE_image.h"
#include "BKE_mesh.h"
#include "BKE_mesh_mapping.h"
-#include "BKE_multires.h"
-#include "BKE_node.h"
#include "BKE_object.h"
#include "BKE_paint.h"
#include "BKE_pbvh.h"
-#include "BKE_scene.h"
-#include "BKE_subdiv_ccg.h"
-
-#include "DEG_depsgraph.h"
-
-#include "WM_api.h"
-#include "WM_toolsystem.h"
-#include "WM_types.h"
-#include "RNA_access.h"
-#include "RNA_define.h"
-
-#include "ED_object.h"
-#include "ED_screen.h"
-#include "ED_sculpt.h"
-#include "ED_view3d.h"
#include "paint_intern.h"
#include "sculpt_intern.h"
-#include "IMB_colormanagement.h"
-#include "IMB_imbuf.h"
-
#include "bmesh.h"
#include <math.h>
@@ -170,8 +144,6 @@ static float *SCULPT_geodesic_mesh_create(Object *ob,
}
}
- const bool *hide_poly = BKE_pbvh_get_poly_hide(ss->pbvh);
-
/* Add edges adjacent to an initial vertex to the queue. */
for (int i = 0; i < totedge; i++) {
const int v1 = edges[i].v1;
@@ -201,7 +173,7 @@ static float *SCULPT_geodesic_mesh_create(Object *ob,
if (ss->epmap[e].count != 0) {
for (int poly_map_index = 0; poly_map_index < ss->epmap[e].count; poly_map_index++) {
const int poly = ss->epmap[e].indices[poly_map_index];
- if (hide_poly && hide_poly[poly]) {
+ if (ss->hide_poly && ss->hide_poly[poly]) {
continue;
}
const MPoly *mpoly = &polys[poly];
diff --git a/source/blender/editors/sculpt_paint/sculpt_intern.h b/source/blender/editors/sculpt_paint/sculpt_intern.h
index 7a72e5cc84b..bf47b64d176 100644
--- a/source/blender/editors/sculpt_paint/sculpt_intern.h
+++ b/source/blender/editors/sculpt_paint/sculpt_intern.h
@@ -27,6 +27,7 @@ extern "C" {
#endif
struct AutomaskingCache;
+struct AutomaskingNodeData;
struct Image;
struct ImageUser;
struct KeyBlock;
@@ -34,6 +35,9 @@ struct Object;
struct SculptUndoNode;
struct bContext;
struct PaintModeSettings;
+struct wmKeyConfig;
+struct wmOperator;
+struct wmOperatorType;
/* Updates */
@@ -311,10 +315,6 @@ typedef struct SculptThreadedTaskData {
float *cloth_sim_initial_location;
float cloth_sim_radius;
- float dirty_mask_min;
- float dirty_mask_max;
- bool dirty_mask_dirty_only;
-
/* Mask By Color Tool */
float mask_by_color_threshold;
@@ -332,7 +332,7 @@ typedef struct SculptThreadedTaskData {
int mask_init_seed;
ThreadMutex mutex;
-
+ int iteration;
} SculptThreadedTaskData;
/*************** Brush testing declarations ****************/
@@ -398,13 +398,20 @@ typedef struct AutomaskingSettings {
/* Flags from eAutomasking_flag. */
int flags;
int initial_face_set;
+
+ float cavity_factor;
+ int cavity_blur_steps;
+ struct CurveMapping *cavity_curve;
+
+ float start_normal_limit, start_normal_falloff;
+ float view_normal_limit, view_normal_falloff;
} AutomaskingSettings;
typedef struct AutomaskingCache {
AutomaskingSettings settings;
- /* Precomputed auto-mask factor indexed by vertex, owned by the auto-masking system and
- * initialized in #SCULPT_automasking_cache_init when needed. */
- float *factor;
+
+ bool can_reuse_mask;
+ uchar current_stroke_id;
} AutomaskingCache;
typedef struct FilterCache {
@@ -464,6 +471,8 @@ typedef struct FilterCache {
/* Auto-masking. */
AutomaskingCache *automasking;
+ float initial_normal[3];
+ float view_normal[3];
/* Pre-smoothed colors used by sharpening. Colors are HSL. */
float (*pre_smoothed_color)[4];
@@ -636,6 +645,7 @@ typedef struct StrokeCache {
rcti previous_r; /* previous redraw rectangle */
rcti current_r; /* current redraw rectangle */
+ int stroke_id;
} StrokeCache;
/* -------------------------------------------------------------------- */
@@ -913,6 +923,8 @@ float SCULPT_vertex_mask_get(struct SculptSession *ss, PBVHVertRef vertex);
void SCULPT_vertex_color_get(const SculptSession *ss, PBVHVertRef vertex, float r_color[4]);
void SCULPT_vertex_color_set(SculptSession *ss, PBVHVertRef vertex, const float color[4]);
+bool SCULPT_vertex_is_occluded(SculptSession *ss, PBVHVertRef vertex, bool original);
+
/** Returns true if a color attribute exists in the current sculpt session. */
bool SCULPT_has_colors(const SculptSession *ss);
@@ -1004,9 +1016,13 @@ void SCULPT_connected_components_ensure(Object *ob);
void SCULPT_vertex_visible_set(SculptSession *ss, PBVHVertRef vertex, bool visible);
bool SCULPT_vertex_visible_get(SculptSession *ss, PBVHVertRef vertex);
+bool SCULPT_vertex_all_faces_visible_get(const SculptSession *ss, PBVHVertRef vertex);
+bool SCULPT_vertex_any_face_visible_get(SculptSession *ss, PBVHVertRef vertex);
+
+void SCULPT_face_visibility_all_invert(SculptSession *ss);
+void SCULPT_face_visibility_all_set(SculptSession *ss, bool visible);
-void SCULPT_visibility_sync_all_face_sets_to_verts(struct Object *ob);
-void SCULPT_visibility_sync_all_vertex_to_face_sets(struct SculptSession *ss);
+void SCULPT_visibility_sync_all_from_faces(struct Object *ob);
/** \} */
@@ -1024,11 +1040,6 @@ bool SCULPT_vertex_has_unique_face_set(SculptSession *ss, PBVHVertRef vertex);
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, PBVHVertRef vertex);
-bool SCULPT_vertex_any_face_set_visible_get(SculptSession *ss, PBVHVertRef vertex);
-
-void SCULPT_face_sets_visibility_invert(SculptSession *ss);
-void SCULPT_face_sets_visibility_all_set(SculptSession *ss, bool visible);
/** \} */
@@ -1195,7 +1206,8 @@ float SCULPT_brush_strength_factor(struct SculptSession *ss,
const float fno[3],
float mask,
const PBVHVertRef vertex,
- int thread_id);
+ int thread_id,
+ struct AutomaskingNodeData *automask_data);
/**
* Tilts a normal by the x and y tilt values using the view axis.
@@ -1274,7 +1286,6 @@ void sculpt_dynamic_topology_disable_with_undo(struct Main *bmain,
bool SCULPT_stroke_is_dynamic_topology(const SculptSession *ss, const Brush *brush);
void SCULPT_dynamic_topology_triangulate(struct BMesh *bm);
-void SCULPT_dyntopo_node_layers_add(struct SculptSession *ss);
enum eDynTopoWarnFlag SCULPT_dynamic_topology_check(Scene *scene, Object *ob);
@@ -1284,9 +1295,30 @@ enum eDynTopoWarnFlag SCULPT_dynamic_topology_check(Scene *scene, Object *ob);
/** \name Auto-masking.
* \{ */
+typedef struct AutomaskingNodeData {
+ PBVHNode *node;
+ SculptOrigVertData orig_data;
+ bool have_orig_data;
+} AutomaskingNodeData;
+
+/** Call before PBVH vertex iteration.
+ * \param automask_data: pointer to an uninitialized AutomaskingNodeData struct.
+ */
+void SCULPT_automasking_node_begin(struct Object *ob,
+ const SculptSession *ss,
+ struct AutomaskingCache *automasking,
+ AutomaskingNodeData *automask_data,
+ PBVHNode *node);
+
+/* Call before SCULPT_automasking_factor_get and SCULPT_brush_strength_factor. */
+void SCULPT_automasking_node_update(SculptSession *ss,
+ AutomaskingNodeData *automask_data,
+ PBVHVertexIter *vd);
+
float SCULPT_automasking_factor_get(struct AutomaskingCache *automasking,
SculptSession *ss,
- PBVHVertRef vertex);
+ PBVHVertRef vertex,
+ AutomaskingNodeData *automask_data);
/* Returns the automasking cache depending on the active tool. Used for code that can run both for
* brushes and filter. */
@@ -1302,6 +1334,12 @@ float *SCULPT_boundary_automasking_init(Object *ob,
eBoundaryAutomaskMode mode,
int propagation_steps,
float *automask_factor);
+bool SCULPT_automasking_needs_normal(const SculptSession *ss,
+ const Sculpt *sculpt,
+ const Brush *brush);
+bool SCULPT_automasking_needs_original(const struct Sculpt *sd, const struct Brush *brush);
+int SCULPT_automasking_settings_hash(Object *ob, AutomaskingCache *automasking);
+
/** \} */
/* -------------------------------------------------------------------- */
@@ -1315,7 +1353,7 @@ float *SCULPT_boundary_automasking_init(Object *ob,
* fallback to euclidean distances to one of the initial vertices in the set.
*/
float *SCULPT_geodesic_distances_create(struct Object *ob,
- struct GSet *initial_vertices,
+ struct GSet *initial_verts,
float limit_radius);
float *SCULPT_geodesic_from_vertex_and_symm(struct Sculpt *sd,
struct Object *ob,
@@ -1328,8 +1366,14 @@ float *SCULPT_geodesic_from_vertex(Object *ob, PBVHVertRef vertex, float limit_r
/** \name Filter API
* \{ */
-void SCULPT_filter_cache_init(struct bContext *C, Object *ob, Sculpt *sd, int undo_type);
+void SCULPT_filter_cache_init(struct bContext *C,
+ Object *ob,
+ Sculpt *sd,
+ int undo_type,
+ const int mval[2],
+ float area_normal_radius);
void SCULPT_filter_cache_free(SculptSession *ss);
+void SCULPT_mesh_filter_properties(struct wmOperatorType *ot);
void SCULPT_mask_filter_smooth_apply(
Sculpt *sd, Object *ob, PBVHNode **nodes, int totnode, int smooth_iterations);
@@ -1592,7 +1636,6 @@ void SCULPT_OT_color_filter(struct wmOperatorType *ot);
/* Mask filter and Dirty Mask. */
void SCULPT_OT_mask_filter(struct wmOperatorType *ot);
-void SCULPT_OT_dirty_mask(struct wmOperatorType *ot);
/* Mask and Face Sets Expand. */
@@ -1847,6 +1890,15 @@ BLI_INLINE bool SCULPT_tool_is_face_sets(int tool)
return ELEM(tool, SCULPT_TOOL_DRAW_FACE_SETS);
}
+void SCULPT_stroke_id_ensure(struct Object *ob);
+void SCULPT_stroke_id_next(struct Object *ob);
+bool SCULPT_tool_can_reuse_automask(int sculpt_tool);
+
#ifdef __cplusplus
}
#endif
+
+/* Make SCULPT_ alias to a few blenkernel sculpt methods. */
+
+#define SCULPT_vertex_attr_get BKE_sculpt_vertex_attr_get
+#define SCULPT_face_attr_get BKE_sculpt_face_attr_get
diff --git a/source/blender/editors/sculpt_paint/sculpt_mask_expand.c b/source/blender/editors/sculpt_paint/sculpt_mask_expand.c
index ec246cd3788..1b8cc5347ac 100644
--- a/source/blender/editors/sculpt_paint/sculpt_mask_expand.c
+++ b/source/blender/editors/sculpt_paint/sculpt_mask_expand.c
@@ -7,44 +7,30 @@
#include "MEM_guardedalloc.h"
-#include "BLI_blenlib.h"
#include "BLI_math.h"
#include "BLI_task.h"
#include "BLT_translation.h"
#include "DNA_brush_types.h"
-#include "DNA_mesh_types.h"
#include "DNA_meshdata_types.h"
+#include "DNA_modifier_types.h"
#include "DNA_object_types.h"
-#include "BKE_brush.h"
#include "BKE_ccg.h"
-#include "BKE_colortools.h"
#include "BKE_context.h"
-#include "BKE_mesh.h"
-#include "BKE_multires.h"
-#include "BKE_node.h"
-#include "BKE_object.h"
#include "BKE_paint.h"
#include "BKE_pbvh.h"
-#include "BKE_scene.h"
#include "DEG_depsgraph.h"
#include "WM_api.h"
-#include "WM_message.h"
-#include "WM_toolsystem.h"
#include "WM_types.h"
#include "RNA_access.h"
#include "RNA_define.h"
-#include "ED_object.h"
#include "ED_screen.h"
-#include "ED_sculpt.h"
-#include "ED_view3d.h"
-#include "paint_intern.h"
#include "sculpt_intern.h"
#include "bmesh.h"
@@ -346,6 +332,11 @@ static int sculpt_mask_expand_invoke(bContext *C, wmOperator *op, const wmEvent
SculptCursorGeometryInfo sgi;
const float mval_fl[2] = {UNPACK2(event->mval)};
+ MultiresModifierData *mmd = BKE_sculpt_multires_active(CTX_data_scene(C), ob);
+ BKE_sculpt_mask_layers_ensure(depsgraph, CTX_data_main(C), ob, mmd);
+
+ BKE_sculpt_update_object_for_edit(depsgraph, ob, true, true, false);
+
SCULPT_vertex_random_access_ensure(ss);
op->customdata = MEM_mallocN(sizeof(float[2]), "initial mouse position");
@@ -353,8 +344,6 @@ static int sculpt_mask_expand_invoke(bContext *C, wmOperator *op, const wmEvent
SCULPT_cursor_geometry_info_update(C, &sgi, mval_fl, false);
- BKE_sculpt_update_object_for_edit(depsgraph, ob, true, true, false);
-
int vertex_count = SCULPT_vertex_count_get(ss);
ss->filter_cache = MEM_callocN(sizeof(FilterCache), "filter cache");
diff --git a/source/blender/editors/sculpt_paint/sculpt_mask_init.c b/source/blender/editors/sculpt_paint/sculpt_mask_init.c
index b9b889ab2ce..99a7bb8a926 100644
--- a/source/blender/editors/sculpt_paint/sculpt_mask_init.c
+++ b/source/blender/editors/sculpt_paint/sculpt_mask_init.c
@@ -7,27 +7,20 @@
#include "MEM_guardedalloc.h"
-#include "BLI_blenlib.h"
#include "BLI_hash.h"
#include "BLI_math.h"
#include "BLI_task.h"
-#include "BLT_translation.h"
-
#include "PIL_time.h"
#include "DNA_brush_types.h"
-#include "DNA_mesh_types.h"
#include "DNA_meshdata_types.h"
+#include "DNA_modifier_types.h"
#include "DNA_object_types.h"
-#include "BKE_brush.h"
#include "BKE_ccg.h"
#include "BKE_context.h"
-#include "BKE_mesh.h"
#include "BKE_multires.h"
-#include "BKE_node.h"
-#include "BKE_object.h"
#include "BKE_paint.h"
#include "BKE_pbvh.h"
@@ -39,8 +32,6 @@
#include "RNA_access.h"
#include "RNA_define.h"
-#include "ED_sculpt.h"
-#include "paint_intern.h"
#include "sculpt_intern.h"
#include "bmesh.h"
@@ -120,6 +111,9 @@ static int sculpt_mask_init_exec(bContext *C, wmOperator *op)
const int mode = RNA_enum_get(op->ptr, "mode");
+ MultiresModifierData *mmd = BKE_sculpt_multires_active(CTX_data_scene(C), ob);
+ BKE_sculpt_mask_layers_ensure(depsgraph, CTX_data_main(C), ob, mmd);
+
BKE_sculpt_update_object_for_edit(depsgraph, ob, true, true, false);
PBVH *pbvh = ob->sculpt->pbvh;
diff --git a/source/blender/editors/sculpt_paint/sculpt_multiplane_scrape.c b/source/blender/editors/sculpt_paint/sculpt_multiplane_scrape.c
index 1e8731e54c0..fd8f5b8945c 100644
--- a/source/blender/editors/sculpt_paint/sculpt_multiplane_scrape.c
+++ b/source/blender/editors/sculpt_paint/sculpt_multiplane_scrape.c
@@ -5,36 +5,22 @@
* \ingroup edsculpt
*/
-#include "MEM_guardedalloc.h"
-
-#include "BLI_blenlib.h"
#include "BLI_math.h"
#include "BLI_task.h"
#include "DNA_brush_types.h"
-#include "DNA_mesh_types.h"
#include "DNA_meshdata_types.h"
#include "DNA_object_types.h"
-#include "BKE_brush.h"
#include "BKE_ccg.h"
-#include "BKE_colortools.h"
#include "BKE_context.h"
-#include "BKE_mesh.h"
-#include "BKE_multires.h"
-#include "BKE_node.h"
-#include "BKE_object.h"
#include "BKE_paint.h"
#include "BKE_pbvh.h"
-#include "BKE_scene.h"
-#include "paint_intern.h"
#include "sculpt_intern.h"
#include "GPU_immediate.h"
-#include "GPU_immediate_util.h"
#include "GPU_matrix.h"
-#include "GPU_state.h"
#include "bmesh.h"
@@ -69,6 +55,10 @@ static void calc_multiplane_scrape_surface_task_cb(void *__restrict userdata,
test_radius *= brush->normal_radius_factor;
test.radius_squared = test_radius * test_radius;
+ AutomaskingNodeData automask_data;
+ SCULPT_automasking_node_begin(
+ data->ob, ss, ss->cache->automasking, &automask_data, data->nodes[n]);
+
BKE_pbvh_vertex_iter_begin (ss->pbvh, data->nodes[n], vd, PBVH_ITER_UNIQUE) {
if (!sculpt_brush_test_sq_fn(&test, vd.co)) {
@@ -78,6 +68,9 @@ static void calc_multiplane_scrape_surface_task_cb(void *__restrict userdata,
float normal[3];
copy_v3_v3(normal, vd.no ? vd.no : vd.fno);
mul_v3_m4v3(local_co, mat, vd.co);
+
+ SCULPT_automasking_node_update(ss, &automask_data, &vd);
+
/* Use the brush falloff to weight the sampled normals. */
const float fade = SCULPT_brush_strength_factor(ss,
brush,
@@ -87,7 +80,8 @@ static void calc_multiplane_scrape_surface_task_cb(void *__restrict userdata,
vd.fno,
vd.mask ? *vd.mask : 0.0f,
vd.vertex,
- thread_id);
+ thread_id,
+ &automask_data);
/* Sample the normal and area of the +X and -X axis individually. */
if (local_co[0] > 0.0f) {
@@ -144,6 +138,10 @@ static void do_multiplane_scrape_brush_task_cb_ex(void *__restrict userdata,
ss, &test, data->brush->falloff_shape);
const int thread_id = BLI_task_parallel_thread_id(tls);
+ AutomaskingNodeData automask_data;
+ SCULPT_automasking_node_begin(
+ data->ob, ss, ss->cache->automasking, &automask_data, data->nodes[n]);
+
BKE_pbvh_vertex_iter_begin (ss->pbvh, data->nodes[n], vd, PBVH_ITER_UNIQUE) {
if (!sculpt_brush_test_sq_fn(&test, vd.co)) {
@@ -184,6 +182,9 @@ static void do_multiplane_scrape_brush_task_cb_ex(void *__restrict userdata,
if (!SCULPT_plane_trim(ss->cache, brush, val)) {
continue;
}
+
+ SCULPT_automasking_node_update(ss, &automask_data, &vd);
+
/* Deform the local space along the Y axis to avoid artifacts on curved strokes. */
/* This produces a not round brush tip. */
local_co[1] *= 2.0f;
@@ -195,7 +196,8 @@ static void do_multiplane_scrape_brush_task_cb_ex(void *__restrict userdata,
vd.fno,
vd.mask ? *vd.mask : 0.0f,
vd.vertex,
- thread_id);
+ thread_id,
+ &automask_data);
mul_v3_v3fl(proxy[vd.i], val, fade);
diff --git a/source/blender/editors/sculpt_paint/sculpt_ops.c b/source/blender/editors/sculpt_paint/sculpt_ops.c
index 055e02a5703..8affb0e9d53 100644
--- a/source/blender/editors/sculpt_paint/sculpt_ops.c
+++ b/source/blender/editors/sculpt_paint/sculpt_ops.c
@@ -8,33 +8,20 @@
#include "MEM_guardedalloc.h"
-#include "BLI_array.h"
-#include "BLI_blenlib.h"
-#include "BLI_dial_2d.h"
#include "BLI_ghash.h"
#include "BLI_gsqueue.h"
-#include "BLI_hash.h"
-#include "BLI_link_utils.h"
-#include "BLI_linklist.h"
-#include "BLI_linklist_stack.h"
-#include "BLI_listbase.h"
#include "BLI_math.h"
-#include "BLI_math_color_blend.h"
-#include "BLI_memarena.h"
-#include "BLI_rand.h"
#include "BLI_task.h"
#include "BLI_utildefines.h"
-#include "atomic_ops.h"
#include "BLT_translation.h"
-#include "PIL_time.h"
-
#include "DNA_brush_types.h"
#include "DNA_customdata_types.h"
#include "DNA_listBase.h"
#include "DNA_mesh_types.h"
#include "DNA_meshdata_types.h"
+#include "DNA_modifier_types.h"
#include "DNA_node_types.h"
#include "DNA_object_types.h"
#include "DNA_scene_types.h"
@@ -42,44 +29,23 @@
#include "BKE_attribute.h"
#include "BKE_brush.h"
#include "BKE_ccg.h"
-#include "BKE_colortools.h"
#include "BKE_context.h"
-#include "BKE_image.h"
-#include "BKE_kelvinlet.h"
-#include "BKE_key.h"
#include "BKE_layer.h"
-#include "BKE_lib_id.h"
#include "BKE_main.h"
#include "BKE_mesh.h"
-#include "BKE_mesh_fair.h"
-#include "BKE_mesh_mapping.h"
#include "BKE_mesh_mirror.h"
#include "BKE_modifier.h"
#include "BKE_multires.h"
-#include "BKE_node.h"
#include "BKE_object.h"
#include "BKE_paint.h"
-#include "BKE_particle.h"
#include "BKE_pbvh.h"
-#include "BKE_pointcache.h"
#include "BKE_report.h"
#include "BKE_scene.h"
-#include "BKE_screen.h"
-#include "BKE_subdiv_ccg.h"
-#include "BKE_subsurf.h"
#include "DEG_depsgraph.h"
-#include "DEG_depsgraph_query.h"
#include "IMB_colormanagement.h"
-#include "GPU_batch.h"
-#include "GPU_batch_presets.h"
-#include "GPU_immediate.h"
-#include "GPU_immediate_util.h"
-#include "GPU_matrix.h"
-#include "GPU_state.h"
-
#include "WM_api.h"
#include "WM_message.h"
#include "WM_toolsystem.h"
@@ -89,9 +55,6 @@
#include "ED_object.h"
#include "ED_screen.h"
#include "ED_sculpt.h"
-#include "ED_space_api.h"
-#include "ED_transform_snap_object_context.h"
-#include "ED_view3d.h"
#include "paint_intern.h"
#include "sculpt_intern.h"
@@ -103,7 +66,6 @@
#include "UI_resources.h"
#include "bmesh.h"
-#include "bmesh_tools.h"
#include <math.h>
#include <stdlib.h>
@@ -117,24 +79,33 @@ static int sculpt_set_persistent_base_exec(bContext *C, wmOperator *UNUSED(op))
Object *ob = CTX_data_active_object(C);
SculptSession *ss = ob->sculpt;
- if (!ss) {
+ /* Do not allow in DynTopo just yet. */
+ if (!ss || (ss && ss->bm)) {
return OPERATOR_FINISHED;
}
SCULPT_vertex_random_access_ensure(ss);
BKE_sculpt_update_object_for_edit(depsgraph, ob, false, false, false);
- MEM_SAFE_FREE(ss->persistent_base);
+ SculptAttributeParams params = {0};
+ params.permanent = true;
+
+ ss->attrs.persistent_co = BKE_sculpt_attribute_ensure(
+ ob, ATTR_DOMAIN_POINT, CD_PROP_FLOAT3, SCULPT_ATTRIBUTE_NAME(persistent_co), &params);
+ ss->attrs.persistent_no = BKE_sculpt_attribute_ensure(
+ ob, ATTR_DOMAIN_POINT, CD_PROP_FLOAT3, SCULPT_ATTRIBUTE_NAME(persistent_no), &params);
+ ss->attrs.persistent_disp = BKE_sculpt_attribute_ensure(
+ ob, ATTR_DOMAIN_POINT, CD_PROP_FLOAT, SCULPT_ATTRIBUTE_NAME(persistent_disp), &params);
const int totvert = SCULPT_vertex_count_get(ss);
- ss->persistent_base = MEM_mallocN(sizeof(SculptPersistentBase) * totvert,
- "layer persistent base");
for (int i = 0; i < totvert; i++) {
PBVHVertRef vertex = BKE_pbvh_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;
+ copy_v3_v3((float *)SCULPT_vertex_attr_get(vertex, ss->attrs.persistent_co),
+ SCULPT_vertex_co_get(ss, vertex));
+ SCULPT_vertex_normal_get(
+ ss, vertex, (float *)SCULPT_vertex_attr_get(vertex, ss->attrs.persistent_no));
+ (*(float *)SCULPT_vertex_attr_get(vertex, ss->attrs.persistent_disp)) = 0.0f;
}
return OPERATOR_FINISHED;
@@ -300,7 +271,11 @@ static void sculpt_init_session(Main *bmain, Depsgraph *depsgraph, Scene *scene,
ob->sculpt = MEM_callocN(sizeof(SculptSession), "sculpt session");
ob->sculpt->mode_type = OB_MODE_SCULPT;
- BKE_sculpt_ensure_orig_mesh_data(ob);
+ /* Trigger evaluation of modifier stack to ensure
+ * multires modifier sets .runtime.ccg in
+ * the evaluated mesh.
+ */
+ DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
BKE_scene_graph_evaluated_ensure(depsgraph, bmain);
@@ -348,7 +323,7 @@ void ED_object_sculptmode_enter_ex(Main *bmain,
BKE_report(
reports, RPT_WARNING, "Object has non-uniform scale, sculpting may be unpredictable");
}
- else if (is_negative_m4(ob->obmat)) {
+ else if (is_negative_m4(ob->object_to_world)) {
BKE_report(reports, RPT_WARNING, "Object has negative scale, sculpting may be unpredictable");
}
@@ -421,6 +396,7 @@ void ED_object_sculptmode_enter(struct bContext *C, Depsgraph *depsgraph, Report
Main *bmain = CTX_data_main(C);
Scene *scene = CTX_data_scene(C);
ViewLayer *view_layer = CTX_data_view_layer(C);
+ BKE_view_layer_synced_ensure(scene, view_layer);
Object *ob = BKE_view_layer_active_object_get(view_layer);
ED_object_sculptmode_enter_ex(bmain, depsgraph, scene, ob, false, reports);
}
@@ -473,6 +449,7 @@ void ED_object_sculptmode_exit(bContext *C, Depsgraph *depsgraph)
Main *bmain = CTX_data_main(C);
Scene *scene = CTX_data_scene(C);
ViewLayer *view_layer = CTX_data_view_layer(C);
+ BKE_view_layer_synced_ensure(scene, view_layer);
Object *ob = BKE_view_layer_active_object_get(view_layer);
ED_object_sculptmode_exit_ex(bmain, depsgraph, scene, ob);
}
@@ -485,6 +462,7 @@ static int sculpt_mode_toggle_exec(bContext *C, wmOperator *op)
Scene *scene = CTX_data_scene(C);
ToolSettings *ts = scene->toolsettings;
ViewLayer *view_layer = CTX_data_view_layer(C);
+ BKE_view_layer_synced_ensure(scene, view_layer);
Object *ob = BKE_view_layer_active_object_get(view_layer);
const int mode_flag = OB_MODE_SCULPT;
const bool is_mode_set = (ob->mode & mode_flag) != 0;
@@ -986,6 +964,368 @@ static void SCULPT_OT_mask_by_color(wmOperatorType *ot)
1.0f);
}
+typedef enum {
+ AUTOMASK_BAKE_MIX,
+ AUTOMASK_BAKE_MULTIPLY,
+ AUTOMASK_BAKE_DIVIDE,
+ AUTOMASK_BAKE_ADD,
+ AUTOMASK_BAKE_SUBTRACT,
+} CavityBakeMixMode;
+
+typedef struct AutomaskBakeTaskData {
+ SculptSession *ss;
+ AutomaskingCache *automasking;
+ PBVHNode **nodes;
+ CavityBakeMixMode mode;
+ float factor;
+ Object *ob;
+} AutomaskBakeTaskData;
+
+static void sculpt_bake_cavity_exec_task_cb(void *__restrict userdata,
+ const int n,
+ const TaskParallelTLS *__restrict UNUSED(tls))
+{
+ AutomaskBakeTaskData *tdata = userdata;
+ SculptSession *ss = tdata->ss;
+ PBVHNode *node = tdata->nodes[n];
+ PBVHVertexIter vd;
+ const CavityBakeMixMode mode = tdata->mode;
+ const float factor = tdata->factor;
+
+ SCULPT_undo_push_node(tdata->ob, node, SCULPT_UNDO_MASK);
+
+ AutomaskingNodeData automask_data;
+ SCULPT_automasking_node_begin(tdata->ob, ss, tdata->automasking, &automask_data, node);
+
+ BKE_pbvh_vertex_iter_begin (ss->pbvh, node, vd, PBVH_ITER_UNIQUE) {
+ SCULPT_automasking_node_update(ss, &automask_data, &vd);
+
+ float automask = SCULPT_automasking_factor_get(
+ tdata->automasking, ss, vd.vertex, &automask_data);
+ float mask;
+
+ switch (mode) {
+ case AUTOMASK_BAKE_MIX:
+ mask = automask;
+ break;
+ case AUTOMASK_BAKE_MULTIPLY:
+ mask = *vd.mask * automask;
+ break;
+ break;
+ case AUTOMASK_BAKE_DIVIDE:
+ mask = automask > 0.00001f ? *vd.mask / automask : 0.0f;
+ break;
+ break;
+ case AUTOMASK_BAKE_ADD:
+ mask = *vd.mask + automask;
+ break;
+ case AUTOMASK_BAKE_SUBTRACT:
+ mask = *vd.mask - automask;
+ break;
+ }
+
+ mask = *vd.mask + (mask - *vd.mask) * factor;
+ CLAMP(mask, 0.0f, 1.0f);
+
+ *vd.mask = mask;
+ }
+ BKE_pbvh_vertex_iter_end;
+
+ BKE_pbvh_node_mark_update_mask(node);
+}
+
+static int sculpt_bake_cavity_exec(bContext *C, wmOperator *op)
+{
+ Depsgraph *depsgraph = CTX_data_depsgraph_pointer(C);
+ Object *ob = CTX_data_active_object(C);
+ SculptSession *ss = ob->sculpt;
+ Sculpt *sd = CTX_data_tool_settings(C)->sculpt;
+ Brush *brush = BKE_paint_brush(&sd->paint);
+
+ MultiresModifierData *mmd = BKE_sculpt_multires_active(CTX_data_scene(C), ob);
+ BKE_sculpt_mask_layers_ensure(depsgraph, CTX_data_main(C), ob, mmd);
+
+ BKE_sculpt_update_object_for_edit(depsgraph, ob, true, true, false);
+ SCULPT_vertex_random_access_ensure(ss);
+
+ SCULPT_undo_push_begin(ob, op);
+
+ CavityBakeMixMode mode = RNA_enum_get(op->ptr, "mix_mode");
+ float factor = RNA_float_get(op->ptr, "mix_factor");
+
+ PBVHNode **nodes;
+ int totnode;
+
+ BKE_pbvh_search_gather(ss->pbvh, NULL, NULL, &nodes, &totnode);
+
+ AutomaskBakeTaskData tdata;
+
+ /* Set up automasking settings.
+ */
+ Sculpt sd2 = *sd;
+
+ /* Override cavity mask settings if use_automask_settings is false. */
+ if (!RNA_boolean_get(op->ptr, "use_automask_settings")) {
+ if (RNA_boolean_get(op->ptr, "invert")) {
+ sd2.automasking_flags = BRUSH_AUTOMASKING_CAVITY_INVERTED;
+ }
+ else {
+ sd2.automasking_flags = BRUSH_AUTOMASKING_CAVITY_NORMAL;
+ }
+
+ if (RNA_boolean_get(op->ptr, "use_curve")) {
+ sd2.automasking_flags |= BRUSH_AUTOMASKING_CAVITY_USE_CURVE;
+ }
+
+ sd2.automasking_cavity_blur_steps = RNA_int_get(op->ptr, "blur_steps");
+ sd2.automasking_cavity_factor = RNA_float_get(op->ptr, "factor");
+
+ sd2.automasking_cavity_curve = sd->automasking_cavity_curve_op;
+ }
+ else {
+ sd2.automasking_flags &= BRUSH_AUTOMASKING_CAVITY_ALL | BRUSH_AUTOMASKING_CAVITY_USE_CURVE;
+
+ /* Ensure cavity mask is actually enabled. */
+ if (!(sd2.automasking_flags & BRUSH_AUTOMASKING_CAVITY_ALL)) {
+ sd2.automasking_flags |= BRUSH_AUTOMASKING_CAVITY_NORMAL;
+ }
+ }
+
+ /* Create copy of brush with cleared automasking settings. */
+ Brush brush2 = *brush;
+ brush2.automasking_flags = 0;
+ brush2.automasking_boundary_edges_propagation_steps = 1;
+ brush2.automasking_cavity_curve = sd2.automasking_cavity_curve;
+
+ SCULPT_stroke_id_next(ob);
+
+ tdata.ob = ob;
+ tdata.mode = mode;
+ tdata.factor = factor;
+ tdata.ss = ss;
+ tdata.nodes = nodes;
+ tdata.automasking = SCULPT_automasking_cache_init(&sd2, &brush2, ob);
+
+ TaskParallelSettings settings;
+ BKE_pbvh_parallel_range_settings(&settings, true, totnode);
+ BLI_task_parallel_range(0, totnode, &tdata, sculpt_bake_cavity_exec_task_cb, &settings);
+
+ MEM_SAFE_FREE(nodes);
+ SCULPT_automasking_cache_free(tdata.automasking);
+
+ BKE_pbvh_update_vertex_data(ss->pbvh, PBVH_UpdateMask);
+ SCULPT_undo_push_end(ob);
+
+ SCULPT_flush_update_done(C, ob, SCULPT_UPDATE_MASK);
+ SCULPT_tag_update_overlays(C);
+
+ return OPERATOR_FINISHED;
+}
+
+static void cavity_bake_ui(bContext *C, wmOperator *op)
+{
+ uiLayout *layout = op->layout;
+ Scene *scene = CTX_data_scene(C);
+ Sculpt *sd = scene->toolsettings ? scene->toolsettings->sculpt : NULL;
+
+ uiLayoutSetPropSep(layout, true);
+ uiLayoutSetPropDecorate(layout, false);
+ bool use_curve = false;
+
+ if (!sd || !RNA_boolean_get(op->ptr, "use_automask_settings")) {
+ uiItemR(layout, op->ptr, "mix_mode", 0, NULL, ICON_NONE);
+ uiItemR(layout, op->ptr, "mix_factor", 0, NULL, ICON_NONE);
+ uiItemR(layout, op->ptr, "use_automask_settings", 0, NULL, ICON_NONE);
+ uiItemR(layout, op->ptr, "factor", 0, NULL, ICON_NONE);
+ uiItemR(layout, op->ptr, "blur_steps", 0, NULL, ICON_NONE);
+ uiItemR(layout, op->ptr, "invert", 0, NULL, ICON_NONE);
+ uiItemR(layout, op->ptr, "use_curve", 0, NULL, ICON_NONE);
+
+ use_curve = RNA_boolean_get(op->ptr, "use_curve");
+ }
+ else {
+ PointerRNA sculpt_ptr;
+
+ RNA_pointer_create(&scene->id, &RNA_Sculpt, sd, &sculpt_ptr);
+ uiItemR(layout, op->ptr, "mix_mode", 0, NULL, ICON_NONE);
+ uiItemR(layout, op->ptr, "mix_factor", 0, NULL, ICON_NONE);
+ uiItemR(layout, op->ptr, "use_automask_settings", 0, NULL, ICON_NONE);
+
+ use_curve = false;
+ }
+
+ if (use_curve) {
+ PointerRNA sculpt_ptr;
+
+ const char *curve_prop;
+
+ if (RNA_boolean_get(op->ptr, "use_automask_settings")) {
+ curve_prop = "automasking_cavity_curve";
+ }
+ else {
+ curve_prop = "automasking_cavity_curve_op";
+ }
+
+ if (scene->toolsettings && scene->toolsettings->sculpt) {
+ RNA_pointer_create(&scene->id, &RNA_Sculpt, scene->toolsettings->sculpt, &sculpt_ptr);
+ uiTemplateCurveMapping(layout, &sculpt_ptr, curve_prop, 'v', false, false, false, false);
+ }
+ }
+}
+
+static void SCULPT_OT_mask_from_cavity(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name = "Mask From Cavity";
+ ot->idname = "SCULPT_OT_mask_from_cavity";
+ ot->description = "Creates a mask based on the curvature of the surface";
+ ot->ui = cavity_bake_ui;
+
+ static EnumPropertyItem mix_modes[] = {
+ {AUTOMASK_BAKE_MIX, "MIX", ICON_NONE, "Mix", ""},
+ {AUTOMASK_BAKE_MULTIPLY, "MULTIPLY", ICON_NONE, "Multiply", ""},
+ {AUTOMASK_BAKE_DIVIDE, "DIVIDE", ICON_NONE, "Divide", ""},
+ {AUTOMASK_BAKE_ADD, "ADD", ICON_NONE, "Add", ""},
+ {AUTOMASK_BAKE_SUBTRACT, "SUBTRACT", ICON_NONE, "Subtract", ""},
+ {0, NULL, 0, NULL, NULL},
+ };
+
+ /* api callbacks */
+ ot->exec = sculpt_bake_cavity_exec;
+ ot->poll = SCULPT_mode_poll;
+
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+
+ RNA_def_enum(ot->srna, "mix_mode", mix_modes, AUTOMASK_BAKE_MIX, "Mode", "Mix mode");
+ RNA_def_float(ot->srna, "mix_factor", 1.0f, 0.0f, 5.0f, "Mix Factor", "", 0.0f, 1.0f);
+
+ RNA_def_boolean(ot->srna,
+ "use_automask_settings",
+ false,
+ "Use Automask Settings",
+ "Use default settings from Options panel in sculpt mode");
+
+ RNA_def_float(ot->srna,
+ "factor",
+ 0.5f,
+ 0.0f,
+ 5.0f,
+ "Cavity Factor",
+ "The contrast of the cavity mask",
+ 0.0f,
+ 1.0f);
+ RNA_def_int(ot->srna,
+ "blur_steps",
+ 2,
+ 0,
+ 25,
+ "Cavity Blur",
+ "The number of times the cavity mask is blurred",
+ 0,
+ 25);
+ RNA_def_boolean(ot->srna, "use_curve", false, "Use Curve", "");
+
+ RNA_def_boolean(ot->srna, "invert", false, "Cavity (Inverted)", "");
+}
+
+static int sculpt_reveal_all_exec(bContext *C, wmOperator *op)
+{
+ Object *ob = CTX_data_active_object(C);
+ SculptSession *ss = ob->sculpt;
+ Depsgraph *depsgraph = CTX_data_depsgraph_pointer(C);
+
+ Mesh *mesh = BKE_object_get_original_mesh(ob);
+
+ BKE_sculpt_update_object_for_edit(depsgraph, ob, true, true, false);
+
+ if (!ss->pbvh) {
+ return OPERATOR_CANCELLED;
+ }
+
+ PBVHNode **nodes;
+ int totnode;
+ bool with_bmesh = BKE_pbvh_type(ss->pbvh) == PBVH_BMESH;
+
+ BKE_pbvh_search_gather(ss->pbvh, NULL, NULL, &nodes, &totnode);
+
+ if (!totnode) {
+ return OPERATOR_CANCELLED;
+ }
+
+ /* Propagate face hide state to verts for undo. */
+ SCULPT_visibility_sync_all_from_faces(ob);
+
+ SCULPT_undo_push_begin(ob, op);
+
+ for (int i = 0; i < totnode; i++) {
+ BKE_pbvh_node_mark_update_visibility(nodes[i]);
+
+ if (!with_bmesh) {
+ SCULPT_undo_push_node(ob, nodes[i], SCULPT_UNDO_HIDDEN);
+ }
+ }
+
+ if (!with_bmesh) {
+ /* As an optimization, free the hide attribute when making all geometry visible. This allows
+ * reduced memory usage without manually clearing it later, and allows sculpt operations to
+ * avoid checking element's hide status. */
+ CustomData_free_layer_named(&mesh->pdata, ".hide_poly", mesh->totpoly);
+ ss->hide_poly = NULL;
+ }
+ else {
+ SCULPT_undo_push_node(ob, nodes[0], SCULPT_UNDO_HIDDEN);
+
+ BMIter iter;
+ BMFace *f;
+ BMVert *v;
+ const int cd_mask = CustomData_get_offset(&ss->bm->vdata, CD_PAINT_MASK);
+
+ BM_ITER_MESH (v, &iter, ss->bm, BM_VERTS_OF_MESH) {
+ BM_log_vert_before_modified(ss->bm_log, v, cd_mask);
+ }
+ BM_ITER_MESH (f, &iter, ss->bm, BM_FACES_OF_MESH) {
+ BM_log_face_modified(ss->bm_log, f);
+ }
+
+ SCULPT_face_visibility_all_set(ss, true);
+ }
+
+ SCULPT_visibility_sync_all_from_faces(ob);
+
+ /* NOTE: #SCULPT_visibility_sync_all_from_faces may have deleted
+ * `pbvh->hide_vert` if hide_poly did not exist, which is why
+ * we call #BKE_pbvh_update_hide_attributes_from_mesh here instead of
+ * after #CustomData_free_layer_named above. */
+ if (!with_bmesh) {
+ BKE_pbvh_update_hide_attributes_from_mesh(ss->pbvh);
+ }
+
+ BKE_pbvh_update_visibility(ss->pbvh);
+
+ SCULPT_undo_push_end(ob);
+ MEM_SAFE_FREE(nodes);
+
+ SCULPT_tag_update_overlays(C);
+ DEG_id_tag_update(&ob->id, ID_RECALC_SHADING);
+ ED_region_tag_redraw(CTX_wm_region(C));
+
+ return OPERATOR_FINISHED;
+}
+
+static void SCULPT_OT_reveal_all(wmOperatorType *ot)
+{
+ /* Identifiers. */
+ ot->name = "Reveal All";
+ ot->idname = "SCULPT_OT_reveal_all";
+ ot->description = "Unhide all geometry";
+
+ /* Api callbacks. */
+ ot->exec = sculpt_reveal_all_exec;
+ ot->poll = SCULPT_mode_poll;
+
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+}
+
void ED_operatortypes_sculpt(void)
{
WM_operatortype_append(SCULPT_OT_brush_stroke);
@@ -999,7 +1339,6 @@ void ED_operatortypes_sculpt(void)
WM_operatortype_append(SCULPT_OT_set_detail_size);
WM_operatortype_append(SCULPT_OT_mesh_filter);
WM_operatortype_append(SCULPT_OT_mask_filter);
- WM_operatortype_append(SCULPT_OT_dirty_mask);
WM_operatortype_append(SCULPT_OT_mask_expand);
WM_operatortype_append(SCULPT_OT_set_pivot_position);
WM_operatortype_append(SCULPT_OT_face_sets_create);
@@ -1021,4 +1360,6 @@ void ED_operatortypes_sculpt(void)
WM_operatortype_append(SCULPT_OT_mask_init);
WM_operatortype_append(SCULPT_OT_expand);
+ WM_operatortype_append(SCULPT_OT_mask_from_cavity);
+ WM_operatortype_append(SCULPT_OT_reveal_all);
}
diff --git a/source/blender/editors/sculpt_paint/sculpt_paint_color.c b/source/blender/editors/sculpt_paint/sculpt_paint_color.c
index c494c71f1eb..ee716d1107a 100644
--- a/source/blender/editors/sculpt_paint/sculpt_paint_color.c
+++ b/source/blender/editors/sculpt_paint/sculpt_paint_color.c
@@ -7,46 +7,24 @@
#include "MEM_guardedalloc.h"
-#include "BLI_blenlib.h"
#include "BLI_hash.h"
#include "BLI_math.h"
#include "BLI_math_color_blend.h"
#include "BLI_task.h"
-#include "DNA_mesh_types.h"
#include "DNA_meshdata_types.h"
#include "BKE_brush.h"
#include "BKE_colorband.h"
#include "BKE_colortools.h"
#include "BKE_context.h"
-#include "BKE_mesh.h"
-#include "BKE_mesh_mapping.h"
-#include "BKE_object.h"
#include "BKE_paint.h"
#include "BKE_pbvh.h"
-#include "BKE_scene.h"
-
-#include "DEG_depsgraph.h"
#include "IMB_colormanagement.h"
-#include "WM_api.h"
-#include "WM_message.h"
-#include "WM_toolsystem.h"
-#include "WM_types.h"
-
-#include "ED_object.h"
-#include "ED_screen.h"
-#include "ED_sculpt.h"
-#include "paint_intern.h"
#include "sculpt_intern.h"
-#include "RNA_access.h"
-#include "RNA_define.h"
-
-#include "UI_interface.h"
-
#include "IMB_imbuf.h"
#include "bmesh.h"
@@ -70,10 +48,17 @@ static void do_color_smooth_task_cb_exec(void *__restrict userdata,
ss, &test, data->brush->falloff_shape);
const int thread_id = BLI_task_parallel_thread_id(tls);
+ AutomaskingNodeData automask_data;
+ SCULPT_automasking_node_begin(
+ data->ob, ss, ss->cache->automasking, &automask_data, data->nodes[n]);
+
BKE_pbvh_vertex_iter_begin (ss->pbvh, data->nodes[n], vd, PBVH_ITER_UNIQUE) {
if (!sculpt_brush_test_sq_fn(&test, vd.co)) {
continue;
}
+
+ SCULPT_automasking_node_update(ss, &automask_data, &vd);
+
const float fade = bstrength * SCULPT_brush_strength_factor(ss,
brush,
vd.co,
@@ -82,7 +67,8 @@ static void do_color_smooth_task_cb_exec(void *__restrict userdata,
vd.fno,
vd.mask ? *vd.mask : 0.0f,
vd.vertex,
- thread_id);
+ thread_id,
+ &automask_data);
float smooth_color[4];
SCULPT_neighbor_color_average(ss, smooth_color, vd.vertex);
@@ -125,6 +111,10 @@ static void do_paint_brush_task_cb_ex(void *__restrict userdata,
IMB_colormanagement_srgb_to_scene_linear_v3(brush_color, brush_color);
+ AutomaskingNodeData automask_data;
+ SCULPT_automasking_node_begin(
+ data->ob, ss, ss->cache->automasking, &automask_data, data->nodes[n]);
+
if (brush->flag & BRUSH_USE_GRADIENT) {
switch (brush->gradient_stroke_mode) {
case BRUSH_GRADIENT_PRESSURE:
@@ -161,6 +151,8 @@ static void do_paint_brush_task_cb_ex(void *__restrict userdata,
continue;
}
+ SCULPT_automasking_node_update(ss, &automask_data, &vd);
+
float fade = bstrength * SCULPT_brush_strength_factor(ss,
brush,
vd.co,
@@ -169,7 +161,8 @@ static void do_paint_brush_task_cb_ex(void *__restrict userdata,
vd.fno,
vd.mask ? *vd.mask : 0.0f,
vd.vertex,
- thread_id);
+ thread_id,
+ &automask_data);
/* Density. */
float noise = 1.0f;
@@ -195,8 +188,11 @@ static void do_paint_brush_task_cb_ex(void *__restrict userdata,
paint_color, paint_color, wet_mix_color, ss->cache->paint_brush.wet_mix);
blend_color_mix_float(color_buffer->color[vd.i], color_buffer->color[vd.i], paint_color);
- /* Final mix over the original color using brush alpha. */
- mul_v4_v4fl(buffer_color, color_buffer->color[vd.i], brush->alpha);
+ /* Final mix over the original color using brush alpha. We apply auto-making again
+ * at this point to avoid washing out non-binary masking modes like cavity masking. */
+ float automasking = SCULPT_automasking_factor_get(
+ ss->cache->automasking, ss, vd.vertex, &automask_data);
+ mul_v4_v4fl(buffer_color, color_buffer->color[vd.i], brush->alpha * automasking);
float col[4];
SCULPT_vertex_color_get(ss, vd.vertex, col);
@@ -402,10 +398,17 @@ static void do_smear_brush_task_cb_exec(void *__restrict userdata,
sub_v3_v3v3(brush_delta, ss->cache->location, ss->cache->last_location);
}
+ AutomaskingNodeData automask_data;
+ SCULPT_automasking_node_begin(
+ data->ob, ss, ss->cache->automasking, &automask_data, data->nodes[n]);
+
BKE_pbvh_vertex_iter_begin (ss->pbvh, data->nodes[n], vd, PBVH_ITER_UNIQUE) {
if (!sculpt_brush_test_sq_fn(&test, vd.co)) {
continue;
}
+
+ SCULPT_automasking_node_update(ss, &automask_data, &vd);
+
const float fade = bstrength * SCULPT_brush_strength_factor(ss,
brush,
vd.co,
@@ -414,7 +417,8 @@ static void do_smear_brush_task_cb_exec(void *__restrict userdata,
vd.fno,
vd.mask ? *vd.mask : 0.0f,
vd.vertex,
- thread_id);
+ thread_id,
+ &automask_data);
float current_disp[3];
float current_disp_norm[3];
diff --git a/source/blender/editors/sculpt_paint/sculpt_paint_image.cc b/source/blender/editors/sculpt_paint/sculpt_paint_image.cc
index 8a3a3fe7adc..d3b3100458d 100644
--- a/source/blender/editors/sculpt_paint/sculpt_paint_image.cc
+++ b/source/blender/editors/sculpt_paint/sculpt_paint_image.cc
@@ -2,13 +2,9 @@
* Copyright 2022 Blender Foundation. All rights reserved. */
#include "DNA_image_types.h"
-#include "DNA_material_types.h"
-#include "DNA_mesh_types.h"
-#include "DNA_node_types.h"
#include "DNA_object_types.h"
#include "ED_paint.h"
-#include "ED_uvedit.h"
#include "BLI_math.h"
#include "BLI_math_color_blend.h"
@@ -19,14 +15,11 @@
#include "BKE_brush.h"
#include "BKE_image_wrappers.hh"
-#include "BKE_material.h"
#include "BKE_pbvh.h"
#include "BKE_pbvh_pixels.hh"
#include "bmesh.h"
-#include "NOD_shader.h"
-
#include "sculpt_intern.h"
namespace blender::ed::sculpt_paint::paint::image {
@@ -153,7 +146,10 @@ template<typename ImageBuffer> class PaintingKernel {
init_brush_test();
}
- bool paint(const Triangles &triangles, const PackedPixelRow &pixel_row, ImBuf *image_buffer)
+ bool paint(const Triangles &triangles,
+ const PackedPixelRow &pixel_row,
+ ImBuf *image_buffer,
+ AutomaskingNodeData *automask_data)
{
image_accessor.set_image_position(image_buffer, pixel_row.start_image_coordinate);
const TrianglePaintInput triangle = triangles.get_paint_input(pixel_row.triangle_index);
@@ -171,6 +167,7 @@ template<typename ImageBuffer> class PaintingKernel {
const float3 normal(0.0f, 0.0f, 0.0f);
const float3 face_normal(0.0f, 0.0f, 0.0f);
const float mask = 0.0f;
+
const float falloff_strength = SCULPT_brush_strength_factor(
ss,
brush,
@@ -180,7 +177,8 @@ template<typename ImageBuffer> class PaintingKernel {
face_normal,
mask,
BKE_pbvh_make_vref(PBVH_REF_NONE),
- thread_id);
+ thread_id,
+ automask_data);
float4 paint_color = brush_color * falloff_strength * brush_strength;
float4 buffer_color;
blend_color_mix_float(buffer_color, color, paint_color);
@@ -321,6 +319,9 @@ static void do_paint_pixels(void *__restrict userdata,
PaintingKernel<ImageBufferFloat4> kernel_float4(ss, brush, thread_id, mvert);
PaintingKernel<ImageBufferByte4> kernel_byte4(ss, brush, thread_id, mvert);
+ AutomaskingNodeData automask_data;
+ SCULPT_automasking_node_begin(ob, ss, ss->cache->automasking, &automask_data, data->nodes[n]);
+
ImageUser image_user = *data->image_data.image_user;
bool pixels_updated = false;
for (UDIMTilePixels &tile_data : node_data.tiles) {
@@ -347,10 +348,12 @@ static void do_paint_pixels(void *__restrict userdata,
}
bool pixels_painted = false;
if (image_buffer->rect_float != nullptr) {
- pixels_painted = kernel_float4.paint(node_data.triangles, pixel_row, image_buffer);
+ pixels_painted = kernel_float4.paint(
+ node_data.triangles, pixel_row, image_buffer, &automask_data);
}
else {
- pixels_painted = kernel_byte4.paint(node_data.triangles, pixel_row, image_buffer);
+ pixels_painted = kernel_byte4.paint(
+ node_data.triangles, pixel_row, image_buffer, &automask_data);
}
if (pixels_painted) {
@@ -421,7 +424,7 @@ static void push_undo(const NodeData &node_data,
static void do_push_undo_tile(void *__restrict userdata,
const int n,
- const TaskParallelTLS *__restrict UNUSED(tls))
+ const TaskParallelTLS *__restrict /*tls*/)
{
TexturePaintingUserData *data = static_cast<TexturePaintingUserData *>(userdata);
PBVHNode *node = data->nodes[n];
@@ -450,7 +453,7 @@ static void do_push_undo_tile(void *__restrict userdata,
static void do_mark_dirty_regions(void *__restrict userdata,
const int n,
- const TaskParallelTLS *__restrict UNUSED(tls))
+ const TaskParallelTLS *__restrict /*tls*/)
{
TexturePaintingUserData *data = static_cast<TexturePaintingUserData *>(userdata);
PBVHNode *node = data->nodes[n];
diff --git a/source/blender/editors/sculpt_paint/sculpt_pose.c b/source/blender/editors/sculpt_paint/sculpt_pose.c
index d1418c8dc35..5f671c1f0e1 100644
--- a/source/blender/editors/sculpt_paint/sculpt_pose.c
+++ b/source/blender/editors/sculpt_paint/sculpt_pose.c
@@ -7,12 +7,10 @@
#include "MEM_guardedalloc.h"
-#include "BLI_blenlib.h"
#include "BLI_math.h"
#include "BLI_task.h"
#include "DNA_brush_types.h"
-#include "DNA_mesh_types.h"
#include "DNA_meshdata_types.h"
#include "DNA_object_types.h"
@@ -20,13 +18,8 @@
#include "BKE_ccg.h"
#include "BKE_colortools.h"
#include "BKE_context.h"
-#include "BKE_mesh.h"
-#include "BKE_multires.h"
-#include "BKE_node.h"
-#include "BKE_object.h"
#include "BKE_paint.h"
#include "BKE_pbvh.h"
-#include "BKE_scene.h"
#include "paint_intern.h"
#include "sculpt_intern.h"
@@ -157,9 +150,13 @@ static void do_pose_brush_task_cb_ex(void *__restrict userdata,
SculptOrigVertData orig_data;
SCULPT_orig_vert_data_init(&orig_data, data->ob, data->nodes[n], SCULPT_UNDO_COORDS);
+ AutomaskingNodeData automask_data;
+ SCULPT_automasking_node_begin(
+ data->ob, ss, ss->cache->automasking, &automask_data, data->nodes[n]);
BKE_pbvh_vertex_iter_begin (ss->pbvh, data->nodes[n], vd, PBVH_ITER_UNIQUE) {
SCULPT_orig_vert_data_update(&orig_data, &vd);
+ SCULPT_automasking_node_update(ss, &automask_data, &vd);
float total_disp[3];
zero_v3(total_disp);
@@ -182,7 +179,8 @@ static void do_pose_brush_task_cb_ex(void *__restrict userdata,
/* Apply the vertex mask to the displacement. */
const float mask = vd.mask ? 1.0f - *vd.mask : 1.0f;
- const float automask = SCULPT_automasking_factor_get(ss->cache->automasking, ss, vd.vertex);
+ const float automask = SCULPT_automasking_factor_get(
+ ss->cache->automasking, ss, vd.vertex, &automask_data);
mul_v3_fl(disp, mask * automask);
/* Accumulate the displacement. */
diff --git a/source/blender/editors/sculpt_paint/sculpt_smooth.c b/source/blender/editors/sculpt_paint/sculpt_smooth.c
index 2ef3c28ba0c..09b1c69da45 100644
--- a/source/blender/editors/sculpt_paint/sculpt_smooth.c
+++ b/source/blender/editors/sculpt_paint/sculpt_smooth.c
@@ -7,40 +7,18 @@
#include "MEM_guardedalloc.h"
-#include "BLI_blenlib.h"
-#include "BLI_hash.h"
#include "BLI_math.h"
#include "BLI_task.h"
#include "DNA_brush_types.h"
-#include "DNA_mesh_types.h"
#include "DNA_meshdata_types.h"
-#include "BKE_brush.h"
#include "BKE_context.h"
-#include "BKE_mesh.h"
-#include "BKE_mesh_mapping.h"
-#include "BKE_object.h"
#include "BKE_paint.h"
#include "BKE_pbvh.h"
-#include "BKE_scene.h"
-#include "DEG_depsgraph.h"
-
-#include "WM_api.h"
-#include "WM_message.h"
-#include "WM_toolsystem.h"
-#include "WM_types.h"
-
-#include "ED_object.h"
-#include "ED_screen.h"
-#include "ED_sculpt.h"
-#include "paint_intern.h"
#include "sculpt_intern.h"
-#include "RNA_access.h"
-#include "RNA_define.h"
-
#include "bmesh.h"
#include <math.h>
@@ -217,11 +195,17 @@ static void do_enhance_details_brush_task_cb_ex(void *__restrict userdata,
ss, &test, data->brush->falloff_shape);
const int thread_id = BLI_task_parallel_thread_id(tls);
+ AutomaskingNodeData automask_data;
+ SCULPT_automasking_node_begin(
+ data->ob, ss, ss->cache->automasking, &automask_data, data->nodes[n]);
+
BKE_pbvh_vertex_iter_begin (ss->pbvh, data->nodes[n], vd, PBVH_ITER_UNIQUE) {
if (!sculpt_brush_test_sq_fn(&test, vd.co)) {
continue;
}
+ SCULPT_automasking_node_update(ss, &automask_data, &vd);
+
const float fade = bstrength * SCULPT_brush_strength_factor(ss,
brush,
vd.co,
@@ -230,7 +214,8 @@ static void do_enhance_details_brush_task_cb_ex(void *__restrict userdata,
vd.fno,
vd.mask ? *vd.mask : 0.0f,
vd.vertex,
- thread_id);
+ thread_id,
+ &automask_data);
float disp[3];
madd_v3_v3v3fl(disp, vd.co, ss->cache->detail_directions[vd.index], fade);
@@ -300,11 +285,17 @@ static void do_smooth_brush_task_cb_ex(void *__restrict userdata,
ss, &test, data->brush->falloff_shape);
const int thread_id = BLI_task_parallel_thread_id(tls);
+ AutomaskingNodeData automask_data;
+ SCULPT_automasking_node_begin(
+ data->ob, ss, ss->cache->automasking, &automask_data, data->nodes[n]);
BKE_pbvh_vertex_iter_begin (ss->pbvh, data->nodes[n], vd, PBVH_ITER_UNIQUE) {
if (!sculpt_brush_test_sq_fn(&test, vd.co)) {
continue;
}
+
+ SCULPT_automasking_node_update(ss, &automask_data, &vd);
+
const float fade = bstrength * SCULPT_brush_strength_factor(
ss,
brush,
@@ -314,7 +305,8 @@ static void do_smooth_brush_task_cb_ex(void *__restrict userdata,
vd.fno,
smooth_mask ? 0.0f : (vd.mask ? *vd.mask : 0.0f),
vd.vertex,
- thread_id);
+ thread_id,
+ &automask_data);
if (smooth_mask) {
float val = SCULPT_neighbor_mask_average(ss, vd.vertex) - *vd.mask;
val *= fade * bstrength;
@@ -470,12 +462,18 @@ static void SCULPT_do_surface_smooth_brush_laplacian_task_cb_ex(
const int thread_id = BLI_task_parallel_thread_id(tls);
SCULPT_orig_vert_data_init(&orig_data, data->ob, data->nodes[n], SCULPT_UNDO_COORDS);
+ AutomaskingNodeData automask_data;
+ SCULPT_automasking_node_begin(
+ data->ob, ss, ss->cache->automasking, &automask_data, data->nodes[n]);
BKE_pbvh_vertex_iter_begin (ss->pbvh, data->nodes[n], vd, PBVH_ITER_UNIQUE) {
SCULPT_orig_vert_data_update(&orig_data, &vd);
if (!sculpt_brush_test_sq_fn(&test, vd.co)) {
continue;
}
+
+ SCULPT_automasking_node_update(ss, &automask_data, &vd);
+
const float fade = bstrength * SCULPT_brush_strength_factor(ss,
brush,
vd.co,
@@ -484,7 +482,8 @@ static void SCULPT_do_surface_smooth_brush_laplacian_task_cb_ex(
vd.fno,
vd.mask ? *vd.mask : 0.0f,
vd.vertex,
- thread_id);
+ thread_id,
+ &automask_data);
float disp[3];
SCULPT_surface_smooth_laplacian_step(
@@ -512,11 +511,17 @@ static void SCULPT_do_surface_smooth_brush_displace_task_cb_ex(
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);
+ AutomaskingNodeData automask_data;
+ SCULPT_automasking_node_begin(
+ data->ob, ss, ss->cache->automasking, &automask_data, data->nodes[n]);
BKE_pbvh_vertex_iter_begin (ss->pbvh, data->nodes[n], vd, PBVH_ITER_UNIQUE) {
if (!sculpt_brush_test_sq_fn(&test, vd.co)) {
continue;
}
+
+ SCULPT_automasking_node_update(ss, &automask_data, &vd);
+
const float fade = bstrength * SCULPT_brush_strength_factor(ss,
brush,
vd.co,
@@ -525,7 +530,8 @@ static void SCULPT_do_surface_smooth_brush_displace_task_cb_ex(
vd.fno,
vd.mask ? *vd.mask : 0.0f,
vd.vertex,
- thread_id);
+ thread_id,
+ &automask_data);
SCULPT_surface_smooth_displace_step(
ss, vd.co, ss->cache->surface_smooth_laplacian_disp, vd.vertex, beta, fade);
}
diff --git a/source/blender/editors/sculpt_paint/sculpt_transform.c b/source/blender/editors/sculpt_paint/sculpt_transform.c
index dfaa0bd4daa..0463e8adbaf 100644
--- a/source/blender/editors/sculpt_paint/sculpt_transform.c
+++ b/source/blender/editors/sculpt_paint/sculpt_transform.c
@@ -7,31 +7,22 @@
#include "MEM_guardedalloc.h"
-#include "BLI_blenlib.h"
#include "BLI_math.h"
#include "BLI_task.h"
-#include "DNA_mesh_types.h"
#include "DNA_meshdata_types.h"
#include "BKE_brush.h"
#include "BKE_context.h"
#include "BKE_kelvinlet.h"
-#include "BKE_mesh.h"
-#include "BKE_mesh_mapping.h"
-#include "BKE_object.h"
#include "BKE_paint.h"
#include "BKE_pbvh.h"
-#include "BKE_scene.h"
#include "DEG_depsgraph.h"
#include "WM_api.h"
-#include "WM_message.h"
-#include "WM_toolsystem.h"
#include "WM_types.h"
-#include "ED_object.h"
#include "ED_screen.h"
#include "ED_sculpt.h"
#include "ED_view3d.h"
@@ -46,7 +37,10 @@
#include <math.h>
#include <stdlib.h>
-void ED_sculpt_init_transform(struct bContext *C, Object *ob, const char *undo_name)
+void ED_sculpt_init_transform(struct bContext *C,
+ Object *ob,
+ const int mval[2],
+ const char *undo_name)
{
Sculpt *sd = CTX_data_tool_settings(C)->sculpt;
SculptSession *ss = ob->sculpt;
@@ -66,7 +60,8 @@ void ED_sculpt_init_transform(struct bContext *C, Object *ob, const char *undo_n
ss->pivot_rot[3] = 1.0f;
SCULPT_vertex_random_access_ensure(ss);
- SCULPT_filter_cache_init(C, ob, sd, SCULPT_UNDO_COORDS);
+
+ SCULPT_filter_cache_init(C, ob, sd, SCULPT_UNDO_COORDS, mval, 5.0);
if (sd->transform_mode == SCULPT_TRANSFORM_MODE_RADIUS_ELASTIC) {
ss->filter_cache->transform_displacement_mode = SCULPT_TRANSFORM_DISPLACEMENT_INCREMENTAL;
diff --git a/source/blender/editors/sculpt_paint/sculpt_undo.c b/source/blender/editors/sculpt_paint/sculpt_undo.c
index af94cad88f3..eb92c865f18 100644
--- a/source/blender/editors/sculpt_paint/sculpt_undo.c
+++ b/source/blender/editors/sculpt_paint/sculpt_undo.c
@@ -56,7 +56,6 @@
#include "BKE_layer.h"
#include "BKE_main.h"
#include "BKE_mesh.h"
-#include "BKE_mesh_mapping.h"
#include "BKE_mesh_runtime.h"
#include "BKE_multires.h"
#include "BKE_object.h"
@@ -82,6 +81,9 @@
#include "bmesh.h"
#include "sculpt_intern.h"
+/* Uncomment to print the undo stack in the console on push/undo/redo. */
+//#define SCULPT_UNDO_DEBUG
+
/* Implementation of undo system for objects in sculpt mode.
*
* Each undo step in sculpt mode consists of list of nodes, each node contains:
@@ -148,11 +150,130 @@ typedef struct SculptUndoStep {
SculptAttrRef active_color_end;
bContext *C;
+
+#ifdef SCULPT_UNDO_DEBUG
+ int id;
+#endif
} SculptUndoStep;
static UndoSculpt *sculpt_undo_get_nodes(void);
static bool sculpt_attribute_ref_equals(SculptAttrRef *a, SculptAttrRef *b);
static void sculpt_save_active_attribute(Object *ob, SculptAttrRef *attr);
+static UndoSculpt *sculpt_undosys_step_get_nodes(UndoStep *us_p);
+
+#ifdef SCULPT_UNDO_DEBUG
+# 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;
+
+static void print_sculpt_node(Object *ob, SculptUndoNode *node)
+{
+ printf(" %s:%s {applied=%d}\n", undo_type_to_str(node->type), node->idname, node->applied);
+
+ if (node->bm_entry) {
+ BM_log_print_entry(ob->sculpt ? ob->sculpt->bm : NULL, node->bm_entry);
+ }
+}
+
+static void print_sculpt_undo_step(Object *ob, UndoStep *us, UndoStep *active, int i)
+{
+ SculptUndoNode *node;
+
+ if (us->type != BKE_UNDOSYS_TYPE_SCULPT) {
+ printf("%d %s (non-sculpt): '%s', type:%s, use_memfile_step:%s\n",
+ i,
+ us == active ? "->" : " ",
+ us->name,
+ us->type->name,
+ us->use_memfile_step ? "true" : "false");
+ return;
+ }
+
+ int id = -1;
+
+ SculptUndoStep *su = (SculptUndoStep *)us;
+ if (!su->id) {
+ su->id = nodeidgen++;
+ }
+
+ id = su->id;
+
+ printf("id=%d %s %d %s (use_memfile_step=%s)\n",
+ id,
+ us == active ? "->" : " ",
+ i,
+ us->name,
+ us->use_memfile_step ? "true" : "false");
+
+ if (us->type == BKE_UNDOSYS_TYPE_SCULPT) {
+ UndoSculpt *usculpt = sculpt_undosys_step_get_nodes(us);
+
+ for (node = usculpt->nodes.first; node; node = node->next) {
+ print_sculpt_node(ob, node);
+ }
+ }
+}
+void sculpt_undo_print_nodes(Object *ob, void *active)
+{
+
+ printf("=================== Sculpt undo steps ==============\n");
+
+ UndoStack *ustack = ED_undo_stack_get();
+ UndoStep *us = ustack->steps.first;
+ if (active == NULL) {
+ active = ustack->step_active;
+ }
+
+ if (!us) {
+ return;
+ }
+
+ printf("\n");
+ if (ustack->step_init) {
+ printf("===Undo initialization stepB===\n");
+ print_sculpt_undo_step(ob, ustack->step_init, active, -1);
+ printf("===============\n");
+ }
+
+ int i = 0, act_i = -1;
+ for (; us; us = us->next, i++) {
+ if (active == us) {
+ act_i = i;
+ }
+
+ print_sculpt_undo_step(ob, us, active, i);
+ }
+
+ if (ustack->step_active) {
+ printf("\n\n==Active step:==\n");
+ print_sculpt_undo_step(ob, ustack->step_active, active, act_i);
+ }
+}
+#else
+# define sculpt_undo_print_nodes(ob, active) while (0)
+#endif
static void update_cb(PBVHNode *node, void *rebuild)
{
@@ -253,7 +374,9 @@ static bool sculpt_undo_restore_deformed(
static bool sculpt_undo_restore_coords(bContext *C, Depsgraph *depsgraph, SculptUndoNode *unode)
{
+ const Scene *scene = CTX_data_scene(C);
ViewLayer *view_layer = CTX_data_view_layer(C);
+ BKE_view_layer_synced_ensure(scene, view_layer);
Object *ob = BKE_view_layer_active_object_get(view_layer);
SculptSession *ss = ob->sculpt;
SubdivCCG *subdiv_ccg = ss->subdiv_ccg;
@@ -365,7 +488,9 @@ static bool sculpt_undo_restore_coords(bContext *C, Depsgraph *depsgraph, Sculpt
static bool sculpt_undo_restore_hidden(bContext *C, SculptUndoNode *unode, bool *modified_vertices)
{
+ const Scene *scene = CTX_data_scene(C);
ViewLayer *view_layer = CTX_data_view_layer(C);
+ BKE_view_layer_synced_ensure(scene, view_layer);
Object *ob = BKE_view_layer_active_object_get(view_layer);
SculptSession *ss = ob->sculpt;
SubdivCCG *subdiv_ccg = ss->subdiv_ccg;
@@ -395,7 +520,9 @@ static bool sculpt_undo_restore_hidden(bContext *C, SculptUndoNode *unode, bool
static bool sculpt_undo_restore_color(bContext *C, SculptUndoNode *unode, bool *modified_vertices)
{
+ const Scene *scene = CTX_data_scene(C);
ViewLayer *view_layer = CTX_data_view_layer(C);
+ BKE_view_layer_synced_ensure(scene, view_layer);
Object *ob = BKE_view_layer_active_object_get(view_layer);
SculptSession *ss = ob->sculpt;
@@ -427,7 +554,9 @@ static bool sculpt_undo_restore_color(bContext *C, SculptUndoNode *unode, bool *
static bool sculpt_undo_restore_mask(bContext *C, SculptUndoNode *unode, bool *modified_vertices)
{
+ const Scene *scene = CTX_data_scene(C);
ViewLayer *view_layer = CTX_data_view_layer(C);
+ BKE_view_layer_synced_ensure(scene, view_layer);
Object *ob = BKE_view_layer_active_object_get(view_layer);
SculptSession *ss = ob->sculpt;
SubdivCCG *subdiv_ccg = ss->subdiv_ccg;
@@ -473,11 +602,18 @@ static bool sculpt_undo_restore_mask(bContext *C, SculptUndoNode *unode, bool *m
static bool sculpt_undo_restore_face_sets(bContext *C, SculptUndoNode *unode)
{
+ const Scene *scene = CTX_data_scene(C);
ViewLayer *view_layer = CTX_data_view_layer(C);
+ BKE_view_layer_synced_ensure(scene, view_layer);
Object *ob = BKE_view_layer_active_object_get(view_layer);
Mesh *me = BKE_object_get_original_mesh(ob);
- int *face_sets = CustomData_add_layer(
- &me->pdata, CD_SCULPT_FACE_SETS, CD_CONSTRUCT, NULL, me->totpoly);
+
+ int *face_sets = CustomData_get_layer_named(&me->pdata, CD_PROP_INT32, ".sculpt_face_set");
+ if (!face_sets) {
+ face_sets = CustomData_add_layer_named(
+ &me->pdata, CD_PROP_INT32, CD_CONSTRUCT, NULL, me->totpoly, ".sculpt_face_set");
+ }
+
for (int i = 0; i < me->totpoly; i++) {
SWAP(int, face_sets[i], unode->face_sets[i]);
}
@@ -537,7 +673,7 @@ static void sculpt_undo_bmesh_enable(Object *ob, SculptUndoNode *unode)
.use_toolflags = false,
}));
BM_data_layer_add(ss->bm, &ss->bm->vdata, CD_PAINT_MASK);
- SCULPT_dyntopo_node_layers_add(ss);
+
me->flag |= ME_SCULPT_DYNAMIC_TOPOLOGY;
/* Restore the BMLog using saved entries. */
@@ -721,7 +857,8 @@ static void sculpt_undo_restore_list(bContext *C, Depsgraph *depsgraph, ListBase
{
Scene *scene = CTX_data_scene(C);
ViewLayer *view_layer = CTX_data_view_layer(C);
- View3D *v3d = CTX_wm_view3d(C);
+ RegionView3D *rv3d = CTX_wm_region_view3d(C);
+ BKE_view_layer_synced_ensure(scene, view_layer);
Object *ob = BKE_view_layer_active_object_get(view_layer);
SculptSession *ss = ob->sculpt;
SubdivCCG *subdiv_ccg = ss->subdiv_ccg;
@@ -729,8 +866,13 @@ static void sculpt_undo_restore_list(bContext *C, Depsgraph *depsgraph, ListBase
bool update = false, rebuild = false, update_mask = false, update_visibility = false;
bool need_mask = false;
bool need_refine_subdiv = false;
+ bool clear_automask_cache = false;
for (unode = lb->first; unode; unode = unode->next) {
+ if (!ELEM(unode->type, SCULPT_UNDO_COLOR, SCULPT_UNDO_MASK)) {
+ clear_automask_cache = true;
+ }
+
/* Restore pivot. */
copy_v3_v3(ss->pivot_pos, unode->pivot_pos);
copy_v3_v3(ss->pivot_rot, unode->pivot_rot);
@@ -744,6 +886,10 @@ static void sculpt_undo_restore_list(bContext *C, Depsgraph *depsgraph, ListBase
}
}
+ if (clear_automask_cache) {
+ ss->last_automasking_settings_hash = 0;
+ }
+
DEG_id_tag_update(&ob->id, ID_RECALC_SHADING);
if (lb->first) {
@@ -756,7 +902,7 @@ static void sculpt_undo_restore_list(bContext *C, Depsgraph *depsgraph, ListBase
BKE_sculpt_update_object_for_edit(depsgraph, ob, true, need_mask, false);
- SCULPT_visibility_sync_all_face_sets_to_verts(ob);
+ SCULPT_visibility_sync_all_from_faces(ob);
BKE_pbvh_update_vertex_data(ss->pbvh, PBVH_UpdateVisibility);
@@ -765,7 +911,7 @@ static void sculpt_undo_restore_list(bContext *C, Depsgraph *depsgraph, ListBase
}
DEG_id_tag_update(&ob->id, ID_RECALC_SHADING);
- if (!BKE_sculptsession_use_pbvh_draw(ob, v3d)) {
+ if (!BKE_sculptsession_use_pbvh_draw(ob, rv3d)) {
DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
}
@@ -912,7 +1058,6 @@ static void sculpt_undo_restore_list(bContext *C, Depsgraph *depsgraph, ListBase
}
if (update_visibility) {
- SCULPT_visibility_sync_all_vertex_to_face_sets(ss);
BKE_pbvh_update_visibility(ss->pbvh);
}
@@ -925,7 +1070,7 @@ static void sculpt_undo_restore_list(bContext *C, Depsgraph *depsgraph, ListBase
}
}
- tag_update |= ID_REAL_USERS(ob->data) > 1 || !BKE_sculptsession_use_pbvh_draw(ob, v3d) ||
+ tag_update |= ID_REAL_USERS(ob->data) > 1 || !BKE_sculptsession_use_pbvh_draw(ob, rv3d) ||
ss->shapekey_active || ss->deform_modifiers_active;
if (tag_update) {
@@ -1354,7 +1499,7 @@ static SculptUndoNode *sculpt_undo_face_sets_push(Object *ob, SculptUndoType typ
unode->face_sets = MEM_callocN(me->totpoly * sizeof(int), "sculpt face sets");
- const int *face_sets = CustomData_get_layer(&me->pdata, CD_SCULPT_FACE_SETS);
+ const int *face_sets = CustomData_get_layer_named(&me->pdata, CD_PROP_INT32, ".sculpt_face_set");
if (face_sets) {
for (int i = 0; i < me->totpoly; i++) {
unode->face_sets[i] = face_sets[i];
@@ -1645,6 +1790,7 @@ void SCULPT_undo_push_end_ex(struct Object *ob, const bool use_nested_undo)
ustack, BKE_UNDOSYS_TYPE_SCULPT);
sculpt_save_active_attribute(ob, &us->active_color_end);
+ sculpt_undo_print_nodes(ob, NULL);
}
/* -------------------------------------------------------------------- */
@@ -1744,6 +1890,8 @@ static void sculpt_undosys_step_decode_undo_impl(struct bContext *C,
sculpt_undo_restore_list(C, depsgraph, &us->data.nodes);
us->step.is_applied = false;
+
+ sculpt_undo_print_nodes(CTX_data_active_object(C), NULL);
}
static void sculpt_undosys_step_decode_redo_impl(struct bContext *C,
@@ -1754,6 +1902,8 @@ static void sculpt_undosys_step_decode_redo_impl(struct bContext *C,
sculpt_undo_restore_list(C, depsgraph, &us->data.nodes);
us->step.is_applied = true;
+
+ sculpt_undo_print_nodes(CTX_data_active_object(C), NULL);
}
static void sculpt_undosys_step_decode_undo(struct bContext *C,
@@ -1823,6 +1973,7 @@ static void sculpt_undosys_step_decode(
{
Scene *scene = CTX_data_scene(C);
ViewLayer *view_layer = CTX_data_view_layer(C);
+ BKE_view_layer_synced_ensure(scene, view_layer);
Object *ob = BKE_view_layer_active_object_get(view_layer);
if (ob && (ob->type == OB_MESH)) {
if (ob->mode & (OB_MODE_SCULPT | OB_MODE_VERTEX_PAINT)) {