-
Notifications
You must be signed in to change notification settings - Fork 4
/
Copy pathvec2.go
334 lines (285 loc) · 7.67 KB
/
vec2.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
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
package glmatrix
import (
"fmt"
"math"
"math/rand"
)
// NewVec2 creates a new, empty vec2
func NewVec2() []float64 {
return []float64{0., 0.}
}
// Vec2Create creates a new vec2 initialized with values from an existing vector
func Vec2Create() []float64 {
return NewVec2()
}
// Vec2Clone creates a new vec2 initialized with the given values
func Vec2Clone(a []float64) []float64 {
return []float64{a[0], a[1]}
}
// Vec2FromValues creates a new vec2 initialized with the given values
func Vec2FromValues(x, y float64) []float64 {
return []float64{x, y}
}
// Vec2Copy copy the values from one vec2 to another
func Vec2Copy(out, a []float64) []float64 {
out[0] = a[0]
out[1] = a[1]
return out
}
// Vec2Set set the components of a vec2 to the given values
func Vec2Set(out []float64, x, y float64) []float64 {
out[0] = x
out[1] = y
return out
}
// Vec2Add adds two vec2's
func Vec2Add(out, a, b []float64) []float64 {
out[0] = a[0] + b[0]
out[1] = a[1] + b[1]
return out
}
// Vec2Subtract subtracts vector b from vector a
func Vec2Subtract(out, a, b []float64) []float64 {
out[0] = a[0] - b[0]
out[1] = a[1] - b[1]
return out
}
// Vec2Multiply multiplies two vec2's
func Vec2Multiply(out, a, b []float64) []float64 {
out[0] = a[0] * b[0]
out[1] = a[1] * b[1]
return out
}
// Vec2Divide divides two vec2's
func Vec2Divide(out, a, b []float64) []float64 {
out[0] = a[0] / b[0]
out[1] = a[1] / b[1]
return out
}
// Vec2Ceil math.ceil the components of a vec2
func Vec2Ceil(out, a []float64) []float64 {
out[0] = math.Ceil(a[0])
out[1] = math.Ceil(a[1])
return out
}
// Vec2Floor math.floor the components of a vec2
func Vec2Floor(out, a []float64) []float64 {
out[0] = math.Floor(a[0])
out[1] = math.Floor(a[1])
return out
}
// Vec2Min returns the minimum of two vec2's
func Vec2Min(out, a, b []float64) []float64 {
out[0] = math.Min(a[0], b[0])
out[1] = math.Min(a[1], b[1])
return out
}
// Vec2Max returns the maximum of two vec2's
func Vec2Max(out, a, b []float64) []float64 {
out[0] = math.Max(a[0], b[0])
out[1] = math.Max(a[1], b[1])
return out
}
// Vec2Round math.round the components of a vec2
func Vec2Round(out, a []float64) []float64 {
out[0] = math.Round(a[0])
out[1] = math.Round(a[1])
return out
}
// Vec2Scale scales a vec2 by a scalar number
func Vec2Scale(out, a []float64, scale float64) []float64 {
out[0] = a[0] * scale
out[1] = a[1] * scale
return out
}
// Vec2ScaleAndAdd adds two vec2's after scaling the second operand by a scalar value
func Vec2ScaleAndAdd(out, a, b []float64, scale float64) []float64 {
out[0] = a[0] + b[0]*scale
out[1] = a[1] + b[1]*scale
return out
}
// Vec2Distance calculates the euclidian distance between two vec2's
func Vec2Distance(a, b []float64) float64 {
x := b[0] - a[0]
y := b[1] - a[1]
return math.Hypot(x, y)
}
// Vec2SquaredDistance calculates the squared euclidian distance between two vec2's
func Vec2SquaredDistance(a, b []float64) float64 {
x := b[0] - a[0]
y := b[1] - a[1]
return x*x + y*y
}
// Vec2Length calculates the length of a vec2
func Vec2Length(out []float64) float64 {
x := out[0]
y := out[1]
return math.Hypot(x, y)
}
// Vec2SquaredLength calculates the squared length of a vec2
func Vec2SquaredLength(out []float64) float64 {
x := out[0]
y := out[1]
return x*x + y*y
}
// Vec2Negate negates the components of a vec2
func Vec2Negate(out, a []float64) []float64 {
out[0] = -a[0]
out[1] = -a[1]
return out
}
// Vec2Inverse returns the inverse of the components of a vec2
func Vec2Inverse(out, a []float64) []float64 {
out[0] = 1. / a[0]
out[1] = 1. / a[1]
return out
}
// Vec2Normalize normalize a vec2
func Vec2Normalize(out, a []float64) []float64 {
len := Vec2Length(a)
if 0 < len {
len = 1. / len
}
out[0] = a[0] * len
out[1] = a[1] * len
return out
}
// Vec2Dot calculates the dot product of two vec2's
func Vec2Dot(a, b []float64) float64 {
return a[0]*b[0] + a[1]*b[1]
}
// Vec2Cross computes the cross product of two vec2's
// Note that the cross product must by definition produce a 3D vector
func Vec2Cross(out, a, b []float64) []float64 {
z := a[0]*b[1] - a[1]*b[0]
out[0] = 0
out[1] = 0
out[2] = z
return out
}
// Vec2Lerp performs a linear interpolation between two vec2's
func Vec2Lerp(out, a, b []float64, t float64) []float64 {
ax := a[0]
ay := a[1]
out[0] = ax + t*(b[0]-ax)
out[1] = ay + t*(b[1]-ay)
return out
}
// Vec2Random generates a random vector with the given scale
func Vec2Random(out []float64, scale float64) []float64 {
r := rand.Float64() * 2.0 * math.Pi
out[0] = math.Cos(r) * scale
out[1] = math.Sin(r) * scale
return out
}
// Vec2TransformMat2 transforms the vec2 with a mat2
func Vec2TransformMat2(out, a, m []float64) []float64 {
x := a[0]
y := a[1]
out[0] = m[0]*x + m[2]*y
out[1] = m[1]*x + m[3]*y
return out
}
// Vec2TransformMat2d transforms the vec2 with a mat2d
func Vec2TransformMat2d(out, a, m []float64) []float64 {
x := a[0]
y := a[1]
out[0] = m[0]*x + m[2]*y + m[4]
out[1] = m[1]*x + m[3]*y + m[5]
return out
}
// Vec2TransformMat3 transforms the vec2 with a mat3
// 3rd vector component is implicitly '1'
func Vec2TransformMat3(out, a, m []float64) []float64 {
x := a[0]
y := a[1]
out[0] = m[0]*x + m[2]*y + m[6]
out[1] = m[1]*x + m[3]*y + m[7]
return out
}
// Vec2TransformMat4 transforms the vec2 with a mat4
// 3rd vector component is implicitly '0'
// 4th vector component is implicitly '1'
func Vec2TransformMat4(out, a, m []float64) []float64 {
x := a[0]
y := a[1]
out[0] = m[0]*x + m[2]*y + m[12]
out[1] = m[1]*x + m[3]*y + m[13]
return out
}
// Vec2Rotate rotate a 2D vector
func Vec2Rotate(out, p, c []float64, rad float64) []float64 {
p0 := p[0] - c[0]
p1 := p[1] - c[1]
sinC := math.Sin(rad)
cosC := math.Cos(rad)
out[0] = p0*cosC - p1*sinC + c[0]
out[1] = p0*sinC + p1*cosC + c[1]
return out
}
// Vec2Angle get the angle between two 2D vectors
func Vec2Angle(a, b []float64) float64 {
x1 := a[0]
y1 := a[1]
x2 := b[0]
y2 := b[1]
cosine := math.Sqrt(x1*x1+y1*y1) * math.Sqrt(x2*x2+y2*y2)
if cosine != 0 {
cosine = (x1*x2 + y1*y2) / cosine
}
return math.Acos(math.Min(math.Max(cosine, -1), 1))
}
// Vec2Zero set the components of a vec2 to zero
func Vec2Zero(out []float64) []float64 {
out[0] = 0.
out[1] = 0.
return out
}
// Vec2Str returns a string representation of a vector
func Vec2Str(out []float64) string {
return fmt.Sprintf("vec2(%v, %v)", out[0], out[1])
}
// Vec2ExactEquals returns whether or not the vectors exactly have the same elements in the same position (when compared with ===)
func Vec2ExactEquals(a, b []float64) bool {
return a[0] == b[0] && a[1] == b[1]
}
// Vec2Equals returns whether or not the vectors have approximately the same elements in the same position.
func Vec2Equals(a, b []float64) bool {
return equals(a[0], b[0]) && equals(a[1], b[1])
}
// Vec2Len alias for Vec2Length
var Vec2Len = Vec2Length
// Vec2Sub alias for Vec2Subtract
var Vec2Sub = Vec2Subtract
// Vec2Mul alias for Vec2Multiply
var Vec2Mul = Vec2Multiply
// Vec2Div alias for Vec2Divide
var Vec2Div = Vec2Divide
// Vec2Dist alias for Vec2Distance
var Vec2Dist = Vec2Distance
// Vec2SqrDist alias for Vec2SquaredDistance
var Vec2SqrDist = Vec2SquaredDistance
// Vec2SqrLen alias for Vec2SquaredLength
var Vec2SqrLen = Vec2SquaredLength
// Vec2ForEach perform some operation over an array of vec2s.
func Vec2ForEach(a []float64, stride, offset, count int, fn func([]float64, []float64, []float64), arg []float64) []float64 {
if stride <= 0 {
stride = 2
}
if offset <= 0 {
offset = 0
}
var l int
if 0 < count {
l = int(math.Min(float64(count*stride+offset), float64(len(a))))
} else {
l = len(a)
}
for i := offset; i < l; i += stride {
vec := []float64{a[i], a[i+1]}
fn(vec, vec, arg)
a[i] = vec[0]
a[i+1] = vec[1]
}
return a
}