[Bf-blender-cvs] SVN commit: /data/svn/bf-blender [45779] trunk/blender/source/blender: BMESH_TODO: xsort of vertices working again.

Bastien Montagne montagne29 at wanadoo.fr
Thu Apr 19 14:31:40 CEST 2012


Revision: 45779
          http://projects.blender.org/scm/viewvc.php?view=rev&root=bf-blender&revision=45779
Author:   mont29
Date:     2012-04-19 12:31:39 +0000 (Thu, 19 Apr 2012)
Log Message:
-----------
BMESH_TODO: xsort of vertices working again.

This commits adds a new function which can remap vertices/edges/faces of a BMesh in a new given order:
void BM_mesh_remap(BMesh *bm, int *vert_idx, int *edge_idx, int *face_idx)

Modified Paths:
--------------
    trunk/blender/source/blender/bmesh/intern/bmesh_mesh.c
    trunk/blender/source/blender/bmesh/intern/bmesh_mesh.h
    trunk/blender/source/blender/editors/mesh/editmesh_tools.c

Modified: trunk/blender/source/blender/bmesh/intern/bmesh_mesh.c
===================================================================
--- trunk/blender/source/blender/bmesh/intern/bmesh_mesh.c	2012-04-19 12:21:44 UTC (rev 45778)
+++ trunk/blender/source/blender/bmesh/intern/bmesh_mesh.c	2012-04-19 12:31:39 UTC (rev 45779)
@@ -584,6 +584,176 @@
 
 }
 
