From b58b9e55560658f4df92b7810b6ac3420128f2a4 Mon Sep 17 00:00:00 2001 From: Daniel Buch Hansen Date: Thu, 14 Apr 2022 00:36:04 +0200 Subject: [PATCH 1/5] Tessellate: Implement precomputed vertices for rounding Before: demo_with_tessellate__realistic time: [328.77 us 329.22 us 329.70 us] change: [-2.6116% -1.1978% +0.2520%] (p = 0.10 > 0.05) No change in performance detected. demo_no_tessellate time: [164.67 us 165.82 us 167.30 us] demo_only_tessellate time: [159.34 us 159.85 us 160.67 us] After: demo_with_tessellate__realistic time: [309.48 us 309.92 us 310.41 us] change: [-7.1042% -5.6164% -4.0262%] (p = 0.00 < 0.05) Performance has improved. demo_no_tessellate time: [160.44 us 161.30 us 162.49 us] change: [-4.5692% -2.8617% -1.3549%] (p = 0.00 < 0.05) Performance has improved. demo_only_tessellate time: [139.45 us 140.23 us 141.25 us] change: [-13.637% -12.245% -10.695%] (p = 0.00 < 0.05) Performance has improved. Not sure this is the right path. So i didn't bother to port Path::add_point() Also we might want to fallback to computed vertices for radii >= 20 or add another precomputed batch. --- epaint/src/tessellator.rs | 144 ++++++++++++++++++++++++++++++++++---- 1 file changed, 131 insertions(+), 13 deletions(-) diff --git a/epaint/src/tessellator.rs b/epaint/src/tessellator.rs index 980abee5dcc..bd0d4da240c 100644 --- a/epaint/src/tessellator.rs +++ b/epaint/src/tessellator.rs @@ -192,6 +192,117 @@ pub mod path { use super::*; + mod precomputed_quadrants { + use emath::{vec2, Vec2}; + + pub const QUADRANTS_0_5: [[Vec2; 3]; 4] = [ + // quadrant 0: right bottom + [ + vec2(1.000000, 0.000000), + vec2(0.707107, 0.707107), + vec2(-0.000000, 1.000000) + ], + // quadrant 1: left bottom + [ + vec2(-0.000000, 1.000000), + vec2(-0.707107, 0.707107), + vec2(-1.000000, -0.000000), + ], + // quadrant 2: left top + [ + vec2(-1.000000, -0.000000), + vec2(-0.707107, -0.707107), + vec2(0.000000, -1.000000), + ], + // quadrant 3: right top + [ + vec2(0.000000, -1.000000), + vec2(0.707107, -0.707107), + vec2(1.000000, 0.000000), + ], + ]; + + pub const QUADRANTS_5_10: [[Vec2; 5]; 4] = [ + // quadrant 0: right bottom + [ + vec2(1.000000, 0.000000), + vec2(0.923880, 0.382683), + vec2(0.707107, 0.707107), + vec2(0.382683, 0.923880), + vec2(-0.000000, 1.000000), + ], + // quadrant 1: left bottom + [ + vec2(-0.000000, 1.000000), + vec2(-0.382684, 0.923880), + vec2(-0.707107, 0.707107), + vec2(-0.923880, 0.382683), + vec2(-1.000000, -0.000000), + ], + // quadrant 2: left top + [ + vec2(-1.000000, -0.000000), + vec2(-0.923880, -0.382683), + vec2(-0.707107, -0.707107), + vec2(-0.382684, -0.923880), + vec2(0.000000, -1.000000), + ], + // quadrant 3: right top + [ + vec2(0.000000, -1.000000), + vec2(0.382684, -0.923879), + vec2(0.707107, -0.707107), + vec2(0.923880, -0.382683), + vec2(1.000000, 0.000000), + ], + ]; + + pub const QUADRANTS_10_20: [[Vec2; 7]; 4] = [ + // quadrant 0: right bottom + [ + vec2(1.000000, 0.000000), + vec2(0.965926, 0.258819), + vec2(0.866025, 0.500000), + vec2(0.707107, 0.707107), + vec2(0.500000, 0.866025), + vec2(0.258819, 0.965926), + vec2(-0.000000, 1.000000), + ], + // quadrant 1: left bottom + [ + vec2(-0.000000, 1.000000), + vec2(-0.258819, 0.965926), + vec2(-0.500000, 0.866025), + vec2(-0.707107, 0.707107), + vec2(-0.866025, 0.500000), + vec2(-0.965926, 0.258819), + vec2(-1.000000, -0.000000), + ], + // quadrant 2: left top + [ + vec2(-1.000000, -0.000000), + vec2(-0.965926, -0.258819), + vec2(-0.866026, -0.500000), + vec2(-0.707107, -0.707107), + vec2(-0.500000, -0.866025), + vec2(-0.258819, -0.965926), + vec2(0.000000, -1.000000), + ], + // quadrant 3: right top + [ + vec2(0.000000, -1.000000), + vec2(0.258819, -0.965926), + vec2(0.500000, -0.866025), + vec2(0.707107, -0.707107), + vec2(0.866025, -0.500000), + vec2(0.965926, -0.258819), + vec2(1.000000, 0.000000), + ], + ]; + } + + use precomputed_quadrants::*; + /// overwrites existing points pub fn rounded_rectangle(path: &mut Vec, rect: Rect, rounding: Rounding) { path.clear(); @@ -236,19 +347,26 @@ pub mod path { // - quadrant 3: right top // * angle 4 * TAU / 4 = right pub fn add_circle_quadrant(path: &mut Vec, center: Pos2, radius: f32, quadrant: f32) { - // TODO: optimize with precalculated vertices for some radii ranges - - let n = (radius * 0.75).round() as i32; // TODO: tweak a bit more - let n = n.clamp(2, 32); - const RIGHT_ANGLE: f32 = TAU / 4.0; - path.reserve(n as usize + 1); - for i in 0..=n { - let angle = remap( - i as f32, - 0.0..=n as f32, - quadrant * RIGHT_ANGLE..=(quadrant + 1.0) * RIGHT_ANGLE, - ); - path.push(center + radius * Vec2::angled(angle)); + if radius == 0.0 { + path.push(center); + } else if radius <= 5.0 { + let quadrant_vertices = QUADRANTS_0_5[quadrant as usize]; + path.reserve(quadrant_vertices.len()); + quadrant_vertices + .iter() + .for_each(|v| path.push(center + radius * *v)); + } else if radius > 5.0 && radius <= 10.0 { + let quadrant_vertices = QUADRANTS_5_10[quadrant as usize]; + path.reserve(quadrant_vertices.len()); + quadrant_vertices + .iter() + .for_each(|v| path.push(center + radius * *v)); + } else { + let quadrant_vertices = QUADRANTS_10_20[quadrant as usize]; + path.reserve(quadrant_vertices.len()); + quadrant_vertices + .iter() + .for_each(|v| path.push(center + radius * *v)); } } From df838b9fcb8e106c5c9d56bc048adde2ec514de1 Mon Sep 17 00:00:00 2001 From: Daniel Buch Hansen Date: Sun, 17 Apr 2022 22:17:16 +0200 Subject: [PATCH 2/5] adapt to code review --- epaint/src/tessellator.rs | 21 ++++++--------------- 1 file changed, 6 insertions(+), 15 deletions(-) diff --git a/epaint/src/tessellator.rs b/epaint/src/tessellator.rs index bd0d4da240c..12dcbb6dbf6 100644 --- a/epaint/src/tessellator.rs +++ b/epaint/src/tessellator.rs @@ -200,7 +200,7 @@ pub mod path { [ vec2(1.000000, 0.000000), vec2(0.707107, 0.707107), - vec2(-0.000000, 1.000000) + vec2(-0.000000, 1.000000), ], // quadrant 1: left bottom [ @@ -347,26 +347,17 @@ pub mod path { // - quadrant 3: right top // * angle 4 * TAU / 4 = right pub fn add_circle_quadrant(path: &mut Vec, center: Pos2, radius: f32, quadrant: f32) { - if radius == 0.0 { + if radius <= 0.0 { path.push(center); } else if radius <= 5.0 { let quadrant_vertices = QUADRANTS_0_5[quadrant as usize]; - path.reserve(quadrant_vertices.len()); - quadrant_vertices - .iter() - .for_each(|v| path.push(center + radius * *v)); - } else if radius > 5.0 && radius <= 10.0 { + path.extend(quadrant_vertices.iter().map(|v| center + radius * *v)); + } else if radius <= 10.0 { let quadrant_vertices = QUADRANTS_5_10[quadrant as usize]; - path.reserve(quadrant_vertices.len()); - quadrant_vertices - .iter() - .for_each(|v| path.push(center + radius * *v)); + path.extend(quadrant_vertices.iter().map(|v| center + radius * *v)); } else { let quadrant_vertices = QUADRANTS_10_20[quadrant as usize]; - path.reserve(quadrant_vertices.len()); - quadrant_vertices - .iter() - .for_each(|v| path.push(center + radius * *v)); + path.extend(quadrant_vertices.iter().map(|v| center + radius * *v)); } } From 2880f1300401f20fd623b6172a5c706dd22d732b Mon Sep 17 00:00:00 2001 From: Emil Ernerfeldt Date: Sat, 30 Apr 2022 12:12:49 +0200 Subject: [PATCH 3/5] silence clippy --- epaint/src/tessellator.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/epaint/src/tessellator.rs b/epaint/src/tessellator.rs index 12dcbb6dbf6..dd4e9d06133 100644 --- a/epaint/src/tessellator.rs +++ b/epaint/src/tessellator.rs @@ -192,6 +192,7 @@ pub mod path { use super::*; + #[allow(clippy::approx_constant)] mod precomputed_quadrants { use emath::{vec2, Vec2}; From 2dab8d5350deadcd2af5c45d78037fa656d83ec8 Mon Sep 17 00:00:00 2001 From: Emil Ernerfeldt Date: Sat, 30 Apr 2022 12:52:52 +0200 Subject: [PATCH 4/5] Use the same precomputed vertices for circle quadrants and for circles --- epaint/src/tessellator.rs | 470 +++++++++++++++++++++++++++----------- 1 file changed, 341 insertions(+), 129 deletions(-) diff --git a/epaint/src/tessellator.rs b/epaint/src/tessellator.rs index dd4e9d06133..f6e84a5d1c7 100644 --- a/epaint/src/tessellator.rs +++ b/epaint/src/tessellator.rs @@ -7,7 +7,293 @@ use crate::*; use emath::*; -use std::f32::consts::TAU; + +// ---------------------------------------------------------------------------- + +#[allow(clippy::approx_constant)] +mod precomputed_vertices { + /* + fn main() { + let n = 64; + println!("pub const CIRCLE_{}: [Vec2; {}] = [", n, n+1); + for i in 0..=n { + let a = std::f64::consts::TAU * i as f64 / n as f64; + println!(" vec2({:.06}, {:.06}),", a.cos(), a.sin()); + } + println!("];") + } + */ + + use emath::{vec2, Vec2}; + + pub const CIRCLE_8: [Vec2; 9] = [ + vec2(1.000000, 0.000000), + vec2(0.707107, 0.707107), + vec2(0.000000, 1.000000), + vec2(-0.707107, 0.707107), + vec2(-1.000000, 0.000000), + vec2(-0.707107, -0.707107), + vec2(0.000000, -1.000000), + vec2(0.707107, -0.707107), + vec2(1.000000, 0.000000), + ]; + + pub const CIRCLE_16: [Vec2; 17] = [ + vec2(1.000000, 0.000000), + vec2(0.923880, 0.382683), + vec2(0.707107, 0.707107), + vec2(0.382683, 0.923880), + vec2(0.000000, 1.000000), + vec2(-0.382684, 0.923880), + vec2(-0.707107, 0.707107), + vec2(-0.923880, 0.382683), + vec2(-1.000000, 0.000000), + vec2(-0.923880, -0.382683), + vec2(-0.707107, -0.707107), + vec2(-0.382684, -0.923880), + vec2(0.000000, -1.000000), + vec2(0.382684, -0.923879), + vec2(0.707107, -0.707107), + vec2(0.923880, -0.382683), + vec2(1.000000, 0.000000), + ]; + + pub const CIRCLE_32: [Vec2; 33] = [ + vec2(1.000000, 0.000000), + vec2(0.980785, 0.195090), + vec2(0.923880, 0.382683), + vec2(0.831470, 0.555570), + vec2(0.707107, 0.707107), + vec2(0.555570, 0.831470), + vec2(0.382683, 0.923880), + vec2(0.195090, 0.980785), + vec2(0.000000, 1.000000), + vec2(-0.195090, 0.980785), + vec2(-0.382683, 0.923880), + vec2(-0.555570, 0.831470), + vec2(-0.707107, 0.707107), + vec2(-0.831470, 0.555570), + vec2(-0.923880, 0.382683), + vec2(-0.980785, 0.195090), + vec2(-1.000000, 0.000000), + vec2(-0.980785, -0.195090), + vec2(-0.923880, -0.382683), + vec2(-0.831470, -0.555570), + vec2(-0.707107, -0.707107), + vec2(-0.555570, -0.831470), + vec2(-0.382683, -0.923880), + vec2(-0.195090, -0.980785), + vec2(-0.000000, -1.000000), + vec2(0.195090, -0.980785), + vec2(0.382683, -0.923880), + vec2(0.555570, -0.831470), + vec2(0.707107, -0.707107), + vec2(0.831470, -0.555570), + vec2(0.923880, -0.382683), + vec2(0.980785, -0.195090), + vec2(1.000000, -0.000000), + ]; + + pub const CIRCLE_64: [Vec2; 65] = [ + vec2(1.000000, 0.000000), + vec2(0.995185, 0.098017), + vec2(0.980785, 0.195090), + vec2(0.956940, 0.290285), + vec2(0.923880, 0.382683), + vec2(0.881921, 0.471397), + vec2(0.831470, 0.555570), + vec2(0.773010, 0.634393), + vec2(0.707107, 0.707107), + vec2(0.634393, 0.773010), + vec2(0.555570, 0.831470), + vec2(0.471397, 0.881921), + vec2(0.382683, 0.923880), + vec2(0.290285, 0.956940), + vec2(0.195090, 0.980785), + vec2(0.098017, 0.995185), + vec2(0.000000, 1.000000), + vec2(-0.098017, 0.995185), + vec2(-0.195090, 0.980785), + vec2(-0.290285, 0.956940), + vec2(-0.382683, 0.923880), + vec2(-0.471397, 0.881921), + vec2(-0.555570, 0.831470), + vec2(-0.634393, 0.773010), + vec2(-0.707107, 0.707107), + vec2(-0.773010, 0.634393), + vec2(-0.831470, 0.555570), + vec2(-0.881921, 0.471397), + vec2(-0.923880, 0.382683), + vec2(-0.956940, 0.290285), + vec2(-0.980785, 0.195090), + vec2(-0.995185, 0.098017), + vec2(-1.000000, 0.000000), + vec2(-0.995185, -0.098017), + vec2(-0.980785, -0.195090), + vec2(-0.956940, -0.290285), + vec2(-0.923880, -0.382683), + vec2(-0.881921, -0.471397), + vec2(-0.831470, -0.555570), + vec2(-0.773010, -0.634393), + vec2(-0.707107, -0.707107), + vec2(-0.634393, -0.773010), + vec2(-0.555570, -0.831470), + vec2(-0.471397, -0.881921), + vec2(-0.382683, -0.923880), + vec2(-0.290285, -0.956940), + vec2(-0.195090, -0.980785), + vec2(-0.098017, -0.995185), + vec2(-0.000000, -1.000000), + vec2(0.098017, -0.995185), + vec2(0.195090, -0.980785), + vec2(0.290285, -0.956940), + vec2(0.382683, -0.923880), + vec2(0.471397, -0.881921), + vec2(0.555570, -0.831470), + vec2(0.634393, -0.773010), + vec2(0.707107, -0.707107), + vec2(0.773010, -0.634393), + vec2(0.831470, -0.555570), + vec2(0.881921, -0.471397), + vec2(0.923880, -0.382683), + vec2(0.956940, -0.290285), + vec2(0.980785, -0.195090), + vec2(0.995185, -0.098017), + vec2(1.000000, -0.000000), + ]; + + pub const CIRCLE_128: [Vec2; 129] = [ + vec2(1.000000, 0.000000), + vec2(0.998795, 0.049068), + vec2(0.995185, 0.098017), + vec2(0.989177, 0.146730), + vec2(0.980785, 0.195090), + vec2(0.970031, 0.242980), + vec2(0.956940, 0.290285), + vec2(0.941544, 0.336890), + vec2(0.923880, 0.382683), + vec2(0.903989, 0.427555), + vec2(0.881921, 0.471397), + vec2(0.857729, 0.514103), + vec2(0.831470, 0.555570), + vec2(0.803208, 0.595699), + vec2(0.773010, 0.634393), + vec2(0.740951, 0.671559), + vec2(0.707107, 0.707107), + vec2(0.671559, 0.740951), + vec2(0.634393, 0.773010), + vec2(0.595699, 0.803208), + vec2(0.555570, 0.831470), + vec2(0.514103, 0.857729), + vec2(0.471397, 0.881921), + vec2(0.427555, 0.903989), + vec2(0.382683, 0.923880), + vec2(0.336890, 0.941544), + vec2(0.290285, 0.956940), + vec2(0.242980, 0.970031), + vec2(0.195090, 0.980785), + vec2(0.146730, 0.989177), + vec2(0.098017, 0.995185), + vec2(0.049068, 0.998795), + vec2(0.000000, 1.000000), + vec2(-0.049068, 0.998795), + vec2(-0.098017, 0.995185), + vec2(-0.146730, 0.989177), + vec2(-0.195090, 0.980785), + vec2(-0.242980, 0.970031), + vec2(-0.290285, 0.956940), + vec2(-0.336890, 0.941544), + vec2(-0.382683, 0.923880), + vec2(-0.427555, 0.903989), + vec2(-0.471397, 0.881921), + vec2(-0.514103, 0.857729), + vec2(-0.555570, 0.831470), + vec2(-0.595699, 0.803208), + vec2(-0.634393, 0.773010), + vec2(-0.671559, 0.740951), + vec2(-0.707107, 0.707107), + vec2(-0.740951, 0.671559), + vec2(-0.773010, 0.634393), + vec2(-0.803208, 0.595699), + vec2(-0.831470, 0.555570), + vec2(-0.857729, 0.514103), + vec2(-0.881921, 0.471397), + vec2(-0.903989, 0.427555), + vec2(-0.923880, 0.382683), + vec2(-0.941544, 0.336890), + vec2(-0.956940, 0.290285), + vec2(-0.970031, 0.242980), + vec2(-0.980785, 0.195090), + vec2(-0.989177, 0.146730), + vec2(-0.995185, 0.098017), + vec2(-0.998795, 0.049068), + vec2(-1.000000, 0.000000), + vec2(-0.998795, -0.049068), + vec2(-0.995185, -0.098017), + vec2(-0.989177, -0.146730), + vec2(-0.980785, -0.195090), + vec2(-0.970031, -0.242980), + vec2(-0.956940, -0.290285), + vec2(-0.941544, -0.336890), + vec2(-0.923880, -0.382683), + vec2(-0.903989, -0.427555), + vec2(-0.881921, -0.471397), + vec2(-0.857729, -0.514103), + vec2(-0.831470, -0.555570), + vec2(-0.803208, -0.595699), + vec2(-0.773010, -0.634393), + vec2(-0.740951, -0.671559), + vec2(-0.707107, -0.707107), + vec2(-0.671559, -0.740951), + vec2(-0.634393, -0.773010), + vec2(-0.595699, -0.803208), + vec2(-0.555570, -0.831470), + vec2(-0.514103, -0.857729), + vec2(-0.471397, -0.881921), + vec2(-0.427555, -0.903989), + vec2(-0.382683, -0.923880), + vec2(-0.336890, -0.941544), + vec2(-0.290285, -0.956940), + vec2(-0.242980, -0.970031), + vec2(-0.195090, -0.980785), + vec2(-0.146730, -0.989177), + vec2(-0.098017, -0.995185), + vec2(-0.049068, -0.998795), + vec2(-0.000000, -1.000000), + vec2(0.049068, -0.998795), + vec2(0.098017, -0.995185), + vec2(0.146730, -0.989177), + vec2(0.195090, -0.980785), + vec2(0.242980, -0.970031), + vec2(0.290285, -0.956940), + vec2(0.336890, -0.941544), + vec2(0.382683, -0.923880), + vec2(0.427555, -0.903989), + vec2(0.471397, -0.881921), + vec2(0.514103, -0.857729), + vec2(0.555570, -0.831470), + vec2(0.595699, -0.803208), + vec2(0.634393, -0.773010), + vec2(0.671559, -0.740951), + vec2(0.707107, -0.707107), + vec2(0.740951, -0.671559), + vec2(0.773010, -0.634393), + vec2(0.803208, -0.595699), + vec2(0.831470, -0.555570), + vec2(0.857729, -0.514103), + vec2(0.881921, -0.471397), + vec2(0.903989, -0.427555), + vec2(0.923880, -0.382683), + vec2(0.941544, -0.336890), + vec2(0.956940, -0.290285), + vec2(0.970031, -0.242980), + vec2(0.980785, -0.195090), + vec2(0.989177, -0.146730), + vec2(0.995185, -0.098017), + vec2(0.998795, -0.049068), + vec2(1.000000, -0.000000), + ]; +} // ---------------------------------------------------------------------------- @@ -50,13 +336,36 @@ impl Path { } pub fn add_circle(&mut self, center: Pos2, radius: f32) { - let n = (radius * 4.0).round() as i32; // TODO: tweak a bit more - let n = n.clamp(4, 64); - self.reserve(n as usize); - for i in 0..n { - let angle = remap(i as f32, 0.0..=n as f32, 0.0..=TAU); - let normal = vec2(angle.cos(), angle.sin()); - self.add_point(center + radius * normal, normal); + use precomputed_vertices::*; + + // These cutoffs are based on a high-dpi display. TODO: use pixels_per_point here? + // same cutoffs as in add_circle_quadrant + + if radius <= 2.0 { + self.0.extend(CIRCLE_8.iter().map(|&n| PathPoint { + pos: center + radius * n, + normal: n, + })); + } else if radius <= 5.0 { + self.0.extend(CIRCLE_16.iter().map(|&n| PathPoint { + pos: center + radius * n, + normal: n, + })); + } else if radius < 18.0 { + self.0.extend(CIRCLE_32.iter().map(|&n| PathPoint { + pos: center + radius * n, + normal: n, + })); + } else if radius < 50.0 { + self.0.extend(CIRCLE_64.iter().map(|&n| PathPoint { + pos: center + radius * n, + normal: n, + })); + } else { + self.0.extend(CIRCLE_128.iter().map(|&n| PathPoint { + pos: center + radius * n, + normal: n, + })); } } @@ -189,120 +498,7 @@ impl Path { pub mod path { //! Helpers for constructing paths use crate::shape::Rounding; - - use super::*; - - #[allow(clippy::approx_constant)] - mod precomputed_quadrants { - use emath::{vec2, Vec2}; - - pub const QUADRANTS_0_5: [[Vec2; 3]; 4] = [ - // quadrant 0: right bottom - [ - vec2(1.000000, 0.000000), - vec2(0.707107, 0.707107), - vec2(-0.000000, 1.000000), - ], - // quadrant 1: left bottom - [ - vec2(-0.000000, 1.000000), - vec2(-0.707107, 0.707107), - vec2(-1.000000, -0.000000), - ], - // quadrant 2: left top - [ - vec2(-1.000000, -0.000000), - vec2(-0.707107, -0.707107), - vec2(0.000000, -1.000000), - ], - // quadrant 3: right top - [ - vec2(0.000000, -1.000000), - vec2(0.707107, -0.707107), - vec2(1.000000, 0.000000), - ], - ]; - - pub const QUADRANTS_5_10: [[Vec2; 5]; 4] = [ - // quadrant 0: right bottom - [ - vec2(1.000000, 0.000000), - vec2(0.923880, 0.382683), - vec2(0.707107, 0.707107), - vec2(0.382683, 0.923880), - vec2(-0.000000, 1.000000), - ], - // quadrant 1: left bottom - [ - vec2(-0.000000, 1.000000), - vec2(-0.382684, 0.923880), - vec2(-0.707107, 0.707107), - vec2(-0.923880, 0.382683), - vec2(-1.000000, -0.000000), - ], - // quadrant 2: left top - [ - vec2(-1.000000, -0.000000), - vec2(-0.923880, -0.382683), - vec2(-0.707107, -0.707107), - vec2(-0.382684, -0.923880), - vec2(0.000000, -1.000000), - ], - // quadrant 3: right top - [ - vec2(0.000000, -1.000000), - vec2(0.382684, -0.923879), - vec2(0.707107, -0.707107), - vec2(0.923880, -0.382683), - vec2(1.000000, 0.000000), - ], - ]; - - pub const QUADRANTS_10_20: [[Vec2; 7]; 4] = [ - // quadrant 0: right bottom - [ - vec2(1.000000, 0.000000), - vec2(0.965926, 0.258819), - vec2(0.866025, 0.500000), - vec2(0.707107, 0.707107), - vec2(0.500000, 0.866025), - vec2(0.258819, 0.965926), - vec2(-0.000000, 1.000000), - ], - // quadrant 1: left bottom - [ - vec2(-0.000000, 1.000000), - vec2(-0.258819, 0.965926), - vec2(-0.500000, 0.866025), - vec2(-0.707107, 0.707107), - vec2(-0.866025, 0.500000), - vec2(-0.965926, 0.258819), - vec2(-1.000000, -0.000000), - ], - // quadrant 2: left top - [ - vec2(-1.000000, -0.000000), - vec2(-0.965926, -0.258819), - vec2(-0.866026, -0.500000), - vec2(-0.707107, -0.707107), - vec2(-0.500000, -0.866025), - vec2(-0.258819, -0.965926), - vec2(0.000000, -1.000000), - ], - // quadrant 3: right top - [ - vec2(0.000000, -1.000000), - vec2(0.258819, -0.965926), - vec2(0.500000, -0.866025), - vec2(0.707107, -0.707107), - vec2(0.866025, -0.500000), - vec2(0.965926, -0.258819), - vec2(1.000000, 0.000000), - ], - ]; - } - - use precomputed_quadrants::*; + use emath::*; /// overwrites existing points pub fn rounded_rectangle(path: &mut Vec, rect: Rect, rounding: Rounding) { @@ -348,17 +544,33 @@ pub mod path { // - quadrant 3: right top // * angle 4 * TAU / 4 = right pub fn add_circle_quadrant(path: &mut Vec, center: Pos2, radius: f32, quadrant: f32) { + use super::precomputed_vertices::*; + + // These cutoffs are based on a high-dpi display. TODO: use pixels_per_point here? + // same cutoffs as in add_circle + if radius <= 0.0 { path.push(center); + } else if radius <= 2.0 { + let offset = quadrant as usize * 2; + let quadrant_vertices = &CIRCLE_8[offset..=offset + 2]; + path.extend(quadrant_vertices.iter().map(|&n| center + radius * n)); } else if radius <= 5.0 { - let quadrant_vertices = QUADRANTS_0_5[quadrant as usize]; - path.extend(quadrant_vertices.iter().map(|v| center + radius * *v)); - } else if radius <= 10.0 { - let quadrant_vertices = QUADRANTS_5_10[quadrant as usize]; - path.extend(quadrant_vertices.iter().map(|v| center + radius * *v)); + let offset = quadrant as usize * 4; + let quadrant_vertices = &CIRCLE_16[offset..=offset + 4]; + path.extend(quadrant_vertices.iter().map(|&n| center + radius * n)); + } else if radius < 18.0 { + let offset = quadrant as usize * 8; + let quadrant_vertices = &CIRCLE_32[offset..=offset + 8]; + path.extend(quadrant_vertices.iter().map(|&n| center + radius * n)); + } else if radius < 50.0 { + let offset = quadrant as usize * 16; + let quadrant_vertices = &CIRCLE_64[offset..=offset + 16]; + path.extend(quadrant_vertices.iter().map(|&n| center + radius * n)); } else { - let quadrant_vertices = QUADRANTS_10_20[quadrant as usize]; - path.extend(quadrant_vertices.iter().map(|v| center + radius * *v)); + let offset = quadrant as usize * 32; + let quadrant_vertices = &CIRCLE_128[offset..=offset + 32]; + path.extend(quadrant_vertices.iter().map(|&n| center + radius * n)); } } From 5933e726ddb2a7c8c7d8d65a1b2587097462bdd8 Mon Sep 17 00:00:00 2001 From: Emil Ernerfeldt Date: Sat, 30 Apr 2022 12:57:58 +0200 Subject: [PATCH 5/5] Update epaint changelog --- epaint/CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/epaint/CHANGELOG.md b/epaint/CHANGELOG.md index 278d6ebfa29..a20336772d6 100644 --- a/epaint/CHANGELOG.md +++ b/epaint/CHANGELOG.md @@ -21,6 +21,7 @@ All notable changes to the epaint crate will be documented in this file. * MSRV (Minimum Supported Rust Version) is now `1.60.0` ([#1467](https://github.com/emilk/egui/pull/1467)). * Renamed the feature `convert_bytemuck` to `bytemuck` ([#1467](https://github.com/emilk/egui/pull/1467)). * Renamed the feature `serialize` to `serde` ([#1467](https://github.com/emilk/egui/pull/1467)). +* Optimize tessellation of circles and boxes with rounded corners ([#1547](https://github.com/emilk/egui/pull/1547)). ## 0.17.0 - 2022-02-22