larb 0.1.0 → 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 (51) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +4 -0
  3. data/README.md +14 -1
  4. data/ext/larb/color.c +446 -0
  5. data/ext/larb/color.h +35 -0
  6. data/ext/larb/extconf.rb +11 -0
  7. data/ext/larb/larb.c +27 -0
  8. data/ext/larb/larb.h +8 -0
  9. data/ext/larb/mat2.c +300 -0
  10. data/ext/larb/mat2.h +30 -0
  11. data/ext/larb/mat2d.c +380 -0
  12. data/ext/larb/mat2d.h +35 -0
  13. data/ext/larb/mat3.c +469 -0
  14. data/ext/larb/mat3.h +33 -0
  15. data/ext/larb/mat4.c +671 -0
  16. data/ext/larb/mat4.h +31 -0
  17. data/ext/larb/quat.c +523 -0
  18. data/ext/larb/quat.h +39 -0
  19. data/ext/larb/quat2.c +473 -0
  20. data/ext/larb/quat2.h +39 -0
  21. data/ext/larb/vec2.c +342 -0
  22. data/ext/larb/vec2.h +43 -0
  23. data/ext/larb/vec3.c +503 -0
  24. data/ext/larb/vec3.h +52 -0
  25. data/ext/larb/vec4.c +340 -0
  26. data/ext/larb/vec4.h +38 -0
  27. data/lib/larb/version.rb +5 -0
  28. data/lib/larb.rb +2 -14
  29. data/test/larb/color_test.rb +278 -0
  30. data/test/larb/mat2_test.rb +144 -0
  31. data/test/larb/mat2d_test.rb +172 -0
  32. data/test/larb/mat3_test.rb +147 -0
  33. data/test/larb/mat4_test.rb +270 -0
  34. data/test/larb/quat2_test.rb +161 -0
  35. data/test/larb/quat_test.rb +224 -0
  36. data/test/larb/vec2_test.rb +251 -0
  37. data/test/larb/vec3_test.rb +310 -0
  38. data/test/larb/vec4_test.rb +189 -0
  39. data/test/test_helper.rb +4 -0
  40. metadata +53 -14
  41. data/Rakefile +0 -11
  42. data/lib/larb/color.rb +0 -148
  43. data/lib/larb/mat2.rb +0 -119
  44. data/lib/larb/mat2d.rb +0 -180
  45. data/lib/larb/mat3.rb +0 -238
  46. data/lib/larb/mat4.rb +0 -329
  47. data/lib/larb/quat.rb +0 -238
  48. data/lib/larb/quat2.rb +0 -193
  49. data/lib/larb/vec2.rb +0 -150
  50. data/lib/larb/vec3.rb +0 -218
  51. data/lib/larb/vec4.rb +0 -125
