summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorJuan Manuel Tomás <jtomas1815@gmail.com>2021-01-30 18:18:23 -0300
committerJuan Manuel Tomás <jtomas1815@gmail.com>2021-01-30 18:18:23 -0300
commitfc22d14dfdb041797db66a9232b3beb06fada08d (patch)
treeef1505d62834056fe6da8e8812935662413daf6f /src
parentf7f8755215f2701698e173ad753f282231655bdd (diff)
downloadbezier-fc22d14dfdb041797db66a9232b3beb06fada08d.tar.gz
bezier-fc22d14dfdb041797db66a9232b3beb06fada08d.zip
Refactor curve drawing functionality
Diffstat (limited to 'src')
-rw-r--r--src/lib.rs149
-rw-r--r--src/main.rs163
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<f32>,
@@ -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);
}