parry icon indicating copy to clipboard operation
parry copied to clipboard

`is_inside` test always returns false?

Open Makogan opened this issue 3 months ago • 0 comments

In the following snippet, I expect the assert within trimesh_sdf to trigger, it seems the function is returning the right distances but not the right inclusion sign. The following are the ground truth result of a mesh sdf and the second is the result made by the trimesh:

Image Image

As you can see, the second image is not an SDF but a UGF. I suspect there's something wrong with the implementation of the algorithm but I could not find it.

        use parry3d_f64::na::Point3;
        use parry3d_f64::query::PointQuery;
        use parry3d_f64::shape::TriMesh;
        let mesh = ObjData::from_disk_file("../../../Assets/bunny_closed.obj");
        let tri_mesh = TriMesh::new(
            mesh.vertices
                .iter()
                .map(|v| Point3::<f64>::new(v.x as f64, v.y as f64, v.z as f64))
                .collect::<Vec<_>>(),
            mesh.vertex_face_indices
                .iter()
                .map(|l| [l[0] as u32, l[1] as u32, l[2] as u32])
                .collect::<Vec<_>>(),
        );

        let trimesh_sdf = |v: [f64; 3]| {
            use parry3d_f64::na::Isometry;

            let p = Point3::<f64>::new(v[0] as f64, v[1] as f64, v[2] as f64);
            let proj = tri_mesh.project_local_point(&p, false);

            let d = (proj.point.coords - p.coords).norm();
            let sign = if proj.is_inside
            {
                -1.
            }
            else
            {
                1.
            };
            assert!(sign >= 1.);

            let d = (d * sign) as f64;
            d
        };

        let resolution = 512;
        let mut img: RgbaImage = ImageBuffer::new(resolution as u32, resolution as u32);
        let mut img2: RgbaImage = ImageBuffer::new(resolution as u32, resolution as u32);
        let mut img_diff: RgbaImage =
            ImageBuffer::new(resolution as u32, resolution as u32);

        let val_to_pixel = |x: f64| (((x + 1.0) / 2.0) * 255.0) as u8;
        for [i, j] in IterDimensions::new([resolution, resolution])
        {
            let x = i as f64 / resolution as f64;
            let y = j as f64 / resolution as f64;
            let x = x * (extents[0] as f64 - 0.1) + mins[0] as f64 + 0.1;
            let y = y * (extents[1] as f64 - 0.1) + mins[1] as f64 + 0.1;

            let pos = [x, y, 0.];
            let true_value = sdf(pos);

            let dbg_value = trimesh_sdf(pos); //hp_sdf.eval(pos);
            let diff = (true_value - dbg_value).abs();

            let pixel = val_to_pixel(true_value);
            img.put_pixel(i as u32, j as u32, Rgba::<u8>([pixel, pixel, pixel, 255]));

            let pixel = val_to_pixel(dbg_value);
            img2.put_pixel(i as u32, j as u32, Rgba::<u8>([pixel, pixel, pixel, 255]));

            let (_cell_corner, _size, _node_id) = hp_sdf.fetch_cell(pos);
            // if (x - cell_corner.x as f64).abs() < 0.05
            //     || (y - _cell_corner.y as f64).abs() < 0.05
            // {
            //     img2.put_pixel(i as u32, j as u32, Rgba::<u8>([0, 255, 0, 255]));
            // }

            let pixel = val_to_pixel(diff);
            img_diff.put_pixel(
                i as u32,
                j as u32,
                Rgba::<u8>([pixel, pixel, pixel, 255]),
            );
        }

Makogan avatar Sep 29 '25 00:09 Makogan