Implement viewport culling (#667)

* culling is working

* fixed tests

* Ready for review

* cleanup

* code review

* Fix import

Co-authored-by: Keavon Chambers <keavon@keavon.com>
This commit is contained in:
mfish33
2022-06-10 14:38:42 -07:00
committed by Keavon Chambers
co-authored by Keavon Chambers
parent 4f968385c5
commit be717b3bd4
12 changed files with 47 additions and 27 deletions
+22 -8
View File
@@ -61,7 +61,7 @@ pub trait LayerData {
/// let mut svg = String::new();
///
/// // Render the shape without any transforms, in normal view mode
/// shape.render(&mut svg, &mut String::new(), &mut vec![], ViewMode::Normal, &Default::default());
/// shape.render(&mut svg, &mut String::new(), &mut vec![], ViewMode::Normal, &Default::default(), None);
///
/// assert_eq!(
/// svg,
@@ -70,7 +70,7 @@ pub trait LayerData {
/// </g>"
/// );
/// ```
fn render(&mut self, svg: &mut String, svg_defs: &mut String, transforms: &mut Vec<glam::DAffine2>, view_mode: ViewMode, font_cache: &FontCache);
fn render(&mut self, svg: &mut String, svg_defs: &mut String, transforms: &mut Vec<glam::DAffine2>, view_mode: ViewMode, font_cache: &FontCache, culling_bounds: Option<[DVec2; 2]>);
/// Determine the layers within this layer that intersect a given quad.
/// # Example
@@ -117,8 +117,8 @@ pub trait LayerData {
}
impl LayerData for LayerDataType {
fn render(&mut self, svg: &mut String, svg_defs: &mut String, transforms: &mut Vec<glam::DAffine2>, view_mode: ViewMode, font_cache: &FontCache) {
self.inner_mut().render(svg, svg_defs, transforms, view_mode, font_cache)
fn render(&mut self, svg: &mut String, svg_defs: &mut String, transforms: &mut Vec<glam::DAffine2>, view_mode: ViewMode, font_cache: &FontCache, viewport_bounds: Option<[DVec2; 2]>) {
self.inner_mut().render(svg, svg_defs, transforms, view_mode, font_cache, viewport_bounds)
}
fn intersects_quad(&self, quad: Quad, path: &mut Vec<LayerId>, intersections: &mut Vec<Vec<LayerId>>, font_cache: &FontCache) {
@@ -223,16 +223,29 @@ impl Layer {
LayerIter { stack: vec![self] }
}
pub fn render(&mut self, transforms: &mut Vec<DAffine2>, view_mode: ViewMode, svg_defs: &mut String, font_cache: &FontCache) -> &str {
pub fn render(&mut self, transforms: &mut Vec<DAffine2>, view_mode: ViewMode, svg_defs: &mut String, font_cache: &FontCache, culling_bounds: Option<[DVec2; 2]>) -> &str {
if !self.visible {
return "";
}
transforms.push(self.transform);
if let Some(viewport_bounds) = culling_bounds {
if let Some(bounding_box) = self.data.bounding_box(transforms.iter().cloned().reduce(|a, b| a * b).unwrap_or(DAffine2::IDENTITY), font_cache) {
let is_overlapping =
viewport_bounds[0].x < bounding_box[1].x && bounding_box[0].x < viewport_bounds[1].x && viewport_bounds[0].y < bounding_box[1].y && bounding_box[0].y < viewport_bounds[1].y;
if !is_overlapping {
transforms.pop();
self.cache.clear();
self.cache_dirty = true;
return "";
}
}
}
if self.cache_dirty {
transforms.push(self.transform);
self.thumbnail_cache.clear();
self.svg_defs_cache.clear();
self.data.render(&mut self.thumbnail_cache, &mut self.svg_defs_cache, transforms, view_mode, font_cache);
self.data.render(&mut self.thumbnail_cache, &mut self.svg_defs_cache, transforms, view_mode, font_cache, culling_bounds);
self.cache.clear();
let _ = writeln!(self.cache, r#"<g transform="matrix("#);
@@ -246,9 +259,10 @@ impl Layer {
self.opacity,
self.thumbnail_cache.as_str()
);
transforms.pop();
self.cache_dirty = false;
}
transforms.pop();
svg_defs.push_str(&self.svg_defs_cache);
self.cache.as_str()