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,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
|
+
}
|