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:
Diffstat (limited to 'source')
-rw-r--r--source/blender/editors/sculpt_paint/sculpt.c32
-rw-r--r--source/blender/editors/sculpt_paint/sculpt_boundary.c24
-rw-r--r--source/blender/editors/sculpt_paint/sculpt_cloth.c31
-rw-r--r--source/blender/editors/sculpt_paint/sculpt_intern.h15
-rw-r--r--source/blender/editors/sculpt_paint/sculpt_pose.c5
-rw-r--r--source/blender/makesdna/DNA_brush_types.h9
-rw-r--r--source/blender/makesrna/intern/rna_brush.c20
7 files changed, 114 insertions, 22 deletions
diff --git a/source/blender/editors/sculpt_paint/sculpt.c b/source/blender/editors/sculpt_paint/sculpt.c
index 5d09109c506..e1c1b8ee5fb 100644
--- a/source/blender/editors/sculpt_paint/sculpt.c
+++ b/source/blender/editors/sculpt_paint/sculpt.c
@@ -275,6 +275,19 @@ void SCULPT_active_vertex_normal_get(SculptSession *ss, float normal[3])
SCULPT_vertex_normal_get(ss, SCULPT_active_vertex_get(ss), normal);
}
+float *SCULPT_brush_deform_target_vertex_co_get(SculptSession *ss,
+ const int deform_target,
+ PBVHVertexIter *iter)
+{
+ switch (deform_target) {
+ case BRUSH_DEFORM_TARGET_GEOMETRY:
+ return iter->co;
+ case BRUSH_DEFORM_TARGET_CLOTH_SIM:
+ return ss->cache->cloth_sim->deformation_pos[iter->index];
+ }
+ return iter->co;
+}
+
/* Sculpt Face Sets and Visibility. */
int SCULPT_active_face_set_get(SculptSession *ss)
@@ -5690,6 +5703,16 @@ static void do_brush_action(Sculpt *sd, Object *ob, Brush *brush, UnifiedPaintSe
SCULPT_pose_brush_init(sd, ob, ss, brush);
}
+ if (brush->deform_target == BRUSH_DEFORM_TARGET_CLOTH_SIM) {
+ if (!ss->cache->cloth_sim) {
+ ss->cache->cloth_sim = SCULPT_cloth_brush_simulation_create(ss, brush, 1.0f, 0.0f, false);
+ SCULPT_cloth_brush_simulation_init(ss, ss->cache->cloth_sim);
+ SCULPT_cloth_brush_build_nodes_constraints(
+ sd, ob, nodes, totnode, ss->cache->cloth_sim, ss->cache->location, FLT_MAX);
+ }
+ SCULPT_cloth_brush_store_simulation_state(ss, ss->cache->cloth_sim);
+ }
+
bool invert = ss->cache->pen_flip || ss->cache->invert || brush->flag & BRUSH_DIR_IN;
/* Apply one type of brush action. */
@@ -5828,6 +5851,12 @@ static void do_brush_action(Sculpt *sd, Object *ob, Brush *brush, UnifiedPaintSe
do_gravity(sd, ob, nodes, totnode, sd->gravity_factor);
}
+ if (brush->deform_target == BRUSH_DEFORM_TARGET_CLOTH_SIM) {
+ if (SCULPT_stroke_is_main_symmetry_pass(ss->cache)) {
+ SCULPT_cloth_brush_do_simulation_step(sd, ob, ss->cache->cloth_sim, nodes, totnode);
+ }
+ }
+
MEM_SAFE_FREE(nodes);
/* Update average stroke position. */
@@ -7308,7 +7337,8 @@ static void sculpt_brush_stroke_init(bContext *C, wmOperator *op)
need_mask = true;
}
- if (brush->sculpt_tool == SCULPT_TOOL_CLOTH) {
+ if (brush->sculpt_tool == SCULPT_TOOL_CLOTH ||
+ brush->deform_target == BRUSH_DEFORM_TARGET_CLOTH_SIM) {
need_mask = true;
}
diff --git a/source/blender/editors/sculpt_paint/sculpt_boundary.c b/source/blender/editors/sculpt_paint/sculpt_boundary.c
index a188d6a678c..5e01e034715 100644
--- a/source/blender/editors/sculpt_paint/sculpt_boundary.c
+++ b/source/blender/editors/sculpt_paint/sculpt_boundary.c
@@ -633,6 +633,7 @@ static void do_boundary_brush_bend_task_cb_ex(void *__restrict userdata,
const int symm_area = ss->cache->mirror_symmetry_pass;
SculptBoundary *boundary = ss->cache->boundaries[symm_area];
const ePaintSymmetryFlags symm = data->sd->paint.symmetry_flags & PAINT_SYMM_AXIS_ALL;
+ const Brush *brush = data->brush;
const float strength = ss->cache->bstrength;
@@ -657,12 +658,13 @@ static void do_boundary_brush_bend_task_cb_ex(void *__restrict userdata,
orig_data.co, boundary->initial_vertex_position, symm)) {
const float mask = vd.mask ? 1.0f - *vd.mask : 1.0f;
float t_orig_co[3];
+ 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]);
- rotate_v3_v3v3fl(vd.co,
+ rotate_v3_v3v3fl(target_co,
t_orig_co,
boundary->bend.pivot_rotation_axis[vd.index],
angle * boundary->edit_info[vd.index].strength_factor * mask);
- add_v3_v3(vd.co, boundary->bend.pivot_positions[vd.index]);
+ add_v3_v3(target_co, boundary->bend.pivot_positions[vd.index]);
}
}
@@ -682,6 +684,7 @@ static void do_boundary_brush_slide_task_cb_ex(void *__restrict userdata,
const int symm_area = ss->cache->mirror_symmetry_pass;
SculptBoundary *boundary = ss->cache->boundaries[symm_area];
const ePaintSymmetryFlags symm = data->sd->paint.symmetry_flags & PAINT_SYMM_AXIS_ALL;
+ const Brush *brush = data->brush;
const float strength = ss->cache->bstrength;
@@ -699,7 +702,8 @@ static void do_boundary_brush_slide_task_cb_ex(void *__restrict userdata,
if (SCULPT_check_vertex_pivot_symmetry(
orig_data.co, boundary->initial_vertex_position, symm)) {
const float mask = vd.mask ? 1.0f - *vd.mask : 1.0f;
- madd_v3_v3v3fl(vd.co,
+ float *target_co = SCULPT_brush_deform_target_vertex_co_get(ss, brush->deform_target, &vd);
+ madd_v3_v3v3fl(target_co,
orig_data.co,
boundary->slide.directions[vd.index],
boundary->edit_info[vd.index].strength_factor * disp * mask * strength);
@@ -722,6 +726,7 @@ static void do_boundary_brush_inflate_task_cb_ex(void *__restrict userdata,
const int symm_area = ss->cache->mirror_symmetry_pass;
SculptBoundary *boundary = ss->cache->boundaries[symm_area];
const ePaintSymmetryFlags symm = data->sd->paint.symmetry_flags & PAINT_SYMM_AXIS_ALL;
+ const Brush *brush = data->brush;
const float strength = ss->cache->bstrength;
@@ -741,7 +746,8 @@ static void do_boundary_brush_inflate_task_cb_ex(void *__restrict userdata,
const float mask = vd.mask ? 1.0f - *vd.mask : 1.0f;
float normal[3];
normal_short_to_float_v3(normal, orig_data.no);
- madd_v3_v3v3fl(vd.co,
+ float *target_co = SCULPT_brush_deform_target_vertex_co_get(ss, brush->deform_target, &vd);
+ madd_v3_v3v3fl(target_co,
orig_data.co,
normal,
boundary->edit_info[vd.index].strength_factor * disp * mask * strength);
@@ -764,6 +770,7 @@ static void do_boundary_brush_grab_task_cb_ex(void *__restrict userdata,
const int symm_area = ss->cache->mirror_symmetry_pass;
SculptBoundary *boundary = ss->cache->boundaries[symm_area];
const ePaintSymmetryFlags symm = data->sd->paint.symmetry_flags & PAINT_SYMM_AXIS_ALL;
+ const Brush *brush = data->brush;
const float strength = ss->cache->bstrength;
@@ -779,7 +786,8 @@ static void do_boundary_brush_grab_task_cb_ex(void *__restrict userdata,
if (SCULPT_check_vertex_pivot_symmetry(
orig_data.co, boundary->initial_vertex_position, symm)) {
const float mask = vd.mask ? 1.0f - *vd.mask : 1.0f;
- madd_v3_v3v3fl(vd.co,
+ float *target_co = SCULPT_brush_deform_target_vertex_co_get(ss, brush->deform_target, &vd);
+ madd_v3_v3v3fl(target_co,
orig_data.co,
ss->cache->grab_delta_symmetry,
boundary->edit_info[vd.index].strength_factor * mask * strength);
@@ -802,6 +810,7 @@ static void do_boundary_brush_twist_task_cb_ex(void *__restrict userdata,
const int symm_area = ss->cache->mirror_symmetry_pass;
SculptBoundary *boundary = ss->cache->boundaries[symm_area];
const ePaintSymmetryFlags symm = data->sd->paint.symmetry_flags & PAINT_SYMM_AXIS_ALL;
+ const Brush *brush = data->brush;
const float strength = ss->cache->bstrength;
@@ -826,12 +835,13 @@ static void do_boundary_brush_twist_task_cb_ex(void *__restrict userdata,
orig_data.co, boundary->initial_vertex_position, symm)) {
const float mask = vd.mask ? 1.0f - *vd.mask : 1.0f;
float t_orig_co[3];
+ 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);
- rotate_v3_v3v3fl(vd.co,
+ rotate_v3_v3v3fl(target_co,
t_orig_co,
boundary->twist.rotation_axis,
angle * mask * boundary->edit_info[vd.index].strength_factor);
- add_v3_v3(vd.co, boundary->twist.pivot_position);
+ add_v3_v3(target_co, boundary->twist.pivot_position);
}
}
diff --git a/source/blender/editors/sculpt_paint/sculpt_cloth.c b/source/blender/editors/sculpt_paint/sculpt_cloth.c
index acfa04022cb..ea94398ee5d 100644
--- a/source/blender/editors/sculpt_paint/sculpt_cloth.c
+++ b/source/blender/editors/sculpt_paint/sculpt_cloth.c
@@ -134,6 +134,7 @@ static float cloth_brush_simulation_falloff_get(const Brush *brush,
#define CLOTH_SIMULATION_ITERATIONS 5
#define CLOTH_MAX_CONSTRAINTS_PER_VERTEX 1024
#define CLOTH_SIMULATION_TIME_STEP 0.01f
+#define CLOTH_DEFORMATION_TARGET_STRENGTH 0.35f
static bool cloth_brush_sim_has_length_constraint(SculptClothSimulation *cloth_sim,
const int v1,
@@ -297,9 +298,22 @@ static void do_cloth_brush_build_constraints_task_cb_ex(
}
}
- if (cloth_is_deform_brush && len_squared < radius_squared) {
- const float fade = BKE_brush_curve_strength(brush, sqrtf(len_squared), ss->cache->radius);
- cloth_brush_add_deformation_constraint(data->cloth_sim, vd.index, fade);
+ if (brush && brush->sculpt_tool == SCULPT_TOOL_CLOTH) {
+ /* The cloth brush works by applying forces in most of its modes, but some of them require
+ * deformation coordinates to make the simulation stable. */
+ if (cloth_is_deform_brush && len_squared < radius_squared) {
+ /* When a deform brush is used as part of the cloth brush, deformation constraints are
+ * created with different strengths and only inside the radius of the brush. */
+ const float fade = BKE_brush_curve_strength(brush, sqrtf(len_squared), ss->cache->radius);
+ cloth_brush_add_deformation_constraint(data->cloth_sim, vd.index, fade);
+ }
+ }
+ else if (data->cloth_sim->deformation_pos) {
+ /* Any other tool that target the cloth simulation handle the falloff in
+ * their own code when modifying the deformation coordinates of the simulation, so
+ * deformation constraints are created with a fixed strength for all vercies. */
+ cloth_brush_add_deformation_constraint(
+ data->cloth_sim, vd.index, CLOTH_DEFORMATION_TARGET_STRENGTH);
}
if (pin_simulation_boundary) {
@@ -716,7 +730,7 @@ static void cloth_brush_satisfy_constraints(SculptSession *ss,
}
}
-static void cloth_brush_do_simulation_step(
+void SCULPT_cloth_brush_do_simulation_step(
Sculpt *sd, Object *ob, SculptClothSimulation *cloth_sim, PBVHNode **nodes, int totnode)
{
SculptSession *ss = ob->sculpt;
@@ -924,7 +938,6 @@ void SCULPT_do_cloth_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnode
{
SculptSession *ss = ob->sculpt;
Brush *brush = BKE_paint_brush(&sd->paint);
- const int totverts = SCULPT_vertex_count_get(ss);
/* In the first brush step of each symmetry pass, build the constraints for the vertices in all
* nodes inside the simulation's limits. */
@@ -954,15 +967,13 @@ void SCULPT_do_cloth_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnode
}
/* Store the initial state in the simulation. */
- for (int i = 0; i < totverts; i++) {
- copy_v3_v3(ss->cache->cloth_sim->pos[i], SCULPT_vertex_co_get(ss, i));
- }
+ SCULPT_cloth_brush_store_simulation_state(ss, ss->cache->cloth_sim);
/* Apply forces to the vertices. */
cloth_brush_apply_brush_foces(sd, ob, nodes, totnode);
/* Update and write the simulation to the nodes. */
- cloth_brush_do_simulation_step(sd, ob, ss->cache->cloth_sim, nodes, totnode);
+ SCULPT_cloth_brush_do_simulation_step(sd, ob, ss->cache->cloth_sim, nodes, totnode);
}
void SCULPT_cloth_simulation_free(struct SculptClothSimulation *cloth_sim)
@@ -1189,7 +1200,7 @@ static int sculpt_cloth_filter_modal(bContext *C, wmOperator *op, const wmEvent
0, ss->filter_cache->totnode, &data, cloth_filter_apply_forces_task_cb, &settings);
/* Update and write the simulation to the nodes. */
- cloth_brush_do_simulation_step(
+ SCULPT_cloth_brush_do_simulation_step(
sd, ob, ss->filter_cache->cloth_sim, ss->filter_cache->nodes, ss->filter_cache->totnode);
if (ss->deform_modifiers_active || ss->shapekey_active) {
diff --git a/source/blender/editors/sculpt_paint/sculpt_intern.h b/source/blender/editors/sculpt_paint/sculpt_intern.h
index df81deeb9d4..548ef00ad87 100644
--- a/source/blender/editors/sculpt_paint/sculpt_intern.h
+++ b/source/blender/editors/sculpt_paint/sculpt_intern.h
@@ -104,6 +104,12 @@ void SCULPT_vertex_persistent_normal_get(SculptSession *ss, int index, float no[
* current coordinate of the vertex. */
void SCULPT_vertex_limit_surface_get(SculptSession *ss, int index, float r_co[3]);
+/* Returns the pointer to the coordinates that should be edited from a brush tool iterator
+ * depending on the given deformation target. */
+float *SCULPT_brush_deform_target_vertex_co_get(SculptSession *ss,
+ const int deform_target,
+ PBVHVertexIter *iter);
+
#define SCULPT_VERTEX_NEIGHBOR_FIXED_CAPACITY 256
typedef struct SculptVertexNeighborIter {
/* Storage */
@@ -350,6 +356,7 @@ void SCULPT_do_cloth_brush(struct Sculpt *sd,
struct Object *ob,
struct PBVHNode **nodes,
int totnode);
+
void SCULPT_cloth_simulation_free(struct SculptClothSimulation *cloth_sim);
struct SculptClothSimulation *SCULPT_cloth_brush_simulation_create(struct SculptSession *ss,
@@ -391,8 +398,12 @@ void SCULPT_cloth_plane_falloff_preview_draw(const uint gpuattr,
BLI_INLINE bool SCULPT_is_cloth_deform_brush(const Brush *brush)
{
- return brush->sculpt_tool == SCULPT_TOOL_CLOTH &&
- brush->cloth_deform_type == BRUSH_CLOTH_DEFORM_GRAB;
+ return (brush->sculpt_tool == SCULPT_TOOL_CLOTH &&
+ brush->cloth_deform_type == BRUSH_CLOTH_DEFORM_GRAB) ||
+ /* All brushes that are not the cloth brush deform the simulation using softbody
+ constriants instead of applying forces. */
+ (brush->sculpt_tool != SCULPT_TOOL_CLOTH &&
+ brush->deform_target == BRUSH_DEFORM_TARGET_CLOTH_SIM);
}
/* Pose Brush. */
diff --git a/source/blender/editors/sculpt_paint/sculpt_pose.c b/source/blender/editors/sculpt_paint/sculpt_pose.c
index 4d41d069155..e53e33c1186 100644
--- a/source/blender/editors/sculpt_paint/sculpt_pose.c
+++ b/source/blender/editors/sculpt_paint/sculpt_pose.c
@@ -165,6 +165,7 @@ static void do_pose_brush_task_cb_ex(void *__restrict userdata,
SculptSession *ss = data->ob->sculpt;
SculptPoseIKChain *ik_chain = ss->cache->pose_ik_chain;
SculptPoseIKChainSegment *segments = ik_chain->segments;
+ const Brush *brush = data->brush;
PBVHVertexIter vd;
float disp[3], new_co[3];
@@ -206,7 +207,9 @@ static void do_pose_brush_task_cb_ex(void *__restrict userdata,
/* Apply the accumulated displacement to the vertex. */
add_v3_v3v3(final_pos, orig_data.co, total_disp);
- copy_v3_v3(vd.co, final_pos);
+
+ float *target_co = SCULPT_brush_deform_target_vertex_co_get(ss, brush->deform_target, &vd);
+ copy_v3_v3(target_co, final_pos);
if (vd.mvert) {
vd.mvert->flag |= ME_VERT_PBVH_UPDATE;
diff --git a/source/blender/makesdna/DNA_brush_types.h b/source/blender/makesdna/DNA_brush_types.h
index 6c4d2856526..3873763e3e0 100644
--- a/source/blender/makesdna/DNA_brush_types.h
+++ b/source/blender/makesdna/DNA_brush_types.h
@@ -322,6 +322,11 @@ typedef enum eBrushCurvePreset {
BRUSH_CURVE_SMOOTHER = 9,
} eBrushCurvePreset;
+typedef enum eBrushDeformTarget {
+ BRUSH_DEFORM_TARGET_GEOMETRY = 0,
+ BRUSH_DEFORM_TARGET_CLOTH_SIM = 1,
+} eBrushDeformTarget;
+
typedef enum eBrushElasticDeformType {
BRUSH_ELASTIC_DEFORM_GRAB = 0,
BRUSH_ELASTIC_DEFORM_GRAB_BISCALE = 1,
@@ -539,7 +544,7 @@ typedef struct Brush {
/** Source for fill tool color gradient application. */
char gradient_fill_mode;
- char _pad0[1];
+ char _pad0[5];
/** Projection shape (sphere, circle). */
char falloff_shape;
@@ -587,6 +592,8 @@ typedef struct Brush {
/* Maximun distance to search fake neighbors from a vertex. */
float disconnected_distance_max;
+ int deform_target;
+
/* automasking */
int automasking_flags;
int automasking_boundary_edges_propagation_steps;
diff --git a/source/blender/makesrna/intern/rna_brush.c b/source/blender/makesrna/intern/rna_brush.c
index cc39a5dbe8d..fa48cf2f399 100644
--- a/source/blender/makesrna/intern/rna_brush.c
+++ b/source/blender/makesrna/intern/rna_brush.c
@@ -1979,6 +1979,20 @@ static void rna_def_brush(BlenderRNA *brna)
{0, NULL, 0, NULL, NULL},
};
+ static const EnumPropertyItem brush_deformation_target_items[] = {
+ {BRUSH_DEFORM_TARGET_GEOMETRY,
+ "GEOMETRY",
+ 0,
+ "Geometry",
+ "Brush deformation displaces the vertices of the mesh"},
+ {BRUSH_DEFORM_TARGET_CLOTH_SIM,
+ "CLOTH_SIM",
+ 0,
+ "Cloth Simulation",
+ "Brush deforms the mesh by deforming the constraints of a cloth simulation"},
+ {0, NULL, 0, NULL, NULL},
+ };
+
static const EnumPropertyItem brush_elastic_deform_type_items[] = {
{BRUSH_ELASTIC_DEFORM_GRAB, "GRAB", 0, "Grab", ""},
{BRUSH_ELASTIC_DEFORM_GRAB_BISCALE, "GRAB_BISCALE", 0, "Bi-scale Grab", ""},
@@ -2207,6 +2221,12 @@ static void rna_def_brush(BlenderRNA *brna)
RNA_def_property_ui_text(prop, "Curve Preset", "");
RNA_def_property_update(prop, 0, "rna_Brush_update");
+ prop = RNA_def_property(srna, "deform_target", PROP_ENUM, PROP_NONE);
+ RNA_def_property_enum_items(prop, brush_deformation_target_items);
+ RNA_def_property_ui_text(
+ prop, "Deformation Target", "How the deformation of the brush will affect the object");
+ RNA_def_property_update(prop, 0, "rna_Brush_update");
+
prop = RNA_def_property(srna, "elastic_deform_type", PROP_ENUM, PROP_NONE);
RNA_def_property_enum_items(prop, brush_elastic_deform_type_items);
RNA_def_property_ui_text(prop, "Deformation", "Deformation type that is used in the brush");