cglm 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +16 -0
- data/.travis.yml +7 -0
- data/.yardopts +2 -0
- data/Gemfile +6 -0
- data/Gemfile.lock +39 -0
- data/LICENSE.txt +21 -0
- data/README.md +91 -0
- data/Rakefile +22 -0
- data/bin/console +14 -0
- data/bin/setup +8 -0
- data/cglm.gemspec +46 -0
- data/ext/cglm/extconf.rb +50 -0
- data/ext/cglm/rb_cglm.c +79 -0
- data/ext/cglm/rb_cglm.h +169 -0
- data/ext/cglm/rb_cglm_aabb.c +271 -0
- data/ext/cglm/rb_cglm_affine.c +325 -0
- data/ext/cglm/rb_cglm_cam.c +365 -0
- data/ext/cglm/rb_cglm_color.c +23 -0
- data/ext/cglm/rb_cglm_ease.c +160 -0
- data/ext/cglm/rb_cglm_euler.c +141 -0
- data/ext/cglm/rb_cglm_frustum.c +306 -0
- data/ext/cglm/rb_cglm_mat3.c +252 -0
- data/ext/cglm/rb_cglm_mat4.c +308 -0
- data/ext/cglm/rb_cglm_plane.c +36 -0
- data/ext/cglm/rb_cglm_project.c +99 -0
- data/ext/cglm/rb_cglm_quat.c +358 -0
- data/ext/cglm/rb_cglm_sphere.c +57 -0
- data/ext/cglm/rb_cglm_vec3.c +882 -0
- data/ext/cglm/rb_cglm_vec4.c +724 -0
- data/lib/cglm.rb +26 -0
- data/lib/cglm/aabb.rb +4 -0
- data/lib/cglm/base.rb +38 -0
- data/lib/cglm/frustum.rb +9 -0
- data/lib/cglm/mat3.rb +27 -0
- data/lib/cglm/mat4.rb +46 -0
- data/lib/cglm/plane.rb +9 -0
- data/lib/cglm/quat.rb +10 -0
- data/lib/cglm/sphere.rb +11 -0
- data/lib/cglm/vec3.rb +88 -0
- data/lib/cglm/vec4.rb +104 -0
- data/lib/cglm/vector_type.rb +17 -0
- data/lib/cglm/version.rb +3 -0
- metadata +202 -0
@@ -0,0 +1,141 @@
|
|
1
|
+
#include "rb_cglm.h"
|
2
|
+
|
3
|
+
/* call-seq: angles(mat4[, dest]) => dest or new Vec3
|
4
|
+
*
|
5
|
+
* Extracts euler angles (in radians) using xyz order.
|
6
|
+
*/
|
7
|
+
VALUE rb_cglm_euler_angles(int argc, VALUE *argv, VALUE self) {
|
8
|
+
VALUE m, dest;
|
9
|
+
rb_scan_args(argc, argv, "11", &m, &dest);
|
10
|
+
if (NIL_P(dest)) dest = VEC3_NEW(ALLOC_VEC3);
|
11
|
+
glm_euler_angles(VAL2MAT4(m), VAL2VEC3(dest));
|
12
|
+
return dest;
|
13
|
+
}
|
14
|
+
|
15
|
+
/* call-seq: xyz(angles[, dest]) => dest or new Mat4
|
16
|
+
*
|
17
|
+
* Builds a rotation matrix from the specified angles, in xyz order. `angles`
|
18
|
+
* must be a Vec3 specifying the X, Y and Z angles (in that order).
|
19
|
+
*/
|
20
|
+
VALUE rb_cglm_euler_xyz(int argc, VALUE *argv, VALUE self) {
|
21
|
+
VALUE angles, dest;
|
22
|
+
rb_scan_args(argc, argv, "11", &angles, &dest);
|
23
|
+
if (NIL_P(dest)) dest = MAT4_NEW(ALLOC_MAT4);
|
24
|
+
glm_euler_xyz(VAL2VEC3(angles), VAL2MAT4(dest));
|
25
|
+
return dest;
|
26
|
+
}
|
27
|
+
|
28
|
+
/* call-seq: zyx(angles[, dest]) => dest or new Mat4
|
29
|
+
*
|
30
|
+
* Builds a rotation matrix from the specified angles, in zyx order. `angles`
|
31
|
+
* must be a Vec3 specifying the X, Y and Z angles (in that order).
|
32
|
+
*/
|
33
|
+
VALUE rb_cglm_euler_zyx(int argc, VALUE *argv, VALUE self) {
|
34
|
+
VALUE angles, dest;
|
35
|
+
rb_scan_args(argc, argv, "11", &angles, &dest);
|
36
|
+
if (NIL_P(dest)) dest = MAT4_NEW(ALLOC_MAT4);
|
37
|
+
glm_euler_zyx(VAL2VEC3(angles), VAL2MAT4(dest));
|
38
|
+
return dest;
|
39
|
+
}
|
40
|
+
|
41
|
+
/* call-seq: zxy(angles[, dest]) => dest or new Mat4
|
42
|
+
*
|
43
|
+
* Builds a rotation matrix from the specified angles, in zxy order. `angles`
|
44
|
+
* must be a Vec3 specifying the X, Y and Z angles (in that order).
|
45
|
+
*/
|
46
|
+
VALUE rb_cglm_euler_zxy(int argc, VALUE *argv, VALUE self) {
|
47
|
+
VALUE angles, dest;
|
48
|
+
rb_scan_args(argc, argv, "11", &angles, &dest);
|
49
|
+
if (NIL_P(dest)) dest = MAT4_NEW(ALLOC_MAT4);
|
50
|
+
glm_euler_zxy(VAL2VEC3(angles), VAL2MAT4(dest));
|
51
|
+
return dest;
|
52
|
+
}
|
53
|
+
|
54
|
+
/* call-seq: xzy(angles[, dest]) => dest or new Mat4
|
55
|
+
*
|
56
|
+
* Builds a rotation matrix from the specified angles, in xzy order. `angles`
|
57
|
+
* must be a Vec3 specifying the X, Y and Z angles (in that order).
|
58
|
+
*/
|
59
|
+
VALUE rb_cglm_euler_xzy(int argc, VALUE *argv, VALUE self) {
|
60
|
+
VALUE angles, dest;
|
61
|
+
rb_scan_args(argc, argv, "11", &angles, &dest);
|
62
|
+
if (NIL_P(dest)) dest = MAT4_NEW(ALLOC_MAT4);
|
63
|
+
glm_euler_xzy(VAL2VEC3(angles), VAL2MAT4(dest));
|
64
|
+
return dest;
|
65
|
+
}
|
66
|
+
|
67
|
+
/* call-seq: yzx(angles[, dest]) => dest or new Mat4
|
68
|
+
*
|
69
|
+
* Builds a rotation matrix from the specified angles, in yzx order. `angles`
|
70
|
+
* must be a Vec3 specifying the X, Y and Z angles (in that order).
|
71
|
+
*/
|
72
|
+
VALUE rb_cglm_euler_yzx(int argc, VALUE *argv, VALUE self) {
|
73
|
+
VALUE angles, dest;
|
74
|
+
rb_scan_args(argc, argv, "11", &angles, &dest);
|
75
|
+
if (NIL_P(dest)) dest = MAT4_NEW(ALLOC_MAT4);
|
76
|
+
glm_euler_yzx(VAL2VEC3(angles), VAL2MAT4(dest));
|
77
|
+
return dest;
|
78
|
+
}
|
79
|
+
|
80
|
+
/* call-seq: yxz(angles[, dest]) => dest or new Mat4
|
81
|
+
*
|
82
|
+
* Builds a rotation matrix from the specified angles, in yxz order. `angles`
|
83
|
+
* must be a Vec3 specifying the X, Y and Z angles (in that order).
|
84
|
+
*/
|
85
|
+
VALUE rb_cglm_euler_yxz(int argc, VALUE *argv, VALUE self) {
|
86
|
+
VALUE angles, dest;
|
87
|
+
rb_scan_args(argc, argv, "11", &angles, &dest);
|
88
|
+
if (NIL_P(dest)) dest = MAT4_NEW(ALLOC_MAT4);
|
89
|
+
glm_euler_yxz(VAL2VEC3(angles), VAL2MAT4(dest));
|
90
|
+
return dest;
|
91
|
+
}
|
92
|
+
|
93
|
+
/* call-seq: by_order(axis, angles[, dest]) => dest or new Mat4
|
94
|
+
*
|
95
|
+
* Builds a rotation matrix from the specified angles, in the specified order,
|
96
|
+
* which can be one of the constants from the Euler module, or computed using
|
97
|
+
* #order. `angles` must be a Vec3 specifying the X, Y and Z angles (in that
|
98
|
+
* order).
|
99
|
+
*/
|
100
|
+
VALUE rb_cglm_euler_by_order(int argc, VALUE *argv, VALUE self) {
|
101
|
+
VALUE angles, axis, dest;
|
102
|
+
rb_scan_args(argc, argv, "21", &axis, &angles, &dest);
|
103
|
+
if (NIL_P(dest)) dest = MAT4_NEW(ALLOC_MAT4);
|
104
|
+
glm_euler_by_order(VAL2VEC3(angles), NUM2INT(axis), VAL2MAT4(dest));
|
105
|
+
return dest;
|
106
|
+
}
|
107
|
+
|
108
|
+
|
109
|
+
/* call-seq: order(axis) => Numeric
|
110
|
+
*
|
111
|
+
* Returns a numeric handle representing the specified axis order. `axis` is
|
112
|
+
* an array containing axis indices (0 for X, 1 for Y, 2 for Z).
|
113
|
+
*
|
114
|
+
* Example:
|
115
|
+
*
|
116
|
+
* order([0, 2, 1]) #=> first X, then Z, then Y
|
117
|
+
*/
|
118
|
+
VALUE rb_cglm_euler_order(VALUE klass, VALUE order_ary) {
|
119
|
+
int order[3] = { NUM2INT(rb_ary_entry(order_ary, 0)),
|
120
|
+
NUM2INT(rb_ary_entry(order_ary, 1)),
|
121
|
+
NUM2INT(rb_ary_entry(order_ary, 2)) };
|
122
|
+
return INT2NUM(glm_euler_order(order));
|
123
|
+
}
|
124
|
+
|
125
|
+
void Init_cglm_euler() {
|
126
|
+
rb_define_const(rb_mEuler, "XYZ", INT2NUM(GLM_EULER_XYZ));
|
127
|
+
rb_define_const(rb_mEuler, "XZY", INT2NUM(GLM_EULER_XZY));
|
128
|
+
rb_define_const(rb_mEuler, "YZX", INT2NUM(GLM_EULER_YZX));
|
129
|
+
rb_define_const(rb_mEuler, "YXZ", INT2NUM(GLM_EULER_YXZ));
|
130
|
+
rb_define_const(rb_mEuler, "ZXY", INT2NUM(GLM_EULER_ZXY));
|
131
|
+
rb_define_const(rb_mEuler, "ZYX", INT2NUM(GLM_EULER_ZYX));
|
132
|
+
rb_define_singleton_method(rb_mEuler, "order", rb_cglm_euler_order, 1);
|
133
|
+
rb_define_singleton_method(rb_mEuler, "xyz", rb_cglm_euler_xyz, -1);
|
134
|
+
rb_define_singleton_method(rb_mEuler, "zyx", rb_cglm_euler_zyx, -1);
|
135
|
+
rb_define_singleton_method(rb_mEuler, "zxy", rb_cglm_euler_zxy, -1);
|
136
|
+
rb_define_singleton_method(rb_mEuler, "xzy", rb_cglm_euler_xzy, -1);
|
137
|
+
rb_define_singleton_method(rb_mEuler, "yzx", rb_cglm_euler_yzx, -1);
|
138
|
+
rb_define_singleton_method(rb_mEuler, "yxz", rb_cglm_euler_yxz, -1);
|
139
|
+
rb_define_singleton_method(rb_mEuler, "by_order", rb_cglm_euler_by_order, -1);
|
140
|
+
rb_define_singleton_method(rb_mEuler, "angles", rb_cglm_euler_angles, -1);
|
141
|
+
}
|
@@ -0,0 +1,306 @@
|
|
1
|
+
#define GLM_CUSTOM_CLIPSPACE 1
|
2
|
+
#include "cglm/types.h"
|
3
|
+
|
4
|
+
#undef near
|
5
|
+
#undef far
|
6
|
+
|
7
|
+
/* near */
|
8
|
+
static float CSCOORD_LBN[4] = {-1.0f, -1.0f, -1.0f, 1.0f};
|
9
|
+
static float CSCOORD_LTN[4] = {-1.0f, 1.0f, -1.0f, 1.0f};
|
10
|
+
static float CSCOORD_RTN[4] = { 1.0f, 1.0f, -1.0f, 1.0f};
|
11
|
+
static float CSCOORD_RBN[4] = { 1.0f, -1.0f, -1.0f, 1.0f};
|
12
|
+
|
13
|
+
/* far */
|
14
|
+
static float CSCOORD_LBF[4] = {-1.0f, -1.0f, 1.0f, 1.0f};
|
15
|
+
static float CSCOORD_LTF[4] = {-1.0f, 1.0f, 1.0f, 1.0f};
|
16
|
+
static float CSCOORD_RTF[4] = { 1.0f, 1.0f, 1.0f, 1.0f};
|
17
|
+
static float CSCOORD_RBF[4] = { 1.0f, -1.0f, 1.0f, 1.0f};
|
18
|
+
|
19
|
+
#define GLM_CSCOORD_LBN { CSCOORD_LBN[0], CSCOORD_LBN[1], CSCOORD_LBN[2], CSCOORD_LBN[3] }
|
20
|
+
#define GLM_CSCOORD_LTN { CSCOORD_LTN[0], CSCOORD_LTN[1], CSCOORD_LTN[2], CSCOORD_LTN[3] }
|
21
|
+
#define GLM_CSCOORD_RTN { CSCOORD_RTN[0], CSCOORD_RTN[1], CSCOORD_RTN[2], CSCOORD_RTN[3] }
|
22
|
+
#define GLM_CSCOORD_RBN { CSCOORD_RBN[0], CSCOORD_RBN[1], CSCOORD_RBN[2], CSCOORD_RBN[3] }
|
23
|
+
#define GLM_CSCOORD_LBF { CSCOORD_LBF[0], CSCOORD_LBF[1], CSCOORD_LBF[2], CSCOORD_LBF[3] }
|
24
|
+
#define GLM_CSCOORD_LTF { CSCOORD_LTF[0], CSCOORD_LTF[1], CSCOORD_LTF[2], CSCOORD_LTF[3] }
|
25
|
+
#define GLM_CSCOORD_RTF { CSCOORD_RTF[0], CSCOORD_RTF[1], CSCOORD_RTF[2], CSCOORD_RTF[3] }
|
26
|
+
#define GLM_CSCOORD_RBF { CSCOORD_RBF[0], CSCOORD_RBF[1], CSCOORD_RBF[2], CSCOORD_RBF[3] }
|
27
|
+
|
28
|
+
#include "rb_cglm.h"
|
29
|
+
#define SYMBOL(cstr) ID2SYM(rb_intern(cstr))
|
30
|
+
|
31
|
+
/* call-seq: planes(space[, dest]) => dest | new Hash
|
32
|
+
*
|
33
|
+
* Extracts the 6 view frustum planes into an hash of 6 Vec4's. If `dest` is
|
34
|
+
* omitted, a new Hash is allocated.
|
35
|
+
*
|
36
|
+
* * `space` is the Mat4 representing the space in which the 6 frustum planes
|
37
|
+
* are defined. If it's a `projection` matrix, the result is in view space. If
|
38
|
+
* it's a `(view * projection)` matrix, the result is in world space. If it's
|
39
|
+
* a `(model * view * projection)` matrix, the result is in object space.
|
40
|
+
*
|
41
|
+
* * `dest` is a Hash containing the following keys: `:left`, `:right`, `:bottom`,
|
42
|
+
* `:top`, `:near`, `:far`. Each value is a Vec4.
|
43
|
+
*
|
44
|
+
* You probably want to extract planes in world space, so use `(view * projection)`
|
45
|
+
* as `space`.
|
46
|
+
*/
|
47
|
+
VALUE rb_cglm_frustum_singleton_planes(int argc, VALUE *argv, VALUE self) {
|
48
|
+
VALUE mat, dest;
|
49
|
+
rb_scan_args(argc, argv, "11", &mat, &dest);
|
50
|
+
if (NIL_P(dest)) dest = rb_hash_new();
|
51
|
+
vec4 planes[6];
|
52
|
+
glm_frustum_planes(VAL2MAT4(mat), planes);
|
53
|
+
|
54
|
+
#define HASH_GET_OR_SET(index, name, str) \
|
55
|
+
VALUE name = rb_hash_aref(dest, SYMBOL(str)); \
|
56
|
+
if (NIL_P(name)) { \
|
57
|
+
name = VEC4_NEW(ALLOC_VEC4); \
|
58
|
+
rb_hash_aset(dest, SYMBOL(str), name); \
|
59
|
+
} \
|
60
|
+
memcpy(&VAL2VEC4(name), &planes[index], sizeof(vec4));
|
61
|
+
|
62
|
+
HASH_GET_OR_SET(GLM_LEFT, left, "left");
|
63
|
+
HASH_GET_OR_SET(GLM_RIGHT, right, "right");
|
64
|
+
HASH_GET_OR_SET(GLM_BOTTOM, bottom, "bottom");
|
65
|
+
HASH_GET_OR_SET(GLM_TOP, top, "top");
|
66
|
+
HASH_GET_OR_SET(GLM_NEAR, n, "near");
|
67
|
+
HASH_GET_OR_SET(GLM_FAR, f, "far");
|
68
|
+
#undef HASH_GET_OR_SET
|
69
|
+
|
70
|
+
return dest;
|
71
|
+
}
|
72
|
+
|
73
|
+
|
74
|
+
/* call-seq: corners(inv_space[, dest]) => dest | new Hash
|
75
|
+
*
|
76
|
+
* Extracts the view frustum corners using clip-space coordinates.
|
77
|
+
*
|
78
|
+
* * `inv_space` is the inverse of the Mat4 representing the space in which
|
79
|
+
* the 8 frustum corners are defined. If it's an `(inverse(view * projection))`
|
80
|
+
* matrix, the result is in world space. If it's an `(inverse(model * view * projection))`
|
81
|
+
* matrix, the result is in object space.
|
82
|
+
*
|
83
|
+
* * You probably want to extract planes in world space, so use
|
84
|
+
* `(inverse(view * projection))` as `inv_space`.
|
85
|
+
*
|
86
|
+
* * `dest` is a Hash containing the following keys: `:lbn`, `:ltn`, `:rtn`,
|
87
|
+
* `:rbn`, `:lbf`, `:ltf`, `:rtf`, `:rbf`. Each value is a Vec4.
|
88
|
+
*
|
89
|
+
* * The `dest` hash, if created, is ordered such that you can index into
|
90
|
+
* the array of values with the Frustum class constants. For example,
|
91
|
+
* `hash.values[Frustum::RTN]`.
|
92
|
+
*
|
93
|
+
* * If you know the index of a near coord, you can get its far coord by
|
94
|
+
* adding 4. For example,
|
95
|
+
* `hash.values[Frustum::RTN + 4] == hash.values[Frustum::RTF]`.
|
96
|
+
*
|
97
|
+
*/
|
98
|
+
VALUE rb_cglm_frustum_singleton_corners(int argc, VALUE *argv, VALUE self) {
|
99
|
+
VALUE mat, dest;
|
100
|
+
rb_scan_args(argc, argv, "11", &mat, &dest);
|
101
|
+
if (NIL_P(dest)) dest = rb_hash_new();
|
102
|
+
vec4 corners[8];
|
103
|
+
glm_frustum_corners(VAL2MAT4(mat), corners);
|
104
|
+
|
105
|
+
#define HASH_GET_OR_SET(index, name) \
|
106
|
+
VALUE name = rb_hash_aref(dest, SYMBOL(#name)); \
|
107
|
+
if (NIL_P(name)) { \
|
108
|
+
name = VEC4_NEW(ALLOC_VEC4); \
|
109
|
+
rb_hash_aset(dest, SYMBOL(#name), name); \
|
110
|
+
} \
|
111
|
+
memcpy(&VAL2VEC4(name), &corners[index], sizeof(vec4));
|
112
|
+
|
113
|
+
HASH_GET_OR_SET(GLM_LBN, lbn);
|
114
|
+
HASH_GET_OR_SET(GLM_LTN, ltn);
|
115
|
+
HASH_GET_OR_SET(GLM_RTN, rtn);
|
116
|
+
HASH_GET_OR_SET(GLM_RBN, rbn);
|
117
|
+
HASH_GET_OR_SET(GLM_LBF, lbf);
|
118
|
+
HASH_GET_OR_SET(GLM_LTF, ltf);
|
119
|
+
HASH_GET_OR_SET(GLM_RTF, rtf);
|
120
|
+
HASH_GET_OR_SET(GLM_RBF, rbf);
|
121
|
+
#undef HASH_GET_OR_SET
|
122
|
+
|
123
|
+
return dest;
|
124
|
+
}
|
125
|
+
|
126
|
+
#define hash_to_corner(corners, corners_v, index, name) \
|
127
|
+
{ \
|
128
|
+
VALUE v = rb_hash_aref(corners_v, SYMBOL(name)); \
|
129
|
+
if (NIL_P(v)) v = VEC4_NEW(ALLOC_VEC4); \
|
130
|
+
memcpy(&corners[index][0], &VAL2VEC4(v), sizeof(vec4)); \
|
131
|
+
}
|
132
|
+
|
133
|
+
#define hash_to_corners(corners, corners_v) \
|
134
|
+
hash_to_corner(corners, corners_v, GLM_LBN, "lbn"); \
|
135
|
+
hash_to_corner(corners, corners_v, GLM_LTN, "ltn"); \
|
136
|
+
hash_to_corner(corners, corners_v, GLM_RTN, "rtn"); \
|
137
|
+
hash_to_corner(corners, corners_v, GLM_RBN, "rbn"); \
|
138
|
+
hash_to_corner(corners, corners_v, GLM_LBF, "lbf"); \
|
139
|
+
hash_to_corner(corners, corners_v, GLM_LTF, "ltf"); \
|
140
|
+
hash_to_corner(corners, corners_v, GLM_RTF, "rtf"); \
|
141
|
+
hash_to_corner(corners, corners_v, GLM_RBF, "rbf");
|
142
|
+
|
143
|
+
/* call-seq: center(corners[, dest]) => dest | new vec4
|
144
|
+
*
|
145
|
+
* Returns the center of the view frustum described by the hash `corners`,
|
146
|
+
* which must follow the format returned by {corners}.
|
147
|
+
*/
|
148
|
+
VALUE rb_cglm_frustum_singleton_center(int argc, VALUE *argv, VALUE self) {
|
149
|
+
VALUE corners_v, dest;
|
150
|
+
rb_scan_args(argc, argv, "11", &corners_v, &dest);
|
151
|
+
if (NIL_P(dest)) dest = VEC4_NEW(ALLOC_VEC4);
|
152
|
+
vec4 corners[8];
|
153
|
+
hash_to_corners(corners, corners_v);
|
154
|
+
glm_frustum_center(corners, VAL2VEC4(dest));
|
155
|
+
return dest;
|
156
|
+
}
|
157
|
+
|
158
|
+
/* call-seq: aabb(matr, corners[, dest]) => dest | new AABB
|
159
|
+
*
|
160
|
+
* Finds a bounding box for the frustum defined by `corners` relative to the
|
161
|
+
* givn matrix (e.g. a view matrix). Places the result in `dest` and returns
|
162
|
+
* `dest`, or a new AABB if `dest` is omitted.
|
163
|
+
*/
|
164
|
+
VALUE rb_cglm_frustum_singleton_aabb(int argc, VALUE *argv, VALUE self) {
|
165
|
+
VALUE matr, corners_v, dest;
|
166
|
+
rb_scan_args(argc, argv, "21", &matr, &corners_v, &dest);
|
167
|
+
if (NIL_P(dest)) dest = rb_funcall(rb_cAABB, rb_intern("new"), 0);
|
168
|
+
vec4 corners[8];
|
169
|
+
hash_to_corners(corners, corners_v);
|
170
|
+
glm_frustum_box(corners, VAL2MAT4(matr), VAL2AABB(dest).corners);
|
171
|
+
return dest;
|
172
|
+
}
|
173
|
+
|
174
|
+
/* call-seq: corners_at(corners, split, far[, dest]) => dest | new Hash
|
175
|
+
*
|
176
|
+
* Finds the corners of a plane which lies between the near and far planes of
|
177
|
+
* the frustum.
|
178
|
+
*
|
179
|
+
* This will be helpful if you want to split a frustum, e.g. CSM/PSSM.
|
180
|
+
*
|
181
|
+
* * `corners` are the 8 corners of the frustum and follow the same format as
|
182
|
+
* is returned by {corners}.
|
183
|
+
*
|
184
|
+
* * `split` is the distance at which to calculate the 4 corners.
|
185
|
+
*
|
186
|
+
* * `far` is the far distance of the frustum.
|
187
|
+
*
|
188
|
+
* * `dest` is a Hash containing :lb, :lt, :rt, and :rb (all of which are
|
189
|
+
* Vec4's). If omitted, one will be created.
|
190
|
+
*/
|
191
|
+
VALUE rb_cglm_frustum_singleton_corners_at(int argc, VALUE *argv, VALUE self) {
|
192
|
+
VALUE corners_v, split, f, dest;
|
193
|
+
rb_scan_args(argc, argv, "31", &corners_v, &split, &f, &dest);
|
194
|
+
if (NIL_P(dest)) dest = rb_hash_new();
|
195
|
+
vec4 corners[8];
|
196
|
+
hash_to_corners(corners, corners_v);
|
197
|
+
vec4 plane_corners[4];
|
198
|
+
glm_frustum_corners_at(corners, NUM2FLT(split), NUM2FLT(f), plane_corners);
|
199
|
+
|
200
|
+
#define HASH_GET_OR_SET(index, name) \
|
201
|
+
VALUE name = rb_hash_aref(dest, SYMBOL(#name)); \
|
202
|
+
if (NIL_P(name)) { \
|
203
|
+
name = VEC4_NEW(ALLOC_VEC4); \
|
204
|
+
rb_hash_aset(dest, SYMBOL(#name), name); \
|
205
|
+
} \
|
206
|
+
memcpy(&VAL2VEC4(name), &plane_corners[index], sizeof(vec4));
|
207
|
+
|
208
|
+
HASH_GET_OR_SET(0, lb);
|
209
|
+
HASH_GET_OR_SET(1, lt);
|
210
|
+
HASH_GET_OR_SET(2, rt);
|
211
|
+
HASH_GET_OR_SET(3, rb);
|
212
|
+
#undef HASH_GET_OR_SET
|
213
|
+
|
214
|
+
return dest;
|
215
|
+
}
|
216
|
+
|
217
|
+
/* call-seq: planes([dest]) => dest | new Hash
|
218
|
+
*
|
219
|
+
* Same as calling {planes} with `self.matrix` as the first argument.
|
220
|
+
*/
|
221
|
+
VALUE rb_cglm_frustum_planes(int argc, VALUE *argv, VALUE self) {
|
222
|
+
VALUE mat = rb_ivar_get(self, rb_intern("@matrix"));
|
223
|
+
VALUE dest;
|
224
|
+
rb_scan_args(argc, argv, "01", &dest);
|
225
|
+
return rb_funcall(rb_cFrustum, rb_intern("planes"), 2, mat, dest);
|
226
|
+
}
|
227
|
+
|
228
|
+
/* call-seq: corners([dest]) => dest | new Hash
|
229
|
+
*
|
230
|
+
* Same as calling {corners} with `self.matrix.inverse` as the first argument.
|
231
|
+
*/
|
232
|
+
VALUE rb_cglm_frustum_corners(int argc, VALUE *argv, VALUE self) {
|
233
|
+
VALUE mat = rb_funcall(rb_ivar_get(self, rb_intern("@matrix")), rb_intern("inverse"), 0);
|
234
|
+
VALUE dest;
|
235
|
+
rb_scan_args(argc, argv, "01", &dest);
|
236
|
+
return rb_funcall(rb_cFrustum, rb_intern("corners"), 2, mat, dest);
|
237
|
+
}
|
238
|
+
|
239
|
+
/* call-seq: center([dest]) => dest | new Hash
|
240
|
+
*
|
241
|
+
* Same as calling {center} with #corners as the first argument.
|
242
|
+
*/
|
243
|
+
VALUE rb_cglm_frustum_center(int argc, VALUE *argv, VALUE self) {
|
244
|
+
VALUE corners = rb_funcall(self, rb_intern("corners"), 0);
|
245
|
+
VALUE dest;
|
246
|
+
rb_scan_args(argc, argv, "01", &dest);
|
247
|
+
return rb_funcall(rb_cFrustum, rb_intern("center"), 2, corners, dest);
|
248
|
+
}
|
249
|
+
|
250
|
+
/* call-seq: to_aabb(matr[, dest]) => dest | new AABB
|
251
|
+
*
|
252
|
+
* Same as calling {aabb} with #corners as the first argument.
|
253
|
+
*/
|
254
|
+
VALUE rb_cglm_frustum_to_aabb(int argc, VALUE *argv, VALUE self) {
|
255
|
+
VALUE corners = rb_funcall(self, rb_intern("corners"), 0);
|
256
|
+
VALUE split, f, dest;
|
257
|
+
rb_scan_args(argc, argv, "21", &split, &f, &dest);
|
258
|
+
return rb_funcall(rb_cFrustum, rb_intern("aabb"), 4, corners, split, f, dest);
|
259
|
+
}
|
260
|
+
|
261
|
+
/* call-seq: corners_at(split, far[, dest]) => dest | new Hash
|
262
|
+
*
|
263
|
+
* Same as calling {corners_at} with #corners as the first argument.
|
264
|
+
*/
|
265
|
+
VALUE rb_cglm_frustum_corners_at(int argc, VALUE *argv, VALUE self) {
|
266
|
+
VALUE corners = rb_funcall(self, rb_intern("corners"), 0);
|
267
|
+
VALUE split, f, dest;
|
268
|
+
rb_scan_args(argc, argv, "21", &split, &f, &dest);
|
269
|
+
return rb_funcall(rb_cFrustum, rb_intern("corners_at"), 4, corners, split, f, dest);
|
270
|
+
}
|
271
|
+
|
272
|
+
void Init_cglm_frustum() {
|
273
|
+
/* left bottom near */ rb_define_const(rb_cFrustum, "LBN", GLM_LBN);
|
274
|
+
/* left top near */ rb_define_const(rb_cFrustum, "LTN", GLM_LTN);
|
275
|
+
/* right top near */ rb_define_const(rb_cFrustum, "RTN", GLM_RTN);
|
276
|
+
/* right bottom near */ rb_define_const(rb_cFrustum, "RBN", GLM_RBN);
|
277
|
+
/* left bottom far */ rb_define_const(rb_cFrustum, "LBF", GLM_LBF);
|
278
|
+
/* left top far */ rb_define_const(rb_cFrustum, "LTF", GLM_LTF);
|
279
|
+
/* right top far */ rb_define_const(rb_cFrustum, "RTF", GLM_RTF);
|
280
|
+
/* right bottom far */ rb_define_const(rb_cFrustum, "RBF", GLM_RBF);
|
281
|
+
rb_define_const(rb_cFrustum, "LEFT", GLM_LEFT);
|
282
|
+
rb_define_const(rb_cFrustum, "RIGHT", GLM_RIGHT);
|
283
|
+
rb_define_const(rb_cFrustum, "BOTTOM", GLM_BOTTOM);
|
284
|
+
rb_define_const(rb_cFrustum, "TOP", GLM_TOP);
|
285
|
+
rb_define_const(rb_cFrustum, "NEAR", GLM_NEAR);
|
286
|
+
rb_define_const(rb_cFrustum, "FAR", GLM_FAR);
|
287
|
+
/* left bottom near */ rb_define_const(rb_cFrustum, "CLIPSPACE_COORD_LBN", VEC4_NEW(CSCOORD_LBN));
|
288
|
+
/* left top near */ rb_define_const(rb_cFrustum, "CLIPSPACE_COORD_LTN", VEC4_NEW(CSCOORD_LTN));
|
289
|
+
/* right top near */ rb_define_const(rb_cFrustum, "CLIPSPACE_COORD_RTN", VEC4_NEW(CSCOORD_RTN));
|
290
|
+
/* right bottom near */ rb_define_const(rb_cFrustum, "CLIPSPACE_COORD_RBN", VEC4_NEW(CSCOORD_RBN));
|
291
|
+
/* left bottom far */ rb_define_const(rb_cFrustum, "CLIPSPACE_COORD_LBF", VEC4_NEW(CSCOORD_LBF));
|
292
|
+
/* left top far */ rb_define_const(rb_cFrustum, "CLIPSPACE_COORD_LTF", VEC4_NEW(CSCOORD_LTF));
|
293
|
+
/* right top far */ rb_define_const(rb_cFrustum, "CLIPSPACE_COORD_RTF", VEC4_NEW(CSCOORD_RTF));
|
294
|
+
/* right bottom far */ rb_define_const(rb_cFrustum, "CLIPSPACE_COORD_RBF", VEC4_NEW(CSCOORD_RBF));
|
295
|
+
|
296
|
+
rb_define_method(rb_cFrustum, "planes", rb_cglm_frustum_planes, -1);
|
297
|
+
rb_define_method(rb_cFrustum, "corners", rb_cglm_frustum_corners, -1);
|
298
|
+
rb_define_method(rb_cFrustum, "center", rb_cglm_frustum_center, -1);
|
299
|
+
rb_define_method(rb_cFrustum, "aabb", rb_cglm_frustum_to_aabb, -1);
|
300
|
+
rb_define_method(rb_cFrustum, "corners_at", rb_cglm_frustum_to_aabb, -1);
|
301
|
+
|
302
|
+
rb_define_singleton_method(rb_cFrustum, "planes", rb_cglm_frustum_singleton_planes, -1);
|
303
|
+
rb_define_singleton_method(rb_cFrustum, "corners", rb_cglm_frustum_singleton_corners, -1);
|
304
|
+
rb_define_singleton_method(rb_cFrustum, "to_aabb", rb_cglm_frustum_singleton_aabb, -1);
|
305
|
+
rb_define_singleton_method(rb_cFrustum, "corners_at", rb_cglm_frustum_singleton_corners_at, -1);
|
306
|
+
}
|
@@ -0,0 +1,252 @@
|
|
1
|
+
#include "rb_cglm.h"
|
2
|
+
|
3
|
+
/* call-seq: identity([dest]) => dest | new Mat3
|
4
|
+
*
|
5
|
+
* Sets `dest` to the identity if provided. If omitted, a new Mat4 is created
|
6
|
+
* and set to the identity. `dest` or the new Mat3 is returned.
|
7
|
+
*/
|
8
|
+
VALUE rb_cglm_mat3_new_identity(int argc, VALUE *argv, VALUE self) {
|
9
|
+
VALUE dest;
|
10
|
+
rb_scan_args(argc, argv, "01", &dest);
|
11
|
+
if (NIL_P(dest)) dest = MAT3_NEW(ALLOC_MAT3);
|
12
|
+
glm_mat3_identity(VAL2MAT3(dest));
|
13
|
+
return dest;
|
14
|
+
}
|
15
|
+
|
16
|
+
/* call-seq: mul_mat3(other[, dest]) => dest | new Mat3
|
17
|
+
*
|
18
|
+
* Multiplies this Mat3 with `other`, returning the result.
|
19
|
+
*/
|
20
|
+
VALUE rb_cglm_mat3_mul_mat3(int argc, VALUE *argv, VALUE self) {
|
21
|
+
VALUE other, dest;
|
22
|
+
rb_scan_args(argc, argv, "11", &other, &dest);
|
23
|
+
if (NIL_P(dest)) dest = MAT3_NEW(ALLOC_MAT3);
|
24
|
+
glm_mat3_mul(VAL2MAT3(self), VAL2MAT3(other), VAL2MAT3(dest));
|
25
|
+
return dest;
|
26
|
+
}
|
27
|
+
|
28
|
+
/* call-seq: mul_vec3(other[, dest]) => dest | new Vec3
|
29
|
+
*
|
30
|
+
* Multiplies this Vec3 with `other`, returning the result.
|
31
|
+
*/
|
32
|
+
VALUE rb_cglm_mat3_mul_vec3(int argc, VALUE *argv, VALUE self) {
|
33
|
+
VALUE other, dest;
|
34
|
+
rb_scan_args(argc, argv, "11", &other, &dest);
|
35
|
+
if (NIL_P(dest)) dest = VEC3_NEW(ALLOC_VEC3);
|
36
|
+
glm_mat3_mulv(VAL2MAT3(self), VAL2VEC3(other), VAL2VEC3(dest));
|
37
|
+
return dest;
|
38
|
+
}
|
39
|
+
|
40
|
+
/* call-seq: transpose([dest]) => dest | new Mat3
|
41
|
+
*
|
42
|
+
* Transposes this matrix and places it into `dest`. If `dest` is omitted, a
|
43
|
+
* new Mat3 will be allocated.
|
44
|
+
*/
|
45
|
+
VALUE rb_cglm_mat3_transpose(int argc, VALUE *argv, VALUE self) {
|
46
|
+
VALUE dest;
|
47
|
+
rb_scan_args(argc, argv, "01", &dest);
|
48
|
+
if (NIL_P(dest)) dest = MAT3_NEW(ALLOC_MAT3);
|
49
|
+
glm_mat3_transpose_to(VAL2MAT3(self), VAL2MAT3(dest));
|
50
|
+
return dest;
|
51
|
+
}
|
52
|
+
|
53
|
+
/* call-seq: transpose! => self
|
54
|
+
*
|
55
|
+
* Transposes this matrix in-place and returns `self`.
|
56
|
+
*/
|
57
|
+
VALUE rb_cglm_mat3_transpose_self(int argc, VALUE *argv, VALUE self) {
|
58
|
+
glm_mat3_transpose(VAL2MAT3(self));
|
59
|
+
return self;
|
60
|
+
}
|
61
|
+
|
62
|
+
/* call-seq: to_quat([dest]) => dest | new Quat
|
63
|
+
*
|
64
|
+
* Converts `self` to a Quat. If `dest` is omitted, a new Quat is created.
|
65
|
+
*/
|
66
|
+
VALUE rb_cglm_mat3_to_quat(int argc, VALUE *argv, VALUE self) {
|
67
|
+
VALUE dest;
|
68
|
+
rb_scan_args(argc, argv, "01", &dest);
|
69
|
+
if (NIL_P(dest)) dest = QUAT_NEW(ALLOC_QUAT);
|
70
|
+
glm_mat3_quat(VAL2MAT3(self), VAL2QUAT(dest));
|
71
|
+
return dest;
|
72
|
+
}
|
73
|
+
|
74
|
+
/* call-seq: mul_scalar(scalar[, dest]) => dest | new Mat3
|
75
|
+
*
|
76
|
+
* Multiplies each element in this matrix by the specified scalar amount.
|
77
|
+
* Places the result in `dest` and returns it, creating a new Mat3 if `dest`
|
78
|
+
* is omitted.
|
79
|
+
*/
|
80
|
+
VALUE rb_cglm_mat3_mul_scalar(int argc, VALUE *argv, VALUE self) {
|
81
|
+
VALUE scalar, dest;
|
82
|
+
rb_scan_args(argc, argv, "11", &scalar, &dest);
|
83
|
+
if (NIL_P(dest)) dest = MAT3_NEW(ALLOC_MAT3);
|
84
|
+
glm_mat3_scale(VAL2MAT3(dest), NUM2FLT(scalar));
|
85
|
+
return dest;
|
86
|
+
}
|
87
|
+
|
88
|
+
/* call-seq: mul_scalar!(scalar) => self
|
89
|
+
*
|
90
|
+
* Multiplies each element in this matrix by the specified scalar amount,
|
91
|
+
* modifying `self` in-place and returning it.
|
92
|
+
*/
|
93
|
+
VALUE rb_cglm_mat3_mul_scalar_self(VALUE self, VALUE scalar) {
|
94
|
+
glm_mat3_scale(VAL2MAT3(self), NUM2FLT(scalar));
|
95
|
+
return self;
|
96
|
+
}
|
97
|
+
|
98
|
+
VALUE rb_cglm_mat3_determinant(VALUE self) {
|
99
|
+
return glm_mat3_det(VAL2MAT3(self));
|
100
|
+
}
|
101
|
+
|
102
|
+
/* call-seq: inverse([dest]) => dest | new Mat3
|
103
|
+
*
|
104
|
+
* Places the inverse of `self` into `dest`, creating a new Mat3 if `dest` is
|
105
|
+
* omitted. Returns `dest`.
|
106
|
+
*/
|
107
|
+
VALUE rb_cglm_mat3_inverse(int argc, VALUE *argv, VALUE self) {
|
108
|
+
VALUE dest;
|
109
|
+
rb_scan_args(argc, argv, "01", &dest);
|
110
|
+
if (NIL_P(dest)) dest = MAT3_NEW(ALLOC_MAT3);
|
111
|
+
glm_mat3_inv(VAL2MAT3(self), VAL2MAT3(dest));
|
112
|
+
return dest;
|
113
|
+
}
|
114
|
+
|
115
|
+
/* call-seq: invert! => self
|
116
|
+
*
|
117
|
+
* Calcaultes the inverse of `self`, modifies `self` in-place, and returns
|
118
|
+
* `self`.
|
119
|
+
*/
|
120
|
+
VALUE rb_cglm_mat3_inverse_self(int argc, VALUE *argv, VALUE self) {
|
121
|
+
glm_mat3_inv(VAL2MAT3(self), VAL2MAT3(self));
|
122
|
+
return self;
|
123
|
+
}
|
124
|
+
|
125
|
+
/* call-seq: swap_col!(col1, col2) => self
|
126
|
+
*
|
127
|
+
* Swaps two matrix columns and returns `self`.
|
128
|
+
*/
|
129
|
+
VALUE rb_cglm_mat3_swap_col_self(VALUE self, VALUE col1, VALUE col2) {
|
130
|
+
glm_mat3_swap_col(VAL2MAT3(self), NUM2INT(col1), NUM2INT(col2));
|
131
|
+
return self;
|
132
|
+
}
|
133
|
+
|
134
|
+
/* call-seq: swap_row!(row1, row2) => self
|
135
|
+
*
|
136
|
+
* Swaps two matrix rows and returns `self`.
|
137
|
+
*/
|
138
|
+
VALUE rb_cglm_mat3_swap_row_self(VALUE self, VALUE row1, VALUE row2) {
|
139
|
+
glm_mat3_swap_row(VAL2MAT3(self), NUM2INT(row1), NUM2INT(row2));
|
140
|
+
return self;
|
141
|
+
}
|
142
|
+
|
143
|
+
VALUE rb_cglm_mat3_aref(VALUE self, VALUE index) {
|
144
|
+
CHECK_RANGE(index, 0, 2);
|
145
|
+
float *addr = (float *) VAL2MAT3(self);
|
146
|
+
return VEC3_NEW(addr + (NUM2INT(index) * 3));
|
147
|
+
}
|
148
|
+
|
149
|
+
VALUE rb_cglm_mat3_aset(VALUE self, VALUE index, VALUE val) {
|
150
|
+
CHECK_RANGE(index, 0, 2);
|
151
|
+
if (rb_funcall(val, rb_intern("kind_of?"), 1, rb_cVec4))
|
152
|
+
memcpy(&(VAL2MAT4(self)[NUM2INT(index)]), &VAL2VEC4(val), sizeof(vec3));
|
153
|
+
else if (rb_funcall(val, rb_intern("kind_of?"), 1, rb_cVec3))
|
154
|
+
memcpy(&(VAL2MAT4(self)[NUM2INT(index)]), &VAL2VEC3(val), sizeof(vec3));
|
155
|
+
else {
|
156
|
+
VALUE row = rb_cglm_mat3_aref(self, index);
|
157
|
+
for (int i = 0; i < 3; i++) {
|
158
|
+
VALUE v = rb_funcall(val, rb_intern("[]"), 1, INT2NUM(i));
|
159
|
+
if (!NIL_P(v)) {
|
160
|
+
rb_funcall(row, rb_intern("[]="), 2, INT2NUM(i), v);
|
161
|
+
}
|
162
|
+
}
|
163
|
+
}
|
164
|
+
return self;
|
165
|
+
}
|
166
|
+
|
167
|
+
VALUE rb_cglm_mat3_to_mat4(int argc, VALUE *argv, VALUE self) {
|
168
|
+
VALUE dest;
|
169
|
+
if (argc == 0) dest = MAT4_NEW(ALLOC_MAT4);
|
170
|
+
dest = argv[0];
|
171
|
+
glm_mat4_ins3(VAL2MAT3(self), VAL2MAT4(dest));
|
172
|
+
return dest;
|
173
|
+
}
|
174
|
+
|
175
|
+
VALUE rb_cglm_mat3_size_bytes(VALUE klass) { return SIZET2NUM(mat3_size()); }
|
176
|
+
|
177
|
+
VALUE rb_cglm_mat3_alignment_bytes(VALUE klass) { return SIZET2NUM(MAT3_ALIGNMENT); }
|
178
|
+
|
179
|
+
VALUE rb_cglm_mat3_equal(VALUE self, VALUE other) {
|
180
|
+
if (memcmp(&VAL2MAT3(self), &VAL2MAT3(other), sizeof(mat3))) return Qfalse;
|
181
|
+
return Qtrue;
|
182
|
+
}
|
183
|
+
|
184
|
+
/* call-seq: a =~ b => true|false
|
185
|
+
*
|
186
|
+
* Returns true if each member of `a` is very close to, but not necessarily
|
187
|
+
* exactly equal to, each corresponding member of `b`. This is useful in many
|
188
|
+
* circumstances because imprecision introduced by floating point calculations
|
189
|
+
* can lead to two expressions which are otherwise mathematically equivalent
|
190
|
+
* returning false.
|
191
|
+
*/
|
192
|
+
VALUE rb_cglm_mat3_equalish(int argc, VALUE *argv, VALUE self) {
|
193
|
+
VALUE other, epsilon;
|
194
|
+
float feps = FLT_EPSILON;
|
195
|
+
rb_scan_args(argc, argv, "11", &other, &epsilon);
|
196
|
+
if (!NIL_P(epsilon)) feps = NUM2FLT(epsilon);
|
197
|
+
mat3 *a = &VAL2MAT3(self);
|
198
|
+
mat3 *b = &VAL2MAT3(other);
|
199
|
+
for (int i = 0; i < 3; i++) {
|
200
|
+
for (int j = 0; j < 3; j++) {
|
201
|
+
if (fabsf((*a)[i][j] - (*b)[i][j]) > feps)
|
202
|
+
return Qfalse;
|
203
|
+
}
|
204
|
+
}
|
205
|
+
return Qtrue;
|
206
|
+
}
|
207
|
+
|
208
|
+
/* call-seq: random([dest]) => dest | new Mat3
|
209
|
+
*
|
210
|
+
* Fills `dest` or a new Mat3 with a random rotation about a random axis with
|
211
|
+
* a random angle, and returns it.
|
212
|
+
*/
|
213
|
+
VALUE rb_cglm_mat3_new_random(int argc, VALUE *argv, VALUE self) {
|
214
|
+
VALUE dest;
|
215
|
+
rb_scan_args(argc, argv, "01", &dest);
|
216
|
+
if (NIL_P(dest)) dest = MAT3_NEW(ALLOC_MAT3);
|
217
|
+
|
218
|
+
mat4 m4;
|
219
|
+
glm_rotate_make(m4, drand48(), (vec3){drand48(), drand48(), drand48()});
|
220
|
+
glm_mat4_pick3(m4, VAL2MAT3(dest));
|
221
|
+
|
222
|
+
return dest;
|
223
|
+
}
|
224
|
+
|
225
|
+
void Init_cglm_mat3() {
|
226
|
+
rb_define_method(rb_cMat3, "equalish", rb_cglm_mat3_equalish, -1);
|
227
|
+
rb_define_method(rb_cMat3, "==", rb_cglm_mat3_equal, 1);
|
228
|
+
rb_define_method(rb_cMat3, "[]", rb_cglm_mat3_aref, 1);
|
229
|
+
rb_define_method(rb_cMat3, "[]=", rb_cglm_mat3_aset, 2);
|
230
|
+
rb_define_method(rb_cMat3, "mul_mat3", rb_cglm_mat3_mul_mat3, -1);
|
231
|
+
rb_define_method(rb_cMat3, "mul_vec3", rb_cglm_mat3_mul_vec3, -1);
|
232
|
+
rb_define_method(rb_cMat3, "mul_scalar", rb_cglm_mat3_mul_scalar, -1);
|
233
|
+
rb_define_method(rb_cMat3, "mul_scalar!", rb_cglm_mat3_mul_scalar_self, 0);
|
234
|
+
rb_define_method(rb_cMat3, "transpose", rb_cglm_mat3_transpose, -1);
|
235
|
+
rb_define_method(rb_cMat3, "transpose!", rb_cglm_mat3_transpose_self, 0);
|
236
|
+
rb_define_method(rb_cMat3, "to_quat", rb_cglm_mat3_to_quat, -1);
|
237
|
+
rb_define_method(rb_cMat3, "determinant", rb_cglm_mat3_determinant, 0);
|
238
|
+
rb_define_method(rb_cMat3, "invert", rb_cglm_mat3_inverse, -1);
|
239
|
+
rb_define_method(rb_cMat3, "invert!", rb_cglm_mat3_inverse_self, 0);
|
240
|
+
rb_define_method(rb_cMat3, "swap_col!", rb_cglm_mat3_swap_col_self, 2);
|
241
|
+
rb_define_method(rb_cMat3, "swap_row!", rb_cglm_mat3_swap_row_self, 2);
|
242
|
+
rb_define_method(rb_cMat3, "to_mat4", rb_cglm_mat3_to_mat4, -1);
|
243
|
+
|
244
|
+
rb_define_alias(rb_cMat3, "=~", "equalish");
|
245
|
+
rb_define_alias(rb_cMat3, "det", "determinant");
|
246
|
+
|
247
|
+
rb_define_singleton_method(rb_cMat3, "identity", rb_cglm_mat3_new_identity, -1);
|
248
|
+
rb_define_singleton_method(rb_cMat3, "size", rb_cglm_mat3_size_bytes, 0);
|
249
|
+
rb_define_singleton_method(rb_cMat3, "alignment", rb_cglm_mat3_alignment_bytes, 0);
|
250
|
+
rb_define_singleton_method(rb_cMat3, "random", rb_cglm_mat3_new_random, -1);
|
251
|
+
rb_define_singleton_method(rb_cMat3, "rand", rb_cglm_mat3_new_random, -1);
|
252
|
+
}
|