1
// ---------------------------------------------------------
6
// Encapsulates all collision detection and resolution functions.
8
// ---------------------------------------------------------
10
#ifndef EL_TOPO_COLLISIONPIPELINE_H
11
#define EL_TOPO_COLLISIONPIPELINE_H
21
// A potentially colliding pair of primitives. Each pair is a triple of size_ts:
22
// elements 0 and 1 are the indices of the primitives involved.
23
// element 2 specifies if the potential collision is point-triangle or edge-edge
24
typedef std::deque<Vec3st> CollisionCandidateSet;
26
// --------------------------------------------------------
28
/// A collision between a triangle and a vertex or between two edges
30
// --------------------------------------------------------
34
/// Default collision constructor
37
m_is_edge_edge( false ),
38
m_vertex_indices( Vec4st(static_cast<size_t>(~0)) ),
39
m_normal( Vec3d(UNINITIALIZED_DOUBLE) ),
40
m_alphas( Vec4d(UNINITIALIZED_DOUBLE) ),
41
m_relative_displacement( UNINITIALIZED_DOUBLE )
44
/// Collision constructor
46
Collision( bool in_is_edge_edge, const Vec4st& in_vertex_indices, const Vec3d& in_normal, const Vec4d& in_alphas, double in_relative_displacement ) :
47
m_is_edge_edge( in_is_edge_edge ),
48
m_vertex_indices( in_vertex_indices ),
49
m_normal( in_normal ),
50
m_alphas( in_alphas ),
51
m_relative_displacement( in_relative_displacement )
53
if ( !m_is_edge_edge ) { assert( m_alphas[0] == 1.0 ); }
56
/// Determine if one or more vertices is shared between this Collision and other
58
inline bool overlap_vertices( const Collision& other ) const;
60
/// Determine if ALL vertices are shared between this Collision and other
62
inline bool same_vertices( const Collision& other ) const;
64
/// Are the two elements both edges
68
/// Which vertices are involved in the collision
70
Vec4st m_vertex_indices;
76
/// Barycentric coordinates of the point of intersection
80
/// Magnitude of relative motion over the timestep
82
double m_relative_displacement;
87
// --------------------------------------------------------
89
/// The results of processing a group of collision candidates.
91
// --------------------------------------------------------
93
struct ProcessCollisionStatus
97
ProcessCollisionStatus() :
98
collision_found( false ),
100
all_candidates_processed( false )
103
/// Whether one or more collisions was found.
105
bool collision_found;
107
/// Whether the number of collision candidates overflowed the candidate container.
111
/// Whether all collision candidates were processed, or if the processing was terminated early.
112
/// This is not necessarily equivalent to (!overflow): processing might stop early without overflow.
114
bool all_candidates_processed;
119
// --------------------------------------------------------
121
/// Encapsulates all collision detection and resolution.
123
// --------------------------------------------------------
125
class CollisionPipeline
132
CollisionPipeline(DynamicSurface& surface,
133
BroadPhase& broadphase,
134
double in_friction_coefficient );
138
void handle_proximities( double dt );
140
/// Sequential impulses
142
bool handle_collisions( double dt );
144
/// Get all collisions at once
146
bool detect_collisions( std::vector<Collision>& collisions );
148
/// Get collisions involving vertices in the impact zones
150
bool detect_new_collisions( const std::vector<ImpactZone> impact_zones,
151
std::vector<Collision>& collisions );
153
/// Get any collisions involving an edge and a triangle
155
void detect_collisions( size_t edge_index, size_t triangle_index, std::vector<Collision>& collisions );
157
/// Re-check the elements in the specified collision objectto see if there is still a collision
159
bool check_if_collision_persists( const Collision& collision );
161
/// Friction coefficient to apply during collision resolution
163
double m_friction_coefficient;
167
friend class DynamicSurface;
168
friend class EdgeCollapser;
170
/// Apply a collision implulse between two edges
172
void apply_edge_edge_impulse( const Collision& collision, double impulse_magnitude, double dt );
174
/// Apply a collision implulse between a triangle and a vertex
176
void apply_triangle_point_impulse( const Collision& collision, double impulse_magnitude, double dt );
178
/// Apply a collision implulse to the specified vertices, weighted by the alphas, along the specified normal
180
void apply_impulse(const Vec4d& alphas,
181
const Vec4st& vertex_indices,
182
double impulse_magnitude,
186
/// Check all triangles for AABB overlaps against the specified vertex.
188
void add_point_candidates(size_t vertex_index,
191
CollisionCandidateSet& collision_candidates );
193
/// Check all edges for AABB overlaps against the specified edge.
195
void add_edge_candidates(size_t edge_index,
198
CollisionCandidateSet& collision_candidates );
200
/// Check all edges for AABB overlaps against the specified edge.
202
void add_triangle_candidates(size_t triangle_index,
205
CollisionCandidateSet& collision_candidates );
207
/// Called when the specified vertex is moved. Checks all incident mesh elements for AABB overlaps.
209
void add_point_update_candidates(size_t vertex_index,
210
CollisionCandidateSet& collision_candidates );
212
/// Run continuous collision detection on a pair of edges.
214
bool detect_segment_segment_collision( const Vec3st& candidate, Collision& collision );
216
/// Run continuous collision detection on a vertex-triangle pair.
218
bool detect_point_triangle_collision( const Vec3st& candidate, Collision& collision );
220
/// Test the candidates for proximity and apply impulses
222
void process_proximity_candidates( double dt,
223
CollisionCandidateSet& candidates );
225
/// Test dynamic points vs. solid triangles for proximities, and apply repulsion forces
227
void dynamic_point_vs_solid_triangle_proximities(double dt);
229
/// Test dynamic triangles vs. all vertices for proximities, and apply repulsion forces
231
void dynamic_triangle_vs_all_point_proximities(double dt);
233
/// Test dynamic edges vs. all edges for proximities, and apply repulsion forces
235
void dynamic_edge_vs_all_edge_proximities(double dt);
238
/// Test the candidates and fix any collisions with impulses
240
void process_collision_candidates(double dt,
241
CollisionCandidateSet& candidates,
242
bool add_to_new_candidates,
243
CollisionCandidateSet& new_candidates,
244
ProcessCollisionStatus& status );
246
/// Test the candidates and return collision info
248
void test_collision_candidates(CollisionCandidateSet& candidates,
249
std::vector<Collision>& collisions,
250
ProcessCollisionStatus& status );
252
/// Check if any collision exists in the set of candidates. Stop when the first collision is found.
254
bool any_collision( CollisionCandidateSet& candidates, Collision& collision );
256
/// Check for collisions between dynamic points and solid triangles
258
void dynamic_point_vs_solid_triangle_collisions(double dt,
259
bool collect_candidates,
260
CollisionCandidateSet& update_collision_candidates,
261
ProcessCollisionStatus& status );
263
/// Check for collisions between dynamic triangles and all points
265
void dynamic_triangle_vs_all_point_collisions(double dt,
266
bool collect_candidates,
267
CollisionCandidateSet& update_collision_candidates,
268
ProcessCollisionStatus& status );
270
/// Check for collisions between dynamic edges and all other edges
272
void dynamic_edge_vs_all_edge_collisions( double dt,
273
bool collect_candidates,
274
CollisionCandidateSet& update_collision_candidates,
275
ProcessCollisionStatus& status );
277
DynamicSurface& m_surface;
278
BroadPhase& m_broadphase;
282
// ---------------------------------------------------------
284
// ---------------------------------------------------------
286
// --------------------------------------------------------
288
/// Determine if another collision has any vertices in common with this collision.
290
// --------------------------------------------------------
292
inline bool Collision::overlap_vertices( const Collision& other ) const
294
for ( unsigned short i = 0; i < 4; ++i )
296
if ( m_vertex_indices[i] == other.m_vertex_indices[0] ||
297
m_vertex_indices[i] == other.m_vertex_indices[1] ||
298
m_vertex_indices[i] == other.m_vertex_indices[2] ||
299
m_vertex_indices[i] == other.m_vertex_indices[3] )
308
// --------------------------------------------------------
310
/// Determine if another collision has all the same vertices as this collision.
312
// --------------------------------------------------------
314
inline bool Collision::same_vertices( const Collision& other ) const
317
for ( unsigned short i = 0; i < 4; ++i )
319
if ( m_vertex_indices[i] == other.m_vertex_indices[0] ||
320
m_vertex_indices[i] == other.m_vertex_indices[1] ||
321
m_vertex_indices[i] == other.m_vertex_indices[2] ||
322
m_vertex_indices[i] == other.m_vertex_indices[3] )
332
return ( found[0] && found[1] && found[2] && found[3] );