diff options
Diffstat (limited to 'source/blender/modifiers/intern/MOD_solidify_extrude.c')
-rw-r--r-- | source/blender/modifiers/intern/MOD_solidify_extrude.c | 324 |
1 files changed, 229 insertions, 95 deletions
diff --git a/source/blender/modifiers/intern/MOD_solidify_extrude.c b/source/blender/modifiers/intern/MOD_solidify_extrude.c index 8febf78fef5..75d2be5292e 100644 --- a/source/blender/modifiers/intern/MOD_solidify_extrude.c +++ b/source/blender/modifiers/intern/MOD_solidify_extrude.c @@ -10,7 +10,7 @@ * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software Foundation, + * along with this program; if not, write to the Free Software Foundation, * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ @@ -183,9 +183,7 @@ static void mesh_calc_hq_normal(Mesh *mesh, float (*poly_nors)[3], float (*r_ver /** \name Main Solidify Function * \{ */ -Mesh *MOD_solidify_extrude_applyModifier(ModifierData *md, - const ModifierEvalContext *ctx, - Mesh *mesh) +Mesh *MOD_solidify_extrude_modifyMesh(ModifierData *md, const ModifierEvalContext *ctx, Mesh *mesh) { Mesh *result; const SolidifyModifierData *smd = (SolidifyModifierData *)md; @@ -224,22 +222,28 @@ Mesh *MOD_solidify_extrude_applyModifier(ModifierData *md, const bool need_poly_normals = (smd->flag & MOD_SOLIDIFY_NORMAL_CALC) || (smd->flag & MOD_SOLIDIFY_EVEN) || - (smd->flag & MOD_SOLIDIFY_OFFSET_ANGLE_CLAMP); + (smd->flag & MOD_SOLIDIFY_OFFSET_ANGLE_CLAMP) || + (smd->bevel_convex != 0); const float ofs_orig = -(((-smd->offset_fac + 1.0f) * 0.5f) * smd->offset); const float ofs_new = smd->offset + ofs_orig; const float offset_fac_vg = smd->offset_fac_vg; const float offset_fac_vg_inv = 1.0f - smd->offset_fac_vg; + const float bevel_convex = smd->bevel_convex; const bool do_flip = (smd->flag & MOD_SOLIDIFY_FLIP) != 0; const bool do_clamp = (smd->offset_clamp != 0.0f); - const bool do_angle_clamp = (smd->flag & MOD_SOLIDIFY_OFFSET_ANGLE_CLAMP) != 0; - const bool do_shell = ((smd->flag & MOD_SOLIDIFY_RIM) && (smd->flag & MOD_SOLIDIFY_NOSHELL)) == - 0; + const bool do_angle_clamp = do_clamp && (smd->flag & MOD_SOLIDIFY_OFFSET_ANGLE_CLAMP) != 0; + const bool do_bevel_convex = bevel_convex != 0.0f; + const bool do_rim = (smd->flag & MOD_SOLIDIFY_RIM) != 0; + const bool do_shell = !(do_rim && (smd->flag & MOD_SOLIDIFY_NOSHELL) != 0); /* weights */ MDeformVert *dvert; const bool defgrp_invert = (smd->flag & MOD_SOLIDIFY_VGROUP_INV) != 0; int defgrp_index; + const int shell_defgrp_index = BKE_object_defgroup_name_index(ctx->object, + smd->shell_defgrp_name); + const int rim_defgrp_index = BKE_object_defgroup_name_index(ctx->object, smd->rim_defgrp_name); /* array size is doubled in case of using a shell */ const uint stride = do_shell ? 2 : 1; @@ -268,7 +272,7 @@ Mesh *MOD_solidify_extrude_applyModifier(ModifierData *md, STACK_INIT(new_vert_arr, numVerts * 2); STACK_INIT(new_edge_arr, numEdges * 2); - if (smd->flag & MOD_SOLIDIFY_RIM) { + if (do_rim) { BLI_bitmap *orig_mvert_tag = BLI_BITMAP_NEW(numVerts, __func__); uint eidx; uint i; @@ -367,6 +371,11 @@ Mesh *MOD_solidify_extrude_applyModifier(ModifierData *md, medge = result->medge; mvert = result->mvert; + if (do_bevel_convex) { + /* Make sure bweight is enabled. */ + result->cd_flag |= ME_CDFLAG_EDGE_BWEIGHT; + } + if (do_shell) { CustomData_copy_data(&mesh->vdata, &result->vdata, 0, 0, (int)numVerts); CustomData_copy_data(&mesh->vdata, &result->vdata, 0, (int)numVerts, (int)numVerts); @@ -507,62 +516,81 @@ Mesh *MOD_solidify_extrude_applyModifier(ModifierData *md, const float offset = fabsf(smd->offset) * smd->offset_clamp; const float offset_sq = offset * offset; - if (do_clamp) { - uint i; + /* for bevel weight */ + float *edge_angs = NULL; + if (do_clamp) { vert_lens = MEM_malloc_arrayN(numVerts, sizeof(float), "vert_lens"); copy_vn_fl(vert_lens, (int)numVerts, FLT_MAX); - for (i = 0; i < numEdges; i++) { + for (uint i = 0; i < numEdges; i++) { const float ed_len_sq = len_squared_v3v3(mvert[medge[i].v1].co, mvert[medge[i].v2].co); vert_lens[medge[i].v1] = min_ff(vert_lens[medge[i].v1], ed_len_sq); vert_lens[medge[i].v2] = min_ff(vert_lens[medge[i].v2], ed_len_sq); } + } + + if (do_angle_clamp || do_bevel_convex) { + uint eidx; if (do_angle_clamp) { - uint eidx; vert_angs = MEM_malloc_arrayN(numVerts, sizeof(float), "vert_angs"); copy_vn_fl(vert_angs, (int)numVerts, 0.5f * M_PI); - uint(*edge_user_pairs)[2] = MEM_malloc_arrayN( - numEdges, sizeof(*edge_user_pairs), "edge_user_pairs"); - for (eidx = 0; eidx < numEdges; eidx++) { - edge_user_pairs[eidx][0] = INVALID_UNUSED; - edge_user_pairs[eidx][1] = INVALID_UNUSED; + } + if (do_bevel_convex) { + edge_angs = MEM_malloc_arrayN(numEdges, sizeof(float), "edge_angs"); + if (!do_rim) { + edge_users = MEM_malloc_arrayN(numEdges, sizeof(*edge_users), "solid_mod edges"); } - for (i = 0, mp = orig_mpoly; i < numPolys; i++, mp++) { - ml = orig_mloop + mp->loopstart; - MLoop *ml_prev = ml + (mp->totloop - 1); - - for (int j = 0; j < mp->totloop; j++, ml++) { - /* add edge user */ - eidx = ml_prev->e; - ed = orig_medge + eidx; - BLI_assert(ELEM(ml_prev->v, ed->v1, ed->v2) && ELEM(ml->v, ed->v1, ed->v2)); - char flip = (char)((ml_prev->v > ml->v) == (ed->v1 < ed->v2)); - if (edge_user_pairs[eidx][flip] == INVALID_UNUSED) { - edge_user_pairs[eidx][flip] = i; - } - else { - edge_user_pairs[eidx][0] = INVALID_PAIR; - edge_user_pairs[eidx][1] = INVALID_PAIR; - } - ml_prev = ml; + } + uint(*edge_user_pairs)[2] = MEM_malloc_arrayN( + numEdges, sizeof(*edge_user_pairs), "edge_user_pairs"); + for (eidx = 0; eidx < numEdges; eidx++) { + edge_user_pairs[eidx][0] = INVALID_UNUSED; + edge_user_pairs[eidx][1] = INVALID_UNUSED; + } + mp = orig_mpoly; + for (uint i = 0; i < numPolys; i++, mp++) { + ml = orig_mloop + mp->loopstart; + MLoop *ml_prev = ml + (mp->totloop - 1); + + for (uint j = 0; j < mp->totloop; j++, ml++) { + /* add edge user */ + eidx = ml_prev->e; + ed = orig_medge + eidx; + BLI_assert(ELEM(ml_prev->v, ed->v1, ed->v2) && ELEM(ml->v, ed->v1, ed->v2)); + char flip = (char)((ml_prev->v > ml->v) == (ed->v1 < ed->v2)); + if (edge_user_pairs[eidx][flip] == INVALID_UNUSED) { + edge_user_pairs[eidx][flip] = i; + } + else { + edge_user_pairs[eidx][0] = INVALID_PAIR; + edge_user_pairs[eidx][1] = INVALID_PAIR; } + ml_prev = ml; } - ed = orig_medge; - float e[3]; - for (i = 0; i < numEdges; i++, ed++) { - if (!ELEM(edge_user_pairs[i][0], INVALID_UNUSED, INVALID_PAIR) && - !ELEM(edge_user_pairs[i][1], INVALID_UNUSED, INVALID_PAIR)) { - const float *n0 = poly_nors[edge_user_pairs[i][0]]; - const float *n1 = poly_nors[edge_user_pairs[i][1]]; - sub_v3_v3v3(e, orig_mvert[ed->v1].co, orig_mvert[ed->v2].co); - normalize_v3(e); - const float angle = angle_signed_on_axis_v3v3_v3(n0, n1, e); + } + ed = orig_medge; + float e[3]; + for (uint i = 0; i < numEdges; i++, ed++) { + if (!ELEM(edge_user_pairs[i][0], INVALID_UNUSED, INVALID_PAIR) && + !ELEM(edge_user_pairs[i][1], INVALID_UNUSED, INVALID_PAIR)) { + const float *n0 = poly_nors[edge_user_pairs[i][0]]; + const float *n1 = poly_nors[edge_user_pairs[i][1]]; + sub_v3_v3v3(e, orig_mvert[ed->v1].co, orig_mvert[ed->v2].co); + normalize_v3(e); + const float angle = angle_signed_on_axis_v3v3_v3(n0, n1, e); + if (do_angle_clamp) { vert_angs[ed->v1] = max_ff(vert_angs[ed->v1], angle); vert_angs[ed->v2] = max_ff(vert_angs[ed->v2], angle); } + if (do_bevel_convex) { + edge_angs[i] = angle; + if (!do_rim) { + edge_users[i] = INVALID_PAIR; + } + } } - MEM_freeN(edge_user_pairs); } + MEM_freeN(edge_user_pairs); } if (ofs_new != 0.0f) { @@ -658,6 +686,33 @@ Mesh *MOD_solidify_extrude_applyModifier(ModifierData *md, } } + if (do_bevel_convex) { + for (uint i = 0; i < numEdges; i++) { + if (edge_users[i] == INVALID_PAIR) { + float angle = edge_angs[i]; + medge[i].bweight = (char)clamp_i( + (int)medge[i].bweight + (int)((angle < M_PI ? clamp_f(bevel_convex, 0.0f, 1.0f) : + clamp_f(bevel_convex, -1.0f, 0.0f)) * + 255), + 0, + 255); + if (do_shell) { + medge[i + numEdges].bweight = (char)clamp_i( + (int)medge[i + numEdges].bweight + + (int)((angle > M_PI ? clamp_f(bevel_convex, 0.0f, 1.0f) : + clamp_f(bevel_convex, -1.0f, 0.0f)) * + 255), + 0, + 255); + } + } + } + if (!do_rim) { + MEM_freeN(edge_users); + } + MEM_freeN(edge_angs); + } + if (do_clamp) { MEM_freeN(vert_lens); if (do_angle_clamp) { @@ -754,6 +809,74 @@ Mesh *MOD_solidify_extrude_applyModifier(ModifierData *md, } } + /* for angle clamp */ + float *vert_angs = NULL; + /* for bevel convex */ + float *edge_angs = NULL; + + if (do_angle_clamp || do_bevel_convex) { + uint eidx; + if (do_angle_clamp) { + vert_angs = MEM_malloc_arrayN(numVerts, sizeof(float), "vert_angs even"); + copy_vn_fl(vert_angs, (int)numVerts, 0.5f * M_PI); + } + if (do_bevel_convex) { + edge_angs = MEM_malloc_arrayN(numEdges, sizeof(float), "edge_angs even"); + if (!do_rim) { + edge_users = MEM_malloc_arrayN(numEdges, sizeof(*edge_users), "solid_mod edges"); + } + } + uint(*edge_user_pairs)[2] = MEM_malloc_arrayN( + numEdges, sizeof(*edge_user_pairs), "edge_user_pairs"); + for (eidx = 0; eidx < numEdges; eidx++) { + edge_user_pairs[eidx][0] = INVALID_UNUSED; + edge_user_pairs[eidx][1] = INVALID_UNUSED; + } + for (i = 0, mp = orig_mpoly; i < numPolys; i++, mp++) { + ml = orig_mloop + mp->loopstart; + MLoop *ml_prev = ml + (mp->totloop - 1); + + for (int j = 0; j < mp->totloop; j++, ml++) { + /* add edge user */ + eidx = ml_prev->e; + ed = orig_medge + eidx; + BLI_assert(ELEM(ml_prev->v, ed->v1, ed->v2) && ELEM(ml->v, ed->v1, ed->v2)); + char flip = (char)((ml_prev->v > ml->v) == (ed->v1 < ed->v2)); + if (edge_user_pairs[eidx][flip] == INVALID_UNUSED) { + edge_user_pairs[eidx][flip] = i; + } + else { + edge_user_pairs[eidx][0] = INVALID_PAIR; + edge_user_pairs[eidx][1] = INVALID_PAIR; + } + ml_prev = ml; + } + } + ed = orig_medge; + float e[3]; + for (i = 0; i < numEdges; i++, ed++) { + if (!ELEM(edge_user_pairs[i][0], INVALID_UNUSED, INVALID_PAIR) && + !ELEM(edge_user_pairs[i][1], INVALID_UNUSED, INVALID_PAIR)) { + const float *n0 = poly_nors[edge_user_pairs[i][0]]; + const float *n1 = poly_nors[edge_user_pairs[i][1]]; + if (do_angle_clamp) { + const float angle = M_PI - angle_normalized_v3v3(n0, n1); + vert_angs[ed->v1] = max_ff(vert_angs[ed->v1], angle); + vert_angs[ed->v2] = max_ff(vert_angs[ed->v2], angle); + } + if (do_bevel_convex) { + sub_v3_v3v3(e, orig_mvert[ed->v1].co, orig_mvert[ed->v2].co); + normalize_v3(e); + edge_angs[i] = angle_signed_on_axis_v3v3_v3(n0, n1, e); + if (!do_rim) { + edge_users[i] = INVALID_PAIR; + } + } + } + } + MEM_freeN(edge_user_pairs); + } + if (do_clamp) { const float clamp_fac = 1 + (do_angle_clamp ? fabsf(smd->offset_fac) : 0); const float offset = fabsf(smd->offset) * smd->offset_clamp * clamp_fac; @@ -767,48 +890,6 @@ Mesh *MOD_solidify_extrude_applyModifier(ModifierData *md, vert_lens_sq[medge[i].v2] = min_ff(vert_lens_sq[medge[i].v2], ed_len); } if (do_angle_clamp) { - uint eidx; - float *vert_angs = MEM_malloc_arrayN(numVerts, sizeof(float), "vert_angs even"); - copy_vn_fl(vert_angs, (int)numVerts, 0.5f * M_PI); - uint(*edge_user_pairs)[2] = MEM_malloc_arrayN( - numEdges, sizeof(*edge_user_pairs), "edge_user_pairs"); - for (eidx = 0; eidx < numEdges; eidx++) { - edge_user_pairs[eidx][0] = INVALID_UNUSED; - edge_user_pairs[eidx][1] = INVALID_UNUSED; - } - for (i = 0, mp = orig_mpoly; i < numPolys; i++, mp++) { - ml = orig_mloop + mp->loopstart; - MLoop *ml_prev = ml + (mp->totloop - 1); - - for (int j = 0; j < mp->totloop; j++, ml++) { - /* add edge user */ - eidx = ml_prev->e; - ed = orig_medge + eidx; - BLI_assert(ELEM(ml_prev->v, ed->v1, ed->v2) && ELEM(ml->v, ed->v1, ed->v2)); - char flip = (char)((ml_prev->v > ml->v) == (ed->v1 < ed->v2)); - if (edge_user_pairs[eidx][flip] == INVALID_UNUSED) { - edge_user_pairs[eidx][flip] = i; - } - else { - edge_user_pairs[eidx][0] = INVALID_PAIR; - edge_user_pairs[eidx][1] = INVALID_PAIR; - } - ml_prev = ml; - } - } - ed = orig_medge; - for (i = 0; i < numEdges; i++, ed++) { - if (!ELEM(edge_user_pairs[i][0], INVALID_UNUSED, INVALID_PAIR) && - !ELEM(edge_user_pairs[i][1], INVALID_UNUSED, INVALID_PAIR)) { - const float *n0 = poly_nors[edge_user_pairs[i][0]]; - const float *n1 = poly_nors[edge_user_pairs[i][1]]; - const float angle = M_PI - angle_normalized_v3v3(n0, n1); - vert_angs[ed->v1] = max_ff(vert_angs[ed->v1], angle); - vert_angs[ed->v2] = max_ff(vert_angs[ed->v2], angle); - } - } - MEM_freeN(edge_user_pairs); - for (i = 0; i < numVerts; i++) { float cos_ang = cosf(vert_angs[i] * 0.5f); if (cos_ang > 0) { @@ -832,6 +913,33 @@ Mesh *MOD_solidify_extrude_applyModifier(ModifierData *md, } } + if (do_bevel_convex) { + for (i = 0; i < numEdges; i++) { + if (edge_users[i] == INVALID_PAIR) { + float angle = edge_angs[i]; + medge[i].bweight = (char)clamp_i( + (int)medge[i].bweight + (int)((angle < M_PI ? clamp_f(bevel_convex, 0, 1) : + clamp_f(bevel_convex, -1, 0)) * + 255), + 0, + 255); + if (do_shell) { + medge[i + numEdges].bweight = (char)clamp_i( + (int)medge[i + numEdges].bweight + + (int)((angle > M_PI ? clamp_f(bevel_convex, 0, 1) : + clamp_f(bevel_convex, -1, 0)) * + 255), + 0, + 255); + } + } + } + if (!do_rim) { + MEM_freeN(edge_users); + } + MEM_freeN(edge_angs); + } + #undef INVALID_UNUSED #undef INVALID_PAIR @@ -874,7 +982,7 @@ Mesh *MOD_solidify_extrude_applyModifier(ModifierData *md, } /* must recalculate normals with vgroups since they can displace unevenly [#26888] */ - if ((mesh->runtime.cd_dirty_vert & CD_MASK_NORMAL) || (smd->flag & MOD_SOLIDIFY_RIM) || dvert) { + if ((mesh->runtime.cd_dirty_vert & CD_MASK_NORMAL) || do_rim || dvert) { result->runtime.cd_dirty_vert |= CD_MASK_NORMAL; } else if (do_shell) { @@ -886,7 +994,37 @@ Mesh *MOD_solidify_extrude_applyModifier(ModifierData *md, } } - if (smd->flag & MOD_SOLIDIFY_RIM) { + /* Add vertex weights for rim and shell vgroups. */ + if (shell_defgrp_index != -1 || rim_defgrp_index != -1) { + dvert = CustomData_duplicate_referenced_layer(&result->vdata, CD_MDEFORMVERT, result->totvert); + /* If no vertices were ever added to an object's vgroup, dvert might be NULL. */ + if (dvert == NULL) { + /* Add a valid data layer! */ + dvert = CustomData_add_layer( + &result->vdata, CD_MDEFORMVERT, CD_CALLOC, NULL, result->totvert); + } + /* Ultimate security check. */ + if (!dvert) { + return result; + } + result->dvert = dvert; + + if (rim_defgrp_index != -1) { + for (uint i = 0; i < rimVerts; i++) { + BKE_defvert_ensure_index(&result->dvert[new_vert_arr[i]], rim_defgrp_index)->weight = 1.0f; + BKE_defvert_ensure_index(&result->dvert[(do_shell ? new_vert_arr[i] : i) + numVerts], + rim_defgrp_index) + ->weight = 1.0f; + } + } + + if (shell_defgrp_index != -1) { + for (uint i = numVerts; i < result->totvert; i++) { + BKE_defvert_ensure_index(&result->dvert[i], shell_defgrp_index)->weight = 1.0f; + } + } + } + if (do_rim) { uint i; /* bugger, need to re-calculate the normals for the new edge faces. @@ -1093,10 +1231,6 @@ Mesh *MOD_solidify_extrude_applyModifier(ModifierData *md, MEM_freeN(poly_nors); } - if (numPolys == 0 && numVerts != 0) { - modifier_setError(md, "Faces needed for useful output"); - } - return result; } |