From fc22d14dfdb041797db66a9232b3beb06fada08d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Juan=20Manuel=20Tom=C3=A1s?= Date: Sat, 30 Jan 2021 18:18:23 -0300 Subject: Refactor curve drawing functionality --- src/lib.rs | 149 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 149 insertions(+) (limited to 'src/lib.rs') diff --git a/src/lib.rs b/src/lib.rs index d6a1374..db5d42f 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -4,6 +4,10 @@ mod poly; use lerp::Lerp; use poly::Poly; +use std::ffi::{CStr, CString}; + +use gl::types::*; + pub struct Bezier { pub degree: usize, pub vx: Vec, @@ -68,4 +72,149 @@ impl Bezier { } s } + + pub fn draw(&self) { + let vertex_shader_source = b" + #version 410 core + layout (location = 0) in vec3 aPos; + + void main() { + gl_Position = vec4(aPos.xyz, 1.0); + } + " + .to_vec(); + + let fragment_shader_source = format!( + " + #version 410 core + out vec4 FragColor; + + 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_px(float t) {{ + float result = 0.0; + for (int i = 0; i < {sx}; i++) {{ + result += px[i] * pow(t, i); + }} + return result; + }} + + float eval_py(float t) {{ + float result = 0.0; + for (int i = 0; i < {sy}; 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; + }} + + float control(vec2 pos) {{ + float closest = inf; + for (int i = 0; i < {s}; i++) {{ + float d = distance(pos, vec2(vx[i], vy[i])); + if (d < closest) {{ + closest = d; + }} + }} + return 1 - closest / thr; + }} + + float inside(vec2 pos) {{ + float closest = inf; + float t = 0.0; + 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) {{ + closest = d; + }} + t = step; + }} + return 1 - closest / thr; + }} + + void main() {{ + float r = inside(gl_FragCoord.xy); + float c = control(gl_FragCoord.xy); + FragColor = vec4(r, c, 0.0, 1.0); + }} + ", + s = self.degree, + vx = self.show_x(), + vy = self.show_y(), + px = &self.px, + py = &self.py, + sx = self.px.degree() + 1, + sy = self.py.degree() + 1, + dpx = &self.dpx, + dpy = &self.dpy, + dsx = self.dpx.degree() + 1, + dsy = self.dpy.degree() + 1, + ) + .into_bytes(); + + let shader_program: GLuint; + unsafe { + let vertex_shader = shader_from_source( + &CString::from_vec_unchecked(vertex_shader_source), + gl::VERTEX_SHADER, + ); + let fragment_shader = shader_from_source( + &CString::from_vec_unchecked(fragment_shader_source), + gl::FRAGMENT_SHADER, + ); + shader_program = gl::CreateProgram(); + gl::AttachShader(shader_program, vertex_shader); + gl::AttachShader(shader_program, fragment_shader); + gl::LinkProgram(shader_program); + gl::DeleteShader(vertex_shader); + gl::DeleteShader(fragment_shader); + gl::UseProgram(shader_program); + } + } } + +fn shader_from_source(source: &CStr, shader_type: GLenum) -> GLuint { + unsafe { + let shader: GLuint = gl::CreateShader(shader_type); + gl::ShaderSource(shader, 1, &source.as_ptr(), std::ptr::null()); + gl::CompileShader(shader); + let mut success: gl::types::GLint = 1; + gl::GetShaderiv(shader, gl::COMPILE_STATUS, &mut success); + if success == 0 { + println!("Compilation error: {}", source.to_str().unwrap()); + } + shader + } +} \ No newline at end of file -- cgit v1.2.3