dimforge / parry

2D and 3D collision-detection library for Rust.
https://parry.rs
Apache License 2.0
526 stars 93 forks source link

Convex decomposition in 2d produces bad shapes #189

Open hakolao opened 2 months ago

hakolao commented 2 months ago

Convex decomposition with params produces bad shapes.

I would like to use triangle colliders, because they provide better shapes (for dynamic bodies), but they break completely with ccd enabled, which is necessary to prevent objects going within terrain. Therefore, I use convex decomposition instead. However, that sometimes produces really bad shapes.

I haven't found a combination of parameters which would fix this.

ColliderBuilder::convex_decomposition_with_params(
            &contours,
            &indices,
            &VHACDParameters {
                resolution: 32,
               FillMode::FloodFill {
                detect_cavities: true,
                detect_self_intersections: true,
              },
                ..Default::default()
            },
        )

Contour input: image

Resulting collider: image

Test data:

contour
[[0.1388889, 0.12962963],
[0.1388889, 0.11111111],
[0.1388889, 0.0925926],
[0.1388889, 0.074074075],
[0.1388889, 0.055555556],
[0.1388889, 0.037037037],
[0.1388889, 0.018518519],
[0.1388889, 0.0],
[0.1388889, -0.018518519],
[0.1388889, -0.037037037],
[0.1388889, -0.055555556],
[0.1388889, -0.074074075],
[0.1388889, -0.0925926],
[0.1388889, -0.11111111],
[0.1388889, -0.12962963],
[0.1388889, -0.14814815],
[0.12962963, -0.1574074],
[0.11111111, -0.1574074],
[0.0925926, -0.1574074],
[0.074074075, -0.1574074],
[0.055555556, -0.1574074],
[0.037037037, -0.1574074],
[0.018518519, -0.1574074],
[0.0, -0.1574074],
[-0.018518519, -0.1574074],
[-0.037037037, -0.1574074],
[-0.055555556, -0.1574074],
[-0.074074075, -0.1574074],
[-0.0925926, -0.1574074],
[-0.11111111, -0.1574074],
[-0.12962963, -0.1574074],
[-0.14814815, -0.1574074],
[-0.1574074, -0.14814815],
[-0.1574074, -0.12962963],
[-0.1574074, -0.11111111],
[-0.1574074, -0.0925926],
[-0.1574074, -0.074074075],
[-0.1574074, -0.055555556],
[-0.1574074, -0.037037037],
[-0.1574074, -0.018518519],
[-0.1574074, 0.0],
[-0.1574074, 0.018518519],
[-0.1574074, 0.037037037],
[-0.1574074, 0.055555556],
[-0.1574074, 0.074074075],
[-0.1574074, 0.0925926],
[-0.1574074, 0.11111111],
[-0.1574074, 0.12962963],
[-0.14814815, 0.1388889],
[-0.12962963, 0.1388889],
[-0.11111111, 0.1388889],
[-0.0925926, 0.1388889],
[-0.074074075, 0.1388889],
[-0.055555556, 0.1388889],
[-0.037037037, 0.1388889],
[-0.018518519, 0.1388889],
[0.0, 0.1388889],
[0.018518519, 0.1388889],
[0.037037037, 0.1388889],
[0.055555556, 0.1388889],
[0.074074075, 0.1388889],
[0.0925926, 0.1388889],
[0.11111111, 0.1388889],
[0.12962963, 0.1388889],
[0.1388889, 0.12962963]]

indices
[[0, 1],
[1, 2],
[2, 3],
[3, 4],
[4, 5],
[5, 6],
[6, 7],
[7, 8],
[8, 9],
[9, 10],
[10, 11],
[11, 12],
[12, 13],
[13, 14],
[14, 15],
[15, 16],
[16, 17],
[17, 18],
[18, 19],
[19, 20],
[20, 21],
[21, 22],
[22, 23],
[23, 24],
[24, 25],
[25, 26],
[26, 27],
[27, 28],
[28, 29],
[29, 30],
[30, 31],
[31, 32],
[32, 33],
[33, 34],
[34, 35],
[35, 36],
[36, 37],
[37, 38],
[38, 39],
[39, 40],
[40, 41],
[41, 42],
[42, 43],
[43, 44],
[44, 45],
[45, 46],
[46, 47],
[47, 48],
[48, 49],
[49, 50],
[50, 51],
[51, 52],
[52, 53],
[53, 54],
[54, 55],
[55, 56],
[56, 57],
[57, 58],
[58, 59],
[59, 60],
[60, 61],
[61, 62],
[62, 63],
[63, 64]]
hakolao commented 2 months ago

The shape is correct with

FillMode::FloodFill {
                    detect_cavities: false,
                    detect_self_intersections: false,
                }

image.

But I can only use it for the initial state of the object (which can deform). For this particular object this isn't an issue though.

FillMode::SurfaceOnly gives the same result as the reported example.

hakolao commented 2 months ago

Kinda helps if i simplify the contours (to be less lines).

sebcrozet commented 1 week ago

Thank you for providing this test case. I think the right move here is to not use VHACD in 2D (it was originally designed for 3D anyway), and switch to triangulation (currently implemented as ear-clipping in parry) + Hertel-Mehlhorn.

Both features already exist (TriMesh::from_polygon and transformation::hertel_mehlhorn) but they have limitations (like no support for holes, and an API that’s not just one function call); this will be improved in the near term.