I notice that my old quat type has a few more utility functions
If anyone maintaining minib3d wants to use them feel free, they will need a *slight* adaptation as i was using a flat matrix [0..15] instead of [0..3,0..3]
it has the following methods
FromMatrix
ToMatrix
Normalise
FromAxisAngle
Multiply
GetEuler
Copy
FromEuler
Set
Invert
If anyone maintaining minib3d wants to use them feel free, they will need a *slight* adaptation as i was using a flat matrix [0..15] instead of [0..3,0..3]
it has the following methods
FromMatrix
ToMatrix
Normalise
FromAxisAngle
Multiply
GetEuler
Copy
FromEuler
Set
Invert
Type TQuat Field x!,y!,z!,w! Method FromMatrix(mat:Double[]) Local T:Float= 1 + mat[0] + mat[5] + mat[10] Local S:Float If ( T > 0.00000001 ) Then S = Sqr(T) * 2 X = ( mat[6] - mat[9] ) / S Y = ( mat[8] - mat[2] ) / S Z = ( mat[1] - mat[4] ) / S W = 0.25 * S Return EndIf If mat[0] > mat[5] And mat[0] > mat[10] Then 'Column 0: S = Sqr( 1.0 + mat[0] - mat[5] - mat[10] ) * 2 X = 0.25 * S Y = (mat[1] + mat[4] ) / S Z = (mat[8] + mat[2] ) / S W = (mat[6] - mat[9] ) / S ElseIf mat[5] > mat[10] 'Column 1: S = Sqr( 1.0 + mat[5] - mat[0] - mat[10] ) * 2 X = (mat[1] + mat[4] ) / S Y = 0.25 * S Z = (mat[6] + mat[9] ) / S W = (mat[8] - mat[2] ) / S Else 'Column 2: S = Sqr( 1.0 + mat[10] - mat[0] - mat[5] ) * 2 X = (mat[8] + mat[2] ) / S Y = (mat[6] + mat[9] ) / S Z = 0.25 * S W = (mat[1] - mat[4] ) / S EndIf EndMethod Method ToMatrix:Double[]() Local xx!=x*x Local xy!=x*y Local xz!=x*z Local xw!=x*w Local yy!=y*y Local yz!=y*z Local yw!=y*w Local zz!=z*z Local zw!=z*w Local m:Double[16] m[0]= 1-2*(yy+zz) m[4]= 2*(xy-zw) m[8]= 2*(xz+yw) m[1]= 2*(xy+zw) m[5]= 1-2*(xx+zz) m[9]= 2*(yz-xw) m[2]= 2*(xz-yw) m[6]= 2*(yz+xw) m[10]=1-2*(xx+yy) m[12]=0;m[13]=0;m[14]=0 m[3]=0;m[7]=0;m[11]=0 m[15]=1 Return m EndMethod Method Normalise() Local m:Double m=Sqr(w*w+x*x+y*y+z*z) If m=1 Then Return ' is exactly 1 more often than you'd think... w:/m x:/m y:/m z:/m EndMethod Method FromAxisAngle(a!,axis:TVec3) Local sin_a! = Sin( a / 2 ) Local cos_a! = Cos( a / 2 ) X = axis.x * sin_a Y = axis.y * sin_a Z = axis.z * sin_a W = cos_a Normalise() Return EndMethod Method Multiply:TQuat(q:TQuat) Local a#, b#, c#, d#, e#, f#, g#, h# a = (w + x) * (q.w + q.x) b = (z - y) * (q.y - q.z) c = (w - x) * (q.y + q.z) d = (y + z) * (q.w - q.x) e = (x + z) * (q.x + q.y) f = (x - z) * (q.x - q.y) g = (w + y) * (q.w - q.z) h = (w - y) * (q.w + q.z) w = b + (-e - f + g + h) / 2 x = a - ( e + f + g + h) / 2 y = c + ( e - f + g - h) / 2 z = d + ( e - f - g + h) / 2 End Method Const QuatToEulerAccuracy# = 0.000000000001 Method GetEuler:TVec3() ' using vec3 to hold eulers Local sint!, cost!, sinv!, cosv!, sinf!, cosf! Local cost_temp! normalise() sint = (2 * w * y) - (2 * x * z) cost_temp = 1.0 - (sint * sint) If Abs(cost_temp) > QuatToEulerAccuracy cost = Sqr(cost_temp) Else cost = 0 EndIf If Abs(cost) > QuatToEulerAccuracy sinv = ((2 * y * z) + (2 * w * x)) / cost cosv = (1 - (2 * x * x) - (2 * y * y)) / cost sinf = ((2 * x * y) + (2 * w * z)) / cost cosf = (1 - (2 * y * y) - (2 * z * z)) / cost Else sinv = (2 * w * x) - (2 * y * z) cosv = 1 - (2 * x * x) - (2 * z * z) sinf = 0 cosf = 1 EndIf Local out:TVec3=New Tvec3 out.x = ATan2(sinv, cosv) out.y = ATan2(sint, cost) out.z = ATan2(sinf, cosf) ' out.x=bound(out.x) ' out.y=bound(out.y) ' out.z=bound(out.z) Return out EndMethod Method Copy(q:TQuat) w=q.w x=q.x y=q.y z=q.z EndMethod Method FromEuler(src:TVec3) Local cr! = Cos(src.x/2) Local cp! = Cos(src.y/2) Local cy! = Cos(src.z/2) Local sr! = Sin(src.x/2) Local sp! = Sin(src.y/2) Local sy! = Sin(src.z/2) '; These variables are only here To cut down on the number of multiplications Local cpcy! = cp * cy Local spsy! = sp * sy Local spcy! = sp * cy Local cpsy! = cp * sy w = cr * cpcy + sr * spsy x = sr * cpcy - cr * spsy y = cr * spcy + sr * cpsy z = cr * cpsy - sr * spcy normalise() EndMethod Method Set(nw!,nx!,ny!,nz!) w=nw;x=nx;y=ny;z=nz EndMethod Method Invert() x=-x;y=-y;z=-z EndMethod EndType