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
}
}