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,271 @@
|
|
1
|
+
#include "rb_cglm.h"
|
2
|
+
|
3
|
+
/* call-seq: transform(mat4[, dest]) => dest | new AABB
|
4
|
+
*
|
5
|
+
* Applies transform to an axis-aligned bounding box, placing the result in
|
6
|
+
* `dest` and allocating it if necessary.
|
7
|
+
*/
|
8
|
+
VALUE rb_cglm_aabb_transform(int argc, VALUE *argv, VALUE self) {
|
9
|
+
VALUE matr, dest;
|
10
|
+
rb_scan_args(argc, argv, "11", &matr, &dest);
|
11
|
+
if (NIL_P(dest)) dest = AABB_NEW(ALLOC_AABB);
|
12
|
+
mat4 *m;
|
13
|
+
aabb *a, *b;
|
14
|
+
m = &VAL2MAT4(matr);
|
15
|
+
a = &VAL2AABB(self);
|
16
|
+
b = &VAL2AABB(dest);
|
17
|
+
glm_aabb_transform(a->corners, *m, a->corners);
|
18
|
+
return dest;
|
19
|
+
}
|
20
|
+
|
21
|
+
/* call-seq: merge(other[, dest]) => dest | new AABB
|
22
|
+
*
|
23
|
+
* Merges two axis-aligned bounding boxes, storing the result in `dest`. If
|
24
|
+
* `dest` is omitted, a new AABB is created. Returns `dest`.
|
25
|
+
*
|
26
|
+
* Both boxes must be in the same space.
|
27
|
+
*/
|
28
|
+
VALUE rb_cglm_aabb_merge(int argc, VALUE *argv, VALUE self) {
|
29
|
+
VALUE other, dest;
|
30
|
+
rb_scan_args(argc, argv, "11", &other, &dest);
|
31
|
+
if (NIL_P(dest)) dest = AABB_NEW(ALLOC_AABB);
|
32
|
+
aabb *a, *b, *out;
|
33
|
+
a = &VAL2AABB(self);
|
34
|
+
b = &VAL2AABB(other);
|
35
|
+
out = &VAL2AABB(dest);
|
36
|
+
glm_aabb_merge(a->corners, b->corners, out->corners);
|
37
|
+
return dest;
|
38
|
+
}
|
39
|
+
|
40
|
+
/* call-seq: crop(crop[, dest]) => dest | new AABB
|
41
|
+
*
|
42
|
+
* Crops this AABB by `crop`, placing the result in `dest` or creating a new
|
43
|
+
* one. Returns `dest`.
|
44
|
+
*
|
45
|
+
* This could be useful for gettng an AABB which fits with view frustum and
|
46
|
+
* object bounding boxes. In this case you crop view frustum box with object's
|
47
|
+
* box.
|
48
|
+
*/
|
49
|
+
VALUE rb_cglm_aabb_crop(int argc, VALUE *argv, VALUE self) {
|
50
|
+
VALUE other, dest;
|
51
|
+
rb_scan_args(argc, argv, "11", &other, &dest);
|
52
|
+
if (NIL_P(dest)) dest = AABB_NEW(ALLOC_AABB);
|
53
|
+
aabb *a, *b, *out;
|
54
|
+
a = &VAL2AABB(self);
|
55
|
+
b = &VAL2AABB(other);
|
56
|
+
out = &VAL2AABB(dest);
|
57
|
+
glm_aabb_crop(a->corners, b->corners, out->corners);
|
58
|
+
return dest;
|
59
|
+
}
|
60
|
+
|
61
|
+
/* call-seq: crop_until(crop, clamp[, dest]) => dest | new AABB
|
62
|
+
*
|
63
|
+
* Crops this AABB by `crop`, placing the result in `dest` or creating a new
|
64
|
+
* one. Returns `dest`. If the result would be smaller than `clamp`, it is
|
65
|
+
* restricted to the extents of `clamp` instead.
|
66
|
+
*
|
67
|
+
* This could be useful for gettng a bbox which fits with view frustum and
|
68
|
+
* object bounding boxes. In this case you crop view frustum box with objects
|
69
|
+
* box.
|
70
|
+
*/
|
71
|
+
VALUE rb_cglm_aabb_crop_until(int argc, VALUE *argv, VALUE self) {
|
72
|
+
VALUE other, clamp, dest;
|
73
|
+
rb_scan_args(argc, argv, "21", &other, &clamp, &dest);
|
74
|
+
if (NIL_P(dest)) dest = AABB_NEW(ALLOC_AABB);
|
75
|
+
aabb *a, *b, *c, *out;
|
76
|
+
a = &VAL2AABB(self);
|
77
|
+
b = &VAL2AABB(other);
|
78
|
+
c = &VAL2AABB(clamp);
|
79
|
+
out = &VAL2AABB(dest);
|
80
|
+
glm_aabb_crop_until(a->corners, b->corners, c->corners, out->corners);
|
81
|
+
return dest;
|
82
|
+
}
|
83
|
+
|
84
|
+
/* call-seq: intersects_frustum?(frustum) => true|false
|
85
|
+
*
|
86
|
+
* Returns true if this AABB intersects the given Frustum, false otherwise.
|
87
|
+
*/
|
88
|
+
VALUE rb_cglm_aabb_intersect_frustum(VALUE self, VALUE frstm) {
|
89
|
+
aabb *a;
|
90
|
+
frustum *f;
|
91
|
+
a = &VAL2AABB(self);
|
92
|
+
f = &VAL2FRUSTUM(frstm);
|
93
|
+
return glm_aabb_frustum(a->corners, f->planes) ? Qtrue : Qfalse;
|
94
|
+
}
|
95
|
+
|
96
|
+
/* call-seq: invalidate => self
|
97
|
+
*
|
98
|
+
* Invalidates the AABB min and max values.
|
99
|
+
*/
|
100
|
+
VALUE rb_cglm_aabb_invalidate_self(VALUE self) {
|
101
|
+
aabb *a;
|
102
|
+
a = &VAL2AABB(self);
|
103
|
+
glm_aabb_invalidate(a->corners);
|
104
|
+
return self;
|
105
|
+
}
|
106
|
+
|
107
|
+
/* call-seq: valid? => true|false
|
108
|
+
*
|
109
|
+
* Returns true if this AABB is valid, false otherwise.
|
110
|
+
*/
|
111
|
+
VALUE rb_cglm_aabb_is_valid(VALUE self) {
|
112
|
+
aabb *a;
|
113
|
+
a = &VAL2AABB(self);
|
114
|
+
glm_aabb_isvalid(a->corners);
|
115
|
+
return self;
|
116
|
+
}
|
117
|
+
|
118
|
+
/* call-seq: size => number
|
119
|
+
*
|
120
|
+
* Returns the length of the diagonal line between the corners of this AABB.
|
121
|
+
*/
|
122
|
+
VALUE rb_cglm_aabb_size(VALUE self) {
|
123
|
+
aabb *a;
|
124
|
+
a = &VAL2AABB(self);
|
125
|
+
return DBL2NUM(glm_aabb_size(a->corners));
|
126
|
+
}
|
127
|
+
|
128
|
+
/* call-seq: radius => number
|
129
|
+
*
|
130
|
+
* Returns the radius of a sphere which surrounds this AABB.
|
131
|
+
*/
|
132
|
+
VALUE rb_cglm_aabb_radius(VALUE self) {
|
133
|
+
aabb *a;
|
134
|
+
a = &VAL2AABB(self);
|
135
|
+
return DBL2NUM(glm_aabb_radius(a->corners));
|
136
|
+
}
|
137
|
+
|
138
|
+
/* call-seq: center([dest]) => dest | new Vec3
|
139
|
+
*
|
140
|
+
* Computes the center point of the AABB and places it into the Vec3 `dest`,
|
141
|
+
* creating a new one if `dest` is omitted.
|
142
|
+
*/
|
143
|
+
VALUE rb_cglm_aabb_center(int argc, VALUE *argv, VALUE self) {
|
144
|
+
VALUE dest;
|
145
|
+
rb_scan_args(argc, argv, "01", &dest);
|
146
|
+
if (NIL_P(dest)) dest = VEC3_NEW(ALLOC_VEC3);
|
147
|
+
aabb *a;
|
148
|
+
vec3 *b;
|
149
|
+
a = &VAL2AABB(self);
|
150
|
+
b = &VAL2VEC3(dest);
|
151
|
+
glm_aabb_center(a->corners, *b);
|
152
|
+
return dest;
|
153
|
+
}
|
154
|
+
|
155
|
+
/* call-seq: intersects_aabb?(aabb) => true|false
|
156
|
+
*
|
157
|
+
* Returns true if the two AABB's overlap, false otherwise.
|
158
|
+
*/
|
159
|
+
VALUE rb_cglm_aabb_intersect_aabb(VALUE self, VALUE other) {
|
160
|
+
aabb *a, *b;
|
161
|
+
a = &VAL2AABB(self);
|
162
|
+
b = &VAL2AABB(other);
|
163
|
+
return glm_aabb_aabb(a->corners, b->corners) ? Qtrue : Qfalse;
|
164
|
+
}
|
165
|
+
|
166
|
+
/* call-seq: intersects_sphere?(vec4) => true|false
|
167
|
+
*
|
168
|
+
* Returns true if the sphere described by the given Vec4 intersects this
|
169
|
+
* AABB, false otherwise.
|
170
|
+
*/
|
171
|
+
VALUE rb_cglm_aabb_intersect_sphere(VALUE self, VALUE sphere) {
|
172
|
+
aabb *a;
|
173
|
+
vec4 *b;
|
174
|
+
a = &VAL2AABB(self);
|
175
|
+
b = &VAL2VEC4(sphere);
|
176
|
+
return glm_aabb_sphere(a->corners, *b) ? Qtrue : Qfalse;
|
177
|
+
}
|
178
|
+
|
179
|
+
/* call-seq: contains_point?(vec3) => true|false
|
180
|
+
*
|
181
|
+
* Returns true if this AABB contains the specified point (inclusive), false
|
182
|
+
* otherwise.
|
183
|
+
*/
|
184
|
+
VALUE rb_cglm_aabb_contains_point(VALUE self, VALUE point) {
|
185
|
+
aabb *a;
|
186
|
+
vec3 *b;
|
187
|
+
a = &VAL2AABB(self);
|
188
|
+
b = &VAL2VEC3(point);
|
189
|
+
return glm_aabb_point(a->corners, *b) ? Qtrue : Qfalse;
|
190
|
+
}
|
191
|
+
|
192
|
+
/* call-seq: contains_aabb?(aabb) => true|false
|
193
|
+
*
|
194
|
+
* Returns true if this AABB contains the specified AABB, false otherwise.
|
195
|
+
*/
|
196
|
+
VALUE rb_cglm_aabb_contains_aabb(VALUE self, VALUE other) {
|
197
|
+
aabb *a, *b;
|
198
|
+
a = &VAL2AABB(self);
|
199
|
+
b = &VAL2AABB(other);
|
200
|
+
return glm_aabb_contains(a->corners, b->corners) ? Qtrue : Qfalse;
|
201
|
+
}
|
202
|
+
|
203
|
+
VALUE rb_cglm_aabb_aref(VALUE self, VALUE corner_index) {
|
204
|
+
CHECK_RANGE(corner_index, 0, 1);
|
205
|
+
return VEC3_NEW(VAL2AABB(self).corners[NUM2INT(corner_index)]);
|
206
|
+
}
|
207
|
+
|
208
|
+
VALUE rb_cglm_aabb_aset(VALUE self, VALUE index, VALUE val) {
|
209
|
+
CHECK_RANGE(index, 0, 1);
|
210
|
+
memcpy(VAL2AABB(self).corners[NUM2INT(index)], VAL2VEC3(val), sizeof(vec3));
|
211
|
+
return self;
|
212
|
+
}
|
213
|
+
|
214
|
+
VALUE rb_cglm_aabb_size_bytes(VALUE klass) { return SIZET2NUM(aabb_size()); }
|
215
|
+
|
216
|
+
VALUE rb_cglm_aabb_alignment_bytes(VALUE klass) { return SIZET2NUM(AABB_ALIGNMENT); }
|
217
|
+
|
218
|
+
VALUE rb_cglm_aabb_equals_aabb(VALUE self, VALUE other) {
|
219
|
+
if (memcmp(&VAL2AABB(self), &VAL2AABB(other), sizeof(aabb))) return Qfalse;
|
220
|
+
return Qtrue;
|
221
|
+
}
|
222
|
+
|
223
|
+
/* call-seq: a =~ b => true|false
|
224
|
+
*
|
225
|
+
* Returns true if each member of `a` is very close to, but not necessarily
|
226
|
+
* exactly equal to, each corresponding member of `b`. This is useful in many
|
227
|
+
* circumstances because imprecision introduced by floating point calculations
|
228
|
+
* can lead to two expressions which are otherwise mathematically equivalent
|
229
|
+
* returning false.
|
230
|
+
*/
|
231
|
+
VALUE rb_cglm_aabb_equalish_aabb(int argc, VALUE *argv, VALUE self) {
|
232
|
+
VALUE other, epsilon;
|
233
|
+
float feps = FLT_EPSILON;
|
234
|
+
rb_scan_args(argc, argv, "11", &other, &epsilon);
|
235
|
+
if (!NIL_P(epsilon)) feps = NUM2FLT(epsilon);
|
236
|
+
aabb *a = &VAL2AABB(self);
|
237
|
+
aabb *b = &VAL2AABB(other);
|
238
|
+
for (int i = 0; i < 2; i++) {
|
239
|
+
for (int j = 0; j < 3; j++) {
|
240
|
+
if (fabsf((*a).corners[i][j] - (*b).corners[i][j]) > feps)
|
241
|
+
return Qfalse;
|
242
|
+
}
|
243
|
+
}
|
244
|
+
return Qtrue;
|
245
|
+
}
|
246
|
+
|
247
|
+
void Init_cglm_box() {
|
248
|
+
rb_define_method(rb_cAABB, "==", rb_cglm_aabb_equals_aabb, 1);
|
249
|
+
rb_define_method(rb_cAABB, "equalish", rb_cglm_aabb_equalish_aabb, -1);
|
250
|
+
rb_define_method(rb_cAABB, "transform", rb_cglm_aabb_transform, -1);
|
251
|
+
rb_define_method(rb_cAABB, "merge", rb_cglm_aabb_merge, -1);
|
252
|
+
rb_define_method(rb_cAABB, "crop", rb_cglm_aabb_crop, -1);
|
253
|
+
rb_define_method(rb_cAABB, "crop_until", rb_cglm_aabb_crop_until, -1);
|
254
|
+
rb_define_method(rb_cAABB, "intersects_frustum?", rb_cglm_aabb_intersect_frustum, 1);
|
255
|
+
rb_define_method(rb_cAABB, "invalidate!", rb_cglm_aabb_invalidate_self, 0);
|
256
|
+
rb_define_method(rb_cAABB, "valid?", rb_cglm_aabb_is_valid, 0);
|
257
|
+
rb_define_method(rb_cAABB, "size", rb_cglm_aabb_size, 0);
|
258
|
+
rb_define_method(rb_cAABB, "radius", rb_cglm_aabb_radius, 0);
|
259
|
+
rb_define_method(rb_cAABB, "center", rb_cglm_aabb_center, -1);
|
260
|
+
rb_define_method(rb_cAABB, "intersects_aabb?", rb_cglm_aabb_intersect_aabb, 1);
|
261
|
+
rb_define_method(rb_cAABB, "intersects_sphere?", rb_cglm_aabb_intersect_sphere, 1);
|
262
|
+
rb_define_method(rb_cAABB, "contains_point?", rb_cglm_aabb_contains_point, 1);
|
263
|
+
rb_define_method(rb_cAABB, "contains_aabb?", rb_cglm_aabb_contains_aabb, 1);
|
264
|
+
rb_define_method(rb_cAABB, "[]", rb_cglm_aabb_aref, 1);
|
265
|
+
rb_define_method(rb_cAABB, "[]=", rb_cglm_aabb_aset, 2);
|
266
|
+
|
267
|
+
rb_define_alias(rb_cAABB, "=~", "equalish");
|
268
|
+
|
269
|
+
rb_define_singleton_method(rb_cAABB, "size", rb_cglm_aabb_size_bytes, 0);
|
270
|
+
rb_define_singleton_method(rb_cAABB, "alignment", rb_cglm_aabb_alignment_bytes, 0);
|
271
|
+
}
|
@@ -0,0 +1,325 @@
|
|
1
|
+
#include "rb_cglm.h"
|
2
|
+
|
3
|
+
/*
|
4
|
+
* call-seq: affine_mul_rot(m[, dest]) => dest | new Mat4
|
5
|
+
*
|
6
|
+
* This is similar to #mul but specialized to affine transform.
|
7
|
+
*
|
8
|
+
* Right Matrix format should be:
|
9
|
+
*
|
10
|
+
* R R R 0
|
11
|
+
* R R R 0
|
12
|
+
* R R R 0
|
13
|
+
* 0 0 0 1
|
14
|
+
*
|
15
|
+
* This reduces some multiplications. It should be faster than #mul.
|
16
|
+
* if you are not sure about matrix format then DON'T use this! use #mul.
|
17
|
+
*
|
18
|
+
* * `m` is the second affine Mat4 to multiply `self` against.
|
19
|
+
* * `dest` is the out Mat4 to place the result in, and will be allocated if
|
20
|
+
* omitted.
|
21
|
+
*
|
22
|
+
*/
|
23
|
+
VALUE rb_cglm_affine_mul_rot(int argc, VALUE *argv, VALUE self) {
|
24
|
+
VALUE m_v, dest_v;
|
25
|
+
rb_scan_args(argc, argv, "11", &m_v, &dest_v);
|
26
|
+
if (NIL_P(dest_v)) dest_v = MAT4_NEW(ALLOC_MAT4);
|
27
|
+
|
28
|
+
mat4 *m1 = NULL, *m2 = NULL, *dest = NULL;
|
29
|
+
m1 = &VAL2MAT4(self);
|
30
|
+
m2 = &VAL2MAT4(m_v);
|
31
|
+
dest = &VAL2MAT4(dest_v);
|
32
|
+
glm_mul_rot(*m1, *m2, *dest);
|
33
|
+
return dest_v;
|
34
|
+
}
|
35
|
+
|
36
|
+
/*
|
37
|
+
* call-seq: inv_tr() => self
|
38
|
+
*
|
39
|
+
* inverse orthonormal rotation + translation matrix (ridgid-body)
|
40
|
+
*
|
41
|
+
* X = | R T | X' = | R' -R'T |
|
42
|
+
* | 0 1 | | 0 1 |
|
43
|
+
*
|
44
|
+
*/
|
45
|
+
VALUE rb_cglm_affine_inv_tr(VALUE mat) {
|
46
|
+
mat4 *m = NULL;
|
47
|
+
m = &VAL2MAT4(mat);
|
48
|
+
glm_inv_tr(*m);
|
49
|
+
return mat;
|
50
|
+
}
|
51
|
+
|
52
|
+
/*
|
53
|
+
* call-seq: affine_mul(m[, dest]) => dest | new Mat4
|
54
|
+
*
|
55
|
+
* This is similar to #mul but specialized to affine transform.
|
56
|
+
*
|
57
|
+
* Right Matrix format should be:
|
58
|
+
*
|
59
|
+
* R R R X
|
60
|
+
* R R R Y
|
61
|
+
* R R R Z
|
62
|
+
* 0 0 0 W
|
63
|
+
*
|
64
|
+
* This reduces some multiplications. It should be faster than #mul.
|
65
|
+
* if you are not sure about matrix format then DON'T use this! use #mul.
|
66
|
+
*
|
67
|
+
* * `m` is the second affine Mat4 to multiply `self` against.
|
68
|
+
* * `dest` is the out Mat4 to place the result in, and will be allocated if
|
69
|
+
* omitted.
|
70
|
+
*
|
71
|
+
*/
|
72
|
+
VALUE rb_cglm_affine_mul(int argc, VALUE *argv, VALUE self) {
|
73
|
+
VALUE m_v, dest_v;
|
74
|
+
rb_scan_args(argc, argv, "11", &m_v, &dest_v);
|
75
|
+
if (NIL_P(dest_v)) dest_v = MAT4_NEW(ALLOC_MAT4);
|
76
|
+
mat4 *m1 = NULL, *m2 = NULL, *dest = NULL;
|
77
|
+
m1 = &VAL2MAT4(self);
|
78
|
+
m2 = &VAL2MAT4(m_v);
|
79
|
+
dest = &VAL2MAT4(dest_v);
|
80
|
+
glm_mul(*m1, *m2, *dest);
|
81
|
+
return dest_v;
|
82
|
+
}
|
83
|
+
|
84
|
+
/* call-seq: translate(vec3[, dest]) => dest | new Mat4 */
|
85
|
+
VALUE rb_cglm_translate(int argc, VALUE *argv, VALUE self) {
|
86
|
+
VALUE vec_v, dest_v;
|
87
|
+
rb_scan_args(argc, argv, "11", &vec_v, &dest_v);
|
88
|
+
if (NIL_P(dest_v)) dest_v = MAT4_NEW(ALLOC_MAT4);
|
89
|
+
mat4 *m1 = NULL, *dest = NULL;
|
90
|
+
vec3 *vec = NULL;
|
91
|
+
m1 = &VAL2MAT4(self);
|
92
|
+
vec = &VAL2VEC3(vec_v);
|
93
|
+
dest = &VAL2MAT4(dest_v);
|
94
|
+
glm_translate_to(*m1, *vec, *dest);
|
95
|
+
return dest_v;
|
96
|
+
}
|
97
|
+
|
98
|
+
/* call-seq: translate!(vec3) => self */
|
99
|
+
VALUE rb_cglm_translate_self(VALUE self, VALUE vec_v) {
|
100
|
+
mat4 *m1 = NULL;
|
101
|
+
vec3 *vec = NULL;
|
102
|
+
m1 = &VAL2MAT4(self);
|
103
|
+
vec = &VAL2VEC3(vec_v);
|
104
|
+
glm_translate(*m1, *vec);
|
105
|
+
return self;
|
106
|
+
}
|
107
|
+
|
108
|
+
/* call-seq: translate_x!(float) => self */
|
109
|
+
VALUE rb_cglm_translate_x_self(VALUE self, VALUE flt) {
|
110
|
+
mat4 *m1 = NULL;
|
111
|
+
m1 = &VAL2MAT4(self);
|
112
|
+
glm_translate_x(*m1, (float) NUM2DBL(flt));
|
113
|
+
return self;
|
114
|
+
}
|
115
|
+
|
116
|
+
/* call-seq: mat4.translate_y!(float) => mat4 */
|
117
|
+
VALUE rb_cglm_translate_y_self(VALUE self, VALUE flt) {
|
118
|
+
mat4 *m1 = NULL;
|
119
|
+
m1 = &VAL2MAT4(self);
|
120
|
+
glm_translate_y(*m1, (float) NUM2DBL(flt));
|
121
|
+
return self;
|
122
|
+
}
|
123
|
+
|
124
|
+
/* call-seq: translate_z!(float) => self */
|
125
|
+
VALUE rb_cglm_translate_z_self(VALUE self, VALUE flt) {
|
126
|
+
mat4 *m1 = NULL;
|
127
|
+
m1 = &VAL2MAT4(self);
|
128
|
+
glm_translate_z(*m1, (float) NUM2DBL(flt));
|
129
|
+
return self;
|
130
|
+
}
|
131
|
+
|
132
|
+
/* call-seq: translate(vec3) => new Mat4 */
|
133
|
+
VALUE rb_cglm_translate_new(VALUE klass, VALUE vec_v) {
|
134
|
+
VALUE dest = MAT4_NEW(ALLOC_MAT4);
|
135
|
+
glm_translate_make(VAL2MAT4(dest), VAL2VEC3(vec_v));
|
136
|
+
return dest;
|
137
|
+
}
|
138
|
+
|
139
|
+
/* call-seq: scale(vec3) => new Mat4 */
|
140
|
+
VALUE rb_cglm_scale_new(VALUE klass, VALUE vec_v) {
|
141
|
+
VALUE dest = MAT4_NEW(ALLOC_MAT4);
|
142
|
+
glm_scale_make(VAL2MAT4(dest), VAL2VEC3(vec_v));
|
143
|
+
return dest;
|
144
|
+
}
|
145
|
+
|
146
|
+
/* call-seq: rotate(axis, angle) => new Mat4 */
|
147
|
+
VALUE rb_cglm_rotate_new(VALUE klass, VALUE axis, VALUE angle) {
|
148
|
+
VALUE dest = MAT4_NEW(ALLOC_MAT4);
|
149
|
+
glm_rotate_make(VAL2MAT4(dest), (float) NUM2DBL(angle), VAL2VEC3(axis));
|
150
|
+
return dest;
|
151
|
+
}
|
152
|
+
|
153
|
+
/* call-seq: scale(vec3|float[, dest]) => dest | new Mat4 */
|
154
|
+
VALUE rb_cglm_scale(int argc, VALUE *argv, VALUE self) {
|
155
|
+
VALUE factor, dest;
|
156
|
+
rb_scan_args(argc, argv, "11", &factor, &dest);
|
157
|
+
if (NIL_P(dest)) dest = MAT4_NEW(ALLOC_MAT4);
|
158
|
+
|
159
|
+
if (RB_FLOAT_TYPE_P(factor) || RB_INTEGER_TYPE_P(factor)) {
|
160
|
+
memcpy(&VAL2MAT4(dest), &VAL2MAT4(self), sizeof(mat4));
|
161
|
+
glm_scale_uni(VAL2MAT4(dest), (float) NUM2DBL(factor));
|
162
|
+
} else {
|
163
|
+
glm_scale_to(VAL2MAT4(self), VAL2VEC3(factor), VAL2MAT4(dest));
|
164
|
+
}
|
165
|
+
|
166
|
+
return dest;
|
167
|
+
}
|
168
|
+
|
169
|
+
/* call-seq: scale!(vec3|float) => self */
|
170
|
+
VALUE rb_cglm_scale_self(VALUE self, VALUE factor) {
|
171
|
+
mat4 *m1 = NULL;
|
172
|
+
m1 = &VAL2MAT4(self);
|
173
|
+
if (RB_FLOAT_TYPE_P(factor) || RB_INTEGER_TYPE_P(factor)) {
|
174
|
+
glm_scale_uni(*m1, (float) NUM2DBL(factor));
|
175
|
+
} else {
|
176
|
+
vec3 *vec = NULL;
|
177
|
+
vec = &VAL2VEC3(factor);
|
178
|
+
glm_scale(*m1, *vec);
|
179
|
+
}
|
180
|
+
return self;
|
181
|
+
}
|
182
|
+
|
183
|
+
/* call-seq: rotate_x(float[, dest]) => dest | new Mat4 */
|
184
|
+
VALUE rb_cglm_rotate_x(int argc, VALUE *argv, VALUE self) {
|
185
|
+
VALUE angle, dest;
|
186
|
+
rb_scan_args(argc, argv, "11", &angle, &dest);
|
187
|
+
if (NIL_P(dest)) dest = MAT4_NEW(ALLOC_MAT4);
|
188
|
+
mat4 *m1, *m2;
|
189
|
+
m1 = &VAL2MAT4(self);
|
190
|
+
m2 = &VAL2MAT4(dest);
|
191
|
+
glm_rotate_x(*m1, (float) NUM2DBL(angle), *m2);
|
192
|
+
return dest;
|
193
|
+
}
|
194
|
+
|
195
|
+
/* call-seq: rotate_y(float[, dest]) => dest | new Mat4 */
|
196
|
+
VALUE rb_cglm_rotate_y(int argc, VALUE *argv, VALUE self) {
|
197
|
+
VALUE angle, dest;
|
198
|
+
rb_scan_args(argc, argv, "11", &angle, &dest);
|
199
|
+
if (NIL_P(dest)) dest = MAT4_NEW(ALLOC_MAT4);
|
200
|
+
mat4 *m1, *m2;
|
201
|
+
m1 = &VAL2MAT4(self);
|
202
|
+
m2 = &VAL2MAT4(dest);
|
203
|
+
glm_rotate_y(*m1, (float) NUM2DBL(angle), *m2);
|
204
|
+
return dest;
|
205
|
+
}
|
206
|
+
|
207
|
+
/* call-seq: rotate_z(float[, dest]) => dest | new Mat4 */
|
208
|
+
VALUE rb_cglm_rotate_z(int argc, VALUE *argv, VALUE self) {
|
209
|
+
VALUE angle, dest;
|
210
|
+
rb_scan_args(argc, argv, "11", &angle, &dest);
|
211
|
+
if (NIL_P(dest)) dest = MAT4_NEW(ALLOC_MAT4);
|
212
|
+
mat4 *m1, *m2;
|
213
|
+
m1 = &VAL2MAT4(self);
|
214
|
+
m2 = &VAL2MAT4(dest);
|
215
|
+
glm_rotate_z(*m1, (float) NUM2DBL(angle), *m2);
|
216
|
+
return dest;
|
217
|
+
}
|
218
|
+
|
219
|
+
/* call-seq: rotate!(axis, angle) => self */
|
220
|
+
VALUE rb_cglm_rotate_self(VALUE self, VALUE axis, VALUE angle) {
|
221
|
+
mat4 *mat;
|
222
|
+
vec3 *vec;
|
223
|
+
mat = &VAL2MAT4(self);
|
224
|
+
vec = &VAL2VEC3(axis);
|
225
|
+
glm_rotate(*mat, (float) NUM2DBL(angle), *vec);
|
226
|
+
return self;
|
227
|
+
}
|
228
|
+
|
229
|
+
/* call-seq: rotate_at!(pivot_point, axis, angle) => self */
|
230
|
+
VALUE rb_cglm_rotate_self_at(VALUE self, VALUE pivot, VALUE axis, VALUE angle) {
|
231
|
+
mat4 *m;
|
232
|
+
vec3 *v1, *v2;
|
233
|
+
m = &VAL2MAT4(self);
|
234
|
+
v1 = &VAL2VEC3(pivot);
|
235
|
+
v2 = &VAL2VEC3(axis);
|
236
|
+
glm_rotate_at(*m, *v1, (float) NUM2DBL(angle), *v2);
|
237
|
+
return self;
|
238
|
+
}
|
239
|
+
|
240
|
+
/* call-seq: axis_angle_rotate_at(pivot_point, axis, angle) => new Mat4 */
|
241
|
+
VALUE rb_cglm_rotate_at_new(VALUE klass, VALUE pivot, VALUE axis, VALUE angle) {
|
242
|
+
VALUE self = MAT4_NEW(ALLOC_MAT4);
|
243
|
+
mat4 *m;
|
244
|
+
vec3 *v1, *v2;
|
245
|
+
m = &VAL2MAT4(self);
|
246
|
+
v1 = &VAL2VEC3(pivot);
|
247
|
+
v2 = &VAL2VEC3(axis);
|
248
|
+
glm_rotate_atm(*m, *v1, (float) NUM2DBL(angle), *v2);
|
249
|
+
return self;
|
250
|
+
}
|
251
|
+
|
252
|
+
/* call-seq: decompose_scale(vec3) => vec3 */
|
253
|
+
VALUE rb_cglm_decompose_scale(VALUE self, VALUE out) {
|
254
|
+
mat4 *m;
|
255
|
+
vec3 *v;
|
256
|
+
m = &VAL2MAT4(self);
|
257
|
+
v = &VAL2VEC3(self);
|
258
|
+
glm_decompose_scalev(*m, *v);
|
259
|
+
return out;
|
260
|
+
}
|
261
|
+
|
262
|
+
/* call-seq: uniform_scale? => true|false */
|
263
|
+
VALUE rb_cglm_is_uniform_scale(VALUE self) {
|
264
|
+
mat4 *m;
|
265
|
+
m = &VAL2MAT4(self);
|
266
|
+
return glm_uniscaled(*m) ? Qtrue : Qfalse;
|
267
|
+
}
|
268
|
+
|
269
|
+
/* call-seq: decompose_rs(r, s) => self
|
270
|
+
*
|
271
|
+
* Decomposes `self` into a rotation Mat4 `r` and scale Vec3 `s`.
|
272
|
+
*/
|
273
|
+
VALUE rb_cglm_decompose_rs(VALUE self, VALUE rot, VALUE scale) {
|
274
|
+
mat4 *m, *r;
|
275
|
+
vec3 *s;
|
276
|
+
m = &VAL2MAT4(self);
|
277
|
+
r = &VAL2MAT4(rot);
|
278
|
+
s = &VAL2VEC3(scale);
|
279
|
+
glm_decompose_rs(*m, *r, *s);
|
280
|
+
return self;
|
281
|
+
}
|
282
|
+
|
283
|
+
/* call-seq: decompose(t, r, s) => self
|
284
|
+
*
|
285
|
+
* Decomposes `self` into a translation Vec4 `t`, rotation Mat4 `r` and scale
|
286
|
+
* Vec3 `s`.
|
287
|
+
*/
|
288
|
+
VALUE rb_cglm_decompose(VALUE self, VALUE trans, VALUE rot, VALUE scale) {
|
289
|
+
mat4 *m, *r;
|
290
|
+
vec3 *s;
|
291
|
+
vec4 *t;
|
292
|
+
m = &VAL2MAT4(self);
|
293
|
+
t = &VAL2VEC4(trans);
|
294
|
+
r = &VAL2MAT4(rot);
|
295
|
+
s = &VAL2VEC3(scale);
|
296
|
+
glm_decompose(*m, *t, *r, *s);
|
297
|
+
return self;
|
298
|
+
}
|
299
|
+
|
300
|
+
void Init_cglm_affine() {
|
301
|
+
rb_define_method(rb_cMat4, "affine_inv_tr", rb_cglm_affine_inv_tr, 0);
|
302
|
+
rb_define_method(rb_cMat4, "affine_mul_rot", rb_cglm_affine_mul_rot, -1);
|
303
|
+
rb_define_method(rb_cMat4, "affine_mul", rb_cglm_affine_mul, -1);
|
304
|
+
rb_define_method(rb_cMat4, "translate_to", rb_cglm_translate, -1);
|
305
|
+
rb_define_method(rb_cMat4, "translate!", rb_cglm_translate_self, 1);
|
306
|
+
rb_define_method(rb_cMat4, "translate_x!", rb_cglm_translate_x_self, 1);
|
307
|
+
rb_define_method(rb_cMat4, "translate_y!", rb_cglm_translate_y_self, 1);
|
308
|
+
rb_define_method(rb_cMat4, "translate_z!", rb_cglm_translate_z_self, 1);
|
309
|
+
rb_define_method(rb_cMat4, "scale", rb_cglm_scale, -1);
|
310
|
+
rb_define_method(rb_cMat4, "scale!", rb_cglm_scale_self, 1);
|
311
|
+
rb_define_method(rb_cMat4, "rotate_x", rb_cglm_rotate_x, -1);
|
312
|
+
rb_define_method(rb_cMat4, "rotate_y", rb_cglm_rotate_y, -1);
|
313
|
+
rb_define_method(rb_cMat4, "rotate_z", rb_cglm_rotate_z, -1);
|
314
|
+
rb_define_method(rb_cMat4, "rotate!", rb_cglm_rotate_self, 2);
|
315
|
+
rb_define_method(rb_cMat4, "rotate_at!", rb_cglm_rotate_self_at, 3);
|
316
|
+
rb_define_method(rb_cMat4, "decompose_scale",rb_cglm_decompose_scale, 1);
|
317
|
+
rb_define_method(rb_cMat4, "uniform_scale?", rb_cglm_is_uniform_scale, 0);
|
318
|
+
rb_define_method(rb_cMat4, "decompose_rs", rb_cglm_decompose_rs, 2);
|
319
|
+
rb_define_method(rb_cMat4, "decompose", rb_cglm_decompose, 3);
|
320
|
+
|
321
|
+
rb_define_singleton_method(rb_cMat4, "translate", rb_cglm_translate_new, 1);
|
322
|
+
rb_define_singleton_method(rb_cMat4, "scale", rb_cglm_scale_new, 1);
|
323
|
+
rb_define_singleton_method(rb_cMat4, "rotate", rb_cglm_rotate_new, 2);
|
324
|
+
rb_define_singleton_method(rb_cMat4, "axis_angle_rotate_at", rb_cglm_rotate_at_new, 3);
|
325
|
+
}
|