Add basic barrel distortion support for VR
This commit is contained in:
parent
2819a88060
commit
6ca5dc5f62
|
@ -63,6 +63,8 @@ public class PathfinderDemoActivity extends Activity {
|
|||
void setVRMode(boolean enabled) {
|
||||
try {
|
||||
setVrModeEnabled(false, mVRListenerComponentName);
|
||||
mContentView.setStereoModeEnabled(enabled);
|
||||
mContentView.setDistortionCorrectionEnabled(false);
|
||||
} catch (PackageManager.NameNotFoundException exception) {
|
||||
startActivity(new Intent(Settings.ACTION_VR_LISTENER_SETTINGS));
|
||||
}
|
||||
|
@ -77,7 +79,6 @@ public class PathfinderDemoActivity extends Activity {
|
|||
setContentView(R.layout.activity_pathfinder);
|
||||
|
||||
mContentView = findViewById(R.id.fullscreen_content);
|
||||
mContentView.setStereoModeEnabled(false);
|
||||
setVRMode(false);
|
||||
|
||||
mContentView.setEGLContextClientVersion(3);
|
||||
|
|
|
@ -21,6 +21,7 @@ use pathfinder_geometry::basic::rect::{RectF32, RectI32};
|
|||
use pathfinder_geometry::basic::transform2d::Transform2DF32;
|
||||
use pathfinder_geometry::basic::transform3d::{Perspective, Transform3DF32};
|
||||
use pathfinder_geometry::color::ColorU;
|
||||
use pathfinder_geometry::distortion::BarrelDistortionCoefficients;
|
||||
use pathfinder_gl::GLDevice;
|
||||
use pathfinder_gpu::resources::ResourceLoader;
|
||||
use pathfinder_gpu::{DepthFunc, DepthState, Device, Primitive, RenderState, StencilFunc};
|
||||
|
@ -213,6 +214,11 @@ impl<W> DemoApp<W> where W: Window {
|
|||
|
||||
let is_first_frame = self.frame_counter == 0;
|
||||
let frame_count = if is_first_frame { 2 } else { 1 };
|
||||
let barrel_distortion = match self.ui.mode {
|
||||
Mode::VR => Some(self.window.barrel_distortion_coefficients()),
|
||||
_ => None,
|
||||
};
|
||||
|
||||
for _ in 0..frame_count {
|
||||
let viewport_count = self.ui.mode.viewport_count();
|
||||
let render_transforms = iter::repeat(render_transform.clone()).take(viewport_count)
|
||||
|
@ -224,6 +230,7 @@ impl<W> DemoApp<W> where W: Window {
|
|||
} else {
|
||||
None
|
||||
},
|
||||
barrel_distortion,
|
||||
})).unwrap();
|
||||
}
|
||||
|
||||
|
@ -686,6 +693,7 @@ enum MainToSceneMsg {
|
|||
struct BuildOptions {
|
||||
render_transforms: Vec<RenderTransform>,
|
||||
stem_darkening_font_size: Option<f32>,
|
||||
barrel_distortion: Option<BarrelDistortionCoefficients>,
|
||||
}
|
||||
|
||||
struct SceneToMainMsg {
|
||||
|
@ -798,6 +806,7 @@ fn build_scene(scene: &Scene,
|
|||
Point2DF32::new(x, y).scale(font_size)
|
||||
}
|
||||
},
|
||||
barrel_distortion: build_options.barrel_distortion,
|
||||
};
|
||||
|
||||
let built_options = render_options.prepare(scene.bounds);
|
||||
|
|
|
@ -11,6 +11,7 @@
|
|||
//! A minimal cross-platform windowing layer.
|
||||
|
||||
use pathfinder_geometry::basic::point::Point2DI32;
|
||||
use pathfinder_geometry::distortion::BarrelDistortionCoefficients;
|
||||
use pathfinder_gl::GLVersion;
|
||||
use pathfinder_gpu::resources::ResourceLoader;
|
||||
use std::path::PathBuf;
|
||||
|
@ -24,6 +25,11 @@ pub trait Window {
|
|||
fn push_user_event(message_type: u32, message_data: u32);
|
||||
fn present_open_svg_dialog(&mut self);
|
||||
fn run_save_dialog(&self, extension: &str) -> Result<PathBuf, ()>;
|
||||
|
||||
#[inline]
|
||||
fn barrel_distortion_coefficients(&self) -> BarrelDistortionCoefficients {
|
||||
BarrelDistortionCoefficients::default()
|
||||
}
|
||||
}
|
||||
|
||||
pub enum Event {
|
||||
|
|
|
@ -0,0 +1,67 @@
|
|||
// pathfinder/geometry/src/distortion.rs
|
||||
//
|
||||
// Copyright © 2019 The Pathfinder Project Developers.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
use crate::basic::point::{Point2DF32, Point2DI32};
|
||||
use crate::outline::{self, Contour};
|
||||
|
||||
#[derive(Clone, Copy, Debug)]
|
||||
pub struct BarrelDistortionCoefficients {
|
||||
pub k0: f32,
|
||||
pub k1: f32,
|
||||
}
|
||||
|
||||
impl Default for BarrelDistortionCoefficients {
|
||||
// Matches Google Daydream (Cardboard v2.2).
|
||||
#[inline]
|
||||
fn default() -> BarrelDistortionCoefficients {
|
||||
BarrelDistortionCoefficients { k0: 0.34, k1: 0.55 }
|
||||
}
|
||||
}
|
||||
|
||||
pub struct ContourBarrelDistorter<'a> {
|
||||
contour: &'a mut Contour,
|
||||
window_size: Point2DI32,
|
||||
coefficients: BarrelDistortionCoefficients,
|
||||
}
|
||||
|
||||
impl<'a> ContourBarrelDistorter<'a> {
|
||||
pub fn new(contour: &'a mut Contour,
|
||||
coefficients: BarrelDistortionCoefficients,
|
||||
window_size: Point2DI32)
|
||||
-> ContourBarrelDistorter<'a> {
|
||||
ContourBarrelDistorter { contour, window_size, coefficients }
|
||||
}
|
||||
|
||||
pub fn distort(&mut self) {
|
||||
let one = Point2DF32::splat(1.0);
|
||||
let window_size = self.window_size.to_f32();
|
||||
let inv_window_size = Point2DF32(window_size.0.approx_recip());
|
||||
let BarrelDistortionCoefficients { k0, k1 } = self.coefficients;
|
||||
|
||||
let point_count = self.contour.len();
|
||||
for point_index in 0..point_count {
|
||||
// Convert from window coordinates to NDC.
|
||||
let mut position = self.contour.position_of(point_index);
|
||||
position = position.scale_xy(inv_window_size).scale(2.0) - one;
|
||||
|
||||
// Apply distortion.
|
||||
let r2 = position.square_length();
|
||||
let scaling = 1.0 + k0 * r2 + k1 * r2 * r2;
|
||||
position = position.scale(1.0 / scaling);
|
||||
|
||||
// Convert back to window coordinates.
|
||||
position = (position + one).scale(0.5).scale_xy(window_size);
|
||||
|
||||
// Store resulting point.
|
||||
self.contour.points[point_index as usize] = position;
|
||||
outline::union_rect(&mut self.contour.bounds, position, point_index == 0);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -18,6 +18,7 @@ extern crate bitflags;
|
|||
pub mod basic;
|
||||
pub mod clip;
|
||||
pub mod color;
|
||||
pub mod distortion;
|
||||
pub mod monotonic;
|
||||
pub mod orientation;
|
||||
pub mod outline;
|
||||
|
|
|
@ -11,12 +11,13 @@
|
|||
//! A compressed in-memory representation of paths.
|
||||
|
||||
use crate::basic::line_segment::LineSegmentF32;
|
||||
use crate::basic::point::Point2DF32;
|
||||
use crate::basic::point::{Point2DF32, Point2DI32};
|
||||
use crate::basic::rect::RectF32;
|
||||
use crate::basic::transform2d::Transform2DF32;
|
||||
use crate::basic::transform3d::Perspective;
|
||||
use crate::clip::{self, ContourPolygonClipper, ContourRectClipper};
|
||||
use crate::dilation::ContourDilator;
|
||||
use crate::distortion::{BarrelDistortionCoefficients, ContourBarrelDistorter};
|
||||
use crate::orientation::Orientation;
|
||||
use crate::segment::{Segment, SegmentFlags, SegmentKind};
|
||||
use std::fmt::{self, Debug, Formatter};
|
||||
|
@ -135,6 +136,17 @@ impl Outline {
|
|||
self.bounds = self.bounds.dilate(amount);
|
||||
}
|
||||
|
||||
pub fn barrel_distort(&mut self,
|
||||
coefficients: BarrelDistortionCoefficients,
|
||||
window_size: Point2DI32) {
|
||||
let mut new_bounds = None;
|
||||
for contour in &mut self.contours {
|
||||
contour.barrel_distort(coefficients, window_size);
|
||||
contour.update_bounds(&mut new_bounds);
|
||||
}
|
||||
self.bounds = new_bounds.unwrap_or_else(|| RectF32::default());
|
||||
}
|
||||
|
||||
pub fn prepare_for_tiling(&mut self, view_box: RectF32) {
|
||||
self.contours.iter_mut().for_each(|contour| contour.prepare_for_tiling(view_box));
|
||||
self.bounds = self.bounds.intersection(view_box).unwrap_or_else(|| RectF32::default());
|
||||
|
@ -419,6 +431,12 @@ impl Contour {
|
|||
self.bounds = self.bounds.dilate(amount);
|
||||
}
|
||||
|
||||
pub fn barrel_distort(&mut self,
|
||||
coefficients: BarrelDistortionCoefficients,
|
||||
window_size: Point2DI32) {
|
||||
ContourBarrelDistorter::new(self, coefficients, window_size).distort();
|
||||
}
|
||||
|
||||
fn prepare_for_tiling(&mut self, view_box: RectF32) {
|
||||
// Snap points to the view box bounds. This mops up floating point error from the clipping
|
||||
// process.
|
||||
|
@ -667,7 +685,7 @@ impl<'a> Iterator for ContourIter<'a> {
|
|||
}
|
||||
|
||||
#[inline]
|
||||
fn union_rect(bounds: &mut RectF32, new_point: Point2DF32, first: bool) {
|
||||
pub(crate) fn union_rect(bounds: &mut RectF32, new_point: Point2DF32, first: bool) {
|
||||
if first {
|
||||
*bounds = RectF32::from_points(new_point, new_point);
|
||||
} else {
|
||||
|
|
|
@ -20,6 +20,7 @@ use pathfinder_geometry::basic::rect::{RectF32, RectI32};
|
|||
use pathfinder_geometry::basic::transform2d::Transform2DF32;
|
||||
use pathfinder_geometry::basic::transform3d::Perspective;
|
||||
use pathfinder_geometry::clip::PolygonClipper3D;
|
||||
use pathfinder_geometry::distortion::BarrelDistortionCoefficients;
|
||||
use std::iter;
|
||||
use std::u16;
|
||||
|
||||
|
@ -126,6 +127,7 @@ impl SceneBuilder {
|
|||
pub struct RenderOptions {
|
||||
pub transform: RenderTransform,
|
||||
pub dilation: Point2DF32,
|
||||
pub barrel_distortion: Option<BarrelDistortionCoefficients>,
|
||||
}
|
||||
|
||||
impl RenderOptions {
|
||||
|
@ -133,6 +135,7 @@ impl RenderOptions {
|
|||
PreparedRenderOptions {
|
||||
transform: self.transform.prepare(bounds),
|
||||
dilation: self.dilation,
|
||||
barrel_distortion: self.barrel_distortion,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -201,6 +204,7 @@ impl RenderTransform {
|
|||
pub struct PreparedRenderOptions {
|
||||
pub transform: PreparedRenderTransform,
|
||||
pub dilation: Point2DF32,
|
||||
pub barrel_distortion: Option<BarrelDistortionCoefficients>,
|
||||
}
|
||||
|
||||
impl PreparedRenderOptions {
|
||||
|
@ -218,4 +222,3 @@ pub enum PreparedRenderTransform {
|
|||
Transform2D(Transform2DF32),
|
||||
Perspective { perspective: Perspective, clip_polygon: Vec<Point2DF32>, quad: [Point3DF32; 4] }
|
||||
}
|
||||
|
||||
|
|
|
@ -116,6 +116,11 @@ impl Scene {
|
|||
outline = (*original_outline).clone();
|
||||
outline.clip_against_polygon(clip_polygon);
|
||||
outline.apply_perspective(perspective);
|
||||
|
||||
// TODO(pcwalton): Support this in 2D too.
|
||||
if let Some(barrel_distortion) = options.barrel_distortion {
|
||||
outline.barrel_distort(barrel_distortion, perspective.window_size);
|
||||
}
|
||||
}
|
||||
}
|
||||
PreparedRenderTransform::Transform2D(ref transform) => {
|
||||
|
|
File diff suppressed because it is too large
Load Diff
After Width: | Height: | Size: 192 KiB |
|
@ -31,6 +31,11 @@ impl F32x4 {
|
|||
|
||||
// Basic operations
|
||||
|
||||
#[inline]
|
||||
pub fn approx_recip(self) -> F32x4 {
|
||||
F32x4([1.0 / self[0], 1.0 / self[1], 1.0 / self[2], 1.0 / self[3]])
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn min(self, other: F32x4) -> F32x4 {
|
||||
F32x4([
|
||||
|
|
|
@ -37,6 +37,11 @@ impl F32x4 {
|
|||
|
||||
// Basic operations
|
||||
|
||||
#[inline]
|
||||
pub fn approx_recip(self) -> F32x4 {
|
||||
unsafe { F32x4(x86_64::_mm_rcp_ps(self.0)) }
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn min(self, other: F32x4) -> F32x4 {
|
||||
unsafe { F32x4(x86_64::_mm_min_ps(self.0, other.0)) }
|
||||
|
|
Loading…
Reference in New Issue