diff options
Diffstat (limited to 'source/blender/blenkernel/intern/collision.c')
-rw-r--r-- | source/blender/blenkernel/intern/collision.c | 203 |
1 files changed, 105 insertions, 98 deletions
diff --git a/source/blender/blenkernel/intern/collision.c b/source/blender/blenkernel/intern/collision.c index 1df749ee842..d7fab317105 100644 --- a/source/blender/blenkernel/intern/collision.c +++ b/source/blender/blenkernel/intern/collision.c @@ -33,8 +33,8 @@ #include "MEM_guardedalloc.h" #include "DNA_cloth_types.h" +#include "DNA_collection_types.h" #include "DNA_effect_types.h" -#include "DNA_group_types.h" #include "DNA_object_types.h" #include "DNA_object_force_types.h" #include "DNA_scene_types.h" @@ -46,7 +46,9 @@ #include "BLI_edgehash.h" #include "BKE_cloth.h" +#include "BKE_collection.h" #include "BKE_effect.h" +#include "BKE_layer.h" #include "BKE_modifier.h" #include "BKE_scene.h" @@ -56,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 @@ -477,139 +483,143 @@ 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) { - GroupObject *go; - Group *group= ob->dup_group; + Collection *collection= ob->dup_group; /* add objects */ - for (go= group->gobject.first; go; go= go->next) - add_collision_object(objs, numobj, maxobj, go->ob, self, level+1, modifier_type); + FOREACH_COLLECTION_OBJECT_RECURSIVE_BEGIN(collection, object) + { + 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, Group *group, int layer, 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) { - Base *base; - Object **objs; - GroupObject *go; - unsigned int numobj= 0, maxobj= 100; - int level = dupli ? 0 : 1; - - objs= MEM_callocN(sizeof(Object *)*maxobj, "CollisionObjectsArray"); - - /* gather all collision objects */ - if (group) { - /* use specified group */ - for (go= group->gobject.first; go; go= go->next) - add_collision_object(&objs, &numobj, &maxobj, go->ob, self, level, modifier_type); - } - else { - Scene *sce_iter; - /* add objects in same layer in scene */ - for (SETLOOPER(scene, sce_iter, base)) { - if ( base->lay & layer ) - add_collision_object(&objs, &numobj, &maxobj, base->object, self, level, modifier_type); + ViewLayer *view_layer = DEG_get_input_view_layer(depsgraph); + Base *base = BKE_collection_or_layer_objects(view_layer, collection); + const bool for_render = (DEG_get_mode(depsgraph) == DAG_EVAL_RENDER); + const int base_flag = (for_render) ? BASE_ENABLED_RENDER : BASE_ENABLED_VIEWPORT; + ListBase *relations = MEM_callocN(sizeof(ListBase), "CollisionRelation list"); + + for (; base; base = base->next) { + if (base->flag & base_flag) { + add_collision_object(relations, base->object, 0, modifier_type); } } - *numcollobj= numobj; - - return objs; + return relations; } -Object **get_collisionobjects(Scene *scene, Object *self, Group *group, 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, group, self->lay | scene->lay, numcollobj, modifier_type, true); + if (relations) { + BLI_freelistN(relations); + MEM_freeN(relations); + } } -static void add_collider_cache_object(ListBase **objs, Object *ob, Object *self, int level) +/* 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) { - CollisionModifierData *cmd= NULL; - ColliderCache *col; + ListBase *relations = DEG_get_collision_relations(depsgraph, collection, modifier_type); - if (ob == self) - return; + if (!relations) { + *numcollobj = 0; + return NULL; + } - if (ob->pd && ob->pd->deflect) - cmd =(CollisionModifierData *)modifiers_findByType(ob, eModifierType_Collision); + int maxnum = BLI_listbase_count(relations); + int num = 0; + Object **objects = MEM_callocN(sizeof(Object*) * maxnum, __func__); - if (cmd && cmd->bvhtree) { - if (*objs == NULL) - *objs = MEM_callocN(sizeof(ListBase), "ColliderCache array"); + for (CollisionRelation *relation = relations->first; relation; relation = relation->next) { + /* Get evaluated object. */ + Object *ob = (Object*)DEG_get_evaluated_id(depsgraph, &relation->ob->id); - 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); + if (ob != self) { + objects[num] = ob; + num++; + } } - /* objects in dupli groups, one level only for now */ - if (ob->dup_group && level == 0) { - GroupObject *go; - Group *group= ob->dup_group; + if (num == 0) { + MEM_freeN(objects); + objects = NULL; + } - /* add objects */ - for (go= group->gobject.first; go; go= go->next) - add_collider_cache_object(objs, go->ob, self, level+1); + *numcollobj = num; + return objects; +} + +void BKE_collision_objects_free(Object **objects) +{ + if (objects) { + MEM_freeN(objects); } } -ListBase *get_collider_cache(Scene *scene, Object *self, Group *group) +/* Create effective list of colliders from relations built beforehand. + * Self will be excluded. */ +ListBase *BKE_collider_cache_create(Depsgraph *depsgraph, Object *self, Collection *collection) { - GroupObject *go; - ListBase *objs= NULL; + ListBase *relations = DEG_get_collision_relations(depsgraph, collection, eModifierType_Collision); + ListBase *cache = NULL; - /* add object in same layer in scene */ - if (group) { - for (go= group->gobject.first; go; go= go->next) - add_collider_cache_object(&objs, go->ob, self, 0); + if (!relations) { + return NULL; } - else { - Scene *sce_iter; - Base *base; - /* add objects in same layer in scene */ - for (SETLOOPER(scene, sce_iter, base)) { - if (!self || (base->lay & self->lay)) - add_collider_cache_object(&objs, base->object, self, 0); + 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 objs; + return cache; } -void free_collider_cache(ListBase **colliders) +void BKE_collider_cache_free(ListBase **colliders) { if (*colliders) { BLI_freelistN(*colliders); @@ -676,7 +686,7 @@ static int cloth_bvh_objcollisions_resolve ( ClothModifierData * clmd, Collision } // cloth - object collisions -int cloth_bvh_objcollision(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; @@ -702,7 +712,7 @@ int cloth_bvh_objcollision(Object *ob, ClothModifierData *clmd, float step, floa 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(clmd->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; @@ -884,8 +894,7 @@ int cloth_bvh_objcollision(Object *ob, ClothModifierData *clmd, float step, floa } while ( ret2 && ( clmd->coll_parms->loop_count>rounds ) ); - if (collobjs) - MEM_freeN(collobjs); + BKE_collision_objects_free(collobjs); return 1|MIN2 ( ret, 1 ); } @@ -1197,7 +1206,7 @@ static int cloth_points_objcollisions_resolve( } // cloth - object collisions -int cloth_points_objcollision(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; @@ -1230,7 +1239,7 @@ int cloth_points_objcollision(Object *ob, ClothModifierData *clmd, float step, f /* balance tree */ BLI_bvhtree_balance(cloth_bvh); - collobjs = get_collisionobjects(clmd->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; @@ -1311,15 +1320,14 @@ int cloth_points_objcollision(Object *ob, ClothModifierData *clmd, float step, f } 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(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; @@ -1340,7 +1348,7 @@ void cloth_find_point_contacts(Object *ob, ClothModifierData *clmd, float step, //////////////////////////////////////////////////////////// /* Check we do have collision objects to test against, before doing anything else. */ - collobjs = get_collisionobjects(clmd->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; @@ -1412,8 +1420,7 @@ void cloth_find_point_contacts(Object *ob, ClothModifierData *clmd, float step, MEM_freeN(overlap); } - if (collobjs) - MEM_freeN(collobjs); + BKE_collision_objects_free(collobjs); BLI_bvhtree_free(cloth_bvh); |