[Bf-blender-cvs] [5865230] master: Vert/Edge Slide: better UV interpolation

Campbell Barton noreply at git.blender.org
Mon Feb 16 08:53:02 CET 2015


Commit: 58652301dee685f67edf03c2bfcfbafe15a7cb6e
Author: Campbell Barton
Date:   Mon Feb 16 18:49:18 2015 +1100
Branches: master
https://developer.blender.org/rB58652301dee685f67edf03c2bfcfbafe15a7cb6e

Vert/Edge Slide: better UV interpolation

Ignore faces which the sliding vert is outside of.

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

M	source/blender/bmesh/intern/bmesh_interp.c
M	source/blender/bmesh/intern/bmesh_interp.h
M	source/blender/editors/transform/transform.c
M	source/blender/editors/transform/transform.h

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

diff --git a/source/blender/bmesh/intern/bmesh_interp.c b/source/blender/bmesh/intern/bmesh_interp.c
index a88f38c..d60c01b 100644
--- a/source/blender/bmesh/intern/bmesh_interp.c
+++ b/source/blender/bmesh/intern/bmesh_interp.c
@@ -925,12 +925,15 @@ struct LoopWalkCtx {
 	/* reference for this contiguous fan */
 	const void *data_ref;
 	int data_len;
+
+	/* accumulate 'LoopGroupCD.weight' to make unit length */
+	float weight_accum;
+
 	/* both arrays the size of the 'BM_vert_face_count(v)'
 	 * each contiguous fan gets a slide of these arrays */
 	void **data_array;
+	int *data_index_array;
 	float *weight_array;
-	/* accumulate 'LoopGroupCD.weight' to make unit length */
-	float weight_accum;
 };
 
 /* Store vars to pass into 'CustomData_bmesh_interp' */
@@ -939,6 +942,8 @@ struct LoopGroupCD {
 	void **data;
 	/* weights (aligned with 'data') */
 	float *data_weights;
+	/* index-in-face */
+	int *data_index;
 	/* number of loops in the fan */
 	int data_len;
 };
@@ -948,6 +953,7 @@ static void bm_loop_walk_add(struct LoopWalkCtx *lwc, BMLoop *l)
 	const float w = BM_loop_calc_face_angle(l);
 	BM_elem_flag_enable(l, BM_ELEM_INTERNAL_TAG);
 	lwc->data_array[lwc->data_len] = BM_ELEM_CD_GET_VOID_P(l, lwc->cd_layer_offset);
+	lwc->data_index_array[lwc->data_len] = BM_elem_index_get(l);
 	lwc->weight_array[lwc->data_len] = w;
 	lwc->weight_accum += w;
 
