Sculpt: Implement accumulate for paint and
other fixes * The paint brush now supports accumulate. * Fixed bug with PBVH_FACES not setting MSculptVert update flags correctly in face set draw brush. * Topology rake now has a mode where it simply propegates directions from boundaries.
This commit is contained in:
parent
a55b58476e
commit
5cc582fec7
|
@ -218,6 +218,7 @@ places in rna_engine_codebase are relevent:
|
|||
MAKE_ENUM(topology_rake_mode, "Topology Rake Mode", "", 1, {
|
||||
{0, "BRUSH_DIRECTION", "NONE", "Stroke", "Stroke Direction"},
|
||||
{1, "CURVATURE", "NONE", "Curvature", "Follow mesh curvature"},
|
||||
{2, "NONE", "NONE", "Boundary Only", "Boundaries only"},
|
||||
{-1}
|
||||
})
|
||||
|
||||
|
|
|
@ -1466,30 +1466,7 @@ static float maskcb_get(EdgeQueueContext *eq_ctx, BMEdge *e)
|
|||
|
||||
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);
|
||||
// float val = (float)BM_vert_edge_count(v1) + (float)BM_vert_edge_count(v2);
|
||||
MSculptVert *mv1 = BKE_PBVH_SCULPTVERT(eq_ctx->cd_sculpt_vert, v1);
|
||||
MSculptVert *mv2 = BKE_PBVH_SCULPTVERT(eq_ctx->cd_sculpt_vert, v2);
|
||||
float val = (float)(mv1->valence + mv2->valence) * 0.5f;
|
||||
|
||||
val -= 6.0f;
|
||||
val = MAX2(val, 1.0f);
|
||||
|
||||
// val = powf(val, 0.5);
|
||||
l *= val;
|
||||
|
||||
return l;
|
||||
#elif 0 // penalize 4-valence verts
|
||||
float l = len_squared_v3v3(v1->co, v2->co);
|
||||
if (BM_vert_edge_count(v1) == 4 || BM_vert_edge_count(v2) == 4) {
|
||||
l *= 0.25f;
|
||||
}
|
||||
|
||||
return l;
|
||||
#else
|
||||
|
||||
# ifdef WITH_ADAPTIVE_CURVATURE
|
||||
#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);
|
||||
|
||||
|
@ -1499,33 +1476,25 @@ static float calc_weighted_edge_split(EdgeQueueContext *eq_ctx, BMVert *v1, BMVe
|
|||
fac = min_ff(fac, 4.0f);
|
||||
|
||||
return fac * len_squared_v3v3(v1->co, v2->co);
|
||||
# else
|
||||
#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);
|
||||
float len_sq = len_squared_v3v3(v1->co, v2->co);
|
||||
|
||||
#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);
|
||||
#if 0 // this rule here seems to improve topology, but need to study it more
|
||||
MSculptVert *mv1 = BKE_PBVH_SCULPTVERT(eq_ctx->cd_sculpt_vert, v1);
|
||||
MSculptVert *mv2 = BKE_PBVH_SCULPTVERT(eq_ctx->cd_sculpt_vert, v2);
|
||||
float val = (float)(mv1->valence + mv2->valence) * 0.5f;
|
||||
|
||||
val -= 6.0f;
|
||||
val = MAX2(val, 1.0f);
|
||||
|
||||
// val = powf(val, 0.5);
|
||||
l *= val;
|
||||
|
||||
return l;
|
||||
#else
|
||||
return len_squared_v3v3(v1->co, v2->co);
|
||||
if (mv1->valence == 5 && mv2->valence == 5) {
|
||||
len_sq *= 0.25;
|
||||
}
|
||||
#endif
|
||||
|
||||
return len_sq;
|
||||
}
|
||||
|
||||
/* only tag'd edges are in the queue */
|
||||
|
@ -3625,8 +3594,6 @@ static BMVert *pbvh_bmesh_collapse_edge(PBVH *pbvh,
|
|||
|
||||
bool snap = !(mv2->flag & SCULPTVERT_ALL_CORNER);
|
||||
|
||||
BMLoop *l;
|
||||
|
||||
/* snap customdata */
|
||||
if (snap) {
|
||||
int ni_conn = BM_ELEM_CD_GET_INT(v_conn, pbvh->cd_vert_node_offset);
|
||||
|
@ -5704,8 +5671,6 @@ cd_sculpt_vert, etc*/
|
|||
DynTopoState *BKE_dyntopo_init(BMesh *bm, PBVH *existing_pbvh)
|
||||
{
|
||||
PBVH *pbvh;
|
||||
PBVHNode _node;
|
||||
PBVH _start;
|
||||
|
||||
if (!existing_pbvh) {
|
||||
pbvh = MEM_callocN(sizeof(*pbvh), "pbvh");
|
||||
|
|
|
@ -1643,7 +1643,9 @@ 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;
|
||||
float th = saacos(dot_v3v3(e->l->f->no, e->l->radial_next->f->no));
|
||||
|
||||
th *= M_1_PI * 0.25f;
|
||||
// th = th * 0.5 + 0.5;
|
||||
curv += th;
|
||||
totcurv += 1.0f;
|
||||
|
|
|
@ -3730,6 +3730,9 @@ static void do_topology_rake_bmesh_task_cb_ex(void *__restrict userdata,
|
|||
const Brush *brush = data->brush;
|
||||
PBVHNode *node = data->nodes[n];
|
||||
|
||||
int mode = SCULPT_get_int(ss, topology_rake_mode, sd, brush);
|
||||
const bool use_curvature = mode == 1;
|
||||
|
||||
bool do_reproject = SCULPT_need_reproject(ss);
|
||||
|
||||
float direction[3];
|
||||
|
@ -3755,7 +3758,6 @@ 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 = data->use_curvature;
|
||||
int check_fsets = ss->cache->brush->flag2 & BRUSH_SMOOTH_PRESERVE_FACE_SETS;
|
||||
check_fsets = check_fsets ? SCULPT_BOUNDARY_FACE_SET : 0;
|
||||
|
||||
|
@ -3801,6 +3803,10 @@ static void do_topology_rake_bmesh_task_cb_ex(void *__restrict userdata,
|
|||
if (use_curvature) {
|
||||
SCULPT_curvature_dir_get(ss, vd.vertex, direction2, false);
|
||||
}
|
||||
else if (mode == 2) { // zero
|
||||
zero_v3(direction);
|
||||
zero_v3(direction2);
|
||||
}
|
||||
else {
|
||||
copy_v3_v3(direction2, direction);
|
||||
}
|
||||
|
@ -3821,7 +3827,7 @@ static void do_topology_rake_bmesh_task_cb_ex(void *__restrict userdata,
|
|||
}
|
||||
#endif
|
||||
|
||||
// check origdata to be sure we don't mess it up
|
||||
/* check origdata to be sure we don't mess it up */
|
||||
SCULPT_vertex_check_origdata(ss, vd.vertex);
|
||||
|
||||
float *co = vd.co;
|
||||
|
@ -3882,6 +3888,7 @@ void SCULPT_bmesh_topology_rake(Sculpt *sd,
|
|||
|
||||
// vector4, nto color
|
||||
SCULPT_dyntopo_ensure_templayer(ss, CD_PROP_COLOR, "_rake_temp", false);
|
||||
|
||||
int cd_temp = SCULPT_dyntopo_get_templayer(ss, CD_PROP_COLOR, "_rake_temp");
|
||||
|
||||
#ifdef SCULPT_DIAGONAL_EDGE_MARKS
|
||||
|
@ -3938,17 +3945,15 @@ void SCULPT_bmesh_topology_rake(Sculpt *sd,
|
|||
|
||||
for (iteration = 0; iteration <= count; iteration++) {
|
||||
|
||||
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_sculpt_vert = ss->cd_sculpt_vert,
|
||||
.rake_projection = brush->topology_rake_projection,
|
||||
.do_origco = needs_origco};
|
||||
SculptThreadedTaskData data = {.sd = sd,
|
||||
.ob = ob,
|
||||
.brush = brush,
|
||||
.nodes = nodes,
|
||||
.strength = factor,
|
||||
.cd_temp = cd_temp,
|
||||
.cd_sculpt_vert = ss->cd_sculpt_vert,
|
||||
.rake_projection = brush->topology_rake_projection,
|
||||
.do_origco = needs_origco};
|
||||
TaskParallelSettings settings;
|
||||
BKE_pbvh_parallel_range_settings(&settings, true, totnode);
|
||||
|
||||
|
|
|
@ -397,7 +397,7 @@ static void do_draw_face_sets_brush_task_cb_ex(void *__restrict userdata,
|
|||
MVert *v = &ss->mvert[ml->v];
|
||||
float fno[3];
|
||||
|
||||
MSculptVert *mv = ss->mdyntopo_verts + i;
|
||||
MSculptVert *mv = ss->mdyntopo_verts + ml->v;
|
||||
|
||||
MV_ADD_FLAG(mv, SCULPTVERT_NEED_BOUNDARY);
|
||||
|
||||
|
|
|
@ -1076,7 +1076,7 @@ typedef struct SculptThreadedTaskData {
|
|||
ThreadMutex mutex;
|
||||
|
||||
// Layer brush
|
||||
int cd_temp, cd_sculpt_vert;
|
||||
int cd_temp, cd_temp2, cd_temp3, cd_sculpt_vert;
|
||||
|
||||
float smooth_projection;
|
||||
float rake_projection;
|
||||
|
|
|
@ -124,6 +124,8 @@ static void do_paint_brush_task_cb_ex(void *__restrict userdata,
|
|||
const SculptCustomLayer *buffer_scl = data->scl;
|
||||
const SculptCustomLayer *stroke_id_scl = data->scl2;
|
||||
|
||||
const bool do_accum = SCULPT_get_int(ss, accumulate, NULL, brush);
|
||||
|
||||
PBVHVertexIter vd;
|
||||
|
||||
// SculptOrigVertData orig_data;
|
||||
|
@ -222,11 +224,19 @@ static void do_paint_brush_task_cb_ex(void *__restrict userdata,
|
|||
paint_color, paint_color, wet_mix_color, ss->cache->paint_brush.wet_mix);
|
||||
blend_color_mix_float(color_buffer, color_buffer, paint_color);
|
||||
|
||||
/* Final mix over the original color using brush alpha. */
|
||||
/* Final mix over the color/original-color using brush alpha. */
|
||||
mul_v4_v4fl(buffer_color, color_buffer, alpha);
|
||||
|
||||
MSculptVert *mv = SCULPT_vertex_get_mdyntopo(ss, vd.vertex);
|
||||
IMB_blend_color_float(vd.col, mv->origcolor, buffer_color, brush->blend);
|
||||
if (do_accum) {
|
||||
mul_v4_fl(buffer_color, fade);
|
||||
|
||||
IMB_blend_color_float(vd.col, vd.col, buffer_color, brush->blend);
|
||||
vd.col[3] = 1.0f;
|
||||
}
|
||||
else {
|
||||
MSculptVert *mv = SCULPT_vertex_get_mdyntopo(ss, vd.vertex);
|
||||
IMB_blend_color_float(vd.col, mv->origcolor, buffer_color, brush->blend);
|
||||
}
|
||||
|
||||
CLAMP4(vd.col, 0.0f, 1.0f);
|
||||
|
||||
|
|
|
@ -787,6 +787,7 @@ void SCULPT_bmesh_four_neighbor_average(SculptSession *ss,
|
|||
|
||||
const float selfw = (float)mv->valence * 0.0025f;
|
||||
madd_v3_v3fl(dir3, direction, selfw);
|
||||
|
||||
totdir3 += selfw;
|
||||
|
||||
BMIter eiter;
|
||||
|
@ -800,14 +801,7 @@ void SCULPT_bmesh_four_neighbor_average(SculptSession *ss,
|
|||
float dir2[3];
|
||||
float *col2 = BM_ELEM_CD_GET_VOID_P(v_other, cd_temp);
|
||||
|
||||
float bucketw = 1.0f; // col2[3] < col[3] ? 2.0f : 1.0f;
|
||||
// bucketw /= 0.00001f + len_v3v3(e->v1->co, e->v2->co);
|
||||
// if (weighted) {
|
||||
// bucketw = 1.0 / (0.000001 + areas[area_i]);
|
||||
//}
|
||||
// if (e == v->e) {
|
||||
// bucketw *= 2.0;
|
||||
//}
|
||||
float bucketw = 1.0f;
|
||||
|
||||
MSculptVert *mv2 = BKE_PBVH_SCULPTVERT(cd_sculpt_vert, v_other);
|
||||
float *co2;
|
||||
|
@ -834,7 +828,7 @@ void SCULPT_bmesh_four_neighbor_average(SculptSession *ss,
|
|||
int bound = SCULPT_edge_is_boundary(ss, (SculptEdgeRef){.i = (intptr_t)e}, bflag);
|
||||
float dirw = 1.0f;
|
||||
|
||||
if (bound) {
|
||||
if (bound) { // || v_other->head.hflag & BM_ELEM_SELECT) { // XXX
|
||||
had_bound = true;
|
||||
|
||||
sub_v3_v3v3(dir2, co2, co1);
|
||||
|
@ -860,7 +854,6 @@ void SCULPT_bmesh_four_neighbor_average(SculptSession *ss,
|
|||
tot_co = 0.0f;
|
||||
continue;
|
||||
}
|
||||
|
||||
float vec[3];
|
||||
sub_v3_v3v3(vec, co2, co1);
|
||||
|
||||
|
|
Loading…
Reference in New Issue