Class: CGLM::Mat4

Inherits:
MatrixType show all
Defined in:
lib/cglm/mat4.rb,
ext/cglm/rb_cglm.c

Instance Attribute Summary

Attributes inherited from Base

#addr

Class Method Summary collapse

Instance Method Summary collapse

Methods inherited from MatrixType

#to_flat_a

Methods inherited from Base

#copy_to, #dup, #initialize_dup

Constructor Details

#initialize(initial_values = nil, **args) ⇒ Mat4

Returns a new instance of Mat4.



3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
# File 'lib/cglm/mat4.rb', line 3

def initialize(initial_values = nil, **args)
  super(**args)
  case initial_values
  when Mat3
    initial_values.to_a.each_with_index { |row, i| self[i] = row }
  when Mat4
    addr[0, self.class.size] = initial_values.addr[0, self.class.size]
  when Array
    initial_values.each_with_index do |row, i|
      self[i] = row
    end
  when nil
  else
    raise ArgumentError, 'initial values should be a Mat4, a Mat3 or an array of Array/Vec3/Vec4'
  end
end

Class Method Details

.alignmentObject



219
# File 'ext/cglm/rb_cglm_mat4.c', line 219

VALUE rb_cglm_mat4_alignment_bytes(VALUE klass) { return SIZET2NUM(MAT4_ALIGNMENT); }

.axis_angle_rotate_at(pivot_point, axis, angle) ⇒ new Mat4

Returns:



249
250
251
252
253
254
255
256
257
258
# File 'ext/cglm/rb_cglm_affine.c', line 249

VALUE rb_cglm_rotate_at_new(VALUE klass, VALUE pivot, VALUE axis, VALUE angle) {
  VALUE self = MAT4_NEW(ALLOC_MAT4);
  mat4 *m;
  vec3 *v1, *v2;
  m = &VAL2MAT4(self);
  v1 = &VAL2VEC3(pivot);
  v2 = &VAL2VEC3(axis);
  glm_rotate_atm(*m, *v1, (float) NUM2DBL(angle), *v2);
  return self;
}

.frustum([dest], left: , right: , bottom: , top: , near: , far: ) ⇒ dest | new Mat4

Sets up a perspective projection matrix. dest is a Mat4. If it is omitted, it is created.

  • left is the viewport left
  • right is the viewport right
  • bottom is the viewport bottom
  • top is the viewport top
  • near is the near clipping plane
  • far is the far clipping plane
  • dest is the result matrix

Returns:



317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
# File 'ext/cglm/rb_cglm_cam.c', line 317

VALUE rb_cglm_cam_frustum(int argc, VALUE *argv, VALUE klass) {
  static ID kwargs_ids[6];
  if (!kwargs_ids[0]) {
    kwargs_ids[0] = rb_intern_const("left");
    kwargs_ids[1] = rb_intern_const("right");
    kwargs_ids[2] = rb_intern_const("bottom");
    kwargs_ids[3] = rb_intern_const("top");
    kwargs_ids[4] = rb_intern_const("near");
    kwargs_ids[5] = rb_intern_const("far");
  };
  VALUE dest, kwargs[6], opts;
  rb_scan_args(argc, argv, "01:", &dest, &opts);
  rb_get_kwargs(opts, kwargs_ids, 6, 0, kwargs);
  if (NIL_P(dest)) dest = MAT4_NEW(ALLOC_MAT4);
  glm_frustum(NUM2FLT(kwargs[0]),
              NUM2FLT(kwargs[1]),
              NUM2FLT(kwargs[2]),
              NUM2FLT(kwargs[3]),
              NUM2FLT(kwargs[4]),
              NUM2FLT(kwargs[5]),
              VAL2MAT4(dest));
  return dest;
}

.identity([dest]) ⇒ dest | new Mat4

Sets dest to the identity if provided. If omitted, a new Mat4 is created and set to the identity. dest or the new Mat4 is returned.

Returns:



8
9
10
11
12
13
14
# File 'ext/cglm/rb_cglm_mat4.c', line 8

VALUE rb_cglm_mat4_new_identity(int argc, VALUE *argv, VALUE self) {
  VALUE dest;
  rb_scan_args(argc, argv, "01", &dest);
  if (NIL_P(dest)) dest = MAT4_NEW(ALLOC_MAT4);
  glm_mat4_identity(VAL2MAT4(dest));
  return dest;
}

.look(eye, direction[, up, dest]) ⇒ dest | new Mat4

Convenience wrapper for look_at for if you only have direction and not the target position.

If up is omitted (or nil), it is assumed that you don't care what it is, and one will be computed for you.

Note: The up vector must not be parallel to the line of sight from the eye point to the reference point.

Returns:



130
131
132
133
134
135
136
137
138
139
# File 'ext/cglm/rb_cglm_cam.c', line 130

VALUE rb_cglm_cam_look(int argc, VALUE *argv, VALUE self) {
  VALUE dest, eye, dir, up;
  rb_scan_args(argc, argv, "31", &eye, &dir, &up, &dest);
  if (NIL_P(dest)) dest = MAT4_NEW(ALLOC_MAT4);
  if (NIL_P(up))
    glm_look_anyup(VAL2VEC3(eye), VAL2VEC3(dir), VAL2MAT4(dest));
  else
    glm_look(VAL2VEC3(eye), VAL2VEC3(dir), VAL2VEC3(up), VAL2MAT4(dest));
  return dest;
}

.look_at(eye, target_position, up[, dest]) ⇒ dest | new Mat4

Sets up a view matrix.

NOTE: The up vector must not be parallel to the line of sight from the eye point to the reference point.

Returns:



148
149
150
151
152
153
154
# File 'ext/cglm/rb_cglm_cam.c', line 148

VALUE rb_cglm_cam_look_at(int argc, VALUE *argv, VALUE self) {
  VALUE dest, eye, center, up;
  rb_scan_args(argc, argv, "31", &eye, &center, &up, &dest);
  if (NIL_P(dest)) dest = MAT4_NEW(ALLOC_MAT4);
  glm_lookat(VAL2VEC3(eye), VAL2VEC3(center), VAL2VEC3(up), VAL2MAT4(dest));
  return dest;
}

.ortho([dest], left: , right: , bottom: , top: , near: , far: ) ⇒ dest | new Mat4

Sets up an orthographic projection matrix. dest is a Mat4. If it is omitted, it is created.

  • left is the viewport left
  • right is the viewport right
  • bottom is the viewport bottom
  • top is the viewport top
  • near is the near clipping plane
  • far is the far clipping plane
  • dest is the result matrix

Returns:



279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
# File 'ext/cglm/rb_cglm_cam.c', line 279

