GJK Algorithm Explanation & Implementation

Поділитися
Вставка
  • Опубліковано 25 лис 2024

КОМЕНТАРІ • 79

  • @chiyokuoni5658
    @chiyokuoni5658 4 роки тому +60

    The best explanation of GJK that i have ever seen in my life

  • @soranuareane
    @soranuareane 6 місяців тому

    Where were you back in 2013 when I was writing my Terraria world analysis software that depended on computing biome extents using these algorithms...
    Thank you for such a clear explanation. This is amazingly informative and very useful.

  • @movingheadmau8128
    @movingheadmau8128 4 роки тому +8

    Great explanation! The one slide in my robotics script was nowhere near enough to understand this :D

    • @Winterdev
      @Winterdev  4 роки тому

      Thanks, glad it helped!

  • @YoTengoUnLCD
    @YoTengoUnLCD 4 роки тому +26

    Great video! It just felt a bit too quick on the last section (gjk itself). I’m surprised you only have about 90 subs! Keep up the good work.

    • @Winterdev
      @Winterdev  4 роки тому +2

      Thanks! Pacing is something I still need to pin down... I write articles to go along with the videos so it's a tricky decision

  • @DragonJawad
    @DragonJawad 2 роки тому +3

    Just wanna say, the first time I saw this I really appreciated it but didn't truly understand it. Months later, after reading various articles and the like, I understood the theoretical aspect but was hella worried about implementation.
    Then I found this vid again and god DAMN it was a life savor
    You a life savor
    Thanks a ton for saving me a whoooole lotta implementation headache

    • @Winterdev
      @Winterdev  2 роки тому

      Thanks! I made this to be sorta like a tutorial if you already knew 50% of it. I’m glad to hear that’s how it worked out for you!

  • @larzcaetano
    @larzcaetano 2 роки тому +5

    Maybe a small or better implementation is to make the first GJK support to be in the direction of the relative positions of the shapes. That way, you already get an extreme point, using, for instance, the center of mass of both objects 'direction = colliderB->getCenterOfMass() - colliderA->getCenterOfMass()'. Amazing video!!!

    • @Winterdev
      @Winterdev  2 роки тому +3

      I’ve seen some people do that and I think you could shave off some iterations but I was going for extra small code so I didn’t. Thanks!

  • @Higgsinophysics
    @Higgsinophysics 2 роки тому +1

    You are a real talented teacher. Well done!

  • @larsmaier9772
    @larsmaier9772 3 роки тому

    That was quick. The hard part is not copy'n paste that algorithm but understanding why the orientations are correct.

  • @Johnny-tw5pr
    @Johnny-tw5pr 2 роки тому +4

    It's complicated math but when you simplify it and write the code for it it's actually much faster than you expect

  • @dandymcgee
    @dandymcgee 3 роки тому +1

    Nice visualizations. I really like the Minkowski Sum one.

  • @brianzhou4070
    @brianzhou4070 2 роки тому

    you dropped the best video series ever just to disappear :(

  • @erickweil4580
    @erickweil4580 3 роки тому +1

    5:57 in the Line case, I found that the AB not pointing towards AO never happening in practice, and if you consider the operation, it go as follows: the same direction check is basically testing the dot product, consider 2d case, ABx * AOx + ABy * AOy > 0, if you substitute the values and re-arrange you get: Ax^2 + Ay^2 > Ax*Bx + Ay*By , wich is basically saying geomretrically: A dot A > A dot B, if A and B are unit vectors and A != B, then this is always true.
    Maybe I'm wrong but also if the A point isn't past the origin it wouldn't also be dropped on the main gjk loop with the dir check?
    So the Line function doesn't need the false block of if(SameDirection(ab,ao)) because it never will be executed based on my tests, the maths and the logic.
    EDIT: ok realised your code uses the Line function on the triangle and tetrahedron, so it's more general, that is why it is possible.

    • @Winterdev
      @Winterdev  3 роки тому

      Aa ok this is code that I wrote months ago so I takes a little bit to go back and look. This vid was supposed to be a super condensed version of the one that Casey did, so he came up with the if flow. Glad I got you interested in this algo I appreciate the scrutiny cus I learn more from these comment that I did making the vid in the first place! Thinking about it you’re right for the line case because there can be a further point that A cus that’s the by def what the support point is, but it allows the code to be nice and condensed for the later checks where it could be on either side of A. Thanks for the comment :)

  • @쾌남시대
    @쾌남시대 Рік тому

    Wow!! Thank you for the easy explanation.!!!

  • @gmjammin4367
    @gmjammin4367 Рік тому

    Not to be a jerk but I think it would be valuable to clarify that this is really the sub-variant of the traditional GJK algorithm (GJK-SAT). As well as this, the number of cases in three dimensional space actually expands to considering all regions rather than just the faces of the simplex. I hate to be rude but I spent way too long figuring this out when attempting to implement this myself. Gino van den Bergen's 'Colllsion Detection in Interactive 3D Environments' documents the GJK as well as Gino's EPA rather extensively, and I think the full distance minimization implementation is insightful for those just figuring this stuff out. Either way, this video does a fantastic job explaining the essence of the support function and the configuration space obstacle. I can't wait to see what else you're up to!

    • @Hector-bj3ls
      @Hector-bj3ls 4 місяці тому

      The resource you mentioned has almost 300 pages.

  • @CDBelfer4
    @CDBelfer4 3 роки тому +4

    I'm actually quite impressed with the quality of the videos; visual, simple, and concise. Keep up the great work! P.S. You've earned a new sub :)

  • @wal9745
    @wal9745 3 роки тому +1

    This is an awesome explanation

  • @TheErer1243
    @TheErer1243 3 роки тому

    awesome video!! I was reading about gjk on the allen chou game physics blog and just didn't get it. the visualizations made it click immediately

  • @tintingai8894
    @tintingai8894 2 роки тому

    great video ! Unfortunatly the full article is down :c

  • @MrRenanwill
    @MrRenanwill 2 роки тому +1

    It's needed to know the vertex to compute the algorithm? Some convex sets are given by equations, like c(x)

    • @Winterdev
      @Winterdev  2 роки тому

      If you can get a support function then yes. If you look at how the sphere works it generates a point based on the direction and the center point/radius. I think that this also isn’t very good with those types of shapes however because it loops forever unless you put a max step count in. I wonder if there is a version specifically for these types of functions/shapes?

  • @pako_powr
    @pako_powr 4 роки тому +3

    damn, really nice explanation and visualization

  • @Red-di7zb
    @Red-di7zb 4 роки тому +2

    Amazing content. Hello from Russia.

    • @Winterdev
      @Winterdev  4 роки тому +1

      Thanks from America!

  • @fominvic81
    @fominvic81 3 роки тому +3

    The best tutorial that i have ever seen! Thanks!

  • @samsaraAI2025
    @samsaraAI2025 10 місяців тому

    When you say that you iterate the direction D. How you do that? How many directions you use? Which values?

  • @jonathanpinto6847
    @jonathanpinto6847 4 роки тому +2

    Amazing Explanation!

    • @Winterdev
      @Winterdev  4 роки тому

      Thanks glad you enjoyed it

  • @klimawubsi1395
    @klimawubsi1395 3 роки тому +1

    Your variant breaks down if the origin is contained in one of the edges or faces.

    • @Winterdev
      @Winterdev  3 роки тому

      Yeah someone else brought up the >= too. I did that but because it seemed to decrease the number of iterations in some cases without changing how the tests worked. Maybe that has more of an effect than I realized though. You don’t get 0 distance collisions, but those would have no effect so I dropped them, maybe for rotational that is a problem though. I need to see an example of it breaking to put this to rest!

  • @laddermane9945
    @laddermane9945 Рік тому +2

    Pretty sure there is an error in formula @2:20. We want max(D*A - D*B) => max(D*A) - min(D*B) => max(D*A) - (-max(-D*B)) => max(D*A) + max(-D*B). This is using the identity that min(f(x)) = -max(-f(x)). I think you just merged the minus signs on accident. What are your thoughts? Am I missing something?

    • @ruslahn6717
      @ruslahn6717 4 місяці тому +1

      thought the same thing. I also think, that this is an error.

  • @loganbrown898
    @loganbrown898 3 роки тому +1

    In my implementation I'm never getting support.dot(direction)

    • @Winterdev
      @Winterdev  3 роки тому

      I’d start by putting a cap on the number of iterations and see if you’re getting a correct answer. Then I’d log the simplex points and direction to make sure they’re right. If you’re in 2d, you could check out the website winter.dev/lilapps/gjk and put the same points in your code as those and step though each to spot a difference. Good luck! :)

  • @bamsgian9759
    @bamsgian9759 Рік тому

    How to find direction in supporting point?

  • @sebastientaymans
    @sebastientaymans 3 роки тому +1

    I don't understand why "support.dot(direction)

    • @Winterdev
      @Winterdev  3 роки тому

      I remember changing that to stop an infinite loop if the origin lies directly on the simplex. I think that you're correct in wanting 0 distance collisions, I was only thinking about position, but if you're working with forces, then friction for example would be more accurate with 0 distance collisions. I played around with the code and it seems like that the anomaly caused by

    • @sebastientaymans
      @sebastientaymans 3 роки тому +1

      ​@@Winterdev In 2D, I found a case where a real collision (where they actually collide deeper than just with the border) occur but is not detected by taking 2 same square that are exactly in the same y position and overlap on the x axis. In this case, the first support point is exactly along the x axis. Then, the second support point is also exactly along the x axis in the other direction. In this situation, the Line function will set the direction with the 0 vector. And then, if the direction is the 0 vector, it will verify "support.dot(direction)

    • @Winterdev
      @Winterdev  3 роки тому +2

      ​@@sebastientaymans Yeah I was playing around with a similar edge case in the little tool, it seems like removing '=' results in the same behavior though. The order of vertices shouldn't matter, it seems like if the direction from the simple is 0, then something has gone wrong so it should just exit, you could put code that checks for this, but in practice it this case never comes up. Maybe there is a stronger way to find the direction, this is a simplified version specifically for games, the people who do CAD need much higher fidelity version that you can read whitepapers about, but they are wordy. dl.acm.org/doi/abs/10.1145/3072959.3083724 this has a cool video

  • @arifkasim3241
    @arifkasim3241 3 роки тому +1

    One word - Superb!

  • @bluedev6304
    @bluedev6304 3 роки тому +1

    I implemented this in unity and then compared the results with unity's physics engine and with 36 of these mesh colliders the frame rate dropped to 80fps. but with unity's mesh collider it stayed at 280fps. So I would like to know how can I optimize this type of mesh collider?

    • @compositeembryo7186
      @compositeembryo7186 3 роки тому

      How are you checking them? Brute force, or some kind of tree algorithm? There's probably a couple of other optimisations that unity is using, but that's one of the big ones I can think of

    • @bluedev6304
      @bluedev6304 3 роки тому

      @@compositeembryo7186 Currently I only have one optimization that is using aabb trees

    • @compositeembryo7186
      @compositeembryo7186 3 роки тому

      @@bluedev6304 I don't know if this will help because I am nowhere near the skill of the people who develop unity itself, but maybe give a kd or quadtree a try

    • @Winterdev
      @Winterdev  3 роки тому +1

      my guess is that if unity is using physx then it’s prob more paralleled on the gpu

  • @vectozavr
    @vectozavr 3 роки тому +3

    4:52 - why did you chose -support for the new direction?
    And also why did't you normalize this vector? As I got from your explanation vector D should be normalized (2:12)

    • @Winterdev
      @Winterdev  3 роки тому +1

      At 2:21 all the points get scaled by D's length, so you don't need to normalize. And at 4:52 it's slightly confusing but we want the direction to the origin at (0, 0) so you take (0, 0) - support = -support

    • @vectozavr
      @vectozavr 3 роки тому

      @@Winterdev thank's a lot for your videos and answer!
      p/s: I am writing 3d engine by my own to make a video on my channel about it :)

    • @Winterdev
      @Winterdev  3 роки тому +4

      @@vectozavr Sounds cool, good luck with it! I've got the engine, now I got to make the videos :)

    • @fnhm_
      @fnhm_ 3 роки тому

      Вектозавр, ты чего тут забыл?)

  • @TheUnmistakableMan
    @TheUnmistakableMan 4 роки тому +1

    This helped me out so much! So clearly explained! Thank you :)

    • @Winterdev
      @Winterdev  4 роки тому

      Nice! Good to hear it helped :)

  • @matanmigdal7108
    @matanmigdal7108 4 роки тому +1

    can you do one for EPA?

    • @Winterdev
      @Winterdev  4 роки тому +3

      I am planning to do that next, should be up in the next 2 weeks or so

  • @fhvirus3221
    @fhvirus3221 2 роки тому

    Hello!
    It seems like the description and figure for Minkowski difference is wrong. According to the link provided below (and the link in the linked page), the Minkowski difference of A and B should be C s.t. the Minkowski sum of B and C is equal to A. The polygon shown in the video is the Minkowski sum of A and -B rather than their difference. Given that, the algorithm does not produce Minkowski difference, but it's still correct.

    • @Winterdev
      @Winterdev  2 роки тому

      Aa good point I was trying to simplify the terms cus everyone talks about a sum but then subtracts, what makes this different than normal addition and subtraction that we can’t flip the terms like I did?

    • @fhvirus3221
      @fhvirus3221 2 роки тому

      @@Winterdev For example, in 1D world, the sum of A [0, 1] and B [0, 2] would be C [0, 3]. If we use C + (-B), we will get [-2, 3], but if we use C - B, we should get A (meaning undoing the addition operation).

    • @David_Raab
      @David_Raab 3 місяці тому

      @@fhvirus3221 C + (-B) is [0,1]. Long way. [0,3] - [0,2] = [0-0, 3-2] = [0,1]. Doesn't change if you negate and then add [0,3] + [-0,-2] = [0+-0, 3+-2] = [0,1]

  • @chyza2012
    @chyza2012 3 роки тому

    I've been struggling with my own implementation for a few days and this really helped, however I'm sometimes getting false positives with an analytical cylinder support when rotation for one or both of the objects is zero, which is strange. I'm not sure if this is fault of the core gjk or the support function though.

    • @Winterdev
      @Winterdev  3 роки тому

      Thanks for the comment! I’m gonna need a drawing lol I don’t really know what you mean. Are you saying that when you have two objects, 0 angle, I’m assuming in 2d, the line case fails?

    • @chyza2012
      @chyza2012 3 роки тому +1

      @@Winterdev Thanks for the reply.
      When i have two 3d cylinders with an analytically computed support (instead of using a mesh and looping over the vertices) and the rotation is zero in all axes, the algorithm detects a collision where there is none in some cases, even when the objects are really far from each other. I'm not exactly sure where it fails because there doesn't seem to be a pattern, however the core algorithm works 100% of the time when using mesh supports.
      Here's the actual function, sorry if it gets mangled by youtube formatting.
      vec3 cylinder_support(vec3 dir, float radius, float high_y, float low_y) {
      vec3 xz = normalize(vec3(dir.x, 0, dir.z)) * radius;
      xz.y = (dir.y < 0) ? low_y : high_y;
      return xz;
      }
      It seems to return almost the same exact points as when using an equivalent cylinder mesh, so I'm not sure where the issue could come from, in my mind it ought to return a marginally different collision when the shapes are really close, not complete nonsense.
      And also a screenshot, although you can't tell much from it. i.imgur.com/MR5Knp5.png, the wireframes are green for collision. (ignore the z-fighting on the lower cylinder)

    • @Winterdev
      @Winterdev  3 роки тому

      @@chyza2012 Interesting... False positives were a common issue when I was making the original version, but I use the analytical support for the sphere v mesh collisions. I don't see why that would be any different. I'll have to make a cylinder collider and test it in my version. I'll let you know what I find

    • @chyza2012
      @chyza2012 3 роки тому +1

      @@Winterdev
      I've resolved this a while ago, but it didn't occur to me to update this comment chain.
      In the end it was a dumb division by zero issue in the support function.
      if the direction was purely in the y direction, the normalize in the line
      vec3 xz = normalize(vec3(dir.x, 0, dir.z)) * radius;
      would divide by zero (since the vector would end up being {0, 0, 0}) and result in all nans, these would mess up the rest of the algorithm, apparently this degenerate case happened often enough with perfectly axis aligned cylinders to be an issue.
      To fix it i simply added a check
      vec3 cylinder_support(vec3 dir, float radius, float high_y, float low_y) {
      vec3 xz = vec3(0);
      if (dir.x != 0 && dir.y != 0) {
      xz = normalize(vec3(dir.x, 0, dir.z)) * radius;
      }
      xz.y = (dir.y < 0) ? low_y : high_y;
      return xz;
      }
      Might not be the most elegant but it works.

    • @Winterdev
      @Winterdev  3 роки тому

      aa that makes sense. I had put your code in, but never got around to making a mesh for it so I couldn't tell if it was correct. Glad you found a solution :)

  • @Serotonindude
    @Serotonindude 3 роки тому +4

    it's a great video! but it's too fast... if you want to reach people who do not already know what you know, give them some time to think about what you're trying to tell them...

    • @Winterdev
      @Winterdev  3 роки тому +2

      Yeah haha that was the goal when I made these vids a year ago. I was thinking that if you wanted to code along, instead of sifting through an hour it would be easier to sift through a condensed 5-10mim cus you need to watch more than once. Looking back now though if you’re not specifically looking for this exactly it’s a tense watch. There are articles to read if the vids too fast was my thought. When I make more tutorial like vids I think I am going to aim for that zen feel. Thanks for the comment!

  • @skybuck2000
    @skybuck2000 Рік тому

    It might not be stable, floating point comparisons

  • @BuyMyBeard
    @BuyMyBeard Рік тому +1

    Ugh. Too. Much. Math. I think i’ll just stick to iterating over my edges to find an overlap

  • @DragonJawad
    @DragonJawad 2 роки тому +1

    A solid theoretical intro on GJK in case it helps anyone:
    ua-cam.com/video/SDS5gLSiLg0/v-deo.html
    That vid plus this vid saved my life

    • @Winterdev
      @Winterdev  2 роки тому

      Oh yea this talk is interesting, I like the bits about expanding surfaces

  • @guydude82
    @guydude82 2 роки тому

    It seems like you miss a few edge-case checks:
    1. For the line simplex: what if the origin is on the line?
    2. For the tetrahedron: what if the origin is in a region between two triangular faces? (i.e. sameDirection could return true for two faces of the tetrahedron, if the origin is in the right spot)
    Also the animation at 5:35 doesn't represent a possible scenario, if I'm understanding correctly. If you start with point B and search towards the origin, and A is the furthest support point you can find in that direction, no collision occurred because A does not pass the origin in the direction BO.

  • @MissPiggyM976
    @MissPiggyM976 5 днів тому

    Too fast...