From 666cca69e90bf1f5c1bfb5a6582c56c2e8311f04 Mon Sep 17 00:00:00 2001 From: Brecht Van Lommel Date: Fri, 26 Mar 2010 10:52:55 +0000 Subject: Cloth simulation can now use a group to specify which objects to collide with, in addition to the effectors group. (commit 27746 by Brecht from render25 branch) --- source/blender/blenkernel/BKE_collision.h | 13 +- source/blender/blenkernel/intern/collision.c | 261 ++++++++------------- source/blender/blenkernel/intern/effect.c | 2 +- source/blender/blenkernel/intern/implicit.c | 2 +- source/blender/blenkernel/intern/particle_system.c | 2 +- source/blender/blenkernel/intern/scene.c | 1 + 6 files changed, 109 insertions(+), 172 deletions(-) (limited to 'source/blender/blenkernel') diff --git a/source/blender/blenkernel/BKE_collision.h b/source/blender/blenkernel/BKE_collision.h index 689fa96ffa6..91c5eb4afee 100644 --- a/source/blender/blenkernel/BKE_collision.h +++ b/source/blender/blenkernel/BKE_collision.h @@ -49,12 +49,13 @@ #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); ///////////////////////////////////////////////// diff --git a/source/blender/blenkernel/intern/collision.c b/source/blender/blenkernel/intern/collision.c index b024ba5f4e1..c85bd2f90b3 100644 --- a/source/blender/blenkernel/intern/collision.c +++ b/source/blender/blenkernel/intern/collision.c @@ -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; diff --git a/source/blender/blenkernel/intern/effect.c b/source/blender/blenkernel/intern/effect.c index 66e7f805f50..118f4885af4 100644 --- a/source/blender/blenkernel/intern/effect.c +++ b/source/blender/blenkernel/intern/effect.c @@ -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; diff --git a/source/blender/blenkernel/intern/implicit.c b/source/blender/blenkernel/intern/implicit.c index b4fb34d8464..c625fb28840 100644 --- a/source/blender/blenkernel/intern/implicit.c +++ b/source/blender/blenkernel/intern/implicit.c @@ -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 */ diff --git a/source/blender/blenkernel/intern/particle_system.c b/source/blender/blenkernel/intern/particle_system.c index a99a8affbd3..a8446c0009f 100644 --- a/source/blender/blenkernel/intern/particle_system.c +++ b/source/blender/blenkernel/intern/particle_system.c @@ -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; diff --git a/source/blender/blenkernel/intern/scene.c b/source/blender/blenkernel/intern/scene.c index 0bce2d004e3..dd2a3143d3d 100644 --- a/source/blender/blenkernel/intern/scene.c +++ b/source/blender/blenkernel/intern/scene.c @@ -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" -- cgit v1.2.3