mrDIMAS

GJK

Oct 1st, 2015
341
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 10.57 KB | None | 0 0
  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <float.h>
  4. #include <stdbool.h>
  5.  
  6. #include "vector3.h"
  7.  
  8. typedef struct TSimplex {
  9.     TVec3 points[4];
  10.     int size;
  11. } TSimplex;
  12.  
  13. typedef enum EShapeType {
  14.     CS_SPHERE,
  15.     CS_CONVEX,
  16. } EShapeType;
  17.  
  18. typedef struct TConvexShape {
  19.     TVec3 * points;
  20.     int count;
  21.     int type;
  22.     float radius; // for sphere
  23. } TConvexShape;
  24.  
  25. // ===========================
  26. // HELPERS
  27. // ===========================
  28. bool Helper_SameDirection( TVec3 a, TVec3 b ) {
  29.     return Vec3_Dot( a, b ) > 0;
  30. }
  31.  
  32. // ===========================
  33. // SIMPLEX ROUTINE
  34. // ===========================
  35. void Simplex_RemovePoint( TSimplex * s, int num ) {
  36.     if( s->size > 0 ) {
  37.         if( num == 0 ) {
  38.             s->points[0] = s->points[1];
  39.             s->points[1] = s->points[2];
  40.             s->points[2] = s->points[3];
  41.         }
  42.         if( num == 1 ) {
  43.             s->points[1] = s->points[2];
  44.             s->points[2] = s->points[3];
  45.         }
  46.         if( num == 2 ) {
  47.             s->points[2] = s->points[3];
  48.         }
  49.         s->size--;
  50.     }
  51. }
  52.  
  53. void Simplex_AddPoint( TSimplex * s, TVec3 p ) {
  54.     if( s->size < 3 ) {
  55.         s->points[ s->size ] = p;
  56.         s->size++;
  57.     }
  58. }
  59.  
  60. // ===========================
  61. // CONVEX SHAPE ROUTINE
  62. // ===========================
  63. void ConvexShape_CreateTriangle( TConvexShape * shape, TVec3 a, TVec3 b, TVec3 c ) {
  64.     shape->count = 3;
  65.     shape->points = malloc( shape->count * sizeof( TVec3 ));
  66.     shape->points[0] = a;
  67.     shape->points[1] = b;
  68.     shape->points[2] = c;
  69.     shape->type = CS_CONVEX;
  70.     shape->radius = 0;
  71. }
  72.  
  73. void ConvexShape_CreateTetrahedron( TConvexShape * shape, TVec3 a, TVec3 b, TVec3 c, TVec3 d ) {
  74.     shape->count = 4;
  75.     shape->points = malloc( shape->count * sizeof( TVec3 ));
  76.     shape->points[0] = a;
  77.     shape->points[1] = b;
  78.     shape->points[2] = c;
  79.     shape->points[3] = d;
  80.     shape->type = CS_CONVEX;
  81.     shape->radius = 0;
  82. }
  83.  
  84. void ConvexShape_CreateSphere( TConvexShape * shape, TVec3 position, float radius ) {
  85.     shape->count = 1;
  86.     shape->points = malloc( shape->count * sizeof( TVec3 ));
  87.     shape->points[ 0 ] = position;
  88.     shape->type = CS_SPHERE;
  89.     shape->radius = radius;
  90. }
  91.  
  92.  
  93. TVec3 ConvexShape_GetFarthestPointInDirection( TConvexShape * shape, TVec3 dir ) {
  94.     if( shape->type == CS_CONVEX ) {
  95.         TVec3 farthest;
  96.         float lastDot = -FLT_MAX;
  97.         for( int i = 0; i < shape->count; i++ ) {
  98.             float dot = Vec3_Dot( dir, shape->points[i] );
  99.             if( dot > lastDot ) {
  100.                 farthest = shape->points[i];
  101.                 lastDot = dot;
  102.             }
  103.         }
  104.         return farthest;
  105.     } else {
  106.         if( fabs( dir.x ) < 0.000001 &&
  107.             fabs( dir.y ) < 0.000001 &&
  108.             fabs( dir.z ) < 0.000001 ) {
  109.             printf( "Warn! Zero dir passed!\n" );
  110.         }
  111.         TVec3 dn = Vec3_Normalize( dir );
  112.        
  113.         return Vec3_Add( shape->points[0], Vec3_Scale( dn, shape->radius ));
  114.     }
  115. }
  116.  
  117. // ===========================
  118. // GJK ALGORITHM ROUTINE
  119. // ===========================
  120. TVec3 GJK_GetSupport( TConvexShape * shape1, TConvexShape * shape2, TVec3 dir ) {
  121.     return Vec3_Sub( ConvexShape_GetFarthestPointInDirection( shape1, dir ), ConvexShape_GetFarthestPointInDirection( shape2, Vec3_Negate( dir )));
  122. }
  123.  
  124. bool GJK_ProcessLine( TSimplex * simplex, TVec3 * outDirection ) {
  125.     TVec3 a = simplex->points[1];
  126.     TVec3 b = simplex->points[0];
  127.     TVec3 ab = Vec3_Sub( b, a );
  128.     TVec3 aO = Vec3_Negate( a );
  129.    
  130.     if( Helper_SameDirection( ab, aO )) {
  131.         *outDirection = Vec3_Cross( Vec3_Cross( ab, aO ), ab );
  132.     } else {
  133.         Simplex_RemovePoint( simplex, 0 );
  134.         *outDirection = aO;
  135.     }
  136.     return false;
  137. }
  138.  
  139. bool GJK_ProcessTriangle( TSimplex * simplex, TVec3 * outDirection ) {
  140.     TVec3 a = simplex->points[2];
  141.     TVec3 b = simplex->points[1];
  142.     TVec3 c = simplex->points[0];
  143.     TVec3 aO = Vec3_Negate( a );
  144.     TVec3 ab = Vec3_Sub( b, a );
  145.     TVec3 ac = Vec3_Sub( c, a );
  146.     TVec3 abPerp = Vec3_Cross( Vec3_Cross( ac, ab ), ab );
  147.     TVec3 acPerp = Vec3_Cross( Vec3_Cross( ab, ac ), ac );
  148.     if( Helper_SameDirection( abPerp, aO )) {
  149.         Simplex_RemovePoint( simplex, 0 );
  150.         *outDirection = abPerp;
  151.     } else {
  152.         if( Helper_SameDirection( acPerp, aO )) {
  153.             Simplex_RemovePoint( simplex, 1 );
  154.             *outDirection = acPerp;
  155.         } else {
  156.             return true;
  157.         }
  158.     }
  159.     return false;
  160. }
  161.  
  162. bool GJK_ProcessTetrahedron( TSimplex * simplex, TVec3 * outDirection ) {
  163.     TVec3 a = simplex->points[3];
  164.     TVec3 b = simplex->points[2];
  165.     TVec3 c = simplex->points[1];
  166.     TVec3 d = simplex->points[0];
  167.    
  168.     TVec3 ac = Vec3_Sub( c, a );
  169.     TVec3 ab = Vec3_Sub( b, a );
  170.     TVec3 ad = Vec3_Sub( d, a );
  171.    
  172.     TVec3 acd = Vec3_Cross( ad, ac );
  173.     TVec3 abd = Vec3_Cross( ab, ad );
  174.     TVec3 abc = Vec3_Cross( ac, ab );
  175.    
  176.     TVec3 aO = Vec3_Negate( a );
  177.    
  178.     if( Helper_SameDirection( abc, aO )) {
  179.         if( Helper_SameDirection( Vec3_Cross( abc, ac ), aO )) {
  180.             Simplex_RemovePoint( simplex, 2 );
  181.             Simplex_RemovePoint( simplex, 0 );
  182.             *outDirection = Vec3_Cross( Vec3_Cross( ac, aO ), ac );
  183.         } else if( Helper_SameDirection( Vec3_Cross( ab, abc ), aO )) {
  184.             Simplex_RemovePoint( simplex, 1 );
  185.             Simplex_RemovePoint( simplex, 0 );
  186.             *outDirection = Vec3_Cross( Vec3_Cross( ab, aO ), ab );
  187.         } else {
  188.             Simplex_RemovePoint( simplex, 0 );
  189.             *outDirection = abc;
  190.         }
  191.     } else if( Helper_SameDirection( acd, aO )) {
  192.         if( Helper_SameDirection( Vec3_Cross( acd, ad ), aO )) {
  193.             Simplex_RemovePoint( simplex, 2 );
  194.             Simplex_RemovePoint( simplex, 1 );
  195.             *outDirection = Vec3_Cross( Vec3_Cross( ad, aO ), ad );
  196.         } else if ( Helper_SameDirection( Vec3_Cross( ac, acd ), aO )) {
  197.             Simplex_RemovePoint( simplex, 2 );
  198.             Simplex_RemovePoint( simplex, 0 );
  199.             *outDirection = Vec3_Cross( Vec3_Cross( ac, aO ), ac );
  200.         } else {
  201.            Simplex_RemovePoint( simplex, 2 );
  202.             *outDirection = acd;
  203.         }
  204.     } else if( Helper_SameDirection( abd, aO )) {
  205.         if( Helper_SameDirection( Vec3_Cross( abd, ab ), aO )) {
  206.             Simplex_RemovePoint( simplex, 1 );
  207.             Simplex_RemovePoint( simplex, 0 );
  208.             *outDirection = Vec3_Cross( Vec3_Cross( ab, aO ), ab );
  209.         } else if( Helper_SameDirection( Vec3_Cross( ad, abd ), aO )) {
  210.             Simplex_RemovePoint( simplex, 2 );
  211.             Simplex_RemovePoint( simplex, 1 );
  212.             *outDirection = Vec3_Cross( Vec3_Cross( ad, aO ), ad );
  213.         } else {
  214.             Simplex_RemovePoint( simplex, 1 );
  215.             *outDirection = abd;
  216.         }
  217.     } else {
  218.         return true;
  219.     }
  220.    
  221.     return false;
  222. }
  223.  
  224. bool GJK_ProcessSimplex( TSimplex * simplex, TVec3 * outDirection ) {
  225.     if( simplex->size == 2 ) {
  226.         return GJK_ProcessLine( simplex, outDirection );
  227.     } else if ( simplex->size == 3 ) {
  228.         return GJK_ProcessTriangle( simplex, outDirection );
  229.     } else {
  230.         return GJK_ProcessTetrahedron( simplex, outDirection );
  231.     }
  232. }
  233.  
  234. bool GJK_IsIntersects( TConvexShape * shape1, TConvexShape * shape2 ) {
  235.     TVec3 dir = Vec3_Set( 0, 1, 0 );
  236.    
  237.     TSimplex simplex = { 0 };
  238.     Simplex_AddPoint( &simplex, GJK_GetSupport( shape1, shape2, dir ));
  239.    
  240.     dir = Vec3_Negate( dir );
  241.    
  242.     int convergenceLimit = 45;
  243.     for( int i = 0; i < convergenceLimit; i++ ) {
  244.         TVec3 lastSupport = GJK_GetSupport( shape1, shape2, dir );              
  245.         if( Helper_SameDirection( dir, lastSupport )) {
  246.             Simplex_AddPoint( &simplex, lastSupport );            
  247.             if( GJK_ProcessSimplex( &simplex, &dir )) {
  248.                 printf( "Intersection! %d iteration(s)!\n", i );
  249.                 return true;
  250.             }            
  251.         } else {
  252.             printf( "No intersection! %d iteration(s)!\n", i );            
  253.             return false;
  254.         }
  255.     }
  256.    
  257.     printf( "No intersection! Convergence limit has reached!\n" );
  258.     return false;
  259. }
  260.  
  261. int main(int argc, char **argv) {
  262.     {
  263.         printf( "Triangle-Triangle Intersection Test - " );
  264.         TConvexShape shape1, shape2;
  265.         ConvexShape_CreateTriangle( &shape1, Vec3_Set( 0, 0, 0 ), Vec3_Set( 0, 1, 0 ), Vec3_Set( 1, 0, 0 ));
  266.         ConvexShape_CreateTriangle( &shape2, Vec3_Set( 0, 0.5, 0 ), Vec3_Set( 0, 1.5, 1 ), Vec3_Set( 1, 0.5, 1 ));
  267.         GJK_IsIntersects( &shape1, &shape2 );
  268.     }
  269.     {
  270.         printf( "Triangle-Tetrahedron Intersection Test - " );
  271.         TConvexShape shape1, shape2;
  272.         ConvexShape_CreateTriangle( &shape1, Vec3_Set( 0, 0, 0.5 ), Vec3_Set( 0, 1, 0.5 ), Vec3_Set( 1, 0, 0.5 ));
  273.         ConvexShape_CreateTetrahedron( &shape2, Vec3_Set( 0, 0, 0 ), Vec3_Set( 0, 1, 0 ), Vec3_Set( 1, 0, 0 ), Vec3_Set( 0, 0, 1 ));
  274.         GJK_IsIntersects( &shape1, &shape2 );
  275.     }
  276.     {
  277.         {
  278.             printf( "Sphere-Tetrahedron Intersection Test Without Small Offset - " );
  279.             TConvexShape shape1, shape2;
  280.             ConvexShape_CreateSphere( &shape1, Vec3_Set( 0,0,0 ), 1 );
  281.             ConvexShape_CreateTetrahedron( &shape2, Vec3_Set( 0, 0, 0 ), Vec3_Set( 0, 1, 0 ), Vec3_Set( 1, 0, 0 ), Vec3_Set( 0, 0, 1 ));
  282.             GJK_IsIntersects( &shape1, &shape2 );
  283.         }
  284.         {
  285.             printf( "Sphere-Tetrahedron Intersection Test With Small Offset - " );
  286.             TConvexShape shape1, shape2;
  287.             ConvexShape_CreateSphere( &shape1, Vec3_Set( 0.0001, 0, 0 ), 1 );
  288.             ConvexShape_CreateTetrahedron( &shape2, Vec3_Set( 0, 0, 0 ), Vec3_Set( 0, 1, 0 ), Vec3_Set( 1, 0, 0 ), Vec3_Set( 0, 0, 1 ));
  289.             GJK_IsIntersects( &shape1, &shape2 );
  290.         }      
  291.     }
  292.     {
  293.         printf( "Tetrahedron-Tetrahedron Intersection Test - " );
  294.         TConvexShape shape1, shape2;
  295.         ConvexShape_CreateTetrahedron( &shape1, Vec3_Set( 0, 0, 0.5 ), Vec3_Set( 0, 1, 0.5 ), Vec3_Set( 1, 0, 0.5 ), Vec3_Set( 0, 0, 1.5 ));
  296.         ConvexShape_CreateTetrahedron( &shape2, Vec3_Set( 0, 0, 0 ), Vec3_Set( 0, 1, 0 ), Vec3_Set( 1, 0, 0 ), Vec3_Set( 0, 0, 1 ));
  297.         GJK_IsIntersects( &shape1, &shape2 );
  298.     }
  299.     {
  300.         printf( "Sphere-Sphere Intersection Test - " );
  301.         TConvexShape shape1, shape2;
  302.         ConvexShape_CreateSphere( &shape1, Vec3_Set( 1,0,0 ), 1 );
  303.         ConvexShape_CreateSphere( &shape2, Vec3_Set( 0,0,0 ), 1 );
  304.         GJK_IsIntersects( &shape1, &shape2 );
  305.     }    
  306.     return 0;
  307. }
Advertisement
Add Comment
Please, Sign In to add comment