Created
January 27, 2019 18:57
-
-
Save haxtibal/799f028f0c7113422194118e7c2518d4 to your computer and use it in GitHub Desktop.
Use crate lyon_tessellation to triangulate a 3D volume
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
extern crate lyon_tessellation; | |
#[cfg(test)] | |
mod tests { | |
use lyon_tessellation::{FillError, FillOptions, FillTessellator, FillVertex}; | |
use lyon_tessellation::path::builder::{FlatPathBuilder,PolygonBuilder}; | |
use lyon_tessellation::path::default::Path; | |
use lyon_tessellation::geometry_builder::{BuffersBuilder,VertexBuffers}; | |
use lyon_tessellation::geom::euclid::{Point2D, Point3D}; | |
struct Mesh3D { | |
positions: Vec<Point3D<f32>>, | |
faces: Vec<Vec<usize>> | |
} | |
impl Mesh3D { | |
fn get_face<'a>(&'a self, faceidx: usize) -> Face3D<'a> { | |
Face3D {mesh: self, faceidx: faceidx} | |
} | |
} | |
struct Face3D<'a> { | |
mesh: &'a Mesh3D, | |
faceidx: usize | |
} | |
impl<'a> Face3D<'a> { | |
fn get_point(&self, index: usize) -> Point3D<f32> { | |
let idx = self.mesh.faces[self.faceidx as usize][index as usize]; | |
self.mesh.positions[idx] | |
} | |
fn get_len(&self) -> usize { | |
self.mesh.faces[self.faceidx].len() | |
} | |
fn to2d(&self) -> ProjectedFace<'a> { | |
let mut polygon2d = Vec::new(); | |
let v0 = self.get_point(0).to_vector(); | |
let loc_x = self.get_point(1).to_vector() - v0; | |
let n = loc_x.cross(self.get_point(2).to_vector() - v0); | |
let loc_y = n.cross(loc_x); | |
let x_n = loc_x.normalize(); | |
let y_n = loc_y.normalize(); | |
for idx in 0..self.get_len() { | |
let to_p = self.get_point(idx).to_vector() - v0; | |
polygon2d.push(Point2D::new(to_p.dot(x_n), to_p.dot(y_n))); | |
} | |
ProjectedFace { | |
mesh: self.mesh, | |
faceidx: self.faceidx, | |
points: polygon2d | |
} | |
} | |
} | |
struct ProjectedFace<'a> { | |
mesh: &'a Mesh3D, | |
faceidx: usize, | |
points: Vec<Point2D<f32>> | |
} | |
impl<'a> ProjectedFace<'a> { | |
fn get_mesh_idx(&self, point_index: usize) -> usize { | |
self.mesh.faces[self.faceidx as usize][point_index as usize] | |
} | |
fn to_path(&self) -> Path { | |
let mut builder = Path::builder(); | |
builder.polygon(&self.points); | |
builder.build() | |
} | |
fn tesselate(&self) -> Result<Vec<usize>, FillError> { | |
let delta = 0.00001; | |
let mut tess = FillTessellator::new(); | |
let mut outbuf: VertexBuffers<usize, u16> = VertexBuffers::new(); | |
tess.tessellate_path( | |
self.to_path().path_iter(), | |
&FillOptions::default().with_tolerance(0.5), | |
&mut BuffersBuilder::new(&mut outbuf, | |
|vertex: FillVertex| { | |
let point_index_search = self.points.iter().position( | |
|&point| (point.x - vertex.position.x).abs() < delta && | |
(point.y - vertex.position.y).abs() < delta); | |
match point_index_search { | |
Some(point_index) => self.get_mesh_idx(point_index), | |
None => {println!("Error: Vertex {:?} is not part of input polygon {:?}", vertex, self.points); 0} | |
} | |
} | |
), | |
)?; | |
Ok(outbuf.indices.iter().map(|item: &u16| {outbuf.vertices[*item as usize]}).collect()) | |
} | |
} | |
#[test] | |
fn test_tessellate_3dmesh() { | |
let mesh = Mesh3D { | |
positions: vec![ | |
Point3D::new(0., 0., 0.), Point3D::new(10., 0., 0.), Point3D::new(10., 10., 0.), Point3D::new(5., 5., 0.), Point3D::new(0., 10., 0.), | |
Point3D::new(0., 0., 10.), Point3D::new(10., 0., 10.), Point3D::new(10., 10., 10.), Point3D::new(5., 5., 10.), Point3D::new(0., 10., 10.) | |
], | |
faces: vec![ | |
vec![0, 1, 2, 3, 4], // bottom face | |
vec![5, 6, 7, 8, 9], // top face | |
vec![0, 1, 6, 5], // side | |
vec![1, 2, 7, 6], // side | |
vec![2, 3, 8, 7], // side | |
vec![3, 4, 9, 8], // side | |
vec![4, 0, 5, 9], // side | |
] | |
}; | |
assert_eq!(mesh.get_face(0).to2d().tesselate().unwrap(), [3, 0, 4, 1, 0, 3, 1, 3, 2]); | |
assert_eq!(mesh.get_face(1).to2d().tesselate().unwrap(), [8, 5, 9, 6, 5, 8, 6, 8, 7]); | |
assert_eq!(mesh.get_face(2).to2d().tesselate().unwrap(), [1, 0, 5, 1, 5, 6]); | |
assert_eq!(mesh.get_face(3).to2d().tesselate().unwrap(), [2, 1, 6, 2, 6, 7]); | |
assert_eq!(mesh.get_face(4).to2d().tesselate().unwrap(), [3, 2, 7, 3, 7, 8]); | |
assert_eq!(mesh.get_face(5).to2d().tesselate().unwrap(), [4, 3, 8, 4, 8, 9]); | |
assert_eq!(mesh.get_face(6).to2d().tesselate().unwrap(), [0, 4, 9, 0, 9, 5]); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment