~siretart/ubuntu/utopic/blender/libav10

« back to all changes in this revision

Viewing changes to extern/eltopo/eltopo3d/dynamicsurface.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Kevin Roy
  • Date: 2011-06-24 11:13:28 UTC
  • mto: (14.1.6 experimental) (1.5.1)
  • mto: This revision was merged to the branch mainline in revision 28.
  • Revision ID: james.westby@ubuntu.com-20110624111328-27ribg6l36edf2ay
Tags: upstream-2.58-svn37702
ImportĀ upstreamĀ versionĀ 2.58-svn37702

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
// ---------------------------------------------------------
 
2
//
 
3
//  dynamicsurface.cpp
 
4
//  Tyson Brochu 2008
 
5
//  
 
6
//  A triangle mesh with associated vertex locations and 
 
7
//  velocities.  Collision detection and solving.
 
8
//
 
9
// ---------------------------------------------------------
 
10
 
 
11
// ---------------------------------------------------------
 
12
// Includes
 
13
// ---------------------------------------------------------
 
14
 
 
15
#include <dynamicsurface.h>
 
16
 
 
17
#include <vector>
 
18
#include <deque>
 
19
#include <queue>
 
20
 
 
21
#ifdef __APPLE__
 
22
#include <OpenGL/gl.h>
 
23
#else
 
24
#ifdef WIN32
 
25
#include <windows.h>
 
26
#endif
 
27
#include <GL/gl.h>
 
28
#endif
 
29
 
 
30
#include <vec.h>
 
31
#include <mat.h>
 
32
#include <array3.h>
 
33
#include <ccd_wrapper.h>
 
34
#include <gluvi.h>
 
35
#include <ctime>
 
36
#include <nondestructivetrimesh.h>
 
37
#include <broadphasegrid.h>
 
38
#include <wallclocktime.h>
 
39
#include <cassert>
 
40
#include <sparse_matrix.h>
 
41
#include <krylov_solvers.h>
 
42
#include <fstream>
 
43
#include <lapack_wrapper.h>
 
44
#include <array2.h>
 
45
 
 
46
#include <ccd_wrapper.h>
 
47
#include <collisionqueries.h>
 
48
 
 
49
//#define USE_EXACT_ARITHMETIC_RAY_CASTING
 
50
 
 
51
#ifdef USE_EXACT_ARITHMETIC_RAY_CASTING
 
52
#include <tunicate.h>
 
53
#endif
 
54
 
 
55
// ---------------------------------------------------------
 
56
// Local constants, typedefs, macros
 
57
// ---------------------------------------------------------
 
58
 
 
59
// ---------------------------------------------------------
 
60
//  Extern globals
 
61
// ---------------------------------------------------------
 
62
 
 
63
const double G_EIGENVALUE_RANK_RATIO = 0.03;
 
64
 
 
65
// ---------------------------------------------------------
 
66
// Static function definitions
 
67
// ---------------------------------------------------------
 
68
 
 
69
// ---------------------------------------------------------
 
70
///
 
71
/// Add a collision to the list as long as it doesn't have the same vertices as any other collisions in the list.
 
72
///
 
73
// ---------------------------------------------------------
 
74
 
 
75
static void add_unique_collision( std::vector<Collision>& collisions, const Collision& new_collision )
 
76
{
 
77
   for ( std::vector<Collision>::iterator iter = collisions.begin(); iter != collisions.end(); ++iter )
 
78
   {
 
79
      if ( iter->same_vertices( new_collision ) )
 
80
      {
 
81
         return;
 
82
      }
 
83
   }
 
84
   
 
85
   collisions.push_back( new_collision );
 
86
}
 
87
 
 
88
// ---------------------------------------------------------
 
89
///
 
90
/// Helper function: multiply transpose(A) * D * B
 
91
///
 
92
// ---------------------------------------------------------
 
93
 
 
94
static void AtDB(const SparseMatrixDynamicCSR &A, const double* diagD, const SparseMatrixDynamicCSR &B, SparseMatrixDynamicCSR &C)
 
95
{
 
96
   assert(A.m==B.m);
 
97
   C.resize(A.n, B.n);
 
98
   C.set_zero();
 
99
   for(int k=0; k<A.m; ++k)
 
100
   {
 
101
      const DynamicSparseVector& r = A.row[k];
 
102
      
 
103
      for( DynamicSparseVector::const_iterator p=r.begin(); p != r.end(); ++p )
 
104
      {
 
105
         int i = p->index;
 
106
         double multiplier = p->value * diagD[k];
 
107
         C.add_sparse_row( i, B.row[k], multiplier );
 
108
      }
 
109
   }
 
110
}
 
111
 
 
112
// ---------------------------------------------------------
 
113
// Member function definitions
 
114
// ---------------------------------------------------------
 
115
 
 
116
// ---------------------------------------------------------
 
117
///
 
118
/// DynamicSurface constructor.  Copy triangles and vertex locations.
 
119
///
 
120
// ---------------------------------------------------------
 
121
 
 
122
DynamicSurface::DynamicSurface( const std::vector<Vec3d>& vertex_positions, 
 
123
                                const std::vector<Vec3ui>& triangles,
 
124
                                const std::vector<double>& masses,
 
125
                                double in_proximity_epsilon,
 
126
                                bool in_collision_safety,
 
127
                                bool in_verbose ) :
 
128
   m_proximity_epsilon( in_proximity_epsilon ),
 
129
   m_verbose( in_verbose ),   
 
130
   m_collision_safety( in_collision_safety ),
 
131
   m_positions(0), m_newpositions(0), m_velocities(0), m_masses(0),
 
132
   m_mesh(),
 
133
   m_num_collisions_this_step(0), m_total_num_collisions(0)
 
134
{
 
135
   
 
136
   m_broad_phase = new BroadPhaseGrid();
 
137
   
 
138
   std::cout << "constructing dynamic surface" << std::endl;
 
139
  
 
140
   for(unsigned int i = 0; i < vertex_positions.size(); i++)
 
141
   {
 
142
      m_positions.push_back( vertex_positions[i] );
 
143
                m_newpositions.push_back( vertex_positions[i] );
 
144
      m_velocities.push_back( Vec3d(0,0,0) );
 
145
      m_masses.push_back( masses[i] );
 
146
   }
 
147
   
 
148
   for(unsigned int i = 0; i < triangles.size(); i++)
 
149
   {
 
150
      m_mesh.m_tris.push_back( triangles[i] );
 
151
   }
 
152
   
 
153
   std::cout << "constructed dynamic surface" << std::endl;
 
154
}
 
155
 
 
156
 
 
157
// ---------------------------------------------------------
 
158
///
 
159
/// 
 
160
///
 
161
// ---------------------------------------------------------
 
162
 
 
163
DynamicSurface::~DynamicSurface()
 
164
{
 
165
   delete m_broad_phase;
 
166
}
 
167
 
 
168
 
 
169
// ---------------------------------------------------------
 
170
///
 
171
/// Compute rank of the quadric metric tensor at a vertex
 
172
///
 
173
// ---------------------------------------------------------
 
174
 
 
175
unsigned int DynamicSurface::classify_vertex( unsigned int v )
 
176
{     
 
177
   if ( m_mesh.m_vtxtri[v].empty() )     { return 0; }
 
178
   
 
179
   const std::vector<unsigned int>& incident_triangles = m_mesh.m_vtxtri[v];
 
180
   
 
181
   std::vector< Vec3d > N;
 
182
   std::vector< double > W;
 
183
   
 
184
   for ( unsigned int i = 0; i < incident_triangles.size(); ++i )
 
185
   {
 
186
      unsigned int triangle_index = incident_triangles[i];
 
187
      N.push_back( get_triangle_normal(triangle_index) );
 
188
      W.push_back( get_triangle_area(triangle_index) );
 
189
   }
 
190
   
 
191
   Mat33d A(0,0,0,0,0,0,0,0,0);
 
192
   
 
193
   for ( unsigned int i = 0; i < N.size(); ++i )
 
194
   {
 
195
      A(0,0) += N[i][0] * W[i] * N[i][0];
 
196
      A(1,0) += N[i][1] * W[i] * N[i][0];
 
197
      A(2,0) += N[i][2] * W[i] * N[i][0];
 
198
      
 
199
      A(0,1) += N[i][0] * W[i] * N[i][1];
 
200
      A(1,1) += N[i][1] * W[i] * N[i][1];
 
201
      A(2,1) += N[i][2] * W[i] * N[i][1];
 
202
      
 
203
      A(0,2) += N[i][0] * W[i] * N[i][2];
 
204
      A(1,2) += N[i][1] * W[i] * N[i][2];
 
205
      A(2,2) += N[i][2] * W[i] * N[i][2];
 
206
   }
 
207
   
 
208
   // get eigen decomposition
 
209
   double eigenvalues[3];
 
210
   double work[9];
 
211
   int info = ~0, n = 3, lwork = 9;
 
212
   LAPACK::get_eigen_decomposition( &n, A.a, &n, eigenvalues, work, &lwork, &info );
 
213
   
 
214
   if ( info != 0 )
 
215
   {
 
216
      std::cout << "Eigen decomp failed.  Incident triangles: " << std::endl;
 
217
      for ( unsigned int i = 0; i < W.size(); ++i )
 
218
      {
 
219
         std::cout << "normal: ( " << N[i] << " )    ";  
 
220
         std::cout << "area: " << W[i] << std::endl;
 
221
      }
 
222
      return 4;
 
223
   }
 
224
   
 
225
   // compute rank of primary space
 
226
   unsigned int rank = 0;
 
227
   for ( unsigned int i = 0; i < 3; ++i )
 
228
   {
 
229
      if ( eigenvalues[i] > G_EIGENVALUE_RANK_RATIO * eigenvalues[2] )
 
230
      {
 
231
         ++rank;
 
232
      }
 
233
   }
 
234
   
 
235
   return rank;
 
236
   
 
237
}
 
238
 
 
239
 
 
240
 
 
241
// ---------------------------------------------------------
 
242
///
 
243
/// Add a triangle to the surface.  Update the underlying TriMesh and acceleration grid. 
 
244
///
 
245
// ---------------------------------------------------------
 
246
 
 
247
unsigned int DynamicSurface::add_triangle( const Vec3ui& t )
 
248
{
 
249
   unsigned int new_triangle_index = m_mesh.m_tris.size();
 
250
   m_mesh.nondestructive_add_triangle( t );
 
251
 
 
252
   if ( m_collision_safety )
 
253
   {
 
254
      // Add to the triangle grid
 
255
      Vec3d low, high;
 
256
      triangle_static_bounds( new_triangle_index, low, high );
 
257
      m_broad_phase->add_triangle( new_triangle_index, low, high );
 
258
      
 
259
      // Add edges to grid as well
 
260
      unsigned int new_edge_index = m_mesh.get_edge( t[0], t[1] );
 
261
      assert( new_edge_index != m_mesh.m_edges.size() );
 
262
      edge_static_bounds( new_edge_index, low, high );
 
263
      m_broad_phase->add_edge( new_edge_index, low, high );
 
264
      
 
265
      new_edge_index = m_mesh.get_edge( t[1], t[2] );
 
266
      assert( new_edge_index != m_mesh.m_edges.size() );   
 
267
      edge_static_bounds( new_edge_index, low, high );
 
268
      m_broad_phase->add_edge( new_edge_index, low, high );
 
269
      
 
270
      new_edge_index = m_mesh.get_edge( t[2], t[0] );
 
271
      assert( new_edge_index != m_mesh.m_edges.size() );   
 
272
      edge_static_bounds( new_edge_index, low, high );
 
273
      m_broad_phase->add_edge( new_edge_index, low, high );
 
274
   }
 
275
   
 
276
   return new_triangle_index;
 
277
}
 
278
 
 
279
 
 
280
// ---------------------------------------------------------
 
281
///
 
282
/// Remove a triangle from the surface.  Update the underlying TriMesh and acceleration grid. 
 
283
///
 
284
// ---------------------------------------------------------
 
285
 
 
286
void DynamicSurface::remove_triangle(unsigned int t)
 
287
{
 
288
   m_mesh.nondestructive_remove_triangle( t );
 
289
   if ( m_collision_safety )
 
290
   {
 
291
      m_broad_phase->remove_triangle( t );
 
292
   }
 
293
}
 
294
 
 
295
 
 
296
// ---------------------------------------------------------
 
297
///
 
298
/// Add a vertex to the surface.  Update the acceleration grid. 
 
299
///
 
300
// ---------------------------------------------------------
 
301
 
 
302
unsigned int DynamicSurface::add_vertex( const Vec3d& new_vertex_position, 
 
303
                                         const Vec3d& new_vertex_velocity, 
 
304
                                         double new_vertex_mass )
 
305
{
 
306
   m_positions.push_back( new_vertex_position );
 
307
   m_newpositions.push_back( new_vertex_position );
 
308
   m_velocities.push_back( new_vertex_velocity );
 
309
   m_masses.push_back( new_vertex_mass );
 
310
      
 
311
   unsigned int new_vertex_index = m_mesh.nondestructive_add_vertex( );
 
312
 
 
313
   assert( new_vertex_index == m_positions.size() - 1 );
 
314
   
 
315
   if ( m_collision_safety )
 
316
   {
 
317
      m_broad_phase->add_vertex( new_vertex_index, m_positions[new_vertex_index], m_positions[new_vertex_index] );       
 
318
   }
 
319
   
 
320
   return new_vertex_index;
 
321
}
 
322
 
 
323
 
 
324
// ---------------------------------------------------------
 
325
///
 
326
/// Remove a vertex from the surface.  Update the acceleration grid. 
 
327
///
 
328
// ---------------------------------------------------------
 
329
 
 
330
void DynamicSurface::remove_vertex( unsigned int vertex_index )
 
331
{
 
332
   m_mesh.nondestructive_remove_vertex( vertex_index );
 
333
   
 
334
   if ( m_collision_safety )
 
335
   {
 
336
      m_broad_phase->remove_vertex( vertex_index );
 
337
   }
 
338
   
 
339
   m_positions[ vertex_index ] = Vec3d( 0.0, 0.0, 0.0 );
 
340
   m_newpositions[ vertex_index ] = Vec3d( 0.0, 0.0, 0.0 );
 
341
}
 
342
 
 
343
 
 
344
// --------------------------------------------------------
 
345
///
 
346
/// Determine surface IDs for all vertices
 
347
///
 
348
// --------------------------------------------------------
 
349
 
 
350
void DynamicSurface::partition_surfaces( std::vector<unsigned int>& surface_ids, std::vector< std::vector< unsigned int> >& surfaces ) const
 
351
{
 
352
      
 
353
   static const unsigned int UNASSIGNED = (unsigned int) ~0;
 
354
   
 
355
   surfaces.clear();
 
356
   
 
357
   surface_ids.clear();
 
358
   surface_ids.resize( m_positions.size(), UNASSIGNED );
 
359
   
 
360
   unsigned int curr_surface = 0;
 
361
   
 
362
   while ( true )
 
363
   { 
 
364
      unsigned int next_unassigned_vertex;
 
365
      for ( next_unassigned_vertex = 0; next_unassigned_vertex < surface_ids.size(); ++next_unassigned_vertex )
 
366
      {
 
367
         if ( m_mesh.m_vtxedge[next_unassigned_vertex].empty() ) { continue; }
 
368
         
 
369
         if ( surface_ids[next_unassigned_vertex] == UNASSIGNED )
 
370
         {
 
371
            break;
 
372
         }
 
373
      }
 
374
      
 
375
      if ( next_unassigned_vertex == surface_ids.size() )
 
376
      {
 
377
         break;
 
378
      }
 
379
      
 
380
      std::queue<unsigned int> open;
 
381
      open.push( next_unassigned_vertex );
 
382
      
 
383
      std::vector<unsigned int> surface_vertices;
 
384
      
 
385
      while ( false == open.empty() )
 
386
      {
 
387
         unsigned int vertex_index = open.front();
 
388
         open.pop();
 
389
         
 
390
         if ( m_mesh.m_vtxedge[vertex_index].empty() ) { continue; }
 
391
         
 
392
         if ( surface_ids[vertex_index] != UNASSIGNED )
 
393
         {
 
394
            assert( surface_ids[vertex_index] == curr_surface );
 
395
            continue;
 
396
         }
 
397
         
 
398
         surface_ids[vertex_index] = curr_surface;
 
399
         surface_vertices.push_back( vertex_index );
 
400
         
 
401
         const std::vector<unsigned int>& incident_edges = m_mesh.m_vtxedge[vertex_index];
 
402
         
 
403
         for( unsigned int i = 0; i < incident_edges.size(); ++i )
 
404
         {
 
405
            unsigned int adjacent_vertex = m_mesh.m_edges[ incident_edges[i] ][0];
 
406
            if ( adjacent_vertex == vertex_index ) { adjacent_vertex = m_mesh.m_edges[ incident_edges[i] ][1]; }
 
407
            
 
408
            if ( surface_ids[adjacent_vertex] == UNASSIGNED )
 
409
            {
 
410
               open.push( adjacent_vertex );
 
411
            }
 
412
            else
 
413
            {
 
414
               assert( surface_ids[adjacent_vertex] == curr_surface );
 
415
            }
 
416
            
 
417
         } 
 
418
      }
 
419
      
 
420
      surfaces.push_back( surface_vertices );
 
421
      
 
422
      ++curr_surface;
 
423
      
 
424
   }
 
425
   
 
426
   std::cout << " %%%%%%%%%%%%%%%%%%%%%%% number of surfaces: " << surfaces.size() << std::endl;
 
427
   
 
428
   //
 
429
   // assert all vertices are assigned and share volume IDs with their neighbours
 
430
   //
 
431
   
 
432
   for ( unsigned int i = 0; i < surface_ids.size(); ++i )
 
433
   {
 
434
      if ( m_mesh.m_vtxedge[i].empty() ) { continue; }
 
435
      
 
436
      assert( surface_ids[i] != UNASSIGNED );
 
437
      
 
438
      const std::vector<unsigned int>& incident_edges = m_mesh.m_vtxedge[i];    
 
439
      for( unsigned int j = 0; j < incident_edges.size(); ++j )
 
440
      {
 
441
         unsigned int adjacent_vertex = m_mesh.m_edges[ incident_edges[j] ][0];
 
442
         if ( adjacent_vertex == i ) { adjacent_vertex = m_mesh.m_edges[ incident_edges[j] ][1]; }
 
443
         assert( surface_ids[adjacent_vertex] == surface_ids[i] );         
 
444
      } 
 
445
      
 
446
   }
 
447
   
 
448
}
 
449
 
 
450
 
 
451
// ---------------------------------------------------------
 
452
///
 
453
/// Compute the maximum timestep that will not invert any triangle normals, using a quadratic solve as in [Jiao 2007].
 
454
///
 
455
// ---------------------------------------------------------
 
456
 
 
457
double DynamicSurface::compute_max_timestep_quadratic_solve( const std::vector<Vec3ui>& tris, 
 
458
                                                       const std::vector<Vec3d>& positions, 
 
459
                                                       const std::vector<Vec3d>& displacements, 
 
460
                                                       bool verbose ) 
 
