radar-gi/src/graphics/collections/agg_fast_path.rs
2024-07-10 22:58:03 +08:00

257 lines
5.4 KiB
Rust

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<Point>,
}
impl AggFastPath {
pub fn new<T: Transform>(transform: &T, viewport: &Viewport) -> Result<Self> {
let vertex = Shader::new(
glow::VERTEX_SHADER,
CodeType::<String>::Path("agg-fast-path.vert".into()),
)?;
let fragment = Shader::new(
glow::FRAGMENT_SHADER,
CodeType::<String>::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<Point>,
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();
}
}