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