461
{
 
462
   double max_beta = 1.0;
 
463
   
 
464
   double min_area = 1e30;
 
465
   
 
466
   for ( unsigned int i = 0; i < tris.size(); ++i )
 
467
   {
 
468
      if ( tris[i][0] == tris[i][1] ) { continue; }
 
469
      
 
470
      const Vec3d& x1 = positions[tris[i][0]];
 
471
      const Vec3d& x2 = positions[tris[i][1]];
 
472
      const Vec3d& x3 = positions[tris[i][2]];
 
473
      
 
474
      const Vec3d& u1 = displacements[tris[i][0]];
 
475
      const Vec3d& u2 = displacements[tris[i][1]];
 
476
      const Vec3d& u3 = displacements[tris[i][2]];
 
477
      
 
478
      Vec3d new_x1 = x1 + u1;
 
479
      Vec3d new_x2 = x2 + u2;
 
480
      Vec3d new_x3 = x3 + u3;
 
481
      
 
482
      const Vec3d c0 = cross( (x2-x1), (x3-x1) );
 
483
      const Vec3d c1 = cross( (x2-x1), (u3-u1) ) - cross( (x3-x1), (u2-u1) );
 
484
      const Vec3d c2 = cross( (u2-u1), (u3-u1) );
 
485
      const double a = dot(c0, c2);
 
486
      const double b = dot(c0, c1);
 
487
      const double c = dot(c0, c0);
 
488
      
 
489
      double beta = 1.0;
 
490
      
 
491
      min_area = min( min_area, c );
 
492
      
 
493
      if ( c < 1e-14 )
 
494
      {
 
495
         if ( verbose ) 
 
496
         {
 
497
            printf( "super small triangle %d (%d %d %d)\n", i, tris[i][0], tris[i][1], tris[i][2] );
 
498
         }
 
499
      }
 
500
      
 
501
      if ( fabs(a) == 0 )
 
502
      {
 
503
         if ( verbose ) 
 
504
         { 
 
505
            //printf( "triangle %d: ", i ); 
 
506
            //printf( "a == 0 (%g)\n", a ); 
 
507
         }
 
508
         
 
509
         if ( ( fabs(b) > 1e-14 ) && ( -c / b >= 0.0 ) )
 
510
         {
 
511
            beta = -c / b;
 
512
         }
 
513
         else
 
514
         {
 
515
            if ( verbose )
 
516
            {
 
517
               if ( fabs(b) < 1e-14 )
 
518
               {
 
519
                  printf( "triangle %d: ", i ); 
 
520
                  printf( "b == 0 too (%g).\n", b );
 
521
               }
 
522
            }
 
523
         }
 
524
      }
 
525
      else
 
526
      {
 
527
         double descriminant = b*b - 4.0*a*c;
 
528
         
 
529
         if ( descriminant < 0.0  )
 
530
         {
 
531
            // Hmm, what does this mean?
 
532
            if ( verbose )
 
533
            {
 
534
               printf( "triangle %d: descriminant == %g\n", i, descriminant );
 
535
            }
 
536
            
 
537
            beta = 1.0;
 
538
         }
 
539
         else
 
540
         {
 
541
            double q;
 
542
            if ( b > 0.0 )
 
543
            {
 
544
               q = -0.5 * ( b + sqrt( descriminant ) );
 
545
            }
 
546
            else
 
547
            {
 
548
               q = -0.5 * ( b - sqrt( descriminant ) );
 
549
            }
 
550
            
 
551
            double beta_1 = q / a;
 
552
            double beta_2 = c / q;
 
553
            
 
554
            if ( beta_1 < 0.0 )
 
555
            {
 
556
               if ( beta_2 < 0.0 )
 
557
               {
 
558
                  assert( dot( triangle_normal(x1, x2, x3), triangle_normal(new_x1, new_x2, new_x3) ) > 0.0 );
 
559
               }
 
560
               else
 
561
               {
 
562
                  beta = beta_2;
 
563
               }
 
564
            }
 
565
            else
 
566
            {
 
567
               if ( beta_2 < 0.0 )
 
568
               {
 
569
                  beta = beta_1;
 
570
               }
 
571
               else if ( beta_1 < beta_2 )
 
572
               {
 
573
                  beta = beta_1;
 
574
               }
 
575
               else
 
576
               {
 
577
                  beta = beta_2;
 
578
               }
 
579
            }
 
580
            
 
581
         }
 
582
      }
 
583
      
 
584
      bool changed = false;
 
585
      if ( beta < max_beta )
 
586
      {
 
587
         max_beta = 0.99 * beta;
 
588
         changed = true;
 
589
         
 
590
         if ( verbose )
 
591
         {
 
592
            printf( "changing beta --- triangle: %d\n", i );
 
593
            printf( "new max beta: %g\n", max_beta );
 
594
            printf( "a = %g, b = %g, c = %g\n", a, b, c );
 
595
         }
 
596
         
 
597
         if ( max_beta < 1e-4 )
 
598
         {
 
599
            //assert(0);
 
600
         }
 
601
         
 
602
      }
 
603
      
 
604
      new_x1 = x1 + max_beta * u1;
 
605
      new_x2 = x2 + max_beta * u2;
 
606
      new_x3 = x3 + max_beta * u3;
 
607
      
 
608
      Vec3d old_normal = cross(x2-x1, x3-x1);
 
609
      Vec3d new_normal = cross(new_x2-new_x1, new_x3-new_x1);
 
610
      
 
611
      if ( dot( old_normal, new_normal ) < 0.0 )
 
612
      {
 
613
         printf( "triangle %d: (%d %d %d)\n", i, tris[i][0], tris[i][1], tris[i][2] );
 
614
         printf( "old normal: %g %g %g\n", old_normal[0], old_normal[1], old_normal[2] );
 
615
         printf( "new normal: %g %g %g\n", new_normal[0], new_normal[1], new_normal[2] );         
 
616
         printf( "dot product: %g\n", dot( triangle_normal(x1, x2, x3), triangle_normal(new_x1, new_x2, new_x3) ) );
 
617
         printf( "%s\n", (changed ? "changed" : "not changed") );
 
618
         printf( "beta: %g\n", beta );
 
619
         printf( "max beta: %g\n", max_beta );
 
620
         //assert(0);
 
621
      }
 
622
   }
 
623
   
 
624
   return max_beta;
 
625
}
 
626
 
 
627
 
 
628
// ---------------------------------------------------------
 
629
///
 
630
/// Compute the unsigned distance to the surface.
 
631
///
 
632
// ---------------------------------------------------------
 
633
 
 
634
double DynamicSurface::distance_to_surface( const Vec3d& p, unsigned int& closest_triangle )
 
635
{
 
636
   
 
637
   double padding = m_proximity_epsilon;
 
638
   double min_distance = 1e30;
 
639
   
 
640
   while ( min_distance == 1e30 )
 
641
   {
 
642
      
 
643
      Vec3d xmin( p - Vec3d( padding ) );
 
644
      Vec3d xmax( p + Vec3d( padding ) );
 
645
      
 
646
      std::vector<unsigned int> nearby_triangles;   
 
647
      
 
648
      m_broad_phase->get_potential_triangle_collisions( xmin, xmax, nearby_triangles );
 
649
            
 
650
      for ( unsigned int j = 0; j < nearby_triangles.size(); ++j )
 
651
      {
 
652
         const Vec3ui& tri = m_mesh.m_tris[ nearby_triangles[j] ];
 
653
 
 
654
         if ( tri[0] == tri[1] || tri[1] == tri[2] || tri[0] == tri[2] ) { continue; }
 
655
 
 
656
         if ( m_masses[tri[0]] > 1.5 && m_masses[tri[1]] > 1.5 && m_masses[tri[2]] > 1.5 ) { continue; }
 
657
         
 
658
         double curr_distance;
 
659
         check_point_triangle_proximity( p, m_positions[tri[0]], m_positions[tri[1]], m_positions[tri[2]], curr_distance );
 
660
         if ( curr_distance < padding )
 
661
         {   
 
662
            min_distance = min( min_distance, curr_distance );
 
663
            closest_triangle = nearby_triangles[j];
 
664
         }
 
665
      }
 
666
 
 
667
      padding *= 2.0;
 
668
 
 
669
   }
 
670
 
 
671
   return min_distance;
 
672
 
 
673
}
 
674
 
 
675
 
 
676
// ---------------------------------------------------------
 
677
///
 
678
/// Run intersection detection against all triangles
 
679
///
 
680
// ---------------------------------------------------------
 
681
 
 
682
void DynamicSurface::get_triangle_intersections( const Vec3d& segment_point_a, 
 
683
                                                 const Vec3d& segment_point_b,
 
684
                                                 std::vector<double>& hit_ss,
 
685
                                                 std::vector<unsigned int>& hit_triangles ) const
 
686
{
 
687
   Vec3d aabb_low, aabb_high;
 
688
   minmax( segment_point_a, segment_point_b, aabb_low, aabb_high );
 
689
   
 
690
   std::vector<unsigned int> overlapping_triangles;
 
691
   m_broad_phase->get_potential_triangle_collisions( aabb_low, aabb_high, overlapping_triangles );
 
692
   
 
693
   for ( unsigned int i = 0; i < overlapping_triangles.size(); ++i )
 
694
   {
 
695
      const Vec3ui& tri = m_mesh.m_tris[ overlapping_triangles[i] ];
 
696
      
 
697
      Vec3ui t = sort_triangle( tri );
 
698
      assert( t[0] < t[1] && t[0] < t[2] && t[1] < t[2] );
 
699
      
 
700
      const Vec3d& v0 = m_positions[ t[0] ];
 
701
      const Vec3d& v1 = m_positions[ t[1] ];
 
702
      const Vec3d& v2 = m_positions[ t[2] ];      
 
703
      
 
704
      unsigned int dummy_index = m_positions.size();
 
705
      
 
706
      double bary1, bary2, bary3;
 
707
      Vec3d normal;
 
708
      double s;
 
709
      double relative_normal_displacement;
 
710
      
 
711
      bool hit = point_triangle_collision( segment_point_a, segment_point_b, dummy_index,
 
712
                                           v0, v0, t[0],
 
713
                                           v1, v1, t[1],
 
714
                                           v2, v2, t[2],
 
715
                                           bary1, bary2, bary3,
 
716
                                           normal,
 
717
                                           s, relative_normal_displacement );
 
718
                                
 
719
      if ( hit )
 
720
      {
 
721
         hit_ss.push_back( s );
 
722
         hit_triangles.push_back( overlapping_triangles[i] );
 
723
      }         
 
724
      
 
725
   }
 
726
   
 
727
}
 
728
 
 
729
// ---------------------------------------------------------
 
730
///
 
731
/// Run intersection detection against all triangles and return the number of hits.
 
732
///
 
733
// ---------------------------------------------------------
 
734
 
 
735
unsigned int DynamicSurface::get_number_of_triangle_intersections( const Vec3d& segment_point_a, 
 
736
                                                                   const Vec3d& segment_point_b ) const
 
737
{
 
738
   int num_hits = 0;
 
739
   int num_misses = 0;
 
740
   Vec3d aabb_low, aabb_high;
 
741
   minmax( segment_point_a, segment_point_b, aabb_low, aabb_high );
 
742
   
 
743
   std::vector<unsigned int> overlapping_triangles;
 
744
   m_broad_phase->get_potential_triangle_collisions( aabb_low, aabb_high, overlapping_triangles );
 
745
 
 
746
   for ( unsigned int i = 0; i < overlapping_triangles.size(); ++i )
 
747
   {
 
748
      const Vec3ui& tri = m_mesh.m_tris[ overlapping_triangles[i] ];
 
749
      
 
750
      Vec3ui t = sort_triangle( tri );
 
751
      assert( t[0] < t[1] && t[0] < t[2] && t[1] < t[2] );
 
752
      
 
753
      const Vec3d& v0 = m_positions[ t[0] ];
 
754
      const Vec3d& v1 = m_positions[ t[1] ];
 
755
      const Vec3d& v2 = m_positions[ t[2] ];      
 
756
      
 
757
      unsigned int dummy_index = m_positions.size();
 
758
      static const bool degenerate_counts_as_hit = true;
 
759
 
 
760
      bool hit = segment_triangle_intersection( segment_point_a, dummy_index,
 
761
                                                segment_point_b, dummy_index + 1, 
 
762
                                                v0, t[0],
 
763
                                                v1, t[1],
 
764
                                                v2, t[2],   
 
765
                                                degenerate_counts_as_hit );
 
766
      
 
767
      if ( hit )
 
768
      {
 
769
         ++num_hits;
 
770
      }         
 
771
      else
 
772
      {
 
773
         ++num_misses;
 
774
      }
 
775
   }
 
776
      
 
777
   return num_hits;
 
778
 
 
779
}
 
780
 
 
781
 
 
782
#ifdef USE_EXACT_ARITHMETIC_RAY_CASTING
 
783
 
 
784
static Mat44d look_at(const Vec3d& from,
 
785
                      const Vec3d& to)
 
786
{
 
787
   Mat44d T;
 
788
   Vec3d c=-normalized(to-from);
 
789
   Vec3d a=cross(Vec3d(0,1,0), c);
 
790
   Vec3d b=cross(c, a);
 
791
   
 
792
   T(0,0)=a[0]; T(0,1)=a[1]; T(0,2)=a[2]; T(0,3) = -dot(a,from);
 
793
   T(1,0)=b[0]; T(1,1)=b[1]; T(1,2)=b[2]; T(1,3) = -dot(b,from);
 
794
   T(2,0)=c[0]; T(2,1)=c[1]; T(2,2)=c[2]; T(2,3) = -dot(c,from);
 
795
   T(3,0)=0.0;  T(3,1)=0.0;  T(3,2)=0.0;  T(3,3) = 1.0;
 
796
   
 
797
   return T;
 
798
}
 
799
 
 
800
static Vec3d apply_to_point( const Mat44d& M, const Vec3d& x )
 
801
{
 
802
   double w = M(3,0)*x[0] + M(3,1)*x[1] + M(3,2)*x[2] + M(3,3);
 
803
   
 
804
   return Vec3d((M(0,0)*x[0] + M(0,1)*x[1] + M(0,2)*x[2] + M(0,3))/w,
 
805
                (M(1,0)*x[0] + M(1,1)*x[1] + M(1,2)*x[2] + M(1,3))/w,
 
806
                (M(2,0)*x[0] + M(2,1)*x[1] + M(2,2)*x[2] + M(2,3))/w );
 
807
}
 
808
 
 
809
// ---------------------------------------------------------
 
810
///
 
811
/// Run intersection detection against all triangles and return the number of hits.  Use exact arithmetic.
 
812
///
 
813
// ---------------------------------------------------------
 
814
 
 
815
unsigned int DynamicSurface::get_number_of_triangle_intersections_exact( const Vec3d& segment_point_a, 
 
816
                                                                         const Vec3d& segment_point_b ) const
 
817
{
 
818
   int num_hits = 0;
 
819
   int num_misses = 0;
 
820
   Vec3d aabb_low, aabb_high;
 
821
   minmax( segment_point_a, segment_point_b, aabb_low, aabb_high );
 
822
   
 
823
   std::vector<unsigned int> overlapping_triangles;
 
824
   m_broad_phase->get_potential_triangle_collisions( aabb_low, aabb_high, overlapping_triangles );
 
825
   
 
826
   for ( unsigned int i = 0; i < overlapping_triangles.size(); ++i )
 
827
   {
 
828
      const Vec3ui& tri = m_mesh.m_tris[ overlapping_triangles[i] ];
 
829
      
 
830
      Vec3ui t = sort_triangle( tri );
 
831
      assert( t[0] < t[1] && t[0] < t[2] && t[1] < t[2] );
 
832
      
 
833
      const Vec3d v0 = (m_positions[ t[0] ]);
 
834
      const Vec3d v1 = (m_positions[ t[1] ]);
 
835
      const Vec3d v2 = (m_positions[ t[2] ]);      
 
836
            
 
837
      Vec3d ortho = cross( v1-v0, v2-v0 );
 
838
      
 
839
      double ray_length = mag( segment_point_b - segment_point_a );
 
840
      Vec3d ray_direction = ( segment_point_b - segment_point_a ) / ray_length;
 
841
      Vec3d ray_origin( segment_point_a );
 
842
      
 
843
      // find plane intersection with ray
 
844
      double dn=dot( ray_direction, ortho );
 
845
 
 
846
      if ( dn==0 )
 
847
      {
 
848
         ++num_misses;
 
849
         continue;
 
850
      }
 
851
   
 
852
      double s0 = -dot( ray_origin - v0, ortho ) / dn;
 
853
 
 
854
      if ( s0 < 0 || s0 > ray_length ) 
 
855
      { 
 
856
         // no hit
 
857
         ++num_misses;
 
858
         continue;
 
859
      }
 
860
      
 
861
      Mat44d transform = look_at( ray_direction, Vec3d(0,0,0) );
 
862
      
 
863
      Vec3d a = apply_to_point( transform, v0 - ray_origin );
 
864
      Vec3d b = apply_to_point( transform, v1 - ray_origin );
 
865
      Vec3d c = apply_to_point( transform, v2 - ray_origin );
 
866
      
 
867
      Vec2d a2( a[0], a[1] );
 
868
      Vec2d b2( b[0], b[1] );
 
869
      Vec2d c2( c[0], c[1] );
 
870
      Vec2d r2( 0, 0 );
 
871
      
 
872
      //std::cout << "2d triangle: " << a2 << ", " << b2 << ", " << c2 << std::endl;
 
873
      
 
874
      double bary[4];
 
875
      int dummy_index = m_positions.size();
 
876
      int result = sos_simplex_intersection2d( 3, 
 
877
                                               t[0], a2.v, 
 
878
                                               t[1], b2.v, 
 
879
                                               t[2], c2.v, 
 
880
                                               dummy_index, r2.v, 
 
881
                                               &(bary[0]), &(bary[1]), &(bary[2]), &(bary[3]) );
 
882
 
 
883
      if ( result != 0 )
 
884
      {
 
885
         ++num_hits;
 
886
      }         
 
887
      else
 
888
      {
 
889
         ++num_misses;
 
890
      }
 
891
   }
 
892
   
 
893
   return num_hits;
 
894
}
 
895
 
 
896
#endif
 
897
 
 
898
 
 
899
// ---------------------------------------------------------
 
900
///
 
901
/// Determine whether a point is inside the volume defined by the surface.  Uses raycast-voting.
 
902
///
 
903
// ---------------------------------------------------------
 
904
 
 
905
bool DynamicSurface::point_is_inside( const Vec3d& p )
 
906
{
 
907
 
 
908
#ifdef USE_EXACT_ARITHMETIC_RAY_CASTING
 
909
   
 
910
   // Exact arithmetic ray casting:
 
911
   Vec3d ray_end( p + Vec3d( 1e+3, 1, 0 ) );
 
912
   int hits = get_number_of_triangle_intersections_exact( p, ray_end );
 
913
   
 
914
   if ( hits % 2 == 1 ) { return true; }   
 
915
   return false;
 
916
   
 
917
#else
 
918
   
 
919
   //
 
920
   // The point is inside if there are an odd number of hits on a ray cast from the point. 
 
921
   // We'll cast six rays for numerical robustness.
 
922
   //
 
923
 
 
924
   
 
925
   unsigned int inside_votes = 0;
 
926
   
 
927
   // shoot a ray in the positive-x direction
 
928
   Vec3d ray_end( p + Vec3d( 1e+3, 1, 0 ) );
 
929
   int hits = get_number_of_triangle_intersections( p, ray_end );
 
930
   if ( hits % 2 == 1 ) { ++inside_votes; }
 
931
   
 
932
   // negative x
 
933
   ray_end = p - Vec3d( 1e+3, 0, 1 );
 
934
   hits = get_number_of_triangle_intersections( p, ray_end );
 
935
   if ( hits % 2 == 1 ) { ++inside_votes; }
 
936
 
 
937
   // positive y
 
938
   ray_end = p + Vec3d( 1, 1e+3, 0 );
 
939
   hits = get_number_of_triangle_intersections( p, ray_end );
 
940
   if ( hits % 2 == 1 ) { ++inside_votes; }
 
941
 
 
942
   // negative y
 
943
   ray_end = p - Vec3d( 0, 1e+3, 1 );
 
944
   hits = get_number_of_triangle_intersections( p, ray_end );
 
945
   if ( hits % 2 == 1 ) { ++inside_votes; }
 
946
 
 
947
   // positive z
 
948
   ray_end = p + Vec3d( 0, 1, 1e+3 );
 
949
   hits = get_number_of_triangle_intersections( p, ray_end );
 
950
   if ( hits % 2 == 1 ) { ++inside_votes; }
 
951
   
 
952
   // negative z
 
953
   ray_end = p - Vec3d( 1, 0, 1e+3 );
 
954
   hits = get_number_of_triangle_intersections( p, ray_end );
 
955
   if ( hits % 2 == 1 ) { ++inside_votes; }
 
956
   
 
957
   return ( inside_votes > 3 );
 
958
   
 
959
#endif
 
960
   
 
961
}
 
962
 
 
963
 
 
964
// ---------------------------------------------------------
 
965
///
 
966
/// Remove all vertices not incident on any triangles.
 
967
///
 
968
// ---------------------------------------------------------
 
969
 
 
970
void DynamicSurface::clear_deleted_vertices( )
 
971
{
 
972
 
 
973
   unsigned int j = 0;
 
974
   
 
975
   for ( unsigned int i = 0; i < m_positions.size(); ++i )
 
976
   {
 
977
      std::vector<unsigned int>& inc_tris = m_mesh.m_vtxtri[i];
 
978
 
 
979
      if ( inc_tris.size() != 0 )
 
980
      {
 
981
         m_positions[j] = m_positions[i];
 
982
         m_newpositions[j] = m_newpositions[i];
 
983
         m_velocities[j] = m_velocities[i];
 
984
         m_masses[j] = m_masses[i];
 
985
         
 
986
         for ( unsigned int t = 0; t < inc_tris.size(); ++t )
 
987
         {
 
988
            Vec3ui& triangle = m_mesh.m_tris[ inc_tris[t] ];
 
989
            
 
990
            if ( triangle[0] == i ) { triangle[0] = j; }
 
991
            if ( triangle[1] == i ) { triangle[1] = j; }
 
992
            if ( triangle[2] == i ) { triangle[2] = j; }            
 
993
         }
 
994
         
 
995
         ++j;
 
996
      }
 
997
 
 
998
   }
 
999
      
 
1000
   m_positions.resize(j);
 
1001
   m_newpositions.resize(j);
 
1002
   m_velocities.resize(j);
 
1003
   m_masses.resize(j);
 
1004
 
 
1005
}
 
1006
 
 
1007
 
 
1008
// ---------------------------------------------------------
 
1009
///
 
1010
/// Apply an impulse between two edges 
 
1011
///
 
1012
// ---------------------------------------------------------
 
1013
 
 
1014
void DynamicSurface::apply_edge_edge_impulse( const Vec2ui& edge0, 
 
1015
                                              const Vec2ui& edge1,
 
1016
                                              double s0, 
 
1017
                                              double s2, 
 
1018
                                              Vec3d& direction, 
 
1019
                                              double magnitude )
 
