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:
@@ -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"
|
||||
|
||||
@@ -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);
|
||||
|
||||
/////////////////////////////////////////////////
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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 */
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
|
||||
@@ -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)
|
||||
|
||||
Reference in New Issue
Block a user