diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/lerp.rs | 8 | ||||
-rw-r--r-- | src/lib.rs | 21 | ||||
-rw-r--r-- | src/main.rs | 61 | ||||
-rw-r--r-- | src/poly.rs (renamed from src/lerp/poly.rs) | 52 | ||||
-rw-r--r-- | src/poly/iter.rs (renamed from src/lerp/poly/iter.rs) | 0 |
5 files changed, 90 insertions, 52 deletions
diff --git a/src/lerp.rs b/src/lerp.rs index b613620..4c829a1 100644 --- a/src/lerp.rs +++ b/src/lerp.rs @@ -1,6 +1,4 @@ -pub mod poly; - -use poly::Poly; +use crate::poly::Poly; pub enum Lerp { Node(Box<Lerp>, Box<Lerp>), @@ -9,7 +7,7 @@ pub enum Lerp { } impl Lerp { - pub fn new(v: Vec<f32>) -> Box<Lerp> { + pub fn new(v: &Vec<f32>) -> Box<Lerp> { Lerp::new_s(&v[..]) } @@ -33,7 +31,7 @@ impl Lerp { let a = a.to_poly(); let b = b.to_poly(); let c = &b - &a; - &a + &(&c * &Poly::new(vec![0.0, 1.0])) + &a + &c.shift() } } } @@ -1,14 +1,17 @@ mod lerp; +mod poly; use lerp::Lerp; -use lerp::poly::Poly; +use poly::Poly; pub struct Bezier { + pub degree: usize, pub vx: Vec<f32>, pub vy: Vec<f32>, pub px: Poly, pub py: Poly, - pub degree: usize + pub dpx: Poly, + pub dpy: Poly } impl Bezier { @@ -18,6 +21,8 @@ impl Bezier { vy: Vec::<f32>::new(), px: Poly::new(vec![]), py: Poly::new(vec![]), + dpy: Poly::new(vec![]), + dpx: Poly::new(vec![]), degree: 0, } } @@ -25,16 +30,20 @@ impl Bezier { pub fn push(&mut self, x: i32, y: i32) { self.vx.push(x as f32); self.vy.push(y as f32); - self.px = Lerp::new(self.vx.clone()).to_poly(); - self.py = Lerp::new(self.vy.clone()).to_poly(); + self.px = Lerp::new(&self.vx).to_poly(); + self.py = Lerp::new(&self.vy).to_poly(); + self.dpx = self.px.deriv(); + self.dpy = self.py.deriv(); self.degree += 1; } pub fn remove(&mut self, index: usize) { self.vx.remove(index); self.vy.remove(index); - self.px = Lerp::new(self.vx.clone()).to_poly(); - self.py = Lerp::new(self.vy.clone()).to_poly(); + self.px = Lerp::new(&self.vx).to_poly(); + self.py = Lerp::new(&self.vy).to_poly(); + self.dpx = self.px.deriv(); + self.dpy = self.py.deriv(); self.degree -= 1; } diff --git a/src/main.rs b/src/main.rs index f01526b..a61478f 100644 --- a/src/main.rs +++ b/src/main.rs @@ -37,25 +37,47 @@ fn compile_bezier_shader(c: &Bezier) -> GLuint { #version 410 core out vec4 FragColor; - float inf = 1000000; float vx[{s}] = float[{s}]({vx}); float vy[{s}] = float[{s}]({vy}); + float px[{sx}] = float[{sx}]({px}); float py[{sy}] = float[{sy}]({py}); + + float dpx[{dsx}] = float[{dsx}]({dpx}); + float dpy[{dsy}] = float[{dsy}]({dpy}); + float thr = 32; + float step_size = 10; + float inf = 1000000; - float eval_a(float[{sx}] v, float t) {{ + float eval_px(float t) {{ float result = 0.0; for (int i = 0; i < {sx}; i++) {{ - result += v[i] * pow(t, i); + result += px[i] * pow(t, i); }} return result; }} - float eval_b(float[{sy}] v, float t) {{ + float eval_py(float t) {{ float result = 0.0; for (int i = 0; i < {sy}; i++) {{ - result += v[i] * pow(t, i); + result += py[i] * pow(t, i); + }} + return result; + }} + + float eval_dpx(float t) {{ + float result = 0.0; + for (int i = 0; i < {dsx}; i++) {{ + result += dpx[i] * pow(t, i); + }} + return result; + }} + + float eval_dpy(float t) {{ + float result = 0.0; + for (int i = 0; i < {dsy}; i++) {{ + result += dpy[i] * pow(t, i); }} return result; }} @@ -72,13 +94,14 @@ fn compile_bezier_shader(c: &Bezier) -> GLuint { }} float inside(vec2 pos) {{ - float res = 100; float closest = inf; float t = 0.0; - while (t < 1.0 - 1.0 / res) {{ - float step = t + 1.0 / res; - vec2 a = vec2(eval_a(px, t), eval_b(py, t)); - vec2 b = vec2(eval_a(px, step), eval_b(py, step)); + float dstep = 0.0; + while (t < 1.0 - dstep) {{ + dstep = step_size / length(vec2(eval_dpx(t), eval_dpy(t))); + float step = t + dstep; + vec2 a = vec2(eval_px(t), eval_py(t)); + vec2 b = vec2(eval_px(step), eval_py(step)); float c = pow(length(a - b), 2); float d = distance(pos, a + clamp(dot(pos - a, b - a) / c, 0, 1) * (b - a)); if (d < closest) {{ @@ -95,13 +118,17 @@ fn compile_bezier_shader(c: &Bezier) -> GLuint { FragColor = vec4(r, c, 0.0, 1.0); }} ", - sx = c.px.degree() + 1, - sy = c.py.degree() + 1, - px = &c.px, - py = &c.py, - s = c.degree, - vx = c.show_x(), - vy = c.show_y(), + s = c.degree, + vx = c.show_x(), + vy = c.show_y(), + px = &c.px, + py = &c.py, + sx = c.px.degree() + 1, + sy = c.py.degree() + 1, + dpx = &c.dpx, + dpy = &c.dpy, + dsx = c.dpx.degree() + 1, + dsy = c.dpy.degree() + 1, ) .into_bytes(); diff --git a/src/lerp/poly.rs b/src/poly.rs index 961c56c..35e85d8 100644 --- a/src/lerp/poly.rs +++ b/src/poly.rs @@ -2,7 +2,7 @@ mod iter; use iter::Iter; use std::fmt; -use std::ops::{Add, Mul, Sub}; +use std::ops::{Add, Sub}; #[derive(PartialEq, Debug, Clone)] pub struct Poly { @@ -12,7 +12,7 @@ pub struct Poly { impl Poly { pub fn new(data: Vec<f32>) -> Poly { - if data.len() > 0 { + if data.len() > 1 { let mut i = data.len() - 1; while data[i] == 0.0 && i > 0 { i -= 1; @@ -30,6 +30,24 @@ impl Poly { fn iter(&self) -> Iter { Iter::new(self.data.clone(), self.degree()) } + + pub fn shift(self) -> Poly { + let mut r = vec![0.0]; + r.append(&mut self.data.clone()); + Poly::new(r) + } + + pub fn deriv(&self) -> Poly { + let mut data = vec![0.0; self.degree()]; + if self.degree() > 0 { + for i in 0..self.degree() { + data[i] = self.data[i + 1] * (i + 1) as f32; + } + Poly::new(data) + } else { + Poly::new(vec![0.0]) + } + } } impl Add for &Poly { @@ -48,25 +66,6 @@ impl Sub for &Poly { } } -impl Mul for &Poly { - type Output = Poly; - - fn mul(self, other: Self) -> Poly { - let mut r = Vec::new(); - for i in 0..other.degree() + 1 { - let mut prefix = vec![0.0; i]; - let mut suffix: Vec<f32> = self - .iter() - .take(self.degree() + 1) - .map(|x| x * other.data[i]) - .collect(); - prefix.append(&mut suffix); - r.push(Poly::new(prefix)); - } - r.iter().fold(Poly::new(vec![0.0]), |acc, x| &acc + x) - } -} - impl fmt::Display for &Poly { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { let mut s = String::new(); @@ -85,10 +84,9 @@ mod tests { use super::*; #[test] - fn mul_test() { + fn shift_test() { let a = Poly::new(vec![1.0, 2.0, 3.0]); - let b = Poly::new(vec![1.0, 2.0]); - assert_eq!(&a * &b, Poly::new(vec![1.0, 4.0, 7.0, 6.0])); + assert_eq!(a.shift(), Poly::new(vec![0.0, 1.0, 2.0, 3.0])); } #[test] @@ -106,6 +104,12 @@ mod tests { } #[test] + fn deriv_test() { + let p = Poly::new(vec![1.0, 2.0, 3.0, 4.0]); + assert_eq!(p.deriv(), Poly::new(vec![2.0, 6.0, 12.0])); + } + + #[test] fn degree_is_five() { let p = Poly::new(vec![0.0, 0.0, 0.0, 0.0, 0.0, 2.0]); assert_eq!(p.degree(), 5); diff --git a/src/lerp/poly/iter.rs b/src/poly/iter.rs index 90cc4b5..90cc4b5 100644 --- a/src/lerp/poly/iter.rs +++ b/src/poly/iter.rs |