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:
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
|
@ -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);
|
||||
|
|
|
@ -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(
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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])
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
Loading…
Reference in New Issue