+/**
+ * Remaps the vertices, edges and/or faces of the bmesh as indicated by vert/edge/face_idx arrays
+ * (xxx_idx[org_index] = new_index).
+ *
+ * A NULL array means no changes.
+ *
+ * Note: - Does not mess with indices, just sets elem_index_dirty flag.
+ *       - For verts/edges/faces only (as loops must remain "ordered" and "aligned"
+ *         on a per-face basis...).
+ *
+ * WARNING: Be careful if you keep pointers to affected BM elements, or arrays, when using this func!
+ */
+void BM_mesh_remap(BMesh *bm, int *vert_idx, int *edge_idx, int *face_idx)
+{
+	/* Mapping old to new pointers. */
+	GHash *vptr_map = NULL, *eptr_map = NULL, *fptr_map = NULL;
+	BMIter iter, iterl;
+	BMVert *ve;
+	BMEdge *ed;
+	BMFace *fa;
+	BMLoop *lo;
+
+	if (!(vert_idx || edge_idx || face_idx))
+		return;
+
+	/* Remap vertices */
+	if (vert_idx) {
+		BMVert **verts_pool, *verts_copy, **vep;
+		int i, totvert = bm->totvert;
+		int *new_idx = NULL;
+
+		/* Init the old-to-new vert pointers mapping */
+		vptr_map = BLI_ghash_new(BLI_ghashutil_ptrhash, BLI_ghashutil_ptrcmp, "BM_mesh_remap vert pointers mapping");
+
+		/* Make a copy of all vertices. */
+		verts_pool = MEM_callocN(sizeof(BMVert*) * totvert, "BM_mesh_remap verts pool");
+		BM_iter_as_array(bm, BM_VERTS_OF_MESH, NULL, (void**)verts_pool, totvert);
+		verts_copy = MEM_mallocN(sizeof(BMVert) * totvert, "BM_mesh_remap verts copy");
+		for (i = totvert, ve = verts_copy + totvert - 1, vep = verts_pool + totvert - 1; i--; ve--, vep--) {
+			*ve = **vep;
+/*			printf("*vep: %p, verts_pool[%d]: %p\n", *vep, i, verts_pool[i]);*/
+		}
+
+		/* Copy back verts to their new place, and update old2new pointers mapping. */
+		new_idx = vert_idx + totvert - 1;
+		ve = verts_copy + totvert - 1;
+		vep = verts_pool + totvert - 1; /* old, org pointer */
+		for (i = totvert; i--; new_idx--, ve--, vep--) {
+			BMVert *new_vep = verts_pool[*new_idx];
+			*new_vep = *ve;
+/*			printf("mapping vert from %d to %d (%p/%p to %p)\n", i, *new_idx, *vep, verts_pool[i], new_vep);*/
+			BLI_ghash_insert(vptr_map, (void*)*vep, (void*)new_vep);
+		}
+		bm->elem_index_dirty |= BM_VERT;
+
+		MEM_freeN(verts_pool);
+		MEM_freeN(verts_copy);
+	}
+
+	/* XXX Code not tested yet (though I don't why it would fail)! */
+	if (edge_idx) {
+		BMEdge **edges_pool, *edges_copy, **edp;
+		int i, totedge = bm->totedge;
+		int *new_idx = NULL;
+
+		/* Init the old-to-new vert pointers mapping */
+		eptr_map = BLI_ghash_new(BLI_ghashutil_ptrhash, BLI_ghashutil_ptrcmp, "BM_mesh_remap edge pointers mapping");
+
+		/* Make a copy of all vertices. */
+		edges_pool = MEM_callocN(sizeof(BMEdge*) * totedge, "BM_mesh_remap edges pool");
+		BM_iter_as_array(bm, BM_EDGES_OF_MESH, NULL, (void**)edges_pool, totedge);
+		edges_copy = MEM_mallocN(sizeof(BMEdge) * totedge, "BM_mesh_remap edges copy");
+		for (i = totedge, ed = edges_copy + totedge - 1, edp = edges_pool + totedge - 1; i--; ed--, edp--) {
+			*ed = **edp;
+		}
+
+		/* Copy back verts to their new place, and update old2new pointers mapping. */
+		new_idx = edge_idx + totedge - 1;
+		ed = edges_copy + totedge - 1;
+		edp = edges_pool + totedge - 1; /* old, org pointer */
+		for (i = totedge; i--; new_idx--, ed--, edp--) {
+			BMEdge *new_edp = edges_pool[*new_idx];
+			*new_edp = *ed;
+			BLI_ghash_insert(eptr_map, (void*)*edp, (void*)new_edp);
+		}
+
+		bm->elem_index_dirty |= BM_EDGE;
+
+		MEM_freeN(edges_pool);
+		MEM_freeN(edges_copy);
+	}
+
+	/* XXX Code not tested yet (though I don't why it would fail)! */
+	if (face_idx) {
+		BMFace **faces_pool, *faces_copy, **fap;
+		int i, totface = bm->totface;
+		int *new_idx = NULL;
+
+		/* Init the old-to-new vert pointers mapping */
+		fptr_map = BLI_ghash_new(BLI_ghashutil_ptrhash, BLI_ghashutil_ptrcmp, "BM_mesh_remap face pointers mapping");
+
+		/* Make a copy of all vertices. */
+		faces_pool = MEM_callocN(sizeof(BMFace*) * totface, "BM_mesh_remap faces pool");
+		BM_iter_as_array(bm, BM_FACES_OF_MESH, NULL, (void**)faces_pool, totface);
+		faces_copy = MEM_mallocN(sizeof(BMFace) * totface, "BM_mesh_remap faces copy");
+		for (i = totface, fa = faces_copy + totface - 1, fap = faces_pool + totface - 1; i--; fa--, fap--) {
+			*fa = **fap;
+		}
+
+		/* Copy back verts to their new place, and update old2new pointers mapping. */
+		new_idx = face_idx + totface - 1;
+		fa = faces_copy + totface - 1;
+		fap = faces_pool + totface - 1; /* old, org pointer */
+		for (i = totface; i--; new_idx--, fa--, fap--) {
+			BMFace *new_fap = faces_pool[*new_idx];
+			*new_fap = *fa;
+			BLI_ghash_insert(fptr_map, (void*)*fap, (void*)new_fap);
+		}
+
+		bm->elem_index_dirty |= BM_FACE;
+
+		MEM_freeN(faces_pool);
+		MEM_freeN(faces_copy);
+	}
+
+	/* And now, fix all vertices/edges/faces/loops pointers! */
+	/* Verts' pointers, only edge pointers... */
+	if (eptr_map) {
+		BM_ITER(ve, &iter, bm, BM_VERTS_OF_MESH, NULL) {
+/*			printf("Vert e: %p -> %p\n", ve->e, BLI_ghash_lookup(eptr_map, (const void*)ve->e));*/
+			ve->e = BLI_ghash_lookup(eptr_map, (const void*)ve->e);
+		}
+	}
+
+	/* Edges' pointers, only vert pointers (as we don’t mess with loops!)... */
+	if (vptr_map) {
+		BM_ITER(ed, &iter, bm, BM_EDGES_OF_MESH, NULL) {
+/*			printf("Edge v1: %p -> %p\n", ed->v1, BLI_ghash_lookup(vptr_map, (const void*)ed->v1));*/
+/*			printf("Edge v2: %p -> %p\n", ed->v2, BLI_ghash_lookup(vptr_map, (const void*)ed->v2));*/
+			ed->v1 = BLI_ghash_lookup(vptr_map, (const void*)ed->v1);
+			ed->v2 = BLI_ghash_lookup(vptr_map, (const void*)ed->v2);
+		}
+	}
+
+	/* Faces' pointers (loops, in fact), always needed... */
+	BM_ITER(fa, &iter, bm, BM_FACES_OF_MESH, NULL) {
+		BM_ITER(lo, &iterl, bm, BM_LOOPS_OF_FACE, fa) {
+			if (vptr_map) {
+/*				printf("Loop v: %p -> %p\n", lo->v, BLI_ghash_lookup(vptr_map, (const void*)lo->v));*/
+				lo->v = BLI_ghash_lookup(vptr_map, (const void*)lo->v);
+			}
+			if (eptr_map) {
+/*				printf("Loop e: %p -> %p\n", lo->e, BLI_ghash_lookup(eptr_map, (const void*)lo->e));*/
+				lo->e = BLI_ghash_lookup(eptr_map, (const void*)lo->e);
+			}
+			if (fptr_map) {
+/*				printf("Loop f: %p -> %p\n", lo->f, BLI_ghash_lookup(fptr_map, (const void*)lo->f));*/
+				lo->f = BLI_ghash_lookup(fptr_map, (const void*)lo->f);
+			}
+		}
+	}
+
+	if (vptr_map)
+		BLI_ghash_free(vptr_map, NULL, NULL);
+	if (eptr_map)
+		BLI_ghash_free(eptr_map, NULL, NULL);
+	if (fptr_map)
+		BLI_ghash_free(fptr_map, NULL, NULL);
+}
+
 BMVert *BM_vert_at_index(BMesh *bm, const int index)
 {
 	return BLI_mempool_findelem(bm->vpool, index);

Modified: trunk/blender/source/blender/bmesh/intern/bmesh_mesh.h
===================================================================
--- trunk/blender/source/blender/bmesh/intern/bmesh_mesh.h	2012-04-19 12:21:44 UTC (rev 45778)
+++ trunk/blender/source/blender/bmesh/intern/bmesh_mesh.h	2012-04-19 12:31:39 UTC (rev 45779)
@@ -43,6 +43,7 @@
 void BM_mesh_elem_index_ensure(BMesh *bm, const char hflag);
 void BM_mesh_elem_index_validate(BMesh *bm, const char *location, const char *func,
                                  const char *msg_a, const char *msg_b);
+void BM_mesh_remap(BMesh *bm, int *vert_idx, int *edge_idx, int *face_idx);
 
 BMVert *BM_vert_at_index(BMesh *bm, const int index);
 BMEdge *BM_edge_at_index(BMesh *bm, const int index);

Modified: trunk/blender/source/blender/editors/mesh/editmesh_tools.c
===================================================================
--- trunk/blender/source/blender/editors/mesh/editmesh_tools.c	2012-04-19 12:21:44 UTC (rev 45778)
+++ trunk/blender/source/blender/editors/mesh/editmesh_tools.c	2012-04-19 12:31:39 UTC (rev 45779)
@@ -3599,15 +3599,14 @@
 	RNA_def_boolean(ot->srna, "extend", 0, "Extend", "Extend the existing selection");
 }
 
