Guest User

Untitled

a guest
Sep 27th, 2015
218
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 6.37 KB | None | 0 0
  1. #include "GJK.h"
  2. #include <iostream>
  3. #include <GLM/gtx/string_cast.hpp>
  4.  
  5.  
  6.  
  7. namespace Ryno{
  8.  
  9.     glm::vec3 GJK::a = glm::vec3(0);
  10.     glm::vec3 GJK::b = a, GJK::c = a, GJK::d = a;
  11.     F32 GJK::length = 0;
  12.  
  13.  
  14.     glm::vec3 double_cross(const glm::vec3& v1, const glm::vec3& v2){
  15.         return glm::cross(glm::cross(v1, v2), v1);
  16.     }
  17.  
  18.     bool GJK::gjk(GameObject* go1, GameObject* go2){
  19.         Collider* s1 = go1->collider->adapt_to_transform(go1->transform);
  20.         Collider* s2 = go2->collider->adapt_to_transform(go2->transform);
  21.        
  22.         bool b = gjk_colliders(s1, s2);
  23.         delete s1;
  24.         delete s2;
  25.         return b;
  26.     }
  27.  
  28.     bool GJK::gjk_colliders(Collider* c1, Collider* c2)
  29.     {
  30.         //Random initial dir
  31.         glm::vec3 dir = c2->get_center() - c1->get_center();
  32.        
  33.         //Get support in the initial direction
  34.         c = support(c1, c2, dir);
  35.  
  36.         //Invert the direction
  37.         dir = -c;
  38.  
  39.         //Get the new support in the new direction
  40.         b = support(c1,c2, dir);
  41.  
  42.         //Se il dot tra OB e DIR e' minore di zero si ritorna,
  43.         //dato che l'origine e' oltre e irraggiungibile
  44.         if (dot(b, dir) < 0) return false;
  45.        
  46.         //Get new direction on the same plane as BC and perpendicular to B
  47.         dir = double_cross(c - b, -b);
  48.  
  49.         //Update the length of the simplex to 2
  50.         length = 2; //begin with 2 points in simplex
  51.  
  52.         //Loop till 50 to avoid infinite loop.
  53.         //It is just a precaution, it should never loop infinitely
  54.         I32 steps = 0;
  55.  
  56.         //Main Loop
  57.         while (steps < 50)
  58.         {
  59.             //Get new point a
  60.             a = support(c1, c2, dir);
  61.  
  62.             //Return false if a is not past the origin
  63.             if (dot(a, dir) < 0) return false;
  64.             //else return true if the current simplex holds the origin
  65.             else if (contains_origin(dir)) return true;
  66.                
  67.             steps++;
  68.             if (steps == 50)
  69.                 std::cout << "Warning: GJK loop" << std::endl;
  70.         }
  71.  
  72.         return false;
  73.     }
  74.  
  75.     bool GJK::contains_origin(glm::vec3& dir)
  76.     {
  77.  
  78.         if (length == 2)
  79.         {
  80.             return triangle(dir);   //always returns false actually
  81.         }
  82.         else if (length == 3)
  83.         {
  84.             return tetrahedron(dir);
  85.         }
  86.  
  87.         return false;
  88.     }
  89.  
  90.  
  91.     bool GJK::triangle(glm::vec3& dir)
  92.     {
  93.         //Get the three edges of triangles
  94.         glm::vec3 ao = glm::vec3(-a.x, -a.y, -a.z);
  95.         glm::vec3 ab = b - a;
  96.         glm::vec3 ac = c - a;
  97.         //Get normal to triangle surface
  98.         glm::vec3 abc = glm::cross(ab, ac);
  99.  
  100.         //Point a cannot be behind the BC segment.
  101.         //But in can be in three different locations after BC: in the triangle, at its left or right.
  102.         //Let's test this:
  103.  
  104.         //Get the normal of AB.
  105.         //Then check the dot with the origin.
  106.         //If > 0, since the normal is pointing outside the triangle, the origin is too,
  107.         //and thus it must be outside the triangle.
  108.         glm::vec3 ab_abc = glm::cross(ab, abc);
  109.  
  110.         if (dot(ab_abc,ao) > 0)
  111.         {
  112.             //If origin is outside, I remove the point C,
  113.             //I go back to a line and set the normal as the new direction
  114.             c = b;
  115.             b = a;
  116.  
  117.             //Calculate the dir.
  118.             //I cannot use ab_abc instead because, while similar, ab_abc does not point
  119.             //Towards the origin, is just a ormal to the AB edge
  120.             dir = double_cross(ab, ao);
  121.  
  122.             //The direction changed, the tetrahedron cannot be built
  123.             return false;
  124.         }
  125.  
  126.         //Then we need to check the two other cases.
  127.         //Is it inside or outside AC?
  128.         //Same as before, I won't comment this
  129.         glm::vec3 abc_ac = glm::cross(abc, ac);
  130.  
  131.  
  132.         if (dot(abc_ac,ao) > 0)
  133.         {
  134.             //Remove B this time
  135.             b = a;
  136.  
  137.             dir = double_cross(ac, ao);
  138.             return false;
  139.         }
  140.  
  141.         //If the code gets here, the origin is inside the triangle.
  142.         //The tetrahedron can be built, but the direction is required.
  143.         //It is a simple matter of calculating the dot product between
  144.         //the normal to the surface of the triangle and the origin
  145.         if (dot(abc,ao) > 0)
  146.         {
  147.             //base of tetrahedron
  148.             d = c;
  149.             c = b;
  150.             b = a;
  151.  
  152.             //new direction
  153.             dir = abc;
  154.         }
  155.         else
  156.         {
  157.             //upside down tetrahedron.
  158.             //Reverse winding order
  159.             d = b;
  160.             //c = c; implied
  161.             b = a;
  162.             dir = -abc;
  163.         }
  164.  
  165.         length = 3;
  166.  
  167.         return false;
  168.     }
  169.    
  170.    
  171.  
  172.     bool GJK::tetrahedron(glm::vec3& dir)
  173.     {
  174.         //Now we have the final triangle.
  175.         //Here we get the edges
  176.         glm::vec3 ao = -a;
  177.         glm::vec3 ab = b - a;
  178.         glm::vec3 ac = c - a;
  179.  
  180.         //get triangle normal
  181.         glm::vec3 abc = glm::cross(ab, ac);
  182.  
  183.         //CASE 1: Origin in front of the triangle ABC
  184.         if (dot(abc,ao) > 0)
  185.         {
  186.             check_tetrahedron(ao, ab, ac, abc, dir);
  187.         }
  188.  
  189.         //CASE 2: Build ACD triangle and do the same
  190.         glm::vec3 ad = d - a;
  191.  
  192.         //build acd triangle
  193.         glm::vec3 acd = glm::cross(ac, ad);
  194.  
  195.         //same direaction with ao
  196.         if (dot(acd,ao) > 0)
  197.         {
  198.             //in front of triangle ACD
  199.             b = c;
  200.             c = d;
  201.             ab = ac;
  202.             ac = ad;
  203.             abc = acd;
  204.  
  205.             check_tetrahedron(ao, ab, ac, abc, dir);
  206.         }
  207.  
  208.         //CASE 3: Same thing with ADB triangle
  209.         //build adb triangle
  210.         glm::vec3 adb = glm::cross(ad, ab);
  211.  
  212.         //same direaction with ao
  213.         if (dot(adb,ao) > 0)
  214.         {
  215.             //in front of triangle ADB
  216.             c = b;
  217.             b = d;
  218.  
  219.             ac = ab;
  220.             ab = ad;
  221.  
  222.             abc = adb;
  223.             check_tetrahedron(ao, ab, ac, abc, dir);
  224.         }
  225.  
  226.         //origin in tetrahedron
  227.         return true;
  228.  
  229.     }
  230.    
  231.     bool GJK::check_tetrahedron(const glm::vec3& ao, const glm::vec3& ab, const glm::vec3& ac, const glm::vec3& abc, glm::vec3& dir)
  232.     {
  233.  
  234.         //almost the same like triangle checks
  235.         glm::vec3 ab_abc = glm::cross(ab, abc);
  236.  
  237.         //If outside the AB edge of the triangle
  238.         if (dot(ab_abc,ao) > 0)
  239.         {
  240.             c = b;
  241.             b = a;
  242.  
  243.             //dir is not ab_abc because it's not pointing towards the origin (it's just a normal)
  244.             //ABxA0xAB direction we are looking for
  245.             dir = double_cross(ab, ao);
  246.  
  247.             //build new triangle
  248.             // d will be lost
  249.             length = 2;
  250.  
  251.             return false;
  252.         }
  253.  
  254.         //Case 2
  255.         glm::vec3 acp = glm::cross(abc, ac);
  256.  
  257.         //If outside the AC edge
  258.         if (dot(acp,ao) > 0)
  259.         {
  260.             b = a;
  261.  
  262.             //dir is not abc_ac because it's not pointing towards the origin
  263.             //ACxA0xAC direction we are looking for
  264.             dir = double_cross(ac, ao);
  265.  
  266.             //build new triangle
  267.             //d will be lost
  268.             length = 2;
  269.  
  270.             return false;
  271.         }
  272.  
  273.         //Case 3 does not need to be checked because implicitely impossible
  274.         //So the point must be inside the tethraedron with base:
  275.         d = c;
  276.         c = b;
  277.         b = a;
  278.  
  279.         dir = abc;
  280.  
  281.         length = 3;
  282.  
  283.         //The next iteration will check it and find that the point is inside it.
  284.  
  285.         return false;
  286.     }
  287.     glm::vec3 GJK::support(Collider* c1, Collider* c2, glm::vec3& dir)
  288.     {
  289.         return c1->get_farthest_point(dir) - c2->get_farthest_point(-dir);
  290.     }
  291. }
Advertisement
Add Comment
Please, Sign In to add comment