use std::ops::{Deref, DerefMut}; use bytemuck::{Pod, Zeroable}; use crate::components::{fetchcode, CodeComponent, CodeType, Program, Shader, Snippet}; use crate::errors::*; use crate::graphics::transforms::viewport::Viewport; use crate::graphics::transforms::Transform; use crate::graphics::ty::Ty; use crate::graphics::Graphics; use super::Colletion; struct AggFastPath { program: Program, buffer: Vec, } impl AggFastPath { pub fn new(transform: &T, viewport: &Viewport) -> Result { let vertex = Shader::new( glow::VERTEX_SHADER, CodeType::::Path("agg-fast-path.vert".into()), )?; let fragment = Shader::new( glow::FRAGMENT_SHADER, CodeType::::Path("agg-fast-path.frag".into()), )?; let input_snippet = Snippet::new("input",CodeType::Code(" layout(location = 0) in vec3 prev; layout(location = 1) in vec3 curr; layout(location = 2) in vec3 next; uniform float linewidth; unifrom float antialias; uniform vec4 color; ") ,false, None)?; print!("{}", input_snippet); let vertex = vertex.add_snippet_before(input_snippet + fetchcode([], "agg_fast")); let mut program = Program::new(vertex, fragment, None, ""); program.set_transform(transform); program.set_viewport(viewport); Ok(Self { program, buffer: Vec::with_capacity(128), }) } } impl Colletion for AggFastPath { type Item = Path; fn append(&mut self, item: Self::Item) { self.buffer.extend(item.points); } } impl Graphics for AggFastPath { fn draw(&self) -> Result<()> { use bytemuck::cast_slice; let b:&[u8] = cast_slice(&self.buffer); Ok(()) } } #[repr(C)] #[derive(Debug, Clone, Copy, Zeroable, Pod)] pub struct Point { prev: [f32; 3], curr: [f32; 3], next: [f32; 3], } impl Ty for Point {} #[derive(Debug)] pub struct Path { points: Vec, is_closed: bool, is_empty: bool, } impl Default for Path { fn default() -> Self { Self { points: Vec::with_capacity(500), is_closed: false, is_empty: true } } } pub struct PathBuilder { is_closed: bool, } impl Default for PathBuilder{ fn default() -> Self { Self { is_closed: false } } } impl PathBuilder { pub fn is_closed(&mut self , is_closed: bool) -> &mut Self { self.is_closed = is_closed; self } pub fn build(&self) -> Path { Path { points: Vec::with_capacity(500), is_closed: self.is_closed, is_empty: true, } } } impl Path { pub fn new(is_closed: bool) -> Self { Self { points: Vec::with_capacity(500), is_closed, is_empty: true, } } pub fn builder() -> PathBuilder { PathBuilder::default() } pub fn push(&mut self, point: [f32; 3]) { if self.is_empty { self.points.push(Point { prev: point, curr: point, next: point, }); self.points.push(Point { prev: point, curr: point, next: point, }); self.is_empty = false; } else { let len = self.points.len(); let prev = self.points[len - 1].curr; let curr = point; let next = point; self.points.push(Point { prev, curr, next }); self.points[len - 1].next = curr; if len == 2 { self.points[0].next = curr; } } } pub fn finish(&mut self) { if self.is_closed { let len = self.points.len(); let curr = self.points.first().unwrap().curr; let prev = self.points[len - 1].curr; let next = self.points[1].next; self.points.push(Point { prev, curr, next }); self.points[len - 1].next = curr; } self.points.push(self.points.last().unwrap().clone()); } pub fn len(&self) -> usize { self.points.len() - 2 } } impl Deref for Path { type Target = [u8]; fn deref(&self) -> &Self::Target { use bytemuck::cast_slice; cast_slice(&self.points) } } impl DerefMut for Path { fn deref_mut(&mut self) -> &mut Self::Target { use bytemuck::cast_slice_mut; cast_slice_mut(&mut self.points) } } mod test { use crate::graphics::transforms::{polar::Polar, position::Position, trackball::Trackball}; use super::*; #[test] fn test_path() { let mut path = Path::builder().is_closed(false).build(); path.push([9.0, 9.0, 9.0]); path.push([9.0, 19.0, 9.0]); path.finish(); println!("{:?}, len: {}", path, path.len()); } #[test] fn test_agg() { let viewport = Trackball::new().unwrap(); let trans = Polar::new().unwrap(); let position = Position::new().unwrap(); let transform = viewport.chain(trans.chain(position)); let viewport = &Viewport::new().unwrap(); let agg_path = AggFastPath::new(&transform, &viewport).unwrap(); } }