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:
authorAlexander Gavrilov <angavrilov@gmail.com>2021-01-06 14:48:42 +0300
committerAlexander Gavrilov <angavrilov@gmail.com>2021-01-08 12:24:50 +0300
commit4a0b8c9427b57422f47c125a494c4631a6c0bfd1 (patch)
treee99c8bbffcf978319c78f7342006946878736e30 /source/blender/blenkernel/intern/collision.c
parent8877e294dfd680f0ad9c1598b6462dd726cc46f3 (diff)
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. Differential Revision: https://developer.blender.org/D10041
Diffstat (limited to 'source/blender/blenkernel/intern/collision.c')
-rw-r--r--source/blender/blenkernel/intern/collision.c75
1 files changed, 57 insertions, 18 deletions
diff --git a/source/blender/blenkernel/intern/collision.c b/source/blender/blenkernel/intern/collision.c
index 72525272254..068216e3159 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 *UNUSED(clmd),
+ const Cloth *cloth,
+ const MVertTri *tri_a)
+{
+ const ClothVertex *verts = cloth->verts;
+
+ /* Fully pinned triangles don't need collision processing. */
+ const int flags_a = verts[tri_a->tri[0]].flags & verts[tri_a->tri[1]].flags &
+ verts[tri_a->tri[2]].flags;
+
+ if (flags_a & 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,31 @@ 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. */
+ const int flags_a = verts[tri_a->tri[0]].flags & verts[tri_a->tri[1]].flags &
+ verts[tri_a->tri[2]].flags;
+ const int flags_b = verts[tri_b->tri[0]].flags & verts[tri_b->tri[1]].flags &
+ verts[tri_b->tri[2]].flags;
+
+ if ((flags_a | flags_b) & CLOTH_VERT_FLAG_NOSELFCOLL) {
+ return false;
+ }
+
+ /* Skip when both triangles are pinned. */
+ if ((flags_a & flags_b) & 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 +1115,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;
}
@@ -1106,10 +1135,7 @@ static void cloth_selfcollision(void *__restrict userdata,
tri_a = &clmd->clothObject->tri[data->overlap[index].indexA];
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));
-#endif
+ BLI_assert(cloth_bvh_selfcollision_is_active(clmd, clmd->clothObject, tri_a, tri_b));
/* Compute distance and normal. */
distance = compute_collision_point_tri_tri(verts1[tri_a->tri[0]].tx,
@@ -1508,6 +1534,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 +1556,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 +1614,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);
}
}
}