diff options
Diffstat (limited to 'source/blender/blenkernel/intern/pbvh_bmesh.c')
-rw-r--r-- | source/blender/blenkernel/intern/pbvh_bmesh.c | 74 |
1 files changed, 57 insertions, 17 deletions
diff --git a/source/blender/blenkernel/intern/pbvh_bmesh.c b/source/blender/blenkernel/intern/pbvh_bmesh.c index 4bfda8ebf28..187891e7210 100644 --- a/source/blender/blenkernel/intern/pbvh_bmesh.c +++ b/source/blender/blenkernel/intern/pbvh_bmesh.c @@ -718,20 +718,24 @@ static void pbvh_bmesh_node_drop_orig(PBVHNode *node) /****************************** EdgeQueue *****************************/ -typedef struct { +struct EdgeQueue; + +typedef struct EdgeQueue { Heap *heap; const float *center; + float center_proj[3]; /* for when we use projected coords. */ float radius_squared; float limit_len_squared; #ifdef USE_EDGEQUEUE_EVEN_SUBDIV float limit_len; #endif -#ifdef USE_EDGEQUEUE_FRONTFACE + bool (*edge_queue_tri_in_range)(const struct EdgeQueue *q, BMFace *f); + const float *view_normal; +#ifdef USE_EDGEQUEUE_FRONTFACE unsigned int use_view_normal : 1; #endif - } EdgeQueue; typedef struct { @@ -785,7 +789,6 @@ static bool edge_queue_tri_in_sphere(const EdgeQueue *q, BMFace *f) float c[3]; /* Get closest point in triangle to sphere center */ - // BM_iter_as_array(NULL, BM_VERTS_OF_FACE, f, (void **)v_tri, 3); BM_face_as_array_vert_tri(f, v_tri); closest_on_tri_to_point_v3(c, q->center, v_tri[0]->co, v_tri[1]->co, v_tri[2]->co); @@ -794,6 +797,25 @@ static bool edge_queue_tri_in_sphere(const EdgeQueue *q, BMFace *f) return len_squared_v3v3(q->center, c) <= q->radius_squared; } +static bool edge_queue_tri_in_circle(const EdgeQueue *q, BMFace *f) +{ + BMVert *v_tri[3]; + float c[3]; + float tri_proj[3][3]; + + /* Get closest point in triangle to sphere center */ + BM_face_as_array_vert_tri(f, v_tri); + + project_plane_normalized_v3_v3v3(tri_proj[0], v_tri[0]->co, q->view_normal); + project_plane_normalized_v3_v3v3(tri_proj[1], v_tri[1]->co, q->view_normal); + project_plane_normalized_v3_v3v3(tri_proj[2], v_tri[2]->co, q->view_normal); + + closest_on_tri_to_point_v3(c, q->center_proj, tri_proj[0], tri_proj[1], tri_proj[2]); + + /* Check if triangle intersects the sphere */ + return len_squared_v3v3(q->center_proj, c) <= q->radius_squared; +} + /* Return true if the vertex mask is less than 1.0, false otherwise */ static bool check_mask(EdgeQueueContext *eq_ctx, BMVert *v) { @@ -929,7 +951,7 @@ static void long_edge_queue_face_add( } #endif - if (edge_queue_tri_in_sphere(eq_ctx->q, f)) { + if (eq_ctx->q->edge_queue_tri_in_range(eq_ctx->q, f)) { /* Check each edge of the face */ BMLoop *l_first = BM_FACE_FIRST_LOOP(f); BMLoop *l_iter = l_first; @@ -960,7 +982,7 @@ static void short_edge_queue_face_add( } #endif - if (edge_queue_tri_in_sphere(eq_ctx->q, f)) { + if (eq_ctx->q->edge_queue_tri_in_range(eq_ctx->q, f)) { BMLoop *l_iter; BMLoop *l_first; @@ -984,7 +1006,7 @@ static void short_edge_queue_face_add( static void long_edge_queue_create( EdgeQueueContext *eq_ctx, PBVH *bvh, const float center[3], const float view_normal[3], - float radius) + float radius, const bool use_frontface, const bool use_projected) { eq_ctx->q->heap = BLI_heap_new(); eq_ctx->q->center = center; @@ -994,13 +1016,22 @@ static void long_edge_queue_create( eq_ctx->q->limit_len = bvh->bm_max_edge_len; #endif -#ifdef USE_EDGEQUEUE_FRONTFACE eq_ctx->q->view_normal = view_normal; - eq_ctx->q->use_view_normal = (view_normal != NULL); + +#ifdef USE_EDGEQUEUE_FRONTFACE + eq_ctx->q->use_view_normal = use_frontface; #else - UNUSED_VARS(view_normal); + UNUSED_VARS(use_frontface); #endif + if (use_projected) { + eq_ctx->q->edge_queue_tri_in_range = edge_queue_tri_in_circle; + project_plane_normalized_v3_v3v3(eq_ctx->q->center_proj, center, view_normal); + } + else { + eq_ctx->q->edge_queue_tri_in_range = edge_queue_tri_in_sphere; + } + #ifdef USE_EDGEQUEUE_TAG_VERIFY pbvh_bmesh_edge_tag_verify(bvh); #endif @@ -1037,7 +1068,7 @@ static void long_edge_queue_create( static void short_edge_queue_create( EdgeQueueContext *eq_ctx, PBVH *bvh, const float center[3], const float view_normal[3], - float radius) + float radius, const bool use_frontface, const bool use_projected) { eq_ctx->q->heap = BLI_heap_new(); eq_ctx->q->center = center; @@ -1047,13 +1078,22 @@ static void short_edge_queue_create( eq_ctx->q->limit_len = bvh->bm_min_edge_len; #endif -#ifdef USE_EDGEQUEUE_FRONTFACE eq_ctx->q->view_normal = view_normal; - eq_ctx->q->use_view_normal = (view_normal != NULL); + +#ifdef USE_EDGEQUEUE_FRONTFACE + eq_ctx->q->use_view_normal = use_frontface; #else - UNUSED_VARS(view_normal); + UNUSED_VARS(use_frontface); #endif + if (use_projected) { + eq_ctx->q->edge_queue_tri_in_range = edge_queue_tri_in_circle; + project_plane_normalized_v3_v3v3(eq_ctx->q->center_proj, center, view_normal); + } + else { + eq_ctx->q->edge_queue_tri_in_range = edge_queue_tri_in_sphere; + } + for (int n = 0; n < bvh->totnode; n++) { PBVHNode *node = &bvh->nodes[n]; @@ -1895,7 +1935,7 @@ void BKE_pbvh_build_bmesh( bool BKE_pbvh_bmesh_update_topology( PBVH *bvh, PBVHTopologyUpdateMode mode, const float center[3], const float view_normal[3], - float radius) + float radius, const bool use_frontface, const bool use_projected) { /* 2 is enough for edge faces - manifold edge */ BLI_buffer_declare_static(BMLoop *, edge_loops, BLI_BUFFER_NOP, 2); @@ -1918,7 +1958,7 @@ bool BKE_pbvh_bmesh_update_topology( cd_vert_mask_offset, cd_vert_node_offset, cd_face_node_offset, }; - short_edge_queue_create(&eq_ctx, bvh, center, view_normal, radius); + short_edge_queue_create(&eq_ctx, bvh, center, view_normal, radius, use_frontface, use_projected); modified |= pbvh_bmesh_collapse_short_edges( &eq_ctx, bvh, &deleted_faces); BLI_heap_free(q.heap, NULL); @@ -1933,7 +1973,7 @@ bool BKE_pbvh_bmesh_update_topology( cd_vert_mask_offset, cd_vert_node_offset, cd_face_node_offset, }; - long_edge_queue_create(&eq_ctx, bvh, center, view_normal, radius); + long_edge_queue_create(&eq_ctx, bvh, center, view_normal, radius, use_frontface, use_projected); modified |= pbvh_bmesh_subdivide_long_edges( &eq_ctx, bvh, &edge_loops); BLI_heap_free(q.heap, NULL); |