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,308 @@
|
|
1
|
+
#include "rb_cglm.h"
|
2
|
+
|
3
|
+
/* call-seq: identity([dest]) => dest | new Mat4
|
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 Mat4 is returned.
|
7
|
+
*/
|
8
|
+
VALUE rb_cglm_mat4_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 = MAT4_NEW(ALLOC_MAT4);
|
12
|
+
glm_mat4_identity(VAL2MAT4(dest));
|
13
|
+
return dest;
|
14
|
+
}
|
15
|
+
|
16
|
+
/* call-seq: quat_rotate_at(quat, pivot_point[, dest]) => dest | new Mat4
|
17
|
+
*
|
18
|
+
* Creates a new transformation matrix using the quaternion at the pivot
|
19
|
+
* point. Places the result into `dest`, or creates a new Mat4 if `dest` is
|
20
|
+
* omitted. Returns `dest`.
|
21
|
+
*/
|
22
|
+
VALUE rb_cglm_mat4_new_rotate_at(int argc, VALUE *argv, VALUE self) {
|
23
|
+
VALUE q, pivot, dest;
|
24
|
+
rb_scan_args(argc, argv, "21", &q, &pivot, &dest);
|
25
|
+
if (NIL_P(dest)) dest = MAT4_NEW(ALLOC_MAT4);
|
26
|
+
glm_quat_rotate_atm(VAL2MAT4(dest), VAL2QUAT(q), VAL2VEC3(pivot));
|
27
|
+
return dest;
|
28
|
+
}
|
29
|
+
|
30
|
+
VALUE rb_cglm_mat4_aref(VALUE self, VALUE index) {
|
31
|
+
CHECK_RANGE(index, 0, 3);
|
32
|
+
float *addr = (float *) VAL2MAT4(self);
|
33
|
+
return VEC4_NEW(addr + (NUM2INT(index) * 4));
|
34
|
+
}
|
35
|
+
|
36
|
+
VALUE rb_cglm_mat4_aset(VALUE self, VALUE index, VALUE val) {
|
37
|
+
CHECK_RANGE(index, 0, 3);
|
38
|
+
if (rb_funcall(val, rb_intern("kind_of?"), 1, rb_cVec4))
|
39
|
+
memcpy(&(VAL2MAT4(self)[NUM2INT(index)]), &VAL2VEC4(val), sizeof(vec4));
|
40
|
+
else if (rb_funcall(val, rb_intern("kind_of?"), 1, rb_cVec3))
|
41
|
+
memcpy(&(VAL2MAT4(self)[NUM2INT(index)]), &VAL2VEC3(val), sizeof(vec3));
|
42
|
+
else {
|
43
|
+
VALUE row = rb_cglm_mat4_aref(self, index);
|
44
|
+
for (int i = 0; i < 4; i++) {
|
45
|
+
VALUE v = rb_funcall(val, rb_intern("[]"), 1, INT2NUM(i));
|
46
|
+
if (!NIL_P(v)) {
|
47
|
+
rb_funcall(row, rb_intern("[]="), 2, INT2NUM(i), v);
|
48
|
+
}
|
49
|
+
}
|
50
|
+
}
|
51
|
+
return self;
|
52
|
+
}
|
53
|
+
|
54
|
+
VALUE rb_cglm_mat4_to_mat3(int argc, VALUE *argv, VALUE self) {
|
55
|
+
VALUE dest;
|
56
|
+
if (argc == 0) dest = MAT3_NEW(ALLOC_MAT3);
|
57
|
+
else dest = argv[0];
|
58
|
+
glm_mat4_pick3(VAL2MAT4(self), VAL2MAT3(dest));
|
59
|
+
return dest;
|
60
|
+
}
|
61
|
+
|
62
|
+
VALUE rb_cglm_mat4_to_transposed_mat3(int argc, VALUE *argv, VALUE self) {
|
63
|
+
VALUE dest;
|
64
|
+
if (argc == 0) dest = MAT3_NEW(ALLOC_MAT3);
|
65
|
+
dest = argv[0];
|
66
|
+
glm_mat4_pick3t(VAL2MAT4(self), VAL2MAT3(dest));
|
67
|
+
return dest;
|
68
|
+
}
|
69
|
+
|
70
|
+
VALUE rb_cglm_mat4_mul_mat4(int argc, VALUE *argv, VALUE self) {
|
71
|
+
VALUE other, dest;
|
72
|
+
rb_scan_args(argc, argv, "11", &other, &dest);
|
73
|
+
if (NIL_P(dest)) dest = MAT4_NEW(ALLOC_MAT4);
|
74
|
+
glm_mat4_mul(VAL2MAT4(self), VAL2MAT4(other), VAL2MAT4(dest));
|
75
|
+
return dest;
|
76
|
+
}
|
77
|
+
|
78
|
+
VALUE rb_cglm_mat4_mul_vec4(int argc, VALUE *argv, VALUE self) {
|
79
|
+
VALUE other, dest;
|
80
|
+
rb_scan_args(argc, argv, "11", &other, &dest);
|
81
|
+
if (NIL_P(dest)) dest = VEC4_NEW(ALLOC_VEC4);
|
82
|
+
glm_mat4_mulv(VAL2MAT4(self), VAL2VEC4(other), VAL2VEC4(dest));
|
83
|
+
return dest;
|
84
|
+
}
|
85
|
+
|
86
|
+
VALUE rb_cglm_mat4_mul_vec3(int argc, VALUE *argv, VALUE self) {
|
87
|
+
VALUE other, last, dest;
|
88
|
+
rb_scan_args(argc, argv, "12", &other, &last, &dest);
|
89
|
+
if (NIL_P(last)) last = DBL2NUM(1.0);
|
90
|
+
if (NIL_P(dest)) dest = VEC3_NEW(ALLOC_VEC3);
|
91
|
+
glm_mat4_mulv3(VAL2MAT4(self), VAL2VEC3(other), NUM2FLT(last), VAL2VEC3(dest));
|
92
|
+
return dest;
|
93
|
+
}
|
94
|
+
|
95
|
+
VALUE rb_cglm_mat4_to_quat(int argc, VALUE *argv, VALUE self) {
|
96
|
+
VALUE dest;
|
97
|
+
rb_scan_args(argc, argv, "01", &dest);
|
98
|
+
if (NIL_P(dest)) dest = QUAT_NEW(ALLOC_QUAT);
|
99
|
+
glm_mat4_quat(VAL2MAT4(self), VAL2QUAT(dest));
|
100
|
+
return dest;
|
101
|
+
}
|
102
|
+
|
103
|
+
VALUE rb_cglm_mat4_transpose(int argc, VALUE *argv, VALUE self) {
|
104
|
+
VALUE dest;
|
105
|
+
rb_scan_args(argc, argv, "01", &dest);
|
106
|
+
if (NIL_P(dest)) dest = QUAT_NEW(ALLOC_QUAT);
|
107
|
+
glm_mat4_transpose_to(VAL2MAT4(self), VAL2MAT4(dest));
|
108
|
+
return dest;
|
109
|
+
}
|
110
|
+
|
111
|
+
VALUE rb_cglm_mat4_transpose_self(VALUE self) {
|
112
|
+
glm_mat4_transpose(VAL2MAT4(self));
|
113
|
+
return self;
|
114
|
+
}
|
115
|
+
|
116
|
+
/* call-seq: mul_scalar(scalar[, dest]) => dest | new Mat3
|
117
|
+
*
|
118
|
+
* Multiplies each element in this matrix by the specified scalar amount.
|
119
|
+
* Places the result in `dest` and returns it, creating a new Mat4 if `dest`
|
120
|
+
* is omitted.
|
121
|
+
*/
|
122
|
+
VALUE rb_cglm_mat4_mul_scalar(int argc, VALUE *argv, VALUE self) {
|
123
|
+
VALUE scalar, dest;
|
124
|
+
rb_scan_args(argc, argv, "11", &scalar, &dest);
|
125
|
+
if (NIL_P(dest)) dest = MAT4_NEW(ALLOC_MAT4);
|
126
|
+
memcpy(&VAL2MAT4(self), &VAL2MAT4(dest), sizeof(mat4));
|
127
|
+
glm_mat4_scale(VAL2MAT4(dest), NUM2FLT(scalar));
|
128
|
+
return dest;
|
129
|
+
}
|
130
|
+
|
131
|
+
/* call-seq: mul_scalar!(scalar) => self
|
132
|
+
*
|
133
|
+
* Multiplies each element in this matrix by the specified scalar amount,
|
134
|
+
* modifying `self` in-place and returning it.
|
135
|
+
*/
|
136
|
+
VALUE rb_cglm_mat4_mul_scalar_self(VALUE self, VALUE scalar) {
|
137
|
+
glm_mat4_scale(VAL2MAT4(self), NUM2FLT(scalar));
|
138
|
+
return self;
|
139
|
+
}
|
140
|
+
|
141
|
+
/* call-seq: determinant => Numeric
|
142
|
+
*/
|
143
|
+
VALUE rb_cglm_mat4_determinant(VALUE self) {
|
144
|
+
return DBL2NUM(glm_mat4_det(VAL2MAT4(self)));
|
145
|
+
}
|
146
|
+
|
147
|
+
/* call-seq: invert([dest]) => dest | new Mat4
|
148
|
+
*
|
149
|
+
* Computes the inverse of this matrix and stores it in `dest`, creating a
|
150
|
+
* new Mat4 if `dest` is omitted. Returns `dest`.
|
151
|
+
*/
|
152
|
+
VALUE rb_cglm_mat4_invert(int argc, VALUE *argv, VALUE self) {
|
153
|
+
VALUE dest;
|
154
|
+
rb_scan_args(argc, argv, "01", &dest);
|
155
|
+
if (NIL_P(dest)) dest = MAT4_NEW(ALLOC_MAT4);
|
156
|
+
glm_mat4_inv(VAL2MAT4(self), VAL2MAT4(dest));
|
157
|
+
return dest;
|
158
|
+
}
|
159
|
+
|
160
|
+
/* call-seq: invert! => self
|
161
|
+
*
|
162
|
+
* Computes the inverse of this matrix in-place and returns `self`.
|
163
|
+
*/
|
164
|
+
VALUE rb_cglm_mat4_invert_self(int argc, VALUE *argv, VALUE self) {
|
165
|
+
glm_mat4_inv(VAL2MAT4(self), VAL2MAT4(self));
|
166
|
+
return self;
|
167
|
+
}
|
168
|
+
|
169
|
+
/* call-seq: invert_fast([dest]) => dest | new Mat4
|
170
|
+
*
|
171
|
+
* Computes the inverse of this matrix and stores it in `dest`, creating a
|
172
|
+
* new Mat4 if `dest` is omitted. Returns `dest`.
|
173
|
+
*
|
174
|
+
* * NOTE: This method uses reciprocal approximation without extra corrections,
|
175
|
+
* e.g Newton-Raphson. This should work faster than normal, but will be less
|
176
|
+
* precise.
|
177
|
+
*/
|
178
|
+
VALUE rb_cglm_mat4_invert_fast(int argc, VALUE *argv, VALUE self) {
|
179
|
+
VALUE dest;
|
180
|
+
rb_scan_args(argc, argv, "01", &dest);
|
181
|
+
if (NIL_P(dest)) dest = MAT4_NEW(ALLOC_MAT4);
|
182
|
+
glm_mat4_inv_fast(VAL2MAT4(self), VAL2MAT4(dest));
|
183
|
+
return dest;
|
184
|
+
}
|
185
|
+
|
186
|
+
/* call-seq: invert_fast!([dest]) => dest | new Mat4
|
187
|
+
*
|
188
|
+
* Computes the inverse of this matrix in-place and returns `self`.
|
189
|
+
*
|
190
|
+
* * NOTE: This method uses reciprocal approximation without extra corrections,
|
191
|
+
* e.g Newton-Raphson. This should work faster than normal, but will be less
|
192
|
+
* precise.
|
193
|
+
*/
|
194
|
+
VALUE rb_cglm_mat4_invert_fast_self(int argc, VALUE *argv, VALUE self) {
|
195
|
+
glm_mat4_inv_fast(VAL2MAT4(self), VAL2MAT4(self));
|
196
|
+
return self;
|
197
|
+
}
|
198
|
+
|
199
|
+
/* call-seq: swap_col!(col1, col2) => self
|
200
|
+
*
|
201
|
+
* Swaps two matrix columns and returns `self`.
|
202
|
+
*/
|
203
|
+
VALUE rb_cglm_mat4_swap_col_self(VALUE self, VALUE col1, VALUE col2) {
|
204
|
+
glm_mat4_swap_col(VAL2MAT4(self), NUM2INT(col1), NUM2INT(col2));
|
205
|
+
return self;
|
206
|
+
}
|
207
|
+
|
208
|
+
/* call-seq: swap_row!(row1, row2) => self
|
209
|
+
*
|
210
|
+
* Swaps two matrix rows and returns `self`.
|
211
|
+
*/
|
212
|
+
VALUE rb_cglm_mat4_swap_row_self(VALUE self, VALUE row1, VALUE row2) {
|
213
|
+
glm_mat4_swap_row(VAL2MAT4(self), NUM2INT(row1), NUM2INT(row2));
|
214
|
+
return self;
|
215
|
+
}
|
216
|
+
|
217
|
+
VALUE rb_cglm_mat4_size_bytes(VALUE klass) { return SIZET2NUM(mat4_size()); }
|
218
|
+
|
219
|
+
VALUE rb_cglm_mat4_alignment_bytes(VALUE klass) { return SIZET2NUM(MAT4_ALIGNMENT); }
|
220
|
+
|
221
|
+
VALUE rb_cglm_mat4_equal(VALUE self, VALUE other) {
|
222
|
+
if (memcmp(&VAL2MAT4(self), &VAL2MAT4(other), sizeof(mat4))) return Qfalse;
|
223
|
+
return Qtrue;
|
224
|
+
}
|
225
|
+
|
226
|
+
/* call-seq: a =~ b => true|false
|
227
|
+
*
|
228
|
+
* Returns true if each member of `a` is very close to, but not necessarily
|
229
|
+
* exactly equal to, each corresponding member of `b`. This is useful in many
|
230
|
+
* circumstances because imprecision introduced by floating point calculations
|
231
|
+
* can lead to two expressions which are otherwise mathematically equivalent
|
232
|
+
* returning false.
|
233
|
+
*/
|
234
|
+
VALUE rb_cglm_mat4_equalish(int argc, VALUE *argv, VALUE self) {
|
235
|
+
VALUE other, epsilon;
|
236
|
+
float feps = FLT_EPSILON;
|
237
|
+
rb_scan_args(argc, argv, "11", &other, &epsilon);
|
238
|
+
if (!NIL_P(epsilon)) feps = NUM2FLT(epsilon);
|
239
|
+
mat4 *a = &VAL2MAT4(self);
|
240
|
+
mat4 *b = &VAL2MAT4(other);
|
241
|
+
for (int i = 0; i < 4; i++) {
|
242
|
+
for (int j = 0; j < 4; j++) {
|
243
|
+
if (fabsf((*a)[i][j] - (*b)[i][j]) > feps)
|
244
|
+
return Qfalse;
|
245
|
+
}
|
246
|
+
}
|
247
|
+
return Qtrue;
|
248
|
+
}
|
249
|
+
|
250
|
+
/* call-seq: random([dest]) => dest | new Mat4
|
251
|
+
*
|
252
|
+
* Fills `dest` or a new Mat4 with a random translation and rotation, and
|
253
|
+
* returns it.
|
254
|
+
*/
|
255
|
+
VALUE rb_cglm_mat4_new_random(int argc, VALUE *argv, VALUE self) {
|
256
|
+
VALUE dest;
|
257
|
+
rb_scan_args(argc, argv, "01", &dest);
|
258
|
+
if (NIL_P(dest)) dest = MAT4_NEW(ALLOC_MAT4);
|
259
|
+
|
260
|
+
glm_mat4_copy(GLM_MAT4_IDENTITY, VAL2MAT4(dest));
|
261
|
+
|
262
|
+
/* random position */
|
263
|
+
VAL2MAT4(dest)[3][0] = drand48();
|
264
|
+
VAL2MAT4(dest)[3][1] = drand48();
|
265
|
+
VAL2MAT4(dest)[3][2] = drand48();
|
266
|
+
|
267
|
+
/* random rotatation around random axis with random angle */
|
268
|
+
glm_rotate(VAL2MAT4(dest), drand48(), (vec3){drand48(), drand48(), drand48()});
|
269
|
+
|
270
|
+
/* random scale */
|
271
|
+
/* glm_scale(dest, (vec3){drand48(), drand48(), drand48()}); */
|
272
|
+
|
273
|
+
return dest;
|
274
|
+
}
|
275
|
+
|
276
|
+
void Init_cglm_mat4() {
|
277
|
+
rb_define_method(rb_cMat4, "equalish", rb_cglm_mat4_equalish, -1);
|
278
|
+
rb_define_method(rb_cMat4, "==", rb_cglm_mat4_equal, 1);
|
279
|
+
rb_define_method(rb_cMat4, "[]", rb_cglm_mat4_aref, 1);
|
280
|
+
rb_define_method(rb_cMat4, "[]=", rb_cglm_mat4_aset, 2);
|
281
|
+
rb_define_method(rb_cMat4, "to_mat3", rb_cglm_mat4_to_mat3, -1);
|
282
|
+
rb_define_method(rb_cMat4, "to_transposed_mat3", rb_cglm_mat4_to_transposed_mat3, -1);
|
283
|
+
rb_define_method(rb_cMat4, "to_quat", rb_cglm_mat4_to_quat, -1);
|
284
|
+
rb_define_method(rb_cMat4, "mul_mat4", rb_cglm_mat4_mul_mat4, -1);
|
285
|
+
rb_define_method(rb_cMat4, "mul_vec4", rb_cglm_mat4_mul_vec4, -1);
|
286
|
+
rb_define_method(rb_cMat4, "mul_vec3", rb_cglm_mat4_mul_vec3, -1);
|
287
|
+
rb_define_method(rb_cMat4, "mul_scalar", rb_cglm_mat4_mul_scalar, -1);
|
288
|
+
rb_define_method(rb_cMat4, "mul_scalar!", rb_cglm_mat4_mul_scalar_self, 0);
|
289
|
+
rb_define_method(rb_cMat4, "transpose", rb_cglm_mat4_transpose, -1);
|
290
|
+
rb_define_method(rb_cMat4, "transpose!", rb_cglm_mat4_transpose_self, 0);
|
291
|
+
rb_define_method(rb_cMat4, "determinant", rb_cglm_mat4_determinant, 0);
|
292
|
+
rb_define_method(rb_cMat4, "invert", rb_cglm_mat4_invert, -1);
|
293
|
+
rb_define_method(rb_cMat4, "invert_fast", rb_cglm_mat4_invert_fast, -1);
|
294
|
+
rb_define_method(rb_cMat4, "invert!", rb_cglm_mat4_invert_self, 0);
|
295
|
+
rb_define_method(rb_cMat4, "invert_fast!", rb_cglm_mat4_invert_fast_self, 0);
|
296
|
+
rb_define_method(rb_cMat4, "swap_col!", rb_cglm_mat4_swap_col_self, 2);
|
297
|
+
rb_define_method(rb_cMat4, "swap_row!", rb_cglm_mat4_swap_row_self, 2);
|
298
|
+
|
299
|
+
rb_define_alias(rb_cMat4, "det", "determinant");
|
300
|
+
rb_define_alias(rb_cMat4, "=~", "equalish");
|
301
|
+
|
302
|
+
rb_define_singleton_method(rb_cMat4, "random", rb_cglm_mat4_new_random, -1);
|
303
|
+
rb_define_singleton_method(rb_cMat4, "rand", rb_cglm_mat4_new_random, -1);
|
304
|
+
rb_define_singleton_method(rb_cMat4, "identity", rb_cglm_mat4_new_identity, -1);
|
305
|
+
rb_define_singleton_method(rb_cMat4, "quat_rotate_at", rb_cglm_mat4_new_rotate_at, -1);
|
306
|
+
rb_define_singleton_method(rb_cMat4, "size", rb_cglm_mat4_size_bytes, 0);
|
307
|
+
rb_define_singleton_method(rb_cMat4, "alignment", rb_cglm_mat4_alignment_bytes, 0);
|
308
|
+
}
|
@@ -0,0 +1,36 @@
|
|
1
|
+
#include "rb_cglm.h"
|
2
|
+
|
3
|
+
/* call-seq: normalize([dest]) => dest | new Plane
|
4
|
+
*
|
5
|
+
* Normalizes this plane and places the result in `dest`, or allocates a new
|
6
|
+
* Plane if `dest` is omitted.
|
7
|
+
*/
|
8
|
+
VALUE rb_cglm_plane_normalize(int argc, VALUE *argv, VALUE self) {
|
9
|
+
VALUE dest;
|
10
|
+
rb_scan_args(argc, argv, "01", &dest);
|
11
|
+
if (NIL_P(dest)) dest = PLANE_NEW(ALLOC_PLANE);
|
12
|
+
memcpy(&(VAL2VEC4(self)), &(VAL2VEC4(dest)), sizeof(vec4));
|
13
|
+
glm_plane_normalize(VAL2VEC4(dest));
|
14
|
+
return dest;
|
15
|
+
}
|
16
|
+
|
17
|
+
/* call-seq: normalize! => self
|
18
|
+
*
|
19
|
+
* Normalizes this Vec4 (which represents a plane) and returns it.
|
20
|
+
*/
|
21
|
+
VALUE rb_cglm_plane_normalize_self(VALUE self) {
|
22
|
+
glm_plane_normalize(VAL2VEC4(self));
|
23
|
+
return self;
|
24
|
+
}
|
25
|
+
|
26
|
+
VALUE rb_cglm_plane_size_bytes(VALUE klass) { return SIZET2NUM(plane_size()); }
|
27
|
+
|
28
|
+
VALUE rb_cglm_plane_alignment_bytes(VALUE klass) { return SIZET2NUM(PLANE_ALIGNMENT); }
|
29
|
+
|
30
|
+
void Init_cglm_plane() {
|
31
|
+
rb_define_method(rb_cPlane, "normalize", rb_cglm_plane_normalize, -1);
|
32
|
+
rb_define_method(rb_cPlane, "normalize!", rb_cglm_plane_normalize_self, 0);
|
33
|
+
|
34
|
+
rb_define_singleton_method(rb_cPlane, "size", rb_cglm_plane_size_bytes, 0);
|
35
|
+
rb_define_singleton_method(rb_cPlane, "alignment", rb_cglm_plane_alignment_bytes, 0);
|
36
|
+
}
|
@@ -0,0 +1,99 @@
|
|
1
|
+
#include "rb_cglm.h"
|
2
|
+
|
3
|
+
/* call-seq: unproject_i(pos, viewport[, dest]) => dest | new Vec3
|
4
|
+
*
|
5
|
+
* Maps the specified position into the space represented by this matrix,
|
6
|
+
* places it in `dest` or a new Vec3 if `dest` is omitted, and returns it.
|
7
|
+
*
|
8
|
+
* * NOTE: This method assumes that `self` represents the **inverse** of a
|
9
|
+
* projection matrix. It's faster than calling #unproject assuming you
|
10
|
+
* already have an inverse matrix. If you don't have an inverse, you should
|
11
|
+
* just rely on #unproject (to save the overhead of the extra method call),
|
12
|
+
* but if you have or need the inverse for other computations, you can use
|
13
|
+
* #unproject_i to save yourself the cost of the inversion.
|
14
|
+
*
|
15
|
+
* * If `self` is an `inverse(projection)` matrix, then the result will be
|
16
|
+
* in view space.
|
17
|
+
*
|
18
|
+
* * If `self` is an `inverse(projection * view)` matrix, then the result will
|
19
|
+
* be in world space.
|
20
|
+
*
|
21
|
+
* * If `self` is an `inverse(projection * view * model)` matrix, then the
|
22
|
+
* result will be in object space.
|
23
|
+
*
|
24
|
+
* * `pos` is a Vec3 specifying the coordinates to unproject.
|
25
|
+
*
|
26
|
+
* * `viewport` is a Vec4 specifying the dimensions of the viewport in
|
27
|
+
* `[x, y, width, height]` format.
|
28
|
+
*
|
29
|
+
* * `dest` is the Vec3 to place the results into, and will be created if
|
30
|
+
* omitted.
|
31
|
+
*/
|
32
|
+
VALUE rb_cglm_project_unproject_i(int argc, VALUE *argv, VALUE self) {
|
33
|
+
VALUE pos, viewport, dest;
|
34
|
+
rb_scan_args(argc, argv, "21", &pos, &viewport, &dest);
|
35
|
+
if (NIL_P(dest)) dest = VEC3_NEW(ALLOC_VEC3);
|
36
|
+
glm_unprojecti(VAL2VEC3(pos), VAL2MAT4(self), VAL2VEC4(viewport), VAL2VEC3(dest));
|
37
|
+
return dest;
|
38
|
+
}
|
39
|
+
|
40
|
+
/* call-seq: unproject(pos, viewport[, dest]) => dest | new Vec3
|
41
|
+
*
|
42
|
+
* Maps the specified position into the space represented by this matrix,
|
43
|
+
* places it in `dest` or a new Vec3 if `dest` is omitted, and returns it.
|
44
|
+
*
|
45
|
+
* * NOTE: This method must calculate the inverse of the current matrix. If
|
46
|
+
* you already have the inverse handy, you should use #unproject_i for
|
47
|
+
* better performance.
|
48
|
+
*
|
49
|
+
* * If `self` is a `projection` matrix, then the result will be
|
50
|
+
* in view space.
|
51
|
+
*
|
52
|
+
* * If `self` is a `projection * view` matrix, then the result will
|
53
|
+
* be in world space.
|
54
|
+
*
|
55
|
+
* * If `self` is an `projection * view * model` matrix, then the
|
56
|
+
* result will be in object space.
|
57
|
+
*
|
58
|
+
* * `pos` is a Vec3 specifying the coordinates to unproject.
|
59
|
+
*
|
60
|
+
* * `viewport` is a Vec4 specifying the dimensions of the viewport in
|
61
|
+
* `[x, y, width, height]` format.
|
62
|
+
*
|
63
|
+
* * `dest` is the Vec3 to place the results into, and will be created if
|
64
|
+
* omitted.
|
65
|
+
*/
|
66
|
+
VALUE rb_cglm_project_unproject(int argc, VALUE *argv, VALUE self) {
|
67
|
+
VALUE pos, viewport, dest;
|
68
|
+
rb_scan_args(argc, argv, "21", &pos, &viewport, &dest);
|
69
|
+
if (NIL_P(dest)) dest = VEC3_NEW(ALLOC_VEC3);
|
70
|
+
glm_unproject(VAL2VEC3(pos), VAL2MAT4(self), VAL2VEC4(viewport), VAL2VEC3(dest));
|
71
|
+
return dest;
|
72
|
+
}
|
73
|
+
|
74
|
+
/* call-seq: project(pos, viewport[, dest]) => dest | new Vec3
|
75
|
+
*
|
76
|
+
* Maps the given object-space coordinates into window coordinates using
|
77
|
+
* `self` as the projection matrix.
|
78
|
+
*
|
79
|
+
* * `pos` is a Vec3 specifying the object-space coordinates.
|
80
|
+
*
|
81
|
+
* * `viewport` is a Vec4 specifying the dimensions of the viewport in
|
82
|
+
* `[x, y, width, height]` format.
|
83
|
+
*
|
84
|
+
* * `dest` is the Vec3 to place the results into, and will be created if
|
85
|
+
* omitted.
|
86
|
+
*/
|
87
|
+
VALUE rb_cglm_project_project(int argc, VALUE *argv, VALUE self) {
|
88
|
+
VALUE pos, viewport, dest;
|
89
|
+
rb_scan_args(argc, argv, "21", &pos, &viewport, &dest);
|
90
|
+
if (NIL_P(dest)) dest = VEC3_NEW(ALLOC_VEC3);
|
91
|
+
glm_project(VAL2VEC3(pos), VAL2MAT4(self), VAL2VEC4(viewport), VAL2VEC3(dest));
|
92
|
+
return dest;
|
93
|
+
}
|
94
|
+
|
95
|
+
void Init_cglm_project() {
|
96
|
+
rb_define_method(rb_cMat4, "unproject_i", rb_cglm_project_unproject_i, -1);
|
97
|
+
rb_define_method(rb_cMat4, "unproject", rb_cglm_project_unproject, -1);
|
98
|
+
rb_define_method(rb_cMat4, "project", rb_cglm_project_project, -1);
|
99
|
+
}
|
@@ -0,0 +1,358 @@
|
|
1
|
+
#include "rb_cglm.h"
|
2
|
+
|
3
|
+
/* call-seq: identity([dest]) => dest | new Quat */
|
4
|
+
VALUE rb_cglm_quat_new_identity(int argc, VALUE *argv, VALUE self) {
|
5
|
+
VALUE dest;
|
6
|
+
rb_scan_args(argc, argv, "01", &dest);
|
7
|
+
if (NIL_P(dest)) dest = QUAT_NEW(ALLOC_QUAT);
|
8
|
+
glm_quat_identity(VAL2QUAT(dest));
|
9
|
+
return dest;
|
10
|
+
}
|
11
|
+
|
12
|
+
/* call-seq: axis_angle(axis, angle[, dest]) => dest | new Quat */
|
13
|
+
VALUE rb_cglm_quat_new_axis_angle(int argc, VALUE *argv, VALUE self) {
|
14
|
+
VALUE axis, angle, dest;
|
15
|
+
rb_scan_args(argc, argv, "21", &axis, &angle, &dest);
|
16
|
+
if (NIL_P(dest)) dest = QUAT_NEW(ALLOC_QUAT);
|
17
|
+
glm_quatv(VAL2QUAT(dest), NUM2FLT(angle), VAL2VEC3(axis));
|
18
|
+
return dest;
|
19
|
+
}
|
20
|
+
|
21
|
+
/* call-seq: copy_to(dest) => dest */
|
22
|
+
VALUE rb_cglm_quat_copy_to(VALUE self, VALUE dest) {
|
23
|
+
glm_quat_copy(VAL2QUAT(self), VAL2QUAT(dest));
|
24
|
+
return dest;
|
25
|
+
}
|
26
|
+
|
27
|
+
/* call-seq: normalize([dest]) => dest */
|
28
|
+
VALUE rb_cglm_quat_normalize(int argc, VALUE *argv, VALUE self) {
|
29
|
+
VALUE dest;
|
30
|
+
rb_scan_args(argc, argv, "01", &dest);
|
31
|
+
if (NIL_P(dest)) dest = QUAT_NEW(ALLOC_QUAT);
|
32
|
+
glm_quat_normalize_to(VAL2QUAT(self), VAL2QUAT(dest));
|
33
|
+
return dest;
|
34
|
+
}
|
35
|
+
|
36
|
+
/* call-seq: normalize! => self */
|
37
|
+
VALUE rb_cglm_quat_normalize_self(VALUE self) {
|
38
|
+
glm_quat_normalize(VAL2QUAT(self));
|
39
|
+
return self;
|
40
|
+
}
|
41
|
+
|
42
|
+
/* call-seq: conjugate([dest]) => dest | new Quat */
|
43
|
+
VALUE rb_cglm_quat_conjugate(int argc, VALUE *argv, VALUE self) {
|
44
|
+
VALUE dest;
|
45
|
+
rb_scan_args(argc, argv, "01", &dest);
|
46
|
+
if (NIL_P(dest)) dest = QUAT_NEW(ALLOC_QUAT);
|
47
|
+
glm_quat_conjugate(VAL2QUAT(self), VAL2QUAT(dest));
|
48
|
+
return dest;
|
49
|
+
}
|
50
|
+
|
51
|
+
/* call-seq: invert([dest]) => dest | new Quat */
|
52
|
+
VALUE rb_cglm_quat_invert(int argc, VALUE *argv, VALUE self) {
|
53
|
+
VALUE dest;
|
54
|
+
rb_scan_args(argc, argv, "01", &dest);
|
55
|
+
if (NIL_P(dest)) dest = QUAT_NEW(ALLOC_QUAT);
|
56
|
+
glm_quat_inv(VAL2QUAT(self), VAL2QUAT(dest));
|
57
|
+
return dest;
|
58
|
+
}
|
59
|
+
|
60
|
+
/* call-seq: invert! => self */
|
61
|
+
VALUE rb_cglm_quat_invert_self(VALUE self) {
|
62
|
+
glm_quat_inv(VAL2QUAT(self), VAL2QUAT(self));
|
63
|
+
return self;
|
64
|
+
}
|
65
|
+
|
66
|
+
/* call-seq: real => Numeric
|
67
|
+
*
|
68
|
+
* Returns the real part of the quaternion.
|
69
|
+
*/
|
70
|
+
VALUE rb_cglm_quat_real(VALUE self) {
|
71
|
+
return DBL2NUM(glm_quat_real(VAL2QUAT(self)));
|
72
|
+
}
|
73
|
+
|
74
|
+
/* call-seq: imag([dest]) => dest | new Vec3
|
75
|
+
*
|
76
|
+
* Returns the imaginary part of the quaternion in `dest`.
|
77
|
+
*/
|
78
|
+
VALUE rb_cglm_quat_imag(int argc, VALUE *argv, VALUE self) {
|
79
|
+
VALUE dest;
|
80
|
+
rb_scan_args(argc, argv, "01", &dest);
|
81
|
+
if (NIL_P(dest)) dest = VEC3_NEW(ALLOC_VEC3);
|
82
|
+
glm_quat_imag(VAL2QUAT(self), VAL2VEC3(dest));
|
83
|
+
return dest;
|
84
|
+
}
|
85
|
+
|
86
|
+
/* call-seq: imagn([dest]) => dest | new Vec3
|
87
|
+
*
|
88
|
+
* Returns the imaginary part of the quaternion in `dest`, normalized.
|
89
|
+
*/
|
90
|
+
VALUE rb_cglm_quat_imagn(int argc, VALUE *argv, VALUE self) {
|
91
|
+
VALUE dest;
|
92
|
+
rb_scan_args(argc, argv, "01", &dest);
|
93
|
+
if (NIL_P(dest)) dest = VEC3_NEW(ALLOC_VEC3);
|
94
|
+
glm_quat_imagn(VAL2QUAT(self), VAL2VEC3(dest));
|
95
|
+
return dest;
|
96
|
+
}
|
97
|
+
|
98
|
+
/* call-seq: imaglen => Numeric
|
99
|
+
*
|
100
|
+
* Returns the length of the imaginary part of the quaternion.
|
101
|
+
*/
|
102
|
+
VALUE rb_cglm_quat_imaglen(VALUE self) {
|
103
|
+
return DBL2NUM(glm_quat_imaglen(VAL2QUAT(self)));
|
104
|
+
}
|
105
|
+
|
106
|
+
/* call-seq: angle => Numeric
|
107
|
+
*
|
108
|
+
* Returns the angle of the quaternion.
|
109
|
+
*/
|
110
|
+
VALUE rb_cglm_quat_angle(VALUE self) {
|
111
|
+
return DBL2NUM(glm_quat_angle(VAL2QUAT(self)));
|
112
|
+
}
|
113
|
+
|
114
|
+
/* call-seq: axis([dest]) => dest | new Vec3
|
115
|
+
*
|
116
|
+
* Returns the axis of the quaternion in `dest`.
|
117
|
+
*/
|
118
|
+
VALUE rb_cglm_quat_axis(int argc, VALUE *argv, VALUE self) {
|
119
|
+
VALUE dest;
|
120
|
+
rb_scan_args(argc, argv, "01", &dest);
|
121
|
+
if (NIL_P(dest)) dest = VEC3_NEW(ALLOC_VEC3);
|
122
|
+
glm_quat_axis(VAL2QUAT(self), VAL2VEC3(dest));
|
123
|
+
return dest;
|
124
|
+
}
|
125
|
+
|
126
|
+
/* call-seq: mul_quat(other[, dest]) => dest | new Quat
|
127
|
+
*
|
128
|
+
* Multiplies `self` by `other` and stores the result in `dest`. If `dest`
|
129
|
+
* is omitted, a new Quat is created. `dest` or the new Quat is returned.
|
130
|
+
*/
|
131
|
+
VALUE rb_cglm_quat_mul_quat(int argc, VALUE *argv, VALUE self) {
|
132
|
+
VALUE other, dest;
|
133
|
+
rb_scan_args(argc, argv, "11", &other, &dest);
|
134
|
+
if (NIL_P(dest)) dest = QUAT_NEW(ALLOC_QUAT);
|
135
|
+
glm_quat_mul(VAL2QUAT(self), VAL2QUAT(other), VAL2QUAT(dest));
|
136
|
+
return dest;
|
137
|
+
}
|
138
|
+
|
139
|
+
/* call-seq: mul_quat!(other) => self
|
140
|
+
*
|
141
|
+
* Multiplies `self` by `other`. Modifies `self` in-place and returns `self`.
|
142
|
+
*/
|
143
|
+
VALUE rb_cglm_quat_mul_quat_self(VALUE self, VALUE other) {
|
144
|
+
quat dest;
|
145
|
+
glm_quat_mul(VAL2QUAT(self), VAL2QUAT(other), dest);
|
146
|
+
memcpy(&VAL2QUAT(self), &dest, sizeof(quat));
|
147
|
+
return self;
|
148
|
+
}
|
149
|
+
|
150
|
+
/* call-seq: to_mat4([dest]) => dest | new Mat4
|
151
|
+
*
|
152
|
+
* Converts this quaternion into a Mat4. Places the result into `dest` or
|
153
|
+
* creates a new Mat4.
|
154
|
+
*/
|
155
|
+
VALUE rb_cglm_quat_to_mat4(int argc, VALUE *argv, VALUE self) {
|
156
|
+
VALUE dest;
|
157
|
+
rb_scan_args(argc, argv, "01", &dest);
|
158
|
+
if (NIL_P(dest)) dest = MAT4_NEW(ALLOC_MAT4);
|
159
|
+
glm_quat_mat4(VAL2QUAT(self), VAL2MAT4(dest));
|
160
|
+
return dest;
|
161
|
+
}
|
162
|
+
|
163
|
+
/* call-seq: to_transposed_mat4([dest]) => dest | new Mat4
|
164
|
+
*
|
165
|
+
* Converts this quaternion into a transposed Mat4. Places the result into
|
166
|
+
* `dest` or creates a new Mat4.
|
167
|
+
*/
|
168
|
+
VALUE rb_cglm_quat_to_mat4t(int argc, VALUE *argv, VALUE self) {
|
169
|
+
VALUE dest;
|
170
|
+
rb_scan_args(argc, argv, "01", &dest);
|
171
|
+
if (NIL_P(dest)) dest = MAT4_NEW(ALLOC_MAT4);
|
172
|
+
glm_quat_mat4t(VAL2QUAT(self), VAL2MAT4(dest));
|
173
|
+
return dest;
|
174
|
+
}
|
175
|
+
|
176
|
+
/* call-seq: to_mat3([dest]) => dest | new Mat3
|
177
|
+
*
|
178
|
+
* Converts this quaternion into a Mat3. Places the result into `dest` or
|
179
|
+
* creates a new Mat3.
|
180
|
+
*/
|
181
|
+
VALUE rb_cglm_quat_to_mat3(int argc, VALUE *argv, VALUE self) {
|
182
|
+
VALUE dest;
|
183
|
+
rb_scan_args(argc, argv, "01", &dest);
|
184
|
+
if (NIL_P(dest)) dest = MAT3_NEW(ALLOC_MAT3);
|
185
|
+
glm_quat_mat3(VAL2QUAT(self), VAL2MAT3(dest));
|
186
|
+
return dest;
|
187
|
+
}
|
188
|
+
|
189
|
+
/* call-seq: to_transposed_mat3([dest]) => dest | new Mat3
|
190
|
+
*
|
191
|
+
* Converts this quaternion into a transposed Mat3. Places the result into
|
192
|
+
* `dest` or creates a new Mat3.
|
193
|
+
*/
|
194
|
+
VALUE rb_cglm_quat_to_mat3t(int argc, VALUE *argv, VALUE self) {
|
195
|
+
VALUE dest;
|
196
|
+
rb_scan_args(argc, argv, "01", &dest);
|
197
|
+
if (NIL_P(dest)) dest = MAT3_NEW(ALLOC_MAT3);
|
198
|
+
glm_quat_mat3t(VAL2QUAT(self), VAL2MAT3(dest));
|
199
|
+
return dest;
|
200
|
+
}
|
201
|
+
|
202
|
+
/* call-seq: lerp!(from, to, amount) => self */
|
203
|
+
VALUE rb_cglm_quat_lerp_self(VALUE self, VALUE from, VALUE to, VALUE amount) {
|
204
|
+
glm_quat_lerp(VAL2QUAT(from), VAL2QUAT(to), NUM2FLT(to), VAL2QUAT(self));
|
205
|
+
return self;
|
206
|
+
}
|
207
|
+
|
208
|
+
/* call-seq: slerp!(from, to, amount) => self */
|
209
|
+
VALUE rb_cglm_quat_slerp_self(VALUE self, VALUE from, VALUE to, VALUE amount) {
|
210
|
+
glm_quat_slerp(VAL2QUAT(from), VAL2QUAT(to), NUM2FLT(to), VAL2QUAT(self));
|
211
|
+
return self;
|
212
|
+
}
|
213
|
+
|
214
|
+
/* call-seq: look(position[, dest]) => dest | new Mat4
|
215
|
+
*
|
216
|
+
* Creates a view matrix, stored in `dest`, using this quaternion as the
|
217
|
+
* camera orientation. Returns `dest`. Creates a new Mat4 if `dest` is
|
218
|
+
* omitted.
|
219
|
+
*/
|
220
|
+
VALUE rb_cglm_quat_look(int argc, VALUE *argv, VALUE self) {
|
221
|
+
VALUE position, dest;
|
222
|
+
rb_scan_args(argc, argv, "11", &position, &dest);
|
223
|
+
if (NIL_P(dest)) dest = MAT4_NEW(ALLOC_MAT4);
|
224
|
+
glm_quat_look(VAL2VEC3(position), VAL2QUAT(self), VAL2MAT4(dest));
|
225
|
+
return dest;
|
226
|
+
}
|
227
|
+
|
228
|
+
/* call-seq: look(dir, fwd, up[, dest]) => dest | new Quat
|
229
|
+
*
|
230
|
+
* Creates a rotation quaternion that has the specified orientation. Places
|
231
|
+
* the result in `dest`, or creates a new Quat if `dest` was omitted. Returns
|
232
|
+
* `dest`.
|
233
|
+
*
|
234
|
+
* * `dir` is the direction to look (a Vec3).
|
235
|
+
*
|
236
|
+
* * `fwd` is the forward vector (a Vec3).
|
237
|
+
*
|
238
|
+
* * `up` is the up vector (a Vec3).
|
239
|
+
*/
|
240
|
+
VALUE rb_cglm_quat_new_look(int argc, VALUE *argv, VALUE self) {
|
241
|
+
VALUE dir, fwd, up, dest;
|
242
|
+
rb_scan_args(argc, argv, "31", &dir, &fwd, &up, &dest);
|
243
|
+
if (NIL_P(dest)) dest = QUAT_NEW(ALLOC_QUAT);
|
244
|
+
glm_quat_for(VAL2VEC3(dir), VAL2VEC3(fwd), VAL2VEC3(up), VAL2QUAT(dest));
|
245
|
+
return dest;
|
246
|
+
}
|
247
|
+
|
248
|
+
/* call-seq: look_at(position, target, fwd, up[, dest]) => dest | new Quat
|
249
|
+
*
|
250
|
+
* Creates a rotation quaternion that has the specified orientation. Places
|
251
|
+
* the result in `dest`, or creates a new Quat if `dest` was omitted. Returns
|
252
|
+
* `dest`.
|
253
|
+
*
|
254
|
+
* * `position` is the current position to look from (a Vec3).
|
255
|
+
*
|
256
|
+
* * `target` is the position to look toward (a Vec3).
|
257
|
+
*
|
258
|
+
* * `fwd` is the forward vector (a Vec3).
|
259
|
+
*
|
260
|
+
* * `up` is the up vector (a Vec3).
|
261
|
+
*/
|
262
|
+
VALUE rb_cglm_quat_new_look_at(int argc, VALUE *argv, VALUE self) {
|
263
|
+
VALUE position, target, fwd, up, dest;
|
264
|
+
rb_scan_args(argc, argv, "41", &position, &target, &fwd, &up, &dest);
|
265
|
+
if (NIL_P(dest)) dest = QUAT_NEW(ALLOC_QUAT);
|
266
|
+
glm_quat_forp(VAL2VEC3(position), VAL2VEC3(target), VAL2VEC3(fwd), VAL2VEC3(up), VAL2QUAT(dest));
|
267
|
+
return dest;
|
268
|
+
}
|
269
|
+
|
270
|
+
/* call-seq: rotate_vec3(vec[, dest]) => dest | new Vec3
|
271
|
+
*
|
272
|
+
* Rotates the given Vec3 by this quaternion. Returns the result in `dest`,
|
273
|
+
* or a new Vec3 if `dest` was omitted.
|
274
|
+
*/
|
275
|
+
VALUE rb_cglm_quat_rotate_vec3(int argc, VALUE *argv, VALUE self) {
|
276
|
+
VALUE vec, dest;
|
277
|
+
rb_scan_args(argc, argv, "11", &vec, &dest);
|
278
|
+
if (NIL_P(dest)) dest = VEC3_NEW(ALLOC_VEC3);
|
279
|
+
glm_quat_rotatev(VAL2QUAT(self), VAL2VEC3(vec), VAL2VEC3(dest));
|
280
|
+
return dest;
|
281
|
+
}
|
282
|
+
|
283
|
+
/* call-seq: rotate_mat4(vec[, dest]) => dest | new Mat4
|
284
|
+
*
|
285
|
+
* Rotates the given Mat4 by this quaternion. Returns the result in `dest`,
|
286
|
+
* or a new Mat4 if `dest` was omitted.
|
287
|
+
*/
|
288
|
+
VALUE rb_cglm_quat_rotate_mat4(int argc, VALUE *argv, VALUE self) {
|
289
|
+
VALUE mat, dest;
|
290
|
+
rb_scan_args(argc, argv, "11", &mat, &dest);
|
291
|
+
if (NIL_P(dest)) dest = MAT4_NEW(ALLOC_MAT4);
|
292
|
+
glm_quat_rotate(VAL2MAT4(mat), VAL2QUAT(self), VAL2MAT4(dest));
|
293
|
+
return dest;
|
294
|
+
}
|
295
|
+
|
296
|
+
/* call-seq: pivot_mat4(mat, pivot_point[, dest]) => dest | new Mat4
|
297
|
+
*
|
298
|
+
* Rotates the given transform matrix using this quaternion at the pivot
|
299
|
+
* point (a Vec3). Places the resultant Mat4 into `dest`, or creates a new
|
300
|
+
* Mat4 if `dest` is omitted. Returns `dest`.
|
301
|
+
*/
|
302
|
+
VALUE rb_cglm_quat_pivot_mat4(int argc, VALUE *argv, VALUE self) {
|
303
|
+
VALUE mat, pivot, dest;
|
304
|
+
rb_scan_args(argc, argv, "21", &mat, &pivot, &dest);
|
305
|
+
if (NIL_P(dest)) dest = MAT4_NEW(ALLOC_MAT4);
|
306
|
+
memcpy(&VAL2MAT4(dest), &VAL2MAT4(mat), sizeof(mat4));
|
307
|
+
glm_quat_rotate_at(VAL2MAT4(dest), VAL2QUAT(self), VAL2VEC3(pivot));
|
308
|
+
return dest;
|
309
|
+
}
|
310
|
+
|
311
|
+
/* call-seq: random([dest]) => dest | new Quat
|
312
|
+
*
|
313
|
+
* Fills `dest` or a new Quat with a random orientation, and returns it.
|
314
|
+
*/
|
315
|
+
VALUE rb_cglm_quat_new_random(int argc, VALUE *argv, VALUE self) {
|
316
|
+
VALUE dest;
|
317
|
+
rb_scan_args(argc, argv, "01", &dest);
|
318
|
+
if (NIL_P(dest)) dest = QUAT_NEW(ALLOC_QUAT);
|
319
|
+
|
320
|
+
glm_quat(VAL2QUAT(dest), drand48(), drand48(), drand48(), drand48());
|
321
|
+
glm_quat_normalize(VAL2QUAT(dest));
|
322
|
+
|
323
|
+
return dest;
|
324
|
+
}
|
325
|
+
|
326
|
+
void Init_cglm_quat() {
|
327
|
+
rb_define_method(rb_cQuat, "copy_to", rb_cglm_quat_copy_to, 1);
|
328
|
+
rb_define_method(rb_cQuat, "normalize", rb_cglm_quat_normalize, -1);
|
329
|
+
rb_define_method(rb_cQuat, "normalize!", rb_cglm_quat_normalize_self, 0);
|
330
|
+
rb_define_method(rb_cQuat, "conjugate", rb_cglm_quat_conjugate, -1);
|
331
|
+
rb_define_method(rb_cQuat, "invert", rb_cglm_quat_invert, -1);
|
332
|
+
rb_define_method(rb_cQuat, "invert!", rb_cglm_quat_invert_self, 0);
|
333
|
+
rb_define_method(rb_cQuat, "real", rb_cglm_quat_real, 0);
|
334
|
+
rb_define_method(rb_cQuat, "imag", rb_cglm_quat_imag, -1);
|
335
|
+
rb_define_method(rb_cQuat, "imagn", rb_cglm_quat_imagn, -1);
|
336
|
+
rb_define_method(rb_cQuat, "imaglen", rb_cglm_quat_imaglen, 0);
|
337
|
+
rb_define_method(rb_cQuat, "angle", rb_cglm_quat_angle, 0);
|
338
|
+
rb_define_method(rb_cQuat, "axis", rb_cglm_quat_axis, -1);
|
339
|
+
rb_define_method(rb_cQuat, "mul_quat", rb_cglm_quat_mul_quat, -1);
|
340
|
+
rb_define_method(rb_cQuat, "mul_quat!", rb_cglm_quat_mul_quat_self, 1);
|
341
|
+
rb_define_method(rb_cQuat, "to_mat4", rb_cglm_quat_to_mat4, -1);
|
342
|
+
rb_define_method(rb_cQuat, "to_transposed_mat4", rb_cglm_quat_to_mat4t, -1);
|
343
|
+
rb_define_method(rb_cQuat, "to_mat3", rb_cglm_quat_to_mat3, -1);
|
344
|
+
rb_define_method(rb_cQuat, "to_transposed_mat3", rb_cglm_quat_to_mat3t, -1);
|
345
|
+
rb_define_method(rb_cQuat, "lerp!", rb_cglm_quat_lerp_self, 3);
|
346
|
+
rb_define_method(rb_cQuat, "slerp!", rb_cglm_quat_slerp_self, 3);
|
347
|
+
rb_define_method(rb_cQuat, "look", rb_cglm_quat_look, -1);
|
348
|
+
rb_define_method(rb_cQuat, "rotate_vec3", rb_cglm_quat_rotate_vec3, -1);
|
349
|
+
rb_define_method(rb_cQuat, "rotate_mat4", rb_cglm_quat_rotate_mat4, -1);
|
350
|
+
rb_define_method(rb_cQuat, "pivot_mat4", rb_cglm_quat_pivot_mat4, -1);
|
351
|
+
|
352
|
+
rb_define_singleton_method(rb_cQuat, "random", rb_cglm_quat_new_random, -1);
|
353
|
+
rb_define_singleton_method(rb_cQuat, "rand", rb_cglm_quat_new_random, -1);
|
354
|
+
rb_define_singleton_method(rb_cQuat, "identity", rb_cglm_quat_new_identity, -1);
|
355
|
+
rb_define_singleton_method(rb_cQuat, "axis_angle", rb_cglm_quat_new_axis_angle, -1);
|
356
|
+
rb_define_singleton_method(rb_cQuat, "look", rb_cglm_quat_new_look, -1);
|
357
|
+
rb_define_singleton_method(rb_cQuat, "look_at", rb_cglm_quat_new_look_at, -1);
|
358
|
+
}
|