Commit: ceddd2bcd913a94e5200448f4316962d2b86cf33
Author: Luca Rood
Date:   Wed Sep 19 15:40:38 2018 +0200
Branches: cloth-improvements
https://developer.blender.org/rBceddd2bcd913a94e5200448f4316962d2b86cf33

Fix collision multithreading inconsistency

Multithreading makes collisions be detected in different orders, causing
the clustering step of collision resolution to generate possibly
slightly different results on each run. This commit makes collision
order consistent.

===================================================================

M       source/blender/blenkernel/BKE_collision.h
M       source/blender/blenkernel/intern/collision.c

===================================================================

diff --git a/source/blender/blenkernel/BKE_collision.h 
b/source/blender/blenkernel/BKE_collision.h
index 654f3a8db1a..92ebb254bd1 100644
--- a/source/blender/blenkernel/BKE_collision.h
+++ b/source/blender/blenkernel/BKE_collision.h
@@ -62,6 +62,7 @@ typedef enum {
        COLLISION_USE_COLLFACE =    (1 << 2),
        COLLISION_IS_EDGES =        (1 << 3),
 #endif
+       COLLISION_INACTIVE =        (1 << 4),
 } COLLISION_FLAGS;
 
 
diff --git a/source/blender/blenkernel/intern/collision.c 
b/source/blender/blenkernel/intern/collision.c
index 3a4f9ec872c..b85fbff4522 100644
--- a/source/blender/blenkernel/intern/collision.c
+++ b/source/blender/blenkernel/intern/collision.c
@@ -72,16 +72,16 @@ typedef struct ColDetectData {
        CollisionModifierData *collmd;
        BVHTreeOverlap *overlap;
        CollPair *collisions;
-       unsigned int *coll_count;
        bool culling;
        bool use_normal;
+       bool collided;
 } ColDetectData;
 
 typedef struct SelfColDetectData {
        ClothModifierData *clmd;
        BVHTreeOverlap *overlap;
        CollPair *collisions;
-       unsigned int *coll_count;
+       bool collided;
 } SelfColDetectData;
 
 /***********************************
@@ -681,7 +681,7 @@ static int 
cloth_collision_response_static(ClothModifierData *clmd, CollisionMod
                zero_v3(i3);
 
                /* only handle static collisions here */
