Last active
October 29, 2019 21:38
-
-
Save matthewjberger/eea3a9d855bd548f3e3f1de2349aca07 to your computer and use it in GitHub Desktop.
Using petgraph to create a scene graph and traverse it non-recursively with DFS, keeping track of transformations via indices
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
[package] | |
name = "dfs" | |
version = "0.1.0" | |
authors = ["Matthew J. Berger <matthewberger@nevada.unr.edu>"] | |
edition = "2018" | |
[dependencies] | |
petgraph = "0.4.13" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
use petgraph::{ | |
prelude::*, | |
Graph, | |
visit::Dfs | |
}; | |
struct Node { | |
transform: i32, // This would be some other data type depending on the transform | |
} | |
impl Node { | |
fn new(transform: i32) -> Self { Node { transform } } | |
} | |
fn main() { | |
// Tree: | |
// 0 | |
// / \ | |
// 1 2 | |
// / \ / | |
// 3 4 8 | |
// / \ | |
// 5 6 | |
// / | |
// 7 | |
let mut graph: Graph<Node, ()> = Graph::new(); | |
let a = graph.add_node(Node::new(0)); | |
let b = graph.add_node(Node::new(1)); | |
let c = graph.add_node(Node::new(2)); | |
let d = graph.add_node(Node::new(3)); | |
let e = graph.add_node(Node::new(4)); | |
let f = graph.add_node(Node::new(5)); | |
let g = graph.add_node(Node::new(6)); | |
let h = graph.add_node(Node::new(7)); | |
let i = graph.add_node(Node::new(8)); | |
graph.add_edge(a, b, ()); | |
graph.add_edge(a, c, ()); | |
graph.add_edge(b, d, ()); | |
graph.add_edge(b, e, ()); | |
graph.add_edge(d, f, ()); | |
graph.add_edge(d, g, ()); | |
graph.add_edge(f, h, ()); | |
graph.add_edge(c, i, ()); | |
let mut transform_indices: Vec<NodeIndex> = Vec::new(); | |
// The dfs does not keep a borrow to the graph, so the graph is still mutable after this | |
let mut dfs = Dfs::new(&graph, a); | |
while let Some(nx) = dfs.next(&graph) { | |
let mut incoming_walker = graph.neighbors_directed(nx, Incoming).detach(); | |
let mut outgoing_walker = graph.neighbors_directed(nx, Outgoing).detach(); | |
if let Some(parent) = incoming_walker.next_node(&graph) { | |
while let Some(last_index) = transform_indices.last() { | |
if *last_index == parent { | |
break; | |
} | |
// Discard indices for transforms that are no longer needed | |
transform_indices.pop(); | |
} | |
} | |
println!("{:?}: Transform_indices: {:#?}", nx, transform_indices); | |
let current_transform = transform_indices.iter().fold(1, |transform, index| transform * graph[*index].transform); | |
let transform = current_transform * graph[nx].transform; | |
// If the node has children, store the index for children to use | |
if outgoing_walker.next(&graph).is_some() { | |
transform_indices.push(nx); | |
} | |
// Render with the given transform | |
println!(""); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment