1use super::matrix4x4::Matrix4x4;
2use crate::core::base::*;
3use crate::core::geometry::*;
4use crate::core::interaction::*;
5
6use std::ops;
7
8const MACHINE_EPSILON: Float = Float::EPSILON * 0.5;
9const GAMMA3: Float = (3.0 * MACHINE_EPSILON) / (1.0 - (3.0 * MACHINE_EPSILON));
10
11#[inline]
12fn radians(x: Float) -> Float {
13 return x * (PI / 180.0);
14}
15
16#[derive(Debug, PartialEq, Copy, Clone)]
17pub struct Transform {
18 pub m: Matrix4x4,
19 pub minv: Matrix4x4,
20}
21
22impl Transform {
23 pub fn new() -> Self {
24 Self::identity()
25 }
26
27 pub fn identity() -> Self {
28 let m = Matrix4x4::identity();
29 let minv = Matrix4x4::identity();
30 Transform { m, minv }
31 }
32
33 pub fn translate(x: Float, y: Float, z: Float) -> Self {
34 let m = Matrix4x4::translate(x, y, z);
35 let minv = Matrix4x4::translate(-x, -y, -z);
36 Transform { m, minv }
37 }
38
39 pub fn scale(x: Float, y: Float, z: Float) -> Self {
40 let m = Matrix4x4::scale(x, y, z);
41 let minv = Matrix4x4::scale(1.0 / x, 1.0 / y, 1.0 / z);
42 Transform { m, minv }
43 }
44
45 pub fn rotate_x(theta: Float) -> Self {
46 let m = Matrix4x4::rotate_x(theta);
47 let minv = m.transpose();
48 Transform { m, minv }
49 }
50
51 pub fn rotate_y(theta: Float) -> Self {
52 let m = Matrix4x4::rotate_y(theta);
53 let minv = m.transpose();
54 Transform { m, minv }
55 }
56
57 pub fn rotate_z(theta: Float) -> Self {
58 let m = Matrix4x4::rotate_z(theta);
59 let minv = m.transpose();
60 Transform { m, minv }
61 }
62
63 pub fn rotate(theta: Float, x: Float, y: Float, z: Float) -> Transform {
64 let m = Matrix4x4::rotate(theta, x, y, z);
65 let minv = m.transpose();
66 Transform { m, minv }
67 }
68
69 pub fn look_at(
70 ex: Float,
71 ey: Float,
72 ez: Float,
73 lx: Float,
74 ly: Float,
75 lz: Float,
76 ux: Float,
77 uy: Float,
78 uz: Float,
79 ) -> Self {
80 let c2w = Matrix4x4::camera_to_world(ex, ey, ez, lx, ly, lz, ux, uy, uz);
81 let w2c = c2w.inverse().unwrap();
82 Transform { m: w2c, minv: c2w }
83 }
84
85 pub fn orthographic(z_near: Float, z_far: Float) -> Self {
86 return Self::scale(1.0, 1.0, 1.0 / (z_far - z_near)) * Self::translate(0.0, 0.0, -z_near);
87 }
88
89 pub fn perspective(fov: Float, n: Float, f: Float) -> Self {
90 #[rustfmt::skip]
91 let persp = Matrix4x4::new(
92 1.0, 0.0, 0.0, 0.0,
93 0.0, 1.0, 0.0, 0.0,
94 0.0, 0.0, f / (f - n), -f * n / (f - n),
95 0.0, 0.0, 1.0, 0.0,
96 );
97 let inv_tan_ang = 1.0 / Float::tan(radians(fov) / 2.0);
98 return Self::scale(inv_tan_ang, inv_tan_ang, 1.0) * Transform::from(persp);
99 }
100
101 pub fn set(&mut self, other: &Transform) {
102 self.m = other.m;
103 self.minv = other.minv;
104 }
105
106 pub fn inverse(&self) -> Self {
107 Transform {
108 m: self.minv,
109 minv: self.m,
110 }
111 }
112
113 pub fn swaps_handedness(&self) -> bool {
114 let m = &self.m;
115 #[rustfmt::skip]
116 let det = m.m[4 * 0 + 0] * (m.m[4 * 1 + 1] * m.m[4 * 2 + 2] - m.m[4 * 1 + 2] * m.m[4 * 2 + 1]) -
117 m.m[4 * 0 + 1] * (m.m[4 * 1 + 0] * m.m[4 * 2 + 2] - m.m[4 * 1 + 2] * m.m[4 * 2 + 0]) +
118 m.m[4 * 0 + 2] * (m.m[4 * 1 + 0] * m.m[4 * 2 + 1] - m.m[4 * 1 + 1] * m.m[4 * 2 + 0]);
119 return det < 0.0;
120 }
121
122 pub fn transform_point(&self, p: &Point3f) -> Point3f {
123 return self.m.transform_point(p);
124 }
125
126 pub fn transform_vector(&self, p: &Vector3f) -> Vector3f {
127 return self.m.transform_vector(p);
128 }
129
130 pub fn transform_normal(&self, p: &Normal3f) -> Normal3f {
131 return self.minv.transform_normal(p);
132 }
133
134 pub fn transform_bounds(&self, bounds: &Bounds3f) -> Bounds3f {
135 let min = &bounds.min;
136 let max = &bounds.max;
137 let p = [
138 [min.x, min.y, min.z],
139 [min.x, min.y, max.z],
140 [min.x, max.y, min.z],
141 [min.x, max.y, max.z],
142 [max.x, min.y, min.z],
143 [max.x, min.y, max.z],
144 [max.x, max.y, min.z],
145 [max.x, max.y, max.z],
146 ];
147 let q: Vec<Vector3f> = p
148 .iter()
149 .map(|v| -> Vector3f {
150 return self.transform_point(&Vector3f::new(v[0], v[1], v[2]));
151 })
152 .collect();
153 let min = q
154 .iter()
155 .map(|v| [v.x, v.y, v.z])
156 .reduce(|acc, v| {
157 return [
158 Float::min(acc[0], v[0]),
159 Float::min(acc[1], v[1]),
160 Float::min(acc[2], v[2]),
161 ];
162 })
163 .unwrap();
164 let max = q
165 .iter()
166 .map(|v| [v.x, v.y, v.z])
167 .reduce(|acc, v| {
168 return [
169 Float::max(acc[0], v[0]),
170 Float::max(acc[1], v[1]),
171 Float::max(acc[2], v[2]),
172 ];
173 })
174 .unwrap();
175 assert!(min[0] <= max[0]);
176 assert!(min[1] <= max[1]);
177 assert!(min[2] <= max[2]);
178 assert!(q.iter().all(|v| v.x >= min[0] && v.x <= max[0]));
179 assert!(q.iter().all(|v| v.y >= min[1] && v.y <= max[1]));
180 assert!(q.iter().all(|v| v.z >= min[2] && v.z <= max[2]));
181 return Bounds3f::from(((min[0], min[1], min[2]), (max[0], max[1], max[2])));
182 }
183
184 pub fn transform_point_with_error(&self, p: &Point3f) -> (Point3f, Vector3f) {
185 let x = p.x;
186 let y = p.y;
187 let z = p.z;
188 let p = self.transform_point(p);
189 let x_abs_sum = Float::abs(self.m.m[4 * 0 + 0] * x)
190 + Float::abs(self.m.m[4 * 0 + 1] * y)
191 + Float::abs(self.m.m[4 * 0 + 2] * z)
192 + Float::abs(self.m.m[4 * 0 + 3]);
193 let y_abs_sum = Float::abs(self.m.m[4 * 1 + 0] * x)
194 + Float::abs(self.m.m[4 * 1 + 1] * y)
195 + Float::abs(self.m.m[4 * 1 + 2] * z)
196 + Float::abs(self.m.m[4 * 1 + 3]);
197 let z_abs_sum = Float::abs(self.m.m[4 * 2 + 0] * x)
198 + Float::abs(self.m.m[4 * 2 + 1] * y)
199 + Float::abs(self.m.m[4 * 2 + 2] * z)
200 + Float::abs(self.m.m[4 * 2 + 3]);
201 let p_error = GAMMA3 * Vector3f::new(x_abs_sum, y_abs_sum, z_abs_sum);
202 return (p, p_error);
203 }
204
205 pub fn transform_point_with_abs_error(
206 &self,
207 p: &Point3f,
208 pt_error: &Vector3f,
209 ) -> (Point3f, Vector3f) {
210 let x = p.x;
211 let y = p.y;
212 let z = p.z;
213 let p = self.transform_point(p);
214 let ex = (GAMMA3 + 1.0)
215 * (Float::abs(self.m.m[4 * 0 + 0]) * pt_error.x
216 + Float::abs(self.m.m[4 * 0 + 1]) * pt_error.y
217 + Float::abs(self.m.m[4 * 0 + 2]) * pt_error.z)
218 + GAMMA3
219 * (Float::abs(self.m.m[4 * 0 + 0] * x)
220 + Float::abs(self.m.m[4 * 0 + 1] * y)
221 + Float::abs(self.m.m[4 * 0 + 2] * z)
222 + Float::abs(self.m.m[4 * 0 + 3]));
223 let ey = (GAMMA3 + 1.0)
224 * (Float::abs(self.m.m[4 * 1 + 0]) * pt_error.x
225 + Float::abs(self.m.m[4 * 1 + 1]) * pt_error.y
226 + Float::abs(self.m.m[4 * 1 + 2]) * pt_error.z)
227 + GAMMA3
228 * (Float::abs(self.m.m[4 * 1 + 0] * x)
229 + Float::abs(self.m.m[4 * 1 + 1] * y)
230 + Float::abs(self.m.m[4 * 1 + 2] * z)
231 + Float::abs(self.m.m[4 * 1 + 3]));
232 let ez = (GAMMA3 + 1.0)
233 * (Float::abs(self.m.m[4 * 2 + 0]) * pt_error.x
234 + Float::abs(self.m.m[4 * 2 + 1]) * pt_error.y
235 + Float::abs(self.m.m[4 * 2 + 2]) * pt_error.z)
236 + GAMMA3
237 * (Float::abs(self.m.m[4 * 2 + 0] * x)
238 + Float::abs(self.m.m[4 * 2 + 1] * y)
239 + Float::abs(self.m.m[4 * 2 + 2] * z)
240 + Float::abs(self.m.m[4 * 2 + 3]));
241 let p_error = Vector3f::new(ex, ey, ez);
242 return (p, p_error);
243 }
244
245 pub fn transform_vector_with_error(&self, v: &Vector3f) -> (Vector3f, Vector3f) {
246 let x = v.x;
247 let y = v.y;
248 let z = v.z;
249 let ex = GAMMA3
250 * (Float::abs(self.m.m[4 * 0 + 0] * v.x)
251 + Float::abs(self.m.m[4 * 0 + 1] * v.y)
252 + Float::abs(self.m.m[4 * 0 + 2] * v.z));
253 let ey = GAMMA3
254 * (Float::abs(self.m.m[4 * 1 + 0] * v.x)
255 + Float::abs(self.m.m[4 * 1 + 1] * v.y)
256 + Float::abs(self.m.m[4 * 1 + 2] * v.z));
257 let ez = GAMMA3
258 * (Float::abs(self.m.m[4 * 2 + 0] * v.x)
259 + Float::abs(self.m.m[4 * 2 + 1] * v.y)
260 + Float::abs(self.m.m[4 * 2 + 2] * v.z));
261 let vv = Vector3f::new(
262 self.m.m[4 * 0 + 0] * x + self.m.m[4 * 0 + 1] * y + self.m.m[4 * 0 + 2] * z,
263 self.m.m[4 * 1 + 0] * x + self.m.m[4 * 1 + 1] * y + self.m.m[4 * 1 + 2] * z,
264 self.m.m[4 * 2 + 0] * x + self.m.m[4 * 2 + 1] * y + self.m.m[4 * 2 + 2] * z,
265 );
266 let ve = Vector3f::new(ex, ey, ez);
267 return (vv, ve);
268 }
269
270 pub fn transform_ray(&self, r: &Ray) -> (Ray, Vector3f, Vector3f) {
271 let (mut o, o_error) = self.transform_point_with_error(&r.o);
272 let (d, d_error) = self.transform_vector_with_error(&r.d);
273 let t_max = r.t_max.get();
274 let length_squared = d.length_squared();
275 if length_squared > 0.0 {
276 let dt = d.abs().dot(&o_error) / length_squared;
277 o += d * dt;
278 }
279 let mut r2 = Ray::new(&o, &d, t_max, r.time);
280 r2.medium = r.medium.clone();
281 return (r2, o_error, d_error);
282 }
283
284 pub fn transform_ray_differential(
285 &self,
286 r: &RayDifferential,
287 ) -> (RayDifferential, Vector3f, Vector3f) {
288 let mut ret = r.clone();
289 let (tr, o_error, d_error) = self.transform_ray(&r.ray);
290 ret.ray = tr;
291 ret.has_differentials = r.has_differentials;
292 ret.rx_origin = self.transform_point(&r.rx_origin);
293 ret.ry_origin = self.transform_point(&r.ry_origin);
294 ret.rx_direction = self.transform_vector(&r.rx_direction);
295 ret.ry_direction = self.transform_vector(&r.ry_direction);
296 return (ret, o_error, d_error);
297 }
298
299 pub fn transform_surface_interaction(&self, si: &SurfaceInteraction) -> SurfaceInteraction {
300 let mut ret = si.clone();
301 let (p, p_error) = self.transform_point_with_abs_error(&si.p, &si.p_error);
302 ret.p = p;
303 ret.p_error = p_error;
304 ret.n = self.transform_normal(&si.n).normalize();
305 ret.wo = self.transform_vector(&si.wo).normalize();
306 ret.dpdu = self.transform_vector(&ret.dpdu);
308 ret.dpdv = self.transform_vector(&ret.dpdv);
309 ret.dndu = self.transform_normal(&ret.dndu);
310 ret.dndv = self.transform_normal(&ret.dndv);
311
312 ret.shading.n = self.transform_normal(&si.shading.n).normalize();
313 ret.shading.dpdu = self.transform_vector(&ret.shading.dpdu);
314 ret.shading.dpdv = self.transform_vector(&ret.shading.dpdv);
315 ret.shading.dndu = self.transform_normal(&ret.shading.dndu);
316 ret.shading.dndv = self.transform_normal(&ret.shading.dndv);
317
318 ret.dpdx = self.transform_vector(&ret.dpdx);
319 ret.dpdy = self.transform_vector(&ret.dpdy);
320
321 ret.shading.n = face_forward(&ret.shading.n, &ret.n);
322 return ret;
323 }
324
325 pub fn is_identity(&self) -> bool {
326 return false;
327 }
329
330 pub fn has_scale(&self) -> bool {
331 let m = &self.m;
332 let la2 = m.m[4 * 0 + 0] * m.m[4 * 0 + 0]
333 + m.m[4 * 0 + 1] * m.m[4 * 0 + 1]
334 + m.m[4 * 0 + 2] * m.m[4 * 0 + 2];
335 let lb2 = m.m[4 * 1 + 0] * m.m[4 * 1 + 0]
336 + m.m[4 * 1 + 1] * m.m[4 * 1 + 1]
337 + m.m[4 * 1 + 2] * m.m[4 * 1 + 2];
338 let lc2 = m.m[4 * 2 + 0] * m.m[4 * 2 + 0]
339 + m.m[4 * 2 + 1] * m.m[4 * 2 + 1]
340 + m.m[4 * 2 + 2] * m.m[4 * 2 + 2];
341 let det = m.m[4 * 0 + 0]
342 * (m.m[4 * 1 + 1] * m.m[4 * 2 + 2] - m.m[4 * 1 + 2] * m.m[4 * 2 + 1])
343 - m.m[4 * 0 + 1] * (m.m[4 * 1 + 0] * m.m[4 * 2 + 2] - m.m[4 * 1 + 2] * m.m[4 * 2 + 0])
344 + m.m[4 * 0 + 2] * (m.m[4 * 1 + 0] * m.m[4 * 2 + 1] - m.m[4 * 1 + 1] * m.m[4 * 2 + 0]);
345 return Float::abs(det) < 0.01 || (la2 < 0.01 || lb2 < 0.01 || lc2 < 0.01);
346 }
347}
348
349impl Default for Transform {
350 fn default() -> Self {
351 Self::new()
352 }
353}
354
355impl ops::Mul<Transform> for Transform {
356 type Output = Transform;
357 fn mul(self, t2: Transform) -> Transform {
358 return Transform {
359 m: self.m * t2.m,
360 minv: t2.minv * self.minv,
361 };
362 }
363}
364
365impl From<[Float; 16]> for Transform {
366 fn from(v: [Float; 16]) -> Self {
367 let m = Matrix4x4::from(v);
368 let minv = m.inverse().unwrap();
369 Transform { m, minv }
370 }
371}
372
373impl From<Matrix4x4> for Transform {
374 fn from(m: Matrix4x4) -> Self {
375 Transform {
376 m,
377 minv: m.inverse().unwrap(),
378 }
379 }
380}
381
382impl From<(Matrix4x4, Matrix4x4)> for Transform {
383 fn from(v: (Matrix4x4, Matrix4x4)) -> Self {
384 Transform { m: v.0, minv: v.1 }
385 }
386}
387
388#[cfg(test)]
389mod tests {
390 use super::*;
391
392 #[test]
393 fn test_001() {
394 let t1 = Transform::scale(4.0, 4.0, 4.0);
395 let t2 = t1.inverse();
396 let t3 = Transform::scale(0.25, 0.25, 0.25);
397 assert_eq!(t2, t3);
398 }
399
400 #[test]
401 fn test_002() {
402 let t1 = Transform::translate(4.0, 4.0, 4.0);
403 let t2 = t1.inverse();
404 let t3 = Transform::translate(-4.0, -4.0, -4.0);
405 assert_eq!(t2, t3);
406 }
407
408 #[test]
409 fn test_003() {
410 let t1 = Transform::rotate_x(90.0);
411 let t2 = t1.inverse();
412 let t3 = Transform::rotate_x(-90.0);
413 assert_eq!(t2, t3);
414 }
415
416 #[test]
417 fn test_004() {
418 let t1 = Transform::rotate_y(90.0);
419 let t2 = t1.inverse();
420 let t3 = Transform::rotate_y(-90.0);
421 assert_eq!(t2, t3);
422 }
423
424 #[test]
425 fn test_005() {
426 let t1 = Transform::rotate_z(90.0);
427 let t2 = t1.inverse();
428 let t3 = Transform::rotate_z(-90.0);
429 assert_eq!(t2, t3);
430 }
431
432 #[test]
433 fn test_007() {
434 let v1 = Vector3f::new(0.0, 1.0, 1.0);
435 let t1 = Transform::look_at(0.0, 1.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0); let v2 = t1.transform_point(&v1);
437 assert!(Vector3f::distance_squared(&v2, &Vector3f::zero()) < 0.1);
438 }
439}