1 // Copyright 2013-2014 The CGMath Developers. 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 //! Linear algebra types and functions. 16 //! Most of the code in this module was borrowed from the `cgmath` package. 17 18 pub use num_traits::{cast, Float, One, Zero}; 19 20 /// 2D vector. 21 #[repr(C)] 22 #[derive(Debug, PartialEq, Eq, Copy, Clone, Hash)] 23 pub struct Vector2<S> { 24 pub x: S, 25 pub y: S, 26 } 27 28 impl<S: Sized> Vector2<S> { new(x: S, y: S) -> Self29 pub const fn new(x: S, y: S) -> Self { 30 Vector2 { x, y } 31 } 32 33 /// Returns a vector with the same direction and a given magnitude. 34 #[inline] normalize(self) -> Self where S: One + Float + std::ops::Div + std::ops::Mul,35 pub fn normalize(self) -> Self 36 where 37 S: One + Float + std::ops::Div + std::ops::Mul, 38 { 39 self * (S::one() / self.magnitude()) 40 } 41 42 /// The distance from the tail to the tip of the vector. 43 #[inline] magnitude(self) -> S where S: Float,44 pub fn magnitude(self) -> S 45 where 46 S: Float, 47 { 48 Float::sqrt(Self::dot(self, self)) 49 } 50 51 /// Dot product of two vectors. 52 /// 53 /// ``` 54 /// use rgx::math::*; 55 /// 56 /// let v1 = Vector4::new(1, 3, -5, 4); 57 /// let v2 = Vector4::new(4, -2, -1, 3); 58 /// 59 /// assert_eq!(v1 * v2, 15); 60 /// ``` 61 #[inline] dot(a: Self, b: Self) -> <S as std::ops::Add>::Output where S: std::ops::Mul<Output = S> + std::ops::Add,62 pub fn dot(a: Self, b: Self) -> <S as std::ops::Add>::Output 63 where 64 S: std::ops::Mul<Output = S> + std::ops::Add, 65 { 66 a.x * b.x + a.y * b.y 67 } 68 69 /// Distance between two vectors. 70 #[inline] distance(self, other: Self) -> S where S: Float,71 pub fn distance(self, other: Self) -> S 72 where 73 S: Float, 74 { 75 (other - self).magnitude() 76 } 77 78 /// Extend vector to three dimensions. extend(self, z: S) -> Vector3<S>79 pub fn extend(self, z: S) -> Vector3<S> { 80 Vector3::new(self.x, self.y, z) 81 } 82 map<F, T>(self, mut f: F) -> Vector2<T> where F: FnMut(S) -> T,83 pub fn map<F, T>(self, mut f: F) -> Vector2<T> 84 where 85 F: FnMut(S) -> T, 86 { 87 Vector2::new(f(self.x), f(self.y)) 88 } 89 } 90 91 impl<S: Zero + Copy + PartialEq> Zero for Vector2<S> { 92 #[inline] zero() -> Self93 fn zero() -> Self { 94 Vector2::new(S::zero(), S::zero()) 95 } 96 97 #[inline] is_zero(&self) -> bool98 fn is_zero(&self) -> bool { 99 *self == Vector2::zero() 100 } 101 } 102 103 impl<S> std::ops::Add<Vector2<S>> for Vector2<S> 104 where 105 S: std::ops::Add<Output = S> + Copy, 106 { 107 type Output = Self; 108 add(self, other: Vector2<S>) -> Self109 fn add(self, other: Vector2<S>) -> Self { 110 Self { 111 x: self.x + other.x, 112 y: self.y + other.y, 113 } 114 } 115 } 116 117 impl<S> std::ops::Sub<Vector2<S>> for Vector2<S> 118 where 119 S: std::ops::Sub<Output = S> + Copy, 120 { 121 type Output = Self; 122 sub(self, other: Vector2<S>) -> Self123 fn sub(self, other: Vector2<S>) -> Self { 124 Self { 125 x: self.x - other.x, 126 y: self.y - other.y, 127 } 128 } 129 } 130 131 impl<S> std::ops::Mul<S> for Vector2<S> 132 where 133 S: std::ops::Mul<Output = S> + Copy, 134 { 135 type Output = Self; 136 mul(self, s: S) -> Self137 fn mul(self, s: S) -> Self { 138 Self { 139 x: self.x * s, 140 y: self.y * s, 141 } 142 } 143 } 144 145 impl<S> From<Point2<S>> for Vector2<S> { from(p: Point2<S>) -> Self146 fn from(p: Point2<S>) -> Self { 147 Self::new(p.x, p.y) 148 } 149 } 150 151 /// 3D vector. 152 #[repr(C)] 153 #[derive(Debug, PartialEq, Eq, Copy, Clone, Hash)] 154 pub struct Vector3<S> { 155 pub x: S, 156 pub y: S, 157 pub z: S, 158 } 159 160 impl<S> Vector3<S> { new(x: S, y: S, z: S) -> Self161 pub const fn new(x: S, y: S, z: S) -> Self { 162 Vector3 { x, y, z } 163 } 164 165 /// Extend vector to four dimensions. extend(self, w: S) -> Vector4<S>166 pub fn extend(self, w: S) -> Vector4<S> { 167 Vector4::new(self.x, self.y, self.z, w) 168 } 169 } 170 171 /// 4D vector. 172 #[repr(C)] 173 #[derive(Debug, PartialEq, Eq, Copy, Clone, Hash)] 174 pub struct Vector4<S> { 175 pub x: S, 176 pub y: S, 177 pub z: S, 178 pub w: S, 179 } 180 181 impl From<Vector4<f32>> for [f32; 4] { from(mat: Vector4<f32>) -> Self182 fn from(mat: Vector4<f32>) -> Self { 183 unsafe { std::mem::transmute(mat) } 184 } 185 } 186 187 impl<S> Vector4<S> { new(x: S, y: S, z: S, w: S) -> Self188 pub const fn new(x: S, y: S, z: S, w: S) -> Self { 189 Vector4 { x, y, z, w } 190 } 191 } 192 193 impl<S> std::ops::Mul<S> for Vector4<S> 194 where 195 S: std::ops::Mul<Output = S> + Copy, 196 { 197 type Output = Self; 198 mul(self, s: S) -> Self199 fn mul(self, s: S) -> Self { 200 Self { 201 x: self.x * s, 202 y: self.y * s, 203 z: self.z * s, 204 w: self.w * s, 205 } 206 } 207 } 208 209 impl<S> std::ops::Mul<Vector4<S>> for Vector4<S> 210 where 211 S: std::ops::Mul<Output = S> + std::ops::Add<Output = S> + Copy, 212 { 213 type Output = S; 214 mul(self, other: Vector4<S>) -> S215 fn mul(self, other: Vector4<S>) -> S { 216 other.x * self.x + other.y * self.y + other.z * self.z + other.w * self.w 217 } 218 } 219 220 impl<S> std::ops::Add<Vector4<S>> for Vector4<S> 221 where 222 S: std::ops::Add<Output = S> + Copy, 223 { 224 type Output = Self; 225 add(self, other: Vector4<S>) -> Self226 fn add(self, other: Vector4<S>) -> Self { 227 Self { 228 x: self.x + other.x, 229 y: self.y + other.y, 230 z: self.z + other.z, 231 w: self.w + other.w, 232 } 233 } 234 } 235 236 #[repr(C)] 237 #[derive(Debug, PartialEq, Eq, Copy, Clone, Hash)] 238 pub struct Point2<S> { 239 pub x: S, 240 pub y: S, 241 } 242 243 impl<S> Point2<S> { new(x: S, y: S) -> Self244 pub const fn new(x: S, y: S) -> Self { 245 Point2 { x, y } 246 } 247 map<F, T>(self, mut f: F) -> Point2<T> where F: FnMut(S) -> T,248 pub fn map<F, T>(self, mut f: F) -> Point2<T> 249 where 250 F: FnMut(S) -> T, 251 { 252 Point2::new(f(self.x), f(self.y)) 253 } 254 } 255 256 impl<S> From<Vector2<S>> for Point2<S> { from(v: Vector2<S>) -> Self257 fn from(v: Vector2<S>) -> Self { 258 Self::new(v.x, v.y) 259 } 260 } 261 262 impl<S> std::ops::Div<S> for Point2<S> 263 where 264 S: std::ops::Div<Output = S> + Copy, 265 { 266 type Output = Self; 267 div(self, s: S) -> Self268 fn div(self, s: S) -> Self { 269 Self { 270 x: self.x / s, 271 y: self.y / s, 272 } 273 } 274 } 275 276 impl<S> std::ops::Mul<S> for Point2<S> 277 where 278 S: std::ops::Mul<Output = S> + Copy, 279 { 280 type Output = Self; 281 mul(self, s: S) -> Self282 fn mul(self, s: S) -> Self { 283 Self { 284 x: self.x * s, 285 y: self.y * s, 286 } 287 } 288 } 289 290 impl<S> std::ops::Add<Vector2<S>> for Point2<S> 291 where 292 S: std::ops::Add<Output = S> + Copy, 293 { 294 type Output = Self; 295 add(self, other: Vector2<S>) -> Self296 fn add(self, other: Vector2<S>) -> Self { 297 Self { 298 x: self.x + other.x, 299 y: self.y + other.y, 300 } 301 } 302 } 303 304 impl<S> std::ops::Sub<Vector2<S>> for Point2<S> 305 where 306 S: std::ops::Sub<Output = S> + Copy, 307 { 308 type Output = Self; 309 sub(self, other: Vector2<S>) -> Self310 fn sub(self, other: Vector2<S>) -> Self { 311 Self { 312 x: self.x - other.x, 313 y: self.y - other.y, 314 } 315 } 316 } 317 318 impl<S> std::ops::Sub<Point2<S>> for Point2<S> 319 where 320 S: std::ops::Sub<Output = S> + Copy, 321 { 322 type Output = Vector2<S>; 323 sub(self, other: Point2<S>) -> Vector2<S>324 fn sub(self, other: Point2<S>) -> Vector2<S> { 325 Vector2 { 326 x: self.x - other.x, 327 y: self.y - other.y, 328 } 329 } 330 } 331 332 /// A 4 x 4, column major matrix 333 /// 334 /// This type is marked as `#[repr(C)]`. 335 #[repr(C)] 336 #[derive(Debug, Copy, Clone, PartialEq)] 337 pub struct Matrix4<S> { 338 /// The first column of the matrix. 339 pub x: Vector4<S>, 340 /// The second column of the matrix. 341 pub y: Vector4<S>, 342 /// The third column of the matrix. 343 pub z: Vector4<S>, 344 /// The fourth column of the matrix. 345 pub w: Vector4<S>, 346 } 347 348 impl From<Matrix4<f32>> for [[f32; 4]; 4] { from(mat: Matrix4<f32>) -> Self349 fn from(mat: Matrix4<f32>) -> Self { 350 unsafe { std::mem::transmute(mat) } 351 } 352 } 353 354 impl<S: Copy + Zero + One> Matrix4<S> { 355 /// Create a new matrix, providing values for each index. 356 #[inline] 357 #[rustfmt::skip] new( c0r0: S, c0r1: S, c0r2: S, c0r3: S, c1r0: S, c1r1: S, c1r2: S, c1r3: S, c2r0: S, c2r1: S, c2r2: S, c2r3: S, c3r0: S, c3r1: S, c3r2: S, c3r3: S, ) -> Self358 pub fn new( 359 c0r0: S, c0r1: S, c0r2: S, c0r3: S, 360 c1r0: S, c1r1: S, c1r2: S, c1r3: S, 361 c2r0: S, c2r1: S, c2r2: S, c2r3: S, 362 c3r0: S, c3r1: S, c3r2: S, c3r3: S, 363 ) -> Self { 364 Self { 365 x: Vector4::new(c0r0, c0r1, c0r2, c0r3), 366 y: Vector4::new(c1r0, c1r1, c1r2, c1r3), 367 z: Vector4::new(c2r0, c2r1, c2r2, c2r3), 368 w: Vector4::new(c3r0, c3r1, c3r2, c3r3), 369 } 370 } 371 372 #[inline] 373 #[rustfmt::skip] identity() -> Self374 pub fn identity() -> Self { 375 Matrix4::new( 376 S::one(), S::zero(), S::zero(), S::zero(), 377 S::zero(), S::one(), S::zero(), S::zero(), 378 S::zero(), S::zero(), S::one(), S::zero(), 379 S::zero(), S::zero(), S::zero(), S::one(), 380 ) 381 } 382 383 /// Create a homogeneous transformation matrix from a translation vector. 384 #[inline] from_translation(v: Vector3<S>) -> Self385 pub fn from_translation(v: Vector3<S>) -> Self { 386 #[cfg_attr(rustfmt, rustfmt_skip)] 387 Matrix4::new( 388 S::one(), S::zero(), S::zero(), S::zero(), 389 S::zero(), S::one(), S::zero(), S::zero(), 390 S::zero(), S::zero(), S::one(), S::zero(), 391 v.x, v.y, v.z, S::one(), 392 ) 393 } 394 395 #[inline] row(&self, n: usize) -> Vector4<S>396 pub fn row(&self, n: usize) -> Vector4<S> { 397 match n { 398 0 => Vector4::new(self.x.x, self.y.x, self.z.x, self.w.x), 399 1 => Vector4::new(self.x.y, self.y.y, self.z.y, self.w.y), 400 2 => Vector4::new(self.x.z, self.y.z, self.z.z, self.w.z), 401 3 => Vector4::new(self.x.w, self.y.w, self.z.w, self.w.w), 402 _ => panic!("Matrix4::row: invalid row number: {}", n), 403 } 404 } 405 406 /// Create a homogeneous transformation matrix from a scale value. 407 #[inline] from_scale(value: S) -> Matrix4<S>408 pub fn from_scale(value: S) -> Matrix4<S> { 409 Matrix4::from_nonuniform_scale(value, value, value) 410 } 411 412 /// Create a homogeneous transformation matrix from a set of scale values. 413 #[inline] 414 #[rustfmt::skip] from_nonuniform_scale(x: S, y: S, z: S) -> Matrix4<S>415 pub fn from_nonuniform_scale(x: S, y: S, z: S) -> Matrix4<S> { 416 Matrix4::new( 417 x, S::zero(), S::zero(), S::zero(), 418 S::zero(), y, S::zero(), S::zero(), 419 S::zero(), S::zero(), z, S::zero(), 420 S::zero(), S::zero(), S::zero(), S::one(), 421 ) 422 } 423 } 424 425 impl<S> std::ops::Mul<Matrix4<S>> for Matrix4<S> 426 where 427 S: std::ops::Mul<Output = S> + std::ops::Add<Output = S> + Copy, 428 { 429 type Output = Self; 430 431 #[rustfmt::skip] mul(self, rhs: Matrix4<S>) -> Matrix4<S>432 fn mul(self, rhs: Matrix4<S>) -> Matrix4<S> { 433 let a = self.x; 434 let b = self.y; 435 let c = self.z; 436 let d = self.w; 437 438 #[cfg_attr(rustfmt, rustfmt_skip)] 439 Matrix4 { 440 x: a * rhs.x.x + b * rhs.x.y + c * rhs.x.z + d * rhs.x.w, 441 y: a * rhs.y.x + b * rhs.y.y + c * rhs.y.z + d * rhs.y.w, 442 z: a * rhs.z.x + b * rhs.z.y + c * rhs.z.z + d * rhs.z.w, 443 w: a * rhs.w.x + b * rhs.w.y + c * rhs.w.z + d * rhs.w.w, 444 } 445 } 446 } 447 448 /// Transform a [`Vector3`] with a [`Matrix4`]. 449 /// 450 /// ``` 451 /// use rgx::math::*; 452 /// let m = Matrix4::from_translation(Vector3::new(8., 8., 0.)); 453 /// let v = Vector3::new(1., 1., 0.); 454 /// 455 /// assert_eq!(m * v, Vector3::new(9., 9., 0.)); 456 /// ``` 457 impl std::ops::Mul<Vector3<f32>> for Matrix4<f32> { 458 type Output = Vector3<f32>; 459 mul(self, vec: Vector3<f32>) -> Vector3<f32>460 fn mul(self, vec: Vector3<f32>) -> Vector3<f32> { 461 let vec = vec.extend(1.); 462 Vector3::new(self.row(0) * vec, self.row(1) * vec, self.row(2) * vec) 463 } 464 } 465 466 /// Transform a [`Point2`] with a [`Matrix4`]. 467 /// 468 /// ``` 469 /// use rgx::math::*; 470 /// let m = Matrix4::from_translation(Vector3::new(8., 8., 0.)); 471 /// let p = Point2::new(1., 1.); 472 /// 473 /// assert_eq!(m * p, Point2::new(9., 9.)); 474 /// ``` 475 impl std::ops::Mul<Point2<f32>> for Matrix4<f32> { 476 type Output = Point2<f32>; 477 mul(self, p: Point2<f32>) -> Point2<f32>478 fn mul(self, p: Point2<f32>) -> Point2<f32> { 479 let vec = Vector4::new(p.x, p.y, 0., 1.); 480 Point2::new(self.row(0) * vec, self.row(1) * vec) 481 } 482 } 483 484 /// An orthographic projection with arbitrary left/right/bottom/top distances 485 #[derive(Copy, Clone, Debug, PartialEq)] 486 pub struct Ortho<S> { 487 pub left: S, 488 pub right: S, 489 pub bottom: S, 490 pub top: S, 491 pub near: S, 492 pub far: S, 493 } 494 495 impl<S: Float> From<Ortho<S>> for Matrix4<S> { from(ortho: Ortho<S>) -> Matrix4<S>496 fn from(ortho: Ortho<S>) -> Matrix4<S> { 497 let two: S = cast(2).unwrap(); 498 499 let c0r0 = two / (ortho.right - ortho.left); 500 let c0r1 = S::zero(); 501 let c0r2 = S::zero(); 502 let c0r3 = S::zero(); 503 504 let c1r0 = S::zero(); 505 let c1r1 = two / (ortho.top - ortho.bottom); 506 let c1r2 = S::zero(); 507 let c1r3 = S::zero(); 508 509 let c2r0 = S::zero(); 510 let c2r1 = S::zero(); 511 let c2r2 = -two / (ortho.far - ortho.near); 512 let c2r3 = S::zero(); 513 514 let c3r0 = -(ortho.right + ortho.left) / (ortho.right - ortho.left); 515 let c3r1 = -(ortho.top + ortho.bottom) / (ortho.top - ortho.bottom); 516 let c3r2 = -(ortho.far + ortho.near) / (ortho.far - ortho.near); 517 let c3r3 = S::one(); 518 519 #[cfg_attr(rustfmt, rustfmt_skip)] 520 Matrix4::new( 521 c0r0, c0r1, c0r2, c0r3, 522 c1r0, c1r1, c1r2, c1r3, 523 c2r0, c2r1, c2r2, c2r3, 524 c3r0, c3r1, c3r2, c3r3, 525 ) 526 } 527 } 528