use utilities::prelude::*; use vulkan_rs::prelude::*; use anyhow::Result; use gltf_loader::prelude::*; use utilities::prelude::cgmath::{prelude::One, Matrix4}; use std::sync::Arc; use crate::scene_type::SceneType; use crate::vertextypes::prelude::*; use super::asset::MatrixBuffer; pub const BONE_COUNT: usize = 64; fn new_model_buffer( device: &Arc, model_matrix: impl Into, ) -> Result>> { Buffer::builder() .set_usage(VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT) .set_memory_usage(MemoryUsage::CpuOnly) .set_data(&[model_matrix.into()]) .build(device.clone()) } fn new_bone_buffer(device: &Arc) -> Result>> { Buffer::builder() .set_usage(VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT) .set_memory_usage(MemoryUsage::CpuOnly) .set_data(&[cgmath::Matrix4::one().into(); BONE_COUNT]) .build(device.clone()) } pub trait AddPrimitiveToMesh { fn add_primitive( &mut self, vertex_buffer: Arc>, color_texture: Option>, normal_texture: Option>, material: PrimitiveMaterial, opaque: bool, ) -> Result<()>; } #[derive(Clone, Debug)] pub struct AssetMesh { device: Arc, render_type: SceneType, pub name: Option, pub node_index: usize, // model_matrix with uniform buffer model_matrix: Matrix4, pub(crate) model_buffer: Arc>, pub(crate) bone_buffer: Option>>, // primitives pub primitive_types: Vec, } impl AssetMesh { pub fn new(device: &Arc, render_type: SceneType) -> Result { Self::new_custom_model(device, render_type, Matrix4::identity()) } pub(crate) fn new_custom_model( device: &Arc, render_type: SceneType, model_matrix: Matrix4, ) -> Result { Ok(AssetMesh { device: device.clone(), render_type, name: None, node_index: 0, model_matrix, model_buffer: new_model_buffer(device, model_matrix)?, bone_buffer: None, primitive_types: Vec::new(), }) } pub fn set_node_index(&mut self, node_index: usize) { self.node_index = node_index; } pub fn add_bone_buffer(&mut self) -> Result<()> { self.bone_buffer = Some(new_bone_buffer(&self.device)?); Ok(()) } pub fn set_name(&mut self, name: &str) { self.name = Some(name.to_string()) } pub fn bone_buffer(&self) -> &Option>> { &self.bone_buffer } pub fn model_matrix(&self) -> Matrix4 { self.model_matrix } pub fn model_buffer(&self) -> &Arc> { &self.model_buffer } /// basically a clone, but it creates new vulkan handles to separate instances pub fn separated_copy(&self) -> Result { let model_buffer = new_model_buffer(&self.device, self.model_matrix)?; let bone_buffer = match self.bone_buffer { Some(_) => Some(new_bone_buffer(&self.device)?), None => None, }; let mut primitive_types = Vec::with_capacity(self.primitive_types.len()); for primitive_type in &self.primitive_types { primitive_types.push(primitive_type.clone(&model_buffer, bone_buffer.as_ref())?); } Ok(AssetMesh { device: self.device.clone(), render_type: self.render_type, name: self.name.clone(), node_index: self.node_index, model_matrix: self.model_matrix, model_buffer, bone_buffer, primitive_types, }) } } impl AddPrimitiveToMesh for AssetMesh { fn add_primitive( &mut self, vertex_buffer: Arc>, color_texture: Option>, normal_texture: Option>, material: PrimitiveMaterial, opaque: bool, ) -> Result<()> { self.primitive_types.push(PrimitiveDataTypes::new( &self.device, vertex_buffer, color_texture, normal_texture, &self.model_buffer, self.bone_buffer.as_ref(), self.render_type, material, opaque, )?); Ok(()) } } impl AddPrimitiveToMesh for AssetMesh { fn add_primitive( &mut self, vertex_buffer: Arc>, color_texture: Option>, normal_texture: Option>, material: PrimitiveMaterial, opaque: bool, ) -> Result<()> { self.primitive_types.push(PrimitiveDataTypes::new( &self.device, vertex_buffer, color_texture, normal_texture, &self.model_buffer, self.bone_buffer.as_ref(), self.render_type, material, opaque, )?); Ok(()) } } impl AddPrimitiveToMesh for AssetMesh { fn add_primitive( &mut self, vertex_buffer: Arc>, color_texture: Option>, normal_texture: Option>, material: PrimitiveMaterial, opaque: bool, ) -> Result<()> { self.primitive_types.push(PrimitiveDataTypes::new( &self.device, vertex_buffer, color_texture, normal_texture, &self.model_buffer, self.bone_buffer.as_ref(), self.render_type, material, opaque, )?); Ok(()) } } impl AddPrimitiveToMesh for AssetMesh { fn add_primitive( &mut self, vertex_buffer: Arc>, color_texture: Option>, normal_texture: Option>, material: PrimitiveMaterial, opaque: bool, ) -> Result<()> { self.primitive_types.push(PrimitiveDataTypes::new( &self.device, vertex_buffer, color_texture, normal_texture, &self.model_buffer, self.bone_buffer.as_ref(), self.render_type, material, opaque, )?); Ok(()) } } impl AddPrimitiveToMesh for AssetMesh { fn add_primitive( &mut self, vertex_buffer: Arc>, color_texture: Option>, normal_texture: Option>, material: PrimitiveMaterial, opaque: bool, ) -> Result<()> { self.primitive_types.push(PrimitiveDataTypes::new( &self.device, vertex_buffer, color_texture, normal_texture, &self.model_buffer, self.bone_buffer.as_ref(), self.render_type, material, opaque, )?); Ok(()) } } impl AddPrimitiveToMesh for AssetMesh { fn add_primitive( &mut self, vertex_buffer: Arc>, color_texture: Option>, normal_texture: Option>, material: PrimitiveMaterial, opaque: bool, ) -> Result<()> { self.primitive_types.push(PrimitiveDataTypes::new( &self.device, vertex_buffer, color_texture, normal_texture, &self.model_buffer, self.bone_buffer.as_ref(), self.render_type, material, opaque, )?); Ok(()) } } impl AddPrimitiveToMesh for AssetMesh { fn add_primitive( &mut self, vertex_buffer: Arc>, color_texture: Option>, normal_texture: Option>, material: PrimitiveMaterial, opaque: bool, ) -> Result<()> { self.primitive_types.push(PrimitiveDataTypes::new( &self.device, vertex_buffer, color_texture, normal_texture, &self.model_buffer, self.bone_buffer.as_ref(), self.render_type, material, opaque, )?); Ok(()) } } impl AddPrimitiveToMesh for AssetMesh { fn add_primitive( &mut self, vertex_buffer: Arc>, color_texture: Option>, normal_texture: Option>, material: PrimitiveMaterial, opaque: bool, ) -> Result<()> { self.primitive_types.push(PrimitiveDataTypes::new( &self.device, vertex_buffer, color_texture, normal_texture, &self.model_buffer, self.bone_buffer.as_ref(), self.render_type, material, opaque, )?); Ok(()) } } impl AddPrimitiveToMesh for AssetMesh { fn add_primitive( &mut self, vertex_buffer: Arc>, color_texture: Option>, normal_texture: Option>, material: PrimitiveMaterial, opaque: bool, ) -> Result<()> { self.primitive_types.push(PrimitiveDataTypes::new( &self.device, vertex_buffer, color_texture, normal_texture, &self.model_buffer, self.bone_buffer.as_ref(), self.render_type, material, opaque, )?); Ok(()) } }