use crate::rendering::compute_registry::ComputeShaderType;
use crate::rendering::shader_registry::ShaderType;
use crate::scene::animation::AnimationType;
use crate::{geometry::Mesh, Physics};
use nalgebra::{Matrix4, Rotation3, Vector3};
use vulkano::buffer::Subbuffer;
use vulkano::command_buffer::DrawIndexedIndirectCommand;
#[repr(C)]
#[derive(Copy, Clone, Debug, bytemuck::Pod, bytemuck::Zeroable)]
pub struct InstanceData {
pub model: [[f32; 4]; 4], pub color: [f32; 4], pub mat_props: [f32; 4], pub velocity: [f32; 4], pub angular_velocity: [f32; 4], pub physic_props: [f32; 4], }
#[repr(C)]
#[derive(Copy, Clone, Debug, bytemuck::Pod, bytemuck::Zeroable)]
pub struct PhysicsPushConstants {
pub dt: f32,
pub total_objects: u32,
pub offset: u32,
pub count: u32,
pub num_big_objects: u32,
pub _pad: [u32; 3], pub global_gravity: [f32; 4], }
#[derive(Clone)]
pub struct Instance {
pub color: [f32; 3],
pub emissive: f32,
pub roughness: f32,
pub metalness: f32,
pub base_color_texture: Option<usize>,
pub metallic_roughness_texture: Option<usize>,
pub animation: AnimationType,
pub model_matrix: [[f32; 4]; 4],
pub physics: Physics,
pub shader: ShaderType,
}
impl Default for Instance {
fn default() -> Self {
Self {
animation: AnimationType::Static,
model_matrix: [
[1.0, 0.0, 0.0, 0.0],
[0.0, 1.0, 0.0, 0.0],
[0.0, 0.0, 1.0, 0.0],
[0.0, 0.0, 0.0, 1.0],
],
color: [1.0, 1.0, 1.0],
emissive: 0.0,
base_color_texture: None,
metallic_roughness_texture: None,
roughness: 0.5,
metalness: 0.5,
physics: Physics::default(),
shader: ShaderType::Pbr,
}
}
}
pub struct Texture {
pub pixels: Vec<u8>,
pub width: u32,
pub height: u32,
}
#[derive(Copy, Clone, Debug)]
pub struct Transform {
pub position: [f32; 3], pub rotation: [f32; 3], pub scale: [f32; 3], }
impl Default for Transform {
fn default() -> Self {
Self {
position: [0.0, 0.0, 0.0],
rotation: [0.0, 0.0, 0.0],
scale: [1.0, 1.0, 1.0],
}
}
}
impl Transform {
pub fn to_matrix(&self) -> [[f32; 4]; 4] {
let translation = Matrix4::new_translation(&Vector3::from(self.position));
let rotation =
Rotation3::from_euler_angles(self.rotation[0], self.rotation[1], self.rotation[2])
.to_homogeneous();
let scale = Matrix4::new_nonuniform_scaling(&Vector3::from(self.scale));
let model_matrix = translation * rotation * scale;
model_matrix.into()
}
pub fn from_matrix(m: Matrix4<f32>) -> Self {
let position = [m[(0, 3)], m[(1, 3)], m[(2, 3)]];
let scale = [
Vector3::new(m[(0, 0)], m[(1, 0)], m[(2, 0)]).norm(),
Vector3::new(m[(0, 1)], m[(1, 1)], m[(2, 1)]).norm(),
Vector3::new(m[(0, 2)], m[(1, 2)], m[(2, 2)]).norm(),
];
let rotation_matrix = nalgebra::Matrix3::new(
m[(0, 0)] / scale[0],
m[(0, 1)] / scale[1],
m[(0, 2)] / scale[2],
m[(1, 0)] / scale[0],
m[(1, 1)] / scale[1],
m[(1, 2)] / scale[2],
m[(2, 0)] / scale[0],
m[(2, 1)] / scale[1],
m[(2, 2)] / scale[2],
);
let rotation = Rotation3::from_matrix_unchecked(rotation_matrix).euler_angles();
Self {
position,
rotation: [rotation.0, rotation.1, rotation.2],
scale,
}
}
pub fn translate(mut self, x: f32, y: f32, z: f32) -> Self {
self.position = [x, y, z];
self
}
pub fn rotate(mut self, x: f32, y: f32, z: f32) -> Self {
self.rotation = [x, y, z];
self
}
pub fn scale(mut self, x: f32, y: f32, z: f32) -> Self {
self.scale = [x, y, z];
self
}
pub fn uniform_scale(mut self, s: f32) -> Self {
self.scale = [s, s, s];
self
}
}
impl std::ops::Mul for Transform {
type Output = Self;
fn mul(self, rhs: Self) -> Self::Output {
let lhs_matrix = nalgebra::Matrix4::from(self.to_matrix());
let rhs_matrix = nalgebra::Matrix4::from(rhs.to_matrix());
let result_matrix = lhs_matrix * rhs_matrix;
Transform::from_matrix(result_matrix)
}
}
pub struct RenderBatch {
pub mesh: Mesh,
pub base_color_texture: Option<usize>,
pub metallic_roughness_texture: Option<usize>,
pub instances: Vec<Instance>,
pub shader: ShaderType,
pub compute_shader: ComputeShaderType,
pub indirect_buffer: Subbuffer<[DrawIndexedIndirectCommand]>,
pub base_instance_offset: u32,
}