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
diff options
context:
space:
mode:
Diffstat (limited to 'source/blender/bmesh/operators/bmo_subdivide.c')
-rw-r--r--source/blender/bmesh/operators/bmo_subdivide.c209
1 files changed, 109 insertions, 100 deletions
diff --git a/source/blender/bmesh/operators/bmo_subdivide.c b/source/blender/bmesh/operators/bmo_subdivide.c
index fc507cdbd21..45e3c8d193d 100644
--- a/source/blender/bmesh/operators/bmo_subdivide.c
+++ b/source/blender/bmesh/operators/bmo_subdivide.c
@@ -32,6 +32,7 @@
#include "BLI_rand.h"
#include "BLI_array.h"
#include "BLI_noise.h"
+#include "BLI_stack.h"
#include "BKE_customdata.h"
@@ -79,8 +80,9 @@ static void bmo_subd_init_shape_info(BMesh *bm, SubDParams *params)
}
-typedef void (*subd_pattern_fill_fp)(BMesh *bm, BMFace *face, BMVert **verts,
- const SubDParams *params);
+typedef void (*subd_pattern_fill_fp)(
+ BMesh *bm, BMFace *face, BMVert **verts,
+ const SubDParams *params);
/*
* note: this is a pattern-based edge subdivider.
@@ -162,10 +164,11 @@ static BMEdge *connect_smallest_face(BMesh *bm, BMVert *v_a, BMVert *v_b, BMFace
return NULL;
}
/* calculates offset for co, based on fractal, sphere or smooth settings */
-static void alter_co(BMVert *v, BMEdge *UNUSED(origed), const SubDParams *params, float perc,
- BMVert *vsta, BMVert *vend)
+static void alter_co(
+ BMVert *v, BMEdge *UNUSED(e_orig),
+ const SubDParams *params, const float perc,
+ const BMVert *v_a, const BMVert *v_b)
{
- float tvec[3], fac;
float *co = BM_ELEM_CD_GET_VOID_P(v, params->shape_info.cd_vert_shape_offset_tmp);
int i;
@@ -177,28 +180,26 @@ static void alter_co(BMVert *v, BMEdge *UNUSED(origed), const SubDParams *params
}
else if (params->use_smooth) {
/* we calculate an offset vector vec1[], to be added to *co */
- float len, nor[3], nor1[3], nor2[3], val;
+ float dir[3], tvec[3];
+ float fac, len, val;
- sub_v3_v3v3(nor, vsta->co, vend->co);
- len = 0.5f * normalize_v3(nor);
-
- copy_v3_v3(nor1, vsta->no);
- copy_v3_v3(nor2, vend->no);
+ sub_v3_v3v3(dir, v_a->co, v_b->co);
+ len = (float)M_SQRT1_2 * normalize_v3(dir);
/* cosine angle */
- fac = dot_v3v3(nor, nor1);
- mul_v3_v3fl(tvec, nor1, fac);
+ fac = dot_v3v3(dir, v_a->no);
+ mul_v3_v3fl(tvec, v_a->no, fac);
/* cosine angle */
- fac = -dot_v3v3(nor, nor2);
- madd_v3_v3fl(tvec, nor2, fac);
+ fac = -dot_v3v3(dir, v_b->no);
+ madd_v3_v3fl(tvec, v_b->no, fac);
/* falloff for multi subdivide */
val = fabsf(1.0f - 2.0f * fabsf(0.5f - perc));
val = bmesh_subd_falloff_calc(params->smooth_falloff, val);
if (params->use_smooth_even) {
- val *= BM_vert_calc_shell_factor(v);
+ val *= shell_v3v3_mid_normalized_to_dist(v_a->no, v_b->no);
}
mul_v3_fl(tvec, params->smooth * val * len);
@@ -207,12 +208,13 @@ static void alter_co(BMVert *v, BMEdge *UNUSED(origed), const SubDParams *params
}
if (params->use_fractal) {
- const float len = len_v3v3(vsta->co, vend->co);
- float normal[3], co2[3], base1[3], base2[3];
+ float normal[3], co2[3], base1[3], base2[3], tvec[3];
+ const float len = len_v3v3(v_a->co, v_b->co);
+ float fac;
fac = params->fractal * len;
- mid_v3_v3v3(normal, vsta->no, vend->no);
+ mid_v3_v3v3(normal, v_a->no, v_b->no);
ortho_basis_v3v3_v3(base1, base2, normal);
add_v3_v3v3(co2, v->co, params->fractal_ofs);
@@ -233,9 +235,12 @@ static void alter_co(BMVert *v, BMEdge *UNUSED(origed), const SubDParams *params
* this by getting the normals and coords for each shape key and
* re-calculate the smooth value for each but this is quite involved.
* for now its ok to simply apply the difference IMHO - campbell */
- sub_v3_v3v3(tvec, v->co, co);
if (params->shape_info.totlayer > 1) {
+ float tvec[3];
+
+ sub_v3_v3v3(tvec, v->co, co);
+
/* skip the last layer since its the temp */
i = params->shape_info.totlayer - 1;
co = BM_ELEM_CD_GET_VOID_P(v, params->shape_info.cd_vert_shape_offset);
@@ -249,19 +254,21 @@ static void alter_co(BMVert *v, BMEdge *UNUSED(origed), const SubDParams *params
/* assumes in the edge is the correct interpolated vertices already */
/* percent defines the interpolation, rad and flag are for special options */
/* results in new vertex with correct coordinate, vertex normal and weight group info */
-static BMVert *bm_subdivide_edge_addvert(BMesh *bm, BMEdge *edge, BMEdge *oedge,
- const SubDParams *params, float percent,
- float percent2,
- BMEdge **out, BMVert *vsta, BMVert *vend)
+static BMVert *bm_subdivide_edge_addvert(
+ BMesh *bm, BMEdge *edge, BMEdge *e_orig,
+ const SubDParams *params,
+ const float factor_edge_split, const float factor_subd,
+ BMVert *v_a, BMVert *v_b,
+ BMEdge **r_edge)
{
- BMVert *ev;
+ BMVert *v_new;
- ev = BM_edge_split(bm, edge, edge->v1, out, percent);
+ v_new = BM_edge_split(bm, edge, edge->v1, r_edge, factor_edge_split);
- BMO_elem_flag_enable(bm, ev, ELE_INNER);
+ BMO_elem_flag_enable(bm, v_new, ELE_INNER);
/* offset for smooth or sphere or fractal */
- alter_co(ev, oedge, params, percent2, vsta, vend);
+ alter_co(v_new, e_orig, params, factor_subd, v_a, v_b);
#if 0 //BMESH_TODO
/* clip if needed by mirror modifier */
@@ -278,35 +285,40 @@ static BMVert *bm_subdivide_edge_addvert(BMesh *bm, BMEdge *edge, BMEdge *oedge,
}
#endif
- interp_v3_v3v3(ev->no, vsta->no, vend->no, percent2);
- normalize_v3(ev->no);
+ interp_v3_v3v3(v_new->no, v_a->no, v_b->no, factor_subd);
+ normalize_v3(v_new->no);
- return ev;
+ return v_new;
}
-static BMVert *subdivideedgenum(BMesh *bm, BMEdge *edge, BMEdge *oedge,
- int curpoint, int totpoint, const SubDParams *params,
- BMEdge **newe, BMVert *vsta, BMVert *vend)
+static BMVert *subdivide_edge_num(
+ BMesh *bm, BMEdge *edge, BMEdge *e_orig,
+ int curpoint, int totpoint, const SubDParams *params,
+ BMVert *v_a, BMVert *v_b,
+ BMEdge **r_edge)
{
- BMVert *ev;
- float percent, percent2 = 0.0f;
+ BMVert *v_new;
+ float factor_edge_split, factor_subd;
if (BMO_elem_flag_test(bm, edge, EDGE_PERCENT) && totpoint == 1) {
- percent = BMO_slot_map_float_get(params->slot_edge_percents, edge);
+ factor_edge_split = BMO_slot_map_float_get(params->slot_edge_percents, edge);
+ factor_subd = 0.0f;
}
else {
- percent = 1.0f / (float)(totpoint + 1 - curpoint);
- percent2 = (float)(curpoint + 1) / (float)(totpoint + 1);
-
+ factor_edge_split = 1.0f / (float)(totpoint + 1 - curpoint);
+ factor_subd = (float)(curpoint + 1) / (float)(totpoint + 1);
}
- ev = bm_subdivide_edge_addvert(bm, edge, oedge, params, percent,
- percent2, newe, vsta, vend);
- return ev;
+ v_new = bm_subdivide_edge_addvert(
+ bm, edge, e_orig, params,
+ factor_edge_split, factor_subd,
+ v_a, v_b, r_edge);
+ return v_new;
}
-static void bm_subdivide_multicut(BMesh *bm, BMEdge *edge, const SubDParams *params,
- BMVert *vsta, BMVert *vend)
+static void bm_subdivide_multicut(
+ BMesh *bm, BMEdge *edge, const SubDParams *params,
+ BMVert *v_a, BMVert *v_b)
{
BMEdge *eed = edge, *e_new, e_tmp = *edge;
BMVert *v, v1_tmp = *edge->v1, v2_tmp = *edge->v2, *v1 = edge->v1, *v2 = edge->v2;
@@ -316,15 +328,11 @@ static void bm_subdivide_multicut(BMesh *bm, BMEdge *edge, const SubDParams *par
e_tmp.v2 = &v2_tmp;
for (i = 0; i < numcuts; i++) {
- v = subdivideedgenum(bm, eed, &e_tmp, i, params->numcuts, params, &e_new, vsta, vend);
-
- BMO_elem_flag_enable(bm, v, SUBD_SPLIT);
- BMO_elem_flag_enable(bm, eed, SUBD_SPLIT);
- BMO_elem_flag_enable(bm, e_new, SUBD_SPLIT);
+ v = subdivide_edge_num(bm, eed, &e_tmp, i, params->numcuts, params, v_a, v_b, &e_new);
- BMO_elem_flag_enable(bm, v, ELE_SPLIT);
- BMO_elem_flag_enable(bm, eed, ELE_SPLIT);
- BMO_elem_flag_enable(bm, e_new, SUBD_SPLIT);
+ BMO_elem_flag_enable(bm, v, SUBD_SPLIT | ELE_SPLIT);
+ BMO_elem_flag_enable(bm, eed, SUBD_SPLIT | ELE_SPLIT);
+ BMO_elem_flag_enable(bm, e_new, SUBD_SPLIT | ELE_SPLIT);
BM_CHECK_ELEMENT(v);
if (v->e) BM_CHECK_ELEMENT(v->e);
@@ -437,7 +445,7 @@ static void quad_2edge_split_innervert(BMesh *bm, BMFace *UNUSED(face), BMVert *
e = connect_smallest_face(bm, verts[i], verts[numcuts + (numcuts - i)], &f_new);
e_tmp = *e;
- v = bm_subdivide_edge_addvert(bm, e, &e_tmp, params, 0.5f, 0.5f, &e_new, e->v1, e->v2);
+ v = bm_subdivide_edge_addvert(bm, e, &e_tmp, params, 0.5f, 0.5f, e->v1, e->v2, &e_new);
if (i != numcuts - 1) {
connect_smallest_face(bm, v_last, v, &f_new);
@@ -580,8 +588,7 @@ static void quad_4edge_subdivide(BMesh *bm, BMFace *UNUSED(face), BMVert **verts
e_tmp = *e;
for (a = 0; a < numcuts; a++) {
- v = subdivideedgenum(bm, e, &e_tmp, a, numcuts, params, &e_new,
- v1, v2);
+ v = subdivide_edge_num(bm, e, &e_tmp, a, numcuts, params, v1, v2, &e_new);
BMESH_ASSERT(v != NULL);
@@ -688,8 +695,7 @@ static void tri_3edge_subdivide(BMesh *bm, BMFace *UNUSED(face), BMVert **verts,
e_tmp.v1 = &v1_tmp;
e_tmp.v2 = &v2_tmp;
for (j = 0; j < i; j++) {
- v = subdivideedgenum(bm, e, &e_tmp, j, i, params, &e_new,
- verts[a], verts[b]);
+ v = subdivide_edge_num(bm, e, &e_tmp, j, i, params, verts[a], verts[b], &e_new);
lines[i + 1][j + 1] = v;
BMO_elem_flag_enable(bm, e_new, ELE_INNER);
@@ -766,8 +772,7 @@ void bmo_subdivide_edges_exec(BMesh *bm, BMOperator *op)
BMOpSlot *einput;
const SubDPattern *pat;
SubDParams params;
- SubDFaceData *facedata = NULL;
- BLI_array_declare(facedata);
+ BLI_Stack *facedata;
BMIter viter, fiter, liter;
BMVert *v, **verts = NULL;
BMEdge *edge;
@@ -782,7 +787,7 @@ void bmo_subdivide_edges_exec(BMesh *bm, BMOperator *op)
BLI_array_declare(verts);
float smooth, fractal, along_normal;
bool use_sphere, use_single_edge, use_grid_fill, use_only_quads;
- int cornertype, seed, i, j, matched, a, b, numcuts, totesel, smooth_falloff;
+ int cornertype, seed, i, j, a, b, numcuts, totesel, smooth_falloff;
BMO_slot_buffer_flag_enable(bm, op->slots_in, "edges", BM_EDGE, SUBD_SPLIT);
@@ -802,13 +807,13 @@ void bmo_subdivide_edges_exec(BMesh *bm, BMOperator *op)
patterns[1] = NULL;
/* straight cut is patterns[1] == NULL */
switch (cornertype) {
- case SUBD_PATH:
+ case SUBD_CORNER_PATH:
patterns[1] = &quad_2edge_path;
break;
- case SUBD_INNERVERT:
+ case SUBD_CORNER_INNERVERT:
patterns[1] = &quad_2edge_innervert;
break;
- case SUBD_FAN:
+ case SUBD_CORNER_FAN:
patterns[1] = &quad_2edge_fan;
break;
}
@@ -875,9 +880,12 @@ void bmo_subdivide_edges_exec(BMesh *bm, BMOperator *op)
BM_EDGE, EDGE_PERCENT);
+ facedata = BLI_stack_new(sizeof(SubDFaceData), __func__);
+
BM_ITER_MESH (face, &fiter, bm, BM_FACES_OF_MESH) {
BMEdge *e1 = NULL, *e2 = NULL;
float vec1[3], vec2[3];
+ bool matched = false;
/* skip non-quads if requested */
if (use_only_quads && face->len != 4)
@@ -891,8 +899,6 @@ void bmo_subdivide_edges_exec(BMesh *bm, BMOperator *op)
BLI_array_grow_items(edges, face->len);
BLI_array_grow_items(verts, face->len);
- matched = 0;
-
totesel = 0;
BM_ITER_ELEM_INDEX (l_new, &liter, face, BM_LOOPS_OF_FACE, i) {
edges[i] = l_new->e;
@@ -930,12 +936,13 @@ void bmo_subdivide_edges_exec(BMesh *bm, BMOperator *op)
}
}
if (matched) {
- BLI_array_grow_one(facedata);
- b = BLI_array_count(facedata) - 1;
- facedata[b].pat = pat;
- facedata[b].start = verts[i];
- facedata[b].face = face;
- facedata[b].totedgesel = totesel;
+ SubDFaceData *fd;
+
+ fd = BLI_stack_push_r(facedata);
+ fd->pat = pat;
+ fd->start = verts[i];
+ fd->face = face;
+ fd->totedgesel = totesel;
BMO_elem_flag_enable(bm, face, SUBD_SPLIT);
break;
}
@@ -966,15 +973,15 @@ void bmo_subdivide_edges_exec(BMesh *bm, BMOperator *op)
}
}
if (matched) {
- BLI_array_grow_one(facedata);
- j = BLI_array_count(facedata) - 1;
+ SubDFaceData *fd;
BMO_elem_flag_enable(bm, face, SUBD_SPLIT);
- facedata[j].pat = pat;
- facedata[j].start = verts[a];
- facedata[j].face = face;
- facedata[j].totedgesel = totesel;
+ fd = BLI_stack_push_r(facedata);
+ fd->pat = pat;
+ fd->start = verts[a];
+ fd->face = face;
+ fd->totedgesel = totesel;
break;
}
}
@@ -982,16 +989,16 @@ void bmo_subdivide_edges_exec(BMesh *bm, BMOperator *op)
}
if (!matched && totesel) {
- BLI_array_grow_one(facedata);
- j = BLI_array_count(facedata) - 1;
+ SubDFaceData *fd;
BMO_elem_flag_enable(bm, face, SUBD_SPLIT);
/* must initialize all members here */
- facedata[j].start = NULL;
- facedata[j].pat = NULL;
- facedata[j].totedgesel = totesel;
- facedata[j].face = face;
+ fd = BLI_stack_push_r(facedata);
+ fd->start = NULL;
+ fd->pat = NULL;
+ fd->totedgesel = totesel;
+ fd->face = face;
}
}
@@ -1009,16 +1016,17 @@ void bmo_subdivide_edges_exec(BMesh *bm, BMOperator *op)
copy_v3_v3(v->co, co);
}
- i = 0;
- for (i = 0; i < BLI_array_count(facedata); i++) {
- face = facedata[i].face;
+ for (; !BLI_stack_is_empty(facedata); BLI_stack_discard(facedata)) {
+ SubDFaceData *fd = BLI_stack_peek(facedata);
+
+ face = fd->face;
/* figure out which pattern to use */
BLI_array_empty(verts);
- pat = facedata[i].pat;
+ pat = fd->pat;
- if (!pat && facedata[i].totedgesel == 2) {
+ if (!pat && fd->totedgesel == 2) {
int vlen;
/* ok, no pattern. we still may be able to do something */
@@ -1079,7 +1087,7 @@ void bmo_subdivide_edges_exec(BMesh *bm, BMOperator *op)
BMIter other_fiter;
BM_ITER_ELEM (other_loop, &other_fiter, loops[a]->v, BM_LOOPS_OF_VERT) {
if (other_loop->f != face) {
- if (BM_vert_in_face(other_loop->f, loops[b]->v)) {
+ if (BM_vert_in_face(loops[b]->v, other_loop->f)) {
/* we assume that these verts are not making an edge in the face */
BLI_assert(other_loop->prev->v != loops[a]->v);
BLI_assert(other_loop->next->v != loops[a]->v);
@@ -1131,7 +1139,7 @@ void bmo_subdivide_edges_exec(BMesh *bm, BMOperator *op)
a = 0;
BM_ITER_ELEM_INDEX (l_new, &liter, face, BM_LOOPS_OF_FACE, j) {
- if (l_new->v == facedata[i].start) {
+ if (l_new->v == fd->start) {
a = j + 1;
break;
}
@@ -1156,7 +1164,7 @@ void bmo_subdivide_edges_exec(BMesh *bm, BMOperator *op)
BM_data_layer_free_n(bm, &bm->vdata, CD_SHAPEKEY, params.shape_info.tmpkey);
- if (facedata) BLI_array_free(facedata);
+ BLI_stack_free(facedata);
if (edges) BLI_array_free(edges);
if (verts) BLI_array_free(verts);
BLI_array_free(loops_split);
@@ -1169,14 +1177,15 @@ void bmo_subdivide_edges_exec(BMesh *bm, BMOperator *op)
}
/* editmesh-emulating function */
-void BM_mesh_esubdivide(BMesh *bm, const char edge_hflag,
- const float smooth, const short smooth_falloff, const bool use_smooth_even,
- const float fractal, const float along_normal,
- const int numcuts,
- const int seltype, const int cornertype,
- const short use_single_edge, const short use_grid_fill,
- const short use_only_quads,
- const int seed)
+void BM_mesh_esubdivide(
+ BMesh *bm, const char edge_hflag,
+ const float smooth, const short smooth_falloff, const bool use_smooth_even,
+ const float fractal, const float along_normal,
+ const int numcuts,
+ const int seltype, const int cornertype,
+ const short use_single_edge, const short use_grid_fill,
+ const short use_only_quads,
+ const int seed)
{
BMOperator op;