Sculpt: Expose the functions to create and init a SculptClothSimulation
This will be used for new features like supporting cloth deformation in other brushes and tools outside of the cloth brush code. No functional changes. Reviewed By: sergey Differential Revision: https://developer.blender.org/D8602
This commit is contained in:
@@ -505,49 +505,6 @@ static ListBase *cloth_brush_collider_cache_create(Depsgraph *depsgraph)
|
||||
return cache;
|
||||
}
|
||||
|
||||
static SculptClothSimulation *cloth_brush_simulation_create(SculptSession *ss,
|
||||
Brush *brush,
|
||||
const float cloth_mass,
|
||||
const float cloth_damping,
|
||||
const bool use_collisions)
|
||||
{
|
||||
const int totverts = SCULPT_vertex_count_get(ss);
|
||||
SculptClothSimulation *cloth_sim;
|
||||
|
||||
cloth_sim = MEM_callocN(sizeof(SculptClothSimulation), "cloth constraints");
|
||||
|
||||
cloth_sim->length_constraints = MEM_callocN(sizeof(SculptClothLengthConstraint) *
|
||||
CLOTH_LENGTH_CONSTRAINTS_BLOCK,
|
||||
"cloth length constraints");
|
||||
cloth_sim->capacity_length_constraints = CLOTH_LENGTH_CONSTRAINTS_BLOCK;
|
||||
|
||||
cloth_sim->acceleration = MEM_calloc_arrayN(
|
||||
totverts, sizeof(float[3]), "cloth sim acceleration");
|
||||
cloth_sim->pos = MEM_calloc_arrayN(totverts, sizeof(float[3]), "cloth sim pos");
|
||||
cloth_sim->prev_pos = MEM_calloc_arrayN(totverts, sizeof(float[3]), "cloth sim prev pos");
|
||||
cloth_sim->last_iteration_pos = MEM_calloc_arrayN(
|
||||
totverts, sizeof(float[3]), "cloth sim last iteration pos");
|
||||
cloth_sim->init_pos = MEM_calloc_arrayN(totverts, sizeof(float[3]), "cloth sim init pos");
|
||||
cloth_sim->length_constraint_tweak = MEM_calloc_arrayN(
|
||||
totverts, sizeof(float), "cloth sim length tweak");
|
||||
|
||||
/* Brush can be NULL for tools that need the solver but don't rely on constraint to deformation
|
||||
* positions. */
|
||||
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->mass = cloth_mass;
|
||||
cloth_sim->damping = cloth_damping;
|
||||
|
||||
if (use_collisions) {
|
||||
cloth_sim->collider_list = cloth_brush_collider_cache_create(ss->depsgraph);
|
||||
}
|
||||
|
||||
return cloth_sim;
|
||||
}
|
||||
|
||||
typedef struct ClothBrushCollision {
|
||||
CollisionModifierData *col_data;
|
||||
struct IsectRayPrecalc isect_precalc;
|
||||
@@ -699,43 +656,6 @@ static void do_cloth_brush_solve_simulation_task_cb_ex(
|
||||
BKE_pbvh_vertex_iter_end;
|
||||
}
|
||||
|
||||
static void cloth_brush_build_nodes_constraints(
|
||||
Sculpt *sd,
|
||||
Object *ob,
|
||||
PBVHNode **nodes,
|
||||
int totnode,
|
||||
SculptClothSimulation *cloth_sim,
|
||||
/* Cannot be const, because it is assigned to a non-const variable.
|
||||
* NOLINTNEXTLINE: readability-non-const-parameter. */
|
||||
float initial_location[3],
|
||||
const float radius)
|
||||
{
|
||||
Brush *brush = BKE_paint_brush(&sd->paint);
|
||||
|
||||
/* TODO: Multi-threaded needs to be disabled for this task until implementing the optimization of
|
||||
* storing the constraints per node. */
|
||||
/* Currently all constrains are added to the same global array which can't be accessed from
|
||||
* different threads. */
|
||||
TaskParallelSettings settings;
|
||||
BKE_pbvh_parallel_range_settings(&settings, false, totnode);
|
||||
|
||||
cloth_sim->created_length_constraints = BLI_edgeset_new("created length constraints");
|
||||
|
||||
SculptThreadedTaskData build_constraints_data = {
|
||||
.sd = sd,
|
||||
.ob = ob,
|
||||
.brush = brush,
|
||||
.nodes = nodes,
|
||||
.cloth_sim = cloth_sim,
|
||||
.cloth_sim_initial_location = initial_location,
|
||||
.cloth_sim_radius = radius,
|
||||
};
|
||||
BLI_task_parallel_range(
|
||||
0, totnode, &build_constraints_data, do_cloth_brush_build_constraints_task_cb_ex, &settings);
|
||||
|
||||
BLI_edgeset_free(cloth_sim->created_length_constraints);
|
||||
}
|
||||
|
||||
static void cloth_brush_satisfy_constraints(SculptSession *ss,
|
||||
Brush *brush,
|
||||
SculptClothSimulation *cloth_sim)
|
||||
@@ -897,6 +817,107 @@ static void cloth_brush_apply_brush_foces(Sculpt *sd, Object *ob, PBVHNode **nod
|
||||
}
|
||||
|
||||
/* Public functions. */
|
||||
SculptClothSimulation *SCULPT_cloth_brush_simulation_create(SculptSession *ss,
|
||||
Brush *brush,
|
||||
const float cloth_mass,
|
||||
const float cloth_damping,
|
||||
const bool use_collisions)
|
||||
{
|
||||
const int totverts = SCULPT_vertex_count_get(ss);
|
||||
SculptClothSimulation *cloth_sim;
|
||||
|
||||
cloth_sim = MEM_callocN(sizeof(SculptClothSimulation), "cloth constraints");
|
||||
|
||||
cloth_sim->length_constraints = MEM_callocN(sizeof(SculptClothLengthConstraint) *
|
||||
CLOTH_LENGTH_CONSTRAINTS_BLOCK,
|
||||
"cloth length constraints");
|
||||
cloth_sim->capacity_length_constraints = CLOTH_LENGTH_CONSTRAINTS_BLOCK;
|
||||
|
||||
cloth_sim->acceleration = MEM_calloc_arrayN(
|
||||
totverts, sizeof(float[3]), "cloth sim acceleration");
|
||||
cloth_sim->pos = MEM_calloc_arrayN(totverts, sizeof(float[3]), "cloth sim pos");
|
||||
cloth_sim->prev_pos = MEM_calloc_arrayN(totverts, sizeof(float[3]), "cloth sim prev pos");
|
||||
cloth_sim->last_iteration_pos = MEM_calloc_arrayN(
|
||||
totverts, sizeof(float[3]), "cloth sim last iteration pos");
|
||||
cloth_sim->init_pos = MEM_calloc_arrayN(totverts, sizeof(float[3]), "cloth sim init pos");
|
||||
cloth_sim->length_constraint_tweak = MEM_calloc_arrayN(
|
||||
totverts, sizeof(float), "cloth sim length tweak");
|
||||
|
||||
/* Brush can be NULL for tools that need the solver but don't rely on constraint to deformation
|
||||
* positions. */
|
||||
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->mass = cloth_mass;
|
||||
cloth_sim->damping = cloth_damping;
|
||||
|
||||
if (use_collisions) {
|
||||
cloth_sim->collider_list = cloth_brush_collider_cache_create(ss->depsgraph);
|
||||
}
|
||||
|
||||
return cloth_sim;
|
||||
}
|
||||
|
||||
void SCULPT_cloth_brush_build_nodes_constraints(
|
||||
Sculpt *sd,
|
||||
Object *ob,
|
||||
PBVHNode **nodes,
|
||||
int totnode,
|
||||
SculptClothSimulation *cloth_sim,
|
||||
/* Cannot be const, because it is assigned to a non-const variable.
|
||||
* NOLINTNEXTLINE: readability-non-const-parameter. */
|
||||
float initial_location[3],
|
||||
const float radius)
|
||||
{
|
||||
Brush *brush = BKE_paint_brush(&sd->paint);
|
||||
|
||||
/* TODO: Multi-threaded needs to be disabled for this task until implementing the optimization of
|
||||
* storing the constraints per node. */
|
||||
/* Currently all constrains are added to the same global array which can't be accessed from
|
||||
* different threads. */
|
||||
TaskParallelSettings settings;
|
||||
BKE_pbvh_parallel_range_settings(&settings, false, totnode);
|
||||
|
||||
cloth_sim->created_length_constraints = BLI_edgeset_new("created length constraints");
|
||||
|
||||
SculptThreadedTaskData build_constraints_data = {
|
||||
.sd = sd,
|
||||
.ob = ob,
|
||||
.brush = brush,
|
||||
.nodes = nodes,
|
||||
.cloth_sim = cloth_sim,
|
||||
.cloth_sim_initial_location = initial_location,
|
||||
.cloth_sim_radius = radius,
|
||||
};
|
||||
BLI_task_parallel_range(
|
||||
0, totnode, &build_constraints_data, do_cloth_brush_build_constraints_task_cb_ex, &settings);
|
||||
|
||||
BLI_edgeset_free(cloth_sim->created_length_constraints);
|
||||
}
|
||||
|
||||
void SCULPT_cloth_brush_simulation_init(SculptSession *ss, SculptClothSimulation *cloth_sim)
|
||||
{
|
||||
const int totverts = SCULPT_vertex_count_get(ss);
|
||||
const bool has_deformation_pos = cloth_sim->deformation_pos != NULL;
|
||||
for (int i = 0; i < totverts; i++) {
|
||||
copy_v3_v3(cloth_sim->last_iteration_pos[i], SCULPT_vertex_co_get(ss, i));
|
||||
copy_v3_v3(cloth_sim->init_pos[i], SCULPT_vertex_co_get(ss, i));
|
||||
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));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void SCULPT_cloth_brush_store_simulation_state(SculptSession *ss, SculptClothSimulation *cloth_sim)
|
||||
{
|
||||
const int totverts = SCULPT_vertex_count_get(ss);
|
||||
for (int i = 0; i < totverts; i++) {
|
||||
copy_v3_v3(cloth_sim->pos[i], SCULPT_vertex_co_get(ss, i));
|
||||
}
|
||||
}
|
||||
|
||||
/* Main Brush Function. */
|
||||
void SCULPT_do_cloth_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnode)
|
||||
@@ -914,27 +935,19 @@ void SCULPT_do_cloth_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnode
|
||||
|
||||
/* The simulation structure only needs to be created on the first symmetry pass. */
|
||||
if (SCULPT_stroke_is_first_brush_step(ss->cache) || !ss->cache->cloth_sim) {
|
||||
const bool is_cloth_deform_brush = SCULPT_is_cloth_deform_brush(brush);
|
||||
ss->cache->cloth_sim = cloth_brush_simulation_create(
|
||||
ss->cache->cloth_sim = SCULPT_cloth_brush_simulation_create(
|
||||
ss,
|
||||
brush,
|
||||
brush->cloth_mass,
|
||||
brush->cloth_damping,
|
||||
(brush->flag2 & BRUSH_CLOTH_USE_COLLISION));
|
||||
for (int i = 0; i < totverts; i++) {
|
||||
copy_v3_v3(ss->cache->cloth_sim->last_iteration_pos[i], SCULPT_vertex_co_get(ss, i));
|
||||
copy_v3_v3(ss->cache->cloth_sim->init_pos[i], SCULPT_vertex_co_get(ss, i));
|
||||
copy_v3_v3(ss->cache->cloth_sim->prev_pos[i], SCULPT_vertex_co_get(ss, i));
|
||||
if (is_cloth_deform_brush) {
|
||||
copy_v3_v3(ss->cache->cloth_sim->deformation_pos[i], SCULPT_vertex_co_get(ss, i));
|
||||
}
|
||||
}
|
||||
SCULPT_cloth_brush_simulation_init(ss, ss->cache->cloth_sim);
|
||||
}
|
||||
|
||||
/* Build the constraints. */
|
||||
const float radius = ss->cache->initial_radius;
|
||||
const float limit = radius + (radius * brush->cloth_sim_limit);
|
||||
cloth_brush_build_nodes_constraints(
|
||||
SCULPT_cloth_brush_build_nodes_constraints(
|
||||
sd, ob, nodes, totnode, ss->cache->cloth_sim, ss->cache->location, limit);
|
||||
|
||||
return;
|
||||
@@ -1192,26 +1205,21 @@ static int sculpt_cloth_filter_invoke(bContext *C, wmOperator *op, const wmEvent
|
||||
const float cloth_mass = RNA_float_get(op->ptr, "cloth_mass");
|
||||
const float cloth_damping = RNA_float_get(op->ptr, "cloth_damping");
|
||||
const bool use_collisions = RNA_boolean_get(op->ptr, "use_collisions");
|
||||
ss->filter_cache->cloth_sim = cloth_brush_simulation_create(
|
||||
ss->filter_cache->cloth_sim = SCULPT_cloth_brush_simulation_create(
|
||||
ss, NULL, cloth_mass, cloth_damping, use_collisions);
|
||||
|
||||
copy_v3_v3(ss->filter_cache->cloth_sim_pinch_point, SCULPT_active_vertex_co_get(ss));
|
||||
|
||||
const int totverts = SCULPT_vertex_count_get(ss);
|
||||
for (int i = 0; i < totverts; i++) {
|
||||
copy_v3_v3(ss->filter_cache->cloth_sim->last_iteration_pos[i], SCULPT_vertex_co_get(ss, i));
|
||||
copy_v3_v3(ss->filter_cache->cloth_sim->prev_pos[i], SCULPT_vertex_co_get(ss, i));
|
||||
copy_v3_v3(ss->filter_cache->cloth_sim->init_pos[i], SCULPT_vertex_co_get(ss, i));
|
||||
}
|
||||
SCULPT_cloth_brush_simulation_init(ss, ss->filter_cache->cloth_sim);
|
||||
|
||||
float origin[3] = {0.0f, 0.0f, 0.0f};
|
||||
cloth_brush_build_nodes_constraints(sd,
|
||||
ob,
|
||||
ss->filter_cache->nodes,
|
||||
ss->filter_cache->totnode,
|
||||
ss->filter_cache->cloth_sim,
|
||||
origin,
|
||||
FLT_MAX);
|
||||
SCULPT_cloth_brush_build_nodes_constraints(sd,
|
||||
ob,
|
||||
ss->filter_cache->nodes,
|
||||
ss->filter_cache->totnode,
|
||||
ss->filter_cache->cloth_sim,
|
||||
origin,
|
||||
FLT_MAX);
|
||||
|
||||
const bool use_face_sets = RNA_boolean_get(op->ptr, "use_face_sets");
|
||||
if (use_face_sets) {
|
||||
|
||||
@@ -352,6 +352,30 @@ void SCULPT_do_cloth_brush(struct Sculpt *sd,
|
||||
int totnode);
|
||||
void SCULPT_cloth_simulation_free(struct SculptClothSimulation *cloth_sim);
|
||||
|
||||
struct SculptClothSimulation *SCULPT_cloth_brush_simulation_create(struct SculptSession *ss,
|
||||
struct Brush *brush,
|
||||
const float cloth_mass,
|
||||
const float cloth_damping,
|
||||
const bool use_collisions);
|
||||
void SCULPT_cloth_brush_simulation_init(struct SculptSession *ss,
|
||||
struct SculptClothSimulation *cloth_sim);
|
||||
void SCULPT_cloth_brush_store_simulation_state(struct SculptSession *ss,
|
||||
struct SculptClothSimulation *cloth_sim);
|
||||
|
||||
void SCULPT_cloth_brush_do_simulation_step(struct Sculpt *sd,
|
||||
struct Object *ob,
|
||||
struct SculptClothSimulation *cloth_sim,
|
||||
struct PBVHNode **nodes,
|
||||
int totnode);
|
||||
|
||||
void SCULPT_cloth_brush_build_nodes_constraints(struct Sculpt *sd,
|
||||
struct Object *ob,
|
||||
struct PBVHNode **nodes,
|
||||
int totnode,
|
||||
struct SculptClothSimulation *cloth_sim,
|
||||
float initial_location[3],
|
||||
const float radius);
|
||||
|
||||
void SCULPT_cloth_simulation_limits_draw(const uint gpuattr,
|
||||
const struct Brush *brush,
|
||||
const float location[3],
|
||||
|
||||
Reference in New Issue
Block a user