Fix T61353: Crash converting a curve to a mesh
authorCampbell Barton <ideasman42@gmail.com>
Thu, 14 Feb 2019 06:21:55 +0000 (17:21 +1100)
committerCampbell Barton <ideasman42@gmail.com>
Thu, 14 Feb 2019 06:21:55 +0000 (17:21 +1100)
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.

source/blender/blenkernel/BKE_curve.h
source/blender/blenkernel/BKE_displist.h
source/blender/blenkernel/intern/curve.c
source/blender/blenkernel/intern/displist.c
source/blender/blenkernel/intern/effect.c
source/blender/blenkernel/intern/mesh_convert.c
source/blender/blenkernel/intern/object_update.c
source/blender/editors/curve/editcurve.c
source/blender/editors/object/object_add.c
source/blender/editors/object/object_modifier.c
source/blender/editors/object/object_relations.c

index 236c5e8..fe8f9ac 100644 (file)
@@ -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);
index 3f9589a..c232234 100644 (file)
@@ -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(
index 8bb47a6..3be1011 100644 (file)
@@ -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;
index 869d5e6..0f3a319 100644 (file)
@@ -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])
index d10aafd..c3e9afc 100644 (file)
@@ -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);
index 3e7d517..ded0982 100644 (file)
@@ -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;
index 4975bc3..59068dc 100644 (file)
@@ -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:
index 23dc165..6c9932c 100644 (file)
@@ -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);
index 2931fb8..a6360ac 100644 (file)
@@ -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);
index d6aa74d..c91173d 100644 (file)
@@ -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);
        }
 }
 
index 970a64d..e5a5c04 100644 (file)
@@ -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;