VALUE rb_cglm_cam_ortho(int argc, VALUE *argv, VALUE klass) {
  static ID kwargs_ids[6];
  if (!kwargs_ids[0]) {
    kwargs_ids[0] = rb_intern_const("left");
    kwargs_ids[1] = rb_intern_const("right");
    kwargs_ids[2] = rb_intern_const("bottom");
    kwargs_ids[3] = rb_intern_const("top");
    kwargs_ids[4] = rb_intern_const("near");
    kwargs_ids[5] = rb_intern_const("far");
  };
  VALUE dest, kwargs[6], opts;
  rb_scan_args(argc, argv, "01:", &dest, &opts);
  rb_get_kwargs(opts, kwargs_ids, 6, 0, kwargs);
  if (NIL_P(dest)) dest = MAT4_NEW(ALLOC_MAT4);
  glm_ortho(NUM2FLT(kwargs[0]),
            NUM2FLT(kwargs[1]),
            NUM2FLT(kwargs[2]),
            NUM2FLT(kwargs[3]),
            NUM2FLT(kwargs[4]),
            NUM2FLT(kwargs[5]),
            VAL2MAT4(dest));
  return dest;
}

.ortho_aabb(aabb[, dest], padding: 0, padding_z: 0) ⇒ dest | new Mat4

Sets up an orthographic projection matrix using the given bounding box.

If dest is omitted, a new Mat4 will be allocated and returned. Otherwise, the result will be placed into dest and returned.

If padding is present and padding_z is omitted, then the entire projection will have the same padding (including near/far values). If both are present, the near/far values will use padding_z while all other values will be padded with padding.

Returns:



231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
# File 'ext/cglm/rb_cglm_cam.c', line 231

VALUE rb_cglm_cam_ortho_aabb(int argc, VALUE *argv, VALUE self) {
  VALUE boxv, dest, opts;
  static ID kwargs_ids[2];
  if (!kwargs_ids[0]) {
    kwargs_ids[0] = rb_intern_const("padding");
    kwargs_ids[1] = rb_intern_const("padding_z");
  }
  VALUE kwargs[2];
  rb_scan_args(argc, argv, "11:", &boxv, &dest, &opts);
  rb_get_kwargs(opts, kwargs_ids, 0, 2, kwargs);
  aabb box = VAL2AABB(boxv);
  if (NIL_P(dest)) dest = MAT4_NEW(ALLOC_MAT4);
  if (RB_TYPE_P(kwargs[0], T_UNDEF)) {
    if (RB_TYPE_P(kwargs[1], T_UNDEF)) {
      glm_ortho_aabb(box.corners, VAL2MAT4(dest));
    } else {
      glm_ortho_aabb_pz(box.corners, NUM2FLT(kwargs[1]), VAL2MAT4(dest));
    }
  }
  else{
    if (RB_TYPE_P(kwargs[1], T_UNDEF)) {
      glm_ortho_aabb_p(box.corners, NUM2FLT(kwargs[0]), VAL2MAT4(dest));
    } else {
      float padding  = NUM2FLT(kwargs[0]);
      float paddingz = NUM2FLT(kwargs[1]);
      glm_ortho(box.corners[0][0] - padding,     box.corners[1][0] + padding,
                box.corners[0][1] - padding,     box.corners[1][1] + padding,
              -(box.corners[1][2] + paddingz), -(box.corners[0][2] - paddingz),
                VAL2MAT4(dest));
    }
  }
  return dest;
}

.ortho_cube(aspect, size[, dest]) ⇒ dest | new Mat4

Sets up a new cubed orthographic projection matrix (it has the same size in all dimensions).

Returns:



199
200
201
202
203
204
205
# File 'ext/cglm/rb_cglm_cam.c', line 199

VALUE rb_cglm_cam_ortho_cube(int argc, VALUE *argv, VALUE self) {
  VALUE aspect, size, dest;
  rb_scan_args(argc, argv, "21", &aspect, &size, &dest);
  if (NIL_P(dest)) dest = MAT4_NEW(ALLOC_MAT4);
  glm_ortho_default_s(NUM2FLT(aspect), NUM2FLT(size), VAL2MAT4(dest));
  return dest;
}

.ortho_unit(aspect[, dest]) ⇒ dest | new Mat4

Sets up a unit orthographic projection matrix.

Returns:



211
212
213
214
215
216
217
# File 'ext/cglm/rb_cglm_cam.c', line 211

VALUE rb_cglm_cam_ortho_unit(int argc, VALUE *argv, VALUE self) {
  VALUE aspect, dest;
  rb_scan_args(argc, argv, "11", &aspect, &dest);
  if (NIL_P(dest)) dest = MAT4_NEW(ALLOC_MAT4);
  glm_ortho_default(NUM2FLT(aspect), VAL2MAT4(dest));
  return dest;
}

.perspective([dest], fovy: PI/4, aspect: , near: 0.1, far: 100.0) ⇒ dest | new Mat4

Sets up a perspective projection matrix.

Returns:



171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
# File 'ext/cglm/rb_cglm_cam.c', line 171

VALUE rb_cglm_cam_perspective(int argc, VALUE *argv, VALUE self) {
  static ID kwargs_ids[4];
  if (!kwargs_ids[0]) {
    kwargs_ids[0] = rb_intern_const("aspect");
    kwargs_ids[1] = rb_intern_const("fovy");
    kwargs_ids[2] = rb_intern_const("near");
    kwargs_ids[3] = rb_intern_const("far");
  };
  VALUE dest, kwargs[4], opts;
  rb_scan_args(argc, argv, "01:", &dest, &opts);
  rb_get_kwargs(opts, kwargs_ids, 1, 3, kwargs);
  if (NIL_P(dest)) dest = MAT4_NEW(ALLOC_MAT4);
  if (RB_TYPE_P(kwargs[1], T_UNDEF)) kwargs[1] = DBL2NUM(GLM_PI_4f);
  if (RB_TYPE_P(kwargs[2], T_UNDEF)) kwargs[2] = DBL2NUM(0.1);
  if (RB_TYPE_P(kwargs[3], T_UNDEF)) kwargs[3] = DBL2NUM(100.0);
  glm_perspective(NUM2FLT(kwargs[1]),
                  NUM2FLT(kwargs[0]),
                  NUM2FLT(kwargs[2]),
                  NUM2FLT(kwargs[3]),
                  VAL2MAT4(dest));
  return dest;
}

.quat_rotate_at(quat, pivot_point[, dest]) ⇒ dest | new Mat4

Creates a new transformation matrix using the quaternion at the pivot point. Places the result into dest, or creates a new Mat4 if dest is omitted. Returns dest.

Returns:



22
23
24
25
26
27
28
# File 'ext/cglm/rb_cglm_mat4.c', line 22

