pub unsafe trait TVertex: Copy + Default + dataview::Pod {
const LAYOUT: &'static VertexLayout;
}
pub trait TVertex2: TVertex {
fn position(&self) -> cvmath::Vec2f;
}
pub trait TVertex3: TVertex {
fn position(&self) -> cvmath::Vec3f;
}
#[derive(Copy, Clone, Debug, Eq, PartialEq, Hash)]
pub enum VertexAttributeSize {
One = 1,
Two = 2,
Three = 3,
Four = 4,
}
#[derive(Copy, Clone, Debug, Eq, PartialEq, Hash)]
pub enum VertexAttributeType {
F32,
F64,
I32,
U32,
I16,
U16,
I8,
U8,
}
#[derive(Copy, Clone, Debug, Eq, PartialEq, Hash)]
pub enum VertexAttributeFormat {
F32,
F32v2,
F32v3,
F32v4,
F64,
F64v2,
F64v3,
F64v4,
I32,
I32v2,
I32v3,
I32v4,
U32,
U32v2,
U32v3,
U32v4,
I16,
I16v2,
I16v3,
I16v4,
U16,
U16v2,
U16v3,
U16v4,
I8,
I8v2,
I8v3,
I8v4,
U8,
U8v2,
U8v3,
U8v4,
I16Norm,
I16Normv2,
I16Normv3,
I16Normv4,
U16Norm,
U16Normv2,
U16Normv3,
U16Normv4,
I8Norm,
I8Normv2,
I8Normv3,
I8Normv4,
U8Norm,
U8Normv2,
U8Normv3,
U8Normv4,
}
impl VertexAttributeFormat {
#[inline]
pub const fn size(self) -> VertexAttributeSize {
match self as u8 % 4 {
0 => VertexAttributeSize::One,
1 => VertexAttributeSize::Two,
2 => VertexAttributeSize::Three,
3 => VertexAttributeSize::Four,
_ => unreachable!(),
}
}
#[inline]
pub const fn ty(self) -> VertexAttributeType {
match self as u8 / 4 {
0 => VertexAttributeType::F32,
1 => VertexAttributeType::F64,
2 => VertexAttributeType::I32,
3 => VertexAttributeType::U32,
4 => VertexAttributeType::I16,
5 => VertexAttributeType::U16,
6 => VertexAttributeType::I8,
7 => VertexAttributeType::U8,
8 => VertexAttributeType::I16,
9 => VertexAttributeType::U16,
10 => VertexAttributeType::I8,
11 => VertexAttributeType::U8,
_ => unreachable!(),
}
}
#[inline]
pub const fn normalized(self) -> bool {
self as usize >= VertexAttributeFormat::I16Norm as usize
}
}
#[derive(Copy, Clone, Debug, Default, Eq, PartialEq, Ord, PartialOrd, Hash)]
#[repr(transparent)]
pub struct Norm<T>(pub T);
unsafe impl<T: dataview::Pod> dataview::Pod for Norm<T> {}
#[macro_export]
macro_rules! norm {
([$($e:expr),* $(,)?]) => {
[$($crate::Norm($e)),*]
}
}
pub trait TVertexAttributeFormat {
const FORMAT: VertexAttributeFormat;
}
macro_rules! TVertexAttributeFormat {
($ty:ty; $v:ident, $v2:ident, $v3:ident, $v4:ident) => {
impl TVertexAttributeFormat for $ty {
const FORMAT: VertexAttributeFormat = VertexAttributeFormat::$v;
}
impl TVertexAttributeFormat for [$ty; 1] {
const FORMAT: VertexAttributeFormat = VertexAttributeFormat::$v;
}
impl TVertexAttributeFormat for [$ty; 2] {
const FORMAT: VertexAttributeFormat = VertexAttributeFormat::$v2;
}
impl TVertexAttributeFormat for [$ty; 3] {
const FORMAT: VertexAttributeFormat = VertexAttributeFormat::$v3;
}
impl TVertexAttributeFormat for [$ty; 4] {
const FORMAT: VertexAttributeFormat = VertexAttributeFormat::$v4;
}
impl TVertexAttributeFormat for cvmath::Vec2<$ty> {
const FORMAT: VertexAttributeFormat = VertexAttributeFormat::$v2;
}
impl TVertexAttributeFormat for cvmath::Vec3<$ty> {
const FORMAT: VertexAttributeFormat = VertexAttributeFormat::$v3;
}
impl TVertexAttributeFormat for cvmath::Vec4<$ty> {
const FORMAT: VertexAttributeFormat = VertexAttributeFormat::$v4;
}
}
}
TVertexAttributeFormat!(f32; F32, F32v2, F32v3, F32v4);
TVertexAttributeFormat!(f64; F64, F64v2, F64v3, F64v4);
TVertexAttributeFormat!(i32; I32, I32v2, I32v3, I32v4);
TVertexAttributeFormat!(u32; U32, U32v2, U32v3, U32v4);
TVertexAttributeFormat!(i16; I16, I16v2, I16v3, I16v4);
TVertexAttributeFormat!(u16; U16, U16v2, U16v3, U16v4);
TVertexAttributeFormat!(i8; I8, I8v2, I8v3, I8v4);
TVertexAttributeFormat!(u8; U8, U8v2, U8v3, U8v4);
TVertexAttributeFormat!(Norm<i16>; I16Norm, I16Normv2, I16Normv3, I16Normv4);
TVertexAttributeFormat!(Norm<u16>; U16Norm, U16Normv2, U16Normv3, U16Normv4);
TVertexAttributeFormat!(Norm<i8>; I8Norm, I8Normv2, I8Normv3, I8Normv4);
TVertexAttributeFormat!(Norm<u8>; U8Norm, U8Normv2, U8Normv3, U8Normv4);
#[derive(Copy, Clone, Debug)]
pub struct VertexAttribute {
pub name: &'static str,
pub format: VertexAttributeFormat,
pub offset: u16,
}
impl VertexAttribute {
pub const fn with<T: TVertexAttributeFormat>(name: &'static str, offset: usize) -> VertexAttribute {
VertexAttribute {
name,
format: T::FORMAT,
offset: offset as u16,
}
}
}
#[derive(Copy, Clone, Debug)]
pub struct VertexLayout {
pub size: u16,
pub alignment: u16,
pub attributes: &'static [VertexAttribute],
}
#[derive(Copy, Clone, Default, Debug, Eq, PartialEq, Hash)]
pub enum VertexDivisor {
#[default]
PerVertex,
PerInstance,
}