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)
This commit is contained in:
2010-03-26 10:52:55 +00:00
parent 05b1f00858
commit 666cca69e9
10 changed files with 121 additions and 175 deletions

View 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"

View File

@@ -49,12 +49,13 @@
#include "BLI_kdopbvh.h"
struct Cloth;
struct ClothModifierData;
struct DerivedMesh;
struct Group;
struct MFace;
struct Object;
struct Scene;
struct Cloth;
struct MFace;
struct DerivedMesh;
struct ClothModifierData;
////////////////////////////////////////
// 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);
/////////////////////////////////////////////////

View File

@@ -1299,188 +1299,122 @@ static int cloth_collision_moving ( ClothModifierData *clmd, CollisionModifierDa
}
#endif
static void add_collision_object(Object ***objs, int *numobj, int *maxobj, Object *ob, Object *self, int level)
{
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);
if(cmd) {
/* extend array */
if(*numobj >= *maxobj) {
*maxobj *= 2;
*objs= MEM_reallocN(*objs, sizeof(Object*)*(*maxobj));
}
(*objs)[*numobj] = ob;
(*numobj)++;
}
/* objects in dupli groups, one level only for now */
if(ob->dup_group && level == 0) {
GroupObject *go;
Group *group= 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);
}
}
// return all collision objects in scene
// collision object will exclude self
Object **get_collisionobjects(Scene *scene, Object *self, int *numcollobj)
Object **get_collisionobjects(Scene *scene, Object *self, Group *group, int *numcollobj)
{
Base *base=NULL;
Object **objs = NULL;
Object *coll_ob = NULL;
CollisionModifierData *collmd = NULL;
int numobj = 0, maxobj = 100;
Base *base;
Object **objs;
GroupObject *go;
int numobj= 0, maxobj= 100;
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 );
}
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= MEM_callocN(sizeof(Object *)*maxobj, "CollisionObjectsArray");
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;
if ( !collmd )
continue;
if( !collmd->bvhtree)
continue;
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++;
}
}
}
/* 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);
}
*numcollobj = numobj;
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;
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;
if(ob == self)
return;
if(ob->pd && ob->pd->deflect)
cmd =(CollisionModifierData *)modifiers_findByType(ob, eModifierType_Collision);
// 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(cmd && cmd->bvhtree) {
if(*objs == NULL)
*objs = MEM_callocN(sizeof(ListBase), "ColliderCache array");
if(self && (base->lay & self->lay)==0)
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 );
}
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;
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;
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);
}
}
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);
}
/* objects in dupli groups, one level only for now */
if(ob->dup_group && level == 0) {
GroupObject *go;
Group *group= ob->dup_group;
/* 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;

View 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;

View 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 */

View 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;

View 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"

View 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);
}
}

View 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;

View 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)