class Mittsu::Vector4

Constants

DIMENSIONS
ELEMENTS

Public Class Methods

new(x = 0, y = 0, z = 0, w = 1) click to toggle source
Calls superclass method Mittsu::Vector::new
# File lib/mittsu/math/vector4.rb, line 8
def initialize(x = 0, y = 0, z = 0, w = 1)
  super [x.to_f, y.to_f, z.to_f, w.to_f]
end

Public Instance Methods

apply_matrix4(m) click to toggle source
# File lib/mittsu/math/vector4.rb, line 26
def apply_matrix4(m)
  _x, _y, _z, _w = *@elements
  e = m.elements
  @elements[0] = e[0] * _x + e[4] * _y + e[8]  * _z + e[12] * _w
  @elements[1] = e[1] * _x + e[5] * _y + e[9]  * _z + e[13] * _w
  @elements[2] = e[2] * _x + e[6] * _y + e[10] * _z + e[14] * _w
  @elements[3] = e[3] * _x + e[7] * _y + e[11] * _z + e[15] * _w
  self
end
divide_scalar(scalar) click to toggle source
# File lib/mittsu/math/vector4.rb, line 36
def divide_scalar(scalar)
  if scalar != 0.0
    inv_scalar = 1.0 / scalar
    @elements[0] *= inv_scalar
    @elements[1] *= inv_scalar
    @elements[2] *= inv_scalar
    @elements[3] *= inv_scalar
  else
    @elements = [0.0, 0.0, 0.0, 1.0]
  end
  self
end
dot(v) click to toggle source
# File lib/mittsu/math/vector4.rb, line 146
def dot(v)
  x * v.x + y * v.y + z * v.z + w * v.w
end
from_attribute(attribute, index, offset = 0) click to toggle source
# File lib/mittsu/math/vector4.rb, line 154
def from_attribute(attribute, index, offset = 0)
  index = index * attribute.itemSize + offset
  @elements[0] = attribute.array[index]
  @elements[1] = attribute.array[index + 1]
  @elements[2] = attribute.array[index + 2]
  @elements[3] = attribute.array[index + 3]
  self
end
length_manhattan() click to toggle source
# File lib/mittsu/math/vector4.rb, line 150
def length_manhattan
  x.abs + y.abs + z.abs + w.abs
end
set(x, y, z, w) click to toggle source
Calls superclass method Mittsu::Vector#set
# File lib/mittsu/math/vector4.rb, line 12
def set(x, y, z, w)
  super [x.to_f, y.to_f, z.to_f, w.to_f]
end
set_axis_angle_from_quaternion(q) click to toggle source
# File lib/mittsu/math/vector4.rb, line 49
def set_axis_angle_from_quaternion(q)
  # http:#www.euclideanspace.com/maths/geometry/rotations/conversions/quaternionToAngle/index.htm
  # q is assumed to be normalized
  @elements[3] = 2.0 * ::Math.acos(q.w)
  s = ::Math.sqrt(1.0 - q.w * q.w)
  if s < 0.0001
     @elements[0] = 1.0
     @elements[1] = 0.0
     @elements[2] = 0.0
  else
     @elements[0] = q.x / s
     @elements[1] = q.y / s
     @elements[2] = q.z / s
  end
  self
end
set_axis_angle_from_rotation_matrix(m) click to toggle source
# File lib/mittsu/math/vector4.rb, line 66
def set_axis_angle_from_rotation_matrix(m)
  # http:#www.euclideanspace.com/maths/geometry/rotations/conversions/matrixToAngle/index.htm
  # assumes the upper 3x3 of m is a pure rotation matrix (i.e, unscaled)
  angle, x1, y1, z1 = nil    # variables for result
  epsilon = 0.01    # margin to allow for rounding errors
  epsilon2 = 0.1    # margin to distinguish between 0 and 180 degrees
  te = m.elements
  m11, m12, m13 = te[0], te[4], te[8]
  m21, m22, m23 = te[1], te[5], te[9]
  m31, m32, m33 = te[2], te[6], te[10]
  if (((m12 - m21).abs < epsilon) &&
      ((m13 - m31).abs < epsilon) &&
      ((m23 - m32).abs < epsilon))
    # singularity found
    # first check for identity matrix which must have +1 for all terms
    # in leading diagonal and zero in other terms
    if (((m12 + m21).abs < epsilon2) &&
        ((m13 + m31).abs < epsilon2) &&
        ((m23 + m32).abs < epsilon2) &&
        ((m11 + m22 + m33 - 3).abs < epsilon2))
      # self singularity is identity matrix so angle = 0
      @elements = [1.0, 0.0, 0.0, 0.0]
      return self # zero angle, arbitrary axis
    end
    # otherwise self singularity is angle = 180
    angle = ::Math::PI
    xx = (m11 + 1.0) / 2.0
    yy = (m22 + 1.0) / 2.0
    zz = (m33 + 1.0) / 2.0
    xy = (m12 + m21) / 4.0
    xz = (m13 + m31) / 4.0
    yz = (m23 + m32) / 4.0
    if (xx > yy) && (xx > zz) # m11 is the largest diagonal term
      if xx < epsilon
        x1 = 0.0
        y1 = 0.707106781
        z1 = 0.707106781
      else
        x1 = ::Math.sqrt(xx)
        y1 = xy / x1
        z1 = xz / x1
      end
    elsif yy > zz # m22 is the largest diagonal term
      if yy < epsilon
        x1 = 0.707106781
        y1 = 0.0
        z1 = 0.707106781
      else
        y1 = ::Math.sqrt(yy)
        x1 = xy / y1
        z1 = yz / y1
      end
    else # m33 is the largest diagonal term so base result on self
      if zz < epsilon
        x1 = 0.707106781
        y1 = 0.707106781
        z1 = 0.0
      else
        z1 = ::Math.sqrt(zz)
        x1 = xz / z1
        y1 = yz / z1
      end
    end
    @elements = [x1, y1, z1, angle]
    return self # return 180 deg rotation
  end
  # as we have reached here there are no singularities so we can handle normally
  s = ::Math.sqrt((m32 - m23) * (m32 - m23) +
    (m13 - m31) * (m13 - m31) +
    (m21 - m12) * (m21 - m12)) # used to normalize
  s = 1.0 if (s.abs < 0.001)
  # prevent divide by zero, should not happen if matrix is orthogonal and should be
  # caught by singularity test above, but I've left it in just in case
  @elements[0] = (m32 - m23) / s
  @elements[1] = (m13 - m31) / s
  @elements[2] = (m21 - m12) / s
  @elements[3] = ::Math.acos((m11 + m22 + m33 - 1.0) / 2.0)
  self
end
w() click to toggle source
# File lib/mittsu/math/vector4.rb, line 19
def w; @elements[3]; end
w=(value) click to toggle source
# File lib/mittsu/math/vector4.rb, line 24
def w=(value); @elements[3] = value.to_f; end
x() click to toggle source
# File lib/mittsu/math/vector4.rb, line 16
def x; @elements[0]; end
x=(value) click to toggle source
# File lib/mittsu/math/vector4.rb, line 21
def x=(value); @elements[0] = value.to_f; end
y() click to toggle source
# File lib/mittsu/math/vector4.rb, line 17
def y; @elements[1]; end
y=(value) click to toggle source
# File lib/mittsu/math/vector4.rb, line 22
def y=(value); @elements[1] = value.to_f; end
z() click to toggle source
# File lib/mittsu/math/vector4.rb, line 18
def z; @elements[2]; end
z=(value) click to toggle source
# File lib/mittsu/math/vector4.rb, line 23
def z=(value); @elements[2] = value.to_f; end