VALUE rb_cglm_mat4_new_rotate_at(int argc, VALUE *argv, VALUE self) {
  VALUE q, pivot, dest;
  rb_scan_args(argc, argv, "21", &q, &pivot, &dest);
  if (NIL_P(dest)) dest = MAT4_NEW(ALLOC_MAT4);
  glm_quat_rotate_atm(VAL2MAT4(dest), VAL2QUAT(q), VAL2VEC3(pivot));
  return dest;
}

.random([dest]) ⇒ dest | new Mat4

Fills dest or a new Mat4 with a random translation and rotation, and returns it.

Returns:



255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
# File 'ext/cglm/rb_cglm_mat4.c', line 255

VALUE rb_cglm_mat4_new_random(int argc, VALUE *argv, VALUE self) {
  VALUE dest;
  rb_scan_args(argc, argv, "01", &dest);
  if (NIL_P(dest)) dest = MAT4_NEW(ALLOC_MAT4);

  glm_mat4_copy(GLM_MAT4_IDENTITY, VAL2MAT4(dest));
  
  /* random position */
  VAL2MAT4(dest)[3][0] = drand48();
  VAL2MAT4(dest)[3][1] = drand48();
  VAL2MAT4(dest)[3][2] = drand48();
  
  /* random rotatation around random axis with random angle */
  glm_rotate(VAL2MAT4(dest), drand48(), (vec3){drand48(), drand48(), drand48()});
  
  /* random scale */
  /* glm_scale(dest, (vec3){drand48(), drand48(), drand48()}); */

  return dest;
}

.random([dest]) ⇒ dest | new Mat4

Fills dest or a new Mat4 with a random translation and rotation, and returns it.

Returns:



255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
# File 'ext/cglm/rb_cglm_mat4.c', line 255

VALUE rb_cglm_mat4_new_random(int argc, VALUE *argv, VALUE self) {
  VALUE dest;
  rb_scan_args(argc, argv, "01", &dest);
  if (NIL_P(dest)) dest = MAT4_NEW(ALLOC_MAT4);

  glm_mat4_copy(GLM_MAT4_IDENTITY, VAL2MAT4(dest));
  
  /* random position */
  VAL2MAT4(dest)[3][0] = drand48();
  VAL2MAT4(dest)[3][1] = drand48();
  VAL2MAT4(dest)[3][2] = drand48();
  
  /* random rotatation around random axis with random angle */
  glm_rotate(VAL2MAT4(dest), drand48(), (vec3){drand48(), drand48(), drand48()});
  
  /* random scale */
  /* glm_scale(dest, (vec3){drand48(), drand48(), drand48()}); */

  return dest;
}

.rotate(axis, angle[, dest]) ⇒ dest | new Mat4

Returns:



153
154
155
156
157
158
159
# File 'ext/cglm/rb_cglm_affine.c', line 153

VALUE rb_cglm_rotate_new(int argc, VALUE *argv, VALUE klass) {
  VALUE axis, angle, dest;
  rb_scan_args(argc, argv, "21", &axis, &angle, &dest);
  if (NIL_P(dest)) dest = MAT4_NEW(ALLOC_MAT4);
  glm_rotate_make(VAL2MAT4(dest), (float) NUM2DBL(angle), VAL2VEC3(axis));
  return dest;
}

.scale(vec3) ⇒ new Mat4

Returns:



142
143
144
145
146
147
148
# File 'ext/cglm/rb_cglm_affine.c', line 142

VALUE rb_cglm_scale_new(int argc, VALUE *argv, VALUE klass) {
  VALUE vec_v, dest;
  rb_scan_args(argc, argv, "11", &vec_v, &dest);
  if (NIL_P(dest)) dest = MAT4_NEW(ALLOC_MAT4);
  glm_scale_make(VAL2MAT4(dest), VAL2VEC3(vec_v));
  return dest;
}

.sizeObject



217
# File 'ext/cglm/rb_cglm_mat4.c', line 217

VALUE rb_cglm_mat4_size_bytes(VALUE klass) { return SIZET2NUM(mat4_size()); }

.translate(vec3) ⇒ new Mat4

Returns:



133
134
135
136
137
138
139
# File 'ext/cglm/rb_cglm_affine.c', line 133

VALUE rb_cglm_translate_new(int argc, VALUE *argv, VALUE klass) {
  VALUE vec_v, dest;
  rb_scan_args(argc, argv, "11", &vec_v, &dest);
  if (NIL_P(dest)) dest = MAT4_NEW(ALLOC_MAT4);
  glm_translate_make(VAL2MAT4(dest), VAL2VEC3(vec_v));
  return dest;
}

Instance Method Details

#*(other) ⇒ Object

Performs multiplication with other and returns the result.

  • other is a Mat3 or Vec3.


35
36
37
38
39
40
41
42
43
44
# File 'lib/cglm/mat4.rb', line 35

def *(other)
  case other
  when Mat4    then mul_mat4(other)
  when Mat3    then mul_mat3(other)
  when Vec3    then mul_vec3(other)
  when Vec4    then mul_vec4(other)
  when Numeric then mul_scalar(other)
  else raise ArgumentError, "Don't know how to multiply Mat4 with object: #{other.inspect}"
  end
end

#==(other) ⇒ Object



221
222
223
224
# File 'ext/cglm/rb_cglm_mat4.c', line 221

VALUE rb_cglm_mat4_equal(VALUE self, VALUE other) {
  if (memcmp(&VAL2MAT4(self), &VAL2MAT4(other), sizeof(mat4))) return Qfalse;
  return Qtrue;
}

#[](index) ⇒ Object



30
31
32
33
34
# File 'ext/cglm/rb_cglm_mat4.c', line 30

VALUE rb_cglm_mat4_aref(VALUE self, VALUE index) {
  CHECK_RANGE(index, 0, 3);
  float *addr = (float *) VAL2MAT4(self);
  return VEC4_NEW(addr + (NUM2INT(index) * 4));
}

#[]=(index, val) ⇒ Object



36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
# File 'ext/cglm/rb_cglm_mat4.c', line 36

VALUE rb_cglm_mat4_aset(VALUE self, VALUE index, VALUE val) {
  CHECK_RANGE(index, 0, 3);
  if (rb_funcall(val, rb_intern("kind_of?"), 1, rb_cVec4))
    memcpy(&(VAL2MAT4(self)[NUM2INT(index)]), &VAL2VEC4(val), sizeof(vec4));
  else if (rb_funcall(val, rb_intern("kind_of?"), 1, rb_cVec3))
    memcpy(&(VAL2MAT4(self)[NUM2INT(index)]), &VAL2VEC3(val), sizeof(vec3));
  else {
    VALUE row = rb_cglm_mat4_aref(self, index);
    for (int i = 0; i < 4; i++) {
      VALUE v = rb_funcall(val, rb_intern("[]"), 1, INT2NUM(i));
      if (!NIL_P(v)) {
        rb_funcall(row, rb_intern("[]="), 2, INT2NUM(i), v);
      }
    }
  }
  return self;
}

