pbrt_r3/core/transform/
transform.rs

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        //
307        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        //return self.m.is_identity();
328    }
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); //world2camera
436        let v2 = t1.transform_point(&v1);
437        assert!(Vector3f::distance_squared(&v2, &Vector3f::zero()) < 0.1);
438    }
439}