sphere.go 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148
  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. // Sphere represents a 3D sphere defined by its center point and a radius
  6. type Sphere struct {
  7. Center Vector3 // center of the sphere
  8. Radius float32 // radius of the sphere
  9. }
  10. // NewSphere creates and returns a pointer to a new sphere with
  11. // the specified center and radius.
  12. func NewSphere(center *Vector3, radius float32) *Sphere {
  13. s := new(Sphere)
  14. s.Center = *center
  15. s.Radius = radius
  16. return s
  17. }
  18. // Set sets the center and radius of this sphere.
  19. // Returns pointer to this update sphere.
  20. func (s *Sphere) Set(center *Vector3, radius float32) *Sphere {
  21. s.Center = *center
  22. s.Radius = radius
  23. return s
  24. }
  25. // SetFromPoints sets this sphere from the specified points array and optional center.
  26. // Returns pointer to this update sphere.
  27. func (s *Sphere) SetFromPoints(points []Vector3, optionalCenter *Vector3) *Sphere {
  28. box := NewBox3(nil, nil)
  29. if optionalCenter != nil {
  30. s.Center.Copy(optionalCenter)
  31. } else {
  32. box.SetFromPoints(points).Center(&s.Center)
  33. }
  34. var maxRadiusSq float32
  35. for i := 0; i < len(points); i++ {
  36. maxRadiusSq = Max(maxRadiusSq, s.Center.DistanceToSquared(&points[i]))
  37. }
  38. s.Radius = Sqrt(maxRadiusSq)
  39. return s
  40. }
  41. // Copy copy other sphere to this one.
  42. // Returns pointer to this update sphere.
  43. func (s *Sphere) Copy(other *Sphere) *Sphere {
  44. *s = *other
  45. return s
  46. }
  47. // Empty checks if this sphere is empty (radius <= 0)
  48. func (s *Sphere) Empty(sphere *Sphere) bool {
  49. if s.Radius <= 0 {
  50. return true
  51. }
  52. return false
  53. }
  54. // ContainsPoint returns if this sphere contains the specified point.
  55. func (s *Sphere) ContainsPoint(point *Vector3) bool {
  56. if point.DistanceToSquared(&s.Center) <= (s.Radius * s.Radius) {
  57. return true
  58. }
  59. return false
  60. }
  61. // DistanceToPoint returns the distance from the sphere surface to the specified point.
  62. func (s *Sphere) DistanceToPoint(point *Vector3) float32 {
  63. return point.DistanceTo(&s.Center) - s.Radius
  64. }
  65. // IntersectSphere returns if other sphere intersects this one.
  66. func (s *Sphere) IntersectSphere(other *Sphere) bool {
  67. radiusSum := s.Radius + other.Radius
  68. if other.Center.DistanceToSquared(&s.Center) <= (radiusSum * radiusSum) {
  69. return true
  70. }
  71. return false
  72. }
  73. // ClampPoint clamps the specified point inside the sphere.
  74. // If the specified point is inside the sphere, it is the clamped point.
  75. // Otherwise the clamped point is the the point in the sphere surface in the
  76. // nearest of the specified point.
  77. // The clamped point is stored in optionalTarget, if not nil, and returned.
  78. func (s *Sphere) ClampPoint(point *Vector3, optionalTarget *Vector3) *Vector3 {
  79. deltaLengthSq := s.Center.DistanceToSquared(point)
  80. var result *Vector3
  81. if optionalTarget != nil {
  82. result = optionalTarget
  83. } else {
  84. result = NewVector3(0, 0, 0)
  85. }
  86. result.Copy(point)
  87. if deltaLengthSq > (s.Radius * s.Radius) {
  88. result.Sub(&s.Center).Normalize()
  89. result.MultiplyScalar(s.Radius).Add(&s.Center)
  90. }
  91. return result
  92. }
  93. // GetBoundingBox calculates a Box3 which bounds this sphere.
  94. // Update optionalTarget with the calculated Box3, if not nil, and also returns it.
  95. func (s *Sphere) GetBoundingBox(optionalTarget *Box3) *Box3 {
  96. var box *Box3
  97. if optionalTarget != nil {
  98. box = optionalTarget
  99. } else {
  100. box = NewBox3(nil, nil)
  101. }
  102. box.Set(&s.Center, &s.Center)
  103. box.ExpandByScalar(s.Radius)
  104. return box
  105. }
  106. // ApplyMatrix4 applies the specified matrix transform to this sphere.
  107. // Returns pointer to this updated sphere.
  108. func (s *Sphere) ApplyMatrix4(matrix *Matrix4) *Sphere {
  109. s.Center.ApplyMatrix4(matrix)
  110. s.Radius = s.Radius * matrix.GetMaxScaleOnAxis()
  111. return s
  112. }
  113. // Translate translates this sphere by the specified offset.
  114. // Returns pointer to this updated sphere.
  115. func (s *Sphere) Translate(offset *Vector3) *Sphere {
  116. s.Center.Add(offset)
  117. return s
  118. }