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:
authorCampbell Barton <ideasman42@gmail.com>2017-10-05 16:18:11 +0300
committerCampbell Barton <ideasman42@gmail.com>2017-10-05 17:20:31 +0300
commitd8509b349d1d6219923615e7af81267bb6f06b68 (patch)
treeaad149802beb5dc7a19f96a3f78400ffc52ca8c9
parent56a07ba70650b1e65f5979eab39730a1db314c56 (diff)
Sculpt Mode: 2D falloff option
This makes brush influence into a tube instead of a sphere. It can be used along the outline of a mesh to adjust it's silhouette. Note that all this takes advantage of changes from vertex paint, from testing this seems useful so exposing from the brush options.
-rw-r--r--release/scripts/startup/bl_ui/space_view3d_toolbar.py11
-rw-r--r--source/blender/blenkernel/BKE_pbvh.h2
-rw-r--r--source/blender/blenkernel/intern/pbvh_bmesh.c74
-rw-r--r--source/blender/blenloader/intern/versioning_270.c2
-rw-r--r--source/blender/editors/sculpt_paint/paint_vertex.c34
-rw-r--r--source/blender/editors/sculpt_paint/sculpt.c337
-rw-r--r--source/blender/editors/sculpt_paint/sculpt_intern.h9
-rw-r--r--source/blender/makesdna/DNA_brush_types.h13
-rw-r--r--source/blender/makesdna/DNA_scene_types.h9
-rw-r--r--source/blender/makesrna/intern/rna_brush.c6
-rw-r--r--source/blender/makesrna/intern/rna_sculpt_paint.c12
11 files changed, 304 insertions, 205 deletions
diff --git a/release/scripts/startup/bl_ui/space_view3d_toolbar.py b/release/scripts/startup/bl_ui/space_view3d_toolbar.py
index 5aca4c554d8..d795e09e435 100644
--- a/release/scripts/startup/bl_ui/space_view3d_toolbar.py
+++ b/release/scripts/startup/bl_ui/space_view3d_toolbar.py
@@ -1083,6 +1083,8 @@ class VIEW3D_PT_tools_brush(Panel, View3DPaintPanel):
row = col.row()
row.prop(brush, "use_frontface", text="Front Faces Only")
+ col.row().prop(brush, "use_projected", expand=True)
+
# direction
col.separator()
col.row().prop(brush, "direction", expand=True)
@@ -1137,6 +1139,8 @@ class VIEW3D_PT_tools_brush(Panel, View3DPaintPanel):
col.prop(brush, "use_accumulate")
col.separator()
+ col.row().prop(brush, "use_projected")
+
col = layout.column()
col.prop(toolsettings, "use_auto_normalize", text="Auto Normalize")
col.prop(toolsettings, "use_multipaint", text="Multi-Paint")
@@ -1168,9 +1172,12 @@ class VIEW3D_PT_tools_brush(Panel, View3DPaintPanel):
# row.prop(brush, "use_pressure_jitter", toggle=True, text="")
col.separator()
col.prop(brush, "vertex_tool", text="Blend")
+
col.prop(brush, "use_accumulate")
col.prop(brush, "use_alpha")
+ col.row().prop("use_projected")
+
col.separator()
col.template_ID(settings, "palette", new="palette.new")
@@ -1763,8 +1770,6 @@ class VIEW3D_PT_tools_weightpaint_options(Panel, View3DPaintPanel):
col = layout.column()
col.label("Falloff:")
row = col.row()
- row.prop(wpaint, "falloff_shape", expand=True)
- row = col.row()
row.prop(wpaint, "use_backface_culling")
row = col.row()
row.prop(wpaint, "use_normal_falloff")
@@ -1806,8 +1811,6 @@ class VIEW3D_PT_tools_vertexpaint(Panel, View3DPaintPanel):
col = layout.column()
col.label("Falloff:")
row = col.row()
- row.prop(vpaint, "falloff_shape", expand=True)
- row = col.row()
row.prop(vpaint, "use_backface_culling")
row = col.row()
row.prop(vpaint, "use_normal_falloff")
diff --git a/source/blender/blenkernel/BKE_pbvh.h b/source/blender/blenkernel/BKE_pbvh.h
index c6b9b6a4de6..2daa2ef7182 100644
--- a/source/blender/blenkernel/BKE_pbvh.h
+++ b/source/blender/blenkernel/BKE_pbvh.h
@@ -168,7 +168,7 @@ typedef enum {
bool BKE_pbvh_bmesh_update_topology(
PBVH *bvh, PBVHTopologyUpdateMode mode,
const float center[3], const float view_normal[3],
- float radius);
+ float radius, const bool use_frontface, const bool use_projected);
/* Node Access */
diff --git a/source/blender/blenkernel/intern/pbvh_bmesh.c b/source/blender/blenkernel/intern/pbvh_bmesh.c
index 4bfda8ebf28..187891e7210 100644
--- a/source/blender/blenkernel/intern/pbvh_bmesh.c
+++ b/source/blender/blenkernel/intern/pbvh_bmesh.c
@@ -718,20 +718,24 @@ static void pbvh_bmesh_node_drop_orig(PBVHNode *node)
/****************************** EdgeQueue *****************************/
-typedef struct {
+struct EdgeQueue;
+
+typedef struct EdgeQueue {
Heap *heap;
const float *center;
+ float center_proj[3]; /* for when we use projected coords. */
float radius_squared;
float limit_len_squared;
#ifdef USE_EDGEQUEUE_EVEN_SUBDIV
float limit_len;
#endif
-#ifdef USE_EDGEQUEUE_FRONTFACE
+ bool (*edge_queue_tri_in_range)(const struct EdgeQueue *q, BMFace *f);
+
const float *view_normal;
+#ifdef USE_EDGEQUEUE_FRONTFACE
unsigned int use_view_normal : 1;
#endif
-
} EdgeQueue;
typedef struct {
@@ -785,7 +789,6 @@ static bool edge_queue_tri_in_sphere(const EdgeQueue *q, BMFace *f)
float c[3];
/* Get closest point in triangle to sphere center */
- // BM_iter_as_array(NULL, BM_VERTS_OF_FACE, f, (void **)v_tri, 3);
BM_face_as_array_vert_tri(f, v_tri);
closest_on_tri_to_point_v3(c, q->center, v_tri[0]->co, v_tri[1]->co, v_tri[2]->co);
@@ -794,6 +797,25 @@ static bool edge_queue_tri_in_sphere(const EdgeQueue *q, BMFace *f)
return len_squared_v3v3(q->center, c) <= q->radius_squared;
}
+static bool edge_queue_tri_in_circle(const EdgeQueue *q, BMFace *f)
+{
+ BMVert *v_tri[3];
+ float c[3];
+ float tri_proj[3][3];
+
+ /* Get closest point in triangle to sphere center */
+ BM_face_as_array_vert_tri(f, v_tri);
+
+ project_plane_normalized_v3_v3v3(tri_proj[0], v_tri[0]->co, q->view_normal);
+ project_plane_normalized_v3_v3v3(tri_proj[1], v_tri[1]->co, q->view_normal);
+ project_plane_normalized_v3_v3v3(tri_proj[2], v_tri[2]->co, q->view_normal);
+
+ closest_on_tri_to_point_v3(c, q->center_proj, tri_proj[0], tri_proj[1], tri_proj[2]);
+
+ /* Check if triangle intersects the sphere */
+ return len_squared_v3v3(q->center_proj, c) <= q->radius_squared;
+}
+
/* Return true if the vertex mask is less than 1.0, false otherwise */
static bool check_mask(EdgeQueueContext *eq_ctx, BMVert *v)
{
@@ -929,7 +951,7 @@ static void long_edge_queue_face_add(
}
#endif
- if (edge_queue_tri_in_sphere(eq_ctx->q, f)) {
+ if (eq_ctx->q->edge_queue_tri_in_range(eq_ctx->q, f)) {
/* Check each edge of the face */
BMLoop *l_first = BM_FACE_FIRST_LOOP(f);
BMLoop *l_iter = l_first;
@@ -960,7 +982,7 @@ static void short_edge_queue_face_add(
}
#endif
- if (edge_queue_tri_in_sphere(eq_ctx->q, f)) {
+ if (eq_ctx->q->edge_queue_tri_in_range(eq_ctx->q, f)) {
BMLoop *l_iter;
BMLoop *l_first;
@@ -984,7 +1006,7 @@ static void short_edge_queue_face_add(
static void long_edge_queue_create(
EdgeQueueContext *eq_ctx,
PBVH *bvh, const float center[3], const float view_normal[3],
- float radius)
+ float radius, const bool use_frontface, const bool use_projected)
{
eq_ctx->q->heap = BLI_heap_new();
eq_ctx->q->center = center;
@@ -994,13 +1016,22 @@ static void long_edge_queue_create(
eq_ctx->q->limit_len = bvh->bm_max_edge_len;
#endif
-#ifdef USE_EDGEQUEUE_FRONTFACE
eq_ctx->q->view_normal = view_normal;
- eq_ctx->q->use_view_normal = (view_normal != NULL);
+
+#ifdef USE_EDGEQUEUE_FRONTFACE
+ eq_ctx->q->use_view_normal = use_frontface;
#else
- UNUSED_VARS(view_normal);
+ UNUSED_VARS(use_frontface);
#endif
+ if (use_projected) {
+ eq_ctx->q->edge_queue_tri_in_range = edge_queue_tri_in_circle;
+ project_plane_normalized_v3_v3v3(eq_ctx->q->center_proj, center, view_normal);
+ }
+ else {
+ eq_ctx->q->edge_queue_tri_in_range = edge_queue_tri_in_sphere;
+ }
+
#ifdef USE_EDGEQUEUE_TAG_VERIFY
pbvh_bmesh_edge_tag_verify(bvh);
#endif
@@ -1037,7 +1068,7 @@ static void long_edge_queue_create(
static void short_edge_queue_create(
EdgeQueueContext *eq_ctx,
PBVH *bvh, const float center[3], const float view_normal[3],
- float radius)
+ float radius, const bool use_frontface, const bool use_projected)
{
eq_ctx->q->heap = BLI_heap_new();
eq_ctx->q->center = center;
@@ -1047,13 +1078,22 @@ static void short_edge_queue_create(
eq_ctx->q->limit_len = bvh->bm_min_edge_len;
#endif
-#ifdef USE_EDGEQUEUE_FRONTFACE
eq_ctx->q->view_normal = view_normal;
- eq_ctx->q->use_view_normal = (view_normal != NULL);
+
+#ifdef USE_EDGEQUEUE_FRONTFACE
+ eq_ctx->q->use_view_normal = use_frontface;
#else
- UNUSED_VARS(view_normal);
+ UNUSED_VARS(use_frontface);
#endif
+ if (use_projected) {
+ eq_ctx->q->edge_queue_tri_in_range = edge_queue_tri_in_circle;
+ project_plane_normalized_v3_v3v3(eq_ctx->q->center_proj, center, view_normal);
+ }
+ else {
+ eq_ctx->q->edge_queue_tri_in_range = edge_queue_tri_in_sphere;
+ }
+
for (int n = 0; n < bvh->totnode; n++) {
PBVHNode *node = &bvh->nodes[n];
@@ -1895,7 +1935,7 @@ void BKE_pbvh_build_bmesh(
bool BKE_pbvh_bmesh_update_topology(
PBVH *bvh, PBVHTopologyUpdateMode mode,
const float center[3], const float view_normal[3],
- float radius)
+ float radius, const bool use_frontface, const bool use_projected)
{
/* 2 is enough for edge faces - manifold edge */
BLI_buffer_declare_static(BMLoop *, edge_loops, BLI_BUFFER_NOP, 2);
@@ -1918,7 +1958,7 @@ bool BKE_pbvh_bmesh_update_topology(
cd_vert_mask_offset, cd_vert_node_offset, cd_face_node_offset,
};
- short_edge_queue_create(&eq_ctx, bvh, center, view_normal, radius);
+ short_edge_queue_create(&eq_ctx, bvh, center, view_normal, radius, use_frontface, use_projected);
modified |= pbvh_bmesh_collapse_short_edges(
&eq_ctx, bvh, &deleted_faces);
BLI_heap_free(q.heap, NULL);
@@ -1933,7 +1973,7 @@ bool BKE_pbvh_bmesh_update_topology(
cd_vert_mask_offset, cd_vert_node_offset, cd_face_node_offset,
};
- long_edge_queue_create(&eq_ctx, bvh, center, view_normal, radius);
+ long_edge_queue_create(&eq_ctx, bvh, center, view_normal, radius, use_frontface, use_projected);
modified |= pbvh_bmesh_subdivide_long_edges(
&eq_ctx, bvh, &edge_loops);
BLI_heap_free(q.heap, NULL);
diff --git a/source/blender/blenloader/intern/versioning_270.c b/source/blender/blenloader/intern/versioning_270.c
index e1a4137d069..08e8d904b88 100644
--- a/source/blender/blenloader/intern/versioning_270.c
+++ b/source/blender/blenloader/intern/versioning_270.c
@@ -1683,7 +1683,7 @@ void blo_do_versions_270(FileData *fd, Library *UNUSED(lib), Main *main)
}
}
- if (!DNA_struct_elem_find(fd->filesdna, "VPaint", "char", "falloff_shape")) {
+ if (!DNA_struct_elem_find(fd->filesdna, "VPaint", "char", "normal_angle")) {
for (Scene *scene = main->scene.first; scene; scene = scene->id.next) {
ToolSettings *ts = scene->toolsettings;
for (int i = 0; i < 2; i++) {
diff --git a/source/blender/editors/sculpt_paint/paint_vertex.c b/source/blender/editors/sculpt_paint/paint_vertex.c
index a6b41b51ca6..7c54277639a 100644
--- a/source/blender/editors/sculpt_paint/paint_vertex.c
+++ b/source/blender/editors/sculpt_paint/paint_vertex.c
@@ -1500,22 +1500,6 @@ static float wpaint_get_active_weight(const MDeformVert *dv, const WeightPaintIn
}
}
-static SculptBrushTestFn sculpt_brush_test_init_with_falloff_shape(
- SculptSession *ss, SculptBrushTest *test, char falloff_shape)
-{
- sculpt_brush_test_init(ss, test);
- SculptBrushTestFn sculpt_brush_test_sq_fn;
- if (falloff_shape == VP_FALLOFF_SHAPE_SPHERE) {
- sculpt_brush_test_sq_fn = sculpt_brush_test_sphere_sq;
- }
- else {
- /* VP_FALLOFF_SHAPE_TUBE */
- plane_from_point_normal_v3(test->plane, test->location, ss->cache->view_normal);
- sculpt_brush_test_sq_fn = sculpt_brush_test_circle_sq;
- }
- return sculpt_brush_test_sq_fn;
-}
-
static void do_wpaint_brush_blur_task_cb_ex(
void *userdata, void *UNUSED(userdata_chunk), const int n, const int UNUSED(thread_id))
{
@@ -1536,7 +1520,7 @@ static void do_wpaint_brush_blur_task_cb_ex(
SculptBrushTest test;
SculptBrushTestFn sculpt_brush_test_sq_fn =
- sculpt_brush_test_init_with_falloff_shape(ss, &test, data->vp->falloff_shape);
+ sculpt_brush_test_init_with_falloff_shape(ss, &test, data->brush->falloff_shape);
/* For each vertex */
PBVHVertexIter vd;
@@ -1629,7 +1613,7 @@ static void do_wpaint_brush_smear_task_cb_ex(
SculptBrushTest test;
SculptBrushTestFn sculpt_brush_test_sq_fn =
- sculpt_brush_test_init_with_falloff_shape(ss, &test, data->vp->falloff_shape);
+ sculpt_brush_test_init_with_falloff_shape(ss, &test, data->brush->falloff_shape);
/* For each vertex */
PBVHVertexIter vd;
@@ -1729,7 +1713,7 @@ static void do_wpaint_brush_draw_task_cb_ex(
SculptBrushTest test;
SculptBrushTestFn sculpt_brush_test_sq_fn =
- sculpt_brush_test_init_with_falloff_shape(ss, &test, data->vp->falloff_shape);
+ sculpt_brush_test_init_with_falloff_shape(ss, &test, data->brush->falloff_shape);
/* For each vertex */
PBVHVertexIter vd;
@@ -1794,7 +1778,7 @@ static void do_wpaint_brush_calc_average_weight_cb_ex(
SculptBrushTest test;
SculptBrushTestFn sculpt_brush_test_sq_fn =
- sculpt_brush_test_init_with_falloff_shape(ss, &test, data->vp->falloff_shape);
+ sculpt_brush_test_init_with_falloff_shape(ss, &test, data->brush->falloff_shape);
/* For each vertex */
PBVHVertexIter vd;
@@ -1896,7 +1880,7 @@ static PBVHNode **vwpaint_pbvh_gather_generic(
PBVHNode **nodes = NULL;
/* Build a list of all nodes that are potentially within the brush's area of influence */
- if (wp->falloff_shape == VP_FALLOFF_SHAPE_SPHERE) {
+ if (brush->falloff_shape == PAINT_FALLOFF_SHAPE_SPHERE) {
SculptSearchSphereData data = {
.ss = ss,
.sd = sd,
@@ -2455,7 +2439,7 @@ static void do_vpaint_brush_calc_average_color_cb_ex(
SculptBrushTest test;
SculptBrushTestFn sculpt_brush_test_sq_fn =
- sculpt_brush_test_init_with_falloff_shape(ss, &test, data->vp->falloff_shape);
+ sculpt_brush_test_init_with_falloff_shape(ss, &test, data->brush->falloff_shape);
/* For each vertex */
PBVHVertexIter vd;
@@ -2524,7 +2508,7 @@ static void do_vpaint_brush_draw_task_cb_ex(
SculptBrushTest test;
SculptBrushTestFn sculpt_brush_test_sq_fn =
- sculpt_brush_test_init_with_falloff_shape(ss, &test, data->vp->falloff_shape);
+ sculpt_brush_test_init_with_falloff_shape(ss, &test, data->brush->falloff_shape);
/* For each vertex */
PBVHVertexIter vd;
@@ -2613,7 +2597,7 @@ static void do_vpaint_brush_blur_task_cb_ex(
SculptBrushTest test;
SculptBrushTestFn sculpt_brush_test_sq_fn =
- sculpt_brush_test_init_with_falloff_shape(ss, &test, data->vp->falloff_shape);
+ sculpt_brush_test_init_with_falloff_shape(ss, &test, data->brush->falloff_shape);
/* For each vertex */
PBVHVertexIter vd;
@@ -2726,7 +2710,7 @@ static void do_vpaint_brush_smear_task_cb_ex(
SculptBrushTest test;
SculptBrushTestFn sculpt_brush_test_sq_fn =
- sculpt_brush_test_init_with_falloff_shape(ss, &test, data->vp->falloff_shape);
+ sculpt_brush_test_init_with_falloff_shape(ss, &test, data->brush->falloff_shape);
/* For each vertex */
PBVHVertexIter vd;
diff --git a/source/blender/editors/sculpt_paint/sculpt.c b/source/blender/editors/sculpt_paint/sculpt.c
index f74ac68262f..487ab32c5a6 100644
--- a/source/blender/editors/sculpt_paint/sculpt.c
+++ b/source/blender/editors/sculpt_paint/sculpt.c
@@ -524,7 +524,8 @@ void sculpt_brush_test_init(SculptSession *ss, SculptBrushTest *test)
test->dist = 0.0f; /* just for initialize */
/* Only for 2D projection. */
- zero_v4(test->plane);
+ zero_v4(test->plane_view);
+ zero_v4(test->plane_tool);
test->mirror_symmetry_pass = ss->cache->mirror_symmetry_pass;
@@ -590,7 +591,7 @@ bool sculpt_brush_test_sphere_fast(const SculptBrushTest *test, const float co[3
bool sculpt_brush_test_circle_sq(SculptBrushTest *test, const float co[3])
{
float co_proj[3];
- closest_to_plane_normalized_v3(co_proj, test->plane, co);
+ closest_to_plane_normalized_v3(co_proj, test->plane_view, co);
float distsq = len_squared_v3v3(co_proj, test->location);
if (distsq <= test->radius_squared) {
@@ -634,6 +635,22 @@ bool sculpt_brush_test_cube(SculptBrushTest *test, const float co[3], float loca
}
}
+SculptBrushTestFn sculpt_brush_test_init_with_falloff_shape(
+ SculptSession *ss, SculptBrushTest *test, char falloff_shape)
+{
+ sculpt_brush_test_init(ss, test);
+ SculptBrushTestFn sculpt_brush_test_sq_fn;
+ if (falloff_shape == PAINT_FALLOFF_SHAPE_SPHERE) {
+ sculpt_brush_test_sq_fn = sculpt_brush_test_sphere_sq;
+ }
+ else {
+ /* PAINT_FALLOFF_SHAPE_TUBE */
+ plane_from_point_normal_v3(test->plane_view, test->location, ss->cache->view_normal);
+ sculpt_brush_test_sq_fn = sculpt_brush_test_circle_sq;
+ }
+ return sculpt_brush_test_sq_fn;
+}
+
static float frontface(const Brush *br, const float sculpt_normal[3],
const short no[3], const float fno[3])
{
@@ -1249,7 +1266,7 @@ bool sculpt_search_circle_cb(PBVHNode *node, void *data_v)
const float dist_sq = dist_squared_ray_to_aabb(
data->dist_ray_to_aabb_precalc, bb_min, bb_max, dummy_co, &dummy_depth);
- return dist_sq < data->radius_squared;
+ return dist_sq < data->radius_squared || 1;
}
/* Handles clipping against a mirror modifier and SCULPT_LOCK axis flags */
@@ -1268,6 +1285,37 @@ static void sculpt_clip(Sculpt *sd, SculptSession *ss, float co[3], const float
}
}
+static PBVHNode **sculpt_pbvh_gather_generic(
+ Object *ob, Sculpt *sd, const Brush *brush, bool use_original, float radius_scale, int *r_totnode)
+{
+ SculptSession *ss = ob->sculpt;
+ PBVHNode **nodes = NULL;
+
+ /* Build a list of all nodes that are potentially within the brush's area of influence */
+ if (brush->falloff_shape == PAINT_FALLOFF_SHAPE_SPHERE) {
+ SculptSearchSphereData data = {
+ .ss = ss,
+ .sd = sd,
+ .radius_squared = SQUARE(ss->cache->radius * radius_scale),
+ .original = use_original,
+ };
+ BKE_pbvh_search_gather(ss->pbvh, sculpt_search_sphere_cb, &data, &nodes, r_totnode);
+ }
+ else {
+ struct DistRayAABB_Precalc dist_ray_to_aabb_precalc;
+ dist_squared_ray_to_aabb_precalc(&dist_ray_to_aabb_precalc, ss->cache->location, ss->cache->view_normal);
+ SculptSearchCircleData data = {
+ .ss = ss,
+ .sd = sd,
+ .radius_squared = SQUARE(ss->cache->radius * radius_scale),
+ .original = use_original,
+ .dist_ray_to_aabb_precalc = &dist_ray_to_aabb_precalc,
+ };
+ BKE_pbvh_search_gather(ss->pbvh, sculpt_search_circle_cb, &data, &nodes, r_totnode);
+ }
+ return nodes;
+}
+
/* Calculate primary direction of movement for many brushes */
static void calc_sculpt_normal(
Sculpt *sd, Object *ob,
@@ -1569,19 +1617,19 @@ static void do_smooth_brush_mesh_task_cb_ex(
float bstrength = data->strength;
PBVHVertexIter vd;
- SculptBrushTest test;
CLAMP(bstrength, 0.0f, 1.0f);
- sculpt_brush_test_init(ss, &test);
+ SculptBrushTest test;
+ SculptBrushTestFn sculpt_brush_test_sq_fn =
+ sculpt_brush_test_init_with_falloff_shape(ss, &test, data->brush->falloff_shape);
BKE_pbvh_vertex_iter_begin(ss->pbvh, data->nodes[n], vd, PBVH_ITER_UNIQUE)
{
- if (sculpt_brush_test_sphere(&test, vd.co)) {
+ if (sculpt_brush_test_sq_fn(&test, vd.co)) {
const float fade = bstrength * tex_strength(
- ss, brush, vd.co, test.dist, vd.no, vd.fno,
- smooth_mask ? 0.0f : (vd.mask ? *vd.mask : 0.0f),
- thread_id);
+ ss, brush, vd.co, sqrtf(test.dist),
+ vd.no, vd.fno, smooth_mask ? 0.0f : (vd.mask ? *vd.mask : 0.0f), thread_id);
if (smooth_mask) {
float val = neighbor_average_mask(ss, vd.vert_indices[vd.i]) - *vd.mask;
val *= fade * bstrength;
@@ -1617,18 +1665,19 @@ static void do_smooth_brush_bmesh_task_cb_ex(
float bstrength = data->strength;
PBVHVertexIter vd;
- SculptBrushTest test;
CLAMP(bstrength, 0.0f, 1.0f);
- sculpt_brush_test_init(ss, &test);
+ SculptBrushTest test;
+ SculptBrushTestFn sculpt_brush_test_sq_fn =
+ sculpt_brush_test_init_with_falloff_shape(ss, &test, data->brush->falloff_shape);
BKE_pbvh_vertex_iter_begin(ss->pbvh, data->nodes[n], vd, PBVH_ITER_UNIQUE)
{
- if (sculpt_brush_test_sphere(&test, vd.co)) {
+ if (sculpt_brush_test_sq_fn(&test, vd.co)) {
const float fade = bstrength * tex_strength(
- ss, brush, vd.co, test.dist, vd.no, vd.fno, smooth_mask ? 0.0f : *vd.mask,
- thread_id);
+ ss, brush, vd.co, sqrtf(test.dist),
+ vd.no, vd.fno, smooth_mask ? 0.0f : *vd.mask, thread_id);
if (smooth_mask) {
float val = bmesh_neighbor_average_mask(vd.bm_vert, vd.cd_vert_mask_offset) - *vd.mask;
val *= fade * bstrength;
@@ -1664,7 +1713,6 @@ static void do_smooth_brush_multires_task_cb_ex(
const bool smooth_mask = data->smooth_mask;
float bstrength = data->strength;
- SculptBrushTest test;
CCGElem **griddata, *gddata;
CCGKey key;
@@ -1677,7 +1725,9 @@ static void do_smooth_brush_multires_task_cb_ex(
int *grid_indices, totgrid, gridsize;
int i, x, y;
- sculpt_brush_test_init(ss, &test);
+ SculptBrushTest test;
+ SculptBrushTestFn sculpt_brush_test_sq_fn =
+ sculpt_brush_test_init_with_falloff_shape(ss, &test, data->brush->falloff_shape);
CLAMP(bstrength, 0.0f, 1.0f);
@@ -1764,10 +1814,11 @@ static void do_smooth_brush_multires_task_cb_ex(
fno = CCG_elem_offset_no(&key, gddata, index);
mask = CCG_elem_offset_mask(&key, gddata, index);
- if (sculpt_brush_test_sphere(&test, co)) {
+ if (sculpt_brush_test_sq_fn(&test, co)) {
const float strength_mask = (smooth_mask ? 0.0f : *mask);
const float fade = bstrength * tex_strength(
- ss, brush, co, test.dist, NULL, fno, strength_mask, thread_id);
+ ss, brush, co, sqrtf(test.dist),
+ NULL, fno, strength_mask, thread_id);
float f = 1.0f / 16.0f;
if (x == 0 || x == gridsize - 1)
@@ -1878,14 +1929,17 @@ static void do_mask_brush_draw_task_cb_ex(
const float bstrength = ss->cache->bstrength;
PBVHVertexIter vd;
- SculptBrushTest test;
- sculpt_brush_test_init(ss, &test);
+ SculptBrushTest test;
+ SculptBrushTestFn sculpt_brush_test_sq_fn =
+ sculpt_brush_test_init_with_falloff_shape(ss, &test, data->brush->falloff_shape);
BKE_pbvh_vertex_iter_begin(ss->pbvh, data->nodes[n], vd, PBVH_ITER_UNIQUE)
{
- if (sculpt_brush_test_sphere(&test, vd.co)) {
- const float fade = tex_strength(ss, brush, vd.co, test.dist, vd.no, vd.fno, 0.0f, thread_id);
+ if (sculpt_brush_test_sq_fn(&test, vd.co)) {
+ const float fade = tex_strength(
+ ss, brush, vd.co, sqrtf(test.dist),
+ vd.no, vd.fno, 0.0f, thread_id);
(*vd.mask) += fade * bstrength;
CLAMP(*vd.mask, 0, 1);
@@ -1935,19 +1989,21 @@ static void do_draw_brush_task_cb_ex(
const float *offset = data->offset;
PBVHVertexIter vd;
- SculptBrushTest test;
float (*proxy)[3];
proxy = BKE_pbvh_node_add_proxy(ss->pbvh, data->nodes[n])->co;
- sculpt_brush_test_init(ss, &test);
+ SculptBrushTest test;
+ SculptBrushTestFn sculpt_brush_test_sq_fn =
+ sculpt_brush_test_init_with_falloff_shape(ss, &test, data->brush->falloff_shape);
BKE_pbvh_vertex_iter_begin(ss->pbvh, data->nodes[n], vd, PBVH_ITER_UNIQUE)
{
- if (sculpt_brush_test_sphere(&test, vd.co)) {
+ if (sculpt_brush_test_sq_fn(&test, vd.co)) {
/* offset vertex */
const float fade = tex_strength(
- ss, brush, vd.co, test.dist, vd.no, vd.fno, vd.mask ? *vd.mask : 0.0f, thread_id);
+ ss, brush, vd.co, sqrtf(test.dist),
+ vd.no, vd.fno, vd.mask ? *vd.mask : 0.0f, thread_id);
mul_v3_v3fl(proxy[vd.i], offset, fade);
@@ -1992,19 +2048,21 @@ static void do_crease_brush_task_cb_ex(
const float *offset = data->offset;
PBVHVertexIter vd;
- SculptBrushTest test;
float (*proxy)[3];
proxy = BKE_pbvh_node_add_proxy(ss->pbvh, data->nodes[n])->co;
- sculpt_brush_test_init(ss, &test);
+ SculptBrushTest test;
+ SculptBrushTestFn sculpt_brush_test_sq_fn =
+ sculpt_brush_test_init_with_falloff_shape(ss, &test, data->brush->falloff_shape);
BKE_pbvh_vertex_iter_begin(ss->pbvh, data->nodes[n], vd, PBVH_ITER_UNIQUE)
{
- if (sculpt_brush_test_sphere(&test, vd.co)) {
+ if (sculpt_brush_test_sq_fn(&test, vd.co)) {
/* offset vertex */
const float fade = tex_strength(
- ss, brush, vd.co, test.dist, vd.no, vd.fno, vd.mask ? *vd.mask : 0.0f, thread_id);
+ ss, brush, vd.co, sqrtf(test.dist),
+ vd.no, vd.fno, vd.mask ? *vd.mask : 0.0f, thread_id);
float val1[3];
float val2[3];
@@ -2077,19 +2135,21 @@ static void do_pinch_brush_task_cb_ex(
const Brush *brush = data->brush;
PBVHVertexIter vd;
- SculptBrushTest test;
float (*proxy)[3];
const float bstrength = ss->cache->bstrength;
proxy = BKE_pbvh_node_add_proxy(ss->pbvh, data->nodes[n])->co;
- sculpt_brush_test_init(ss, &test);
+ SculptBrushTest test;
+ SculptBrushTestFn sculpt_brush_test_sq_fn =
+ sculpt_brush_test_init_with_falloff_shape(ss, &test, data->brush->falloff_shape);
BKE_pbvh_vertex_iter_begin(ss->pbvh, data->nodes[n], vd, PBVH_ITER_UNIQUE)
{
- if (sculpt_brush_test_sphere(&test, vd.co)) {
+ if (sculpt_brush_test_sq_fn(&test, vd.co)) {
const float fade = bstrength * tex_strength(
- ss, brush, vd.co, test.dist, vd.no, vd.fno, vd.mask ? *vd.mask : 0.0f, thread_id);
+ ss, brush, vd.co, sqrtf(test.dist),
+ vd.no, vd.fno, vd.mask ? *vd.mask : 0.0f, thread_id);
float val[3];
sub_v3_v3v3(val, test.location, vd.co);
@@ -2124,7 +2184,6 @@ static void do_grab_brush_task_cb_ex(
const float *grab_delta = data->grab_delta;
PBVHVertexIter vd;
- SculptBrushTest test;
SculptOrigVertData orig_data;
float (*proxy)[3];
const float bstrength = ss->cache->bstrength;
@@ -2133,16 +2192,18 @@ static void do_grab_brush_task_cb_ex(
proxy = BKE_pbvh_node_add_proxy(ss->pbvh, data->nodes[n])->co;
- sculpt_brush_test_init(ss, &test);
+ SculptBrushTest test;
+ SculptBrushTestFn sculpt_brush_test_sq_fn =
+ sculpt_brush_test_init_with_falloff_shape(ss, &test, data->brush->falloff_shape);
BKE_pbvh_vertex_iter_begin(ss->pbvh, data->nodes[n], vd, PBVH_ITER_UNIQUE)
{
sculpt_orig_vert_data_update(&orig_data, &vd);
- if (sculpt_brush_test_sphere(&test, orig_data.co)) {
+ if (sculpt_brush_test_sq_fn(&test, orig_data.co)) {
const float fade = bstrength * tex_strength(
- ss, brush, orig_data.co, test.dist, orig_data.no, NULL, vd.mask ? *vd.mask : 0.0f,
- thread_id);
+ ss, brush, orig_data.co, sqrtf(test.dist),
+ orig_data.no, NULL, vd.mask ? *vd.mask : 0.0f, thread_id);
mul_v3_v3fl(proxy[vd.i], grab_delta, fade);
@@ -2184,19 +2245,21 @@ static void do_nudge_brush_task_cb_ex(
const float *cono = data->cono;
PBVHVertexIter vd;
- SculptBrushTest test;
float (*proxy)[3];
const float bstrength = ss->cache->bstrength;
proxy = BKE_pbvh_node_add_proxy(ss->pbvh, data->nodes[n])->co;
- sculpt_brush_test_init(ss, &test);
+ SculptBrushTest test;
+ SculptBrushTestFn sculpt_brush_test_sq_fn =
+ sculpt_brush_test_init_with_falloff_shape(ss, &test, data->brush->falloff_shape);
BKE_pbvh_vertex_iter_begin(ss->pbvh, data->nodes[n], vd, PBVH_ITER_UNIQUE)
{
- if (sculpt_brush_test_sphere(&test, vd.co)) {
+ if (sculpt_brush_test_sq_fn(&test, vd.co)) {
const float fade = bstrength * tex_strength(
- ss, brush, vd.co, test.dist, vd.no, vd.fno, vd.mask ? *vd.mask : 0.0f, thread_id);
+ ss, brush, vd.co, sqrtf(test.dist),
+ vd.no, vd.fno, vd.mask ? *vd.mask : 0.0f, thread_id);
mul_v3_v3fl(proxy[vd.i], cono, fade);
@@ -2239,7 +2302,6 @@ static void do_snake_hook_brush_task_cb_ex(
const float *grab_delta = data->grab_delta;
PBVHVertexIter vd;
- SculptBrushTest test;
float (*proxy)[3];
const float bstrength = ss->cache->bstrength;
const bool do_rake_rotation = ss->cache->is_rake_rotation_valid;
@@ -2249,13 +2311,16 @@ static void do_snake_hook_brush_task_cb_ex(
proxy = BKE_pbvh_node_add_proxy(ss->pbvh, data->nodes[n])->co;
- sculpt_brush_test_init(ss, &test);
+ SculptBrushTest test;
+ SculptBrushTestFn sculpt_brush_test_sq_fn =
+ sculpt_brush_test_init_with_falloff_shape(ss, &test, data->brush->falloff_shape);
BKE_pbvh_vertex_iter_begin(ss->pbvh, data->nodes[n], vd, PBVH_ITER_UNIQUE)
{
- if (sculpt_brush_test_sphere(&test, vd.co)) {
+ if (sculpt_brush_test_sq_fn(&test, vd.co)) {
const float fade = bstrength * tex_strength(
- ss, brush, vd.co, test.dist, vd.no, vd.fno, vd.mask ? *vd.mask : 0.0f, thread_id);
+ ss, brush, vd.co, sqrtf(test.dist),
+ vd.no, vd.fno, vd.mask ? *vd.mask : 0.0f, thread_id);
mul_v3_v3fl(proxy[vd.i], grab_delta, fade);
@@ -2339,7 +2404,6 @@ static void do_thumb_brush_task_cb_ex(
const float *cono = data->cono;
PBVHVertexIter vd;
- SculptBrushTest test;
SculptOrigVertData orig_data;
float (*proxy)[3];
const float bstrength = ss->cache->bstrength;
@@ -2348,16 +2412,18 @@ static void do_thumb_brush_task_cb_ex(
proxy = BKE_pbvh_node_add_proxy(ss->pbvh, data->nodes[n])->co;
- sculpt_brush_test_init(ss, &test);
+ SculptBrushTest test;
+ SculptBrushTestFn sculpt_brush_test_sq_fn =
+ sculpt_brush_test_init_with_falloff_shape(ss, &test, data->brush->falloff_shape);
BKE_pbvh_vertex_iter_begin(ss->pbvh, data->nodes[n], vd, PBVH_ITER_UNIQUE)
{
sculpt_orig_vert_data_update(&orig_data, &vd);
- if (sculpt_brush_test_sphere(&test, orig_data.co)) {
+ if (sculpt_brush_test_sq_fn(&test, orig_data.co)) {
const float fade = bstrength * tex_strength(
- ss, brush, orig_data.co, test.dist, orig_data.no, NULL, vd.mask ? *vd.mask : 0.0f,
- thread_id);
+ ss, brush, orig_data.co, sqrtf(test.dist),
+ orig_data.no, NULL, vd.mask ? *vd.mask : 0.0f, thread_id);
mul_v3_v3fl(proxy[vd.i], cono, fade);
@@ -2399,7 +2465,6 @@ static void do_rotate_brush_task_cb_ex(
const float angle = data->angle;
PBVHVertexIter vd;
- SculptBrushTest test;
SculptOrigVertData orig_data;
float (*proxy)[3];
const float bstrength = ss->cache->bstrength;
@@ -2408,17 +2473,19 @@ static void do_rotate_brush_task_cb_ex(
proxy = BKE_pbvh_node_add_proxy(ss->pbvh, data->nodes[n])->co;
- sculpt_brush_test_init(ss, &test);
+ SculptBrushTest test;
+ SculptBrushTestFn sculpt_brush_test_sq_fn =
+ sculpt_brush_test_init_with_falloff_shape(ss, &test, data->brush->falloff_shape);
BKE_pbvh_vertex_iter_begin(ss->pbvh, data->nodes[n], vd, PBVH_ITER_UNIQUE)
{
sculpt_orig_vert_data_update(&orig_data, &vd);
- if (sculpt_brush_test_sphere(&test, orig_data.co)) {
+ if (sculpt_brush_test_sq_fn(&test, orig_data.co)) {
float vec[3], rot[3][3];
const float fade = bstrength * tex_strength(
- ss, brush, orig_data.co, test.dist, orig_data.no, NULL, vd.mask ? *vd.mask : 0.0f,
- thread_id);
+ ss, brush, orig_data.co, sqrtf(test.dist),
+ orig_data.no, NULL, vd.mask ? *vd.mask : 0.0f, thread_id);
sub_v3_v3v3(vec, orig_data.co, ss->cache->location);
axis_angle_normalized_to_mat3(rot, ss->cache->sculpt_normal_symm, angle * fade);
@@ -2461,7 +2528,6 @@ static void do_layer_brush_task_cb_ex(
const float *offset = data->offset;
PBVHVertexIter vd;
- SculptBrushTest test;
SculptOrigVertData orig_data;
float *layer_disp;
const float bstrength = ss->cache->bstrength;
@@ -2476,15 +2542,18 @@ static void do_layer_brush_task_cb_ex(
layer_disp = BKE_pbvh_node_layer_disp_get(ss->pbvh, data->nodes[n]);
BLI_mutex_unlock(&data->mutex);
- sculpt_brush_test_init(ss, &test);
+ SculptBrushTest test;
+ SculptBrushTestFn sculpt_brush_test_sq_fn =
+ sculpt_brush_test_init_with_falloff_shape(ss, &test, data->brush->falloff_shape);
BKE_pbvh_vertex_iter_begin(ss->pbvh, data->nodes[n], vd, PBVH_ITER_UNIQUE)
{
sculpt_orig_vert_data_update(&orig_data, &vd);
- if (sculpt_brush_test_sphere(&test, orig_data.co)) {
+ if (sculpt_brush_test_sq_fn(&test, orig_data.co)) {
const float fade = bstrength * tex_strength(
- ss, brush, vd.co, test.dist, vd.no, vd.fno, vd.mask ? *vd.mask : 0.0f, thread_id);
+ ss, brush, vd.co, sqrtf(test.dist),
+ vd.no, vd.fno, vd.mask ? *vd.mask : 0.0f, thread_id);
float *disp = &layer_disp[vd.i];
float val[3];
@@ -2544,19 +2613,21 @@ static void do_inflate_brush_task_cb_ex(
const Brush *brush = data->brush;
PBVHVertexIter vd;
- SculptBrushTest test;
float (*proxy)[3];
const float bstrength = ss->cache->bstrength;
proxy = BKE_pbvh_node_add_proxy(ss->pbvh, data->nodes[n])->co;
- sculpt_brush_test_init(ss, &test);
+ SculptBrushTest test;
+ SculptBrushTestFn sculpt_brush_test_sq_fn =
+ sculpt_brush_test_init_with_falloff_shape(ss, &test, data->brush->falloff_shape);
BKE_pbvh_vertex_iter_begin(ss->pbvh, data->nodes[n], vd, PBVH_ITER_UNIQUE)
{
- if (sculpt_brush_test_sphere(&test, vd.co)) {
+ if (sculpt_brush_test_sq_fn(&test, vd.co)) {
const float fade = bstrength * tex_strength(
- ss, brush, vd.co, test.dist, vd.no, vd.fno, vd.mask ? *vd.mask : 0.0f, thread_id);
+ ss, brush, vd.co, sqrtf(test.dist),
+ vd.no, vd.fno, vd.mask ? *vd.mask : 0.0f, thread_id);
float val[3];
if (vd.fno)
@@ -2704,29 +2775,31 @@ static void do_flatten_brush_task_cb_ex(
const float *area_co = data->area_co;
PBVHVertexIter vd;
- SculptBrushTest test;
float (*proxy)[3];
const float bstrength = ss->cache->bstrength;
proxy = BKE_pbvh_node_add_proxy(ss->pbvh, data->nodes[n])->co;
- sculpt_brush_test_init(ss, &test);
- plane_from_point_normal_v3(test.plane, area_co, area_no);
+ SculptBrushTest test;
+ SculptBrushTestFn sculpt_brush_test_sq_fn =
+ sculpt_brush_test_init_with_falloff_shape(ss, &test, data->brush->falloff_shape);
+
+ plane_from_point_normal_v3(test.plane_tool, area_co, area_no);
BKE_pbvh_vertex_iter_begin(ss->pbvh, data->nodes[n], vd, PBVH_ITER_UNIQUE)
{
- if (sculpt_brush_test_sphere_sq(&test, vd.co)) {
+ if (sculpt_brush_test_sq_fn(&test, vd.co)) {
float intr[3];
float val[3];
- closest_to_plane_normalized_v3(intr, test.plane, vd.co);
+ closest_to_plane_normalized_v3(intr, test.plane_tool, vd.co);
sub_v3_v3v3(val, intr, vd.co);
if (plane_trim(ss->cache, brush, val)) {
const float fade = bstrength * tex_strength(
- ss, brush, vd.co, sqrtf(test.dist), vd.no, vd.fno, vd.mask ? *vd.mask : 0.0f,
- thread_id);
+ ss, brush, vd.co, sqrtf(test.dist),
+ vd.no, vd.fno, vd.mask ? *vd.mask : 0.0f, thread_id);
mul_v3_v3fl(proxy[vd.i], val, fade);
@@ -2780,24 +2853,26 @@ static void do_clay_brush_task_cb_ex(
const float *area_co = data->area_co;
PBVHVertexIter vd;
- SculptBrushTest test;
float (*proxy)[3];
const bool flip = (ss->cache->bstrength < 0);
const float bstrength = flip ? -ss->cache->bstrength : ss->cache->bstrength;
proxy = BKE_pbvh_node_add_proxy(ss->pbvh, data->nodes[n])->co;
- sculpt_brush_test_init(ss, &test);
- plane_from_point_normal_v3(test.plane, area_co, area_no);
+ SculptBrushTest test;
+ SculptBrushTestFn sculpt_brush_test_sq_fn =
+ sculpt_brush_test_init_with_falloff_shape(ss, &test, data->brush->falloff_shape);
+
+ plane_from_point_normal_v3(test.plane_tool, area_co, area_no);
BKE_pbvh_vertex_iter_begin(ss->pbvh, data->nodes[n], vd, PBVH_ITER_UNIQUE)
{
- if (sculpt_brush_test_sphere_sq(&test, vd.co)) {
- if (plane_point_side_flip(vd.co, test.plane, flip)) {
+ if (sculpt_brush_test_sq_fn(&test, vd.co)) {
+ if (plane_point_side_flip(vd.co, test.plane_tool, flip)) {
float intr[3];
float val[3];
- closest_to_plane_normalized_v3(intr, test.plane, vd.co);
+ closest_to_plane_normalized_v3(intr, test.plane_tool, vd.co);
sub_v3_v3v3(val, intr, vd.co);
@@ -2805,8 +2880,8 @@ static void do_clay_brush_task_cb_ex(
/* note, the normal from the vertices is ignored,
* causes glitch with planes, see: T44390 */
const float fade = bstrength * tex_strength(
- ss, brush, vd.co, sqrtf(test.dist), vd.no, vd.fno, vd.mask ? *vd.mask : 0.0f,
- thread_id);
+ ss, brush, vd.co, sqrtf(test.dist),
+ vd.no, vd.fno, vd.mask ? *vd.mask : 0.0f, thread_id);
mul_v3_v3fl(proxy[vd.i], val, fade);
@@ -2873,16 +2948,16 @@ static void do_clay_strips_brush_task_cb_ex(
proxy = BKE_pbvh_node_add_proxy(ss->pbvh, data->nodes[n])->co;
sculpt_brush_test_init(ss, &test);
- plane_from_point_normal_v3(test.plane, area_co, area_no_sp);
+ plane_from_point_normal_v3(test.plane_tool, area_co, area_no_sp);
BKE_pbvh_vertex_iter_begin(ss->pbvh, data->nodes[n], vd, PBVH_ITER_UNIQUE)
{
if (sculpt_brush_test_cube(&test, vd.co, mat)) {
- if (plane_point_side_flip(vd.co, test.plane, flip)) {
+ if (plane_point_side_flip(vd.co, test.plane_tool, flip)) {
float intr[3];
float val[3];
- closest_to_plane_normalized_v3(intr, test.plane, vd.co);
+ closest_to_plane_normalized_v3(intr, test.plane_tool, vd.co);
sub_v3_v3v3(val, intr, vd.co);
@@ -2890,8 +2965,8 @@ static void do_clay_strips_brush_task_cb_ex(
/* note, the normal from the vertices is ignored,
* causes glitch with planes, see: T44390 */
const float fade = bstrength * tex_strength(
- ss, brush, vd.co, ss->cache->radius * test.dist,
- vd.no, vd.fno, vd.mask ? *vd.mask : 0.0f, thread_id);
+ ss, brush, vd.co, ss->cache->radius * test.dist,
+ vd.no, vd.fno, vd.mask ? *vd.mask : 0.0f, thread_id);
mul_v3_v3fl(proxy[vd.i], val, fade);
@@ -2974,30 +3049,32 @@ static void do_fill_brush_task_cb_ex(
const float *area_co = data->area_co;
PBVHVertexIter vd;
- SculptBrushTest test;
float (*proxy)[3];
const float bstrength = ss->cache->bstrength;
proxy = BKE_pbvh_node_add_proxy(ss->pbvh, data->nodes[n])->co;
- sculpt_brush_test_init(ss, &test);
- plane_from_point_normal_v3(test.plane, area_co, area_no);
+ SculptBrushTest test;
+ SculptBrushTestFn sculpt_brush_test_sq_fn =
+ sculpt_brush_test_init_with_falloff_shape(ss, &test, data->brush->falloff_shape);
+
+ plane_from_point_normal_v3(test.plane_tool, area_co, area_no);
BKE_pbvh_vertex_iter_begin(ss->pbvh, data->nodes[n], vd, PBVH_ITER_UNIQUE)
{
- if (sculpt_brush_test_sphere_sq(&test, vd.co)) {
- if (plane_point_side(vd.co, test.plane)) {
+ if (sculpt_brush_test_sq_fn(&test, vd.co)) {
+ if (plane_point_side(vd.co, test.plane_tool)) {
float intr[3];
float val[3];
- closest_to_plane_normalized_v3(intr, test.plane, vd.co);
+ closest_to_plane_normalized_v3(intr, test.plane_tool, vd.co);
sub_v3_v3v3(val, intr, vd.co);
if (plane_trim(ss->cache, brush, val)) {
const float fade = bstrength * tex_strength(
- ss, brush, vd.co, sqrtf(test.dist),
- vd.no, vd.fno, vd.mask ? *vd.mask : 0.0f, thread_id);
+ ss, brush, vd.co, sqrtf(test.dist),
+ vd.no, vd.fno, vd.mask ? *vd.mask : 0.0f, thread_id);
mul_v3_v3fl(proxy[vd.i], val, fade);
@@ -3053,30 +3130,31 @@ static void do_scrape_brush_task_cb_ex(
const float *area_co = data->area_co;
PBVHVertexIter vd;
- SculptBrushTest test;
float (*proxy)[3];
const float bstrength = ss->cache->bstrength;
proxy = BKE_pbvh_node_add_proxy(ss->pbvh, data->nodes[n])->co;
- sculpt_brush_test_init(ss, &test);
- plane_from_point_normal_v3(test.plane, area_co, area_no);
+ SculptBrushTest test;
+ SculptBrushTestFn sculpt_brush_test_sq_fn =
+ sculpt_brush_test_init_with_falloff_shape(ss, &test, data->brush->falloff_shape);
+ plane_from_point_normal_v3(test.plane_tool, area_co, area_no);
BKE_pbvh_vertex_iter_begin(ss->pbvh, data->nodes[n], vd, PBVH_ITER_UNIQUE)
{
- if (sculpt_brush_test_sphere_sq(&test, vd.co)) {
- if (!plane_point_side(vd.co, test.plane)) {
+ if (sculpt_brush_test_sq_fn(&test, vd.co)) {
+ if (!plane_point_side(vd.co, test.plane_tool)) {
float intr[3];
float val[3];
- closest_to_plane_normalized_v3(intr, test.plane, vd.co);
+ closest_to_plane_normalized_v3(intr, test.plane_tool, vd.co);
sub_v3_v3v3(val, intr, vd.co);
if (plane_trim(ss->cache, brush, val)) {
const float fade = bstrength * tex_strength(
- ss, brush, vd.co, sqrtf(test.dist), vd.no, vd.fno, vd.mask ? *vd.mask : 0.0f,
- thread_id);
+ ss, brush, vd.co, sqrtf(test.dist),
+ vd.no, vd.fno, vd.mask ? *vd.mask : 0.0f, thread_id);
mul_v3_v3fl(proxy[vd.i], val, fade);
@@ -3131,18 +3209,19 @@ static void do_gravity_task_cb_ex(
float *offset = data->offset;
PBVHVertexIter vd;
- SculptBrushTest test;
float (*proxy)[3];
proxy = BKE_pbvh_node_add_proxy(ss->pbvh, data->nodes[n])->co;
- sculpt_brush_test_init(ss, &test);
+ SculptBrushTest test;
+ SculptBrushTestFn sculpt_brush_test_sq_fn =
+ sculpt_brush_test_init_with_falloff_shape(ss, &test, data->brush->falloff_shape);
BKE_pbvh_vertex_iter_begin(ss->pbvh, data->nodes[n], vd, PBVH_ITER_UNIQUE) {
- if (sculpt_brush_test_sphere_sq(&test, vd.co)) {
+ if (sculpt_brush_test_sq_fn(&test, vd.co)) {
const float fade = tex_strength(
- ss, brush, vd.co, sqrtf(test.dist), vd.no, vd.fno, vd.mask ? *vd.mask : 0.0f,
- thread_id);
+ ss, brush, vd.co, sqrtf(test.dist),
+ vd.no, vd.fno, vd.mask ? *vd.mask : 0.0f, thread_id);
mul_v3_v3fl(proxy[vd.i], offset, fade);
@@ -3226,22 +3305,12 @@ void sculpt_vertcos_to_key(Object *ob, KeyBlock *kb, float (*vertCos)[3])
static void sculpt_topology_update(Sculpt *sd, Object *ob, Brush *brush, UnifiedPaintSettings *UNUSED(ups))
{
SculptSession *ss = ob->sculpt;
- SculptSearchSphereData data;
- PBVHNode **nodes = NULL;
- float radius;
- int n, totnode;
-
- /* Build a list of all nodes that are potentially within the
- * brush's area of influence */
- data.ss = ss;
- data.sd = sd;
-
- radius = ss->cache->radius * 1.25f;
-
- data.radius_squared = radius * radius;
- data.original = sculpt_tool_needs_original(brush->sculpt_tool) ? true : ss->cache->original;
- BKE_pbvh_search_gather(ss->pbvh, sculpt_search_sphere_cb, &data, &nodes, &totnode);
+ int n, totnode;
+ /* Build a list of all nodes that are potentially within the brush's area of influence */
+ const bool use_original = sculpt_tool_needs_original(brush->sculpt_tool) ? true : ss->cache->original;
+ const float radius_scale = 1.25f;
+ PBVHNode **nodes = sculpt_pbvh_gather_generic(ob, sd, brush, use_original, radius_scale, &totnode);
/* Only act if some verts are inside the brush area */
if (totnode) {
@@ -3273,8 +3342,10 @@ static void sculpt_topology_update(Sculpt *sd, Object *ob, Brush *brush, Unified
BKE_pbvh_bmesh_update_topology(
ss->pbvh, mode,
ss->cache->location,
- (brush->flag & BRUSH_FRONTFACE) ? ss->cache->view_normal : NULL,
- ss->cache->radius);
+ ss->cache->view_normal,
+ ss->cache->radius,
+ (brush->flag & BRUSH_FRONTFACE) != 0,
+ (brush->falloff_shape != PAINT_FALLOFF_SHAPE_SPHERE));
}
MEM_freeN(nodes);
@@ -3297,16 +3368,12 @@ static void do_brush_action_task_cb(void *userdata, const int n)
static void do_brush_action(Sculpt *sd, Object *ob, Brush *brush, UnifiedPaintSettings *ups)
{
SculptSession *ss = ob->sculpt;
- SculptSearchSphereData data;
- PBVHNode **nodes = NULL;
int totnode;
/* Build a list of all nodes that are potentially within the brush's area of influence */
- data.ss = ss;
- data.sd = sd;
- data.radius_squared = ss->cache->radius_squared;
- data.original = sculpt_tool_needs_original(brush->sculpt_tool) ? true : ss->cache->original;
- BKE_pbvh_search_gather(ss->pbvh, sculpt_search_sphere_cb, &data, &nodes, &totnode);
+ const bool use_original = sculpt_tool_needs_original(brush->sculpt_tool) ? true : ss->cache->original;
+ const float radius_scale = 1.0f;
+ PBVHNode **nodes = sculpt_pbvh_gather_generic(ob, sd, brush, use_original, radius_scale, &totnode);
/* Only act if some verts are inside the brush area */
if (totnode) {
@@ -4461,10 +4528,9 @@ bool sculpt_stroke_get_location(bContext *C, float out[3], const float mouse[2])
}
}
- /* We may want to move this into a brush option, it could be useful in sculpt mode too. */
- const bool use_nearest = ((ob->mode & (OB_MODE_VERTEX_PAINT | OB_MODE_WEIGHT_PAINT)) != 0);
-
- if (hit == false && use_nearest) {
+ if (hit == false) {
+ const Brush *brush = BKE_paint_brush(BKE_paint_get_active_from_context(C));
+ if (ELEM(brush->falloff_shape, PAINT_FALLOFF_SHAPE_TUBE)) {
SculptFindNearestToRayData srd = {
.original = original,
.ss = ob->sculpt,
@@ -4483,6 +4549,7 @@ bool sculpt_stroke_get_location(bContext *C, float out[3], const float mouse[2])
mul_v3_fl(out, srd.depth);
add_v3_v3(out, ray_start);
}
+ }
}
//used in vwpaint
@@ -5520,7 +5587,7 @@ static int sculpt_detail_flood_fill_exec(bContext *C, wmOperator *UNUSED(op))
while (BKE_pbvh_bmesh_update_topology(
ss->pbvh, PBVH_Collapse | PBVH_Subdivide,
- center, NULL, size))
+ center, NULL, size, false, false))
{
for (i = 0; i < totnodes; i++)
BKE_pbvh_node_mark_topology_update(nodes[i]);
diff --git a/source/blender/editors/sculpt_paint/sculpt_intern.h b/source/blender/editors/sculpt_paint/sculpt_intern.h
index b9b662f4157..73581d402cf 100644
--- a/source/blender/editors/sculpt_paint/sculpt_intern.h
+++ b/source/blender/editors/sculpt_paint/sculpt_intern.h
@@ -182,7 +182,10 @@ typedef struct SculptBrushTest {
int mirror_symmetry_pass;
/* For circle (not sphere) projection. */
- float plane[4];
+ float plane_view[4];
+
+ /* Some tool code uses a plane for it's calculateions. */
+ float plane_tool[4];
/* View3d clipping - only set rv3d for clipping */
struct RegionView3D *clip_rv3d;
@@ -213,6 +216,10 @@ bool sculpt_brush_test_cube(SculptBrushTest *test, const float co[3], float loca
bool sculpt_brush_test_circle_sq(SculptBrushTest *test, const float co[3]);
bool sculpt_search_sphere_cb(PBVHNode *node, void *data_v);
bool sculpt_search_circle_cb(PBVHNode *node, void *data_v);
+
+SculptBrushTestFn sculpt_brush_test_init_with_falloff_shape(
+ SculptSession *ss, SculptBrushTest *test, char falloff_shape);
+
float tex_strength(
struct SculptSession *ss, const struct Brush *br,
const float point[3],
diff --git a/source/blender/makesdna/DNA_brush_types.h b/source/blender/makesdna/DNA_brush_types.h
index 67a35d4e207..6f239ec558b 100644
--- a/source/blender/makesdna/DNA_brush_types.h
+++ b/source/blender/makesdna/DNA_brush_types.h
@@ -95,8 +95,11 @@ typedef struct Brush {
float plane_offset; /* offset for plane brushes (clay, flatten, fill, scrape) */
int gradient_spacing;
- int gradient_stroke_mode; /* source for stroke color gradient application */
- int gradient_fill_mode; /* source for fill tool color gradient application */
+ char gradient_stroke_mode; /* source for stroke color gradient application */
+ char gradient_fill_mode; /* source for fill tool color gradient application */
+
+ char falloff_shape; /* Projection shape (sphere, circle) */
+ char pad[5];
char sculpt_tool; /* active sculpt tool */
char vertexpaint_tool; /* active vertex/weight paint blend mode (poorly named) */
@@ -343,6 +346,12 @@ typedef enum BlurKernelType {
KERNEL_BOX
} BlurKernelType;
+/* Brush.falloff_shape */
+enum {
+ PAINT_FALLOFF_SHAPE_SPHERE = 0,
+ PAINT_FALLOFF_SHAPE_TUBE = 1,
+};
+
#define MAX_BRUSH_PIXEL_RADIUS 500
#endif /* __DNA_BRUSH_TYPES_H__ */
diff --git a/source/blender/makesdna/DNA_scene_types.h b/source/blender/makesdna/DNA_scene_types.h
index 89a8a410f3e..830c584529c 100644
--- a/source/blender/makesdna/DNA_scene_types.h
+++ b/source/blender/makesdna/DNA_scene_types.h
@@ -1118,7 +1118,8 @@ typedef struct UvSculpt {
typedef struct VPaint {
Paint paint;
short flag;
- char falloff_shape, normal_angle;
+ char normal_angle;
+ char pad;
int radial_symm[3]; /* For mirrored painting */
} VPaint;
@@ -1132,12 +1133,6 @@ enum {
VP_FLAG_VGROUP_RESTRICT = (1 << 7)
};
-/* VPaint.falloff_shape */
-enum {
- VP_FALLOFF_SHAPE_SPHERE = 0,
- VP_FALLOFF_SHAPE_TUBE = 1,
-};
-
/* ------------------------------------------- */
/* GPencil Stroke Sculpting */
diff --git a/source/blender/makesrna/intern/rna_brush.c b/source/blender/makesrna/intern/rna_brush.c
index 0923fc92567..e6e8f6f5f95 100644
--- a/source/blender/makesrna/intern/rna_brush.c
+++ b/source/blender/makesrna/intern/rna_brush.c
@@ -1117,6 +1117,12 @@ static void rna_def_brush(BlenderRNA *brna)
RNA_def_property_update(prop, 0, "rna_Brush_update");
/* flag */
+ /* This is an enum but its unlikely we add other shapes, so expose as a boolean. */
+ prop = RNA_def_property(srna, "use_projected", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "falloff_shape", BRUSH_AIRBRUSH);
+ RNA_def_property_ui_text(prop, "2D Falloff", "Apply brush influence in 2D circle instead of a sphere");
+ RNA_def_property_update(prop, 0, "rna_Brush_update");
+
prop = RNA_def_property(srna, "use_airbrush", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "flag", BRUSH_AIRBRUSH);
RNA_def_property_ui_text(prop, "Airbrush", "Keep applying paint effect while holding mouse (spray)");
diff --git a/source/blender/makesrna/intern/rna_sculpt_paint.c b/source/blender/makesrna/intern/rna_sculpt_paint.c
index 6e493e2c865..6bd4aefed7a 100644
--- a/source/blender/makesrna/intern/rna_sculpt_paint.c
+++ b/source/blender/makesrna/intern/rna_sculpt_paint.c
@@ -671,18 +671,6 @@ static void rna_def_vertex_paint(BlenderRNA *brna)
RNA_def_struct_path_func(srna, "rna_VertexPaint_path");
RNA_def_struct_ui_text(srna, "Vertex Paint", "Properties of vertex and weight paint mode");
- static EnumPropertyItem prop_falloff_items[] = {
- {VP_FALLOFF_SHAPE_SPHERE, "SPHERE", 0, "Sphere", "Spherical falloff from the brush"},
- {VP_FALLOFF_SHAPE_TUBE, "TUBE", 0, "Circle", "Circular falloff from the brush along the view"},
- {0, NULL, 0, NULL, NULL}
- };
-
- prop = RNA_def_property(srna, "falloff_shape", PROP_ENUM, PROP_NONE);
- RNA_def_property_enum_sdna(prop, NULL, "falloff_shape");
- RNA_def_property_enum_items(prop, prop_falloff_items);
- RNA_def_property_ui_text(prop, "Falloff", "");
- RNA_def_property_update(prop, NC_SCENE | ND_TOOLSETTINGS, NULL);
-
prop = RNA_def_property(srna, "use_backface_culling", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_negative_sdna(prop, NULL, "flag", VP_FLAG_PROJECT_BACKFACE);
RNA_def_property_ui_text(prop, "Cull", "Ignore vertices pointing away from the view (faster)");