[Bf-blender-cvs] SVN commit: /data/svn/bf-blender [51459] trunk/blender/source/blender: bmesh decimator support for loop & edge customdata.

Campbell Barton ideasman42 at gmail.com
Sat Oct 20 19:31:07 CEST 2012


Revision: 51459
          http://projects.blender.org/scm/viewvc.php?view=rev&root=bf-blender&revision=51459
Author:   campbellbarton
Date:     2012-10-20 17:31:07 +0000 (Sat, 20 Oct 2012)
Log Message:
-----------
bmesh decimator support for loop & edge customdata. (most importantly UVs and vertex colors).

Modified Paths:
--------------
    trunk/blender/source/blender/blenkernel/BKE_customdata.h
    trunk/blender/source/blender/blenkernel/intern/customdata.c
    trunk/blender/source/blender/bmesh/intern/bmesh_decimate.c
    trunk/blender/source/blender/modifiers/intern/MOD_decimate.c

Modified: trunk/blender/source/blender/blenkernel/BKE_customdata.h
===================================================================
--- trunk/blender/source/blender/blenkernel/BKE_customdata.h	2012-10-20 16:48:54 UTC (rev 51458)
+++ trunk/blender/source/blender/blenkernel/BKE_customdata.h	2012-10-20 17:31:07 UTC (rev 51459)
@@ -81,6 +81,11 @@
  */
 int CustomData_layer_has_math(struct CustomData *data, int layer_n);
 
+/**
+ * Checks if any of the customdata layers has math.
+ */
+int CustomData_has_math(struct CustomData *data);
+
 /* copies the "value" (e.g. mloopuv uv or mloopcol colors) from one block to
  * another, while not overwriting anything else (e.g. flags).  probably only
  * implemented for mloopuv/mloopcol, for now.*/
@@ -205,8 +210,8 @@
 void CustomData_interp(const struct CustomData *source, struct CustomData *dest,
                        int *src_indices, float *weights, float *sub_weights,
                        int count, int dest_index);
-void CustomData_bmesh_interp(struct CustomData *data, void **src_blocks, 
-                             float *weights, float *sub_weights, int count,
+void CustomData_bmesh_interp(struct CustomData *data, void **src_blocks,
+                             const float *weights, const float *sub_weights, int count,
                              void *dest_block);
 
 

Modified: trunk/blender/source/blender/blenkernel/intern/customdata.c
===================================================================
--- trunk/blender/source/blender/blenkernel/intern/customdata.c	2012-10-20 16:48:54 UTC (rev 51458)
+++ trunk/blender/source/blender/blenkernel/intern/customdata.c	2012-10-20 17:31:07 UTC (rev 51459)
@@ -2477,12 +2477,26 @@
 	if (typeInfo->equal && typeInfo->add && typeInfo->multiply && 
 	    typeInfo->initminmax && typeInfo->dominmax)
 	{
-		return 1;
+		return TRUE;
 	}
 	
-	return 0;
+	return FALSE;
 }
 
+int CustomData_has_math(struct CustomData *data)
+{
+	int i;
+
+	/* interpolates a layer at a time */
+	for (i = 0; i < data->totlayer; ++i) {
+		if (CustomData_layer_has_math(data, i)) {
+			return TRUE;
+		}
+	}
+
+	return FALSE;
+}
+
 /* copies the "value" (e.g. mloopuv uv or mloopcol colors) from one block to
  * another, while not overwriting anything else (e.g. flags)*/
 void CustomData_data_copy_value(int type, void *source, void *dest)
@@ -2580,8 +2594,8 @@
 		memcpy(dest, source, typeInfo->size);
 }
 
