Fix for crash caused by effectors doing precalculation //during// DAG
authorLukas Tönne <lukas.toenne@gmail.com>
Fri, 14 Feb 2014 11:54:42 +0000 (12:54 +0100)
committerLukas Tönne <lukas.toenne@gmail.com>
Fri, 14 Feb 2014 11:58:43 +0000 (12:58 +0100)
updates.

This file crashes on loading with NULL pointer access to curve_cache:
{F77132}

The pdInitEffectors function was amalgamating the simple
collection of effector objects with an automatic precalculation for
curve guides and the like. This precalculation requires object data
that may not be available until the DAG has finished.

Since for DAG dependencies only the list of effectors is required,
added an argument to disable precalculation when collecting effectors.

source/blender/blenkernel/BKE_effect.h
source/blender/blenkernel/intern/cloth.c
source/blender/blenkernel/intern/depsgraph.c
source/blender/blenkernel/intern/dynamicpaint.c
source/blender/blenkernel/intern/effect.c
source/blender/blenkernel/intern/particle_system.c
source/blender/blenkernel/intern/rigidbody.c
source/blender/blenkernel/intern/smoke.c
source/blender/blenkernel/intern/softbody.c

index 562a67f14f5f4095503e4f51ad42311d07d54115..d5e54d849cd7ff5c51851bd20a93ffa672a5db08 100644 (file)
@@ -110,8 +110,9 @@ typedef struct EffectorCache {
 } EffectorCache;
 
 void            free_partdeflect(struct PartDeflect *pd);
-struct ListBase *pdInitEffectors(struct Scene *scene, struct Object *ob_src, struct ParticleSystem *psys_src, struct EffectorWeights *weights);
+struct ListBase *pdInitEffectors(struct Scene *scene, struct Object *ob_src, struct ParticleSystem *psys_src, struct EffectorWeights *weights, bool precalc);
 void            pdEndEffectors(struct ListBase **effectors);
+void            pdPrecalculateEffectors(struct ListBase *effectors);
 void            pdDoEffectors(struct ListBase *effectors, struct ListBase *colliders, struct EffectorWeights *weights, struct EffectedPoint *point, float *force, float *impulse);
 
 void pd_point_from_particle(struct ParticleSimulationData *sim, struct ParticleData *pa, struct ParticleKey *state, struct EffectedPoint *point);
index acafa7628539dc222df31bdfa80dc3578c58688c..3ab522ac24b655c13e8df2ecf78ee7c9769e62ac 100644 (file)
@@ -376,7 +376,7 @@ static int do_step_cloth(Object *ob, ClothModifierData *clmd, DerivedMesh *resul
                mul_m4_v3(ob->obmat, verts->xconst);
        }
 
-       effectors = pdInitEffectors(clmd->scene, ob, NULL, clmd->sim_parms->effector_weights);
+       effectors = pdInitEffectors(clmd->scene, ob, NULL, clmd->sim_parms->effector_weights, true);
 
        /* Support for dynamic vertex groups, changing from frame to frame */
        cloth_apply_vgroup ( clmd, result );
index af84055fb50c91e2a72d2c8e72853e8b77525e59..fdeefad795bd06af4f570a406e520c485369462c 100644 (file)
@@ -761,7 +761,7 @@ static void build_dag_object(DagForest *dag, DagNode *scenenode, Scene *scene, O
                                }
                        }
 