#inv_trself

inverse orthonormal rotation + translation matrix (ridgid-body)

X = | R  T |   X' = | R' -R'T |
    | 0  1 |        | 0     1 |

Returns:

  • (self)


45
46
47
48
49
50
# File 'ext/cglm/rb_cglm_affine.c', line 45

VALUE rb_cglm_affine_inv_tr(VALUE mat) {
  mat4 *m = NULL;
  m = &VAL2MAT4(mat);
  glm_inv_tr(*m);
  return mat;
}

#affine_mul(m[, dest]) ⇒ dest | new Mat4

This is similar to #mul but specialized to affine transform.

Right Matrix format should be:

R  R  R  X
R  R  R  Y
R  R  R  Z
0  0  0  W

This reduces some multiplications. It should be faster than #mul. if you are not sure about matrix format then DON'T use this! use #mul.

  • m is the second affine Mat4 to multiply self against.
  • dest is the out Mat4 to place the result in, and will be allocated if omitted.

Returns:



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

VALUE rb_cglm_affine_mul(int argc, VALUE *argv, VALUE self) {
  VALUE m_v, dest_v;
  rb_scan_args(argc, argv, "11", &m_v, &dest_v);
  if (NIL_P(dest_v)) dest_v = MAT4_NEW(ALLOC_MAT4);
  mat4 *m1 = NULL, *m2 = NULL, *dest = NULL;
  m1 = &VAL2MAT4(self);
  m2 = &VAL2MAT4(m_v);
  dest = &VAL2MAT4(dest_v);
  glm_mul(*m1, *m2, *dest);
  return dest_v;
}

#affine_mul_rot(m[, dest]) ⇒ dest | new Mat4

This is similar to #mul but specialized to affine transform.

Right Matrix format should be:

R  R  R  0
R  R  R  0
R  R  R  0
0  0  0  1

This reduces some multiplications. It should be faster than #mul. if you are not sure about matrix format then DON'T use this! use #mul.

  • m is the second affine Mat4 to multiply self against.
  • dest is the out Mat4 to place the result in, and will be allocated if omitted.

Returns:



23
24
25
26
27
28
29
30
31
32
33
34
# File 'ext/cglm/rb_cglm_affine.c', line 23

VALUE rb_cglm_affine_mul_rot(int argc, VALUE *argv, VALUE self) {
  VALUE m_v, dest_v;
  rb_scan_args(argc, argv, "11", &m_v, &dest_v);
  if (NIL_P(dest_v)) dest_v = MAT4_NEW(ALLOC_MAT4);

  mat4 *m1 = NULL, *m2 = NULL, *dest = NULL;
  m1 = &VAL2MAT4(self);
  m2 = &VAL2MAT4(m_v);
  dest = &VAL2MAT4(dest_v);
  glm_mul_rot(*m1, *m2, *dest);
  return dest_v;
}

#aspectNumeric

Returns:



4
5
6
# File 'ext/cglm/rb_cglm_cam.c', line 4

VALUE rb_cglm_cam_decomp_aspect(VALUE self) {
  return DBL2NUM(glm_persp_aspect(VAL2MAT4(self)));
}

#bottomNumeric

Returns:



79
80
81
82
83
# File 'ext/cglm/rb_cglm_cam.c', line 79

VALUE rb_cglm_cam_decomp_bottom(VALUE self) {
  float top, bottom;
  glm_persp_decomp_y(VAL2MAT4(self), &top, &bottom);
  return DBL2NUM(bottom);
}

#decompose(t, r, s) ⇒ self

Decomposes self into a translation Vec4 t, rotation Mat4 r and scale Vec3 s.

Returns:

  • (self)


296
297
298
299
300
301
302
303
304
305
306
# File 'ext/cglm/rb_cglm_affine.c', line 296

VALUE rb_cglm_decompose(VALUE self, VALUE trans, VALUE rot, VALUE scale) {
  mat4 *m, *r;
  vec3 *s;
  vec4 *t;
  m = &VAL2MAT4(self);
  t = &VAL2VEC4(trans);
  r = &VAL2MAT4(rot);
  s = &VAL2VEC3(scale);
  glm_decompose(*m, *t, *r, *s);
  return self;
}

#decompose_rs(r, s) ⇒ self

Decomposes self into a rotation Mat4 r and scale Vec3 s.

Returns:

  • (self)


281
282
283
284
285
286
287
288
289
# File 'ext/cglm/rb_cglm_affine.c', line 281

VALUE rb_cglm_decompose_rs(VALUE self, VALUE rot, VALUE scale) {
  mat4 *m, *r;
  vec3 *s;
  m = &VAL2MAT4(self);
  r = &VAL2MAT4(rot);
  s = &VAL2VEC3(scale);
  glm_decompose_rs(*m, *r, *s);
  return self;
}

#decompose_scale(vec3) ⇒ Object



261
262
263
264
265
266
267
268
# File 'ext/cglm/rb_cglm_affine.c', line 261

VALUE rb_cglm_decompose_scale(VALUE self, VALUE out) {
  mat4 *m;
  vec3 *v;
  m = &VAL2MAT4(self);
  v = &VAL2VEC3(self);
  glm_decompose_scalev(*m, *v);
  return out;
}

#determinantNumeric Also known as: det

Returns:



143
144
145
# File 'ext/cglm/rb_cglm_mat4.c', line 143

VALUE rb_cglm_mat4_determinant(VALUE self) {
  return DBL2NUM(glm_mat4_det(VAL2MAT4(self)));
}

#=~(b) ⇒ Object Also known as: =~

Returns true if each member of a is very close to, but not necessarily exactly equal to, each corresponding member of b. This is useful in many circumstances because imprecision introduced by floating point calculations can lead to two expressions which are otherwise mathematically equivalent returning false.



234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
# File 'ext/cglm/rb_cglm_mat4.c', line 234

VALUE rb_cglm_mat4_equalish(int argc, VALUE *argv, VALUE self) {
  VALUE other, epsilon;
  float feps = FLT_EPSILON;
  rb_scan_args(argc, argv, "11", &other, &epsilon);
  if (!NIL_P(epsilon)) feps = NUM2FLT(epsilon);
  mat4 *a = &VAL2MAT4(self);
  mat4 *b = &VAL2MAT4(other);
  for (int i = 0; i < 4; i++) {
    for (int j = 0; j < 4; j++) {
      if (fabsf((*a)[i][j] - (*b)[i][j]) > feps)
        return Qfalse;
    }
  }
  return Qtrue;
}

#farNumeric

