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:
-rw-r--r--release/scripts/startup/bl_ui/properties_paint_common.py2
-rw-r--r--source/blender/blenkernel/BKE_paint.h5
-rw-r--r--source/blender/editors/sculpt_paint/paint_cursor.c2
-rw-r--r--source/blender/editors/sculpt_paint/sculpt_boundary.c77
-rw-r--r--source/blender/editors/sculpt_paint/sculpt_intern.h1
-rw-r--r--source/blender/makesdna/DNA_brush_types.h9
-rw-r--r--source/blender/makesrna/intern/rna_brush.c39
7 files changed, 127 insertions, 8 deletions
diff --git a/release/scripts/startup/bl_ui/properties_paint_common.py b/release/scripts/startup/bl_ui/properties_paint_common.py
index 397ce5d0324..6a541863aef 100644
--- a/release/scripts/startup/bl_ui/properties_paint_common.py
+++ b/release/scripts/startup/bl_ui/properties_paint_common.py
@@ -722,6 +722,8 @@ def brush_settings(layout, context, brush, popover=False):
elif sculpt_tool == 'BOUNDARY':
col = layout.column()
col.prop(brush, "boundary_deform_type")
+ col.prop(brush, "boundary_falloff_type")
+ col.prop(brush, "boundary_offset")
elif sculpt_tool == 'TOPOLOGY':
col = layout.column()
diff --git a/source/blender/blenkernel/BKE_paint.h b/source/blender/blenkernel/BKE_paint.h
index 58687858a9e..7b63a4154fa 100644
--- a/source/blender/blenkernel/BKE_paint.h
+++ b/source/blender/blenkernel/BKE_paint.h
@@ -337,6 +337,11 @@ typedef struct SculptBoundary {
int vertices_capacity;
int num_vertices;
+ /* Distance from a vertex in the boundary to initial vertex indexed by vertex index, taking into
+ * account the lengh of all edges between them. Any vertex that is not in the boundary will have
+ * a distance of 0. */
+ float *distance;
+
/* Data for drawing the preview. */
SculptBoundaryPreviewEdge *edges;
int edges_capacity;
diff --git a/source/blender/editors/sculpt_paint/paint_cursor.c b/source/blender/editors/sculpt_paint/paint_cursor.c
index 88998d5063d..d4379262666 100644
--- a/source/blender/editors/sculpt_paint/paint_cursor.c
+++ b/source/blender/editors/sculpt_paint/paint_cursor.c
@@ -1542,7 +1542,7 @@ static void paint_cursor_preview_boundary_data_update(PaintCursorContext *pconte
}
ss->boundary_preview = SCULPT_boundary_data_init(
- pcontext->vc.obact, ss->active_vertex_index, pcontext->radius);
+ pcontext->vc.obact, pcontext->brush, ss->active_vertex_index, pcontext->radius);
}
static void paint_cursor_draw_3d_view_brush_cursor_inactive(PaintCursorContext *pcontext)
diff --git a/source/blender/editors/sculpt_paint/sculpt_boundary.c b/source/blender/editors/sculpt_paint/sculpt_boundary.c
index c86e922a347..5bedee6f3e2 100644
--- a/source/blender/editors/sculpt_paint/sculpt_boundary.c
+++ b/source/blender/editors/sculpt_paint/sculpt_boundary.c
@@ -132,10 +132,14 @@ static int BOUNDARY_INDICES_BLOCK_SIZE = 300;
static void sculpt_boundary_index_add(SculptBoundary *bdata,
const int new_index,
+ const float distance,
GSet *included_vertices)
{
bdata->vertices[bdata->num_vertices] = new_index;
+ if (bdata->distance) {
+ bdata->distance[new_index] = distance;
+ }
if (included_vertices) {
BLI_gset_add(included_vertices, POINTER_FROM_INT(new_index));
}
@@ -213,7 +217,11 @@ static bool boundary_floodfill_cb(
BoundaryFloodFillData *data = userdata;
SculptBoundary *bdata = data->bdata;
if (SCULPT_vertex_is_boundary(ss, to_v)) {
- sculpt_boundary_index_add(bdata, to_v, data->included_vertices);
+ const float edge_len = len_v3v3(SCULPT_vertex_co_get(ss, from_v),
+ SCULPT_vertex_co_get(ss, to_v));
+ const float distance_boundary_to_dst = bdata->distance ? bdata->distance[from_v] + edge_len :
+ 0.0f;
+ sculpt_boundary_index_add(bdata, to_v, distance_boundary_to_dst, data->included_vertices);
if (!is_duplicate) {
sculpt_boundary_preview_edge_add(bdata, from_v, to_v);
}
@@ -224,11 +232,16 @@ static bool boundary_floodfill_cb(
static void sculpt_boundary_indices_init(SculptSession *ss,
SculptBoundary *bdata,
+ const bool init_boundary_distances,
const int initial_boundary_index)
{
+ const int totvert = SCULPT_vertex_count_get(ss);
bdata->vertices = MEM_malloc_arrayN(
BOUNDARY_INDICES_BLOCK_SIZE, sizeof(int), "boundary indices");
+ if (init_boundary_distances) {
+ bdata->distance = MEM_calloc_arrayN(totvert, sizeof(float), "boundary distances");
+ }
bdata->edges = MEM_malloc_arrayN(
BOUNDARY_INDICES_BLOCK_SIZE, sizeof(SculptBoundaryPreviewEdge), "boundary edges");
@@ -238,7 +251,7 @@ static void sculpt_boundary_indices_init(SculptSession *ss,
bdata->initial_vertex = initial_boundary_index;
copy_v3_v3(bdata->initial_vertex_position, SCULPT_vertex_co_get(ss, bdata->initial_vertex));
- sculpt_boundary_index_add(bdata, initial_boundary_index, included_vertices);
+ sculpt_boundary_index_add(bdata, initial_boundary_index, 0.0f, included_vertices);
SCULPT_floodfill_add_initial(&flood, initial_boundary_index);
BoundaryFloodFillData fdata = {
@@ -407,7 +420,8 @@ static void sculpt_boundary_edit_data_init(SculptSession *ss,
*/
static void sculpt_boundary_falloff_factor_init(SculptSession *ss,
SculptBoundary *bdata,
- Brush *brush)
+ Brush *brush,
+ const float radius)
{
const int totvert = SCULPT_vertex_count_get(ss);
BKE_curvemapping_init(brush->curve);
@@ -417,12 +431,55 @@ static void sculpt_boundary_falloff_factor_init(SculptSession *ss,
bdata->edit_info[i].strength_factor = BKE_brush_curve_strength(
brush, bdata->edit_info[i].num_propagation_steps, bdata->max_propagation_steps);
}
+
+ if (bdata->edit_info[i].original_vertex == bdata->initial_vertex) {
+ /* All vertices that are propagated from the original vertex won't be affected by the
+ * boundary falloff, so there is no need to calculate anything else. */
+ continue;
+ }
+
+ if (!bdata->distance) {
+ /* There are falloff modes that do not require to modify the previously calculated falloff
+ * based on boundary distances. */
+ continue;
+ }
+
+ const float boundary_distance = bdata->distance[bdata->edit_info[i].original_vertex];
+ float falloff_distance = 0.0f;
+ float direction = 1.0f;
+
+ switch (brush->boundary_falloff_type) {
+ case BRUSH_BOUNDARY_FALLOFF_RADIUS:
+ falloff_distance = boundary_distance;
+ break;
+ case BRUSH_BOUNDARY_FALLOFF_LOOP: {
+ const int div = boundary_distance / radius;
+ const float mod = fmodf(boundary_distance, radius);
+ falloff_distance = div % 2 == 0 ? mod : radius - mod;
+ } break;
+ case BRUSH_BOUNDARY_FALLOFF_LOOP_INVERT: {
+ const int div = boundary_distance / radius;
+ const float mod = fmodf(boundary_distance, radius);
+ falloff_distance = div % 2 == 0 ? mod : radius - mod;
+ /* Inverts the faloff in the intervals 1 2 5 6 9 10 ... */
+ if (((div - 1) & 2) == 0) {
+ direction = -1.0f;
+ }
+ } break;
+ case BRUSH_BOUNDARY_FALLOFF_CONSTANT:
+ /* For constant falloff distances are not allocated, so this should never happen. */
+ BLI_assert(false);
+ }
+
+ bdata->edit_info[i].strength_factor *= direction * BKE_brush_curve_strength(
+ brush, falloff_distance, radius);
}
}
/* Main function to get SculptBoundary data both for brush deformation and viewport preview. Can
* return NULL if there is no boundary from the given vertex using the given radius. */
SculptBoundary *SCULPT_boundary_data_init(Object *object,
+ Brush *brush,
const int initial_vertex,
const float radius)
{
@@ -446,8 +503,12 @@ SculptBoundary *SCULPT_boundary_data_init(Object *object,
SculptBoundary *bdata = MEM_callocN(sizeof(SculptBoundary), "Boundary edit data");
- sculpt_boundary_indices_init(ss, bdata, boundary_initial_vertex);
- sculpt_boundary_edit_data_init(ss, bdata, boundary_initial_vertex, radius);
+ const bool init_boundary_distances = brush->boundary_falloff_type !=
+ BRUSH_BOUNDARY_FALLOFF_CONSTANT;
+ sculpt_boundary_indices_init(ss, bdata, init_boundary_distances, boundary_initial_vertex);
+
+ const float boundary_radius = radius * (1.0f + brush->boundary_offset);
+ sculpt_boundary_edit_data_init(ss, bdata, boundary_initial_vertex, boundary_radius);
return bdata;
}
@@ -455,6 +516,7 @@ SculptBoundary *SCULPT_boundary_data_init(Object *object,
void SCULPT_boundary_data_free(SculptBoundary *bdata)
{
MEM_SAFE_FREE(bdata->vertices);
+ MEM_SAFE_FREE(bdata->distance);
MEM_SAFE_FREE(bdata->edit_info);
MEM_SAFE_FREE(bdata->bend.pivot_positions);
MEM_SAFE_FREE(bdata->bend.pivot_rotation_axis);
@@ -775,7 +837,7 @@ void SCULPT_do_boundary_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totn
}
ss->cache->bdata[symm_area] = SCULPT_boundary_data_init(
- ob, initial_vertex, ss->cache->initial_radius);
+ ob, brush, initial_vertex, ss->cache->initial_radius);
if (ss->cache->bdata[symm_area]) {
@@ -795,7 +857,8 @@ void SCULPT_do_boundary_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totn
break;
}
- sculpt_boundary_falloff_factor_init(ss, ss->cache->bdata[symm_area], brush);
+ sculpt_boundary_falloff_factor_init(
+ ss, ss->cache->bdata[symm_area], brush, ss->cache->initial_radius);
}
}
diff --git a/source/blender/editors/sculpt_paint/sculpt_intern.h b/source/blender/editors/sculpt_paint/sculpt_intern.h
index b11a7005fb5..22316eb4631 100644
--- a/source/blender/editors/sculpt_paint/sculpt_intern.h
+++ b/source/blender/editors/sculpt_paint/sculpt_intern.h
@@ -398,6 +398,7 @@ void SCULPT_pose_ik_chain_free(struct SculptPoseIKChain *ik_chain);
/* Boundary Brush. */
struct SculptBoundary *SCULPT_boundary_data_init(Object *object,
+ Brush *brush,
const int initial_vertex,
const float radius);
void SCULPT_boundary_data_free(struct SculptBoundary *bdata);
diff --git a/source/blender/makesdna/DNA_brush_types.h b/source/blender/makesdna/DNA_brush_types.h
index 5d8eddaf5e1..6c4d2856526 100644
--- a/source/blender/makesdna/DNA_brush_types.h
+++ b/source/blender/makesdna/DNA_brush_types.h
@@ -387,6 +387,13 @@ typedef enum eBrushBoundaryDeformType {
BRUSH_BOUNDARY_DEFORM_TWIST = 4,
} eBrushBushBoundaryDeformType;
+typedef enum eBrushBoundaryFalloffType {
+ BRUSH_BOUNDARY_FALLOFF_CONSTANT = 0,
+ BRUSH_BOUNDARY_FALLOFF_RADIUS = 1,
+ BRUSH_BOUNDARY_FALLOFF_LOOP = 2,
+ BRUSH_BOUNDARY_FALLOFF_LOOP_INVERT = 3,
+} eBrushBoundaryFalloffType;
+
/* Gpencilsettings.Vertex_mode */
typedef enum eGp_Vertex_Mode {
/* Affect to Stroke only. */
@@ -596,6 +603,8 @@ typedef struct Brush {
/* boundary */
int boundary_deform_type;
+ int boundary_falloff_type;
+ float boundary_offset;
/* cloth */
int cloth_deform_type;
diff --git a/source/blender/makesrna/intern/rna_brush.c b/source/blender/makesrna/intern/rna_brush.c
index 38916e2a45a..a3fa4fed575 100644
--- a/source/blender/makesrna/intern/rna_brush.c
+++ b/source/blender/makesrna/intern/rna_brush.c
@@ -1997,6 +1997,31 @@ static void rna_def_brush(BlenderRNA *brna)
{0, NULL, 0, NULL, NULL},
};
+ static const EnumPropertyItem brush_boundary_falloff_type_items[] = {
+ {BRUSH_BOUNDARY_FALLOFF_CONSTANT,
+ "CONSTANT",
+ 0,
+ "Constant",
+ "Applies the same deformation in the entire boundary"},
+ {BRUSH_BOUNDARY_FALLOFF_RADIUS,
+ "RADIUS",
+ 0,
+ "Brush Radius",
+ "Applies the deformation in a localiced area limited by the brush radius"},
+ {BRUSH_BOUNDARY_FALLOFF_LOOP,
+ "LOOP",
+ 0,
+ "Loop",
+ "Applies the brush falloff in a loop pattern"},
+ {BRUSH_BOUNDARY_FALLOFF_LOOP_INVERT,
+ "LOOP_INVERT",
+ 0,
+ "Loop and Invert",
+ "Applies the fallof radius in a loop pattern, inverting the displacement direction in each "
+ "pattern repetition"},
+ {0, NULL, 0, NULL, NULL},
+ };
+
static const EnumPropertyItem brush_cloth_simulation_area_type_items[] = {
{BRUSH_CLOTH_SIMULATION_AREA_LOCAL,
"LOCAL",
@@ -2194,6 +2219,12 @@ static void rna_def_brush(BlenderRNA *brna)
"Part of the mesh that is going to be simulated when the stroke is active");
RNA_def_property_update(prop, 0, "rna_Brush_update");
+ prop = RNA_def_property(srna, "boundary_falloff_type", PROP_ENUM, PROP_NONE);
+ RNA_def_property_enum_items(prop, brush_boundary_falloff_type_items);
+ RNA_def_property_ui_text(
+ prop, "Boundary Falloff", "How the brush falloff is applied across the boundary");
+ RNA_def_property_update(prop, 0, "rna_Brush_update");
+
prop = RNA_def_property(srna, "smooth_deform_type", PROP_ENUM, PROP_NONE);
RNA_def_property_enum_items(prop, brush_smooth_deform_type_items);
RNA_def_property_ui_text(prop, "Deformation", "Deformation type that is used in the brush");
@@ -2545,6 +2576,14 @@ static void rna_def_brush(BlenderRNA *brna)
"Maximum distance to search for disconnected loose parts in the mesh");
RNA_def_property_update(prop, 0, "rna_Brush_update");
+ prop = RNA_def_property(srna, "boundary_offset", PROP_FLOAT, PROP_FACTOR);
+ RNA_def_property_float_sdna(prop, NULL, "boundary_offset");
+ RNA_def_property_range(prop, 0.0f, 30.0f);
+ RNA_def_property_ui_text(prop,
+ "Boundary Origin Offset",
+ "Offset of the boundary origin in relation to the brush radius");
+ RNA_def_property_update(prop, 0, "rna_Brush_update");
+
prop = RNA_def_property(srna, "surface_smooth_shape_preservation", PROP_FLOAT, PROP_FACTOR);
RNA_def_property_float_sdna(prop, NULL, "surface_smooth_shape_preservation");
RNA_def_property_range(prop, 0.0f, 1.0f);