geo3d 0.0.5 → 0.0.6
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/README.md +49 -1
- data/Rakefile +7 -0
- data/geo3d.gemspec +1 -0
- data/lib/geo3d.rb +1 -0
- data/lib/geo3d/version.rb +1 -1
- data/lib/matrix.rb +39 -12
- data/lib/plane.rb +95 -0
- data/lib/quaternion.rb +5 -4
- data/lib/vector.rb +8 -0
- data/spec/lib/matrix_spec.rb +227 -0
- data/spec/lib/plane_spec.rb +80 -0
- data/spec/lib/quaternion_spec.rb +113 -0
- data/spec/lib/vector_spec.rb +77 -0
- data/spec/spec_helper.rb +1 -0
- metadata +28 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: d8f3862b698223418bf989a4cce3c0dc45c74aec
|
4
|
+
data.tar.gz: 8df829279ef53a7003215b5aeb18c3a4127af036
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: ef96a2ee15de30cc29f298cac21258a45c764d8895837525b172280973f89bf905ef7ceb5af4240471b5894c890e57aed57856e2c8337aca7472a47411462e66
|
7
|
+
data.tar.gz: 79c5f1a2776f2647d139f7de64f4fcc148a242bfe0bf9e9c0db3ba0357cda31d522114da94adf2cfd20581080028b36577c67bc814296b36c0d8428a93552518
|
data/README.md
CHANGED
@@ -179,23 +179,71 @@ Matrix Decomposition
|
|
179
179
|
|
180
180
|
A mathematical construct to represent rotations in 3d space.
|
181
181
|
|
182
|
+
Quaternions support all the basic math operations.
|
183
|
+
|
184
|
+
Addition
|
185
|
+
```
|
186
|
+
quat_a + quat_b
|
187
|
+
```
|
188
|
+
Subtraction
|
189
|
+
```
|
190
|
+
quat_a - quat_b
|
191
|
+
```
|
182
192
|
Quaternion Multiplication
|
183
193
|
```
|
184
194
|
quat_a * quat_b
|
185
195
|
```
|
196
|
+
Scalar Multiplication
|
197
|
+
```
|
198
|
+
quat * scalar
|
199
|
+
```
|
200
|
+
Scalar Division
|
201
|
+
```
|
202
|
+
quat / scalar
|
203
|
+
```
|
186
204
|
Getting axis and angle
|
187
205
|
```
|
188
206
|
quat.axis
|
189
|
-
quat.angle
|
207
|
+
quat.angle #returns angle in radians
|
208
|
+
quat.angle_degrees #returns angle in degrees
|
190
209
|
```
|
191
210
|
Converting to a matrix
|
192
211
|
```
|
193
212
|
quat.to_matrix
|
194
213
|
```
|
214
|
+
|
215
|
+
Additional quaternion operations
|
216
|
+
Magnitude
|
217
|
+
```
|
218
|
+
quat.length
|
219
|
+
```
|
220
|
+
Squared Magnitude
|
221
|
+
```
|
222
|
+
quat.length_squared
|
223
|
+
```
|
224
|
+
Normalize
|
225
|
+
```
|
226
|
+
quat.normalize #returns a normalized version of the quaternion
|
227
|
+
quat.normalize! #normalizes the quaternion in place
|
228
|
+
```
|
229
|
+
Inverse
|
230
|
+
```
|
231
|
+
quat.inverse #returns inverse of quaternion
|
232
|
+
```
|
233
|
+
Conjugate
|
234
|
+
```
|
235
|
+
quat.conjugate
|
236
|
+
```
|
237
|
+
Dot product
|
238
|
+
```
|
239
|
+
quat.dot
|
240
|
+
```
|
241
|
+
|
195
242
|
Constructors
|
196
243
|
```
|
197
244
|
Geo3d::Quaternion.from_axis rotation_axis, radians #returns a quaternion from an axis and angle
|
198
245
|
Geo3d::Quaternion.from_matrix m #returns a quaternion from a rotation matrix
|
246
|
+
Geo3d::Quaternion.identity #returns the identity quaternion
|
199
247
|
|
200
248
|
```
|
201
249
|
|
data/Rakefile
CHANGED
data/geo3d.gemspec
CHANGED
data/lib/geo3d.rb
CHANGED
data/lib/geo3d/version.rb
CHANGED
data/lib/matrix.rb
CHANGED
@@ -54,6 +54,32 @@ module Geo3d
|
|
54
54
|
send (%w{_11 _12 _13 _14 _21 _22 _23 _24 _31 _32 _33 _34 _41 _42 _43 _44}[4*x + y] + '=').to_sym, v
|
55
55
|
end
|
56
56
|
|
57
|
+
def row i
|
58
|
+
if i >= 0 && i <= 3
|
59
|
+
Vector.new self[0, i], self[1, i], self[2, i], self[3, i]
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
def col i
|
64
|
+
if i >= 0 && i <= 3
|
65
|
+
Vector.new self[i, 0], self[i, 1], self [i, 2], self[i, 3]
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
def set_row i, v
|
70
|
+
self[0, i] = v.x
|
71
|
+
self[1, i] = v.y
|
72
|
+
self[2, i] = v.z
|
73
|
+
self[3, i] = v.w
|
74
|
+
end
|
75
|
+
|
76
|
+
def set_col i, v
|
77
|
+
self[i, 0] = v.x
|
78
|
+
self[i, 1] = v.y
|
79
|
+
self[i, 2] = v.z
|
80
|
+
self[i, 3] = v.w
|
81
|
+
end
|
82
|
+
|
57
83
|
def == m
|
58
84
|
a = to_a
|
59
85
|
b = m.to_a
|
@@ -155,10 +181,10 @@ module Geo3d
|
|
155
181
|
elsif Vector == v.class
|
156
182
|
vec = v
|
157
183
|
transformed_vector = Vector.new
|
158
|
-
transformed_vector.x = _11 * vec.x + _21 * vec.y + _31 * vec.z + _41
|
159
|
-
transformed_vector.y = _12 * vec.x + _22 * vec.y + _32 * vec.z + _42
|
160
|
-
transformed_vector.z = _13 * vec.x + _23 * vec.y + _33 * vec.z + _43
|
161
|
-
transformed_vector.w = _14 * vec.x + _24 * vec.y + _34 * vec.z + _44
|
184
|
+
transformed_vector.x = _11 * vec.x + _21 * vec.y + _31 * vec.z + _41 * vec.w
|
185
|
+
transformed_vector.y = _12 * vec.x + _22 * vec.y + _32 * vec.z + _42 * vec.w
|
186
|
+
transformed_vector.z = _13 * vec.x + _23 * vec.y + _33 * vec.z + _43 * vec.w
|
187
|
+
transformed_vector.w = _14 * vec.x + _24 * vec.y + _34 * vec.z + _44 * vec.w
|
162
188
|
return transformed_vector
|
163
189
|
else
|
164
190
|
scalar = v
|
@@ -212,12 +238,7 @@ module Geo3d
|
|
212
238
|
end
|
213
239
|
|
214
240
|
def transform_coord vec
|
215
|
-
|
216
|
-
transformed_vector = self * vec
|
217
|
-
transformed_vector.x /= norm
|
218
|
-
transformed_vector.y /= norm
|
219
|
-
transformed_vector.z /= norm
|
220
|
-
transformed_vector
|
241
|
+
self * Vector.new( vec.x, vec.y, vec.z, 1.0 )
|
221
242
|
end
|
222
243
|
|
223
244
|
def transform vec
|
@@ -348,9 +369,9 @@ module Geo3d
|
|
348
369
|
|
349
370
|
|
350
371
|
# calculate matrix inverse
|
351
|
-
|
372
|
+
inverse_det = 1.0/det
|
352
373
|
for j in 0..15
|
353
|
-
dst[j] *=
|
374
|
+
dst[j] *= inverse_det
|
354
375
|
end
|
355
376
|
|
356
377
|
inverted_matrix = self.class.new *dst
|
@@ -402,6 +423,10 @@ module Geo3d
|
|
402
423
|
puts "_44: #{_44}\n"
|
403
424
|
end
|
404
425
|
|
426
|
+
def to_s
|
427
|
+
(0..3).to_a.map{ |i| row(i).to_s}.join "\n"
|
428
|
+
end
|
429
|
+
|
405
430
|
def self.perspective_fov_rh fovy, aspect, zn, zf
|
406
431
|
fovy = fovy.to_f
|
407
432
|
aspect = aspect.to_f
|
@@ -533,6 +558,7 @@ module Geo3d
|
|
533
558
|
end
|
534
559
|
|
535
560
|
def self.reflection reflection_plane
|
561
|
+
reflection_plane = Geo3d::Vector.new *reflection_plane.to_a
|
536
562
|
reflection_matrix = self.new
|
537
563
|
|
538
564
|
plane_magnitude = Vector.new(reflection_plane.x, reflection_plane.y, reflection_plane.z, 0).length
|
@@ -566,6 +592,7 @@ module Geo3d
|
|
566
592
|
end
|
567
593
|
|
568
594
|
def self.shadow light_position, plane
|
595
|
+
plane = Geo3d::Vector.new *plane.to_a
|
569
596
|
norm = plane.x * plane.x + plane.y * plane.y + plane.z * plane.z
|
570
597
|
normalized_plane = plane / norm
|
571
598
|
dot = normalized_plane.dot(light_position)
|
data/lib/plane.rb
ADDED
@@ -0,0 +1,95 @@
|
|
1
|
+
module Geo3d
|
2
|
+
class Plane
|
3
|
+
attr_accessor :a, :b, :c, :d
|
4
|
+
alias :x :a
|
5
|
+
alias :y :b
|
6
|
+
alias :z :c
|
7
|
+
alias :w :d
|
8
|
+
|
9
|
+
def initialize *args
|
10
|
+
@a = 0.0
|
11
|
+
@b = 0.0
|
12
|
+
@c = 0.0
|
13
|
+
@d = 0.0
|
14
|
+
@a = args[0].to_f if args.size > 0
|
15
|
+
@b = args[1].to_f if args.size > 1
|
16
|
+
@c = args[2].to_f if args.size > 2
|
17
|
+
@d = args[3].to_f if args.size > 3
|
18
|
+
end
|
19
|
+
|
20
|
+
def self.from_points pv1, pv2, pv3
|
21
|
+
edge1 = pv2 - pv1
|
22
|
+
edge2 = pv3 - pv1
|
23
|
+
from_point_and_normal pv1, edge1.cross(edge2).normalize
|
24
|
+
end
|
25
|
+
|
26
|
+
def self.from_point_and_normal point, normal
|
27
|
+
point.w = 0
|
28
|
+
self.new normal.x, normal.y, normal.z, -point.dot(normal)
|
29
|
+
end
|
30
|
+
|
31
|
+
def to_a
|
32
|
+
[a,b,c,d]
|
33
|
+
end
|
34
|
+
|
35
|
+
def == p
|
36
|
+
Geo3d::Utils.float_cmp(a, p.a) && Geo3d::Utils.float_cmp(b, p.b) && Geo3d::Utils.float_cmp(c, p.c) && Geo3d::Utils.float_cmp(d, p.d)
|
37
|
+
end
|
38
|
+
|
39
|
+
def != vec
|
40
|
+
!(self == vec)
|
41
|
+
end
|
42
|
+
|
43
|
+
def dot v
|
44
|
+
a * v.x + b * v.y + c * v.z + d * v.w
|
45
|
+
end
|
46
|
+
|
47
|
+
def normalize!
|
48
|
+
norm = Math.sqrt(a*a + b*b + c*c)
|
49
|
+
if norm.zero?
|
50
|
+
@a = 0
|
51
|
+
@b = 0
|
52
|
+
@c = 0
|
53
|
+
@d = 0
|
54
|
+
else
|
55
|
+
@a /= norm
|
56
|
+
@b /= norm
|
57
|
+
@c /= norm
|
58
|
+
@d /= norm
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
def normalize
|
63
|
+
p = self.class.new a, b, c, d
|
64
|
+
p.normalize!
|
65
|
+
p
|
66
|
+
end
|
67
|
+
|
68
|
+
def normal
|
69
|
+
Vector.new a, b, c
|
70
|
+
end
|
71
|
+
|
72
|
+
def line_intersection line_start, line_end
|
73
|
+
direction = line_end - line_start
|
74
|
+
|
75
|
+
normal_dot_direction = normal.dot direction
|
76
|
+
|
77
|
+
if (normal_dot_direction.zero?)
|
78
|
+
nil
|
79
|
+
else
|
80
|
+
temp = (d + normal.dot(line_start)) / normal_dot_direction
|
81
|
+
line_start - direction * temp
|
82
|
+
end
|
83
|
+
end
|
84
|
+
|
85
|
+
def transform matrix, use_inverse_transpose = true
|
86
|
+
matrix = matrix.inverse.transpose if use_inverse_transpose
|
87
|
+
p = self.class.new
|
88
|
+
p.a = dot matrix.row(0)
|
89
|
+
p.b = dot matrix.row(1)
|
90
|
+
p.c = dot matrix.row(2)
|
91
|
+
p.d = dot matrix.row(3)
|
92
|
+
p
|
93
|
+
end
|
94
|
+
end
|
95
|
+
end
|
data/lib/quaternion.rb
CHANGED
@@ -46,9 +46,7 @@ module Geo3d
|
|
46
46
|
end
|
47
47
|
|
48
48
|
def self.from_axis rotation_axis, radians = 0
|
49
|
-
normalized_rotation_axis = rotation_axis.normalize
|
50
|
-
#const float radians = GeoConvertToRadians( degrees );
|
51
|
-
|
49
|
+
normalized_rotation_axis = rotation_axis.zero_w.normalize
|
52
50
|
q = self.new
|
53
51
|
q.x = Math.sin(radians / 2.0) * normalized_rotation_axis.x
|
54
52
|
q.y = Math.sin(radians / 2.0) * normalized_rotation_axis.y
|
@@ -70,6 +68,8 @@ module Geo3d
|
|
70
68
|
pout.y = (pm._31 - pm._13) / (2.0 * Math.sqrt(trace))
|
71
69
|
pout.z = (pm._12- pm._21) / (2.0 * Math.sqrt(trace))
|
72
70
|
pout.w = Math.sqrt(trace) / 2.0
|
71
|
+
puts "a and pout is #{pout.inspect}"
|
72
|
+
|
73
73
|
return pout
|
74
74
|
end
|
75
75
|
maxi = 0
|
@@ -104,6 +104,7 @@ module Geo3d
|
|
104
104
|
pout.z = 0.25 * s
|
105
105
|
pout.w = (pm._12 - pm._21) / s
|
106
106
|
end
|
107
|
+
puts "b"
|
107
108
|
pout
|
108
109
|
end
|
109
110
|
|
@@ -134,7 +135,7 @@ module Geo3d
|
|
134
135
|
end
|
135
136
|
|
136
137
|
def to_matrix
|
137
|
-
v =
|
138
|
+
v = normalize
|
138
139
|
matrix = Matrix.identity
|
139
140
|
matrix._11 = 1.0 - 2.0 * (v.y * v.y + v.z * v.z)
|
140
141
|
matrix._12 = 2.0 * (v.x * v.y + v.z * v.w)
|
data/lib/vector.rb
CHANGED
@@ -0,0 +1,227 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Geo3d::Matrix do
|
4
|
+
def random_matrix
|
5
|
+
r = Geo3d::Matrix.new
|
6
|
+
for i in 0..3
|
7
|
+
for j in 0..3
|
8
|
+
r[i, j] = rand 10000
|
9
|
+
end
|
10
|
+
end
|
11
|
+
r
|
12
|
+
end
|
13
|
+
|
14
|
+
def random_vector
|
15
|
+
v = Geo3d::Vector.new
|
16
|
+
v.x = rand 10000
|
17
|
+
v.y = rand 10000
|
18
|
+
v.z = rand 10000
|
19
|
+
v.w = rand 10000
|
20
|
+
v
|
21
|
+
end
|
22
|
+
|
23
|
+
|
24
|
+
it "should default all values to zero" do
|
25
|
+
Geo3d::Matrix.new.to_a.select(&:zero?).size.should == 16
|
26
|
+
end
|
27
|
+
|
28
|
+
it "should be able to extract translation component" do
|
29
|
+
|
30
|
+
end
|
31
|
+
|
32
|
+
it "should be able to extract scaling component" do
|
33
|
+
|
34
|
+
end
|
35
|
+
|
36
|
+
it "should be able to extract rotation component" do
|
37
|
+
|
38
|
+
end
|
39
|
+
|
40
|
+
it "should be invertible" do
|
41
|
+
100.times do
|
42
|
+
r = random_matrix
|
43
|
+
(r * r.inverse).identity?.should == true
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
it "should return the determinant" do
|
48
|
+
[{:matrix => [0.321046, 0.000000, 0.000000, 0.000000, 0.000000, 0.642093, 0.000000, 0.000000, 0.000000, 0.000000, -1.000095, -1.000000, 0.000000, 0.000000, -2.000190, 0.000000], :expected => -0.412322},
|
49
|
+
{:matrix => [1.000000, 0.000000, 0.000000, 0.000000, 0.000000, -1.000000, 0.000000, 0.000000, 0.000000, 0.000000, 1.000000, 0.000000, 0.000000, -2.000000, 0.000000, 1.000000], :expected => -1},
|
50
|
+
{:matrix => [-0.392804, -0.878379, -0.272314, 0.000000, 0.000000, 0.296115, -0.955152, 0.000000, 0.919622, -0.375187, -0.116315, 0.000000, -2.366064, 1.411711, 2.531564, 1.000000], :expected => 1}].each do |data|
|
51
|
+
data[:matrix].size.should == 16
|
52
|
+
Geo3d::Utils.float_cmp( Geo3d::Matrix.new(*data[:matrix]).determinant, data[:expected] ).should == true
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
it "should be transposable" do
|
57
|
+
|
58
|
+
end
|
59
|
+
|
60
|
+
it "should have an identity constructor" do
|
61
|
+
identity = Geo3d::Matrix.identity
|
62
|
+
identity.identity?.should == true
|
63
|
+
end
|
64
|
+
|
65
|
+
it "should have a right handed perspective projection constructor" do
|
66
|
+
[{:fovy => 2, :aspect => 2, :zn => 2, :zf => 21000, :expected => [0.321046, 0.000000, 0.000000, 0.000000, 0.000000, 0.642093, 0.000000, 0.000000, 0.000000, 0.000000, -1.000095, -1.000000, 0.000000, 0.000000, -2.000190, 0.000000]}].each do |data|
|
67
|
+
matrix = Geo3d::Matrix.perspective_fov_rh data[:fovy], data[:aspect], data[:zn], data[:zf]
|
68
|
+
data[:expected].size.should == 16
|
69
|
+
expected = Geo3d::Matrix.new *data[:expected]
|
70
|
+
matrix.should == expected
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
|
75
|
+
it "should have a left handed perspective projection constructor" do
|
76
|
+
[{:fovy => 2, :aspect => 2, :zn => 2, :zf => 21000, :expected => [0.321046, 0.000000, 0.000000, 0.000000, 0.000000, 0.642093, 0.000000, 0.000000, 0.000000, 0.000000, 1.000095, 1.000000, 0.000000, 0.000000, -2.000190, 0.000000]}].each do |data|
|
77
|
+
matrix = Geo3d::Matrix.perspective_fov_lh data[:fovy], data[:aspect], data[:zn], data[:zf]
|
78
|
+
data[:expected].size.should == 16
|
79
|
+
expected = Geo3d::Matrix.new *data[:expected]
|
80
|
+
matrix.should == expected
|
81
|
+
end
|
82
|
+
end
|
83
|
+
|
84
|
+
|
85
|
+
it "should have a right handed orthographic projection constructor" do
|
86
|
+
[{:l => -100, :r => 100, :b => -200, :t => 200, :zn => 1, :zf => 2000, :expected => [0.010000, 0.000000, 0.000000, 0.000000, 0.000000, 0.005000, 0.000000, 0.000000, 0.000000, 0.000000, -0.000500, 0.000000, -0.000000, -0.000000, -0.000500, 1.000000]}].each do |data|
|
87
|
+
matrix = Geo3d::Matrix.ortho_off_center_rh data[:l], data[:r], data[:b], data[:t], data[:zn], data[:zf]
|
88
|
+
data[:expected].size.should == 16
|
89
|
+
expected = Geo3d::Matrix.new *data[:expected]
|
90
|
+
matrix.should == expected
|
91
|
+
end
|
92
|
+
end
|
93
|
+
|
94
|
+
|
95
|
+
it "should have a left handed orthographic projection constructor" do
|
96
|
+
[{:l => -100, :r => 100, :b => -200, :t => 200, :zn => 1, :zf => 2000, :expected => [0.010000, 0.000000, 0.000000, 0.000000, 0.000000, 0.005000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000500, 0.000000, -0.000000, -0.000000, -0.000500, 1.000000]}].each do |data|
|
97
|
+
matrix = Geo3d::Matrix.ortho_off_center_lh data[:l], data[:r], data[:b], data[:t], data[:zn], data[:zf]
|
98
|
+
data[:expected].size.should == 16
|
99
|
+
expected = Geo3d::Matrix.new *data[:expected]
|
100
|
+
matrix.should == expected
|
101
|
+
end
|
102
|
+
end
|
103
|
+
|
104
|
+
|
105
|
+
it "should have a right handed view constructor" do
|
106
|
+
[{:eye => [1, 2, 3], :focus => [200, 700, 88], :up => [0, 1, 0], :expected => [-0.392804, -0.878379, -0.272314, 0.000000, 0.000000, 0.296115, -0.955152, 0.000000, 0.919622, -0.375187, -0.116315, 0.000000, -2.366064, 1.411711, 2.531564, 1.000000]}].each do |data|
|
107
|
+
matrix = Geo3d::Matrix.look_at_rh Geo3d::Vector.new(*data[:eye]), Geo3d::Vector.new(*data[:focus]), Geo3d::Vector.new(*data[:up])
|
108
|
+
data[:expected].size.should == 16
|
109
|
+
expected = Geo3d::Matrix.new *data[:expected]
|
110
|
+
matrix.should == expected
|
111
|
+
end
|
112
|
+
end
|
113
|
+
|
114
|
+
|
115
|
+
it "should have a left handed view constructor" do
|
116
|
+
[{:eye => [1, 2, 3], :focus => [200, 700, 88], :up => [0, 1, 0], :expected => [0.392804, -0.878379, 0.272314, 0.000000, 0.000000, 0.296115, 0.955152, 0.000000, -0.919622, -0.375187, 0.116315, 0.000000, 2.366064, 1.411711, -2.531564, 1.000000]}].each do |data|
|
117
|
+
matrix = Geo3d::Matrix.look_at_lh Geo3d::Vector.new(*data[:eye]), Geo3d::Vector.new(*data[:focus]), Geo3d::Vector.new(*data[:up])
|
118
|
+
data[:expected].size.should == 16
|
119
|
+
expected = Geo3d::Matrix.new *data[:expected]
|
120
|
+
matrix.should == expected
|
121
|
+
end
|
122
|
+
end
|
123
|
+
|
124
|
+
it "should have a translation constructor" do
|
125
|
+
10.times do
|
126
|
+
random_translation = random_vector
|
127
|
+
matrix = Geo3d::Matrix.translation random_translation.x, random_translation.y, random_translation.z
|
128
|
+
10.times do
|
129
|
+
random_vec = random_vector.one_w
|
130
|
+
Geo3d::Utils.float_cmp((matrix * random_vec).x, random_vec.x + random_translation.x).should == true
|
131
|
+
Geo3d::Utils.float_cmp((matrix * random_vec).y, random_vec.y + random_translation.y).should == true
|
132
|
+
Geo3d::Utils.float_cmp((matrix * random_vec).z, random_vec.z + random_translation.z).should == true
|
133
|
+
Geo3d::Utils.float_cmp((matrix * random_vec).w, 1).should == true
|
134
|
+
end
|
135
|
+
end
|
136
|
+
end
|
137
|
+
|
138
|
+
it "should have a scaling constructor" do
|
139
|
+
10.times do
|
140
|
+
random_scaling = random_vector
|
141
|
+
matrix = Geo3d::Matrix.scaling random_scaling.x, random_scaling.y, random_scaling.z
|
142
|
+
10.times do
|
143
|
+
random_vec = random_vector.one_w
|
144
|
+
Geo3d::Utils.float_cmp((matrix * random_vec).x, random_vec.x * random_scaling.x).should == true
|
145
|
+
Geo3d::Utils.float_cmp((matrix * random_vec).y, random_vec.y * random_scaling.y).should == true
|
146
|
+
Geo3d::Utils.float_cmp((matrix * random_vec).z, random_vec.z * random_scaling.z).should == true
|
147
|
+
Geo3d::Utils.float_cmp((matrix * random_vec).w, 1).should == true
|
148
|
+
end
|
149
|
+
end
|
150
|
+
end
|
151
|
+
|
152
|
+
|
153
|
+
it "should have an x-axis rotation constructor" do
|
154
|
+
[{:angle => 1, :expected => [1.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.540302, 0.841471, 0.000000, 0.000000, -0.841471, 0.540302, 0.000000, 0.000000, 0.000000, 0.000000, 1.000000]},
|
155
|
+
{:angle => 3.2, :expected => [1.000000, 0.000000, 0.000000, 0.000000, 0.000000, -0.998295, -0.058374, 0.000000, 0.000000, 0.058374, -0.998295, 0.000000, 0.000000, 0.000000, 0.000000, 1.000000]}].each do |data|
|
156
|
+
matrix = Geo3d::Matrix.rotation_x data[:angle]
|
157
|
+
data[:expected].size.should == 16
|
158
|
+
expected = Geo3d::Matrix.new *data[:expected]
|
159
|
+
matrix.should == expected
|
160
|
+
end
|
161
|
+
end
|
162
|
+
|
163
|
+
it "should have an y-axis rotation constructor" do
|
164
|
+
[{:angle => 1, :expected => [0.540302, 0.000000, -0.841471, 0.000000, 0.000000, 1.000000, 0.000000, 0.000000, 0.841471, 0.000000, 0.540302, 0.000000, 0.000000, 0.000000, 0.000000, 1.000000]},
|
165
|
+
{:angle => 3.2, :expected => [-0.998295, 0.000000, 0.058374, 0.000000, 0.000000, 1.000000, 0.000000, 0.000000, -0.058374, 0.000000, -0.998295, 0.000000, 0.000000, 0.000000, 0.000000, 1.000000]}].each do |data|
|
166
|
+
matrix = Geo3d::Matrix.rotation_y data[:angle]
|
167
|
+
data[:expected].size.should == 16
|
168
|
+
expected = Geo3d::Matrix.new *data[:expected]
|
169
|
+
matrix.should == expected
|
170
|
+
end
|
171
|
+
end
|
172
|
+
|
173
|
+
it "should have a z-axis rotation constructor" do
|
174
|
+
[{:angle => 1, :expected => [0.540302, 0.841471, 0.000000, 0.000000, -0.841471, 0.540302, 0.000000, 0.000000, 0.000000, 0.000000, 1.000000, 0.000000, 0.000000, 0.000000, 0.000000, 1.000000]},
|
175
|
+
{:angle => 3.2, :expected => [-0.998295, -0.058374, 0.000000, 0.000000, 0.058374, -0.998295, 0.000000, 0.000000, 0.000000, 0.000000, 1.000000, 0.000000, 0.000000, 0.000000, 0.000000, 1.000000]}].each do |data|
|
176
|
+
matrix = Geo3d::Matrix.rotation_z data[:angle]
|
177
|
+
data[:expected].size.should == 16
|
178
|
+
expected = Geo3d::Matrix.new *data[:expected]
|
179
|
+
matrix.should == expected
|
180
|
+
end
|
181
|
+
end
|
182
|
+
|
183
|
+
it "should have an arbitrary axis rotation constructor" do
|
184
|
+
[{:axis => [1, 1, 0], :angle => 88.7, :expected => [0.870782, 0.129218, -0.474385, 0.000000, 0.129218, 0.870782, 0.474385, 0.000000, 0.474385, -0.474385, 0.741564, 0.000000, 0.000000, 0.000000, 0.000000, 1.000000]}].each do |data|
|
185
|
+
matrix = Geo3d::Matrix.rotation Geo3d::Vector.new(*data[:axis]), data[:angle]
|
186
|
+
data[:expected].size.should == 16
|
187
|
+
expected = Geo3d::Matrix.new *data[:expected]
|
188
|
+
matrix.should == expected
|
189
|
+
end
|
190
|
+
end
|
191
|
+
|
192
|
+
it "should have a reflection constructor" do
|
193
|
+
[{:plane => [0, 1, 0, 0], :expected => [1.000000, 0.000000, 0.000000, 0.000000, 0.000000, -1.000000, 0.000000, 0.000000, 0.000000, 0.000000, 1.000000, 0.000000, 0.000000, 0.000000, 0.000000, 1.000000]},
|
194
|
+
{:plane => [0, 1, 0, 1], :expected => [1.000000, 0.000000, 0.000000, 0.000000, 0.000000, -1.000000, 0.000000, 0.000000, 0.000000, 0.000000, 1.000000, 0.000000, 0.000000, -2.000000, 0.000000, 1.000000]}].each do |data|
|
195
|
+
matrix = Geo3d::Matrix.reflection Geo3d::Plane.new(*data[:plane])
|
196
|
+
data[:expected].size.should == 16
|
197
|
+
expected = Geo3d::Matrix.new *data[:expected]
|
198
|
+
matrix.should == expected
|
199
|
+
end
|
200
|
+
end
|
201
|
+
|
202
|
+
it "should have a shadow constructor" do
|
203
|
+
[{:plane => [0, 1, 0, 1], :light_pos => [0, 700, 0, 1], :expected => [701.000000, 0.000000, 0.000000, 0.000000, 0.000000, 1.000000, 0.000000, -1.000000, 0.000000, 0.000000, 701.000000, 0.000000, 0.000000, -700.000000, 0.000000, 700.000000]}].each do |data|
|
204
|
+
matrix = Geo3d::Matrix.shadow Geo3d::Vector.new(*data[:light_pos]), Geo3d::Plane.new(*data[:plane])
|
205
|
+
data[:expected].size.should == 16
|
206
|
+
expected = Geo3d::Matrix.new *data[:expected]
|
207
|
+
matrix.should == expected
|
208
|
+
end
|
209
|
+
end
|
210
|
+
|
211
|
+
it "multiplying a matrix by the identity matrix should result in the same matrix" do
|
212
|
+
identity = Geo3d::Matrix.identity
|
213
|
+
10.times do
|
214
|
+
r = random_matrix
|
215
|
+
(r * identity).should == r
|
216
|
+
(identity * r).should == r
|
217
|
+
end
|
218
|
+
end
|
219
|
+
|
220
|
+
it "should transform vectors" do
|
221
|
+
|
222
|
+
end
|
223
|
+
|
224
|
+
it "should multiply with other matrices" do
|
225
|
+
|
226
|
+
end
|
227
|
+
end
|
@@ -0,0 +1,80 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Geo3d::Plane do
|
4
|
+
it "should default all values to zero" do
|
5
|
+
p = Geo3d::Plane.new
|
6
|
+
p.a.zero?.should == true
|
7
|
+
p.b.zero?.should == true
|
8
|
+
p.c.zero?.should == true
|
9
|
+
p.d.zero?.should == true
|
10
|
+
end
|
11
|
+
|
12
|
+
it "should construct from a point and a normal" do
|
13
|
+
[{:point => [0, 0, 0], :normal => [0, 1, 0], :expected => [0, 1, 0, 0]},
|
14
|
+
{:point => [1, 2, 3], :normal => [1, 1, 1], :expected => [1, 1, 1, -6]},
|
15
|
+
{:point => [221, 772, 33], :normal => [2, 0, 1], :expected => [2, 0, 1, -475]},
|
16
|
+
{:point => [999, 888, 777], :normal => [-1, 3, 0], :expected => [-1, 3, 0, -1665]}].each do |data|
|
17
|
+
plane = Geo3d::Plane.from_point_and_normal Geo3d::Vector.new(*data[:point]), Geo3d::Vector.new(*data[:normal])
|
18
|
+
expected = Geo3d::Plane.new *data[:expected]
|
19
|
+
plane.should == expected
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
it "should construct from points" do
|
24
|
+
[{:a => [1, 1, 1], :b => [2, 2, 2], :c => [3, 3, 3], :expected => [0, 0, 0, 0]},
|
25
|
+
{:a => [-1.5, 1.5, 3.0, 0], :b => [1.5, 1.5, 3.0, 0], :c => [-1.5, -1.5, 3.0, 0], :expected => [0, 0, -1, 3]},
|
26
|
+
{:a => [10, 1, 33], :b => [1, 11, 3], :c => [-1, -1, 3], :expected => [-0.930808, 0.155135, 0.330954, -1.768534]}].each do |data|
|
27
|
+
plane = Geo3d::Plane.from_points Geo3d::Vector.new(*data[:a]), Geo3d::Vector.new(*data[:b]), Geo3d::Vector.new(*data[:c])
|
28
|
+
expected = Geo3d::Plane.new *data[:expected]
|
29
|
+
plane.should == expected
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
it "should support dot products with vectors" do
|
34
|
+
[{:plane => [1, 1, 1, 1], :vector => [2, 2, 2, 2], :expected => 8},
|
35
|
+
{:plane => [0, 1, 0, -99], :vector => [0, -42, 2, 52], :expected => -5190},
|
36
|
+
{:plane => [91, -2731, 1, 123], :vector => [2, 7, -9, 2], :expected => -18698},
|
37
|
+
].each do |data|
|
38
|
+
plane = Geo3d::Plane.new *data[:plane]
|
39
|
+
vector = Geo3d::Vector.new *data[:vector]
|
40
|
+
Geo3d::Utils.float_cmp(plane.dot(vector), data[:expected]).should == true
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
it "should be normalizable" do
|
45
|
+
[{:plane => [0, 0, -1, 3], :expected => [0, 0, -1, 3]},
|
46
|
+
{:plane => [11, 11, -7, 3], :expected => [0.644831, 0.644831, -0.410347, 0.175863]},
|
47
|
+
{:plane => [-56, 23, 923, 9], :expected => [-0.060542, 0.024865, 0.997856, 0.009730]}].each do |data|
|
48
|
+
plane = Geo3d::Plane.new(*data[:plane]).normalize
|
49
|
+
expected = Geo3d::Plane.new *data[:expected]
|
50
|
+
plane.should == expected
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
it "should be able to detect line intersections" do
|
55
|
+
[{:plane => [0,0,-1,3], :line_start => [1,1,1,0], :line_end => [2,2,2,0], :expected => [3,3,3,0]},
|
56
|
+
{:plane => [0,0,-1,3], :line_start => [1,1,1,1], :line_end => [2,2,2,1], :expected => [3,3,3,1]},
|
57
|
+
{:plane => [0,1,0,-30], :line_start => [1,0,0,0], :line_end => [2,0,0,0], :expected => nil},
|
58
|
+
{:plane => [0,1,0,-30], :line_start => [1,1,0,0], :line_end => [2,0,0,0], :expected => [-28,30,0,0]},
|
59
|
+
{:plane => [0,1,0,-30], :line_start => [1,1,0,1], :line_end => [2,0,0,1], :expected => [-28,30,0,1]}].each do |data|
|
60
|
+
plane = Geo3d::Plane.new *data[:plane]
|
61
|
+
line_start = Geo3d::Vector.new *data[:line_start]
|
62
|
+
line_end = Geo3d::Vector.new *data[:line_end]
|
63
|
+
if data[:expected]
|
64
|
+
expected = Geo3d::Vector.new *data[:expected]
|
65
|
+
else
|
66
|
+
expected = nil
|
67
|
+
end
|
68
|
+
plane.line_intersection(line_start, line_end).should == expected
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
it "should be transformable" do
|
73
|
+
test_transform = ->(matrix, plane,expected) do
|
74
|
+
plane.transform(matrix).should == expected
|
75
|
+
end
|
76
|
+
test_transform.call Geo3d::Matrix.translation(0,5,0), Geo3d::Plane.new(0,1,0,0), Geo3d::Plane.new(0,1,0,-5)
|
77
|
+
test_transform.call Geo3d::Matrix.translation(0,5,0), Geo3d::Plane.new(1,1,1,1), Geo3d::Plane.new(1,1,1,-4)
|
78
|
+
test_transform.call Geo3d::Matrix.rotation_x(1), Geo3d::Plane.new(1,1,1,1), Geo3d::Plane.new(1.000000, -0.301169, 1.381773, 1.000000)
|
79
|
+
end
|
80
|
+
end
|
@@ -0,0 +1,113 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Geo3d::Quaternion do
|
4
|
+
it "should default all values to zero" do
|
5
|
+
q = Geo3d::Quaternion.new
|
6
|
+
q.x.zero?.should == true
|
7
|
+
q.y.zero?.should == true
|
8
|
+
q.z.zero?.should == true
|
9
|
+
q.w.zero?.should == true
|
10
|
+
end
|
11
|
+
|
12
|
+
it "should be constructable from an axis and angle" do
|
13
|
+
[{:axis => [0, 1, 0], :angle => 1, :expected => [0.000000, 0.479426, 0.000000, 0.877583]},
|
14
|
+
{:axis => [0, -1, 0], :angle => 1, :expected => [0.000000, -0.479426, 0.000000, 0.877583]},
|
15
|
+
{:axis => [0, 1, 0], :angle => -1, :expected => [0.000000, -0.479426, 0.000000, 0.877583]},
|
16
|
+
{:axis => [0, 1, 0], :angle => -6, :expected => [-0.000000, -0.141120, -0.000000, -0.989992]},
|
17
|
+
{:axis => [-213, 133, 22, -232], :angle => -3432, :expected => [0.538065, -0.335975, -0.055575, 0.771050]}].each do |data|
|
18
|
+
Geo3d::Quaternion.from_axis(Geo3d::Vector.new(*data[:axis]), data[:angle]).should == Geo3d::Quaternion.new(*data[:expected])
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
it "should be constructable from a rotation matrix" do
|
23
|
+
Geo3d::Quaternion.from_matrix(Geo3d::Matrix.rotation_x 1).should == Geo3d::Quaternion.new(0.479426, 0.000000, -0.000000, 0.877583)
|
24
|
+
Geo3d::Quaternion.from_matrix(Geo3d::Matrix.rotation_y 1).should == Geo3d::Quaternion.new(-0.000000, 0.479426, -0.000000, 0.877583)
|
25
|
+
Geo3d::Quaternion.from_matrix(Geo3d::Matrix.rotation_z 1).should == Geo3d::Quaternion.new(-0.000000, 0.000000, 0.479426, 0.877583)
|
26
|
+
Geo3d::Quaternion.from_matrix(Geo3d::Matrix.rotation_x 3.2).should == Geo3d::Quaternion.new(0.999574, 0.000000, 0.000000, -0.029200)
|
27
|
+
end
|
28
|
+
|
29
|
+
it "should be able to construct as the identity quaternion" do
|
30
|
+
q = Geo3d::Quaternion.identity
|
31
|
+
q.should == Geo3d::Quaternion.new(0, 0, 0, 1)
|
32
|
+
q.identity?.should == true
|
33
|
+
end
|
34
|
+
|
35
|
+
it "should be able to convert to a rotation matrix" do
|
36
|
+
|
37
|
+
end
|
38
|
+
|
39
|
+
it "should return axis of rotation" do
|
40
|
+
for i in 0..10000
|
41
|
+
angle = 0.1 * i + 0.1
|
42
|
+
# puts "angle is #{angle}"
|
43
|
+
#Geo3d::Quaternion.from_matrix(Geo3d::Matrix.rotation_x angle).axis.should == Geo3d::Vector.new(1, 0, 0)
|
44
|
+
#Geo3d::Quaternion.from_matrix(Geo3d::Matrix.rotation_y angle).axis.should == Geo3d::Vector.new(0, 1, 0)
|
45
|
+
#Geo3d::Quaternion.from_matrix(Geo3d::Matrix.rotation_z angle).axis.should == Geo3d::Vector.new(0, 0, 1)
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
it "should return rotation amount as angle" do
|
50
|
+
|
51
|
+
end
|
52
|
+
|
53
|
+
it "should return conjugate" do
|
54
|
+
[{:quaternion => [1, 1, 1, 1], :expected => [-1, -1, -1, 1]}].each do |data|
|
55
|
+
quaternion = Geo3d::Quaternion.new *data[:quaternion]
|
56
|
+
expected = Geo3d::Quaternion.new *data[:expected]
|
57
|
+
quaternion.conjugate.should == expected
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
it "should return inverse" do
|
62
|
+
[{:quaternion => [1, 1, 1, 1], :expected => [-0.250000, -0.250000, -0.250000, 0.250000]},
|
63
|
+
{:quaternion => [-1, -1, -1, -1], :expected => [0.250000, 0.250000, 0.250000, -0.250000]}].each do |data|
|
64
|
+
quaternion = Geo3d::Quaternion.new *data[:quaternion]
|
65
|
+
expected = Geo3d::Quaternion.new *data[:expected]
|
66
|
+
quaternion.inverse.should == expected
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
it "should support dot products with other quaternions" do
|
71
|
+
[{:a => [1, 1, 1, 1], :b => [2, 2, 2, 2], :expected => 8},
|
72
|
+
{:a => [0, 1, 0, -99], :b => [0, -42, 2, 52], :expected => -5190},
|
73
|
+
{:a => [91, -2731, 1, 123], :b => [2, 7, -9, 2], :expected => -18698},
|
74
|
+
].each do |data|
|
75
|
+
a = Geo3d::Quaternion.new *data[:a]
|
76
|
+
b = Geo3d::Quaternion.new *data[:b]
|
77
|
+
Geo3d::Utils.float_cmp(a.dot(b), data[:expected]).should == true
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
81
|
+
it "should return length" do
|
82
|
+
[{:quaternion => [0, 0, -1, 3], :expected => 3.162278},
|
83
|
+
{:quaternion => [11, 11, -7, 3], :expected => 17.320509},
|
84
|
+
{:quaternion => [-56, 23, 923, 9], :expected => 925.027039}].each do |data|
|
85
|
+
quaternion = Geo3d::Quaternion.new *data[:quaternion]
|
86
|
+
expected = data[:expected]
|
87
|
+
Geo3d::Utils.float_cmp(quaternion.length, expected).should == true
|
88
|
+
end
|
89
|
+
end
|
90
|
+
|
91
|
+
it "should return length squared" do
|
92
|
+
[{:quaternion => [0, 0, -1, 3], :expected => 10},
|
93
|
+
{:quaternion => [11, 11, -7, 3], :expected => 300},
|
94
|
+
{:quaternion => [-56, 23, 923, 9], :expected => 855675}].each do |data|
|
95
|
+
quaternion = Geo3d::Quaternion.new *data[:quaternion]
|
96
|
+
expected = data[:expected]
|
97
|
+
Geo3d::Utils.float_cmp(quaternion.length_squared, expected).should == true
|
98
|
+
end
|
99
|
+
end
|
100
|
+
|
101
|
+
it "should be normalizable" do
|
102
|
+
[{:quaternion => [0, 0, -1, 3], :expected => [0, 0, -0.316228, 0.948683]},
|
103
|
+
{:quaternion => [11, 11, -7, 3], :expected => [0.635085, 0.635085, -0.404145, 0.173205]},
|
104
|
+
{:quaternion => [-56, 23, 923, 9], :expected => [-0.060539, 0.024864, 0.997809, 0.009729]}].each do |data|
|
105
|
+
quaternion = Geo3d::Quaternion.new(*data[:quaternion]).normalize
|
106
|
+
expected = Geo3d::Quaternion.new *data[:expected]
|
107
|
+
quaternion.should == expected
|
108
|
+
end
|
109
|
+
end
|
110
|
+
|
111
|
+
#todo: add tests for quaternion interpolation
|
112
|
+
|
113
|
+
end
|
@@ -0,0 +1,77 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Geo3d::Vector do
|
4
|
+
it "should default all values to zero" do
|
5
|
+
v = Geo3d::Vector.new
|
6
|
+
v.x.zero?.should == true
|
7
|
+
v.y.zero?.should == true
|
8
|
+
v.z.zero?.should == true
|
9
|
+
v.w.zero?.should == true
|
10
|
+
end
|
11
|
+
|
12
|
+
it "should support dot products with other vectors" do
|
13
|
+
[{:a => [1, 1, 1, 1], :b => [2, 2, 2, 2], :expected => 8},
|
14
|
+
{:a => [0, 1, 0, -99], :b => [0, -42, 2, 52], :expected => -5190},
|
15
|
+
{:a => [91, -2731, 1, 123], :b => [2, 7, -9, 2], :expected => -18698},
|
16
|
+
].each do |data|
|
17
|
+
a = Geo3d::Vector.new *data[:a]
|
18
|
+
b = Geo3d::Vector.new *data[:b]
|
19
|
+
Geo3d::Utils.float_cmp(a.dot(b), data[:expected]).should == true
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
it "should support cross products with other vectors" do
|
24
|
+
[{:a => [1,0,0,0], :b => [0,1,0,0], :expected => [0,0,1,0] },
|
25
|
+
{:a => [1,0,0,1], :b => [0,1,0,1], :expected => [0,0,1,0] },
|
26
|
+
{:a => [1,1,1,1], :b => [1,1,1,1], :expected => [0,0,0,0] },
|
27
|
+
{:a => [2,99,6,0], :b => [-11,-91,77,0], :expected => [8169.000000, -220.000000, 907.000000, 0.000000] }].each do |data|
|
28
|
+
a = Geo3d::Vector.new *data[:a]
|
29
|
+
b = Geo3d::Vector.new *data[:b]
|
30
|
+
expected = Geo3d::Vector.new *data[:expected]
|
31
|
+
a.cross(b).should == expected
|
32
|
+
b.cross(a).should == -expected
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
it "should return length" do
|
37
|
+
[{:vector => [0, 0, -1, 3], :expected => 3.162278},
|
38
|
+
{:vector => [11, 11, -7, 3], :expected => 17.320509},
|
39
|
+
{:vector => [-56, 23, 923, 9], :expected => 925.027039}].each do |data|
|
40
|
+
vector = Geo3d::Vector.new *data[:vector]
|
41
|
+
expected = data[:expected]
|
42
|
+
Geo3d::Utils.float_cmp(vector.length, expected).should == true
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
it "should return length squared" do
|
47
|
+
[{:vector => [0, 0, -1, 3], :expected => 10},
|
48
|
+
{:vector => [11, 11, -7, 3], :expected => 300},
|
49
|
+
{:vector => [-56, 23, 923, 9], :expected => 855675}].each do |data|
|
50
|
+
vector = Geo3d::Vector.new *data[:vector]
|
51
|
+
expected = data[:expected]
|
52
|
+
Geo3d::Utils.float_cmp(vector.length_squared, expected).should == true
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
it "should be normalizable" do
|
57
|
+
[{:vector => [0, 0, -1, 3], :expected => [0, 0, -0.316228, 0.948683]},
|
58
|
+
{:vector => [11, 11, -7, 3], :expected => [0.635085, 0.635085, -0.404145, 0.173205]},
|
59
|
+
{:vector => [-56, 23, 923, 9], :expected => [-0.060539, 0.024864, 0.997809, 0.009729]}].each do |data|
|
60
|
+
vector = Geo3d::Vector.new(*data[:vector]).normalize
|
61
|
+
expected = Geo3d::Vector.new *data[:expected]
|
62
|
+
vector.should == expected
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
it "should be able to linearly interpolate" do
|
67
|
+
[{:a => [0,0,0,0], :b => [1,1,1,1], :interpolate_fraction => 0.5, :expected => [0.5, 0.5, 0.5, 0.5]},
|
68
|
+
{:a => [23,-3,425,-332], :b => [-22,-45443,886,122], :interpolate_fraction => 0.21234433, :expected => [13.444505, -9651.926758, 522.890747, -235.595673]}].each do |data|
|
69
|
+
a = Geo3d::Vector.new *data[:a]
|
70
|
+
b = Geo3d::Vector.new *data[:b]
|
71
|
+
expected = Geo3d::Vector.new *data[:expected]
|
72
|
+
s = data[:interpolate_fraction]
|
73
|
+
a.lerp( b, s).should == expected
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
end
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
require 'geo3d'
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: geo3d
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.6
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Misha Conway
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2014-01-
|
11
|
+
date: 2014-01-15 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
@@ -38,6 +38,20 @@ dependencies:
|
|
38
38
|
- - '>='
|
39
39
|
- !ruby/object:Gem::Version
|
40
40
|
version: '0'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: rspec
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - '>='
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '0'
|
48
|
+
type: :development
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - '>='
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '0'
|
41
55
|
description: Library for common 3d graphics vector and matrix operations
|
42
56
|
email:
|
43
57
|
- MishaAConway@gmail.com
|
@@ -54,9 +68,15 @@ files:
|
|
54
68
|
- lib/geo3d.rb
|
55
69
|
- lib/geo3d/version.rb
|
56
70
|
- lib/matrix.rb
|
71
|
+
- lib/plane.rb
|
57
72
|
- lib/quaternion.rb
|
58
73
|
- lib/utils.rb
|
59
74
|
- lib/vector.rb
|
75
|
+
- spec/lib/matrix_spec.rb
|
76
|
+
- spec/lib/plane_spec.rb
|
77
|
+
- spec/lib/quaternion_spec.rb
|
78
|
+
- spec/lib/vector_spec.rb
|
79
|
+
- spec/spec_helper.rb
|
60
80
|
homepage: https://github.com/MishaConway/geo3d
|
61
81
|
licenses:
|
62
82
|
- MIT
|
@@ -81,4 +101,9 @@ rubygems_version: 2.1.11
|
|
81
101
|
signing_key:
|
82
102
|
specification_version: 4
|
83
103
|
summary: Library for common 3d graphics vector and matrix operations
|
84
|
-
test_files:
|
104
|
+
test_files:
|
105
|
+
- spec/lib/matrix_spec.rb
|
106
|
+
- spec/lib/plane_spec.rb
|
107
|
+
- spec/lib/quaternion_spec.rb
|
108
|
+
- spec/lib/vector_spec.rb
|
109
|
+
- spec/spec_helper.rb
|