data/ext/larb/vec2.c ADDED
@@ -0,0 +1,342 @@
1
+ #include "vec2.h"
2
+
3
+ #include <math.h>
4
+
5
+ static void vec2_free(void *ptr) {
6
+ xfree(ptr);
7
+ }
8
+
9
+ static size_t vec2_memsize(const void *ptr) {
10
+ return sizeof(Vec2Data);
11
+ }
12
+
13
+ static const rb_data_type_t vec2_type = {
14
+ "Vec2",
15
+ {0, vec2_free, vec2_memsize},
16
+ 0,
17
+ 0,
18
+ RUBY_TYPED_FREE_IMMEDIATELY,
19
+ };
20
+
21
+ static VALUE cVec2 = Qnil;
22
+
23
+ static double value_to_double(VALUE value) {
24
+ VALUE coerced = rb_funcall(value, rb_intern("to_f"), 0);
25
+ return NUM2DBL(coerced);
26
+ }
27
+
28
+ static Vec2Data *vec2_get(VALUE obj) {
29
+ Vec2Data *data = NULL;
30
+ TypedData_Get_Struct(obj, Vec2Data, &vec2_type, data);
31
+ return data;
32
+ }
33
+
34
+ static VALUE vec2_build(VALUE klass, double x, double y) {
35
+ VALUE obj = vec2_alloc(klass);
36
+ Vec2Data *data = vec2_get(obj);
37
+ data->x = x;
38
+ data->y = y;
39
+ return obj;
40
+ }
41
+
42
+ VALUE vec2_alloc(VALUE klass) {
43
+ Vec2Data *data = ALLOC(Vec2Data);
44
+ data->x = 0.0;
45
+ data->y = 0.0;
46
+ return TypedData_Wrap_Struct(klass, &vec2_type, data);
47
+ }
48
+
49
+ VALUE vec2_initialize(int argc, VALUE *argv, VALUE self) {
50
+ VALUE vx = Qnil;
51
+ VALUE vy = Qnil;
52
+ Vec2Data *data = vec2_get(self);
53
+
54
+ rb_scan_args(argc, argv, "02", &vx, &vy);
55
+ data->x = NIL_P(vx) ? 0.0 : value_to_double(vx);
56
+ data->y = NIL_P(vy) ? 0.0 : value_to_double(vy);
57
+
58
+ return self;
59
+ }
60
+
61
+ static VALUE vec2_class_bracket(VALUE klass, VALUE x, VALUE y) {
62
+ return vec2_build(klass, value_to_double(x), value_to_double(y));
63
+ }
64
+
65
+ static VALUE vec2_class_zero(VALUE klass) {
66
+ return vec2_build(klass, 0.0, 0.0);
67
+ }
68
+
69
+ static VALUE vec2_class_one(VALUE klass) {
70
+ return vec2_build(klass, 1.0, 1.0);
71
+ }
72
+
73
+ static VALUE vec2_get_x(VALUE self) {
74
+ Vec2Data *data = vec2_get(self);
75
+ return DBL2NUM(data->x);
76
+ }
77
+
78
+ static VALUE vec2_set_x(VALUE self, VALUE value) {
79
+ Vec2Data *data = vec2_get(self);
80
+ data->x = NUM2DBL(value);
81
+ return value;
82
+ }
83
+
84
+ static VALUE vec2_get_y(VALUE self) {
85
+ Vec2Data *data = vec2_get(self);
86
+ return DBL2NUM(data->y);
87
+ }
88
+
89
+ static VALUE vec2_set_y(VALUE self, VALUE value) {
90
+ Vec2Data *data = vec2_get(self);
91
+ data->y = NUM2DBL(value);
92
+ return value;
93
+ }
94
+
95
+ VALUE vec2_add(VALUE self, VALUE other) {
96
+ Vec2Data *a = vec2_get(self);
97
+ Vec2Data *b = vec2_get(other);
98
+ return vec2_build(rb_obj_class(self), a->x + b->x, a->y + b->y);
99
+ }
100
+
101
+ VALUE vec2_sub(VALUE self, VALUE other) {
102
+ Vec2Data *a = vec2_get(self);
103
+ Vec2Data *b = vec2_get(other);
104
+ return vec2_build(rb_obj_class(self), a->x - b->x, a->y - b->y);
105
+ }
106
+
107
+ VALUE vec2_mul(VALUE self, VALUE scalar) {
108
+ Vec2Data *a = vec2_get(self);
109
+ double s = NUM2DBL(scalar);
110
+ return vec2_build(rb_obj_class(self), a->x * s, a->y * s);
111
+ }
112
+
113
+ VALUE vec2_div(VALUE self, VALUE scalar) {
114
+ Vec2Data *a = vec2_get(self);
115
+ double s = NUM2DBL(scalar);
116
+ return vec2_build(rb_obj_class(self), a->x / s, a->y / s);
117
+ }
118
+
119
+ VALUE vec2_negate(VALUE self) {
120
+ Vec2Data *a = vec2_get(self);
121
+ return vec2_build(rb_obj_class(self), -a->x, -a->y);
122
+ }
123
+
124
+ VALUE vec2_dot(VALUE self, VALUE other) {
125
+ Vec2Data *a = vec2_get(self);
126
+ Vec2Data *b = vec2_get(other);
127
+ return DBL2NUM(a->x * b->x + a->y * b->y);
128
+ }
129
+
130
+ VALUE vec2_length(VALUE self) {
131
+ Vec2Data *a = vec2_get(self);
132
+ return DBL2NUM(sqrt(a->x * a->x + a->y * a->y));
133
+ }
134
+
135
+ VALUE vec2_length_squared(VALUE self) {
136
+ Vec2Data *a = vec2_get(self);
137
+ return DBL2NUM(a->x * a->x + a->y * a->y);
138
+ }
139
+
140
+ VALUE vec2_normalize(VALUE self) {
141
+ Vec2Data *a = vec2_get(self);
142
+ double len = sqrt(a->x * a->x + a->y * a->y);
143
+ return vec2_build(rb_obj_class(self), a->x / len, a->y / len);
144
+ }
145
+
146
+ VALUE vec2_normalize_bang(VALUE self) {
147
+ Vec2Data *a = vec2_get(self);
148
+ double len = sqrt(a->x * a->x + a->y * a->y);
149
+ a->x /= len;
150
+ a->y /= len;
151
+ return self;
152
+ }
153
+
154
+ VALUE vec2_lerp(VALUE self, VALUE other, VALUE t) {
155
+ Vec2Data *a = vec2_get(self);
156
+ Vec2Data *b = vec2_get(other);
157
+ double s = NUM2DBL(t);
158
+ return vec2_build(rb_obj_class(self), a->x + (b->x - a->x) * s,
159
+ a->y + (b->y - a->y) * s);
160
+ }
161
+
162
+ VALUE vec2_to_a(VALUE self) {
163
+ Vec2Data *a = vec2_get(self);
164
+ VALUE ary = rb_ary_new_capa(2);
165
+ rb_ary_push(ary, DBL2NUM(a->x));
166
+ rb_ary_push(ary, DBL2NUM(a->y));
167
+ return ary;
168
+ }
169
+
170
+ VALUE vec2_aref(VALUE self, VALUE index) {
171
+ VALUE ary = vec2_to_a(self);
172
+ return rb_ary_entry(ary, NUM2LONG(index));
173
+ }
174
+
175
+ VALUE vec2_aset(VALUE self, VALUE index, VALUE value) {
176
+ Vec2Data *a = vec2_get(self);
177
+ long idx = NUM2LONG(index);
178
+ if (idx == 0) {
179
+ a->x = NUM2DBL(value);
180
+ } else {
181
+ a->y = NUM2DBL(value);
182
+ }
183
+ return value;
184
+ }
185
+
186
+ VALUE vec2_equal(VALUE self, VALUE other) {
187
+ if (!rb_obj_is_kind_of(other, cVec2)) {
188
+ return Qfalse;
189
+ }
190
+ Vec2Data *a = vec2_get(self);
191
+ Vec2Data *b = vec2_get(other);
192
+ return (a->x == b->x && a->y == b->y) ? Qtrue : Qfalse;
193
+ }
194
+
195
+ VALUE vec2_near(int argc, VALUE *argv, VALUE self) {
196
+ VALUE other = Qnil;
197
+ VALUE epsilon = Qnil;
198
+
199
+ rb_scan_args(argc, argv, "11", &other, &epsilon);
200
+ Vec2Data *a = vec2_get(self);
201
+ Vec2Data *b = vec2_get(other);
202
+ double eps = NIL_P(epsilon) ? 1e-6 : NUM2DBL(epsilon);
203
+
204
+ if (fabs(a->x - b->x) < eps && fabs(a->y - b->y) < eps) {
205
+ return Qtrue;
206
+ }
207
+ return Qfalse;
208
+ }
209
+
210
+ VALUE vec2_angle(VALUE self) {
211
+ Vec2Data *a = vec2_get(self);
212
+ return DBL2NUM(atan2(a->y, a->x));
213
+ }
214
+
215
+ VALUE vec2_angle_to(VALUE self, VALUE other) {
216
+ Vec2Data *a = vec2_get(self);
217
+ Vec2Data *b = vec2_get(other);
218
+ return DBL2NUM(atan2(b->y - a->y, b->x - a->x));
219
+ }
220
+
221
+ VALUE vec2_rotate(VALUE self, VALUE radians) {
222
+ Vec2Data *a = vec2_get(self);
223
+ double r = NUM2DBL(radians);
224
+ double c = cos(r);
225
+ double s = sin(r);
226
+ return vec2_build(rb_obj_class(self), a->x * c - a->y * s,
227
+ a->x * s + a->y * c);
228
+ }
229
+
230
+ VALUE vec2_distance(VALUE self, VALUE other) {
231
+ Vec2Data *a = vec2_get(self);
232
+ Vec2Data *b = vec2_get(other);
233
+ double dx = a->x - b->x;
234
+ double dy = a->y - b->y;
235
+ return DBL2NUM(sqrt(dx * dx + dy * dy));
236
+ }
237
+
238
+ VALUE vec2_distance_squared(VALUE self, VALUE other) {
239
+ Vec2Data *a = vec2_get(self);
240
+ Vec2Data *b = vec2_get(other);
241
+ double dx = a->x - b->x;
242
+ double dy = a->y - b->y;
243
+ return DBL2NUM(dx * dx + dy * dy);
244
+ }
245
+
246
+ VALUE vec2_cross(VALUE self, VALUE other) {
247
+ Vec2Data *a = vec2_get(self);
248
+ Vec2Data *b = vec2_get(other);
249
+ return DBL2NUM(a->x * b->y - a->y * b->x);
250
+ }
251
+
252
+ VALUE vec2_perpendicular(VALUE self) {
253
+ Vec2Data *a = vec2_get(self);
254
+ return vec2_build(rb_obj_class(self), -a->y, a->x);
255
+ }
256
+
257
+ VALUE vec2_reflect(VALUE self, VALUE normal) {
258
+ Vec2Data *a = vec2_get(self);
259
+ Vec2Data *n = vec2_get(normal);
260
+ double dot = a->x * n->x + a->y * n->y;
261
+ return vec2_build(rb_obj_class(self), a->x - n->x * (2.0 * dot),
262
+ a->y - n->y * (2.0 * dot));
263
+ }
264
+
265
+ VALUE vec2_clamp_length(VALUE self, VALUE max_length) {
266
+ Vec2Data *a = vec2_get(self);
267
+ double max_len = NUM2DBL(max_length);
268
+ double len_sq = a->x * a->x + a->y * a->y;
269
+ if (len_sq <= max_len * max_len) {
270
+ return self;
271
+ }
272
+ double scale = max_len / sqrt(len_sq);
273
+ return vec2_build(rb_obj_class(self), a->x * scale, a->y * scale);
274
+ }
275
+
276
+ VALUE vec2_to_vec3(int argc, VALUE *argv, VALUE self) {
277
+ VALUE vz = Qnil;
278
+ Vec2Data *a = vec2_get(self);
279
+
280
+ rb_scan_args(argc, argv, "01", &vz);
281
+ VALUE vec3_class = rb_const_get(mLarb, rb_intern("Vec3"));
282
+ return rb_funcall(vec3_class, rb_intern("new"), 3, DBL2NUM(a->x),
283
+ DBL2NUM(a->y), NIL_P(vz) ? DBL2NUM(0.0) : vz);
284
+ }
285
+
286
+ VALUE vec2_inspect(VALUE self) {
287
+ Vec2Data *a = vec2_get(self);
288
+ VALUE sx = rb_funcall(DBL2NUM(a->x), rb_intern("to_s"), 0);
289
+ VALUE sy = rb_funcall(DBL2NUM(a->y), rb_intern("to_s"), 0);
290
+ VALUE str = rb_str_new_cstr("Vec2[");
291
+ rb_str_concat(str, sx);
292
+ rb_str_cat_cstr(str, ", ");
293
+ rb_str_concat(str, sy);
294
+ rb_str_cat_cstr(str, "]");
295
+ return str;
296
+ }
297
+
298
+ void Init_vec2(VALUE module) {
299
+ cVec2 = rb_define_class_under(module, "Vec2", rb_cObject);
300
+
301
+ rb_define_alloc_func(cVec2, vec2_alloc);
302
+ rb_define_method(cVec2, "initialize", vec2_initialize, -1);
303
+
304
+ rb_define_singleton_method(cVec2, "[]", vec2_class_bracket, 2);
305
+ rb_define_singleton_method(cVec2, "zero", vec2_class_zero, 0);
306
+ rb_define_singleton_method(cVec2, "one", vec2_class_one, 0);
307
+
308
+ rb_define_method(cVec2, "x", vec2_get_x, 0);
309
+ rb_define_method(cVec2, "x=", vec2_set_x, 1);
310
+ rb_define_method(cVec2, "y", vec2_get_y, 0);
311
+ rb_define_method(cVec2, "y=", vec2_set_y, 1);
312
+
313
+ rb_define_method(cVec2, "+", vec2_add, 1);
314
+ rb_define_method(cVec2, "-", vec2_sub, 1);
315
+ rb_define_method(cVec2, "*", vec2_mul, 1);
316
+ rb_define_method(cVec2, "/", vec2_div, 1);
317
+ rb_define_method(cVec2, "-@", vec2_negate, 0);
318
+
319
+ rb_define_method(cVec2, "dot", vec2_dot, 1);
320
+ rb_define_method(cVec2, "length", vec2_length, 0);
321
+ rb_define_method(cVec2, "length_squared", vec2_length_squared, 0);
322
+ rb_define_method(cVec2, "normalize", vec2_normalize, 0);
323
+ rb_define_method(cVec2, "normalize!", vec2_normalize_bang, 0);
324
+ rb_define_method(cVec2, "lerp", vec2_lerp, 2);
325
+ rb_define_method(cVec2, "to_a", vec2_to_a, 0);
326
+ rb_define_method(cVec2, "[]", vec2_aref, 1);
327
+ rb_define_method(cVec2, "[]=", vec2_aset, 2);
328
+ rb_define_method(cVec2, "==", vec2_equal, 1);
329
+ rb_define_method(cVec2, "near?", vec2_near, -1);
330
+ rb_define_method(cVec2, "angle", vec2_angle, 0);
331
+ rb_define_method(cVec2, "angle_to", vec2_angle_to, 1);
332
+ rb_define_method(cVec2, "rotate", vec2_rotate, 1);
333
+ rb_define_method(cVec2, "distance", vec2_distance, 1);
334
+ rb_define_method(cVec2, "distance_squared", vec2_distance_squared, 1);
335
+ rb_define_method(cVec2, "cross", vec2_cross, 1);
336
+ rb_define_method(cVec2, "perpendicular", vec2_perpendicular, 0);
337
+ rb_define_method(cVec2, "reflect", vec2_reflect, 1);
338
+ rb_define_method(cVec2, "clamp_length", vec2_clamp_length, 1);
339
+ rb_define_method(cVec2, "to_vec3", vec2_to_vec3, -1);
340
+ rb_define_method(cVec2, "inspect", vec2_inspect, 0);
341
+ rb_define_alias(cVec2, "to_s", "inspect");
342
+ }
data/ext/larb/vec2.h ADDED
@@ -0,0 +1,43 @@
1
+ #ifndef VEC2_H
2
+ #define VEC2_H
3
+
4
+ #include "larb.h"
5
+
6
+ typedef struct {
7
+ double x;
8
+ double y;
9
+ } Vec2Data;
10
+
11
+ void Init_vec2(VALUE module);
12
+ VALUE vec2_alloc(VALUE klass);
13
+ VALUE vec2_initialize(int argc, VALUE *argv, VALUE self);
14
+
15
+ VALUE vec2_add(VALUE self, VALUE other);
16
+ VALUE vec2_sub(VALUE self, VALUE other);
17
+ VALUE vec2_mul(VALUE self, VALUE scalar);
18
+ VALUE vec2_div(VALUE self, VALUE scalar);
19
+ VALUE vec2_negate(VALUE self);
20
+ VALUE vec2_dot(VALUE self, VALUE other);
21
+ VALUE vec2_length(VALUE self);
22
+ VALUE vec2_length_squared(VALUE self);
23
+ VALUE vec2_normalize(VALUE self);
24
+ VALUE vec2_normalize_bang(VALUE self);
25
+ VALUE vec2_lerp(VALUE self, VALUE other, VALUE t);
26
+ VALUE vec2_to_a(VALUE self);
27
+ VALUE vec2_aref(VALUE self, VALUE index);
28
+ VALUE vec2_aset(VALUE self, VALUE index, VALUE value);
29
+ VALUE vec2_equal(VALUE self, VALUE other);
30
+ VALUE vec2_near(int argc, VALUE *argv, VALUE self);
31
+ VALUE vec2_angle(VALUE self);
32
+ VALUE vec2_angle_to(VALUE self, VALUE other);
33
+ VALUE vec2_rotate(VALUE self, VALUE radians);
34
+ VALUE vec2_distance(VALUE self, VALUE other);
35
+ VALUE vec2_distance_squared(VALUE self, VALUE other);
36
+ VALUE vec2_cross(VALUE self, VALUE other);
37
+ VALUE vec2_perpendicular(VALUE self);
38
+ VALUE vec2_reflect(VALUE self, VALUE normal);
39
+ VALUE vec2_clamp_length(VALUE self, VALUE max_length);
40
+ VALUE vec2_to_vec3(int argc, VALUE *argv, VALUE self);
41
+ VALUE vec2_inspect(VALUE self);
42
+
43
+ #endif