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/vec4.c ADDED
@@ -0,0 +1,340 @@
1
+ #include "vec4.h"
2
+
3
+ #include <math.h>
4
+
5
+ static void vec4_free(void *ptr) {
6
+ xfree(ptr);
7
+ }
8
+
9
+ static size_t vec4_memsize(const void *ptr) {
10
+ return sizeof(Vec4Data);
11
+ }
12
+
13
+ static const rb_data_type_t vec4_type = {
14
+ "Vec4",
15
+ {0, vec4_free, vec4_memsize},
16
+ 0,
17
+ 0,
18
+ RUBY_TYPED_FREE_IMMEDIATELY,
19
+ };
20
+
21
+ static VALUE cVec4 = 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 Vec4Data *vec4_get(VALUE obj) {
29
+ Vec4Data *data = NULL;
30
+ TypedData_Get_Struct(obj, Vec4Data, &vec4_type, data);
31
+ return data;
32
+ }
33
+
34
+ static VALUE vec4_build(VALUE klass, double x, double y, double z, double w) {
35
+ VALUE obj = vec4_alloc(klass);
36
+ Vec4Data *data = vec4_get(obj);
37
+ data->x = x;
38
+ data->y = y;
39
+ data->z = z;
40
+ data->w = w;
41
+ return obj;
42
+ }
43
+
44
+ VALUE vec4_alloc(VALUE klass) {
45
+ Vec4Data *data = ALLOC(Vec4Data);
46
+ data->x = 0.0;
47
+ data->y = 0.0;
48
+ data->z = 0.0;
49
+ data->w = 1.0;
50
+ return TypedData_Wrap_Struct(klass, &vec4_type, data);
51
+ }
52
+
53
+ VALUE vec4_initialize(int argc, VALUE *argv, VALUE self) {
54
+ VALUE vx = Qnil;
55
+ VALUE vy = Qnil;
56
+ VALUE vz = Qnil;
57
+ VALUE vw = Qnil;
58
+ Vec4Data *data = vec4_get(self);
59
+
60
+ rb_scan_args(argc, argv, "04", &vx, &vy, &vz, &vw);
61
+ data->x = NIL_P(vx) ? 0.0 : value_to_double(vx);
62
+ data->y = NIL_P(vy) ? 0.0 : value_to_double(vy);
63
+ data->z = NIL_P(vz) ? 0.0 : value_to_double(vz);
64
+ data->w = NIL_P(vw) ? 1.0 : value_to_double(vw);
65
+
66
+ return self;
67
+ }
68
+
69
+ static VALUE vec4_class_bracket(int argc, VALUE *argv, VALUE klass) {
70
+ VALUE vx = Qnil;
71
+ VALUE vy = Qnil;
72
+ VALUE vz = Qnil;
73
+ VALUE vw = Qnil;
74
+
75
+ rb_scan_args(argc, argv, "31", &vx, &vy, &vz, &vw);
76
+ return vec4_build(klass, value_to_double(vx), value_to_double(vy),
77
+ value_to_double(vz), NIL_P(vw) ? 1.0 : value_to_double(vw));
78
+ }
79
+
80
+ static VALUE vec4_class_zero(VALUE klass) {
81
+ return vec4_build(klass, 0.0, 0.0, 0.0, 0.0);
82
+ }
83
+
84
+ static VALUE vec4_class_one(VALUE klass) {
85
+ return vec4_build(klass, 1.0, 1.0, 1.0, 1.0);
86
+ }
87
+
88
+ static VALUE vec4_get_x(VALUE self) {
89
+ Vec4Data *data = vec4_get(self);
90
+ return DBL2NUM(data->x);
91
+ }
92
+
93
+ static VALUE vec4_set_x(VALUE self, VALUE value) {
94
+ Vec4Data *data = vec4_get(self);
95
+ data->x = value_to_double(value);
96
+ return value;
97
+ }
98
+
99
+ static VALUE vec4_get_y(VALUE self) {
100
+ Vec4Data *data = vec4_get(self);
101
+ return DBL2NUM(data->y);
102
+ }
103
+
104
+ static VALUE vec4_set_y(VALUE self, VALUE value) {
105
+ Vec4Data *data = vec4_get(self);
106
+ data->y = value_to_double(value);
107
+ return value;
108
+ }
109
+
110
+ static VALUE vec4_get_z(VALUE self) {
111
+ Vec4Data *data = vec4_get(self);
112
+ return DBL2NUM(data->z);
113
+ }
114
+
115
+ static VALUE vec4_set_z(VALUE self, VALUE value) {
116
+ Vec4Data *data = vec4_get(self);
117
+ data->z = value_to_double(value);
118
+ return value;
119
+ }
120
+
121
+ static VALUE vec4_get_w(VALUE self) {
122
+ Vec4Data *data = vec4_get(self);
123
+ return DBL2NUM(data->w);
124
+ }
125
+
126
+ static VALUE vec4_set_w(VALUE self, VALUE value) {
127
+ Vec4Data *data = vec4_get(self);
128
+ data->w = value_to_double(value);
129
+ return value;
130
+ }
131
+
132
+ VALUE vec4_add(VALUE self, VALUE other) {
133
+ Vec4Data *a = vec4_get(self);
134
+ Vec4Data *b = vec4_get(other);
135
+ return vec4_build(rb_obj_class(self), a->x + b->x, a->y + b->y,
136
+ a->z + b->z, a->w + b->w);
137
+ }
138
+
139
+ VALUE vec4_sub(VALUE self, VALUE other) {
140
+ Vec4Data *a = vec4_get(self);
141
+ Vec4Data *b = vec4_get(other);
142
+ return vec4_build(rb_obj_class(self), a->x - b->x, a->y - b->y,
143
+ a->z - b->z, a->w - b->w);
144
+ }
145
+
146
+ VALUE vec4_mul(VALUE self, VALUE scalar) {
147
+ Vec4Data *a = vec4_get(self);
148
+ double s = value_to_double(scalar);
149
+ return vec4_build(rb_obj_class(self), a->x * s, a->y * s, a->z * s,
150
+ a->w * s);
151
+ }
152
+
153
+ VALUE vec4_div(VALUE self, VALUE scalar) {
154
+ Vec4Data *a = vec4_get(self);
155
+ double s = value_to_double(scalar);
156
+ return vec4_build(rb_obj_class(self), a->x / s, a->y / s, a->z / s,
157
+ a->w / s);
158
+ }
159
+
160
+ VALUE vec4_negate(VALUE self) {
161
+ Vec4Data *a = vec4_get(self);
162
+ return vec4_build(rb_obj_class(self), -a->x, -a->y, -a->z, -a->w);
163
+ }
164
+
165
+ VALUE vec4_dot(VALUE self, VALUE other) {
166
+ Vec4Data *a = vec4_get(self);
167
+ Vec4Data *b = vec4_get(other);
168
+ return DBL2NUM(a->x * b->x + a->y * b->y + a->z * b->z + a->w * b->w);
169
+ }
170
+
171
+ VALUE vec4_length(VALUE self) {
172
+ Vec4Data *a = vec4_get(self);
173
+ return DBL2NUM(sqrt(a->x * a->x + a->y * a->y + a->z * a->z + a->w * a->w));
174
+ }
175
+
176
+ VALUE vec4_length_squared(VALUE self) {
177
+ Vec4Data *a = vec4_get(self);
178
+ return DBL2NUM(a->x * a->x + a->y * a->y + a->z * a->z + a->w * a->w);
179
+ }
180
+
181
+ VALUE vec4_normalize(VALUE self) {
182
+ Vec4Data *a = vec4_get(self);
183
+ double len = sqrt(a->x * a->x + a->y * a->y + a->z * a->z + a->w * a->w);
184
+ return vec4_build(rb_obj_class(self), a->x / len, a->y / len, a->z / len,
185
+ a->w / len);
186
+ }
187
+
188
+ VALUE vec4_normalize_bang(VALUE self) {
189
+ Vec4Data *a = vec4_get(self);
190
+ double len = sqrt(a->x * a->x + a->y * a->y + a->z * a->z + a->w * a->w);
191
+ a->x /= len;
192
+ a->y /= len;
193
+ a->z /= len;
194
+ a->w /= len;
195
+ return self;
196
+ }
197
+
198
+ VALUE vec4_perspective_divide(VALUE self) {
199
+ Vec4Data *a = vec4_get(self);
200
+ VALUE vec3_class = rb_const_get(mLarb, rb_intern("Vec3"));
201
+
202
+ if (a->w == 0.0 || a->w == 1.0) {
203
+ return rb_funcall(vec3_class, rb_intern("new"), 3, DBL2NUM(a->x),
204
+ DBL2NUM(a->y), DBL2NUM(a->z));
205
+ }
206
+
207
+ return rb_funcall(vec3_class, rb_intern("new"), 3, DBL2NUM(a->x / a->w),
208
+ DBL2NUM(a->y / a->w), DBL2NUM(a->z / a->w));
209
+ }
210
+
211
+ VALUE vec4_xyz(VALUE self) {
212
+ Vec4Data *a = vec4_get(self);
213
+ VALUE vec3_class = rb_const_get(mLarb, rb_intern("Vec3"));
214
+ return rb_funcall(vec3_class, rb_intern("new"), 3, DBL2NUM(a->x),
215
+ DBL2NUM(a->y), DBL2NUM(a->z));
216
+ }
217
+
218
+ VALUE vec4_xy(VALUE self) {
219
+ Vec4Data *a = vec4_get(self);
220
+ VALUE vec2_class = rb_const_get(mLarb, rb_intern("Vec2"));
221
+ return rb_funcall(vec2_class, rb_intern("new"), 2, DBL2NUM(a->x),
222
+ DBL2NUM(a->y));
223
+ }
224
+
225
+ VALUE vec4_rgb(VALUE self) {
226
+ return vec4_xyz(self);
227
+ }
228
+
229
+ VALUE vec4_to_a(VALUE self) {
230
+ Vec4Data *a = vec4_get(self);
231
+ VALUE ary = rb_ary_new_capa(4);
232
+ rb_ary_push(ary, DBL2NUM(a->x));
233
+ rb_ary_push(ary, DBL2NUM(a->y));
234
+ rb_ary_push(ary, DBL2NUM(a->z));
235
+ rb_ary_push(ary, DBL2NUM(a->w));
236
+ return ary;
237
+ }
238
+
239
+ VALUE vec4_aref(VALUE self, VALUE index) {
240
+ VALUE ary = vec4_to_a(self);
241
+ return rb_ary_entry(ary, NUM2LONG(index));
242
+ }
243
+
244
+ VALUE vec4_equal(VALUE self, VALUE other) {
245
+ if (!rb_obj_is_kind_of(other, cVec4)) {
246
+ return Qfalse;
247
+ }
248
+ Vec4Data *a = vec4_get(self);
249
+ Vec4Data *b = vec4_get(other);
250
+ return (a->x == b->x && a->y == b->y && a->z == b->z && a->w == b->w)
251
+ ? Qtrue
252
+ : Qfalse;
253
+ }
254
+
255
+ VALUE vec4_near(int argc, VALUE *argv, VALUE self) {
256
+ VALUE other = Qnil;
257
+ VALUE epsilon = Qnil;
258
+
259
+ rb_scan_args(argc, argv, "11", &other, &epsilon);
260
+ Vec4Data *a = vec4_get(self);
261
+ Vec4Data *b = vec4_get(other);
262
+ double eps = NIL_P(epsilon) ? 1e-6 : value_to_double(epsilon);
263
+
264
+ if (fabs(a->x - b->x) < eps && fabs(a->y - b->y) < eps &&
265
+ fabs(a->z - b->z) < eps && fabs(a->w - b->w) < eps) {
266
+ return Qtrue;
267
+ }
268
+ return Qfalse;
269
+ }
270
+
271
+ VALUE vec4_lerp(VALUE self, VALUE other, VALUE t) {
272
+ Vec4Data *a = vec4_get(self);
273
+ Vec4Data *b = vec4_get(other);
274
+ double s = value_to_double(t);
275
+ return vec4_build(rb_obj_class(self), a->x + (b->x - a->x) * s,
276
+ a->y + (b->y - a->y) * s,
277
+ a->z + (b->z - a->z) * s,
278
+ a->w + (b->w - a->w) * s);
279
+ }
280
+
281
+ VALUE vec4_inspect(VALUE self) {
282
+ Vec4Data *a = vec4_get(self);
283
+ VALUE sx = rb_funcall(DBL2NUM(a->x), rb_intern("to_s"), 0);
284
+ VALUE sy = rb_funcall(DBL2NUM(a->y), rb_intern("to_s"), 0);
285
+ VALUE sz = rb_funcall(DBL2NUM(a->z), rb_intern("to_s"), 0);
286
+ VALUE sw = rb_funcall(DBL2NUM(a->w), rb_intern("to_s"), 0);
287
+ VALUE str = rb_str_new_cstr("Vec4[");
288
+ rb_str_concat(str, sx);
289
+ rb_str_cat_cstr(str, ", ");
290
+ rb_str_concat(str, sy);
291
+ rb_str_cat_cstr(str, ", ");
292
+ rb_str_concat(str, sz);
293
+ rb_str_cat_cstr(str, ", ");
294
+ rb_str_concat(str, sw);
295
+ rb_str_cat_cstr(str, "]");
296
+ return str;
297
+ }
298
+
299
+ void Init_vec4(VALUE module) {
300
+ cVec4 = rb_define_class_under(module, "Vec4", rb_cObject);
301
+
302
+ rb_define_alloc_func(cVec4, vec4_alloc);
303
+ rb_define_method(cVec4, "initialize", vec4_initialize, -1);
304
+
305
+ rb_define_singleton_method(cVec4, "[]", vec4_class_bracket, -1);
306
+ rb_define_singleton_method(cVec4, "zero", vec4_class_zero, 0);
307
+ rb_define_singleton_method(cVec4, "one", vec4_class_one, 0);
308
+
309
+ rb_define_method(cVec4, "x", vec4_get_x, 0);
310
+ rb_define_method(cVec4, "x=", vec4_set_x, 1);
311
+ rb_define_method(cVec4, "y", vec4_get_y, 0);
312
+ rb_define_method(cVec4, "y=", vec4_set_y, 1);
313
+ rb_define_method(cVec4, "z", vec4_get_z, 0);
314
+ rb_define_method(cVec4, "z=", vec4_set_z, 1);
315
+ rb_define_method(cVec4, "w", vec4_get_w, 0);
316
+ rb_define_method(cVec4, "w=", vec4_set_w, 1);
317
+
318
+ rb_define_method(cVec4, "+", vec4_add, 1);
319
+ rb_define_method(cVec4, "-", vec4_sub, 1);
320
+ rb_define_method(cVec4, "*", vec4_mul, 1);
321
+ rb_define_method(cVec4, "/", vec4_div, 1);
322
+ rb_define_method(cVec4, "-@", vec4_negate, 0);
323
+
324
+ rb_define_method(cVec4, "dot", vec4_dot, 1);
325
+ rb_define_method(cVec4, "length", vec4_length, 0);
326
+ rb_define_method(cVec4, "length_squared", vec4_length_squared, 0);
327
+ rb_define_method(cVec4, "normalize", vec4_normalize, 0);
328
+ rb_define_method(cVec4, "normalize!", vec4_normalize_bang, 0);
329
+ rb_define_method(cVec4, "perspective_divide", vec4_perspective_divide, 0);
330
+ rb_define_method(cVec4, "xyz", vec4_xyz, 0);
331
+ rb_define_method(cVec4, "xy", vec4_xy, 0);
332
+ rb_define_method(cVec4, "rgb", vec4_rgb, 0);
333
+ rb_define_method(cVec4, "to_a", vec4_to_a, 0);
334
+ rb_define_method(cVec4, "[]", vec4_aref, 1);
335
+ rb_define_method(cVec4, "==", vec4_equal, 1);
336
+ rb_define_method(cVec4, "near?", vec4_near, -1);
337
+ rb_define_method(cVec4, "lerp", vec4_lerp, 2);
338
+ rb_define_method(cVec4, "inspect", vec4_inspect, 0);
339
+ rb_define_alias(cVec4, "to_s", "inspect");
340
+ }
data/ext/larb/vec4.h ADDED
@@ -0,0 +1,38 @@
1
+ #ifndef VEC4_H
2
+ #define VEC4_H
3
+
4
+ #include "larb.h"
5
+
6
+ typedef struct {
7
+ double x;
8
+ double y;
9
+ double z;
10
+ double w;
11
+ } Vec4Data;
12
+
13
+ void Init_vec4(VALUE module);
14
+ VALUE vec4_alloc(VALUE klass);
15
+ VALUE vec4_initialize(int argc, VALUE *argv, VALUE self);
16
+
17
+ VALUE vec4_add(VALUE self, VALUE other);
18
+ VALUE vec4_sub(VALUE self, VALUE other);
19
+ VALUE vec4_mul(VALUE self, VALUE scalar);
20
+ VALUE vec4_div(VALUE self, VALUE scalar);
21
+ VALUE vec4_negate(VALUE self);
22
+ VALUE vec4_dot(VALUE self, VALUE other);
23
+ VALUE vec4_length(VALUE self);
24
+ VALUE vec4_length_squared(VALUE self);
25
+ VALUE vec4_normalize(VALUE self);
26
+ VALUE vec4_normalize_bang(VALUE self);
27
+ VALUE vec4_perspective_divide(VALUE self);
28
+ VALUE vec4_xyz(VALUE self);
29
+ VALUE vec4_xy(VALUE self);
30
+ VALUE vec4_rgb(VALUE self);
31
+ VALUE vec4_to_a(VALUE self);
32
+ VALUE vec4_aref(VALUE self, VALUE index);
33
+ VALUE vec4_equal(VALUE self, VALUE other);
34
+ VALUE vec4_near(int argc, VALUE *argv, VALUE self);
35
+ VALUE vec4_lerp(VALUE self, VALUE other, VALUE t);
36
+ VALUE vec4_inspect(VALUE self);
37
+
38
+ #endif
@@ -0,0 +1,5 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Larb
4
+ VERSION = "1.0.0"
5
+ end
data/lib/larb.rb CHANGED
@@ -1,16 +1,4 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require_relative "larb/vec2"
4
- require_relative "larb/vec3"
5
- require_relative "larb/vec4"
6
- require_relative "larb/quat"
7
- require_relative "larb/quat2"
8
- require_relative "larb/mat2"
9
- require_relative "larb/mat2d"
10
- require_relative "larb/mat3"
11
- require_relative "larb/mat4"
12
- require_relative "larb/color"
13
-
14
- module Larb
15
- VERSION = "0.1.0"
16
- end
3
+ require "larb/larb"
4
+ require "larb/version"
@@ -0,0 +1,278 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "../test_helper"
4
+
5
+ class ColorTest < Test::Unit::TestCase
6
+ def test_new_with_default_values
7
+ c = Larb::Color.new
8
+ assert_equal 0.0, c.r
9
+ assert_equal 0.0, c.g
10
+ assert_equal 0.0, c.b
11
+ assert_equal 1.0, c.a
12
+ end
13
+
14
+ def test_new_with_given_values
15
+ c = Larb::Color.new(0.1, 0.2, 0.3, 0.4)
16
+ assert_equal 0.1, c.r
17
+ assert_equal 0.2, c.g
18
+ assert_equal 0.3, c.b
19
+ assert_equal 0.4, c.a
20
+ end
21
+
22
+ def test_bracket_syntax
23
+ c = Larb::Color[0.1, 0.2, 0.3, 0.4]
24
+ assert_equal 0.1, c.r
25
+ assert_equal 0.2, c.g
26
+ assert_equal 0.3, c.b
27
+ assert_equal 0.4, c.a
28
+ end
29
+
30
+ def test_bracket_syntax_default_alpha
31
+ c = Larb::Color[0.1, 0.2, 0.3]
32
+ assert_equal 1.0, c.a
33
+ end
34
+
35
+ def test_rgb
36
+ c = Larb::Color.rgb(0.5, 0.6, 0.7)
37
+ assert_equal 0.5, c.r
38
+ assert_equal 0.6, c.g
39
+ assert_equal 0.7, c.b
40
+ assert_equal 1.0, c.a
41
+ end
42
+
43
+ def test_rgba
44
+ c = Larb::Color.rgba(0.1, 0.2, 0.3, 0.4)
45
+ assert_equal 0.1, c.r
46
+ assert_equal 0.2, c.g
47
+ assert_equal 0.3, c.b
48
+ assert_equal 0.4, c.a
49
+ end
50
+
51
+ def test_from_bytes
52
+ c = Larb::Color.from_bytes(255, 128, 0, 255)
53
+ assert_equal 1.0, c.r
54
+ assert_in_delta 0.5, c.g, 0.01
55
+ assert_equal 0.0, c.b
56
+ assert_equal 1.0, c.a
57
+ end
58
+
59
+ def test_from_bytes_default_alpha
60
+ c = Larb::Color.from_bytes(255, 0, 0)
61
+ assert_equal 1.0, c.a
62
+ end
63
+
64
+ def test_from_hex
65
+ c = Larb::Color.from_hex("#ff8000")
66
+ assert_equal 1.0, c.r
67
+ assert_in_delta 0.5, c.g, 0.01
68
+ assert_equal 0.0, c.b
69
+ assert_equal 1.0, c.a
70
+ end
71
+
72
+ def test_from_hex_without_hash
73
+ c = Larb::Color.from_hex("ff0000")
74
+ assert_equal 1.0, c.r
75
+ assert_equal 0.0, c.g
76
+ assert_equal 0.0, c.b
77
+ end
78
+
79
+ def test_from_hex_with_alpha
80
+ c = Larb::Color.from_hex("#ff000080")
81
+ assert_equal 1.0, c.r
82
+ assert_in_delta 0.5, c.a, 0.01
83
+ end
84
+
85
+ def test_black
86
+ c = Larb::Color.black
87
+ assert_equal 0.0, c.r
88
+ assert_equal 0.0, c.g
89
+ assert_equal 0.0, c.b
90
+ assert_equal 1.0, c.a
91
+ end
92
+
93
+ def test_white
94
+ c = Larb::Color.white
95
+ assert_equal 1.0, c.r
96
+ assert_equal 1.0, c.g
97
+ assert_equal 1.0, c.b
98
+ end
99
+
100
+ def test_red
101
+ c = Larb::Color.red
102
+ assert_equal 1.0, c.r
103
+ assert_equal 0.0, c.g
104
+ assert_equal 0.0, c.b
105
+ end
106
+
107
+ def test_green
108
+ c = Larb::Color.green
109
+ assert_equal 0.0, c.r
110
+ assert_equal 1.0, c.g
111
+ assert_equal 0.0, c.b
112
+ end
113
+
114
+ def test_blue
115
+ c = Larb::Color.blue
116
+ assert_equal 0.0, c.r
117
+ assert_equal 0.0, c.g
118
+ assert_equal 1.0, c.b
119
+ end
120
+
121
+ def test_yellow
122
+ c = Larb::Color.yellow
123
+ assert_equal 1.0, c.r
124
+ assert_equal 1.0, c.g
125
+ assert_equal 0.0, c.b
126
+ end
127
+
128
+ def test_cyan
129
+ c = Larb::Color.cyan
130
+ assert_equal 0.0, c.r
131
+ assert_equal 1.0, c.g
132
+ assert_equal 1.0, c.b
133
+ end
134
+
135
+ def test_magenta
136
+ c = Larb::Color.magenta
137
+ assert_equal 1.0, c.r
138
+ assert_equal 0.0, c.g
139
+ assert_equal 1.0, c.b
140
+ end
141
+
142
+ def test_transparent
143
+ c = Larb::Color.transparent
144
+ assert_equal 0.0, c.r
145
+ assert_equal 0.0, c.g
146
+ assert_equal 0.0, c.b
147
+ assert_equal 0.0, c.a
148
+ end
149
+
150
+ def test_add
151
+ c1 = Larb::Color.new(0.1, 0.2, 0.3, 0.4)
152
+ c2 = Larb::Color.new(0.2, 0.3, 0.4, 0.5)
153
+ result = c1 + c2
154
+ assert_in_delta 0.3, result.r, 1e-10
155
+ assert_in_delta 0.5, result.g, 1e-10
156
+ assert_in_delta 0.7, result.b, 1e-10
157
+ assert_in_delta 0.9, result.a, 1e-10
158
+ end
159
+
160
+ def test_subtract
161
+ c1 = Larb::Color.new(0.5, 0.6, 0.7, 0.8)
162
+ c2 = Larb::Color.new(0.1, 0.2, 0.3, 0.4)
163
+ result = c1 - c2
164
+ assert_in_delta 0.4, result.r, 1e-10
165
+ assert_in_delta 0.4, result.g, 1e-10
166
+ assert_in_delta 0.4, result.b, 1e-10
167
+ assert_in_delta 0.4, result.a, 1e-10
168
+ end
169
+
170
+ def test_multiply_by_scalar
171
+ c = Larb::Color.new(0.2, 0.3, 0.4, 0.5)
172
+ result = c * 2
173
+ assert_in_delta 0.4, result.r, 1e-10
174
+ assert_in_delta 0.6, result.g, 1e-10
175
+ assert_in_delta 0.8, result.b, 1e-10
176
+ assert_in_delta 1.0, result.a, 1e-10
177
+ end
178
+
179
+ def test_multiply_by_color
180
+ c1 = Larb::Color.new(0.5, 0.5, 0.5, 1.0)
181
+ c2 = Larb::Color.new(1.0, 0.5, 0.0, 1.0)
182
+ result = c1 * c2
183
+ assert_in_delta 0.5, result.r, 1e-10
184
+ assert_in_delta 0.25, result.g, 1e-10
185
+ assert_equal 0.0, result.b
186
+ end
187
+
188
+ def test_lerp
189
+ c1 = Larb::Color.new(0, 0, 0, 0)
190
+ c2 = Larb::Color.new(1, 1, 1, 1)
191
+ result = c1.lerp(c2, 0.5)
192
+ assert_equal 0.5, result.r
193
+ assert_equal 0.5, result.g
194
+ assert_equal 0.5, result.b
195
+ assert_equal 0.5, result.a
196
+ end
197
+
198
+ def test_clamp
199
+ c = Larb::Color.new(-0.5, 1.5, 0.5, 2.0)
200
+ result = c.clamp
201
+ assert_equal 0.0, result.r
202
+ assert_equal 1.0, result.g
203
+ assert_equal 0.5, result.b
204
+ assert_equal 1.0, result.a
205
+ end
206
+
207
+ def test_to_bytes
208
+ c = Larb::Color.new(1.0, 0.5, 0.0, 1.0)
209
+ bytes = c.to_bytes
210
+ assert_equal 255, bytes[0]
211
+ assert_equal 128, bytes[1]
212
+ assert_equal 0, bytes[2]
213
+ assert_equal 255, bytes[3]
214
+ end
215
+
216
+ def test_to_hex
217
+ c = Larb::Color.new(1.0, 0.0, 0.0, 1.0)
218
+ assert_equal "#ff0000ff", c.to_hex
219
+ end
220
+
221
+ def test_to_vec3
222
+ c = Larb::Color.new(0.1, 0.2, 0.3, 1.0)
223
+ v = c.to_vec3
224
+ assert_instance_of Larb::Vec3, v
225
+ assert_equal 0.1, v.x
226
+ assert_equal 0.2, v.y
227
+ assert_equal 0.3, v.z
228
+ end
229
+
230
+ def test_to_vec4
231
+ c = Larb::Color.new(0.1, 0.2, 0.3, 0.4)
232
+ v = c.to_vec4
233
+ assert_instance_of Larb::Vec4, v
234
+ assert_equal 0.1, v.x
235
+ assert_equal 0.2, v.y
236
+ assert_equal 0.3, v.z
237
+ assert_equal 0.4, v.w
238
+ end
239
+
240
+ def test_to_a
241
+ c = Larb::Color.new(0.1, 0.2, 0.3, 0.4)
242
+ assert_equal [0.1, 0.2, 0.3, 0.4], c.to_a
243
+ end
244
+
245
+ def test_from_vec4
246
+ v = Larb::Vec4.new(0.1, 0.2, 0.3, 0.4)
247
+ c = Larb::Color.from_vec4(v)
248
+ assert_equal 0.1, c.r
249
+ assert_equal 0.2, c.g
250
+ assert_equal 0.3, c.b
251
+ assert_equal 0.4, c.a
252
+ end
253
+
254
+ def test_from_vec3
255
+ v = Larb::Vec3.new(0.1, 0.2, 0.3)
256
+ c = Larb::Color.from_vec3(v)
257
+ assert_equal 0.1, c.r
258
+ assert_equal 0.2, c.g
259
+ assert_equal 0.3, c.b
260
+ assert_equal 1.0, c.a
261
+ end
262
+
263
+ def test_from_vec3_with_alpha
264
+ v = Larb::Vec3.new(0.1, 0.2, 0.3)
265
+ c = Larb::Color.from_vec3(v, 0.5)
266
+ assert_equal 0.5, c.a
267
+ end
268
+
269
+ def test_inspect
270
+ c = Larb::Color.new(0.1, 0.2, 0.3, 0.4)
271
+ assert_equal "Color[0.1, 0.2, 0.3, 0.4]", c.inspect
272
+ end
273
+
274
+ def test_to_s
275
+ c = Larb::Color.new(0.1, 0.2, 0.3, 0.4)
276
+ assert_equal c.inspect, c.to_s
277
+ end
278
+ end