frustum.go 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194
  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. // Frustum represents a frustum
  6. type Frustum struct {
  7. planes []Plane
  8. }
  9. // NewFrustum returns a pointer to a new Frustum object
  10. func NewFrustum(p0, p1, p2, p3, p4, p5 *Plane) *Frustum {
  11. f := new(Frustum)
  12. f.planes = make([]Plane, 6)
  13. if p0 != nil {
  14. f.planes[0] = *p0
  15. }
  16. if p1 != nil {
  17. f.planes[1] = *p1
  18. }
  19. if p2 != nil {
  20. f.planes[2] = *p2
  21. }
  22. if p3 != nil {
  23. f.planes[3] = *p3
  24. }
  25. if p4 != nil {
  26. f.planes[4] = *p4
  27. }
  28. if p5 != nil {
  29. f.planes[5] = *p5
  30. }
  31. return f
  32. }
  33. // Set sets the frustum's planes
  34. func (f *Frustum) Set(p0, p1, p2, p3, p4, p5 *Plane) *Frustum {
  35. if p0 != nil {
  36. f.planes[0] = *p0
  37. }
  38. if p1 != nil {
  39. f.planes[1] = *p1
  40. }
  41. if p2 != nil {
  42. f.planes[2] = *p2
  43. }
  44. if p3 != nil {
  45. f.planes[3] = *p3
  46. }
  47. if p4 != nil {
  48. f.planes[4] = *p4
  49. }
  50. if p5 != nil {
  51. f.planes[5] = *p5
  52. }
  53. return f
  54. }
  55. // Copy modifies the receiver frustum to match the provided frustum
  56. func (f *Frustum) Copy(frustum *Frustum) *Frustum {
  57. for i := 0; i < 6; i++ {
  58. f.planes[i] = frustum.planes[i]
  59. }
  60. return f
  61. }
  62. // SetFromMatrix sets the frustum's planes based on the specified Matrix4
  63. func (f *Frustum) SetFromMatrix(m *Matrix4) *Frustum {
  64. planes := f.planes
  65. me0 := m[0]
  66. me1 := m[1]
  67. me2 := m[2]
  68. me3 := m[3]
  69. me4 := m[4]
  70. me5 := m[5]
  71. me6 := m[6]
  72. me7 := m[7]
  73. me8 := m[8]
  74. me9 := m[9]
  75. me10 := m[10]
  76. me11 := m[11]
  77. me12 := m[12]
  78. me13 := m[13]
  79. me14 := m[14]
  80. me15 := m[15]
  81. planes[0].SetComponents(me3-me0, me7-me4, me11-me8, me15-me12).Normalize()
  82. planes[1].SetComponents(me3+me0, me7+me4, me11+me8, me15+me12).Normalize()
  83. planes[2].SetComponents(me3+me1, me7+me5, me11+me9, me15+me13).Normalize()
  84. planes[3].SetComponents(me3-me1, me7-me5, me11-me9, me15-me13).Normalize()
  85. planes[4].SetComponents(me3-me2, me7-me6, me11-me10, me15-me14).Normalize()
  86. planes[5].SetComponents(me3+me2, me7+me6, me11+me10, me15+me14).Normalize()
  87. return f
  88. }
  89. /**
  90. SHOULD NOT DEPEND on core package (Move to core ?)
  91. func (this *Frustum) IntersectsObject(geometry *core.Geometry) bool {
  92. return false
  93. }
  94. */
  95. // IntersectsSphere determines whether the specified sphere is intersecting the frustum
  96. func (f *Frustum) IntersectsSphere(sphere *Sphere) bool {
  97. planes := f.planes
  98. negRadius := -sphere.Radius
  99. for i := 0; i < 6; i++ {
  100. distance := planes[i].DistanceToPoint(&sphere.Center)
  101. if distance < negRadius {
  102. return false
  103. }
  104. }
  105. return true
  106. }
  107. // IntersectsBox determines whether the specified box is intersecting the frustum
  108. func (f *Frustum) IntersectsBox(box *Box3) bool {
  109. var p1 Vector3
  110. var p2 Vector3
  111. for i := 0; i < 6; i++ {
  112. plane := &f.planes[i]
  113. if plane.normal.X > 0 {
  114. p1.X = box.Min.X
  115. } else {
  116. p1.X = box.Max.X
  117. }
  118. if plane.normal.X > 0 {
  119. p2.X = box.Max.X
  120. } else {
  121. p2.X = box.Min.X
  122. }
  123. if plane.normal.Y > 0 {
  124. p2.Y = box.Min.Y
  125. } else {
  126. p2.Y = box.Max.Y
  127. }
  128. if plane.normal.Y > 0 {
  129. p2.Y = box.Max.Y
  130. } else {
  131. p2.Y = box.Min.Y
  132. }
  133. if plane.normal.Z > 0 {
  134. p1.Z = box.Min.Z
  135. } else {
  136. p1.Z = box.Max.Z
  137. }
  138. if plane.normal.Z > 0 {
  139. p1.Z = box.Max.Z
  140. } else {
  141. p2.Z = box.Min.Z
  142. }
  143. d1 := plane.DistanceToPoint(&p1)
  144. d2 := plane.DistanceToPoint(&p2)
  145. // if both outside plane, no intersection
  146. if d1 < 0 && d2 < 0 {
  147. return false
  148. }
  149. }
  150. return true
  151. }
  152. // ContainsPoint determines whether the frustum contains the specified point
  153. func (f *Frustum) ContainsPoint(point *Vector3) bool {
  154. for i := 0; i < 6; i++ {
  155. if f.planes[i].DistanceToPoint(point) < 0 {
  156. return false
  157. }
  158. }
  159. return true
  160. }
  161. // Clone returns a pointer to a new Frustum object with the same planes as the original
  162. func (f *Frustum) Clone() *Frustum {
  163. return NewFrustum(nil, nil, nil, nil, nil, nil).Copy(f)
  164. }