Returns:



93
94
95
96
97
# File 'ext/cglm/rb_cglm_cam.c', line 93

VALUE rb_cglm_cam_decomp_far(VALUE self) {
  float f;
  glm_persp_decomp_far(VAL2MAT4(self), &f);
  return DBL2NUM(f);
}

#fovyNumeric

Returns:



9
10
11
# File 'ext/cglm/rb_cglm_cam.c', line 9

VALUE rb_cglm_cam_decomp_fovy(VALUE self) {
  return DBL2NUM(glm_persp_fovy(VAL2MAT4(self)));
}

#frustumHash

Decomposes this perspective matrix into a hash containing the 6 frustum values: :near, :far, :top, :bottom, :left, and :right.

Returns:

  • (Hash)


106
107
108
109
110
111
112
113
114
115
116
117
# File 'ext/cglm/rb_cglm_cam.c', line 106

VALUE rb_cglm_cam_frustum_decomp(VALUE self) {
  VALUE hash = rb_hash_new();
  float left, top, right, bottom, n, f;
  glm_persp_decomp(VAL2MAT4(self), &n, &f, &top, &bottom, &left, &right);
  rb_hash_aset(hash, ID2SYM(rb_intern("near")),   DBL2NUM(n));
  rb_hash_aset(hash, ID2SYM(rb_intern("far")),    DBL2NUM(f));
  rb_hash_aset(hash, ID2SYM(rb_intern("left")),   DBL2NUM(left));
  rb_hash_aset(hash, ID2SYM(rb_intern("right")),  DBL2NUM(right));
  rb_hash_aset(hash, ID2SYM(rb_intern("bottom")), DBL2NUM(bottom));
  rb_hash_aset(hash, ID2SYM(rb_intern("top")),    DBL2NUM(top));
  return hash;
}

#inspectObject



24
25
26
27
28
29
30
# File 'lib/cglm/mat4.rb', line 24

def inspect
  vals = to_a
  longest_val_size = vals.flatten.reduce(0) { |a, v| a < v.to_s.size ? v.to_s.size : a }
  vals.map! { |row| row.map { |val| val.to_s.rjust(longest_val_size) }.join(', ') }
  left = "#<#{self.class}@#{addr.to_i.to_s(16)} ["
  left + vals.join(",\n" + (" " * left.size)) + "]>"
end

#invert([dest]) ⇒ dest | new Mat4

Computes the inverse of this matrix and stores it in dest, creating a new Mat4 if dest is omitted. Returns dest.

Returns:



152
153
154
155
156
157
158
# File 'ext/cglm/rb_cglm_mat4.c', line 152

VALUE rb_cglm_mat4_invert(int argc, VALUE *argv, VALUE self) {
  VALUE dest;
  rb_scan_args(argc, argv, "01", &dest);
  if (NIL_P(dest)) dest = MAT4_NEW(ALLOC_MAT4);
  glm_mat4_inv(VAL2MAT4(self), VAL2MAT4(dest));
  return dest;
}

#invert!self

Computes the inverse of this matrix in-place and returns self.

Returns:

  • (self)


164
165
166
167
# File 'ext/cglm/rb_cglm_mat4.c', line 164

VALUE rb_cglm_mat4_invert_self(VALUE self) {
  glm_mat4_inv(VAL2MAT4(self), VAL2MAT4(self));
  return self;
}

#invert_fast([dest]) ⇒ dest | new Mat4

Computes the inverse of this matrix and stores it in dest, creating a new Mat4 if dest is omitted. Returns dest.

  • NOTE: This method uses reciprocal approximation without extra corrections, e.g Newton-Raphson. This should work faster than normal, but will be less precise.

Returns:



178
179
180
181
182
183
184
# File 'ext/cglm/rb_cglm_mat4.c', line 178

VALUE rb_cglm_mat4_invert_fast(int argc, VALUE *argv, VALUE self) {
  VALUE dest;
  rb_scan_args(argc, argv, "01", &dest);
  if (NIL_P(dest)) dest = MAT4_NEW(ALLOC_MAT4);
  glm_mat4_inv_fast(VAL2MAT4(self), VAL2MAT4(dest));
  return dest;
}

#invert_fast!([dest]) ⇒ dest | new Mat4

Computes the inverse of this matrix in-place and returns self.

  • NOTE: This method uses reciprocal approximation without extra corrections, e.g Newton-Raphson. This should work faster than normal, but will be less precise.

Returns:



194
195
196
197
# File 'ext/cglm/rb_cglm_mat4.c', line 194

VALUE rb_cglm_mat4_invert_fast_self(VALUE self) {
  glm_mat4_inv_fast(VAL2MAT4(self), VAL2MAT4(self));
  return self;
}

#leftNumeric

Returns:



58
59
60
61
62
# File 'ext/cglm/rb_cglm_cam.c', line 58

VALUE rb_cglm_cam_decomp_left(VALUE self) {
  float left, right;
  glm_persp_decomp_x(VAL2MAT4(self), &left, &right);
  return DBL2NUM(left);
}

#left_and_rightArray

Returns:

  • (Array)


14
15
16
17
18
# File 'ext/cglm/rb_cglm_cam.c', line 14

VALUE rb_cglm_cam_decomp_left_and_right(VALUE self) {
  float left, right;
  glm_persp_decomp_x(VAL2MAT4(self), &left, &right);
  return rb_ary_new_from_args(2, DBL2NUM(left), DBL2NUM(right));
}

#mul_mat4(*args) ⇒ Object



70
71
72
73
74
75
76
# File 'ext/cglm/rb_cglm_mat4.c', line 70

VALUE rb_cglm_mat4_mul_mat4(int argc, VALUE *argv, VALUE self) {
  VALUE other, dest;
  rb_scan_args(argc, argv, "11", &other, &dest);
  if (NIL_P(dest)) dest = MAT4_NEW(ALLOC_MAT4);
  glm_mat4_mul(VAL2MAT4(self), VAL2MAT4(other), VAL2MAT4(dest));
  return dest;
}

#mul_scalar(scalar[, dest]) ⇒ dest | new Mat3

Multiplies each element in this matrix by the specified scalar amount. Places the result in dest and returns it, creating a new Mat4 if dest is omitted.

Returns:



122
123
124
125
126
127
128
129
# File 'ext/cglm/rb_cglm_mat4.c', line 122

VALUE rb_cglm_mat4_mul_scalar(int argc, VALUE *argv, VALUE self) {
  VALUE scalar, dest;
  rb_scan_args(argc, argv, "11", &scalar, &dest);
  if (NIL_P(dest)) dest = MAT4_NEW(ALLOC_MAT4);
  memcpy(&VAL2MAT4(self), &VAL2MAT4(dest), sizeof(mat4));
  glm_mat4_scale(VAL2MAT4(dest), NUM2FLT(scalar));
  return dest;
}

