diff --git a/editor/src/main.rs b/editor/src/main.rs index 5f69d23..ba4cb78 100644 --- a/editor/src/main.rs +++ b/editor/src/main.rs @@ -62,7 +62,7 @@ impl Default for MeshSettings { r2: 0.8, d1: Vec3::new(0.4, 0.3, 0.0), rot: 0.3, - segs: 30, + segs: 5, } } } @@ -71,7 +71,7 @@ fn make_mesh(settings: &MeshSettings) -> MeshVec3 { let mut mesh = MeshVec3::regular_star(settings.r, settings.r2, settings.n); //cuboid(1.0, 1.0, 2.0); mesh.transform( - &bevy::transform::components::Transform::from_translation(Vec3::new(0.0, -1.0, 0.0)) + &bevy::transform::components::Transform::from_translation(Vec3::new(0.0, -0.99, 0.0)) .with_rotation(Quat::from_rotation_z(PI)), ); @@ -80,6 +80,7 @@ fn make_mesh(settings: &MeshSettings) -> MeshVec3 { bevy::transform::components::Transform::from_rotation(Quat::from_rotation_y(settings.rot)) .with_translation(settings.d1), true, + true, ); for _ in 0..settings.segs { @@ -90,6 +91,7 @@ fn make_mesh(settings: &MeshSettings) -> MeshVec3 { )) .with_translation(settings.d1), true, + true, ); } diff --git a/src/representation/face/mod.rs b/src/representation/face/mod.rs index 46045a6..2ba6f88 100644 --- a/src/representation/face/mod.rs +++ b/src/representation/face/mod.rs @@ -27,6 +27,8 @@ where // No! We don't have i // a half-edge incident to each inner component of the face // inner_components: Vec, + /// whether the face is curved, i.e., not planar + curved: bool, } impl Face { @@ -49,11 +51,12 @@ impl Face { } /// Creates a new face. - pub fn new(edge: E) -> Self { + pub fn new(edge: E, curved: bool) -> Self { assert!(edge != IndexType::max()); Self { id: IndexType::max(), edge, + curved, } } @@ -82,9 +85,6 @@ impl Face { return true; } - // TODO: Ignoring planar-ness for now - return true; - // TODO: is this correct? // TODO: collinear points cause problems @@ -97,6 +97,11 @@ impl Face { }) } + /// Whether the face is allowed to be curved. + pub fn may_be_curved(&self) -> bool { + self.curved + } + /// Whether the face is planar. pub fn is_planar2(&self, mesh: &Mesh) -> bool { self.is_planar(mesh, P::S::EPS * 10.0.into()) @@ -119,7 +124,8 @@ impl Face { { // TODO: overload this in a way that allows different dimensions - assert!(self.is_planar2(mesh)); + // TODO: allows only for slight curvature... + assert!(self.may_be_curved() || self.is_planar2(mesh)); let mut normal = P::Vec::zero(); for (a, b) in self @@ -160,8 +166,6 @@ impl Face { P::Vec: Vector3D, { // TODO: overload this in a way that allows different dimensions - - assert!(self.is_planar2(mesh)); assert!(P::Vec::dimensions() == 3); let normal = self.normal(mesh); @@ -204,6 +208,7 @@ impl Default for Face { Self { id: IndexType::max(), edge: IndexType::max(), + curved: false, } } } diff --git a/src/representation/face/tesselate/mod.rs b/src/representation/face/tesselate/mod.rs index 240204a..b96b661 100644 --- a/src/representation/face/tesselate/mod.rs +++ b/src/representation/face/tesselate/mod.rs @@ -1,10 +1,9 @@ -use super::{Face, Mesh, Payload, Scalar}; +use super::{Face, Mesh, Payload}; use crate::representation::{ payload::{Vector, Vector2D, Vector3D}, IndexType, }; use itertools::Itertools; -use rand::prelude::*; use std::collections::HashMap; impl Face @@ -18,7 +17,7 @@ where mesh: &Mesh, indices: &mut Vec, ) { - assert!(self.is_planar(mesh, P::S::EPS * 10.0.into())); + assert!(self.may_be_curved() || self.is_planar2(mesh)); assert!(self.is_convex(mesh)); let center = self.vertices(mesh).next().unwrap(); @@ -41,7 +40,7 @@ where P::Vec: Vector3D, { // TODO: ear clipping is inefficient - assert!(self.is_planar(mesh, P::S::EPS * 10.0.into())); + assert!(self.may_be_curved() || self.is_planar2(mesh)); let vs: Vec<(>::Vec2D, V)> = self.vertices_2d::(mesh).collect(); @@ -108,7 +107,7 @@ where P::Vec: Vector3D, { // TODO: ear clipping is inefficient - assert!(self.is_planar(mesh, P::S::EPS * 10.0.into())); + assert!(self.may_be_curved() || self.is_planar2(mesh)); let vs: Vec<(>::Vec2D, V)> = self.vertices_2d::(mesh).collect(); @@ -229,6 +228,7 @@ where where P::Vec: Vector3D, { + // TODO: This shortens edges producing invalid meshess! let vs: Vec<(>::Vec2D, V)> = self.vertices_2d::(mesh).collect(); assert!(vs.len() == self.vertices(mesh).count()); @@ -302,7 +302,8 @@ where for _ in 1..10 { let mut local_indices = Vec::new(); self.ear_clipping_rand2(mesh, &mut local_indices); - self.shorten(mesh, &mut local_indices); + + // self.shorten(mesh, &mut local_indices); let mut dist = 0.0.into(); @@ -344,7 +345,7 @@ where mesh: &Mesh, _indices: &mut Vec, ) { - assert!(self.is_planar(mesh, P::S::EPS * 10.0.into())); + assert!(self.may_be_curved() || self.is_planar2(mesh)); diff --git a/src/representation/mesh/bevy/mod.rs b/src/representation/mesh/bevy/mod.rs index 7783b9a..0d4bdf3 100644 --- a/src/representation/mesh/bevy/mod.rs +++ b/src/representation/mesh/bevy/mod.rs @@ -62,6 +62,9 @@ where bevy::render::mesh::Mesh::ATTRIBUTE_POSITION, VertexAttributeValues::Float32x3(vertices), ); + + // mesh.duplicate_vertices(); + // mesh.compute_flat_normals(); } /// Convert the mesh to a bevy mesh diff --git a/src/representation/mesh/builder/extrude.rs b/src/representation/mesh/builder/extrude.rs index fb8e98c..3c02e01 100644 --- a/src/representation/mesh/builder/extrude.rs +++ b/src/representation/mesh/builder/extrude.rs @@ -18,6 +18,7 @@ where e, >::Transform::from_translation(direction), close, + false, ) } @@ -28,6 +29,7 @@ where e: E, transform: >::Transform, close: bool, + curved: bool, ) -> F { assert!(self.edge(e).is_boundary_self()); @@ -39,19 +41,20 @@ where let p = edges[i].origin(self).payload().transform(&transform); let curr = self.add_vertex((last, p)).0; + if i > 0 { - self.close_face((last, curr, edges[i].origin_id())); + self.close_face((last, curr, edges[i].origin_id(), curved)); } else { second = curr; } if i == edges.len() - 1 { - self.close_face((edges[i].origin_id(), curr, second)); + self.close_face((edges[i].origin_id(), curr, second, curved)); } last = curr; } if close { - return self.close_face(self.edge_id_between(second, last)); + return self.close_face((self.edge_id_between(second, last), curved)); } return IndexType::max(); @@ -70,9 +73,10 @@ where f: F, transform: >::Transform, close: bool, + curved: bool, ) -> F { let e = self.face(f).edge_id(); self.remove_face(f); - return self.extrude_ex(e, transform, close); + return self.extrude_ex(e, transform, close, curved); } } diff --git a/src/representation/mesh/builder/face.rs b/src/representation/mesh/builder/face.rs index c446caa..ecc0379 100644 --- a/src/representation/mesh/builder/face.rs +++ b/src/representation/mesh/builder/face.rs @@ -9,12 +9,14 @@ pub trait CloseFace { fn close_face(&mut self, input: Input) -> Self::FaceIndex; } -impl CloseFace for Mesh { +impl CloseFace<(E, bool)> + for Mesh +{ type FaceIndex = F; /// Close the open boundary with a single face - fn close_face(&mut self, e: E) -> F { - let f = self.faces.push(Face::new(e)); + fn close_face(&mut self, (e, curved): (E, bool)) -> F { + let f = self.faces.push(Face::new(e, curved)); self.edge(e) .clone() .edges_face_mut(self) @@ -23,11 +25,13 @@ impl CloseFace for Mesh } } -impl CloseFace<(E, E)> for Mesh { +impl CloseFace<(E, E, bool)> + for Mesh +{ type FaceIndex = F; /// Close the face by connecting `inside` with the next edge to close the face and `outside` with the next edge to complete the outside - fn close_face(&mut self, (inside, outside): (E, E)) -> F { + fn close_face(&mut self, (inside, outside, curved): (E, E, bool)) -> F { let e_inside = self.edge(inside); let e_outside = self.edge(outside); let v = e_inside.target(self).id(); @@ -58,7 +62,7 @@ impl CloseFace<(E, E)> for self.edge_mut(inside).set_next(e1); self.edge_mut(outside).set_next(e2); - let f = self.faces.push(Face::new(inside)); + let f = self.faces.push(Face::new(inside, curved)); self.edge(inside) .clone() @@ -69,13 +73,13 @@ impl CloseFace<(E, E)> for } } -impl CloseFace<(V, V, V)> +impl CloseFace<(V, V, V, bool)> for Mesh { type FaceIndex = F; /// Close the face by connecting the edge from v1 to v2 with vertex w. - fn close_face(&mut self, (prev, from, to): (V, V, V)) -> F { + fn close_face(&mut self, (prev, from, to, curved): (V, V, V, bool)) -> F { let inside = self.edge_between(prev, from).unwrap().id(); assert!( @@ -95,6 +99,6 @@ impl CloseFace<(V, V, V)> .unwrap() .id(); - return self.close_face((inside, outside)); + return self.close_face((inside, outside, curved)); } } diff --git a/src/representation/mesh/primitives/cuboid.rs b/src/representation/mesh/primitives/cuboid.rs index 6b0d988..739de13 100644 --- a/src/representation/mesh/primitives/cuboid.rs +++ b/src/representation/mesh/primitives/cuboid.rs @@ -20,16 +20,16 @@ where let (v0, v1) = mesh.add_isolated_edge(make(x, y, z), make(-x, y, z)); let v2 = mesh.add_vertex((v1, make(-x, -y, z))).0; let v3 = mesh.add_vertex((v2, make(x, -y, z))).0; - mesh.close_face((v2, v3, v0)); + mesh.close_face((v2, v3, v0, false)); let v4 = mesh.add_vertex((v1, make(-x, y, -z))).0; let v5 = mesh.add_vertex((v4, make(-x, -y, -z))).0; - mesh.close_face((v4, v5, v2)); + mesh.close_face((v4, v5, v2, false)); let v6 = mesh.add_vertex((v0, make(x, y, -z))).0; let v7 = mesh.add_vertex((v3, make(x, -y, -z))).0; - mesh.close_face((v3, v7, v6)); - mesh.close_face((v2, v5, v7)); - mesh.close_face((v0, v6, v4)); - mesh.close_face(mesh.edge_between(v6, v7).unwrap().id()); + mesh.close_face((v3, v7, v6, false)); + mesh.close_face((v2, v5, v7, false)); + mesh.close_face((v0, v6, v4, false)); + mesh.close_face((mesh.edge_between(v6, v7).unwrap().id(), false)); mesh } } diff --git a/src/representation/mesh/primitives/regular_polygon.rs b/src/representation/mesh/primitives/regular_polygon.rs index 208c107..becd637 100644 --- a/src/representation/mesh/primitives/regular_polygon.rs +++ b/src/representation/mesh/primitives/regular_polygon.rs @@ -58,7 +58,7 @@ where .0; } - mesh.close_face((prev, current, v0)); + mesh.close_face((prev, current, v0, false)); mesh } diff --git a/src/representation/vertex/payload/bevy.rs b/src/representation/vertex/payload/bevy.rs index 2561ca7..9ad5025 100644 --- a/src/representation/vertex/payload/bevy.rs +++ b/src/representation/vertex/payload/bevy.rs @@ -194,11 +194,6 @@ impl Transform for bevy::transform::components::Transform { bevy::transform::components::Transform::default() } - #[inline(always)] - fn from_axis_angle(axis: Vec3, angle: f32) -> Self { - bevy::transform::components::Transform::from_rotation(Quat::from_axis_angle(axis, angle)) - } - #[inline(always)] fn from_rotation_arc(from: Vec3, to: Vec3) -> Self { assert!((from.length() - 1.0).abs() < 0.01); @@ -243,14 +238,9 @@ impl Transform for Affine2 { Affine2::IDENTITY } - #[inline(always)] - fn from_axis_angle(axis: Vec2, angle: f32) -> Self { - bevy::math::Affine2::from_axis_angle(axis, angle) - } - #[inline(always)] fn from_rotation_arc(from: Vec2, to: Vec2) -> Self { - bevy::math::Affine2::from_rotation_arc(from, to) + bevy::math::Affine2::from_angle(from.angle_between(to)) } #[inline(always)] diff --git a/src/representation/vertex/payload/vector.rs b/src/representation/vertex/payload/vector.rs index 2ed6f23..6aa4311 100644 --- a/src/representation/vertex/payload/vector.rs +++ b/src/representation/vertex/payload/vector.rs @@ -39,6 +39,7 @@ pub trait Scalar: /// Returns the arcus cosine of the scalar. fn acos(self) -> Self; + /// Returns the determinant of a 3x3 matrix. fn det3( a: Self, b: Self, @@ -106,9 +107,6 @@ pub trait Transform: Clone + Copy + Default + std::fmt::Debug + 'static { /// Returns the identity rotation. fn identity() -> Self; - /// Returns a rotation from an axis and an angle. - fn from_axis_angle(axis: Self::Vec, angle: Self::S) -> Self; - /// Returns a rotation from a rotation arc. fn from_rotation_arc(from: Self::Vec, to: Self::Vec) -> Self;