Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDaniel Genrich <daniel.genrich@gmx.net>2008-07-03 00:28:49 +0400
committerDaniel Genrich <daniel.genrich@gmx.net>2008-07-03 00:28:49 +0400
commit8ca128414ddbe73bf31755df6cf19e5c70aba99c (patch)
tree4d7994a0b5a324b17a817c007d1711cc7cc167bd
parentb0958b6646b3b1fa8127f7620ce00e63ff82d0e7 (diff)
Cloth collisions: Reorganized collision system to be more flexible for other parts of blender, so it can be more easily reused. Also slowed down friction impulse.
-rw-r--r--source/blender/blenkernel/BKE_cloth.h2
-rw-r--r--source/blender/blenkernel/intern/cloth.c4
-rw-r--r--source/blender/blenkernel/intern/collision.c467
-rw-r--r--source/blender/blenkernel/intern/implicit.c13
4 files changed, 274 insertions, 212 deletions
diff --git a/source/blender/blenkernel/BKE_cloth.h b/source/blender/blenkernel/BKE_cloth.h
index 2e5da236a89..f3c13d3d820 100644
--- a/source/blender/blenkernel/BKE_cloth.h
+++ b/source/blender/blenkernel/BKE_cloth.h
@@ -208,7 +208,7 @@ typedef enum
////////////////////////////////////////////////
// needed for implicit.c
-int cloth_bvh_objcollision ( ClothModifierData * clmd, float step, float dt );
+int cloth_bvh_objcollision ( Object *ob, ClothModifierData * clmd, float step, float dt );
////////////////////////////////////////////////
diff --git a/source/blender/blenkernel/intern/cloth.c b/source/blender/blenkernel/intern/cloth.c
index 6034b85e20f..c7817b017ef 100644
--- a/source/blender/blenkernel/intern/cloth.c
+++ b/source/blender/blenkernel/intern/cloth.c
@@ -132,7 +132,7 @@ void cloth_init ( ClothModifierData *clmd )
clmd->coll_parms->self_friction = 5.0;
clmd->coll_parms->friction = 5.0;
- clmd->coll_parms->loop_count = 3;
+ clmd->coll_parms->loop_count = 2;
clmd->coll_parms->epsilon = 0.015f;
clmd->coll_parms->flags = CLOTH_COLLSETTINGS_FLAG_ENABLED;
clmd->coll_parms->collision_list = NULL;
@@ -471,7 +471,7 @@ static int do_step_cloth(Object *ob, ClothModifierData *clmd, DerivedMesh *resul
tend();
- /* printf ( "Cloth simulation time: %f\n", ( float ) tval() ); */
+ // printf ( "%f\n", ( float ) tval() );
return ret;
}
diff --git a/source/blender/blenkernel/intern/collision.c b/source/blender/blenkernel/intern/collision.c
index 7f41ca033d3..26c5d186d87 100644
--- a/source/blender/blenkernel/intern/collision.c
+++ b/source/blender/blenkernel/intern/collision.c
@@ -541,7 +541,7 @@ int cloth_collision_response_static ( ClothModifierData *clmd, CollisionModifier
{
Normalize ( vrel_t_pre );
- impulse = 2.0 * magtangent / ( 1.0 + w1*w1 + w2*w2 + w3*w3 );
+ impulse = magtangent / ( 1.0 + w1*w1 + w2*w2 + w3*w3 ); // 2.0 *
VECADDMUL ( cloth1->verts[collpair->ap1].impulse, vrel_t_pre, w1 * impulse );
VECADDMUL ( cloth1->verts[collpair->ap2].impulse, vrel_t_pre, w2 * impulse );
VECADDMUL ( cloth1->verts[collpair->ap3].impulse, vrel_t_pre, w3 * impulse );
@@ -1291,52 +1291,223 @@ int cloth_collision_moving ( ClothModifierData *clmd, CollisionModifierData *col
return 1;
}
-int cloth_bvh_objcollisions_do ( ClothModifierData * clmd, CollisionModifierData *collmd, float step, float dt )
-{
+int cloth_do_selfcollisions(ClothModifierData * clmd)
+{
+ int ret2 = 0, l;
Cloth *cloth = clmd->clothObject;
- BVHTree *cloth_bvh= ( BVHTree * ) cloth->bvhtree;
- long i=0, j = 0, numfaces = 0, numverts = 0;
- ClothVertex *verts = NULL;
- CollPair *collisions = NULL, *collisions_index = NULL;
- int ret = 0;
- int result = 0;
- float tnull[3] = {0,0,0};
- BVHTreeOverlap *overlap = NULL;
-
-
- numfaces = clmd->clothObject->numfaces;
- numverts = clmd->clothObject->numverts;
-
- verts = cloth->verts;
+
+ if ( clmd->clothObject->bvhselftree )
+ {
+ for(l = 0; l < clmd->coll_parms->self_loop_count; l++)
+ {
+ BVHTreeOverlap *overlap = NULL;
+ ClothVertex *verts = clmd->clothObject->verts; // needed for openMP
+ int k;
+ int ret = 0, result = 0;
+
+ // search for overlapping collision pairs
+ overlap = BLI_bvhtree_overlap ( cloth->bvhselftree, cloth->bvhselftree, &result );
+
+// #pragma omp parallel for private(k, i, j) schedule(static)
+ for ( k = 0; k < result; k++ )
+ {
+ float temp[3];
+ float length = 0;
+ float mindistance;
+ int i, j;
+
+ i = overlap[k].indexA;
+ j = overlap[k].indexB;
+
+ mindistance = clmd->coll_parms->selfepsilon* ( cloth->verts[i].avg_spring_len + cloth->verts[j].avg_spring_len );
+
+ if ( clmd->sim_parms->flags & CLOTH_SIMSETTINGS_FLAG_GOAL )
+ {
+ if ( ( cloth->verts [i].flags & CLOTH_VERT_FLAG_PINNED )
+ && ( cloth->verts [j].flags & CLOTH_VERT_FLAG_PINNED ) )
+ {
+ continue;
+ }
+ }
+
+ VECSUB ( temp, verts[i].tx, verts[j].tx );
+
+ if ( ( ABS ( temp[0] ) > mindistance ) || ( ABS ( temp[1] ) > mindistance ) || ( ABS ( temp[2] ) > mindistance ) ) continue;
+
+ // check for adjacent points (i must be smaller j)
+ if ( BLI_edgehash_haskey ( cloth->edgehash, MIN2(i, j), MAX2(i, j) ) )
+ {
+ continue;
+ }
+
+ length = Normalize ( temp );
+
+ if ( length < mindistance )
+ {
+ float correction = mindistance - length;
+
+ if ( cloth->verts [i].flags & CLOTH_VERT_FLAG_PINNED )
+ {
+ VecMulf ( temp, -correction );
+ VECADD ( verts[j].tx, verts[j].tx, temp );
+ }
+ else if ( cloth->verts [j].flags & CLOTH_VERT_FLAG_PINNED )
+ {
+ VecMulf ( temp, correction );
+ VECADD ( verts[i].tx, verts[i].tx, temp );
+ }
+ else
+ {
+ VecMulf ( temp, -correction*0.5 );
+ VECADD ( verts[j].tx, verts[j].tx, temp );
+
+ VECSUB ( verts[i].tx, verts[i].tx, temp );
+ }
+ ret = 1;
+ ret2 += ret;
+ }
+ else
+ {
+ // check for approximated time collisions
+ }
+ }
+
+ if ( overlap )
+ MEM_freeN ( overlap );
+
+ if(!ret)
+ break;
+
+ }
+ ////////////////////////////////////////////////////////////
+
+ ////////////////////////////////////////////////////////////
+ // SELFCOLLISIONS: update velocities
+ ////////////////////////////////////////////////////////////
+ if ( ret2 )
+ {
+ int i;
+ ClothVertex *verts = clmd->clothObject->verts; // needed for openMP
+
+ for ( i = 0; i < cloth->numverts; i++ )
+ {
+ if ( ! ( verts [i].flags & CLOTH_VERT_FLAG_PINNED ) )
+ {
+ VECSUB ( verts[i].tv, verts[i].tx, verts[i].txold );
+ }
+ }
+ }
+ ////////////////////////////////////////////////////////////
+ }
+ return ret2;
+}
- if ( collmd->bvhtree )
+// return all collision objects in scene
+// collision object will exclude self
+CollisionModifierData **get_collisionobjects(Object *self, int *numcollobj)
+{
+ Base *base=NULL;
+ CollisionModifierData **objs = NULL;
+ Object *coll_ob = NULL;
+ CollisionModifierData *collmd = NULL;
+ int numobj = 0, maxobj = 100;
+
+ objs = MEM_callocN(sizeof(CollisionModifierData *)*maxobj, "CollisionObjectsArray");
+ // check all collision objects
+ for ( base = G.scene->base.first; base; base = base->next )
{
- /* get pointer to bounding volume hierarchy */
- BVHTree *coll_bvh = collmd->bvhtree;
+ coll_ob = base->object;
+ collmd = ( CollisionModifierData * ) modifiers_findByType ( coll_ob, eModifierType_Collision );
+
+ if ( !collmd )
+ {
+ if ( coll_ob->dup_group )
+ {
+ GroupObject *go;
+ Group *group = coll_ob->dup_group;
- /* move object to position (step) in time */
- collision_move_object ( collmd, step + dt, step );
+ for ( go= group->gobject.first; go; go= go->next )
+ {
+ coll_ob = go->ob;
- /* search for overlapping collision pairs */
- overlap = BLI_bvhtree_overlap ( cloth_bvh, coll_bvh, &result );
+ collmd = ( CollisionModifierData * ) modifiers_findByType ( coll_ob, eModifierType_Collision );
- collisions = ( CollPair* ) MEM_mallocN ( sizeof ( CollPair ) * result*4, "collision array" ); //*4 since cloth_collision_static can return more than 1 collision
- collisions_index = collisions;
+ if ( !collmd )
+ continue;
- for ( i = 0; i < result; i++ )
- {
- collisions_index = cloth_collision ( ( ModifierData * ) clmd, ( ModifierData * ) collmd, overlap+i, collisions_index );
- }
+ if(coll_ob == self)
+ continue;
- if ( overlap )
- MEM_freeN ( overlap );
+ if(numobj >= maxobj)
+ {
+ // realloc
+ int oldmax = maxobj;
+ CollisionModifierData **tmp;
+ maxobj *= 2;
+ tmp = MEM_callocN(sizeof(CollisionModifierData *)*maxobj, "CollisionObjectsArray");
+ memcpy(tmp, objs, sizeof(CollisionModifierData *)*oldmax);
+ MEM_freeN(objs);
+ objs = tmp;
+ }
+
+ objs[numobj] = collmd;
+ numobj++;
+ }
+ }
+ }
+ else
+ {
+ if(coll_ob == self)
+ continue;
+
+ if(numobj >= maxobj)
+ {
+ // realloc
+ int oldmax = maxobj;
+ CollisionModifierData **tmp;
+ maxobj *= 2;
+ tmp = MEM_callocN(sizeof(CollisionModifierData *)*maxobj, "CollisionObjectsArray");
+ memcpy(tmp, objs, sizeof(CollisionModifierData *)*oldmax);
+ MEM_freeN(objs);
+ objs = tmp;
+
+ }
+
+ objs[numobj] = collmd;
+ numobj++;
+ }
}
- else
+ *numcollobj = numobj;
+ return objs;
+}
+
+void cloth_bvh_objcollisions_nearcheck ( ClothModifierData * clmd, CollisionModifierData *collmd, CollPair **collisions, CollPair **collisions_index, int numresult, BVHTreeOverlap *overlap)
+{
+ int i;
+
+ *collisions = ( CollPair* ) MEM_mallocN ( sizeof ( CollPair ) * numresult * 4, "collision array" ); //*4 since cloth_collision_static can return more than 1 collision
+ *collisions_index = *collisions;
+
+ for ( i = 0; i < numresult; i++ )
{
- if ( G.rt > 0 )
- printf ( "cloth_bvh_objcollision: found a collision object with clothObject or collData NULL.\n" );
+ *collisions_index = cloth_collision ( ( ModifierData * ) clmd, ( ModifierData * ) collmd, overlap+i, *collisions_index );
}
+}
+int cloth_bvh_objcollisions_resolve ( ClothModifierData * clmd, CollisionModifierData *collmd, CollPair *collisions, CollPair *collisions_index)
+{
+ Cloth *cloth = clmd->clothObject;
+ int i=0, j = 0, numfaces = 0, numverts = 0;
+ ClothVertex *verts = NULL;
+ int ret = 0;
+ int result = 0;
+ float tnull[3] = {0,0,0};
+
+ numfaces = clmd->clothObject->numfaces;
+ numverts = clmd->clothObject->numverts;
+
+ verts = cloth->verts;
+
// process all collisions (calculate impulses, TODO: also repulses if distance too short)
result = 1;
for ( j = 0; j < 5; j++ ) // 5 is just a value that ensures convergence
@@ -1363,48 +1534,22 @@ int cloth_bvh_objcollisions_do ( ClothModifierData * clmd, CollisionModifierData
}
}
}
-/*
- result += cloth_collision_moving ( clmd, collmd, collisions, collisions_index );
-
- // apply impulses in parallel
- if ( result )
- {
- for ( i = 0; i < numverts; i++ )
- {
- // calculate "velocities" (just xnew = xold + v; no dt in v)
- if ( verts[i].impulse_count )
- {
- VECADDMUL ( verts[i].tv, verts[i].impulse, 1.0f / verts[i].impulse_count );
- VECCOPY ( verts[i].impulse, tnull );
- verts[i].impulse_count = 0;
-
- ret++;
- }
- }
- }
-*/
}
}
-
- if ( collisions ) MEM_freeN ( collisions );
-
return ret;
}
// cloth - object collisions
-int cloth_bvh_objcollision ( ClothModifierData * clmd, float step, float dt )
+int cloth_bvh_objcollision ( Object *ob, ClothModifierData * clmd, float step, float dt )
{
- Base *base=NULL;
- CollisionModifierData *collmd=NULL;
Cloth *cloth=NULL;
- Object *coll_ob=NULL;
BVHTree *cloth_bvh=NULL;
- long i=0, j = 0, k = 0, l = 0, numfaces = 0, numverts = 0;
- int result = 0, rounds = 0; // result counts applied collisions; ic is for debug output;
+ long i=0, numfaces = 0, numverts = 0;
+ int rounds = 0; // result counts applied collisions; ic is for debug output;
ClothVertex *verts = NULL;
int ret = 0, ret2 = 0;
- ClothModifierData *tclmd;
- int collisions = 0;
+ CollisionModifierData **collobjs = NULL;
+ int numcollobj = 0;
if ( ( clmd->sim_parms->flags & CLOTH_SIMSETTINGS_FLAG_COLLOBJ ) || ! ( ( ( Cloth * ) clmd->clothObject )->bvhtree ) )
{
@@ -1424,54 +1569,61 @@ int cloth_bvh_objcollision ( ClothModifierData * clmd, float step, float dt )
// update cloth bvh
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(ob, &numcollobj);
+
+ if(!collobjs)
+ return 0;
do
{
- result = 0;
+ CollPair **collisions, **collisions_index;
+
ret2 = 0;
+ collisions = MEM_callocN(sizeof(CollPair *) *numcollobj , "CollPair");
+ collisions_index = MEM_callocN(sizeof(CollPair *) *numcollobj , "CollPair");
+
// check all collision objects
- for ( base = G.scene->base.first; base; base = base->next )
+ for(i = 0; i < numcollobj; i++)
{
- coll_ob = base->object;
- collmd = ( CollisionModifierData * ) modifiers_findByType ( coll_ob, eModifierType_Collision );
-
- if ( !collmd )
- {
- 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 = ( CollisionModifierData * ) modifiers_findByType ( coll_ob, eModifierType_Collision );
-
- if ( !collmd )
- continue;
-
- tclmd = ( ClothModifierData * ) modifiers_findByType ( coll_ob, eModifierType_Cloth );
- if ( tclmd == clmd )
- continue;
-
- ret += cloth_bvh_objcollisions_do ( clmd, collmd, step, dt );
- ret2 += ret;
- }
- }
- }
- else
+ CollisionModifierData *collmd = collobjs[i];
+ BVHTreeOverlap *overlap = NULL;
+ int result = 0;
+
+ /* move object to position (step) in time */
+ collision_move_object ( collmd, step + dt, step );
+
+ /* search for overlapping collision pairs */
+ overlap = BLI_bvhtree_overlap ( cloth_bvh, collmd->bvhtree, &result );
+
+ // go to next object if no overlap is there
+ if(!result || !overlap)
{
- tclmd = ( ClothModifierData * ) modifiers_findByType ( coll_ob, eModifierType_Cloth );
- if ( tclmd == clmd )
- continue;
-
- ret += cloth_bvh_objcollisions_do ( clmd, collmd, step, dt );
- ret2 += ret;
+ if ( overlap )
+ MEM_freeN ( overlap );
+ continue;
}
+
+ /* check if collisions really happen (costly near check) */
+ cloth_bvh_objcollisions_nearcheck ( clmd, collmd, &collisions[i], &collisions_index[i], result, overlap);
+
+ // resolve nearby collisions
+ ret += cloth_bvh_objcollisions_resolve ( clmd, collmd, collisions[i], collisions_index[i]);
+ ret2 += ret;
+
+ if ( overlap )
+ MEM_freeN ( overlap );
}
rounds++;
+
+ for(i = 0; i < numcollobj; i++)
+ {
+ if ( collisions[i] ) MEM_freeN ( collisions[i] );
+ }
+
+ MEM_freeN(collisions);
+ MEM_freeN(collisions_index);
////////////////////////////////////////////////////////////
// update positions
@@ -1493,117 +1645,20 @@ int cloth_bvh_objcollision ( ClothModifierData * clmd, float step, float dt )
}
////////////////////////////////////////////////////////////
-
+
////////////////////////////////////////////////////////////
// Test on *simple* selfcollisions
////////////////////////////////////////////////////////////
if ( clmd->coll_parms->flags & CLOTH_COLLSETTINGS_FLAG_SELF )
{
- for(l = 0; l < clmd->coll_parms->self_loop_count; l++)
- {
- // TODO: add coll quality rounds again
- BVHTreeOverlap *overlap = NULL;
-
- collisions = 1;
- verts = cloth->verts; // needed for openMP
-
- numfaces = clmd->clothObject->numfaces;
- numverts = clmd->clothObject->numverts;
-
- verts = cloth->verts;
-
- if ( cloth->bvhselftree )
- {
- // search for overlapping collision pairs
- overlap = BLI_bvhtree_overlap ( cloth->bvhselftree, cloth->bvhselftree, &result );
-
- // #pragma omp parallel for private(k, i, j) schedule(static)
- for ( k = 0; k < result; k++ )
- {
- float temp[3];
- float length = 0;
- float mindistance;
-
- i = overlap[k].indexA;
- j = overlap[k].indexB;
-
- mindistance = clmd->coll_parms->selfepsilon* ( cloth->verts[i].avg_spring_len + cloth->verts[j].avg_spring_len );
-
- if ( clmd->sim_parms->flags & CLOTH_SIMSETTINGS_FLAG_GOAL )
- {
- if ( ( cloth->verts [i].flags & CLOTH_VERT_FLAG_PINNED )
- && ( cloth->verts [j].flags & CLOTH_VERT_FLAG_PINNED ) )
- {
- continue;
- }
- }
-
- VECSUB ( temp, verts[i].tx, verts[j].tx );
-
- if ( ( ABS ( temp[0] ) > mindistance ) || ( ABS ( temp[1] ) > mindistance ) || ( ABS ( temp[2] ) > mindistance ) ) continue;
-
- // check for adjacent points (i must be smaller j)
- if ( BLI_edgehash_haskey ( cloth->edgehash, MIN2(i, j), MAX2(i, j) ) )
- {
- continue;
- }
-
- length = Normalize ( temp );
-
- if ( length < mindistance )
- {
- float correction = mindistance - length;
-
- if ( cloth->verts [i].flags & CLOTH_VERT_FLAG_PINNED )
- {
- VecMulf ( temp, -correction );
- VECADD ( verts[j].tx, verts[j].tx, temp );
- }
- else if ( cloth->verts [j].flags & CLOTH_VERT_FLAG_PINNED )
- {
- VecMulf ( temp, correction );
- VECADD ( verts[i].tx, verts[i].tx, temp );
- }
- else
- {
- VecMulf ( temp, -correction*0.5 );
- VECADD ( verts[j].tx, verts[j].tx, temp );
-
- VECSUB ( verts[i].tx, verts[i].tx, temp );
- }
- ret = 1;
- ret2 += ret;
- }
- else
- {
- // check for approximated time collisions
- }
- }
-
- if ( overlap )
- MEM_freeN ( overlap );
-
- }
- }
- ////////////////////////////////////////////////////////////
-
- ////////////////////////////////////////////////////////////
- // SELFCOLLISIONS: update velocities
- ////////////////////////////////////////////////////////////
- if ( ret2 )
- {
- for ( i = 0; i < cloth->numverts; i++ )
- {
- if ( ! ( verts [i].flags & CLOTH_VERT_FLAG_PINNED ) )
- {
- VECSUB ( verts[i].tv, verts[i].tx, verts[i].txold );
- }
- }
- }
- ////////////////////////////////////////////////////////////
+ ret2 += cloth_do_selfcollisions(clmd);
}
+ ////////////////////////////////////////////////////////////
}
while ( ret2 && ( clmd->coll_parms->loop_count>rounds ) );
+
+ if(collobjs)
+ + MEM_freeN(collobjs);
return MIN2 ( ret, 1 );
}
diff --git a/source/blender/blenkernel/intern/implicit.c b/source/blender/blenkernel/intern/implicit.c
index 808984aaa3c..297ac0b1530 100644
--- a/source/blender/blenkernel/intern/implicit.c
+++ b/source/blender/blenkernel/intern/implicit.c
@@ -1588,10 +1588,17 @@ int implicit_solver (Object *ob, float frame, ClothModifierData *clmd, ListBase
VECSUB(verts[i].tv, verts[i].tx, verts[i].txold);
VECCOPY(verts[i].v, verts[i].tv);
}
-
+
// call collision function
- result = cloth_bvh_objcollision(clmd, step + dt, dt);
-
+ // TODO: check if "step" or "step+dt" is correct - dg
+ result = cloth_bvh_objcollision(ob, clmd, step, dt);
+
+ // correct velocity again, just to be sure we had to change it due to adaptive collisions
+ for(i = 0; i < numverts; i++)
+ {
+ VECSUB(verts[i].tv, verts[i].tx, id->X[i]);
+ }
+
// copy corrected positions back to simulation
for(i = 0; i < numverts; i++)
{