diff options
author | Daniel Genrich <daniel.genrich@gmx.net> | 2008-02-12 14:04:58 +0300 |
---|---|---|
committer | Daniel Genrich <daniel.genrich@gmx.net> | 2008-02-12 14:04:58 +0300 |
commit | e82484b0bb628a533fc1cd43be804c365d54f3f1 (patch) | |
tree | 419a5a24f87b24da2d610c4d29aacd931488ef22 /source/blender | |
parent | 695ea7230ad3c2ef16f742f4cdc4247fa58056e9 (diff) |
Cloth: New: *simple* (OpenMP enabled) Selfcollisions available
Diffstat (limited to 'source/blender')
-rw-r--r-- | source/blender/blenkernel/BKE_cloth.h | 5 | ||||
-rw-r--r-- | source/blender/blenkernel/BKE_collision.h | 8 | ||||
-rw-r--r-- | source/blender/blenkernel/intern/cloth.c | 158 | ||||
-rw-r--r-- | source/blender/blenkernel/intern/collision.c | 130 | ||||
-rw-r--r-- | source/blender/blenkernel/intern/implicit.c | 8 | ||||
-rw-r--r-- | source/blender/blenkernel/intern/kdop.c | 80 | ||||
-rw-r--r-- | source/blender/blenkernel/intern/modifier.c | 2 | ||||
-rw-r--r-- | source/blender/makesdna/DNA_cloth_types.h | 9 | ||||
-rw-r--r-- | source/blender/src/buttons_object.c | 12 |
9 files changed, 248 insertions, 164 deletions
diff --git a/source/blender/blenkernel/BKE_cloth.h b/source/blender/blenkernel/BKE_cloth.h index 19fd0ef4105..8dc84f5945e 100644 --- a/source/blender/blenkernel/BKE_cloth.h +++ b/source/blender/blenkernel/BKE_cloth.h @@ -94,10 +94,11 @@ typedef struct ClothVertex float goal; /* goal, from SB */ float impulse[3]; /* used in collision.c */ unsigned int impulse_count; /* same as above */ - float avg_spring_len; /* average length of connected springs, UNUSED ATM */ + float avg_spring_len; /* average length of connected springs */ float struct_stiff; float bend_stiff; float shear_stiff; + int spring_count; /* how many springs attached? */ } ClothVertex; @@ -153,7 +154,7 @@ typedef enum typedef enum { CLOTH_COLLSETTINGS_FLAG_ENABLED = ( 1 << 1 ), /* enables cloth - object collisions */ - CLOTH_COLLSETTINGS_FLAG_SELF = ( 1 << 2 ), /* unused */ + CLOTH_COLLSETTINGS_FLAG_SELF = ( 1 << 2 ), /* enables selfcollisions */ } CLOTH_COLLISIONSETTINGS_FLAGS; /* Spring types as defined in the paper.*/ diff --git a/source/blender/blenkernel/BKE_collision.h b/source/blender/blenkernel/BKE_collision.h index 05c8d390ea6..463254b8e4f 100644 --- a/source/blender/blenkernel/BKE_collision.h +++ b/source/blender/blenkernel/BKE_collision.h @@ -73,6 +73,8 @@ typedef struct CollisionTree int count_nodes; // how many nodes are used int traversed; // how many nodes already traversed until this level? int isleaf; + float alpha; /* for selfcollision */ + float normal[3]; /* for selfcollision */ } CollisionTree; @@ -103,11 +105,11 @@ BVH; typedef void ( *CM_COLLISION_RESPONSE ) ( ModifierData *md1, ModifierData *md2, CollisionTree *tree1, CollisionTree *tree2 ); // needed for collision.c -int bvh_traverse ( ModifierData * md1, ModifierData * md2, CollisionTree * tree1, CollisionTree * tree2, float step, CM_COLLISION_RESPONSE collision_response); -int bvh_traverse_mt ( ModifierData * md1, ModifierData * md2, CollisionTree * tree1, CollisionTree * tree2, float step, CM_COLLISION_RESPONSE collision_response); -//////////////////////////////////////////////// +int bvh_traverse ( ModifierData * md1, ModifierData * md2, CollisionTree * tree1, CollisionTree * tree2, float step, CM_COLLISION_RESPONSE collision_response, int selfcollision); + //////////////////////////////////////// + //////////////////////////////////////// // used for collisions in kdop.c and also collision.c //////////////////////////////////////// diff --git a/source/blender/blenkernel/intern/cloth.c b/source/blender/blenkernel/intern/cloth.c index e1e80a62d4c..ecd478be8fd 100644 --- a/source/blender/blenkernel/intern/cloth.c +++ b/source/blender/blenkernel/intern/cloth.c @@ -165,6 +165,7 @@ void cloth_init ( ClothModifierData *clmd ) clmd->sim_parms->editedframe = 0; clmd->sim_parms->autoprotect = 25; clmd->sim_parms->firstcachedframe = -1.0; + clmd->sim_parms->avg_spring_len = 0.0; clmd->coll_parms->self_friction = 5.0; clmd->coll_parms->friction = 5.0; @@ -172,6 +173,8 @@ void cloth_init ( ClothModifierData *clmd ) clmd->coll_parms->epsilon = 0.015f; clmd->coll_parms->flags = CLOTH_COLLSETTINGS_FLAG_ENABLED; clmd->coll_parms->collision_list = NULL; + clmd->coll_parms->self_loop_count = 1.0; + clmd->coll_parms->selfepsilon = 0.75; /* These defaults are copied from softbody.c's * softbody_calc_forces() function. @@ -269,130 +272,6 @@ void bvh_update_from_cloth(ClothModifierData *clmd, int moving) bvh_update(bvh, moving); } -// unused in the moment, cloth needs quads from mesh -DerivedMesh *CDDM_convert_to_triangle ( DerivedMesh *dm ) -{ - DerivedMesh *result = NULL; - int i; - int numverts = dm->getNumVerts ( dm ); - int numedges = dm->getNumEdges ( dm ); - int numfaces = dm->getNumFaces ( dm ); - - MVert *mvert = CDDM_get_verts ( dm ); - MEdge *medge = CDDM_get_edges ( dm ); - MFace *mface = CDDM_get_faces ( dm ); - - MVert *mvert2; - MFace *mface2; - unsigned int numtris=0; - unsigned int numquads=0; - int a = 0; - int random = 0; - int firsttime = 0; - float vec1[3], vec2[3], vec3[3], vec4[3], vec5[3]; - float mag1=0, mag2=0; - - for ( i = 0; i < numfaces; i++ ) - { - if ( mface[i].v4 ) - numquads++; - else - numtris++; - } - - result = CDDM_from_template ( dm, numverts, 0, numtris + 2*numquads ); - - if ( !result ) - return NULL; - - // do verts - mvert2 = CDDM_get_verts ( result ); - for ( a=0; a<numverts; a++ ) - { - MVert *inMV; - MVert *mv = &mvert2[a]; - - inMV = &mvert[a]; - - DM_copy_vert_data ( dm, result, a, a, 1 ); - *mv = *inMV; - } - - - // do faces - mface2 = CDDM_get_faces ( result ); - for ( a=0, i=0; a<numfaces; a++ ) - { - MFace *mf = &mface2[i]; - MFace *inMF; - inMF = &mface[a]; - - /* - DM_copy_face_data(dm, result, a, i, 1); - - *mf = *inMF; - */ - - if ( mface[a].v4 && random==1 ) - { - mf->v1 = mface[a].v2; - mf->v2 = mface[a].v3; - mf->v3 = mface[a].v4; - } - else - { - mf->v1 = mface[a].v1; - mf->v2 = mface[a].v2; - mf->v3 = mface[a].v3; - } - - mf->v4 = 0; - mf->flag |= ME_SMOOTH; - - test_index_face ( mf, NULL, 0, 3 ); - - if ( mface[a].v4 ) - { - MFace *mf2; - - i++; - - mf2 = &mface2[i]; - /* - DM_copy_face_data(dm, result, a, i, 1); - - *mf2 = *inMF; - */ - - if ( random==1 ) - { - mf2->v1 = mface[a].v1; - mf2->v2 = mface[a].v2; - mf2->v3 = mface[a].v4; - } - else - { - mf2->v1 = mface[a].v4; - mf2->v2 = mface[a].v1; - mf2->v3 = mface[a].v3; - } - mf2->v4 = 0; - mf2->flag |= ME_SMOOTH; - - test_index_face ( mf2, NULL, 0, 3 ); - } - - i++; - } - - CDDM_calc_edges ( result ); - CDDM_calc_normals ( result ); - - return result; - -} - - DerivedMesh *CDDM_create_tearing ( ClothModifierData *clmd, DerivedMesh *dm ) { DerivedMesh *result = NULL; @@ -922,6 +801,11 @@ void cloth_free_modifier ( Object *ob, ClothModifierData *clmd ) // we save our faces for collision objects if ( cloth->mfaces ) MEM_freeN ( cloth->mfaces ); + + if(cloth->edgehash) + BLI_edgehash_free ( cloth->edgehash, NULL ); + + /* if(clmd->clothObject->facemarks) MEM_freeN(clmd->clothObject->facemarks); @@ -988,6 +872,11 @@ void cloth_free_modifier_extern ( ClothModifierData *clmd ) // we save our faces for collision objects if ( cloth->mfaces ) MEM_freeN ( cloth->mfaces ); + + if(cloth->edgehash) + BLI_edgehash_free ( cloth->edgehash, NULL ); + + /* if(clmd->clothObject->facemarks) MEM_freeN(clmd->clothObject->facemarks); @@ -1136,6 +1025,7 @@ static int cloth_from_object(Object *ob, ClothModifierData *clmd, DerivedMesh *d clmd->clothObject->old_solver_type = 255; // clmd->clothObject->old_collision_type = 255; cloth = clmd->clothObject; + clmd->clothObject->edgehash = NULL; } else if ( !clmd->clothObject ) { @@ -1236,8 +1126,7 @@ static void cloth_from_mesh ( Object *ob, ClothModifierData *clmd, DerivedMesh * MFace *mface = CDDM_get_faces(dm); unsigned int i = 0; - /* Allocate our vertices. - */ + /* Allocate our vertices. */ clmd->clothObject->numverts = numverts; clmd->clothObject->verts = MEM_callocN ( sizeof ( ClothVertex ) * clmd->clothObject->numverts, "clothVertex" ); if ( clmd->clothObject->verts == NULL ) @@ -1349,7 +1238,11 @@ int cloth_build_springs ( ClothModifierData *clmd, DerivedMesh *dm ) spring->kl = medge[i].v2; VECSUB ( temp, cloth->verts[spring->kl].x, cloth->verts[spring->ij].x ); spring->restlen = sqrt ( INPR ( temp, temp ) ); - clmd->coll_parms->avg_spring_len += spring->restlen; + clmd->sim_parms->avg_spring_len += spring->restlen; + cloth->verts[spring->ij].avg_spring_len += spring->restlen; + cloth->verts[spring->kl].avg_spring_len += spring->restlen; + cloth->verts[spring->ij].spring_count++; + cloth->verts[spring->kl].spring_count++; spring->type = CLOTH_SPRING_TYPE_STRUCTURAL; spring->flags = 0; spring->stiffness = (cloth->verts[spring->kl].struct_stiff + cloth->verts[spring->ij].struct_stiff) / 2.0; @@ -1363,7 +1256,12 @@ int cloth_build_springs ( ClothModifierData *clmd, DerivedMesh *dm ) } } - clmd->coll_parms->avg_spring_len /= struct_springs; + clmd->sim_parms->avg_spring_len /= struct_springs; + + for(i = 0; i < numverts; i++) + { + cloth->verts[i].avg_spring_len = cloth->verts[i].avg_spring_len * 0.49 / ((float)cloth->verts[i].spring_count); + } // shear springs for ( i = 0; i < numfaces; i++ ) @@ -1452,10 +1350,10 @@ int cloth_build_springs ( ClothModifierData *clmd, DerivedMesh *dm ) if ( edgelist ) MEM_freeN ( edgelist ); - BLI_edgehash_free ( edgehash, NULL ); + cloth->edgehash = edgehash; if(G.rt>0) - printf("avg_len: %f\n",clmd->coll_parms->avg_spring_len); + printf("avg_len: %f\n",clmd->sim_parms->avg_spring_len); return 1; diff --git a/source/blender/blenkernel/intern/collision.c b/source/blender/blenkernel/intern/collision.c index da9312b01ab..9ec99548bb1 100644 --- a/source/blender/blenkernel/intern/collision.c +++ b/source/blender/blenkernel/intern/collision.c @@ -948,6 +948,29 @@ void cloth_collision_moving(ClothModifierData *clmd, ClothModifierData *coll_clm cloth_collision_moving_tris(coll_clmd, clmd, tree2, tree1); } +void cloth_collision_self_static(ModifierData *md1, ModifierData *md2, CollisionTree *tree1, CollisionTree *tree2) +{ + ClothModifierData *clmd = (ClothModifierData *)md1; + CollisionModifierData *collmd = (CollisionModifierData *)md2; + CollPair *collpair = NULL; + Cloth *cloth1=NULL; + MFace *face1=NULL, *face2=NULL; + ClothVertex *verts1=NULL; + double distance = 0; + float epsilon = clmd->coll_parms->epsilon; + unsigned int i = 0; + + +} + +/* aye this belongs to arith.c */ +static void Vec3PlusStVec(float *v, float s, float *v1) +{ + v[0] += s*v1[0]; + v[1] += s*v1[1]; + v[2] += s*v1[2]; +} + // cloth - object collisions int cloth_bvh_objcollision(ClothModifierData * clmd, float step, float dt) { @@ -956,12 +979,13 @@ int cloth_bvh_objcollision(ClothModifierData * clmd, float step, float dt) Cloth *cloth=NULL; Object *coll_ob=NULL; BVH *cloth_bvh=NULL; - unsigned int i=0, j = 0, numfaces = 0, numverts = 0; + long i=0, j = 0, numfaces = 0, numverts = 0; unsigned int result = 0, ic = 0, rounds = 0; // result counts applied collisions; ic is for debug output; ClothVertex *verts = NULL; float tnull[3] = {0,0,0}; int ret = 0; ClothModifierData *tclmd; + int collisions = 0, count = 0; if ((clmd->sim_parms->flags & CLOTH_SIMSETTINGS_FLAG_COLLOBJ) || !(((Cloth *)clmd->clothObject)->tree)) { @@ -1006,7 +1030,7 @@ int cloth_bvh_objcollision(ClothModifierData * clmd, float step, float dt) collision_move_object(collmd, step + dt, step); - bvh_traverse((ModifierData *)clmd, (ModifierData *)collmd, cloth_bvh->root, coll_bvh->root, step, cloth_collision_static); + bvh_traverse((ModifierData *)clmd, (ModifierData *)collmd, cloth_bvh->root, coll_bvh->root, step, cloth_collision_static, 0); } else printf ("cloth_bvh_objcollision: found a collision object with clothObject or collData NULL.\n"); @@ -1068,7 +1092,7 @@ int cloth_bvh_objcollision(ClothModifierData * clmd, float step, float dt) { if(clmd->sim_parms->flags & CLOTH_SIMSETTINGS_FLAG_GOAL) { - if(verts [i].goal >= SOFTGOALSNAP) + if(verts [i].flags & CLOTH_VERT_FLAG_PINNED) { continue; } @@ -1077,7 +1101,103 @@ int cloth_bvh_objcollision(ClothModifierData * clmd, float step, float dt) VECADD(verts[i].tx, verts[i].txold, verts[i].tv); } //////////////////////////////////////////////////////////// - + + + //////////////////////////////////////////////////////////// + // Test on *simple* selfcollisions + //////////////////////////////////////////////////////////// + if (clmd->coll_parms->flags & CLOTH_COLLSETTINGS_FLAG_SELF) + { + collisions = 1; + verts = cloth->verts; // needed for openMP + + for(count = 0; count < clmd->coll_parms->self_loop_count; count++) + { + if(collisions) + { + collisions = 0; + #pragma omp parallel for private(i,j, collisions) shared(verts, ret) + for(i = 0; i < cloth->numverts; i++) + { + for(j = i + 1; j < cloth->numverts; j++) + { + float temp[3]; + float length = 0; + float 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 + if(BLI_edgehash_haskey (cloth->edgehash, 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); + } + + collisions = 1; + + if(!ret) + { + #pragma omp critical + { + ret = 1; + } + } + } + } + } + } + } + //////////////////////////////////////////////////////////// + + //////////////////////////////////////////////////////////// + // SELFCOLLISIONS: update velocities + //////////////////////////////////////////////////////////// + if(ret) + { + for(i = 0; i < cloth->numverts; i++) + { + if(!(cloth->verts [i].flags & CLOTH_VERT_FLAG_PINNED)) + VECSUB(verts[i].tv, verts[i].tx, verts[i].txold); + } + } + //////////////////////////////////////////////////////////// + } + //////////////////////////////////////////////////////////// // moving collisions // @@ -1132,7 +1252,7 @@ int cloth_bvh_objcollision(ClothModifierData * clmd, float step, float dt) { BVH *coll_bvh = coll_clmd->clothObject->tree; - bvh_traverse(clmd, coll_clmd, cloth_bvh->root, coll_bvh->root, step, cloth_collision_moving); + bvh_traverse(clmd, coll_clmd, cloth_bvh->root, coll_bvh->root, step, cloth_collision_moving, 0); } else printf ("cloth_bvh_objcollision: found a collision object with clothObject or collData NULL.\n"); diff --git a/source/blender/blenkernel/intern/implicit.c b/source/blender/blenkernel/intern/implicit.c index 7c2721d9feb..bde56bb5fe1 100644 --- a/source/blender/blenkernel/intern/implicit.c +++ b/source/blender/blenkernel/intern/implicit.c @@ -1289,9 +1289,7 @@ DO_INLINE void cloth_calc_spring_force(ClothModifierData *clmd, ClothSpring *s, scaling = k + s->stiffness * ABS(clmd->sim_parms->max_struct-k); - k = scaling / (clmd->coll_parms->avg_spring_len + FLT_EPSILON); - if(G.rt>3) - printf("struct scaling: %f\n", k); + k = scaling / (clmd->sim_parms->avg_spring_len + FLT_EPSILON); // TODO: verify, half verified (couldn't see error) mul_fvector_S(stretch_force, dir, k*(length-L)); @@ -1333,7 +1331,7 @@ DO_INLINE void cloth_calc_spring_force(ClothModifierData *clmd, ClothSpring *s, mul_fvector_S(dir, extent, 0.0f); k = clmd->sim_parms->goalspring; - k /= (clmd->coll_parms->avg_spring_len + FLT_EPSILON); + k /= (clmd->sim_parms->avg_spring_len + FLT_EPSILON); k *= verts [s->ij].goal; VECADDS(s->f, s->f, extent, k); @@ -1353,7 +1351,7 @@ DO_INLINE void cloth_calc_spring_force(ClothModifierData *clmd, ClothSpring *s, k = clmd->sim_parms->bending; scaling = k + s->stiffness * ABS(clmd->sim_parms->max_bend-k); - cb = k = scaling / (20.0*(clmd->coll_parms->avg_spring_len + FLT_EPSILON)); + cb = k = scaling / (20.0*(clmd->sim_parms->avg_spring_len + FLT_EPSILON)); if(G.rt>3) printf("bend scaling: %f\n", k); diff --git a/source/blender/blenkernel/intern/kdop.c b/source/blender/blenkernel/intern/kdop.c index 817844dce6f..06525449bf4 100644 --- a/source/blender/blenkernel/intern/kdop.c +++ b/source/blender/blenkernel/intern/kdop.c @@ -71,6 +71,8 @@ #include "BIF_space.h" #include "mydevice.h" +#include "BKE_utildefines.h" + #ifdef _OPENMP #include <omp.h> @@ -387,12 +389,13 @@ DO_INLINE void bvh_calc_DOP_hull_from_faces(BVH * bvh, CollisionTree **tri, int } } -DO_INLINE void bvh_calc_DOP_hull_static(BVH * bvh, CollisionTree **tri, int numfaces, float *bv) +DO_INLINE void bvh_calc_DOP_hull_static(BVH * bvh, CollisionTree **tri, int numfaces, float *bv, CollisionTree *tree) { MFace *tempMFace = bvh->mfaces; float *tempBV = bv; float newminmax; int i, j, k; + for (j = 0; j < numfaces; j++) { tempMFace = bvh->mfaces + (tri [j])->tri_index; @@ -422,15 +425,31 @@ DO_INLINE void bvh_calc_DOP_hull_static(BVH * bvh, CollisionTree **tri, int numf tempBV[(2 * i) + 1] = newminmax; } } + + /* calculate normal of this face */ + /* (code copied from cdderivedmesh.c) */ + if(tempMFace->v4) + CalcNormFloat4(bvh->current_xold[tempMFace->v1].co, bvh->current_xold[tempMFace->v2].co, + bvh->current_xold[tempMFace->v3].co, bvh->current_xold[tempMFace->v4].co, tree->normal); + else + CalcNormFloat(bvh->current_xold[tempMFace->v1].co, bvh->current_xold[tempMFace->v2].co, + bvh->current_xold[tempMFace->v3].co, tree->normal); + + tree->alpha = 0; + + } } -DO_INLINE void bvh_calc_DOP_hull_moving(BVH * bvh, CollisionTree **tri, int numfaces, float *bv) +DO_INLINE void bvh_calc_DOP_hull_moving(BVH * bvh, CollisionTree **tri, int numfaces, float *bv, CollisionTree *tree) { MFace *tempMFace = bvh->mfaces; float *tempBV = bv; float newminmax; int i, j, k; + + /* TODO: calculate normals */ + for (j = 0; j < numfaces; j++) { tempMFace = bvh->mfaces + (tri [j])->tri_index; @@ -614,7 +633,7 @@ void bvh_build (BVH *bvh) tree->nodes[0] = tree->nodes[1] = tree->nodes[2] = tree->nodes[3] = NULL; - bvh_calc_DOP_hull_static(bvh, &face_list[i], 1, tree->bv); + bvh_calc_DOP_hull_static(bvh, &face_list[i], 1, tree->bv, tree); // inflate the bv with some epsilon for (j = KDOP_START; j < KDOP_END; j++) @@ -659,6 +678,19 @@ DO_INLINE int bvh_overlap(float *bv1, float *bv2) return 1; } +// bvh_overlap_self - is it possbile for 2 bv's to selfcollide ? +DO_INLINE int bvh_overlap_self(CollisionTree * tree1, CollisionTree * tree2) +{ + // printf("overlap: %f, q: %f\n", (saacos(INPR(tree1->normal, tree2->normal)) / 2.0)+MAX2(tree1->alpha, tree2->alpha), saacos(INPR(tree1->normal, tree2->normal))); + + if((saacos(INPR(tree1->normal, tree2->normal)) / 2.0)+MAX2(tree1->alpha, tree2->alpha) > M_PI) + { + return 1; + } + else + return 0; +} + /** * bvh_traverse - traverse two bvh trees looking for potential collisions. * @@ -666,9 +698,9 @@ DO_INLINE int bvh_overlap(float *bv1, float *bv2) * every other triangle that doesn't require any realloc, but uses * much memory */ -int bvh_traverse ( ModifierData * md1, ModifierData * md2, CollisionTree * tree1, CollisionTree * tree2, float step, CM_COLLISION_RESPONSE collision_response) +int bvh_traverse ( ModifierData * md1, ModifierData * md2, CollisionTree * tree1, CollisionTree * tree2, float step, CM_COLLISION_RESPONSE collision_response, int selfcollision) { - int i = 0, ret=0; + int i = 0, ret=0, overlap = 0; /* // Shouldn't be possible @@ -678,7 +710,13 @@ int bvh_traverse ( ModifierData * md1, ModifierData * md2, CollisionTree * tree1 return 0; } */ - if (bvh_overlap(tree1->bv, tree2->bv)) + + if(selfcollision) + overlap = bvh_overlap_self(tree1, tree2); + else + overlap = bvh_overlap(tree1->bv, tree2->bv); + + if (overlap) { // Check if this node in the first tree is a leaf if (tree1->isleaf) @@ -698,7 +736,7 @@ int bvh_traverse ( ModifierData * md1, ModifierData * md2, CollisionTree * tree1 for (i = 0; i < 4; i++) { // Only traverse nodes that exist. - if (tree2->nodes[i] && bvh_traverse (md1, md2, tree1, tree2->nodes[i], step, collision_response)) + if (tree2->nodes[i] && bvh_traverse (md1, md2, tree1, tree2->nodes[i], step, collision_response, selfcollision)) ret = 1; } } @@ -709,7 +747,7 @@ int bvh_traverse ( ModifierData * md1, ModifierData * md2, CollisionTree * tree1 for (i = 0; i < 4; i++) { // Only traverse nodes that exist. - if (tree1->nodes [i] && bvh_traverse (md1, md2, tree1->nodes[i], tree2, step, collision_response)) + if (tree1->nodes [i] && bvh_traverse (md1, md2, tree1->nodes[i], tree2, step, collision_response, selfcollision)) ret = 1; } } @@ -717,12 +755,13 @@ int bvh_traverse ( ModifierData * md1, ModifierData * md2, CollisionTree * tree1 return ret; } - // bottom up update of bvh tree: // join the 4 children here -void bvh_join(CollisionTree * tree) +void bvh_join(CollisionTree *tree) { int i = 0, j = 0; + float max = 0; + if (!tree) return; @@ -743,10 +782,27 @@ void bvh_join(CollisionTree * tree) tree->bv[(2 * j) + 1] = tree->nodes[i]->bv[(2 * j) + 1]; } } + + /* for selfcollisions */ + if(!i) + { + tree->alpha = tree->nodes[i]->alpha; + VECCOPY(tree->normal, tree->nodes[i]->normal); + } + else + { + tree->alpha += saacos(INPR(tree->normal, tree->nodes[i]->normal)) / 2.0; + VECADD(tree->normal, tree->normal, tree->nodes[i]->normal); + VecMulf(tree->normal, 0.5); + max = MAX2(max, tree->nodes[i]->alpha); + } + } else break; } + + tree->alpha += max; } // update static bvh @@ -765,9 +821,9 @@ void bvh_update(BVH * bvh, int moving) leaf->parent->traversed = 0; } if(!moving) - bvh_calc_DOP_hull_static(bvh, &leaf, 1, leaf->bv); + bvh_calc_DOP_hull_static(bvh, &leaf, 1, leaf->bv, leaf); else - bvh_calc_DOP_hull_moving(bvh, &leaf, 1, leaf->bv); + bvh_calc_DOP_hull_moving(bvh, &leaf, 1, leaf->bv, leaf); // inflate the bv with some epsilon for (j = KDOP_START; j < KDOP_END; j++) diff --git a/source/blender/blenkernel/intern/modifier.c b/source/blender/blenkernel/intern/modifier.c index 049146fb05f..ead7f4f2c9e 100644 --- a/source/blender/blenkernel/intern/modifier.c +++ b/source/blender/blenkernel/intern/modifier.c @@ -4960,8 +4960,6 @@ static void clothModifier_initData(ModifierData *md) return; cloth_init (clmd); - if(G.rt >0) - printf("clothModifier_initData\n"); } static DerivedMesh *clothModifier_applyModifier(ModifierData *md, Object *ob, diff --git a/source/blender/makesdna/DNA_cloth_types.h b/source/blender/makesdna/DNA_cloth_types.h index 2b18142258c..40abe012a5a 100644 --- a/source/blender/makesdna/DNA_cloth_types.h +++ b/source/blender/makesdna/DNA_cloth_types.h @@ -82,21 +82,21 @@ typedef struct SimulationSettings float max_struct; /* max structural scaling value, min is "structural" */ float max_shear; /* max shear scaling value, UNUSED */ int firstcachedframe; - int pad; + float avg_spring_len; /* used for normalized springs */ } SimulationSettings; typedef struct CollisionSettings { - float epsilon; /* The radius of a particle in the cloth. */ + float epsilon; /* min distance for collisions. */ float self_friction; /* Fiction/damping with self contact. */ float friction; /* Friction/damping applied on contact with other object.*/ - short collision_type; /* which collision system is used. */ + short self_loop_count; /* How many iterations for the selfcollision loop */ short loop_count; /* How many iterations for the collision loop. */ struct LinkNode *collision_list; /* e.g. pointer to temp memory for collisions */ int flags; /* collision flags defined in BKE_cloth.h */ - float avg_spring_len; /* for selfcollision */ + float selfepsilon; /* for selfcollision */ } CollisionSettings; @@ -125,6 +125,7 @@ typedef struct Cloth struct MFace *mfaces; struct Implicit_Data *implicit; /* our implicit solver connects to this pointer */ struct Implicit_Data *implicitEM; /* our implicit solver connects to this pointer */ + struct EdgeHash *edgehash; /* used for selfcollisions */ } Cloth; diff --git a/source/blender/src/buttons_object.c b/source/blender/src/buttons_object.c index 8ac960e92cd..62f7300fc98 100644 --- a/source/blender/src/buttons_object.c +++ b/source/blender/src/buttons_object.c @@ -5322,8 +5322,18 @@ static void object_panel_cloth_II(Object *ob) if (clmd->coll_parms->flags & CLOTH_COLLSETTINGS_FLAG_ENABLED) { uiDefButF(block, NUM, REDRAWBUTSOBJECT, "Min Distance:", 160,60,150,20, &clmd->coll_parms->epsilon, 0.001f, 1.0, 0.01f, 0, "Minimum distance between collision objects before collision response takes in, can be changed for each frame"); - uiDefButS(block, NUM, REDRAWBUTSOBJECT, "Collision Quality:", 10,40,150,20, &clmd->coll_parms->loop_count, 1.0, 100.0, 1.0, 0, "How many collision iterations should be done. (higher = better = slower), can be changed for each frame"); + uiDefButS(block, NUM, REDRAWBUTSOBJECT, "Collision Quality:", 10,40,150,20, &clmd->coll_parms->loop_count, 1.0, 20.0, 1.0, 0, "How many collision iterations should be done. (higher = better = slower), can be changed for each frame"); uiDefButF(block, NUM, REDRAWBUTSOBJECT, "Friction:", 160,40,150,20, &clmd->coll_parms->friction, 0.0, 10.0, 1.0, 0, "Friction force if a collision happened (high=slower movement when collided)"); + + uiDefButBitI(block, TOG, CLOTH_COLLSETTINGS_FLAG_SELF, B_CLOTH_RENEW, "Enable selfcollisions", 10,20,150,20, &clmd->coll_parms->flags, 0, 0, 0, 0, "Enable selfcollisions with this object"); + if (clmd->coll_parms->flags & CLOTH_COLLSETTINGS_FLAG_SELF) + { + uiDefButF(block, NUM, REDRAWBUTSOBJECT, "Min Distance:", 160,20,150,20, &clmd->coll_parms->selfepsilon, 0.5f, 1.0, 0.01f, 0, "0.5 means no distance at all, 1.0 is maximum distance"); + // self_loop_count + uiDefButS(block, NUM, REDRAWBUTSOBJECT, "Selfcoll Quality:", 10,0,150,20, &clmd->coll_parms->self_loop_count, 1.0, 10.0, 1.0, 0, "How many selfcollision iterations should be done. (higher = better = slower), can be changed for each frame"); + } + else + uiDefBut(block, LABEL, 0, "",160,20,150,20, NULL, 0.0, 0, 0, 0, ""); } else uiDefBut(block, LABEL, 0, "",160,60,150,20, NULL, 0.0, 0, 0, 0, ""); |