Cloth simulation can now use a group to specify which objects
authorBrecht Van Lommel <brechtvanlommel@pandora.be>
Fri, 26 Mar 2010 10:52:55 +0000 (10:52 +0000)
committerBrecht Van Lommel <brechtvanlommel@pandora.be>
Fri, 26 Mar 2010 10:52:55 +0000 (10:52 +0000)
to collide with, in addition to the effectors group.
(commit 27746 by Brecht from render25 branch)

release/scripts/ui/properties_physics_cloth.py
source/blender/blenkernel/BKE_collision.h
source/blender/blenkernel/intern/collision.c
source/blender/blenkernel/intern/effect.c
source/blender/blenkernel/intern/implicit.c
source/blender/blenkernel/intern/particle_system.c
source/blender/blenkernel/intern/scene.c
source/blender/blenloader/intern/readfile.c
source/blender/makesdna/DNA_cloth_types.h
source/blender/makesrna/intern/rna_cloth.c

index 7a65420..22a83e0 100644 (file)
@@ -179,6 +179,7 @@ class PHYSICS_PT_cloth_collision(PhysicButtonsPanel):
         sub.prop(cloth, "self_collision_quality", slider=True, text="Quality")
         sub.prop(cloth, "self_min_distance", slider=True, text="Distance")
 
+        layout.prop(cloth, "group")
 
 class PHYSICS_PT_cloth_stiffness(PhysicButtonsPanel):
     bl_label = "Cloth Stiffness Scaling"
index 689fa96..91c5eb4 100644 (file)
 
 #include "BLI_kdopbvh.h"
 
-struct Object;
-struct Scene;
 struct Cloth;
-struct MFace;
-struct DerivedMesh;
 struct ClothModifierData;
+struct DerivedMesh;
+struct Group;
+struct MFace;
+struct Object;
+struct Scene;
 
 ////////////////////////////////////////
 // used for collisions in collision.c
