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*/