numerix 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (60) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +18 -0
  3. data/.travis.yml +5 -0
  4. data/.yardopts +5 -0
  5. data/CODE_OF_CONDUCT.md +74 -0
  6. data/Gemfile +6 -0
  7. data/LICENSE.txt +21 -0
  8. data/README.md +66 -0
  9. data/Rakefile +18 -0
  10. data/TODO.txt +25 -0
  11. data/bin/console +14 -0
  12. data/bin/setup +8 -0
  13. data/ext/numerix/common.h +107 -0
  14. data/ext/numerix/extconf.rb +3 -0
  15. data/ext/numerix/matrix3x2.c +638 -0
  16. data/ext/numerix/matrix3x2.h +52 -0
  17. data/ext/numerix/matrix4x4.c +1807 -0
  18. data/ext/numerix/matrix4x4.h +90 -0
  19. data/ext/numerix/matrix_base.c +307 -0
  20. data/ext/numerix/matrix_base.h +70 -0
  21. data/ext/numerix/numerix.c +33 -0
  22. data/ext/numerix/numerix.h +19 -0
  23. data/ext/numerix/plane.c +311 -0
  24. data/ext/numerix/plane.h +34 -0
  25. data/ext/numerix/quaternion.c +712 -0
  26. data/ext/numerix/quaternion.h +53 -0
  27. data/ext/numerix/structure.c +154 -0
  28. data/ext/numerix/structure.h +24 -0
  29. data/ext/numerix/vector.c +326 -0
  30. data/ext/numerix/vector.h +57 -0
  31. data/ext/numerix/vector2.c +641 -0
  32. data/ext/numerix/vector2.h +64 -0
  33. data/ext/numerix/vector3.c +805 -0
  34. data/ext/numerix/vector3.h +68 -0
  35. data/ext/numerix/vector4.c +727 -0
  36. data/ext/numerix/vector4.h +63 -0
  37. data/ext/numerix/vector_base.c +94 -0
  38. data/ext/numerix/vector_base.h +30 -0
  39. data/extra/numerix128.png +0 -0
  40. data/extra/numerix24.png +0 -0
  41. data/extra/numerix32.png +0 -0
  42. data/extra/numerix320.png +0 -0
  43. data/extra/numerix48.png +0 -0
  44. data/extra/numerix96.png +0 -0
  45. data/lib/numerix/error.rb +36 -0
  46. data/lib/numerix/matrix3x2.rb +420 -0
  47. data/lib/numerix/matrix4x4.rb +676 -0
  48. data/lib/numerix/matrix_base.rb +14 -0
  49. data/lib/numerix/plane.rb +154 -0
  50. data/lib/numerix/quaternion.rb +355 -0
  51. data/lib/numerix/structure.rb +124 -0
  52. data/lib/numerix/vector.rb +13 -0
  53. data/lib/numerix/vector2.rb +534 -0
  54. data/lib/numerix/vector3.rb +572 -0
  55. data/lib/numerix/vector4.rb +551 -0
  56. data/lib/numerix/vector_base.rb +14 -0
  57. data/lib/numerix/version.rb +6 -0
  58. data/lib/numerix.rb +10 -0
  59. data/numerix.gemspec +30 -0
  60. metadata +167 -0