@@ -139,7 +140,7 @@ void interpolateOnTriangle ( float to[3], float v1[3], float v2[3], float v3[3],
 /////////////////////////////////////////////////
 // used in effect.c
 /////////////////////////////////////////////////
-Object **get_collisionobjects(struct Scene *scene, Object *self, int *numcollobj);
+struct Object **get_collisionobjects(struct Scene *scene, struct Object *self, struct Group *group, int *numcollobj);
 
 typedef struct ColliderCache {
        struct ColliderCache *next, *prev;
@@ -147,7 +148,7 @@ typedef struct ColliderCache {
        struct CollisionModifierData *collmd;
 } ColliderCache;
 
-struct ListBase *get_collider_cache(struct Scene *scene, Object *self);
+struct ListBase *get_collider_cache(struct Scene *scene, struct Object *self, struct Group *group);
 void free_collider_cache(struct ListBase **colliders);
 
 /////////////////////////////////////////////////
index b024ba5..c85bd2f 100644 (file)
@@ -1299,188 +1299,122 @@ static int cloth_collision_moving ( ClothModifierData *clmd, CollisionModifierDa
 }
 #endif
 
-
-// return all collision objects in scene
-// collision object will exclude self 
-Object **get_collisionobjects(Scene *scene, Object *self, int *numcollobj)
+static void add_collision_object(Object ***objs, int *numobj, int *maxobj, Object *ob, Object *self, int level)
 {
-       Base *base=NULL;
-       Object **objs = NULL;
-       Object *coll_ob = NULL;
-       CollisionModifierData *collmd = NULL;
-       int numobj = 0, maxobj = 100;
+       CollisionModifierData *cmd= NULL;
+
+       if(ob == self)
+               return;
+
+       /* only get objects with collision modifier */
+       if(ob->pd && ob->pd->deflect)
+               cmd= (CollisionModifierData *)modifiers_findByType(ob, eModifierType_Collision);
        
-       objs = MEM_callocN(sizeof(Object *)*maxobj, "CollisionObjectsArray");
-       // check all collision objects
-       for ( base = scene->base.first; base; base = base->next )
-       {
-               /*Only proceed for mesh object in same layer */
-               if(!(base->object->type==OB_MESH && (base->lay & self->lay))) 
-                       continue;
-               
-               coll_ob = base->object;
-               
-               if(coll_ob == self)
-                               continue;
-               
-               if(coll_ob->pd && coll_ob->pd->deflect)
-               {
-                       collmd = ( CollisionModifierData * ) modifiers_findByType ( coll_ob, eModifierType_Collision );
+       if(cmd) {       
+               /* extend array */
+               if(*numobj >= *maxobj) {
+                       *maxobj *= 2;
+                       *objs= MEM_reallocN(*objs, sizeof(Object*)*(*maxobj));
                }
-               else
-                       collmd = NULL;
                
-               if ( collmd )
-               {       
-                       if(numobj >= maxobj)
-                       {
-                               // realloc
-                               int oldmax = maxobj;
-                               Object **tmp;
-                               maxobj *= 2;
-                               tmp = MEM_callocN(sizeof(Object *)*maxobj, "CollisionObjectsArray");
-                               memcpy(tmp, objs, sizeof(Object *)*oldmax);
-                               MEM_freeN(objs);
-                               objs = tmp;
-                               
-                       }
-                       
-                       objs[numobj] = coll_ob;
-                       numobj++;
-               }
-               else
-               {
-                       if ( coll_ob->dup_group )
-                       {
-                               GroupObject *go;
-                               Group *group = coll_ob->dup_group;
+               (*objs)[*numobj] = ob;
+               (*numobj)++;
+       }
 
-                               for ( go= group->gobject.first; go; go= go->next )
-                               {
-                                       coll_ob = go->ob;
-                                       collmd = NULL;
-                                       
-                                       if(coll_ob == self)
-                                               continue;
-                                       
-                                       if(coll_ob->pd && coll_ob->pd->deflect)
-                                       {
-                                               collmd = ( CollisionModifierData * ) modifiers_findByType ( coll_ob, eModifierType_Collision );
-                                       }
-                                       else
-                                               collmd = NULL;
+       /* objects in dupli groups, one level only for now */
+       if(ob->dup_group && level == 0) {
+               GroupObject *go;
+               Group *group= ob->dup_group;
 
-                                       if ( !collmd )
-                                               continue;
-                                       
-                                       if( !collmd->bvhtree)
-                                               continue;
+               /* add objects */
+               for(go= group->gobject.first; go; go= go->next)
+                       add_collision_object(objs, numobj, maxobj, go->ob, self, level+1);
+       }       
+}
 
-                                       if(numobj >= maxobj)
-                                       {
-                                               // realloc
-                                               int oldmax = maxobj;
-                                               Object **tmp;
-                                               maxobj *= 2;
-                                               tmp = MEM_callocN(sizeof(Object *)*maxobj, "CollisionObjectsArray");
-                                               memcpy(tmp, objs, sizeof(Object *)*oldmax);
-                                               MEM_freeN(objs);
-                                               objs = tmp;
-                                       }
-                                       
-                                       objs[numobj] = coll_ob;
-                                       numobj++;
-                               }
-                       }
-               }       
+// return all collision objects in scene
+// collision object will exclude self 
+Object **get_collisionobjects(Scene *scene, Object *self, Group *group, int *numcollobj)
+{
+       Base *base;
+       Object **objs;
+       GroupObject *go;
+       int numobj= 0, maxobj= 100;
+       
+       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, 0);
+       }
+       else {
+               /* add objects in same layer in scene */
+               for(base = scene->base.first; base; base = base->next)
+                       if(base->lay & self->lay) 
+                               add_collision_object(&objs, &numobj, &maxobj, base->object, self, 0);
        }
-       *numcollobj = numobj;
+
+       *numcollobj= numobj;
+
        return objs;
 }
 
-ListBase *get_collider_cache(Scene *scene, Object *self)
+static void add_collider_cache_object(ListBase **objs, Object *ob, Object *self, int level)
 {
-       Base *base=NULL;
-       ListBase *objs = NULL;
-       Object *coll_ob = NULL;
-       CollisionModifierData *collmd = NULL;
+       CollisionModifierData *cmd= NULL;
        ColliderCache *col;
-       
-       // check all collision objects
-       for ( base = scene->base.first; base; base = base->next )
-       {
-               /*Only proceed for mesh object in same layer */
-               if(base->object->type!=OB_MESH)
-                       continue;
 
-               if(self && (base->lay & self->lay)==0) 
-                       continue;
+       if(ob == self)
+               return;
 
-               
-               coll_ob = base->object;
-               
-               if(coll_ob == self)
-                               continue;
-               
-               if(coll_ob->pd && coll_ob->pd->deflect)
-               {
-                       collmd = ( CollisionModifierData * ) modifiers_findByType ( coll_ob, eModifierType_Collision );
-               }
-               else
-                       collmd = NULL;
-               
-               if ( collmd )
-               {       
-                       if(objs == NULL)
-                               objs = MEM_callocN(sizeof(ListBase), "ColliderCache array");
-
-                       col = MEM_callocN(sizeof(ColliderCache), "ColliderCache");
-                       col->ob = coll_ob;
-                       col->collmd = collmd;
-                       /* make sure collider is properly set up */
-                       collision_move_object(collmd, 1.0, 0.0);
-                       BLI_addtail(objs, col);
-               }
-               else if ( coll_ob->dup_group )
-                       {
-                               GroupObject *go;
-                               Group *group = coll_ob->dup_group;
+       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);
+       }
 
-                               for ( go= group->gobject.first; go; go= go->next )
-                               {
-                                       coll_ob = go->ob;
-                                       collmd = NULL;
-                                       
-                                       if(coll_ob == self)
-                                               continue;
-                                       
-                                       if(coll_ob->pd && coll_ob->pd->deflect)
-                                       {
-                                               collmd = ( CollisionModifierData * ) modifiers_findByType ( coll_ob, eModifierType_Collision );
-                                       }
-                                       else
-                                               collmd = NULL;
+       /* objects in dupli groups, one level only for now */
+       if(ob->dup_group && level == 0) {
+               GroupObject *go;
+               Group *group= ob->dup_group;
 
-                                       if ( !collmd )
-                                               continue;
-                                       
-                                       if( !collmd->bvhtree)
-                                               continue;
-
-                                       if(objs == NULL)
-                                               objs = MEM_callocN(sizeof(ListBase), "ColliderCache array");
-
-                                       col = MEM_callocN(sizeof(ColliderCache), "ColliderCache");
-                                       col->ob = coll_ob;
-                                       col->collmd = collmd;
-                                       /* make sure collider is properly set up */
-                                       collision_move_object(collmd, 1.0, 0.0);
-                                       BLI_addtail(objs, col);
-                               }
-                       }
+               /* add objects */
+               for(go= group->gobject.first; go; go= go->next)
+                       add_collider_cache_object(objs, go->ob, self, level+1);
+       }
+}
+
+ListBase *get_collider_cache(Scene *scene, Object *self, Group *group)
+{
+       Base *base;
+       GroupObject *go;
+       ListBase *objs= 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);
+       }
+       else {
+               for(base = scene->base.first; base; base = base->next)
+                       if(self && (base->lay & self->lay)==0) 
+                               add_collider_cache_object(&objs, base->object, self, 0);
        }
