larb 0.1.0 → 1.0.1

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 (54) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +13 -1
  3. data/README.md +63 -1
  4. data/ext/larb/color.c +449 -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 +31 -0
  9. data/ext/larb/mat2.c +303 -0
  10. data/ext/larb/mat2.h +30 -0
  11. data/ext/larb/mat2d.c +397 -0
  12. data/ext/larb/mat2d.h +35 -0
  13. data/ext/larb/mat3.c +455 -0
  14. data/ext/larb/mat3.h +33 -0
  15. data/ext/larb/mat4.c +651 -0
  16. data/ext/larb/mat4.h +31 -0
  17. data/ext/larb/matrix_utils.h +97 -0
  18. data/ext/larb/quat.c +567 -0
  19. data/ext/larb/quat.h +39 -0
  20. data/ext/larb/quat2.c +511 -0
  21. data/ext/larb/quat2.h +39 -0
  22. data/ext/larb/vec2.c +365 -0
  23. data/ext/larb/vec2.h +43 -0
  24. data/ext/larb/vec3.c +538 -0
  25. data/ext/larb/vec3.h +52 -0
  26. data/ext/larb/vec4.c +361 -0
  27. data/ext/larb/vec4.h +38 -0
  28. data/lib/larb/version.rb +5 -0
  29. data/lib/larb.rb +2 -14
  30. data/test/larb/color_test.rb +299 -0
  31. data/test/larb/mat2_test.rb +144 -0
  32. data/test/larb/mat2d_test.rb +197 -0
  33. data/test/larb/mat3_test.rb +147 -0
  34. data/test/larb/mat4_test.rb +347 -0
  35. data/test/larb/matrix_test.rb +135 -0
  36. data/test/larb/native_value_test.rb +157 -0
  37. data/test/larb/quat2_test.rb +254 -0
  38. data/test/larb/quat_test.rb +284 -0
  39. data/test/larb/vec2_test.rb +274 -0
  40. data/test/larb/vec3_test.rb +373 -0
  41. data/test/larb/vec4_test.rb +196 -0
  42. data/test/test_helper.rb +4 -0
  43. metadata +60 -18
  44. data/Rakefile +0 -11
  45. data/lib/larb/color.rb +0 -148
  46. data/lib/larb/mat2.rb +0 -119
  47. data/lib/larb/mat2d.rb +0 -180
  48. data/lib/larb/mat3.rb +0 -238
  49. data/lib/larb/mat4.rb +0 -329
  50. data/lib/larb/quat.rb +0 -238
  51. data/lib/larb/quat2.rb +0 -193
  52. data/lib/larb/vec2.rb +0 -150
  53. data/lib/larb/vec3.rb +0 -218
  54. data/lib/larb/vec4.rb +0 -125
