-
Notifications
You must be signed in to change notification settings - Fork 1.3k
/
tri.js
135 lines (120 loc) · 3.54 KB
/
tri.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
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
import { Vec3 } from '../math/vec3.js';
const e1 = new Vec3();
const e2 = new Vec3();
const h = new Vec3();
const s = new Vec3();
const q = new Vec3();
// constants
const EPSILON = 1e-6;
/**
* A triangle.
*
* @category Math
*/
class Tri {
/**
* The first 3-dimensional vector of the triangle.
*
* @type {Vec3}
*/
v0 = new Vec3();
/**
* The second 3-dimensional vector of the triangle.
*
* @type {Vec3}
*/
v1 = new Vec3();
/**
* The third 3-dimensional vector of the triangle.
*
* @type {Vec3}
*/
v2 = new Vec3();
/**
* Creates a new Tri object.
*
* @param {Vec3} [v0] - The first 3-dimensional vector.
* @param {Vec3} [v1] - The second 3-dimensional vector.
* @param {Vec3} [v2] - The third 3-dimensional vector.
* @example
* const v0 = new pc.Vec3(1, 0, 0);
* const v1 = new pc.Vec3(0, 1, 0);
* const v2 = new pc.Vec3(2, 2, 1);
* const t = new pc.Tri(v0, v1, v2);
*/
constructor(v0 = Vec3.ZERO, v1 = Vec3.ZERO, v2 = Vec3.ZERO) {
this.set(v0, v1, v2);
}
/**
* Sets the specified triangle to the supplied 3-dimensional vectors.
*
* @param {Vec3} v0 - The value set on the first 3-dimensional vector of the triangle.
* @param {Vec3} v1 - The value set on the second 3-dimensional vector of the triangle.
* @param {Vec3} v2 - The value set on the third 3-dimensional vector of the triangle.
* @returns {Tri} Self for chaining
* @example
* const t = new pc.Tri(pc.Vec3.UP, pc.Vec3.RIGHT, pc.Vec3.BACK);
* const v0 = new pc.Vec3(1, 0, 0);
* const v1 = new pc.Vec3(0, 1, 0);
* const v2 = new pc.Vec3(2, 2, 1);
* t.set(v0, v1, v2);
*
* // Outputs [[1, 0, 0], [0, 1, 0], [2, 2, 1]]
* console.log("The result of the triangle set is: " + t.toString());
*/
set(v0, v1, v2) {
this.v0.copy(v0);
this.v1.copy(v1);
this.v2.copy(v2);
return this;
}
/**
* Test if a ray intersects with the triangle.
*
* @param {import('./ray.js').Ray} ray - Ray to test against (direction must be normalized).
* @param {Vec3} [point] - If there is an intersection, the intersection point will be copied
* into here.
* @returns {boolean} True if there is an intersection.
*/
intersectsRay(ray, point) {
e1.sub2(this.v1, this.v0);
e2.sub2(this.v2, this.v0);
h.cross(ray.direction, e2);
const a = e1.dot(h);
if (a > -EPSILON && a < EPSILON) {
return false;
}
const f = 1 / a;
s.sub2(ray.origin, this.v0);
const u = f * s.dot(h);
if (u < 0 || u > 1) {
return false;
}
q.cross(s, e1);
const v = f * ray.direction.dot(q);
if (v < 0 || u + v > 1) {
return false;
}
const t = f * e2.dot(q);
if (t > EPSILON) {
if (point instanceof Vec3) {
point.copy(ray.direction).mulScalar(t).add(ray.origin);
}
return true;
}
return false;
}
/**
* Converts the specified triangle to string form.
*
* @returns {string} The triangle in string form.
* @example
* const t = new pc.Tri(pc.Vec3.UP, pc.Vec3.RIGHT, pc.Vec3.BACK);
* // Outputs [[0, 1, 0], [1, 0, 0], [0, 0, 1]]
* console.log(t.toString());
*/
toString() {
return '[' + this.v0.toString() + ', ' + this.v1.toString() + ', ' + this.v2.toString() + ']';
}
}
export { Tri };