mrDIMAS

GJK EPA 3

Oct 15th, 2015
189
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 30.63 KB | None | 0 0
  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <float.h>
  4. #include <stdbool.h>
  5. #include <string.h>
  6.  
  7. #include "vector3.h"
  8.  
  9. typedef struct TSupport {
  10.     TVec3 supportA;
  11.     TVec3 minkowskiDifPoint;
  12. } TSupport;
  13.  
  14. typedef struct TSimplex {
  15.     TSupport points[4];
  16.     int size;
  17. } TSimplex;
  18.  
  19. typedef struct TEPAFace {
  20.     int a, b, c;
  21. } TEPAFace;
  22.  
  23. typedef struct TSphereShape {
  24.     float radius;
  25. } TSphereShape;
  26.  
  27. typedef struct TConvexShape {
  28.     TVec3 * points;
  29.     int count;    
  30. } TConvexShape;
  31.  
  32. typedef struct TTriangleShape {
  33.     TVec3 a, b, c;
  34. } TTriangleShape;
  35.  
  36. typedef struct TTriangleMeshShape {
  37.     TVec3 * vertices;
  38.     int vertexCount;
  39.     TEPAFace * faces;
  40.     int faceCount;
  41. } TTriangleMeshShape;
  42.  
  43. typedef struct TBoxShape {
  44.     TVec3 vertices[8];
  45. } TBoxShape;
  46.  
  47. typedef struct TShape {
  48.     TConvexShape * convex;
  49.     TSphereShape * sphere;
  50.     TTriangleMeshShape * triMesh;
  51.     TTriangleShape * triangle;
  52.     TBoxShape * box;
  53.     TVec3 position;
  54. } TShape;
  55.  
  56. typedef struct TEPATriangle {
  57.     TSupport a, b, c;
  58.     TVec3 normal;
  59.     float dist;
  60.     int numInPolytope;
  61. } TEPATriangle;
  62.  
  63. typedef struct TEPAContact {
  64.     TVec3 normal;
  65.     float penetrationDepth;
  66. } TEPAContact;
  67.  
  68. typedef struct TEPAPolytope {
  69.     TSupport * vertices;
  70.     int vertexCount;
  71.     TEPAFace * faces;
  72.     int faceCount;
  73. } TEPAPolytope;
  74.  
  75. typedef struct TEdge {
  76.     int a;
  77.     int b;
  78.     bool free;
  79. } TEdge;
  80.  
  81. typedef struct TEdgeList {
  82.     TEdge * edges;
  83.     int count;
  84.     int freeCount;
  85. } TEdgeList;
  86.  
  87. typedef struct TBody {
  88.     TVec3 position;
  89.     TShape * shape;
  90. } TBody;
  91.  
  92. #ifndef M_PI
  93. #   define M_PI 3.14159
  94. #endif
  95.  
  96.  
  97. TEPAPolytope * currentPolytope;
  98. TShape * currentShape1;
  99. TShape * currentShape2;
  100. // ===========================
  101. // HELPERS
  102. // ===========================
  103. bool Helper_SameDirection( TVec3 a, TVec3 b ) {
  104.     return Vec3_Dot( a, b ) > 0;
  105. }
  106.  
  107. // ===========================
  108. // SIMPLEX ROUTINE
  109. // ===========================
  110. void Simplex_RemovePoint( TSimplex * s, int num ) {
  111.     if( s->size > 0 ) {
  112.         if( num == 0 ) {
  113.             s->points[0] = s->points[1];
  114.             s->points[1] = s->points[2];
  115.             s->points[2] = s->points[3];
  116.         }
  117.         if( num == 1 ) {
  118.             s->points[1] = s->points[2];
  119.             s->points[2] = s->points[3];
  120.         }
  121.         if( num == 2 ) {
  122.             s->points[2] = s->points[3];
  123.         }
  124.         s->size--;
  125.     }
  126. }
  127.  
  128. void Simplex_AddPoint( TSimplex * s, TSupport p ) {
  129.     if( s->size < 4 ) {
  130.         s->points[ s->size ] = p;
  131.         s->size++;
  132.     }
  133. }
  134.  
  135. // ===========================
  136. // CONVEX SHAPE ROUTINE
  137. // ===========================
  138. TShape * ConvexShape_CreateTriangle( TVec3 a, TVec3 b, TVec3 c ) {
  139.     TShape * shape = calloc( 1, sizeof( TShape ));
  140.     shape->convex = calloc( 1, sizeof( TConvexShape ));
  141.     shape->convex->count = 3;
  142.     shape->convex->points = malloc( shape->convex->count * sizeof( TVec3 ));
  143.     shape->convex->points[0] = a;
  144.     shape->convex->points[1] = b;
  145.     shape->convex->points[2] = c;
  146.     return shape;
  147. }
  148.  
  149. TShape * ConvexShape_CreateTetrahedron( TVec3 a, TVec3 b, TVec3 c, TVec3 d ) {
  150.     TShape * shape = calloc( 1, sizeof( TShape ));
  151.     shape->convex = calloc( 1, sizeof( TConvexShape ));
  152.     shape->convex->count = 4;
  153.     shape->convex->points = malloc( shape->convex->count * sizeof( TVec3 ));
  154.     shape->convex->points[0] = a;
  155.     shape->convex->points[1] = b;
  156.     shape->convex->points[2] = c;
  157.     shape->convex->points[3] = d;
  158.     shape->position = Vec3_Set( 0,0,0 );
  159.     return shape;
  160. }
  161.  
  162. TShape * ConvexShape_CreateSphere( TVec3 position, float radius ) {
  163.     TShape * shape = calloc( 1, sizeof( TShape ));
  164.     shape->sphere = calloc( 1, sizeof( TSphereShape ));    
  165.     shape->position = position;
  166.     shape->sphere->radius = radius;
  167.     return shape;
  168. }
  169.  
  170. void ConvexShape_Delete( TShape * shape ) {
  171.     if( shape->convex ) {
  172.         free( shape->convex );
  173.     }
  174.     if( shape->sphere ) {
  175.         free( shape->sphere );
  176.     }
  177.     free( shape );
  178. }
  179.  
  180. TVec3 ConvexShape_GetFarthestPointInDirection( TShape * shape, TVec3 dir ) {
  181.     const float eps = 0.000001;
  182.     if( fabs( dir.x ) < eps && fabs( dir.y ) < eps && fabs( dir.z ) < eps ) {
  183.         printf( "GJK Warning: Zero direction passed!\n" );
  184.     }
  185.     dir = Vec3_Normalize( dir );
  186.     if( shape->convex ) {
  187.         TVec3 farthest;
  188.         float lastDot = -FLT_MAX;
  189.         for( int i = 0; i < shape->convex->count; i++ ) {
  190.             float dot = Vec3_Dot( dir, shape->convex->points[i] );
  191.             if( dot > lastDot ) {
  192.                 farthest = shape->convex->points[i];
  193.                 lastDot = dot;
  194.             }
  195.         }
  196.         farthest = Vec3_Add( farthest, shape->position );
  197.         return farthest;
  198.     }
  199.     if( shape->sphere ) {
  200.         return Vec3_Add( shape->position, Vec3_Scale( dir, shape->sphere->radius ));
  201.     }
  202.     if( shape->box ) {
  203.         TVec3 farthest;
  204.         float lastDot = -FLT_MAX;
  205.         for( int i = 0; i < 8; i++ ) {
  206.             float dot = Vec3_Dot( dir, shape->box->vertices[i] );
  207.             if( dot > lastDot ) {
  208.                 farthest = shape->box->vertices[i];
  209.                 lastDot = dot;
  210.             }
  211.         }
  212.         farthest = Vec3_Add( farthest, shape->position );
  213.         return farthest;
  214.     }
  215.     return Vec3_Set( 0, 0, 0 );
  216. }
  217.  
  218. TShape * BoxShape_Create( float size ) {
  219.     float hs = size / 2;
  220.     TShape * shape = calloc( 1, sizeof( TShape ));
  221.     shape->box = calloc( 1, sizeof( TBoxShape ));
  222.     shape->box->vertices[0] = Vec3_Set( -hs, -hs, -hs );
  223.     shape->box->vertices[1] = Vec3_Set( -hs, -hs,  hs );
  224.     shape->box->vertices[2] = Vec3_Set(  hs, -hs, -hs );
  225.     shape->box->vertices[3] = Vec3_Set(  hs, -hs,  hs );
  226.    
  227.     shape->box->vertices[4] = Vec3_Set( -hs,  hs, -hs );
  228.     shape->box->vertices[5] = Vec3_Set( -hs,  hs,  hs );
  229.     shape->box->vertices[6] = Vec3_Set(  hs,  hs, -hs );
  230.     shape->box->vertices[7] = Vec3_Set(  hs,  hs,  hs );
  231.     return shape;
  232. }
  233.  
  234. // ===========================
  235. // GJK ALGORITHM ROUTINE
  236. // ===========================
  237. TSupport GJK_GetSupport( TShape * shape1, TShape * shape2, TVec3 dir ) {
  238.     TSupport sup;
  239.     sup.supportA = ConvexShape_GetFarthestPointInDirection( shape1, dir );
  240.     sup.minkowskiDifPoint = Vec3_Sub( sup.supportA, ConvexShape_GetFarthestPointInDirection( shape2, Vec3_Negate( dir )));
  241.     return sup;
  242. }
  243.  
  244. bool GJK_ProcessLine( TSimplex * simplex, TVec3 * outDirection ) {
  245.     TVec3 a = simplex->points[1].minkowskiDifPoint;
  246.     TVec3 b = simplex->points[0].minkowskiDifPoint;
  247.     TVec3 ab = Vec3_Sub( b, a );
  248.     TVec3 aO = Vec3_Negate( a );
  249.    
  250.     if( Helper_SameDirection( ab, aO )) {
  251.         *outDirection = Vec3_Cross( Vec3_Cross( ab, aO ), ab );
  252.     } else {
  253.         Simplex_RemovePoint( simplex, 0 );
  254.         *outDirection = aO;
  255.     }
  256.     return false;
  257. }
  258.  
  259. bool GJK_ProcessTriangle( TSimplex * simplex, TVec3 * outDirection ) {
  260.     TVec3 a = simplex->points[2].minkowskiDifPoint;
  261.     TVec3 b = simplex->points[1].minkowskiDifPoint;
  262.     TVec3 c = simplex->points[0].minkowskiDifPoint;
  263.     TVec3 aO = Vec3_Negate( a );
  264.     TVec3 ab = Vec3_Sub( b, a );
  265.     TVec3 ac = Vec3_Sub( c, a );
  266.     TVec3 abc = Vec3_Cross( ab, ac );
  267.     TVec3 acNormal = Vec3_Cross( abc, ac );
  268.     TVec3 abNormal = Vec3_Cross( ab, abc );
  269.    
  270.     if( Helper_SameDirection( acNormal, aO )) {
  271.         if( Helper_SameDirection( ac, aO )) {
  272.             Simplex_RemovePoint( simplex, 1 );
  273.             *outDirection = Vec3_Cross( Vec3_Cross(ac, aO), ac );
  274.         } else {
  275.             if( Helper_SameDirection( ab, aO )) {
  276.                 Simplex_RemovePoint( simplex, 0 );
  277.                 *outDirection = Vec3_Cross( Vec3_Cross(ab, aO), ab);
  278.             } else {
  279.                 Simplex_RemovePoint( simplex, 1 );
  280.                 Simplex_RemovePoint( simplex, 0 );
  281.                 *outDirection = aO;
  282.             }
  283.         }
  284.     } else {
  285.         if( Helper_SameDirection( abNormal, aO )) {
  286.             if( Helper_SameDirection( ab, aO )) {
  287.                 Simplex_RemovePoint( simplex, 0 );
  288.                 *outDirection = Vec3_Cross( Vec3_Cross(ab, aO), ab);
  289.             } else {
  290.                 Simplex_RemovePoint( simplex, 1 );
  291.                 Simplex_RemovePoint( simplex, 0 );
  292.                 *outDirection = aO;
  293.             }
  294.         } else {
  295.             if( Helper_SameDirection( abc, aO )) {
  296.                 *outDirection = Vec3_Cross(Vec3_Cross(abc, aO), abc);
  297.             } else {
  298.                 *outDirection = Vec3_Cross(Vec3_Cross( Vec3_Negate( abc ), aO), Vec3_Negate( abc ) );
  299.             }
  300.         }
  301.     }
  302.    
  303.     return false;
  304. }
  305.  
  306. bool GJK_ProcessTetrahedron( TSimplex * simplex, TVec3 * outDirection ) {
  307.     TVec3 a = simplex->points[3].minkowskiDifPoint;
  308.     TVec3 b = simplex->points[2].minkowskiDifPoint;
  309.     TVec3 c = simplex->points[1].minkowskiDifPoint;
  310.     TVec3 d = simplex->points[0].minkowskiDifPoint;
  311.    
  312.     TVec3 ac = Vec3_Sub( c, a );
  313.     TVec3 ab = Vec3_Sub( b, a );
  314.     TVec3 ad = Vec3_Sub( d, a );
  315.    
  316.     TVec3 acd = Vec3_Cross( ad, ac );
  317.     TVec3 abd = Vec3_Cross( ab, ad );
  318.     TVec3 abc = Vec3_Cross( ac, ab );
  319.    
  320.     TVec3 aO = Vec3_Negate( a );
  321.    
  322.     if( Helper_SameDirection( abc, aO )) {
  323.         if( Helper_SameDirection( Vec3_Cross( abc, ac ), aO )) {
  324.             Simplex_RemovePoint( simplex, 2 );
  325.             Simplex_RemovePoint( simplex, 0 );
  326.             *outDirection = Vec3_Cross( Vec3_Cross( ac, aO ), ac );
  327.         } else if( Helper_SameDirection( Vec3_Cross( ab, abc ), aO )) {
  328.             Simplex_RemovePoint( simplex, 1 );
  329.             Simplex_RemovePoint( simplex, 0 );
  330.             *outDirection = Vec3_Cross( Vec3_Cross( ab, aO ), ab );
  331.         } else {
  332.             Simplex_RemovePoint( simplex, 0 );
  333.             *outDirection = abc;
  334.         }
  335.     } else if( Helper_SameDirection( acd, aO )) {
  336.         if( Helper_SameDirection( Vec3_Cross( acd, ad ), aO )) {
  337.             Simplex_RemovePoint( simplex, 2 );
  338.             Simplex_RemovePoint( simplex, 1 );
  339.             *outDirection = Vec3_Cross( Vec3_Cross( ad, aO ), ad );
  340.         } else if ( Helper_SameDirection( Vec3_Cross( ac, acd ), aO )) {
  341.             Simplex_RemovePoint( simplex, 2 );
  342.             Simplex_RemovePoint( simplex, 0 );
  343.             *outDirection = Vec3_Cross( Vec3_Cross( ac, aO ), ac );
  344.         } else {
  345.            Simplex_RemovePoint( simplex, 2 );
  346.             *outDirection = acd;
  347.         }
  348.     } else if( Helper_SameDirection( abd, aO )) {
  349.         if( Helper_SameDirection( Vec3_Cross( abd, ab ), aO )) {
  350.             Simplex_RemovePoint( simplex, 1 );
  351.             Simplex_RemovePoint( simplex, 0 );
  352.             *outDirection = Vec3_Cross( Vec3_Cross( ab, aO ), ab );
  353.         } else if( Helper_SameDirection( Vec3_Cross( ad, abd ), aO )) {
  354.             Simplex_RemovePoint( simplex, 2 );
  355.             Simplex_RemovePoint( simplex, 1 );
  356.             *outDirection = Vec3_Cross( Vec3_Cross( ad, aO ), ad );
  357.         } else {
  358.             Simplex_RemovePoint( simplex, 1 );
  359.             *outDirection = abd;
  360.         }
  361.     } else {
  362.         return true;
  363.     }
  364.    
  365.     return false;
  366. }
  367.  
  368. bool GJK_ProcessSimplex( TSimplex * simplex, TVec3 * outDirection ) {
  369.     if( simplex->size == 2 ) {
  370.         return GJK_ProcessLine( simplex, outDirection );
  371.     } else if ( simplex->size == 3 ) {
  372.         return GJK_ProcessTriangle( simplex, outDirection );
  373.     } else {
  374.         return GJK_ProcessTetrahedron( simplex, outDirection );
  375.     }
  376. }
  377.  
  378. bool GJK_IsIntersects( TShape * shape1, TShape * shape2, TSimplex * finalSimplex ) {
  379.     TVec3 dir = Vec3_Set( 1, 1, 1 );
  380.    
  381.     TSimplex simplex = { 0 };
  382.     Simplex_AddPoint( &simplex, GJK_GetSupport( shape1, shape2, dir ));
  383.    
  384.     dir = Vec3_Negate( dir );
  385.    
  386.     int convergenceLimit = 500;
  387.     for( int i = 0; i < convergenceLimit; i++ ) {
  388.         TSupport lastSupport = GJK_GetSupport( shape1, shape2, dir );              
  389.         if( Helper_SameDirection( dir, lastSupport.minkowskiDifPoint )) {
  390.             Simplex_AddPoint( &simplex, lastSupport );            
  391.             if( GJK_ProcessSimplex( &simplex, &dir )) {
  392.                 printf( "GJK: Intersection! %d iteration(s)!\n", i );
  393.                 if( finalSimplex ) {
  394.                     *finalSimplex = simplex;
  395.                 }
  396.                 return true;
  397.             }            
  398.         } else {
  399.             printf( "GJK: No intersection! %d iteration(s)!\n", i );            
  400.             return false;
  401.         }
  402.     }
  403.    
  404.     printf( "GJK: No intersection! Convergence limit has reached!\n" );
  405.     return false;
  406. }
  407.  
  408. // ===========================
  409. // EPA ALGORITHM ROUTINE
  410. // ===========================
  411. void Polytope_SetFromSimplex( TEPAPolytope * polytope, TSimplex * simplex ) {
  412.     polytope->vertexCount = 4;
  413.     polytope->vertices = calloc( polytope->vertexCount, sizeof( TSupport ));
  414.     for( int i = 0; i < polytope->vertexCount; i++ ) {
  415.         polytope->vertices[i] = simplex->points[i];
  416.     }
  417.     polytope->faceCount = 4;
  418.     polytope->faces = calloc( polytope->faceCount, sizeof( TEPAFace ));
  419.     polytope->faces[0] = (TEPAFace) { 0, 1, 2 };
  420.     polytope->faces[1] = (TEPAFace) { 0, 3, 1 };
  421.     polytope->faces[2] = (TEPAFace) { 0, 2, 3 };
  422.     polytope->faces[3] = (TEPAFace) { 2, 1, 3 };
  423. }
  424.  
  425. void Polytope_Free( TEPAPolytope * polytope ) {
  426.     free( polytope->faces );
  427.     free( polytope->vertices );
  428.     polytope->faceCount = -1;
  429.     polytope->vertexCount = -1;
  430. }
  431.  
  432. void EdgeList_Create( TEdgeList * edgeList, TEPAPolytope * polytope ) {
  433.     edgeList->count = polytope->faceCount * 3;
  434.     edgeList->edges = calloc( edgeList->count, sizeof( TEdge ));
  435. }
  436.  
  437. void EdgeList_Free( TEdgeList * edgeList ) {
  438.     free( edgeList->edges );
  439.     edgeList->count = 0;
  440. }
  441.  
  442. void EdgeList_Fill( TEdgeList * edgeList, TEPAPolytope * polytope ) {
  443.     for( int i = 0, j = 0; i < polytope->faceCount; i++, j += 3 ) {
  444.         edgeList->edges[j+0] = (TEdge) { .a = polytope->faces[i].a, .b = polytope->faces[i].b, .free = true };
  445.         edgeList->edges[j+1] = (TEdge) { .a = polytope->faces[i].b, .b = polytope->faces[i].c, .free = true };
  446.         edgeList->edges[j+2] = (TEdge) { .a = polytope->faces[i].c, .b = polytope->faces[i].a, .free = true };
  447.        // printf( "%d %d\n%d %d\n%d %d\n", edgeList->edges[j+0].a, edgeList->edges[j+0].b, edgeList->edges[j+1].a, edgeList->edges[j+1].b, edgeList->edges[j+2].a, edgeList->edges[j+2].b );
  448.     }
  449. }
  450.  
  451. void EdgeList_MarkHoles( TEdgeList * edgeList ) {
  452.     for( int i = 0; i < edgeList->count; i++ ) {
  453.         for( int j = 0; j < edgeList->count; j++ ) {
  454.             if( edgeList->edges[i].free && edgeList->edges[j].free ) {
  455.                 if( edgeList->edges[j].a == edgeList->edges[i].b && edgeList->edges[j].b == edgeList->edges[i].a ) {
  456.                     edgeList->edges[i].free = false;
  457.                     edgeList->edges[j].free = false;
  458.                 }
  459.             }
  460.         }
  461.     }
  462.     edgeList->freeCount = 0;
  463.     for( int i = 0; i < edgeList->count; i++ ) {
  464.         if( edgeList->edges[i].free ) {
  465.             edgeList->freeCount++;
  466.         }
  467.     }
  468.     //printf( "Free count: %d\n", edgeList->freeCount );
  469. }
  470.  
  471. int Polytope_ReserveFaces( TEPAPolytope * polytope, int faceCount ) {
  472.     int last = polytope->faceCount;
  473.     polytope->faceCount += faceCount;
  474.     polytope->faces = realloc( polytope->faces, polytope->faceCount * sizeof( TEPAFace ));
  475.     return last;
  476. }
  477.  
  478. void Polytope_PatchHoles( TEPAPolytope * polytope, TEdgeList * edgeList, int newPointIndex ) {
  479.     int lastFree = Polytope_ReserveFaces( polytope, edgeList->freeCount );
  480.     for( int i = 0; i < edgeList->count; i++ ) {
  481.         if( edgeList->edges[i].free ) {
  482.             polytope->faces[lastFree] = (TEPAFace) { .a = newPointIndex, .b = edgeList->edges[i].b, .c = edgeList->edges[i].a };
  483.             lastFree++;
  484.         }
  485.     }
  486. }
  487.  
  488. void Polytope_RemoveFace( TEPAPolytope * polytope, int n ) {
  489.     if( n == 0 ) {
  490.         polytope->faceCount--;
  491.         memmove( polytope->faces, polytope->faces + 1, sizeof( TEPAFace ) * polytope->faceCount );
  492.     } else if( n == polytope->faceCount - 1 ) {
  493.         // keep last face in array but reduce face count
  494.         polytope->faceCount--;
  495.     } else {
  496.         memmove( polytope->faces + n, polytope->faces + n + 1, sizeof( TEPAFace ) * ( polytope->faceCount - n ));
  497.         polytope->faceCount--;
  498.     }
  499. }
  500.  
  501. int Polytope_AddVertex( TEPAPolytope * polytope, TSupport newSupport ) {
  502.     int last = polytope->vertexCount;
  503.     polytope->vertexCount++;
  504.     polytope->vertices = realloc( polytope->vertices, polytope->vertexCount * sizeof( TSupport ));
  505.     polytope->vertices[last] = newSupport;
  506.     return last;
  507. }
  508.  
  509. TVec3 Math_ProjectOriginOntoPlane( TVec3 planePoint, TVec3 planeNormal ) {
  510.     float t = -Vec3_Dot( planePoint, planeNormal );
  511.     return Vec3_Negate( Vec3_Scale( planeNormal, t ));
  512. }
  513.  
  514. float Math_DistanceToOrigin( TVec3 normal, TVec3 point ) {
  515.     return Vec3_Dot( normal, point );
  516. }
  517.  
  518. void Math_GetBarycentricCoords( TVec3 p, TVec3 a, TVec3 b, TVec3 c, float *u,float *v,float *w ) {
  519.      TVec3 v0 = Vec3_Sub( b, a );
  520.      TVec3 v1 = Vec3_Sub( c, a );
  521.      TVec3 v2 = Vec3_Sub( p, a );
  522.      float d00 = Vec3_Dot( v0, v0 );
  523.      float d01 = Vec3_Dot( v0, v1 );
  524.      float d11 = Vec3_Dot( v1, v1 );
  525.      float d20 = Vec3_Dot( v2, v0 );
  526.      float d21 = Vec3_Dot( v2, v1 );
  527.      float denom = d00 * d11 - d01 * d01;
  528.      *v = (d11 * d20 - d01 * d21) / denom;
  529.      *w = (d00 * d21 - d01 * d20) / denom;
  530.      *u = 1.0f - *v - *w;
  531. }
  532.  
  533. bool Polytope_IsFaceSeenFromPoint( TEPAPolytope * polytope, int a, int b, int c, TVec3 point ) {
  534.     TVec3 va = polytope->vertices[ a ].minkowskiDifPoint;
  535.     TVec3 vb = polytope->vertices[ b ].minkowskiDifPoint;
  536.     TVec3 vc = polytope->vertices[ c ].minkowskiDifPoint;
  537.     TVec3 normal = Vec3_Cross( Vec3_Sub( vb, va ), Vec3_Sub( vc, va ));
  538.     return Vec3_Dot( normal, Vec3_Sub( point, va )) > 0;
  539. }
  540.  
  541. int Polytope_GetFirstFaceSeenFromPoint( TEPAPolytope * polytope, TVec3 point ) {
  542.     for( int i = 0; i < polytope->faceCount; i++ ) {
  543.         if( Polytope_IsFaceSeenFromPoint( polytope, polytope->faces[i].a, polytope->faces[i].b, polytope->faces[i].c, point )) {
  544.             return i;
  545.         }
  546.     }
  547.     return -1;
  548. }
  549.  
  550. bool Polytope_IsFaceDegenerated( TEPAPolytope * polytope, int n ) {
  551.     TVec3 a = polytope->vertices[ polytope->faces[ n ].a ].minkowskiDifPoint;
  552.     TVec3 b = polytope->vertices[ polytope->faces[ n ].b ].minkowskiDifPoint;
  553.     TVec3 c = polytope->vertices[ polytope->faces[ n ].c ].minkowskiDifPoint;
  554.  
  555.     TVec3 normal = Vec3_Cross( Vec3_Sub( b, a ), Vec3_Sub( c, a ) );
  556.  
  557.     // degenerated triangle, ignore
  558.     return Vec3_SqrLength( normal ) < 0.00001;
  559. }
  560.  
  561. void Polytope_RemoveDegeneratedFaces( TEPAPolytope * polytope ) {
  562.     while( true ) {
  563.         int n = -1;
  564.         for( int i = 0; i < polytope->faceCount; i++ ) {
  565.             if( Polytope_IsFaceDegenerated( polytope, i )) {
  566.                 Polytope_RemoveFace( polytope, i );
  567.                 n = i;
  568.                 break;
  569.             }
  570.         }
  571.         if( n < 0 ) {
  572.             break;
  573.         }
  574.     }
  575. }
  576.  
  577. TEPATriangle Polytope_GetClosestTriangleToOrigin( TEPAPolytope * polytope ) {
  578.     int closest;
  579.     float closestDistance = FLT_MAX;
  580.     TVec3 closestNormal;
  581.     for( int i = 0; i < polytope->faceCount; i++ ) {
  582.         TVec3 a = polytope->vertices[ polytope->faces[ i ].a ].minkowskiDifPoint;
  583.         TVec3 b = polytope->vertices[ polytope->faces[ i ].b ].minkowskiDifPoint;
  584.         TVec3 c = polytope->vertices[ polytope->faces[ i ].c ].minkowskiDifPoint;
  585.  
  586.         TVec3 normal = Vec3_Cross( Vec3_Sub( b, a ), Vec3_Sub( c, a ) );
  587.  
  588.         // degenerated triangle, ignore
  589.         if( Vec3_SqrLength( normal ) < 0.00001 ) {
  590.             continue;
  591.         }
  592.         float d = Math_DistanceToOrigin( normal, a );
  593.         if( d < closestDistance ) {
  594.             closestDistance = d;
  595.             closest = i;
  596.             closestNormal = normal;
  597.         }        
  598.     }
  599.     return (TEPATriangle) { .a = polytope->vertices[ polytope->faces[ closest ].a ], .b = polytope->vertices[ polytope->faces[ closest ].b ],
  600.                             .c = polytope->vertices[ polytope->faces[ closest ].c ], .normal = closestNormal, .dist = closestDistance, .numInPolytope = closest };
  601. }
  602.  
  603. bool EPA_ComputeContacts( TEPAPolytope * polytope, TShape * shape1, TShape * shape2, TEPAContact * outContact ) {
  604.     const int convergenceLimit = 500;
  605.     for( int i = 0; i < convergenceLimit; i++ ) {      
  606.         Polytope_RemoveDegeneratedFaces( polytope );  
  607.         TEPATriangle closestTriangle = Polytope_GetClosestTriangleToOrigin( polytope );
  608.         TSupport p = GJK_GetSupport( shape1, shape2, closestTriangle.normal );
  609.         float d = Vec3_Dot( p.minkowskiDifPoint, closestTriangle.normal );
  610.         if( d - closestTriangle.dist < 0.00001 ) {      
  611.             if( d < 0.00001 ) {
  612.                 return false;
  613.             }      
  614.             TVec3 proj = Math_ProjectOriginOntoPlane( closestTriangle.a.minkowskiDifPoint, closestTriangle.normal );
  615.             float u, v, w;
  616.             Math_GetBarycentricCoords( proj, closestTriangle.a.minkowskiDifPoint, closestTriangle.b.minkowskiDifPoint, closestTriangle.c.minkowskiDifPoint, &u, &v, &w );
  617.             TVec3 a = Vec3_Scale( closestTriangle.a.supportA, u );
  618.             TVec3 b = Vec3_Scale( closestTriangle.b.supportA, v );
  619.             TVec3 c = Vec3_Scale( closestTriangle.c.supportA, w );
  620.             TVec3 collPoint = Vec3_Add( Vec3_Add( a, b ), c );
  621.             closestTriangle.normal = Vec3_Normalize( Vec3_Negate( closestTriangle.normal ));
  622.             outContact->normal = closestTriangle.normal;
  623.             outContact->penetrationDepth = d;
  624.  
  625.             printf( "EPA: Done in %d iteration(s)!\nClosest: %.3f, %.3f, %.3f\nNormal: %.3f, %.3f, %.3f\nPenetration depth: %f\n", i, collPoint.x, collPoint.y, collPoint.z, closestTriangle.normal.x, closestTriangle.normal.y, closestTriangle.normal.z, d );
  626.             return true;
  627.         } else {                
  628.             TEdgeList edgeList;            
  629.             while( true ) {
  630.                 int seenFace = Polytope_GetFirstFaceSeenFromPoint( polytope, p.minkowskiDifPoint );
  631.                 if( seenFace < 0 ) {
  632.                     break;
  633.                 } else {
  634.                     Polytope_RemoveFace( polytope, seenFace );
  635.                 }
  636.             }        
  637.             EdgeList_Create( &edgeList, polytope );    
  638.             EdgeList_Fill( &edgeList, polytope );
  639.             EdgeList_MarkHoles( &edgeList );
  640.             Polytope_PatchHoles( polytope, &edgeList, Polytope_AddVertex( polytope, p ) );
  641.             EdgeList_Free( &edgeList );            
  642.         }
  643.     }
  644.     printf( "EPA: Convergence limit has reached!\n" );
  645.     return false;
  646. }
  647.  
  648. // ===========================
  649. // TRIANGLE MESH SHAPE ROUTINE
  650. // ===========================
  651. TTriangleMeshShape * TriangleMesh_CreatePlane() {
  652.     TTriangleMeshShape * triMesh = calloc( 1, sizeof( TTriangleMeshShape ));
  653.    
  654.     return triMesh;
  655. }
  656.  
  657. // ===========================
  658. // BODY ROUTINE
  659. // ===========================
  660. TBody * Body_Create( TShape * shape ) {
  661.     TBody * body = calloc( 1, sizeof( TBody ));
  662.     body->position = shape->position;
  663.     body->shape = shape;
  664.     return body;
  665. }
  666.  
  667. void Body_SolveCollision( TBody * body1, TBody * body2 ) {
  668.     if( body1->shape->triMesh ) {
  669.         TBody * temp = body1;
  670.         body1 = body2;
  671.         body2 = temp;
  672.     }
  673.    
  674.     currentShape1 = body1->shape;
  675.     currentShape2 = body2->shape;
  676.    
  677.     TSimplex finalSimplex;
  678.     TEPAContact contact;
  679.    
  680.     body1->shape->position = body1->position;
  681.     body2->shape->position = body2->position;
  682.    
  683.     while( GJK_IsIntersects( body1->shape, body2->shape, &finalSimplex )) {
  684.         if( currentPolytope ) {
  685.             Polytope_Free( currentPolytope );
  686.             free( currentPolytope );
  687.         }
  688.         currentPolytope = calloc( 1, sizeof( TEPAPolytope ));
  689.         Polytope_SetFromSimplex( currentPolytope, &finalSimplex );        
  690.         if( EPA_ComputeContacts( currentPolytope, body1->shape, body2->shape, &contact )) {
  691.             body1->position = Vec3_Add( body1->position, Vec3_Scale( contact.normal, contact.penetrationDepth / 2  ));
  692.         } else {
  693.             break;
  694.         }    
  695.         body1->shape->position = body1->position;
  696.         body2->shape->position = body2->position;    
  697.     }
  698. }
  699.  
  700. // ===========================
  701. // RENDERING ROUTINE
  702. // ===========================
  703. #include <windows.h>
  704. #include "glut.h"
  705. #include "gl/gl.h"
  706.  
  707. #define WINDOW_SIZE 800
  708.  
  709. void Renderer_DrawShape( TShape * shape ) {
  710.     glPolygonMode( GL_FRONT_AND_BACK, GL_LINE );
  711.    
  712.     if( shape->convex ) {
  713.         if( shape->convex->count == 3 ) { // triangle        
  714.             glPushMatrix();
  715.            
  716.             glTranslatef( shape->position.x, shape->position.y, shape->position.z );
  717.            
  718.             TVec3 a = shape->convex->points[0];
  719.             TVec3 b = shape->convex->points[1];
  720.             TVec3 c = shape->convex->points[2];
  721.            
  722.             glBegin(GL_TRIANGLES);
  723.             glColor3ub( 0, 0, 255 );
  724.             glVertex3f( a.x, a.y, a.z );
  725.             glVertex3f( b.x, b.y, b.z );
  726.             glVertex3f( c.x, c.y, c.z );    
  727.            
  728.             glEnd();
  729.            
  730.             glPopMatrix();
  731.         }
  732.        
  733.         if( shape->convex->count == 4 ) { // tetrahedron        
  734.             glPushMatrix();
  735.            
  736.             glTranslatef( shape->position.x, shape->position.y, shape->position.z );
  737.            
  738.             TVec3 a = shape->convex->points[0];
  739.             TVec3 b = shape->convex->points[1];
  740.             TVec3 c = shape->convex->points[2];
  741.             TVec3 d = shape->convex->points[3];
  742.            
  743.             glBegin(GL_TRIANGLES);
  744.             glColor3ub( 255, 0, 0 );
  745.             glVertex3f( a.x, a.y, a.z );
  746.             glVertex3f( b.x, b.y, b.z );
  747.             glVertex3f( c.x, c.y, c.z );
  748.            
  749.             glColor3ub( 0, 255, 0 );
  750.             glVertex3f( a.x, a.y, a.z );
  751.             glVertex3f( d.x, d.y, d.z );
  752.             glVertex3f( b.x, b.y, b.z );
  753.            
  754.             glColor3ub( 0, 0, 255 );
  755.             glVertex3f( a.x, a.y, a.z );
  756.             glVertex3f( c.x, c.y, c.z );
  757.             glVertex3f( d.x, d.y, d.z );            
  758.            
  759.             glColor3ub( 255, 255, 0 );
  760.             glVertex3f( c.x, c.y, c.z );
  761.             glVertex3f( b.x, b.y, b.z );
  762.             glVertex3f( d.x, d.y, d.z );
  763.            
  764.             glEnd();
  765.            
  766.             glPopMatrix();
  767.         }
  768.     } else if( shape->sphere ) {
  769.         glPushMatrix();
  770.        
  771.         glTranslatef( shape->position.x, shape->position.y, shape->position.z );        
  772.         glutSolidSphere( shape->sphere->radius, 32, 32 );        
  773.         glPopMatrix();
  774.     } else if( shape->box ) {
  775.         glPushMatrix();
  776.        
  777.         glTranslatef( shape->position.x, shape->position.y, shape->position.z );        
  778.         glutSolidCube( 1 );        
  779.         glPopMatrix();
  780.     }
  781. }
  782.  
  783. void Renderer_Display() {
  784.     static float a = 0;
  785.     glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
  786.  
  787.     glMatrixMode(GL_MODELVIEW);
  788.     glLoadIdentity();
  789.     gluLookAt( 0, 0, 2.2, 0, 0, 0, 0, 1, 0 );
  790.     glRotatef( a, 0, 1, 0 );
  791.     a+=0.725;
  792.    
  793.     if( currentPolytope ) {
  794.         glPolygonMode( GL_FRONT_AND_BACK, GL_LINE );
  795.        
  796.         for( int i = 0; i < currentPolytope->faceCount; i++ ) {
  797.             int ia = currentPolytope->faces[i].a;
  798.             int ib = currentPolytope->faces[i].b;
  799.             int ic = currentPolytope->faces[i].c;
  800.      
  801.             TVec3 a = currentPolytope->vertices[ ia ].minkowskiDifPoint;
  802.             TVec3 b = currentPolytope->vertices[ ib ].minkowskiDifPoint;
  803.             TVec3 c = currentPolytope->vertices[ ic ].minkowskiDifPoint;
  804.            
  805.             TVec3 normal = Vec3_Normalize( Vec3_Cross( Vec3_Sub( b,a ), Vec3_Sub( c,a )));
  806.            
  807.             glBegin(GL_TRIANGLES);
  808.             //glColor3ub( i * 8 + 50, i * 8 + 50, i * 8 + 50 );
  809.             glVertex3f( a.x, a.y, a.z );
  810.             glVertex3f( b.x, b.y, b.z );
  811.             glVertex3f( c.x, c.y, c.z );
  812.             glEnd();
  813.            
  814.             glBegin(GL_LINES);
  815.             glColor3ub( 255, 0, 255 );
  816.             glVertex3f( a.x * 0.333f + b.x * 0.333f + c.x * 0.333f, a.y * 0.333f + b.y * 0.333f + c.y * 0.333f, a.z * 0.333f + b.z * 0.333f + c.z * 0.333f );
  817.             glVertex3f( a.x * 0.333f + b.x * 0.333f + c.x * 0.333f + normal.x, a.y * 0.333f + b.y * 0.333f + c.y * 0.333f + normal.y, a.z * 0.333f + b.z * 0.333f + c.z * 0.333f + normal.z );
  818.             glEnd();
  819.         }
  820.     }
  821.    glColor3ub( 255, 0, 0 );
  822.     Renderer_DrawShape( currentShape1 );
  823.     glColor3ub( 255, 255, 0 );
  824.     Renderer_DrawShape( currentShape2 );
  825.    
  826.     glutSwapBuffers();
  827.     glutPostRedisplay();
  828. }
  829.  
  830. void Renderer_Init() {
  831.     glClearColor(0.000, 0.110, 0.392, 0.0);
  832.  
  833.     glMatrixMode(GL_PROJECTION);
  834.     glLoadIdentity();
  835.     gluPerspective( 80, 1, 0.01, 1024 );
  836.    
  837.  
  838.    
  839.     glClearDepth( 1.0f );
  840.     glEnable( GL_DEPTH_TEST );
  841.     glDepthFunc( GL_LEQUAL );
  842.     glHint( GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST );
  843.     glEnable( GL_TEXTURE_2D );
  844.     glShadeModel( GL_SMOOTH );
  845.    
  846.     glEnable( GL_CULL_FACE );
  847.    
  848.     glDisable( GL_STENCIL_TEST );
  849.     glCullFace( GL_BACK );    
  850.     glEnable( GL_ALPHA_TEST );
  851.     glAlphaFunc( GL_GREATER, 0.025f );
  852.  
  853.    
  854.     //currentShape1 = ConvexShape_CreateTetrahedron( Vec3_Set( -1, .5, 0 ), Vec3_Set( -1, 1.5, 0 ), Vec3_Set( 0.1, 0.5, 0 ), Vec3_Set( -1, 0.5, 1 ));
  855.     //currentShape1 = ConvexShape_CreateTetrahedron( Vec3_Set( 0, 0, 0 ), Vec3_Set( 0, 1, 0 ), Vec3_Set( 1, 0, 0 ), Vec3_Set( 0, 0, 1 ));
  856.     //currentShape1 = ConvexShape_CreateSphere( Vec3_Set( 0,0,0 ), 0.5 );
  857.     //currentShape2 = ConvexShape_CreateSphere( Vec3_Set( 0.5,0,0.0), 0.8 );
  858.     //currentShape1 = ConvexShape_CreateTriangle( Vec3_Set( 0, 0, 0.5 ), Vec3_Set( 0.5, 1, 0.5 ), Vec3_Set( 0.5, 0, 0 ));
  859.     //currentShape2 = ConvexShape_CreateTriangle( Vec3_Set( 0, 0.1, 0 ), Vec3_Set( 0, 0.1, 1 ), Vec3_Set( 1, 0.1, 0 ));
  860.     currentShape1 = BoxShape_Create( 1 );
  861.     currentShape2 = BoxShape_Create( 1 );
  862.  
  863.     TBody * body1 = Body_Create( currentShape1 );
  864.     body1->position = Vec3_Set( 0.1, 0, 0 );
  865.     TBody * body2 = Body_Create( currentShape2 );
  866.     Body_SolveCollision( body1, body2 );
  867. }
  868.  
  869. // ===========================
  870. // TESTS
  871. // ===========================
  872. int main(int argc, char **argv) {
  873.     glutInit(&argc, argv);
  874.     glutInitDisplayMode( GLUT_DEPTH | GLUT_DOUBLE | GLUT_RGBA );
  875.     glutInitWindowSize( 800, 800 );
  876.     glutInitWindowPosition(0, 0);
  877.     glutCreateWindow("Test");
  878.     glutDisplayFunc(Renderer_Display);
  879.     Renderer_Init();
  880.  
  881.     glutMainLoop();
  882. }
Advertisement
Add Comment
Please, Sign In to add comment