1020
{
 
1021
   Vec3d& v0 = m_velocities[edge0[0]];
 
1022
   Vec3d& v1 = m_velocities[edge0[1]];
 
1023
   Vec3d& v2 = m_velocities[edge1[0]];
 
1024
   Vec3d& v3 = m_velocities[edge1[1]];
 
1025
   double inv_m0 = m_masses[edge0[0]] < 100 ? 1 / m_masses[edge0[0]] : 0.0;
 
1026
   double inv_m1 = m_masses[edge0[1]] < 100 ? 1 / m_masses[edge0[1]] : 0.0;
 
1027
   double inv_m2 = m_masses[edge1[0]] < 100 ? 1 / m_masses[edge1[0]] : 0.0;
 
1028
   double inv_m3 = m_masses[edge1[1]] < 100 ? 1 / m_masses[edge1[1]] : 0.0;
 
1029
    
 
1030
   double s1 = 1.0 - s0;
 
1031
   double s3 = 1.0 - s2;
 
1032
   double i = magnitude/(s0*s0*inv_m0 + s1*s1*inv_m1 + s2*s2*inv_m2 + s3*s3*inv_m3);
 
1033
   
 
1034
   v0 += i*s0*inv_m0 * direction;
 
1035
   v1 += i*s1*inv_m1 * direction;
 
1036
   v2 -= i*s2*inv_m2 * direction;
 
1037
   v3 -= i*s3*inv_m3 * direction;
 
1038
}
 
1039
 
 
1040
// ---------------------------------------------------------
 
1041
///
 
1042
/// Apply an impulse between a point and a triangle
 
1043
///
 
1044
// ---------------------------------------------------------
 
1045
 
 
1046
void DynamicSurface::apply_triangle_point_impulse( const Vec3ui& tri, 
 
1047
                                                   unsigned int v,
 
1048
                                                   double s1, 
 
1049
                                                   double s2, 
 
1050
                                                   double s3, 
 
1051
                                                   Vec3d& direction, 
 
1052
                                                   double magnitude )
 
1053
{
 
1054
 
 
1055
   Vec3d& v0 = m_velocities[v];
 
1056
   Vec3d& v1 = m_velocities[tri[0]];
 
1057
   Vec3d& v2 = m_velocities[tri[1]];
 
1058
   Vec3d& v3 = m_velocities[tri[2]];
 
1059
   double inv_m0 = m_masses[v] < 100 ? 1 / m_masses[v] : 0.0;
 
1060
   double inv_m1 = m_masses[tri[0]] < 100 ? 1 / m_masses[tri[0]] : 0.0;
 
1061
   double inv_m2 = m_masses[tri[1]] < 100 ? 1 / m_masses[tri[1]] : 0.0;
 
1062
   double inv_m3 = m_masses[tri[2]] < 100 ? 1 / m_masses[tri[2]] : 0.0;
 
1063
 
 
1064
   double i = magnitude / (inv_m0 + s1*s1*inv_m1 + s2*s2*inv_m2 + s3*s3*inv_m3);
 
1065
 
 
1066
   v0 += (i*inv_m0) * direction;
 
1067
   v1 -= (i*s1*inv_m1) * direction;
 
1068
   v2 -= (i*s2*inv_m2) * direction;
 
1069
   v3 -= (i*s3*inv_m3) * direction;
 
1070
}
 
1071
 
 
1072
 
 
1073
 
 
1074
// ---------------------------------------------------------
 
1075
///
 
1076
/// Detect all triangle-point proximities and apply repulsion impulses
 
1077
///
 
1078
// ---------------------------------------------------------
 
1079
 
 
1080
void DynamicSurface::handle_triangle_point_proximities( double dt )
 
1081
{
 
1082
 
 
1083
   unsigned int broadphase_hits = 0;
 
1084
   unsigned int point_triangle_proximities = 0;
 
1085
   
 
1086
   for ( unsigned int i = 0; i < m_mesh.m_tris.size(); ++i )
 
1087
   {
 
1088
      const Vec3ui& tri = m_mesh.m_tris[i];
 
1089
      
 
1090
      if ( tri[0] == tri[1] )    { continue; }
 
1091
 
 
1092
 
 
1093
      Vec3d low, high;
 
1094
      triangle_static_bounds( i, low, high );
 
1095
      std::vector<unsigned int> potential_vertex_collisions;
 
1096
      m_broad_phase->get_potential_vertex_collisions( low, high, potential_vertex_collisions );
 
1097
      
 
1098
      for ( unsigned int j = 0; j < potential_vertex_collisions.size(); ++j )
 
1099
      {
 
1100
         unsigned int v = potential_vertex_collisions[j];
 
1101
   
 
1102
         if(tri[0] != v && tri[1] != v && tri[2] != v)
 
1103
         {
 
1104
            ++broadphase_hits;
 
1105
            double distance, s1, s2, s3;
 
1106
            Vec3d normal;
 
1107
            
 
1108
            point_triangle_distance( m_positions[v], v,
 
1109
                                     m_positions[tri[0]], tri[0],
 
1110
                                     m_positions[tri[1]], tri[1],
 
1111
                                     m_positions[tri[2]], tri[2],
 
1112
                                     distance, s1, s2, s3, normal );
 
1113
            
 
1114
            if(distance < m_proximity_epsilon)
 
1115
            {
 
1116
               
 
1117
               double relvel = dot(normal, m_velocities[v] - (s1*m_velocities[tri[0]] + s2*m_velocities[tri[1]] + s3*m_velocities[tri[2]]));
 
1118
               double desired_relative_velocity = ( m_proximity_epsilon - distance ) / dt;
 
1119
               double impulse = (desired_relative_velocity - relvel);
 
1120
               
 
1121
               apply_triangle_point_impulse( tri, v, s1, s2, s3, normal, impulse);
 
1122
               
 
1123
               ++point_triangle_proximities;
 
1124
               
 
1125
            }
 
1126
         }      
 
1127
      }
 
1128
   }
 
1129
 
 
1130
}
 
1131
 
 
1132
 
 
1133
// ---------------------------------------------------------
 
1134
///
 
1135
/// Detect all edge-edge proximities and apply repulsion impulses
 
1136
///
 
1137
// ---------------------------------------------------------
 
1138
 
 
1139
void DynamicSurface::handle_edge_edge_proximities( double dt )
 
1140
{
 
1141
 
 
1142
   unsigned int edge_edge_proximities = 0;
 
1143
   
 
1144
   for ( unsigned int i = 0; i < m_mesh.m_edges.size(); ++i )
 
1145
   {
 
1146
      const Vec2ui& e0 = m_mesh.m_edges[ i ];
 
1147
      
 
1148
      if ( e0[0] == e0[1] ) { continue; }
 
1149
      
 
1150
      Vec3d low, high;
 
1151
      edge_static_bounds( i, low, high );
 
1152
      std::vector<unsigned int> potential_collisions;
 
1153
      m_broad_phase->get_potential_edge_collisions( low, high, potential_collisions );
 
1154
      
 
1155
      for ( unsigned int j = 0; j < potential_collisions.size(); ++j )
 
1156
      {
 
1157
         if ( potential_collisions[j] <= i )    { continue; }
 
1158
         
 
1159
         const Vec2ui& e1 = m_mesh.m_edges[ potential_collisions[j] ];
 
1160
         
 
1161
         if ( e1[0] == e1[1] )   { continue; }
 
1162
         
 
1163
         if(e0[0] != e1[0] && e0[0] != e1[1] && e0[1] != e1[0] && e0[1] != e1[1])
 
1164
         {
 
1165
            double distance, s0, s2;
 
1166
            Vec3d normal;
 
1167
            
 
1168
            segment_segment_distance( m_positions[e0[0]], e0[0],
 
1169
                                      m_positions[e0[1]], e0[1],
 
1170
                                      m_positions[e1[0]], e1[0],
 
1171
                                      m_positions[e1[1]], e0[1],
 
1172
                                      distance, s0, s2, normal);
 
1173
            
 
1174
            if( distance < m_proximity_epsilon )
 
1175
            {
 
1176
               ++edge_edge_proximities;
 
1177
               
 
1178
               double relvel = dot(normal, s0*m_velocities[e0[0]] + (1.0-s0)*m_velocities[e0[1]] - (s2*m_velocities[e1[0]] + (1.0-s2)*m_velocities[e1[1]]));
 
1179
               double desired_relative_velocity = ( m_proximity_epsilon - distance ) / dt;               
 
1180
               double impulse = ( desired_relative_velocity - relvel );
 
1181
               
 
1182
               apply_edge_edge_impulse( e0, e1, s0, s2, normal, impulse);
 
1183
            }
 
1184
         }
 
1185
      }
 
1186
   }
 
1187
   
 
1188
}
 
1189
 
 
1190
 
 
1191
// ---------------------------------------------------------
 
1192
///
 
1193
/// Add point-triangle collision candidates for a specified triangle
 
1194
///
 
1195
// ---------------------------------------------------------
 
1196
 
 
1197
void DynamicSurface::add_triangle_candidates(unsigned int t, CollisionCandidateSet& collision_candidates)
 
1198
{
 
1199
   Vec3d tmin, tmax;
 
1200
   triangle_continuous_bounds(t, tmin, tmax);
 
1201
   tmin -= Vec3d( m_proximity_epsilon, m_proximity_epsilon, m_proximity_epsilon );
 
1202
   tmax += Vec3d( m_proximity_epsilon, m_proximity_epsilon, m_proximity_epsilon );
 
1203
   
 
1204
   std::vector<unsigned int> candidate_vertices;
 
1205
   m_broad_phase->get_potential_vertex_collisions( tmin, tmax, candidate_vertices );
 
1206
   
 
1207
   for(unsigned int j = 0; j < candidate_vertices.size(); j++)
 
1208
   {
 
1209
      add_to_collision_candidates( collision_candidates, Vec3ui(t, candidate_vertices[j], 0) );
 
1210
   }
 
1211
   
 
1212
}
 
1213
 
 
1214
// ---------------------------------------------------------
 
1215
///
 
1216
/// Add edge-edge collision candidates for a specified edge
 
1217
///
 
1218
// ---------------------------------------------------------
 
1219
 
 
1220
void DynamicSurface::add_edge_candidates(unsigned int e, CollisionCandidateSet& collision_candidates)
 
1221
{
 
1222
   Vec3d emin, emax;
 
1223
   edge_continuous_bounds(e, emin, emax);
 
1224
   emin -= Vec3d( m_proximity_epsilon, m_proximity_epsilon, m_proximity_epsilon );
 
1225
   emax += Vec3d( m_proximity_epsilon, m_proximity_epsilon, m_proximity_epsilon );
 
1226
   
 
1227
   std::vector<unsigned int> candidate_edges;
 
1228
   m_broad_phase->get_potential_edge_collisions( emin, emax, candidate_edges);
 
1229
   
 
1230
   for(unsigned int j = 0; j < candidate_edges.size(); j++)
 
1231
   {
 
1232
      add_to_collision_candidates( collision_candidates, Vec3ui(e, candidate_edges[j], 1) );
 
1233
   }
 
1234
}
 
1235
 
 
1236
// ---------------------------------------------------------
 
1237
///
 
1238
/// Add point-triangle collision candidates for a specified vertex
 
1239
///
 
1240
// ---------------------------------------------------------
 
1241
 
 
1242
void DynamicSurface::add_point_candidates(unsigned int v, CollisionCandidateSet& collision_candidates)
 
1243
{
 
1244
   Vec3d vmin, vmax;
 
1245
   vertex_continuous_bounds(v, vmin, vmax);
 
1246
   vmin -= Vec3d( m_proximity_epsilon, m_proximity_epsilon, m_proximity_epsilon );
 
1247
   vmax += Vec3d( m_proximity_epsilon, m_proximity_epsilon, m_proximity_epsilon );
 
1248
   
 
1249
   std::vector<unsigned int> candidate_triangles;
 
1250
   m_broad_phase->get_potential_triangle_collisions( vmin, vmax, candidate_triangles);
 
1251
   
 
1252
   for(unsigned int j = 0; j < candidate_triangles.size(); j++)
 
1253
   {
 
1254
      add_to_collision_candidates( collision_candidates, Vec3ui(candidate_triangles[j], v, 0) );
 
1255
   }
 
1256
}
 
1257
 
 
1258
// ---------------------------------------------------------
 
1259
///
 
1260
/// Add collision candidates for a specified vertex and all elements incident on the vertex
 
1261
///
 
1262
// ---------------------------------------------------------
 
1263
 
 
1264
void DynamicSurface::add_point_update_candidates(unsigned int v, CollisionCandidateSet& collision_candidates)
 
1265
{
 
1266
   add_point_candidates(v, collision_candidates);
 
1267
   
 
1268
   std::vector<unsigned int>& incident_triangles = m_mesh.m_vtxtri[v];
 
1269
   std::vector<unsigned int>& incident_edges = m_mesh.m_vtxedge[v];
 
1270
   
 
1271
   for(unsigned int i = 0; i < incident_triangles.size(); i++)
 
1272
      add_triangle_candidates(incident_triangles[i], collision_candidates);
 
1273
   
 
1274
   for(unsigned int i = 0; i < incident_edges.size(); i++)
 
1275
      add_edge_candidates(incident_edges[i], collision_candidates);
 
1276
}
 
1277
 
 
1278
 
 
1279
// ---------------------------------------------------------
 
1280
///
 
1281
/// Perform one sweep of impulse collision handling, only for "deformable" vertices against "solid" triangles
 
1282
///
 
1283
// ---------------------------------------------------------
 
1284
 
 
1285
void DynamicSurface::handle_point_vs_solid_triangle_collisions( double dt )
 
1286
{
 
1287
   
 
1288
   for(unsigned int i = 0; i < m_mesh.m_tris.size(); i++)
 
1289
   {
 
1290
      CollisionCandidateSet triangle_collision_candidates;
 
1291
      add_triangle_candidates(i, triangle_collision_candidates);
 
1292
      
 
1293
      while( false == triangle_collision_candidates.empty() )
 
1294
      {
 
1295
         CollisionCandidateSet::iterator iter = triangle_collision_candidates.begin();
 
1296
         Vec3ui candidate = *iter;
 
1297
         triangle_collision_candidates.erase(iter);
 
1298
      
 
1299
         unsigned int t = candidate[0];
 
1300
         Vec3ui tri = m_mesh.m_tris[t];
 
1301
         unsigned int v = candidate[1];
 
1302
         
 
1303
         if ( m_masses[v] < 100 && m_masses[tri[0]] > 100 && m_masses[tri[1]] > 100 && m_masses[tri[2]] > 100 )
 
1304
         {
 
1305
         
 
1306
            if(tri[0] != v && tri[1] != v && tri[2] != v)
 
1307
            {
 
1308
               double time, s1, s2, s3, rel_disp;
 
1309
               Vec3d normal;
 
1310
                            
 
1311
               Vec3ui sorted_tri = sort_triangle( tri );
 
1312
               
 
1313
               assert( sorted_tri[0] < sorted_tri[1] && sorted_tri[0] < sorted_tri[2] && sorted_tri[1] < sorted_tri[2] );
 
1314
               
 
1315
               if ( point_triangle_collision( m_positions[v], m_newpositions[v], v, 
 
1316
                                             m_positions[sorted_tri[0]], m_newpositions[sorted_tri[0]], sorted_tri[0],
 
1317
                                             m_positions[sorted_tri[1]], m_newpositions[sorted_tri[1]], sorted_tri[1],
 
1318
                                             m_positions[sorted_tri[2]], m_newpositions[sorted_tri[2]], sorted_tri[2],
 
1319
                                             s1, s2, s3,
 
1320
                                             normal,
 
1321
                                             time, rel_disp ) )                                 
 
1322
                  
 
1323
               {
 
1324
                  
 
1325
                  ++m_num_collisions_this_step;
 
1326
                  
 
1327
                  double relvel = rel_disp / dt;
 
1328
                  
 
1329
                  apply_triangle_point_impulse(sorted_tri, v, s1, s2, s3, normal, -relvel);
 
1330
                                  
 
1331
                  m_newpositions[v] = m_positions[v] + dt*m_velocities[v];
 
1332
                  m_newpositions[tri[0]] = m_positions[tri[0]] + dt*m_velocities[tri[0]];
 
1333
                  m_newpositions[tri[1]] = m_positions[tri[1]] + dt*m_velocities[tri[1]];
 
1334
                  m_newpositions[tri[2]] = m_positions[tri[2]] + dt*m_velocities[tri[2]];
 
1335
                  
 
1336
                  update_continuous_broad_phase( v );
 
1337
                  update_continuous_broad_phase( tri[0] );
 
1338
                  update_continuous_broad_phase( tri[1] );
 
1339
                  update_continuous_broad_phase( tri[2] );             
 
1340
               }
 
1341
                  
 
1342
            }
 
1343
         }
 
1344
      }      
 
1345
   }
 
1346
   
 
1347
}
 
1348
 
 
1349
 
 
1350
// ---------------------------------------------------------
 
1351
///
 
1352
/// Detect all continuous collisions and apply impulses to prevent them.
 
1353
/// Return true if all collisions were resolved.
 
1354
///
 
1355
// ---------------------------------------------------------
 
1356
 
 
1357
bool DynamicSurface::handle_collisions(double dt)
 
