From 584523e0adeb2663077602953f0d3288c4c60fe4 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Thu, 7 Sep 2017 00:10:13 +1000 Subject: Screw Modifier: remove doubles option Vertices on the axis can be optionally merged, nice for creating objects which close at the end-points. --- source/blender/modifiers/intern/MOD_screw.c | 61 +++++++++++++++++++++++++++++ 1 file changed, 61 insertions(+) (limited to 'source/blender/modifiers/intern/MOD_screw.c') diff --git a/source/blender/modifiers/intern/MOD_screw.c b/source/blender/modifiers/intern/MOD_screw.c index 87859cd240a..2c3d7f394bb 100644 --- a/source/blender/modifiers/intern/MOD_screw.c +++ b/source/blender/modifiers/intern/MOD_screw.c @@ -112,6 +112,56 @@ static void screwvert_iter_step(ScrewVertIter *iter) } } +static DerivedMesh *dm_remove_doubles_on_axis( + DerivedMesh *result, MVert *mvert_new, const uint totvert, const uint step_tot, + const float axis_vec[3], const float axis_offset[3], const float merge_threshold) +{ + const float merge_threshold_sq = SQUARE(merge_threshold); + const bool use_offset = axis_offset != NULL; + uint tot_doubles = 0; + for (uint i = 0; i < totvert; i += 1) { + float axis_co[3]; + if (use_offset) { + float offset_co[3]; + sub_v3_v3v3(offset_co, mvert_new[i].co, axis_offset); + project_v3_v3v3_normalized(axis_co, offset_co, axis_vec); + add_v3_v3(axis_co, axis_offset); + } + else { + project_v3_v3v3_normalized(axis_co, mvert_new[i].co, axis_vec); + } + const float dist_sq = len_squared_v3v3(axis_co, mvert_new[i].co); + if (dist_sq <= merge_threshold_sq) { + mvert_new[i].flag |= ME_VERT_TMP_TAG; + tot_doubles += 1; + copy_v3_v3(mvert_new[i].co, axis_co); + } + } + + if (tot_doubles != 0) { + uint tot = totvert * step_tot; + int *full_doubles_map = MEM_mallocN(sizeof(int) * tot, __func__); + copy_vn_i(full_doubles_map, (int)tot, -1); + + uint tot_doubles_left = tot_doubles; + for (uint i = 0; i < totvert; i += 1) { + if (mvert_new[i].flag & ME_VERT_TMP_TAG) { + int *doubles_map = &full_doubles_map[totvert + i] ; + for (uint step = 1; step < step_tot; step += 1) { + *doubles_map = (int)i; + doubles_map += totvert; + } + tot_doubles_left -= 1; + if (tot_doubles_left == 0) { + break; + } + } + } + result = CDDM_merge_verts(result, full_doubles_map, (int)(tot_doubles * (step_tot - 1)), CDDM_MERGE_VERTS_DUMP_IF_MAPPED); + MEM_freeN(full_doubles_map); + } + return result; +} static void initData(ModifierData *md) { @@ -123,6 +173,7 @@ static void initData(ModifierData *md) ltmd->steps = 16; ltmd->render_steps = 16; ltmd->iter = 1; + ltmd->merge_dist = 0.01f; } static void copyData(ModifierData *md, ModifierData *target) @@ -1050,6 +1101,16 @@ static DerivedMesh *applyModifier(ModifierData *md, Object *ob, MEM_freeN(vert_loop_map); } + if ((ltmd->flag & MOD_SCREW_MERGE) && (screw_ofs == 0.0f)) { + DerivedMesh *result_prev = result; + result = dm_remove_doubles_on_axis( + result, mvert_new, totvert, step_tot, + axis_vec, ltmd->ob_axis ? mtx_tx[3] : NULL, ltmd->merge_dist); + if (result != result_prev) { + result->dirty |= DM_DIRTY_NORMALS; + } + } + if ((ltmd->flag & MOD_SCREW_NORMAL_CALC) == 0) { result->dirty |= DM_DIRTY_NORMALS; } -- cgit v1.2.3