gosling 2.0.1 → 2.1.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 9e6f0f8aedff9ad18db82e215fb3228fd59b79be
4
- data.tar.gz: 13b4208f4759774469e045e5cdfaa6d4697343b0
3
+ metadata.gz: 6522b7771bdf2e2b85a0bf3cbf7f440497d21a91
4
+ data.tar.gz: e0d6aa8c63c4361aeb7dffb1f25c6310bb050730
5
5
  SHA512:
6
- metadata.gz: 143ae71d33d54592e6a45624c96f7083f419970110dd09a4763fd7f20f3d55abb1cc0c28b0226a36c55ad2775a1ac846118f57f05580d693a96b0e7a4bf83c85
7
- data.tar.gz: e542b0689382e52d4a2e430ba9a389cd99f12a37f261fec7468fbad3afc927b2743301cd820da451ac93635bfd3e0ec74e06384aa2f04477f0709adda717ca89
6
+ metadata.gz: a1646556b4e6765ceda7ede9e7c7447cd71eda9af4eb510bd7413e9ba8e9116c4c4177e9b8096c3f2fc81584c0bcb310ab6caf00691d951f1b549b5ffb98eeb8
7
+ data.tar.gz: 719da8786b573ae344338586f2c53ebc0bc41987d392fc0383b218fc4408e94f5f411ffc3a506bf78a9958eae033ae34db14385db3c4702f380e6e312250d753
@@ -15,6 +15,8 @@ module Gosling
15
15
  class Collision
16
16
  include Singleton
17
17
 
18
+ COLLISION_TOLERANCE = 0.000001
19
+
18
20
  ##
19
21
  # Tests two Actors or child classes to see whether they overlap. Actors, having no shape, never overlap. Child
20
22
  # classes use appropriate algorithms based on their shape.
@@ -42,6 +44,50 @@ module Gosling
42
44
  return true
43
45
  end
44
46
 
47
+ ##
48
+ # Tests two Actors or child classes to see whether they overlap. This is similar to #test, but returns additional
49
+ # information.
50
+ #
51
+ # Arguments:
52
+ # - shapeA: an Actor
53
+ # - shapeB: another Actor
54
+ #
55
+ # Returns a hash with the following key/value pairs:
56
+ # - colliding: true if the Actors overlap; false otherwise
57
+ # - overlap: if colliding, the smallest overlapping distance; nil otherwise
58
+ # - penetration: if colliding, a vector representing how far shape B must move to be separated from (or merely
59
+ # touching) shape A; nil otherwise
60
+ #
61
+ def self.get_collision_info(shapeA, shapeB)
62
+ info = { colliding: false, overlap: nil, penetration: nil }
63
+
64
+ return info if shapeA.instance_of?(Actor) || shapeB.instance_of?(Actor)
65
+
66
+ return info if shapeA === shapeB
67
+
68
+ separation_axes = get_separation_axes(shapeA, shapeB)
69
+
70
+ smallest_overlap = nil
71
+ smallest_axis = nil
72
+ separation_axes.each do |axis|
73
+ projectionA = project_onto_axis(shapeA, axis)
74
+ projectionB = project_onto_axis(shapeB, axis)
75
+ overlap = get_overlap(projectionA, projectionB)
76
+ return info unless overlap && overlap > COLLISION_TOLERANCE
77
+ if smallest_overlap.nil? || smallest_overlap > overlap
78
+ smallest_overlap = overlap
79
+ flip = (projectionA[0] + projectionA[1]) * 0.5 > (projectionB[0] + projectionB[1]) * 0.5
80
+ smallest_axis = flip ? -axis : axis
81
+ end
82
+ end
83
+
84
+ info[:colliding] = true
85
+ info[:overlap] = smallest_overlap
86
+ info[:penetration] = smallest_axis.normalize * smallest_overlap
87
+
88
+ return info
89
+ end
90
+
45
91
  ##
46
92
  # Tests a point in space to see whether it is inside the actor's shape or not.
47
93
  #
@@ -147,6 +193,11 @@ module Gosling
147
193
  end
148
194
 
149
195
  def self.projections_overlap?(a, b)
196
+ overlap = get_overlap(a, b)
197
+ overlap != nil && overlap > COLLISION_TOLERANCE
198
+ end
199
+
200
+ def self.get_overlap(a, b)
150
201
  type_check(a, Array)
