[Bf-blender-cvs] [54ee221] dyntopo_holes: Merge branch 'master' into dyntopo_holes
Campbell Barton
noreply at git.blender.org
Sat Oct 11 14:23:21 CEST 2014
Commit: 54ee22130ca0ce59500c6eddb562b78eb4526bcd
Author: Campbell Barton
Date: Sat Oct 11 14:17:14 2014 +0200
Branches: dyntopo_holes
https://developer.blender.org/rB54ee22130ca0ce59500c6eddb562b78eb4526bcd
Merge branch 'master' into dyntopo_holes
Conflicts:
source/blender/blenkernel/intern/pbvh_bmesh.c
===================================================================
===================================================================
diff --cc source/blender/blenkernel/intern/pbvh_bmesh.c
index 28c01e0,9e18d54..e0cf9ee
--- a/source/blender/blenkernel/intern/pbvh_bmesh.c
+++ b/source/blender/blenkernel/intern/pbvh_bmesh.c
@@@ -764,224 -722,6 +802,224 @@@ static void short_edge_queue_create(Edg
}
}
+#ifdef USE_HOLE_VOLUME_CLEAN
+static void tetrahedron_edge_queue_create(
+ EdgeQueueContext *eq_ctx,
+ PBVH *bvh, const float center[3],
+ float radius)
+{
+ int n;
+
+ eq_ctx->q->heap = BLI_heap_new();
+ eq_ctx->q->center = center;
+ eq_ctx->q->radius_squared = radius * radius;
+ eq_ctx->q->limit_len_squared = bvh->bm_min_edge_len * bvh->bm_min_edge_len;
+
+ for (n = 0; n < bvh->totnode; n++) {
+ PBVHNode *node = &bvh->nodes[n];
+
+ /* Check leaf nodes marked for topology update */
+ if ((node->flag & PBVH_Leaf) &&
+ (node->flag & PBVH_UpdateTopology) &&
+ !(node->flag & PBVH_FullyHidden))
+ {
+ GSetIterator gs_iter;
+
+ /* Check each face */
+ GSET_ITER (gs_iter, node->bm_faces) {
+ BMFace *f = BLI_gsetIterator_getKey(&gs_iter);
+
+ tetrahedron_edge_queue_face_add(eq_ctx, f);
+ }
+ }
+ }
+}
+#endif /* USE_HOLE_VOLUME_CLEAN */
+
+static void pbvh_bmesh_delete_vert_face(PBVH *bvh, BMVert *v, BMFace *f_del, GSet *deleted_verts, EdgeQueueContext *eq_ctx)
+{
+ BMLoop *l_iter;
+ BMVert *v_tri[3];
+ BMEdge *e_tri[3];
+ int j;
+
+ /* Get vertices and edges of face */
+ BLI_assert(f_del->len == 3);
+ l_iter = BM_FACE_FIRST_LOOP(f_del);
+ v_tri[0] = l_iter->v; e_tri[0] = l_iter->e; l_iter = l_iter->next;
+ v_tri[1] = l_iter->v; e_tri[1] = l_iter->e; l_iter = l_iter->next;
+ v_tri[2] = l_iter->v; e_tri[2] = l_iter->e;
+
+ /* Check if any of the face's vertices are now unused, if so
+ * remove them from the PBVH */
+ for (j = 0; j < 3; j++) {
+ if (v_tri[j] != v && BM_vert_face_count(v_tri[j]) == 1) {
+ BLI_gset_insert(deleted_verts, v_tri[j]);
- pbvh_bmesh_vert_remove(bvh, v_tri[j], eq_ctx->cd_vert_node_offset, eq_ctx->cd_face_node_offset);
++ pbvh_bmesh_vert_remove(bvh, v_tri[j]);
+ }
+ else {
+ v_tri[j] = NULL;
+ }
+ }
+
+ /* Remove the face */
- pbvh_bmesh_face_remove(bvh, f_del, eq_ctx->cd_vert_node_offset, eq_ctx->cd_face_node_offset);
++ pbvh_bmesh_face_remove(bvh, f_del);
+ BM_face_kill(bvh->bm, f_del);
+
+ /* Check if any of the face's edges are now unused by any
+ * face, if so delete them */
+ for (j = 0; j < 3; j++) {
+ if (BM_edge_is_wire(e_tri[j]))
+ BM_edge_kill(bvh->bm, e_tri[j]);
+ }
+
+ /* Delete unused vertices */
+ for (j = 0; j < 3; j++) {
+ if (v_tri[j]) {
+ BM_log_vert_removed(bvh->bm_log, v_tri[j], eq_ctx->cd_vert_mask_offset);
+ BM_vert_kill(bvh->bm, v_tri[j]);
+ }
+ }
+}
+
+
+/**
+ * Same as #pbvh_bmesh_delete_vert_face but keeps verts
+ */
- static void pbvh_bmesh_delete_edge_face(PBVH *bvh, BMFace *f_del, EdgeQueueContext *eq_ctx)
++static void pbvh_bmesh_delete_edge_face(PBVH *bvh, BMFace *f_del)
+{
+ BMLoop *l_iter;
+ BMEdge *e_tri[3];
+ int j;
+
+ /* Get vertices and edges of face */
+ BLI_assert(f_del->len == 3);
+ l_iter = BM_FACE_FIRST_LOOP(f_del);
+ e_tri[0] = l_iter->e; l_iter = l_iter->next;
+ e_tri[1] = l_iter->e; l_iter = l_iter->next;
+ e_tri[2] = l_iter->e;
+
+ /* Remove the face */
- pbvh_bmesh_face_remove(bvh, f_del, eq_ctx->cd_vert_node_offset, eq_ctx->cd_face_node_offset);
++ pbvh_bmesh_face_remove(bvh, f_del);
+ BM_face_kill(bvh->bm, f_del);
+
+ /* Check if any of the face's edges are now unused by any
+ * face, if so delete them */
+ for (j = 0; j < 3; j++) {
+ if (BM_edge_is_wire(e_tri[j]))
+ BM_edge_kill(bvh->bm, e_tri[j]);
+ }
+}
+
+/* Create a priority queue containing vertex pairs not connected by an
+ * edge, but close enough as defined by PBVH.bm_min_edge_len.
+ *
+ * Only nodes marked for topology update are checked, and in those
+ * nodes only edges used by a face intersecting the (center, radius)
+ * sphere are checked.
+ *
+ * The highest priority (lowest number) is given to the pair of vertices with
+ * the shortest distance.
+ */
+static void close_vert_queue_create(EdgeQueueContext *eq_ctx,
+ PBVH *bvh, const float center[3],
+ float radius)
+{
+ int n;
+ Heap *distheap = BLI_heap_new();
+ BMVert *vprev, *vcur;
+ int num_close_verts;
+ /* list of verts for faster traversing */
+ ListBase vlist = {0};
+ LinkData *curnode;
+ LinkData *prevnode;
+
+ eq_ctx->q->heap = BLI_heap_new();
+ eq_ctx->q->center = center;
+ eq_ctx->q->radius_squared = radius * radius;
+ eq_ctx->q->limit_len_squared = bvh->bm_min_edge_len * bvh->bm_min_edge_len;
+
+ for (n = 0; n < bvh->totnode; n++) {
+ PBVHNode *node = &bvh->nodes[n];
+
+ /* Check leaf nodes marked for topology update */
+ if ((node->flag & PBVH_Leaf) &&
+ (node->flag & PBVH_UpdateTopology) &&
+ !(node->flag & PBVH_FullyHidden))
+ {
+ GSetIterator gs_iter;
+
+ /* Insert vertices in a distance heap */
+ GSET_ITER (gs_iter, node->bm_unique_verts) {
+ BMVert *v = BLI_gsetIterator_getKey(&gs_iter);
+ float dist_to_center_sq = len_squared_v3v3(eq_ctx->q->center, v->co);
+
+ if (dist_to_center_sq <= eq_ctx->q->radius_squared && check_mask(eq_ctx, v) && !BM_vert_is_boundary(v))
+ BLI_heap_insert(distheap, dist_to_center_sq, v);
+ }
+ }
+ }
+
+ num_close_verts = BLI_heap_size(distheap);
+
+ for (n = 0; n < num_close_verts; n++) {
+ LinkData *d = MEM_callocN(sizeof(*d), "Node");
+ d->data = BLI_heap_popmin(distheap);
+ BLI_addtail(&vlist, d);
+ }
+
+ BLI_heap_free(distheap, NULL);
+
+ curnode = vlist.first;
+
+ /* iterate the list and make pairs of vertices that are closer than the squared limit distance
+ * and not on part of the same face. The logic here is borrowed from our remove doubles operator */
+ while (curnode) {
+ vprev = (BMVert *)curnode->data;
+
+ prevnode = curnode;
+ curnode = curnode->next;
+
+ while (curnode) {
+ vcur = (BMVert *)curnode->data;
+
+ /* vertices belonging to the same face are not eligible for merging */
+ if (!BM_edge_exists(vprev, vcur)) {
+ float dist_sq = len_squared_v3v3(vcur->co, vprev->co);
+
+ if (dist_sq < eq_ctx->q->limit_len_squared)
+ {
+ BMVert **pair = BLI_mempool_alloc(eq_ctx->pool);
+ pair[0] = vprev;
+ pair[1] = vcur;
+
+#if 0
+ BLI_heap_insert(eq_ctx->q->heap,
+ min_ff(len_squared_v3v3(eq_ctx->q->center, vcur->co),
+ len_squared_v3v3(eq_ctx->q->center, vprev->co)),
+ pair);
+#else
+ BLI_heap_insert(eq_ctx->q->heap, dist_sq, pair);
+#endif
+ }
+
+ /* the two vertices in the pair are obliterated as part of the genus topology change, get a new
+ * vertex for processing. If the test does not pass then a new vertex must be used as
+ * previous because it is guaranteed that next vertices will not pass the test */
+ BLI_remlink(&vlist, curnode);
+ MEM_freeN(curnode);
+ curnode = prevnode->next;
+ break;
+ }
+
+ curnode = curnode->next;
+ }
+ }
+
+ BLI_freelistN(&vlist);
+}
+
+
/*************************** Topology update **************************/
static void bm_edges_from_tri(BMesh *bm, BMVert *v_tri[3], BMEdge *e_tri[3])
@@@ -1283,95 -1065,6 +1322,95 @@@ static bool pbvh_bmesh_collapse_short_e
return any_collapsed;
}
+#ifdef USE_HOLE_VOLUME_CLEAN
+
+static float len_to_tetrahedron_volume(float f)
+{
+ return (f * f * f) / 6.0f;
+}
+
+static bool pbvh_bmesh_collapse_small_tetrahedrons(
+ EdgeQueueContext *eq_ctx,
+ PBVH *bvh,
+ BLI_Buffer *deleted_faces)
+{
+ /* length as a tetrahedron volume, x1.5x to remove more... gives a bit nicer results */
+ float min_volume = len_to_tetrahedron_volume(bvh->bm_min_edge_len) * 1.5f;
+ GSet *deleted_verts;
+ bool any_collapsed = false;
+
+ deleted_verts = BLI_gset_ptr_new("deleted_verts");
+
+ while (!BLI_heap_is_empty(eq_ctx->q->heap)) {
+ BMLoop *l_a, *l_b;
+ BMVert **pair = BLI_heap_popmin(eq_ctx->q->heap);
+ BMVert *v1 = pair[0], *v2 = pair[1];
+ BMEdge *e;
+
+ /* values on either side of the edge */
+ BMLoop *l_adj;
+ BMVert *v1_alt;
+ BMVert *v2_alt;
+ BMEdge *e_alt;
+
+ BLI_mempool_free(eq_ctx->pool, pair);
+ pair = NULL;
+
+ /* Check the verts still exist */
+ if (BLI_gset_haskey(deleted_verts, v1) ||
+ BLI_gset_haskey(deleted_verts, v2))
+ {
+ continue;
+ }
+
+ /* Check that the edge still exists */
+ if (!(e = BM_edge_exists(v1, v2))) {
+ continue;
+ }
+
+ if (!BM_edge_loop_pair(e, &l_a, &l_b)) {
+ continue;
+ }
+
+ v1_alt = l_a->prev->v;
+ v2_alt = l_b->prev->v;
+
+ if (bm_edge_calc_volume_weighted(e) > min_volume) {
+ continue;
+ }
+
+ /* Check that the edge's vertices are still in the PBVH. It's
+ * possible that an edge collapse has deleted adjacent faces
+ * and the node has been split, thus leaving wire edges and
+ * associated vertices. */
+ if ((BM_ELEM_CD_GET_INT(e->v1, eq_ctx->cd_vert_node_offset) == DYNTOPO_NODE_NONE) ||
+ (BM_ELEM_CD_GET_INT(e->v2, eq_ctx->cd_vert_node_offset) == DYNTOPO_NODE_NONE))
+ {
+ continue;
+ }
+
+ any_collapsed = true;
+
+ /* Remove all faces adjacent to the edge, we _KNOW_ there are 2! */
+ while ((l_adj = e->l)) {
+ BMFace *f_adj = l_adj->f;
- pbvh_bmesh_face_remove(bvh, f_adj, eq_ctx->cd_vert_node_offset, eq_ctx->cd_face_node_offset);
++ pbvh_bmesh_face_remove(bvh, f_adj);
+ BM_face_kill(bvh->bm, f_adj);
+ }
+
+ e_alt = BM_edge_create(bvh->bm, v1_alt, v2_alt, NULL, BM_CREATE_NO_DOUBLE);
+
+ pbvh_bmesh_collapse_edge(bvh, e_alt, v1_alt, v2_alt,
+ deleted_verts,
+ deleted_faces, eq_ctx);
+ }
+
+ BLI_gset_free(deleted_verts, NULL);
+
+ return any_collapsed;
+}
+#endif /* USE_HOLE_VOLUME_CLEAN */
+
/************************* Called from pbvh.c *************************/
bool pbvh_bmesh_node_raycast(PBVHNode *node, const float ray_start[3],
@@@ -1414,462 -1107,6 +1453,462 @@@
retu
@@ Diff output truncated at 10240 characters. @@
More information about the Bf-blender-cvs
mailing list