class RMath3D::RQuat
Document-class: RMath3D::RQuat
provies quaternion arithmetic.
Public Class Methods
Calculates the dot product of q_a
and q_b
.
# File lib/rmath3d/rmath3d_plain.rb, line 2557 def RQuat.dot( q1, q2 ) if q1.class != RQuat || q2.class != RQuat raise TypeError, "RQuat#dot : Unknown type q1:#{q2.class}, q2:#{q2.class}." return nil end return q1.x*q2.x + q1.y*q2.y + q1.z*q2.z + q1.w*q2.w end
Creates a new quaternion.
# File lib/rmath3d/rmath3d_plain.rb, line 2358 def initialize( *a ) @e = [] case a.length when 0 @e = [0.0, 0.0, 0.0, 0.0] when 1 case a[0] when Float, Integer @e = [ a[0], a[0], a[0], a[0] ] when RQuat @e = [ a[0].x, a[0].y, a[0].z, a[0].w ] else raise TypeError, "RQuat#initialize : Unknown type #{a[0].class}." return nil end when 4 a.each_with_index do |elem, index| case elem when Float, Integer @e[index] = elem else raise TypeError, "RQuat#initialize : Unknown type #{elem.class}." return nil end end else raise RuntimeError, "RQuat#initialize : wrong # of arguments (#{a.length})" return nil end return self end
Calculates the spherical linear interpolation between q_a
and q_b
at time t
(0.0~1.0).
# File lib/rmath3d/rmath3d_plain.rb, line 2571 def RQuat.slerp( q1, q2, t ) if q1.class != RQuat || q2.class != RQuat raise TypeError, "RQuat#slerp : Unknown type q1:#{q2.class}, q2:#{q2.class}." return nil end s1 = 0.0 s2 = 0.0 it = 1.0 - t cosine = RQuat.dot( q1, q2 ) qn1 = q1 qn2 = q2 if ( cosine < 0.0 ) cosine *= -1.0 qn1 *= -1.0 end if ( (1.0 - cosine) > TOLERANCE ) theta = Math.acos( cosine ) sin_theta = Math.sin( theta ) s1 = Math.sin( it * theta ) / sin_theta s2 = Math.sin( t * theta ) / sin_theta else s1 = it s2 = t end qn1 *= s1 qn2 *= s2 qResult = qn1 + qn2 return qResult end
Public Instance Methods
quat1 * quat2 : Binary multiply operator.
# File lib/rmath3d/rmath3d_plain.rb, line 2738 def *( arg ) case arg when RQuat q1x = self.x q1y = self.y q1z = self.z q1w = self.w q2x = arg.x q2y = arg.y q2z = arg.z q2w = arg.w x = q1w*q2x + q1x*q2w + q1y*q2z - q1z*q2y y = q1w*q2y - q1x*q2z + q1y*q2w + q1z*q2x z = q1w*q2z + q1x*q2y - q1y*q2x + q1z*q2w w = q1w*q2w - q1x*q2x - q1y*q2y - q1z*q2z return RQuat.new( x, y, z, w ) when Float, Integer return RQuat.new( @e[0]*arg, @e[1]*arg, @e[2]*arg, @e[3]*arg ) else raise TypeError, "RQuat#* : Unknown type #{arg}." return nil end end
quat1 + quat2 : Binary plus operator.
# File lib/rmath3d/rmath3d_plain.rb, line 2712 def +( arg ) if arg.class != RQuat raise TypeError, "RQuat#+ : Unknown type #{arg.class}." return nil end RQuat.new( x+arg.x, y+arg.y, z+arg.z, w+arg.w ) end
+quat : Unary plus operator.
# File lib/rmath3d/rmath3d_plain.rb, line 2694 def +@ return self end
quat1 - quat2 : Binary minus operator.
# File lib/rmath3d/rmath3d_plain.rb, line 2725 def -( arg ) if arg.class != RQuat raise TypeError, "RQuat#- : Unknown type #{arg.class}." return nil end RQuat.new( x-arg.x, y-arg.y, z-arg.z, w-arg.w ) end
-quat : Unary minus operator.
# File lib/rmath3d/rmath3d_plain.rb, line 2703 def -@ return RQuat.new( -@e[0], -@e[1], -@e[2], -@e[3] ) end
quat1 == quat2 : evaluates equality.
# File lib/rmath3d/rmath3d_plain.rb, line 2767 def ==( other ) if other.class == RQuat if (x-other.x).abs<=Float::EPSILON && (y-other.y).abs<=Float::EPSILON && (z-other.z).abs<=Float::EPSILON && (w-other.w).abs<=Float::EPSILON return true else return false end else return false end end
Returns the element at i
.
# File lib/rmath3d/rmath3d_plain.rb, line 2492 def [](i) @e[i] end
Stores value
at i
.
# File lib/rmath3d/rmath3d_plain.rb, line 2440 def []=(i,value) @e[i] = value end
quat1 += quat2 : appends the elements of quat2
into corresponding quat1
elements.
# File lib/rmath3d/rmath3d_plain.rb, line 2787 def add!( other ) if other.class != RQuat raise TypeError, "RQ#add! : Unknown type #{other.class}." return nil end self.x += other.x self.y += other.y self.z += other.z self.w += other.w return self end
Resolves type mismatch.
# File lib/rmath3d/rmath3d_plain.rb, line 2413 def coerce( arg ) case arg when Float, Integer return [ self, arg ] else raise TypeError, "RQuat#coerce : #{arg.self} can't be coerced into #{self.class}." return nil end end
Conjugates itself.
# File lib/rmath3d/rmath3d_plain.rb, line 2634 def conjugate! @e[0] *= -1.0 @e[1] *= -1.0 @e[2] *= -1.0 return self end
Returns its conjugate quaternion.
# File lib/rmath3d/rmath3d_plain.rb, line 2625 def getConjugated return RQuat.new( -@e[0], -@e[1], -@e[2], @e[3] ) end
Returns the inverse.
# File lib/rmath3d/rmath3d_plain.rb, line 2646 def getInverse length_sq = getLengthSq() return RQuat.new( -@e[0]/length_sq, -@e[1]/length_sq, -@e[2]/length_sq, @e[3]/length_sq ) end
Returns the Euclidean length.
# File lib/rmath3d/rmath3d_plain.rb, line 2539 def getLength return Math.sqrt( @e[0]*@e[0] + @e[1]*@e[1] + @e[2]*@e[2] + @e[3]*@e[3] ) end
Returns the squared Euclidean length.
# File lib/rmath3d/rmath3d_plain.rb, line 2548 def getLengthSq return (@e[0]*@e[0] + @e[1]*@e[1] + @e[2]*@e[2] + @e[3]*@e[3]).to_f end
Returns normalized quaternion.
# File lib/rmath3d/rmath3d_plain.rb, line 2670 def getNormalized length = getLength() return RQuat.new( @e[0]/length, @e[1]/length, @e[2]/length, @e[3]/length ) end
Inverts itself.
# File lib/rmath3d/rmath3d_plain.rb, line 2656 def invert! length_sq = getLengthSq() @e[0] /= -length_sq @e[1] /= -length_sq @e[2] /= -length_sq @e[3] /= length_sq return self end
quat1 *= quat2
# File lib/rmath3d/rmath3d_plain.rb, line 2825 def mul!( other ) case other when RQuat q1x = self.x q1y = self.y q1z = self.z q1w = self.w q2x = other.x q2y = other.y q2z = other.z q2w = other.w x = q1w*q2x + q1x*q2w + q1y*q2z - q1z*q2y y = q1w*q2y - q1x*q2z + q1y*q2w + q1z*q2x z = q1w*q2z + q1x*q2y - q1y*q2x + q1z*q2w w = q1w*q2w - q1x*q2x - q1y*q2y - q1z*q2z self.x = x self.y = y self.z = z self.w = w return self when Float, Integer self.x *= other self.y *= other self.z *= other self.w *= other return self else raise TypeError, "RQuat#mul! : Unknown type #{other.class}." return nil end end
Normalizes itself.
# File lib/rmath3d/rmath3d_plain.rb, line 2680 def normalize! length = getLength() @e[0] /= length @e[1] /= length @e[2] /= length @e[3] /= length return self end
Makes a quaternion that rotates around the axis
.
# File lib/rmath3d/rmath3d_plain.rb, line 2915 def rotationAxis( axis, radian ) if axis.class != RVec3 raise TypeError, "RQuat#rotationAxis : Unknown type #{axis.class}." return nil end s = Math.sin( radian / 2.0 ) self.x = s * axis.x self.y = s * axis.y self.z = s * axis.z self.w = Math.cos( radian / 2.0 ) return self end
Makes a rotation quaternion from a rotation matrix mtx4
(RMtx4
).
# File lib/rmath3d/rmath3d_plain.rb, line 2867 def rotationMatrix( mtx ) if mtx.class != RMtx3 && mtx.class != RMtx4 raise TypeError, "RQuat#rotationMatrix : Unknown type #{mtx.class}." return nil end diag00 = mtx.getElement(0,0) diag11 = mtx.getElement(1,1) diag22 = mtx.getElement(2,2) if ( diag00 + diag11 + diag22 > 0.0 ) t = diag00 + diag11 + diag22 + 1.0 s = 1.0 / ( Math.sqrt( t ) * 2.0 ) self.w = s * t self.z = (mtx.getElement(1,0) - mtx.getElement(0,1)) * s self.y = (mtx.getElement(0,2) - mtx.getElement(2,0)) * s self.x = (mtx.getElement(2,1) - mtx.getElement(1,2)) * s elsif ( diag00 > diag11 && diag00 > diag22 ) t = diag00 - diag11 - diag22 + 1.0 s = 1.0 / ( Math.sqrt( t ) * 2.0 ) self.x = s * t self.y = (mtx.getElement(1,0) + mtx.getElement(0,1)) * s self.z = (mtx.getElement(0,2) + mtx.getElement(2,0)) * s self.w = (mtx.getElement(2,1) - mtx.getElement(1,2)) * s elsif ( diag11 > diag22 ) t = -diag00 + diag11 - diag22 + 1.0 s = 1.0 / ( Math.sqrt( t ) * 2.0 ) self.y = s * t self.x = (mtx.getElement(1,0) + mtx.getElement(0,1)) * s self.w = (mtx.getElement(0,2) - mtx.getElement(2,0)) * s self.z = (mtx.getElement(2,1) + mtx.getElement(1,2)) * s else t = -diag00 - diag11 + diag22 + 1.0 s = 1.0 / ( Math.sqrt( t ) * 2.0 ) self.z = s * t self.w = (mtx.getElement(1,0) - mtx.getElement(0,1)) * s self.x = (mtx.getElement(0,2) + mtx.getElement(2,0)) * s self.y = (mtx.getElement(2,1) + mtx.getElement(1,2)) * s end return self end
Stores given 4 new values.
# File lib/rmath3d/rmath3d_plain.rb, line 2428 def setElements( x, y, z, w ) self.x = x self.y = y self.z = z self.w = w end
Sets as identity quaternion.
# File lib/rmath3d/rmath3d_plain.rb, line 2612 def setIdentity self.x = 0.0 self.y = 0.0 self.z = 0.0 self.w = 1.0 return self end
quat1 -= quat2 : subtracts the elements of quat2
from corresponding quat1
elements.
# File lib/rmath3d/rmath3d_plain.rb, line 2806 def sub!( other ) if other.class != RQuat raise TypeError, "RQuat#sub! : Unknown type #{other.class}." return nil end self.x -= other.x self.y -= other.y self.z -= other.z self.w -= other.w return self end
Returns its rotation axis (RVec3
) and rotation angle (in radian).
# File lib/rmath3d/rmath3d_plain.rb, line 2935 def toAxisAngle axis = RVec3.new( self.x, self.y, self.z ).normalize! radian = 2.0 * Math.acos( self.w ) return [ axis, radian ] end
Returns its elements as a new Array.
# File lib/rmath3d/rmath3d_plain.rb, line 2404 def to_a return @e end
Returns human-readable string.
# File lib/rmath3d/rmath3d_plain.rb, line 2395 def to_s return "( #{@e[0]}, #{@e[1]}, #{@e[2]}, #{@e[3]} )" end
Returns the value of w
.
# File lib/rmath3d/rmath3d_plain.rb, line 2523 def w() return @e[3] end
Stores value
as w
.
# File lib/rmath3d/rmath3d_plain.rb, line 2470 def w=(value) @e[3] = value end
Returns the value of x
.
# File lib/rmath3d/rmath3d_plain.rb, line 2502 def x() return @e[0] end
Stores value
as x
.
# File lib/rmath3d/rmath3d_plain.rb, line 2449 def x=(value) @e[0] = value end
Returns the values of x
, y
and z
with new RVec3(x
,y
,z
).
# File lib/rmath3d/rmath3d_plain.rb, line 2530 def xyz() return RVec3.new( @e[0], @e[1], @e[2] ) end
Copies the values of vXYZ
(RVec3
) into x
, y
and z
.
# File lib/rmath3d/rmath3d_plain.rb, line 2477 def xyz=( arg ) if arg.class != RVec3 raise TypeError, "RQuat#xyz= : Unknown type #{arg.class}." return nil end @e[0] = arg.x @e[1] = arg.y @e[2] = arg.z end
Returns the value of y
.
# File lib/rmath3d/rmath3d_plain.rb, line 2509 def y() return @e[1] end
Stores value
as y
.
# File lib/rmath3d/rmath3d_plain.rb, line 2456 def y=(value) @e[1] = value end
Returns the value of z
.
# File lib/rmath3d/rmath3d_plain.rb, line 2516 def z() return @e[2] end
Stores value
as z
.
# File lib/rmath3d/rmath3d_plain.rb, line 2463 def z=(value) @e[2] = value end