11import {
2+ Box3 ,
23 InstancedInterleavedBuffer ,
34 InterleavedBufferAttribute ,
45 Line3 ,
56 MathUtils ,
67 Matrix4 ,
78 Mesh ,
9+ Sphere ,
810 Vector3 ,
911 Vector4
1012} from '../../../build/three.module.js' ;
@@ -73,6 +75,10 @@ LineSegments2.prototype = Object.assign( Object.create( Mesh.prototype ), {
7375 var line = new Line3 ( ) ;
7476 var closestPoint = new Vector3 ( ) ;
7577
78+ var box = new Box3 ( ) ;
79+ var sphere = new Sphere ( ) ;
80+ var clipToWorldVector = new Vector4 ( ) ;
81+
7682 return function raycast ( raycaster , intersects ) {
7783
7884 if ( raycaster . camera === null ) {
@@ -87,6 +93,7 @@ LineSegments2.prototype = Object.assign( Object.create( Mesh.prototype ), {
8793 var camera = raycaster . camera ;
8894 var projectionMatrix = camera . projectionMatrix ;
8995
96+ var matrixWorld = this . matrixWorld ;
9097 var geometry = this . geometry ;
9198 var material = this . material ;
9299 var resolution = material . resolution ;
@@ -98,6 +105,71 @@ LineSegments2.prototype = Object.assign( Object.create( Mesh.prototype ), {
98105 // camera forward is negative
99106 var near = - camera . near ;
100107
108+ // clip space is [ - 1, 1 ] so multiply by two to get the full
109+ // width in clip space
110+ var ssMaxWidth = 2.0 * Math . max ( lineWidth / resolution . width , lineWidth / resolution . height ) ;
111+
112+ //
113+
114+ // check if we intersect the sphere bounds
115+ if ( geometry . boundingSphere === null ) {
116+
117+ geometry . computeBoundingSphere ( ) ;
118+
119+ }
120+
121+ sphere . copy ( geometry . boundingSphere ) . applyMatrix4 ( matrixWorld ) ;
122+ var distanceToSphere = Math . max ( camera . near , sphere . distanceToPoint ( ray . origin ) ) ;
123+
124+ // get the w component to scale the world space line width
125+ clipToWorldVector . set ( 0 , 0 , - distanceToSphere , 1.0 ) . applyMatrix4 ( camera . projectionMatrix ) ;
126+ clipToWorldVector . multiplyScalar ( 1.0 / clipToWorldVector . w ) ;
127+ clipToWorldVector . applyMatrix4 ( camera . projectionMatrixInverse ) ;
128+
129+ // increase the sphere bounds by the worst case line screen space width
130+ var sphereMargin = Math . abs ( ssMaxWidth / clipToWorldVector . w ) * 0.5 ;
131+ sphere . radius += sphereMargin ;
132+
133+ if ( raycaster . ray . intersectsSphere ( sphere ) === false ) {
134+
135+ return ;
136+
137+ }
138+
139+ //
140+
141+ // check if we intersect the box bounds
142+ if ( geometry . boundingBox === null ) {
143+
144+ geometry . computeBoundingBox ( ) ;
145+
146+ }
147+
148+ box . copy ( geometry . boundingBox ) . applyMatrix4 ( matrixWorld ) ;
149+ var distanceToBox = Math . max ( camera . near , box . distanceToPoint ( ray . origin ) ) ;
150+
151+ // get the w component to scale the world space line width
152+ clipToWorldVector . set ( 0 , 0 , - distanceToBox , 1.0 ) . applyMatrix4 ( camera . projectionMatrix ) ;
153+ clipToWorldVector . multiplyScalar ( 1.0 / clipToWorldVector . w ) ;
154+ clipToWorldVector . applyMatrix4 ( camera . projectionMatrixInverse ) ;
155+
156+ // increase the sphere bounds by the worst case line screen space width
157+ var boxMargin = Math . abs ( ssMaxWidth / clipToWorldVector . w ) * 0.5 ;
158+ box . max . x += boxMargin ;
159+ box . max . y += boxMargin ;
160+ box . max . z += boxMargin ;
161+ box . min . x -= boxMargin ;
162+ box . min . y -= boxMargin ;
163+ box . min . z -= boxMargin ;
164+
165+ if ( raycaster . ray . intersectsBox ( box ) === false ) {
166+
167+ return ;
168+
169+ }
170+
171+ //
172+
101173 // pick a point 1 unit out along the ray to avoid the ray origin
102174 // sitting at the camera origin which will cause "w" to be 0 when
103175 // applying the projection matrix.
@@ -116,7 +188,6 @@ LineSegments2.prototype = Object.assign( Object.create( Mesh.prototype ), {
116188
117189 ssOrigin3 . copy ( ssOrigin ) ;
118190
119- var matrixWorld = this . matrixWorld ;
120191 mvMatrix . multiplyMatrices ( camera . matrixWorldInverse , matrixWorld ) ;
121192
122193 for ( var i = 0 , l = instanceStart . count ; i < l ; i ++ ) {
0 commit comments