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:
authorPablo Dobarro <pablodp606@gmail.com>2020-08-25 00:26:37 +0300
committerPablo Dobarro <pablodp606@gmail.com>2020-08-25 00:28:01 +0300
commit46eca3366efbdc83e4dcfbd9ac4cd23f70da6399 (patch)
treecf37cc05e13f6355d4c6bb0b93c4a45db189c800 /source/blender/editors/sculpt_paint/sculpt_cloth.c
parent5a634735e6e2fe805b639b03168afa983c52fa5b (diff)
Sculpt: Cloth Snake Hook Brush
This implements Snake Hook as a deform type for the cloth brush. This brush changes the strength of the deformation constraints per brush step to avoid affecting the results of the simulation as much as possible. It allows to grab the cloth without producing any artifacts in the surface and create more natural looking folds than any of the other deformation modes. Reviewed By: sergey Differential Revision: https://developer.blender.org/D8621
Diffstat (limited to 'source/blender/editors/sculpt_paint/sculpt_cloth.c')
-rw-r--r--source/blender/editors/sculpt_paint/sculpt_cloth.c51
1 files changed, 45 insertions, 6 deletions
diff --git a/source/blender/editors/sculpt_paint/sculpt_cloth.c b/source/blender/editors/sculpt_paint/sculpt_cloth.c
index cf2ed0943eb..c3666c8aaad 100644
--- a/source/blender/editors/sculpt_paint/sculpt_cloth.c
+++ b/source/blender/editors/sculpt_paint/sculpt_cloth.c
@@ -169,6 +169,8 @@ static void cloth_brush_add_length_constraint(SculptSession *ss,
length_constraint->elem_position_a = cloth_sim->pos[v1];
length_constraint->elem_position_b = cloth_sim->pos[v2];
+ length_constraint->type = SCULPT_CLOTH_CONSTRAINT_STRUCTURAL;
+
if (use_persistent) {
length_constraint->length = len_v3v3(SCULPT_vertex_persistent_co_get(ss, v1),
SCULPT_vertex_persistent_co_get(ss, v2));
@@ -201,6 +203,8 @@ static void cloth_brush_add_softbody_constraint(SculptClothSimulation *cloth_sim
length_constraint->elem_position_a = cloth_sim->pos[v];
length_constraint->elem_position_b = cloth_sim->init_pos[v];
+ length_constraint->type = SCULPT_CLOTH_CONSTRAINT_SOFTBODY;
+
length_constraint->length = 0.0f;
length_constraint->strength = strength;
@@ -220,6 +224,8 @@ static void cloth_brush_add_deformation_constraint(SculptClothSimulation *cloth_
length_constraint->elem_index_a = v;
length_constraint->elem_index_b = v;
+ length_constraint->type = SCULPT_CLOTH_CONSTRAINT_DEFORMATION;
+
length_constraint->elem_position_a = cloth_sim->pos[v];
length_constraint->elem_position_b = cloth_sim->deformation_pos[v];
@@ -301,12 +307,18 @@ static void do_cloth_brush_build_constraints_task_cb_ex(
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. */
+ if (brush->cloth_deform_type == BRUSH_CLOTH_DEFORM_GRAB && len_squared < radius_squared) {
+ /* When the grab brush 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 (brush->cloth_deform_type == BRUSH_CLOTH_DEFORM_SNAKE_HOOK) {
+ /* Cloth Snake Hook creates deformation constraint with fixed strength because the strength
+ * is controlled per iteration using cloth_sim->deformation_strength. */
+ cloth_brush_add_deformation_constraint(
+ data->cloth_sim, vd.index, CLOTH_DEFORMATION_TARGET_STRENGTH);
+ }
}
else if (data->cloth_sim->deformation_pos) {
/* Any other tool that target the cloth simulation handle the falloff in
@@ -397,7 +409,7 @@ static void do_cloth_brush_apply_forces_task_cb_ex(void *__restrict userdata,
brush, ss->cache->radius, ss->cache->initial_location, cloth_sim->init_pos[vd.index]);
float current_vertex_location[3];
- if (SCULPT_is_cloth_deform_brush(brush)) {
+ if (brush->cloth_deform_type == BRUSH_CLOTH_DEFORM_GRAB) {
SCULPT_orig_vert_data_update(&orig_data, &vd);
copy_v3_v3(current_vertex_location, orig_data.co);
}
@@ -456,6 +468,12 @@ static void do_cloth_brush_apply_forces_task_cb_ex(void *__restrict userdata,
fade);
zero_v3(force);
break;
+ case BRUSH_CLOTH_DEFORM_SNAKE_HOOK:
+ copy_v3_v3(cloth_sim->deformation_pos[vd.index], cloth_sim->pos[vd.index]);
+ madd_v3_v3fl(cloth_sim->deformation_pos[vd.index], ss->cache->grab_delta_symmetry, fade);
+ cloth_sim->deformation_strength[vd.index] = fade;
+ zero_v3(force);
+ break;
case BRUSH_CLOTH_DEFORM_PINCH_POINT:
if (use_falloff_plane) {
float distance = dist_signed_to_plane_v3(vd.co, deform_plane);
@@ -718,13 +736,21 @@ static void cloth_brush_satisfy_constraints(SculptSession *ss,
cloth_sim->init_pos[v2]) :
1.0f;
+ float deformation_strength = 1.0f;
+ if (constraint->type == SCULPT_CLOTH_CONSTRAINT_DEFORMATION) {
+ deformation_strength = (cloth_sim->deformation_strength[v1] +
+ cloth_sim->deformation_strength[v2]) *
+ 0.5f;
+ }
+
madd_v3_v3fl(cloth_sim->pos[v1],
correction_vector_half,
- 1.0f * mask_v1 * sim_factor_v1 * constraint->strength);
+ 1.0f * mask_v1 * sim_factor_v1 * constraint->strength * deformation_strength);
if (v1 != v2) {
madd_v3_v3fl(cloth_sim->pos[v2],
correction_vector_half,
- -1.0f * mask_v2 * sim_factor_v2 * constraint->strength);
+ -1.0f * mask_v2 * sim_factor_v2 * constraint->strength *
+ deformation_strength);
}
}
}
@@ -824,6 +850,15 @@ static void cloth_brush_apply_brush_foces(Sculpt *sd, Object *ob, PBVHNode **nod
}
}
+ if (brush->cloth_deform_type == BRUSH_CLOTH_DEFORM_SNAKE_HOOK) {
+ /* Set the deformation strength to 0. Snake hook will initialize the strength in the required
+ * area. */
+ const int totverts = SCULPT_vertex_count_get(ss);
+ for (int i = 0; i < totverts; i++) {
+ ss->cache->cloth_sim->deformation_strength[i] = 0.0f;
+ }
+ }
+
TaskParallelSettings settings;
BKE_pbvh_parallel_range_settings(&settings, true, totnode);
BLI_task_parallel_range(
@@ -862,6 +897,8 @@ SculptClothSimulation *SCULPT_cloth_brush_simulation_create(SculptSession *ss,
if (brush && SCULPT_is_cloth_deform_brush(brush)) {
cloth_sim->deformation_pos = MEM_calloc_arrayN(
totverts, sizeof(float[3]), "cloth sim deformation positions");
+ cloth_sim->deformation_strength = MEM_calloc_arrayN(
+ totverts, sizeof(float), "cloth sim deformation strength");
}
cloth_sim->mass = cloth_mass;
@@ -921,6 +958,7 @@ void SCULPT_cloth_brush_simulation_init(SculptSession *ss, SculptClothSimulation
copy_v3_v3(cloth_sim->prev_pos[i], SCULPT_vertex_co_get(ss, i));
if (has_deformation_pos) {
copy_v3_v3(cloth_sim->deformation_pos[i], SCULPT_vertex_co_get(ss, i));
+ cloth_sim->deformation_strength[i] = 1.0f;
}
}
}
@@ -986,6 +1024,7 @@ void SCULPT_cloth_simulation_free(struct SculptClothSimulation *cloth_sim)
MEM_SAFE_FREE(cloth_sim->length_constraint_tweak);
MEM_SAFE_FREE(cloth_sim->deformation_pos);
MEM_SAFE_FREE(cloth_sim->init_pos);
+ MEM_SAFE_FREE(cloth_sim->deformation_strength);
if (cloth_sim->collider_list) {
BKE_collider_cache_free(&cloth_sim->collider_list);
}