gosling 2.0.1 → 2.1.0

Sign up to get free protection for your applications and to get access to all the features.
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