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 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158
//a Imports
use crate::hierarchy;
use hierarchy::Hierarchy;
use crate::{Component, Instance, Material, RenderRecipe, Renderable, Skeleton, Texture, Vertices};
//a Instantiable
//tp Instantiable
/// An [Instantiable] is a type that is related to a set of Mesh data,
/// which can be instanced for different drawable::Instance's
///
/// It requires a related set of Mesh data that it does not refer to:
/// in object construction this Mesh data is likely to be the
/// structures containing vertex information and so on resident on a
/// CPU; in rendering the Mesh data is likely to be graphical objects
/// (such as OpenGL VAOs) that may reside (at least in part) on the
/// GPU.
///
/// The Instantiable data must be kept available to its related Instance.
///
/// The content of the Instantiable includes an array of Skeletons and
/// mesh transformation matrices, with appropriate index values. These
/// index values are into the related set of Mesh data.
#[derive(Debug)]
pub struct Instantiable<R>
where
R: Renderable,
{
/// Skeleton
pub skeleton: Option<Skeleton>,
/// All the vertices used
pub vertices: Vec<R::Vertices>,
/// All the textures used
pub textures: Vec<R::Texture>,
/// All the materials used
pub materials: Vec<R::Material>,
/// Render recipe
pub render_recipe: RenderRecipe,
/// Number of bone matrices required for all the bone sets in this structure
pub num_bone_matrices: usize,
}
//ip Instantiable
impl<R> Instantiable<R>
where
R: Renderable,
{
//fp new
/// Create a new instantiable drawable - something to which meshes
/// and bone sets will be added, and for which a set of mesh
/// matrices and rest bone positions will be derived.
///
/// Such a type can that be 'instance'd with a specific
/// transformation and bone poses, and such instances can then be
/// drawn using shaders.
pub fn new<M: Material>(
skeleton: Option<Skeleton>,
vertices: Vec<&Vertices<R>>,
textures: Vec<&Texture<R>>,
materials: Vec<R::Material>,
mut components: Hierarchy<Component>,
) -> Self {
components.find_roots();
let render_recipe = RenderRecipe::from_component_hierarchy(&components);
let num_bone_matrices = 0;
let vertices = vertices
.into_iter()
.map(|v| v.borrow_client().clone())
.collect();
let textures = textures
.into_iter()
.map(|t| t.borrow_client().clone())
.collect();
Self {
skeleton,
vertices,
textures,
materials,
render_recipe,
num_bone_matrices,
}
}
//mp instantiate
/// Create an `Instance` from this instantiable - must be used with accompanying mesh data in the appropriate form for the client
/// Must still add bone_poses one per bone set
pub fn instantiate(&self) -> Instance<R> {
Instance::new(self, self.num_bone_matrices)
}
//zz All done
}
/*
//mp borrow_mesh_data
/// Borrow the mesh data
pub fn borrow_mesh_data (&self, index:usize) -> &MeshIndexData {
&self.mesh_data[index]
}
pub fn add_meshes_of_node_iter(&self, meshes:&mut Vec<usize>, drawable:&mut drawable::Instantiable, iter:NodeIter<ObjectNode>) {
let mut parent = None;
let mut transformation = None;
let mut bone_matrices = (0,0);
let mut mesh_stack = Vec::new();
for op in iter {
match op {
NodeIterOp::Push((n,obj_node), _has_children) => {
mesh_stack.push((parent, transformation, bone_matrices));
if let Some(bone_set) = obj_node.bones {
bone_matrices = drawable.add_bone_set(bone_set);
}
if let Some(obj_transformation) = &obj_node.transformation {
if transformation.is_none() {
transformation = Some(obj_transformation.mat4());
} else {
transformation = Some(matrix::multiply4(&transformation.unwrap(), &obj_transformation.mat4()));
}
}
if obj_node.mesh.is_some() {
let index = drawable.add_mesh(&parent, &transformation, &bone_matrices);
assert_eq!(index, meshes.len());
meshes.push(n);
parent = Some(index);
transformation = None;
}
},
NodeIterOp::Pop(_,_) => {
let ptb = mesh_stack.pop().unwrap();
parent = ptb.0;
transformation = ptb.1;
bone_matrices = ptb.2;
},
}
}
}
pub fn create_instantiable(&mut self) -> drawable::Instantiable {
self.nodes.find_roots();
let mut drawable = drawable::Instantiable::new();
let mut meshes = Vec::new();
for r in self.nodes.borrow_roots() {
self.add_meshes_of_node_iter(&mut meshes, &mut drawable, self.nodes.iter_from_root(*r));
}
self.meshes = meshes;
drawable
}
pub fn bind_shader<'b, S:ShaderClass>(&self, drawable:&'b drawable::Instantiable, shader:&S) -> shader::Instantiable<'b> {
let mut s = shader::Instantiable::new(drawable);
for i in 0..self.meshes.len() {
let obj_node = self.nodes.borrow_node(self.meshes[i]);
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");
let mesh = obj_node.mesh.unwrap();
mesh.add_shader_drawables(shader, &mut s);
}
s
}
*/