Rename `partitionfinder` to `partitioner` and remove the old tessellator
This commit is contained in:
parent
ef040b61bf
commit
95b356435e
|
@ -1,10 +1,10 @@
|
||||||
[package]
|
[package]
|
||||||
name = "partitionfinder"
|
name = "pathfinder_partitioner"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
authors = ["Patrick Walton <pcwalton@mimiga.net>"]
|
authors = ["Patrick Walton <pcwalton@mimiga.net>"]
|
||||||
|
|
||||||
[lib]
|
[lib]
|
||||||
name = "partitionfinder"
|
name = "pathfinder_partitioner"
|
||||||
crate-type = ["dylib", "rlib"]
|
crate-type = ["dylib", "rlib"]
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
|
@ -1,14 +1,12 @@
|
||||||
// partitionfinder/capi.rs
|
// partitionfinder/capi.rs
|
||||||
|
|
||||||
use env_logger;
|
use env_logger;
|
||||||
use euclid::{Point2D, Transform2D};
|
use euclid::Point2D;
|
||||||
use legalizer::Legalizer;
|
use legalizer::Legalizer;
|
||||||
use partitioner::Partitioner;
|
use partitioner::Partitioner;
|
||||||
use tessellator::{QuadTessLevels, Tessellator};
|
|
||||||
use std::mem;
|
use std::mem;
|
||||||
use std::slice;
|
use std::slice;
|
||||||
use {AntialiasingMode, BQuad, BVertex, CurveIndices, EdgeInstance, Endpoint, LineIndices};
|
use {BQuad, BVertex, CurveIndices, Endpoint, LineIndices, Subpath};
|
||||||
use {Subpath, Vertex};
|
|
||||||
|
|
||||||
#[derive(Clone, Copy)]
|
#[derive(Clone, Copy)]
|
||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
|
@ -221,95 +219,6 @@ pub unsafe extern fn pf_partitioner_edge_indices<'a>(partitioner: *const Partiti
|
||||||
(*out_edge_indices).lower_curve_indices_len = edge_indices.lower_curve_indices.len() as u32;
|
(*out_edge_indices).lower_curve_indices_len = edge_indices.lower_curve_indices.len() as u32;
|
||||||
}
|
}
|
||||||
|
|
||||||
#[no_mangle]
|
|
||||||
pub unsafe extern fn pf_tessellator_new(antialiasing_mode: AntialiasingMode)
|
|
||||||
-> *mut Tessellator<'static> {
|
|
||||||
let mut tessellator = Box::new(Tessellator::new(antialiasing_mode));
|
|
||||||
let tessellator_ptr: *mut Tessellator<'static> = &mut *tessellator;
|
|
||||||
mem::forget(tessellator);
|
|
||||||
tessellator_ptr
|
|
||||||
}
|
|
||||||
|
|
||||||
#[no_mangle]
|
|
||||||
pub unsafe extern fn pf_tessellator_destroy<'a>(tessellator: *mut Tessellator<'a>) {
|
|
||||||
drop(mem::transmute::<*mut Tessellator<'a>, Box<Tessellator>>(tessellator))
|
|
||||||
}
|
|
||||||
|
|
||||||
#[no_mangle]
|
|
||||||
pub unsafe extern fn pf_tessellator_init<'a>(tessellator: *mut Tessellator<'a>,
|
|
||||||
b_quads: *const BQuad,
|
|
||||||
b_quad_count: u32,
|
|
||||||
b_vertices: *const BVertex,
|
|
||||||
b_vertex_count: u32,
|
|
||||||
b_indices: *const u32,
|
|
||||||
b_index_count: u32) {
|
|
||||||
// FIXME(pcwalton): This is unsafe! `Point2D<f32>` and `Point2DF32` may have different layouts!
|
|
||||||
(*tessellator).init(slice::from_raw_parts(b_quads, b_quad_count as usize),
|
|
||||||
slice::from_raw_parts(b_vertices as *const BVertex,
|
|
||||||
b_vertex_count as usize),
|
|
||||||
slice::from_raw_parts(b_indices as *const u32, b_index_count as usize))
|
|
||||||
}
|
|
||||||
|
|
||||||
#[no_mangle]
|
|
||||||
pub unsafe extern fn pf_tessellator_compute_hull<'a>(tessellator: *mut Tessellator<'a>,
|
|
||||||
transform: *const Matrix2DF32) {
|
|
||||||
(*tessellator).compute_hull(&Transform2D::column_major((*transform).m00,
|
|
||||||
(*transform).m01,
|
|
||||||
(*transform).m02,
|
|
||||||
(*transform).m10,
|
|
||||||
(*transform).m11,
|
|
||||||
(*transform).m12))
|
|
||||||
}
|
|
||||||
|
|
||||||
#[no_mangle]
|
|
||||||
pub unsafe extern fn pf_tessellator_compute_domain<'a>(tessellator: *mut Tessellator<'a>) {
|
|
||||||
(*tessellator).compute_domain()
|
|
||||||
}
|
|
||||||
|
|
||||||
#[no_mangle]
|
|
||||||
pub unsafe extern fn pf_tessellator_tess_levels<'a>(tessellator: *mut Tessellator<'a>,
|
|
||||||
out_tess_levels_count: *mut u32)
|
|
||||||
-> *const QuadTessLevels {
|
|
||||||
let tess_levels = (*tessellator).tess_levels();
|
|
||||||
if !out_tess_levels_count.is_null() {
|
|
||||||
*out_tess_levels_count = tess_levels.len() as u32
|
|
||||||
}
|
|
||||||
tess_levels.as_ptr()
|
|
||||||
}
|
|
||||||
|
|
||||||
#[no_mangle]
|
|
||||||
pub unsafe extern fn pf_tessellator_vertices<'a>(tessellator: *mut Tessellator<'a>,
|
|
||||||
out_vertex_count: *mut u32)
|
|
||||||
-> *const Vertex {
|
|
||||||
let vertices = (*tessellator).vertices();
|
|
||||||
if !out_vertex_count.is_null() {
|
|
||||||
*out_vertex_count = vertices.len() as u32
|
|
||||||
}
|
|
||||||
vertices.as_ptr()
|
|
||||||
}
|
|
||||||
|
|
||||||
#[no_mangle]
|
|
||||||
pub unsafe extern fn pf_tessellator_msaa_indices<'a>(tessellator: *mut Tessellator<'a>,
|
|
||||||
out_msaa_index_count: *mut u32)
|
|
||||||
-> *const u32 {
|
|
||||||
let msaa_indices = (*tessellator).msaa_indices();
|
|
||||||
if !out_msaa_index_count.is_null() {
|
|
||||||
*out_msaa_index_count = msaa_indices.len() as u32
|
|
||||||
}
|
|
||||||
msaa_indices.as_ptr()
|
|
||||||
}
|
|
||||||
|
|
||||||
#[no_mangle]
|
|
||||||
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
|
|
||||||
}
|
|
||||||
edge_instances.as_ptr()
|
|
||||||
}
|
|
||||||
|
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
pub unsafe extern fn pf_init_env_logger() -> u32 {
|
pub unsafe extern fn pf_init_env_logger() -> u32 {
|
||||||
env_logger::init().is_ok() as u32
|
env_logger::init().is_ok() as u32
|
|
@ -18,7 +18,6 @@ pub mod capi;
|
||||||
pub mod geometry;
|
pub mod geometry;
|
||||||
pub mod legalizer;
|
pub mod legalizer;
|
||||||
pub mod partitioner;
|
pub mod partitioner;
|
||||||
pub mod tessellator;
|
|
||||||
|
|
||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
#[derive(Debug, Clone, Copy)]
|
#[derive(Debug, Clone, Copy)]
|
||||||
|
@ -130,36 +129,6 @@ impl BVertex {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Copy, Debug)]
|
|
||||||
#[repr(C)]
|
|
||||||
pub struct Vertex {
|
|
||||||
pub left_b_vertex_index: u32,
|
|
||||||
pub control_point_b_vertex_index: u32,
|
|
||||||
pub right_b_vertex_index: u32,
|
|
||||||
pub time: f32,
|
|
||||||
pub path_id: u32,
|
|
||||||
pad: u32,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Vertex {
|
|
||||||
#[inline]
|
|
||||||
pub fn new(path_id: u32,
|
|
||||||
left_b_vertex_index: u32,
|
|
||||||
control_point_b_vertex_index: u32,
|
|
||||||
right_b_vertex_index: u32,
|
|
||||||
time: f32)
|
|
||||||
-> Vertex {
|
|
||||||
Vertex {
|
|
||||||
path_id: path_id,
|
|
||||||
left_b_vertex_index: left_b_vertex_index,
|
|
||||||
control_point_b_vertex_index: control_point_b_vertex_index,
|
|
||||||
right_b_vertex_index: right_b_vertex_index,
|
|
||||||
time: time,
|
|
||||||
pad: 0,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug, Clone, Copy)]
|
#[derive(Debug, Clone, Copy)]
|
||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
pub struct LineIndices {
|
pub struct LineIndices {
|
||||||
|
@ -198,20 +167,3 @@ impl CurveIndices {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Copy, Debug)]
|
|
||||||
#[repr(C)]
|
|
||||||
pub struct EdgeInstance {
|
|
||||||
pub left_vertex_index: u32,
|
|
||||||
pub right_vertex_index: u32,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl EdgeInstance {
|
|
||||||
#[inline]
|
|
||||||
pub fn new(left_vertex_index: u32, right_vertex_index: u32) -> EdgeInstance {
|
|
||||||
EdgeInstance {
|
|
||||||
left_vertex_index: left_vertex_index,
|
|
||||||
right_vertex_index: right_vertex_index,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,7 +1,7 @@
|
||||||
// partitionfinder/partitionfinder.h
|
// pathfinder/partitioner/partitioner.h
|
||||||
|
|
||||||
#ifndef PARTITIONFINDER_H
|
#ifndef PATHFINDER_PARTITIONER_H
|
||||||
#define PARTITIONFINDER_H
|
#define PATHFINDER_PARTITIONER_H
|
||||||
|
|
||||||
#include <limits.h>
|
#include <limits.h>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
@ -47,18 +47,6 @@ struct pf_b_vertex {
|
||||||
|
|
||||||
typedef struct pf_b_vertex pf_b_vertex_t;
|
typedef struct pf_b_vertex pf_b_vertex_t;
|
||||||
|
|
||||||
struct pf_vertex {
|
|
||||||
uint32_t left_b_vertex_index;
|
|
||||||
uint32_t control_point_b_vertex_index;
|
|
||||||
uint32_t right_b_vertex_index;
|
|
||||||
float time;
|
|
||||||
uint32_t path_id;
|
|
||||||
uint8_t bottom;
|
|
||||||
uint8_t pad0, pad1, pad2;
|
|
||||||
};
|
|
||||||
|
|
||||||
typedef struct pf_vertex pf_vertex_t;
|
|
||||||
|
|
||||||
struct pf_cover_indices {
|
struct pf_cover_indices {
|
||||||
const uint32_t *interior_indices;
|
const uint32_t *interior_indices;
|
||||||
uint32_t interior_indices_len;
|
uint32_t interior_indices_len;
|
||||||
|
@ -97,20 +85,6 @@ struct pf_edge_indices {
|
||||||
|
|
||||||
typedef struct pf_edge_indices pf_edge_indices_t;
|
typedef struct pf_edge_indices pf_edge_indices_t;
|
||||||
|
|
||||||
struct pf_edge_instance {
|
|
||||||
uint32_t left_vertex;
|
|
||||||
uint32_t right_vertex;
|
|
||||||
};
|
|
||||||
|
|
||||||
typedef struct pf_edge_instance pf_edge_instance_t;
|
|
||||||
|
|
||||||
struct pf_quad_tess_levels {
|
|
||||||
pf_float16_t outer[4];
|
|
||||||
pf_float16_t inner[2];
|
|
||||||
};
|
|
||||||
|
|
||||||
typedef struct pf_quad_tess_levels pf_quad_tess_levels_t;
|
|
||||||
|
|
||||||
struct pf_b_quad {
|
struct pf_b_quad {
|
||||||
uint32_t upper_left_vertex_index;
|
uint32_t upper_left_vertex_index;
|
||||||
uint32_t upper_control_point_vertex_index;
|
uint32_t upper_control_point_vertex_index;
|
||||||
|
@ -146,10 +120,6 @@ struct pf_partitioner;
|
||||||
|
|
||||||
typedef struct pf_partitioner pf_partitioner_t;
|
typedef struct pf_partitioner pf_partitioner_t;
|
||||||
|
|
||||||
struct pf_tessellator;
|
|
||||||
|
|
||||||
typedef struct pf_tessellator pf_tessellator_t;
|
|
||||||
|
|
||||||
pf_legalizer_t *pf_legalizer_new();
|
pf_legalizer_t *pf_legalizer_new();
|
||||||
|
|
||||||
void pf_legalizer_destroy(pf_legalizer_t *legalizer);
|
void pf_legalizer_destroy(pf_legalizer_t *legalizer);
|
||||||
|
@ -207,34 +177,6 @@ const void pf_partitioner_cover_indices(const pf_partitioner_t *partitioner,
|
||||||
const void pf_partitioner_edge_indices(const pf_partitioner_t *partitioner,
|
const void pf_partitioner_edge_indices(const pf_partitioner_t *partitioner,
|
||||||
pf_edge_indices_t *out_edge_indices);
|
pf_edge_indices_t *out_edge_indices);
|
||||||
|
|
||||||
pf_tessellator_t *pf_tessellator_new(pf_antialiasing_mode_t antialiasing_mode);
|
|
||||||
|
|
||||||
void pf_tessellator_destroy(pf_tessellator_t *tessellator);
|
|
||||||
|
|
||||||
void pf_tessellator_init(pf_tessellator_t *tessellator,
|
|
||||||
const pf_b_quad_t *b_quads,
|
|
||||||
uint32_t b_quad_count,
|
|
||||||
const pf_point2d_f32_t *b_vertices,
|
|
||||||
uint32_t b_vertex_count,
|
|
||||||
const uint32_t *b_indices,
|
|
||||||
uint32_t b_index_count);
|
|
||||||
|
|
||||||
void pf_tessellator_compute_hull(pf_tessellator_t *tessellator, const pf_matrix2d_f32_t *transform);
|
|
||||||
|
|
||||||
void pf_tessellator_compute_domain(pf_tessellator_t *tessellator);
|
|
||||||
|
|
||||||
const pf_quad_tess_levels_t *pf_tessellator_tess_levels(const pf_tessellator_t *tessellator,
|
|
||||||
uint32_t *out_tess_levels_count);
|
|
||||||
|
|
||||||
const pf_vertex_t *pf_tessellator_vertices(const pf_tessellator_t *tessellator,
|
|
||||||
uint32_t *out_vertex_count);
|
|
||||||
|
|
||||||
const uint32_t *pf_tessellator_msaa_indices(const pf_tessellator_t *tessellator,
|
|
||||||
uint32_t *out_msaa_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();
|
uint32_t pf_init_env_logger();
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
|
@ -5,7 +5,7 @@ use euclid::Point2D;
|
||||||
use geometry::{self, SubdividedQuadraticBezier};
|
use geometry::{self, SubdividedQuadraticBezier};
|
||||||
use log::LogLevel;
|
use log::LogLevel;
|
||||||
use std::collections::BinaryHeap;
|
use std::collections::BinaryHeap;
|
||||||
use std::cmp::{self, Ordering};
|
use std::cmp::Ordering;
|
||||||
use std::f32;
|
use std::f32;
|
||||||
use std::u32;
|
use std::u32;
|
||||||
use {BQuad, BVertex, BVertexKind, CurveIndices, Endpoint, LineIndices, Subpath};
|
use {BQuad, BVertex, BVertexKind, CurveIndices, Endpoint, LineIndices, Subpath};
|
|
@ -1,191 +0,0 @@
|
||||||
// partitionfinder/tessellator.rs
|
|
||||||
|
|
||||||
#![allow(dead_code)]
|
|
||||||
|
|
||||||
use euclid::Transform2D;
|
|
||||||
use half::{f16, self};
|
|
||||||
use std::cmp;
|
|
||||||
use std::u32;
|
|
||||||
use {AntialiasingMode, BQuad, BVertex, EdgeInstance, Vertex};
|
|
||||||
|
|
||||||
const TOLERANCE: f32 = 0.25;
|
|
||||||
|
|
||||||
pub struct Tessellator<'a> {
|
|
||||||
b_quads: &'a [BQuad],
|
|
||||||
b_vertices: &'a [BVertex],
|
|
||||||
b_indices: &'a [u32],
|
|
||||||
antialiasing_mode: AntialiasingMode,
|
|
||||||
|
|
||||||
tess_levels: Vec<QuadTessLevels>,
|
|
||||||
vertices: Vec<Vertex>,
|
|
||||||
msaa_indices: Vec<u32>,
|
|
||||||
edge_instances: Vec<EdgeInstance>,
|
|
||||||
}
|
|
||||||
|
|
||||||
// NB: This must match the layout of `MTLQuadTessellationFactorsHalf` in Metal in order for the
|
|
||||||
// Pathfinder demo to work.
|
|
||||||
#[derive(Clone, Copy, Debug)]
|
|
||||||
#[repr(C)]
|
|
||||||
pub struct QuadTessLevels {
|
|
||||||
pub outer: [f16; 4],
|
|
||||||
pub inner: [f16; 2],
|
|
||||||
}
|
|
||||||
|
|
||||||
impl QuadTessLevels {
|
|
||||||
fn new() -> QuadTessLevels {
|
|
||||||
QuadTessLevels {
|
|
||||||
outer: [half::consts::ZERO; 4],
|
|
||||||
inner: [half::consts::ZERO; 2],
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'a> Tessellator<'a> {
|
|
||||||
pub fn new<'b>(antialiasing_mode: AntialiasingMode) -> Tessellator<'b> {
|
|
||||||
Tessellator {
|
|
||||||
b_quads: &[],
|
|
||||||
b_vertices: &[],
|
|
||||||
b_indices: &[],
|
|
||||||
antialiasing_mode: antialiasing_mode,
|
|
||||||
|
|
||||||
tess_levels: vec![],
|
|
||||||
vertices: vec![],
|
|
||||||
msaa_indices: vec![],
|
|
||||||
edge_instances: vec![],
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn init(&mut self, b_quads: &'a [BQuad], b_vertices: &'a [BVertex], b_indices: &'a [u32]) {
|
|
||||||
self.b_quads = b_quads;
|
|
||||||
self.b_vertices = b_vertices;
|
|
||||||
self.b_indices = b_indices;
|
|
||||||
self.tess_levels = vec![QuadTessLevels::new(); b_quads.len()];
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn compute_hull(&mut self, transform: &Transform2D<f32>) {
|
|
||||||
for b_quad_index in 0..self.tess_levels.len() {
|
|
||||||
let b_quad = &self.b_quads[b_quad_index as usize];
|
|
||||||
|
|
||||||
let upper_tess_level = tess_level_for_edge(b_quad.upper_left_vertex_index,
|
|
||||||
b_quad.upper_control_point_vertex_index,
|
|
||||||
b_quad.upper_right_vertex_index,
|
|
||||||
transform,
|
|
||||||
self.b_vertices);
|
|
||||||
let lower_tess_level = tess_level_for_edge(b_quad.lower_left_vertex_index,
|
|
||||||
b_quad.lower_control_point_vertex_index,
|
|
||||||
b_quad.lower_right_vertex_index,
|
|
||||||
transform,
|
|
||||||
self.b_vertices);
|
|
||||||
|
|
||||||
// TODO(pcwalton): Use fewer thin triangles.
|
|
||||||
let mut tess_levels = &mut self.tess_levels[b_quad_index as usize];
|
|
||||||
tess_levels.outer[0] = half::consts::ONE;
|
|
||||||
tess_levels.outer[1] = f16::from_f32(upper_tess_level as f32);
|
|
||||||
tess_levels.outer[2] = half::consts::ONE;
|
|
||||||
tess_levels.outer[3] = f16::from_f32(lower_tess_level as f32);
|
|
||||||
tess_levels.inner[0] = f16::from_f32(cmp::max(upper_tess_level,
|
|
||||||
lower_tess_level) as f32);
|
|
||||||
tess_levels.inner[1] = half::consts::ZERO;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO(pcwalton): Do a better tessellation that doesn't make so many sliver triangles.
|
|
||||||
pub fn compute_domain(&mut self) {
|
|
||||||
for (b_quad_index, tess_levels) in self.tess_levels.iter().enumerate() {
|
|
||||||
let b_quad = &self.b_quads[b_quad_index as usize];
|
|
||||||
|
|
||||||
let upper_tess_level = f32::from(tess_levels.outer[1]) as u32;
|
|
||||||
let lower_tess_level = f32::from(tess_levels.outer[3]) as u32;
|
|
||||||
let tess_level = cmp::max(upper_tess_level, lower_tess_level);
|
|
||||||
|
|
||||||
let path_id = self.b_vertices[b_quad.upper_left_vertex_index as usize].path_id;
|
|
||||||
|
|
||||||
let first_upper_vertex_index = self.vertices.len() as u32;
|
|
||||||
self.vertices.extend((0..(tess_level + 1)).map(|index| {
|
|
||||||
Vertex::new(path_id,
|
|
||||||
b_quad.upper_left_vertex_index,
|
|
||||||
b_quad.upper_control_point_vertex_index,
|
|
||||||
b_quad.upper_right_vertex_index,
|
|
||||||
index as f32 / tess_level as f32)
|
|
||||||
}));
|
|
||||||
|
|
||||||
let first_lower_vertex_index = self.vertices.len() as u32;
|
|
||||||
self.vertices.extend((0..(tess_level + 1)).map(|index| {
|
|
||||||
Vertex::new(path_id,
|
|
||||||
b_quad.lower_left_vertex_index,
|
|
||||||
b_quad.lower_control_point_vertex_index,
|
|
||||||
b_quad.lower_right_vertex_index,
|
|
||||||
index as f32 / tess_level as f32)
|
|
||||||
}));
|
|
||||||
|
|
||||||
// Emit a triangle strip.
|
|
||||||
self.msaa_indices.reserve(tess_level as usize * 6);
|
|
||||||
for index in 0..tess_level {
|
|
||||||
self.msaa_indices.extend([
|
|
||||||
first_upper_vertex_index + index + 0,
|
|
||||||
first_upper_vertex_index + index + 1,
|
|
||||||
first_lower_vertex_index + index + 0,
|
|
||||||
first_upper_vertex_index + index + 1,
|
|
||||||
first_lower_vertex_index + index + 1,
|
|
||||||
first_lower_vertex_index + index + 0,
|
|
||||||
].into_iter())
|
|
||||||
}
|
|
||||||
|
|
||||||
// If ECAA is in use, then emit edge instances.
|
|
||||||
if self.antialiasing_mode == AntialiasingMode::Ecaa {
|
|
||||||
for index in 0..tess_level {
|
|
||||||
self.edge_instances.extend([
|
|
||||||
EdgeInstance::new(first_upper_vertex_index + index + 0,
|
|
||||||
first_upper_vertex_index + index + 1),
|
|
||||||
EdgeInstance::new(first_lower_vertex_index + index + 0,
|
|
||||||
first_lower_vertex_index + index + 1)
|
|
||||||
].into_iter())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline]
|
|
||||||
pub fn tess_levels(&self) -> &[QuadTessLevels] {
|
|
||||||
&self.tess_levels
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline]
|
|
||||||
pub fn vertices(&self) -> &[Vertex] {
|
|
||||||
&self.vertices
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline]
|
|
||||||
pub fn msaa_indices(&self) -> &[u32] {
|
|
||||||
&self.msaa_indices
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline]
|
|
||||||
pub fn edge_instances(&self) -> &[EdgeInstance] {
|
|
||||||
&self.edge_instances
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// http://antigrain.com/research/adaptive_bezier/
|
|
||||||
fn tess_level_for_edge(left_endpoint_index: u32,
|
|
||||||
control_point_index: u32,
|
|
||||||
right_endpoint_index: u32,
|
|
||||||
transform: &Transform2D<f32>,
|
|
||||||
b_vertices: &[BVertex])
|
|
||||||
-> u32 {
|
|
||||||
if control_point_index == u32::MAX {
|
|
||||||
return 1
|
|
||||||
}
|
|
||||||
|
|
||||||
let left_endpoint = &b_vertices[left_endpoint_index as usize].position;
|
|
||||||
let right_endpoint = &b_vertices[right_endpoint_index as usize].position;
|
|
||||||
let control_point = &b_vertices[control_point_index as usize].position;
|
|
||||||
|
|
||||||
let p0 = transform.transform_point(left_endpoint);
|
|
||||||
let p1 = transform.transform_point(control_point);
|
|
||||||
let p2 = transform.transform_point(right_endpoint);
|
|
||||||
|
|
||||||
// FIXME(pcwalton): Is this good for quadratics?
|
|
||||||
let length = (p1 - p0).length() + (p2 - p1).length();
|
|
||||||
1 + (length * TOLERANCE) as u32
|
|
||||||
}
|
|
Loading…
Reference in New Issue