Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'source/blender/blenkernel/intern/collision.c')
-rw-r--r--source/blender/blenkernel/intern/collision.c203
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);