-void CustomData_bmesh_interp(CustomData *data, void **src_blocks, float *weights,
-                             float *sub_weights, int count, void *dest_block)
+void CustomData_bmesh_interp(CustomData *data, void **src_blocks, const float *weights,
+                             const float *sub_weights, int count, void *dest_block)
 {
 	int i, j;
 	void *source_buf[SOURCE_BUF_SIZE];

Modified: trunk/blender/source/blender/bmesh/intern/bmesh_decimate.c
===================================================================
--- trunk/blender/source/blender/bmesh/intern/bmesh_decimate.c	2012-10-20 16:48:54 UTC (rev 51458)
+++ trunk/blender/source/blender/bmesh/intern/bmesh_decimate.c	2012-10-20 17:31:07 UTC (rev 51459)
@@ -36,6 +36,8 @@
 #include "BLI_quadric.h"
 #include "BLI_heap.h"
 
+#include "BKE_customdata.h"
+
 #include "bmesh.h"
 #include "bmesh_structure.h"
 #include "bmesh_decimate.h"
@@ -49,7 +51,13 @@
 
 #define BOUNDARY_PRESERVE_WEIGHT 100.0f
 
+typedef enum CD_UseFlag {
+	CD_DO_VERT,
+	CD_DO_EDGE,  /* not used yet */
+	CD_DO_LOOP
+} CD_UseFlag;
 
+
 /* BMesh Helper Functions
  * ********************** */
 
@@ -322,40 +330,146 @@
 /* Edge Collapse Functions
  * *********************** */
 
+#ifdef USE_CUSTOMDATA
+
 /**
+ * \param v is the target to merge into.
+ */
+static void bm_edge_collapse_loop_customdata(BMesh *bm, BMLoop *l, BMVert *v_clear, BMVert *v_other, const float customdata_fac)
+{
+	/* these don't need to be updated, since they will get removed when the edge collapses */
+	BMLoop *l_clear, *l_other;
+	const int is_manifold = BM_edge_is_manifold(l->e);
+	int side;
+
+	/* l defines the vert to collapse into  */
+
+	/* first find the loop of 'v_other' thats attached to the face of 'l' */
+	if (l->v == v_clear) {
+		l_clear = l;
+		l_other = l->next;
+	}
+	else {
+		l_clear = l->next;
+		l_other = l;
+	}
+
+	BLI_assert(l_clear->v == v_clear);
+	BLI_assert(l_other->v == v_other);
+
+	/* now we have both corners of the face 'l->f' */
+	for (side = 0; side < 2; side++) {
+		int is_seam = FALSE;
+		void *src[2];
+		BMFace *f_exit = is_manifold ? l->radial_next->f : NULL;
+		BMEdge *e_prev = l->e;
+		BMLoop *l_first;
+		BMLoop *l_iter;
+		float w[2];
+
+		if (side == 0) {
+			l_iter = l_first = l_clear;
+			src[0] = l_clear->head.data;
+			src[1] = l_other->head.data;
+
+			w[0] = customdata_fac;
+			w[1] = 1.0f - customdata_fac;
+		}
+		else {
+			l_iter = l_first = l_other;
+			src[0] = l_other->head.data;
+			src[1] = l_clear->head.data;
+
+			w[0] = 1.0f - customdata_fac;
+			w[1] = customdata_fac;
+		}
+
+		/* WATCH IT! - should NOT reference (_clear or _other) vars for this while loop */
+
+		/* walk around the fan using 'e_prev' */
+		while (((l_iter = BM_vert_step_fan_loop(l_iter, &e_prev)) != l_first) && (l_iter != NULL)) {
+			int i;
+			/* quit once we hit the opposite face, if we have one */
+			if (f_exit && UNLIKELY(f_exit == l_iter->f)) {
+				break;
+			}
+
+			/* break out unless we find a match */
+			is_seam = TRUE;
+
+			/* ok. we have a loop. now be smart with it! */
+			for (i = 0; i < bm->ldata.totlayer; i++) {
+				if (CustomData_layer_has_math(&bm->ldata, i)) {
+					int offset = bm->ldata.layers[i].offset;
+					int type = bm->ldata.layers[i].type;
+					void *cd_src, *cd_iter;
+
+					/* todo, make nicer macros for this */
+					cd_src = (char *)src[0] + offset;
+					// cd_dst = (char *)src[1] + offset;  // UNUSED
+					cd_iter  = (char *)l_iter->head.data  + offset;
+
+					/* detect seams */
+					if (CustomData_data_equals(type, cd_src, cd_iter)) {
+						CustomData_bmesh_interp(&bm->ldata, src, w, NULL, 2, l_iter->head.data);
+						is_seam = FALSE;
+					}
+				}
+			}
+
+			if (is_seam) {
+				break;
+			}
+		}
+	}
+
+	/* first walk around the fan until we hit a seam */
+
+
+
+	/* last, interpolate ourselves */
+
+
+}
+#endif  /* USE_CUSTOMDATA */
+
+/**
  * special, highly limited edge collapse function
  * intended for speed over flexibiliy.
  * can only collapse edges connected to (1, 2) tris.
  *
  * Important - dont add vert/edge/face data on collapsing!
  *
- * \param ke_other let caller know what edges we remove besides \a ke
+ * \param e_clear_other let caller know what edges we remove besides \a e_clear
+ * \param customdata_flag merge factor, scales from 0 - 1 ('v_clear' -> 'v_other')
  */
-static int bm_edge_collapse(BMesh *bm, BMEdge *ke, BMVert *kv, int ke_other[2],
+static int bm_edge_collapse(BMesh *bm, BMEdge *e_clear, BMVert *v_clear, int r_e_clear_other[2],
 #ifdef USE_CUSTOMDATA
+                            const CD_UseFlag customdata_flag,
                             const float customdata_fac
 #else
+                            const CD_UseFlag UNUSED(customdata_flag),
                             const float UNUSED(customdata_fac)
 #endif
                             )
 {
-	BMVert *v_other = BM_edge_other_vert(ke, kv);
+	BMVert *v_other = BM_edge_other_vert(e_clear, v_clear);
 
 	BLI_assert(v_other != NULL);
 
-	if (BM_edge_is_manifold(ke)) {
+	if (BM_edge_is_manifold(e_clear)) {
 		BMLoop *l_a, *l_b;
 		BMEdge *e_a_other[2], *e_b_other[2];
 		int ok;
 
-		ok = BM_edge_loop_pair(ke, &l_a, &l_b);
+		ok = BM_edge_loop_pair(e_clear, &l_a, &l_b);
 
 		BLI_assert(ok == TRUE);
 		BLI_assert(l_a->f->len == 3);
 		BLI_assert(l_b->f->len == 3);
 
-		/* keep 'kv' 0th */
-		if (BM_vert_in_edge(l_a->prev->e, kv)) {
+		/* keep 'v_clear' 0th */
+		if (BM_vert_in_edge(l_a->prev->e, v_clear)) {
 			e_a_other[0] = l_a->prev->e;
 			e_a_other[1] = l_a->next->e;
 		}
@@ -364,7 +478,7 @@
 			e_a_other[0] = l_a->next->e;
 		}
 
-		if (BM_vert_in_edge(l_b->prev->e, kv)) {
+		if (BM_vert_in_edge(l_b->prev->e, v_clear)) {
 			e_b_other[0] = l_b->prev->e;
 			e_b_other[1] = l_b->next->e;
 		}
@@ -390,20 +504,27 @@
 			return FALSE;
 		}
 
-		ke_other[0] = BM_elem_index_get(e_a_other[0]);
-		ke_other[1] = BM_elem_index_get(e_b_other[0]);
+		r_e_clear_other[0] = BM_elem_index_get(e_a_other[0]);
+		r_e_clear_other[1] = BM_elem_index_get(e_b_other[0]);
 
 #ifdef USE_CUSTOMDATA
-		/* TODO, loops */
-		// const float w[2] = {customdata_fac, 1.0f - customdata_fac};
-
 		/* before killing, do customdata */
-		BM_data_interp_from_verts(bm, v_other, kv, v_other, customdata_fac);
+		if (customdata_flag & CD_DO_VERT) {
+			BM_data_interp_from_verts(bm, v_other, v_clear, v_other, customdata_fac);
+		}
+		if (customdata_flag & CD_DO_EDGE) {
+			BM_data_interp_from_edges(bm, e_a_other[1], e_a_other[0], e_a_other[1], customdata_fac);
+			BM_data_interp_from_edges(bm, e_b_other[1], e_b_other[0], e_b_other[1], customdata_fac);
+		}
+		if (customdata_flag & CD_DO_LOOP) {
+			bm_edge_collapse_loop_customdata(bm, e_clear->l,              v_clear, v_other, customdata_fac);
+			bm_edge_collapse_loop_customdata(bm, e_clear->l->radial_next, v_clear, v_other, customdata_fac);
+		}
 #endif
 
-		BM_edge_kill(bm, ke);
+		BM_edge_kill(bm, e_clear);
 
-		BM_vert_splice(bm, kv, v_other);
+		BM_vert_splice(bm, v_clear, v_other);
 
 		BM_edge_splice(bm, e_a_other[0], e_a_other[1]);
 		BM_edge_splice(bm, e_b_other[0], e_b_other[1]);
@@ -412,17 +533,17 @@
 
 		return TRUE;
 	}
-	else if (BM_edge_is_boundary(ke)) {
+	else if (BM_edge_is_boundary(e_clear)) {
 		/* same as above but only one triangle */
 		BMLoop *l_a;
 		BMEdge *e_a_other[2];
 
-		l_a = ke->l;
+		l_a = e_clear->l;
 
 		BLI_assert(l_a->f->len == 3);
 
-		/* keep 'kv' 0th */
-		if (BM_vert_in_edge(l_a->prev->e, kv)) {
+		/* keep 'v_clear' 0th */
+		if (BM_vert_in_edge(l_a->prev->e, v_clear)) {
 			e_a_other[0] = l_a->prev->e;
 			e_a_other[1] = l_a->next->e;
 		}
@@ -431,20 +552,25 @@
 			e_a_other[0] = l_a->next->e;
 		}
 
-		ke_other[0] = BM_elem_index_get(e_a_other[0]);
-		ke_other[1] = -1;
+		r_e_clear_other[0] = BM_elem_index_get(e_a_other[0]);
+		r_e_clear_other[1] = -1;
 
 #ifdef USE_CUSTOMDATA
-		/* TODO, loops */
-		// const float w[2] = {customdata_fac, 1.0f - customdata_fac};
-
 		/* before killing, do customdata */
-		BM_data_interp_from_verts(bm, v_other, kv, v_other, customdata_fac);
+		if (customdata_flag & CD_DO_VERT) {
+			BM_data_interp_from_verts(bm, v_other, v_clear, v_other, customdata_fac);
+		}

@@ Diff output truncated at 10240 characters. @@



More information about the Bf-blender-cvs mailing list