diff options
author | Campbell Barton <ideasman42@gmail.com> | 2014-02-25 16:01:50 +0400 |
---|---|---|
committer | Campbell Barton <ideasman42@gmail.com> | 2014-02-25 16:03:26 +0400 |
commit | ca2b4323a8b20e20c8b5ffe980d27da58d7b2b07 (patch) | |
tree | 373de975c507b4ff36428b1b62b06808ee7a6274 /source/blender/modifiers | |
parent | dbf653acb763392c92a30e7576fb4693fe167926 (diff) |
Fix T38003: Skin modifier crash with long edges
Diffstat (limited to 'source/blender/modifiers')
-rw-r--r-- | source/blender/modifiers/intern/MOD_skin.c | 33 |
1 files changed, 23 insertions, 10 deletions
diff --git a/source/blender/modifiers/intern/MOD_skin.c b/source/blender/modifiers/intern/MOD_skin.c index fa239cedb02..07be90b9ce1 100644 --- a/source/blender/modifiers/intern/MOD_skin.c +++ b/source/blender/modifiers/intern/MOD_skin.c @@ -753,10 +753,13 @@ static EMat *build_edge_mats(const MVertSkin *vs, static int calc_edge_subdivisions(const MVert *mvert, const MVertSkin *nodes, const MEdge *e, int *degree) { + /* prevent memory errors [#38003] */ +#define NUM_SUBDIVISIONS_MAX 128 + const MVertSkin *evs[2] = {&nodes[e->v1], &nodes[e->v2]}; - float edge_len, avg[2]; - int v1_branch = degree[e->v1] > 2; - int v2_branch = degree[e->v2] > 2; + float avg_radius; + const bool v1_branch = degree[e->v1] > 2; + const bool v2_branch = degree[e->v2] > 2; int num_subdivisions; /* If either end is a branch node marked 'loose', don't subdivide @@ -770,15 +773,23 @@ static int calc_edge_subdivisions(const MVert *mvert, const MVertSkin *nodes, return 0; } - edge_len = len_v3v3(mvert[e->v1].co, mvert[e->v2].co); - - avg[0] = half_v2(evs[0]->radius); - avg[1] = half_v2(evs[1]->radius); + avg_radius = half_v2(evs[0]->radius) + half_v2(evs[1]->radius); - if (avg[0] + avg[1] == 0.0f) + if (avg_radius != 0.0f) { + /* possible (but unlikely) that we overflow INT_MAX */ + float num_subdivisions_fl; + const float edge_len = len_v3v3(mvert[e->v1].co, mvert[e->v2].co); + num_subdivisions_fl = (edge_len / avg_radius); + if (num_subdivisions_fl < NUM_SUBDIVISIONS_MAX) { + num_subdivisions = (int)num_subdivisions_fl; + } + else { + num_subdivisions = NUM_SUBDIVISIONS_MAX; + } + } + else { num_subdivisions = 0; - else - num_subdivisions = (int)((float)edge_len / (avg[0] + avg[1])); + } /* If both ends are branch nodes, two intermediate nodes are * required */ @@ -786,6 +797,8 @@ static int calc_edge_subdivisions(const MVert *mvert, const MVertSkin *nodes, num_subdivisions = 2; return num_subdivisions; + +#undef NUM_SUBDIVISIONS_MAX } /* Take a DerivedMesh and subdivide its edges to keep skin nodes |