mod3d_base/instantiable.rs
1//a Imports
2use crate::hierarchy;
3use hierarchy::Hierarchy;
4
5use crate::{Component, Instance, Material, RenderRecipe, Renderable, Skeleton, Texture, Vertices};
6
7//a Instantiable
8//tp Instantiable
9/// An [Instantiable] is a type that is related to a set of Mesh data,
10/// which can be instanced for different drawable::Instance's
11///
12/// It requires a related set of Mesh data that it does not refer to:
13/// in object construction this Mesh data is likely to be the
14/// structures containing vertex information and so on resident on a
15/// CPU; in rendering the Mesh data is likely to be graphical objects
16/// (such as OpenGL VAOs) that may reside (at least in part) on the
17/// GPU.
18///
19/// The Instantiable data must be kept available to its related Instance.
20///
21/// The content of the Instantiable includes an array of Skeletons and
22/// mesh transformation matrices, with appropriate index values. These
23/// index values are into the related set of Mesh data.
24#[derive(Debug)]
25pub struct Instantiable<R>
26where
27 R: Renderable,
28{
29 /// Skeleton
30 pub skeleton: Option<Skeleton>,
31 /// All the vertices used
32 pub vertices: Vec<R::Vertices>,
33 /// All the textures used
34 pub textures: Vec<R::Texture>,
35 /// All the materials used
36 pub materials: Vec<R::Material>,
37 /// Render recipe
38 pub render_recipe: RenderRecipe,
39 /// Number of bone matrices required for all the bone sets in this structure
40 pub num_bone_matrices: usize,
41}
42
43//ip Instantiable
44impl<R> Instantiable<R>
45where
46 R: Renderable,
47{
48 //fp new
49 /// Create a new instantiable drawable - something to which meshes
50 /// and bone sets will be added, and for which a set of mesh
51 /// matrices and rest bone positions will be derived.
52 ///
53 /// Such a type can that be 'instance'd with a specific
54 /// transformation and bone poses, and such instances can then be
55 /// drawn using shaders.
56 pub fn new<M: Material>(
57 skeleton: Option<Skeleton>,
58 vertices: Vec<&Vertices<R>>,
59 textures: Vec<&Texture<R>>,
60 materials: Vec<R::Material>,
61 mut components: Hierarchy<Component>,
62 ) -> Self {
63 components.find_roots();
64 let render_recipe = RenderRecipe::from_component_hierarchy(&components);
65 let num_bone_matrices = 0;
66 let vertices = vertices
67 .into_iter()
68 .map(|v| v.borrow_client().clone())
69 .collect();
70 let textures = textures
71 .into_iter()
72 .map(|t| t.borrow_client().clone())
73 .collect();
74 Self {
75 skeleton,
76 vertices,
77 textures,
78 materials,
79 render_recipe,
80 num_bone_matrices,
81 }
82 }
83
84 //mp instantiate
85 /// Create an `Instance` from this instantiable - must be used with accompanying mesh data in the appropriate form for the client
86 /// Must still add bone_poses one per bone set
87 pub fn instantiate(&self) -> Instance<R> {
88 Instance::new(self, self.num_bone_matrices)
89 }
90
91 //zz All done
92}
93
94/*
95 //mp borrow_mesh_data
96 /// Borrow the mesh data
97 pub fn borrow_mesh_data (&self, index:usize) -> &MeshIndexData {
98 &self.mesh_data[index]
99 }
100
101 pub fn add_meshes_of_node_iter(&self, meshes:&mut Vec<usize>, drawable:&mut drawable::Instantiable, iter:NodeIter<ObjectNode>) {
102 let mut parent = None;
103 let mut transformation = None;
104 let mut bone_matrices = (0,0);
105 let mut mesh_stack = Vec::new();
106 for op in iter {
107 match op {
108 NodeIterOp::Push((n,obj_node), _has_children) => {
109 mesh_stack.push((parent, transformation, bone_matrices));
110 if let Some(bone_set) = obj_node.bones {
111 bone_matrices = drawable.add_bone_set(bone_set);
112 }
113 if let Some(obj_transformation) = &obj_node.transformation {
114 if transformation.is_none() {
115 transformation = Some(obj_transformation.mat4());
116 } else {
117 transformation = Some(matrix::multiply4(&transformation.unwrap(), &obj_transformation.mat4()));
118 }
119 }
120 if obj_node.mesh.is_some() {
121 let index = drawable.add_mesh(&parent, &transformation, &bone_matrices);
122 assert_eq!(index, meshes.len());
123 meshes.push(n);
124 parent = Some(index);
125 transformation = None;
126 }
127 },
128 NodeIterOp::Pop(_,_) => {
129 let ptb = mesh_stack.pop().unwrap();
130 parent = ptb.0;
131 transformation = ptb.1;
132 bone_matrices = ptb.2;
133 },
134 }
135 }
136 }
137
138 pub fn create_instantiable(&mut self) -> drawable::Instantiable {
139 self.nodes.find_roots();
140 let mut drawable = drawable::Instantiable::new();
141 let mut meshes = Vec::new();
142 for r in self.nodes.borrow_roots() {
143 self.add_meshes_of_node_iter(&mut meshes, &mut drawable, self.nodes.iter_from_root(*r));
144 }
145 self.meshes = meshes;
146 drawable
147 }
148 pub fn bind_shader<'b, S:ShaderClass>(&self, drawable:&'b drawable::Instantiable, shader:&S) -> shader::Instantiable<'b> {
149 let mut s = shader::Instantiable::new(drawable);
150 for i in 0..self.meshes.len() {
151 let obj_node = self.nodes.borrow_node(self.meshes[i]);
152 assert!(obj_node.mesh.is_some(), "Mesh at node must be Some() for it to have been added to the self.meshes array by add_meshes_of_node_iter");
153 let mesh = obj_node.mesh.unwrap();
154 mesh.add_shader_drawables(shader, &mut s);
155 }
156 s
157 }
158*/