RandyGaul / cute_headers

Collection of cross-platform one-file C/C++ libraries with no dependencies, primarily used for games
4.24k stars 264 forks source link

possibly incorrect hitpoint on polytopoly #318

Closed Thomas-de-Bock closed 1 year ago

Thomas-de-Bock commented 1 year ago

So I'm using this code to get the result between two square polies (I know I shouldnt be using polytopoly for squares but this is for testing).

                c2Manifold result;
                c2PolytoPolyManifold(&(*thiscollisionpolies)[a], NULL, &(*thiscollisionpolies)[b], NULL, &result);

                float depth = result.depths[0];
                c2v normal = result.normal;
                c2v hitpoints[2];

                std::cout << "hitpoint1: " << Vector3(result.contact_points[0].x, result.contact_points[0].y).String() << " hitpoint2: " << Vector3(result.contact_points[1].x, result.contact_points[1].y).String() << std::endl;

                std::cout << "body1: ";
                for (int i = 0; i < (*thiscollisionpolies)[a].count; i++)
                {
                    std::cout << "(" << (*thiscollisionpolies)[a].verts[i].x << ", " << (*thiscollisionpolies)[a].verts[i].y << ")";
                }
                std::cout << std::endl;
                std::cout << "body2: ";
                for (int i = 0; i < (*thiscollisionpolies)[b].count; i++)
                {
                    std::cout << "(" << (*thiscollisionpolies)[b].verts[i].x << ", " << (*thiscollisionpolies)[b].verts[i].y << ")";
                }

and print out the points of intersection and vertices, what this prints out in my case is:

hitpoint1: (-0.250000, 7.636099) hitpoint2: (-0.250000, 8.636099)

body1: (0.250000, 8.636099)(-1.750000, 8.636100)(-1.750000, 6.636099)(0.250000, 6.636099)

body2: (1.750000, 7.636099)(1.750000, 9.636099)(-0.250000, 9.636099)(-0.250000, 7.636099)

these values are all in line with what they should be in my program, but the contact points seem weird to me. I'm using my own rendering code which is still very barebones so to make it clear I plotted the points here: image

these are the points of the polygons, but when I also plot the contact points, specified with the arrows (one of the points is on the same position as one of the vertices of the right square): image

If I'm not mistaken about the definition of contact points in this case shouldn't they be placed here? image

as that is where the lines intersect?

I create the polygons with:

        c2Poly poly;
        poly.count = WorldParticles.size();
        for (int i = 0; i < poly.count; i++) {
            poly.verts[i] = c2V(WorldParticles[i].Position.x, WorldParticles[i].Position.y);
        }

        c2MakePoly(&poly);

(WorldParticles just contains the world positions of the vertices of the current shape)

RandyGaul commented 1 year ago

The purpose of the collision plane (the manifold) is to define a plane of contact to push the shapes apart along its normal vector. This normal describes the axis of minimum translation to separate the shapes.

We could represent the contact by points along the intersection of edges, but this wouldn’t provide the best results for a collision solver.

We can calculate the depth of the collision by calculating the distance of each point along the normal vector until separation. The depth is already given to you in the manifold struct.

If you’d like to read more about this kind of algorithm there are comments near the bottom of cute_c2.h describing the algorithm and reading materials.

I’m going to close this issue, but you can of course comment here further if you have more questions or want to discuss more.

Thomas-de-Bock commented 1 year ago

Sorry for responding so late, I read it and I think I understand the point of the returned values now, thanks. Though I am curious to know if there is any way of getting the points of intersection in the c2 header as I need it for calculating certain forces in my engine.

RandyGaul commented 1 year ago

I’m quite suspicious that you don’t need these intersection points, and would like to learn more about your use case to try and help verify what you need and don’t need. The most difficult part of game physics is understanding the problem context and then selecting good algorithms.

Sutherland hodgman clipping would be the algorithm to collect your intersection points. If you like I can provide you with a 2D implementation in C.

RandyGaul commented 1 year ago

Here you go: https://gist.github.com/RandyGaul/8b9c3f3724ea34959586205220be1da3

Though note, if you want edge-edge intersections you'll have to deal with cases like this:

out

As not all the cases have a nice and simple 2 collision points like this case:

out

Thomas-de-Bock commented 1 year ago

That's perfect, thanks so much!