Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCampbell Barton <ideasman42@gmail.com>2015-03-23 09:43:14 +0300
committerCampbell Barton <ideasman42@gmail.com>2015-03-23 12:03:14 +0300
commitc451dba550788c745e3c6c96700fc2620a31eb47 (patch)
tree8b6dec51204b3d507001bf72a99772bed55c8212 /source/blender/editors/transform
parented7e593a4b129e1367a7f5aa2d0e9036e5363bea (diff)
Mitigate T44035: Proportional editing lag
Calculating connected data can be slow, it still lags with heavy meshes but perform some optimizations (nearly twice as fast)
Diffstat (limited to 'source/blender/editors/transform')
-rw-r--r--source/blender/editors/transform/transform_conversions.c86
1 files changed, 55 insertions, 31 deletions
diff --git a/source/blender/editors/transform/transform_conversions.c b/source/blender/editors/transform/transform_conversions.c
index b50f56aae3e..2c189b715c4 100644
--- a/source/blender/editors/transform/transform_conversions.c
+++ b/source/blender/editors/transform/transform_conversions.c
@@ -1972,17 +1972,19 @@ static void editmesh_set_connectivity_distance(BMesh *bm, float mtx[3][3], float
int i;
BM_ITER_MESH_INDEX (v, &viter, bm, BM_VERTS_OF_MESH, i) {
+ float dist;
BM_elem_index_set(v, i); /* set_inline */
BM_elem_flag_disable(v, BM_ELEM_TAG);
if (BM_elem_flag_test(v, BM_ELEM_SELECT) == 0 || BM_elem_flag_test(v, BM_ELEM_HIDDEN)) {
- dists[i] = FLT_MAX;
+ dist = FLT_MAX;
}
else {
BLI_LINKSTACK_PUSH(queue, v);
-
- dists[i] = 0.0f;
+ dist = 0.0f;
}
+
+ dists[i] = dists_prev[i] = dist;
}
bm->elem_index_dirty &= ~BM_VERT;
}
@@ -1991,55 +1993,77 @@ static void editmesh_set_connectivity_distance(BMesh *bm, float mtx[3][3], float
BMVert *v;
LinkNode *lnk;
+ /* this is correct but slow to do each iteration,
+ * instead sync the dist's while clearing BM_ELEM_TAG (below) */
+#if 0
memcpy(dists_prev, dists, sizeof(float) * bm->totvert);
+#endif
while ((v = BLI_LINKSTACK_POP(queue))) {
- /* quick checks */
- bool has_edges = (v->e != NULL);
- bool has_faces = false;
+ BLI_assert(dists[BM_elem_index_get(v)] != FLT_MAX);
/* connected edge-verts */
- if (has_edges) {
- BMIter iter;
- BMEdge *e;
+ if (v->e != NULL) {
+ BMEdge *e_iter, *e_first;
+
+ e_iter = e_first = v->e;
- BM_ITER_ELEM (e, &iter, v, BM_EDGES_OF_VERT) {
- has_faces |= (BM_edge_is_wire(e) == false);
+ /* would normally use BM_EDGES_OF_VERT, but this runs so often,
+ * its faster to iterate on the data directly */
+ do {
- if (BM_elem_flag_test(e, BM_ELEM_HIDDEN) == 0) {
- BMVert *v_other = BM_edge_other_vert(e, v);
+ if (BM_elem_flag_test(e_iter, BM_ELEM_HIDDEN) == 0) {
+
+ /* edge distance */
+ BMVert *v_other = BM_edge_other_vert(e_iter, v);
if (bmesh_test_dist_add(v, v_other, dists, dists_prev, mtx)) {
if (BM_elem_flag_test(v_other, BM_ELEM_TAG) == 0) {
BM_elem_flag_enable(v_other, BM_ELEM_TAG);
BLI_LINKSTACK_PUSH(queue_next, v_other);
}
}
- }
- }
- }
-
- /* imaginary edge diagonally across quad */
- if (has_faces) {
- BMIter iter;
- BMLoop *l;
- BM_ITER_ELEM (l, &iter, v, BM_LOOPS_OF_VERT) {
- if ((BM_elem_flag_test(l->f, BM_ELEM_HIDDEN) == 0) && (l->f->len == 4)) {
- BMVert *v_other = l->next->next->v;
- if (bmesh_test_dist_add(v, v_other, dists, dists_prev, mtx)) {
- if (BM_elem_flag_test(v_other, BM_ELEM_TAG) == 0) {
- BM_elem_flag_enable(v_other, BM_ELEM_TAG);
- BLI_LINKSTACK_PUSH(queue_next, v_other);
- }
+ /* face distance */
+ if (e_iter->l) {
+ BMLoop *l_iter_radial, *l_first_radial;
+ /**
+ * imaginary edge diagonally across quad,
+ * \note, this takes advantage of the rules of winding that we
+ * know 2 or more of a verts edges wont reference the same face twice.
+ * Also, if the edge is hidden, the face will be hidden too.
+ */
+ l_iter_radial = l_first_radial = e_iter->l;
+
+ do {
+ if ((l_iter_radial->v == v) &&
+ (l_iter_radial->f->len == 4) &&
+ (BM_elem_flag_test(l_iter_radial->f, BM_ELEM_HIDDEN) == 0))
+ {
+ BMVert *v_other = l_iter_radial->next->next->v;
+ if (bmesh_test_dist_add(v, v_other, dists, dists_prev, mtx)) {
+ if (BM_elem_flag_test(v_other, BM_ELEM_TAG) == 0) {
+ BM_elem_flag_enable(v_other, BM_ELEM_TAG);
+ BLI_LINKSTACK_PUSH(queue_next, v_other);
+ }
+ }
+ }
+ } while ((l_iter_radial = l_iter_radial->radial_next) != l_first_radial);
}
}
- }
+ } while ((e_iter = BM_DISK_EDGE_NEXT(e_iter, v)) != e_first);
}
}
+
/* clear for the next loop */
for (lnk = queue_next; lnk; lnk = lnk->next) {
- BM_elem_flag_disable((BMVert *)lnk->link, BM_ELEM_TAG);
+ BMVert *v = lnk->link;
+ const int i = BM_elem_index_get(v);
+
+ BM_elem_flag_disable(v, BM_ELEM_TAG);
+
+ /* keep in sync, avoid having to do full memcpy each iteration */
+ dists_prev[i] = dists[i];
}
BLI_LINKSTACK_SWAP(queue, queue_next);