-                       effectors = pdInitEffectors(scene, ob, psys, part->effector_weights);
+                       effectors = pdInitEffectors(scene, ob, psys, part->effector_weights, false);
 
                        if (effectors) {
                                for (eff = effectors->first; eff; eff = eff->next) {
index 817b81a6db3e09f9e76381046224a38f32a49175..997876dcd5898a7fb2462364ce38801f48fed33f 100644 (file)
@@ -4225,7 +4225,7 @@ static int dynamicPaint_prepareEffectStep(DynamicPaintSurface *surface, Scene *s
        /* Init force data if required */
        if (surface->effect & MOD_DPAINT_EFFECT_DO_DRIP) {
                float vel[3] = {0};
-               ListBase *effectors = pdInitEffectors(scene, ob, NULL, surface->effector_weights);
+               ListBase *effectors = pdInitEffectors(scene, ob, NULL, surface->effector_weights, true);
 
                /* allocate memory for force data (dir vector + strength) */
                *force = MEM_mallocN(sData->total_points * 4 * sizeof(float), "PaintEffectForces");
index a8124c0f9c0d8633ebbae2dd625a6da4eeba8b50..fc18a204526750004e6f304087dfd7fe65d6723b 100644 (file)
@@ -166,45 +166,6 @@ void free_partdeflect(PartDeflect *pd)
        MEM_freeN(pd);
 }
 
-static void precalculate_effector(EffectorCache *eff)
-{
-       unsigned int cfra = (unsigned int)(eff->scene->r.cfra >= 0 ? eff->scene->r.cfra : -eff->scene->r.cfra);
-       if (!eff->pd->rng)
-               eff->pd->rng = BLI_rng_new(eff->pd->seed + cfra);
-       else
-               BLI_rng_srandom(eff->pd->rng, eff->pd->seed + cfra);
-
-       if (eff->pd->forcefield == PFIELD_GUIDE && eff->ob->type==OB_CURVE) {
-               Curve *cu= eff->ob->data;
-               if (cu->flag & CU_PATH) {
-                       if (eff->ob->curve_cache == NULL || eff->ob->curve_cache->path==NULL || eff->ob->curve_cache->path->data==NULL)
-                               BKE_displist_make_curveTypes(eff->scene, eff->ob, 0);
-
-                       if (eff->ob->curve_cache->path && eff->ob->curve_cache->path->data) {
-                               where_on_path(eff->ob, 0.0, eff->guide_loc, eff->guide_dir, NULL, &eff->guide_radius, NULL);
-                               mul_m4_v3(eff->ob->obmat, eff->guide_loc);
-                               mul_mat3_m4_v3(eff->ob->obmat, eff->guide_dir);
-                       }
-               }
-       }
-       else if (eff->pd->shape == PFIELD_SHAPE_SURFACE) {
-               eff->surmd = (SurfaceModifierData *)modifiers_findByType( eff->ob, eModifierType_Surface );
-               if (eff->ob->type == OB_CURVE)
-                       eff->flag |= PE_USE_NORMAL_DATA;
-       }
-       else if (eff->psys)
-               psys_update_particle_tree(eff->psys, eff->scene->r.cfra);
-
-       /* Store object velocity */
-       if (eff->ob) {
-               float old_vel[3];
-
-               BKE_object_where_is_calc_time(eff->scene, eff->ob, cfra - 1.0f);
-               copy_v3_v3(old_vel, eff->ob->obmat[3]);
-               BKE_object_where_is_calc_time(eff->scene, eff->ob, cfra);
-               sub_v3_v3v3(eff->velocity, eff->ob->obmat[3], old_vel);
-       }
-}
 static EffectorCache *new_effector_cache(Scene *scene, Object *ob, ParticleSystem *psys, PartDeflect *pd)
 {
        EffectorCache *eff = MEM_callocN(sizeof(EffectorCache), "EffectorCache");
@@ -213,9 +174,6 @@ static EffectorCache *new_effector_cache(Scene *scene, Object *ob, ParticleSyste
        eff->psys = psys;
        eff->pd = pd;
        eff->frame = -1;
-
-       precalculate_effector(eff);
-
        return eff;
 }
 static void add_object_to_effectors(ListBase **effectors, Scene *scene, EffectorWeights *weights, Object *ob, Object *ob_src)
@@ -264,7 +222,8 @@ static void add_particles_to_effectors(ListBase **effectors, Scene *scene, Effec
 }
 
 /* returns ListBase handle with objects taking part in the effecting */
-ListBase *pdInitEffectors(Scene *scene, Object *ob_src, ParticleSystem *psys_src, EffectorWeights *weights)
+ListBase *pdInitEffectors(Scene *scene, Object *ob_src, ParticleSystem *psys_src,
+                          EffectorWeights *weights, bool precalc)
 {
        Base *base;
        unsigned int layer= ob_src->lay;
@@ -302,6 +261,10 @@ ListBase *pdInitEffectors(Scene *scene, Object *ob_src, ParticleSystem *psys_src
                        }
                }
        }
+       
+       if (precalc)
+               pdPrecalculateEffectors(effectors);
+       
        return effectors;
 }
 
@@ -321,6 +284,55 @@ void pdEndEffectors(ListBase **effectors)
        }
 }
 
