Allow scenes to be dumped as SVG (untested) and make 3D mode optional in the demo

This commit is contained in:
Patrick Walton 2019-01-29 14:50:15 -08:00
parent ab93ea1f22
commit e958363872
4 changed files with 134 additions and 36 deletions

View File

@ -90,23 +90,35 @@ fn main() {
let window_size = Size2D::new(drawable_width, drawable_height);
let mut base_scene = load_scene(&options, &window_size);
let mut dump_transformed_scene = false;
while !exit {
let rotation = Transform3DF32::from_rotation(-camera_yaw, -camera_pitch, 0.0);
camera_position = camera_position + rotation.transform_point(camera_velocity);
let mut transform = Transform3DF32::from_perspective(FRAC_PI_4, 4.0 / 3.0, 0.01, 100.0);
transform = transform.post_mul(&Transform3DF32::from_rotation(camera_yaw,
camera_pitch,
0.0));
transform = transform.post_mul(&Transform3DF32::from_translation(-camera_position.x(),
-camera_position.y(),
-camera_position.z()));
transform = transform.post_mul(&Transform3DF32::from_scale(1.0 / 800.0, 1.0 / 800.0, 1.0));
let perspective = Perspective::new(&transform, &window_size);
let mut scene = base_scene.clone();
scene.apply_perspective(&perspective);
if options.run_in_3d {
let rotation = Transform3DF32::from_rotation(-camera_yaw, -camera_pitch, 0.0);
camera_position = camera_position + rotation.transform_point(camera_velocity);
let mut transform =
Transform3DF32::from_perspective(FRAC_PI_4, 4.0 / 3.0, 0.0001, 100.0);
transform = transform.post_mul(&Transform3DF32::from_rotation(camera_yaw,
camera_pitch,
0.0));
transform =
transform.post_mul(&Transform3DF32::from_translation(-camera_position.x(),
-camera_position.y(),
-camera_position.z()));
transform =
transform.post_mul(&Transform3DF32::from_scale(1.0 / 800.0, 1.0 / 800.0, 1.0));
let perspective = Perspective::new(&transform, &window_size);
scene.apply_perspective(&perspective);
}
if dump_transformed_scene {
println!("{:?}", scene);
dump_transformed_scene = false;
}
let built_scene = build_scene(&scene, &options);
@ -139,6 +151,9 @@ fn main() {
Event::KeyDown { keycode: Some(Keycode::D), .. } => {
camera_velocity.set_x(CAMERA_VELOCITY)
}
Event::KeyDown { keycode: Some(Keycode::T), .. } => {
dump_transformed_scene = true;
}
Event::KeyUp { keycode: Some(Keycode::W), .. } |
Event::KeyUp { keycode: Some(Keycode::S), .. } => {
camera_velocity.set_z(0.0);
@ -155,6 +170,7 @@ fn main() {
struct Options {
jobs: Option<usize>,
run_in_3d: bool,
input_path: PathBuf,
}
@ -169,6 +185,12 @@ impl Options {
.takes_value(true)
.help("Number of threads to use"),
)
.arg(
Arg::with_name("3d")
.short("3")
.long("3d")
.help("Run in 3D"),
)
.arg(
Arg::with_name("INPUT")
.help("Path to the SVG file to render")
@ -179,6 +201,7 @@ impl Options {
let jobs: Option<usize> = matches
.value_of("jobs")
.map(|string| string.parse().unwrap());
let run_in_3d = matches.is_present("3d");
let input_path = PathBuf::from(matches.value_of("INPUT").unwrap());
// Set up Rayon.
@ -188,7 +211,7 @@ impl Options {
}
thread_pool_builder.build_global().unwrap();
Options { jobs, input_path }
Options { jobs, run_in_3d, input_path }
}
}

View File

@ -21,7 +21,7 @@ use euclid::{Point2D, Rect, Size2D};
use std::fmt::{self, Debug, Formatter};
use std::mem;
#[derive(Clone, Debug)]
#[derive(Clone)]
pub struct Outline {
pub contours: Vec<Contour>,
bounds: Rect<f32>,
@ -142,6 +142,18 @@ impl Outline {
}
}
impl Debug for Outline {
fn fmt(&self, formatter: &mut Formatter) -> fmt::Result {
for (contour_index, contour) in self.contours.iter().enumerate() {
if contour_index > 0 {
write!(formatter, " ")?;
}
contour.fmt(formatter)?;
}
Ok(())
}
}
impl Contour {
#[inline]
pub fn new() -> Contour {
@ -328,27 +340,45 @@ impl Contour {
}
impl Debug for Contour {
#[inline]
fn fmt(&self, formatter: &mut Formatter) -> fmt::Result {
formatter.write_str("[")?;
if formatter.alternate() {
formatter.write_str("\n")?
}
for (index, segment) in self.iter().enumerate() {
if index > 0 {
formatter.write_str(" ")?;
for (segment_index, segment) in self.iter().enumerate() {
if segment_index == 0 {
write!(formatter,
"M {} {}",
segment.baseline.from_x(),
segment.baseline.from_y())?;
}
if formatter.alternate() {
formatter.write_str("\n ")?;
}
segment.fmt(formatter)?;
}
if formatter.alternate() {
formatter.write_str("\n")?
}
formatter.write_str("]")?;
return Ok(());
match segment.kind {
SegmentKind::None => {}
SegmentKind::Line => {
write!(formatter,
" L {} {}",
segment.baseline.to_x(),
segment.baseline.to_y())?;
}
SegmentKind::Quadratic => {
write!(formatter,
" Q {} {} {} {}",
segment.ctrl.from_x(),
segment.ctrl.from_y(),
segment.baseline.to_x(),
segment.baseline.to_y())?;
}
SegmentKind::Cubic => {
write!(formatter,
" C {} {} {} {} {} {}",
segment.ctrl.from_x(),
segment.ctrl.from_y(),
segment.ctrl.to_x(),
segment.ctrl.to_y(),
segment.baseline.to_x(),
segment.baseline.to_y())?;
}
}
}
write!(formatter, " z")
}
}

View File

@ -10,6 +10,8 @@
//! How a path is to be filled.
use std::fmt::{self, Debug, Formatter};
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
pub struct Paint {
pub color: ColorU,
@ -18,7 +20,7 @@ pub struct Paint {
#[derive(Clone, Copy, PartialEq, Debug)]
pub struct PaintId(pub u16);
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, Default)]
#[derive(Clone, Copy, PartialEq, Eq, Hash, Default)]
pub struct ColorU {
pub r: u8,
pub g: u8,
@ -38,6 +40,22 @@ impl ColorU {
}
}
impl Debug for ColorU {
fn fmt(&self, formatter: &mut Formatter) -> fmt::Result {
if self.a == 255 {
write!(formatter, "#{:02x}{:02x}{:02x}", self.r, self.g, self.b)
} else {
write!(formatter,
"rgba({}, {}, {}, {})",
self.r,
self.g,
self.b,
self.a as f32 / 255.0)
}
}
}
#[derive(Clone, Copy, Debug, PartialEq)]
pub struct ShaderId(pub u16);

View File

@ -22,8 +22,9 @@ use pathfinder_geometry::point::Point3DF32;
use pathfinder_geometry::transform3d::Perspective;
use pathfinder_geometry::transform::Transform2DF32;
use rayon::iter::{IndexedParallelIterator, IntoParallelRefIterator, ParallelIterator};
use std::fmt::{self, Debug, Formatter};
#[derive(Clone, Debug)]
#[derive(Clone)]
pub struct Scene {
pub objects: Vec<PathObject>,
pub paints: Vec<Paint>,
@ -162,6 +163,27 @@ impl Scene {
}
}
impl Debug for Scene {
fn fmt(&self, formatter: &mut Formatter) -> fmt::Result {
writeln!(formatter,
"<svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"{} {} {} {}\">",
self.view_box.origin.x,
self.view_box.origin.y,
self.view_box.size.width,
self.view_box.size.height)?;
for object in &self.objects {
let paint = &self.paints[object.paint.0 as usize];
write!(formatter, " <path")?;
if !object.name.is_empty() {
write!(formatter, " id=\"{}\"", object.name)?;
}
writeln!(formatter, " fill=\"{:?}\" d=\"{:?}\" />", paint.color, object.outline)?;
}
writeln!(formatter, "</svg>")?;
Ok(())
}
}
#[derive(Clone, Debug)]
pub struct PathObject {
outline: Outline,
@ -187,6 +209,11 @@ impl PathObject {
kind,
}
}
#[inline]
pub fn outline(&self) -> &Outline {
&self.outline
}
}
#[inline]