Crates.io | mesh_to_sdf |
lib.rs | mesh_to_sdf |
version | 0.2.1 |
source | src |
created_at | 2024-02-05 22:07:18.041731 |
updated_at | 2024-02-18 19:06:03.176712 |
description | Mesh to signed distance field (SDF) converter |
homepage | https://github.com/Azkellas/mesh_to_sdf |
repository | https://github.com/Azkellas/mesh_to_sdf |
max_upload_size | |
id | 1128014 |
size | 134,968 |
⚠️ This crate is still in its early stages. Expect the API to change.
This crate provides two entry points:
generate_sdf
]: computes the signed distance field for the mesh defined by vertices
and indices
at the points query_points
.generate_grid_sdf
]: computes the signed distance field for the mesh defined by vertices
and indices
on a [Grid].use mesh_to_sdf::{generate_sdf, generate_grid_sdf, SignMethod, Topology, Grid};
// vertices are [f32; 3], but can be cgmath::Vector3<f32>, glam::Vec3, etc.
let vertices: Vec<[f32; 3]> = vec![[0.5, 1.5, 0.5], [1., 2., 3.], [1., 3., 7.]];
let indices: Vec<u32> = vec![0, 1, 2];
// query points must be of the same type as vertices
let query_points: Vec<[f32; 3]> = vec![[0.5, 0.5, 0.5]];
// Query points are expected to be in the same space as the mesh.
let sdf: Vec<f32> = generate_sdf(
&vertices,
Topology::TriangleList(Some(&indices)), // TriangleList as opposed to TriangleStrip
&query_points,
SignMethod::Raycast, // How the sign is computed.
); // Raycast is robust but requires the mesh to be watertight.
for point in query_points.iter().zip(sdf.iter()) {
// distance is positive outside the mesh and negative inside.
println!("Distance to {:?}: {}", point.0, point.1);
}
// if you can, use generate_grid_sdf instead of generate_sdf as it's optimized and much faster.
let bounding_box_min = [0., 0., 0.];
let bounding_box_max = [10., 10., 10.];
let cell_count = [10, 10, 10];
let grid = Grid::from_bounding_box(&bounding_box_min, &bounding_box_max, cell_count);
let sdf: Vec<f32> = generate_grid_sdf(
&vertices,
Topology::TriangleList(Some(&indices)),
&grid,
SignMethod::Raycast, // How the sign is computed.
); // Raycast is robust but requires the mesh to be watertight.
for x in 0..cell_count[0] {
for y in 0..cell_count[1] {
for z in 0..cell_count[2] {
let index = grid.get_cell_idx(&[x, y, z]);
log::info!("Distance to cell [{}, {}, {}]: {}", x, y, z, sdf[index as usize]);
}
}
}
Indices can be of any type that implements Into<u32>
, e.g. u16
and u32
. Topology can be list or strip.
If the indices are not provided, they are supposed to be 0..vertices.len()
.
For vertices, this library aims to be as generic as possible by providing a trait Point
that can be implemented for any type.
Implementations for most common math libraries are gated behind feature flags. By default, only [f32; 3]
is provided.
If you do not find your favorite library, feel free to implement the trait for it and submit a PR or open an issue.
This crate provides two methods to compute the sign of the distance:
SignMethod::Raycast
(default): a robust method to compute the sign of the distance. It counts the number of intersection between a ray starting from the query point and the triangles of the mesh.
It only works for watertight meshes, but garantees the sign is correct.SignMethod::Normal
: It uses the normals of the triangles to estimate the sign by doing a dot product with the direction of the query point.
It works for non-watertight meshes but might leak negative distances outside the mesh.For grid generation, Raycast
is ~1% slower.
For query points, Raycast
is ~10% slower.
Note that it depends on the query points / grid size to triangle ratio, but this gives a rough idea.
To use your favorite math library with mesh_to_sdf
, you need to add it to mesh_to_sdf
dependency. For example, to use glam
:
[dependencies]
mesh_to_sdf = { version = "0.2.1", features = ["glam"] }
Currently, the following libraries are supported:
cgmath
(cgmath::Vector3<f32>
)glam
(glam::Vec3
)mint
(mint::Vector3<f32>
and mint::Point3<f32>
)nalgebra
(nalgebra::Vector3<f32>
and nalgebra::Point3<f32>
)[f32; 3]
[generate_grid_sdf
] is much faster than [generate_sdf
] and should be used whenever possible.
[generate_sdf
] does not allocate memory (except for the result array) but is slow. A faster implementation is planned for the future.
[SignMethod::Raycast
] is slightly slower than [SignMethod::Normal
] but is robust and should be used whenever possible (~1% in [generate_grid_sdf
], ~10% in [generate_sdf
]).
License: MIT OR Apache-2.0