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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +4 -0
- data/README.md +14 -1
- data/ext/larb/color.c +446 -0
- data/ext/larb/color.h +35 -0
- data/ext/larb/extconf.rb +11 -0
- data/ext/larb/larb.c +27 -0
- data/ext/larb/larb.h +8 -0
- data/ext/larb/mat2.c +300 -0
- data/ext/larb/mat2.h +30 -0
- data/ext/larb/mat2d.c +380 -0
- data/ext/larb/mat2d.h +35 -0
- data/ext/larb/mat3.c +469 -0
- data/ext/larb/mat3.h +33 -0
- data/ext/larb/mat4.c +671 -0
- data/ext/larb/mat4.h +31 -0
- data/ext/larb/quat.c +523 -0
- data/ext/larb/quat.h +39 -0
- data/ext/larb/quat2.c +473 -0
- data/ext/larb/quat2.h +39 -0
- data/ext/larb/vec2.c +342 -0
- data/ext/larb/vec2.h +43 -0
- data/ext/larb/vec3.c +503 -0
- data/ext/larb/vec3.h +52 -0
- data/ext/larb/vec4.c +340 -0
- data/ext/larb/vec4.h +38 -0
- data/lib/larb/version.rb +5 -0
- data/lib/larb.rb +2 -14
- data/test/larb/color_test.rb +278 -0
- data/test/larb/mat2_test.rb +144 -0
- data/test/larb/mat2d_test.rb +172 -0
- data/test/larb/mat3_test.rb +147 -0
- data/test/larb/mat4_test.rb +270 -0
- data/test/larb/quat2_test.rb +161 -0
- data/test/larb/quat_test.rb +224 -0
- data/test/larb/vec2_test.rb +251 -0
- data/test/larb/vec3_test.rb +310 -0
- data/test/larb/vec4_test.rb +189 -0
- data/test/test_helper.rb +4 -0
- metadata +53 -14
- data/Rakefile +0 -11
- data/lib/larb/color.rb +0 -148
- data/lib/larb/mat2.rb +0 -119
- data/lib/larb/mat2d.rb +0 -180
- data/lib/larb/mat3.rb +0 -238
- data/lib/larb/mat4.rb +0 -329
- data/lib/larb/quat.rb +0 -238
- data/lib/larb/quat2.rb +0 -193
- data/lib/larb/vec2.rb +0 -150
- data/lib/larb/vec3.rb +0 -218
- data/lib/larb/vec4.rb +0 -125
|
@@ -0,0 +1,144 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require_relative "../test_helper"
|
|
4
|
+
|
|
5
|
+
class Mat2Test < Test::Unit::TestCase
|
|
6
|
+
def test_new_identity_by_default
|
|
7
|
+
m = Larb::Mat2.new
|
|
8
|
+
assert_equal 1.0, m[0]
|
|
9
|
+
assert_equal 0.0, m[1]
|
|
10
|
+
assert_equal 0.0, m[2]
|
|
11
|
+
assert_equal 1.0, m[3]
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
def test_new_with_data
|
|
15
|
+
m = Larb::Mat2.new([1, 2, 3, 4])
|
|
16
|
+
assert_equal [1, 2, 3, 4], m.data
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
def test_identity
|
|
20
|
+
m = Larb::Mat2.identity
|
|
21
|
+
assert_equal 1.0, m[0]
|
|
22
|
+
assert_equal 1.0, m[3]
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
def test_zero
|
|
26
|
+
m = Larb::Mat2.zero
|
|
27
|
+
4.times { |i| assert_equal 0.0, m[i] }
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
def test_rotation
|
|
31
|
+
m = Larb::Mat2.rotation(Math::PI / 2)
|
|
32
|
+
assert_in_delta 0.0, m[0], 1e-10
|
|
33
|
+
assert_in_delta 1.0, m[1], 1e-10
|
|
34
|
+
assert_in_delta(-1.0, m[2], 1e-10)
|
|
35
|
+
assert_in_delta 0.0, m[3], 1e-10
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
def test_scaling
|
|
39
|
+
m = Larb::Mat2.scaling(2, 3)
|
|
40
|
+
assert_equal 2.0, m[0]
|
|
41
|
+
assert_equal 3.0, m[3]
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
def test_from_vec2
|
|
45
|
+
v1 = Larb::Vec2.new(1, 2)
|
|
46
|
+
v2 = Larb::Vec2.new(3, 4)
|
|
47
|
+
m = Larb::Mat2.from_vec2(v1, v2)
|
|
48
|
+
assert_equal [1.0, 2.0, 3.0, 4.0], m.data
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
def test_multiply_mat2
|
|
52
|
+
m1 = Larb::Mat2.rotation(Math::PI / 4)
|
|
53
|
+
m2 = Larb::Mat2.rotation(Math::PI / 4)
|
|
54
|
+
result = m1 * m2
|
|
55
|
+
expected = Larb::Mat2.rotation(Math::PI / 2)
|
|
56
|
+
assert result.near?(expected)
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
def test_multiply_vec2
|
|
60
|
+
m = Larb::Mat2.rotation(Math::PI / 2)
|
|
61
|
+
v = Larb::Vec2.new(1, 0)
|
|
62
|
+
result = m * v
|
|
63
|
+
assert_in_delta 0.0, result.x, 1e-10
|
|
64
|
+
assert_in_delta 1.0, result.y, 1e-10
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
def test_multiply_scalar
|
|
68
|
+
m = Larb::Mat2.identity
|
|
69
|
+
result = m * 2
|
|
70
|
+
assert_equal 2.0, result[0]
|
|
71
|
+
assert_equal 2.0, result[3]
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
def test_add
|
|
75
|
+
m1 = Larb::Mat2.identity
|
|
76
|
+
m2 = Larb::Mat2.identity
|
|
77
|
+
result = m1 + m2
|
|
78
|
+
assert_equal 2.0, result[0]
|
|
79
|
+
end
|
|
80
|
+
|
|
81
|
+
def test_subtract
|
|
82
|
+
m1 = Larb::Mat2.identity
|
|
83
|
+
m2 = Larb::Mat2.identity
|
|
84
|
+
result = m1 - m2
|
|
85
|
+
assert_equal 0.0, result[0]
|
|
86
|
+
end
|
|
87
|
+
|
|
88
|
+
def test_determinant
|
|
89
|
+
m = Larb::Mat2.identity
|
|
90
|
+
assert_equal 1.0, m.determinant
|
|
91
|
+
end
|
|
92
|
+
|
|
93
|
+
def test_determinant_scaling
|
|
94
|
+
m = Larb::Mat2.scaling(2, 3)
|
|
95
|
+
assert_equal 6.0, m.determinant
|
|
96
|
+
end
|
|
97
|
+
|
|
98
|
+
def test_inverse
|
|
99
|
+
m = Larb::Mat2.scaling(2, 4)
|
|
100
|
+
inv = m.inverse
|
|
101
|
+
result = m * inv
|
|
102
|
+
assert result.near?(Larb::Mat2.identity)
|
|
103
|
+
end
|
|
104
|
+
|
|
105
|
+
def test_inverse_singular
|
|
106
|
+
m = Larb::Mat2.zero
|
|
107
|
+
assert_raise_message("Matrix is not invertible") { m.inverse }
|
|
108
|
+
end
|
|
109
|
+
|
|
110
|
+
def test_transpose
|
|
111
|
+
m = Larb::Mat2.new([1, 2, 3, 4])
|
|
112
|
+
result = m.transpose
|
|
113
|
+
assert_equal [1, 3, 2, 4], result.data
|
|
114
|
+
end
|
|
115
|
+
|
|
116
|
+
def test_adjoint
|
|
117
|
+
m = Larb::Mat2.new([1, 2, 3, 4])
|
|
118
|
+
adj = m.adjoint
|
|
119
|
+
assert_equal 4.0, adj[0]
|
|
120
|
+
assert_equal(-2.0, adj[1])
|
|
121
|
+
end
|
|
122
|
+
|
|
123
|
+
def test_frobenius_norm
|
|
124
|
+
m = Larb::Mat2.new([1, 2, 2, 0])
|
|
125
|
+
assert_equal 3.0, m.frobenius_norm
|
|
126
|
+
end
|
|
127
|
+
|
|
128
|
+
def test_equality
|
|
129
|
+
m1 = Larb::Mat2.identity
|
|
130
|
+
m2 = Larb::Mat2.identity
|
|
131
|
+
assert_equal m1, m2
|
|
132
|
+
end
|
|
133
|
+
|
|
134
|
+
def test_near
|
|
135
|
+
m1 = Larb::Mat2.identity
|
|
136
|
+
m2 = Larb::Mat2.new([1.0000001, 0, 0, 1.0000001])
|
|
137
|
+
assert m1.near?(m2)
|
|
138
|
+
end
|
|
139
|
+
|
|
140
|
+
def test_inspect
|
|
141
|
+
m = Larb::Mat2.identity
|
|
142
|
+
assert_match(/Mat2/, m.inspect)
|
|
143
|
+
end
|
|
144
|
+
end
|
|
@@ -0,0 +1,172 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require_relative "../test_helper"
|
|
4
|
+
|
|
5
|
+
class Mat2dTest < Test::Unit::TestCase
|
|
6
|
+
def test_new_identity_by_default
|
|
7
|
+
m = Larb::Mat2d.new
|
|
8
|
+
assert_equal 1.0, m[0]
|
|
9
|
+
assert_equal 0.0, m[1]
|
|
10
|
+
assert_equal 0.0, m[2]
|
|
11
|
+
assert_equal 1.0, m[3]
|
|
12
|
+
assert_equal 0.0, m[4]
|
|
13
|
+
assert_equal 0.0, m[5]
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
def test_new_with_data
|
|
17
|
+
data = [1, 2, 3, 4, 5, 6]
|
|
18
|
+
m = Larb::Mat2d.new(data)
|
|
19
|
+
assert_equal [1, 2, 3, 4, 5, 6], m.data
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
def test_identity
|
|
23
|
+
m = Larb::Mat2d.identity
|
|
24
|
+
assert_equal 1.0, m[0]
|
|
25
|
+
assert_equal 1.0, m[3]
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
def test_zero
|
|
29
|
+
m = Larb::Mat2d.zero
|
|
30
|
+
6.times { |i| assert_equal 0.0, m[i] }
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
def test_translation
|
|
34
|
+
m = Larb::Mat2d.translation(10, 20)
|
|
35
|
+
assert_equal 10.0, m[4]
|
|
36
|
+
assert_equal 20.0, m[5]
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
def test_rotation
|
|
40
|
+
m = Larb::Mat2d.rotation(Math::PI / 2)
|
|
41
|
+
assert_in_delta 0.0, m[0], 1e-10
|
|
42
|
+
assert_in_delta 1.0, m[1], 1e-10
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
def test_scaling
|
|
46
|
+
m = Larb::Mat2d.scaling(2, 3)
|
|
47
|
+
assert_equal 2.0, m[0]
|
|
48
|
+
assert_equal 3.0, m[3]
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
def test_from_rotation_translation_scale
|
|
52
|
+
m = Larb::Mat2d.from_rotation_translation_scale(
|
|
53
|
+
0,
|
|
54
|
+
Larb::Vec2.new(10, 20),
|
|
55
|
+
Larb::Vec2.new(2, 3)
|
|
56
|
+
)
|
|
57
|
+
assert_equal 2.0, m[0]
|
|
58
|
+
assert_equal 3.0, m[3]
|
|
59
|
+
assert_equal 10.0, m[4]
|
|
60
|
+
assert_equal 20.0, m[5]
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
def test_multiply_mat2d
|
|
64
|
+
m1 = Larb::Mat2d.translation(10, 0)
|
|
65
|
+
m2 = Larb::Mat2d.translation(5, 0)
|
|
66
|
+
result = m1 * m2
|
|
67
|
+
assert_equal 15.0, result[4]
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
def test_multiply_vec2
|
|
71
|
+
m = Larb::Mat2d.translation(10, 20)
|
|
72
|
+
v = Larb::Vec2.new(0, 0)
|
|
73
|
+
result = m * v
|
|
74
|
+
assert_equal 10.0, result.x
|
|
75
|
+
assert_equal 20.0, result.y
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
def test_multiply_rotation_translation
|
|
79
|
+
m = Larb::Mat2d.rotation(Math::PI / 2) * Larb::Mat2d.translation(1, 0)
|
|
80
|
+
v = Larb::Vec2.new(0, 0)
|
|
81
|
+
result = m * v
|
|
82
|
+
assert_in_delta 0.0, result.x, 1e-10
|
|
83
|
+
assert_in_delta 1.0, result.y, 1e-10
|
|
84
|
+
end
|
|
85
|
+
|
|
86
|
+
def test_determinant
|
|
87
|
+
m = Larb::Mat2d.identity
|
|
88
|
+
assert_equal 1.0, m.determinant
|
|
89
|
+
end
|
|
90
|
+
|
|
91
|
+
def test_determinant_scaling
|
|
92
|
+
m = Larb::Mat2d.scaling(2, 3)
|
|
93
|
+
assert_equal 6.0, m.determinant
|
|
94
|
+
end
|
|
95
|
+
|
|
96
|
+
def test_inverse
|
|
97
|
+
m = Larb::Mat2d.translation(10, 20) * Larb::Mat2d.scaling(2, 2)
|
|
98
|
+
inv = m.inverse
|
|
99
|
+
result = m * inv
|
|
100
|
+
assert result.near?(Larb::Mat2d.identity)
|
|
101
|
+
end
|
|
102
|
+
|
|
103
|
+
def test_inverse_singular
|
|
104
|
+
m = Larb::Mat2d.zero
|
|
105
|
+
assert_raise_message("Matrix is not invertible") { m.inverse }
|
|
106
|
+
end
|
|
107
|
+
|
|
108
|
+
def test_translate
|
|
109
|
+
m = Larb::Mat2d.identity
|
|
110
|
+
result = m.translate(5, 10)
|
|
111
|
+
assert_equal 5.0, result[4]
|
|
112
|
+
assert_equal 10.0, result[5]
|
|
113
|
+
end
|
|
114
|
+
|
|
115
|
+
def test_rotate
|
|
116
|
+
m = Larb::Mat2d.identity
|
|
117
|
+
result = m.rotate(Math::PI / 2)
|
|
118
|
+
assert_in_delta 0.0, result[0], 1e-10
|
|
119
|
+
end
|
|
120
|
+
|
|
121
|
+
def test_scale
|
|
122
|
+
m = Larb::Mat2d.identity
|
|
123
|
+
result = m.scale(2, 3)
|
|
124
|
+
assert_equal 2.0, result[0]
|
|
125
|
+
assert_equal 3.0, result[3]
|
|
126
|
+
end
|
|
127
|
+
|
|
128
|
+
def test_extract_translation
|
|
129
|
+
m = Larb::Mat2d.translation(10, 20)
|
|
130
|
+
t = m.extract_translation
|
|
131
|
+
assert_equal 10.0, t.x
|
|
132
|
+
assert_equal 20.0, t.y
|
|
133
|
+
end
|
|
134
|
+
|
|
135
|
+
def test_extract_rotation
|
|
136
|
+
m = Larb::Mat2d.rotation(Math::PI / 4)
|
|
137
|
+
angle = m.extract_rotation
|
|
138
|
+
assert_in_delta Math::PI / 4, angle, 1e-10
|
|
139
|
+
end
|
|
140
|
+
|
|
141
|
+
def test_extract_scale
|
|
142
|
+
m = Larb::Mat2d.scaling(2, 3)
|
|
143
|
+
s = m.extract_scale
|
|
144
|
+
assert_in_delta 2.0, s.x, 1e-10
|
|
145
|
+
assert_in_delta 3.0, s.y, 1e-10
|
|
146
|
+
end
|
|
147
|
+
|
|
148
|
+
def test_to_mat3
|
|
149
|
+
m = Larb::Mat2d.translation(10, 20)
|
|
150
|
+
m3 = m.to_mat3
|
|
151
|
+
assert_instance_of Larb::Mat3, m3
|
|
152
|
+
assert_equal 10.0, m3[6]
|
|
153
|
+
assert_equal 20.0, m3[7]
|
|
154
|
+
end
|
|
155
|
+
|
|
156
|
+
def test_equality
|
|
157
|
+
m1 = Larb::Mat2d.identity
|
|
158
|
+
m2 = Larb::Mat2d.identity
|
|
159
|
+
assert_equal m1, m2
|
|
160
|
+
end
|
|
161
|
+
|
|
162
|
+
def test_near
|
|
163
|
+
m1 = Larb::Mat2d.identity
|
|
164
|
+
m2 = Larb::Mat2d.new([1.0000001, 0, 0, 1.0000001, 0, 0])
|
|
165
|
+
assert m1.near?(m2)
|
|
166
|
+
end
|
|
167
|
+
|
|
168
|
+
def test_inspect
|
|
169
|
+
m = Larb::Mat2d.identity
|
|
170
|
+
assert_match(/Mat2d/, m.inspect)
|
|
171
|
+
end
|
|
172
|
+
end
|
|
@@ -0,0 +1,147 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require_relative "../test_helper"
|
|
4
|
+
|
|
5
|
+
class Mat3Test < Test::Unit::TestCase
|
|
6
|
+
def test_new_identity_by_default
|
|
7
|
+
m = Larb::Mat3.new
|
|
8
|
+
assert_equal 1.0, m[0]
|
|
9
|
+
assert_equal 1.0, m[4]
|
|
10
|
+
assert_equal 1.0, m[8]
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
def test_new_with_data
|
|
14
|
+
data = Array.new(9) { |i| i.to_f }
|
|
15
|
+
m = Larb::Mat3.new(data)
|
|
16
|
+
assert_equal data, m.data
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
def test_identity
|
|
20
|
+
m = Larb::Mat3.identity
|
|
21
|
+
assert_equal 1.0, m[0]
|
|
22
|
+
assert_equal 1.0, m[4]
|
|
23
|
+
assert_equal 1.0, m[8]
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
def test_zero
|
|
27
|
+
m = Larb::Mat3.zero
|
|
28
|
+
9.times { |i| assert_equal 0.0, m[i] }
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
def test_from_mat4
|
|
32
|
+
m4 = Larb::Mat4.identity
|
|
33
|
+
m3 = Larb::Mat3.from_mat4(m4)
|
|
34
|
+
assert_equal 1.0, m3[0]
|
|
35
|
+
assert_equal 1.0, m3[4]
|
|
36
|
+
assert_equal 1.0, m3[8]
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
def test_from_quaternion
|
|
40
|
+
q = Larb::Quat.from_axis_angle(Larb::Vec3.new(0, 0, 1), Math::PI / 2)
|
|
41
|
+
m = Larb::Mat3.from_quaternion(q)
|
|
42
|
+
assert_in_delta 0.0, m[0], 1e-10
|
|
43
|
+
assert_in_delta 1.0, m[1], 1e-10
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
def test_translation
|
|
47
|
+
m = Larb::Mat3.translation(5, 10)
|
|
48
|
+
assert_equal 5.0, m[6]
|
|
49
|
+
assert_equal 10.0, m[7]
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
def test_rotation
|
|
53
|
+
m = Larb::Mat3.rotation(Math::PI / 2)
|
|
54
|
+
assert_in_delta 0.0, m[0], 1e-10
|
|
55
|
+
assert_in_delta 1.0, m[1], 1e-10
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
def test_scaling
|
|
59
|
+
m = Larb::Mat3.scaling(2, 3)
|
|
60
|
+
assert_equal 2.0, m[0]
|
|
61
|
+
assert_equal 3.0, m[4]
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
def test_multiply_mat3
|
|
65
|
+
m1 = Larb::Mat3.identity
|
|
66
|
+
m2 = Larb::Mat3.translation(1, 2)
|
|
67
|
+
result = m1 * m2
|
|
68
|
+
assert_equal 1.0, result[6]
|
|
69
|
+
assert_equal 2.0, result[7]
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
def test_multiply_vec3
|
|
73
|
+
m = Larb::Mat3.scaling(2, 3)
|
|
74
|
+
v = Larb::Vec3.new(1, 1, 1)
|
|
75
|
+
result = m * v
|
|
76
|
+
assert_equal 2.0, result.x
|
|
77
|
+
assert_equal 3.0, result.y
|
|
78
|
+
end
|
|
79
|
+
|
|
80
|
+
def test_determinant
|
|
81
|
+
m = Larb::Mat3.identity
|
|
82
|
+
assert_equal 1.0, m.determinant
|
|
83
|
+
end
|
|
84
|
+
|
|
85
|
+
def test_determinant_scaling
|
|
86
|
+
m = Larb::Mat3.scaling(2, 3)
|
|
87
|
+
assert_equal 6.0, m.determinant
|
|
88
|
+
end
|
|
89
|
+
|
|
90
|
+
def test_inverse
|
|
91
|
+
m = Larb::Mat3.scaling(2, 4)
|
|
92
|
+
inv = m.inverse
|
|
93
|
+
result = m * inv
|
|
94
|
+
assert result.near?(Larb::Mat3.identity)
|
|
95
|
+
end
|
|
96
|
+
|
|
97
|
+
def test_inverse_singular
|
|
98
|
+
m = Larb::Mat3.zero
|
|
99
|
+
assert_raise_message("Matrix is not invertible") { m.inverse }
|
|
100
|
+
end
|
|
101
|
+
|
|
102
|
+
def test_transpose
|
|
103
|
+
data = Array.new(9) { |i| i.to_f }
|
|
104
|
+
m = Larb::Mat3.new(data)
|
|
105
|
+
result = m.transpose
|
|
106
|
+
assert_equal 3.0, result[1]
|
|
107
|
+
assert_equal 1.0, result[3]
|
|
108
|
+
end
|
|
109
|
+
|
|
110
|
+
def test_translate
|
|
111
|
+
m = Larb::Mat3.identity
|
|
112
|
+
result = m.translate(5, 10)
|
|
113
|
+
assert_equal 5.0, result[6]
|
|
114
|
+
assert_equal 10.0, result[7]
|
|
115
|
+
end
|
|
116
|
+
|
|
117
|
+
def test_rotate
|
|
118
|
+
m = Larb::Mat3.identity
|
|
119
|
+
result = m.rotate(Math::PI / 2)
|
|
120
|
+
assert_in_delta 0.0, result[0], 1e-10
|
|
121
|
+
end
|
|
122
|
+
|
|
123
|
+
def test_scale
|
|
124
|
+
m = Larb::Mat3.identity
|
|
125
|
+
result = m.scale(2, 3)
|
|
126
|
+
assert_equal 2.0, result[0]
|
|
127
|
+
assert_equal 3.0, result[4]
|
|
128
|
+
end
|
|
129
|
+
|
|
130
|
+
def test_equality
|
|
131
|
+
m1 = Larb::Mat3.identity
|
|
132
|
+
m2 = Larb::Mat3.identity
|
|
133
|
+
assert_equal m1, m2
|
|
134
|
+
end
|
|
135
|
+
|
|
136
|
+
def test_near
|
|
137
|
+
m1 = Larb::Mat3.identity
|
|
138
|
+
m2 = Larb::Mat3.identity
|
|
139
|
+
m2[0] = 1.0000001
|
|
140
|
+
assert m1.near?(m2)
|
|
141
|
+
end
|
|
142
|
+
|
|
143
|
+
def test_inspect
|
|
144
|
+
m = Larb::Mat3.identity
|
|
145
|
+
assert_match(/Mat3/, m.inspect)
|
|
146
|
+
end
|
|
147
|
+
end
|
|
@@ -0,0 +1,270 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require_relative "../test_helper"
|
|
4
|
+
|
|
5
|
+
class Mat4Test < Test::Unit::TestCase
|
|
6
|
+
def test_new_identity_by_default
|
|
7
|
+
m = Larb::Mat4.new
|
|
8
|
+
assert_equal 1.0, m[0]
|
|
9
|
+
assert_equal 1.0, m[5]
|
|
10
|
+
assert_equal 1.0, m[10]
|
|
11
|
+
assert_equal 1.0, m[15]
|
|
12
|
+
assert_equal 0.0, m[1]
|
|
13
|
+
assert_equal 0.0, m[4]
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
def test_new_with_data
|
|
17
|
+
data = Array.new(16) { |i| i.to_f }
|
|
18
|
+
m = Larb::Mat4.new(data)
|
|
19
|
+
assert_equal data, m.data
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
def test_identity
|
|
23
|
+
m = Larb::Mat4.identity
|
|
24
|
+
assert_equal 1.0, m[0]
|
|
25
|
+
assert_equal 1.0, m[5]
|
|
26
|
+
assert_equal 1.0, m[10]
|
|
27
|
+
assert_equal 1.0, m[15]
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
def test_zero
|
|
31
|
+
m = Larb::Mat4.zero
|
|
32
|
+
16.times { |i| assert_equal 0.0, m[i] }
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
def test_translation
|
|
36
|
+
m = Larb::Mat4.translation(1, 2, 3)
|
|
37
|
+
assert_equal 1.0, m[12]
|
|
38
|
+
assert_equal 2.0, m[13]
|
|
39
|
+
assert_equal 3.0, m[14]
|
|
40
|
+
assert_equal 1.0, m[0]
|
|
41
|
+
assert_equal 1.0, m[5]
|
|
42
|
+
assert_equal 1.0, m[10]
|
|
43
|
+
assert_equal 1.0, m[15]
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
def test_scaling
|
|
47
|
+
m = Larb::Mat4.scaling(2, 3, 4)
|
|
48
|
+
assert_equal 2.0, m[0]
|
|
49
|
+
assert_equal 3.0, m[5]
|
|
50
|
+
assert_equal 4.0, m[10]
|
|
51
|
+
assert_equal 1.0, m[15]
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
def test_rotation_x
|
|
55
|
+
m = Larb::Mat4.rotation_x(Math::PI / 2)
|
|
56
|
+
assert_equal 1.0, m[0]
|
|
57
|
+
assert_in_delta 0.0, m[5], 1e-10
|
|
58
|
+
assert_in_delta 1.0, m[6], 1e-10
|
|
59
|
+
assert_in_delta(-1.0, m[9], 1e-10)
|
|
60
|
+
assert_in_delta 0.0, m[10], 1e-10
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
def test_rotation_y
|
|
64
|
+
m = Larb::Mat4.rotation_y(Math::PI / 2)
|
|
65
|
+
assert_in_delta 0.0, m[0], 1e-10
|
|
66
|
+
assert_in_delta(-1.0, m[2], 1e-10)
|
|
67
|
+
assert_equal 1.0, m[5]
|
|
68
|
+
assert_in_delta 1.0, m[8], 1e-10
|
|
69
|
+
assert_in_delta 0.0, m[10], 1e-10
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
def test_rotation_z
|
|
73
|
+
m = Larb::Mat4.rotation_z(Math::PI / 2)
|
|
74
|
+
assert_in_delta 0.0, m[0], 1e-10
|
|
75
|
+
assert_in_delta 1.0, m[1], 1e-10
|
|
76
|
+
assert_in_delta(-1.0, m[4], 1e-10)
|
|
77
|
+
assert_in_delta 0.0, m[5], 1e-10
|
|
78
|
+
assert_equal 1.0, m[10]
|
|
79
|
+
end
|
|
80
|
+
|
|
81
|
+
def test_rotation
|
|
82
|
+
m = Larb::Mat4.rotation(Larb::Vec3.new(0, 1, 0), Math::PI / 2)
|
|
83
|
+
assert_in_delta 0.0, m[0], 1e-10
|
|
84
|
+
assert_in_delta 1.0, m[8], 1e-10
|
|
85
|
+
end
|
|
86
|
+
|
|
87
|
+
def test_look_at
|
|
88
|
+
eye = Larb::Vec3.new(0, 0, 5)
|
|
89
|
+
target = Larb::Vec3.new(0, 0, 0)
|
|
90
|
+
up = Larb::Vec3.new(0, 1, 0)
|
|
91
|
+
m = Larb::Mat4.look_at(eye, target, up)
|
|
92
|
+
assert_instance_of Larb::Mat4, m
|
|
93
|
+
assert_in_delta(-5.0, m[14], 1e-10)
|
|
94
|
+
end
|
|
95
|
+
|
|
96
|
+
def test_perspective
|
|
97
|
+
m = Larb::Mat4.perspective(Math::PI / 4, 16.0 / 9.0, 0.1, 100.0)
|
|
98
|
+
assert_instance_of Larb::Mat4, m
|
|
99
|
+
assert_equal(-1.0, m[11])
|
|
100
|
+
end
|
|
101
|
+
|
|
102
|
+
def test_orthographic
|
|
103
|
+
m = Larb::Mat4.orthographic(-1, 1, -1, 1, 0.1, 100)
|
|
104
|
+
assert_instance_of Larb::Mat4, m
|
|
105
|
+
assert_equal 1.0, m[0]
|
|
106
|
+
assert_equal 1.0, m[5]
|
|
107
|
+
end
|
|
108
|
+
|
|
109
|
+
def test_index_access
|
|
110
|
+
m = Larb::Mat4.identity
|
|
111
|
+
assert_equal 1.0, m[0]
|
|
112
|
+
assert_equal 0.0, m[1]
|
|
113
|
+
end
|
|
114
|
+
|
|
115
|
+
def test_index_assignment
|
|
116
|
+
m = Larb::Mat4.identity
|
|
117
|
+
m[0] = 5.0
|
|
118
|
+
assert_equal 5.0, m[0]
|
|
119
|
+
end
|
|
120
|
+
|
|
121
|
+
def test_multiply_mat4
|
|
122
|
+
m1 = Larb::Mat4.translation(1, 0, 0)
|
|
123
|
+
m2 = Larb::Mat4.translation(0, 1, 0)
|
|
124
|
+
result = m1 * m2
|
|
125
|
+
assert_equal 1.0, result[12]
|
|
126
|
+
assert_equal 1.0, result[13]
|
|
127
|
+
end
|
|
128
|
+
|
|
129
|
+
def test_multiply_identity
|
|
130
|
+
m = Larb::Mat4.translation(1, 2, 3)
|
|
131
|
+
result = Larb::Mat4.identity * m
|
|
132
|
+
assert_equal m.data, result.data
|
|
133
|
+
end
|
|
134
|
+
|
|
135
|
+
def test_multiply_vec4
|
|
136
|
+
m = Larb::Mat4.translation(1, 2, 3)
|
|
137
|
+
v = Larb::Vec4.new(0, 0, 0, 1)
|
|
138
|
+
result = m * v
|
|
139
|
+
assert_equal 1.0, result.x
|
|
140
|
+
assert_equal 2.0, result.y
|
|
141
|
+
assert_equal 3.0, result.z
|
|
142
|
+
assert_equal 1.0, result.w
|
|
143
|
+
end
|
|
144
|
+
|
|
145
|
+
def test_multiply_vec3
|
|
146
|
+
m = Larb::Mat4.translation(1, 2, 3)
|
|
147
|
+
v = Larb::Vec3.new(0, 0, 0)
|
|
148
|
+
result = m * v
|
|
149
|
+
assert_equal 1.0, result.x
|
|
150
|
+
assert_equal 2.0, result.y
|
|
151
|
+
assert_equal 3.0, result.z
|
|
152
|
+
end
|
|
153
|
+
|
|
154
|
+
def test_transpose
|
|
155
|
+
data = Array.new(16) { |i| i.to_f }
|
|
156
|
+
m = Larb::Mat4.new(data)
|
|
157
|
+
result = m.transpose
|
|
158
|
+
assert_equal 4.0, result[1]
|
|
159
|
+
assert_equal 1.0, result[4]
|
|
160
|
+
assert_equal 8.0, result[2]
|
|
161
|
+
assert_equal 2.0, result[8]
|
|
162
|
+
end
|
|
163
|
+
|
|
164
|
+
def test_inverse
|
|
165
|
+
m = Larb::Mat4.translation(1, 2, 3)
|
|
166
|
+
inv = m.inverse
|
|
167
|
+
result = m * inv
|
|
168
|
+
assert_in_delta 1.0, result[0], 1e-10
|
|
169
|
+
assert_in_delta 1.0, result[5], 1e-10
|
|
170
|
+
assert_in_delta 1.0, result[10], 1e-10
|
|
171
|
+
assert_in_delta 1.0, result[15], 1e-10
|
|
172
|
+
assert_in_delta 0.0, result[12], 1e-10
|
|
173
|
+
assert_in_delta 0.0, result[13], 1e-10
|
|
174
|
+
assert_in_delta 0.0, result[14], 1e-10
|
|
175
|
+
end
|
|
176
|
+
|
|
177
|
+
def test_inverse_singular
|
|
178
|
+
m = Larb::Mat4.zero
|
|
179
|
+
assert_raise_message("Matrix is not invertible") { m.inverse }
|
|
180
|
+
end
|
|
181
|
+
|
|
182
|
+
def test_to_a
|
|
183
|
+
m = Larb::Mat4.identity
|
|
184
|
+
arr = m.to_a
|
|
185
|
+
assert_equal m.data, arr
|
|
186
|
+
arr[0] = 999
|
|
187
|
+
assert_equal 1.0, m.data[0]
|
|
188
|
+
end
|
|
189
|
+
|
|
190
|
+
def test_determinant
|
|
191
|
+
m = Larb::Mat4.identity
|
|
192
|
+
assert_equal 1.0, m.determinant
|
|
193
|
+
end
|
|
194
|
+
|
|
195
|
+
def test_determinant_zero
|
|
196
|
+
m = Larb::Mat4.zero
|
|
197
|
+
assert_equal 0.0, m.determinant
|
|
198
|
+
end
|
|
199
|
+
|
|
200
|
+
def test_determinant_scaling
|
|
201
|
+
m = Larb::Mat4.scaling(2, 3, 4)
|
|
202
|
+
assert_equal 24.0, m.determinant
|
|
203
|
+
end
|
|
204
|
+
|
|
205
|
+
def test_add
|
|
206
|
+
m1 = Larb::Mat4.identity
|
|
207
|
+
m2 = Larb::Mat4.identity
|
|
208
|
+
result = m1 + m2
|
|
209
|
+
assert_equal 2.0, result[0]
|
|
210
|
+
assert_equal 2.0, result[5]
|
|
211
|
+
end
|
|
212
|
+
|
|
213
|
+
def test_subtract
|
|
214
|
+
m1 = Larb::Mat4.identity
|
|
215
|
+
m2 = Larb::Mat4.identity
|
|
216
|
+
result = m1 - m2
|
|
217
|
+
assert_equal 0.0, result[0]
|
|
218
|
+
assert_equal 0.0, result[5]
|
|
219
|
+
end
|
|
220
|
+
|
|
221
|
+
def test_equality
|
|
222
|
+
m1 = Larb::Mat4.identity
|
|
223
|
+
m2 = Larb::Mat4.identity
|
|
224
|
+
assert_equal m1, m2
|
|
225
|
+
end
|
|
226
|
+
|
|
227
|
+
def test_inequality
|
|
228
|
+
m1 = Larb::Mat4.identity
|
|
229
|
+
m2 = Larb::Mat4.translation(1, 0, 0)
|
|
230
|
+
assert_not_equal m1, m2
|
|
231
|
+
end
|
|
232
|
+
|
|
233
|
+
def test_near
|
|
234
|
+
m1 = Larb::Mat4.identity
|
|
235
|
+
m2 = Larb::Mat4.identity
|
|
236
|
+
m2[0] = 1.0000001
|
|
237
|
+
assert m1.near?(m2)
|
|
238
|
+
end
|
|
239
|
+
|
|
240
|
+
def test_extract_translation
|
|
241
|
+
m = Larb::Mat4.translation(1, 2, 3)
|
|
242
|
+
result = m.extract_translation
|
|
243
|
+
assert_equal Larb::Vec3.new(1, 2, 3), result
|
|
244
|
+
end
|
|
245
|
+
|
|
246
|
+
def test_extract_scale
|
|
247
|
+
m = Larb::Mat4.scaling(2, 3, 4)
|
|
248
|
+
result = m.extract_scale
|
|
249
|
+
assert_in_delta 2.0, result.x, 1e-10
|
|
250
|
+
assert_in_delta 3.0, result.y, 1e-10
|
|
251
|
+
assert_in_delta 4.0, result.z, 1e-10
|
|
252
|
+
end
|
|
253
|
+
|
|
254
|
+
def test_frustum
|
|
255
|
+
m = Larb::Mat4.frustum(-1, 1, -1, 1, 0.1, 100)
|
|
256
|
+
assert_instance_of Larb::Mat4, m
|
|
257
|
+
end
|
|
258
|
+
|
|
259
|
+
def test_from_quaternion
|
|
260
|
+
q = Larb::Quat.from_axis_angle(Larb::Vec3.new(0, 1, 0), Math::PI / 2)
|
|
261
|
+
m = Larb::Mat4.from_quaternion(q)
|
|
262
|
+
assert_instance_of Larb::Mat4, m
|
|
263
|
+
assert_in_delta 0.0, m[0], 1e-10
|
|
264
|
+
end
|
|
265
|
+
|
|
266
|
+
def test_inspect
|
|
267
|
+
m = Larb::Mat4.identity
|
|
268
|
+
assert_match(/Mat4/, m.inspect)
|
|
269
|
+
end
|
|
270
|
+
end
|