1358
{
 
1359
   
 
1360
   const unsigned int MAX_PASS = 3;
 
1361
   const unsigned int MAX_CANDIDATES = (unsigned int) 1e+6; 
 
1362
   
 
1363
   CollisionCandidateSet update_collision_candidates;
 
1364
   
 
1365
   if ( MAX_PASS == 0 )
 
1366
   {
 
1367
      return false;
 
1368
   }
 
1369
   
 
1370
   bool collision_found = true;
 
1371
   bool candidate_overflow = false;
 
1372
 
 
1373
   for ( unsigned int pass = 0; ( collision_found && (pass < MAX_PASS) ); ++pass )
 
1374
   {
 
1375
      collision_found = false;
 
1376
      
 
1377
      for(unsigned int i = 0; i < m_mesh.m_tris.size(); i++)
 
1378
      {
 
1379
         CollisionCandidateSet triangle_collision_candidates;
 
1380
         add_triangle_candidates(i, triangle_collision_candidates);
 
1381
         
 
1382
         while( false == triangle_collision_candidates.empty() )
 
1383
         {
 
1384
            CollisionCandidateSet::iterator iter = triangle_collision_candidates.begin();
 
1385
            Vec3ui candidate = *iter;
 
1386
            triangle_collision_candidates.erase(iter);
 
1387
            
 
1388
            unsigned int t = candidate[0];
 
1389
            Vec3ui tri = m_mesh.m_tris[t];
 
1390
            unsigned int v = candidate[1];
 
1391
            
 
1392
            if(tri[0] != v && tri[1] != v && tri[2] != v)
 
1393
            {
 
1394
               double time, s1, s2, s3, rel_disp;
 
1395
               Vec3d normal;              
 
1396
 
 
1397
               Vec3ui sorted_tri = sort_triangle( tri );
 
1398
 
 
1399
               if ( point_triangle_collision( m_positions[v], m_newpositions[v], v,
 
1400
                                             m_positions[sorted_tri[0]], m_newpositions[sorted_tri[0]], sorted_tri[0],
 
1401
                                             m_positions[sorted_tri[1]], m_newpositions[sorted_tri[1]], sorted_tri[1],
 
1402
                                             m_positions[sorted_tri[2]], m_newpositions[sorted_tri[2]], sorted_tri[2],
 
1403
                                             s1, s2, s3,
 
1404
                                             normal,
 
1405
                                             time, rel_disp ) )               
 
1406
                  
 
1407
               {
 
1408
                                                             
 
1409
                  ++m_num_collisions_this_step;
 
1410
                  
 
1411
                  double relvel = rel_disp / dt;
 
1412
                 
 
1413
                  apply_triangle_point_impulse(sorted_tri, v, s1, s2, s3, normal, -relvel);
 
1414
                  
 
1415
                  if ( m_verbose ) std::cout << "(PT) time: " << time << ", relative velocity before: " << relvel;
 
1416
                  
 
1417
                  double relvel_after = dot(normal, m_velocities[v] - (s1*m_velocities[sorted_tri[0]] + s2*m_velocities[sorted_tri[1]] + s3*m_velocities[sorted_tri[2]]));
 
1418
                  
 
1419
                  if ( m_verbose ) std::cout << " and relative velocity after: " << relvel_after << std::endl;
 
1420
                  
 
1421
                  m_newpositions[v] = m_positions[v] + dt*m_velocities[v];
 
1422
                  m_newpositions[tri[0]] = m_positions[tri[0]] + dt*m_velocities[tri[0]];
 
1423
                  m_newpositions[tri[1]] = m_positions[tri[1]] + dt*m_velocities[tri[1]];
 
1424
                  m_newpositions[tri[2]] = m_positions[tri[2]] + dt*m_velocities[tri[2]];
 
1425
                  
 
1426
                  update_continuous_broad_phase( v  );
 
1427
                  update_continuous_broad_phase( tri[0] );
 
1428
                  update_continuous_broad_phase( tri[1] );
 
1429
                  update_continuous_broad_phase( tri[2] );
 
1430
                                    
 
1431
                  if ( pass == MAX_PASS - 1 )
 
1432
                  {
 
1433
                     if ( update_collision_candidates.size() < MAX_CANDIDATES )
 
1434
                     {
 
1435
                        add_point_update_candidates(v, update_collision_candidates);
 
1436
                        add_point_update_candidates(tri[0], update_collision_candidates);
 
1437
                        add_point_update_candidates(tri[1], update_collision_candidates);
 
1438
                        add_point_update_candidates(tri[2], update_collision_candidates);
 
1439
                     }
 
1440
                     else
 
1441
                     {
 
1442
                        candidate_overflow = true;
 
1443
                     }
 
1444
                  }
 
1445
                  
 
1446
                  collision_found = true;
 
1447
                  
 
1448
               }            
 
1449
            }
 
1450
         }      
 
1451
      }
 
1452
         
 
1453
      m_verbose = false;
 
1454
      
 
1455
      for(unsigned int i = 0; i < m_mesh.m_edges.size(); i++)
 
1456
      {
 
1457
         CollisionCandidateSet edge_collision_candidates;
 
1458
         add_edge_candidates(i, edge_collision_candidates);
 
1459
                           
 
1460
         while ( false == edge_collision_candidates.empty() )
 
1461
         {
 
1462
            CollisionCandidateSet::iterator iter = edge_collision_candidates.begin();
 
1463
            Vec3ui candidate = *iter;
 
1464
            edge_collision_candidates.erase(iter);
 
1465
                     
 
1466
            Vec2ui e0 = m_mesh.m_edges[candidate[0]];
 
1467
            Vec2ui e1 = m_mesh.m_edges[candidate[1]];
 
1468
                                    
 
1469
            assert( candidate[0] == i );
 
1470
            
 
1471
            if ( candidate[1] <= i ) { continue; }
 
1472
            
 
1473
            if ( e0[0] == e0[1] ) { continue; }
 
1474
            if ( e1[0] == e1[1] ) { continue; }
 
1475
               
 
1476
            if(e0[0] != e1[0] && e0[0] != e1[1] && e0[1] != e1[0] && e0[1] != e1[1])
 
1477
            {
 
1478
               double time, s0, s2, rel_disp;
 
1479
               Vec3d normal;
 
1480
 
 
1481
               if ( e0[1] < e0[0] ) { swap( e0[0], e0[1] ); }
 
1482
               if ( e1[1] < e1[0] ) { swap( e1[0], e1[1] ); }
 
1483
               
 
1484
               if ( ( e0[1] < e0[0] ) || ( e1[1] < e1[0] ) )
 
1485
               {
 
1486
                  std::cout << e0 << std::endl;
 
1487
                  std::cout << e1 << std::endl;
 
1488
                  assert(0);
 
1489
               }
 
1490
               
 
1491
               if ( segment_segment_collision( m_positions[e0[0]], m_newpositions[e0[0]], e0[0],
 
1492
                                              m_positions[e0[1]], m_newpositions[e0[1]], e0[1],
 
1493
                                              m_positions[e1[0]], m_newpositions[e1[0]], e1[0],
 
1494
                                              m_positions[e1[1]], m_newpositions[e1[1]], e1[1],
 
1495
                                              s0, s2,
 
1496
                                              normal,
 
1497
                                              time, rel_disp ) )
 
1498
                  
 
1499
               {
 
1500
                                    
 
1501
                  ++m_num_collisions_this_step;
 
1502
                  
 
1503
                  double relvel = rel_disp / dt;
 
1504
                  
 
1505
                  if ( m_verbose ) 
 
1506
                  {
 
1507
                     std::cout << "(EE) time: " << time << ", relative velocity before: " << relvel;
 
1508
                     std::cout << ", normal: " << normal;
 
1509
                  }
 
1510
                  
 
1511
                  apply_edge_edge_impulse(e0, e1, s0, s2, normal, -relvel);
 
1512
                  
 
1513
                  double relvel_after = dot(normal, s0*m_velocities[e0[0]] + (1.0-s0)*m_velocities[e0[1]] - (s2*m_velocities[e1[0]] + (1.0-s2)*m_velocities[e1[1]]));
 
1514
                  
 
1515
                  if ( m_verbose ) std::cout << " and relative velocity after: " << relvel_after << std::endl;
 
1516
 
 
1517
                  m_newpositions[e0[0]] = m_positions[e0[0]] + dt*m_velocities[e0[0]];
 
1518
                  m_newpositions[e0[1]] = m_positions[e0[1]] + dt*m_velocities[e0[1]];
 
1519
                  m_newpositions[e1[0]] = m_positions[e1[0]] + dt*m_velocities[e1[0]];
 
1520
                  m_newpositions[e1[1]] = m_positions[e1[1]] + dt*m_velocities[e1[1]];
 
1521
                  
 
1522
                  update_continuous_broad_phase( e0[0] );
 
1523
                  update_continuous_broad_phase( e0[1] );
 
1524
                  update_continuous_broad_phase( e1[0] );
 
1525
                  update_continuous_broad_phase( e1[1] );
 
1526
                                    
 
1527
                  if ( pass == MAX_PASS - 1 )
 
1528
                  {
 
1529
                     if ( update_collision_candidates.size() < MAX_CANDIDATES )
 
1530
                     {
 
1531
                        add_point_update_candidates(e0[0], update_collision_candidates);
 
1532
                        add_point_update_candidates(e0[1], update_collision_candidates);
 
1533
                        add_point_update_candidates(e1[0], update_collision_candidates);
 
1534
                        add_point_update_candidates(e1[1], update_collision_candidates);
 
1535
                     }
 
1536
                     else
 
1537
                     {
 
1538
                        candidate_overflow = true;
 
1539
                     }
 
1540
                  }
 
1541
                  
 
1542
                  collision_found = true;
 
1543
                  
 
1544
                  m_verbose = false;
 
1545
                  
 
1546
               }               
 
1547
            }
 
1548
         }      
 
1549
      }
 
1550
         
 
1551
   }
 
1552
   
 
1553
   {
 
1554
      CollisionCandidateSet::iterator new_end = std::unique( update_collision_candidates.begin(), update_collision_candidates.end() );
 
1555
      update_collision_candidates.erase( new_end, update_collision_candidates.end() );
 
1556
   }
 
1557
   
 
1558
   unsigned int n = update_collision_candidates.size();
 
1559
   unsigned int c = 0;
 
1560
   
 
1561
   while( !update_collision_candidates.empty() && c++ < (5 * n) )
 
1562
   {
 
1563
 
 
1564
      CollisionCandidateSet::iterator iter = update_collision_candidates.begin();
 
1565
      Vec3ui candidate = *iter;
 
1566
      update_collision_candidates.erase(iter);
 
1567
            
 
1568
      if(candidate[2]==0)
 
1569
      {
 
1570
         unsigned int t = candidate[0];
 
1571
         const Vec3ui& tri = m_mesh.m_tris[t];
 
1572
         unsigned int v = candidate[1];
 
1573
         
 
1574
         if(tri[0] != v && tri[1] != v && tri[2] != v)
 
1575
         {
 
1576
            double time, s1, s2, s3, rel_disp;
 
1577
            Vec3d normal;
 
1578
            
 
1579
            Vec3ui sorted_tri = sort_triangle( tri );            
 
1580
            
 
1581
            if ( point_triangle_collision( m_positions[v], m_newpositions[v], v,
 
1582
                                          m_positions[sorted_tri[0]], m_newpositions[sorted_tri[0]], sorted_tri[0],
 
1583
                                          m_positions[sorted_tri[1]], m_newpositions[sorted_tri[1]], sorted_tri[1],
 
1584
                                          m_positions[sorted_tri[2]], m_newpositions[sorted_tri[2]], sorted_tri[2],
 
1585
                                          s1, s2, s3,
 
1586
                                          normal,
 
1587
                                          time, rel_disp ) )               
 
1588
               
 
1589
            {
 
1590
 
 
1591
               ++m_num_collisions_this_step;
 
1592
               
 
1593
               double relvel = rel_disp / dt;
 
1594
               
 
1595
               if ( m_verbose ) std::cout << "VT ( " << v << " " << tri << " ) relative velocity before: " << relvel; 
 
1596
               
 
1597
               apply_triangle_point_impulse( sorted_tri, v, s1, s2, s3, normal, -relvel);
 
1598
               
 
1599
               double relvel_after = dot(normal, m_velocities[v] - (s1*m_velocities[tri[0]] + s2*m_velocities[tri[1]] + s3*m_velocities[tri[2]]));
 
1600
               
 
1601
               if ( m_verbose ) std::cout << " and relative velocity after: " << relvel_after << std::endl;
 
1602
 
 
1603
               m_newpositions[v] = m_positions[v] + dt*m_velocities[v];
 
1604
               m_newpositions[tri[0]] = m_positions[tri[0]] + dt*m_velocities[tri[0]];
 
1605
               m_newpositions[tri[1]] = m_positions[tri[1]] + dt*m_velocities[tri[1]];
 
1606
               m_newpositions[tri[2]] = m_positions[tri[2]] + dt*m_velocities[tri[2]];
 
1607
               
 
1608
               update_continuous_broad_phase( v  );
 
1609
               update_continuous_broad_phase( tri[0] );
 
1610
               update_continuous_broad_phase( tri[1] );
 
1611
               update_continuous_broad_phase( tri[2] );
 
1612
               
 
1613
               if ( update_collision_candidates.size() < MAX_CANDIDATES )
 
1614
               {
 
1615
                  add_point_update_candidates(v, update_collision_candidates);
 
1616
                  add_point_update_candidates(tri[0], update_collision_candidates);
 
1617
                  add_point_update_candidates(tri[1], update_collision_candidates);
 
1618
                  add_point_update_candidates(tri[2], update_collision_candidates);
 
1619
               }
 
1620
               else
 
1621
               {
 
1622
                  candidate_overflow = true;
 
1623
               }
 
1624
            }
 
1625
         }
 
1626
      }
 
1627
      else
 
1628
      {
 
1629
         Vec2ui e0 = m_mesh.m_edges[candidate[0]];
 
1630
         Vec2ui e1 = m_mesh.m_edges[candidate[1]];
 
1631
         if(e0[0] != e1[0] && e0[0] != e1[1] && e0[1] != e1[0] && e0[1] != e1[1])
 
1632
         {
 
1633
            if ( e0[1] < e0[0] ) { swap( e0[0], e0[1] ); }
 
1634
            if ( e1[1] < e1[0] ) { swap( e1[0], e1[1] ); }
 
1635
            
 
1636
            double time, s0, s2, rel_disp;
 
1637
            Vec3d normal;
 
1638
            
 
1639
            if ( segment_segment_collision( m_positions[e0[0]], m_newpositions[e0[0]], e0[0],
 
1640
                                           m_positions[e0[1]], m_newpositions[e0[1]], e0[1],
 
1641
                                           m_positions[e1[0]], m_newpositions[e1[0]], e1[0],
 
1642
                                           m_positions[e1[1]], m_newpositions[e1[1]], e1[1],
 
1643
                                           s0, s2,
 
1644
                                           normal,
 
1645
                                           time, rel_disp ) )
 
1646
               
 
1647
            {
 
1648
 
 
1649
               ++m_num_collisions_this_step;
 
1650
               
 
1651
               double relvel = rel_disp / dt;
 
1652
               
 
1653
               if ( m_verbose ) std::cout << "EE relative velocity before: " << relvel;
 
1654
               
 
1655
               apply_edge_edge_impulse(e0, e1, s0, s2, normal, -relvel);
 
1656
               
 
1657
               double relvel_after = dot(normal, s0*m_velocities[e0[0]] + (1.0-s0)*m_velocities[e0[1]] - (s2*m_velocities[e1[0]] + (1.0-s2)*m_velocities[e1[1]]));
 
1658
               
 
1659
               if ( m_verbose ) std::cout << " and relative velocity after: " << relvel_after << std::endl;            
 
1660
                              
 
1661
               m_newpositions[e0[0]] = m_positions[e0[0]] + dt*m_velocities[e0[0]];
 
1662
               m_newpositions[e0[1]] = m_positions[e0[1]] + dt*m_velocities[e0[1]];
 
1663
               m_newpositions[e1[0]] = m_positions[e1[0]] + dt*m_velocities[e1[0]];
 
1664
               m_newpositions[e1[1]] = m_positions[e1[1]] + dt*m_velocities[e1[1]];
 
1665
                              
 
1666
               
 
1667
               update_continuous_broad_phase( e0[0] );
 
1668
               update_continuous_broad_phase( e0[1] );
 
1669
               update_continuous_broad_phase( e1[0] );
 
1670
               update_continuous_broad_phase( e1[1] );
 
1671
               
 
1672
               if ( update_collision_candidates.size() < MAX_CANDIDATES )
 
1673
               {
 
1674
                  add_point_update_candidates(e0[0], update_collision_candidates);
 
1675
                  add_point_update_candidates(e0[1], update_collision_candidates);
 
1676
                  add_point_update_candidates(e1[0], update_collision_candidates);
 
1677
                  add_point_update_candidates(e1[1], update_collision_candidates);
 
1678
               }
 
1679
               else
 
1680
               {
 
1681
                  candidate_overflow = true;
 
1682
               }
 
1683
               
 
1684
            }
 
1685
         }
 
1686
      }
 
1687
      
 
1688
   }
 
1689
 
 
1690
   
 
1691
   return ( !candidate_overflow ) && ( update_collision_candidates.empty() );
 
1692
   
 
1693
}
 
1694
 
 
1695
 
 
1696
 
 
1697
// ---------------------------------------------------------
 
1698
///
 
1699
/// Detect all continuous collisions
 
1700
///
 
1701
// ---------------------------------------------------------
 
1702
 
 
1703
bool DynamicSurface::detect_collisions( std::vector<Collision>& collisions )
 
1704
{
 
1705
   
 
1706
   static const unsigned int MAX_COLLISIONS = 5000;
 
1707
   
 
1708
   rebuild_continuous_broad_phase();
 
1709
  
 
1710
   //
 
1711
   // point-triangle
 
1712
   //
 
1713
   
 
1714
   for ( unsigned int i = 0; i < m_mesh.m_tris.size(); ++i )
 
1715
   {     
 
1716
      const Vec3ui& tri = m_mesh.m_tris[i];
 
1717
      
 
1718
      if ( tri[0] == tri[1] || tri[1] == tri[2] || tri[2] == tri[0] )    { continue; }
 
1719
 
 
1720
      Vec3d low, high;
 
1721
      triangle_continuous_bounds( i, low, high );
 
1722
      
 
1723
      std::vector<unsigned int> potential_collisions;
 
1724
      
 
1725
      m_broad_phase->get_potential_vertex_collisions( low, high, potential_collisions );
 
1726
      
 
1727
      for ( unsigned int j = 0; j < potential_collisions.size(); ++j )
 
1728
      {
 
1729
         unsigned int vertex_index = potential_collisions[j];
 
1730
         
 
1731
         assert ( m_mesh.m_vtxtri[vertex_index].size() != 0 );
 
1732
      
 
1733
         if( tri[0] != vertex_index && tri[1] != vertex_index && tri[2] != vertex_index )
 
1734
         {
 
1735
            double time, s1, s2, s3, rel_disp;
 
1736
            Vec3d normal;
 
1737
            
 
1738
            Vec3ui sorted_tri = sort_triangle( tri );            
 
1739
            
 
1740
            if ( point_triangle_collision( m_positions[vertex_index], m_newpositions[vertex_index], vertex_index,
 
1741
                                           m_positions[sorted_tri[0]], m_newpositions[sorted_tri[0]], sorted_tri[0],
 
1742
                                           m_positions[sorted_tri[1]], m_newpositions[sorted_tri[1]], sorted_tri[1],
 
1743
                                           m_positions[sorted_tri[2]], m_newpositions[sorted_tri[2]], sorted_tri[2],
 
1744
                                           s1, s2, s3,
 
1745
                                           normal,
 
1746
                                           time, rel_disp ) )               
 
1747
               
 
1748
            {
 
1749
               ++m_num_collisions_this_step;
 
1750
                              
 
1751
               Collision new_collision( false, Vec4ui( vertex_index, sorted_tri[0], sorted_tri[1], sorted_tri[2] ), normal, Vec4d( 1, -s1, -s2, -s3 ), rel_disp );
 
1752
                                             
 
1753
               collisions.push_back( new_collision );
 
1754
               
 
1755
               if ( collisions.size() > MAX_COLLISIONS ) 
 
1756
               {
 
1757
                  return false; 
 
1758
               }
 
1759
            }            
 
1760
         }
 
1761
      }
 
1762
   }
 
1763
   
 
1764
   //
 
1765
   // edge-edge
 
1766
   //
 
1767
 
 
1768
   for ( unsigned int edge_index_a = 0; edge_index_a < m_mesh.m_edges.size(); ++edge_index_a )
 
1769
   {
 
1770
      if ( m_mesh.m_edges[edge_index_a][0] == m_mesh.m_edges[edge_index_a][1] )    { continue; }
 
1771
      
 
1772
      Vec3d low, high;
 
1773
      edge_continuous_bounds(edge_index_a, low, high);
 
1774
      std::vector<unsigned int> potential_collisions;
 
1775
      m_broad_phase->get_potential_edge_collisions( low, high, potential_collisions );
 
1776
      
 
1777
      for ( unsigned int j = 0; j < potential_collisions.size(); ++j )
 
1778
      {
 
1779
   
 
1780
         unsigned int edge_index_b = potential_collisions[j];
 
1781
         
 
1782
         if ( edge_index_b <= edge_index_a )    { continue; }
 
1783
         
 
1784
         assert ( m_mesh.m_edges[edge_index_b][0] != m_mesh.m_edges[edge_index_b][1] );
 
1785
                  
 
1786
         Vec2ui e0 = m_mesh.m_edges[edge_index_a];
 
1787
         Vec2ui e1 = m_mesh.m_edges[edge_index_b];
 
1788
         
 
1789
         if( e0[0] != e1[0] && e0[0] != e1[1] && e0[1] != e1[0] && e0[1] != e1[1] )
 
1790
         {            
 
1791
            
 
1792
            double time, s0, s2, rel_disp;
 
1793
            Vec3d normal;
 
1794
            
 
1795
            if ( e0[1] < e0[0] ) { swap( e0[0], e0[1] ); }
 
1796
            if ( e1[1] < e1[0] ) { swap( e1[0], e1[1] ); }
 
1797
            
 
1798
            if ( segment_segment_collision( m_positions[e0[0]], m_newpositions[e0[0]], e0[0],
 
1799
                                            m_positions[e0[1]], m_newpositions[e0[1]], e0[1],
 
1800
                                            m_positions[e1[0]], m_newpositions[e1[0]], e1[0],
 
1801
                                            m_positions[e1[1]], m_newpositions[e1[1]], e1[1],
 
1802
                                            s0, s2,
 
1803
                                            normal,
 
1804
                                            time, rel_disp ) )
 
1805
               
 
1806
            {
 
1807
                  
 
1808
               ++m_num_collisions_this_step;
 
1809
               
 
1810
               Collision new_collision( true, Vec4ui( e0[0], e0[1], e1[0], e1[1] ), normal, Vec4d( -s0, -(1-s0), s2, (1-s2) ), rel_disp );
 
1811
                              
 
1812
               collisions.push_back( new_collision );
 
1813
               
 
1814
               if ( collisions.size() > MAX_COLLISIONS ) 
 
1815
               {
 
1816
                  std::cout << "maxed out collisions at edge " << edge_index_a << std::endl;
 
1817
                  return false; 
 
1818
               }                 
 
1819
            }
 
1820
            else if ( segment_segment_collision( m_positions[e1[0]], m_newpositions[e1[0]], e1[0],
 
1821
                                                 m_positions[e1[1]], m_newpositions[e1[1]], e1[1],
 
1822
                                                 m_positions[e0[0]], m_newpositions[e0[0]], e0[0],
 
1823
                                                 m_positions[e0[1]], m_newpositions[e0[1]], e0[1],
 
1824
                                                 s0, s2,
 
1825
                                                 normal,
 
1826
                                                 time, rel_disp ) )
 
1827
               
 
1828
            {
 
1829
               
 
1830
               ++m_num_collisions_this_step;
 
1831
               
 
1832
               Collision new_collision( true, Vec4ui( e0[0], e0[1], e1[0], e1[1] ), normal, Vec4d( -s0, -(1-s0), s2, (1-s2) ), rel_disp );
 
1833
               
 
1834
               collisions.push_back( new_collision );
 
1835
               
 
1836
               if ( collisions.size() > MAX_COLLISIONS ) 
 
1837
               {
 
1838
                  std::cout << "maxed out collisions at edge " << edge_index_a << std::endl;
 
1839
                  return false; 
 
1840
               }               
 
1841
               
 
1842
            }
 
1843
            
 
1844
         }
 
1845
      }
 
1846
   }
 
1847
   
 
1848
   return true;
 
1849
   
 
1850
}
 
1851
 
 
1852
 
 
1853
 
 
1854
 
 
1855
// ---------------------------------------------------------
 