151
202
  type_check(b, Array)
152
203
  a.each { |x| type_check(x, Numeric) }
@@ -155,7 +206,11 @@ module Gosling
155
206
 
156
207
  a.sort! if a[0] > a[1]
157
208
  b.sort! if b[0] > b[1]
158
- (a[0] <= b[1] && (b[1] <= a[1] || b[0] <= a[0])) || (b[0] <= a[1] && (a[0] <= b[0] || a[1] <= b[1]))
209
+ return b[1] - b[0] if a[0] <= b[0] && b[1] <= a[1]
210
+ return a[1] - a[0] if b[0] <= a[0] && a[1] <= b[1]
211
+ return a[1] - b[0] if a[0] <= b[0] && b[0] <= a[1]
212
+ return b[1] - a[0] if b[0] <= a[0] && a[0] <= b[1]
213
+ nil
159
214
  end
160
215
  end
161
216
  end
@@ -31,16 +31,34 @@ module Gosling
31
31
  end
32
32
 
33
33
  ##
34
- # Sets this polygon's vertices. Requires three or more Snow::Vec3.
34
+ # Sets this polygon's vertices. Requires three or more Snow::Vec2, Vec3, Vec4, or Arrays containing 2 or more
35
+ # numbers.
35
36
  #
36
37
  # Usage:
37
38
  # - polygon.set_vertices([Snow::Vec3[-1, 0, 0], Snow::Vec3[0, -1, 0], Snow::Vec3[1, 1, 0]])
38
39
  #
39
40
  def set_vertices(vertices)
40
41
  type_check(vertices, Array)
41
- raise ArgumentError.new("set_vertices() expects an array of at least three 3D Vectors") unless vertices.length >= 3
42
- vertices.each { |v| type_check(v, Snow::Vec3) }
43
- @vertices.replace(vertices)
42
+ raise ArgumentError.new("set_vertices() expects an array of at least three 2D vectors") unless vertices.length >= 3
43
+ vertices.each do |v|
44
+ types_check(v, Snow::Vec2, Snow::Vec3, Snow::Vec4, Array)
45
+ if v.is_a?(Array)
46
+ raise ArgumentError.new("set_vertices() expects an array of at least three 2D vectors") unless v.length >= 2
47
+ v.each { |n| type_check(n, Numeric) }
48
+ end
49
+ end
50
+
51
+ if @vertices.length < vertices.length
52
+ @vertices.concat(Array.new(vertices.length - @vertices.length) { Snow::Vec3.new })
53
+ elsif @vertices.length > vertices.length
54
+ @vertices.pop(@vertices.length - vertices.length)
55
+ end
56
+
57
+ vertices.each_index do |i|
58
+ @vertices[i].x = vertices[i][0]
59
+ @vertices[i].y = vertices[i][1]
60
+ @vertices[i].z = 0
61
+ end
44
62
  end
45
63
 
46
64
  ##
@@ -9,57 +9,15 @@ module Gosling
9
9
  # SnowMath gem to remain performant.
10
10
  #
11
11
  module Transformable
12
- ##
13
- # Wraps Math.sin to produce rationals instead of floats. Common values are returned quickly from a lookup table.
14
- #
15
- def self.rational_sin(r)
16
- type_check(r, Numeric)
17
-
18
- r = r % (2 * Math::PI)
19
- case r
20
- when 0.0
21
- 0.to_r
22
- when Math::PI / 2
23
- 1.to_r
24
- when Math::PI
25
- 0.to_r
26
- when Math::PI * 3 / 2
27
- -1.to_r
28
- else
29
- Math.sin(r).to_r
30
- end
31
- end
32
-
33
- ##
34
- # Wraps Math.cos to produce rationals instead of floats. Common values are returned quickly from a lookup table.
35
- #
36
- def self.rational_cos(r)
37
- type_check(r, Numeric)
38
-
39
- r = r % (2 * Math::PI)
40
- case r
41
- when 0.0
42
- 1.to_r
43
- when Math::PI / 2
44
- 0.to_r
45
- when Math::PI
46
- -1.to_r
47
- when Math::PI * 3 / 2
48
- 0.to_r
49
- else
50
- Math.cos(r).to_r
51
- end
52
- end
53
-
54
12
  attr_reader :rotation
