forked from g3n/engine
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathsphere.go
148 lines (118 loc) · 3.84 KB
/
sphere.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
// 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
}