@@ -1001,11 +1007,14 @@ LinkNode *BM_vert_loop_groups_data_layer_create(BMesh *bm, BMVert *v, int layer_
 	loop_num = 0;
 	BM_ITER_ELEM (l, &liter, v, BM_LOOPS_OF_VERT) {
 		BM_elem_flag_disable(l, BM_ELEM_INTERNAL_TAG);
+		BM_elem_index_set(l, loop_num);  /* set_dirty! */
 		loop_num++;
 	}
+	bm->elem_index_dirty |= BM_LOOP;
 
 	lwc.data_len = 0;
 	lwc.data_array = BLI_memarena_alloc(lwc.arena, sizeof(void *) * loop_num);
+	lwc.data_index_array = BLI_memarena_alloc(lwc.arena, sizeof(int) * loop_num);
 	lwc.weight_array = BLI_memarena_alloc(lwc.arena, sizeof(float) * loop_num);
 
 	BM_ITER_ELEM (l, &liter, v, BM_LOOPS_OF_VERT) {
@@ -1017,6 +1026,7 @@ LinkNode *BM_vert_loop_groups_data_layer_create(BMesh *bm, BMVert *v, int layer_
 
 			/* assign len-last */
 			lf->data         = &lwc.data_array[lwc.data_len];
+			lf->data_index   = &lwc.data_index_array[lwc.data_len];
 			lf->data_weights = &lwc.weight_array[lwc.data_len];
 			lwc.weight_accum = 0.0f;
 
@@ -1040,12 +1050,48 @@ LinkNode *BM_vert_loop_groups_data_layer_create(BMesh *bm, BMVert *v, int layer_
 	return groups;
 }
 
-static void bm_vert_loop_groups_data_layer_merge__single(BMesh *bm, void *lf_p, void *data, int type)
+static void bm_vert_loop_groups_data_layer_merge__single(
+        BMesh *bm, void *lf_p, void *data, int type)
+{
+	struct LoopGroupCD *lf = lf_p;
+	int i;
+	const float *data_weights;
+
+	data_weights = lf->data_weights;
+
+	CustomData_bmesh_interp(&bm->ldata, lf->data, data_weights, NULL, lf->data_len, data);
+
+	for (i = 0; i < lf->data_len; i++) {
+		CustomData_copy_elements(type, data, lf->data[i], 1);
+	}
+}
+
+static void bm_vert_loop_groups_data_layer_merge_weights__single(
+        BMesh *bm, void *lf_p, void *data, int type, const float *loop_weights)
 {
 	struct LoopGroupCD *lf = lf_p;
 	int i;
+	const float *data_weights;
+
+	/* re-weight */
+	float *temp_weights = BLI_array_alloca(temp_weights, lf->data_len);
+	float weight_accum = 0.0f;
 
-	CustomData_bmesh_interp(&bm->ldata, lf->data, lf->data_weights, NULL, lf->data_len, data);
+	for (i = 0; i < lf->data_len; i++) {
+		float w = loop_weights[lf->data_index[i]] * lf->data_weights[i];
+		temp_weights[i] = w;
+		weight_accum += w;
+	}
+
+	if (LIKELY(weight_accum != 0.0f)) {
+		mul_vn_fl(temp_weights, lf->data_len, 1.0f / weight_accum);
+		data_weights = temp_weights;
+	}
+	else {
+		data_weights = lf->data_weights;
+	}
+
+	CustomData_bmesh_interp(&bm->ldata, lf->data, data_weights, NULL, lf->data_len, data);
 
 	for (i = 0; i < lf->data_len; i++) {
 		CustomData_copy_elements(type, data, lf->data[i], 1);
@@ -1066,4 +1112,19 @@ void BM_vert_loop_groups_data_layer_merge(BMesh *bm, LinkNode *groups, int layer
 	} while ((groups = groups->next));
 }
 
+/**
+ * A version of #BM_vert_loop_groups_data_layer_merge
+ * that takes an array of loop-weights (aligned with #BM_LOOPS_OF_VERT iterator)
+ */
+void BM_vert_loop_groups_data_layer_merge_weights(BMesh *bm, LinkNode *groups, int layer_n, const float *loop_weights)
+{
+	int type = bm->ldata.layers[layer_n].type;
+	int size = CustomData_sizeof(type);
+	void *data = alloca(size);
+
+	do {
+		bm_vert_loop_groups_data_layer_merge_weights__single(bm, groups->link, data, type, loop_weights);
+	} while ((groups = groups->next));
+}
+
 /** \} */
\ No newline at end of file
diff --git a/source/blender/bmesh/intern/bmesh_interp.h b/source/blender/bmesh/intern/bmesh_interp.h
index cd6d5e2..1c1c063 100644
--- a/source/blender/bmesh/intern/bmesh_interp.h
+++ b/source/blender/bmesh/intern/bmesh_interp.h
@@ -54,5 +54,6 @@ void  BM_loop_interp_from_face(BMesh *bm, BMLoop *target, BMFace *source,
 void  BM_face_multires_bounds_smooth(BMesh *bm, BMFace *f);
 struct LinkNode *BM_vert_loop_groups_data_layer_create(BMesh *bm, BMVert *v, int layer_n, struct MemArena *arena);
 void BM_vert_loop_groups_data_layer_merge(BMesh *bm, struct LinkNode *groups, int layer_n);
+void BM_vert_loop_groups_data_layer_merge_weights(BMesh *bm, struct LinkNode *groups, int layer_n, const float *loop_weights);
 
 #endif /* __BMESH_INTERP_H__ */
diff --git a/source/blender/editors/transform/transform.c b/source/blender/editors/transform/transform.c
index 1740e54..193bcbb 100644
--- a/source/blender/editors/transform/transform.c
+++ b/source/blender/editors/transform/transform.c
@@ -44,6 +44,7 @@
 #include "DNA_movieclip_types.h"
 #include "DNA_scene_types.h"  /* PET modes */
 
+#include "BLI_alloca.h"
 #include "BLI_utildefines.h"
 #include "BLI_math.h"
 #include "BLI_rect.h"
@@ -5269,6 +5270,8 @@ static void slide_origdata_create_data(
 
 		sod->arena = BLI_memarena_new(BLI_MEMARENA_STD_BUFSIZE, __func__);
 
+		sod->origverts = BLI_ghash_ptr_new_ex(__func__, v_num);
+
 		for (i = 0; i < v_num; i++, sv = (void *)(((char *)sv) + v_stride)) {
 			BMIter fiter;
 			BMFace *f;
@@ -5294,6 +5297,64 @@ static void slide_origdata_create_data(
 			else {
 				sv->cd_loop_groups = NULL;
 			}
+
+			BLI_ghash_insert(sod->origverts, sv->v, sv);
+		}
+	}
+}
+
+/**
+ * If we're sliding the vert, return its original location, if not, the current location is good.
+ */
+static const float *slide_origdata_orig_vert_co(SlideOrigData *sod, BMVert *v)
+{
+	TransDataGenericSlideVert *sv = BLI_ghash_lookup(sod->origverts, v);
+	return sv ? sv->co_orig_3d : v->co;
+}
+
+static void slide_origdata_interp_data_vert(
+        SlideOrigData *sod, BMesh *bm, bool is_final,
+        TransDataGenericSlideVert *sv)
+{
+	BMIter liter;
+	BMLoop *l;
+	int j;
+	float *loop_weights;
+	const bool do_loop_weight = (len_squared_v3v3(sv->v->co, sv->co_orig_3d) > FLT_EPSILON);
+
+	// BM_ITER_ELEM (l, &liter, sv->v, BM_LOOPS_OF_VERT) {
+	l = BM_iter_new(&liter, bm, BM_LOOPS_OF_VERT, sv->v);
+	loop_weights = do_loop_weight ? BLI_array_alloca(loop_weights, liter.count) : NULL;
+	for (j = 0 ; l; l = BM_iter_step(&liter), j++) {
+		BMFace *f_copy;  /* the copy of 'f' */
+
+		f_copy = BLI_ghash_lookup(sod->origfaces, l->f);
+
+		/* only loop data, no vertex data since that contains shape keys,
+		 * and we do not want to mess up other shape keys */
+		BM_loop_interp_from_face(bm, l, f_copy, false, is_final);
+
+		/* make sure face-attributes are correct (e.g. MTexPoly) */
+		BM_elem_attrs_copy(sod->bm_origfaces, bm, f_copy, l->f);
+
+		/* weight the loop */
+		if (do_loop_weight) {
+			const float *v_prev = slide_origdata_orig_vert_co(sod, l->prev->v);
+			const float *v_next = slide_origdata_orig_vert_co(sod, l->next->v);
+			const float dist = dist_signed_squared_to_corner_v3v3v3(sv->v->co, v_prev, sv->co_orig_3d, v_next, f_copy->no);
+			const float eps = 0.00001f;
+			loop_weights[j] = (dist >= 0.0f) ? 1.0f : ((dist <= -eps) ? 0.0f : (1.0f + (dist / eps)));
+		}
+	}
+
+	if (do_loop_weight) {
+		for (j = 0; j < sod->layer_math_map_num; j++) {
+			 BM_vert_loop_groups_data_layer_merge_weights(bm, sv->cd_loop_groups[j], sod->layer_math_map[j], loop_weights);
+		}
+	}
+	else {
+		for (j = 0; j < sod->layer_math_map_num; j++) {
+			 BM_vert_loop_groups_data_layer_merge(bm, sv->cd_loop_groups[j], sod->layer_math_map[j]);
 		}
 	}
 }
@@ -5305,33 +5366,13 @@ static void slide_origdata_interp_data(
 {
 	if (sod->use_origfaces) {
 		BMEditMesh *em = BKE_editmesh_from_object(t->obedit);
+		BMesh *bm = em->bm;
 		unsigned int i;
 
-		const int *layer_math_map = sod->layer_math_map;
-
 		for (i = 0; i < v_num; i++, sv = (void *)(((char *)sv) + v_stride)) {
 
 			if (sv->cd_loop_groups) {
-				BMIter fiter;
-				BMLoop *l;
-				int j;
-
-				BM_ITER_ELEM (l, &fiter, sv->v, BM_LOOPS_OF_VERT) {
-					BMFace *f_copy;  /* the copy of 'f' */
-
-					f_copy = BLI_ghash_lookup(sod->origfaces, l->f);
-
-					/* only loop data, no vertex data since that contains shape keys,
-					 * and we do not want to mess up other shape keys */
-					BM_loop_interp_from_face(em->bm, l, f_copy, false, is_final);
-
-					/* make sure face-attributes are correct (e.g. MTexPoly) */
-					BM_elem_attrs_copy(sod->bm_origfaces, em->bm, f_copy, l->f);
-				}
-
-				for (j = 0; j < sod->layer_math_map_num; j++) {
-					 BM_vert_loop_groups_data_layer_merge(em->bm, sv->cd_loop_groups[j], layer_math_map[j]);
-				}
+				slide_origdata_interp_data_vert(sod, bm, is_final, sv);
 			}
 		}
 	}
@@ -5351,6 +5392,11 @@ static void slide_origdata_free_date(
 			sod->origfaces = NULL;
 		}
 
+		if (sod->origverts) {
+			BLI_ghash_free(sod->origverts, NULL, NULL);
+			sod->origverts = NULL;
+		}
+
 		if (sod->arena) {
 			BLI_memarena_free(sod->arena);
 			sod->arena = NULL;
diff --git a/source/blender/editors/transform/transform.h b/source/blender/editors/transform/transform.h
index 84a81e8..8d6c693 100644
--- a/source/blender/editors/transform/transform.h
+++ b/source/blender/editors/transform/transform.h
@@ -204,19 +204,20 @@ struct GHash;
 typedef struct TransDataGenericSlideVert {
 	struct BMVert *v;
 	struct LinkNode **cd_loop_groups;
+	float co_

@@ Diff output truncated at 10240 characters. @@




More information about the Bf-blender-cvs mailing list