#mul_scalar!(scalar) ⇒ self

Multiplies each element in this matrix by the specified scalar amount, modifying self in-place and returning it.

Returns:

  • (self)


136
137
138
139
# File 'ext/cglm/rb_cglm_mat4.c', line 136

VALUE rb_cglm_mat4_mul_scalar_self(VALUE self, VALUE scalar) {
  glm_mat4_scale(VAL2MAT4(self), NUM2FLT(scalar));
  return self;
}

#mul_vec3(*args) ⇒ Object



86
87
88
89
90
91
92
93
# File 'ext/cglm/rb_cglm_mat4.c', line 86

VALUE rb_cglm_mat4_mul_vec3(int argc, VALUE *argv, VALUE self) {
  VALUE other, last, dest;
  rb_scan_args(argc, argv, "12", &other, &last, &dest);
  if (NIL_P(last)) last = DBL2NUM(1.0);
  if (NIL_P(dest)) dest = VEC3_NEW(ALLOC_VEC3);
  glm_mat4_mulv3(VAL2MAT4(self), VAL2VEC3(other), NUM2FLT(last), VAL2VEC3(dest));
  return dest;
}

#mul_vec4(*args) ⇒ Object



78
79
80
81
82
83
84
# File 'ext/cglm/rb_cglm_mat4.c', line 78

VALUE rb_cglm_mat4_mul_vec4(int argc, VALUE *argv, VALUE self) {
  VALUE other, dest;
  rb_scan_args(argc, argv, "11", &other, &dest);
  if (NIL_P(dest)) dest = VEC4_NEW(ALLOC_VEC4);
  glm_mat4_mulv(VAL2MAT4(self), VAL2VEC4(other), VAL2VEC4(dest));
  return dest;
}

#nearNumeric

Returns:



86
87
88
89
90
# File 'ext/cglm/rb_cglm_cam.c', line 86

VALUE rb_cglm_cam_decomp_near(VALUE self) {
  float n;
  glm_persp_decomp_near(VAL2MAT4(self), &n);
  return DBL2NUM(n);
}

#near_and_farArray

Returns:

  • (Array)


51
52
53
54
55
# File 'ext/cglm/rb_cglm_cam.c', line 51

VALUE rb_cglm_cam_decomp_near_and_far(VALUE self) {
  float n, f;
  glm_persp_decomp_z(VAL2MAT4(self), &n, &f);
  return rb_ary_new_from_args(2, DBL2NUM(n), DBL2NUM(f));
}

#perspective_resize!(aspect) ⇒ self

Resizes this perspective matrix by the given aspect ratio (width / height). This makes it very easy to resize the projective matrix when the window or viewport is changed.

Returns:

  • (self)


162
163
164
165
# File 'ext/cglm/rb_cglm_cam.c', line 162

VALUE rb_cglm_cam_perspective_resize_self(VALUE self, VALUE aspect) {
  glm_perspective_resize(NUM2FLT(aspect), VAL2MAT4(self));
  return self;
}

#project(pos, viewport[, dest]) ⇒ dest | new Vec3

Maps the given object-space coordinates into window coordinates using self as the projection matrix.

  • pos is a Vec3 specifying the object-space coordinates.

  • viewport is a Vec4 specifying the dimensions of the viewport in [x, y, width, height] format.

  • dest is the Vec3 to place the results into, and will be created if omitted.

Returns:



87
88
89
90
91
92
93
# File 'ext/cglm/rb_cglm_project.c', line 87

VALUE rb_cglm_project_project(int argc, VALUE *argv, VALUE self) {
  VALUE pos, viewport, dest;
  rb_scan_args(argc, argv, "21", &pos, &viewport, &dest);
  if (NIL_P(dest)) dest = VEC3_NEW(ALLOC_VEC3);
  glm_project(VAL2VEC3(pos), VAL2MAT4(self), VAL2VEC4(viewport), VAL2VEC3(dest));
  return dest;
}

#rightNumeric

Returns:



65
66
67
68
69
# File 'ext/cglm/rb_cglm_cam.c', line 65

VALUE rb_cglm_cam_decomp_right(VALUE self) {
  float left, right;
  glm_persp_decomp_x(VAL2MAT4(self), &left, &right);
  return DBL2NUM(right);
}

#rotate!(axis, angle) ⇒ self

Returns:

  • (self)


228
229
230
231
232
233
234
235
# File 'ext/cglm/rb_cglm_affine.c', line 228

VALUE rb_cglm_rotate_self(VALUE self, VALUE axis, VALUE angle) {
  mat4 *mat;
  vec3 *vec;
  mat = &VAL2MAT4(self);
  vec = &VAL2VEC3(axis);
  glm_rotate(*mat, (float) NUM2DBL(angle), *vec);
  return self;
}

#rotate_at!(pivot_point, axis, angle) ⇒ self

Returns:

  • (self)


238
239
240
241
242
243
244
245
246
# File 'ext/cglm/rb_cglm_affine.c', line 238

VALUE rb_cglm_rotate_self_at(VALUE self, VALUE pivot, VALUE axis, VALUE angle) {
  mat4 *m;
  vec3 *v1, *v2;
  m = &VAL2MAT4(self);
  v1 = &VAL2VEC3(pivot);
  v2 = &VAL2VEC3(axis);
  glm_rotate_at(*m, *v1, (float) NUM2DBL(angle), *v2);
  return self;
}

#rotate_x(float[, dest]) ⇒ dest | new Mat4

Returns:



192
193
194
195
196
197
198
199
200
201
# File 'ext/cglm/rb_cglm_affine.c', line 192

VALUE rb_cglm_rotate_x(int argc, VALUE *argv, VALUE self) {
  VALUE angle, dest;
  rb_scan_args(argc, argv, "11", &angle, &dest);
  if (NIL_P(dest)) dest = MAT4_NEW(ALLOC_MAT4);
  mat4 *m1, *m2;
  m1 = &VAL2MAT4(self);
  m2 = &VAL2MAT4(dest);
  glm_rotate_x(*m1, (float) NUM2DBL(angle), *m2);
  return dest;
}

#rotate_y(float[, dest]) ⇒ dest | new Mat4

Returns:



204
205
206
207
208
209
210
211
212
213
# File 'ext/cglm/rb_cglm_affine.c', line 204

VALUE rb_cglm_rotate_y(int argc, VALUE *argv, VALUE self) {
  VALUE angle, dest;
  rb_scan_args(argc, argv, "11", &angle, &dest);
  if (NIL_P(dest)) dest = MAT4_NEW(ALLOC_MAT4);
  mat4 *m1, *m2;
  m1 = &VAL2MAT4(self);
  m2 = &VAL2MAT4(dest);
  glm_rotate_y(*m1, (float) NUM2DBL(angle), *m2);
  return dest;
}

