Sculpt: Cloth brush Pin Simulation Boundary property
The cloth brush has a defined simulated area with a falloff. In the falloff area (the area between the dashed white circle and the exterior white circle), simulation properties change in order to fade out the simulation deformation effects towards the boundary. With some brushes and stroke types (like anchored strokes with pinching or grabbing with full strength), it is possible to apply more force than what the boundary falloff can compensate, so the simulation breaks when this happens. This option pins the falloff area with softbody constraints, This produces a much better deformation falloff and it is no longer possible to move the vertices near the simulation boundary, so the simulation won't break no matter the strength of the forces applied inside the simulated areas. This is an option as it is particularly useful for some brushes to add localized details, but for brushes that are supposed to deform the entire mesh (like the grab brush in D8424), this can add unwanted softbody constraints that affect the simulation result. Reviewed By: sergey Differential Revision: https://developer.blender.org/D8435
This commit is contained in:
parent
6faa765af8
commit
bf65820782
|
@ -656,6 +656,7 @@ def brush_settings(layout, context, brush, popover=False):
|
|||
layout.separator()
|
||||
layout.prop(brush, "cloth_sim_limit")
|
||||
layout.prop(brush, "cloth_sim_falloff")
|
||||
layout.prop(brush, "use_cloth_pin_simulation_boundary")
|
||||
layout.separator()
|
||||
layout.prop(brush, "cloth_deform_type")
|
||||
layout.prop(brush, "cloth_force_falloff_type")
|
||||
|
|
|
@ -100,6 +100,28 @@
|
|||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
static float cloth_brush_simulation_falloff_get(const Brush *brush,
|
||||
const float radius,
|
||||
const float location[3],
|
||||
const float co[3])
|
||||
{
|
||||
const float distance = len_v3v3(location, co);
|
||||
const float limit = radius + (radius * brush->cloth_sim_limit);
|
||||
const float falloff = radius + (radius * brush->cloth_sim_limit * brush->cloth_sim_falloff);
|
||||
|
||||
if (distance > limit) {
|
||||
/* Outiside the limits. */
|
||||
return 0.0f;
|
||||
}
|
||||
if (distance < falloff) {
|
||||
/* Before the falloff area. */
|
||||
return 1.0f;
|
||||
}
|
||||
/* Do a smoothstep transition inside the falloff area. */
|
||||
float p = 1.0f - ((distance - falloff) / (limit - falloff));
|
||||
return 3.0f * p * p - 2.0f * p * p * p;
|
||||
}
|
||||
|
||||
#define CLOTH_LENGTH_CONSTRAINTS_BLOCK 100000
|
||||
#define CLOTH_SIMULATION_ITERATIONS 5
|
||||
#define CLOTH_MAX_CONSTRAINTS_PER_VERTEX 1024
|
||||
|
@ -210,6 +232,9 @@ static void do_cloth_brush_build_constraints_task_cb_ex(
|
|||
|
||||
PBVHVertexIter vd;
|
||||
|
||||
const bool pin_simulation_boundary = ss->cache != NULL && brush != NULL &&
|
||||
brush->flag2 & BRUSH_CLOTH_PIN_SIMULATION_BOUNDARY;
|
||||
|
||||
const bool use_persistent = brush != NULL && brush->flag & BRUSH_PERSISTENT;
|
||||
|
||||
/* Brush can be NULL in tools that use the solver without relying of constraints with deformation
|
||||
|
@ -264,32 +289,21 @@ static void do_cloth_brush_build_constraints_task_cb_ex(
|
|||
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 (pin_simulation_boundary) {
|
||||
const float sim_falloff = cloth_brush_simulation_falloff_get(
|
||||
brush, ss->cache->initial_radius, ss->cache->location, vd.co);
|
||||
/* Vertex is inside the area of the simulation without any falloff aplied. */
|
||||
if (sim_falloff < 1.0f) {
|
||||
/* Create constraints with more strength the closer the vertex is to the simulation
|
||||
* boundary. */
|
||||
cloth_brush_add_softbody_constraint(data->cloth_sim, vd.index, 1.0f - sim_falloff);
|
||||
}
|
||||
}
|
||||
}
|
||||
BKE_pbvh_vertex_iter_end;
|
||||
}
|
||||
|
||||
static float cloth_brush_simulation_falloff_get(const Brush *brush,
|
||||
const float radius,
|
||||
const float location[3],
|
||||
const float co[3])
|
||||
{
|
||||
const float distance = len_v3v3(location, co);
|
||||
const float limit = radius + (radius * brush->cloth_sim_limit);
|
||||
const float falloff = radius + (radius * brush->cloth_sim_limit * brush->cloth_sim_falloff);
|
||||
|
||||
if (distance > limit) {
|
||||
/* Outiside the limits. */
|
||||
return 0.0f;
|
||||
}
|
||||
if (distance < falloff) {
|
||||
/* Before the falloff area. */
|
||||
return 1.0f;
|
||||
}
|
||||
/* Do a smoothstep transition inside the falloff area. */
|
||||
float p = 1.0f - ((distance - falloff) / (limit - falloff));
|
||||
return 3.0f * p * p - 2.0f * p * p * p;
|
||||
}
|
||||
|
||||
static void cloth_brush_apply_force_to_vertex(SculptSession *UNUSED(ss),
|
||||
SculptClothSimulation *cloth_sim,
|
||||
const float force[3],
|
||||
|
|
|
@ -726,6 +726,7 @@ typedef enum eBrushFlags2 {
|
|||
BRUSH_MULTIPLANE_SCRAPE_PLANES_PREVIEW = (1 << 1),
|
||||
BRUSH_POSE_IK_ANCHORED = (1 << 2),
|
||||
BRUSH_USE_CONNECTED_ONLY = (1 << 3),
|
||||
BRUSH_CLOTH_PIN_SIMULATION_BOUNDARY = (1 << 4),
|
||||
} eBrushFlags2;
|
||||
|
||||
typedef enum {
|
||||
|
|
|
@ -2793,6 +2793,15 @@ static void rna_def_brush(BlenderRNA *brna)
|
|||
RNA_def_property_ui_text(prop, "Connected Only", "Affect only topologically connected elements");
|
||||
RNA_def_property_update(prop, 0, "rna_Brush_update");
|
||||
|
||||
prop = RNA_def_property(srna, "use_cloth_pin_simulation_boundary", PROP_BOOLEAN, PROP_NONE);
|
||||
RNA_def_property_boolean_sdna(prop, NULL, "flag2", BRUSH_CLOTH_PIN_SIMULATION_BOUNDARY);
|
||||
RNA_def_property_ui_text(
|
||||
prop,
|
||||
"Pin Simulation Boundary",
|
||||
"Lock the position of the vertices in the simulation falloff area to avoid artifacts and "
|
||||
"create a softer transitionwith with unnafected areas");
|
||||
RNA_def_property_update(prop, 0, "rna_Brush_update");
|
||||
|
||||
prop = RNA_def_property(srna, "invert_to_scrape_fill", PROP_BOOLEAN, PROP_NONE);
|
||||
RNA_def_property_boolean_sdna(prop, NULL, "flag", BRUSH_INVERT_TO_SCRAPE_FILL);
|
||||
RNA_def_property_ui_text(prop,
|
||||
|
|
Loading…
Reference in New Issue