class RMath3D::RQuat

Document-class: RMath3D::RQuat provies quaternion arithmetic.

Public Class Methods

dot(q_a,q_b) → value click to toggle source

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
new → (0,0,0,0) click to toggle source
new(e) → (e,e,e,e)
new( other ) : Copy Constructor
new( e0, e1, e2, e3 ) → (e0,e1,e2,e3)

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
slerp( q_a, q_b, t ) → interpolated quaternion click to toggle source

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

* click to toggle source

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
+ click to toggle source

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
+ click to toggle source

+quat : Unary plus operator.

# File lib/rmath3d/rmath3d_plain.rb, line 2694
def +@
  return self
end
- click to toggle source

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
- click to toggle source

-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
== click to toggle source

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
quat[i] → value click to toggle source

Returns the element at i.

# File lib/rmath3d/rmath3d_plain.rb, line 2492
def [](i)
  @e[i]
end
quat[i]= value click to toggle source

Stores value at i.

# File lib/rmath3d/rmath3d_plain.rb, line 2440
def []=(i,value)
  @e[i] = value
end
add!( quat2 ) click to toggle source

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
coerse(other) click to toggle source

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
conjugate! click to toggle source

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
getConjugated click to toggle source

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
getInverse → inverse quaternion click to toggle source

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
getLength click to toggle source

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
getLengthSq click to toggle source

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
getNormalized → RQuat click to toggle source

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
invert! → self click to toggle source

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
mul!( quat2 ) click to toggle source

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
normalize! → self click to toggle source

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
rotationAxis(axis,radian) → self click to toggle source

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
rotationMarix(mtx4) → self click to toggle source

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
setElements( e0, e1, e2, e3 ) click to toggle source

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
setIdentity click to toggle source

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
sub!( quat2 ) click to toggle source

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
toAxisAngle → [axis,radian] click to toggle source

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
to_a click to toggle source

Returns its elements as a new Array.

# File lib/rmath3d/rmath3d_plain.rb, line 2404
def to_a
  return @e
end
to_s click to toggle source

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
w → value click to toggle source

Returns the value of w.

# File lib/rmath3d/rmath3d_plain.rb, line 2523
def w() return @e[3] end
w= value click to toggle source

Stores value as w.

# File lib/rmath3d/rmath3d_plain.rb, line 2470
def w=(value) @e[3] = value end
x → value click to toggle source

Returns the value of x.

# File lib/rmath3d/rmath3d_plain.rb, line 2502
def x() return @e[0] end
x= value click to toggle source

Stores value as x.

# File lib/rmath3d/rmath3d_plain.rb, line 2449
def x=(value) @e[0] = value end
xyz → RVec3 click to toggle source

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
xyz= vXYZ click to toggle source

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
y → value click to toggle source

Returns the value of y.

# File lib/rmath3d/rmath3d_plain.rb, line 2509
def y() return @e[1] end
y= value click to toggle source

Stores value as y.

# File lib/rmath3d/rmath3d_plain.rb, line 2456
def y=(value) @e[1] = value end
z → value click to toggle source

Returns the value of z.

# File lib/rmath3d/rmath3d_plain.rb, line 2516
def z() return @e[2] end
z= value click to toggle source

Stores value as z.

# File lib/rmath3d/rmath3d_plain.rb, line 2463
def z=(value) @e[2] = value end