Class: Mittsu::Box3

Inherits:
Object
  • Object
show all
Defined in:
lib/mittsu/math/box3.rb

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(min = nil, max = nil) ⇒ Box3

Returns a new instance of Box3.



5
6
7
8
# File 'lib/mittsu/math/box3.rb', line 5

def initialize(min = nil, max = nil)
  @min = min || Mittsu::Vector3.new(Float::INFINITY, Float::INFINITY, Float::INFINITY)
  @max = max || Mittsu::Vector3.new(-Float::INFINITY, -Float::INFINITY, -Float::INFINITY)
end

Instance Attribute Details

#maxObject

Returns the value of attribute max.



3
4
5
# File 'lib/mittsu/math/box3.rb', line 3

def max
  @max
end

#minObject

Returns the value of attribute min.



3
4
5
# File 'lib/mittsu/math/box3.rb', line 3

def min
  @min
end

Instance Method Details

#==(box) ⇒ Object



183
184
185
# File 'lib/mittsu/math/box3.rb', line 183

def ==(box)
  box.min == @min && box.max == @max
end

#apply_matrix4(matrix) ⇒ Object



160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
# File 'lib/mittsu/math/box3.rb', line 160

def apply_matrix4(matrix)
  points = [
    # NOTE: I am using a binary pattern to specify all 2^3 combinations below
    Mittsu::Vector3.new(@min.x, @min.y, @min.z).apply_matrix4(matrix), # 000
    Mittsu::Vector3.new(@min.x, @min.y, @max.z).apply_matrix4(matrix), # 001
    Mittsu::Vector3.new(@min.x, @max.y, @min.z).apply_matrix4(matrix), # 010
    Mittsu::Vector3.new(@min.x, @max.y, @max.z).apply_matrix4(matrix), # 011
    Mittsu::Vector3.new(@max.x, @min.y, @min.z).apply_matrix4(matrix), # 100
    Mittsu::Vector3.new(@max.x, @min.y, @max.z).apply_matrix4(matrix), # 101
    Mittsu::Vector3.new(@max.x, @max.y, @min.z).apply_matrix4(matrix), # 110
    Mittsu::Vector3.new(@max.x, @max.y, @max.z).apply_matrix4(matrix)  # 111
  ]
  self.make_empty
  self.set_from_points(points)
  self
end

#bounding_sphere(target = Mittsu::Sphere.new) ⇒ Object



142
143
144
145
146
# File 'lib/mittsu/math/box3.rb', line 142

def bounding_sphere(target = Mittsu::Sphere.new)
  target.center = self.center
  target.radius = self.size().length * 0.5
  target
end

#center(target = Mittsu::Vector3.new) ⇒ Object



78
79
80
# File 'lib/mittsu/math/box3.rb', line 78

def center(target = Mittsu::Vector3.new)
  target.add_vectors(@min, @max).multiply_scalar(0.5)
end

#clamp_point(point, target = Mittsu::Vector3.new) ⇒ Object



134
135
136
# File 'lib/mittsu/math/box3.rb', line 134

def clamp_point(point, target = Mittsu::Vector3.new)
  target.copy(point).clamp(@min, @max)
end

#cloneObject



187
188
189
# File 'lib/mittsu/math/box3.rb', line 187

def clone
  Mittsu::Box3.new.copy(self)
end

#contains_box?(box) ⇒ Boolean

Returns:

  • (Boolean)


110
111
112
113
114
# File 'lib/mittsu/math/box3.rb', line 110

def contains_box?(box)
  ((@min.x <= box.min.x) && (box.max.x <= @max.x) &&
    (@min.y <= box.min.y) && (box.max.y <= @max.y) &&
    (@min.z <= box.min.z) && (box.max.z <= @max.z))
end

#contains_point?(point) ⇒ Boolean

Returns:

  • (Boolean)


104
105
106
107
108
# File 'lib/mittsu/math/box3.rb', line 104

def contains_point?(point)
  !(point.x < @min.x || point.x > @max.x ||
    point.y < @min.y || point.y > @max.y ||
    point.z < @min.z || point.z > @max.z)
end

#copy(box) ⇒ Object



61
62
63
64
65
# File 'lib/mittsu/math/box3.rb', line 61

def copy(box)
  @min.copy(box.min)
  @max.copy(box.max)
  self
end

#distance_to_point(point, target = Mittsu::Vector3.new) ⇒ Object



138
139
140
# File 'lib/mittsu/math/box3.rb', line 138

def distance_to_point(point, target = Mittsu::Vector3.new)
  target.copy(point).clamp(@min, @max).sub(point).length
end

#empty?Boolean

Returns:

  • (Boolean)


73
74
75
76
# File 'lib/mittsu/math/box3.rb', line 73

