use std::fmt::{Debug, Display, Formatter};
use glium::implement_vertex;
use nalgebra::Vector3;
use serde::{Deserialize, Serialize};
#[repr(C, align(16))]
#[derive(Copy, Clone)]
pub struct BoneTransforms {
pub bone_transforms: [[[f32; 4]; 4]; 128]
}
impl glium::uniforms::UniformBlock for BoneTransforms {
fn matches(_layout: &glium::program::BlockLayout, _base_offset: usize) -> Result<(), glium::uniforms::LayoutMismatchError> {
Ok(())
}
fn build_layout(base_offset: usize) -> glium::program::BlockLayout {
glium::program::BlockLayout::Struct {
members: vec![
("bone_transforms".to_owned(), glium::program::BlockLayout::Array {
content: Box::new(glium::program::BlockLayout::BasicType {
ty: glium::uniforms::UniformType::FloatMat4,
offset_in_buffer: base_offset,
}),
length: 128,
}),
],
}
}
}
#[derive(Copy, Clone)]
pub struct InstanceAttribute {
pub model_matrix: [[f32; 4]; 4],
}
implement_vertex!(InstanceAttribute, model_matrix);
#[derive(Copy, Clone, Serialize, Deserialize)]
pub struct Vertex {
pub position: [f32; 3],
pub texcoord: [f32; 2],
pub color: [f32; 3],
pub normal: [f32; 3],
pub bone_indices: [u32; 4],
pub bone_weights: [f32; 4],
}
glium::implement_vertex!(Vertex, position, texcoord, color, normal, bone_indices, bone_weights);
#[derive(Serialize, Deserialize)]
pub struct BoundingBoxSerializer {
pub center: [f32; 3],
pub width: f32,
pub height: f32,
pub depth: f32,
}
#[derive(Copy, Clone)]
pub struct BoundingBox {
pub center: Vector3<f32>,
pub width: f32,
pub height: f32,
pub depth: f32,
}
#[derive(Serialize, Deserialize)]
pub struct BoundingBoxMesh {
pub vertices: Vec<Vertex>,
pub indices: Vec<u32>,
}
impl Debug for Vertex {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("Vertex")
.field("position", &self.position)
.field("texcoord", &self.texcoord)
.field("color", &self.color)
.field("normal", &self.normal)
.field("bone_indices", &self.bone_indices)
.field("bone_weights", &self.bone_weights)
.finish()
}
}
impl Display for Vertex {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
f.debug_struct("Vertex")
.field("position", &self.position)
.field("texcoord", &self.texcoord)
.field("color", &self.color)
.field("normal", &self.normal)
.field("bone_indices", &self.bone_indices)
.field("bone_weights", &self.bone_weights)
.finish()
}
}
impl BoundingBoxMesh {
pub fn new(bounding_box: &BoundingBox) -> Self {
let half_width = bounding_box.width / 2.0;
let half_height = bounding_box.height / 2.0;
let half_depth = bounding_box.depth / 2.0;
let corners = [
bounding_box.center + Vector3::new(-half_width, -half_height, -half_depth),
bounding_box.center + Vector3::new(half_width, -half_height, -half_depth),
bounding_box.center + Vector3::new(half_width, half_height, -half_depth),
bounding_box.center + Vector3::new(-half_width, half_height, -half_depth),
bounding_box.center + Vector3::new(-half_width, -half_height, half_depth),
bounding_box.center + Vector3::new(half_width, -half_height, half_depth),
bounding_box.center + Vector3::new(half_width, half_height, half_depth),
bounding_box.center + Vector3::new(-half_width, half_height, half_depth),
];
let mut vertices = Vec::new();
for i in 0..corners.len() {
let corner = corners[i];
vertices.push(Vertex {
position: [corner.x, corner.y, corner.z],
texcoord: [0.0, 0.0],
color: [1.0, 1.0, 1.0],
normal: [0.0, 0.0, 0.0],
bone_indices: [0, 0, 0, 0],
bone_weights: [0.0, 0.0, 0.0, 0.0],
});
}
let indices = vec![
0, 1, 2, 2, 3, 0, 1, 5, 6, 6, 2, 1, 5, 4, 7, 7, 6, 5, 4, 0, 3, 3, 7, 4, 3, 2, 6, 6, 7, 3, 4, 5, 1, 1, 0, 4, ];
Self {
vertices,
indices,
}
}
}
impl BoundingBox {
pub fn new(min_point: [f32; 3], max_point: [f32; 3]) -> Self {
let min = Vector3::from(min_point);
let max = Vector3::from(max_point);
let center = (min + max) / 2.0;
let width = max.x - min.x;
let height = max.y - min.y;
let depth = max.z - min.z;
BoundingBox {
center,
width,
height,
depth,
}
}
pub fn min_point(&self) -> Vector3<f32> {
Vector3::new(
self.center.x - self.width / 2.0,
self.center.y - self.height / 2.0,
self.center.z - self.depth / 2.0,
)
}
pub fn max_point(&self) -> Vector3<f32> {
Vector3::new(
self.center.x + self.width / 2.0,
self.center.y + self.height / 2.0,
self.center.z + self.depth / 2.0,
)
}
pub fn to_serializer(&self) -> BoundingBoxSerializer {
BoundingBoxSerializer {
center: [self.center.x, self.center.y, self.center.z],
width: self.width,
height: self.height,
depth: self.depth,
}
}
pub fn from_serializer(serializer: BoundingBoxSerializer) -> Self {
Self {
center: Vector3::new(serializer.center[0], serializer.center[1], serializer.center[2]),
width: serializer.width,
height: serializer.height,
depth: serializer.depth,
}
}
}