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/lib/larb/mat4.rb DELETED
@@ -1,329 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Larb
4
- class Mat4
5
- attr_reader :data
6
-
7
- def initialize(data = nil)
8
- @data = data || Array.new(16, 0.0)
9
- unless data
10
- @data[0] = @data[5] = @data[10] = @data[15] = 1.0
11
- end
12
- end
13
-
14
- def self.identity
15
- new
16
- end
17
-
18
- def self.zero
19
- new(Array.new(16, 0.0))
20
- end
21
-
22
- def self.translation(x, y, z)
23
- m = identity
24
- m[12] = x.to_f
25
- m[13] = y.to_f
26
- m[14] = z.to_f
27
- m
28
- end
29
-
30
- def self.scaling(x, y, z)
31
- m = zero
32
- m[0] = x.to_f
33
- m[5] = y.to_f
34
- m[10] = z.to_f
35
- m[15] = 1.0
36
- m
37
- end
38
-
39
- def self.rotation_x(radians)
40
- c = Math.cos(radians)
41
- s = Math.sin(radians)
42
- m = identity
43
- m[5] = c
44
- m[6] = s
45
- m[9] = -s
46
- m[10] = c
47
- m
48
- end
49
-
50
- def self.rotation_y(radians)
51
- c = Math.cos(radians)
52
- s = Math.sin(radians)
53
- m = identity
54
- m[0] = c
55
- m[2] = -s
56
- m[8] = s
57
- m[10] = c
58
- m
59
- end
60
-
61
- def self.rotation_z(radians)
62
- c = Math.cos(radians)
63
- s = Math.sin(radians)
64
- m = identity
65
- m[0] = c
66
- m[1] = s
67
- m[4] = -s
68
- m[5] = c
69
- m
70
- end
71
-
72
- def self.rotation(axis, radians)
73
- axis = axis.normalize
74
- c = Math.cos(radians)
75
- s = Math.sin(radians)
76
- t = 1 - c
77
- x = axis.x
78
- y = axis.y
79
- z = axis.z
80
-
81
- new([
82
- t * x * x + c, t * x * y + s * z, t * x * z - s * y, 0,
83
- t * x * y - s * z, t * y * y + c, t * y * z + s * x, 0,
84
- t * x * z + s * y, t * y * z - s * x, t * z * z + c, 0,
85
- 0, 0, 0, 1
86
- ])
87
- end
88
-
89
- def self.look_at(eye, target, up)
90
- f = (target - eye).normalize
91
- r = f.cross(up).normalize
92
- u = r.cross(f)
93
-
94
- new([
95
- r.x, u.x, -f.x, 0,
96
- r.y, u.y, -f.y, 0,
97
- r.z, u.z, -f.z, 0,
98
- -r.dot(eye), -u.dot(eye), f.dot(eye), 1
99
- ])
100
- end
101
-
102
- def self.perspective(fov_y, aspect, near, far)
103
- f = 1.0 / Math.tan(fov_y / 2.0)
104
- nf = 1.0 / (near - far)
105
-
106
- new([
107
- f / aspect, 0, 0, 0,
108
- 0, f, 0, 0,
109
- 0, 0, (far + near) * nf, -1,
110
- 0, 0, 2 * far * near * nf, 0
111
- ])
112
- end
113
-
114
- def self.orthographic(left, right, bottom, top, near, far)
115
- rl = 1.0 / (right - left)
116
- tb = 1.0 / (top - bottom)
117
- fn = 1.0 / (far - near)
118
-
119
- new([
120
- 2 * rl, 0, 0, 0,
121
- 0, 2 * tb, 0, 0,
122
- 0, 0, -2 * fn, 0,
123
- -(right + left) * rl, -(top + bottom) * tb, -(far + near) * fn, 1
124
- ])
125
- end
126
-
127
- def self.frustum(left, right, bottom, top, near, far)
128
- rl = 1.0 / (right - left)
129
- tb = 1.0 / (top - bottom)
130
- nf = 1.0 / (near - far)
131
-
132
- new([
133
- 2 * near * rl, 0, 0, 0,
134
- 0, 2 * near * tb, 0, 0,
135
- (right + left) * rl, (top + bottom) * tb, (far + near) * nf, -1,
136
- 0, 0, 2 * far * near * nf, 0
137
- ])
138
- end
139
-
140
- def self.from_quaternion(q)
141
- x, y, z, w = q.x, q.y, q.z, q.w
142
-
143
- x2 = x + x
144
- y2 = y + y
145
- z2 = z + z
146
-
147
- xx = x * x2
148
- xy = x * y2
149
- xz = x * z2
150
- yy = y * y2
151
- yz = y * z2
152
- zz = z * z2
153
- wx = w * x2
154
- wy = w * y2
155
- wz = w * z2
156
-
157
- new([
158
- 1 - (yy + zz), xy + wz, xz - wy, 0,
159
- xy - wz, 1 - (xx + zz), yz + wx, 0,
160
- xz + wy, yz - wx, 1 - (xx + yy), 0,
161
- 0, 0, 0, 1
162
- ])
163
- end
164
-
165
- def self.trs(translation, rotation, scale)
166
- from_quaternion(rotation) * scaling(scale.x, scale.y, scale.z) *
167
- self.translation(translation.x, translation.y, translation.z)
168
- end
169
-
170
- def [](i)
171
- @data[i]
172
- end
173
-
174
- def []=(i, v)
175
- @data[i] = v.to_f
176
- end
177
-
178
- def *(other)
179
- case other
180
- when Mat4
181
- result = Array.new(16, 0.0)
182
- 4.times do |col|
183
- 4.times do |row|
184
- 4.times do |k|
185
- result[col * 4 + row] += @data[k * 4 + row] * other[col * 4 + k]
186
- end
187
- end
188
- end
189
- Mat4.new(result)
190
-
191
- when Vec4
192
- Vec4.new(
193
- @data[0] * other.x + @data[4] * other.y + @data[8] * other.z + @data[12] * other.w,
194
- @data[1] * other.x + @data[5] * other.y + @data[9] * other.z + @data[13] * other.w,
195
- @data[2] * other.x + @data[6] * other.y + @data[10] * other.z + @data[14] * other.w,
196
- @data[3] * other.x + @data[7] * other.y + @data[11] * other.z + @data[15] * other.w
197
- )
198
-
199
- when Vec3
200
- self * other.to_vec4
201
- end
202
- end
203
-
204
- def transpose
205
- Mat4.new([
206
- @data[0], @data[4], @data[8], @data[12],
207
- @data[1], @data[5], @data[9], @data[13],
208
- @data[2], @data[6], @data[10], @data[14],
209
- @data[3], @data[7], @data[11], @data[15]
210
- ])
211
- end
212
-
213
- def inverse
214
- m = @data
215
- inv = Array.new(16)
216
-
217
- inv[0] = m[5] * m[10] * m[15] - m[5] * m[11] * m[14] - m[9] * m[6] * m[15] + m[9] * m[7] * m[14] + m[13] * m[6] * m[11] - m[13] * m[7] * m[10]
218
- inv[4] = -m[4] * m[10] * m[15] + m[4] * m[11] * m[14] + m[8] * m[6] * m[15] - m[8] * m[7] * m[14] - m[12] * m[6] * m[11] + m[12] * m[7] * m[10]
219
- inv[8] = m[4] * m[9] * m[15] - m[4] * m[11] * m[13] - m[8] * m[5] * m[15] + m[8] * m[7] * m[13] + m[12] * m[5] * m[11] - m[12] * m[7] * m[9]
220
- inv[12] = -m[4] * m[9] * m[14] + m[4] * m[10] * m[13] + m[8] * m[5] * m[14] - m[8] * m[6] * m[13] - m[12] * m[5] * m[10] + m[12] * m[6] * m[9]
221
-
222
- inv[1] = -m[1] * m[10] * m[15] + m[1] * m[11] * m[14] + m[9] * m[2] * m[15] - m[9] * m[3] * m[14] - m[13] * m[2] * m[11] + m[13] * m[3] * m[10]
223
- inv[5] = m[0] * m[10] * m[15] - m[0] * m[11] * m[14] - m[8] * m[2] * m[15] + m[8] * m[3] * m[14] + m[12] * m[2] * m[11] - m[12] * m[3] * m[10]
224
- inv[9] = -m[0] * m[9] * m[15] + m[0] * m[11] * m[13] + m[8] * m[1] * m[15] - m[8] * m[3] * m[13] - m[12] * m[1] * m[11] + m[12] * m[3] * m[9]
225
- inv[13] = m[0] * m[9] * m[14] - m[0] * m[10] * m[13] - m[8] * m[1] * m[14] + m[8] * m[2] * m[13] + m[12] * m[1] * m[10] - m[12] * m[2] * m[9]
226
-
227
- inv[2] = m[1] * m[6] * m[15] - m[1] * m[7] * m[14] - m[5] * m[2] * m[15] + m[5] * m[3] * m[14] + m[13] * m[2] * m[7] - m[13] * m[3] * m[6]
228
- inv[6] = -m[0] * m[6] * m[15] + m[0] * m[7] * m[14] + m[4] * m[2] * m[15] - m[4] * m[3] * m[14] - m[12] * m[2] * m[7] + m[12] * m[3] * m[6]
229
- inv[10] = m[0] * m[5] * m[15] - m[0] * m[7] * m[13] - m[4] * m[1] * m[15] + m[4] * m[3] * m[13] + m[12] * m[1] * m[7] - m[12] * m[3] * m[5]
230
- inv[14] = -m[0] * m[5] * m[14] + m[0] * m[6] * m[13] + m[4] * m[1] * m[14] - m[4] * m[2] * m[13] - m[12] * m[1] * m[6] + m[12] * m[2] * m[5]
231
-
232
- inv[3] = -m[1] * m[6] * m[11] + m[1] * m[7] * m[10] + m[5] * m[2] * m[11] - m[5] * m[3] * m[10] - m[9] * m[2] * m[7] + m[9] * m[3] * m[6]
233
- inv[7] = m[0] * m[6] * m[11] - m[0] * m[7] * m[10] - m[4] * m[2] * m[11] + m[4] * m[3] * m[10] + m[8] * m[2] * m[7] - m[8] * m[3] * m[6]
234
- inv[11] = -m[0] * m[5] * m[11] + m[0] * m[7] * m[9] + m[4] * m[1] * m[11] - m[4] * m[3] * m[9] - m[8] * m[1] * m[7] + m[8] * m[3] * m[5]
235
- inv[15] = m[0] * m[5] * m[10] - m[0] * m[6] * m[9] - m[4] * m[1] * m[10] + m[4] * m[2] * m[9] + m[8] * m[1] * m[6] - m[8] * m[2] * m[5]
236
-
237
- det = m[0] * inv[0] + m[1] * inv[4] + m[2] * inv[8] + m[3] * inv[12]
238
- raise "Matrix is not invertible" if det.abs < 1e-10
239
-
240
- det = 1.0 / det
241
- Mat4.new(inv.map { |v| v * det })
242
- end
243
-
244
- def to_a
245
- @data.dup
246
- end
247
-
248
- def determinant
249
- m = @data
250
- m[0] * (m[5] * (m[10] * m[15] - m[11] * m[14]) -
251
- m[9] * (m[6] * m[15] - m[7] * m[14]) +
252
- m[13] * (m[6] * m[11] - m[7] * m[10])) -
253
- m[4] * (m[1] * (m[10] * m[15] - m[11] * m[14]) -
254
- m[9] * (m[2] * m[15] - m[3] * m[14]) +
255
- m[13] * (m[2] * m[11] - m[3] * m[10])) +
256
- m[8] * (m[1] * (m[6] * m[15] - m[7] * m[14]) -
257
- m[5] * (m[2] * m[15] - m[3] * m[14]) +
258
- m[13] * (m[2] * m[7] - m[3] * m[6])) -
259
- m[12] * (m[1] * (m[6] * m[11] - m[7] * m[10]) -
260
- m[5] * (m[2] * m[11] - m[3] * m[10]) +
261
- m[9] * (m[2] * m[7] - m[3] * m[6]))
262
- end
263
-
264
- def +(other)
265
- Mat4.new(@data.zip(other.data).map { |a, b| a + b })
266
- end
267
-
268
- def -(other)
269
- Mat4.new(@data.zip(other.data).map { |a, b| a - b })
270
- end
271
-
272
- def ==(other)
273
- return false unless other.is_a?(Mat4)
274
-
275
- @data == other.data
276
- end
277
-
278
- def near?(other, epsilon = 1e-6)
279
- @data.zip(other.data).all? { |a, b| (a - b).abs < epsilon }
280
- end
281
-
282
- def extract_translation
283
- Vec3.new(@data[12], @data[13], @data[14])
284
- end
285
-
286
- def extract_scale
287
- sx = Vec3.new(@data[0], @data[1], @data[2]).length
288
- sy = Vec3.new(@data[4], @data[5], @data[6]).length
289
- sz = Vec3.new(@data[8], @data[9], @data[10]).length
290
- Vec3.new(sx, sy, sz)
291
- end
292
-
293
- def extract_rotation
294
- scale = extract_scale
295
- m00 = @data[0] / scale.x
296
- m01 = @data[1] / scale.x
297
- m02 = @data[2] / scale.x
298
- m10 = @data[4] / scale.y
299
- m11 = @data[5] / scale.y
300
- m12 = @data[6] / scale.y
301
- m20 = @data[8] / scale.z
302
- m21 = @data[9] / scale.z
303
- m22 = @data[10] / scale.z
304
-
305
- trace = m00 + m11 + m22
306
- if trace > 0
307
- s = 0.5 / Math.sqrt(trace + 1.0)
308
- Quat.new((m12 - m21) * s, (m20 - m02) * s, (m01 - m10) * s, 0.25 / s)
309
- elsif m00 > m11 && m00 > m22
310
- s = 2.0 * Math.sqrt(1.0 + m00 - m11 - m22)
311
- Quat.new(0.25 * s, (m10 + m01) / s, (m20 + m02) / s, (m12 - m21) / s)
312
- elsif m11 > m22
313
- s = 2.0 * Math.sqrt(1.0 + m11 - m00 - m22)
314
- Quat.new((m10 + m01) / s, 0.25 * s, (m21 + m12) / s, (m20 - m02) / s)
315
- else
316
- s = 2.0 * Math.sqrt(1.0 + m22 - m00 - m11)
317
- Quat.new((m20 + m02) / s, (m21 + m12) / s, 0.25 * s, (m01 - m10) / s)
318
- end
319
- end
320
-
321
- def inspect
322
- "Mat4[\n" \
323
- " #{@data[0..3].map { |v| format('%8.4f', v) }.join(', ')}\n" \
324
- " #{@data[4..7].map { |v| format('%8.4f', v) }.join(', ')}\n" \
325
- " #{@data[8..11].map { |v| format('%8.4f', v) }.join(', ')}\n" \
326
- " #{@data[12..15].map { |v| format('%8.4f', v) }.join(', ')}\n]"
327
- end
328
- end
329
- end
data/lib/larb/quat.rb DELETED
@@ -1,238 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Larb
4
- class Quat
5
- attr_accessor :x, :y, :z, :w
6
-
7
- def initialize(x = 0.0, y = 0.0, z = 0.0, w = 1.0)
8
- @x = x.to_f
9
- @y = y.to_f
10
- @z = z.to_f
11
- @w = w.to_f
12
- end
13
-
14
- def self.[](x, y, z, w)
15
- new(x, y, z, w)
16
- end
17
-
18
- def self.identity
19
- new(0, 0, 0, 1)
20
- end
21
-
22
- def self.from_axis_angle(axis, radians)
23
- half = radians * 0.5
24
- s = Math.sin(half)
25
- axis = axis.normalize
26
- new(axis.x * s, axis.y * s, axis.z * s, Math.cos(half))
27
- end
28
-
29
- def self.from_euler(x, y, z)
30
- cx = Math.cos(x * 0.5)
31
- sx = Math.sin(x * 0.5)
32
- cy = Math.cos(y * 0.5)
33
- sy = Math.sin(y * 0.5)
34
- cz = Math.cos(z * 0.5)
35
- sz = Math.sin(z * 0.5)
36
-
37
- new(
38
- sx * cy * cz - cx * sy * sz,
39
- cx * sy * cz + sx * cy * sz,
40
- cx * cy * sz - sx * sy * cz,
41
- cx * cy * cz + sx * sy * sz
42
- )
43
- end
44
-
45
- def self.look_rotation(forward, up = Vec3.up)
46
- forward = forward.normalize
47
- right = up.cross(forward).normalize
48
- up = forward.cross(right)
49
-
50
- m00 = right.x
51
- m01 = up.x
52
- m02 = forward.x
53
- m10 = right.y
54
- m11 = up.y
55
- m12 = forward.y
56
- m20 = right.z
57
- m21 = up.z
58
- m22 = forward.z
59
-
60
- trace = m00 + m11 + m22
61
- if trace > 0
62
- s = 0.5 / Math.sqrt(trace + 1.0)
63
- new((m21 - m12) * s, (m02 - m20) * s, (m10 - m01) * s, 0.25 / s)
64
- elsif m00 > m11 && m00 > m22
65
- s = 2.0 * Math.sqrt(1.0 + m00 - m11 - m22)
66
- new(0.25 * s, (m01 + m10) / s, (m02 + m20) / s, (m21 - m12) / s)
67
- elsif m11 > m22
68
- s = 2.0 * Math.sqrt(1.0 + m11 - m00 - m22)
69
- new((m01 + m10) / s, 0.25 * s, (m12 + m21) / s, (m02 - m20) / s)
70
- else
71
- s = 2.0 * Math.sqrt(1.0 + m22 - m00 - m11)
72
- new((m02 + m20) / s, (m12 + m21) / s, 0.25 * s, (m10 - m01) / s)
73
- end
74
- end
75
-
76
- def *(other)
77
- case other
78
- when Quat
79
- Quat.new(
80
- @w * other.x + @x * other.w + @y * other.z - @z * other.y,
81
- @w * other.y - @x * other.z + @y * other.w + @z * other.x,
82
- @w * other.z + @x * other.y - @y * other.x + @z * other.w,
83
- @w * other.w - @x * other.x - @y * other.y - @z * other.z
84
- )
85
- when Vec3
86
- qv = Vec3.new(@x, @y, @z)
87
- uv = qv.cross(other)
88
- uuv = qv.cross(uv)
89
- other + (uv * @w + uuv) * 2
90
- when Numeric
91
- Quat.new(@x * other, @y * other, @z * other, @w * other)
92
- end
93
- end
94
-
95
- def +(other)
96
- Quat.new(@x + other.x, @y + other.y, @z + other.z, @w + other.w)
97
- end
98
-
99
- def -(other)
100
- Quat.new(@x - other.x, @y - other.y, @z - other.z, @w - other.w)
101
- end
102
-
103
- def -@
104
- Quat.new(-@x, -@y, -@z, -@w)
105
- end
106
-
107
- def dot(other)
108
- @x * other.x + @y * other.y + @z * other.z + @w * other.w
109
- end
110
-
111
- def length
112
- Math.sqrt(length_squared)
113
- end
114
-
115
- def length_squared
116
- @x * @x + @y * @y + @z * @z + @w * @w
117
- end
118
-
119
- def normalize
120
- l = length
121
- Quat.new(@x / l, @y / l, @z / l, @w / l)
122
- end
123
-
124
- def normalize!
125
- l = length
126
- @x /= l
127
- @y /= l
128
- @z /= l
129
- @w /= l
130
- self
131
- end
132
-
133
- def conjugate
134
- Quat.new(-@x, -@y, -@z, @w)
135
- end
136
-
137
- def inverse
138
- len_sq = length_squared
139
- Quat.new(-@x / len_sq, -@y / len_sq, -@z / len_sq, @w / len_sq)
140
- end
141
-
142
- def lerp(other, t)
143
- Quat.new(
144
- @x + (other.x - @x) * t,
145
- @y + (other.y - @y) * t,
146
- @z + (other.z - @z) * t,
147
- @w + (other.w - @w) * t
148
- ).normalize
149
- end
150
-
151
- def slerp(other, t)
152
- dot_val = dot(other)
153
-
154
- other = -other if dot_val < 0
155
- dot_val = dot_val.abs
156
-
157
- if dot_val > 0.9995
158
- return lerp(other, t)
159
- end
160
-
161
- theta_0 = Math.acos(dot_val.clamp(-1.0, 1.0))
162
- theta = theta_0 * t
163
- sin_theta = Math.sin(theta)
164
- sin_theta_0 = Math.sin(theta_0)
165
-
166
- s0 = Math.cos(theta) - dot_val * sin_theta / sin_theta_0
167
- s1 = sin_theta / sin_theta_0
168
-
169
- Quat.new(
170
- @x * s0 + other.x * s1,
171
- @y * s0 + other.y * s1,
172
- @z * s0 + other.z * s1,
173
- @w * s0 + other.w * s1
174
- )
175
- end
176
-
177
- def to_axis_angle
178
- angle = 2 * Math.acos(@w.clamp(-1.0, 1.0))
179
- s = Math.sqrt(1 - @w * @w)
180
- if s < 0.001
181
- axis = Vec3.new(1, 0, 0)
182
- else
183
- axis = Vec3.new(@x / s, @y / s, @z / s)
184
- end
185
- [axis, angle]
186
- end
187
-
188
- def to_euler
189
- sinr_cosp = 2 * (@w * @x + @y * @z)
190
- cosr_cosp = 1 - 2 * (@x * @x + @y * @y)
191
- roll = Math.atan2(sinr_cosp, cosr_cosp)
192
-
193
- sinp = 2 * (@w * @y - @z * @x)
194
- pitch = if sinp.abs >= 1
195
- Math.copysign(Math::PI / 2, sinp)
196
- else
197
- Math.asin(sinp)
198
- end
199
-
200
- siny_cosp = 2 * (@w * @z + @x * @y)
201
- cosy_cosp = 1 - 2 * (@y * @y + @z * @z)
202
- yaw = Math.atan2(siny_cosp, cosy_cosp)
203
-
204
- Vec3.new(roll, pitch, yaw)
205
- end
206
-
207
- def to_mat4
208
- Mat4.from_quaternion(self)
209
- end
210
-
211
- def to_a
212
- [@x, @y, @z, @w]
213
- end
214
-
215
- def [](i)
216
- to_a[i]
217
- end
218
-
219
- def ==(other)
220
- return false unless other.is_a?(Quat)
221
-
222
- @x == other.x && @y == other.y && @z == other.z && @w == other.w
223
- end
224
-
225
- def near?(other, epsilon = 1e-6)
226
- (@x - other.x).abs < epsilon &&
227
- (@y - other.y).abs < epsilon &&
228
- (@z - other.z).abs < epsilon &&
229
- (@w - other.w).abs < epsilon
230
- end
231
-
232
- def inspect
233
- "Quat[#{@x}, #{@y}, #{@z}, #{@w}]"
234
- end
235
-
236
- alias to_s inspect
237
- end
238
- end