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
path: root/source
diff options
context:
space:
mode:
authorPablo Dobarro <pablodp606@gmail.com>2020-08-11 17:33:35 +0300
committerPablo Dobarro <pablodp606@gmail.com>2020-08-13 00:06:42 +0300
commitc77bf952210a4947f151b3f6cb657584d788a548 (patch)
treea096173874507e35e7ee7f8397925b6b0ff70bed /source
parentdb7cfd03b08cbe5a2c986cfebfa4a04d8aa8a40d (diff)
Sculpt: Boundary Brush Falloff Types and Offset
This adds the boundary_falloff_type and boundary_offset to control how the falloff of the Boundary Brush is applied. Boundary Origin Offset is the same concept as the Pose Origin offset in the Pose Brush. It is a multiplier that adds extra length to the brush radius to locate the deformation pivot further from the boundary without affecting the falloff. The Falloff type includes Constant (previous default), brush radius, loop and loop and invert. Loop and Loop and Invert can be used to create deformation patterns in a mesh. Reviewed By: sergey Differential Revision: https://developer.blender.org/D8526
Diffstat (limited to 'source')
-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
6 files changed, 125 insertions, 8 deletions
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);