| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148 |
- // Copyright 2016 The G3N Authors. All rights reserved.
- // Use of this source code is governed by a BSD-style
- // license that can be found in the LICENSE file.
- package math32
- // Sphere represents a 3D sphere defined by its center point and a radius
- type Sphere struct {
- Center Vector3 // center of the sphere
- Radius float32 // radius of the sphere
- }
- // NewSphere creates and returns a pointer to a new sphere with
- // the specified center and radius.
- func NewSphere(center *Vector3, radius float32) *Sphere {
- s := new(Sphere)
- s.Center = *center
- s.Radius = radius
- return s
- }
- // Set sets the center and radius of this sphere.
- // Returns pointer to this update sphere.
- func (s *Sphere) Set(center *Vector3, radius float32) *Sphere {
- s.Center = *center
- s.Radius = radius
- return s
- }
- // SetFromPoints sets this sphere from the specified points array and optional center.
- // Returns pointer to this update sphere.
- func (s *Sphere) SetFromPoints(points []Vector3, optionalCenter *Vector3) *Sphere {
- box := NewBox3(nil, nil)
- if optionalCenter != nil {
- s.Center.Copy(optionalCenter)
- } else {
- box.SetFromPoints(points).Center(&s.Center)
- }
- var maxRadiusSq float32
- for i := 0; i < len(points); i++ {
- maxRadiusSq = Max(maxRadiusSq, s.Center.DistanceToSquared(&points[i]))
- }
- s.Radius = Sqrt(maxRadiusSq)
- return s
- }
- // Copy copy other sphere to this one.
- // Returns pointer to this update sphere.
- func (s *Sphere) Copy(other *Sphere) *Sphere {
- *s = *other
- return s
- }
- // Empty checks if this sphere is empty (radius <= 0)
- func (s *Sphere) Empty(sphere *Sphere) bool {
- if s.Radius <= 0 {
- return true
- }
- return false
- }
- // ContainsPoint returns if this sphere contains the specified point.
- func (s *Sphere) ContainsPoint(point *Vector3) bool {
- if point.DistanceToSquared(&s.Center) <= (s.Radius * s.Radius) {
- return true
- }
- return false
- }
- // DistanceToPoint returns the distance from the sphere surface to the specified point.
- func (s *Sphere) DistanceToPoint(point *Vector3) float32 {
- return point.DistanceTo(&s.Center) - s.Radius
- }
- // IntersectSphere returns if other sphere intersects this one.
- func (s *Sphere) IntersectSphere(other *Sphere) bool {
- radiusSum := s.Radius + other.Radius
- if other.Center.DistanceToSquared(&s.Center) <= (radiusSum * radiusSum) {
- return true
- }
- return false
- }
- // ClampPoint clamps the specified point inside the sphere.
- // If the specified point is inside the sphere, it is the clamped point.
- // Otherwise the clamped point is the the point in the sphere surface in the
- // nearest of the specified point.
- // The clamped point is stored in optionalTarget, if not nil, and returned.
- func (s *Sphere) ClampPoint(point *Vector3, optionalTarget *Vector3) *Vector3 {
- deltaLengthSq := s.Center.DistanceToSquared(point)
- var result *Vector3
- if optionalTarget != nil {
- result = optionalTarget
- } else {
- result = NewVector3(0, 0, 0)
- }
- result.Copy(point)
- if deltaLengthSq > (s.Radius * s.Radius) {
- result.Sub(&s.Center).Normalize()
- result.MultiplyScalar(s.Radius).Add(&s.Center)
- }
- return result
- }
- // GetBoundingBox calculates a Box3 which bounds this sphere.
- // Update optionalTarget with the calculated Box3, if not nil, and also returns it.
- func (s *Sphere) GetBoundingBox(optionalTarget *Box3) *Box3 {
- var box *Box3
- if optionalTarget != nil {
- box = optionalTarget
- } else {
- box = NewBox3(nil, nil)
- }
- box.Set(&s.Center, &s.Center)
- box.ExpandByScalar(s.Radius)
- return box
- }
- // ApplyMatrix4 applies the specified matrix transform to this sphere.
- // Returns pointer to this updated sphere.
- func (s *Sphere) ApplyMatrix4(matrix *Matrix4) *Sphere {
- s.Center.ApplyMatrix4(matrix)
- s.Radius = s.Radius * matrix.GetMaxScaleOnAxis()
- return s
- }
- // Translate translates this sphere by the specified offset.
- // Returns pointer to this updated sphere.
- func (s *Sphere) Translate(offset *Vector3) *Sphere {
- s.Center.Add(offset)
- return s
- }
|