Rotate and scale around the appropriate points in the demo
This commit is contained in:
parent
4053b7dd0c
commit
0983812b90
|
@ -191,13 +191,7 @@ impl DemoApp {
|
|||
|
||||
RenderTransform::Perspective(Perspective::new(&transform, &drawable_size))
|
||||
}
|
||||
Camera::TwoD { ref position, scale } => {
|
||||
let mut transform = Transform2DF32::from_rotation(self.ui.rotation());
|
||||
transform =
|
||||
transform.post_mul(&Transform2DF32::from_scale(&Point2DF32::splat(scale)));
|
||||
transform = transform.post_mul(&Transform2DF32::from_translation(position));
|
||||
RenderTransform::Transform2D(transform)
|
||||
}
|
||||
Camera::TwoD(transform) => RenderTransform::Transform2D(transform),
|
||||
};
|
||||
|
||||
let count = if self.frame_counter == 0 { 2 } else { 1 };
|
||||
|
@ -263,8 +257,14 @@ impl DemoApp {
|
|||
self.dirty = true;
|
||||
}
|
||||
Event::MultiGesture { d_dist, .. } => {
|
||||
if let Camera::TwoD { ref mut scale, .. } = self.camera {
|
||||
*scale *= 1.0 + d_dist * CAMERA_SCALE_SPEED_2D;
|
||||
if let Camera::TwoD(ref mut transform) = self.camera {
|
||||
let mouse_state = self.sdl_event_pump.mouse_state();
|
||||
let position = Point2DI32::new(mouse_state.x(), mouse_state.y());
|
||||
let position = position.to_f32().scale(self.scale_factor);
|
||||
*transform = transform.post_translate(-position);
|
||||
let scale_delta = 1.0 + d_dist * CAMERA_SCALE_SPEED_2D;
|
||||
*transform = transform.post_scale(Point2DF32::splat(scale_delta));
|
||||
*transform = transform.post_translate(position);
|
||||
}
|
||||
}
|
||||
Event::KeyDown { keycode: Some(Keycode::W), .. } => {
|
||||
|
@ -358,17 +358,34 @@ impl DemoApp {
|
|||
self.dirty = true;
|
||||
}
|
||||
UIAction::ZoomIn => {
|
||||
if let Camera::TwoD { ref mut scale, .. } = self.camera {
|
||||
*scale *= 1.0 + CAMERA_ZOOM_AMOUNT_2D;
|
||||
if let Camera::TwoD(ref mut transform) = self.camera {
|
||||
let scale = Point2DF32::splat(1.0 + CAMERA_ZOOM_AMOUNT_2D);
|
||||
let center = center_of_window(&self.window);
|
||||
*transform = transform.post_translate(-center)
|
||||
.post_scale(scale)
|
||||
.post_translate(center);
|
||||
self.dirty = true;
|
||||
}
|
||||
}
|
||||
UIAction::ZoomOut => {
|
||||
if let Camera::TwoD { ref mut scale, .. } = self.camera {
|
||||
*scale *= 1.0 - CAMERA_ZOOM_AMOUNT_2D;
|
||||
if let Camera::TwoD(ref mut transform) = self.camera {
|
||||
let scale = Point2DF32::splat(1.0 - CAMERA_ZOOM_AMOUNT_2D);
|
||||
let center = center_of_window(&self.window);
|
||||
*transform = transform.post_translate(-center)
|
||||
.post_scale(scale)
|
||||
.post_translate(center);
|
||||
self.dirty = true;
|
||||
}
|
||||
}
|
||||
UIAction::Rotate(theta) => {
|
||||
if let Camera::TwoD(ref mut transform) = self.camera {
|
||||
let old_rotation = transform.rotation();
|
||||
let center = center_of_window(&self.window);
|
||||
*transform = transform.post_translate(-center)
|
||||
.post_rotate(theta - old_rotation)
|
||||
.post_translate(center);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Switch camera mode (2D/3D) if requested.
|
||||
|
@ -386,8 +403,8 @@ impl DemoApp {
|
|||
self.mouselook_enabled = !self.mouselook_enabled;
|
||||
}
|
||||
UIEvent::MouseDragged { relative_position, .. } => {
|
||||
if let Camera::TwoD { ref mut position, .. } = self.camera {
|
||||
*position = *position + relative_position.to_f32();
|
||||
if let Camera::TwoD(ref mut transform) = self.camera {
|
||||
*transform = transform.post_translate(relative_position.to_f32());
|
||||
}
|
||||
}
|
||||
_ => {}
|
||||
|
@ -574,14 +591,19 @@ fn update_drawable_size(window: &Window, scene_thread_proxy: &SceneThreadProxy)
|
|||
drawable_size
|
||||
}
|
||||
|
||||
fn center_of_window(window: &Window) -> Point2DF32 {
|
||||
let (drawable_width, drawable_height) = window.drawable_size();
|
||||
Point2DI32::new(drawable_width as i32, drawable_height as i32).to_f32().scale(0.5)
|
||||
}
|
||||
|
||||
enum Camera {
|
||||
TwoD { position: Point2DF32, scale: f32 },
|
||||
TwoD(Transform2DF32),
|
||||
ThreeD { position: Point3DF32, velocity: Point3DF32, yaw: f32, pitch: f32 },
|
||||
}
|
||||
|
||||
impl Camera {
|
||||
fn two_d() -> Camera {
|
||||
Camera::TwoD { position: Point2DF32::new(0.0, 0.0), scale: 1.0 }
|
||||
Camera::TwoD(Transform2DF32::default())
|
||||
}
|
||||
|
||||
fn three_d() -> Camera {
|
||||
|
|
|
@ -81,7 +81,7 @@ impl DemoUI {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn rotation(&self) -> f32 {
|
||||
fn rotation(&self) -> f32 {
|
||||
(self.rotation as f32 / SLIDER_WIDTH as f32 * 2.0 - 1.0) * PI
|
||||
}
|
||||
|
||||
|
@ -145,7 +145,7 @@ impl DemoUI {
|
|||
self.draw_effects_panel(debug_ui, event);
|
||||
|
||||
// Draw rotate panel, if necessary.
|
||||
self.draw_rotate_panel(debug_ui, event);
|
||||
self.draw_rotate_panel(debug_ui, event, action);
|
||||
}
|
||||
|
||||
fn draw_effects_panel(&mut self, debug_ui: &mut DebugUI, event: &mut UIEvent) {
|
||||
|
@ -184,7 +184,10 @@ impl DemoUI {
|
|||
|
||||
}
|
||||
|
||||
fn draw_rotate_panel(&mut self, debug_ui: &mut DebugUI, event: &mut UIEvent) {
|
||||
fn draw_rotate_panel(&mut self,
|
||||
debug_ui: &mut DebugUI,
|
||||
event: &mut UIEvent,
|
||||
action: &mut UIAction) {
|
||||
if !self.rotate_panel_visible {
|
||||
return;
|
||||
}
|
||||
|
@ -201,6 +204,7 @@ impl DemoUI {
|
|||
Point2DI32::new(SLIDER_WIDTH, SLIDER_KNOB_HEIGHT));
|
||||
if let Some(position) = event.handle_mouse_down_or_dragged_in_rect(widget_rect) {
|
||||
self.rotation = position.x();
|
||||
*action = UIAction::Rotate(self.rotation());
|
||||
}
|
||||
|
||||
let slider_track_y = rotate_panel_y + PADDING + SLIDER_KNOB_HEIGHT / 2 -
|
||||
|
@ -291,6 +295,7 @@ pub enum UIAction {
|
|||
OpenFile(PathBuf),
|
||||
ZoomIn,
|
||||
ZoomOut,
|
||||
Rotate(f32),
|
||||
}
|
||||
|
||||
pub enum UIEvent {
|
||||
|
|
|
@ -12,7 +12,7 @@
|
|||
|
||||
use euclid::Point2D;
|
||||
use pathfinder_simd::default::{F32x4, I32x4};
|
||||
use std::ops::{Add, AddAssign, Mul, Sub};
|
||||
use std::ops::{Add, AddAssign, Mul, Neg, Sub};
|
||||
|
||||
/// 2D points with 32-bit floating point coordinates.
|
||||
#[derive(Clone, Copy, Debug, Default)]
|
||||
|
@ -161,6 +161,14 @@ impl Mul<Point2DF32> for Point2DF32 {
|
|||
}
|
||||
}
|
||||
|
||||
impl Neg for Point2DF32 {
|
||||
type Output = Point2DF32;
|
||||
#[inline]
|
||||
fn neg(self) -> Point2DF32 {
|
||||
Point2DF32(-self.0)
|
||||
}
|
||||
}
|
||||
|
||||
/// 2D points with 32-bit signed integer coordinates.
|
||||
#[derive(Clone, Copy, Debug, Default)]
|
||||
pub struct Point2DI32(pub I32x4);
|
||||
|
|
|
@ -82,6 +82,15 @@ impl Matrix2x2F32 {
|
|||
pub fn inverse(&self) -> Matrix2x2F32 {
|
||||
Matrix2x2F32(F32x4::splat(1.0 / self.det()) * self.adjugate().0)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn m11(&self) -> f32 { self.0[0] }
|
||||
#[inline]
|
||||
pub fn m21(&self) -> f32 { self.0[1] }
|
||||
#[inline]
|
||||
pub fn m12(&self) -> f32 { self.0[2] }
|
||||
#[inline]
|
||||
pub fn m22(&self) -> f32 { self.0[3] }
|
||||
}
|
||||
|
||||
impl Sub<Matrix2x2F32> for Matrix2x2F32 {
|
||||
|
@ -132,6 +141,14 @@ impl Transform2DF32 {
|
|||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn from_scale_rotation_translation(scale: Point2DF32, theta: f32, translation: Point2DF32)
|
||||
-> Transform2DF32 {
|
||||
let rotation = Transform2DF32::from_rotation(theta);
|
||||
let translation = Transform2DF32::from_translation(&translation);
|
||||
Transform2DF32::from_scale(&scale).post_mul(&rotation).post_mul(&translation)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn row_major(m11: f32, m12: f32, m21: f32, m22: f32, m31: f32, m32: f32)
|
||||
-> Transform2DF32 {
|
||||
|
@ -182,6 +199,54 @@ impl Transform2DF32 {
|
|||
pub fn is_identity(&self) -> bool {
|
||||
*self == Transform2DF32::default()
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn m11(&self) -> f32 { self.matrix.m11() }
|
||||
#[inline]
|
||||
pub fn m21(&self) -> f32 { self.matrix.m21() }
|
||||
#[inline]
|
||||
pub fn m12(&self) -> f32 { self.matrix.m12() }
|
||||
#[inline]
|
||||
pub fn m22(&self) -> f32 { self.matrix.m22() }
|
||||
|
||||
#[inline]
|
||||
pub fn post_translate(&self, vector: Point2DF32) -> Transform2DF32 {
|
||||
self.post_mul(&Transform2DF32::from_translation(&vector))
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn post_rotate(&self, theta: f32) -> Transform2DF32 {
|
||||
self.post_mul(&Transform2DF32::from_rotation(theta))
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn post_scale(&self, scale: Point2DF32) -> Transform2DF32 {
|
||||
self.post_mul(&Transform2DF32::from_scale(&scale))
|
||||
}
|
||||
|
||||
/// Returns the translation part of this matrix.
|
||||
///
|
||||
/// This decomposition assumes that scale, rotation, and translation are applied in that order.
|
||||
#[inline]
|
||||
pub fn translation(&self) -> Point2DF32 {
|
||||
self.vector
|
||||
}
|
||||
|
||||
/// Returns the rotation angle of this matrix.
|
||||
///
|
||||
/// This decomposition assumes that scale, rotation, and translation are applied in that order.
|
||||
#[inline]
|
||||
pub fn rotation(&self) -> f32 {
|
||||
f32::atan2(self.m21(), self.m11())
|
||||
}
|
||||
|
||||
/// Returns the scale factor of this matrix.
|
||||
///
|
||||
/// This decomposition assumes that scale, rotation, and translation are applied in that order.
|
||||
#[inline]
|
||||
pub fn scale_factor(&self) -> f32 {
|
||||
Point2DF32(self.matrix.0.zwxy()).length()
|
||||
}
|
||||
}
|
||||
|
||||
/// Transforms a path with a SIMD 2D transform.
|
||||
|
|
Loading…
Reference in New Issue