optimize bmesh operations that use triangle BMFace's (dyn-topo and mesh conversion).

This commit is contained in:
Campbell Barton
2013-01-16 21:09:54 +00:00
parent 7f513023d4
commit 5ddc7d64a8
8 changed files with 141 additions and 58 deletions

View File

@@ -53,7 +53,8 @@ static void pbvh_bmesh_node_finalize(PBVH *bvh, int node_index)
GHASH_ITER (gh_iter, n->bm_faces) {
BMFace *f = BLI_ghashIterator_getKey(&gh_iter);
BMIter bm_iter;
BMLoop *l_iter;
BMLoop *l_first;
BMVert *v;
void *node_val = SET_INT_IN_POINTER(node_index);
@@ -61,7 +62,9 @@ static void pbvh_bmesh_node_finalize(PBVH *bvh, int node_index)
BLI_ghash_insert(bvh->bm_face_to_node, f, node_val);
/* Update vertices */
BM_ITER_ELEM (v, &bm_iter, f, BM_VERTS_OF_FACE) {
l_iter = l_first = BM_FACE_FIRST_LOOP(f);
do {
v = l_iter->v;
if (!BLI_ghash_haskey(n->bm_unique_verts, v)) {
if (BLI_ghash_haskey(bvh->bm_vert_to_node, v)) {
if (!BLI_ghash_haskey(n->bm_other_verts, v))
@@ -74,7 +77,7 @@ static void pbvh_bmesh_node_finalize(PBVH *bvh, int node_index)
}
/* Update node bounding box */
BB_expand(&n->vb, v->co);
}
} while ((l_iter = l_iter->next) != l_first);
}
BLI_assert(n->vb.bmin[0] <= n->vb.bmax[0] &&
@@ -233,15 +236,16 @@ static int pbvh_bmesh_node_limit_ensure(PBVH *bvh, int node_index)
prim_bbc = BLI_ghash_ptr_new("prim_bbc");
GHASH_ITER (gh_iter, bvh->nodes[node_index].bm_faces) {
BMIter bm_iter;
BMVert *v;
BMFace *f = BLI_ghashIterator_getKey(&gh_iter);
BBC *bbc = MEM_callocN(sizeof(BBC), "BBC");
BMLoop *l_iter;
BMLoop *l_first;
BB_reset((BB *)bbc);
BM_ITER_ELEM (v, &bm_iter, f, BM_VERTS_OF_FACE) {
BB_expand((BB *)bbc, v->co);
}
l_iter = l_first = BM_FACE_FIRST_LOOP(f);
do {
BB_expand((BB *)bbc, l_iter->v->co);
} while ((l_iter = l_iter->next) != l_first);
BBC_update_centroid(bbc);
BLI_ghash_insert(prim_bbc, f, bbc);
@@ -394,14 +398,18 @@ static void pbvh_bmesh_vert_remove(PBVH *bvh, BMVert *v)
static void pbvh_bmesh_face_remove(PBVH *bvh, BMFace *f)
{
PBVHNode *f_node;
BMIter bm_iter;
BMVert *v;
BMLoop *l_iter;
BMLoop *l_first;
f_node = pbvh_bmesh_node_lookup(bvh, bvh->bm_face_to_node, f);
/* Check if any of this face's vertices need to be removed
* from the node */
BM_ITER_ELEM (v, &bm_iter, f, BM_VERTS_OF_FACE) {
l_iter = l_first = BM_FACE_FIRST_LOOP(f);
do {
v = l_iter->v;
if (pbvh_bmesh_node_vert_use_count(bvh, f_node, v) == 1) {
if (BLI_ghash_lookup(f_node->bm_unique_verts, v)) {
/* Find a different node that uses 'v' */
@@ -419,7 +427,7 @@ static void pbvh_bmesh_face_remove(PBVH *bvh, BMFace *f)
BLI_ghash_remove(f_node->bm_other_verts, v, NULL, NULL);
}
}
}
} while ((l_iter = l_iter->next) != l_first);
/* Remove face from node and top level */
BLI_ghash_remove(f_node->bm_faces, f, NULL, NULL);
@@ -436,18 +444,21 @@ static BMVert *bm_triangle_other_vert_find(BMFace *triangle, const BMVert *v1,
BLI_assert(v1 != v2);
if (triangle->len == 3) {
BMIter iter;
BMLoop *l_iter;
BMLoop *l_first;
BMVert *v, *other = NULL;
int found_v1 = FALSE, found_v2 = FALSE;
bool found_v1 = false, found_v2 = false;
BM_ITER_ELEM (v, &iter, triangle, BM_VERTS_OF_FACE) {
l_iter = l_first = BM_FACE_FIRST_LOOP(triangle);
do {
v = l_iter->v;
if (v == v1)
found_v1 = TRUE;
found_v1 = true;
else if (v == v2)
found_v2 = TRUE;
found_v2 = true;
else
other = v;
}
} while ((l_iter = l_iter->next) != l_first);
if (found_v1 && found_v2)
return other;
@@ -508,7 +519,9 @@ static int 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, 3);
// BM_iter_as_array(NULL, BM_VERTS_OF_FACE, f, (void **)v, 3);
BM_face_as_array_vert_tri(f, v);
closest_on_tri_to_point_v3(c, q->center, v[0]->co, v[1]->co, v[2]->co);
/* Check if triangle intersects the sphere */
@@ -810,7 +823,8 @@ static void pbvh_bmesh_collapse_edge(PBVH *bvh, BMEdge *e, BMVert *v1,
int ni;
/* Get vertices, replace use of v2 with v1 */
BM_iter_as_array(NULL, BM_VERTS_OF_FACE, f, (void **)v, 3);
// BM_iter_as_array(NULL, BM_VERTS_OF_FACE, f, (void **)v, 3);
BM_face_as_array_vert_tri(f, v);
for (i = 0; i < 3; i++) {
if (v[i] == v2)
v[i] = v1;
@@ -845,7 +859,8 @@ static void pbvh_bmesh_collapse_edge(PBVH *bvh, BMEdge *e, BMVert *v1,
BMVert *v[3];
int j;
BM_iter_as_array(NULL, BM_VERTS_OF_FACE, f_del, (void **)v, 3);
// BM_iter_as_array(NULL, BM_VERTS_OF_FACE, f_del, (void **)v, 3);
BM_face_as_array_vert_tri(f_del, v);
/* Check if any of the face's vertices are now unused, if so
remove them from the PBVH */
@@ -965,12 +980,13 @@ int pbvh_bmesh_node_raycast(PBVHNode *node, const float ray_start[3],
if (f->len == 3) {
BMVert *v[3];
BM_iter_as_array(NULL, BM_VERTS_OF_FACE, f, (void **)v, 3);
// BM_iter_as_array(NULL, BM_VERTS_OF_FACE, f, (void **)v, 3);
BM_face_as_array_vert_tri(f, v);
hit |= ray_face_intersection(ray_start, ray_normal,
v[0]->co,
v[1]->co,
v[2]->co,
NULL, dist);
v[0]->co,
v[1]->co,
v[2]->co,
NULL, dist);
}
}
}
@@ -1083,6 +1099,17 @@ int BKE_pbvh_bmesh_update_topology(PBVH *bvh, PBVHTopologyUpdateMode mode,
return modified;
}
BLI_INLINE void bm_face_as_array_index_tri(BMFace *f, int r_index[3])
{
BMLoop *l = BM_FACE_FIRST_LOOP(f);
BLI_assert(f->len == 3);
r_index[0] = BM_elem_index_get(l->v); l = l->next;
r_index[1] = BM_elem_index_get(l->v); l = l->next;
r_index[2] = BM_elem_index_get(l->v);
}
/* In order to perform operations on the original node coordinates
* (such as raycast), store the node's triangles and vertices.*/
void BKE_pbvh_bmesh_node_save_orig(PBVHNode *node)
@@ -1120,15 +1147,19 @@ void BKE_pbvh_bmesh_node_save_orig(PBVHNode *node)
/* Copy the triangles */
i = 0;
GHASH_ITER (gh_iter, node->bm_faces) {
BMIter bm_iter;
BMFace *f = BLI_ghashIterator_getKey(&gh_iter);
#if 0
BMIter bm_iter;
BMVert *v;
int j = 0;
BM_ITER_ELEM (v, &bm_iter, f, BM_VERTS_OF_FACE) {
node->bm_ortri[i][j] = BM_elem_index_get(v);
j++;
}
#else
bm_face_as_array_index_tri(f, node->bm_ortri[i]);
#endif
i++;
}
node->bm_tot_ortri = i;

View File

@@ -215,7 +215,8 @@ static BMLogFace *bm_log_face_alloc(BMLog *log, BMFace *f)
BLI_assert(f->len == 3);
BM_iter_as_array(NULL, BM_VERTS_OF_FACE, f, (void **)v, 3);
// BM_iter_as_array(NULL, BM_VERTS_OF_FACE, f, (void **)v, 3);
BM_face_as_array_vert_tri(f, v);
lf->v_ids[0] = bm_log_vert_id_get(log, v[0]);
lf->v_ids[1] = bm_log_vert_id_get(log, v[1]);

View File

@@ -710,12 +710,13 @@ void BM_editselection_plane(BMEditSelection *ese, float r_plane[3])
cross_v3_v3v3(r_plane, efa->no, vec);
}
else {
BMVert *verts[4] = {NULL};
BM_iter_as_array(NULL, BM_VERTS_OF_FACE, efa, (void **)verts, 4);
if (efa->len == 4) {
BMVert *verts[4] = {NULL};
float vecA[3], vecB[3];
// BM_iter_as_array(NULL, BM_VERTS_OF_FACE, efa, (void **)verts, 4);
BM_face_as_array_vert_quad(efa, verts);
sub_v3_v3v3(vecA, verts[3]->co, verts[2]->co);
sub_v3_v3v3(vecB, verts[0]->co, verts[1]->co);
add_v3_v3v3(r_plane, vecA, vecB);

View File

@@ -174,7 +174,6 @@ void BM_mesh_bm_from_me(BMesh *bm, Mesh *me, bool set_key, int act_key_nr)
BMVert *v, **vt = NULL, **verts = NULL;
BMEdge *e, **fedges = NULL, **et = NULL;
BMFace *f;
BMLoop *l;
BLI_array_declare(fedges);
float (*keyco)[3] = NULL;
int *keyi;
@@ -343,7 +342,8 @@ void BM_mesh_bm_from_me(BMesh *bm, Mesh *me, bool set_key, int act_key_nr)
mpoly = me->mpoly;
for (i = 0; i < me->totpoly; i++, mpoly++) {
BMIter iter;
BMLoop *l_iter;
BMLoop *l_first;
BLI_array_empty(fedges);
BLI_array_empty(verts);
@@ -401,11 +401,12 @@ void BM_mesh_bm_from_me(BMesh *bm, Mesh *me, bool set_key, int act_key_nr)
f->mat_nr = mpoly->mat_nr;
if (i == me->act_face) bm->act_face = f;
j = 0;
BM_ITER_ELEM_INDEX (l, &iter, f, BM_LOOPS_OF_FACE, j) {
j = mpoly->loopstart;
l_iter = l_first = BM_FACE_FIRST_LOOP(f);
do {
/* Save index of correspsonding MLoop */
CustomData_to_bmesh_block(&me->ldata, &bm->ldata, mpoly->loopstart + j, &l->head.data, true);
}
CustomData_to_bmesh_block(&me->ldata, &bm->ldata, j++, &l_iter->head.data, true);
} while ((l_iter = l_iter->next) != l_first);
/* Copy Custom Data */
CustomData_to_bmesh_block(&me->pdata, &bm->pdata, i, &f->head.data, true);

View File

@@ -1080,3 +1080,37 @@ void BM_face_legal_splits(BMesh *bm, BMFace *f, BMLoop *(*loops)[2], int len)
}
}
}
/**
* Small utility functions for fast access
*
* faster alternative to:
* BM_iter_as_array(bm, BM_VERTS_OF_FACE, f, (void**)v, 3);
*/
void BM_face_as_array_vert_tri(BMFace *f, BMVert *r_verts[3])
{
BMLoop *l = BM_FACE_FIRST_LOOP(f);
BLI_assert(f->len == 3);
r_verts[0] = l->v; l = l->next;
r_verts[1] = l->v; l = l->next;
r_verts[2] = l->v;
}
/**
* faster alternative to:
* BM_iter_as_array(bm, BM_VERTS_OF_FACE, f, (void**)v, 4);
*/
void BM_face_as_array_vert_quad(BMFace *f, BMVert *r_verts[4])
{
BMLoop *l = BM_FACE_FIRST_LOOP(f);
BLI_assert(f->len == 4);
r_verts[0] = l->v; l = l->next;
r_verts[1] = l->v; l = l->next;
r_verts[2] = l->v; l = l->next;
r_verts[3] = l->v;
}

View File

@@ -50,4 +50,7 @@ void BM_face_triangulate(BMesh *bm, BMFace *f, float (*projectverts)[3],
void BM_face_legal_splits(BMesh *bm, BMFace *f, BMLoop *(*loops)[2], int len);
void BM_face_as_array_vert_tri(BMFace *f, BMVert *r_verts[3]);
void BM_face_as_array_vert_quad(BMFace *f, BMVert *r_verts[4]);
#endif /* __BMESH_POLYGON_H__ */

View File

@@ -1925,15 +1925,17 @@ static int gpu_bmesh_vert_visible_count(GHash *bm_unique_verts,
/* Return TRUE if all vertices in the face are visible, FALSE otherwise */
static int gpu_bmesh_face_visible(BMFace *f)
{
BMIter bm_iter;
BMVert *v;
BMLoop *l_iter;
BMLoop *l_first;
BM_ITER_ELEM (v, &bm_iter, f, BM_VERTS_OF_FACE) {
if (BM_elem_flag_test(v, BM_ELEM_HIDDEN))
return FALSE;
}
l_iter = l_first = BM_FACE_FIRST_LOOP(f);
do {
if (BM_elem_flag_test(l_iter->v, BM_ELEM_HIDDEN)) {
return false;
}
} while ((l_iter = l_iter->next) != l_first);
return TRUE;
return true;
}
/* Return the total number of visible faces */
@@ -2017,19 +2019,20 @@ void GPU_update_bmesh_buffers(GPU_Buffers *buffers,
float fmask = 0;
int i;
BM_iter_as_array(bm, BM_VERTS_OF_FACE, f, (void**)v, 3);
// BM_iter_as_array(bm, BM_VERTS_OF_FACE, f, (void**)v, 3);
BM_face_as_array_vert_tri(f, v);
/* Average mask value */
for (i = 0; i < 3; i++) {
fmask += *((float*)CustomData_bmesh_get(&bm->vdata,
v[i]->head.data,
CD_PAINT_MASK));
v[i]->head.data,
CD_PAINT_MASK));
}
fmask /= 3.0f;
for (i = 0; i < 3; i++) {
gpu_bmesh_vert_to_buffer_copy(v[i], bm, vert_data,
&v_index, f->no, &fmask);
&v_index, f->no, &fmask);
}
}
}
@@ -2063,12 +2066,15 @@ void GPU_update_bmesh_buffers(GPU_Buffers *buffers,
GHashIterator gh_iter;
GHASH_ITER (gh_iter, bm_faces) {
BMIter bm_iter;
BMFace *f = BLI_ghashIterator_getKey(&gh_iter);
BMVert *v;
if (gpu_bmesh_face_visible(f)) {
BM_ITER_ELEM (v, &bm_iter, f, BM_VERTS_OF_FACE) {
BMLoop *l_iter;
BMLoop *l_first;
l_iter = l_first = BM_FACE_FIRST_LOOP(f);
do {
BMVert *v = l_iter->v;
if (use_short) {
unsigned short *elem = tri_data;
(*elem) = BM_elem_index_get(v);
@@ -2081,7 +2087,7 @@ void GPU_update_bmesh_buffers(GPU_Buffers *buffers,
elem++;
tri_data = elem;
}
}
} while ((l_iter = l_iter->next) != l_first);
}
}

View File

@@ -1278,7 +1278,8 @@ static void skin_fix_hole_no_good_verts(BMesh *bm, Frame *frame, BMFace *split_f
return;
/* Get split face's verts */
BM_iter_as_array(bm, BM_VERTS_OF_FACE, split_face, (void **)verts, 4);
// BM_iter_as_array(bm, BM_VERTS_OF_FACE, split_face, (void **)verts, 4);
BM_face_as_array_vert_quad(split_face, verts);
skin_choose_quad_bridge_order(verts, frame->verts, best_order);
/* Delete split face and merge */
@@ -1314,16 +1315,21 @@ static void skin_hole_detach_partially_attached_frame(BMesh *bm, Frame *frame)
}
static void quad_from_tris(BMesh *bm, BMEdge *e, BMFace *adj[2], BMVert *ndx[4])
static void quad_from_tris(BMEdge *e, BMFace *adj[2], BMVert *ndx[4])
{
BMVert *tri[2][3];
BMVert *opp = NULL;
int i, j;
BLI_assert(adj[0]->len == 3 && adj[1]->len == 3);
#if 0
BM_iter_as_array(bm, BM_VERTS_OF_FACE, adj[0], (void **)tri[0], 3);
BM_iter_as_array(bm, BM_VERTS_OF_FACE, adj[1], (void **)tri[1], 3);
#else
BM_face_as_array_vert_tri(adj[0], tri[0]);
BM_face_as_array_vert_tri(adj[1], tri[1]);
#endif
/* Find what the second tri has that the first doesn't */
for (i = 0; i < 3; i++) {
@@ -1354,7 +1360,7 @@ static void add_quad_from_tris(SkinOutput *so, BMEdge *e, BMFace *adj[2])
{
BMVert *quad[4];
quad_from_tris(so->bm, e, adj, quad);
quad_from_tris(e, adj, quad);
add_poly(so, quad[0], quad[1], quad[2], quad[3]);
}
@@ -1381,7 +1387,7 @@ static void hull_merge_triangles(SkinOutput *so, const SkinModifierData *smd)
/* Construct quad using the two triangles adjacent to
* the edge */
quad_from_tris(so->bm, e, adj, quad);
quad_from_tris(e, adj, quad);
/* Calculate a score for the quad, higher score for
* triangles being closer to coplanar */