/
Plane.js
207 lines (153 loc) · 4.58 KB
/
Plane.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
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
import { Vector3 } from './Vector3.js';
const v1 = new Vector3();
const v2 = new Vector3();
const d = new Vector3();
/**
* Class representing a plane in 3D space. The plane is specified in Hessian normal form.
*
* @author {@link https://github.com/Mugen87|Mugen87}
*/
class Plane {
/**
* Constructs a new plane with the given values.
*
* @param {Vector3} normal - The normal vector of the plane.
* @param {Number} constant - The distance of the plane from the origin.
*/
constructor( normal = new Vector3( 0, 0, 1 ), constant = 0 ) {
/**
* The normal vector of the plane.
* @type {Vector3}
*/
this.normal = normal;
/**
* The distance of the plane from the origin.
* @type {Number}
*/
this.constant = constant;
}
/**
* Sets the given values to this plane.
*
* @param {Vector3} normal - The normal vector of the plane.
* @param {Number} constant - The distance of the plane from the origin.
* @return {Plane} A reference to this plane.
*/
set( normal, constant ) {
this.normal = normal;
this.constant = constant;
return this;
}
/**
* Copies all values from the given plane to this plane.
*
* @param {Plane} plane - The plane to copy.
* @return {Plane} A reference to this plane.
*/
copy( plane ) {
this.normal.copy( plane.normal );
this.constant = plane.constant;
return this;
}
/**
* Creates a new plane and copies all values from this plane.
*
* @return {Plane} A new plane.
*/
clone() {
return new this.constructor().copy( this );
}
/**
* Computes the signed distance from the given 3D vector to this plane.
* The sign of the distance indicates the half-space in which the points lies.
* Zero means the point lies on the plane.
*
* @param {Vector3} point - A point in 3D space.
* @return {Number} The signed distance.
*/
distanceToPoint( point ) {
return this.normal.dot( point ) + this.constant;
}
/**
* Sets the values of the plane from the given normal vector and a coplanar point.
*
* @param {Vector3} normal - A normalized vector.
* @param {Vector3} point - A coplanar point.
* @return {Plane} A reference to this plane.
*/
fromNormalAndCoplanarPoint( normal, point ) {
this.normal.copy( normal );
this.constant = - point.dot( this.normal );
return this;
}
/**
* Sets the values of the plane from three given coplanar points.
*
* @param {Vector3} a - A coplanar point.
* @param {Vector3} b - A coplanar point.
* @param {Vector3} c - A coplanar point.
* @return {Plane} A reference to this plane.
*/
fromCoplanarPoints( a, b, c ) {
v1.subVectors( c, b ).cross( v2.subVectors( a, b ) ).normalize();
this.fromNormalAndCoplanarPoint( v1, a );
return this;
}
/**
* Performs a plane/plane intersection test and stores the intersection point
* to the given 3D vector. If no intersection is detected, *null* is returned.
*
* Reference: Intersection of Two Planes in Real-Time Collision Detection
* by Christer Ericson (chapter 5.4.4)
*
* @param {Plane} plane - The plane to test.
* @param {Vector3} result - The result vector.
* @return {Vector3} The result vector.
*/
intersectPlane( plane, result ) {
// compute direction of intersection line
d.crossVectors( this.normal, plane.normal );
// if d is zero, the planes are parallel (and separated)
// or coincident, so they’re not considered intersecting
const denom = d.dot( d );
if ( denom === 0 ) return null;
// compute point on intersection line
v1.copy( plane.normal ).multiplyScalar( this.constant );
v2.copy( this.normal ).multiplyScalar( plane.constant );
result.crossVectors( v1.sub( v2 ), d ).divideScalar( denom );
return result;
}
/**
* Returns true if the given plane intersects this plane.
*
* @param {Plane} plane - The plane to test.
* @return {Boolean} The result of the intersection test.
*/
intersectsPlane( plane ) {
const d = this.normal.dot( plane.normal );
return ( Math.abs( d ) !== 1 );
}
/**
* Projects the given point onto the plane. The result is written
* to the given vector.
*
* @param {Vector3} point - The point to project onto the plane.
* @param {Vector3} result - The projected point.
* @return {Vector3} The projected point.
*/
projectPoint( point, result ) {
v1.copy( this.normal ).multiplyScalar( this.distanceToPoint( point ) );
result.subVectors( point, v1 );
return result;
}
/**
* Returns true if the given plane is deep equal with this plane.
*
* @param {Plane} plane - The plane to test.
* @return {Boolean} The result of the equality test.
*/
equals( plane ) {
return plane.normal.equals( this.normal ) && plane.constant === this.constant;
}
}
export { Plane };