diff options
author | Martin Felke <martin.felke@googlemail.com> | 2015-03-17 22:48:03 +0300 |
---|---|---|
committer | Martin Felke <martin.felke@googlemail.com> | 2015-03-17 22:48:03 +0300 |
commit | 14a023abddcd27f8084945deb0e7609bebf54d7e (patch) | |
tree | 30ac552a0726f4f022ffd1d1e291d10aa3bb153c /source/blender/blenkernel/intern/fracture_util.c | |
parent | d21c1dc1b44c6bd8220a326b0f0bdc6b2bd74883 (diff) |
refactoring of FractureModifier: split very long functions into more, shorter ones
Diffstat (limited to 'source/blender/blenkernel/intern/fracture_util.c')
-rw-r--r-- | source/blender/blenkernel/intern/fracture_util.c | 747 |
1 files changed, 406 insertions, 341 deletions
diff --git a/source/blender/blenkernel/intern/fracture_util.c b/source/blender/blenkernel/intern/fracture_util.c index 8e15f4f3aea..c6ab51a5056 100644 --- a/source/blender/blenkernel/intern/fracture_util.c +++ b/source/blender/blenkernel/intern/fracture_util.c @@ -100,11 +100,69 @@ void uv_transform(float uv[][2], int num_uv, float mat[2][2]) } } +static void do_unwrap(MPoly *mp, MVert *mvert, MLoop* mloop, int i, MLoopUV **mluv, BoxPack **boxpack) +{ + MLoop *ml; + int j = 0; + float (*verts)[3] = MEM_mallocN(sizeof(float[3]) * mp->totloop, "unwrap_shard_dm verts"); + float nor[3]; + float mat[3][3]; + float (*uv)[2] = MEM_mallocN(sizeof(float[2]) * mp->totloop, "unwrap_shard_dm_uv"); + BoxPack *box; + float uvbbox[2][2]; + float angle; + + /* uv unwrap cells, so inner faces get a uv map */ + for (j = 0; j < mp->totloop; j++) { + ml = mloop + mp->loopstart + j; + copy_v3_v3(verts[j], (mvert + ml->v)->co); + } + + normal_poly_v3(nor, (const float (*)[3])verts, mp->totloop); + normalize_v3(nor); + axis_dominant_v3_to_m3(mat, nor); + + for (j = 0; j < mp->totloop; j++) { + mul_v2_m3v3(uv[j], mat, verts[j]); + } + + /* rotate uvs for better packing */ + angle = BLI_convexhull_aabb_fit_points_2d((const float (*)[2])uv, mp->totloop); + + if (angle != 0.0f) { + float mat[2][2]; + angle_to_mat2(mat, angle); + uv_transform((float (*)[2])uv, mp->totloop, mat); + } + + /* prepare box packing... one poly is a box */ + box = (*boxpack) + i; + uv_bbox((float (*)[2])uv, mp->totloop, uvbbox[0], uvbbox[1]); + + uvbbox[0][0] = -uvbbox[0][0]; + uvbbox[0][1] = -uvbbox[0][1]; + + uv_translate((float (*)[2])uv, mp->totloop, uvbbox[0]); + + box->w = uvbbox[1][0] + uvbbox[0][0]; + box->h = uvbbox[1][1] + uvbbox[0][1]; + box->index = i; + + /* copy coords back */ + for (j = 0; j < mp->totloop; j++) { + copy_v2_v2((*mluv)[j + mp->loopstart].uv, uv[j]); + (*mluv)[j + mp->loopstart].flag = 0; + } + + MEM_freeN(uv); + MEM_freeN(verts); +} + void unwrap_shard_dm(DerivedMesh *dm) { - MPoly *mpoly, *mp; - MLoop *mloop; MVert *mvert; + MLoop *mloop; + MPoly *mpoly, *mp; int totpoly, i = 0; MLoopUV *mluv = MEM_callocN(sizeof(MLoopUV) * dm->numLoopData, "mluv"); BoxPack *boxpack = MEM_mallocN(sizeof(BoxPack) * dm->numPolyData, "boxpack"); @@ -116,60 +174,7 @@ void unwrap_shard_dm(DerivedMesh *dm) mloop = dm->getLoopArray(dm); totpoly = dm->getNumPolys(dm); for (i = 0, mp = mpoly; i < totpoly; i++, mp++) { - MLoop *ml; - int j = 0; - float (*verts)[3] = MEM_mallocN(sizeof(float[3]) * mp->totloop, "unwrap_shard_dm verts"); - float nor[3]; - float mat[3][3]; - float (*uv)[2] = MEM_mallocN(sizeof(float[2]) * mp->totloop, "unwrap_shard_dm_uv"); - BoxPack *box; - float uvbbox[2][2]; - float angle; - - /* uv unwrap cells, so inner faces get a uv map */ - for (j = 0; j < mp->totloop; j++) { - ml = mloop + mp->loopstart + j; - copy_v3_v3(verts[j], (mvert + ml->v)->co); - } - - normal_poly_v3(nor, (const float (*)[3])verts, mp->totloop); - normalize_v3(nor); - axis_dominant_v3_to_m3(mat, nor); - - for (j = 0; j < mp->totloop; j++) { - mul_v2_m3v3(uv[j], mat, verts[j]); - } - - /* rotate uvs for better packing */ - angle = BLI_convexhull_aabb_fit_points_2d((const float (*)[2])uv, mp->totloop); - - if (angle != 0.0f) { - float mat[2][2]; - angle_to_mat2(mat, angle); - uv_transform((float (*)[2])uv, mp->totloop, mat); - } - - /* prepare box packing... one poly is a box */ - box = boxpack + i; - uv_bbox((float (*)[2])uv, mp->totloop, uvbbox[0], uvbbox[1]); - - uvbbox[0][0] = -uvbbox[0][0]; - uvbbox[0][1] = -uvbbox[0][1]; - - uv_translate((float (*)[2])uv, mp->totloop, uvbbox[0]); - - box->w = uvbbox[1][0] + uvbbox[0][0]; - box->h = uvbbox[1][1] + uvbbox[0][1]; - box->index = i; - - /* copy coords back */ - for (j = 0; j < mp->totloop; j++) { - copy_v2_v2(mluv[j + mp->loopstart].uv, uv[j]); - mluv[j + mp->loopstart].flag = 0; - } - - MEM_freeN(uv); - MEM_freeN(verts); + do_unwrap(mp, mvert, mloop, i, &mluv, &boxpack); } /* do box packing and match uvs according to it */ @@ -282,217 +287,285 @@ static bool compare_dm_size(DerivedMesh *dmOld, DerivedMesh *dmNew) return v2 <= (v1 + 0.000001); } -Shard *BKE_fracture_shard_boolean(Object *obj, DerivedMesh *dm_parent, Shard *child, short inner_material_index, int num_cuts, float fractal, Shard** other, float mat[4][4], float radius, bool use_smooth_inner, int num_levels) +static bool do_other_output(DerivedMesh** other_dm, Shard** other, DerivedMesh** output_dm, DerivedMesh** left_dm, float mat[4][4]) { - Shard *output_s; - DerivedMesh *left_dm, *right_dm, *output_dm, *other_dm; - MPoly *mpoly, *mp; - BMesh* bm = NULL; - int totpoly, i = 0; - BMFace* f; - BMIter iter; - - if (other != NULL && mat != NULL) + if (*other_dm) { - /*create a grid plane */ - - bm = BM_mesh_create(&bm_mesh_allocsize_default); - BMO_op_callf(bm, (BMO_FLAG_DEFAULTS & ~BMO_FLAG_RESPECT_HIDE), - "create_grid x_segments=%i y_segments=%i size=%f matrix=%m4", - 1, 1, radius*1.4, mat); + *other = BKE_create_fracture_shard((*other_dm)->getVertArray(*other_dm), + (*other_dm)->getPolyArray(*other_dm), + (*other_dm)->getLoopArray(*other_dm), + (*other_dm)->getNumVerts(*other_dm), + (*other_dm)->getNumPolys(*other_dm), + (*other_dm)->getNumLoops(*other_dm), + true); + + *other = BKE_custom_data_to_shard(*other, *other_dm); + + #if 0 + /* XXX TODO this might be wrong by now ... */ + output_s->neighbor_count = child->neighbor_count; + output_s->neighbor_ids = MEM_mallocN(sizeof(int) * child->neighbor_count, __func__); + memcpy(output_s->neighbor_ids, child->neighbor_ids, sizeof(int) * child->neighbor_count); + #endif + BKE_fracture_shard_center_centroid(*other, (*other)->centroid); - /*subdivide the plane fractally*/ - for (i = 0; i < num_levels; i++) + /* free the temp derivedmesh */ + (*other_dm)->needsFree = 1; + (*other_dm)->release(*other_dm); + *other_dm = NULL; + } + else + { + if (other != NULL) + *other = NULL; + if (*left_dm != NULL) { + (*left_dm)->needsFree = 1; + (*left_dm)->release(*left_dm); + (*left_dm) = NULL; + } + if (*other_dm != NULL) { - BMO_op_callf(bm,(BMO_FLAG_DEFAULTS & ~BMO_FLAG_RESPECT_HIDE), - "subdivide_edges edges=ae " - "smooth=%f smooth_falloff=%i use_smooth_even=%b " - "fractal=%f along_normal=%f " - "cuts=%i " - "quad_corner_type=%i " - "use_single_edge=%b use_grid_fill=%b " - "use_only_quads=%b " - "seed=%i", - 0.0f, SUBD_FALLOFF_ROOT, false, - fractal, 1.0f, - num_cuts, - SUBD_CORNER_INNERVERT, - false, true, - true, - 0); + (*other_dm)->needsFree = 1; + (*other_dm)->release(*other_dm); + (*other_dm) = NULL; } - BMO_op_callf(bm, (BMO_FLAG_DEFAULTS & ~BMO_FLAG_RESPECT_HIDE), - "recalc_face_normals faces=af"); - - BM_ITER_MESH(f, &iter, bm, BM_FACES_OF_MESH) + /*discard only at fractal boolean */ + if (mat != NULL) { - if (use_smooth_inner) - { - BM_elem_flag_enable(f, BM_ELEM_SMOOTH); - } - - if (inner_material_index > 0) - { - f->mat_nr = inner_material_index; + if (*output_dm != NULL) { + (*output_dm)->needsFree = 1; + (*output_dm)->release(*output_dm); + (*output_dm) = NULL; } + return true; } + } - /*convert back*/ - left_dm = CDDM_from_bmesh(bm, true); + return false; +} + +static Shard *do_output_shard_dm(DerivedMesh** output_dm, Shard *child, int num_cuts, float fractal, Shard **other) +{ + Shard* output_s = BKE_create_fracture_shard((*output_dm)->getVertArray(*output_dm), + (*output_dm)->getPolyArray(*output_dm), + (*output_dm)->getLoopArray(*output_dm), + (*output_dm)->getNumVerts(*output_dm), + (*output_dm)->getNumPolys(*output_dm), + (*output_dm)->getNumLoops(*output_dm), + true); + + output_s = BKE_custom_data_to_shard(output_s, *output_dm); + + /* useless, because its a bisect fast-like approach here */ + if (num_cuts == 0 || fractal == 0.0f || other == NULL) { + /* XXX TODO this might be wrong by now ... */ + output_s->neighbor_count = child->neighbor_count; + output_s->neighbor_ids = MEM_mallocN(sizeof(int) * child->neighbor_count, __func__); + memcpy(output_s->neighbor_ids, child->neighbor_ids, sizeof(int) * child->neighbor_count); } - else + + BKE_fracture_shard_center_centroid(output_s, output_s->centroid); + + /* free the temp derivedmesh */ + (*output_dm)->needsFree = 1; + (*output_dm)->release(*output_dm); + *output_dm = NULL; + + return output_s; +} + +static BMesh* do_fractal(float radius, float mat[4][4], bool use_smooth_inner, short inner_material_index, + int num_levels, int num_cuts, float fractal, DerivedMesh** left_dm) +{ + BMFace* f; + BMIter iter; + BMesh *bm; + int i; + + /*create a grid plane */ + bm = BM_mesh_create(&bm_mesh_allocsize_default); + BMO_op_callf(bm, (BMO_FLAG_DEFAULTS & ~BMO_FLAG_RESPECT_HIDE), + "create_grid x_segments=%i y_segments=%i size=%f matrix=%m4", + 1, 1, radius*1.4, mat); + + /*subdivide the plane fractally*/ + for (i = 0; i < num_levels; i++) { - left_dm = BKE_shard_create_dm(child, false); - unwrap_shard_dm(left_dm); + BMO_op_callf(bm,(BMO_FLAG_DEFAULTS & ~BMO_FLAG_RESPECT_HIDE), + "subdivide_edges edges=ae " + "smooth=%f smooth_falloff=%i use_smooth_even=%b " + "fractal=%f along_normal=%f " + "cuts=%i " + "quad_corner_type=%i " + "use_single_edge=%b use_grid_fill=%b " + "use_only_quads=%b " + "seed=%i", + 0.0f, SUBD_FALLOFF_ROOT, false, + fractal, 1.0f, + num_cuts, + SUBD_CORNER_INNERVERT, + false, true, + true, + 0); } - /* set inner material on child shard */ - if (other == NULL || mat == NULL) + BMO_op_callf(bm, (BMO_FLAG_DEFAULTS & ~BMO_FLAG_RESPECT_HIDE), + "recalc_face_normals faces=af"); + + BM_ITER_MESH(f, &iter, bm, BM_FACES_OF_MESH) { - mpoly = left_dm->getPolyArray(left_dm); - totpoly = left_dm->getNumPolys(left_dm); - for (i = 0, mp = mpoly; i < totpoly; i++, mp++) { - if (inner_material_index > 0) { - mp->mat_nr = inner_material_index; + if (use_smooth_inner) + { + BM_elem_flag_enable(f, BM_ELEM_SMOOTH); + } + + if (inner_material_index > 0) + { + f->mat_nr = inner_material_index; + } + } + + /*convert back*/ + *left_dm = CDDM_from_bmesh(bm, true); + + return bm; +} + +static bool do_check_watertight_other(DerivedMesh **other_dm, DerivedMesh **output_dm, Shard **other, DerivedMesh *right_dm, + DerivedMesh **left_dm, float mat[4][4]) +{ + bool do_return = false; + + if (!other_dm || check_non_manifold(*other_dm) || !compare_dm_size(right_dm, *other_dm)) { + if (other != NULL) + *other = NULL; + if (*left_dm != NULL) { + (*left_dm)->needsFree = 1; + (*left_dm)->release(*left_dm); + (*left_dm) = NULL; + } + if (*other_dm != NULL) + { + (*other_dm)->needsFree = 1; + (*other_dm)->release(*other_dm); + (*other_dm) = NULL; + } + + /*discard only at fractal boolean */ + if (mat != NULL) + { + if (*output_dm != NULL) { + (*output_dm)->needsFree = 1; + (*output_dm)->release(*output_dm); + (*output_dm) = NULL; } - mp->flag |= ME_FACE_SEL; + do_return = true; } } - right_dm = dm_parent; - output_dm = NewBooleanDerivedMesh(right_dm, obj, left_dm, obj, 1); /*1 == intersection, 3 == difference*/ + return do_return; +} - /*check for watertightness*/ - if (!output_dm || check_non_manifold(output_dm) || !compare_dm_size(right_dm, output_dm)) { +static bool do_check_watertight(DerivedMesh **output_dm, BMesh** bm, DerivedMesh** left_dm, DerivedMesh *right_dm, Shard **other, float mat[4][4]) +{ + bool do_return = false; + + if (!(*output_dm) || check_non_manifold(*output_dm) || !compare_dm_size(right_dm, (*output_dm))) { if (mat != NULL) { if (other != NULL) *other = NULL; - if (bm != NULL) - BM_mesh_free(bm); + if (*bm != NULL) { + BM_mesh_free(*bm); + *bm = NULL; + } - if (left_dm != NULL) { - left_dm->needsFree = 1; - left_dm->release(left_dm); - left_dm = NULL; + if (*left_dm != NULL) { + (*left_dm)->needsFree = 1; + (*left_dm)->release(*left_dm); + *left_dm = NULL; } } - if (output_dm != NULL) { - output_dm->needsFree = 1; - output_dm->release(output_dm); - output_dm = NULL; + if (*output_dm != NULL) { + (*output_dm)->needsFree = 1; + (*output_dm)->release(*output_dm); + *output_dm = NULL; } if (mat != NULL) { - return NULL; + do_return = true; } } - if (other != NULL) - { + return do_return; +} -#if 0 - if (bm == NULL) - { - bm = DM_to_bmesh(left_dm, true); +static void do_set_inner_material(Shard **other, float mat[4][4], DerivedMesh* left_dm, short inner_material_index) +{ + MPoly *mpoly, *mp; + int totpoly, i = 0; + + /* set inner material on child shard */ + if (other == NULL || mat == NULL) + { + mpoly = left_dm->getPolyArray(left_dm); + totpoly = left_dm->getNumPolys(left_dm); + for (i = 0, mp = mpoly; i < totpoly; i++, mp++) { + if (inner_material_index > 0) { + mp->mat_nr = inner_material_index; + } + mp->flag |= ME_FACE_SEL; } + } +} - BMO_op_callf(bm, (BMO_FLAG_DEFAULTS & ~BMO_FLAG_RESPECT_HIDE), - "reverse_faces faces=af"); +Shard *BKE_fracture_shard_boolean(Object *obj, DerivedMesh *dm_parent, Shard *child, short inner_material_index, + int num_cuts, float fractal, Shard** other, float mat[4][4], float radius, bool use_smooth_inner, int num_levels) +{ + DerivedMesh *left_dm = NULL, *right_dm, *output_dm, *other_dm; + BMesh* bm = NULL; - left_dm->needsFree = 1; - left_dm->release(left_dm); - left_dm = NULL; + if (other != NULL && mat != NULL) + { + do_fractal(radius, mat, use_smooth_inner, inner_material_index, num_levels, num_cuts, fractal, &left_dm); + } + else + { + left_dm = BKE_shard_create_dm(child, false); + unwrap_shard_dm(left_dm); + } - left_dm = CDDM_from_bmesh(bm, true); -#endif + do_set_inner_material(other, mat, left_dm, inner_material_index); + + right_dm = dm_parent; + output_dm = NewBooleanDerivedMesh(right_dm, obj, left_dm, obj, 1); /*1 == intersection, 3 == difference*/ + + /*check for watertightness*/ + if (do_check_watertight(&output_dm, &bm, &left_dm, right_dm, other, mat)) + { + return NULL; + } + + if (other != NULL) + { if (bm != NULL) BM_mesh_free(bm); other_dm = NewBooleanDerivedMesh(left_dm, obj, right_dm, obj, 3); - /*check for watertightness again*/ - if (!other_dm || check_non_manifold(other_dm) || !compare_dm_size(right_dm, other_dm)) { - if (other != NULL) - *other = NULL; - if (left_dm != NULL) { - left_dm->needsFree = 1; - left_dm->release(left_dm); - left_dm = NULL; - } - if (other_dm != NULL) - { - other_dm->needsFree = 1; - other_dm->release(other_dm); - other_dm = NULL; - } - - /*discard only at fractal boolean */ - if (mat != NULL) - { - if (output_dm != NULL) { - output_dm->needsFree = 1; - output_dm->release(output_dm); - output_dm = NULL; - } - return NULL; - } - } - - if (other_dm) + /*check for watertightness again, true means do return NULL here*/ + if (do_check_watertight_other(&other_dm, &output_dm, other, right_dm, &left_dm, mat)) { - *other = BKE_create_fracture_shard(other_dm->getVertArray(other_dm), - other_dm->getPolyArray(other_dm), - other_dm->getLoopArray(other_dm), - other_dm->getNumVerts(other_dm), - other_dm->getNumPolys(other_dm), - other_dm->getNumLoops(other_dm), - true); - - *other = BKE_custom_data_to_shard(*other, other_dm); - -#if 0 - /* XXX TODO this might be wrong by now ... */ - output_s->neighbor_count = child->neighbor_count; - output_s->neighbor_ids = MEM_mallocN(sizeof(int) * child->neighbor_count, __func__); - memcpy(output_s->neighbor_ids, child->neighbor_ids, sizeof(int) * child->neighbor_count); -#endif - BKE_fracture_shard_center_centroid(*other, (*other)->centroid); - - /* free the temp derivedmesh */ - other_dm->needsFree = 1; - other_dm->release(other_dm); - other_dm = NULL; + return NULL; } - else - { - if (other != NULL) - *other = NULL; - if (left_dm != NULL) { - left_dm->needsFree = 1; - left_dm->release(left_dm); - left_dm = NULL; - } - if (other_dm != NULL) - { - other_dm->needsFree = 1; - other_dm->release(other_dm); - other_dm = NULL; - } - /*discard only at fractal boolean */ - if (mat != NULL) - { - if (output_dm != NULL) { - output_dm->needsFree = 1; - output_dm->release(output_dm); - output_dm = NULL; - } - return NULL; - } + /*return here if this function returns true */ + if (do_other_output(&other_dm, other, &output_dm, &left_dm, mat)) + { + return NULL; } } @@ -505,47 +578,111 @@ Shard *BKE_fracture_shard_boolean(Object *obj, DerivedMesh *dm_parent, Shard *ch if (output_dm) { - output_s = BKE_create_fracture_shard(output_dm->getVertArray(output_dm), - output_dm->getPolyArray(output_dm), - output_dm->getLoopArray(output_dm), - output_dm->getNumVerts(output_dm), - output_dm->getNumPolys(output_dm), - output_dm->getNumLoops(output_dm), - true); - - output_s = BKE_custom_data_to_shard(output_s, output_dm); - - /* useless, because its a bisect fast-like approach here */ - if (num_cuts == 0 || fractal == 0.0f || other == NULL) { - /* XXX TODO this might be wrong by now ... */ - output_s->neighbor_count = child->neighbor_count; - output_s->neighbor_ids = MEM_mallocN(sizeof(int) * child->neighbor_count, __func__); - memcpy(output_s->neighbor_ids, child->neighbor_ids, sizeof(int) * child->neighbor_count); - } + return do_output_shard_dm(&output_dm, child, num_cuts, fractal, other); + } - BKE_fracture_shard_center_centroid(output_s, output_s->centroid); + return NULL; +} - /* free the temp derivedmesh */ - output_dm->needsFree = 1; - output_dm->release(output_dm); - output_dm = NULL; +static Shard *do_output_shard(BMesh* bm_parent, Shard *child) +{ + Shard *output_s = NULL; + DerivedMesh *dm_out; + + if (bm_parent->totvert >= 3) + { /* atleast 3 verts form a face, so strip out invalid stuff */ + dm_out = CDDM_from_bmesh(bm_parent, true); + output_s = BKE_create_fracture_shard(dm_out->getVertArray(dm_out), + dm_out->getPolyArray(dm_out), + dm_out->getLoopArray(dm_out), + dm_out->getNumVerts(dm_out), + dm_out->getNumPolys(dm_out), + dm_out->getNumLoops(dm_out), true); + + output_s = BKE_custom_data_to_shard(output_s, dm_out); - return output_s; + /*XXX TODO this might be wrong by now ... */ + output_s->neighbor_count = child->neighbor_count; + output_s->neighbor_ids = MEM_mallocN(sizeof(int) * child->neighbor_count, __func__); + memcpy(output_s->neighbor_ids, child->neighbor_ids, sizeof(int) * child->neighbor_count); + BKE_fracture_shard_center_centroid(output_s, output_s->centroid); + + dm_out->needsFree = 1; + dm_out->release(dm_out); + dm_out = NULL; } - return NULL; + return output_s; } - -Shard *BKE_fracture_shard_bisect(BMesh *bm_orig, Shard *child, float obmat[4][4], bool use_fill, bool clear_inner, - bool clear_outer, int cutlimit, float centroid[3], short inner_mat_index) +static void do_fill(float plane_no[3], bool clear_outer, bool clear_inner, BMOperator bmop, short inner_mat_index, BMesh* bm_parent) { + float normal_fill[3]; + BMOperator bmop_fill; + BMOperator bmop_attr; - Shard *output_s; - DerivedMesh *dm_child = BKE_shard_create_dm(child, false); - DerivedMesh *dm_out; - BMesh *bm_parent = BM_mesh_copy(bm_orig); - BMesh *bm_child; + normalize_v3_v3(normal_fill, plane_no); + if (clear_outer == true && clear_inner == false) { + negate_v3(normal_fill); + } + + /* Fill, XXX attempted different fill algorithms here, needs further thoughts because none really suited */ +#if 0 + BMO_op_initf(bm_parent, &bmop_fill, (BMO_FLAG_DEFAULTS & ~BMO_FLAG_RESPECT_HIDE), + "contextual_create geom=%S mat_nr=%i use_smooth=%b", + &bmop, "geom_cut.out", 0, false); + BMO_op_exec(bm_parent, &bmop_fill); + + BMO_op_initf(bm_parent, &bmop_attr, (BMO_FLAG_DEFAULTS & ~BMO_FLAG_RESPECT_HIDE), + "face_attribute_fill faces=%S use_normals=%b use_data=%b", + &bmop_fill, "faces.out", false, true); + BMO_op_exec(bm_parent, &bmop_attr); + + BMO_op_initf(bm_parent, &bmop_del, (BMO_FLAG_DEFAULTS & ~BMO_FLAG_RESPECT_HIDE), + "delete geom=%S context=%i", &bmop_fill, "edges.out", DEL_EDGESFACES); + BMO_op_exec(bm_parent, &bmop_del); + + BMO_slot_buffer_hflag_enable(bm_parent, bmop_fill.slots_out, "faces.out", BM_FACE, BM_ELEM_TAG, true); +#endif + + if (inner_mat_index == 0) { /* dont use inner material here*/ + BMO_op_initf( + bm_parent, &bmop_fill, (BMO_FLAG_DEFAULTS & ~BMO_FLAG_RESPECT_HIDE), + "triangle_fill edges=%S normal=%v use_dissolve=%b use_beauty=%b", + &bmop, "geom_cut.out", normal_fill, true, true); + BMO_op_exec(bm_parent, &bmop_fill); + + BMO_op_initf(bm_parent, &bmop_attr, (BMO_FLAG_DEFAULTS & ~BMO_FLAG_RESPECT_HIDE), + "face_attribute_fill faces=%S use_normals=%b use_data=%b", + &bmop_fill, "geom.out", false, true); + BMO_op_exec(bm_parent, &bmop_attr); + + BMO_slot_buffer_hflag_enable(bm_parent, bmop_fill.slots_out, "geom.out", BM_FACE, BM_ELEM_TAG | BM_ELEM_SELECT, true); + } + else { + /* use edgenet fill with inner material */ + BMO_op_initf( + bm_parent, &bmop_fill, (BMO_FLAG_DEFAULTS & ~BMO_FLAG_RESPECT_HIDE), + "edgenet_fill edges=%S mat_nr=%i use_smooth=%b sides=%i", + &bmop, "geom_cut.out", inner_mat_index, false, 2); + BMO_op_exec(bm_parent, &bmop_fill); + + /* Copy Attributes */ + BMO_op_initf(bm_parent, &bmop_attr, (BMO_FLAG_DEFAULTS & ~BMO_FLAG_RESPECT_HIDE), + "face_attribute_fill faces=%S use_normals=%b use_data=%b", + &bmop_fill, "faces.out", true, false); + BMO_op_exec(bm_parent, &bmop_attr); + + BMO_slot_buffer_hflag_enable(bm_parent, bmop_fill.slots_out, "faces.out", BM_FACE, BM_ELEM_TAG | BM_ELEM_SELECT, true); + } + + BMO_op_finish(bm_parent, &bmop_attr); + BMO_op_finish(bm_parent, &bmop_fill); +} + +static void do_bisect(BMesh* bm_parent, BMesh* bm_child, float obmat[4][4], bool use_fill, bool clear_inner, + bool clear_outer, int cutlimit, float centroid[3], short inner_mat_index) +{ BMIter iter; BMFace *f; @@ -558,14 +695,8 @@ Shard *BKE_fracture_shard_bisect(BMesh *bm_orig, Shard *child, float obmat[4][4] bool do_break = false; int cut_index = 0; - - unwrap_shard_dm(dm_child); - bm_child = DM_to_bmesh(dm_child, true); - invert_m4_m4(imat, obmat); - BM_mesh_elem_hflag_enable_all(bm_parent, BM_VERT | BM_EDGE | BM_FACE, BM_ELEM_TAG, false); - BM_ITER_MESH_INDEX (f, &iter, bm_child, BM_FACES_OF_MESH, cut_index) { if (do_break) { @@ -596,100 +727,36 @@ Shard *BKE_fracture_shard_bisect(BMesh *bm_orig, Shard *child, float obmat[4][4] BM_mesh_elem_hflag_disable_all(bm_parent, BM_VERT | BM_EDGE | BM_FACE, BM_ELEM_TAG, false); if (use_fill) { - float normal_fill[3]; - BMOperator bmop_fill; - BMOperator bmop_attr; - - normalize_v3_v3(normal_fill, plane_no); - if (clear_outer == true && clear_inner == false) { - negate_v3(normal_fill); - } - - /* Fill, XXX attempted different fill algorithms here, needs further thoughts because none really suited */ -#if 0 - BMO_op_initf(bm_parent, &bmop_fill, (BMO_FLAG_DEFAULTS & ~BMO_FLAG_RESPECT_HIDE), - "contextual_create geom=%S mat_nr=%i use_smooth=%b", - &bmop, "geom_cut.out", 0, false); - BMO_op_exec(bm_parent, &bmop_fill); - - BMO_op_initf(bm_parent, &bmop_attr, (BMO_FLAG_DEFAULTS & ~BMO_FLAG_RESPECT_HIDE), - "face_attribute_fill faces=%S use_normals=%b use_data=%b", - &bmop_fill, "faces.out", false, true); - BMO_op_exec(bm_parent, &bmop_attr); + do_fill(plane_no, clear_outer, clear_inner, bmop, inner_mat_index, bm_parent); + } - BMO_op_initf(bm_parent, &bmop_del, (BMO_FLAG_DEFAULTS & ~BMO_FLAG_RESPECT_HIDE), - "delete geom=%S context=%i", &bmop_fill, "edges.out", DEL_EDGESFACES); - BMO_op_exec(bm_parent, &bmop_del); + BMO_slot_buffer_hflag_enable(bm_parent, bmop.slots_out, "geom_cut.out", BM_VERT | BM_EDGE, BM_ELEM_TAG, true); - BMO_slot_buffer_hflag_enable(bm_parent, bmop_fill.slots_out, "faces.out", BM_FACE, BM_ELEM_TAG, true); -#endif + BMO_op_finish(bm_parent, &bmop); + } +} - if (inner_mat_index == 0) { /* dont use inner material here*/ - BMO_op_initf( - bm_parent, &bmop_fill, (BMO_FLAG_DEFAULTS & ~BMO_FLAG_RESPECT_HIDE), - "triangle_fill edges=%S normal=%v use_dissolve=%b use_beauty=%b", - &bmop, "geom_cut.out", normal_fill, true, true); - BMO_op_exec(bm_parent, &bmop_fill); - BMO_op_initf(bm_parent, &bmop_attr, (BMO_FLAG_DEFAULTS & ~BMO_FLAG_RESPECT_HIDE), - "face_attribute_fill faces=%S use_normals=%b use_data=%b", - &bmop_fill, "geom.out", false, true); - BMO_op_exec(bm_parent, &bmop_attr); +Shard *BKE_fracture_shard_bisect(BMesh *bm_orig, Shard *child, float obmat[4][4], bool use_fill, bool clear_inner, + bool clear_outer, int cutlimit, float centroid[3], short inner_mat_index) +{ - BMO_slot_buffer_hflag_enable(bm_parent, bmop_fill.slots_out, "geom.out", BM_FACE, BM_ELEM_TAG | BM_ELEM_SELECT, true); - } - else { - /* use edgenet fill with inner material */ - BMO_op_initf( - bm_parent, &bmop_fill, (BMO_FLAG_DEFAULTS & ~BMO_FLAG_RESPECT_HIDE), - "edgenet_fill edges=%S mat_nr=%i use_smooth=%b sides=%i", - &bmop, "geom_cut.out", inner_mat_index, false, 2); - BMO_op_exec(bm_parent, &bmop_fill); - - /* Copy Attributes */ - BMO_op_initf(bm_parent, &bmop_attr, (BMO_FLAG_DEFAULTS & ~BMO_FLAG_RESPECT_HIDE), - "face_attribute_fill faces=%S use_normals=%b use_data=%b", - &bmop_fill, "faces.out", true, false); - BMO_op_exec(bm_parent, &bmop_attr); - - BMO_slot_buffer_hflag_enable(bm_parent, bmop_fill.slots_out, "faces.out", BM_FACE, BM_ELEM_TAG | BM_ELEM_SELECT, true); - } + Shard *output_s; + DerivedMesh *dm_child = BKE_shard_create_dm(child, false); - BMO_op_finish(bm_parent, &bmop_attr); - BMO_op_finish(bm_parent, &bmop_fill); - } + BMesh *bm_parent = BM_mesh_copy(bm_orig); + BMesh *bm_child; - BMO_slot_buffer_hflag_enable(bm_parent, bmop.slots_out, "geom_cut.out", BM_VERT | BM_EDGE, BM_ELEM_TAG, true); - BMO_op_finish(bm_parent, &bmop); - } + unwrap_shard_dm(dm_child); + bm_child = DM_to_bmesh(dm_child, true); - if (bm_parent->totvert >= 3) - { /* atleast 3 verts form a face, so strip out invalid stuff */ - dm_out = CDDM_from_bmesh(bm_parent, true); - output_s = BKE_create_fracture_shard(dm_out->getVertArray(dm_out), - dm_out->getPolyArray(dm_out), - dm_out->getLoopArray(dm_out), - dm_out->getNumVerts(dm_out), - dm_out->getNumPolys(dm_out), - dm_out->getNumLoops(dm_out), true); - output_s = BKE_custom_data_to_shard(output_s, dm_out); + BM_mesh_elem_hflag_enable_all(bm_parent, BM_VERT | BM_EDGE | BM_FACE, BM_ELEM_TAG, false); - /*XXX TODO this might be wrong by now ... */ - output_s->neighbor_count = child->neighbor_count; - output_s->neighbor_ids = MEM_mallocN(sizeof(int) * child->neighbor_count, __func__); - memcpy(output_s->neighbor_ids, child->neighbor_ids, sizeof(int) * child->neighbor_count); - BKE_fracture_shard_center_centroid(output_s, output_s->centroid); + do_bisect(bm_parent, bm_child, obmat, use_fill, clear_inner, clear_outer, cutlimit, centroid, inner_mat_index); - dm_out->needsFree = 1; - dm_out->release(dm_out); - dm_out = NULL; - } - else - { - output_s = NULL; - } + output_s = do_output_shard(bm_parent, child); BM_mesh_free(bm_child); BM_mesh_free(bm_parent); @@ -698,7 +765,5 @@ Shard *BKE_fracture_shard_bisect(BMesh *bm_orig, Shard *child, float obmat[4][4] dm_child->release(dm_child); dm_child = NULL; - - return output_s; } |