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 {
|
||||
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 = transform.post_mul(&Transform3DF::from_translation(
|
||||
-self.position.x(),
|
||||
-self.position.y(),
|
||||
-self.position.z(),
|
||||
));
|
||||
transform *= Transform3DF::from_uniform_scale(2.0 * self.scale);
|
||||
transform *= Transform3DF::from_translation(-self.position.x(),
|
||||
-self.position.y(),
|
||||
-self.position.z());
|
||||
|
||||
// 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
|
||||
}
|
||||
|
|
|
@ -256,10 +256,9 @@ impl<W> DemoApp<W> where W: Window {
|
|||
if modelview_transform.offset(*velocity) {
|
||||
self.dirty = true;
|
||||
}
|
||||
let perspective = scene_transform
|
||||
.perspective
|
||||
.post_mul(&scene_transform.modelview_to_eye)
|
||||
.post_mul(&modelview_transform.to_transform());
|
||||
let perspective = scene_transform.perspective *
|
||||
scene_transform.modelview_to_eye *
|
||||
modelview_transform.to_transform();
|
||||
Some(RenderTransform::Perspective(perspective))
|
||||
}
|
||||
Camera::TwoD(transform) => Some(RenderTransform::Transform2D(transform)),
|
||||
|
@ -356,13 +355,20 @@ impl<W> DemoApp<W> where W: Window {
|
|||
*scene_transform = eye_transforms[0];
|
||||
for (index, eye_transform) in eye_transforms.iter().enumerate().skip(1) {
|
||||
let weight = 1.0 / (index + 1) as f32;
|
||||
scene_transform.perspective.transform = 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);
|
||||
scene_transform.perspective.transform =
|
||||
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?
|
||||
let z_offset = -DEFAULT_EYE_OFFSET * scene_transform.perspective.transform.c0.x();
|
||||
scene_transform.modelview_to_eye = scene_transform.modelview_to_eye
|
||||
.pre_mul(&Transform3DF::from_translation(0.0, 0.0, z_offset));
|
||||
let z_offset = -DEFAULT_EYE_OFFSET *
|
||||
scene_transform.perspective.transform.c0.x();
|
||||
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')) => {
|
||||
|
|
|
@ -169,18 +169,16 @@ impl<W> DemoApp<W> where W: Window {
|
|||
1.0,
|
||||
);
|
||||
|
||||
let scene_transform_matrix = scene_transform
|
||||
.perspective
|
||||
.post_mul(&scene_transform.modelview_to_eye)
|
||||
.post_mul(&modelview_transform.to_transform())
|
||||
.post_mul(&quad_scale_transform);
|
||||
let scene_transform_matrix = scene_transform.perspective *
|
||||
scene_transform.modelview_to_eye *
|
||||
modelview_transform.to_transform() *
|
||||
quad_scale_transform;
|
||||
|
||||
let eye_transform = &eye_transforms[render_scene_index as usize];
|
||||
let eye_transform_matrix = eye_transform
|
||||
.perspective
|
||||
.post_mul(&eye_transform.modelview_to_eye)
|
||||
.post_mul(&modelview_transform.to_transform())
|
||||
.post_mul(&quad_scale_transform);
|
||||
let eye_transform_matrix = eye_transform.perspective *
|
||||
eye_transform.modelview_to_eye *
|
||||
modelview_transform.to_transform() *
|
||||
quad_scale_transform;
|
||||
|
||||
debug!(
|
||||
"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 mut base_transform = perspective.transform;
|
||||
base_transform = base_transform.post_mul(&Transform3DF::from_translation(
|
||||
-0.5 * self.scene_metadata.view_box.max_x(),
|
||||
self.scene_metadata.view_box.max_y(),
|
||||
-0.5 * ground_scale,
|
||||
));
|
||||
let base_transform = perspective.transform *
|
||||
Transform3DF::from_translation(-0.5 * self.scene_metadata.view_box.max_x(),
|
||||
self.scene_metadata.view_box.max_y(),
|
||||
-0.5 * ground_scale);
|
||||
|
||||
// Fill ground.
|
||||
let mut transform = base_transform;
|
||||
transform =
|
||||
transform.post_mul(&Transform3DF::from_scale(ground_scale, 1.0, ground_scale));
|
||||
let transform = base_transform * Transform3DF::from_scale(ground_scale, 1.0, ground_scale);
|
||||
|
||||
// Don't clear the first scene after drawing it.
|
||||
let clear_color = if render_scene_index == 0 {
|
||||
|
|
|
@ -14,7 +14,7 @@ use crate::vector::{Vector2F, Vector2I, Vector4F};
|
|||
use crate::rect::RectF;
|
||||
use crate::transform2d::Matrix2x2F;
|
||||
use pathfinder_simd::default::F32x4;
|
||||
use std::ops::{Add, Neg};
|
||||
use std::ops::{Add, Mul, MulAssign, Neg};
|
||||
|
||||
/// 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]
|
||||
pub fn transform_point(&self, point: Vector4F) -> Vector4F {
|
||||
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 {
|
||||
type Output = Matrix2x2F;
|
||||
#[inline]
|
||||
|
@ -366,11 +367,14 @@ impl Perspective {
|
|||
let max_point = upper_left.max(upper_right).max(lower_left).max(lower_right);
|
||||
RectF::from_points(min_point, max_point)
|
||||
}
|
||||
}
|
||||
|
||||
impl Mul<Transform3DF> for Perspective {
|
||||
type Output = Perspective;
|
||||
#[inline]
|
||||
pub fn post_mul(&self, other: &Transform3DF) -> Perspective {
|
||||
fn mul(self, other: Transform3DF) -> Perspective {
|
||||
Perspective {
|
||||
transform: self.transform.post_mul(other),
|
||||
transform: self.transform * other,
|
||||
window_size: self.window_size,
|
||||
}
|
||||
}
|
||||
|
|
|
@ -472,7 +472,7 @@ where
|
|||
let draw_viewport = self.draw_viewport().size().to_f32();
|
||||
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);
|
||||
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) {
|
||||
|
|
Loading…
Reference in New Issue