From 7f6521f8dc95f175eb09c77c26f5a3eb3dc7a3c0 Mon Sep 17 00:00:00 2001 From: Brecht Van Lommel Date: Wed, 9 Nov 2022 20:30:41 +0100 Subject: Fix T100883: crash with particle instancing and clumping Properly initialize clump curve mapping tables for duplis and other cases where this was missed by making a generic init/free function instead of duplicating the same logic in multiple places. Also fold lattice deform init into this. --- source/blender/blenkernel/BKE_particle.h | 8 +++- source/blender/blenkernel/intern/fluid.c | 14 ++---- source/blender/blenkernel/intern/object_dupli.cc | 8 +--- source/blender/blenkernel/intern/particle.c | 50 +++++++++++++++------- source/blender/blenkernel/intern/particle_system.c | 27 +++++------- .../draw/intern/draw_cache_impl_particles.c | 4 +- .../io/alembic/exporter/abc_writer_points.cc | 7 +-- source/blender/modifiers/intern/MOD_explode.c | 7 +-- .../modifiers/intern/MOD_particleinstance.c | 7 +-- .../blender/render/intern/texture_pointdensity.c | 14 ++---- 10 files changed, 69 insertions(+), 77 deletions(-) diff --git a/source/blender/blenkernel/BKE_particle.h b/source/blender/blenkernel/BKE_particle.h index a797aef73f6..05b9aca7544 100644 --- a/source/blender/blenkernel/BKE_particle.h +++ b/source/blender/blenkernel/BKE_particle.h @@ -291,7 +291,11 @@ void psys_set_current_num(struct Object *ob, int index); /* UNUSED */ // struct Object *psys_find_object(struct Scene *scene, struct ParticleSystem *psys); -struct LatticeDeformData *psys_create_lattice_deform_data(struct ParticleSimulationData *sim); +/** + * Initialize/free data for particle simulation evaluation. + */ +void psys_sim_data_init(struct ParticleSimulationData *sim); +void psys_sim_data_free(struct ParticleSimulationData *sim); /** * For a given evaluated particle system get its original. @@ -416,7 +420,7 @@ void psys_get_particle_on_path(struct ParticleSimulationData *sim, struct ParticleKey *state, bool vel); /** - * Gets particle's state at a time. + * Gets particle's state at a time. Must call psys_sim_data_init before this. * \return true if particle exists and can be seen and false if not. */ bool psys_get_particle_state(struct ParticleSimulationData *sim, diff --git a/source/blender/blenkernel/intern/fluid.c b/source/blender/blenkernel/intern/fluid.c index a3d2d73678c..c72f498cd5a 100644 --- a/source/blender/blenkernel/intern/fluid.c +++ b/source/blender/blenkernel/intern/fluid.c @@ -1532,18 +1532,8 @@ static void emit_from_particles(Object *flow_ob, sim.scene = scene; sim.ob = flow_ob; sim.psys = psys; - sim.psys->lattice_deform_data = psys_create_lattice_deform_data(&sim); - /* prepare curvemapping tables */ - if ((psys->part->child_flag & PART_CHILD_USE_CLUMP_CURVE) && psys->part->clumpcurve) { - BKE_curvemapping_changed_all(psys->part->clumpcurve); - } - if ((psys->part->child_flag & PART_CHILD_USE_ROUGH_CURVE) && psys->part->roughcurve) { - BKE_curvemapping_changed_all(psys->part->roughcurve); - } - if ((psys->part->child_flag & PART_CHILD_USE_TWIST_CURVE) && psys->part->twistcurve) { - BKE_curvemapping_changed_all(psys->part->twistcurve); - } + psys_sim_data_init(&sim); /* initialize particle cache */ if (psys->part->type == PART_HAIR) { @@ -1684,6 +1674,8 @@ static void emit_from_particles(Object *flow_ob, if (particle_vel) { MEM_freeN(particle_vel); } + + psys_sim_data_free(&sim); } } diff --git a/source/blender/blenkernel/intern/object_dupli.cc b/source/blender/blenkernel/intern/object_dupli.cc index a41f7c8bce4..5efd44c620b 100644 --- a/source/blender/blenkernel/intern/object_dupli.cc +++ b/source/blender/blenkernel/intern/object_dupli.cc @@ -1390,7 +1390,7 @@ static void make_duplis_particle_system(const DupliContext *ctx, ParticleSystem RNG *rng = BLI_rng_new_srandom(31415926u + uint(psys->seed)); - psys->lattice_deform_data = psys_create_lattice_deform_data(&sim); + psys_sim_data_init(&sim); /* Gather list of objects or single object. */ int totcollection = 0; @@ -1612,17 +1612,13 @@ static void make_duplis_particle_system(const DupliContext *ctx, ParticleSystem } BLI_rng_free(rng); + psys_sim_data_free(&sim); } /* Clean up. */ if (oblist) { MEM_freeN(oblist); } - - if (psys->lattice_deform_data) { - BKE_lattice_deform_data_destroy(psys->lattice_deform_data); - psys->lattice_deform_data = nullptr; - } } static void make_duplis_particles(const DupliContext *ctx) diff --git a/source/blender/blenkernel/intern/particle.c b/source/blender/blenkernel/intern/particle.c index 4a0a09bcf56..6a277295efd 100644 --- a/source/blender/blenkernel/intern/particle.c +++ b/source/blender/blenkernel/intern/particle.c @@ -684,10 +684,13 @@ void psys_set_current_num(Object *ob, int index) } } -struct LatticeDeformData *psys_create_lattice_deform_data(ParticleSimulationData *sim) +void psys_sim_data_init(ParticleSimulationData *sim) { - struct LatticeDeformData *lattice_deform_data = NULL; + ParticleSystem *psys = sim->psys; + ParticleSettings *part = psys->part; + /* Prepare lattice deform. */ + psys->lattice_deform_data = NULL; if (psys_in_edit_mode(sim->depsgraph, sim->psys) == 0) { Object *lattice = NULL; ModifierData *md = (ModifierData *)psys_get_modifier(sim->ob, sim->psys); @@ -699,19 +702,39 @@ struct LatticeDeformData *psys_create_lattice_deform_data(ParticleSimulationData if (md->mode & mode) { LatticeModifierData *lmd = (LatticeModifierData *)md; lattice = lmd->object; - sim->psys->lattice_strength = lmd->strength; + psys->lattice_strength = lmd->strength; } break; } } if (lattice) { - lattice_deform_data = BKE_lattice_deform_data_create(lattice, NULL); + psys->lattice_deform_data = BKE_lattice_deform_data_create(lattice, NULL); } } - return lattice_deform_data; + /* Prepare curvemapping tables. */ + if ((part->child_flag & PART_CHILD_USE_CLUMP_CURVE) && part->clumpcurve) { + BKE_curvemapping_init(part->clumpcurve); + } + if ((part->child_flag & PART_CHILD_USE_ROUGH_CURVE) && part->roughcurve) { + BKE_curvemapping_init(part->roughcurve); + } + if ((part->child_flag & PART_CHILD_USE_TWIST_CURVE) && part->twistcurve) { + BKE_curvemapping_init(part->twistcurve); + } } + +void psys_sim_data_free(ParticleSimulationData *sim) +{ + ParticleSystem *psys = sim->psys; + + if (psys->lattice_deform_data) { + BKE_lattice_deform_data_destroy(psys->lattice_deform_data); + psys->lattice_deform_data = NULL; + } +} + void psys_disable_all(Object *ob) { ParticleSystem *psys = ob->particlesystem.first; @@ -2784,7 +2807,7 @@ static bool psys_thread_context_init_path(ParticleThreadContext *ctx, ctx->cfra = cfra; ctx->editupdate = editupdate; - psys->lattice_deform_data = psys_create_lattice_deform_data(&ctx->sim); + psys_sim_data_init(&ctx->sim); /* cache all relevant vertex groups if they exist */ ctx->vg_length = psys_cache_vgroup(ctx->mesh, psys, PSYS_VG_LENGTH); @@ -3340,7 +3363,7 @@ void psys_cache_paths(ParticleSimulationData *sim, float cfra, const bool use_re cache = psys->pathcache = psys_alloc_path_cache_buffers( &psys->pathcachebufs, totpart, segments + 1); - psys->lattice_deform_data = psys_create_lattice_deform_data(sim); + psys_sim_data_init(sim); ma = BKE_object_material_get(sim->ob, psys->part->omat); if (ma && (psys->part->draw_col == PART_DRAW_COL_MAT)) { copy_v3_v3(col, &ma->r); @@ -3507,10 +3530,7 @@ void psys_cache_paths(ParticleSimulationData *sim, float cfra, const bool use_re psys->totcached = totpart; - if (psys->lattice_deform_data) { - BKE_lattice_deform_data_destroy(psys->lattice_deform_data); - psys->lattice_deform_data = NULL; - } + psys_sim_data_free(sim); if (vg_effector) { MEM_freeN(vg_effector); @@ -4867,6 +4887,7 @@ void psys_get_particle_on_path(ParticleSimulationData *sim, } } } + bool psys_get_particle_state(ParticleSimulationData *sim, int p, ParticleKey *state, @@ -5225,7 +5246,7 @@ void psys_apply_hair_lattice(Depsgraph *depsgraph, Scene *scene, Object *ob, Par sim.psys = psys; sim.psmd = psys_get_modifier(ob, psys); - psys->lattice_deform_data = psys_create_lattice_deform_data(&sim); + psys_sim_data_init(&sim); if (psys->lattice_deform_data) { ParticleData *pa = psys->particles; @@ -5246,12 +5267,11 @@ void psys_apply_hair_lattice(Depsgraph *depsgraph, Scene *scene, Object *ob, Par } } - BKE_lattice_deform_data_destroy(psys->lattice_deform_data); - psys->lattice_deform_data = NULL; - /* protect the applied shape */ psys->flag |= PSYS_EDITED; } + + psys_sim_data_free(&sim); } /* Draw Engine */ diff --git a/source/blender/blenkernel/intern/particle_system.c b/source/blender/blenkernel/intern/particle_system.c index 72094f8cf04..d97a217a734 100644 --- a/source/blender/blenkernel/intern/particle_system.c +++ b/source/blender/blenkernel/intern/particle_system.c @@ -516,10 +516,7 @@ void psys_thread_context_free(ParticleThreadContext *ctx) MEM_freeN(ctx->vg_twist); } - if (ctx->sim.psys->lattice_deform_data) { - BKE_lattice_deform_data_destroy(ctx->sim.psys->lattice_deform_data); - ctx->sim.psys->lattice_deform_data = NULL; - } + psys_sim_data_free(&ctx->sim); /* distribution */ if (ctx->jit) { @@ -3557,12 +3554,12 @@ static void save_hair(ParticleSimulationData *sim, float UNUSED(cfra)) invert_m4_m4(ob->world_to_object, ob->object_to_world); - psys->lattice_deform_data = psys_create_lattice_deform_data(sim); - if (psys->totpart == 0) { return; } + psys_sim_data_init(sim); + /* save new keys for elements if needed */ LOOP_PARTICLES { @@ -3596,6 +3593,8 @@ static void save_hair(ParticleSimulationData *sim, float UNUSED(cfra)) zero_v3(root->co); } } + + psys_sim_data_free(sim); } /* Code for an adaptive time step based on the Courant-Friedrichs-Lewy @@ -4099,6 +4098,8 @@ static void cached_step(ParticleSimulationData *sim, float cfra, const bool use_ disp = psys_get_current_display_percentage(psys, use_render_params); + psys_sim_data_init(sim); + LOOP_PARTICLES { psys_get_texture(sim, pa, &ptex, PAMAP_SIZE, cfra); @@ -4107,8 +4108,6 @@ static void cached_step(ParticleSimulationData *sim, float cfra, const bool use_ pa->size *= 1.0f - part->randsize * psys_frand(psys, p + 1); } - psys->lattice_deform_data = psys_create_lattice_deform_data(sim); - dietime = pa->dietime; /* update alive status and push events */ @@ -4125,11 +4124,6 @@ static void cached_step(ParticleSimulationData *sim, float cfra, const bool use_ pa->alive = PARS_ALIVE; } - if (psys->lattice_deform_data) { - BKE_lattice_deform_data_destroy(psys->lattice_deform_data); - psys->lattice_deform_data = NULL; - } - if (psys_frand(psys, p) > disp) { pa->flag |= PARS_NO_DISP; } @@ -4137,6 +4131,8 @@ static void cached_step(ParticleSimulationData *sim, float cfra, const bool use_ pa->flag &= ~PARS_NO_DISP; } } + + psys_sim_data_free(sim); } static bool particles_has_flip(short parttype) @@ -4609,10 +4605,7 @@ static void system_step(ParticleSimulationData *sim, float cfra, const bool use_ update_children(sim, use_render_params); /* cleanup */ - if (psys->lattice_deform_data) { - BKE_lattice_deform_data_destroy(psys->lattice_deform_data); - psys->lattice_deform_data = NULL; - } + psys_sim_data_free(sim); } void psys_changed_type(Object *ob, ParticleSystem *psys) diff --git a/source/blender/draw/intern/draw_cache_impl_particles.c b/source/blender/draw/intern/draw_cache_impl_particles.c index 8facea4333f..cddab74c46f 100644 --- a/source/blender/draw/intern/draw_cache_impl_particles.c +++ b/source/blender/draw/intern/draw_cache_impl_particles.c @@ -1346,7 +1346,7 @@ static void particle_batch_cache_ensure_pos(Object *object, sim.ob = object; sim.psys = psys; sim.psmd = psys_get_modifier(object, psys); - sim.psys->lattice_deform_data = psys_create_lattice_deform_data(&sim); + psys_sim_data_init(&sim); GPU_VERTBUF_DISCARD_SAFE(point_cache->pos); @@ -1392,6 +1392,8 @@ static void particle_batch_cache_ensure_pos(Object *object, if (curr_point != psys->totpart) { GPU_vertbuf_data_resize(point_cache->pos, curr_point); } + + psys_sim_data_free(&sim); } static void drw_particle_update_ptcache_edit(Object *object_eval, diff --git a/source/blender/io/alembic/exporter/abc_writer_points.cc b/source/blender/io/alembic/exporter/abc_writer_points.cc index 6ec6f736818..9372bffc3ca 100644 --- a/source/blender/io/alembic/exporter/abc_writer_points.cc +++ b/source/blender/io/alembic/exporter/abc_writer_points.cc @@ -85,7 +85,7 @@ void ABCPointsWriter::do_write(HierarchyContext &context) sim.ob = context.object; sim.psys = psys; - psys->lattice_deform_data = psys_create_lattice_deform_data(&sim); + psys_sim_data_init(&sim); uint64_t index = 0; for (int p = 0; p < psys->totpart; p++) { @@ -113,10 +113,7 @@ void ABCPointsWriter::do_write(HierarchyContext &context) ids.push_back(index++); } - if (psys->lattice_deform_data) { - BKE_lattice_deform_data_destroy(psys->lattice_deform_data); - psys->lattice_deform_data = nullptr; - } + psys_sim_data_free(&sim); Alembic::Abc::P3fArraySample psample(points); Alembic::Abc::UInt64ArraySample idsample(ids); diff --git a/source/blender/modifiers/intern/MOD_explode.c b/source/blender/modifiers/intern/MOD_explode.c index 96bf836fa4a..b0806fed91c 100644 --- a/source/blender/modifiers/intern/MOD_explode.c +++ b/source/blender/modifiers/intern/MOD_explode.c @@ -987,7 +987,7 @@ static Mesh *explodeMesh(ExplodeModifierData *emd, /* getting back to object space */ invert_m4_m4(imat, ctx->object->object_to_world); - psmd->psys->lattice_deform_data = psys_create_lattice_deform_data(&sim); + psys_sim_data_init(&sim); const MVert *mesh_verts = BKE_mesh_verts(mesh); MVert *explode_verts = BKE_mesh_verts_for_write(explode); @@ -1112,10 +1112,7 @@ static Mesh *explodeMesh(ExplodeModifierData *emd, BKE_mesh_calc_edges_tessface(explode); BKE_mesh_convert_mfaces_to_mpolys(explode); - if (psmd->psys->lattice_deform_data) { - BKE_lattice_deform_data_destroy(psmd->psys->lattice_deform_data); - psmd->psys->lattice_deform_data = NULL; - } + psys_sim_data_free(&sim); return explode; } diff --git a/source/blender/modifiers/intern/MOD_particleinstance.c b/source/blender/modifiers/intern/MOD_particleinstance.c index f65f8bc4fb3..46e14dd6bfb 100644 --- a/source/blender/modifiers/intern/MOD_particleinstance.c +++ b/source/blender/modifiers/intern/MOD_particleinstance.c @@ -303,7 +303,7 @@ static Mesh *modifyMesh(ModifierData *md, const ModifierEvalContext *ctx, Mesh * maxedge += totedge; } - psys->lattice_deform_data = psys_create_lattice_deform_data(&sim); + psys_sim_data_init(&sim); if (psys->flag & (PSYS_HAIR_DONE | PSYS_KEYED) || psys->pointcache->flag & PTCACHE_BAKED) { float min[3], max[3]; @@ -514,10 +514,7 @@ static Mesh *modifyMesh(ModifierData *md, const ModifierEvalContext *ctx, Mesh * p_skip++; } - if (psys->lattice_deform_data) { - BKE_lattice_deform_data_destroy(psys->lattice_deform_data); - psys->lattice_deform_data = NULL; - } + psys_sim_data_free(&sim); if (size) { MEM_freeN(size); diff --git a/source/blender/render/intern/texture_pointdensity.c b/source/blender/render/intern/texture_pointdensity.c index 5c31192f62a..09173aaa0e3 100644 --- a/source/blender/render/intern/texture_pointdensity.c +++ b/source/blender/render/intern/texture_pointdensity.c @@ -178,7 +178,7 @@ static void pointdensity_cache_psys( invert_m4_m4(ob->world_to_object, ob->object_to_world); total_particles = psys->totpart + psys->totchild; - psys->lattice_deform_data = psys_create_lattice_deform_data(&sim); + psys_sim_data_init(&sim); pd->point_tree = BLI_bvhtree_new(total_particles, 0.0, 4, 6); pd->totpoints = total_particles; @@ -258,10 +258,7 @@ static void pointdensity_cache_psys( BLI_bvhtree_balance(pd->point_tree); - if (psys->lattice_deform_data) { - BKE_lattice_deform_data_destroy(psys->lattice_deform_data); - psys->lattice_deform_data = NULL; - } + psys_sim_data_free(&sim); } static void pointdensity_cache_vertex_color(PointDensity *pd, @@ -780,7 +777,7 @@ static void particle_system_minmax(Depsgraph *depsgraph, invert_m4_m4(imat, object->object_to_world); total_particles = psys->totpart + psys->totchild; - psys->lattice_deform_data = psys_create_lattice_deform_data(&sim); + psys_sim_data_init(&sim); for (i = 0, pa = psys->particles; i < total_particles; i++, pa++) { float co_object[3], co_min[3], co_max[3]; @@ -796,10 +793,7 @@ static void particle_system_minmax(Depsgraph *depsgraph, minmax_v3v3_v3(min, max, co_max); } - if (psys->lattice_deform_data) { - BKE_lattice_deform_data_destroy(psys->lattice_deform_data); - psys->lattice_deform_data = NULL; - } + psys_sim_data_free(&sim); } void RE_point_density_cache(struct Depsgraph *depsgraph, PointDensity *pd) -- cgit v1.2.3