Use operator overloading for 3D matrix multiplication
This commit is contained in:
parent
abf97c9adb
commit
eb0a61679d
|
@ -153,15 +153,13 @@ impl CameraTransform3D {
|
||||||
|
|
||||||
pub fn to_transform(&self) -> Transform3DF {
|
pub fn to_transform(&self) -> Transform3DF {
|
||||||
let mut transform = Transform3DF::from_rotation(self.yaw, self.pitch, 0.0);
|
let mut transform = Transform3DF::from_rotation(self.yaw, self.pitch, 0.0);
|
||||||
transform = transform.post_mul(&Transform3DF::from_uniform_scale(2.0 * self.scale));
|
transform *= Transform3DF::from_uniform_scale(2.0 * self.scale);
|
||||||
transform = transform.post_mul(&Transform3DF::from_translation(
|
transform *= Transform3DF::from_translation(-self.position.x(),
|
||||||
-self.position.x(),
|
|
||||||
-self.position.y(),
|
-self.position.y(),
|
||||||
-self.position.z(),
|
-self.position.z());
|
||||||
));
|
|
||||||
|
|
||||||
// Flip Y.
|
// Flip Y.
|
||||||
transform = transform.post_mul(&Transform3DF::from_scale(1.0, -1.0, 1.0));
|
transform *= Transform3DF::from_scale(1.0, -1.0, 1.0);
|
||||||
|
|
||||||
transform
|
transform
|
||||||
}
|
}
|
||||||
|
|
|
@ -256,10 +256,9 @@ impl<W> DemoApp<W> where W: Window {
|
||||||
if modelview_transform.offset(*velocity) {
|
if modelview_transform.offset(*velocity) {
|
||||||
self.dirty = true;
|
self.dirty = true;
|
||||||
}
|
}
|
||||||
let perspective = scene_transform
|
let perspective = scene_transform.perspective *
|
||||||
.perspective
|
scene_transform.modelview_to_eye *
|
||||||
.post_mul(&scene_transform.modelview_to_eye)
|
modelview_transform.to_transform();
|
||||||
.post_mul(&modelview_transform.to_transform());
|
|
||||||
Some(RenderTransform::Perspective(perspective))
|
Some(RenderTransform::Perspective(perspective))
|
||||||
}
|
}
|
||||||
Camera::TwoD(transform) => Some(RenderTransform::Transform2D(transform)),
|
Camera::TwoD(transform) => Some(RenderTransform::Transform2D(transform)),
|
||||||
|
@ -356,13 +355,20 @@ impl<W> DemoApp<W> where W: Window {
|
||||||
*scene_transform = eye_transforms[0];
|
*scene_transform = eye_transforms[0];
|
||||||
for (index, eye_transform) in eye_transforms.iter().enumerate().skip(1) {
|
for (index, eye_transform) in eye_transforms.iter().enumerate().skip(1) {
|
||||||
let weight = 1.0 / (index + 1) as f32;
|
let weight = 1.0 / (index + 1) as f32;
|
||||||
scene_transform.perspective.transform = scene_transform.perspective.transform.lerp(weight, &eye_transform.perspective.transform);
|
scene_transform.perspective.transform =
|
||||||
scene_transform.modelview_to_eye = scene_transform.modelview_to_eye.lerp(weight, &eye_transform.modelview_to_eye);
|
scene_transform.perspective
|
||||||
|
.transform
|
||||||
|
.lerp(weight, &eye_transform.perspective.transform);
|
||||||
|
scene_transform.modelview_to_eye =
|
||||||
|
scene_transform.modelview_to_eye
|
||||||
|
.lerp(weight, &eye_transform.modelview_to_eye);
|
||||||
}
|
}
|
||||||
// TODO: calculate the eye offset from the eye transforms?
|
// TODO: calculate the eye offset from the eye transforms?
|
||||||
let z_offset = -DEFAULT_EYE_OFFSET * scene_transform.perspective.transform.c0.x();
|
let z_offset = -DEFAULT_EYE_OFFSET *
|
||||||
scene_transform.modelview_to_eye = scene_transform.modelview_to_eye
|
scene_transform.perspective.transform.c0.x();
|
||||||
.pre_mul(&Transform3DF::from_translation(0.0, 0.0, z_offset));
|
scene_transform.modelview_to_eye =
|
||||||
|
Transform3DF::from_translation(0.0, 0.0, z_offset) *
|
||||||
|
scene_transform.modelview_to_eye;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Event::KeyDown(Keycode::Alphanumeric(b'w')) => {
|
Event::KeyDown(Keycode::Alphanumeric(b'w')) => {
|
||||||
|
|
|
@ -169,18 +169,16 @@ impl<W> DemoApp<W> where W: Window {
|
||||||
1.0,
|
1.0,
|
||||||
);
|
);
|
||||||
|
|
||||||
let scene_transform_matrix = scene_transform
|
let scene_transform_matrix = scene_transform.perspective *
|
||||||
.perspective
|
scene_transform.modelview_to_eye *
|
||||||
.post_mul(&scene_transform.modelview_to_eye)
|
modelview_transform.to_transform() *
|
||||||
.post_mul(&modelview_transform.to_transform())
|
quad_scale_transform;
|
||||||
.post_mul(&quad_scale_transform);
|
|
||||||
|
|
||||||
let eye_transform = &eye_transforms[render_scene_index as usize];
|
let eye_transform = &eye_transforms[render_scene_index as usize];
|
||||||
let eye_transform_matrix = eye_transform
|
let eye_transform_matrix = eye_transform.perspective *
|
||||||
.perspective
|
eye_transform.modelview_to_eye *
|
||||||
.post_mul(&eye_transform.modelview_to_eye)
|
modelview_transform.to_transform() *
|
||||||
.post_mul(&modelview_transform.to_transform())
|
quad_scale_transform;
|
||||||
.post_mul(&quad_scale_transform);
|
|
||||||
|
|
||||||
debug!(
|
debug!(
|
||||||
"eye transform({}).modelview_to_eye={:?}",
|
"eye transform({}).modelview_to_eye={:?}",
|
||||||
|
@ -214,17 +212,13 @@ impl<W> DemoApp<W> where W: Window {
|
||||||
|
|
||||||
let ground_scale = self.scene_metadata.view_box.max_x() * 2.0;
|
let ground_scale = self.scene_metadata.view_box.max_x() * 2.0;
|
||||||
|
|
||||||
let mut base_transform = perspective.transform;
|
let base_transform = perspective.transform *
|
||||||
base_transform = base_transform.post_mul(&Transform3DF::from_translation(
|
Transform3DF::from_translation(-0.5 * self.scene_metadata.view_box.max_x(),
|
||||||
-0.5 * self.scene_metadata.view_box.max_x(),
|
|
||||||
self.scene_metadata.view_box.max_y(),
|
self.scene_metadata.view_box.max_y(),
|
||||||
-0.5 * ground_scale,
|
-0.5 * ground_scale);
|
||||||
));
|
|
||||||
|
|
||||||
// Fill ground.
|
// Fill ground.
|
||||||
let mut transform = base_transform;
|
let transform = base_transform * Transform3DF::from_scale(ground_scale, 1.0, ground_scale);
|
||||||
transform =
|
|
||||||
transform.post_mul(&Transform3DF::from_scale(ground_scale, 1.0, ground_scale));
|
|
||||||
|
|
||||||
// Don't clear the first scene after drawing it.
|
// Don't clear the first scene after drawing it.
|
||||||
let clear_color = if render_scene_index == 0 {
|
let clear_color = if render_scene_index == 0 {
|
||||||
|
|
|
@ -14,7 +14,7 @@ use crate::vector::{Vector2F, Vector2I, Vector4F};
|
||||||
use crate::rect::RectF;
|
use crate::rect::RectF;
|
||||||
use crate::transform2d::Matrix2x2F;
|
use crate::transform2d::Matrix2x2F;
|
||||||
use pathfinder_simd::default::F32x4;
|
use pathfinder_simd::default::F32x4;
|
||||||
use std::ops::{Add, Neg};
|
use std::ops::{Add, Mul, MulAssign, Neg};
|
||||||
|
|
||||||
/// An transform, optimized with SIMD.
|
/// An transform, optimized with SIMD.
|
||||||
///
|
///
|
||||||
|
@ -218,31 +218,6 @@ impl Transform3DF {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// FIXME(pcwalton): Is this right, due to transposition? I think we may have to reverse the
|
|
||||||
// two.
|
|
||||||
//
|
|
||||||
// https://stackoverflow.com/a/18508113
|
|
||||||
#[inline]
|
|
||||||
pub fn pre_mul(&self, other: &Transform3DF) -> Transform3DF {
|
|
||||||
return Transform3DF {
|
|
||||||
c0: mul_col(self.c0, other),
|
|
||||||
c1: mul_col(self.c1, other),
|
|
||||||
c2: mul_col(self.c2, other),
|
|
||||||
c3: mul_col(self.c3, other),
|
|
||||||
};
|
|
||||||
|
|
||||||
fn mul_col(a_col: F32x4, b: &Transform3DF) -> F32x4 {
|
|
||||||
let (a0, a1) = (F32x4::splat(a_col[0]), F32x4::splat(a_col[1]));
|
|
||||||
let (a2, a3) = (F32x4::splat(a_col[2]), F32x4::splat(a_col[3]));
|
|
||||||
a0 * b.c0 + a1 * b.c1 + a2 * b.c2 + a3 * b.c3
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline]
|
|
||||||
pub fn post_mul(&self, other: &Transform3DF) -> Transform3DF {
|
|
||||||
other.pre_mul(self)
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn transform_point(&self, point: Vector4F) -> Vector4F {
|
pub fn transform_point(&self, point: Vector4F) -> Vector4F {
|
||||||
let term0 = self.c0 * F32x4::splat(point.x());
|
let term0 = self.c0 * F32x4::splat(point.x());
|
||||||
|
@ -313,6 +288,32 @@ impl Transform3DF {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl Mul<Transform3DF> for Transform3DF {
|
||||||
|
type Output = Transform3DF;
|
||||||
|
|
||||||
|
// https://stackoverflow.com/a/18508113
|
||||||
|
#[inline]
|
||||||
|
fn mul(self, other: Transform3DF) -> Transform3DF {
|
||||||
|
return Transform3DF {
|
||||||
|
c0: mul_col(&self, other.c0),
|
||||||
|
c1: mul_col(&self, other.c1),
|
||||||
|
c2: mul_col(&self, other.c2),
|
||||||
|
c3: mul_col(&self, other.c3),
|
||||||
|
};
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn mul_col(a: &Transform3DF, b_col: F32x4) -> F32x4 {
|
||||||
|
a.c0 * b_col.xxxx() + a.c1 * b_col.yyyy() + a.c2 * b_col.zzzz() + a.c3 * b_col.wwww()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl MulAssign<Transform3DF> for Transform3DF {
|
||||||
|
fn mul_assign(&mut self, other: Transform3DF) {
|
||||||
|
*self = *self * other
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl Add<Matrix2x2F> for Matrix2x2F {
|
impl Add<Matrix2x2F> for Matrix2x2F {
|
||||||
type Output = Matrix2x2F;
|
type Output = Matrix2x2F;
|
||||||
#[inline]
|
#[inline]
|
||||||
|
@ -366,11 +367,14 @@ impl Perspective {
|
||||||
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)
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Mul<Transform3DF> for Perspective {
|
||||||
|
type Output = Perspective;
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn post_mul(&self, other: &Transform3DF) -> Perspective {
|
fn mul(self, other: Transform3DF) -> Perspective {
|
||||||
Perspective {
|
Perspective {
|
||||||
transform: self.transform.post_mul(other),
|
transform: self.transform * other,
|
||||||
window_size: self.window_size,
|
window_size: self.window_size,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -472,7 +472,7 @@ where
|
||||||
let draw_viewport = self.draw_viewport().size().to_f32();
|
let draw_viewport = self.draw_viewport().size().to_f32();
|
||||||
let scale = F32x2::new(2.0 / draw_viewport.x(), -2.0 / draw_viewport.y());
|
let scale = F32x2::new(2.0 / draw_viewport.x(), -2.0 / draw_viewport.y());
|
||||||
let transform = Transform3DF::from_scale(scale.x(), scale.y(), 1.0);
|
let transform = Transform3DF::from_scale(scale.x(), scale.y(), 1.0);
|
||||||
Transform3DF::from_translation(-1.0, 1.0, 0.0).post_mul(&transform)
|
Transform3DF::from_translation(-1.0, 1.0, 0.0) * transform
|
||||||
}
|
}
|
||||||
|
|
||||||
fn draw_alpha_tiles(&mut self, count: u32) {
|
fn draw_alpha_tiles(&mut self, count: u32) {
|
||||||
|
|
Loading…
Reference in New Issue