Skip to content

Commit df9487c

Browse files
author
Peter
committed
Associativity issue because w is not multiplied
1 parent 2e30b5c commit df9487c

File tree

2 files changed

+41
-5
lines changed

2 files changed

+41
-5
lines changed

src/matrix4d.rs

Lines changed: 23 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -369,10 +369,10 @@ where T: Copy + Clone +
369369
/// The input point must be use the unit Src, and the returned point has the unit Dst.
370370
#[inline]
371371
pub fn transform_point4d(&self, p: &TypedPoint4D<T, Src>) -> TypedPoint4D<T, Dst> {
372-
let x = p.x * self.m11 + p.y * self.m21 + p.z * self.m31 + self.m41;
373-
let y = p.x * self.m12 + p.y * self.m22 + p.z * self.m32 + self.m42;
374-
let z = p.x * self.m13 + p.y * self.m23 + p.z * self.m33 + self.m43;
375-
let w = p.x * self.m14 + p.y * self.m24 + p.z * self.m34 + self.m44;
372+
let x = p.x * self.m11 + p.y * self.m21 + p.z * self.m31 + p.w * self.m41;
373+
let y = p.x * self.m12 + p.y * self.m22 + p.z * self.m32 + p.w * self.m42;
374+
let z = p.x * self.m13 + p.y * self.m23 + p.z * self.m33 + p.w * self.m43;
375+
let w = p.x * self.m14 + p.y * self.m24 + p.z * self.m34 + p.w * self.m44;
376376
TypedPoint4D::new(x, y, z, w)
377377
}
378378

@@ -553,7 +553,8 @@ impl<T: Copy + fmt::Debug, Src, Dst> fmt::Debug for TypedMatrix4D<T, Src, Dst> {
553553

554554
#[cfg(test)]
555555
mod tests {
556-
use point::Point2D;
556+
use approxeq::ApproxEq;
557+
use point::{Point2D, Point4D};
557558
use Radians;
558559
use super::*;
559560

@@ -644,4 +645,21 @@ mod tests {
644645
let m2 = Matrix4D::identity().pre_translated(1.0, 2.0, 3.0).pre_scaled(1.0, 2.0, 3.0);
645646
assert!(m1.approx_eq(&m2));
646647
}
648+
649+
#[test]
650+
pub fn test_transform_associativity() {
651+
let m1 = Mf32::row_major(3.0, 2.0, 1.5, 1.0,
652+
0.0, 4.5, -1.0, -4.0,
653+
0.0, 3.5, 2.5, 40.0,
654+
0.0, 3.0, 0.0, 1.0);
655+
let m2 = Mf32::row_major(1.0, -1.0, 3.0, 0.0,
656+
-1.0, 0.5, 0.0, 2.0,
657+
1.5, -2.0, 6.0, 0.0,
658+
-2.5, 6.0, 1.0, 1.0);
659+
660+
let p = Point4D::new(1.0, 3.0, 5.0, 1.0);
661+
let p1 = m2.pre_mul(&m1).transform_point4d(&p);
662+
let p2 = m2.transform_point4d(&m1.transform_point4d(&p));
663+
assert!(p1.approx_eq(&p2));
664+
}
647665
}

src/point.rs

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
// except according to those terms.
99

1010
use super::UnknownUnit;
11+
use approxeq::ApproxEq;
1112
use length::Length;
1213
use scale_factor::ScaleFactor;
1314
use size::TypedSize2D;
@@ -693,6 +694,23 @@ impl<T: NumCast + Copy, U> TypedPoint4D<T, U> {
693694
}
694695
}
695696

697+
impl<T: ApproxEq<T>, U> ApproxEq<T> for TypedPoint4D<T, U> {
698+
fn approx_epsilon() -> T {
699+
T::approx_epsilon()
700+
}
701+
702+
fn approx_eq_eps(&self, other: &Self, approx_epsilon: &T) -> bool {
703+
self.x.approx_eq_eps(&other.x, approx_epsilon)
704+
&& self.y.approx_eq_eps(&other.y, approx_epsilon)
705+
&& self.z.approx_eq_eps(&other.z, approx_epsilon)
706+
&& self.w.approx_eq_eps(&other.w, approx_epsilon)
707+
}
708+
709+
fn approx_eq(&self, other: &Self) -> bool {
710+
self.approx_eq_eps(&other, &Self::approx_epsilon())
711+
}
712+
}
713+
696714
#[cfg(test)]
697715
mod point2d {
698716
use super::Point2D;

0 commit comments

Comments
 (0)