frustum.go 3.7 KB

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