Sculpt: fix broken ray casting of original data in pbvh

Not sure if this ever worked.
This commit is contained in:
Joseph Eagar 2021-10-06 01:46:25 -07:00
parent c209e0902d
commit f6a8d745c2
11 changed files with 220 additions and 36 deletions

View File

@ -1278,6 +1278,15 @@ class VIEW3D_PT_sculpt_options(Panel, View3DPaintPanel):
"""
col.separator()
UnifiedPaintPanel.channel_unified(layout.column(),
context,
brush,
"show_origco",
toolsettings_only=True, ui_editing=False)
col.separator()
col.operator("sculpt.set_limit_surface")

View File

@ -505,6 +505,7 @@ void BKE_pbvh_bmesh_update_all_valence(PBVH *pbvh);
void BKE_pbvh_bmesh_flag_all_disk_sort(PBVH *pbvh);
bool BKE_pbvh_bmesh_mark_update_valence(PBVH *pbvh, SculptVertRef vertex);
void BKE_pbvh_node_mark_original_update(PBVHNode *node);
void BKE_pbvh_node_mark_update_tri_area(PBVHNode *node);
void BKE_pbvh_update_all_tri_areas(PBVH *pbvh);
void BKE_pbvh_node_mark_update(PBVHNode *node);
@ -836,6 +837,7 @@ void BKE_pbvh_update_vert_boundary(int cd_dyn_vert,
int cd_faceset_offset,
int cd_vert_node_offset,
int cd_face_node_offset,
int cd_vcol,
struct BMVert *v,
int symmetry);

View File

@ -277,6 +277,7 @@ places in rna_engine_codebase are relevent:
MAKE_FLOAT(hardness, "Hardness", "Brush falloff hardness", 0.0f, 0.0f, 1.0f)
MAKE_FLOAT(tip_roundness, "Tip Roundness", "", 1.0f, 0.0f, 1.0f)
MAKE_BOOL(accumulate, "Accumulate", "", false)
MAKE_BOOL_EX(show_origco, "Show OrigCo", "", false, BRUSH_CHANNEL_INHERIT)
MAKE_ENUM(direction, "Direction", "", 0, {\
{0, "ADD", "ADD", "Add", "Add effect of brush"},
{1, "SUBTRACT", "REMOVE", "Subtract", "Subtract effect of brush"},

View File

@ -974,6 +974,8 @@ void BKE_brush_builtin_patch(Brush *brush, int tool)
ADDCH(radius_unit);
ADDCH(unprojected_radius);
ADDCH(show_origco);
ADDCH(use_surface_falloff);
if (!BRUSHSET_LOOKUP(chset, use_smoothed_rake)) {
@ -1781,6 +1783,8 @@ void BKE_brush_check_toolsettings(Sculpt *sd)
ADDCH(radius_unit);
ADDCH(unprojected_radius);
ADDCH(show_origco);
ADDCH(smooth_strength_factor);
ADDCH(smooth_strength_projection);

View File

@ -153,26 +153,75 @@ void BBC_update_centroid(BBC *bbc)
}
/* Not recursive */
static void update_node_vb(PBVH *pbvh, PBVHNode *node)
static void update_node_vb(PBVH *pbvh, PBVHNode *node, int updateflag)
{
if (!(updateflag & (PBVH_UpdateBB | PBVH_UpdateOriginalBB))) {
return;
}
/* cannot clear flag here, causes leaky pbvh */
// node->flag &= ~(updateflag & (PBVH_UpdateBB | PBVH_UpdateOriginalBB));
BB vb;
BB orig_vb;
BB_reset(&vb);
BB_reset(&orig_vb);
bool do_orig = updateflag | PBVH_UpdateOriginalBB;
bool do_normal = updateflag | PBVH_UpdateBB;
if (node->flag & PBVH_Leaf) {
PBVHVertexIter vd;
BKE_pbvh_vertex_iter_begin (pbvh, node, vd, PBVH_ITER_ALL) {
BB_expand(&vb, vd.co);
if (do_normal) {
BB_expand(&vb, vd.co);
}
if (do_orig) {
MDynTopoVert *mv = pbvh->type == PBVH_BMESH ?
BM_ELEM_CD_GET_VOID_P(vd.bm_vert, pbvh->cd_dyn_vert) :
pbvh->mdyntopo_verts + vd.index;
if (mv->stroke_id != pbvh->stroke_id) {
BB_expand(&orig_vb, vd.co);
}
else {
BB_expand(&orig_vb, mv->origco);
}
}
}
BKE_pbvh_vertex_iter_end;
}
else {
BB_expand_with_bb(&vb, &pbvh->nodes[node->children_offset].vb);
BB_expand_with_bb(&vb, &pbvh->nodes[node->children_offset + 1].vb);
if (do_normal) {
BB_expand_with_bb(&vb, &pbvh->nodes[node->children_offset].vb);
BB_expand_with_bb(&vb, &pbvh->nodes[node->children_offset + 1].vb);
}
if (do_orig) {
BB_expand_with_bb(&orig_vb, &pbvh->nodes[node->children_offset].orig_vb);
BB_expand_with_bb(&orig_vb, &pbvh->nodes[node->children_offset + 1].orig_vb);
}
}
node->vb = vb;
if (do_normal) {
node->vb = vb;
}
if (do_orig) {
#if 0
float size[3];
sub_v3_v3v3(size, orig_vb.bmax, orig_vb.bmin);
mul_v3_fl(size, 0.05);
sub_v3_v3(orig_vb.bmin, size);
add_v3_v3(orig_vb.bmax, size);
#endif
node->orig_vb = orig_vb;
}
}
// void BKE_pbvh_node_BB_reset(PBVHNode *node)
@ -1288,15 +1337,7 @@ static void pbvh_update_BB_redraw_task_cb(void *__restrict userdata,
PBVHNode *node = data->nodes[n];
const int flag = data->flag;
if ((flag & PBVH_UpdateBB) && (node->flag & PBVH_UpdateBB)) {
/* don't clear flag yet, leave it for flushing later */
/* Note that bvh usage is read-only here, so no need to thread-protect it. */
update_node_vb(pbvh, node);
}
if ((flag & PBVH_UpdateOriginalBB) && (node->flag & PBVH_UpdateOriginalBB)) {
node->orig_vb = node->vb;
}
update_node_vb(pbvh, node, flag);
if ((flag & PBVH_UpdateRedraw) && (node->flag & PBVH_UpdateRedraw)) {
node->flag &= ~PBVH_UpdateRedraw;
@ -1577,12 +1618,7 @@ static int pbvh_flush_bb(PBVH *pbvh, PBVHNode *node, int flag)
update |= pbvh_flush_bb(pbvh, pbvh->nodes + node->children_offset, flag);
update |= pbvh_flush_bb(pbvh, pbvh->nodes + node->children_offset + 1, flag);
if (update & PBVH_UpdateBB) {
update_node_vb(pbvh, node);
}
if (update & PBVH_UpdateOriginalBB) {
node->orig_vb = node->vb;
}
update_node_vb(pbvh, node, update);
return update;
}
@ -1949,6 +1985,11 @@ BMesh *BKE_pbvh_get_bmesh(PBVH *pbvh)
/***************************** Node Access ***********************************/
void BKE_pbvh_node_mark_original_update(PBVHNode *node)
{
node->flag |= PBVH_UpdateOriginalBB;
}
void BKE_pbvh_node_mark_update(PBVHNode *node)
{
node->flag |= PBVH_UpdateNormals | PBVH_UpdateBB | PBVH_UpdateOriginalBB |
@ -2261,8 +2302,10 @@ void BKE_pbvh_raycast(PBVH *pbvh,
RaycastData rcd;
isect_ray_aabb_v3_precalc(&rcd.ray, ray_start, ray_normal);
rcd.original = original;
rcd.stroke_id = stroke_id;
pbvh->stroke_id = stroke_id;
BKE_pbvh_search_callback_occluded(pbvh, ray_aabb_intersect, &rcd, cb, data);
}
@ -2352,6 +2395,7 @@ bool ray_face_intersection_depth_tri(const float ray_start[3],
int *hit_count)
{
float depth_test;
if (!isect_ray_tri_watertight_v3(ray_start, isect_precalc, t0, t1, t2, &depth_test, NULL)) {
return false;
}
@ -3112,6 +3156,9 @@ void BKE_pbvh_draw_cb(PBVH *pbvh,
MEM_SAFE_FREE(nodes);
}
// bad global from gpu_buffers.c
extern bool pbvh_show_orig_co;
void BKE_pbvh_draw_debug_cb(
PBVH *pbvh,
void (*draw_fn)(void *user_data, const float bmin[3], const float bmax[3], PBVHNodeFlags flag),
@ -3122,7 +3169,12 @@ void BKE_pbvh_draw_debug_cb(
int num = a + node->updategen;
draw_fn(&num, node->vb.bmin, node->vb.bmax, node->flag);
if (pbvh_show_orig_co) {
draw_fn(&num, node->orig_vb.bmin, node->orig_vb.bmax, node->flag);
}
else {
draw_fn(&num, node->vb.bmin, node->vb.bmax, node->flag);
}
}
}

View File

@ -254,6 +254,7 @@ static void pbvh_bmesh_node_finalize(PBVH *pbvh,
n->bm_other_verts = BLI_table_gset_new("bm_other_verts");
BB_reset(&n->vb);
BB_reset(&n->orig_vb);
BMFace *f;
TGSET_ITER (f, n->bm_faces) {
@ -280,6 +281,7 @@ static void pbvh_bmesh_node_finalize(PBVH *pbvh,
}
/* Update node bounding box */
BB_expand(&n->vb, v->co);
BB_expand(&n->orig_vb, mv->origco);
} while ((l_iter = l_iter->next) != l_first);
if (!BM_elem_flag_test(f, BM_ELEM_HIDDEN)) {
@ -291,8 +293,6 @@ static void pbvh_bmesh_node_finalize(PBVH *pbvh,
BLI_assert(n->vb.bmin[0] <= n->vb.bmax[0] && n->vb.bmin[1] <= n->vb.bmax[1] &&
n->vb.bmin[2] <= n->vb.bmax[2]);
n->orig_vb = n->vb;
/* Build GPU buffers for new node and update vertex normals */
BKE_pbvh_node_mark_rebuild_draw(n);
@ -888,6 +888,7 @@ bool pbvh_bmesh_node_raycast(PBVH *pbvh,
for (int i = 0; i < node->tribuf->tottri; i++) {
PBVHTri *tri = tribuf->tris + i;
BMVert *v1 = (BMVert *)tribuf->verts[tri->v[0]].i;
BMVert *v2 = (BMVert *)tribuf->verts[tri->v[1]].i;
BMVert *v3 = (BMVert *)tribuf->verts[tri->v[2]].i;
@ -925,7 +926,7 @@ bool pbvh_bmesh_node_raycast(PBVH *pbvh,
for (int j = 0; j < 3; j++) {
BMVert *v = (BMVert *)tribuf->verts[tri->v[j]].i;
float *co = BKE_PBVH_DYNVERT(cd_dyn_vert, v)->origco;
float *co = use_original ? BKE_PBVH_DYNVERT(cd_dyn_vert, v)->origco : v->co;
float dist = len_squared_v3v3(co, ray_start);
if (dist < nearest_vertex_dist) {
@ -1469,10 +1470,29 @@ int BKE_pbvh_do_fset_symmetry(int fset, const int symflag, const float *co)
return fset;
}
//#define MV_COLOR_BOUNDARY
#ifdef MV_COLOR_BOUNDARY
static int color_boundary_key(float col[4])
{
const float steps = 2.0f;
float hsv[3];
rgb_to_hsv(col[0], col[1], col[2], hsv, hsv + 1, hsv + 2);
int x = (int)((hsv[0] * 0.5f + 0.5f) * steps + 0.5f);
int y = (int)(hsv[1] * steps + 0.5f);
int z = (int)(hsv[2] * steps + 0.5f);
return z * steps * steps + y * steps + x;
}
#endif
void bke_pbvh_update_vert_boundary(int cd_dyn_vert,
int cd_faceset_offset,
int cd_vert_node_offset,
int cd_face_node_offset,
int cd_vcol,
BMVert *v,
int bound_symmetry)
{
@ -1498,6 +1518,10 @@ void bke_pbvh_update_vert_boundary(int cd_dyn_vert,
int seamcount = 0;
int quadcount = 0;
#ifdef MV_COLOR_BOUNDARY
int last_key = -1;
#endif
#if 0
struct FaceSetRef {
int fset;
@ -1524,6 +1548,20 @@ void bke_pbvh_update_vert_boundary(int cd_dyn_vert,
}
}
#ifdef MV_COLOR_BOUNDARY
if (cd_vcol >= 0) {
float *color1 = BM_ELEM_CD_GET_VOID_P(v, cd_vcol);
float *color2 = BM_ELEM_CD_GET_VOID_P(v2, cd_vcol);
int colorkey1 = color_boundary_key(color1);
int colorkey2 = color_boundary_key(color2);
if (colorkey1 != colorkey2) {
mv->flag |= DYNVERT_FSET_BOUNDARY;
}
}
#endif
if (!(e->head.hflag & BM_ELEM_SMOOTH)) {
mv->flag |= DYNVERT_SHARP_BOUNDARY;
sharpcount++;
@ -1634,11 +1672,17 @@ void BKE_pbvh_update_vert_boundary(int cd_dyn_vert,
int cd_faceset_offset,
int cd_vert_node_offset,
int cd_face_node_offset,
int cd_vcol,
BMVert *v,
int bound_symmetry)
{
bke_pbvh_update_vert_boundary(
cd_dyn_vert, cd_faceset_offset, cd_vert_node_offset, cd_face_node_offset, v, bound_symmetry);
bke_pbvh_update_vert_boundary(cd_dyn_vert,
cd_faceset_offset,
cd_vert_node_offset,
cd_face_node_offset,
cd_vcol,
v,
bound_symmetry);
}
/*Used by symmetrize to update boundary flags*/
@ -1652,6 +1696,7 @@ void BKE_pbvh_recalc_bmesh_boundary(PBVH *pbvh)
pbvh->cd_faceset_offset,
pbvh->cd_vert_node_offset,
pbvh->cd_face_node_offset,
pbvh->cd_vcol_offset,
v,
pbvh->boundary_symmetry);
}
@ -1846,6 +1891,7 @@ void BKE_pbvh_build_bmesh(PBVH *pbvh,
pbvh->cd_faceset_offset,
pbvh->cd_vert_node_offset,
pbvh->cd_face_node_offset,
pbvh->cd_vcol_offset,
v,
pbvh->boundary_symmetry);
BKE_pbvh_bmesh_update_valence(pbvh->cd_dyn_vert, (SculptVertRef){(intptr_t)v});
@ -2964,18 +3010,39 @@ static void pbvh_bmesh_balance_tree(PBVH *pbvh)
float volume = BB_volume(&child1->vb) + BB_volume(&child2->vb);
/* dissolve nodes whose children overlap by more then a percentage
of the total volume. we use a simple huerstic to calculate the
cutoff threshold.*/
BB_intersect(&clip, &child1->vb, &child2->vb);
float overlap = BB_volume(&clip);
float factor;
// for (int i = 0; i < depthmap[node - pbvh->nodes]; i++) {
// printf("-");
//}
/* use higher threshold for the root node and its immediate children */
switch (BLI_array_len(stack)) {
case 0:
factor = 0.75;
break;
case 1:
case 2:
factor = 0.5;
break;
default:
factor = 0.2;
break;
}
// printf("volume: %.4f overlap: %.4f ratio: %.3f\n", volume, overlap, overlap / volume);
#if 0
for (int k = 0; k < BLI_array_len(stack); k++) {
printf(" ");
}
if (overlap > volume * 0.1) {
printf("factor: %.3f\n", factor);
#endif
if (overlap > volume * factor) {
modified = true;
// printf(" DELETE!\n");
printf(" DELETE! %.4f %.4f %d\n", overlap, volume, BLI_array_len(stack));
BLI_array_clear(substack);

View File

@ -340,6 +340,7 @@ void bke_pbvh_update_vert_boundary(int cd_dyn_vert,
int cd_faceset_offset,
int cd_vert_node_offset,
int cd_face_node_offset,
int cd_vcol_offset,
BMVert *v,
int bound_symmetry);
@ -352,6 +353,7 @@ BLI_INLINE bool pbvh_check_vert_boundary(PBVH *pbvh, struct BMVert *v)
pbvh->cd_faceset_offset,
pbvh->cd_vert_node_offset,
pbvh->cd_face_node_offset,
pbvh->cd_vcol_offset,
v,
pbvh->boundary_symmetry);
return true;

View File

@ -2220,6 +2220,7 @@ SculptCornerType SCULPT_vertex_is_corner(const SculptSession *ss,
ss->cd_faceset_offset,
ss->cd_vert_node_offset,
ss->cd_face_node_offset,
ss->cd_vcol_offset,
(BMVert *)vertex.i,
ss->boundary_symmetry);
}
@ -2277,6 +2278,7 @@ SculptBoundaryType SCULPT_vertex_is_boundary(const SculptSession *ss,
ss->cd_faceset_offset,
ss->cd_vert_node_offset,
ss->cd_face_node_offset,
ss->cd_vcol_offset,
(BMVert *)vertex.i,
ss->boundary_symmetry);
}
@ -2779,7 +2781,7 @@ void SCULPT_orig_vert_data_init(SculptOrigVertData *data,
data->datatype = type;
}
void SCULPT_vertex_check_origdata(SculptSession *ss, SculptVertRef vertex)
bool SCULPT_vertex_check_origdata(SculptSession *ss, SculptVertRef vertex)
{
// check if we need to update original data for current stroke
MDynTopoVert *mv = ss->bm ? BKE_PBVH_DYNVERT(ss->cd_dyn_vert, (BMVert *)vertex.i) :
@ -2797,7 +2799,11 @@ void SCULPT_vertex_check_origdata(SculptSession *ss, SculptVertRef vertex)
}
mv->origmask = SCULPT_vertex_mask_get(ss, vertex);
return false;
}
return true;
}
/**
@ -8684,6 +8690,26 @@ static void sculpt_topology_update(Sculpt *sd,
ss->totvert = ss->bm->totvert;
}
static void do_check_origco_cb(void *__restrict userdata,
const int n,
const TaskParallelTLS *__restrict UNUSED(tls))
{
SculptThreadedTaskData *data = userdata;
SculptSession *ss = data->ob->sculpt;
PBVHVertexIter vd;
bool modified = false;
BKE_pbvh_vertex_iter_begin (ss->pbvh, data->nodes[n], vd, PBVH_ITER_UNIQUE) {
modified |= SCULPT_vertex_check_origdata(ss, vd.vertex);
}
BKE_pbvh_vertex_iter_end;
if (modified) {
BKE_pbvh_node_mark_original_update(data->nodes[n]);
}
}
static void do_brush_action_task_cb(void *__restrict userdata,
const int n,
const TaskParallelTLS *__restrict UNUSED(tls))
@ -8795,7 +8821,7 @@ void do_brush_action(Sculpt *sd, Object *ob, Brush *brush, UnifiedPaintSettings
/* Update last stroke position. */
ups->last_stroke_valid = true;
copy_v3_v3(ss->cache->true_last_location, ss->cache->true_location);
// copy_v3_v3(ss->cache->true_last_location, ss->cache->true_location);
return;
}
@ -9445,6 +9471,21 @@ static void SCULPT_run_command_list(
Brush *oldbrush = ss->cache->brush;
Brush _dummy = *brush, *brush2 = &_dummy;
if (ss->cache->original) {
SculptThreadedTaskData task_data = {
.sd = sd,
.ob = ob,
.brush = brush,
.nodes = nodes,
};
TaskParallelSettings settings;
BKE_pbvh_parallel_range_settings(&settings, true, totnode);
BLI_task_parallel_range(0, totnode, &task_data, do_check_origco_cb, &settings);
BKE_pbvh_update_bounds(ss->pbvh, PBVH_UpdateOriginalBB);
}
for (int step = 0; step < list->totcommand; step++) {
BrushCommand *cmd = list->commands + step;
@ -11820,6 +11861,10 @@ void sculpt_stroke_update_step(bContext *C, struct PaintStroke *stroke, PointerR
ss->cache->channels_final = BKE_brush_channelset_copy(brush->channels);
}
// bad debug global
extern bool pbvh_show_orig_co;
pbvh_show_orig_co = BRUSHSET_GET_INT(ss->cache->channels_final, show_origco, NULL);
ss->cache->use_plane_trim = BRUSHSET_GET_INT(
ss->cache->channels_final, use_plane_trim, &ss->cache->input_mapping);

View File

@ -870,6 +870,7 @@ void SCULPT_dynamic_topology_enable_ex(Main *bmain, Depsgraph *depsgraph, Scene
ss->cd_faceset_offset,
ss->cd_vert_node_offset,
ss->cd_face_node_offset,
ss->cd_vcol_offset,
v,
ss->boundary_symmetry);
BKE_pbvh_bmesh_update_valence(ss->cd_dyn_vert, (SculptVertRef){.i = (intptr_t)v});

View File

@ -1677,7 +1677,7 @@ void SCULPT_cache_calc_brushdata_symm(StrokeCache *cache,
const float angle);
void SCULPT_cache_free(SculptSession *ss, StrokeCache *cache);
void SCULPT_vertex_check_origdata(SculptSession *ss, SculptVertRef vertex);
bool SCULPT_vertex_check_origdata(SculptSession *ss, SculptVertRef vertex);
void SCULPT_orig_vert_data_init(SculptOrigVertData *data,
Object *ob,

View File

@ -1061,6 +1061,7 @@ GPU_PBVH_Buffers *GPU_pbvh_grid_buffers_build(int totgrid, BLI_bitmap **grid_hid
* \{ */
static int debug_pass = 0;
bool pbvh_show_orig_co = false;
/* Output a BMVert into a VertexBufferFormat array at v_index. */
static void gpu_bmesh_vert_to_buffer_copy(BMesh *bm,
@ -1090,7 +1091,7 @@ static void gpu_bmesh_vert_to_buffer_copy(BMesh *bm,
short no_short[3];
/* Set coord, normal, and mask */
if (G.debug_value == 890) {
if (G.debug_value == 890 || pbvh_show_orig_co) {
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);