notedeck

One damus client to rule them all
git clone git://jb55.com/notedeck
Log | Files | Refs | README | LICENSE

quaternion.rs (2434B)


      1 use crate::Vec3;
      2 
      3 // A simple quaternion implementation
      4 pub struct Quaternion {
      5     pub x: f32,
      6     pub y: f32,
      7     pub z: f32,
      8     pub w: f32,
      9 }
     10 
     11 impl Quaternion {
     12     // Create identity quaternion
     13     pub fn identity() -> Self {
     14         Self {
     15             x: 0.0,
     16             y: 0.0,
     17             z: 0.0,
     18             w: 1.0,
     19         }
     20     }
     21 
     22     // Create from axis-angle representation
     23     pub fn from_axis_angle(axis: &Vec3, angle: f32) -> Self {
     24         let half_angle = angle * 0.5;
     25         let s = half_angle.sin();
     26         Self {
     27             x: axis.x * s,
     28             y: axis.y * s,
     29             z: axis.z * s,
     30             w: half_angle.cos(),
     31         }
     32     }
     33 
     34     // Multiply two quaternions (combines rotations)
     35     pub fn multiply(&self, other: &Self) -> Self {
     36         Self {
     37             x: self.w * other.x + self.x * other.w + self.y * other.z - self.z * other.y,
     38             y: self.w * other.y - self.x * other.z + self.y * other.w + self.z * other.x,
     39             z: self.w * other.z + self.x * other.y - self.y * other.x + self.z * other.w,
     40             w: self.w * other.w - self.x * other.x - self.y * other.y - self.z * other.z,
     41         }
     42     }
     43 
     44     // Convert quaternion to 4x4 matrix (for 3D transformation with homogeneous coordinates)
     45     pub fn to_matrix4(&self) -> [f32; 16] {
     46         // Normalize quaternion
     47         let magnitude =
     48             (self.x * self.x + self.y * self.y + self.z * self.z + self.w * self.w).sqrt();
     49         let x = self.x / magnitude;
     50         let y = self.y / magnitude;
     51         let z = self.z / magnitude;
     52         let w = self.w / magnitude;
     53 
     54         let x2 = x * x;
     55         let y2 = y * y;
     56         let z2 = z * z;
     57         let xy = x * y;
     58         let xz = x * z;
     59         let yz = y * z;
     60         let wx = w * x;
     61         let wy = w * y;
     62         let wz = w * z;
     63 
     64         // Row-major 3x3 rotation matrix components
     65         let m00 = 1.0 - 2.0 * (y2 + z2);
     66         let m01 = 2.0 * (xy - wz);
     67         let m02 = 2.0 * (xz + wy);
     68 
     69         let m10 = 2.0 * (xy + wz);
     70         let m11 = 1.0 - 2.0 * (x2 + z2);
     71         let m12 = 2.0 * (yz - wx);
     72 
     73         let m20 = 2.0 * (xz - wy);
     74         let m21 = 2.0 * (yz + wx);
     75         let m22 = 1.0 - 2.0 * (x2 + y2);
     76 
     77         // Convert 3x3 rotation matrix to 4x4 transformation matrix
     78         // Note: This is column-major for WGPU
     79         [
     80             m00, m10, m20, 0.0, m01, m11, m21, 0.0, m02, m12, m22, 0.0, 0.0, 0.0, 0.0, 1.0,
     81         ]
     82     }
     83 }