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
path: root/source
diff options
context:
space:
mode:
authorCampbell Barton <ideasman42@gmail.com>2015-02-16 10:49:18 +0300
committerCampbell Barton <ideasman42@gmail.com>2015-02-16 10:49:18 +0300
commit58652301dee685f67edf03c2bfcfbafe15a7cb6e (patch)
tree812b7cf32e5f0437355780078f44bf4830f504a4 /source
parent421d0f3bdea56ef056372476a24b1fc5e5ee06e5 (diff)
Vert/Edge Slide: better UV interpolation
Ignore faces which the sliding vert is outside of.
Diffstat (limited to 'source')
-rw-r--r--source/blender/bmesh/intern/bmesh_interp.c69
-rw-r--r--source/blender/bmesh/intern/bmesh_interp.h1
-rw-r--r--source/blender/editors/transform/transform.c90
-rw-r--r--source/blender/editors/transform/transform.h10
4 files changed, 140 insertions, 30 deletions
diff --git a/source/blender/bmesh/intern/bmesh_interp.c b/source/blender/bmesh/intern/bmesh_interp.c
index a88f38caf78..d60c01bd0ff 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 cd6d5e2731d..1c1c063b7ed 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 1740e54abbf..193bcbb3691 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 84a81e8b3d8..8d6c693b14a 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_orig_3d[3];
} TransDataGenericSlideVert;
typedef struct TransDataEdgeSlideVert {
/* TransDataGenericSlideVert */
struct BMVert *v;
struct LinkNode **cd_loop_groups;
- /* end generic */
-
- struct BMVert *v_a, *v_b;
float v_co_orig[3];
+ /* end generic */
float edge_len;
+ struct BMVert *v_a, *v_b;
+
/* add origvert.co to get the original locations */
float dir_a[3], dir_b[3];
@@ -228,6 +229,7 @@ typedef struct TransDataEdgeSlideVert {
typedef struct SlideOrigData {
/* flag that is set when origfaces is initialized */
bool use_origfaces;
+ struct GHash *origverts; /* map {BMVert: TransDataGenericSlideVert} */
struct GHash *origfaces;
struct BMesh *bm_origfaces;
@@ -261,9 +263,9 @@ typedef struct TransDataVertSlideVert {
/* TransDataGenericSlideVert */
BMVert *v;
struct LinkNode **cd_loop_groups;
+ float co_orig_3d[3];
/* end generic */
- float co_orig_3d[3];
float co_orig_2d[2];
float (*co_link_orig_3d)[3];
float (*co_link_orig_2d)[2];