1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94
//a Imports
use crate::hierarchy;
use hierarchy::{Hierarchy, NodeEnumOp};
use geo_nd::matrix;
use crate::Mat4;
use crate::{Component, Primitive};
//a RenderRecipe
//tp RenderRecipe
/// A [RenderRecipe] for a hierarchy of components
///
/// Created from a hierarchy of components, this is an array of
/// transformation matrices, an array of [Primitive]s, and an array of
/// pairs (matrix index, primitive index) of what needs to be drawn
#[derive(Debug)]
pub struct RenderRecipe {
/// Matrices to use (the first is the identity matrix)
pub matrices: Vec<Mat4>,
/// The primitives within the component
pub primitives: Vec<Primitive>,
/// Draw requirements - matrix index for the associated primitive index
pub matrix_for_primitives: Vec<usize>,
}
//ip Default RenderRecipe
impl Default for RenderRecipe {
fn default() -> Self {
Self::new()
}
}
//ip RenderRecipe
impl RenderRecipe {
//fp new
/// Create a new [RenderRecipe]
pub fn new() -> Self {
let matrices = Vec::new();
let primitives = Vec::new();
let matrix_for_primitives = Vec::new();
Self {
matrices,
primitives,
matrix_for_primitives,
}
}
//fp from_component_hierarchy
/// Build a RenderRecipe from a [Hierarchy] of [Component]
///
/// It requires the hierarchy to have had 'find_roots' executed prior
pub fn from_component_hierarchy(components: &Hierarchy<Component>) -> Self {
let mut recipe = Self::new();
// Create matrices for all meshes in the component,
// and enumerate them as (mesh index, matrix index) in `meshes`
recipe.matrices.push(matrix::identity4());
let mut meshes = Vec::new();
for root in components.borrow_roots() {
let mut trans_index = 0;
let mut mesh_stack = Vec::new();
for op in components.iter_from(*root) {
match op {
NodeEnumOp::Push((n, comp), _has_children) => {
mesh_stack.push(trans_index);
if let Some(transformation) = comp.transformation {
let transformation = matrix::multiply4(
&recipe.matrices[trans_index],
&transformation.mat4(),
);
trans_index = recipe.matrices.len();
recipe.matrices.push(transformation);
} // else keep same trans_index as its parent
meshes.push((n, trans_index));
}
NodeEnumOp::Pop(_, _) => {
trans_index = mesh_stack.pop().unwrap();
}
}
}
}
// Copy out the mesh primitives paired with the matrix index
for (n, trans_index) in meshes {
for p in &components.borrow_node(n).mesh.primitives {
recipe.primitives.push(p.clone());
recipe.matrix_for_primitives.push(trans_index);
}
}
recipe
}
}