@@ -0,0 +1,727 @@
1
+
2
+ #include "vector4.h"
3
+
4
+ void Init_vector4(VALUE outer) {
5
+ rb_define_alloc_func(rb_cVector4, rb_vector4_alloc);
6
+
7
+ // Instance Methods
8
+ rb_define_method(rb_cVector4, "initialize", rb_vector4_initialize, -1);
9
+ rb_define_method(rb_cVector4, "length", rb_vector4_length, 0);
10
+ rb_define_method(rb_cVector4, "length_squared", rb_vector4_length_squared, 0);
11
+ rb_define_method(rb_cVector4, "one?", rb_vector4_one_p, 0);
12
+ rb_define_method(rb_cVector4, "zero?", rb_vector4_zero_p, 0);
13
+ rb_define_method(rb_cVector4, "min_value", rb_vector4_min_value, 0);
14
+ rb_define_method(rb_cVector4, "max_value", rb_vector4_max_value, 0);
15
+ rb_define_method(rb_cVector4, "distance", rb_vector4_distance, 1);
16
+ rb_define_method(rb_cVector4, "distance_squared", rb_vector4_distance_squared, 1);
17
+ rb_define_method(rb_cVector4, "normalize", rb_vector4_normalize, 0);
18
+ rb_define_method(rb_cVector4, "normalize!", rb_vector4_normalize_bang, 0);
19
+ rb_define_method(rb_cVector4, "lerp", rb_vector4_lerp, 2);
20
+ rb_define_method(rb_cVector4, "lerp!", rb_vector4_lerp_bang, 2);
21
+ rb_define_method(rb_cVector4, "transform", rb_vector4_transform, 1);
22
+ rb_define_method(rb_cVector4, "transform!", rb_vector4_transform_bang, 1);
23
+ rb_define_method(rb_cVector4, "abs", rb_vector4_abs, 0);
24
+ rb_define_method(rb_cVector4, "sqrt", rb_vector4_sqrt, 0);
25
+ rb_define_method(rb_cVector4, "dot", rb_vector4_dot, 1);
26
+ rb_define_method(rb_cVector4, "clamp", rb_vector4_clamp, 2);
27
+ rb_define_method(rb_cVector4, "clamp!", rb_vector4_clamp_bang, 2);
28
+ rb_define_method(rb_cVector4, "map", rb_vector4_map, 0);
29
+ rb_define_method(rb_cVector4, "map!", rb_vector4_map_bang, 0);
30
+
31
+ // Conversion
32
+ rb_define_method(rb_cVector4, "to_s", rb_vector4_to_s, 0);
33
+ rb_define_method(rb_cVector4, "to_a", rb_vector4_to_a, 0);
34
+ rb_define_method(rb_cVector4, "to_h", rb_vector4_to_h, 0);
35
+ rb_define_method(rb_cVector4, "to_quaternion", rb_vector4_to_quaternion, 0);
36
+ rb_define_method(rb_cVector4, "to_plane", rb_vector4_to_plane, 0);
37
+ rb_define_method(rb_cVector4, "to_vec2", rb_vector4_to_vec2, 0);
38
+ rb_define_method(rb_cVector4, "to_vec3", rb_vector4_to_vec3, 0);
39
+
40
+ // Operators
41
+ rb_define_method(rb_cVector4, "+", rb_vector4_add, 1);
42
+ rb_define_method(rb_cVector4, "-", rb_vector4_subtract, 1);
43
+ rb_define_method(rb_cVector4, "*", rb_vector4_multiply, 1);
44
+ rb_define_method(rb_cVector4, "/", rb_vector4_divide, 1);
45
+ rb_define_method(rb_cVector4, "==", rb_vector4_equal, 1);
46
+ rb_define_method(rb_cVector4, "-@", rb_vector4_negate, 0);
47
+ rb_define_method(rb_cVector4, "**", rb_vector4_pow, 1);
48
+
49
+ // Alias
50
+ rb_define_alias(rb_cVector4, "magnitude", "length");
51
+ rb_define_alias(rb_cVector4, "elements", "to_a");
52
+ rb_define_alias(rb_cVector4, "collect", "map");
53
+ rb_define_alias(rb_cVector4, "collect!", "map!");
54
+
55
+ // Singleton Methods
56
+ rb_define_singleton_method(rb_cVector4, "zero", rb_vector4_alloc, 0);
57
+ rb_define_singleton_method(rb_cVector4, "one", rb_vector4_one, 0);
58
+ rb_define_singleton_method(rb_cVector4, "unit_x", rb_vector4_unit_x, 0);
59
+ rb_define_singleton_method(rb_cVector4, "unit_y", rb_vector4_unit_y, 0);
60
+ rb_define_singleton_method(rb_cVector4, "unit_z", rb_vector4_unit_z, 0);
61
+ rb_define_singleton_method(rb_cVector4, "unit_w", rb_vector4_unit_w, 0);
62
+ rb_define_singleton_method(rb_cVector4, "create_norm", rb_vector4_create_norm, 4);
63
+ rb_define_singleton_method(rb_cVector4, "clamp", rb_vector4_clamp_s, 3);
64
+ rb_define_singleton_method(rb_cVector4, "lerp", rb_vector4_lerp_s, 3);
65
+ rb_define_singleton_method(rb_cVector4, "transform", rb_vector4_transform_s, 2);
66
+ rb_define_singleton_method(rb_cVector4, "min", rb_vector4_min_s, 2);
67
+ rb_define_singleton_method(rb_cVector4, "max", rb_vector4_max_s, 2);
68
+ }
69
+
70
+ static VALUE rb_vector4_alloc(VALUE klass) {
71
+ void *v = ALLOC(Vector4);
72
+ memset(v, 0, sizeof(Vector4));
73
+ return NUMERIX_WRAP(klass, v);
74
+ }
75
+
76
+ VALUE rb_vector4_initialize(int argc, VALUE *argv, VALUE self) {
77
+ VECTOR4();
78
+ switch (argc) {
79
+ case 0:
80
+ break;
81
+ case 1: {
82
+ float value = NUM2FLT(argv[0]);
83
+ v->x = value;
84
+ v->y = value;
85
+ v->z = value;
86
+ v->w = value;
87
+ break;
88
+ }
89
+ case 2: {
90
+ if (NUMERIX_TYPE_P(argv[0], rb_cVector3)) {
91
+ Vector3 *vec3;
92
+ Data_Get_Struct(argv[0], Vector3, vec3);
93
+ v->x = vec3->x;
94
+ v->y = vec3->y;
95
+ v->z = vec3->z;
96
+ v->w = NUM2FLT(argv[1]);
97
+ } else {
98
+ Vector2 *v1, *v2;
99
+ Data_Get_Struct(argv[0], Vector2, v1);
100
+ Data_Get_Struct(argv[1], Vector2, v2);
101
+ v->x = v1->x;
102
+ v->y = v1->y;
103
+ v->z = v2->x;
104
+ v->w = v2->y;
105
+ }
106
+ break;
107
+ }
108
+ case 3: {
109
+ Vector2 *vec2;
110
+ Data_Get_Struct(argv[0], Vector2, vec2);
111
+ v->x = vec2->x;
112
+ v->y = vec2->y;
113
+ v->z = NUM2FLT(argv[1]);
114
+ v->w = NUM2FLT(argv[2]);
115
+ break;
116
+ }
117
+ case 4: {
118
+ v->x = NUM2FLT(argv[0]);
119
+ v->y = NUM2FLT(argv[1]);
120
+ v->z = NUM2FLT(argv[2]);
121
+ v->w = NUM2FLT(argv[3]);
122
+ break;
123
+ }
124
+ default:
125
+ rb_raise(rb_eArgError, "wrong number of arguments (given %d, expected 0, 1, 2, 3, 4)", argc);
126
+ break;
127
+ }
128
+ return Qnil;
129
+ }
130
+
131
+ VALUE rb_vector4_one(VALUE klass) {
132
+ Vector4 *v = ALLOC(Vector4);
133
+ v->x = 1.0f;
134
+ v->y = 1.0f;
135
+ v->z = 1.0f;
136
+ v->w = 1.0f;
137
+ return NUMERIX_WRAP(klass, v);
138
+ }
139
+
140
+ VALUE rb_vector4_unit_x(VALUE klass) {
141
+ Vector4 *v = ALLOC(Vector4);
142
+ v->x = 1.0f;
143
+ v->y = 0.0f;
144
+ v->z = 0.0f;
145
+ v->w = 0.0f;
146
+ return NUMERIX_WRAP(klass, v);
147
+ }
148
+
149
+ VALUE rb_vector4_unit_y(VALUE klass) {
150
+ Vector4 *v = ALLOC(Vector4);
151
+ v->x = 0.0f;
152
+ v->y = 1.0f;
153
+ v->z = 0.0f;
154
+ v->w = 0.0f;
155
+ return NUMERIX_WRAP(klass, v);
156
+ }
157
+
158
+ VALUE rb_vector4_unit_z(VALUE klass) {
159
+ Vector4 *v = ALLOC(Vector4);
160
+ v->x = 0.0f;
161
+ v->y = 0.0f;
162
+ v->z = 1.0f;
163
+ v->w = 0.0f;
164
+ return NUMERIX_WRAP(klass, v);
165
+ }
166
+
167
+ VALUE rb_vector4_unit_w(VALUE klass) {
168
+ Vector4 *v = ALLOC(Vector4);
169
+ v->x = 0.0f;
170
+ v->y = 0.0f;
171
+ v->z = 0.0f;
172
+ v->w = 1.0f;
173
+ return NUMERIX_WRAP(klass, v);
174
+ }
175
+
176
+ VALUE rb_vector4_length(VALUE self) {
177
+ VECTOR4();
178
+ return DBL2NUM(sqrtf(v->x * v->x + v->y * v->y + v->z * v->z + v->w * v->w));
179
+ }
180
+
181
+ VALUE rb_vector4_length_squared(VALUE self) {
182
+ VECTOR4();
183
+ return DBL2NUM(v->x * v->x + v->y * v->y + v->z * v->z + v->w * v->w);
184
+ }
185
+
186
+ VALUE rb_vector4_one_p(VALUE self) {
187
+ VECTOR4();
188
+ return v->x == 1.0f && v->y == 1.0f && v->z == 1.0f && v->w == 1.0f ? Qtrue : Qfalse;
189
+ }
190
+
191
+ VALUE rb_vector4_zero_p(VALUE self) {
192
+ VECTOR4();
193
+ return v->x == 0.0f && v->y == 0.0f && v->z == 0.0f && v->w == 0.0f ? Qtrue : Qfalse;
194
+ }
195
+
196
+ VALUE rb_vector4_add(VALUE self, VALUE other) {
197
+ VECTOR4();
198
+ Vector4 *result = ALLOC(Vector4);
199
+ Vector4 *v2;
200
+ Data_Get_Struct(other, Vector4, v2);
201
+
202
+ result->x = v->x + v2->x;
203
+ result->y = v->y + v2->y;
204
+ result->z = v->z + v2->z;
205
+ result->w = v->w + v2->w;
206
+
207
+ return NUMERIX_WRAP(CLASS_OF(self), result);
208
+ }
209
+
210
+ VALUE rb_vector4_subtract(VALUE self, VALUE other) {
211
+ VECTOR4();
212
+ Vector4 *result = ALLOC(Vector4);
213
+ Vector4 *v2;
214
+ Data_Get_Struct(other, Vector4, v2);
215
+
216
+ result->x = v->x - v2->x;
217
+ result->y = v->y - v2->y;
218
+ result->z = v->z - v2->z;
219
+ result->w = v->w - v2->w;
220
+
221
+ return NUMERIX_WRAP(CLASS_OF(self), result);
222
+ }
223
+
224
+ VALUE rb_vector4_multiply(VALUE self, VALUE other) {
225
+ VECTOR4();
226
+ Vector4 *result = ALLOC(Vector4);
227
+
228
+ if (NUMERIX_TYPE_P(other, rb_cVector4)) {
229
+ Vector4 *v2;
230
+ Data_Get_Struct(other, Vector4, v2);
231
+ result->x = v->x * v2->x;
232
+ result->y = v->x * v2->y;
233
+ result->z = v->z * v2->z;
234
+ result->w = v->w * v2->w;
235
+ } else {
236
+ float scalar = NUM2FLT(other);
237
+ result->x = v->x * scalar;
238
+ result->y = v->y * scalar;
239
+ result->z = v->z * scalar;
240
+ result->w = v->w * scalar;
241
+ }
242
+
243
+ return NUMERIX_WRAP(CLASS_OF(self), result);
244
+ }
245
+
246
+ VALUE rb_vector4_divide(VALUE self, VALUE other) {
247
+ VECTOR4();
248
+ Vector4 *result = ALLOC(Vector4);
249
+
250
+ if (NUMERIX_TYPE_P(other, rb_cVector4)) {
251
+ Vector4 *v2;
252
+ Data_Get_Struct(other, Vector4, v2);
253
+ result->x = v->x / v2->x;
254
+ result->y = v->y / v2->y;
255
+ result->z = v->z / v2->z;
256
+ result->w = v->w / v2->w;
257
+ } else {
258
+ float scalar = 1.0f / NUM2FLT(other);
259
+ result->x = v->x * scalar;
260
+ result->y = v->y * scalar;
261
+ result->z = v->z * scalar;
262
+ result->w = v->w * scalar;
263
+ }
264
+
265
+ return NUMERIX_WRAP(CLASS_OF(self), result);
266
+ }
267
+
268
+ VALUE rb_vector4_equal(VALUE self, VALUE other) {
269
+ if (CLASS_OF(other) != CLASS_OF(self))
270
+ return Qfalse;
271
+ Vector4 *v1, *v2;
272
+ Data_Get_Struct(self, Vector4, v1);
273
+ Data_Get_Struct(other, Vector4, v2);
274
+ return FLT_EQUAL(v1->x, v2->x) && FLT_EQUAL(v1->y, v2->y) && FLT_EQUAL(v1->z, v2->z) && FLT_EQUAL(v1->w, v2->w) ? Qtrue : Qfalse;
275
+ }
276
+
277
+ VALUE rb_vector4_negate(VALUE self) {
278
+ VECTOR4();
279
+ Vector4 *result = ALLOC(Vector4);
280
+
281
+ result->x = -v->x;
282
+ result->y = -v->y;
283
+ result->z = -v->z;
284
+ result->w = -v->w;
285
+
286
+ return NUMERIX_WRAP(CLASS_OF(self), result);
287
+ }
288
+
289
+ VALUE rb_vector4_map(VALUE self) {
290
+ VECTOR4();
291
+ Vector4 *result = ALLOC(Vector4);
292
+
293
+ result->x = NUM2FLT(rb_yield(DBL2NUM(v->x)));
294
+ result->y = NUM2FLT(rb_yield(DBL2NUM(v->y)));
295
+ result->z = NUM2FLT(rb_yield(DBL2NUM(v->z)));
296
+ result->w = NUM2FLT(rb_yield(DBL2NUM(v->w)));
297
+
298
+ return NUMERIX_WRAP(CLASS_OF(self), result);
299
+ }
300
+
301
+ VALUE rb_vector4_map_bang(VALUE self) {
302
+ VECTOR4();
303
+
304
+ v->x = NUM2FLT(rb_yield(DBL2NUM(v->x)));
305
+ v->y = NUM2FLT(rb_yield(DBL2NUM(v->y)));
306
+ v->z = NUM2FLT(rb_yield(DBL2NUM(v->z)));
307
+ v->w = NUM2FLT(rb_yield(DBL2NUM(v->w)));
308
+
309
+ return self;
310
+ }
311
+
312
+ VALUE rb_vector4_to_s(VALUE self) {
313
+ VECTOR4();
314
+ return rb_sprintf("<%f, %f, %f, %f>", v->x, v->y, v->z, v->w);
315
+ }
316
+
317
+ VALUE rb_vector4_to_a(VALUE self) {
318
+ VECTOR4();
319
+ VALUE ary = rb_ary_new_capa(4);
320
+ rb_ary_store(ary, 0, DBL2NUM(v->x));
321
+ rb_ary_store(ary, 1, DBL2NUM(v->y));
322
+ rb_ary_store(ary, 2, DBL2NUM(v->z));
323
+ rb_ary_store(ary, 3, DBL2NUM(v->w));
324
+ return ary;
325
+ }
326
+
327
+ VALUE rb_vector4_to_h(VALUE self) {
328
+ VECTOR4();
329
+ VALUE hash = rb_hash_new();
330
+ rb_hash_aset(hash, ID2SYM(rb_intern("x")), DBL2NUM(v->x));
331
+ rb_hash_aset(hash, ID2SYM(rb_intern("y")), DBL2NUM(v->y));
332
+ rb_hash_aset(hash, ID2SYM(rb_intern("z")), DBL2NUM(v->z));
333
+ rb_hash_aset(hash, ID2SYM(rb_intern("w")), DBL2NUM(v->w));
334
+ return hash;
335
+ }
336
+
337
+ VALUE rb_vector4_to_vec2(VALUE self) {
338
+ VECTOR4();
339
+ Vector2 *vec = ALLOC(Vector2);
340
+ vec->x = v->x;
341
+ vec->y = v->y;
342
+ return NUMERIX_WRAP(rb_cVector2, vec);
343
+ }
344
+
345
+ VALUE rb_vector4_to_vec3(VALUE self) {
346
+ VECTOR4();
347
+ Vector3 *vec = ALLOC(Vector3);
348
+ vec->x = v->x;
349
+ vec->y = v->y;
350
+ vec->z = v->z;
351
+ return NUMERIX_WRAP(rb_cVector3, vec);
352
+ }
353
+
354
+ VALUE rb_vector4_to_quaternion(VALUE self) {
355
+ VECTOR4();
356
+ Quaternion *q = ALLOC(Quaternion);
357
+ memcpy(q, v, sizeof(Vector4));
358
+ return NUMERIX_WRAP(rb_cQuaternion, q);
359
+ }
360
+
361
+ VALUE rb_vector4_to_plane(VALUE self) {
362
+ VECTOR4();
363
+ Plane *p = ALLOC(Plane);
364
+ memcpy(p, v, sizeof(Vector4));
365
+ return NUMERIX_WRAP(rb_cPlane, p);
366
+ }
367
+
368
+ VALUE rb_vector4_min_value(VALUE self) {
369
+ VECTOR4();
370
+ float m = NUMERIX_MIN(v->x, NUMERIX_MIN(v->y, NUMERIX_MIN(v->z, v->w)));
371
+ return DBL2NUM(m);
372
+ }
373
+
374
+ VALUE rb_vector4_max_value(VALUE self) {
375
+ VECTOR4();
376
+ float m = NUMERIX_MAX(v->x, NUMERIX_MAX(v->y, NUMERIX_MAX(v->z, v->w)));
377
+ return DBL2NUM(m);
378
+ }
379
+
380
+ VALUE rb_vector4_distance(VALUE self, VALUE other) {
381
+ Vector4 *v1, *v2;
382
+ Data_Get_Struct(self, Vector4, v1);
383
+ Data_Get_Struct(other, Vector4, v2);
384
+
385
+ float dx = v1->x - v2->x;
386
+ float dy = v1->y - v2->y;
387
+ float dz = v1->z - v2->z;
388
+ float dw = v1->w - v2->w;
389
+
390
+ return DBL2NUM(sqrtf(dx * dx + dy * dy + dz * dz + dw * dw));
391
+ }
392
+
393
+ VALUE rb_vector4_distance_squared(VALUE self, VALUE other) {
394
+ Vector4 *v1, *v2;
395
+ Data_Get_Struct(self, Vector4, v1);
396
+ Data_Get_Struct(other, Vector4, v2);
397
+
398
+ float dx = v1->x - v2->x;
399
+ float dy = v1->y - v2->y;
400
+ float dz = v1->z - v2->z;
401
+ float dw = v1->w - v2->w;
402
+
403
+ return DBL2NUM(dx * dx + dy * dy + dz * dz + dw * dw);
404
+ }
405
+
406
+ VALUE rb_vector4_normalize(VALUE self) {
407
+ VECTOR4();
408
+ Vector4 *result = ALLOC(Vector4);
409
+
410
+ float inv = 1.0f / sqrtf(v->x * v->x + v->y * v->y + v->z * v->z + v->w * v->w);
411
+ result->x = v->x * inv;
412
+ result->y = v->y * inv;
413
+ result->z = v->z * inv;
414
+ result->w = v->w * inv;
415
+
416
+ return NUMERIX_WRAP(CLASS_OF(self), result);
417
+ }
418
+
419
+ VALUE rb_vector4_lerp(VALUE self, VALUE other, VALUE amount) {
420
+ return rb_vector4_lerp_s(CLASS_OF(self), self, other, amount);
421
+ }
422
+
423
+ VALUE rb_vector4_transform(VALUE self, VALUE other) {
424
+ return rb_vector4_transform_s(CLASS_OF(self), self, other);
425
+ }
426
+
427
+ VALUE rb_vector4_abs(VALUE self) {
428
+ VECTOR4();
429
+ Vector4 *result = ALLOC(Vector4);
430
+
431
+ result->x = fabsf(v->x);
432
+ result->y = fabsf(v->y);
433
+ result->z = fabsf(v->z);
434
+ result->w = fabsf(v->w);
435
+
436
+ return NUMERIX_WRAP(CLASS_OF(self), result);
437
+ }
438
+
439
+ VALUE rb_vector4_sqrt(VALUE self) {
440
+ VECTOR4();
441
+ Vector4 *result = ALLOC(Vector4);
442
+
443
+ result->x = sqrtf(v->x);
444
+ result->y = sqrtf(v->y);
445
+ result->z = sqrtf(v->z);
446
+ result->w = sqrtf(v->w);
447
+
448
+ return NUMERIX_WRAP(CLASS_OF(self), result);
449
+ }
450
+
451
+ VALUE rb_vector4_pow(VALUE self, VALUE exponent) {
452
+ VECTOR4();
453
+ Vector4 *result = ALLOC(Vector4);
454
+ float e = fabsf(NUM2FLT(exponent));
455
+
456
+ result->x = powf(fabsf(v->x), e);
457
+ result->y = powf(fabsf(v->y), e);
458
+ result->z = powf(fabsf(v->z), e);
459
+ result->w = powf(fabsf(v->w), e);
460
+
461
+ return NUMERIX_WRAP(CLASS_OF(self), result);
462
+ }
463
+
464
+ VALUE rb_vector4_dot(VALUE self, VALUE other) {
465
+ Vector4 *v1, *v2;
466
+ Data_Get_Struct(self, Vector4, v1);
467
+ Data_Get_Struct(other, Vector4, v2);
468
+
469
+ return DBL2NUM(v1->x * v2->x + v1->y * v2->y + v1->z * v2->z + v1->w * v2->w);
470
+ }
471
+
472
+ VALUE rb_vector4_clamp(VALUE self, VALUE min, VALUE max) {
473
+ return rb_vector4_clamp_s(CLASS_OF(self), self, min, max);
474
+ }
475
+
476
+ VALUE rb_vector4_normalize_bang(VALUE self) {
477
+ VECTOR4();
478
+ float inv = 1.0f / sqrtf(v->x * v->x + v->y * v->y + v->z * v->z + v->w * v->w);
479
+ v->x = v->x * inv;
480
+ v->y = v->y * inv;
481
+ v->z = v->z * inv;
482
+ v->w = v->w * inv;
483
+
484
+ return self;
485
+ }
486
+
487
+ VALUE rb_vector4_lerp_bang(VALUE self, VALUE other, VALUE amount) {
488
+ Vector4 *v1, *v2;
489
+ Data_Get_Struct(self, Vector4, v1);
490
+ Data_Get_Struct(other, Vector4, v2);
491
+ float w = NUMERIX_CLAMP(NUM2FLT(amount), 0.0f, 1.0f);
492
+
493
+ v1->x = v1->x + (v2->x - v1->x) * w;
494
+ v1->y = v1->y + (v2->y - v1->y) * w;
495
+ v1->z = v1->z + (v2->z - v1->z) * w;
496
+ v1->w = v1->w + (v2->w - v1->w) * w;
497
+
498
+ return self;
499
+ }
500
+
501
+ VALUE rb_vector4_transform_bang(VALUE self, VALUE other) {
502
+ struct RData *rdata = RDATA(self);
503
+ VALUE result = rb_vector4_transform_s(rdata->basic.klass, self, other);
504
+ Vector4 *src;
505
+ Data_Get_Struct(result, Vector4, src);
506
+ memcpy(rdata->data, src, sizeof(Vector4));
507
+ return self;
508
+ }
509
+
510
+ VALUE rb_vector4_clamp_bang(VALUE self, VALUE min, VALUE max) {
511
+ struct RData *rdata = RDATA(self);
512
+ VALUE result = rb_vector4_clamp_s(rdata->basic.klass, self, min, max);
513
+ Vector4 *src;
514
+ Data_Get_Struct(result, Vector4, src);
515
+ memcpy(rdata->data, src, sizeof(Vector4));
516
+ return self;
517
+ }
518
+
519
+ static inline VALUE rb_vector4_clamp_s(VALUE klass, VALUE vector, VALUE minimum, VALUE maximum) {
520
+ Vector4 *v, *result;
521
+ Data_Get_Struct(vector, Vector4, v);
522
+ result = ALLOC(Vector4);
523
+ float x = v->x, y = v->y, z = v->z, w = v->w;
524
+
525
+ // This compare order is very important!!!
526
+ // We must follow HLSL behavior in the case user specified min value is bigger than max value.
527
+ if (NUMERIX_TYPE_P(minimum, rb_cVector4) && NUMERIX_TYPE_P(maximum, rb_cVector4)) {
528
+ Vector4 *min, *max;
529
+ Data_Get_Struct(minimum, Vector4, min);
530
+ Data_Get_Struct(maximum, Vector4, max);
531
+
532
+ x = NUMERIX_MIN(x, max->x);
533
+ x = NUMERIX_MAX(x, min->x);
534
+
535
+ y = NUMERIX_MIN(y, max->y);
536
+ y = NUMERIX_MAX(y, min->y);
537
+
538
+ z = NUMERIX_MIN(z, max->z);
539
+ z = NUMERIX_MAX(z, min->z);
540
+
541
+ w = NUMERIX_MIN(w, max->w);
542
+ w = NUMERIX_MAX(w, min->w);
543
+ } else {
544
+ float minf = NUM2FLT(minimum);
545
+ float maxf = NUM2FLT(maximum);
546
+
547
+ x = NUMERIX_MIN(x, maxf);
548
+ x = NUMERIX_MAX(x, minf);
549
+
550
+ y = NUMERIX_MIN(y, maxf);
551
+ y = NUMERIX_MAX(y, minf);
552
+
553
+ z = NUMERIX_MIN(z, maxf);
554
+ z = NUMERIX_MAX(z, minf);
555
+
556
+ w = NUMERIX_MIN(w, maxf);
557
+ w = NUMERIX_MAX(w, minf);
558
+ }
559
+
560
+ result->x = x;
561
+ result->y = y;
562
+ result->z = z;
563
+ result->w = w;
564
+ return NUMERIX_WRAP(klass, result);
565
+ }
566
+
567
+ static inline VALUE rb_vector4_lerp_s(VALUE klass, VALUE vec1, VALUE vec2, VALUE amount) {
568
+ Vector4 *v1, *v2, *result;
569
+ Data_Get_Struct(vec1, Vector4, v1);
570
+ Data_Get_Struct(vec2, Vector4, v2);
571
+ result = ALLOC(Vector4);
572
+
573
+ float w = NUMERIX_CLAMP(NUM2FLT(amount), 0.0f, 1.0f);
574
+
575
+ result->x = v1->x + (v2->x - v1->x) * w;
576
+ result->y = v1->y + (v2->y - v1->y) * w;
577
+ result->z = v1->z + (v2->z - v1->z) * w;
578
+ result->w = v1->w + (v2->w - v1->w) * w;
579
+
580
+ return NUMERIX_WRAP(klass, result);
581
+ }
582
+
583
+ static inline VALUE rb_vector4_transform_s(VALUE klass, VALUE vector, VALUE matrix) {
584
+ Vector4 *v, *result;
585
+ result = ALLOC(Vector4);
586
+
587
+ if (NUMERIX_TYPE_P(matrix, rb_cMatrix4x4)) {
588
+ Matrix4x4 *m;
589
+ Data_Get_Struct(matrix, Matrix4x4, m);
590
+ if (NUMERIX_TYPE_P(vector, rb_cVector2)) {
591
+ result->x = v->x * m->m11 + v->y * m->m21 + m->m41;
592
+ result->y = v->x * m->m12 + v->y * m->m22 + m->m42;
593
+ result->z = v->x * m->m13 + v->y * m->m23 + m->m43;
594
+ result->w = v->x * m->m14 + v->y * m->m24 + m->m44;
595
+ } else if (NUMERIX_TYPE_P(vector, rb_cVector3)) {
596
+ result->x = v->x * m->m11 + v->y * m->m21 + v->z * m->m31 + m->m41;
597
+ result->y = v->x * m->m12 + v->y * m->m22 + v->z * m->m32 + m->m42;
598
+ result->z = v->x * m->m13 + v->y * m->m23 + v->z * m->m33 + m->m43;
599
+ result->w = v->x * m->m14 + v->y * m->m24 + v->z * m->m34 + m->m44;
600
+ } else if (NUMERIX_TYPE_P(vector, rb_cVector4)) {
601
+ result->x = v->x * m->m11 + v->y * m->m21 + v->z * m->m31 + v->w * m->m41;
602
+ result->y = v->x * m->m12 + v->y * m->m22 + v->z * m->m32 + v->w * m->m42;
603
+ result->z = v->x * m->m13 + v->y * m->m23 + v->z * m->m33 + v->w * m->m43;
604
+ result->w = v->x * m->m14 + v->y * m->m24 + v->z * m->m34 + v->w * m->m44;
605
+ } else
606
+ rb_raise(rb_eTypeError, "%s is not a valid Vector type", CLASS_NAME(vector));
607
+ } else if (NUMERIX_TYPE_P(matrix, rb_cQuaternion)) {
608
+ Quaternion *q;
609
+ Data_Get_Struct(matrix, Quaternion, q);
610
+ float x2, y2, z2, wx2, wy2, wz2, xx2, xy2, xz2, yy2, yz2, zz2;
611
+ if (NUMERIX_TYPE_P(vector, rb_cVector2)) {
612
+ Vector2 *v2;
613
+ Data_Get_Struct(vector, Vector2, v2);
614
+ x2 = q->x + q->x;
615
+ y2 = q->y + q->y;
616
+ z2 = q->z + q->z;
617
+
618
+ wx2 = q->w * x2;
619
+ wy2 = q->w * y2;
620
+ wz2 = q->w * z2;
621
+ xx2 = q->x * x2;
622
+ xy2 = q->x * y2;
623
+ xz2 = q->x * z2;
624
+ yy2 = q->y * y2;
625
+ yz2 = q->y * z2;
626
+ zz2 = q->z * z2;
627
+
628
+ result->x = v2->x * (1.0f - yy2 - zz2) + v2->y * (xy2 - wz2);
629
+ result->y = v2->x * (xy2 + wz2) + v2->y * (1.0f - xx2 - zz2);
630
+ result->z = v2->x * (xz2 - wy2) + v2->y * (yz2 + wx2);
631
+ result->w = 1.0f;
632
+ } else if (NUMERIX_TYPE_P(vector, rb_cVector3)) {
633
+ Vector3 *v3;
634
+ Data_Get_Struct(vector, Vector3, v3);
635
+ x2 = q->x + q->x;
636
+ y2 = q->y + q->y;
637
+ z2 = q->z + q->z;
638
+
639
+ wx2 = q->w * x2;
640
+ wy2 = q->w * y2;
641
+ wz2 = q->w * z2;
642
+ xx2 = q->x * x2;
643
+ xy2 = q->x * y2;
644
+ xz2 = q->x * z2;
645
+ yy2 = q->y * y2;
646
+ yz2 = q->y * z2;
647
+ zz2 = q->z * z2;
648
+
649
+ result->x = v3->x * (1.0f - yy2 - zz2) + v3->y * (xy2 - wz2) + v3->z * (xz2 + wy2);
650
+ result->y = v3->x * (xy2 + wz2) + v3->y * (1.0f - xx2 - zz2) + v3->z * (yz2 - wx2);
651
+ result->z = v3->x * (xz2 - wy2) + v3->y * (yz2 + wx2) + v3->z * (1.0f - xx2 - yy2);
652
+ result->w = 1.0f;
653
+ } else if (NUMERIX_TYPE_P(vector, rb_cVector4)) {
654
+ Vector4 *v4;
655
+ Data_Get_Struct(vector, Vector4, v4);
656
+ x2 = q->x + q->x;
657
+ y2 = q->y + q->y;
658
+ z2 = q->z + q->z;
659
+
660
+ wx2 = q->w * x2;
661
+ wy2 = q->w * y2;
662
+ wz2 = q->w * z2;
663
+ xx2 = q->x * x2;
664
+ xy2 = q->x * y2;
665
+ xz2 = q->x * z2;
666
+ yy2 = q->y * y2;
667
+ yz2 = q->y * z2;
668
+ zz2 = q->z * z2;
669
+
670
+ result->x = v4->x * (1.0f - yy2 - zz2) + v4->y * (xy2 - wz2) + v4->z * (xz2 + wy2);
671
+ result->y = v4->x * (xy2 + wz2) + v4->y * (1.0f - xx2 - zz2) + v4->z * (yz2 - wx2);
672
+ result->z = v4->x * (xz2 - wy2) + v4->y * (yz2 + wx2) + v4->z * (1.0f - xx2 - yy2);
673
+ result->w = v4->w;
674
+ } else
675
+ rb_raise(rb_eTypeError, "%s is not a valid Vector type", CLASS_NAME(vector));
676
+
677
+ } else {
678
+ rb_raise(rb_eTypeError, "%s is not a valid Matrix4x4 or Quaternion", CLASS_NAME(matrix));
679
+ return Qnil;
680
+ }
681
+
682
+ return NUMERIX_WRAP(klass, result);
683
+ }
684
+
685
+ static inline VALUE rb_vector4_min_s(VALUE klass, VALUE vec1, VALUE vec2) {
686
+ Vector4 *v1, *v2, *result;
687
+ Data_Get_Struct(vec1, Vector4, v1);
688
+ Data_Get_Struct(vec2, Vector4, v2);
689
+ result = ALLOC(Vector4);
690
+
691
+ result->x = NUMERIX_MIN(v1->x, v2->x);
692
+ result->y = NUMERIX_MIN(v1->y, v2->y);
693
+ result->z = NUMERIX_MIN(v1->z, v2->z);
694
+ result->w = NUMERIX_MIN(v1->w, v2->w);
695
+
696
+ return NUMERIX_WRAP(klass, result);
697
+ }
698
+
699
+ static inline VALUE rb_vector4_max_s(VALUE klass, VALUE vec1, VALUE vec2) {
700
+ Vector4 *v1, *v2, *result;
701
+ Data_Get_Struct(vec1, Vector4, v1);
702
+ Data_Get_Struct(vec2, Vector4, v2);
703
+ result = ALLOC(Vector4);
704
+
705
+ result->x = NUMERIX_MAX(v1->x, v2->x);
706
+ result->y = NUMERIX_MAX(v1->y, v2->y);
707
+ result->z = NUMERIX_MAX(v1->z, v2->z);
708
+ result->w = NUMERIX_MAX(v1->w, v2->w);
709
+
710
+ return NUMERIX_WRAP(klass, result);
711
+ }
712
+
713
+ VALUE rb_vector4_create_norm(VALUE klass, VALUE x, VALUE y, VALUE z, VALUE w) {
714
+ Vector4 *v = ALLOC(Vector4);
715
+ float vx = NUM2FLT(x);
716
+ float vy = NUM2FLT(y);
717
+ float vz = NUM2FLT(z);
718
+ float vw = NUM2FLT(w);
719
+
720
+ float inv = 1.0f / sqrtf(vx * vx + vy * vy + vz * vz + vw * vw);
721
+ v->x = vx * inv;
722
+ v->y = vy * inv;
723
+ v->z = vz * inv;
724
+ v->w = vw * inv;
725
+
726
+ return NUMERIX_WRAP(klass, v);
727
+ }