Merge branch 'master' into blender2.8
authorBastien Montagne <montagne29@wanadoo.fr>
Mon, 3 Sep 2018 13:33:07 +0000 (15:33 +0200)
committerBastien Montagne <montagne29@wanadoo.fr>
Mon, 3 Sep 2018 13:33:07 +0000 (15:33 +0200)
1  2 
source/blender/blenkernel/intern/collision.c

index 0ba30fedc325ea4c6c92221011f9eb09c6a060ac,65c84187307283f59b085518c2bc2cb4107bba9d..d3aa52509557f33482a950467052076353ee5b9c
@@@ -33,8 -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,9 -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"
  
  #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
@@@ -483,143 -477,139 +483,143 @@@ static CollPair* cloth_collision(Modifi
        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);
@@@ -686,7 -676,7 +686,7 @@@ static int cloth_bvh_objcollisions_reso
  }
  
  // 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;
        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;
        }
        while ( ret2 && ( clmd->coll_parms->loop_count>rounds ) );
  
 -      if (collobjs)
 -              MEM_freeN(collobjs);
 +      BKE_collision_objects_free(collobjs);
  
        return 1|MIN2 ( ret, 1 );
  }
@@@ -1206,7 -1197,7 +1206,7 @@@ static int cloth_points_objcollisions_r
  }
  
  // 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;
        /* 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;
  
        }
        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;
        /* 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) {
                *r_collider_contacts = NULL;
                *r_totcolliders = 0;
+               BLI_bvhtree_free(cloth_bvh);
                return;
        }
  
                        MEM_freeN(overlap);
        }
  
 -      if (collobjs)
 -              MEM_freeN(collobjs);
 +      BKE_collision_objects_free(collobjs);
  
        BLI_bvhtree_free(cloth_bvh);