mirror of
https://github.com/hannobraun/Fornjot
synced 2025-02-15 03:35:52 +00:00
Merge pull request #459 from hannobraun/mesh
Expand `Mesh` API with methods that work with triangles
This commit is contained in:
commit
9090f0f8d6
@ -1,6 +1,6 @@
|
|||||||
use std::f64::consts::FRAC_PI_2;
|
use std::f64::consts::FRAC_PI_2;
|
||||||
|
|
||||||
use fj_interop::mesh::Triangle;
|
use fj_interop::mesh::Mesh;
|
||||||
use fj_math::{Aabb, Scalar};
|
use fj_math::{Aabb, Scalar};
|
||||||
use nalgebra::{Point, TAffine, Transform, Translation, Vector};
|
use nalgebra::{Point, TAffine, Transform, Translation, Vector};
|
||||||
use parry3d_f64::query::{Ray, RayCast as _};
|
use parry3d_f64::query::{Ray, RayCast as _};
|
||||||
@ -131,7 +131,7 @@ impl Camera {
|
|||||||
&self,
|
&self,
|
||||||
window: &Window,
|
window: &Window,
|
||||||
cursor: Option<PhysicalPosition<f64>>,
|
cursor: Option<PhysicalPosition<f64>>,
|
||||||
triangles: &[Triangle],
|
mesh: &Mesh<fj_math::Point<3>>,
|
||||||
) -> FocusPoint {
|
) -> FocusPoint {
|
||||||
let cursor = match cursor {
|
let cursor = match cursor {
|
||||||
Some(cursor) => cursor,
|
Some(cursor) => cursor,
|
||||||
@ -147,7 +147,7 @@ impl Camera {
|
|||||||
|
|
||||||
let mut min_t = None;
|
let mut min_t = None;
|
||||||
|
|
||||||
for triangle in triangles {
|
for triangle in mesh.triangles() {
|
||||||
let t = triangle.inner.to_parry().cast_local_ray(
|
let t = triangle.inner.to_parry().cast_local_ray(
|
||||||
&ray,
|
&ray,
|
||||||
f64::INFINITY,
|
f64::INFINITY,
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
use bytemuck::{Pod, Zeroable};
|
use bytemuck::{Pod, Zeroable};
|
||||||
use fj_interop::{
|
use fj_interop::{
|
||||||
debug::DebugInfo,
|
debug::DebugInfo,
|
||||||
mesh::{Index, Mesh, Triangle},
|
mesh::{Index, Mesh},
|
||||||
};
|
};
|
||||||
use nalgebra::{vector, Point};
|
use nalgebra::{vector, Point};
|
||||||
|
|
||||||
@ -66,22 +66,22 @@ impl Vertices {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<&Vec<Triangle>> for Vertices {
|
impl From<&Mesh<fj_math::Point<3>>> for Vertices {
|
||||||
fn from(triangles: &Vec<Triangle>) -> Self {
|
fn from(mesh: &Mesh<fj_math::Point<3>>) -> Self {
|
||||||
let mut mesh = Mesh::new();
|
let mut m = Mesh::new();
|
||||||
|
|
||||||
for triangle in triangles {
|
for triangle in mesh.triangles() {
|
||||||
let [a, b, c] = triangle.inner.points();
|
let [a, b, c] = triangle.inner.points();
|
||||||
|
|
||||||
let normal = (b - a).cross(&(c - a)).normalize();
|
let normal = (b - a).cross(&(c - a)).normalize();
|
||||||
let color = triangle.color;
|
let color = triangle.color;
|
||||||
|
|
||||||
mesh.push((a, normal, color));
|
m.push_vertex((a, normal, color));
|
||||||
mesh.push((b, normal, color));
|
m.push_vertex((b, normal, color));
|
||||||
mesh.push((c, normal, color));
|
m.push_vertex((c, normal, color));
|
||||||
}
|
}
|
||||||
|
|
||||||
let vertices = mesh
|
let vertices = m
|
||||||
.vertices()
|
.vertices()
|
||||||
.map(|(vertex, normal, color)| Vertex {
|
.map(|(vertex, normal, color)| Vertex {
|
||||||
position: vertex.into(),
|
position: vertex.into(),
|
||||||
@ -90,7 +90,7 @@ impl From<&Vec<Triangle>> for Vertices {
|
|||||||
})
|
})
|
||||||
.collect();
|
.collect();
|
||||||
|
|
||||||
let indices = mesh.indices().collect();
|
let indices = m.indices().collect();
|
||||||
|
|
||||||
Self { vertices, indices }
|
Self { vertices, indices }
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
use std::time::Instant;
|
use std::time::Instant;
|
||||||
|
|
||||||
use fj_interop::mesh::Triangle;
|
use fj_interop::mesh::Mesh;
|
||||||
|
use fj_math::Point;
|
||||||
use winit::{
|
use winit::{
|
||||||
dpi::PhysicalPosition,
|
dpi::PhysicalPosition,
|
||||||
event::{
|
event::{
|
||||||
@ -121,9 +122,9 @@ impl Handler {
|
|||||||
now: Instant,
|
now: Instant,
|
||||||
camera: &mut Camera,
|
camera: &mut Camera,
|
||||||
window: &Window,
|
window: &Window,
|
||||||
triangles: &[Triangle],
|
mesh: &Mesh<Point<3>>,
|
||||||
) {
|
) {
|
||||||
let focus_point = camera.focus_point(window, self.cursor, triangles);
|
let focus_point = camera.focus_point(window, self.cursor, mesh);
|
||||||
|
|
||||||
self.zoom.discard_old_events(now);
|
self.zoom.discard_old_events(now);
|
||||||
self.zoom.update_speed(now, delta_t, focus_point, camera);
|
self.zoom.update_speed(now, delta_t, focus_point, camera);
|
||||||
|
@ -9,10 +9,9 @@ use std::path::PathBuf;
|
|||||||
use std::{collections::HashMap, time::Instant};
|
use std::{collections::HashMap, time::Instant};
|
||||||
|
|
||||||
use fj_host::Model;
|
use fj_host::Model;
|
||||||
use fj_interop::mesh::Triangle;
|
|
||||||
use fj_interop::{debug::DebugInfo, mesh::Mesh};
|
use fj_interop::{debug::DebugInfo, mesh::Mesh};
|
||||||
use fj_kernel::algorithms::triangulate;
|
use fj_kernel::algorithms::triangulate;
|
||||||
use fj_math::{Aabb, Scalar};
|
use fj_math::{Aabb, Point, Scalar};
|
||||||
use fj_operations::ToShape as _;
|
use fj_operations::ToShape as _;
|
||||||
use futures::executor::block_on;
|
use futures::executor::block_on;
|
||||||
use tracing::{trace, warn};
|
use tracing::{trace, warn};
|
||||||
@ -85,18 +84,10 @@ fn main() -> anyhow::Result<()> {
|
|||||||
let shape = model.load_once(¶meters)?;
|
let shape = model.load_once(¶meters)?;
|
||||||
let shape = shape_processor.process(&shape);
|
let shape = shape_processor.process(&shape);
|
||||||
|
|
||||||
let mut mesh_maker = Mesh::new();
|
|
||||||
|
|
||||||
for triangle in shape.triangles {
|
|
||||||
for vertex in triangle.inner.points() {
|
|
||||||
mesh_maker.push(vertex);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
let vertices =
|
let vertices =
|
||||||
mesh_maker.vertices().map(|vertex| vertex.into()).collect();
|
shape.mesh.vertices().map(|vertex| vertex.into()).collect();
|
||||||
|
|
||||||
let indices: Vec<_> = mesh_maker.indices().collect();
|
let indices: Vec<_> = shape.mesh.indices().collect();
|
||||||
let triangles = indices
|
let triangles = indices
|
||||||
.chunks(3)
|
.chunks(3)
|
||||||
.map(|triangle| {
|
.map(|triangle| {
|
||||||
@ -187,7 +178,7 @@ fn main() -> anyhow::Result<()> {
|
|||||||
let focus_point = camera.focus_point(
|
let focus_point = camera.focus_point(
|
||||||
&window,
|
&window,
|
||||||
input_handler.cursor(),
|
input_handler.cursor(),
|
||||||
&shape.triangles,
|
&shape.mesh,
|
||||||
);
|
);
|
||||||
|
|
||||||
input_handler.handle_mouse_input(
|
input_handler.handle_mouse_input(
|
||||||
@ -213,7 +204,7 @@ fn main() -> anyhow::Result<()> {
|
|||||||
now,
|
now,
|
||||||
camera,
|
camera,
|
||||||
&window,
|
&window,
|
||||||
&shape.triangles,
|
&shape.mesh,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -292,17 +283,15 @@ impl ShapeProcessor {
|
|||||||
};
|
};
|
||||||
|
|
||||||
let mut debug_info = DebugInfo::new();
|
let mut debug_info = DebugInfo::new();
|
||||||
let mut triangles = Vec::new();
|
let mesh = triangulate(
|
||||||
triangulate(
|
|
||||||
shape.to_shape(tolerance, &mut debug_info),
|
shape.to_shape(tolerance, &mut debug_info),
|
||||||
tolerance,
|
tolerance,
|
||||||
&mut triangles,
|
|
||||||
&mut debug_info,
|
&mut debug_info,
|
||||||
);
|
);
|
||||||
|
|
||||||
ProcessedShape {
|
ProcessedShape {
|
||||||
aabb,
|
aabb,
|
||||||
triangles,
|
mesh,
|
||||||
debug_info,
|
debug_info,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -310,14 +299,14 @@ impl ShapeProcessor {
|
|||||||
|
|
||||||
struct ProcessedShape {
|
struct ProcessedShape {
|
||||||
aabb: Aabb<3>,
|
aabb: Aabb<3>,
|
||||||
triangles: Vec<Triangle>,
|
mesh: Mesh<Point<3>>,
|
||||||
debug_info: DebugInfo,
|
debug_info: DebugInfo,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ProcessedShape {
|
impl ProcessedShape {
|
||||||
fn update_geometry(&self, renderer: &mut Renderer) {
|
fn update_geometry(&self, renderer: &mut Renderer) {
|
||||||
renderer.update_geometry(
|
renderer.update_geometry(
|
||||||
(&self.triangles).into(),
|
(&self.mesh).into(),
|
||||||
(&self.debug_info).into(),
|
(&self.debug_info).into(),
|
||||||
self.aabb,
|
self.aabb,
|
||||||
);
|
);
|
||||||
|
@ -2,12 +2,15 @@
|
|||||||
|
|
||||||
use std::{collections::HashMap, hash::Hash};
|
use std::{collections::HashMap, hash::Hash};
|
||||||
|
|
||||||
|
use fj_math::Point;
|
||||||
|
|
||||||
/// A triangle mesh
|
/// A triangle mesh
|
||||||
pub struct Mesh<V> {
|
pub struct Mesh<V> {
|
||||||
vertices: Vec<V>,
|
vertices: Vec<V>,
|
||||||
indices: Vec<Index>,
|
indices: Vec<Index>,
|
||||||
|
|
||||||
indices_by_vertex: HashMap<V, Index>,
|
indices_by_vertex: HashMap<V, Index>,
|
||||||
|
triangles: Vec<Triangle>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<V> Mesh<V>
|
impl<V> Mesh<V>
|
||||||
@ -20,7 +23,7 @@ where
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Add a vertex to the mesh
|
/// Add a vertex to the mesh
|
||||||
pub fn push(&mut self, vertex: V) {
|
pub fn push_vertex(&mut self, vertex: V) {
|
||||||
let index =
|
let index =
|
||||||
*self.indices_by_vertex.entry(vertex).or_insert_with(|| {
|
*self.indices_by_vertex.entry(vertex).or_insert_with(|| {
|
||||||
let index = self.vertices.len();
|
let index = self.vertices.len();
|
||||||
@ -31,6 +34,25 @@ where
|
|||||||
self.indices.push(index);
|
self.indices.push(index);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Determine whether the mesh contains the provided triangle
|
||||||
|
///
|
||||||
|
/// Returns true, if a triangle with any combination of the points of the
|
||||||
|
/// provided triangle is part of the mesh.
|
||||||
|
pub fn contains_triangle(
|
||||||
|
&self,
|
||||||
|
triangle: impl Into<fj_math::Triangle<3>>,
|
||||||
|
) -> bool {
|
||||||
|
let triangle = triangle.into().normalize();
|
||||||
|
|
||||||
|
for t in &self.triangles {
|
||||||
|
if triangle == t.inner.normalize() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
false
|
||||||
|
}
|
||||||
|
|
||||||
/// Access the vertices of the mesh
|
/// Access the vertices of the mesh
|
||||||
pub fn vertices(&self) -> impl Iterator<Item = V> + '_ {
|
pub fn vertices(&self) -> impl Iterator<Item = V> + '_ {
|
||||||
self.vertices.iter().copied()
|
self.vertices.iter().copied()
|
||||||
@ -40,6 +62,28 @@ where
|
|||||||
pub fn indices(&self) -> impl Iterator<Item = Index> + '_ {
|
pub fn indices(&self) -> impl Iterator<Item = Index> + '_ {
|
||||||
self.indices.iter().copied()
|
self.indices.iter().copied()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Access the triangles of the mesh
|
||||||
|
pub fn triangles(&self) -> impl Iterator<Item = Triangle> + '_ {
|
||||||
|
self.triangles.iter().copied()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Mesh<Point<3>> {
|
||||||
|
/// Add a triangle to the mesh
|
||||||
|
pub fn push_triangle(
|
||||||
|
&mut self,
|
||||||
|
triangle: impl Into<fj_math::Triangle<3>>,
|
||||||
|
color: Color,
|
||||||
|
) {
|
||||||
|
let triangle = triangle.into();
|
||||||
|
|
||||||
|
for point in triangle.points() {
|
||||||
|
self.push_vertex(point);
|
||||||
|
}
|
||||||
|
|
||||||
|
self.triangles.push(Triangle::new(triangle, color));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// This needs to be a manual implementation. Deriving `Default` would require
|
// This needs to be a manual implementation. Deriving `Default` would require
|
||||||
@ -50,6 +94,7 @@ impl<V> Default for Mesh<V> {
|
|||||||
vertices: Default::default(),
|
vertices: Default::default(),
|
||||||
indices: Default::default(),
|
indices: Default::default(),
|
||||||
indices_by_vertex: Default::default(),
|
indices_by_vertex: Default::default(),
|
||||||
|
triangles: Default::default(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2,8 +2,8 @@ mod delaunay;
|
|||||||
mod polygon;
|
mod polygon;
|
||||||
mod ray;
|
mod ray;
|
||||||
|
|
||||||
use fj_interop::{debug::DebugInfo, mesh::Triangle};
|
use fj_interop::{debug::DebugInfo, mesh::Mesh};
|
||||||
use fj_math::Scalar;
|
use fj_math::{Point, Scalar};
|
||||||
|
|
||||||
use crate::{shape::Shape, topology::Face};
|
use crate::{shape::Shape, topology::Face};
|
||||||
|
|
||||||
@ -15,9 +15,10 @@ use super::FaceApprox;
|
|||||||
pub fn triangulate(
|
pub fn triangulate(
|
||||||
mut shape: Shape,
|
mut shape: Shape,
|
||||||
tolerance: Scalar,
|
tolerance: Scalar,
|
||||||
out: &mut Vec<Triangle>,
|
|
||||||
debug_info: &mut DebugInfo,
|
debug_info: &mut DebugInfo,
|
||||||
) {
|
) -> Mesh<Point<3>> {
|
||||||
|
let mut mesh = Mesh::new();
|
||||||
|
|
||||||
for face in shape.topology().faces() {
|
for face in shape.topology().faces() {
|
||||||
let face = face.get();
|
let face = face.get();
|
||||||
match &face {
|
match &face {
|
||||||
@ -61,20 +62,26 @@ pub fn triangulate(
|
|||||||
)
|
)
|
||||||
});
|
});
|
||||||
|
|
||||||
out.extend(triangles.into_iter().map(|triangle| {
|
for triangle in triangles {
|
||||||
let points = triangle.map(|point| point.canonical());
|
let points = triangle.map(|point| point.canonical());
|
||||||
Triangle::new(points, *color)
|
mesh.push_triangle(points, *color);
|
||||||
}));
|
|
||||||
}
|
|
||||||
Face::Triangles(triangles) => out.extend(triangles),
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Face::Triangles(triangles) => {
|
||||||
|
for triangle in triangles {
|
||||||
|
mesh.push_triangle(triangle.inner, triangle.color);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
mesh
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use fj_interop::{debug::DebugInfo, mesh::Triangle};
|
use fj_interop::{debug::DebugInfo, mesh::Mesh};
|
||||||
use fj_math::Scalar;
|
use fj_math::{Point, Scalar};
|
||||||
|
|
||||||
use crate::{geometry::Surface, shape::Shape, topology::Face};
|
use crate::{geometry::Surface, shape::Shape, topology::Face};
|
||||||
|
|
||||||
@ -92,10 +99,10 @@ mod tests {
|
|||||||
.build()?;
|
.build()?;
|
||||||
|
|
||||||
let triangles = triangulate(shape);
|
let triangles = triangulate(shape);
|
||||||
assert!(triangles.contains([a, b, d]));
|
assert!(triangles.contains_triangle([a, b, d]));
|
||||||
assert!(triangles.contains([b, c, d]));
|
assert!(triangles.contains_triangle([b, c, d]));
|
||||||
assert!(!triangles.contains([a, b, c]));
|
assert!(!triangles.contains_triangle([a, b, c]));
|
||||||
assert!(!triangles.contains([a, c, d]));
|
assert!(!triangles.contains_triangle([a, c, d]));
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
@ -123,44 +130,22 @@ mod tests {
|
|||||||
|
|
||||||
// Should contain some triangles from the polygon. Don't need to test
|
// Should contain some triangles from the polygon. Don't need to test
|
||||||
// them all.
|
// them all.
|
||||||
assert!(triangles.contains([a, e, h]));
|
assert!(triangles.contains_triangle([a, e, h]));
|
||||||
assert!(triangles.contains([a, d, h]));
|
assert!(triangles.contains_triangle([a, d, h]));
|
||||||
|
|
||||||
// Shouldn't contain any possible triangle from the hole.
|
// Shouldn't contain any possible triangle from the hole.
|
||||||
assert!(!triangles.contains([e, f, g]));
|
assert!(!triangles.contains_triangle([e, f, g]));
|
||||||
assert!(!triangles.contains([e, g, h]));
|
assert!(!triangles.contains_triangle([e, g, h]));
|
||||||
assert!(!triangles.contains([e, f, h]));
|
assert!(!triangles.contains_triangle([e, f, h]));
|
||||||
assert!(!triangles.contains([f, g, h]));
|
assert!(!triangles.contains_triangle([f, g, h]));
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn triangulate(shape: Shape) -> Triangles {
|
fn triangulate(shape: Shape) -> Mesh<Point<3>> {
|
||||||
let tolerance = Scalar::ONE;
|
let tolerance = Scalar::ONE;
|
||||||
|
|
||||||
let mut triangles = Vec::new();
|
|
||||||
let mut debug_info = DebugInfo::new();
|
let mut debug_info = DebugInfo::new();
|
||||||
|
super::triangulate(shape, tolerance, &mut debug_info)
|
||||||
super::triangulate(shape, tolerance, &mut triangles, &mut debug_info);
|
|
||||||
|
|
||||||
for triangle in &mut triangles {
|
|
||||||
*triangle = Triangle {
|
|
||||||
inner: triangle.inner.normalize(),
|
|
||||||
..*triangle
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
Triangles(triangles)
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug)]
|
|
||||||
struct Triangles(Vec<Triangle>);
|
|
||||||
|
|
||||||
impl Triangles {
|
|
||||||
fn contains(&self, triangle: impl Into<fj_math::Triangle<3>>) -> bool {
|
|
||||||
let triangle =
|
|
||||||
Triangle::new(triangle.into().normalize(), [255, 0, 0, 255]);
|
|
||||||
self.0.contains(&triangle)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user