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 | 
