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