1 module daque.math.quaternion; 2 3 import std.math; 4 5 import daque.math.geometry; 6 import daque.math.linear; 7 8 struct Quaternion(R) 9 { 10 public R scalar; 11 public R[3] vector; 12 13 public this(R[4] components) 14 { 15 scalar = components[0]; 16 vector[] = components[1 .. 4]; 17 } 18 19 public this(R scalar, R[3] vector) 20 { 21 this.scalar = scalar; 22 this.vector = vector; 23 } 24 25 static public Quaternion!R getRotation(R[3] axis, R amount) 26 { 27 Quaternion quaternion = Quaternion([0, 0, 0, 0]); 28 quaternion.scalar = sin(amount / 2.0f); 29 quaternion.vector[] = cos(amount / 2.0f) * axis[]; 30 return quaternion; 31 } 32 33 Matrix!(R, 3, 3) getRotationMatrix() 34 { 35 auto m = Matrix!(R, 3, 3).Identity(); 36 37 for(uint j; j < 3; j++) 38 { 39 Quaternion columnQuaternion = Quaternion([0, 0, 0, 0]); 40 columnQuaternion.scalar = 0; 41 for(uint i; i < 3; i++) 42 columnQuaternion.vector[i] = m[i, j]; 43 44 columnQuaternion = columnQuaternion * this; 45 for(uint i; i < 3; i++) 46 m[i, j] = columnQuaternion.vector[i]; 47 } 48 49 return m; 50 } 51 52 public Quaternion opBinary(string op)(Quaternion rhs) 53 { 54 Quaternion result; 55 static if (op == "+") 56 { 57 result.scalar = this.scalar + rhs.scalar; 58 result.vector[] = this.vector[] + rhs.vector[]; 59 } 60 else static if (op == "*") 61 { 62 result.scalar = this.scalar * rhs.scalar - dot(this.vector, rhs.vector); 63 result.vector[] = this.scalar * rhs.vector[] + this.vector[] * rhs.scalar + cross(this.vector, rhs.vector)[]; 64 } 65 else 66 { 67 static assert(0, "Quaternion: Unsupported operation: " ~ op); 68 } 69 return result; 70 } 71 72 public Quaternion conjugate() 73 { 74 Quaternion conjugateQuaternion; 75 conjugateQuaternion.scalar = this.scalar; 76 conjugateQuaternion.vector[] = -1 * this.vector[]; 77 return conjugateQuaternion; 78 } 79 80 public Quaternion inverse() 81 { 82 Quaternion invSquareAbs = Quaternion(1.0 / squareAbs(), [0, 0, 0]); 83 return conjugate() * invSquareAbs; 84 } 85 86 public real abs() 87 { 88 return sqrt(squareAbs); 89 } 90 91 public real squareAbs() 92 { 93 return (this * this.conjugate).scalar; 94 } 95 }