Sculpt: fix symmetry bug and mesh filter
smooth improvements * Fixed symmetry bug * Exposed a few hard edge options to the mesh filter tool * Updated default brushes inside of startup.blend.
This commit is contained in:
parent
6c16801001
commit
318bc8ea42
Binary file not shown.
|
@ -1346,6 +1346,15 @@ class _defs_sculpt:
|
|||
elif props.type == 'SPHERE':
|
||||
layout.prop(props, "sphere_center", expand=False)
|
||||
|
||||
if props.type in ["SMOOTH", "SPHERE", "SURFACE_SMOOTH", "SHARPEN"]:
|
||||
layout.prop(props, "weighted")
|
||||
|
||||
if props.type == "SMOOTH":
|
||||
#layout.prop(props, "hard_edge_fac")
|
||||
layout.prop(props, "hard_edge_mode")
|
||||
layout.prop(props, "preserve_fset_boundaries")
|
||||
layout.prop(props, "bound_smooth_radius")
|
||||
|
||||
return dict(idname="builtin.mesh_filter",
|
||||
label="Mesh Filter",
|
||||
icon="ops.sculpt.mesh_filter",
|
||||
|
|
|
@ -162,9 +162,13 @@ void BKE_brush_default_input_curves_set(struct Brush *brush);
|
|||
#define BKE_brush_tool_set(brush, p, tool) \
|
||||
{ \
|
||||
CHECK_TYPE_ANY(brush, struct Brush *); \
|
||||
char _old = *(char *)POINTER_OFFSET(brush, (p)->runtime.tool_offset); \
|
||||
*(char *)POINTER_OFFSET(brush, (p)->runtime.tool_offset) = tool; \
|
||||
if ((p)->runtime.ob_mode == OB_MODE_SCULPT) { \
|
||||
BKE_brush_builtin_patch(brush, tool); \
|
||||
if (_old != tool) { \
|
||||
BKE_brush_sculpt_reset(brush, tool); \
|
||||
} \
|
||||
} \
|
||||
} \
|
||||
((void)0)
|
||||
|
|
|
@ -537,7 +537,7 @@ BrushFlagMap brush_flags_map[] = {
|
|||
DEF(flag, accumulate, BRUSH_ACCUMULATE)
|
||||
DEF(flag2, use_weighted_smooth, BRUSH_SMOOTH_USE_AREA_WEIGHT)
|
||||
DEF(flag2, preserve_faceset_boundary, BRUSH_SMOOTH_PRESERVE_FACE_SETS)
|
||||
DEF(flag2, hard_edge_mode, BRUSH_HARD_EDGE_MODE)
|
||||
//DEF(flag2, hard_edge_mode, BRUSH_HARD_EDGE_MODE) don't convert, this only existed on temp_bmesh_multires
|
||||
DEF(flag2, grab_silhouette, BRUSH_GRAB_SILHOUETTE)
|
||||
DEF(flag, invert_to_scrape_fill, BRUSH_INVERT_TO_SCRAPE_FILL)
|
||||
DEF(flag2, use_multiplane_scrape_dynamic, BRUSH_MULTIPLANE_SCRAPE_DYNAMIC)
|
||||
|
@ -1703,13 +1703,14 @@ void BKE_brush_builtin_create(Brush *brush, int tool)
|
|||
break;
|
||||
case SCULPT_TOOL_CREASE:
|
||||
GETCH(direction)->ivalue = true;
|
||||
GETCH(strength)->fvalue = 0.25;
|
||||
GETCH(strength)->fvalue = 0.25f;
|
||||
GETCH(crease_pinch_factor)->fvalue = 0.5f;
|
||||
break;
|
||||
case SCULPT_TOOL_SCRAPE:
|
||||
case SCULPT_TOOL_FILL:
|
||||
GETCH(strength)->fvalue = 0.7f;
|
||||
GETCH(area_radius_factor)->fvalue = 0.5f;
|
||||
GETCH(spacing)->fvalue = 7;
|
||||
GETCH(spacing)->fvalue = 7.0f;
|
||||
ADDCH(invert_to_scrape_fill);
|
||||
GETCH(invert_to_scrape_fill)->ivalue = true;
|
||||
GETCH(accumulate)->ivalue = true;
|
||||
|
@ -1805,6 +1806,11 @@ void BKE_brush_channelset_check_radius(BrushChannelSet *chset)
|
|||
return;
|
||||
}
|
||||
|
||||
if (ch1->fvalue == 0.0 || ch2->fvalue == 0.0) {
|
||||
ch1->fvalue = 100.0f;
|
||||
ch2->fvalue = 0.1f;
|
||||
}
|
||||
|
||||
int mask = BRUSH_CHANNEL_INHERIT | BRUSH_CHANNEL_INHERIT_IF_UNSET |
|
||||
/*BRUSH_CHANNEL_SHOW_IN_HEADER | BRUSH_CHANNEL_SHOW_IN_WORKSPACE |*/
|
||||
BRUSH_CHANNEL_UI_EXPANDED;
|
||||
|
|
|
@ -1510,8 +1510,9 @@ static void layerDynTopoVert_copy(const void *source, void *dest, int count)
|
|||
static void layerDynTopoVert_interp(
|
||||
const void **sources, const float *weights, const float *sub_weights, int count, void *dest)
|
||||
{
|
||||
float co[3], no[3], origmask, color[4];
|
||||
float co[3], no[3], origmask, color[4], curv;
|
||||
MSculptVert *mv = (MSculptVert *)dest;
|
||||
|
||||
// float totweight = 0.0f;
|
||||
|
||||
if (count == 0) {
|
||||
|
@ -1522,6 +1523,7 @@ static void layerDynTopoVert_interp(
|
|||
zero_v3(co);
|
||||
zero_v3(no);
|
||||
origmask = 0.0f;
|
||||
curv = 0.0f;
|
||||
zero_v4(color);
|
||||
|
||||
for (int i = 0; i < count; i++) {
|
||||
|
@ -1538,7 +1540,8 @@ static void layerDynTopoVert_interp(
|
|||
madd_v3_v3fl(co, mv2->origco, w);
|
||||
madd_v3_v3fl(no, mv2->origno, w);
|
||||
madd_v4_v4fl(color, mv2->origcolor, w);
|
||||
origmask += mv2->origmask * w;
|
||||
origmask += (float)mv2->origmask * w;
|
||||
curv += (float)mv2->curv * w;
|
||||
|
||||
// totweight += w;
|
||||
}
|
||||
|
@ -1561,7 +1564,8 @@ static void layerDynTopoVert_interp(
|
|||
copy_v3_v3(mv->origno, no);
|
||||
copy_v4_v4(mv->origcolor, color);
|
||||
|
||||
mv->origmask = origmask;
|
||||
mv->curv = (short)curv;
|
||||
mv->origmask = (short)origmask;
|
||||
}
|
||||
|
||||
static void layerInterp_noop(const void **UNUSED(sources),
|
||||
|
|
|
@ -35,6 +35,7 @@
|
|||
#include <stdio.h>
|
||||
|
||||
//#define DYNTOPO_REPORT
|
||||
//#define WITH_ADAPTIVE_CURVATURE
|
||||
|
||||
#define SCULPTVERT_VALENCE_TEMP SCULPTVERT_SPLIT_TEMP
|
||||
|
||||
|
@ -1422,8 +1423,10 @@ static void edge_queue_insert_val34_vert(EdgeQueueContext *eq_ctx, BMVert *v)
|
|||
eq_ctx->val34_verts[eq_ctx->val34_verts_tot - 1] = v;
|
||||
}
|
||||
|
||||
BLI_INLINE float maskcb_get(EdgeQueueContext *eq_ctx, BMEdge *e)
|
||||
ATTR_NO_OPT static float maskcb_get(EdgeQueueContext *eq_ctx, BMEdge *e)
|
||||
{
|
||||
float ret = 0.0f;
|
||||
|
||||
if (eq_ctx->mask_cb) {
|
||||
SculptVertRef sv1 = {(intptr_t)e->v1};
|
||||
SculptVertRef sv2 = {(intptr_t)e->v2};
|
||||
|
@ -1431,13 +1434,16 @@ BLI_INLINE float maskcb_get(EdgeQueueContext *eq_ctx, BMEdge *e)
|
|||
float w1 = eq_ctx->mask_cb(sv1, eq_ctx->mask_cb_data);
|
||||
float w2 = eq_ctx->mask_cb(sv2, eq_ctx->mask_cb_data);
|
||||
|
||||
return (w1 + w2) * 0.5f;
|
||||
ret = (w1 + w2) * 0.5f;
|
||||
}
|
||||
else {
|
||||
ret = 1.0f;
|
||||
}
|
||||
|
||||
return 1.0f;
|
||||
return ret;
|
||||
}
|
||||
|
||||
BLI_INLINE float calc_weighted_edge_split(EdgeQueueContext *eq_ctx, BMVert *v1, BMVert *v2)
|
||||
ATTR_NO_OPT static float calc_weighted_edge_split(EdgeQueueContext *eq_ctx, BMVert *v1, BMVert *v2)
|
||||
{
|
||||
#ifdef FANCY_EDGE_WEIGHTS
|
||||
float l = len_squared_v3v3(v1->co, v2->co);
|
||||
|
@ -1461,12 +1467,27 @@ BLI_INLINE float calc_weighted_edge_split(EdgeQueueContext *eq_ctx, BMVert *v1,
|
|||
|
||||
return l;
|
||||
#else
|
||||
|
||||
# ifdef WITH_ADAPTIVE_CURVATURE
|
||||
MSculptVert *mv1 = BKE_PBVH_SCULPTVERT(eq_ctx->cd_sculpt_vert, v1);
|
||||
MSculptVert *mv2 = BKE_PBVH_SCULPTVERT(eq_ctx->cd_sculpt_vert, v2);
|
||||
|
||||
float c1 = (float)mv1->curv / 65535.0f;
|
||||
float c2 = (float)mv2->curv / 65535.0f;
|
||||
float fac = 1.0f + powf((c1 + c2) * 100.0, 4.0f);
|
||||
fac = min_ff(fac, 4.0f);
|
||||
|
||||
return fac * len_squared_v3v3(v1->co, v2->co);
|
||||
# else
|
||||
return len_squared_v3v3(v1->co, v2->co);
|
||||
# endif
|
||||
#endif
|
||||
}
|
||||
|
||||
BLI_INLINE float calc_weighted_edge_collapse(EdgeQueueContext *eq_ctx, BMVert *v1, BMVert *v2)
|
||||
{
|
||||
return calc_weighted_edge_split(eq_ctx, v1, v2);
|
||||
|
||||
#ifdef FANCY_EDGE_WEIGHTS
|
||||
float l = len_squared_v3v3(v1->co, v2->co);
|
||||
// float val = (float)BM_vert_edge_count(v1) + (float)BM_vert_edge_count(v2);
|
||||
|
@ -1812,7 +1833,7 @@ static void long_edge_queue_edge_add(EdgeQueueContext *eq_ctx, BMEdge *e)
|
|||
#endif
|
||||
{
|
||||
const float w = maskcb_get(eq_ctx, e);
|
||||
const float len_sq = BM_edge_calc_length_squared(e) * w * w;
|
||||
const float len_sq = calc_weighted_edge_split(eq_ctx, e->v1, e->v2) * w * w;
|
||||
|
||||
if (len_sq > eq_ctx->q->limit_len_squared) {
|
||||
edge_queue_insert(eq_ctx, e, -len_sq, eq_ctx->q->limit_len);
|
||||
|
@ -1855,7 +1876,8 @@ static void long_edge_queue_edge_add_recursive(EdgeQueueContext *eq_ctx,
|
|||
do {
|
||||
BMLoop *l_adjacent[2] = {l_iter->next, l_iter->prev};
|
||||
for (int i = 0; i < (int)ARRAY_SIZE(l_adjacent); i++) {
|
||||
float len_sq_other = BM_edge_calc_length_squared(l_adjacent[i]->e);
|
||||
float len_sq_other = calc_weighted_edge_split(
|
||||
eq_ctx, l_adjacent[i]->e->v1, l_adjacent[i]->e->v2);
|
||||
float w = maskcb_get(eq_ctx, l_adjacent[i]->e);
|
||||
|
||||
len_sq_other *= w * w;
|
||||
|
@ -1906,7 +1928,7 @@ static void long_edge_queue_face_add(EdgeQueueContext *eq_ctx, BMFace *f, bool i
|
|||
BMLoop *l_iter = l_first;
|
||||
do {
|
||||
#ifdef USE_EDGEQUEUE_EVEN_SUBDIV
|
||||
float len_sq = BM_edge_calc_length_squared(l_iter->e);
|
||||
float len_sq = calc_weighted_edge_split(eq_ctx, l_iter->e->v1, l_iter->e->v2);
|
||||
float w = maskcb_get(eq_ctx, l_iter->e);
|
||||
|
||||
len_sq *= w * w;
|
||||
|
@ -2187,8 +2209,7 @@ static void long_edge_queue_task_cb(void *__restrict userdata,
|
|||
|
||||
#ifdef USE_EDGEQUEUE_EVEN_SUBDIV
|
||||
float w = maskcb_get(eq_ctx, l_iter->e);
|
||||
float len_sq = BM_edge_calc_length_squared(l_iter->e);
|
||||
|
||||
float len_sq = calc_weighted_edge_split(eq_ctx, l_iter->e->v1, l_iter->e->v2);
|
||||
len_sq *= w * w;
|
||||
|
||||
if (len_sq > eq_ctx->q->limit_len_squared) {
|
||||
|
|
|
@ -817,6 +817,10 @@ void BKE_pbvh_bmesh_update_origvert(
|
|||
BM_log_vert_before_modified(pbvh->bm_log, v, pbvh->cd_vert_mask_offset, r_color != NULL);
|
||||
}
|
||||
|
||||
if (pbvh->cd_vert_mask_offset) {
|
||||
mv->origmask = (short)(BM_ELEM_CD_GET_FLOAT(v, pbvh->cd_vert_mask_offset) * 65535.0f);
|
||||
}
|
||||
|
||||
if (r_co || r_no) {
|
||||
|
||||
copy_v3_v3(mv->origco, v->co);
|
||||
|
@ -1489,16 +1493,20 @@ static int color_boundary_key(float col[4])
|
|||
}
|
||||
#endif
|
||||
|
||||
void bke_pbvh_update_vert_boundary(int cd_sculpt_vert,
|
||||
int cd_faceset_offset,
|
||||
int cd_vert_node_offset,
|
||||
int cd_face_node_offset,
|
||||
int cd_vcol,
|
||||
BMVert *v,
|
||||
int bound_symmetry)
|
||||
ATTR_NO_OPT void bke_pbvh_update_vert_boundary(int cd_sculpt_vert,
|
||||
int cd_faceset_offset,
|
||||
int cd_vert_node_offset,
|
||||
int cd_face_node_offset,
|
||||
int cd_vcol,
|
||||
BMVert *v,
|
||||
int bound_symmetry)
|
||||
{
|
||||
MSculptVert *mv = BKE_PBVH_SCULPTVERT(cd_sculpt_vert, v);
|
||||
|
||||
float avg[3] = {0.0f, 0.0f, 0.0f};
|
||||
float avg_len = 0.0f;
|
||||
float curv = 0.0f, totcurv = 0.0f;
|
||||
|
||||
BMEdge *e = v->e;
|
||||
mv->flag &= ~(SCULPTVERT_BOUNDARY | SCULPTVERT_FSET_BOUNDARY | SCULPTVERT_NEED_BOUNDARY |
|
||||
SCULPTVERT_NEED_TRIANGULATE | SCULPTVERT_FSET_CORNER | SCULPTVERT_CORNER |
|
||||
|
@ -1536,6 +1544,17 @@ void bke_pbvh_update_vert_boundary(int cd_sculpt_vert,
|
|||
do {
|
||||
BMVert *v2 = v == e->v1 ? e->v2 : e->v1;
|
||||
|
||||
#if 0
|
||||
float tmp[3];
|
||||
sub_v3_v3v3(tmp, v2->co, v->co);
|
||||
madd_v3_v3fl(avg, v->no, -dot_v3v3(v->no, tmp));
|
||||
// madd_v3_v3fl(tmp, v->no, -dot_v3v3(v->no, tmp));
|
||||
add_v3_v3(avg, tmp);
|
||||
|
||||
avg_len += len_squared_v3(tmp);
|
||||
totcurv += 1.0f;
|
||||
#endif
|
||||
|
||||
if (BM_ELEM_CD_GET_INT(v2, cd_vert_node_offset) != ni) {
|
||||
mv->flag |= SCULPTVERT_PBVH_BOUNDARY;
|
||||
}
|
||||
|
@ -1612,6 +1631,11 @@ void bke_pbvh_update_vert_boundary(int cd_sculpt_vert,
|
|||
// also check e->l->radial_next, in case we are not manifold
|
||||
// which can mess up the loop order
|
||||
if (e->l->radial_next != e->l) {
|
||||
float th = saacos(dot_v3v3(e->l->f->no, e->l->radial_next->f->no)) * M_1_PI * 0.25f;
|
||||
// th = th * 0.5 + 0.5;
|
||||
curv += th;
|
||||
totcurv += 1.0f;
|
||||
|
||||
// fset = abs(BM_ELEM_CD_GET_INT(e->l->radial_next->f, cd_faceset_offset));
|
||||
int fset2 = BKE_pbvh_do_fset_symmetry(
|
||||
BM_ELEM_CD_GET_INT(e->l->radial_next->f, cd_faceset_offset), bound_symmetry, v2->co);
|
||||
|
@ -1661,6 +1685,27 @@ void bke_pbvh_update_vert_boundary(int cd_sculpt_vert,
|
|||
mv->flag |= SCULPTVERT_CORNER;
|
||||
}
|
||||
|
||||
#if 0
|
||||
if (totcurv > 0.0f) {
|
||||
mul_v3_fl(avg, 1.0f / totcurv);
|
||||
avg_len /= totcurv;
|
||||
}
|
||||
|
||||
if (avg_len > 0.0f) {
|
||||
curv = len_squared_v3(avg) / avg_len;
|
||||
}
|
||||
else {
|
||||
curv = 0.0f;
|
||||
}
|
||||
#else
|
||||
if (totcurv > 0.0f) {
|
||||
curv /= totcurv;
|
||||
}
|
||||
#endif
|
||||
|
||||
// mv->curv = (short)(fabsf(min_ff(curv * 50.0f, 1.0f)) * 32767.0f);
|
||||
mv->curv = (short)(min_ff(fabsf(curv), 1.0f) * 65535.0f);
|
||||
|
||||
BLI_array_free(fsets);
|
||||
}
|
||||
|
||||
|
|
|
@ -2985,7 +2985,7 @@ bool SCULPT_vertex_check_origdata(SculptSession *ss, SculptVertRef vertex)
|
|||
copy_v4_v4(mv->origcolor, color);
|
||||
}
|
||||
|
||||
mv->origmask = SCULPT_vertex_mask_get(ss, vertex);
|
||||
mv->origmask = (short)(SCULPT_vertex_mask_get(ss, vertex) * 65535.0f);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
@ -3014,7 +3014,7 @@ void SCULPT_orig_vert_data_update(SculptOrigVertData *orig_data, SculptVertRef v
|
|||
orig_data->col = mv->origcolor;
|
||||
}
|
||||
else if (orig_data->datatype == SCULPT_UNDO_MASK) {
|
||||
orig_data->mask = mv->origmask;
|
||||
orig_data->mask = (float)mv->origmask / 65535.0f;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -9690,12 +9690,6 @@ static void SCULPT_run_command(
|
|||
|
||||
/*create final, input mapped parameter list*/
|
||||
|
||||
BKE_brush_channelset_free(cmd->params_mapped);
|
||||
|
||||
cmd->params_mapped = BKE_brush_channelset_copy(cmd->params_final);
|
||||
BKE_brush_channelset_apply_mapping(cmd->params_mapped, &ss->cache->input_mapping);
|
||||
BKE_brush_channelset_clear_inherit(cmd->params_mapped);
|
||||
|
||||
radius_scale = 1.0f;
|
||||
|
||||
*brush2 = *brush;
|
||||
|
@ -10071,6 +10065,14 @@ static void SCULPT_run_commandlist(
|
|||
.totnode = 0,
|
||||
.radius_max = radius_max}; //, .nodes = nodes, .totnode = totnode};
|
||||
|
||||
if (cmd->params_mapped) {
|
||||
BKE_brush_channelset_free(cmd->params_mapped);
|
||||
}
|
||||
|
||||
cmd->params_mapped = BKE_brush_channelset_copy(cmd->params_final);
|
||||
BKE_brush_channelset_apply_mapping(cmd->params_mapped, &ss->cache->input_mapping);
|
||||
BKE_brush_channelset_clear_inherit(cmd->params_mapped);
|
||||
|
||||
do_symmetrical_brush_actions(sd, ob, SCULPT_run_command, ups, &data);
|
||||
|
||||
sculpt_combine_proxies(sd, ob);
|
||||
|
|
|
@ -963,7 +963,7 @@ static void do_cloth_brush_build_constraints_task_cb_ex(
|
|||
use_persistent);
|
||||
}
|
||||
else if (mp1->totloop == 4) {
|
||||
ml1 = (ml1 + 1) % mp1->loopstart;
|
||||
ml1 = (ml1 + 1) % mp1->loopstart;
|
||||
|
||||
cloth_brush_add_bend_constraint(ss,
|
||||
data->cloth_sim,
|
||||
|
|
|
@ -331,7 +331,20 @@ static void mesh_filter_task_cb(void *__restrict userdata,
|
|||
/* This produces better results as the relax operation is no completely focused on the
|
||||
* boundaries. */
|
||||
const bool relax_face_sets = !(ss->filter_cache->iteration_count % 3 == 0);
|
||||
const bool weighted = false;
|
||||
const bool weighted = ss->filter_cache->weighted_smooth;
|
||||
const bool preserve_fset_boundaries = ss->filter_cache->preserve_fset_boundaries;
|
||||
// const float hard_edge_fac = ss->filter_cache->hard_edge_fac;
|
||||
const bool hard_edge_mode = ss->filter_cache->hard_edge_mode;
|
||||
const float bound_smooth_radius = ss->filter_cache->bound_smooth_radius;
|
||||
|
||||
if (ELEM(filter_type,
|
||||
MESH_FILTER_SMOOTH,
|
||||
MESH_FILTER_SURFACE_SMOOTH,
|
||||
MESH_FILTER_SHARPEN,
|
||||
MESH_FILTER_RELAX,
|
||||
MESH_FILTER_RELAX_FACE_SETS)) {
|
||||
BKE_pbvh_check_tri_areas(ss->pbvh, node);
|
||||
}
|
||||
|
||||
PBVHVertexIter vd;
|
||||
BKE_pbvh_vertex_iter_begin (ss->pbvh, node, vd, PBVH_ITER_UNIQUE) {
|
||||
|
@ -365,20 +378,24 @@ static void mesh_filter_task_cb(void *__restrict userdata,
|
|||
|
||||
switch (filter_type) {
|
||||
case MESH_FILTER_SMOOTH: {
|
||||
// float bound_smooth = SCULPT_get_float(ss, boundary_smooth, ss->, ss->cache->brush);
|
||||
// float projection = SCULPT_get_float(ss, autosmooth_projection, NULL, ss->cache->brush);
|
||||
// float slide_fset = SCULPT_get_float(ss, fset_slide, NULL, ss->cache->brush);
|
||||
|
||||
fade = clamp_f(fade, -1.0f, 1.0f);
|
||||
float bsmooth = bound_smooth_radius > 0.0f ? 0.5f : 0.0f;
|
||||
float slide_fset = bound_smooth_radius > 0.0f ?
|
||||
bsmooth :
|
||||
1.0f - (float)hard_edge_mode; // powf(1.0 - hard_edge_fac, 0.5f);
|
||||
|
||||
SCULPT_neighbor_coords_average_interior(
|
||||
ss,
|
||||
avg,
|
||||
vd.vertex,
|
||||
&((SculptSmoothArgs){.projection = 0.0f,
|
||||
.slide_fset = 0.0f,
|
||||
.bound_smooth = 0.0f,
|
||||
.preserve_fset_boundaries = false,
|
||||
.do_weighted_smooth = false}));
|
||||
.slide_fset = slide_fset, // 1.0f - hard_edge_fac,
|
||||
.bound_smooth = bsmooth,
|
||||
.preserve_fset_boundaries = preserve_fset_boundaries,
|
||||
.do_weighted_smooth = weighted,
|
||||
.bound_smooth_radius = bound_smooth_radius,
|
||||
.bound_scl = bsmooth > 0.0f ? &ss->filter_cache->bound_scl :
|
||||
NULL}));
|
||||
|
||||
sub_v3_v3v3(val, avg, orig_co);
|
||||
madd_v3_v3v3fl(val, orig_co, val, fade);
|
||||
|
@ -535,6 +552,7 @@ static void mesh_filter_task_cb(void *__restrict userdata,
|
|||
}
|
||||
BKE_pbvh_vertex_iter_end;
|
||||
|
||||
BKE_pbvh_node_mark_update_tri_area(node);
|
||||
BKE_pbvh_node_mark_update(node);
|
||||
}
|
||||
|
||||
|
@ -868,6 +886,17 @@ static int sculpt_mesh_filter_invoke(bContext *C, wmOperator *op, const wmEvent
|
|||
SculptFilterOrientation orientation = RNA_enum_get(op->ptr, "orientation");
|
||||
ss->filter_cache->orientation = orientation;
|
||||
|
||||
ss->filter_cache->weighted_smooth = RNA_boolean_get(op->ptr, "weighted");
|
||||
ss->filter_cache->preserve_fset_boundaries = RNA_boolean_get(op->ptr,
|
||||
"preserve_fset_boundaries");
|
||||
// ss->filter_cache->hard_edge_fac = RNA_float_get(op->ptr, "hard_edge_fac");
|
||||
ss->filter_cache->hard_edge_mode = RNA_boolean_get(op->ptr, "hard_edge_mode");
|
||||
ss->filter_cache->bound_smooth_radius = RNA_float_get(op->ptr, "bound_smooth_radius");
|
||||
|
||||
if (filter_type == MESH_FILTER_SMOOTH && ss->filter_cache->bound_smooth_radius != 0.0f) {
|
||||
SCULPT_bound_smooth_init(ss, &ss->filter_cache->bound_scl);
|
||||
}
|
||||
|
||||
WM_event_add_modal_handler(C, op);
|
||||
return OPERATOR_RUNNING_MODAL;
|
||||
}
|
||||
|
@ -963,4 +992,28 @@ void SCULPT_OT_mesh_filter(struct wmOperatorType *ot)
|
|||
MESH_FILTER_SPHERE_CENTER_AVERAGE,
|
||||
"Sphere Center",
|
||||
"Position of the center of the sphere created by the filter");
|
||||
|
||||
RNA_def_boolean(ot->srna, "weighted", true, "Weighted", "Weight smoothing by face areas");
|
||||
RNA_def_boolean(ot->srna,
|
||||
"preserve_fset_boundaries",
|
||||
true,
|
||||
"Preserve Face Sets",
|
||||
"Preserve face set boundaries");
|
||||
// RNA_def_float(ot->srna, "hard_edge_fac", 0.0f, 0.0f, 1.0f, "Hard Edge Factor", "",
|
||||
// 0.0f, 1.0f);
|
||||
RNA_def_boolean(ot->srna,
|
||||
"hard_edge_mode",
|
||||
false,
|
||||
"Hard Edge Mode",
|
||||
"Treat face set boundaries as hard edges");
|
||||
|
||||
RNA_def_float(ot->srna,
|
||||
"bound_smooth_radius",
|
||||
0.0,
|
||||
0.0,
|
||||
1000.0f,
|
||||
"Bevel Radius",
|
||||
"Radius to bevel hard edges, 0 disables",
|
||||
0.0f,
|
||||
5.0f);
|
||||
}
|
||||
|
|
|
@ -412,6 +412,7 @@ typedef struct SculptSmoothArgs {
|
|||
bool do_origco : 1;
|
||||
bool do_weighted_smooth : 1;
|
||||
bool preserve_fset_boundaries : 1;
|
||||
float bound_smooth_radius; // if 0, ss->cache->radius will be used
|
||||
} SculptSmoothArgs;
|
||||
|
||||
/* Utils. */
|
||||
|
@ -1690,6 +1691,13 @@ typedef struct FilterCache {
|
|||
|
||||
GHash *mask_delta_step;
|
||||
|
||||
bool preserve_fset_boundaries;
|
||||
bool weighted_smooth;
|
||||
float hard_edge_fac;
|
||||
bool hard_edge_mode;
|
||||
float bound_smooth_radius;
|
||||
|
||||
struct SculptCustomLayer bound_scl;
|
||||
} FilterCache;
|
||||
|
||||
void SCULPT_cache_calc_brushdata_symm(StrokeCache *cache,
|
||||
|
@ -1997,6 +2005,10 @@ void SCULPT_replay_test(void);
|
|||
|
||||
struct BMesh *SCULPT_dyntopo_empty_bmesh();
|
||||
|
||||
/* initializes customdata layer used by SCULPT_neighbor_coords_average_interior when bound_smooth >
|
||||
* 0.0f*/
|
||||
void SCULPT_bound_smooth_init(SculptSession *ss, SculptCustomLayer *r_bound_scl);
|
||||
|
||||
#define SCULPT_stroke_needs_original(brush) \
|
||||
ELEM(brush->sculpt_tool, \
|
||||
SCULPT_TOOL_DRAW_SHARP, \
|
||||
|
|
|
@ -74,10 +74,10 @@
|
|||
#include <math.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
void SCULPT_neighbor_coords_average_interior(SculptSession *ss,
|
||||
float result[3],
|
||||
SculptVertRef vertex,
|
||||
SculptSmoothArgs *args)
|
||||
ATTR_NO_OPT void SCULPT_neighbor_coords_average_interior(SculptSession *ss,
|
||||
float result[3],
|
||||
SculptVertRef vertex,
|
||||
SculptSmoothArgs *args)
|
||||
{
|
||||
float avg[3] = {0.0f, 0.0f, 0.0f};
|
||||
|
||||
|
@ -155,7 +155,10 @@ void SCULPT_neighbor_coords_average_interior(SculptSession *ss,
|
|||
if (bound_scl) {
|
||||
b1 = SCULPT_temp_cdata_get(vertex, bound_scl);
|
||||
b1_orig = *b1;
|
||||
*b1 = 0.0f;
|
||||
|
||||
if (1 || is_boundary) {
|
||||
*b1 = 0.0f;
|
||||
}
|
||||
}
|
||||
|
||||
SculptVertexNeighborIter ni;
|
||||
|
@ -276,12 +279,22 @@ void SCULPT_neighbor_coords_average_interior(SculptSession *ss,
|
|||
copy_v3_v3(no2, mv2->origno);
|
||||
}
|
||||
|
||||
float radius = ss->cache->radius * 10.0f;
|
||||
float radius;
|
||||
if (!args->bound_smooth_radius && ss->cache) {
|
||||
radius = ss->cache->radius * 1.0f;
|
||||
}
|
||||
else {
|
||||
radius = args->bound_smooth_radius * 1.0f;
|
||||
}
|
||||
|
||||
radius = radius == 0.0f ? 0.0001f : radius;
|
||||
|
||||
float th = radius - b1_orig;
|
||||
th = MAX2(th, 0.0f);
|
||||
th /= radius;
|
||||
|
||||
// th = 1.0 - th;
|
||||
|
||||
#if 0
|
||||
float *color = (float *)SCULPT_vertex_color_get(ss, ni.vertex);
|
||||
color[0] = color[1] = color[2] = th;
|
||||
|
@ -291,10 +304,24 @@ void SCULPT_neighbor_coords_average_interior(SculptSession *ss,
|
|||
float fac = bound_smooth;
|
||||
fac = MIN2(fac * 4.0f, 1.0f);
|
||||
fac = powf(fac, 0.2);
|
||||
th *= fac;
|
||||
// th *= fac;
|
||||
// th *= shell_angle_to_dist(shellth * 1.0) * 0.5;
|
||||
|
||||
sub_v3_v3(tmp, co);
|
||||
madd_v3_v3fl(tmp, no2, th * dot_v3v3(no2, tmp));
|
||||
/* jump above the v,no2 plane, using distance from plane (which doubles after this)*/
|
||||
// sub_v3_v3(tmp, co);
|
||||
// madd_v3_v3fl(tmp, no2, th * dot_v3v3(no2, tmp));
|
||||
// add_v3_v3(tmp, co);
|
||||
|
||||
th = min_ff(b1_orig / radius, 1.0f);
|
||||
|
||||
/*ok this bit smoothes the bevel edges. why? hit on it
|
||||
by accident.*/
|
||||
float shellth = saacos(dot_v3v3(no, no2));
|
||||
shellth = shell_angle_to_dist(shellth * 2.0);
|
||||
th /= 0.00001 + shellth;
|
||||
|
||||
sub_v3_v3v3(tmp, co2, co);
|
||||
madd_v3_v3fl(tmp, no, -dot_v3v3(no, tmp) * th);
|
||||
add_v3_v3(tmp, co);
|
||||
}
|
||||
|
||||
|
@ -353,7 +380,7 @@ void SCULPT_neighbor_coords_average_interior(SculptSession *ss,
|
|||
corner_smooth = MAX2(slide_fset, bound_smooth);
|
||||
}
|
||||
else {
|
||||
corner_smooth = bound_smooth;
|
||||
corner_smooth = 2.0f * bound_smooth;
|
||||
}
|
||||
|
||||
interp_v3_v3v3(result, result, co, 1.0f - corner_smooth);
|
||||
|
@ -1139,6 +1166,13 @@ static void do_smooth_brush_task_cb_ex(void *__restrict userdata,
|
|||
}
|
||||
#endif
|
||||
|
||||
void SCULPT_bound_smooth_init(SculptSession *ss, SculptCustomLayer *r_bound_scl)
|
||||
{
|
||||
SculptLayerParams params = {.permanent = true, .simple_array = false};
|
||||
SCULPT_temp_customlayer_get(
|
||||
ss, ATTR_DOMAIN_POINT, CD_PROP_COLOR, "t__smooth_bdist", r_bound_scl, ¶ms);
|
||||
}
|
||||
|
||||
void SCULPT_smooth(Sculpt *sd,
|
||||
Object *ob,
|
||||
PBVHNode **nodes,
|
||||
|
@ -1213,12 +1247,7 @@ void SCULPT_smooth(Sculpt *sd,
|
|||
bound_smooth = powf(ss->cache->brush->boundary_smooth_factor, BOUNDARY_SMOOTH_EXP);
|
||||
|
||||
bound_scl = &_scl;
|
||||
SculptLayerParams params = {.permanent = false, .simple_array = false};
|
||||
|
||||
SCULPT_temp_customlayer_ensure(
|
||||
ss, ATTR_DOMAIN_POINT, CD_PROP_FLOAT, "__smooth_bdist", ¶ms);
|
||||
SCULPT_temp_customlayer_get(
|
||||
ss, ATTR_DOMAIN_POINT, CD_PROP_FLOAT, "__smooth_bdist", bound_scl, ¶ms);
|
||||
SCULPT_bound_smooth_init(ss, bound_scl);
|
||||
|
||||
if (do_vel_smooth) {
|
||||
SCULPT_temp_customlayer_get(
|
||||
|
|
|
@ -526,7 +526,7 @@ typedef struct MRecast {
|
|||
/** \} */
|
||||
|
||||
typedef struct MSculptVert {
|
||||
short flag, valence;
|
||||
unsigned short flag, valence;
|
||||
|
||||
/**original coordinates*/
|
||||
float origco[3], origno[3];
|
||||
|
@ -534,7 +534,13 @@ typedef struct MSculptVert {
|
|||
/**original color*/
|
||||
float origcolor[4];
|
||||
|
||||
float origmask;
|
||||
unsigned short origmask;
|
||||
|
||||
/* curv is a fast curvature approximation used by dyntopo
|
||||
adaptive curvature. */
|
||||
unsigned short curv;
|
||||
|
||||
/* curvature_dir parallels a principle curvature direction */
|
||||
float curvature_dir[3];
|
||||
|
||||
/* id of current stroke, used to detect
|
||||
|
|
Loading…
Reference in New Issue