Skip to content

Commit

Permalink
allow curved faces
Browse files Browse the repository at this point in the history
  • Loading branch information
Agapanthus committed Mar 5, 2024
1 parent 981c7c1 commit 485859d
Show file tree
Hide file tree
Showing 10 changed files with 57 additions and 50 deletions.
6 changes: 4 additions & 2 deletions editor/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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,
}
}
}
Expand All @@ -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)),
);

Expand All @@ -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 {
Expand All @@ -90,6 +91,7 @@ fn make_mesh(settings: &MeshSettings) -> MeshVec3 {
))
.with_translation(settings.d1),
true,
true,
);
}

Expand Down
19 changes: 12 additions & 7 deletions src/representation/face/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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<EdgeIndex>,
/// whether the face is curved, i.e., not planar
curved: bool,
}

impl<E: IndexType, F: IndexType> Face<E, F> {
Expand All @@ -49,11 +51,12 @@ impl<E: IndexType, F: IndexType> Face<E, F> {
}

/// 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,
}
}

Expand Down Expand Up @@ -82,9 +85,6 @@ impl<E: IndexType, F: IndexType> Face<E, F> {
return true;
}

// TODO: Ignoring planar-ness for now
return true;

// TODO: is this correct?
// TODO: collinear points cause problems

Expand All @@ -97,6 +97,11 @@ impl<E: IndexType, F: IndexType> Face<E, F> {
})
}

/// 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<V: IndexType, P: Payload>(&self, mesh: &Mesh<E, V, F, P>) -> bool {
self.is_planar(mesh, P::S::EPS * 10.0.into())
Expand All @@ -119,7 +124,8 @@ impl<E: IndexType, F: IndexType> Face<E, F> {
{
// 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
Expand Down Expand Up @@ -160,8 +166,6 @@ impl<E: IndexType, F: IndexType> Face<E, F> {
P::Vec: Vector3D<P::S>,
{
// 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);
Expand Down Expand Up @@ -204,6 +208,7 @@ impl<E: IndexType, F: IndexType> Default for Face<E, F> {
Self {
id: IndexType::max(),
edge: IndexType::max(),
curved: false,
}
}
}
15 changes: 8 additions & 7 deletions src/representation/face/tesselate/mod.rs
Original file line number Diff line number Diff line change
@@ -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<E, F> Face<E, F>
Expand All @@ -18,7 +17,7 @@ where
mesh: &Mesh<E, V, F, P>,
indices: &mut Vec<V>,
) {
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();
Expand All @@ -41,7 +40,7 @@ where
P::Vec: Vector3D<P::S>,
{
// 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<(<P::Vec as Vector<P::S>>::Vec2D, V)> =
self.vertices_2d::<V, P>(mesh).collect();
Expand Down Expand Up @@ -108,7 +107,7 @@ where
P::Vec: Vector3D<P::S>,
{
// 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<(<P::Vec as Vector<P::S>>::Vec2D, V)> =
self.vertices_2d::<V, P>(mesh).collect();
Expand Down Expand Up @@ -229,6 +228,7 @@ where
where
P::Vec: Vector3D<P::S>,
{
// TODO: This shortens edges producing invalid meshess!
let vs: Vec<(<P::Vec as Vector<P::S>>::Vec2D, V)> =
self.vertices_2d::<V, P>(mesh).collect();
assert!(vs.len() == self.vertices(mesh).count());
Expand Down Expand Up @@ -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();

Expand Down Expand Up @@ -344,7 +345,7 @@ where
mesh: &Mesh<E, V, F, P>,
_indices: &mut Vec<V>,
) {
assert!(self.is_planar(mesh, P::S::EPS * 10.0.into()));
assert!(self.may_be_curved() || self.is_planar2(mesh));
Expand Down
3 changes: 3 additions & 0 deletions src/representation/mesh/bevy/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
12 changes: 8 additions & 4 deletions src/representation/mesh/builder/extrude.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ where
e,
<P::Vec as Vector<P::S>>::Transform::from_translation(direction),
close,
false,
)
}

Expand All @@ -28,6 +29,7 @@ where
e: E,
transform: <P::Vec as Vector<P::S>>::Transform,
close: bool,
curved: bool,
) -> F {
assert!(self.edge(e).is_boundary_self());

Expand All @@ -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();
Expand All @@ -70,9 +73,10 @@ where
f: F,
transform: <P::Vec as Vector<P::S>>::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);
}
}
22 changes: 13 additions & 9 deletions src/representation/mesh/builder/face.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,12 +9,14 @@ pub trait CloseFace<Input> {
fn close_face(&mut self, input: Input) -> Self::FaceIndex;
}

impl<E: IndexType, V: IndexType, F: IndexType, P: Payload> CloseFace<E> for Mesh<E, V, F, P> {
impl<E: IndexType, V: IndexType, F: IndexType, P: Payload> CloseFace<(E, bool)>
for Mesh<E, V, F, P>
{
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)
Expand All @@ -23,11 +25,13 @@ impl<E: IndexType, V: IndexType, F: IndexType, P: Payload> CloseFace<E> for Mesh
}
}

impl<E: IndexType, V: IndexType, F: IndexType, P: Payload> CloseFace<(E, E)> for Mesh<E, V, F, P> {
impl<E: IndexType, V: IndexType, F: IndexType, P: Payload> CloseFace<(E, E, bool)>
for Mesh<E, V, F, P>
{
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();
Expand Down Expand Up @@ -58,7 +62,7 @@ impl<E: IndexType, V: IndexType, F: IndexType, P: Payload> 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()
Expand All @@ -69,13 +73,13 @@ impl<E: IndexType, V: IndexType, F: IndexType, P: Payload> CloseFace<(E, E)> for
}
}

impl<E: IndexType, V: IndexType, F: IndexType, P: Payload> CloseFace<(V, V, V)>
impl<E: IndexType, V: IndexType, F: IndexType, P: Payload> CloseFace<(V, V, V, bool)>
for Mesh<E, V, F, P>
{
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!(
Expand All @@ -95,6 +99,6 @@ impl<E: IndexType, V: IndexType, F: IndexType, P: Payload> CloseFace<(V, V, V)>
.unwrap()
.id();

return self.close_face((inside, outside));
return self.close_face((inside, outside, curved));
}
}
12 changes: 6 additions & 6 deletions src/representation/mesh/primitives/cuboid.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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
}
}
2 changes: 1 addition & 1 deletion src/representation/mesh/primitives/regular_polygon.rs
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ where
.0;
}

mesh.close_face((prev, current, v0));
mesh.close_face((prev, current, v0, false));

mesh
}
Expand Down
12 changes: 1 addition & 11 deletions src/representation/vertex/payload/bevy.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down Expand Up @@ -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)]
Expand Down
4 changes: 1 addition & 3 deletions src/representation/vertex/payload/vector.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down Expand Up @@ -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;

Expand Down

0 comments on commit 485859d

Please sign in to comment.