1856
///
 
1857
/// Detect continuous collisions among elements in the given ImpactZones, and adjacent to the given ImpactZones.
 
1858
///
 
1859
// ---------------------------------------------------------
 
1860
 
 
1861
void DynamicSurface::detect_new_collisions( const std::vector<ImpactZone> impact_zones, std::vector<Collision>& collisions )
 
1862
{
 
1863
 
 
1864
   rebuild_continuous_broad_phase();
 
1865
   
 
1866
   std::vector<unsigned int> zone_vertices;
 
1867
   std::vector<unsigned int> zone_edges;
 
1868
   std::vector<unsigned int> zone_triangles;
 
1869
 
 
1870
   // Get all vertices in the impact zone
 
1871
   
 
1872
   for ( unsigned int i = 0; i < impact_zones.size(); ++i )
 
1873
   {
 
1874
      for ( unsigned int j = 0; j < impact_zones[i].collisions.size(); ++j )
 
1875
      {
 
1876
         add_unique( zone_vertices, impact_zones[i].collisions[j].vertex_indices[0] );
 
1877
         add_unique( zone_vertices, impact_zones[i].collisions[j].vertex_indices[1] );
 
1878
         add_unique( zone_vertices, impact_zones[i].collisions[j].vertex_indices[2] );
 
1879
         add_unique( zone_vertices, impact_zones[i].collisions[j].vertex_indices[3] );         
 
1880
         
 
1881
         update_continuous_broad_phase( impact_zones[i].collisions[j].vertex_indices[0] );
 
1882
         update_continuous_broad_phase( impact_zones[i].collisions[j].vertex_indices[1] );
 
1883
         update_continuous_broad_phase( impact_zones[i].collisions[j].vertex_indices[2] );
 
1884
         update_continuous_broad_phase( impact_zones[i].collisions[j].vertex_indices[3] );         
 
1885
         
 
1886
      }
 
1887
   }
 
1888
   
 
1889
   // Get all triangles in the impact zone
 
1890
   
 
1891
   for ( unsigned int i = 0; i < zone_vertices.size(); ++i )
 
1892
   {
 
1893
      for ( unsigned int j = 0; j < m_mesh.m_vtxtri[zone_vertices[i]].size(); ++j )
 
1894
      {
 
1895
         add_unique( zone_triangles, m_mesh.m_vtxtri[zone_vertices[i]][j] );
 
1896
      }
 
1897
   }
 
1898
 
 
1899
   // Get all edges in the impact zone
 
1900
   
 
1901
   for ( unsigned int i = 0; i < zone_vertices.size(); ++i )
 
1902
   {
 
1903
      for ( unsigned int j = 0; j < m_mesh.m_vtxedge[zone_vertices[i]].size(); ++j )
 
1904
      {
 
1905
         add_unique( zone_edges, m_mesh.m_vtxedge[zone_vertices[i]][j] );
 
1906
      }
 
1907
   }
 
1908
 
 
1909
   // Check zone vertices vs all triangles
 
1910
   
 
1911
   for ( unsigned int i = 0; i < zone_vertices.size(); ++i )
 
1912
   {
 
1913
      unsigned int vertex_index = zone_vertices[i];
 
1914
 
 
1915
      Vec3d query_low, query_high;
 
1916
      vertex_continuous_bounds( zone_vertices[i], query_low, query_high );
 
1917
      std::vector<unsigned int> overlapping_triangles;
 
1918
      m_broad_phase->get_potential_triangle_collisions( query_low, query_high, overlapping_triangles );
 
1919
      
 
1920
      for ( unsigned int j = 0; j < overlapping_triangles.size(); ++j )
 
1921
      {
 
1922
         const Vec3ui& tri = m_mesh.m_tris[overlapping_triangles[j]];
 
1923
         
 
1924
         assert( m_mesh.m_vtxtri[vertex_index].size() != 0 );
 
1925
         
 
1926
         if( tri[0] != vertex_index && tri[1] != vertex_index && tri[2] != vertex_index )
 
1927
         {
 
1928
            double time, s1, s2, s3, rel_disp;
 
1929
            Vec3d normal;
 
1930
            
 
1931
            Vec3ui sorted_tri = sort_triangle( tri );            
 
1932
            assert( sorted_tri[0] < sorted_tri[1] && sorted_tri[1] < sorted_tri[2] && sorted_tri[0] < sorted_tri[2] );
 
1933
            
 
1934
            if ( point_triangle_collision( m_positions[vertex_index], m_newpositions[vertex_index], vertex_index,
 
1935
                                                    m_positions[sorted_tri[0]], m_newpositions[sorted_tri[0]], sorted_tri[0],
 
1936
                                                    m_positions[sorted_tri[1]], m_newpositions[sorted_tri[1]], sorted_tri[1],
 
1937
                                                    m_positions[sorted_tri[2]], m_newpositions[sorted_tri[2]], sorted_tri[2],
 
1938
                                                    s1, s2, s3,
 
1939
                                                    normal,
 
1940
                                                    time, rel_disp ) )               
 
1941
               
 
1942
            {
 
1943
                             
 
1944
               assert( fabs(mag(normal) - 1.0) < 1e-10 );
 
1945
               
 
1946
               Collision new_collision( false, Vec4ui( vertex_index, sorted_tri[0], sorted_tri[1], sorted_tri[2] ), normal, Vec4d( 1, -s1, -s2, -s3 ), rel_disp );
 
1947
               
 
1948
               add_unique_collision( collisions, new_collision );
 
1949
               
 
1950
               bool exists = false;
 
1951
               for ( unsigned int z = 0; z < impact_zones.size(); ++z )
 
1952
               {
 
1953
                  for ( unsigned int c = 0; c < impact_zones[z].collisions.size(); ++c )
 
1954
                  {
 
1955
                     if ( new_collision.same_vertices( impact_zones[z].collisions[c] ) )
 
1956
                     {
 
1957
                        std::cout << "duplicate collision: " << new_collision.vertex_indices << std::endl;
 
1958
                        exists = true;
 
1959
                     }
 
1960
                  }
 
1961
               }
 
1962
               
 
1963
               if ( !exists )
 
1964
               {
 
1965
                  ++m_num_collisions_this_step;
 
1966
               }
 
1967
               
 
1968
            } 
 
1969
         }
 
1970
      }
 
1971
   }
 
1972
   
 
1973
   // Check zone triangles vs all vertices
 
1974
   
 
1975
   for ( unsigned int i = 0; i < zone_triangles.size(); ++i )
 
1976
   {
 
1977
      const Vec3ui& tri = m_mesh.m_tris[zone_triangles[i]];
 
1978
      
 
1979
      Vec3d query_low, query_high;
 
1980
      triangle_continuous_bounds( zone_triangles[i], query_low, query_high );
 
1981
      std::vector<unsigned int> overlapping_vertices;
 
1982
      m_broad_phase->get_potential_vertex_collisions( query_low, query_high, overlapping_vertices );
 
1983
      
 
1984
      for ( unsigned int j = 0; j < overlapping_vertices.size(); ++j )
 
1985
      {                      
 
1986
         unsigned int vertex_index = overlapping_vertices[j];
 
1987
         
 
1988
         assert( m_mesh.m_vtxtri[vertex_index].size() != 0 );
 
1989
         
 
1990
         if( tri[0] != vertex_index && tri[1] != vertex_index && tri[2] != vertex_index )
 
1991
         {
 
1992
            double time, s1, s2, s3, rel_disp;
 
1993
            Vec3d normal;
 
1994
            
 
1995
            Vec3ui sorted_tri = sort_triangle( tri ); 
 
1996
            assert( sorted_tri[0] < sorted_tri[1] && sorted_tri[1] < sorted_tri[2] && sorted_tri[0] < sorted_tri[2] );
 
1997
                        
 
1998
            if ( point_triangle_collision( m_positions[vertex_index], m_newpositions[vertex_index], vertex_index,
 
1999
                                                    m_positions[sorted_tri[0]], m_newpositions[sorted_tri[0]], sorted_tri[0],
 
2000
                                                    m_positions[sorted_tri[1]], m_newpositions[sorted_tri[1]], sorted_tri[1],
 
2001
                                                    m_positions[sorted_tri[2]], m_newpositions[sorted_tri[2]], sorted_tri[2],
 
2002
                                                    s1, s2, s3,
 
2003
                                                    normal,
 
2004
                                                    time, rel_disp ) )                
 
2005
            {
 
2006
               
 
2007
               assert( fabs(mag(normal) - 1.0) < 1e-10 );
 
2008
               
 
2009
               Collision new_collision( false, Vec4ui( vertex_index, sorted_tri[0], sorted_tri[1], sorted_tri[2] ), normal, Vec4d( 1, -s1, -s2, -s3 ), rel_disp );                              
 
2010
               
 
2011
               add_unique_collision( collisions, new_collision );
 
2012
               
 
2013
               bool exists = false;
 
2014
               for ( unsigned int z = 0; z < impact_zones.size(); ++z )
 
2015
               {
 
2016
                  for ( unsigned int c = 0; c < impact_zones[z].collisions.size(); ++c )
 
2017
                  {
 
2018
                     if ( new_collision.same_vertices( impact_zones[z].collisions[c] ) )
 
2019
                     {
 
2020
                        std::cout << "duplicate collision: " << new_collision.vertex_indices << std::endl;
 
2021
                        exists = true;
 
2022
                     }
 
2023
                  }
 
2024
               }
 
2025
               
 
2026
               if ( !exists )
 
2027
               {
 
2028
                  ++m_num_collisions_this_step;
 
2029
               }
 
2030
               
 
2031
               
 
2032
            } 
 
2033
         }
 
2034
      }
 
2035
   }
 
2036
   
 
2037
   // Check zone edges vs all edges
 
2038
   
 
2039
   for ( unsigned int i = 0; i < zone_edges.size(); ++i )
 
2040
   {
 
2041
      unsigned int edge_index_a = zone_edges[i];
 
2042
      
 
2043
      if ( m_mesh.m_edges[edge_index_a][0] == m_mesh.m_edges[edge_index_a][1] )    { continue; }
 
2044
      
 
2045
      Vec3d low, high;
 
2046
      edge_continuous_bounds(edge_index_a, low, high);
 
2047
      std::vector<unsigned int> potential_collisions;
 
2048
      m_broad_phase->get_potential_edge_collisions( low, high, potential_collisions );
 
2049
            
 
2050
      for ( unsigned int j = 0; j < potential_collisions.size(); ++j )
 
2051
      {   
 
2052
         unsigned int edge_index_b = potential_collisions[j];
 
2053
         
 
2054
         assert ( m_mesh.m_edges[edge_index_b][0] != m_mesh.m_edges[edge_index_b][1] );    
 
2055
         
 
2056
         Vec2ui e0 = m_mesh.m_edges[edge_index_a];
 
2057
         Vec2ui e1 = m_mesh.m_edges[edge_index_b];
 
2058
         
 
2059
         if( e0[0] != e1[0] && e0[0] != e1[1] && e0[1] != e1[0] && e0[1] != e1[1] )
 
2060
         {
 
2061
            if ( e0[1] < e0[0] ) { swap( e0[0], e0[1] ); }
 
2062
            if ( e1[1] < e1[0] ) { swap( e1[0], e1[1] ); }
 
2063
            
 
2064
            assert( e0[0] < e0[1] && e1[0] < e1[1] );
 
2065
            
 
2066
            double time, s0, s2, rel_disp;
 
2067
            Vec3d normal;
 
2068
            
 
2069
            if ( segment_segment_collision( m_positions[e0[0]], m_newpositions[e0[0]], e0[0],
 
2070
                                            m_positions[e0[1]], m_newpositions[e0[1]], e0[1],
 
2071
                                            m_positions[e1[0]], m_newpositions[e1[0]], e1[0],
 
2072
                                            m_positions[e1[1]], m_newpositions[e1[1]], e1[1],
 
2073
                                            s0, s2,
 
2074
                                            normal,
 
2075
                                            time, rel_disp ) )
 
2076
               
 
2077
            {
 
2078
                              
 
2079
               normalize(normal);
 
2080
               
 
2081
               Collision new_collision( true, Vec4ui( e0[0], e0[1], e1[0], e1[1] ), normal, Vec4d( -s0, -(1-s0), s2, (1-s2) ), rel_disp );
 
2082
               
 
2083
               add_unique_collision( collisions, new_collision );
 
2084
               
 
2085
               
 
2086
               bool exists = false;
 
2087
               for ( unsigned int z = 0; z < impact_zones.size(); ++z )
 
2088
               {
 
2089
                  for ( unsigned int c = 0; c < impact_zones[z].collisions.size(); ++c )
 
2090
                  {
 
2091
                     if ( new_collision.same_vertices( impact_zones[z].collisions[c] ) )
 
2092
                     {
 
2093
                        std::cout << "duplicate collision: " << new_collision.vertex_indices << std::endl;
 
2094
                        exists = true;
 
2095
                     }
 
2096
                  }
 
2097
               }
 
2098
               
 
2099
               if ( !exists )
 
2100
               {
 
2101
                  ++m_num_collisions_this_step;
 
2102
               }
 
2103
               
 
2104
 
 
2105
            }
 
2106
            else if ( segment_segment_collision( m_positions[e1[0]], m_newpositions[e1[0]], e1[0],
 
2107
                                                 m_positions[e1[1]], m_newpositions[e1[1]], e1[1],
 
2108
                                                 m_positions[e0[0]], m_newpositions[e0[0]], e0[0],
 
2109
                                                 m_positions[e0[1]], m_newpositions[e0[1]], e0[1],
 
2110
                                                 s0, s2,
 
2111
                                                 normal,
 
2112
                                                 time, rel_disp ) )
 
2113
            {
 
2114
               normalize(normal);
 
2115
               
 
2116
               Collision new_collision( true, Vec4ui( e1[0], e1[1], e0[0], e0[1] ), normal, Vec4d( -s0, -(1-s0), s2, (1-s2) ), rel_disp );
 
2117
               
 
2118
               add_unique_collision( collisions, new_collision );
 
2119
               
 
2120
               bool exists = false;
 
2121
               for ( unsigned int z = 0; z < impact_zones.size(); ++z )
 
2122
               {
 
2123
                  for ( unsigned int c = 0; c < impact_zones[z].collisions.size(); ++c )
 
2124
                  {
 
2125
                     if ( new_collision.same_vertices( impact_zones[z].collisions[c] ) )
 
2126
                     {
 
2127
                        std::cout << "duplicate collision: " << new_collision.vertex_indices << std::endl;
 
2128
                        exists = true;
 
2129
                     }
 
2130
                  }
 
2131
               }
 
2132
               
 
2133
               if ( !exists )
 
2134
               {
 
2135
                  ++m_num_collisions_this_step;
 
2136
               } 
 
2137
            }
 
2138
         }
 
2139
      }
 
2140
   }
 
2141
}
 
2142
 
 
2143
 
 
2144
 
 
2145
 
 
2146
// ---------------------------------------------------------
 
2147
///
 
2148
/// Combine impact zones which have overlapping vertex stencils
 
2149
///
 
2150
// ---------------------------------------------------------
 
2151
 
 
2152
void DynamicSurface::merge_impact_zones( std::vector<ImpactZone>& new_impact_zones, std::vector<ImpactZone>& master_impact_zones )
 
2153
{
 
2154
   
 
2155
   bool merge_ocurred = true;
 
2156
      
 
2157
   for ( unsigned int i = 0; i < master_impact_zones.size(); ++i )
 
2158
   {
 
2159
      master_impact_zones[i].all_solved = true;
 
2160
   }
 
2161
 
 
2162
   for ( unsigned int i = 0; i < new_impact_zones.size(); ++i )
 
2163
   {
 
2164
      new_impact_zones[i].all_solved = false;
 
2165
   }
 
2166
 
 
2167
   
 
2168
   while ( merge_ocurred )
 
2169
   {
 
2170
            
 
2171
      merge_ocurred = false;
 
2172
           
 
2173
      for ( unsigned int i = 0; i < new_impact_zones.size(); ++i )
 
2174
      {
 
2175
         bool i_is_disjoint = true;
 
2176
         
 
2177
         for ( unsigned int j = 0; j < master_impact_zones.size(); ++j )
 
2178
         {
 
2179
            // check if impact zone i and j share any vertices
 
2180
            
 
2181
            if ( master_impact_zones[j].share_vertices( new_impact_zones[i] ) )
 
2182
            {
 
2183
               
 
2184
               bool found_new_collision = false;
 
2185
               
 
2186
               // steal all of j's collisions
 
2187
               for ( unsigned int c = 0; c < new_impact_zones[i].collisions.size(); ++c )
 
2188
               {
 
2189
 
 
2190
                  bool same_collision_exists = false;
 
2191
                  
 
2192
                  for ( unsigned int m = 0; m < master_impact_zones[j].collisions.size(); ++m )
 
2193
                  {                 
 
2194
                     if ( master_impact_zones[j].collisions[m].same_vertices( new_impact_zones[i].collisions[c] ) )
 
2195
                     {
 
2196
 
 
2197
                        same_collision_exists = true;
 
2198
                        break;
 
2199
                     }
 
2200
                     
 
2201
                  }
 
2202
                  
 
2203
                  if ( !same_collision_exists )
 
2204
                  {
 
2205
                     master_impact_zones[j].collisions.push_back( new_impact_zones[i].collisions[c] );
 
2206
                     found_new_collision = true;
 
2207
                  }
 
2208
               }
 
2209
               
 
2210
               // did we find any collisions in zone i that zone j didn't already have?
 
2211
               if ( found_new_collision )
 
2212
               {
 
2213
                  master_impact_zones[j].all_solved &= new_impact_zones[i].all_solved;
 
2214
               }
 
2215
               
 
2216
               merge_ocurred = true;
 
2217
               i_is_disjoint = false;
 
2218
               break;
 
2219
            }
 
2220
            
 
2221
         }     // end for(j)
 
2222
         
 
2223
         if ( i_is_disjoint )
 
2224
         {
 
2225
            // copy the impact zone
 
2226
            
 
2227
            ImpactZone new_zone;
 
2228
            for ( unsigned int c = 0; c < new_impact_zones[i].collisions.size(); ++c )
 
2229
            {
 
2230
               new_zone.collisions.push_back( new_impact_zones[i].collisions[c] );
 
2231
            }
 
2232
            
 
2233
            new_zone.all_solved = new_impact_zones[i].all_solved;
 
2234
            
 
2235
            master_impact_zones.push_back( new_zone );
 
2236
         }
 
2237
      }     // end for(i)
 
2238
      
 
2239
      new_impact_zones = master_impact_zones;
 
2240
      master_impact_zones.clear();
 
2241
      
 
2242
   }  // while
 
2243
 
 
2244
   master_impact_zones = new_impact_zones;
 
2245
     
 
2246
}
 
2247
 
 
2248
 
 
2249
// ---------------------------------------------------------
 
2250
///
 
2251
/// Iteratively project out relative normal velocities for a set of collisions in an impact zone until all collisions are solved.
 
2252
///
 
2253
// ---------------------------------------------------------
 
2254
 
 
2255
bool DynamicSurface::iterated_inelastic_projection( ImpactZone& iz, double dt )
 
