commit prior to small cleanup
This commit is contained in:
parent
9680edf77c
commit
12f87d02c6
|
@ -2823,11 +2823,12 @@ cleanup_valence_3_4(EdgeQueueContext *ectx,
|
|||
int ni = BM_ELEM_CD_GET_INT(v, pbvh->cd_vert_node_offset);
|
||||
|
||||
if (ni >= 0 && BLI_table_gset_haskey(pbvh->nodes[ni].bm_other_verts, v)) {
|
||||
printf("error! %d\n", (int)BLI_table_gset_haskey(pbvh->nodes[ni].bm_unique_verts, v));
|
||||
printf("cleanup_valence_3_4 error! %d\n",
|
||||
(int)BLI_table_gset_haskey(pbvh->nodes[ni].bm_unique_verts, v));
|
||||
BLI_table_gset_remove(pbvh->nodes[ni].bm_other_verts, v, NULL);
|
||||
}
|
||||
else if (ni < 0) {
|
||||
printf("error!\n");
|
||||
printf("cleanup_valence_3_4 error!\n");
|
||||
|
||||
// attempt to recover
|
||||
|
||||
|
@ -3055,8 +3056,13 @@ bool BKE_pbvh_bmesh_update_topology(PBVH *pbvh,
|
|||
}
|
||||
# endif
|
||||
|
||||
float brusharea = radius / (pbvh->bm_min_edge_len * 0.5f + pbvh->bm_max_edge_len * 0.5f);
|
||||
brusharea = brusharea * brusharea * M_PI;
|
||||
|
||||
int max_steps = (int)((float)DYNTOPO_MAX_ITER * ratio);
|
||||
|
||||
printf("max_steps %d\n", max_steps);
|
||||
|
||||
pbvh_bmesh_check_nodes(pbvh);
|
||||
modified |= pbvh_bmesh_collapse_short_edges(&eq_ctx, pbvh, &deleted_faces, max_steps);
|
||||
pbvh_bmesh_check_nodes(pbvh);
|
||||
|
@ -3078,7 +3084,7 @@ bool BKE_pbvh_bmesh_update_topology(PBVH *pbvh,
|
|||
long_edge_queue_create(
|
||||
&eq_ctx, pbvh, center, view_normal, radius, use_frontface, use_projected);
|
||||
|
||||
# ifdef SKINNY_EDGE_FIX
|
||||
# if 0 /// def SKINNY_EDGE_FIX
|
||||
// prevent remesher thrashing by throttling edge splitting in pathological case of skinny edges
|
||||
float avg_elen = eq_ctx.avg_elen;
|
||||
if (eq_ctx.totedge > 0.0f) {
|
||||
|
@ -3091,13 +3097,22 @@ bool BKE_pbvh_bmesh_update_topology(PBVH *pbvh,
|
|||
|
||||
if (avg_elen > 0.0f) {
|
||||
ratio = (pbvh->bm_max_edge_len * 0.5 + emin * 0.5) / avg_elen;
|
||||
ratio = MAX2(ratio, 0.05f);
|
||||
ratio = MAX2(ratio, 0.75f);
|
||||
ratio = MIN2(ratio, 1.0f);
|
||||
}
|
||||
}
|
||||
# else
|
||||
ratio = 1.0f;
|
||||
# endif
|
||||
|
||||
float brusharea = radius / (pbvh->bm_min_edge_len * 0.5f + pbvh->bm_max_edge_len * 0.5f);
|
||||
brusharea = brusharea * brusharea * M_PI;
|
||||
|
||||
int max_steps = (int)((float)DYNTOPO_MAX_ITER * ratio);
|
||||
max_steps = (int)(brusharea * ratio * 1.0f);
|
||||
|
||||
printf("brusharea: %.2f, ratio: %.2f\n", brusharea, ratio);
|
||||
printf("max_steps %d\n", max_steps);
|
||||
|
||||
pbvh_bmesh_check_nodes(pbvh);
|
||||
modified |= pbvh_bmesh_subdivide_long_edges(&eq_ctx, pbvh, &edge_loops, max_steps);
|
||||
|
@ -3347,7 +3362,7 @@ static const int splitmap[43][16] = {
|
|||
{6, -1, 3, -1, 5, -1, 1, -1}, // 42
|
||||
};
|
||||
|
||||
static void pbvh_split_edges(PBVH *pbvh, BMesh *bm, BMEdge **edges, int totedge)
|
||||
ATTR_NO_OPT static void pbvh_split_edges(PBVH *pbvh, BMesh *bm, BMEdge **edges, int totedge)
|
||||
{
|
||||
BMFace **faces = NULL;
|
||||
BLI_array_staticdeclare(faces, 512);
|
||||
|
@ -3388,7 +3403,7 @@ static void pbvh_split_edges(PBVH *pbvh, BMesh *bm, BMEdge **edges, int totedge)
|
|||
l2->v->head.hflag &= ~SPLIT_TAG;
|
||||
|
||||
MDynTopoVert *mv = BKE_PBVH_DYNVERT(pbvh->cd_dyn_vert, l2->v);
|
||||
mv->flag |= DYNVERT_NEED_VALENCE;
|
||||
mv->flag |= DYNVERT_NEED_VALENCE | DYNVERT_NEED_BOUNDARY | DYNVERT_NEED_DISK_SORT;
|
||||
} while ((l2 = l2->next) != l->f->l_first);
|
||||
|
||||
l->f->head.hflag &= ~SPLIT_TAG;
|
||||
|
@ -3419,7 +3434,8 @@ static void pbvh_split_edges(PBVH *pbvh, BMesh *bm, BMEdge **edges, int totedge)
|
|||
BMFace *f = faces[i];
|
||||
BMLoop *l = f->l_first;
|
||||
|
||||
pbvh_bmesh_face_remove(pbvh, f, true, false, false);
|
||||
// pbvh_bmesh_face_remove(pbvh, f, true, false, false);
|
||||
BM_log_face_removed(pbvh->bm_log, f);
|
||||
|
||||
int mask = 0;
|
||||
int j = 0;
|
||||
|
@ -3450,9 +3466,45 @@ static void pbvh_split_edges(PBVH *pbvh, BMesh *bm, BMEdge **edges, int totedge)
|
|||
MDynTopoVert *mv = BKE_PBVH_DYNVERT(pbvh->cd_dyn_vert, newv);
|
||||
|
||||
newv->head.hflag |= SPLIT_TAG;
|
||||
mv->flag |= DYNVERT_NEED_VALENCE;
|
||||
mv->flag |= DYNVERT_NEED_VALENCE | DYNVERT_NEED_BOUNDARY | DYNVERT_NEED_DISK_SORT;
|
||||
|
||||
# if 1
|
||||
int ni = BM_ELEM_CD_GET_INT(e->v1, pbvh->cd_vert_node_offset);
|
||||
|
||||
if (ni == DYNTOPO_NODE_NONE) {
|
||||
ni = BM_ELEM_CD_GET_INT(e->v2, pbvh->cd_vert_node_offset);
|
||||
}
|
||||
|
||||
if (ni != DYNTOPO_NODE_NONE) {
|
||||
PBVHNode *node = pbvh->nodes + ni;
|
||||
|
||||
BLI_table_gset_add(node->bm_unique_verts, newv);
|
||||
BMIter iter;
|
||||
BMFace *f;
|
||||
|
||||
# if 0
|
||||
BM_ITER_ELEM (f, &iter, newv, BM_FACES_OF_VERT) {
|
||||
int ni2 = BM_ELEM_CD_GET_INT(f, pbvh->cd_face_node_offset);
|
||||
|
||||
if (ni != ni2 && ni2 != DYNTOPO_NODE_NONE) {
|
||||
PBVHNode *node2 = pbvh->nodes + ni2;
|
||||
|
||||
BLI_table_gset_add(node2->bm_other_verts, newv);
|
||||
}
|
||||
}
|
||||
# endif
|
||||
|
||||
BM_ELEM_CD_SET_INT(newv, pbvh->cd_vert_node_offset, ni);
|
||||
}
|
||||
else {
|
||||
BM_ELEM_CD_SET_INT(newv, pbvh->cd_vert_node_offset, DYNTOPO_NODE_NONE);
|
||||
printf("eek!");
|
||||
}
|
||||
|
||||
# else
|
||||
BM_ELEM_CD_SET_INT(newv, pbvh->cd_vert_node_offset, DYNTOPO_NODE_NONE);
|
||||
# endif
|
||||
|
||||
BM_log_vert_added(pbvh->bm_log, newv, pbvh->cd_vert_mask_offset);
|
||||
}
|
||||
|
||||
|
@ -3460,6 +3512,8 @@ static void pbvh_split_edges(PBVH *pbvh, BMesh *bm, BMEdge **edges, int totedge)
|
|||
BMFace *f = faces[i];
|
||||
int mask = 0;
|
||||
|
||||
int ni = BM_ELEM_CD_GET_INT(f, pbvh->cd_face_node_offset);
|
||||
|
||||
BMLoop *l = f->l_first;
|
||||
int j = 0;
|
||||
do {
|
||||
|
@ -3524,6 +3578,20 @@ static void pbvh_split_edges(PBVH *pbvh, BMesh *bm, BMEdge **edges, int totedge)
|
|||
|
||||
BMFace *newf = BM_face_split(bm, f2, l1, l2, &rl, NULL, false);
|
||||
if (newf) {
|
||||
bool ok = ni != DYNTOPO_NODE_NONE;
|
||||
ok = ok && BM_ELEM_CD_GET_INT(v1, pbvh->cd_vert_node_offset) != DYNTOPO_NODE_NONE;
|
||||
ok = ok && BM_ELEM_CD_GET_INT(v2, pbvh->cd_vert_node_offset) != DYNTOPO_NODE_NONE;
|
||||
|
||||
if (ok) {
|
||||
PBVHNode *node = pbvh->nodes + ni;
|
||||
|
||||
BLI_table_gset_add(node->bm_faces, newf);
|
||||
BM_ELEM_CD_SET_INT(newf, pbvh->cd_face_node_offset, ni);
|
||||
}
|
||||
else {
|
||||
BM_ELEM_CD_SET_INT(newf, pbvh->cd_face_node_offset, DYNTOPO_NODE_NONE);
|
||||
}
|
||||
|
||||
newfaces[count++] = newf;
|
||||
f2 = newf;
|
||||
}
|
||||
|
@ -3534,10 +3602,50 @@ static void pbvh_split_edges(PBVH *pbvh, BMesh *bm, BMEdge **edges, int totedge)
|
|||
}
|
||||
|
||||
for (j = 0; j < count; j++) {
|
||||
BKE_pbvh_bmesh_add_face(pbvh, newfaces[j], true, false);
|
||||
if (BM_ELEM_CD_GET_INT(newfaces[j], pbvh->cd_face_node_offset) == DYNTOPO_NODE_NONE) {
|
||||
BKE_pbvh_bmesh_add_face(pbvh, newfaces[j], false, true);
|
||||
}
|
||||
else {
|
||||
BMFace *f = newfaces[j];
|
||||
if (f->len != 3) {
|
||||
printf("eek! f->len was not 3! len: %d\n", f->len);
|
||||
}
|
||||
|
||||
// add face verts to bm_other_verts
|
||||
|
||||
int lastni2 = -1;
|
||||
|
||||
BMLoop *l = f->l_first;
|
||||
do {
|
||||
BMEdge *e = l->v->e;
|
||||
|
||||
do {
|
||||
BMLoop *l2 = e->l;
|
||||
do {
|
||||
int ni = BM_ELEM_CD_GET_INT(l->v, pbvh->cd_vert_node_offset);
|
||||
int ni2 = BM_ELEM_CD_GET_INT(l2->f, pbvh->cd_face_node_offset);
|
||||
|
||||
if (ni2 != ni && ni2 != lastni2 && ni2 != DYNTOPO_NODE_NONE) {
|
||||
PBVHNode *node = pbvh->nodes + ni2;
|
||||
|
||||
BLI_table_gset_add(node->bm_other_verts, l->v);
|
||||
lastni2 = ni2;
|
||||
}
|
||||
} while ((l2 = l2->radial_next) != e->l);
|
||||
|
||||
e = l->v == e->v1 ? e->v1_disk_link.next : e->v2_disk_link.next;
|
||||
} while (e != l->v->e);
|
||||
} while ((l = l->next) != f->l_first);
|
||||
}
|
||||
|
||||
BM_log_face_added(pbvh->bm_log, newfaces[j]);
|
||||
}
|
||||
|
||||
BKE_pbvh_bmesh_add_face(pbvh, f, true, false);
|
||||
if (BM_ELEM_CD_GET_INT(f, pbvh->cd_face_node_offset) == DYNTOPO_NODE_NONE) {
|
||||
BKE_pbvh_bmesh_add_face(pbvh, f, false, true);
|
||||
}
|
||||
|
||||
BM_log_face_added(pbvh->bm_log, f);
|
||||
}
|
||||
|
||||
BLI_array_free(faces);
|
||||
|
|
|
@ -81,6 +81,27 @@ void BB_reset(BB *bb)
|
|||
bb->bmax[0] = bb->bmax[1] = bb->bmax[2] = -FLT_MAX;
|
||||
}
|
||||
|
||||
void BB_intersect(BB *r_out, BB *a, BB *b)
|
||||
{
|
||||
for (int i = 0; i < 3; i++) {
|
||||
r_out->bmin[i] = max_ff(a->bmin[i], b->bmin[i]);
|
||||
r_out->bmax[i] = min_ff(a->bmax[i], b->bmax[i]);
|
||||
|
||||
if (r_out->bmax[i] < r_out->bmin[i]) {
|
||||
r_out->bmax[i] = r_out->bmin[i] = 0.0f;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
float BB_volume(const BB *bb)
|
||||
{
|
||||
float dx = bb->bmax[0] - bb->bmin[0];
|
||||
float dy = bb->bmax[1] - bb->bmin[1];
|
||||
float dz = bb->bmax[2] - bb->bmin[2];
|
||||
|
||||
return dx * dy * dz;
|
||||
}
|
||||
|
||||
/* Expand the bounding box to include a new coordinate */
|
||||
void BB_expand(BB *bb, const float co[3])
|
||||
{
|
||||
|
|
|
@ -170,6 +170,12 @@ void pbvh_bmesh_check_nodes(PBVH *pbvh)
|
|||
TGSET_ITER (f, node->bm_faces) {
|
||||
if (!f || f->head.htype != BM_FACE) {
|
||||
printf("corruption in pbvh! bm_faces\n");
|
||||
continue;
|
||||
}
|
||||
|
||||
int ni = BM_ELEM_CD_GET_INT(f, pbvh->cd_face_node_offset);
|
||||
if (pbvh->nodes + ni != node) {
|
||||
printf("face in multiple nodes!\n");
|
||||
}
|
||||
}
|
||||
TGSET_ITER_END;
|
||||
|
@ -596,7 +602,7 @@ void bke_pbvh_insert_face(PBVH *pbvh, struct BMFace *f)
|
|||
}
|
||||
|
||||
if (ni < 0 || !(pbvh->nodes[ni].flag & PBVH_Leaf)) {
|
||||
fprintf(stderr, "pbvh error!\n");
|
||||
fprintf(stderr, "pbvh error! failed to find node to insert face into!\n");
|
||||
fflush(stderr);
|
||||
return;
|
||||
}
|
||||
|
@ -1422,10 +1428,7 @@ void bke_pbvh_update_vert_boundary(int cd_dyn_vert, int cd_faceset_offset, BMVer
|
|||
e = e->v1 == v ? e->v1_disk_link.next : e->v2_disk_link.next;
|
||||
} while (e != v->e);
|
||||
|
||||
if (fset1 && fset2) {
|
||||
mv->flag |= DYNVERT_FSET_BOUNDARY;
|
||||
}
|
||||
|
||||
#if 0
|
||||
if (fset2 && !fset3) {
|
||||
int n = MIN2(fset1_count, fset2_count);
|
||||
float maxth = 0;
|
||||
|
@ -1465,10 +1468,17 @@ void bke_pbvh_update_vert_boundary(int cd_dyn_vert, int cd_faceset_offset, BMVer
|
|||
mv->flag |= DYNVERT_FSET_CORNER;
|
||||
}
|
||||
}
|
||||
else if (fset2 && fset3) {
|
||||
else
|
||||
#endif
|
||||
|
||||
if (fset2 && fset3) {
|
||||
mv->flag |= DYNVERT_FSET_CORNER;
|
||||
}
|
||||
|
||||
if (fset1 && fset2) {
|
||||
mv->flag |= DYNVERT_FSET_BOUNDARY;
|
||||
}
|
||||
|
||||
mv->valence = val;
|
||||
if (val < 4 && (mv->flag & DYNVERT_BOUNDARY)) {
|
||||
mv->flag |= DYNVERT_CORNER;
|
||||
|
@ -2458,6 +2468,374 @@ static void BKE_pbvh_bmesh_correct_tree(PBVH *pbvh, PBVHNode *node, PBVHNode *pa
|
|||
}
|
||||
}
|
||||
|
||||
// deletes PBVH_Delete marked nodes
|
||||
static void pbvh_bmesh_compact_tree(PBVH *bvh)
|
||||
{
|
||||
// compact nodes
|
||||
int totnode = 0;
|
||||
for (int i = 0; i < bvh->totnode; i++) {
|
||||
PBVHNode *n = bvh->nodes + i;
|
||||
|
||||
if (!(n->flag & PBVH_Delete)) {
|
||||
if (!(n->flag & PBVH_Leaf)) {
|
||||
PBVHNode *n1 = bvh->nodes + n->children_offset;
|
||||
PBVHNode *n2 = bvh->nodes + n->children_offset + 1;
|
||||
|
||||
if ((n1->flag & PBVH_Delete) != (n2->flag & PBVH_Delete)) {
|
||||
printf("un-deleting an empty node\n");
|
||||
PBVHNode *n3 = n1->flag & PBVH_Delete ? n1 : n2;
|
||||
|
||||
n3->flag = PBVH_Leaf | PBVH_UpdateTris;
|
||||
n3->bm_unique_verts = BLI_table_gset_new("bm_unique_verts");
|
||||
n3->bm_other_verts = BLI_table_gset_new("bm_other_verts");
|
||||
n3->bm_faces = BLI_table_gset_new("bm_faces");
|
||||
n3->tribuf = NULL;
|
||||
}
|
||||
else if ((n1->flag & PBVH_Delete) && (n2->flag & PBVH_Delete)) {
|
||||
n->children_offset = 0;
|
||||
n->flag |= PBVH_Leaf | PBVH_UpdateTris;
|
||||
|
||||
if (!n->bm_unique_verts) {
|
||||
// should not happen
|
||||
n->bm_unique_verts = BLI_table_gset_new("bm_unique_verts");
|
||||
n->bm_other_verts = BLI_table_gset_new("bm_other_verts");
|
||||
n->bm_faces = BLI_table_gset_new("bm_faces");
|
||||
n->tribuf = NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
totnode++;
|
||||
}
|
||||
}
|
||||
|
||||
int *map = MEM_callocN(sizeof(int) * bvh->totnode, "bmesh map temp");
|
||||
|
||||
// build idx map for child offsets
|
||||
int j = 0;
|
||||
for (int i = 0; i < bvh->totnode; i++) {
|
||||
PBVHNode *n = bvh->nodes + i;
|
||||
|
||||
if (!(n->flag & PBVH_Delete)) {
|
||||
map[i] = j++;
|
||||
}
|
||||
else if (1) {
|
||||
if (n->layer_disp) {
|
||||
MEM_freeN(n->layer_disp);
|
||||
n->layer_disp = NULL;
|
||||
}
|
||||
|
||||
pbvh_free_all_draw_buffers(n);
|
||||
|
||||
if (n->vert_indices) {
|
||||
MEM_freeN((void *)n->vert_indices);
|
||||
n->vert_indices = NULL;
|
||||
}
|
||||
if (n->face_vert_indices) {
|
||||
MEM_freeN((void *)n->face_vert_indices);
|
||||
n->face_vert_indices = NULL;
|
||||
}
|
||||
|
||||
if (n->tribuf || n->tri_buffers) {
|
||||
BKE_pbvh_bmesh_free_tris(bvh, n);
|
||||
}
|
||||
|
||||
if (n->bm_unique_verts) {
|
||||
BLI_table_gset_free(n->bm_unique_verts, NULL);
|
||||
n->bm_unique_verts = NULL;
|
||||
}
|
||||
|
||||
if (n->bm_other_verts) {
|
||||
BLI_table_gset_free(n->bm_other_verts, NULL);
|
||||
n->bm_other_verts = NULL;
|
||||
}
|
||||
|
||||
if (n->bm_faces) {
|
||||
BLI_table_gset_free(n->bm_faces, NULL);
|
||||
n->bm_faces = NULL;
|
||||
}
|
||||
|
||||
#ifdef PROXY_ADVANCED
|
||||
BKE_pbvh_free_proxyarray(bvh, n);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
// compact node array
|
||||
j = 0;
|
||||
for (int i = 0; i < bvh->totnode; i++) {
|
||||
if (!(bvh->nodes[i].flag & PBVH_Delete)) {
|
||||
if (bvh->nodes[i].children_offset >= bvh->totnode - 1) {
|
||||
printf("error %i %i\n", i, bvh->nodes[i].children_offset);
|
||||
continue;
|
||||
}
|
||||
|
||||
int i1 = map[bvh->nodes[i].children_offset];
|
||||
int i2 = map[bvh->nodes[i].children_offset + 1];
|
||||
|
||||
if (bvh->nodes[i].children_offset >= bvh->totnode) {
|
||||
printf("bad child node reference %d->%d, totnode: %d\n",
|
||||
i,
|
||||
bvh->nodes[i].children_offset,
|
||||
bvh->totnode);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (bvh->nodes[i].children_offset && i2 != i1 + 1) {
|
||||
printf(" pbvh corruption during node join %d %d\n", i1, i2);
|
||||
}
|
||||
|
||||
bvh->nodes[j] = bvh->nodes[i];
|
||||
bvh->nodes[j].children_offset = i1;
|
||||
|
||||
j++;
|
||||
}
|
||||
}
|
||||
|
||||
if (j != totnode) {
|
||||
printf("pbvh error: %s", __func__);
|
||||
}
|
||||
|
||||
if (bvh->totnode != j) {
|
||||
memset(bvh->nodes + j, 0, sizeof(*bvh->nodes) * (bvh->totnode - j));
|
||||
bvh->node_mem_count = j;
|
||||
}
|
||||
|
||||
bvh->totnode = j;
|
||||
|
||||
// set vert/face node indices again
|
||||
for (int i = 0; i < bvh->totnode; i++) {
|
||||
PBVHNode *n = bvh->nodes + i;
|
||||
|
||||
if (!(n->flag & PBVH_Leaf)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!n->bm_unique_verts) {
|
||||
printf("ERROR!\n");
|
||||
n->bm_unique_verts = BLI_table_gset_new("bleh");
|
||||
n->bm_other_verts = BLI_table_gset_new("bleh");
|
||||
n->bm_faces = BLI_table_gset_new("bleh");
|
||||
}
|
||||
|
||||
BMVert *v;
|
||||
|
||||
TGSET_ITER (v, n->bm_unique_verts) {
|
||||
BM_ELEM_CD_SET_INT(v, bvh->cd_vert_node_offset, i);
|
||||
}
|
||||
TGSET_ITER_END
|
||||
|
||||
BMFace *f;
|
||||
|
||||
TGSET_ITER (f, n->bm_faces) {
|
||||
BM_ELEM_CD_SET_INT(f, bvh->cd_face_node_offset, i);
|
||||
}
|
||||
TGSET_ITER_END
|
||||
}
|
||||
|
||||
BMVert **scratch = NULL;
|
||||
BLI_array_declare(scratch);
|
||||
|
||||
for (int i = 0; i < bvh->totnode; i++) {
|
||||
PBVHNode *n = bvh->nodes + i;
|
||||
|
||||
if (!(n->flag & PBVH_Leaf)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
BLI_array_clear(scratch);
|
||||
BMVert *v;
|
||||
|
||||
TGSET_ITER (v, n->bm_other_verts) {
|
||||
int ni = BM_ELEM_CD_GET_INT(v, bvh->cd_vert_node_offset);
|
||||
if (ni == DYNTOPO_NODE_NONE) {
|
||||
BLI_array_append(scratch, v);
|
||||
}
|
||||
// BM_ELEM_CD_SET_INT(v, bvh->cd_vert_node_offset, i);
|
||||
}
|
||||
TGSET_ITER_END
|
||||
|
||||
int slen = BLI_array_len(scratch);
|
||||
for (int j = 0; j < slen; j++) {
|
||||
BMVert *v = scratch[j];
|
||||
|
||||
BLI_table_gset_remove(n->bm_other_verts, v, NULL);
|
||||
BLI_table_gset_add(n->bm_unique_verts, v);
|
||||
BM_ELEM_CD_SET_INT(v, bvh->cd_vert_node_offset, i);
|
||||
}
|
||||
}
|
||||
|
||||
BLI_array_free(scratch);
|
||||
MEM_freeN(map);
|
||||
}
|
||||
|
||||
static void recursive_delete_nodes(PBVH *pbvh, int ni)
|
||||
{
|
||||
PBVHNode *node = pbvh->nodes + ni;
|
||||
|
||||
node->flag |= PBVH_Delete;
|
||||
|
||||
if (!(node->flag & PBVH_Leaf) && node->children_offset) {
|
||||
if (node->children_offset < pbvh->totnode) {
|
||||
recursive_delete_nodes(pbvh, node->children_offset);
|
||||
}
|
||||
|
||||
if (node->children_offset + 1 < pbvh->totnode) {
|
||||
recursive_delete_nodes(pbvh, node->children_offset + 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// static float bbox_overlap()
|
||||
/* works by detect overlay of leaf nodes, destroying them
|
||||
and then re-inserting them*/
|
||||
ATTR_NO_OPT static void pbvh_bmesh_balance_tree(PBVH *pbvh)
|
||||
{
|
||||
PBVHNode **stack = NULL;
|
||||
float *overlaps = MEM_calloc_arrayN(pbvh->totnode, sizeof(float), "overlaps");
|
||||
PBVHNode **parentmap = MEM_calloc_arrayN(pbvh->totnode, sizeof(*parentmap), "parentmap");
|
||||
int *depthmap = MEM_calloc_arrayN(pbvh->totnode, sizeof(*depthmap), "depthmap");
|
||||
BLI_array_declare(stack);
|
||||
|
||||
BMFace **faces = NULL;
|
||||
BLI_array_declare(faces);
|
||||
|
||||
PBVHNode **substack = NULL;
|
||||
BLI_array_declare(substack);
|
||||
|
||||
for (int i = 0; i < pbvh->totnode; i++) {
|
||||
PBVHNode *node = pbvh->nodes + i;
|
||||
|
||||
if ((node->flag & PBVH_Leaf) || node->children_offset == 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (node->children_offset < pbvh->totnode) {
|
||||
parentmap[node->children_offset] = node;
|
||||
}
|
||||
|
||||
if (node->children_offset + 1 < pbvh->totnode) {
|
||||
parentmap[node->children_offset + 1] = node;
|
||||
}
|
||||
}
|
||||
|
||||
#if 0
|
||||
for (int i = 0; i < pbvh->totnode; i++) {
|
||||
PBVHNode *node = pbvh->nodes + i;
|
||||
PBVHNode *parent = parentmap[i];
|
||||
int depth = 0;
|
||||
|
||||
while (parent) {
|
||||
parent = parentmap[parent - pbvh->nodes];
|
||||
depth++;
|
||||
}
|
||||
|
||||
depthmap[i] = depth;
|
||||
}
|
||||
#endif
|
||||
|
||||
const int cd_vert_node = pbvh->cd_vert_node_offset;
|
||||
const int cd_face_node = pbvh->cd_face_node_offset;
|
||||
|
||||
bool modified = false;
|
||||
|
||||
BLI_array_append(stack, pbvh->nodes);
|
||||
while (BLI_array_len(stack) > 0) {
|
||||
PBVHNode *node = BLI_array_pop(stack);
|
||||
BB clip;
|
||||
|
||||
if (!(node->flag & PBVH_Leaf) && node->children_offset > 0) {
|
||||
PBVHNode *child1 = pbvh->nodes + node->children_offset;
|
||||
PBVHNode *child2 = pbvh->nodes + node->children_offset + 1;
|
||||
|
||||
float volume = BB_volume(&child1->vb) + BB_volume(&child2->vb);
|
||||
|
||||
BB_intersect(&clip, &child1->vb, &child2->vb);
|
||||
float overlap = BB_volume(&clip);
|
||||
|
||||
// for (int i = 0; i < depthmap[node - pbvh->nodes]; i++) {
|
||||
// printf("-");
|
||||
//}
|
||||
|
||||
// printf("volume: %.4f overlap: %.4f ratio: %.3f\n", volume, overlap, overlap / volume);
|
||||
|
||||
if (overlap > volume * 0.25) {
|
||||
modified = true;
|
||||
// printf(" DELETE!\n");
|
||||
|
||||
BLI_array_clear(substack);
|
||||
|
||||
BLI_array_append(substack, child1);
|
||||
BLI_array_append(substack, child2);
|
||||
|
||||
while (BLI_array_len(substack) > 0) {
|
||||
PBVHNode *node2 = BLI_array_pop(substack);
|
||||
|
||||
node2->flag |= PBVH_Delete;
|
||||
|
||||
if (node2->flag & PBVH_Leaf) {
|
||||
BMFace *f;
|
||||
BMVert *v;
|
||||
|
||||
TGSET_ITER (f, node2->bm_faces) {
|
||||
if (BM_ELEM_CD_GET_INT(f, cd_face_node) == -1) {
|
||||
// eek!
|
||||
continue;
|
||||
}
|
||||
|
||||
BM_ELEM_CD_SET_INT(f, cd_face_node, DYNTOPO_NODE_NONE);
|
||||
BLI_array_append(faces, f);
|
||||
}
|
||||
TGSET_ITER_END;
|
||||
|
||||
TGSET_ITER (v, node2->bm_unique_verts) {
|
||||
BM_ELEM_CD_SET_INT(v, cd_vert_node, DYNTOPO_NODE_NONE);
|
||||
}
|
||||
TGSET_ITER_END;
|
||||
}
|
||||
else if (node2->children_offset > 0 && node2->children_offset < pbvh->totnode) {
|
||||
BLI_array_append(substack, pbvh->nodes + node2->children_offset);
|
||||
|
||||
if (node2->children_offset + 1 < pbvh->totnode) {
|
||||
BLI_array_append(substack, pbvh->nodes + node2->children_offset + 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (node->children_offset < pbvh->totnode) {
|
||||
BLI_array_append(stack, child1);
|
||||
}
|
||||
|
||||
if (node->children_offset + 1 < pbvh->totnode) {
|
||||
BLI_array_append(stack, child2);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (modified) {
|
||||
pbvh_bmesh_compact_tree(pbvh);
|
||||
|
||||
printf("joined nodes; %d faces\n", BLI_array_len(faces));
|
||||
|
||||
for (int i = 0; i < BLI_array_len(faces); i++) {
|
||||
if (BM_ELEM_CD_GET_INT(faces[i], cd_face_node) != DYNTOPO_NODE_NONE) {
|
||||
// printf("duplicate faces in pbvh_bmesh_balance_tree!\n");
|
||||
continue;
|
||||
}
|
||||
|
||||
bke_pbvh_insert_face(pbvh, faces[i]);
|
||||
}
|
||||
}
|
||||
|
||||
BLI_array_free(faces);
|
||||
|
||||
MEM_SAFE_FREE(parentmap);
|
||||
MEM_SAFE_FREE(overlaps);
|
||||
BLI_array_free(stack);
|
||||
BLI_array_free(substack);
|
||||
}
|
||||
|
||||
static void pbvh_bmesh_join_nodes(PBVH *bvh)
|
||||
{
|
||||
if (bvh->totnode < 2) {
|
||||
|
@ -2669,12 +3047,20 @@ void BKE_pbvh_bmesh_after_stroke(PBVH *pbvh)
|
|||
{
|
||||
int totnode = pbvh->totnode;
|
||||
|
||||
BKE_pbvh_update_bounds(pbvh, (PBVH_UpdateBB | PBVH_UpdateOriginalBB | PBVH_UpdateRedraw));
|
||||
|
||||
pbvh_bmesh_check_nodes(pbvh);
|
||||
pbvh_bmesh_join_nodes(pbvh);
|
||||
pbvh_bmesh_check_nodes(pbvh);
|
||||
|
||||
BKE_pbvh_update_bounds(pbvh, (PBVH_UpdateBB | PBVH_UpdateOriginalBB | PBVH_UpdateRedraw));
|
||||
|
||||
if (1 || pbvh->balance_counter++ == 5) {
|
||||
pbvh_bmesh_balance_tree(pbvh);
|
||||
pbvh_bmesh_check_nodes(pbvh);
|
||||
pbvh->balance_counter = 0;
|
||||
}
|
||||
|
||||
totnode = pbvh->totnode;
|
||||
|
||||
for (int i = 0; i < totnode; i++) {
|
||||
|
|
|
@ -208,6 +208,8 @@ struct PBVH {
|
|||
|
||||
bool flat_vcol_shading;
|
||||
bool need_full_render; // used by pbvh drawing for PBVH_BMESH
|
||||
|
||||
int balance_counter;
|
||||
};
|
||||
|
||||
/* pbvh.c */
|
||||
|
@ -216,6 +218,9 @@ void BB_expand(BB *bb, const float co[3]);
|
|||
void BB_expand_with_bb(BB *bb, BB *bb2);
|
||||
void BBC_update_centroid(BBC *bbc);
|
||||
int BB_widest_axis(const BB *bb);
|
||||
void BB_intersect(BB *r_out, BB *a, BB *b);
|
||||
float BB_volume(const BB *bb);
|
||||
|
||||
void pbvh_grow_nodes(PBVH *bvh, int totnode);
|
||||
bool ray_face_intersection_quad(const float ray_start[3],
|
||||
struct IsectRayPrecalc *isect_precalc,
|
||||
|
|
|
@ -1542,8 +1542,7 @@ void SCULPT_dyntopo_save_persistent_base(SculptSession *ss);
|
|||
#define SCULPT_LAYER_DISP "__dyntopo_layer_disp"
|
||||
|
||||
// these tools don't support dynamic pbvh splitting during the stroke
|
||||
#define DYNTOPO_HAS_DYNAMIC_SPLIT(tool) \
|
||||
(ELEM(tool, SCULPT_TOOL_DRAW_SHARP, SCULPT_TOOL_LAYER) == 0)
|
||||
#define DYNTOPO_HAS_DYNAMIC_SPLIT(tool) (ELEM(tool, SCULPT_TOOL_LAYER) == 0)
|
||||
|
||||
/*get current symmetry pass index inclusive of both
|
||||
mirror and radial symmetry*/
|
||||
|
|
|
@ -1060,6 +1060,8 @@ GPU_PBVH_Buffers *GPU_pbvh_grid_buffers_build(int totgrid, BLI_bitmap **grid_hid
|
|||
/** \name BMesh PBVH
|
||||
* \{ */
|
||||
|
||||
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,
|
||||
GPUVertBuf *vert_buf,
|
||||
|
@ -1099,7 +1101,7 @@ static void gpu_bmesh_vert_to_buffer_copy(BMVert *v,
|
|||
if (G.debug_value == 889) {
|
||||
int ni = BM_ELEM_CD_GET_INT(v, cd_vert_node_offset);
|
||||
|
||||
effective_mask = ni == -1 ? 0.0f : (float)((ni * 50) % 32) / 32.0f;
|
||||
effective_mask = ni == -1 ? 0.0f : (float)(((ni + debug_pass) * 511) % 64) / 64;
|
||||
}
|
||||
|
||||
uchar cmask = (uchar)(effective_mask * 255);
|
||||
|
@ -1267,6 +1269,8 @@ void GPU_pbvh_update_attribute_names(CustomData *vdata,
|
|||
{
|
||||
const bool active_only = !need_full_render;
|
||||
|
||||
debug_pass++;
|
||||
|
||||
GPU_vertformat_clear(&g_vbo_id.format);
|
||||
|
||||
g_vbo_id.fast_mode = fast_mode;
|
||||
|
|
Loading…
Reference in New Issue