Stop clipping 3D quads over and over

This commit is contained in:
Patrick Walton 2019-02-02 13:53:04 -08:00
parent b0e91369e5
commit a5234e6695
2 changed files with 51 additions and 39 deletions

View File

@ -229,10 +229,7 @@ enum MainToSceneMsg {
}
enum SceneToMainMsg {
Render {
built_scene: BuiltScene,
tile_time: Duration,
}
Render { built_scene: BuiltScene, tile_time: Duration }
}
#[derive(Clone)]

View File

@ -68,11 +68,12 @@ impl Scene {
pub fn build_objects_sequentially(&self, build_transform: &BuildTransform, z_buffer: &ZBuffer)
-> Vec<BuiltObject> {
let build_transform = build_transform.prepare(&self.bounds);
self.objects
.iter()
.enumerate()
.map(|(object_index, object)| {
let outline = self.apply_build_transform(&object.outline, build_transform);
let outline = self.apply_build_transform(&object.outline, &build_transform);
let mut tiler = Tiler::new(
&outline,
&self.view_box,
@ -88,11 +89,12 @@ impl Scene {
pub fn build_objects(&self, build_transform: &BuildTransform, z_buffer: &ZBuffer)
-> Vec<BuiltObject> {
let build_transform = build_transform.prepare(&self.bounds);
self.objects
.par_iter()
.enumerate()
.map(|(object_index, object)| {
let outline = self.apply_build_transform(&object.outline, build_transform);
let outline = self.apply_build_transform(&object.outline, &build_transform);
let mut tiler = Tiler::new(
&outline,
&self.view_box,
@ -106,52 +108,24 @@ impl Scene {
.collect()
}
fn apply_build_transform(&self, outline: &Outline, build_transform: &BuildTransform)
fn apply_build_transform(&self, outline: &Outline, build_transform: &PreparedBuildTransform)
-> Outline {
// FIXME(pcwalton): Don't clone?
let mut outline = (*outline).clone();
match *build_transform {
BuildTransform::Perspective(ref perspective) => {
// FIXME(pcwalton): Do this only once!
let quad = self.apply_perspective_to_quad(perspective);
outline.clip_against_polygon(&quad);
PreparedBuildTransform::Perspective(ref perspective, ref quad) => {
outline.clip_against_polygon(quad);
outline.apply_perspective(perspective);
}
BuildTransform::Transform2D(ref transform) => {
PreparedBuildTransform::Transform2D(ref transform) => {
outline.transform(transform);
}
BuildTransform::None => {}
PreparedBuildTransform::None => {}
}
outline.clip_against_rect(&self.view_box);
outline.make_monotonic();
outline
}
fn apply_perspective_to_quad(&self, perspective: &Perspective) -> Vec<Point2DF32> {
let quad = self.clip_bounding_quad_with_perspective(perspective);
let inverse_transform = perspective.transform.inverse();
quad.into_iter()
.map(|point| inverse_transform.transform_point(point).perspective_divide().to_2d())
.collect()
}
fn clip_bounding_quad_with_perspective(&self, perspective: &Perspective) -> Vec<Point3DF32> {
let mut points = vec![
Point3DF32::from_euclid_2d(&self.bounds.origin),
Point3DF32::from_euclid_2d(&self.bounds.top_right()),
Point3DF32::from_euclid_2d(&self.bounds.bottom_right()),
Point3DF32::from_euclid_2d(&self.bounds.bottom_left()),
];
//println!("-----");
//println!("bounds={:?} ORIGINAL quad={:?}", self.bounds, points);
for point in &mut points {
*point = perspective.transform.transform_point(*point);
}
//println!("... PERSPECTIVE quad={:?}", points);
points = PolygonClipper3D::new(points).clip();
//println!("... CLIPPED quad={:?}", points);
points.into_iter().map(|point| point.perspective_divide()).collect()
}
}
impl Debug for Scene {
@ -218,3 +192,44 @@ pub enum BuildTransform {
Transform2D(Transform2DF32),
Perspective(Perspective),
}
impl BuildTransform {
fn prepare(&self, bounds: &Rect<f32>) -> PreparedBuildTransform {
let perspective = match self {
BuildTransform::None => return PreparedBuildTransform::None,
BuildTransform::Transform2D(ref transform) => {
return PreparedBuildTransform::Transform2D(*transform)
}
BuildTransform::Perspective(ref perspective) => *perspective,
};
let mut points = vec![
Point3DF32::from_euclid_2d(&bounds.origin),
Point3DF32::from_euclid_2d(&bounds.top_right()),
Point3DF32::from_euclid_2d(&bounds.bottom_right()),
Point3DF32::from_euclid_2d(&bounds.bottom_left()),
];
//println!("-----");
//println!("bounds={:?} ORIGINAL quad={:?}", self.bounds, points);
for point in &mut points {
*point = perspective.transform.transform_point(*point);
}
//println!("... PERSPECTIVE quad={:?}", points);
points = PolygonClipper3D::new(points).clip();
//println!("... CLIPPED quad={:?}", points);
for point in &mut points {
*point = point.perspective_divide()
}
let inverse_transform = perspective.transform.inverse();
let points = points.into_iter().map(|point| {
inverse_transform.transform_point(point).perspective_divide().to_2d()
}).collect();
PreparedBuildTransform::Perspective(perspective, points)
}
}
enum PreparedBuildTransform {
None,
Transform2D(Transform2DF32),
Perspective(Perspective, Vec<Point2DF32>),
}