2256
{
 
2257
   assert( m_masses.size() == m_positions.size() );
 
2258
   
 
2259
   static const unsigned int MAX_PROJECTION_ITERATIONS = 20;
 
2260
   
 
2261
   for ( unsigned int i = 0; i < MAX_PROJECTION_ITERATIONS; ++i )
 
2262
   {
 
2263
      m_verbose = true;
 
2264
      bool success = inelastic_projection( iz );
 
2265
      m_verbose = false;
 
2266
            
 
2267
      if ( !success )
 
2268
      {
 
2269
         std::cout << "failure in inelastic projection" << std::endl;
 
2270
         return false;
 
2271
      }
 
2272
      
 
2273
      bool collision_still_exists = false;
 
2274
      
 
2275
      for ( unsigned int c = 0; c < iz.collisions.size(); ++c )
 
2276
      {
 
2277
         // run collision detection on this pair again
 
2278
         
 
2279
         Collision& collision = iz.collisions[c];
 
2280
         const Vec4ui& vs = collision.vertex_indices;
 
2281
            
 
2282
         m_newpositions[vs[0]] = m_positions[vs[0]] + dt * m_velocities[vs[0]];
 
2283
         m_newpositions[vs[1]] = m_positions[vs[1]] + dt * m_velocities[vs[1]];
 
2284
         m_newpositions[vs[2]] = m_positions[vs[2]] + dt * m_velocities[vs[2]];
 
2285
         m_newpositions[vs[3]] = m_positions[vs[3]] + dt * m_velocities[vs[3]];
 
2286
            
 
2287
         if ( m_verbose ) { std::cout << "checking collision " << vs << std::endl; }
 
2288
         
 
2289
         if ( collision.is_edge_edge )
 
2290
         {
 
2291
            
 
2292
            double time, s0, s2, rel_disp;
 
2293
            Vec3d normal;
 
2294
            
 
2295
            assert( vs[0] < vs[1] && vs[2] < vs[3] );       // should have been sorted by original collision detection
 
2296
            
 
2297
            
 
2298
            if ( segment_segment_collision( m_positions[vs[0]], m_newpositions[vs[0]], vs[0],
 
2299
                                                     m_positions[vs[1]], m_newpositions[vs[1]], vs[1],
 
2300
                                                     m_positions[vs[2]], m_newpositions[vs[2]], vs[2],
 
2301
                                                     m_positions[vs[3]], m_newpositions[vs[3]], vs[3],
 
2302
                                                     s0, s2,
 
2303
                                                     normal,
 
2304
                                                     time, rel_disp, false ) )               
 
2305
            {
 
2306
               
 
2307
               std::cout << "collision remains.  delta alphas: " << Vec4d( -s0, -(1-s0), s2, (1-s2) ) - collision.alphas << std::endl;
 
2308
               std::cout << "alphas: " << Vec4d( -s0, -(1-s0), s2, (1-s2) ) << std::endl;
 
2309
               std::cout << "normal: " << normal << std::endl;
 
2310
               std::cout << "rel_disp: " << rel_disp << std::endl;
 
2311
               std::cout << "time: " << time << std::endl;               
 
2312
               collision.normal = normal;
 
2313
               collision.alphas = Vec4d( -s0, -(1-s0), s2, (1-s2) );
 
2314
               collision.relative_displacement = rel_disp;
 
2315
               collision_still_exists = true;
 
2316
            }
 
2317
            
 
2318
         }
 
2319
         else
 
2320
         {
 
2321
               
 
2322
            double time, s1, s2, s3, rel_disp;
 
2323
            Vec3d normal;
 
2324
            
 
2325
            assert( vs[1] < vs[2] && vs[2] < vs[3] && vs[1] < vs[3] );    // should have been sorted by original collision detection
 
2326
            
 
2327
            if ( point_triangle_collision( m_positions[vs[0]], m_newpositions[vs[0]], vs[0],
 
2328
                                                    m_positions[vs[1]], m_newpositions[vs[1]], vs[1],
 
2329
                                                    m_positions[vs[2]], m_newpositions[vs[2]], vs[2],
 
2330
                                                    m_positions[vs[3]], m_newpositions[vs[3]], vs[3],
 
2331
                                                    s1, s2, s3,
 
2332
                                                    normal,
 
2333
                                                    time, rel_disp, false ) )                                 
 
2334
            {
 
2335
               std::cout << "collision remains.  delta alphas: " << Vec4d( 1, -s1, -s2, -s3 ) - collision.alphas << std::endl;
 
2336
               std::cout << "alphas: " << Vec4d( 1, -s1, -s2, -s3 ) << std::endl;            
 
2337
               std::cout << "normal: " << normal << std::endl;
 
2338
               std::cout << "rel_disp: " << rel_disp << std::endl;
 
2339
               std::cout << "time: " << time << std::endl;               
 
2340
               collision.normal = normal;
 
2341
               collision.alphas = Vec4d( 1, -s1, -s2, -s3 );
 
2342
               collision.relative_displacement = rel_disp;
 
2343
               collision_still_exists = true;
 
2344
            }
 
2345
            
 
2346
         }
 
2347
         
 
2348
      } // for collisions
 
2349
      
 
2350
      if ( false == collision_still_exists )  
 
2351
      {
 
2352
         return true; 
 
2353
      }
 
2354
      
 
2355
   } // for iterations
 
2356
 
 
2357
   std::cout << "reached max iterations for this zone" << std::endl;
 
2358
 
 
2359
   return false;
 
2360
   
 
2361
}
 
2362
 
 
2363
 
 
2364
// ---------------------------------------------------------
 
2365
///
 
2366
/// Project out relative normal velocities for a set of collisions in an impact zone.
 
2367
///
 
2368
// ---------------------------------------------------------
 
2369
 
 
2370
bool DynamicSurface::inelastic_projection( const ImpactZone& iz )
 
2371
{
 
2372
   
 
2373
   if ( m_verbose )
 
2374
   {
 
2375
      std::cout << " ----- using sparse solver " << std::endl;
 
2376
   }
 
2377
   
 
2378
   static double IMPULSE_MULTIPLIER = 0.8;
 
2379
   
 
2380
   const unsigned int k = iz.collisions.size();    // notation from [Harmon et al 2008]: k == number of collisions
 
2381
   
 
2382
   std::vector<unsigned int> zone_vertices;
 
2383
   iz.get_all_vertices( zone_vertices );
 
2384
   
 
2385
   const unsigned int n = zone_vertices.size();       // n == number of distinct colliding vertices
 
2386
   
 
2387
   if ( m_verbose )
 
2388
   {
 
2389
      std::cout << "GCT: " << 3*n << "x" << k << std::endl;
 
2390
   }
 
2391
   
 
2392
   SparseMatrixDynamicCSR GCT( 3*n, k );
 
2393
   GCT.set_zero();
 
2394
   
 
2395
   // construct matrix grad C transpose
 
2396
   for ( unsigned int i = 0; i < k; ++i )
 
2397
   {
 
2398
      // set col i
 
2399
      const Collision& coll = iz.collisions[i];
 
2400
      
 
2401
      for ( unsigned int v = 0; v < 4; ++v )
 
2402
      {
 
2403
         // block row j ( == block column j of grad C )
 
2404
         unsigned int j = coll.vertex_indices[v];
 
2405
         
 
2406
         std::vector<unsigned int>::iterator zone_vertex_iter = find( zone_vertices.begin(), zone_vertices.end(), j );
 
2407
         
 
2408
         assert( zone_vertex_iter != zone_vertices.end() );
 
2409
         
 
2410
         unsigned int mat_j = (unsigned int) ( zone_vertex_iter - zone_vertices.begin() );
 
2411
         
 
2412
         GCT(mat_j*3, i) = coll.alphas[v] * coll.normal[0];
 
2413
         GCT(mat_j*3+1, i) = coll.alphas[v] * coll.normal[1];
 
2414
         GCT(mat_j*3+2, i) = coll.alphas[v] * coll.normal[2];
 
2415
         
 
2416
      }
 
2417
   }
 
2418
 
 
2419
   Array1d inv_masses;
 
2420
   inv_masses.reserve(3*n);
 
2421
   Array1d column_velocities;
 
2422
   column_velocities.reserve(3*n);
 
2423
   
 
2424
   for ( unsigned int i = 0; i < n; ++i )
 
2425
   {
 
2426
      if ( m_masses[zone_vertices[i]] < 100.0 )
 
2427
      {
 
2428
         inv_masses.push_back( 1.0 / m_masses[zone_vertices[i]] );
 
2429
         inv_masses.push_back( 1.0 / m_masses[zone_vertices[i]] );
 
2430
         inv_masses.push_back( 1.0 / m_masses[zone_vertices[i]] );
 
2431
      }
 
2432
      else
 
2433
      {
 
2434
         // infinite mass (scripted objects)
 
2435
         
 
2436
         inv_masses.push_back( 0.0 );
 
2437
         inv_masses.push_back( 0.0 );
 
2438
         inv_masses.push_back( 0.0 );         
 
2439
      }
 
2440
 
 
2441
      column_velocities.push_back( m_velocities[zone_vertices[i]][0] );
 
2442
      column_velocities.push_back( m_velocities[zone_vertices[i]][1] );
 
2443
      column_velocities.push_back( m_velocities[zone_vertices[i]][2] );
 
2444
   }
 
2445
 
 
2446
   //
 
2447
   // minimize | M^(-1/2) * GC^T x - M^(1/2) * v |^2
 
2448
   //
 
2449
   
 
2450
   // solution vector
 
2451
   Array1d x(k);
 
2452
         
 
2453
   static const bool use_cgnr = false;
 
2454
   KrylovSolverStatus solver_result;
 
2455
   
 
2456
   if ( use_cgnr )
 
2457
   {
 
2458
      std::cout << "CGNR currently disabled: matrices are not scaled by masses." << std::endl;
 
2459
      assert( false );
 
2460
      
 
2461
      CGNR_Solver cg_solver;
 
2462
      SparseMatrixStaticCSR solver_matrix( GCT );
 
2463
      cg_solver.max_iterations = INT_MAX;
 
2464
      solver_result = cg_solver.solve( solver_matrix, column_velocities.data, x.data );      
 
2465
   }
 
2466
   else
 
2467
   {
 
2468
      // normal equations: GC * M^(-1) GCT * x = GC * v
 
2469
      //                   A * x = b
 
2470
 
 
2471
      SparseMatrixDynamicCSR A( k, k );
 
2472
      A.set_zero();
 
2473
      AtDB( GCT, inv_masses.data, GCT, A ); 
 
2474
      
 
2475
      Array1d b(k);
 
2476
      GCT.apply_transpose( column_velocities.data, b.data );   
 
2477
 
 
2478
      if ( m_verbose )  { std::cout << "system built" << std::endl; }
 
2479
 
 
2480
      MINRES_CR_Solver solver;   
 
2481
      SparseMatrixStaticCSR solver_matrix( A );    // convert dynamic to static
 
2482
      solver.max_iterations = 1000;
 
2483
      solver_result = solver.solve( solver_matrix, b.data, x.data ); 
 
2484
   }
 
2485
 
 
2486
   if ( solver_result != KRYLOV_CONVERGED )
 
2487
   {
 
2488
      std::cout << "CR solver failed: ";
 
2489
      
 
2490
      if ( solver_result == KRYLOV_BREAKDOWN )
 
2491
      {
 
2492
         std::cout << "KRYLOV_BREAKDOWN" << std::endl;
 
2493
      }
 
2494
      else
 
2495
      {
 
2496
         std::cout << "KRYLOV_EXCEEDED_MAX_ITERATIONS" << std::endl;
 
2497
      }
 
2498
      
 
2499
      return false;          
 
2500
   } 
 
2501
   
 
2502
   // apply impulses 
 
2503
   Array1d applied_impulses(3*n);
 
2504
   GCT.apply( x.data, applied_impulses.data );
 
2505
     
 
2506
   for ( unsigned int i = 0; i < applied_impulses.size(); ++i )
 
2507
   {
 
2508
      column_velocities[i] -= IMPULSE_MULTIPLIER * inv_masses[i] * applied_impulses[i];      
 
2509
   }
 
2510
   
 
2511
   for ( unsigned int i = 0; i < n; ++i )
 
2512
   {
 
2513
      Vec3d new_velocity( column_velocities[3*i], column_velocities[3*i + 1], column_velocities[3*i + 2] );
 
2514
      
 
2515
      m_velocities[zone_vertices[i]][0] = column_velocities[3*i];
 
2516
      m_velocities[zone_vertices[i]][1] = column_velocities[3*i + 1];
 
2517
      m_velocities[zone_vertices[i]][2] = column_velocities[3*i + 2];      
 
2518
   }
 
2519
    
 
2520
   
 
2521
   return true;
 
2522
   
 
2523
}
 
2524
 
 
2525
 
 
2526
// ---------------------------------------------------------
 
2527
///
 
2528
/// Handle all collisions simultaneously by iteratively solving individual impact zones until no new collisions are detected.
 
2529
///
 
2530
// ---------------------------------------------------------
 
2531
 
 
2532
bool DynamicSurface::handle_collisions_simultaneous(double dt)
 
2533
{
 
2534
 
 
2535
   // copy
 
2536
   std::vector<Vec3d> old_velocities = m_velocities;
 
2537
 
 
2538
   std::vector<ImpactZone> impact_zones;
 
2539
 
 
2540
   bool finished_detecting_collisions = false;
 
2541
   
 
2542
   std::vector<Collision> total_collisions;
 
2543
   finished_detecting_collisions = detect_collisions(total_collisions);
 
2544
      
 
2545
   while ( false == total_collisions.empty() )
 
2546
   {      
 
2547
      // insert each new collision constraint into its own impact zone
 
2548
      std::vector<ImpactZone> new_impact_zones;
 
2549
      for ( unsigned int i = 0; i < total_collisions.size(); ++i )
 
2550
      {
 
2551
         ImpactZone new_zone;
 
2552
         new_zone.collisions.push_back( total_collisions[i] );
 
2553
         new_impact_zones.push_back( new_zone );
 
2554
      }
 
2555
      
 
2556
      assert( new_impact_zones.size() == total_collisions.size() );
 
2557
 
 
2558
      // merge all impact zones that share vertices
 
2559
      merge_impact_zones( new_impact_zones, impact_zones );
 
2560
 
 
2561
      for ( int i = 0; i < (int) impact_zones.size(); ++i )
 
2562
      {
 
2563
         if ( impact_zones[i].all_solved ) 
 
2564
         {
 
2565
            impact_zones.erase( impact_zones.begin() + i );
 
2566
            --i;
 
2567
         }
 
2568
      }
 
2569
 
 
2570
      for ( int i = 0; i < (int) impact_zones.size(); ++i )
 
2571
      {
 
2572
         assert( false == impact_zones[i].all_solved );
 
2573
      }            
 
2574
            
 
2575
      bool solver_ok = true;
 
2576
      
 
2577
      // for each impact zone
 
2578
      for ( unsigned int i = 0; i < impact_zones.size(); ++i )
 
2579
      {
 
2580
         
 
2581
         std::vector<unsigned int> zone_vertices;
 
2582
         
 
2583
         // reset impact zone to pre-response m_velocities
 
2584
         for ( unsigned int j = 0; j < impact_zones[i].collisions.size(); ++j )
 
2585
         {
 
2586
            Vec4ui& vs = impact_zones[i].collisions[j].vertex_indices;
 
2587
            
 
2588
            m_velocities[vs[0]] = old_velocities[vs[0]];
 
2589
            m_velocities[vs[1]] = old_velocities[vs[1]];
 
2590
            m_velocities[vs[2]] = old_velocities[vs[2]];
 
2591
            m_velocities[vs[3]] = old_velocities[vs[3]]; 
 
2592
            
 
2593
            zone_vertices.push_back( vs[0] );
 
2594
            zone_vertices.push_back( vs[1] );
 
2595
            zone_vertices.push_back( vs[2] );
 
2596
            zone_vertices.push_back( vs[3] );            
 
2597
         }
 
2598
         
 
2599
         // apply inelastic projection
 
2600
         
 
2601
         solver_ok &= iterated_inelastic_projection( impact_zones[i], dt );
 
2602
                  
 
2603
         // reset predicted m_positions
 
2604
         for ( unsigned int j = 0; j < impact_zones[i].collisions.size(); ++j )
 
2605
         {
 
2606
            const Vec4ui& vs = impact_zones[i].collisions[j].vertex_indices;            
 
2607
 
 
2608
            m_newpositions[vs[0]] = m_positions[vs[0]] + dt * m_velocities[vs[0]];
 
2609
            m_newpositions[vs[1]] = m_positions[vs[1]] + dt * m_velocities[vs[1]];
 
2610
            m_newpositions[vs[2]] = m_positions[vs[2]] + dt * m_velocities[vs[2]];
 
2611
            m_newpositions[vs[3]] = m_positions[vs[3]] + dt * m_velocities[vs[3]];
 
2612
         } 
 
2613
      
 
2614
      }  // for IZs
 
2615
      
 
2616
      if ( false == solver_ok )
 
2617
      {
 
2618
         std::cout << "solver problem" << std::endl;
 
2619
         return false;
 
2620
      }
 
2621
      
 
2622
      total_collisions.clear();
 
2623
      
 
2624
      if ( !finished_detecting_collisions )
 
2625
      {
 
2626
         std::cout << "attempting to finish global collision detection" << std::endl;
 
2627
         finished_detecting_collisions = detect_collisions( total_collisions );
 
2628
         impact_zones.clear();
 
2629
      }
 
2630
      else
 
2631
      {
 
2632
         detect_new_collisions( impact_zones, total_collisions );
 
2633
      }
 
2634
      
 
2635
   }
 
2636
   
 
2637
   return true;
 
2638
}
 
2639
 
 
2640
 
 
2641
// ---------------------------------------------------------
 
2642
///
 
2643
/// 
 
2644
///
 
2645
// ---------------------------------------------------------
 
2646
 
 
2647
bool DynamicSurface::collision_solved( const Collision& collision )
 
2648
{
 
2649
   if ( collision.is_edge_edge )
 
2650
   {
 
2651
      Vec2ui e0( collision.vertex_indices[0], collision.vertex_indices[1] );
 
2652
      Vec2ui e1( collision.vertex_indices[2], collision.vertex_indices[3] );
 
2653
      
 
2654
      double time, s0, s2, rel_disp;
 
2655
      Vec3d normal;
 
2656
      
 
2657
      if ( e0[1] < e0[0] ) { swap( e0[0], e0[1] ); }
 
2658
      if ( e1[1] < e1[0] ) { swap( e1[0], e1[1] ); }
 
2659
      
 
2660
      if ( segment_segment_collision( m_positions[e0[0]], m_newpositions[e0[0]], e0[0],
 
2661
                                     m_positions[e0[1]], m_newpositions[e0[1]], e0[1],
 
2662
                                     m_positions[e1[0]], m_newpositions[e1[0]], e1[0],
 
2663
                                     m_positions[e1[1]], m_newpositions[e1[1]], e1[1],
 
2664
                                     s0, s2,
 
2665
                                     normal,
 
2666
                                     time, rel_disp ) )
 
2667
         
 
2668
      {
 
2669
         return false;
 
2670
      }
 
2671
      else if ( segment_segment_collision( m_positions[e1[0]], m_newpositions[e1[0]], e1[0],
 
2672
                                          m_positions[e1[1]], m_newpositions[e1[1]], e1[1],
 
2673
                                          m_positions[e0[0]], m_newpositions[e0[0]], e0[0],
 
2674
                                          m_positions[e0[1]], m_newpositions[e0[1]], e0[1],
 
2675
                                          s0, s2,
 
2676
                                          normal,
 
2677
                                          time, rel_disp ) )
 
2678
         
 
2679
      {
 
2680
         return false;
 
2681
      }
 
2682
      
 
2683
   }
 
2684
   else
 
2685
   {
 
2686
      unsigned int vertex_index = collision.vertex_indices[0];
 
2687
      Vec3ui tri( collision.vertex_indices[1], collision.vertex_indices[2], collision.vertex_indices[3] );
 
2688
      
 
2689
      Vec3ui sorted_tri = sort_triangle( tri );            
 
2690
      
 
2691
      double time, s1, s2, s3, rel_disp;
 
2692
      Vec3d normal;
 
2693
 
 
2694
      if ( point_triangle_collision( m_positions[vertex_index], m_newpositions[vertex_index], vertex_index,
 
2695
                                     m_positions[sorted_tri[0]], m_newpositions[sorted_tri[0]], sorted_tri[0],
 
2696
                                     m_positions[sorted_tri[1]], m_newpositions[sorted_tri[1]], sorted_tri[1],
 
2697
                                     m_positions[sorted_tri[2]], m_newpositions[sorted_tri[2]], sorted_tri[2],
 
2698
                                     s1, s2, s3,
 
2699
                                     normal,
 
2700
                                     time, rel_disp ) )               
 
2701
         
 
2702
      {
 
2703
         return false; 
 
2704
      }                  
 
2705
   }
 
2706
   
 
2707
   return true;
 
2708
   
 
2709
}
 
2710
 
 
2711
 
 
2712
// ---------------------------------------------------------
 
2713
///
 
2714
/// 
 
2715
///
 
2716
// ---------------------------------------------------------
 
2717
 
 
2718
 
 
2719
bool DynamicSurface::new_rigid_impact_zones(double dt)
 
