Sculpt: Fix topology rake updating original coordinates

This commit is contained in:
Joseph Eagar 2021-10-05 00:17:15 -07:00
parent 4d8648a9f3
commit e557b2096a
8 changed files with 123 additions and 61 deletions

View File

@ -791,6 +791,8 @@ void BKE_brush_channelset_merge(BrushChannelSet *dst,
continue;
}
/*TODO: should inherit if unset should always apply, i.e. this block should be moved above the
* previous one?*/
if (ch->type == BRUSH_CHANNEL_TYPE_BITMASK && (ch->flag & BRUSH_CHANNEL_INHERIT_IF_UNSET)) {
mch->ivalue = ch->ivalue | pch->ivalue;
}
@ -1537,7 +1539,7 @@ void BKE_builtin_apply_hard_edge_mode(BrushChannelSet *chset, bool do_apply)
ch->ivalue = 1;
}
//turn off dyntopo surface smoothing
// turn off dyntopo surface smoothing
ch = BRUSHSET_LOOKUP(chset, dyntopo_disable_smooth);
if (ch) {
ch->flag &= ~BRUSH_CHANNEL_INHERIT;

View File

@ -514,6 +514,7 @@ BrushFlagMap brush_flags_map[] = {
DEF(flag, use_plane_trim, BRUSH_PLANE_TRIM)
DEF(flag2, use_surface_falloff, BRUSH_USE_SURFACE_FALLOFF)
DEF(flag2, use_grab_active_vertex, BRUSH_GRAB_ACTIVE_VERTEX)
DEF(flag, accumulate, BRUSH_ACCUMULATE)
};
int brush_flags_map_len = ARRAY_SIZE(brush_flags_map);
@ -1465,7 +1466,7 @@ void BKE_brush_builtin_create(Brush *brush, int tool)
BRUSHSET_SET_FLOAT(chset, strength, 0.5);
BRUSHSET_SET_FLOAT(chset, autosmooth, 0.05);
BRUSHSET_SET_INT(chset, topology_rake_mode, 1); // curvature mode
BRUSHSET_SET_FLOAT(chset, topology_rake, 0.35);
BRUSHSET_SET_FLOAT(chset, topology_rake, 0.5);
BrushChannel *ch = BRUSHSET_LOOKUP(chset, dyntopo_mode);
ch->flag &= ~BRUSH_CHANNEL_INHERIT;

View File

@ -1512,7 +1512,7 @@ static void layerDynTopoVert_interp(
{
float co[3], no[3], origmask, color[4];
MDynTopoVert *mv = (MDynTopoVert *)dest;
float totweight = 0.0f;
// float totweight = 0.0f;
if (count == 0) {
memset(mv, 0, sizeof(*mv));
@ -1533,28 +1533,29 @@ static void layerDynTopoVert_interp(
mv->stroke_id = mv2->stroke_id;
}
if (sub_weights) {
w = sub_weights[i];
}
else {
w = 1.0f;
}
w = weights[i];
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;
totweight += w;
// totweight += w;
}
normalize_v3(no);
#if 0
if (fabsf(totweight - 1.0) > 0.001) {
printf("eek\n");
}
float mul = 1.0f / totweight;
mul_v3_fl(co, mul);
normalize_v3(no);
mul_v4_fl(color, mul);
origmask *= mul;
#endif
copy_v3_v3(mv->origco, co);
copy_v3_v3(mv->origno, no);

View File

@ -1980,9 +1980,9 @@ BLI_INLINE int dyntopo_thread_rand(int seed)
return (seed * multiplier + addend) & mask;
}
static void long_edge_queue_task_cb(void *__restrict userdata,
const int n,
const TaskParallelTLS *__restrict tls)
static void long_edge_queue_task_cb(void *__restrict userdata,
const int n,
const TaskParallelTLS *__restrict tls)
{
EdgeQueueThreadData *tdata = ((EdgeQueueThreadData *)userdata) + n;
PBVHNode *node = tdata->node;
@ -3930,7 +3930,13 @@ static void pbvh_bmesh_collapse_edge(PBVH *pbvh,
copy_v3_v3(v_conn->co, co);
}
else {
float co[3];
add_v3_v3v3(co, v_del->co, v_conn->co);
mul_v3_fl(co, 0.5f);
BM_edge_collapse(pbvh->bm, e, v_del, true, true, true);
copy_v3_v3(v_conn->co, co);
}
for (int i = 0; i < BLI_array_len(delvs); i++) {

View File

@ -4476,7 +4476,7 @@ static void do_topology_rake_bmesh_task_cb_ex(void *__restrict userdata,
ss, &test, data->brush->falloff_shape);
const int thread_id = BLI_task_parallel_thread_id(tls);
const bool use_curvature = ss->cache->brush->flag2 & BRUSH_CURVATURE_RAKE;
const bool use_curvature = data->use_curvature;
int check_fsets = ss->cache->brush->flag2 & BRUSH_SMOOTH_PRESERVE_FACE_SETS;
check_fsets = check_fsets ? SCULPT_BOUNDARY_FACE_SET : 0;
@ -4542,39 +4542,55 @@ static void do_topology_rake_bmesh_task_cb_ex(void *__restrict userdata,
}
#endif
int steps = data->do_origco ? 2 : 1;
// check origdata to be sure we don't mess it up
SCULPT_vertex_check_origdata(ss, vd.vertex);
for (int step = 0; step < steps; step++) {
float *co = step ? (float *)SCULPT_vertex_origco_get(ss, vd.vertex) : vd.co;
float *co = vd.co;
SCULPT_bmesh_four_neighbor_average(ss,
avg,
direction2,
vd.bm_vert,
data->rake_projection,
check_fsets,
data->cd_temp,
data->cd_dyn_vert,
step);
float oldco[3];
copy_v3_v3(oldco, co);
sub_v3_v3v3(val, avg, co);
madd_v3_v3v3fl(val, co, val, fade);
SCULPT_clip(sd, ss, co, val);
}
SCULPT_bmesh_four_neighbor_average(ss,
avg,
direction2,
vd.bm_vert,
data->rake_projection,
check_fsets,
data->cd_temp,
data->cd_dyn_vert,
0);
sub_v3_v3v3(val, avg, co);
float tan[3];
copy_v3_v3(tan, val);
madd_v3_v3fl(tan, vd.bm_vert->no, -dot_v3v3(tan, vd.bm_vert->no));
MDynTopoVert *mv = BKE_PBVH_DYNVERT(ss->cd_dyn_vert, vd.bm_vert);
madd_v3_v3v3fl(mv->origco, mv->origco, tan, fade * 0.5);
madd_v3_v3v3fl(val, co, val, fade);
SCULPT_clip(sd, ss, co, val);
if (vd.mvert) {
vd.mvert->flag |= ME_VERT_PBVH_UPDATE;
}
}
BKE_pbvh_vertex_iter_end;
BKE_pbvh_node_mark_normals_update(data->nodes[n]);
}
static void bmesh_topology_rake(
Sculpt *sd, Object *ob, PBVHNode **nodes, const int totnode, float bstrength)
static void bmesh_topology_rake(Sculpt *sd,
Object *ob,
PBVHNode **nodes,
const int totnode,
float bstrength,
bool needs_origco)
{
SculptSession *ss = ob->sculpt;
Brush *brush = ss->cache ? ss->cache->brush : BKE_paint_brush(&sd->paint);
const float strength = clamp_f(bstrength, 0.0f, 1.0f);
const float strength = bstrength; // clamp_f(bstrength, 0.0f, 1.0f);
Brush local_brush;
@ -4632,23 +4648,26 @@ static void bmesh_topology_rake(
int iteration;
const int count = iterations * strength + 1;
const float factor = iterations * strength / count;
const float factor = iterations * strength / count * 0.25;
for (iteration = 0; iteration <= count; iteration++) {
SculptThreadedTaskData data = {.sd = sd,
.ob = ob,
.brush = brush,
.nodes = nodes,
.strength = factor,
.cd_temp = cd_temp,
.cd_dyn_vert = ss->cd_dyn_vert,
.rake_projection = brush->topology_rake_projection,
.do_origco = SCULPT_stroke_needs_original(brush)};
SculptThreadedTaskData data = {
.sd = sd,
.ob = ob,
.brush = brush,
.nodes = nodes,
.strength = factor,
.cd_temp = cd_temp,
.use_curvature = SCULPT_get_int(ss, topology_rake_mode, sd, brush),
.cd_dyn_vert = ss->cd_dyn_vert,
.rake_projection = brush->topology_rake_projection,
.do_origco = needs_origco};
TaskParallelSettings settings;
BKE_pbvh_parallel_range_settings(&settings, true, totnode);
BLI_task_parallel_range(0, totnode, &data, do_topology_rake_bmesh_task_cb_ex, &settings);
BKE_pbvh_update_normals(ss->pbvh, ss->subdiv_ccg);
}
}
@ -7471,6 +7490,8 @@ static void do_clay_brush_task_cb_ex(void *__restrict userdata,
continue;
}
SCULPT_vertex_check_origdata(ss, vd.vertex);
float intr[3];
float val[3];
closest_to_plane_normalized_v3(intr, test.plane_tool, vd.co);
@ -8965,7 +8986,14 @@ void do_brush_action(Sculpt *sd, Object *ob, Brush *brush, UnifiedPaintSettings
break;
case SCULPT_TOOL_SMOOTH:
if (brush->smooth_deform_type == BRUSH_SMOOTH_DEFORM_LAPLACIAN) {
SCULPT_do_smooth_brush(sd, ob, nodes, totnode, brush->autosmooth_projection);
SCULPT_do_smooth_brush(
sd,
ob,
nodes,
totnode,
brush->autosmooth_projection,
SCULPT_stroke_needs_original(
brush)); // TODO: extract need original from commandlist and not parent brush
}
else if (brush->smooth_deform_type == BRUSH_SMOOTH_DEFORM_SURFACE) {
SCULPT_do_surface_smooth_brush(sd, ob, nodes, totnode);
@ -9173,7 +9201,8 @@ void do_brush_action(Sculpt *sd, Object *ob, Brush *brush, UnifiedPaintSettings
ss->cache->radius_squared = ss->cache->radius * ss->cache->radius;
}
bmesh_topology_rake(sd, ob, nodes, totnode, brush->topology_rake_factor);
bmesh_topology_rake(
sd, ob, nodes, totnode, brush->topology_rake_factor, SCULPT_stroke_needs_original(brush));
if (brush->topology_rake_radius_factor != 1.0f) {
ss->cache->radius = start_radius;
@ -9548,8 +9577,12 @@ static void SCULPT_run_command_list(
break;
case SCULPT_TOOL_SMOOTH:
if (brush2->smooth_deform_type == BRUSH_SMOOTH_DEFORM_LAPLACIAN) {
SCULPT_do_smooth_brush(
sd, ob, nodes, totnode, BRUSHSET_GET_FLOAT(cmd->params_mapped, projection, NULL));
SCULPT_do_smooth_brush(sd,
ob,
nodes,
totnode,
BRUSHSET_GET_FLOAT(cmd->params_mapped, projection, NULL),
SCULPT_stroke_needs_original(brush));
}
else if (brush2->smooth_deform_type == BRUSH_SMOOTH_DEFORM_SURFACE) {
SCULPT_do_surface_smooth_brush(sd, ob, nodes, totnode);
@ -9680,7 +9713,8 @@ static void SCULPT_run_command_list(
break;
case SCULPT_TOOL_TOPOLOGY_RAKE:
if (ss->bm) {
bmesh_topology_rake(sd, ob, nodes, totnode, ss->cache->bstrength);
bmesh_topology_rake(
sd, ob, nodes, totnode, ss->cache->bstrength, SCULPT_stroke_needs_original(brush));
}
break;
case SCULPT_TOOL_DYNTOPO:

View File

@ -784,7 +784,7 @@ void SCULPT_smooth(Sculpt *sd,
bool do_origco);
void SCULPT_do_smooth_brush(
Sculpt *sd, Object *ob, PBVHNode **nodes, int totnode, float projection);
Sculpt *sd, Object *ob, PBVHNode **nodes, int totnode, float projection, bool do_origco);
/* Surface Smooth Brush. */
@ -1059,6 +1059,7 @@ typedef struct SculptThreadedTaskData {
float fset_slide, bound_smooth;
float crease_pinch_factor;
bool use_curvature;
} SculptThreadedTaskData;
/*************** Brush testing declarations ****************/

View File

@ -1020,6 +1020,10 @@ static void do_smooth_brush_task_cb_ex(void *__restrict userdata,
if (!sculpt_brush_test_sq_fn(&test, vd.co)) {
continue;
}
// check origdata to be sure we don't mess it up
SCULPT_vertex_check_origdata(ss, vd.vertex);
const float fade = bstrength * SCULPT_brush_strength_factor(
ss,
brush,
@ -1172,7 +1176,7 @@ void SCULPT_smooth(Sculpt *sd,
.bound_smooth = bound_smooth,
.scl = have_scl ? &scl : NULL,
.scl2 = bound_scl,
.do_origco = SCULPT_stroke_needs_original(ss->cache->brush),
.do_origco = do_origco,
};
TaskParallelSettings settings;
@ -1186,7 +1190,7 @@ void SCULPT_smooth(Sculpt *sd,
}
void SCULPT_do_smooth_brush(
Sculpt *sd, Object *ob, PBVHNode **nodes, int totnode, float projection)
Sculpt *sd, Object *ob, PBVHNode **nodes, int totnode, float projection, bool do_origco)
{
SculptSession *ss = ob->sculpt;
@ -1206,7 +1210,7 @@ void SCULPT_do_smooth_brush(
}
else {
/* Regular mode, smooth. */
SCULPT_smooth(sd, ob, nodes, totnode, ss->cache->bstrength, false, projection, false);
SCULPT_smooth(sd, ob, nodes, totnode, ss->cache->bstrength, false, projection, do_origco);
}
}

View File

@ -1063,7 +1063,8 @@ GPU_PBVH_Buffers *GPU_pbvh_grid_buffers_build(int totgrid, BLI_bitmap **grid_hid
static int debug_pass = 0;
/* Output a BMVert into a VertexBufferFormat array at v_index. */
static void gpu_bmesh_vert_to_buffer_copy(BMVert *v,
static void gpu_bmesh_vert_to_buffer_copy(BMesh *bm,
BMVert *v,
GPUVertBuf *vert_buf,
int v_index,
const float fno[3],
@ -1086,12 +1087,21 @@ static void gpu_bmesh_vert_to_buffer_copy(BMVert *v,
vert_buf, g_vbo_id.vertex_attrs, g_vbo_id.vertex_attrs_len, (BMElem *)v, v_index);
#endif
/* Set coord, normal, and mask */
GPU_vertbuf_attr_set(vert_buf, g_vbo_id.pos, v_index, v->co);
short no_short[3];
normal_float_to_short_v3(no_short, fno ? fno : v->no);
/* Set coord, normal, and mask */
if (G.debug_value == 890) {
const int cd_dyn_vert = bm->vdata.layers[bm->vdata.typemap[CD_DYNTOPO_VERT]].offset;
MDynTopoVert *mv = BM_ELEM_CD_GET_VOID_P(v, cd_dyn_vert);
GPU_vertbuf_attr_set(vert_buf, g_vbo_id.pos, v_index, mv->origco);
normal_float_to_short_v3(no_short, mv->origno);
}
else {
GPU_vertbuf_attr_set(vert_buf, g_vbo_id.pos, v_index, v->co);
normal_float_to_short_v3(no_short, fno ? fno : v->no);
}
GPU_vertbuf_attr_set(vert_buf, g_vbo_id.nor, v_index, no_short);
#ifndef GPU_PERF_TEST
@ -1746,7 +1756,8 @@ static void GPU_pbvh_bmesh_buffers_update_indexed(GPU_PBVH_Buffers *buffers,
GPU_vertbuf_attr_set(vert_buf, g_vbo_id.nor, i, no_short);
#else
gpu_bmesh_vert_to_buffer_copy(v,
gpu_bmesh_vert_to_buffer_copy(bm,
v,
buffers->vert_buf,
i,
NULL,
@ -1961,7 +1972,8 @@ void GPU_pbvh_bmesh_buffers_update(GPU_PBVH_Buffers *buffers,
for (int j = 0; j < 3; j++) {
float *no = buffers->smooth ? v[j]->no : f->no;
gpu_bmesh_vert_to_buffer_copy(v[j],
gpu_bmesh_vert_to_buffer_copy(bm,
v[j],
buffers->vert_buf,
v_index,
no,
@ -2079,7 +2091,8 @@ void GPU_pbvh_bmesh_buffers_update(GPU_PBVH_Buffers *buffers,
for (i = 0; i < 3; i++) {
float *no = buffers->smooth ? v[i]->no : f->no;
gpu_bmesh_vert_to_buffer_copy(v[i],
gpu_bmesh_vert_to_buffer_copy(bm,
v[i],
buffers->vert_buf,
v_index,
no,