cglm 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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
|
+
}
|