Support limiting collisions by group for softbody and particles
authorAlexander Gavrilov <angavrilov@gmail.com>
Sun, 31 Jul 2016 08:56:44 +0000 (18:56 +1000)
committerCampbell Barton <ideasman42@gmail.com>
Sun, 31 Jul 2016 08:57:19 +0000 (18:57 +1000)
This feature is extremely useful for layering multiple cloth objects,
and there is no reason there shouldn't be the same kind of feature for softbody.

release/scripts/startup/bl_ui/properties_particle.py
release/scripts/startup/bl_ui/properties_physics_softbody.py
source/blender/blenkernel/intern/library_query.c
source/blender/blenkernel/intern/particle_system.c
source/blender/blenkernel/intern/softbody.c
source/blender/blenloader/intern/readfile.c
source/blender/makesdna/DNA_object_force.h
source/blender/makesdna/DNA_particle_types.h
source/blender/makesrna/intern/rna_object_force.c
source/blender/makesrna/intern/rna_particle.c

index 08290f20a69ba65791c30a83f857ab81cab9c360..c2580d4ac718f18c25c573a0f43b634322ba2f46 100644 (file)
@@ -605,6 +605,8 @@ class PARTICLE_PT_physics(ParticleButtonsPanel, Panel):
             row.prop(part, "use_size_deflect")
             row.prop(part, "use_die_on_collision")
 
+            layout.prop(part, "collision_group")
+
             if part.physics_type == 'FLUID':
                 fluid = part.fluid
 
index c96f455a10581fe277f4ccfe7ffed4f498d2d2b9..a458af739f2abe2c84eb35dc84dc1bdcbf81ed43 100644 (file)
@@ -68,6 +68,8 @@ class PHYSICS_PT_softbody(PhysicButtonsPanel, Panel):
         col.label(text="Simulation:")
         col.prop(softbody, "speed")
 
+        layout.prop(softbody, "collision_group")
+
 
 class PHYSICS_PT_softbody_cache(PhysicButtonsPanel, Panel):
     bl_label = "Soft Body Cache"
index 86602e6d70ab718df3df9d1e5a4d8bd56a4bae51..d71e8012e1000fed676db0ada8d3102c09b30328 100644 (file)
@@ -499,8 +499,12 @@ void BKE_library_foreach_ID_link(ID *id, LibraryIDLinkCallback callback, void *u
                                        BKE_particlesystem_id_loop(psys, library_foreach_particlesystemsObjectLooper, &data);
                                }
 
