Class: Ra::Transform

Inherits:
Matrix
  • Object
show all
Defined in:
lib/ra/transform.rb

Overview

A transform is represnted with a four by four matrix. These transforms are useful manupulate vectors. For example:

p = Vector[1, 2, 3, Ra::Tuple::POINT]
Ra::Transform.translate(2, 3, 4) * p == Vector[3, 5, 7, Ra::Tupl::POINT]
Ra::Transform.scale(1, 2, 3) * p == Vector[1, 4, 9, Ra::Tuple::POINT]

As a convenience, transforms can also be chained:

Ra::Transform
  .translate(2, 3, 4)
  .scale(1, 2, 3)
  .rotate_x(Math::PI / 4)
  .rotate_y(Math::PI / 4)
  .rotate_z(Math::PI / 4)

Constant Summary collapse

IDENTITY =
identity(4)

Class Method Summary collapse

Instance Method Summary collapse

Class Method Details

.rotate_x(rotation) ⇒ Ra::Transform

Parameters:

  • rotation (Numeric)

Returns:



62
63
64
65
66
67
68
69
# File 'lib/ra/transform.rb', line 62

def self.rotate_x(rotation)
  self[
    [1, 0, 0, 0],
    [0, +Math.cos(rotation), -Math.sin(rotation), 0],
    [0, +Math.sin(rotation), +Math.cos(rotation), 0],
    [0, 0, 0, 1],
  ]
end

.rotate_y(rotation) ⇒ Ra::Transform

Parameters:

  • rotation (Numeric)

Returns:



73
74
75
76
77
78
79
80
# File 'lib/ra/transform.rb', line 73

def self.rotate_y(rotation)
  self[
    [+Math.cos(rotation), 0, +Math.sin(rotation), 0],
    [0, 1, 0, 0],
    [-Math.sin(rotation), 0, +Math.cos(rotation), 0],
    [0, 0, 0, 1],
  ]
end

.rotate_z(rotation) ⇒ Ra::Transform

Parameters:

  • rotation (Numeric)

Returns:



84
85
86
87
88
89
90
91
# File 'lib/ra/transform.rb', line 84

def self.rotate_z(rotation)
  self[
    [+Math.cos(rotation), -Math.sin(rotation), 0, 0],
    [+Math.sin(rotation), +Math.cos(rotation), 0, 0],
    [0, 0, 1, 0],
    [0, 0, 0, 1],
  ]
end

.scale(x, y, z) ⇒ Ra::Transform

Parameters:

  • x (Numeric)
  • y (Numeric)
  • z (Numeric)

Returns:



51
52
53
54
55
56
57
58
# File 'lib/ra/transform.rb', line 51

def self.scale(x, y, z)
  self[
    [x, 0, 0, 0],
    [0, y, 0, 0],
    [0, 0, z, 0],
    [0, 0, 0, 1],
  ]
end

.translate(x, y, z) ⇒ Ra::Transform

Parameters:

  • x (Numeric)
  • y (Numeric)
  • z (Numeric)

Returns:



38
39
40
41
42
43
44
45
# File 'lib/ra/transform.rb', line 38

def self.translate(x, y, z)
  self[
    [1, 0, 0, x],
    [0, 1, 0, y],
    [0, 0, 1, z],
    [0, 0, 0, 1],
  ]
end

.view(from:, to:, up:) ⇒ Ra::Transform

Parameters:

  • from (Vector)
  • to (Vector)
  • up (Vector)

Returns:



25
26
27
28
29
30
31
32
# File 'lib/ra/transform.rb', line 25

def self.view(from:, to:, up:)
  f = (to - from).normalize
  l = Tuple.cross(f, up.normalize)
  u = Tuple.cross(l, f)

  self[l, u, -f, [0, 0, 0, 1]]
    .translate(-from[0], -from[1], -from[2])
end

Instance Method Details

#inverseRa::Transform

Avoid re-computing a transform inverse by memoizing.

Returns:



130
131
132
# File 'lib/ra/transform.rb', line 130

def inverse
  @inverse ||= super
end

#rotate_x(rotation) ⇒ Ra::Transform

Parameters:

  • rotation (Numeric)

Returns:



111
112
113
# File 'lib/ra/transform.rb', line 111

def rotate_x(rotation)
  self * self.class.rotate_x(rotation)
end

#rotate_y(rotation) ⇒ Ra::Transform

Parameters:

  • rotation (Numeric)

Returns:



117
118
119
# File 'lib/ra/transform.rb', line 117

def rotate_y(rotation)
  self * self.class.rotate_y(rotation)
end

#rotate_z(rotation) ⇒ Ra::Transform

Parameters:

  • rotation (Numeric)

Returns:



123
124
125
# File 'lib/ra/transform.rb', line 123

def rotate_z(rotation)
  self * self.class.rotate_z(rotation)
end

#scale(x, y, z) ⇒ Ra::Transform

Parameters:

  • x (Numeric)
  • y (Numeric)
  • z (Numeric)

Returns:



105
106
107
# File 'lib/ra/transform.rb', line 105

def scale(x, y, z)
  self * self.class.scale(x, y, z)
end

#tranposeRa::Transform

Avoid re-computing a transform tranpose by memoizing.

Returns:



137
138
139
# File 'lib/ra/transform.rb', line 137

def tranpose
  @tranpose ||= super
end

#translate(x, y, z) ⇒ Ra::Transform

Parameters:

  • x (Numeric)
  • y (Numeric)
  • z (Numeric)

Returns:



97
98
99
# File 'lib/ra/transform.rb', line 97

def translate(x, y, z)
  self * self.class.translate(x, y, z)
end