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,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 */