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:
Diffstat (limited to 'source/blender/editors/sculpt_paint')
-rw-r--r--source/blender/editors/sculpt_paint/paint_cursor.c3
-rw-r--r--source/blender/editors/sculpt_paint/paint_image.c11
-rw-r--r--source/blender/editors/sculpt_paint/paint_image_2d.c4
-rw-r--r--source/blender/editors/sculpt_paint/paint_image_proj.c6
-rw-r--r--source/blender/editors/sculpt_paint/paint_intern.h1
-rw-r--r--source/blender/editors/sculpt_paint/paint_mask.c52
-rw-r--r--source/blender/editors/sculpt_paint/paint_ops.c1
-rw-r--r--source/blender/editors/sculpt_paint/paint_stroke.c4
-rw-r--r--source/blender/editors/sculpt_paint/paint_vertex_weight_ops.c2
-rw-r--r--source/blender/editors/sculpt_paint/sculpt.c18
-rw-r--r--source/blender/editors/sculpt_paint/sculpt_cloth.c232
-rw-r--r--source/blender/editors/sculpt_paint/sculpt_face_set.c2
-rw-r--r--source/blender/editors/sculpt_paint/sculpt_filter_color.c2
-rw-r--r--source/blender/editors/sculpt_paint/sculpt_intern.h3
-rw-r--r--source/blender/editors/sculpt_paint/sculpt_multiplane_scrape.c1
-rw-r--r--source/blender/editors/sculpt_paint/sculpt_paint_color.c4
-rw-r--r--source/blender/editors/sculpt_paint/sculpt_pose.c4
-rw-r--r--source/blender/editors/sculpt_paint/sculpt_uv.c2
18 files changed, 255 insertions, 97 deletions
diff --git a/source/blender/editors/sculpt_paint/paint_cursor.c b/source/blender/editors/sculpt_paint/paint_cursor.c
index d0082769575..9398e4443f3 100644
--- a/source/blender/editors/sculpt_paint/paint_cursor.c
+++ b/source/blender/editors/sculpt_paint/paint_cursor.c
@@ -56,7 +56,6 @@
#include "DEG_depsgraph.h"
-#include "GPU_draw.h"
#include "GPU_immediate.h"
#include "GPU_immediate_util.h"
#include "GPU_matrix.h"
@@ -456,7 +455,7 @@ static int load_tex_cursor(Brush *br, ViewContext *vc, float zoom)
}
buffer = MEM_mallocN(sizeof(GLubyte) * size * size, "load_tex");
- BKE_curvemapping_initialize(br->curve);
+ BKE_curvemapping_init(br->curve);
LoadTexData data = {
.br = br,
diff --git a/source/blender/editors/sculpt_paint/paint_image.c b/source/blender/editors/sculpt_paint/paint_image.c
index 7ee3d991eb7..34c9cac67c8 100644
--- a/source/blender/editors/sculpt_paint/paint_image.c
+++ b/source/blender/editors/sculpt_paint/paint_image.c
@@ -74,7 +74,6 @@
#include "RNA_access.h"
#include "RNA_define.h"
-#include "GPU_draw.h"
#include "GPU_immediate.h"
#include "GPU_state.h"
@@ -182,7 +181,7 @@ void imapaint_image_update(
int h = imapaintpartial.y2 - imapaintpartial.y1;
if (w && h) {
/* Testing with partial update in uv editor too */
- GPU_paint_update_image(image, iuser, imapaintpartial.x1, imapaintpartial.y1, w, h);
+ BKE_image_update_gputexture(image, iuser, imapaintpartial.x1, imapaintpartial.y1, w, h);
}
}
}
@@ -1164,9 +1163,9 @@ void ED_object_texture_paint_mode_enter_ex(Main *bmain, Scene *scene, Object *ob
BKE_paint_toolslots_brush_validate(bmain, &imapaint->paint);
if (U.glreslimit != 0) {
- GPU_free_images(bmain);
+ BKE_image_free_all_gputextures(bmain);
}
- GPU_paint_set_mipmap(bmain, 0);
+ BKE_image_paint_set_mipmap(bmain, 0);
toggle_paint_cursor(scene, true);
@@ -1189,9 +1188,9 @@ void ED_object_texture_paint_mode_exit_ex(Main *bmain, Scene *scene, Object *ob)
ob->mode &= ~OB_MODE_TEXTURE_PAINT;
if (U.glreslimit != 0) {
- GPU_free_images(bmain);
+ BKE_image_free_all_gputextures(bmain);
}
- GPU_paint_set_mipmap(bmain, 1);
+ BKE_image_paint_set_mipmap(bmain, 1);
toggle_paint_cursor(scene, false);
Mesh *me = BKE_mesh_from_object(ob);
diff --git a/source/blender/editors/sculpt_paint/paint_image_2d.c b/source/blender/editors/sculpt_paint/paint_image_2d.c
index a7f09390a3d..6d588d1450b 100644
--- a/source/blender/editors/sculpt_paint/paint_image_2d.c
+++ b/source/blender/editors/sculpt_paint/paint_image_2d.c
@@ -57,8 +57,6 @@
#include "UI_view2d.h"
-#include "GPU_draw.h"
-
#include "paint_intern.h"
/* Brush Painting for 2D image editor */
@@ -1784,7 +1782,7 @@ void paint_2d_redraw(const bContext *C, void *ps, bool final)
if (final) {
if (s->image && !(s->sima && s->sima->lock)) {
- GPU_free_image(s->image);
+ BKE_image_free_gputextures(s->image);
}
/* compositor listener deals with updating */
diff --git a/source/blender/editors/sculpt_paint/paint_image_proj.c b/source/blender/editors/sculpt_paint/paint_image_proj.c
index 5af3a3f4241..af2762889e8 100644
--- a/source/blender/editors/sculpt_paint/paint_image_proj.c
+++ b/source/blender/editors/sculpt_paint/paint_image_proj.c
@@ -100,8 +100,6 @@
#include "RNA_define.h"
#include "RNA_enum_types.h"
-#include "GPU_draw.h"
-
#include "IMB_colormanagement.h"
//#include "bmesh_tools.h"
@@ -6134,7 +6132,7 @@ static int texture_paint_camera_project_exec(bContext *C, wmOperator *op)
project_image_refresh_tagged(&ps);
for (a = 0; a < ps.image_tot; a++) {
- GPU_free_image(ps.projImages[a].ima);
+ BKE_image_free_gputextures(ps.projImages[a].ima);
WM_event_add_notifier(C, NC_IMAGE | NA_EDITED, ps.projImages[a].ima);
}
@@ -6175,7 +6173,7 @@ static bool texture_paint_image_from_view_poll(bContext *C)
CTX_wm_operator_poll_msg_set(C, "No 3D viewport found to create image from");
return false;
}
- if (G.background || !GPU_is_initialized()) {
+ if (G.background || !GPU_is_init()) {
return false;
}
return true;
diff --git a/source/blender/editors/sculpt_paint/paint_intern.h b/source/blender/editors/sculpt_paint/paint_intern.h
index 0d4e957c77b..feadeb28cd5 100644
--- a/source/blender/editors/sculpt_paint/paint_intern.h
+++ b/source/blender/editors/sculpt_paint/paint_intern.h
@@ -341,6 +341,7 @@ typedef enum {
void PAINT_OT_mask_flood_fill(struct wmOperatorType *ot);
void PAINT_OT_mask_lasso_gesture(struct wmOperatorType *ot);
+void PAINT_OT_mask_box_gesture(struct wmOperatorType *ot);
/* paint_curve.c */
void PAINTCURVE_OT_new(struct wmOperatorType *ot);
diff --git a/source/blender/editors/sculpt_paint/paint_mask.c b/source/blender/editors/sculpt_paint/paint_mask.c
index 6e0402fc6e0..c255cbcaaab 100644
--- a/source/blender/editors/sculpt_paint/paint_mask.c
+++ b/source/blender/editors/sculpt_paint/paint_mask.c
@@ -25,6 +25,7 @@
#include "DNA_meshdata_types.h"
#include "DNA_object_types.h"
+#include "DNA_vec_types.h"
#include "BLI_bitmap_draw_2d.h"
#include "BLI_lasso_2d.h"
@@ -290,27 +291,32 @@ static void mask_box_select_task_cb(void *__restrict userdata,
}
}
-bool ED_sculpt_mask_box_select(struct bContext *C, ViewContext *vc, const rcti *rect, bool select)
+static int paint_mask_gesture_box_exec(bContext *C, wmOperator *op)
{
+ ViewContext vc;
Depsgraph *depsgraph = CTX_data_ensure_evaluated_depsgraph(C);
- Sculpt *sd = vc->scene->toolsettings->sculpt;
+ ED_view3d_viewcontext_init(C, &vc, depsgraph);
+
+ Sculpt *sd = vc.scene->toolsettings->sculpt;
BoundBox bb;
float clip_planes[4][4];
float clip_planes_final[4][4];
- ARegion *region = vc->region;
- Object *ob = vc->obact;
- PaintMaskFloodMode mode;
+ ARegion *region = vc.region;
+ Object *ob = vc.obact;
bool multires;
PBVH *pbvh;
PBVHNode **nodes;
int totnode;
int symm = sd->paint.symmetry_flags & PAINT_SYMM_AXIS_ALL;
- mode = PAINT_MASK_FLOOD_VALUE;
- float value = select ? 1.0f : 0.0f;
+ const PaintMaskFloodMode mode = RNA_enum_get(op->ptr, "mode");
+ const float value = RNA_float_get(op->ptr, "value");
+
+ rcti rect;
+ WM_operator_properties_border_to_rcti(op, &rect);
/* Transform the clip planes in object space. */
- ED_view3d_clipping_calc(&bb, clip_planes, vc->region, vc->obact, rect);
+ ED_view3d_clipping_calc(&bb, clip_planes, vc.region, vc.obact, &rect);
BKE_sculpt_update_object_for_edit(depsgraph, ob, false, true, false);
pbvh = ob->sculpt->pbvh;
@@ -589,3 +595,33 @@ void PAINT_OT_mask_lasso_gesture(wmOperatorType *ot)
0.0f,
1.0f);
}
+
+void PAINT_OT_mask_box_gesture(wmOperatorType *ot)
+{
+ ot->name = "Mask Box Gesture";
+ ot->idname = "PAINT_OT_mask_box_gesture";
+ ot->description = "Add mask within the box as you move the brush";
+
+ ot->invoke = WM_gesture_box_invoke;
+ ot->modal = WM_gesture_box_modal;
+ ot->exec = paint_mask_gesture_box_exec;
+
+ ot->poll = SCULPT_mode_poll;
+
+ ot->flag = OPTYPE_REGISTER;
+
+ /* Properties. */
+ WM_operator_properties_border(ot);
+
+ RNA_def_enum(ot->srna, "mode", mode_items, PAINT_MASK_FLOOD_VALUE, "Mode", NULL);
+ RNA_def_float(
+ ot->srna,
+ "value",
+ 1.0f,
+ 0.0f,
+ 1.0f,
+ "Value",
+ "Mask level to use when mode is 'Value'; zero means no masking and one is fully masked",
+ 0.0f,
+ 1.0f);
+}
diff --git a/source/blender/editors/sculpt_paint/paint_ops.c b/source/blender/editors/sculpt_paint/paint_ops.c
index d65f158174f..0fe6e259d8d 100644
--- a/source/blender/editors/sculpt_paint/paint_ops.c
+++ b/source/blender/editors/sculpt_paint/paint_ops.c
@@ -1356,6 +1356,7 @@ void ED_operatortypes_paint(void)
/* paint masking */
WM_operatortype_append(PAINT_OT_mask_flood_fill);
WM_operatortype_append(PAINT_OT_mask_lasso_gesture);
+ WM_operatortype_append(PAINT_OT_mask_box_gesture);
}
void ED_keymap_paint(wmKeyConfig *keyconf)
diff --git a/source/blender/editors/sculpt_paint/paint_stroke.c b/source/blender/editors/sculpt_paint/paint_stroke.c
index caecc7b708a..b9361726826 100644
--- a/source/blender/editors/sculpt_paint/paint_stroke.c
+++ b/source/blender/editors/sculpt_paint/paint_stroke.c
@@ -920,9 +920,9 @@ PaintStroke *paint_stroke_new(bContext *C,
ups->average_stroke_counter = 0;
/* initialize here to avoid initialization conflict with threaded strokes */
- BKE_curvemapping_initialize(br->curve);
+ BKE_curvemapping_init(br->curve);
if (p->flags & PAINT_USE_CAVITY_MASK) {
- BKE_curvemapping_initialize(p->cavity_curve);
+ BKE_curvemapping_init(p->cavity_curve);
}
BKE_paint_set_overlay_override(br->overlay_flags);
diff --git a/source/blender/editors/sculpt_paint/paint_vertex_weight_ops.c b/source/blender/editors/sculpt_paint/paint_vertex_weight_ops.c
index 6965946d2ce..83d76c166ce 100644
--- a/source/blender/editors/sculpt_paint/paint_vertex_weight_ops.c
+++ b/source/blender/editors/sculpt_paint/paint_vertex_weight_ops.c
@@ -811,7 +811,7 @@ static int paint_weight_gradient_exec(bContext *C, wmOperator *op)
VPaint *wp = ts->wpaint;
struct Brush *brush = BKE_paint_brush(&wp->paint);
- BKE_curvemapping_initialize(brush->curve);
+ BKE_curvemapping_init(brush->curve);
data.brush = brush;
data.weightpaint = BKE_brush_weight_get(scene, brush);
diff --git a/source/blender/editors/sculpt_paint/sculpt.c b/source/blender/editors/sculpt_paint/sculpt.c
index e838d87aeff..cde4039d20f 100644
--- a/source/blender/editors/sculpt_paint/sculpt.c
+++ b/source/blender/editors/sculpt_paint/sculpt.c
@@ -196,7 +196,7 @@ void SCULPT_vertex_normal_get(SculptSession *ss, int index, float no[3])
}
}
-static const float *sculpt_vertex_persistent_co_get(SculptSession *ss, int index)
+const float *SCULPT_vertex_persistent_co_get(SculptSession *ss, int index)
{
if (ss->persistent_base) {
return ss->persistent_base[index].co;
@@ -204,7 +204,7 @@ static const float *sculpt_vertex_persistent_co_get(SculptSession *ss, int index
return SCULPT_vertex_co_get(ss, index);
}
-static void sculpt_vertex_persistent_normal_get(SculptSession *ss, int index, float no[3])
+void SCULPT_vertex_persistent_normal_get(SculptSession *ss, int index, float no[3])
{
if (ss->persistent_base) {
copy_v3_v3(no, ss->persistent_base[index].no);
@@ -2966,7 +2966,7 @@ static void do_draw_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnode)
/* XXX - this shouldn't be necessary, but sculpting crashes in blender2.8 otherwise
* initialize before threads so they can do curve mapping. */
- BKE_curvemapping_initialize(brush->curve);
+ BKE_curvemapping_init(brush->curve);
/* Threaded loop over nodes. */
SculptThreadedTaskData data = {
@@ -3043,7 +3043,7 @@ static void do_draw_sharp_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int to
/* XXX - this shouldn't be necessary, but sculpting crashes in blender2.8 otherwise
* initialize before threads so they can do curve mapping. */
- BKE_curvemapping_initialize(brush->curve);
+ BKE_curvemapping_init(brush->curve);
/* Threaded loop over nodes. */
SculptThreadedTaskData data = {
@@ -3273,7 +3273,7 @@ static void do_slide_relax_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int t
return;
}
- BKE_curvemapping_initialize(brush->curve);
+ BKE_curvemapping_init(brush->curve);
SculptThreadedTaskData data = {
.sd = sd,
@@ -4341,9 +4341,9 @@ static void do_layer_brush_task_cb_ex(void *__restrict userdata,
float normal[3];
if (use_persistent_base) {
- sculpt_vertex_persistent_normal_get(ss, vi, normal);
+ SCULPT_vertex_persistent_normal_get(ss, vi, normal);
mul_v3_fl(normal, brush->height);
- madd_v3_v3v3fl(final_co, sculpt_vertex_persistent_co_get(ss, vi), normal, *disp_factor);
+ madd_v3_v3v3fl(final_co, SCULPT_vertex_persistent_co_get(ss, vi), normal, *disp_factor);
}
else {
normal_short_to_float_v3(normal, orig_data.no);
@@ -6390,7 +6390,7 @@ static void sculpt_update_cache_invariants(
brush = br;
cache->saved_smooth_size = BKE_brush_size_get(scene, brush);
BKE_brush_size_set(scene, brush, size);
- BKE_curvemapping_initialize(brush->curve);
+ BKE_curvemapping_init(brush->curve);
}
}
}
@@ -6458,7 +6458,7 @@ static void sculpt_update_cache_invariants(
#define PIXEL_INPUT_THRESHHOLD 5
if (brush->sculpt_tool == SCULPT_TOOL_ROTATE) {
- cache->dial = BLI_dial_initialize(cache->initial_mouse, PIXEL_INPUT_THRESHHOLD);
+ cache->dial = BLI_dial_init(cache->initial_mouse, PIXEL_INPUT_THRESHHOLD);
}
#undef PIXEL_INPUT_THRESHHOLD
diff --git a/source/blender/editors/sculpt_paint/sculpt_cloth.c b/source/blender/editors/sculpt_paint/sculpt_cloth.c
index 4232be91034..51b2d50e73b 100644
--- a/source/blender/editors/sculpt_paint/sculpt_cloth.c
+++ b/source/blender/editors/sculpt_paint/sculpt_cloth.c
@@ -85,7 +85,6 @@
#include "RNA_access.h"
#include "RNA_define.h"
-#include "GPU_draw.h"
#include "GPU_immediate.h"
#include "GPU_immediate_util.h"
#include "GPU_matrix.h"
@@ -101,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
@@ -113,19 +134,8 @@ static bool cloth_brush_sim_has_length_constraint(SculptClothSimulation *cloth_s
return BLI_edgeset_haskey(cloth_sim->created_length_constraints, v1, v2);
}
-static void cloth_brush_add_length_constraint(SculptSession *ss,
- SculptClothSimulation *cloth_sim,
- const int v1,
- const int v2)
+static void cloth_brush_reallocate_constraints(SculptClothSimulation *cloth_sim)
{
- cloth_sim->length_constraints[cloth_sim->tot_length_constraints].v1 = v1;
- cloth_sim->length_constraints[cloth_sim->tot_length_constraints].v2 = v2;
- cloth_sim->length_constraints[cloth_sim->tot_length_constraints].length = len_v3v3(
- SCULPT_vertex_co_get(ss, v1), SCULPT_vertex_co_get(ss, v2));
-
- cloth_sim->tot_length_constraints++;
-
- /* Reallocation if the array capacity is exceeded. */
if (cloth_sim->tot_length_constraints >= cloth_sim->capacity_length_constraints) {
cloth_sim->capacity_length_constraints += CLOTH_LENGTH_CONSTRAINTS_BLOCK;
cloth_sim->length_constraints = MEM_reallocN_id(cloth_sim->length_constraints,
@@ -133,23 +143,115 @@ static void cloth_brush_add_length_constraint(SculptSession *ss,
sizeof(SculptClothLengthConstraint),
"length constraints");
}
+}
+
+static void cloth_brush_add_length_constraint(SculptSession *ss,
+ SculptClothSimulation *cloth_sim,
+ const int v1,
+ const int v2,
+ const bool use_persistent)
+{
+ SculptClothLengthConstraint *length_constraint =
+ &cloth_sim->length_constraints[cloth_sim->tot_length_constraints];
+
+ length_constraint->elem_index_a = v1;
+ length_constraint->elem_index_b = v2;
+
+ length_constraint->elem_position_a = cloth_sim->pos[v1];
+ length_constraint->elem_position_b = cloth_sim->pos[v2];
+
+ if (use_persistent) {
+ length_constraint->length = len_v3v3(SCULPT_vertex_persistent_co_get(ss, v1),
+ SCULPT_vertex_persistent_co_get(ss, v2));
+ }
+ else {
+ length_constraint->length = len_v3v3(SCULPT_vertex_co_get(ss, v1),
+ SCULPT_vertex_co_get(ss, v2));
+ }
+ length_constraint->strength = 1.0f;
+
+ cloth_sim->tot_length_constraints++;
+
+ /* Reallocation if the array capacity is exceeded. */
+ cloth_brush_reallocate_constraints(cloth_sim);
/* Add the constraint to the GSet to avoid creating it again. */
BLI_edgeset_add(cloth_sim->created_length_constraints, v1, v2);
}
+static void cloth_brush_add_softbody_constraint(SculptClothSimulation *cloth_sim,
+ const int v,
+ const float strength)
+{
+ SculptClothLengthConstraint *length_constraint =
+ &cloth_sim->length_constraints[cloth_sim->tot_length_constraints];
+
+ length_constraint->elem_index_a = v;
+ length_constraint->elem_index_b = v;
+
+ length_constraint->elem_position_a = cloth_sim->pos[v];
+ length_constraint->elem_position_b = cloth_sim->init_pos[v];
+
+ length_constraint->length = 0.0f;
+ length_constraint->strength = strength;
+
+ cloth_sim->tot_length_constraints++;
+
+ /* Reallocation if the array capacity is exceeded. */
+ cloth_brush_reallocate_constraints(cloth_sim);
+}
+
+static void cloth_brush_add_deformation_constraint(SculptClothSimulation *cloth_sim,
+ const int v,
+ const float strength)
+{
+ SculptClothLengthConstraint *length_constraint =
+ &cloth_sim->length_constraints[cloth_sim->tot_length_constraints];
+
+ length_constraint->elem_index_a = v;
+ length_constraint->elem_index_b = v;
+
+ length_constraint->elem_position_a = cloth_sim->pos[v];
+ length_constraint->elem_position_b = cloth_sim->deformation_pos[v];
+
+ length_constraint->length = 0.0f;
+ length_constraint->strength = strength;
+
+ cloth_sim->tot_length_constraints++;
+
+ /* Reallocation if the array capacity is exceeded. */
+ cloth_brush_reallocate_constraints(cloth_sim);
+}
+
static void do_cloth_brush_build_constraints_task_cb_ex(
void *__restrict userdata, const int n, const TaskParallelTLS *__restrict UNUSED(tls))
{
SculptThreadedTaskData *data = userdata;
SculptSession *ss = data->ob->sculpt;
+ const Brush *brush = data->brush;
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
+ * positions. */
+ const bool cloth_is_deform_brush = ss->cache != NULL && brush != NULL &&
+ SCULPT_is_cloth_deform_brush(brush);
+ float radius_squared = 0.0f;
+ if (cloth_is_deform_brush) {
+ radius_squared = ss->cache->initial_radius * ss->cache->initial_radius;
+ }
+
+ const float cloth_sim_radius_squared = data->cloth_sim_radius * data->cloth_sim_radius;
+
BKE_pbvh_vertex_iter_begin(ss->pbvh, data->nodes[n], vd, PBVH_ITER_UNIQUE)
{
- if (len_squared_v3v3(vd.co, data->cloth_sim_initial_location) <
- data->cloth_sim_radius * data->cloth_sim_radius) {
+ const float len_squared = len_squared_v3v3(vd.co, data->cloth_sim_initial_location);
+ if (len_squared < cloth_sim_radius_squared) {
SculptVertexNeighborIter ni;
int build_indices[CLOTH_MAX_CONSTRAINTS_PER_VERTEX];
@@ -162,6 +264,11 @@ static void do_cloth_brush_build_constraints_task_cb_ex(
}
SCULPT_VERTEX_NEIGHBORS_ITER_END(ni);
+ if (brush->cloth_constraint_softbody_strength > 0.0f) {
+ cloth_brush_add_softbody_constraint(
+ data->cloth_sim, vd.index, brush->cloth_constraint_softbody_strength);
+ }
+
/* As we don't know the order of the neighbor vertices, we create all possible combinations
* between the neighbor and the original vertex as length constraints. */
/* This results on a pattern that contains structural, shear and bending constraints for all
@@ -172,35 +279,29 @@ static void do_cloth_brush_build_constraints_task_cb_ex(
if (c_i != c_j && !cloth_brush_sim_has_length_constraint(
data->cloth_sim, build_indices[c_i], build_indices[c_j])) {
cloth_brush_add_length_constraint(
- ss, data->cloth_sim, build_indices[c_i], build_indices[c_j]);
+ ss, data->cloth_sim, build_indices[c_i], build_indices[c_j], use_persistent);
}
}
}
}
- }
- 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 (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 (distance > limit) {
- /* Outiside the limits. */
- return 0.0f;
- }
- if (distance < falloff) {
- /* Before the falloff area. */
- return 1.0f;
+ 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);
+ }
+ }
}
- /* 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;
+ BKE_pbvh_vertex_iter_end;
}
static void cloth_brush_apply_force_to_vertex(SculptSession *UNUSED(ss),
@@ -323,9 +424,10 @@ static void do_cloth_brush_apply_forces_task_cb_ex(void *__restrict userdata,
mul_v3_v3fl(force, offset, -fade);
break;
case BRUSH_CLOTH_DEFORM_GRAB:
- /* Grab writes the positions in the simulation directly without applying forces. */
- madd_v3_v3v3fl(
- cloth_sim->pos[vd.index], orig_data.co, ss->cache->grab_delta_symmetry, fade);
+ madd_v3_v3v3fl(cloth_sim->deformation_pos[vd.index],
+ orig_data.co,
+ ss->cache->grab_delta_symmetry,
+ fade);
zero_v3(force);
break;
case BRUSH_CLOTH_DEFORM_PINCH_POINT:
@@ -367,6 +469,7 @@ static void do_cloth_brush_apply_forces_task_cb_ex(void *__restrict userdata,
}
static SculptClothSimulation *cloth_brush_simulation_create(SculptSession *ss,
+ Brush *brush,
const float cloth_mass,
const float cloth_damping)
{
@@ -380,12 +483,20 @@ static SculptClothSimulation *cloth_brush_simulation_create(SculptSession *ss,
"cloth length constraints");
cloth_sim->capacity_length_constraints = CLOTH_LENGTH_CONSTRAINTS_BLOCK;
- cloth_sim->acceleration = MEM_callocN(sizeof(float) * 3 * totverts, "cloth sim acceleration");
- cloth_sim->pos = MEM_callocN(sizeof(float) * 3 * totverts, "cloth sim pos");
- cloth_sim->prev_pos = MEM_callocN(sizeof(float) * 3 * totverts, "cloth sim prev pos");
- cloth_sim->init_pos = MEM_callocN(sizeof(float) * 3 * totverts, "cloth sim init pos");
- cloth_sim->length_constraint_tweak = MEM_callocN(sizeof(float) * totverts,
- "cloth sim length tweak");
+ cloth_sim->acceleration = MEM_calloc_arrayN(
+ totverts, 3 * sizeof(float), "cloth sim acceleration");
+ cloth_sim->pos = MEM_calloc_arrayN(totverts, 3 * sizeof(float), "cloth sim pos");
+ cloth_sim->prev_pos = MEM_calloc_arrayN(totverts, 3 * sizeof(float), "cloth sim prev pos");
+ cloth_sim->init_pos = MEM_calloc_arrayN(totverts, 3 * sizeof(float), "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, 3 * sizeof(float), "cloth sim deformation positions");
+ }
cloth_sim->mass = cloth_mass;
cloth_sim->damping = cloth_damping;
@@ -484,11 +595,11 @@ static void cloth_brush_satisfy_constraints(SculptSession *ss,
for (int i = 0; i < cloth_sim->tot_length_constraints; i++) {
const SculptClothLengthConstraint *constraint = &cloth_sim->length_constraints[i];
- const int v1 = constraint->v1;
- const int v2 = constraint->v2;
+ const int v1 = constraint->elem_index_a;
+ const int v2 = constraint->elem_index_b;
float v1_to_v2[3];
- sub_v3_v3v3(v1_to_v2, cloth_sim->pos[v2], cloth_sim->pos[v1]);
+ sub_v3_v3v3(v1_to_v2, constraint->elem_position_b, constraint->elem_position_a);
const float current_distance = len_v3(v1_to_v2);
float correction_vector[3];
float correction_vector_half[3];
@@ -524,8 +635,14 @@ static void cloth_brush_satisfy_constraints(SculptSession *ss,
cloth_sim->init_pos[v2]) :
1.0f;
- madd_v3_v3fl(cloth_sim->pos[v1], correction_vector_half, 1.0f * mask_v1 * sim_factor_v1);
- madd_v3_v3fl(cloth_sim->pos[v2], correction_vector_half, -1.0f * mask_v2 * sim_factor_v2);
+ madd_v3_v3fl(cloth_sim->pos[v1],
+ correction_vector_half,
+ 1.0f * mask_v1 * sim_factor_v1 * constraint->strength);
+ if (v1 != v2) {
+ madd_v3_v3fl(cloth_sim->pos[v2],
+ correction_vector_half,
+ -1.0f * mask_v2 * sim_factor_v2 * constraint->strength);
+ }
}
}
}
@@ -577,7 +694,7 @@ static void cloth_brush_apply_brush_foces(Sculpt *sd, Object *ob, PBVHNode **nod
.mat = imat,
};
- BKE_curvemapping_initialize(brush->curve);
+ BKE_curvemapping_init(brush->curve);
/* Init the grab delta. */
copy_v3_v3(grab_delta, ss->cache->grab_delta_symmetry);
@@ -649,10 +766,16 @@ 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) {
ss->cache->cloth_sim = cloth_brush_simulation_create(
- ss, brush->cloth_mass, brush->cloth_damping);
+ ss, brush, brush->cloth_mass, brush->cloth_damping);
+
+ const bool is_cloth_deform_brush = SCULPT_is_cloth_deform_brush(brush);
+
for (int i = 0; i < totverts; i++) {
copy_v3_v3(ss->cache->cloth_sim->prev_pos[i], SCULPT_vertex_co_get(ss, i));
copy_v3_v3(ss->cache->cloth_sim->init_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));
+ }
}
}
@@ -684,6 +807,7 @@ void SCULPT_cloth_simulation_free(struct SculptClothSimulation *cloth_sim)
MEM_SAFE_FREE(cloth_sim->acceleration);
MEM_SAFE_FREE(cloth_sim->length_constraints);
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);
}
@@ -913,7 +1037,7 @@ 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");
- ss->filter_cache->cloth_sim = cloth_brush_simulation_create(ss, cloth_mass, cloth_damping);
+ ss->filter_cache->cloth_sim = cloth_brush_simulation_create(ss, NULL, cloth_mass, cloth_damping);
copy_v3_v3(ss->filter_cache->cloth_sim_pinch_point, SCULPT_active_vertex_co_get(ss));
const int totverts = SCULPT_vertex_count_get(ss);
diff --git a/source/blender/editors/sculpt_paint/sculpt_face_set.c b/source/blender/editors/sculpt_paint/sculpt_face_set.c
index 1940b007cb0..5cc32be331e 100644
--- a/source/blender/editors/sculpt_paint/sculpt_face_set.c
+++ b/source/blender/editors/sculpt_paint/sculpt_face_set.c
@@ -192,7 +192,7 @@ void SCULPT_do_draw_face_sets_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, in
SculptSession *ss = ob->sculpt;
Brush *brush = BKE_paint_brush(&sd->paint);
- BKE_curvemapping_initialize(brush->curve);
+ BKE_curvemapping_init(brush->curve);
/* Threaded loop over nodes. */
SculptThreadedTaskData data = {
diff --git a/source/blender/editors/sculpt_paint/sculpt_filter_color.c b/source/blender/editors/sculpt_paint/sculpt_filter_color.c
index ef0897ce70e..912dfd808b0 100644
--- a/source/blender/editors/sculpt_paint/sculpt_filter_color.c
+++ b/source/blender/editors/sculpt_paint/sculpt_filter_color.c
@@ -80,7 +80,7 @@ typedef enum eSculptColorFilterTypes {
COLOR_FILTER_SMOOTH,
} eSculptColorFilterTypes;
-EnumPropertyItem prop_color_filter_types[] = {
+static EnumPropertyItem prop_color_filter_types[] = {
{COLOR_FILTER_FILL, "FILL", 0, "Fill", "Fill with a specific color"},
{COLOR_FILTER_HUE, "HUE", 0, "Hue", "Change hue"},
{COLOR_FILTER_SATURATION, "SATURATION", 0, "Saturation", "Change saturation"},
diff --git a/source/blender/editors/sculpt_paint/sculpt_intern.h b/source/blender/editors/sculpt_paint/sculpt_intern.h
index f834ab7b179..47e6fb55d81 100644
--- a/source/blender/editors/sculpt_paint/sculpt_intern.h
+++ b/source/blender/editors/sculpt_paint/sculpt_intern.h
@@ -98,6 +98,9 @@ void SCULPT_vertex_normal_get(SculptSession *ss, int index, float no[3]);
float SCULPT_vertex_mask_get(struct SculptSession *ss, int index);
const float *SCULPT_vertex_color_get(SculptSession *ss, int index);
+const float *SCULPT_vertex_persistent_co_get(SculptSession *ss, int index);
+void SCULPT_vertex_persistent_normal_get(SculptSession *ss, int index, float no[3]);
+
#define SCULPT_VERTEX_NEIGHBOR_FIXED_CAPACITY 256
typedef struct SculptVertexNeighborIter {
/* Storage */
diff --git a/source/blender/editors/sculpt_paint/sculpt_multiplane_scrape.c b/source/blender/editors/sculpt_paint/sculpt_multiplane_scrape.c
index b52036d753c..bc3f8537289 100644
--- a/source/blender/editors/sculpt_paint/sculpt_multiplane_scrape.c
+++ b/source/blender/editors/sculpt_paint/sculpt_multiplane_scrape.c
@@ -47,7 +47,6 @@
#include "paint_intern.h"
#include "sculpt_intern.h"
-#include "GPU_draw.h"
#include "GPU_immediate.h"
#include "GPU_immediate_util.h"
#include "GPU_matrix.h"
diff --git a/source/blender/editors/sculpt_paint/sculpt_paint_color.c b/source/blender/editors/sculpt_paint/sculpt_paint_color.c
index f01a914fdd3..00a59949130 100644
--- a/source/blender/editors/sculpt_paint/sculpt_paint_color.c
+++ b/source/blender/editors/sculpt_paint/sculpt_paint_color.c
@@ -255,7 +255,7 @@ void SCULPT_do_paint_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnode
return;
}
- BKE_curvemapping_initialize(brush->curve);
+ BKE_curvemapping_init(brush->curve);
float area_no[3];
float mat[4][4];
@@ -468,7 +468,7 @@ void SCULPT_do_smear_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnode
}
}
- BKE_curvemapping_initialize(brush->curve);
+ BKE_curvemapping_init(brush->curve);
SculptThreadedTaskData data = {
.sd = sd,
diff --git a/source/blender/editors/sculpt_paint/sculpt_pose.c b/source/blender/editors/sculpt_paint/sculpt_pose.c
index a338b5346af..976006b3958 100644
--- a/source/blender/editors/sculpt_paint/sculpt_pose.c
+++ b/source/blender/editors/sculpt_paint/sculpt_pose.c
@@ -1000,7 +1000,7 @@ void SCULPT_pose_brush_init(Sculpt *sd, Object *ob, SculptSession *ss, Brush *br
static void sculpt_pose_do_translate_deform(SculptSession *ss, Brush *brush)
{
SculptPoseIKChain *ik_chain = ss->cache->pose_ik_chain;
- BKE_curvemapping_initialize(brush->curve);
+ BKE_curvemapping_init(brush->curve);
pose_solve_translate_chain(ik_chain, ss->cache->grab_delta);
}
@@ -1041,7 +1041,7 @@ static void sculpt_pose_do_twist_deform(SculptSession *ss, Brush *brush)
/* Calculate the maximum roll. 0.02 radians per pixel works fine. */
float roll = (ss->cache->initial_mouse[0] - ss->cache->mouse[0]) * ss->cache->bstrength * 0.02f;
- BKE_curvemapping_initialize(brush->curve);
+ BKE_curvemapping_init(brush->curve);
pose_solve_roll_chain(ik_chain, brush, roll);
}
diff --git a/source/blender/editors/sculpt_paint/sculpt_uv.c b/source/blender/editors/sculpt_paint/sculpt_uv.c
index 4b3df2dfea2..be509f4aed6 100644
--- a/source/blender/editors/sculpt_paint/sculpt_uv.c
+++ b/source/blender/editors/sculpt_paint/sculpt_uv.c
@@ -488,7 +488,7 @@ static UvSculptData *uv_sculpt_stroke_init(bContext *C, wmOperator *op, const wm
op->customdata = data;
- BKE_curvemapping_initialize(ts->uvsculpt->paint.brush->curve);
+ BKE_curvemapping_init(ts->uvsculpt->paint.brush->curve);
if (data) {
int counter = 0, i;