box3.go 7.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287
  1. // Copyright 2016 The G3N Authors. All rights reserved.
  2. // Use of this source code is governed by a BSD-style
  3. // license that can be found in the LICENSE file.
  4. package math32
  5. // Box3 represents a 3D bounding box defined by two points:
  6. // the point with minimum coordinates and the point with maximum coordinates.
  7. type Box3 struct {
  8. Min Vector3
  9. Max Vector3
  10. }
  11. // NewBox3 creates and returns a pointer to a new Box3 defined
  12. // by its minimum and maximum coordinates.
  13. func NewBox3(min, max *Vector3) *Box3 {
  14. b := new(Box3)
  15. b.Set(min, max)
  16. return b
  17. }
  18. // Set sets this bounding box minumum and maximum coordinates.
  19. // Returns pointer to this updated bounding box.
  20. func (b *Box3) Set(min, max *Vector3) *Box3 {
  21. if min != nil {
  22. b.Min = *min
  23. } else {
  24. b.Min.Set(Infinity, Infinity, Infinity)
  25. }
  26. if max != nil {
  27. b.Max = *max
  28. } else {
  29. b.Max.Set(-Infinity, -Infinity, -Infinity)
  30. }
  31. return b
  32. }
  33. // SetFromPoints set this bounding box from the specified array of points.
  34. // Returns pointer to this updated bounding box.
  35. func (b *Box3) SetFromPoints(points []Vector3) *Box3 {
  36. b.MakeEmpty()
  37. for i := 0; i < len(points); i++ {
  38. b.ExpandByPoint(&points[i])
  39. }
  40. return b
  41. }
  42. // SetFromCenterAndSize set this bounding box from a center point and size.
  43. // Size is a vector from the minumum point to the maximum point.
  44. // Returns pointer to this updated bounding box.
  45. func (b *Box3) SetFromCenterAndSize(center, size *Vector3) *Box3 {
  46. v1 := NewVector3(0, 0, 0)
  47. halfSize := v1.Copy(size).MultiplyScalar(0.5)
  48. b.Min.Copy(center).Sub(halfSize)
  49. b.Max.Copy(center).Add(halfSize)
  50. return b
  51. }
  52. // Copy copy other to this bounding box.
  53. // Returns pointer to this updated bounding box.
  54. func (b *Box3) Copy(other *Box3) *Box3 {
  55. b.Min = other.Min
  56. b.Max = other.Max
  57. return b
  58. }
  59. // MakeEmpty set this bounding box to empty.
  60. // Returns pointer to this updated bounding box.
  61. func (b *Box3) MakeEmpty() *Box3 {
  62. b.Min.X = Infinity
  63. b.Min.Y = Infinity
  64. b.Min.Z = Infinity
  65. b.Max.X = -Infinity
  66. b.Max.Y = -Infinity
  67. b.Max.Z = -Infinity
  68. return b
  69. }
  70. // Empty returns if this bounding box is empty.
  71. func (b *Box3) Empty() bool {
  72. return (b.Max.X < b.Min.X) || (b.Max.Y < b.Min.Y) || (b.Max.Z < b.Min.Z)
  73. }
  74. // Center calculates the center point of this bounding box and
  75. // stores its pointer to optionalTarget, if not nil, and also returns it.
  76. func (b *Box3) Center(optionalTarget *Vector3) *Vector3 {
  77. var result *Vector3
  78. if optionalTarget == nil {
  79. result = NewVector3(0, 0, 0)
  80. } else {
  81. result = optionalTarget
  82. }
  83. return result.AddVectors(&b.Min, &b.Max).MultiplyScalar(0.5)
  84. }
  85. // Size calculates the size of this bounding box: the vector from
  86. // its minimum point to its maximum point.
  87. // Store pointer to the calculated size into optionalTarget, if not nil,
  88. // and also returns it.
  89. func (b *Box3) Size(optionalTarget *Vector3) *Vector3 {
  90. var result *Vector3
  91. if optionalTarget == nil {
  92. result = NewVector3(0, 0, 0)
  93. } else {
  94. result = optionalTarget
  95. }
  96. return result.SubVectors(&b.Min, &b.Max)
  97. }
  98. // ExpandByPoint may expand this bounding box to include the specified point.
  99. // Returns pointer to this updated bounding box.
  100. func (b *Box3) ExpandByPoint(point *Vector3) *Box3 {
  101. b.Min.Min(point)
  102. b.Max.Max(point)
  103. return b
  104. }
  105. // ExpandByVector expands this bounding box by the specified vector.
  106. // Returns pointer to this updated bounding box.
  107. func (b *Box3) ExpandByVector(vector *Vector3) *Box3 {
  108. b.Min.Sub(vector)
  109. b.Max.Add(vector)
  110. return b
  111. }
  112. // ExpandByScalar expands this bounding box by the specified scalar.
  113. // Returns pointer to this updated bounding box.
  114. func (b *Box3) ExpandByScalar(scalar float32) *Box3 {
  115. b.Min.AddScalar(-scalar)
  116. b.Max.AddScalar(scalar)
  117. return b
  118. }
  119. // ContainsPoint returns if this bounding box contains the specified point.
  120. func (b *Box3) ContainsPoint(point *Vector3) bool {
  121. if point.X < b.Min.X || point.X > b.Max.X ||
  122. point.Y < b.Min.Y || point.Y > b.Max.Y ||
  123. point.Z < b.Min.Z || point.Z > b.Max.Z {
  124. return false
  125. }
  126. return true
  127. }
  128. // ContainsBox returns if this bounding box contains other box.
  129. func (b *Box3) ContainsBox(box *Box3) bool {
  130. if (b.Min.X <= box.Max.X) && (box.Max.X <= b.Max.X) &&
  131. (b.Min.Y <= box.Min.Y) && (box.Max.Y <= b.Max.Y) &&
  132. (b.Min.Z <= box.Min.Z) && (box.Max.Z <= b.Max.Z) {
  133. return true
  134. }
  135. return false
  136. }
  137. // IsIntersectionBox returns if other box intersects this one.
  138. func (b *Box3) IsIntersectionBox(other *Box3) bool {
  139. // using 6 splitting planes to rule out intersections.
  140. if other.Max.X < b.Min.X || other.Min.X > b.Max.X ||
  141. other.Max.Y < b.Min.Y || other.Min.Y > b.Max.Y ||
  142. other.Max.Z < b.Min.Z || other.Min.Z > b.Max.Z {
  143. return false
  144. }
  145. return true
  146. }
  147. // ClampPoint calculates a new point which is the specified point clamped inside this box.
  148. // Stores the pointer to this new point into optionaTarget, if not nil, and also returns it.
  149. func (b *Box3) ClampPoint(point *Vector3, optionalTarget *Vector3) *Vector3 {
  150. var result *Vector3
  151. if optionalTarget == nil {
  152. result = NewVector3(0, 0, 0)
  153. } else {
  154. result = optionalTarget
  155. }
  156. return result.Copy(point).Clamp(&b.Min, &b.Max)
  157. }
  158. // DistanceToPoint returns the distance from this box to the specified point.
  159. func (b *Box3) DistanceToPoint(point *Vector3) float32 {
  160. var v1 Vector3
  161. clampedPoint := v1.Copy(point).Clamp(&b.Min, &b.Max)
  162. return clampedPoint.Sub(point).Length()
  163. }
  164. // GetBoundingSphere creates a bounding sphere to this bounding box.
  165. // Store its pointer into optionalTarget, if not nil, and also returns it.
  166. func (b *Box3) GetBoundingSphere(optionalTarget *Sphere) *Sphere {
  167. var v1 Vector3
  168. var result *Sphere
  169. if optionalTarget == nil {
  170. result = NewSphere(nil, 0)
  171. } else {
  172. result = optionalTarget
  173. }
  174. result.Center = *b.Center(nil)
  175. result.Radius = b.Size(&v1).Length() * 0.5
  176. return result
  177. }
  178. // Intersect sets this box to the intersection with other box.
  179. // Returns pointer to this updated bounding box.
  180. func (b *Box3) Intersect(other *Box3) *Box3 {
  181. b.Min.Max(&other.Min)
  182. b.Max.Min(&other.Max)
  183. return b
  184. }
  185. // Union set this box to the union with other box.
  186. // Returns pointer to this updated bounding box.
  187. func (b *Box3) Union(other *Box3) *Box3 {
  188. b.Min.Min(&other.Min)
  189. b.Max.Max(&other.Max)
  190. return b
  191. }
  192. // ApplyMatrix4 applies the specified matrix to the vertices of this bounding box.
  193. // Returns pointer to this updated bounding box.
  194. func (b *Box3) ApplyMatrix4(matrix *Matrix4) *Box3 {
  195. points := []Vector3{
  196. Vector3{},
  197. Vector3{},
  198. Vector3{},
  199. Vector3{},
  200. Vector3{},
  201. Vector3{},
  202. Vector3{},
  203. Vector3{},
  204. }
  205. points[0].Set(b.Min.X, b.Min.Y, b.Min.Z).ApplyMatrix4(matrix) // 000
  206. points[1].Set(b.Min.X, b.Min.Y, b.Max.Z).ApplyMatrix4(matrix) // 001
  207. points[2].Set(b.Min.X, b.Max.Y, b.Min.Z).ApplyMatrix4(matrix) // 010
  208. points[3].Set(b.Min.X, b.Max.Y, b.Max.Z).ApplyMatrix4(matrix) // 011
  209. points[4].Set(b.Max.X, b.Min.Y, b.Min.Z).ApplyMatrix4(matrix) // 100
  210. points[5].Set(b.Max.X, b.Min.Y, b.Max.Z).ApplyMatrix4(matrix) // 101
  211. points[6].Set(b.Max.X, b.Max.Y, b.Min.Z).ApplyMatrix4(matrix) // 110
  212. points[7].Set(b.Max.X, b.Max.Y, b.Max.Z).ApplyMatrix4(matrix) // 111
  213. b.MakeEmpty()
  214. b.SetFromPoints(points)
  215. return b
  216. }
  217. // Translate translates the position of this box by offset.
  218. // Returns pointer to this updated box.
  219. func (b *Box3) Translate(offset *Vector3) *Box3 {
  220. b.Min.Add(offset)
  221. b.Max.Add(offset)
  222. return b
  223. }
  224. // Equals returns if this box is equal to other
  225. func (b *Box3) Equals(other *Box3) bool {
  226. return other.Min.Equals(&b.Min) && other.Max.Equals(&b.Max)
  227. }
  228. // Clone creates and returns a pointer to copy of this bounding box
  229. func (b *Box3) Clone() *Box3 {
  230. return NewBox3(&b.Min, &b.Max)
  231. }