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.
This commit is contained in:
Campbell Barton 2019-02-14 17:21:55 +11:00
parent caa8e7ff28
commit 6074f62d1a
Notes: blender-bot 2023-02-14 11:42:40 +01:00
Referenced by issue #61353, 2.8 beta crashes when converting curve to mesh
11 changed files with 58 additions and 25 deletions

View 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);

View 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(

View 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;

View 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])

View 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);

View 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;

View 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:

View 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);

View 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);

View 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);
}
}

View 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;