2020-06-10 20:38:48 +08:00

142 lines
3.1 KiB
Go

// Copyright 2017-2020 The ShadowEditor Authors. All rights reserved.
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file.
//
// For more information, please visit: https://github.com/tengge1/ShadowEditor
// You can also visit: https://gitee.com/tengge1/ShadowEditor
//
// This package is translated from three.js, visit `https://github.com/mrdoob/three.js`
// for more information.
package three
import "math"
// NewSphere :
func NewSphere(center Vector3, radius float64) *Sphere {
return &Sphere{center, radius}
}
// Sphere :
type Sphere struct {
Center Vector3
Radius float64
}
// Set :
func (s Sphere) Set(center Vector3, radius float64) *Sphere {
s.Center.Copy(center)
s.Radius = radius
return &s
}
// SetFromPoints :
func (s Sphere) SetFromPoints(points []Vector3, optionalCenter Vector3) *Sphere {
center := s.Center
center.Copy(optionalCenter)
maxRadiusSq := float64(0)
for i, il := 0, len(points); i < il; i++ {
maxRadiusSq = math.Max(maxRadiusSq, center.DistanceToSquared(points[i]))
}
s.Radius = math.Sqrt(maxRadiusSq)
return &s
}
// Clone :
func (s Sphere) Clone() *Sphere {
return NewSphere(s.Center, s.Radius).Copy(s)
}
// Copy :
func (s Sphere) Copy(sphere Sphere) *Sphere {
s.Center.Copy(sphere.Center)
s.Radius = sphere.Radius
return &s
}
// IsEmpty :
func (s Sphere) IsEmpty() bool {
return s.Radius < 0
}
// MakeEmpty :
func (s Sphere) MakeEmpty() *Sphere {
s.Center.Set(0, 0, 0)
s.Radius = -1
return &s
}
// ContainsPoint :
func (s Sphere) ContainsPoint(point Vector3) bool {
return point.DistanceToSquared(s.Center) <= s.Radius*s.Radius
}
// DistanceToPoint :
func (s Sphere) DistanceToPoint(point Vector3) float64 {
return point.DistanceTo(s.Center) - s.Radius
}
// IntersectsSphere :
func (s Sphere) IntersectsSphere(sphere Sphere) bool {
radiusSum := s.Radius + sphere.Radius
return sphere.Center.DistanceToSquared(s.Center) <= radiusSum*radiusSum
}
// IntersectsBox :
func (s Sphere) IntersectsBox(box Box3) bool {
return box.IntersectsSphere(s)
}
// IntersectsPlane :
func (s Sphere) IntersectsPlane(plane Plane) bool {
return math.Abs(plane.DistanceToPoint(s.Center)) <= s.Radius
}
// ClampPoint :
func (s Sphere) ClampPoint(point, target Vector3) *Vector3 {
deltaLengthSq := s.Center.DistanceToSquared(point)
target.Copy(point)
if deltaLengthSq > s.Radius*s.Radius {
target.Sub(s.Center).Normalize()
target.MultiplyScalar(s.Radius).Add(s.Center)
}
return &target
}
// GetBoundingBox :
func (s Sphere) GetBoundingBox(target Box3) *Box3 {
if s.IsEmpty() {
// Empty sphere produces empty bounding box
target.MakeEmpty()
return &target
}
target.Set(s.Center, s.Center)
target.ExpandByScalar(s.Radius)
return &target
}
// ApplyMatrix4 :
func (s Sphere) ApplyMatrix4(matrix Matrix4) *Sphere {
s.Center.ApplyMatrix4(matrix)
s.Radius = s.Radius * matrix.GetMaxScaleOnAxis()
return &s
}
// Translate :
func (s Sphere) Translate(offset Vector3) *Sphere {
s.Center.Add(offset)
return &s
}
// Equals :
func (s Sphere) Equals(sphere Sphere) bool {
return sphere.Center.Equals(s.Center) && sphere.Radius == s.Radius
}