[Bf-blender-cvs] [3c3c993c7c1] temp-angavrilov-constraints: Cloth: completely exclude fully pinned triangles from collision.

Alexander Gavrilov noreply at git.blender.org
Wed Jan 6 13:30:21 CET 2021


Commit: 3c3c993c7c103932dce7b30cd69b501e4769bf60
Author: Alexander Gavrilov
Date:   Wed Jan 6 14:48:42 2021 +0300
Branches: temp-angavrilov-constraints
https://developer.blender.org/rB3c3c993c7c103932dce7b30cd69b501e4769bf60

Cloth: completely exclude fully pinned triangles from collision.

Currently such triangles are effectively already excluded, because
the calculated forces are not applied to pinned vertices. However
these forces are still being computed, which is inefficient.

This adds an early check for triangles where all vertices are
pinned during BVH overlap detection, which significantly speeds
up certain use cases with big fully pinned areas that happen to
overlap a collider. In case of self collision both triangles must
be fully pinned to exclude safely, because the computation is
symmetric and handles two triangles at the same time.

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

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

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

diff --git a/source/blender/blenkernel/intern/collision.c b/source/blender/blenkernel/intern/collision.c
index 72525272254..5c62de24a46 100644
--- a/source/blender/blenkernel/intern/collision.c
+++ b/source/blender/blenkernel/intern/collision.c
@@ -1002,6 +1002,23 @@ static int cloth_selfcollision_response_static(ClothModifierData *clmd,
 #  pragma GCC diagnostic pop
 #endif
 
+static bool cloth_bvh_collision_is_active(const ClothModifierData *clmd,
+                                          const Cloth *cloth,
+                                          const MVertTri *tri_a)
+{
+  const ClothVertex *verts = cloth->verts;
+
+  /* Fully pinned triangles don't need collision processing. */
+  if (clmd->sim_parms->vgroup_mass > 0) {
+    if ((verts[tri_a->tri[0]].flags & verts[tri_a->tri[1]].flags & verts[tri_a->tri[2]].flags) &
+        CLOTH_VERT_FLAG_PINNED) {
+      return false;
+    }
+  }
+
+  return true;
+}
+
 static void cloth_collision(void *__restrict userdata,
                             const int index,
                             const TaskParallelTLS *__restrict UNUSED(tls))
@@ -1059,13 +1076,32 @@ static void cloth_collision(void *__restrict userdata,
   }
 }
 
-static bool cloth_bvh_selfcollision_is_active(const Cloth *cloth,
+static bool cloth_bvh_selfcollision_is_active(const ClothModifierData *clmd,
+                                              const Cloth *cloth,
                                               const MVertTri *tri_a,
-                                              const MVertTri *tri_b,
-                                              bool sewing_active)
+                                              const MVertTri *tri_b)
 {
   const ClothVertex *verts = cloth->verts;
+
+  /* Skip when either triangle is excluded. */
+  if (((verts[tri_a->tri[0]].flags & verts[tri_a->tri[1]].flags & verts[tri_a->tri[2]].flags) |
+       (verts[tri_b->tri[0]].flags & verts[tri_b->tri[1]].flags & verts[tri_b->tri[2]].flags)) &
+      CLOTH_VERT_FLAG_NOSELFCOLL) {
+    return false;
+  }
+
+  /* Skip when both triangles are pinned. */
+  if (clmd->sim_parms->vgroup_mass > 0) {
+    if (((verts[tri_a->tri[0]].flags & verts[tri_a->tri[1]].flags & verts[tri_a->tri[2]].flags) &
+         (verts[tri_b->tri[0]].flags & verts[tri_b->tri[1]].flags & verts[tri_b->tri[2]].flags)) &
+        CLOTH_VERT_FLAG_PINNED) {
+      return false;
+    }
+  }
+
   /* Ignore overlap of neighboring triangles and triangles connected by a sewing edge. */
+  bool sewing_active = (clmd->sim_parms->flags & CLOTH_SIMSETTINGS_FLAG_SEW);
+
   for (uint i = 0; i < 3; i++) {
     for (uint j = 0; j < 3; j++) {
       if (tri_a->tri[i] == tri_b->tri[j]) {
@@ -1080,12 +1116,6 @@ static bool cloth_bvh_selfcollision_is_active(const Cloth *cloth,
     }
   }
 
-  if (((verts[tri_a->tri[0]].flags & verts[tri_a->tri[1]].flags & verts[tri_a->tri[2]].flags) |
-       (verts[tri_b->tri[0]].flags & verts[tri_b->tri[1]].flags & verts[tri_b->tri[2]].flags)) &
-      CLOTH_VERT_FLAG_NOSELFCOLL) {
-    return false;
-  }
-
   return true;
 }
 
@@ -1107,8 +1137,7 @@ static void cloth_selfcollision(void *__restrict userdata,
   tri_b = &clmd->clothObject->tri[data->overlap[index].indexB];
 
 #ifdef DEBUG
-  bool sewing_active = (clmd->sim_parms->flags & CLOTH_SIMSETTINGS_FLAG_SEW);
-  BLI_assert(cloth_bvh_selfcollision_is_active(clmd->clothObject, tri_a, tri_b, sewing_active));
+  BLI_assert(cloth_bvh_selfcollision_is_active(clmd, clmd->clothObject, tri_a, tri_b));
 #endif
 
   /* Compute distance and normal. */
@@ -1508,6 +1537,18 @@ static int cloth_bvh_selfcollisions_resolve(ClothModifierData *clmd,
   return ret;
 }
 
+static bool cloth_bvh_obj_overlap_cb(void *userdata,
+                                     int index_a,
+                                     int UNUSED(index_b),
+                                     int UNUSED(thread))
+{
+  ClothModifierData *clmd = (ClothModifierData *)userdata;
+  struct Cloth *clothObject = clmd->clothObject;
+  const MVertTri *tri_a = &clothObject->tri[index_a];
+
+  return cloth_bvh_collision_is_active(clmd, clothObject, tri_a);
+}
+
 static bool cloth_bvh_self_overlap_cb(void *userdata, int index_a, int index_b, int UNUSED(thread))
 {
   /* No need for equal combinations (eg. (0,1) & (1,0)). */
@@ -1518,9 +1559,7 @@ static bool cloth_bvh_self_overlap_cb(void *userdata, int index_a, int index_b,
     tri_a = &clothObject->tri[index_a];
     tri_b = &clothObject->tri[index_b];
 
-    bool sewing_active = (clmd->sim_parms->flags & CLOTH_SIMSETTINGS_FLAG_SEW);
-
-    if (cloth_bvh_selfcollision_is_active(clothObject, tri_a, tri_b, sewing_active)) {
+    if (cloth_bvh_selfcollision_is_active(clmd, clothObject, tri_a, tri_b)) {
       return true;
     }
   }
@@ -1578,8 +1617,11 @@ int cloth_bvh_collision(
         /* Move object to position (step) in time. */
         collision_move_object(collmd, step + dt, step, false);
 
-        overlap_obj[i] = BLI_bvhtree_overlap(
-            cloth_bvh, collmd->bvhtree, &coll_counts_obj[i], NULL, NULL);
+        overlap_obj[i] = BLI_bvhtree_overlap(cloth_bvh,
+                                             collmd->bvhtree,
+                                             &coll_counts_obj[i],
+                                             is_hair ? NULL : cloth_bvh_obj_overlap_cb,
+                                             clmd);
       }
     }
   }



More information about the Bf-blender-cvs mailing list