diff options
author | Campbell Barton <ideasman42@gmail.com> | 2019-02-14 09:21:55 +0300 |
---|---|---|
committer | Campbell Barton <ideasman42@gmail.com> | 2019-02-14 09:21:55 +0300 |
commit | 6074f62d1a099fc378aa25506a93321dba2d956b (patch) | |
tree | becbb4abdb6c9c9a047c1a6f5d5c94c53e56ff50 | |
parent | caa8e7ff2894ed22ea436bc61b06fb292d844108 (diff) |
Fix T61353: Crash converting a curve to a mesh
This was caused by curves pointing to each other
creating a cyclic dependency.
While the dependency graph detects this, generating a mesh for render
recursively generates data which cashes in this case.
Add in a check to detect cyclic links.
Note, this bug exists in 2.7x too - but only crashes on render
since 2.7x didn't use 'for_render' when converting data.
-rw-r--r-- | source/blender/blenkernel/BKE_curve.h | 4 | ||||
-rw-r--r-- | source/blender/blenkernel/BKE_displist.h | 10 | ||||
-rw-r--r-- | source/blender/blenkernel/intern/curve.c | 17 | ||||
-rw-r--r-- | source/blender/blenkernel/intern/displist.c | 36 | ||||
-rw-r--r-- | source/blender/blenkernel/intern/effect.c | 2 | ||||
-rw-r--r-- | source/blender/blenkernel/intern/mesh_convert.c | 4 | ||||
-rw-r--r-- | source/blender/blenkernel/intern/object_update.c | 2 | ||||
-rw-r--r-- | source/blender/editors/curve/editcurve.c | 2 | ||||
-rw-r--r-- | source/blender/editors/object/object_add.c | 2 | ||||
-rw-r--r-- | source/blender/editors/object/object_modifier.c | 2 | ||||
-rw-r--r-- | source/blender/editors/object/object_relations.c | 2 |
11 files changed, 58 insertions, 25 deletions
diff --git a/source/blender/blenkernel/BKE_curve.h b/source/blender/blenkernel/BKE_curve.h index 236c5e8da06..fe8f9ace134 100644 --- a/source/blender/blenkernel/BKE_curve.h +++ b/source/blender/blenkernel/BKE_curve.h @@ -27,6 +27,7 @@ struct Curve; struct Depsgraph; struct EditNurb; struct GHash; +struct LinkNode; struct ListBase; struct Main; struct Nurb; @@ -119,7 +120,8 @@ void BKE_curve_bevelList_free(struct ListBase *bev); void BKE_curve_bevelList_make(struct Object *ob, struct ListBase *nurbs, bool for_render); void BKE_curve_bevel_make( struct Depsgraph *depsgraph, struct Scene *scene, struct Object *ob, struct ListBase *disp, - const bool for_render, const bool use_render_resolution); + const bool for_render, const bool use_render_resolution, + struct LinkNode *ob_cyclic_list); void BKE_curve_forward_diff_bezier(float q0, float q1, float q2, float q3, float *p, int it, int stride); void BKE_curve_forward_diff_tangent_bezier(float q0, float q1, float q2, float q3, float *p, int it, int stride); diff --git a/source/blender/blenkernel/BKE_displist.h b/source/blender/blenkernel/BKE_displist.h index 3f9589ae341..c232234dd62 100644 --- a/source/blender/blenkernel/BKE_displist.h +++ b/source/blender/blenkernel/BKE_displist.h @@ -49,6 +49,7 @@ enum { /* prototypes */ struct Depsgraph; +struct LinkNode; struct ListBase; struct Main; struct Mesh; @@ -83,12 +84,15 @@ void BKE_displist_make_surf( struct Mesh **r_final, const bool for_render, const bool for_orco, const bool use_render_resolution); void BKE_displist_make_curveTypes( struct Depsgraph *depsgraph, struct Scene *scene, struct Object *ob, - const bool for_render, const bool for_orco); + const bool for_render, const bool for_orco, + struct LinkNode *ob_cyclic_list); void BKE_displist_make_curveTypes_forRender( struct Depsgraph *depsgraph, struct Scene *scene, struct Object *ob, struct ListBase *dispbase, - struct Mesh **r_final, const bool for_orco, const bool use_render_resolution); + struct Mesh **r_final, const bool for_orco, const bool use_render_resolution, + struct LinkNode *ob_cyclic_list); void BKE_displist_make_curveTypes_forOrco( - struct Depsgraph *depsgraph, struct Scene *scene, struct Object *ob, struct ListBase *dispbase); + struct Depsgraph *depsgraph, struct Scene *scene, struct Object *ob, struct ListBase *dispbase, + struct LinkNode *ob_cyclic_list); void BKE_displist_make_mball( struct Depsgraph *depsgraph, struct Scene *scene, struct Object *ob); void BKE_displist_make_mball_forRender( diff --git a/source/blender/blenkernel/intern/curve.c b/source/blender/blenkernel/intern/curve.c index 8bb47a6a69b..3be101134ec 100644 --- a/source/blender/blenkernel/intern/curve.c +++ b/source/blender/blenkernel/intern/curve.c @@ -31,6 +31,7 @@ #include "BLI_math.h" #include "BLI_utildefines.h" #include "BLI_ghash.h" +#include "BLI_linklist.h" #include "DNA_anim_types.h" #include "DNA_curve_types.h" @@ -1735,7 +1736,7 @@ float *BKE_curve_make_orco(Depsgraph *depsgraph, Scene *scene, Object *ob, int * float *fp, *coord_array; ListBase disp = {NULL, NULL}; - BKE_displist_make_curveTypes_forOrco(depsgraph, scene, ob, &disp); + BKE_displist_make_curveTypes_forOrco(depsgraph, scene, ob, &disp, NULL); numVerts = 0; for (dl = disp.first; dl; dl = dl->next) { @@ -1828,7 +1829,8 @@ float *BKE_curve_make_orco(Depsgraph *depsgraph, Scene *scene, Object *ob, int * void BKE_curve_bevel_make( Depsgraph *depsgraph, Scene *scene, Object *ob, ListBase *disp, - const bool for_render, const bool use_render_resolution) + const bool for_render, const bool use_render_resolution, + LinkNode *ob_cyclic_list) { DispList *dl, *dlnew; Curve *bevcu, *cu; @@ -1852,8 +1854,15 @@ void BKE_curve_bevel_make( facy = cu->bevobj->size[1]; if (for_render) { - BKE_displist_make_curveTypes_forRender(depsgraph, scene, cu->bevobj, &bevdisp, NULL, false, use_render_resolution); - dl = bevdisp.first; + if (BLI_linklist_index(ob_cyclic_list, cu->bevobj) == -1) { + BKE_displist_make_curveTypes_forRender( + depsgraph, scene, cu->bevobj, &bevdisp, NULL, false, use_render_resolution, + &(LinkNode){ .link = ob, .next = ob_cyclic_list, }); + dl = bevdisp.first; + } + else { + dl = NULL; + } } else if (cu->bevobj->runtime.curve_cache) { dl = cu->bevobj->runtime.curve_cache->disp.first; diff --git a/source/blender/blenkernel/intern/displist.c b/source/blender/blenkernel/intern/displist.c index 869d5e6f362..0f3a3192d75 100644 --- a/source/blender/blenkernel/intern/displist.c +++ b/source/blender/blenkernel/intern/displist.c @@ -38,6 +38,7 @@ #include "BLI_math.h" #include "BLI_scanfill.h" #include "BLI_utildefines.h" +#include "BLI_linklist.h" #include "BKE_displist.h" #include "BKE_cdderivedmesh.h" @@ -683,7 +684,7 @@ static float displist_calc_taper(Depsgraph *depsgraph, Scene *scene, Object *tap dl = taperobj->runtime.curve_cache ? taperobj->runtime.curve_cache->disp.first : NULL; if (dl == NULL) { - BKE_displist_make_curveTypes(depsgraph, scene, taperobj, false, false); + BKE_displist_make_curveTypes(depsgraph, scene, taperobj, false, false, NULL); dl = taperobj->runtime.curve_cache->disp.first; } if (dl) { @@ -1554,8 +1555,9 @@ static void calc_bevfac_mapping(Curve *cu, BevList *bl, Nurb *nu, static void do_makeDispListCurveTypes( Depsgraph *depsgraph, Scene *scene, Object *ob, ListBase *dispbase, - Mesh **r_final, - const bool for_render, const bool for_orco, const bool use_render_resolution) + const bool for_render, const bool for_orco, const bool use_render_resolution, + LinkNode *ob_cyclic_list, + Mesh **r_final) { Curve *cu = ob->data; @@ -1593,7 +1595,9 @@ static void do_makeDispListCurveTypes( BKE_curve_bevelList_make(ob, &nubase, use_render_resolution); /* If curve has no bevel will return nothing */ - BKE_curve_bevel_make(depsgraph, scene, ob, &dlbev, for_render, use_render_resolution); + BKE_curve_bevel_make( + depsgraph, scene, ob, &dlbev, for_render, use_render_resolution, + ob_cyclic_list); /* no bevel or extrude, and no width correction? */ if (!dlbev.first && cu->width == 1.0f) { @@ -1801,7 +1805,8 @@ static void do_makeDispListCurveTypes( } void BKE_displist_make_curveTypes( - Depsgraph *depsgraph, Scene *scene, Object *ob, const bool for_render, const bool for_orco) + Depsgraph *depsgraph, Scene *scene, Object *ob, const bool for_render, const bool for_orco, + LinkNode *ob_cyclic_list) { ListBase *dispbase; @@ -1819,7 +1824,10 @@ void BKE_displist_make_curveTypes( dispbase = &(ob->runtime.curve_cache->disp); - do_makeDispListCurveTypes(depsgraph, scene, ob, dispbase, &ob->runtime.mesh_eval, for_render, for_orco, false); + do_makeDispListCurveTypes( + depsgraph, scene, ob, dispbase, for_render, for_orco, false, + ob_cyclic_list, + &ob->runtime.mesh_eval); boundbox_displist_object(ob); } @@ -1827,23 +1835,31 @@ void BKE_displist_make_curveTypes( void BKE_displist_make_curveTypes_forRender( Depsgraph *depsgraph, Scene *scene, Object *ob, ListBase *dispbase, Mesh **r_final, const bool for_orco, - const bool use_render_resolution) + const bool use_render_resolution, + LinkNode *ob_cyclic_list) { if (ob->runtime.curve_cache == NULL) { ob->runtime.curve_cache = MEM_callocN(sizeof(CurveCache), "CurveCache for Curve"); } - do_makeDispListCurveTypes(depsgraph, scene, ob, dispbase, r_final, true, for_orco, use_render_resolution); + do_makeDispListCurveTypes( + depsgraph, scene, ob, dispbase, true, for_orco, use_render_resolution, + ob_cyclic_list, + r_final); } void BKE_displist_make_curveTypes_forOrco( - Depsgraph *depsgraph, Scene *scene, Object *ob, ListBase *dispbase) + Depsgraph *depsgraph, Scene *scene, Object *ob, ListBase *dispbase, + LinkNode *ob_cyclic_list) { if (ob->runtime.curve_cache == NULL) { ob->runtime.curve_cache = MEM_callocN(sizeof(CurveCache), "CurveCache for Curve"); } - do_makeDispListCurveTypes(depsgraph, scene, ob, dispbase, NULL, 1, 1, 1); + do_makeDispListCurveTypes( + depsgraph, scene, ob, dispbase, 1, 1, 1, + ob_cyclic_list, + NULL); } void BKE_displist_minmax(ListBase *dispbase, float min[3], float max[3]) diff --git a/source/blender/blenkernel/intern/effect.c b/source/blender/blenkernel/intern/effect.c index d10aafdc513..c3e9afcca1e 100644 --- a/source/blender/blenkernel/intern/effect.c +++ b/source/blender/blenkernel/intern/effect.c @@ -158,7 +158,7 @@ static void precalculate_effector(struct Depsgraph *depsgraph, EffectorCache *ef Curve *cu = eff->ob->data; if (cu->flag & CU_PATH) { if (eff->ob->runtime.curve_cache == NULL || eff->ob->runtime.curve_cache->path == NULL || eff->ob->runtime.curve_cache->path->data == NULL) - BKE_displist_make_curveTypes(depsgraph, eff->scene, eff->ob, false, false); + BKE_displist_make_curveTypes(depsgraph, eff->scene, eff->ob, false, false, NULL); if (eff->ob->runtime.curve_cache->path && eff->ob->runtime.curve_cache->path->data) { where_on_path(eff->ob, 0.0, eff->guide_loc, eff->guide_dir, NULL, &eff->guide_radius, NULL); diff --git a/source/blender/blenkernel/intern/mesh_convert.c b/source/blender/blenkernel/intern/mesh_convert.c index 3e7d51716a1..ded0982c2da 100644 --- a/source/blender/blenkernel/intern/mesh_convert.c +++ b/source/blender/blenkernel/intern/mesh_convert.c @@ -896,7 +896,9 @@ Mesh *BKE_mesh_new_from_object( copycu->editnurb = tmpcu->editnurb; /* get updated display list, and convert to a mesh */ - BKE_displist_make_curveTypes_forRender(depsgraph, sce, tmpobj, &dispbase, &me_eval_final, false, render); + BKE_displist_make_curveTypes_forRender( + depsgraph, sce, tmpobj, &dispbase, &me_eval_final, false, render, + NULL); copycu->editfont = NULL; copycu->editnurb = NULL; diff --git a/source/blender/blenkernel/intern/object_update.c b/source/blender/blenkernel/intern/object_update.c index 4975bc3bafb..59068dc4cd5 100644 --- a/source/blender/blenkernel/intern/object_update.c +++ b/source/blender/blenkernel/intern/object_update.c @@ -202,7 +202,7 @@ void BKE_object_handle_data_update( case OB_CURVE: case OB_SURF: case OB_FONT: - BKE_displist_make_curveTypes(depsgraph, scene, ob, false, false); + BKE_displist_make_curveTypes(depsgraph, scene, ob, false, false, NULL); break; case OB_LATTICE: diff --git a/source/blender/editors/curve/editcurve.c b/source/blender/editors/curve/editcurve.c index 23dc165cc4c..6c9932cc6cc 100644 --- a/source/blender/editors/curve/editcurve.c +++ b/source/blender/editors/curve/editcurve.c @@ -6660,7 +6660,7 @@ static int match_texture_space_exec(bContext *C, wmOperator *UNUSED(op)) int a; if (object->runtime.curve_cache == NULL) { - BKE_displist_make_curveTypes(depsgraph, scene, object, false, false); + BKE_displist_make_curveTypes(depsgraph, scene, object, false, false, NULL); } INIT_MINMAX(min, max); diff --git a/source/blender/editors/object/object_add.c b/source/blender/editors/object/object_add.c index 2931fb89d7e..a6360ac2e38 100644 --- a/source/blender/editors/object/object_add.c +++ b/source/blender/editors/object/object_add.c @@ -1771,7 +1771,7 @@ static void convert_ensure_curve_cache(Depsgraph *depsgraph, Scene *scene, Objec if (ELEM(ob->type, OB_SURF, OB_CURVE, OB_FONT)) { /* We need 'for render' ON here, to enable computing bevel dipslist if needed. * Also makes sense anyway, we would not want e.g. to loose hidden parts etc. */ - BKE_displist_make_curveTypes(depsgraph, scene, ob, true, false); + BKE_displist_make_curveTypes(depsgraph, scene, ob, true, false, NULL); } else if (ob->type == OB_MBALL) { BKE_displist_make_mball(depsgraph, scene, ob); diff --git a/source/blender/editors/object/object_modifier.c b/source/blender/editors/object/object_modifier.c index d6aa74da273..c91173d95ca 100644 --- a/source/blender/editors/object/object_modifier.c +++ b/source/blender/editors/object/object_modifier.c @@ -105,7 +105,7 @@ static void object_force_modifier_update_for_bind(Depsgraph *depsgraph, Scene *s BKE_displist_make_mball(depsgraph, scene, ob); } else if (ELEM(ob->type, OB_CURVE, OB_SURF, OB_FONT)) { - BKE_displist_make_curveTypes(depsgraph, scene, ob, false, false); + BKE_displist_make_curveTypes(depsgraph, scene, ob, false, false, NULL); } } diff --git a/source/blender/editors/object/object_relations.c b/source/blender/editors/object/object_relations.c index 970a64d5e78..e5a5c045f9d 100644 --- a/source/blender/editors/object/object_relations.c +++ b/source/blender/editors/object/object_relations.c @@ -628,7 +628,7 @@ bool ED_object_parent_set(ReportList *reports, const bContext *C, Scene *scene, if ((cu->flag & CU_PATH) == 0) { cu->flag |= CU_PATH | CU_FOLLOW; /* force creation of path data */ - BKE_displist_make_curveTypes(depsgraph, scene, par, false, false); + BKE_displist_make_curveTypes(depsgraph, scene, par, false, false, NULL); } else { cu->flag |= CU_FOLLOW; |