-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathVector.java
More file actions
231 lines (185 loc) · 6.82 KB
/
Copy pathVector.java
File metadata and controls
231 lines (185 loc) · 6.82 KB
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
package ptjava;
import java.util.concurrent.ThreadLocalRandom;
import jdk.incubator.vector.DoubleVector;
import jdk.incubator.vector.VectorMask;
import jdk.incubator.vector.VectorOperators;
import jdk.incubator.vector.VectorShuffle;
import jdk.incubator.vector.VectorSpecies;
public class Vector {
private static final VectorSpecies<Double> SPECIES = DoubleVector.SPECIES_256;
private static final VectorMask<Double> XYZ_MASK = SPECIES.indexInRange(0, 3);
private static final VectorShuffle<Double> YZX = VectorShuffle.fromValues(SPECIES, 1, 2, 0, 3);
private static final VectorShuffle<Double> ZXY = VectorShuffle.fromValues(SPECIES, 2, 0, 1, 3);
public final DoubleVector vec;
public static final Vector ZERO = new Vector(0, 0, 0);
public static final Vector UP = new Vector(0, 1, 0);
public static final Vector RIGHT = new Vector(1, 0, 0);
public static final Vector FORWARD = new Vector(0, 0, 1);
public Vector() {
vec = DoubleVector.zero(SPECIES);
}
public double getX() {
return vec.lane(0);
}
public double getY() {
return vec.lane(1);
}
public double getZ() {
return vec.lane(2);
}
public Vector withX(double x) {
return new Vector(vec.withLane(0, x));
}
public Vector withY(double y) {
return new Vector(vec.withLane(1, y));
}
public Vector withZ(double z) {
return new Vector(vec.withLane(2, z));
}
private Vector(DoubleVector vec) {
this.vec = vec;
}
public Vector(double x, double y, double z) {
vec = DoubleVector.zero(SPECIES).withLane(0, x).withLane(1, y).withLane(2, z);
}
public static Vector RandomUnitVector(ThreadLocalRandom rnd) {
double z = rnd.nextDouble() * 2.0 - 1.0;
double a = rnd.nextDouble() * 2.0 * Math.PI;
double r = Math.sqrt(1.0 - z * z);
double x = Math.sin(a);
double y = Math.cos(a);
return new Vector(r * x, r * y, z);
}
public double Length() {
return Math.sqrt(this.vec.mul(this.vec).reduceLanes(VectorOperators.ADD, XYZ_MASK));
}
public double LengthN(double n) {
if (n == 2) {
return this.Length();
}
DoubleVector absVec = this.vec.abs();
double x = Math.pow(absVec.lane(0), n);
double y = Math.pow(absVec.lane(1), n);
double z = Math.pow(absVec.lane(2), n);
return Math.pow(x + y + z, 1.0 / n);
}
public double Dot(Vector b) {
return this.vec.mul(b.vec).reduceLanes(VectorOperators.ADD, XYZ_MASK);
}
public Vector Cross(Vector b) {
DoubleVector a_yzx = this.vec.rearrange(YZX);
DoubleVector b_zxy = b.vec.rearrange(ZXY);
DoubleVector a_zxy = this.vec.rearrange(ZXY);
DoubleVector b_yzx = b.vec.rearrange(YZX);
return new Vector(a_yzx.mul(b_zxy).sub(a_zxy.mul(b_yzx)));
}
public Vector Normalize() {
return new Vector(this.vec.div(this.Length()));
}
public Vector Negate() {
return new Vector(this.vec.neg());
}
public Vector Abs() {
return new Vector(this.vec.abs());
}
public Vector Add(Vector b) {
return new Vector(this.vec.add(b.vec));
}
public Vector Sub(Vector b) {
return new Vector(this.vec.sub(b.vec));
}
public Vector Mul(Vector b) {
return new Vector(this.vec.mul(b.vec));
}
public Vector Div(Vector b) {
return new Vector(this.vec.div(b.vec));
}
public Vector Mod(Vector b) {
double x = this.getX() % b.getX();
double y = this.getY() % b.getY();
double z = this.getZ() % b.getZ();
return new Vector(x, y, z);
}
public Vector AddScalar(double b) {
return new Vector(this.vec.add(DoubleVector.broadcast(SPECIES, b), XYZ_MASK));
}
public Vector SubScalar(double b) {
return new Vector(this.vec.sub(DoubleVector.broadcast(SPECIES, b), XYZ_MASK));
}
public Vector MulScalar(double b) {
return new Vector(this.vec.mul(b));
}
public Vector DivScalar(double b) {
return new Vector(this.vec.div(b));
}
public Vector Min(Vector b) {
return new Vector(this.vec.min(b.vec));
}
public static Vector Min(Vector a, Vector b) {
return new Vector(a.vec.min(b.vec));
}
public Vector Max(Vector b) {
return new Vector(this.vec.max(b.vec));
}
public static Vector Max(Vector a, Vector b) {
return new Vector(a.vec.max(b.vec));
}
public Vector MinAxis() {
double x = Math.abs(vec.lane(0));
double y = Math.abs(vec.lane(1));
double z = Math.abs(vec.lane(2));
if (x <= y && x <= z) {
return new Vector(1, 0, 0);
} else if (y <= x && y <= z) {
return new Vector(0, 1, 0);
}
return new Vector(0, 0, 1);
}
public double MinComponent() {
return Math.min(Math.min(vec.lane(0), vec.lane(1)), vec.lane(2));
}
public double MaxComponent() {
return Math.max(Math.max(vec.lane(0), vec.lane(1)), vec.lane(2));
}
public Vector Reflect(Vector i) {
return i.Sub(this.MulScalar(2 * this.Dot(i)));
}
public Vector Refract(Vector i, double n1, double n2) {
double nr = n1 / n2;
double cosI = -this.Dot(i);
double sinT2 = nr * nr * (1 - cosI * cosI);
if (sinT2 > 1) {
return new Vector();
}
double cosT = Math.sqrt(1 - sinT2);
return i.MulScalar(nr).Add(this.MulScalar(nr * cosI - cosT));
}
public double Reflectance(Vector i, double n1, double n2) {
double nr = n1 / n2;
double cosI = -this.Dot(i);
double sinT2 = nr * nr * (1 - cosI * cosI);
if (sinT2 > 1) {
return 1;
}
double cosT = Math.sqrt(1 - sinT2);
double rOrth = (n1 * cosI - n2 * cosT) / (n1 * cosI + n2 * cosT);
double rPar = (n2 * cosI - n1 * cosT) / (n2 * cosI + n1 * cosT);
return (rOrth * rOrth + rPar * rPar) / 2;
}
@Override
public boolean equals(Object obj) {
if (this == obj) return true;
if (!(obj instanceof Vector)) return false;
Vector other = (Vector) obj;
return Double.compare(getX(), other.getX()) == 0
&& Double.compare(getY(), other.getY()) == 0
&& Double.compare(getZ(), other.getZ()) == 0;
}
@Override
public int hashCode() {
long bits = Double.doubleToLongBits(getX());
bits = 31 * bits + Double.doubleToLongBits(getY());
bits = 31 * bits + Double.doubleToLongBits(getZ());
return (int)(bits ^ (bits >>> 32));
}
}