iMSTK
Interactive Medical Simulation Toolkit
imstkCollisionData.h
1 /*
2 ** This file is part of the Interactive Medical Simulation Toolkit (iMSTK)
3 ** iMSTK is distributed under the Apache License, Version 2.0.
4 ** See accompanying NOTICE for details.
5 */
6 
7 #pragma once
8 
9 #include "imstkLogger.h"
10 #include "imstkMath.h"
11 #include "imstkTypes.h"
12 
13 namespace imstk
14 {
15 class Geometry;
16 
17 enum class CollisionElementType
18 {
19  Empty,
20  CellVertex,
21  CellIndex,
22  PointDirection,
23  PointIndexDirection
24 };
25 
26 // iMSTK collision data (not contacts) are broken down into the following:
27 // 1.) Intersecting cells which can be used for contact generation
28 // 2.) Direct (point, normal, depth) which can be used for contacts
29 // - \todo: Consider interpreting PointDirection and Index as CellVertex and CellIndex
30 // but give CellVertex and Index a cache-all void* clientData or something for direction, and depth
31 //
32 // There are then 3 ways to report a cell:
33 // 1.) Provide via a single cell id (CellIndexElement)
34 // - Not always possible. Some elements don't have ids
35 // 2.) Provide via a set of vertex ids (CellIndexElement)
36 // - Avoids requiring an id for the cell but requires ids for vertices
37 // - Useful for cells of cells that may not have ids.
38 // ie: edges of triangle, tetrahedron, or face of tet
39 // 3.) Provide the cell by vertex value (CellVertexElement)
40 // - Useful for implicit geometry (cells and verts aren't explicit given in any form)
41 //
42 // \todo: Inline initialization can't be used on basic primitive types in a union?
43 //
44 struct EmptyElement { };
45 
52 {
53  Vec3d pts[4] = { Vec3d::Zero(), Vec3d::Zero(), Vec3d::Zero(), Vec3d::Zero() };
54  int size = 0;
55 };
67 {
68  int ids[4] = { -1, -1, -1, -1 };
69  int parentId = -1; // Often doesn't exist
70  int idCount = 0;
71  CellTypeId cellType = IMSTK_VERTEX;
72 };
73 
79 {
80  Vec3d pt = Vec3d::Zero();
81  Vec3d dir = Vec3d::Zero();
82  double penetrationDepth = 0.0;
83 };
89 {
90  int ptIndex = 0;
91  Vec3d dir = Vec3d::Zero();
92  double penetrationDepth = 0.0;
93 };
94 
101 {
102  CollisionElement() : m_element{EmptyElement()}, m_type{CollisionElementType::Empty} { }
103 
104  CollisionElement(const EmptyElement& element) : m_element{element}, m_type{CollisionElementType::Empty} { }
105  void operator=(const EmptyElement& element)
106  {
107  m_element.m_EmptyElement = element;
108  m_type = CollisionElementType::Empty;
109  }
110 
111  CollisionElement(const CellVertexElement& element) : m_element{element}, m_type{CollisionElementType::CellVertex} { }
112  void operator=(const CellVertexElement& element)
113  {
114  m_element.m_CellVertexElement = element;
115  m_type = CollisionElementType::CellVertex;
116  }
117 
118  CollisionElement(const CellIndexElement& element) : m_element{element}, m_type{CollisionElementType::CellIndex} { }
119  void operator=(const CellIndexElement& element)
120  {
121  m_element.m_CellIndexElement = element;
122  m_type = CollisionElementType::CellIndex;
123  }
124 
125  CollisionElement(const PointDirectionElement& element) : m_element{element}, m_type{CollisionElementType::PointDirection} { }
126  void operator=(const PointDirectionElement& element)
127  {
128  m_element.m_PointDirectionElement = element;
129  m_type = CollisionElementType::PointDirection;
130  }
131 
132  CollisionElement(const PointIndexDirectionElement& element) : m_element{element}, m_type{CollisionElementType::PointIndexDirection} { }
133  void operator=(const PointIndexDirectionElement& element)
134  {
135  m_element.m_PointIndexDirectionElement = element;
136  m_type = CollisionElementType::PointIndexDirection;
137  }
138 
139  CollisionElement(const CollisionElement& other)
140  {
141  m_type = other.m_type;
142  m_ccdData = other.m_ccdData;
143  switch (m_type)
144  {
145  case CollisionElementType::Empty:
146  break;
147  case CollisionElementType::CellVertex:
148  m_element.m_CellVertexElement = other.m_element.m_CellVertexElement;
149  break;
150  case CollisionElementType::CellIndex:
151  m_element.m_CellIndexElement = other.m_element.m_CellIndexElement;
152  break;
153  case CollisionElementType::PointDirection:
154  m_element.m_PointDirectionElement = other.m_element.m_PointDirectionElement;
155  break;
156  case CollisionElementType::PointIndexDirection:
157  m_element.m_PointIndexDirectionElement = other.m_element.m_PointIndexDirectionElement;
158  break;
159  }
160  }
161 
162  CollisionElement& operator=(const CollisionElement& other)
163  {
164  m_type = other.m_type;
165  m_ccdData = other.m_ccdData;
166  switch (m_type)
167  {
168  case CollisionElementType::Empty:
169  break;
170  case CollisionElementType::CellVertex:
171  m_element.m_CellVertexElement = other.m_element.m_CellVertexElement;
172  break;
173  case CollisionElementType::CellIndex:
174  m_element.m_CellIndexElement = other.m_element.m_CellIndexElement;
175  break;
176  case CollisionElementType::PointDirection:
177  m_element.m_PointDirectionElement = other.m_element.m_PointDirectionElement;
178  break;
179  case CollisionElementType::PointIndexDirection:
180  m_element.m_PointIndexDirectionElement = other.m_element.m_PointIndexDirectionElement;
181  break;
182  }
183  return *this;
184  }
185 
186  union Element
187  {
188  EmptyElement m_EmptyElement;
189  CellVertexElement m_CellVertexElement;
190  CellIndexElement m_CellIndexElement;
191  PointDirectionElement m_PointDirectionElement;
192  PointIndexDirectionElement m_PointIndexDirectionElement;
193 
194  Element() : m_EmptyElement(EmptyElement()) { }
195  // Constructors needed here for implicit conversions+assignment between elements and parent struct
196  Element(const EmptyElement& ele) : m_EmptyElement(ele) { }
197  Element(const CellVertexElement& ele) : m_CellVertexElement(ele) { }
198  Element(const CellIndexElement& ele) : m_CellIndexElement(ele) { }
199  Element(const PointDirectionElement& ele) : m_PointDirectionElement(ele) { }
200  Element(const PointIndexDirectionElement& ele) : m_PointIndexDirectionElement(ele) { }
201  } m_element;
202 
203  CollisionElementType m_type;
204  bool m_ccdData = false;
205 };
206 
211 {
212 public:
213  std::vector<CollisionElement> elementsA;
214  std::vector<CollisionElement> elementsB;
215  std::shared_ptr<Geometry> geomA;
216  std::shared_ptr<Geometry> geomB;
217  std::shared_ptr<Geometry> prevGeomA;
218  std::shared_ptr<Geometry> prevGeomB;
219 };
220 } // namespace imstk
Compound Geometry.
Union of collision elements. We use a union to avoid polymorphism. There may be many elements and acc...
Represents a cell by a single cell id OR by N vertex ids. Which case can be determined by the idCount...
Describes the contact manifold between two geometries.
Direclty gives a point-direction contact as its collision data, point given by index.
Represents a cell by its vertex values Possible cells may be: point, edge, triangle, quad, or tetrahedron Maximum 4 vertices (tetrahedron is maximum cell it could represent)
Direclty gives a point-direction contact as its collision data.