1 module math.linear.axis_rot; 2 3 import std.math; 4 5 import math.linear.vector; 6 7 public import math.linear._qa; 8 9 // TODO: Add tests to ensure T is a compotable type (number, etc...). 10 struct AxisRot(T) { 11 union { 12 T[4] data; 13 struct { 14 T angle; 15 Vec3!T axis; 16 } 17 struct { 18 T a; 19 T x; 20 T y; 21 T z; 22 } 23 } 24 25 this(T angle, T[3] axis ...) { 26 this.angle = angle; 27 this.axis = axis; 28 } 29 this(T[4] data) { 30 this.data = data; 31 } 32 this(T[3] axis, T angle) { 33 this.angle = angle; 34 this.axis = axis; 35 } 36 this(typeof(this) v) { 37 this.data = v.data; 38 } 39 40 Quat!T _toQuat() { 41 return Quat!T(this); 42 } 43 alias _toQuat this; 44 45 auto opBinary(string op, T)(T b) if (__traits(compiles, opBinaryImpl!op(this, b))){ 46 return opBinaryImpl!op(this, b); 47 } 48 auto opBinaryRight(string op, T)(T a) if (__traits(compiles, opBinaryImpl!op(a, this))){ 49 return opBinaryImpl!op(a,this); 50 } 51 auto opOpAssign(string op, T)(T b) if (__traits(compiles, opOpAssignImpl!op(this, b))){ 52 return opOpAssignImpl!op(this, b); 53 } 54 } 55 auto axisRot(T)(T[4] data) { 56 return AxisRot!T(data); 57 } 58 auto axisRot(T)(T angle, T[3] axis ...) { 59 return AxisRot!T(angle, axis); 60 } 61 auto axisRot(T)(T[3] axis, T angle) { 62 return AxisRot!T(angle, axis); 63 } 64 auto axisRot(T)(axisRot!T data) { 65 return AxisRot!T(data); 66 } 67 68 69 Quat!T toQuat(T)(AxisRot!T a) { 70 return Quat!T(a); 71 } 72 73 74 AxisRot!T identity(T)() { 75 return AxisRot!T(0,[0,0,0]); 76 } 77 78 void normalize(T)(AxisRot!T t) { 79 if (t.angle==0) return; 80 t.axis.normalize; 81 } 82 AxisRot!T normalized(T)(AxisRot!T t) { 83 if (t.angle==0) return identity; 84 return AxisRot!T(t.angle,t.axis.normalized); 85 } 86 87 88 void invert(T)(AxisRot!T t) { 89 t.axis.invert; 90 } 91 AxisRot!T inverse(T)(AxisRot!T t) { 92 return AxisRot!T(t.a, [-t.x, -t.y, -t.z]); 93 } 94 95 96 97 auto opBinaryImpl(string op:"*", T,U)(AxisRot!T a, AxisRot!U b) 98 if (__traits(compiles, typeof(mixin("a.data[0]*b.data[0]"))) 99 && __traits(compiles, typeof(mixin("a.data[0]+b.data[0]"))) 100 && __traits(compiles, typeof(mixin("a.data[0]-b.data[0]"))) 101 ) 102 { 103 if (a.angle == 0) return b; 104 if (b.angle == 0) return a; 105 return axisRot ( acos(cos(a.a)*cos(b.a) - dot(a.axis*sin(a.a),(b.axis*sin(b.a)))) 106 , ((cos(a.a))*(b.axis*sin(b.a)) + (cos(b.a))*(a.axis*sin(a.a)) + cross((a.axis*sin(a.a)),(b.axis*sin(b.a)))).normalized 107 ); 108 } 109 110 auto opBinaryImpl(string op:"*", T,U)(AxisRot!T a, U b) 111 if (__traits(compiles, typeof(mixin("a.data[0]*b")))) 112 { 113 return axisRot(a.angle*b, a.axis); 114 } 115 116 117 118 119 120 auto opOpAssignImpl(string op, size_t size,T,U)(ref Vec!(T, size) a, Vec!(U, size) b) 121 if (__traits(compiles, typeof(mixin("a.data[0]"~op~"=b.data[0]")))) 122 { 123 mixin("a.data[]"~op~"=b.data[];"); 124 return a; 125 } 126 auto opOpAssignImpl(string op, size_t size,T,U)(ref Vec!(T, size) a, U[size] b) 127 if (__traits(compiles, typeof(mixin("a.data[0]"~op~"=b[0]")))) 128 { 129 mixin("a.data[]"~op~"=b[];"); 130 return a; 131 } 132 auto opOpAssignImpl(string op, size_t size,T,U)(ref Vec!(T, size) a, U b) 133 if (__traits(compiles, typeof(mixin("a[0]"~op~"=b")))) 134 { 135 mixin("a.data[]"~op~"=b;"); 136 return a; 137 } 138