diff --git a/partitionfinder/src/capi.rs b/partitionfinder/src/capi.rs index 24e84b33..3115369d 100644 --- a/partitionfinder/src/capi.rs +++ b/partitionfinder/src/capi.rs @@ -6,7 +6,7 @@ use partitioner::Partitioner; use tessellator::{QuadTessLevels, Tessellator}; use std::mem; use std::slice; -use {AntialiasingMode, BQuad, ControlPoints, Endpoint, Subpath, Vertex}; +use {AntialiasingMode, BQuad, ControlPoints, EdgeInstance, Endpoint, Subpath, Vertex}; #[derive(Clone, Copy)] #[repr(C)] @@ -138,14 +138,14 @@ pub unsafe extern fn pf_tessellator_msaa_indices<'a>(tessellator: *mut Tessellat } #[no_mangle] -pub unsafe extern fn pf_tessellator_levien_indices<'a>(tessellator: *mut Tessellator<'a>, - out_levien_index_count: *mut u32) - -> *const u32 { - let levien_indices = (*tessellator).levien_indices(); - if !out_levien_index_count.is_null() { - *out_levien_index_count = levien_indices.len() as u32 +pub unsafe extern fn pf_tessellator_edge_instances<'a>(tessellator: *mut Tessellator<'a>, + out_edge_instance_count: *mut u32) + -> *const EdgeInstance { + let edge_instances = (*tessellator).edge_instances(); + if !out_edge_instance_count.is_null() { + *out_edge_instance_count = edge_instances.len() as u32 } - levien_indices.as_ptr() + edge_instances.as_ptr() } #[no_mangle] diff --git a/partitionfinder/src/lib.rs b/partitionfinder/src/lib.rs index 540fd02a..de2f2073 100644 --- a/partitionfinder/src/lib.rs +++ b/partitionfinder/src/lib.rs @@ -82,3 +82,25 @@ impl Vertex { } } } + +#[derive(Clone, Copy, Debug)] +#[repr(C)] +pub struct EdgeInstance { + pub prev_endpoint_index: u32, + pub next_endpoint_index: u32, + pub prev_time: f32, + pub next_time: f32, +} + +impl EdgeInstance { + #[inline] + pub fn new(prev_endpoint_index: u32, next_endpoint_index: u32, prev_time: f32, next_time: f32) + -> EdgeInstance { + EdgeInstance { + prev_endpoint_index: prev_endpoint_index, + next_endpoint_index: next_endpoint_index, + prev_time: prev_time, + next_time: next_time, + } + } +} diff --git a/partitionfinder/src/partitionfinder.h b/partitionfinder/src/partitionfinder.h index 886696c2..cc1fb28f 100644 --- a/partitionfinder/src/partitionfinder.h +++ b/partitionfinder/src/partitionfinder.h @@ -38,6 +38,15 @@ struct pf_vertex { typedef struct pf_vertex pf_vertex_t; +struct pf_edge_instance { + uint32_t prev_endpoint_index; + uint32_t next_endpoint_index; + float prev_time; + float next_time; +}; + +typedef struct pf_edge_instance pf_edge_instance_t; + struct pf_quad_tess_levels { pf_float16_t outer[4]; pf_float16_t inner[2]; @@ -125,8 +134,8 @@ const pf_vertex_t *pf_tessellator_vertices(const pf_tessellator_t *tessellator, const uint32_t *pf_tessellator_msaa_indices(const pf_tessellator_t *tessellator, uint32_t *out_msaa_index_count); -const uint32_t *pf_tessellator_levien_indices(const pf_tessellator_t *tessellator, - uint32_t *out_levien_index_count); +const pf_edge_instance_t *pf_tessellator_edge_instances(const pf_tessellator_t *tessellator, + uint32_t *out_edge_instance_count); uint32_t pf_init_env_logger(); diff --git a/partitionfinder/src/tessellator.rs b/partitionfinder/src/tessellator.rs index 543cf488..80477a78 100644 --- a/partitionfinder/src/tessellator.rs +++ b/partitionfinder/src/tessellator.rs @@ -6,7 +6,7 @@ use euclid::{Length, Transform2D}; use half::{f16, self}; use std::cmp; use std::u32; -use {AntialiasingMode, BQuad, ControlPoints, Endpoint, Vertex}; +use {AntialiasingMode, BQuad, ControlPoints, EdgeInstance, Endpoint, Vertex}; const TOLERANCE: f32 = 0.25; @@ -19,7 +19,7 @@ pub struct Tessellator<'a> { tess_levels: Vec, vertices: Vec, msaa_indices: Vec, - levien_indices: Vec, + edge_instances: Vec, } // NB: This must match the layout of `MTLQuadTessellationFactorsHalf` in Metal in order for the @@ -55,7 +55,7 @@ impl<'a> Tessellator<'a> { tess_levels: vec![QuadTessLevels::new(); b_quads.len()], vertices: vec![], msaa_indices: vec![], - levien_indices: vec![], + edge_instances: vec![], } } @@ -124,6 +124,41 @@ impl<'a> Tessellator<'a> { first_lower_vertex_index + index + 0, ].into_iter()) } + + // If Levien-style antialiasing is in use, then emit edge instances. + if self.antialiasing_mode == AntialiasingMode::Levien { + let upper_left_endpoint_time: Length = Length::new(b_quad.upper_left_time); + let upper_right_endpoint_time: Length = + Length::new(b_quad.upper_right_time); + let lower_left_endpoint_time: Length = Length::new(b_quad.lower_left_time); + let lower_right_endpoint_time: Length = + Length::new(b_quad.lower_right_time); + + for index in 0..tess_level { + let left_tess_coord = index as f32 / tess_level as f32; + let right_tess_coord = (index + 1) as f32 / tess_level as f32; + + let upper_left_time = upper_left_endpoint_time.lerp(upper_right_endpoint_time, + left_tess_coord).get(); + let upper_right_time = upper_left_endpoint_time.lerp(upper_right_endpoint_time, + right_tess_coord).get(); + let lower_left_time = lower_left_endpoint_time.lerp(lower_right_endpoint_time, + left_tess_coord).get(); + let lower_right_time = lower_left_endpoint_time.lerp(lower_right_endpoint_time, + right_tess_coord).get(); + + self.edge_instances.extend([ + EdgeInstance::new(b_quad.upper_prev_endpoint, + b_quad.upper_next_endpoint, + upper_left_time, + upper_right_time), + EdgeInstance::new(b_quad.lower_prev_endpoint, + b_quad.lower_next_endpoint, + lower_left_time, + lower_right_time), + ].into_iter()) + } + } } } @@ -143,10 +178,9 @@ impl<'a> Tessellator<'a> { } #[inline] - pub fn levien_indices(&self) -> &[u32] { - &self.levien_indices + pub fn edge_instances(&self) -> &[EdgeInstance] { + &self.edge_instances } - } // http://antigrain.com/research/adaptive_bezier/