Przeglądaj źródła

Fix missed intersections when the segment extends behind camera near

Garrett Johnson 4 lat temu
rodzic
commit
91d4d2e4c8
1 zmienionych plików z 26 dodań i 9 usunięć
  1. 26 9
      examples/js/lines/LineSegments2.js

+ 26 - 9
examples/js/lines/LineSegments2.js

@@ -82,6 +82,9 @@ THREE.LineSegments2.prototype = Object.assign( Object.create( THREE.Mesh.prototy
 			var instanceStart = geometry.attributes.instanceStart;
 			var instanceEnd = geometry.attributes.instanceEnd;
 
+			// camera forward is negative
+			var near = - camera.near;
+
 			// pick a point 1 unit out along the ray to avoid the ray origin
 			// sitting at the camera origin which will cause "w" to be 0 when
 			// applying the projection matrix.
@@ -115,6 +118,29 @@ THREE.LineSegments2.prototype = Object.assign( Object.create( THREE.Mesh.prototy
 				start.applyMatrix4( mvMatrix );
 				end.applyMatrix4( mvMatrix );
 
+				// skip the segment if it's entirely behind the camera
+				var isBehindCameraNear = start.z > near && end.z > near;
+				if ( isBehindCameraNear ) {
+
+					continue;
+
+				}
+
+				// trim the segment if it extends behind camera near
+				if ( start.z > near ) {
+
+					const deltaDist = start.z - end.z;
+					const t = ( start.z - near ) / deltaDist;
+					start.lerp( end, t );
+
+				} else if ( end.z > near ) {
+
+					const deltaDist = end.z - start.z;
+					const t = ( end.z - near ) / deltaDist;
+					end.lerp( start, t );
+
+				}
+
 				// clip space
 				start.applyMatrix4( projectionMatrix );
 				end.applyMatrix4( projectionMatrix );
@@ -123,15 +149,6 @@ THREE.LineSegments2.prototype = Object.assign( Object.create( THREE.Mesh.prototy
 				start.multiplyScalar( 1 / start.w );
 				end.multiplyScalar( 1 / end.w );
 
-				// skip the segment if it's outside the camera near and far planes
-				var isBehindCameraNear = start.z < - 1 && end.z < - 1;
-				var isPastCameraFar = start.z > 1 && end.z > 1;
-				if ( isBehindCameraNear || isPastCameraFar ) {
-
-					continue;
-
-				}
-
 				// screen space
 				start.x *= resolution.x / 2;
 				start.y *= resolution.y / 2;