use device;
use device::{PrimitiveType, BufferHandle, VertexCount};
use device::attrib;
#[derive(Clone, PartialEq, Debug)]
pub struct Attribute {
pub name: String,
pub buffer: device::RawBufferHandle,
pub format: attrib::Format,
}
pub trait VertexFormat {
fn generate(Option<Self>, buffer: device::RawBufferHandle) -> Vec<Attribute>;
}
#[derive(Clone, PartialEq, Debug)]
pub struct Mesh {
pub num_vertices: device::VertexCount,
pub attributes: Vec<Attribute>,
}
impl Mesh {
pub fn new(nv: device::VertexCount) -> Mesh {
Mesh {
num_vertices: nv,
attributes: Vec::new(),
}
}
pub fn from_format<V: VertexFormat>(buf: device::BufferHandle<V>, nv: device::VertexCount) -> Mesh {
Mesh {
num_vertices: nv,
attributes: VertexFormat::generate(None::<V>, buf.raw()),
}
}
pub fn from_format_instanced<V: VertexFormat, U: VertexFormat>(
buf: device::BufferHandle<V>, nv: device::VertexCount,
inst: device::BufferHandle<U>) -> Mesh {
let per_vertex = VertexFormat::generate(None::<V>, buf.raw());
let per_instance = VertexFormat::generate(None::<U>, inst.raw());
let mut attributes = per_vertex;
for mut at in per_instance.into_iter() {
at.format.instance_rate = 1;
attributes.push(at);
}
Mesh {
num_vertices: nv,
attributes: attributes,
}
}
}
#[derive(Copy, Clone, Debug)]
pub struct Slice {
pub start: VertexCount,
pub end: VertexCount,
pub prim_type: PrimitiveType,
pub kind: SliceKind,
}
#[derive(Copy, Clone, Debug)]
pub enum SliceKind {
Vertex,
Index8(BufferHandle<u8>, VertexCount),
Index16(BufferHandle<u16>, VertexCount),
Index32(BufferHandle<u32>, VertexCount),
}
pub trait ToSlice {
fn to_slice(&self, pt: PrimitiveType) -> Slice;
}
impl ToSlice for Mesh {
fn to_slice(&self, ty: PrimitiveType) -> Slice {
Slice {
start: 0,
end: self.num_vertices,
prim_type: ty,
kind: SliceKind::Vertex
}
}
}
impl ToSlice for BufferHandle<u8> {
fn to_slice(&self, ty: PrimitiveType) -> Slice {
Slice {
start: 0,
end: self.len() as VertexCount,
prim_type: ty,
kind: SliceKind::Index8(*self, 0)
}
}
}
impl ToSlice for BufferHandle<u16> {
fn to_slice(&self, ty: PrimitiveType) -> Slice {
Slice {
start: 0,
end: self.len() as VertexCount,
prim_type: ty,
kind: SliceKind::Index16(*self, 0)
}
}
}
impl ToSlice for BufferHandle<u32> {
fn to_slice(&self, ty: PrimitiveType) -> Slice {
Slice {
start: 0,
end: self.len() as VertexCount,
prim_type: ty,
kind: SliceKind::Index32(*self, 0)
}
}
}
#[derive(Clone, Copy, Debug)]
pub enum LinkError {
MeshAttribute(usize),
ShaderInput(usize),
}
const BITS_PER_ATTRIBUTE: usize = 4;
const MAX_SHADER_INPUTS: usize = 64 / BITS_PER_ATTRIBUTE;
const MESH_ATTRIBUTE_MASK: usize = (1 << BITS_PER_ATTRIBUTE) - 1;
#[derive(Copy)]
pub struct AttributeIndices {
value: u64,
}
impl Iterator for AttributeIndices {
type Item = usize;
fn next(&mut self) -> Option<usize> {
let id = (self.value as usize) & MESH_ATTRIBUTE_MASK;
self.value >>= BITS_PER_ATTRIBUTE;
Some(id)
}
}
#[derive(Copy)]
pub struct Link {
table: u64,
}
impl Link {
pub fn from_iter<I: Iterator<Item=usize>>(iter: I) -> Result<Link, LinkError> {
let mut table = 0u64;
for (input, attrib) in iter.enumerate() {
if input >= MAX_SHADER_INPUTS {
return Err(LinkError::ShaderInput(input))
} else if attrib > MESH_ATTRIBUTE_MASK {
return Err(LinkError::MeshAttribute(attrib))
} else {
table |= (attrib as u64) << (input * BITS_PER_ATTRIBUTE);
}
}
Ok(Link {
table: table,
})
}
pub fn attribute_indices(&self) -> AttributeIndices {
AttributeIndices {
value: self.table,
}
}
}