[Bf-blender-cvs] [e9c28dd] soc-2014-shapekey: Implemented draft topology x17-based hashing in BKE_editmesh

Grigory Revzin noreply at git.blender.org
Fri May 16 02:02:38 CEST 2014


Commit: e9c28ddbbdbfc38a25edaf1e2f4d05e0ad272296
Author: Grigory Revzin
Date:   Fri May 16 03:19:36 2014 +0400
https://developer.blender.org/rBe9c28ddbbdbfc38a25edaf1e2f4d05e0ad272296

Implemented draft topology x17-based hashing in BKE_editmesh

===================================================================

M	source/blender/blenkernel/BKE_editmesh.h
M	source/blender/blenkernel/intern/editmesh.c

===================================================================

diff --git a/source/blender/blenkernel/BKE_editmesh.h b/source/blender/blenkernel/BKE_editmesh.h
index 38c8cf1..5a700ac 100644
--- a/source/blender/blenkernel/BKE_editmesh.h
+++ b/source/blender/blenkernel/BKE_editmesh.h
@@ -38,6 +38,12 @@ struct Scene;
 struct DerivedMesh;
 struct MeshStatVis;
 
+/* struct for storing data to determine if the mesh's topology has changed */
+typedef struct {
+	int totvert, totedge, totloop, totface;
+	int topohash;
+} EMTopoChangeData;
+
 /* ok: the EDBM module is for editmode bmesh stuff.  in contrast, the 
  *     BMEdit module is for code shared with blenkernel that concerns
  *     the BMEditMesh structure.
@@ -78,6 +84,10 @@ typedef struct BMEditMesh {
 	/* Object this editmesh came from (if it came from one) */
 	struct Object *ob;
 
+	/* used to know if the editmesh's topology has changed from a certain point in time,
+	 * use BKE_editmesh_topochange_calc/BKE_editmesh_topo_has_changed */
+	EMTopoChangeData topochange;
+
 	/*temp variables for x-mirror editing*/
 	int mirror_cdlayer; /* -1 is invalid */
 } BMEditMesh;
@@ -94,6 +104,12 @@ void        BKE_editmesh_update_linked_customdata(BMEditMesh *em);
 void        BKE_editmesh_color_free(BMEditMesh *em);
 void        BKE_editmesh_color_ensure(BMEditMesh *em, const char htype);
 
+/* calculates a topology-dependent hash to detect if topology has been modified later */
+void		BKE_editmesh_topochange_calc(BMEditMesh *em);
+
+/* checks if the topology has changed since last call to BKE_editmesh_syncdata_calc. Does not recalc! */
+bool		BKE_editmesh_topo_has_changed(BMEditMesh *em);
+
 /* editderivedmesh.c */
 /* should really be defined in editmesh.c, but they use 'EditDerivedBMesh' */
 void        BKE_editmesh_statvis_calc(BMEditMesh *em, struct DerivedMesh *dm,
diff --git a/source/blender/blenkernel/intern/editmesh.c b/source/blender/blenkernel/intern/editmesh.c
index 2247b91..3d41be7 100644
--- a/source/blender/blenkernel/intern/editmesh.c
+++ b/source/blender/blenkernel/intern/editmesh.c
@@ -246,3 +246,102 @@ void BKE_editmesh_color_ensure(BMEditMesh *em, const char htype)
 			break;
 	}
 }
+
+
+/* ==================== topology hashing ======================= */
+
+unsigned int x17_hash(const char *data, unsigned int len, unsigned int seed)
+{
+	unsigned int hash = seed + len;
+	for (; len & ~1; len -= 2, data += 2)
+		hash = (((hash * 17) + (data[0] - ' ')) * 17) + (data[1] - ' ');
+
+	if (len & 1)
+		hash = (hash * 17) + (data[0] - ' ');
+	return hash;
+}
+
+int hashfunc(void *data, int len)
+{
+	return (int) x17_hash(data, len, 0x27127127);
+}
+
+int hashloop_topo(BMLoop *l)
+{
+	/* skip header, don't track customdata */
+	return hashfunc(((char *)l) + sizeof(BMHeader), sizeof(BMLoop) - sizeof(BMHeader));
+}
+
+int hashface_topo(BMFace *f)
+{
+	/* skip header & flags & face normals and material */
+	int a = f->len + (int)f->l_first;
+	return hashfunc(&a, sizeof(int));
+}
+
+/* TODO better hashing */
+int bmesh_topohash(BMesh *bm)
+{
+	BMIter iter;
+	BMLoop *l;
+	BMFace *f;
+	BMEdge *e;
+	int i;
+	int j;
+	int hash = bm->totedge + bm->totvert + bm->totloop + bm->totface;
+
+	if (!hash) {
+		return 0;
+	}
+
+	if (bm->totface)
+	{
+		BM_ITER_MESH_INDEX(f, &iter, bm, BM_FACES_OF_MESH, i) {
+			hash += i * hashface_topo(f);
+			l = f->l_first;
+			int len3 = f->len * f->len * f->len;
+			for (j = 0; j < f->len; ++j) {
+				hash += (len3 + i - j) * hashloop_topo(l);
+				l = l->next;
+			}
+		}
+		/* this next cycle is to counter weird meshes like one face, one million wire edges*/
+		BM_ITER_MESH_INDEX(e, &iter, bm, BM_EDGES_OF_MESH, i) {
+			j = (int)e->v1 + (int)e->v2;
+			hash += hashfunc(&j, sizeof(int));
+		}
+	}
+	else {
+		if (bm->totedge == 0) {
+			/* cloud mesh */
+			return hashfunc(&bm->totvert, sizeof(int));
+		}
+		else {
+			/* wire mesh */
+			BM_ITER_MESH_INDEX(e, &iter, bm, BM_EDGES_OF_MESH, i) {
+				j = (int)e->v1 + (int)e->v2;
+				hash += hashfunc(&j, sizeof(int));
+			}
+		}
+	}
+	return hash;
+}
+
+void BKE_editmesh_topochange_calc(BMEditMesh *em)
+{
+	em->topochange.topohash = bmesh_topohash(em->bm);
+	memcpy(&em->topochange.totvert, &em->bm->totvert, sizeof(int) * 4);
+}
+
+
+bool BKE_editmesh_topo_has_changed(BMEditMesh *em)
+{
+	/* fast way to compare em->bm->totvert/totface/totetc with topochange */
+	if (!memcmp(&em->bm->totvert, &em->topochange.totvert, sizeof(int) * 4)) {
+		int hash = bmesh_topohash(em->bm);
+		if (hash == em->topochange.topohash)
+			return false;
+		else return true;
+	}
+	return true;
+}




More information about the Bf-blender-cvs mailing list