Depsgraph: cache collision relations, for performance and stability.

Same reasoning as effector relations in earlier commit.
This commit is contained in:
Brecht Van Lommel 2018-06-22 14:42:03 +02:00
parent 5b3ff9f7d8
commit a99dcab148
28 changed files with 298 additions and 208 deletions

View File

@ -210,10 +210,10 @@ typedef struct ColliderContacts {
} ColliderContacts;
// needed for implicit.c
int cloth_bvh_objcollision (struct Scene *scene, struct Object *ob, struct ClothModifierData *clmd, float step, float dt );
int cloth_points_objcollision(struct Scene *scene, struct Object *ob, struct ClothModifierData *clmd, float step, float dt);
int cloth_bvh_objcollision (struct Depsgraph *depsgraph, struct Object *ob, struct ClothModifierData *clmd, float step, float dt );
int cloth_points_objcollision(struct Depsgraph *depsgraph, struct Object *ob, struct ClothModifierData *clmd, float step, float dt);
void cloth_find_point_contacts(struct Scene *scene, struct Object *ob, struct ClothModifierData *clmd, float step, float dt,
void cloth_find_point_contacts(struct Depsgraph *depsgraph, struct Object *ob, struct ClothModifierData *clmd, float step, float dt,
ColliderContacts **r_collider_contacts, int *r_totcolliders);
void cloth_free_contacts(ColliderContacts *collider_contacts, int totcolliders);

View File

@ -49,6 +49,7 @@ struct MFace;
struct MVert;
struct Object;
struct Scene;
struct Depsgraph;
struct MVertTri;
////////////////////////////////////////
@ -143,14 +144,29 @@ void collision_move_object(struct CollisionModifierData *collmd, float step, flo
void collision_get_collider_velocity(float vel_old[3], float vel_new[3], struct CollisionModifierData *collmd, struct CollPair *collpair);
/////////////////////////////////////////////////
// used in effect.c
/////////////////////////////////////////////////
/* explicit control over layer mask and dupli recursion */
struct Object **get_collisionobjects_ext(struct Scene *scene, struct Object *self, struct Collection *collection, unsigned int *numcollobj, unsigned int modifier_type, bool dupli);
/* Collision relations for dependency graph build. */
struct Object **get_collisionobjects(struct Scene *scene, struct Object *self, struct Collection *collection, unsigned int *numcollobj, unsigned int modifier_type);
typedef struct CollisionRelation {
struct CollisionRelation *next, *prev;
struct Object *ob;
} CollisionRelation;
struct ListBase *BKE_collision_relations_create(
struct Depsgraph *depsgraph,
struct Collection *collection,
unsigned int modifier_type);
void BKE_collision_relations_free(struct ListBase *relations);
/* Collision object lists for physics simulation evaluation. */
struct Object **BKE_collision_objects_create(
struct Depsgraph *depsgraph,
struct Object *self,
struct Collection *collection,
unsigned int *numcollobj,
unsigned int modifier_type);
void BKE_collision_objects_free(struct Object **objects);
typedef struct ColliderCache {
struct ColliderCache *next, *prev;
@ -158,8 +174,11 @@ typedef struct ColliderCache {
struct CollisionModifierData *collmd;
} ColliderCache;
struct ListBase *get_collider_cache(struct Scene *scene, struct Object *self, struct Collection *collection);
void free_collider_cache(struct ListBase **colliders);
struct ListBase *BKE_collider_cache_create(
struct Depsgraph *scene,
struct Object *self,
struct Collection *collection);
void BKE_collider_cache_free(struct ListBase **colliders);
/////////////////////////////////////////////////

View File

@ -130,7 +130,6 @@ void BKE_effector_relations_free(struct ListBase *lb);
struct ListBase *BKE_effectors_create(
struct Depsgraph *depsgraph,
struct Scene *scene,
struct Object *ob_src,
struct ParticleSystem *psys_src,
struct EffectorWeights *weights);

View File

@ -350,7 +350,7 @@ static int do_init_cloth(Object *ob, ClothModifierData *clmd, Mesh *result, int
return 1;
}
static int do_step_cloth(struct Depsgraph *depsgraph, Scene *scene, Object *ob, ClothModifierData *clmd, Mesh *result, int framenr)
static int do_step_cloth(Depsgraph *depsgraph, Object *ob, ClothModifierData *clmd, Mesh *result, int framenr)
{
ClothVertex *verts = NULL;
Cloth *cloth;
@ -375,7 +375,7 @@ static int do_step_cloth(struct Depsgraph *depsgraph, Scene *scene, Object *ob,
mul_m4_v3(ob->obmat, verts->xconst);
}
effectors = BKE_effectors_create(depsgraph, scene, ob, NULL, clmd->sim_parms->effector_weights);
effectors = BKE_effectors_create(depsgraph, ob, NULL, clmd->sim_parms->effector_weights);
if (clmd->sim_parms->flags & CLOTH_SIMSETTINGS_FLAG_DYNAMIC_BASEMESH )
cloth_update_verts ( ob, clmd, result );
@ -391,7 +391,7 @@ static int do_step_cloth(struct Depsgraph *depsgraph, Scene *scene, Object *ob,
// TIMEIT_START(cloth_step)
/* call the solver. */
ret = BPH_cloth_solve(scene, ob, framenr, clmd, effectors);
ret = BPH_cloth_solve(depsgraph, ob, framenr, clmd, effectors);
// TIMEIT_END(cloth_step)
@ -405,7 +405,7 @@ static int do_step_cloth(struct Depsgraph *depsgraph, Scene *scene, Object *ob,
/************************************************
* clothModifier_do - main simulation function
************************************************/
void clothModifier_do(ClothModifierData *clmd, struct Depsgraph *depsgraph, Scene *scene, Object *ob, Mesh *mesh, float (*vertexCos)[3])
void clothModifier_do(ClothModifierData *clmd, Depsgraph *depsgraph, Scene *scene, Object *ob, Mesh *mesh, float (*vertexCos)[3])
{
PointCache *cache;
PTCacheID pid;
@ -492,7 +492,7 @@ void clothModifier_do(ClothModifierData *clmd, struct Depsgraph *depsgraph, Scen
/* do simulation */
BKE_ptcache_validate(cache, framenr);
if (!do_step_cloth(depsgraph, scene, ob, clmd, mesh, framenr)) {
if (!do_step_cloth(depsgraph, ob, clmd, mesh, framenr)) {
BKE_ptcache_invalidate(cache);
}
else

View File

@ -58,6 +58,10 @@
#include "BLI_kdopbvh.h"
#include "BKE_collision.h"
#include "DEG_depsgraph.h"
#include "DEG_depsgraph_physics.h"
#include "DEG_depsgraph_query.h"
#ifdef WITH_ELTOPO
#include "eltopo-capi.h"
#endif
@ -479,147 +483,161 @@ static CollPair* cloth_collision(ModifierData *md1, ModifierData *md2,
return collpair;
}
static void add_collision_object(Object ***objs, unsigned int *numobj, unsigned int *maxobj, Object *ob, Object *self, int level, unsigned int modifier_type)
static void add_collision_object(ListBase *relations, Object *ob, int level, unsigned int modifier_type)
{
CollisionModifierData *cmd= NULL;
if (ob == self)
return;
/* only get objects with collision modifier */
if (((modifier_type == eModifierType_Collision) && ob->pd && ob->pd->deflect) || (modifier_type != eModifierType_Collision))
cmd= (CollisionModifierData *)modifiers_findByType(ob, modifier_type);
if (cmd) {
/* extend array */
if (*numobj >= *maxobj) {
*maxobj *= 2;
*objs= MEM_reallocN(*objs, sizeof(Object *)*(*maxobj));
}
(*objs)[*numobj] = ob;
(*numobj)++;
CollisionRelation *relation = MEM_callocN(sizeof(CollisionRelation), "CollisionRelation");
relation->ob = ob;
BLI_addtail(relations, relation);
}
/* objects in dupli groups, one level only for now */
/* TODO: this doesn't really work, we are not taking into account the
* dupli transforms and can get objects in the list multiple times. */
if (ob->dup_group && level == 0) {
Collection *collection= ob->dup_group;
/* add objects */
FOREACH_COLLECTION_OBJECT_RECURSIVE_BEGIN(collection, object)
{
add_collision_object(objs, numobj, maxobj, object, self, level+1, modifier_type);
add_collision_object(relations, object, level+1, modifier_type);
}
FOREACH_COLLECTION_OBJECT_RECURSIVE_END;
}
}
// return all collision objects in scene
// collision object will exclude self
Object **get_collisionobjects_ext(Scene *scene, Object *self, Collection *collection, unsigned int *numcollobj, unsigned int modifier_type, bool dupli)
/* Create list of collision relations in the collection or entire scene.
* This is used by the depsgraph to build relations, as well as faster
* lookup of colliders during evaluation. */
ListBase *BKE_collision_relations_create(Depsgraph *depsgraph, Collection *collection, unsigned int modifier_type)
{
Object **objs;
unsigned int numobj= 0, maxobj= 100;
int level = dupli ? 0 : 1;
objs= MEM_callocN(sizeof(Object *)*maxobj, "CollisionObjectsArray");
ListBase *relations = MEM_callocN(sizeof(ListBase), "CollisionRelation list");
int level = 0;
/* gather all collision objects */
if (collection) {
/* use specified collection */
FOREACH_COLLECTION_OBJECT_RECURSIVE_BEGIN(collection, object)
{
add_collision_object(&objs, &numobj, &maxobj, object, self, level, modifier_type);
add_collision_object(relations, object, level, modifier_type);
}
FOREACH_COLLECTION_OBJECT_RECURSIVE_END;
}
else {
Scene *scene = DEG_get_input_scene(depsgraph);
Scene *sce_iter;
Base *base;
/* add objects in same layer in scene */
for (SETLOOPER(scene, sce_iter, base)) {
if ((base->flag & BASE_VISIBLED) != 0) {
add_collision_object(&objs, &numobj, &maxobj, base->object, self, level, modifier_type);
add_collision_object(relations, base->object, level, modifier_type);
}
}
}
*numcollobj= numobj;
return objs;
return relations;
}
Object **get_collisionobjects(Scene *scene, Object *self, Collection *collection, unsigned int *numcollobj, unsigned int modifier_type)
void BKE_collision_relations_free(ListBase *relations)
{
/* Need to check for active layers, too.
Otherwise this check fails if the objects are not on the same layer - DG */
return get_collisionobjects_ext(scene, self, collection, numcollobj, modifier_type, true);
}
static void add_collider_cache_object(ListBase **objs, Object *ob, Object *self, int level)
{
CollisionModifierData *cmd= NULL;
ColliderCache *col;
if (ob == self)
return;
if (ob->pd && ob->pd->deflect)
cmd =(CollisionModifierData *)modifiers_findByType(ob, eModifierType_Collision);
if (cmd && cmd->bvhtree) {
if (*objs == NULL)
*objs = MEM_callocN(sizeof(ListBase), "ColliderCache array");
col = MEM_callocN(sizeof(ColliderCache), "ColliderCache");
col->ob = ob;
col->collmd = cmd;
/* make sure collider is properly set up */
collision_move_object(cmd, 1.0, 0.0);
BLI_addtail(*objs, col);
}
/* objects in dupli collection, one level only for now */
if (ob->dup_group && level == 0) {
Collection *collection= ob->dup_group;
/* add objects */
FOREACH_COLLECTION_OBJECT_RECURSIVE_BEGIN(collection, object)
{
add_collider_cache_object(objs, object, self, level+1);
}
FOREACH_COLLECTION_OBJECT_RECURSIVE_END;
if (relations) {
BLI_freelistN(relations);
MEM_freeN(relations);
}
}
ListBase *get_collider_cache(Scene *scene, Object *self, Collection *collection)
/* Create effective list of colliders from relations built beforehand.
* Self will be excluded. */
Object **BKE_collision_objects_create(Depsgraph *depsgraph, Object *self, Collection *collection, unsigned int *numcollobj, unsigned int modifier_type)
{
ListBase *objs= NULL;
ListBase *relations;
/* add object in same layer in scene */
if (collection) {
FOREACH_COLLECTION_OBJECT_RECURSIVE_BEGIN(collection, object)
{
add_collider_cache_object(&objs, object, self, 0);
}
FOREACH_COLLECTION_OBJECT_RECURSIVE_END;
if (modifier_type == eModifierType_Smoke) {
relations = DEG_get_smoke_collision_relations(depsgraph, collection);
}
else {
Scene *sce_iter;
Base *base;
relations = DEG_get_collision_relations(depsgraph, collection);
}
/* add objects in same layer in scene */
for (SETLOOPER(scene, sce_iter, base)) {
if (!self || ((base->flag & BASE_VISIBLED) != 0))
add_collider_cache_object(&objs, base->object, self, 0);
if (!relations) {
return NULL;
}
int maxnum = BLI_listbase_count(relations);
int num = 0;
Object **objects = MEM_callocN(sizeof(Object*) * maxnum, __func__);
for (CollisionRelation *relation = relations->first; relation; relation = relation->next) {
/* Get evaluated object. */
Object *ob = (Object*)DEG_get_evaluated_id(depsgraph, &relation->ob->id);
if (ob != self) {
objects[num] = ob;
num++;
}
}
return objs;
if (num == 0) {
MEM_freeN(objects);
objects = NULL;
}
*numcollobj = num;
return objects;
}
void free_collider_cache(ListBase **colliders)
void BKE_collision_objects_free(Object **objects)
{
if (objects) {
MEM_freeN(objects);
}
}
/* Create effective list of colliders from relations built beforehand.
* Self will be excluded. */
ListBase *BKE_collider_cache_create(Depsgraph *depsgraph, Object *self, Collection *collection)
{
/* TODO: does this get built? */
ListBase *relations = DEG_get_collision_relations(depsgraph, collection);
ListBase *cache = NULL;
if (!relations) {
return NULL;
}
for (CollisionRelation *relation = relations->first; relation; relation = relation->next) {
/* Get evaluated object. */
Object *ob = (Object*)DEG_get_evaluated_id(depsgraph, &relation->ob->id);
if (ob == self) {
continue;
}
CollisionModifierData *cmd = (CollisionModifierData *)modifiers_findByType(ob, eModifierType_Collision);
if (cmd && cmd->bvhtree) {
if (cache == NULL) {
cache = MEM_callocN(sizeof(ListBase), "ColliderCache array");
}
ColliderCache *col = MEM_callocN(sizeof(ColliderCache), "ColliderCache");
col->ob = ob;
col->collmd = cmd;
/* make sure collider is properly set up */
collision_move_object(cmd, 1.0, 0.0);
BLI_addtail(cache, col);
}
}
return cache;
}
void BKE_collider_cache_free(ListBase **colliders)
{
if (*colliders) {
BLI_freelistN(*colliders);
@ -686,7 +704,7 @@ static int cloth_bvh_objcollisions_resolve ( ClothModifierData * clmd, Collision
}
// cloth - object collisions
int cloth_bvh_objcollision(Scene *scene, Object *ob, ClothModifierData *clmd, float step, float dt )
int cloth_bvh_objcollision(Depsgraph *depsgraph, Object *ob, ClothModifierData *clmd, float step, float dt )
{
Cloth *cloth= clmd->clothObject;
BVHTree *cloth_bvh= cloth->bvhtree;
@ -712,7 +730,7 @@ int cloth_bvh_objcollision(Scene *scene, Object *ob, ClothModifierData *clmd, fl
bvhtree_update_from_cloth ( clmd, 1 ); // 0 means STATIC, 1 means MOVING (see later in this function)
bvhselftree_update_from_cloth ( clmd, 0 ); // 0 means STATIC, 1 means MOVING (see later in this function)
collobjs = get_collisionobjects(scene, ob, clmd->coll_parms->group, &numcollobj, eModifierType_Collision);
collobjs = BKE_collision_objects_create(depsgraph, ob, clmd->coll_parms->group, &numcollobj, eModifierType_Collision);
if (!collobjs)
return 0;
@ -894,8 +912,7 @@ int cloth_bvh_objcollision(Scene *scene, Object *ob, ClothModifierData *clmd, fl
}
while ( ret2 && ( clmd->coll_parms->loop_count>rounds ) );
if (collobjs)
MEM_freeN(collobjs);
BKE_collision_objects_free(collobjs);
return 1|MIN2 ( ret, 1 );
}
@ -1207,7 +1224,7 @@ static int cloth_points_objcollisions_resolve(
}
// cloth - object collisions
int cloth_points_objcollision(Scene *scene, Object *ob, ClothModifierData *clmd, float step, float dt)
int cloth_points_objcollision(Depsgraph *depsgraph, Object *ob, ClothModifierData *clmd, float step, float dt)
{
Cloth *cloth= clmd->clothObject;
BVHTree *cloth_bvh;
@ -1240,7 +1257,7 @@ int cloth_points_objcollision(Scene *scene, Object *ob, ClothModifierData *clmd,
/* balance tree */
BLI_bvhtree_balance(cloth_bvh);
collobjs = get_collisionobjects(scene, ob, clmd->coll_parms->group, &numcollobj, eModifierType_Collision);
collobjs = BKE_collision_objects_create(depsgraph, ob, clmd->coll_parms->group, &numcollobj, eModifierType_Collision);
if (!collobjs)
return 0;
@ -1321,15 +1338,14 @@ int cloth_points_objcollision(Scene *scene, Object *ob, ClothModifierData *clmd,
}
while ( ret2 && ( clmd->coll_parms->loop_count>rounds ) );
if (collobjs)
MEM_freeN(collobjs);
BKE_collision_objects_free(collobjs);
BLI_bvhtree_free(cloth_bvh);
return 1|MIN2 ( ret, 1 );
}
void cloth_find_point_contacts(Scene *scene, Object *ob, ClothModifierData *clmd, float step, float dt,
void cloth_find_point_contacts(Depsgraph *depsgraph, Object *ob, ClothModifierData *clmd, float step, float dt,
ColliderContacts **r_collider_contacts, int *r_totcolliders)
{
Cloth *cloth= clmd->clothObject;
@ -1363,7 +1379,7 @@ void cloth_find_point_contacts(Scene *scene, Object *ob, ClothModifierData *clmd
/* balance tree */
BLI_bvhtree_balance(cloth_bvh);
collobjs = get_collisionobjects(scene, ob, clmd->coll_parms->group, &numcollobj, eModifierType_Collision);
collobjs = BKE_collision_objects_create(depsgraph, ob, clmd->coll_parms->group, &numcollobj, eModifierType_Collision);
if (!collobjs) {
*r_collider_contacts = NULL;
*r_totcolliders = 0;
@ -1421,8 +1437,7 @@ void cloth_find_point_contacts(Scene *scene, Object *ob, ClothModifierData *clmd
MEM_freeN(overlap);
}
if (collobjs)
MEM_freeN(collobjs);
BKE_collision_objects_free(collobjs);
BLI_bvhtree_free(cloth_bvh);

View File

@ -4926,7 +4926,7 @@ static int dynamicPaint_prepareEffectStep(
/* Init force data if required */
if (surface->effect & MOD_DPAINT_EFFECT_DO_DRIP) {
ListBase *effectors = BKE_effectors_create(depsgraph, scene, ob, NULL, surface->effector_weights);
ListBase *effectors = BKE_effectors_create(depsgraph, ob, NULL, surface->effector_weights);
/* allocate memory for force data (dir vector + strength) */
*force = MEM_mallocN(sData->total_points * 4 * sizeof(float), "PaintEffectForces");

View File

@ -267,11 +267,11 @@ void BKE_effector_relations_free(ListBase *lb)
/* Create effective list of effectors from relations built beforehand. */
ListBase *BKE_effectors_create(
Depsgraph *depsgraph,
Scene *scene,
Object *ob_src,
ParticleSystem *psys_src,
EffectorWeights *weights)
{
Scene *scene = DEG_get_evaluated_scene(depsgraph);
ListBase *relations = DEG_get_effector_relations(depsgraph, weights->group);
ListBase *effectors = NULL;
@ -420,7 +420,7 @@ static float eff_calc_visibility(ListBase *colliders, EffectorCache *eff, Effect
return visibility;
if (!colls)
colls = get_collider_cache(eff->scene, eff->ob, NULL);
colls = BKE_collider_cache_create(eff->depsgraph, eff->ob, NULL);
if (!colls)
return visibility;
@ -458,7 +458,7 @@ static float eff_calc_visibility(ListBase *colliders, EffectorCache *eff, Effect
}
if (!colliders)
free_collider_cache(&colls);
BKE_collider_cache_free(&colls);
return visibility;
}

View File

@ -1310,7 +1310,7 @@ static void psys_update_effectors(ParticleSimulationData *sim)
{
BKE_effectors_free(sim->psys->effectors);
sim->psys->effectors = BKE_effectors_create(sim->depsgraph,
sim->scene, sim->ob, sim->psys,
sim->ob, sim->psys,
sim->psys->part->effector_weights);
precalc_guides(sim, sim->psys->effectors);
}
@ -3540,7 +3540,7 @@ static void dynamics_step(ParticleSimulationData *sim, float cfra)
psys_update_effectors(sim);
if (part->type != PART_HAIR)
sim->colliders = get_collider_cache(sim->scene, sim->ob, part->collision_group);
sim->colliders = BKE_collider_cache_create(sim->depsgraph, sim->ob, part->collision_group);
/* initialize physics type specific stuff */
switch (part->phystype) {
@ -3747,7 +3747,7 @@ static void dynamics_step(ParticleSimulationData *sim, float cfra)
pa->state.time=cfra;
}
free_collider_cache(&sim->colliders);
BKE_collider_cache_free(&sim->colliders);
BLI_rng_free(sim->rng);
sim->rng = NULL;
}

View File

@ -1283,7 +1283,7 @@ static void rigidbody_update_sim_ob(Depsgraph *depsgraph, Scene *scene, RigidBod
ListBase *effectors;
/* get effectors present in the group specified by effector_weights */
effectors = BKE_effectors_create(depsgraph, scene, ob, NULL, effector_weights);
effectors = BKE_effectors_create(depsgraph, ob, NULL, effector_weights);
if (effectors) {
float eff_force[3] = {0.0f, 0.0f, 0.0f};
float eff_loc[3], eff_vel[3];

View File

@ -893,7 +893,7 @@ static void obstacles_from_derivedmesh(
}
/* Animated obstacles: dx_step = ((x_new - x_old) / totalsteps) * substep */
static void update_obstacles(Scene *scene, Object *ob, SmokeDomainSettings *sds, float dt,
static void update_obstacles(Depsgraph *depsgraph, Object *ob, SmokeDomainSettings *sds, float dt,
int UNUSED(substep), int UNUSED(totalsteps))
{
Object **collobjs = NULL;
@ -933,7 +933,7 @@ static void update_obstacles(Scene *scene, Object *ob, SmokeDomainSettings *sds,
}
collobjs = get_collisionobjects(scene, ob, sds->coll_group, &numcollobj, eModifierType_Smoke);
collobjs = BKE_collision_objects_create(depsgraph, ob, sds->coll_group, &numcollobj, eModifierType_Smoke);
// update obstacle tags in cells
for (collIndex = 0; collIndex < numcollobj; collIndex++)
@ -950,8 +950,7 @@ static void update_obstacles(Scene *scene, Object *ob, SmokeDomainSettings *sds,
}
}
if (collobjs)
MEM_freeN(collobjs);
BKE_collision_objects_free(collobjs);
/* obstacle cells should not contain any velocity from the smoke simulation */
for (z = 0; z < sds->res[0] * sds->res[1] * sds->res[2]; z++)
@ -2151,7 +2150,7 @@ static void update_flowsfluids(
sds->p1[2] = sds->p0[2] + sds->cell_size[2] * sds->base_res[2];
}
flowobjs = get_collisionobjects(scene, ob, sds->fluid_group, &numflowobj, eModifierType_Smoke);
flowobjs = BKE_collision_objects_create(depsgraph, ob, sds->fluid_group, &numflowobj, eModifierType_Smoke);
/* init emission maps for each flow */
emaps = MEM_callocN(sizeof(struct EmissionMap) * numflowobj, "smoke_flow_maps");
@ -2452,8 +2451,7 @@ static void update_flowsfluids(
}
}
if (flowobjs)
MEM_freeN(flowobjs);
BKE_collision_objects_free(flowobjs);
if (emaps)
MEM_freeN(emaps);
}
@ -2533,7 +2531,7 @@ static void update_effectors(struct Depsgraph *depsgraph, Scene *scene, Object *
ListBase *effectors;
/* make sure smoke flow influence is 0.0f */
sds->effector_weights->weight[PFIELD_SMOKEFLOW] = 0.0f;
effectors = BKE_effectors_create(depsgraph, scene, ob, NULL, sds->effector_weights);
effectors = BKE_effectors_create(depsgraph, ob, NULL, sds->effector_weights);
if (effectors) {
// precalculate wind forces
@ -2636,7 +2634,7 @@ static void step(
{
// calc animated obstacle velocities
update_flowsfluids(depsgraph, scene, ob, sds, dtSubdiv);
update_obstacles(scene, ob, sds, dtSubdiv, substep, totalSubsteps);
update_obstacles(depsgraph, ob, sds, dtSubdiv, substep, totalSubsteps);
if (sds->total_cells > 1) {
update_effectors(depsgraph, scene, ob, sds, dtSubdiv); // DG TODO? problem --> uses forces instead of velocity, need to check how they need to be changed with variable dt

View File

@ -1522,7 +1522,7 @@ static void scan_for_ext_spring_forces(struct Depsgraph *depsgraph, Scene *scene
{
SoftBody *sb = ob->soft;
ListBase *effectors = BKE_effectors_create(depsgraph, scene, ob, NULL, sb->effector_weights);
ListBase *effectors = BKE_effectors_create(depsgraph, ob, NULL, sb->effector_weights);
_scan_for_ext_spring_forces(scene, ob, timenow, 0, sb->totspring, effectors);
BKE_effectors_free(effectors);
}
@ -1541,7 +1541,7 @@ static void sb_sfesf_threads_run(struct Depsgraph *depsgraph, Scene *scene, stru
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 */
ListBase *effectors = BKE_effectors_create(depsgraph, scene, ob, NULL, ob->soft->effector_weights);
ListBase *effectors = BKE_effectors_create(depsgraph, ob, NULL, ob->soft->effector_weights);
/* figure the number of threads while preventing pretty pointless threading overhead */
totthread= BKE_scene_num_threads(scene);
@ -2226,7 +2226,7 @@ static void softbody_calc_forcesEx(struct Depsgraph *depsgraph, Scene *scene, Ob
sb_sfesf_threads_run(depsgraph, scene, ob, timenow, sb->totspring, NULL);
/* after spring scan because it uses Effoctors too */
ListBase *effectors = BKE_effectors_create(depsgraph, scene, ob, NULL, sb->effector_weights);
ListBase *effectors = BKE_effectors_create(depsgraph, ob, NULL, sb->effector_weights);
if (do_deflector) {
float defforce[3];
@ -2287,7 +2287,7 @@ static void softbody_calc_forces(struct Depsgraph *depsgraph, Scene *scene, Obje
if (do_springcollision || do_aero) scan_for_ext_spring_forces(depsgraph, scene, ob, timenow);
/* after spring scan because it uses Effoctors too */
ListBase *effectors = BKE_effectors_create(depsgraph, scene, ob, NULL, ob->soft->effector_weights);
ListBase *effectors = BKE_effectors_create(depsgraph, ob, NULL, ob->soft->effector_weights);
if (do_deflector) {
float defforce[3];

View File

@ -157,15 +157,12 @@ void DEG_add_special_eval_flag(struct Depsgraph *graph, struct ID *id, short fla
typedef bool (*DEG_CollobjFilterFunction)(struct Object *obj, struct ModifierData *md);
void DEG_add_collision_relations(struct DepsNodeHandle *handle,
struct Scene *scene,
struct Object *object,
struct Collection *collection,
unsigned int modifier_type,
DEG_CollobjFilterFunction fn,
bool dupli,
const char *name);
void DEG_add_forcefield_relations(struct DepsNodeHandle *handle,
struct Scene *scene,
struct Object *object,
struct EffectorWeights *eff,
bool add_absorption,

View File

@ -34,15 +34,21 @@
struct Colllection;
struct Depsgraph;
struct ListBase;
#ifdef __cplusplus
extern "C" {
#endif
/* Get effector relations from collection or entire scene during evaluation,
* these are created during depsgraph relations building. */
/* Get collision/effector relations from collection or entire scene. These
* created during depsgraph relations building and should only be accessed
* during evaluation. */
struct ListBase *DEG_get_effector_relations(const struct Depsgraph *depsgraph,
struct Collection *collection);
struct ListBase *DEG_get_collision_relations(const struct Depsgraph *depsgraph,
struct Collection *collection);
struct ListBase *DEG_get_smoke_collision_relations(const struct Depsgraph *depsgraph,
struct Collection *collection);
#ifdef __cplusplus
} /* extern "C" */

View File

@ -298,36 +298,25 @@ DepsRelation *DepsgraphRelationBuilder::add_operation_relation(
void DepsgraphRelationBuilder::add_collision_relations(
const OperationKey &key,
Scene *scene,
Object *object,
Collection *collection,
bool dupli,
const char *name)
{
unsigned int numcollobj;
Object **collobjs = get_collisionobjects_ext(scene,
object,
collection,
&numcollobj,
eModifierType_Collision,
dupli);
for (unsigned int i = 0; i < numcollobj; i++) {
Object *ob1 = collobjs[i];
ListBase *relations = deg_build_collision_relations(graph_, collection);
ComponentKey trf_key(&ob1->id, DEG_NODE_TYPE_TRANSFORM);
add_relation(trf_key, key, name);
LISTBASE_FOREACH (CollisionRelation *, relation, relations) {
if (relation->ob != object) {
ComponentKey trf_key(&relation->ob->id, DEG_NODE_TYPE_TRANSFORM);
add_relation(trf_key, key, name);
ComponentKey coll_key(&ob1->id, DEG_NODE_TYPE_GEOMETRY);
add_relation(coll_key, key, name);
}
if (collobjs != NULL) {
MEM_freeN(collobjs);
ComponentKey coll_key(&relation->ob->id, DEG_NODE_TYPE_GEOMETRY);
add_relation(coll_key, key, name);
}
}
}
void DepsgraphRelationBuilder::add_forcefield_relations(
const OperationKey &key,
Scene *scene,
Object *object,
ParticleSystem *psys,
EffectorWeights *eff,
@ -351,10 +340,8 @@ void DepsgraphRelationBuilder::add_forcefield_relations(
}
if (add_absorption && (relation->pd->flag & PFIELD_VISIBILITY)) {
add_collision_relations(key,
scene,
object,
NULL,
true,
"Force Absorption");
}
}
@ -1586,10 +1573,8 @@ void DepsgraphRelationBuilder::build_particles(Object *object)
/* Collisions */
if (part->type != PART_HAIR) {
add_collision_relations(psys_key,
scene_,
object,
part->collision_group,
true,
"Particle Collision");
}
else if ((psys->flag & PSYS_HAIR_DYNAMICS) &&
@ -1597,15 +1582,12 @@ void DepsgraphRelationBuilder::build_particles(Object *object)
psys->clmd->coll_parms != NULL)
{
add_collision_relations(psys_key,
scene_,
object,
psys->clmd->coll_parms->group,
true,
"Hair Collision");
}
/* Effectors. */
add_forcefield_relations(psys_key,
scene_,
object,
psys,
part->effector_weights,

View File

@ -272,13 +272,10 @@ struct DepsgraphRelationBuilder
void build_nested_shapekey(ID *owner, Key *key);
void add_collision_relations(const OperationKey &key,
Scene *scene,
Object *object,
Collection *collection,
bool dupli,
const char *name);
void add_forcefield_relations(const OperationKey &key,
Scene *scene,
Object *object,
ParticleSystem *psys,
EffectorWeights *eff,

View File

@ -94,7 +94,9 @@ Depsgraph::Depsgraph(Scene *scene,
ctime(BKE_scene_frame_get(scene)),
scene_cow(NULL),
is_active(false),
effector_relations(NULL)
collision_relations(NULL),
smoke_collision_relations(NULL),
effector_relations(NULL)
{
BLI_spin_init(&lock);
id_hash = BLI_ghash_ptr_new("Depsgraph id hash");

View File

@ -227,8 +227,10 @@ struct Depsgraph {
int debug_flags;
string debug_name;
/* Cached list of effectors for collections and the scene created
* along with relations, for fast lookup during evaluation. */
/* Cached list of colliders/effectors for collections and the scene
* created along with relations, for fast lookup during evaluation. */
GHash *collision_relations;
GHash *smoke_collision_relations;
GHash *effector_relations;
};

View File

@ -324,32 +324,35 @@ void DEG_relations_tag_update(Main *bmain)
}
void DEG_add_collision_relations(DepsNodeHandle *handle,
Scene *scene,
Object *object,
Collection *collection,
unsigned int modifier_type,
DEG_CollobjFilterFunction fn,
bool dupli,
const char *name)
{
unsigned int numcollobj;
Object **collobjs = get_collisionobjects_ext(scene, object, collection, &numcollobj, modifier_type, dupli);
Depsgraph *depsgraph = DEG_get_graph_from_handle(handle);
DEG::Depsgraph *deg_graph = (DEG::Depsgraph *)depsgraph;
ListBase *relations;
for (unsigned int i = 0; i < numcollobj; i++) {
Object *ob1 = collobjs[i];
if (!fn || fn(ob1, modifiers_findByType(ob1, (ModifierType)modifier_type))) {
DEG_add_object_relation(handle, ob1, DEG_OB_COMP_TRANSFORM, name);
DEG_add_object_relation(handle, ob1, DEG_OB_COMP_GEOMETRY, name);
}
if (modifier_type == eModifierType_Smoke) {
relations = deg_build_smoke_collision_relations(deg_graph, collection);
}
else {
relations = deg_build_collision_relations(deg_graph, collection);
}
if (collobjs)
MEM_freeN(collobjs);
LISTBASE_FOREACH (CollisionRelation *, relation, relations) {
Object *ob1 = relation->ob;
if (ob1 != object) {
if (!fn || fn(ob1, modifiers_findByType(ob1, (ModifierType)modifier_type))) {
DEG_add_object_relation(handle, ob1, DEG_OB_COMP_TRANSFORM, name);
DEG_add_object_relation(handle, ob1, DEG_OB_COMP_GEOMETRY, name);
}
}
}
}
void DEG_add_forcefield_relations(DepsNodeHandle *handle,
Scene *scene,
Object *object,
EffectorWeights *effector_weights,
bool add_absorption,
@ -382,12 +385,10 @@ void DEG_add_forcefield_relations(DepsNodeHandle *handle,
}
if (add_absorption && (relation->pd->flag & PFIELD_VISIBILITY)) {
DEG_add_collision_relations(handle,
scene,
object,
NULL,
eModifierType_Collision,
NULL,
true,
"Force Absorption");
}
}

View File

@ -143,6 +143,8 @@ string deg_color_end(void);
/* Physics Utilities -------------------------------------------------- */
struct ListBase *deg_build_effector_relations(Depsgraph *graph, struct Collection *collection);
struct ListBase *deg_build_collision_relations(Depsgraph *graph, struct Collection *collection);
struct ListBase *deg_build_smoke_collision_relations(Depsgraph *graph, struct Collection *collection);
void deg_clear_physics_relations(Depsgraph *graph);
} // namespace DEG

View File

@ -33,6 +33,7 @@
#include "BLI_ghash.h"
extern "C" {
#include "BKE_collision.h"
#include "BKE_effect.h"
} /* extern "C" */
@ -56,6 +57,28 @@ ListBase *DEG_get_effector_relations(const Depsgraph *graph,
return (ListBase *)BLI_ghash_lookup(deg_graph->effector_relations, collection);
}
ListBase *DEG_get_collision_relations(const Depsgraph *graph,
Collection *collection)
{
const DEG::Depsgraph *deg_graph = reinterpret_cast<const DEG::Depsgraph *>(graph);
if (deg_graph->collision_relations == NULL) {
return NULL;
}
return (ListBase*)BLI_ghash_lookup(deg_graph->collision_relations, collection);
}
ListBase *DEG_get_smoke_collision_relations(const Depsgraph *graph,
Collection *collection)
{
const DEG::Depsgraph *deg_graph = reinterpret_cast<const DEG::Depsgraph *>(graph);
if (deg_graph->smoke_collision_relations == NULL) {
return NULL;
}
return (ListBase*)BLI_ghash_lookup(deg_graph->smoke_collision_relations, collection);
}
/*********************** Internal API ************************/
namespace DEG
@ -78,13 +101,60 @@ ListBase *deg_build_effector_relations(Depsgraph *graph,
return relations;
}
ListBase *deg_build_collision_relations(Depsgraph *graph,
Collection *collection)
{
if (graph->collision_relations == NULL) {
graph->collision_relations = BLI_ghash_ptr_new("Depsgraph collision relations hash");
}
ListBase *relations = reinterpret_cast<ListBase*>(BLI_ghash_lookup(graph->collision_relations, collection));
if (relations == NULL) {
::Depsgraph *depsgraph = reinterpret_cast<::Depsgraph*>(graph);
relations = BKE_collision_relations_create(depsgraph, collection, eModifierType_Collision);
BLI_ghash_insert(graph->collision_relations, collection, relations);
}
return relations;
}
ListBase *deg_build_smoke_collision_relations(Depsgraph *graph,
Collection *collection)
{
if (graph->smoke_collision_relations == NULL) {
graph->smoke_collision_relations = BLI_ghash_ptr_new("Depsgraph smoke collision relations hash");
}
ListBase *relations = reinterpret_cast<ListBase*>(BLI_ghash_lookup(graph->smoke_collision_relations, collection));
if (relations == NULL) {
::Depsgraph *depsgraph = reinterpret_cast<::Depsgraph*>(graph);
relations = BKE_collision_relations_create(depsgraph, collection, eModifierType_Smoke);
BLI_ghash_insert(graph->smoke_collision_relations, collection, relations);
}
return relations;
}
static void free_effector_relations(void *value)
{
BKE_effector_relations_free(reinterpret_cast<ListBase*>(value));
}
static void free_collision_relations(void *value)
{
BKE_collision_relations_free(reinterpret_cast<ListBase*>(value));
}
void deg_clear_physics_relations(Depsgraph *graph)
{
if (graph->collision_relations) {
BLI_ghash_free(graph->collision_relations, NULL, free_collision_relations);
graph->collision_relations = NULL;
}
if (graph->smoke_collision_relations) {
BLI_ghash_free(graph->smoke_collision_relations, NULL, free_collision_relations);
graph->smoke_collision_relations = NULL;
}
if (graph->effector_relations) {
BLI_ghash_free(graph->effector_relations, NULL, free_effector_relations);
graph->effector_relations = NULL;

View File

@ -135,10 +135,8 @@ static void updateDepsgraph(ModifierData *md, const ModifierUpdateDepsgraphConte
{
ClothModifierData *clmd = (ClothModifierData *)md;
if (clmd != NULL) {
/* Actual code uses get_collisionobjects */
DEG_add_collision_relations(ctx->node, ctx->scene, ctx->object, clmd->coll_parms->group, eModifierType_Collision, NULL, true, "Cloth Collision");
DEG_add_forcefield_relations(ctx->node, ctx->scene, ctx->object, clmd->sim_parms->effector_weights, true, 0, "Cloth Field");
DEG_add_collision_relations(ctx->node, ctx->object, clmd->coll_parms->group, eModifierType_Collision, NULL, "Cloth Collision");
DEG_add_forcefield_relations(ctx->node, ctx->object, clmd->sim_parms->effector_weights, true, 0, "Cloth Field");
}
}

View File

@ -125,11 +125,11 @@ static void updateDepsgraph(ModifierData *md, const ModifierUpdateDepsgraphConte
if (pmd->canvas != NULL) {
for (DynamicPaintSurface *surface = pmd->canvas->surfaces.first; surface; surface = surface->next) {
if (surface->effect & MOD_DPAINT_EFFECT_DO_DRIP) {
DEG_add_forcefield_relations(ctx->node, ctx->scene, ctx->object, surface->effector_weights, true, 0, "Dynamic Paint Field");
DEG_add_forcefield_relations(ctx->node, ctx->object, surface->effector_weights, true, 0, "Dynamic Paint Field");
}
/* Actual code uses custom loop over group/scene without layer checks in dynamicPaint_doStep */
DEG_add_collision_relations(ctx->node, ctx->scene, ctx->object, surface->brush_group, eModifierType_DynamicPaint, is_brush_cb, false, "Dynamic Paint Brush");
DEG_add_collision_relations(ctx->node, ctx->object, surface->brush_group, eModifierType_DynamicPaint, is_brush_cb, "Dynamic Paint Brush");
}
}
}

View File

@ -139,11 +139,9 @@ static void updateDepsgraph(ModifierData *md, const ModifierUpdateDepsgraphConte
SmokeModifierData *smd = (SmokeModifierData *)md;
if (smd && (smd->type & MOD_SMOKE_TYPE_DOMAIN) && smd->domain) {
/* Actual code uses get_collisionobjects */
DEG_add_collision_relations(ctx->node, ctx->scene, ctx->object, smd->domain->fluid_group, eModifierType_Smoke, is_flow_cb, true, "Smoke Flow");
DEG_add_collision_relations(ctx->node, ctx->scene, ctx->object, smd->domain->coll_group, eModifierType_Smoke, is_coll_cb, true, "Smoke Coll");
DEG_add_forcefield_relations(ctx->node, ctx->scene, ctx->object, smd->domain->effector_weights, true, PFIELD_SMOKEFLOW, "Smoke Force Field");
DEG_add_collision_relations(ctx->node, ctx->object, smd->domain->fluid_group, eModifierType_Smoke, is_flow_cb, "Smoke Flow");
DEG_add_collision_relations(ctx->node, ctx->object, smd->domain->coll_group, eModifierType_Smoke, is_coll_cb, "Smoke Coll");
DEG_add_forcefield_relations(ctx->node, ctx->object, smd->domain->effector_weights, true, PFIELD_SMOKEFLOW, "Smoke Force Field");
}
}

View File

@ -69,9 +69,8 @@ static void updateDepsgraph(ModifierData *UNUSED(md), const ModifierUpdateDepsgr
{
if (ctx->object->soft) {
/* Actual code uses ccd_build_deflector_hash */
DEG_add_collision_relations(ctx->node, ctx->scene, ctx->object, ctx->object->soft->collision_group, eModifierType_Collision, NULL, false, "Softbody Collision");
DEG_add_forcefield_relations(ctx->node, ctx->scene, ctx->object, ctx->object->soft->effector_weights, true, 0, "Softbody Field");
DEG_add_collision_relations(ctx->node, ctx->object, ctx->object->soft->collision_group, eModifierType_Collision, NULL, "Softbody Collision");
DEG_add_forcefield_relations(ctx->node, ctx->object, ctx->object->soft->effector_weights, true, 0, "Softbody Field");
}
}

View File

@ -40,7 +40,7 @@ struct Implicit_Data;
struct Object;
struct ClothModifierData;
struct ListBase;
struct Scene;
struct Depsgraph;
struct VoxelData;
typedef enum eMassSpringSolverStatus {
@ -56,7 +56,7 @@ int BPH_mass_spring_solver_numvert(struct Implicit_Data *id);
int BPH_cloth_solver_init(struct Object *ob, struct ClothModifierData *clmd);
void BPH_cloth_solver_free(struct ClothModifierData *clmd);
int BPH_cloth_solve(struct Scene *scene, struct Object *ob, float frame, struct ClothModifierData *clmd, struct ListBase *effectors);
int BPH_cloth_solve(struct Depsgraph *depsgraph, struct Object *ob, float frame, struct ClothModifierData *clmd, struct ListBase *effectors);
void BKE_cloth_solver_set_positions(struct ClothModifierData *clmd);
#ifdef __cplusplus

View File

@ -28,6 +28,7 @@ set(INC
intern
../blenlib
../blenkernel
../depsgraph
../imbuf
../makesdna
../../../intern/guardedalloc

View File

@ -51,6 +51,9 @@ extern "C" {
#include "BPH_mass_spring.h"
#include "implicit.h"
#include "DEG_depsgraph.h"
#include "DEG_depsgraph_query.h"
static float I3[3][3] = {{1.0, 0.0, 0.0}, {0.0, 1.0, 0.0}, {0.0, 0.0, 1.0}};
/* Number of off-diagonal non-zero matrix blocks.
@ -848,7 +851,7 @@ static void cloth_calc_volume_force(ClothModifierData *clmd)
* until a good replacement is ready
*/
static void cloth_collision_solve_extra(
Scene *scene, Object *ob, ClothModifierData *clmd, ListBase *effectors,
Depsgraph *depsgraph, Scene *scene, Object *ob, ClothModifierData *clmd, ListBase *effectors,
float frame, float step, float dt)
{
Cloth *cloth = clmd->clothObject;
@ -882,7 +885,7 @@ static void cloth_collision_solve_extra(
// call collision function
// TODO: check if "step" or "step+dt" is correct - dg
do_extra_solve = cloth_bvh_objcollision(
scene, ob, clmd, step / clmd->sim_parms->timescale, dt / clmd->sim_parms->timescale);
depsgraph, ob, clmd, step / clmd->sim_parms->timescale, dt / clmd->sim_parms->timescale);
// copy corrected positions back to simulation
for (i = 0; i < mvert_num; i++) {
@ -970,12 +973,13 @@ static void cloth_record_result(ClothModifierData *clmd, ImplicitSolverResult *r
sres->status |= result->status;
}
int BPH_cloth_solve(Scene *scene, Object *ob, float frame, ClothModifierData *clmd, ListBase *effectors)
int BPH_cloth_solve(Depsgraph *depsgraph, Object *ob, float frame, ClothModifierData *clmd, ListBase *effectors)
{
/* Hair currently is a cloth sim in disguise ...
* Collision detection and volumetrics work differently then.
* Bad design, TODO
*/
Scene *scene = DEG_get_evaluated_scene(depsgraph);
const bool is_hair = (clmd->hairdata != NULL);
unsigned int i=0;
@ -1020,7 +1024,7 @@ int BPH_cloth_solve(Scene *scene, Object *ob, float frame, ClothModifierData *cl
if (is_hair) {
/* determine contact points */
if (clmd->coll_parms->flags & CLOTH_COLLSETTINGS_FLAG_ENABLED) {
cloth_find_point_contacts(scene, ob, clmd, 0.0f, tf, &contacts, &totcolliders);
cloth_find_point_contacts(depsgraph, ob, clmd, 0.0f, tf, &contacts, &totcolliders);
}
/* setup vertex constraints for pinned vertices and contacts */
@ -1059,7 +1063,7 @@ int BPH_cloth_solve(Scene *scene, Object *ob, float frame, ClothModifierData *cl
BPH_mass_spring_solve_positions(id, dt);
if (!is_hair) {
cloth_collision_solve_extra(scene, ob, clmd, effectors, frame, step, dt);
cloth_collision_solve_extra(depsgraph, scene, ob, clmd, effectors, frame, step, dt);
}
BPH_mass_spring_apply_result(id);

View File

@ -1054,7 +1054,7 @@ static HairGridVert *hair_volume_create_collision_grid(ClothModifierData *clmd,
}
/* gather colliders */
colliders = get_collider_cache(clmd->scene, NULL, NULL);
colliders = BKE_collider_cache_create(depsgraph, NULL, NULL);
if (colliders && collfac > 0.0f) {
for (col = colliders->first; col; col = col->next) {
MVert *loc0 = col->collmd->x;
@ -1087,7 +1087,7 @@ static HairGridVert *hair_volume_create_collision_grid(ClothModifierData *clmd,
}
}
}
free_collider_cache(&colliders);
BKE_collider_cache_free(&colliders);
/* divide velocity with density */
for (i = 0; i < size; i++) {