numerix 1.0.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.
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,641 @@
1
+
2
+ #include "vector2.h"
3
+
4
+ void Init_vector2(VALUE outer) {
5
+ rb_define_alloc_func(rb_cVector2, rb_vector2_alloc);
6
+
7
+ // Instance Methods
8
+ rb_define_method(rb_cVector2, "initialize", rb_vector2_initialize, -1);
9
+ rb_define_method(rb_cVector2, "length", rb_vector2_length, 0);
10
+ rb_define_method(rb_cVector2, "length_squared", rb_vector2_length_squared, 0);
11
+ rb_define_method(rb_cVector2, "one?", rb_vector2_one_p, 0);
12
+ rb_define_method(rb_cVector2, "zero?", rb_vector2_zero_p, 0);
13
+ rb_define_method(rb_cVector2, "min_value", rb_vector2_min_value, 0);
14
+ rb_define_method(rb_cVector2, "max_value", rb_vector2_max_value, 0);
15
+ rb_define_method(rb_cVector2, "distance", rb_vector2_distance, 1);
16
+ rb_define_method(rb_cVector2, "distance_squared", rb_vector2_distance_squared, 1);
17
+ rb_define_method(rb_cVector2, "normalize", rb_vector2_normalize, 0);
18
+ rb_define_method(rb_cVector2, "normalize!", rb_vector2_normalize_bang, 0);
19
+ rb_define_method(rb_cVector2, "lerp", rb_vector2_lerp, 2);
20
+ rb_define_method(rb_cVector2, "lerp!", rb_vector2_lerp_bang, 2);
21
+ rb_define_method(rb_cVector2, "transform", rb_vector2_transform, 1);
22
+ rb_define_method(rb_cVector2, "transform!", rb_vector2_transform_bang, 1);
23
+ rb_define_method(rb_cVector2, "transform_normal", rb_vector2_transform_normal, 1);
24
+ rb_define_method(rb_cVector2, "transform_normal!", rb_vector2_transform_normal_bang, 1);
25
+ rb_define_method(rb_cVector2, "abs", rb_vector2_abs, 0);
26
+ rb_define_method(rb_cVector2, "sqrt", rb_vector2_sqrt, 0);
27
+ rb_define_method(rb_cVector2, "dot", rb_vector2_dot, 1);
28
+ rb_define_method(rb_cVector2, "cross_product", rb_vector2_cross_product, 1);
29
+ rb_define_method(rb_cVector2, "clamp", rb_vector2_clamp, 2);
30
+ rb_define_method(rb_cVector2, "clamp!", rb_vector2_clamp_bang, 2);
31
+ rb_define_method(rb_cVector2, "reflect", rb_vector2_reflect, 2);
32
+ rb_define_method(rb_cVector2, "reflect!", rb_vector2_reflect_bang, 2);
33
+ rb_define_method(rb_cVector2, "angle", rb_vector2_angle, 1);
34
+ rb_define_method(rb_cVector2, "map", rb_vector2_map, 0);
35
+ rb_define_method(rb_cVector2, "map!", rb_vector2_map_bang, 0);
36
+
37
+ // Conversion
38
+ rb_define_method(rb_cVector2, "to_s", rb_vector2_to_s, 0);
39
+ rb_define_method(rb_cVector2, "to_a", rb_vector2_to_a, 0);
40
+ rb_define_method(rb_cVector2, "to_h", rb_vector2_to_h, 0);
41
+ rb_define_method(rb_cVector2, "to_vec3", rb_vector2_to_vec3, 0);
42
+ rb_define_method(rb_cVector2, "to_vec4", rb_vector2_to_vec4, 0);
43
+
44
+ // Operators
45
+ rb_define_method(rb_cVector2, "+", rb_vector2_add, 1);
46
+ rb_define_method(rb_cVector2, "-", rb_vector2_subtract, 1);
47
+ rb_define_method(rb_cVector2, "*", rb_vector2_multiply, 1);
48
+ rb_define_method(rb_cVector2, "/", rb_vector2_divide, 1);
49
+ rb_define_method(rb_cVector2, "==", rb_vector2_equal, 1);
50
+ rb_define_method(rb_cVector2, "-@", rb_vector2_negate, 0);
51
+ rb_define_method(rb_cVector2, "**", rb_vector2_pow, 1);
52
+
53
+ // Alias
54
+ rb_define_alias(rb_cVector2, "magnitude", "length");
55
+ rb_define_alias(rb_cVector2, "elements", "to_a");
56
+ rb_define_alias(rb_cVector2, "collect", "map");
57
+ rb_define_alias(rb_cVector2, "collect!", "map!");
58
+
59
+ // Singleton Methods
60
+ rb_define_singleton_method(rb_cVector2, "zero", rb_vector2_alloc, 0);
61
+ rb_define_singleton_method(rb_cVector2, "one", rb_vector2_one, 0);
62
+ rb_define_singleton_method(rb_cVector2, "unit_x", rb_vector2_unit_x, 0);
63
+ rb_define_singleton_method(rb_cVector2, "unit_y", rb_vector2_unit_y, 0);
64
+ rb_define_singleton_method(rb_cVector2, "create_norm", rb_vector2_create_norm, 2);
65
+ rb_define_singleton_method(rb_cVector2, "clamp", rb_vector2_clamp_s, 3);
66
+ rb_define_singleton_method(rb_cVector2, "lerp", rb_vector2_lerp_s, 3);
67
+ rb_define_singleton_method(rb_cVector2, "min", rb_vector2_min_s, 2);
68
+ rb_define_singleton_method(rb_cVector2, "max", rb_vector2_max_s, 2);
69
+ }
70
+
71
+ static VALUE rb_vector2_alloc(VALUE klass) {
72
+ void *v = ALLOC(Vector2);
73
+ memset(v, 0, sizeof(Vector2));
74
+ return NUMERIX_WRAP(klass, v);
75
+ }
76
+
77
+ VALUE rb_vector2_initialize(int argc, VALUE *argv, VALUE self) {
78
+ VECTOR2();
79
+ switch (argc) {
80
+ case 0:
81
+ break;
82
+ case 1: {
83
+ float value = NUM2FLT(argv[0]);
84
+ v->x = value;
85
+ v->y = value;
86
+ break;
87
+ }
88
+ case 2: {
89
+ v->x = NUM2FLT(argv[0]);
90
+ v->y = NUM2FLT(argv[1]);
91
+ break;
92
+ }
93
+ default:
94
+ rb_raise(rb_eArgError, "wrong number of arguments (given %d, expected 0, 1, 2)", argc);
95
+ break;
96
+ }
97
+ return Qnil;
98
+ }
99
+
100
+ VALUE rb_vector2_one(VALUE klass) {
101
+ Vector2 *v = ALLOC(Vector2);
102
+ v->x = 1.0f;
103
+ v->y = 1.0f;
104
+ return NUMERIX_WRAP(klass, v);
105
+ }
106
+
107
+ VALUE rb_vector2_unit_x(VALUE klass) {
108
+ Vector2 *v = ALLOC(Vector2);
109
+ v->x = 1.0f;
110
+ v->y = 0.0f;
111
+ return NUMERIX_WRAP(klass, v);
112
+ }
113
+
114
+ VALUE rb_vector2_unit_y(VALUE klass) {
115
+ Vector2 *v = ALLOC(Vector2);
116
+ v->x = 0.0f;
117
+ v->y = 1.0f;
118
+ return NUMERIX_WRAP(klass, v);
119
+ }
120
+
121
+ VALUE rb_vector2_length(VALUE self) {
122
+ VECTOR2();
123
+ return DBL2NUM(sqrtf(v->x * v->x + v->y * v->y));
124
+ }
125
+
126
+ VALUE rb_vector2_length_squared(VALUE self) {
127
+ VECTOR2();
128
+ return DBL2NUM(v->x * v->x + v->y * v->y);
129
+ }
130
+
131
+ VALUE rb_vector2_add(VALUE self, VALUE other) {
132
+ Vector2 *v1, *v2, *result;
133
+ Data_Get_Struct(self, Vector2, v1);
134
+ Data_Get_Struct(other, Vector2, v2);
135
+ result = ALLOC(Vector2);
136
+
137
+ result->x = v1->x + v2->x;
138
+ result->y = v1->y + v2->y;
139
+
140
+ return NUMERIX_WRAP(CLASS_OF(self), result);
141
+ }
142
+
143
+ VALUE rb_vector2_subtract(VALUE self, VALUE other) {
144
+ Vector2 *v1, *v2, *result;
145
+ Data_Get_Struct(self, Vector2, v1);
146
+ Data_Get_Struct(other, Vector2, v2);
147
+ result = ALLOC(Vector2);
148
+
149
+ result->x = v1->x - v2->x;
150
+ result->y = v1->y - v2->y;
151
+
152
+ return NUMERIX_WRAP(CLASS_OF(self), result);
153
+ }
154
+
155
+ VALUE rb_vector2_multiply(VALUE self, VALUE other) {
156
+ Vector2 *v1, *result;
157
+ Data_Get_Struct(self, Vector2, v1);
158
+ result = ALLOC(Vector2);
159
+
160
+ if (NUMERIX_TYPE_P(other, rb_cVector2)) {
161
+ Vector2 *v2;
162
+ Data_Get_Struct(other, Vector2, v2);
163
+ result->x = v1->x * v2->x;
164
+ result->y = v1->y * v2->y;
165
+ } else {
166
+ float scalar = NUM2FLT(other);
167
+ result->x = v1->x * scalar;
168
+ result->y = v1->y * scalar;
169
+ }
170
+ return NUMERIX_WRAP(CLASS_OF(self), result);
171
+ }
172
+
173
+ VALUE rb_vector2_divide(VALUE self, VALUE other) {
174
+ Vector2 *v1, *result;
175
+ Data_Get_Struct(self, Vector2, v1);
176
+ result = ALLOC(Vector2);
177
+
178
+ if (NUMERIX_TYPE_P(other, rb_cVector2)) {
179
+ Vector2 *v2;
180
+ Data_Get_Struct(other, Vector2, v2);
181
+ result->x = v1->x / v2->x;
182
+ result->y = v1->y / v2->y;
183
+ } else {
184
+ float scalar = 1.0f / NUM2FLT(other);
185
+ result->x = v1->x * scalar;
186
+ result->y = v1->y * scalar;
187
+ }
188
+ return NUMERIX_WRAP(CLASS_OF(self), result);
189
+ }
190
+
191
+ VALUE rb_vector2_equal(VALUE self, VALUE other) {
192
+ if (CLASS_OF(other) != CLASS_OF(self))
193
+ return Qfalse;
194
+ Vector2 *v1, *v2;
195
+ Data_Get_Struct(self, Vector2, v1);
196
+ Data_Get_Struct(other, Vector2, v2);
197
+ return FLT_EQUAL(v1->x, v2->x) && FLT_EQUAL(v1->y, v2->y) ? Qtrue : Qfalse;
198
+ }
199
+
200
+ VALUE rb_vector2_pow(VALUE self, VALUE exponent) {
201
+ VECTOR2();
202
+ Vector2 *result = ALLOC(Vector2);
203
+ float e = fabsf(NUM2FLT(exponent));
204
+
205
+ result->x = powf(fabsf(v->x), e);
206
+ result->y = powf(fabsf(v->y), e);
207
+
208
+ return NUMERIX_WRAP(CLASS_OF(self), result);
209
+ }
210
+
211
+ VALUE rb_vector2_negate(VALUE self) {
212
+ VECTOR2();
213
+ Vector2 *result = ALLOC(Vector2);
214
+
215
+ result->x = -v->x;
216
+ result->y = -v->y;
217
+
218
+ return NUMERIX_WRAP(CLASS_OF(self), result);
219
+ }
220
+
221
+ VALUE rb_vector2_min_value(VALUE self) {
222
+ VECTOR2();
223
+ float m = NUMERIX_MIN(v->x, v->y);
224
+ return DBL2NUM(m);
225
+ }
226
+
227
+ VALUE rb_vector2_max_value(VALUE self) {
228
+ VECTOR2();
229
+ float m = NUMERIX_MAX(v->x, v->y);
230
+ return DBL2NUM(m);
231
+ }
232
+
233
+ VALUE rb_vector2_distance(VALUE self, VALUE other) {
234
+ Vector2 *v1, *v2;
235
+ Data_Get_Struct(self, Vector2, v1);
236
+ Data_Get_Struct(other, Vector2, v2);
237
+
238
+ float dx = v1->x - v2->x;
239
+ float dy = v1->y - v2->y;
240
+
241
+ return DBL2NUM(sqrtf(dx * dx + dy * dy));
242
+ }
243
+
244
+ VALUE rb_vector2_distance_squared(VALUE self, VALUE other) {
245
+ Vector2 *v1, *v2;
246
+ Data_Get_Struct(self, Vector2, v1);
247
+ Data_Get_Struct(other, Vector2, v2);
248
+
249
+ float dx = v1->x - v2->x;
250
+ float dy = v1->y - v2->y;
251
+
252
+ return DBL2NUM(dx * dx + dy * dy);
253
+ }
254
+
255
+ VALUE rb_vector2_normalize(VALUE self) {
256
+ VECTOR2();
257
+ Vector2 *result = ALLOC(Vector2);
258
+
259
+ float inv = 1.0f / sqrtf(v->x * v->x + v->y * v->y);
260
+ result->x = v->x * inv;
261
+ result->y = v->y * inv;
262
+
263
+ return NUMERIX_WRAP(CLASS_OF(self), result);
264
+ }
265
+
266
+ VALUE rb_vector2_lerp(VALUE self, VALUE other, VALUE amount) {
267
+ return rb_vector2_lerp_s(CLASS_OF(self), self, other, amount);
268
+ }
269
+
270
+ VALUE rb_vector2_transform(VALUE self, VALUE other) {
271
+ VECTOR2();
272
+ Vector2 *result = ALLOC(Vector2);
273
+
274
+ if (NUMERIX_TYPE_P(other, rb_cMatrix3x2)) {
275
+ Matrix3x2 *m3;
276
+ Data_Get_Struct(other, Matrix3x2, m3);
277
+
278
+ result->x = v->x * m3->m11 + v->y * m3->m21 + m3->m31;
279
+ result->y = v->x * m3->m12 + v->y * m3->m22 + m3->m32;
280
+ } else if (NUMERIX_TYPE_P(other, rb_cMatrix4x4)) {
281
+ Matrix4x4 *m4;
282
+ Data_Get_Struct(other, Matrix4x4, m4);
283
+
284
+ result->x = v->x * m4->m11 + v->y * m4->m21 + m4->m41;
285
+ result->y = v->x * m4->m12 + v->y * m4->m22 + m4->m42;
286
+ } else {
287
+ Quaternion *q;
288
+ Data_Get_Struct(other, Quaternion, q);
289
+
290
+ float x2 = q->x + q->x;
291
+ float y2 = q->y + q->y;
292
+ float z2 = q->z + q->z;
293
+
294
+ float wz2 = q->w * z2;
295
+ float xx2 = q->x * x2;
296
+ float xy2 = q->x * y2;
297
+ float yy2 = q->y * y2;
298
+ float zz2 = q->z * z2;
299
+
300
+ result->x = v->x * (1.0f - yy2 - zz2) + v->y * (xy2 - wz2);
301
+ result->y = v->x * (xy2 + wz2) + v->y * (1.0f - xx2 - zz2);
302
+ }
303
+
304
+ return NUMERIX_WRAP(CLASS_OF(self), result);
305
+ }
306
+
307
+ VALUE rb_vector2_map(VALUE self) {
308
+ VECTOR2();
309
+ Vector2 *result = ALLOC(Vector2);
310
+
311
+ result->x = NUM2FLT(rb_yield(DBL2NUM(v->x)));
312
+ result->y = NUM2FLT(rb_yield(DBL2NUM(v->y)));
313
+
314
+ return NUMERIX_WRAP(CLASS_OF(self), result);
315
+ }
316
+
317
+ VALUE rb_vector2_map_bang(VALUE self) {
318
+ VECTOR2();
319
+
320
+ v->x = NUM2FLT(rb_yield(DBL2NUM(v->x)));
321
+ v->y = NUM2FLT(rb_yield(DBL2NUM(v->y)));
322
+
323
+ return self;
324
+ }
325
+
326
+ VALUE rb_vector2_abs(VALUE self) {
327
+ VECTOR2();
328
+ Vector2 *result = ALLOC(Vector2);
329
+
330
+ result->x = fabsf(v->x);
331
+ result->y = fabsf(v->y);
332
+
333
+ return NUMERIX_WRAP(CLASS_OF(self), result);
334
+ }
335
+
336
+ VALUE rb_vector2_sqrt(VALUE self) {
337
+ VECTOR2();
338
+ Vector2 *result = ALLOC(Vector2);
339
+
340
+ result->x = sqrtf(v->x);
341
+ result->y = sqrtf(v->y);
342
+
343
+ return NUMERIX_WRAP(CLASS_OF(self), result);
344
+ }
345
+
346
+ VALUE rb_vector2_dot(VALUE self, VALUE other) {
347
+ Vector2 *v1, *v2;
348
+ Data_Get_Struct(self, Vector2, v1);
349
+ Data_Get_Struct(other, Vector2, v2);
350
+
351
+ return DBL2NUM(v1->x * v2->x + v1->y * v2->y);
352
+ }
353
+
354
+ VALUE rb_vector2_clamp(VALUE self, VALUE min, VALUE max) {
355
+ return rb_vector2_clamp_s(CLASS_OF(self), self, min, max);
356
+ }
357
+
358
+ VALUE rb_vector2_to_s(VALUE self) {
359
+ VECTOR2();
360
+ return rb_sprintf("<%f, %f>", v->x, v->y);
361
+ }
362
+
363
+ VALUE rb_vector2_to_a(VALUE self) {
364
+ VECTOR2();
365
+ VALUE ary = rb_ary_new_capa(2);
366
+ rb_ary_store(ary, 0, DBL2NUM(v->x));
367
+ rb_ary_store(ary, 1, DBL2NUM(v->y));
368
+ return ary;
369
+ }
370
+
371
+ VALUE rb_vector2_to_h(VALUE self) {
372
+ VECTOR2();
373
+ VALUE hash = rb_hash_new();
374
+ rb_hash_aset(hash, ID2SYM(rb_intern("x")), DBL2NUM(v->x));
375
+ rb_hash_aset(hash, ID2SYM(rb_intern("y")), DBL2NUM(v->y));
376
+ return hash;
377
+ }
378
+
379
+ VALUE rb_vector2_to_vec3(VALUE self) {
380
+ VECTOR2();
381
+ Vector3 *vec = ALLOC(Vector3);
382
+ vec->x = v->x;
383
+ vec->y = v->y;
384
+ vec->z = 0.0f;
385
+ return NUMERIX_WRAP(rb_cVector3, vec);
386
+ }
387
+
388
+ VALUE rb_vector2_to_vec4(VALUE self) {
389
+ VECTOR2();
390
+ Vector4 *vec = ALLOC(Vector4);
391
+ vec->x = v->x;
392
+ vec->y = v->y;
393
+ vec->z = 0.0f;
394
+ vec->w = 0.0f;
395
+ return NUMERIX_WRAP(rb_cVector4, vec);
396
+ }
397
+
398
+ VALUE rb_vector2_normalize_bang(VALUE self) {
399
+ VECTOR2();
400
+ float inv = 1.0f / sqrtf(v->x * v->x + v->y * v->y);
401
+ v->x = v->x * inv;
402
+ v->y = v->y * inv;
403
+
404
+ return self;
405
+ }
406
+
407
+ VALUE rb_vector2_lerp_bang(VALUE self, VALUE other, VALUE amount) {
408
+ Vector2 *v1, *v2;
409
+ Data_Get_Struct(self, Vector2, v1);
410
+ Data_Get_Struct(other, Vector2, v2);
411
+ float w = NUMERIX_CLAMP(NUM2FLT(amount), 0.0f, 1.0f);
412
+
413
+ v1->x = v1->x + (v2->x - v1->x) * w;
414
+ v1->y = v1->y + (v2->y - v1->y) * w;
415
+
416
+ return self;
417
+ }
418
+
419
+ VALUE rb_vector2_transform_bang(VALUE self, VALUE other) {
420
+ VECTOR2();
421
+
422
+ if (NUMERIX_TYPE_P(other, rb_cMatrix3x2)) {
423
+ Matrix3x2 *m3;
424
+ Data_Get_Struct(other, Matrix3x2, m3);
425
+
426
+ v->x = v->x * m3->m11 + v->y * m3->m21 + m3->m31;
427
+ v->y = v->x * m3->m12 + v->y * m3->m22 + m3->m32;
428
+ } else if (NUMERIX_TYPE_P(other, rb_cMatrix4x4)) {
429
+ Matrix4x4 *m4;
430
+ Data_Get_Struct(other, Matrix4x4, m4);
431
+
432
+ v->x = v->x * m4->m11 + v->y * m4->m21 + m4->m41;
433
+ v->y = v->x * m4->m12 + v->y * m4->m22 + m4->m42;
434
+ } else {
435
+ Quaternion *q;
436
+ Data_Get_Struct(other, Quaternion, q);
437
+
438
+ float x2 = q->x + q->x;
439
+ float y2 = q->y + q->y;
440
+ float z2 = q->z + q->z;
441
+
442
+ float wz2 = q->w * z2;
443
+ float xx2 = q->x * x2;
444
+ float xy2 = q->x * y2;
445
+ float yy2 = q->y * y2;
446
+ float zz2 = q->z * z2;
447
+
448
+ v->x = v->x * (1.0f - yy2 - zz2) + v->y * (xy2 - wz2);
449
+ v->y = v->x * (xy2 + wz2) + v->y * (1.0f - xx2 - zz2);
450
+ }
451
+
452
+ return self;
453
+ }
454
+
455
+ VALUE rb_vector2_transform_normal(VALUE self, VALUE other) {
456
+ Vector2 *v, *result;
457
+ Data_Get_Struct(self, Vector2, v);
458
+ result = ALLOC(Vector2);
459
+ if (NUMERIX_TYPE_P(other, rb_cMatrix3x2)) {
460
+ Matrix3x2 *m3;
461
+ Data_Get_Struct(other, Matrix3x2, m3);
462
+
463
+ result->x = v->x * m3->m11 + v->y * m3->m21;
464
+ result->y = v->x * m3->m12 + v->y * m3->m22;
465
+ } else {
466
+ Matrix4x4 *m4;
467
+ Data_Get_Struct(other, Matrix4x4, m4);
468
+
469
+ result->x = v->x * m4->m11 + v->y * m4->m21;
470
+ result->y = v->x * m4->m12 + v->y * m4->m22;
471
+ }
472
+
473
+ return NUMERIX_WRAP(CLASS_OF(self), result);
474
+ }
475
+
476
+ VALUE rb_vector2_transform_normal_bang(VALUE self, VALUE other) {
477
+ VECTOR2();
478
+ if (NUMERIX_TYPE_P(other, rb_cMatrix3x2)) {
479
+ Matrix3x2 *m3;
480
+ Data_Get_Struct(other, Matrix3x2, m3);
481
+
482
+ v->x = v->x * m3->m11 + v->y * m3->m21;
483
+ v->y = v->x * m3->m12 + v->y * m3->m22;
484
+ } else {
485
+ Matrix4x4 *m4;
486
+ Data_Get_Struct(other, Matrix4x4, m4);
487
+
488
+ v->x = v->x * m4->m11 + v->y * m4->m21;
489
+ v->y = v->x * m4->m12 + v->y * m4->m22;
490
+ }
491
+
492
+ return self;
493
+ }
494
+
495
+ VALUE rb_vector2_clamp_bang(VALUE self, VALUE min, VALUE max) {
496
+ struct RData *rdata = RDATA(self);
497
+ VALUE result = rb_vector2_clamp_s(rdata->basic.klass, self, min, max);
498
+ Vector2 *src;
499
+ Data_Get_Struct(result, Vector2, src);
500
+ memcpy(rdata->data, src, sizeof(Vector2));
501
+ return self;
502
+ }
503
+
504
+ VALUE rb_vector2_one_p(VALUE self) {
505
+ VECTOR2();
506
+ return v->x == 1.0f && v->y == 1.0f ? Qtrue : Qfalse;
507
+ }
508
+
509
+ VALUE rb_vector2_zero_p(VALUE self) {
510
+ VECTOR2();
511
+ return v->x == 0.0f && v->y == 0.0f ? Qtrue : Qfalse;
512
+ }
513
+
514
+ VALUE rb_vector2_reflect(VALUE self, VALUE other) {
515
+ Vector2 *v1, *v2, *result;
516
+ Data_Get_Struct(self, Vector2, v1);
517
+ Data_Get_Struct(other, Vector2, v2);
518
+ result = ALLOC(Vector2);
519
+
520
+ float dot = v1->x * v2->x + v1->y * v2->y;
521
+ result->x = v1->x - 2.0f * dot * v2->x;
522
+ result->y = v1->y - 2.0f * dot * v2->y;
523
+
524
+ return NUMERIX_WRAP(CLASS_OF(self), result);
525
+ }
526
+
527
+ VALUE rb_vector2_reflect_bang(VALUE self, VALUE other) {
528
+ Vector2 *v1, *v2;
529
+ Data_Get_Struct(self, Vector2, v1);
530
+ Data_Get_Struct(other, Vector2, v2);
531
+
532
+ float dot = v1->x * v2->x + v1->y * v2->y;
533
+ v1->x = v1->x - 2.0f * dot * v2->x;
534
+ v1->y = v1->y - 2.0f * dot * v2->y;
535
+
536
+ return self;
537
+ }
538
+
539
+ VALUE rb_vector2_angle(VALUE self, VALUE other) {
540
+ Vector2 *v1, *v2;
541
+ Data_Get_Struct(self, Vector2, v1);
542
+ Data_Get_Struct(other, Vector2, v2);
543
+
544
+ const float rad = 180.0f / NUMERIX_PI;
545
+ float s = v1->x * v2->y - v2->x * v1->y;
546
+ float c = v1->x * v2->x + v1->y * v2->y;
547
+
548
+ return DBL2NUM(atan2f(s, c) * rad);
549
+ }
550
+
551
+ VALUE rb_vector2_cross_product(VALUE self, VALUE other) {
552
+ Vector2 *v1, *v2;
553
+ Data_Get_Struct(self, Vector2, v1);
554
+ Data_Get_Struct(other, Vector2, v2);
555
+
556
+ return DBL2NUM(v1->x * v2->y - v1->y * v2->x);
557
+ }
558
+
559
+ static inline VALUE rb_vector2_clamp_s(VALUE klass, VALUE vector, VALUE minimum, VALUE maximum) {
560
+ Vector2 *v, *result;
561
+ Data_Get_Struct(vector, Vector2, v);
562
+ result = ALLOC(Vector2);
563
+ float x = v->x, y = v->y;
564
+
565
+ // This compare order is very important!
566
+ // Required in the case user specified min value is bigger than max value.
567
+ if (NUMERIX_TYPE_P(minimum, rb_cVector2) && NUMERIX_TYPE_P(maximum, rb_cVector2)) {
568
+ Vector2 *min, *max;
569
+ Data_Get_Struct(minimum, Vector2, min);
570
+ Data_Get_Struct(maximum, Vector2, max);
571
+
572
+ x = NUMERIX_MIN(x, max->x);
573
+ x = NUMERIX_MAX(x, min->x);
574
+
575
+ y = NUMERIX_MIN(y, max->y);
576
+ y = NUMERIX_MAX(y, min->y);
577
+ } else {
578
+ float minf = NUM2FLT(minimum);
579
+ float maxf = NUM2FLT(maximum);
580
+
581
+ x = NUMERIX_MIN(x, maxf);
582
+ x = NUMERIX_MAX(x, minf);
583
+
584
+ y = NUMERIX_MIN(y, maxf);
585
+ y = NUMERIX_MAX(y, minf);
586
+ }
587
+
588
+ result->x = x;
589
+ result->y = y;
590
+ return NUMERIX_WRAP(klass, result);
591
+ }
592
+
593
+ static inline VALUE rb_vector2_lerp_s(VALUE klass, VALUE vec1, VALUE vec2, VALUE amount) {
594
+ Vector2 *v1, *v2, *result;
595
+ Data_Get_Struct(vec1, Vector2, v1);
596
+ Data_Get_Struct(vec2, Vector2, v2);
597
+ result = ALLOC(Vector2);
598
+
599
+ float w = NUMERIX_CLAMP(NUM2FLT(amount), 0.0f, 1.0f);
600
+
601
+ result->x = v1->x + (v2->x - v1->x) * w;
602
+ result->y = v1->y + (v2->y - v1->y) * w;
603
+
604
+ return NUMERIX_WRAP(klass, result);
605
+ }
606
+
607
+ static inline VALUE rb_vector2_min_s(VALUE klass, VALUE vec1, VALUE vec2) {
608
+ Vector2 *v1, *v2, *result;
609
+ Data_Get_Struct(vec1, Vector2, v1);
610
+ Data_Get_Struct(vec2, Vector2, v2);
611
+ result = ALLOC(Vector2);
612
+
613
+ result->x = NUMERIX_MIN(v1->x, v2->x);
614
+ result->y = NUMERIX_MIN(v1->y, v2->y);
615
+
616
+ return NUMERIX_WRAP(klass, result);
617
+ }
618
+
619
+ static inline VALUE rb_vector2_max_s(VALUE klass, VALUE vec1, VALUE vec2) {
620
+ Vector2 *v1, *v2, *result;
621
+ Data_Get_Struct(vec1, Vector2, v1);
622
+ Data_Get_Struct(vec2, Vector2, v2);
623
+ result = ALLOC(Vector2);
624
+
625
+ result->x = NUMERIX_MAX(v1->x, v2->x);
626
+ result->y = NUMERIX_MAX(v1->y, v2->y);
627
+
628
+ return NUMERIX_WRAP(klass, result);
629
+ }
630
+
631
+ VALUE rb_vector2_create_norm(VALUE klass, VALUE x, VALUE y) {
632
+ Vector2 *v = ALLOC(Vector2);
633
+ float vx = NUM2FLT(x);
634
+ float vy = NUM2FLT(y);
635
+
636
+ float inv = 1.0f / sqrtf(vx * vx + vy * vy);
637
+ v->x = vx * inv;
638
+ v->y = vy * inv;
639
+
640
+ return NUMERIX_WRAP(klass, v);
641
+ }
@@ -0,0 +1,64 @@
1
+ #ifndef NUMERIX_VECTOR2_H
2
+ #define NUMERIX_VECTOR2_H 1
3
+
4
+ #include "common.h"
5
+ #include "vector_base.h"
6
+
7
+ void Init_vector2(VALUE outer);
8
+ static VALUE rb_vector2_alloc(VALUE klass);
9
+ VALUE rb_vector2_initialize(int argc, VALUE *argv, VALUE self);
10
+
11
+ // Instance
12
+ VALUE rb_vector2_length(VALUE self);
13
+ VALUE rb_vector2_length_squared(VALUE self);
14
+ VALUE rb_vector2_add(VALUE self, VALUE other);
15
+ VALUE rb_vector2_subtract(VALUE self, VALUE other);
16
+ VALUE rb_vector2_multiply(VALUE self, VALUE other);
17
+ VALUE rb_vector2_divide(VALUE self, VALUE other);
18
+ VALUE rb_vector2_equal(VALUE self, VALUE other);
19
+ VALUE rb_vector2_negate(VALUE self);
20
+ VALUE rb_vector2_one_p(VALUE self);
21
+ VALUE rb_vector2_zero_p(VALUE self);
22
+ VALUE rb_vector2_min_value(VALUE self);
23
+ VALUE rb_vector2_max_value(VALUE self);
24
+ VALUE rb_vector2_distance(VALUE self, VALUE other);
25
+ VALUE rb_vector2_distance_squared(VALUE self, VALUE other);
26
+ VALUE rb_vector2_normalize(VALUE self);
27
+ VALUE rb_vector2_normalize_bang(VALUE self);
28
+ VALUE rb_vector2_lerp(VALUE self, VALUE other, VALUE amount);
29
+ VALUE rb_vector2_lerp_bang(VALUE self, VALUE other, VALUE amount);
30
+ VALUE rb_vector2_transform(VALUE self, VALUE other);
31
+ VALUE rb_vector2_transform_bang(VALUE self, VALUE other);
32
+ VALUE rb_vector2_transform_normal(VALUE self, VALUE other);
33
+ VALUE rb_vector2_transform_normal_bang(VALUE self, VALUE other);
34
+ VALUE rb_vector2_abs(VALUE self);
35
+ VALUE rb_vector2_sqrt(VALUE self);
36
+ VALUE rb_vector2_pow(VALUE self, VALUE exponent);
37
+ VALUE rb_vector2_dot(VALUE self, VALUE other);
38
+ VALUE rb_vector2_cross_product(VALUE self, VALUE other);
39
+ VALUE rb_vector2_clamp(VALUE self, VALUE min, VALUE max);
40
+ VALUE rb_vector2_clamp_bang(VALUE self, VALUE min, VALUE max);
41
+ VALUE rb_vector2_reflect(VALUE self, VALUE other);
42
+ VALUE rb_vector2_reflect_bang(VALUE self, VALUE other);
43
+ VALUE rb_vector2_angle(VALUE self, VALUE other);
44
+ VALUE rb_vector2_map(VALUE self);
45
+ VALUE rb_vector2_map_bang(VALUE self);
46
+
47
+ // Conversion
48
+ VALUE rb_vector2_to_s(VALUE self);
49
+ VALUE rb_vector2_to_a(VALUE self);
50
+ VALUE rb_vector2_to_h(VALUE self);
51
+ VALUE rb_vector2_to_vec3(VALUE self);
52
+ VALUE rb_vector2_to_vec4(VALUE self);
53
+
54
+ // Class
55
+ VALUE rb_vector2_one(VALUE klass);
56
+ VALUE rb_vector2_unit_x(VALUE klass);
57
+ VALUE rb_vector2_unit_y(VALUE klass);
58
+ VALUE rb_vector2_create_norm(VALUE klass, VALUE x, VALUE y);
59
+ static inline VALUE rb_vector2_clamp_s(VALUE klass, VALUE vector, VALUE min, VALUE max);
60
+ static inline VALUE rb_vector2_lerp_s(VALUE klass, VALUE vec1, VALUE vec2, VALUE amount);
61
+ static inline VALUE rb_vector2_min_s(VALUE klass, VALUE vec1, VALUE vec2);
62
+ static inline VALUE rb_vector2_max_s(VALUE klass, VALUE vec1, VALUE vec2);
63
+
64
+ #endif /* NUMERIX_VECTOR2_H */