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
MeshVertexTetrahedronDcd.h
1#ifndef PBAT_SIM_CONTACT_MESHVERTEXTETRAHEDRONDCD_H
2#define PBAT_SIM_CONTACT_MESHVERTEXTETRAHEDRONDCD_H
3
4#include "MultibodyTetrahedralMeshSystem.h"
5#include "PhysicsBasedAnimationToolkitExport.h"
6#include "pbat/Aliases.h"
8#include "pbat/geometry/AabbRadixTreeHierarchy.h"
10#include "pbat/geometry/HierarchicalHashGrid.h"
12#include "pbat/math/linalg/mini/Eigen.h"
13
14#include <exception>
15#include <unordered_map>
16#include <vector>
17
18namespace pbat::sim::contact {
19
30{
31 public:
33 using IndexType = Index;
34 static constexpr int kMaxVertexTriangleContacts =
35 8;
36 static constexpr int kDims = 3;
37
45 Eigen::Ref<Eigen::Matrix<ScalarType, kDims, Eigen::Dynamic>> X,
46 Eigen::Ref<Eigen::Matrix<IndexType, 4, Eigen::Dynamic>> T);
53 PBAT_API void UpdateActiveSet(
54 Eigen::Ref<Eigen::Matrix<ScalarType, kDims, Eigen::Dynamic> const> const& X,
55 Eigen::Ref<Eigen::Matrix<IndexType, 4, Eigen::Dynamic> const> const& T);
64 template <class FOnVertexTriangleContactPair>
66 IndexType v,
67 FOnVertexTriangleContactPair fOnVertexTriangleContactPair) const;
72
73 protected:
79 template <class TDerivedX>
80 void ComputeTriangleAabbs(Eigen::DenseBase<TDerivedX> const& X);
89 template <class TDerivedX, class TDerivedT>
91 IndexType o,
92 Eigen::DenseBase<TDerivedX> const& X,
93 Eigen::DenseBase<TDerivedT> const& T);
99 PBAT_API void ComputeBodyAabbs();
103 PBAT_API void UpdateMeshTriangleBvhs();
108 PBAT_API void UpdateMeshTetrahedronHashGrid(IndexType bodyIndex);
112 PBAT_API void RecomputeBodiesBvh();
118 template <class FOnBodyPair>
119 void ForEachBodyPair(FOnBodyPair&& fOnBodyPair) const;
129 template <class TDerivedX, class TDerivedT>
131 IndexType ov,
132 IndexType ot,
133 Eigen::DenseBase<TDerivedX> const& X,
134 Eigen::DenseBase<TDerivedT> const& T);
143 template <class TDerivedX>
145 IndexType ov,
146 IndexType of,
147 Eigen::DenseBase<TDerivedX> const& X);
148
149 private:
151 mMultibodySystem;
152
153 Eigen::Matrix<ScalarType, 2 * kDims, Eigen::Dynamic>
154 mTriangleAabbs;
157 Eigen::Matrix<ScalarType, 2 * kDims, Eigen::Dynamic>
158 mTetrahedronAabbs;
161
162 Eigen::Matrix<ScalarType, 2 * kDims, Eigen::Dynamic>
163 mBodyAabbs;
165
166 std::vector<geometry::AabbKdTreeHierarchy<kDims>>
167 mTriangleMeshBvhs;
168 std::vector<geometry::HierarchicalHashGrid<kDims, ScalarType, IndexType>>
169 mTetrahedronMeshHashGrids;
170
172
173 Eigen::Vector<bool, Eigen::Dynamic>
174 mIsTetrahedronMeshHashGridDirty;
178 std::vector<std::unordered_map<IndexType, IndexType>>
179 mBodyVertexToOtherBodiesValence;
183 Eigen::Matrix<IndexType, kMaxVertexTriangleContacts, Eigen::Dynamic>
184 mVFC;
187};
188
189template <class FOnVertexTriangleContactPair>
191 IndexType v,
192 FOnVertexTriangleContactPair fOnVertexTriangleContactPair) const
193{
194 for (auto k = 0; k < kMaxVertexTriangleContacts; ++k)
195 {
196 IndexType const f = mVFC(k, v);
197 if (f == -1)
198 break;
199 fOnVertexTriangleContactPair(f, k);
200 }
201}
202
203template <class TDerivedX>
204inline void MeshVertexTetrahedronDcd::ComputeTriangleAabbs(Eigen::DenseBase<TDerivedX> const& X)
205{
206 PBAT_PROFILE_NAMED_SCOPE("pbat.sim.contact.MeshVertexTetrahedronDcd.ComputeTriangleAabbs");
207 auto const nTriangles = mMultibodySystem.NumContactTriangles();
208 for (auto f = 0; f < nTriangles; ++f)
209 {
211 XF = X(Eigen::placeholders::all, mMultibodySystem.F.col(f)).template block<kDims, 3>(0, 0);
212 auto L = mTriangleAabbs.col(f).head<kDims>();
213 auto U = mTriangleAabbs.col(f).tail<kDims>();
214 L = XF.rowwise().minCoeff();
215 U = XF.rowwise().maxCoeff();
216 }
217}
218
219template <class TDerivedX, class TDerivedT>
221 IndexType o,
222 Eigen::DenseBase<TDerivedX> const& X,
223 Eigen::DenseBase<TDerivedT> const& T)
224{
225 PBAT_PROFILE_NAMED_SCOPE(
226 "pbat.sim.contact.MeshVertexTetrahedronDcd.ComputeTetrahedronMeshAabbs");
227 auto const [tbegin, tend] = mMultibodySystem.TetrahedraRangeFor(o);
228 auto TB = mTetrahedronAabbs(Eigen::placeholders::all, Eigen::seq(tbegin, tend - 1));
229 for (auto t = tbegin; t < tend; ++t)
230 {
231 Matrix<kDims, 4> XT = X(Eigen::placeholders::all, T.col(t)).template block<kDims, 4>(0, 0);
232 auto L = TB.col(t - tbegin).template head<kDims>();
233 auto U = TB.col(t - tbegin).template tail<kDims>();
234 L = XT.rowwise().minCoeff();
235 U = XT.rowwise().maxCoeff();
236 }
237}
238
239template <class FOnBodyPair>
240inline void MeshVertexTetrahedronDcd::ForEachBodyPair(FOnBodyPair&& fOnBodyPair) const
241{
242 PBAT_PROFILE_NAMED_SCOPE("pbat.sim.contact.MeshVertexTetrahedronDcd.ForEachBodyPair");
243 mBodiesBvh.SelfOverlaps(
244 [this](IndexType oi, IndexType oj) {
245 if (oi == oj)
246 {
247 throw std::runtime_error(
248 "MeshVertexTetrahedronDcd::UpdateActiveSet: oi == oj, which is not allowed.");
249 }
250 auto L1 = mBodyAabbs.col(oi).template head<kDims>();
251 auto U1 = mBodyAabbs.col(oi).template tail<kDims>();
252 auto L2 = mBodyAabbs.col(oj).template head<kDims>();
253 auto U2 = mBodyAabbs.col(oj).template tail<kDims>();
254 using math::linalg::mini::FromEigen;
256 FromEigen(L1),
257 FromEigen(U1),
258 FromEigen(L2),
259 FromEigen(U2));
260 },
261 [fOnBodyPair = std::forward<FOnBodyPair>(
262 fOnBodyPair)](IndexType oi, IndexType oj, [[maybe_unused]] IndexType k) {
263 fOnBodyPair(oi, oj);
264 });
265}
266
267template <class TDerivedX, class TDerivedT>
269 IndexType ov,
270 IndexType ot,
271 Eigen::DenseBase<TDerivedX> const& X,
272 Eigen::DenseBase<TDerivedT> const& T)
273{
274 PBAT_PROFILE_NAMED_SCOPE("pbat.sim.contact.MeshVertexTetrahedronDcd.MarkPenetratingVertices");
275 auto const Vov = mMultibodySystem.ContactVerticesOf(ov);
276 auto Xv = X(Eigen::placeholders::all, Vov);
277 auto const [tbegin, tend] = mMultibodySystem.TetrahedraRangeFor(ot);
278 auto Lt =
279 mTetrahedronAabbs(Eigen::placeholders::all, Eigen::seq(tbegin, tend - 1)).topRows<kDims>();
280 auto Ut = mTetrahedronAabbs(Eigen::placeholders::all, Eigen::seq(tbegin, tend - 1))
281 .bottomRows<kDims>();
282 std::unordered_map<IndexType, IndexType>& mBodyVertexToOtherBodiesValenceMap =
283 mBodyVertexToOtherBodiesValence[static_cast<std::size_t>(ov)];
284 mTetrahedronMeshHashGrids[static_cast<std::size_t>(ot)]
285 .BroadPhase(Lt, Ut, Xv, [&](IndexType vq, IndexType tp) {
286 auto const i = Vov(vq);
287 auto const XT = X(Eigen::placeholders::all, T.col(tbegin + tp));
288 using math::linalg::mini::FromEigen;
290 FromEigen(X.col(i).template head<kDims>()),
291 FromEigen(XT.col(0).template head<kDims>()),
292 FromEigen(XT.col(1).template head<kDims>()),
293 FromEigen(XT.col(2).template head<kDims>()),
294 FromEigen(XT.col(3).template head<kDims>())))
295 {
296 auto it = mBodyVertexToOtherBodiesValenceMap.find(vq);
297 auto end = mBodyVertexToOtherBodiesValenceMap.end();
298 if (it == end)
299 {
300 mBodyVertexToOtherBodiesValenceMap.insert({vq, IndexType(1)});
301 }
302 else
303 {
304 auto& valence = it->second;
305 ++valence;
306 }
307 }
308 });
309}
310
311template <class TDerivedX>
313 IndexType ov,
314 IndexType of,
315 Eigen::DenseBase<TDerivedX> const& X)
316{
317 PBAT_PROFILE_NAMED_SCOPE(
318 "pbat.sim.contact.MeshVertexTetrahedronDcd.FindNearestTrianglesToPenetratingVertices");
319 IndexType const vbegin = mMultibodySystem.ContactVerticesRangeFor(ov).first;
320 auto const fbegin = mMultibodySystem.ContactTrianglesRangeFor(of).first;
321 std::unordered_map<IndexType, IndexType>& mBodyVertexToOtherBodiesValenceMap =
322 mBodyVertexToOtherBodiesValence[static_cast<std::size_t>(ov)];
323 for (auto& [vq, valence] : mBodyVertexToOtherBodiesValenceMap)
324 {
325 assert(valence > 0);
326 --valence;
327 auto const v = vbegin + vq;
328 auto const i = mMultibodySystem.V(v);
329 auto const P = X.col(i).template head<kDims>();
330 using math::linalg::mini::FromEigen;
331 mTriangleMeshBvhs[static_cast<std::size_t>(of)].NearestNeighbours(
332 [&]<class TL, class TU>(TL const& L, TU const& U) {
334 FromEigen(P),
335 FromEigen(L),
336 FromEigen(U));
337 },
338 [&](IndexType fq) {
339 auto const f = fbegin + fq;
340 auto const iF = mMultibodySystem.F.col(f);
341 auto const XT = X(Eigen::placeholders::all, iF);
343 FromEigen(P),
344 FromEigen(XT.col(0).template head<kDims>()),
345 FromEigen(XT.col(1).template head<kDims>()),
346 FromEigen(XT.col(2).template head<kDims>()));
347 },
348 [&](IndexType fq, [[maybe_unused]] ScalarType d, IndexType k) {
350 return;
351 mVFC(k, v) = fbegin + fq;
352 }/*,
353 radius,
354 eps*/);
355 }
356 std::erase_if(mBodyVertexToOtherBodiesValenceMap, [](auto const& keyValuePair) {
357 auto const& valence = keyValuePair.second;
358 assert(valence >= 0);
359 return valence == 0;
360 });
361}
362
363} // namespace pbat::sim::contact
364
365#endif // PBAT_SIM_CONTACT_MESHVERTEXTETRAHEDRONDCD_H
BVH over axis-aligned bounding boxes using a k-D tree.
This file contains functions to answer distance queries.
This file contains functions to answer overlap queries.
Axis-aligned radix tree hierarchy of axis-aligned bounding boxes.
Definition AabbRadixTreeHierarchy.h:35
Index IndexType
Index type used in the contact detection system.
Definition MeshVertexTetrahedronDcd.h:33
PBAT_API MeshVertexTetrahedronDcd(Eigen::Ref< Eigen::Matrix< ScalarType, kDims, Eigen::Dynamic > > X, Eigen::Ref< Eigen::Matrix< IndexType, 4, Eigen::Dynamic > > T)
Construct a new MeshVertexTetrahedronDcd object from input tetrahedron meshes.
Definition MeshVertexTetrahedronDcd.cpp:5
PBAT_API MultibodyTetrahedralMeshSystem< IndexType > const & MultibodySystem() const
Get the multibody tetrahedral mesh system.
Definition MeshVertexTetrahedronDcd.cpp:80
PBAT_API void UpdateMeshTriangleBvhs()
Recompute mesh triangle BVH bounding boxes.
Definition MeshVertexTetrahedronDcd.cpp:103
void ForEachActiveVertexTriangleContact(IndexType v, FOnVertexTriangleContactPair fOnVertexTriangleContactPair) const
Visit the triangles in active vertex-triangle contacts.
Definition MeshVertexTetrahedronDcd.h:190
static constexpr int kDims
Number of dimensions in the contact detection system.
Definition MeshVertexTetrahedronDcd.h:36
void ComputeTriangleAabbs(Eigen::DenseBase< TDerivedX > const &X)
Compute axis-aligned bounding boxes for triangles for DCD.
Definition MeshVertexTetrahedronDcd.h:204
PBAT_API void ComputeBodyAabbs()
Computes body AABBs from mesh vertex BVHs.
Definition MeshVertexTetrahedronDcd.cpp:85
void FindNearestTrianglesToPenetratingVertices(IndexType ov, IndexType of, Eigen::DenseBase< TDerivedX > const &X)
Find the nearest triangles on the triangle mesh of to penetrating vertices of body ov
Definition MeshVertexTetrahedronDcd.h:312
PBAT_API void UpdateMeshTetrahedronHashGrid(IndexType bodyIndex)
Recompute mesh tetrahedron hash grid for a specific body.
Definition MeshVertexTetrahedronDcd.cpp:118
static constexpr int kMaxVertexTriangleContacts
Maximum number of contacting triangles per vertex.
Definition MeshVertexTetrahedronDcd.h:34
void ForEachBodyPair(FOnBodyPair &&fOnBodyPair) const
Compute and visit all contacting body pairs.
Definition MeshVertexTetrahedronDcd.h:240
Scalar ScalarType
Scalar type used in the contact detection system.
Definition MeshVertexTetrahedronDcd.h:32
void ComputeTetrahedronMeshAabbs(IndexType o, Eigen::DenseBase< TDerivedX > const &X, Eigen::DenseBase< TDerivedT > const &T)
Computes AABBs for tetrahedra from mesh vertex positions.
Definition MeshVertexTetrahedronDcd.h:220
PBAT_API void UpdateActiveSet(Eigen::Ref< Eigen::Matrix< ScalarType, kDims, Eigen::Dynamic > const > const &X, Eigen::Ref< Eigen::Matrix< IndexType, 4, Eigen::Dynamic > const > const &T)
Update the active set of vertex-triangle contacts.
Definition MeshVertexTetrahedronDcd.cpp:48
void MarkPenetratingVertices(IndexType ov, IndexType ot, Eigen::DenseBase< TDerivedX > const &X, Eigen::DenseBase< TDerivedT > const &T)
Register all collision vertices of body ov that penetrate into body ot
Definition MeshVertexTetrahedronDcd.h:268
PBAT_API void RecomputeBodiesBvh()
Recompute bodies BVH tree and internal node bounding boxes.
Definition MeshVertexTetrahedronDcd.cpp:128
PBAT_HOST_DEVICE auto PointTriangle(TMatrixP const &P, TMatrixA const &A, TMatrixB const &B, TMatrixC const &C) -> typename TMatrixP::ScalarType
Obtain squared distance between point P and triangle ABC.
Definition DistanceQueries.h:217
PBAT_HOST_DEVICE auto PointAxisAlignedBoundingBox(TMatrixP const &P, TMatrixL const &L, TMatrixU const &U) -> typename TMatrixP::ScalarType
Obtain squared distance between point P and axis-aligned box (L,U)
Definition DistanceQueries.h:199
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
Namespace for contact detection algorithms.
Definition Constraints.cpp:3
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
Multibody Tetrahedral Mesh System.
Definition MultibodyTetrahedralMeshSystem.h:26