#rotate_z(float[, dest]) ⇒ dest | new Mat4

Returns:



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

VALUE rb_cglm_rotate_z(int argc, VALUE *argv, VALUE self) {
  VALUE angle, dest;
  rb_scan_args(argc, argv, "11", &angle, &dest);
  if (NIL_P(dest)) dest = MAT4_NEW(ALLOC_MAT4);
  mat4 *m1, *m2;
  m1 = &VAL2MAT4(self);
  m2 = &VAL2MAT4(dest);
  glm_rotate_z(*m1, (float) NUM2DBL(angle), *m2);
  return dest;
}

#scale(vec3|float[, dest]) ⇒ dest | new Mat4

Returns:



162
163
164
165
166
167
168
169
170
171
172
173
174
175
# File 'ext/cglm/rb_cglm_affine.c', line 162

VALUE rb_cglm_scale(int argc, VALUE *argv, VALUE self) {
  VALUE factor, dest;
  rb_scan_args(argc, argv, "11", &factor, &dest);
  if (NIL_P(dest)) dest = MAT4_NEW(ALLOC_MAT4);

  if (RB_FLOAT_TYPE_P(factor) || RB_INTEGER_TYPE_P(factor)) {
    memcpy(&VAL2MAT4(dest), &VAL2MAT4(self), sizeof(mat4));
    glm_scale_uni(VAL2MAT4(dest), (float) NUM2DBL(factor));
  } else {
    glm_scale_to(VAL2MAT4(self), VAL2VEC3(factor), VAL2MAT4(dest));
  }

  return dest;
}

#scale!(vec3|float) ⇒ self

Returns:

  • (self)


178
179
180
181
182
183
184
185
186
187
188
189
# File 'ext/cglm/rb_cglm_affine.c', line 178

VALUE rb_cglm_scale_self(VALUE self, VALUE factor) {
  mat4 *m1 = NULL;
  m1 = &VAL2MAT4(self);
  if (RB_FLOAT_TYPE_P(factor) || RB_INTEGER_TYPE_P(factor)) {
    glm_scale_uni(*m1, (float) NUM2DBL(factor));
  } else {
    vec3 *vec = NULL;
    vec = &VAL2VEC3(factor);
    glm_scale(*m1, *vec);
  }
  return self;
}

#sizes([fovy]) ⇒ Hash

Returns the sizes of the near and far planes of this perspective projection. The return value has the following format:

{ near: [width, height], far: [width, height] }

If fovy is omitted, it will be decomposed from the current matrix.

Returns:

  • (Hash)


29
30
31
32
33
34
35
36
37
38
39
40
41
# File 'ext/cglm/rb_cglm_cam.c', line 29

VALUE rb_cglm_cam_sizes(int argc, VALUE *argv, VALUE self) {
  VALUE fovy = Qnil;
  if (argc == 0) fovy = rb_cglm_cam_decomp_fovy(self);
  else fovy = argv[0];
  vec4 out;
  glm_persp_sizes(VAL2MAT4(self), NUM2FLT(fovy), out);
  VALUE n = rb_ary_new_from_args(2, DBL2NUM(out[0]), DBL2NUM(out[1]));
  VALUE f  = rb_ary_new_from_args(2, DBL2NUM(out[2]), DBL2NUM(out[3]));
  VALUE dest = rb_hash_new();
  rb_hash_aset(dest, ID2SYM(rb_intern("near")), n);
  rb_hash_aset(dest, ID2SYM(rb_intern("far")), f);
  return dest;
}

#swap_col!(col1, col2) ⇒ self

Swaps two matrix columns and returns self.

Returns:

  • (self)


203
204
205
206
# File 'ext/cglm/rb_cglm_mat4.c', line 203

VALUE rb_cglm_mat4_swap_col_self(VALUE self, VALUE col1, VALUE col2) {
  glm_mat4_swap_col(VAL2MAT4(self), NUM2INT(col1), NUM2INT(col2));
  return self;
}

#swap_row!(row1, row2) ⇒ self

Swaps two matrix rows and returns self.

Returns:

  • (self)


212
213
214
215
# File 'ext/cglm/rb_cglm_mat4.c', line 212

VALUE rb_cglm_mat4_swap_row_self(VALUE self, VALUE row1, VALUE row2) {
  glm_mat4_swap_row(VAL2MAT4(self), NUM2INT(row1), NUM2INT(row2));
  return self;
}

#to_aObject



20
21
22
# File 'lib/cglm/mat4.rb', line 20

def to_a
  4.times.map { |i| self[i].to_a }
end

#to_mat3(*args) ⇒ Object



54
55
56
57
58
59
60
# File 'ext/cglm/rb_cglm_mat4.c', line 54

VALUE rb_cglm_mat4_to_mat3(int argc, VALUE *argv, VALUE self) {
  VALUE dest;
  if (argc == 0) dest = MAT3_NEW(ALLOC_MAT3);
  else dest = argv[0];
  glm_mat4_pick3(VAL2MAT4(self), VAL2MAT3(dest));
  return dest;
}

#to_quat(*args) ⇒ Object



95
96
97
98
99
100
101
# File 'ext/cglm/rb_cglm_mat4.c', line 95

VALUE rb_cglm_mat4_to_quat(int argc, VALUE *argv, VALUE self) {
  VALUE dest;
  rb_scan_args(argc, argv, "01", &dest);
  if (NIL_P(dest)) dest = QUAT_NEW(ALLOC_QUAT);
  glm_mat4_quat(VAL2MAT4(self), VAL2QUAT(dest));
  return dest;
}

#to_transposed_mat3(*args) ⇒ Object



62
63
64
65
66
67
68
# File 'ext/cglm/rb_cglm_mat4.c', line 62

VALUE rb_cglm_mat4_to_transposed_mat3(int argc, VALUE *argv, VALUE self) {
  VALUE dest;
  if (argc == 0) dest = MAT3_NEW(ALLOC_MAT3);
  dest = argv[0];
  glm_mat4_pick3t(VAL2MAT4(self), VAL2MAT3(dest));
  return dest;
}

#topNumeric

Returns:



72
73
74
75
76
# File 'ext/cglm/rb_cglm_cam.c', line 72

VALUE rb_cglm_cam_decomp_top(VALUE self) {
  float top, bottom;
  glm_persp_decomp_y(VAL2MAT4(self), &top, &bottom);
  return DBL2NUM(top);
}

#top_and_bottomArray

Returns:

  • (Array)


44
45
46
47
48
# File 'ext/cglm/rb_cglm_cam.c', line 44

