AGX Dynamics 2.42.1.1
Loading...
Searching...
No Matches
LineCollisionUtils.h
Go to the documentation of this file.
1/*
2Copyright 2007-2025. Algoryx Simulation AB.
3
4All AGX source code, intellectual property, documentation, sample code,
5tutorials, scene files and technical white papers, are copyrighted, proprietary
6and confidential material of Algoryx Simulation AB. You may not download, read,
7store, distribute, publish, copy or otherwise disseminate, use or expose this
8material unless having a written signed agreement with Algoryx Simulation AB, or having been
9advised so by Algoryx Simulation AB for a time limited evaluation, or having purchased a
10valid commercial license from Algoryx Simulation AB.
11
12Algoryx Simulation AB disclaims all responsibilities for loss or damage caused
13from using this software, unless otherwise stated in written agreements with
14Algoryx Simulation AB.
15*/
16
17#ifndef AGXSDK_LINECOLLISIONUTILS_H
18#define AGXSDK_LINECOLLISIONUTILS_H
19
20#include <agx/Math.h>
21#include <agx/Vec3.h>
22#include <agx/Vec4.h>
23#include <agx/Quat.h>
24#include <agx/AffineMatrix4x4.h>
25#include <agxCollide/Mesh.h>
26
27namespace agxSDK
28{
29 // Return true if boundLower - threshold < val < boundUpper + threshold
30 static inline bool inBound( agx::Real val, agx::Real boundLower, agx::Real boundUpper, agx::Real threshold = agx::Real( 1E-6 ) )
31 {
32 return val > boundLower - threshold && val < boundUpper + threshold;
33 }
34
35 // Returns the sign pattern in v
36 static inline agx::Vec3 getSigned( const agx::Vec3& v )
37 {
38 return agx::Vec3( agx::sign( v.x() ), agx::sign( v.y() ), agx::sign( v.z() ) );
39 }
40
41 // Computes the scalar triple product: s = p * (q x r)
42 static inline agx::Real scalarTripleProduct( const agx::Vec3& p, const agx::Vec3& q, const agx::Vec3& r )
43 {
44 return p * ( q ^ r );
45 }
46
47 static inline agx::Vec3 getProjection( const agx::Vec3 contactPoint, agx::Vec3 edge, bool normalizedEdge = false ) {
48
49 if (!normalizedEdge)
50 edge.normalize();
51 return (edge*(contactPoint*edge));
52
53 }
54
55 static inline agx::Real getTotalAngleShapeCoordinates( agx::Vec3 edge, agx::Vec3 contactToCenter, const agx::Vec3& pos1, const agx::Vec3& pos2, const agx::Vec3& pos3, bool& onSameEdge )
56 {
57 // Calculate vectors
58 agx::Vec3 v21 = pos1 - pos2;
59 agx::Vec3 v23 = pos3 - pos2;
60 // Project all vectors onto plane defined by edge
61 contactToCenter -= edge * (edge * contactToCenter);
62 v21 -= edge * (edge * v21);
63 v23 -= edge * (edge * v23);
64 agx::Real l1 = contactToCenter.normalize();
65 agx::Real l2 = v21.normalize();
66 agx::Real l3 = v23.normalize();
67 onSameEdge = ( agx::equalsZero( l1 ) || agx::equalsZero( l2 ) || agx::equalsZero( l3 ) );
68 return (agx::Real)(acos( agx::clamp( v21 * contactToCenter, agx::Real( -1 ), agx::Real( 1 ) ) ) + acos( agx::clamp( v23 * contactToCenter, agx::Real( -1 ), agx::Real( 1 ) ) ));
69 }
70
71 static inline agx::Real findDistanceFromPointToLine( const agx::Vec3& L1, const agx::Vec3& L2, const agx::Vec3& P )
72 {
73 agx::Vec3 v1 = L2 - L1;
74 agx::Vec3 v2 = P - L1;
75 if ( agx::equalsZero(L2.distance2(P)) )
76 return 0.0;
77
78 if ( agx::equalsZero(L1.distance2(P)) )
79 return 0.0;
80
81 if ( agx::equalsZero(L2.distance2(L1)) )
82 return P.distance(L1);
83
84 //project v2 to v1
85 agx::Vec3 v2Proj = v1*(v1*v2)/v1.length2();
86
87 /************************************************************************/
88 /*
89 CASE 1:
90 L1------------------------------------L2 return dist between P and L1
91 P
92
93 CASE 2:
94
95 L1------------p-----------------------L2 return normal distance to line
96 |
97 |
98 P
99 CASE 3:
100
101 L1------------------------------------L2 return dist between P1 and L2
102
103 P
104
105 */
106 /************************************************************************/
107
108 if ( agx::leq(v2Proj * v1,agx::Real(0) ) )
109 {// CASE 1
110 return P.distance(L1);
111 }
112 else
113 {
114 if ( agx::geq( v2Proj.length2(), v1.length2()) )
115 {//CASE 3
116 return P.distance(L2);
117 }
118 else
119 {
120 agx::Vec3 p = L1 + v2Proj;
121 return P.distance(p);
122 }
123
124 }
125
126 }
127
128 // Given a vector with 12 elements, pair( Vec3, Vec3 ), this function will fill that what vector
129 // with the twelve edges.
130 static inline void fillEdgeVector( agx::Vector< std::pair< agx::Vec3, agx::Vec3 > >& v, const agx::Vec3& halfExtent )
131 {
132 agx::Real hex = halfExtent.x();
133 agx::Real hey = halfExtent.y();
134 agx::Real hez = halfExtent.z();
135
136 // ---------------------------------------------
137
138 v[ 0 ].first.set( -hex, -hey, -hez );
139 v[ 0 ].second.set( -hex, hey, -hez );
140
141 v[ 1 ].first.set( -hex, -hey, hez );
142 v[ 1 ].second.set( -hex, hey, hez );
143
144 v[ 2 ].first.set( hex, -hey, hez );
145 v[ 2 ].second.set( hex, hey, hez );
146
147 v[ 3 ].first.set( hex, -hey, -hez );
148 v[ 3 ].second.set( hex, hey, -hez );
149
150 // ---------------------------------------------
151
152 v[ 4 ].first.set( -hex, -hey, -hez );
153 v[ 4 ].second.set( -hex, -hey, hez );
154
155 v[ 5 ].first.set( -hex, -hey, hez );
156 v[ 5 ].second.set( hex, -hey, hez );
157
158 v[ 6 ].first.set( hex, -hey, -hez );
159 v[ 6 ].second.set( hex, -hey, hez );
160
161 v[ 7 ].first.set( -hex, -hey, -hez );
162 v[ 7 ].second.set( hex, -hey, -hez );
163
164 // ---------------------------------------------
165
166 v[ 8 ].first.set( -hex, hey, -hez );
167 v[ 8 ].second.set( -hex, hey, hez );
168
169 v[ 9 ].first.set( -hex, hey, hez );
170 v[ 9 ].second.set( hex, hey, hez );
171
172 v[ 10].first.set( hex, hey, -hez );
173 v[ 10].second.set( hex, hey, hez );
174
175 v[ 11].first.set( -hex, hey, -hez );
176 v[ 11].second.set( hex, hey, -hez );
177
178 // ---------------------------------------------
179 }
180
181 // Given A and B in the circle plane, this function will find Q1 and/or Q2 which is the points
182 // where the line segment intersects the circle.
184 const agx::Vec3& A,
185 const agx::Vec3& B,
186 const agx::Vec3& circlePos,
187 agx::Real radius,
188 agx::Vec3& Q1,
189 agx::Vec3& Q2,
190 bool& Q1Found,
191 bool& Q2Found,
192 const agx::Real epsilon = agx::AGX_EQUIVALENT_EPSILON )
193 {
194 Q1Found = false;
195 Q2Found = false;
196
197 agx::Vec3 R = A - circlePos;
198 agx::Vec3 dir = B - A;
199 agx::Real segmentLengthSq = dir.length2();
200
201 if ( agx::equalsZero( segmentLengthSq ) )
202 return false;
203
204 agx::Real a = 2 * ( dir * R ) / segmentLengthSq;
205 agx::Real b = ( R.length2() - radius * radius ) / segmentLengthSq;
206
207 agx::Real roots = agx::Real(0.25) * a * a - b;
208 if ( roots < 0 || agx::equalsZero( roots ) )
209 return false;
210
211 roots = std::sqrt( roots );
212
213 agx::Real t1 = agx::Real(-0.5) * a - roots;
214 agx::Real t2 = agx::Real(-0.5) * a + roots;
215
216 agxAssert( t1 < t2 );
217
218 if ( agx::geq( t1 , agx::Real(0),epsilon*radius*radius ) && agx::leq( t1 , 1,epsilon*radius*radius) )
219 {
220 if ( t1 < 0 )
221 t1 = 0;
222 if ( t1 > 1 )
223 t1 = 1;
224 Q1Found = true;
225 Q1 = A + dir * t1;
226 }
227 if ( agx::geq( t2 , agx::Real(0),epsilon*radius*radius ) && agx::leq( t2 , 1, epsilon*radius*radius) )
228 {
229 if ( t2 < 0 )
230 t2 = 0;
231 if ( t2 > 1 )
232 t2 = 1;
233 Q2Found = true;
234 Q2 = A + dir * t2;
235 }
236
237 return Q1Found || Q2Found;
238 }
239
240 // Given line segment A -> B and a plane, this method finds the point in the plane where the line segment passes.
241 static bool findPlaneLineSegmentIntersection( const agx::Vec3& A, const agx::Vec3& B, const agx::Vec3& planeOrigin, const agx::Vec3& planeNormal, agx::Real nearEndsThreshold, agx::Vec3& Q )
242 {
243 agxAssert( agx::equivalent( planeNormal.length2(), agx::Real( 1 ) ) );
244
245 agx::Real lengthInPlane = planeNormal * ( B - A );
246 // Segment is parallel to the plane, check if A is in the plane?
247 if ( agx::equalsZero( lengthInPlane ) )
248 return false;
249
250 agx::Real s = ( planeNormal * ( planeOrigin - A ) ) / lengthInPlane;
251 Q = A + ( B - A ) * s;
252 return inBound( s, 0 - nearEndsThreshold, 1 + nearEndsThreshold, 0 );
253 }
254
255 // Given line segment A -> B and a circle, this method finds the intersection point in the circle.
256 // If the return value is true, the segment intersects the circle.
257 static inline bool findSegmentCircleIntersection3D( const agx::Vec3& A, const agx::Vec3& B, const agx::Vec3& circleOrigin, const agx::Vec3& circleNormal, agx::Real circleRadius, agx::Real nearEndsThreshold, agx::Vec3& intersectionPoint )
258 {
259 bool intersects = findPlaneLineSegmentIntersection( A, B, circleOrigin, circleNormal, nearEndsThreshold, intersectionPoint );
260 if ( !intersects )
261 return false;
262
263 agx::Real l2 = ( intersectionPoint - circleOrigin ).length2();
264
265 return l2 < circleRadius * circleRadius && !agx::equalsZero( l2-circleRadius*circleRadius, nearEndsThreshold*2 ) ;
266 }
267
268 static inline bool pointInsideCircle( const agx::Vec3& point, const agx::Vec3& circleOrigin, agx::Real radius )
269 {
270 agx::Real dist2 = point.distance2( circleOrigin );
271 agx::Real r2 = radius * radius;
272 return agx::leq(dist2, r2) && !agx::equalsZero( dist2 - r2,agx::Real(1E-5) );
273 }
274
275 static inline agx::AffineMatrix4x4 getFuturePosition( const agx::Vec3& velocity, const agx::Vec3& angularVelocity, const agx::Vec3& position, const agx::Quat& rotation, agx::Real time )
276 {
278 ret.setTranslate( position + velocity * time );
279 agx::Vec3 ww = angularVelocity;
280 agx::Real alpha = agx::Real(0.5) * time * ww.normalize();
281 ret.setRotate( rotation * agx::Quat( agx::Vec4( ww * (agx::Real)sin( alpha ), (agx::Real)cos( alpha ) ) ) );
282 return ret;
283 }
284
286 {
287 public:
288 LineContactEdge() : m_length( 0 ) {}
289 LineContactEdge( const agx::Vec3& start, const agx::Vec3& end )
290 : m_start( start ), m_end( end )
291 {
292 m_normalized = end-start;
293 m_length = m_normalized.normalize();
294 }
296 const agx::Vec3& getNormalized() const { return m_normalized; }
297 const agx::Vec3& getStartPoint() const { return m_start; }
298 const agx::Vec3& getEndPoint() const { return m_end; }
299 agx::Vec3 getVector() const { return m_end-m_start; }
300 agx::Real getLength() const { return m_length; }
301
303 {
304 agx::Real max = 0.0;
305 int maxIndex = -1;
306 for ( int i = 0; i < 3; ++i ) {
307 if (m_normalized[i] > max) {
308 maxIndex = i;
309 max = m_normalized[i];
310 }
311 }
312 return maxIndex;
313
314 }
315
316 void mirror()
317 {
318 agx::Vec3 temp = m_start;
319 m_start = m_end;
320 m_end = temp;
321 m_normalized = m_end-m_start;
322 m_length = m_normalized.normalize();
323 }
324
326 {
327 agx::Vec3 edgeStart = m_start;
328 agx::Vec3 edgeEnd = m_end;
329 negateWhereNormalEntriesAreZero( edgeStart );
330 negateWhereNormalEntriesAreZero( edgeEnd );
331 return LineContactEdge( edgeStart, edgeEnd );
332 }
333
337 static inline agx::Vec3 setValueWhereZeroEntries( const agx::Vec3& edge, agx::Real value )
338 {
339 return agx::Vec3( edge[ 0 ] == 0 ? value : 0, edge[ 1 ] == 0 ? value : 0, edge[ 2 ] == 0 ? value : 0 );
340 }
341
342 static inline LineContactEdge findOppositeEdge( const agx::Vec3& edgeStart, const agx::Vec3& edgeEnd, const agx::Vec3& edge )
343 {
344 agx::Vec3 oppositeEdgeStart = edgeStart;
345 agx::Vec3 oppositeEdgeEnd = edgeEnd;
346
347 for ( int i = 0; i < 3; ++i ) {
348 if ( edge[ i ] == 0 ) {
349 oppositeEdgeStart[ i ] *= -1;
350 oppositeEdgeEnd[ i ] *= -1;
351 }
352 else {
353 agxAssert( !agx::equalsZero( edge[ i ] ) );
354 }
355 }
356
357 return LineContactEdge( oppositeEdgeStart, oppositeEdgeEnd );
358 }
359 private:
360 void negateWhereNormalEntriesAreZero( agx::Vec3& v ) const
361 {
362 v[ 0 ] *= agx::Real(m_normalized[ 0 ] == 0 ? -1 : 1);
363 v[ 1 ] *= agx::Real(m_normalized[ 1 ] == 0 ? -1 : 1);
364 v[ 2 ] *= agx::Real(m_normalized[ 2 ] == 0 ? -1 : 1);
365 }
366
367 agx::Vec3 m_start;
368 agx::Vec3 m_end;
369 agx::Vec3 m_normalized;
370 agx::Real m_length;
371 };
372
374 {
375 public:
377 :m_t(0), m_edge(LineContactEdge()){}
378
380 {
381 m_edge = LineContactEdge(start,end);
382
383 }
384
386
389 {
390 return m_edge.getStartPoint()+(m_edge.getEndPoint()-m_edge.getStartPoint())*m_t;
391 }
392
393 agx::Real getT() const {return m_t;}
394 const LineContactEdge& getEdge() const {return m_edge;}
395
396 private:
397 agx::Real m_t;
398 LineContactEdge m_edge;
399 };
400
401 static inline agx::Vec3 calculateBoxOffset( const agx::Vec3& shapeEdge, const agx::Vec3& shapeContactPosition, agx::Real radius )
402 {
403 agx::Vec3 offset = LineContactEdge::setValueWhereZeroEntries( shapeEdge, radius );
404 return agx::Vec3::mul( offset, getSigned( shapeContactPosition ) );
405 }
406
407 static inline agx::Vec3 calculateCylinderOffset( const agx::Vec3& shapeEdge, const agx::Vec3& shapeContactPosition, agx::Real radius )
408 {
409
410 agx::Vec3 offset;
411 agx::Vec3 radialDir = shapeContactPosition;
412 radialDir.y() = 0;
413 radialDir.normalize();
414 radialDir *= radius;
415 offset = radialDir;
416 if ( agx::equalsZero( shapeEdge.y() ) )
417 {//circle contact
418
419 offset += agx::Vec3(0,(agx::Real)agx::sign(shapeContactPosition.y())*radius,0);
420 }
421 return offset;
422 }
423
424 static inline agx::Vec3 calculateMeshOffset( const agxCollide::Mesh* mesh, const size_t triangleIndex, const uint8_t edgeIndex ,const agx::Vec3& /*shapeEdge*/, const agx::Real radius )
425 {
426 const agxCollide::Mesh::Triangle triangle1 = mesh->getTriangle(triangleIndex);
427 if ( !triangle1.isValid() )
428 return agx::Vec3(0,0,0);
429
430 agx::Vec3 normal1 = triangle1.getNormal();
431
432 const agxCollide::Mesh::Triangle triangle2 = triangle1.getHalfEdgePartner( edgeIndex );
433
434 agx::Vec3 normal2;
435
436 if ( !triangle2.isValid() )
437 normal2 = agx::Vec3(0,0,0);
438 else
439 normal2 = triangle2.getNormal();
440
441 agx::Vec3 offset = normal1 + normal2;
442 offset.normalize();
443 offset *= radius;
444 return offset;
445
446 }
447
448 static inline uint8_t getEdgeStartLocalVertexIndex(const uint8_t localEdgeIndex,const bool atBegin)
449 {
450 uint8_t vertexIndex = localEdgeIndex;
451 if ( !atBegin )
452 vertexIndex = (uint8_t)((localEdgeIndex + 1)%3);
453 return vertexIndex;
454 }
455
456 static inline uint8_t getEdgeEndLocalVertexIndex(const uint8_t localEdgeIndex,const bool atBegin)
457 {
458 //The other end of edge, must be compared with the result so that we don't get the same edge again, but other direction
459 uint8_t startEdgeIndex = getEdgeStartLocalVertexIndex(localEdgeIndex, atBegin);
460
461 if ( atBegin )
462 startEdgeIndex = (uint8_t)((startEdgeIndex + 1)%3);
463 else
464 startEdgeIndex = (uint8_t)((startEdgeIndex + 2)%3);
465
466 return startEdgeIndex;//really end =)
467
468 }
469 static inline uint8_t getLocalEdgeIndexFromVertexIndices( const size_t iteratedVertexIndex, const size_t oppositeVertexIndex )
470 {
471 uint8_t localEdgeIndex = 0;
472 if ( oppositeVertexIndex > iteratedVertexIndex )
473 {
474 if ( oppositeVertexIndex == 2 )
475 {
476 if ( iteratedVertexIndex == 0 )
477 localEdgeIndex = 2;
478 else //iteratedVertexIndex == 1
479 localEdgeIndex = 1;
480 }
481 else if ( oppositeVertexIndex == 1 )
482 localEdgeIndex = 0;
483 }
484 else
485 {
486 if ( oppositeVertexIndex == 1 )
487 {
488
489 localEdgeIndex = 1;
490 }
491 else if ( oppositeVertexIndex == 0 )
492 {
493 if ( iteratedVertexIndex == 2 )
494 localEdgeIndex = 2;
495 else //iteratedVertexIndex == 1
496 localEdgeIndex = 0;
497 }
498 }
499 return localEdgeIndex;
500 }
501
502 static inline void findMostParallelEdgeAmongNeighboringTriangles( const agxCollide::Mesh* mesh,const agx::Vec3& /*shapeOffset*/,const size_t triangleIndex,const uint8_t edgeIndex, size_t& tempNewTriangleStartIndex,size_t& tempNewEdgeLocalStartIndex,const bool atBegin )
503 {
504
505 agxCollide::Mesh::Triangle triangle = mesh->getTriangle(triangleIndex);
506
507 uint8_t vertexIndex = getEdgeStartLocalVertexIndex(edgeIndex,atBegin);
508
509 agx::Real angle = agx::Real(1.1)*agx::PI;
510
511 agxCollide::Mesh::VertexEdgeCirculator triangleIteratorVertex = mesh->createVertexEdgeCirculator( triangleIndex, vertexIndex);
512
513 agx::Vec3 currentEdge = mesh->getTriangleVertex(triangleIndex, (uint_fast8_t)(edgeIndex + (uint8_t)1)%(uint8_t)3) - mesh->getTriangleVertex(triangleIndex,(uint_fast8_t)edgeIndex);
514 currentEdge.normalize();
515
516 if ( atBegin )
517 currentEdge *= -1.0;
518
519 size_t globalVertexIndex = triangleIteratorVertex.getTriangle().getGlobalVertexIndex(vertexIndex);
520 agx::Vec3 vertexPos = triangleIteratorVertex.getTriangle().getVertex(vertexIndex);
521
522 bool done = false;
523
524 triangleIteratorVertex++; //++
525
526 while ( triangleIteratorVertex.isValid() && !triangleIteratorVertex.atEnd() ) {
527
528 size_t tempTriangleIndex = triangleIteratorVertex.getTriangle().getTriangleIndex();
529
530 if ( tempTriangleIndex == triangleIndex )
531 {
532 if ( triangleIteratorVertex.getTriangle().hasHalfEdgePartner( triangleIteratorVertex.getLocalEdgeIndex() ) )
533 {
534 tempTriangleIndex = triangleIteratorVertex.getTriangle().getHalfEdgePartner( triangleIteratorVertex.getLocalEdgeIndex() ).getTriangleIndex();
535 }
536 }
537
538
539 agxCollide::Mesh::Triangle tempTriangle = mesh->getTriangle( tempTriangleIndex );
540
541 if ( tempTriangleIndex != triangleIndex )
542 {
543 agx::Vec3 end1,end2;
544 uint8_t i1 = 0;
545 uint8_t i2 = 0;
546 size_t localVertexIndex = 0;
547 if ( tempTriangle.getGlobalVertexIndex( 0 ) == globalVertexIndex )
548 {
549 i1 = 1;
550 i2 = 2;
551 localVertexIndex = 0;
552 }
553 else if ( tempTriangle.getGlobalVertexIndex( 1 ) == globalVertexIndex )
554 {
555 i1 = 0;
556 i2 = 2;
557 localVertexIndex = 1;
558 }
559 else if ( tempTriangle.getGlobalVertexIndex( 2 ) == globalVertexIndex )
560 {
561 i1 = 0;
562 i2 = 1;
563 localVertexIndex = 2;
564 }
565 else
566 {
567 triangleIteratorVertex++;
568 continue;
569 }
570
571 end1 = tempTriangle.getVertex(i1);
572 end2 = tempTriangle.getVertex(i2);
573
574 end1 -= vertexPos;
575 end1.normalize();
576
577 end2 -= vertexPos;
578 end2.normalize();
579
580 agx::Real tempAngle1 = (agx::Real)acos( agx::clamp( currentEdge * end1,agx::Real(-1),agx::Real(1) ));
581
582 //if ( end1 * shapeOffset > 0 )
583 // tempAngle1 += agx::PI;
584
585 agx::Real tempAngle2 = (agx::Real)acos( agx::clamp( currentEdge * end2 ,agx::Real(-1),agx::Real(1)) );
586
587 //if ( end2 * shapeOffset > 0 )
588 // tempAngle2 += agx::PI;
589
590 bool secondIsVerified = false;
591 uint8_t localEdgeIndex = 0;
592 if ( tempAngle2 < tempAngle1)
593 {//only need to check the larger of the two
594
595 //verify i2
596 localEdgeIndex = getLocalEdgeIndexFromVertexIndices( localVertexIndex,i2 );
597
598 if ( triangle.getTriangleIndex() != tempTriangle.getHalfEdgePartner( localEdgeIndex ).getTriangleIndex() )
599 {
600 tempAngle1 = tempAngle2;
601 i1 = i2;
602 secondIsVerified = true;
603 }
604
605 }
606
607 if ( tempAngle1 < angle )
608 {
609 if ( !secondIsVerified )
610 {
611 localEdgeIndex = getLocalEdgeIndexFromVertexIndices( localVertexIndex,i1 );
612
613 if ( triangle.getTriangleIndex() == tempTriangle.getHalfEdgePartner( localEdgeIndex ).getTriangleIndex() )
614 {
615 triangleIteratorVertex++;
616 continue;
617 }
618 }
619
620 tempNewTriangleStartIndex = tempTriangleIndex;
621 tempNewEdgeLocalStartIndex = localEdgeIndex;
622 angle = tempAngle1;
623 done = true;
624
625 }
626 }
627
628 triangleIteratorVertex++; //++
629
630 }
631
632 if ( !done )
633 {
634 tempNewTriangleStartIndex = triangleIndex;
635 tempNewEdgeLocalStartIndex = edgeIndex;
636 }
637
638 }
639
648 static inline agx::Real findAdjustmentForMeshEdge( const agx::Vec3& lineEndW, const agx::Vec3& lineStartW, const agx::Vec3& edgeStart, const agx::Vec3& edgeEnd , agx::Real lineRadius)
649 {
650 agx::Real t = 0;
651
652 agx::Vec3 v1 = lineEndW - lineStartW;
653 agx::Vec3 v2 = edgeEnd - edgeStart;
654 agx::Real dist = v1.normalize();
655 v2.normalize();
656
657 agx::Vec3 mean = v2+v1;
658 mean.normalize();
659
660 agx::Real angle = (agx::Real)acos( agx::clamp(-v1*v2,agx::Real(-1),agx::Real(1)) );
661 agx::Real removedDist = lineRadius * (agx::Real)tan( angle * agx::Real(0.5) ) + lineRadius;
662
663 if ( dist - removedDist < 0 )
664 return 0;
665
666 t = (dist - removedDist)/dist;
667
668 return t;
669 }
670
671 static inline void copyVectors( agx::Vec3Vector& newContactShapeTranslates,const agx::Vec3Vector& newContactShapeTranslatesB,agx::Vector<size_t>& newTriangleIndices,const agx::Vector<size_t>& newTriangleIndicesB,agx::Vector<size_t>& newEdgeIndices,const agx::Vector<size_t>& newEdgeIndicesB )
672 {
673 for ( size_t i = 0; i < newContactShapeTranslatesB.size(); ++i )
674 {
675 newContactShapeTranslates.push_back( newContactShapeTranslatesB[i] );
676 newTriangleIndices.push_back( newTriangleIndicesB[i] );
677 newEdgeIndices.push_back( newEdgeIndicesB[i] );
678 }
679 }
680
681}
682
683#endif
684
Class for more intuitive access to the Mesh's mesh data.
Definition: Mesh.h:79
agx::Vec3 getVertex(uint_fast8_t localVertexIndex) const
Definition: Mesh.h:666
size_t getGlobalVertexIndex(uint_fast8_t localVertexIndex) const
Returns the global index of the vertex.
Definition: Mesh.h:648
bool isValid() const
Definition: Mesh.h:654
agx::Vec3 getNormal() const
This function returns the triangle normal (as stored in the collision mesh data).
Definition: Mesh.h:660
bool hasHalfEdgePartner(uint_fast8_t localEdgeIndex) const
Definition: Mesh.h:711
size_t getTriangleIndex() const
Implementations.
Definition: Mesh.h:642
const Triangle getHalfEdgePartner(uint_fast8_t localEdgeIndex) const
Definition: Mesh.h:696
Class in order to circulate over the edges connected to a Triangle's vertex.
Definition: Mesh.h:203
const Triangle getTriangle() const
Definition: Mesh.h:971
uint_fast8_t getLocalEdgeIndex() const
Definition: Mesh.h:978
Mesh is a common base class for triangle meshes, such as Mesh or HeightField.
Definition: Mesh.h:70
VertexEdgeCirculator createVertexEdgeCirculator(size_t triangleIndex, uint_fast8_t localVertexIndex) const
Creates an VertexEdgeCirculator pointing to this Triangle and a Voronoi region.
Definition: Mesh.h:1013
const Triangle getTriangle(size_t triangleIndex) const
Definition: Mesh.h:731
agx::Vec3 getTriangleVertex(size_t triangleIndex, uint_fast8_t localVertexIndex) const
Returns one of the three vertices in a triangle.
Definition: Mesh.h:767
LineContactEdge(const agx::Vec3 &start, const agx::Vec3 &end)
agx::Vec3 getVector() const
LineContactEdge findOppositeEdge() const
const agx::Vec3 & getStartPoint() const
agx::Real getLength() const
const agx::Vec3 & getNormalized() const
static agx::Vec3 setValueWhereZeroEntries(const agx::Vec3 &edge, agx::Real value)
Sets the value where the edge entry is zero.
static LineContactEdge findOppositeEdge(const agx::Vec3 &edgeStart, const agx::Vec3 &edgeEnd, const agx::Vec3 &edge)
const agx::Vec3 & getEndPoint() const
LineContactPosition(agx::Vec3 start, agx::Vec3 end, agx::Real t)
const LineContactEdge & getEdge() const
AffineMatrix4x4T< T > & setRotate(const QuatT< T > &q)
Set the rotational part of the matrix using the specified quaternion leaving the translational part u...
AffineMatrix4x4T< T > & setTranslate(const Vec3T< T > &t)
Set the translational part of the matrix using the vector t.
size_t size() const
Definition: Container.h:134
Real normalize()
Normalize the vector so that it has length unity.
Definition: Vec3Template.h:701
Real distance2(const Vec3T &v2) const
Squared distance to another vector.
Definition: Vec3Template.h:876
static Vec3T mul(const Vec3T &lhs, const Vec3T &rhs)
Element-wise-multiplication.
Definition: Vec3Template.h:569
Real distance(const Vec3T &v2) const
Distance to another vector.
Definition: Vec3Template.h:695
Real length2() const
Length squared of the vector = vec .
Definition: Vec3Template.h:689
A class holding 4 dimensional vectors and providing basic arithmetic.
Definition: Vec4Template.h:35
void push_back(const T &value)
Definition: agx/Vector.h:1362
Templated vector class.
Definition: agx/Vector.h:53
void push_back(const T2 &value)
Definition: agx/Vector.h:715
#define agxAssert(expr)
Definition: debug.h:143
The agxSDK namespace contain classes to bridge the collision detection system and the dynamical simul...
Definition: Constraint.h:31
static uint8_t getEdgeStartLocalVertexIndex(const uint8_t localEdgeIndex, const bool atBegin)
static bool pointInsideCircle(const agx::Vec3 &point, const agx::Vec3 &circleOrigin, agx::Real radius)
static void copyVectors(agx::Vec3Vector &newContactShapeTranslates, const agx::Vec3Vector &newContactShapeTranslatesB, agx::Vector< size_t > &newTriangleIndices, const agx::Vector< size_t > &newTriangleIndicesB, agx::Vector< size_t > &newEdgeIndices, const agx::Vector< size_t > &newEdgeIndicesB)
static bool findPlaneLineSegmentIntersection(const agx::Vec3 &A, const agx::Vec3 &B, const agx::Vec3 &planeOrigin, const agx::Vec3 &planeNormal, agx::Real nearEndsThreshold, agx::Vec3 &Q)
static agx::AffineMatrix4x4 getFuturePosition(const agx::Vec3 &velocity, const agx::Vec3 &angularVelocity, const agx::Vec3 &position, const agx::Quat &rotation, agx::Real time)
static bool inBound(agx::Real val, agx::Real boundLower, agx::Real boundUpper, agx::Real threshold=agx::Real(1E-6))
static bool findSegmentCircleIntersection3D(const agx::Vec3 &A, const agx::Vec3 &B, const agx::Vec3 &circleOrigin, const agx::Vec3 &circleNormal, agx::Real circleRadius, agx::Real nearEndsThreshold, agx::Vec3 &intersectionPoint)
static uint8_t getLocalEdgeIndexFromVertexIndices(const size_t iteratedVertexIndex, const size_t oppositeVertexIndex)
static agx::Vec3 calculateCylinderOffset(const agx::Vec3 &shapeEdge, const agx::Vec3 &shapeContactPosition, agx::Real radius)
static agx::Real findAdjustmentForMeshEdge(const agx::Vec3 &lineEndW, const agx::Vec3 &lineStartW, const agx::Vec3 &edgeStart, const agx::Vec3 &edgeEnd, agx::Real lineRadius)
Shorten the movement range due to neighboring triangles.
static agx::Vec3 calculateMeshOffset(const agxCollide::Mesh *mesh, const size_t triangleIndex, const uint8_t edgeIndex, const agx::Vec3 &, const agx::Real radius)
static bool findSegmentCircleIntersections2D(const agx::Vec3 &A, const agx::Vec3 &B, const agx::Vec3 &circlePos, agx::Real radius, agx::Vec3 &Q1, agx::Vec3 &Q2, bool &Q1Found, bool &Q2Found, const agx::Real epsilon=agx::AGX_EQUIVALENT_EPSILON)
static uint8_t getEdgeEndLocalVertexIndex(const uint8_t localEdgeIndex, const bool atBegin)
static agx::Real scalarTripleProduct(const agx::Vec3 &p, const agx::Vec3 &q, const agx::Vec3 &r)
static void fillEdgeVector(agx::Vector< std::pair< agx::Vec3, agx::Vec3 > > &v, const agx::Vec3 &halfExtent)
static agx::Vec3 getProjection(const agx::Vec3 contactPoint, agx::Vec3 edge, bool normalizedEdge=false)
static agx::Real getTotalAngleShapeCoordinates(agx::Vec3 edge, agx::Vec3 contactToCenter, const agx::Vec3 &pos1, const agx::Vec3 &pos2, const agx::Vec3 &pos3, bool &onSameEdge)
static agx::Vec3 calculateBoxOffset(const agx::Vec3 &shapeEdge, const agx::Vec3 &shapeContactPosition, agx::Real radius)
static agx::Vec3 getSigned(const agx::Vec3 &v)
static agx::Real findDistanceFromPointToLine(const agx::Vec3 &L1, const agx::Vec3 &L2, const agx::Vec3 &P)
static void findMostParallelEdgeAmongNeighboringTriangles(const agxCollide::Mesh *mesh, const agx::Vec3 &, const size_t triangleIndex, const uint8_t edgeIndex, size_t &tempNewTriangleStartIndex, size_t &tempNewEdgeLocalStartIndex, const bool atBegin)
T sign(T v)
Definition: Math.h:328
Vec3T< Real > Vec3
The object holding 3 dimensional vectors and providing basic arithmetic.
Definition: agx/Vec3.h:36
bool geq(double a, double b, double eps=(double) AGX_EQUIVALENT_EPSILON)
Definition: Math.h:381
T1 clamp(T1 v, T2 minimum, T3 maximum)
Definition: Math.h:318
AGXPHYSICS_EXPORT agx::Bool equalsZero(const agx::AddedMassInteraction::Matrix6x6 &matrix, agx::Real eps=agx::RealEpsilon)
static constexpr Real PI
Definition: Math.h:63
double Real
Definition: Real.h:41
bool leq(double a, double b, double eps=(double) AGX_EQUIVALENT_EPSILON)
Definition: Math.h:369
static constexpr Real AGX_EQUIVALENT_EPSILON
Definition: Math.h:57
AGXPHYSICS_EXPORT agx::Bool equivalent(const agx::AddedMassInteraction::Matrix6x6 &lhs, const agx::AddedMassInteraction::Matrix6x6 &rhs, agx::Real eps=agx::RealEpsilon)