diff --git a/.github/workflows/nannou.yml b/.github/workflows/nannou.yml index b46d78f89..2de100f9a 100644 --- a/.github/workflows/nannou.yml +++ b/.github/workflows/nannou.yml @@ -72,6 +72,31 @@ jobs: command: test args: --doc --all-features --verbose + cargo-test-core-no-std: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v2 + - name: Update apt + run: sudo apt update + - name: Install libxcb dev tools + run: sudo apt-get install libxcb-composite0-dev + - name: Install stable + uses: actions-rs/toolchain@v1 + with: + profile: minimal + toolchain: stable + override: true + - name: Text no_std + uses: actions-rs/cargo@v1 + with: + command: test + args: -p nannou_core --no-default-features --features "libm" --verbose + - name: Test no_std serde + uses: actions-rs/cargo@v1 + with: + command: test + args: -p nannou_core --no-default-features --features "libm serde" --verbose + cargo-check-examples: runs-on: ubuntu-latest steps: @@ -113,6 +138,11 @@ jobs: profile: minimal toolchain: stable override: true + - name: Cargo publish nannou_core + continue-on-error: true + run: cargo publish --token $CRATESIO_TOKEN --manifest-path nannou_core/Cargo.toml + - name: Wait for crates.io + run: sleep 30 - name: Cargo publish nannou continue-on-error: true run: cargo publish --token $CRATESIO_TOKEN --manifest-path nannou/Cargo.toml diff --git a/Cargo.toml b/Cargo.toml index c82591100..7b833bbbf 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -5,6 +5,7 @@ members = [ "guide/book_tests", "nannou", "nannou_audio", + "nannou_core", "nannou_isf", "nannou_laser", "nannou_new", diff --git a/examples/audio/hrtf-noise.rs b/examples/audio/hrtf-noise.rs index bef5f1dbc..a69c6741c 100644 --- a/examples/audio/hrtf-noise.rs +++ b/examples/audio/hrtf-noise.rs @@ -86,7 +86,7 @@ fn model(app: &App) -> Model { // Initialise the state that we want to live on the audio thread. let source_position = [0.0; 3].into(); let audio_model = Audio { - rng: SmallRng::from_seed([0; 16]), + rng: SmallRng::seed_from_u64(0), hrtf_data: HrtfData::new(), hrtf_processor, source_position, @@ -201,7 +201,7 @@ fn view(app: &App, model: &Model, frame: Frame) { // Simple function for determining a gain based on the distance from the listener. fn dist_gain(p: &Point3) -> f32 { - let m = p.magnitude(); + let m = p.length(); if m == 0.0 { 1.0 } else if m > 1.0 { diff --git a/examples/draw/draw_arrow.rs b/examples/draw/draw_arrow.rs index 4c20afb34..71ccc1c2b 100644 --- a/examples/draw/draw_arrow.rs +++ b/examples/draw/draw_arrow.rs @@ -15,8 +15,8 @@ fn view(app: &App, frame: Frame) { let side = r.w().min(r.h()); let start = r.xy(); let start_to_mouse = app.mouse.position() - start; - let target_mag = start_to_mouse.magnitude().min(side * 0.5); - let end = start + start_to_mouse.with_magnitude(target_mag); + let target_mag = start_to_mouse.length().min(side * 0.5); + let end = start + start_to_mouse.normalize() * target_mag; draw.arrow().weight(5.0).points(start, end); } } diff --git a/examples/draw/draw_mesh.rs b/examples/draw/draw_mesh.rs index b8f739685..98c8be5b0 100644 --- a/examples/draw/draw_mesh.rs +++ b/examples/draw/draw_mesh.rs @@ -41,7 +41,7 @@ fn view(app: &App, frame: Frame) { tri.map_vertices(|v| { let y_fract = map_range(v.y.abs(), 0.0, win.top(), 0.0, 1.0); let color = srgba(y_fract, 1.0 - y_fract, 1.0 - y_fract, 1.0); - (v, color) + (v.extend(0.0), color) }) }); diff --git a/examples/draw/draw_textured_mesh.rs b/examples/draw/draw_textured_mesh.rs index dd545e22c..4c483bc94 100644 --- a/examples/draw/draw_textured_mesh.rs +++ b/examples/draw/draw_textured_mesh.rs @@ -37,7 +37,8 @@ fn view(app: &App, model: &Model, frame: Frame) { .map(|point| { // Tex coords should be in range (0.0, 0.0) to (1.0, 1.0); // This will have the logo show on the front and back faces. - let tex_coords = [point.x + 0.5, 1.0 - (point.y + 0.5)]; + let [x, y, _] = point; + let tex_coords = [x + 0.5, 1.0 - (y + 0.5)]; (point, tex_coords) }); diff --git a/examples/draw/draw_textured_polygon.rs b/examples/draw/draw_textured_polygon.rs index 86659268e..51bc7e9f8 100644 --- a/examples/draw/draw_textured_polygon.rs +++ b/examples/draw/draw_textured_polygon.rs @@ -28,15 +28,15 @@ fn view(app: &App, model: &Model, frame: Frame) { let draw = app.draw(); // We'll make a wave from an ellipse with a wave added onto its circumference. - let resolution = win_rect.right() as usize; + let resolution = win_rect.right().floor(); let rect = geom::Rect::from_wh(vec2(1.0, 1.0)); let ellipse = geom::Ellipse::new(rect, resolution).circumference(); // The wave's frequency and amplitude are derived from the mouse position. let freq = map_range(app.mouse.x, win_rect.left(), win_rect.right(), 1.0, 20.0); let amp = map_range(app.mouse.y, win_rect.bottom(), win_rect.top(), 0.0, 0.5); - let wave = (0..resolution).map(|i| { - let phase = i as f32 / resolution as f32; + let wave = (0..resolution as usize).map(|i| { + let phase = i as f32 / resolution; (phase * freq * PI * 2.0).sin() * amp }); @@ -44,6 +44,7 @@ fn view(app: &App, model: &Model, frame: Frame) { let points = ellipse.zip(wave).map(|(point, wave)| { // Base the tex coords on the non-wavey points. // This will make the texture look wavey. + let point = Point2::from(point); let tex_coords = [point.x + 0.5, 1.0 - (point.y + 0.5)]; // Apply the wave to the points. let point = point + point * wave; diff --git a/examples/laser/laser_frame_stream.rs b/examples/laser/laser_frame_stream.rs index 6b6e12547..ca4d3616e 100644 --- a/examples/laser/laser_frame_stream.rs +++ b/examples/laser/laser_frame_stream.rs @@ -110,8 +110,8 @@ fn laser(laser: &mut Laser, frame: &mut laser::Frame) { TestPattern::Circle => { let n_points = frame.points_per_frame() as usize / 4; let rect = Rect::from_w_h(1.0, 1.0); - let ellipse: Vec<_> = geom::ellipse::Circumference::new(rect, n_points) - .map(|p| lit_p([p.x, p.y])) + let ellipse: Vec<_> = geom::ellipse::Circumference::new(rect, n_points as f32) + .map(|[x, y]| lit_p([x, y])) .collect(); frame.add_lines(&ellipse); } diff --git a/examples/laser/laser_frame_stream_gui.rs b/examples/laser/laser_frame_stream_gui.rs index 7b198615d..106173181 100644 --- a/examples/laser/laser_frame_stream_gui.rs +++ b/examples/laser/laser_frame_stream_gui.rs @@ -297,8 +297,8 @@ fn laser(laser: &mut Laser, frame: &mut laser::Frame) { TestPattern::Circle => { let n_points = frame.points_per_frame() as usize / 4; let rect = Rect::from_w_h(2.0, 2.0); - let ellipse: Vec<_> = geom::ellipse::Circumference::new(rect, n_points) - .map(|p| lit_p([p.x, p.y])) + let ellipse: Vec<_> = geom::ellipse::Circumference::new(rect, n_points as f32) + .map(|[x, y]| lit_p([x, y])) .collect(); add_points(&ellipse, laser.draw_mode, laser.scale, frame); } diff --git a/examples/nannou_basics/all_functions.rs b/examples/nannou_basics/all_functions.rs index 6ccaa731b..ff7beb4d5 100644 --- a/examples/nannou_basics/all_functions.rs +++ b/examples/nannou_basics/all_functions.rs @@ -105,7 +105,7 @@ fn touchpad_pressure(_app: &App, _model: &mut Model, _pressure: TouchpadPressure fn window_moved(_app: &App, _model: &mut Model, _pos: Point2) {} -fn window_resized(_app: &App, _model: &mut Model, _dim: Vector2) {} +fn window_resized(_app: &App, _model: &mut Model, _dim: Vec2) {} fn window_focused(_app: &App, _model: &mut Model) {} diff --git a/examples/offline/quadtree.rs b/examples/offline/quadtree.rs index 87ab1b0ef..853aa9c47 100644 --- a/examples/offline/quadtree.rs +++ b/examples/offline/quadtree.rs @@ -14,7 +14,7 @@ pub struct QuadTree { } pub trait WithPos { - fn get_pos(&self) -> Vector2; + fn get_pos(&self) -> Vec2; } impl QuadTree { diff --git a/examples/offline/tree.rs b/examples/offline/tree.rs index ad3c7ed01..04a7ff255 100644 --- a/examples/offline/tree.rs +++ b/examples/offline/tree.rs @@ -21,7 +21,7 @@ struct Model { // a Thing will be our main object, it'll try to grow outward struct Thing { - position: Vector2, + position: Vec2, size: f32, energy: f32, frac: f32, @@ -39,7 +39,7 @@ impl PartialEq for Thing { } // define what to use for the quadtree impl quadtree::WithPos for Thing { - fn get_pos(&self) -> Vector2 { + fn get_pos(&self) -> Vec2 { self.position } } @@ -275,7 +275,7 @@ fn view(app: &App, model: &Model, frame: Frame) { //draw in three steps draw.ellipse() - .resolution(20) + .resolution(20.0) .xy(model.things[k].position * scale) .w_h( model.things[k].size * 1.3 * scale, @@ -283,7 +283,7 @@ fn view(app: &App, model: &Model, frame: Frame) { ) .color(c); draw.ellipse() - .resolution(20) + .resolution(20.0) .xy(model.things[k].position * scale) .w_h( model.things[k].size * 1.2 * scale, @@ -291,7 +291,7 @@ fn view(app: &App, model: &Model, frame: Frame) { ) .color(c2); draw.ellipse() - .resolution(20) + .resolution(20.0) .xy(model.things[k].position * scale) .w_h( model.things[k].size * 0.5 * scale, diff --git a/examples/ui/simple_ui.rs b/examples/ui/simple_ui.rs index 33ccf9251..36f902f11 100644 --- a/examples/ui/simple_ui.rs +++ b/examples/ui/simple_ui.rs @@ -8,7 +8,7 @@ fn main() { struct Model { ui: Ui, ids: Ids, - resolution: usize, + resolution: f32, scale: f32, rotation: f32, color: Rgb, @@ -36,7 +36,7 @@ fn model(app: &App) -> Model { let ids = Ids::new(ui.widget_id_generator()); // Init our variables - let resolution = 6; + let resolution = 6.0; let scale = 200.0; let rotation = 0.0; let position = pt2(0.0, 0.0); @@ -66,12 +66,12 @@ fn update(_app: &App, model: &mut Model, _update: Update) { .border(0.0) } - for value in slider(model.resolution as f32, 3.0, 15.0) + for value in slider(model.resolution, 3.0, 15.0) .top_left_with_margin(20.0) .label("Resolution") .set(model.ids.resolution, ui) { - model.resolution = value as usize; + model.resolution = value.round(); } for value in slider(model.scale, 10.0, 500.0) diff --git a/examples/wgpu/wgpu_instancing/wgpu_instancing.rs b/examples/wgpu/wgpu_instancing/wgpu_instancing.rs index 15273eb02..8c3a57f06 100644 --- a/examples/wgpu/wgpu_instancing/wgpu_instancing.rs +++ b/examples/wgpu/wgpu_instancing/wgpu_instancing.rs @@ -1,4 +1,3 @@ -use nannou::math::cgmath::{self, Matrix3, Matrix4, Point3, Rad, Vector3}; use nannou::prelude::*; use std::cell::RefCell; @@ -9,7 +8,7 @@ mod data; * regularly than it would be with for instance polar coordinates (which is the case for UV map). * See https://en.wikipedia.org/wiki/Geodesic_polyhedron */ -fn make_geodesic_isocahedron(subdivisions: usize) -> Vec> { +fn make_geodesic_isocahedron(subdivisions: usize) -> Vec { let sqrt5 = 5f32.sqrt(); let phi = (1f32 + sqrt5) * 0.5f32; let ratio = (10f32 + (2f32 * sqrt5)).sqrt() / (4f32 * phi); @@ -17,18 +16,18 @@ fn make_geodesic_isocahedron(subdivisions: usize) -> Vec> { let b = (1f32 / ratio) / (2f32 * phi); let mut points = vec![ - Vector3::new(0f32, b, -a), - Vector3::new(b, a, 0f32), - Vector3::new(-b, a, 0f32), - Vector3::new(0f32, b, a), - Vector3::new(0f32, -b, a), - Vector3::new(-a, 0f32, b), - Vector3::new(0f32, -b, -a), - Vector3::new(a, 0f32, -b), - Vector3::new(a, 0f32, b), - Vector3::new(-a, 0f32, -b), - Vector3::new(b, -a, 0f32), - Vector3::new(-b, -a, 0f32), + vec3(0f32, b, -a), + vec3(b, a, 0f32), + vec3(-b, a, 0f32), + vec3(0f32, b, a), + vec3(0f32, -b, a), + vec3(-a, 0f32, b), + vec3(0f32, -b, -a), + vec3(a, 0f32, -b), + vec3(a, 0f32, b), + vec3(-a, 0f32, -b), + vec3(b, -a, 0f32), + vec3(-b, -a, 0f32), ]; let triangles = vec![ @@ -103,7 +102,7 @@ fn make_geodesic_isocahedron(subdivisions: usize) -> Vec> { struct Model { graphics: RefCell, - sphere: Vec>, + sphere: Vec, } struct Graphics { @@ -133,15 +132,15 @@ pub struct Normal { #[repr(C)] #[derive(Copy, Clone, Debug)] pub struct Uniforms { - world: Matrix4, - view: Matrix4, - proj: Matrix4, + world: Mat4, + view: Mat4, + proj: Mat4, } #[repr(C)] #[derive(Copy, Clone)] pub struct Instance { - transformation: Matrix4, + transformation: Mat4, color: [f32; 3], } @@ -233,27 +232,30 @@ fn model(app: &App) -> Model { } fn make_instance( - orientation: Vector3, + orientation: Vec3, offset: f32, local_rotation: f32, scale: f32, color: [f32; 3], ) -> Instance { - let scale_m = Matrix4::from_scale(scale); - let local_rotation_m = Matrix4::from(Matrix3::from_angle_y(Rad(local_rotation))); + let scale_m = Mat4::from_scale(Vec3::splat(scale)); + let local_rotation_m = Mat4::from_rotation_y(local_rotation); let orientation_m = { - let up = Vector3::new(0f32, 1f32, 0f32); + let up = Vec3::Y; let cosine = orientation.dot(up); if cosine > 0.999 { - Matrix4::identity() + Mat4::IDENTITY } else if cosine < -0.999 { - Matrix4::from_axis_angle(Vector3::new(1f32, 0f32, 0f32), Rad(std::f32::consts::PI)) + Mat4::from_axis_angle(Vec3::X, std::f32::consts::PI) } else { - Matrix4::from_axis_angle(up.cross(orientation).normalize(), up.angle(orientation)) + Mat4::from_axis_angle( + up.cross(orientation).normalize(), + up.angle_between(orientation), + ) } }; - let translation_m = Matrix4::from_translation(offset * orientation); + let translation_m = Mat4::from_translation(offset * orientation); Instance { transformation: translation_m * orientation_m * local_rotation_m * scale_m, @@ -356,19 +358,19 @@ fn view(app: &App, model: &Model, frame: Frame) { } fn create_uniforms(world_rotation: f32, [w, h]: [u32; 2]) -> Uniforms { - let world_rotation = Matrix3::from_angle_y(Rad(world_rotation as f32)); + let world_rotation = Mat4::from_rotation_y(world_rotation); let aspect_ratio = w as f32 / h as f32; - let proj = cgmath::perspective(Rad(std::f32::consts::FRAC_PI_2), aspect_ratio, 0.01, 100.0); - let view = Matrix4::look_at( - Point3::new(0.3, 0.3, 1.0), - Point3::new(0.0, 0.0, 0.0), - Vector3::new(0.0, 1.0, 0.0), - ); - - let world_scale = Matrix4::from_scale(0.015); - + let fov_y = std::f32::consts::FRAC_PI_2; + let near = 0.01; + let far = 100.0; + let proj = Mat4::perspective_rh_gl(fov_y, aspect_ratio, near, far); + let eye = pt3(0.3, 0.3, 1.0); + let target = Point3::ZERO; + let up = Vec3::Y; + let view = Mat4::look_at_rh(eye, target, up); + let world_scale = Mat4::from_scale(Vec3::splat(0.015)); Uniforms { - world: Matrix4::from(world_rotation).into(), + world: world_rotation, view: (view * world_scale).into(), proj: proj.into(), } diff --git a/examples/wgpu/wgpu_teapot/wgpu_teapot.rs b/examples/wgpu/wgpu_teapot/wgpu_teapot.rs index 9e1e69a69..ad4d72c12 100644 --- a/examples/wgpu/wgpu_teapot/wgpu_teapot.rs +++ b/examples/wgpu/wgpu_teapot/wgpu_teapot.rs @@ -1,4 +1,3 @@ -use nannou::math::cgmath::{self, Matrix3, Matrix4, Point3, Rad, Vector3}; use nannou::prelude::*; use std::cell::RefCell; @@ -35,9 +34,9 @@ pub struct Normal { #[repr(C)] #[derive(Copy, Clone, Debug)] pub struct Uniforms { - world: Matrix4, - view: Matrix4, - proj: Matrix4, + world: Mat4, + view: Mat4, + proj: Mat4, } const DEPTH_FORMAT: wgpu::TextureFormat = wgpu::TextureFormat::Depth32Float; @@ -169,17 +168,19 @@ fn view(app: &App, model: &Model, frame: Frame) { } fn create_uniforms(rotation: f32, [w, h]: [u32; 2]) -> Uniforms { - let rotation = Matrix3::from_angle_y(Rad(rotation as f32)); + let rotation = Mat4::from_rotation_y(rotation); let aspect_ratio = w as f32 / h as f32; - let proj = cgmath::perspective(Rad(std::f32::consts::FRAC_PI_2), aspect_ratio, 0.01, 100.0); - let view = Matrix4::look_at( - Point3::new(0.3, 0.3, 1.0), - Point3::new(0.0, 0.0, 0.0), - Vector3::new(0.0, 1.0, 0.0), - ); - let scale = Matrix4::from_scale(0.01); + let fov_y = std::f32::consts::FRAC_PI_2; + let near = 0.01; + let far = 100.0; + let proj = Mat4::perspective_rh_gl(fov_y, aspect_ratio, near, far); + let eye = pt3(0.3, 0.3, 1.0); + let target = Point3::ZERO; + let up = Vec3::Y; + let view = Mat4::look_at_rh(eye, target, up); + let scale = Mat4::from_scale(Vec3::splat(0.01)); Uniforms { - world: Matrix4::from(rotation).into(), + world: rotation, view: (view * scale).into(), proj: proj.into(), } diff --git a/examples/wgpu/wgpu_teapot_camera/wgpu_teapot_camera.rs b/examples/wgpu/wgpu_teapot_camera/wgpu_teapot_camera.rs index e3f0d5cd6..8d58bcc08 100644 --- a/examples/wgpu/wgpu_teapot_camera/wgpu_teapot_camera.rs +++ b/examples/wgpu/wgpu_teapot_camera/wgpu_teapot_camera.rs @@ -1,4 +1,3 @@ -use nannou::math::cgmath::{self, Matrix3, Matrix4, Point3, Rad, Vector3}; use nannou::prelude::*; use nannou::winit; use std::cell::RefCell; @@ -25,7 +24,7 @@ struct Graphics { // A simple first person camera. struct Camera { // The position of the camera. - eye: Point3, + eye: Point3, // Rotation around the x axis. pitch: f32, // Rotation around the y axis. @@ -48,33 +47,33 @@ pub struct Normal { #[repr(C)] #[derive(Copy, Clone, Debug)] pub struct Uniforms { - world: Matrix4, - view: Matrix4, - proj: Matrix4, + world: Mat4, + view: Mat4, + proj: Mat4, } const DEPTH_FORMAT: wgpu::TextureFormat = wgpu::TextureFormat::Depth32Float; impl Camera { // Calculate the direction vector from the pitch and yaw. - fn direction(&self) -> Vector3 { + fn direction(&self) -> Vec3 { pitch_yaw_to_direction(self.pitch, self.yaw) } // The camera's "view" matrix. - fn view(&self) -> Matrix4 { + fn view(&self) -> Mat4 { let direction = self.direction(); - let up = Vector3::new(0.0, 1.0, 0.0); - Matrix4::look_at_dir(self.eye, direction, up) + let up = Vec3::Y; + Mat4::look_to_rh(self.eye, direction, up) } } -fn pitch_yaw_to_direction(pitch: f32, yaw: f32) -> Vector3 { +fn pitch_yaw_to_direction(pitch: f32, yaw: f32) -> Vec3 { let xz_unit_len = pitch.cos(); let x = xz_unit_len * yaw.cos(); let y = pitch.sin(); let z = xz_unit_len * (-yaw).sin(); - Vector3::new(x, y, z) + vec3(x, y, z) } fn main() { @@ -302,13 +301,16 @@ fn view(_app: &App, model: &Model, frame: Frame) { render_pass.draw_indexed(index_range, start_vertex, instance_range); } -fn create_uniforms([w, h]: [u32; 2], view: Matrix4) -> Uniforms { - let rotation = Matrix3::from_angle_y(Rad(0f32)); +fn create_uniforms([w, h]: [u32; 2], view: Mat4) -> Uniforms { + let rotation = Mat4::from_rotation_y(0f32); let aspect_ratio = w as f32 / h as f32; - let proj = cgmath::perspective(Rad(std::f32::consts::FRAC_PI_2), aspect_ratio, 0.01, 100.0); - let scale = Matrix4::from_scale(0.01); + let fov_y = std::f32::consts::FRAC_PI_2; + let near = 0.01; + let far = 100.0; + let proj = Mat4::perspective_rh_gl(fov_y, aspect_ratio, near, far); + let scale = Mat4::from_scale(Vec3::splat(0.01)); Uniforms { - world: Matrix4::from(rotation).into(), + world: rotation, view: (view * scale).into(), proj: proj.into(), } diff --git a/generative_design/color/p_1_2_3_03.rs b/generative_design/color/p_1_2_3_03.rs index 75615c635..e09c90d41 100644 --- a/generative_design/color/p_1_2_3_03.rs +++ b/generative_design/color/p_1_2_3_03.rs @@ -107,7 +107,7 @@ fn view(app: &App, model: &Model, frame: Frame) { // count tiles let mut counter = 0; // row count and row height - let row_count = rng.gen_range(5, 30); + let row_count = rng.gen_range(5..30); let row_height = (app.window_rect().h() as i32 / row_count) as i32; // seperate each line in parts @@ -120,13 +120,13 @@ fn view(app: &App, model: &Model, frame: Frame) { // sub fragment of not? if rng.gen::() < 0.075 { // take care of big values - let fragments = rng.gen_range(2, 20); + let fragments = rng.gen_range(2..20); part_count = part_count + fragments - 1; for _ in 0..fragments { - parts.push(rng.gen_range(0, 2)); + parts.push(rng.gen_range(0..2)); } } else { - parts.push(rng.gen_range(2, 20)); + parts.push(rng.gen_range(2..20)); } } @@ -154,8 +154,8 @@ fn view(app: &App, model: &Model, frame: Frame) { let index = counter % model.color_count; let rect = nannou::geom::rect::Rect::from_x_y_w_h(0.0, 0.0, w, h); - let points_colored = rect.corners_iter().map(|c| { - let lum = map_range(c.y, h / 2.0, -h / 2.0, 0.0, 1.0); + let points_colored = rect.corners_iter().map(|[x, y]| { + let lum = map_range(y, h / 2.0, -h / 2.0, 0.0, 1.0); let col = hsva( model.hue_values[index as usize], @@ -163,7 +163,7 @@ fn view(app: &App, model: &Model, frame: Frame) { model.brightness_values[index as usize], model.alpha_value * lum, ); - (pt2(c.x, c.y), col) + (pt2(x, y), col) }); draw.polygon() diff --git a/generative_design/color/p_1_2_3_04.rs b/generative_design/color/p_1_2_3_04.rs index 0e21daa7f..4c98a2c1b 100644 --- a/generative_design/color/p_1_2_3_04.rs +++ b/generative_design/color/p_1_2_3_04.rs @@ -107,7 +107,7 @@ fn view(app: &App, model: &Model, frame: Frame) { // count tiles let mut counter = 0; // row count and row height - let row_count = rng.gen_range(5, 30); + let row_count = rng.gen_range(5..30); let row_height = (app.window_rect().h() as i32 / row_count) as i32; // seperate each line in parts @@ -120,13 +120,13 @@ fn view(app: &App, model: &Model, frame: Frame) { // sub fragment of not? if rng.gen::() < 0.075 { // take care of big values - let fragments = rng.gen_range(2, 20); + let fragments = rng.gen_range(2..20); part_count = part_count + fragments - 1; for _ in 0..fragments { - parts.push(rng.gen_range(0, 2)); + parts.push(rng.gen_range(0..2)); } } else { - parts.push(rng.gen_range(2, 20)); + parts.push(rng.gen_range(2..20)); } } @@ -155,8 +155,8 @@ fn view(app: &App, model: &Model, frame: Frame) { let index = counter % model.color_count; let rect = nannou::geom::rect::Rect::from_x_y_w_h(0.0, 0.0, w, h); - let points_colored = rect.corners_iter().map(|c| { - let lum = map_range(c.y, h / 2.0, -h / 2.0, 0.0, 1.0); + let points_colored = rect.corners_iter().map(|[x, y]| { + let lum = map_range(y, h / 2.0, -h / 2.0, 0.0, 1.0); let col = hsva( model.hue_values[index as usize], @@ -164,7 +164,7 @@ fn view(app: &App, model: &Model, frame: Frame) { model.brightness_values[index as usize], model.alpha_value * lum, ); - (pt2(c.x, c.y), col) + (pt2(x, y), col) }); draw.polygon() diff --git a/generative_design/dynamic_data_structure/m_6_1_01.rs b/generative_design/dynamic_data_structure/m_6_1_01.rs index 8842ee21b..23bd1024f 100644 --- a/generative_design/dynamic_data_structure/m_6_1_01.rs +++ b/generative_design/dynamic_data_structure/m_6_1_01.rs @@ -41,7 +41,7 @@ struct Node { ramp: f32, // Influences the shape of the function strength: f32, // Strength: positive value attracts, negative value repels damping: f32, - velocity: Vector2, + velocity: Vec2, max_velocity: f32, } @@ -64,7 +64,7 @@ impl Node { } fn update(&mut self) { - self.velocity = self.velocity.limit_magnitude(self.max_velocity); + self.velocity = self.velocity.clamp_length_max(self.max_velocity); self.x += self.velocity.x; self.y += self.velocity.y; @@ -136,7 +136,7 @@ fn attract_nodes(nodes: &mut Vec, target: usize) { } } -fn attract(current_node: &Node, other_node: &Node) -> Vector2 { +fn attract(current_node: &Node, other_node: &Node) -> Vec2 { let current_node_vector = vec2(current_node.x, current_node.y); let other_node_vector = vec2(other_node.x, other_node.y); let d = current_node_vector.distance(other_node_vector); diff --git a/generative_design/dynamic_data_structure/m_6_1_02.rs b/generative_design/dynamic_data_structure/m_6_1_02.rs index 4e4da95a5..b2b62be98 100644 --- a/generative_design/dynamic_data_structure/m_6_1_02.rs +++ b/generative_design/dynamic_data_structure/m_6_1_02.rs @@ -41,7 +41,7 @@ struct Node { min_y: f32, max_y: f32, pub damping: f32, - pub velocity: Vector2, + pub velocity: Vec2, max_velocity: f32, } @@ -61,7 +61,7 @@ impl Node { } fn update(&mut self) { - self.velocity = self.velocity.limit_magnitude(self.max_velocity); + self.velocity = self.velocity.clamp_length_max(self.max_velocity); self.x += self.velocity.x; self.y += self.velocity.y; diff --git a/generative_design/dynamic_data_structure/m_6_1_03.rs b/generative_design/dynamic_data_structure/m_6_1_03.rs index f5d086d9a..41afb65cf 100644 --- a/generative_design/dynamic_data_structure/m_6_1_03.rs +++ b/generative_design/dynamic_data_structure/m_6_1_03.rs @@ -41,7 +41,7 @@ struct Node { ramp: f32, // Influences the shape of the function strength: f32, // Strength: positive value attracts, negative value repels pub damping: f32, - pub velocity: Vector2, + pub velocity: Vec2, max_velocity: f32, } @@ -64,7 +64,7 @@ impl Node { } fn update(&mut self) { - self.velocity = self.velocity.limit_magnitude(self.max_velocity); + self.velocity = self.velocity.clamp_length_max(self.max_velocity); self.x += self.velocity.x; self.y += self.velocity.y; @@ -158,7 +158,7 @@ fn attract_nodes(nodes: &mut Vec, target: usize) { } } -fn attract(current_node: &Node, other_node: &Node) -> Vector2 { +fn attract(current_node: &Node, other_node: &Node) -> Vec2 { let current_node_vector = vec2(current_node.x, current_node.y); let other_node_vector = vec2(other_node.x, other_node.y); let d = current_node_vector.distance(other_node_vector); diff --git a/generative_design/oscillation_figures/m_2_5_02.rs b/generative_design/oscillation_figures/m_2_5_02.rs index d04a499de..c7dacec6e 100644 --- a/generative_design/oscillation_figures/m_2_5_02.rs +++ b/generative_design/oscillation_figures/m_2_5_02.rs @@ -181,8 +181,8 @@ fn calculate_lissajous_points(app: &App, model: &mut Model) { * (angle * model.mod_freq_x).cos(); let mut y = (angle * model.freq_y * fmy).sin() * (angle * model.mod_freq_y).cos(); - let rx = rng.gen_range(-model.random_offset, model.random_offset + 1.0); - let ry = rng.gen_range(-model.random_offset, model.random_offset + 1.0); + let rx = rng.gen_range(-model.random_offset..model.random_offset + 1.0); + let ry = rng.gen_range(-model.random_offset..model.random_offset + 1.0); x = (x * (win.w() / 2.0 - 30.0 - model.random_offset) + win.w() / 2.0) + rx; y = (y * (win.h() / 2.0 - 30.0 - model.random_offset) + win.h() / 2.0) + ry; diff --git a/generative_design/random_and_noise/m_1_1_01.rs b/generative_design/random_and_noise/m_1_1_01.rs index fc4213197..36a191ed0 100644 --- a/generative_design/random_and_noise/m_1_1_01.rs +++ b/generative_design/random_and_noise/m_1_1_01.rs @@ -63,7 +63,7 @@ fn view(app: &App, model: &Model, frame: Frame) { let range = win.w() as usize / 10; let vertices = (0..=range).map(|i| { - let y = rng.gen_range(win.bottom(), win.top() + 1.0) as f32; + let y = rng.gen_range(win.bottom()..win.top() + 1.0) as f32; pt2(win.left() + (i as f32 * 10.0), y as f32) }); draw.polyline() @@ -74,7 +74,7 @@ fn view(app: &App, model: &Model, frame: Frame) { let mut rng = StdRng::seed_from_u64(model.act_random_seed); for x in (0..win.w() as usize).step_by(10) { - let y = rng.gen_range(win.bottom(), win.top() + 1.0) as f32; + let y = rng.gen_range(win.bottom()..win.top() + 1.0) as f32; draw.ellipse() .x_y(win.left() + x as f32, y as f32) .w_h(3.0, 3.0) diff --git a/generative_design/random_and_noise/m_1_2_01.rs b/generative_design/random_and_noise/m_1_2_01.rs index 6351383b0..8eb048a5b 100644 --- a/generative_design/random_and_noise/m_1_2_01.rs +++ b/generative_design/random_and_noise/m_1_2_01.rs @@ -69,8 +69,8 @@ fn view(app: &App, model: &Model, frame: Frame) { for i in 0..model.count { // positions - let random_x = rng.gen_range(win.left(), win.right() + 1.0); - let random_y = rng.gen_range(win.bottom(), win.top() + 1.0); + let random_x = rng.gen_range(win.left()..win.right() + 1.0); + let random_y = rng.gen_range(win.bottom()..win.top() + 1.0); let circle_x = (angle * i as f32).cos() * 300.0; let circle_y = (angle * i as f32).sin() * 300.0; diff --git a/generative_design/random_and_noise/m_1_3_02.rs b/generative_design/random_and_noise/m_1_3_02.rs index dae08cc3e..30dbc9a24 100644 --- a/generative_design/random_and_noise/m_1_3_02.rs +++ b/generative_design/random_and_noise/m_1_3_02.rs @@ -70,7 +70,7 @@ fn view(app: &App, model: &Model, frame: Frame) { let mut rng = SmallRng::seed_from_u64(model.act_random_seed); let image = image::ImageBuffer::from_fn(win.w() as u32, win.h() as u32, |_x, _y| { - let r: u8 = rng.gen_range(0, std::u8::MAX); + let r: u8 = rng.gen_range(0..std::u8::MAX); nannou::image::Rgba([r, r, r, std::u8::MAX]) }); diff --git a/generative_design/random_and_noise/m_1_5_02.rs b/generative_design/random_and_noise/m_1_5_02.rs index 501149391..d49885e3c 100644 --- a/generative_design/random_and_noise/m_1_5_02.rs +++ b/generative_design/random_and_noise/m_1_5_02.rs @@ -33,8 +33,8 @@ fn main() { } struct Agent { - vector: Vector2, - vector_old: Vector2, + vector: Vec2, + vector_old: Vec2, step_size: f32, angle: f32, is_outside: bool, diff --git a/generative_design/random_and_noise/m_1_5_03.rs b/generative_design/random_and_noise/m_1_5_03.rs index 8ae4540dc..3a67a744a 100644 --- a/generative_design/random_and_noise/m_1_5_03.rs +++ b/generative_design/random_and_noise/m_1_5_03.rs @@ -33,8 +33,8 @@ fn main() { } struct Agent { - vector: Vector2, - vector_old: Vector2, + vector: Vec2, + vector_old: Vec2, step_size: f32, angle: f32, noise_z: f64, diff --git a/generative_design/random_and_noise/m_1_5_04.rs b/generative_design/random_and_noise/m_1_5_04.rs index 9d2b8f122..c04baa858 100644 --- a/generative_design/random_and_noise/m_1_5_04.rs +++ b/generative_design/random_and_noise/m_1_5_04.rs @@ -34,8 +34,8 @@ fn main() { } struct Agent { - vector: Vector2, - vector_old: Vector2, + vector: Vec2, + vector_old: Vec2, randomizer: f32, step_size: f32, z_noise: f32, diff --git a/generative_design/shape/p_2_1_2_01.rs b/generative_design/shape/p_2_1_2_01.rs index 2ae91e9c7..f3458d7fa 100644 --- a/generative_design/shape/p_2_1_2_01.rs +++ b/generative_design/shape/p_2_1_2_01.rs @@ -79,8 +79,8 @@ fn view(app: &App, model: &Model, frame: Frame) { let mx = clamp(win.right() + app.mouse.x, 0.0, win.w()); let my = clamp(win.top() - app.mouse.y, 0.0, win.h()); - let shift_x = rng.gen_range(-mx, mx + 1.0) / 20.0; - let shift_y = rng.gen_range(-mx, mx + 1.0) / 20.0; + let shift_x = rng.gen_range(-mx..mx + 1.0) / 20.0; + let shift_y = rng.gen_range(-mx..mx + 1.0) / 20.0; draw.ellipse() .x_y(pos_x + shift_x, pos_y + shift_y) diff --git a/generative_design/shape/p_2_1_2_02.rs b/generative_design/shape/p_2_1_2_02.rs index 5df451518..ffe7ab302 100644 --- a/generative_design/shape/p_2_1_2_02.rs +++ b/generative_design/shape/p_2_1_2_02.rs @@ -95,8 +95,8 @@ fn view(app: &App, model: &Model, frame: Frame) { let pos_x = (win.left() + (tile_w / 2.0)) + tile_w * grid_x as f32; let pos_y = (win.top() - (tile_h / 2.0)) - tile_h * grid_y as f32; - let shift_x = rng.gen_range(-mx, mx + 1.0) / 20.0; - let shift_y = rng.gen_range(-my, my + 1.0) / 20.0; + let shift_x = rng.gen_range(-mx..mx + 1.0) / 20.0; + let shift_y = rng.gen_range(-my..my + 1.0) / 20.0; draw.ellipse() .x_y(pos_x + shift_x, pos_y + shift_y) diff --git a/generative_design/shape/p_2_1_2_04.rs b/generative_design/shape/p_2_1_2_04.rs index 021743fe1..6319a53b5 100644 --- a/generative_design/shape/p_2_1_2_04.rs +++ b/generative_design/shape/p_2_1_2_04.rs @@ -77,14 +77,14 @@ fn view(app: &App, model: &Model, frame: Frame) { let mx = clamp(win.right() + app.mouse.x, 0.0, win.w()); let my = clamp(win.top() - app.mouse.y, 0.0, win.h()); - let shift_x1 = mx / 20.0 * rng.gen_range(-1.0, 1.0); - let shift_y1 = my / 20.0 * rng.gen_range(-1.0, 1.0); - let shift_x2 = mx / 20.0 * rng.gen_range(-1.0, 1.0); - let shift_y2 = my / 20.0 * rng.gen_range(-1.0, 1.0); - let shift_x3 = mx / 20.0 * rng.gen_range(-1.0, 1.0); - let shift_y3 = my / 20.0 * rng.gen_range(-1.0, 1.0); - let shift_x4 = mx / 20.0 * rng.gen_range(-1.0, 1.0); - let shift_y4 = my / 20.0 * rng.gen_range(-1.0, 1.0); + let shift_x1 = mx / 20.0 * rng.gen_range(-1.0..1.0); + let shift_y1 = my / 20.0 * rng.gen_range(-1.0..1.0); + let shift_x2 = mx / 20.0 * rng.gen_range(-1.0..1.0); + let shift_y2 = my / 20.0 * rng.gen_range(-1.0..1.0); + let shift_x3 = mx / 20.0 * rng.gen_range(-1.0..1.0); + let shift_y3 = my / 20.0 * rng.gen_range(-1.0..1.0); + let shift_x4 = mx / 20.0 * rng.gen_range(-1.0..1.0); + let shift_y4 = my / 20.0 * rng.gen_range(-1.0..1.0); let mut points = Vec::new(); points.push(pt2(pos_x + shift_x1, pos_y + shift_y1)); points.push(pt2(pos_x + model.rect_size + shift_x2, pos_y + shift_y2)); diff --git a/generative_design/shape/p_2_1_3_01.rs b/generative_design/shape/p_2_1_3_01.rs index aa0c4e2e9..08dc40950 100644 --- a/generative_design/shape/p_2_1_3_01.rs +++ b/generative_design/shape/p_2_1_3_01.rs @@ -90,7 +90,7 @@ fn view(app: &App, model: &Model, frame: Frame) { //println!("x {} || y {}", win.left() + model.tile_width * grid_x as f32, win.top() - model.tile_height * grid_y as f32); let scale = model.tile_width / model.tile_height; draw = draw.scale(scale); - let toggle = rng.gen_range(0, 4); + let toggle = rng.gen_range(0..4); let rotation = match toggle { 0 => -(PI / 2.0), 1 => 0.0, diff --git a/generative_design/shape/p_2_1_3_04.rs b/generative_design/shape/p_2_1_3_04.rs index ea3ef6155..0b9fe2f5d 100644 --- a/generative_design/shape/p_2_1_3_04.rs +++ b/generative_design/shape/p_2_1_3_04.rs @@ -89,11 +89,8 @@ fn view(app: &App, model: &Model, frame: Frame) { } 2 => { for i in 0..count { - let gradient = VectorSpace::lerp( - vec3(0.0, 0.0, 0.0), - vec3(0.14, 1.0, 0.71), - i as f32 / count as f32, - ); + let gradient = + Vec3::ZERO.lerp(vec3(0.14, 1.0, 0.71), i as f32 / count as f32); draw = draw.rotate(PI / 4.0); draw.rect().x_y(0.0, 0.0).w_h(tile_width, tile_height).hsla( gradient.x, @@ -106,17 +103,14 @@ fn view(app: &App, model: &Model, frame: Frame) { } 3 => { for i in 0..count { - let gradient = VectorSpace::lerp( - vec3(0.0, 0.5, 0.64), - vec3(1.0, 1.0, 1.0), - i as f32 / count as f32, - ); + let gradient = + vec3(0.0, 0.5, 0.64).lerp(vec3(1.0, 1.0, 1.0), i as f32 / count as f32); let draw2 = draw.x_y(4.0 * i as f32, 0.0); draw2 .ellipse() .x_y(0.0, 0.0) .w_h(tile_width / 4.0, tile_height / 4.0) - .resolution(12) + .resolution(12.0) .rgba(gradient.x, gradient.y, gradient.z, 0.66); let draw3 = draw.x_y(-4.0 * i as f32, 0.0); @@ -124,7 +118,7 @@ fn view(app: &App, model: &Model, frame: Frame) { .ellipse() .x_y(0.0, 0.0) .w_h(tile_width / 4.0, tile_height / 4.0) - .resolution(12) + .resolution(12.0) .rgba(gradient.x, gradient.y, gradient.z, 0.66); draw = draw.scale(1.0 - 1.5 / count as f32).rotate(para * 1.5); diff --git a/generative_design/shape/p_2_1_3_05.rs b/generative_design/shape/p_2_1_3_05.rs index 6030f6766..ee19981ec 100644 --- a/generative_design/shape/p_2_1_3_05.rs +++ b/generative_design/shape/p_2_1_3_05.rs @@ -85,7 +85,7 @@ fn view(app: &App, model: &Model, frame: Frame) { let pos_y = (win.top() - (tile_height / 2.0)) - tile_height * grid_y as f32; //modules - let heading = rng.gen_range(0, 4); + let heading = rng.gen_range(0..4); for i in 0..step_size as usize { let radius = map_range(i, 0, step_size as usize, tile_width, end_size) / 2.0; @@ -100,7 +100,7 @@ fn view(app: &App, model: &Model, frame: Frame) { draw.ellipse() .x_y(x, y) .radius(radius) - .resolution(32) + .resolution(32.0) .color(col); } } diff --git a/generative_design/shape/p_2_1_5_02.rs b/generative_design/shape/p_2_1_5_02.rs index 86ac243b0..6c1b38a2a 100644 --- a/generative_design/shape/p_2_1_5_02.rs +++ b/generative_design/shape/p_2_1_5_02.rs @@ -53,7 +53,7 @@ impl Shape { draw.ellipse() .x_y(self.x, self.y) .radius(i as f32 / 2.0) - .resolution(200) + .resolution(200.0) .no_fill() .stroke_weight(1.25) .stroke(BLACK); diff --git a/generative_design/shape/p_2_1_5_03.rs b/generative_design/shape/p_2_1_5_03.rs index da941933e..ce88cd2a5 100644 --- a/generative_design/shape/p_2_1_5_03.rs +++ b/generative_design/shape/p_2_1_5_03.rs @@ -49,11 +49,11 @@ struct Shape { x2: f32, y2: f32, h: f32, - c: Vector3, + c: Vec3, } impl Shape { - fn new(x1: f32, y1: f32, x2: f32, y2: f32, h: f32, c: Vector3) -> Self { + fn new(x1: f32, y1: f32, x2: f32, y2: f32, h: f32, c: Vec3) -> Self { Shape { x1, y1, @@ -83,9 +83,9 @@ struct Model { shapes: Vec, density: usize, shape_height: f32, - shape_color: Vector3, + shape_color: Vec3, new_shape: Option, - p_mouse: Vector2, + p_mouse: Point2, } fn model(app: &App) -> Model { diff --git a/generative_design/shape/p_2_2_6_01.rs b/generative_design/shape/p_2_2_6_01.rs index 0f435d4ca..5688fbe70 100644 --- a/generative_design/shape/p_2_2_6_01.rs +++ b/generative_design/shape/p_2_2_6_01.rs @@ -46,7 +46,7 @@ struct Model { joints: usize, line_length: f32, speed_relation: f32, - center: Vector2, + center: Point2, pendulum_paths: Vec>, start_positions: Vec, angle: f32, @@ -108,9 +108,8 @@ fn update(_app: &App, model: &mut Model, _update: Update) { let vy = a.to_radians().sin(); let mut next_pos = pt2(vx, vy); - next_pos = next_pos.with_magnitude( - (model.joints - i) as f32 / model.joints as f32 * model.line_length, - ); + let magnitude = (model.joints - i) as f32 / model.joints as f32 * model.line_length; + next_pos = next_pos.normalize() * magnitude; next_pos += pos; model.start_positions[i] = pos; diff --git a/generative_design/type/p_3_1_3_03.rs b/generative_design/type/p_3_1_3_03.rs index 0e16b522f..792c02c9d 100644 --- a/generative_design/type/p_3_1_3_03.rs +++ b/generative_design/type/p_3_1_3_03.rs @@ -123,7 +123,7 @@ fn view(app: &App, model: &Model, frame: Frame) { 1.0, ); let line_length = char_size; - let line_angle = rng.gen_range(-PI, PI) * mx * (PI / 2.0); + let line_angle = rng.gen_range(-PI..PI) * mx * (PI / 2.0); let new_pos_x = line_length * line_angle.cos(); let new_pos_y = line_length * line_angle.sin(); diff --git a/guide/src/changelog.md b/guide/src/changelog.md index bf06329f6..e89d1179a 100644 --- a/guide/src/changelog.md +++ b/guide/src/changelog.md @@ -14,7 +14,20 @@ Most changes have been about renaming Blend-related data structres and fixing sh - `BlendState` -> `BlendComponent` - `wgpu::Extend3d::depth` -> `wgpu::Extend3d::depth_of_array_layers` - Float tpes are now typed more descripively. E.g., `Float2` -> `Float32x2` - + +**Refactor core of `nannou` into `nannou_core` crate** + +- Add a new `nannou_core` crate, targeted towards headless or embedded apps, + libraries and rust-gpu. +- Move the `color`, `geom`, `math` and `rand` crates into `nannou_core`. +- Remove the `geom::Graph` type due to lack of strong use-case and no reports of + use. +- Remove generic scalar param from `Draw` API in favour of using `f32` + generally. +- Remove `cgmath` computer graphics linear algebra lib in favour of `glam` for + faster compile times, simpler API, easier documentation, `no_std` support and + more. + --- # Version 0.16.0 (2021-04-21) diff --git a/guide/src/tutorials/basics/window-coordinates.md b/guide/src/tutorials/basics/window-coordinates.md index 239a34529..be001e37a 100644 --- a/guide/src/tutorials/basics/window-coordinates.md +++ b/guide/src/tutorials/basics/window-coordinates.md @@ -190,7 +190,7 @@ like so: # use nannou::prelude::*; # fn main() { # let draw: Draw = unimplemented!(); -let r = Rect::from_w_h(100.0, 100.0); +let r = Rect::from_w_h(100.0f32, 100.0f32); draw.rect() .xy(r.xy()) .wh(r.wh()) diff --git a/nannou/Cargo.toml b/nannou/Cargo.toml index 005dd775c..68cad0d3d 100644 --- a/nannou/Cargo.toml +++ b/nannou/Cargo.toml @@ -14,7 +14,6 @@ edition = "2018" default = ["notosans"] [dependencies] -cgmath = { version = "0.17", features = ["serde"] } conrod_core = "0.73" conrod_wgpu = "0.73" conrod_winit = "0.72" @@ -24,12 +23,11 @@ futures = { version = "0.3", features = ["executor", "thread-pool"] } image = "0.23" instant = "0.1.9" lyon = "0.15" +nannou_core = { version = "0.16.0", path = "../nannou_core", features = ["std", "serde"] } noise = "0.6" notosans = { version = "0.1", optional = true } num_cpus = "1" -palette = { version = "0.5", features = ["serializing"] } pennereq = "0.3" -rand = { version = "0.7", features = ["small_rng"] } rusttype = "0.8" serde = "1" serde_derive = "1" diff --git a/nannou/src/app.rs b/nannou/src/app.rs index fa1e2be3c..2b71cbff8 100644 --- a/nannou/src/app.rs +++ b/nannou/src/app.rs @@ -154,7 +154,7 @@ pub struct App { /// running installations. This is because the "resolution" of floating point values reduces as /// the number becomes higher. Instead, we recommend using `app.duration.since_start` or /// `app.duration.since_prev_update` to access a more precise form of app time. - pub time: DrawScalar, + pub time: f32, } /// Miscellaneous app configuration parameters. @@ -168,16 +168,10 @@ struct Config { // Draw state managed by the **App**. #[derive(Debug)] struct DrawState { - draw: RefCell>, + draw: RefCell, renderers: RefCell>>, } -/// The app uses a set scalar type in order to provide a simplistic API to users. -/// -/// If you require changing the scalar type to something else, consider using a custom -/// **nannou::draw::Draw** instance. -pub type DrawScalar = geom::scalar::Default; - /// A handle to the **App** that can be shared across threads. This may be used to "wake up" the /// **App**'s inner event loop. #[derive(Clone)] @@ -776,7 +770,7 @@ impl App { /// The **Rect** coords are described in "points" (pixels divided by the hidpi factor). /// /// **Panics** if there are no windows or if no window is in focus. - pub fn window_rect(&self) -> geom::Rect { + pub fn window_rect(&self) -> geom::Rect { self.main_window().rect() } diff --git a/nannou/src/draw/background.rs b/nannou/src/draw/background.rs index e39439350..c09d69f7c 100644 --- a/nannou/src/draw/background.rs +++ b/nannou/src/draw/background.rs @@ -1,29 +1,18 @@ use crate::color::{self, IntoLinSrgba, Srgb, Srgba}; use crate::draw::properties::ColorScalar; use crate::draw::Draw; -use crate::geom; -use crate::math::BaseFloat; /// A type used to update the background colour. -pub struct Background<'a, S = geom::scalar::Default> -where - S: 'a + BaseFloat, -{ - draw: &'a Draw, +pub struct Background<'a> { + draw: &'a Draw, } /// Begin coloring the background. -pub fn new<'a, S>(draw: &'a Draw) -> Background<'a, S> -where - S: BaseFloat, -{ +pub fn new<'a>(draw: &'a Draw) -> Background<'a> { Background { draw } } -impl<'a, S> Background<'a, S> -where - S: BaseFloat, -{ +impl<'a> Background<'a> { /// Clear the background with the given color. /// /// This method supports any color type that can be converted into RGBA. @@ -100,10 +89,7 @@ where /// /// See the [wikipedia entry](https://en.wikipedia.org/wiki/HSL_and_HSV) for more details on /// this color space. - pub fn hsva(self, h: ColorScalar, s: ColorScalar, v: ColorScalar, a: ColorScalar) -> Self - where - S: Into>, - { + pub fn hsva(self, h: ColorScalar, s: ColorScalar, v: ColorScalar, a: ColorScalar) -> Self { let hue = h * 360.0; self.color(color::Hsva::new(hue, s, v, a)) } diff --git a/nannou/src/draw/drawing.rs b/nannou/src/draw/drawing.rs index 000470868..9b902039a 100644 --- a/nannou/src/draw/drawing.rs +++ b/nannou/src/draw/drawing.rs @@ -1,12 +1,12 @@ use crate::color::IntoLinSrgba; -use crate::draw::mesh::vertex::Color; +use crate::draw::mesh::vertex::{Color, TexCoords}; use crate::draw::primitive::Primitive; use crate::draw::properties::{ ColorScalar, SetColor, SetDimensions, SetFill, SetOrientation, SetPosition, SetStroke, }; use crate::draw::{self, Draw}; -use crate::geom::{self, Point2, Point3, Vector2, Vector3}; -use crate::math::{Angle, BaseFloat, Euler, Quaternion, Rad}; +use crate::geom::{Point2, Point3}; +use crate::glam::{Quat, Vec2, Vec3}; use lyon::path::PathEvent; use lyon::tessellation::{FillOptions, LineCap, LineJoin, StrokeOptions}; use std::marker::PhantomData; @@ -22,12 +22,9 @@ use std::marker::PhantomData; /// graph. As a result, each **Drawing** is associated with a single, unique node. Thus a /// **Drawing** can be thought of as a way of specifying properties for a node. #[derive(Debug)] -pub struct Drawing<'a, T, S = geom::scalar::Default> -where - S: 'a + BaseFloat, -{ +pub struct Drawing<'a, T> { // The `Draw` instance used to create this drawing. - draw: &'a Draw, + draw: &'a Draw, // The draw command index of the primitive being drawn. index: usize, // Whether or not the **Drawing** should attempt to finish the drawing on drop. @@ -39,24 +36,21 @@ where /// Some context that may be optionally provided to primitives in the drawing implementation. /// /// This is particularly useful for paths and meshes. -pub struct DrawingContext<'a, S> { +pub struct DrawingContext<'a> { /// The intermediary mesh for buffering yet-to-be-drawn paths and meshes. - pub mesh: &'a mut draw::Mesh, + pub mesh: &'a mut draw::Mesh, /// A re-usable buffer for collecting path events. pub path_event_buffer: &'a mut Vec, /// A re-usable buffer for collecting colored polyline points. - pub path_points_colored_buffer: &'a mut Vec<(Point2, Color)>, + pub path_points_colored_buffer: &'a mut Vec<(Point2, Color)>, /// A re-usable buffer for collecting textured polyline points. - pub path_points_textured_buffer: &'a mut Vec<(Point2, Point2)>, + pub path_points_textured_buffer: &'a mut Vec<(Point2, TexCoords)>, /// A re-usable buffer for collecting text. pub text_buffer: &'a mut String, } /// Construct a new **Drawing** instance. -pub fn new<'a, T, S>(draw: &'a Draw, index: usize) -> Drawing<'a, T, S> -where - S: BaseFloat, -{ +pub fn new<'a, T>(draw: &'a Draw, index: usize) -> Drawing<'a, T> { let _ty = PhantomData; let finish_on_drop = true; Drawing { @@ -67,10 +61,7 @@ where } } -impl<'a, T, S> Drop for Drawing<'a, T, S> -where - S: BaseFloat, -{ +impl<'a, T> Drop for Drawing<'a, T> { fn drop(&mut self) { if self.finish_on_drop { self.finish_inner(); @@ -78,9 +69,9 @@ where } } -impl<'a, S> DrawingContext<'a, S> { +impl<'a> DrawingContext<'a> { // Initialise the DrawingContext from the draw's IntermediaryState. - pub(crate) fn from_intermediary_state(state: &'a mut super::IntermediaryState) -> Self { + pub(crate) fn from_intermediary_state(state: &'a mut super::IntermediaryState) -> Self { let super::IntermediaryState { ref mut intermediary_mesh, ref mut path_event_buffer, @@ -98,10 +89,7 @@ impl<'a, S> DrawingContext<'a, S> { } } -impl<'a, T, S> Drawing<'a, T, S> -where - S: BaseFloat, -{ +impl<'a, T> Drawing<'a, T> { // Shared between the **finish** method and the **Drawing**'s **Drop** implementation. // // 1. Create vertices based on node-specific position, points, etc. @@ -123,10 +111,10 @@ where // Map the given function onto the primitive stored within **Draw** at `index`. // // The functionn is only applied if the node has not yet been **Drawn**. - fn map_primitive(mut self, map: F) -> Drawing<'a, T2, S> + fn map_primitive(mut self, map: F) -> Drawing<'a, T2> where - F: FnOnce(Primitive) -> Primitive, - T2: Into>, + F: FnOnce(Primitive) -> Primitive, + T2: Into, { if let Ok(mut state) = self.draw.state.try_borrow_mut() { if let Some(mut primitive) = state.drawing.remove(&self.index) { @@ -147,10 +135,10 @@ where // The same as `map_primitive` but also passes a mutable reference to the vertex data to the // map function. This is useful for types that may have an unknown number of arbitrary // vertices. - fn map_primitive_with_context(mut self, map: F) -> Drawing<'a, T2, S> + fn map_primitive_with_context(mut self, map: F) -> Drawing<'a, T2> where - F: FnOnce(Primitive, DrawingContext) -> Primitive, - T2: Into>, + F: FnOnce(Primitive, DrawingContext) -> Primitive, + T2: Into, { if let Ok(mut state) = self.draw.state.try_borrow_mut() { if let Some(mut primitive) = state.drawing.remove(&self.index) { @@ -177,11 +165,11 @@ where /// The function is only applied if the node has not yet been **Drawn**. /// /// **Panics** if the primitive does not contain type **T**. - pub fn map_ty(self, map: F) -> Drawing<'a, T2, S> + pub fn map_ty(self, map: F) -> Drawing<'a, T2> where F: FnOnce(T) -> T2, - T2: Into>, - Primitive: Into>, + T2: Into, + Primitive: Into>, { self.map_primitive(|prim| { let maybe_ty: Option = prim.into(); @@ -196,11 +184,11 @@ where /// The function is only applied if the node has not yet been **Drawn**. /// /// **Panics** if the primitive does not contain type **T**. - pub(crate) fn map_ty_with_context(self, map: F) -> Drawing<'a, T2, S> + pub(crate) fn map_ty_with_context(self, map: F) -> Drawing<'a, T2> where - F: FnOnce(T, DrawingContext) -> T2, - T2: Into>, - Primitive: Into>, + F: FnOnce(T, DrawingContext) -> T2, + T2: Into, + Primitive: Into>, { self.map_primitive_with_context(|prim, ctxt| { let maybe_ty: Option = prim.into(); @@ -213,11 +201,10 @@ where // SetColor implementations. -impl<'a, T, S> Drawing<'a, T, S> +impl<'a, T> Drawing<'a, T> where - T: SetColor + Into>, - Primitive: Into>, - S: BaseFloat, + T: SetColor + Into, + Primitive: Into>, { /// Specify a color. /// @@ -313,226 +300,192 @@ where // SetDimensions implementations. -impl<'a, T, S> Drawing<'a, T, S> +impl<'a, T> Drawing<'a, T> where - T: SetDimensions + Into>, - Primitive: Into>, - S: BaseFloat, + T: SetDimensions + Into, + Primitive: Into>, { /// Set the absolute width for the node. - pub fn width(self, w: S) -> Self { + pub fn width(self, w: f32) -> Self { self.map_ty(|ty| SetDimensions::width(ty, w)) } /// Set the absolute height for the node. - pub fn height(self, h: S) -> Self { + pub fn height(self, h: f32) -> Self { self.map_ty(|ty| SetDimensions::height(ty, h)) } /// Set the absolute depth for the node. - pub fn depth(self, d: S) -> Self { + pub fn depth(self, d: f32) -> Self { self.map_ty(|ty| SetDimensions::depth(ty, d)) } /// Short-hand for the **width** method. - pub fn w(self, w: S) -> Self { + pub fn w(self, w: f32) -> Self { self.map_ty(|ty| SetDimensions::w(ty, w)) } /// Short-hand for the **height** method. - pub fn h(self, h: S) -> Self { + pub fn h(self, h: f32) -> Self { self.map_ty(|ty| SetDimensions::h(ty, h)) } /// Short-hand for the **depth** method. - pub fn d(self, d: S) -> Self { + pub fn d(self, d: f32) -> Self { self.map_ty(|ty| SetDimensions::d(ty, d)) } /// Set the **x** and **y** dimensions for the node. - pub fn wh(self, v: Vector2) -> Self { + pub fn wh(self, v: Vec2) -> Self { self.map_ty(|ty| SetDimensions::wh(ty, v)) } /// Set the **x**, **y** and **z** dimensions for the node. - pub fn whd(self, v: Vector3) -> Self { + pub fn whd(self, v: Vec3) -> Self { self.map_ty(|ty| SetDimensions::whd(ty, v)) } /// Set the width and height for the node. - pub fn w_h(self, x: S, y: S) -> Self { + pub fn w_h(self, x: f32, y: f32) -> Self { self.map_ty(|ty| SetDimensions::w_h(ty, x, y)) } /// Set the width and height for the node. - pub fn w_h_d(self, x: S, y: S, z: S) -> Self { + pub fn w_h_d(self, x: f32, y: f32, z: f32) -> Self { self.map_ty(|ty| SetDimensions::w_h_d(ty, x, y, z)) } } // SetPosition methods. -impl<'a, T, S> Drawing<'a, T, S> +impl<'a, T> Drawing<'a, T> where - T: SetPosition + Into>, - Primitive: Into>, - S: BaseFloat, + T: SetPosition + Into, + Primitive: Into>, { /// Build with the given **Absolute** **Position** along the *x* axis. - pub fn x(self, x: S) -> Self { + pub fn x(self, x: f32) -> Self { self.map_ty(|ty| SetPosition::x(ty, x)) } /// Build with the given **Absolute** **Position** along the *y* axis. - pub fn y(self, y: S) -> Self { + pub fn y(self, y: f32) -> Self { self.map_ty(|ty| SetPosition::y(ty, y)) } /// Build with the given **Absolute** **Position** along the *z* axis. - pub fn z(self, z: S) -> Self { + pub fn z(self, z: f32) -> Self { self.map_ty(|ty| SetPosition::z(ty, z)) } /// Set the **Position** with some two-dimensional point. - pub fn xy(self, p: Point2) -> Self { + pub fn xy(self, p: Point2) -> Self { self.map_ty(|ty| SetPosition::xy(ty, p)) } /// Set the **Position** with some three-dimensional point. - pub fn xyz(self, p: Point3) -> Self { + pub fn xyz(self, p: Point3) -> Self { self.map_ty(|ty| SetPosition::xyz(ty, p)) } /// Set the **Position** with *x* *y* coordinates. - pub fn x_y(self, x: S, y: S) -> Self { + pub fn x_y(self, x: f32, y: f32) -> Self { self.map_ty(|ty| SetPosition::x_y(ty, x, y)) } /// Set the **Position** with *x* *y* *z* coordinates. - pub fn x_y_z(self, x: S, y: S, z: S) -> Self { + pub fn x_y_z(self, x: f32, y: f32, z: f32) -> Self { self.map_ty(|ty| SetPosition::x_y_z(ty, x, y, z)) } } // SetOrientation methods. -impl<'a, T, S> Drawing<'a, T, S> +impl<'a, T> Drawing<'a, T> where - T: SetOrientation + Into>, - Primitive: Into>, - S: BaseFloat, + T: SetOrientation + Into, + Primitive: Into>, { /// Describe orientation via the vector that points to the given target. - pub fn look_at(self, target: Point3) -> Self { + pub fn look_at(self, target: Point3) -> Self { self.map_ty(|ty| SetOrientation::look_at(ty, target)) } /// Specify the orientation around the *x* axis as an absolute value in radians. - pub fn x_radians(self, x: S) -> Self { + pub fn x_radians(self, x: f32) -> Self { self.map_ty(|ty| SetOrientation::x_radians(ty, x)) } /// Specify the orientation around the *y* axis as an absolute value in radians. - pub fn y_radians(self, y: S) -> Self { + pub fn y_radians(self, y: f32) -> Self { self.map_ty(|ty| SetOrientation::y_radians(ty, y)) } /// Specify the orientation around the *z* axis as an absolute value in radians. - pub fn z_radians(self, z: S) -> Self { + pub fn z_radians(self, z: f32) -> Self { self.map_ty(|ty| SetOrientation::z_radians(ty, z)) } /// Specify the orientation around the *x* axis as an absolute value in degrees. - pub fn x_degrees(self, x: S) -> Self - where - S: BaseFloat, - { + pub fn x_degrees(self, x: f32) -> Self { self.map_ty(|ty| SetOrientation::x_degrees(ty, x)) } /// Specify the orientation around the *y* axis as an absolute value in degrees. - pub fn y_degrees(self, y: S) -> Self - where - S: BaseFloat, - { + pub fn y_degrees(self, y: f32) -> Self { self.map_ty(|ty| SetOrientation::y_degrees(ty, y)) } /// Specify the orientation around the *z* axis as an absolute value in degrees. - pub fn z_degrees(self, z: S) -> Self - where - S: BaseFloat, - { + pub fn z_degrees(self, z: f32) -> Self { self.map_ty(|ty| SetOrientation::z_degrees(ty, z)) } /// Specify the orientation around the *x* axis as a number of turns around the axis. - pub fn x_turns(self, x: S) -> Self - where - S: BaseFloat, - { + pub fn x_turns(self, x: f32) -> Self { self.map_ty(|ty| SetOrientation::x_turns(ty, x)) } /// Specify the orientation around the *y* axis as a number of turns around the axis. - pub fn y_turns(self, y: S) -> Self - where - S: BaseFloat, - { + pub fn y_turns(self, y: f32) -> Self { self.map_ty(|ty| SetOrientation::y_turns(ty, y)) } /// Specify the orientation around the *z* axis as a number of turns around the axis. - pub fn z_turns(self, z: S) -> Self - where - S: BaseFloat, - { + pub fn z_turns(self, z: f32) -> Self { self.map_ty(|ty| SetOrientation::z_turns(ty, z)) } /// Specify the orientation along each axis with the given **Vector** of radians. /// /// This has the same affect as calling `self.x_radians(v.x).y_radians(v.y).z_radians(v.z)`. - pub fn radians(self, v: Vector3) -> Self { + pub fn radians(self, v: Vec3) -> Self { self.map_ty(|ty| SetOrientation::radians(ty, v)) } /// Specify the orientation along each axis with the given **Vector** of degrees. /// /// This has the same affect as calling `self.x_degrees(v.x).y_degrees(v.y).z_degrees(v.z)`. - pub fn degrees(self, v: Vector3) -> Self - where - S: BaseFloat, - { + pub fn degrees(self, v: Vec3) -> Self { self.map_ty(|ty| SetOrientation::degrees(ty, v)) } /// Specify the orientation along each axis with the given **Vector** of "turns". /// /// This has the same affect as calling `self.x_turns(v.x).y_turns(v.y).z_turns(v.z)`. - pub fn turns(self, v: Vector3) -> Self - where - S: BaseFloat, - { + pub fn turns(self, v: Vec3) -> Self { self.map_ty(|ty| SetOrientation::turns(ty, v)) } /// Specify the orientation with the given **Euler**. /// - /// The euler can be specified in either radians (via **Rad**) or degrees (via **Deg**). - pub fn euler(self, e: Euler) -> Self - where - S: BaseFloat, - A: Angle + Into>, - { + /// The euler must be specified in radians. + pub fn euler(self, e: Vec3) -> Self { self.map_ty(|ty| SetOrientation::euler(ty, e)) } /// Specify the orientation with the given **Quaternion**. - pub fn quaternion(self, q: Quaternion) -> Self - where - S: BaseFloat, - { + pub fn quaternion(self, q: Quat) -> Self { self.map_ty(|ty| SetOrientation::quaternion(ty, q)) } @@ -541,21 +494,21 @@ where /// Specify the "pitch" of the orientation in radians. /// /// This has the same effect as calling `x_radians`. - pub fn pitch(self, pitch: S) -> Self { + pub fn pitch(self, pitch: f32) -> Self { self.map_ty(|ty| SetOrientation::pitch(ty, pitch)) } /// Specify the "yaw" of the orientation in radians. /// /// This has the same effect as calling `y_radians`. - pub fn yaw(self, yaw: S) -> Self { + pub fn yaw(self, yaw: f32) -> Self { self.map_ty(|ty| SetOrientation::yaw(ty, yaw)) } /// Specify the "roll" of the orientation in radians. /// /// This has the same effect as calling `z_radians`. - pub fn roll(self, roll: S) -> Self { + pub fn roll(self, roll: f32) -> Self { self.map_ty(|ty| SetOrientation::roll(ty, roll)) } @@ -563,18 +516,17 @@ where /// given value is specified in radians. /// /// This is equivalent to calling the `z_radians` or `roll` methods. - pub fn rotate(self, radians: S) -> Self { + pub fn rotate(self, radians: f32) -> Self { self.map_ty(|ty| SetOrientation::rotate(ty, radians)) } } // SetFill methods -impl<'a, T, S> Drawing<'a, T, S> +impl<'a, T> Drawing<'a, T> where - T: SetFill + Into>, - Primitive: Into>, - S: BaseFloat, + T: SetFill + Into, + Primitive: Into>, { /// Specify the whole set of fill tessellation options. pub fn fill_opts(self, opts: FillOptions) -> Self { @@ -614,11 +566,10 @@ where // SetStroke methods -impl<'a, T, S> Drawing<'a, T, S> +impl<'a, T> Drawing<'a, T> where - T: SetStroke + Into>, - Primitive: Into>, - S: BaseFloat, + T: SetStroke + Into, + Primitive: Into>, { /// The start line cap as specified by the SVG spec. pub fn start_cap(self, cap: LineCap) -> Self { diff --git a/nannou/src/draw/mesh/builder.rs b/nannou/src/draw/mesh/builder.rs index dc7186739..232b0b901 100644 --- a/nannou/src/draw/mesh/builder.rs +++ b/nannou/src/draw/mesh/builder.rs @@ -6,8 +6,8 @@ //! Lyon tessellators assume `f32` data, so we do the same in the following implementations. use crate::draw; -use crate::geom; -use cgmath::Matrix4; +use crate::geom::Point2; +use crate::glam::Mat4; use lyon::tessellation::geometry_builder::{ self, FillGeometryBuilder, GeometryBuilder, StrokeGeometryBuilder, }; @@ -21,7 +21,7 @@ pub struct MeshBuilder<'a, A> { /// The number of indices in the mesh when begin was called. begin_index_count: u32, /// Transform matrix that also integrates position and orientation here. - transform: Matrix4, + transform: Mat4, /// The way in which vertex attributes should be sourced. attributes: A, } @@ -32,7 +32,7 @@ pub struct TexCoordsPerPoint; impl<'a, A> MeshBuilder<'a, A> { /// Begin extending the mesh. - fn new(mesh: &'a mut draw::Mesh, transform: Matrix4, attributes: A) -> Self { + fn new(mesh: &'a mut draw::Mesh, transform: Mat4, attributes: A) -> Self { MeshBuilder { mesh, begin_vertex_count: 0, @@ -47,7 +47,7 @@ impl<'a> MeshBuilder<'a, SingleColor> { /// Begin extending a mesh rendered with a single colour. pub fn single_color( mesh: &'a mut draw::Mesh, - transform: Matrix4, + transform: Mat4, color: draw::mesh::vertex::Color, ) -> Self { Self::new(mesh, transform, SingleColor(color)) @@ -56,14 +56,14 @@ impl<'a> MeshBuilder<'a, SingleColor> { impl<'a> MeshBuilder<'a, ColorPerPoint> { /// Begin extending a mesh where the path interpolates a unique color per point. - pub fn color_per_point(mesh: &'a mut draw::Mesh, transform: Matrix4) -> Self { + pub fn color_per_point(mesh: &'a mut draw::Mesh, transform: Mat4) -> Self { Self::new(mesh, transform, ColorPerPoint) } } impl<'a> MeshBuilder<'a, TexCoordsPerPoint> { /// Begin extending a mesh where the path interpolates a unique texture coordinates per point. - pub fn tex_coords_per_point(mesh: &'a mut draw::Mesh, transform: Matrix4) -> Self { + pub fn tex_coords_per_point(mesh: &'a mut draw::Mesh, transform: Mat4) -> Self { Self::new(mesh, transform, TexCoordsPerPoint) } } @@ -102,9 +102,8 @@ impl<'a> FillGeometryBuilder for MeshBuilder<'a, SingleColor> { let id = VertexId::from_usize(self.mesh.points().len()); // Construct and insert the point - let p = geom::Point3::from(geom::Point2::from(position)); - let p = cgmath::Transform::transform_point(&self.transform, p.into()); - let point = geom::vec3(p.x, p.y, p.z); + let p = Point2::new(position.x, position.y).extend(0.0); + let point = self.transform.transform_point3(p); let SingleColor(color) = self.attributes; let tex_coords = draw::mesh::vertex::default_tex_coords(); let vertex = draw::mesh::vertex::new(point, color, tex_coords); @@ -125,9 +124,8 @@ impl<'a> StrokeGeometryBuilder for MeshBuilder<'a, SingleColor> { let id = VertexId::from_usize(self.mesh.points().len()); // Construct and insert the point - let p = geom::Point3::from(geom::Point2::from(position)); - let p = cgmath::Transform::transform_point(&self.transform, p.into()); - let point = geom::vec3(p.x, p.y, p.z); + let p = Point2::new(position.x, position.y).extend(0.0); + let point = self.transform.transform_point3(p); let SingleColor(color) = self.attributes; let tex_coords = draw::mesh::vertex::default_tex_coords(); let vertex = draw::mesh::vertex::new(point, color, tex_coords); @@ -148,9 +146,8 @@ impl<'a> FillGeometryBuilder for MeshBuilder<'a, ColorPerPoint> { let id = VertexId::from_usize(self.mesh.points().len()); // Construct and insert the point - let p = geom::Point3::from(geom::Point2::from(position)); - let p = cgmath::Transform::transform_point(&self.transform, p.into()); - let point = geom::vec3(p.x, p.y, p.z); + let p = Point2::new(position.x, position.y).extend(0.0); + let point = self.transform.transform_point3(p); let col = &attrs.interpolated_attributes(); let color: draw::mesh::vertex::Color = (col[0], col[1], col[2], col[3]).into(); let tex_coords = draw::mesh::vertex::default_tex_coords(); @@ -172,9 +169,8 @@ impl<'a> StrokeGeometryBuilder for MeshBuilder<'a, ColorPerPoint> { let id = VertexId::from_usize(self.mesh.points().len()); // Construct and insert the point - let p = geom::Point3::from(geom::Point2::from(position)); - let p = cgmath::Transform::transform_point(&self.transform, p.into()); - let point = geom::vec3(p.x, p.y, p.z); + let p = Point2::new(position.x, position.y).extend(0.0); + let point = self.transform.transform_point3(p); let col = &attrs.interpolated_attributes(); let color: draw::mesh::vertex::Color = (col[0], col[1], col[2], col[3]).into(); let tex_coords = draw::mesh::vertex::default_tex_coords(); @@ -196,9 +192,8 @@ impl<'a> FillGeometryBuilder for MeshBuilder<'a, TexCoordsPerPoint> { let id = VertexId::from_usize(self.mesh.points().len()); // Construct and insert the point - let p = geom::Point3::from(geom::Point2::from(position)); - let p = cgmath::Transform::transform_point(&self.transform, p.into()); - let point = geom::vec3(p.x, p.y, p.z); + let p = Point2::new(position.x, position.y).extend(0.0); + let point = self.transform.transform_point3(p); let tc = &attrs.interpolated_attributes(); let tex_coords: draw::mesh::vertex::TexCoords = (tc[0], tc[1]).into(); let color = draw::mesh::vertex::DEFAULT_VERTEX_COLOR; @@ -220,9 +215,8 @@ impl<'a> StrokeGeometryBuilder for MeshBuilder<'a, TexCoordsPerPoint> { let id = VertexId::from_usize(self.mesh.points().len()); // Construct and insert the point - let p = geom::Point3::from(geom::Point2::from(position)); - let p = cgmath::Transform::transform_point(&self.transform, p.into()); - let point = geom::vec3(p.x, p.y, p.z); + let p = Point2::new(position.x, position.y).extend(0.0); + let point = self.transform.transform_point3(p); let tc = &attrs.interpolated_attributes(); let tex_coords: draw::mesh::vertex::TexCoords = (tc[0], tc[1]).into(); let color = draw::mesh::vertex::DEFAULT_VERTEX_COLOR; diff --git a/nannou/src/draw/mesh/mod.rs b/nannou/src/draw/mesh/mod.rs index 201089c2d..3bc07f73e 100644 --- a/nannou/src/draw/mesh/mod.rs +++ b/nannou/src/draw/mesh/mod.rs @@ -10,22 +10,22 @@ pub mod vertex; pub use self::builder::MeshBuilder; pub use self::vertex::Vertex; -pub type Points = Vec>; +pub type Points = Vec; pub type Indices = Vec; pub type Colors = Vec; -pub type TexCoords = Vec>; +pub type TexCoords = Vec; /// The inner mesh type used by the **draw::Mesh**. -pub type MeshType = - WithTexCoords>, Indices>, Colors>, TexCoords>; +pub type MeshType = + WithTexCoords, Indices>, Colors>, TexCoords>; /// The custom mesh type used internally by the **Draw** API. #[derive(Clone, Debug)] -pub struct Mesh { - mesh: MeshType, +pub struct Mesh { + mesh: MeshType, } -impl Mesh { +impl Mesh { /// The number of raw vertices contained within the mesh. pub fn raw_vertex_count(&self) -> usize { mesh::raw_vertex_count(self) @@ -42,7 +42,7 @@ impl Mesh { } /// The **Mesh**'s vertex position channel. - pub fn points(&self) -> &[vertex::Point] { + pub fn points(&self) -> &[vertex::Point] { mesh::Points::points(self) } @@ -57,12 +57,12 @@ impl Mesh { } /// The **Mesh**'s vertex texture coordinates channel. - pub fn tex_coords(&self) -> &[vertex::TexCoords] { + pub fn tex_coords(&self) -> &[vertex::TexCoords] { mesh::TexCoords::tex_coords(self) } /// Push the given vertex onto the inner channels. - pub fn push_vertex(&mut self, v: Vertex) { + pub fn push_vertex(&mut self, v: Vertex) { mesh::push_vertex(self, v); } @@ -74,7 +74,7 @@ impl Mesh { /// Extend the mesh channels with the given vertices. pub fn extend_vertices(&mut self, vs: I) where - I: IntoIterator>, + I: IntoIterator, { mesh::extend_vertices(self, vs); } @@ -90,7 +90,7 @@ impl Mesh { /// Extend the **Mesh** with the given vertices and indices. pub fn extend(&mut self, vs: V, is: I) where - V: IntoIterator>, + V: IntoIterator, I: IntoIterator, { self.extend_vertices(vs); @@ -121,12 +121,7 @@ impl Mesh { pub fn into_raw_vertices(self) -> mesh::RawVertices { mesh::raw_vertices(self) } -} -impl Mesh -where - S: Clone, -{ /// Extend the mesh from the given slices. /// /// This is faster than `extend` which uses iteration internally. @@ -134,10 +129,10 @@ where /// **Panic!**s if the length of the given points, colors and tex_coords slices do not match. pub fn extend_from_slices( &mut self, - points: &[vertex::Point], + points: &[vertex::Point], indices: &[u32], colors: &[vertex::Color], - tex_coords: &[vertex::TexCoords], + tex_coords: &[vertex::TexCoords], ) { assert_eq!(points.len(), colors.len()); assert_eq!(points.len(), tex_coords.len()); @@ -148,9 +143,9 @@ where /// Extend the mesh with the given slices of vertices. pub fn extend_vertices_from_slices( &mut self, - points: &[vertex::Point], + points: &[vertex::Point], colors: &[vertex::Color], - tex_coords: &[vertex::TexCoords], + tex_coords: &[vertex::TexCoords], ) { self.extend_from_slices(points, &[], colors, tex_coords); } @@ -181,45 +176,42 @@ where } } -impl Default for Mesh { +impl Default for Mesh { fn default() -> Self { let mesh = Default::default(); Mesh { mesh } } } -impl Deref for Mesh { - type Target = MeshType; +impl Deref for Mesh { + type Target = MeshType; fn deref(&self) -> &Self::Target { &self.mesh } } -impl DerefMut for Mesh { +impl DerefMut for Mesh { fn deref_mut(&mut self) -> &mut Self::Target { &mut self.mesh } } -impl mesh::GetVertex for Mesh -where - S: Clone, -{ - type Vertex = Vertex; +impl mesh::GetVertex for Mesh { + type Vertex = Vertex; fn get_vertex(&self, index: u32) -> Option { mesh::WithTexCoords::get_vertex(&self.mesh, index) } } -impl mesh::Points for Mesh { - type Point = vertex::Point; - type Points = Points; +impl mesh::Points for Mesh { + type Point = vertex::Point; + type Points = Points; fn points(&self) -> &Self::Points { self.mesh.points() } } -impl mesh::Indices for Mesh { +impl mesh::Indices for Mesh { type Index = u32; type Indices = Indices; fn indices(&self) -> &Self::Indices { @@ -227,7 +219,7 @@ impl mesh::Indices for Mesh { } } -impl mesh::Colors for Mesh { +impl mesh::Colors for Mesh { type Color = vertex::Color; type Colors = Colors; fn colors(&self) -> &Self::Colors { @@ -235,21 +227,21 @@ impl mesh::Colors for Mesh { } } -impl mesh::TexCoords for Mesh { - type TexCoord = geom::Point2; - type TexCoords = TexCoords; +impl mesh::TexCoords for Mesh { + type TexCoord = geom::Point2; + type TexCoords = TexCoords; fn tex_coords(&self) -> &Self::TexCoords { self.mesh.tex_coords() } } -impl mesh::PushVertex> for Mesh { - fn push_vertex(&mut self, v: Vertex) { +impl mesh::PushVertex for Mesh { + fn push_vertex(&mut self, v: Vertex) { self.mesh.push_vertex(v); } } -impl mesh::PushIndex for Mesh { +impl mesh::PushIndex for Mesh { type Index = u32; fn push_index(&mut self, index: Self::Index) { @@ -264,13 +256,13 @@ impl mesh::PushIndex for Mesh { } } -impl mesh::ClearIndices for Mesh { +impl mesh::ClearIndices for Mesh { fn clear_indices(&mut self) { self.mesh.clear_indices(); } } -impl mesh::ClearVertices for Mesh { +impl mesh::ClearVertices for Mesh { fn clear_vertices(&mut self) { self.mesh.clear_vertices(); } diff --git a/nannou/src/draw/mesh/vertex.rs b/nannou/src/draw/mesh/vertex.rs index 558079d2e..df738cc92 100644 --- a/nannou/src/draw/mesh/vertex.rs +++ b/nannou/src/draw/mesh/vertex.rs @@ -1,19 +1,16 @@ use crate::color; -use crate::geom::{self, Point2, Point3, Vector3}; -use crate::math::BaseFloat; +use crate::geom::{Point2, Point3, Vec3}; use crate::mesh::vertex::{WithColor, WithTexCoords}; -use std::marker::PhantomData; -pub type Point = Point3; +pub type Point = Point3; pub type Color = color::LinSrgba; -pub type TexCoords = Point2; -pub type Normal = Vector3; -pub type ColoredPoint = WithColor, Color>; -pub type ColoredPoint2 = WithColor, Color>; +pub type TexCoords = Point2; +pub type Normal = Vec3; +pub type ColoredPoint = WithColor; +pub type ColoredPoint2 = WithColor; /// The vertex type produced by the **draw::Mesh**'s inner **MeshType**. -pub type Vertex = - WithTexCoords, Color>, TexCoords>; +pub type Vertex = WithTexCoords, TexCoords>; /// The number of channels in the color type. pub const COLOR_CHANNEL_COUNT: usize = 4; @@ -29,7 +26,7 @@ pub const DEFAULT_VERTEX_COLOR: Color = color::Alpha { }; /// Simplified constructor for a **draw::mesh::Vertex**. -pub fn new(point: Point, color: Color, tex_coords: TexCoords) -> Vertex { +pub fn new(point: Point, color: Color, tex_coords: TexCoords) -> Vertex { WithTexCoords { tex_coords, vertex: WithColor { @@ -40,24 +37,18 @@ pub fn new(point: Point, color: Color, tex_coords: TexCoords) -> Vertex } /// Default texture coordinates, for the case where a type is not textured. -pub fn default_tex_coords() -> TexCoords -where - S: BaseFloat, -{ - Point2 { - x: S::zero(), - y: S::zero(), - } +pub fn default_tex_coords() -> TexCoords { + [0.0; 2].into() } -impl Vertex { +impl Vertex { /// Borrow the inner **Point**. - pub fn point(&self) -> &Point { + pub fn point(&self) -> &Point { &self.vertex.vertex } /// Mutably borrow the inner **Point**. - pub fn point_mut(&mut self) -> &mut Point { + pub fn point_mut(&mut self) -> &mut Point { &mut self.vertex.vertex } } @@ -66,36 +57,30 @@ impl Vertex { /// /// Default values are used for tex_coords. #[derive(Clone, Debug)] -pub struct IterFromColoredPoints { +pub struct IterFromColoredPoints { colored_points: I, - _scalar: PhantomData, } -impl IterFromColoredPoints { +impl IterFromColoredPoints { /// Produce an iterator that converts an iterator yielding colored points to an iterator /// yielding **Vertex**s. /// /// The default value of `(0.0, 0.0)` is used for tex_coords. pub fn new

(colored_points: P) -> Self where - P: IntoIterator, Color>>, - I: Iterator, Color>>, + P: IntoIterator>, + I: Iterator>, { let colored_points = colored_points.into_iter(); - let _scalar = PhantomData; - IterFromColoredPoints { - colored_points, - _scalar, - } + IterFromColoredPoints { colored_points } } } -impl Iterator for IterFromColoredPoints +impl Iterator for IterFromColoredPoints where - I: Iterator, Color>>, - S: BaseFloat, + I: Iterator>, { - type Item = Vertex; + type Item = Vertex; fn next(&mut self) -> Option { self.colored_points.next().map(|vertex| { let tex_coords = default_tex_coords(); @@ -111,10 +96,9 @@ where /// /// The default value of `(0.0, 0.0)` is used for tex_coords. #[derive(Clone, Debug)] -pub struct IterFromPoints { +pub struct IterFromPoints { points: I, default_color: Color, - _scalar: PhantomData, } /// A type that converts an iterator yielding 2D points to an iterator yielding **Vertex**s. @@ -125,13 +109,12 @@ pub struct IterFromPoints { /// /// The default value of `(0.0, 0.0)` is used for tex_coords. #[derive(Clone, Debug)] -pub struct IterFromPoint2s { +pub struct IterFromPoint2s { points: I, default_color: Color, - _scalar: PhantomData, } -impl IterFromPoints { +impl IterFromPoints { /// Produce an iterator that converts an iterator yielding points to an iterator yielding /// **Vertex**s. /// @@ -140,20 +123,18 @@ impl IterFromPoints { /// The default value of `(0.0, 0.0)` is used for tex_coords. pub fn new

(points: P, default_color: Color) -> Self where - P: IntoIterator>, - I: Iterator>, + P: IntoIterator, + I: Iterator, { let points = points.into_iter(); - let _scalar = PhantomData; IterFromPoints { points, default_color, - _scalar, } } } -impl IterFromPoint2s { +impl IterFromPoint2s { /// A type that converts an iterator yielding 2D points to an iterator yielding **Vertex**s. /// /// The `z` position for each vertex will be `0.0`. @@ -163,25 +144,22 @@ impl IterFromPoint2s { /// The default value of `(0.0, 0.0)` is used for tex_coords. pub fn new

(points: P, default_color: Color) -> Self where - P: IntoIterator>, - I: Iterator>, + P: IntoIterator, + I: Iterator, { let points = points.into_iter(); - let _scalar = PhantomData; IterFromPoint2s { points, default_color, - _scalar, } } } -impl Iterator for IterFromPoints +impl Iterator for IterFromPoints where - I: Iterator>, - S: BaseFloat, + I: Iterator, { - type Item = Vertex; + type Item = Vertex; fn next(&mut self) -> Option { self.points.next().map(|vertex| { let color = self.default_color; @@ -193,15 +171,14 @@ where } } -impl Iterator for IterFromPoint2s +impl Iterator for IterFromPoint2s where - I: Iterator>, - S: BaseFloat, + I: Iterator, { - type Item = Vertex; + type Item = Vertex; fn next(&mut self) -> Option { - self.points.next().map(|Point2 { x, y }| { - let vertex = Point3 { x, y, z: S::zero() }; + self.points.next().map(|p| { + let vertex = p.extend(0.0); let color = self.default_color; let vertex = WithColor { vertex, color }; let tex_coords = default_tex_coords(); diff --git a/nannou/src/draw/mod.rs b/nannou/src/draw/mod.rs index ab821e148..aee06422c 100644 --- a/nannou/src/draw/mod.rs +++ b/nannou/src/draw/mod.rs @@ -3,7 +3,8 @@ //! See the [**Draw** type](./struct.Draw.html) for more details. use crate::geom::{self, Point2}; -use crate::math::{deg_to_rad, turns_to_rad, BaseFloat, Matrix4, SquareMatrix}; +use crate::glam::{vec3, EulerRot, Mat4, Quat, Vec2, Vec3}; +use crate::math::{deg_to_rad, turns_to_rad}; use crate::wgpu; use lyon::path::PathEvent; use std::cell::RefCell; @@ -13,7 +14,7 @@ use std::rc::Rc; pub use self::background::Background; pub use self::drawing::{Drawing, DrawingContext}; -use self::mesh::vertex::Color; +use self::mesh::vertex::{Color, TexCoords}; pub use self::mesh::Mesh; use self::primitive::Primitive; pub use self::renderer::{Builder as RendererBuilder, Renderer}; @@ -42,10 +43,7 @@ pub mod theme; /// See the [draw](https://github.com/nannou-org/nannou/blob/master/examples) examples for a /// variety of demonstrations of how the **Draw** type can be used! #[derive(Clone, Debug)] -pub struct Draw -where - S: BaseFloat, -{ +pub struct Draw { /// The state of the **Draw**. /// /// State is shared between this **Draw** instance and all other **Draw** instances that were @@ -55,17 +53,17 @@ where /// purpose of a **Draw** is to be an easy-as-possible, high-level API for drawing stuff. In /// order to be friendlier to new users, we want to avoid them having to think about mutability /// and focus on creativity. Rust-lang nuances can come later. - state: Rc>>, + state: Rc>, /// The current context of this **Draw** instance. - context: Context, + context: Context, } /// The current **Transform**, alpha **BlendState** and **Scissor** of a **Draw** instance. #[derive(Clone, Debug, PartialEq)] -pub struct Context { - pub transform: Matrix4, +pub struct Context { + pub transform: Mat4, pub blend: wgpu::BlendState, - pub scissor: Scissor, + pub scissor: Scissor, // TODO: Consider changing `PolygonMode` (added as of wgpu 0.7) rather than `PrimitiveTopology` // here. pub topology: wgpu::PrimitiveTopology, @@ -77,20 +75,20 @@ pub struct Context { /// During rendering, the list of **DrawCommand**s are converted into a list of **RenderCommands** /// that are directly associated with encodable render pass commands. #[derive(Clone, Debug)] -pub enum DrawCommand { +pub enum DrawCommand { /// Draw a primitive. - Primitive(Primitive), + Primitive(Primitive), /// A change in the rendering context occurred. - Context(Context), + Context(Context), } /// The scissor for a **Draw**'s render context. #[derive(Clone, Copy, Debug, PartialEq)] -pub enum Scissor { +pub enum Scissor { /// The extent of the scissor matches the bounds of the target texture. Full, /// Crop the view to the given rect. - Rect(geom::Rect), + Rect(geom::Rect), /// The scissor has no overlap with the previous window, resulting in nothing to draw. NoOverlap, } @@ -103,44 +101,41 @@ pub enum Scissor { /// drawing stuff. In order to be friendlier to new users, we want to avoid requiring them to think /// about mutability and instead focus on creativity. Rust-lang nuances can come later. #[derive(Clone, Debug)] -pub struct State -where - S: BaseFloat, -{ +pub struct State { /// The last context used to draw an image, used to detect changes and emit commands for them. - last_draw_context: Option>, + last_draw_context: Option, /// If `Some`, the **Draw** should first clear the frame's texture with the given color. background_color: Option, /// Primitives that are in the process of being drawn. /// /// Keys are indices into the `draw_commands` Vec. - drawing: HashMap>, + drawing: HashMap, /// The list of recorded draw commands. /// /// An element may be `None` if it is a primitive in the process of being drawn. - draw_commands: Vec>>, + draw_commands: Vec>, /// State made accessible via the `DrawingContext`. - intermediary_state: RefCell>, + intermediary_state: RefCell, /// The theme containing default values. theme: Theme, } /// State made accessible via the `DrawingContext`. #[derive(Clone, Debug)] -pub struct IntermediaryState { +pub struct IntermediaryState { /// Buffers of vertex data that may be re-used for paths, meshes, etc between view calls. - intermediary_mesh: Mesh, + intermediary_mesh: Mesh, /// A re-usable buffer for collecting path events. path_event_buffer: Vec, /// A re-usable buffer for collecting colored polyline points. - path_points_colored_buffer: Vec<(Point2, Color)>, + path_points_colored_buffer: Vec<(Point2, Color)>, /// A re-usable buffer for collecting textured polyline points. - path_points_textured_buffer: Vec<(Point2, Point2)>, + path_points_textured_buffer: Vec<(Point2, TexCoords)>, /// A buffer containing all text. text_buffer: String, } -impl IntermediaryState { +impl IntermediaryState { pub fn reset(&mut self) { self.intermediary_mesh.clear(); self.path_event_buffer.clear(); @@ -150,10 +145,7 @@ impl IntermediaryState { } } -impl State -where - S: BaseFloat, -{ +impl State { // Resets all state within the `Draw` instance. fn reset(&mut self) { self.background_color = None; @@ -180,17 +172,14 @@ where } // Insert the draw primitive command at the given index. - fn insert_draw_command(&mut self, index: usize, prim: Primitive) { + fn insert_draw_command(&mut self, index: usize, prim: Primitive) { if let Some(elem) = self.draw_commands.get_mut(index) { *elem = Some(DrawCommand::Primitive(prim)); } } } -impl Draw -where - S: BaseFloat, -{ +impl Draw { /// Create a new **Draw** instance. /// /// This is the same as calling **Draw::default**. @@ -209,148 +198,139 @@ where /// /// The resulting **Draw** instance will be have a transform equal to the new transform applied /// to the existing transform. - pub fn transform(&self, transform_matrix: Matrix4) -> Self { + pub fn transform(&self, transform_matrix: Mat4) -> Self { let mut context = self.context.clone(); context.transform = context.transform * transform_matrix; self.context(context) } /// Translate the position of the origin by the given translation vector. - pub fn translate(&self, v: geom::Vector3) -> Self { - self.transform(Matrix4::from_translation(v.into())) + pub fn translate(&self, v: Vec3) -> Self { + self.transform(Mat4::from_translation(v)) } /// Translate the position of the origin by the given translation vector. /// /// This method is short for `translate`. - pub fn xyz(&self, v: geom::Vector3) -> Self { + pub fn xyz(&self, v: Vec3) -> Self { self.translate(v) } /// Translate the position of the origin by the given translation vector. - pub fn xy(&self, v: geom::Vector2) -> Self { - self.xyz(v.into()) + pub fn xy(&self, v: Vec2) -> Self { + self.xyz(v.extend(0.0)) } /// Translate the position of the origin by the given amount across each axis. - pub fn x_y_z(&self, x: S, y: S, z: S) -> Self { + pub fn x_y_z(&self, x: f32, y: f32, z: f32) -> Self { self.xyz([x, y, z].into()) } /// Translate the position of the origin by the given amount across each axis. - pub fn x_y(&self, x: S, y: S) -> Self { + pub fn x_y(&self, x: f32, y: f32) -> Self { self.xy([x, y].into()) } /// Translate the position of the origin along the x axis. - pub fn x(&self, x: S) -> Self { - self.x_y(x, S::zero()) + pub fn x(&self, x: f32) -> Self { + self.x_y(x, 0.0) } /// Translate the position of the origin along the y axis. - pub fn y(&self, y: S) -> Self { - self.x_y(S::zero(), y) + pub fn y(&self, y: f32) -> Self { + self.x_y(0.0, y) } /// Translate the position of the origin along the z axis. - pub fn z(&self, z: S) -> Self { - self.x_y_z(S::zero(), S::zero(), z) + pub fn z(&self, z: f32) -> Self { + self.x_y_z(0.0, 0.0, z) } /// Produce a new **Draw** instance where the contents are scaled uniformly by the given value. - pub fn scale(&self, s: S) -> Self { - self.scale_axes(geom::vec3(s, s, s)) + pub fn scale(&self, s: f32) -> Self { + self.scale_axes(vec3(s, s, s)) } /// Produce a new **Draw** instance where the contents are scaled by the given amount across /// each axis. - pub fn scale_axes(&self, v: geom::Vector3) -> Self { - self.transform(Matrix4::from_nonuniform_scale(v.x, v.y, v.z)) + pub fn scale_axes(&self, v: Vec3) -> Self { + self.transform(Mat4::from_scale(v)) } /// Produce a new **Draw** instance where the contents are scaled by the given amount along the /// x axis - pub fn scale_x(&self, s: S) -> Self { - self.scale_axes(geom::vec3(s, S::one(), S::one())) + pub fn scale_x(&self, s: f32) -> Self { + self.scale_axes(vec3(s, 1.0, 1.0)) } /// Produce a new **Draw** instance where the contents are scaled by the given amount along the /// y axis - pub fn scale_y(&self, s: S) -> Self { - self.scale_axes(geom::vec3(S::one(), s, S::one())) + pub fn scale_y(&self, s: f32) -> Self { + self.scale_axes(vec3(1.0, s, 1.0)) } /// Produce a new **Draw** instance where the contents are scaled by the given amount along the /// z axis - pub fn scale_z(&self, s: S) -> Self { - self.scale_axes(geom::vec3(S::one(), S::one(), s)) + pub fn scale_z(&self, s: f32) -> Self { + self.scale_axes(vec3(1.0, 1.0, s)) } /// The given vector is interpreted as a Euler angle in radians and a transform is applied /// accordingly. - pub fn euler(&self, euler: cgmath::Euler>) -> Self { - self.transform(euler.into()) + pub fn euler(&self, euler: Vec3) -> Self { + self.transform(Mat4::from_euler(EulerRot::XYZ, euler.x, euler.y, euler.z)) } /// Specify the orientation with the given **Quaternion**. - pub fn quaternion(&self, q: cgmath::Quaternion) -> Self { - self.transform(q.into()) + pub fn quaternion(&self, q: Quat) -> Self { + self.transform(Mat4::from_quat(q)) } /// Specify the orientation along each axis with the given **Vector** of radians. /// /// This currently has the same affect as calling `euler`. - pub fn radians(&self, v: geom::Vector3) -> Self { - let euler = cgmath::Euler { - x: cgmath::Rad(v.x), - y: cgmath::Rad(v.y), - z: cgmath::Rad(v.z), - }; - self.euler(euler) + pub fn radians(&self, v: Vec3) -> Self { + self.euler(v) } /// Specify the orientation around the *x* axis in radians. - pub fn x_radians(&self, x: S) -> Self { - self.radians(geom::vec3(x, S::zero(), S::zero())) + pub fn x_radians(&self, x: f32) -> Self { + self.radians(vec3(x, 0.0, 0.0)) } /// Specify the orientation around the *y* axis in radians. - pub fn y_radians(&self, y: S) -> Self { - self.radians(geom::vec3(S::zero(), y, S::zero())) + pub fn y_radians(&self, y: f32) -> Self { + self.radians(vec3(0.0, y, 0.0)) } /// Specify the orientation around the *z* axis in radians. - pub fn z_radians(&self, z: S) -> Self { - self.radians(geom::vec3(S::zero(), S::zero(), z)) + pub fn z_radians(&self, z: f32) -> Self { + self.radians(vec3(0.0, 0.0, z)) } /// Specify the orientation along each axis with the given **Vector** of degrees. - pub fn degrees(&self, v: geom::Vector3) -> Self { - self.radians(geom::vec3( - deg_to_rad(v.x), - deg_to_rad(v.y), - deg_to_rad(v.z), - )) + pub fn degrees(&self, v: Vec3) -> Self { + self.radians(vec3(deg_to_rad(v.x), deg_to_rad(v.y), deg_to_rad(v.z))) } /// Specify the orientation around the *x* axis in degrees. - pub fn x_degrees(&self, x: S) -> Self { + pub fn x_degrees(&self, x: f32) -> Self { self.x_radians(deg_to_rad(x)) } /// Specify the orientation around the *y* axis in degrees. - pub fn y_degrees(&self, y: S) -> Self { + pub fn y_degrees(&self, y: f32) -> Self { self.y_radians(deg_to_rad(y)) } /// Specify the orientation around the *z* axis in degrees. - pub fn z_degrees(&self, z: S) -> Self { + pub fn z_degrees(&self, z: f32) -> Self { self.z_radians(deg_to_rad(z)) } /// Specify the orientation along each axis with the given **Vector** of degrees. - pub fn turns(&self, v: geom::Vector3) -> Self { - self.radians(geom::vec3( + pub fn turns(&self, v: Vec3) -> Self { + self.radians(vec3( turns_to_rad(v.x), turns_to_rad(v.y), turns_to_rad(v.z), @@ -358,38 +338,38 @@ where } /// Specify the orientation around the *x* axis as a number of turns around the axis. - pub fn x_turns(&self, x: S) -> Self { + pub fn x_turns(&self, x: f32) -> Self { self.x_radians(turns_to_rad(x)) } /// Specify the orientation around the *y* axis as a number of turns around the axis. - pub fn y_turns(&self, y: S) -> Self { + pub fn y_turns(&self, y: f32) -> Self { self.y_radians(turns_to_rad(y)) } /// Specify the orientation around the *z* axis as a number of turns around the axis. - pub fn z_turns(&self, z: S) -> Self { + pub fn z_turns(&self, z: f32) -> Self { self.z_radians(turns_to_rad(z)) } /// Specify the "pitch" of the orientation in radians. /// /// This has the same effect as calling `x_radians`. - pub fn pitch(&self, pitch: S) -> Self { + pub fn pitch(&self, pitch: f32) -> Self { self.x_radians(pitch) } /// Specify the "yaw" of the orientation in radians. /// /// This has the same effect as calling `y_radians`. - pub fn yaw(&self, yaw: S) -> Self { + pub fn yaw(&self, yaw: f32) -> Self { self.y_radians(yaw) } /// Specify the "roll" of the orientation in radians. /// /// This has the same effect as calling `z_radians`. - pub fn roll(&self, roll: S) -> Self { + pub fn roll(&self, roll: f32) -> Self { self.z_radians(roll) } @@ -397,7 +377,7 @@ where /// given value is specified in radians. /// /// This is equivalent to calling the `z_radians` or `roll` methods. - pub fn rotate(&self, radians: S) -> Self { + pub fn rotate(&self, radians: f32) -> Self { self.z_radians(radians) } @@ -424,7 +404,7 @@ where /// /// If the current **Draw** instance already contains a scissor, the result will be the overlap /// between the original scissor and the new one. - pub fn scissor(&self, scissor: geom::Rect) -> Self { + pub fn scissor(&self, scissor: geom::Rect) -> Self { let mut context = self.context.clone(); context.scissor = match context.scissor { Scissor::Full => Scissor::Rect(scissor), @@ -491,7 +471,7 @@ where } /// Produce a new **Draw** instance with the given context. - fn context(&self, context: Context) -> Self { + fn context(&self, context: Context) -> Self { let state = self.state.clone(); Draw { state, context } } @@ -499,15 +479,15 @@ where // Primitives. /// Specify a color with which the background should be cleared. - pub fn background(&self) -> Background { + pub fn background(&self) -> Background { background::new(self) } /// Add the given type to be drawn. - pub fn a(&self, primitive: T) -> Drawing + pub fn a(&self, primitive: T) -> Drawing where - T: Into>, - Primitive: Into>, + T: Into, + Primitive: Into>, { let index = { let mut state = self.state.borrow_mut(); @@ -520,7 +500,7 @@ where } // The primitive will be inserted in the next element. let index = state.draw_commands.len(); - let primitive: Primitive = primitive.into(); + let primitive: Primitive = primitive.into(); state.draw_commands.push(None); state.drawing.insert(index, primitive); index @@ -529,59 +509,59 @@ where } /// Begin drawing a **Path**. - pub fn path(&self) -> Drawing, S> { + pub fn path(&self) -> Drawing { self.a(Default::default()) } /// Begin drawing an **Ellipse**. - pub fn ellipse(&self) -> Drawing, S> { + pub fn ellipse(&self) -> Drawing { self.a(Default::default()) } /// Begin drawing a **Line**. - pub fn line(&self) -> Drawing, S> { + pub fn line(&self) -> Drawing { self.a(Default::default()) } /// Begin drawing an **Arrow**. - pub fn arrow(&self) -> Drawing, S> { + pub fn arrow(&self) -> Drawing { self.a(Default::default()) } /// Begin drawing a **Quad**. - pub fn quad(&self) -> Drawing, S> { + pub fn quad(&self) -> Drawing { self.a(Default::default()) } /// Begin drawing a **Rect**. - pub fn rect(&self) -> Drawing, S> { + pub fn rect(&self) -> Drawing { self.a(Default::default()) } /// Begin drawing a **Triangle**. - pub fn tri(&self) -> Drawing, S> { + pub fn tri(&self) -> Drawing { self.a(Default::default()) } /// Begin drawing a **Polygon**. - pub fn polygon(&self) -> Drawing, S> { + pub fn polygon(&self) -> Drawing { self.a(Default::default()) } /// Begin drawing a **Mesh**. - pub fn mesh(&self) -> Drawing { + pub fn mesh(&self) -> Drawing { self.a(Default::default()) } /// Begin drawing a **Polyline**. /// /// Note that this is simply short-hand for `draw.path().stroke()` - pub fn polyline(&self) -> Drawing, S> { + pub fn polyline(&self) -> Drawing { self.path().stroke() } /// Begin drawing a **Text**. - pub fn text(&self, s: &str) -> Drawing, S> { + pub fn text(&self, s: &str) -> Drawing { let text = { let state = self.state.borrow(); let mut intermediary_state = state.intermediary_state.borrow_mut(); @@ -592,13 +572,13 @@ where } /// Begin drawing a **Texture**. - pub fn texture(&self, view: &dyn wgpu::ToTextureView) -> Drawing, S> { + pub fn texture(&self, view: &dyn wgpu::ToTextureView) -> Drawing { self.a(primitive::Texture::new(view)) } /// Finish any drawings-in-progress and produce an iterator draining the inner draw commands /// and yielding them by value. - pub fn drain_commands(&self) -> impl Iterator> { + pub fn drain_commands(&self) -> impl Iterator { self.finish_remaining_drawings(); let cmds = { let mut state = self.state.borrow_mut(); @@ -614,7 +594,7 @@ where } } -impl Default for IntermediaryState { +impl Default for IntermediaryState { fn default() -> Self { let intermediary_mesh = Default::default(); let path_event_buffer = Default::default(); @@ -631,10 +611,7 @@ impl Default for IntermediaryState { } } -impl Default for State -where - S: BaseFloat, -{ +impl Default for State { fn default() -> Self { let last_draw_context = None; let background_color = Default::default(); @@ -653,24 +630,18 @@ where } } -impl Default for Draw -where - S: BaseFloat, -{ +impl Default for Draw { fn default() -> Self { - let state: Rc>> = Rc::new(RefCell::new(Default::default())); + let state: Rc> = Rc::new(RefCell::new(Default::default())); let context = Default::default(); Draw { state, context } } } -impl Default for Context -where - S: BaseFloat, -{ +impl Default for Context { fn default() -> Self { Self { - transform: Matrix4::identity(), + transform: Mat4::IDENTITY, blend: wgpu::BlendState { color: wgpu::RenderPipelineBuilder::DEFAULT_COLOR_BLEND, alpha: wgpu::RenderPipelineBuilder::DEFAULT_ALPHA_BLEND, diff --git a/nannou/src/draw/primitive/arrow.rs b/nannou/src/draw/primitive/arrow.rs index a943c2de3..1296c6409 100644 --- a/nannou/src/draw/primitive/arrow.rs +++ b/nannou/src/draw/primitive/arrow.rs @@ -5,24 +5,24 @@ use crate::draw::primitive::Primitive; use crate::draw::properties::spatial::{orientation, position}; use crate::draw::properties::{ColorScalar, SetColor, SetOrientation, SetPosition, SetStroke}; use crate::draw::{self, Drawing}; -use crate::geom::{self, pt2, vec2, Point2}; -use crate::math::{BaseFloat, Zero}; +use crate::geom::{pt2, Point2}; +use crate::glam::vec2; use lyon::tessellation::StrokeOptions; /// A path containing only two points - a start and end. /// /// A triangle is drawn on the end to indicate direction. #[derive(Clone, Debug)] -pub struct Arrow { - line: Line, - head_length: Option, - head_width: Option, +pub struct Arrow { + line: Line, + head_length: Option, + head_width: Option, } /// The drawing context for a line. -pub type DrawingArrow<'a, S = geom::scalar::Default> = Drawing<'a, Arrow, S>; +pub type DrawingArrow<'a> = Drawing<'a, Arrow>; -impl Arrow { +impl Arrow { /// Short-hand for the `stroke_weight` method. pub fn weight(self, weight: f32) -> Self { self.map_line(|l| l.weight(weight)) @@ -34,17 +34,17 @@ impl Arrow { } /// Specify the start point of the arrow. - pub fn start(self, start: Point2) -> Self { + pub fn start(self, start: Point2) -> Self { self.map_line(|l| l.start(start)) } /// Specify the end point of the arrow. - pub fn end(self, end: Point2) -> Self { + pub fn end(self, end: Point2) -> Self { self.map_line(|l| l.end(end)) } /// Specify the start and end points of the arrow. - pub fn points(self, start: Point2, end: Point2) -> Self { + pub fn points(self, start: Point2, end: Point2) -> Self { self.map_line(|l| l.points(start, end)) } @@ -53,7 +53,7 @@ impl Arrow { /// By default, this is equal to `weight * 4.0`. /// /// This value will be clamped to the length of the line itself. - pub fn head_length(mut self, length: S) -> Self { + pub fn head_length(mut self, length: f32) -> Self { self.head_length = Some(length); self } @@ -61,7 +61,7 @@ impl Arrow { /// The width of the arrow head. /// /// By default, this is equal to `weight * 2.0`. - pub fn head_width(mut self, width: S) -> Self { + pub fn head_width(mut self, width: f32) -> Self { self.head_width = Some(width); self } @@ -69,7 +69,7 @@ impl Arrow { // Map the inner `PathStroke` using the given function. fn map_line(self, map: F) -> Self where - F: FnOnce(Line) -> Line, + F: FnOnce(Line) -> Line, { let Arrow { line, @@ -85,10 +85,7 @@ impl Arrow { } } -impl<'a, S> DrawingArrow<'a, S> -where - S: BaseFloat, -{ +impl<'a> DrawingArrow<'a> { /// Short-hand for the `stroke_weight` method. pub fn weight(self, weight: f32) -> Self { self.map_ty(|ty| ty.weight(weight)) @@ -100,17 +97,17 @@ where } /// Specify the start point of the arrow. - pub fn start(self, start: Point2) -> Self { + pub fn start(self, start: Point2) -> Self { self.map_ty(|ty| ty.start(start)) } /// Specify the end point of the arrow. - pub fn end(self, end: Point2) -> Self { + pub fn end(self, end: Point2) -> Self { self.map_ty(|ty| ty.end(end)) } /// Specify the start and end points of the arrow. - pub fn points(self, start: Point2, end: Point2) -> Self { + pub fn points(self, start: Point2, end: Point2) -> Self { self.map_ty(|ty| ty.points(start, end)) } @@ -119,50 +116,50 @@ where /// By default, this is equal to `weight * 4.0`. /// /// This value will be clamped to the length of the line itself. - pub fn head_length(self, length: S) -> Self { + pub fn head_length(self, length: f32) -> Self { self.map_ty(|ty| ty.head_length(length)) } /// The width of the arrow head. /// /// By default, this is equal to `weight * 2.0`. - pub fn head_width(self, width: S) -> Self { + pub fn head_width(self, width: f32) -> Self { self.map_ty(|ty| ty.head_width(width)) } } -impl SetStroke for Arrow { +impl SetStroke for Arrow { fn stroke_options_mut(&mut self) -> &mut StrokeOptions { SetStroke::stroke_options_mut(&mut self.line) } } -impl SetOrientation for Arrow { - fn properties(&mut self) -> &mut orientation::Properties { +impl SetOrientation for Arrow { + fn properties(&mut self) -> &mut orientation::Properties { SetOrientation::properties(&mut self.line) } } -impl SetPosition for Arrow { - fn properties(&mut self) -> &mut position::Properties { +impl SetPosition for Arrow { + fn properties(&mut self) -> &mut position::Properties { SetPosition::properties(&mut self.line) } } -impl SetColor for Arrow { +impl SetColor for Arrow { fn rgba_mut(&mut self) -> &mut Option { SetColor::rgba_mut(&mut self.line) } } -impl From> for Primitive { - fn from(prim: Arrow) -> Self { +impl From for Primitive { + fn from(prim: Arrow) -> Self { Primitive::Arrow(prim) } } -impl Into>> for Primitive { - fn into(self) -> Option> { +impl Into> for Primitive { + fn into(self) -> Option { match self { Primitive::Arrow(prim) => Some(prim), _ => None, @@ -170,7 +167,7 @@ impl Into>> for Primitive { } } -impl draw::renderer::RenderPrimitive for Arrow { +impl draw::renderer::RenderPrimitive for Arrow { fn render_primitive( self, mut ctxt: draw::renderer::RenderContext, @@ -193,28 +190,28 @@ impl draw::renderer::RenderPrimitive for Arrow { let head_width = head_width.unwrap_or(line_w_2); let head_length = head_length.unwrap_or(line_w_4); let line_dir = end - start; - let line_dir_mag = line_dir.magnitude(); - let tri_len = head_length.min(line_dir_mag); - let tri_dir_norm = line_dir.with_magnitude(tri_len); + let line_dir_len = line_dir.length(); + let tri_len = head_length.min(line_dir_len); + let tri_dir_norm = line_dir.normalize() * tri_len; let tri_start = end - tri_dir_norm; let tri_end = end; let line_start = start; let line_end = tri_start; let tri_a = tri_end; - let tri_w_dir = vec2(-tri_dir_norm.y, tri_dir_norm.x).with_magnitude(head_width); + let tri_w_dir = vec2(-tri_dir_norm.y, tri_dir_norm.x).normalize() * head_width; let tri_b = tri_start + tri_w_dir; let tri_c = tri_start - tri_w_dir; // The line should only be drawn if there is space after drawing the triangle. - let draw_line = line_dir_mag > tri_len; + let draw_line = line_dir_len > tri_len; // Determine the transform to apply to all points. - let global_transform = ctxt.transform; + let global_transform = *ctxt.transform; let local_transform = line.path.position.transform() * line.path.orientation.transform(); let transform = global_transform * local_transform; // Draw the tri. let tri_points = [tri_a, tri_b, tri_c]; - let tri_points = tri_points.iter().cloned().map(Into::into); + let tri_points = tri_points.iter().cloned().map(|p| p.to_array().into()); let close_tri = true; let tri_events = lyon::path::iterator::FromPolyline::new(close_tri, tri_points); path::render_path_events( @@ -232,7 +229,7 @@ impl draw::renderer::RenderPrimitive for Arrow { // Draw the line. if draw_line { let line_points = [line_start, line_end]; - let line_points = line_points.iter().cloned().map(Into::into); + let line_points = line_points.iter().cloned().map(|p| p.to_array().into()); let close_line = false; let line_events = lyon::path::iterator::FromPolyline::new(close_line, line_points); path::render_path_events( @@ -252,10 +249,7 @@ impl draw::renderer::RenderPrimitive for Arrow { } } -impl Default for Arrow -where - S: Zero, -{ +impl Default for Arrow { fn default() -> Self { let line = Default::default(); let head_length = Default::default(); diff --git a/nannou/src/draw/primitive/ellipse.rs b/nannou/src/draw/primitive/ellipse.rs index 7a9ef998e..28a91fb43 100644 --- a/nannou/src/draw/primitive/ellipse.rs +++ b/nannou/src/draw/primitive/ellipse.rs @@ -7,27 +7,24 @@ use crate::draw::properties::{ spatial, ColorScalar, LinSrgba, SetColor, SetDimensions, SetOrientation, SetPosition, SetStroke, }; use crate::draw::Drawing; -use crate::geom::{self, Vector2}; -use crate::math::{BaseFloat, Zero}; +use crate::geom; +use crate::glam::Vec2; use lyon::tessellation::StrokeOptions; /// Properties related to drawing an **Ellipse**. -#[derive(Clone, Debug)] -pub struct Ellipse { - dimensions: spatial::dimension::Properties, - resolution: Option, - polygon: PolygonInit, +#[derive(Clone, Debug, Default)] +pub struct Ellipse { + dimensions: spatial::dimension::Properties, + resolution: Option, + polygon: PolygonInit, } /// The drawing context for an ellipse. -pub type DrawingEllipse<'a, S = geom::scalar::Default> = Drawing<'a, Ellipse, S>; +pub type DrawingEllipse<'a> = Drawing<'a, Ellipse>; // Ellipse-specific methods. -impl Ellipse -where - S: BaseFloat, -{ +impl Ellipse { /// Stroke the outline with the given color. pub fn stroke(self, color: C) -> Self where @@ -37,8 +34,8 @@ where } /// Specify the width and height of the **Ellipse** via a given **radius**. - pub fn radius(self, radius: S) -> Self { - let side = radius * (S::one() + S::one()); + pub fn radius(self, radius: f32) -> Self { + let side = radius * 2.0; self.w_h(side, side) } @@ -46,7 +43,7 @@ where /// /// By default, ellipse does not use a resolution, but rather uses a stroke tolerance to /// determine how many vertices to use during tessellation. - pub fn resolution(mut self, resolution: usize) -> Self { + pub fn resolution(mut self, resolution: f32) -> Self { self.resolution = Some(resolution); self } @@ -54,7 +51,7 @@ where // Trait implementations. -impl draw::renderer::RenderPrimitive for Ellipse { +impl draw::renderer::RenderPrimitive for Ellipse { fn render_primitive( self, ctxt: draw::renderer::RenderContext, @@ -98,9 +95,9 @@ impl draw::renderer::RenderPrimitive for Ellipse { } } Some(resolution) => { - let rect = geom::Rect::from_wh(Vector2 { x: w, y: h }); + let rect = geom::Rect::from_w_h(w, h); let ellipse = geom::Ellipse::new(rect, resolution); - let points = ellipse.circumference(); + let points = ellipse.circumference().map(Vec2::from); polygon::render_points_themed( polygon.opts, points, @@ -115,68 +112,52 @@ impl draw::renderer::RenderPrimitive for Ellipse { } } -impl Default for Ellipse -where - S: Zero, -{ - fn default() -> Self { - let dimensions = Default::default(); - let polygon = Default::default(); - let resolution = Default::default(); - Ellipse { - dimensions, - polygon, - resolution, - } - } -} - -impl SetOrientation for Ellipse { - fn properties(&mut self) -> &mut orientation::Properties { +impl SetOrientation for Ellipse { + fn properties(&mut self) -> &mut orientation::Properties { SetOrientation::properties(&mut self.polygon) } } -impl SetPosition for Ellipse { - fn properties(&mut self) -> &mut position::Properties { +impl SetPosition for Ellipse { + fn properties(&mut self) -> &mut position::Properties { SetPosition::properties(&mut self.polygon) } } -impl SetDimensions for Ellipse { - fn properties(&mut self) -> &mut dimension::Properties { +impl SetDimensions for Ellipse { + fn properties(&mut self) -> &mut dimension::Properties { SetDimensions::properties(&mut self.dimensions) } } -impl SetColor for Ellipse { +impl SetColor for Ellipse { fn rgba_mut(&mut self) -> &mut Option { SetColor::rgba_mut(&mut self.polygon) } } -impl SetStroke for Ellipse { +impl SetStroke for Ellipse { fn stroke_options_mut(&mut self) -> &mut StrokeOptions { SetStroke::stroke_options_mut(&mut self.polygon) } } -impl SetPolygon for Ellipse { - fn polygon_options_mut(&mut self) -> &mut PolygonOptions { +impl SetPolygon for Ellipse { + fn polygon_options_mut(&mut self) -> &mut PolygonOptions { SetPolygon::polygon_options_mut(&mut self.polygon) } } // Primitive conversion. -impl From> for Primitive { - fn from(prim: Ellipse) -> Self { +impl From for Primitive { + fn from(prim: Ellipse) -> Self { Primitive::Ellipse(prim) } } -impl Into>> for Primitive { - fn into(self) -> Option> { +impl Into> for Primitive { + fn into(self) -> Option { match self { Primitive::Ellipse(prim) => Some(prim), _ => None, @@ -186,10 +167,7 @@ impl Into>> for Primitive { // Drawing methods. -impl<'a, S> DrawingEllipse<'a, S> -where - S: BaseFloat, -{ +impl<'a> DrawingEllipse<'a> { /// Stroke the outline with the given color. pub fn stroke(self, color: C) -> Self where @@ -199,12 +177,12 @@ where } /// Specify the width and height of the **Ellipse** via a given **radius**. - pub fn radius(self, radius: S) -> Self { + pub fn radius(self, radius: f32) -> Self { self.map_ty(|ty| ty.radius(radius)) } /// The number of sides used to draw the ellipse. - pub fn resolution(self, resolution: usize) -> Self { + pub fn resolution(self, resolution: f32) -> Self { self.map_ty(|ty| ty.resolution(resolution)) } } diff --git a/nannou/src/draw/primitive/line.rs b/nannou/src/draw/primitive/line.rs index c7c72a18f..b263c29e8 100644 --- a/nannou/src/draw/primitive/line.rs +++ b/nannou/src/draw/primitive/line.rs @@ -4,25 +4,24 @@ use crate::draw::primitive::{PathStroke, Primitive}; use crate::draw::properties::spatial::{orientation, position}; use crate::draw::properties::{ColorScalar, SetColor, SetOrientation, SetPosition, SetStroke}; use crate::draw::{self, Drawing}; -use crate::geom::{self, pt2, Point2}; -use crate::math::{BaseFloat, Zero}; +use crate::geom::{pt2, Point2}; use lyon::tessellation::StrokeOptions; /// A path containing only two points - a start and end. /// /// The usage of this type is almost identical to `PathStroke` but provides `start`, `end` and /// `points(a, b)` methods. -#[derive(Clone, Debug)] -pub struct Line { - pub path: PathStroke, - pub start: Option>, - pub end: Option>, +#[derive(Clone, Debug, Default)] +pub struct Line { + pub path: PathStroke, + pub start: Option, + pub end: Option, } /// The drawing context for a line. -pub type DrawingLine<'a, S = geom::scalar::Default> = Drawing<'a, Line, S>; +pub type DrawingLine<'a> = Drawing<'a, Line>; -impl Line { +impl Line { /// Short-hand for the `stroke_weight` method. pub fn weight(self, weight: f32) -> Self { self.map_path(|p| p.stroke_weight(weight)) @@ -34,26 +33,26 @@ impl Line { } /// Specify the start point of the line. - pub fn start(mut self, start: Point2) -> Self { + pub fn start(mut self, start: Point2) -> Self { self.start = Some(start); self } /// Specify the end point of the line. - pub fn end(mut self, end: Point2) -> Self { + pub fn end(mut self, end: Point2) -> Self { self.end = Some(end); self } /// Specify the start and end points of the line. - pub fn points(self, start: Point2, end: Point2) -> Self { + pub fn points(self, start: Point2, end: Point2) -> Self { self.start(start).end(end) } // Map the inner `PathStroke` using the given function. fn map_path(self, map: F) -> Self where - F: FnOnce(PathStroke) -> PathStroke, + F: FnOnce(PathStroke) -> PathStroke, { let Line { path, start, end } = self; let path = map(path); @@ -61,10 +60,7 @@ impl Line { } } -impl<'a, S> DrawingLine<'a, S> -where - S: BaseFloat, -{ +impl<'a> DrawingLine<'a> { /// Short-hand for the `stroke_weight` method. pub fn weight(self, weight: f32) -> Self { self.map_ty(|ty| ty.weight(weight)) @@ -76,53 +72,53 @@ where } /// Specify the start point of the line. - pub fn start(self, start: Point2) -> Self { + pub fn start(self, start: Point2) -> Self { self.map_ty(|ty| ty.start(start)) } /// Specify the end point of the line. - pub fn end(self, end: Point2) -> Self { + pub fn end(self, end: Point2) -> Self { self.map_ty(|ty| ty.end(end)) } /// Specify the start and end points of the line. - pub fn points(self, start: Point2, end: Point2) -> Self { + pub fn points(self, start: Point2, end: Point2) -> Self { self.map_ty(|ty| ty.points(start, end)) } } -impl SetStroke for Line { +impl SetStroke for Line { fn stroke_options_mut(&mut self) -> &mut StrokeOptions { SetStroke::stroke_options_mut(&mut self.path) } } -impl SetOrientation for Line { - fn properties(&mut self) -> &mut orientation::Properties { +impl SetOrientation for Line { + fn properties(&mut self) -> &mut orientation::Properties { SetOrientation::properties(&mut self.path) } } -impl SetPosition for Line { - fn properties(&mut self) -> &mut position::Properties { +impl SetPosition for Line { + fn properties(&mut self) -> &mut position::Properties { SetPosition::properties(&mut self.path) } } -impl SetColor for Line { +impl SetColor for Line { fn rgba_mut(&mut self) -> &mut Option { SetColor::rgba_mut(&mut self.path) } } -impl From> for Primitive { - fn from(prim: Line) -> Self { +impl From for Primitive { + fn from(prim: Line) -> Self { Primitive::Line(prim) } } -impl Into>> for Primitive { - fn into(self) -> Option> { +impl Into> for Primitive { + fn into(self) -> Option { match self { Primitive::Line(prim) => Some(prim), _ => None, @@ -130,7 +126,7 @@ impl Into>> for Primitive { } } -impl draw::renderer::RenderPrimitive for Line { +impl draw::renderer::RenderPrimitive for Line { fn render_primitive( self, mut ctxt: draw::renderer::RenderContext, @@ -144,11 +140,11 @@ impl draw::renderer::RenderPrimitive for Line { } let close = false; let points = [start, end]; - let points = points.iter().cloned().map(Into::into); + let points = points.iter().cloned().map(|p| p.to_array().into()); let events = lyon::path::iterator::FromPolyline::new(close, points); // Determine the transform to apply to all points. - let global_transform = ctxt.transform; + let global_transform = *ctxt.transform; let local_transform = path.position.transform() * path.orientation.transform(); let transform = global_transform * local_transform; @@ -167,16 +163,3 @@ impl draw::renderer::RenderPrimitive for Line { draw::renderer::PrimitiveRender::default() } } - -impl Default for Line -where - S: Zero, -{ - fn default() -> Self { - Line { - path: Default::default(), - start: Default::default(), - end: Default::default(), - } - } -} diff --git a/nannou/src/draw/primitive/mesh.rs b/nannou/src/draw/primitive/mesh.rs index 2987c390b..bbf2c03fe 100644 --- a/nannou/src/draw/primitive/mesh.rs +++ b/nannou/src/draw/primitive/mesh.rs @@ -5,7 +5,6 @@ use crate::draw::properties::spatial::{orientation, position}; use crate::draw::properties::{ColorScalar, LinSrgba, SetColor, SetOrientation, SetPosition}; use crate::draw::{self, Drawing}; use crate::geom; -use crate::math::BaseFloat; use crate::wgpu; use std::ops; @@ -15,9 +14,9 @@ pub struct Vertexless; /// Properties related to drawing an arbitrary mesh of colours, geometry and texture. #[derive(Clone, Debug)] -pub struct Mesh { - position: position::Properties, - orientation: orientation::Properties, +pub struct Mesh { + position: position::Properties, + orientation: orientation::Properties, vertex_range: ops::Range, index_range: ops::Range, vertex_mode: draw::renderer::VertexMode, @@ -36,7 +35,7 @@ struct FlattenIndices { current: [usize; 3], } -pub type DrawingMesh<'a, S> = Drawing<'a, Mesh, S>; +pub type DrawingMesh<'a> = Drawing<'a, Mesh>; impl Vertexless { /// Describe the mesh with a sequence of textured points. @@ -45,17 +44,16 @@ impl Vertexless { /// coordinates in that order, e.g. `(point, tex_coords)`. `point` may be of any type that /// implements `Into` and `tex_coords` may be of any type that implements /// `Into`. - pub fn points_textured( + pub fn points_textured( self, - inner_mesh: &mut draw::Mesh, + inner_mesh: &mut draw::Mesh, texture_view: &dyn wgpu::ToTextureView, points: I, - ) -> Mesh + ) -> Mesh where - S: BaseFloat, I: IntoIterator, - P: Into>, - T: Into>, + P: Into, + T: Into, { let points = points.into_iter().map(|(p, t)| { let point = p.into(); @@ -77,11 +75,10 @@ impl Vertexless { /// Each of the points must be represented as a tuple containing the point and the color in /// that order, e.g. `(point, color)`. `point` may be of any type that implements /// `Into` and `color` may be of any type that implements `IntoLinSrgba`. - pub fn points_colored(self, inner_mesh: &mut draw::Mesh, points: I) -> Mesh + pub fn points_colored(self, inner_mesh: &mut draw::Mesh, points: I) -> Mesh where - S: BaseFloat, I: IntoIterator, - P: Into>, + P: Into, C: IntoLinSrgba, { let vertices = points.into_iter().map(|(p, c)| { @@ -101,11 +98,10 @@ impl Vertexless { /// This method assumes that the entire mesh should be coloured with a single colour. If a /// colour is not specified via one of the builder methods, a default colour will be retrieved /// from the inner `Theme`. - pub fn points(self, inner_mesh: &mut draw::Mesh, points: I) -> Mesh + pub fn points(self, inner_mesh: &mut draw::Mesh, points: I) -> Mesh where - S: BaseFloat, I: IntoIterator, - I::Item: Into>, + I::Item: Into, { let vertices = points.into_iter().map(|p| { let point = p.into(); @@ -119,16 +115,15 @@ impl Vertexless { mesh } - fn points_inner( + fn points_inner( self, - inner_mesh: &mut draw::Mesh, + inner_mesh: &mut draw::Mesh, vertices: I, vertex_mode: draw::renderer::VertexMode, texture_view: Option, - ) -> Mesh + ) -> Mesh where - S: BaseFloat, - I: Iterator>, + I: Iterator, { let v_start = inner_mesh.points().len(); let i_start = inner_mesh.indices().len(); @@ -147,17 +142,16 @@ impl Vertexless { /// coordinates in that order, e.g. `(point, tex_coords)`. `point` may be of any type that /// implements `Into` and `tex_coords` may be of any type that implements /// `Into`. - pub fn tris_textured( + pub fn tris_textured( self, - inner_mesh: &mut draw::Mesh, + inner_mesh: &mut draw::Mesh, texture_view: &dyn wgpu::ToTextureView, tris: I, - ) -> Mesh + ) -> Mesh where - S: BaseFloat, I: IntoIterator>, - P: Into>, - T: Into>, + P: Into, + T: Into, { let points = tris .into_iter() @@ -171,11 +165,10 @@ impl Vertexless { /// Each of the vertices must be represented as a tuple containing the point and the color in /// that order, e.g. `(point, color)`. `point` may be of any type that implements `Into` /// and `color` may be of any type that implements `IntoLinSrgba`. - pub fn tris_colored(self, inner_mesh: &mut draw::Mesh, tris: I) -> Mesh + pub fn tris_colored(self, inner_mesh: &mut draw::Mesh, tris: I) -> Mesh where - S: BaseFloat, I: IntoIterator>, - P: Into>, + P: Into, C: IntoLinSrgba, { let points = tris @@ -193,11 +186,10 @@ impl Vertexless { /// This method assumes that the entire mesh should be coloured with a single colour. If a /// colour is not specified via one of the builder methods, a default colour will be retrieved /// from the inner `Theme`. - pub fn tris(self, inner_mesh: &mut draw::Mesh, tris: I) -> Mesh + pub fn tris(self, inner_mesh: &mut draw::Mesh, tris: I) -> Mesh where - S: BaseFloat, I: IntoIterator>, - V: Into>, + V: Into, { let points = tris .into_iter() @@ -214,19 +206,18 @@ impl Vertexless { /// coordinates in that order, e.g. `(point, tex_coords)`. `point` may be of any type that /// implements `Into` and `tex_coords` may be of any type that implements /// `Into`. - pub fn indexed_textured( + pub fn indexed_textured( self, - inner_mesh: &mut draw::Mesh, + inner_mesh: &mut draw::Mesh, texture_view: &dyn wgpu::ToTextureView, points: V, indices: I, - ) -> Mesh + ) -> Mesh where - S: BaseFloat, V: IntoIterator, I: IntoIterator, - P: Into>, - T: Into>, + P: Into, + T: Into, { let vertices = points.into_iter().map(|(p, t)| { let point = p.into(); @@ -251,17 +242,16 @@ impl Vertexless { /// Each of the `points` must be represented as a tuple containing the point and the color in /// that order, e.g. `(point, color)`. `point` may be of any type that implements /// `Into` and `color` may be of any type that implements `IntoLinSrgba`. - pub fn indexed_colored( + pub fn indexed_colored( self, - inner_mesh: &mut draw::Mesh, + inner_mesh: &mut draw::Mesh, points: V, indices: I, - ) -> Mesh + ) -> Mesh where - S: BaseFloat, V: IntoIterator, I: IntoIterator, - P: Into>, + P: Into, C: IntoLinSrgba, { let vertices = points.into_iter().map(|(p, c)| { @@ -279,11 +269,10 @@ impl Vertexless { /// Each trio of `indices` describes a single triangle made up of `points`. /// /// Each point may be any type that may be converted directly into the `Point3` type. - pub fn indexed(self, inner_mesh: &mut draw::Mesh, points: V, indices: I) -> Mesh + pub fn indexed(self, inner_mesh: &mut draw::Mesh, points: V, indices: I) -> Mesh where - S: BaseFloat, V: IntoIterator, - V::Item: Into>, + V::Item: Into, I: IntoIterator, { let vertices = points.into_iter().map(|p| { @@ -298,17 +287,16 @@ impl Vertexless { mesh } - fn indexed_inner( + fn indexed_inner( self, - inner_mesh: &mut draw::Mesh, + inner_mesh: &mut draw::Mesh, vertices: V, indices: I, vertex_mode: draw::renderer::VertexMode, texture_view: Option, - ) -> Mesh + ) -> Mesh where - S: BaseFloat, - V: IntoIterator>, + V: IntoIterator, I: IntoIterator, { let v_start = inner_mesh.points().len(); @@ -321,10 +309,7 @@ impl Vertexless { } } -impl Mesh -where - S: BaseFloat, -{ +impl Mesh { // Initialise a new `Mesh` with its ranges into the intermediary mesh, ready for drawing. fn new( vertex_range: ops::Range, @@ -347,10 +332,7 @@ where } } -impl<'a, S> Drawing<'a, Vertexless, S> -where - S: BaseFloat, -{ +impl<'a> Drawing<'a, Vertexless> { /// Describe the mesh with a sequence of points. /// /// The given iterator may yield any type that can be converted directly into `Point3`s. @@ -358,10 +340,10 @@ where /// This method assumes that the entire mesh should be coloured with a single colour. If a /// colour is not specified via one of the builder methods, a default colour will be retrieved /// from the inner `Theme`. - pub fn points(self, points: I) -> DrawingMesh<'a, S> + pub fn points(self, points: I) -> DrawingMesh<'a> where I: IntoIterator, - I::Item: Into>, + I::Item: Into, { self.map_ty_with_context(|ty, ctxt| ty.points(ctxt.mesh, points)) } @@ -371,10 +353,10 @@ where /// Each of the points must be represented as a tuple containing the point and the color in /// that order, e.g. `(point, color)`. `point` may be of any type that implements /// `Into` and `color` may be of any type that implements `IntoLinSrgba`. - pub fn points_colored(self, points: I) -> DrawingMesh<'a, S> + pub fn points_colored(self, points: I) -> DrawingMesh<'a> where I: IntoIterator, - P: Into>, + P: Into, C: IntoLinSrgba, { self.map_ty_with_context(|ty, ctxt| ty.points_colored(ctxt.mesh, points)) @@ -390,11 +372,11 @@ where self, view: &dyn wgpu::ToTextureView, points: I, - ) -> DrawingMesh<'a, S> + ) -> DrawingMesh<'a> where I: IntoIterator, - P: Into>, - T: Into>, + P: Into, + T: Into, { self.map_ty_with_context(|ty, ctxt| ty.points_textured(ctxt.mesh, view, points)) } @@ -407,10 +389,10 @@ where /// This method assumes that the entire mesh should be coloured with a single colour. If a /// colour is not specified via one of the builder methods, a default colour will be retrieved /// from the inner `Theme`. - pub fn tris(self, tris: I) -> DrawingMesh<'a, S> + pub fn tris(self, tris: I) -> DrawingMesh<'a> where I: IntoIterator>, - V: Into>, + V: Into, { self.map_ty_with_context(|ty, ctxt| ty.tris(ctxt.mesh, tris)) } @@ -420,10 +402,10 @@ where /// Each of the vertices must be represented as a tuple containing the point and the color in /// that order, e.g. `(point, color)`. `point` may be of any type that implements `Into` /// and `color` may be of any type that implements `IntoLinSrgba`. - pub fn tris_colored(self, tris: I) -> DrawingMesh<'a, S> + pub fn tris_colored(self, tris: I) -> DrawingMesh<'a> where I: IntoIterator>, - P: Into>, + P: Into, C: IntoLinSrgba, { self.map_ty_with_context(|ty, ctxt| ty.tris_colored(ctxt.mesh, tris)) @@ -435,15 +417,11 @@ where /// coordinates in that order, e.g. `(point, tex_coords)`. `point` may be of any type that /// implements `Into` and `tex_coords` may be of any type that implements /// `Into`. - pub fn tris_textured( - self, - view: &dyn wgpu::ToTextureView, - tris: I, - ) -> DrawingMesh<'a, S> + pub fn tris_textured(self, view: &dyn wgpu::ToTextureView, tris: I) -> DrawingMesh<'a> where I: IntoIterator>, - P: Into>, - T: Into>, + P: Into, + T: Into, { self.map_ty_with_context(|ty, ctxt| ty.tris_textured(ctxt.mesh, view, tris)) } @@ -453,10 +431,10 @@ where /// Each trio of `indices` describes a single triangle made up of `points`. /// /// Each point may be any type that may be converted directly into the `Point3` type. - pub fn indexed(self, points: V, indices: I) -> DrawingMesh<'a, S> + pub fn indexed(self, points: V, indices: I) -> DrawingMesh<'a> where V: IntoIterator, - V::Item: Into>, + V::Item: Into, I: IntoIterator, { self.map_ty_with_context(|ty, ctxt| ty.indexed(ctxt.mesh, points, indices)) @@ -469,11 +447,11 @@ where /// Each of the `points` must be represented as a tuple containing the point and the color in /// that order, e.g. `(point, color)`. `point` may be of any type that implements /// `Into` and `color` may be of any type that implements `IntoLinSrgba`. - pub fn indexed_colored(self, points: V, indices: I) -> DrawingMesh<'a, S> + pub fn indexed_colored(self, points: V, indices: I) -> DrawingMesh<'a> where V: IntoIterator, I: IntoIterator, - P: Into>, + P: Into, C: IntoLinSrgba, { self.map_ty_with_context(|ty, ctxt| ty.indexed_colored(ctxt.mesh, points, indices)) @@ -492,18 +470,18 @@ where view: &dyn wgpu::ToTextureView, points: V, indices: I, - ) -> DrawingMesh<'a, S> + ) -> DrawingMesh<'a> where V: IntoIterator, I: IntoIterator, - P: Into>, - T: Into>, + P: Into, + T: Into, { self.map_ty_with_context(|ty, ctxt| ty.indexed_textured(ctxt.mesh, view, points, indices)) } } -impl draw::renderer::RenderPrimitive for Mesh { +impl draw::renderer::RenderPrimitive for Mesh { fn render_primitive( self, ctxt: draw::renderer::RenderContext, @@ -520,7 +498,7 @@ impl draw::renderer::RenderPrimitive for Mesh { } = self; // Determine the transform to apply to vertices. - let global_transform = ctxt.transform; + let global_transform = *ctxt.transform; let local_transform = position.transform() * orientation.transform(); let transform = global_transform * local_transform; @@ -532,11 +510,7 @@ impl draw::renderer::RenderPrimitive for Mesh { .map(|i| new_mesh_vertex_start + i - old_mesh_vertex_start); // A small function for transforming a point via the transform matrix. - let transform_point = |p: geom::Point3| -> geom::Point3 { - let p = cgmath::Point3::new(p.x, p.y, p.z); - let p = cgmath::Transform::transform_point(&transform, p); - p.into() - }; + let transform_point = |p: geom::Point3| -> geom::Point3 { transform.transform_point3(p) }; // Color the vertices based on whether or not we should fill, then extend the mesh! match fill_color { @@ -593,37 +567,37 @@ where } } -impl SetOrientation for Mesh { - fn properties(&mut self) -> &mut orientation::Properties { +impl SetOrientation for Mesh { + fn properties(&mut self) -> &mut orientation::Properties { SetOrientation::properties(&mut self.orientation) } } -impl SetPosition for Mesh { - fn properties(&mut self) -> &mut position::Properties { +impl SetPosition for Mesh { + fn properties(&mut self) -> &mut position::Properties { SetPosition::properties(&mut self.position) } } -impl SetColor for Mesh { +impl SetColor for Mesh { fn rgba_mut(&mut self) -> &mut Option { &mut self.fill_color.get_or_insert_with(Default::default).0 } } -impl From for Primitive { +impl From for Primitive { fn from(prim: Vertexless) -> Self { Primitive::MeshVertexless(prim) } } -impl From> for Primitive { - fn from(prim: Mesh) -> Self { +impl From for Primitive { + fn from(prim: Mesh) -> Self { Primitive::Mesh(prim) } } -impl Into> for Primitive { +impl Into> for Primitive { fn into(self) -> Option { match self { Primitive::MeshVertexless(prim) => Some(prim), @@ -632,8 +606,8 @@ impl Into> for Primitive { } } -impl Into>> for Primitive { - fn into(self) -> Option> { +impl Into> for Primitive { + fn into(self) -> Option { match self { Primitive::Mesh(prim) => Some(prim), _ => None, diff --git a/nannou/src/draw/primitive/mod.rs b/nannou/src/draw/primitive/mod.rs index a73748535..60272a10f 100644 --- a/nannou/src/draw/primitive/mod.rs +++ b/nannou/src/draw/primitive/mod.rs @@ -10,8 +10,6 @@ pub mod text; pub mod texture; pub mod tri; -use crate::geom; - pub use self::arrow::Arrow; pub use self::ellipse::Ellipse; pub use self::line::Line; @@ -30,21 +28,21 @@ pub use self::tri::Tri; /// This also allows us to flush all pending drawings to the mesh if `Draw::to_frame` is called /// before their respective **Drawing** types are dropped. #[derive(Clone, Debug)] -pub enum Primitive { - Arrow(Arrow), - Ellipse(Ellipse), - Line(Line), +pub enum Primitive { + Arrow(Arrow), + Ellipse(Ellipse), + Line(Line), MeshVertexless(mesh::Vertexless), - Mesh(Mesh), - PathInit(PathInit), - PathFill(PathFill), - PathStroke(PathStroke), - Path(Path), - PolygonInit(PolygonInit), - Polygon(Polygon), - Quad(Quad), - Rect(Rect), - Text(Text), - Texture(Texture), - Tri(Tri), + Mesh(Mesh), + PathInit(PathInit), + PathFill(PathFill), + PathStroke(PathStroke), + Path(Path), + PolygonInit(PolygonInit), + Polygon(Polygon), + Quad(Quad), + Rect(Rect), + Text(Text), + Texture(Texture), + Tri(Tri), } diff --git a/nannou/src/draw/primitive/path.rs b/nannou/src/draw/primitive/path.rs index 38d9d8aba..8ee422876 100644 --- a/nannou/src/draw/primitive/path.rs +++ b/nannou/src/draw/primitive/path.rs @@ -7,8 +7,8 @@ use crate::draw::properties::{ ColorScalar, SetColor, SetFill, SetOrientation, SetPosition, SetStroke, }; use crate::draw::{self, Drawing, DrawingContext}; -use crate::geom::{self, Point2}; -use crate::math::{BaseFloat, Zero}; +use crate::geom::Point2; +use crate::glam::Mat4; use crate::wgpu; use lyon::path::PathEvent; use lyon::tessellation::{FillOptions, FillTessellator, StrokeOptions, StrokeTessellator}; @@ -51,16 +51,16 @@ pub(crate) enum PathEventSourceIter<'a> { /// The beginning of the path building process, prior to choosing the tessellation mode (fill or /// stroke). -#[derive(Clone, Debug)] -pub struct PathInit(std::marker::PhantomData); +#[derive(Clone, Debug, Default)] +pub struct PathInit; /// A path drawing context ready to specify tessellation options. -#[derive(Clone, Debug)] -pub struct PathOptions { +#[derive(Clone, Debug, Default)] +pub struct PathOptions { pub(crate) opts: T, pub(crate) color: Option, - pub(crate) position: position::Properties, - pub(crate) orientation: orientation::Properties, + pub(crate) position: position::Properties, + pub(crate) orientation: orientation::Properties, } /// Mutable access to stroke and fill tessellators. @@ -70,17 +70,17 @@ pub struct Tessellators<'a> { } /// A filled path drawing context. -pub type PathFill = PathOptions; +pub type PathFill = PathOptions; /// A stroked path drawing context. -pub type PathStroke = PathOptions; +pub type PathStroke = PathOptions; /// Properties related to drawing a **Path**. #[derive(Clone, Debug)] -pub struct Path { +pub struct Path { color: Option, - position: position::Properties, - orientation: orientation::Properties, + position: position::Properties, + orientation: orientation::Properties, path_event_src: PathEventSource, options: Options, vertex_mode: draw::renderer::VertexMode, @@ -88,19 +88,19 @@ pub struct Path { } /// The initial drawing context for a path. -pub type DrawingPathInit<'a, S = geom::scalar::Default> = Drawing<'a, PathInit, S>; +pub type DrawingPathInit<'a> = Drawing<'a, PathInit>; /// The drawing context for a path in the tessellation options state. -pub type DrawingPathOptions<'a, T, S = geom::scalar::Default> = Drawing<'a, PathOptions, S>; +pub type DrawingPathOptions<'a, T> = Drawing<'a, PathOptions>; /// The drawing context for a stroked path, prior to path event submission. -pub type DrawingPathStroke<'a, S = geom::scalar::Default> = Drawing<'a, PathStroke, S>; +pub type DrawingPathStroke<'a> = Drawing<'a, PathStroke>; /// The drawing context for a filled path, prior to path event submission. -pub type DrawingPathFill<'a, S = geom::scalar::Default> = Drawing<'a, PathFill, S>; +pub type DrawingPathFill<'a> = Drawing<'a, PathFill>; /// The drawing context for a polyline whose vertices have been specified. -pub type DrawingPath<'a, S = geom::scalar::Default> = Drawing<'a, Path, S>; +pub type DrawingPath<'a> = Drawing<'a, Path>; /// Dynamically distinguish between fill and stroke tessellation options. #[derive(Clone, Debug)] @@ -109,14 +109,11 @@ pub enum Options { Stroke(StrokeOptions), } -impl PathInit { +impl PathInit { /// Specify that we want to use fill tessellation for the path. /// /// The returned building context allows for specifying the fill tessellation options. - pub fn fill(self) -> PathFill - where - S: Zero, - { + pub fn fill(self) -> PathFill { let opts = FillOptions::default(); PathFill::new(opts) } @@ -124,19 +121,13 @@ impl PathInit { /// Specify that we want to use stroke tessellation for the path. /// /// The returned building context allows for specifying the stroke tessellation options. - pub fn stroke(self) -> PathStroke - where - S: Zero, - { + pub fn stroke(self) -> PathStroke { let opts = Default::default(); PathStroke::new(opts) } } -impl PathOptions -where - S: Zero, -{ +impl PathOptions { /// Initialise the `PathOptions` builder. pub fn new(opts: T) -> Self { let orientation = Default::default(); @@ -151,7 +142,7 @@ where } } -impl PathFill { +impl PathFill { /// Maximum allowed distance to the path when building an approximation. /// /// This method is shorthand for the `fill_tolerance` method. @@ -169,7 +160,7 @@ impl PathFill { } } -impl PathStroke { +impl PathStroke { /// Short-hand for the `stroke_weight` method. pub fn weight(self, weight: f32) -> Self { self.stroke_weight(weight) @@ -181,14 +172,13 @@ impl PathStroke { } } -impl PathOptions +impl PathOptions where T: TessellationOptions, { /// Submit the path events to be tessellated. - pub(crate) fn events(self, ctxt: DrawingContext, events: I) -> Path + pub(crate) fn events(self, ctxt: DrawingContext, events: I) -> Path where - S: BaseFloat, I: IntoIterator, { let DrawingContext { @@ -209,11 +199,10 @@ where } /// Consumes an iterator of points and converts them to an iterator yielding path events. - pub fn points(self, ctxt: DrawingContext, points: I) -> Path + pub fn points(self, ctxt: DrawingContext, points: I) -> Path where - S: BaseFloat, I: IntoIterator, - I::Item: Into>, + I::Item: Into, { self.points_inner(ctxt, false, points) } @@ -221,32 +210,29 @@ where /// Consumes an iterator of points and converts them to an iterator yielding path events. /// /// Closes the start and end points. - pub fn points_closed(self, ctxt: DrawingContext, points: I) -> Path + pub fn points_closed(self, ctxt: DrawingContext, points: I) -> Path where - S: BaseFloat, I: IntoIterator, - I::Item: Into>, + I::Item: Into, { self.points_inner(ctxt, true, points) } /// Submit path events as a polyline of colored points. - pub fn points_colored(self, ctxt: DrawingContext, points: I) -> Path + pub fn points_colored(self, ctxt: DrawingContext, points: I) -> Path where - S: BaseFloat, I: IntoIterator, - P: Into>, + P: Into, C: IntoLinSrgba, { self.points_colored_inner(ctxt, false, points) } /// Submit path events as a polyline of colored points. - pub fn points_colored_closed(self, ctxt: DrawingContext, points: I) -> Path + pub fn points_colored_closed(self, ctxt: DrawingContext, points: I) -> Path where - S: BaseFloat, I: IntoIterator, - P: Into>, + P: Into, C: IntoLinSrgba, { self.points_colored_inner(ctxt, true, points) @@ -255,15 +241,14 @@ where /// Submit path events as a polyline of textured points. pub fn points_textured( self, - ctxt: DrawingContext, + ctxt: DrawingContext, texture_view: &dyn wgpu::ToTextureView, points: I, - ) -> Path + ) -> Path where - S: BaseFloat, I: IntoIterator, - P: Into>, - TC: Into>, + P: Into, + TC: Into, { self.points_textured_inner(ctxt, texture_view.to_texture_view(), false, points) } @@ -271,45 +256,37 @@ where /// Submit path events as a polyline of textured points. pub fn points_textured_closed( self, - ctxt: DrawingContext, + ctxt: DrawingContext, texture_view: &dyn wgpu::ToTextureView, points: I, - ) -> Path + ) -> Path where - S: BaseFloat, I: IntoIterator, - P: Into>, - TC: Into>, + P: Into, + TC: Into, { self.points_textured_inner(ctxt, texture_view.to_texture_view(), true, points) } // Consumes an iterator of points and converts them to an iterator yielding events. - fn points_inner(self, ctxt: DrawingContext, close: bool, points: I) -> Path + fn points_inner(self, ctxt: DrawingContext, close: bool, points: I) -> Path where - S: BaseFloat, I: IntoIterator, - I::Item: Into>, + I::Item: Into, { - let iter = points.into_iter().map(Into::into).map(|p| { - let p: geom::Point2 = p.cast().expect("failed to cast point"); - lyon::math::point(p.x, p.y) - }); + let iter = points + .into_iter() + .map(Into::into) + .map(|p| lyon::math::point(p.x, p.y)); let events = lyon::path::iterator::FromPolyline::new(close, iter); self.events(ctxt, events) } // Consumes an iterator of points and converts them to an iterator yielding events. - fn points_colored_inner( - self, - ctxt: DrawingContext, - close: bool, - points: I, - ) -> Path + fn points_colored_inner(self, ctxt: DrawingContext, close: bool, points: I) -> Path where - S: BaseFloat, I: IntoIterator, - P: Into>, + P: Into, C: IntoLinSrgba, { let DrawingContext { @@ -340,16 +317,15 @@ where // Consumes an iterator of textured points and buffers them for rendering. fn points_textured_inner( self, - ctxt: DrawingContext, + ctxt: DrawingContext, texture_view: wgpu::TextureView, close: bool, points: I, - ) -> Path + ) -> Path where - S: BaseFloat, I: IntoIterator, - P: Into>, - TC: Into>, + P: Into, + TC: Into, { let DrawingContext { path_points_textured_buffer, @@ -378,7 +354,7 @@ where pub(crate) fn render_path_events( events: I, color: Option, - transform: cgmath::Matrix4, + transform: Mat4, options: Options, theme: &draw::Theme, theme_prim: &draw::theme::Primitive, @@ -408,7 +384,7 @@ pub(crate) fn render_path_events( pub(crate) fn render_path_points_colored( points_colored: I, close: bool, - transform: cgmath::Matrix4, + transform: Mat4, options: Options, fill_tessellator: &mut lyon::tessellation::FillTessellator, stroke_tessellator: &mut lyon::tessellation::StrokeTessellator, @@ -447,7 +423,7 @@ pub(crate) fn render_path_points_colored( pub(crate) fn render_path_points_textured( points_textured: I, close: bool, - transform: cgmath::Matrix4, + transform: Mat4, options: Options, fill_tessellator: &mut lyon::tessellation::FillTessellator, stroke_tessellator: &mut lyon::tessellation::StrokeTessellator, @@ -487,7 +463,7 @@ pub(crate) fn render_path_source( // TODO: path_src: PathEventSourceIter, color: Option, - transform: cgmath::Matrix4, + transform: Mat4, options: Options, theme: &draw::Theme, theme_prim: &draw::theme::Primitive, @@ -528,7 +504,7 @@ pub(crate) fn render_path_source( } } -impl draw::renderer::RenderPrimitive for Path { +impl draw::renderer::RenderPrimitive for Path { fn render_primitive( self, mut ctxt: draw::renderer::RenderContext, @@ -545,7 +521,7 @@ impl draw::renderer::RenderPrimitive for Path { } = self; // Determine the transform to apply to all points. - let global_transform = ctxt.transform; + let global_transform = *ctxt.transform; let local_transform = position.transform() * orientation.transform(); let transform = global_transform * local_transform; @@ -626,13 +602,13 @@ where // Begin the path. let mut iter = points_colored.into_iter(); let (first_point, first_color) = iter.next()?; - let p = first_point.into(); + let p = first_point.to_array().into(); let (r, g, b, a) = first_color.into(); path_builder.move_to(p, &[r, g, b, a]); // Add the lines, keeping track of the last for (point, color) in iter { - let p = point.into(); + let p = point.to_array().into(); let (r, g, b, a) = color.into(); path_builder.line_to(p, &[r, g, b, a]); } @@ -658,13 +634,13 @@ where // Begin the path. let mut iter = points_textured.into_iter(); let (first_point, first_tex_coords) = iter.next()?; - let p = first_point.into(); + let p = first_point.to_array().into(); let (tc_x, tc_y) = first_tex_coords.into(); path_builder.move_to(p, &[tc_x, tc_y]); // Add the lines, keeping track of the last for (point, tex_coords) in iter { - let p = point.into(); + let p = point.to_array().into(); let (tc_x, tc_y) = tex_coords.into(); path_builder.line_to(p, &[tc_x, tc_y]); } @@ -678,14 +654,11 @@ where Some(path_builder.build()) } -impl Path -where - S: BaseFloat, -{ +impl Path { // Initialise a new `Path` with its ranges into the intermediary mesh, ready for drawing. fn new( - position: position::Properties, - orientation: orientation::Properties, + position: position::Properties, + orientation: orientation::Properties, color: Option, path_event_src: PathEventSource, options: Options, @@ -704,29 +677,23 @@ where } } -impl<'a, S> DrawingPathInit<'a, S> -where - S: BaseFloat, -{ +impl<'a> DrawingPathInit<'a> { /// Specify that we want to use fill tessellation for the path. /// /// The returned building context allows for specifying the fill tessellation options. - pub fn fill(self) -> DrawingPathFill<'a, S> { + pub fn fill(self) -> DrawingPathFill<'a> { self.map_ty(|ty| ty.fill()) } /// Specify that we want to use stroke tessellation for the path. /// /// The returned building context allows for specifying the stroke tessellation options. - pub fn stroke(self) -> DrawingPathStroke<'a, S> { + pub fn stroke(self) -> DrawingPathStroke<'a> { self.map_ty(|ty| ty.stroke()) } } -impl<'a, S> DrawingPathFill<'a, S> -where - S: BaseFloat, -{ +impl<'a> DrawingPathFill<'a> { /// Maximum allowed distance to the path when building an approximation. pub fn tolerance(self, tolerance: f32) -> Self { self.map_ty(|ty| ty.tolerance(tolerance)) @@ -740,10 +707,7 @@ where } } -impl<'a, S> DrawingPathStroke<'a, S> -where - S: BaseFloat, -{ +impl<'a> DrawingPathStroke<'a> { /// Short-hand for the `stroke_weight` method. pub fn weight(self, weight: f32) -> Self { self.map_ty(|ty| ty.stroke_weight(weight)) @@ -755,15 +719,14 @@ where } } -impl<'a, T, S> DrawingPathOptions<'a, T, S> +impl<'a, T> DrawingPathOptions<'a, T> where - S: BaseFloat, T: TessellationOptions, - PathOptions: Into>, - Primitive: Into>>, + PathOptions: Into, + Primitive: Into>>, { /// Submit the path events to be tessellated. - pub fn events(self, events: I) -> DrawingPath<'a, S> + pub fn events(self, events: I) -> DrawingPath<'a> where I: IntoIterator, { @@ -771,10 +734,10 @@ where } /// Submit the path events as a polyline of points. - pub fn points(self, points: I) -> DrawingPath<'a, S> + pub fn points(self, points: I) -> DrawingPath<'a> where I: IntoIterator, - I::Item: Into>, + I::Item: Into, { self.map_ty_with_context(|ty, ctxt| ty.points(ctxt, points)) } @@ -782,20 +745,19 @@ where /// Submit the path events as a polyline of points. /// /// An event will be generated that closes the start and end points. - pub fn points_closed(self, points: I) -> DrawingPath<'a, S> + pub fn points_closed(self, points: I) -> DrawingPath<'a> where I: IntoIterator, - I::Item: Into>, + I::Item: Into, { self.map_ty_with_context(|ty, ctxt| ty.points_closed(ctxt, points)) } /// Submit path events as a polyline of colored points. - pub fn points_colored(self, points: I) -> DrawingPath<'a, S> + pub fn points_colored(self, points: I) -> DrawingPath<'a> where - S: BaseFloat, I: IntoIterator, - P: Into>, + P: Into, C: IntoLinSrgba, { self.map_ty_with_context(|ty, ctxt| ty.points_colored(ctxt, points)) @@ -804,11 +766,10 @@ where /// Submit path events as a polyline of colored points. /// /// The path with automatically close from the end point to the start point. - pub fn points_colored_closed(self, points: I) -> DrawingPath<'a, S> + pub fn points_colored_closed(self, points: I) -> DrawingPath<'a> where - S: BaseFloat, I: IntoIterator, - P: Into>, + P: Into, C: IntoLinSrgba, { self.map_ty_with_context(|ty, ctxt| ty.points_colored_closed(ctxt, points)) @@ -819,12 +780,11 @@ where self, view: &dyn wgpu::ToTextureView, points: I, - ) -> DrawingPath<'a, S> + ) -> DrawingPath<'a> where - S: BaseFloat, I: IntoIterator, - P: Into>, - TC: Into>, + P: Into, + TC: Into, { self.map_ty_with_context(|ty, ctxt| ty.points_textured(ctxt, view, points)) } @@ -836,24 +796,23 @@ where self, view: &dyn wgpu::ToTextureView, points: I, - ) -> DrawingPath<'a, S> + ) -> DrawingPath<'a> where - S: BaseFloat, I: IntoIterator, - P: Into>, - TC: Into>, + P: Into, + TC: Into, { self.map_ty_with_context(|ty, ctxt| ty.points_textured_closed(ctxt, view, points)) } } -impl SetFill for PathFill { +impl SetFill for PathFill { fn fill_options_mut(&mut self) -> &mut FillOptions { &mut self.opts } } -impl SetStroke for PathStroke { +impl SetStroke for PathStroke { fn stroke_options_mut(&mut self) -> &mut StrokeOptions { &mut self.opts } @@ -873,85 +832,68 @@ impl TessellationOptions for StrokeOptions { } } -impl Default for PathInit { - fn default() -> Self { - PathInit(std::marker::PhantomData) - } -} - -impl Default for PathOptions -where - S: Zero, - T: Default, -{ - fn default() -> Self { - let opts = Default::default(); - PathOptions::new(opts) - } -} - -impl SetOrientation for PathOptions { - fn properties(&mut self) -> &mut orientation::Properties { +impl SetOrientation for PathOptions { + fn properties(&mut self) -> &mut orientation::Properties { SetOrientation::properties(&mut self.orientation) } } -impl SetPosition for PathOptions { - fn properties(&mut self) -> &mut position::Properties { +impl SetPosition for PathOptions { + fn properties(&mut self) -> &mut position::Properties { SetPosition::properties(&mut self.position) } } -impl SetColor for PathOptions { +impl SetColor for PathOptions { fn rgba_mut(&mut self) -> &mut Option { SetColor::rgba_mut(&mut self.color) } } -impl SetOrientation for Path { - fn properties(&mut self) -> &mut orientation::Properties { +impl SetOrientation for Path { + fn properties(&mut self) -> &mut orientation::Properties { SetOrientation::properties(&mut self.orientation) } } -impl SetPosition for Path { - fn properties(&mut self) -> &mut position::Properties { +impl SetPosition for Path { + fn properties(&mut self) -> &mut position::Properties { SetPosition::properties(&mut self.position) } } -impl SetColor for Path { +impl SetColor for Path { fn rgba_mut(&mut self) -> &mut Option { SetColor::rgba_mut(&mut self.color) } } -impl From> for Primitive { - fn from(prim: PathInit) -> Self { +impl From for Primitive { + fn from(prim: PathInit) -> Self { Primitive::PathInit(prim) } } -impl From> for Primitive { - fn from(prim: PathStroke) -> Self { +impl From for Primitive { + fn from(prim: PathStroke) -> Self { Primitive::PathStroke(prim) } } -impl From> for Primitive { - fn from(prim: PathFill) -> Self { +impl From for Primitive { + fn from(prim: PathFill) -> Self { Primitive::PathFill(prim) } } -impl From> for Primitive { - fn from(prim: Path) -> Self { +impl From for Primitive { + fn from(prim: Path) -> Self { Primitive::Path(prim) } } -impl Into>> for Primitive { - fn into(self) -> Option> { +impl Into> for Primitive { + fn into(self) -> Option { match self { Primitive::PathInit(prim) => Some(prim), _ => None, @@ -959,8 +901,8 @@ impl Into>> for Primitive { } } -impl Into>> for Primitive { - fn into(self) -> Option> { +impl Into> for Primitive { + fn into(self) -> Option { match self { Primitive::PathFill(prim) => Some(prim), _ => None, @@ -968,8 +910,8 @@ impl Into>> for Primitive { } } -impl Into>> for Primitive { - fn into(self) -> Option> { +impl Into> for Primitive { + fn into(self) -> Option { match self { Primitive::PathStroke(prim) => Some(prim), _ => None, @@ -977,8 +919,8 @@ impl Into>> for Primitive { } } -impl Into>> for Primitive { - fn into(self) -> Option> { +impl Into> for Primitive { + fn into(self) -> Option { match self { Primitive::Path(prim) => Some(prim), _ => None, diff --git a/nannou/src/draw/primitive/polygon.rs b/nannou/src/draw/primitive/polygon.rs index ac2a018f2..754cf71e9 100644 --- a/nannou/src/draw/primitive/polygon.rs +++ b/nannou/src/draw/primitive/polygon.rs @@ -8,16 +8,15 @@ use crate::draw::properties::{ ColorScalar, LinSrgba, SetColor, SetOrientation, SetPosition, SetStroke, }; use crate::draw::{self, Drawing}; -use crate::geom::{self, Point2}; -use crate::math::{BaseFloat, Zero}; +use crate::geom::Point2; use crate::wgpu; use lyon::path::PathEvent; use lyon::tessellation::StrokeOptions; /// A trait implemented for all polygon draw primitives. -pub trait SetPolygon: Sized { +pub trait SetPolygon: Sized { /// Access to the polygon builder parameters. - fn polygon_options_mut(&mut self) -> &mut PolygonOptions; + fn polygon_options_mut(&mut self) -> &mut PolygonOptions; /// Specify no fill color and in turn no fill tessellation for the polygon. fn no_fill(mut self) -> Self { @@ -38,23 +37,23 @@ pub trait SetPolygon: Sized { } /// Specify the whole set of polygon options. - fn polygon_options(mut self, opts: PolygonOptions) -> Self { + fn polygon_options(mut self, opts: PolygonOptions) -> Self { *self.polygon_options_mut() = opts; self } } /// State related to drawing a **Polygon**. -#[derive(Clone, Debug)] -pub struct PolygonInit { - pub(crate) opts: PolygonOptions, +#[derive(Clone, Debug, Default)] +pub struct PolygonInit { + pub(crate) opts: PolygonOptions, } /// The set of options shared by all polygon types. -#[derive(Clone, Debug)] -pub struct PolygonOptions { - pub position: position::Properties, - pub orientation: orientation::Properties, +#[derive(Clone, Debug, Default)] +pub struct PolygonOptions { + pub position: position::Properties, + pub orientation: orientation::Properties, pub no_fill: bool, pub stroke_color: Option, pub color: Option, @@ -63,19 +62,19 @@ pub struct PolygonOptions { /// A polygon with vertices already submitted. #[derive(Clone, Debug)] -pub struct Polygon { - opts: PolygonOptions, +pub struct Polygon { + opts: PolygonOptions, path_event_src: PathEventSource, texture_view: Option, } /// Initialised drawing state for a polygon. -pub type DrawingPolygonInit<'a, S = geom::scalar::Default> = Drawing<'a, PolygonInit, S>; +pub type DrawingPolygonInit<'a> = Drawing<'a, PolygonInit>; /// Initialised drawing state for a polygon. -pub type DrawingPolygon<'a, S = geom::scalar::Default> = Drawing<'a, Polygon, S>; +pub type DrawingPolygon<'a> = Drawing<'a, Polygon>; -impl PolygonInit { +impl PolygonInit { /// Stroke the outline with the given color. pub fn stroke(self, color: C) -> Self where @@ -85,9 +84,8 @@ impl PolygonInit { } /// Submit the path events to be tessellated. - pub(crate) fn events(self, ctxt: DrawingContext, events: I) -> Polygon + pub(crate) fn events(self, ctxt: DrawingContext, events: I) -> Polygon where - S: BaseFloat, I: IntoIterator, { let DrawingContext { @@ -104,15 +102,14 @@ impl PolygonInit { } /// Consumes an iterator of points and converts them to an iterator yielding path events. - pub fn points(self, ctxt: DrawingContext, points: I) -> Polygon + pub fn points(self, ctxt: DrawingContext, points: I) -> Polygon where - S: BaseFloat, I: IntoIterator, - I::Item: Into>, + I::Item: Into, { let points = points.into_iter().map(|p| { - let p: Point2 = p.into().cast().expect("failed to cast point"); - p.into() + let p: Point2 = p.into(); + p.to_array().into() }); let close = true; let events = lyon::path::iterator::FromPolyline::new(close, points); @@ -120,11 +117,10 @@ impl PolygonInit { } /// Consumes an iterator of points and converts them to an iterator yielding path events. - pub fn points_colored(self, ctxt: DrawingContext, points: I) -> Polygon + pub fn points_colored(self, ctxt: DrawingContext, points: I) -> Polygon where - S: BaseFloat, I: IntoIterator, - P: Into>, + P: Into, C: IntoLinSrgba, { let DrawingContext { @@ -150,15 +146,14 @@ impl PolygonInit { /// Consumes an iterator of points and converts them to an iterator yielding path events. pub fn points_textured( self, - ctxt: DrawingContext, + ctxt: DrawingContext, view: &dyn wgpu::ToTextureView, points: I, - ) -> Polygon + ) -> Polygon where - S: BaseFloat, I: IntoIterator, - P: Into>, - T: Into>, + P: Into, + T: Into, { let DrawingContext { path_points_textured_buffer, @@ -199,7 +194,7 @@ pub fn render_events_themed( } = opts; // Determine the transform to apply to all points. - let global_transform = ctxt.transform; + let global_transform = *ctxt.transform; let local_transform = position.transform() * orientation.transform(); let transform = global_transform * local_transform; @@ -260,14 +255,14 @@ pub fn render_points_themed( { render_events_themed( opts, - || lyon::path::iterator::FromPolyline::closed(points.clone().map(|p| p.into())), + || lyon::path::iterator::FromPolyline::closed(points.clone().map(|p| p.to_array().into())), ctxt, theme_primitive, mesh, ); } -impl Polygon { +impl Polygon { pub(crate) fn render_themed( self, ctxt: draw::renderer::RenderContext, @@ -299,7 +294,7 @@ impl Polygon { } = ctxt; // Determine the transform to apply to all points. - let global_transform = transform; + let global_transform = *transform; let local_transform = position.transform() * orientation.transform(); let transform = global_transform * local_transform; @@ -439,7 +434,7 @@ impl Polygon { } } -impl draw::renderer::RenderPrimitive for Polygon { +impl draw::renderer::RenderPrimitive for Polygon { fn render_primitive( self, ctxt: draw::renderer::RenderContext, @@ -449,11 +444,10 @@ impl draw::renderer::RenderPrimitive for Polygon { } } -impl<'a, S, T> Drawing<'a, T, S> +impl<'a, T> Drawing<'a, T> where - S: BaseFloat, - T: SetPolygon + Into>, - Primitive: Into>, + T: SetPolygon + Into, + Primitive: Into>, { /// Specify no fill color and in turn no fill tessellation for the polygon. pub fn no_fill(self) -> Self { @@ -472,15 +466,12 @@ where } /// Specify the whole set of polygon options. - pub fn polygon_options(self, opts: PolygonOptions) -> Self { + pub fn polygon_options(self, opts: PolygonOptions) -> Self { self.map_ty(|ty| ty.polygon_options(opts)) } } -impl<'a, S> DrawingPolygonInit<'a, S> -where - S: BaseFloat, -{ +impl<'a> DrawingPolygonInit<'a> { /// Stroke the outline with the given color. pub fn stroke(self, color: C) -> Self where @@ -490,30 +481,27 @@ where } /// Describe the polygon with a sequence of path events. - pub fn events(self, events: I) -> DrawingPolygon<'a, S> + pub fn events(self, events: I) -> DrawingPolygon<'a> where - S: BaseFloat, I: IntoIterator, { self.map_ty_with_context(|ty, ctxt| ty.events(ctxt, events)) } /// Describe the polygon with a sequence of points. - pub fn points(self, points: I) -> DrawingPolygon<'a, S> + pub fn points(self, points: I) -> DrawingPolygon<'a> where - S: BaseFloat, I: IntoIterator, - I::Item: Into>, + I::Item: Into, { self.map_ty_with_context(|ty, ctxt| ty.points(ctxt, points)) } /// Consumes an iterator of points and converts them to an iterator yielding path events. - pub fn points_colored(self, points: I) -> DrawingPolygon<'a, S> + pub fn points_colored(self, points: I) -> DrawingPolygon<'a> where - S: BaseFloat, I: IntoIterator, - P: Into>, + P: Into, C: IntoLinSrgba, { self.map_ty_with_context(|ty, ctxt| ty.points_colored(ctxt, points)) @@ -524,117 +512,84 @@ where self, view: &dyn wgpu::ToTextureView, points: I, - ) -> DrawingPolygon<'a, S> + ) -> DrawingPolygon<'a> where - S: BaseFloat, I: IntoIterator, - P: Into>, - T: Into>, + P: Into, + T: Into, { self.map_ty_with_context(|ty, ctxt| ty.points_textured(ctxt, view, points)) } } -impl Default for PolygonInit -where - S: Zero, -{ - fn default() -> Self { - let opts = Default::default(); - PolygonInit { opts } - } -} - -impl Default for PolygonOptions -where - S: Zero, -{ - fn default() -> Self { - let position = Default::default(); - let orientation = Default::default(); - let no_fill = false; - let color = None; - let stroke_color = None; - let stroke = None; - PolygonOptions { - position, - orientation, - no_fill, - color, - stroke_color, - stroke, - } - } -} - -impl SetPolygon for PolygonOptions { - fn polygon_options_mut(&mut self) -> &mut PolygonOptions { +impl SetPolygon for PolygonOptions { + fn polygon_options_mut(&mut self) -> &mut PolygonOptions { self } } -impl SetOrientation for PolygonInit { - fn properties(&mut self) -> &mut orientation::Properties { +impl SetOrientation for PolygonInit { + fn properties(&mut self) -> &mut orientation::Properties { SetOrientation::properties(&mut self.opts.orientation) } } -impl SetPosition for PolygonInit { - fn properties(&mut self) -> &mut position::Properties { +impl SetPosition for PolygonInit { + fn properties(&mut self) -> &mut position::Properties { SetPosition::properties(&mut self.opts.position) } } -impl SetColor for PolygonInit { +impl SetColor for PolygonInit { fn rgba_mut(&mut self) -> &mut Option { SetColor::rgba_mut(&mut self.opts.color) } } -impl SetPolygon for PolygonInit { - fn polygon_options_mut(&mut self) -> &mut PolygonOptions { +impl SetPolygon for PolygonInit { + fn polygon_options_mut(&mut self) -> &mut PolygonOptions { SetPolygon::polygon_options_mut(&mut self.opts) } } -impl SetStroke for PolygonInit { +impl SetStroke for PolygonInit { fn stroke_options_mut(&mut self) -> &mut StrokeOptions { SetStroke::stroke_options_mut(&mut self.opts.stroke) } } -impl SetOrientation for Polygon { - fn properties(&mut self) -> &mut orientation::Properties { +impl SetOrientation for Polygon { + fn properties(&mut self) -> &mut orientation::Properties { SetOrientation::properties(&mut self.opts.orientation) } } -impl SetPosition for Polygon { - fn properties(&mut self) -> &mut position::Properties { +impl SetPosition for Polygon { + fn properties(&mut self) -> &mut position::Properties { SetPosition::properties(&mut self.opts.position) } } -impl SetColor for Polygon { +impl SetColor for Polygon { fn rgba_mut(&mut self) -> &mut Option { SetColor::rgba_mut(&mut self.opts.color) } } -impl From> for Primitive { - fn from(prim: PolygonInit) -> Self { +impl From for Primitive { + fn from(prim: PolygonInit) -> Self { Primitive::PolygonInit(prim) } } -impl From> for Primitive { - fn from(prim: Polygon) -> Self { +impl From for Primitive { + fn from(prim: Polygon) -> Self { Primitive::Polygon(prim) } } -impl Into>> for Primitive { - fn into(self) -> Option> { +impl Into> for Primitive { + fn into(self) -> Option { match self { Primitive::PolygonInit(prim) => Some(prim), _ => None, @@ -642,8 +597,8 @@ impl Into>> for Primitive { } } -impl Into>> for Primitive { - fn into(self) -> Option> { +impl Into> for Primitive { + fn into(self) -> Option { match self { Primitive::Polygon(prim) => Some(prim), _ => None, diff --git a/nannou/src/draw/primitive/quad.rs b/nannou/src/draw/primitive/quad.rs index e7819798d..04c47a41b 100644 --- a/nannou/src/draw/primitive/quad.rs +++ b/nannou/src/draw/primitive/quad.rs @@ -6,24 +6,24 @@ use crate::draw::properties::{ spatial, ColorScalar, LinSrgba, SetColor, SetDimensions, SetOrientation, SetPosition, SetStroke, }; use crate::draw::{self, Drawing}; -use crate::geom::{self, Point2, Vector2}; -use crate::math::{BaseFloat, ElementWise}; +use crate::geom::{self, pt2, Point2}; +use crate::glam::vec2; use lyon::tessellation::StrokeOptions; /// Properties related to drawing a **Quad**. #[derive(Clone, Debug)] -pub struct Quad { - quad: geom::Quad>, - polygon: PolygonInit, - dimensions: spatial::dimension::Properties, +pub struct Quad { + quad: geom::Quad, + polygon: PolygonInit, + dimensions: spatial::dimension::Properties, } /// The drawing context for a `Quad`. -pub type DrawingQuad<'a, S = geom::scalar::Default> = Drawing<'a, Quad, S>; +pub type DrawingQuad<'a> = Drawing<'a, Quad>; // Quad-specific methods. -impl Quad { +impl Quad { /// Stroke the outline with the given color. pub fn stroke(self, color: C) -> Self where @@ -35,7 +35,7 @@ impl Quad { /// Use the given four points as the vertices (corners) of the quad. pub fn points

(mut self, a: P, b: P, c: P, d: P) -> Self where - P: Into>, + P: Into, { let a = a.into(); let b = b.into(); @@ -47,7 +47,7 @@ impl Quad { } // Trait implementations. -impl draw::renderer::RenderPrimitive for Quad { +impl draw::renderer::RenderPrimitive for Quad { fn render_primitive( self, ctxt: draw::renderer::RenderContext, @@ -66,12 +66,9 @@ impl draw::renderer::RenderPrimitive for Quad { let centroid = quad.centroid(); let x_scale = maybe_x.map(|x| x / cuboid.w()).unwrap_or(1.0); let y_scale = maybe_y.map(|y| y / cuboid.h()).unwrap_or(1.0); - let scale = Vector2 { - x: x_scale, - y: y_scale, - }; + let scale = vec2(x_scale, y_scale); let (a, b, c, d) = quad.into(); - let translate = |v: Point2| centroid + ((v - centroid).mul_element_wise(scale)); + let translate = |v: Point2| centroid + ((v - centroid) * scale); let new_a = translate(a); let new_b = translate(b); let new_c = translate(c); @@ -92,11 +89,8 @@ impl draw::renderer::RenderPrimitive for Quad { } } -impl From>> for Quad -where - S: BaseFloat, -{ - fn from(quad: geom::Quad>) -> Self { +impl From> for Quad { + fn from(quad: geom::Quad) -> Self { let polygon = Default::default(); let dimensions = Default::default(); Quad { @@ -107,74 +101,68 @@ where } } -impl Default for Quad -where - S: BaseFloat, -{ +impl Default for Quad { fn default() -> Self { // Create a quad pointing towards 0.0 radians. - let fifty = S::from(50.0).unwrap(); + let fifty = 50.0; let left = -fifty; let bottom = -fifty; let right = fifty; let top = fifty; - let a = Point2 { x: left, y: bottom }; - let b = Point2 { x: left, y: top }; - let c = Point2 { x: right, y: top }; - let d = Point2 { - x: right, - y: bottom, - }; + let a = pt2(left, bottom); + let b = pt2(left, top); + let c = pt2(right, top); + let d = pt2(right, bottom); Quad::from(geom::Quad([a, b, c, d])) } } -impl SetOrientation for Quad { - fn properties(&mut self) -> &mut orientation::Properties { +impl SetOrientation for Quad { + fn properties(&mut self) -> &mut orientation::Properties { SetOrientation::properties(&mut self.polygon) } } -impl SetPosition for Quad { - fn properties(&mut self) -> &mut position::Properties { +impl SetPosition for Quad { + fn properties(&mut self) -> &mut position::Properties { SetPosition::properties(&mut self.polygon) } } -impl SetDimensions for Quad { - fn properties(&mut self) -> &mut dimension::Properties { +impl SetDimensions for Quad { + fn properties(&mut self) -> &mut dimension::Properties { SetDimensions::properties(&mut self.dimensions) } } -impl SetColor for Quad { +impl SetColor for Quad { fn rgba_mut(&mut self) -> &mut Option { SetColor::rgba_mut(&mut self.polygon) } } -impl SetStroke for Quad { +impl SetStroke for Quad { fn stroke_options_mut(&mut self) -> &mut StrokeOptions { SetStroke::stroke_options_mut(&mut self.polygon) } } -impl SetPolygon for Quad { - fn polygon_options_mut(&mut self) -> &mut PolygonOptions { +impl SetPolygon for Quad { + fn polygon_options_mut(&mut self) -> &mut PolygonOptions { SetPolygon::polygon_options_mut(&mut self.polygon) } } // Primitive conversions. -impl From> for Primitive { - fn from(prim: Quad) -> Self { +impl From for Primitive { + fn from(prim: Quad) -> Self { Primitive::Quad(prim) } } -impl Into>> for Primitive { - fn into(self) -> Option> { +impl Into> for Primitive { + fn into(self) -> Option { match self { Primitive::Quad(prim) => Some(prim), _ => None, @@ -184,14 +172,11 @@ impl Into>> for Primitive { // Drawing methods. -impl<'a, S> DrawingQuad<'a, S> -where - S: BaseFloat, -{ +impl<'a> DrawingQuad<'a> { /// Use the given points as the vertices (corners) of the quad. pub fn points

(self, a: P, b: P, c: P, d: P) -> Self where - P: Into>, + P: Into, { self.map_ty(|ty| ty.points(a, b, c, d)) } diff --git a/nannou/src/draw/primitive/rect.rs b/nannou/src/draw/primitive/rect.rs index 030c40174..b52c8cf18 100644 --- a/nannou/src/draw/primitive/rect.rs +++ b/nannou/src/draw/primitive/rect.rs @@ -6,23 +6,23 @@ use crate::draw::properties::{ ColorScalar, LinSrgba, SetColor, SetDimensions, SetOrientation, SetPosition, SetStroke, }; use crate::draw::{self, Drawing}; -use crate::geom::{self, Vector2}; -use crate::math::BaseFloat; +use crate::geom; +use crate::glam::Vec2; use lyon::tessellation::StrokeOptions; /// Properties related to drawing a **Rect**. #[derive(Clone, Debug)] -pub struct Rect { - dimensions: dimension::Properties, - polygon: PolygonInit, +pub struct Rect { + dimensions: dimension::Properties, + polygon: PolygonInit, } /// The drawing context for a Rect. -pub type DrawingRect<'a, S = geom::scalar::Default> = Drawing<'a, Rect, S>; +pub type DrawingRect<'a> = Drawing<'a, Rect>; // Trait implementations. -impl Rect { +impl Rect { /// Stroke the outline with the given color. pub fn stroke(self, color: C) -> Self where @@ -32,10 +32,7 @@ impl Rect { } } -impl<'a, S> DrawingRect<'a, S> -where - S: BaseFloat, -{ +impl<'a> DrawingRect<'a> { /// Stroke the outline with the given color. pub fn stroke(self, color: C) -> Self where @@ -45,7 +42,7 @@ where } } -impl draw::renderer::RenderPrimitive for Rect { +impl draw::renderer::RenderPrimitive for Rect { fn render_primitive( self, ctxt: draw::renderer::RenderContext, @@ -64,8 +61,8 @@ impl draw::renderer::RenderPrimitive for Rect { ); let w = maybe_x.unwrap_or(100.0); let h = maybe_y.unwrap_or(100.0); - let rect = geom::Rect::from_wh(Vector2 { x: w, y: h }); - let points = rect.corners().vertices(); + let rect = geom::Rect::from_wh([w, h].into()); + let points = rect.corners().vertices().map(Vec2::from); polygon::render_points_themed( polygon.opts, points, @@ -78,20 +75,14 @@ impl draw::renderer::RenderPrimitive for Rect { } } -impl From> for Rect -where - S: BaseFloat, -{ - fn from(r: geom::Rect) -> Self { +impl From> for Rect { + fn from(r: geom::Rect) -> Self { let (x, y, w, h) = r.x_y_w_h(); Self::default().x_y(x, y).w_h(w, h) } } -impl Default for Rect -where - S: BaseFloat, -{ +impl Default for Rect { fn default() -> Self { let dimensions = <_>::default(); let polygon = <_>::default(); @@ -102,52 +93,52 @@ where } } -impl SetOrientation for Rect { - fn properties(&mut self) -> &mut orientation::Properties { +impl SetOrientation for Rect { + fn properties(&mut self) -> &mut orientation::Properties { SetOrientation::properties(&mut self.polygon) } } -impl SetPosition for Rect { - fn properties(&mut self) -> &mut position::Properties { +impl SetPosition for Rect { + fn properties(&mut self) -> &mut position::Properties { SetPosition::properties(&mut self.polygon) } } -impl SetDimensions for Rect { - fn properties(&mut self) -> &mut dimension::Properties { +impl SetDimensions for Rect { + fn properties(&mut self) -> &mut dimension::Properties { SetDimensions::properties(&mut self.dimensions) } } -impl SetColor for Rect { +impl SetColor for Rect { fn rgba_mut(&mut self) -> &mut Option { SetColor::rgba_mut(&mut self.polygon) } } -impl SetStroke for Rect { +impl SetStroke for Rect { fn stroke_options_mut(&mut self) -> &mut StrokeOptions { SetStroke::stroke_options_mut(&mut self.polygon) } } -impl SetPolygon for Rect { - fn polygon_options_mut(&mut self) -> &mut PolygonOptions { +impl SetPolygon for Rect { + fn polygon_options_mut(&mut self) -> &mut PolygonOptions { SetPolygon::polygon_options_mut(&mut self.polygon) } } // Primitive conversions. -impl From> for Primitive { - fn from(prim: Rect) -> Self { +impl From for Primitive { + fn from(prim: Rect) -> Self { Primitive::Rect(prim) } } -impl Into>> for Primitive { - fn into(self) -> Option> { +impl Into> for Primitive { + fn into(self) -> Option { match self { Primitive::Rect(prim) => Some(prim), _ => None, diff --git a/nannou/src/draw/primitive/text.rs b/nannou/src/draw/primitive/text.rs index 80653809c..f031bcc57 100644 --- a/nannou/src/draw/primitive/text.rs +++ b/nannou/src/draw/primitive/text.rs @@ -6,14 +6,13 @@ use crate::draw::properties::{ ColorScalar, LinSrgba, SetColor, SetDimensions, SetOrientation, SetPosition, }; use crate::draw::{self, theme, Drawing}; -use crate::geom::{self, Vector2}; -use crate::math::{BaseFloat, Zero}; +use crate::geom::{self, Point2}; use crate::text::{self, Align, Font, FontSize, Justify, Layout, Scalar, Wrap}; /// Properties related to drawing the **Text** primitive. #[derive(Clone, Debug)] -pub struct Text { - spatial: spatial::Properties, +pub struct Text { + spatial: spatial::Properties, style: Style, // The byte range into the `Draw` context's text buffer. text: std::ops::Range, @@ -28,14 +27,11 @@ pub struct Style { } /// The drawing context for the **Text** primitive. -pub type DrawingText<'a, S = geom::scalar::Default> = Drawing<'a, Text, S>; +pub type DrawingText<'a> = Drawing<'a, Text>; -impl Text { +impl Text { /// Begin drawing some text. - pub fn new(ctxt: DrawingContext, text: &str) -> Self - where - S: Zero, - { + pub fn new(ctxt: DrawingContext, text: &str) -> Self { let start = ctxt.text_buffer.len(); ctxt.text_buffer.push_str(text); let end = ctxt.text_buffer.len(); @@ -162,10 +158,7 @@ impl Text { } } -impl<'a, S> DrawingText<'a, S> -where - S: BaseFloat, -{ +impl<'a> DrawingText<'a> { /// The font size to use for the text. pub fn font_size(self, size: text::FontSize) -> Self { self.map_ty(|ty| ty.font_size(size)) @@ -266,7 +259,7 @@ where } } -impl draw::renderer::RenderPrimitive for Text { +impl draw::renderer::RenderPrimitive for Text { fn render_primitive( self, ctxt: draw::renderer::RenderContext, @@ -292,13 +285,9 @@ impl draw::renderer::RenderPrimitive for Text { maybe_z.is_none(), "z dimension support for text is unimplemented" ); - let w = maybe_x - .map(|s| ::from(s).unwrap()) - .unwrap_or(200.0); - let h = maybe_y - .map(|s| ::from(s).unwrap()) - .unwrap_or(200.0); - let rect: geom::Rect = geom::Rect::from_wh(Vector2 { x: w, y: h }); + let w = maybe_x.unwrap_or(200.0); + let h = maybe_y.unwrap_or(200.0); + let rect: geom::Rect = geom::Rect::from_wh([w, h].into()); let color = color.unwrap_or_else(|| ctxt.theme.fill_lin_srgba(&theme::Primitive::Text)); let text_str = &ctxt.text_buffer[text.clone()]; @@ -352,7 +341,7 @@ impl draw::renderer::RenderPrimitive for Text { } // Determine the transform to apply to all points. - let global_transform = ctxt.transform; + let global_transform = *ctxt.transform; let local_transform = spatial.position.transform() * spatial.orientation.transform(); let transform = global_transform * local_transform; @@ -365,7 +354,7 @@ impl draw::renderer::RenderPrimitive for Text { let r = screen_rect.max.x as f32 / scale_factor - half_out_w; let t = -(screen_rect.min.y as f32 / scale_factor - half_out_h); let b = -(screen_rect.max.y as f32 / scale_factor - half_out_h); - geom::Rect::from_corners(geom::pt2(l, b), geom::pt2(r, t)) + geom::Rect::from_corners([l, b].into(), [r, t].into()) }; // Skips non-rendered colors (e.g. due to line breaks), @@ -386,9 +375,8 @@ impl draw::renderer::RenderPrimitive for Text { let rect = to_nannou_rect(screen_rect); // Create a mesh-compatible vertex from the position and tex_coords. - let v = |position, tex_coords: [f32; 2]| -> draw::mesh::Vertex { - let p = geom::Point3::from(position); - let p = cgmath::Transform::transform_point(&transform, p.into()); + let v = |p: Point2, tex_coords: [f32; 2]| -> draw::mesh::Vertex { + let p = transform.transform_point3([p.x, p.y, 0.0].into()); let point = draw::mesh::vertex::Point::from(p); draw::mesh::vertex::new(point, g_color.to_owned(), tex_coords.into()) }; @@ -428,25 +416,25 @@ impl draw::renderer::RenderPrimitive for Text { } } -impl SetOrientation for Text { - fn properties(&mut self) -> &mut orientation::Properties { +impl SetOrientation for Text { + fn properties(&mut self) -> &mut orientation::Properties { SetOrientation::properties(&mut self.spatial) } } -impl SetPosition for Text { - fn properties(&mut self) -> &mut position::Properties { +impl SetPosition for Text { + fn properties(&mut self) -> &mut position::Properties { SetPosition::properties(&mut self.spatial) } } -impl SetDimensions for Text { - fn properties(&mut self) -> &mut dimension::Properties { +impl SetDimensions for Text { + fn properties(&mut self) -> &mut dimension::Properties { SetDimensions::properties(&mut self.spatial) } } -impl SetColor for Text { +impl SetColor for Text { fn rgba_mut(&mut self) -> &mut Option { SetColor::rgba_mut(&mut self.style.color) } @@ -454,14 +442,14 @@ impl SetColor for Text { // Primitive conversions. -impl From> for Primitive { - fn from(prim: Text) -> Self { +impl From for Primitive { + fn from(prim: Text) -> Self { Primitive::Text(prim) } } -impl Into>> for Primitive { - fn into(self) -> Option> { +impl Into> for Primitive { + fn into(self) -> Option { match self { Primitive::Text(prim) => Some(prim), _ => None, diff --git a/nannou/src/draw/primitive/texture.rs b/nannou/src/draw/primitive/texture.rs index 0f78953bb..5b86714a9 100644 --- a/nannou/src/draw/primitive/texture.rs +++ b/nannou/src/draw/primitive/texture.rs @@ -3,32 +3,29 @@ use crate::draw::primitive::Primitive; use crate::draw::properties::spatial::{self, dimension, orientation, position}; use crate::draw::properties::{SetDimensions, SetOrientation, SetPosition}; use crate::draw::{self, Drawing}; -use crate::geom::{self, Vector2}; -use crate::math::BaseFloat; +use crate::geom; +use crate::glam::Vec2; use crate::wgpu; /// Properties related to drawing a **Rect**. #[derive(Clone, Debug)] -pub struct Texture { +pub struct Texture { texture_view: wgpu::TextureView, - spatial: spatial::Properties, + spatial: spatial::Properties, area: geom::Rect, } /// The drawing context for a Rect. -pub type DrawingTexture<'a, S = geom::scalar::Default> = Drawing<'a, Texture, S>; +pub type DrawingTexture<'a> = Drawing<'a, Texture>; // Trait implementations. -impl Texture -where - S: BaseFloat, -{ +impl Texture { pub(crate) fn new(view: &dyn wgpu::ToTextureView) -> Self { let texture_view = view.to_texture_view(); let [w, h] = texture_view.size(); - let w = S::from(w).unwrap(); - let h = S::from(h).unwrap(); + let w = w as f32; + let h = h as f32; let spatial = spatial::Properties::default().w_h(w, h); let x = geom::Range { start: 0.0, @@ -47,7 +44,7 @@ where } } -impl Texture { +impl Texture { /// Specify the area of the texture to draw. /// /// The bounds of the rectangle should represent the desired area as texture coordinates of the @@ -63,10 +60,7 @@ impl Texture { } } -impl<'a, S> DrawingTexture<'a, S> -where - S: BaseFloat, -{ +impl<'a> DrawingTexture<'a> { /// Specify the area of the texture to draw. /// /// The bounds of the rectangle should represent the desired area as texture coordinates of the @@ -81,7 +75,7 @@ where } } -impl draw::renderer::RenderPrimitive for Texture { +impl draw::renderer::RenderPrimitive for Texture { fn render_primitive( self, mut ctxt: draw::renderer::RenderContext, @@ -106,10 +100,10 @@ impl draw::renderer::RenderPrimitive for Texture { ); let w = maybe_x.unwrap_or(100.0); let h = maybe_y.unwrap_or(100.0); - let rect = geom::Rect::from_wh(Vector2 { x: w, y: h }); + let rect = geom::Rect::from_w_h(w, h); // Determine the transform to apply to all points. - let global_transform = ctxt.transform; + let global_transform = *ctxt.transform; let local_transform = position.transform() * orientation.transform(); let transform = global_transform * local_transform; @@ -117,7 +111,8 @@ impl draw::renderer::RenderPrimitive for Texture { let points_textured = rect .corners() .vertices() - .zip(area.invert_y().corners().vertices()); + .map(Vec2::from) + .zip(area.invert_y().corners().vertices().map(Vec2::from)); path::render_path_points_textured( points_textured, @@ -133,34 +128,34 @@ impl draw::renderer::RenderPrimitive for Texture { } } -impl SetOrientation for Texture { - fn properties(&mut self) -> &mut orientation::Properties { +impl SetOrientation for Texture { + fn properties(&mut self) -> &mut orientation::Properties { SetOrientation::properties(&mut self.spatial) } } -impl SetPosition for Texture { - fn properties(&mut self) -> &mut position::Properties { +impl SetPosition for Texture { + fn properties(&mut self) -> &mut position::Properties { SetPosition::properties(&mut self.spatial) } } -impl SetDimensions for Texture { - fn properties(&mut self) -> &mut dimension::Properties { +impl SetDimensions for Texture { + fn properties(&mut self) -> &mut dimension::Properties { SetDimensions::properties(&mut self.spatial) } } // Primitive conversions. -impl From> for Primitive { - fn from(prim: Texture) -> Self { +impl From for Primitive { + fn from(prim: Texture) -> Self { Primitive::Texture(prim) } } -impl Into>> for Primitive { - fn into(self) -> Option> { +impl Into> for Primitive { + fn into(self) -> Option { match self { Primitive::Texture(prim) => Some(prim), _ => None, diff --git a/nannou/src/draw/primitive/tri.rs b/nannou/src/draw/primitive/tri.rs index edb0f4093..8b0f96e70 100644 --- a/nannou/src/draw/primitive/tri.rs +++ b/nannou/src/draw/primitive/tri.rs @@ -6,24 +6,24 @@ use crate::draw::properties::{ ColorScalar, LinSrgba, SetColor, SetDimensions, SetOrientation, SetPosition, SetStroke, }; use crate::draw::{self, Drawing}; -use crate::geom::{self, Point2, Vector2}; -use crate::math::{BaseFloat, ElementWise}; +use crate::geom::{self, pt2, Point2}; +use crate::glam::vec2; use lyon::tessellation::StrokeOptions; /// Properties related to drawing a **Tri**. #[derive(Clone, Debug)] -pub struct Tri { - tri: geom::Tri>, - dimensions: dimension::Properties, - polygon: PolygonInit, +pub struct Tri { + tri: geom::Tri, + dimensions: dimension::Properties, + polygon: PolygonInit, } /// The drawing context for a `Tri`. -pub type DrawingTri<'a, S = geom::scalar::Default> = Drawing<'a, Tri, S>; +pub type DrawingTri<'a> = Drawing<'a, Tri>; // Tri-specific methods. -impl Tri { +impl Tri { /// Stroke the outline with the given color. pub fn stroke(self, color: C) -> Self where @@ -35,7 +35,7 @@ impl Tri { /// Use the given three points as the vertices (corners) of the triangle. pub fn points

(mut self, a: P, b: P, c: P) -> Self where - P: Into>, + P: Into, { let a = a.into(); let b = b.into(); @@ -47,10 +47,7 @@ impl Tri { // Drawing methods. -impl<'a, S> DrawingTri<'a, S> -where - S: BaseFloat, -{ +impl<'a> DrawingTri<'a> { /// Stroke the outline with the given color. pub fn stroke(self, color: C) -> Self where @@ -62,7 +59,7 @@ where /// Use the given points as the vertices (corners) of the triangle. pub fn points

(self, a: P, b: P, c: P) -> Self where - P: Into>, + P: Into, { self.map_ty(|ty| ty.points(a, b, c)) } @@ -70,7 +67,7 @@ where // Trait implementations. -impl draw::renderer::RenderPrimitive for Tri { +impl draw::renderer::RenderPrimitive for Tri { fn render_primitive( self, ctxt: draw::renderer::RenderContext, @@ -88,12 +85,9 @@ impl draw::renderer::RenderPrimitive for Tri { let centroid = tri.centroid(); let x_scale = maybe_x.map(|x| x / cuboid.w()).unwrap_or(1.0); let y_scale = maybe_y.map(|y| y / cuboid.h()).unwrap_or(1.0); - let scale = Vector2 { - x: x_scale, - y: y_scale, - }; + let scale = vec2(x_scale, y_scale); let (a, b, c) = tri.into(); - let translate = |v: Point2| centroid + ((v - centroid).mul_element_wise(scale)); + let translate = |v: Point2| centroid + ((v - centroid) * scale); let new_a = translate(a); let new_b = translate(b); let new_c = translate(c); @@ -112,11 +106,8 @@ impl draw::renderer::RenderPrimitive for Tri { } } -impl From>> for Tri -where - S: BaseFloat, -{ - fn from(tri: geom::Tri>) -> Self { +impl From> for Tri { + fn from(tri: geom::Tri) -> Self { let dimensions = <_>::default(); let polygon = <_>::default(); Tri { @@ -127,74 +118,64 @@ where } } -impl Default for Tri -where - S: BaseFloat, -{ +impl Default for Tri { fn default() -> Self { // Create a triangle pointing towards 0.0 radians. - let zero = S::zero(); - let fifty = S::from(50.0).unwrap(); - let thirty_three = S::from(33.0).unwrap(); - let a = Point2 { - x: -fifty, - y: thirty_three, - }; - let b = Point2 { x: fifty, y: zero }; - let c = Point2 { - x: -fifty, - y: -thirty_three, - }; + let fifty = 50.0; + let thirty_three = 33.0; + let a = pt2(-fifty, thirty_three); + let b = pt2(fifty, 0.0); + let c = pt2(-fifty, -thirty_three); Tri::from(geom::Tri([a, b, c])) } } -impl SetOrientation for Tri { - fn properties(&mut self) -> &mut orientation::Properties { +impl SetOrientation for Tri { + fn properties(&mut self) -> &mut orientation::Properties { SetOrientation::properties(&mut self.polygon) } } -impl SetPosition for Tri { - fn properties(&mut self) -> &mut position::Properties { +impl SetPosition for Tri { + fn properties(&mut self) -> &mut position::Properties { SetPosition::properties(&mut self.polygon) } } -impl SetDimensions for Tri { - fn properties(&mut self) -> &mut dimension::Properties { +impl SetDimensions for Tri { + fn properties(&mut self) -> &mut dimension::Properties { SetDimensions::properties(&mut self.dimensions) } } -impl SetColor for Tri { +impl SetColor for Tri { fn rgba_mut(&mut self) -> &mut Option { SetColor::rgba_mut(&mut self.polygon) } } -impl SetStroke for Tri { +impl SetStroke for Tri { fn stroke_options_mut(&mut self) -> &mut StrokeOptions { SetStroke::stroke_options_mut(&mut self.polygon) } } -impl SetPolygon for Tri { - fn polygon_options_mut(&mut self) -> &mut PolygonOptions { +impl SetPolygon for Tri { + fn polygon_options_mut(&mut self) -> &mut PolygonOptions { SetPolygon::polygon_options_mut(&mut self.polygon) } } // Primitive conversions. -impl From> for Primitive { - fn from(prim: Tri) -> Self { +impl From for Primitive { + fn from(prim: Tri) -> Self { Primitive::Tri(prim) } } -impl Into>> for Primitive { - fn into(self) -> Option> { +impl Into> for Primitive { + fn into(self) -> Option { match self { Primitive::Tri(prim) => Some(prim), _ => None, diff --git a/nannou/src/draw/properties/spatial/dimension.rs b/nannou/src/draw/properties/spatial/dimension.rs index 26753f9c4..3ad341760 100644 --- a/nannou/src/draw/properties/spatial/dimension.rs +++ b/nannou/src/draw/properties/spatial/dimension.rs @@ -1,84 +1,74 @@ -use crate::geom::{self, Vector2, Vector3}; +use crate::glam::{Vec2, Vec3}; /// Dimension properties for **Drawing** a **Primitive**. -#[derive(Copy, Clone, Debug, PartialEq)] -pub struct Properties { - pub x: Option, - pub y: Option, - pub z: Option, +#[derive(Copy, Clone, Debug, Default, PartialEq)] +pub struct Properties { + pub x: Option, + pub y: Option, + pub z: Option, } /// Primitives that support different dimensions. -pub trait SetDimensions: Sized { +pub trait SetDimensions: Sized { /// Provide a mutable reference to the **dimension::Properties** for updating. - fn properties(&mut self) -> &mut Properties; + fn properties(&mut self) -> &mut Properties; /// Set the absolute width for the primitive. - fn width(mut self, w: S) -> Self { + fn width(mut self, w: f32) -> Self { self.properties().x = Some(w); self } /// Set the absolute height for the primitive. - fn height(mut self, h: S) -> Self { + fn height(mut self, h: f32) -> Self { self.properties().y = Some(h); self } /// Set the absolute depth for the primitive. - fn depth(mut self, d: S) -> Self { + fn depth(mut self, d: f32) -> Self { self.properties().z = Some(d); self } /// Short-hand for the **width** method. - fn w(self, w: S) -> Self { + fn w(self, w: f32) -> Self { self.width(w) } /// Short-hand for the **height** method. - fn h(self, h: S) -> Self { + fn h(self, h: f32) -> Self { self.height(h) } /// Short-hand for the **depth** method. - fn d(self, d: S) -> Self { + fn d(self, d: f32) -> Self { self.depth(d) } /// Set the **x** and **y** dimensions for the primitive. - fn wh(self, v: Vector2) -> Self { + fn wh(self, v: Vec2) -> Self { self.w(v.x).h(v.y) } /// Set the **x**, **y** and **z** dimensions for the primitive. - fn whd(self, v: Vector3) -> Self { + fn whd(self, v: Vec3) -> Self { self.w(v.x).h(v.y).d(v.z) } /// Set the width and height for the primitive. - fn w_h(self, x: S, y: S) -> Self { - self.wh(Vector2 { x, y }) + fn w_h(self, x: f32, y: f32) -> Self { + self.wh([x, y].into()) } /// Set the width and height for the primitive. - fn w_h_d(self, x: S, y: S, z: S) -> Self { - self.whd(Vector3 { x, y, z }) + fn w_h_d(self, x: f32, y: f32, z: f32) -> Self { + self.whd([x, y, z].into()) } } -impl SetDimensions for Properties { - fn properties(&mut self) -> &mut Properties { +impl SetDimensions for Properties { + fn properties(&mut self) -> &mut Properties { self } } - -impl Default for Properties { - fn default() -> Self { - Self { - x: None, - y: None, - z: None, - } - } -} diff --git a/nannou/src/draw/properties/spatial/mod.rs b/nannou/src/draw/properties/spatial/mod.rs index a217686a3..d7aa8fa57 100644 --- a/nannou/src/draw/properties/spatial/mod.rs +++ b/nannou/src/draw/properties/spatial/mod.rs @@ -1,6 +1,3 @@ -use crate::geom; -use crate::math::Zero; - pub mod dimension; pub mod orientation; pub mod position; @@ -10,21 +7,18 @@ pub use self::orientation::SetOrientation; pub use self::position::SetPosition; /// Types that may be positioned, sized and oriented within 3D space. -pub trait SetSpatial: SetDimensions + SetPosition + SetOrientation {} +pub trait SetSpatial: SetDimensions + SetPosition + SetOrientation {} -impl SetSpatial for T where T: SetDimensions + SetPosition + SetOrientation {} +impl SetSpatial for T where T: SetDimensions + SetPosition + SetOrientation {} #[derive(Copy, Clone, Debug, PartialEq)] -pub struct Properties { - pub position: position::Properties, - pub dimensions: dimension::Properties, - pub orientation: orientation::Properties, +pub struct Properties { + pub position: position::Properties, + pub dimensions: dimension::Properties, + pub orientation: orientation::Properties, } -impl Default for Properties -where - S: Zero, -{ +impl Default for Properties { fn default() -> Self { let position = Default::default(); let dimensions = Default::default(); @@ -37,20 +31,20 @@ where } } -impl SetPosition for Properties { - fn properties(&mut self) -> &mut position::Properties { +impl SetPosition for Properties { + fn properties(&mut self) -> &mut position::Properties { self.position.properties() } } -impl SetDimensions for Properties { - fn properties(&mut self) -> &mut dimension::Properties { +impl SetDimensions for Properties { + fn properties(&mut self) -> &mut dimension::Properties { self.dimensions.properties() } } -impl SetOrientation for Properties { - fn properties(&mut self) -> &mut orientation::Properties { +impl SetOrientation for Properties { + fn properties(&mut self) -> &mut orientation::Properties { self.orientation.properties() } } diff --git a/nannou/src/draw/properties/spatial/orientation.rs b/nannou/src/draw/properties/spatial/orientation.rs index b15029d9f..c312189eb 100644 --- a/nannou/src/draw/properties/spatial/orientation.rs +++ b/nannou/src/draw/properties/spatial/orientation.rs @@ -1,36 +1,28 @@ -use crate::geom::{self, Point3, Vector3}; -use crate::math::{deg_to_rad, turns_to_rad, Angle, BaseFloat, Euler, Quaternion, Rad, Zero}; +use crate::geom::Point3; +use crate::glam::{EulerRot, Mat4, Quat, Vec3}; +use crate::math::{deg_to_rad, turns_to_rad}; /// Orientation properties for **Drawing** a **Primitive**. #[derive(Copy, Clone, Debug, PartialEq)] -pub enum Properties { +pub enum Properties { /// The orientation described by an angle along each axis. - Axes(Vector3), + Axes(Vec3), /// The orientation described by looking at some other point. - LookAt(Point3), + LookAt(Point3), + /// Angle described by quarternion. + Quat(Quat), } -impl Properties -where - S: Zero, -{ - pub fn transform(&self) -> cgmath::Matrix4 - where - S: BaseFloat, - { +impl Properties { + pub fn transform(&self) -> Mat4 { match *self { - Properties::Axes(v) => { - let euler = cgmath::Euler { - x: cgmath::Rad(v.x), - y: cgmath::Rad(v.y), - z: cgmath::Rad(v.z), - }; - cgmath::Matrix4::from(euler) - } + Properties::Axes(v) => Mat4::from_euler(EulerRot::XYZ, v.x, v.y, v.z), Properties::LookAt(p) => { - let eye = Vector3::new(S::zero(), S::zero(), S::zero()); - cgmath::Matrix4::look_at_dir(eye.into(), p.into(), up().into()) + let eye = Vec3::ZERO; + let up = Vec3::Y; + Mat4::look_at_rh(eye, p, up) } + Properties::Quat(q) => Mat4::from_quat(q), } } @@ -40,24 +32,20 @@ where /// If the `Properties` is already `Axes`, nothing changes. pub fn switch_to_axes(&mut self) { if let Properties::LookAt(_) = *self { - *self = Properties::Axes(Vector3::zero()); + *self = Properties::Axes(Vec3::ZERO); } } } -fn up() -> Vector3 { - Vector3::new(S::zero(), S::one(), S::zero()) -} - /// An API for setting the **orientation::Properties**. -pub trait SetOrientation: Sized { +pub trait SetOrientation: Sized { /// Provide a mutable reference to the **orientation::Properties** for updating. - fn properties(&mut self) -> &mut Properties; + fn properties(&mut self) -> &mut Properties; // Describing orientation via a target. /// Describe orientation via the vector that points to the given target. - fn look_at(mut self, target: Point3) -> Self { + fn look_at(mut self, target: Point3) -> Self { *self.properties() = Properties::LookAt(target); self } @@ -65,130 +53,86 @@ pub trait SetOrientation: Sized { // Absolute orientation. /// Specify the orientation around the *x* axis as an absolute value in radians. - fn x_radians(mut self, x: S) -> Self - where - S: BaseFloat, - { + fn x_radians(mut self, x: f32) -> Self { self.properties().switch_to_axes(); expect_axes(self.properties()).x = x; self } /// Specify the orientation around the *y* axis as an absolute value in radians. - fn y_radians(mut self, y: S) -> Self - where - S: BaseFloat, - { + fn y_radians(mut self, y: f32) -> Self { self.properties().switch_to_axes(); expect_axes(self.properties()).y = y; self } /// Specify the orientation around the *z* axis as an absolute value in radians. - fn z_radians(mut self, z: S) -> Self - where - S: BaseFloat, - { + fn z_radians(mut self, z: f32) -> Self { self.properties().switch_to_axes(); expect_axes(self.properties()).z = z; self } /// Specify the orientation around the *x* axis as an absolute value in degrees. - fn x_degrees(self, x: S) -> Self - where - S: BaseFloat, - { + fn x_degrees(self, x: f32) -> Self { self.x_radians(deg_to_rad(x)) } /// Specify the orientation around the *y* axis as an absolute value in degrees. - fn y_degrees(self, y: S) -> Self - where - S: BaseFloat, - { + fn y_degrees(self, y: f32) -> Self { self.y_radians(deg_to_rad(y)) } /// Specify the orientation around the *z* axis as an absolute value in degrees. - fn z_degrees(self, z: S) -> Self - where - S: BaseFloat, - { + fn z_degrees(self, z: f32) -> Self { self.z_radians(deg_to_rad(z)) } /// Specify the orientation around the *x* axis as a number of turns around the axis. - fn x_turns(self, x: S) -> Self - where - S: BaseFloat, - { + fn x_turns(self, x: f32) -> Self { self.x_radians(turns_to_rad(x)) } /// Specify the orientation around the *y* axis as a number of turns around the axis. - fn y_turns(self, y: S) -> Self - where - S: BaseFloat, - { + fn y_turns(self, y: f32) -> Self { self.y_radians(turns_to_rad(y)) } /// Specify the orientation around the *z* axis as a number of turns around the axis. - fn z_turns(self, z: S) -> Self - where - S: BaseFloat, - { + fn z_turns(self, z: f32) -> Self { self.z_radians(turns_to_rad(z)) } /// Specify the orientation along each axis with the given **Vector** of radians. /// /// This has the same affect as calling `self.x_radians(v.x).y_radians(v.y).z_radians(v.z)`. - fn radians(self, v: Vector3) -> Self - where - S: BaseFloat, - { + fn radians(self, v: Vec3) -> Self { self.x_radians(v.x).y_radians(v.y).z_radians(v.z) } /// Specify the orientation along each axis with the given **Vector** of degrees. /// /// This has the same affect as calling `self.x_degrees(v.x).y_degrees(v.y).z_degrees(v.z)`. - fn degrees(self, v: Vector3) -> Self - where - S: BaseFloat, - { + fn degrees(self, v: Vec3) -> Self { self.x_degrees(v.x).y_degrees(v.y).z_degrees(v.z) } /// Specify the orientation along each axis with the given **Vector** of "turns". /// /// This has the same affect as calling `self.x_turns(v.x).y_turns(v.y).z_turns(v.z)`. - fn turns(self, v: Vector3) -> Self - where - S: BaseFloat, - { + fn turns(self, v: Vec3) -> Self { self.x_turns(v.x).y_turns(v.y).z_turns(v.z) } - /// Specify the orientation with the given **Euler**. - /// - /// The euler can be specified in either radians (via **Rad**) or degrees (via **Deg**). - fn euler(self, e: Euler) -> Self - where - S: BaseFloat, - A: Angle + Into>, - { - self.radians(euler_to_vec3(e)) + /// Specify the orientation with the given euler orientation in radians. + fn euler(self, e: Vec3) -> Self { + self.radians(e) } /// Specify the orientation with the given **Quaternion**. - fn quaternion(self, q: Quaternion) -> Self - where - S: BaseFloat, - { - self.euler(q.into()) + fn quaternion(mut self, q: Quat) -> Self { + *self.properties() = Properties::Quat(q); + self } // Higher level methods. @@ -196,30 +140,21 @@ pub trait SetOrientation: Sized { /// Specify the "pitch" of the orientation in radians. /// /// This has the same effect as calling `x_radians`. - fn pitch(self, pitch: S) -> Self - where - S: BaseFloat, - { + fn pitch(self, pitch: f32) -> Self { self.x_radians(pitch) } /// Specify the "yaw" of the orientation in radians. /// /// This has the same effect as calling `y_radians`. - fn yaw(self, yaw: S) -> Self - where - S: BaseFloat, - { + fn yaw(self, yaw: f32) -> Self { self.y_radians(yaw) } /// Specify the "roll" of the orientation in radians. /// /// This has the same effect as calling `z_radians`. - fn roll(self, roll: S) -> Self - where - S: BaseFloat, - { + fn roll(self, roll: f32) -> Self { self.z_radians(roll) } @@ -227,45 +162,28 @@ pub trait SetOrientation: Sized { /// given value is specified in radians. /// /// This is equivalent to calling the `z_radians` or `roll` methods. - fn rotate(self, radians: S) -> Self - where - S: BaseFloat, - { + fn rotate(self, radians: f32) -> Self { self.z_radians(radians) } } -impl SetOrientation for Properties { - fn properties(&mut self) -> &mut Properties { +impl SetOrientation for Properties { + fn properties(&mut self) -> &mut Properties { self } } -impl Default for Properties -where - S: Zero, -{ +impl Default for Properties { fn default() -> Self { - Properties::Axes(Vector3::zero()) + Properties::Axes(Vec3::ZERO) } } // Expects the `Axes` variant from the given properties. -fn expect_axes(p: &mut Properties) -> &mut Vector3 { +fn expect_axes(p: &mut Properties) -> &mut Vec3 { match *p { Properties::Axes(ref mut axes) => axes, Properties::LookAt(_) => panic!("expected `Axes`, found `LookAt`"), + Properties::Quat(_) => panic!("expected `Axes`, found `Quat`"), } } - -// Convert the given `Euler` into a `Vector3`. -fn euler_to_vec3(e: Euler) -> Vector3 -where - S: BaseFloat, - A: Angle + Into>, -{ - let x = e.x.into().0; - let y = e.y.into().0; - let z = e.z.into().0; - Vector3 { x, y, z } -} diff --git a/nannou/src/draw/properties/spatial/position.rs b/nannou/src/draw/properties/spatial/position.rs index 45814e92d..413c09907 100644 --- a/nannou/src/draw/properties/spatial/position.rs +++ b/nannou/src/draw/properties/spatial/position.rs @@ -1,79 +1,73 @@ //! Items related to describing positioning along each axis as -use crate::geom::{self, Point2, Point3}; -use crate::math::{BaseFloat, Zero}; +use crate::geom::{Point2, Point3}; +use crate::glam::Mat4; /// Position properties for **Drawing** a **Primitive**. #[derive(Copy, Clone, Debug, PartialEq)] -pub struct Properties { - pub point: Point3, +pub struct Properties { + pub point: Point3, } /// An API for setting the **position::Properties**. -pub trait SetPosition: Sized { +pub trait SetPosition: Sized { /// Provide a mutable reference to the **position::Properties** for updating. - fn properties(&mut self) -> &mut Properties; + fn properties(&mut self) -> &mut Properties; /// Build with the given **Absolute** **Position** along the *x* axis. - fn x(mut self, x: S) -> Self { + fn x(mut self, x: f32) -> Self { self.properties().point.x = x; self } /// Build with the given **Absolute** **Position** along the *y* axis. - fn y(mut self, y: S) -> Self { + fn y(mut self, y: f32) -> Self { self.properties().point.y = y; self } /// Build with the given **Absolute** **Position** along the *z* axis. - fn z(mut self, z: S) -> Self { + fn z(mut self, z: f32) -> Self { self.properties().point.z = z; self } /// Set the **Position** with some two-dimensional point. - fn xy(self, p: Point2) -> Self { + fn xy(self, p: Point2) -> Self { self.x(p.x).y(p.y) } /// Set the **Position** with some three-dimensional point. - fn xyz(self, p: Point3) -> Self { + fn xyz(self, p: Point3) -> Self { self.x(p.x).y(p.y).z(p.z) } /// Set the **Position** with *x* *y* coordinates. - fn x_y(self, x: S, y: S) -> Self { - self.xy(Point2 { x, y }) + fn x_y(self, x: f32, y: f32) -> Self { + self.xy([x, y].into()) } /// Set the **Position** with *x* *y* *z* coordinates. - fn x_y_z(self, x: S, y: S, z: S) -> Self { - self.xyz(Point3 { x, y, z }) + fn x_y_z(self, x: f32, y: f32, z: f32) -> Self { + self.xyz([x, y, z].into()) } } -impl Properties { - pub fn transform(&self) -> cgmath::Matrix4 - where - S: BaseFloat, - { - cgmath::Matrix4::from_translation(self.point.into()) +impl Properties { + pub fn transform(&self) -> Mat4 { + Mat4::from_translation(self.point.into()) } } -impl SetPosition for Properties { - fn properties(&mut self) -> &mut Properties { +impl SetPosition for Properties { + fn properties(&mut self) -> &mut Properties { self } } -impl Default for Properties -where - S: Zero, -{ +impl Default for Properties { fn default() -> Self { - let point = Point3::zero(); + let point = Point3::ZERO; Self { point } } } diff --git a/nannou/src/draw/renderer/mod.rs b/nannou/src/draw/renderer/mod.rs index 0c95f9c61..9f5dd00c8 100644 --- a/nannou/src/draw/renderer/mod.rs +++ b/nannou/src/draw/renderer/mod.rs @@ -1,8 +1,9 @@ use crate::draw; -use crate::draw::mesh::vertex::Color; +use crate::draw::mesh::vertex::{Color, TexCoords}; use crate::frame::Frame; -use crate::geom::{self, Point2, Rect, Vector2}; -use crate::math::{map_range, Matrix4}; +use crate::geom::{self, Point2, Rect}; +use crate::glam::{Mat4, Vec2, Vec3}; +use crate::math::map_range; use crate::text; use crate::wgpu; use lyon::path::PathEvent; @@ -33,17 +34,17 @@ pub struct PrimitiveRender { /// The context provided to primitives to assist with the rendering process. pub struct RenderContext<'a> { - pub transform: &'a crate::math::Matrix4, + pub transform: &'a Mat4, pub intermediary_mesh: &'a draw::Mesh, pub path_event_buffer: &'a [PathEvent], pub path_points_colored_buffer: &'a [(Point2, Color)], - pub path_points_textured_buffer: &'a [(Point2, Point2)], + pub path_points_textured_buffer: &'a [(Point2, TexCoords)], pub text_buffer: &'a str, pub theme: &'a draw::Theme, pub glyph_cache: &'a mut GlyphCache, pub fill_tessellator: &'a mut FillTessellator, pub stroke_tessellator: &'a mut StrokeTessellator, - pub output_attachment_size: Vector2, // logical coords + pub output_attachment_size: Vec2, // logical coords pub output_attachment_scale_factor: f32, } @@ -139,10 +140,6 @@ pub struct DrawError; #[repr(C)] #[derive(Copy, Clone, Debug)] struct Uniforms { - // /// The vector to multiply onto vertices in the vertex shader to map them from window space to - // /// shader space. - // window_to_shader: [f32; 3], - //view: Matrix4, /// Translates from "logical pixel coordinate space" (our "world space") to screen space. /// /// Specifically: @@ -150,7 +147,7 @@ struct Uniforms { /// - x is transformed from (-half_logical_win_w, half_logical_win_w) to (-1, 1). /// - y is transformed from (-half_logical_win_h, half_logical_win_h) to (1, -1). /// - z is transformed from (-max_logical_win_side, max_logical_win_side) to (0, 1). - proj: Matrix4, + proj: Mat4, } type SamplerId = u64; @@ -532,7 +529,7 @@ impl Renderer { let pt_to_px = |s: f32| (s * scale_factor).round() as u32; let full_rect = Rect::from_w_h(px_to_pt(w_px), px_to_pt(h_px)); - let window_to_scissor = |v: Vector2| -> [u32; 2] { + let window_to_scissor = |v: Vec2| -> [u32; 2] { let x = map_range(v.x, full_rect.left(), full_rect.right(), 0u32, w_px); let y = map_range(v.y, full_rect.bottom(), full_rect.top(), 0u32, h_px); [x, y] @@ -578,7 +575,7 @@ impl Renderer { fill_tessellator: &mut fill_tessellator, stroke_tessellator: &mut stroke_tessellator, glyph_cache: &mut self.glyph_cache, - output_attachment_size: Vector2::new(px_to_pt(w_px), px_to_pt(h_px)), + output_attachment_size: Vec2::new(px_to_pt(w_px), px_to_pt(h_px)), output_attachment_scale_factor: scale_factor, }; @@ -674,7 +671,7 @@ impl Renderer { .unwrap_or(geom::Rect::from_w_h(0.0, 0.0)), draw::Scissor::NoOverlap => geom::Rect::from_w_h(0.0, 0.0), }; - let [left, bottom] = window_to_scissor(rect.bottom_left()); + let [left, bottom] = window_to_scissor(rect.bottom_left().into()); let (width, height) = rect.w_h(); let (width, height) = (pt_to_px(width), pt_to_px(height)); let scissor = Scissor { @@ -1029,11 +1026,12 @@ fn create_uniforms([img_w, img_h]: [u32; 2], scale_factor: f32) -> Uniforms { let bottom = -top; let far = std::cmp::max(img_w, img_h) as f32 / scale_factor; let near = -far; - let proj = cgmath::ortho(left, right, bottom, top, near, far); + let proj = Mat4::orthographic_rh_gl(left, right, bottom, top, near, far); // By default, ortho scales z values to the range -1.0 to 1.0. We want to scale and translate // the z axis so that it is in the range of 0.0 to 1.0. - let trans = cgmath::Matrix4::from_translation(cgmath::Vector3::new(0.0, 0.0, 1.0)); - let scale = cgmath::Matrix4::from_nonuniform_scale(1.0, 1.0, 0.5); + // TODO: Can possibly solve this more easily by using `Mat4::orthographic_rh` above instead. + let trans = Mat4::from_translation(Vec3::Z); + let scale = Mat4::from_scale([1.0, 1.0, 0.5].into()); let proj = scale * trans * proj; let proj = proj.into(); Uniforms { proj } diff --git a/nannou/src/event.rs b/nannou/src/event.rs index e40b7fc76..3f4d73e54 100644 --- a/nannou/src/event.rs +++ b/nannou/src/event.rs @@ -6,7 +6,8 @@ //! - [**WindowEvent**](./enum.WindowEvent.html) - a stripped-back, simplified, newcomer-friendly //! version of the **raw**, low-level winit event. -use crate::geom::{self, Point2, Vector2}; +use crate::geom::{self, Point2}; +use crate::glam::Vec2; use crate::window; use crate::App; use std::path::PathBuf; @@ -74,7 +75,7 @@ pub struct TouchEvent { /// The state of the touch. pub phase: TouchPhase, /// The position of the touch. - pub position: Point2, + pub position: Point2, } /// Pressure on a touch pad. @@ -112,7 +113,7 @@ pub struct AxisMotion { #[derive(Clone, Debug, PartialEq)] pub enum WindowEvent { /// The window has been moved to a new position. - Moved(Point2), + Moved(Point2), /// The given keyboard key was pressed. KeyPressed(Key), @@ -121,7 +122,7 @@ pub enum WindowEvent { KeyReleased(Key), /// The mouse moved to the given x, y position. - MouseMoved(Point2), + MouseMoved(Point2), /// The given mouse button was pressed. MousePressed(MouseButton), @@ -139,7 +140,7 @@ pub enum WindowEvent { MouseWheel(MouseScrollDelta, TouchPhase), /// The window was resized to the given dimensions (in DPI-agnostic points, not pixels). - Resized(Vector2), + Resized(Vec2), /// A file at the given path was hovered over the window. HoveredFile(PathBuf), @@ -195,24 +196,24 @@ impl WindowEvent { // // winit produces input events in pixels, so these positions need to be divided by the // width and height of the window in order to be DPI agnostic. - let tw = |w: f64| w as geom::scalar::Default; - let th = |h: f64| h as geom::scalar::Default; - let tx = |x: f64| (x - win_w / 2.0) as geom::scalar::Default; - let ty = |y: f64| (-(y - win_h / 2.0)) as geom::scalar::Default; + let tw = |w: f64| w as f32; + let th = |h: f64| h as f32; + let tx = |x: f64| (x - win_w / 2.0) as f32; + let ty = |y: f64| (-(y - win_h / 2.0)) as f32; let event = match event { winit::event::WindowEvent::Resized(new_size) => { let (new_w, new_h) = new_size.to_logical::(scale_factor).into(); let x = tw(new_w); let y = th(new_h); - Resized(Vector2 { x, y }) + Resized([x, y].into()) } winit::event::WindowEvent::Moved(new_pos) => { let (new_x, new_y) = new_pos.to_logical::(scale_factor).into(); let x = tx(new_x); let y = ty(new_y); - Moved(Point2 { x, y }) + Moved([x, y].into()) } // TODO: Should separate the behaviour of close requested and destroyed. @@ -238,7 +239,7 @@ impl WindowEvent { let (x, y) = position.to_logical::(scale_factor).into(); let x = tx(x); let y = ty(y); - MouseMoved(Point2 { x, y }) + MouseMoved([x, y].into()) } winit::event::WindowEvent::CursorEntered { .. } => MouseEntered, @@ -263,7 +264,7 @@ impl WindowEvent { let (x, y) = location.to_logical::(scale_factor).into(); let x = tx(x); let y = ty(y); - let position = Point2 { x, y }; + let position = [x, y].into(); let touch = TouchEvent { phase: phase.clone(), position, diff --git a/nannou/src/geom/graph/edge.rs b/nannou/src/geom/graph/edge.rs deleted file mode 100644 index ae897a4d0..000000000 --- a/nannou/src/geom/graph/edge.rs +++ /dev/null @@ -1,251 +0,0 @@ -//! Items related to the edges of a geometry graph. -use crate::geom::{self, Vector3}; -use crate::math::{BaseFloat, Euler, Rad}; -use daggy; - -/// Unique index for an **Edge** within a **Graph**. -pub type Index = daggy::EdgeIndex; - -/// An iterator yielding multiple `Index`es. -pub type Indices = daggy::EdgeIndices; - -/// Describes an edge within the geometry graph. -#[derive(Copy, Clone, Debug, PartialEq)] -pub struct Edge { - /// The unique kind of edge. - /// - /// Represents the combination of `Axis` and `Relative` association described by the edge. - pub kind: Kind, - /// A weight whose value's meaning depends on the edge's `Relative` association. - /// - /// For `Position` kind edges this represents a relative scalar value. - /// For `Orientation` kind edges this represents a relative angle in radians. - /// For `Scale` kind edges this represents the relative scale. - pub weight: S, -} - -/// The unique `Edge` kind - a combo of a `Relative` association and an `Axis`. -/// -/// Every incoming (parent) `Edge` for each `Node` in the graph *must* be a unique kind. E.g. -/// it does not make sense for a `Node` to be positioned relatively along the *x* axis to two -/// different parent `Node`s. -#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)] -pub struct Kind { - /// The axis along which this edge describes some relationship. - pub axis: Axis, - /// The relative association described by the edge. - pub relative: Relative, -} - -/// Describes one of the three axes in three-dimensional space. -#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)] -pub enum Axis { - X, - Y, - Z, -} - -/// The various possible relative relationships that can be created between nodes. -#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)] -pub enum Relative { - /// A relative position as a scalar value. - Position, - /// A relative orientation in radians. - Orientation, - /// A relative scale. - Scale, -} - -impl Kind { - /// Simple constructor for an edge `Kind`. - pub fn new(axis: Axis, relative: Relative) -> Self { - Kind { axis, relative } - } - - /// Simple constructor for and Edge describing a relative association over the **X** axis. - pub fn x(relative: Relative) -> Self { - Kind::new(Axis::X, relative) - } - - /// Simple constructor for and Edge describing a relative association over the **Y** axis. - pub fn y(relative: Relative) -> Self { - Kind::new(Axis::Y, relative) - } - - /// Simple constructor for and Edge describing a relative association over the **Z** axis. - pub fn z(relative: Relative) -> Self { - Kind::new(Axis::Z, relative) - } - - /// Simple constructor for an Edge describing a relative position along the given axis. - pub fn position(axis: Axis) -> Self { - let relative = Relative::Position; - Kind { axis, relative } - } - - /// Simple constructor for an Edge describing a relative orientation along the given axis. - pub fn orientation(axis: Axis) -> Self { - let relative = Relative::Orientation; - Kind { axis, relative } - } - - /// Simple constructor for an Edge describing a relative scale along the given axis. - pub fn scale(axis: Axis) -> Self { - let relative = Relative::Scale; - Kind { axis, relative } - } - - /// Simple constructor for and Edge describing a relative position over the **X** axis. - pub fn x_position() -> Self { - Kind::x(Relative::Position) - } - - /// Simple constructor for and Edge describing a relative orientation over the **X** axis. - pub fn x_orientation() -> Self { - Kind::x(Relative::Orientation) - } - - /// Simple constructor for and Edge describing a relative scale over the **X** axis. - pub fn x_scale() -> Self { - Kind::x(Relative::Scale) - } - - /// Simple constructor for and Edge describing a relative position over the **Y** axis. - pub fn y_position() -> Self { - Kind::y(Relative::Position) - } - - /// Simple constructor for and Edge describing a relative orientation over the **Y** axis. - pub fn y_orientation() -> Self { - Kind::y(Relative::Orientation) - } - - /// Simple constructor for and Edge describing a relative scale over the **Y** axis. - pub fn y_scale() -> Self { - Kind::y(Relative::Scale) - } - - /// Simple constructor for and Edge describing a relative position over the **Z** axis. - pub fn z_position() -> Self { - Kind::z(Relative::Position) - } - - /// Simple constructor for and Edge describing a relative orientation over the **Z** axis. - pub fn z_orientation() -> Self { - Kind::z(Relative::Orientation) - } - - /// Simple constructor for and Edge describing a relative scale over the **Z** axis. - pub fn z_scale() -> Self { - Kind::z(Relative::Scale) - } -} - -impl Edge { - /// Simple constructor for an `Edge`. - pub fn new(kind: Kind, weight: S) -> Self { - Edge { kind, weight } - } - - /// Simple constructor for an `Edge` describing a relative association over the **X** axis. - pub fn x(relative: Relative, weight: S) -> Self { - Edge::new(Kind::x(relative), weight) - } - - /// Simple constructor for an `Edge` describing a relative association over the **Y** axis. - pub fn y(relative: Relative, weight: S) -> Self { - Edge::new(Kind::y(relative), weight) - } - - /// Simple constructor for an `Edge` describing a relative association over the **Z** axis. - pub fn z(relative: Relative, weight: S) -> Self { - Edge::new(Kind::z(relative), weight) - } - - /// Simple constructor for an `Edge` describing a relative position over the given axis. - pub fn position(axis: Axis, weight: S) -> Self { - Edge::new(Kind::position(axis), weight) - } - - /// Simple constructor for an `Edge` describing a relative orientation over the given axis. - pub fn orientation(axis: Axis, weight: S) -> Self { - Edge::new(Kind::orientation(axis), weight) - } - - /// Simple constructor for an `Edge` describing a relative scale over the given axis. - pub fn scale(axis: Axis, weight: S) -> Self { - Edge::new(Kind::scale(axis), weight) - } - - /// Simple constructor for an `Edge` describing a relative position over the **X** axis. - pub fn x_position(weight: S) -> Self { - Edge::new(Kind::x_position(), weight) - } - - /// Simple constructor for an `Edge` describing a relative orientation over the **X** axis. - pub fn x_orientation(weight: S) -> Self { - Edge::new(Kind::x_orientation(), weight) - } - - /// Simple constructor for an `Edge` describing a relative scale over the **X** axis. - pub fn x_scale(weight: S) -> Self { - Edge::new(Kind::x_scale(), weight) - } - - /// Simple constructor for an `Edge` describing a relative position over the **Y** axis. - pub fn y_position(weight: S) -> Self { - Edge::new(Kind::y_position(), weight) - } - - /// Simple constructor for an `Edge` describing a relative orientation over the **Y** axis. - pub fn y_orientation(weight: S) -> Self { - Edge::new(Kind::y_orientation(), weight) - } - - /// Simple constructor for an `Edge` describing a relative scale over the **Y** axis. - pub fn y_scale(weight: S) -> Self { - Edge::new(Kind::y_scale(), weight) - } - - /// Simple constructor for an `Edge` describing a relative position over the **Z** axis. - pub fn z_position(weight: S) -> Self { - Edge::new(Kind::z_position(), weight) - } - - /// Simple constructor for an `Edge` describing a relative orientation over the **Z** axis. - pub fn z_orientation(weight: S) -> Self { - Edge::new(Kind::z_orientation(), weight) - } - - /// Simple constructor for an `Edge` describing a relative scale over the **Z** axis. - pub fn z_scale(weight: S) -> Self { - Edge::new(Kind::z_scale(), weight) - } -} - -/// The three edges describing the given position displacement. -pub fn displace(v: Vector3) -> [Edge; 3] { - [ - Edge::x_position(v.x), - Edge::y_position(v.y), - Edge::z_position(v.z), - ] -} - -/// The three edges describing the given orientation rotation. -pub fn rotate(e: Euler>) -> [Edge; 3] { - [ - Edge::x_orientation(e.x.0), - Edge::y_orientation(e.x.0), - Edge::z_orientation(e.z.0), - ] -} - -/// An edge for scaling each axis using the given single scalar scale value. -pub fn scale(scale: S) -> [Edge; 3] { - [ - Edge::x_scale(scale), - Edge::y_scale(scale), - Edge::z_scale(scale), - ] -} diff --git a/nannou/src/geom/graph/mod.rs b/nannou/src/geom/graph/mod.rs deleted file mode 100644 index f3c7192d1..000000000 --- a/nannou/src/geom/graph/mod.rs +++ /dev/null @@ -1,829 +0,0 @@ -use crate::geom::{self, Point3, Vector3}; -use crate::math::BaseFloat; -use daggy::petgraph::visit::{GraphBase, IntoNeighbors, Visitable}; -use daggy::{self, Walker}; -use std::iter; -use std::ops; -use std::option; - -pub use self::edge::Edge; -pub use self::node::Node; - -pub mod edge; -pub mod node; - -/// A composition of geometry described by an acyclic directed graph. -/// -/// The `Node`s within a graph may describe some primitive geometry (e.g. `Line`, `Cuboid`, etc) or -/// may contain other `Graph`s. This allows graphs to be composed of other graphs, which may then -/// be composed with other graphs, etc. -/// -/// The `Edge`s within a graph describe the relationships between the nodes. They allow for -/// describing the **position**, **orientation** and **scale** of nodes relative to others. -/// -/// All `Node`s other than the graph's "origin" node must have at least one parent, but may never -/// have more than one parent of each `edge::Kind`. -#[derive(Clone, Debug)] -pub struct Graph -where - S: BaseFloat, -{ - dag: Dag, - origin: node::Index, -} - -/// The `daggy` "directed acyclic graph" type used within the geometry graph. -pub type Dag = daggy::Dag, Edge, usize>; - -/// A **Walker** over some node's parent nodes. -pub struct Parents -where - S: BaseFloat, -{ - parents: daggy::Parents, Edge, usize>, -} - -/// A **Walker** over some node's children nodes. -pub struct Children -where - S: BaseFloat, -{ - children: daggy::Children, Edge, usize>, -} - -/// The slice of all nodes stored within the graph. -pub type RawNodes<'a, S = geom::scalar::Default> = daggy::RawNodes<'a, Node, usize>; - -/// The slice of all edges stored within the graph. -pub type RawEdges<'a, S = geom::scalar::Default> = daggy::RawEdges<'a, Edge, usize>; - -/// An alias for our Graph's **WouldCycle** error type. -pub type WouldCycle = daggy::WouldCycle>; - -/// An alias for our Graph's recursive walker. -pub type RecursiveWalk = daggy::walker::Recursive, F>; - -// An alias for the iterator yielding three parents that may or may not exist. -// -// Used for the `Position`, `Orientation` and `Scale` parents. -type ThreeNodes = iter::Chain< - iter::Chain, option::IntoIter>, - option::IntoIter, ->; - -/// An alias for the iterator yielding **X**, **Y** and **Z** **Position** parents. -pub type PositionParents = ThreeNodes; -/// An alias for the iterator yielding **X**, **Y** and **Z** **Orientation** parents. -pub type OrientationParents = ThreeNodes; -/// An alias for the iterator yielding **X**, **Y** and **Z** **Scale** parents. -pub type ScaleParents = ThreeNodes; -/// An alias for the iterator yielding **Position**, **Orientation** and **Scale** parents over the -/// **X** axis. -pub type XParents = ThreeNodes; -/// An alias for the iterator yielding **Position**, **Orientation** and **Scale** parents over the -/// **Y** axis. -pub type YParents = ThreeNodes; -/// An alias for the iterator yielding **Position**, **Orientation** and **Scale** parents over the -/// **Z** axis. -pub type ZParents = ThreeNodes; - -/// A **Walker** type yielding all transformed vertices of all nodes within the graph. -pub struct WalkVertices<'a, F, I, S: 'a = geom::scalar::Default> -where - F: Fn(&node::Index) -> I, - I: IntoIterator, - S: BaseFloat, -{ - dfs: &'a mut node::Dfs, - vertices_fn: F, - node: Option>, -} - -/// A **Walker** type yielding all transformed triangles of all nodes within the graph. -pub struct WalkTriangles<'a, F, I, V, S: 'a = geom::scalar::Default> -where - F: Fn(&node::Index) -> I, - I: IntoIterator, - S: BaseFloat, -{ - dfs: &'a mut node::Dfs, - triangles_fn: F, - node: Option>, -} - -/// An iterator yielding all vertices of all nodes within the graph. -/// -/// Uses the `WalkVertices` internally. -pub struct Vertices<'a, 'b, F, I, S: 'a + 'b = geom::scalar::Default> -where - F: Fn(&node::Index) -> I, - I: IntoIterator, - S: BaseFloat, -{ - graph: &'a Graph, - walker: WalkVertices<'b, F, I, S>, -} - -/// An iterator yielding all triangles of all nodes within the graph. -/// -/// Uses the `WalkTriangles` internally. -pub struct Triangles<'a, 'b, F, I, V, S: 'a + 'b = geom::scalar::Default> -where - F: Fn(&node::Index) -> I, - I: IntoIterator, - S: BaseFloat, -{ - graph: &'a Graph, - walker: WalkTriangles<'b, F, I, V, S>, -} - -impl<'a, F, I, S> WalkVertices<'a, F, I, S> -where - F: Fn(&node::Index) -> I, - I: IntoIterator, - I::Item: node::ApplyTransform, - S: BaseFloat, -{ - /// Return the next vertex in the graph. - pub fn next(&mut self, graph: &Graph) -> Option { - let WalkVertices { - ref mut dfs, - ref vertices_fn, - ref mut node, - } = *self; - loop { - if let Some(v) = node.as_mut().and_then(|n| n.next()) { - return Some(v); - } - match dfs.next_vertices(graph, vertices_fn) { - Some((_n, vs)) => *node = Some(vs), - None => return None, - } - } - } -} - -impl<'a, F, I, V, S> WalkTriangles<'a, F, I, V, S> -where - F: Fn(&node::Index) -> I, - I: IntoIterator>, - V: geom::Vertex + node::ApplyTransform, - S: BaseFloat, -{ - /// Return the next vertex in the graph. - pub fn next(&mut self, graph: &Graph) -> Option> { - let WalkTriangles { - ref mut dfs, - ref triangles_fn, - ref mut node, - } = *self; - loop { - if let Some(v) = node.as_mut().and_then(|n| n.next()) { - return Some(v); - } - match dfs.next_triangles(graph, triangles_fn) { - Some((_n, ts)) => *node = Some(ts), - None => return None, - } - } - } -} - -impl<'a, 'b, F, I, S> Iterator for Vertices<'a, 'b, F, I, S> -where - F: Fn(&node::Index) -> I, - I: IntoIterator, - I::Item: node::ApplyTransform, - S: BaseFloat, -{ - type Item = I::Item; - fn next(&mut self) -> Option { - self.walker.next(self.graph) - } -} - -impl<'a, 'b, F, I, V, S> Iterator for Triangles<'a, 'b, F, I, V, S> -where - F: Fn(&node::Index) -> I, - I: IntoIterator>, - V: geom::Vertex + node::ApplyTransform, - S: BaseFloat, -{ - type Item = geom::Tri; - fn next(&mut self) -> Option { - self.walker.next(self.graph) - } -} - -impl Graph -where - S: BaseFloat, -{ - /// Construct a new empty `Graph` with a single "origin" node. - /// - /// The "origin" is the "parent-most" of all nodes. Its transform is always equal to - /// `Transform::default()`. - /// - /// Calling this is the same as calling `Graph::default()`. - pub fn new() -> Self { - Graph::default() - } - - /// The **node::Index** of the origin node. - pub fn origin(&self) -> node::Index { - self.origin - } - - /// Construct the graph with pre-allocated buffers for the given `nodes`, `edges` and - /// `vertices` capacities. - pub fn with_capacity(nodes: usize, edges: usize) -> Self { - let mut dag = Dag::with_capacity(nodes, edges); - let origin = dag.add_node(Node::Point); - Graph { dag, origin } - } - - /// The total number of **Node**s in the **Graph**. - pub fn node_count(&self) -> usize { - self.dag.node_count() - } - - /// The total number of **Edge**s in the **Graph**. - pub fn edge_count(&self) -> usize { - self.dag.edge_count() - } - - /// Borrow the node at the given **node::Index** if there is one. - pub fn node(&self, idx: node::Index) -> Option<&Node> { - self.dag.node_weight(idx) - } - - /// Determine the full **Transform** for the **Node**. - /// - /// Returns **None** if the node does not exist. - pub fn node_transform(&self, idx: node::Index) -> Option> { - // If there is no node for the index, return **None**. - if self.node(idx).is_none() { - return None; - } - - // Calculate the transform. - let mut transform = node::Transform::default(); - for (e, parent) in self.parents(idx).iter(self) { - let parent_transform = self - .node_transform(parent) - .expect("no node for yielded parent"); - let edge = &self[e]; - transform.apply_edge(&parent_transform, edge); - } - - Some(transform) - } - - /// Transform the given vertices with the given node's **Transform**. - /// - /// This method uses the **node_transform** method internally. - /// - /// Returns **None** if the node does not exist. - pub fn node_vertices( - &self, - idx: node::Index, - vertices: I, - ) -> Option> - where - I: IntoIterator, - I::Item: node::ApplyTransform, - { - self.node_transform(idx) - .map(|transform| transform.vertices(vertices.into_iter())) - } - - /// Transform the given triangles with the given node's **Transform**. - /// - /// This method uses the **node_transform** method internally. - /// - /// Returns **None** if the node does not exist. - pub fn node_triangles( - &self, - idx: node::Index, - triangles: I, - ) -> Option> - where - I: IntoIterator>, - V: geom::Vertex + node::ApplyTransform, - { - self.node_transform(idx) - .map(|transform| transform.triangles(triangles.into_iter())) - } - - /// Borrow the edge at the given **edge::Index** if there is one. - pub fn edge(&self, idx: edge::Index) -> Option<&Edge> { - self.dag.edge_weight(idx) - } - - /// The slice containing all nodes. - pub fn raw_nodes(&self) -> RawNodes { - self.dag.raw_nodes() - } - - /// The slice containing all edges. - pub fn raw_edges(&self) -> RawEdges { - self.dag.raw_edges() - } - - /// Removes all **Node**s, **Edge**s and vertices from the **Graph** and resets the origin node. - /// - /// This does not de-allocate any buffers and should retain capacity. To drop all inner - /// buffers, use `mem::replace` with a new empty **Graph**. - pub fn clear(&mut self) { - self.dag.clear(); - let origin = self.dag.add_node(Node::Point); - self.origin = origin; - } - - /// Return the parent and child nodes on either end of the **Edge** at the given index. - pub fn edge_endpoints(&self, idx: edge::Index) -> Option<(node::Index, node::Index)> { - self.dag.edge_endpoints(idx) - } - - /// A **Walker** type that recursively walks the **Graph** using the given `recursive_fn`. - /// - /// **Panics** If the given start index does not exist within the **Graph**. - pub fn recursive_walk(&self, start: node::Index, recursive_fn: F) -> RecursiveWalk - where - F: FnMut(&Self, node::Index) -> Option<(edge::Index, node::Index)>, - { - RecursiveWalk::new(start, recursive_fn) - } - - /// Borrow the inner `daggy::Dag` (directed acyclic graph) upon which `Graph` is built. - /// - /// Can be useful/necessary for utilising some of the `daggy::Walker` types. - pub fn dag(&self) -> &Dag { - &self.dag - } - - /// Add the given **Node** to the graph. - /// - /// The created node will be a child of the graph's origin node. - /// - /// Returns the index of the new node. - pub fn add_node(&mut self, node: Node) -> node::Index { - let origin = self.origin(); - let zero = S::zero(); - let (x, y, z) = (zero, zero, zero); - let edges = edge::displace(Vector3 { x, y, z }); - let (_es, n) = self.add_child(origin, edges.iter().cloned(), node); - n - } - - // Remove and return the **Edge** at the given index. - // - // Return `None` if it didn't exist. - fn remove_edge(&mut self, idx: edge::Index) -> Option> { - self.dag.remove_edge(idx) - } - - /// Set the given **Edge** within the graph. - /// - /// The added edge will be in the direction `a` -> `b` - /// - /// There may only ever be one **Edge** of the given variant between `a` -> `b`. - /// - /// Checks if the edge would create a cycle in the **Graph**. - /// - /// If adding the edge **would not** cause the graph to cycle, the edge will be added and its - /// `edge::Index` returned. - /// - /// If adding the edge **would** cause the graph to cycle, the edge will not be added and - /// instead a `WouldCycle` error with the given weight will be returned. - /// - /// **Panics** if either `a` or `b` do not exist within the **Graph**. - /// - /// **Panics** if the **Graph** is at the maximum number of nodes for its index type. - pub fn set_edge( - &mut self, - a: node::Index, - b: node::Index, - edge: Edge, - ) -> Result> { - // Check to see if the node already has some matching incoming edge. - // Keep it if it's the one we want. Otherwise, remove any incoming edge that matches the given - // edge kind but isn't coming from the node that we desire. - let mut parents = self.parents(b); - let mut already_set = None; - - while let Some((in_edge_idx, in_node_idx)) = parents.walk_next(self) { - if edge.kind == self[in_edge_idx].kind { - if in_node_idx == a { - self.dag[in_edge_idx].weight = edge.weight; - already_set = Some(in_edge_idx); - } else { - self.remove_edge(in_edge_idx); - } - // Note that we only need to check for *one* edge as there can only ever be one - // parent edge of any kind for each node. We know this, as this method is the only - // function used by a public method that adds edges. - break; - } - } - - // If we don't already have an incoming edge from the requested parent, add one. - match already_set { - Some(edge_idx) => Ok(edge_idx), - None => self.dag.add_edge(a, b, edge), - } - } - - /// Add the given node as a child to the given `parent` connected via the given edges. - /// - /// There may only ever be one **Edge** of the given variant between `a` -> `b`. - /// - /// **Panics** if: - /// - /// - `parent` does not exist within the **Graph**. - /// - `edges` does not contain at least one **Edge**. - /// - the **Graph** is at the maximum number of nodes for its index type. - pub fn add_child( - &mut self, - parent: node::Index, - edges: E, - node: Node, - ) -> (edge::Indices, node::Index) - where - E: IntoIterator>, - { - let n = self.dag.add_node(node); - let mut edges = edges.into_iter().peekable(); - match edges.next() { - None => panic!("`edges` must contain at least one edge"), - Some(first) => { - let edges = Some(first).into_iter().chain(edges).map(|e| (parent, n, e)); - let edge_indices = self - .dag - .add_edges(edges) - .expect("cannot create a cycle when adding a new child"); - (edge_indices, n) - } - } - } - - /// Add the given children to the given `parent` connected via the given edges for each child. - /// - /// Returns an iterator yielding the node and edge indices for each child that was added. - /// - /// There may only ever be one **Edge** of the given variant between `a` -> `b`. - /// - /// **Panics** if: - /// - /// - `parent` does not exist within the **Graph**. - /// - any of the child `edges` iterators do not contain at least one **Edge**. - /// - the **Graph** is at the maximum number of nodes for its index type. - pub fn add_children( - &mut self, - parent: node::Index, - children: C, - ) -> Vec<(edge::Indices, node::Index)> - where - C: IntoIterator)>, - E: IntoIterator>, - { - let mut children_indices = vec![]; - for (edges, node) in children { - let child_indices = self.add_child(parent, edges, node); - children_indices.push(child_indices); - } - children_indices - } - - /// Produce a walker yielding all vertices from all nodes within the graph in order of - /// discovery within a depth-first-search. - pub fn walk_vertices<'a, F, I>( - &self, - dfs: &'a mut node::Dfs, - vertices_fn: F, - ) -> WalkVertices<'a, F, I, S> - where - F: Fn(&node::Index) -> I, - I: IntoIterator, - I::Item: node::ApplyTransform, - { - let node = None; - WalkVertices { - dfs, - vertices_fn, - node, - } - } - - /// Produce a walker yielding all vertices from all nodes within the graph in order of - /// discovery within a depth-first-search. - pub fn walk_triangles<'a, F, I, V>( - &self, - dfs: &'a mut node::Dfs, - triangles_fn: F, - ) -> WalkTriangles<'a, F, I, V, S> - where - F: Fn(&node::Index) -> I, - I: IntoIterator>, - V: geom::Vertex + node::ApplyTransform, - { - let node = None; - WalkTriangles { - dfs, - triangles_fn, - node, - } - } - - /// Produce an iterator yielding all vertices from all nodes within the graph in order of - /// discovery within a depth-first-search. - pub fn vertices<'a, 'b, F, I>( - &'a self, - dfs: &'b mut node::Dfs, - vertices_fn: F, - ) -> Vertices<'a, 'b, F, I, S> - where - F: Fn(&node::Index) -> I, - I: IntoIterator, - I::Item: node::ApplyTransform, - { - let walker = self.walk_vertices(dfs, vertices_fn); - let graph = self; - Vertices { graph, walker } - } - - /// Produce an iterator yielding all triangles from all nodes within the graph in order of - /// discovery within a depth-first-search. - pub fn triangles<'a, 'b, F, I, V>( - &'a self, - dfs: &'b mut node::Dfs, - triangles_fn: F, - ) -> Triangles<'a, 'b, F, I, V, S> - where - F: Fn(&node::Index) -> I, - I: IntoIterator>, - V: geom::Vertex + node::ApplyTransform, - { - let walker = self.walk_triangles(dfs, triangles_fn); - let graph = self; - Triangles { graph, walker } - } - - /// The `Cuboid` that bounds all nodes within the geometry graph. - /// - /// Returns `None` if the graph contains no vertices. - /// - /// 1. Iterates over all nodes. - /// 2. Expands a cuboid to the max bounds of each node. - /// 3. Returns the resulting cuboid. - pub fn bounding_cuboid( - &self, - dfs: &mut node::Dfs, - vertices_fn: F, - ) -> Option> - where - F: Fn(&node::Index) -> I, - I: IntoIterator>, - { - let vertices = self.vertices(dfs, vertices_fn); - geom::bounding_cuboid(vertices) - } - - //--------------- - // PARENT METHODS - //--------------- - - /// A **Walker** type that may be used to step through the parents of the given child node. - pub fn parents(&self, child: node::Index) -> Parents { - let parents = self.dag.parents(child); - Parents { parents } - } - - /// If the **Node** at the given index has some parent along an **Edge** of the given variant, - /// return an index to it. - pub fn edge_parent(&self, idx: node::Index, edge: edge::Kind) -> Option { - self.parents(idx) - .iter(self) - .find(|&(e, _)| self[e].kind == edge) - .map(|(_, n)| n) - } - - /// Return the index of the parent along the given node's **Position** **Edge**. - pub fn position_parent(&self, idx: node::Index, axis: edge::Axis) -> Option { - let kind = edge::Kind::new(axis, edge::Relative::Position); - self.edge_parent(idx, kind) - } - - /// Return the index of the parent along the given node's **Position** **Edge**. - pub fn x_position_parent(&self, idx: node::Index) -> Option { - self.position_parent(idx, edge::Axis::X) - } - - /// Return the index of the parent along the given node's **Position** **Edge**. - pub fn y_position_parent(&self, idx: node::Index) -> Option { - self.position_parent(idx, edge::Axis::Y) - } - - /// Return the index of the parent along the given node's **Position** **Edge**. - pub fn z_position_parent(&self, idx: node::Index) -> Option { - self.position_parent(idx, edge::Axis::Z) - } - - /// Produce an **Iterator** yielding the **Position** parents to the given node. - /// - /// Parents are always yielded in order of axis, e.g. **X**, **Y** then **Z**. - pub fn position_parents(&self, idx: node::Index) -> PositionParents { - self.x_position_parent(idx) - .into_iter() - .chain(self.y_position_parent(idx)) - .chain(self.z_position_parent(idx)) - } - - /// Return the index of the parent along the given node's **Orientation** **Edge**. - pub fn orientation_parent(&self, idx: node::Index, axis: edge::Axis) -> Option { - let kind = edge::Kind::new(axis, edge::Relative::Orientation); - self.edge_parent(idx, kind) - } - - /// Return the index of the parent along the given node's **Orientation** **Edge**. - pub fn x_orientation_parent(&self, idx: node::Index) -> Option { - self.orientation_parent(idx, edge::Axis::X) - } - - /// Return the index of the parent along the given node's **Orientation** **Edge**. - pub fn y_orientation_parent(&self, idx: node::Index) -> Option { - self.orientation_parent(idx, edge::Axis::Y) - } - - /// Return the index of the parent along the given node's **Orientation** **Edge**. - pub fn z_orientation_parent(&self, idx: node::Index) -> Option { - self.orientation_parent(idx, edge::Axis::Z) - } - - /// Produce an **Iterator** yielding the **Orientation** parents to the given node. - /// - /// Parents are always yielded in order of axis, e.g. **X**, **Y** then **Z**. - pub fn orientation_parents(&self, idx: node::Index) -> OrientationParents { - self.x_orientation_parent(idx) - .into_iter() - .chain(self.y_orientation_parent(idx)) - .chain(self.z_orientation_parent(idx)) - } - - /// Return the index of the parent along the given node's **Scale** **Edge**. - pub fn scale_parent(&self, idx: node::Index, axis: edge::Axis) -> Option { - let kind = edge::Kind::new(axis, edge::Relative::Scale); - self.edge_parent(idx, kind) - } - - /// Return the index of the parent along the given node's **Scale** **Edge**. - pub fn x_scale_parent(&self, idx: node::Index) -> Option { - self.scale_parent(idx, edge::Axis::X) - } - - /// Return the index of the parent along the given node's **Scale** **Edge**. - pub fn y_scale_parent(&self, idx: node::Index) -> Option { - self.scale_parent(idx, edge::Axis::Y) - } - - /// Return the index of the parent along the given node's **Scale** **Edge**. - pub fn z_scale_parent(&self, idx: node::Index) -> Option { - self.scale_parent(idx, edge::Axis::Z) - } - - /// Produce an **Iterator** yielding the **Scale** parents to the given node. - /// - /// Parents are always yielded in order of axis, e.g. **X**, **Y** then **Z**. - pub fn scale_parents(&self, idx: node::Index) -> ScaleParents { - self.x_scale_parent(idx) - .into_iter() - .chain(self.y_scale_parent(idx)) - .chain(self.z_scale_parent(idx)) - } - - /// Produce an **Iterator** yielding the **X** parents to the given node. - /// - /// Parents are always yielded in order of **Position**, **Orientation** and **Scale**. - pub fn x_parents(&self, idx: node::Index) -> XParents { - self.x_position_parent(idx) - .into_iter() - .chain(self.x_orientation_parent(idx)) - .chain(self.x_scale_parent(idx)) - } - - /// Produce an **Iterator** yielding the **Y** parents to the given node. - /// - /// Parents are always yielded in order of **Position**, **Orientation** and **Scale**. - pub fn y_parents(&self, idx: node::Index) -> YParents { - self.y_position_parent(idx) - .into_iter() - .chain(self.y_orientation_parent(idx)) - .chain(self.y_scale_parent(idx)) - } - - /// Produce an **Iterator** yielding the **Z** parents to the given node. - /// - /// Parents are always yielded in order of **Position**, **Orientation** and **Scale**. - pub fn z_parents(&self, idx: node::Index) -> ZParents { - self.z_position_parent(idx) - .into_iter() - .chain(self.z_orientation_parent(idx)) - .chain(self.z_scale_parent(idx)) - } - - //----------------- - // CHILDREN METHODS - //----------------- - - /// A **Walker** type that may be used to step through the children of the given parent node. - pub fn children(&self, parent: node::Index) -> Children { - let children = self.dag.children(parent); - Children { children } - } - - // TODO: Add `x_position_children`, `position_children`, etc methods. -} - -impl Default for Graph -where - S: BaseFloat, -{ - fn default() -> Self { - let mut dag = Dag::new(); - let origin = dag.add_node(Node::Point); - Graph { dag, origin } - } -} - -impl GraphBase for Graph -where - S: BaseFloat, -{ - type NodeId = node::Index; - type EdgeId = edge::Index; -} - -impl Visitable for Graph -where - S: BaseFloat, -{ - type Map = as Visitable>::Map; - fn visit_map(&self) -> Self::Map { - self.dag.visit_map() - } - fn reset_map(&self, map: &mut Self::Map) { - self.dag.reset_map(map) - } -} - -impl<'a, S> IntoNeighbors for &'a Graph -where - S: BaseFloat, -{ - type Neighbors = <&'a Dag as IntoNeighbors>::Neighbors; - fn neighbors(self, n: Self::NodeId) -> Self::Neighbors { - self.dag.neighbors(n) - } -} - -impl ops::Index for Graph -where - S: BaseFloat, -{ - type Output = Node; - fn index<'a>(&'a self, id: node::Index) -> &'a Self::Output { - self.node(id).unwrap() - } -} - -impl ops::Index for Graph -where - S: BaseFloat, -{ - type Output = Edge; - fn index<'a>(&'a self, idx: edge::Index) -> &'a Self::Output { - self.edge(idx).unwrap() - } -} - -impl<'a, S> Walker<&'a Graph> for Children -where - S: BaseFloat, -{ - type Item = (edge::Index, node::Index); - #[inline] - fn walk_next(&mut self, graph: &'a Graph) -> Option { - self.children.walk_next(&graph.dag) - } -} - -impl<'a, S> Walker<&'a Graph> for Parents -where - S: BaseFloat, -{ - type Item = (edge::Index, node::Index); - #[inline] - fn walk_next(&mut self, graph: &'a Graph) -> Option { - self.parents.walk_next(&graph.dag) - } -} diff --git a/nannou/src/geom/graph/node.rs b/nannou/src/geom/graph/node.rs deleted file mode 100644 index ebbd6a8f8..000000000 --- a/nannou/src/geom/graph/node.rs +++ /dev/null @@ -1,465 +0,0 @@ -//! Items related to the nodes of a geometry graph. - -use crate::geom; -use crate::geom::graph::Edge; -use crate::geom::{scalar, Graph, Point3, Vector3}; -use crate::math::{self, BaseFloat, Basis3, Euler, Rad, Rotation}; -use daggy::petgraph::visit::{self, Visitable}; -use daggy::{self, Walker}; -use std::collections::HashMap; -use std::marker::PhantomData; -use std::ops; - -/// Unique index for a **Node** within a **Graph**. -pub type Index = daggy::NodeIndex; - -/// The **Node** type used within the **Graph**. -#[derive(Clone, Debug)] -pub enum Node -where - S: BaseFloat, -{ - /// A point has no vertices other than that yielded at the node's position. - /// - /// Useful for acting as an invisible "reference" node for controlling other children nodes. - /// - /// Also used to represent the graph's "origin" node. - Point, - /// A nested Graph. - Graph { graph: super::Graph, dfs: Dfs }, -} - -/// An iterator yielding all vertices for a node transformed by some given transform. -#[derive(Clone, Debug)] -pub struct TransformedVertices -where - S: BaseFloat, -{ - transform: PreparedTransform, - vertices: I, -} - -/// An iterator yielding all vertices for a node transformed by some given transform. -#[derive(Clone, Debug)] -pub struct TransformedTriangles -where - S: BaseFloat, -{ - transform: PreparedTransform, - triangles: I, - _vertex: PhantomData, -} - -/// A node's resulting rotation, displacement and scale relative to the graph's origin. -/// -/// A transform is calculated and applied to a node's vertices in the following order: -/// -/// 1. **scale**: `1.0 * parent_scale * edge_scale` -/// 2. **rotation**: `0.0 + parent_position + edge_displacement` -/// 3. **displacement**: 0.0 + parent_orientation + edge_orientation` -#[derive(Clone, Debug, PartialEq)] -pub struct Transform -where - S: BaseFloat, -{ - /// A scaling amount along each axis. - /// - /// The scaling amount is multiplied onto each vertex of the node. - pub scale: Vector3, - /// A rotation amount along each axis, describing a relative orientation. - /// - /// Rotates all vertices around the node origin when applied. - pub rot: Euler>, - /// A displacement amount along each axis. - /// - /// This vector is added onto the position of each vertex of the node. - pub disp: Vector3, -} - -/// A node's resulting rotation, displacement and scale relative to the graph's origin. -/// -/// The same as **Transfrom** but the euler has been converted to a matrix for more efficient -/// application. -#[derive(Clone, Debug, PartialEq)] -pub struct PreparedTransform { - /// A scaling amount along each axis. - /// - /// The scaling amount is multiplied onto each vertex of the node. - pub scale: Vector3, - /// A rotation amount along each axis, describing a relative orientation. - /// - /// Rotates all vertices around the node origin when applied. - pub rot: Basis3, - /// A displacement amount along each axis. - /// - /// This vector is added onto the position of each vertex of the node. - pub disp: Vector3, -} - -/// Mappings from node indices to their respective transform within the graph. -/// -/// This is calculated via the `Graph::update_transform_map` method. -#[derive(Clone, Debug, PartialEq)] -pub struct TransformMap -where - S: BaseFloat, -{ - map: HashMap>, -} - -/// A depth-first-search over nodes in the graph, yielding each node's unique index alongside its -/// absolute transform. -/// -/// The traversal may start at any given node. -/// -/// **Note:** The algorithm may not behave correctly if nodes are removed during iteration. It may -/// not necessarily visit added nodes or edges. -#[derive(Clone, Debug)] -pub struct Dfs -where - S: BaseFloat, -{ - dfs: visit::Dfs as Visitable>::Map>, - visited: TransformMap, -} - -impl Dfs -where - S: BaseFloat, -{ - /// Create a new **Dfs** starting from the graph's origin. - pub fn new(graph: &Graph) -> Self { - Self::start_from(graph, graph.origin()) - } - - /// Create a new **Dfs** starting from the node at the given node. - pub fn start_from(graph: &Graph, start: Index) -> Self { - let dfs = visit::Dfs::new(graph, start); - let visited = TransformMap::default(); - Dfs { dfs, visited } - } - - /// Clears the visit state. - pub fn reset(&mut self, graph: &Graph) { - self.dfs.reset(graph); - self.dfs.move_to(graph.origin()); - } - - /// Keep the discovered map but clear the visit stack and restart the dfs from the given node. - pub fn move_to(&mut self, start: Index) { - self.dfs.move_to(start); - } - - /// Return the tranform for the next node in the DFS. - /// - /// Returns `None` if the traversal is finished. - pub fn next_transform(&mut self, graph: &Graph) -> Option<(Index, Transform)> { - let n = match self.dfs.next(graph) { - None => return None, - Some(n) => n, - }; - let mut transform = Transform::default(); - for (e, parent) in graph.parents(n).iter(graph) { - let parent_transform = &self.visited[&parent]; - let edge = &graph[e]; - transform.apply_edge(parent_transform, edge); - } - self.visited.map.insert(n, transform.clone()); - Some((n, transform)) - } - - /// Return the vertices for the next node in the DFS. - /// - /// Uses `Dfs::next_transform` internally. - /// - /// Returns `None` if the traversal is finished. - pub fn next_vertices( - &mut self, - graph: &Graph, - vertices_fn: F, - ) -> Option<(Index, TransformedVertices)> - where - F: FnOnce(&Index) -> I, - I: IntoIterator, - I::Item: ApplyTransform, - { - self.next_transform(graph).map(|(n, transform)| { - let vertices = vertices_fn(&n); - let vertices = vertices.into_iter(); - (n, transform.vertices(vertices)) - }) - } - - /// Return the triangles for the next node in the DFS. - /// - /// Uses `Dfs::next_transform` and `Node::triangles` internally. - /// - /// Returns `None` if the traversal is finished. - pub fn next_triangles( - &mut self, - graph: &Graph, - triangles_fn: F, - ) -> Option<(Index, TransformedTriangles)> - where - F: FnOnce(&Index) -> I, - I: IntoIterator>, - V: geom::Vertex + ApplyTransform, - { - self.next_transform(graph).map(|(n, transform)| { - let triangles = triangles_fn(&n); - let triangles = triangles.into_iter(); - (n, transform.triangles(triangles)) - }) - } -} - -impl<'a, S> Walker<&'a Graph> for Dfs -where - S: BaseFloat, -{ - type Item = (Index, Transform); - fn walk_next(&mut self, graph: &'a Graph) -> Option { - self.next_transform(graph) - } -} - -impl Default for TransformMap -where - S: BaseFloat, -{ - fn default() -> Self { - TransformMap { - map: Default::default(), - } - } -} - -impl ops::Deref for TransformMap -where - S: BaseFloat, -{ - type Target = HashMap>; - fn deref(&self) -> &Self::Target { - &self.map - } -} - -impl Into>> for TransformMap -where - S: BaseFloat, -{ - fn into(self) -> HashMap> { - self.map - } -} - -impl Transform -where - S: BaseFloat, -{ - /// Apply the given parent `Edge` to this transform. - pub fn apply_edge(&mut self, parent: &Self, edge: &Edge) { - use crate::geom::graph::edge::{Axis, Relative}; - match (edge.kind.relative, edge.kind.axis) { - (Relative::Position, Axis::X) => self.disp.x += parent.disp.x + edge.weight, - (Relative::Position, Axis::Y) => self.disp.y += parent.disp.y + edge.weight, - (Relative::Position, Axis::Z) => self.disp.z += parent.disp.z + edge.weight, - (Relative::Orientation, Axis::X) => self.rot.x += parent.rot.x - Rad(edge.weight), - (Relative::Orientation, Axis::Y) => self.rot.y += parent.rot.y - Rad(edge.weight), - (Relative::Orientation, Axis::Z) => self.rot.z += parent.rot.z - Rad(edge.weight), - (Relative::Scale, Axis::X) => self.scale.x *= parent.scale.x * edge.weight, - (Relative::Scale, Axis::Y) => self.scale.y *= parent.scale.y * edge.weight, - (Relative::Scale, Axis::Z) => self.scale.z *= parent.scale.z * edge.weight, - } - } - - /// Prepare this transform for application. - pub fn prepare(self) -> PreparedTransform { - let Transform { disp, rot, scale } = self; - let rot = Basis3::from(rot); - PreparedTransform { disp, rot, scale } - } - - /// Transform the given vertices. - pub fn vertices(self, vertices: I) -> TransformedVertices - where - I: IntoIterator, - I::Item: ApplyTransform, - { - let transform = self.prepare(); - let vertices = vertices.into_iter(); - TransformedVertices { - transform, - vertices, - } - } - - /// Transform the given vertices. - pub fn triangles(self, triangles: I) -> TransformedTriangles - where - I: IntoIterator>, - V: geom::Vertex + ApplyTransform, - { - let transform = self.prepare(); - let triangles = triangles.into_iter(); - let _vertex = PhantomData; - TransformedTriangles { - transform, - triangles, - _vertex, - } - } -} - -impl Default for Transform -where - S: BaseFloat, -{ - fn default() -> Self { - let zero = S::zero(); - let one = S::one(); - let scale = Vector3 { - x: one, - y: one, - z: one, - }; - let rot = Euler { - x: Rad(zero), - y: Rad(zero), - z: Rad(zero), - }; - let disp = Vector3 { - x: zero, - y: zero, - z: zero, - }; - Transform { scale, rot, disp } - } -} - -impl math::Transform> for Transform -where - S: BaseFloat, -{ - fn one() -> Self { - let one = S::one(); - let (x, y, z) = (one, one, one); - Transform { - scale: Vector3 { x, y, z }, - rot: Euler { - x: Rad(x), - y: Rad(y), - z: Rad(z), - }, - disp: Vector3 { x, y, z }, - } - } - - fn look_at(_eye: Point3, _center: Point3, _up: Vector3) -> Self { - unimplemented!(); - } - - fn transform_vector(&self, _vec: Vector3) -> Vector3 { - unimplemented!(); - } - - fn inverse_transform_vector(&self, _vec: Vector3) -> Option> { - unimplemented!(); - } - - fn transform_point(&self, _point: Point3) -> Point3 { - unimplemented!(); - } - - fn concat(&self, _other: &Self) -> Self { - unimplemented!(); - } - - fn inverse_transform(&self) -> Option { - unimplemented!(); - } -} - -/// Apply the given transform to the given 3D point. -pub fn transform_point(transform: &PreparedTransform, mut point: Point3) -> Point3 -where - S: BaseFloat, -{ - // Scale the point relative to the node origin. - point.x *= transform.scale.x; - point.y *= transform.scale.y; - point.z *= transform.scale.z; - // Rotate the point around the node origin. - point = transform.rot.rotate_point(point.into()).into(); - // Displace the point from the node origin. - point += transform.disp; - point -} - -/// Vertex types which may apply a transform and produce a resulting transform. -pub trait ApplyTransform -where - S: BaseFloat, -{ - /// Apply the given transform and return the result. - fn apply_transform(self, transform: &PreparedTransform) -> Self; -} - -impl ApplyTransform for Point3 -where - S: BaseFloat, -{ - fn apply_transform(self, transform: &PreparedTransform) -> Self { - transform_point(transform, self) - } -} - -impl Iterator for TransformedVertices -where - I: Iterator, - I::Item: ApplyTransform, - S: BaseFloat, -{ - type Item = I::Item; - fn next(&mut self) -> Option { - self.vertices - .next() - .map(|vertex| vertex.apply_transform(&self.transform)) - } -} - -impl Iterator for TransformedTriangles -where - I: Iterator>, - V: geom::Vertex + ApplyTransform, - S: BaseFloat, -{ - type Item = geom::Tri; - fn next(&mut self) -> Option { - self.triangles - .next() - .map(|tri| tri.map_vertices(|vertex| vertex.apply_transform(&self.transform))) - } -} - -impl ExactSizeIterator for TransformedVertices -where - I: ExactSizeIterator, - I::Item: ApplyTransform, - S: BaseFloat, -{ - fn len(&self) -> usize { - self.vertices.len() - } -} - -impl ExactSizeIterator for TransformedTriangles -where - I: Iterator> + ExactSizeIterator, - V: geom::Vertex + ApplyTransform, - S: BaseFloat, -{ - fn len(&self) -> usize { - self.triangles.len() - } -} diff --git a/nannou/src/geom/mod.rs b/nannou/src/geom/mod.rs index aaa05fdf3..04632824c 100644 --- a/nannou/src/geom/mod.rs +++ b/nannou/src/geom/mod.rs @@ -9,100 +9,7 @@ //! - Functions for determining the bounding rectangle or cuboid. //! - A function for finding the centroid. -use crate::math::num_traits::cast; -use crate::math::{BaseFloat, EuclideanSpace}; -use std::ops; - -pub mod cuboid; -pub mod ellipse; -pub mod graph; pub mod path; -pub mod point; -pub mod polygon; -pub mod quad; -pub mod range; -pub mod rect; -pub mod scalar; -pub mod tri; -pub mod vector; -pub mod vertex; -pub use self::cuboid::Cuboid; -pub use self::ellipse::Ellipse; -pub use self::graph::Graph; pub use self::path::{path, Path}; -pub use self::point::{pt2, pt3, pt4, Point2, Point3, Point4}; -pub use self::polygon::Polygon; -pub use self::quad::Quad; -pub use self::range::{Align, Edge, Range}; -pub use self::rect::{Corner, Padding, Rect}; -pub use self::tri::Tri; -pub use self::vector::{vec2, vec3, vec4, Vector2, Vector3, Vector4}; -pub use self::vertex::{Vertex, Vertex2d, Vertex3d}; - -// General geometry utility functions - -/// The `Rect` that bounds the given sequence of vertices. -/// -/// Returns `None` if the given iterator is empty. -pub fn bounding_rect(vertices: I) -> Option::Scalar>> -where - I: IntoIterator, - I::Item: Vertex2d, -{ - let mut vertices = vertices.into_iter(); - vertices.next().map(|first| { - let Point2 { x, y } = first.point2(); - let bounds = Rect { - x: Range::new(x, x), - y: Range::new(y, y), - }; - vertices.fold(bounds, |b, v| { - let Point2 { x, y } = v.point2(); - let point = Point2 { x, y }; - b.stretch_to_point(point) - }) - }) -} - -/// The `Cuboid` that bounds the given sequence of vertices. -/// -/// Returns `None` if the given iterator is empty. -pub fn bounding_cuboid(vertices: I) -> Option::Scalar>> -where - I: IntoIterator, - I::Item: Vertex3d, -{ - let mut vertices = vertices.into_iter(); - vertices.next().map(|first| { - let Point3 { x, y, z } = first.point3(); - let bounds = Cuboid { - x: Range::new(x, x), - y: Range::new(y, y), - z: Range::new(z, z), - }; - vertices.fold(bounds, |b, v| { - let Point3 { x, y, z } = v.point3(); - let point = Point3 { x, y, z }; - b.stretch_to_point(point) - }) - }) -} - -/// The `centroid` (average position) of all vertices in the given iterator. -/// -/// Returns `None` if the given iterator contains no vertices. -pub fn centroid(vertices: I) -> Option -where - I: IntoIterator, - I::Item: Vertex + EuclideanSpace, - ::Diff: ops::Div::Diff>, - S: BaseFloat, -{ - let mut vertices = vertices.into_iter(); - vertices.next().map(|first| { - let init = (1, first.to_vec()); - let (len, total) = vertices.fold(init, |(i, acc), p| (i + 1, acc + p.to_vec())); - EuclideanSpace::from_vec(total / cast(len).unwrap()) - }) -} +pub use nannou_core::geom::*; diff --git a/nannou/src/geom/path.rs b/nannou/src/geom/path.rs index 80661c6a6..c4ced61b3 100644 --- a/nannou/src/geom/path.rs +++ b/nannou/src/geom/path.rs @@ -4,7 +4,8 @@ //! offerred by `lyon` in a way that interoperates a little more fluidly and consistently with the //! rest of nannou's API. -use crate::geom::{Point2, Vector2}; +use crate::geom::Point2; +use crate::glam::Vec2; /// A wrapper around a 2D lyon path exposing a nannou-friendly API. pub struct Path { @@ -97,13 +98,13 @@ impl Builder { /// /// If the current sub-path contains edges, this ends the sub-path without closing it. pub fn move_to(mut self, to: Point2) -> Self { - self.builder.move_to(to.into()); + self.builder.move_to(to.to_array().into()); self } /// Adds a line segment to the current sub-path and sets the current position. pub fn line_to(mut self, to: Point2) -> Self { - self.builder.line_to(to.into()); + self.builder.line_to(to.to_array().into()); self } @@ -116,14 +117,18 @@ impl Builder { /// Add a quadratic bezier curve to the path. pub fn quadratic_bezier_to(mut self, ctrl: Point2, to: Point2) -> Self { - self.builder.quadratic_bezier_to(ctrl.into(), to.into()); + self.builder + .quadratic_bezier_to(ctrl.to_array().into(), to.to_array().into()); self } /// Add a cubic bezier curve to the path. pub fn cubic_bezier_to(mut self, ctrl1: Point2, ctrl2: Point2, to: Point2) -> Self { - self.builder - .cubic_bezier_to(ctrl1.into(), ctrl2.into(), to.into()); + self.builder.cubic_bezier_to( + ctrl1.to_array().into(), + ctrl2.to_array().into(), + to.to_array().into(), + ); self } @@ -131,13 +136,13 @@ impl Builder { pub fn arc( mut self, center: Point2, - radii: Vector2, + radii: Vec2, sweep_angle_radians: f32, x_rotation_radians: f32, ) -> Self { self.builder.arc( - center.into(), - radii.into(), + center.to_array().into(), + radii.to_array().into(), lyon::math::Angle::radians(sweep_angle_radians), lyon::math::Angle::radians(x_rotation_radians), ); @@ -152,7 +157,8 @@ impl Builder { /// Returns the current position of the head of the path. pub fn position(&self) -> Point2 { - self.builder.current_position().into() + let p = self.builder.current_position(); + [p.x, p.y].into() } /// Build the path and return it. diff --git a/nannou/src/geom/scalar.rs b/nannou/src/geom/scalar.rs deleted file mode 100644 index 044e82e8f..000000000 --- a/nannou/src/geom/scalar.rs +++ /dev/null @@ -1,2 +0,0 @@ -/// The default scalar type used for geometry throughout Nannou. -pub type Default = f32; diff --git a/nannou/src/geom/vector.rs b/nannou/src/geom/vector.rs deleted file mode 100644 index 9eda85d43..000000000 --- a/nannou/src/geom/vector.rs +++ /dev/null @@ -1,1614 +0,0 @@ -//! Implementation of the **Vector** types. -//! -//! **Note:** Much of the code in this module is inspired by or copied directly from the `cgmath` -//! crate. Originally we used the `cgmath` types directly, however we decided to switch to our own -//! implementations in order to gain some flexibility. - -use crate::geom::scalar; -use crate::math::{self, BaseFloat, Bounded, InnerSpace, NumCast, One, Zero}; -use crate::rand::distributions::{Distribution, Standard}; -use crate::rand::Rng; -use crate::serde_derive::{Deserialize, Serialize}; -use std::{iter, ops}; - -/// A 2-dimensional vector. -#[repr(C)] -#[derive(Default, Debug, PartialEq, Eq, Copy, Clone, Hash, Serialize, Deserialize)] -pub struct Vector2 { - pub x: S, - pub y: S, -} - -/// A 3-dimensional vector. -#[repr(C)] -#[derive(Default, Debug, PartialEq, Eq, Copy, Clone, Hash, Serialize, Deserialize)] -pub struct Vector3 { - pub x: S, - pub y: S, - pub z: S, -} - -/// A 4-dimensional vector. -#[repr(C)] -#[derive(Default, Debug, PartialEq, Eq, Copy, Clone, Hash, Serialize, Deserialize)] -pub struct Vector4 { - pub x: S, - pub y: S, - pub z: S, - pub w: S, -} - -// Generates index operators for a compound type -// -// Code originally from `cgmath` macros module. -macro_rules! impl_index_operators { - ($VectorN:ident < $S:ident > , $n:expr, $Output:ty, $I:ty) => { - impl<$S> ::std::ops::Index<$I> for $VectorN<$S> { - type Output = $Output; - - #[inline] - fn index<'a>(&'a self, i: $I) -> &'a $Output { - let v: &[$S; $n] = self.as_ref(); - &v[i] - } - } - - impl<$S> ::std::ops::IndexMut<$I> for $VectorN<$S> { - #[inline] - fn index_mut<'a>(&'a mut self, i: $I) -> &'a mut $Output { - let v: &mut [$S; $n] = self.as_mut(); - &mut v[i] - } - } - }; -} - -// Utility macro for generating associated functions for the vectors -macro_rules! impl_vector { - ($VectorN:ident { $($field:ident),+ }, $n:expr, $constructor:ident) => { - impl $VectorN { - /// Construct a new vector, using the provided values. - #[inline] - pub fn new($($field: S),+) -> $VectorN { - $VectorN { $($field: $field),+ } - } - - /// Construct a vector using the given value for each field. - #[inline] - pub fn from_value(scalar: S) -> $VectorN - where - S: Clone, - { - $VectorN { $($field: scalar.clone()),+ } - } - - /// The number of dimensions in the vector. - #[inline] - pub fn len(&self) -> usize { - $n - } - - /// Perform the given operation on each field in the vector, returning a new vector - /// constructed from the operations. - #[inline] - pub fn map(self, mut f: F) -> $VectorN - where - F: FnMut(S) -> U, - { - $VectorN { $($field: f(self.$field)),+ } - } - - /// Perform the given operation on each each field on both vectors, returning a new - /// vector constructed from the operations. - #[inline] - pub fn zip_map(self, other: $VectorN, mut f: F) -> $VectorN - where - F: FnMut(S, T) -> U, - { - $VectorN { $($field: f(self.$field, other.$field)),+ } - } - - /// Test whether or not the vector is infinite. - pub fn is_finite(&self) -> bool - where - S: BaseFloat, - { - $(self.$field.is_finite())&&+ - } - - /// Component-wise casting to another type. - #[inline] - pub fn cast(&self) -> Option<$VectorN> - where - S: NumCast + Clone, - T: NumCast, - { - $( - let $field = match NumCast::from(self.$field.clone()) { - Some(field) => field, - None => return None - }; - )+ - Some($VectorN { $($field),+ }) - } - - /// A zeroed vector. - #[inline] - pub fn zero() -> $VectorN - where - S: Zero, - { - $VectorN { $($field: S::zero()),+ } - } - - /// Whether or not the vector is zeroed. - #[inline] - pub fn is_zero(&self) -> bool - where - S: PartialEq + Zero, - { - *self == $VectorN::zero() - } - - /// A vector with `1` for each element. - #[inline] - pub fn one() -> $VectorN - where - S: One, - { - $VectorN { $($field: S::one()),+ } - } - - /// Whether or not each element in the vector is equal to `1`. - #[inline] - pub fn is_one(&self) -> bool - where - S: PartialEq + One, - { - *self == $VectorN::one() - } - - /// Tests whether or not any of the vector's elements is `NaN`. - #[inline] - pub fn is_nan(&self) -> bool - where - S: BaseFloat, - { - $(self.$field.is_nan())||+ - } - - /// Sum the fields of the vector. - #[inline] - pub fn sum(self) -> S - where - S: ops::Add + Copy, - { - math::Array::sum(self) - } - - /// The product of the fields of the vector. - #[inline] - pub fn product(self) -> S - where - S: ops::Mul + Copy, - { - math::Array::product(self) - } - - /// Return a vector whose magnitude is limited to the given value. - #[inline] - pub fn limit_magnitude(self, limit: S) -> Self - where - S: BaseFloat, - { - limit_magnitude(self, limit) - } - - /// Return a vector with the given magnitude. - #[inline] - pub fn with_magnitude(self, magnitude: S) -> Self - where - S: BaseFloat, - { - self.normalize() * magnitude - } - - /// Return a normalized vector. - /// - /// If `self` `is_zero`, this returns `self`. - pub fn normalize(self) -> Self - where - S: BaseFloat, - { - if self.is_zero() { - self - } else { - InnerSpace::normalize(self) - } - } - - /// The magnitude of the vector. - /// - /// The magnitude represents the distance from the origin to the point described by the - /// vector. - /// - /// Note: This is equivalent to `.magnitude2().sqrt()`. As a result, it can be quite a - /// bit more computationally efficient to use `.magnitude2()` directly when feasible. - /// - /// ## Example - /// - /// ``` - /// # use nannou::prelude::*; - /// # fn main() { - /// let a = vec2(5.0, 0.0); - /// let b = vec2(0.0, 5.0); - /// assert_eq!(a.magnitude(), 5.0); - /// assert_eq!(b.magnitude(), 5.0); - /// # } - /// - /// ``` - pub fn magnitude(self) -> S - where - S: BaseFloat, - { - InnerSpace::magnitude(self) - } - - /// The square of the magnitude. - /// - /// See the `magnitude` docs for details. - pub fn magnitude2(self) -> S - where - S: BaseFloat, - { - InnerSpace::magnitude2(self) - } - - /// The dot product of self and the given vector. - #[inline] - pub fn dot(self, other: $VectorN) -> S - where - S: BaseFloat, - { - InnerSpace::dot(self, other) - } - } - - impl iter::Sum<$VectorN> for $VectorN - where - S: Zero + ops::Add, - { - #[inline] - fn sum(iter: I) -> $VectorN - where - I: Iterator>, - { - iter.fold($VectorN::zero(), ops::Add::add) - } - } - - impl<'a, S: 'a> iter::Sum<&'a $VectorN> for $VectorN - where - S: 'a + Clone + Zero + ops::Add, - { - #[inline] - fn sum(iter: I) -> $VectorN - where - I: Iterator>, - { - iter.fold($VectorN::zero(), |acc, s| acc + s.clone())// ops::Add::add) - } - } - - // std::ops - vector vector - - impl ops::Neg for $VectorN - where - S: ops::Neg, - { - type Output = $VectorN; - - #[inline] - fn neg(self) -> $VectorN { - self.map(|s| -s) - } - } - - impl ops::Add for $VectorN - where - S: ops::Add, - { - type Output = $VectorN; - - #[inline] - fn add(self, other: Self) -> Self { - self.zip_map(other, |a, b| a + b) - } - } - - impl ops::Sub for $VectorN - where - S: ops::Sub, - { - type Output = $VectorN; - - #[inline] - fn sub(self, other: Self) -> Self { - self.zip_map(other, |a, b| a - b) - } - } - - impl ops::Mul for $VectorN - where - S: ops::Mul, - { - type Output = $VectorN; - - #[inline] - fn mul(self, other: Self) -> Self { - self.zip_map(other, |a, b| a * b) - } - } - - impl ops::Div for $VectorN - where - S: ops::Div, - { - type Output = $VectorN; - - #[inline] - fn div(self, other: Self) -> Self { - self.zip_map(other, |a, b| a / b) - } - } - - impl ops::Rem for $VectorN - where - S: ops::Rem, - { - type Output = $VectorN; - - #[inline] - fn rem(self, other: Self) -> Self { - self.zip_map(other, |a, b| a % b) - } - } - - impl ops::AddAssign for $VectorN - where - S: ops::AddAssign, - { - fn add_assign(&mut self, other: Self) { - $(self.$field += other.$field;)+ - } - } - - impl ops::SubAssign for $VectorN - where - S: ops::SubAssign, - { - fn sub_assign(&mut self, other: Self) { - $(self.$field -= other.$field;)+ - } - } - - impl ops::DivAssign for $VectorN - where - S: Copy + ops::DivAssign, - { - #[inline] - fn div_assign(&mut self, other: Self) { - $(self.$field /= other.$field;)+ - } - } - - impl ops::MulAssign for $VectorN - where - S: Copy + ops::MulAssign, - { - #[inline] - fn mul_assign(&mut self, other: Self) { - $(self.$field *= other.$field;)+ - } - } - - impl ops::RemAssign for $VectorN - where - S: Copy + ops::RemAssign, - { - #[inline] - fn rem_assign(&mut self, other: Self) { - $(self.$field %= other.$field;)+ - } - } - - // std::ops - vector scalar - - impl ops::Rem for $VectorN - where - S: Copy + ops::Rem, - { - type Output = $VectorN; - - #[inline] - fn rem(self, scalar: S) -> Self { - self.map(|s| s % scalar) - } - } - - impl ops::Div for $VectorN - where - S: Copy + ops::Div, - { - type Output = $VectorN; - - #[inline] - fn div(self, scalar: S) -> Self { - self.map(|s| s / scalar) - } - } - - impl ops::Mul for $VectorN - where - S: Copy + ops::Mul, - { - type Output = $VectorN; - - #[inline] - fn mul(self, scalar: S) -> Self { - self.map(|s| s * scalar) - } - } - - impl ops::RemAssign for $VectorN - where - S: Copy + ops::RemAssign, - { - #[inline] - fn rem_assign(&mut self, scalar: S) { - $(self.$field %= scalar;)+ - } - } - - impl ops::DivAssign for $VectorN - where - S: Copy + ops::DivAssign, - { - #[inline] - fn div_assign(&mut self, scalar: S) { - $(self.$field /= scalar;)+ - } - } - - impl ops::MulAssign for $VectorN - where - S: Copy + ops::MulAssign, - { - #[inline] - fn mul_assign(&mut self, scalar: S) { - $(self.$field *= scalar;)+ - } - } - - // indexing - - impl_index_operators!($VectorN, $n, S, usize); - impl_index_operators!($VectorN, $n, [S], ops::Range); - impl_index_operators!($VectorN, $n, [S], ops::RangeTo); - impl_index_operators!($VectorN, $n, [S], ops::RangeFrom); - impl_index_operators!($VectorN, $n, [S], ops::RangeFull); - - // conversions - - impl From<[S; $n]> for $VectorN - where - S: Copy, - { - #[inline] - fn from(v: [S; $n]) -> Self { - let [$($field),+] = v; - $VectorN { $($field),+ } - } - } - - impl Into<[S; $n]> for $VectorN { - #[inline] - fn into(self) -> [S; $n] { - let $VectorN { $($field),+ } = self; - [$($field),+] - } - } - - impl AsRef<[S; $n]> for $VectorN { - #[inline] - fn as_ref(&self) -> &[S; $n] { - unsafe { - let ptr = self as *const _ as *const [S; $n]; - &*ptr - } - } - } - - impl AsMut<[S; $n]> for $VectorN { - #[inline] - fn as_mut(&mut self) -> &mut [S; $n] { - unsafe { - let ptr = self as *mut _ as *mut [S; $n]; - &mut*ptr - } - } - } - - impl ops::Deref for $VectorN { - type Target = [S; $n]; - #[inline] - fn deref(&self) -> &Self::Target { - self.as_ref() - } - } - - impl ops::DerefMut for $VectorN { - #[inline] - fn deref_mut(&mut self) -> &mut Self::Target { - self.as_mut() - } - } - - // num-traits - - impl Bounded for $VectorN - where - S: Bounded, - { - #[inline] - fn min_value() -> $VectorN { - $VectorN { $($field: S::min_value()),+ } - } - - #[inline] - fn max_value() -> $VectorN { - $VectorN { $($field: S::max_value()),+ } - } - } - - impl Zero for $VectorN - where - S: PartialEq + Zero, - { - #[inline] - fn zero() -> $VectorN { - $VectorN { $($field: S::zero()),* } - } - - #[inline] - fn is_zero(&self) -> bool { - *self == $VectorN::zero() - } - } - - // `rand` crate implementations - - impl Distribution<$VectorN> for Standard - where - Standard: Distribution, - { - fn sample(&self, rng: &mut R) -> $VectorN { - $VectorN { $($field: rng.gen()),+ } - } - } - - /// The short constructor. - #[inline] - pub fn $constructor($($field: S),+) -> $VectorN { - $VectorN::new($($field),+) - } - }; -} - -mod cgmath_impl { - // From `cgmath` - macro_rules! fold_array { - (& $method:ident, { $x:expr }) => { - *$x - }; - (& $method:ident, { $x:expr, $y:expr }) => { - $x.$method(&$y) - }; - (& $method:ident, { $x:expr, $y:expr, $z:expr }) => { - $x.$method(&$y).$method(&$z) - }; - (& $method:ident, { $x:expr, $y:expr, $z:expr, $w:expr }) => { - $x.$method(&$y).$method(&$z).$method(&$w) - }; - ($method:ident, { $x:expr }) => { - $x - }; - ($method:ident, { $x:expr, $y:expr }) => { - $x.$method($y) - }; - ($method:ident, { $x:expr, $y:expr, $z:expr }) => { - $x.$method($y).$method($z) - }; - ($method:ident, { $x:expr, $y:expr, $z:expr, $w:expr }) => { - $x.$method($y).$method($z).$method($w) - }; - } - - use super::{Vector2, Vector3, Vector4}; - use crate::math::cgmath::{ - self, Angle, Array, BaseFloat, BaseNum, ElementWise, EuclideanSpace, InnerSpace, - MetricSpace, Rad, VectorSpace, - }; - use crate::math::cgmath::{AbsDiffEq, RelativeEq, UlpsEq}; - use std::ops; - - macro_rules! impl_vector_cgmath { - ($VectorN:ident { $($field:ident),+ }, $n:expr) => { - impl From> for $VectorN { - #[inline] - fn from(v: cgmath::$VectorN) -> Self { - let cgmath::$VectorN { $($field),+ } = v; - $VectorN { $($field),+ } - } - } - - impl Into> for $VectorN { - #[inline] - fn into(self) -> cgmath::$VectorN { - let $VectorN { $($field),+ } = self; - cgmath::$VectorN { $($field),+ } - } - } - - impl VectorSpace for $VectorN - where - S: BaseNum, - { - type Scalar = S; - } - - impl MetricSpace for $VectorN - where - S: BaseFloat, - { - type Metric = S; - - #[inline] - fn distance2(self, other: Self) -> S { - (other - self).magnitude2() - } - } - - impl AbsDiffEq for $VectorN - where - S: AbsDiffEq, - S::Epsilon: Copy, - { - type Epsilon = S::Epsilon; - - #[inline] - fn default_epsilon() -> S::Epsilon { - S::default_epsilon() - } - - #[inline] - fn abs_diff_eq( - &self, - other: &Self, - epsilon: Self::Epsilon, - ) -> bool { - $(self.$field.abs_diff_eq(&other.$field, epsilon))&&+ - } - } - - impl RelativeEq for $VectorN - where - S: RelativeEq, - S::Epsilon: Copy, - { - #[inline] - fn default_max_relative() -> S::Epsilon { - S::default_max_relative() - } - - #[inline] - fn relative_eq( - &self, - other: &Self, - epsilon: Self::Epsilon, - max_relative: Self::Epsilon, - ) -> bool { - $(self.$field.relative_eq(&other.$field, epsilon, max_relative))&&+ - } - } - - impl UlpsEq for $VectorN - where - S: UlpsEq, - S::Epsilon: Copy, - { - #[inline] - fn default_max_ulps() -> u32 { - S::default_max_ulps() - } - - #[inline] - fn ulps_eq(&self, other: &Self, epsilon: Self::Epsilon, max_ulps: u32) -> bool { - $(self.$field.ulps_eq(&other.$field, epsilon, max_ulps))&&+ - } - } - - impl ElementWise for $VectorN - where - S: BaseNum, - { - #[inline] - fn add_element_wise(self, rhs: S) -> $VectorN { - $VectorN::new($(self.$field + rhs),+) - } - #[inline] - fn sub_element_wise(self, rhs: S) -> $VectorN { - $VectorN::new($(self.$field - rhs),+) - } - #[inline] - fn mul_element_wise(self, rhs: S) -> $VectorN { - $VectorN::new($(self.$field * rhs),+) - } - #[inline] - fn div_element_wise(self, rhs: S) -> $VectorN { - $VectorN::new($(self.$field / rhs),+) - } - #[inline] - fn rem_element_wise(self, rhs: S) -> $VectorN { - $VectorN::new($(self.$field % rhs),+) - } - - #[inline] - fn add_assign_element_wise(&mut self, rhs: S) { - $(self.$field += rhs);+ - } - #[inline] - fn sub_assign_element_wise(&mut self, rhs: S) { - $(self.$field -= rhs);+ - } - #[inline] - fn mul_assign_element_wise(&mut self, rhs: S) { - $(self.$field *= rhs);+ - } - #[inline] - fn div_assign_element_wise(&mut self, rhs: S) { - $(self.$field /= rhs);+ - } - #[inline] - fn rem_assign_element_wise(&mut self, rhs: S) { - $(self.$field %= rhs);+ - } - } - - impl ElementWise for $VectorN - where - S: BaseFloat, - { - #[inline] - fn add_element_wise(self, rhs: $VectorN) -> $VectorN { - $VectorN::new($(self.$field + rhs.$field),+) - } - #[inline] - fn sub_element_wise(self, rhs: $VectorN) -> $VectorN { - $VectorN::new($(self.$field - rhs.$field),+) - } - #[inline] - fn mul_element_wise(self, rhs: $VectorN) -> $VectorN { - $VectorN::new($(self.$field * rhs.$field),+) - } - #[inline] - fn div_element_wise(self, rhs: $VectorN) -> $VectorN { - $VectorN::new($(self.$field / rhs.$field),+) - } - #[inline] - fn rem_element_wise(self, rhs: $VectorN) -> $VectorN { - $VectorN::new($(self.$field % rhs.$field),+) - } - - #[inline] - fn add_assign_element_wise(&mut self, rhs: $VectorN) { - $(self.$field += rhs.$field);+ - } - #[inline] - fn sub_assign_element_wise(&mut self, rhs: $VectorN) { - $(self.$field -= rhs.$field);+ - } - #[inline] - fn mul_assign_element_wise(&mut self, rhs: $VectorN) { - $(self.$field *= rhs.$field);+ - } - #[inline] - fn div_assign_element_wise(&mut self, rhs: $VectorN) { - $(self.$field /= rhs.$field);+ - } - #[inline] - fn rem_assign_element_wise(&mut self, rhs: $VectorN) { - $(self.$field %= rhs.$field);+ - } - } - - impl Array for $VectorN - where - S: Copy, - { - type Element = S; - - #[inline] - fn len() -> usize { - $n - } - - #[inline] - fn from_value(scalar: S) -> $VectorN { - $VectorN { $($field: scalar),+ } - } - - #[inline] - fn sum(self) -> S - where - S: ops::Add, - { - fold_array!(add, { $(self.$field),+ }) - } - - #[inline] - fn product(self) -> S - where - S: ops::Mul, - { - fold_array!(mul, { $(self.$field),+ }) - } - - #[inline] - fn is_finite(&self) -> bool - where - S: BaseFloat, - { - $(self.$field.is_finite())&&+ - } - } - - impl EuclideanSpace for $VectorN - where - S: BaseNum, - { - type Scalar = S; - type Diff = $VectorN; - - #[inline] - fn origin() -> Self { - $VectorN { $($field: S::zero()),+ } - } - - #[inline] - fn from_vec(v: $VectorN) -> Self { - $VectorN::new($(v.$field),+) - } - - #[inline] - fn to_vec(self) -> $VectorN { - $VectorN::new($(self.$field),+) - } - - #[inline] - fn dot(self, other: $VectorN) -> S { - $VectorN::new($(self.$field * other.$field),+).sum() - } - } - } - } - - // A macro to simplify the implementation of the point conversion traits. - macro_rules! impl_point_conversions { - ($VectorN:ident { $($field:ident),+ }, $PointN:ident) => { - impl From> for $VectorN { - #[inline] - fn from(v: cgmath::$PointN) -> Self { - let cgmath::$PointN { $($field),+ } = v; - $VectorN { $($field),+ } - } - } - - impl Into> for $VectorN { - #[inline] - fn into(self) -> cgmath::$PointN { - let $VectorN { $($field),+ } = self; - cgmath::$PointN { $($field),+ } - } - } - }; - } - - impl_vector_cgmath!(Vector2 { x, y }, 2); - impl_vector_cgmath!(Vector3 { x, y, z }, 3); - impl_vector_cgmath!(Vector4 { x, y, z, w }, 4); - - impl_point_conversions!(Vector2 { x, y }, Point2); - impl_point_conversions!(Vector3 { x, y, z }, Point3); - - impl InnerSpace for Vector2 - where - S: BaseFloat, - { - #[inline] - fn dot(self, other: Vector2) -> S { - Vector2::mul_element_wise(self, other).sum() - } - - #[inline] - fn angle(self, other: Vector2) -> Rad { - Rad::atan2(Self::perp_dot(self, other), Self::dot(self, other)) - } - } - - impl InnerSpace for Vector3 - where - S: BaseFloat, - { - #[inline] - fn dot(self, other: Vector3) -> S { - Vector3::mul_element_wise(self, other).sum() - } - - #[inline] - fn angle(self, other: Vector3) -> Rad { - Rad::atan2(self.cross(other).magnitude(), Self::dot(self, other)) - } - } - - impl InnerSpace for Vector4 - where - S: BaseFloat, - { - #[inline] - fn dot(self, other: Vector4) -> S { - Vector4::mul_element_wise(self, other).sum() - } - } -} - -mod lyon_impl { - use super::{Vector2, Vector3, Vector4}; - use crate::math::Zero; - - impl From for Vector2 - where - S: From, - { - fn from(p: lyon::math::Point) -> Self { - (S::from(p.x), S::from(p.y)).into() - } - } - - impl From for Vector3 - where - S: From + Zero, - { - fn from(p: lyon::math::Point) -> Self { - Vector2::from(p).into() - } - } - - impl From for Vector4 - where - S: From + Zero, - { - fn from(p: lyon::math::Point) -> Self { - Vector2::from(p).into() - } - } - - impl From for Vector2 - where - S: From, - { - fn from(p: lyon::math::F64Point) -> Self { - (S::from(p.x), S::from(p.y)).into() - } - } - - impl From for Vector3 - where - S: From + Zero, - { - fn from(p: lyon::math::F64Point) -> Self { - Vector2::from(p).into() - } - } - - impl From for Vector4 - where - S: From + Zero, - { - fn from(p: lyon::math::F64Point) -> Self { - Vector2::from(p).into() - } - } - - impl From for Vector2 - where - S: From, - { - fn from(v: lyon::math::Vector) -> Self { - (S::from(v.x), S::from(v.y)).into() - } - } - - impl From for Vector3 - where - S: From + Zero, - { - fn from(v: lyon::math::Vector) -> Self { - Vector2::from(v).into() - } - } - - impl From for Vector4 - where - S: From + Zero, - { - fn from(v: lyon::math::Vector) -> Self { - Vector2::from(v).into() - } - } - - impl From for Vector2 - where - S: From, - { - fn from(p: lyon::math::Size) -> Self { - (S::from(p.width), S::from(p.height)).into() - } - } - - impl From for Vector3 - where - S: From + Zero, - { - fn from(p: lyon::math::Size) -> Self { - Vector2::from(p).into() - } - } - - impl From for Vector4 - where - S: From + Zero, - { - fn from(p: lyon::math::Size) -> Self { - Vector2::from(p).into() - } - } - - impl Into for Vector2 { - fn into(self) -> lyon::math::Point { - (self.x, self.y).into() - } - } - - impl Into for Vector3 { - fn into(self) -> lyon::math::Point { - (self.x, self.y).into() - } - } - - impl Into for Vector4 { - fn into(self) -> lyon::math::Point { - (self.x, self.y).into() - } - } - - impl Into for Vector2 - where - S: Into, - { - fn into(self) -> lyon::math::F64Point { - (self.x.into(), self.y.into()).into() - } - } - - impl Into for Vector3 - where - S: Into, - { - fn into(self) -> lyon::math::F64Point { - (self.x.into(), self.y.into()).into() - } - } - - impl Into for Vector4 - where - S: Into, - { - fn into(self) -> lyon::math::F64Point { - (self.x.into(), self.y.into()).into() - } - } - - impl Into for Vector2 { - fn into(self) -> lyon::math::Vector { - (self.x, self.y).into() - } - } - - impl Into for Vector3 { - fn into(self) -> lyon::math::Vector { - (self.x, self.y).into() - } - } - - impl Into for Vector4 { - fn into(self) -> lyon::math::Vector { - (self.x, self.y).into() - } - } - - impl Into for Vector2 { - fn into(self) -> lyon::math::Size { - (self.x, self.y).into() - } - } - - impl Into for Vector3 { - fn into(self) -> lyon::math::Size { - (self.x, self.y).into() - } - } - - impl Into for Vector4 { - fn into(self) -> lyon::math::Size { - (self.x, self.y).into() - } - } -} - -impl_vector!(Vector2 { x, y }, 2, vec2); -impl_vector!(Vector3 { x, y, z }, 3, vec3); -impl_vector!(Vector4 { x, y, z, w }, 4, vec4); - -// tuple conversions - -impl From<(S, S)> for Vector2 { - fn from((x, y): (S, S)) -> Self { - Vector2 { x, y } - } -} - -impl From<(S, S, S)> for Vector3 { - fn from((x, y, z): (S, S, S)) -> Self { - Vector3 { x, y, z } - } -} - -impl From<(S, S, S, S)> for Vector4 { - fn from((x, y, z, w): (S, S, S, S)) -> Self { - Vector4 { x, y, z, w } - } -} - -impl Into<(S, S)> for Vector2 { - fn into(self) -> (S, S) { - let Vector2 { x, y } = self; - (x, y) - } -} - -impl Into<(S, S, S)> for Vector3 { - fn into(self) -> (S, S, S) { - let Vector3 { x, y, z } = self; - (x, y, z) - } -} - -impl Into<(S, S, S, S)> for Vector4 { - fn into(self) -> (S, S, S, S) { - let Vector4 { x, y, z, w } = self; - (x, y, z, w) - } -} - -// expanding tuple conversions - -impl From<(S, S)> for Vector3 -where - S: Zero, -{ - fn from((x, y): (S, S)) -> Self { - let z = S::zero(); - Vector3 { x, y, z } - } -} - -impl From<(S, S)> for Vector4 -where - S: Zero, -{ - fn from((x, y): (S, S)) -> Self { - let z = S::zero(); - let w = S::zero(); - Vector4 { x, y, z, w } - } -} - -impl From<(S, S, S)> for Vector4 -where - S: Zero, -{ - fn from((x, y, z): (S, S, S)) -> Self { - let w = S::zero(); - Vector4 { x, y, z, w } - } -} - -// expanding fixed-size array conversions - -impl From<[S; 2]> for Vector3 -where - S: Zero, -{ - fn from([x, y]: [S; 2]) -> Self { - let z = S::zero(); - Vector3 { x, y, z } - } -} - -impl From<[S; 2]> for Vector4 -where - S: Zero, -{ - fn from([x, y]: [S; 2]) -> Self { - let z = S::zero(); - let w = S::zero(); - Vector4 { x, y, z, w } - } -} - -impl From<[S; 3]> for Vector4 -where - S: Zero, -{ - fn from([x, y, z]: [S; 3]) -> Self { - let w = S::zero(); - Vector4 { x, y, z, w } - } -} - -// expanding vector conversions - -impl From> for Vector3 -where - S: Zero, -{ - fn from(Vector2 { x, y }: Vector2) -> Self { - let z = S::zero(); - Vector3 { x, y, z } - } -} - -impl From> for Vector4 -where - S: Zero, -{ - fn from(Vector2 { x, y }: Vector2) -> Self { - let z = S::zero(); - let w = S::zero(); - Vector4 { x, y, z, w } - } -} - -impl From> for Vector4 -where - S: Zero, -{ - fn from(Vector3 { x, y, z }: Vector3) -> Self { - let w = S::zero(); - Vector4 { x, y, z, w } - } -} - -// Vector 2 - -impl Vector2 { - /// A unit vector in the `x` direction. - #[inline] - pub fn unit_x() -> Vector2 - where - S: Zero + One, - { - Vector2::new(S::one(), S::zero()) - } - - /// A unit vector in the `y` direction. - #[inline] - pub fn unit_y() -> Vector2 - where - S: Zero + One, - { - Vector2::new(S::zero(), S::one()) - } - - /// The perpendicular dot product of the vector and `other`. - #[inline] - pub fn perp_dot(self, other: Vector2) -> S - where - S: ops::Sub + ops::Mul, - { - (self.x * other.y) - (self.y * other.x) - } - - /// Create a `Vector3`, using the `x` and `y` values from this vector, and the - /// provided `z`. - #[inline] - pub fn extend(self, z: S) -> Vector3 { - Vector3::new(self.x, self.y, z) - } - - /// Construct a normalised (aka "unit") vector from the given angle in radians. - /// - /// # Examples - /// - /// ``` - /// # use nannou::prelude::*; - /// # fn main() { - /// assert_eq!(Vector2::from_angle(0.0), vec2(1.0, 0.0)); - /// // Keep an eye out for accumulating floating point error. - /// assert_eq!(Vector2::from_angle(PI * 0.5), vec2(-0.00000004371139, 1.0)); - /// assert_eq!(Vector2::from_angle(PI), vec2(-1.0, -0.00000008742278)); - /// assert_eq!(Vector2::from_angle(PI * 1.5), vec2(0.000000011924881, -1.0)); - /// assert_eq!(Vector2::from_angle(TAU), vec2(1.0, 0.00000017484555)); - /// # } - /// ``` - pub fn from_angle(radians: S) -> Self - where - S: BaseFloat, - { - vec2(radians.cos(), radians.sin()) - } - - /// Returns the angle of the vector in radians. - /// - /// # Examples - /// - /// ``` - /// # use nannou::prelude::*; - /// # use nannou::Draw; - /// # fn main() { - /// let v = vec2(-0.5, 0.5); - /// let radians = v.angle(); - /// # let draw = Draw::new(); - /// draw.quad() - /// .rotate(radians); - /// assert_eq!(radians, 2.356194490192345); - /// # } - /// ``` - /// - pub fn angle(self) -> S - where - S: BaseFloat, - { - self.y.atan2(self.x) - } - - /// Returns the angle of the vector between `self` and `other` in radians. - /// - /// The result is between 0 and PI. Note: Nannou's implementation is commutative - /// (`v1.angle_between(v2)` == `v2.angle_between(v1)`). - /// - /// # Example - /// - /// ``` - /// # use nannou::prelude::*; - /// # fn main() { - /// let right = vec2(2.0, 0.0); - /// let up = vec2(0.0, 3.0); - /// let down = vec2(0.0, -100.0); - /// assert_eq!(right.angle_between(up), PI/2.0); - /// assert_eq!(right.angle_between(down), PI/2.0); - /// # } - /// ``` - pub fn angle_between(self, other: Self) -> S - where - S: BaseFloat, - { - let cos_theta = self.dot(other) / (self.magnitude() * other.magnitude()); - // Handle float rounding issues by clamping to [-1, 1]. - let cos_theta = cos_theta.min(S::one()).max(-S::one()); - cos_theta.acos() - } - - /// Rotate the vector around the origin (0.0, 0.0) by the given radians. - /// - /// # Examples - /// - /// ``` - /// # use nannou::prelude::*; - /// # fn main() { - /// let v = vec2(100.0, 0.0); - /// assert_eq!(v.rotate(PI).x, -v.x); - /// assert_eq!(v.rotate(TAU).x, v.x); - /// # } - /// ``` - pub fn rotate(self, radians: S) -> Self - where - S: BaseFloat, - { - let rad_cos = radians.cos(); - let rad_sin = radians.sin(); - let x = self.x * rad_cos - self.y * rad_sin; - let y = self.x * rad_sin + self.y * rad_cos; - vec2(x, y) - } - - //impl_swizzle_functions!(Vector1, Vector2, Vector3, Vector4, S, xy); -} - -// Vector 3 - -impl Vector3 { - /// A unit vector in the `x` direction. - #[inline] - pub fn unit_x() -> Vector3 - where - S: Zero + One, - { - Vector3::new(S::one(), S::zero(), S::zero()) - } - - /// A unit vector in the `y` direction. - #[inline] - pub fn unit_y() -> Vector3 - where - S: Zero + One, - { - Vector3::new(S::zero(), S::one(), S::zero()) - } - - /// A unit vector in the `z` direction. - #[inline] - pub fn unit_z() -> Vector3 - where - S: Zero + One, - { - Vector3::new(S::zero(), S::zero(), S::one()) - } - - /// Returns the cross product of the vector and `other`. - #[inline] - pub fn cross(self, other: Vector3) -> Vector3 - where - S: Copy + ops::Sub + ops::Mul, - { - Vector3::new( - (self.y * other.z) - (self.z * other.y), - (self.z * other.x) - (self.x * other.z), - (self.x * other.y) - (self.y * other.x), - ) - } - - /// Create a `Vector4`, using the `x`, `y` and `z` values from this vector, and the - /// provided `w`. - #[inline] - pub fn extend(self, w: S) -> Vector4 { - Vector4::new(self.x, self.y, self.z, w) - } - - /// Create a `Vector2`, dropping the `z` value. - #[inline] - pub fn truncate(self) -> Vector2 { - Vector2::new(self.x, self.y) - } - - // impl_swizzle_functions!(Vector1, Vector2, Vector3, Vector4, S, xyz); -} - -// Vector 4 - -impl Vector4 { - /// A unit vector in the `x` direction. - #[inline] - pub fn unit_x() -> Vector4 - where - S: Zero + One, - { - Vector4::new(S::one(), S::zero(), S::zero(), S::zero()) - } - - /// A unit vector in the `y` direction. - #[inline] - pub fn unit_y() -> Vector4 - where - S: Zero + One, - { - Vector4::new(S::zero(), S::one(), S::zero(), S::zero()) - } - - /// A unit vector in the `z` direction. - #[inline] - pub fn unit_z() -> Vector4 - where - S: Zero + One, - { - Vector4::new(S::zero(), S::zero(), S::one(), S::zero()) - } - - /// A unit vector in the `w` direction. - #[inline] - pub fn unit_w() -> Vector4 - where - S: Zero + One, - { - Vector4::new(S::zero(), S::zero(), S::zero(), S::one()) - } - - /// Create a `Vector3`, dropping the `w` value. - #[inline] - pub fn truncate(self) -> Vector3 { - Vector3::new(self.x, self.y, self.z) - } - - /// Create a `Vector3`, dropping the nth element. - #[inline] - pub fn truncate_n(&self, n: isize) -> Vector3 - where - S: Copy, - { - match n { - 0 => Vector3::new(self.y, self.z, self.w), - 1 => Vector3::new(self.x, self.z, self.w), - 2 => Vector3::new(self.x, self.y, self.w), - 3 => Vector3::new(self.x, self.y, self.z), - _ => panic!("{:?} is out of range", n), - } - } - - //impl_swizzle_functions!(Vector1, Vector2, Vector3, Vector4, S, xyzw); -} - -// utility functions - -fn limit_magnitude(v: V, limit: V::Scalar) -> V -where - V: InnerSpace, - V::Scalar: BaseFloat, -{ - let magnitude2 = v.magnitude2(); - if magnitude2 <= limit * limit { - v - } else { - v.normalize() * limit - } -} - -#[cfg(test)] -mod tests { - use super::*; - use crate::prelude::*; - use cgmath::assert_ulps_eq; - - #[test] - fn test_angle_between() { - let right = vec2(1.0, 0.0); - let upright = vec2(1.0, 1.0); - assert_eq!(right.angle_between(upright), PI / 4.0); - // angle_between is symmetric. - assert_eq!(upright.angle_between(right), PI / 4.0); - - let left = vec2(-1.0, 0.0); - let left2 = vec2(-1.0123456789, 0.0); - assert_ulps_eq!(right.angle_between(left), PI); - assert_ulps_eq!(right.angle_between(left2), PI); - - // angle between same vector is 0. - assert_eq!(upright.angle_between(upright), 0.0); - assert_eq!(left.angle_between(left), 0.0); - assert_eq!(left2.angle_between(left2), 0.0); - - // handles zero vector. - assert_eq!(right.angle_between(vec2(0.0, 0.0)), 0.0); - assert_eq!(left2.angle_between(vec2(0.0, 0.0)), 0.0); - } -} diff --git a/nannou/src/geom/vertex.rs b/nannou/src/geom/vertex.rs deleted file mode 100644 index a05c8ef32..000000000 --- a/nannou/src/geom/vertex.rs +++ /dev/null @@ -1,344 +0,0 @@ -use crate::color; -use crate::geom::{scalar, Point2, Point3}; -use crate::math::BaseNum; -use std::ops::{Deref, DerefMut}; - -/// Types used as vertices that can be used to describe geometric points in space. -pub trait Vertex: Clone + Copy + PartialEq { - /// The values used to describe the vertex position. - type Scalar: BaseNum; -} - -/// Vertex types that have at least 2 dimensions. -pub trait Vertex2d: Vertex { - /// The x, y location of the vertex. - fn point2(self) -> Point2; -} - -/// Vertex types that have at least 3 dimensions. -pub trait Vertex3d: Vertex2d { - /// The x, y, z location of the vertex. - fn point3(self) -> Point3; -} - -/// If a type is not specified for a piece of geometry, this is the default type used. -pub type Default = Point3; - -/// An iterator yielding a vertex for each index yielded by the given indices iterator. -#[derive(Clone, Debug)] -pub struct IterFromIndices<'a, I, V: 'a = Default> { - indices: I, - vertices: &'a [V], -} - -/// A vertex that is colored with the given `sRGBA` color. -#[derive(Copy, Clone, Debug, PartialEq)] -pub struct Srgba(pub V, pub color::Srgba); - -/// Produce an iterator yielding a vertex for each index yielded by the given indices iterator. -pub fn iter_from_indices(indices: I, vertices: &[V]) -> IterFromIndices -where - I: IntoIterator, -{ - let indices = indices.into_iter(); - IterFromIndices { indices, vertices } -} - -// Iterators - -impl<'a, I, V> Iterator for IterFromIndices<'a, I, V> -where - I: Iterator, -{ - type Item = &'a V; - fn next(&mut self) -> Option { - let IterFromIndices { - ref mut indices, - ref vertices, - } = *self; - indices.next().map(|i| &vertices[i]) - } - - fn size_hint(&self) -> (usize, Option) { - self.indices.size_hint() - } -} - -impl<'a, I, V> DoubleEndedIterator for IterFromIndices<'a, I, V> -where - I: Iterator + DoubleEndedIterator, -{ - fn next_back(&mut self) -> Option { - let IterFromIndices { - ref mut indices, - ref vertices, - } = *self; - indices.next_back().map(|i| &vertices[i]) - } -} - -impl<'a, I, V> ExactSizeIterator for IterFromIndices<'a, I, V> -where - I: Iterator + ExactSizeIterator, -{ - fn len(&self) -> usize { - self.indices.len() - } -} - -// Srgba impls. - -impl Srgba { - /// A reference to the inner vertex. - pub fn vertex(&self) -> &V { - &self.0 - } - /// A reference to the inner rgba. - pub fn rgba(&self) -> &color::Srgba { - &self.1 - } -} - -impl Deref for Srgba { - type Target = V; - fn deref(&self) -> &Self::Target { - &self.0 - } -} - -impl DerefMut for Srgba { - fn deref_mut(&mut self) -> &mut Self::Target { - &mut self.0 - } -} - -impl From<(V, color::Srgba)> for Srgba { - fn from((v, rgba): (V, color::Srgba)) -> Self { - Srgba(v, rgba) - } -} - -impl Into<(V, color::Srgba)> for Srgba { - fn into(self) -> (V, color::Srgba) { - let Srgba(v, rgba) = self; - (v, rgba) - } -} - -// Vertex impls - -impl Vertex for Point2 -where - S: BaseNum, -{ - type Scalar = S; -} - -impl Vertex for Point3 -where - S: BaseNum, -{ - type Scalar = S; -} - -impl Vertex for [S; 2] -where - S: BaseNum, -{ - type Scalar = S; -} - -impl Vertex for [S; 3] -where - S: BaseNum, -{ - type Scalar = S; -} - -impl Vertex for (S, S) -where - S: BaseNum, -{ - type Scalar = S; -} - -impl Vertex for (S, S, S) -where - S: BaseNum, -{ - type Scalar = S; -} - -// impl Vertex for Vector2 -// where -// S: BaseNum, -// { -// type Scalar = S; -// } -// -// impl Vertex for Vector3 -// where -// S: BaseNum, -// { -// type Scalar = S; -// } - -impl Vertex for Srgba -where - V: Vertex, -{ - type Scalar = V::Scalar; -} - -// Vertex2d impls - -impl Vertex2d for Point2 -where - S: BaseNum, -{ - fn point2(self) -> Point2 { - Point2 { - x: self.x, - y: self.y, - } - } -} - -impl Vertex2d for Point3 -where - S: BaseNum, -{ - fn point2(self) -> Point2 { - Point2 { - x: self.x, - y: self.y, - } - } -} - -impl Vertex2d for [S; 2] -where - S: BaseNum, -{ - fn point2(self) -> Point2 { - Point2 { - x: self[0], - y: self[1], - } - } -} - -impl Vertex2d for [S; 3] -where - S: BaseNum, -{ - fn point2(self) -> Point2 { - Point2 { - x: self[0], - y: self[1], - } - } -} - -impl Vertex2d for (S, S) -where - S: BaseNum, -{ - fn point2(self) -> Point2 { - let (x, y) = self; - Point2 { x, y } - } -} - -impl Vertex2d for (S, S, S) -where - S: BaseNum, -{ - fn point2(self) -> Point2 { - let (x, y, _) = self; - Point2 { x, y } - } -} - -// impl Vertex2d for Vector2 -// where -// S: BaseNum, -// { -// fn point2(self) -> Point2 { -// self -// } -// } -// -// impl Vertex2d for Vector3 -// where -// S: BaseNum, -// { -// fn point2(self) -> Point2 { -// Point2 { x: self.x, y: self.y } -// } -// } - -impl Vertex2d for Srgba -where - V: Vertex2d, -{ - fn point2(self) -> Point2 { - self.0.point2() - } -} - -// Vertex3d impls - -impl Vertex3d for Point3 -where - S: BaseNum, -{ - fn point3(self) -> Point3 { - Point3 { - x: self.x, - y: self.y, - z: self.z, - } - } -} - -impl Vertex3d for [S; 3] -where - S: BaseNum, -{ - fn point3(self) -> Point3 { - Point3 { - x: self[0], - y: self[1], - z: self[2], - } - } -} - -impl Vertex3d for (S, S, S) -where - S: BaseNum, -{ - fn point3(self) -> Point3 { - let (x, y, z) = self; - Point3 { x, y, z } - } -} - -// impl Vertex3d for Vector3 -// where -// S: BaseNum, -// { -// fn point3(self) -> Point3 { -// self -// } -// } - -impl Vertex3d for Srgba -where - V: Vertex3d, -{ - fn point3(self) -> Point3 { - self.0.point3() - } -} diff --git a/nannou/src/lib.rs b/nannou/src/lib.rs index 5806d3759..2f12f0888 100644 --- a/nannou/src/lib.rs +++ b/nannou/src/lib.rs @@ -19,17 +19,17 @@ pub use conrod_winit; pub use daggy; pub use find_folder; pub use lyon; -use serde_derive; pub use winit; +pub use self::app::{App, LoopMode}; +pub use self::draw::Draw; pub use self::event::Event; pub use self::frame::Frame; pub use self::ui::Ui; -pub use crate::app::{App, LoopMode}; -pub use crate::draw::Draw; +#[doc(inline)] +pub use nannou_core::{color, glam, math, rand}; pub mod app; -pub mod color; pub mod draw; pub mod ease; pub mod event; @@ -37,11 +37,9 @@ pub mod frame; pub mod geom; pub mod image; pub mod io; -pub mod math; pub mod mesh; pub mod noise; pub mod prelude; -pub mod rand; pub mod state; pub mod text; pub mod time; diff --git a/nannou/src/math.rs b/nannou/src/math.rs deleted file mode 100644 index ce30772fc..000000000 --- a/nannou/src/math.rs +++ /dev/null @@ -1,158 +0,0 @@ -//! A mathematical foundation for nannou including point and vector types and a range of -//! helper/utility functions. - -pub use cgmath; - -pub use self::cgmath::num_traits::{self, Bounded, Float, NumCast, One, Zero}; -// cgmath modules -pub use self::cgmath::prelude; -// cgmath types -pub use self::cgmath::{ - Basis2, Basis3, Decomposed, Deg, Euler, Matrix2, Matrix3, Matrix4, Ortho, Perspective, - PerspectiveFov, Quaternion, Rad, -}; -// cgmath traits -pub use self::cgmath::{ - Angle, Array, BaseFloat, BaseNum, ElementWise, EuclideanSpace, InnerSpace, Matrix, MetricSpace, - Rotation, Rotation2, Rotation3, SquareMatrix, Transform, Transform2, Transform3, VectorSpace, -}; -use std::ops::Add; - -/// Maps a value from an input range to an output range. -/// -/// Note that `map_range` doesn't clamp the output: if `val` is outside the input range, the mapped -/// value will be outside the output range. (Use `clamp` to restrict the output, if desired.) -/// -/// # Examples -/// ``` -/// # use nannou::prelude::*; -/// assert_eq!(map_range(128, 0, 255, 0.0, 1.0), 0.5019607843137255); -/// ``` -/// ``` -/// # use nannou::prelude::*; -/// assert_eq!(map_range(3, 0, 10, 0.0, 1.0), 0.3); -/// ``` -/// ``` -/// # use nannou::prelude::*; -/// // When the value is outside the input range, the result will be outside the output range. -/// let result = map_range(15, 0, 10, 0.0, 1.0); -/// assert_eq!(result, 1.5); -/// assert_eq!(clamp(result, 0.0, 1.0), 1.0); -/// ``` -pub fn map_range(val: X, in_min: X, in_max: X, out_min: Y, out_max: Y) -> Y -where - X: NumCast, - Y: NumCast, -{ - macro_rules! unwrap_or_panic { - ($result:expr, $arg:expr) => { - $result.unwrap_or_else(|| panic!("[map_range] failed to cast {} arg to `f64`", $arg)) - }; - } - - let val_f: f64 = unwrap_or_panic!(NumCast::from(val), "first"); - let in_min_f: f64 = unwrap_or_panic!(NumCast::from(in_min), "second"); - let in_max_f: f64 = unwrap_or_panic!(NumCast::from(in_max), "third"); - let out_min_f: f64 = unwrap_or_panic!(NumCast::from(out_min), "fourth"); - let out_max_f: f64 = unwrap_or_panic!(NumCast::from(out_max), "fifth"); - - NumCast::from((val_f - in_min_f) / (in_max_f - in_min_f) * (out_max_f - out_min_f) + out_min_f) - .unwrap_or_else(|| panic!("[map_range] failed to cast result to target type")) -} - -/// The max between two partially ordered values. -pub fn partial_max(a: T, b: T) -> T -where - T: PartialOrd, -{ - if a >= b { - a - } else { - b - } -} - -/// The min between two partially ordered values. -pub fn partial_min(a: T, b: T) -> T -where - T: PartialOrd, -{ - if a <= b { - a - } else { - b - } -} - -/// Clamp a value between some range. -pub fn clamp(n: T, start: T, end: T) -> T -where - T: PartialOrd, -{ - if start <= end { - if n < start { - start - } else if n > end { - end - } else { - n - } - } else { - if n < end { - end - } else if n > start { - start - } else { - n - } - } -} - -pub fn two() -> S -where - S: Add + One, -{ - S::one() + S::one() -} - -/// Models the C++ fmod function. -#[inline] -pub fn fmod(numer: F, denom: F) -> F -where - F: Float, -{ - let rquot: F = (numer / denom).floor(); - numer - rquot * denom -} - -/// Convert the given angle in degrees to the same angle in radians. -pub fn deg_to_rad(deg: S) -> S -where - S: BaseFloat, -{ - Rad::from(Deg(deg)).0 -} - -/// Convert the given angle in radians to the same angle in degrees. -pub fn rad_to_deg(rad: S) -> S -where - S: BaseFloat, -{ - Deg::from(Rad(rad)).0 -} - -/// Convert the given value as a number of "turns" into the equivalent angle in radians. -pub fn turns_to_rad(turns: S) -> S -where - S: BaseFloat, -{ - turns * NumCast::from(2.0 * ::std::f64::consts::PI).unwrap() -} - -/// Convert the given value in radians to the equivalent value as a number of turns. -pub fn rad_to_turns(rad: S) -> S -where - S: BaseFloat, -{ - rad / NumCast::from(2.0 * ::std::f64::consts::PI).unwrap() -} diff --git a/nannou/src/mesh/vertex.rs b/nannou/src/mesh/vertex.rs index c93f87667..2294a9d4d 100644 --- a/nannou/src/mesh/vertex.rs +++ b/nannou/src/mesh/vertex.rs @@ -1,9 +1,7 @@ //! Vertex types yielded by the mesh adaptors and their implementations. use crate::color::{self, IntoLinSrgba}; -use crate::geom::graph::node::{self, ApplyTransform}; -use crate::geom::{self, Point2, Point3}; -use crate::math::BaseFloat; +use crate::geom::{self, Point2}; use std::ops::{Deref, DerefMut}; /// A vertex with a specified color. @@ -15,7 +13,7 @@ pub struct WithColor> { /// A vertex with some specified texture coordinates. #[derive(Copy, Clone, Debug, Default, PartialEq)] -pub struct WithTexCoords> { +pub struct WithTexCoords { pub vertex: V, pub tex_coords: T, } @@ -27,49 +25,6 @@ pub struct WithNormal { pub normal: N, } -// Node Transform application implementations. - -impl ApplyTransform for WithColor -where - V: ApplyTransform, - S: BaseFloat, -{ - fn apply_transform(self, transform: &node::PreparedTransform) -> Self { - let WithColor { mut vertex, color } = self; - vertex = vertex.apply_transform(transform); - WithColor { vertex, color } - } -} - -impl ApplyTransform for WithTexCoords -where - V: ApplyTransform, - S: BaseFloat, -{ - fn apply_transform(self, transform: &node::PreparedTransform) -> Self { - let WithTexCoords { - mut vertex, - tex_coords, - } = self; - vertex = vertex.apply_transform(transform); - WithTexCoords { vertex, tex_coords } - } -} - -impl ApplyTransform for WithNormal -where - V: ApplyTransform, - S: BaseFloat, -{ - fn apply_transform(self, _transform: &node::PreparedTransform) -> Self { - //let WithNormal { mut vertex, mut normal } = self; - //vertex = vertex.apply_transform(transform); - // TODO: Apply transform to the `normal`. - unimplemented!(); - //WithNormal { vertex, normal } - } -} - // Deref implementations for each vertex adaptor to their inner vertex type. impl Deref for WithColor { @@ -142,7 +97,7 @@ where V: geom::Vertex2d, Self: geom::Vertex, { - fn point2(self) -> Point2 { + fn point2(self) -> [Self::Scalar; 2] { self.vertex.point2() } } @@ -152,7 +107,7 @@ where V: geom::Vertex2d, Self: geom::Vertex, { - fn point2(self) -> Point2 { + fn point2(self) -> [Self::Scalar; 2] { self.vertex.point2() } } @@ -162,7 +117,7 @@ where V: geom::Vertex2d, Self: geom::Vertex, { - fn point2(self) -> Point2 { + fn point2(self) -> [Self::Scalar; 2] { self.vertex.point2() } } @@ -172,7 +127,7 @@ where V: geom::Vertex3d, Self: geom::Vertex, { - fn point3(self) -> Point3 { + fn point3(self) -> [Self::Scalar; 3] { self.vertex.point3() } } @@ -182,7 +137,7 @@ where V: geom::Vertex3d, Self: geom::Vertex, { - fn point3(self) -> Point3 { + fn point3(self) -> [Self::Scalar; 3] { self.vertex.point3() } } @@ -192,7 +147,7 @@ where V: geom::Vertex3d, Self: geom::Vertex, { - fn point3(self) -> Point3 { + fn point3(self) -> [Self::Scalar; 3] { self.vertex.point3() } } @@ -240,6 +195,6 @@ where #[test] fn test_tuple_conv() { use crate::color::named::GREEN; - let _: Point2<_> = [0.0, 0.0].into(); - let _: WithColor> = ([0.0, 0.0], GREEN).into(); + let _: Point2 = [0.0, 0.0].into(); + let _: WithColor = ([0.0, 0.0], GREEN).into(); } diff --git a/nannou/src/prelude.rs b/nannou/src/prelude.rs index ee3acca06..91bd8fa3a 100644 --- a/nannou/src/prelude.rs +++ b/nannou/src/prelude.rs @@ -1,14 +1,6 @@ //! A collection of commonly used items that we recommend importing for ease of use. pub use crate::app::{self, App, LoopMode}; -pub use crate::color::named::*; -pub use crate::color::{ - gray, hsl, hsla, hsv, hsva, lin_srgb, lin_srgba, rgb, rgb8, rgba, rgba8, srgb, srgb8, srgba, - srgba8, -}; -pub use crate::color::{ - Gray, Hsl, Hsla, Hsv, Hsva, LinSrgb, LinSrgba, Rgb, Rgb8, Rgba, Rgba8, Srgb, Srgba, -}; pub use crate::draw::Draw; pub use crate::event::WindowEvent::*; pub use crate::event::{ @@ -16,17 +8,7 @@ pub use crate::event::{ TouchpadPressure, Update, WindowEvent, }; pub use crate::frame::{Frame, RawFrame}; -pub use crate::geom::{ - self, pt2, pt3, vec2, vec3, vec4, Cuboid, Point2, Point3, Rect, Vector2, Vector3, Vector4, -}; pub use crate::io::{load_from_json, load_from_toml, safe_file_save, save_to_json, save_to_toml}; -pub use crate::math::num_traits::*; -pub use crate::math::prelude::*; -pub use crate::math::{ - clamp, deg_to_rad, fmod, map_range, partial_max, partial_min, rad_to_deg, rad_to_turns, - turns_to_rad, -}; -pub use crate::rand::{random, random_ascii, random_f32, random_f64, random_range}; pub use crate::text::{self, text}; pub use crate::time::DurationF64; pub use crate::ui; @@ -38,14 +20,4 @@ pub use crate::wgpu::blend::{ pub use crate::wgpu::util::{BufferInitDescriptor, DeviceExt}; pub use crate::window::{self, Id as WindowId}; pub use crate::window::{Fullscreen, Window}; - -// The following constants have "regular" names for the `DefaultScalar` type and type suffixes for -// other types. If the `DefaultScalar` changes, these should probably change too. - -pub use std::f32::consts::PI; -pub use std::f64::consts::PI as PI_F64; - -/// Two times PI. -pub const TAU: f32 = PI * 2.0; -/// Two times PI. -pub const TAU_F64: f64 = PI_F64 * 2.0; +pub use nannou_core::prelude::*; diff --git a/nannou/src/state.rs b/nannou/src/state.rs index bcf8ba652..545f7fcd7 100644 --- a/nannou/src/state.rs +++ b/nannou/src/state.rs @@ -65,14 +65,10 @@ pub mod keys { /// Tracked state related to the mouse. pub mod mouse { - use crate::geom::{self, Point2}; - use crate::math::BaseFloat; + use crate::geom::Point2; use crate::window; use std; - /// The default scalar value used for positions. - pub type DefaultScalar = geom::scalar::Default; - #[doc(inline)] pub use crate::event::MouseButton as Button; @@ -81,76 +77,64 @@ pub mod mouse { /// The state of the `Mouse` at a single moment in time. #[derive(Copy, Clone, Debug, PartialEq)] - pub struct Mouse { + pub struct Mouse { /// The ID of the last window currently in focus. pub window: Option, /// *x* position relative to the middle of `window`. - pub x: S, + pub x: f32, /// *y* position relative to the middle of `window`. - pub y: S, + pub y: f32, /// A map describing the state of each mouse button. pub buttons: ButtonMap, } /// Whether the button is up or down. #[derive(Copy, Clone, Debug, PartialEq)] - pub enum ButtonPosition { + pub enum ButtonPosition { /// The button is up (i.e. pressed). Up, /// The button is down and was originally pressed down at the given `Point2`. - Down(Point2), + Down(Point2), } /// Stores the state of all mouse buttons. /// /// If the mouse button is down, it stores the position of the mouse when the button was pressed #[derive(Copy, Clone, Debug, PartialEq)] - pub struct ButtonMap { - buttons: [ButtonPosition; NUM_BUTTONS], + pub struct ButtonMap { + buttons: [ButtonPosition; NUM_BUTTONS], } /// An iterator yielding all pressed buttons. #[derive(Clone)] - pub struct PressedButtons<'a, S: 'a = DefaultScalar> { - buttons: std::iter::Enumerate>>, + pub struct PressedButtons<'a> { + buttons: std::iter::Enumerate>, } - impl Mouse - where - S: BaseFloat, - { + impl Mouse { /// Construct a new default `Mouse`. pub fn new() -> Self { Mouse { window: None, buttons: ButtonMap::new(), - x: S::zero(), - y: S::zero(), + x: 0.0, + y: 0.0, } } /// The position of the mouse relative to the middle of the window in focus.. - pub fn position(&self) -> Point2 { - Point2 { - x: self.x, - y: self.y, - } + pub fn position(&self) -> Point2 { + [self.x, self.y].into() } } - impl ButtonPosition - where - S: BaseFloat, - { + impl ButtonPosition { /// If the mouse button is down, return a new one with position relative to the given `xy`. - pub fn relative_to(self, xy: Point2) -> Self { + pub fn relative_to(self, xy: Point2) -> Self { match self { ButtonPosition::Down(pos) => { let rel_p = pos - xy; - ButtonPosition::Down(Point2 { - x: rel_p.x, - y: rel_p.y, - }) + ButtonPosition::Down([rel_p.x, rel_p.y].into()) } button_pos => button_pos, } @@ -173,7 +157,7 @@ pub mod mouse { } /// Returns the position at which the button was pressed. - pub fn if_down(&self) -> Option> { + pub fn if_down(&self) -> Option { match *self { ButtonPosition::Down(xy) => Some(xy), _ => None, @@ -181,10 +165,7 @@ pub mod mouse { } } - impl ButtonMap - where - S: BaseFloat, - { + impl ButtonMap { /// Returns a new button map with all states set to `None` pub fn new() -> Self { ButtonMap { @@ -193,7 +174,7 @@ pub mod mouse { } /// Returns a copy of the ButtonMap relative to the given `Point` - pub fn relative_to(self, xy: Point2) -> Self { + pub fn relative_to(self, xy: Point2) -> Self { self.buttons .iter() .enumerate() @@ -204,22 +185,22 @@ pub mod mouse { } /// The state of the left mouse button. - pub fn left(&self) -> &ButtonPosition { + pub fn left(&self) -> &ButtonPosition { &self[Button::Left] } /// The state of the middle mouse button. - pub fn middle(&self) -> &ButtonPosition { + pub fn middle(&self) -> &ButtonPosition { &self[Button::Middle] } /// The state of the right mouse button. - pub fn right(&self) -> &ButtonPosition { + pub fn right(&self) -> &ButtonPosition { &self[Button::Right] } /// Sets the `Button` in the `Down` position. - pub fn press(&mut self, button: Button, xy: Point2) { + pub fn press(&mut self, button: Button, xy: Point2) { self.buttons[button_to_idx(button)] = ButtonPosition::Down(xy); } @@ -230,25 +211,22 @@ pub mod mouse { /// An iterator yielding all pressed mouse buttons along with the location at which they /// were originally pressed. - pub fn pressed(&self) -> PressedButtons { + pub fn pressed(&self) -> PressedButtons { PressedButtons { buttons: self.buttons.iter().enumerate(), } } } - impl std::ops::Index