+static void precalculate_effector(EffectorCache *eff)
+{
+       unsigned int cfra = (unsigned int)(eff->scene->r.cfra >= 0 ? eff->scene->r.cfra : -eff->scene->r.cfra);
+       if (!eff->pd->rng)
+               eff->pd->rng = BLI_rng_new(eff->pd->seed + cfra);
+       else
+               BLI_rng_srandom(eff->pd->rng, eff->pd->seed + cfra);
+
+       if (eff->pd->forcefield == PFIELD_GUIDE && eff->ob->type==OB_CURVE) {
+               Curve *cu= eff->ob->data;
+               if (cu->flag & CU_PATH) {
+                       if (eff->ob->curve_cache == NULL || eff->ob->curve_cache->path==NULL || eff->ob->curve_cache->path->data==NULL)
+                               BKE_displist_make_curveTypes(eff->scene, eff->ob, 0);
+
+                       if (eff->ob->curve_cache->path && eff->ob->curve_cache->path->data) {
+                               where_on_path(eff->ob, 0.0, eff->guide_loc, eff->guide_dir, NULL, &eff->guide_radius, NULL);
+                               mul_m4_v3(eff->ob->obmat, eff->guide_loc);
+                               mul_mat3_m4_v3(eff->ob->obmat, eff->guide_dir);
+                       }
+               }
+       }
+       else if (eff->pd->shape == PFIELD_SHAPE_SURFACE) {
+               eff->surmd = (SurfaceModifierData *)modifiers_findByType( eff->ob, eModifierType_Surface );
+               if (eff->ob->type == OB_CURVE)
+                       eff->flag |= PE_USE_NORMAL_DATA;
+       }
+       else if (eff->psys)
+               psys_update_particle_tree(eff->psys, eff->scene->r.cfra);
+
+       /* Store object velocity */
+       if (eff->ob) {
+               float old_vel[3];
+
+               BKE_object_where_is_calc_time(eff->scene, eff->ob, cfra - 1.0f);
+               copy_v3_v3(old_vel, eff->ob->obmat[3]);
+               BKE_object_where_is_calc_time(eff->scene, eff->ob, cfra);
+               sub_v3_v3v3(eff->velocity, eff->ob->obmat[3], old_vel);
+       }
+}
+
+void pdPrecalculateEffectors(ListBase *effectors)
+{
+       if (effectors) {
+               EffectorCache *eff = effectors->first;
+               for (; eff; eff=eff->next)
+                       precalculate_effector(eff);
+       }
+}
+
 
 void pd_point_from_particle(ParticleSimulationData *sim, ParticleData *pa, ParticleKey *state, EffectedPoint *point)
 {
index 71b9134072136f94dca0028904720c6a0f5afaf3..4eaa2618e26346184ae30183684fc69f2776de07 100644 (file)
@@ -2264,7 +2264,8 @@ void psys_update_particle_tree(ParticleSystem *psys, float cfra)
 static void psys_update_effectors(ParticleSimulationData *sim)
 {
        pdEndEffectors(&sim->psys->effectors);
-       sim->psys->effectors = pdInitEffectors(sim->scene, sim->ob, sim->psys, sim->psys->part->effector_weights);
+       sim->psys->effectors = pdInitEffectors(sim->scene, sim->ob, sim->psys,
+                                              sim->psys->part->effector_weights, true);
        precalc_guides(sim, sim->psys->effectors);
 }
 
index 216620c351da3d492f6bcf325627dff5a7d20bc9..4b4cb0543379b6d492c71e6f2cf0c69b7af6476f 100644 (file)
@@ -1066,7 +1066,7 @@ static void rigidbody_update_sim_ob(Scene *scene, RigidBodyWorld *rbw, Object *o
                ListBase *effectors;
 
                /* get effectors present in the group specified by effector_weights */
-               effectors = pdInitEffectors(scene, ob, NULL, effector_weights);
+               effectors = pdInitEffectors(scene, ob, NULL, effector_weights, true);
                if (effectors) {
                        float eff_force[3] = {0.0f, 0.0f, 0.0f};
                        float eff_loc[3], eff_vel[3];
index 6aaf2ee4df0b21850b974de950e654d5305a2f4e..61d9ea99c2f25f14b17bc2aa30b2a59d052dc902 100644 (file)
@@ -2363,7 +2363,7 @@ static void update_effectors(Scene *scene, Object *ob, SmokeDomainSettings *sds,
        ListBase *effectors;
        /* make sure smoke flow influence is 0.0f */
        sds->effector_weights->weight[PFIELD_SMOKEFLOW] = 0.0f;
-       effectors = pdInitEffectors(scene, ob, NULL, sds->effector_weights);
+       effectors = pdInitEffectors(scene, ob, NULL, sds->effector_weights, true);
 
        if (effectors)
        {
index 4e2f708eae4b80cab0425413e39574b4c4d4354b..fb5fc97fd460c9c9ce9bbe30a87df470e0e7c807 100644 (file)
@@ -1642,7 +1642,7 @@ static void scan_for_ext_spring_forces(Scene *scene, Object *ob, float timenow)
        SoftBody *sb = ob->soft;
        ListBase *do_effector = NULL;
 
-       do_effector = pdInitEffectors(scene, ob, NULL, sb->effector_weights);
+       do_effector = pdInitEffectors(scene, ob, NULL, sb->effector_weights, true);
        _scan_for_ext_spring_forces(scene, ob, timenow, 0, sb->totspring, do_effector);
        pdEndEffectors(&do_effector);
 }
@@ -1662,7 +1662,7 @@ static void sb_sfesf_threads_run(Scene *scene, struct Object *ob, float timenow,
        int i, totthread, left, dec;
        int lowsprings =100; /* wild guess .. may increase with better thread management 'above' or even be UI option sb->spawn_cf_threads_nopts */
 
-       do_effector= pdInitEffectors(scene, ob, NULL, ob->soft->effector_weights);
+       do_effector= pdInitEffectors(scene, ob, NULL, ob->soft->effector_weights, true);
 
        /* figure the number of threads while preventing pretty pointless threading overhead */
        totthread= BKE_scene_num_threads(scene);
@@ -2468,7 +2468,7 @@ static void softbody_calc_forcesEx(Scene *scene, Object *ob, float forcetime, fl
        sb_sfesf_threads_run(scene, ob, timenow, sb->totspring, NULL);
 
        /* after spring scan because it uses Effoctors too */
-       do_effector= pdInitEffectors(scene, ob, NULL, sb->effector_weights);
+       do_effector= pdInitEffectors(scene, ob, NULL, sb->effector_weights, true);
 
        if (do_deflector) {
                float defforce[3];
@@ -2543,7 +2543,7 @@ static void softbody_calc_forces(Scene *scene, Object *ob, float forcetime, floa
 
                if (do_springcollision || do_aero)  scan_for_ext_spring_forces(scene, ob, timenow);
                /* after spring scan because it uses Effoctors too */
-               do_effector= pdInitEffectors(scene, ob, NULL, ob->soft->effector_weights);
+               do_effector= pdInitEffectors(scene, ob, NULL, ob->soft->effector_weights, true);
 
                if (do_deflector) {
                        float defforce[3];