data/lib/larb/mat2d.rb DELETED
@@ -1,180 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Larb
4
- # 2D affine transformation matrix (2x3)
5
- # Layout: [a, b, c, d, tx, ty]
6
- # Represents:
7
- # | a c tx |
8
- # | b d ty |
9
- # | 0 0 1 |
10
- class Mat2d
11
- attr_reader :data
12
-
13
- def initialize(data = nil)
14
- @data = data || [1.0, 0.0, 0.0, 1.0, 0.0, 0.0]
15
- end
16
-
17
- def self.identity
18
- new
19
- end
20
-
21
- def self.zero
22
- new([0.0, 0.0, 0.0, 0.0, 0.0, 0.0])
23
- end
24
-
25
- def self.translation(x, y)
26
- new([1.0, 0.0, 0.0, 1.0, x.to_f, y.to_f])
27
- end
28
-
29
- def self.rotation(radians)
30
- c = Math.cos(radians)
31
- s = Math.sin(radians)
32
- new([c, s, -s, c, 0.0, 0.0])
33
- end
34
-
35
- def self.scaling(x, y)
36
- new([x.to_f, 0.0, 0.0, y.to_f, 0.0, 0.0])
37
- end
38
-
39
- def self.from_rotation_translation_scale(rotation, translation, scale)
40
- c = Math.cos(rotation)
41
- s = Math.sin(rotation)
42
- new([
43
- c * scale.x,
44
- s * scale.x,
45
- -s * scale.y,
46
- c * scale.y,
47
- translation.x,
48
- translation.y
49
- ])
50
- end
51
-
52
- def [](i)
53
- @data[i]
54
- end
55
-
56
- def []=(i, v)
57
- @data[i] = v.to_f
58
- end
59
-
60
- def *(other)
61
- case other
62
- when Mat2d
63
- a = @data
64
- b = other.data
65
- Mat2d.new([
66
- a[0] * b[0] + a[2] * b[1],
67
- a[1] * b[0] + a[3] * b[1],
68
- a[0] * b[2] + a[2] * b[3],
69
- a[1] * b[2] + a[3] * b[3],
70
- a[0] * b[4] + a[2] * b[5] + a[4],
71
- a[1] * b[4] + a[3] * b[5] + a[5]
72
- ])
73
- when Vec2
74
- Vec2.new(
75
- @data[0] * other.x + @data[2] * other.y + @data[4],
76
- @data[1] * other.x + @data[3] * other.y + @data[5]
77
- )
78
- when Numeric
79
- Mat2d.new(@data.map { |v| v * other })
80
- end
81
- end
82
-
83
- def +(other)
84
- Mat2d.new(@data.zip(other.data).map { |a, b| a + b })
85
- end
86
-
87
- def -(other)
88
- Mat2d.new(@data.zip(other.data).map { |a, b| a - b })
89
- end
90
-
91
- def determinant
92
- @data[0] * @data[3] - @data[1] * @data[2]
93
- end
94
-
95
- def inverse
96
- a = @data
97
- det = determinant
98
- raise "Matrix is not invertible" if det.abs < 1e-10
99
-
100
- inv_det = 1.0 / det
101
- Mat2d.new([
102
- a[3] * inv_det,
103
- -a[1] * inv_det,
104
- -a[2] * inv_det,
105
- a[0] * inv_det,
106
- (a[2] * a[5] - a[3] * a[4]) * inv_det,
107
- (a[1] * a[4] - a[0] * a[5]) * inv_det
108
- ])
109
- end
110
-
111
- def translate(x, y)
112
- a = @data
113
- Mat2d.new([
114
- a[0], a[1], a[2], a[3],
115
- a[0] * x + a[2] * y + a[4],
116
- a[1] * x + a[3] * y + a[5]
117
- ])
118
- end
119
-
120
- def rotate(radians)
121
- self * Mat2d.rotation(radians)
122
- end
123
-
124
- def scale(x, y)
125
- a = @data
126
- Mat2d.new([
127
- a[0] * x, a[1] * x,
128
- a[2] * y, a[3] * y,
129
- a[4], a[5]
130
- ])
131
- end
132
-
133
- def extract_translation
134
- Vec2.new(@data[4], @data[5])
135
- end
136
-
137
- def extract_rotation
138
- Math.atan2(@data[1], @data[0])
139
- end
140
-
141
- def extract_scale
142
- Vec2.new(
143
- Math.sqrt(@data[0] * @data[0] + @data[1] * @data[1]),
144
- Math.sqrt(@data[2] * @data[2] + @data[3] * @data[3])
145
- )
146
- end
147
-
148
- def frobenius_norm
149
- Math.sqrt(@data.sum { |v| v * v })
150
- end
151
-
152
- def to_mat3
153
- Mat3.new([
154
- @data[0], @data[1], 0,
155
- @data[2], @data[3], 0,
156
- @data[4], @data[5], 1
157
- ])
158
- end
159
-
160
- def to_a
161
- @data.dup
162
- end
163
-
164
- def ==(other)
165
- return false unless other.is_a?(Mat2d)
166
-
167
- @data == other.data
168
- end
169
-
170
- def near?(other, epsilon = 1e-6)
171
- @data.zip(other.data).all? { |a, b| (a - b).abs < epsilon }
172
- end
173
-
174
- def inspect
175
- "Mat2d[#{@data.map { |v| format('%.4f', v) }.join(', ')}]"
176
- end
177
-
178
- alias to_s inspect
179
- end
180
- end
data/lib/larb/mat3.rb DELETED
@@ -1,238 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Larb
4
- class Mat3
5
- attr_reader :data
6
-
7
- def initialize(data = nil)
8
- @data = data || [1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 1.0]
9
- end
10
-
11
- def self.identity
12
- new
13
- end
14
-
15
- def self.zero
16
- new(Array.new(9, 0.0))
17
- end
18
-
19
- def self.from_mat4(m)
20
- new([
21
- m[0], m[1], m[2],
22
- m[4], m[5], m[6],
23
- m[8], m[9], m[10]
24
- ])
25
- end
26
-
27
- def self.from_mat2d(m)
28
- new([
29
- m[0], m[1], 0,
30
- m[2], m[3], 0,
31
- m[4], m[5], 1
32
- ])
33
- end
34
-
35
- def self.from_quaternion(q)
36
- x, y, z, w = q.x, q.y, q.z, q.w
37
- x2 = x + x
38
- y2 = y + y
39
- z2 = z + z
40
- xx = x * x2
41
- yx = y * x2
42
- yy = y * y2
43
- zx = z * x2
44
- zy = z * y2
45
- zz = z * z2
46
- wx = w * x2
47
- wy = w * y2
48
- wz = w * z2
49
-
50
- new([
51
- 1 - yy - zz, yx + wz, zx - wy,
52
- yx - wz, 1 - xx - zz, zy + wx,
53
- zx + wy, zy - wx, 1 - xx - yy
54
- ])
55
- end
56
-
57
- def self.normal_from_mat4(m)
58
- from_mat4(m).inverse.transpose
59
- end
60
-
61
- def self.projection(width, height)
62
- new([
63
- 2.0 / width, 0, 0,
64
- 0, -2.0 / height, 0,
65
- -1, 1, 1
66
- ])
67
- end
68
-
69
- def self.translation(x, y)
70
- new([
71
- 1, 0, 0,
72
- 0, 1, 0,
73
- x.to_f, y.to_f, 1
74
- ])
75
- end
76
-
77
- def self.rotation(radians)
78
- c = Math.cos(radians)
79
- s = Math.sin(radians)
80
- new([
81
- c, s, 0,
82
- -s, c, 0,
83
- 0, 0, 1
84
- ])
85
- end
86
-
87
- def self.scaling(x, y)
88
- new([
89
- x.to_f, 0, 0,
90
- 0, y.to_f, 0,
91
- 0, 0, 1
92
- ])
93
- end
94
-
95
- def [](i)
96
- @data[i]
97
- end
98
-
99
- def []=(i, v)
100
- @data[i] = v.to_f
101
- end
102
-
103
- def *(other)
104
- case other
105
- when Mat3
106
- a = @data
107
- b = other.data
108
- Mat3.new([
109
- a[0] * b[0] + a[3] * b[1] + a[6] * b[2],
110
- a[1] * b[0] + a[4] * b[1] + a[7] * b[2],
111
- a[2] * b[0] + a[5] * b[1] + a[8] * b[2],
112
- a[0] * b[3] + a[3] * b[4] + a[6] * b[5],
113
- a[1] * b[3] + a[4] * b[4] + a[7] * b[5],
114
- a[2] * b[3] + a[5] * b[4] + a[8] * b[5],
115
- a[0] * b[6] + a[3] * b[7] + a[6] * b[8],
116
- a[1] * b[6] + a[4] * b[7] + a[7] * b[8],
117
- a[2] * b[6] + a[5] * b[7] + a[8] * b[8]
118
- ])
119
- when Vec3
120
- Vec3.new(
121
- @data[0] * other.x + @data[3] * other.y + @data[6] * other.z,
122
- @data[1] * other.x + @data[4] * other.y + @data[7] * other.z,
123
- @data[2] * other.x + @data[5] * other.y + @data[8] * other.z
124
- )
125
- when Numeric
126
- Mat3.new(@data.map { |v| v * other })
127
- end
128
- end
129
-
130
- def +(other)
131
- Mat3.new(@data.zip(other.data).map { |a, b| a + b })
132
- end
133
-
134
- def -(other)
135
- Mat3.new(@data.zip(other.data).map { |a, b| a - b })
136
- end
137
-
138
- def determinant
139
- a = @data
140
- a[0] * (a[4] * a[8] - a[5] * a[7]) -
141
- a[3] * (a[1] * a[8] - a[2] * a[7]) +
142
- a[6] * (a[1] * a[5] - a[2] * a[4])
143
- end
144
-
145
- def inverse
146
- a = @data
147
- det = determinant
148
- raise "Matrix is not invertible" if det.abs < 1e-10
149
-
150
- inv_det = 1.0 / det
151
- Mat3.new([
152
- (a[4] * a[8] - a[5] * a[7]) * inv_det,
153
- (a[2] * a[7] - a[1] * a[8]) * inv_det,
154
- (a[1] * a[5] - a[2] * a[4]) * inv_det,
155
- (a[5] * a[6] - a[3] * a[8]) * inv_det,
156
- (a[0] * a[8] - a[2] * a[6]) * inv_det,
157
- (a[2] * a[3] - a[0] * a[5]) * inv_det,
158
- (a[3] * a[7] - a[4] * a[6]) * inv_det,
159
- (a[1] * a[6] - a[0] * a[7]) * inv_det,
160
- (a[0] * a[4] - a[1] * a[3]) * inv_det
161
- ])
162
- end
163
-
164
- def transpose
165
- Mat3.new([
166
- @data[0], @data[3], @data[6],
167
- @data[1], @data[4], @data[7],
168
- @data[2], @data[5], @data[8]
169
- ])
170
- end
171
-
172
- def adjoint
173
- a = @data
174
- Mat3.new([
175
- a[4] * a[8] - a[5] * a[7],
176
- a[2] * a[7] - a[1] * a[8],
177
- a[1] * a[5] - a[2] * a[4],
178
- a[5] * a[6] - a[3] * a[8],
179
- a[0] * a[8] - a[2] * a[6],
180
- a[2] * a[3] - a[0] * a[5],
181
- a[3] * a[7] - a[4] * a[6],
182
- a[1] * a[6] - a[0] * a[7],
183
- a[0] * a[4] - a[1] * a[3]
184
- ])
185
- end
186
-
187
- def frobenius_norm
188
- Math.sqrt(@data.sum { |v| v * v })
189
- end
190
-
191
- def translate(x, y)
192
- a = @data
193
- Mat3.new([
194
- a[0], a[1], a[2],
195
- a[3], a[4], a[5],
196
- x * a[0] + y * a[3] + a[6],
197
- x * a[1] + y * a[4] + a[7],
198
- x * a[2] + y * a[5] + a[8]
199
- ])
200
- end
201
-
202
- def rotate(radians)
203
- self * Mat3.rotation(radians)
204
- end
205
-
206
- def scale(x, y)
207
- a = @data
208
- Mat3.new([
209
- a[0] * x, a[1] * x, a[2] * x,
210
- a[3] * y, a[4] * y, a[5] * y,
211
- a[6], a[7], a[8]
212
- ])
213
- end
214
-
215
- def to_a
216
- @data.dup
217
- end
218
-
219
- def ==(other)
220
- return false unless other.is_a?(Mat3)
221
-
222
- @data == other.data
223
- end
224
-
225
- def near?(other, epsilon = 1e-6)
226
- @data.zip(other.data).all? { |a, b| (a - b).abs < epsilon }
227
- end
228
-
229
- def inspect
230
- "Mat3[\n" \
231
- " #{@data[0..2].map { |v| format('%8.4f', v) }.join(', ')}\n" \
232
- " #{@data[3..5].map { |v| format('%8.4f', v) }.join(', ')}\n" \
233
- " #{@data[6..8].map { |v| format('%8.4f', v) }.join(', ')}\n]"
234
- end
235
-
236
- alias to_s inspect
237
- end
238
- end