Make Transform struct
This commit is contained in:
parent
e26b528464
commit
84711d67c0
@ -16,8 +16,6 @@
|
||||
|
||||
- Elegance & succinctness (my recent closure work may help with this):
|
||||
- Why must I repeat myself so much in these definitions?
|
||||
- The notation for transforms is really cumbersome. Some syntactic
|
||||
sugar might go far.
|
||||
- What patterns can I factor out? I do some things regularly, like:
|
||||
the clockwise boundaries, the zigzag connections, the iterating over
|
||||
a `Vec<Vertex>` to transform each element and make another vector.
|
||||
|
||||
@ -2,7 +2,8 @@ use std::rc::Rc;
|
||||
use nalgebra::*;
|
||||
//pub mod examples;
|
||||
|
||||
use crate::openmesh::{OpenMesh, Mat4, vertex, transform};
|
||||
use crate::openmesh::{OpenMesh};
|
||||
use crate::xform::{Transform, vertex};
|
||||
use crate::rule::{Rule, RuleFn, RuleEval, Child};
|
||||
use crate::prim;
|
||||
use crate::util;
|
||||
@ -16,19 +17,18 @@ fn cube_thing() -> Rule {
|
||||
let z = &Vector3::z_axis();
|
||||
|
||||
// Each element of this turns to a branch for the recursion:
|
||||
let turns: Vec<Mat4> = vec![
|
||||
geometry::Transform3::identity().to_homogeneous(),
|
||||
geometry::Rotation3::from_axis_angle(y, qtr).to_homogeneous(),
|
||||
geometry::Rotation3::from_axis_angle(y, qtr * 2.0).to_homogeneous(),
|
||||
geometry::Rotation3::from_axis_angle(y, qtr * 3.0).to_homogeneous(),
|
||||
geometry::Rotation3::from_axis_angle(z, qtr).to_homogeneous(),
|
||||
geometry::Rotation3::from_axis_angle(z, -qtr).to_homogeneous(),
|
||||
let id = Transform::new();
|
||||
let turns: Vec<Transform> = vec![
|
||||
id.clone(),
|
||||
id.rotate(y, qtr),
|
||||
id.rotate(y, qtr * 2.0),
|
||||
id.rotate(y, qtr * 3.0),
|
||||
id.rotate(z, qtr),
|
||||
id.rotate(z, -qtr),
|
||||
];
|
||||
|
||||
let gen_xform = |rot: &Mat4| -> Mat4 {
|
||||
(rot *
|
||||
Matrix4::new_scaling(0.5) *
|
||||
geometry::Translation3::new(6.0, 0.0, 0.0).to_homogeneous())
|
||||
let gen_xform = |rot: &Transform| -> Transform {
|
||||
rot.scale(0.5).translate(6.0, 0.0, 0.0)
|
||||
};
|
||||
|
||||
let rec = move |self_: Rc<Rule>| -> RuleEval {
|
||||
@ -367,13 +367,13 @@ impl RamHorn {
|
||||
fn twist(f: f32, subdiv: usize) -> Rule {
|
||||
// TODO: Clean this code up. It was a very naive conversion from
|
||||
// the non-closure version.
|
||||
let xf = geometry::Rotation3::from_axis_angle(&Vector3::x_axis(), -0.7).to_homogeneous();
|
||||
let xf = Transform::new().rotate(&Vector3::x_axis(), -0.7);
|
||||
let seed = {
|
||||
let s = vec![vertex(-0.5, 0.0, -0.5),
|
||||
vertex( 0.5, 0.0, -0.5),
|
||||
vertex( 0.5, 0.0, 0.5),
|
||||
vertex(-0.5, 0.0, 0.5)];
|
||||
util::subdivide_cycle(&transform(&s, &xf), subdiv)
|
||||
util::subdivide_cycle(&xf.transform(&s), subdiv)
|
||||
};
|
||||
let n = seed.len();
|
||||
let dx0: f32 = 1.5;
|
||||
@ -385,19 +385,14 @@ fn twist(f: f32, subdiv: usize) -> Rule {
|
||||
let qtr = std::f32::consts::FRAC_PI_2;
|
||||
let y = Vector3::y_axis();
|
||||
|
||||
let incr_inner = geometry::Translation3::new(-dx0, 0.0, 0.0).to_homogeneous() *
|
||||
geometry::Rotation3::from_axis_angle(&y, ang).to_homogeneous() *
|
||||
geometry::Translation3::new(dx0, dy, 0.0).to_homogeneous();
|
||||
let incr_outer = geometry::Translation3::new(-dx0*2.0, 0.0, 0.0).to_homogeneous() *
|
||||
geometry::Rotation3::from_axis_angle(&y, ang/2.0).to_homogeneous() *
|
||||
geometry::Translation3::new(dx0*2.0, dy, 0.0).to_homogeneous();
|
||||
// TODO: Cleanliness fix - transforms?
|
||||
let incr_inner = Transform::new().translate(-dx0, 0.0, 0.0).rotate(&y, ang).translate(dx0, dy, 0.0);
|
||||
let incr_outer = Transform::new().translate(-dx0*2.0, 0.0, 0.0).rotate(&y, ang/2.0).translate(dx0*2.0, dy, 0.0);
|
||||
|
||||
let seed2 = seed.clone();
|
||||
// TODO: Why do I need the above?
|
||||
let recur = move |incr: Mat4| -> RuleFn {
|
||||
let recur = move |incr: Transform| -> RuleFn {
|
||||
|
||||
let seed_next = transform(&seed2, &incr);
|
||||
let seed_next = incr.transform(&seed2);
|
||||
|
||||
// TODO: Cleanliness fix - utility function to make a zigzag mesh?
|
||||
let geom = OpenMesh {
|
||||
@ -437,11 +432,9 @@ fn twist(f: f32, subdiv: usize) -> Rule {
|
||||
|
||||
let start = move |_| -> RuleEval {
|
||||
|
||||
let xform = |dx, i, ang0, div| -> Mat4 {
|
||||
(geometry::Rotation3::from_axis_angle(&y, ang0 + (qtr / div * (i as f32))).to_homogeneous() *
|
||||
geometry::Translation3::new(dx, 0.0, 0.0).to_homogeneous())
|
||||
let xform = |dx, i, ang0, div| -> Transform {
|
||||
Transform::new().rotate(&y, ang0 + (qtr / div * (i as f32))).translate(dx, 0.0, 0.0)
|
||||
};
|
||||
// TODO: Cleanliness fix - transforms?
|
||||
|
||||
let make_child = |incr, xform| -> (OpenMesh, Child) {
|
||||
|
||||
@ -452,7 +445,7 @@ fn twist(f: f32, subdiv: usize) -> Rule {
|
||||
vmap: (0..(n+1)).collect(),
|
||||
// N.B. n+1, not n. the +1 is for the centroid below.
|
||||
};
|
||||
let mut vs = transform(&seed, &xform);
|
||||
let mut vs = xform.transform(&seed);
|
||||
// and in the process, generate faces for these seeds:
|
||||
let (centroid, f) = util::connect_convex(&vs, false);
|
||||
vs.push(centroid);
|
||||
|
||||
@ -3,6 +3,7 @@ pub mod openmesh;
|
||||
pub mod rule;
|
||||
pub mod prim;
|
||||
pub mod util;
|
||||
pub mod xform;
|
||||
|
||||
//pub use crate::examples;
|
||||
//pub use crate::openmesh::test_thing;
|
||||
|
||||
@ -1,24 +1,8 @@
|
||||
//pub mod openmesh;
|
||||
|
||||
use nalgebra::*;
|
||||
use std::fs::OpenOptions;
|
||||
use std::io;
|
||||
use std::borrow::Borrow;
|
||||
|
||||
/// A type for mesh vertices. Initialize with [vertex][self::vertex].
|
||||
pub type Vertex = Vector4<f32>;
|
||||
/// A type for homogeneous transforms
|
||||
pub type Mat4 = Matrix4<f32>;
|
||||
|
||||
/// Initializes a vertex:
|
||||
pub fn vertex(x: f32, y: f32, z: f32) -> Vertex {
|
||||
Vertex::new(x, y, z, 1.0)
|
||||
}
|
||||
|
||||
/// Transforms a vector of vertices:
|
||||
pub fn transform(verts: &Vec<Vertex>, xf: &Mat4) -> Vec<Vertex> {
|
||||
verts.iter().map(|v| xf * v).collect()
|
||||
}
|
||||
use crate::xform::{Vertex, Transform};
|
||||
|
||||
/// A type for a 'tagged' vertex index referring either to an index of
|
||||
/// a mesh, or of its parent.
|
||||
@ -81,9 +65,9 @@ impl OpenMesh {
|
||||
}
|
||||
|
||||
/// Returns a new `OpenMesh` whose vertices have been transformed.
|
||||
pub fn transform(&self, xfm: &Mat4) -> OpenMesh {
|
||||
pub fn transform(&self, xfm: &Transform) -> OpenMesh {
|
||||
OpenMesh {
|
||||
verts: self.verts.iter().map(|v| xfm * v).collect(),
|
||||
verts: xfm.transform(&self.verts),
|
||||
// TODO: Is the above faster if I pack vectors into a
|
||||
// bigger matrix, and transform that?
|
||||
faces: self.faces.clone(), // TODO: Use Rc?
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
use nalgebra::*;
|
||||
use crate::openmesh::{OpenMesh, Tag, vertex};
|
||||
use crate::openmesh::{OpenMesh, Tag};
|
||||
use crate::xform::{vertex, Transform};
|
||||
|
||||
/// Returns an empty mesh (no vertices, no faces).
|
||||
pub fn empty_mesh() -> OpenMesh {
|
||||
@ -36,5 +36,5 @@ pub fn cube() -> OpenMesh {
|
||||
Tag::Body(0), Tag::Body(1), Tag::Body(5),
|
||||
Tag::Body(0), Tag::Body(5), Tag::Body(4),
|
||||
],
|
||||
}.transform(&geometry::Translation3::new(-0.5, -0.5, -0.5).to_homogeneous())
|
||||
}.transform(&Transform::new().translate(-0.5, -0.5, -0.5))
|
||||
}
|
||||
|
||||
@ -1,4 +1,5 @@
|
||||
use crate::openmesh::{OpenMesh, Tag, Mat4};
|
||||
use crate::openmesh::{OpenMesh, Tag};
|
||||
use crate::xform::{Transform};
|
||||
//use crate::prim;
|
||||
use std::borrow::Borrow;
|
||||
use std::rc::Rc;
|
||||
@ -62,7 +63,7 @@ pub struct Child {
|
||||
/// The transform to apply to all geometry produced by `rule`
|
||||
/// (including its own `geom` and `final_geom` if needed, as well
|
||||
/// as all sub-geometry produced recursively).
|
||||
pub xf: Mat4,
|
||||
pub xf: Transform,
|
||||
|
||||
/// The parent vertex mapping: a mapping to apply to turn a
|
||||
/// Tag::Parent vertex reference into a vertex index of the parent
|
||||
@ -127,7 +128,7 @@ impl Rule {
|
||||
next: usize,
|
||||
// World transform of the *parent* of 'rules', that is,
|
||||
// not including any transform of any element of 'rules'.
|
||||
xf: Mat4,
|
||||
xf: Transform,
|
||||
// How many levels 'deeper' can we recurse?
|
||||
depth: usize,
|
||||
}
|
||||
@ -143,7 +144,7 @@ impl Rule {
|
||||
let mut stack: Vec<State> = vec![State {
|
||||
rules: eval.children,
|
||||
next: 0,
|
||||
xf: nalgebra::geometry::Transform3::identity().to_homogeneous(),
|
||||
xf: Transform::new(),
|
||||
depth: max_depth,
|
||||
}];
|
||||
let mut geom = eval.geom;
|
||||
|
||||
@ -1,4 +1,5 @@
|
||||
use crate::openmesh::{Tag, Vertex};
|
||||
use crate::openmesh::{Tag};
|
||||
use crate::xform::{Vertex};
|
||||
//use crate::rule::{Rule, Child};
|
||||
|
||||
/// Linearly subdivides a list of points that are to be treated as a
|
||||
|
||||
67
src/xform.rs
Normal file
67
src/xform.rs
Normal file
@ -0,0 +1,67 @@
|
||||
use nalgebra::*;
|
||||
use std::ops::Mul;
|
||||
|
||||
/// A type for mesh vertices. Initialize with [vertex][self::vertex].
|
||||
pub type Vertex = Vector4<f32>;
|
||||
/// A type for homogeneous transforms
|
||||
pub type Mat4 = Matrix4<f32>;
|
||||
|
||||
#[derive(Clone, Copy)]
|
||||
pub struct Transform {
|
||||
pub mtx: Mat4,
|
||||
}
|
||||
|
||||
/// Initializes a vertex:
|
||||
pub fn vertex(x: f32, y: f32, z: f32) -> Vertex {
|
||||
Vertex::new(x, y, z, 1.0)
|
||||
}
|
||||
|
||||
impl Transform {
|
||||
|
||||
pub fn new() -> Transform {
|
||||
Transform {
|
||||
mtx: geometry::Transform3::identity().to_homogeneous(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn rotate(&self, axis: &Unit<Vector3<f32>>, angle: f32) -> Transform {
|
||||
Transform {
|
||||
mtx: self.mtx * Matrix4::from_axis_angle(axis, angle),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn translate(&self, x: f32, y: f32, z: f32) -> Transform {
|
||||
let xf = geometry::Translation3::new(x, y, z);
|
||||
Transform {
|
||||
mtx: self.mtx * xf.to_homogeneous(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn scale(&self, f: f32) -> Transform {
|
||||
let xf = Matrix4::new_scaling(f);
|
||||
Transform {
|
||||
mtx: self.mtx * xf,
|
||||
}
|
||||
}
|
||||
|
||||
/// Transforms a vector of vertices:
|
||||
pub fn transform(&self, verts: &Vec<Vertex>) -> Vec<Vertex> {
|
||||
verts.iter().map(|v| self.mtx * v).collect()
|
||||
}
|
||||
}
|
||||
|
||||
impl Mul for Transform {
|
||||
type Output = Self;
|
||||
fn mul(self, rhs: Self) -> Self {
|
||||
Transform { mtx: self.mtx * rhs.mtx }
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
impl<'a> Mul for &'a Transform {
|
||||
type Output = Self;
|
||||
fn mul(self, rhs: Self) -> Self {
|
||||
&Transform { mtx: self.mtx * rhs.mtx }
|
||||
}
|
||||
}
|
||||
*/
|
||||
Loading…
x
Reference in New Issue
Block a user