VALUE rb_cglm_cam_decomp_top_and_bottom(VALUE self) {
  float top, bottom;
  glm_persp_decomp_y(VAL2MAT4(self), &top, &bottom);
  return rb_ary_new_from_args(2, DBL2NUM(top), DBL2NUM(bottom));
}

#translate!(vec3) ⇒ self

Returns:

  • (self)


99
100
101
102
103
104
105
106
# File 'ext/cglm/rb_cglm_affine.c', line 99

VALUE rb_cglm_translate_self(VALUE self, VALUE vec_v) {
  mat4 *m1 = NULL;
  vec3 *vec = NULL;
  m1 = &VAL2MAT4(self);
  vec = &VAL2VEC3(vec_v);
  glm_translate(*m1, *vec);
  return self;
}

#translate(vec3[, dest]) ⇒ dest | new Mat4

Returns:



85
86
87
88
89
90
91
92
93
94
95
96
# File 'ext/cglm/rb_cglm_affine.c', line 85

VALUE rb_cglm_translate(int argc, VALUE *argv, VALUE self) {
  VALUE vec_v, dest_v;
  rb_scan_args(argc, argv, "11", &vec_v, &dest_v);
  if (NIL_P(dest_v)) dest_v = MAT4_NEW(ALLOC_MAT4);
  mat4 *m1 = NULL, *dest = NULL;
  vec3 *vec = NULL;
  m1 = &VAL2MAT4(self);
  vec = &VAL2VEC3(vec_v);
  dest = &VAL2MAT4(dest_v);
  glm_translate_to(*m1, *vec, *dest);
  return dest_v;
}

#translate_x!(float) ⇒ self

Returns:

  • (self)


109
110
111
112
113
114
# File 'ext/cglm/rb_cglm_affine.c', line 109

VALUE rb_cglm_translate_x_self(VALUE self, VALUE flt) {
  mat4 *m1 = NULL;
  m1 = &VAL2MAT4(self);
  glm_translate_x(*m1, (float) NUM2DBL(flt));
  return self;
}

#translate_y!(float) ⇒ Object



117
118
119
120
121
122
# File 'ext/cglm/rb_cglm_affine.c', line 117

VALUE rb_cglm_translate_y_self(VALUE self, VALUE flt) {
  mat4 *m1 = NULL;
  m1 = &VAL2MAT4(self);
  glm_translate_y(*m1, (float) NUM2DBL(flt));
  return self;
}

#translate_z!(float) ⇒ self

Returns:

  • (self)


125
126
127
128
129
130
# File 'ext/cglm/rb_cglm_affine.c', line 125

VALUE rb_cglm_translate_z_self(VALUE self, VALUE flt) {
  mat4 *m1 = NULL;
  m1 = &VAL2MAT4(self);
  glm_translate_z(*m1, (float) NUM2DBL(flt));
  return self;
}

#transpose(*args) ⇒ Object



103
104
105
106
107
108
109
# File 'ext/cglm/rb_cglm_mat4.c', line 103

VALUE rb_cglm_mat4_transpose(int argc, VALUE *argv, VALUE self) {
  VALUE dest;
  rb_scan_args(argc, argv, "01", &dest);
  if (NIL_P(dest)) dest = QUAT_NEW(ALLOC_QUAT);
  glm_mat4_transpose_to(VAL2MAT4(self), VAL2MAT4(dest));
  return dest;
}

#transpose!Object



111
112
113
114
# File 'ext/cglm/rb_cglm_mat4.c', line 111

VALUE rb_cglm_mat4_transpose_self(VALUE self) {
  glm_mat4_transpose(VAL2MAT4(self));
  return self;
}

#uniform_scale?Boolean

Returns:

  • (Boolean)


271
272
273
274
275
# File 'ext/cglm/rb_cglm_affine.c', line 271

VALUE rb_cglm_is_uniform_scale(VALUE self) {
  mat4 *m;
  m = &VAL2MAT4(self);
  return glm_uniscaled(*m) ? Qtrue : Qfalse;
}

#unproject(pos, viewport[, dest]) ⇒ dest | new Vec3

Maps the specified position into the space represented by this matrix, places it in dest or a new Vec3 if dest is omitted, and returns it.

  • NOTE: This method must calculate the inverse of the current matrix. If you already have the inverse handy, you should use #unproject_i for better performance.

  • If self is a projection matrix, then the result will be in view space.

  • If self is a projection * view matrix, then the result will be in world space.

  • If self is an projection * view * model matrix, then the result will be in object space.

  • pos is a Vec3 specifying the coordinates to unproject.

  • viewport is a Vec4 specifying the dimensions of the viewport in [x, y, width, height] format.

  • dest is the Vec3 to place the results into, and will be created if omitted.

Returns:



66
67
68
69
70
71
72
# File 'ext/cglm/rb_cglm_project.c', line 66

VALUE rb_cglm_project_unproject(int argc, VALUE *argv, VALUE self) {
  VALUE pos, viewport, dest;
  rb_scan_args(argc, argv, "21", &pos, &viewport, &dest);
  if (NIL_P(dest)) dest = VEC3_NEW(ALLOC_VEC3);
  glm_unproject(VAL2VEC3(pos), VAL2MAT4(self), VAL2VEC4(viewport), VAL2VEC3(dest));
  return dest;
}

#unproject_i(pos, viewport[, dest]) ⇒ dest | new Vec3

Maps the specified position into the space represented by this matrix, places it in dest or a new Vec3 if dest is omitted, and returns it.

  • NOTE: This method assumes that self represents the inverse of a projection matrix. It's faster than calling #unproject assuming you already have an inverse matrix. If you don't have an inverse, you should just rely on #unproject (to save the overhead of the extra method call), but if you have or need the inverse for other computations, you can use

    unproject_i to save yourself the cost of the inversion.

  • If self is an inverse(projection) matrix, then the result will be in view space.

  • If self is an inverse(projection * view) matrix, then the result will be in world space.

  • If self is an inverse(projection * view * model) matrix, then the result will be in object space.

  • pos is a Vec3 specifying the coordinates to unproject.

  • viewport is a Vec4 specifying the dimensions of the viewport in [x, y, width, height] format.

  • dest is the Vec3 to place the results into, and will be created if omitted.

Returns:



32
33
34
35
36
37
38
# File 'ext/cglm/rb_cglm_project.c', line 32

VALUE rb_cglm_project_unproject_i(int argc, VALUE *argv, VALUE self) {
  VALUE pos, viewport, dest;
  rb_scan_args(argc, argv, "21", &pos, &viewport, &dest);
  if (NIL_P(dest)) dest = VEC3_NEW(ALLOC_VEC3);
  glm_unprojecti(VAL2VEC3(pos), VAL2MAT4(self), VAL2VEC4(viewport), VAL2VEC3(dest));
  return dest;
}