+
        return objs;
 }
+
 void free_collider_cache(ListBase **colliders)
 {
        if(*colliders) {
@@ -1489,6 +1423,7 @@ void free_collider_cache(ListBase **colliders)
                *colliders = NULL;
        }
 }
+
 static void cloth_bvh_objcollisions_nearcheck ( ClothModifierData * clmd, CollisionModifierData *collmd, CollPair **collisions, CollPair **collisions_index, int numresult, BVHTreeOverlap *overlap)
 {
        int i;
@@ -1574,7 +1509,7 @@ int cloth_bvh_objcollision (Object *ob, ClothModifierData * clmd, float step, 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(clmd->scene, ob, &numcollobj);
+       collobjs = get_collisionobjects(clmd->scene, ob, clmd->coll_parms->group, &numcollobj);
        
        if(!collobjs)
                return 0;
index 66e7f80..118f488 100644 (file)
@@ -429,7 +429,7 @@ static float eff_calc_visibility(ListBase *colliders, EffectorCache *eff, Effect
                return visibility;
 
        if(!colls)
-               colls = get_collider_cache(eff->scene, NULL);
+               colls = get_collider_cache(eff->scene, NULL, NULL);
 
        if(!colls)
                return visibility;
index b4fb34d..c625fb2 100644 (file)
@@ -1422,7 +1422,7 @@ static void hair_velocity_smoothing(ClothModifierData *clmd, lfVector *lF, lfVec
        /* 10x10x10 grid gives nice initial results */
        HairGridVert grid[10][10][10];
        HairGridVert colg[10][10][10];
-       ListBase *colliders = get_collider_cache(clmd->scene, NULL);
+       ListBase *colliders = get_collider_cache(clmd->scene, NULL, NULL);
        ColliderCache *col = NULL;
        float gmin[3], gmax[3], density;
        /* 2.0f is an experimental value that seems to give good results */
index a99a8af..a8446c0 100644 (file)
@@ -3229,7 +3229,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, NULL);
+               sim->colliders = get_collider_cache(sim->scene, NULL, NULL);
 
        if(part->phystype==PART_PHYS_BOIDS){
                ParticleTarget *pt = psys->targets.first;
index 0bce2d0..dd2a314 100644 (file)
@@ -53,6 +53,7 @@
 #include "BKE_animsys.h"
 #include "BKE_depsgraph.h"
 #include "BKE_global.h"
+#include "BKE_group.h"
 #include "BKE_idprop.h"
 #include "BKE_library.h"
 #include "BKE_main.h"
index 768fe1f..356ae15 100644 (file)
@@ -3065,6 +3065,7 @@ static void lib_link_particlesystems(FileData *fd, Object *ob, ID *id, ListBase
                                 * pointcache should /w cloth should be added in 'ParticleSystem' - campbell */
                                psys->clmd->point_cache= psys->pointcache;
                                psys->clmd->ptcaches.first= psys->clmd->ptcaches.last= NULL;
+                               psys->clmd->coll_parms->group= newlibadr(fd, id->lib, psys->clmd->coll_parms->group);
                        }
                }
                else {
@@ -3621,6 +3622,7 @@ static void lib_link_object(FileData *fd, Main *main)
                                if(clmd) 
                                {
                                        clmd->sim_parms->effector_weights->group = newlibadr(fd, ob->id.lib, clmd->sim_parms->effector_weights->group);
+                                       clmd->coll_parms->group= newlibadr(fd, ob->id.lib, clmd->coll_parms->group);
                                }
                        }
                        
index 8fa63e6..bd323c5 100644 (file)
@@ -93,6 +93,7 @@ typedef struct ClothCollSettings
        int     flags;                  /* collision flags defined in BKE_cloth.h */
        short   self_loop_count;        /* How many iterations for the selfcollision loop       */
        short   loop_count;             /* How many iterations for the collision loop.          */
+       struct Group *group;    /* Only use colliders from this group of objects */
 } ClothCollSettings;
 
 
index 7dcdd92..19718a3 100644 (file)
@@ -430,6 +430,11 @@ static void rna_def_cloth_collision_settings(BlenderRNA *brna)
        RNA_def_property_range(prop, 1, 10);
        RNA_def_property_ui_text(prop, "Self Collision Quality", "How many self collision iterations should be done. (higher is better quality but slower)");
        RNA_def_property_update(prop, 0, "rna_cloth_update");
+
+       prop= RNA_def_property(srna, "group", PROP_POINTER, PROP_NONE);
+       RNA_def_property_flag(prop, PROP_EDITABLE);
+       RNA_def_property_ui_text(prop, "Collision Group", "Limit colliders to this Group");
+       RNA_def_property_update(prop, 0, "rna_cloth_update");
 }
 
 void RNA_def_cloth(BlenderRNA *brna)