55
13
 
56
14
  ##
57
15
  # Initializes this Transformable to have no transformations (identity matrix).
58
16
  #
59
17
  def initialize
60
- @center = Snow::Vec3[0.to_r, 0.to_r, 1.to_r]
61
- @scale = Snow::Vec2[1.to_r, 1.to_r]
62
- @translation = Snow::Vec3[0.to_r, 0.to_r, 1.to_r]
18
+ @center = Snow::Vec3[0, 0, 1]
19
+ @scale = Snow::Vec2[1, 1]
20
+ @translation = Snow::Vec3[0, 0, 1]
63
21
  reset
64
22
  end
65
23
 
@@ -68,10 +26,10 @@ module Gosling
68
26
  # matrix.
69
27
  #
70
28
  def reset
71
- self.center = 0.to_r, 0.to_r
72
- self.scale = 1.to_r, 1.to_r
73
- self.rotation = 0.to_r
74
- self.translation = 0.to_r, 0.to_r
29
+ self.center = 0, 0
30
+ self.scale = 1, 1
31
+ self.rotation = 0
32
+ self.translation = 0, 0
75
33
  end
76
34
 
77
35
  ##
@@ -258,6 +216,9 @@ module Gosling
258
216
  #
259
217
  def rotation=(radians)
260
218
  type_check(radians, Numeric)
219
+ if radians.is_a?(Float)
220
+ raise ArgumentError.new("Expected a finite number, but received #{radians.inspect}!") unless radians.finite?
221
+ end
261
222
  @rotation = radians
262
223
  @rotate_is_dirty = @is_dirty = true
263
224
  end
@@ -347,8 +308,8 @@ module Gosling
347
308
  def self.transform_point(mat, v)
348
309
  type_check(mat, Snow::Mat3)
349
310
  type_check(v, Snow::Vec3)
350
- result = mat * Snow::Vec3[v[0], v[1], 1.to_r]
351
- result[2] = 0.to_r
311
+ result = mat * Snow::Vec3[v[0], v[1], 1]
312
+ result[2] = 0
352
313
  result
353
314
  end
354
315
 
@@ -371,8 +332,8 @@ module Gosling
371
332
  unless inverse_mat
372
333
  raise "Unable to invert matrix: #{mat}!"
373
334
  end
374
- result = mat.inverse * Snow::Vec3[v[0], v[1], 1.to_r]
375
- result[2] = 0.to_r
335
+ result = mat.inverse * Snow::Vec3[v[0], v[1], 1]
336
+ result[2] = 0
376
337
  result
377
338
  end
378
339
 
@@ -397,18 +358,17 @@ module Gosling
397
358
  def update_scale_matrix
398
359
  return unless @scale_is_dirty || @scale_mat.nil?
399
360
  @scale_mat ||= Snow::Mat3.new
400
- @scale_mat[0] = @scale[0].to_r
401
- @scale_mat[4] = @scale[1].to_r
361
+ @scale_mat[0] = @scale[0]
362
+ @scale_mat[4] = @scale[1]
402
363
  @scale_is_dirty = false
403
364
  end
404
365
 
405
366
  def update_rotate_matrix
406
367
  return unless @rotate_is_dirty || @rotate_mat.nil?
407
368
  @rotate_mat ||= Snow::Mat3.new
408
- @rotate_mat[0] = Transformable.rational_cos(@rotation)
409
- @rotate_mat[1] = Transformable.rational_sin(@rotation)
410
- @rotate_mat[3] = -Transformable.rational_sin(@rotation)
411
- @rotate_mat[4] = Transformable.rational_cos(@rotation)
369
+ @rotate_mat[4] = @rotate_mat[0] = Math.cos(@rotation)
370
+ @rotate_mat[1] = Math.sin(@rotation)
371
+ @rotate_mat[3] = -@rotate_mat[1]
412
372
  @rotate_is_dirty = false
413
373
  end
414
374
 
@@ -3,5 +3,5 @@
3
3
  # MINOR version when you add functionality in a backwards-compatible manner, and
4
4
  # PATCH version when you make backwards-compatible bug fixes.
5
5
  module Gosling
6
- VERSION = '2.0.1'
6
+ VERSION = '2.1.0'
7
7
  end