Class: Ray::Matrix

Inherits:
Object
  • Object
show all
Defined in:
ext/matrix.c,
lib/ray/matrix.rb,
ext/matrix.c

Overview

Ray::Matrix represents a 4x4 matrices. Such matrices can be used to aplly transformations to a point. It contains methods creating such transformation matrices directly, or adding new transformations to the current matrix.

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(content = nil) ⇒ Matrix

Returns a new instance of Matrix.

Parameters:

  • content (Array<Float>, nil) (defaults to: nil)

    Either nothing or the content of each of the 16 cells of the matrix. If nil, the identity matrix is created.


61
62
63
# File 'lib/ray/matrix.rb', line 61

def initialize(content = nil)
  self.content = content if content
end

Class Method Details

.[](*content) ⇒ Ray::Matrix

Returns A new instance of Ray::Matrix.

Parameters:

  • content (Array<Float>)

    Content of each of the 16 cells of the matrix.

Returns:


7
8
9
# File 'lib/ray/matrix.rb', line 7

def [](*content)
  new(content)
end

.identityRay::Matrix

Returns The identity matrix.

Returns:


12
13
14
# File 'lib/ray/matrix.rb', line 12

def identity
  new
end

.look_at(eye, center, up) ⇒ Object

Creates a view matrix, usually for 3D.

Parameters:


36
37
38
# File 'lib/ray/matrix.rb', line 36

def looking_at(eye, center, up)
  new.look_at(eye, center, up)
end

.orthogonal(*args) ⇒ Ray::Matrix

Returns An orthogonal projection matrix.

Returns:


42
43
44
# File 'lib/ray/matrix.rb', line 42

def orthogonal(*args)
  new.orthogonal(*args)
end

.perspective(*args) ⇒ Ray::Matrix

Returns A perspective projection matrix.

Returns:


48
49
50
# File 'lib/ray/matrix.rb', line 48

def perspective(*args)
  new.perspective(*args)
end

.rotation(angle, vector) ⇒ Ray::Matrix

Returns A rotation matrix.

