/
vpvec4x64.go
384 lines (295 loc) · 8.75 KB
/
vpvec4x64.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
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
// Vapor is a toolkit designed to support Liquid War 7.
// Copyright (C) 2015, 2016 Christian Mauduit <ufoot@ufoot.org>
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
//
// Vapor homepage: https://github.com/ufoot/vapor
// Contact author: ufoot@ufoot.org
package vpvec4
import (
"encoding/json"
"github.com/ufoot/vapor/go/vpmath"
"github.com/ufoot/vapor/go/vpnumber"
"github.com/ufoot/vapor/go/vpvec3"
)
// X64 is a vector containing 4 fixed point 64 bit values.
// Can be used in 3D matrix transformations.
type X64 [Size]vpnumber.X64
// X64UnaryOperator designs funcs such as Neg,
// which operates on one vector and returns another vector.
type X64UnaryOperator func(a *X64) *X64
// X64BinaryOperator designs funcs such as Add, Sub, Min, Max,
// which operates on two vectors and return one.
type X64BinaryOperator func(a, b *X64) *X64
// X64New creates a new vector containing 4 fixed point 64 bit values.
func X64New(x1, x2, x3, x4 vpnumber.X64) *X64 {
return &X64{x1, x2, x3, x4}
}
// X64AxisX returns a new vector representing the X axis.
func X64AxisX() *X64 {
return &X64{vpnumber.X64Const1, vpnumber.X64Const0, vpnumber.X64Const0, vpnumber.X64Const0}
}
// X64AxisY returns a new vector representing the Y axis.
func X64AxisY() *X64 {
return &X64{vpnumber.X64Const0, vpnumber.X64Const1, vpnumber.X64Const0, vpnumber.X64Const0}
}
// X64AxisZ returns a new vector representing the Z axis.
func X64AxisZ() *X64 {
return &X64{vpnumber.X64Const0, vpnumber.X64Const0, vpnumber.X64Const1, vpnumber.X64Const0}
}
// X64FromVec3 creates a new vector from a smaller one,
// by appending a value at its end.
func X64FromVec3(vec *vpvec3.X64, x vpnumber.X64) *X64 {
return &X64{vec[0], vec[1], vec[2], x}
}
// ToVec3 creates a smaller vector by removing the last value.
func (vec *X64) ToVec3() *vpvec3.X64 {
return &vpvec3.X64{vec[0], vec[1], vec[2]}
}
// ToI32 converts the vector to an int32 vector.
func (vec *X64) ToI32() *I32 {
var ret I32
for i, v := range vec {
ret[i] = vpnumber.X64ToI32(v)
}
return &ret
}
// ToI64 converts the vector to an int32 vector.
func (vec *X64) ToI64() *I64 {
var ret I64
for i, v := range vec {
ret[i] = vpnumber.X64ToI64(v)
}
return &ret
}
// ToX32 converts the vector to a fixed point number vector on 64 bits.
func (vec *X64) ToX32() *X32 {
var ret X32
for i, v := range vec {
ret[i] = vpnumber.X64ToX32(v)
}
return &ret
}
// ToF32 converts the vector to a float32 vector.
func (vec *X64) ToF32() *F32 {
var ret F32
for i, v := range vec {
ret[i] = vpnumber.X64ToF32(v)
}
return &ret
}
// ToF64 converts the vector to a float64 vector.
func (vec *X64) ToF64() *F64 {
var ret F64
for i, v := range vec {
ret[i] = vpnumber.X64ToF64(v)
}
return &ret
}
// String returns a readable form of the vector.
func (vec *X64) String() string {
buf, err := json.Marshal(vec.ToF64())
if err != nil {
// Catching & ignoring error
return ""
}
return string(buf)
}
// Add adds operand to the vector.
// It modifies the vector, and returns a pointer on it.
func (vec *X64) Add(op *X64) *X64 {
for i, v := range op {
vec[i] += v
}
return vec
}
// Sub substracts operand from the vector.
// It modifies the vector, and returns a pointer on it.
func (vec *X64) Sub(op *X64) *X64 {
for i, v := range op {
vec[i] -= v
}
return vec
}
// Neg changes the sign of all vector members.
// It modifies the vector, and returns a pointer on it.
func (vec *X64) Neg() *X64 {
for i, v := range vec {
vec[i] = -v
}
return vec
}
// Min returns the minimum of all vector members.
// It modifies the vector, and returns a pointer on it.
func (vec *X64) Min(op *X64) *X64 {
for i, v := range op {
if vec[i] > v {
vec[i] = v
}
}
return vec
}
// Max returns the maximum of all vector members.
// It modifies the vector, and returns a pointer on it.
func (vec *X64) Max(op *X64) *X64 {
for i, v := range op {
if vec[i] < v {
vec[i] = v
}
}
return vec
}
// MulScale multiplies all values of the vector by factor.
// It modifies the vector, and returns a pointer on it.
func (vec *X64) MulScale(factor vpnumber.X64) *X64 {
for i, v := range vec {
vec[i] = vpnumber.X64Mul(v, factor)
}
return vec
}
// DivScale divides all values of the vector by factor.
// It modifies the vector, and returns a pointer on it.
func (vec *X64) DivScale(factor vpnumber.X64) *X64 {
for i, v := range vec {
vec[i] = vpnumber.X64Div(v, factor)
}
return vec
}
// Lerp performs a linear interpolation with another vector.
func (vec *X64) Lerp(op *X64, beta vpnumber.X64) *X64 {
switch {
case beta <= vpnumber.X64Const0:
return vec
case beta >= vpnumber.X64Const1:
*vec = *op
return vec
}
vec.MulScale(vpnumber.X64Const1 - beta)
vec.Add(X64MulScale(op, beta))
return vec
}
// SqMag returns the sum of the squares of all values.
// It is used to calculate length, it is faster than the complete
// length calculation, as it does not perform a square root.
func (vec *X64) SqMag() vpnumber.X64 {
var sq vpnumber.X64
for _, v := range vec {
sq += vpnumber.X64Mul(v, v)
}
return sq
}
// Length returns the length of the vector.
func (vec *X64) Length() vpnumber.X64 {
return vpmath.X64Sqrt(vec.SqMag())
}
// Normalize scales the vector so that its length is 1.
// It modifies the vector, and returns a pointer on it.
func (vec *X64) Normalize() *X64 {
vec.DivScale(vec.Length())
return vec
}
// Homogeneous scales the vector so that its latest member is 1.
// This what we want to do when projecting, to have homegemous coords.
// It modifies the vector, and returns a pointer on it.
func (vec *X64) Homogeneous() *X64 {
vec.DivScale(vec[Size-1])
return vec
}
// IsSimilar returns true if vectors are approximatively the same.
// This is a workarround to ignore rounding errors.
func (vec *X64) IsSimilar(op *X64) bool {
ret := true
for i, v := range vec {
ret = ret && vpnumber.X64IsSimilar(v, op[i])
}
return ret
}
// Dot returns the the dot product of two vectors.
func (vec *X64) Dot(op *X64) vpnumber.X64 {
var dot vpnumber.X64
for i, v := range op {
dot += vpnumber.X64Mul(vec[i], v)
}
return dot
}
// X64Add adds two vectors.
// Args are left untouched, a pointer on a new object is returned.
func X64Add(veca, vecb *X64) *X64 {
var ret = *veca
_ = ret.Add(vecb)
return &ret
}
// X64Sub substracts vector b from vector a.
// Args are left untouched, a pointer on a new object is returned.
func X64Sub(veca, vecb *X64) *X64 {
var ret = *veca
_ = ret.Sub(vecb)
return &ret
}
// X64Neg changes the sign of all vector members.
// Arg is left untouched, a pointer on a new object is returned.
func X64Neg(vec *X64) *X64 {
var ret = *vec
_ = ret.Neg()
return &ret
}
// X64Min returns the mininum (member-wise) of two vectors.
// Args are left untouched, a pointer on a new object is returned.
func X64Min(veca *X64, vecb *X64) *X64 {
var ret = *veca
_ = ret.Min(vecb)
return &ret
}
// X64Max returns the mininum (member-wise) of two vectors.
// Args are left untouched, a pointer on a new object is returned.
func X64Max(veca *X64, vecb *X64) *X64 {
var ret = *veca
_ = ret.Max(vecb)
return &ret
}
// X64MulScale multiplies all values of a vector by a scalar.
// Args are left untouched, a pointer on a new object is returned.
func X64MulScale(vec *X64, factor vpnumber.X64) *X64 {
var ret = *vec
_ = ret.MulScale(factor)
return &ret
}
// X64DivScale divides all values of a vector by a scalar.
// Args are left untouched, a pointer on a new object is returned.
func X64DivScale(vec *X64, factor vpnumber.X64) *X64 {
var ret = *vec
_ = ret.DivScale(factor)
return &ret
}
// X64Lerp performs a linear interpolation between 2 vectors.
func X64Lerp(veca, vecb *X64, beta vpnumber.X64) *X64 {
var ret = *veca
ret.Lerp(vecb, beta)
return &ret
}
// X64Normalize scales a vector so that its length is 1.
// Arg is left untouched, a pointer on a new object is returned.
func X64Normalize(vec *X64) *X64 {
var ret = *vec
_ = ret.Normalize()
return &ret
}
// X64Homogeneous scales the vector so that its latest member is 1.
// This what we want to do when projecting, to have homegemous coords.
// Arg is left untouched, a pointer on a new object is returned.
func X64Homogeneous(vec *X64) *X64 {
var ret = *vec
_ = ret.Homogeneous()
return &ret
}