2720
{
 
2721
   
 
2722
   // copy
 
2723
   std::vector<Vec3d> old_velocities = m_velocities;
 
2724
   
 
2725
   std::vector<ImpactZone> impact_zones;
 
2726
   
 
2727
   bool finished_detecting_collisions = false;
 
2728
   
 
2729
   std::vector<Collision> total_collisions;
 
2730
   finished_detecting_collisions = detect_collisions(total_collisions);
 
2731
      
 
2732
   while ( false == total_collisions.empty() )
 
2733
   {      
 
2734
      // insert each new collision constraint into its own impact zone
 
2735
      std::vector<ImpactZone> new_impact_zones;
 
2736
      for ( unsigned int i = 0; i < total_collisions.size(); ++i )
 
2737
      {
 
2738
         ImpactZone new_zone;
 
2739
         new_zone.collisions.push_back( total_collisions[i] );
 
2740
         new_impact_zones.push_back( new_zone );
 
2741
      }
 
2742
      
 
2743
      assert( new_impact_zones.size() == total_collisions.size() );
 
2744
      
 
2745
      // merge all impact zones that share vertices
 
2746
      merge_impact_zones( new_impact_zones, impact_zones );
 
2747
      
 
2748
      for ( int i = 0; i < (int) impact_zones.size(); ++i )
 
2749
      {
 
2750
         if ( impact_zones[i].all_solved ) 
 
2751
         {
 
2752
            impact_zones[i].all_solved = false;
 
2753
            impact_zones.erase( impact_zones.begin() + i );
 
2754
            --i;
 
2755
         }
 
2756
      }
 
2757
      
 
2758
      for ( int i = 0; i < (int) impact_zones.size(); ++i )
 
2759
      {
 
2760
         assert( false == impact_zones[i].all_solved );
 
2761
      }            
 
2762
      
 
2763
      // for each impact zone
 
2764
      for ( unsigned int i = 0; i < impact_zones.size(); ++i )
 
2765
      {
 
2766
         
 
2767
         std::vector<unsigned int> zone_vertices;
 
2768
         impact_zones[i].get_all_vertices( zone_vertices );
 
2769
         calculate_rigid_motion(dt, zone_vertices);
 
2770
         
 
2771
         bool all_solved = true;
 
2772
         for ( unsigned int c = 0; c < impact_zones[i].collisions.size(); ++c )
 
2773
         {
 
2774
            all_solved &= collision_solved( impact_zones[i].collisions[c] );
 
2775
         }
 
2776
         
 
2777
         if ( !all_solved )
 
2778
         {
 
2779
            std::cout << "RIZ failed.  Getting desperate!" << std::endl;
 
2780
            
 
2781
            Vec3d average_velocity(0,0,0);
 
2782
            for ( unsigned int v = 0; v < zone_vertices.size(); ++v )
 
2783
            {
 
2784
               average_velocity += m_velocities[ zone_vertices[v] ];
 
2785
            }
 
2786
            average_velocity /= (double) zone_vertices.size();
 
2787
            
 
2788
            for ( unsigned int v = 0; v < zone_vertices.size(); ++v )
 
2789
            {
 
2790
               m_velocities[ zone_vertices[v] ] = average_velocity;
 
2791
               m_newpositions[ zone_vertices[v] ] = m_positions[ zone_vertices[v] ] + dt * m_velocities[ zone_vertices[v] ];
 
2792
            }
 
2793
         }
 
2794
         
 
2795
      }  
 
2796
      
 
2797
      total_collisions.clear();
 
2798
      
 
2799
      if ( !finished_detecting_collisions )
 
2800
      {
 
2801
         finished_detecting_collisions = detect_collisions( total_collisions );
 
2802
         impact_zones.clear();
 
2803
      }
 
2804
      else
 
2805
      {
 
2806
         detect_new_collisions( impact_zones, total_collisions );
 
2807
      }
 
2808
      
 
2809
   }
 
2810
   
 
2811
   return true;
 
2812
}
 
2813
 
 
2814
 
 
2815
// ---------------------------------------------------------
 
2816
///
 
2817
/// 
 
2818
///
 
2819
// ---------------------------------------------------------
 
2820
 
 
2821
void DynamicSurface::calculate_rigid_motion(double dt, std::vector<unsigned int>& vs)
 
2822
{
 
2823
   Vec3d xcm(0,0,0);
 
2824
   Vec3d vcm(0,0,0);
 
2825
   double mass = 0;
 
2826
   
 
2827
   for(unsigned int i = 0; i < vs.size(); i++)
 
2828
   {
 
2829
      unsigned int idx = vs[i];
 
2830
      double m = m_masses[idx];
 
2831
      
 
2832
      mass += m;
 
2833
      
 
2834
      m_velocities[idx] = ( m_newpositions[idx] - m_positions[idx] ) / dt;
 
2835
      
 
2836
      xcm += m * m_positions[idx];
 
2837
      vcm += m * m_velocities[idx];
 
2838
   }
 
2839
   
 
2840
   xcm /= mass;
 
2841
   vcm /= mass;
 
2842
   
 
2843
   Vec3d L(0,0,0);
 
2844
   
 
2845
   for(unsigned int i = 0; i < vs.size(); i++)
 
2846
   {
 
2847
      unsigned int idx = vs[i];
 
2848
      double m = m_masses[idx];
 
2849
      
 
2850
      Vec3d xdiff = m_positions[idx] - xcm;
 
2851
      Vec3d vdiff = m_velocities[idx] - vcm;
 
2852
      
 
2853
      L += m * cross(xdiff, vdiff);
 
2854
   }
 
2855
   
 
2856
   Mat33d I(0,0,0,0,0,0,0,0,0);
 
2857
   
 
2858
   for(unsigned int i = 0; i < vs.size(); i++)
 
2859
   {
 
2860
      unsigned int idx = vs[i];
 
2861
      double m = m_masses[idx];
 
2862
      
 
2863
      Vec3d xdiff = m_positions[idx] - xcm;
 
2864
      Mat33d tens = outer(-xdiff, xdiff);
 
2865
      
 
2866
      double d = mag2(xdiff);
 
2867
      tens(0,0) += d;
 
2868
      tens(1,1) += d;
 
2869
      tens(2,2) += d;
 
2870
      
 
2871
      I += m * tens;
 
2872
   }
 
2873
   
 
2874
//   std::cout << "determinant " << determinant(I);
 
2875
//   std::cout << "I " << std::endl << I << std::endl;
 
2876
//   std::cout << "I^-1 " << std::endl << inverse(I) << std::endl;
 
2877
   
 
2878
   Vec3d w = inverse(I) * L;
 
2879
   double wmag = mag(w);
 
2880
   Vec3d wnorm = w/wmag;
 
2881
   
 
2882
   double cosdtw = cos(dt * wmag);
 
2883
   Vec3d sindtww = sin(dt * wmag) * wnorm;
 
2884
   
 
2885
   Vec3d xrigid = xcm + dt * vcm;
 
2886
   
 
2887
   for(unsigned int i = 0; i < vs.size(); i++)
 
2888
   {
 
2889
      unsigned int idx = vs[i];
 
2890
      
 
2891
      Vec3d xdiff = m_positions[idx] - xcm;
 
2892
      Vec3d xf = dot(xdiff, wnorm) * wnorm;
 
2893
      Vec3d xr = xdiff - xf;
 
2894
      
 
2895
      m_newpositions[idx] = xrigid + xf + cosdtw * xr + cross(sindtww, xr);
 
2896
      
 
2897
      m_velocities[idx] = ( m_newpositions[idx] - m_positions[idx] ) / dt;
 
2898
   }
 
2899
   
 
2900
//   std::cout << "\n\ninter-vertex distances after rigid motion: " << std::endl;
 
2901
//   for(unsigned int i = 0; i < vs.size(); i++)
 
2902
//   {
 
2903
//      for(unsigned int j = 0; j < vs.size(); j++)
 
2904
//      {
 
2905
//         std::cout << dist( m_newpositions[vs[i]], m_newpositions[vs[j]] ) << std::endl;
 
2906
//      }
 
2907
//   }
 
2908
   
 
2909
   // std::cout << "calculated rigid motion" << std::endl;
 
2910
   // for(unsigned int i = 0; i < vs.size(); i++)
 
2911
   // for(unsigned int j = 0; j < vs.size(); j++)
 
2912
   // std::cout << (dist(positions[vs[i]], positions[vs[j]]) - dist(newpositions[vs[i]], newpositions[vs[j]])) << std::endl;
 
2913
   
 
2914
}
 
2915
 
 
2916
 
 
2917
// ---------------------------------------------------------
 
2918
///
 
2919
/// 
 
2920
///
 
2921
// ---------------------------------------------------------
 
2922
 
 
2923
std::vector<unsigned int> DynamicSurface::merge_impact_zones( std::vector<unsigned int>& zones, 
 
2924
                                                              unsigned int z0, 
 
2925
                                                              unsigned int z1, 
 
2926
                                                              unsigned int z2, 
 
2927
                                                              unsigned int z3 )
 
2928
{
 
2929
   
 
2930
   std::vector<unsigned int> vs;
 
2931
   for(unsigned int i = 0; i < m_positions.size(); i++)
 
2932
   {
 
2933
      unsigned int& z = zones[i];
 
2934
      if(z == z0)
 
2935
      {
 
2936
         vs.push_back(i);
 
2937
      }
 
2938
      else if(z == z1)
 
2939
      {
 
2940
         vs.push_back(i);
 
2941
         z = z0;
 
2942
      }
 
2943
      else if(z == z2)
 
2944
      {
 
2945
         vs.push_back(i);
 
2946
         z = z0;
 
2947
      }
 
2948
      else if(z == z3)
 
2949
      {
 
2950
         vs.push_back(i);
 
2951
         z = z0;
 
2952
      }
 
2953
   }
 
2954
      
 
2955
   return vs;
 
2956
}
 
2957
 
 
2958
 
 
2959
// ---------------------------------------------------------
 
2960
///
 
2961
/// Advance mesh by one time step 
 
2962
///
 
2963
// ---------------------------------------------------------
 
2964
 
 
2965
void DynamicSurface::integrate( double dt )
 
2966
{     
 
2967
      
 
2968
   std::cout << "---------------------- El Topo: integration and collision handling --------------------" << std::endl;
 
2969
   
 
2970
   assert( m_positions.size() == m_velocities.size() );
 
2971
  
 
2972
   double curr_dt = dt;
 
2973
   double t = 0;
 
2974
      
 
2975
   while ( t < dt )
 
2976
   {
 
2977
      
 
2978
      // Handle proximities
 
2979
 
 
2980
//      for(unsigned int i = 0; i < m_positions.size(); i++)
 
2981
//      {
 
2982
//         m_velocities[i] = ( m_newpositions[i] - m_positions[i] ) / curr_dt;
 
2983
//      }
 
2984
      
 
2985
      m_num_collisions_this_step = 0;
 
2986
      
 
2987
      if ( m_collision_safety )
 
2988
      {
 
2989
         rebuild_static_broad_phase();
 
2990
         handle_edge_edge_proximities( curr_dt );
 
2991
         handle_triangle_point_proximities( curr_dt );
 
2992
      }
 
2993
 
 
2994
      
 
2995
      for(unsigned int i = 0; i < m_positions.size(); i++)
 
2996
      {
 
2997
         m_newpositions[i] = m_positions[i] + curr_dt * m_velocities[i];  
 
2998
      }
 
2999
      
 
3000
      
 
3001
      if ( m_collision_safety )
 
3002
      {        
 
3003
         // Handle continuous collisions
 
3004
         rebuild_continuous_broad_phase();
 
3005
 
 
3006
         bool all_collisions_handled = false;
 
3007
 
 
3008
         handle_point_vs_solid_triangle_collisions( curr_dt );
 
3009
         all_collisions_handled = handle_collisions( curr_dt );
 
3010
         
 
3011
         // failsafe impact zones 
 
3012
         
 
3013
         bool solver_ok = true;
 
3014
         
 
3015
         if ( !all_collisions_handled )
 
3016
         {
 
3017
            //solver_ok = handle_collisions_simultaneous( curr_dt );            
 
3018
         }
 
3019
 
 
3020
         if ( !solver_ok )
 
3021
         {
 
3022
            // punt to rigid impact zones
 
3023
           // new_rigid_impact_zones( curr_dt );
 
3024
         }  
 
3025
         
 
3026
         //assert_predicted_mesh_is_intersection_free();
 
3027
         
 
3028
      }
 
3029
 
 
3030
      m_total_num_collisions += m_num_collisions_this_step;
 
3031
      
 
3032
      // Set m_positions
 
3033
      for(unsigned int i = 0; i < m_positions.size(); i++)
 
3034
      {
 
3035
         m_positions[i] = m_newpositions[i];
 
3036
      } 
 
3037
      
 
3038
      t += curr_dt;
 
3039
   }
 
3040
   
 
3041
 
 
3042
}
 
3043
 
 
3044
// ---------------------------------------------------------
 
3045
///
 
3046
/// Construct static acceleration structure
 
3047
///
 
3048
// ---------------------------------------------------------
 
3049
 
 
3050
void DynamicSurface::rebuild_static_broad_phase()
 
3051
{
 
3052
   m_broad_phase->update_broad_phase_static( *this );
 
3053
}
 
3054
 
 
3055
// ---------------------------------------------------------
 
3056
///
 
3057
/// Construct continuous acceleration structure
 
3058
///
 
3059
// ---------------------------------------------------------
 
3060
 
 
3061
void DynamicSurface::rebuild_continuous_broad_phase()
 
3062
{
 
3063
   m_broad_phase->update_broad_phase_continuous( *this );
 
3064
}
 
3065
 
 
3066
 
 
3067
// ---------------------------------------------------------
 
3068
///
 
3069
/// Update the broadphase elements incident to the given vertex
 
3070
///
 
3071
// ---------------------------------------------------------
 
3072
 
 
3073
void DynamicSurface::update_static_broad_phase( unsigned int vertex_index )
 
3074
{
 
3075
   const std::vector<unsigned int>& incident_tris = m_mesh.m_vtxtri[ vertex_index ];
 
3076
   const std::vector<unsigned int>& incident_edges = m_mesh.m_vtxedge[ vertex_index ];
 
3077
   
 
3078
   Vec3d low, high;
 
3079
   vertex_static_bounds( vertex_index, low, high );
 
3080
   m_broad_phase->update_vertex( vertex_index, low, high );
 
3081
   
 
3082
   for ( unsigned int t = 0; t < incident_tris.size(); ++t )
 
3083
   {
 
3084
      triangle_static_bounds( incident_tris[t], low, high );
 
3085
      m_broad_phase->update_triangle( incident_tris[t], low, high );
 
3086
   }
 
3087
   
 
3088
   for ( unsigned int e = 0; e < incident_edges.size(); ++e )
 
3089
   {
 
3090
      edge_static_bounds( incident_edges[e], low, high );
 
3091
      m_broad_phase->update_edge( incident_edges[e], low, high );
 
3092
   }
 
3093
 
 
3094
}
 
3095
 
 
3096
 
 
3097
// ---------------------------------------------------------
 
3098
///
 
3099
/// Update the broadphase elements incident to the given vertex, using current and predicted vertex positions
 
3100
///
 
3101
// ---------------------------------------------------------
 
3102
 
 
3103
void DynamicSurface::update_continuous_broad_phase( unsigned int vertex_index )
 
3104
{
 
3105
   const std::vector<unsigned int>& incident_tris = m_mesh.m_vtxtri[ vertex_index ];
 
3106
   const std::vector<unsigned int>& incident_edges = m_mesh.m_vtxedge[ vertex_index ];
 
3107
 
 
3108
   Vec3d low, high;
 
3109
   vertex_continuous_bounds( vertex_index, low, high );
 
3110
   m_broad_phase->update_vertex( vertex_index, low, high );
 
3111
   
 
3112
   for ( unsigned int t = 0; t < incident_tris.size(); ++t )
 
3113
   {
 
3114
      triangle_continuous_bounds( incident_tris[t], low, high );
 
3115
      m_broad_phase->update_triangle( incident_tris[t], low, high );
 
3116
   }
 
3117
   
 
3118
   for ( unsigned int e = 0; e < incident_edges.size(); ++e )
 
3119
   {
 
3120
      edge_continuous_bounds( incident_edges[e], low, high );
 
3121
      m_broad_phase->update_edge( incident_edges[e], low, high );
 
3122
   }
 
3123
}
 
3124
 
 
3125
 
 
3126
// ---------------------------------------------------------
 
3127
///
 
3128
/// Compute the (padded) AABB of a vertex
 
3129
///
 
3130
// ---------------------------------------------------------
 
3131
 
 
3132
void DynamicSurface::vertex_static_bounds(unsigned int v, Vec3d &xmin, Vec3d &xmax) const
 
3133
{
 
3134
   if ( m_mesh.m_vtxtri[v].empty() )
 
3135
   {
 
3136
      xmin = Vec3d(m_proximity_epsilon, m_proximity_epsilon, m_proximity_epsilon);
 
3137
      xmax = -Vec3d(m_proximity_epsilon, m_proximity_epsilon, m_proximity_epsilon);
 
3138
   }
 
3139
   else
 
3140
   {
 
3141
      xmin = m_positions[v] - Vec3d(m_proximity_epsilon, m_proximity_epsilon, m_proximity_epsilon);
 
3142
      xmax = m_positions[v] + Vec3d(m_proximity_epsilon, m_proximity_epsilon, m_proximity_epsilon);
 
3143
   }
 
3144
}
 
3145
 
 
3146
// ---------------------------------------------------------
 
3147
///
 
3148
/// Compute the AABB of an edge
 
3149
///
 
3150
// ---------------------------------------------------------
 
3151
 
 
3152
void DynamicSurface::edge_static_bounds(unsigned int e, Vec3d &xmin, Vec3d &xmax) const
 
3153
{
 
3154
   const Vec2ui& edge = m_mesh.m_edges[e];
 
3155
   if ( edge[0] == edge[1] )
 
3156
   {
 
3157
      xmin = Vec3d(m_proximity_epsilon, m_proximity_epsilon, m_proximity_epsilon);
 
3158
      xmax = -Vec3d(m_proximity_epsilon, m_proximity_epsilon, m_proximity_epsilon);
 
3159
   }
 
3160
   else
 
3161
   {            
 
3162
      minmax(m_positions[edge[0]], m_positions[edge[1]], xmin, xmax);
 
3163
      xmin -= Vec3d(m_proximity_epsilon, m_proximity_epsilon, m_proximity_epsilon);
 
3164
      xmax += Vec3d(m_proximity_epsilon, m_proximity_epsilon, m_proximity_epsilon);
 
3165
   }
 
3166
}
 
3167
 
 
3168
// ---------------------------------------------------------
 
3169
///
 
3170
/// Compute the AABB of a triangle
 
3171
///
 
3172
// ---------------------------------------------------------
 
3173
 
 
3174
void DynamicSurface::triangle_static_bounds(unsigned int t, Vec3d &xmin, Vec3d &xmax) const
 
3175
{
 
3176
   const Vec3ui& tri = m_mesh.m_tris[t];  
 
3177
   if ( tri[0] == tri[1] )
 
3178
   {
 
3179
      xmin = Vec3d(m_proximity_epsilon, m_proximity_epsilon, m_proximity_epsilon);
 
3180
      xmax = -Vec3d(m_proximity_epsilon, m_proximity_epsilon, m_proximity_epsilon);
 
3181
   }
 
3182
   else
 
3183
   {      
 
3184
      minmax(m_positions[tri[0]], m_positions[tri[1]], m_positions[tri[2]], xmin, xmax);
 
3185
      xmin -= Vec3d(m_proximity_epsilon, m_proximity_epsilon, m_proximity_epsilon);
 
3186
      xmax += Vec3d(m_proximity_epsilon, m_proximity_epsilon, m_proximity_epsilon);
 
3187
   }
 
3188
}
 
3189
 
 
3190
// ---------------------------------------------------------
 
3191
///
 
3192
/// Compute the AABB of a continuous vertex
 
3193
///
 
3194
// ---------------------------------------------------------
 
3195
 
 
3196
void DynamicSurface::vertex_continuous_bounds(unsigned int v, Vec3d &xmin, Vec3d &xmax) const
 
3197
{
 
3198
   if ( m_mesh.m_vtxtri[v].empty() )
 
3199
   {
 
3200
      xmin = Vec3d(m_proximity_epsilon, m_proximity_epsilon, m_proximity_epsilon);
 
3201
      xmax = -Vec3d(m_proximity_epsilon, m_proximity_epsilon, m_proximity_epsilon);
 
3202
   }
 
3203
   else
 
3204
   {
 
3205
      minmax(m_positions[v], m_newpositions[v], xmin, xmax);
 
3206
      xmin -= Vec3d(m_proximity_epsilon, m_proximity_epsilon, m_proximity_epsilon);
 
3207
      xmax += Vec3d(m_proximity_epsilon, m_proximity_epsilon, m_proximity_epsilon);
 
3208
   }
 
3209
}
 
3210
 
 
3211
// ---------------------------------------------------------
 
3212
///
 
3213
/// Compute the AABB of a continuous edge
 
3214
///
 
3215
// ---------------------------------------------------------
 
3216
 
 
3217
void DynamicSurface::edge_continuous_bounds(unsigned int e, Vec3d &xmin, Vec3d &xmax) const
 
3218
{
 
3219
   const Vec2ui& edge = m_mesh.m_edges[e];   
 
3220
   if ( edge[0] == edge[1] )
 
3221
   {
 
3222
      xmin = Vec3d(m_proximity_epsilon, m_proximity_epsilon, m_proximity_epsilon);
 
3223
      xmax = -Vec3d(m_proximity_epsilon, m_proximity_epsilon, m_proximity_epsilon);
 
3224
   }
 
3225
   else
 
3226
   {      
 
3227
      minmax(m_positions[edge[0]], m_newpositions[edge[0]], m_positions[edge[1]], m_newpositions[edge[1]], xmin, xmax);
 
3228
      xmin -= Vec3d(m_proximity_epsilon, m_proximity_epsilon, m_proximity_epsilon);
 
3229
      xmax += Vec3d(m_proximity_epsilon, m_proximity_epsilon, m_proximity_epsilon);   
 
3230
   }
 
3231
}
 
3232
 
 
3233
// ---------------------------------------------------------
 
3234
///
 
3235
/// Compute the AABB of a continuous triangle
 
3236
///
 
3237
// ---------------------------------------------------------
 
3238
 
 
3239
void DynamicSurface::triangle_continuous_bounds(unsigned int t, Vec3d &xmin, Vec3d &xmax) const
 
