Cloth: Collision improvements
This commit includes several performance, stability, and reliability improvements to cloth collisions. Most notably: * The implementation of a new self-collisions system. * Multithreading of collision detection. * Implementation of single sided collisions and normal overrides. * Replacement of the `plNearestPoints` function from Bullet with a dedicated solution. Further, this also includes several bug fixes, and algorithmic improvements. Reviewed By: brecht Differential Revision: http://developer.blender.org/D3712
This commit is contained in:
@@ -124,8 +124,7 @@ 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;
|
||||
clmd->coll_parms->selfepsilon = 0.015;
|
||||
clmd->coll_parms->vgroup_selfcol = 0;
|
||||
|
||||
/* These defaults are copied from softbody.c's
|
||||
@@ -153,44 +152,6 @@ void cloth_init(ClothModifierData *clmd )
|
||||
clmd->point_cache->step = 1;
|
||||
}
|
||||
|
||||
static BVHTree *bvhselftree_build_from_cloth (ClothModifierData *clmd, float epsilon)
|
||||
{
|
||||
unsigned int i;
|
||||
BVHTree *bvhtree;
|
||||
Cloth *cloth;
|
||||
ClothVertex *verts;
|
||||
|
||||
if (!clmd)
|
||||
return NULL;
|
||||
|
||||
cloth = clmd->clothObject;
|
||||
|
||||
if (!cloth)
|
||||
return NULL;
|
||||
|
||||
verts = cloth->verts;
|
||||
|
||||
/* in the moment, return zero if no faces there */
|
||||
if (!cloth->mvert_num)
|
||||
return NULL;
|
||||
|
||||
/* create quadtree with k=26 */
|
||||
bvhtree = BLI_bvhtree_new(cloth->mvert_num, epsilon, 4, 6);
|
||||
|
||||
/* fill tree */
|
||||
for (i = 0; i < cloth->mvert_num; i++, verts++) {
|
||||
const float *co;
|
||||
co = verts->xold;
|
||||
|
||||
BLI_bvhtree_insert(bvhtree, i, co, 1);
|
||||
}
|
||||
|
||||
/* balance tree */
|
||||
BLI_bvhtree_balance(bvhtree);
|
||||
|
||||
return bvhtree;
|
||||
}
|
||||
|
||||
static BVHTree *bvhtree_build_from_cloth (ClothModifierData *clmd, float epsilon)
|
||||
{
|
||||
unsigned int i;
|
||||
@@ -234,14 +195,21 @@ static BVHTree *bvhtree_build_from_cloth (ClothModifierData *clmd, float epsilon
|
||||
return bvhtree;
|
||||
}
|
||||
|
||||
void bvhtree_update_from_cloth(ClothModifierData *clmd, bool moving)
|
||||
void bvhtree_update_from_cloth(ClothModifierData *clmd, bool moving, bool self)
|
||||
{
|
||||
unsigned int i = 0;
|
||||
Cloth *cloth = clmd->clothObject;
|
||||
BVHTree *bvhtree = cloth->bvhtree;
|
||||
BVHTree *bvhtree;
|
||||
ClothVertex *verts = cloth->verts;
|
||||
const MVertTri *vt;
|
||||
|
||||
if (self) {
|
||||
bvhtree = cloth->bvhselftree;
|
||||
}
|
||||
else {
|
||||
bvhtree = cloth->bvhtree;
|
||||
}
|
||||
|
||||
if (!bvhtree)
|
||||
return;
|
||||
|
||||
@@ -253,12 +221,12 @@ void bvhtree_update_from_cloth(ClothModifierData *clmd, bool moving)
|
||||
float co[3][3], co_moving[3][3];
|
||||
bool ret;
|
||||
|
||||
copy_v3_v3(co[0], verts[vt->tri[0]].txold);
|
||||
copy_v3_v3(co[1], verts[vt->tri[1]].txold);
|
||||
copy_v3_v3(co[2], verts[vt->tri[2]].txold);
|
||||
|
||||
/* copy new locations into array */
|
||||
if (moving) {
|
||||
copy_v3_v3(co[0], verts[vt->tri[0]].txold);
|
||||
copy_v3_v3(co[1], verts[vt->tri[1]].txold);
|
||||
copy_v3_v3(co[2], verts[vt->tri[2]].txold);
|
||||
|
||||
/* update moving positions */
|
||||
copy_v3_v3(co_moving[0], verts[vt->tri[0]].tx);
|
||||
copy_v3_v3(co_moving[1], verts[vt->tri[1]].tx);
|
||||
@@ -267,6 +235,10 @@ void bvhtree_update_from_cloth(ClothModifierData *clmd, bool moving)
|
||||
ret = BLI_bvhtree_update_node(bvhtree, i, co[0], co_moving[0], 3);
|
||||
}
|
||||
else {
|
||||
copy_v3_v3(co[0], verts[vt->tri[0]].tx);
|
||||
copy_v3_v3(co[1], verts[vt->tri[1]].tx);
|
||||
copy_v3_v3(co[2], verts[vt->tri[2]].tx);
|
||||
|
||||
ret = BLI_bvhtree_update_node(bvhtree, i, co[0], NULL, 3);
|
||||
}
|
||||
|
||||
@@ -280,47 +252,6 @@ void bvhtree_update_from_cloth(ClothModifierData *clmd, bool moving)
|
||||
}
|
||||
}
|
||||
|
||||
void bvhselftree_update_from_cloth(ClothModifierData *clmd, bool moving)
|
||||
{
|
||||
unsigned int i = 0;
|
||||
Cloth *cloth = clmd->clothObject;
|
||||
BVHTree *bvhtree = cloth->bvhselftree;
|
||||
ClothVertex *verts = cloth->verts;
|
||||
const MVertTri *vt;
|
||||
|
||||
if (!bvhtree)
|
||||
return;
|
||||
|
||||
vt = cloth->tri;
|
||||
|
||||
/* update vertex position in bvh tree */
|
||||
if (verts && vt) {
|
||||
for (i = 0; i < cloth->mvert_num; i++, verts++) {
|
||||
const float *co, *co_moving;
|
||||
bool ret;
|
||||
|
||||
co = verts->txold;
|
||||
|
||||
/* copy new locations into array */
|
||||
if (moving) {
|
||||
/* update moving positions */
|
||||
co_moving = verts->tx;
|
||||
ret = BLI_bvhtree_update_node(bvhtree, i, co, co_moving, 1);
|
||||
}
|
||||
else {
|
||||
ret = BLI_bvhtree_update_node(bvhtree, i, co, NULL, 1);
|
||||
}
|
||||
|
||||
/* check if tree is already full */
|
||||
if (ret == false) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
BLI_bvhtree_update_tree(bvhtree);
|
||||
}
|
||||
}
|
||||
|
||||
void cloth_clear_cache(Object *ob, ClothModifierData *clmd, float framenr)
|
||||
{
|
||||
PTCacheID pid;
|
||||
@@ -357,6 +288,7 @@ static int do_init_cloth(Object *ob, ClothModifierData *clmd, Mesh *result, int
|
||||
BKE_cloth_solver_set_positions(clmd);
|
||||
|
||||
clmd->clothObject->last_frame= MINFRAME-1;
|
||||
clmd->sim_parms->dt = 1.0f / clmd->sim_parms->stepsPerFrame;
|
||||
}
|
||||
|
||||
return 1;
|
||||
@@ -444,9 +376,6 @@ void clothModifier_do(ClothModifierData *clmd, Depsgraph *depsgraph, Scene *scen
|
||||
cache->flag &= ~PTCACHE_REDO_NEEDED;
|
||||
}
|
||||
|
||||
// unused in the moment, calculated separately in implicit.c
|
||||
clmd->sim_parms->dt = clmd->sim_parms->timescale / clmd->sim_parms->stepsPerFrame;
|
||||
|
||||
/* simulation is only active during a specific period */
|
||||
if (framenr < startframe) {
|
||||
BKE_ptcache_invalidate(cache);
|
||||
@@ -795,8 +724,6 @@ static int cloth_from_object(Object *ob, ClothModifierData *clmd, Mesh *mesh, fl
|
||||
ClothVertex *verts = NULL;
|
||||
float (*shapekey_rest)[3] = NULL;
|
||||
float tnull[3] = {0, 0, 0};
|
||||
Cloth *cloth = NULL;
|
||||
float maxdist = 0;
|
||||
|
||||
// If we have a clothObject, free it.
|
||||
if ( clmd->clothObject != NULL ) {
|
||||
@@ -809,8 +736,6 @@ static int cloth_from_object(Object *ob, ClothModifierData *clmd, Mesh *mesh, fl
|
||||
clmd->clothObject = MEM_callocN ( sizeof ( Cloth ), "cloth" );
|
||||
if ( clmd->clothObject ) {
|
||||
clmd->clothObject->old_solver_type = 255;
|
||||
// clmd->clothObject->old_collision_type = 255;
|
||||
cloth = clmd->clothObject;
|
||||
clmd->clothObject->edgeset = NULL;
|
||||
}
|
||||
else if (!clmd->clothObject) {
|
||||
@@ -889,13 +814,8 @@ static int cloth_from_object(Object *ob, ClothModifierData *clmd, Mesh *mesh, fl
|
||||
if (!first)
|
||||
BKE_cloth_solver_set_positions(clmd);
|
||||
|
||||
clmd->clothObject->bvhtree = bvhtree_build_from_cloth ( clmd, MAX2(clmd->coll_parms->epsilon, clmd->coll_parms->distance_repel) );
|
||||
|
||||
for (i = 0; i < mesh->totvert; i++) {
|
||||
maxdist = MAX2(maxdist, clmd->coll_parms->selfepsilon* ( cloth->verts[i].avg_spring_len*2.0f));
|
||||
}
|
||||
|
||||
clmd->clothObject->bvhselftree = bvhselftree_build_from_cloth ( clmd, maxdist );
|
||||
clmd->clothObject->bvhtree = bvhtree_build_from_cloth (clmd, clmd->coll_parms->epsilon);
|
||||
clmd->clothObject->bvhselftree = bvhtree_build_from_cloth(clmd, clmd->coll_parms->selfepsilon);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user