Skip to content

Commit

Permalink
set up basic graph
Browse files Browse the repository at this point in the history
  • Loading branch information
kayhhh committed Nov 9, 2023
1 parent 28adb34 commit aa6840a
Show file tree
Hide file tree
Showing 6 changed files with 143 additions and 9 deletions.
1 change: 1 addition & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,3 +6,5 @@
[![Documentation](https://docs.rs/gltf_kun/badge.svg)](https://docs.rs/gltf_kun)

Extensible library for building [glTF](https://github.com/KhronosGroup/glTF) toolchains.

Builds upon the lower level [`gltf`](https://github.com/gltf-rs/gltf) crate to create a traversable graph of the glTF document.
1 change: 1 addition & 0 deletions core/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -24,3 +24,4 @@ gltf = { version = "1.3.0", features = [
"KHR_materials_specular",
"KHR_materials_emissive_strength",
] }
petgraph = "0.6.4"
12 changes: 4 additions & 8 deletions core/examples/read.rs
Original file line number Diff line number Diff line change
@@ -1,16 +1,12 @@
use std::{fs, io};

const CARGO_MANIFEST_DIR: &str = env!("CARGO_MANIFEST_DIR");
const ASSETS_DIR: &str = "../assets";

const MODEL: &str = "TriangleWithoutIndices/TriangleWithoutIndices.gltf";

fn main() {
let path = format!("{}/{}/{}", CARGO_MANIFEST_DIR, ASSETS_DIR, MODEL);
let gltf = gltf_kun::import(&path).unwrap();

let file = fs::File::open(path).unwrap();
let reader = io::BufReader::new(file);
let gltf = gltf_kun::Gltf::from_reader(reader).unwrap();

println!("{:#?}", gltf);
gltf.nodes().iter().for_each(|node| {
println!("{:#?}", node.data());
});
}
36 changes: 36 additions & 0 deletions core/src/graph.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
pub struct AssetData {
pub version: String,
pub generator: Option<String>,
pub extensions_used: Vec<String>,
pub extensions_required: Vec<String>,
}

pub struct MeshData {
pub name: Option<String>,
}

#[derive(Debug)]
pub struct NodeData {
pub name: Option<String>,
pub translation: [f32; 3],
pub rotation: [f32; 4],
pub scale: [f32; 3],
}

pub struct SceneData {
pub name: Option<String>,
}

pub enum GraphNode {
Asset(AssetData),
Mesh(MeshData),
Node(NodeData),
Scene(SceneData),
}

pub enum GraphEdge {
Parent,
Child,
}

pub type GltfGraph = petgraph::graph::DiGraph<GraphNode, GraphEdge>;
100 changes: 99 additions & 1 deletion core/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1 +1,99 @@
pub use gltf::*;
use std::collections::HashMap;
use std::sync::Arc;

mod graph;

use graph::*;
use petgraph::graph::NodeIndex;
use petgraph::visit::EdgeRef;

pub struct Node {
graph: Arc<GltfGraph>,
index: NodeIndex,
}

impl Node {
pub fn data(&self) -> &NodeData {
match &self.graph[self.index] {
GraphNode::Node(node) => node,
_ => panic!("Node is not a NodeData"),
}
}

pub fn children(&self) -> Vec<Node> {
self.graph
.edges(self.index)
.filter_map(|edge| {
let index = match edge.weight() {
GraphEdge::Child => edge.target(),
_ => return None,
};

Some(Node {
graph: self.graph.clone(),
index,
})
})
.collect()
}
}

pub struct Gltf {
graph: Arc<GltfGraph>,
}

impl Gltf {
/// Create a new Gltf from json
pub fn from_json(json: &gltf::json::Root) -> Self {
let mut graph = GltfGraph::new();
let mut nodes = HashMap::new();

json.nodes.iter().enumerate().for_each(|(i, node)| {
let graph_node = graph.add_node(GraphNode::Node(NodeData {
name: node.name.clone(),
translation: node.translation.unwrap_or([0.0, 0.0, 0.0]),
rotation: node.rotation.unwrap_or_default().0,
scale: node.scale.unwrap_or([1.0, 1.0, 1.0]),
}));

nodes.insert(i, graph_node);
});

json.nodes.iter().enumerate().for_each(|(i, node)| {
let graph_node = nodes.get(&i).unwrap();

if let Some(children) = &node.children {
children.iter().for_each(|child| {
let child_graph_node = nodes.get(&child.value()).unwrap();

graph.add_edge(*graph_node, *child_graph_node, GraphEdge::Child);
graph.add_edge(*child_graph_node, *graph_node, GraphEdge::Parent);
});
}
});

Gltf {
graph: Arc::new(graph),
}
}

/// Get all glTF nodes
pub fn nodes(&self) -> Vec<Node> {
self.graph
.node_indices()
.filter_map(|index| match self.graph[index] {
GraphNode::Node(_) => Some(Node {
graph: self.graph.clone(),
index,
}),
_ => None,
})
.collect()
}
}

/// Import a glTF from the file system
pub fn import(path: &str) -> Result<Gltf, gltf::Error> {
let (doc, _, _) = gltf::import(path)?;
Ok(Gltf::from_json(&doc.into_json()))
}

0 comments on commit aa6840a

Please sign in to comment.