use crate::gl::types::*;
use crate::gl;
use super::{Renderer2d, basic_material, Render2d, Material, BasicMaterial, SimpleFbo};
use rin_graphics::{self as graphics,Mesh,PrimitiveType,IndexT,MeshSlice};
use glin::{Result, ErrorKind};
use glin::RenderSurface;
use std::borrow::Cow;
use rin_math::{Vec2, Vec3, vec2, Pnt2};
use rin_graphics::PrimitiveTypeToGl;
pub trait ToSimpleVao<T,U>{
fn to_simple_vao<C, B>(&self, gl: &C, bindings: &B, usage: GLenum) -> Result<glin::SimpleVao<T>>
where
C: glin::CreationContext,
B: glin::attributes::Bindings;
fn as_simple_vao_data(&self) -> glin::simple_vao::Data<T>;
}
impl<T: glin::VertexFormat + Clone + 'static> ToSimpleVao<T,Mesh<T>> for Mesh<T>{
fn to_simple_vao<C, B>(&self, gl: &C, bindings: &B, usage: GLenum) -> Result<glin::SimpleVao<T>>
where
C: glin::CreationContext,
B: glin::attributes::Bindings
{
let vao_data = self.as_simple_vao_data();
gl.new_simple_vao().from_data_bindings(vao_data, bindings, usage)
}
fn as_simple_vao_data(&self) -> glin::simple_vao::Data<T>{
glin::simple_vao::Data{
vertices: self,
indices: self.indices(),
mode: self.primitive_type().to_gl(),
}
}
}
impl ToSimpleVao<Vec2, Vec2> for Mesh<Vec2>{
fn to_simple_vao<C, B>(&self, gl: &C, bindings: &B, usage: GLenum) -> Result<glin::SimpleVao<Vec2>>
where
C: glin::CreationContext,
B: glin::attributes::Bindings
{
let buffer = if !self.is_empty(){
gl.new_buffer().from_data_target(self.as_ref(), usage, gl::ARRAY_BUFFER).unwrap()
}else{
gl.new_buffer().empty_target(gl::ARRAY_BUFFER).unwrap()
};
let indices = if !self.indices().is_empty(){
Some(gl.new_buffer().from_data_target(self.indices(), usage, gl::ELEMENT_ARRAY_BUFFER).unwrap())
}else{
None
};
let formats = vec![
glin::attributes::Format{
name: Cow::Borrowed("position"),
location: bindings.attribute_location("position").ok_or(ErrorKind::AttributeNotFound)?,
num_coords: 2,
.. Default::default()
}
];
let simple_format = glin::simple_vao::Format{
buffer: buffer,
attribute_formats: formats,
indices: indices,
mode: self.primitive_type().to_gl(),
};
gl.new_simple_vao().from_format(simple_format)
}
fn as_simple_vao_data(&self) -> glin::simple_vao::Data<Vec2>{
glin::simple_vao::Data{
vertices: self,
indices: self.indices(),
mode: self.primitive_type().to_gl(),
}
}
}
impl ToSimpleVao<Vec3, Vec3> for Mesh<Vec3>{
fn to_simple_vao<C, B>(&self, gl: &C, bindings: &B, usage: GLenum) -> Result<glin::SimpleVao<Vec3>>
where
C: glin::CreationContext,
B: glin::attributes::Bindings
{
let buffer = if !self.is_empty(){
gl.new_buffer().from_data_target(self.as_ref(), usage, gl::ARRAY_BUFFER).unwrap()
}else{
gl.new_buffer().empty_target(gl::ARRAY_BUFFER).unwrap()
};
let indices = if !self.indices().is_empty(){
Some(gl.new_buffer().from_data_target(self.indices(), usage, gl::ELEMENT_ARRAY_BUFFER).unwrap())
}else{
None
};
let formats = vec![
glin::attributes::Format{
name: Cow::Borrowed("position"),
location: bindings.attribute_location("position").ok_or(ErrorKind::AttributeNotFound)?,
num_coords: 3,
.. Default::default()
}
];
let simple_format = glin::simple_vao::Format{
buffer: buffer,
attribute_formats: formats,
indices: indices,
mode: self.primitive_type().to_gl(),
};
gl.new_simple_vao().from_format(simple_format)
}
fn as_simple_vao_data(&self) -> glin::simple_vao::Data<Vec3>{
glin::simple_vao::Data{
vertices: self,
indices: self.indices(),
mode: self.primitive_type().to_gl(),
}
}
}
impl<'a, T: glin::VertexFormat + Clone + 'static> ToSimpleVao<T, MeshSlice<'a, T>> for MeshSlice<'a, T>{
fn to_simple_vao<C, B>(&self, gl: &C, bindings: &B, usage: GLenum) -> Result<glin::SimpleVao<T>>
where
C: glin::CreationContext,
B: glin::attributes::Bindings
{
let vao_data = self.as_simple_vao_data();
gl.new_simple_vao().from_data_bindings(vao_data, bindings, usage)
}
fn as_simple_vao_data(&self) -> glin::simple_vao::Data<T>{
glin::simple_vao::Data{
vertices: self,
indices: self.indices(),
mode: self.primitive_type().to_gl(),
}
}
}
impl<'a> ToSimpleVao<Vec2, Vec2> for MeshSlice<'a, Vec2>{
fn to_simple_vao<C, B>(&self, gl: &C, bindings: &B, usage: GLenum) -> Result<glin::SimpleVao<Vec2>>
where
C: glin::CreationContext,
B: glin::attributes::Bindings
{
let buffer = if !self.is_empty(){
gl.new_buffer().from_data_target(self.as_ref(), usage, gl::ARRAY_BUFFER).unwrap()
}else{
gl.new_buffer().empty_target(gl::ARRAY_BUFFER).unwrap()
};
let indices = if !self.indices().is_empty(){
Some(gl.new_buffer().from_data_target(self.indices(), usage, gl::ELEMENT_ARRAY_BUFFER).unwrap())
}else{
None
};
let formats = vec![
glin::attributes::Format{
name: Cow::Borrowed("position"),
location: bindings.attribute_location("position").ok_or(ErrorKind::AttributeNotFound)?,
num_coords: 2,
.. Default::default()
}
];
let simple_format = glin::simple_vao::Format{
buffer: buffer,
attribute_formats: formats,
indices: indices,
mode: self.primitive_type().to_gl(),
};
gl.new_simple_vao().from_format(simple_format)
}
fn as_simple_vao_data(&self) -> glin::simple_vao::Data<Vec2>{
glin::simple_vao::Data{
vertices: self,
indices: self.indices(),
mode: self.primitive_type().to_gl(),
}
}
}
impl<'a> ToSimpleVao<Vec3, Vec3> for MeshSlice<'a, Vec3>{
fn to_simple_vao<C, B>(&self, gl: &C, bindings: &B, usage: GLenum) -> Result<glin::SimpleVao<Vec3>>
where
C: glin::CreationContext,
B: glin::attributes::Bindings
{
let buffer = if !self.is_empty(){
gl.new_buffer().from_data_target(self.as_ref(), usage, gl::ARRAY_BUFFER).unwrap()
}else{
gl.new_buffer().empty_target(gl::ARRAY_BUFFER).unwrap()
};
let indices = if !self.indices().is_empty(){
Some(gl.new_buffer().from_data_target(self.indices(), usage, gl::ELEMENT_ARRAY_BUFFER).unwrap())
}else{
None
};
let formats = vec![
glin::attributes::Format{
name: Cow::Borrowed("position"),
location: bindings.attribute_location("position").ok_or(ErrorKind::AttributeNotFound)?,
num_coords: 3,
.. Default::default()
}
];
let simple_format = glin::simple_vao::Format{
buffer: buffer,
attribute_formats: formats,
indices: indices,
mode: self.primitive_type().to_gl(),
};
gl.new_simple_vao().from_format(simple_format)
}
fn as_simple_vao_data(&self) -> glin::simple_vao::Data<Vec3>{
glin::simple_vao::Data{
vertices: self,
indices: self.indices(),
mode: self.primitive_type().to_gl(),
}
}
}
impl<'a, T: glin::VertexFormat + Clone + 'static> ToSimpleVao<T,(&'a [T], PrimitiveType)> for (&'a [T], PrimitiveType){
fn to_simple_vao<C, B>(&self, gl: &C, bindings: &B, usage: GLenum) -> Result<glin::SimpleVao<T>>
where
C: glin::CreationContext,
B: glin::attributes::Bindings
{
let vao_data = self.as_simple_vao_data();
gl.new_simple_vao().from_data_bindings(vao_data, bindings, usage)
}
fn as_simple_vao_data(&self) -> glin::simple_vao::Data<T>{
glin::simple_vao::Data{
vertices: &self.0,
indices: &[],
mode: self.1.to_gl(),
}
}
}
impl<'a, T: glin::VertexFormat + Clone + 'static> ToSimpleVao<T,(&'a [T], &'a [IndexT], PrimitiveType)> for (&'a [T], &'a [IndexT], PrimitiveType){
fn to_simple_vao<C, B>(&self, gl: &C, bindings: &B, usage: GLenum) -> Result<glin::SimpleVao<T>>
where
C: glin::CreationContext,
B: glin::attributes::Bindings
{
let vao_data = self.as_simple_vao_data();
gl.new_simple_vao().from_data_bindings(vao_data, bindings, usage)
}
fn as_simple_vao_data(&self) -> glin::simple_vao::Data<T>{
glin::simple_vao::Data{
vertices: &self.0,
indices: &self.1,
mode: self.2.to_gl(),
}
}
}
impl<'a> Render2d for &'a glin::Texture{
type Material = BasicMaterial<&'a glin::Texture>;
fn default_material<'b, 'c>(&'b self) -> BasicMaterial<&'a glin::Texture>{
basic_material::Builder::new()
.texture(*self)
.build()
}
fn render_with_material<R: RenderSurface, M: Material>(&self, gl: &super::Renderer<R>, pos: &Pnt2, material: &M){
self.render_size_with_material(gl, pos, &vec2(self.width() as f32, self.height() as f32), material);
}
fn render_size_with_material<R: RenderSurface, M: Material>(&self, gl: &super::Renderer<R>, pos: &Pnt2, size: &Vec2, material: &M){
let mesh = match gl.origin(){
graphics::CoordinateOrigin::TopLeft | graphics::CoordinateOrigin::CenterDown => {
graphics::rectangle_texcoords(pos,size.x,size.y,0.0,0.0,1.0,1.0)
}
graphics::CoordinateOrigin::BottomLeft | graphics::CoordinateOrigin::CenterUp => {
graphics::rectangle_texcoords(pos,size.x,size.y,0.0,1.0,1.0,0.0)
}
};
gl.draw_mesh_with_material(&mesh, material);
}
}
impl<'a> Render2d for glin::TextureSampler<'a>{
type Material = BasicMaterial<glin::TextureSampler<'a>>;
fn default_material<'b, 'c>(&'b self) -> BasicMaterial<glin::TextureSampler<'a>>{
basic_material::Builder::new()
.texture(*self)
.build()
}
fn render_with_material<R: RenderSurface, M: Material>(&self, gl: &super::Renderer<R>, pos: &Pnt2, material: &M){
self.render_size_with_material(gl, pos, &vec2(self.width() as f32, self.height() as f32), material);
}
fn render_size_with_material<R: RenderSurface, M: Material>(&self, gl: &super::Renderer<R>, pos: &Pnt2, size: &Vec2, material: &M){
let mesh = match gl.origin(){
graphics::CoordinateOrigin::TopLeft | graphics::CoordinateOrigin::CenterDown => {
graphics::rectangle_texcoords(pos,size.x,size.y,0.0,0.0,1.0,1.0)
}
graphics::CoordinateOrigin::BottomLeft | graphics::CoordinateOrigin::CenterUp => {
graphics::rectangle_texcoords(pos,size.x,size.y,0.0,1.0,1.0,0.0)
}
};
gl.draw_mesh_with_material(&mesh, material);
}
}
impl<'a> Render2d for &'a glin::Fbo{
type Material = BasicMaterial<&'a glin::Texture>;
fn default_material<'b, 'c>(&'b self) -> BasicMaterial<&'a glin::Texture>{
if let Some(tex) = self.color_tex(0) {
basic_material::Builder::new()
.texture(tex)
.build()
}else{
panic!("Can't draw an fbo without a texture color attachment");
}
}
fn render_with_material<R: RenderSurface, M: Material>(&self, gl: &super::Renderer<R>, pos: &Pnt2, material: &M){
self.render_size_with_material(gl, pos, &vec2(self.width() as f32, self.height() as f32), material);
}
fn render_size_with_material<R: RenderSurface, M: Material>(&self, gl: &super::Renderer<R>, pos: &Pnt2, size: &Vec2, material: &M){
let mesh = match gl.origin(){
graphics::CoordinateOrigin::TopLeft | graphics::CoordinateOrigin::CenterDown => {
graphics::rectangle_texcoords(pos,size.x,size.y,0.0,0.0,1.0,1.0)
}
graphics::CoordinateOrigin::BottomLeft | graphics::CoordinateOrigin::CenterUp => {
graphics::rectangle_texcoords(pos,size.x,size.y,0.0,1.0,1.0,0.0)
}
};
gl.draw_mesh_with_material(&mesh, material);
}
}
impl<'a> Render2d for &'a SimpleFbo{
type Material = BasicMaterial<&'a glin::Texture>;
fn default_material<'b, 'c>(&'b self) -> BasicMaterial<&'a glin::Texture>{
let tex = self.color_tex(0);
basic_material::Builder::new()
.texture(tex)
.build()
}
fn render_with_material<R: RenderSurface, M: Material>(&self, gl: &super::Renderer<R>, pos: &Pnt2, material: &M){
self.render_size_with_material(gl, pos, &vec2(self.width() as f32, self.height() as f32), material);
}
fn render_size_with_material<R: RenderSurface, M: Material>(&self, gl: &super::Renderer<R>, pos: &Pnt2, size: &Vec2, material: &M){
let mesh = match gl.origin(){
graphics::CoordinateOrigin::TopLeft | graphics::CoordinateOrigin::CenterDown => {
graphics::rectangle_texcoords(pos,size.x,size.y,0.0,0.0,1.0,1.0)
}
graphics::CoordinateOrigin::BottomLeft | graphics::CoordinateOrigin::CenterUp => {
graphics::rectangle_texcoords(pos,size.x,size.y,0.0,1.0,1.0,0.0)
}
};
gl.draw_mesh_with_material(&mesh, material);
}
}