-#if 0 /* UNUSED */
 /* qsort routines.  not sure how to make these
  * work, since we aren't using linked lists for
  * geometry anymore.  might need a sortof "swap"
  * function for bmesh elements. */
 
 typedef struct xvertsort {
-	float x;
-	BMVert *v1;
+	int x; /* X screen-coordinate */
+	int org_idx; /* Original index of this vertex _in the mempool_ */
 } xvertsort;
 
 
@@ -3615,11 +3614,13 @@
 {
 	const xvertsort *x1 = v1, *x2 = v2;
 
-	if (x1->x > x2->x) return 1;
-	else if (x1->x < x2->x) return -1;
-	return 0;
+	/* We move unchanged vertices (org_idx < 0) at the begining of the sorted list. */
+	if (x1->org_idx >= 0 && x2->org_idx >= 0)
+		return (x1->x > x2->x) - (x1->x < x2->x);
+	return (x2->org_idx < 0) - (x1->org_idx < 0);
 }
 
+#if 0 /* Unused */
 struct facesort {
 	uintptr_t x;
 	struct EditFace *efa;
@@ -3635,66 +3636,78 @@
 }
 #endif
 
-// XXX is this needed?
-/* called from buttons */
-#if 0 /* UNUSED */
-static void xsortvert_flag__doSetX(void *userData, EditVert *UNUSED(eve), int x, int UNUSED(y), int index)
+static void xsortvert_flag__doSetX(void *userData, BMVert *UNUSED(eve), int x, int UNUSED(y), int index)
 {
 	xvertsort *sortblock = userData;
 
 	sortblock[index].x = x;
 }
