From db4e08dfdc9c90680e4722e02a3c6f35d51f124f Mon Sep 17 00:00:00 2001 From: Pablo Dobarro Date: Mon, 17 Aug 2020 22:18:26 +0200 Subject: 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 --- source/blender/editors/sculpt_paint/sculpt_cloth.c | 218 +++++++++++---------- .../blender/editors/sculpt_paint/sculpt_intern.h | 24 +++ 2 files changed, 137 insertions(+), 105 deletions(-) (limited to 'source/blender/editors/sculpt_paint') diff --git a/source/blender/editors/sculpt_paint/sculpt_cloth.c b/source/blender/editors/sculpt_paint/sculpt_cloth.c index 4070822a0a8..bdc7d7520ea 100644 --- a/source/blender/editors/sculpt_paint/sculpt_cloth.c +++ b/source/blender/editors/sculpt_paint/sculpt_cloth.c @@ -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) { diff --git a/source/blender/editors/sculpt_paint/sculpt_intern.h b/source/blender/editors/sculpt_paint/sculpt_intern.h index ee0eaeb28f3..4ac7c79e839 100644 --- a/source/blender/editors/sculpt_paint/sculpt_intern.h +++ b/source/blender/editors/sculpt_paint/sculpt_intern.h @@ -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], -- cgit v1.2.3