use ::context;
use context::Context;
use program::Program;
use std::mem;
#[derive(Clone, Debug)]
pub struct Buffer {
buffer_id: BufferId,
num_elements: usize,
}
#[derive(Copy, Clone, Debug, Eq, PartialEq)]
pub struct BufferId {
id: u32,
}
impl BufferId {
pub fn invalid() -> Self {
BufferId{ id: 0 }
}
pub fn index(&self) -> u32 {
self.id
}
}
#[derive(Copy, Clone, Debug, Eq, PartialEq)]
pub enum DrawMode {
Points,
Lines,
LineStrip,
LineLoop,
Triangles,
TriangleStrip,
TriangleFan,
}
impl DrawMode {
pub fn to_gl_enum(self) -> u32 {
match self {
DrawMode::Points => context::gl::POINTS,
DrawMode::Lines => context::gl::LINES,
DrawMode::LineStrip => context::gl::LINE_STRIP,
DrawMode::LineLoop => context::gl::LINE_LOOP,
DrawMode::Triangles => context::gl::TRIANGLES,
DrawMode::TriangleStrip => context::gl::TRIANGLE_STRIP,
DrawMode::TriangleFan => context::gl::TRIANGLE_FAN,
}
}
}
impl Buffer {
pub fn new(cx: &mut Context, vertex_data: &[f32], num_elements: usize) -> Buffer {
let mut buffer_id = BufferId { id: 0 };
unsafe {
cx.gl.GenBuffers(1, &mut buffer_id.id);
cx.bind_buffer(buffer_id);
cx.gl.BufferData(context::gl::ARRAY_BUFFER,
(vertex_data.len() * mem::size_of::<f32>()) as context::gl::types::GLsizeiptr,
vertex_data.as_ptr() as *const _,
context::gl::STATIC_DRAW);
}
Buffer {
buffer_id,
num_elements,
}
}
pub fn set_data(&mut self, cx: &mut Context, vertex_data: &[f32], num_elements: usize) {
cx.bind_buffer(self.buffer_id);
unsafe {
cx.gl.BufferData(context::gl::ARRAY_BUFFER,
(vertex_data.len() * mem::size_of::<f32>()) as context::gl::types::GLsizeiptr,
vertex_data.as_ptr() as *const _,
context::gl::DYNAMIC_DRAW);
}
self.num_elements = num_elements;
}
pub fn draw(&self, cx: &mut Context, program: &Program, mode: DrawMode) {
cx.bind_buffer(self.buffer_id);
cx.use_program(program.id());
program.enable_vertex_attribs(cx);
unsafe {
cx.gl.DrawArrays(
mode.to_gl_enum(),
0,
self.num_elements as context::gl::types::GLsizei);
}
}
pub fn id(&self) -> BufferId {
self.buffer_id
}
}