-                               if (object->soft && object->soft->effector_weights) {
-                                       CALLBACK_INVOKE(object->soft->effector_weights->group, IDWALK_NOP);
+                               if (object->soft) {
+                                       CALLBACK_INVOKE(object->soft->collision_group, IDWALK_NOP);
+
+                                       if (object->soft->effector_weights) {
+                                               CALLBACK_INVOKE(object->soft->effector_weights->group, IDWALK_NOP);
+                                       }
                                }
 
                                BKE_sca_sensors_id_loop(&object->sensors, library_foreach_sensorsObjectLooper, &data);
@@ -715,6 +719,7 @@ void BKE_library_foreach_ID_link(ID *id, LibraryIDLinkCallback callback, void *u
                                CALLBACK_INVOKE(psett->dup_group, IDWALK_NOP);
                                CALLBACK_INVOKE(psett->dup_ob, IDWALK_NOP);
                                CALLBACK_INVOKE(psett->bb_ob, IDWALK_NOP);
+                               CALLBACK_INVOKE(psett->collision_group, IDWALK_NOP);
 
                                for (i = 0; i < MAX_MTEX; i++) {
                                        if (psett->mtex[i]) {
index c3f47fac85211e4c4e8d4e5bb0dd9716a262f3e6..e7561ee699e0e06307b64456b1619ad24d548d83 100644 (file)
@@ -3493,7 +3493,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, NULL);
+               sim->colliders = get_collider_cache(sim->scene, sim->ob, part->collision_group);
 
        /* initialize physics type specific stuff */
        switch (part->phystype) {
index 8fec817d6948bea6d03201d6d096967506cb35fe..7aa899dcf2a69f52112ecde659320bbccf11f65b 100644 (file)
@@ -63,6 +63,7 @@ variables on the UI for now
 #include "DNA_curve_types.h"
 #include "DNA_mesh_types.h"
 #include "DNA_meshdata_types.h"
+#include "DNA_group_types.h"
 
 #include "BLI_math.h"
 #include "BLI_utildefines.h"
@@ -496,59 +497,100 @@ static void ccd_mesh_free(ccd_Mesh *ccdm)
        }
 }
 
-static void ccd_build_deflector_hash(Scene *scene, Object *vertexowner, GHash *hash)
+static void ccd_build_deflector_hash_single(GHash *hash, Object *ob)
+{
+       /* only with deflecting set */
+       if (ob->pd && ob->pd->deflect) {
+               void **val_p;
+               if (!BLI_ghash_ensure_p(hash, ob, &val_p)) {
+                       ccd_Mesh *ccdmesh = ccd_mesh_make(ob);
+                       *val_p = ccdmesh;
+               }
+       }
+}
+
+/**
+ * \note group overrides scene when not NULL.
+ */
+static void ccd_build_deflector_hash(Scene *scene, Group *group, Object *vertexowner, GHash *hash)
 {
-       Base *base= scene->base.first;
        Object *ob;
 
        if (!hash) return;
-       while (base) {
-               /*Only proceed for mesh object in same layer */
-               if (base->object->type==OB_MESH && (base->lay & vertexowner->lay)) {
-                       ob= base->object;
-                       if ((vertexowner) && (ob == vertexowner)) {
-                               /* if vertexowner is given  we don't want to check collision with owner object */
-                               base = base->next;
+
+       if (group) {
+               /* Explicit collision group */
+               for (GroupObject *go = group->gobject.first; go; go = go->next) {
+                       ob = go->ob;
+
+                       if (ob == vertexowner || ob->type != OB_MESH)
                                continue;
-                       }
 
-                       /*+++ only with deflecting set */
-                       if (ob->pd && ob->pd->deflect && BLI_ghash_lookup(hash, ob) == NULL) {
-                               ccd_Mesh *ccdmesh = ccd_mesh_make(ob);
-                               BLI_ghash_insert(hash, ob, ccdmesh);
-                       }/*--- only with deflecting set */
+                       ccd_build_deflector_hash_single(hash, ob);
+               }
+       }
+       else {
+               for (Base *base = scene->base.first; base; base = base->next) {
+                       /*Only proceed for mesh object in same layer */
+                       if (base->object->type == OB_MESH && (base->lay & vertexowner->lay)) {
+                               ob= base->object;
+                               if ((vertexowner) && (ob == vertexowner)) {
+                                       /* if vertexowner is given  we don't want to check collision with owner object */
+                                       base = base->next;
+                                       continue;
+                               }
+
+                               ccd_build_deflector_hash_single(hash, ob);
+                       }
+               }
+       }
+}
 
-               }/* mesh && layer*/
-               base = base->next;
-       } /* while (base) */
+static void ccd_update_deflector_hash_single(GHash *hash, Object *ob)
+{
+       if (ob->pd && ob->pd->deflect) {
+               ccd_Mesh *ccdmesh = BLI_ghash_lookup(hash, ob);
+               if (ccdmesh) {
+                       ccd_mesh_update(ob, ccdmesh);
+               }
+       }
 }
 
-static void ccd_update_deflector_hash(Scene *scene, Object *vertexowner, GHash *hash)
+/**
+ * \note group overrides scene when not NULL.
+ */
+static void ccd_update_deflector_hash(Scene *scene, Group *group, Object *vertexowner, GHash *hash)
 {
-       Base *base= scene->base.first;
        Object *ob;
 
        if ((!hash) || (!vertexowner)) return;
-       while (base) {
-               /*Only proceed for mesh object in same layer */
-               if (base->object->type==OB_MESH && (base->lay & vertexowner->lay)) {
-                       ob= base->object;
-                       if (ob == vertexowner) {
-                               /* if vertexowner is given  we don't want to check collision with owner object */
-                               base = base->next;
+
+       if (group) {
+               /* Explicit collision group */
+               for (GroupObject *go = group->gobject.first; go; go = go->next) {
+                       ob = go->ob;
+
+                       if (ob == vertexowner || ob->type != OB_MESH)
                                continue;
-                       }
 
-                       /*+++ only with deflecting set */
-                       if (ob->pd && ob->pd->deflect) {
-                               ccd_Mesh *ccdmesh = BLI_ghash_lookup(hash, ob);
-                               if (ccdmesh)
-                                       ccd_mesh_update(ob, ccdmesh);
-                       }/*--- only with deflecting set */
+                       ccd_update_deflector_hash_single(hash, ob);
+               }
+       }
+       else {
+               for (Base *base = scene->base.first; base; base = base->next) {
+                       /*Only proceed for mesh object in same layer */
+                       if (base->object->type == OB_MESH && (base->lay & vertexowner->lay)) {
+                               ob= base->object;
+                               if (ob == vertexowner) {
+                                       /* if vertexowner is given  we don't want to check collision with owner object */
+                                       base = base->next;
+                                       continue;
+                               }
 
-               }/* mesh && layer*/
-               base = base->next;
-       } /* while (base) */
+                               ccd_update_deflector_hash_single(hash, ob);
+                       }
+               }
+       }
 }
 
 
@@ -934,22 +976,32 @@ static void free_softbody_intern(SoftBody *sb)
 
 /* +++ dependency information functions*/
 
-static int are_there_deflectors(Scene *scene, unsigned int layer)
+/**
+ * \note group overrides scene when not NULL.
+ */
+static bool are_there_deflectors(Scene *scene, Group *group, unsigned int layer)
 {
-       Base *base;
-
-       for (base = scene->base.first; base; base= base->next) {
-               if ( (base->lay & layer) && base->object->pd) {
-                       if (base->object->pd->deflect)
+       if (group) {
+               for (GroupObject *go = group->gobject.first; go; go = go->next) {
+                       if (go->ob->pd && go->ob->pd->deflect)
                                return 1;
                }
        }
+       else {
+               for (Base *base = scene->base.first; base; base= base->next) {
+                       if ( (base->lay & layer) && base->object->pd) {
+                               if (base->object->pd->deflect)
+                                       return 1;
+                       }
+               }
+       }
+
        return 0;
 }
 
-static int query_external_colliders(Scene *scene, Object *me)
+static int query_external_colliders(Scene *scene, Group *group, Object *me)
 {
-       return(are_there_deflectors(scene, me->lay));
+       return(are_there_deflectors(scene, group, me->lay));
 }
 /* --- dependency information functions*/
 
@@ -2197,7 +2249,7 @@ static void softbody_calc_forcesEx(Scene *scene, Object *ob, float forcetime, fl
        /* gravity = sb->grav * sb_grav_force_scale(ob); */ /* UNUSED */
 
        /* check conditions for various options */
-       do_deflector= query_external_colliders(scene, ob);
+       do_deflector= query_external_colliders(scene, sb->collision_group, ob);
        /* do_selfcollision=((ob->softflag & OB_SB_EDGES) && (sb->bspring)&& (ob->softflag & OB_SB_SELF)); */ /* UNUSED */
        do_springcollision=do_deflector && (ob->softflag & OB_SB_EDGES) &&(ob->softflag & OB_SB_EDGECOLL);
        do_aero=((sb->aeroedge)&& (ob->softflag & OB_SB_EDGES));
@@ -2261,7 +2313,7 @@ static void softbody_calc_forces(Scene *scene, Object *ob, float forcetime, floa
                }
 
                /* check conditions for various options */
-               do_deflector= query_external_colliders(scene, ob);
+               do_deflector= query_external_colliders(scene, sb->collision_group, ob);
                do_selfcollision=((ob->softflag & OB_SB_EDGES) && (sb->bspring)&& (ob->softflag & OB_SB_SELF));
                do_springcollision=do_deflector && (ob->softflag & OB_SB_EDGES) &&(ob->softflag & OB_SB_EDGECOLL);
                do_aero=((sb->aeroedge)&& (ob->softflag & OB_SB_EDGES));
@@ -3472,11 +3524,11 @@ static void softbody_step(Scene *scene, Object *ob, SoftBody *sb, float dtime)
         */
        if (dtime < 0 || dtime > 10.5f) return;
 
-       ccd_update_deflector_hash(scene, ob, sb->scratch->colliderhash);
+       ccd_update_deflector_hash(scene, sb->collision_group, ob, sb->scratch->colliderhash);
 
        if (sb->scratch->needstobuildcollider) {
-               if (query_external_colliders(scene, ob)) {
-                       ccd_build_deflector_hash(scene, ob, sb->scratch->colliderhash);
+               if (query_external_colliders(scene, sb->collision_group, ob)) {
+                       ccd_build_deflector_hash(scene, sb->collision_group, ob, sb->scratch->colliderhash);
                }
                sb->scratch->needstobuildcollider=0;
        }
index 50e5eb195db9855962411d1e92c0ec3cca67dd8d..f6d371ee2d3691f69b56e643635be3bc56e736de 100644 (file)
@@ -4040,6 +4040,7 @@ static void lib_link_particlesettings(FileData *fd, Main *main)
                        part->dup_group = newlibadr(fd, part->id.lib, part->dup_group);
                        part->eff_group = newlibadr(fd, part->id.lib, part->eff_group);
                        part->bb_ob = newlibadr(fd, part->id.lib, part->bb_ob);
+                       part->collision_group = newlibadr(fd, part->id.lib, part->collision_group);
                        
                        lib_link_partdeflect(fd, &part->id, part->pd);
                        lib_link_partdeflect(fd, &part->id, part->pd2);
@@ -4891,8 +4892,11 @@ static void lib_link_object(FileData *fd, Main *main)
                        if (ob->pd)
                                lib_link_partdeflect(fd, &ob->id, ob->pd);
                        
-                       if (ob->soft)
+                       if (ob->soft) {
+                               ob->soft->collision_group = newlibadr(fd, ob->id.lib, ob->soft->collision_group);
+
                                ob->soft->effector_weights->group = newlibadr(fd, ob->id.lib, ob->soft->effector_weights->group);
+                       }
                        
                        lib_link_particlesystems(fd, ob, &ob->id, &ob->particlesystem);
                        lib_link_modifiers(fd, ob);
@@ -8840,6 +8844,7 @@ static void expand_particlesettings(FileData *fd, Main *mainvar, ParticleSetting
        expand_doit(fd, mainvar, part->dup_group);
        expand_doit(fd, mainvar, part->eff_group);
        expand_doit(fd, mainvar, part->bb_ob);
+       expand_doit(fd, mainvar, part->collision_group);
        
        if (part->adt)
                expand_animdata(fd, mainvar, part->adt);
@@ -9329,6 +9334,8 @@ static void expand_object(FileData *fd, Main *mainvar, Object *ob)
        }
 
        if (ob->soft) {
+               expand_doit(fd, mainvar, ob->soft->collision_group);
+
                if (ob->soft->effector_weights) {
                        expand_doit(fd, mainvar, ob->soft->effector_weights->group);
                }
index cccee82cb518838673eedc03594f25f08aed829d..59acefeffe45d9d62cd3824e9ba462ca7918a950 100644 (file)
@@ -339,6 +339,8 @@ typedef struct SoftBody {
        struct PointCache *pointcache;
        struct ListBase ptcaches;
 
+       struct Group *collision_group;
+
        struct EffectorWeights *effector_weights;
        /* reverse esimated obmatrix .. no need to store in blend file .. how ever who cares */ 
        float lcom[3];
index b284a683f8e6172fa12c84e72add10ae328853e8..1deb9bf3787c17b1be89ec3033c813b30634ac37 100644 (file)
@@ -160,6 +160,7 @@ typedef struct ParticleSettings {
        struct SPHFluidSettings *fluid;
 
        struct EffectorWeights *effector_weights;
+       struct Group *collision_group;
 
        int flag, rt;
        short type, from, distr, texact;
index a8d8407fe741b8efbbd0fd85af6f9afeb1f6a826..f05813043caf9ac80b3a1f4342cf7849a2245c25 100644 (file)
@@ -1852,6 +1852,11 @@ static void rna_def_softbody(BlenderRNA *brna)
        RNA_def_property_ui_text(prop, "Self Collision", "Enable naive vertex ball self collision");
        RNA_def_property_update(prop, 0, "rna_softbody_update");
 
+       prop = RNA_def_property(srna, "collision_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_softbody_update");
+
        prop = RNA_def_property(srna, "effector_weights", PROP_POINTER, PROP_NONE);
        RNA_def_property_pointer_sdna(prop, NULL, "effector_weights");
        RNA_def_property_struct_type(prop, "EffectorWeights");
index a52473b95f2a28be5c58ef9de05bd066c9b5a07c..eabf41cb3321ace32fd56a2cd1969f860b0fc081 100644 (file)
@@ -2741,6 +2741,10 @@ static void rna_def_particle_settings(BlenderRNA *brna)
        RNA_def_property_ui_text(prop, "Random Size", "Give the particle size a random variation");
        RNA_def_property_update(prop, 0, "rna_Particle_reset");
 
+       prop = RNA_def_property(srna, "collision_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_Particle_reset");
 
        /* global physical properties */
        prop = RNA_def_property(srna, "drag_factor", PROP_FLOAT, PROP_NONE);