3240
{
 
3241
   const Vec3ui& tri = m_mesh.m_tris[t];
 
3242
   if ( tri[0] == tri[1] )
 
3243
   {
 
3244
      xmin = Vec3d(m_proximity_epsilon, m_proximity_epsilon, m_proximity_epsilon);
 
3245
      xmax = -Vec3d(m_proximity_epsilon, m_proximity_epsilon, m_proximity_epsilon);
 
3246
   }
 
3247
   else
 
3248
   {
 
3249
      minmax(m_positions[tri[0]], m_newpositions[tri[0]], m_positions[tri[1]], m_newpositions[tri[1]], m_positions[tri[2]], m_newpositions[tri[2]], xmin, xmax);
 
3250
      xmin -= Vec3d(m_proximity_epsilon, m_proximity_epsilon, m_proximity_epsilon);
 
3251
      xmax += Vec3d(m_proximity_epsilon, m_proximity_epsilon, m_proximity_epsilon);   
 
3252
   }
 
3253
}
 
3254
 
 
3255
 
 
3256
// --------------------------------------------------------
 
3257
///
 
3258
/// Check a triangle (by index) vs all other triangles for any kind of intersection
 
3259
///
 
3260
// --------------------------------------------------------
 
3261
 
 
3262
bool DynamicSurface::check_triangle_vs_all_triangles_for_intersection( unsigned int tri_index  )
 
3263
{
 
3264
   return check_triangle_vs_all_triangles_for_intersection( m_mesh.m_tris[tri_index] );
 
3265
}
 
3266
 
 
3267
// --------------------------------------------------------
 
3268
///
 
3269
/// Check a triangle vs all other triangles for any kind of intersection
 
3270
///
 
3271
// --------------------------------------------------------
 
3272
 
 
3273
bool DynamicSurface::check_triangle_vs_all_triangles_for_intersection( const Vec3ui& tri )
 
3274
{
 
3275
   bool any_intersection = false;
 
3276
   
 
3277
   std::vector<unsigned int> overlapping_triangles;
 
3278
   Vec3d low, high;
 
3279
   
 
3280
   minmax( m_positions[tri[0]], m_positions[tri[1]], low, high );
 
3281
   low -= Vec3d(m_proximity_epsilon, m_proximity_epsilon, m_proximity_epsilon);
 
3282
   high += Vec3d(m_proximity_epsilon, m_proximity_epsilon, m_proximity_epsilon);
 
3283
   
 
3284
   m_broad_phase->get_potential_triangle_collisions( low, high, overlapping_triangles );
 
3285
   
 
3286
   for ( unsigned int i = 0; i < overlapping_triangles.size(); ++i )
 
3287
   {
 
3288
      
 
3289
      bool result = check_edge_triangle_intersection_by_index( tri[0], tri[1],
 
3290
                                                              m_mesh.m_tris[overlapping_triangles[i]][0], 
 
3291
                                                              m_mesh.m_tris[overlapping_triangles[i]][1], 
 
3292
                                                              m_mesh.m_tris[overlapping_triangles[i]][2],
 
3293
                                                              m_positions,
 
3294
                                                              false );
 
3295
      
 
3296
      if ( result )
 
3297
      {
 
3298
         check_edge_triangle_intersection_by_index( tri[0], tri[1],
 
3299
                                                   m_mesh.m_tris[overlapping_triangles[i]][0], 
 
3300
                                                   m_mesh.m_tris[overlapping_triangles[i]][1], 
 
3301
                                                   m_mesh.m_tris[overlapping_triangles[i]][2],
 
3302
                                                   m_positions,
 
3303
                                                   true );
 
3304
         
 
3305
         any_intersection = true;
 
3306
      }
 
3307
   }
 
3308
   
 
3309
   minmax( m_positions[tri[1]], m_positions[tri[2]], low, high );
 
3310
   low -= Vec3d(m_proximity_epsilon, m_proximity_epsilon, m_proximity_epsilon);
 
3311
   high += Vec3d(m_proximity_epsilon, m_proximity_epsilon, m_proximity_epsilon);
 
3312
   
 
3313
   overlapping_triangles.clear();
 
3314
   m_broad_phase->get_potential_triangle_collisions( low, high, overlapping_triangles );
 
3315
   
 
3316
   for ( unsigned int i = 0; i < overlapping_triangles.size(); ++i )
 
3317
   {
 
3318
      
 
3319
      bool result = check_edge_triangle_intersection_by_index( tri[1], tri[2],
 
3320
                                                              m_mesh.m_tris[overlapping_triangles[i]][0], 
 
3321
                                                              m_mesh.m_tris[overlapping_triangles[i]][1], 
 
3322
                                                              m_mesh.m_tris[overlapping_triangles[i]][2],
 
3323
                                                              m_positions,
 
3324
                                                              false );
 
3325
      
 
3326
      if ( result )
 
3327
      {
 
3328
         check_edge_triangle_intersection_by_index( tri[1], tri[2],
 
3329
                                                   m_mesh.m_tris[overlapping_triangles[i]][0], 
 
3330
                                                   m_mesh.m_tris[overlapping_triangles[i]][1], 
 
3331
                                                   m_mesh.m_tris[overlapping_triangles[i]][2],
 
3332
                                                   m_positions,
 
3333
                                                   true );
 
3334
         
 
3335
         any_intersection = true;
 
3336
      }
 
3337
   }
 
3338
   
 
3339
   minmax( m_positions[tri[2]], m_positions[tri[0]], low, high );
 
3340
   low -= Vec3d(m_proximity_epsilon, m_proximity_epsilon, m_proximity_epsilon);
 
3341
   high += Vec3d(m_proximity_epsilon, m_proximity_epsilon, m_proximity_epsilon);
 
3342
   
 
3343
   overlapping_triangles.clear();
 
3344
   m_broad_phase->get_potential_triangle_collisions( low, high, overlapping_triangles );
 
3345
   
 
3346
   for ( unsigned int i = 0; i < overlapping_triangles.size(); ++i )
 
3347
   {
 
3348
      
 
3349
      bool result = check_edge_triangle_intersection_by_index( tri[2], tri[0],
 
3350
                                                              m_mesh.m_tris[overlapping_triangles[i]][0], 
 
3351
                                                              m_mesh.m_tris[overlapping_triangles[i]][1], 
 
3352
                                                              m_mesh.m_tris[overlapping_triangles[i]][2],
 
3353
                                                              m_positions,
 
3354
                                                              false );
 
3355
      
 
3356
      if ( result )
 
3357
      {
 
3358
         check_edge_triangle_intersection_by_index( tri[2], tri[0],
 
3359
                                                   m_mesh.m_tris[overlapping_triangles[i]][0], 
 
3360
                                                   m_mesh.m_tris[overlapping_triangles[i]][1], 
 
3361
                                                   m_mesh.m_tris[overlapping_triangles[i]][2],
 
3362
                                                   m_positions,
 
3363
                                                   true );
 
3364
         
 
3365
         any_intersection = true;         
 
3366
      }
 
3367
   }
 
3368
   
 
3369
   //
 
3370
   // edges
 
3371
   //
 
3372
   
 
3373
   minmax( m_positions[tri[0]], m_positions[tri[1]], m_positions[tri[2]], low, high );
 
3374
   low -= Vec3d(m_proximity_epsilon, m_proximity_epsilon, m_proximity_epsilon);
 
3375
   high += Vec3d(m_proximity_epsilon, m_proximity_epsilon, m_proximity_epsilon);
 
3376
   
 
3377
   std::vector<unsigned int> overlapping_edges;
 
3378
   m_broad_phase->get_potential_edge_collisions( low, high, overlapping_edges );
 
3379
   
 
3380
   for ( unsigned int i = 0; i < overlapping_edges.size(); ++i )
 
3381
   {
 
3382
      
 
3383
      bool result = check_edge_triangle_intersection_by_index( m_mesh.m_edges[overlapping_edges[i]][0], m_mesh.m_edges[overlapping_edges[i]][1], 
 
3384
                                                              tri[0], tri[1], tri[2],
 
3385
                                                              m_positions,
 
3386
                                                              false );
 
3387
      
 
3388
      if ( result )
 
3389
      {
 
3390
         check_edge_triangle_intersection_by_index( m_mesh.m_edges[overlapping_edges[i]][0], m_mesh.m_edges[overlapping_edges[i]][1], 
 
3391
                                                   tri[0], tri[1], tri[2],
 
3392
                                                   m_positions,
 
3393
                                                   true );
 
3394
         
 
3395
         any_intersection = true;         
 
3396
      }
 
3397
   }
 
3398
   
 
3399
   return any_intersection;
 
3400
}
 
3401
 
 
3402
 
 
3403
// ---------------------------------------------------------
 
3404
///
 
3405
/// Fire an assert if any edge is intersecting any triangles
 
3406
///
 
3407
// ---------------------------------------------------------
 
3408
 
 
3409
void DynamicSurface::assert_mesh_is_intersection_free( bool degeneracy_counts_as_intersection )
 
3410
{
 
3411
       
 
3412
   //g_intersecting_triangles.clear();
 
3413
   
 
3414
   m_broad_phase->update_broad_phase_static( *this );
 
3415
      
 
3416
   for ( unsigned int i = 0; i < m_mesh.m_tris.size(); ++i )
 
3417
   {
 
3418
      std::vector<unsigned int> edge_candidates;
 
3419
      
 
3420
      Vec3d low, high;
 
3421
      triangle_static_bounds( i, low, high );       
 
3422
      m_broad_phase->get_potential_edge_collisions( low, high, edge_candidates );
 
3423
         
 
3424
      const Vec3ui& triangle_a = m_mesh.m_tris[i];
 
3425
      
 
3426
      if ( triangle_a[0] == triangle_a[1] || triangle_a[1] == triangle_a[2] || triangle_a[2] == triangle_a[0] )    { continue; }
 
3427
      
 
3428
      assert( m_mesh.get_edge( triangle_a[0], triangle_a[1] ) != m_mesh.m_edges.size() );
 
3429
      assert( m_mesh.get_edge( triangle_a[1], triangle_a[2] ) != m_mesh.m_edges.size() );
 
3430
      assert( m_mesh.get_edge( triangle_a[2], triangle_a[0] ) != m_mesh.m_edges.size() );
 
3431
      
 
3432
      for ( unsigned int j = 0; j < edge_candidates.size(); ++j )
 
3433
      {
 
3434
         
 
3435
         const Vec2ui& edge_b = m_mesh.m_edges[ edge_candidates[j] ];
 
3436
         
 
3437
         if ( edge_b[0] == edge_b[1] )    { continue; }
 
3438
         
 
3439
         if (    edge_b[0] == triangle_a[0] || edge_b[0] == triangle_a[1] || edge_b[0] == triangle_a[2] 
 
3440
              || edge_b[1] == triangle_a[0] || edge_b[1] == triangle_a[1] || edge_b[1] == triangle_a[2] )
 
3441
         {
 
3442
            continue;
 
3443
         }
 
3444
         
 
3445
         if ( segment_triangle_intersection( m_positions[edge_b[0]], edge_b[0], m_positions[edge_b[1]], edge_b[1],
 
3446
                                             m_positions[triangle_a[0]], triangle_a[0], 
 
3447
                                             m_positions[triangle_a[1]], triangle_a[1],
 
3448
                                             m_positions[triangle_a[2]], triangle_a[2],
 
3449
                                             degeneracy_counts_as_intersection, m_verbose ) )
 
3450
         {   
 
3451
            
 
3452
            if ( m_collision_safety )
 
3453
            {
 
3454
               std::cout << "Intersection!  Triangle " << triangle_a << " vs edge " << edge_b << std::endl;
 
3455
               
 
3456
               segment_triangle_intersection( m_positions[edge_b[0]], edge_b[0], m_positions[edge_b[1]], edge_b[1],
 
3457
                                              m_positions[triangle_a[0]], triangle_a[0],
 
3458
                                              m_positions[triangle_a[1]], triangle_a[1], 
 
3459
                                              m_positions[triangle_a[2]], triangle_a[2],
 
3460
                                              true, true );
 
3461
               
 
3462
               assert(0);
 
3463
            }
 
3464
            
 
3465
         }
 
3466
      }
 
3467
   }
 
3468
 
 
3469
}
 
3470
 
 
3471
 
 
3472
// ---------------------------------------------------------
 
3473
///
 
3474
/// Using m_newpositions as the geometry, fire an assert if any edge is intersecting any triangles
 
3475
///
 
3476
// ---------------------------------------------------------
 
3477
 
 
3478
void DynamicSurface::assert_predicted_mesh_is_intersection_free( )
 
3479
{
 
3480
       
 
3481
   rebuild_continuous_broad_phase();
 
3482
   
 
3483
   for ( unsigned int i = 0; i < m_mesh.m_tris.size(); ++i )
 
3484
   {
 
3485
      std::vector<unsigned int> edge_candidates;
 
3486
      
 
3487
      Vec3d low, high;
 
3488
      triangle_continuous_bounds( i, low, high );       
 
3489
      m_broad_phase->get_potential_edge_collisions( low, high, edge_candidates );
 
3490
      
 
3491
      const Vec3ui& triangle_a = m_mesh.m_tris[i];
 
3492
      
 
3493
      if ( triangle_a[0] == triangle_a[1] || triangle_a[1] == triangle_a[2] || triangle_a[2] == triangle_a[0] )    { continue; }
 
3494
      
 
3495
      for ( unsigned int j = 0; j < edge_candidates.size(); ++j )
 
3496
      {
 
3497
         
 
3498
         const Vec2ui& edge_b = m_mesh.m_edges[ edge_candidates[j] ];
 
3499
         
 
3500
         if ( edge_b[0] == edge_b[1] )    { continue; }
 
3501
         
 
3502
         if ( check_edge_triangle_intersection_by_index( edge_b[0], edge_b[1], 
 
3503
                                                         triangle_a[0], triangle_a[1], triangle_a[2], 
 
3504
                                                         m_newpositions, m_verbose )  )
 
3505
         {
 
3506
            if ( m_collision_safety )
 
3507
            {
 
3508
               std::cout << "Intersection!  Triangle " << triangle_a << " vs edge " << edge_b << std::endl;
 
3509
            }
 
3510
                        
 
3511
            m_verbose = true;
 
3512
                        
 
3513
            std::vector<Collision> check_collisions;
 
3514
            detect_collisions( check_collisions );
 
3515
            std::cout << "number of collisions detected: " << check_collisions.size() << std::endl;
 
3516
            
 
3517
            std::cout << "-----\n edge-triangle check using m_positions:" << std::endl;
 
3518
            
 
3519
            bool result = check_edge_triangle_intersection_by_index( edge_b[0], edge_b[1], 
 
3520
                                                       triangle_a[0], triangle_a[1], triangle_a[2], 
 
3521
                                                       m_positions, m_verbose );
 
3522
            
 
3523
            std::cout << "result: " << result << std::endl;
 
3524
            
 
3525
            std::cout << "-----\n edge-triangle check using new m_positions" << std::endl;
 
3526
            
 
3527
            result = check_edge_triangle_intersection_by_index( edge_b[0], edge_b[1], 
 
3528
                                                       triangle_a[0], triangle_a[1], triangle_a[2], 
 
3529
                                                       m_newpositions, m_verbose );
 
3530
            
 
3531
            std::cout << "result: " << result << std::endl;
 
3532
            
 
3533
            Vec3ui sorted_triangle = sort_triangle( triangle_a );
 
3534
            
 
3535
            std::cout << "sorted_triangle: " << sorted_triangle << std::endl;
 
3536
            
 
3537
            const Vec3d& ea = m_positions[edge_b[0]];
 
3538
            const Vec3d& eb = m_positions[edge_b[1]];
 
3539
            const Vec3d& ta = m_positions[sorted_triangle[0]];
 
3540
            const Vec3d& tb = m_positions[sorted_triangle[1]];
 
3541
            const Vec3d& tc = m_positions[sorted_triangle[2]];
 
3542
            
 
3543
            const Vec3d& ea_new = m_newpositions[edge_b[0]];
 
3544
            const Vec3d& eb_new = m_newpositions[edge_b[1]];
 
3545
            const Vec3d& ta_new = m_newpositions[sorted_triangle[0]];
 
3546
            const Vec3d& tb_new = m_newpositions[sorted_triangle[1]];
 
3547
            const Vec3d& tc_new = m_newpositions[sorted_triangle[2]];
 
3548
            
 
3549
            std::cout.precision(20);
 
3550
            
 
3551
            std::cout << "old: (edge0 edge1 tri0 tri1 tri2 )" << std::endl;
 
3552
            
 
3553
            std::cout << ea << std::endl;
 
3554
            std::cout << eb << std::endl;
 
3555
            std::cout << ta << std::endl;
 
3556
            std::cout << tb << std::endl;
 
3557
            std::cout << tc << std::endl;
 
3558
            
 
3559
            std::cout << "new: " << std::endl;
 
3560
            
 
3561
            std::cout << ea_new << std::endl;
 
3562
            std::cout << eb_new << std::endl;
 
3563
            std::cout << ta_new << std::endl;
 
3564
            std::cout << tb_new << std::endl;
 
3565
            std::cout << tc_new << std::endl;
 
3566
            
 
3567
            std::vector<double> possible_times;
 
3568
 
 
3569
            Vec3d normal;
 
3570
            
 
3571
            std::cout << "-----" << std::endl;
 
3572
            
 
3573
            if( segment_segment_collision( ea, ea_new, edge_b[0], eb, eb_new, edge_b[1], ta, ta_new, sorted_triangle[0], tb, tb_new, sorted_triangle[1] ) )
 
3574
            {
 
3575
               
 
3576
               bool check_flipped = segment_segment_collision( ta, ta_new, sorted_triangle[0], tb, tb_new, sorted_triangle[1], ea, ea_new, edge_b[0], eb, eb_new, edge_b[1] );
 
3577
               
 
3578
               assert( check_flipped );
 
3579
               
 
3580
               
 
3581
               double time, s0, s2, rel_disp;
 
3582
               Vec3d normal;
 
3583
               
 
3584
               assert ( segment_segment_collision( ea, ea_new, edge_b[0], 
 
3585
                                                   eb, eb_new, edge_b[1], 
 
3586
                                                   ta, ta_new, sorted_triangle[0], 
 
3587
                                                   tb, tb_new, sorted_triangle[1],
 
3588
                                                   s0, s2,
 
3589
                                                   normal,
 
3590
                                                   time, rel_disp ) );
 
3591
                  
 
3592
               
 
3593
               Vec3d xmin, xmax;
 
3594
               minmax( ea, ea_new, eb, eb_new, xmin, xmax);
 
3595
               xmin -= Vec3d(m_proximity_epsilon, m_proximity_epsilon, m_proximity_epsilon);
 
3596
               xmax += Vec3d(m_proximity_epsilon, m_proximity_epsilon, m_proximity_epsilon);   
 
3597
               std::vector<unsigned int> potential_collisions;
 
3598
               m_broad_phase->get_potential_edge_collisions( xmin, xmax, potential_collisions );
 
3599
             
 
3600
               for ( unsigned int c = 0; c < potential_collisions.size(); ++c )
 
3601
               {
 
3602
                  const Vec2ui& other_edge = m_mesh.m_edges[ potential_collisions[c] ];
 
3603
                  
 
3604
                  if ( ( other_edge[0] == sorted_triangle[0] && other_edge[1] == sorted_triangle[1] ) ||
 
3605
                       ( other_edge[1] == sorted_triangle[0] && other_edge[0] == sorted_triangle[1] ) )
 
3606
                  {
 
3607
                     std::cout << "Broadphase hit" << std::endl;
 
3608
                  }
 
3609
               }
 
3610
               
 
3611
               assert(0);
 
3612
               
 
3613
            }
 
3614
            
 
3615
            std::cout << "-----" << std::endl;
 
3616
            
 
3617
            assert( !segment_segment_collision( ea, ea_new, edge_b[0], eb, eb_new, edge_b[1], tb, tb_new, sorted_triangle[1], tc, tc_new, sorted_triangle[2] ) );
 
3618
                        
 
3619
            std::cout << "-----" << std::endl;
 
3620
 
 
3621
            assert( !segment_segment_collision( ea, ea_new, edge_b[0], eb, eb_new, edge_b[1], tc, tc_new, sorted_triangle[2], ta, ta_new, sorted_triangle[0] ) );
 
3622
            
 
3623
            std::cout << "-----" << std::endl;
 
3624
            
 
3625
            assert( !point_triangle_collision( ea, ea_new, edge_b[0], ta, ta_new, sorted_triangle[0], tb, tb_new, sorted_triangle[1], tc, tc_new, sorted_triangle[2] ) );
 
3626
            
 
3627
            std::cout << "-----" << std::endl;
 
3628
 
 
3629
            assert( !point_triangle_collision( eb, eb_new, edge_b[1], ta, ta_new, sorted_triangle[0], tb, tb_new, sorted_triangle[1], tc, tc_new, sorted_triangle[2] ) );
 
3630
                                   
 
3631
            m_verbose = false;
 
3632
            
 
3633
            if ( m_collision_safety )
 
3634
            {
 
3635
               std::cout << "no collisions detected" << std::endl;
 
3636
               //assert(0);
 
3637
            }
 
3638
         }
 
3639
      }
 
3640
   }
 
3641
   
 
3642
}
 
3643
 
 
3644
 
 
3645
 
 
3646
 
 
3647