Fix extremely nastly memory corruption bug in pbvh
This commit is contained in:
parent
b52e04f794
commit
e07a95b86d
|
@ -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],
|
||||
|
|
|
@ -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();
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
|
|
Loading…
Reference in New Issue