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 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ src/main.rs | 163 +++--------------------------------------------------------- 2 files changed, 155 insertions(+), 157 deletions(-) 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 diff --git a/src/main.rs b/src/main.rs index 25a3ec1..f922376 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,158 +1,10 @@ use bezier::Bezier; -use std::ffi::{CStr, CString}; - use sdl2::event::Event; use sdl2::keyboard::Keycode; use gl::types::*; -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 - } -} - -fn compile_bezier_shader(c: &Bezier) -> GLuint { - 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 = 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(); - - 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); - } - shader_program -} - fn main() { let mut curve = Bezier::new(); @@ -164,8 +16,8 @@ fn main() { gl_attr.set_context_profile(sdl2::video::GLProfile::Core); gl_attr.set_context_version(4, 1); - let window_w: u32 = 1920; - let window_h: u32 = 1080; + let window_w: u32 = 800; + let window_h: u32 = 600; let window = video_subsystem .window("bezier", window_w, window_h) @@ -178,18 +30,14 @@ fn main() { gl::load_with(|s| video_subsystem.gl_get_proc_address(s) as *const std::os::raw::c_void); - unsafe { - gl::Viewport(0, 0, window_w as i32, window_h as i32); - } - let vertices: [f32; 18] = [ - 1.0, 1.0, 0.0, 1.0, -1.0, 0.0, -1.0, 1.0, 0.0, 1.0, -1.0, 0.0, -1.0, -1.0, 0.0, -1.0, 1.0, - 0.0, + 1.0, 1.0, 0.0, 1.0, -1.0, 0.0, -1.0, 1.0, 0.0, 1.0, -1.0, 0.0, -1.0, -1.0, 0.0, -1.0, 1.0, 0.0, ]; let mut vbo: GLuint = 0; let mut vao: GLuint = 0; unsafe { + gl::Viewport(0, 0, window_w as i32, window_h as i32); gl::GenVertexArrays(1, &mut vao); gl::BindVertexArray(vao); gl::GenBuffers(1, &mut vbo); @@ -227,13 +75,14 @@ fn main() { .. } => { curve.push(x, window_h as i32 - y); - compile_bezier_shader(&curve); + curve.draw(); } _ => {} } } unsafe { + gl::ClearColor(0.0, 0.0, 0.0, 1.0); gl::Clear(gl::COLOR_BUFFER_BIT); gl::DrawArrays(gl::TRIANGLES, 0, 6); } -- cgit v1.2.3