Blender V4.3
collision.cc
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: Blender Authors
2 *
3 * SPDX-License-Identifier: GPL-2.0-or-later */
4
9#include <algorithm>
10
11#include "MEM_guardedalloc.h"
12
13#include "DNA_cloth_types.h"
15#include "DNA_object_types.h"
16#include "DNA_scene_types.h"
17
18#include "BLI_math_geom.h"
19#include "BLI_math_vector.h"
20#include "BLI_task.h"
21#include "BLI_threads.h"
22#include "BLI_utildefines.h"
23
24#include "BKE_cloth.hh"
25#include "BKE_collection.hh"
26#include "BKE_modifier.hh"
27
28#include "BKE_collision.h"
29#include "BLI_kdopbvh.h"
30
31#include "DEG_depsgraph.hh"
34
35#ifdef WITH_ELTOPO
36# include "eltopo-capi.h"
37#endif
38
48
55
56/***********************************
57 * Collision modifier code start
58 ***********************************/
59
61 const float step,
62 const float prevstep,
63 const bool moving_bvh)
64{
65 uint i = 0;
66
67 /* the collider doesn't move this frame */
68 if (collmd->is_static) {
69 for (i = 0; i < collmd->mvert_num; i++) {
70 zero_v3(collmd->current_v[i]);
71 }
72
73 return;
74 }
75
76 for (i = 0; i < collmd->mvert_num; i++) {
77 interp_v3_v3v3(collmd->current_x[i], collmd->x[i], collmd->xnew[i], prevstep);
78 interp_v3_v3v3(collmd->current_xnew[i], collmd->x[i], collmd->xnew[i], step);
79 sub_v3_v3v3(collmd->current_v[i], collmd->current_xnew[i], collmd->current_x[i]);
80 }
81
83 collmd->current_xnew,
84 collmd->current_x,
85 reinterpret_cast<const blender::int3 *>(collmd->vert_tris),
86 collmd->tri_num,
87 moving_bvh);
88}
89
90BVHTree *bvhtree_build_from_mvert(const float (*positions)[3],
91 const blender::int3 *vert_tris,
92 int tri_num,
93 float epsilon)
94{
95 BVHTree *tree = BLI_bvhtree_new(tri_num, epsilon, 4, 26);
96
97 /* fill tree */
98 for (int i = 0; i < tri_num; i++) {
99 float co[3][3];
100
101 copy_v3_v3(co[0], positions[vert_tris[i][0]]);
102 copy_v3_v3(co[1], positions[vert_tris[i][1]]);
103 copy_v3_v3(co[2], positions[vert_tris[i][2]]);
104
105 BLI_bvhtree_insert(tree, i, co[0], 3);
106 }
107
108 /* balance tree */
110
111 return tree;
112}
113
115 const float (*positions)[3],
116 const float (*positions_moving)[3],
117 const blender::int3 *vert_tris,
118 int tri_num,
119 bool moving)
120{
121
122 if ((bvhtree == nullptr) || (positions == nullptr)) {
123 return;
124 }
125
126 if (positions_moving == nullptr) {
127 moving = false;
128 }
129
130 for (int i = 0; i < tri_num; i++) {
131 float co[3][3];
132 bool ret;
133
134 copy_v3_v3(co[0], positions[vert_tris[i][0]]);
135 copy_v3_v3(co[1], positions[vert_tris[i][1]]);
136 copy_v3_v3(co[2], positions[vert_tris[i][2]]);
137
138 /* copy new locations into array */
139 if (moving) {
140 float co_moving[3][3];
141 /* update moving positions */
142 copy_v3_v3(co_moving[0], positions_moving[vert_tris[i][0]]);
143 copy_v3_v3(co_moving[1], positions_moving[vert_tris[i][1]]);
144 copy_v3_v3(co_moving[2], positions_moving[vert_tris[i][2]]);
145
146 ret = BLI_bvhtree_update_node(bvhtree, i, &co[0][0], &co_moving[0][0], 3);
147 }
148 else {
149 ret = BLI_bvhtree_update_node(bvhtree, i, &co[0][0], nullptr, 3);
150 }
151
152 /* check if tree is already full */
153 if (ret == false) {
154 break;
155 }
156 }
157
159}
160
161/* ***************************
162 * Collision modifier code end
163 * *************************** */
164
166{
167 return (++i < 3) ? i : 0;
168}
169
170static float compute_collision_point_tri_tri(const float a1[3],
171 const float a2[3],
172 const float a3[3],
173 const float b1[3],
174 const float b2[3],
175 const float b3[3],
176 bool culling,
177 bool use_normal,
178 float r_a[3],
179 float r_b[3],
180 float r_vec[3])
181{
182 float a[3][3];
183 float b[3][3];
184 float dist = FLT_MAX;
185 float tmp_co1[3], tmp_co2[3];
186 float isect_a[3], isect_b[3];
187 float tmp, tmp_vec[3];
188 float normal[3], cent[3];
189 bool backside = false;
190
191 copy_v3_v3(a[0], a1);
192 copy_v3_v3(a[1], a2);
193 copy_v3_v3(a[2], a3);
194
195 copy_v3_v3(b[0], b1);
196 copy_v3_v3(b[1], b2);
197 copy_v3_v3(b[2], b3);
198
199 /* Find intersections. */
200 int tri_a_edge_isect_count;
201 const bool is_intersecting = isect_tri_tri_v3_ex(
202 a, b, isect_a, isect_b, &tri_a_edge_isect_count);
203
204 /* Determine collision side. */
205 if (culling) {
206 normal_tri_v3(normal, b[0], b[1], b[2]);
207 mid_v3_v3v3v3(cent, b[0], b[1], b[2]);
208
209 if (!is_intersecting) {
210 for (int i = 0; i < 3; i++) {
211 sub_v3_v3v3(tmp_vec, a[i], cent);
212 if (dot_v3v3(tmp_vec, normal) < 0.0f) {
213 backside = true;
214 break;
215 }
216 }
217 }
218 else if (tri_a_edge_isect_count != 1) {
219 /* It is not Edge intersection. */
220 backside = true;
221 }
222 }
223 else if (use_normal) {
224 normal_tri_v3(normal, b[0], b[1], b[2]);
225 }
226
227 if (tri_a_edge_isect_count == 1) {
228 /* Edge intersection. */
229 copy_v3_v3(r_a, isect_a);
230 copy_v3_v3(r_b, isect_b);
231
232 if (use_normal) {
233 copy_v3_v3(r_vec, normal);
234 }
235 else {
236 sub_v3_v3v3(r_vec, r_b, r_a);
237 }
238
239 return 0.0f;
240 }
241
242 if (backside) {
243 float maxdist = 0.0f;
244 bool found = false;
245
246 /* Point projections. */
247 for (int i = 0; i < 3; i++) {
248 if (isect_ray_tri_v3(a[i], normal, b[0], b[1], b[2], &tmp, nullptr)) {
249 if (tmp > maxdist) {
250 maxdist = tmp;
251 copy_v3_v3(r_a, a[i]);
252 madd_v3_v3v3fl(r_b, a[i], normal, tmp);
253 found = true;
254 }
255 }
256 }
257
258 negate_v3(normal);
259
260 for (int i = 0; i < 3; i++) {
261 if (isect_ray_tri_v3(b[i], normal, a[0], a[1], a[2], &tmp, nullptr)) {
262 if (tmp > maxdist) {
263 maxdist = tmp;
264 madd_v3_v3v3fl(r_a, b[i], normal, tmp);
265 copy_v3_v3(r_b, b[i]);
266 found = true;
267 }
268 }
269 }
270
271 negate_v3(normal);
272
273 /* Edge projections. */
274 for (int i = 0; i < 3; i++) {
275 float dir[3];
276
277 sub_v3_v3v3(tmp_vec, b[next_ind(i)], b[i]);
278 cross_v3_v3v3(dir, tmp_vec, normal);
279
280 for (int j = 0; j < 3; j++) {
281 if (isect_line_plane_v3(tmp_co1, a[j], a[next_ind(j)], b[i], dir) &&
282 point_in_slice_seg(tmp_co1, a[j], a[next_ind(j)]) &&
283 point_in_slice_seg(tmp_co1, b[i], b[next_ind(i)]))
284 {
285 closest_to_line_v3(tmp_co2, tmp_co1, b[i], b[next_ind(i)]);
286 sub_v3_v3v3(tmp_vec, tmp_co1, tmp_co2);
287 tmp = len_v3(tmp_vec);
288
289 if ((tmp > maxdist) && (dot_v3v3(tmp_vec, normal) < 0.0f)) {
290 maxdist = tmp;
291 copy_v3_v3(r_a, tmp_co1);
292 copy_v3_v3(r_b, tmp_co2);
293 found = true;
294 }
295 }
296 }
297 }
298
299 /* If no point is found, will fallback onto regular proximity test below. */
300 if (found) {
301 sub_v3_v3v3(r_vec, r_b, r_a);
302
303 if (use_normal) {
304 if (dot_v3v3(normal, r_vec) >= 0.0f) {
305 copy_v3_v3(r_vec, normal);
306 }
307 else {
308 negate_v3_v3(r_vec, normal);
309 }
310 }
311
312 return 0.0f;
313 }
314 }
315
316 /* Closest point. */
317 for (int i = 0; i < 3; i++) {
318 closest_on_tri_to_point_v3(tmp_co1, a[i], b[0], b[1], b[2]);
319 tmp = len_squared_v3v3(tmp_co1, a[i]);
320
321 if (tmp < dist) {
322 dist = tmp;
323 copy_v3_v3(r_a, a[i]);
324 copy_v3_v3(r_b, tmp_co1);
325 }
326 }
327
328 for (int i = 0; i < 3; i++) {
329 closest_on_tri_to_point_v3(tmp_co1, b[i], a[0], a[1], a[2]);
330 tmp = len_squared_v3v3(tmp_co1, b[i]);
331
332 if (tmp < dist) {
333 dist = tmp;
334 copy_v3_v3(r_a, tmp_co1);
335 copy_v3_v3(r_b, b[i]);
336 }
337 }
338
339 /* Closest edge. */
340 if (!is_intersecting) {
341 for (int i = 0; i < 3; i++) {
342 for (int j = 0; j < 3; j++) {
343 isect_seg_seg_v3(a[i], a[next_ind(i)], b[j], b[next_ind(j)], tmp_co1, tmp_co2);
344 tmp = len_squared_v3v3(tmp_co1, tmp_co2);
345
346 if (tmp < dist) {
347 dist = tmp;
348 copy_v3_v3(r_a, tmp_co1);
349 copy_v3_v3(r_b, tmp_co2);
350 }
351 }
352 }
353 }
354
355 if (!is_intersecting) {
356 sub_v3_v3v3(r_vec, r_a, r_b);
357 dist = sqrtf(dist);
358 }
359 else {
360 sub_v3_v3v3(r_vec, r_b, r_a);
361 dist = 0.0f;
362 }
363
364 if (culling && use_normal) {
365 copy_v3_v3(r_vec, normal);
366 }
367 else if (use_normal) {
368 if (dot_v3v3(normal, r_vec) >= 0.0f) {
369 copy_v3_v3(r_vec, normal);
370 }
371 else {
372 negate_v3_v3(r_vec, normal);
373 }
374 }
375 else if (culling && (dot_v3v3(r_vec, normal) < 0.0f)) {
376 return FLT_MAX;
377 }
378
379 return dist;
380}
381
382static float compute_collision_point_edge_tri(const float a1[3],
383 const float a2[3],
384 const float b1[3],
385 const float b2[3],
386 const float b3[3],
387 bool culling,
388 bool use_normal,
389 float r_a[3],
390 float r_b[3],
391 float r_vec[3])
392{
393 float a[2][3];
394 float b[3][3];
395 float dist = FLT_MAX;
396 float tmp_co1[3], tmp_co2[3];
397 float isect_a[3];
398 bool isect = false;
399 float tmp, tmp_vec[3];
400 float normal[3], cent[3];
401 bool backside = false;
402
403 copy_v3_v3(a[0], a1);
404 copy_v3_v3(a[1], a2);
405
406 copy_v3_v3(b[0], b1);
407 copy_v3_v3(b[1], b2);
408 copy_v3_v3(b[2], b3);
409
410 normal_tri_v3(normal, b[0], b[1], b[2]);
411
412 /* Find intersection. */
413 if (isect_line_segment_tri_v3(a[0], a[1], b[0], b[1], b[2], &tmp, nullptr)) {
414 interp_v3_v3v3(isect_a, a[0], a[1], tmp);
415 isect = true;
416 }
417
418 /* Determine collision side. */
419 if (culling) {
420 if (isect) {
421 backside = true;
422 }
423 else {
424 mid_v3_v3v3v3(cent, b[0], b[1], b[2]);
425
426 for (int i = 0; i < 2; i++) {
427 sub_v3_v3v3(tmp_vec, a[i], cent);
428 if (dot_v3v3(tmp_vec, normal) < 0.0f) {
429 backside = true;
430 break;
431 }
432 }
433 }
434 }
435
436 if (isect) {
437 /* Edge intersection. */
438 copy_v3_v3(r_a, isect_a);
439 copy_v3_v3(r_b, isect_a);
440
441 copy_v3_v3(r_vec, normal);
442
443 return 0.0f;
444 }
445
446 if (backside) {
447 float maxdist = 0.0f;
448 bool found = false;
449
450 /* Point projections. */
451 for (int i = 0; i < 2; i++) {
452 if (isect_ray_tri_v3(a[i], normal, b[0], b[1], b[2], &tmp, nullptr)) {
453 if (tmp > maxdist) {
454 maxdist = tmp;
455 copy_v3_v3(r_a, a[i]);
456 madd_v3_v3v3fl(r_b, a[i], normal, tmp);
457 found = true;
458 }
459 }
460 }
461
462 /* Edge projections. */
463 for (int i = 0; i < 3; i++) {
464 float dir[3];
465
466 sub_v3_v3v3(tmp_vec, b[next_ind(i)], b[i]);
467 cross_v3_v3v3(dir, tmp_vec, normal);
468
469 if (isect_line_plane_v3(tmp_co1, a[0], a[1], b[i], dir) &&
470 point_in_slice_seg(tmp_co1, a[0], a[1]) &&
471 point_in_slice_seg(tmp_co1, b[i], b[next_ind(i)]))
472 {
473 closest_to_line_v3(tmp_co2, tmp_co1, b[i], b[next_ind(i)]);
474 sub_v3_v3v3(tmp_vec, tmp_co1, tmp_co2);
475 tmp = len_v3(tmp_vec);
476
477 if ((tmp > maxdist) && (dot_v3v3(tmp_vec, normal) < 0.0f)) {
478 maxdist = tmp;
479 copy_v3_v3(r_a, tmp_co1);
480 copy_v3_v3(r_b, tmp_co2);
481 found = true;
482 }
483 }
484 }
485
486 /* If no point is found, will fallback onto regular proximity test below. */
487 if (found) {
488 sub_v3_v3v3(r_vec, r_b, r_a);
489
490 if (use_normal) {
491 if (dot_v3v3(normal, r_vec) >= 0.0f) {
492 copy_v3_v3(r_vec, normal);
493 }
494 else {
495 negate_v3_v3(r_vec, normal);
496 }
497 }
498
499 return 0.0f;
500 }
501 }
502
503 /* Closest point. */
504 for (int i = 0; i < 2; i++) {
505 closest_on_tri_to_point_v3(tmp_co1, a[i], b[0], b[1], b[2]);
506 tmp = len_squared_v3v3(tmp_co1, a[i]);
507
508 if (tmp < dist) {
509 dist = tmp;
510 copy_v3_v3(r_a, a[i]);
511 copy_v3_v3(r_b, tmp_co1);
512 }
513 }
514
515 /* Closest edge. */
516 if (!isect) {
517 for (int j = 0; j < 3; j++) {
518 isect_seg_seg_v3(a[0], a[1], b[j], b[next_ind(j)], tmp_co1, tmp_co2);
519 tmp = len_squared_v3v3(tmp_co1, tmp_co2);
520
521 if (tmp < dist) {
522 dist = tmp;
523 copy_v3_v3(r_a, tmp_co1);
524 copy_v3_v3(r_b, tmp_co2);
525 }
526 }
527 }
528
529 if (isect) {
530 sub_v3_v3v3(r_vec, r_b, r_a);
531 dist = 0.0f;
532 }
533 else {
534 sub_v3_v3v3(r_vec, r_a, r_b);
535 dist = sqrtf(dist);
536 }
537
538 if (culling && use_normal) {
539 copy_v3_v3(r_vec, normal);
540 }
541 else if (use_normal) {
542 if (dot_v3v3(normal, r_vec) >= 0.0f) {
543 copy_v3_v3(r_vec, normal);
544 }
545 else {
546 negate_v3_v3(r_vec, normal);
547 }
548 }
549 else if (culling && (dot_v3v3(r_vec, normal) < 0.0f)) {
550 return FLT_MAX;
551 }
552
553 return dist;
554}
555
556/* `w3` is not perfect. */
557static void collision_compute_barycentric(const float pv[3],
558 const float p1[3],
559 const float p2[3],
560 const float p3[3],
561 float *w1,
562 float *w2,
563 float *w3)
564{
565 /* dot_v3v3 */
566#define INPR(v1, v2) ((v1)[0] * (v2)[0] + (v1)[1] * (v2)[1] + (v1)[2] * (v2)[2])
567
568 double tempV1[3], tempV2[3], tempV4[3];
569 double a, b, c, d, e, f;
570
571 sub_v3db_v3fl_v3fl(tempV1, p1, p3);
572 sub_v3db_v3fl_v3fl(tempV2, p2, p3);
573 sub_v3db_v3fl_v3fl(tempV4, pv, p3);
574
575 a = INPR(tempV1, tempV1);
576 b = INPR(tempV1, tempV2);
577 c = INPR(tempV2, tempV2);
578 e = INPR(tempV1, tempV4);
579 f = INPR(tempV2, tempV4);
580
581 d = (a * c - b * b);
582
583 if (fabs(d) < double(ALMOST_ZERO)) {
584 *w1 = *w2 = *w3 = 1.0 / 3.0;
585 return;
586 }
587
588 w1[0] = float((e * c - b * f) / d);
589
590 if (w1[0] < 0) {
591 w1[0] = 0;
592 }
593
594 w2[0] = float((f - b * double(w1[0])) / c);
595
596 if (w2[0] < 0) {
597 w2[0] = 0;
598 }
599
600 w3[0] = 1.0f - w1[0] - w2[0];
601
602#undef INPR
603}
604
605#ifdef __GNUC__
606# pragma GCC diagnostic push
607# pragma GCC diagnostic ignored "-Wdouble-promotion"
608#endif
609
611 const float v1[3],
612 const float v2[3],
613 const float v3[3],
614 const double w1,
615 const double w2,
616 const double w3)
617{
618 zero_v3(to);
619 VECADDMUL(to, v1, w1);
620 VECADDMUL(to, v2, w2);
621 VECADDMUL(to, v3, w3);
622}
623
624static void cloth_collision_impulse_vert(const float clamp_sq,
625 const float impulse[3],
626 ClothVertex *vert)
627{
628 float impulse_len_sq = len_squared_v3(impulse);
629
630 if ((clamp_sq > 0.0f) && (impulse_len_sq > clamp_sq)) {
631 return;
632 }
633
634 if (fabsf(vert->impulse[0]) < fabsf(impulse[0])) {
635 vert->impulse[0] = impulse[0];
636 }
637
638 if (fabsf(vert->impulse[1]) < fabsf(impulse[1])) {
639 vert->impulse[1] = impulse[1];
640 }
641
642 if (fabsf(vert->impulse[2]) < fabsf(impulse[2])) {
643 vert->impulse[2] = impulse[2];
644 }
645
646 vert->impulse_count++;
647}
648
650 CollisionModifierData *collmd,
651 Object *collob,
652 CollPair *collpair,
653 uint collision_count,
654 const float dt)
655{
656 int result = 0;
657 Cloth *cloth = clmd->clothObject;
658 const float clamp_sq = square_f(clmd->coll_parms->clamp * dt);
659 const float time_multiplier = 1.0f / (clmd->sim_parms->dt * clmd->sim_parms->timescale);
660 const float epsilon2 = BLI_bvhtree_get_epsilon(collmd->bvhtree);
661 const float min_distance = (clmd->coll_parms->epsilon + epsilon2) * (8.0f / 9.0f);
662
663 const bool is_hair = (clmd->hairdata != nullptr);
664 for (int i = 0; i < collision_count; i++, collpair++) {
665 float i1[3], i2[3], i3[3];
666 float v1[3], v2[3], relativeVelocity[3];
667 zero_v3(i1);
668 zero_v3(i2);
669 zero_v3(i3);
670
671 /* Only handle static collisions here. */
672 if (collpair->flag & (COLLISION_IN_FUTURE | COLLISION_INACTIVE)) {
673 continue;
674 }
675
676 /* Compute barycentric coordinates and relative "velocity" for both collision points. */
677 float w1 = collpair->aw1, w2 = collpair->aw2, w3 = collpair->aw3;
678 float u1 = collpair->bw1, u2 = collpair->bw2, u3 = collpair->bw3;
679
680 if (is_hair) {
681 interp_v3_v3v3(v1, cloth->verts[collpair->ap1].tv, cloth->verts[collpair->ap2].tv, w2);
682 }
683 else {
685 cloth->verts[collpair->ap1].tv,
686 cloth->verts[collpair->ap2].tv,
687 cloth->verts[collpair->ap3].tv,
688 w1,
689 w2,
690 w3);
691 }
692
694 collmd->current_v[collpair->bp1],
695 collmd->current_v[collpair->bp2],
696 collmd->current_v[collpair->bp3],
697 u1,
698 u2,
699 u3);
700
701 sub_v3_v3v3(relativeVelocity, v2, v1);
702
703 /* Calculate the normal component of the relative velocity
704 * (actually only the magnitude - the direction is stored in 'normal'). */
705 const float magrelVel = dot_v3v3(relativeVelocity, collpair->normal);
706 const float d = min_distance - collpair->distance;
707
708 /* If magrelVel < 0 the edges are approaching each other. */
709 if (magrelVel > 0.0f) {
710 /* Calculate Impulse magnitude to stop all motion in normal direction. */
711 float magtangent = 0, repulse = 0;
712 double impulse = 0.0;
713 float vrel_t_pre[3];
714 float temp[3];
715
716 /* Calculate tangential velocity. */
717 copy_v3_v3(temp, collpair->normal);
718 mul_v3_fl(temp, magrelVel);
719 sub_v3_v3v3(vrel_t_pre, relativeVelocity, temp);
720
721 /* Decrease in magnitude of relative tangential velocity due to coulomb friction
722 * in original formula "magrelVel" should be the
723 * "change of relative velocity in normal direction". */
724 magtangent = min_ff(collob->pd->pdef_cfrict * 0.01f * magrelVel, len_v3(vrel_t_pre));
725
726 /* Apply friction impulse. */
727 if (magtangent > ALMOST_ZERO) {
728 normalize_v3(vrel_t_pre);
729
730 impulse = magtangent / 1.5;
731
732 VECADDMUL(i1, vrel_t_pre, double(w1) * impulse);
733 VECADDMUL(i2, vrel_t_pre, double(w2) * impulse);
734
735 if (!is_hair) {
736 VECADDMUL(i3, vrel_t_pre, double(w3) * impulse);
737 }
738 }
739
740 /* Apply velocity stopping impulse. */
741 impulse = magrelVel / 1.5f;
742
743 VECADDMUL(i1, collpair->normal, double(w1) * impulse);
744 VECADDMUL(i2, collpair->normal, double(w2) * impulse);
745 if (!is_hair) {
746 VECADDMUL(i3, collpair->normal, double(w3) * impulse);
747 }
748
749 if ((magrelVel < 0.1f * d * time_multiplier) && (d > ALMOST_ZERO)) {
750 repulse = std::min(d / time_multiplier, 0.1f * d * time_multiplier - magrelVel);
751
752 /* Stay on the safe side and clamp repulse. */
753 if (impulse > ALMOST_ZERO) {
754 repulse = min_ff(repulse, 5.0f * impulse);
755 }
756
757 repulse = max_ff(impulse, repulse);
758
759 impulse = repulse / 1.5f;
760
761 VECADDMUL(i1, collpair->normal, impulse);
762 VECADDMUL(i2, collpair->normal, impulse);
763 if (!is_hair) {
764 VECADDMUL(i3, collpair->normal, impulse);
765 }
766 }
767
768 result = 1;
769 }
770 else if (d > ALMOST_ZERO) {
771 /* Stay on the safe side and clamp repulse. */
772 float repulse = d / time_multiplier;
773 float impulse = repulse / 4.5f;
774
775 VECADDMUL(i1, collpair->normal, w1 * impulse);
776 VECADDMUL(i2, collpair->normal, w2 * impulse);
777
778 if (!is_hair) {
779 VECADDMUL(i3, collpair->normal, w3 * impulse);
780 }
781
782 result = 1;
783 }
784
785 if (result) {
786 cloth_collision_impulse_vert(clamp_sq, i1, &cloth->verts[collpair->ap1]);
787 cloth_collision_impulse_vert(clamp_sq, i2, &cloth->verts[collpair->ap2]);
788 if (!is_hair) {
789 cloth_collision_impulse_vert(clamp_sq, i3, &cloth->verts[collpair->ap3]);
790 }
791 }
792 }
793
794 return result;
795}
796
798 CollPair *collpair,
799 uint collision_count,
800 const float dt)
801{
802 int result = 0;
803 Cloth *cloth = clmd->clothObject;
804 const float clamp_sq = square_f(clmd->coll_parms->self_clamp * dt);
805 const float time_multiplier = 1.0f / (clmd->sim_parms->dt * clmd->sim_parms->timescale);
806 const float min_distance = (2.0f * clmd->coll_parms->selfepsilon) * (8.0f / 9.0f);
807
808 for (int i = 0; i < collision_count; i++, collpair++) {
809 float ia[3][3] = {{0.0f}};
810 float ib[3][3] = {{0.0f}};
811 float v1[3], v2[3], relativeVelocity[3];
812
813 /* Only handle static collisions here. */
814 if (collpair->flag & (COLLISION_IN_FUTURE | COLLISION_INACTIVE)) {
815 continue;
816 }
817
818 /* Retrieve barycentric coordinates for both collision points. */
819 float w1 = collpair->aw1, w2 = collpair->aw2, w3 = collpair->aw3;
820 float u1 = collpair->bw1, u2 = collpair->bw2, u3 = collpair->bw3;
821
822 /* Calculate relative "velocity". */
824 cloth->verts[collpair->ap1].tv,
825 cloth->verts[collpair->ap2].tv,
826 cloth->verts[collpair->ap3].tv,
827 w1,
828 w2,
829 w3);
830
832 cloth->verts[collpair->bp1].tv,
833 cloth->verts[collpair->bp2].tv,
834 cloth->verts[collpair->bp3].tv,
835 u1,
836 u2,
837 u3);
838
839 sub_v3_v3v3(relativeVelocity, v2, v1);
840
841 /* Calculate the normal component of the relative velocity
842 * (actually only the magnitude - the direction is stored in 'normal'). */
843 const float magrelVel = dot_v3v3(relativeVelocity, collpair->normal);
844 const float d = min_distance - collpair->distance;
845
846 /* TODO: Impulses should be weighed by mass as this is self col,
847 * this has to be done after mass distribution is implemented. */
848
849 /* If magrelVel < 0 the edges are approaching each other. */
850 if (magrelVel > 0.0f) {
851 /* Calculate Impulse magnitude to stop all motion in normal direction. */
852 float magtangent = 0, repulse = 0;
853 double impulse = 0.0;
854 float vrel_t_pre[3];
855 float temp[3];
856
857 /* Calculate tangential velocity. */
858 copy_v3_v3(temp, collpair->normal);
859 mul_v3_fl(temp, magrelVel);
860 sub_v3_v3v3(vrel_t_pre, relativeVelocity, temp);
861
862 /* Decrease in magnitude of relative tangential velocity due to coulomb friction
863 * in original formula "magrelVel" should be the
864 * "change of relative velocity in normal direction". */
865 magtangent = min_ff(clmd->coll_parms->self_friction * 0.01f * magrelVel, len_v3(vrel_t_pre));
866
867 /* Apply friction impulse. */
868 if (magtangent > ALMOST_ZERO) {
869 normalize_v3(vrel_t_pre);
870
871 impulse = magtangent / 1.5;
872
873 VECADDMUL(ia[0], vrel_t_pre, double(w1) * impulse);
874 VECADDMUL(ia[1], vrel_t_pre, double(w2) * impulse);
875 VECADDMUL(ia[2], vrel_t_pre, double(w3) * impulse);
876
877 VECADDMUL(ib[0], vrel_t_pre, double(u1) * -impulse);
878 VECADDMUL(ib[1], vrel_t_pre, double(u2) * -impulse);
879 VECADDMUL(ib[2], vrel_t_pre, double(u3) * -impulse);
880 }
881
882 /* Apply velocity stopping impulse. */
883 impulse = magrelVel / 3.0f;
884
885 VECADDMUL(ia[0], collpair->normal, double(w1) * impulse);
886 VECADDMUL(ia[1], collpair->normal, double(w2) * impulse);
887 VECADDMUL(ia[2], collpair->normal, double(w3) * impulse);
888
889 VECADDMUL(ib[0], collpair->normal, double(u1) * -impulse);
890 VECADDMUL(ib[1], collpair->normal, double(u2) * -impulse);
891 VECADDMUL(ib[2], collpair->normal, double(u3) * -impulse);
892
893 if ((magrelVel < 0.1f * d * time_multiplier) && (d > ALMOST_ZERO)) {
894 repulse = std::min(d / time_multiplier, 0.1f * d * time_multiplier - magrelVel);
895
896 if (impulse > ALMOST_ZERO) {
897 repulse = min_ff(repulse, 5.0 * impulse);
898 }
899
900 repulse = max_ff(impulse, repulse);
901 impulse = repulse / 1.5f;
902
903 VECADDMUL(ia[0], collpair->normal, double(w1) * impulse);
904 VECADDMUL(ia[1], collpair->normal, double(w2) * impulse);
905 VECADDMUL(ia[2], collpair->normal, double(w3) * impulse);
906
907 VECADDMUL(ib[0], collpair->normal, double(u1) * -impulse);
908 VECADDMUL(ib[1], collpair->normal, double(u2) * -impulse);
909 VECADDMUL(ib[2], collpair->normal, double(u3) * -impulse);
910 }
911
912 result = 1;
913 }
914 else if (d > ALMOST_ZERO) {
915 /* Stay on the safe side and clamp repulse. */
916 float repulse = d * 1.0f / time_multiplier;
917 float impulse = repulse / 9.0f;
918
919 VECADDMUL(ia[0], collpair->normal, w1 * impulse);
920 VECADDMUL(ia[1], collpair->normal, w2 * impulse);
921 VECADDMUL(ia[2], collpair->normal, w3 * impulse);
922
923 VECADDMUL(ib[0], collpair->normal, u1 * -impulse);
924 VECADDMUL(ib[1], collpair->normal, u2 * -impulse);
925 VECADDMUL(ib[2], collpair->normal, u3 * -impulse);
926
927 result = 1;
928 }
929
930 if (result) {
931 cloth_collision_impulse_vert(clamp_sq, ia[0], &cloth->verts[collpair->ap1]);
932 cloth_collision_impulse_vert(clamp_sq, ia[1], &cloth->verts[collpair->ap2]);
933 cloth_collision_impulse_vert(clamp_sq, ia[2], &cloth->verts[collpair->ap3]);
934
935 cloth_collision_impulse_vert(clamp_sq, ib[0], &cloth->verts[collpair->bp1]);
936 cloth_collision_impulse_vert(clamp_sq, ib[1], &cloth->verts[collpair->bp2]);
937 cloth_collision_impulse_vert(clamp_sq, ib[2], &cloth->verts[collpair->bp3]);
938 }
939 }
940
941 return result;
942}
943
944#ifdef __GNUC__
945# pragma GCC diagnostic pop
946#endif
947
949 const Cloth *cloth,
950 const blender::int3 vert_tri_a)
951{
952 const ClothVertex *verts = cloth->verts;
953
954 /* Fully pinned triangles don't need collision processing. */
955 const int flags_a = verts[vert_tri_a[0]].flags & verts[vert_tri_a[1]].flags &
956 verts[vert_tri_a[2]].flags;
957
959 return false;
960 }
961
962 return true;
963}
964
965static void cloth_collision(void *__restrict userdata,
966 const int index,
967 const TaskParallelTLS *__restrict /*tls*/)
968{
969 ColDetectData *data = (ColDetectData *)userdata;
970
971 ClothModifierData *clmd = data->clmd;
972 CollisionModifierData *collmd = data->collmd;
973 CollPair *collpair = data->collisions;
974 ClothVertex *verts1 = clmd->clothObject->verts;
975 float distance = 0.0f;
976 float epsilon1 = clmd->coll_parms->epsilon;
977 float epsilon2 = BLI_bvhtree_get_epsilon(collmd->bvhtree);
978 float pa[3], pb[3], vect[3];
979
980 const blender::int3 vert_tri_a = clmd->clothObject->vert_tris[data->overlap[index].indexA];
981 const blender::int3 vert_tri_b = collmd->vert_tris[data->overlap[index].indexB];
982
983 /* Compute distance and normal. */
984 distance = compute_collision_point_tri_tri(verts1[vert_tri_a[0]].tx,
985 verts1[vert_tri_a[1]].tx,
986 verts1[vert_tri_a[2]].tx,
987 collmd->current_xnew[vert_tri_b[0]],
988 collmd->current_xnew[vert_tri_b[1]],
989 collmd->current_xnew[vert_tri_b[2]],
990 data->culling,
991 data->use_normal,
992 pa,
993 pb,
994 vect);
995
996 if ((distance <= (epsilon1 + epsilon2 + ALMOST_ZERO)) && (len_squared_v3(vect) > ALMOST_ZERO)) {
997 collpair[index].ap1 = vert_tri_a[0];
998 collpair[index].ap2 = vert_tri_a[1];
999 collpair[index].ap3 = vert_tri_a[2];
1000
1001 collpair[index].bp1 = vert_tri_b[0];
1002 collpair[index].bp2 = vert_tri_b[1];
1003 collpair[index].bp3 = vert_tri_b[2];
1004
1005 copy_v3_v3(collpair[index].pa, pa);
1006 copy_v3_v3(collpair[index].pb, pb);
1007 copy_v3_v3(collpair[index].vector, vect);
1008
1009 normalize_v3_v3(collpair[index].normal, collpair[index].vector);
1010
1011 collpair[index].distance = distance;
1012 collpair[index].flag = 0;
1013
1014 data->collided = true;
1015
1016 /* Compute barycentric coordinates for both collision points. */
1018 verts1[vert_tri_a[0]].tx,
1019 verts1[vert_tri_a[1]].tx,
1020 verts1[vert_tri_a[2]].tx,
1021 &collpair[index].aw1,
1022 &collpair[index].aw2,
1023 &collpair[index].aw3);
1024
1026 collmd->current_xnew[vert_tri_b[0]],
1027 collmd->current_xnew[vert_tri_b[1]],
1028 collmd->current_xnew[vert_tri_b[2]],
1029 &collpair[index].bw1,
1030 &collpair[index].bw2,
1031 &collpair[index].bw3);
1032 }
1033 else {
1034 collpair[index].flag = COLLISION_INACTIVE;
1035 }
1036}
1037
1039 const Cloth *cloth,
1040 const blender::int3 vert_tri_a,
1041 const blender::int3 vert_tri_b)
1042{
1043 const ClothVertex *verts = cloth->verts;
1044
1045 /* Skip when either triangle is excluded. */
1046 const int flags_a = verts[vert_tri_a[0]].flags & verts[vert_tri_a[1]].flags &
1047 verts[vert_tri_a[2]].flags;
1048 const int flags_b = verts[vert_tri_b[0]].flags & verts[vert_tri_b[1]].flags &
1049 verts[vert_tri_b[2]].flags;
1050
1051 if ((flags_a | flags_b) & CLOTH_VERT_FLAG_NOSELFCOLL) {
1052 return false;
1053 }
1054
1055 /* Skip when both triangles are pinned. */
1056 if ((flags_a & flags_b) & CLOTH_VERT_FLAG_PINNED) {
1057 return false;
1058 }
1059
1060 /* Ignore overlap of neighboring triangles and triangles connected by a sewing edge. */
1061 bool sewing_active = (clmd->sim_parms->flags & CLOTH_SIMSETTINGS_FLAG_SEW);
1062
1063 for (uint i = 0; i < 3; i++) {
1064 for (uint j = 0; j < 3; j++) {
1065 if (vert_tri_a[i] == vert_tri_b[j]) {
1066 return false;
1067 }
1068
1069 if (sewing_active) {
1070 if (cloth->sew_edge_graph.contains({vert_tri_a[i], vert_tri_b[j]})) {
1071 return false;
1072 }
1073 }
1074 }
1075 }
1076
1077 return true;
1078}
1079
1080static void cloth_selfcollision(void *__restrict userdata,
1081 const int index,
1082 const TaskParallelTLS *__restrict /*tls*/)
1083{
1084 SelfColDetectData *data = (SelfColDetectData *)userdata;
1085
1086 ClothModifierData *clmd = data->clmd;
1087 CollPair *collpair = data->collisions;
1088 ClothVertex *verts1 = clmd->clothObject->verts;
1089 float distance = 0.0f;
1090 float epsilon = clmd->coll_parms->selfepsilon;
1091 float pa[3], pb[3], vect[3];
1092
1093 /* Collision math is currently not symmetric, so ensure a stable order for each pair. */
1094 int indexA = data->overlap[index].indexA, indexB = data->overlap[index].indexB;
1095
1096 if (indexA > indexB) {
1097 std::swap(indexA, indexB);
1098 }
1099
1100 const blender::int3 vert_tri_a = clmd->clothObject->vert_tris[indexA];
1101 const blender::int3 vert_tri_b = clmd->clothObject->vert_tris[indexB];
1102
1103 BLI_assert(cloth_bvh_selfcollision_is_active(clmd, clmd->clothObject, vert_tri_a, vert_tri_b));
1104
1105 /* Compute distance and normal. */
1106 distance = compute_collision_point_tri_tri(verts1[vert_tri_a[0]].tx,
1107 verts1[vert_tri_a[1]].tx,
1108 verts1[vert_tri_a[2]].tx,
1109 verts1[vert_tri_b[0]].tx,
1110 verts1[vert_tri_b[1]].tx,
1111 verts1[vert_tri_b[2]].tx,
1112 false,
1113 false,
1114 pa,
1115 pb,
1116 vect);
1117
1118 if ((distance <= (epsilon * 2.0f + ALMOST_ZERO)) && (len_squared_v3(vect) > ALMOST_ZERO)) {
1119 collpair[index].ap1 = vert_tri_a[0];
1120 collpair[index].ap2 = vert_tri_a[1];
1121 collpair[index].ap3 = vert_tri_a[2];
1122
1123 collpair[index].bp1 = vert_tri_b[0];
1124 collpair[index].bp2 = vert_tri_b[1];
1125 collpair[index].bp3 = vert_tri_b[2];
1126
1127 copy_v3_v3(collpair[index].pa, pa);
1128 copy_v3_v3(collpair[index].pb, pb);
1129 copy_v3_v3(collpair[index].vector, vect);
1130
1131 normalize_v3_v3(collpair[index].normal, collpair[index].vector);
1132
1133 collpair[index].distance = distance;
1134 collpair[index].flag = 0;
1135
1136 data->collided = true;
1137
1138 /* Compute barycentric coordinates for both collision points. */
1140 verts1[vert_tri_a[0]].tx,
1141 verts1[vert_tri_a[1]].tx,
1142 verts1[vert_tri_a[2]].tx,
1143 &collpair[index].aw1,
1144 &collpair[index].aw2,
1145 &collpair[index].aw3);
1146
1148 verts1[vert_tri_b[0]].tx,
1149 verts1[vert_tri_b[1]].tx,
1150 verts1[vert_tri_b[2]].tx,
1151 &collpair[index].bw1,
1152 &collpair[index].bw2,
1153 &collpair[index].bw3);
1154 }
1155 else {
1156 collpair[index].flag = COLLISION_INACTIVE;
1157 }
1158}
1159
1160static void hair_collision(void *__restrict userdata,
1161 const int index,
1162 const TaskParallelTLS *__restrict /*tls*/)
1163{
1164 ColDetectData *data = (ColDetectData *)userdata;
1165
1166 ClothModifierData *clmd = data->clmd;
1167 CollisionModifierData *collmd = data->collmd;
1168 CollPair *collpair = data->collisions;
1169 ClothVertex *verts1 = clmd->clothObject->verts;
1170 float distance = 0.0f;
1171 float epsilon1 = clmd->coll_parms->epsilon;
1172 float epsilon2 = BLI_bvhtree_get_epsilon(collmd->bvhtree);
1173 float pa[3], pb[3], vect[3];
1174
1175 /* TODO: This is not efficient. Might be wise to instead build an array before iterating, to
1176 * avoid walking the list every time. */
1177 const blender::int2 &edge_coll = reinterpret_cast<const blender::int2 *>(
1178 clmd->clothObject->edges)[data->overlap[index].indexA];
1179 const blender::int3 tri_coll = collmd->vert_tris[data->overlap[index].indexB];
1180
1181 /* Compute distance and normal. */
1182 distance = compute_collision_point_edge_tri(verts1[edge_coll[0]].tx,
1183 verts1[edge_coll[1]].tx,
1184 collmd->current_x[tri_coll[0]],
1185 collmd->current_x[tri_coll[1]],
1186 collmd->current_x[tri_coll[2]],
1187 data->culling,
1188 data->use_normal,
1189 pa,
1190 pb,
1191 vect);
1192
1193 if ((distance <= (epsilon1 + epsilon2 + ALMOST_ZERO)) && (len_squared_v3(vect) > ALMOST_ZERO)) {
1194 collpair[index].ap1 = edge_coll[0];
1195 collpair[index].ap2 = edge_coll[1];
1196
1197 collpair[index].bp1 = tri_coll[0];
1198 collpair[index].bp2 = tri_coll[1];
1199 collpair[index].bp3 = tri_coll[2];
1200
1201 copy_v3_v3(collpair[index].pa, pa);
1202 copy_v3_v3(collpair[index].pb, pb);
1203 copy_v3_v3(collpair[index].vector, vect);
1204
1205 normalize_v3_v3(collpair[index].normal, collpair[index].vector);
1206
1207 collpair[index].distance = distance;
1208 collpair[index].flag = 0;
1209
1210 data->collided = true;
1211
1212 /* Compute barycentric coordinates for the collision points. */
1213 collpair[index].aw2 = line_point_factor_v3(
1214 pa, verts1[edge_coll[0]].tx, verts1[edge_coll[1]].tx);
1215
1216 collpair[index].aw1 = 1.0f - collpair[index].aw2;
1217
1219 collmd->current_xnew[tri_coll[0]],
1220 collmd->current_xnew[tri_coll[1]],
1221 collmd->current_xnew[tri_coll[2]],
1222 &collpair[index].bw1,
1223 &collpair[index].bw2,
1224 &collpair[index].bw3);
1225 }
1226 else {
1227 collpair[index].flag = COLLISION_INACTIVE;
1228 }
1229}
1230
1231static void add_collision_object(ListBase *relations,
1232 Object *ob,
1233 int level,
1234 const ModifierType modifier_type)
1235{
1236 /* only get objects with collision modifier */
1237 ModifierData *cmd = BKE_modifiers_findby_type(ob, modifier_type);
1238
1239 if (cmd) {
1240 CollisionRelation *relation = MEM_cnew<CollisionRelation>(__func__);
1241 relation->ob = ob;
1242 BLI_addtail(relations, relation);
1243 }
1244
1245 /* objects in dupli groups, one level only for now */
1246 /* TODO: this doesn't really work, we are not taking into account the
1247 * dupli transforms and can get objects in the list multiple times. */
1248 if (ob->instance_collection && level == 0) {
1249 Collection *collection = ob->instance_collection;
1250
1251 /* add objects */
1252 FOREACH_COLLECTION_OBJECT_RECURSIVE_BEGIN (collection, object) {
1253 add_collision_object(relations, object, level + 1, modifier_type);
1254 }
1256 }
1257}
1258
1260 Collection *collection,
1261 uint modifier_type)
1262{
1263 const Scene *scene = DEG_get_input_scene(depsgraph);
1265 Base *base = BKE_collection_or_layer_objects(scene, view_layer, collection);
1266 const bool for_render = (DEG_get_mode(depsgraph) == DAG_EVAL_RENDER);
1267 const int base_flag = (for_render) ? BASE_ENABLED_RENDER : BASE_ENABLED_VIEWPORT;
1268
1269 ListBase *relations = MEM_cnew<ListBase>(__func__);
1270
1271 for (; base; base = base->next) {
1272 if (base->flag & base_flag) {
1273 add_collision_object(relations, base->object, 0, ModifierType(modifier_type));
1274 }
1275 }
1276
1277 return relations;
1278}
1279
1281{
1282 if (relations) {
1283 BLI_freelistN(relations);
1284 MEM_freeN(relations);
1285 }
1286}
1287
1289 Object *self,
1290 Collection *collection,
1291 uint *numcollobj,
1292 uint modifier_type)
1293{
1294 ListBase *relations = DEG_get_collision_relations(depsgraph, collection, modifier_type);
1295
1296 if (!relations) {
1297 *numcollobj = 0;
1298 return nullptr;
1299 }
1300
1301 int maxnum = BLI_listbase_count(relations);
1302 int num = 0;
1303 Object **objects = MEM_cnew_array<Object *>(maxnum, __func__);
1304
1305 LISTBASE_FOREACH (CollisionRelation *, relation, relations) {
1306 /* Get evaluated object. */
1307 Object *ob = (Object *)DEG_get_evaluated_id(depsgraph, &relation->ob->id);
1308
1309 if (modifier_type == eModifierType_Collision && !(ob->pd && ob->pd->deflect)) {
1310 continue;
1311 }
1312
1313 if (ob != self) {
1314 objects[num] = ob;
1315 num++;
1316 }
1317 }
1318
1319 if (num == 0) {
1320 MEM_freeN(objects);
1321 objects = nullptr;
1322 }
1323
1324 *numcollobj = num;
1325 return objects;
1326}
1327
1329{
1330 if (objects) {
1331 MEM_freeN(objects);
1332 }
1333}
1334
1336{
1338 depsgraph, collection, eModifierType_Collision);
1339 ListBase *cache = nullptr;
1340
1341 if (!relations) {
1342 return nullptr;
1343 }
1344
1345 LISTBASE_FOREACH (CollisionRelation *, relation, relations) {
1346 /* Get evaluated object. */
1347 Object *ob = (Object *)DEG_get_evaluated_id(depsgraph, &relation->ob->id);
1348
1349 if (ob == self) {
1350 continue;
1351 }
1352
1355 if (cmd && cmd->bvhtree) {
1356 if (cache == nullptr) {
1357 cache = MEM_cnew<ListBase>(__func__);
1358 }
1359
1360 ColliderCache *col = MEM_cnew<ColliderCache>(__func__);
1361 col->ob = ob;
1362 col->collmd = cmd;
1363 /* make sure collider is properly set up */
1364 collision_move_object(cmd, 1.0, 0.0, true);
1365 BLI_addtail(cache, col);
1366 }
1367 }
1368
1369 return cache;
1370}
1371
1373{
1374 if (*colliders) {
1375 BLI_freelistN(*colliders);
1376 MEM_freeN(*colliders);
1377 *colliders = nullptr;
1378 }
1379}
1380
1382 CollisionModifierData *collmd,
1383 CollPair **collisions,
1384 int numresult,
1385 BVHTreeOverlap *overlap,
1386 bool culling,
1387 bool use_normal)
1388{
1389 const bool is_hair = (clmd->hairdata != nullptr);
1390 *collisions = (CollPair *)MEM_mallocN(sizeof(CollPair) * numresult, "collision array");
1391
1392 ColDetectData data{};
1393 data.clmd = clmd;
1394 data.collmd = collmd;
1395 data.overlap = overlap;
1396 data.collisions = *collisions;
1397 data.culling = culling;
1398 data.use_normal = use_normal;
1399 data.collided = false;
1400
1401 TaskParallelSettings settings;
1403 settings.use_threading = true;
1405 0, numresult, &data, is_hair ? hair_collision : cloth_collision, &settings);
1406
1407 return data.collided;
1408}
1409
1411 CollPair *collisions,
1412 int numresult,
1413 BVHTreeOverlap *overlap)
1414{
1415 SelfColDetectData data{};
1416 data.clmd = clmd;
1417 data.overlap = overlap;
1418 data.collisions = collisions;
1419 data.collided = false;
1420
1421 TaskParallelSettings settings;
1423 settings.use_threading = true;
1424 BLI_task_parallel_range(0, numresult, &data, cloth_selfcollision, &settings);
1425
1426 return data.collided;
1427}
1428
1430 Object **collobjs,
1431 CollPair **collisions,
1432 uint *collision_counts,
1433 const uint numcollobj,
1434 const float dt)
1435{
1436 Cloth *cloth = clmd->clothObject;
1437 int i = 0, j = 0, mvert_num = 0;
1438 ClothVertex *verts = nullptr;
1439 int ret = 0;
1440 int result = 0;
1441
1442 mvert_num = clmd->clothObject->mvert_num;
1443 verts = cloth->verts;
1444
1445 result = 1;
1446
1447 for (j = 0; j < 2; j++) {
1448 result = 0;
1449
1450 for (i = 0; i < numcollobj; i++) {
1451 Object *collob = collobjs[i];
1453 collob, eModifierType_Collision);
1454
1455 if (collmd->bvhtree) {
1457 clmd, collmd, collob, collisions[i], collision_counts[i], dt);
1458 }
1459 }
1460
1461 /* Apply impulses in parallel. */
1462 if (result) {
1463 for (i = 0; i < mvert_num; i++) {
1464 // calculate "velocities" (just xnew = xold + v; no dt in v)
1465 if (verts[i].impulse_count) {
1466 add_v3_v3(verts[i].tv, verts[i].impulse);
1467 add_v3_v3(verts[i].dcvel, verts[i].impulse);
1468 zero_v3(verts[i].impulse);
1469 verts[i].impulse_count = 0;
1470
1471 ret++;
1472 }
1473 }
1474 }
1475 else {
1476 break;
1477 }
1478 }
1479 return ret;
1480}
1481
1483 CollPair *collisions,
1484 int collision_count,
1485 const float dt)
1486{
1487 Cloth *cloth = clmd->clothObject;
1488 int i = 0, j = 0, mvert_num = 0;
1489 ClothVertex *verts = nullptr;
1490 int ret = 0;
1491 int result = 0;
1492
1493 mvert_num = clmd->clothObject->mvert_num;
1494 verts = cloth->verts;
1495
1496 for (j = 0; j < 2; j++) {
1497 result = 0;
1498
1499 result += cloth_selfcollision_response_static(clmd, collisions, collision_count, dt);
1500
1501 /* Apply impulses in parallel. */
1502 if (result) {
1503 for (i = 0; i < mvert_num; i++) {
1504 if (verts[i].impulse_count) {
1505 // VECADDMUL ( verts[i].tv, verts[i].impulse, 1.0f / verts[i].impulse_count );
1506 add_v3_v3(verts[i].tv, verts[i].impulse);
1507 add_v3_v3(verts[i].dcvel, verts[i].impulse);
1508 zero_v3(verts[i].impulse);
1509 verts[i].impulse_count = 0;
1510
1511 ret++;
1512 }
1513 }
1514 }
1515
1516 if (!result) {
1517 break;
1518 }
1519 }
1520 return ret;
1521}
1522
1523static bool cloth_bvh_obj_overlap_cb(void *userdata, int index_a, int /*index_b*/, int /*thread*/)
1524{
1525 ClothModifierData *clmd = (ClothModifierData *)userdata;
1526 Cloth *clothObject = clmd->clothObject;
1527 const blender::int3 tri_a = clothObject->vert_tris[index_a];
1528
1529 return cloth_bvh_collision_is_active(clmd, clothObject, tri_a);
1530}
1531
1532static bool cloth_bvh_self_overlap_cb(void *userdata, int index_a, int index_b, int /*thread*/)
1533{
1534 /* This shouldn't happen, but just in case. Note that equal combinations
1535 * (eg. (0,1) & (1,0)) would be filtered out by BLI_bvhtree_overlap_self. */
1536 if (index_a != index_b) {
1537 ClothModifierData *clmd = (ClothModifierData *)userdata;
1538 Cloth *clothObject = clmd->clothObject;
1539 const blender::int3 tri_a = clothObject->vert_tris[index_a];
1540 const blender::int3 tri_b = clothObject->vert_tris[index_b];
1541
1542 if (cloth_bvh_selfcollision_is_active(clmd, clothObject, tri_a, tri_b)) {
1543 return true;
1544 }
1545 }
1546 return false;
1547}
1548
1550 Depsgraph *depsgraph, Object *ob, ClothModifierData *clmd, float step, float dt)
1551{
1552 Cloth *cloth = clmd->clothObject;
1553 BVHTree *cloth_bvh = cloth->bvhtree;
1554 uint i = 0, mvert_num = 0;
1555 int rounds = 0;
1556 ClothVertex *verts = nullptr;
1557 int ret = 0, ret2 = 0;
1558 Object **collobjs = nullptr;
1559 uint numcollobj = 0;
1560 uint *coll_counts_obj = nullptr;
1561 BVHTreeOverlap **overlap_obj = nullptr;
1562 uint coll_count_self = 0;
1563 BVHTreeOverlap *overlap_self = nullptr;
1564 bool bvh_updated = false;
1565
1566 if ((clmd->sim_parms->flags & CLOTH_SIMSETTINGS_FLAG_COLLOBJ) || cloth_bvh == nullptr) {
1567 return 0;
1568 }
1569
1570 verts = cloth->verts;
1571 mvert_num = cloth->mvert_num;
1572
1574 bvhtree_update_from_cloth(clmd, false, false);
1575 bvh_updated = true;
1576
1577 /* Enable self collision if this is a hair sim */
1578 const bool is_hair = (clmd->hairdata != nullptr);
1579
1581 is_hair ? nullptr : ob,
1582 clmd->coll_parms->group,
1583 &numcollobj,
1585
1586 if (collobjs) {
1587 coll_counts_obj = MEM_cnew_array<uint>(numcollobj, "CollCounts");
1588 overlap_obj = MEM_cnew_array<BVHTreeOverlap *>(numcollobj, "BVHOverlap");
1589
1590 for (i = 0; i < numcollobj; i++) {
1591 Object *collob = collobjs[i];
1593 collob, eModifierType_Collision);
1594
1595 if (!collmd->bvhtree) {
1596 continue;
1597 }
1598
1599 /* Move object to position (step) in time. */
1600 collision_move_object(collmd, step + dt, step, false);
1601
1602 overlap_obj[i] = BLI_bvhtree_overlap(cloth_bvh,
1603 collmd->bvhtree,
1604 &coll_counts_obj[i],
1605 is_hair ? nullptr : cloth_bvh_obj_overlap_cb,
1606 clmd);
1607 }
1608 }
1609 }
1610
1612 if (cloth->bvhselftree != cloth->bvhtree || !bvh_updated) {
1613 bvhtree_update_from_cloth(clmd, false, true);
1614 }
1615
1616 overlap_self = BLI_bvhtree_overlap_self(
1617 cloth->bvhselftree, &coll_count_self, cloth_bvh_self_overlap_cb, clmd);
1618 }
1619
1620 do {
1621 ret2 = 0;
1622
1623 /* Object collisions. */
1624 if ((clmd->coll_parms->flags & CLOTH_COLLSETTINGS_FLAG_ENABLED) && collobjs) {
1625 CollPair **collisions;
1626 bool collided = false;
1627
1628 collisions = MEM_cnew_array<CollPair *>(numcollobj, "CollPair");
1629
1630 for (i = 0; i < numcollobj; i++) {
1631 Object *collob = collobjs[i];
1633 collob, eModifierType_Collision);
1634
1635 if (!collmd->bvhtree) {
1636 continue;
1637 }
1638
1639 if (coll_counts_obj[i] && overlap_obj[i]) {
1641 clmd,
1642 collmd,
1643 &collisions[i],
1644 coll_counts_obj[i],
1645 overlap_obj[i],
1646 (collob->pd->flag & PFIELD_CLOTH_USE_CULLING),
1647 (collob->pd->flag & PFIELD_CLOTH_USE_NORMAL)) ||
1648 collided;
1649 }
1650 }
1651
1652 if (collided) {
1654 clmd, collobjs, collisions, coll_counts_obj, numcollobj, dt);
1655 ret2 += ret;
1656 }
1657
1658 for (i = 0; i < numcollobj; i++) {
1659 MEM_SAFE_FREE(collisions[i]);
1660 }
1661
1662 MEM_freeN(collisions);
1663 }
1664
1665 /* Self collisions. */
1667 CollPair *collisions = nullptr;
1668
1669 verts = cloth->verts;
1670 mvert_num = cloth->mvert_num;
1671
1672 if (cloth->bvhselftree) {
1673 if (coll_count_self && overlap_self) {
1674 collisions = (CollPair *)MEM_mallocN(sizeof(CollPair) * coll_count_self,
1675 "collision array");
1676
1677 if (cloth_bvh_selfcollisions_nearcheck(clmd, collisions, coll_count_self, overlap_self))
1678 {
1679 ret += cloth_bvh_selfcollisions_resolve(clmd, collisions, coll_count_self, dt);
1680 ret2 += ret;
1681 }
1682 }
1683 }
1684
1685 MEM_SAFE_FREE(collisions);
1686 }
1687
1688 /* Apply all collision resolution. */
1689 if (ret2) {
1690 for (i = 0; i < mvert_num; i++) {
1691 if (clmd->sim_parms->vgroup_mass > 0) {
1692 if (verts[i].flags & CLOTH_VERT_FLAG_PINNED) {
1693 continue;
1694 }
1695 }
1696
1697 add_v3_v3v3(verts[i].tx, verts[i].txold, verts[i].tv);
1698 }
1699 }
1700
1701 rounds++;
1702 } while (ret2 && (clmd->coll_parms->loop_count > rounds));
1703
1704 if (overlap_obj) {
1705 for (i = 0; i < numcollobj; i++) {
1706 MEM_SAFE_FREE(overlap_obj[i]);
1707 }
1708
1709 MEM_freeN(overlap_obj);
1710 }
1711
1712 MEM_SAFE_FREE(coll_counts_obj);
1713
1714 MEM_SAFE_FREE(overlap_self);
1715
1717
1718 return std::min(ret, 1);
1719}
1720
1721BLI_INLINE void max_v3_v3v3(float r[3], const float a[3], const float b[3])
1722{
1723 r[0] = max_ff(a[0], b[0]);
1724 r[1] = max_ff(a[1], b[1]);
1725 r[2] = max_ff(a[2], b[2]);
1726}
1727
1729 float vel_new[3],
1730 CollisionModifierData *collmd,
1731 CollPair *collpair)
1732{
1733 float u1, u2, u3;
1734
1735 /* compute barycentric coordinates */
1737 collmd->current_x[collpair->bp1],
1738 collmd->current_x[collpair->bp2],
1739 collmd->current_x[collpair->bp3],
1740 &u1,
1741 &u2,
1742 &u3);
1743
1745 collmd->current_v[collpair->bp1],
1746 collmd->current_v[collpair->bp2],
1747 collmd->current_v[collpair->bp3],
1748 u1,
1749 u2,
1750 u3);
1751 /* XXX assume constant velocity of the collider for now */
1752 copy_v3_v3(vel_old, vel_new);
1753}
#define DO_INLINE
Definition BKE_cloth.hh:27
@ CLOTH_VERT_FLAG_PINNED
Definition BKE_cloth.hh:38
@ CLOTH_VERT_FLAG_NOSELFCOLL
Definition BKE_cloth.hh:39
@ CLOTH_VERT_FLAG_NOOBJCOLL
Definition BKE_cloth.hh:40
void bvhtree_update_from_cloth(ClothModifierData *clmd, bool moving, bool self)
Definition cloth.cc:121
#define VECADDMUL(v1, v2, aS)
Definition BKE_cloth.hh:176
#define ALMOST_ZERO
Definition BKE_cloth.hh:34
#define FOREACH_COLLECTION_OBJECT_RECURSIVE_END
Base * BKE_collection_or_layer_objects(const Scene *scene, ViewLayer *view_layer, Collection *collection)
#define FOREACH_COLLECTION_OBJECT_RECURSIVE_BEGIN(_collection, _object)
@ COLLISION_INACTIVE
@ COLLISION_IN_FUTURE
ModifierData * BKE_modifiers_findby_type(const Object *ob, ModifierType type)
#define BLI_assert(a)
Definition BLI_assert.h:50
#define BLI_INLINE
BVHTree * BLI_bvhtree_new(int maxsize, float epsilon, char tree_type, char axis)
void BLI_bvhtree_balance(BVHTree *tree)
void BLI_bvhtree_update_tree(BVHTree *tree)
void BLI_bvhtree_insert(BVHTree *tree, int index, const float co[3], int numpoints)
BVHTreeOverlap * BLI_bvhtree_overlap_self(const BVHTree *tree, unsigned int *r_overlap_num, BVHTree_OverlapCallback callback, void *userdata)
bool BLI_bvhtree_update_node(BVHTree *tree, int index, const float co[3], const float co_moving[3], int numpoints)
float BLI_bvhtree_get_epsilon(const BVHTree *tree)
BVHTreeOverlap * BLI_bvhtree_overlap(const BVHTree *tree1, const BVHTree *tree2, unsigned int *r_overlap_num, BVHTree_OverlapCallback callback, void *userdata)
#define LISTBASE_FOREACH(type, var, list)
void void BLI_freelistN(struct ListBase *listbase) ATTR_NONNULL(1)
Definition listbase.cc:496
void BLI_addtail(struct ListBase *listbase, void *vlink) ATTR_NONNULL(1)
Definition listbase.cc:110
int BLI_listbase_count(const struct ListBase *listbase) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1)
MINLINE float max_ff(float a, float b)
MINLINE float min_ff(float a, float b)
MINLINE float square_f(float a)
bool isect_ray_tri_v3(const float ray_origin[3], const float ray_direction[3], const float v0[3], const float v1[3], const float v2[3], float *r_lambda, float r_uv[2])
void isect_seg_seg_v3(const float a0[3], const float a1[3], const float b0[3], const float b1[3], float r_a[3], float r_b[3])
bool point_in_slice_seg(float p[3], float l1[3], float l2[3])
void closest_on_tri_to_point_v3(float r[3], const float p[3], const float v1[3], const float v2[3], const float v3[3])
bool isect_tri_tri_v3_ex(const float tri_a[3][3], const float tri_b[3][3], float r_i1[3], float r_i2[3], int *r_tri_a_edge_isect_count)
float line_point_factor_v3(const float p[3], const float l1[3], const float l2[3])
float closest_to_line_v3(float r_close[3], const float p[3], const float l1[3], const float l2[3])
bool isect_line_plane_v3(float r_isect_co[3], const float l1[3], const float l2[3], const float plane_co[3], const float plane_no[3]) ATTR_WARN_UNUSED_RESULT
float normal_tri_v3(float n[3], const float v1[3], const float v2[3], const float v3[3])
Definition math_geom.cc:39
bool isect_line_segment_tri_v3(const float p1[3], const float p2[3], const float v0[3], const float v1[3], const float v2[3], float *r_lambda, float r_uv[2])
MINLINE void sub_v3db_v3fl_v3fl(double r[3], const float a[3], const float b[3])
MINLINE float len_squared_v3(const float v[3]) ATTR_WARN_UNUSED_RESULT
MINLINE float len_squared_v3v3(const float a[3], const float b[3]) ATTR_WARN_UNUSED_RESULT
MINLINE void sub_v3_v3v3(float r[3], const float a[3], const float b[3])
MINLINE void mul_v3_fl(float r[3], float f)
MINLINE void copy_v3_v3(float r[3], const float a[3])
MINLINE void negate_v3_v3(float r[3], const float a[3])
MINLINE float dot_v3v3(const float a[3], const float b[3]) ATTR_WARN_UNUSED_RESULT
void interp_v3_v3v3(float r[3], const float a[3], const float b[3], float t)
Definition math_vector.c:36
MINLINE void add_v3_v3v3(float r[3], const float a[3], const float b[3])
MINLINE void cross_v3_v3v3(float r[3], const float a[3], const float b[3])
MINLINE void negate_v3(float r[3])
MINLINE float normalize_v3_v3(float r[3], const float a[3])
MINLINE void madd_v3_v3v3fl(float r[3], const float a[3], const float b[3], float f)
MINLINE void zero_v3(float r[3])
MINLINE void add_v3_v3(float r[3], const float a[3])
MINLINE float normalize_v3(float n[3])
void mid_v3_v3v3v3(float v[3], const float v1[3], const float v2[3], const float v3[3])
MINLINE float len_v3(const float a[3]) ATTR_WARN_UNUSED_RESULT
unsigned int uint
void BLI_task_parallel_range(int start, int stop, void *userdata, TaskParallelRangeFunc func, const TaskParallelSettings *settings)
Definition task_range.cc:99
BLI_INLINE void BLI_parallel_range_settings_defaults(TaskParallelSettings *settings)
Definition BLI_task.h:230
typedef double(DMatrix)[4][4]
@ DAG_EVAL_RENDER
ListBase * DEG_get_collision_relations(const Depsgraph *depsgraph, Collection *collection, unsigned int modifier_type)
eEvaluationMode DEG_get_mode(const Depsgraph *graph)
ViewLayer * DEG_get_input_view_layer(const Depsgraph *graph)
Scene * DEG_get_input_scene(const Depsgraph *graph)
ID * DEG_get_evaluated_id(const Depsgraph *depsgraph, ID *id)
@ CLOTH_COLLSETTINGS_FLAG_ENABLED
@ CLOTH_COLLSETTINGS_FLAG_SELF
@ CLOTH_SIMSETTINGS_FLAG_SEW
@ CLOTH_SIMSETTINGS_FLAG_COLLOBJ
@ BASE_ENABLED_RENDER
@ BASE_ENABLED_VIEWPORT
@ eModifierType_Collision
@ PFIELD_CLOTH_USE_NORMAL
@ PFIELD_CLOTH_USE_CULLING
Object is a sort of wrapper for general info.
Read Guarded memory(de)allocation.
#define MEM_SAFE_FREE(v)
ATTR_WARN_UNUSED_RESULT const BMVert * v2
ATTR_WARN_UNUSED_RESULT const BMVert const BMEdge * e
PyObject * self
#define INPR(v1, v2)
void BKE_collider_cache_free(ListBase **colliders)
Object ** BKE_collision_objects_create(Depsgraph *depsgraph, Object *self, Collection *collection, uint *numcollobj, uint modifier_type)
static void add_collision_object(ListBase *relations, Object *ob, int level, const ModifierType modifier_type)
static int cloth_collision_response_static(ClothModifierData *clmd, CollisionModifierData *collmd, Object *collob, CollPair *collpair, uint collision_count, const float dt)
Definition collision.cc:649
static void cloth_collision(void *__restrict userdata, const int index, const TaskParallelTLS *__restrict)
Definition collision.cc:965
static bool cloth_bvh_selfcollisions_nearcheck(ClothModifierData *clmd, CollPair *collisions, int numresult, BVHTreeOverlap *overlap)
static float compute_collision_point_tri_tri(const float a1[3], const float a2[3], const float a3[3], const float b1[3], const float b2[3], const float b3[3], bool culling, bool use_normal, float r_a[3], float r_b[3], float r_vec[3])
Definition collision.cc:170
BLI_INLINE void max_v3_v3v3(float r[3], const float a[3], const float b[3])
static int cloth_bvh_objcollisions_resolve(ClothModifierData *clmd, Object **collobjs, CollPair **collisions, uint *collision_counts, const uint numcollobj, const float dt)
static bool cloth_bvh_collision_is_active(const ClothModifierData *, const Cloth *cloth, const blender::int3 vert_tri_a)
Definition collision.cc:948
static int cloth_bvh_selfcollisions_resolve(ClothModifierData *clmd, CollPair *collisions, int collision_count, const float dt)
DO_INLINE void collision_interpolateOnTriangle(float to[3], const float v1[3], const float v2[3], const float v3[3], const double w1, const double w2, const double w3)
Definition collision.cc:610
BVHTree * bvhtree_build_from_mvert(const float(*positions)[3], const blender::int3 *vert_tris, int tri_num, float epsilon)
Definition collision.cc:90
static void collision_compute_barycentric(const float pv[3], const float p1[3], const float p2[3], const float p3[3], float *w1, float *w2, float *w3)
Definition collision.cc:557
void BKE_collision_relations_free(ListBase *relations)
ListBase * BKE_collision_relations_create(Depsgraph *depsgraph, Collection *collection, uint modifier_type)
static void cloth_selfcollision(void *__restrict userdata, const int index, const TaskParallelTLS *__restrict)
static void hair_collision(void *__restrict userdata, const int index, const TaskParallelTLS *__restrict)
static bool cloth_bvh_objcollisions_nearcheck(ClothModifierData *clmd, CollisionModifierData *collmd, CollPair **collisions, int numresult, BVHTreeOverlap *overlap, bool culling, bool use_normal)
void collision_get_collider_velocity(float vel_old[3], float vel_new[3], CollisionModifierData *collmd, CollPair *collpair)
void BKE_collision_objects_free(Object **objects)
BLI_INLINE int next_ind(int i)
Definition collision.cc:165
static bool cloth_bvh_obj_overlap_cb(void *userdata, int index_a, int, int)
int cloth_bvh_collision(Depsgraph *depsgraph, Object *ob, ClothModifierData *clmd, float step, float dt)
ListBase * BKE_collider_cache_create(Depsgraph *depsgraph, Object *self, Collection *collection)
static float compute_collision_point_edge_tri(const float a1[3], const float a2[3], const float b1[3], const float b2[3], const float b3[3], bool culling, bool use_normal, float r_a[3], float r_b[3], float r_vec[3])
Definition collision.cc:382
void bvhtree_update_from_mvert(BVHTree *bvhtree, const float(*positions)[3], const float(*positions_moving)[3], const blender::int3 *vert_tris, int tri_num, bool moving)
Definition collision.cc:114
void collision_move_object(CollisionModifierData *collmd, const float step, const float prevstep, const bool moving_bvh)
Definition collision.cc:60
static int cloth_selfcollision_response_static(ClothModifierData *clmd, CollPair *collpair, uint collision_count, const float dt)
Definition collision.cc:797
static bool cloth_bvh_self_overlap_cb(void *userdata, int index_a, int index_b, int)
static void cloth_collision_impulse_vert(const float clamp_sq, const float impulse[3], ClothVertex *vert)
Definition collision.cc:624
static bool cloth_bvh_selfcollision_is_active(const ClothModifierData *clmd, const Cloth *cloth, const blender::int3 vert_tri_a, const blender::int3 vert_tri_b)
local_group_size(16, 16) .push_constant(Type b
const Depsgraph * depsgraph
#define fabsf(x)
#define sqrtf(x)
KDTree_3d * tree
draw_view in_light_buf[] float
static float verts[][3]
uint col
void *(* MEM_mallocN)(size_t len, const char *str)
Definition mallocn.cc:44
void MEM_freeN(void *vmemh)
Definition mallocn.cc:105
ccl_device_inline float2 fabs(const float2 a)
float distance(float a, float b)
return ret
#define FLT_MAX
Definition stdcycles.h:14
struct Base * next
short flag
struct Object * object
struct Collection * group
struct ClothHairData * hairdata
struct Cloth * clothObject
struct ClothSimSettings * sim_parms
struct ClothCollSettings * coll_parms
float impulse[3]
Definition BKE_cloth.hh:103
unsigned int impulse_count
Definition BKE_cloth.hh:106
ClothVertex * verts
Definition BKE_cloth.hh:69
unsigned int mvert_num
Definition BKE_cloth.hh:72
const blender::int2 * edges
Definition BKE_cloth.hh:85
blender::int3 * vert_tris
Definition BKE_cloth.hh:79
CollPair * collisions
Definition collision.cc:43
CollisionModifierData * collmd
Definition collision.cc:41
BVHTreeOverlap * overlap
Definition collision.cc:42
ClothModifierData * clmd
Definition collision.cc:40
float distance
float pb[3]
float normal[3]
struct Object * ob
struct Collection * instance_collection
struct PartDeflect * pd
CollPair * collisions
Definition collision.cc:52
ClothModifierData * clmd
Definition collision.cc:50
BVHTreeOverlap * overlap
Definition collision.cc:51