-#endif
 
 /* all verts with (flag & 'flag') are sorted */
-static void xsortvert_flag(bContext *UNUSED(C), int UNUSED(flag))
+static void xsortvert_flag(bContext *C, int flag)
 {
-	/* BMESH_TODO */
-#if 0 //hrm, geometry isn't in linked lists anymore. . .
 	ViewContext vc;
 	BMEditMesh *em;
-	BMVert *eve;
+	BMVert *ve;
 	BMIter iter;
 	xvertsort *sortblock;
-	ListBase tbase;
-	int i, amount;
+	int *unchangedblock, *vmap;
+	int totvert, sorted = 0, unchanged = 0, i;
 
 	em_setup_viewcontext(C, &vc);
 	em = vc.em;
 
-	amount = em->bm->totvert;
-	sortblock = MEM_callocN(sizeof(xvertsort) * amount, "xsort");
-	BM_ITER (eve, &iter, em->bm, BM_VERTS_OF_MESH, NULL) {
-		if (BM_elem_flag_test(eve, BM_ELEM_SELECT))
-			sortblock[i].v1 = eve;
+	/* As we are going to manipulate verts heavily, use an array. */
+	totvert = em->bm->totvert;
+
+	sortblock = MEM_callocN(sizeof(xvertsort) * totvert, "xsort sorted");
+	/* Stores unchanged verts, will be reused as final old2new vert mapping... */
+	unchangedblock = MEM_callocN(sizeof(int) * totvert, "xsort unchanged");
+	BM_ITER_INDEX(ve, &iter, em->bm, BM_VERTS_OF_MESH, NULL, i) {
+		if (BM_elem_flag_test(ve, flag)) {
+			sortblock[i].org_idx = i;
+			sorted++;
+		}

@@ Diff output truncated at 10240 characters. @@



More information about the Bf-blender-cvs mailing list