Parameters:

  • vector (Ray::Vector3)

    (see #rotate)

  • angle (Float)

    (see #rotate)

Returns:


31
32
33
# File 'lib/ray/matrix.rb', line 31

def rotation(angle, vector)
  new.rotate(angle, vector)
end

.scale(vector) ⇒ Ray::Matrix

Returns A scaling matrix.

Parameters:

Returns:


24
25
26
# File 'lib/ray/matrix.rb', line 24

def scale(vector)
  new.scale vector
end

.transformation(*args) ⇒ Ray::Matrix

Returns A 2D transformation matrix.

Returns:


54
55
56
# File 'lib/ray/matrix.rb', line 54

def transformation(*args)
  new.set_transformation(*args)
end

.translation(vector) ⇒ Ray::Matrix

Returns A translation matrix.

Parameters:

Returns:


18
19
20
# File 'lib/ray/matrix.rb', line 18

def translation(vector)
  new.translate vector
end

Instance Method Details

#*(other) ⇒ Ray::Matrix

Returns Product between self and another matrix.

Returns:

  • (Ray::Matrix)

    Product between self and another matrix

See Also:


78
79
80
# File 'lib/ray/matrix.rb', line 78

def *(other)
  dup.multiply_by! other
end

#==(other) ⇒ Object Also known as: eql?


82
83
84
# File 'lib/ray/matrix.rb', line 82

def ==(other)
  other.is_a?(Matrix) && content == other.content
end

#[](x, y) ⇒ Float

Returns Content of the cell at the given position.

Parameters:

  • x (Integer)

    X position of the cell

  • y (Integer)

    Y position of the cell

Returns:

  • (Float)

    Content of the cell at the given position

Raises:

  • (ArgumentError)

    If at least one of x and y is not included in the 0…4 range


48
49
50
51
52
53
54
55
# File 'ext/matrix.c', line 48

static
VALUE ray_matrix_get(VALUE self, VALUE rb_x, VALUE rb_y) {
  int x = NUM2INT(rb_x), y = NUM2INT(rb_y);
  ray_matrix_assert_valid_pos(x, y);

  say_matrix *matrix = ray_rb2matrix(self);
  return rb_float_new(say_matrix_get(matrix, x, y));
}

#[]=(x, y, val) ⇒ void

This method returns an undefined value.

Sets a new value to one of the cell of the matrix

Parameters:

  • x (Integer)

    X position of the cell

  • y (Integer)

    Y position of the cell

  • val (Float)

    New content for the cell

Raises:

  • (ArgumentError)

    If at least one of x and y is not included in the 0…4 range


72
73
74
75
76
77
78
79
80
81
82
83
# File 'ext/matrix.c', line 72

static
VALUE ray_matrix_set(VALUE self, VALUE rb_x, VALUE rb_y, VALUE val) {
  rb_check_frozen(self);

  int x = NUM2INT(rb_x), y = NUM2INT(rb_y);
  ray_matrix_assert_valid_pos(x, y);

  say_matrix *matrix = ray_rb2matrix(self);
  say_matrix_set(matrix, x, y, NUM2DBL(val));

  return val;
}

#cofactor(x, y) ⇒ Float

Returns The cofactor for that element.

Parameters:

  • x (Integer)

    X position of the element

  • y (Integer)

    Y position of the element

Returns:

  • (Float)

    The cofactor for that element


184
185
186
187
188
189
# File 'ext/matrix.c', line 184

static
VALUE ray_matrix_cofactor(VALUE self, VALUE x, VALUE y) {
  return rb_float_new(say_matrix_cofactor(ray_rb2matrix(self),
                                          NUM2INT(x),
                                          NUM2INT(y)));
}

#comatrixRay::Matrix

Returns the comatrix of the current one.

Returns:


194
195
196
197
198
# File 'ext/matrix.c', line 194

static
VALUE ray_matrix_comatrix(VALUE self) {
  say_matrix *comatrix = say_matrix_comatrix(ray_rb2matrix(self));
  return Data_Wrap_Struct(rb_class_of(self), NULL, say_matrix_free, comatrix);
}

#contentArray<Float>

Returns The 16 cells of the matrix.

Examples:

p Matrix.new.content
# result:
#   [1, 0, 0, 0,
#    0, 1, 0, 0,
#    0, 0, 1, 0,
#    0, 0, 0, 1]

Returns:

  • (Array<Float>)

    The 16 cells of the matrix.


96
97
98
99
100
101
102
103
104
105
# File 'ext/matrix.c', line 96

static
VALUE ray_matrix_content(VALUE self) {
  float *content = say_matrix_get_content(ray_rb2matrix(self));

  VALUE result = rb_ary_new();
  for (int i = 0; i < 16; i++)
    rb_ary_push(result, rb_float_new(content[i]));

  return result;
}

#content=(val) ⇒ void

This method returns an undefined value.

Changes the whole content of the matrix.

Parameters:

  • val (Array<Float>)

    The 16 cells of the matrix


115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
# File 'ext/matrix.c', line 115

static
VALUE ray_matrix_set_content(VALUE self, VALUE rb_content) {
  rb_check_frozen(self);

  if (RARRAY_LEN(rb_content) != 16) {
    rb_raise(rb_eArgError, "size of array is %ld, 16 expected",
             RARRAY_LEN(rb_content));
  }

  say_matrix *matrix = ray_rb2matrix(self);

  float content[16];
  for (int i = 0; i < 16; i++)
    content[i] = NUM2DBL(RAY_ARRAY_AT(rb_content, i));

  say_matrix_set_content(matrix, content);

  return rb_content;
}

#hashObject


88
89
90
# File 'lib/ray/matrix.rb', line 88

def hash
  content.hash
end

#initialize_copy(other) ⇒ Object


65
66
67
# File 'lib/ray/matrix.rb', line 65

def initialize_copy(other)
  self.content = other.content
end

#inverseRay::Matrix

Returns The inverse matrix of the current one.

Returns:

  • (Ray::Matrix)

    The inverse matrix of the current one.


204
205
206
207
208
# File 'ext/matrix.c', line 204

static
VALUE ray_matrix_inverse(VALUE self) {
  say_matrix *inverse = say_matrix_inverse(ray_rb2matrix(self));
  return Data_Wrap_Struct(rb_class_of(self), NULL, say_matrix_free, inverse);
}

#look_at(eye, center, up) ⇒ Object

Creates a view matrix, usually for 3D.

Parameters:


272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
# File 'ext/matrix.c', line 272

static
VALUE ray_matrix_look_at(VALUE self, VALUE eye, VALUE center, VALUE up) {
  say_matrix *mat = ray_rb2matrix(self);

  say_vector3 c_eye    = ray_convert_to_vector3(eye);
  say_vector3 c_center = ray_convert_to_vector3(center);
  say_vector3 c_up     = ray_convert_to_vector3(up);

  say_matrix_look_at(mat,
                     c_eye.x, c_eye.y, c_eye.z,
                     c_center.x, c_center.y, c_center.z,
                     c_up.x, c_up.y, c_up.z);

  return self;
}

#multiply_by!(other) ⇒ self

Multiplies this matrix by another one and stores the result in self.

Parameters:

  • other (Matrix)

    A matrix to multiply self by.

Returns:

  • (self)

See Also:


155
156
157
158
159
160
# File 'ext/matrix.c', line 155

static
VALUE ray_matrix_multiply_by(VALUE self, VALUE other) {
  rb_check_frozen(self);
  say_matrix_multiply_by(ray_rb2matrix(self), ray_rb2matrix(other));
  return self;
}

#orthogonal(left, right, bottom, top, near, far) ⇒ Object

Setup an orthogonal projection.

Parameters:

  • left (Float)

    X position of the left corners

  • right (Float)

    X position of the right corners

  • bottom (Float)

    Y position of the bottom corners

  • top (Float)

    Y position of the top corners

  • near (Float)

    Nearest z value that can be seen

  • far (Float)

    Farthest z valaue that can be seen


301
302
303
304
305
306
307
308
309
310
311
312
313
314
# File 'ext/matrix.c', line 301

static
VALUE ray_matrix_orthogonal(VALUE self,
                            VALUE left, VALUE right,
                            VALUE bottom, VALUE top,
                            VALUE z_near, VALUE z_far) {
  rb_check_frozen(self);

  say_matrix_set_ortho(ray_rb2matrix(self),
                       NUM2DBL(left), NUM2DBL(right),
                       NUM2DBL(bottom), NUM2DBL(top),
                       NUM2DBL(z_near), NUM2DBL(z_far));

  return self;
}

#perspective(fovy, aspect, near, far) ⇒ Object

Setup a perspective projection.

Parameters:

  • fovy (Float)

    Field of view in degrees, in the y direction.

  • aspect (Float)

    Width divided by height

  • near (Float)

    Distance from the viewer to the nearest point

  • far (Float)

    Distance from the viewer to the farthest point


326
327
328
329
330
331
332
333
334
335
336
337
# File 'ext/matrix.c', line 326

static
VALUE ray_matrix_perspective(VALUE self,
                             VALUE fovy, VALUE aspect,
                             VALUE z_near, VALUE z_far) {
  rb_check_frozen(self);

  say_matrix_set_perspective(ray_rb2matrix(self),
                             NUM2DBL(fovy), NUM2DBL(aspect),
                             NUM2DBL(z_near), NUM2DBL(z_far));

  return self;
}

#pretty_print(q) ⇒ Object


96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
# File 'lib/ray/matrix.rb', line 96

def pretty_print(q)
  content = self.content.map { |n| ("%g" % n).to_f }

  columns = Array.new(4) do |x|
    Array.new(4) { |y| ("%g" % self[x, y]).to_f }
  end

  column_length = columns.map { |c| c.map { |n| n.to_s.length }.max }

  q.group(2, '{', '}') do
    q.breakable ''
    content.each_slice(4).with_index do |(x, y, z, w), i|
      q.text '('
      q.pp x
      q.text ', ' + ' ' * (column_length[0] - x.to_s.length)
      q.pp y
      q.text ', ' + ' ' * (column_length[1] - y.to_s.length)
      q.pp z
      q.text ', ' + ' ' * (column_length[2] - z.to_s.length)
      q.pp w
      q.text ')'
      q.breakable '' unless i == 3
    end
  end
end

#resetself

Resets a matrix to identity.

Returns:

  • (self)

139
140
141
142
143
144
# File 'ext/matrix.c', line 139

static
VALUE ray_matrix_reset(VALUE self) {
  rb_check_frozen(self);
  say_matrix_reset(ray_rb2matrix(self));
  return self;
}

#rotate(angle, vector) ⇒ void

This method returns an undefined value.

Rotates the matrix.

Parameters:

  • angle (Float)

    Angle of the rotation in degrees

  • vector (Ray::Vector3)

    Vector followed by the rotation


253
254
255
256
257
258
259
260
261
262
# File 'ext/matrix.c', line 253

static
VALUE ray_matrix_rotate(VALUE self, VALUE angle, VALUE rb_vector) {
  rb_check_frozen(self);

  say_vector3 vector = ray_convert_to_vector3(rb_vector);
  say_matrix_rotate(ray_rb2matrix(self), NUM2DBL(angle),
                    vector.x, vector.y, vector.z);

  return self;
}

#scale(vector) ⇒ void

This method returns an undefined value.

Scales the matrix. Sizes are multiplied by the vector.

Parameters:


234
235
236
237
238
239
240
241
242
# File 'ext/matrix.c', line 234

static
VALUE ray_matrix_scale(VALUE self, VALUE rb_vector) {
  rb_check_frozen(self);

  say_vector3 vector = ray_convert_to_vector3(rb_vector);
  say_matrix_scale_by(ray_rb2matrix(self), vector.x, vector.y, vector.z);

  return self;
}

#set_transformation(origin, pos, z, scale, angle) ⇒ Object

Resets the matrix content to a 2D transformation matrix

Parameters:

  • origin (Vector2)

    Origin of all the transformations

  • pos (Vector2)

    Position of the object

  • z (Float)

    Z ordering

  • scale (Vector2)

    Scaling factor

  • angle (Float)

    Rotation


349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
# File 'ext/matrix.c', line 349

static
VALUE ray_matrix_set_transformation(VALUE self,
                                    VALUE origin,
                                    VALUE pos, VALUE z,
                                    VALUE scale,
                                    VALUE angle) {
  rb_check_frozen(self);

  say_matrix_set_transformation(ray_rb2matrix(self),
                                ray_convert_to_vector2(origin),
                                ray_convert_to_vector2(pos),
                                NUM2DBL(z),
                                ray_convert_to_vector2(scale),
                                NUM2DBL(angle));

  return self;
}

#to_sObject


92
93
94
# File 'lib/ray/matrix.rb', line 92

def to_s
  "#<#{self.class} #{content.join(', ')}>"
end

#transform(vector) ⇒ Ray::Vector3

Applies this transformation matrix to a vector.

Parameters:

  • Vector (#to_vector3)

    to apply the transformations to

Returns:

  • (Ray::Vector3)

    A new vector to which the transformations have been applied.


170
171
172
173
174
175
176
# File 'ext/matrix.c', line 170

static
VALUE ray_matrix_transform(VALUE self, VALUE vector) {
  say_vector3 ret = say_matrix_transform(ray_rb2matrix(self),
                                         ray_convert_to_vector3(vector));

  return ray_vector3_to_rb(ret);
}

#translate(vector) ⇒ void

This method returns an undefined value.

Applies a translation to the matrix.

Parameters:


217
218
219
220
221
222
223
224
225
# File 'ext/matrix.c', line 217

static
VALUE ray_matrix_translate(VALUE self, VALUE rb_vector) {
  rb_check_frozen(self);

  say_vector3 vector = ray_convert_to_vector3(rb_vector);
  say_matrix_translate_by(ray_rb2matrix(self), vector.x, vector.y, vector.z);

  return self;
}

#untransform(point) ⇒ Ray::Vector3

Applies opposite transformations to a point.

Parameters:

Returns:

  • (Ray::Vector3)

    The point after applying opposite transforamations


72
73
74
# File 'lib/ray/matrix.rb', line 72

def untransform(point)
  inverse.transform point
end