1 #[macro_use] 2 mod support; 3 4 macro_rules! impl_mat4_tests { 5 ($t:ident, $newmat4:ident, $newvec4:ident, $newvec3:ident, $mat4:ident, $mat3:ident, $quat:ident, $vec4:ident, $vec3:ident) => { 6 use core::$t::INFINITY; 7 use core::$t::NAN; 8 use core::$t::NEG_INFINITY; 9 10 const IDENTITY: [[$t; 4]; 4] = [ 11 [1.0, 0.0, 0.0, 0.0], 12 [0.0, 1.0, 0.0, 0.0], 13 [0.0, 0.0, 1.0, 0.0], 14 [0.0, 0.0, 0.0, 1.0], 15 ]; 16 const MATRIX: [[$t; 4]; 4] = [ 17 [1.0, 2.0, 3.0, 4.0], 18 [5.0, 6.0, 7.0, 8.0], 19 [9.0, 10.0, 11.0, 12.0], 20 [13.0, 14.0, 15.0, 16.0], 21 ]; 22 23 const MATRIX1D: [$t; 16] = [ 24 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0, 11.0, 12.0, 13.0, 14.0, 15.0, 16.0, 25 ]; 26 27 glam_test!(test_const, { 28 const M0: $mat4 = $mat4::from_cols( 29 $newvec4(1.0, 2.0, 3.0, 4.0), 30 $newvec4(5.0, 6.0, 7.0, 8.0), 31 $newvec4(9.0, 10.0, 11.0, 12.0), 32 $newvec4(13.0, 14.0, 15.0, 16.0), 33 ); 34 const M1: $mat4 = $mat4::from_cols_array(&MATRIX1D); 35 const M2: $mat4 = $mat4::from_cols_array_2d(&MATRIX); 36 37 assert_eq!(MATRIX1D, M0.to_cols_array()); 38 assert_eq!(MATRIX1D, M1.to_cols_array()); 39 assert_eq!(MATRIX1D, M2.to_cols_array()); 40 }); 41 42 glam_test!(test_mat4_identity, { 43 assert_eq!( 44 $mat4::IDENTITY, 45 $mat4::from_cols_array(&[ 46 1., 0., 0., 0., // 47 0., 1., 0., 0., // 48 0., 0., 1., 0., // 49 0., 0., 0., 1., // 50 ]) 51 ); 52 let identity = $mat4::IDENTITY; 53 assert_eq!(IDENTITY, identity.to_cols_array_2d()); 54 assert_eq!($mat4::from_cols_array_2d(&IDENTITY), identity); 55 assert_eq!(identity, identity * identity); 56 assert_eq!(identity, $mat4::default()); 57 assert_eq!(identity, $mat4::from_diagonal($vec4::ONE)); 58 }); 59 60 glam_test!(test_mat4_zero, { 61 assert_eq!( 62 $mat4::ZERO, 63 $mat4::from_cols_array(&[ 64 0., 0., 0., 0., // 65 0., 0., 0., 0., // 66 0., 0., 0., 0., // 67 0., 0., 0., 0., // 68 ]) 69 ); 70 }); 71 72 glam_test!(test_mat4_nan, { 73 assert!($mat4::NAN.is_nan()); 74 assert!(!$mat4::NAN.is_finite()); 75 }); 76 77 glam_test!(test_mat4_accessors, { 78 let mut m = $mat4::ZERO; 79 m.x_axis = $vec4::new(1.0, 2.0, 3.0, 4.0); 80 m.y_axis = $vec4::new(5.0, 6.0, 7.0, 8.0); 81 m.z_axis = $vec4::new(9.0, 10.0, 11.0, 12.0); 82 m.w_axis = $vec4::new(13.0, 14.0, 15.0, 16.0); 83 assert_eq!($mat4::from_cols_array_2d(&MATRIX), m); 84 assert_eq!($vec4::new(1.0, 2.0, 3.0, 4.0), m.x_axis); 85 assert_eq!($vec4::new(5.0, 6.0, 7.0, 8.0), m.y_axis); 86 assert_eq!($vec4::new(9.0, 10.0, 11.0, 12.0), m.z_axis); 87 assert_eq!($vec4::new(13.0, 14.0, 15.0, 16.0), m.w_axis); 88 89 assert_eq!($vec4::new(1.0, 2.0, 3.0, 4.0), m.col(0)); 90 assert_eq!($vec4::new(5.0, 6.0, 7.0, 8.0), m.col(1)); 91 assert_eq!($vec4::new(9.0, 10.0, 11.0, 12.0), m.col(2)); 92 assert_eq!($vec4::new(13.0, 14.0, 15.0, 16.0), m.col(3)); 93 94 assert_eq!($newvec4(1.0, 5.0, 9.0, 13.0), m.row(0)); 95 assert_eq!($newvec4(2.0, 6.0, 10.0, 14.0), m.row(1)); 96 assert_eq!($newvec4(3.0, 7.0, 11.0, 15.0), m.row(2)); 97 assert_eq!($newvec4(4.0, 8.0, 12.0, 16.0), m.row(3)); 98 99 *m.col_mut(0) = m.col(0).wzyx(); 100 *m.col_mut(1) = m.col(1).wzyx(); 101 *m.col_mut(2) = m.col(2).wzyx(); 102 *m.col_mut(3) = m.col(3).wzyx(); 103 assert_eq!($newvec4(4.0, 3.0, 2.0, 1.0), m.col(0)); 104 assert_eq!($newvec4(8.0, 7.0, 6.0, 5.0), m.col(1)); 105 assert_eq!($newvec4(12.0, 11.0, 10.0, 9.0), m.col(2)); 106 assert_eq!($newvec4(16.0, 15.0, 14.0, 13.0), m.col(3)); 107 108 should_panic!({ $mat4::ZERO.col(4) }); 109 should_panic!({ 110 let mut m = $mat4::ZERO; 111 m.col_mut(4); 112 }); 113 should_panic!({ $mat4::ZERO.row(4) }); 114 }); 115 116 glam_test!(test_mat4_from_axes, { 117 let a = $mat4::from_cols_array_2d(&[ 118 [1.0, 2.0, 3.0, 4.0], 119 [5.0, 6.0, 7.0, 8.0], 120 [9.0, 10.0, 11.0, 12.0], 121 [13.0, 14.0, 15.0, 16.0], 122 ]); 123 assert_eq!(MATRIX, a.to_cols_array_2d()); 124 let b = $mat4::from_cols( 125 $newvec4(1.0, 2.0, 3.0, 4.0), 126 $newvec4(5.0, 6.0, 7.0, 8.0), 127 $newvec4(9.0, 10.0, 11.0, 12.0), 128 $newvec4(13.0, 14.0, 15.0, 16.0), 129 ); 130 assert_eq!(a, b); 131 let c = $newmat4( 132 $newvec4(1.0, 2.0, 3.0, 4.0), 133 $newvec4(5.0, 6.0, 7.0, 8.0), 134 $newvec4(9.0, 10.0, 11.0, 12.0), 135 $newvec4(13.0, 14.0, 15.0, 16.0), 136 ); 137 assert_eq!(a, c); 138 let d = b.to_cols_array(); 139 let f = $mat4::from_cols_array(&d); 140 assert_eq!(b, f); 141 }); 142 143 glam_test!(test_mat4_translation, { 144 let translate = $mat4::from_translation($newvec3(1.0, 2.0, 3.0)); 145 assert_eq!( 146 $mat4::from_cols( 147 $newvec4(1.0, 0.0, 0.0, 0.0), 148 $newvec4(0.0, 1.0, 0.0, 0.0), 149 $newvec4(0.0, 0.0, 1.0, 0.0), 150 $newvec4(1.0, 2.0, 3.0, 1.0) 151 ), 152 translate 153 ); 154 }); 155 156 glam_test!(test_from_rotation, { 157 let rot_x1 = $mat4::from_rotation_x(deg(180.0)); 158 let rot_x2 = $mat4::from_axis_angle($vec3::X, deg(180.0)); 159 assert_approx_eq!(rot_x1, rot_x2); 160 let rot_y1 = $mat4::from_rotation_y(deg(180.0)); 161 let rot_y2 = $mat4::from_axis_angle($vec3::Y, deg(180.0)); 162 assert_approx_eq!(rot_y1, rot_y2); 163 let rot_z1 = $mat4::from_rotation_z(deg(180.0)); 164 let rot_z2 = $mat4::from_axis_angle($vec3::Z, deg(180.0)); 165 assert_approx_eq!(rot_z1, rot_z2); 166 167 assert_approx_eq!($mat4::IDENTITY, $mat4::from_quat($quat::IDENTITY)); 168 169 should_glam_assert!({ $mat4::from_axis_angle($vec3::ZERO, 0.0) }); 170 should_glam_assert!({ $mat4::from_quat($quat::from_xyzw(0.0, 0.0, 0.0, 0.0)) }); 171 }); 172 173 glam_test!(test_from_mat3, { 174 let m3 = 175 $mat3::from_cols_array_2d(&[[1.0, 2.0, 3.0], [4.0, 5.0, 6.0], [7.0, 8.0, 9.0]]); 176 let m4 = $mat4::from_mat3(m3); 177 assert_eq!( 178 $mat4::from_cols_array_2d(&[ 179 [1.0, 2.0, 3.0, 0.0], 180 [4.0, 5.0, 6.0, 0.0], 181 [7.0, 8.0, 9.0, 0.0], 182 [0.0, 0.0, 0.0, 1.0] 183 ]), 184 m4 185 ); 186 }); 187 188 glam_test!(test_mat4_mul, { 189 let m = $mat4::from_axis_angle($vec3::Z, deg(90.0)); 190 let result3 = m.transform_vector3($vec3::Y); 191 assert_approx_eq!($newvec3(-1.0, 0.0, 0.0), result3); 192 assert_approx_eq!(result3, (m * $vec3::Y.extend(0.0)).truncate().into()); 193 let result4 = m * $vec4::Y; 194 assert_approx_eq!($newvec4(-1.0, 0.0, 0.0, 0.0), result4); 195 assert_approx_eq!(result4, m * $vec4::Y); 196 197 let m = $mat4::from_scale_rotation_translation( 198 $vec3::new(0.5, 1.5, 2.0), 199 $quat::from_rotation_x(deg(90.0)), 200 $vec3::new(1.0, 2.0, 3.0), 201 ); 202 let result3 = m.transform_vector3($vec3::Y); 203 assert_approx_eq!($newvec3(0.0, 0.0, 1.5), result3, 1.0e-6); 204 assert_approx_eq!(result3, (m * $vec3::Y.extend(0.0)).truncate().into()); 205 206 let result3 = m.transform_point3($vec3::Y); 207 assert_approx_eq!($newvec3(1.0, 2.0, 4.5), result3, 1.0e-6); 208 assert_approx_eq!(result3, (m * $vec3::Y.extend(1.0)).truncate().into()); 209 210 let m = $mat4::from_cols( 211 $newvec4(8.0, 0.0, 0.0, 0.0), 212 $newvec4(0.0, 4.0, 0.0, 0.0), 213 $newvec4(0.0, 0.0, 2.0, 2.0), 214 $newvec4(0.0, 0.0, 0.0, 0.0), 215 ); 216 assert_approx_eq!( 217 $newvec3(4.0, 2.0, 1.0), 218 m.project_point3($newvec3(2.0, 2.0, 2.0)) 219 ); 220 221 should_glam_assert!({ $mat4::ZERO.transform_vector3($vec3::X) }); 222 should_glam_assert!({ $mat4::ZERO.transform_point3($vec3::X) }); 223 }); 224 225 glam_test!(test_from_ypr, { 226 use glam::EulerRot; 227 let zero = deg(0.0); 228 let yaw = deg(30.0); 229 let pitch = deg(60.0); 230 let roll = deg(90.0); 231 let y0 = $mat4::from_rotation_y(yaw); 232 let y1 = $mat4::from_euler(EulerRot::YXZ, yaw, zero, zero); 233 assert_approx_eq!(y0, y1); 234 235 let x0 = $mat4::from_rotation_x(pitch); 236 let x1 = $mat4::from_euler(EulerRot::YXZ, zero, pitch, zero); 237 assert_approx_eq!(x0, x1); 238 239 let z0 = $mat4::from_rotation_z(roll); 240 let z1 = $mat4::from_euler(EulerRot::YXZ, zero, zero, roll); 241 assert_approx_eq!(z0, z1); 242 243 let yx0 = y0 * x0; 244 let yx1 = $mat4::from_euler(EulerRot::YXZ, yaw, pitch, zero); 245 assert_approx_eq!(yx0, yx1, 1e-6); 246 247 let yxz0 = y0 * x0 * z0; 248 let yxz1 = $mat4::from_euler(EulerRot::YXZ, yaw, pitch, roll); 249 assert_approx_eq!(yxz0, yxz1, 1e-6); 250 }); 251 252 glam_test!(test_from_scale, { 253 let m = $mat4::from_scale($vec3::new(2.0, 4.0, 8.0)); 254 assert_approx_eq!($vec4::X * 2.0, m.x_axis); 255 assert_approx_eq!($vec4::Y * 4.0, m.y_axis); 256 assert_approx_eq!($vec4::Z * 8.0, m.z_axis); 257 assert_approx_eq!($vec4::W, m.w_axis); 258 assert_approx_eq!( 259 m.transform_point3($vec3::new(1.0, 1.0, 1.0)), 260 $vec3::new(2.0, 4.0, 8.0) 261 ); 262 263 should_glam_assert!({ $mat4::from_scale($vec3::ZERO) }); 264 }); 265 266 glam_test!(test_mat4_transpose, { 267 let m = $newmat4( 268 $newvec4(1.0, 2.0, 3.0, 4.0), 269 $newvec4(5.0, 6.0, 7.0, 8.0), 270 $newvec4(9.0, 10.0, 11.0, 12.0), 271 $newvec4(13.0, 14.0, 15.0, 16.0), 272 ); 273 let mt = m.transpose(); 274 assert_eq!($newvec4(1.0, 5.0, 9.0, 13.0), mt.x_axis); 275 assert_eq!($newvec4(2.0, 6.0, 10.0, 14.0), mt.y_axis); 276 assert_eq!($newvec4(3.0, 7.0, 11.0, 15.0), mt.z_axis); 277 assert_eq!($newvec4(4.0, 8.0, 12.0, 16.0), mt.w_axis); 278 }); 279 280 glam_test!(test_mat4_det, { 281 assert_eq!(0.0, $mat4::ZERO.determinant()); 282 assert_eq!(1.0, $mat4::IDENTITY.determinant()); 283 assert_eq!(1.0, $mat4::from_rotation_x(deg(90.0)).determinant()); 284 assert_eq!(1.0, $mat4::from_rotation_y(deg(180.0)).determinant()); 285 assert_eq!(1.0, $mat4::from_rotation_z(deg(270.0)).determinant()); 286 assert_eq!( 287 2.0 * 2.0 * 2.0, 288 $mat4::from_scale($newvec3(2.0, 2.0, 2.0)).determinant() 289 ); 290 assert_eq!( 291 1.0, 292 $newmat4( 293 $newvec4(0.0, 0.0, 0.0, 1.0), 294 $newvec4(1.0, 0.0, 0.0, 0.0), 295 $newvec4(0.0, 0.0, 1.0, 0.0), 296 $newvec4(0.0, 1.0, 0.0, 0.0), 297 ) 298 .determinant() 299 ); 300 }); 301 302 glam_test!(test_mat4_inverse, { 303 // assert_eq!(None, $mat4::ZERO.inverse()); 304 let inv = $mat4::IDENTITY.inverse(); 305 // assert_ne!(None, inv); 306 assert_approx_eq!($mat4::IDENTITY, inv); 307 308 let rotz = $mat4::from_rotation_z(deg(90.0)); 309 let rotz_inv = rotz.inverse(); 310 // assert_ne!(None, rotz_inv); 311 // let rotz_inv = rotz_inv.unwrap(); 312 assert_approx_eq!($mat4::IDENTITY, rotz * rotz_inv); 313 assert_approx_eq!($mat4::IDENTITY, rotz_inv * rotz); 314 315 let trans = $mat4::from_translation($newvec3(1.0, 2.0, 3.0)); 316 let trans_inv = trans.inverse(); 317 // assert_ne!(None, trans_inv); 318 // let trans_inv = trans_inv.unwrap(); 319 assert_approx_eq!($mat4::IDENTITY, trans * trans_inv); 320 assert_approx_eq!($mat4::IDENTITY, trans_inv * trans); 321 322 let scale = $mat4::from_scale($newvec3(4.0, 5.0, 6.0)); 323 let scale_inv = scale.inverse(); 324 // assert_ne!(None, scale_inv); 325 // let scale_inv = scale_inv.unwrap(); 326 assert_approx_eq!($mat4::IDENTITY, scale * scale_inv); 327 assert_approx_eq!($mat4::IDENTITY, scale_inv * scale); 328 329 let m = scale * rotz * trans; 330 let m_inv = m.inverse(); 331 // assert_ne!(None, m_inv); 332 // let m_inv = m_inv.unwrap(); 333 assert_approx_eq!($mat4::IDENTITY, m * m_inv, 1.0e-5); 334 assert_approx_eq!($mat4::IDENTITY, m_inv * m, 1.0e-5); 335 assert_approx_eq!(m_inv, trans_inv * rotz_inv * scale_inv, 1.0e-6); 336 337 // Make sure we can invert a "random" matrix: 338 let m = $mat4::from_cols( 339 $newvec4(1.0, -0.3, 1.0, 1.0), 340 $newvec4(0.5, 0.6, 0.7, 0.8), 341 $newvec4(-0.9, -0.3, 0.0, 12.0), 342 $newvec4(0.13, 0.14, 0.15, 0.16), 343 ); 344 let m_inv = m.inverse(); 345 assert_approx_eq!($mat4::IDENTITY, m * m_inv, 1.0e-5); 346 assert_approx_eq!($mat4::IDENTITY, m_inv * m, 1.0e-5); 347 348 should_glam_assert!({ $mat4::ZERO.inverse() }); 349 }); 350 351 glam_test!(test_mat4_decompose, { 352 // identity 353 let (out_scale, out_rotation, out_translation) = 354 $mat4::IDENTITY.to_scale_rotation_translation(); 355 assert_approx_eq!($vec3::ONE, out_scale); 356 assert!(out_rotation.is_near_identity()); 357 assert_approx_eq!($vec3::ZERO, out_translation); 358 359 // no scale 360 let in_scale = $vec3::ONE; 361 let in_translation = $vec3::new(-2.0, 4.0, -0.125); 362 let in_rotation = $quat::from_euler( 363 glam::EulerRot::YXZ, 364 $t::to_radians(-45.0), 365 $t::to_radians(180.0), 366 $t::to_radians(270.0), 367 ); 368 let in_mat = 369 $mat4::from_scale_rotation_translation(in_scale, in_rotation, in_translation); 370 let (out_scale, out_rotation, out_translation) = in_mat.to_scale_rotation_translation(); 371 assert_approx_eq!(in_scale, out_scale, 1e-6); 372 // out_rotation is different but produces the same matrix 373 // assert_approx_eq!(in_rotation, out_rotation); 374 assert_approx_eq!(in_translation, out_translation); 375 assert_approx_eq!( 376 in_mat, 377 $mat4::from_scale_rotation_translation(out_scale, out_rotation, out_translation), 378 1e-6 379 ); 380 381 // positive scale 382 let in_scale = $vec3::new(1.0, 2.0, 4.0); 383 let in_mat = 384 $mat4::from_scale_rotation_translation(in_scale, in_rotation, in_translation); 385 let (out_scale, out_rotation, out_translation) = in_mat.to_scale_rotation_translation(); 386 assert_approx_eq!(in_scale, out_scale, 1e-6); 387 // out_rotation is different but produces the same matrix 388 // assert_approx_eq!(in_rotation, out_rotation); 389 assert_approx_eq!(in_translation, out_translation); 390 assert_approx_eq!( 391 in_mat, 392 $mat4::from_scale_rotation_translation(out_scale, out_rotation, out_translation), 393 1e-5 394 ); 395 396 // negative scale 397 let in_scale = $vec3::new(-4.0, 1.0, 2.0); 398 let in_mat = 399 $mat4::from_scale_rotation_translation(in_scale, in_rotation, in_translation); 400 let (out_scale, out_rotation, out_translation) = in_mat.to_scale_rotation_translation(); 401 assert_approx_eq!(in_scale, out_scale, 1e-6); 402 // out_rotation is different but produces the same matrix 403 // assert_approx_eq!(in_rotation, out_rotation); 404 assert_approx_eq!(in_translation, out_translation); 405 assert_approx_eq!( 406 in_mat, 407 $mat4::from_scale_rotation_translation(out_scale, out_rotation, out_translation), 408 1e-5 409 ); 410 411 // negative scale 412 let in_scale = $vec3::new(4.0, -1.0, -2.0); 413 let in_mat = 414 $mat4::from_scale_rotation_translation(in_scale, in_rotation, in_translation); 415 let (out_scale, out_rotation, out_translation) = in_mat.to_scale_rotation_translation(); 416 // out_scale and out_rotation are different but they produce the same matrix 417 // assert_approx_eq!(in_scale, out_scale, 1e-6); 418 // assert_approx_eq!(in_rotation, out_rotation); 419 assert_approx_eq!(in_translation, out_translation); 420 assert_approx_eq!( 421 in_mat, 422 $mat4::from_scale_rotation_translation(out_scale, out_rotation, out_translation), 423 1e-6 424 ); 425 426 should_glam_assert!({ 427 $mat4::from_scale_rotation_translation( 428 $vec3::ONE, 429 $quat::from_xyzw(0.0, 0.0, 0.0, 0.0), 430 $vec3::ZERO, 431 ) 432 }); 433 should_glam_assert!({ 434 $mat4::from_rotation_translation($quat::from_xyzw(0.0, 0.0, 0.0, 0.0), $vec3::ZERO) 435 }); 436 // TODO: should check scale 437 // should_glam_assert!({ $mat4::from_scale_rotation_translation($vec3::ZERO, $quat::IDENTITY, $vec3::ZERO) }); 438 should_glam_assert!({ $mat4::ZERO.to_scale_rotation_translation() }); 439 }); 440 441 glam_test!(test_mat4_look_at, { 442 let eye = $vec3::new(0.0, 0.0, -5.0); 443 let center = $vec3::new(0.0, 0.0, 0.0); 444 let up = $vec3::new(1.0, 0.0, 0.0); 445 446 let point = $vec3::new(1.0, 0.0, 0.0); 447 448 let lh = $mat4::look_at_lh(eye, center, up); 449 let rh = $mat4::look_at_rh(eye, center, up); 450 assert_approx_eq!(lh.transform_point3(point), $vec3::new(0.0, 1.0, 5.0)); 451 assert_approx_eq!(rh.transform_point3(point), $vec3::new(0.0, 1.0, -5.0)); 452 453 let dir = center - eye; 454 let lh = $mat4::look_to_lh(eye, dir, up); 455 let rh = $mat4::look_to_rh(eye, dir, up); 456 assert_approx_eq!(lh.transform_point3(point), $vec3::new(0.0, 1.0, 5.0)); 457 assert_approx_eq!(rh.transform_point3(point), $vec3::new(0.0, 1.0, -5.0)); 458 459 should_glam_assert!({ $mat4::look_at_lh($vec3::ONE, $vec3::ZERO, $vec3::ZERO) }); 460 should_glam_assert!({ $mat4::look_at_rh($vec3::ONE, $vec3::ZERO, $vec3::ZERO) }); 461 }); 462 463 glam_test!(test_mat4_perspective_gl_rh, { 464 let projection = $mat4::perspective_rh_gl($t::to_radians(90.0), 2.0, 5.0, 15.0); 465 466 let original = $vec3::new(5.0, 5.0, -15.0); 467 let projected = projection * original.extend(1.0); 468 assert_approx_eq!($vec4::new(2.5, 5.0, 15.0, 15.0), projected); 469 470 let original = $vec3::new(5.0, 5.0, -5.0); 471 let projected = projection * original.extend(1.0); 472 assert_approx_eq!($vec4::new(2.5, 5.0, -5.0, 5.0), projected); 473 }); 474 475 glam_test!(test_mat4_perspective_lh, { 476 let projection = $mat4::perspective_lh($t::to_radians(90.0), 2.0, 5.0, 15.0); 477 478 let original = $vec3::new(5.0, 5.0, 15.0); 479 let projected = projection * original.extend(1.0); 480 assert_approx_eq!($vec4::new(2.5, 5.0, 15.0, 15.0), projected, 1e-6); 481 482 let original = $vec3::new(5.0, 5.0, 5.0); 483 let projected = projection * original.extend(1.0); 484 assert_approx_eq!($vec4::new(2.5, 5.0, 0.0, 5.0), projected, 1e-6); 485 486 should_glam_assert!({ $mat4::perspective_lh(0.0, 1.0, 1.0, 0.0) }); 487 should_glam_assert!({ $mat4::perspective_lh(0.0, 1.0, 0.0, 1.0) }); 488 }); 489 490 glam_test!(test_mat4_perspective_infinite_lh, { 491 let projection = $mat4::perspective_infinite_lh($t::to_radians(90.0), 2.0, 5.0); 492 493 let original = $vec3::new(5.0, 5.0, 15.0); 494 let projected = projection * original.extend(1.0); 495 assert_approx_eq!($vec4::new(2.5, 5.0, 10.0, 15.0), projected, 1e-6); 496 497 let original = $vec3::new(5.0, 5.0, 5.0); 498 let projected = projection * original.extend(1.0); 499 assert_approx_eq!($vec4::new(2.5, 5.0, 0.0, 5.0), projected, 1e-6); 500 501 should_glam_assert!({ $mat4::perspective_infinite_lh(0.0, 1.0, 0.0) }); 502 }); 503 504 glam_test!(test_mat4_perspective_infinite_reverse_lh, { 505 let projection = $mat4::perspective_infinite_reverse_lh($t::to_radians(90.0), 2.0, 5.0); 506 507 let original = $vec3::new(5.0, 5.0, 15.0); 508 let projected = projection * original.extend(1.0); 509 assert_approx_eq!($vec4::new(2.5, 5.0, 5.0, 15.0), projected, 1e-6); 510 511 let original = $vec3::new(5.0, 5.0, 5.0); 512 let projected = projection * original.extend(1.0); 513 assert_approx_eq!($vec4::new(2.5, 5.0, 5.0, 5.0), projected, 1e-6); 514 515 should_glam_assert!({ $mat4::perspective_infinite_reverse_lh(0.0, 1.0, 0.0) }); 516 }); 517 518 glam_test!(test_mat4_perspective_rh, { 519 let projection = $mat4::perspective_rh($t::to_radians(90.0), 2.0, 5.0, 15.0); 520 521 let original = $vec3::new(5.0, 5.0, 15.0); 522 let projected = projection * original.extend(1.0); 523 assert_approx_eq!($vec4::new(2.5, 5.0, -30.0, -15.0), projected, 1e-6); 524 525 let original = $vec3::new(5.0, 5.0, 5.0); 526 let projected = projection * original.extend(1.0); 527 assert_approx_eq!($vec4::new(2.5, 5.0, -15.0, -5.0), projected, 1e-6); 528 529 should_glam_assert!({ $mat4::perspective_rh(0.0, 1.0, 1.0, 0.0) }); 530 should_glam_assert!({ $mat4::perspective_rh(0.0, 1.0, 0.0, 1.0) }); 531 }); 532 533 glam_test!(test_mat4_perspective_infinite_rh, { 534 let projection = $mat4::perspective_infinite_rh($t::to_radians(90.0), 2.0, 5.0); 535 536 let original = $vec3::new(5.0, 5.0, 15.0); 537 let projected = projection * original.extend(1.0); 538 assert_approx_eq!($vec4::new(2.5, 5.0, -20.0, -15.0), projected); 539 540 let original = $vec3::new(5.0, 5.0, 5.0); 541 let projected = projection * original.extend(1.0); 542 assert_approx_eq!($vec4::new(2.5, 5.0, -10.0, -5.0), projected); 543 544 should_glam_assert!({ $mat4::perspective_infinite_rh(0.0, 1.0, 0.0) }); 545 }); 546 547 glam_test!(test_mat4_perspective_infinite_reverse_rh, { 548 let projection = $mat4::perspective_infinite_reverse_rh($t::to_radians(90.0), 2.0, 5.0); 549 550 let original = $vec3::new(5.0, 5.0, 15.0); 551 let projected = projection * original.extend(1.0); 552 assert_approx_eq!($vec4::new(2.5, 5.0, 5.0, -15.0), projected); 553 554 let original = $vec3::new(5.0, 5.0, 5.0); 555 let projected = projection * original.extend(1.0); 556 assert_approx_eq!($vec4::new(2.5, 5.0, 5.0, -5.0), projected); 557 558 should_glam_assert!({ $mat4::perspective_infinite_reverse_rh(0.0, 1.0, 0.0) }); 559 }); 560 561 glam_test!(test_mat4_orthographic_gl_rh, { 562 let projection = $mat4::orthographic_rh_gl(-10.0, 10.0, -5.0, 5.0, 0.0, -10.0); 563 let original = $vec4::new(5.0, 5.0, -5.0, 1.0); 564 let projected = projection.mul_vec4(original); 565 assert_approx_eq!(projected, $vec4::new(0.5, 1.0, -2.0, 1.0)); 566 }); 567 568 glam_test!(test_mat4_orthographic_rh, { 569 let projection = $mat4::orthographic_rh(-10.0, 10.0, -5.0, 5.0, -10.0, 10.0); 570 let original = $vec4::new(5.0, 5.0, -5.0, 1.0); 571 let projected = projection.mul_vec4(original); 572 assert_approx_eq!(projected, $vec4::new(0.5, 1.0, 0.75, 1.0)); 573 574 let original = $vec4::new(5.0, 5.0, 5.0, 1.0); 575 let projected = projection.mul_vec4(original); 576 assert_approx_eq!(projected, $vec4::new(0.5, 1.0, 0.25, 1.0)); 577 }); 578 579 glam_test!(test_mat4_orthographic_lh, { 580 let projection = $mat4::orthographic_lh(-10.0, 10.0, -5.0, 5.0, -10.0, 10.0); 581 let original = $vec4::new(5.0, 5.0, -5.0, 1.0); 582 let projected = projection.mul_vec4(original); 583 assert_approx_eq!(projected, $vec4::new(0.5, 1.0, 0.25, 1.0)); 584 585 let original = $vec4::new(5.0, 5.0, 5.0, 1.0); 586 let projected = projection.mul_vec4(original); 587 assert_approx_eq!(projected, $vec4::new(0.5, 1.0, 0.75, 1.0)); 588 }); 589 590 glam_test!(test_mat4_ops, { 591 let m0 = $mat4::from_cols_array_2d(&MATRIX); 592 let m0x2 = $mat4::from_cols_array_2d(&[ 593 [2.0, 4.0, 6.0, 8.0], 594 [10.0, 12.0, 14.0, 16.0], 595 [18.0, 20.0, 22.0, 24.0], 596 [26.0, 28.0, 30.0, 32.0], 597 ]); 598 let m0_neg = $mat4::from_cols_array_2d(&[ 599 [-1.0, -2.0, -3.0, -4.0], 600 [-5.0, -6.0, -7.0, -8.0], 601 [-9.0, -10.0, -11.0, -12.0], 602 [-13.0, -14.0, -15.0, -16.0], 603 ]); 604 assert_eq!(m0x2, m0 * 2.0); 605 assert_eq!(m0x2, 2.0 * m0); 606 assert_eq!(m0x2, m0 + m0); 607 assert_eq!($mat4::ZERO, m0 - m0); 608 assert_eq!(m0_neg, -m0); 609 assert_approx_eq!(m0, m0 * $mat4::IDENTITY); 610 assert_approx_eq!(m0, $mat4::IDENTITY * m0); 611 612 let mut m1 = m0; 613 m1 *= 2.0; 614 assert_eq!(m0x2, m1); 615 616 let mut m1 = m0; 617 m1 += m0; 618 assert_eq!(m0x2, m1); 619 620 let mut m1 = m0; 621 m1 -= m0; 622 assert_eq!($mat4::ZERO, m1); 623 624 let mut m1 = $mat4::IDENTITY; 625 m1 *= m0; 626 assert_approx_eq!(m0, m1); 627 }); 628 629 glam_test!(test_mat4_fmt, { 630 let a = $mat4::from_cols_array_2d(&MATRIX); 631 assert_eq!( 632 format!("{}", a), 633 "[[1, 2, 3, 4], [5, 6, 7, 8], [9, 10, 11, 12], [13, 14, 15, 16]]" 634 ); 635 }); 636 637 glam_test!(test_mat4_to_from_slice, { 638 let m = $mat4::from_cols_slice(&MATRIX1D); 639 assert_eq!($mat4::from_cols_array(&MATRIX1D), m); 640 let mut out: [$t; 16] = Default::default(); 641 m.write_cols_to_slice(&mut out); 642 assert_eq!(MATRIX1D, out); 643 644 should_panic!({ $mat4::from_cols_slice(&[0.0; 15]) }); 645 should_panic!({ $mat4::IDENTITY.write_cols_to_slice(&mut [0.0; 15]) }); 646 }); 647 648 glam_test!(test_sum, { 649 let id = $mat4::IDENTITY; 650 assert_eq!([id, id].iter().sum::<$mat4>(), id + id); 651 assert_eq!([id, id].into_iter().sum::<$mat4>(), id + id); 652 }); 653 654 glam_test!(test_product, { 655 let two = $mat4::IDENTITY + $mat4::IDENTITY; 656 assert_eq!([two, two].iter().product::<$mat4>(), two * two); 657 assert_eq!([two, two].into_iter().product::<$mat4>(), two * two); 658 }); 659 660 glam_test!(test_mat4_is_finite, { 661 assert!($mat4::IDENTITY.is_finite()); 662 assert!(!($mat4::IDENTITY * INFINITY).is_finite()); 663 assert!(!($mat4::IDENTITY * NEG_INFINITY).is_finite()); 664 assert!(!($mat4::IDENTITY * NAN).is_finite()); 665 }); 666 }; 667 } 668 669 macro_rules! impl_as_ref_tests { 670 ($mat:ident) => { 671 glam_test!(test_as_ref, { 672 let m = $mat::from_cols_array_2d(&MATRIX); 673 assert_eq!(MATRIX1D, *m.as_ref()); 674 }); 675 glam_test!(test_as_mut, { 676 let mut m = $mat::ZERO; 677 *m.as_mut() = MATRIX1D; 678 assert_eq!($mat::from_cols_array_2d(&MATRIX), m); 679 }); 680 }; 681 } 682 683 mod mat4 { 684 use super::support::deg; 685 use glam::{mat4, swizzles::*, vec3, vec4, Mat3, Mat4, Quat, Vec3, Vec4}; 686 687 glam_test!(test_align, { 688 use std::mem; 689 assert_eq!(mem::align_of::<Vec4>(), mem::align_of::<Mat4>()); 690 assert_eq!(64, mem::size_of::<Mat4>()); 691 }); 692 693 glam_test!(test_from_mat3a, { 694 use glam::Mat3A; 695 let m3 = Mat3A::from_cols_array_2d(&[[1.0, 2.0, 3.0], [4.0, 5.0, 6.0], [7.0, 8.0, 9.0]]); 696 let m4 = Mat4::from_mat3a(m3); 697 assert_eq!( 698 Mat4::from_cols_array_2d(&[ 699 [1.0, 2.0, 3.0, 0.0], 700 [4.0, 5.0, 6.0, 0.0], 701 [7.0, 8.0, 9.0, 0.0], 702 [0.0, 0.0, 0.0, 1.0] 703 ]), 704 m4 705 ); 706 }); 707 708 glam_test!(test_as, { 709 use glam::DMat4; 710 assert_eq!( 711 DMat4::from_cols_array_2d(&[ 712 [1.0, 2.0, 3.0, 4.0], 713 [5.0, 6.0, 7.0, 8.0], 714 [9.0, 10.0, 11.0, 12.0], 715 [13.0, 14.0, 15.0, 16.0] 716 ]), 717 Mat4::from_cols_array_2d(&[ 718 [1.0, 2.0, 3.0, 4.0], 719 [5.0, 6.0, 7.0, 8.0], 720 [9.0, 10.0, 11.0, 12.0], 721 [13.0, 14.0, 15.0, 16.0] 722 ]) 723 .as_dmat4() 724 ); 725 assert_eq!( 726 Mat4::from_cols_array_2d(&[ 727 [1.0, 2.0, 3.0, 4.0], 728 [5.0, 6.0, 7.0, 8.0], 729 [9.0, 10.0, 11.0, 12.0], 730 [13.0, 14.0, 15.0, 16.0] 731 ]), 732 DMat4::from_cols_array_2d(&[ 733 [1.0, 2.0, 3.0, 4.0], 734 [5.0, 6.0, 7.0, 8.0], 735 [9.0, 10.0, 11.0, 12.0], 736 [13.0, 14.0, 15.0, 16.0] 737 ]) 738 .as_mat4() 739 ); 740 }); 741 742 impl_mat4_tests!(f32, mat4, vec4, vec3, Mat4, Mat3, Quat, Vec4, Vec3); 743 impl_as_ref_tests!(Mat4); 744 } 745 746 mod dmat4 { 747 use super::support::deg; 748 use glam::{dmat4, dvec3, dvec4, swizzles::*, DMat3, DMat4, DQuat, DVec3, DVec4}; 749 750 glam_test!(test_align, { 751 use std::mem; 752 assert_eq!(mem::align_of::<DVec4>(), mem::align_of::<DMat4>()); 753 assert_eq!(128, mem::size_of::<DMat4>()); 754 }); 755 756 impl_mat4_tests!(f64, dmat4, dvec4, dvec3, DMat4, DMat3, DQuat, DVec4, DVec3); 757 impl_as_ref_tests!(DMat4); 758 } 759