-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathmath.js
111 lines (92 loc) · 3.14 KB
/
math.js
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
class Vector3 {
constructor(x, y, z) {
this.x = x;
this.y = y;
this.z = z;
}
toArray() {
return [this.x, this.y, this.z];
}
magnitude() {
return Math.sqrt(Math.pow(this.x, 2) + Math.pow(this.y, 2) + Math.pow(this.z, 2));
}
normalize() {
const mag = this.magnitude();
return new Vector3(this.x / mag, this.y / mag, this.z / mag);
}
dot(other) {
return this.x * other.x + this.y * other.y + this.z * other.z;
}
cross(other) {
return new Vector3(
this.y * other.z - this.z * other.y,
this.z * other.x - this.x * other.z,
this.x * other.y - this.y * other.x
);
}
add(other) {
return new Vector3(this.x + other.x, this.y + other.y, this.z + other.z);
}
subtract(other) {
return new Vector3(this.x - other.x, this.y - other.y, this.z - other.z);
}
scale(n) {
return new Vector3(this.x * n, this.y * n, this.z * n);
}
angleBetween(other) {
return Math.acos(this.dot(other) / (this.magnitude() * other.magnitude()));
}
inverse() {
const ret = new Vector3(1.0 / this.x, 1.0 / this.y, 1.0 / this.z);
return new Vector3(isNaN(ret.x) ? 0 : ret.x, isNaN(ret.y) ? 0 : ret.y, isNaN(ret.z) ? 0 : ret.z);
}
negate() {
return new Vector3(-this.x, -this.y, -this.z);
}
multiply(other) {
return new Vector3(this.x * other.x, this.y * other.y, this.z * other.z);
}
abs() {
return new Vector3(Math.abs(this.x), Math.abs(this.y), Math.abs(this.z));
}
dimensionsLessThan(other) {
return this.x <= other.x && this.y <= other.y && this.z <= other.z;
}
in(center, size) {
const diff = this.subtract(center).abs();
return diff.x < size.x && diff.y < size.y && diff.z < size.z;
}
}
class Ray {
constructor(origin, direction) {
this.origin = origin;
this.direction = direction.normalize();
this.m = this.direction.inverse();
}
closestPoint(v3) {
const ap = v3.subtract(this.origin);
const ab = this.direction;
return this.origin.add(this.direction.scale(ap.dot(ab) / ab.dot(ab)));
}
// Get a point down the ray, t units.
pointAlong(t) {
return this.origin.add(this.direction.normalize().scale(t));
}
}
module.exports = {
Vector3,
Ray,
rayIntersectsPrism: function(ray, center, size, maxRayLength) {
const ro = ray.origin.subtract(center);
const s = new Vector3(ray.direction.x < 0 ? 1 : -1, ray.direction.y < 0 ? 1 : -1, ray.direction.z < 0 ? 1 : -1);
const t1 = ray.m.multiply(ro.negate().add(s.multiply(size)));
const t2 = ray.m.multiply(ro.negate().subtract(s.multiply(size)));
const tn = Math.max(Math.max(t1.x, t1.y), t1.z);
const tf = Math.min(Math.min(t2.x, t2.y), t2.z);
if (tn < tf && tf > 0 && tn <= maxRayLength) {
if (t1.x > t1.y && t1.x > t1.z) return new Vector3(s.x, 0, 0);
else if (t1.y > t1.z) return new Vector3(0, s.y, 0);
else return new Vector3(0, 0, s.z);
}
}
};