forked from bartvdbraak/blender
interpolate verts as well as loops for inset.
- add vertex option to BM_face_interp_from_face, also expose via python.
This commit is contained in:
parent
b9b23d697b
commit
c68ae745b6
@ -167,8 +167,8 @@ void BM_data_interp_face_vert_edge(BMesh *bm, BMVert *v1, BMVert *UNUSED(v2), BM
|
||||
*
|
||||
* \note Only handles loop customdata. multires is handled.
|
||||
*/
|
||||
void BM_face_interp_from_face_ex(BMesh *bm, BMFace *target, BMFace *source,
|
||||
void **blocks, float (*cos_2d)[2], float axis_mat[3][3])
|
||||
void BM_face_interp_from_face_ex(BMesh *bm, BMFace *target, BMFace *source, const bool do_vertex,
|
||||
void **blocks_l, void **blocks_v, float (*cos_2d)[2], float axis_mat[3][3])
|
||||
{
|
||||
BMLoop *l_iter;
|
||||
BMLoop *l_first;
|
||||
@ -186,16 +186,20 @@ void BM_face_interp_from_face_ex(BMesh *bm, BMFace *target, BMFace *source,
|
||||
do {
|
||||
mul_v2_m3v3(co, axis_mat, l_iter->v->co);
|
||||
interp_weights_poly_v2(w, cos_2d, source->len, co);
|
||||
CustomData_bmesh_interp(&bm->ldata, blocks, w, NULL, source->len, l_iter->head.data);
|
||||
CustomData_bmesh_interp(&bm->ldata, blocks_l, w, NULL, source->len, l_iter->head.data);
|
||||
if (do_vertex) {
|
||||
CustomData_bmesh_interp(&bm->vdata, blocks_v, w, NULL, source->len, l_iter->v->head.data);
|
||||
}
|
||||
} while (i++, (l_iter = l_iter->next) != l_first);
|
||||
}
|
||||
|
||||
void BM_face_interp_from_face(BMesh *bm, BMFace *target, BMFace *source)
|
||||
void BM_face_interp_from_face(BMesh *bm, BMFace *target, BMFace *source, const bool do_vertex)
|
||||
{
|
||||
BMLoop *l_iter;
|
||||
BMLoop *l_first;
|
||||
|
||||
void **blocks = BLI_array_alloca(blocks, source->len);
|
||||
void **blocks_l = BLI_array_alloca(blocks_l, source->len);
|
||||
void **blocks_v = do_vertex ? BLI_array_alloca(blocks_v, source->len) : NULL;
|
||||
float (*cos_2d)[2] = BLI_array_alloca(cos_2d, source->len);
|
||||
float axis_mat[3][3]; /* use normal to transform into 2d xy coords */
|
||||
int i;
|
||||
@ -207,11 +211,12 @@ void BM_face_interp_from_face(BMesh *bm, BMFace *target, BMFace *source)
|
||||
l_iter = l_first = BM_FACE_FIRST_LOOP(source);
|
||||
do {
|
||||
mul_v2_m3v3(cos_2d[i], axis_mat, l_iter->v->co);
|
||||
blocks[i] = l_iter->head.data;
|
||||
blocks_l[i] = l_iter->head.data;
|
||||
if (do_vertex) blocks_v[i] = l_iter->v->head.data;
|
||||
} while (i++, (l_iter = l_iter->next) != l_first);
|
||||
|
||||
BM_face_interp_from_face_ex(bm, target, source,
|
||||
blocks, cos_2d, axis_mat);
|
||||
BM_face_interp_from_face_ex(bm, target, source, do_vertex,
|
||||
blocks_l, blocks_v, cos_2d, axis_mat);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -42,11 +42,11 @@ void BM_data_layer_copy(BMesh *bm, CustomData *data, int type, int src_n, int d
|
||||
float BM_elem_float_data_get(CustomData *cd, void *element, int type);
|
||||
void BM_elem_float_data_set(CustomData *cd, void *element, int type, const float val);
|
||||
|
||||
void BM_face_interp_from_face_ex(BMesh *bm, BMFace *target, BMFace *source,
|
||||
void **blocks, float (*cos_2d)[2], float axis_mat[3][3]);
|
||||
void BM_face_interp_from_face(BMesh *bm, BMFace *target, BMFace *source);
|
||||
void BM_face_interp_from_face_ex(BMesh *bm, BMFace *target, BMFace *source, const bool do_vertex,
|
||||
void **blocks, void **blocks_v, float (*cos_2d)[2], float axis_mat[3][3]);
|
||||
void BM_face_interp_from_face(BMesh *bm, BMFace *target, BMFace *source, const bool do_vertex);
|
||||
void BM_loop_interp_from_face(BMesh *bm, BMLoop *target, BMFace *source,
|
||||
const bool do_vertex, const bool do_multires);
|
||||
const bool do_vertex, const bool do_multires);
|
||||
|
||||
void BM_face_multires_bounds_smooth(BMesh *bm, BMFace *f);
|
||||
|
||||
|
@ -169,7 +169,7 @@ void bmo_inset_individual_exec(BMesh *bm, BMOperator *op)
|
||||
/* Copy Face Data */
|
||||
/* interpolate loop data or just stretch */
|
||||
if (use_interpolate) {
|
||||
BM_face_interp_from_face(bm, f_new_inner, f);
|
||||
BM_face_interp_from_face(bm, f_new_inner, f, true);
|
||||
}
|
||||
else {
|
||||
BM_elem_attrs_copy(bm, bm, f, f_new_inner);
|
||||
@ -256,7 +256,8 @@ typedef struct SplitEdgeInfo {
|
||||
/* just enough of a face to store interpolation data we can use once the inset is done */
|
||||
typedef struct InterpFace {
|
||||
BMFace *f;
|
||||
void **blocks;
|
||||
void **blocks_l;
|
||||
void **blocks_v;
|
||||
float (*cos_2d)[2];
|
||||
float axis_mat[3][3];
|
||||
} InterpFace;
|
||||
@ -265,7 +266,8 @@ typedef struct InterpFace {
|
||||
static void bm_interp_face_store(InterpFace *iface, BMesh *bm, BMFace *f, MemArena *interp_arena)
|
||||
{
|
||||
BMLoop *l_iter, *l_first;
|
||||
void **blocks = iface->blocks = BLI_memarena_alloc(interp_arena, sizeof(*iface->blocks) * f->len);
|
||||
void **blocks_l = iface->blocks_l = BLI_memarena_alloc(interp_arena, sizeof(*iface->blocks_l) * f->len);
|
||||
void **blocks_v = iface->blocks_v = BLI_memarena_alloc(interp_arena, sizeof(*iface->blocks_v) * f->len);
|
||||
float (*cos_2d)[2] = iface->cos_2d = BLI_memarena_alloc(interp_arena, sizeof(*iface->cos_2d) * f->len);
|
||||
void *axis_mat = iface->axis_mat;
|
||||
int i;
|
||||
@ -278,22 +280,27 @@ static void bm_interp_face_store(InterpFace *iface, BMesh *bm, BMFace *f, MemAre
|
||||
l_iter = l_first = BM_FACE_FIRST_LOOP(f);
|
||||
do {
|
||||
mul_v2_m3v3(cos_2d[i], axis_mat, l_iter->v->co);
|
||||
blocks[i] = NULL;
|
||||
CustomData_bmesh_copy_data(&bm->ldata, &bm->ldata, l_iter->head.data, &blocks[i]);
|
||||
blocks_l[i] = NULL;
|
||||
CustomData_bmesh_copy_data(&bm->ldata, &bm->ldata, l_iter->head.data, &blocks_l[i]);
|
||||
/* if we were not modifying the loops later we would do... */
|
||||
// blocks[i] = l_iter->head.data;
|
||||
|
||||
blocks_v[i] = NULL;
|
||||
CustomData_bmesh_copy_data(&bm->vdata, &bm->vdata, l_iter->v->head.data, &blocks_v[i]);
|
||||
|
||||
/* use later for index lookups */
|
||||
BM_elem_index_set(l_iter, i); /* set_ok */
|
||||
} while (i++, (l_iter = l_iter->next) != l_first);
|
||||
}
|
||||
static void bm_interp_face_free(InterpFace *iface, BMesh *bm)
|
||||
{
|
||||
void **blocks = iface->blocks;
|
||||
void **blocks_l = iface->blocks_l;
|
||||
void **blocks_v = iface->blocks_v;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < iface->f->len; i++) {
|
||||
CustomData_bmesh_free_block(&bm->ldata, &blocks[i]);
|
||||
CustomData_bmesh_free_block(&bm->ldata, &blocks_l[i]);
|
||||
CustomData_bmesh_free_block(&bm->vdata, &blocks_v[i]);
|
||||
}
|
||||
}
|
||||
|
||||
@ -724,8 +731,8 @@ void bmo_inset_region_exec(BMesh *bm, BMOperator *op)
|
||||
for (i = 0; i < iface_array_len; i++) {
|
||||
if (iface_array[i]) {
|
||||
InterpFace *iface = iface_array[i];
|
||||
BM_face_interp_from_face_ex(bm, iface->f, iface->f,
|
||||
iface->blocks, iface->cos_2d, iface->axis_mat);
|
||||
BM_face_interp_from_face_ex(bm, iface->f, iface->f, true,
|
||||
iface->blocks_l, iface->blocks_v, iface->cos_2d, iface->axis_mat);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -800,8 +807,8 @@ void bmo_inset_region_exec(BMesh *bm, BMOperator *op)
|
||||
InterpFace *iface = iface_array[BM_elem_index_get(es->l->f)];
|
||||
const int i_a = BM_elem_index_get(l_a_other);
|
||||
const int i_b = BM_elem_index_get(l_b_other);
|
||||
CustomData_bmesh_copy_data(&bm->ldata, &bm->ldata, iface->blocks[i_a], &l_b->head.data);
|
||||
CustomData_bmesh_copy_data(&bm->ldata, &bm->ldata, iface->blocks[i_b], &l_a->head.data);
|
||||
CustomData_bmesh_copy_data(&bm->ldata, &bm->ldata, iface->blocks_l[i_a], &l_b->head.data);
|
||||
CustomData_bmesh_copy_data(&bm->ldata, &bm->ldata, iface->blocks_l[i_b], &l_a->head.data);
|
||||
}
|
||||
else {
|
||||
BM_elem_attrs_copy(bm, bm, l_a_other, l_b);
|
||||
|
@ -1597,21 +1597,24 @@ static PyObject *bpy_bmedge_normal_update(BPy_BMEdge *self)
|
||||
* ---- */
|
||||
|
||||
PyDoc_STRVAR(bpy_bmface_copy_from_face_interp_doc,
|
||||
".. method:: copy_from_face_interp(face)\n"
|
||||
".. method:: copy_from_face_interp(face, vert=True)\n"
|
||||
"\n"
|
||||
" Interpolate the customdata from another face onto this one (faces should overlap).\n"
|
||||
"\n"
|
||||
" :arg face: The face to interpolate data from.\n"
|
||||
" :type face: :class:`BMFace`\n"
|
||||
" :arg vert: When True, also copy vertex data.\n"
|
||||
" :type vert: boolean\n"
|
||||
);
|
||||
static PyObject *bpy_bmface_copy_from_face_interp(BPy_BMFace *self, PyObject *args)
|
||||
{
|
||||
BPy_BMFace *py_face = NULL;
|
||||
int do_vertex = true;
|
||||
|
||||
BPY_BM_CHECK_OBJ(self);
|
||||
|
||||
if (!PyArg_ParseTuple(args, "O!:BMFace.copy_from_face_interp",
|
||||
&BPy_BMFace_Type, &py_face))
|
||||
if (!PyArg_ParseTuple(args, "O!|i:BMFace.copy_from_face_interp",
|
||||
&BPy_BMFace_Type, &py_face, &do_vertex))
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
@ -1620,7 +1623,7 @@ static PyObject *bpy_bmface_copy_from_face_interp(BPy_BMFace *self, PyObject *ar
|
||||
|
||||
BPY_BM_CHECK_SOURCE_OBJ(py_face, bm, "BMFace.copy_from_face_interp(face)");
|
||||
|
||||
BM_face_interp_from_face(bm, self->f, py_face->f);
|
||||
BM_face_interp_from_face(bm, self->f, py_face->f, do_vertex);
|
||||
|
||||
Py_RETURN_NONE;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user