PhysicsBasedAnimationToolkit 0.0.10
Cross-platform C++20 library of algorithms and data structures commonly used in computer graphics research on physically-based simulation.
Loading...
Searching...
No Matches
MultibodyMeshMixedCcdDcd.h
Go to the documentation of this file.
1
11
12#ifndef PBAT_SIM_CONTACT_MULTIBODYMESHMIXEDCCDDCD_H
13#define PBAT_SIM_CONTACT_MULTIBODYMESHMIXEDCCDDCD_H
14
15#include "PhysicsBasedAnimationToolkitExport.h"
16#include "pbat/Aliases.h"
19#include "pbat/geometry/AabbRadixTreeHierarchy.h"
25#include "pbat/math/linalg/mini/Eigen.h"
27
28#include <algorithm>
29#include <utility>
30#include <vector>
31
32namespace pbat::sim::contact {
33
61{
62 public:
63 static auto constexpr kDims = 3;
69
74 {
75 using TriangleVertices = math::linalg::mini::SVector<Index, 3>;
76
80 };
81
85 {
87 math::linalg::mini::SVector<Scalar, 2>;
88 using EdgeVertices = math::linalg::mini::SVector<Index, 2>;
89
96 };
97
116 template <class TDerivedX>
118 Eigen::DenseBase<TDerivedX> const& X,
119 Eigen::Ref<IndexVectorX const> const& V,
120 Eigen::Ref<IndexMatrix<2, Eigen::Dynamic> const> const& E,
121 Eigen::Ref<IndexMatrix<3, Eigen::Dynamic> const> const& F,
122 Eigen::Ref<IndexMatrix<4, Eigen::Dynamic> const> const& T,
123 Eigen::Ref<IndexVectorX const> const& VP,
124 Eigen::Ref<IndexVectorX const> const& EP,
125 Eigen::Ref<IndexVectorX const> const& FP,
126 Eigen::Ref<IndexVectorX const> const& TP);
148 template <
149 class FOnVertexTriangleContactPair,
150 class FOnEdgeEdgeContactPair,
151 class TDerivedXT,
152 class TDerivedX,
153 class TDerivedXK>
154 void UpdateActiveSet(
155 Eigen::DenseBase<TDerivedXT> const& XT,
156 Eigen::DenseBase<TDerivedX> const& X,
157 Eigen::DenseBase<TDerivedXK> const& XK,
158 FOnVertexTriangleContactPair&& fOnVertexTriangleContactPair,
159 FOnEdgeEdgeContactPair&& fOnEdgeEdgeContactPair);
169 template <class FOnVertexTriangleContactPair, class TDerivedX>
171 Eigen::DenseBase<TDerivedX> const& X,
172 FOnVertexTriangleContactPair&& fOnVertexTriangleContactPair);
186 template <
187 class FOnVertexTriangleContactPair,
188 class FOnEdgeEdgeContactPair,
189 class TDerivedXT,
190 class TDerivedX>
192 Eigen::DenseBase<TDerivedXT> const& XT,
193 Eigen::DenseBase<TDerivedX> const& X,
194 FOnVertexTriangleContactPair&& fOnVertexTriangleContactPair,
195 FOnEdgeEdgeContactPair&& fOnEdgeEdgeContactPair);
196
203 [[maybe_unused]] auto const& GetBodyAabbs() const { return mBodyAabbs; }
210 [[maybe_unused]] auto const& GetVertexAabbs() const { return mVertexAabbs; }
217 [[maybe_unused]] auto const& GetEdgeAabbs() const { return mEdgeAabbs; }
224 [[maybe_unused]] auto const& GetTriangleAabbs() const { return mTriangleAabbs; }
231 [[maybe_unused]] auto const& GetTetrahedronAabbs() const { return mTetrahedronAabbs; }
232
239 template <class TDerivedX>
240 void ComputeVertexAabbs(Eigen::DenseBase<TDerivedX> const& X);
248 template <class TDerivedXT, class TDerivedX>
250 Eigen::DenseBase<TDerivedXT> const& XT,
251 Eigen::DenseBase<TDerivedX> const& X);
258 template <class TDerivedXT, class TDerivedX>
259 void
260 ComputeEdgeAabbs(Eigen::DenseBase<TDerivedXT> const& XT, Eigen::DenseBase<TDerivedX> const& X);
266 template <class TDerivedX>
267 void ComputeTriangleAabbs(Eigen::DenseBase<TDerivedX> const& X);
274 template <class TDerivedXT, class TDerivedX>
276 Eigen::DenseBase<TDerivedXT> const& XT,
277 Eigen::DenseBase<TDerivedX> const& X);
278
282
288 template <class TDerivedX>
289 void ComputeTetrahedronAabbs(Eigen::DenseBase<TDerivedX> const& X);
295 PBAT_API void ComputeBodyAabbs();
299 PBAT_API void UpdateMeshVertexBvhs();
303 PBAT_API void UpdateMeshEdgeBvhs();
307 PBAT_API void UpdateMeshTriangleBvhs();
311 PBAT_API void UpdateMeshTetrahedronBvhs();
315 PBAT_API void RecomputeBodyBvh();
323 template <class FOnBodyPair>
324 void ForEachBodyPair(FOnBodyPair&& fOnBodyPair) const;
334 template <class FOnPenetratingVertex, class TDerivedX>
336 Eigen::DenseBase<TDerivedX> const& X,
337 FOnPenetratingVertex&& fOnPenetratingVertex);
342 [[maybe_unused]] auto VertexCount() const { return mVertexAabbs.cols(); }
347 [[maybe_unused]] auto EdgeCount() const { return mEdgeAabbs.cols(); }
352 [[maybe_unused]] auto TriangleCount() const { return mTriangleAabbs.cols(); }
357 [[maybe_unused]] auto TetrahedronCount() const { return mTetrahedronAabbs.cols(); }
362 [[maybe_unused]] auto BodyCount() const { return mBodyAabbs.cols(); }
363
364 protected:
374 template <class FOnVertexTriangleContactPair, class TDerivedX>
375 void HandleDcdPairs(
376 Eigen::DenseBase<TDerivedX> const& X,
377 FOnVertexTriangleContactPair&& fOnVertexTriangleContactPair);
394 template <
395 class FOnVertexTriangleContactPair,
396 class FOnEdgeEdgeContactPair,
397 class TDerivedXT,
398 class TDerivedX>
399 void HandleCcdPairs(
400 Eigen::DenseBase<TDerivedXT> const& XT,
401 Eigen::DenseBase<TDerivedX> const& X,
402 FOnVertexTriangleContactPair&& fOnVertexTriangleContactPair,
403 FOnEdgeEdgeContactPair&& fOnEdgeEdgeContactPair);
416 template <class FOnVertexTriangleContactPair, class TDerivedXT, class TDerivedX>
418 Eigen::DenseBase<TDerivedXT> const& XT,
419 Eigen::DenseBase<TDerivedX> const& X,
420 Index oi,
421 Index oj,
422 FOnVertexTriangleContactPair fOnVertexTriangleContactPair) const;
435 template <class FOnEdgeEdgeContactPair, class TDerivedXT, class TDerivedX>
437 Eigen::DenseBase<TDerivedXT> const& XT,
438 Eigen::DenseBase<TDerivedX> const& X,
439 Index oi,
440 Index oj,
441 FOnEdgeEdgeContactPair&& fOnEdgeEdgeContactPair) const;
442
443 private:
447
448 Eigen::Ref<IndexVectorX const>
449 mVP;
450 Eigen::Ref<IndexVectorX const> mEP;
451 Eigen::Ref<IndexVectorX const>
452 mFP;
453 Eigen::Ref<IndexVectorX const>
454 mTP;
455
459
460 Eigen::Ref<IndexVectorX const>
461 mV;
462 Eigen::Ref<IndexMatrix<2, Eigen::Dynamic> const>
463 mE;
464 Eigen::Ref<IndexMatrix<3, Eigen::Dynamic> const>
465 mF;
466 Eigen::Ref<IndexMatrix<4, Eigen::Dynamic> const>
467 mT;
468
472
478 mTriangleAabbs;
481 mTetrahedronAabbs;
483
487
488 std::vector<VertexBvh> mVertexBvhs;
489 std::vector<EdgeBvh> mEdgeBvhs;
490 std::vector<TriangleBvh> mTriangleBvhs;
491 std::vector<TetrahedronBvh> mTetrahedronBvhs;
492
496
498 mBodyAabbs;
499 BodyBvh mBodyBvh;
500
501 Eigen::Vector<bool, Eigen::Dynamic> mPenetratingVertexMask;
502};
503
504template <class TDerivedX>
506 Eigen::DenseBase<TDerivedX> const& X,
507 Eigen::Ref<IndexVectorX const> const& V,
508 Eigen::Ref<IndexMatrix<2, Eigen::Dynamic> const> const& E,
509 Eigen::Ref<IndexMatrix<3, Eigen::Dynamic> const> const& F,
510 Eigen::Ref<IndexMatrix<4, Eigen::Dynamic> const> const& T,
511 Eigen::Ref<IndexVectorX const> const& VP,
512 Eigen::Ref<IndexVectorX const> const& EP,
513 Eigen::Ref<IndexVectorX const> const& FP,
514 Eigen::Ref<IndexVectorX const> const& TP)
515 : mVP(VP), mEP(EP), mFP(FP), mTP(TP), mV(V), mE(E), mF(F), mT(T)
516{
517 PBAT_PROFILE_NAMED_SCOPE("pbat.sim.contact.MultibodyMeshMixedCcdDcd.Construct");
518#include "pbat/warning/Push.h"
519#include "pbat/warning/SignConversion.h"
520 // Allocate memory for AABBs and active sets
521 mVertexAabbs.resize(2 * kDims, V.size());
522 mEdgeAabbs.resize(2 * kDims, E.cols());
523 mTriangleAabbs.resize(2 * kDims, F.cols());
524 mTetrahedronAabbs.resize(2 * kDims, T.cols());
525 mBodyAabbs.resize(2 * kDims, VP.size() - 1);
526 mPenetratingVertexMask.resize(X.cols());
527 mPenetratingVertexMask.setConstant(false);
528 // Allocate memory for mesh BVHs
529 auto const nObjects = mVP.size() - 1;
530 mVertexBvhs.resize(nObjects);
531 mEdgeBvhs.resize(nObjects);
532 mTriangleBvhs.resize(nObjects);
533 mTetrahedronBvhs.resize(nObjects);
534 // Compute static mesh primitive AABBs for tree construction
535 ComputeVertexAabbs(X.derived());
536 ComputeEdgeAabbs(X.derived(), X.derived());
537 ComputeTriangleAabbs(X.derived());
538 ComputeTetrahedronAabbs(X.derived());
539 // Construct mesh BVHs
540 for (auto o = 0; o < nObjects; ++o)
541 {
542 auto VB = mVertexAabbs(Eigen::placeholders::all, Eigen::seq(mVP(o), mVP(o + 1) - 1));
543 auto EB = mEdgeAabbs(Eigen::placeholders::all, Eigen::seq(mEP(o), mEP(o + 1) - 1));
544 auto FB = mTriangleAabbs(Eigen::placeholders::all, Eigen::seq(mFP(o), mFP(o + 1) - 1));
545 auto TB = mTetrahedronAabbs(Eigen::placeholders::all, Eigen::seq(mTP(o), mTP(o + 1) - 1));
546 // Construct object o's mesh BVH tree topology
547 mVertexBvhs[o].Construct(VB.topRows<kDims>(), VB.bottomRows<kDims>());
548 mEdgeBvhs[o].Construct(EB.topRows<kDims>(), EB.bottomRows<kDims>());
549 mTriangleBvhs[o].Construct(FB.topRows<kDims>(), FB.bottomRows<kDims>());
550 mTetrahedronBvhs[o].Construct(TB.topRows<kDims>(), TB.bottomRows<kDims>());
551 // Compute object o's AABB
552 auto XVo = X(Eigen::placeholders::all, mV(Eigen::seq(mVP(o), mVP(o + 1) - 1)));
553 mBodyAabbs.col(o).head<kDims>() = XVo.rowwise().minCoeff();
554 mBodyAabbs.col(o).tail<kDims>() = XVo.rowwise().maxCoeff();
555 }
556 // Construct body BVH to allocate memory
557 mBodyBvh.Construct(mBodyAabbs.topRows<kDims>(), mBodyAabbs.bottomRows<kDims>());
558#include "pbat/warning/Pop.h"
559}
560
561template <
562 class FOnVertexTriangleContactPair,
563 class FOnEdgeEdgeContactPair,
564 class TDerivedXT,
565 class TDerivedX,
566 class TDerivedXK>
568 Eigen::DenseBase<TDerivedXT> const& XT,
569 Eigen::DenseBase<TDerivedX> const& X,
570 Eigen::DenseBase<TDerivedXK> const& XK,
571 FOnVertexTriangleContactPair&& fOnVertexTriangleContactPair,
572 FOnEdgeEdgeContactPair&& fOnEdgeEdgeContactPair)
573{
574 PBAT_PROFILE_NAMED_SCOPE("pbat.sim.contact.MultibodyMeshMixedCcdDcd.UpdateActiveSet");
576 XK,
577 std::forward<FOnVertexTriangleContactPair>(fOnVertexTriangleContactPair));
579 XT,
580 X,
581 std::forward<FOnVertexTriangleContactPair>(fOnVertexTriangleContactPair),
582 std::forward<FOnEdgeEdgeContactPair>(fOnEdgeEdgeContactPair));
583}
584
585template <class FOnVertexTriangleContactPair, class TDerivedX>
587 Eigen::DenseBase<TDerivedX> const& X,
588 FOnVertexTriangleContactPair&& fOnVertexTriangleContactPair)
589{
590 PBAT_PROFILE_NAMED_SCOPE("pbat.sim.contact.MultibodyMeshMixedCcdDcd.UpdateDcdActiveSet");
591 // Update AABBs for discrete collision detection
595 // Update BVH bounding boxes
599 // Rebuild world tree
602 // Add DCD vertex-triangle pairs to active set
603 HandleDcdPairs(X, std::forward<FOnVertexTriangleContactPair>(fOnVertexTriangleContactPair));
604}
605
606template <
607 class FOnVertexTriangleContactPair,
608 class FOnEdgeEdgeContactPair,
609 class TDerivedXT,
610 class TDerivedX>
612 Eigen::DenseBase<TDerivedXT> const& XT,
613 Eigen::DenseBase<TDerivedX> const& X,
614 FOnVertexTriangleContactPair&& fOnVertexTriangleContactPair,
615 FOnEdgeEdgeContactPair&& fOnEdgeEdgeContactPair)
616{
617 PBAT_PROFILE_NAMED_SCOPE("pbat.sim.contact.MultibodyMeshMixedCcdDcd.UpdateCcdActiveSet");
618 // Compute AABBs for linearly swept vertices, edges and triangles
619 ComputeVertexAabbs(XT, X);
620 ComputeEdgeAabbs(XT, X);
622 // Update BVHs
626 // Rebuild world tree
629 // Report all vertex-triangle and edge-edge CCD contacts
631 XT,
632 X,
633 std::forward<FOnVertexTriangleContactPair>(fOnVertexTriangleContactPair),
634 std::forward<FOnEdgeEdgeContactPair>(fOnEdgeEdgeContactPair));
635}
636
637template <class TDerivedX>
638inline void MultibodyMeshMixedCcdDcd::ComputeVertexAabbs(Eigen::DenseBase<TDerivedX> const& X)
639{
640 PBAT_PROFILE_NAMED_SCOPE("pbat.sim.contact.MultibodyMeshMixedCcdDcd.ComputeVertexAabbs");
641 auto XV = X(Eigen::placeholders::all, mV);
642 mVertexAabbs.topRows<kDims>() = XV;
643 mVertexAabbs.bottomRows<kDims>() = XV;
644}
645
646template <class TDerivedXT, class TDerivedX>
648 Eigen::DenseBase<TDerivedXT> const& XT,
649 Eigen::DenseBase<TDerivedX> const& X)
650{
651 PBAT_PROFILE_NAMED_SCOPE("pbat.sim.contact.MultibodyMeshMixedCcdDcd.ComputeVertexAabbs");
652 auto XTV = XT.template topRows<kDims>()(Eigen::placeholders::all, mV);
653 auto XV = X.template topRows<kDims>()(Eigen::placeholders::all, mV);
654 for (auto v = 0; v < mV.cols(); ++v)
655 {
656 auto i = mV(v);
657 auto L = mVertexAabbs.col(v).head<kDims>();
658 auto U = mVertexAabbs.col(v).tail<kDims>();
659 L = XTV.col(i).cwiseMin(XV.col(i));
660 U = XTV.col(i).cwiseMin(XV.col(i));
661 }
662}
663
664template <class TDerivedXT, class TDerivedX>
666 Eigen::DenseBase<TDerivedXT> const& XT,
667 Eigen::DenseBase<TDerivedX> const& X)
668{
669 PBAT_PROFILE_NAMED_SCOPE("pbat.sim.contact.MultibodyMeshMixedCcdDcd.ComputeEdgeAabbs");
670 for (auto e = 0; e < mE.cols(); ++e)
671 {
673 XE.leftCols<2>() = XT(Eigen::placeholders::all, mE.col(e)).template block<kDims, 2>(0, 0);
674 XE.rightCols<2>() = X(Eigen::placeholders::all, mE.col(e)).template block<kDims, 2>(0, 0);
675 auto L = mEdgeAabbs.col(e).head<kDims>();
676 auto U = mEdgeAabbs.col(e).tail<kDims>();
677 L = XE.rowwise().minCoeff();
678 U = XE.rowwise().maxCoeff();
679 }
680}
681
682template <class TDerivedX>
683inline void MultibodyMeshMixedCcdDcd::ComputeTriangleAabbs(Eigen::DenseBase<TDerivedX> const& X)
684{
685 PBAT_PROFILE_NAMED_SCOPE("pbat.sim.contact.MultibodyMeshMixedCcdDcd.ComputeTriangleAabbs");
686#include "pbat/warning/Push.h"
687#include "pbat/warning/SignConversion.h"
688 for (auto f = 0; f < mF.cols(); ++f)
689 {
691 XF = X(Eigen::placeholders::all, mF.col(f)).template block<kDims, 3>(0, 0);
692 auto L = mTriangleAabbs.col(f).head<kDims>();
693 auto U = mTriangleAabbs.col(f).tail<kDims>();
694 L = XF.rowwise().minCoeff();
695 U = XF.rowwise().maxCoeff();
696 }
697#include "pbat/warning/Pop.h"
698}
699
700template <class TDerivedXT, class TDerivedX>
702 Eigen::DenseBase<TDerivedXT> const& XT,
703 Eigen::DenseBase<TDerivedX> const& X)
704{
705 PBAT_PROFILE_NAMED_SCOPE("pbat.sim.contact.MultibodyMeshMixedCcdDcd.ComputeTriangleAabbs");
706 for (auto f = 0; f < mF.cols(); ++f)
707 {
709 XF.leftCols<3>() = XT(Eigen::placeholders::all, mF.col(f)).template block<kDims, 3>(0, 0);
710 XF.rightCols<3>() = X(Eigen::placeholders::all, mF.col(f)).template block<kDims, 3>(0, 0);
711 auto L = mTriangleAabbs.col(f).head<kDims>();
712 auto U = mTriangleAabbs.col(f).tail<kDims>();
713 L = XF.rowwise().minCoeff();
714 U = XF.rowwise().maxCoeff();
715 }
716}
717
718template <class TDerivedX>
719inline void MultibodyMeshMixedCcdDcd::ComputeTetrahedronAabbs(Eigen::DenseBase<TDerivedX> const& X)
720{
721 PBAT_PROFILE_NAMED_SCOPE("pbat.sim.contact.MultibodyMeshMixedCcdDcd.ComputeTetrahedronAabbs");
722 for (auto t = 0; t < mT.cols(); ++t)
723 {
724 Matrix<kDims, 4> XT = X(Eigen::placeholders::all, mT.col(t)).template block<kDims, 4>(0, 0);
725 auto L = mTetrahedronAabbs.col(t).template head<kDims>();
726 auto U = mTetrahedronAabbs.col(t).template tail<kDims>();
727 L = XT.rowwise().minCoeff();
728 U = XT.rowwise().maxCoeff();
729 }
730}
731
732template <class FOnBodyPair>
733inline void MultibodyMeshMixedCcdDcd::ForEachBodyPair(FOnBodyPair&& fOnBodyPair) const
734{
735 PBAT_PROFILE_NAMED_SCOPE("pbat.sim.contact.MultibodyMeshMixedCcdDcd.ForEachBodyPair");
736 mBodyBvh.SelfOverlaps(
737 [&](Index o1, Index o2) {
738 using math::linalg::mini::FromEigen;
739 auto L1 = mBodyAabbs.col(o1).template head<kDims>();
740 auto U1 = mBodyAabbs.col(o1).template tail<kDims>();
741 auto L2 = mBodyAabbs.col(o2).template head<kDims>();
742 auto U2 = mBodyAabbs.col(o2).template tail<kDims>();
744 FromEigen(L1),
745 FromEigen(U1),
746 FromEigen(L2),
747 FromEigen(U2));
748 },
749 [fOnBodyPair = std::forward<FOnBodyPair>(
750 fOnBodyPair)](Index oi, Index oj, [[maybe_unused]] Index k) { fOnBodyPair(oi, oj); });
751}
752
753template <class FOnPenetratingVertex, class TDerivedX>
755 Eigen::DenseBase<TDerivedX> const& X,
756 FOnPenetratingVertex&& fOnPenetratingVertex)
757{
758 PBAT_PROFILE_NAMED_SCOPE("pbat.sim.contact.MultibodyMeshMixedCcdDcd.ForEachPenetratingVertex");
759 auto const fVisitPenetratingVerticesOf =
760 [&,
761 fOnPenetratingVertex =
762 std::forward<FOnPenetratingVertex>(fOnPenetratingVertex)](Index oi, Index oj) {
763 Index i;
764 Vector<kDims> xi;
765 mVertexBvhs[static_cast<std::size_t>(oi)].Overlaps(
766 mTetrahedronBvhs[static_cast<std::size_t>(oj)],
767 [&](Index v, Index t) {
768 // Global vertex and tetrahedron indices
769 v = mVP(oi) + v;
770 t = mTP(oj) + t;
771 i = mV(v);
772 // Skip test, if we already know this vertex is penetrating
773 if (mPenetratingVertexMask[i])
774 return false;
775 // Run overlap test
776 xi = X.col(i);
777 IndexVector<4> tinds = mT.col(t);
778 Matrix<kDims, 4> XT = X(Eigen::placeholders::all, tinds);
779 using math::linalg::mini::FromEigen;
780 // Mark vertex as penetrating so that it doesn't participate in CCD
781 bool const bIsPenetrating = geometry::OverlapQueries::PointTetrahedron3D(
782 FromEigen(xi),
783 FromEigen(XT.col(0)),
784 FromEigen(XT.col(1)),
785 FromEigen(XT.col(2)),
786 FromEigen(XT.col(3)));
787 // Cache vertex penetrating status if applicable
788 if (bIsPenetrating)
789 mPenetratingVertexMask[i] = true;
790 return bIsPenetrating;
791 },
792 [&]([[maybe_unused]] Index v, [[maybe_unused]] Index t, [[maybe_unused]] Index k) {
793 fOnPenetratingVertex(i, oj);
794 });
795 };
796 // Reset penetrating vertex mask
797 mPenetratingVertexMask.setConstant(false);
798 // Only check for relevant body pairs where vertices may penetrate
799 ForEachBodyPair([&](Index oi, Index oj) {
800 fVisitPenetratingVerticesOf(oi, oj);
801 fVisitPenetratingVerticesOf(oj, oi);
802 });
803}
804
805template <class FOnVertexTriangleContactPair, class TDerivedX>
807 Eigen::DenseBase<TDerivedX> const& X,
808 FOnVertexTriangleContactPair&& fOnVertexTriangleContactPair)
809{
810#include "pbat/warning/Push.h"
811#include "pbat/warning/SignConversion.h"
812 PBAT_PROFILE_NAMED_SCOPE("pbat.sim.contact.MultibodyMeshMixedCcdDcd.HandleDcdPairs");
813 // Report vertex-triangle contacts for each DCD penetrating vertex
814 ForEachPenetratingVertex(X.derived(), [&](Index i, Index o) {
815 // Contact point is vertex position
816 Vector<kDims> const XC = X.col(i);
817 // Define point-aabb and point-triangle distance functions for vertex i
818 auto const fDistanceToBox = [&]<class TL, class TU>(TL const& L, TU const& U) {
819 using math::linalg::mini::FromEigen;
820 return geometry::DistanceQueries::PointAxisAlignedBoundingBox(
821 FromEigen(XC),
822 FromEigen(L),
823 FromEigen(U));
824 };
825 auto const fDistanceToTriangle = [&](Index f) {
826 using math::linalg::mini::FromEigen;
827 Matrix<kDims, 3> XF = X(Eigen::placeholders::all, mF.col(f));
828 return geometry::DistanceQueries::PointTriangle(
829 FromEigen(XC),
830 FromEigen(XF.col(0)),
831 FromEigen(XF.col(1)),
832 FromEigen(XF.col(2)));
833 };
834 // Find nearest surface point (i.e. triangle)
835 mTriangleBvhs[o].NearestNeighbours(
836 fDistanceToBox,
837 fDistanceToTriangle,
838 [&, fReport = std::forward<FOnVertexTriangleContactPair>(fOnVertexTriangleContactPair)](
839 Index f,
840 [[maybe_unused]] Scalar d,
841 [[maybe_unused]] Index k) {
842 using math::linalg::mini::FromEigen;
843 f = mFP(o) + f;
844 fReport(VertexTriangleContact{i, f, FromEigen(mF.col(f))});
845 });
846 });
847#include "pbat/warning/Pop.h"
848}
849
850template <
851 class FOnVertexTriangleContactPair,
852 class FOnEdgeEdgeContactPair,
853 class TDerivedXT,
854 class TDerivedX>
856 Eigen::DenseBase<TDerivedXT> const& XT,
857 Eigen::DenseBase<TDerivedX> const& X,
858 FOnVertexTriangleContactPair&& fOnVertexTriangleContactPair,
859 FOnEdgeEdgeContactPair&& fOnEdgeEdgeContactPair)
860{
861 PBAT_PROFILE_NAMED_SCOPE("pbat.sim.contact.MultibodyMeshMixedCcdDcd.HandleCcdPairs");
862 ForEachBodyPair([&](Index oi, Index oj) {
864 XT,
865 X,
866 oi,
867 oj,
868 std::forward<FOnVertexTriangleContactPair>(fOnVertexTriangleContactPair));
870 XT,
871 X,
872 oj,
873 oi,
874 std::forward<FOnVertexTriangleContactPair>(fOnVertexTriangleContactPair));
876 XT,
877 X,
878 oi,
879 oj,
880 std::forward<FOnEdgeEdgeContactPair>(fOnEdgeEdgeContactPair));
881 });
882}
883
884template <class FOnVertexTriangleContactPair, class TDerivedXT, class TDerivedX>
886 Eigen::DenseBase<TDerivedXT> const& XT,
887 Eigen::DenseBase<TDerivedX> const& X,
888 Index oi,
889 Index oj,
890 FOnVertexTriangleContactPair fOnVertexTriangleContactPair) const
891{
892 PBAT_PROFILE_NAMED_SCOPE(
893 "pbat.sim.contact.MultibodyMeshMixedCcdDcd.ReportVertexTriangleCcdContacts");
894 mVertexBvhs[static_cast<std::size_t>(oi)].Overlaps(
895 mTriangleBvhs[static_cast<std::size_t>(oj)],
896 [&,
897 fOnVertexTriangleContactPair = std::forward<FOnVertexTriangleContactPair>(
898 fOnVertexTriangleContactPair)](Index v, Index f) {
899 // Global vertex and triangle indices
900 v = mVP(oi) + v;
901 f = mFP(oj) + f;
902 Index i = mV(v);
903 if (mPenetratingVertexMask[i])
904 return false;
905 // Run inexact CCD
906 Vector<kDims> XTV = XT.col(i);
907 Vector<kDims> XV = X.col(i);
908 IndexVector<kDims> finds = mF.col(f);
909 Matrix<kDims, 3> XTF = XT(Eigen::placeholders::all, finds);
910 Matrix<kDims, 3> XF = X(Eigen::placeholders::all, finds);
911 using namespace math::linalg::mini;
912 SVector<Scalar, 4> tbeta = geometry::PointTriangleCcd(
913 FromEigen(XTV),
914 FromEigen(XTF.col(0)),
915 FromEigen(XTF.col(1)),
916 FromEigen(XTF.col(2)),
917 FromEigen(XV),
918 FromEigen(XF.col(0)),
919 FromEigen(XF.col(1)),
920 FromEigen(XF.col(2)));
921 // Report if contact found
922 auto const t = tbeta[0];
923 bool const bIntersects = t >= Scalar(0);
924 if (bIntersects)
925 {
926 // Report contact to caller
927 fOnVertexTriangleContactPair(VertexTriangleContact{i, f, FromEigen(finds)});
928 }
929 return bIntersects;
930 },
931 [](auto, auto, auto) {});
932}
933
934template <class FOnEdgeEdgeContactPair, class TDerivedXT, class TDerivedX>
936 Eigen::DenseBase<TDerivedXT> const& XT,
937 Eigen::DenseBase<TDerivedX> const& X,
938 Index oi,
939 Index oj,
940 FOnEdgeEdgeContactPair&& fOnEdgeEdgeContactPair) const
941{
942 PBAT_PROFILE_NAMED_SCOPE("pbat.sim.contact.MultibodyMeshMixedCcdDcd.ReportEdgeEdgeCcdContacts");
943 mEdgeBvhs[static_cast<std::size_t>(oi)].Overlaps(
944 mEdgeBvhs[static_cast<std::size_t>(oj)],
945 [&,
946 fOnEdgeEdgeContactPair =
947 std::forward<FOnEdgeEdgeContactPair>(fOnEdgeEdgeContactPair)](Index ei, Index ej) {
948 // Global edge indices
949 ei = mEP(oi) + ei;
950 ej = mEP(oj) + ej;
951 // Global edge vertex indices
952 IndexVector<2> eindsi = mE.col(ei);
953 IndexVector<2> eindsj = mE.col(ej);
954 // Do not report contact if any vertex is already penetrating
955 if (mPenetratingVertexMask[eindsi[0]] or mPenetratingVertexMask[eindsi[1]] or
956 mPenetratingVertexMask[eindsj[0]] or mPenetratingVertexMask[eindsj[1]])
957 return false;
958 // Run inexact CCD
959 Matrix<kDims, 2> XTei = XT(Eigen::placeholders::all, eindsi);
960 Matrix<kDims, 2> Xei = X(Eigen::placeholders::all, eindsi);
961 Matrix<kDims, 2> XTej = XT(Eigen::placeholders::all, eindsj);
962 Matrix<kDims, 2> Xej = X(Eigen::placeholders::all, eindsj);
963 using namespace math::linalg::mini;
964 SVector<Scalar, 3> tbeta = geometry::EdgeEdgeCcd(
965 FromEigen(XTei.col(0)),
966 FromEigen(XTei.col(1)),
967 FromEigen(XTej.col(0)),
968 FromEigen(XTej.col(1)),
969 FromEigen(Xei.col(0)),
970 FromEigen(Xei.col(1)),
971 FromEigen(Xej.col(0)),
972 FromEigen(Xej.col(1)));
973 // Report if contact found
974 auto const t = tbeta[0];
975 bool const bIntersects = t >= Scalar(0);
976 if (bIntersects)
977 {
978 auto uv = tbeta.Slice<2, 1>(1, 0);
979 fOnEdgeEdgeContactPair(
980 EdgeEdgeContact{ei, ej, FromEigen(eindsi), FromEigen(eindsj), uv});
981 }
982 return bIntersects;
983 },
984 [](auto, auto, auto) {});
985}
986
987} // namespace pbat::sim::contact
988
989#endif // PBAT_SIM_CONTACT_MULTIBODYMESHMIXEDCCDDCD_H
BVH over axis-aligned bounding boxes using a k-D tree.
Counting sort.
This file contains functions to answer distance queries.
Edge-edge continuous collision detection (CCD) implementation.
This file contains functions to answer intersection queries.
This file contains functions to answer overlap queries.
Point-triangle continuous collision detection (CCD) implementation.
Axis-aligned k-D tree hierarchy of axis-aligned bounding boxes.
Definition AabbKdTreeHierarchy.h:40
Axis-aligned radix tree hierarchy of axis-aligned bounding boxes.
Definition AabbRadixTreeHierarchy.h:35
void UpdateActiveSet(Eigen::DenseBase< TDerivedXT > const &XT, Eigen::DenseBase< TDerivedX > const &X, Eigen::DenseBase< TDerivedXK > const &XK, FOnVertexTriangleContactPair &&fOnVertexTriangleContactPair, FOnEdgeEdgeContactPair &&fOnEdgeEdgeContactPair)
Update the active set of vertex-triangle and edge-edge contact pairs.
Definition MultibodyMeshMixedCcdDcd.h:567
static auto constexpr kDims
Number of spatial dimensions.
Definition MultibodyMeshMixedCcdDcd.h:63
void HandleDcdPairs(Eigen::DenseBase< TDerivedX > const &X, FOnVertexTriangleContactPair &&fOnVertexTriangleContactPair)
Report DCD vertex-triangle contacts.
Definition MultibodyMeshMixedCcdDcd.h:806
void ComputeVertexAabbs(Eigen::DenseBase< TDerivedX > const &X)
Compute axis-aligned bounding boxes for vertices.
Definition MultibodyMeshMixedCcdDcd.h:638
auto TetrahedronCount() const
Number of tetrahedra in the mesh system.
Definition MultibodyMeshMixedCcdDcd.h:357
void HandleCcdPairs(Eigen::DenseBase< TDerivedXT > const &XT, Eigen::DenseBase< TDerivedX > const &X, FOnVertexTriangleContactPair &&fOnVertexTriangleContactPair, FOnEdgeEdgeContactPair &&fOnEdgeEdgeContactPair)
Report CCD (inactive) vertex-triangle and edge-edge pairs.
Definition MultibodyMeshMixedCcdDcd.h:855
void ComputeTetrahedronAabbs(Eigen::DenseBase< TDerivedX > const &X)
We make AABB and BVH computation public for debugging purposes.
Definition MultibodyMeshMixedCcdDcd.h:719
PBAT_API void ComputeBodyAabbs()
Computes body AABBs from mesh vertex BVHs.
Definition MultibodyMeshMixedCcdDcd.cpp:5
auto const & GetVertexAabbs() const
Get the vertex Aabbs of this scene. This is mostly useful for debugging.
Definition MultibodyMeshMixedCcdDcd.h:210
geometry::AabbKdTreeHierarchy< kDims > TetrahedronBvh
BVH over mesh tetrahedra.
Definition MultibodyMeshMixedCcdDcd.h:68
PBAT_API void UpdateMeshTriangleBvhs()
Recompute mesh triangle BVH bounding boxes.
Definition MultibodyMeshMixedCcdDcd.cpp:51
geometry::AabbKdTreeHierarchy< kDims > TriangleBvh
BVH over mesh triangles.
Definition MultibodyMeshMixedCcdDcd.h:67
MultibodyMeshMixedCcdDcd(Eigen::DenseBase< TDerivedX > const &X, Eigen::Ref< IndexVectorX const > const &V, Eigen::Ref< IndexMatrix< 2, Eigen::Dynamic > const > const &E, Eigen::Ref< IndexMatrix< 3, Eigen::Dynamic > const > const &F, Eigen::Ref< IndexMatrix< 4, Eigen::Dynamic > const > const &T, Eigen::Ref< IndexVectorX const > const &VP, Eigen::Ref< IndexVectorX const > const &EP, Eigen::Ref< IndexVectorX const > const &FP, Eigen::Ref< IndexVectorX const > const &TP)
Construct a new TriangleMeshMultibodyCcd object from input triangle meshes.
Definition MultibodyMeshMixedCcdDcd.h:505
auto const & GetTetrahedronAabbs() const
Get the tetrahedron Aabbs of this scene. This is mostly useful for debugging.
Definition MultibodyMeshMixedCcdDcd.h:231
auto const & GetTriangleAabbs() const
Get the triangle Aabbs of this scene. This is mostly useful for debugging.
Definition MultibodyMeshMixedCcdDcd.h:224
auto EdgeCount() const
Number of edges in the mesh system.
Definition MultibodyMeshMixedCcdDcd.h:347
auto BodyCount() const
Number of bodies in the mesh system.
Definition MultibodyMeshMixedCcdDcd.h:362
void ReportEdgeEdgeCcdContacts(Eigen::DenseBase< TDerivedXT > const &XT, Eigen::DenseBase< TDerivedX > const &X, Index oi, Index oj, FOnEdgeEdgeContactPair &&fOnEdgeEdgeContactPair) const
Report edge edge contact pairs from CCD.
Definition MultibodyMeshMixedCcdDcd.h:935
geometry::AabbRadixTreeHierarchy< kDims > BodyBvh
BVH over bodies.
Definition MultibodyMeshMixedCcdDcd.h:64
geometry::AabbKdTreeHierarchy< kDims > EdgeBvh
BVH over mesh edges.
Definition MultibodyMeshMixedCcdDcd.h:66
void UpdateCcdActiveSet(Eigen::DenseBase< TDerivedXT > const &XT, Eigen::DenseBase< TDerivedX > const &X, FOnVertexTriangleContactPair &&fOnVertexTriangleContactPair, FOnEdgeEdgeContactPair &&fOnEdgeEdgeContactPair)
Update the active set using CCD.
Definition MultibodyMeshMixedCcdDcd.h:611
geometry::AabbKdTreeHierarchy< kDims > VertexBvh
BVH over mesh vertices.
Definition MultibodyMeshMixedCcdDcd.h:65
PBAT_API void UpdateMeshEdgeBvhs()
Recompute mesh edge BVH bounding boxes.
Definition MultibodyMeshMixedCcdDcd.cpp:37
void ForEachBodyPair(FOnBodyPair &&fOnBodyPair) const
Loop over all potentially colliding body pairs.
Definition MultibodyMeshMixedCcdDcd.h:733
void ComputeTriangleAabbs(Eigen::DenseBase< TDerivedX > const &X)
Compute axis-aligned bounding boxes for triangles for DCD.
Definition MultibodyMeshMixedCcdDcd.h:683
auto const & GetEdgeAabbs() const
Get the edge Aabbs of this scene. This is mostly useful for debugging.
Definition MultibodyMeshMixedCcdDcd.h:217
PBAT_API void UpdateMeshVertexBvhs()
Recompute mesh vertex BVH bounding boxes.
Definition MultibodyMeshMixedCcdDcd.cpp:23
auto VertexCount() const
Number of vertices in the mesh system.
Definition MultibodyMeshMixedCcdDcd.h:342
PBAT_API void RecomputeBodyBvh()
Recompute body BVH tree and internal node bounding boxes.
Definition MultibodyMeshMixedCcdDcd.cpp:79
void ReportVertexTriangleCcdContacts(Eigen::DenseBase< TDerivedXT > const &XT, Eigen::DenseBase< TDerivedX > const &X, Index oi, Index oj, FOnVertexTriangleContactPair fOnVertexTriangleContactPair) const
Report vertex triangle contact pairs from CCD.
Definition MultibodyMeshMixedCcdDcd.h:885
auto const & GetBodyAabbs() const
Get the body Aabbs of this scene. This is mostly useful for debugging.
Definition MultibodyMeshMixedCcdDcd.h:203
auto TriangleCount() const
Number of triangles in the mesh system.
Definition MultibodyMeshMixedCcdDcd.h:352
void UpdateDcdActiveSet(Eigen::DenseBase< TDerivedX > const &X, FOnVertexTriangleContactPair &&fOnVertexTriangleContactPair)
Update the active set using DCD.
Definition MultibodyMeshMixedCcdDcd.h:586
PBAT_API void UpdateMeshTetrahedronBvhs()
Recompute mesh tetrahedron BVH bounding boxes.
Definition MultibodyMeshMixedCcdDcd.cpp:65
void ForEachPenetratingVertex(Eigen::DenseBase< TDerivedX > const &X, FOnPenetratingVertex &&fOnPenetratingVertex)
Loop over penetrating vertices.
Definition MultibodyMeshMixedCcdDcd.h:754
void ComputeEdgeAabbs(Eigen::DenseBase< TDerivedXT > const &XT, Eigen::DenseBase< TDerivedX > const &X)
Compute axis-aligned bounding boxes for linearly swept edges.
Definition MultibodyMeshMixedCcdDcd.h:665
PBAT_HOST_DEVICE bool AxisAlignedBoundingBoxes(TMatrixL1 const &L1, TMatrixU1 const &U1, TMatrixL2 const &L2, TMatrixU2 const &U2)
Tests for overlap between axis-aligned bounding box (L1,U1) and axis-aligned bounding box (L2,...
Definition OverlapQueries.h:608
PBAT_HOST_DEVICE bool PointTetrahedron3D(TMatrixP const &P, TMatrixA const &A, TMatrixB const &B, TMatrixC const &C, TMatrixD const &D)
Checks if point P is contained in tetrahedron ABCD, in at least 3D.
Definition OverlapQueries.h:562
PBAT_HOST_DEVICE auto PointTriangleCcd(TXT const &XT, TAT const &AT, TBT const &BT, TCT const &CT, TX const &X, TA const &A, TB const &B, TC const &C) -> math::linalg::mini::SVector< TScalar, 4 >
Computes the time of impact and barycentric coordinates of the intersection point between a point a...
Definition PointTriangleCcd.h:125
PBAT_HOST_DEVICE auto EdgeEdgeCcd(TP1T const &P1T, TQ1T const &Q1T, TP2T const &P2T, TQ2T const &Q2T, TP1 const &P1, TQ1 const &Q1, TP2 const &P2, TQ2 const &Q2) -> math::linalg::mini::SVector< TScalar, 3 >
Computes the time of impact and barycentric coordinates of the intersection point between an edge ...
Definition EdgeEdgeCcd.h:127
Mini linear algebra related functionality.
Definition Assign.h:12
Namespace for contact detection algorithms.
Definition Constraints.cpp:3
Eigen::Vector< Index, N > IndexVector
Fixed-size index vector type.
Definition Aliases.h:40
Eigen::Vector< Scalar, N > Vector
Fixed-size vector type.
Definition Aliases.h:24
Eigen::Matrix< Index, Rows, Cols > IndexMatrix
Fixed-size index matrix type.
Definition Aliases.h:47
std::ptrdiff_t Index
Index type.
Definition Aliases.h:17
double Scalar
Scalar type.
Definition Aliases.h:18
Eigen::Matrix< Scalar, Rows, Cols > Matrix
Fixed-size matrix type.
Definition Aliases.h:31
Profiling utilities for the Physics-Based Animation Toolkit (PBAT)
Edge-edge contact pair.
Definition MultibodyMeshMixedCcdDcd.h:85
EdgeBarycentricCoordinates beta
Barycentric weights of the intersection point on each edges.
Definition MultibodyMeshMixedCcdDcd.h:95
math::linalg::mini::SVector< Scalar, 2 > EdgeBarycentricCoordinates
Barycentric coordinates.
Definition MultibodyMeshMixedCcdDcd.h:86
EdgeVertices eis
Edge 1 vertices.
Definition MultibodyMeshMixedCcdDcd.h:92
Index ei
Edge 1.
Definition MultibodyMeshMixedCcdDcd.h:90
Index ej
Edge 2.
Definition MultibodyMeshMixedCcdDcd.h:91
EdgeVertices ejs
Edge 2 vertices.
Definition MultibodyMeshMixedCcdDcd.h:93
math::linalg::mini::SVector< Index, 2 > EdgeVertices
Edge vertices.
Definition MultibodyMeshMixedCcdDcd.h:88
Vertex-triangle contact pair (i,f)
Definition MultibodyMeshMixedCcdDcd.h:74
Index f
Triangle index.
Definition MultibodyMeshMixedCcdDcd.h:78
Index i
Vertex index.
Definition MultibodyMeshMixedCcdDcd.h:77
math::linalg::mini::SVector< Index, 3 > TriangleVertices
Triangle vertices.
Definition MultibodyMeshMixedCcdDcd.h:75
TriangleVertices fjs
Triangle vertices.
Definition MultibodyMeshMixedCcdDcd.h:79