Some nalgebra dabbling
This commit is contained in:
parent
637c5810b8
commit
81aefd4a7c
@ -9,3 +9,4 @@ edition = "2018"
|
|||||||
[dependencies]
|
[dependencies]
|
||||||
tri-mesh = "0.4.0"
|
tri-mesh = "0.4.0"
|
||||||
euclid = "0.20.7"
|
euclid = "0.20.7"
|
||||||
|
nalgebra = "0.19.0"
|
||||||
|
|||||||
@ -1,5 +1,8 @@
|
|||||||
- `curve_horn_*`: actually *combine* geometry properly.
|
- `curve_horn_*`: actually *combine* geometry properly.
|
||||||
|
|
||||||
|
- https://docs.rs/nalgebra/0.19.0/nalgebra/geometry/struct.Translation.html#method.prepend_translation -
|
||||||
|
see this for how to create Matrix4 from a translation
|
||||||
|
|
||||||
- Look at everything in README.md in automata_scratch.
|
- Look at everything in README.md in automata_scratch.
|
||||||
- Implement some of the tougher examples from the above too, e.g. the
|
- Implement some of the tougher examples from the above too, e.g. the
|
||||||
triple nested spiral
|
triple nested spiral
|
||||||
|
|||||||
93
src/main.rs
93
src/main.rs
@ -1,5 +1,83 @@
|
|||||||
//use std::io;
|
//use std::io;
|
||||||
use tri_mesh::prelude::*;
|
use tri_mesh::prelude::*;
|
||||||
|
use nalgebra::base::dimension::{U1, U4};
|
||||||
|
//use nalgebra::Matrix4;
|
||||||
|
|
||||||
|
/// A type for custom mesh vertices. Initialize with [vertex][self::vertex].
|
||||||
|
pub type Vertex = nalgebra::Matrix<f32, U4, U1, nalgebra::ArrayStorage<f32, U4, U1>>;
|
||||||
|
// TODO: Why am I not just using nalgebra's RowVector type here?
|
||||||
|
|
||||||
|
/// Initializes a vertex for a custom mesh.
|
||||||
|
pub fn vertex(x: f32, y: f32, z: f32) -> Vertex {
|
||||||
|
Vertex::new(x, y, z, 1.0)
|
||||||
|
}
|
||||||
|
|
||||||
|
struct OpenMesh {
|
||||||
|
// Vertices (in homogeneous coordinates). These must be in a
|
||||||
|
// specific order: 'Entrance' loops, then 'body' vertices, then
|
||||||
|
// 'exit' loops.
|
||||||
|
verts: Vec<Vertex>,
|
||||||
|
// Triangles, taken as every 3 values, treated each as indices
|
||||||
|
// into 'verts':
|
||||||
|
faces: Vec<usize>,
|
||||||
|
// A list of indices into verts, telling the index at which each
|
||||||
|
// 'entrance' vertex loop begins. The loop implicitly ends where the
|
||||||
|
// next one begins, or if it is the last one, at idxs_body._1.
|
||||||
|
// Thus, this has one element per vertex loop, and must go in
|
||||||
|
// ascending order.
|
||||||
|
idxs_entrance: Vec<usize>,
|
||||||
|
// The same as idxs_entrance, but for 'exit' vertex loops. The final
|
||||||
|
// loop is taken as ending at the end of the list.
|
||||||
|
idxs_exit: Vec<usize>,
|
||||||
|
// The start and end (non-inclusive) of the 'body' vertices -
|
||||||
|
// those that are neither an entrance nor an exit loop.
|
||||||
|
idxs_body: (usize, usize),
|
||||||
|
}
|
||||||
|
// TODO: What is proper for an index, u32 or usize?
|
||||||
|
|
||||||
|
impl OpenMesh {
|
||||||
|
|
||||||
|
fn transform(&self, xfm: nalgebra::Matrix4<f32>) -> OpenMesh {
|
||||||
|
OpenMesh {
|
||||||
|
verts: self.verts.iter().map(|v| xfm * v).collect(),
|
||||||
|
faces: self.faces.clone(), // TODO: Use Rc?
|
||||||
|
idxs_entrance: self.idxs_entrance.clone(), // TODO: Use Rc?
|
||||||
|
idxs_exit: self.idxs_exit.clone(), // TODO: Use Rc?
|
||||||
|
idxs_body: self.idxs_body.clone(), // TODO: Use Rc?
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn connect(&self, others: &Vec<OpenMesh>) -> OpenMesh {
|
||||||
|
|
||||||
|
let mut v = self.verts.clone();
|
||||||
|
let mut f = self.faces.clone();
|
||||||
|
|
||||||
|
for other in others {
|
||||||
|
// We are offsetting all vertices in 'other' by everything
|
||||||
|
// else in 'v', so we need to account for this when we
|
||||||
|
// copy 'faces' (which has vector indices):
|
||||||
|
let offset = v.len();
|
||||||
|
v.extend(other.verts.iter());
|
||||||
|
f.extend(other.faces.iter().map(|f| *f + offset));
|
||||||
|
}
|
||||||
|
|
||||||
|
// - Append entrance loop & body vertices of all.
|
||||||
|
// - Append all faces - but add offset to those from 'other'.
|
||||||
|
// - Connect up so that each of self's exit loops is an
|
||||||
|
// entrance loop from one of 'other'
|
||||||
|
|
||||||
|
return OpenMesh {
|
||||||
|
verts: v,
|
||||||
|
faces: f,
|
||||||
|
idxs_entrance: self.idxs_entrance.clone(), // TODO
|
||||||
|
idxs_exit: self.idxs_exit.clone(), // TODO
|
||||||
|
idxs_body: self.idxs_body.clone(), // TODO
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: Does OpenMesh subsume both 'geom' and 'seeds' in RuleStep?
|
||||||
|
// TODO: Do I benefit with Rc<Rule> below so Rule can be shared?
|
||||||
|
|
||||||
enum Rule {
|
enum Rule {
|
||||||
// Recurse further. Input is "seeds" that further geometry should
|
// Recurse further. Input is "seeds" that further geometry should
|
||||||
@ -129,7 +207,7 @@ fn curve_horn_thing_rule(v: Vec<Mesh>) -> Vec<RuleStep> {
|
|||||||
//println!("connect vert {}, face 2: ({}, {}, {}) = {}, {}, {}", i, b1, a2, b2, vert2str(b1), vert2str(a2), vert2str(b2));
|
//println!("connect vert {}, face 2: ({}, {}, {}) = {}, {}, {}", i, b1, a2, b2, vert2str(b1), vert2str(a2), vert2str(b2));
|
||||||
}
|
}
|
||||||
// TODO: Something is *still* not quite right there. I think
|
// TODO: Something is *still* not quite right there. I think
|
||||||
// that I cannot use MeshBuilder this was and then append
|
// that I cannot use MeshBuilder this way and then append
|
||||||
// meshes - it just leads to disconnected geometry
|
// meshes - it just leads to disconnected geometry
|
||||||
|
|
||||||
let joined = match MeshBuilder::new().
|
let joined = match MeshBuilder::new().
|
||||||
@ -393,9 +471,20 @@ fn main() {
|
|||||||
}
|
}
|
||||||
println!("DEBUG-------------------------------");
|
println!("DEBUG-------------------------------");
|
||||||
|
|
||||||
let (mesh, nodes) = rule_to_mesh(&r2, vec![seed], 75);
|
let (mut mesh, nodes) = rule_to_mesh(&r2, vec![seed], 75);
|
||||||
println!("Collected {} nodes, produced {} faces, {} vertices",
|
println!("Collected {} nodes, produced {} faces, {} vertices",
|
||||||
nodes, mesh.no_faces(), mesh.no_vertices());
|
nodes, mesh.no_faces(), mesh.no_vertices());
|
||||||
|
println!("Trying to merge...");
|
||||||
|
match mesh.merge_overlapping_primitives() {
|
||||||
|
Err(e) => {
|
||||||
|
println!("Couldn't merge overlapping primitives!");
|
||||||
|
println!("Error: {:?}", e);
|
||||||
|
}
|
||||||
|
Ok(v) => {
|
||||||
|
println!("Merged to {} faces, {} vertices",
|
||||||
|
mesh.no_faces(), mesh.no_vertices());
|
||||||
|
}
|
||||||
|
}
|
||||||
println!("Writing OBJ...");
|
println!("Writing OBJ...");
|
||||||
std::fs::write("curve_horn_thing.obj", mesh.parse_as_obj()).unwrap();
|
std::fs::write("curve_horn_thing.obj", mesh.parse_as_obj()).unwrap();
|
||||||
// TODO: Can I make the seed geometry part of the rule itself?
|
// TODO: Can I make the seed geometry part of the rule itself?
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user