1 | /**
|
---|
2 | * @author bhouston / http://exocortex.com
|
---|
3 | */
|
---|
4 |
|
---|
5 | module( "Ray" );
|
---|
6 |
|
---|
7 | test( "constructor/equals", function() {
|
---|
8 | var a = new THREE.Ray();
|
---|
9 | ok( a.origin.equals( zero3 ), "Passed!" );
|
---|
10 | ok( a.direction.equals( zero3 ), "Passed!" );
|
---|
11 |
|
---|
12 | a = new THREE.Ray( two3.clone(), one3.clone() );
|
---|
13 | ok( a.origin.equals( two3 ), "Passed!" );
|
---|
14 | ok( a.direction.equals( one3 ), "Passed!" );
|
---|
15 | });
|
---|
16 |
|
---|
17 | test( "copy/equals", function() {
|
---|
18 | var a = new THREE.Ray( zero3.clone(), one3.clone() );
|
---|
19 | var b = new THREE.Ray().copy( a );
|
---|
20 | ok( b.origin.equals( zero3 ), "Passed!" );
|
---|
21 | ok( b.direction.equals( one3 ), "Passed!" );
|
---|
22 |
|
---|
23 | // ensure that it is a true copy
|
---|
24 | a.origin = zero3;
|
---|
25 | a.direction = one3;
|
---|
26 | ok( b.origin.equals( zero3 ), "Passed!" );
|
---|
27 | ok( b.direction.equals( one3 ), "Passed!" );
|
---|
28 | });
|
---|
29 |
|
---|
30 | test( "set", function() {
|
---|
31 | var a = new THREE.Ray();
|
---|
32 |
|
---|
33 | a.set( one3, one3 );
|
---|
34 | ok( a.origin.equals( one3 ), "Passed!" );
|
---|
35 | ok( a.direction.equals( one3 ), "Passed!" );
|
---|
36 | });
|
---|
37 |
|
---|
38 | test( "at", function() {
|
---|
39 | var a = new THREE.Ray( one3.clone(), new THREE.Vector3( 0, 0, 1 ) );
|
---|
40 |
|
---|
41 | ok( a.at( 0 ).equals( one3 ), "Passed!" );
|
---|
42 | ok( a.at( -1 ).equals( new THREE.Vector3( 1, 1, 0 ) ), "Passed!" );
|
---|
43 | ok( a.at( 1 ).equals( new THREE.Vector3( 1, 1, 2 ) ), "Passed!" );
|
---|
44 | });
|
---|
45 |
|
---|
46 | test( "recast/clone", function() {
|
---|
47 | var a = new THREE.Ray( one3.clone(), new THREE.Vector3( 0, 0, 1 ) );
|
---|
48 |
|
---|
49 | ok( a.recast( 0 ).equals( a ), "Passed!" );
|
---|
50 |
|
---|
51 | var b = a.clone();
|
---|
52 | ok( b.recast( -1 ).equals( new THREE.Ray( new THREE.Vector3( 1, 1, 0 ), new THREE.Vector3( 0, 0, 1 ) ) ), "Passed!" );
|
---|
53 |
|
---|
54 | var c = a.clone();
|
---|
55 | ok( c.recast( 1 ).equals( new THREE.Ray( new THREE.Vector3( 1, 1, 2 ), new THREE.Vector3( 0, 0, 1 ) ) ), "Passed!" );
|
---|
56 |
|
---|
57 | var d = a.clone();
|
---|
58 | var e = d.clone().recast( 1 );
|
---|
59 | ok( d.equals( a ), "Passed!" );
|
---|
60 | ok( ! e.equals( d ), "Passed!" );
|
---|
61 | ok( e.equals( c ), "Passed!" );
|
---|
62 | });
|
---|
63 |
|
---|
64 | test( "closestPointToPoint", function() {
|
---|
65 | var a = new THREE.Ray( one3.clone(), new THREE.Vector3( 0, 0, 1 ) );
|
---|
66 |
|
---|
67 | // behind the ray
|
---|
68 | var b = a.closestPointToPoint( zero3 );
|
---|
69 | ok( b.equals( one3 ), "Passed!" );
|
---|
70 |
|
---|
71 | // front of the ray
|
---|
72 | var c = a.closestPointToPoint( new THREE.Vector3( 0, 0, 50 ) );
|
---|
73 | ok( c.equals( new THREE.Vector3( 1, 1, 50 ) ), "Passed!" );
|
---|
74 |
|
---|
75 | // exactly on the ray
|
---|
76 | var d = a.closestPointToPoint( one3 );
|
---|
77 | ok( d.equals( one3 ), "Passed!" );
|
---|
78 | });
|
---|
79 |
|
---|
80 | test( "distanceToPoint", function() {
|
---|
81 | var a = new THREE.Ray( one3.clone(), new THREE.Vector3( 0, 0, 1 ) );
|
---|
82 |
|
---|
83 | // behind the ray
|
---|
84 | var b = a.distanceToPoint( zero3 );
|
---|
85 | ok( b === Math.sqrt( 3 ), "Passed!" );
|
---|
86 |
|
---|
87 | // front of the ray
|
---|
88 | var c = a.distanceToPoint( new THREE.Vector3( 0, 0, 50 ) );
|
---|
89 | ok( c === Math.sqrt( 2 ), "Passed!" );
|
---|
90 |
|
---|
91 | // exactly on the ray
|
---|
92 | var d = a.distanceToPoint( one3 );
|
---|
93 | ok( d === 0, "Passed!" );
|
---|
94 | });
|
---|
95 |
|
---|
96 | test( "isIntersectionSphere", function() {
|
---|
97 | var a = new THREE.Ray( one3.clone(), new THREE.Vector3( 0, 0, 1 ) );
|
---|
98 | var b = new THREE.Sphere( zero3, 0.5 );
|
---|
99 | var c = new THREE.Sphere( zero3, 1.5 );
|
---|
100 | var d = new THREE.Sphere( one3, 0.1 );
|
---|
101 | var e = new THREE.Sphere( two3, 0.1 );
|
---|
102 | var f = new THREE.Sphere( two3, 1 );
|
---|
103 |
|
---|
104 | ok( ! a.isIntersectionSphere( b ), "Passed!" );
|
---|
105 | ok( ! a.isIntersectionSphere( c ), "Passed!" );
|
---|
106 | ok( a.isIntersectionSphere( d ), "Passed!" );
|
---|
107 | ok( ! a.isIntersectionSphere( e ), "Passed!" );
|
---|
108 | ok( ! a.isIntersectionSphere( f ), "Passed!" );
|
---|
109 | });
|
---|
110 |
|
---|
111 | test( "isIntersectionPlane", function() {
|
---|
112 | var a = new THREE.Ray( one3.clone(), new THREE.Vector3( 0, 0, 1 ) );
|
---|
113 |
|
---|
114 | // parallel plane in front of the ray
|
---|
115 | var b = new THREE.Plane().setFromNormalAndCoplanarPoint( new THREE.Vector3( 0, 0, 1 ), one3.clone().sub( new THREE.Vector3( 0, 0, -1 ) ) );
|
---|
116 | ok( a.isIntersectionPlane( b ), "Passed!" );
|
---|
117 |
|
---|
118 | // parallel plane coincident with origin
|
---|
119 | var c = new THREE.Plane().setFromNormalAndCoplanarPoint( new THREE.Vector3( 0, 0, 1 ), one3.clone().sub( new THREE.Vector3( 0, 0, 0 ) ) );
|
---|
120 | ok( a.isIntersectionPlane( c ), "Passed!" );
|
---|
121 |
|
---|
122 | // parallel plane behind the ray
|
---|
123 | var d = new THREE.Plane().setFromNormalAndCoplanarPoint( new THREE.Vector3( 0, 0, 1 ), one3.clone().sub( new THREE.Vector3( 0, 0, 1 ) ) );
|
---|
124 | ok( ! a.isIntersectionPlane( d ), "Passed!" );
|
---|
125 |
|
---|
126 | // perpendical ray that overlaps exactly
|
---|
127 | var e = new THREE.Plane().setFromNormalAndCoplanarPoint( new THREE.Vector3( 1, 0, 0 ), one3 );
|
---|
128 | ok( a.isIntersectionPlane( e ), "Passed!" );
|
---|
129 |
|
---|
130 | // perpendical ray that doesn't overlap
|
---|
131 | var f = new THREE.Plane().setFromNormalAndCoplanarPoint( new THREE.Vector3( 1, 0, 0 ), zero3 );
|
---|
132 | ok( ! a.isIntersectionPlane( f ), "Passed!" );
|
---|
133 | });
|
---|
134 |
|
---|
135 | test( "intersectPlane", function() {
|
---|
136 | var a = new THREE.Ray( one3.clone(), new THREE.Vector3( 0, 0, 1 ) );
|
---|
137 |
|
---|
138 | // parallel plane behind
|
---|
139 | var b = new THREE.Plane().setFromNormalAndCoplanarPoint( new THREE.Vector3( 0, 0, 1 ), new THREE.Vector3( 1, 1, -1 ) );
|
---|
140 | ok( a.intersectPlane( b ) === null, "Passed!" );
|
---|
141 |
|
---|
142 | // parallel plane coincident with origin
|
---|
143 | var c = new THREE.Plane().setFromNormalAndCoplanarPoint( new THREE.Vector3( 0, 0, 1 ), new THREE.Vector3( 1, 1, 0 ) );
|
---|
144 | ok( a.intersectPlane( c ) === null, "Passed!" );
|
---|
145 |
|
---|
146 | // parallel plane infront
|
---|
147 | var d = new THREE.Plane().setFromNormalAndCoplanarPoint( new THREE.Vector3( 0, 0, 1 ), new THREE.Vector3( 1, 1, 1 ) );
|
---|
148 | ok( a.intersectPlane( d ).equals( a.origin ), "Passed!" );
|
---|
149 |
|
---|
150 | // perpendical ray that overlaps exactly
|
---|
151 | var e = new THREE.Plane().setFromNormalAndCoplanarPoint( new THREE.Vector3( 1, 0, 0 ), one3 );
|
---|
152 | ok( a.intersectPlane( e ).equals( a.origin ), "Passed!" );
|
---|
153 |
|
---|
154 | // perpendical ray that doesn't overlap
|
---|
155 | var f = new THREE.Plane().setFromNormalAndCoplanarPoint( new THREE.Vector3( 1, 0, 0 ), zero3 );
|
---|
156 | ok( a.intersectPlane( f ) === null, "Passed!" );
|
---|
157 | });
|
---|
158 |
|
---|
159 |
|
---|
160 | test( "applyMatrix4", function() {
|
---|
161 | var a = new THREE.Ray( one3.clone(), new THREE.Vector3( 0, 0, 1 ) );
|
---|
162 | var m = new THREE.Matrix4();
|
---|
163 |
|
---|
164 | ok( a.clone().applyMatrix4( m ).equals( a ), "Passed!" );
|
---|
165 |
|
---|
166 | a = new THREE.Ray( zero3.clone(), new THREE.Vector3( 0, 0, 1 ) );
|
---|
167 | m.makeRotationZ( Math.PI );
|
---|
168 | ok( a.clone().applyMatrix4( m ).equals( a ), "Passed!" );
|
---|
169 |
|
---|
170 | m.makeRotationX( Math.PI );
|
---|
171 | var b = a.clone();
|
---|
172 | b.direction.negate();
|
---|
173 | var a2 = a.clone().applyMatrix4( m );
|
---|
174 | ok( a2.origin.distanceTo( b.origin ) < 0.0001, "Passed!" );
|
---|
175 | ok( a2.direction.distanceTo( b.direction ) < 0.0001, "Passed!" );
|
---|
176 |
|
---|
177 | a.origin = new THREE.Vector3( 0, 0, 1 );
|
---|
178 | b.origin = new THREE.Vector3( 0, 0, -1 );
|
---|
179 | var a2 = a.clone().applyMatrix4( m );
|
---|
180 | ok( a2.origin.distanceTo( b.origin ) < 0.0001, "Passed!" );
|
---|
181 | ok( a2.direction.distanceTo( b.direction ) < 0.0001, "Passed!" );
|
---|
182 | });
|
---|
183 |
|
---|
184 |
|
---|
185 | test( "distanceSqToSegment", function() {
|
---|
186 | var a = new THREE.Ray( one3.clone(), new THREE.Vector3( 0, 0, 1 ) );
|
---|
187 | var ptOnLine = new THREE.Vector3();
|
---|
188 | var ptOnSegment = new THREE.Vector3();
|
---|
189 |
|
---|
190 | //segment in front of the ray
|
---|
191 | var v0 = new THREE.Vector3( 3, 5, 50 );
|
---|
192 | var v1 = new THREE.Vector3( 50, 50, 50 ); // just a far away point
|
---|
193 | var distSqr = a.distanceSqToSegment( v0, v1, ptOnLine, ptOnSegment );
|
---|
194 |
|
---|
195 | ok( ptOnSegment.distanceTo( v0 ) < 0.0001, "Passed!" );
|
---|
196 | ok( ptOnLine.distanceTo( new THREE.Vector3(1, 1, 50) ) < 0.0001, "Passed!" );
|
---|
197 | // ((3-1) * (3-1) + (5-1) * (5-1) = 4 + 16 = 20
|
---|
198 | ok( Math.abs( distSqr - 20 ) < 0.0001, "Passed!" );
|
---|
199 |
|
---|
200 | //segment behind the ray
|
---|
201 | v0 = new THREE.Vector3( -50, -50, -50 ); // just a far away point
|
---|
202 | v1 = new THREE.Vector3( -3, -5, -4 );
|
---|
203 | distSqr = a.distanceSqToSegment( v0, v1, ptOnLine, ptOnSegment );
|
---|
204 |
|
---|
205 | ok( ptOnSegment.distanceTo( v1 ) < 0.0001, "Passed!" );
|
---|
206 | ok( ptOnLine.distanceTo( one3 ) < 0.0001, "Passed!" );
|
---|
207 | // ((-3-1) * (-3-1) + (-5-1) * (-5-1) + (-4-1) + (-4-1) = 16 + 36 + 25 = 77
|
---|
208 | ok( Math.abs( distSqr - 77 ) < 0.0001, "Passed!" );
|
---|
209 |
|
---|
210 | //exact intersection between the ray and the segment
|
---|
211 | v0 = new THREE.Vector3( -50, -50, -50 );
|
---|
212 | v1 = new THREE.Vector3( 50, 50, 50 );
|
---|
213 | distSqr = a.distanceSqToSegment( v0, v1, ptOnLine, ptOnSegment );
|
---|
214 |
|
---|
215 | ok( ptOnSegment.distanceTo( one3 ) < 0.0001, "Passed!" );
|
---|
216 | ok( ptOnLine.distanceTo( one3 ) < 0.0001, "Passed!" );
|
---|
217 | ok( distSqr < 0.0001, "Passed!" );
|
---|
218 | });
|
---|
219 |
|
---|
220 | test( "intersectBox", function() {
|
---|
221 |
|
---|
222 | var TOL = 0.0001;
|
---|
223 |
|
---|
224 | var box = new THREE.Box3( new THREE.Vector3( -1, -1, -1 ), new THREE.Vector3( 1, 1, 1 ) );
|
---|
225 |
|
---|
226 | var a = new THREE.Ray( new THREE.Vector3( -2, 0, 0 ), new THREE.Vector3( 1, 0, 0) );
|
---|
227 | //ray should intersect box at -1,0,0
|
---|
228 | ok( a.isIntersectionBox(box) === true, "Passed!" );
|
---|
229 | ok( a.intersectBox(box).distanceTo( new THREE.Vector3( -1, 0, 0 ) ) < TOL, "Passed!" );
|
---|
230 |
|
---|
231 | var b = new THREE.Ray( new THREE.Vector3( -2, 0, 0 ), new THREE.Vector3( -1, 0, 0) );
|
---|
232 | //ray is point away from box, it should not intersect
|
---|
233 | ok( b.isIntersectionBox(box) === false, "Passed!" );
|
---|
234 | ok( b.intersectBox(box) === null, "Passed!" );
|
---|
235 |
|
---|
236 | var c = new THREE.Ray( new THREE.Vector3( 0, 0, 0 ), new THREE.Vector3( 1, 0, 0) );
|
---|
237 | // ray is inside box, should return exit point
|
---|
238 | ok( c.isIntersectionBox(box) === true, "Passed!" );
|
---|
239 | ok( c.intersectBox(box).distanceTo( new THREE.Vector3( 1, 0, 0 ) ) < TOL, "Passed!" );
|
---|
240 |
|
---|
241 | var d = new THREE.Ray( new THREE.Vector3( 0, 2, 1 ), new THREE.Vector3( 0, -1, -1).normalize() );
|
---|
242 | //tilted ray should intersect box at 0,1,0
|
---|
243 | ok( d.isIntersectionBox(box) === true, "Passed!" );
|
---|
244 | ok( d.intersectBox(box).distanceTo( new THREE.Vector3( 0, 1, 0 ) ) < TOL, "Passed!" );
|
---|
245 |
|
---|
246 | var e = new THREE.Ray( new THREE.Vector3( 1, -2, 1 ), new THREE.Vector3( 0, 1, 0).normalize() );
|
---|
247 | //handle case where ray is coplanar with one of the boxes side - box in front of ray
|
---|
248 | ok( e.isIntersectionBox(box) === true, "Passed!" );
|
---|
249 | ok( e.intersectBox(box).distanceTo( new THREE.Vector3( 1, -1, 1 ) ) < TOL, "Passed!" );
|
---|
250 |
|
---|
251 | var f = new THREE.Ray( new THREE.Vector3( 1, -2, 0 ), new THREE.Vector3( 0, -1, 0).normalize() );
|
---|
252 | //handle case where ray is coplanar with one of the boxes side - box behind ray
|
---|
253 | ok( f.isIntersectionBox(box) === false, "Passed!" );
|
---|
254 | ok( f.intersectBox(box) == null, "Passed!" );
|
---|
255 |
|
---|
256 | });
|
---|
257 |
|
---|
258 |
|
---|