-               if (collpair->flag & COLLISION_IN_FUTURE) {
+               if (collpair->flag & (COLLISION_IN_FUTURE | 
COLLISION_INACTIVE)) {
                        continue;
                }
 
@@ -857,7 +857,7 @@ static int 
cloth_selfcollision_response_static(ClothModifierData *clmd, CollPair
                zero_v3(i3);
 
                /* only handle static collisions here */
-               if (collpair->flag & COLLISION_IN_FUTURE) {
+               if (collpair->flag & (COLLISION_IN_FUTURE | 
COLLISION_INACTIVE)) {
                        continue;
                }
 
@@ -1030,7 +1030,6 @@ static void cloth_collision(
        ClothModifierData *clmd = data->clmd;
        CollisionModifierData *collmd = data->collmd;
        CollPair *collpair = data->collisions;
-       unsigned int *coll_count = data->coll_count;
        const MVertTri *tri_a, *tri_b;
        ClothVertex *verts1 = clmd->clothObject->verts;
        float distance = 0.0f;
@@ -1047,28 +1046,29 @@ static void cloth_collision(
                                                                           
data->culling, data->use_normal, pa, pb, vect);
 
        if ((distance <= (epsilon1 + epsilon2 + ALMOST_ZERO)) && 
(len_squared_v3(vect) > FLT_EPSILON)) {
-               int ind;
-
-               ind = atomic_add_and_fetch_u(coll_count, 1) - 1;
-
                /* fill face_a */
-               collpair[ind].ap1 = tri_a->tri[0];
-               collpair[ind].ap2 = tri_a->tri[1];
-               collpair[ind].ap3 = tri_a->tri[2];
+               collpair[index].ap1 = tri_a->tri[0];
+               collpair[index].ap2 = tri_a->tri[1];
+               collpair[index].ap3 = tri_a->tri[2];
 
                /* fill face_b */
-               collpair[ind].bp1 = tri_b->tri[0];
-               collpair[ind].bp2 = tri_b->tri[1];
-               collpair[ind].bp3 = tri_b->tri[2];
+               collpair[index].bp1 = tri_b->tri[0];
+               collpair[index].bp2 = tri_b->tri[1];
+               collpair[index].bp3 = tri_b->tri[2];
 
-               copy_v3_v3(collpair[ind].pa, pa);
-               copy_v3_v3(collpair[ind].pb, pb);
-               copy_v3_v3(collpair[ind].vector, vect);
+               copy_v3_v3(collpair[index].pa, pa);
+               copy_v3_v3(collpair[index].pb, pb);
+               copy_v3_v3(collpair[index].vector, vect);
 
-               normalize_v3_v3(collpair[ind].normal, collpair[ind].vector);
+               normalize_v3_v3(collpair[index].normal, collpair[index].vector);
 
-               collpair[ind].distance = distance;
-               collpair[ind].flag = 0;
+               collpair[index].distance = distance;
+               collpair[index].flag = 0;
+
+               data->collided = true;
+       }
+       else {
+               collpair[index].flag = COLLISION_INACTIVE;
        }
 }
 
@@ -1081,7 +1081,6 @@ static void cloth_selfcollision(
 
        ClothModifierData *clmd = data->clmd;
        CollPair *collpair = data->collisions;
-       unsigned int *coll_count = data->coll_count;
        const MVertTri *tri_a, *tri_b;
        ClothVertex *verts1 = clmd->clothObject->verts;
        float distance = 0.0f;
@@ -1112,28 +1111,29 @@ static void cloth_selfcollision(
 
        // distance -1 means no collision result
        if ((distance <= (epsilon * 2.0f + ALMOST_ZERO)) && 
(len_squared_v3(vect) > FLT_EPSILON)) {
-               int ind;
-
-               ind = atomic_add_and_fetch_u(coll_count, 1) - 1;
-
                /* fill face_a */
-               collpair[ind].ap1 = tri_a->tri[0];
-               collpair[ind].ap2 = tri_a->tri[1];
-               collpair[ind].ap3 = tri_a->tri[2];
+               collpair[index].ap1 = tri_a->tri[0];
+               collpair[index].ap2 = tri_a->tri[1];
+               collpair[index].ap3 = tri_a->tri[2];
 
                /* fill face_b */
-               collpair[ind].bp1 = tri_b->tri[0];
-               collpair[ind].bp2 = tri_b->tri[1];
-               collpair[ind].bp3 = tri_b->tri[2];
+               collpair[index].bp1 = tri_b->tri[0];
+               collpair[index].bp2 = tri_b->tri[1];
+               collpair[index].bp3 = tri_b->tri[2];
+
+               copy_v3_v3(collpair[index].pa, pa);
+               copy_v3_v3(collpair[index].pb, pb);
+               copy_v3_v3(collpair[index].vector, vect);
 
-               copy_v3_v3(collpair[ind].pa, pa);
-               copy_v3_v3(collpair[ind].pb, pb);
-               copy_v3_v3(collpair[ind].vector, vect);
+               normalize_v3_v3(collpair[index].normal, collpair[index].vector);
 
-               normalize_v3_v3(collpair[ind].normal, collpair[ind].vector);
+               collpair[index].distance = distance;
+               collpair[index].flag = 0;
 
-               collpair[ind].distance = distance;
-               collpair[ind].flag = 0;
+               data->collided = true;
+       }
+       else {
+               collpair[index].flag = COLLISION_INACTIVE;
        }
 }
 
@@ -1287,8 +1287,8 @@ void free_collider_cache(ListBase **colliders)
        }
 }
 
-static void cloth_bvh_objcollisions_nearcheck(ClothModifierData * clmd, 
CollisionModifierData *collmd,
-                                              CollPair **collisions, unsigned 
int *coll_count, int numresult,
+static bool cloth_bvh_objcollisions_nearcheck(ClothModifierData * clmd, 
CollisionModifierData *collmd,
+                                              CollPair **collisions, int 
numresult,
                                               BVHTreeOverlap *overlap, bool 
culling, bool use_normal)
 {
        *collisions = (CollPair *)MEM_mallocN(sizeof(CollPair) * numresult, 
"collision array");
@@ -1297,28 +1297,32 @@ static void 
cloth_bvh_objcollisions_nearcheck(ClothModifierData * clmd, Collisio
                              .collmd = collmd,
                              .overlap = overlap,
                              .collisions = *collisions,
-                             .coll_count = coll_count,
                              .culling = culling,
-                             .use_normal = use_normal};
+                             .use_normal = use_normal,
+                             .collided = false};
 
        ParallelRangeSettings settings;
        BLI_parallel_range_settings_defaults(&settings);
        settings.use_threading = true;
        BLI_task_parallel_range(0, numresult, &data, cloth_collision, 
&settings);
+
+       return data.collided;
 }
 
-static void cloth_bvh_selfcollisions_nearcheck(ClothModifierData * clmd, 
CollPair *collisions, unsigned int *coll_count,
+static bool cloth_bvh_selfcollisions_nearcheck(ClothModifierData * clmd, 
CollPair *collisions,
                                                int numresult, BVHTreeOverlap 
*overlap)
 {
        SelfColDetectData data = {.clmd = clmd,
                                  .overlap = overlap,
                                  .collisions = collisions,
-                                 .coll_count = coll_count};
+                                 .collided = false};
 
        ParallelRangeSettings settings;
        BLI_parallel_range_settings_defaults(&settings);
        settings.use_threading = true;
        BLI_task_parallel_range(0, numresult, &data, cloth_selfcollision, 
&settings);
+
+       return data.collided;
 }
 
 static int cloth_bvh_objcollisions_resolve (ClothModifierData * clmd, Object 
**collobjs, CollPair **collisions,
@@ -1482,43 +1486,46 @@ int cloth_bvh_objcollision(Object *ob, 
ClothModifierData *clmd, float step, floa
 
                if (clmd->coll_parms->flags & CLOTH_COLLSETTINGS_FLAG_ENABLED) {
                        CollPair **collisions;
-                       unsigned int *collision_counts;
+                       unsigned int *coll_counts;
+                       bool collided = false;
 
                        collisions = MEM_callocN(sizeof(CollPair *) 
*numcollobj, "CollPair");
-                       collision_counts = 
MEM_callocN(sizeof(*collision_counts) *numcollobj, "CollPair");
+                       coll_counts = MEM_callocN(sizeof(unsigned int) * 
numcollobj, "CollCounts");
 
                        // check all collision objects
                        for (i = 0; i < numcollobj; i++) {
                                Object *collob = collobjs[i];
                                CollisionModifierData *collmd = 
(CollisionModifierData *)modifiers_findByType(collob, eModifierType_Collision);
                                BVHTreeOverlap *overlap = NULL;
-                               unsigned int result = 0;
 
                                if (!collmd->bvhtree)
                                        continue;
 
                                /* search for overlapping collision pairs */
-                               overlap = BLI_bvhtree_overlap(cloth_bvh, 
collmd->bvhtree, &result, NULL, NULL);
+                               overlap = BLI_bvhtree_overlap(cloth_bvh, 
collmd->bvhtree, &coll_counts[i], NULL, NULL);
 
                                // go to next object if no overlap is there
-                               if (result && overlap) {
+                               if (coll_counts[i] && overlap) {
                                        /* check if collisions really happen 
(costly near check) */
-                                       cloth_bvh_objcollisions_nearcheck(clmd, 
collmd, &collisions[i], &collision_counts[i], result, overlap,
-                                                                         
(collob->pd->flag & PFIELD_CLOTH_USE_CULLING), (collob->pd->flag & 
PFIELD_CLOTH_USE_NORMAL));
+                                       collided = 
cloth_bvh_objcollisions_nearcheck(clmd, collmd, &collisions[i], coll_counts[i], 
overlap,
+                                                                               
     (collob->pd->flag & PFIELD_CLOTH_USE_CULLING),
+                                                                               
     (collob->pd->flag & PFIELD_CLOTH_USE_NORMAL)) || collided;
                                }
 
                                MEM_SAFE_FREE(overlap);
                        }
 
-                       ret += cloth_bvh_objcollisions_resolve(clmd, collobjs, 
collisions, collision_counts, numcollobj, dt);
-                       ret2 += ret;
+                       if (collided) {
+                               ret += cloth_bvh_objcollisions_resolve(clmd, 
collobjs, collisions, coll_counts, numcollobj, dt);
+                               ret2 += ret;
+                       }
 
                        for (i = 0; i < numcollobj; i++) {
                                MEM_SAFE_FREE(collisions[i]);
                        }
 
                        MEM_freeN(collisions);
-                       MEM_freeN(collision_counts);
+                       MEM_freeN(coll_counts);
                }
 
                ////////////////////////////////////////////////////////////
@@ -1526,9 +1533,8 @@ int cloth_bvh_objcollision(Object *ob, ClothModifierData 
*clmd, float step, floa
                ////////////////////////////////////////////////////////////
                if (clmd->coll_parms->flags & CLOTH_COLLSETTINGS_FLAG_SELF) {
                        BVHTreeOverlap *overlap = NULL;
-                       unsigned int result = 0;
                        CollPair *collisions = NULL;
-                       unsigned int collision_count = 0;
+                       unsigned int coll_count = 0;
 
                        //

@@ Diff output truncated at 10240 characters. @@

_______________________________________________
Bf-blender-cvs mailing list
Bf-blender-cvs@blender.org
https://lists.blender.org/mailman/listinfo/bf-blender-cvs

Reply via email to