def empty?
  # self is a more robust check for empty than (volume <= 0) because volume can get positive with two negative axes
  (@max.x < @min.x) || (@max.y < @min.y) || (@max.z < @min.z)
end

#expand_by_point(point) ⇒ Object



86
87
88
89
90
# File 'lib/mittsu/math/box3.rb', line 86

def expand_by_point(point)
  @min.min(point)
  @max.max(point)
  self
end

#expand_by_scalar(scalar) ⇒ Object



98
99
100
101
102
# File 'lib/mittsu/math/box3.rb', line 98

def expand_by_scalar(scalar)
  @min.add_scalar(-scalar)
  @max.add_scalar(scalar)
  self
end

#expand_by_vector(vector) ⇒ Object



92
93
94
95
96
# File 'lib/mittsu/math/box3.rb', line 92

def expand_by_vector(vector)
  @min.sub(vector)
  @max.add(vector)
  self
end

#intersect(box) ⇒ Object



148
149
150
151
152
# File 'lib/mittsu/math/box3.rb', line 148

def intersect(box)
  @min.max(box.min)
  @max.min(box.max)
  self
end

#intersection_box?(box) ⇒ Boolean

Returns:

  • (Boolean)


127
128
129
130
131
132
# File 'lib/mittsu/math/box3.rb', line 127

def intersection_box?(box)
  # using 6 splitting planes to rule out intersections.
  !(box.max.x < @min.x || box.min.x > @max.x ||
    box.max.y < @min.y || box.min.y > @max.y ||
    box.max.z < @min.z || box.min.z > @max.z)
end

#make_emptyObject



67
68
69
70
71
# File 'lib/mittsu/math/box3.rb', line 67

def make_empty
  @min.x = @min.y = @min.z = Float::INFINITY
  @max.x = @max.y = @max.z = -Float::INFINITY
  self
end

#parameter(point, target = nil) ⇒ Object



116
117
118
119
120
121
122
123
124
125
# File 'lib/mittsu/math/box3.rb', line 116

def parameter(point, target = nil)
  # This can potentially have a divide by zero if the box
  # has a size dimension of 0.
  result = target || Mittsu::Vector3.new
  result.set(
    (point.x - @min.x) / (@max.x - @min.x),
    (point.y - @min.y) / (@max.y - @min.y),
    (point.z - @min.z) / (@max.z - @min.z)
  )
end

#set(min, max) ⇒ Object



10
11
12
13
14
# File 'lib/mittsu/math/box3.rb', line 10

def set(min, max)
  @min.copy(min)
  @max.copy(max)
  self
end

#set_from_center_and_size(center, size) ⇒ Object



24
25
26
27
28
29
# File 'lib/mittsu/math/box3.rb', line 24

def set_from_center_and_size(center, size)
  halfSize = size.clone.multiply_scalar(0.5)
  @min.copy(center).sub(halfSize)
  @max.copy(center).add(halfSize)
  self
end

#set_from_object(object) ⇒ Object



31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
# File 'lib/mittsu/math/box3.rb', line 31

def set_from_object(object)
  # Computes the world-axis-aligned bounding box of an object (including its children),
  # accounting for both the object's, and childrens', world transforms
  v1 = Mittsu::Vector3.new
  scope = self
  object.update_matrix_world(true)
  self.make_empty
  object.traverse do |node|
    geometry = node.geometry
    if geometry != nil
      if geometry.is_a?(Mittsu::Geometry)
        vertices = geometry.vertices
        vertices.each do |vertex|
          v1.copy(vertex)
          v1.apply_matrix4(node.matrix_world)
          scope.expand_by_point(v1)
        end
      elsif geometry.is_a?(Mittsu::BufferGeometry) && geometry.attributes['position'] != nil
        positions = geometry.attributes['position'].array
        positions.each_slice(3) do |postition|
          v1.set(position[0], position[1], position[2])
          v1.apply_matrix4(node.matrix_world)
          scope.expand_by_point(v1)
        end
      end
    end
  end
  return self
end

#set_from_points(points) ⇒ Object



16
17
18
19
20
21
22
# File 'lib/mittsu/math/box3.rb', line 16

def set_from_points(points)
  self.make_empty
  points.each do |point|
    self.expand_by_point(point)
  end
  self
end

#size(target = Mittsu::Vector3.new) ⇒ Object



82
83
84
# File 'lib/mittsu/math/box3.rb', line 82

def size(target = Mittsu::Vector3.new)
  target.sub_vectors(@max, @min)
end

#translate(offset) ⇒ Object



177
178
179
180
181
# File 'lib/mittsu/math/box3.rb', line 177

def translate(offset)
  @min.add(offset)
  @max.add(offset)
  self
end

#union(box) ⇒ Object



154
155
156
157
158
# File 'lib/mittsu/math/box3.rb', line 154

def union(box)
  @min.min(box.min)
  @max.max(box.max)
  self
end