-
Notifications
You must be signed in to change notification settings - Fork 1
/
vec3.go
160 lines (134 loc) · 4.08 KB
/
vec3.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
149
150
151
152
153
154
155
156
157
158
159
160
// Copyright 2013 Frederik Zipp. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package geom
import "math"
// A Vec3 represents a vector with coordinates X, Y and Z in 3-dimensional
// euclidean space.
type Vec3 struct {
X, Y, Z float32
}
var (
// V3Zero is the zero vector (0,0,0).
V3Zero = Vec3{0, 0, 0}
// V3Unit is the unit vector (1,1,1).
V3Unit = Vec3{1, 1, 1}
// V3UnitX is the x-axis unit vector (1,0,0).
V3UnitX = Vec3{1, 0, 0}
// V3UnitY is the y-axis unit vector (0,1,0).
V3UnitY = Vec3{0, 1, 0}
// V3UnitZ is the z-axis unit vector (0,0,1).
V3UnitZ = Vec3{0, 0, 1}
)
// V3 is shorthand for Vec3{X: x, Y: y, Z: z}.
func V3(x, y, z float32) Vec3 {
return Vec3{x, y, z}
}
// Add returns the vector v+w.
func (v Vec3) Add(w Vec3) Vec3 {
return Vec3{v.X + w.X, v.Y + w.Y, v.Z + w.Z}
}
// Sub returns the vector v-w.
func (v Vec3) Sub(w Vec3) Vec3 {
return Vec3{v.X - w.X, v.Y - w.Y, v.Z - w.Z}
}
// Mul returns the vector v*s.
func (v Vec3) Mul(s float32) Vec3 {
return Vec3{v.X * s, v.Y * s, v.Z * s}
}
// Div returns the vector v/s.
func (v Vec3) Div(s float32) Vec3 {
return Vec3{v.X / s, v.Y / s, v.Z / s}
}
// Neg returns the negated vector of v.
func (v Vec3) Neg() Vec3 {
return v.Mul(-1)
}
// Dot returns the dot (a.k.a. scalar) product of v and w.
func (v Vec3) Dot(w Vec3) float32 {
return v.X*w.X + v.Y*w.Y + v.Z*w.Z
}
// Cross returns the cross product of v and w.
func (v Vec3) Cross(w Vec3) Vec3 {
return Vec3{
v.Y*w.Z - v.Z*w.Y,
v.Z*w.X - v.X*w.Z,
v.X*w.Y - v.Y*w.X,
}
}
// CompMul returns the component-wise multiplication of two vectors.
func (v Vec3) CompMul(w Vec3) Vec3 {
return Vec3{v.X * w.X, v.Y * w.Y, v.Z * w.Z}
}
// CompDiv returns the component-wise division of two vectors.
func (v Vec3) CompDiv(w Vec3) Vec3 {
return Vec3{v.X / w.X, v.Y / w.Y, v.Z / w.Z}
}
// SqDist returns the square of the euclidean distance between two vectors.
func (v Vec3) SqDist(w Vec3) float32 {
return v.Sub(w).SqLen()
}
// Dist returns the euclidean distance between two vectors.
func (v Vec3) Dist(w Vec3) float32 {
return v.Sub(w).Len()
}
// SqLen returns the square of the length (euclidean norm) of a vector.
func (v Vec3) SqLen() float32 {
return v.Dot(v)
}
// Len returns the length (euclidean norm) of a vector.
func (v Vec3) Len() float32 {
return float32(math.Sqrt(float64(v.SqLen())))
}
// Norm returns the normalized vector of a vector.
func (v Vec3) Norm() Vec3 {
return v.Div(v.Len())
}
// Reflect returns the reflection vector of v given a normal n.
func (v Vec3) Reflect(n Vec3) Vec3 {
return v.Sub(n.Mul(2 * v.Dot(n)))
}
// Lerp returns the linear interpolation between v and w by amount t.
// The amount t is usually a value between 0 and 1. If t=0 v will be
// returned; if t=1 w will be returned.
func (v Vec3) Lerp(w Vec3, t float32) Vec3 {
return Vec3{lerp(v.X, w.X, t), lerp(v.Y, w.Y, t), lerp(v.Z, w.Z, t)}
}
// Min returns a vector with each component set to the lesser value
// of the corresponding component pair of v and w.
func (v Vec3) Min(w Vec3) Vec3 {
return Vec3{
min(v.X, w.X),
min(v.Y, w.Y),
min(v.Z, w.Z),
}
}
// Max returns a vector with each component set to the greater value
// of the corresponding component pair of v and w.
func (v Vec3) Max(w Vec3) Vec3 {
return Vec3{
max(v.X, w.X),
max(v.Y, w.Y),
max(v.Z, w.Z),
}
}
// Transform transforms vector v with 4x4 matrix m.
func (v Vec3) Transform(m *Mat4) Vec3 {
return Vec3{
m[0][0]*v.X + m[1][0]*v.Y + m[2][0]*v.Z + m[3][0],
m[0][1]*v.X + m[1][1]*v.Y + m[2][1]*v.Z + m[3][1],
m[0][2]*v.X + m[1][2]*v.Y + m[2][2]*v.Z + m[3][2],
}
}
// NearEq returns whether v and w are approximately equal. This relation is not
// transitive in general. The tolerance for the floating-point components is
// ±1e-5.
func (v Vec3) NearEq(w Vec3) bool {
return nearEq(v.X, w.X, epsilon) &&
nearEq(v.Y, w.Y, epsilon) &&
nearEq(v.Z, w.Z, epsilon)
}
// String returns a string representation of v like "(3.25, -1.5, 1.2)".
func (v Vec3) String() string {
return "(" + str(v.X) + ", " + str(v.Y) + ", " + str(v.Z) + ")"
}