Move the demo camera code into its own module
This commit is contained in:
parent
5e64876579
commit
29b137c81d
|
@ -0,0 +1,195 @@
|
||||||
|
// pathfinder/demo/common/src/camera.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.
|
||||||
|
|
||||||
|
//! Camera management code for the demo.
|
||||||
|
|
||||||
|
// TODO(#140, pcwalton): Move some of this out of the demo and into the library
|
||||||
|
// proper.
|
||||||
|
|
||||||
|
use crate::window::{OcularTransform, View};
|
||||||
|
use pathfinder_geometry::basic::point::{Point2DF32, Point2DI32, Point3DF32};
|
||||||
|
use pathfinder_geometry::basic::rect::RectF32;
|
||||||
|
use pathfinder_geometry::basic::transform2d::Transform2DF32;
|
||||||
|
use pathfinder_geometry::basic::transform3d::{Perspective, Transform3DF32};
|
||||||
|
use std::f32::consts::FRAC_PI_4;
|
||||||
|
|
||||||
|
const NEAR_CLIP_PLANE: f32 = 0.01;
|
||||||
|
const FAR_CLIP_PLANE: f32 = 10.0;
|
||||||
|
|
||||||
|
// Half of the eye separation distance.
|
||||||
|
const DEFAULT_EYE_OFFSET: f32 = 0.025;
|
||||||
|
|
||||||
|
pub enum Camera {
|
||||||
|
TwoD(Transform2DF32),
|
||||||
|
ThreeD {
|
||||||
|
// The ocular transform used for rendering of the scene to the scene framebuffer. If we are
|
||||||
|
// performing stereoscopic rendering, this is then reprojected according to the eye
|
||||||
|
// transforms below.
|
||||||
|
scene_transform: OcularTransform,
|
||||||
|
// For each eye, the perspective from camera coordinates to display coordinates,
|
||||||
|
// and the view transform from world coordinates to camera coordinates.
|
||||||
|
eye_transforms: Vec<OcularTransform>,
|
||||||
|
// The modelview transform from world coordinates to SVG coordinates
|
||||||
|
modelview_transform: CameraTransform3D,
|
||||||
|
// The camera's velocity (in world coordinates)
|
||||||
|
velocity: Point3DF32,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Camera {
|
||||||
|
pub fn new(mode: Mode, view_box: RectF32, viewport_size: Point2DI32) -> Camera {
|
||||||
|
if mode == Mode::TwoD {
|
||||||
|
Camera::new_2d(view_box, viewport_size)
|
||||||
|
} else {
|
||||||
|
Camera::new_3d(mode, view_box, viewport_size)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn new_2d(view_box: RectF32, viewport_size: Point2DI32) -> Camera {
|
||||||
|
let scale = i32::min(viewport_size.x(), viewport_size.y()) as f32
|
||||||
|
* scale_factor_for_view_box(view_box);
|
||||||
|
let origin = viewport_size.to_f32().scale(0.5) - view_box.size().scale(scale * 0.5);
|
||||||
|
Camera::TwoD(Transform2DF32::from_scale(&Point2DF32::splat(scale)).post_translate(origin))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn new_3d(mode: Mode, view_box: RectF32, viewport_size: Point2DI32) -> Camera {
|
||||||
|
let viewport_count = mode.viewport_count();
|
||||||
|
|
||||||
|
let fov_y = FRAC_PI_4;
|
||||||
|
let aspect = viewport_size.x() as f32 / viewport_size.y() as f32;
|
||||||
|
let projection =
|
||||||
|
Transform3DF32::from_perspective(fov_y, aspect, NEAR_CLIP_PLANE, FAR_CLIP_PLANE);
|
||||||
|
let perspective = Perspective::new(&projection, viewport_size);
|
||||||
|
|
||||||
|
// Create a scene transform by moving the camera back from the center of the eyes so that
|
||||||
|
// its field of view encompasses the field of view of both eyes.
|
||||||
|
let z_offset = -DEFAULT_EYE_OFFSET * projection.c0.x();
|
||||||
|
let scene_transform = OcularTransform {
|
||||||
|
perspective,
|
||||||
|
modelview_to_eye: Transform3DF32::from_translation(0.0, 0.0, z_offset),
|
||||||
|
};
|
||||||
|
|
||||||
|
// For now, initialize the eye transforms as copies of the scene transform.
|
||||||
|
let eye_offset = DEFAULT_EYE_OFFSET;
|
||||||
|
let eye_transforms = (0..viewport_count)
|
||||||
|
.map(|viewport_index| {
|
||||||
|
let this_eye_offset = if viewport_index == 0 {
|
||||||
|
eye_offset
|
||||||
|
} else {
|
||||||
|
-eye_offset
|
||||||
|
};
|
||||||
|
OcularTransform {
|
||||||
|
perspective,
|
||||||
|
modelview_to_eye: Transform3DF32::from_translation(this_eye_offset, 0.0, 0.0),
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.collect();
|
||||||
|
|
||||||
|
Camera::ThreeD {
|
||||||
|
scene_transform,
|
||||||
|
eye_transforms,
|
||||||
|
modelview_transform: CameraTransform3D::new(view_box),
|
||||||
|
velocity: Point3DF32::default(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn is_3d(&self) -> bool {
|
||||||
|
match *self {
|
||||||
|
Camera::ThreeD { .. } => true,
|
||||||
|
Camera::TwoD { .. } => false,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn mode(&self) -> Mode {
|
||||||
|
match *self {
|
||||||
|
Camera::ThreeD {
|
||||||
|
ref eye_transforms, ..
|
||||||
|
} if eye_transforms.len() >= 2 => Mode::VR,
|
||||||
|
Camera::ThreeD { .. } => Mode::ThreeD,
|
||||||
|
Camera::TwoD { .. } => Mode::TwoD,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Copy, Debug)]
|
||||||
|
pub struct CameraTransform3D {
|
||||||
|
position: Point3DF32,
|
||||||
|
pub yaw: f32,
|
||||||
|
pub pitch: f32,
|
||||||
|
scale: f32,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl CameraTransform3D {
|
||||||
|
fn new(view_box: RectF32) -> CameraTransform3D {
|
||||||
|
let scale = scale_factor_for_view_box(view_box);
|
||||||
|
CameraTransform3D {
|
||||||
|
position: Point3DF32::new(
|
||||||
|
0.5 * view_box.max_x(),
|
||||||
|
-0.5 * view_box.max_y(),
|
||||||
|
1.5 / scale,
|
||||||
|
1.0,
|
||||||
|
),
|
||||||
|
yaw: 0.0,
|
||||||
|
pitch: 0.0,
|
||||||
|
scale,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn offset(&mut self, vector: Point3DF32) -> bool {
|
||||||
|
let update = !vector.is_zero();
|
||||||
|
if update {
|
||||||
|
let rotation = Transform3DF32::from_rotation(-self.yaw, -self.pitch, 0.0);
|
||||||
|
self.position = self.position + rotation.transform_point(vector);
|
||||||
|
}
|
||||||
|
update
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn to_transform(&self) -> Transform3DF32 {
|
||||||
|
let mut transform = Transform3DF32::from_rotation(self.yaw, self.pitch, 0.0);
|
||||||
|
transform = transform.post_mul(&Transform3DF32::from_uniform_scale(2.0 * self.scale));
|
||||||
|
transform = transform.post_mul(&Transform3DF32::from_translation(
|
||||||
|
-self.position.x(),
|
||||||
|
-self.position.y(),
|
||||||
|
-self.position.z(),
|
||||||
|
));
|
||||||
|
|
||||||
|
// Flip Y.
|
||||||
|
transform = transform.post_mul(&Transform3DF32::from_scale(1.0, -1.0, 1.0));
|
||||||
|
|
||||||
|
transform
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Copy, PartialEq)]
|
||||||
|
pub enum Mode {
|
||||||
|
TwoD = 0,
|
||||||
|
ThreeD = 1,
|
||||||
|
VR = 2,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Mode {
|
||||||
|
pub fn viewport_count(self) -> usize {
|
||||||
|
match self {
|
||||||
|
Mode::TwoD | Mode::ThreeD => 1,
|
||||||
|
Mode::VR => 2,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn view(self, viewport: u32) -> View {
|
||||||
|
match self {
|
||||||
|
Mode::TwoD | Mode::ThreeD => View::Mono,
|
||||||
|
Mode::VR => View::Stereo(viewport),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn scale_factor_for_view_box(view_box: RectF32) -> f32 {
|
||||||
|
1.0 / f32::min(view_box.size().x(), view_box.size().y())
|
||||||
|
}
|
|
@ -13,16 +13,16 @@
|
||||||
#[macro_use]
|
#[macro_use]
|
||||||
extern crate log;
|
extern crate log;
|
||||||
|
|
||||||
|
use crate::camera::{Camera, Mode};
|
||||||
use crate::concurrent::DemoExecutor;
|
use crate::concurrent::DemoExecutor;
|
||||||
use crate::device::{GroundProgram, GroundVertexArray};
|
use crate::device::{GroundProgram, GroundVertexArray};
|
||||||
use crate::ui::{DemoUI, UIAction};
|
use crate::ui::{DemoUI, UIAction};
|
||||||
use crate::window::{Event, Keycode, OcularTransform, SVGPath, View, Window, WindowSize};
|
use crate::window::{Event, Keycode, SVGPath, View, Window, WindowSize};
|
||||||
use clap::{App, Arg};
|
use clap::{App, Arg};
|
||||||
use image::ColorType;
|
use image::ColorType;
|
||||||
use pathfinder_geometry::basic::point::{Point2DF32, Point2DI32, Point3DF32};
|
use pathfinder_geometry::basic::point::{Point2DF32, Point2DI32};
|
||||||
use pathfinder_geometry::basic::rect::RectF32;
|
use pathfinder_geometry::basic::rect::RectF32;
|
||||||
use pathfinder_geometry::basic::transform2d::Transform2DF32;
|
use pathfinder_geometry::basic::transform3d::Transform3DF32;
|
||||||
use pathfinder_geometry::basic::transform3d::{Perspective, Transform3DF32};
|
|
||||||
use pathfinder_geometry::color::{ColorF, ColorU};
|
use pathfinder_geometry::color::{ColorF, ColorU};
|
||||||
use pathfinder_gl::GLDevice;
|
use pathfinder_gl::GLDevice;
|
||||||
use pathfinder_gpu::resources::ResourceLoader;
|
use pathfinder_gpu::resources::ResourceLoader;
|
||||||
|
@ -36,7 +36,6 @@ use pathfinder_renderer::post::{DEFRINGING_KERNEL_CORE_GRAPHICS, STEM_DARKENING_
|
||||||
use pathfinder_renderer::scene::Scene;
|
use pathfinder_renderer::scene::Scene;
|
||||||
use pathfinder_svg::BuiltSVG;
|
use pathfinder_svg::BuiltSVG;
|
||||||
use pathfinder_ui::{MousePosition, UIEvent};
|
use pathfinder_ui::{MousePosition, UIEvent};
|
||||||
use std::f32::consts::FRAC_PI_4;
|
|
||||||
use std::fs::File;
|
use std::fs::File;
|
||||||
use std::io::Read;
|
use std::io::Read;
|
||||||
use std::path::PathBuf;
|
use std::path::PathBuf;
|
||||||
|
@ -54,9 +53,6 @@ const CAMERA_SCALE_SPEED_2D: f32 = 6.0;
|
||||||
// How much the scene is scaled when a zoom button is clicked.
|
// How much the scene is scaled when a zoom button is clicked.
|
||||||
const CAMERA_ZOOM_AMOUNT_2D: f32 = 0.1;
|
const CAMERA_ZOOM_AMOUNT_2D: f32 = 0.1;
|
||||||
|
|
||||||
const NEAR_CLIP_PLANE: f32 = 0.01;
|
|
||||||
const FAR_CLIP_PLANE: f32 = 10.0;
|
|
||||||
|
|
||||||
const LIGHT_BG_COLOR: ColorU = ColorU {
|
const LIGHT_BG_COLOR: ColorU = ColorU {
|
||||||
r: 248,
|
r: 248,
|
||||||
g: 248,
|
g: 248,
|
||||||
|
@ -93,13 +89,11 @@ const APPROX_FONT_SIZE: f32 = 16.0;
|
||||||
|
|
||||||
const MESSAGE_TIMEOUT_SECS: u64 = 5;
|
const MESSAGE_TIMEOUT_SECS: u64 = 5;
|
||||||
|
|
||||||
// Half of the eye separation distance.
|
|
||||||
const DEFAULT_EYE_OFFSET: f32 = 0.025;
|
|
||||||
|
|
||||||
pub const GRIDLINE_COUNT: i32 = 10;
|
pub const GRIDLINE_COUNT: i32 = 10;
|
||||||
|
|
||||||
pub mod window;
|
pub mod window;
|
||||||
|
|
||||||
|
mod camera;
|
||||||
mod concurrent;
|
mod concurrent;
|
||||||
mod device;
|
mod device;
|
||||||
mod ui;
|
mod ui;
|
||||||
|
@ -401,7 +395,8 @@ impl<W> DemoApp<W> where W: Window {
|
||||||
ref mut velocity, ..
|
ref mut velocity, ..
|
||||||
} = self.camera
|
} = self.camera
|
||||||
{
|
{
|
||||||
let scale_factor = scale_factor_for_view_box(self.scene_metadata.view_box);
|
let scale_factor =
|
||||||
|
camera::scale_factor_for_view_box(self.scene_metadata.view_box);
|
||||||
velocity.set_z(-CAMERA_VELOCITY / scale_factor);
|
velocity.set_z(-CAMERA_VELOCITY / scale_factor);
|
||||||
self.dirty = true;
|
self.dirty = true;
|
||||||
}
|
}
|
||||||
|
@ -411,7 +406,8 @@ impl<W> DemoApp<W> where W: Window {
|
||||||
ref mut velocity, ..
|
ref mut velocity, ..
|
||||||
} = self.camera
|
} = self.camera
|
||||||
{
|
{
|
||||||
let scale_factor = scale_factor_for_view_box(self.scene_metadata.view_box);
|
let scale_factor =
|
||||||
|
camera::scale_factor_for_view_box(self.scene_metadata.view_box);
|
||||||
velocity.set_z(CAMERA_VELOCITY / scale_factor);
|
velocity.set_z(CAMERA_VELOCITY / scale_factor);
|
||||||
self.dirty = true;
|
self.dirty = true;
|
||||||
}
|
}
|
||||||
|
@ -421,7 +417,8 @@ impl<W> DemoApp<W> where W: Window {
|
||||||
ref mut velocity, ..
|
ref mut velocity, ..
|
||||||
} = self.camera
|
} = self.camera
|
||||||
{
|
{
|
||||||
let scale_factor = scale_factor_for_view_box(self.scene_metadata.view_box);
|
let scale_factor =
|
||||||
|
camera::scale_factor_for_view_box(self.scene_metadata.view_box);
|
||||||
velocity.set_x(-CAMERA_VELOCITY / scale_factor);
|
velocity.set_x(-CAMERA_VELOCITY / scale_factor);
|
||||||
self.dirty = true;
|
self.dirty = true;
|
||||||
}
|
}
|
||||||
|
@ -431,7 +428,8 @@ impl<W> DemoApp<W> where W: Window {
|
||||||
ref mut velocity, ..
|
ref mut velocity, ..
|
||||||
} = self.camera
|
} = self.camera
|
||||||
{
|
{
|
||||||
let scale_factor = scale_factor_for_view_box(self.scene_metadata.view_box);
|
let scale_factor =
|
||||||
|
camera::scale_factor_for_view_box(self.scene_metadata.view_box);
|
||||||
velocity.set_x(CAMERA_VELOCITY / scale_factor);
|
velocity.set_x(CAMERA_VELOCITY / scale_factor);
|
||||||
self.dirty = true;
|
self.dirty = true;
|
||||||
}
|
}
|
||||||
|
@ -976,29 +974,6 @@ impl Options {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Copy, PartialEq)]
|
|
||||||
pub enum Mode {
|
|
||||||
TwoD = 0,
|
|
||||||
ThreeD = 1,
|
|
||||||
VR = 2,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Mode {
|
|
||||||
pub fn viewport_count(self) -> usize {
|
|
||||||
match self {
|
|
||||||
Mode::TwoD | Mode::ThreeD => 1,
|
|
||||||
Mode::VR => 2,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn view(self, viewport: u32) -> View {
|
|
||||||
match self {
|
|
||||||
Mode::TwoD | Mode::ThreeD => View::Mono,
|
|
||||||
Mode::VR => View::Stereo(viewport),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Clone, Copy, PartialEq)]
|
#[derive(Clone, Copy, PartialEq)]
|
||||||
pub enum UIVisibility {
|
pub enum UIVisibility {
|
||||||
None,
|
None,
|
||||||
|
@ -1024,151 +999,6 @@ fn center_of_window(window_size: &WindowSize) -> Point2DF32 {
|
||||||
window_size.device_size().to_f32().scale(0.5)
|
window_size.device_size().to_f32().scale(0.5)
|
||||||
}
|
}
|
||||||
|
|
||||||
enum Camera {
|
|
||||||
TwoD(Transform2DF32),
|
|
||||||
ThreeD {
|
|
||||||
// The ocular transform used for rendering of the scene to the scene framebuffer. If we are
|
|
||||||
// performing stereoscopic rendering, this is then reprojected according to the eye
|
|
||||||
// transforms below.
|
|
||||||
scene_transform: OcularTransform,
|
|
||||||
// For each eye, the perspective from camera coordinates to display coordinates,
|
|
||||||
// and the view transform from world coordinates to camera coordinates.
|
|
||||||
eye_transforms: Vec<OcularTransform>,
|
|
||||||
// The modelview transform from world coordinates to SVG coordinates
|
|
||||||
modelview_transform: CameraTransform3D,
|
|
||||||
// The camera's velocity (in world coordinates)
|
|
||||||
velocity: Point3DF32,
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Camera {
|
|
||||||
fn new(mode: Mode, view_box: RectF32, viewport_size: Point2DI32) -> Camera {
|
|
||||||
if mode == Mode::TwoD {
|
|
||||||
Camera::new_2d(view_box, viewport_size)
|
|
||||||
} else {
|
|
||||||
Camera::new_3d(mode, view_box, viewport_size)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn new_2d(view_box: RectF32, viewport_size: Point2DI32) -> Camera {
|
|
||||||
let scale = i32::min(viewport_size.x(), viewport_size.y()) as f32
|
|
||||||
* scale_factor_for_view_box(view_box);
|
|
||||||
let origin = viewport_size.to_f32().scale(0.5) - view_box.size().scale(scale * 0.5);
|
|
||||||
Camera::TwoD(Transform2DF32::from_scale(&Point2DF32::splat(scale)).post_translate(origin))
|
|
||||||
}
|
|
||||||
|
|
||||||
fn new_3d(mode: Mode, view_box: RectF32, viewport_size: Point2DI32) -> Camera {
|
|
||||||
let viewport_count = mode.viewport_count();
|
|
||||||
|
|
||||||
let fov_y = FRAC_PI_4;
|
|
||||||
let aspect = viewport_size.x() as f32 / viewport_size.y() as f32;
|
|
||||||
let projection =
|
|
||||||
Transform3DF32::from_perspective(fov_y, aspect, NEAR_CLIP_PLANE, FAR_CLIP_PLANE);
|
|
||||||
let perspective = Perspective::new(&projection, viewport_size);
|
|
||||||
|
|
||||||
// Create a scene transform by moving the camera back from the center of the eyes so that
|
|
||||||
// its field of view encompasses the field of view of both eyes.
|
|
||||||
let z_offset = -DEFAULT_EYE_OFFSET * projection.c0.x();
|
|
||||||
let scene_transform = OcularTransform {
|
|
||||||
perspective,
|
|
||||||
modelview_to_eye: Transform3DF32::from_translation(0.0, 0.0, z_offset),
|
|
||||||
};
|
|
||||||
|
|
||||||
// For now, initialize the eye transforms as copies of the scene transform.
|
|
||||||
let eye_offset = DEFAULT_EYE_OFFSET;
|
|
||||||
let eye_transforms = (0..viewport_count)
|
|
||||||
.map(|viewport_index| {
|
|
||||||
let this_eye_offset = if viewport_index == 0 {
|
|
||||||
eye_offset
|
|
||||||
} else {
|
|
||||||
-eye_offset
|
|
||||||
};
|
|
||||||
OcularTransform {
|
|
||||||
perspective,
|
|
||||||
modelview_to_eye: Transform3DF32::from_translation(this_eye_offset, 0.0, 0.0),
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.collect();
|
|
||||||
|
|
||||||
Camera::ThreeD {
|
|
||||||
scene_transform,
|
|
||||||
eye_transforms,
|
|
||||||
modelview_transform: CameraTransform3D::new(view_box),
|
|
||||||
velocity: Point3DF32::default(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn is_3d(&self) -> bool {
|
|
||||||
match *self {
|
|
||||||
Camera::ThreeD { .. } => true,
|
|
||||||
Camera::TwoD { .. } => false,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn mode(&self) -> Mode {
|
|
||||||
match *self {
|
|
||||||
Camera::ThreeD {
|
|
||||||
ref eye_transforms, ..
|
|
||||||
} if eye_transforms.len() >= 2 => Mode::VR,
|
|
||||||
Camera::ThreeD { .. } => Mode::ThreeD,
|
|
||||||
Camera::TwoD { .. } => Mode::TwoD,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Clone, Copy, Debug)]
|
|
||||||
struct CameraTransform3D {
|
|
||||||
position: Point3DF32,
|
|
||||||
yaw: f32,
|
|
||||||
pitch: f32,
|
|
||||||
scale: f32,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl CameraTransform3D {
|
|
||||||
fn new(view_box: RectF32) -> CameraTransform3D {
|
|
||||||
let scale = scale_factor_for_view_box(view_box);
|
|
||||||
CameraTransform3D {
|
|
||||||
position: Point3DF32::new(
|
|
||||||
0.5 * view_box.max_x(),
|
|
||||||
-0.5 * view_box.max_y(),
|
|
||||||
1.5 / scale,
|
|
||||||
1.0,
|
|
||||||
),
|
|
||||||
yaw: 0.0,
|
|
||||||
pitch: 0.0,
|
|
||||||
scale,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn offset(&mut self, vector: Point3DF32) -> bool {
|
|
||||||
let update = !vector.is_zero();
|
|
||||||
if update {
|
|
||||||
let rotation = Transform3DF32::from_rotation(-self.yaw, -self.pitch, 0.0);
|
|
||||||
self.position = self.position + rotation.transform_point(vector);
|
|
||||||
}
|
|
||||||
update
|
|
||||||
}
|
|
||||||
|
|
||||||
fn to_transform(&self) -> Transform3DF32 {
|
|
||||||
let mut transform = Transform3DF32::from_rotation(self.yaw, self.pitch, 0.0);
|
|
||||||
transform = transform.post_mul(&Transform3DF32::from_uniform_scale(2.0 * self.scale));
|
|
||||||
transform = transform.post_mul(&Transform3DF32::from_translation(
|
|
||||||
-self.position.x(),
|
|
||||||
-self.position.y(),
|
|
||||||
-self.position.z(),
|
|
||||||
));
|
|
||||||
|
|
||||||
// Flip Y.
|
|
||||||
transform = transform.post_mul(&Transform3DF32::from_scale(1.0, -1.0, 1.0));
|
|
||||||
|
|
||||||
transform
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn scale_factor_for_view_box(view_box: RectF32) -> f32 {
|
|
||||||
1.0 / f32::min(view_box.size().x(), view_box.size().y())
|
|
||||||
}
|
|
||||||
|
|
||||||
fn get_svg_building_message(built_svg: &BuiltSVG) -> String {
|
fn get_svg_building_message(built_svg: &BuiltSVG) -> String {
|
||||||
if built_svg.result_flags.is_empty() {
|
if built_svg.result_flags.is_empty() {
|
||||||
return String::new();
|
return String::new();
|
||||||
|
|
|
@ -8,8 +8,9 @@
|
||||||
// option. This file may not be copied, modified, or distributed
|
// option. This file may not be copied, modified, or distributed
|
||||||
// except according to those terms.
|
// except according to those terms.
|
||||||
|
|
||||||
|
use crate::camera::Mode;
|
||||||
use crate::window::Window;
|
use crate::window::Window;
|
||||||
use crate::{BackgroundColor, Mode, Options};
|
use crate::{BackgroundColor, Options};
|
||||||
use pathfinder_geometry::basic::point::Point2DI32;
|
use pathfinder_geometry::basic::point::Point2DI32;
|
||||||
use pathfinder_geometry::basic::rect::RectI32;
|
use pathfinder_geometry::basic::rect::RectI32;
|
||||||
use pathfinder_gpu::resources::ResourceLoader;
|
use pathfinder_gpu::resources::ResourceLoader;
|
||||||
|
|
Loading…
Reference in New Issue