diff options
author | Bastien Montagne <bastien@blender.org> | 2020-04-23 15:47:06 +0300 |
---|---|---|
committer | Bastien Montagne <bastien@blender.org> | 2020-04-23 15:48:48 +0300 |
commit | a0652430d0f824adb26de9d2ae22f80fec721f4e (patch) | |
tree | 1a7fe55ea5be572f3e422c13cfdcc270c395c546 /source/blender | |
parent | 3a0af215b946173402e7d23b7df8c16fdfd15d76 (diff) |
Array modifier: limit maximum amount of generated geometry.
Fixes T75278: Crash when modifier "Array-Fit Curve-Relative Offset"
nears zero.
Diffstat (limited to 'source/blender')
-rw-r--r-- | source/blender/modifiers/intern/MOD_array.c | 36 |
1 files changed, 33 insertions, 3 deletions
diff --git a/source/blender/modifiers/intern/MOD_array.c b/source/blender/modifiers/intern/MOD_array.c index ff5bf3d0ee4..bad1d7d3cf9 100644 --- a/source/blender/modifiers/intern/MOD_array.c +++ b/source/blender/modifiers/intern/MOD_array.c @@ -353,7 +353,6 @@ static Mesh *arrayModifier_doArray(ArrayModifierData *amd, const ModifierEvalContext *ctx, Mesh *mesh) { - const float eps = 1e-6f; const MVert *src_mvert; MVert *mv, *mv_prev, *result_dm_verts; @@ -473,21 +472,52 @@ static Mesh *arrayModifier_doArray(ArrayModifierData *amd, } } + /* About 67 million vertices max seems a decent limit for now. */ + const size_t max_num_vertices = 1 << 26; + /* calculate the maximum number of copies which will fit within the * prescribed length */ if (amd->fit_type == MOD_ARR_FITLENGTH || amd->fit_type == MOD_ARR_FITCURVE) { + const float float_epsilon = 1e-6f; + bool offset_is_too_small = false; float dist = len_v3(offset[3]); - if (dist > eps) { + if (dist > float_epsilon) { /* this gives length = first copy start to last copy end * add a tiny offset for floating point rounding errors */ - count = (length + eps) / dist + 1; + count = (length + float_epsilon) / dist + 1; + + /* Ensure we keep things to a reasonable level, in terms of rough total amount of generated + * vertices. + */ + if (((size_t)count * (size_t)chunk_nverts + (size_t)start_cap_nverts + + (size_t)end_cap_nverts) > max_num_vertices) { + count = 1; + offset_is_too_small = true; + } } else { /* if the offset has no translation, just make one copy */ count = 1; + offset_is_too_small = true; + } + + if (offset_is_too_small) { + modifier_setError( + &amd->modifier, + "The offset is too small, we cannot generate the amount of geometry it would require"); } } + /* Ensure we keep things to a reasonable level, in terms of rough total amount of generated + * vertices. + */ + else if (((size_t)count * (size_t)chunk_nverts + (size_t)start_cap_nverts + + (size_t)end_cap_nverts) > max_num_vertices) { + count = 1; + modifier_setError(&amd->modifier, + "The amount of copies is too high, we cannot generate the amount of " + "geometry it would require"); + } if (count < 1) { count = 1; |