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.
This commit is contained in:
Brecht Van Lommel 2022-11-09 20:30:41 +01:00
parent 8232cf5287
commit 7f6521f8dc
Notes: blender-bot 2023-02-13 22:39:58 +01:00
Referenced by issue #100749, Blender LTS: Maintenance Task 3.3
Referenced by issue #100883, Crash when opening a file with instances for child particles with Curve Clumping
10 changed files with 69 additions and 77 deletions

View File

@ -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,

View File

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

View File

@ -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)

View File

@ -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 */

View File

@ -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)

View File

@ -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,

View File

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

View File

@ -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;
}

View File

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

View File

@ -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)