From 2497bcab7c89f3178d73a979971f25b1639a657a Mon Sep 17 00:00:00 2001 From: AideTechBot Date: Sun, 22 Jan 2023 13:24:20 -0500 Subject: [PATCH] Added Scene Graph Serialization --- src/dot_vox_data.rs | 76 ++++++++++++++++++++++++++++++++++++++++++++- src/scene.rs | 4 +-- 2 files changed, 77 insertions(+), 3 deletions(-) diff --git a/src/dot_vox_data.rs b/src/dot_vox_data.rs index ee882d2..c0825cb 100644 --- a/src/dot_vox_data.rs +++ b/src/dot_vox_data.rs @@ -1,4 +1,4 @@ -use crate::{Color, Layer, Material, Model, SceneNode}; +use crate::{Color, Dict, Layer, Material, Model, SceneNode}; use std::io::{self, Write}; /// Container for `.vox` file data. @@ -27,6 +27,7 @@ impl DotVoxData { // Write out all of the children of MAIN first to get the number of bytes. let mut children_buffer = Vec::new(); self.write_models(&mut children_buffer)?; + self.write_scene_graph(&mut children_buffer)?; self.write_palette_chunk(&mut children_buffer)?; let num_main_children_bytes = children_buffer.len() as u32; @@ -89,6 +90,79 @@ impl DotVoxData { Self::write_leaf_chunk(writer, "XYZI", &xyzi_chunk) } + fn write_string(buffer: &mut Vec, str: &String) { + buffer.extend_from_slice(&((str.len() as u32).to_le_bytes())); + buffer.extend_from_slice(&str.as_bytes()); + } + + fn write_dict(buffer: &mut Vec, dict: &Dict) { + buffer.extend_from_slice(&((dict.len() as u32).to_le_bytes())); + for (key, value) in dict.iter() { + Self::write_string(buffer, key); + Self::write_string(buffer, value); + } + } + + fn write_scene_graph(&self, writer: &mut W) -> Result<(), io::Error> { + for (i, node) in self.scenes.iter().enumerate() { + Self::write_scene_node(writer, node, i as u32)?; + } + + Ok(()) + } + + fn write_scene_node( + writer: &mut W, + node: &SceneNode, + i: u32, + ) -> Result<(), io::Error> { + let id; + let mut node_chunk = Vec::new(); + match node { + SceneNode::Group { + attributes, + children, + } => { + id = "nGRP"; + node_chunk.extend_from_slice(&(i as u32).to_le_bytes()); + Self::write_dict(&mut node_chunk, &attributes); + node_chunk.extend_from_slice(&((children.len() as u32).to_le_bytes())); + for child in children { + node_chunk.extend_from_slice(&child.to_le_bytes()); + } + } + SceneNode::Transform { + frames, + child, + layer_id, + attributes, + } => { + id = "nTRN"; + node_chunk.extend_from_slice(&(i as u32).to_le_bytes()); + Self::write_dict(&mut node_chunk, &attributes); + node_chunk.extend_from_slice(&child.to_le_bytes()); + node_chunk.extend_from_slice(&u32::MAX.to_le_bytes()); + node_chunk.extend_from_slice(&layer_id.to_le_bytes()); + node_chunk.extend_from_slice(&(frames.len() as u32).to_le_bytes()); + for frame in frames { + Self::write_dict(&mut node_chunk, &frame.attributes); + } + } + SceneNode::Shape { attributes, models } => { + id = "nSHP"; + node_chunk.extend_from_slice(&(i as u32).to_le_bytes()); + Self::write_dict(&mut node_chunk, &attributes); + node_chunk.extend_from_slice(&(models.len() as u32).to_le_bytes()); + for model in models { + node_chunk.extend_from_slice(&model.model_id.to_le_bytes()); + Self::write_dict(&mut node_chunk, &model.attributes); + } + } + } + + Self::write_leaf_chunk(writer, id, &node_chunk) + } + fn write_palette_chunk(&self, writer: &mut W) -> Result<(), io::Error> { let mut chunk = Vec::new(); for color in self.palette.iter() { diff --git a/src/scene.rs b/src/scene.rs index 4ddb086..58eb0d5 100644 --- a/src/scene.rs +++ b/src/scene.rs @@ -219,7 +219,7 @@ impl From for (i32, i32, i32) { /// interpolated across the sequence of Frames using their positions. pub struct Frame { /// The raw attributes as parsed from the .vox - attributes: Dict, + pub attributes: Dict, } impl Frame { @@ -236,7 +236,7 @@ impl Frame { if let IResult::<&str, u8>::Ok((_, byte_rotation)) = nom::character::complete::u8(value.as_str()) { - return Some(Rotation::from_byte(byte_rotation)) + return Some(Rotation::from_byte(byte_rotation)); } else { debug!("'_r' attribute for Frame could not be parsed! {}", value); }