Skip to content

Commit cbd1602

Browse files
author
bors-servo
committed
Auto merge of #98 - glennw:matrix-inverse, r=pcwalton
Add 4x4 matrix inverse + basic tests. <!-- Reviewable:start --> [<img src="https://reviewable.io/review_button.png" height=40 alt="Review on Reviewable"/>](https://reviewable.io/reviews/servo/euclid/98) <!-- Reviewable:end -->
2 parents 9cc01f5 + 2535f97 commit cbd1602

File tree

2 files changed

+148
-1
lines changed

2 files changed

+148
-1
lines changed

Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[package]
22
name = "euclid"
3-
version = "0.1.4"
3+
version = "0.1.5"
44
authors = ["The Servo Project Developers"]
55
description = "Geometry primitives"
66
documentation = "http://doc.servo.org/euclid/"

src/matrix.rs

Lines changed: 147 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -99,6 +99,111 @@ impl Matrix4 {
9999
m.m41*self.m14 + m.m42*self.m24 + m.m43*self.m34 + m.m44*self.m44)
100100
}
101101

102+
pub fn invert(&self) -> Matrix4 {
103+
let det = self.determinant();
104+
105+
if det == 0.0 {
106+
return Matrix4::identity();
107+
}
108+
109+
// todo(gw): this could be made faster by special casing
110+
// for simpler matrix types.
111+
let m = Matrix4::new(
112+
self.m23*self.m34*self.m42 - self.m24*self.m33*self.m42 +
113+
self.m24*self.m32*self.m43 - self.m22*self.m34*self.m43 -
114+
self.m23*self.m32*self.m44 + self.m22*self.m33*self.m44,
115+
116+
self.m14*self.m33*self.m42 - self.m13*self.m34*self.m42 -
117+
self.m14*self.m32*self.m43 + self.m12*self.m34*self.m43 +
118+
self.m13*self.m32*self.m44 - self.m12*self.m33*self.m44,
119+
120+
self.m13*self.m24*self.m42 - self.m14*self.m23*self.m42 +
121+
self.m14*self.m22*self.m43 - self.m12*self.m24*self.m43 -
122+
self.m13*self.m22*self.m44 + self.m12*self.m23*self.m44,
123+
124+
self.m14*self.m23*self.m32 - self.m13*self.m24*self.m32 -
125+
self.m14*self.m22*self.m33 + self.m12*self.m24*self.m33 +
126+
self.m13*self.m22*self.m34 - self.m12*self.m23*self.m34,
127+
128+
self.m24*self.m33*self.m41 - self.m23*self.m34*self.m41 -
129+
self.m24*self.m31*self.m43 + self.m21*self.m34*self.m43 +
130+
self.m23*self.m31*self.m44 - self.m21*self.m33*self.m44,
131+
132+
self.m13*self.m34*self.m41 - self.m14*self.m33*self.m41 +
133+
self.m14*self.m31*self.m43 - self.m11*self.m34*self.m43 -
134+
self.m13*self.m31*self.m44 + self.m11*self.m33*self.m44,
135+
136+
self.m14*self.m23*self.m41 - self.m13*self.m24*self.m41 -
137+
self.m14*self.m21*self.m43 + self.m11*self.m24*self.m43 +
138+
self.m13*self.m21*self.m44 - self.m11*self.m23*self.m44,
139+
140+
self.m13*self.m24*self.m31 - self.m14*self.m23*self.m31 +
141+
self.m14*self.m21*self.m33 - self.m11*self.m24*self.m33 -
142+
self.m13*self.m21*self.m34 + self.m11*self.m23*self.m34,
143+
144+
self.m22*self.m34*self.m41 - self.m24*self.m32*self.m41 +
145+
self.m24*self.m31*self.m42 - self.m21*self.m34*self.m42 -
146+
self.m22*self.m31*self.m44 + self.m21*self.m32*self.m44,
147+
148+
self.m14*self.m32*self.m41 - self.m12*self.m34*self.m41 -
149+
self.m14*self.m31*self.m42 + self.m11*self.m34*self.m42 +
150+
self.m12*self.m31*self.m44 - self.m11*self.m32*self.m44,
151+
152+
self.m12*self.m24*self.m41 - self.m14*self.m22*self.m41 +
153+
self.m14*self.m21*self.m42 - self.m11*self.m24*self.m42 -
154+
self.m12*self.m21*self.m44 + self.m11*self.m22*self.m44,
155+
156+
self.m14*self.m22*self.m31 - self.m12*self.m24*self.m31 -
157+
self.m14*self.m21*self.m32 + self.m11*self.m24*self.m32 +
158+
self.m12*self.m21*self.m34 - self.m11*self.m22*self.m34,
159+
160+
self.m23*self.m32*self.m41 - self.m22*self.m33*self.m41 -
161+
self.m23*self.m31*self.m42 + self.m21*self.m33*self.m42 +
162+
self.m22*self.m31*self.m43 - self.m21*self.m32*self.m43,
163+
164+
self.m12*self.m33*self.m41 - self.m13*self.m32*self.m41 +
165+
self.m13*self.m31*self.m42 - self.m11*self.m33*self.m42 -
166+
self.m12*self.m31*self.m43 + self.m11*self.m32*self.m43,
167+
168+
self.m13*self.m22*self.m41 - self.m12*self.m23*self.m41 -
169+
self.m13*self.m21*self.m42 + self.m11*self.m23*self.m42 +
170+
self.m12*self.m21*self.m43 - self.m11*self.m22*self.m43,
171+
172+
self.m12*self.m23*self.m31 - self.m13*self.m22*self.m31 +
173+
self.m13*self.m21*self.m32 - self.m11*self.m23*self.m32 -
174+
self.m12*self.m21*self.m33 + self.m11*self.m22*self.m33
175+
);
176+
177+
m.mul_s(1.0 / det)
178+
}
179+
180+
pub fn determinant(&self) -> f32 {
181+
self.m14 * self.m23 * self.m32 * self.m41 -
182+
self.m13 * self.m24 * self.m32 * self.m41 -
183+
self.m14 * self.m22 * self.m33 * self.m41 +
184+
self.m12 * self.m24 * self.m33 * self.m41 +
185+
self.m13 * self.m22 * self.m34 * self.m41 -
186+
self.m12 * self.m23 * self.m34 * self.m41 -
187+
self.m14 * self.m23 * self.m31 * self.m42 +
188+
self.m13 * self.m24 * self.m31 * self.m42 +
189+
self.m14 * self.m21 * self.m33 * self.m42 -
190+
self.m11 * self.m24 * self.m33 * self.m42 -
191+
self.m13 * self.m21 * self.m34 * self.m42 +
192+
self.m11 * self.m23 * self.m34 * self.m42 +
193+
self.m14 * self.m22 * self.m31 * self.m43 -
194+
self.m12 * self.m24 * self.m31 * self.m43 -
195+
self.m14 * self.m21 * self.m32 * self.m43 +
196+
self.m11 * self.m24 * self.m32 * self.m43 +
197+
self.m12 * self.m21 * self.m34 * self.m43 -
198+
self.m11 * self.m22 * self.m34 * self.m43 -
199+
self.m13 * self.m22 * self.m31 * self.m44 +
200+
self.m12 * self.m23 * self.m31 * self.m44 +
201+
self.m13 * self.m21 * self.m32 * self.m44 -
202+
self.m11 * self.m23 * self.m32 * self.m44 -
203+
self.m12 * self.m21 * self.m33 * self.m44 +
204+
self.m11 * self.m22 * self.m33 * self.m44
205+
}
206+
102207
pub fn mul_s(&self, x: f32) -> Matrix4 {
103208
Matrix4::new(self.m11 * x, self.m12 * x, self.m13 * x, self.m14 * x,
104209
self.m21 * x, self.m22 * x, self.m23 * x, self.m24 * x,
@@ -226,3 +331,45 @@ pub fn test_ortho() {
226331
debug!("result={:?} expected={:?}", result, expected);
227332
assert!(result.approx_eq(&expected));
228333
}
334+
335+
#[test]
336+
pub fn test_invert_simple() {
337+
let m1 = Matrix4::identity();
338+
let m2 = m1.invert();
339+
assert!(m1.approx_eq(&m2));
340+
}
341+
342+
#[test]
343+
pub fn test_invert_scale() {
344+
let m1 = Matrix4::create_scale(1.5, 0.3, 2.1);
345+
let m2 = m1.invert();
346+
assert!(m1.mul(&m2).approx_eq(&Matrix4::identity()));
347+
}
348+
349+
#[test]
350+
pub fn test_invert_translate() {
351+
let m1 = Matrix4::create_translation(-132.0, 0.3, 493.0);
352+
let m2 = m1.invert();
353+
assert!(m1.mul(&m2).approx_eq(&Matrix4::identity()));
354+
}
355+
356+
#[test]
357+
pub fn test_invert_rotate() {
358+
let m1 = Matrix4::create_rotation(0.0, 1.0, 0.0, 1.57);
359+
let m2 = m1.invert();
360+
assert!(m1.mul(&m2).approx_eq(&Matrix4::identity()));
361+
}
362+
363+
#[test]
364+
pub fn test_invert_transform_point_2d() {
365+
let m1 = Matrix4::create_translation(100.0, 200.0, 0.0);
366+
let m2 = m1.invert();
367+
assert!(m1.mul(&m2).approx_eq(&Matrix4::identity()));
368+
369+
let p1 = Point2D::new(1000.0, 2000.0);
370+
let p2 = m1.transform_point(&p1);
371+
assert!(p2.eq(&Point2D::new(1100.0, 2200.0)));
372+
373+
let p3 = m2.transform_point(&p2);
374+
assert!(p3.eq(&p1));
375+
}

0 commit comments

Comments
 (0)