Fix extremely nastly memory corruption bug in pbvh

This commit is contained in:
Joseph Eagar 2021-04-12 04:19:49 -07:00
parent b52e04f794
commit e07a95b86d
4 changed files with 102 additions and 40 deletions

View File

@ -2168,7 +2168,7 @@ bool ray_face_intersection_quad(const float ray_start[3],
return false;
}
__attribute__((optnone)) bool ray_face_intersection_tri(const float ray_start[3],
bool ray_face_intersection_tri(const float ray_start[3],
struct IsectRayPrecalc *isect_precalc,
const float t0[3],
const float t1[3],

View File

@ -775,6 +775,38 @@ static void pbvh_bmesh_vert_ownership_transfer(PBVH *pbvh, PBVHNode *new_owner,
new_owner->flag |= PBVH_UpdateDrawBuffers | PBVH_UpdateBB;
}
static bool pbvh_bmesh_vert_relink(PBVH *pbvh, BMVert *v)
{
const int cd_vert_node = pbvh->cd_vert_node_offset;
const int cd_face_node = pbvh->cd_face_node_offset;
BMFace *f;
BLI_assert(BM_ELEM_CD_GET_INT(v, cd_vert_node) == DYNTOPO_NODE_NONE);
bool added = false;
BM_FACES_OF_VERT_ITER_BEGIN (f, v) {
const int ni = BM_ELEM_CD_GET_INT(f, cd_face_node);
if (ni == DYNTOPO_NODE_NONE) {
continue;
}
PBVHNode *node = pbvh->nodes + ni;
if (BM_ELEM_CD_GET_INT(v, cd_vert_node) == DYNTOPO_NODE_NONE) {
BLI_table_gset_add(node->bm_unique_verts, v);
BM_ELEM_CD_SET_INT(v, cd_vert_node, ni);
}
else {
BLI_table_gset_add(node->bm_other_verts, v);
}
}
BM_FACES_OF_VERT_ITER_END;
return added;
}
static void pbvh_bmesh_vert_remove(PBVH *pbvh, BMVert *v)
{
/* never match for first time */
@ -2326,35 +2358,34 @@ static void pbvh_bmesh_collapse_edge(PBVH *pbvh,
* really buy anything. */
BLI_buffer_clear(deleted_faces);
#define MAX_LS 64
BMLoop *l;
BMLoop *ls[MAX_LS];
BMLoop **ls = NULL;
void **blocks = NULL;
float *ws = NULL;
BLI_array_staticdeclare(ls, 64);
BLI_array_staticdeclare(blocks, 64);
BLI_array_staticdeclare(ws, 64);
int totl = 0;
BM_LOOPS_OF_VERT_ITER_BEGIN (l, v_del) {
if (totl >= MAX_LS) {
break;
}
ls[totl++] = l;
BLI_array_append(ls, l);
totl++;
}
BM_LOOPS_OF_VERT_ITER_END;
BM_LOOPS_OF_VERT_ITER_BEGIN (l, v_conn) {
if (totl >= MAX_LS) {
break;
}
ls[totl++] = l;
BLI_array_append(ls, l);
totl++;
}
BM_LOOPS_OF_VERT_ITER_END;
void *blocks[MAX_LS];
float ws[MAX_LS], w = totl > 0 ? 1.0f / (float)(totl) : 1.0f;
float w = totl > 0 ? 1.0f / (float)(totl) : 1.0f;
for (int i = 0; i < totl; i++) {
blocks[i] = ls[i]->head.data;
ws[i] = w;
BLI_array_append(blocks, ls[i]->head.data);
BLI_array_append(ws, w);
}
// snap customdata
@ -2502,7 +2533,7 @@ static void pbvh_bmesh_collapse_edge(PBVH *pbvh,
if (v_conn != NULL) {
// log vert in bmlog, but don't update original customata layers, we want them to be
// interpolated
BM_log_vert_before_modified(pbvh->bm_log, v_conn, eq_ctx->cd_vert_mask_offset, true);
BM_log_vert_before_modified(pbvh->bm_log, v_conn, eq_ctx->cd_vert_mask_offset, false);
mid_v3_v3v3(v_conn->co, v_conn->co, v_del->co);
add_v3_v3(v_conn->no, v_del->no);
@ -2523,6 +2554,10 @@ static void pbvh_bmesh_collapse_edge(PBVH *pbvh,
/* v_conn == NULL is OK */
BLI_ghash_insert(deleted_verts, v_del, v_conn);
BM_vert_kill(pbvh->bm, v_del);
BLI_array_free(ws);
BLI_array_free(blocks);
BLI_array_free(ls);
}
void BKE_pbvh_bmesh_update_origvert(
@ -2672,15 +2707,15 @@ static bool pbvh_bmesh_collapse_short_edges(EdgeQueueContext *eq_ctx,
/************************* Called from pbvh.c *************************/
__attribute__((optnone)) bool pbvh_bmesh_node_raycast(PBVHNode *node,
const float ray_start[3],
const float ray_normal[3],
struct IsectRayPrecalc *isect_precalc,
float *depth,
bool use_original,
SculptVertRef *r_active_vertex_index,
SculptFaceRef *r_active_face_index,
float *r_face_normal)
bool pbvh_bmesh_node_raycast(PBVHNode *node,
const float ray_start[3],
const float ray_normal[3],
struct IsectRayPrecalc *isect_precalc,
float *depth,
bool use_original,
SculptVertRef *r_active_vertex_index,
SculptFaceRef *r_active_face_index,
float *r_face_normal)
{
bool hit = false;
float nearest_vertex_co[3] = {0.0f};
@ -3307,6 +3342,8 @@ static bool cleanup_valence_3_4(PBVH *pbvh,
const bool use_projected)
{
bool modified = false;
BMVert **relink_verts = NULL;
BLI_array_staticdeclare(relink_verts, 1024);
float radius2 = radius * 1.25;
float rsqr = radius2 * radius2;
@ -3394,9 +3431,19 @@ static bool cleanup_valence_3_4(PBVH *pbvh,
pbvh_bmesh_vert_remove(pbvh, v);
BM_log_vert_removed(pbvh->bm_log, v, pbvh->cd_vert_mask_offset);
BLI_array_clear(relink_verts);
BMFace *f;
BM_ITER_ELEM (f, &iter, v, BM_FACES_OF_VERT) {
pbvh_bmesh_face_remove(pbvh, f);
int ni2 = BM_ELEM_CD_GET_INT(f, pbvh->cd_face_node_offset);
if (ni2 != DYNTOPO_NODE_NONE) {
PBVHNode *node2 = pbvh->nodes + ni2;
BLI_table_gset_remove(node2->bm_unique_verts, v, NULL);
BLI_table_gset_remove(node2->bm_other_verts, v, NULL);
pbvh_bmesh_face_remove(pbvh, f);
}
}
modified = true;
@ -3409,7 +3456,7 @@ static bool cleanup_valence_3_4(PBVH *pbvh,
BMFace *f1 = NULL;
if (vs[0] != vs[1] && vs[1] != vs[2] && vs[0] != vs[2]) {
f1 = pbvh_bmesh_face_create(pbvh, n, vs, NULL, l->f, true, false);
f1 = pbvh_bmesh_face_create(pbvh, n, vs, NULL, l->f, false, false);
}
if (val == 4 && vs[0] != vs[2] && vs[2] != vs[3] && vs[0] != vs[3]) {
@ -3417,7 +3464,7 @@ static bool cleanup_valence_3_4(PBVH *pbvh,
vs[1] = ls[2]->v;
vs[2] = ls[3]->v;
BMFace *f2 = pbvh_bmesh_face_create(pbvh, n, vs, NULL, v->e->l->f, true, false);
BMFace *f2 = pbvh_bmesh_face_create(pbvh, n, vs, NULL, v->e->l->f, false, false);
SWAP(void *, f2->l_first->prev->head.data, ls[3]->head.data);
CustomData_bmesh_copy_data(
@ -3437,10 +3484,24 @@ static bool cleanup_valence_3_4(PBVH *pbvh,
}
BM_vert_kill(pbvh->bm, v);
#if 0
for (int j = 0; j < pbvh->totnode; j++) {
PBVHNode *node2 = pbvh->nodes + j;
if (!node2->bm_unique_verts || !node2->bm_other_verts) { //(node2->flag & PBVH_Leaf)) {
continue;
}
BLI_table_gset_remove(node2->bm_unique_verts, v, NULL);
BLI_table_gset_remove(node2->bm_other_verts, v, NULL);
}
#endif
}
TGSET_ITER_END
}
BLI_array_free(relink_verts);
if (modified) {
pbvh->bm->elem_index_dirty |= BM_VERT | BM_FACE | BM_EDGE;
pbvh->bm->elem_table_dirty |= BM_VERT | BM_FACE | BM_EDGE;
@ -3566,7 +3627,8 @@ bool BKE_pbvh_bmesh_update_topology(PBVH *pbvh,
if (!pbvh_bmesh_node_limit_ensure(pbvh, i)) {
BKE_pbvh_bmesh_node_save_ortri(pbvh->bm, pbvh->nodes + i);
}
} else {
}
else {
BKE_pbvh_bmesh_node_save_ortri(pbvh->bm, pbvh->nodes + i);
}
}
@ -3596,7 +3658,7 @@ bool BKE_pbvh_bmesh_update_topology(PBVH *pbvh,
* (currently just raycast), store the node's triangles and vertices.
*
* Skips triangles that are hidden. */
__attribute__((optnone)) void BKE_pbvh_bmesh_node_save_ortri(BMesh *bm, PBVHNode *node)
void BKE_pbvh_bmesh_node_save_ortri(BMesh *bm, PBVHNode *node)
{
/* Skip if original coords/triangles are already saved */
if (node->bm_orco) {
@ -4024,7 +4086,7 @@ void BKE_pbvh_bmesh_after_stroke(PBVH *pbvh)
check_heap();
int totnode = pbvh->totnode;
pbvh_bmesh_join_nodes(pbvh);
// pbvh_bmesh_join_nodes(pbvh);
check_heap();

View File

@ -330,7 +330,7 @@ static void vert_mask_set(BMVert *v, const float new_mask, const int cd_vert_mas
/* Update a BMLogVert with data from a BMVert */
static void bm_log_vert_bmvert_copy(BMLog *log,
BMLog *entry,
BMLogEntry *entry,
BMLogVert *lv,
BMVert *v,
const int cd_vert_mask_offset,
@ -426,7 +426,7 @@ static void bm_log_faces_unmake(BMesh *bm, BMLog *log, GHash *faces, BMLogEntry
e_tri[i] = l_iter->e;
}
//ensure we have final customdata for face in log
// ensure we have final customdata for face in log
#ifdef CUSTOMDATA
if (lf->customdata_f) {
CustomData_bmesh_copy_data(&bm->pdata, &entry->pdata, f->head.data, &lf->customdata_f);
@ -539,7 +539,7 @@ static void bm_log_vert_values_swap(BMesh *bm, BMLog *log, GHash *verts, BMLogEn
}
}
__attribute__ ((optnone)) static void bm_log_face_values_swap(BMLog *log, GHash *faces, BMLogEntry *entry)
static void bm_log_face_values_swap(BMLog *log, GHash *faces, BMLogEntry *entry)
{
GHashIterator gh_iter;
GHASH_ITER (gh_iter, faces) {
@ -1053,7 +1053,7 @@ void BM_log_entry_drop(BMLogEntry *entry)
/* Undo one BMLogEntry
*
* Has no effect if there's nothing left to undo */
__attribute__((optnone)) static void bm_log_undo_intern(BMesh *bm, BMLog *log, BMLogEntry *entry)
static void bm_log_undo_intern(BMesh *bm, BMLog *log, BMLogEntry *entry)
{
bm->elem_index_dirty |= BM_VERT | BM_EDGE | BM_FACE;
bm->elem_table_dirty |= BM_VERT | BM_EDGE | BM_FACE;

View File

@ -2341,7 +2341,7 @@ typedef struct AreaNormalCenterTLSData {
int count_co[2];
} AreaNormalCenterTLSData;
__attribute__((optnone)) static void calc_area_normal_and_center_task_cb(
static void calc_area_normal_and_center_task_cb(
void *__restrict userdata,
const int n,
const TaskParallelTLS *__restrict tls)
@ -2608,7 +2608,7 @@ void SCULPT_calc_area_normal(
}
/* Expose 'calc_area_normal' externally. */
__attribute__((optnone)) bool SCULPT_pbvh_calc_area_normal(const Brush *brush,
bool SCULPT_pbvh_calc_area_normal(const Brush *brush,
Object *ob,
PBVHNode **nodes,
int totnode,
@ -3121,7 +3121,7 @@ static PBVHNode **sculpt_pbvh_gather_generic(Object *ob,
}
/* Calculate primary direction of movement for many brushes. */
__attribute__ ((optnone)) static void calc_sculpt_normal(
static void calc_sculpt_normal(
Sculpt *sd, Object *ob, PBVHNode **nodes, int totnode, float r_area_no[3])
{
const Brush *brush = BKE_paint_brush(&sd->paint);
@ -3687,7 +3687,7 @@ static void do_displacement_smear_brush(Sculpt *sd, Object *ob, PBVHNode **nodes
/** \} */
__attribute__ ((optnone)) static void do_draw_brush_task_cb_ex(void *__restrict userdata,
static void do_draw_brush_task_cb_ex(void *__restrict userdata,
const int n,
const TaskParallelTLS *__restrict tls)
{