quat.monkey2 3.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189
  1. Namespace std.geom
  2. #rem monkeydoc Convenience type alias for Quat\<Float\>.
  3. #end
  4. Alias Quatf:Quat<Float>
  5. #rem monkeydoc The Quat class provides support for quaternions.
  6. #end
  7. Struct Quat<T>
  8. Field v:Vec3<T>
  9. Field w:T
  10. Method New()
  11. w=1
  12. End
  13. Method New( v:Vec3<T>,w:Float )
  14. Self.v=v; Self.w=w
  15. End
  16. Method New( vx:T,vy:T,vz:T,w:T )
  17. v.x=vx ; v.y=vy ; v.z=vz ; Self.w=w
  18. End
  19. Method New( m:Mat3<T> )
  20. 'Note: assumes m is orthogonalized
  21. '
  22. Const EPSILON:=0
  23. Local t:=m.i.x+m.j.y+m.k.z
  24. If t>EPSILON
  25. t=Sqrt( t+1 )*2
  26. v.x=(m.k.y-m.j.z)/t
  27. v.y=(m.i.z-m.k.x)/t
  28. v.z=(m.j.x-m.i.y)/t
  29. w=t/4
  30. Else If m.i.x>m.j.y And m.i.x>m.k.z
  31. t=Sqrt( m.i.x-m.j.y-m.k.z+1 )*2
  32. v.x=t/4
  33. v.y=(m.j.x+m.i.y)/t
  34. v.z=(m.i.z+m.k.x)/t
  35. w=(m.k.y-m.j.z)/t
  36. Else If m.j.y>m.k.z
  37. t=Sqrt( m.j.y-m.k.z-m.i.x+1 )*2
  38. v.x=(m.j.x+m.i.y)/t
  39. v.y=t/4
  40. v.z=(m.k.y+m.j.z)/t
  41. w=(m.i.z-m.k.x)/t
  42. Else
  43. t=Sqrt( m.k.z-m.j.y-m.i.x+1 )*2
  44. v.x=(m.i.z+m.k.x)/t
  45. v.y=(m.k.y+m.j.z)/t
  46. v.z=t/4
  47. w=(m.j.x-m.i.y)/t
  48. Endif
  49. End
  50. Operator To<C>:Quat<C>()
  51. Return New Quat<C>( v,w )
  52. End
  53. Operator To:Mat3<T>()
  54. Return New Mat3<T>( Self )
  55. End
  56. Method To:String()
  57. Return "Quat("+v+","+w+")"
  58. End
  59. Property Length:Double()
  60. Return Sqrt( v.Dot(v) + w*w )
  61. End
  62. Property I:Vec3<T>()
  63. Local xz:=v.x*v.z , wy:=w*v.y
  64. Local xy:=v.x*v.y , wz:=w*v.z
  65. Local yy:=v.y*v.y , zz:=v.z*v.z
  66. Return New Vec3<T>( 1-2*(yy+zz),2*(xy-wz),2*(xz+wy) )
  67. End
  68. Property J:Vec3<T>()
  69. Local yz:=v.y*v.z , wx:=w*v.x
  70. Local xy:=v.x*v.y , wz:=w*v.z
  71. Local xx:=v.x*v.x , zz:=v.z*v.z
  72. Return New Vec3<T>( 2*(xy+wz),1-2*(xx+zz),2*(yz-wx) )
  73. End
  74. Property K:Vec3<T>()
  75. Local xz:=v.x*v.z , wy:=w*v.y
  76. Local yz:=v.y*v.z , wx:=w*v.x
  77. Local xx:=v.x*v.x , yy:=v.y*v.y
  78. Return New Vec3<T>( 2*(xz-wy),2*(yz+wx),1-2*(xx+yy) )
  79. End
  80. Operator-:Quat()
  81. Return New Quat( -v,w )
  82. End
  83. Operator+:Quat( q:Quat )
  84. Return New Quat( v+q.v,w+q.w )
  85. End
  86. Operator-:Quat( q:Quat )
  87. Return New Quat( v-q.v,w-q.w )
  88. End
  89. Operator*:Quat( q:Quat )
  90. Return New Quat( q.v.Cross( v )+q.v*w+v*q.w, w*q.w-v.Dot( q.v ) )
  91. End
  92. Operator*:Vec3<T>( v:Vec3<T> )
  93. Return (Self * New Quat( v,0 ) * -Self).v
  94. End
  95. Operator*:Quat( t:Double )
  96. Return New Quat( v*t,w*t )
  97. End
  98. Operator/:Quat( t:Double )
  99. Return New Quat( v/t,w/t )
  100. End
  101. Method GetYaw:Double()
  102. Return K.Yaw
  103. End
  104. Method GetPitch:Double()
  105. Return K.Pitch
  106. End
  107. Method GetRoll:Double()
  108. Return ATan2( I.y,J.y )
  109. End
  110. Method Dot:Double( q:Quat )
  111. Return v.x*q.v.x + v.y*q.v.y + v.z*q.v.z + w*q.w
  112. End
  113. Method Normalize:Quat()
  114. Return Self/Length
  115. End
  116. Method Slerp:Quat( q:Quat,a:Double )
  117. Const EPSILON:=0
  118. Local t:=q
  119. Local b:=1-a
  120. Local d:=Dot( q )
  121. If d<0
  122. t.v=-t.v
  123. t.w=-t.w
  124. d=-d
  125. Endif
  126. If d<1-EPSILON
  127. Local om:=ACos( d )
  128. Local si:=Sin( om )
  129. a=Sin( a*om )/si
  130. b=Sin( b*om )/si
  131. Endif
  132. Return Self*b + t*a
  133. End
  134. Function Pitch:Quat( r:Double )
  135. Return New Quat( Sin( r/2 ),0,0,Cos( r/2 ) )
  136. End
  137. Function Yaw:Quat( r:Double )
  138. Return New Quat( 0,Sin( r/2 ),0,Cos( r/2 ) )
  139. End
  140. Function Roll:Quat( r:Double )
  141. Return New Quat( 0,0,Sin( r/2 ),Cos( r/2 ) )
  142. End
  143. Function Rotation:Quat( rv:Vec3<Double> )
  144. Return Yaw( rv.y ) * Pitch( rv.x ) * Roll( rv.z )
  145. End
  146. Function Rotation:Quat( rx:Double,ry:Double,rz:Double )
  147. Return Yaw( ry ) * Pitch( rx ) * Roll( rz )
  148. End
  149. End