Overload `*` between transforms and points
This commit is contained in:
parent
2c984de1ea
commit
437eda96da
|
@ -533,14 +533,14 @@ impl Contour {
|
||||||
}
|
}
|
||||||
|
|
||||||
for (point_index, point) in self.points.iter_mut().enumerate() {
|
for (point_index, point) in self.points.iter_mut().enumerate() {
|
||||||
*point = transform.transform_point(*point);
|
*point = *transform * *point;
|
||||||
union_rect(&mut self.bounds, *point, point_index == 0);
|
union_rect(&mut self.bounds, *point, point_index == 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn apply_perspective(&mut self, perspective: &Perspective) {
|
pub fn apply_perspective(&mut self, perspective: &Perspective) {
|
||||||
for (point_index, point) in self.points.iter_mut().enumerate() {
|
for (point_index, point) in self.points.iter_mut().enumerate() {
|
||||||
*point = perspective.transform_point_2d(*point);
|
*point = *perspective * *point;
|
||||||
union_rect(&mut self.bounds, *point, point_index == 0);
|
union_rect(&mut self.bounds, *point, point_index == 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -34,12 +34,12 @@ where
|
||||||
// TODO(pcwalton): Can we go faster by transforming an entire line segment with SIMD?
|
// TODO(pcwalton): Can we go faster by transforming an entire line segment with SIMD?
|
||||||
let mut segment = self.iter.next()?;
|
let mut segment = self.iter.next()?;
|
||||||
if !segment.is_none() {
|
if !segment.is_none() {
|
||||||
segment.baseline.set_from(self.transform.transform_point(segment.baseline.from()));
|
segment.baseline.set_from(self.transform * segment.baseline.from());
|
||||||
segment.baseline.set_to(self.transform.transform_point(segment.baseline.to()));
|
segment.baseline.set_to(self.transform * segment.baseline.to());
|
||||||
if !segment.is_line() {
|
if !segment.is_line() {
|
||||||
segment.ctrl.set_from(self.transform.transform_point(segment.ctrl.from()));
|
segment.ctrl.set_from(self.transform * segment.ctrl.from());
|
||||||
if !segment.is_quadratic() {
|
if !segment.is_quadratic() {
|
||||||
segment.ctrl.set_to(self.transform.transform_point(segment.ctrl.to()));
|
segment.ctrl.set_to(self.transform * segment.ctrl.to());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -79,14 +79,12 @@ where
|
||||||
fn next(&mut self) -> Option<Segment> {
|
fn next(&mut self) -> Option<Segment> {
|
||||||
let mut segment = self.iter.next()?;
|
let mut segment = self.iter.next()?;
|
||||||
if !segment.is_none() {
|
if !segment.is_none() {
|
||||||
segment.baseline.set_from(
|
segment.baseline.set_from(self.perspective * segment.baseline.from());
|
||||||
self.perspective.transform_point_2d(segment.baseline.from()),
|
segment.baseline.set_to(self.perspective * segment.baseline.to());
|
||||||
);
|
|
||||||
segment.baseline.set_to(self.perspective.transform_point_2d(segment.baseline.to()));
|
|
||||||
if !segment.is_line() {
|
if !segment.is_line() {
|
||||||
segment.ctrl.set_from(self.perspective.transform_point_2d(segment.ctrl.from()));
|
segment.ctrl.set_from(self.perspective * segment.ctrl.from());
|
||||||
if !segment.is_quadratic() {
|
if !segment.is_quadratic() {
|
||||||
segment.ctrl.set_to(self.perspective.transform_point_2d(segment.ctrl.to()));
|
segment.ctrl.set_to(self.perspective * segment.ctrl.to());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -147,7 +147,7 @@ impl CameraTransform3D {
|
||||||
let update = !vector.is_zero();
|
let update = !vector.is_zero();
|
||||||
if update {
|
if update {
|
||||||
let rotation = Transform4F::from_rotation(-self.yaw, -self.pitch, 0.0);
|
let rotation = Transform4F::from_rotation(-self.yaw, -self.pitch, 0.0);
|
||||||
self.position = self.position + rotation.transform_point(vector);
|
self.position = self.position + rotation * vector;
|
||||||
}
|
}
|
||||||
update
|
update
|
||||||
}
|
}
|
||||||
|
|
|
@ -232,7 +232,7 @@ impl LineSegment2F {
|
||||||
if f32::abs(matrix.det()) < EPSILON {
|
if f32::abs(matrix.det()) < EPSILON {
|
||||||
return None;
|
return None;
|
||||||
}
|
}
|
||||||
return Some(matrix.inverse().transform_point(self.from() - other.from()).y());
|
return Some((matrix.inverse() * (self.from() - other.from())).y());
|
||||||
|
|
||||||
const EPSILON: f32 = 0.0001;
|
const EPSILON: f32 = 0.0001;
|
||||||
}
|
}
|
||||||
|
|
|
@ -60,12 +60,6 @@ impl Matrix2x2F {
|
||||||
Matrix2x2F(self.0.wyzx() * F32x4::new(1.0, -1.0, -1.0, 1.0))
|
Matrix2x2F(self.0.wyzx() * F32x4::new(1.0, -1.0, -1.0, 1.0))
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
|
||||||
pub fn transform_point(&self, point: Vector2F) -> Vector2F {
|
|
||||||
let halves = self.0 * point.0.to_f32x4().xxyy();
|
|
||||||
Vector2F(halves.xy() + halves.zw())
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn det(&self) -> f32 {
|
pub fn det(&self) -> f32 {
|
||||||
self.0[0] * self.0[3] - self.0[2] * self.0[1]
|
self.0[0] * self.0[3] - self.0[2] * self.0[1]
|
||||||
|
@ -110,6 +104,15 @@ impl Mul<Matrix2x2F> for Matrix2x2F {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl Mul<Vector2F> for Matrix2x2F {
|
||||||
|
type Output = Vector2F;
|
||||||
|
#[inline]
|
||||||
|
fn mul(self, vector: Vector2F) -> Vector2F {
|
||||||
|
let halves = self.0 * vector.0.to_f32x4().xxyy();
|
||||||
|
Vector2F(halves.xy() + halves.zw())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// An affine transform, optimized with SIMD.
|
/// An affine transform, optimized with SIMD.
|
||||||
#[derive(Clone, Copy, Debug, PartialEq)]
|
#[derive(Clone, Copy, Debug, PartialEq)]
|
||||||
pub struct Transform2F {
|
pub struct Transform2F {
|
||||||
|
@ -179,23 +182,15 @@ impl Transform2F {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
|
||||||
pub fn transform_point(&self, point: Vector2F) -> Vector2F {
|
|
||||||
self.matrix.transform_point(point) + self.vector
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn transform_line_segment(&self, line_segment: LineSegment2F) -> LineSegment2F {
|
pub fn transform_line_segment(&self, line_segment: LineSegment2F) -> LineSegment2F {
|
||||||
LineSegment2F::new(self.transform_point(line_segment.from()),
|
LineSegment2F::new(*self * line_segment.from(), *self * line_segment.to())
|
||||||
self.transform_point(line_segment.to()))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn transform_rect(&self, rect: &RectF) -> RectF {
|
pub fn transform_rect(&self, rect: &RectF) -> RectF {
|
||||||
let upper_left = self.transform_point(rect.origin());
|
let (upper_left, upper_right) = (*self * rect.origin(), *self * rect.upper_right());
|
||||||
let upper_right = self.transform_point(rect.upper_right());
|
let (lower_left, lower_right) = (*self * rect.lower_left(), *self * rect.lower_right());
|
||||||
let lower_left = self.transform_point(rect.lower_left());
|
|
||||||
let lower_right = self.transform_point(rect.lower_right());
|
|
||||||
let min_point = upper_left.min(upper_right).min(lower_left).min(lower_right);
|
let min_point = upper_left.min(upper_right).min(lower_left).min(lower_right);
|
||||||
let max_point = upper_left.max(upper_right).max(lower_left).max(lower_right);
|
let max_point = upper_left.max(upper_right).max(lower_left).max(lower_right);
|
||||||
RectF::from_points(min_point, max_point)
|
RectF::from_points(min_point, max_point)
|
||||||
|
@ -297,11 +292,19 @@ impl Mul<Transform2F> for Transform2F {
|
||||||
fn mul(self, other: Transform2F) -> Transform2F {
|
fn mul(self, other: Transform2F) -> Transform2F {
|
||||||
Transform2F {
|
Transform2F {
|
||||||
matrix: self.matrix * other.matrix,
|
matrix: self.matrix * other.matrix,
|
||||||
vector: self.transform_point(other.vector),
|
vector: self * other.vector,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl Mul<Vector2F> for Transform2F {
|
||||||
|
type Output = Vector2F;
|
||||||
|
#[inline]
|
||||||
|
fn mul(self, vector: Vector2F) -> Vector2F {
|
||||||
|
self.matrix * vector + self.vector
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl MulAssign for Transform2F {
|
impl MulAssign for Transform2F {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn mul_assign(&mut self, other: Transform2F) {
|
fn mul_assign(&mut self, other: Transform2F) {
|
||||||
|
|
|
@ -240,15 +240,6 @@ impl Transform4F {
|
||||||
Transform4F::from_translation(translation) * *self
|
Transform4F::from_translation(translation) * *self
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
|
||||||
pub fn transform_point(&self, point: Vector4F) -> Vector4F {
|
|
||||||
let term0 = self.c0 * F32x4::splat(point.x());
|
|
||||||
let term1 = self.c1 * F32x4::splat(point.y());
|
|
||||||
let term2 = self.c2 * F32x4::splat(point.z());
|
|
||||||
let term3 = self.c3 * F32x4::splat(point.w());
|
|
||||||
Vector4F(term0 + term1 + term2 + term3)
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn upper_left(&self) -> Matrix2x2F {
|
pub fn upper_left(&self) -> Matrix2x2F {
|
||||||
Matrix2x2F(self.c0.concat_xy_xy(self.c1))
|
Matrix2x2F(self.c0.concat_xy_xy(self.c1))
|
||||||
|
@ -330,6 +321,19 @@ impl Mul<Transform4F> for Transform4F {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl Mul<Vector4F> for Transform4F {
|
||||||
|
type Output = Vector4F;
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn mul(self, vector: Vector4F) -> Vector4F {
|
||||||
|
let term0 = self.c0 * F32x4::splat(vector.x());
|
||||||
|
let term1 = self.c1 * F32x4::splat(vector.y());
|
||||||
|
let term2 = self.c2 * F32x4::splat(vector.z());
|
||||||
|
let term3 = self.c3 * F32x4::splat(vector.w());
|
||||||
|
Vector4F(term0 + term1 + term2 + term3)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl MulAssign<Transform4F> for Transform4F {
|
impl MulAssign<Transform4F> for Transform4F {
|
||||||
fn mul_assign(&mut self, other: Transform4F) {
|
fn mul_assign(&mut self, other: Transform4F) {
|
||||||
*self = *self * other
|
*self = *self * other
|
||||||
|
@ -367,24 +371,10 @@ impl Perspective {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
|
||||||
pub fn transform_point_2d(&self, point: Vector2F) -> Vector2F {
|
|
||||||
let point = self
|
|
||||||
.transform
|
|
||||||
.transform_point(point.to_3d())
|
|
||||||
.perspective_divide()
|
|
||||||
.to_2d()
|
|
||||||
* Vector2F::new(1.0, -1.0);
|
|
||||||
(point + Vector2F::splat(1.0)) * self.window_size.to_f32().scale(0.5)
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO(pcwalton): SIMD?
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn transform_rect(&self, rect: RectF) -> RectF {
|
pub fn transform_rect(&self, rect: RectF) -> RectF {
|
||||||
let upper_left = self.transform_point_2d(rect.origin());
|
let (upper_left, upper_right) = (*self * rect.origin(), *self * rect.upper_right());
|
||||||
let upper_right = self.transform_point_2d(rect.upper_right());
|
let (lower_left, lower_right) = (*self * rect.lower_left(), *self * rect.lower_right());
|
||||||
let lower_left = self.transform_point_2d(rect.lower_left());
|
|
||||||
let lower_right = self.transform_point_2d(rect.lower_right());
|
|
||||||
let min_point = upper_left.min(upper_right).min(lower_left).min(lower_right);
|
let min_point = upper_left.min(upper_right).min(lower_left).min(lower_right);
|
||||||
let max_point = upper_left.max(upper_right).max(lower_left).max(lower_right);
|
let max_point = upper_left.max(upper_right).max(lower_left).max(lower_right);
|
||||||
RectF::from_points(min_point, max_point)
|
RectF::from_points(min_point, max_point)
|
||||||
|
@ -402,6 +392,16 @@ impl Mul<Transform4F> for Perspective {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl Mul<Vector2F> for Perspective {
|
||||||
|
type Output = Vector2F;
|
||||||
|
#[inline]
|
||||||
|
fn mul(self, vector: Vector2F) -> Vector2F {
|
||||||
|
let point = (self.transform * vector.to_3d()).perspective_divide().to_2d() *
|
||||||
|
Vector2F::new(1.0, -1.0);
|
||||||
|
(point + Vector2F::splat(1.0)) * self.window_size.to_f32().scale(0.5)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod test {
|
mod test {
|
||||||
use crate::vector::Vector4F;
|
use crate::vector::Vector4F;
|
||||||
|
|
|
@ -83,7 +83,7 @@ impl RenderTransform {
|
||||||
debug!("-----");
|
debug!("-----");
|
||||||
debug!("bounds={:?} ORIGINAL quad={:?}", bounds, points);
|
debug!("bounds={:?} ORIGINAL quad={:?}", bounds, points);
|
||||||
for point in &mut points {
|
for point in &mut points {
|
||||||
*point = perspective.transform.transform_point(*point);
|
*point = perspective.transform * *point;
|
||||||
}
|
}
|
||||||
debug!("... PERSPECTIVE quad={:?}", points);
|
debug!("... PERSPECTIVE quad={:?}", points);
|
||||||
|
|
||||||
|
@ -105,12 +105,7 @@ impl RenderTransform {
|
||||||
let inverse_transform = perspective.transform.inverse();
|
let inverse_transform = perspective.transform.inverse();
|
||||||
let clip_polygon = points
|
let clip_polygon = points
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.map(|point| {
|
.map(|point| (inverse_transform * point).perspective_divide().to_2d())
|
||||||
inverse_transform
|
|
||||||
.transform_point(point)
|
|
||||||
.perspective_divide()
|
|
||||||
.to_2d()
|
|
||||||
})
|
|
||||||
.collect();
|
.collect();
|
||||||
return PreparedRenderTransform::Perspective {
|
return PreparedRenderTransform::Perspective {
|
||||||
perspective,
|
perspective,
|
||||||
|
|
|
@ -147,7 +147,7 @@ impl OutlinePathBuilder {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn convert_point(&self, point: Point2D<f32>) -> Vector2F {
|
fn convert_point(&self, point: Point2D<f32>) -> Vector2F {
|
||||||
self.transform.transform_point(Vector2F::new(point.x, point.y))
|
self.transform * Vector2F::new(point.x, point.y)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue