Merge pull request #457 from hannobraun/triangle

Add `fj_interop::mesh::Triangle`
This commit is contained in:
Hanno Braun 2022-04-12 13:03:26 +02:00 committed by GitHub
commit e24a66456f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
9 changed files with 71 additions and 45 deletions

View File

@ -1,6 +1,7 @@
use std::f64::consts::FRAC_PI_2; use std::f64::consts::FRAC_PI_2;
use fj_math::{Aabb, Scalar, Triangle}; use fj_interop::mesh::Triangle;
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 _};
use winit::dpi::PhysicalPosition; use winit::dpi::PhysicalPosition;
@ -130,7 +131,7 @@ impl Camera {
&self, &self,
window: &Window, window: &Window,
cursor: Option<PhysicalPosition<f64>>, cursor: Option<PhysicalPosition<f64>>,
triangles: &[Triangle<3>], triangles: &[Triangle],
) -> FocusPoint { ) -> FocusPoint {
let cursor = match cursor { let cursor = match cursor {
Some(cursor) => cursor, Some(cursor) => cursor,
@ -147,10 +148,11 @@ impl Camera {
let mut min_t = None; let mut min_t = None;
for triangle in triangles { for triangle in triangles {
let t = let t = triangle.inner.to_parry().cast_local_ray(
triangle &ray,
.to_parry() f64::INFINITY,
.cast_local_ray(&ray, f64::INFINITY, true); true,
);
if let Some(t) = t { if let Some(t) = t {
if t <= min_t.unwrap_or(t) { if t <= min_t.unwrap_or(t) {

View File

@ -1,9 +1,8 @@
use bytemuck::{Pod, Zeroable}; use bytemuck::{Pod, Zeroable};
use fj_interop::{ use fj_interop::{
debug::DebugInfo, debug::DebugInfo,
mesh::{Index, Mesh}, mesh::{Index, Mesh, Triangle},
}; };
use fj_math::Triangle;
use nalgebra::{vector, Point}; use nalgebra::{vector, Point};
#[derive(Debug)] #[derive(Debug)]
@ -67,15 +66,15 @@ impl Vertices {
} }
} }
impl From<&Vec<Triangle<3>>> for Vertices { impl From<&Vec<Triangle>> for Vertices {
fn from(triangles: &Vec<Triangle<3>>) -> Self { fn from(triangles: &Vec<Triangle>) -> Self {
let mut mesh = Mesh::new(); let mut mesh = Mesh::new();
for triangle in triangles { for triangle in triangles {
let [a, b, c] = triangle.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)); mesh.push((a, normal, color));
mesh.push((b, normal, color)); mesh.push((b, normal, color));

View File

@ -1,6 +1,6 @@
use std::time::Instant; use std::time::Instant;
use fj_math::Triangle; use fj_interop::mesh::Triangle;
use winit::{ use winit::{
dpi::PhysicalPosition, dpi::PhysicalPosition,
event::{ event::{
@ -121,7 +121,7 @@ impl Handler {
now: Instant, now: Instant,
camera: &mut Camera, camera: &mut Camera,
window: &Window, window: &Window,
triangles: &[Triangle<3>], triangles: &[Triangle],
) { ) {
let focus_point = camera.focus_point(window, self.cursor, triangles); let focus_point = camera.focus_point(window, self.cursor, triangles);

View File

@ -9,10 +9,10 @@ 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::debug::DebugInfo; use fj_interop::mesh::Triangle;
use fj_interop::mesh::Mesh; use fj_interop::{debug::DebugInfo, mesh::Mesh};
use fj_kernel::algorithms::triangulate; use fj_kernel::algorithms::triangulate;
use fj_math::{Aabb, Scalar, Triangle}; use fj_math::{Aabb, 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};
@ -88,7 +88,7 @@ fn main() -> anyhow::Result<()> {
let mut mesh_maker = Mesh::new(); let mut mesh_maker = Mesh::new();
for triangle in shape.triangles { for triangle in shape.triangles {
for vertex in triangle.points() { for vertex in triangle.inner.points() {
mesh_maker.push(vertex); mesh_maker.push(vertex);
} }
} }
@ -310,7 +310,7 @@ impl ShapeProcessor {
struct ProcessedShape { struct ProcessedShape {
aabb: Aabb<3>, aabb: Aabb<3>,
triangles: Vec<Triangle<3>>, triangles: Vec<Triangle>,
debug_info: DebugInfo, debug_info: DebugInfo,
} }

View File

@ -56,3 +56,26 @@ impl<V> Default for Mesh<V> {
/// An index that refers to a vertex in a mesh /// An index that refers to a vertex in a mesh
pub type Index = u32; pub type Index = u32;
/// A triangle
///
/// Extension of [`fj_math::Triangle`] that also includes a color.
#[derive(Clone, Copy, Debug, Eq, PartialEq, Ord, PartialOrd)]
pub struct Triangle {
/// The non-color part of the triangle
pub inner: fj_math::Triangle<3>,
/// The color of the triangle
pub color: Color,
}
impl Triangle {
/// Construct a new instance of `Triangle`
pub fn new(inner: impl Into<fj_math::Triangle<3>>, color: Color) -> Self {
let inner = inner.into();
Self { inner, color }
}
}
/// RGBA color
pub type Color = [u8; 4];

View File

@ -1,6 +1,7 @@
use std::collections::HashMap; use std::collections::HashMap;
use fj_math::{Scalar, Transform, Triangle, Vector}; use fj_interop::mesh::Triangle;
use fj_math::{Scalar, Transform, Vector};
use crate::{ use crate::{
geometry::{Surface, SweptCurve}, geometry::{Surface, SweptCurve},
@ -149,16 +150,10 @@ pub fn sweep_shape(
quads.push([v0, v1, v2, v3]); quads.push([v0, v1, v2, v3]);
} }
let mut side_face: Vec<Triangle<3>> = Vec::new(); let mut side_face: Vec<Triangle> = Vec::new();
for [v0, v1, v2, v3] in quads { for [v0, v1, v2, v3] in quads {
side_face.push([v0, v1, v2].into()); side_face.push(Triangle::new([v0, v1, v2], color));
side_face.push([v0, v2, v3].into()); side_face.push(Triangle::new([v0, v2, v3], color));
}
// FIXME: We probably want to allow the use of custom colors for the
// "walls" of the swept object.
for s in side_face.iter_mut() {
s.set_color(color);
} }
target.insert(Face::Triangles(side_face)).unwrap(); target.insert(Face::Triangles(side_face)).unwrap();

View File

@ -2,8 +2,8 @@ mod delaunay;
mod polygon; mod polygon;
mod ray; mod ray;
use fj_interop::debug::DebugInfo; use fj_interop::{debug::DebugInfo, mesh::Triangle};
use fj_math::{Scalar, Triangle}; use fj_math::Scalar;
use crate::{shape::Shape, topology::Face}; use crate::{shape::Shape, topology::Face};
@ -15,7 +15,7 @@ use super::FaceApprox;
pub fn triangulate( pub fn triangulate(
mut shape: Shape, mut shape: Shape,
tolerance: Scalar, tolerance: Scalar,
out: &mut Vec<Triangle<3>>, out: &mut Vec<Triangle>,
debug_info: &mut DebugInfo, debug_info: &mut DebugInfo,
) { ) {
for face in shape.topology().faces() { for face in shape.topology().faces() {
@ -62,10 +62,8 @@ pub fn triangulate(
}); });
out.extend(triangles.into_iter().map(|triangle| { out.extend(triangles.into_iter().map(|triangle| {
let [a, b, c] = triangle.map(|point| point.canonical()); let points = triangle.map(|point| point.canonical());
let mut t = Triangle::from([a, b, c]); Triangle::new(points, *color)
t.set_color(*color);
t
})); }));
} }
Face::Triangles(triangles) => out.extend(triangles), Face::Triangles(triangles) => out.extend(triangles),
@ -75,8 +73,8 @@ pub fn triangulate(
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use fj_interop::debug::DebugInfo; use fj_interop::{debug::DebugInfo, mesh::Triangle};
use fj_math::{Scalar, Triangle}; use fj_math::Scalar;
use crate::{geometry::Surface, shape::Shape, topology::Face}; use crate::{geometry::Surface, shape::Shape, topology::Face};
@ -146,17 +144,22 @@ mod tests {
super::triangulate(shape, tolerance, &mut triangles, &mut debug_info); super::triangulate(shape, tolerance, &mut triangles, &mut debug_info);
for triangle in &mut triangles { for triangle in &mut triangles {
*triangle = triangle.normalize(); *triangle = Triangle {
inner: triangle.inner.normalize(),
..*triangle
};
} }
Triangles(triangles) Triangles(triangles)
} }
struct Triangles(Vec<Triangle<3>>); #[derive(Debug)]
struct Triangles(Vec<Triangle>);
impl Triangles { impl Triangles {
fn contains(&self, triangle: impl Into<Triangle<3>>) -> bool { fn contains(&self, triangle: impl Into<fj_math::Triangle<3>>) -> bool {
let triangle = triangle.into().normalize(); let triangle =
Triangle::new(triangle.into().normalize(), [255, 0, 0, 255]);
self.0.contains(&triangle) self.0.contains(&triangle)
} }
} }

View File

@ -1,3 +1,4 @@
use fj_interop::mesh::Triangle;
use fj_math::{Point, Transform}; use fj_math::{Point, Transform};
use crate::{ use crate::{
@ -45,7 +46,10 @@ impl Geometry<'_> {
use std::ops::DerefMut as _; use std::ops::DerefMut as _;
if let Face::Triangles(triangles) = face.deref_mut() { if let Face::Triangles(triangles) = face.deref_mut() {
for triangle in triangles { for triangle in triangles {
*triangle = transform.transform_triangle(triangle); *triangle = Triangle {
inner: transform.transform_triangle(&triangle.inner),
..*triangle
};
} }
} }
}); });

View File

@ -1,6 +1,6 @@
use std::hash::{Hash, Hasher}; use std::hash::{Hash, Hasher};
use fj_math::Triangle; use fj_interop::mesh::Triangle;
use crate::{ use crate::{
geometry::Surface, geometry::Surface,
@ -61,7 +61,7 @@ pub enum Face {
/// The plan is to eventually represent faces as a geometric surface, /// The plan is to eventually represent faces as a geometric surface,
/// bounded by edges. While the transition is being made, this variant is /// bounded by edges. While the transition is being made, this variant is
/// still required. /// still required.
Triangles(Vec<Triangle<3>>), Triangles(Vec<Triangle>),
} }
impl Face { impl Face {